linux-gbmc: aspeed-g7: Update aspeed drivers to SDKv09.07

All these driver patches are from Aspeed SDKv09.07. Please refer to doc:
SDK_User_Guide_v09.07.pdf

Note: kernel version is 6.6.93

The following are added:
```
1. DTSI
2. DTS
3. DRAM
4. SRAM
5. SCU clock
6. Pinctl
7. SCU IRQ
8. RNG
9. GPIO
10. SGPIO
11. ADC
12. I2C
13. GIC IRQ
14. SDHCI
15. MAC
16. RTC
17. LPC-SNOOP
18. MCTP
19. JTAG
20. XDMA
21. ESPI
22. LPC Mailbox
23. SPI-Flash
24. Pure SPI
25. SPI TPM
26. USB1.1 UHCI Host
27. USB2.0 EHCI Host
28. USB3.2 xHCI Host
29. Virtual UART
30. Watchdog
31. Timer
32. UART
33. USB Virtual Hub Controller
34. USB Virtual Hub Controller
35. Crypto
36. I3C
37. OTP
38. LTIP bus
39. LTPI gpio
```

Not ported driver:
```
1. UFS
2. KVM video
3. LPC-KCS
4. LPC-BT
5. PECI
6. Graphics Display
7. CAN
```

Tested:
Check .config and check each drive's source file. And run it on
ast2700 a1 machine. (Test each interface drvier)

Fusion-Link: NA
Google-Bug-Id: 413566800
Change-Id: Ia857597f44e8c6fb966768de700efdb7bb9e1118
Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
diff --git a/recipes-kernel/linux/files/0001-Add-arch-files-for-ast2700.patch b/recipes-kernel/linux/files/0001-Add-arch-files-for-ast2700.patch
index fc0eade..cd7732a 100644
--- a/recipes-kernel/linux/files/0001-Add-arch-files-for-ast2700.patch
+++ b/recipes-kernel/linux/files/0001-Add-arch-files-for-ast2700.patch
@@ -1,34 +1,50 @@
-From d766ae9416b1abfc6b3e2862a449d7e130be623e Mon Sep 17 00:00:00 2001
-From: "yung-sheng.huang" <yung-sheng.huang@fii-na.corp-partner.google.com>
-Date: Tue, 15 Apr 2025 11:07:19 +0800
-Subject: [PATCH 01/26] Add arch files for ast2700
+From fa848e5b55e219c6961643f3f141b6831fd21580 Mon Sep 17 00:00:00 2001
+From: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+Date: Fri, 18 Jul 2025 17:31:08 +0800
+Subject: [PATCH] Add arch files for ast2700
 
-This is base on aspeed SDK 9.06.
+This is base on aspeed SDK 9.07.
 
 Source:
 AspeedTech-BMC github:
 https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/
-(cherry picked from commit v00.06.06)
+(cherry picked from commit v00.06.07)
 
-Signed-off-by: yung-sheng.huang <yung-sheng.huang@fii-na.corp-partner.google.com>
+Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
 ---
  arch/arm64/Kconfig.platforms                  |    6 +
  arch/arm64/boot/dts/Makefile                  |    1 +
- arch/arm64/boot/dts/aspeed/Makefile           |   17 +
+ arch/arm64/boot/dts/aspeed/Makefile           |   23 +
  .../aspeed/aspeed-evb-flash-layout-128.dtsi   |   32 +
- .../boot/dts/aspeed/aspeed-g7-pinctrl.dtsi    | 1348 ++++++++
- arch/arm64/boot/dts/aspeed/aspeed-g7.dtsi     | 2849 +++++++++++++++++
- arch/arm64/boot/dts/aspeed/ast2700-evb.dts    | 1151 +++++++
+ .../boot/dts/aspeed/aspeed-g7-pinctrl.dtsi    | 1358 ++++++++
+ arch/arm64/boot/dts/aspeed/aspeed-g7.dtsi     | 2903 +++++++++++++++++
+ .../boot/dts/aspeed/aspeed-ltpi0-pinctrl.dtsi |  409 +++
+ arch/arm64/boot/dts/aspeed/aspeed-ltpi0.dtsi  |  675 ++++
+ .../boot/dts/aspeed/aspeed-ltpi1-pinctrl.dtsi |  409 +++
+ arch/arm64/boot/dts/aspeed/aspeed-ltpi1.dtsi  |  675 ++++
+ arch/arm64/boot/dts/aspeed/ast2700-dcscm.dts  |  990 ++++++
+ .../aspeed/ast2700-dcscm_ast1700-evb-dual.dts |  218 ++
+ .../dts/aspeed/ast2700-dcscm_ast1700-evb.dts  |  236 ++
+ arch/arm64/boot/dts/aspeed/ast2700-evb.dts    | 1188 +++++++
  .../boot/dts/aspeed/ast2700-reserved-mem.dtsi |  102 +
- arch/arm64/configs/aspeed_g7_defconfig        |  419 +++
- 9 files changed, 5925 insertions(+)
+ arch/arm64/configs/aspeed_g7_defconfig        |  429 +++
+ arch/arm64/configs/aspeed_g7_slt_defconfig    |  407 +++
+ 17 files changed, 10061 insertions(+)
  create mode 100644 arch/arm64/boot/dts/aspeed/Makefile
- create mode 100644 arch/arm64/boot/dts/aspeed/aspeed-evb-flash-layout-128.dtsi
- create mode 100644 arch/arm64/boot/dts/aspeed/aspeed-g7-pinctrl.dtsi
- create mode 100644 arch/arm64/boot/dts/aspeed/aspeed-g7.dtsi
- create mode 100644 arch/arm64/boot/dts/aspeed/ast2700-evb.dts
- create mode 100644 arch/arm64/boot/dts/aspeed/ast2700-reserved-mem.dtsi
- create mode 100644 arch/arm64/configs/aspeed_g7_defconfig
+ create mode 100755 arch/arm64/boot/dts/aspeed/aspeed-evb-flash-layout-128.dtsi
+ create mode 100755 arch/arm64/boot/dts/aspeed/aspeed-g7-pinctrl.dtsi
+ create mode 100755 arch/arm64/boot/dts/aspeed/aspeed-g7.dtsi
+ create mode 100755 arch/arm64/boot/dts/aspeed/aspeed-ltpi0-pinctrl.dtsi
+ create mode 100755 arch/arm64/boot/dts/aspeed/aspeed-ltpi0.dtsi
+ create mode 100755 arch/arm64/boot/dts/aspeed/aspeed-ltpi1-pinctrl.dtsi
+ create mode 100755 arch/arm64/boot/dts/aspeed/aspeed-ltpi1.dtsi
+ create mode 100755 arch/arm64/boot/dts/aspeed/ast2700-dcscm.dts
+ create mode 100755 arch/arm64/boot/dts/aspeed/ast2700-dcscm_ast1700-evb-dual.dts
+ create mode 100755 arch/arm64/boot/dts/aspeed/ast2700-dcscm_ast1700-evb.dts
+ create mode 100755 arch/arm64/boot/dts/aspeed/ast2700-evb.dts
+ create mode 100755 arch/arm64/boot/dts/aspeed/ast2700-reserved-mem.dtsi
+ create mode 100755 arch/arm64/configs/aspeed_g7_defconfig
+ create mode 100755 arch/arm64/configs/aspeed_g7_slt_defconfig
 
 diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
 index 606912019..40d1900fe 100644
@@ -58,15 +74,16 @@
 +subdir-y += aspeed
 diff --git a/arch/arm64/boot/dts/aspeed/Makefile b/arch/arm64/boot/dts/aspeed/Makefile
 new file mode 100644
-index 000000000..0f1cc2cc6
+index 000000000..fabdd24e3
 --- /dev/null
 +++ b/arch/arm64/boot/dts/aspeed/Makefile
-@@ -0,0 +1,17 @@
+@@ -0,0 +1,23 @@
 +# SPDX-License-Identifier: GPL-2.0
 +
 +dtb-$(CONFIG_ARCH_ASPEED) += \
 +	ast2700a0-evb.dtb \
 +	ast2700-evb.dtb \
++	ast2700-raw.dtb \
 +	ast2700-evb-s0.dtb \
 +	ast2700-evb-s1.dtb \
 +	ast2700a0-evb_ast1700a0-evb.dtb \
@@ -76,11 +93,16 @@
 +	ast2700-dcscm.dtb \
 +	ast2700a0-dcscm_ast1700a0-demo.dtb \
 +	ast2700-dcscm_ast1700-evb.dtb \
++	ast2700-dcscm_ast1700-evb-dual.dtb \
++	ast2700-dcscm_ast1800-evb.dtb \
 +	ast2700a0-evb-256-abr.dtb \
 +	ast2700-evb-256-abr.dtb \
-+	ast2700-slt.dtb
++	ast2700-slt.dtb \
++	ast2700-fpga.dtb \
++	ast2700-vff.dtb \
++	ast2700-ci-host.dtb
 diff --git a/arch/arm64/boot/dts/aspeed/aspeed-evb-flash-layout-128.dtsi b/arch/arm64/boot/dts/aspeed/aspeed-evb-flash-layout-128.dtsi
-new file mode 100644
+new file mode 100755
 index 000000000..46e8b7ae4
 --- /dev/null
 +++ b/arch/arm64/boot/dts/aspeed/aspeed-evb-flash-layout-128.dtsi
@@ -118,11 +140,11 @@
 +	};
 +};
 diff --git a/arch/arm64/boot/dts/aspeed/aspeed-g7-pinctrl.dtsi b/arch/arm64/boot/dts/aspeed/aspeed-g7-pinctrl.dtsi
-new file mode 100644
-index 000000000..606be908c
+new file mode 100755
+index 000000000..e593ee73d
 --- /dev/null
 +++ b/arch/arm64/boot/dts/aspeed/aspeed-g7-pinctrl.dtsi
-@@ -0,0 +1,1348 @@
+@@ -0,0 +1,1358 @@
 +// SPDX-License-Identifier: GPL-2.0-or-later
 +
 +&pinctrl0 {
@@ -673,11 +695,21 @@
 +		groups = "RMII0";
 +	};
 +
++	pinctrl_rmii0_rclko_default: rmii0_rclko_default {
++		function = "RMII0RCLKO";
++		groups = "RMII0RCLKO";
++	};
++
 +	pinctrl_rmii1_default: rmii1_default {
 +		function = "RMII1";
 +		groups = "RMII1";
 +	};
 +
++	pinctrl_rmii1_rclko_default: rmii1_rclko_default {
++		function = "RMII1RCLKO";
++		groups = "RMII1RCLKO";
++	};
++
 +	pinctrl_sgmii_default: sgmii_default {
 +		function = "SGMII";
 +		groups = "SGMII";
@@ -1472,11 +1504,11 @@
 +	};
 +};
 diff --git a/arch/arm64/boot/dts/aspeed/aspeed-g7.dtsi b/arch/arm64/boot/dts/aspeed/aspeed-g7.dtsi
-new file mode 100644
-index 000000000..7ba9ccce0
+new file mode 100755
+index 000000000..6dbcef03f
 --- /dev/null
 +++ b/arch/arm64/boot/dts/aspeed/aspeed-g7.dtsi
-@@ -0,0 +1,2849 @@
+@@ -0,0 +1,2903 @@
 +// SPDX-License-Identifier: GPL-2.0-or-later
 +#include <dt-bindings/clock/aspeed,ast2700-scu.h>
 +#include <dt-bindings/reset/aspeed,ast2700-scu.h>
@@ -1560,6 +1592,9 @@
 +		xdma0 = &xdma0;
 +		xdma1 = &xdma1;
 +		xdma2 = &xdma2;
++		bmcdev0 = &bmc_dev0;
++		bmcdev1 = &bmc_dev1;
++		edac = &edac;
 +	};
 +
 +	cpus {
@@ -1631,6 +1666,12 @@
 +		};
 +	};
 +
++	edac: sdram@12c00000 {
++		compatible = "aspeed,ast2700-sdram-edac", "syscon";
++		reg = <0 0x12c00000 0 0x1000>;
++		interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
++	};
++
 +	pmu {
 +		compatible = "arm,cortex-a35-pmu";
 +		interrupt-parent = <&gic>;
@@ -1705,7 +1746,7 @@
 +			aspeed,vhub-generic-endpoints = <21>;
 +			pinctrl-names = "default";
 +			pinctrl-0 = <&pinctrl_usb2axhpd1_default>;
-+			aspeed,device = <&pcie_device0>;
++			aspeed,device = <&pcie_cfg0>;
 +			aspeed,scu = <&syscon0>;
 +			status = "disabled";
 +		};
@@ -1738,7 +1779,7 @@
 +			aspeed,vhub-generic-endpoints = <21>;
 +			pinctrl-names = "default";
 +			pinctrl-0 = <&pinctrl_usb2bxhpd1_default>;
-+			aspeed,device = <&pcie_device1>;
++			aspeed,device = <&pcie_cfg1>;
 +			aspeed,scu = <&syscon0>;
 +			status = "disabled";
 +		};
@@ -1774,7 +1815,7 @@
 +			resets = <&syscon0 SCU0_RESET_PORTA_XHCI>;
 +			pinctrl-names = "default";
 +			pinctrl-0 = <&pinctrl_usb3axhp_default>;
-+			aspeed,device = <&pcie_device0>;
++			aspeed,device = <&pcie_cfg0>;
 +			phys = <&uphy3a>;
 +			phy-names = "usb3-phy";
 +			status = "disabled";
@@ -1813,7 +1854,7 @@
 +			resets = <&syscon0 SCU0_RESET_PORTB_XHCI>;
 +			pinctrl-names = "default";
 +			pinctrl-0 = <&pinctrl_usb3bxhp_default>;
-+			aspeed,device = <&pcie_device1>;
++			aspeed,device = <&pcie_cfg1>;
 +			phys = <&uphy3b>;
 +			phy-names = "usb3-phy";
 +			status = "disabled";
@@ -1829,7 +1870,7 @@
 +			aspeed,vhub-generic-endpoints = <21>;
 +			pinctrl-names = "default";
 +			pinctrl-0 = <&pinctrl_usb2ad0_default>;
-+			aspeed,device = <&pcie_device0>;
++			aspeed,device = <&pcie_cfg0>;
 +			aspeed,scu = <&syscon0>;
 +			status = "disabled";
 +		};
@@ -1852,7 +1893,7 @@
 +			resets = <&syscon0 SCU0_RESET_PORTA_VHUB_EHCI>;
 +			pinctrl-names = "default";
 +			pinctrl-0 = <&pinctrl_usb2ahp_default>;
-+			aspeed,device = <&pcie_device0>;
++			aspeed,device = <&pcie_cfg0>;
 +			status = "disabled";
 +		};
 +
@@ -1866,7 +1907,7 @@
 +			aspeed,vhub-generic-endpoints = <21>;
 +			pinctrl-names = "default";
 +			pinctrl-0 = <&pinctrl_usb2bd0_default>;
-+			aspeed,device = <&pcie_device1>;
++			aspeed,device = <&pcie_cfg1>;
 +			aspeed,scu = <&syscon0>;
 +			status = "disabled";
 +		};
@@ -1889,7 +1930,7 @@
 +			resets = <&syscon0 SCU0_RESET_PORTB_VHUB_EHCI>;
 +			pinctrl-names = "default";
 +			pinctrl-0 = <&pinctrl_usb2bhp_default>;
-+			aspeed,device = <&pcie_device1>;
++			aspeed,device = <&pcie_cfg1>;
 +			status = "disabled";
 +		};
 +
@@ -1979,7 +2020,7 @@
 +			interrupts-extended = <&gic GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>,
 +					      <&scu_ic0 ASPEED_AST2700_SCU_IC0_PCIE_PERST_LO_TO_HI>;
 +			aspeed,config = <&pcie_config0>;
-+			aspeed,device = <&pcie_device0>;
++			aspeed,device = <&pcie_cfg0>;
 +			aspeed,e2m = <&e2m_config0>;
 +			aspeed,scu = <&syscon0>;
 +			pcie2lpc;
@@ -1992,7 +2033,7 @@
 +			interrupts-extended = <&gic GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>,
 +					      <&scu_ic1 ASPEED_AST2700_SCU_IC1_PCIE_RCRST_LO_TO_HI>;
 +			aspeed,config = <&pcie_config1>;
-+			aspeed,device = <&pcie_device1>;
++			aspeed,device = <&pcie_cfg1>;
 +			aspeed,e2m = <&e2m_config1>;
 +			aspeed,scu = <&syscon0>;
 +			pcie2lpc;
@@ -2045,13 +2086,13 @@
 +			reg = <0 0x12c029a0 0 0x40>;
 +		};
 +
-+		pcie_device0: pcie-device@12c02a00 {
-+			compatible = "syscon", "simple-mfd";
++		pcie_cfg0: pcie-cfg@12c02a00 {
++			compatible = "aspeed,ast2700-pcie-cfg", "syscon";
 +			reg = <0 0x12c02a00 0 0x80>;
 +		};
 +
-+		pcie_device1: pcie-device@12c02a80 {
-+			compatible = "syscon", "simple-mfd";
++		pcie_cfg1: pcie-cfg@12c02a80 {
++			compatible = "aspeed,ast2700-pcie-cfg", "syscon";
 +			reg = <0 0x12c02a80 0 0x80>;
 +		};
 +
@@ -2097,7 +2138,9 @@
 +			resets = <&syscon0 SCU0_RESET_CRT0>;
 +			syscon = <&syscon0>;
 +			status = "disabled";
-+			interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
++			interrupts-extended = <&gic GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
++			<&scu_ic0 ASPEED_AST2700_SCU_IC0_PCIE_PERST_LO_TO_HI>,
++			<&scu_ic0 ASPEED_AST2700_SCU_IC0_PCIE_PERST_HI_TO_LO>;
 +		};
 +
 +		disp_intf: disp-intf {
@@ -2114,7 +2157,7 @@
 +			status = "disabled";
 +		};
 +
-+		gpio1: gpio@12c11000 {
++		gpio0: gpio@12c11000 {
 +			#gpio-cells = <2>;
 +			gpio-controller;
 +			compatible = "aspeed,ast2700-gpio";
@@ -2313,9 +2356,12 @@
 +
 +			#interrupt-cells = <1>;
 +			msi-parent = <&pcie0>;
++			msi-controller;
 +			msi_address = <0x000000F0>;
-+			pciephy = <&pcie_phy0>;
-+			aspeed,device = <&pcie_device0>;
++
++			aspeed,pciephy = <&pcie_phy0>;
++			aspeed,pciecfg = <&pcie_cfg0>;
++
 +			interrupt-map-mask = <0 0 0 7>;
 +			interrupt-map = <0 0 0 1 &pcie_intc0 0>,
 +					<0 0 0 2 &pcie_intc0 1>,
@@ -2350,9 +2396,12 @@
 +
 +			#interrupt-cells = <1>;
 +			msi-parent = <&pcie1>;
++			msi-controller;
 +			msi_address = <0x000000F0>;
-+			pciephy = <&pcie_phy1>;
-+			aspeed,device = <&pcie_device1>;
++
++			aspeed,pciephy = <&pcie_phy1>;
++			aspeed,pciecfg = <&pcie_cfg1>;
++
 +			interrupt-map-mask = <0 0 0 7>;
 +			interrupt-map = <0 0 0 1 &pcie_intc1 0>,
 +					<0 0 0 2 &pcie_intc1 1>,
@@ -2402,7 +2451,7 @@
 +			ranges = <0 0 0 0x12c21000 0 0x300>;
 +			#address-cells = <2>;
 +			#size-cells = <2>;
-+			aspeed,device = <&pcie_device0>;
++			aspeed,device = <&pcie_cfg0>;
 +
 +			e2m_ic0: interrupt-controller@14 {
 +				#interrupt-cells = <1>;
@@ -2419,6 +2468,7 @@
 +				index = <0>;
 +				pid = <3>;
 +				bar = <0x3c>;
++				msi = <28>;
 +				status = "disabled";
 +			};
 +
@@ -2428,6 +2478,7 @@
 +				index = <1>;
 +				pid = <4>;
 +				bar = <0x4c>;
++				msi = <29>;
 +				status = "disabled";
 +			};
 +
@@ -2437,6 +2488,7 @@
 +				index = <2>;
 +				pid = <5>;
 +				bar = <0x5c>;
++				msi = <30>;
 +				status = "disabled";
 +			};
 +
@@ -2446,6 +2498,7 @@
 +				index = <3>;
 +				pid = <6>;
 +				bar = <0x6c>;
++				msi = <31>;
 +				status = "disabled";
 +			};
 +		};
@@ -2456,7 +2509,7 @@
 +			ranges = <0x0 0x0 0 0x12c22000 0 0x300>;
 +			#address-cells = <2>;
 +			#size-cells = <2>;
-+			aspeed,device = <&pcie_device1>;
++			aspeed,device = <&pcie_cfg1>;
 +
 +			e2m_ic1: interrupt-controller@14 {
 +				#interrupt-cells = <1>;
@@ -2472,6 +2525,7 @@
 +				index = <4>;
 +				pid = <11>;
 +				bar = <0x3c>;
++				msi = <28>;
 +				status = "disabled";
 +			};
 +
@@ -2481,6 +2535,7 @@
 +				index = <5>;
 +				pid = <12>;
 +				bar = <0x4c>;
++				msi = <29>;
 +				status = "disabled";
 +			};
 +
@@ -2490,6 +2545,7 @@
 +				index = <6>;
 +				pid = <13>;
 +				bar = <0x5c>;
++				msi = <30>;
 +				status = "disabled";
 +			};
 +
@@ -2499,6 +2555,7 @@
 +				index = <7>;
 +				pid = <14>;
 +				bar = <0x6c>;
++				msi = <31>;
 +				status = "disabled";
 +			};
 +		};
@@ -2514,12 +2571,12 @@
 +
 +		video0: video@120a0000 {
 +			compatible = "aspeed,ast2700-video-engine", "syscon";
-+			reg = <0x0 0x120a0000 0x0 0x400>;
++			reg = <0x0 0x120a0000 0x0 0x400>, <0x0 0x14c3a800 0x0 0x400>;
 +			clocks = <&syscon0 SCU0_CLK_GATE_VCLK>,
 +				 <&syscon0 SCU0_CLK_GATE_ECLK>,
 +				 <&syscon0 SCU0_CLK_GATE_CRT1CLK>;
 +			clock-names = "vclk", "eclk", "crt2clk";
-+			interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
++			interrupts-extended = <&gic GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>, <&intc1_5 22>;
 +			resets = <&syscon0 SCU0_RESET_VIDEO>;
 +			aspeed,scu = <&syscon0>;
 +			status = "disabled";
@@ -2598,7 +2655,6 @@
 +			interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
 +			#mbox-cells = <1>;
 +			mbox-name = "ssp";
-+			status = "disabled";
 +		};
 +
 +		mbox1: mbox@12c1c600 {
@@ -2607,7 +2663,6 @@
 +			interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
 +			#mbox-cells = <1>;
 +			mbox-name = "tsp";
-+			status = "disabled";
 +		};
 +	};
 +
@@ -2779,7 +2834,7 @@
 +			status = "disabled";
 +		};
 +
-+		mac0: ftgmac@14050000 {
++		mac0: ethernet@14050000 {
 +			compatible = "aspeed,ast2700-mac", "faraday,ftgmac100";
 +			reg = <0x0 0x14050000 0x0 0x200>;
 +			interrupts-extended = <&intc1_4 0>;
@@ -2789,7 +2844,7 @@
 +			status = "disabled";
 +		};
 +
-+		mac1: ftgmac@14060000 {
++		mac1: ethernet@14060000 {
 +			compatible = "aspeed,ast2700-mac", "faraday,ftgmac100";
 +			reg = <0x0 0x14060000 0x0 0x200>;
 +			interrupts-extended = <&intc1_4 1>;
@@ -2799,7 +2854,7 @@
 +			status = "disabled";
 +		};
 +
-+		mac2: ftgmac@14070000 {
++		mac2: ethernet@14070000 {
 +			compatible = "aspeed,ast2700-mac", "faraday,ftgmac100";
 +			reg = <0x0 0x14070000 0x0 0x200>;
 +			interrupts-extended = <&intc1_4 2>;
@@ -3069,7 +3124,7 @@
 +			status = "disabled";
 +		};
 +
-+		gpio0: gpio@14c0b000 {
++		gpio1: gpio@14c0b000 {
 +			#gpio-cells = <2>;
 +			gpio-controller;
 +			compatible = "aspeed,ast2700-gpio";
@@ -3402,6 +3457,20 @@
 +			status = "disabled";
 +		};
 +
++		rtc_over_espi0: rtc-over_espi0@14c3d000 {
++			compatible = "aspeed,ast2700-rtc-over-espi";
++			reg = <0x0 0x14c3d000 0x0 0x100>;
++			interval-ms = <1000>;
++			status = "disabled";
++		};
++
++		rtc_over_espi1: rtc-over_espi1@14c3d000 {
++			compatible = "aspeed,ast2700-rtc-over-espi";
++			reg = <0x0 0x14c3d100 0x0 0x100>;
++			interval-ms = <1000>;
++			status = "disabled";
++		};
++
 +		vuart0: serial@14c30000 {
 +			compatible = "aspeed,ast2600-uart";
 +			reg = <0x0 0x14c30000 0x0 0x40>;
@@ -3848,6 +3917,14 @@
 +			status = "disabled";
 +		};
 +
++		mbox2: mbox@14c39200 {
++			compatible = "aspeed,ast2700-mailbox";
++			reg = <0x0 0x14c39200 0x0 0x200>;
++			interrupts-extended = <&intc1_5 17>;
++			#mbox-cells = <1>;
++			mbox-name = "bootmcu";
++		};
++
 +		sgpios: sgpios@14c3c000 {
 +			#gpio-cells = <2>;
 +			gpio-controller;
@@ -3885,8 +3962,8 @@
 +			status = "disabled";
 +		};
 +
-+		pcie_device2: pcie-device@14c02a80 {
-+			compatible = "syscon", "simple-mfd";
++		pcie_cfg2: pcie-cfg@14c02a80 {
++			compatible = "aspeed,ast2700-pcie-cfg", "syscon";
 +			reg = <0 0x14c02a80 0 0x80>;
 +		};
 +
@@ -3928,9 +4005,12 @@
 +
 +			#interrupt-cells = <1>;
 +			msi-parent = <&pcie2>;
++			msi-controller;
 +			msi_address = <0x000000F0>;
-+			pciephy = <&pcie_phy2>;
-+			aspeed,device = <&pcie_device2>;
++
++			aspeed,pciephy = <&pcie_phy2>;
++			aspeed,pciecfg = <&pcie_cfg2>;
++
 +			interrupt-map-mask = <0 0 0 7>;
 +			interrupt-map = <0 0 0 1 &pcie_intc2 0>,
 +					<0 0 0 2 &pcie_intc2 1>,
@@ -3949,7 +4029,7 @@
 +			ranges = <0x0 0x0 0 0x14c1d000 0 0x300>;
 +			#address-cells = <2>;
 +			#size-cells = <2>;
-+			aspeed,device = <&pcie_device2>;
++			aspeed,device = <&pcie_cfg2>;
 +
 +			pinctrl-0 = <&pinctrl_pcierc2_perst_default>;
 +			pinctrl-names = "default";
@@ -3968,6 +4048,7 @@
 +				index = <0>;
 +				pid = <2>;
 +				bar = <0x1c>;
++				msi = <1>;
 +				status = "disabled";
 +			};
 +
@@ -3977,6 +4058,7 @@
 +				index = <1>;
 +				pid = <3>;
 +				bar = <0x50>;
++				msi = <2>;
 +				status = "disabled";
 +			};
 +
@@ -3986,6 +4068,7 @@
 +				index = <2>;
 +				pid = <4>;
 +				bar = <0x3c>;
++				msi = <3>;
 +				status = "disabled";
 +			};
 +
@@ -3995,6 +4078,7 @@
 +				index = <3>;
 +				pid = <5>;
 +				bar = <0x4c>;
++				msi = <4>;
 +				status = "disabled";
 +			};
 +
@@ -4004,6 +4088,7 @@
 +				index = <4>;
 +				pid = <6>;
 +				bar = <0x5c>;
++				msi = <5>;
 +				status = "disabled";
 +			};
 +
@@ -4013,6 +4098,7 @@
 +				index = <5>;
 +				pid = <7>;
 +				bar = <0x6c>;
++				msi = <6>;
 +				status = "disabled";
 +			};
 +		};
@@ -4326,12 +4412,3666 @@
 +		status = "disabled";
 +	};
 +};
+diff --git a/arch/arm64/boot/dts/aspeed/aspeed-ltpi0-pinctrl.dtsi b/arch/arm64/boot/dts/aspeed/aspeed-ltpi0-pinctrl.dtsi
+new file mode 100755
+index 000000000..f9b3aa386
+--- /dev/null
++++ b/arch/arm64/boot/dts/aspeed/aspeed-ltpi0-pinctrl.dtsi
+@@ -0,0 +1,409 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++
++&ltpi0_pinctrl {
++	pinctrl_ltpi0_i2c0_default: ltpi0-i2c0-default {
++		function = "I2C0";
++		groups = "I2C0";
++	};
++
++	pinctrl_ltpi0_i2c1_default: ltpi0-i2c1-default {
++		function = "I2C1";
++		groups = "I2C1";
++	};
++
++	pinctrl_ltpi0_i2c2_default: ltpi0-i2c2-default {
++		function = "I2C2";
++		groups = "I2C2";
++	};
++
++	pinctrl_ltpi0_i2c3_default: ltpi0-i2c3-default {
++		function = "I2C3";
++		groups = "I2C3";
++	};
++
++	pinctrl_ltpi0_i2c4_default: ltpi0-i2c4-default {
++		function = "I2C4";
++		groups = "I2C4";
++	};
++
++	pinctrl_ltpi0_i2c5_default: ltpi0-i2c5-default {
++		function = "I2C5";
++		groups = "I2C5";
++	};
++
++	pinctrl_ltpi0_i2c6_default: ltpi0-i2c6-default {
++		function = "I2C6";
++		groups = "I2C6";
++	};
++
++	pinctrl_ltpi0_i2c7_default: ltpi0-i2c7-default {
++		function = "I2C7";
++		groups = "I2C7";
++	};
++
++	pinctrl_ltpi0_i2c8_default: ltpi0-i2c8-default {
++		function = "I2C8";
++		groups = "I2C8";
++	};
++
++	pinctrl_ltpi0_i2c9_default: ltpi0-i2c9-default {
++		function = "I2C9";
++		groups = "I2C9";
++	};
++
++	pinctrl_ltpi0_i2c10_default: ltpi0-i2c10-default {
++		function = "I2C10";
++		groups = "I2C10";
++	};
++
++	pinctrl_ltpi0_i2c11_default: ltpi0-i2c11-default {
++		function = "I2C11";
++		groups = "I2C11";
++	};
++
++	pinctrl_ltpi0_i2c12_default: ltpi0-i2c12-default {
++		function = "I2C12";
++		groups = "I2C12";
++	};
++
++	pinctrl_ltpi0_i2c13_default: ltpi0-i2c13-default {
++		function = "I2C13";
++		groups = "I2C13";
++	};
++
++	pinctrl_ltpi0_i2c14_default: ltpi0-i2c14-default {
++		function = "I2C14";
++		groups = "I2C14";
++	};
++
++	pinctrl_ltpi0_i2c15_default: ltpi0-i2c15-default {
++		function = "I2C15";
++		groups = "I2C15";
++	};
++
++	pinctrl_ltpi0_pwm0_default: ltpi0-pwm0-default {
++		function = "PWM0";
++		groups = "PWM0";
++	};
++
++	pinctrl_ltpi0_pwm1_default: ltpi0-pwm1-default {
++		function = "PWM1";
++		groups = "PWM1";
++	};
++
++	pinctrl_ltpi0_pwm2_default: ltpi0-pwm2-default {
++		function = "PWM2";
++		groups = "PWM2";
++	};
++
++	pinctrl_ltpi0_pwm3_default: ltpi0-pwm3-default {
++		function = "PWM3";
++		groups = "PWM3";
++	};
++
++	pinctrl_ltpi0_pwm4_default: ltpi0-pwm4-default {
++		function = "PWM4";
++		groups = "PWM4";
++	};
++
++	pinctrl_ltpi0_pwm5_default: ltpi0-pwm5-default {
++		function = "PWM5";
++		groups = "PWM5";
++	};
++
++	pinctrl_ltpi0_pwm6_default: ltpi0-pwm6-default {
++		function = "PWM6";
++		groups = "PWM6";
++	};
++
++	pinctrl_ltpi0_pwm7_default: ltpi0-pwm7-default {
++		function = "PWM7";
++		groups = "PWM7";
++	};
++
++	pinctrl_ltpi0_pwm8_default: ltpi0-pwm8-default {
++		function = "PWM8";
++		groups = "PWM8";
++	};
++
++	pinctrl_ltpi0_pwm9_default: ltpi0-pwm9-default {
++		function = "PWM9";
++		groups = "PWM9";
++	};
++
++	pinctrl_ltpi0_pwm10_default: ltpi0-pwm10-default {
++		function = "PWM10";
++		groups = "PWM10";
++	};
++
++	pinctrl_ltpi0_pwm11_default: ltpi0-pwm11-default {
++		function = "PWM11";
++		groups = "PWM11";
++	};
++
++	pinctrl_ltpi0_pwm12_default: ltpi0-pwm12-default {
++		function = "PWM12";
++		groups = "PWM12";
++	};
++
++	pinctrl_ltpi0_pwm13_default: ltpi0-pwm13-default {
++		function = "PWM13";
++		groups = "PWM13";
++	};
++
++	pinctrl_ltpi0_pwm14_default: ltpi0-pwm14-default {
++		function = "PWM14";
++		groups = "PWM14";
++	};
++
++	pinctrl_ltpi0_pwm15_default: ltpi0-pwm15-default {
++		function = "PWM15";
++		groups = "PWM15";
++	};
++
++	pinctrl_ltpi0_tach0_default: ltpi0-tach0-default {
++		function = "TACH0";
++		groups = "TACH0";
++	};
++
++	pinctrl_ltpi0_tach1_default: ltpi0-tach1-default {
++		function = "TACH1";
++		groups = "TACH1";
++	};
++
++	pinctrl_ltpi0_tach2_default: ltpi0-tach2-default {
++		function = "TACH2";
++		groups = "TACH2";
++	};
++
++	pinctrl_ltpi0_tach3_default: ltpi0-tach3-default {
++		function = "TACH3";
++		groups = "TACH3";
++	};
++
++	pinctrl_ltpi0_tach4_default: ltpi0-tach4-default {
++		function = "TACH4";
++		groups = "TACH4";
++	};
++
++	pinctrl_ltpi0_tach5_default: ltpi0-tach5-default {
++		function = "TACH5";
++		groups = "TACH5";
++	};
++
++	pinctrl_ltpi0_tach6_default: ltpi0-tach6-default {
++		function = "TACH6";
++		groups = "TACH6";
++	};
++
++	pinctrl_ltpi0_tach7_default: ltpi0-tach7-default {
++		function = "TACH7";
++		groups = "TACH7";
++	};
++
++	pinctrl_ltpi0_tach8_default: ltpi0-tach8-default {
++		function = "TACH8";
++		groups = "TACH8";
++	};
++
++	pinctrl_ltpi0_tach9_default: ltpi0-tach9-default {
++		function = "TACH9";
++		groups = "TACH9";
++	};
++
++	pinctrl_ltpi0_tach10_default: ltpi0-tach10-default {
++		function = "TACH10";
++		groups = "TACH10";
++	};
++
++	pinctrl_ltpi0_tach11_default: ltpi0-tach11-default {
++		function = "TACH11";
++		groups = "TACH11";
++	};
++
++	pinctrl_ltpi0_tach12_default: ltpi0-tach12-default {
++		function = "TACH12";
++		groups = "TACH12";
++	};
++
++	pinctrl_ltpi0_tach13_default: ltpi0-tach13-default {
++		function = "TACH13";
++		groups = "TACH13";
++	};
++
++	pinctrl_ltpi0_tach14_default: ltpi0-tach14-default {
++		function = "TACH14";
++		groups = "TACH14";
++	};
++
++	pinctrl_ltpi0_tach15_default: ltpi0-tach15-default {
++		function = "TACH15";
++		groups = "TACH15";
++	};
++
++	pinctrl_ltpi0_jtagm_default: ltpi0-jtagm-default {
++		function = "JTAGM";
++		groups = "JTAGM";
++	};
++
++	pinctrl_ltpi0_hvi3c0_default: ltpi0-hvi3c0-default {
++		function = "I3C0";
++		groups = "HVI3C0";
++	};
++
++	pinctrl_ltpi0_hvi3c1_default: ltpi0-hvi3c1-default {
++		function = "I3C1";
++		groups = "HVI3C1";
++	};
++
++	pinctrl_ltpi0_hvi3c2_default: ltpi0-hvi3c2-default {
++		function = "I3C2";
++		groups = "HVI3C2";
++	};
++
++	pinctrl_ltpi0_hvi3c3_default: ltpi0-hvi3c3-default {
++		function = "I3C3";
++		groups = "HVI3C3";
++	};
++
++	pinctrl_ltpi0_i3c4_default: ltpi0-i3c4-default {
++		function = "I3C4";
++		groups = "I3C4";
++	};
++
++	pinctrl_ltpi0_i3c5_default: ltpi0-i3c5-default {
++		function = "I3C5";
++		groups = "I3C5";
++	};
++
++	pinctrl_ltpi0_i3c6_default: ltpi0-i3c6-default {
++		function = "I3C6";
++		groups = "I3C6";
++	};
++
++	pinctrl_ltpi0_i3c7_default: ltpi0-i3c7-default {
++		function = "I3C7";
++		groups = "I3C7";
++	};
++
++	pinctrl_ltpi0_i3c8_default: ltpi0-i3c8-default {
++		function = "I3C8";
++		groups = "I3C8";
++	};
++
++	pinctrl_ltpi0_i3c9_default: ltpi0-i3c9-default {
++		function = "I3C9";
++		groups = "I3C9";
++	};
++
++	pinctrl_ltpi0_i3c10_default: ltpi0-i3c10-default {
++		function = "I3C10";
++		groups = "I3C10";
++	};
++
++	pinctrl_ltpi0_i3c11_default: ltpi0-i3c11-default {
++		function = "I3C11";
++		groups = "I3C11";
++	};
++
++	pinctrl_ltpi0_hvi3c12_default: ltpi0-hvi3c12-default {
++		function = "I3C12";
++		groups = "HVI3C12";
++	};
++
++	pinctrl_ltpi0_hvi3c13_default: ltpi0-hvi3c13-default {
++		function = "I3C13";
++		groups = "HVI3C13";
++	};
++
++	pinctrl_ltpi0_hvi3c14_default: ltpi0-hvi3c14-default {
++		function = "I3C14";
++		groups = "HVI3C14";
++	};
++
++	pinctrl_ltpi0_hvi3c15_default: ltpi0-hvi3c15-default {
++		function = "I3C15";
++		groups = "HVI3C15";
++	};
++
++	pinctrl_ltpi0_adc0_default: ltpi0-adc0-default {
++		function = "ADC0";
++		groups = "ADC0";
++	};
++
++	pinctrl_ltpi0_adc1_default: ltpi0-adc1-default {
++		function = "ADC1";
++		groups = "ADC1";
++	};
++
++	pinctrl_ltpi0_adc2_default: ltpi0-adc2-default {
++		function = "ADC2";
++		groups = "ADC2";
++	};
++
++	pinctrl_ltpi0_adc3_default: ltpi0-adc3-default {
++		function = "ADC3";
++		groups = "ADC3";
++	};
++
++	pinctrl_ltpi0_adc4_default: ltpi0-adc4-default {
++		function = "ADC4";
++		groups = "ADC4";
++	};
++
++	pinctrl_ltpi0_adc5_default: ltpi0-adc5-default {
++		function = "ADC5";
++		groups = "ADC5";
++	};
++
++	pinctrl_ltpi0_adc6_default: ltpi0-adc6-default {
++		function = "ADC6";
++		groups = "ADC6";
++	};
++
++	pinctrl_ltpi0_adc7_default: ltpi0-adc7-default {
++		function = "ADC7";
++		groups = "ADC7";
++	};
++
++	pinctrl_ltpi0_adc8_default: ltpi0-adc8-default {
++		function = "ADC8";
++		groups = "ADC8";
++	};
++
++	pinctrl_ltpi0_adc9_default: ltpi0-adc9-default {
++		function = "ADC9";
++		groups = "ADC9";
++	};
++
++	pinctrl_ltpi0_adc10_default: ltpi0-adc10-default {
++		function = "ADC10";
++		groups = "ADC10";
++	};
++
++	pinctrl_ltpi0_adc11_default: ltpi0-adc11-default {
++		function = "ADC11";
++		groups = "ADC11";
++	};
++
++	pinctrl_ltpi0_adc12_default: ltpi0-adc12-default {
++		function = "ADC12";
++		groups = "ADC12";
++	};
++
++	pinctrl_ltpi0_adc13_default: ltpi0-adc13-default {
++		function = "ADC13";
++		groups = "ADC13";
++	};
++
++	pinctrl_ltpi0_adc14_default: ltpi0-adc14-default {
++		function = "ADC14";
++		groups = "ADC14";
++	};
++
++	pinctrl_ltpi0_adc15_default: ltpi0-adc15-default {
++		function = "ADC15";
++		groups = "ADC15";
++	};
++
++};
+diff --git a/arch/arm64/boot/dts/aspeed/aspeed-ltpi0.dtsi b/arch/arm64/boot/dts/aspeed/aspeed-ltpi0.dtsi
+new file mode 100755
+index 000000000..c36d533be
+--- /dev/null
++++ b/arch/arm64/boot/dts/aspeed/aspeed-ltpi0.dtsi
+@@ -0,0 +1,675 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++#include <dt-bindings/clock/aspeed,ast1700-clk.h>
++#include <dt-bindings/reset/aspeed,ast1700-reset.h>
++
++/ {
++	aliases {
++		i3c100 = &ltpi0_i3c0;
++		i3c101 = &ltpi0_i3c1;
++		i3c102 = &ltpi0_i3c2;
++		i3c103 = &ltpi0_i3c3;
++		i3c104 = &ltpi0_i3c4;
++		i3c105 = &ltpi0_i3c5;
++		i3c106 = &ltpi0_i3c6;
++		i3c107 = &ltpi0_i3c7;
++		i3c108 = &ltpi0_i3c8;
++		i3c109 = &ltpi0_i3c9;
++		i3c110 = &ltpi0_i3c10;
++		i3c111 = &ltpi0_i3c11;
++		i3c112 = &ltpi0_i3c12;
++		i3c113 = &ltpi0_i3c13;
++		i3c114 = &ltpi0_i3c14;
++		i3c115 = &ltpi0_i3c15;
++	};
++
++	ltpi0_bus: ltpi0_bus@30000000 {
++		compatible = "simple-bus";
++		#address-cells = <2>;
++		#size-cells = <2>;
++		ranges;
++
++		ltpi0_syscon: syscon@30c02000 {
++			compatible = "aspeed,ast1700-scu", "syscon", "simple-mfd";
++			reg = <0x0 0x30c02000 0x0 0x1000>;
++			ranges = <0x0 0x0 0x0 0x30c02000 0x0 0x1000>;
++			#address-cells = <2>;
++			#size-cells = <2>;
++			#clock-cells = <1>;
++			#reset-cells = <1>;
++
++			ltpi0_rst: reset-controller@200 {
++				reg = <0x0 0x200 0x0 0x40>;
++			};
++
++			ltpi0_clk: clock-controller@240 {
++				reg = <0x0 0x240 0x0 0x1c0>;
++			};
++
++			ltpi0_pinctrl: pinctrl@400 {
++				compatible = "aspeed,ast1700-pinctrl";
++				reg = <0x0 0x400 0x0 0x100>;
++			};
++		};
++
++		ltpi0_spi2: spi@30030000 {
++			reg = <0x0 0x30030000 0x0 0x1f0>, <0x2 0x80000000 0x0 0x04000000>;
++			#address-cells = <1>;
++			#size-cells = <0>;
++			clocks = <&ltpi0_syscon AST1700_CLK_AHB>;
++			resets = <&ltpi0_syscon AST1700_RESET_SPI2>;
++			num-cs = <2>;
++			ltpi-base = <0x0 0x34000000>;
++			status = "disabled";
++		};
++
++		ltpi0_pwm_tach: pwm-tach-controller@300c0000 {
++			compatible = "aspeed,ast2700-pwm-tach";
++			reg = <0x0 0x300c0000 0 0x100>;
++			clocks = <&ltpi0_syscon AST1700_CLK_AHB>;
++			resets = <&ltpi0_syscon AST1700_RESET_PWM>;
++			#pwm-cells = <3>;
++			status = "disabled";
++		};
++
++		ltpi0_adc0: adc@30c00000 {
++			compatible = "aspeed,ast2700-adc0";
++			reg = <0x0 0x30c00000 0 0x100>;
++			clocks = <&ltpi0_syscon AST1700_CLK_AHB>;
++			resets = <&ltpi0_syscon AST1700_RESET_ADC>;
++			interrupts-extended = <&ltpi0_intc1_0 24>;
++			#io-channel-cells = <1>;
++			aspeed,scu = <&ltpi0_syscon>;
++			status = "disabled";
++		};
++
++		ltpi0_adc1: adc@30c00100 {
++			compatible = "aspeed,ast2700-adc1";
++			reg = <0x0 0x30c00100 0x0 0x100>;
++			clocks = <&ltpi0_syscon AST1700_CLK_AHB>;
++			resets = <&ltpi0_syscon AST1700_RESET_ADC>;
++			interrupts-extended = <&ltpi0_intc1_0 24>;
++			#io-channel-cells = <1>;
++			aspeed,scu = <&ltpi0_syscon>;
++			status = "disabled";
++		};
++
++		ltpi0_jtag: jtag@30c09000 {
++			compatible = "aspeed,ast2700-jtag";
++			reg= <0x0 0x30c09000 0x0 0x40>;
++			clocks = <&ltpi0_syscon AST1700_CLK_AHB>;
++			resets = <&ltpi0_syscon AST1700_RESET_JTAG1>;
++			status = "disabled";
++		};
++
++		ltpi0_i2c: bus@30c0f000 {
++			compatible = "simple-bus";
++			#address-cells = <1>;
++			#size-cells = <1>;
++			ranges = <0x0 0x0 0x30c0f000 0x1100>;
++		};
++
++		ltpi0_intc1: interrupt-controller@30c18000 {
++			compatible = "simple-mfd";
++			reg = <0 0x30c18000 0 0x400>;
++			#address-cells = <2>;
++			#size-cells = <2>;
++			ranges = <0x0 0x0 0x0 0x30c18000 0x0 0x400>;
++
++			ltpi0_intc1_0: interrupt-controller@100 {
++				#interrupt-cells = <1>;
++				interrupt-controller;
++				compatible = "aspeed,ast2700-intc-ic";
++				reg = <0x0 0x100 0x0 0x10>;
++				interrupts-extended = <&intc0_11 6>;
++			};
++
++			ltpi0_intc1_1: interrupt-controller@110 {
++				#interrupt-cells = <1>;
++				interrupt-controller;
++				compatible = "aspeed,ast2700-intc-ic";
++				reg = <0x0 0x110 0x0 0x10>;
++				interrupts-extended = <&intc0_11 7>;
++			};
++		};
++
++		ltpi0_i3c0: i3c0@30c20000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x30c20000 0x0 0x1000>;
++			interrupts-extended = <&ltpi0_intc1_1 0>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi0_syscon AST1700_CLK_GATE_I3C0CLK>;
++			resets = <&ltpi0_syscon AST1700_RESET_I3C0>, <&ltpi0_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi0_hvi3c0_default>;
++			status = "disabled";
++		};
++
++		ltpi0_i3c1: i3c1@30c21000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x30c21000 0x0 0x1000>;
++			interrupts-extended = <&ltpi0_intc1_1 1>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi0_syscon AST1700_CLK_GATE_I3C1CLK>;
++			resets = <&ltpi0_syscon AST1700_RESET_I3C1>, <&ltpi0_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi0_hvi3c1_default>;
++			status = "disabled";
++		};
++
++		ltpi0_i3c2: i3c2@30c22000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x30c22000 0x0 0x1000>;
++			interrupts-extended = <&ltpi0_intc1_1 2>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi0_syscon AST1700_CLK_GATE_I3C2CLK>;
++			resets = <&ltpi0_syscon AST1700_RESET_I3C2>, <&ltpi0_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi0_hvi3c2_default>;
++			status = "disabled";
++		};
++
++		ltpi0_i3c3: i3c3@30c23000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x30c23000 0x0 0x1000>;
++			interrupts-extended = <&ltpi0_intc1_1 3>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi0_syscon AST1700_CLK_GATE_I3C3CLK>;
++			resets = <&ltpi0_syscon AST1700_RESET_I3C3>, <&ltpi0_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi0_hvi3c3_default>;
++			status = "disabled";
++		};
++
++		ltpi0_i3c4: i3c4@30c24000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x30c24000 0x0 0x1000>;
++			interrupts-extended = <&ltpi0_intc1_1 4>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi0_syscon AST1700_CLK_GATE_I3C4CLK>;
++			resets = <&ltpi0_syscon AST1700_RESET_I3C4>, <&ltpi0_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi0_i3c4_default>;
++			status = "disabled";
++		};
++
++		ltpi0_i3c5: i3c5@30c25000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x30c25000 0x0 0x1000>;
++			interrupts-extended = <&ltpi0_intc1_1 5>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi0_syscon AST1700_CLK_GATE_I3C5CLK>;
++			resets = <&ltpi0_syscon AST1700_RESET_I3C5>, <&ltpi0_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi0_i3c5_default>;
++			status = "disabled";
++		};
++
++		ltpi0_i3c6: i3c6@30c26000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x30c26000 0x0 0x1000>;
++			interrupts-extended = <&ltpi0_intc1_1 6>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi0_syscon AST1700_CLK_GATE_I3C6CLK>;
++			resets = <&ltpi0_syscon AST1700_RESET_I3C6>, <&ltpi0_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi0_i3c6_default>;
++			status = "disabled";
++		};
++
++		ltpi0_i3c7: i3c7@30c27000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x30c27000 0x0 0x1000>;
++			interrupts-extended = <&ltpi0_intc1_1 7>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi0_syscon AST1700_CLK_GATE_I3C7CLK>;
++			resets = <&ltpi0_syscon AST1700_RESET_I3C7>, <&ltpi0_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi0_i3c7_default>;
++			status = "disabled";
++		};
++
++		ltpi0_i3c8: i3c8@30c28000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x30c28000 0x0 0x1000>;
++			interrupts-extended = <&ltpi0_intc1_1 8>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi0_syscon AST1700_CLK_GATE_I3C8CLK>;
++			resets = <&ltpi0_syscon AST1700_RESET_I3C8>, <&ltpi0_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi0_i3c8_default>;
++			status = "disabled";
++		};
++
++		ltpi0_i3c9: i3c9@30c29000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x30c29000 0x0 0x1000>;
++			interrupts-extended = <&ltpi0_intc1_1 9>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi0_syscon AST1700_CLK_GATE_I3C9CLK>;
++			resets = <&ltpi0_syscon AST1700_RESET_I3C9>, <&ltpi0_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi0_i3c9_default>;
++			status = "disabled";
++		};
++
++		ltpi0_i3c10: i3c10@30c2a000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x30c2a000 0x0 0x1000>;
++			interrupts-extended = <&ltpi0_intc1_1 10>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi0_syscon AST1700_CLK_GATE_I3C10CLK>;
++			resets = <&ltpi0_syscon AST1700_RESET_I3C10>, <&ltpi0_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi0_i3c10_default>;
++			status = "disabled";
++		};
++
++		ltpi0_i3c11: i3c11@30c2b000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x30c2b000 0x0 0x1000>;
++			interrupts-extended = <&ltpi0_intc1_1 11>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi0_syscon AST1700_CLK_GATE_I3C11CLK>;
++			resets = <&ltpi0_syscon AST1700_RESET_I3C11>, <&ltpi0_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi0_i3c11_default>;
++			status = "disabled";
++		};
++
++		ltpi0_i3c12: i3c12@30c2c000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x30c2c000 0x0 0x1000>;
++			interrupts-extended = <&ltpi0_intc1_1 12>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi0_syscon  AST1700_CLK_GATE_I3C12CLK>;
++			resets = <&ltpi0_syscon AST1700_RESET_I3C12>, <&ltpi0_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi0_hvi3c12_default>;
++			status = "disabled";
++		};
++
++		ltpi0_i3c13: i3c13@30c2d000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x30c2d000 0x0 0x1000>;
++			interrupts-extended = <&ltpi0_intc1_1 13>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi0_syscon  AST1700_CLK_GATE_I3C13CLK>;
++			resets = <&ltpi0_syscon AST1700_RESET_I3C13>, <&ltpi0_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi0_hvi3c13_default>;
++			status = "disabled";
++		};
++
++		ltpi0_i3c14: i3c14@30c2e000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x30c2e000 0x0 0x1000>;
++			interrupts-extended = <&ltpi0_intc1_1 14>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi0_syscon  AST1700_CLK_GATE_I3C14CLK>;
++			resets = <&ltpi0_syscon AST1700_RESET_I3C14>, <&ltpi0_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi0_hvi3c14_default>;
++			status = "disabled";
++		};
++
++		ltpi0_i3c15: i3c15@30c2f000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x30c2f000 0x0 0x1000>;
++			interrupts-extended = <&ltpi0_intc1_1 15>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi0_syscon AST1700_CLK_GATE_I3C15CLK>;
++			resets = <&ltpi0_syscon AST1700_RESET_I3C15>, <&ltpi0_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi0_hvi3c15_default>;
++			status = "disabled";
++		};
++
++		ltpi0_ltpi: ltpi@30c34000 {
++			compatible = "aspeed-ltpi";
++			reg = <0x0 0x30c34000 0x0 0x100>;
++			clocks = <&ltpi0_syscon AST1700_CLK_GATE_LTPICLK>,
++				 <&ltpi0_syscon AST1700_CLK_GATE_LTPIPHYCLK>;
++			clock-names = "ahb", "phy";
++			resets = <&ltpi0_syscon AST1700_RESET_LTPI>;
++			remote-controller;
++			aspeed,scu = <&ltpi0_syscon>;
++			i2c-tunneling = <0x0>;
++			status = "okay";
++		};
++
++		ltpi0_wdt0: watchdog@30c37000 {
++			compatible = "aspeed,ast2700-wdt";
++			reg = <0x0 0x30c37000 0x0 0x40>;
++		};
++	};
++};
++
++#include "aspeed-ltpi0-pinctrl.dtsi"
++
++&ltpi0_i2c {
++	ltpi0_i2c_global: i2c-global-regs@0 {
++		compatible = "aspeed,i2c-global", "simple-mfd", "syscon";
++		reg = <0x0 0x100>;
++		status = "disabled";
++	};
++
++	ltpi0_i2c0: i2c-bus@100 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0x100 0x80>, <0x1a0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi0_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi0_syscon AST1700_CLK_APB>;
++		resets = <&ltpi0_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi0_intc1_0 0>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi0_i2c0_default>;
++		status = "disabled";
++	};
++
++	ltpi0_i2c1: i2c-bus@200 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0x200 0x80>, <0x2a0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi0_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi0_syscon AST1700_CLK_APB>;
++		resets = <&ltpi0_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi0_intc1_0 1>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi0_i2c1_default>;
++		status = "disabled";
++	};
++
++	ltpi0_i2c2: i2c-bus@300 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0x300 0x80>, <0x3a0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi0_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi0_syscon AST1700_CLK_APB>;
++		resets = <&ltpi0_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi0_intc1_0 2>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi0_i2c2_default>;
++		status = "disabled";
++	};
++
++	ltpi0_i2c3: i2c-bus@400 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0x400 0x80>, <0x4a0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi0_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi0_syscon AST1700_CLK_APB>;
++		resets = <&ltpi0_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi0_intc1_0 3>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi0_i2c3_default>;
++		status = "disabled";
++	};
++
++	ltpi0_i2c4: i2c-bus@500 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0x500 0x80>, <0x5a0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi0_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi0_syscon AST1700_CLK_APB>;
++		resets = <&ltpi0_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi0_intc1_0 4>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi0_i2c4_default>;
++		status = "disabled";
++	};
++
++	ltpi0_i2c5: i2c-bus@600 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0x600 0x80>, <0x6a0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi0_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi0_syscon AST1700_CLK_APB>;
++		resets = <&ltpi0_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi0_intc1_0 5>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi0_i2c5_default>;
++		status = "disabled";
++	};
++
++	ltpi0_i2c6: i2c-bus@700 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0x700 0x80>, <0x7a0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi0_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi0_syscon AST1700_CLK_APB>;
++		resets = <&ltpi0_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi0_intc1_0 6>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi0_i2c6_default>;
++		status = "disabled";
++	};
++
++	ltpi0_i2c7: i2c-bus@800 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0x800 0x80>, <0x8a0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi0_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi0_syscon AST1700_CLK_APB>;
++		resets = <&ltpi0_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi0_intc1_0 7>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi0_i2c7_default>;
++		status = "disabled";
++	};
++
++	ltpi0_i2c8: i2c-bus@900 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0x900 0x80>, <0x9a0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi0_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi0_syscon AST1700_CLK_APB>;
++		resets = <&ltpi0_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi0_intc1_0 8>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi0_i2c8_default>;
++		status = "disabled";
++	};
++
++	ltpi0_i2c9: i2c-bus@a00 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0xa00 0x80>, <0xaa0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi0_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi0_syscon AST1700_CLK_APB>;
++		resets = <&ltpi0_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi0_intc1_0 9>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi0_i2c9_default>;
++		status = "disabled";
++	};
++
++	ltpi0_i2c10: i2c-bus@b00 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0xb00 0x80>, <0xba0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi0_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi0_syscon AST1700_CLK_APB>;
++		resets = <&ltpi0_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi0_intc1_0 10>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi0_i2c10_default>;
++		status = "disabled";
++	};
++
++	ltpi0_i2c11: i2c-bus@c00 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0xc00 0x80>, <0xca0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi0_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi0_syscon AST1700_CLK_APB>;
++		resets = <&ltpi0_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi0_intc1_0 11>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi0_i2c11_default>;
++		status = "disabled";
++	};
++
++	ltpi0_i2c12: i2c-bus@d00 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0xd00 0x80>, <0xda0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi0_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi0_syscon AST1700_CLK_APB>;
++		resets = <&ltpi0_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi0_intc1_0 12>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi0_i2c12_default>;
++		status = "disabled";
++	};
++
++	ltpi0_i2c13: i2c-bus@e00 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0xe00 0x80>, <0xea0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi0_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi0_syscon AST1700_CLK_APB>;
++		resets = <&ltpi0_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi0_intc1_0 13>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi0_i2c13_default>;
++		status = "disabled";
++	};
++
++	ltpi0_i2c14: i2c-bus@f00 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0xf00 0x80>, <0xfa0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi0_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi0_syscon AST1700_CLK_APB>;
++		resets = <&ltpi0_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi0_intc1_0 14>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi0_i2c14_default>;
++		status = "disabled";
++	};
++
++	ltpi0_i2c15: i2c-bus@1000 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0x1000 0x80>, <0x10a0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi0_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi0_syscon AST1700_CLK_APB>;
++		resets = <&ltpi0_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi0_intc1_0 15>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi0_i2c15_default>;
++		status = "disabled";
++	};
++};
+diff --git a/arch/arm64/boot/dts/aspeed/aspeed-ltpi1-pinctrl.dtsi b/arch/arm64/boot/dts/aspeed/aspeed-ltpi1-pinctrl.dtsi
+new file mode 100755
+index 000000000..5bdf0cb04
+--- /dev/null
++++ b/arch/arm64/boot/dts/aspeed/aspeed-ltpi1-pinctrl.dtsi
+@@ -0,0 +1,409 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++
++&ltpi1_pinctrl {
++	pinctrl_ltpi1_i2c0_default: ltpi1-i2c0-default {
++		function = "I2C0";
++		groups = "I2C0";
++	};
++
++	pinctrl_ltpi1_i2c1_default: ltpi1-i2c1-default {
++		function = "I2C1";
++		groups = "I2C1";
++	};
++
++	pinctrl_ltpi1_i2c2_default: ltpi1-i2c2-default {
++		function = "I2C2";
++		groups = "I2C2";
++	};
++
++	pinctrl_ltpi1_i2c3_default: ltpi1-i2c3-default {
++		function = "I2C3";
++		groups = "I2C3";
++	};
++
++	pinctrl_ltpi1_i2c4_default: ltpi1-i2c4-default {
++		function = "I2C4";
++		groups = "I2C4";
++	};
++
++	pinctrl_ltpi1_i2c5_default: ltpi1-i2c5-default {
++		function = "I2C5";
++		groups = "I2C5";
++	};
++
++	pinctrl_ltpi1_i2c6_default: ltpi1-i2c6-default {
++		function = "I2C6";
++		groups = "I2C6";
++	};
++
++	pinctrl_ltpi1_i2c7_default: ltpi1-i2c7-default {
++		function = "I2C7";
++		groups = "I2C7";
++	};
++
++	pinctrl_ltpi1_i2c8_default: ltpi1-i2c8-default {
++		function = "I2C8";
++		groups = "I2C8";
++	};
++
++	pinctrl_ltpi1_i2c9_default: ltpi1-i2c9-default {
++		function = "I2C9";
++		groups = "I2C9";
++	};
++
++	pinctrl_ltpi1_i2c10_default: ltpi1-i2c10-default {
++		function = "I2C10";
++		groups = "I2C10";
++	};
++
++	pinctrl_ltpi1_i2c11_default: ltpi1-i2c11-default {
++		function = "I2C11";
++		groups = "I2C11";
++	};
++
++	pinctrl_ltpi1_i2c12_default: ltpi1-i2c12-default {
++		function = "I2C12";
++		groups = "I2C12";
++	};
++
++	pinctrl_ltpi1_i2c13_default: ltpi1-i2c13-default {
++		function = "I2C13";
++		groups = "I2C13";
++	};
++
++	pinctrl_ltpi1_i2c14_default: ltpi1-i2c14-default {
++		function = "I2C14";
++		groups = "I2C14";
++	};
++
++	pinctrl_ltpi1_i2c15_default: ltpi1-i2c15-default {
++		function = "I2C15";
++		groups = "I2C15";
++	};
++
++	pinctrl_ltpi1_pwm0_default: ltpi1-pwm0-default {
++		function = "PWM0";
++		groups = "PWM0";
++	};
++
++	pinctrl_ltpi1_pwm1_default: ltpi1-pwm1-default {
++		function = "PWM1";
++		groups = "PWM1";
++	};
++
++	pinctrl_ltpi1_pwm2_default: ltpi1-pwm2-default {
++		function = "PWM2";
++		groups = "PWM2";
++	};
++
++	pinctrl_ltpi1_pwm3_default: ltpi1-pwm3-default {
++		function = "PWM3";
++		groups = "PWM3";
++	};
++
++	pinctrl_ltpi1_pwm4_default: ltpi1-pwm4-default {
++		function = "PWM4";
++		groups = "PWM4";
++	};
++
++	pinctrl_ltpi1_pwm5_default: ltpi1-pwm5-default {
++		function = "PWM5";
++		groups = "PWM5";
++	};
++
++	pinctrl_ltpi1_pwm6_default: ltpi1-pwm6-default {
++		function = "PWM6";
++		groups = "PWM6";
++	};
++
++	pinctrl_ltpi1_pwm7_default: ltpi1-pwm7-default {
++		function = "PWM7";
++		groups = "PWM7";
++	};
++
++	pinctrl_ltpi1_pwm8_default: ltpi1-pwm8-default {
++		function = "PWM8";
++		groups = "PWM8";
++	};
++
++	pinctrl_ltpi1_pwm9_default: ltpi1-pwm9-default {
++		function = "PWM9";
++		groups = "PWM9";
++	};
++
++	pinctrl_ltpi1_pwm10_default: ltpi1-pwm10-default {
++		function = "PWM10";
++		groups = "PWM10";
++	};
++
++	pinctrl_ltpi1_pwm11_default: ltpi1-pwm11-default {
++		function = "PWM11";
++		groups = "PWM11";
++	};
++
++	pinctrl_ltpi1_pwm12_default: ltpi1-pwm12-default {
++		function = "PWM12";
++		groups = "PWM12";
++	};
++
++	pinctrl_ltpi1_pwm13_default: ltpi1-pwm13-default {
++		function = "PWM13";
++		groups = "PWM13";
++	};
++
++	pinctrl_ltpi1_pwm14_default: ltpi1-pwm14-default {
++		function = "PWM14";
++		groups = "PWM14";
++	};
++
++	pinctrl_ltpi1_pwm15_default: ltpi1-pwm15-default {
++		function = "PWM15";
++		groups = "PWM15";
++	};
++
++	pinctrl_ltpi1_tach0_default: ltpi1-tach0-default {
++		function = "TACH0";
++		groups = "TACH0";
++	};
++
++	pinctrl_ltpi1_tach1_default: ltpi1-tach1-default {
++		function = "TACH1";
++		groups = "TACH1";
++	};
++
++	pinctrl_ltpi1_tach2_default: ltpi1-tach2-default {
++		function = "TACH2";
++		groups = "TACH2";
++	};
++
++	pinctrl_ltpi1_tach3_default: ltpi1-tach3-default {
++		function = "TACH3";
++		groups = "TACH3";
++	};
++
++	pinctrl_ltpi1_tach4_default: ltpi1-tach4-default {
++		function = "TACH4";
++		groups = "TACH4";
++	};
++
++	pinctrl_ltpi1_tach5_default: ltpi1-tach5-default {
++		function = "TACH5";
++		groups = "TACH5";
++	};
++
++	pinctrl_ltpi1_tach6_default: ltpi1-tach6-default {
++		function = "TACH6";
++		groups = "TACH6";
++	};
++
++	pinctrl_ltpi1_tach7_default: ltpi1-tach7-default {
++		function = "TACH7";
++		groups = "TACH7";
++	};
++
++	pinctrl_ltpi1_tach8_default: ltpi1-tach8-default {
++		function = "TACH8";
++		groups = "TACH8";
++	};
++
++	pinctrl_ltpi1_tach9_default: ltpi1-tach9-default {
++		function = "TACH9";
++		groups = "TACH9";
++	};
++
++	pinctrl_ltpi1_tach10_default: ltpi1-tach10-default {
++		function = "TACH10";
++		groups = "TACH10";
++	};
++
++	pinctrl_ltpi1_tach11_default: ltpi1-tach11-default {
++		function = "TACH11";
++		groups = "TACH11";
++	};
++
++	pinctrl_ltpi1_tach12_default: ltpi1-tach12-default {
++		function = "TACH12";
++		groups = "TACH12";
++	};
++
++	pinctrl_ltpi1_tach13_default: ltpi1-tach13-default {
++		function = "TACH13";
++		groups = "TACH13";
++	};
++
++	pinctrl_ltpi1_tach14_default: ltpi1-tach14-default {
++		function = "TACH14";
++		groups = "TACH14";
++	};
++
++	pinctrl_ltpi1_tach15_default: ltpi1-tach15-default {
++		function = "TACH15";
++		groups = "TACH15";
++	};
++
++	pinctrl_ltpi1_jtagm_default: ltpi1-jtagm-default {
++		function = "JTAGM";
++		groups = "JTAGM";
++	};
++
++	pinctrl_ltpi1_hvi3c0_default: ltpi1-hvi3c0-default {
++		function = "I3C0";
++		groups = "HVI3C0";
++	};
++
++	pinctrl_ltpi1_hvi3c1_default: ltpi1-hvi3c1-default {
++		function = "I3C1";
++		groups = "HVI3C1";
++	};
++
++	pinctrl_ltpi1_hvi3c2_default: ltpi1-hvi3c2-default {
++		function = "I3C2";
++		groups = "HVI3C2";
++	};
++
++	pinctrl_ltpi1_hvi3c3_default: ltpi1-hvi3c3-default {
++		function = "I3C3";
++		groups = "HVI3C3";
++	};
++
++	pinctrl_ltpi1_i3c4_default: ltpi1-i3c4-default {
++		function = "I3C4";
++		groups = "I3C4";
++	};
++
++	pinctrl_ltpi1_i3c5_default: ltpi1-i3c5-default {
++		function = "I3C5";
++		groups = "I3C5";
++	};
++
++	pinctrl_ltpi1_i3c6_default: ltpi1-i3c6-default {
++		function = "I3C6";
++		groups = "I3C6";
++	};
++
++	pinctrl_ltpi1_i3c7_default: ltpi1-i3c7-default {
++		function = "I3C7";
++		groups = "I3C7";
++	};
++
++	pinctrl_ltpi1_i3c8_default: ltpi1-i3c8-default {
++		function = "I3C8";
++		groups = "I3C8";
++	};
++
++	pinctrl_ltpi1_i3c9_default: ltpi1-i3c9-default {
++		function = "I3C9";
++		groups = "I3C9";
++	};
++
++	pinctrl_ltpi1_i3c10_default: ltpi1-i3c10-default {
++		function = "I3C10";
++		groups = "I3C10";
++	};
++
++	pinctrl_ltpi1_i3c11_default: ltpi1-i3c11-default {
++		function = "I3C11";
++		groups = "I3C11";
++	};
++
++	pinctrl_ltpi1_hvi3c12_default: ltpi1-hvi3c12-default {
++		function = "I3C12";
++		groups = "HVI3C12";
++	};
++
++	pinctrl_ltpi1_hvi3c13_default: ltpi1-hvi3c13-default {
++		function = "I3C13";
++		groups = "HVI3C13";
++	};
++
++	pinctrl_ltpi1_hvi3c14_default: ltpi1-hvi3c14-default {
++		function = "I3C14";
++		groups = "HVI3C14";
++	};
++
++	pinctrl_ltpi1_hvi3c15_default: ltpi1-hvi3c15-default {
++		function = "I3C15";
++		groups = "HVI3C15";
++	};
++
++	pinctrl_ltpi1_adc0_default: ltpi1-adc0-default {
++		function = "ADC0";
++		groups = "ADC0";
++	};
++
++	pinctrl_ltpi1_adc1_default: ltpi1-adc1-default {
++		function = "ADC1";
++		groups = "ADC1";
++	};
++
++	pinctrl_ltpi1_adc2_default: ltpi1-adc2-default {
++		function = "ADC2";
++		groups = "ADC2";
++	};
++
++	pinctrl_ltpi1_adc3_default: ltpi1-adc3-default {
++		function = "ADC3";
++		groups = "ADC3";
++	};
++
++	pinctrl_ltpi1_adc4_default: ltpi1-adc4-default {
++		function = "ADC4";
++		groups = "ADC4";
++	};
++
++	pinctrl_ltpi1_adc5_default: ltpi1-adc5-default {
++		function = "ADC5";
++		groups = "ADC5";
++	};
++
++	pinctrl_ltpi1_adc6_default: ltpi1-adc6-default {
++		function = "ADC6";
++		groups = "ADC6";
++	};
++
++	pinctrl_ltpi1_adc7_default: ltpi1-adc7-default {
++		function = "ADC7";
++		groups = "ADC7";
++	};
++
++	pinctrl_ltpi1_adc8_default: ltpi1-adc8-default {
++		function = "ADC8";
++		groups = "ADC8";
++	};
++
++	pinctrl_ltpi1_adc9_default: ltpi1-adc9-default {
++		function = "ADC9";
++		groups = "ADC9";
++	};
++
++	pinctrl_ltpi1_adc10_default: ltpi1-adc10-default {
++		function = "ADC10";
++		groups = "ADC10";
++	};
++
++	pinctrl_ltpi1_adc11_default: ltpi1-adc11-default {
++		function = "ADC11";
++		groups = "ADC11";
++	};
++
++	pinctrl_ltpi1_adc12_default: ltpi1-adc12-default {
++		function = "ADC12";
++		groups = "ADC12";
++	};
++
++	pinctrl_ltpi1_adc13_default: ltpi1-adc13-default {
++		function = "ADC13";
++		groups = "ADC13";
++	};
++
++	pinctrl_ltpi1_adc14_default: ltpi1-adc14-default {
++		function = "ADC14";
++		groups = "ADC14";
++	};
++
++	pinctrl_ltpi1_adc15_default: ltpi1-adc15-default {
++		function = "ADC15";
++		groups = "ADC15";
++	};
++
++};
+diff --git a/arch/arm64/boot/dts/aspeed/aspeed-ltpi1.dtsi b/arch/arm64/boot/dts/aspeed/aspeed-ltpi1.dtsi
+new file mode 100755
+index 000000000..772d88d70
+--- /dev/null
++++ b/arch/arm64/boot/dts/aspeed/aspeed-ltpi1.dtsi
+@@ -0,0 +1,675 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++#include <dt-bindings/clock/aspeed,ast1700-clk.h>
++#include <dt-bindings/reset/aspeed,ast1700-reset.h>
++
++/ {
++	aliases {
++		i3c200 = &ltpi1_i3c0;
++		i3c201 = &ltpi1_i3c1;
++		i3c202 = &ltpi1_i3c2;
++		i3c203 = &ltpi1_i3c3;
++		i3c204 = &ltpi1_i3c4;
++		i3c205 = &ltpi1_i3c5;
++		i3c206 = &ltpi1_i3c6;
++		i3c207 = &ltpi1_i3c7;
++		i3c208 = &ltpi1_i3c8;
++		i3c209 = &ltpi1_i3c9;
++		i3c210 = &ltpi1_i3c10;
++		i3c211 = &ltpi1_i3c11;
++		i3c212 = &ltpi1_i3c12;
++		i3c213 = &ltpi1_i3c13;
++		i3c214 = &ltpi1_i3c14;
++		i3c215 = &ltpi1_i3c15;
++	};
++
++	ltpi1_bus: ltpi1_bus@50000000 {
++		compatible = "simple-bus";
++		#address-cells = <2>;
++		#size-cells = <2>;
++		ranges;
++
++		ltpi1_syscon: syscon@50c02000 {
++			compatible = "aspeed,ast1700-scu", "syscon", "simple-mfd";
++			reg = <0x0 0x50c02000 0x0 0x1000>;
++			ranges = <0x0 0x0 0x0 0x50c02000 0x0 0x1000>;
++			#address-cells = <2>;
++			#size-cells = <2>;
++			#clock-cells = <1>;
++			#reset-cells = <1>;
++
++			ltpi1_rst: reset-controller@200 {
++				reg = <0x0 0x200 0x0 0x40>;
++			};
++
++			ltpi1_clk: clock-controller@240 {
++				reg = <0x0 0x240 0x0 0x1c0>;
++			};
++
++			ltpi1_pinctrl: pinctrl@400 {
++				compatible = "aspeed,ast1700-pinctrl";
++				reg = <0x0 0x400 0x0 0x100>;
++			};
++		};
++
++		ltpi1_spi2: spi@50030000 {
++			reg = <0x0 0x50030000 0x0 0x1f0>, <0x2 0x80000000 0x0 0x04000000>;
++			#address-cells = <1>;
++			#size-cells = <0>;
++			clocks = <&ltpi1_syscon AST1700_CLK_AHB>;
++			resets = <&ltpi1_syscon AST1700_RESET_SPI2>;
++			num-cs = <2>;
++			ltpi-base = <0x0 0x54000000>;
++			status = "disabled";
++		};
++
++		ltpi1_pwm_tach: pwm-tach-controller@500c0000 {
++			compatible = "aspeed,ast2700-pwm-tach";
++			reg = <0x0 0x500c0000 0 0x100>;
++			clocks = <&ltpi1_syscon AST1700_CLK_AHB>;
++			resets = <&ltpi1_syscon AST1700_RESET_PWM>;
++			#pwm-cells = <3>;
++			status = "disabled";
++		};
++
++		ltpi1_adc0: adc@50c00000 {
++			compatible = "aspeed,ast2700-adc0";
++			reg = <0x0 0x50c00000 0 0x100>;
++			clocks = <&ltpi1_syscon AST1700_CLK_AHB>;
++			resets = <&ltpi1_syscon AST1700_RESET_ADC>;
++			interrupts-extended = <&ltpi1_intc1_0 24>;
++			#io-channel-cells = <1>;
++			aspeed,scu = <&ltpi1_syscon>;
++			status = "disabled";
++		};
++
++		ltpi1_adc1: adc@50c00100 {
++			compatible = "aspeed,ast2700-adc1";
++			reg = <0x0 0x50c00100 0x0 0x100>;
++			clocks = <&ltpi1_syscon AST1700_CLK_AHB>;
++			resets = <&ltpi1_syscon AST1700_RESET_ADC>;
++			interrupts-extended = <&ltpi1_intc1_0 24>;
++			#io-channel-cells = <1>;
++			aspeed,scu = <&ltpi1_syscon>;
++			status = "disabled";
++		};
++
++		ltpi1_jtag: jtag@50c09000 {
++			compatible = "aspeed,ast2700-jtag";
++			reg= <0x0 0x50c09000 0x0 0x40>;
++			clocks = <&ltpi1_syscon AST1700_CLK_AHB>;
++			resets = <&ltpi1_syscon AST1700_RESET_JTAG1>;
++			status = "disabled";
++		};
++
++		ltpi1_i2c: bus@50c0f000 {
++			compatible = "simple-bus";
++			#address-cells = <1>;
++			#size-cells = <1>;
++			ranges = <0x0 0x0 0x50c0f000 0x1100>;
++		};
++
++		ltpi1_intc1: interrupt-controller@50c18000 {
++			compatible = "simple-mfd";
++			reg = <0 0x50c18000 0 0x400>;
++			#address-cells = <2>;
++			#size-cells = <2>;
++			ranges = <0x0 0x0 0x0 0x50c18000 0x0 0x400>;
++
++			ltpi1_intc1_0: interrupt-controller@100 {
++				#interrupt-cells = <1>;
++				interrupt-controller;
++				compatible = "aspeed,ast2700-intc-ic";
++				reg = <0x0 0x100 0x0 0x10>;
++				interrupts-extended = <&intc0_11 8>;
++			};
++
++			ltpi1_intc1_1: interrupt-controller@110 {
++				#interrupt-cells = <1>;
++				interrupt-controller;
++				compatible = "aspeed,ast2700-intc-ic";
++				reg = <0x0 0x110 0x0 0x10>;
++				interrupts-extended = <&intc0_11 9>;
++			};
++		};
++
++		ltpi1_i3c0: i3c0@50c20000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x50c20000 0x0 0x1000>;
++			interrupts-extended = <&ltpi1_intc1_1 0>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi1_syscon AST1700_CLK_GATE_I3C0CLK>;
++			resets = <&ltpi1_syscon AST1700_RESET_I3C0>, <&ltpi1_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi1_hvi3c0_default>;
++			status = "disabled";
++		};
++
++		ltpi1_i3c1: i3c1@50c21000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x50c21000 0x0 0x1000>;
++			interrupts-extended = <&ltpi1_intc1_1 1>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi1_syscon AST1700_CLK_GATE_I3C1CLK>;
++			resets = <&ltpi1_syscon AST1700_RESET_I3C1>, <&ltpi1_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi1_hvi3c1_default>;
++			status = "disabled";
++		};
++
++		ltpi1_i3c2: i3c2@50c22000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x50c22000 0x0 0x1000>;
++			interrupts-extended = <&ltpi1_intc1_1 2>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi1_syscon AST1700_CLK_GATE_I3C2CLK>;
++			resets = <&ltpi1_syscon AST1700_RESET_I3C2>, <&ltpi1_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi1_hvi3c2_default>;
++			status = "disabled";
++		};
++
++		ltpi1_i3c3: i3c3@50c23000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x50c23000 0x0 0x1000>;
++			interrupts-extended = <&ltpi1_intc1_1 3>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi1_syscon AST1700_CLK_GATE_I3C3CLK>;
++			resets = <&ltpi1_syscon AST1700_RESET_I3C3>, <&ltpi1_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi1_hvi3c3_default>;
++			status = "disabled";
++		};
++
++		ltpi1_i3c4: i3c4@50c24000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x50c24000 0x0 0x1000>;
++			interrupts-extended = <&ltpi1_intc1_1 4>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi1_syscon AST1700_CLK_GATE_I3C4CLK>;
++			resets = <&ltpi1_syscon AST1700_RESET_I3C4>, <&ltpi1_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi1_i3c4_default>;
++			status = "disabled";
++		};
++
++		ltpi1_i3c5: i3c5@50c25000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x50c25000 0x0 0x1000>;
++			interrupts-extended = <&ltpi1_intc1_1 5>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi1_syscon AST1700_CLK_GATE_I3C5CLK>;
++			resets = <&ltpi1_syscon AST1700_RESET_I3C5>, <&ltpi1_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi1_i3c5_default>;
++			status = "disabled";
++		};
++
++		ltpi1_i3c6: i3c6@50c26000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x50c26000 0x0 0x1000>;
++			interrupts-extended = <&ltpi1_intc1_1 6>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi1_syscon AST1700_CLK_GATE_I3C6CLK>;
++			resets = <&ltpi1_syscon AST1700_RESET_I3C6>, <&ltpi1_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi1_i3c6_default>;
++			status = "disabled";
++		};
++
++		ltpi1_i3c7: i3c7@50c27000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x50c27000 0x0 0x1000>;
++			interrupts-extended = <&ltpi1_intc1_1 7>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi1_syscon AST1700_CLK_GATE_I3C7CLK>;
++			resets = <&ltpi1_syscon AST1700_RESET_I3C7>, <&ltpi1_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi1_i3c7_default>;
++			status = "disabled";
++		};
++
++		ltpi1_i3c8: i3c8@50c28000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x50c28000 0x0 0x1000>;
++			interrupts-extended = <&ltpi1_intc1_1 8>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi1_syscon AST1700_CLK_GATE_I3C8CLK>;
++			resets = <&ltpi1_syscon AST1700_RESET_I3C8>, <&ltpi1_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi1_i3c8_default>;
++			status = "disabled";
++		};
++
++		ltpi1_i3c9: i3c9@50c29000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x50c29000 0x0 0x1000>;
++			interrupts-extended = <&ltpi1_intc1_1 9>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi1_syscon AST1700_CLK_GATE_I3C9CLK>;
++			resets = <&ltpi1_syscon AST1700_RESET_I3C9>, <&ltpi1_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi1_i3c9_default>;
++			status = "disabled";
++		};
++
++		ltpi1_i3c10: i3c10@50c2a000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x50c2a000 0x0 0x1000>;
++			interrupts-extended = <&ltpi1_intc1_1 10>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi1_syscon AST1700_CLK_GATE_I3C10CLK>;
++			resets = <&ltpi1_syscon AST1700_RESET_I3C10>, <&ltpi1_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi1_i3c10_default>;
++			status = "disabled";
++		};
++
++		ltpi1_i3c11: i3c11@50c2b000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x50c2b000 0x0 0x1000>;
++			interrupts-extended = <&ltpi1_intc1_1 11>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi1_syscon AST1700_CLK_GATE_I3C11CLK>;
++			resets = <&ltpi1_syscon AST1700_RESET_I3C11>, <&ltpi1_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi1_i3c11_default>;
++			status = "disabled";
++		};
++
++		ltpi1_i3c12: i3c12@50c2c000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x50c2c000 0x0 0x1000>;
++			interrupts-extended = <&ltpi1_intc1_1 12>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi1_syscon AST1700_CLK_GATE_I3C12CLK>;
++			resets = <&ltpi1_syscon AST1700_RESET_I3C12>, <&ltpi1_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi1_hvi3c12_default>;
++			status = "disabled";
++		};
++
++		ltpi1_i3c13: i3c13@50c2d000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x50c2d000 0x0 0x1000>;
++			interrupts-extended = <&ltpi1_intc1_1 13>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi1_syscon AST1700_CLK_GATE_I3C13CLK>;
++			resets = <&ltpi1_syscon AST1700_RESET_I3C13>, <&ltpi1_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi1_hvi3c13_default>;
++			status = "disabled";
++		};
++
++		ltpi1_i3c14: i3c14@50c2e000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x50c2e000 0x0 0x1000>;
++			interrupts-extended = <&ltpi1_intc1_1 14>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi1_syscon AST1700_CLK_GATE_I3C14CLK>;
++			resets = <&ltpi1_syscon AST1700_RESET_I3C14>, <&ltpi1_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi1_hvi3c14_default>;
++			status = "disabled";
++		};
++
++		ltpi1_i3c15: i3c15@50c2f000 {
++			compatible = "aspeed-i3c-hci";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x50c2f000 0x0 0x1000>;
++			interrupts-extended = <&ltpi1_intc1_1 15>;
++			i3c-scl-hz = <1000000>;
++			clocks = <&ltpi1_syscon AST1700_CLK_GATE_I3C15CLK>;
++			resets = <&ltpi1_syscon AST1700_RESET_I3C15>, <&ltpi1_syscon AST1700_RESET_I3CDMA>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_ltpi1_hvi3c15_default>;
++			status = "disabled";
++		};
++
++		ltpi1_ltpi: ltpi@50c34000 {
++			compatible = "aspeed-ltpi";
++			reg = <0x0 0x50c34000 0x0 0x100>;
++			clocks = <&ltpi1_syscon AST1700_CLK_GATE_LTPICLK>,
++				 <&ltpi1_syscon AST1700_CLK_GATE_LTPIPHYCLK>;
++			clock-names = "ahb", "phy";
++			resets = <&ltpi1_syscon AST1700_RESET_LTPI>;
++			remote-controller;
++			aspeed,scu = <&ltpi1_syscon>;
++			i2c-tunneling = <0x0>;
++			status = "okay";
++		};
++
++		ltpi1_wdt0: watchdog@50c37000 {
++			compatible = "aspeed,ast2700-wdt";
++			reg = <0x0 0x50c37000 0x0 0x40>;
++		};
++	};
++};
++
++#include "aspeed-ltpi1-pinctrl.dtsi"
++
++&ltpi1_i2c {
++	ltpi1_i2c_global: i2c-global-regs@0 {
++		compatible = "aspeed,i2c-global", "simple-mfd", "syscon";
++		reg = <0x0 0x100>;
++		status = "disabled";
++	};
++
++	ltpi1_i2c0: i2c-bus@100 {
++		#address-cells = <1>;
++		#size-cells = <1>;
++		#interrupt-cells = <1>;
++		reg = <0x100 0x80>, <0x1a0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi1_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi1_syscon AST1700_CLK_APB>;
++		resets = <&ltpi1_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi1_intc1_0 0>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi1_i2c0_default>;
++		status = "disabled";
++	};
++
++	ltpi1_i2c1: i2c-bus@200 {
++		#address-cells = <1>;
++		#size-cells = <1>;
++		#interrupt-cells = <1>;
++		reg = <0x200 0x80>, <0x2a0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi1_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi1_syscon AST1700_CLK_APB>;
++		resets = <&ltpi1_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi1_intc1_0 1>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi1_i2c1_default>;
++		status = "disabled";
++	};
++
++	ltpi1_i2c2: i2c-bus@300 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0x300 0x80>, <0x3a0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi1_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi1_syscon AST1700_CLK_APB>;
++		resets = <&ltpi1_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi1_intc1_0 2>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi1_i2c2_default>;
++		status = "disabled";
++	};
++
++	ltpi1_i2c3: i2c-bus@400 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0x400 0x80>, <0x4a0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi1_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi1_syscon AST1700_CLK_APB>;
++		resets = <&ltpi1_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi1_intc1_0 3>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi1_i2c3_default>;
++		status = "disabled";
++	};
++
++	ltpi1_i2c4: i2c-bus@500 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0x500 0x80>, <0x5a0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi1_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi1_syscon AST1700_CLK_APB>;
++		resets = <&ltpi1_syscon AST1700_RESET_I2C>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		interrupts-extended = <&ltpi1_intc1_0 4>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi1_i2c4_default>;
++		status = "disabled";
++	};
++
++	ltpi1_i2c5: i2c-bus@600 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0x600 0x80>, <0x6a0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi1_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi1_syscon AST1700_CLK_APB>;
++		resets = <&ltpi1_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi1_intc1_0 5>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi1_i2c5_default>;
++		status = "disabled";
++	};
++
++	ltpi1_i2c6: i2c-bus@700 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0x700 0x80>, <0x7a0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi1_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi1_syscon AST1700_CLK_APB>;
++		resets = <&ltpi1_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi1_intc1_0 6>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi1_i2c6_default>;
++		status = "disabled";
++	};
++
++	ltpi1_i2c7: i2c-bus@800 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0x800 0x80>, <0x8a0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi1_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi1_syscon AST1700_CLK_APB>;
++		resets = <&ltpi1_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi1_intc1_0 7>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi1_i2c7_default>;
++		status = "disabled";
++	};
++
++	ltpi1_i2c8: i2c-bus@900 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0x900 0x80>, <0x9a0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi1_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi1_syscon AST1700_CLK_APB>;
++		resets = <&ltpi1_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi1_intc1_0 8>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi1_i2c8_default>;
++		status = "disabled";
++	};
++
++	ltpi1_i2c9: i2c-bus@a00 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0xa00 0x80>, <0xaa0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi1_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi1_syscon AST1700_CLK_APB>;
++		resets = <&ltpi1_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi1_intc1_0 9>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi1_i2c9_default>;
++		status = "disabled";
++	};
++
++	ltpi1_i2c10: i2c-bus@b00 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0xb00 0x80>, <0xba0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi1_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi1_syscon AST1700_CLK_APB>;
++		resets = <&ltpi1_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi1_intc1_0 10>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi1_i2c10_default>;
++		status = "disabled";
++	};
++
++	ltpi1_i2c11: i2c-bus@c00 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0xc00 0x80>, <0xca0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi1_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi1_syscon AST1700_CLK_APB>;
++		resets = <&ltpi1_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi1_intc1_0 11>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi1_i2c11_default>;
++		status = "disabled";
++	};
++
++	ltpi1_i2c12: i2c-bus@d00 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0xd00 0x80>, <0xda0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi1_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi1_syscon AST1700_CLK_APB>;
++		resets = <&ltpi1_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi1_intc1_0 12>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi1_i2c12_default>;
++		status = "disabled";
++	};
++
++	ltpi1_i2c13: i2c-bus@e00 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0xe00 0x80>, <0xea0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi1_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi1_syscon AST1700_CLK_APB>;
++		resets = <&ltpi1_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi1_intc1_0 13>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi1_i2c13_default>;
++		status = "disabled";
++	};
++
++	ltpi1_i2c14: i2c-bus@f00 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0xf00 0x80>, <0xfa0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi1_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi1_syscon AST1700_CLK_APB>;
++		resets = <&ltpi1_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi1_intc1_0 14>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi1_i2c14_default>;
++		status = "disabled";
++	};
++
++	ltpi1_i2c15: i2c-bus@1000 {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		#interrupt-cells = <1>;
++		reg = <0x1000 0x80>, <0x10a0 0x20>;
++		compatible = "aspeed,ast2700-i2c";
++		aspeed,global-regs = <&ltpi1_i2c_global>;
++		aspeed,enable-dma;
++		clocks = <&ltpi1_syscon AST1700_CLK_APB>;
++		resets = <&ltpi1_syscon AST1700_RESET_I2C>;
++		interrupts-extended = <&ltpi1_intc1_0 15>;
++		clock-frequency = <100000>;
++		debounce-level = <2>;
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_ltpi1_i2c15_default>;
++		status = "disabled";
++	};
++};
+diff --git a/arch/arm64/boot/dts/aspeed/ast2700-dcscm.dts b/arch/arm64/boot/dts/aspeed/ast2700-dcscm.dts
+new file mode 100755
+index 000000000..8bed5f980
+--- /dev/null
++++ b/arch/arm64/boot/dts/aspeed/ast2700-dcscm.dts
+@@ -0,0 +1,990 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++
++/dts-v1/;
++
++#include "aspeed-g7.dtsi"
++#include <dt-bindings/gpio/aspeed-gpio.h>
++#include <dt-bindings/i2c/i2c.h>
++
++/ {
++	model = "AST2700-DCSCM";
++	compatible = "aspeed,ast2700";
++
++	chosen {
++		stdout-path = &uart12;
++	};
++
++	firmware {
++		optee: optee {
++			compatible = "linaro,optee-tz";
++			method = "smc";
++		};
++	};
++
++	memory@400000000 {
++		device_type = "memory";
++		reg = <0x4 0x00000000 0x0 0x40000000>;
++	};
++
++	reserved-memory {
++		#address-cells = <2>;
++		#size-cells = <2>;
++		ranges;
++
++		#include "ast2700-reserved-mem.dtsi"
++
++		video_engine_memory0: video0 {
++			size = <0x0 0x02c00000>;
++			alignment = <0x0 0x00100000>;
++			compatible = "shared-dma-pool";
++			reusable;
++		};
++
++		video_engine_memory1: video1{
++			size = <0x0 0x02c00000>;
++			alignment = <0x0 0x00100000>;
++			compatible = "shared-dma-pool";
++			reusable;
++		};
++
++		gfx_memory: framebuffer {
++			size = <0x0 0x01000000>;
++			alignment = <0x0 0x01000000>;
++			compatible = "shared-dma-pool";
++			reusable;
++		};
++
++		xdma_memory0: xdma0 {
++			size = <0x0 0x01000000>;
++			alignment = <0x0 0x01000000>;
++			compatible = "shared-dma-pool";
++			no-map;
++		};
++
++		xdma_memory1: xdma1 {
++			size = <0x0 0x01000000>;
++			alignment = <0x0 0x01000000>;
++			compatible = "shared-dma-pool";
++			no-map;
++		};
++	};
++
++	iio-hwmon {
++		compatible = "iio-hwmon";
++		io-channels = <&adc0 7>, <&adc1 7>;
++	};
++};
++
++&pwm_tach {
++	status = "okay";
++	pinctrl-names = "default";
++	pinctrl-0 = <&pinctrl_pwm9_default>;
++};
++
++&adc0 {
++	aspeed,int-vref-microvolt = <2500000>;
++	status = "okay";
++	aspeed,battery-sensing;
++	pinctrl-names = "default";
++	pinctrl-0 = <&pinctrl_adc7_default>;
++};
++
++&adc1 {
++	aspeed,int-vref-microvolt = <2500000>;
++	status = "okay";
++	aspeed,battery-sensing;
++	pinctrl-names = "default";
++	pinctrl-0 = <&pinctrl_adc15_default>;
++};
++
++&pinctrl1 {
++	pinctrl_i3c0_3_hv_voltage: i3chv-voltage {
++		pins = "U25";
++		power-source = <1800>;
++	};
++
++	pinctrl_i3c0_driving: i3c0-driving {
++		pins = "U25", "U26";
++		drive-strength = <2>;
++	};
++
++	pinctrl_i3c1_driving: i3c1-driving {
++		pins = "Y26", "AA24";
++		drive-strength = <2>;
++	};
++
++	pinctrl_i3c2_driving: i3c2-driving {
++		pins = "R25", "AA26";
++		drive-strength = <2>;
++	};
++
++	pinctrl_i3c3_driving: i3c3-driving {
++		pins = "R26", "Y25";
++		drive-strength = <2>;
++	};
++
++	pinctrl_rgmii0_driving: rgmii0-driving {
++		pins = "C20", "C19", "A8", "R14", "A7", "P14",
++		       "D20", "A6", "B6", "N14", "B7", "B8";
++		drive-strength = <1>;
++	};
++};
++
++&i3c0 {
++	/* BMC_HPM_I3C_I2C_14, If AST1060 I3C_BMC_PFR_SCM_SEL(GPION4)=0 and I3C_SCM_EN(GPION5)=0 */
++	initial-role = "primary";
++	status = "okay";
++};
++
++&i3c1 {
++	/* BMC_I2C_I3C1_SCL1 */
++	initial-role = "primary";
++	status = "okay";
++};
++
++&i3c2 {
++	/* BMC_I2C_I3C2_SCL2 */
++	initial-role = "primary";
++	status = "okay";
++};
++
++&i3c3 {
++	/* I3C_DBG_SCM */
++	initial-role = "primary";
++	status = "okay";
++};
++
++/* AST2700 i3c4 -> AST1060 i3c2 for MCTP over I3C. */
++&i3c4 {
++	/* I3C_PFR_BMC */
++	initial-role = "target";
++	pid = <0x000007ec 0x06000000>;
++	dcr = /bits/ 8 <0xcc>;
++	status = "okay";
++};
++
++&i3c5 {
++	/* I3C_MNG_BMC_SCM */
++	initial-role = "primary";
++	status = "okay";
++};
++
++&i3c6 {
++	/* I3C_SPD_SCM */
++	initial-role = "primary";
++	status = "okay";
++};
++
++/* Enable UART2 and UART9 for obmc-console. */
++&uart2 {
++	/delete-property/ pinctrl-names;
++	/delete-property/ pinctrl-0;
++	status = "okay";
++};
++
++&uart9 {
++	/delete-property/ pinctrl-names;
++	/delete-property/ pinctrl-0;
++	status = "okay";
++};
++
++/* Enable UART7 and UART10 for obmc-console. */
++&uart7 {
++	/delete-property/ pinctrl-names;
++	/delete-property/ pinctrl-0;
++	status = "okay";
++};
++
++&uart10 {
++	/delete-property/ pinctrl-names;
++	/delete-property/ pinctrl-0;
++	status = "okay";
++};
++
++/* UART3, UART13 and UART14 will be tunnelded to LTPI UART channels. */
++&uart3 {
++	/delete-property/ pinctrl-names;
++	/delete-property/ pinctrl-0;
++	status = "okay";
++};
++
++&uart13 {
++	status = "okay";
++};
++
++&uart14 {
++	status = "okay";
++};
++
++&uart12 {
++	status = "okay";
++};
++
++&fmc {
++	status = "okay";
++	pinctrl-0 = <&pinctrl_fwspi_quad_default>;
++	pinctrl-names = "default";
++
++	flash@0 {
++		status = "okay";
++		m25p,fast-read;
++		label = "bmc";
++		spi-max-frequency = <12500000>;
++		spi-tx-bus-width = <4>;
++		spi-rx-bus-width = <4>;
++		partitions {
++			compatible = "fixed-partitions";
++			#address-cells = <1>;
++			#size-cells = <1>;
++			u-boot@0 {
++				reg = <0x0 0x400000>; // 4MB
++				label = "u-boot";
++			};
++			u-boot-env@400000 {
++				reg = <0x400000 0x20000>; // 128KB
++				label = "u-boot-env";
++			};
++			kernel@420000 {
++				reg = <0x420000 0x900000>; // 9MB
++				label = "kernel";
++			};
++			rofs@d20000 {
++				reg = <0xd20000 0x24a0000>; // 36.625MB
++				label = "rofs";
++			};
++			rwfs@31c0000 {
++				reg = <0x31c0000 0xE40000>; // 14.25MB
++				label = "rwfs";
++			};
++			pfm@4000000 {
++				reg = <0x4000000 0x20000>; // 128KB
++				label = "pfm";
++			};
++			reserved-1@4020000 {
++				reg = <0x4020000 0x200000>; // 128KB
++				label = "reserved-1";
++			};
++			rc-image@4220000 {
++				reg = <0x4220000 0x3de0000>; // 63360KB
++				label = "rc-image";
++			};
++			image-stg@8000000 {
++				reg = <0x8000000 0x3de0000>; // 63360KB
++				label = "img-stg";
++			};
++			pfr-stg@bde0000 {
++				reg = <0xbde0000 0x100000>; // 1024KB
++				label = "pfr-stg";
++			};
++			cpld-stg@bee0000 {
++				reg = <0xbee0000 0x400000>; // 4096KB
++				label = "cpld-stg";
++			};
++			afm-stg@c2e0000 {
++				reg = <0xc2e0000 0x20000>; // 128KB
++				label = "afm-stg";
++			};
++			afm-rc@c300000 {
++				reg = <0xc300000 0x20000>; // 128KB
++				label = "afm-rc";
++			};
++			reserved-2@c320000 {
++				reg = <0xc320000 0x3ce0000>; // 62336KB
++				label = "reserved-2";
++			};
++		};
++	};
++};
++
++&spi0 {
++	status = "okay";
++	pinctrl-0 = <&pinctrl_spi0_default &pinctrl_spi0_cs1_default>;
++	pinctrl-names = "default";
++
++	flash@0 {
++		status = "okay";
++		m25p,fast-read;
++		label = "spi0:0";
++		spi-max-frequency = <12500000>;
++		spi-tx-bus-width = <1>;
++		spi-rx-bus-width = <1>;
++		partitions {
++			compatible = "fixed-partitions";
++			#address-cells = <1>;
++			#size-cells = <1>;
++			spi0_pch_bios@0 {
++				reg = <0x0 0x3fe0000>;
++				label = "spi0_pch_reserved";
++			};
++			spi0_pch_pfm@3fe0000 {
++				reg = <0x3fe0000 0x20000>;
++				label = "spi0_pch_pfm";
++			};
++			spi0_pch_stg@4000000 {
++				reg = <0x4000000 0x2000000>;
++				label = "spi0_pch_stg";
++			};
++			spi0_pch_rc@6000000 {
++				reg = <0x6000000 0x2000000>;
++				label = "spi0_pch_rc";
++			};
++		};
++	};
++
++	flash@1 {
++		status = "okay";
++		m25p,fast-read;
++		label = "spi0:1";
++		spi-max-frequency = <12500000>;
++		spi-tx-bus-width = <1>;
++		spi-rx-bus-width = <1>;
++	};
++};
++
++&spi1 {
++	status = "okay";
++	pinctrl-0 = <&pinctrl_spi1_default &pinctrl_spi1_cs1_default>;
++	pinctrl-names = "default";
++
++	flash@0 {
++		status = "okay";
++		m25p,fast-read;
++		label = "spi1:0";
++		spi-max-frequency = <12500000>;
++		spi-tx-bus-width = <1>;
++		spi-rx-bus-width = <1>;
++		partitions {
++			compatible = "fixed-partitions";
++			#address-cells = <1>;
++			#size-cells = <1>;
++
++			spi1_pch_reserved@0 {
++				reg = <0x0 0x7f0000>;
++				label = "spi1_pch_reserved";
++			};
++
++			spi1_pch_stg@7f0000 {
++				reg = <0x7f0000 0x1400000>;
++				label = "spi1_pch_stg";
++			};
++
++			spi1_pch_rc@1bf0000 {
++				reg = <0x1bf0000 0x1400000>;
++				label = "spi1_pch_rc";
++			};
++
++			spi1_pch_pfm@2ff0000 {
++				reg = <0x2ff0000 0x10000>;
++				label = "spi1_pch_pfm";
++			};
++
++			spi1_pch_bios@3000000 {
++				reg = <0x3000000 0x1000000>;
++				label = "spi1_pch_bios";
++			};
++		};
++	};
++
++	flash@1 {
++		status = "okay";
++		m25p,fast-read;
++		label = "spi1:1";
++		spi-max-frequency = <12500000>;
++		spi-tx-bus-width = <1>;
++		spi-rx-bus-width = <1>;
++	};
++};
++
++&ltpi0 {
++	status = "okay";
++};
++
++&ltpi1 {
++	/* Do not tunnel I2C10 to the HPM */
++	i2c-tunneling = <0x2f>;
++	status = "okay";
++};
++
++/* The LTPI GPIO table is defined in Chapter 6 of the AST2700 LTPI Design Guide v10.pdf. */
++/* line 0:BMC_GPI0(LTPI0_INL16), 1:BMC_GPO0(LTPI0_ONL16), 2:BMC_GPI1(LTPI0_INL17), 3:BMC_GPO1(LTPI0_ONL17), etc... */
++/* BMC_GPI[63:0]   = LTPI0_INL[79:16], BMC_GPO[63:0]   = LTPI0_ONL[79:16] */
++/* BMC_GPI[71:64]  = LTPI0_ILL[11:4],  BMC_GPO[71:64]  = LTPI0_OLL[11:4] */
++/* BMC_GPI[111:72] = LTPI0_INL[127:88],BMC_GPO[111:72] = LTPI0_ONL[127:88] */
++&ltpi0_gpio {
++	status = "okay";
++	gpio-line-names =
++		/*00-07*/ "","","","","","","","",
++		/*08-15*/ "","","","","","","","",
++		/*16-23*/ "","FM_CPU_FBRK_DEBUG_N","","FM_BMC_TRUST_N","","FM_RST_BTN_OUT_CPU0_PLD_N_OE","","FM_PWR_BTN_OUT_CPU0_N",
++		/*24-31*/ "","FM_BMC_ONCTL_N","","","","","","",
++		/*32-39*/ "","BIOS_POST_CODE_LED_0","","BIOS_POST_CODE_LED_1","","BIOS_POST_CODE_LED_2","","BIOS_POST_CODE_LED_3",
++		/*40-47*/ "FP_ID_BTN_N","BIOS_POST_CODE_LED_4","FP_RST_BTN_N","BIOS_POST_CODE_LED_5","","BIOS_POST_CODE_LED_6","","BIOS_POST_CODE_LED_7",
++		/*48-55*/ "","A_P3V_BAT_SCALED_EN","","FM_TPM_EN_PULSE","","FM_SKT0_FAULT_LED","","FM_SKT1_FAULT_LED",
++		/*56-63*/ "","","","","","RST_BMC_SMB_PCIE_MUX_N","","SURPRISE_RESET",
++		/*64-71*/ "PWRGD_S0_PWROK_CPU0","","","","","","","",
++		/*72-79*/ "","","","","","","","",
++		/*80-87*/ "","","","","","","","",
++		/*88-95*/ "","","","","","","","",
++		/*96-103*/ "","","","","","","","",
++		/*104-111*/ "","","","","","","","",
++		/*112-119*/ "","","","","","","","",
++		/*120-127*/ "","","","","","","","",
++		/*128-135*/ "","","","","","","","",
++		/*136-143*/ "","","","","","","","",
++		/*144-151*/ "","","","","","","","",
++		/*152-159*/ "","","","","","","","",
++		/*160-167*/ "","","","","","","","",
++		/*168-175*/ "","","","","","","","",
++		/*176-183*/ "","","","","","","","",
++		/*184-191*/ "","","","","","","","",
++		/*192-199*/ "","","","","","","","",
++		/*200-207*/ "","","","","","","","",
++		/*208-215*/ "","","","","","","","",
++		/*216-223*/ "","","","","","","","";
++
++	gpio_17 {
++		gpio-hog;
++		gpios = <17 GPIO_ACTIVE_HIGH>;
++		output-high;
++		line-name = "FM_CPU_FBRK_DEBUG_N";
++	};
++	gpio_19 {
++		gpio-hog;
++		gpios = <19 GPIO_ACTIVE_HIGH>;
++		output-high;
++		line-name = "FM_BMC_TRUST_N";
++	};
++	gpio_25 {
++		gpio-hog;
++		gpios = <25 GPIO_ACTIVE_HIGH>;
++		output-low;
++		line-name = "FM_BMC_ONCTL_N";
++	};
++	gpio_53 {
++		gpio-hog;
++		gpios = <53 GPIO_ACTIVE_HIGH>;
++		output-high;
++		line-name = "FM_SKT0_FAULT_LED";
++	};
++	gpio_61 {
++		gpio-hog;
++		gpios = <61 GPIO_ACTIVE_HIGH>;
++		output-high;
++		line-name = "RST_BMC_SMB_PCIE_MUX_N";
++	};
++	gpio_63 {
++		gpio-hog;
++		gpios = <63 GPIO_ACTIVE_HIGH>;
++		output-low;
++		line-name = "SURPRISE_RESET";
++	};
++};
++
++&peci0 {
++	status = "okay";
++};
++
++&chassis {
++	status = "okay";
++};
++
++&mdio0 {
++	status = "okay";
++	#address-cells = <1>;
++	#size-cells = <0>;
++
++	ethphy0: ethernet-phy@0 {
++		compatible = "ethernet-phy-ieee802.3-c22";
++		reg = <0>;
++	};
++};
++
++&mac0 {
++	status = "okay";
++
++	phy-mode = "rgmii-id";
++	phy-handle = <&ethphy0>;
++
++	pinctrl-names = "default";
++	pinctrl-0 = <&pinctrl_rgmii0_default &pinctrl_rgmii0_driving>;
++};
++
++&syscon1 {
++	assigned-clocks = <&syscon1 SCU1_CLK_MACHCLK>,
++			  <&syscon1 SCU1_CLK_RGMII>,
++			  <&syscon1 SCU1_CLK_RMII>;
++	assigned-clock-rates = <200000000>, <125000000>, <50000000>;
++};
++
++&gpio1 {
++	pinctrl-0 = <&pinctrl_i3c0_3_hv_voltage
++		     &pinctrl_i3c0_driving &pinctrl_i3c1_driving
++		     &pinctrl_i3c2_driving &pinctrl_i3c3_driving>;
++	pinctrl-names = "default";
++
++	gpio-line-names =
++		/*A0-A7*/ "","","","","","","","",
++		/*B0-B7*/ "","","","","","","","",
++		/*C0-C7*/ "","","","","","","","",
++		/*D0-D7*/ "","","","","","","","",
++		/*E0-E7*/ "","","","","FP_LED_STATUS_GREEN_CPLD_N","FP_LED_STATUS_AMBER_CPLD_N","","",
++		/*F0-F7*/ "","","","","","","","",
++		/*G0-G7*/ "","","","","","","","",
++		/*H0-H7*/ "","","","","","","","",
++		/*I0-I7*/ "","","","","","","","",
++		/*J0-J7*/ "","","","","","","","",
++		/*K0-K7*/ "","","","","","","","",
++		/*L0-L7*/ "","","","","","","","",
++		/*M0-M7*/ "","","","","","","","",
++		/*N0-N7*/ "","","","","","","","",
++		/*O0-O7*/ "","","","","","","","",
++		/*P0-P7*/ "","","","","","","","",
++		/*Q0-Q7*/ "","","","","","","","",
++		/*R0-R7*/ "","","","","","","","",
++		/*S0-S7*/ "","","","","","","","",
++		/*T0-T7*/ "","","","","","","","",
++		/*U0-U7*/ "","","","","","SCM_PHY_RST","","",
++		/*V0-V7*/ "","","","","","","","",
++		/*W0-W7*/ "","","","","","","","",
++		/*X0-X7*/ "","","","","","","","",
++		/*Y0-Y7*/ "","","","","IRQ_PMBUS1_ALERT_LVC3_N","FM_NVME_LVC3_ALERT_N","","",
++		/*Z0-Z7*/ "","","FM_NODE_ID0_N","FM_NODE_ID1_N","","PWRGD_AUX_PWRGD_PFR_CPU0","PWRGD_AUX_PWRGD_PFR_CPU1","",
++		/*AA0-AA7*/ "BMC_BOOT_DONE","","","","","","","",
++		/*AB0-AB7*/ "","","","","","","","",
++		/*AC0-AC7*/ "","","","","","","","",
++		/*AD0-AD7*/ "","","","","","","","",
++		/*AE0-AE7*/ "","","","","","","","";
++};
++
++/* AST2700 A1 support SGPIO slave to 72*2 pins. */
++/* The SGPIO slave table is defined in Chapter 7 of the AST2700 LTPI Design Guide v10.pdf. */
++/* line 0:BMC_SGPI0(SCM_GPI0), 1:BMC_SGPO0(SCM_GPO0), 2:BMC_SGPI1(SCM_GPI1), 3:BMC_SGPO1(SCM_GPO1), etc... */
++/* line 32:BMC_SGPI16(LTPI0_INL80), 33:BMC_SGPO16(LTPI0_ONL80), 34:LTPI0_INL81, 35:LTPI0_ONL81, etc... */
++/* BMC_SGPI[15:0] = SCM_GPI0[15:0], BMC_SGPO[15:0] = BMC_SGPO0[15:0] */
++/* BMC_SGPI[23:16] = LTPI0_INL[87:80], BMC_SGPO[23:16] = LTPI0_ONL[87:80] */
++/* BMC_SGPI[31:24] = LTPI1_INL[87:80], BMC_SGPO[31:24] = LTPI1_ONL[87:80] */
++/* BMC_SGPI[47:32] = LTPI0_INL[15:0],  BMC_SGPO[47:32] = LTPI0_ONL[15:0] */
++/* BMC_SGPI[63:48] = LTPI1_INL[15:0],  BMC_SGPO[63:48] = LTPI1_ONL[15:0] */
++/* BMC_SGPI[71:64] = SREG_GPO[7:0],    BMC_SGPO[71:64] = SREG_GPI[7:0] */
++/* The designe guide only define SCM_GPO9(FP_PWR_BTN_PFR_N) for PFR output pin. */
++/* We use AST2700 SGPIOS line 18 (FP_PWR_BTN_PFR_N_BMC_IN) for x86-power-control power button input. */
++&sgpios {
++	status = "okay";
++	gpio-line-names =
++		/*00-07*/ "","","","","","","","",
++		/*08-15*/ "","","","","","","","",
++		/*16-23*/ "","","FP_PWR_BTN_PFR_N_BMC_IN","","","","","",
++		/*24-31*/ "","","","","","","","",
++		/*32-39*/ "","","","","","","","",
++		/*40-47*/ "","","","","","","","",
++		/*48-55*/ "","","","","","","","",
++		/*56-63*/ "","","","","","","","",
++		/*64-71*/ "","","","","","","","",
++		/*72-79*/ "","","","","","","","",
++		/*80-87*/ "","","","","","","","",
++		/*88-95*/ "","","","","","","","",
++		/*96-103*/ "","","","","","","","",
++		/*104-111*/ "","","","","","","","",
++		/*112-119*/ "","","","","","","","",
++		/*120-127*/ "","","","","","","","",
++		/*128-135*/ "","","","","","","","",
++		/*136-143*/ "","","","","","","","";
++};
++
++&espi0 {
++	status = "okay";
++	perif-dma-mode;
++	perif-mmbi-enable;
++	perif-mmbi-src-addr = <0x0 0xa8000000>;
++	perif-mmbi-tgt-memory = <&espi0_mmbi_memory>;
++	perif-mmbi-instance-num = <0x1>;
++	perif-mcyc-enable;
++	perif-mcyc-src-addr = <0x0 0x98000000>;
++	perif-mcyc-size = <0x0 0x10000>;
++	oob-dma-mode;
++	flash-dma-mode;
++};
++
++#if 0 //eSPI1 and SD are multi-functional pin, SD default on
++&espi1 {
++	status = "okay";
++	perif-dma-mode;
++	perif-mmbi-enable;
++	perif-mmbi-src-addr = <0x0 0xa8000000>;
++	perif-mmbi-tgt-memory = <&espi1_mmbi_memory>;
++	perif-mmbi-instance-num = <0x1>;
++	perif-mcyc-enable;
++	perif-mcyc-src-addr = <0x0 0x98000000>;
++	perif-mcyc-size = <0x0 0x10000>;
++	oob-dma-mode;
++	flash-dma-mode;
++};
++#endif
++
++&lpc0_kcs0 {
++	status = "okay";
++	kcs-io-addr = <0xca0>;
++	kcs-channel = <0>;
++};
++
++&lpc0_kcs1 {
++	status = "okay";
++	kcs-io-addr = <0xca8>;
++	kcs-channel = <1>;
++};
++
++&lpc0_kcs2 {
++	status = "okay";
++	kcs-io-addr = <0xca2>;
++	kcs-channel = <2>;
++};
++
++&lpc0_kcs3 {
++	status = "okay";
++	kcs-io-addr = <0xca4>;
++	kcs-channel = <3>;
++};
++
++&lpc0_ibt {
++	status = "okay";
++};
++
++&lpc0_mbox {
++	status = "okay";
++};
++
++&lpc0_snoop {
++	status = "okay";
++	snoop-ports = <0x80>, <0x81>;
++};
++
++&lpc0_uart_routing {
++	status = "okay";
++};
++
++&lpc1_kcs0 {
++	status = "okay";
++	kcs-io-addr = <0xca0>;
++	kcs-channel = <4>;
++};
++
++&lpc1_kcs1 {
++	status = "okay";
++	kcs-io-addr = <0xca8>;
++	kcs-channel = <5>;
++};
++
++&lpc1_kcs2 {
++	status = "okay";
++	kcs-io-addr = <0xca2>;
++	kcs-channel = <6>;
++};
++
++&lpc1_kcs3 {
++	status = "okay";
++	kcs-io-addr = <0xca4>;
++	kcs-channel = <7>;
++};
++
++&lpc1_ibt {
++	status = "okay";
++};
++
++&lpc1_mbox {
++	status = "okay";
++};
++
++&lpc1_snoop {
++	status = "okay";
++	snoop-ports = <0x80>, <0x81>;
++};
++
++&lpc1_uart_routing {
++	status = "okay";
++};
++
++&video0 {
++	status = "okay";
++	memory-region = <&video_engine_memory0>;
++};
++
++&video1 {
++	status = "okay";
++	memory-region = <&video_engine_memory1>;
++};
++
++&disp_intf {
++	status = "okay";
++};
++
++&rtc {
++	status = "okay";
++};
++
++&rsss {
++	status = "okay";
++};
++
++&ecdsa {
++	status = "okay";
++};
++
++&hace {
++	status = "okay";
++};
++
++&bmc_dev0 {
++	status = "okay";
++	memory-region = <&bmc_dev0_memory>;
++};
++
++&xdma0 {
++	status = "okay";
++	memory-region = <&xdma_memory0>;
++};
++
++&pcie_vuart0 {
++	port = <0x3f8>;
++	sirq = <4>;
++	sirq-polarity = <0>;
++
++	status = "okay";
++};
++
++&pcie_vuart1 {
++	port = <0x2f8>;
++	sirq = <3>;
++	sirq-polarity = <0>;
++
++	status = "okay";
++};
++
++&pcie_lpc0_kcs0 {
++	status = "okay";
++	kcs-io-addr = <0x3a0>;
++	kcs-channel = <8>;
++};
++
++&pcie_lpc0_kcs1 {
++	status = "okay";
++	kcs-io-addr = <0x3a8>;
++	kcs-channel = <9>;
++};
++
++&pcie_lpc0_kcs2 {
++	status = "okay";
++	kcs-io-addr = <0x3a2>;
++	kcs-channel = <10>;
++};
++
++&pcie_lpc0_kcs3 {
++	status = "okay";
++	kcs-io-addr = <0x3a4>;
++	kcs-channel = <11>;
++};
++
++&pcie_lpc0_ibt {
++	status = "okay";
++	bt-channel = <2>;
++};
++
++&bmc_dev1 {
++	status = "okay";
++	memory-region = <&bmc_dev1_memory>;
++};
++
++&xdma1 {
++	status = "okay";
++	memory-region = <&xdma_memory1>;
++};
++
++&pcie_vuart2 {
++	port = <0x3f8>;
++	sirq = <4>;
++	sirq-polarity = <0>;
++
++	status = "okay";
++};
++
++&pcie_vuart3 {
++	port = <0x2f8>;
++	sirq = <3>;
++	sirq-polarity = <0>;
++
++	status = "okay";
++};
++
++&pcie_lpc1_kcs0 {
++	status = "okay";
++	kcs-io-addr = <0x3a0>;
++	kcs-channel = <12>;
++};
++
++&pcie_lpc1_kcs1 {
++	status = "okay";
++	kcs-io-addr = <0x3a8>;
++	kcs-channel = <13>;
++};
++
++&pcie_lpc1_kcs2 {
++	status = "okay";
++	kcs-io-addr = <0x3a2>;
++	kcs-channel = <14>;
++};
++
++&pcie_lpc1_kcs3 {
++	status = "okay";
++	kcs-io-addr = <0x3a4>;
++	kcs-channel = <15>;
++};
++
++&pcie_lpc1_ibt {
++	status = "okay";
++	bt-channel = <3>;
++};
++
++&mctp0 {
++	status = "okay";
++	memory-region = <&mctp0_reserved>;
++};
++
++&mctp1 {
++	status = "okay";
++	memory-region = <&mctp1_reserved>;
++};
++
++/* Enable i2c0~i2c4 for LTPI testing. */
++&i2c0 {
++	/* SMB_PMBUS1_SCM */
++	/delete-property/ pinctrl-names;
++	/delete-property/ pinctrl-0;
++	status = "okay";
++};
++
++&i2c1 {
++	/* SMB_IPMB_SCL1 */
++	/delete-property/ pinctrl-names;
++	/delete-property/ pinctrl-0;
++	status = "okay";
++};
++
++&i2c2 {
++	/* SMB_CPLD_SCL2 */
++	/delete-property/ pinctrl-names;
++	/delete-property/ pinctrl-0;
++	status = "okay";
++};
++
++&i2c3 {
++	/* SMB_PMBUS2_SCM */
++	/delete-property/ pinctrl-names;
++	/delete-property/ pinctrl-0;
++	status = "okay";
++};
++
++&i2c4 {
++	/* SMB_PMBUS1_SCM */
++	/delete-property/ pinctrl-names;
++	/delete-property/ pinctrl-0;
++	status = "okay";
++};
++
++/* Default i2c5 is tunnelded to LTPI. */
++/* Enable i2c5 pinctrl for testing on board LM75. */
++&i2c5 {
++	/* SMB_TMP_BMC */
++	status = "okay";
++};
++
++/* AST2700 i2c8 -> AST1060 i2c5 for PCH mailbox emulation test. */
++&i2c8 {
++	/* SMB_PCIE_SCM */
++	status = "okay";
++	multi-master;
++	mctp-controller;
++	mctp@10 {
++		compatible = "mctp-i2c-controller";
++		reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
++	};
++};
++
++&i2c9 {
++	/* SMB_HOST_BMC */
++	status = "okay";
++	eeprom@50 {
++		compatible = "atmel,24c04";
++		reg = <0x50>;
++		pagesize = <16>;
++	};
++};
++
++/* AST2700 A1 i2c10 -> AST1060 i2c0 for PFR mailbox. */
++&i2c10 {
++	/* SMB_HSBP_BMC */
++	status = "okay";
++	multi-master;
++	mctp-controller;
++	mctp@10 {
++		compatible = "mctp-i2c-controller";
++		reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
++	};
++};
++
++&i2c11 {
++	/* BMC_HPM_I3C_I2C_13 */
++	status = "okay";
++};
++
++&uphy3a {
++	status = "okay";
++};
++
++&uphy3b {
++	status = "okay";
++};
++
++&vhuba0 {
++	status = "okay";
++	pinctrl-0 = <&pinctrl_usb2ahpd0_default>;
++};
++
++&usb3ahp {
++	status = "okay";
++	pinctrl-0 = <&pinctrl_usb3axhp_default &pinctrl_usb2axhp_default>;
++};
++
++&usb3bhp {
++	status = "okay";
++};
++
++&uphy2b {
++	status = "okay";
++};
++
++&vhubb1 {
++	status = "okay";
++};
++
++&vhubc {
++	status = "okay";
++};
++
++&ehci3 {
++	status = "okay";
++};
++
++&uhci1 {
++	status = "okay";
++};
++
++&wdt0 {
++	status = "okay";
++};
++
++&wdt1 {
++	status = "okay";
++};
++
++&otp {
++	status = "okay";
++};
+diff --git a/arch/arm64/boot/dts/aspeed/ast2700-dcscm_ast1700-evb-dual.dts b/arch/arm64/boot/dts/aspeed/ast2700-dcscm_ast1700-evb-dual.dts
+new file mode 100755
+index 000000000..848f348f4
+--- /dev/null
++++ b/arch/arm64/boot/dts/aspeed/ast2700-dcscm_ast1700-evb-dual.dts
+@@ -0,0 +1,218 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++
++/dts-v1/;
++
++#include "ast2700-dcscm_ast1700-evb.dts"
++#include "aspeed-ltpi1.dtsi"
++
++/ {
++	model = "AST2700-DCSCM_AST1700-EVB-DUAL";
++
++	ltpi1-iio-hwmon {
++		compatible = "iio-hwmon";
++		io-channels = <&ltpi1_adc0 0>, <&ltpi1_adc0 1>, <&ltpi1_adc0 2>, <&ltpi1_adc0 3>,
++				<&ltpi1_adc0 4>, <&ltpi1_adc0 5>, <&ltpi1_adc0 6>, <&ltpi1_adc0 7>,
++				<&ltpi1_adc1 0>, <&ltpi1_adc1 1>, <&ltpi1_adc1 2>, <&ltpi1_adc1 3>,
++				<&ltpi1_adc1 4>, <&ltpi1_adc1 5>, <&ltpi1_adc1 6>, <&ltpi1_adc1 7>;
++	};
++};
++
++&ltpi1_adc0 {
++	aspeed,int-vref-microvolt = <2500000>;
++	status = "okay";
++};
++
++&ltpi1_adc1 {
++	aspeed,int-vref-microvolt = <2500000>;
++	status = "okay";
++};
++
++&ltpi1 {
++	i2c-tunneling = <0x0>;
++	status = "okay";
++};
++
++&ltpi1_gpio {
++	status = "okay";
++};
++
++&ltpi1_i3c0 {
++	initial-role = "target";
++	pid = <0x000007ec 0x06010000>;
++	dcr = /bits/ 8 <0xcc>;
++	status = "okay";
++};
++
++&ltpi1_i3c1 {
++	initial-role = "primary";
++	status = "okay";
++};
++
++&ltpi1_i3c2 {
++	initial-role = "target";
++	pid = <0x000007ec 0x06012000>;
++	dcr = /bits/ 8 <0xcc>;
++	status = "okay";
++};
++
++&ltpi1_i3c3 {
++	initial-role = "primary";
++	status = "okay";
++};
++
++&ltpi1_i3c4 {
++	initial-role = "target";
++	pid = <0x000007ec 0x06014000>;
++	dcr = /bits/ 8 <0xcc>;
++	status = "okay";
++};
++
++&ltpi1_i3c5 {
++	initial-role = "primary";
++	status = "okay";
++};
++
++&ltpi1_i3c6 {
++	initial-role = "target";
++	pid = <0x000007ec 0x06016000>;
++	dcr = /bits/ 8 <0xcc>;
++	status = "okay";
++};
++
++&ltpi1_i3c7 {
++	initial-role = "primary";
++	status = "okay";
++};
++
++&ltpi1_i3c8 {
++	initial-role = "target";
++	pid = <0x000007ec 0x06018000>;
++	dcr = /bits/ 8 <0xcc>;
++	status = "okay";
++};
++
++&ltpi1_i3c9 {
++	initial-role = "primary";
++	status = "okay";
++};
++
++&ltpi1_i3c10 {
++	initial-role = "target";
++	pid = <0x000007ec 0x0601A000>;
++	dcr = /bits/ 8 <0xcc>;
++	status = "okay";
++};
++
++&ltpi1_i3c11 {
++	initial-role = "primary";
++	status = "okay";
++};
++
++&ltpi1_i3c12 {
++	initial-role = "target";
++	pid = <0x000007ec 0x0601C000>;
++	dcr = /bits/ 8 <0xcc>;
++	status = "okay";
++};
++
++&ltpi1_i3c13 {
++	initial-role = "primary";
++	status = "okay";
++};
++
++&ltpi1_i3c14 {
++	initial-role = "target";
++	pid = <0x000007ec 0x0601E000>;
++	dcr = /bits/ 8 <0xcc>;
++	status = "okay";
++};
++
++&ltpi1_i3c15 {
++	initial-role = "primary";
++	status = "okay";
++};
++
++&i2c6 {
++	status = "disabled";
++};
++
++&i2c7 {
++	status = "disabled";
++};
++
++// The following I2C buses require enabling according to the ast2700-dcscm.dts.
++// i2c8 / i2c9 / i2c10
++
++&i2c11 {
++	status = "disabled";
++};
++
++&ltpi1_i2c0 {
++	status = "okay";
++};
++
++&ltpi1_i2c1 {
++	status = "okay";
++};
++
++&ltpi1_i2c2 {
++	status = "okay";
++};
++
++&ltpi1_i2c3 {
++	status = "okay";
++};
++
++&ltpi1_i2c4 {
++	status = "okay";
++};
++
++&ltpi1_i2c5 {
++	status = "okay";
++};
++
++&ltpi1_i2c6 {
++	status = "okay";
++};
++
++&ltpi1_i2c7 {
++	status = "okay";
++};
++
++&ltpi1_i2c8 {
++	status = "okay";
++};
++
++&ltpi1_i2c9 {
++	status = "okay";
++};
++
++&ltpi1_i2c10 {
++	status = "okay";
++};
++
++&ltpi1_i2c11 {
++	status = "okay";
++};
++
++&ltpi1_i2c12 {
++	status = "okay";
++};
++
++&ltpi1_i2c13 {
++	status = "okay";
++};
++
++&ltpi1_i2c14 {
++	status = "okay";
++};
++
++&ltpi1_i2c15 {
++	status = "okay";
++};
++
++&uart8 {
++	/delete-property/ pinctrl-names;
++	/delete-property/ pinctrl-0;
++	status = "okay";
++};
+diff --git a/arch/arm64/boot/dts/aspeed/ast2700-dcscm_ast1700-evb.dts b/arch/arm64/boot/dts/aspeed/ast2700-dcscm_ast1700-evb.dts
+new file mode 100755
+index 000000000..680e8f274
+--- /dev/null
++++ b/arch/arm64/boot/dts/aspeed/ast2700-dcscm_ast1700-evb.dts
+@@ -0,0 +1,236 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++
++/dts-v1/;
++
++#include "ast2700-dcscm.dts"
++#include "aspeed-ltpi0.dtsi"
++
++/ {
++	model = "AST2700-DCSCM_AST1700-EVB";
++
++	ltpi0-iio-hwmon {
++		compatible = "iio-hwmon";
++		io-channels = <&ltpi0_adc0 0>, <&ltpi0_adc0 1>, <&ltpi0_adc0 2>, <&ltpi0_adc0 3>,
++				<&ltpi0_adc0 4>, <&ltpi0_adc0 5>, <&ltpi0_adc0 6>, <&ltpi0_adc0 7>,
++				<&ltpi0_adc1 0>, <&ltpi0_adc1 1>, <&ltpi0_adc1 2>, <&ltpi0_adc1 3>,
++				<&ltpi0_adc1 4>, <&ltpi0_adc1 5>, <&ltpi0_adc1 6>, <&ltpi0_adc1 7>;
++	};
++};
++
++&sgpios {
++	/delete-property/ gpio-line-names;
++};
++
++&ltpi0_gpio {
++	/delete-property/ gpio-line-names;
++	/delete-node/ gpio_17;
++	/delete-node/ gpio_19;
++	/delete-node/ gpio_25;
++	/delete-node/ gpio_53;
++	/delete-node/ gpio_61;
++	/delete-node/ gpio_63;
++};
++
++&ltpi0_adc0 {
++	aspeed,int-vref-microvolt = <2500000>;
++	status = "okay";
++};
++
++&ltpi0_adc1 {
++	aspeed,int-vref-microvolt = <2500000>;
++	status = "okay";
++};
++
++&ltpi0 {
++	i2c-tunneling = <0x0>;
++};
++
++&ltpi0_i3c0 {
++	initial-role = "target";
++	pid = <0x000007ec 0x06010000>;
++	dcr = /bits/ 8 <0xcc>;
++	status = "okay";
++};
++
++&ltpi0_i3c1 {
++	initial-role = "primary";
++	status = "okay";
++};
++
++&ltpi0_i3c2 {
++	initial-role = "target";
++	pid = <0x000007ec 0x06012000>;
++	dcr = /bits/ 8 <0xcc>;
++	status = "okay";
++};
++
++&ltpi0_i3c3 {
++	initial-role = "primary";
++	status = "okay";
++};
++
++&ltpi0_i3c4 {
++	initial-role = "target";
++	pid = <0x000007ec 0x06014000>;
++	dcr = /bits/ 8 <0xcc>;
++	status = "okay";
++};
++
++&ltpi0_i3c5 {
++	initial-role = "primary";
++	status = "okay";
++};
++
++&ltpi0_i3c6 {
++	initial-role = "target";
++	pid = <0x000007ec 0x06016000>;
++	dcr = /bits/ 8 <0xcc>;
++	status = "okay";
++};
++
++&ltpi0_i3c7 {
++	initial-role = "primary";
++	status = "okay";
++};
++
++&ltpi0_i3c8 {
++	initial-role = "target";
++	pid = <0x000007ec 0x06018000>;
++	dcr = /bits/ 8 <0xcc>;
++	status = "okay";
++};
++
++&ltpi0_i3c9 {
++	initial-role = "primary";
++	status = "okay";
++};
++
++&ltpi0_i3c10 {
++	initial-role = "target";
++	pid = <0x000007ec 0x0601A000>;
++	dcr = /bits/ 8 <0xcc>;
++	status = "okay";
++};
++
++&ltpi0_i3c11 {
++	initial-role = "primary";
++	status = "okay";
++};
++
++&ltpi0_i3c12 {
++	initial-role = "target";
++	pid = <0x000007ec 0x0601C000>;
++	dcr = /bits/ 8 <0xcc>;
++	status = "okay";
++};
++
++&ltpi0_i3c13 {
++	initial-role = "primary";
++	status = "okay";
++};
++
++&ltpi0_i3c14 {
++	initial-role = "target";
++	pid = <0x000007ec 0x0601E000>;
++	dcr = /bits/ 8 <0xcc>;
++	status = "okay";
++};
++
++&ltpi0_i3c15 {
++	initial-role = "primary";
++	status = "okay";
++};
++
++&i2c0 {
++	status = "disabled";
++};
++
++&i2c1 {
++	status = "disabled";
++};
++
++&i2c2 {
++	status = "disabled";
++};
++
++&i2c3 {
++	status = "disabled";
++};
++
++&i2c4 {
++	status = "disabled";
++};
++
++&i2c5 {
++	status = "disabled";
++};
++
++&ltpi0_i2c0 {
++	status = "okay";
++};
++
++&ltpi0_i2c1 {
++	status = "okay";
++};
++
++&ltpi0_i2c2 {
++	status = "okay";
++};
++
++&ltpi0_i2c3 {
++	status = "okay";
++};
++
++&ltpi0_i2c4 {
++	status = "okay";
++};
++
++&ltpi0_i2c5 {
++	status = "okay";
++};
++
++&ltpi0_i2c6 {
++	status = "okay";
++};
++
++&ltpi0_i2c7 {
++	status = "okay";
++};
++
++&ltpi0_i2c8 {
++	status = "okay";
++};
++
++&ltpi0_i2c9 {
++	status = "okay";
++};
++
++&ltpi0_i2c10 {
++	status = "okay";
++};
++
++&ltpi0_i2c11 {
++	status = "okay";
++};
++
++&ltpi0_i2c12 {
++	status = "okay";
++};
++
++&ltpi0_i2c13 {
++	status = "okay";
++};
++
++&ltpi0_i2c14 {
++	status = "okay";
++};
++
++&ltpi0_i2c15 {
++	status = "okay";
++};
++
++&uart3 {
++	/delete-property/ pinctrl-names;
++	/delete-property/ pinctrl-0;
++	status = "okay";
++};
 diff --git a/arch/arm64/boot/dts/aspeed/ast2700-evb.dts b/arch/arm64/boot/dts/aspeed/ast2700-evb.dts
-new file mode 100644
-index 000000000..bbe9a8c20
+new file mode 100755
+index 000000000..050f3d1e2
 --- /dev/null
 +++ b/arch/arm64/boot/dts/aspeed/ast2700-evb.dts
-@@ -0,0 +1,1151 @@
+@@ -0,0 +1,1188 @@
 +// SPDX-License-Identifier: GPL-2.0-or-later
 +
 +/dts-v1/;
@@ -4564,6 +8304,10 @@
 +	};
 +};
 +
++&edac {
++	status = "okay";
++};
++
 +&mctp0 {
 +	status = "okay";
 +	memory-region = <&mctp0_reserved>;
@@ -4613,6 +8357,22 @@
 +		&pinctrl_adc14_default &pinctrl_adc15_default>;
 +};
 +
++&pinctrl0 {
++	pinctrl_emmcclk_driving: emmcclk-driving {
++		pins = "AC14";
++		drive-strength = <2>;
++	};
++
++	pinctrl_emmccmd_driving: emmccmd-driving {
++		pins = "AE15";
++		drive-strength = <1>;
++	};
++	pinctrl_emmcdat_driving: emmcdat-driving {
++		pins = "AD14", "AE14", "AF14", "AB13";
++		drive-strength = <1>;
++	};
++};
++
 +&pinctrl1 {
 +	pinctrl_i3c0_3_hv_voltage: i3chv-voltage {
 +		pins = "U25";
@@ -4677,7 +8437,7 @@
 +	};
 +};
 +
-+&gpio0 {
++&gpio1 {
 +	pinctrl-0 = <&pinctrl_i3c0_3_hv_voltage &pinctrl_i3c12_15_hv_voltage
 +		     &pinctrl_i3c0_driving &pinctrl_i3c1_driving
 +		     &pinctrl_i3c2_driving &pinctrl_i3c3_driving
@@ -4933,6 +8693,9 @@
 +	pinctrl-0 = <&pinctrl_emmc_default
 +		     &pinctrl_emmcg8_default>;
 +#endif
++	pinctrl-names = "default";
++	pinctrl-0 = <&pinctrl_emmc_default &pinctrl_emmcclk_driving &pinctrl_emmccmd_driving &pinctrl_emmcdat_driving>;
++
 +	non-removable;
 +	max-frequency = <200000000>;
 +};
@@ -5025,12 +8788,6 @@
 +#endif
 +
 +&syscon1 {
-+	mac0-clk-delay = <0x18 0x16
-+			  0x10 0x10
-+			  0x10 0x10>;
-+	mac1-clk-delay = <0x18 0x17
-+			  0x10 0x10
-+			  0x10 0x10>;
 +	assigned-clocks = <&syscon1 SCU1_CLK_MACHCLK>,
 +			  <&syscon1 SCU1_CLK_RGMII>,
 +			  <&syscon1 SCU1_CLK_RMII>;
@@ -5047,8 +8804,18 @@
 +	perif-mcyc-enable;
 +	perif-mcyc-src-addr = <0x0 0x98000000>;
 +	perif-mcyc-size = <0x0 0x10000>;
++	perif-rtc-enable;
 +	oob-dma-mode;
 +	flash-dma-mode;
++#if 0	// if support eDAF MIX mode, open this if case to use sample code
++	flash-edaf-mode = <0x0>;
++	flash-edaf-tgt-addr = <&edaf0>;
++	flash-edaf-size = <0x0 0x4000000>;
++#endif
++};
++
++&rtc_over_espi0 {
++	status = "okay";
 +};
 +
 +&lpc0_kcs0 {
@@ -5223,8 +8990,8 @@
 +	status = "okay";
 +	memory-region = <&pcie0_mmbi0_memory>;
 +
-+	mmbi-bmc-int-value = /bits/ 8 <0x00>;
-+	mmbi-bmc-int-offset = <0x100000>;
++	bmc-int-value = /bits/ 8 <0x00>;
++	bmc-int-location = <0>;
 +};
 +#else
 +&pcie0 {
@@ -5292,8 +9059,8 @@
 +	status = "okay";
 +	memory-region = <&pcie1_mmbi4_memory>;
 +
-+	mmbi-bmc-int-value = /bits/ 8 <0x44>;
-+	mmbi-bmc-int-offset = <0x100400>;
++	bmc-int-value = /bits/ 8 <0x00>;
++	bmc-int-location = <0>;
 +};
 +#else
 +&pcie1 {
@@ -5320,7 +9087,7 @@
 +		regulator-name = "SDHCI0 Vcc";
 +		regulator-min-microvolt = <3300000>;
 +		regulator-max-microvolt = <3300000>;
-+		gpios = <&gpio0 ASPEED_GPIO(G, 6) GPIO_ACTIVE_HIGH>;
++		gpios = <&gpio1 ASPEED_GPIO(G, 6) GPIO_ACTIVE_HIGH>;
 +		enable-active-high;
 +	};
 +
@@ -5329,7 +9096,7 @@
 +		regulator-name = "SDHCI0 VccQ";
 +		regulator-min-microvolt = <1800000>;
 +		regulator-max-microvolt = <3300000>;
-+		gpios = <&gpio0 ASPEED_GPIO(G, 7) GPIO_ACTIVE_HIGH>;
++		gpios = <&gpio1 ASPEED_GPIO(G, 7) GPIO_ACTIVE_HIGH>;
 +		gpios-states = <1>;
 +		states = <3300000 1>,
 +			 <1800000 0>;
@@ -5483,9 +9250,19 @@
 +&otp {
 +	status = "okay";
 +};
++
++#if 0
++&soc0 {
++	mbox-ssp-0 {
++		compatible = "aspeed,aspeed-mbox";
++		reg = <0x4 0x31480000 0x0 0x200000>, <0x0 0x10001000 0x0 0x1000>;
++		mboxes = <&mbox0 0>;
++	};
++};
++#endif
 diff --git a/arch/arm64/boot/dts/aspeed/ast2700-reserved-mem.dtsi b/arch/arm64/boot/dts/aspeed/ast2700-reserved-mem.dtsi
-new file mode 100644
-index 000000000..b6d789fd2
+new file mode 100755
+index 000000000..6a99f094f
 --- /dev/null
 +++ b/arch/arm64/boot/dts/aspeed/ast2700-reserved-mem.dtsi
 @@ -0,0 +1,102 @@
@@ -5522,7 +9299,7 @@
 +	no-map;
 +};
 +
-+espi1_mmbi_memory: espi1-mmbi-memory@428000000 {
++edaf0: safs-mix-mode@428000000 {
 +	reg = <0x4 0x28000000 0x0 0x4000000>;
 +	no-map;
 +};
@@ -5552,14 +9329,14 @@
 +	no-map;
 +};
 +
-+uhci0_reserved: uhci0-reserved@431ba8000 {
-+	reg = <0x4 0x31ba8000 0x0 0x4000>;
++uhci0_reserved: uhci0-reserved@431b30000 {
++	reg = <0x4 0x31b30000 0x0 0x40000>;
 +	compatible = "shared-dma-pool";
 +	no-map;
 +};
 +
-+uhci1_reserved: uhci1-reserved@431bac000 {
-+	reg = <0x4 0x31bac000 0x0 0x4000>;
++uhci1_reserved: uhci1-reserved@431b70000 {
++	reg = <0x4 0x31b70000 0x0 0x40000>;
 +	compatible = "shared-dma-pool";
 +	no-map;
 +};
@@ -5592,11 +9369,11 @@
 +	no-map;
 +};
 diff --git a/arch/arm64/configs/aspeed_g7_defconfig b/arch/arm64/configs/aspeed_g7_defconfig
-new file mode 100644
-index 000000000..cf588bc94
+new file mode 100755
+index 000000000..92e1447f1
 --- /dev/null
 +++ b/arch/arm64/configs/aspeed_g7_defconfig
-@@ -0,0 +1,419 @@
+@@ -0,0 +1,429 @@
 +CONFIG_SYSVIPC=y
 +CONFIG_POSIX_MQUEUE=y
 +CONFIG_AUDIT=y
@@ -5683,6 +9460,7 @@
 +CONFIG_BLK_DEV_NBD=y
 +CONFIG_BLK_DEV_RAM=y
 +CONFIG_BLK_DEV_RAM_SIZE=32768
++CONFIG_BLK_DEV_NVME=y
 +CONFIG_SMPRO_ERRMON=y
 +CONFIG_SMPRO_MISC=y
 +CONFIG_SRAM=y
@@ -5694,10 +9472,10 @@
 +# CONFIG_NET_VENDOR_ALACRITECH is not set
 +# CONFIG_NET_VENDOR_AMAZON is not set
 +# CONFIG_NET_VENDOR_AMD is not set
-+# CONFIG_NET_VENDOR_AQUANTIA is not set
++CONFIG_AQTION=y
 +# CONFIG_NET_VENDOR_ARC is not set
 +# CONFIG_NET_VENDOR_ASIX is not set
-+# CONFIG_NET_VENDOR_BROADCOM is not set
++CONFIG_TIGON3=y
 +# CONFIG_NET_VENDOR_CADENCE is not set
 +# CONFIG_NET_VENDOR_CAVIUM is not set
 +# CONFIG_NET_VENDOR_CORTINA is not set
@@ -5709,7 +9487,11 @@
 +# 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_E100=y
++CONFIG_E1000=y
++CONFIG_E1000E=y
++CONFIG_IGB=y
++CONFIG_IXGBE=y
 +# CONFIG_NET_VENDOR_ADI is not set
 +# CONFIG_NET_VENDOR_LITEX is not set
 +# CONFIG_NET_VENDOR_MARVELL is not set
@@ -5723,6 +9505,7 @@
 +# CONFIG_NET_VENDOR_NETRONOME is not set
 +# CONFIG_NET_VENDOR_PENSANDO is not set
 +# CONFIG_NET_VENDOR_QUALCOMM is not set
++CONFIG_R8169=y
 +# CONFIG_NET_VENDOR_RENESAS is not set
 +# CONFIG_NET_VENDOR_ROCKER is not set
 +# CONFIG_NET_VENDOR_SAMSUNG is not set
@@ -5746,6 +9529,7 @@
 +CONFIG_MCTP_SERIAL=y
 +CONFIG_MCTP_TRANSPORT_I2C=y
 +CONFIG_MCTP_TRANSPORT_I3C=y
++CONFIG_MCTP_TRANSPORT_PCIE_VDM=n
 +CONFIG_USB_USBNET=y
 +# CONFIG_USB_NET_AX8817X is not set
 +# CONFIG_USB_NET_AX88179_178A is not set
@@ -5904,6 +9688,7 @@
 +CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
 +CONFIG_EDAC=y
++CONFIG_EDAC_AST2700=y
 +CONFIG_RTC_CLASS=y
 +CONFIG_RTC_DRV_DS1307=y
 +CONFIG_RTC_DRV_PCF8523=y
@@ -5919,9 +9704,11 @@
 +CONFIG_ASPEED_MCTP=y
 +CONFIG_ASPEED_XDMA=y
 +CONFIG_AST2700_ESPI=y
++CONFIG_AST2700_RTC_OVER_ESPI=y
 +CONFIG_ASPEED_LPC_PCC=y
 +CONFIG_AST2700_OTP=y
 +CONFIG_ASPEED_PCIE_MMBI=y
++CONFIG_ASPEED_MBOX=y
 +CONFIG_IIO=y
 +CONFIG_ASPEED_ADC=y
 +CONFIG_MAX1363=y
@@ -6016,6 +9803,419 @@
 +# CONFIG_RUNTIME_TESTING_MENU is not set
 +CONFIG_MAILBOX=y
 +CONFIG_AST2700_MBOX=y
+diff --git a/arch/arm64/configs/aspeed_g7_slt_defconfig b/arch/arm64/configs/aspeed_g7_slt_defconfig
+new file mode 100755
+index 000000000..6eca77692
+--- /dev/null
++++ b/arch/arm64/configs/aspeed_g7_slt_defconfig
+@@ -0,0 +1,407 @@
++CONFIG_SYSVIPC=y
++CONFIG_POSIX_MQUEUE=y
++CONFIG_AUDIT=y
++CONFIG_NO_HZ_IDLE=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_BPF_SYSCALL=y
++CONFIG_PREEMPT=y
++CONFIG_IRQ_TIME_ACCOUNTING=y
++CONFIG_BSD_PROCESS_ACCT=y
++CONFIG_BSD_PROCESS_ACCT_V3=y
++CONFIG_TASKSTATS=y
++CONFIG_TASK_XACCT=y
++CONFIG_TASK_IO_ACCOUNTING=y
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_LOG_BUF_SHIFT=21
++CONFIG_CGROUPS=y
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE="../rootfs"
++CONFIG_EXPERT=y
++CONFIG_PERF_EVENTS=y
++CONFIG_ARCH_ASPEED=y
++CONFIG_SCHED_SMT=y
++CONFIG_NR_CPUS=4
++# CONFIG_ARM64_HW_AFDBM is not set
++# CONFIG_ARM64_PAN is not set
++# CONFIG_ARM64_RAS_EXTN is not set
++# CONFIG_ARM64_CNP is not set
++# CONFIG_ARM64_PTR_AUTH is not set
++# CONFIG_ARM64_AMU_EXTN is not set
++# CONFIG_ARM64_TLB_RANGE is not set
++# CONFIG_ARM64_BTI is not set
++# CONFIG_ARM64_E0PD is not set
++# CONFIG_EFI is not set
++CONFIG_MODULES=y
++CONFIG_MODULE_FORCE_LOAD=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODULE_FORCE_UNLOAD=y
++# CONFIG_SWAP is not set
++# CONFIG_ZONE_DMA is not set
++# CONFIG_ZONE_DMA32 is not set
++CONFIG_NET=y
++CONFIG_PACKET=y
++CONFIG_PACKET_DIAG=y
++CONFIG_UNIX=y
++CONFIG_UNIX_DIAG=y
++CONFIG_INET=y
++# CONFIG_INET_DIAG is not set
++CONFIG_IPV6_ROUTER_PREF=y
++CONFIG_IPV6_ROUTE_INFO=y
++CONFIG_IPV6_OPTIMISTIC_DAD=y
++# CONFIG_IPV6_SIT is not set
++CONFIG_IPV6_MULTIPLE_TABLES=y
++CONFIG_NETFILTER=y
++# CONFIG_NETFILTER_ADVANCED is not set
++CONFIG_BRIDGE=y
++CONFIG_VLAN_8021Q=y
++CONFIG_NET_NCSI=y
++CONFIG_CAN=y
++CONFIG_MCTP=y
++# CONFIG_WIRELESS is not set
++CONFIG_PCI=y
++CONFIG_PCIEPORTBUS=y
++CONFIG_PCI_DEBUG=y
++CONFIG_PCI_STUB=y
++CONFIG_PCI_IOV=y
++CONFIG_PCI_PRI=y
++CONFIG_PCIE_BUS_SAFE=y
++CONFIG_PCIE_ASPEED=y
++CONFIG_DEVTMPFS=y
++CONFIG_DEVTMPFS_MOUNT=y
++CONFIG_DEVTMPFS_SAFE=y
++# CONFIG_PREVENT_FIRMWARE_BUILD is not set
++CONFIG_ASPEED_LTPI=y
++# CONFIG_ARM_SMCCC_SOC_ID is not set
++CONFIG_MTD=y
++CONFIG_MTD_BLOCK=y
++CONFIG_MTD_PARTITIONED_MASTER=y
++CONFIG_MTD_SPI_NOR=y
++# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
++CONFIG_MTD_UBI=y
++CONFIG_MTD_UBI_FASTMAP=y
++CONFIG_MTD_UBI_BLOCK=y
++CONFIG_BLK_DEV_LOOP=y
++CONFIG_BLK_DEV_NBD=y
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_SIZE=32768
++CONFIG_SMPRO_ERRMON=y
++CONFIG_SMPRO_MISC=y
++CONFIG_SRAM=y
++CONFIG_EEPROM_AT24=y
++CONFIG_EEPROM_AT25=y
++CONFIG_SCSI=y
++CONFIG_BLK_DEV_SD=y
++CONFIG_NETDEVICES=y
++# CONFIG_NET_VENDOR_ALACRITECH is not set
++# CONFIG_NET_VENDOR_AMAZON is not set
++# CONFIG_NET_VENDOR_AMD is not set
++# CONFIG_NET_VENDOR_AQUANTIA is not set
++# CONFIG_NET_VENDOR_ARC is not set
++# CONFIG_NET_VENDOR_ASIX 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_CORTINA is not set
++# CONFIG_NET_VENDOR_DAVICOM is not set
++# CONFIG_NET_VENDOR_ENGLEDER is not set
++# CONFIG_NET_VENDOR_EZCHIP is not set
++CONFIG_FTGMAC100=y
++# CONFIG_NET_VENDOR_FUNGIBLE 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_ADI is not set
++# CONFIG_NET_VENDOR_LITEX is not set
++# CONFIG_NET_VENDOR_MARVELL is not set
++# CONFIG_NET_VENDOR_MELLANOX is not set
++# CONFIG_NET_VENDOR_MICREL is not set
++# CONFIG_NET_VENDOR_MICROCHIP is not set
++# CONFIG_NET_VENDOR_MICROSEMI is not set
++# CONFIG_NET_VENDOR_MICROSOFT is not set
++# 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_NET_VENDOR_SMSC is not set
++# CONFIG_NET_VENDOR_SOCIONEXT is not set
++# CONFIG_NET_VENDOR_STMICRO is not set
++# CONFIG_NET_VENDOR_SYNOPSYS is not set
++# CONFIG_NET_VENDOR_VERTEXCOM is not set
++# CONFIG_NET_VENDOR_VIA is not set
++# CONFIG_NET_VENDOR_WANGXUN is not set
++# CONFIG_NET_VENDOR_WIZNET is not set
++# CONFIG_NET_VENDOR_XILINX is not set
++CONFIG_AIROHA_AN8801_PHY=y
++CONFIG_BROADCOM_PHY=y
++CONFIG_REALTEK_PHY=y
++CONFIG_DP83867_PHY=y
++CONFIG_CAN_ASPEED=y
++CONFIG_CAN_DEBUG_DEVICES=y
++CONFIG_MCTP_SERIAL=y
++CONFIG_MCTP_TRANSPORT_I2C=y
++CONFIG_MCTP_TRANSPORT_I3C=y
++# CONFIG_USB_NET_DRIVERS is not set
++# CONFIG_WLAN is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_KEYBOARD_ATKBD is not set
++CONFIG_KEYBOARD_GPIO=y
++CONFIG_KEYBOARD_GPIO_POLLED=y
++# CONFIG_INPUT_MOUSE is not set
++CONFIG_INPUT_MISC=y
++CONFIG_INPUT_IBM_PANEL=y
++CONFIG_SERIO_RAW=y
++# CONFIG_VT is not set
++# CONFIG_LEGACY_PTYS is not set
++CONFIG_SERIAL_8250=y
++# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=21
++CONFIG_SERIAL_8250_RUNTIME_UARTS=21
++CONFIG_SERIAL_8250_EXTENDED=y
++CONFIG_SERIAL_8250_ASPEED=y
++CONFIG_SERIAL_8250_ASPEED_VUART=y
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++CONFIG_SERIAL_8250_DW=y
++CONFIG_SERIAL_OF_PLATFORM=y
++CONFIG_IPMI_HANDLER=y
++CONFIG_IPMI_DEVICE_INTERFACE=y
++CONFIG_IPMI_SI=m
++CONFIG_IPMI_SSIF=y
++CONFIG_IPMI_IPMB=y
++CONFIG_ASPEED_KCS_IPMI_BMC=y
++CONFIG_IPMI_KCS_BMC_CDEV_IPMI=y
++CONFIG_ASPEED_BT_IPMI_BMC=y
++CONFIG_SSIF_IPMI_BMC=y
++CONFIG_IPMB_DEVICE_INTERFACE=y
++CONFIG_HW_RANDOM=y
++# CONFIG_HW_RANDOM_OPTEE is not set
++# CONFIG_HW_RANDOM_ARM_SMCCC_TRNG is not set
++# CONFIG_HW_RANDOM_CN10K is not set
++CONFIG_HW_RANDOM_DWC=y
++CONFIG_TCG_TPM=y
++CONFIG_TCG_TIS_SPI=y
++# CONFIG_I2C_COMPAT is not set
++CONFIG_I2C_CHARDEV=y
++CONFIG_I2C_AST2600=y
++CONFIG_I2C_SLAVE=y
++CONFIG_I2C_SLAVE_EEPROM=y
++CONFIG_I3C=y
++CONFIG_I3CDEV=y
++CONFIG_I3C_MCTP=y
++CONFIG_I3C_TARGET_MCTP=y
++CONFIG_MIPI_I3C_HCI=y
++CONFIG_SPI=y
++CONFIG_SPI_ASPEED_SMC=y
++CONFIG_SPI_ASPEED_TXRX=y
++CONFIG_PINCTRL=y
++CONFIG_PINCTRL_ASPEED_G7=y
++CONFIG_GPIOLIB=y
++CONFIG_GPIO_SYSFS=y
++CONFIG_GPIO_ASPEED=y
++CONFIG_GPIO_ASPEED_SGPIO=y
++CONFIG_GPIO_PCA953X=y
++CONFIG_GPIO_PCA953X_IRQ=y
++CONFIG_W1=y
++CONFIG_W1_MASTER_GPIO=y
++CONFIG_W1_SLAVE_THERM=y
++CONFIG_SENSORS_SMPRO=y
++CONFIG_SENSORS_ADT7475=y
++CONFIG_SENSORS_ASPEED=y
++CONFIG_SENSORS_ASPEED_G6=y
++CONFIG_SENSORS_ASPEED_CHASSIS=y
++CONFIG_SENSORS_IIO_HWMON=y
++CONFIG_SENSORS_LM75=y
++CONFIG_SENSORS_PECI_CPUTEMP=y
++CONFIG_SENSORS_PECI_DIMMTEMP=y
++CONFIG_PMBUS=y
++CONFIG_SENSORS_ADM1275=y
++CONFIG_SENSORS_IBM_CFFPS=y
++CONFIG_SENSORS_IR35221=y
++CONFIG_SENSORS_IR38064=y
++CONFIG_SENSORS_ISL68137=y
++CONFIG_SENSORS_LM25066=y
++CONFIG_SENSORS_MAX31785=y
++CONFIG_SENSORS_MP5023=y
++CONFIG_SENSORS_UCD9000=y
++CONFIG_SENSORS_UCD9200=y
++CONFIG_SENSORS_PWM_FAN=y
++CONFIG_SENSORS_SBTSI=y
++CONFIG_SENSORS_TMP421=y
++CONFIG_SENSORS_W83773G=y
++CONFIG_WATCHDOG=y
++CONFIG_WATCHDOG_SYSFS=y
++CONFIG_ASPEED_WATCHDOG=y
++CONFIG_MFD_SMPRO=y
++CONFIG_REGULATOR=y
++CONFIG_REGULATOR_FIXED_VOLTAGE=y
++CONFIG_REGULATOR_GPIO=y
++CONFIG_MEDIA_SUPPORT=y
++CONFIG_MEDIA_SUPPORT_FILTER=y
++CONFIG_MEDIA_PLATFORM_SUPPORT=y
++CONFIG_V4L_PLATFORM_DRIVERS=y
++CONFIG_VIDEO_ASPEED=y
++CONFIG_DRM=y
++CONFIG_DRM_AST=y
++CONFIG_DRM_ASPEED_GFX=y
++CONFIG_USB=y
++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
++CONFIG_USB_DYNAMIC_MINORS=y
++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_UHCI_HCD=y
++CONFIG_USB_ACM=y
++CONFIG_USB_STORAGE=y
++CONFIG_USB_UAS=y
++CONFIG_USB_DWC3=y
++CONFIG_USB_DWC3_HOST=y
++# CONFIG_USB_DWC3_HAPS is not set
++# CONFIG_USB_DWC3_OF_SIMPLE is not set
++CONFIG_USB_SERIAL=y
++CONFIG_USB_SERIAL_PL2303=y
++CONFIG_USB_GADGET=y
++CONFIG_USB_ASPEED_VHUB=y
++CONFIG_USB_CONFIGFS=y
++CONFIG_USB_CONFIGFS_ACM=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_MASS_STORAGE=y
++CONFIG_USB_CONFIGFS_F_HID=y
++CONFIG_MMC=y
++CONFIG_MMC_SDHCI=y
++CONFIG_MMC_SDHCI_PLTFM=y
++CONFIG_MMC_SDHCI_OF_ASPEED=y
++CONFIG_SCSI_UFSHCD=y
++CONFIG_SCSI_UFSHCD_PLATFORM=y
++CONFIG_SCSI_UFS_ASPEED=y
++CONFIG_NEW_LEDS=y
++CONFIG_LEDS_CLASS=y
++CONFIG_LEDS_CLASS_FLASH=y
++CONFIG_LEDS_GPIO=y
++CONFIG_LEDS_PCA955X=y
++CONFIG_LEDS_PCA955X_GPIO=y
++CONFIG_LEDS_TRIGGERS=y
++CONFIG_LEDS_TRIGGER_TIMER=y
++CONFIG_LEDS_TRIGGER_HEARTBEAT=y
++CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
++CONFIG_EDAC=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_DRV_DS1307=y
++CONFIG_RTC_DRV_PCF8523=y
++CONFIG_RTC_DRV_S35390A=y
++CONFIG_RTC_DRV_RV8803=y
++CONFIG_RTC_DRV_ASPEED=y
++# CONFIG_VIRTIO_MENU is not set
++CONFIG_COMMON_CLK_AST2700=y
++CONFIG_COMMON_CLK_AST1700=y
++# CONFIG_IOMMU_SUPPORT is not set
++CONFIG_ASPEED_BMC_DEV=y
++CONFIG_ASPEED_HOST_BMC_DEV=y
++CONFIG_ASPEED_MCTP=y
++CONFIG_ASPEED_XDMA=y
++CONFIG_AST2700_ESPI=y
++CONFIG_AST2700_OTP=y
++CONFIG_IIO=y
++CONFIG_ASPEED_ADC=y
++CONFIG_MAX1363=y
++CONFIG_SI7020=y
++CONFIG_BMP280=y
++CONFIG_DPS310=y
++CONFIG_PWM=y
++CONFIG_RESET_ASPEED=y
++CONFIG_PHY_ASPEED_SGMII=y
++CONFIG_PHY_ASPEED_USB3=y
++CONFIG_RAS=y
++CONFIG_FSI=y
++CONFIG_FSI_MASTER_GPIO=y
++CONFIG_FSI_MASTER_HUB=y
++CONFIG_FSI_MASTER_ASPEED=y
++CONFIG_FSI_SCOM=y
++CONFIG_FSI_SBEFIFO=y
++CONFIG_FSI_OCC=y
++CONFIG_TEE=y
++CONFIG_OPTEE=y
++CONFIG_PECI=y
++CONFIG_PECI_ASPEED=y
++CONFIG_JTAG=y
++CONFIG_JTAG_ASPEED=y
++CONFIG_EXT4_FS=y
++CONFIG_FS_ENCRYPTION=y
++CONFIG_FANOTIFY=y
++CONFIG_OVERLAY_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_EXFAT_FS=y
++CONFIG_TMPFS=y
++CONFIG_JFFS2_FS=y
++# CONFIG_JFFS2_FS_WRITEBUFFER is not set
++CONFIG_JFFS2_SUMMARY=y
++CONFIG_JFFS2_FS_XATTR=y
++CONFIG_UBIFS_FS=y
++CONFIG_SQUASHFS=y
++CONFIG_SQUASHFS_XZ=y
++CONFIG_SQUASHFS_ZSTD=y
++CONFIG_PSTORE=y
++CONFIG_PSTORE_CONSOLE=y
++CONFIG_PSTORE_PMSG=y
++CONFIG_PSTORE_RAM=y
++# CONFIG_NETWORK_FILESYSTEMS is not set
++CONFIG_NLS_CODEPAGE_437=y
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_SECURITYFS is not set
++CONFIG_HARDENED_USERCOPY=y
++CONFIG_FORTIFY_SOURCE=y
++CONFIG_INIT_STACK_NONE=y
++CONFIG_CRYPTO_USER=y
++# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
++CONFIG_CRYPTO_TEST=m
++CONFIG_CRYPTO_USER_API_HASH=y
++CONFIG_CRYPTO_USER_API_SKCIPHER=y
++CONFIG_CRYPTO_USER_API_AEAD=y
++CONFIG_CRYPTO_USER_API_AKCIPHER=y
++CONFIG_CRYPTO_SHA1_ARM64_CE=y
++CONFIG_CRYPTO_SHA2_ARM64_CE=y
++CONFIG_CRYPTO_SHA512_ARM64=y
++CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
++CONFIG_CRYPTO_DEV_ASPEED=y
++CONFIG_CRYPTO_DEV_ASPEED_HACE=y
++CONFIG_CRYPTO_DEV_ASPEED_HACE_HASH=y
++CONFIG_CRYPTO_DEV_ASPEED_HACE_CRYPTO=y
++CONFIG_CRYPTO_DEV_ASPEED_RSSS=y
++CONFIG_CRYPTO_DEV_ASPEED_ECDSA=y
++# 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_PRINTK_TIME=y
++CONFIG_DYNAMIC_DEBUG=y
++CONFIG_DEBUG_INFO_DWARF4=y
++CONFIG_DEBUG_INFO_REDUCED=y
++CONFIG_GDB_SCRIPTS=y
++CONFIG_STRIP_ASM_SYMS=y
++CONFIG_DEBUG_FS=y
++CONFIG_DEBUG_WX=y
++CONFIG_SCHED_STACK_END_CHECK=y
++CONFIG_PANIC_ON_OOPS=y
++CONFIG_PANIC_TIMEOUT=-1
++CONFIG_SOFTLOCKUP_DETECTOR=y
++CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
++CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
++CONFIG_WQ_WATCHDOG=y
++# CONFIG_SCHED_DEBUG is not set
++CONFIG_DEBUG_LIST=y
++CONFIG_FUNCTION_TRACER=y
++# CONFIG_STRICT_DEVMEM is not set
++# CONFIG_RUNTIME_TESTING_MENU is not set
++CONFIG_CRYPTO_LRW=y
 -- 
 2.34.1
 
diff --git a/recipes-kernel/linux/files/0002-Add-dt-bindings-head-file-for-ast2700.patch b/recipes-kernel/linux/files/0002-Add-dt-bindings-head-file-for-ast2700.patch
index 2a07c38..3713c55 100644
--- a/recipes-kernel/linux/files/0002-Add-dt-bindings-head-file-for-ast2700.patch
+++ b/recipes-kernel/linux/files/0002-Add-dt-bindings-head-file-for-ast2700.patch
@@ -1,7 +1,7 @@
-From ab3c3a32b2ebf58beed4488c2ea97fdaabacb943 Mon Sep 17 00:00:00 2001
-From: "yung-sheng.huang" <yung-sheng.huang@fii-na.corp-partner.google.com>
-Date: Tue, 15 Apr 2025 11:12:35 +0800
-Subject: [PATCH 02/26] Add dt-bindings head file for ast2700
+From d00501f1ae8899234ffc1d43734eceeb40330643 Mon Sep 17 00:00:00 2001
+From: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+Date: Wed, 16 Jul 2025 17:21:42 +0800
+Subject: [PATCH] Add dt-bindings head file for ast2700
 
 1.clock
 2.dma
@@ -10,16 +10,17 @@
 5.reset
 6.watchdog
 
-This is base on aspeed SDK 9.06.
+This is base on aspeed SDK 9.07.
 
 Source:
 AspeedTech-BMC github:
 https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/
-(cherry picked from commit v00.06.06)
+(cherry picked from commit v00.06.07)
 
-Signed-off-by: yung-sheng.huang <yung-sheng.huang@fii-na.corp-partner.google.com>
+Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
 ---
  .../dt-bindings/clock/aspeed,ast1700-clk.h    |  97 +++++++++++
+ .../dt-bindings/clock/aspeed,ast1800-clk.h    | 104 +++++++++++
  .../dt-bindings/clock/aspeed,ast2700-scu.h    | 164 ++++++++++++++++++
  include/dt-bindings/clock/aspeed-clock.h      |   1 +
  include/dt-bindings/clock/ast2600-clock.h     |  20 ++-
@@ -29,15 +30,18 @@
  .../interrupt-controller/aspeed-e2m-ic.h      |  21 +++
  .../interrupt-controller/aspeed-scu-ic.h      |  14 ++
  .../dt-bindings/reset/aspeed,ast1700-reset.h  |  69 ++++++++
+ .../dt-bindings/reset/aspeed,ast1800-reset.h  |  61 +++++++
  .../dt-bindings/reset/aspeed,ast2700-scu.h    | 124 +++++++++++++
  include/dt-bindings/watchdog/aspeed-wdt.h     |  92 ++++++++++
- 12 files changed, 656 insertions(+), 5 deletions(-)
+ 14 files changed, 821 insertions(+), 5 deletions(-)
  create mode 100644 include/dt-bindings/clock/aspeed,ast1700-clk.h
+ create mode 100755 include/dt-bindings/clock/aspeed,ast1800-clk.h
  create mode 100644 include/dt-bindings/clock/aspeed,ast2700-scu.h
  create mode 100644 include/dt-bindings/dma/ast2600-udma.h
  create mode 100644 include/dt-bindings/i3c/i3c.h
  create mode 100644 include/dt-bindings/interrupt-controller/aspeed-e2m-ic.h
  create mode 100644 include/dt-bindings/reset/aspeed,ast1700-reset.h
+ create mode 100755 include/dt-bindings/reset/aspeed,ast1800-reset.h
  create mode 100644 include/dt-bindings/reset/aspeed,ast2700-scu.h
  create mode 100644 include/dt-bindings/watchdog/aspeed-wdt.h
 
@@ -144,6 +148,116 @@
 +
 +#define AST1700_NUM_CLKS		(AST1700_CLK_MACHCLK + 1)
 +#endif
+diff --git a/include/dt-bindings/clock/aspeed,ast1800-clk.h b/include/dt-bindings/clock/aspeed,ast1800-clk.h
+new file mode 100755
+index 000000000..b8e427696
+--- /dev/null
++++ b/include/dt-bindings/clock/aspeed,ast1800-clk.h
+@@ -0,0 +1,104 @@
++/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
++/*
++ * Device Tree binding constants for AST2700 clock controller.
++ *
++ * Copyright (c) 2023 Aspeed Technology Inc.
++ */
++
++#ifndef __DT_BINDINGS_CLOCK_AST1800_H
++#define __DT_BINDINGS_CLOCK_AST1800_H
++
++#define AST1800_CLK_GATE_MCU         (0)
++#define AST1800_CLK_GATE_CONFIG      (1)
++#define AST1800_CLK_GATE_MEM         (2)
++#define AST1800_CLK_GATE_LTPI        (3)
++#define AST1800_CLK_GATE_SPI_SLAVE   (4)
++#define AST1800_CLK_GATE_I2C_SLAVE   (5)
++#define AST1800_CLK_GATE_SRAM        (6)
++#define AST1800_CLK_GATE_UART_DBG    (7)
++/* reserved bit 8 ~ 31 */
++#define AST1800_CLK_GATE_I3C0        (32)
++#define AST1800_CLK_GATE_I3C1        (33)
++#define AST1800_CLK_GATE_I3C2        (34)
++#define AST1800_CLK_GATE_I3C3        (35)
++#define AST1800_CLK_GATE_I3C4        (36)
++#define AST1800_CLK_GATE_I3C5        (37)
++#define AST1800_CLK_GATE_I3C6        (38)
++#define AST1800_CLK_GATE_I3C7        (39)
++#define AST1800_CLK_GATE_I3C8        (40)
++#define AST1800_CLK_GATE_I3C9        (41)
++#define AST1800_CLK_GATE_I3C10       (42)
++#define AST1800_CLK_GATE_I3C11       (43)
++#define AST1800_CLK_GATE_I3C12       (44)
++#define AST1800_CLK_GATE_I3C13       (45)
++#define AST1800_CLK_GATE_I3C14       (46)
++#define AST1800_CLK_GATE_I3C15       (47)
++/* reserved bit 16 ~ 31 */
++#define AST1800_CLK_GATE_EFPGA0      (64)
++#define AST1800_CLK_GATE_EFPGA1      (65)
++#define AST1800_CLK_GATE_EFPGA2      (66)
++#define AST1800_CLK_GATE_EFPGA3      (67)
++#define AST1800_CLK_GATE_EFPGA4      (68)
++#define AST1800_CLK_GATE_EFPGA5      (69)
++#define AST1800_CLK_GATE_EFPGA6      (70)
++#define AST1800_CLK_GATE_EFPGA7      (71)
++#define AST1800_CLK_GATE_EFPGA_DBG   (72)
++
++#define AST1800_CLKIN                        (AST1800_CLK_GATE_EFPGA_DBG + 0)
++#define AST1800_CLK_HPLL                     (AST1800_CLK_GATE_EFPGA_DBG + 1)
++#define AST1800_CLK_HPLL_DIV2                (AST1800_CLK_GATE_EFPGA_DBG + 2)
++#define AST1800_CLK_HPLL_DIV4                (AST1800_CLK_GATE_EFPGA_DBG + 3)
++#define AST1800_CLK_HPLL_DIV5                (AST1800_CLK_GATE_EFPGA_DBG + 4)
++#define AST1800_CLK_HPLL_DIV8                (AST1800_CLK_GATE_EFPGA_DBG + 5)
++#define AST1800_CLK_HPLL_DIV10               (AST1800_CLK_GATE_EFPGA_DBG + 6)
++#define AST1800_CLK_HPLL_DIV20               (AST1800_CLK_GATE_EFPGA_DBG + 7)
++#define AST1800_CLK_HPLL_DIV25               (AST1800_CLK_GATE_EFPGA_DBG + 8)
++#define AST1800_CLK_HPLL_DIV50               (AST1800_CLK_GATE_EFPGA_DBG + 9)
++#define AST1800_CLK_HPLL_DIV100              (AST1800_CLK_GATE_EFPGA_DBG + 10)
++#define AST1800_CLK_HPLL_DIV200              (AST1800_CLK_GATE_EFPGA_DBG + 11)
++#define AST1800_CLK_HPLL_DIV1000             (AST1800_CLK_GATE_EFPGA_DBG + 12)
++#define AST1800_CLK_HPLL_EFPGA0              (AST1800_CLK_GATE_EFPGA_DBG + 13)
++#define AST1800_CLK_HPLL_EFPGA1              (AST1800_CLK_GATE_EFPGA_DBG + 14)
++#define AST1800_CLK_HPLL_EFPGA2              (AST1800_CLK_GATE_EFPGA_DBG + 15)
++#define AST1800_CLK_HPLL_EFPGA3              (AST1800_CLK_GATE_EFPGA_DBG + 16)
++#define AST1800_CLK_HPLL_EFPGA4              (AST1800_CLK_GATE_EFPGA_DBG + 17)
++#define AST1800_CLK_HPLL_EFPGA5              (AST1800_CLK_GATE_EFPGA_DBG + 18)
++#define AST1800_CLK_HPLL_EFPGA6              (AST1800_CLK_GATE_EFPGA_DBG + 19)
++#define AST1800_CLK_HPLL_EFPGA7              (AST1800_CLK_GATE_EFPGA_DBG + 20)
++#define AST1800_CLK_EPLL                     (AST1800_CLK_GATE_EFPGA_DBG + 21)
++#define AST1800_CLK_EPLL_DIV2                (AST1800_CLK_GATE_EFPGA_DBG + 22)
++#define AST1800_CLK_EPLL_DIV4                (AST1800_CLK_GATE_EFPGA_DBG + 23)
++#define AST1800_CLK_EPLL_DIV8                (AST1800_CLK_GATE_EFPGA_DBG + 24)
++#define AST1800_CLK_EPLL_DIV12               (AST1800_CLK_GATE_EFPGA_DBG + 25)
++#define AST1800_CLK_EPLL_EFPGA0              (AST1800_CLK_GATE_EFPGA_DBG + 26)
++#define AST1800_CLK_EPLL_EFPGA1              (AST1800_CLK_GATE_EFPGA_DBG + 27)
++#define AST1800_CLK_EPLL_EFPGA2              (AST1800_CLK_GATE_EFPGA_DBG + 28)
++#define AST1800_CLK_EPLL_EFPGA3              (AST1800_CLK_GATE_EFPGA_DBG + 29)
++#define AST1800_CLK_EPLL_EFPGA4              (AST1800_CLK_GATE_EFPGA_DBG + 30)
++#define AST1800_CLK_EPLL_EFPGA5              (AST1800_CLK_GATE_EFPGA_DBG + 31)
++#define AST1800_CLK_EPLL_EFPGA6              (AST1800_CLK_GATE_EFPGA_DBG + 32)
++#define AST1800_CLK_EPLL_EFPGA7              (AST1800_CLK_GATE_EFPGA_DBG + 33)
++#define AST1800_CLK_EFPGA0                   (AST1800_CLK_GATE_EFPGA_DBG + 34)
++#define AST1800_CLK_EFPGA1                   (AST1800_CLK_GATE_EFPGA_DBG + 35)
++#define AST1800_CLK_EFPGA2                   (AST1800_CLK_GATE_EFPGA_DBG + 36)
++#define AST1800_CLK_EFPGA3                   (AST1800_CLK_GATE_EFPGA_DBG + 37)
++#define AST1800_CLK_EFPGA4                   (AST1800_CLK_GATE_EFPGA_DBG + 38)
++#define AST1800_CLK_EFPGA5                   (AST1800_CLK_GATE_EFPGA_DBG + 39)
++#define AST1800_CLK_EFPGA6                   (AST1800_CLK_GATE_EFPGA_DBG + 40)
++#define AST1800_CLK_EFPGA7                   (AST1800_CLK_GATE_EFPGA_DBG + 41)
++#define AST1800_CLK_LPLL                     (AST1800_CLK_GATE_EFPGA_DBG + 42)
++#define AST1800_CLK_LPLL_DIV2                (AST1800_CLK_GATE_EFPGA_DBG + 43)
++#define AST1800_CLK_LPLL_DIV4                (AST1800_CLK_GATE_EFPGA_DBG + 44)
++#define AST1800_CLK_LPLL_DIV8                (AST1800_CLK_GATE_EFPGA_DBG + 45)
++#define AST1800_CLK_UXCLK                    (AST1800_CLK_GATE_EFPGA_DBG + 46)
++#define AST1800_CLK_HUXCLK                   (AST1800_CLK_GATE_EFPGA_DBG + 47)
++#define AST1800_CLK_UARTX                    (AST1800_CLK_GATE_EFPGA_DBG + 48)
++#define AST1800_CLK_HUARTX                   (AST1800_CLK_GATE_EFPGA_DBG + 49)
++#define AST1800_CLK_AHB                      (AST1800_CLK_GATE_EFPGA_DBG + 50)
++#define AST1800_CLK_APB                      (AST1800_CLK_GATE_EFPGA_DBG + 51)
++#define AST1800_CLK_UART                     (AST1800_CLK_GATE_EFPGA_DBG + 52)
++#define AST1800_CLK_I3C                      (AST1800_CLK_GATE_EFPGA_DBG + 53)
++
++#define AST1800_NUM_CLKS                     (AST1800_CLK_I3C + 1)
++
++#endif
 diff --git a/include/dt-bindings/clock/aspeed,ast2700-scu.h b/include/dt-bindings/clock/aspeed,ast2700-scu.h
 new file mode 100644
 index 000000000..cecd8c9e0
@@ -579,6 +693,73 @@
 +#define AST1700_RESET_NUMS		(AST1700_RESET_I3CDMA + 1)
 +
 +#endif  /* _MACH_ASPEED_AST1700_RESET_H_ */
+diff --git a/include/dt-bindings/reset/aspeed,ast1800-reset.h b/include/dt-bindings/reset/aspeed,ast1800-reset.h
+new file mode 100755
+index 000000000..b9927de60
+--- /dev/null
++++ b/include/dt-bindings/reset/aspeed,ast1800-reset.h
+@@ -0,0 +1,61 @@
++/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
++/*
++ * Device Tree binding constants for AST1800 reset controller.
++ *
++ * Copyright (c) 2025 Aspeed Technology Inc.
++ */
++
++#ifndef _MACH_ASPEED_AST1800_RESET_H_
++#define _MACH_ASPEED_AST1800_RESET_H_
++
++#define AST1800_RESET_CONFIG      (0)
++#define AST1800_RESET_MEM         (1)
++#define AST1800_RESET_LTPI        (2)
++#define AST1800_RESET_EFPGA_DBG   (3)
++#define AST1800_RESET_SPI_SLAVE   (4)
++#define AST1800_RESET_I2C_SLAVE   (5)
++/* reserved 6 7 */
++#define AST1800_RESET_I2C_MASTER  (8)
++#define AST1800_RESET_I3C_DMA     (9)
++#define AST1800_RESET_ADC         (10)
++#define AST1800_RESET_GPIO        (11)
++#define AST1800_RESET_JTAG        (12)
++#define AST1800_RESET_PWM         (13)
++#define AST1800_RESET_UART_DBG    (14)
++/* reserved 15~31 */
++#define AST1800_RESET_I3C0        (32)
++#define AST1800_RESET_I3C1        (33)
++#define AST1800_RESET_I3C2        (34)
++#define AST1800_RESET_I3C3        (35)
++#define AST1800_RESET_I3C4        (36)
++#define AST1800_RESET_I3C5        (37)
++#define AST1800_RESET_I3C6        (38)
++#define AST1800_RESET_I3C7        (39)
++#define AST1800_RESET_I3C8        (40)
++#define AST1800_RESET_I3C9        (41)
++#define AST1800_RESET_I3C10       (42)
++#define AST1800_RESET_I3C11       (43)
++#define AST1800_RESET_I3C12       (44)
++#define AST1800_RESET_I3C13       (45)
++#define AST1800_RESET_I3C14       (46)
++#define AST1800_RESET_I3C15       (47)
++#define AST1800_RESET_I2C0        (48)
++#define AST1800_RESET_I2C1        (49)
++#define AST1800_RESET_I2C2        (50)
++#define AST1800_RESET_I2C3        (51)
++#define AST1800_RESET_I2C4        (52)
++#define AST1800_RESET_I2C5        (53)
++#define AST1800_RESET_I2C6        (54)
++#define AST1800_RESET_I2C7        (55)
++#define AST1800_RESET_I2C8        (56)
++#define AST1800_RESET_I2C9        (57)
++#define AST1800_RESET_I2C10       (58)
++#define AST1800_RESET_I2C11       (59)
++#define AST1800_RESET_I2C12       (60)
++#define AST1800_RESET_I2C13       (61)
++#define AST1800_RESET_I2C14       (62)
++#define AST1800_RESET_I2C15       (63)
++
++#define AST1800_RESET_NUMS        (AST1800_RESET_I2C15 + 1)
++
++#endif /* _MACH_ASPEED_AST1800_RESET_H_ */
 diff --git a/include/dt-bindings/reset/aspeed,ast2700-scu.h b/include/dt-bindings/reset/aspeed,ast2700-scu.h
 new file mode 100644
 index 000000000..d53c719b7
diff --git a/recipes-kernel/linux/files/0003-Add-reset-controller-driver-for-ast2700.patch b/recipes-kernel/linux/files/0003-Add-reset-controller-driver-for-ast2700.patch
index 83d04b5..e22a9c1 100644
--- a/recipes-kernel/linux/files/0003-Add-reset-controller-driver-for-ast2700.patch
+++ b/recipes-kernel/linux/files/0003-Add-reset-controller-driver-for-ast2700.patch
@@ -1,16 +1,16 @@
-From a92552dc901299005d60a1007869f46ab9fe688b Mon Sep 17 00:00:00 2001
-From: "yung-sheng.huang" <yung-sheng.huang@fii-na.corp-partner.google.com>
-Date: Tue, 15 Apr 2025 11:17:37 +0800
-Subject: [PATCH 03/26] Add reset controller driver for ast2700
+From 4ae8679f2ec17c4b8f1f06e74e700c016a04303a Mon Sep 17 00:00:00 2001
+From: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+Date: Wed, 16 Jul 2025 17:30:14 +0800
+Subject: [PATCH] Add reset controller driver for ast2700
 
-This is base on aspeed SDK 9.06.
+This is base on aspeed SDK 9.07.
 
 Source:
 AspeedTech-BMC github:
 https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/
-(cherry picked from commit v00.06.06)
+(cherry picked from commit v00.06.07)
 
-Signed-off-by: yung-sheng.huang <yung-sheng.huang@fii-na.corp-partner.google.com>
+Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
 ---
  drivers/reset/Kconfig             |   7 +
  drivers/reset/Makefile            |   1 +
diff --git a/recipes-kernel/linux/files/0004-Add-irqchip-driver-for-ast2700.patch b/recipes-kernel/linux/files/0004-Add-irqchip-driver-for-ast2700.patch
index 7a122d0..73df94e 100644
--- a/recipes-kernel/linux/files/0004-Add-irqchip-driver-for-ast2700.patch
+++ b/recipes-kernel/linux/files/0004-Add-irqchip-driver-for-ast2700.patch
@@ -1,24 +1,24 @@
-From 0b8a71f2a1107e06c3ca591eeaa20de9cce5a853 Mon Sep 17 00:00:00 2001
-From: "yung-sheng.huang" <yung-sheng.huang@fii-na.corp-partner.google.com>
-Date: Tue, 15 Apr 2025 11:21:59 +0800
-Subject: [PATCH 04/26] Add irqchip driver for ast2700
+From c25a8c98c6e30cf29362ab276f6226277c58d3c6 Mon Sep 17 00:00:00 2001
+From: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+Date: Wed, 16 Jul 2025 17:39:18 +0800
+Subject: [PATCH] Add pinctrl driver for ast2700
 
-This is base on aspeed SDK 9.06.
+This is base on aspeed SDK 9.07.
 
 Source:
 AspeedTech-BMC github:
 https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/
-(cherry picked from commit v00.06.06)
+(cherry picked from commit v00.06.07)
 
-Signed-off-by: yung-sheng.huang <yung-sheng.huang@fii-na.corp-partner.google.com>
+Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
 ---
  drivers/irqchip/Makefile            |   2 +-
  drivers/irqchip/irq-aspeed-e2m-ic.c | 178 ++++++++++++++++++++
  drivers/irqchip/irq-aspeed-intc.c   | 140 ++++++++++++++++
  drivers/irqchip/irq-aspeed-scu-ic.c | 241 ++++++++++++++++++++++------
  4 files changed, 515 insertions(+), 46 deletions(-)
- create mode 100644 drivers/irqchip/irq-aspeed-e2m-ic.c
- create mode 100644 drivers/irqchip/irq-aspeed-intc.c
+ create mode 100755 drivers/irqchip/irq-aspeed-e2m-ic.c
+ create mode 100755 drivers/irqchip/irq-aspeed-intc.c
 
 diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
 index ffd945fe7..950f3ce4e 100644
@@ -34,7 +34,7 @@
  obj-$(CONFIG_QCOM_IRQ_COMBINER)		+= qcom-irq-combiner.o
  obj-$(CONFIG_IRQ_UNIPHIER_AIDET)	+= irq-uniphier-aidet.o
 diff --git a/drivers/irqchip/irq-aspeed-e2m-ic.c b/drivers/irqchip/irq-aspeed-e2m-ic.c
-new file mode 100644
+new file mode 100755
 index 000000000..e072925f7
 --- /dev/null
 +++ b/drivers/irqchip/irq-aspeed-e2m-ic.c
@@ -218,7 +218,7 @@
 +IRQCHIP_DECLARE(ast2700_e2m_ic, "aspeed,ast2700-e2m-ic",
 +		aspeed_ast2700_e2m_ic_of_init);
 diff --git a/drivers/irqchip/irq-aspeed-intc.c b/drivers/irqchip/irq-aspeed-intc.c
-new file mode 100644
+new file mode 100755
 index 000000000..faf18a675
 --- /dev/null
 +++ b/drivers/irqchip/irq-aspeed-intc.c
diff --git a/recipes-kernel/linux/files/0005-Add-pinctrl-driver-for-ast2700.patch b/recipes-kernel/linux/files/0005-Add-pinctrl-driver-for-ast2700.patch
index 0b493e7..e5fab2a 100644
--- a/recipes-kernel/linux/files/0005-Add-pinctrl-driver-for-ast2700.patch
+++ b/recipes-kernel/linux/files/0005-Add-pinctrl-driver-for-ast2700.patch
@@ -1,30 +1,30 @@
-From 196b725f60f9df73938b2e0acf0e1c2cb4024e7d Mon Sep 17 00:00:00 2001
-From: "yung-sheng.huang" <yung-sheng.huang@fii-na.corp-partner.google.com>
-Date: Tue, 15 Apr 2025 11:25:13 +0800
-Subject: [PATCH 05/26] Add pinctrl driver for ast2700
+From 942f8c6ad19557460a45562183029f73ad00c1b7 Mon Sep 17 00:00:00 2001
+From: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+Date: Wed, 16 Jul 2025 17:42:03 +0800
+Subject: [PATCH] Add pinctrl driver for ast2700
 
-This is base on aspeed SDK 9.06.
+This is base on aspeed SDK 9.07.
 
 Source:
 AspeedTech-BMC github:
 https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/
-(cherry picked from commit v00.06.06)
+(cherry picked from commit v00.06.07)
 
-Signed-off-by: yung-sheng.huang <yung-sheng.huang@fii-na.corp-partner.google.com>
+Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
 ---
  drivers/pinctrl/aspeed/Kconfig                |    8 +
  drivers/pinctrl/aspeed/Makefile               |    1 +
  drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c    |   19 +-
  drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c    |   19 +-
  drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c    |  525 ++--
- .../pinctrl/aspeed/pinctrl-aspeed-g7-ltpi.c   | 1156 +++++++++
+ .../pinctrl/aspeed/pinctrl-aspeed-g7-ltpi.c   | 1156 ++++++++
  .../pinctrl/aspeed/pinctrl-aspeed-g7-soc0.c   |  503 ++++
- .../pinctrl/aspeed/pinctrl-aspeed-g7-soc1.c   | 2291 ++++++++++++++++
- .../pinctrl/aspeed/pinctrl-aspeed-g7a0-soc1.c | 2304 +++++++++++++++++
+ .../pinctrl/aspeed/pinctrl-aspeed-g7-soc1.c   | 2523 +++++++++++++++++
+ .../pinctrl/aspeed/pinctrl-aspeed-g7a0-soc1.c | 2304 +++++++++++++++
  drivers/pinctrl/aspeed/pinctrl-aspeed.c       |   47 +
  drivers/pinctrl/aspeed/pinctrl-aspeed.h       |   11 +-
  drivers/pinctrl/aspeed/pinmux-aspeed.h        |   35 +-
- 12 files changed, 6718 insertions(+), 201 deletions(-)
+ 12 files changed, 6950 insertions(+), 201 deletions(-)
  create mode 100644 drivers/pinctrl/aspeed/pinctrl-aspeed-g7-ltpi.c
  create mode 100644 drivers/pinctrl/aspeed/pinctrl-aspeed-g7-soc0.c
  create mode 100644 drivers/pinctrl/aspeed/pinctrl-aspeed-g7-soc1.c
@@ -2974,10 +2974,10 @@
 +arch_initcall(aspeed_g7_soc0_pinctrl_register);
 diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g7-soc1.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g7-soc1.c
 new file mode 100644
-index 000000000..ac3e26a72
+index 000000000..7c5a5e208
 --- /dev/null
 +++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g7-soc1.c
-@@ -0,0 +1,2291 @@
+@@ -0,0 +1,2523 @@
 +// SPDX-License-Identifier: GPL-2.0
 +
 +#include <linux/bits.h>
@@ -3034,6 +3034,13 @@
 +#define SCU474 0x474 /* Multi-function Pin Control #30 */
 +#define SCU478 0x478 /* Multi-function Pin Control #31 */
 +#define SCU47C 0x47C
++#define SCU480 0x480 /* Disable Pull-Down Control #1 */
++#define SCU484 0x484 /* Disable Pull-Down Control #2 */
++#define SCU488 0x488 /* Disable Pull-Down Control #3 */
++#define SCU48C 0x48C /* Disable Pull-Down Control #4 */
++#define SCU490 0x490 /* Disable Pull-Down Control #5 */
++#define SCU494 0x494 /* Disable Pull-Down Control #6 */
++#define SCU498 0x498 /* Disable Pull-Down Control #7 */
 +#define SCU4A0 0x4A0 /* Voltage Selection */
 +#define SCU4C0 0x4C0 /* Driving Strength #0 A-I */
 +#define SCU4C4 0x4C4 /* Driving Strength #1 J-K */
@@ -3499,8 +3506,10 @@
 +GROUP_DECL(FWSPIWPN, N15);
 +GROUP_DECL(RGMII0, C20, C19, A8, R14, A7, P14, D20, A6, B6, N14, B7, B8);
 +GROUP_DECL(RGMII1, D19, B11, D15, B12, B10, P13, C18, C6, C7, D7, N13, C8);
-+GROUP_DECL(RMII0, C20, A8, R14, A7, P14, D20, A6, B6, N14);
-+GROUP_DECL(RMII1, D19, D15, B12, B10, P13, C18, C6, C7, D7);
++GROUP_DECL(RMII0, C20, A8, R14, A7, P14, A6, B6, N14);
++GROUP_DECL(RMII0RCLKO, D20);
++GROUP_DECL(RMII1, D19, D15, B12, B10, P13, C6, C7, D7);
++GROUP_DECL(RMII1RCLKO, C18);
 +GROUP_DECL(VGA, J11, E7);
 +GROUP_DECL(DSGPM1, D19, B10, C7, D7);
 +GROUP_DECL(SGPS, B11, C18, N13, C8);
@@ -3770,7 +3779,9 @@
 +	ASPEED_PINCTRL_GROUP(RGMII0),
 +	ASPEED_PINCTRL_GROUP(RGMII1),
 +	ASPEED_PINCTRL_GROUP(RMII0),
++	ASPEED_PINCTRL_GROUP(RMII0RCLKO),
 +	ASPEED_PINCTRL_GROUP(RMII1),
++	ASPEED_PINCTRL_GROUP(RMII1RCLKO),
 +	ASPEED_PINCTRL_GROUP(VGA),
 +	ASPEED_PINCTRL_GROUP(DSGPM1),
 +	ASPEED_PINCTRL_GROUP(SGPS),
@@ -3981,7 +3992,9 @@
 +FUNC_DECL_(RGMII0, "RGMII0");
 +FUNC_DECL_(RGMII1, "RGMII1");
 +FUNC_DECL_(RMII0, "RMII0");
++FUNC_DECL_(RMII0RCLKO, "RMII0RCLKO");
 +FUNC_DECL_(RMII1, "RMII1");
++FUNC_DECL_(RMII1RCLKO, "RMII1RCLKO");
 +FUNC_DECL_(VGA, "VGA");
 +FUNC_DECL_(DSGPM1, "DSGPM1");
 +FUNC_DECL_(SGPS, "SGPS");
@@ -4185,7 +4198,9 @@
 +	ASPEED_PINCTRL_FUNC(RGMII0),
 +	ASPEED_PINCTRL_FUNC(RGMII1),
 +	ASPEED_PINCTRL_FUNC(RMII0),
++	ASPEED_PINCTRL_FUNC(RMII0RCLKO),
 +	ASPEED_PINCTRL_FUNC(RMII1),
++	ASPEED_PINCTRL_FUNC(RMII1RCLKO),
 +	ASPEED_PINCTRL_FUNC(VGA),
 +	ASPEED_PINCTRL_FUNC(DSGPM1),
 +	ASPEED_PINCTRL_FUNC(SGPS),
@@ -4748,18 +4763,18 @@
 +FUNCFG_DESCL(F13, PIN_CFG(JTAGM1, SCU440, GENMASK(26, 24), (1 << 24)));
 +FUNCFG_DESCL(N15, PIN_CFG(FWSPIWPEN, SCU440, GENMASK(30, 28), (1 << 28)));
 +FUNCFG_DESCL(C20, PIN_CFG(RGMII0, SCU444, GENMASK(2, 0), 1),
-+	     PIN_CFG(RMII0R, SCU444, GENMASK(2, 0), 2));
++	     PIN_CFG(RMII0, SCU444, GENMASK(2, 0), 2));
 +FUNCFG_DESCL(C19, PIN_CFG(RGMII0, SCU444, GENMASK(6, 4), (1 << 4)));
 +FUNCFG_DESCL(A8, PIN_CFG(RGMII0, SCU444, GENMASK(10, 8), (1 << 8)),
-+	     PIN_CFG(RMII0R, SCU444, GENMASK(10, 8), (2 << 8)));
++	     PIN_CFG(RMII0, SCU444, GENMASK(10, 8), (2 << 8)));
 +FUNCFG_DESCL(R14, PIN_CFG(RGMII0, SCU444, GENMASK(14, 12), (1 << 12)),
-+	     PIN_CFG(RMII0R, SCU444, GENMASK(14, 12), (2 << 12)));
++	     PIN_CFG(RMII0, SCU444, GENMASK(14, 12), (2 << 12)));
 +FUNCFG_DESCL(A7, PIN_CFG(RGMII0, SCU444, GENMASK(18, 16), (1 << 16)),
-+	     PIN_CFG(RMII0C, SCU444, GENMASK(18, 16), (2 << 16)));
++	     PIN_CFG(RMII0, SCU444, GENMASK(18, 16), (2 << 16)));
 +FUNCFG_DESCL(P14, PIN_CFG(RGMII0, SCU444, GENMASK(22, 20), (1 << 20)),
 +	     PIN_CFG(RMII0, SCU444, GENMASK(22, 20), (2 << 20)));
 +FUNCFG_DESCL(D20, PIN_CFG(RGMII0, SCU444, GENMASK(26, 24), (1 << 24)),
-+	     PIN_CFG(RMII0, SCU444, GENMASK(26, 24), (2 << 24)));
++	     PIN_CFG(RMII0RCLKO, SCU444, GENMASK(26, 24), (2 << 24)));
 +FUNCFG_DESCL(A6, PIN_CFG(RGMII0, SCU444, GENMASK(30, 28), (1 << 28)),
 +	     PIN_CFG(RMII0, SCU444, GENMASK(30, 28), (2 << 28)));
 +FUNCFG_DESCL(B6, PIN_CFG(RGMII0, SCU448, GENMASK(2, 0), 1),
@@ -4789,7 +4804,7 @@
 +FUNCFG_DESCL(P13, PIN_CFG(RGMII1, SCU44C, GENMASK(22, 20), (1 << 20)),
 +	     PIN_CFG(RMII1, SCU44C, GENMASK(22, 20), (2 << 20)));
 +FUNCFG_DESCL(C18, PIN_CFG(RGMII1, SCU44C, GENMASK(26, 24), (1 << 24)),
-+	     PIN_CFG(RMII1, SCU44C, GENMASK(26, 24), (2 << 24)),
++	     PIN_CFG(RMII1RCLKO, SCU44C, GENMASK(26, 24), (2 << 24)),
 +	     PIN_CFG(SGPS, SCU44C, GENMASK(26, 24), (5 << 24)));
 +FUNCFG_DESCL(C6, PIN_CFG(RGMII1, SCU44C, GENMASK(30, 28), (1 << 28)),
 +	     PIN_CFG(RMII1, SCU44C, GENMASK(30, 28), (2 << 28)));
@@ -5210,6 +5225,223 @@
 +	{ PIN_CONFIG_DRIVE_STRENGTH, { E8, E8 }, SCU4DC, GENMASK(13, 12) },
 +	{ PIN_CONFIG_DRIVE_STRENGTH, { L12, L12 }, SCU4DC, GENMASK(15, 14) },
 +	{ PIN_CONFIG_POWER_SOURCE, { E9, L12 }, SCU4A0, BIT_MASK(26) },
++
++	ASPEED_PULL_DOWN_PINCONF(C16, SCU480, 0),
++	ASPEED_PULL_DOWN_PINCONF(C14, SCU480, 1),
++	ASPEED_PULL_DOWN_PINCONF(C11, SCU480, 2),
++	ASPEED_PULL_DOWN_PINCONF(D9, SCU480, 3),
++	ASPEED_PULL_DOWN_PINCONF(F14, SCU480, 4),
++	ASPEED_PULL_DOWN_PINCONF(D10, SCU480, 5),
++	ASPEED_PULL_DOWN_PINCONF(C12, SCU480, 6),
++	ASPEED_PULL_DOWN_PINCONF(C13, SCU480, 7),
++	ASPEED_PULL_DOWN_PINCONF(AC26, SCU480, 8),
++	ASPEED_PULL_DOWN_PINCONF(AA25, SCU480, 9),
++	ASPEED_PULL_DOWN_PINCONF(AB23, SCU480, 10),
++	ASPEED_PULL_DOWN_PINCONF(U22, SCU480, 11),
++	ASPEED_PULL_DOWN_PINCONF(V21, SCU480, 12),
++	ASPEED_PULL_DOWN_PINCONF(N26, SCU480, 13),
++	ASPEED_PULL_DOWN_PINCONF(P25, SCU480, 14),
++	ASPEED_PULL_DOWN_PINCONF(N25, SCU480, 15),
++	ASPEED_PULL_DOWN_PINCONF(V23, SCU480, 16),
++	ASPEED_PULL_DOWN_PINCONF(W22, SCU480, 17),
++	ASPEED_PULL_DOWN_PINCONF(AB26, SCU480, 18),
++	ASPEED_PULL_DOWN_PINCONF(AD26, SCU480, 19),
++	ASPEED_PULL_DOWN_PINCONF(P26, SCU480, 20),
++	ASPEED_PULL_DOWN_PINCONF(AE26, SCU480, 21),
++	ASPEED_PULL_DOWN_PINCONF(AF26, SCU480, 22),
++	ASPEED_PULL_DOWN_PINCONF(AF25, SCU480, 23),
++	ASPEED_PULL_DOWN_PINCONF(AE25, SCU480, 24),
++	ASPEED_PULL_DOWN_PINCONF(AD25, SCU480, 25),
++	ASPEED_PULL_DOWN_PINCONF(AF23, SCU480, 26),
++	ASPEED_PULL_DOWN_PINCONF(AF20, SCU480, 27),
++	ASPEED_PULL_DOWN_PINCONF(AF21, SCU480, 28),
++	ASPEED_PULL_DOWN_PINCONF(AE21, SCU480, 29),
++	ASPEED_PULL_DOWN_PINCONF(AE23, SCU480, 30),
++	ASPEED_PULL_DOWN_PINCONF(AD22, SCU480, 31),
++	ASPEED_PULL_DOWN_PINCONF(AF17, SCU484, 0),
++	ASPEED_PULL_DOWN_PINCONF(AA16, SCU484, 1),
++	ASPEED_PULL_DOWN_PINCONF(Y16, SCU484, 2),
++	ASPEED_PULL_DOWN_PINCONF(V17, SCU484, 3),
++	ASPEED_PULL_DOWN_PINCONF(J13, SCU484, 4),
++	ASPEED_PULL_DOWN_PINCONF(AB16, SCU484, 5),
++	ASPEED_PULL_DOWN_PINCONF(AC16, SCU484, 6),
++	ASPEED_PULL_DOWN_PINCONF(AF16, SCU484, 7),
++	ASPEED_PULL_DOWN_PINCONF(AA15, SCU484, 8),
++	ASPEED_PULL_DOWN_PINCONF(AB15, SCU484, 9),
++	ASPEED_PULL_DOWN_PINCONF(AC15, SCU484, 10),
++	ASPEED_PULL_DOWN_PINCONF(AD15, SCU484, 11),
++	ASPEED_PULL_DOWN_PINCONF(Y15, SCU484, 12),
++	ASPEED_PULL_DOWN_PINCONF(AA14, SCU484, 13),
++	ASPEED_PULL_DOWN_PINCONF(W16, SCU484, 14),
++	ASPEED_PULL_DOWN_PINCONF(V16, SCU484, 15),
++	ASPEED_PULL_DOWN_PINCONF(AB18, SCU484, 16),
++	ASPEED_PULL_DOWN_PINCONF(AC18, SCU484, 17),
++	ASPEED_PULL_DOWN_PINCONF(K13, SCU484, 18),
++	ASPEED_PULL_DOWN_PINCONF(AA17, SCU484, 19),
++	ASPEED_PULL_DOWN_PINCONF(AB17, SCU484, 20),
++	ASPEED_PULL_DOWN_PINCONF(AD16, SCU484, 21),
++	ASPEED_PULL_DOWN_PINCONF(AC17, SCU484, 22),
++	ASPEED_PULL_DOWN_PINCONF(AD17, SCU484, 23),
++	ASPEED_PULL_DOWN_PINCONF(AE16, SCU484, 24),
++	ASPEED_PULL_DOWN_PINCONF(AE17, SCU484, 25),
++	ASPEED_PULL_DOWN_PINCONF(AB24, SCU484, 26),
++	ASPEED_PULL_DOWN_PINCONF(W26, SCU484, 27),
++	ASPEED_PULL_DOWN_PINCONF(HOLE0, SCU484, 28),
++	ASPEED_PULL_DOWN_PINCONF(HOLE1, SCU484, 29),
++	ASPEED_PULL_DOWN_PINCONF(HOLE2, SCU484, 30),
++	ASPEED_PULL_DOWN_PINCONF(HOLE3, SCU484, 31),
++	ASPEED_PULL_DOWN_PINCONF(W25, SCU488, 0),
++	ASPEED_PULL_DOWN_PINCONF(Y23, SCU488, 1),
++	ASPEED_PULL_DOWN_PINCONF(Y24, SCU488, 2),
++	ASPEED_PULL_DOWN_PINCONF(W21, SCU488, 3),
++	ASPEED_PULL_DOWN_PINCONF(AA23, SCU488, 4),
++	ASPEED_PULL_DOWN_PINCONF(AC22, SCU488, 5),
++	ASPEED_PULL_DOWN_PINCONF(AB22, SCU488, 6),
++	ASPEED_PULL_DOWN_PINCONF(Y21, SCU488, 7),
++	ASPEED_PULL_DOWN_PINCONF(AE20, SCU488, 8),
++	ASPEED_PULL_DOWN_PINCONF(AF19, SCU488, 9),
++	ASPEED_PULL_DOWN_PINCONF(Y22, SCU488, 10),
++	ASPEED_PULL_DOWN_PINCONF(AA20, SCU488, 11),
++	ASPEED_PULL_DOWN_PINCONF(AA22, SCU488, 12),
++	ASPEED_PULL_DOWN_PINCONF(AB20, SCU488, 13),
++	ASPEED_PULL_DOWN_PINCONF(AF18, SCU488, 14),
++	ASPEED_PULL_DOWN_PINCONF(AE19, SCU488, 15),
++	ASPEED_PULL_DOWN_PINCONF(AD20, SCU488, 16),
++	ASPEED_PULL_DOWN_PINCONF(AC20, SCU488, 17),
++	ASPEED_PULL_DOWN_PINCONF(AA21, SCU488, 18),
++	ASPEED_PULL_DOWN_PINCONF(AB21, SCU488, 19),
++	ASPEED_PULL_DOWN_PINCONF(AC19, SCU488, 20),
++	ASPEED_PULL_DOWN_PINCONF(AE18, SCU488, 21),
++	ASPEED_PULL_DOWN_PINCONF(AD19, SCU488, 22),
++	ASPEED_PULL_DOWN_PINCONF(AD18, SCU488, 23),
++	ASPEED_PULL_DOWN_PINCONF(U25, SCU488, 24),
++	ASPEED_PULL_DOWN_PINCONF(U26, SCU488, 25),
++	ASPEED_PULL_DOWN_PINCONF(Y26, SCU488, 26),
++	ASPEED_PULL_DOWN_PINCONF(AA24, SCU488, 27),
++	ASPEED_PULL_DOWN_PINCONF(R25, SCU488, 28),
++	ASPEED_PULL_DOWN_PINCONF(AA26, SCU488, 29),
++	ASPEED_PULL_DOWN_PINCONF(R26, SCU488, 30),
++	ASPEED_PULL_DOWN_PINCONF(Y25, SCU488, 31),
++	ASPEED_PULL_DOWN_PINCONF(B16, SCU48C, 0),
++	ASPEED_PULL_DOWN_PINCONF(D14, SCU48C, 1),
++	ASPEED_PULL_DOWN_PINCONF(B15, SCU48C, 2),
++	ASPEED_PULL_DOWN_PINCONF(B14, SCU48C, 3),
++	ASPEED_PULL_DOWN_PINCONF(C17, SCU48C, 4),
++	ASPEED_PULL_DOWN_PINCONF(B13, SCU48C, 5),
++	ASPEED_PULL_DOWN_PINCONF(E14, SCU48C, 6),
++	ASPEED_PULL_DOWN_PINCONF(C15, SCU48C, 7),
++	ASPEED_PULL_DOWN_PINCONF(D24, SCU48C, 8),
++	ASPEED_PULL_DOWN_PINCONF(B23, SCU48C, 9),
++	ASPEED_PULL_DOWN_PINCONF(B22, SCU48C, 10),
++	ASPEED_PULL_DOWN_PINCONF(C23, SCU48C, 11),
++	ASPEED_PULL_DOWN_PINCONF(B18, SCU48C, 12),
++	ASPEED_PULL_DOWN_PINCONF(B21, SCU48C, 13),
++	ASPEED_PULL_DOWN_PINCONF(M15, SCU48C, 14),
++	ASPEED_PULL_DOWN_PINCONF(B19, SCU48C, 15),
++	ASPEED_PULL_DOWN_PINCONF(B26, SCU48C, 16),
++	ASPEED_PULL_DOWN_PINCONF(A25, SCU48C, 17),
++	ASPEED_PULL_DOWN_PINCONF(A24, SCU48C, 18),
++	ASPEED_PULL_DOWN_PINCONF(B24, SCU48C, 19),
++	ASPEED_PULL_DOWN_PINCONF(E26, SCU48C, 20),
++	ASPEED_PULL_DOWN_PINCONF(A21, SCU48C, 21),
++	ASPEED_PULL_DOWN_PINCONF(A19, SCU48C, 22),
++	ASPEED_PULL_DOWN_PINCONF(A18, SCU48C, 23),
++	ASPEED_PULL_DOWN_PINCONF(D26, SCU48C, 24),
++	ASPEED_PULL_DOWN_PINCONF(C26, SCU48C, 25),
++	ASPEED_PULL_DOWN_PINCONF(A23, SCU48C, 26),
++	ASPEED_PULL_DOWN_PINCONF(A22, SCU48C, 27),
++	ASPEED_PULL_DOWN_PINCONF(B25, SCU48C, 28),
++	ASPEED_PULL_DOWN_PINCONF(F26, SCU48C, 29),
++	ASPEED_PULL_DOWN_PINCONF(A26, SCU48C, 30),
++	ASPEED_PULL_DOWN_PINCONF(A14, SCU48C, 31),
++	ASPEED_PULL_DOWN_PINCONF(E10, SCU490, 0),
++	ASPEED_PULL_DOWN_PINCONF(E13, SCU490, 1),
++	ASPEED_PULL_DOWN_PINCONF(D12, SCU490, 2),
++	ASPEED_PULL_DOWN_PINCONF(F10, SCU490, 3),
++	ASPEED_PULL_DOWN_PINCONF(E11, SCU490, 4),
++	ASPEED_PULL_DOWN_PINCONF(F11, SCU490, 5),
++	ASPEED_PULL_DOWN_PINCONF(F13, SCU490, 6),
++	ASPEED_PULL_DOWN_PINCONF(N15, SCU490, 7),
++	ASPEED_PULL_DOWN_PINCONF(C20, SCU490, 8),
++	ASPEED_PULL_DOWN_PINCONF(C19, SCU490, 9),
++	ASPEED_PULL_DOWN_PINCONF(A8, SCU490, 10),
++	ASPEED_PULL_DOWN_PINCONF(R14, SCU490, 11),
++	ASPEED_PULL_DOWN_PINCONF(A7, SCU490, 12),
++	ASPEED_PULL_DOWN_PINCONF(P14, SCU490, 13),
++	ASPEED_PULL_DOWN_PINCONF(D20, SCU490, 14),
++	ASPEED_PULL_DOWN_PINCONF(A6, SCU490, 15),
++	ASPEED_PULL_DOWN_PINCONF(B6, SCU490, 16),
++	ASPEED_PULL_DOWN_PINCONF(N14, SCU490, 17),
++	ASPEED_PULL_DOWN_PINCONF(B7, SCU490, 18),
++	ASPEED_PULL_DOWN_PINCONF(B8, SCU490, 19),
++	ASPEED_PULL_DOWN_PINCONF(B9, SCU490, 20),
++	ASPEED_PULL_DOWN_PINCONF(M14, SCU490, 21),
++	ASPEED_PULL_DOWN_PINCONF(J11, SCU490, 22),
++	ASPEED_PULL_DOWN_PINCONF(E7, SCU490, 23),
++	ASPEED_PULL_DOWN_PINCONF(D19, SCU490, 24),
++	ASPEED_PULL_DOWN_PINCONF(B11, SCU490, 25),
++	ASPEED_PULL_DOWN_PINCONF(D15, SCU490, 26),
++	ASPEED_PULL_DOWN_PINCONF(B12, SCU490, 27),
++	ASPEED_PULL_DOWN_PINCONF(B10, SCU490, 28),
++	ASPEED_PULL_DOWN_PINCONF(P13, SCU490, 29),
++	ASPEED_PULL_DOWN_PINCONF(C18, SCU490, 30),
++	ASPEED_PULL_DOWN_PINCONF(C6, SCU490, 31),
++	ASPEED_PULL_DOWN_PINCONF(C7, SCU494, 0),
++	ASPEED_PULL_DOWN_PINCONF(D7, SCU494, 1),
++	ASPEED_PULL_DOWN_PINCONF(N13, SCU494, 2),
++	ASPEED_PULL_DOWN_PINCONF(C8, SCU494, 3),
++	ASPEED_PULL_DOWN_PINCONF(C9, SCU494, 4),
++	ASPEED_PULL_DOWN_PINCONF(C10, SCU494, 5),
++	ASPEED_PULL_DOWN_PINCONF(M16, SCU494, 6),
++	ASPEED_PULL_DOWN_PINCONF(A15, SCU494, 7),
++	ASPEED_PULL_DOWN_PINCONF(G11, SCU494, 8),
++	ASPEED_PULL_DOWN_PINCONF(H7, SCU494, 9),
++	ASPEED_PULL_DOWN_PINCONF(H8, SCU494, 10),
++	ASPEED_PULL_DOWN_PINCONF(H9, SCU494, 11),
++	ASPEED_PULL_DOWN_PINCONF(H10, SCU494, 12),
++	ASPEED_PULL_DOWN_PINCONF(H11, SCU494, 13),
++	ASPEED_PULL_DOWN_PINCONF(J9, SCU494, 14),
++	ASPEED_PULL_DOWN_PINCONF(J10, SCU494, 15),
++	ASPEED_PULL_DOWN_PINCONF(E9, SCU494, 16),
++	ASPEED_PULL_DOWN_PINCONF(F9, SCU494, 17),
++	ASPEED_PULL_DOWN_PINCONF(F8, SCU494, 18),
++	ASPEED_PULL_DOWN_PINCONF(M13, SCU494, 19),
++	ASPEED_PULL_DOWN_PINCONF(F7, SCU494, 20),
++	ASPEED_PULL_DOWN_PINCONF(D8, SCU494, 21),
++	ASPEED_PULL_DOWN_PINCONF(E8, SCU494, 22),
++	ASPEED_PULL_DOWN_PINCONF(L12, SCU494, 23),
++	ASPEED_PULL_DOWN_PINCONF(F12, SCU494, 24),
++	ASPEED_PULL_DOWN_PINCONF(E12, SCU494, 25),
++	ASPEED_PULL_DOWN_PINCONF(J12, SCU494, 26),
++	ASPEED_PULL_DOWN_PINCONF(G7, SCU494, 27),
++	ASPEED_PULL_DOWN_PINCONF(G8, SCU494, 28),
++	ASPEED_PULL_DOWN_PINCONF(G9, SCU494, 29),
++	ASPEED_PULL_DOWN_PINCONF(G10, SCU494, 30),
++	ASPEED_PULL_DOWN_PINCONF(K12, SCU494, 31),
++	ASPEED_PULL_DOWN_PINCONF(W17, SCU498, 0),
++	ASPEED_PULL_DOWN_PINCONF(V18, SCU498, 1),
++	ASPEED_PULL_DOWN_PINCONF(W18, SCU498, 2),
++	ASPEED_PULL_DOWN_PINCONF(Y17, SCU498, 3),
++	ASPEED_PULL_DOWN_PINCONF(AA18, SCU498, 4),
++	ASPEED_PULL_DOWN_PINCONF(AA13, SCU498, 5),
++	ASPEED_PULL_DOWN_PINCONF(Y18, SCU498, 6),
++	ASPEED_PULL_DOWN_PINCONF(AA12, SCU498, 7),
++	ASPEED_PULL_DOWN_PINCONF(W20, SCU498, 8),
++	ASPEED_PULL_DOWN_PINCONF(V20, SCU498, 9),
++	ASPEED_PULL_DOWN_PINCONF(Y11, SCU498, 10),
++	ASPEED_PULL_DOWN_PINCONF(V14, SCU498, 11),
++	ASPEED_PULL_DOWN_PINCONF(V19, SCU498, 12),
++	ASPEED_PULL_DOWN_PINCONF(W14, SCU498, 13),
++	ASPEED_PULL_DOWN_PINCONF(Y20, SCU498, 14),
++	ASPEED_PULL_DOWN_PINCONF(AB19, SCU498, 15),
++	ASPEED_PULL_DOWN_PINCONF(U21, SCU498, 16),
++	ASPEED_PULL_DOWN_PINCONF(T24, SCU498, 17),
++	ASPEED_PULL_DOWN_PINCONF(V24, SCU498, 18),
++	ASPEED_PULL_DOWN_PINCONF(V22, SCU498, 19),
++	ASPEED_PULL_DOWN_PINCONF(T23, SCU498, 20),
++	ASPEED_PULL_DOWN_PINCONF(AC25, SCU498, 21),
++	ASPEED_PULL_DOWN_PINCONF(AB25, SCU498, 22),
++	ASPEED_PULL_DOWN_PINCONF(AC24, SCU498, 23),
 +};
 +
 +static const struct aspeed_pin_config_map aspeed_g7_pin_config_map[] = {
diff --git a/recipes-kernel/linux/files/0006-Add-clk-driver-for-ast2700.patch b/recipes-kernel/linux/files/0006-Add-clk-driver-for-ast2700.patch
index 6e12725..a8d9634 100644
--- a/recipes-kernel/linux/files/0006-Add-clk-driver-for-ast2700.patch
+++ b/recipes-kernel/linux/files/0006-Add-clk-driver-for-ast2700.patch
@@ -1,32 +1,37 @@
-From 5994b1525726b5582d06fbd0c2e07f7cbbc7b104 Mon Sep 17 00:00:00 2001
-From: "yung-sheng.huang" <yung-sheng.huang@fii-na.corp-partner.google.com>
-Date: Tue, 15 Apr 2025 11:30:43 +0800
-Subject: [PATCH 06/26] Add clk driver for ast2700
+From 9baa510927cefdc3a24b6fc6b44c5e2442538186 Mon Sep 17 00:00:00 2001
+From: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+Date: Wed, 16 Jul 2025 17:47:38 +0800
+Subject: [PATCH] Add clk driver for ast2700
 
-This is base on aspeed SDK 9.06.
+This is base on aspeed SDK 9.07.
 
 Source:
 AspeedTech-BMC github:
 https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/
-(cherry picked from commit v00.06.06)
+(cherry picked from commit v00.06.07)
 
-Signed-off-by: yung-sheng.huang <yung-sheng.huang@fii-na.corp-partner.google.com>
+Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
 ---
- drivers/clk/Kconfig       |   22 +
- drivers/clk/Makefile      |    3 +
- drivers/clk/clk-aspeed.c  |    1 +
- drivers/clk/clk-ast1700.c |  807 ++++++++++++++++++++++++
- drivers/clk/clk-ast2600.c |  375 ++++++++---
- drivers/clk/clk-ast2700.c | 1255 +++++++++++++++++++++++++++++++++++++
- 6 files changed, 2384 insertions(+), 79 deletions(-)
+ drivers/clk/Kconfig         |   28 +
+ drivers/clk/Makefile        |    4 +
+ drivers/clk/clk-aspeed.c    |    1 +
+ drivers/clk/clk-ast1700.c   |  807 ++++++++++++++++++++++
+ drivers/clk/clk-ast1800.c   |  855 ++++++++++++++++++++++++
+ drivers/clk/clk-ast2600.c   |  375 ++++++++---
+ drivers/clk/clk-ast2700.c   | 1259 +++++++++++++++++++++++++++++++++++
+ drivers/clk/clk-ast2700a0.c | 1257 ++++++++++++++++++++++++++++++++++
+ 8 files changed, 4507 insertions(+), 79 deletions(-)
  create mode 100644 drivers/clk/clk-ast1700.c
+ create mode 100755 drivers/clk/clk-ast1800.c
+ mode change 100644 => 100755 drivers/clk/clk-ast2600.c
  create mode 100644 drivers/clk/clk-ast2700.c
+ create mode 100755 drivers/clk/clk-ast2700a0.c
 
 diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
-index c30099866..0b7a73039 100644
+index c30099866..7d060eee4 100644
 --- a/drivers/clk/Kconfig
 +++ b/drivers/clk/Kconfig
-@@ -269,6 +269,20 @@ config COMMON_CLK_ASPEED
+@@ -269,6 +269,26 @@ config COMMON_CLK_ASPEED
  	  The G4 and G5 series, including the ast2400 and ast2500, are supported
  	  by this driver.
  
@@ -44,10 +49,16 @@
 +	help
 +	  This driver supports the AST1700 clocks on the Aspeed BMC platforms.
 +
++config COMMON_CLK_AST1800
++        bool "Clock driver for AST1800"
++        depends on ARCH_ASPEED || COMPILE_TEST
++        help
++          This driver supports the AST1700 clocks on the Aspeed BMC platforms.
++
  config COMMON_CLK_S2MPS11
  	tristate "Clock driver for S2MPS1X/S5M8767 MFD"
  	depends on MFD_SEC_CORE || COMPILE_TEST
-@@ -325,6 +339,14 @@ config COMMON_CLK_LOCHNAGAR
+@@ -325,6 +345,14 @@ config COMMON_CLK_LOCHNAGAR
  	  This driver supports the clocking features of the Cirrus Logic
  	  Lochnagar audio development board.
  
@@ -63,19 +74,20 @@
  	bool "Clock driver for Loongson-2 SoC"
  	depends on LOONGARCH || COMPILE_TEST
 diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
-index 18969cbd4..0db16bf26 100644
+index 18969cbd4..a4290206c 100644
 --- a/drivers/clk/Makefile
 +++ b/drivers/clk/Makefile
-@@ -37,6 +37,8 @@ obj-$(CONFIG_COMMON_CLK_FSL_SAI)	+= clk-fsl-sai.o
+@@ -37,6 +37,9 @@ obj-$(CONFIG_COMMON_CLK_FSL_SAI)	+= clk-fsl-sai.o
  obj-$(CONFIG_COMMON_CLK_GEMINI)		+= clk-gemini.o
  obj-$(CONFIG_COMMON_CLK_ASPEED)		+= clk-aspeed.o
  obj-$(CONFIG_MACH_ASPEED_G6)		+= clk-ast2600.o
-+obj-$(CONFIG_COMMON_CLK_AST2700)	+= clk-ast2700.o
++obj-$(CONFIG_COMMON_CLK_AST2700)	+= clk-ast2700.o clk-ast2700a0.o
 +obj-$(CONFIG_COMMON_CLK_AST1700)	+= clk-ast1700.o
++obj-$(CONFIG_COMMON_CLK_AST1800)        += clk-ast1800.o
  obj-$(CONFIG_ARCH_HIGHBANK)		+= clk-highbank.o
  obj-$(CONFIG_CLK_HSDK)			+= clk-hsdk-pll.o
  obj-$(CONFIG_COMMON_CLK_K210)		+= clk-k210.o
-@@ -51,6 +53,7 @@ obj-$(CONFIG_ARCH_MILBEAUT_M10V)	+= clk-milbeaut.o
+@@ -51,6 +54,7 @@ obj-$(CONFIG_ARCH_MILBEAUT_M10V)	+= clk-milbeaut.o
  obj-$(CONFIG_ARCH_MOXART)		+= clk-moxart.o
  obj-$(CONFIG_ARCH_NOMADIK)		+= clk-nomadik.o
  obj-$(CONFIG_ARCH_NPCM7XX)	    	+= clk-npcm7xx.o
@@ -908,8 +920,871 @@
 +
 +CLK_OF_DECLARE_DRIVER(ast1700, "aspeed,ast1700-scu", AST1700_clk_init);
 +
+diff --git a/drivers/clk/clk-ast1800.c b/drivers/clk/clk-ast1800.c
+new file mode 100755
+index 000000000..ef60814d8
+--- /dev/null
++++ b/drivers/clk/clk-ast1800.c
+@@ -0,0 +1,855 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++// Copyright ASPEED Technology
++
++#include <linux/clk-provider.h>
++#include <linux/of_address.h>
++#include <linux/of_device.h>
++#include <linux/reset-controller.h>
++
++#include <dt-bindings/clock/aspeed,ast1800-clk.h>
++#include <dt-bindings/reset/aspeed,ast1800-reset.h>
++
++#define AST1800_CLK_25MHZ 25000000
++#define AST1800_CLK_24MHZ 24000000
++#define AST1800_CLK_192MHZ 192000000
++
++#define AST1800_CLK_STOP1 0x50
++#define AST1800_CLK_STOP2 0x54
++#define AST1800_CLK_STOP3 0x58
++
++#define AST1800_CLK_SEL	0x60
++
++#define AST1800_HPLL_PARAM 0x70
++#define AST1800_EPLL_PARAM 0x78
++#define AST1800_LPLL_PARAM 0x80
++#define AST1800_UXCLK_CTRL 0x88
++#define AST1800_HUXCLK_CTRL 0x8C
++
++static DEFINE_IDA(ast1800_clk_ida);
++
++/* Globally visible clocks */
++static DEFINE_SPINLOCK(ast1800_clk_lock);
++
++static const struct clk_div_table ast1800_clk_div_table[] = {
++	{ 0x0, 40 },
++	{ 0x1, 20 },
++	{ 0x2, 10 },
++	{ 0x3, 5 },
++};
++
++static const struct clk_div_table ast1800_efpga_clk_div_table[] = {
++	{ 0x0, 1 },
++	{ 0x1, 1 },
++	{ 0x2, 2 },
++	{ 0x3, 3 },
++	{ 0x4, 4 },
++	{ 0x5, 5 },
++	{ 0x6, 6 },
++	{ 0x7, 7 },
++	{ 0x8, 8 },
++	{ 0x9, 9 },
++	{ 0xa, 10 },
++	{ 0xb, 11 },
++	{ 0xc, 12 },
++	{ 0xd, 13 },
++	{ 0xe, 14 },
++	{ 0xf, 15 },
++	{ 0x10, 16 },
++	{ 0x11, 17 },
++	{ 0x12, 18 },
++	{ 0x13, 19 },
++	{ 0 }
++};
++
++static struct clk_hw *AST1800_calc_uclk(const char *name, u32 val)
++{
++	unsigned int mult, div;
++
++	/* UARTCLK = UXCLK * R / (N * 2) */
++	u32 r = val & 0xff;
++	u32 n = (val >> 8) & 0x3ff;
++
++	mult = r;
++	div = n * 2;
++
++	return clk_hw_register_fixed_factor(NULL, name, "ast1800-uxclk", 0, mult, div);
++};
++
++static struct clk_hw *AST1800_calc_huclk(const char *name, u32 val)
++{
++	unsigned int mult, div;
++
++	/* UARTCLK = UXCLK * R / (N * 2) */
++	u32 r = val & 0xff;
++	u32 n = (val >> 8) & 0x3ff;
++
++	mult = r;
++	div = n * 2;
++
++	return clk_hw_register_fixed_factor(NULL, name, "ast1800-huxclk", 0, mult, div);
++};
++
++struct clk_hw *AST1800_calc_pll(const char *name, const char *parent_name, u32 val)
++{
++	unsigned int mult, div;
++
++	if (val & BIT(24)) {
++		/* Pass through mode */
++		mult = 1;
++		div = 1;
++	} else {
++		/* F = 25Mhz * [(M + 1) / (n + 1)] / (p + 1) */
++		u32 m = val & 0x1fff;
++		u32 n = (val >> 13) & 0x3f;
++		u32 p = (val >> 19) & 0xf;
++
++		mult = (m + 1) / (n + 1);
++		div = (p + 1);
++	}
++	return clk_hw_register_fixed_factor(NULL, name, parent_name, 0, mult, div);
++};
++
++static int AST1800_clk_is_enabled(struct clk_hw *hw)
++{
++	struct clk_gate *gate = to_clk_gate(hw);
++	u32 clk = BIT(gate->bit_idx % 32);
++	u32 reg = readl(gate->reg);
++
++	return !(reg & clk);
++}
++
++static int AST1800_clk_enable(struct clk_hw *hw)
++{
++	struct clk_gate *gate = to_clk_gate(hw);
++	u32 clk = BIT(gate->bit_idx % 32);
++	u32 val = readl(gate->reg);
++
++	if (val & clk)
++		writel(val & ~clk, gate->reg);
++
++	return 0;
++}
++
++static void AST1800_clk_disable(struct clk_hw *hw)
++{
++	struct clk_gate *gate = to_clk_gate(hw);
++	u32 clk = BIT(gate->bit_idx % 32);
++	u32 val = readl(gate->reg);
++
++	if (!(val & clk))
++		writel(val | clk, gate->reg);
++}
++
++static const struct clk_ops AST1800_clk_gate_ops = {
++	.enable = AST1800_clk_enable,
++	.disable = AST1800_clk_disable,
++	.is_enabled = AST1800_clk_is_enabled,
++};
++
++static struct clk_hw *AST1800_clk_hw_register_gate(struct device *dev, const char *name,
++						   const char *parent_name, unsigned long flags,
++						   void __iomem *reg, u8 clock_idx,
++						   u8 clk_gate_flags, spinlock_t *lock)
++{
++	struct clk_gate *gate;
++	struct clk_hw *hw;
++	struct clk_init_data init;
++	int ret = -EINVAL;
++
++	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
++	if (!gate)
++		return ERR_PTR(-ENOMEM);
++
++	init.name = name;
++	init.ops = &AST1800_clk_gate_ops;
++	init.flags = flags;
++	init.parent_names = parent_name ? &parent_name : NULL;
++	init.num_parents = parent_name ? 1 : 0;
++
++	gate->reg = reg;
++	gate->bit_idx = clock_idx;
++	gate->flags = clk_gate_flags;
++	gate->lock = lock;
++	gate->hw.init = &init;
++
++	hw = &gate->hw;
++	ret = clk_hw_register(dev, hw);
++	if (ret) {
++		kfree(gate);
++		hw = ERR_PTR(ret);
++	}
++
++	return hw;
++}
++
++struct ast1800_reset {
++	void __iomem *base;
++	struct reset_controller_dev rcdev;
++};
++
++#define to_rc_data(p) container_of(p, struct ast1800_reset, rcdev)
++
++static int ast1800_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
++{
++	struct ast1800_reset *rc = to_rc_data(rcdev);
++	u32 rst = BIT(id % 32);
++	u32 reg = id >= 32 ? 0x44 : 0x40;
++
++	writel(readl(rc->base + reg) | rst, rc->base + reg);
++	return 0;
++}
++
++static int ast1800_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
++{
++	struct ast1800_reset *rc = to_rc_data(rcdev);
++	u32 rst = BIT(id % 32);
++	u32 reg = id >= 32 ? 0x44 : 0x40;
++
++	/* Use set to clear register */
++	writel(readl(rc->base + reg) & ~rst, rc->base + reg);
++	return 0;
++}
++
++static int ast1800_reset_status(struct reset_controller_dev *rcdev, unsigned long id)
++{
++	struct ast1800_reset *rc = to_rc_data(rcdev);
++	u32 rst = BIT(id % 32);
++	u32 reg = id >= 32 ? 0x44 : 0x40;
++
++	return (readl(rc->base + reg) & rst);
++}
++
++static const struct reset_control_ops ast1800_reset_ops = {
++	.assert = ast1800_reset_assert,
++	.deassert = ast1800_reset_deassert,
++	.status = ast1800_reset_status,
++};
++
++static const char *const fpga0_sel0[] = {
++	"ast1800_0-hpll_div200",
++	"ast1800_0-hpll_div100",
++	"ast1800_0-hpll_div50",
++	"ast1800_0-hpll_div40",
++	"ast1800_0-hpll_div25",
++	"ast1800_0-hpll_div20",
++	"ast1800_0-hpll_efpga0",
++	"ast1800_0-epll_efpga0",
++};
++
++static const char *const fpga0_sel1[] = {
++	"ast1800_1-hpll_div200",
++	"ast1800_1-hpll_div100",
++	"ast1800_1-hpll_div50",
++	"ast1800_1-hpll_div40",
++	"ast1800_1-hpll_div25",
++	"ast1800_1-hpll_div20",
++	"ast1800_1-hpll_efpga0",
++	"ast1800_1-epll_efpga0",
++};
++
++static const char *const fpga1_sel0[] = {
++	"ast1800_0-hpll_div200",
++	"ast1800_0-hpll_div100",
++	"ast1800_0-hpll_div50",
++	"ast1800_0-hpll_div40",
++	"ast1800_0-hpll_div25",
++	"ast1800_0-hpll_div20",
++	"ast1800_0-hpll_efpga1",
++	"ast1800_0-epll_efpga1",
++};
++
++static const char *const fpga1_sel1[] = {
++	"ast1800_1-hpll_div200",
++	"ast1800_1-hpll_div100",
++	"ast1800_1-hpll_div50",
++	"ast1800_1-hpll_div40",
++	"ast1800_1-hpll_div25",
++	"ast1800_1-hpll_div20",
++	"ast1800_1-hpll_efpga1",
++	"ast1800_1-epll_efpga1",
++};
++
++static const char *const fpga2_sel0[] = {
++	"ast1800_0-hpll_div200",
++	"ast1800_0-hpll_div100",
++	"ast1800_0-hpll_div50",
++	"ast1800_0-hpll_div40",
++	"ast1800_0-hpll_div25",
++	"ast1800_0-hpll_div20",
++	"ast1800_0-hpll_efpga2",
++	"ast1800_0-epll_efpga2",
++};
++
++static const char *const fpga2_sel1[] = {
++	"ast1800_1-hpll_div200",
++	"ast1800_1-hpll_div100",
++	"ast1800_1-hpll_div50",
++	"ast1800_1-hpll_div40",
++	"ast1800_1-hpll_div25",
++	"ast1800_1-hpll_div20",
++	"ast1800_1-hpll_efpga2",
++	"ast1800_1-epll_efpga2",
++};
++
++static const char *const fpga3_sel0[] = {
++	"ast1800_0-hpll_div200",
++	"ast1800_0-hpll_div100",
++	"ast1800_0-hpll_div50",
++	"ast1800_0-hpll_div40",
++	"ast1800_0-hpll_div25",
++	"ast1800_0-hpll_div20",
++	"ast1800_0-hpll_efpga3",
++	"ast1800_0-epll_efpga3",
++};
++
++static const char *const fpga3_sel1[] = {
++	"ast1800_1-hpll_div200",
++	"ast1800_1-hpll_div100",
++	"ast1800_1-hpll_div50",
++	"ast1800_1-hpll_div40",
++	"ast1800_1-hpll_div25",
++	"ast1800_1-hpll_div20",
++	"ast1800_1-hpll_efpga3",
++	"ast1800_1-epll_efpga3",
++};
++
++static const char *const fpga4_sel0[] = {
++	"ast1800_0-hpll_div200",
++	"ast1800_0-hpll_div100",
++	"ast1800_0-hpll_div50",
++	"ast1800_0-hpll_div40",
++	"ast1800_0-hpll_div25",
++	"ast1800_0-hpll_div20",
++	"ast1800_0-hpll_efpga4",
++	"ast1800_0-epll_efpga4",
++};
++
++static const char *const fpga4_sel1[] = {
++	"ast1800_1-hpll_div200",
++	"ast1800_1-hpll_div100",
++	"ast1800_1-hpll_div50",
++	"ast1800_1-hpll_div40",
++	"ast1800_1-hpll_div25",
++	"ast1800_1-hpll_div20",
++	"ast1800_1-hpll_efpga4",
++	"ast1800_1-epll_efpga4",
++};
++
++static const char *const fpga5_sel0[] = {
++	"ast1800_0-hpll_div200",
++	"ast1800_0-hpll_div100",
++	"ast1800_0-hpll_div50",
++	"ast1800_0-hpll_div40",
++	"ast1800_0-hpll_div25",
++	"ast1800_0-hpll_div20",
++	"ast1800_0-hpll_efpga5",
++	"ast1800_0-epll_efpga5",
++};
++
++static const char *const fpga5_sel1[] = {
++	"ast1800_1-hpll_div200",
++	"ast1800_1-hpll_div100",
++	"ast1800_1-hpll_div50",
++	"ast1800_1-hpll_div40",
++	"ast1800_1-hpll_div25",
++	"ast1800_1-hpll_div20",
++	"ast1800_1-hpll_efpga5",
++	"ast1800_1-epll_efpga5",
++};
++
++static const char *const fpga6_sel0[] = {
++	"ast1800_0-hpll_div200",
++	"ast1800_0-hpll_div100",
++	"ast1800_0-hpll_div50",
++	"ast1800_0-hpll_div40",
++	"ast1800_0-hpll_div25",
++	"ast1800_0-hpll_div20",
++	"ast1800_0-hpll_efpga6",
++	"ast1800_0-epll_efpga6",
++};
++
++static const char *const fpga6_sel1[] = {
++	"ast1800_1-hpll_div200",
++	"ast1800_1-hpll_div100",
++	"ast1800_1-hpll_div50",
++	"ast1800_1-hpll_div40",
++	"ast1800_1-hpll_div25",
++	"ast1800_1-hpll_div20",
++	"ast1800_1-hpll_efpga6",
++	"ast1800_1-epll_efpga6",
++};
++
++static const char *const fpga7_sel0[] = {
++	"ast1800_0-hpll_div200",
++	"ast1800_0-hpll_div100",
++	"ast1800_0-hpll_div50",
++	"ast1800_0-hpll_div40",
++	"ast1800_0-hpll_div25",
++	"ast1800_0-hpll_div20",
++	"ast1800_0-hpll_efpga7",
++	"ast1800_0-epll_efpga7",
++};
++
++static const char *const fpga7_sel1[] = {
++	"ast1800_1-hpll_div200",
++	"ast1800_1-hpll_div100",
++	"ast1800_1-hpll_div50",
++	"ast1800_1-hpll_div40",
++	"ast1800_1-hpll_div25",
++	"ast1800_1-hpll_div20",
++	"ast1800_1-hpll_efpga7",
++	"ast1800_1-epll_efpga7",
++};
++
++static const char *const uart_sel0[] = {
++	"ast1800_0-uxclk",
++	"ast1800_0-huxclk",
++};
++
++static const char *const uart_sel1[] = {
++	"ast1800_1-uxclk",
++	"ast1800_1-huxclk",
++};
++
++static const char *const uxclk_sel0[] = {
++	"ast1800_0-hpll_div5",
++	"ast1800_0-hpll_div4",
++	"ast1800_0-hpll_div2",
++	"ast1800_0-epll_div4",
++};
++
++static const char *const uxclk_sel1[] = {
++	"ast1800_1-hpll_div5",
++	"ast1800_1-hpll_div4",
++	"ast1800_1-hpll_div2",
++	"ast1800_1-epll_div4",
++};
++
++static const char *const uartclk_sel0[] = {
++	"ast1800_0-uartxclk",
++	"ast1800_0-huartxclk",
++};
++
++static const char *const uartclk_sel1[] = {
++	"ast1800_1-uartxclk",
++	"ast1800_1-huartxclk",
++};
++
++static const char *const spiclk_sel0[] = {
++	"ast1800_0-hpll",
++	"ast1800_0-epll",
++};
++
++static const char *const spiclk_sel1[] = {
++	"ast1800_1-hpll",
++	"ast1800_1-epll",
++};
++
++static const char *const i3cclk_sel0[] = {
++	"ast1800_0-hpll_div4",
++	"ast1800_0-lpll_div2",
++};
++
++static const char *const i3cclk_sel1[] = {
++	"ast1800_1-hpll_div4",
++	"ast1800_1-lpll_div2",
++};
++
++#define CREATE_CLK_NAME(id, suffix) kasprintf(GFP_KERNEL, "ast1800_%d-%s", id, suffix)
++
++static int AST1800_clk_init(struct device_node *ast1800_node)
++{
++	struct clk_hw_onecell_data *clk_data;
++	struct ast1800_reset *reset;
++	void __iomem *clk_base;
++	struct clk_hw **clks;
++	struct clk_hw *hw;
++	u32 val;
++	int ret;
++
++	int id = ida_simple_get(&ast1800_clk_ida, 0, 0, GFP_KERNEL);
++
++	clk_base = of_iomap(ast1800_node, 0);
++	WARN_ON(!clk_base);
++
++	clk_data = kzalloc(struct_size(clk_data, hws, AST1800_NUM_CLKS), GFP_KERNEL);
++	if (!clk_data)
++		return -ENOMEM;
++
++	clk_data->num = AST1800_NUM_CLKS;
++	clks = clk_data->hws;
++
++	reset = kzalloc(sizeof(*reset), GFP_KERNEL);
++	if (!reset)
++		return -ENOMEM;
++
++	reset->base = clk_base;
++
++	reset->rcdev.owner = THIS_MODULE;
++	reset->rcdev.nr_resets = AST1800_RESET_NUMS;
++	reset->rcdev.ops = &ast1800_reset_ops;
++	reset->rcdev.of_node = ast1800_node;
++
++	ret = reset_controller_register(&reset->rcdev);
++	if (ret) {
++		pr_err("soc1 failed to register reset controller\n");
++		return ret;
++	}
++	/*
++	 * Ast1800 A0 workaround:
++	 * I3C reset should assert all of the I3C controllers simultaneously.
++	 * Otherwise, it may lead to failure in accessing I3C registers.
++	 */
++	if (!(readl(clk_base) & BIT(16))) {
++		for (int i = AST1800_RESET_I3C0; i <= AST1800_RESET_I3C15; i++)
++			ast1800_reset_assert(&reset->rcdev, i);
++	}
++
++	hw = clk_hw_register_fixed_rate(NULL, CREATE_CLK_NAME(id, "clkin"),
++					NULL, 0, AST1800_CLK_25MHZ);
++	if (IS_ERR(hw))
++		return PTR_ERR(hw);
++	clks[AST1800_CLKIN] = hw;
++
++	/* HPLL 1000Mhz */
++	val = readl(clk_base + AST1800_HPLL_PARAM);
++	clks[AST1800_CLK_HPLL] = AST1800_calc_pll(CREATE_CLK_NAME(id, "hpll"),
++						  CREATE_CLK_NAME(id, "clkin"), val);
++
++	/* HPLL/2 huclk */
++	clks[AST1800_CLK_HPLL_DIV2] =
++		clk_hw_register_fixed_factor(NULL, CREATE_CLK_NAME(id, "hpll_div2"),
++					     CREATE_CLK_NAME(id, "hpll"), 0, 1, 2);
++
++	clks[AST1800_CLK_HPLL_DIV4] =
++		clk_hw_register_fixed_factor(NULL, CREATE_CLK_NAME(id, "hpll_div4"),
++					     CREATE_CLK_NAME(id, "hpll"), 0, 1, 4);
++
++	clks[AST1800_CLK_HPLL_DIV5] =
++		clk_hw_register_fixed_factor(NULL, CREATE_CLK_NAME(id, "hpll_div5"),
++					     CREATE_CLK_NAME(id, "hpll"), 0, 1, 5);
++
++	clks[AST1800_CLK_HPLL_DIV8] =
++		clk_hw_register_fixed_factor(NULL, CREATE_CLK_NAME(id, "hpll_div8"),
++					     CREATE_CLK_NAME(id, "hpll"), 0, 1, 8);
++
++	clks[AST1800_CLK_HPLL_DIV10] =
++		clk_hw_register_fixed_factor(NULL, CREATE_CLK_NAME(id, "hpll_div10"),
++					     CREATE_CLK_NAME(id, "hpll"), 0, 1, 10);
++
++	clks[AST1800_CLK_HPLL_DIV20] =
++		clk_hw_register_fixed_factor(NULL, CREATE_CLK_NAME(id, "hpll_div20"),
++					     CREATE_CLK_NAME(id, "hpll"), 0, 1, 10);
++
++	clks[AST1800_CLK_HPLL_DIV25] =
++		clk_hw_register_fixed_factor(NULL, CREATE_CLK_NAME(id, "hpll_div25"),
++					     CREATE_CLK_NAME(id, "hpll"), 0, 1, 10);
++
++	clks[AST1800_CLK_HPLL_DIV50] =
++		clk_hw_register_fixed_factor(NULL, CREATE_CLK_NAME(id, "hpll_div50"),
++					     CREATE_CLK_NAME(id, "hpll"), 0, 1, 10);
++
++	clks[AST1800_CLK_HPLL_DIV100] =
++		clk_hw_register_fixed_factor(NULL, CREATE_CLK_NAME(id, "hpll_div100"),
++					     CREATE_CLK_NAME(id, "hpll"), 0, 1, 10);
++
++	clks[AST1800_CLK_HPLL_DIV200] =
++		clk_hw_register_fixed_factor(NULL, CREATE_CLK_NAME(id, "hpll_div200"),
++					     CREATE_CLK_NAME(id, "hpll"), 0, 1, 10);
++
++	clks[AST1800_CLK_HPLL_DIV1000] =
++		clk_hw_register_fixed_factor(NULL, CREATE_CLK_NAME(id, "hpll_div1000"),
++					     CREATE_CLK_NAME(id, "hpll"), 0, 1, 10);
++
++	clks[AST1800_CLK_HPLL_EFPGA0] =
++		clk_hw_register_divider_table(NULL, CREATE_CLK_NAME(id, "hpll_div10"),
++					      CREATE_CLK_NAME(id, "hpll_efpga0"),
++					      0, clk_base + 0x98,
++					      0, 8, 0, ast1800_efpga_clk_div_table,
++					      &ast1800_clk_lock);
++
++	clks[AST1800_CLK_HPLL_EFPGA1] =
++		clk_hw_register_divider_table(NULL, CREATE_CLK_NAME(id, "hpll_div10"),
++					      CREATE_CLK_NAME(id, "hpll_efpga1"),
++					      0, clk_base + 0x98,
++					      8, 8, 0, ast1800_efpga_clk_div_table,
++					      &ast1800_clk_lock);
++
++	clks[AST1800_CLK_HPLL_EFPGA2] =
++		clk_hw_register_divider_table(NULL, CREATE_CLK_NAME(id, "hpll_div10"),
++					      CREATE_CLK_NAME(id, "hpll_efpga2"),
++					      0, clk_base + 0x98,
++					      16, 8, 0, ast1800_efpga_clk_div_table,
++					      &ast1800_clk_lock);
++
++	clks[AST1800_CLK_HPLL_EFPGA3] =
++		clk_hw_register_divider_table(NULL, CREATE_CLK_NAME(id, "hpll_div10"),
++					      CREATE_CLK_NAME(id, "hpll_efpga3"),
++					      0, clk_base + 0x98,
++					      24, 8, 0, ast1800_efpga_clk_div_table,
++					      &ast1800_clk_lock);
++
++	clks[AST1800_CLK_HPLL_EFPGA4] =
++		clk_hw_register_divider_table(NULL, CREATE_CLK_NAME(id, "hpll_div10"),
++					      CREATE_CLK_NAME(id, "hpll_efpga4"),
++					      0, clk_base + 0x94,
++					      0, 8, 0, ast1800_efpga_clk_div_table,
++					      &ast1800_clk_lock);
++
++	clks[AST1800_CLK_HPLL_EFPGA5] =
++		clk_hw_register_divider_table(NULL, CREATE_CLK_NAME(id, "hpll_div10"),
++					      CREATE_CLK_NAME(id, "hpll_efpga5"),
++					      0, clk_base + 0x94,
++					      8, 8, 0, ast1800_efpga_clk_div_table,
++					      &ast1800_clk_lock);
++
++	clks[AST1800_CLK_HPLL_EFPGA6] =
++		clk_hw_register_divider_table(NULL, CREATE_CLK_NAME(id, "hpll_div10"),
++					      CREATE_CLK_NAME(id, "hpll_efpga6"),
++					      0, clk_base + 0x94,
++					      16, 8, 0, ast1800_efpga_clk_div_table,
++					      &ast1800_clk_lock);
++
++	clks[AST1800_CLK_HPLL_EFPGA7] =
++		clk_hw_register_divider_table(NULL, CREATE_CLK_NAME(id, "hpll_div10"),
++					      CREATE_CLK_NAME(id, "hpll_efpga7"),
++					      0, clk_base + 0x94,
++					      24, 8, 0, ast1800_efpga_clk_div_table,
++					      &ast1800_clk_lock);
++
++	/* EPLL 960Mhz */
++	val = readl(clk_base + AST1800_EPLL_PARAM);
++	clks[AST1800_CLK_EPLL] = AST1800_calc_pll(CREATE_CLK_NAME(id, "epll"),
++						  CREATE_CLK_NAME(id, "clkin"), val);
++
++	// huxclk
++	clks[AST1800_CLK_EPLL_DIV4] =
++		clk_hw_register_fixed_factor(NULL, CREATE_CLK_NAME(id, "epll_div4"),
++					     CREATE_CLK_NAME(id, "epll"), 0, 1, 4);
++
++	clks[AST1800_CLK_EPLL_DIV8] =
++		clk_hw_register_fixed_factor(NULL, CREATE_CLK_NAME(id, "epll_div8"),
++					     CREATE_CLK_NAME(id, "epll"), 0, 1, 8);
++
++	clks[AST1800_CLK_EPLL_EFPGA0] =
++		clk_hw_register_divider_table(NULL, CREATE_CLK_NAME(id, "epll_div8"),
++					      CREATE_CLK_NAME(id, "epll_efpga0"),
++					      0, clk_base + 0x98,
++					      0, 8, 0, ast1800_efpga_clk_div_table,
++					      &ast1800_clk_lock);
++
++	clks[AST1800_CLK_EPLL_EFPGA1] =
++		clk_hw_register_divider_table(NULL, CREATE_CLK_NAME(id, "epll_div8"),
++					      CREATE_CLK_NAME(id, "epll_efpga1"),
++					      0, clk_base + 0x98,
++					      8, 8, 0, ast1800_efpga_clk_div_table,
++					      &ast1800_clk_lock);
++
++	clks[AST1800_CLK_EPLL_EFPGA2] =
++		clk_hw_register_divider_table(NULL, CREATE_CLK_NAME(id, "epll_div8"),
++					      CREATE_CLK_NAME(id, "epll_efpga2"),
++					      0, clk_base + 0x98,
++					      16, 8, 0, ast1800_efpga_clk_div_table,
++					      &ast1800_clk_lock);
++
++	clks[AST1800_CLK_EPLL_EFPGA3] =
++		clk_hw_register_divider_table(NULL, CREATE_CLK_NAME(id, "epll_div8"),
++					      CREATE_CLK_NAME(id, "epll_efpga3"),
++					      0, clk_base + 0x98,
++					      24, 8, 0, ast1800_efpga_clk_div_table,
++					      &ast1800_clk_lock);
++
++	clks[AST1800_CLK_EPLL_EFPGA4] =
++		clk_hw_register_divider_table(NULL, CREATE_CLK_NAME(id, "epll_div8"),
++					      CREATE_CLK_NAME(id, "epll_efpga4"),
++					      0, clk_base + 0x9c,
++					      0, 8, 0, ast1800_efpga_clk_div_table,
++					      &ast1800_clk_lock);
++
++	clks[AST1800_CLK_EPLL_EFPGA5] =
++		clk_hw_register_divider_table(NULL, CREATE_CLK_NAME(id, "epll_div8"),
++					      CREATE_CLK_NAME(id, "epll_efpga5"),
++					      0, clk_base + 0x9c,
++					      8, 8, 0, ast1800_efpga_clk_div_table,
++					      &ast1800_clk_lock);
++
++	clks[AST1800_CLK_EPLL_EFPGA6] =
++		clk_hw_register_divider_table(NULL, CREATE_CLK_NAME(id, "epll_div8"),
++					      CREATE_CLK_NAME(id, "epll_efpga6"),
++					      0, clk_base + 0x9c,
++					      16, 8, 0, ast1800_efpga_clk_div_table,
++					      &ast1800_clk_lock);
++
++	clks[AST1800_CLK_EPLL_EFPGA7] =
++		clk_hw_register_divider_table(NULL, CREATE_CLK_NAME(id, "epll_div8"),
++					      CREATE_CLK_NAME(id, "epll_efpga7"),
++					      0, clk_base + 0x9c,
++					      24, 8, 0, ast1800_efpga_clk_div_table,
++					      &ast1800_clk_lock);
++
++	/* LPLL 1200Mhz */
++	val = readl(clk_base + AST1800_LPLL_PARAM);
++	clks[AST1800_CLK_LPLL] = AST1800_calc_pll(CREATE_CLK_NAME(id, "lpll"),
++						  CREATE_CLK_NAME(id, "clkin"), val);
++
++	clks[AST1800_CLK_LPLL_DIV4] =
++		clk_hw_register_fixed_factor(NULL, CREATE_CLK_NAME(id, "lpll_div4"),
++					     CREATE_CLK_NAME(id, "lpll"), 0, 1, 4);
++
++	/* uxclk mux selection */
++	clks[AST1800_CLK_UXCLK] =
++		clk_hw_register_mux(NULL, CREATE_CLK_NAME(id, "uxclk"),
++				    (id == 0) ? uxclk_sel0 : uxclk_sel1,
++				    (id == 0) ? ARRAY_SIZE(uxclk_sel0) : ARRAY_SIZE(uxclk_sel1),
++				    0, clk_base + AST1800_CLK_SEL,
++				    8, 2, 0, &ast1800_clk_lock);
++
++	val = readl(clk_base + AST1800_UXCLK_CTRL);
++	clks[AST1800_CLK_UARTX] = AST1800_calc_uclk(CREATE_CLK_NAME(id, "uartxclk"), val);
++
++	/* huxclk mux selection */
++	clks[AST1800_CLK_HUXCLK] =
++		clk_hw_register_mux(NULL, CREATE_CLK_NAME(id, "huxclk"),
++				    (id == 0) ? uxclk_sel0 : uxclk_sel1,
++				    (id == 0) ? ARRAY_SIZE(uxclk_sel0) : ARRAY_SIZE(uxclk_sel1),
++				    0, clk_base + AST1800_CLK_SEL,
++				    10, 2, 0, &ast1800_clk_lock);
++
++	val = readl(clk_base + AST1800_HUXCLK_CTRL);
++	clks[AST1800_CLK_HUARTX] = AST1800_calc_huclk(CREATE_CLK_NAME(id, "huartxclk"), val);
++
++	clks[AST1800_CLK_UART] =
++		clk_hw_register_mux(NULL, CREATE_CLK_NAME(id, "uart"),
++				    (id == 0) ? uart_sel0 : uart_sel1,
++				    (id == 0) ? ARRAY_SIZE(uart_sel0) : ARRAY_SIZE(uart_sel1),
++				    0, clk_base + AST1800_CLK_SEL,
++				    7, 1, 0, &ast1800_clk_lock);
++
++	/* AHB CLK = 200Mhz */
++	clks[AST1800_CLK_AHB] =
++		clk_hw_register_divider_table(NULL, CREATE_CLK_NAME(id, "ahb"),
++					      CREATE_CLK_NAME(id, "hpll_div5"),
++					      0, clk_base + AST1800_CLK_SEL,
++					      0, 2, 0, ast1800_clk_div_table, &ast1800_clk_lock);
++
++	/* APB CLK = 100Mhz */
++	clks[AST1800_CLK_APB] =
++		clk_hw_register_fixed_factor(NULL, CREATE_CLK_NAME(id, "apb"),
++					     CREATE_CLK_NAME(id, "ahb"), 0, 1, 2);
++
++	clks[AST1800_CLK_I3C] =
++		clk_hw_register_mux(NULL, CREATE_CLK_NAME(id, "i3cclk"),
++				    (id == 0) ? i3cclk_sel0 : i3cclk_sel1,
++				    (id == 0) ? ARRAY_SIZE(i3cclk_sel0) : ARRAY_SIZE(i3cclk_sel1),
++				    0, clk_base + AST1800_CLK_SEL,
++				    12, 1, 0, &ast1800_clk_lock);
++
++	clks[AST1800_CLK_GATE_I3C0] =
++		AST1800_clk_hw_register_gate(NULL, CREATE_CLK_NAME(id, "i3c0clk-gate"),
++					     CREATE_CLK_NAME(id, "i3cclk"),
++					     0, clk_base + AST1800_CLK_STOP2,
++					     0, 0, &ast1800_clk_lock);
++
++	clks[AST1800_CLK_GATE_I3C1] =
++		AST1800_clk_hw_register_gate(NULL, CREATE_CLK_NAME(id, "i3c1clk-gate"),
++					     CREATE_CLK_NAME(id, "i3cclk"),
++					     0, clk_base + AST1800_CLK_STOP2,
++					     1, 0, &ast1800_clk_lock);
++
++	clks[AST1800_CLK_GATE_I3C2] =
++		AST1800_clk_hw_register_gate(NULL, CREATE_CLK_NAME(id, "i3c2clk-gate"),
++					     CREATE_CLK_NAME(id, "i3cclk"),
++					     0, clk_base + AST1800_CLK_STOP2,
++					     2, 0, &ast1800_clk_lock);
++
++	clks[AST1800_CLK_GATE_I3C3] =
++		AST1800_clk_hw_register_gate(NULL, CREATE_CLK_NAME(id, "i3c3clk-gate"),
++					     CREATE_CLK_NAME(id, "i3cclk"),
++					     0, clk_base + AST1800_CLK_STOP2,
++					     3, 0, &ast1800_clk_lock);
++
++	clks[AST1800_CLK_GATE_I3C4] =
++		AST1800_clk_hw_register_gate(NULL, CREATE_CLK_NAME(id, "i3c4clk-gate"),
++					     CREATE_CLK_NAME(id, "i3cclk"),
++					     0, clk_base + AST1800_CLK_STOP2,
++					     4, 0, &ast1800_clk_lock);
++
++	clks[AST1800_CLK_GATE_I3C5] =
++		AST1800_clk_hw_register_gate(NULL, CREATE_CLK_NAME(id, "i3c5clk-gate"),
++					     CREATE_CLK_NAME(id, "i3cclk"),
++					     0, clk_base + AST1800_CLK_STOP2,
++					     5, 0, &ast1800_clk_lock);
++
++	clks[AST1800_CLK_GATE_I3C6] =
++		AST1800_clk_hw_register_gate(NULL, CREATE_CLK_NAME(id, "i3c6clk-gate"),
++					     CREATE_CLK_NAME(id, "i3cclk"),
++					     0, clk_base + AST1800_CLK_STOP2,
++					     6, 0, &ast1800_clk_lock);
++
++	clks[AST1800_CLK_GATE_I3C7] =
++		AST1800_clk_hw_register_gate(NULL, CREATE_CLK_NAME(id, "i3c7clk-gate"),
++					     CREATE_CLK_NAME(id, "i3cclk"),
++					     0, clk_base + AST1800_CLK_STOP2,
++					     7, 0, &ast1800_clk_lock);
++
++	clks[AST1800_CLK_GATE_I3C8] =
++		AST1800_clk_hw_register_gate(NULL, CREATE_CLK_NAME(id, "i3c8clk-gate"),
++					     CREATE_CLK_NAME(id, "i3cclk"),
++					     0, clk_base + AST1800_CLK_STOP2,
++					     8, 0, &ast1800_clk_lock);
++
++	clks[AST1800_CLK_GATE_I3C9] =
++		AST1800_clk_hw_register_gate(NULL, CREATE_CLK_NAME(id, "i3c9clk-gate"),
++					     CREATE_CLK_NAME(id, "i3cclk"),
++					     0, clk_base + AST1800_CLK_STOP2,
++					     9, 0, &ast1800_clk_lock);
++
++	clks[AST1800_CLK_GATE_I3C10] =
++		AST1800_clk_hw_register_gate(NULL, CREATE_CLK_NAME(id, "i3c10clk-gate"),
++					     CREATE_CLK_NAME(id, "i3cclk"),
++					     0, clk_base + AST1800_CLK_STOP2,
++					     10, 0, &ast1800_clk_lock);
++
++	clks[AST1800_CLK_GATE_I3C11] =
++		AST1800_clk_hw_register_gate(NULL, CREATE_CLK_NAME(id, "i3c11clk-gate"),
++					     CREATE_CLK_NAME(id, "i3cclk"),
++					     0, clk_base + AST1800_CLK_STOP2,
++					     11, 0, &ast1800_clk_lock);
++
++	clks[AST1800_CLK_GATE_I3C12] =
++		AST1800_clk_hw_register_gate(NULL, CREATE_CLK_NAME(id, "i3c12clk-gate"),
++					     CREATE_CLK_NAME(id, "i3cclk"),
++					     0, clk_base + AST1800_CLK_STOP2,
++					     12, 0, &ast1800_clk_lock);
++
++	clks[AST1800_CLK_GATE_I3C13] =
++		AST1800_clk_hw_register_gate(NULL, CREATE_CLK_NAME(id, "i3c13clk-gate"),
++					     CREATE_CLK_NAME(id, "i3cclk"),
++					     0, clk_base + AST1800_CLK_STOP2,
++					     13, 0, &ast1800_clk_lock);
++
++	clks[AST1800_CLK_GATE_I3C14] =
++		AST1800_clk_hw_register_gate(NULL, CREATE_CLK_NAME(id, "i3c14clk-gate"),
++					     CREATE_CLK_NAME(id, "i3cclk"),
++					     0, clk_base + AST1800_CLK_STOP2,
++					     14, 0, &ast1800_clk_lock);
++
++	clks[AST1800_CLK_GATE_I3C15] =
++		AST1800_clk_hw_register_gate(NULL, CREATE_CLK_NAME(id, "i3c15clk-gate"),
++					     CREATE_CLK_NAME(id, "i3cclk"),
++					     0, clk_base + AST1800_CLK_STOP2,
++					     15, 0, &ast1800_clk_lock);
++
++	clks[AST1800_CLK_EFPGA7] =
++		clk_hw_register_mux(NULL, CREATE_CLK_NAME(id, "fpga7"),
++				    (id == 0) ? uart_sel0 : uart_sel1,
++				    (id == 0) ? ARRAY_SIZE(uart_sel0) : ARRAY_SIZE(uart_sel1),
++				    0, clk_base + AST1800_CLK_SEL,
++				    7, 1, 0, &ast1800_clk_lock);
++
++	of_clk_add_hw_provider(ast1800_node, of_clk_hw_onecell_get, clk_data);
++
++	return 0;
++};
++
++CLK_OF_DECLARE_DRIVER(ast1800, "aspeed,ast1800-scu", AST1800_clk_init);
 diff --git a/drivers/clk/clk-ast2600.c b/drivers/clk/clk-ast2600.c
-index 909c3137c..3b59b2172 100644
+old mode 100644
+new mode 100755
+index 909c3137c..3b59b2172
 --- a/drivers/clk/clk-ast2600.c
 +++ b/drivers/clk/clk-ast2600.c
 @@ -19,7 +19,7 @@
@@ -1439,10 +2314,10 @@
  	if (ret)
 diff --git a/drivers/clk/clk-ast2700.c b/drivers/clk/clk-ast2700.c
 new file mode 100644
-index 000000000..3442849f1
+index 000000000..ba7b7974f
 --- /dev/null
 +++ b/drivers/clk/clk-ast2700.c
-@@ -0,0 +1,1255 @@
+@@ -0,0 +1,1259 @@
 +// SPDX-License-Identifier: GPL-2.0
 +/*
 + * Copyright (c) 2024 ASPEED Technology Inc.
@@ -2150,13 +3025,13 @@
 +	GATE_CLK(SCU1_CLK_GATE_MAC2CLK, CLK_GATE_ASPEED, "mac2clk-gate", NULL,
 +		 SCU1_CLK_STOP, 10, 0),
 +	GATE_CLK(SCU1_CLK_GATE_UART0CLK, CLK_GATE_ASPEED, "uart0clk-gate", uart0clk,
-+		 SCU1_CLK_STOP, 11, 0),
++		 SCU1_CLK_STOP, 11, CLK_IS_CRITICAL),
 +	GATE_CLK(SCU1_CLK_GATE_UART1CLK, CLK_GATE_ASPEED, "uart1clk-gate", uart1clk,
-+		 SCU1_CLK_STOP, 12, 0),
++		 SCU1_CLK_STOP, 12, CLK_IS_CRITICAL),
 +	GATE_CLK(SCU1_CLK_GATE_UART2CLK, CLK_GATE_ASPEED, "uart2clk-gate", uart2clk,
-+		 SCU1_CLK_STOP, 13, 0),
++		 SCU1_CLK_STOP, 13, CLK_IS_CRITICAL),
 +	GATE_CLK(SCU1_CLK_GATE_UART3CLK, CLK_GATE_ASPEED, "uart3clk-gate", uart3clk,
-+		 SCU1_CLK_STOP, 14, 0),
++		 SCU1_CLK_STOP, 14, CLK_IS_CRITICAL),
 +	GATE_CLK(SCU1_CLK_GATE_I2CCLK, CLK_GATE_ASPEED, "i2cclk-gate", NULL, SCU1_CLK_STOP, 15, 0),
 +	GATE_CLK(SCU1_CLK_GATE_I3C0CLK, CLK_GATE_ASPEED, "i3c0clk-gate", soc1_i3c,
 +		 SCU1_CLK_STOP, 16, 0),
@@ -2463,10 +3338,14 @@
 +	u32 reg[3];
 +	int ret;
 +
-+	if (readl(clk_ctrl->base + SCU1_REVISION_ID) & REVISION_ID)
-+		reg[0] = AST2700_DEF_MAC12_DELAY_1G_A1;
-+	else
++	if (readl(clk_ctrl->base + SCU1_REVISION_ID) & REVISION_ID) {
++		if ((readl(clk_ctrl->base + SCU1_MAC12_CLK_DLY) & GENMASK(25, 0)) == 0)
++			reg[0] = AST2700_DEF_MAC12_DELAY_1G_A1;
++		else
++			reg[0] = readl(clk_ctrl->base + SCU1_MAC12_CLK_DLY);
++	} else {
 +		reg[0] = AST2700_DEF_MAC12_DELAY_1G_A0;
++	}
 +	reg[1] = AST2700_DEF_MAC12_DELAY_100M;
 +	reg[2] = AST2700_DEF_MAC12_DELAY_10M;
 +
@@ -2698,6 +3577,1269 @@
 +	return platform_driver_register(&ast2700_scu_driver);
 +}
 +arch_initcall(clk_ast2700_init);
+diff --git a/drivers/clk/clk-ast2700a0.c b/drivers/clk/clk-ast2700a0.c
+new file mode 100755
+index 000000000..b4fa226d3
+--- /dev/null
++++ b/drivers/clk/clk-ast2700a0.c
+@@ -0,0 +1,1257 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (c) 2024 ASPEED Technology Inc.
++ * Author: Ryan Chen <ryan_chen@aspeedtech.com>
++ */
++
++#include <linux/clk-provider.h>
++#include <linux/io.h>
++#include <linux/mod_devicetable.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++#include <linux/units.h>
++#include <soc/aspeed/reset-aspeed.h>
++
++#include <dt-bindings/clock/aspeed,ast2700-scu.h>
++
++#define SCU_CLK_12MHZ	(12 * HZ_PER_MHZ)
++#define SCU_CLK_24MHZ	(24 * HZ_PER_MHZ)
++#define SCU_CLK_25MHZ	(25 * HZ_PER_MHZ)
++#define SCU_CLK_192MHZ	(192 * HZ_PER_MHZ)
++
++/* SOC0 */
++#define SCU0_HWSTRAP1		0x010
++#define SCU0_CLK_STOP		0x240
++#define SCU0_CLK_SEL1		0x280
++#define SCU0_CLK_SEL2		0x284
++#define GET_USB_REFCLK_DIV(x)	((GENMASK(23, 20) & (x)) >> 20)
++#define UART_DIV13_EN		BIT(30)
++#define SCU0_HPLL_PARAM		0x300
++#define SCU0_DPLL_PARAM		0x308
++#define SCU0_MPLL_PARAM		0x310
++#define SCU0_D0CLK_PARAM	0x320
++#define SCU0_D1CLK_PARAM	0x330
++#define SCU0_CRT0CLK_PARAM	0x340
++#define SCU0_CRT1CLK_PARAM	0x350
++#define SCU0_MPHYCLK_PARAM	0x360
++
++/* SOC1 */
++#define SCU1_REVISION_ID	0x0
++#define REVISION_ID		GENMASK(23, 16)
++#define SCU1_CLK_STOP		0x240
++#define SCU1_CLK_STOP2		0x260
++#define SCU1_CLK_SEL1		0x280
++#define SCU1_CLK_SEL2		0x284
++#define SCU1_CLK_I3C_DIV_MASK	GENMASK(25, 23)
++#define SCU1_CLK_I3C_DIV(n)	((n) - 1)
++#define UXCLK_MASK		GENMASK(1, 0)
++#define HUXCLK_MASK		GENMASK(4, 3)
++#define SCU1_HPLL_PARAM		0x300
++#define SCU1_APLL_PARAM		0x310
++#define SCU1_DPLL_PARAM		0x320
++#define SCU1_UXCLK_CTRL		0x330
++#define SCU1_HUXCLK_CTRL	0x334
++#define SCU1_MAC12_CLK_DLY	0x390
++#define SCU1_MAC12_CLK_DLY_100M	0x394
++#define SCU1_MAC12_CLK_DLY_10M	0x398
++
++/*
++ * MAC Clock Delay settings
++ */
++#define MAC_CLK_RMII1_50M_RCLK_O_CTRL	BIT(30)
++#define   MAC_CLK_RMII1_50M_RCLK_O_DIS	0
++#define   MAC_CLK_RMII1_50M_RCLK_O_EN	1
++#define MAC_CLK_RMII0_50M_RCLK_O_CTRL	BIT(29)
++#define   MAC_CLK_RMII0_5M_RCLK_O_DIS	0
++#define   MAC_CLK_RMII0_5M_RCLK_O_EN	1
++#define MAC_CLK_RMII_TXD_FALLING_2	BIT(27)
++#define MAC_CLK_RMII_TXD_FALLING_1	BIT(26)
++#define MAC_CLK_RXCLK_INV_2		BIT(25)
++#define MAC_CLK_RXCLK_INV_1		BIT(24)
++#define MAC_CLK_1G_INPUT_DELAY_2	GENMASK(23, 18)
++#define MAC_CLK_1G_INPUT_DELAY_1	GENMASK(17, 12)
++#define MAC_CLK_1G_OUTPUT_DELAY_2	GENMASK(11, 6)
++#define MAC_CLK_1G_OUTPUT_DELAY_1	GENMASK(5, 0)
++
++#define MAC_CLK_100M_10M_RESERVED	GENMASK(31, 26)
++#define MAC_CLK_100M_10M_RXCLK_INV_2	BIT(25)
++#define MAC_CLK_100M_10M_RXCLK_INV_1	BIT(24)
++#define MAC_CLK_100M_10M_INPUT_DELAY_2	GENMASK(23, 18)
++#define MAC_CLK_100M_10M_INPUT_DELAY_1	GENMASK(17, 12)
++#define MAC_CLK_100M_10M_OUTPUT_DELAY_2	GENMASK(11, 6)
++#define MAC_CLK_100M_10M_OUTPUT_DELAY_1	GENMASK(5, 0)
++
++#define AST2700_DEF_MAC12_DELAY_1G_A0	0x00CF4D75
++#define AST2700_DEF_MAC12_DELAY_1G_A1	0x00C70C73
++#define AST2700_DEF_MAC12_DELAY_100M	0x00410410
++#define AST2700_DEF_MAC12_DELAY_10M	0x00410410
++
++struct mac_delay_config {
++	u32 tx_delay_1000;
++	u32 rx_delay_1000;
++	u32 tx_delay_100;
++	u32 rx_delay_100;
++	u32 tx_delay_10;
++	u32 rx_delay_10;
++};
++
++enum ast2700_clk_type {
++	CLK_MUX,
++	CLK_PLL,
++	CLK_HPLL,
++	CLK_GATE,
++	CLK_MISC,
++	CLK_FIXED,
++	DCLK_FIXED,
++	CLK_DIVIDER,
++	CLK_UART_PLL,
++	CLK_FIXED_FACTOR,
++	CLK_GATE_ASPEED,
++};
++
++struct ast2700_clk_fixed_factor_data {
++	const struct clk_parent_data *parent;
++	unsigned int mult;
++	unsigned int div;
++};
++
++struct ast2700_clk_gate_data {
++	const struct clk_parent_data *parent;
++	u32 flags;
++	u32 reg;
++	u8 bit;
++};
++
++struct ast2700_clk_mux_data {
++	const struct clk_parent_data *parents;
++	unsigned int num_parents;
++	u8 bit_shift;
++	u8 bit_width;
++	u32 reg;
++};
++
++struct ast2700_clk_div_data {
++	const struct clk_div_table *div_table;
++	const struct clk_parent_data *parent;
++	u8 bit_shift;
++	u8 bit_width;
++	u32 reg;
++};
++
++struct ast2700_clk_pll_data {
++	const struct clk_parent_data *parent;
++	u32 reg;
++};
++
++struct ast2700_clk_fixed_rate_data {
++	unsigned long fixed_rate;
++};
++
++struct ast2700_clk_info {
++	const char *name;
++	u8 clk_idx;
++	u32 reg;
++	u32 type;
++	union {
++		struct ast2700_clk_fixed_factor_data factor;
++		struct ast2700_clk_fixed_rate_data rate;
++		struct ast2700_clk_gate_data gate;
++		struct ast2700_clk_div_data div;
++		struct ast2700_clk_pll_data pll;
++		struct ast2700_clk_mux_data mux;
++	} data;
++};
++
++struct ast2700_clk_data {
++	struct ast2700_clk_info const *clk_info;
++	unsigned int nr_clks;
++	const int scu;
++};
++
++struct ast2700_clk_ctrl {
++	const struct ast2700_clk_data *clk_data;
++	struct device *dev;
++	void __iomem *base;
++	spinlock_t lock; /* clk lock */
++};
++
++static const struct clk_div_table ast2700_rgmii_div_table[] = {
++	{ 0x0, 4 },
++	{ 0x1, 4 },
++	{ 0x2, 6 },
++	{ 0x3, 8 },
++	{ 0x4, 10 },
++	{ 0x5, 12 },
++	{ 0x6, 14 },
++	{ 0x7, 16 },
++	{ 0 }
++};
++
++static const struct clk_div_table ast2700_rmii_div_table[] = {
++	{ 0x0, 8 },
++	{ 0x1, 8 },
++	{ 0x2, 12 },
++	{ 0x3, 16 },
++	{ 0x4, 20 },
++	{ 0x5, 24 },
++	{ 0x6, 28 },
++	{ 0x7, 32 },
++	{ 0 }
++};
++
++static const struct clk_div_table ast2700_clk_div_table[] = {
++	{ 0x0, 2 },
++	{ 0x1, 2 },
++	{ 0x2, 3 },
++	{ 0x3, 4 },
++	{ 0x4, 5 },
++	{ 0x5, 6 },
++	{ 0x6, 7 },
++	{ 0x7, 8 },
++	{ 0 }
++};
++
++static const struct clk_div_table ast2700_clk_div_table2[] = {
++	{ 0x0, 2 },
++	{ 0x1, 4 },
++	{ 0x2, 6 },
++	{ 0x3, 8 },
++	{ 0x4, 10 },
++	{ 0x5, 12 },
++	{ 0x6, 14 },
++	{ 0x7, 16 },
++	{ 0 }
++};
++
++static const struct clk_div_table ast2700_hclk_div_table[] = {
++	{ 0x0, 6 },
++	{ 0x1, 5 },
++	{ 0x2, 4 },
++	{ 0x3, 7 },
++	{ 0 }
++};
++
++static const struct clk_div_table ast2700a0_hclk_div_table[] = {
++	{ 0x0, 4 },
++	{ 0x1, 4 },
++	{ 0x2, 6 },
++	{ 0x3, 8 },
++	{ 0 }
++};
++
++static const struct clk_div_table ast2700_clk_uart_div_table[] = {
++	{ 0x0, 1 },
++	{ 0x1, 13 },
++	{ 0 }
++};
++
++static const struct clk_parent_data soc0_clkin[] = {
++	{ .fw_name = "soc0-clkin", .name = "soc0-clkin" },
++};
++
++static const struct clk_parent_data pspclk[] = {
++	{ .fw_name = "pspclk", .name = "pspclk" },
++};
++
++static const struct clk_parent_data soc0_mpll_div8[] = {
++	{ .fw_name = "soc0-mpll_div8", .name = "soc0-mpll_div8" },
++};
++
++static const struct clk_parent_data mphysrc[] = {
++	{ .fw_name = "mphysrc", .name = "mphysrc" },
++};
++
++static const struct clk_parent_data u2phy_refclksrc[] = {
++	{ .fw_name = "u2phy_refclksrc", .name = "u2phy_refclksrc" },
++};
++
++static const struct clk_parent_data soc0_hpll[] = {
++	{ .fw_name = "soc0-hpll", .name = "soc0-hpll" },
++};
++
++static const struct clk_parent_data soc0_mpll[] = {
++	{ .fw_name = "soc0-mpll", .name = "soc0-mpll" },
++};
++
++static const struct clk_parent_data axi0clk[] = {
++	{ .fw_name = "axi0clk", .name = "axi0clk" },
++};
++
++static const struct clk_parent_data soc0_ahbmux[] = {
++	{ .fw_name = "soc0-ahbmux", .name = "soc0-ahbmux" },
++};
++
++static const struct clk_parent_data soc0_ahb[] = {
++	{ .fw_name = "soc0-ahb", .name = "soc0-ahb" },
++};
++
++static const struct clk_parent_data soc0_uartclk[] = {
++	{ .fw_name = "soc0-uartclk", .name = "soc0-uartclk" },
++};
++
++static const struct clk_parent_data emmcclk[] = {
++	{ .fw_name = "emmcclk", .name = "emmcclk" },
++};
++
++static const struct clk_parent_data emmcsrc_mux[] = {
++	{ .fw_name = "emmcsrc-mux", .name = "emmcsrc-mux" },
++};
++
++static const struct clk_parent_data soc1_clkin[] = {
++	{ .fw_name = "soc1-clkin", .name = "soc1-clkin" },
++};
++
++static const struct clk_parent_data soc1_hpll[] = {
++	{ .fw_name = "soc1-hpll", .name = "soc1-hpll" },
++};
++
++static const struct clk_parent_data soc1_apll[] = {
++	{ .fw_name = "soc1-apll", .name = "soc1-apll" },
++};
++
++static const struct clk_parent_data sdclk[] = {
++	{ .fw_name = "sdclk", .name = "sdclk" },
++};
++
++static const struct clk_parent_data sdclk_mux[] = {
++	{ .fw_name = "sdclk-mux", .name = "sdclk-mux" },
++};
++
++static const struct clk_parent_data huartxclk[] = {
++	{ .fw_name = "huartxclk", .name = "huartxclk" },
++};
++
++static const struct clk_parent_data uxclk[] = {
++	{ .fw_name = "uxclk", .name = "uxclk" },
++};
++
++static const struct clk_parent_data huxclk[] = {
++	{ .fw_name = "huxclk", .name = "huxclk" },
++};
++
++static const struct clk_parent_data uart0clk[] = {
++	{ .fw_name = "uart0clk", .name = "uart0clk" },
++};
++
++static const struct clk_parent_data uart1clk[] = {
++	{ .fw_name = "uart1clk", .name = "uart1clk" },
++};
++
++static const struct clk_parent_data uart2clk[] = {
++	{ .fw_name = "uart2clk", .name = "uart2clk" },
++};
++
++static const struct clk_parent_data uart3clk[] = {
++	{ .fw_name = "uart3clk", .name = "uart3clk" },
++};
++
++static const struct clk_parent_data uart5clk[] = {
++	{ .fw_name = "uart5clk", .name = "uart5clk" },
++};
++
++static const struct clk_parent_data uart4clk[] = {
++	{ .fw_name = "uart4clk", .name = "uart4clk" },
++};
++
++static const struct clk_parent_data uart6clk[] = {
++	{ .fw_name = "uart6clk", .name = "uart6clk" },
++};
++
++static const struct clk_parent_data uart7clk[] = {
++	{ .fw_name = "uart7clk", .name = "uart7clk" },
++};
++
++static const struct clk_parent_data uart8clk[] = {
++	{ .fw_name = "uart8clk", .name = "uart8clk" },
++};
++
++static const struct clk_parent_data uart9clk[] = {
++	{ .fw_name = "uart9clk", .name = "uart9clk" },
++};
++
++static const struct clk_parent_data uart10clk[] = {
++	{ .fw_name = "uart10clk", .name = "uart10clk" },
++};
++
++static const struct clk_parent_data uart11clk[] = {
++	{ .fw_name = "uart11clk", .name = "uart11clk" },
++};
++
++static const struct clk_parent_data uart12clk[] = {
++	{ .fw_name = "uart12clk", .name = "uart12clk" },
++};
++
++static const struct clk_parent_data uart13clk[] = {
++	{ .fw_name = "uart13clk", .name = "uart13clk" },
++};
++
++static const struct clk_parent_data uart14clk[] = {
++	{ .fw_name = "uart14clk", .name = "uart14clk" },
++};
++
++static const struct clk_parent_data uart15clk[] = {
++	{ .fw_name = "uart15clk", .name = "uart15clk" },
++};
++
++static const struct clk_parent_data uart16clk[] = {
++	{ .fw_name = "uart16clk", .name = "uart16clk" },
++};
++
++static const struct clk_parent_data soc1_ahb[] = {
++	{ .fw_name = "soc1-ahb", .name = "soc1-ahb" },
++};
++
++static const struct clk_parent_data soc1_i3c[] = {
++	{ .fw_name = "soc1-i3c", .name = "soc1-i3c" },
++};
++
++static const struct clk_parent_data canclk[] = {
++	{ .fw_name = "canclk", .name = "canclk" },
++};
++
++static const struct clk_parent_data rmii[] = {
++	{ .fw_name = "rmii", .name = "rmii" },
++};
++
++static const struct clk_parent_data d_clk_sels[] = {
++	{ .fw_name = "soc0-hpll_div2", .name = "soc0-hpll_div2" },
++	{ .fw_name = "soc0-mpll_div2", .name = "soc0-mpll_div2" },
++};
++
++static const struct clk_parent_data hclk_clk_sels[] = {
++	{ .fw_name = "soc0-hpll", .name = "soc0-hpll" },
++	{ .fw_name = "soc0-mpll", .name = "soc0-mpll" },
++};
++
++static const struct clk_parent_data mhpll_clk_sels[] = {
++	{ .fw_name = "soc0-mpll", .name = "soc0-mpll" },
++	{ .fw_name = "soc0-hpll", .name = "soc0-hpll" },
++};
++
++static const struct clk_parent_data mphy_clk_sels[] = {
++	{ .fw_name = "soc0-mpll", .name = "soc0-mpll" },
++	{ .fw_name = "soc0-hpll", .name = "soc0-hpll" },
++	{ .fw_name = "soc0-dpll", .name = "soc0-dpll" },
++	{ .fw_name = "soc0-clk192Mhz", .name = "soc0-clk192Mhz" },
++};
++
++static const struct clk_parent_data psp_clk_sels[] = {
++	{ .fw_name = "soc0-mpll", .name = "soc0-mpll" },
++	{ .fw_name = "soc0-hpll", .name = "soc0-hpll" },
++	{ .fw_name = "soc0-hpll", .name = "soc0-hpll" },
++	{ .fw_name = "soc0-hpll", .name = "soc0-hpll" },
++	{ .fw_name = "soc0-mpll_div2", .name = "soc0-mpll_div2" },
++	{ .fw_name = "soc0-hpll_div2", .name = "soc0-hpll_div2" },
++	{ .fw_name = "soc0-hpll", .name = "soc0-hpll" },
++	{ .fw_name = "soc0-hpll", .name = "soc0-hpll" },
++};
++
++static const struct clk_parent_data uart_clk_sels[] = {
++	{ .fw_name = "soc0-clk24Mhz", .name = "soc0-clk24Mhz" },
++	{ .fw_name = "soc0-clk192Mhz", .name = "soc0-clk192Mhz" },
++};
++
++static const struct clk_parent_data emmc_clk_sels[] = {
++	{ .fw_name = "soc0-mpll_div4", .name = "soc0-mpll_div4" },
++	{ .fw_name = "soc0-hpll_div4", .name = "soc0-hpll_div4" },
++};
++
++static const struct clk_parent_data sdio_clk_sels[] = {
++	{ .fw_name = "soc1-hpll", .name = "soc1-hpll" },
++	{ .fw_name = "soc1-apll", .name = "soc1-apll" },
++};
++
++static const struct clk_parent_data ux_clk_sels[] = {
++	{ .fw_name = "soc1-apll_div4", .name = "soc1-apll_div4" },
++	{ .fw_name = "soc1-apll_div2", .name = "soc1-apll_div2" },
++	{ .fw_name = "soc1-apll", .name = "soc1-apll" },
++	{ .fw_name = "soc1-hpll", .name = "soc1-hpll" },
++};
++
++static const struct clk_parent_data uartx_clk_sels[] = {
++	{ .fw_name = "uartxclk", .name = "uartxclk" },
++	{ .fw_name = "huartxclk", .name = "huartxclk" },
++};
++
++#define FIXED_CLK(_id, _name, _rate) \
++	[_id] = { \
++		.type = CLK_FIXED, \
++		.name = _name, \
++		.data = { .rate = { .fixed_rate = _rate, } }, \
++	}
++
++#define PLL_CLK(_id, _type, _name, _parent, _reg) \
++	[_id] = { \
++		.type = _type, \
++		.name = _name, \
++		.data = { .pll = { .parent = _parent, .reg = _reg, } }, \
++	}
++
++#define MUX_CLK(_id, _name, _parents, _num_parents, _reg, _shift, _width) \
++	[_id] = { \
++		.type = CLK_MUX, \
++		.name = _name, \
++		.data = { \
++			.mux = { \
++				.parents = _parents, \
++				.num_parents = _num_parents, \
++				.reg = _reg, \
++				.bit_shift = _shift, \
++				.bit_width = _width, \
++			}, \
++		}, \
++	}
++
++#define DIVIDER_CLK(_id, _name, _parent, _reg, _shift, _width, _div_table) \
++	[_id] = { \
++		.type = CLK_DIVIDER, \
++		.name = _name, \
++		.data = { \
++			.div = { \
++				.parent = _parent, \
++				.reg = _reg, \
++				.bit_shift = _shift, \
++				.bit_width = _width, \
++				.div_table = _div_table, \
++			}, \
++		}, \
++	}
++
++#define FIXED_FACTOR_CLK(_id, _name, _parent, _mult, _div) \
++	[_id] = { \
++		.type = CLK_FIXED_FACTOR, \
++		.name = _name, \
++		.data = { .factor = { .parent = _parent, .mult = _mult, .div = _div, } }, \
++	}
++
++#define GATE_CLK(_id, _type, _name, _parent, _reg, _bit, _flags) \
++	[_id] = { \
++		.type = _type, \
++		.name = _name, \
++		.data = { \
++			.gate = { \
++				.parent = _parent, \
++				.reg = _reg, \
++				.bit = _bit, \
++				.flags = _flags, \
++			}, \
++		}, \
++	}
++
++static const struct ast2700_clk_info ast2700a0_scu0_clk_info[] __initconst = {
++	FIXED_CLK(SCU0_CLKIN, "soc0-clkin", SCU_CLK_25MHZ),
++	FIXED_CLK(SCU0_CLK_24M, "soc0-clk24Mhz", SCU_CLK_24MHZ),
++	FIXED_CLK(SCU0_CLK_192M, "soc0-clk192Mhz", SCU_CLK_192MHZ),
++	FIXED_CLK(SCU0_CLK_U2PHY_CLK12M, "u2phy_clk12m", SCU_CLK_12MHZ),
++	PLL_CLK(SCU0_CLK_HPLL, CLK_HPLL, "soc0-hpll", soc0_clkin, SCU0_HPLL_PARAM),
++	PLL_CLK(SCU0_CLK_DPLL, CLK_PLL, "soc0-dpll", soc0_clkin, SCU0_DPLL_PARAM),
++	PLL_CLK(SCU0_CLK_MPLL, CLK_PLL, "soc0-mpll", soc0_clkin, SCU0_MPLL_PARAM),
++	PLL_CLK(SCU0_CLK_D0, DCLK_FIXED, "d0clk", NULL, SCU0_D0CLK_PARAM),
++	PLL_CLK(SCU0_CLK_D1, DCLK_FIXED, "d1clk", NULL, SCU0_D1CLK_PARAM),
++	PLL_CLK(SCU0_CLK_CRT0, DCLK_FIXED, "crt0clk", NULL, SCU0_CRT0CLK_PARAM),
++	PLL_CLK(SCU0_CLK_CRT1, DCLK_FIXED, "crt1clk", NULL, SCU0_CRT1CLK_PARAM),
++	PLL_CLK(SCU0_CLK_MPHY, CLK_MISC, "mphyclk", soc0_hpll, SCU0_MPHYCLK_PARAM),
++	PLL_CLK(SCU0_CLK_U2PHY_REFCLK, CLK_MISC, "u2phy_refclk", soc0_mpll_div8, SCU0_CLK_SEL2),
++	FIXED_FACTOR_CLK(SCU0_CLK_HPLL_DIV2, "soc0-hpll_div2", soc0_hpll, 1, 2),
++	FIXED_FACTOR_CLK(SCU0_CLK_HPLL_DIV4, "soc0-hpll_div4", soc0_hpll, 1, 4),
++	FIXED_FACTOR_CLK(SCU0_CLK_MPLL_DIV2, "soc0-mpll_div2", soc0_mpll, 1, 2),
++	FIXED_FACTOR_CLK(SCU0_CLK_MPLL_DIV4, "soc0-mpll_div4", soc0_mpll, 1, 4),
++	FIXED_FACTOR_CLK(SCU0_CLK_MPLL_DIV8, "soc0-mpll_div8", soc0_mpll, 1, 8),
++	FIXED_FACTOR_CLK(SCU0_CLK_AXI0, "axi0clk", pspclk, 1, 2),
++	FIXED_FACTOR_CLK(SCU0_CLK_AXI1, "axi1clk", soc0_ahb, 1, 1),
++	DIVIDER_CLK(SCU0_CLK_AHB, "soc0-ahb", soc0_ahbmux,
++		    SCU0_HWSTRAP1, 5, 2, ast2700a0_hclk_div_table),
++	DIVIDER_CLK(SCU0_CLK_APB, "soc0-apb", axi0clk,
++		    SCU0_CLK_SEL1, 23, 3, ast2700_clk_div_table2),
++	DIVIDER_CLK(SCU0_CLK_UART4, "uart4clk", soc0_uartclk,
++		    SCU0_CLK_SEL2, 30, 1, ast2700_clk_uart_div_table),
++	DIVIDER_CLK(SCU0_CLK_EMMC, "emmcclk", emmcsrc_mux,
++		    SCU0_CLK_SEL1, 12, 3, ast2700_clk_div_table2),
++	MUX_CLK(SCU0_CLK_PSP, "pspclk", mhpll_clk_sels, ARRAY_SIZE(mhpll_clk_sels),
++		SCU0_HWSTRAP1, 4, 1),
++	MUX_CLK(SCU0_CLK_AHBMUX, "soc0-ahbmux", mhpll_clk_sels, ARRAY_SIZE(mhpll_clk_sels),
++		SCU0_HWSTRAP1, 7, 1),
++	MUX_CLK(SCU0_CLK_UART, "soc0-uartclk", uart_clk_sels, ARRAY_SIZE(uart_clk_sels),
++		SCU0_CLK_SEL2, 14, 1),
++	MUX_CLK(SCU0_CLK_EMMCMUX, "emmcsrc-mux", emmc_clk_sels, ARRAY_SIZE(emmc_clk_sels),
++		SCU0_CLK_SEL1, 11, 1),
++	GATE_CLK(SCU0_CLK_GATE_MCLK, CLK_GATE_ASPEED, "mclk-gate", soc0_mpll,
++		 SCU0_CLK_STOP, 0, CLK_IS_CRITICAL),
++	GATE_CLK(SCU0_CLK_GATE_ECLK, CLK_GATE_ASPEED, "eclk-gate", NULL, SCU0_CLK_STOP, 1, 0),
++	GATE_CLK(SCU0_CLK_GATE_2DCLK, CLK_GATE_ASPEED, "gclk-gate", NULL, SCU0_CLK_STOP, 2, 0),
++	GATE_CLK(SCU0_CLK_GATE_VCLK, CLK_GATE_ASPEED, "vclk-gate", NULL, SCU0_CLK_STOP, 3, 0),
++	GATE_CLK(SCU0_CLK_GATE_BCLK, CLK_GATE_ASPEED, "bclk-gate", NULL,
++		 SCU0_CLK_STOP, 4, CLK_IS_CRITICAL),
++	GATE_CLK(SCU0_CLK_GATE_VGA0CLK,  CLK_GATE_ASPEED, "vga0clk-gate", NULL,
++		 SCU0_CLK_STOP, 5, CLK_IS_CRITICAL),
++	GATE_CLK(SCU0_CLK_GATE_REFCLK,  CLK_GATE_ASPEED, "soc0-refclk-gate", soc0_clkin,
++		 SCU0_CLK_STOP, 6, CLK_IS_CRITICAL),
++	GATE_CLK(SCU0_CLK_GATE_PORTBUSB2CLK, CLK_GATE_ASPEED, "portb-usb2clk-gate", NULL,
++		 SCU0_CLK_STOP, 7, 0),
++	GATE_CLK(SCU0_CLK_GATE_UHCICLK, CLK_GATE_ASPEED, "uhciclk-gate", NULL, SCU0_CLK_STOP, 9, 0),
++	GATE_CLK(SCU0_CLK_GATE_VGA1CLK, CLK_GATE_ASPEED, "vga1clk-gate", NULL,
++		 SCU0_CLK_STOP, 10, CLK_IS_CRITICAL),
++	GATE_CLK(SCU0_CLK_GATE_DDRPHYCLK, CLK_GATE_ASPEED, "ddrphy-gate", NULL,
++		 SCU0_CLK_STOP, 11, CLK_IS_CRITICAL),
++	GATE_CLK(SCU0_CLK_GATE_E2M0CLK, CLK_GATE_ASPEED, "e2m0clk-gate", NULL,
++		 SCU0_CLK_STOP, 12, CLK_IS_CRITICAL),
++	GATE_CLK(SCU0_CLK_GATE_HACCLK, CLK_GATE_ASPEED, "hacclk-gate", NULL, SCU0_CLK_STOP, 13, 0),
++	GATE_CLK(SCU0_CLK_GATE_PORTAUSB2CLK, CLK_GATE_ASPEED, "porta-usb2clk-gate", NULL,
++		 SCU0_CLK_STOP, 14, 0),
++	GATE_CLK(SCU0_CLK_GATE_UART4CLK, CLK_GATE_ASPEED, "uart4clk-gate", uart4clk,
++		 SCU0_CLK_STOP, 15, CLK_IS_CRITICAL),
++	GATE_CLK(SCU0_CLK_GATE_SLICLK, CLK_GATE_ASPEED, "soc0-sliclk-gate", NULL,
++		 SCU0_CLK_STOP, 16, CLK_IS_CRITICAL),
++	GATE_CLK(SCU0_CLK_GATE_DACCLK, CLK_GATE_ASPEED, "dacclk-gate", NULL,
++		 SCU0_CLK_STOP, 17, CLK_IS_CRITICAL),
++	GATE_CLK(SCU0_CLK_GATE_DP, CLK_GATE_ASPEED, "dpclk-gate", NULL,
++		 SCU0_CLK_STOP, 18, CLK_IS_CRITICAL),
++	GATE_CLK(SCU0_CLK_GATE_E2M1CLK, CLK_GATE_ASPEED, "e2m1clk-gate", NULL,
++		 SCU0_CLK_STOP, 19, CLK_IS_CRITICAL),
++	GATE_CLK(SCU0_CLK_GATE_CRT0CLK, CLK_GATE_ASPEED, "crt0clk-gate", NULL,
++		 SCU0_CLK_STOP, 20, 0),
++	GATE_CLK(SCU0_CLK_GATE_CRT1CLK, CLK_GATE_ASPEED, "crt1clk-gate", NULL,
++		 SCU0_CLK_STOP, 21, 0),
++	GATE_CLK(SCU0_CLK_GATE_ECDSACLK, CLK_GATE_ASPEED, "eccclk-gate", NULL,
++		 SCU0_CLK_STOP, 23, 0),
++	GATE_CLK(SCU0_CLK_GATE_RSACLK, CLK_GATE_ASPEED, "rsaclk-gate", NULL,
++		 SCU0_CLK_STOP, 24, 0),
++	GATE_CLK(SCU0_CLK_GATE_RVAS0CLK, CLK_GATE_ASPEED, "rvas0clk-gate", NULL,
++		 SCU0_CLK_STOP, 25, 0),
++	GATE_CLK(SCU0_CLK_GATE_UFSCLK, CLK_GATE_ASPEED, "ufsclk-gate", NULL,
++		 SCU0_CLK_STOP, 26, 0),
++	GATE_CLK(SCU0_CLK_GATE_EMMCCLK, CLK_GATE_ASPEED, "emmcclk-gate", emmcclk,
++		 SCU0_CLK_STOP, 27, 0),
++	GATE_CLK(SCU0_CLK_GATE_RVAS1CLK, CLK_GATE_ASPEED, "rvas1clk-gate", NULL,
++		 SCU0_CLK_STOP, 28, 0),
++};
++
++static const struct ast2700_clk_info ast2700a0_scu1_clk_info[] __initconst = {
++	FIXED_CLK(SCU1_CLKIN, "soc1-clkin", SCU_CLK_25MHZ),
++	PLL_CLK(SCU1_CLK_HPLL, CLK_PLL, "soc1-hpll", soc1_clkin, SCU1_HPLL_PARAM),
++	PLL_CLK(SCU1_CLK_APLL, CLK_PLL, "soc1-apll", soc1_clkin, SCU1_APLL_PARAM),
++	PLL_CLK(SCU1_CLK_DPLL, CLK_PLL, "soc1-dpll", soc1_clkin, SCU1_DPLL_PARAM),
++	PLL_CLK(SCU1_CLK_UARTX, CLK_UART_PLL, "uartxclk", uxclk, SCU1_UXCLK_CTRL),
++	PLL_CLK(SCU1_CLK_HUARTX, CLK_UART_PLL, "huartxclk", huxclk, SCU1_HUXCLK_CTRL),
++	FIXED_FACTOR_CLK(SCU1_CLK_APLL_DIV2, "soc1-apll_div2", soc1_apll, 1, 2),
++	FIXED_FACTOR_CLK(SCU1_CLK_APLL_DIV4, "soc1-apll_div4", soc1_apll, 1, 4),
++	FIXED_FACTOR_CLK(SCU1_CLK_UART13, "uart13clk", huartxclk, 1, 1),
++	FIXED_FACTOR_CLK(SCU1_CLK_UART14, "uart14clk", huartxclk, 1, 1),
++	FIXED_FACTOR_CLK(SCU1_CLK_CAN, "canclk", soc1_apll, 1, 10),
++	DIVIDER_CLK(SCU1_CLK_SDCLK, "sdclk", sdclk_mux,
++		    SCU1_CLK_SEL1, 14, 3, ast2700_clk_div_table),
++	DIVIDER_CLK(SCU1_CLK_APB, "soc1-apb", soc1_hpll,
++		    SCU1_CLK_SEL1, 18, 3, ast2700_clk_div_table2),
++	DIVIDER_CLK(SCU1_CLK_RMII, "rmii", soc1_hpll,
++		    SCU1_CLK_SEL1, 21, 3, ast2700_rmii_div_table),
++	DIVIDER_CLK(SCU1_CLK_RGMII, "rgmii", soc1_hpll,
++		    SCU1_CLK_SEL1, 25, 3, ast2700_rgmii_div_table),
++	DIVIDER_CLK(SCU1_CLK_MACHCLK, "machclk", soc1_hpll,
++		    SCU1_CLK_SEL1, 29, 3, ast2700_clk_div_table),
++	DIVIDER_CLK(SCU1_CLK_APLL_DIVN, "soc1-apll_divn", soc1_apll,
++		    SCU1_CLK_SEL2, 8, 3, ast2700_clk_div_table),
++	DIVIDER_CLK(SCU1_CLK_AHB, "soc1-ahb", soc1_hpll,
++		    SCU1_CLK_SEL2, 20, 3, ast2700_clk_div_table),
++	MUX_CLK(SCU1_CLK_UART0, "uart0clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels),
++		SCU1_CLK_SEL1, 0, 1),
++	MUX_CLK(SCU1_CLK_UART1, "uart1clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels),
++		SCU1_CLK_SEL1, 1, 1),
++	MUX_CLK(SCU1_CLK_UART2, "uart2clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels),
++		SCU1_CLK_SEL1, 2, 1),
++	MUX_CLK(SCU1_CLK_UART3, "uart3clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels),
++		SCU1_CLK_SEL1, 3, 1),
++	MUX_CLK(SCU1_CLK_UART5, "uart5clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels),
++		SCU1_CLK_SEL1, 5, 1),
++	MUX_CLK(SCU1_CLK_UART6, "uart6clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels),
++		SCU1_CLK_SEL1, 6, 1),
++	MUX_CLK(SCU1_CLK_UART7, "uart7clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels),
++		SCU1_CLK_SEL1, 7, 1),
++	MUX_CLK(SCU1_CLK_UART8, "uart8clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels),
++		SCU1_CLK_SEL1, 8, 1),
++	MUX_CLK(SCU1_CLK_UART9, "uart9clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels),
++		SCU1_CLK_SEL1, 9, 1),
++	MUX_CLK(SCU1_CLK_UART10, "uart10clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels),
++		SCU1_CLK_SEL1, 10, 1),
++	MUX_CLK(SCU1_CLK_UART11, "uart11clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels),
++		SCU1_CLK_SEL1, 11, 1),
++	MUX_CLK(SCU1_CLK_UART12, "uart12clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels),
++		SCU1_CLK_SEL1, 12, 1),
++	MUX_CLK(SCU1_CLK_SDMUX, "sdclk-mux", sdio_clk_sels, ARRAY_SIZE(sdio_clk_sels),
++		SCU1_CLK_SEL1, 13, 1),
++	MUX_CLK(SCU1_CLK_UXCLK, "uxclk", ux_clk_sels, ARRAY_SIZE(ux_clk_sels),
++		SCU1_CLK_SEL2, 0, 2),
++	MUX_CLK(SCU1_CLK_HUXCLK, "huxclk", ux_clk_sels, ARRAY_SIZE(ux_clk_sels),
++		SCU1_CLK_SEL2, 3, 2),
++	GATE_CLK(SCU1_CLK_MAC0RCLK, CLK_GATE, "mac0rclk-gate", rmii, SCU1_MAC12_CLK_DLY, 29, 0),
++	GATE_CLK(SCU1_CLK_MAC1RCLK, CLK_GATE, "mac1rclk-gate", rmii, SCU1_MAC12_CLK_DLY, 30, 0),
++	GATE_CLK(SCU1_CLK_GATE_LCLK0, CLK_GATE_ASPEED, "lclk0-gate", NULL,
++		 SCU1_CLK_STOP, 0, CLK_IS_CRITICAL),
++	GATE_CLK(SCU1_CLK_GATE_LCLK1, CLK_GATE_ASPEED, "lclk1-gate", NULL,
++		 SCU1_CLK_STOP, 1, CLK_IS_CRITICAL),
++	GATE_CLK(SCU1_CLK_GATE_ESPI0CLK, CLK_GATE_ASPEED, "espi0clk-gate", NULL,
++		 SCU1_CLK_STOP, 2, CLK_IS_CRITICAL),
++	GATE_CLK(SCU1_CLK_GATE_ESPI1CLK, CLK_GATE_ASPEED, "espi1clk-gate", NULL,
++		 SCU1_CLK_STOP, 3, CLK_IS_CRITICAL),
++	GATE_CLK(SCU1_CLK_GATE_SDCLK, CLK_GATE_ASPEED, "sdclk-gate", sdclk,
++		 SCU1_CLK_STOP, 4, CLK_IS_CRITICAL),
++	GATE_CLK(SCU1_CLK_GATE_IPEREFCLK, CLK_GATE_ASPEED, "soc1-iperefclk-gate", NULL,
++		 SCU1_CLK_STOP, 5, CLK_IS_CRITICAL),
++	GATE_CLK(SCU1_CLK_GATE_REFCLK, CLK_GATE_ASPEED, "soc1-refclk-gate", NULL,
++		 SCU1_CLK_STOP, 6, CLK_IS_CRITICAL),
++	GATE_CLK(SCU1_CLK_GATE_LPCHCLK, CLK_GATE_ASPEED, "lpchclk-gate", NULL,
++		 SCU1_CLK_STOP, 7, CLK_IS_CRITICAL),
++	GATE_CLK(SCU1_CLK_GATE_MAC0CLK, CLK_GATE_ASPEED, "mac0clk-gate", NULL,
++		 SCU1_CLK_STOP, 8, 0),
++	GATE_CLK(SCU1_CLK_GATE_MAC1CLK, CLK_GATE_ASPEED, "mac1clk-gate", NULL,
++		 SCU1_CLK_STOP, 9, 0),
++	GATE_CLK(SCU1_CLK_GATE_MAC2CLK, CLK_GATE_ASPEED, "mac2clk-gate", NULL,
++		 SCU1_CLK_STOP, 10, 0),
++	GATE_CLK(SCU1_CLK_GATE_UART0CLK, CLK_GATE_ASPEED, "uart0clk-gate", uart0clk,
++		 SCU1_CLK_STOP, 11, 0),
++	GATE_CLK(SCU1_CLK_GATE_UART1CLK, CLK_GATE_ASPEED, "uart1clk-gate", uart1clk,
++		 SCU1_CLK_STOP, 12, 0),
++	GATE_CLK(SCU1_CLK_GATE_UART2CLK, CLK_GATE_ASPEED, "uart2clk-gate", uart2clk,
++		 SCU1_CLK_STOP, 13, 0),
++	GATE_CLK(SCU1_CLK_GATE_UART3CLK, CLK_GATE_ASPEED, "uart3clk-gate", uart3clk,
++		 SCU1_CLK_STOP, 14, 0),
++	GATE_CLK(SCU1_CLK_GATE_I2CCLK, CLK_GATE_ASPEED, "i2cclk-gate", NULL, SCU1_CLK_STOP, 15, 0),
++	GATE_CLK(SCU1_CLK_GATE_I3C0CLK, CLK_GATE_ASPEED, "i3c0clk-gate", soc1_ahb,
++		 SCU1_CLK_STOP, 16, 0),
++	GATE_CLK(SCU1_CLK_GATE_I3C1CLK, CLK_GATE_ASPEED, "i3c1clk-gate", soc1_ahb,
++		 SCU1_CLK_STOP, 17, 0),
++	GATE_CLK(SCU1_CLK_GATE_I3C2CLK, CLK_GATE_ASPEED, "i3c2clk-gate", soc1_ahb,
++		 SCU1_CLK_STOP, 18, 0),
++	GATE_CLK(SCU1_CLK_GATE_I3C3CLK, CLK_GATE_ASPEED, "i3c3clk-gate", soc1_ahb,
++		 SCU1_CLK_STOP, 19, 0),
++	GATE_CLK(SCU1_CLK_GATE_I3C4CLK, CLK_GATE_ASPEED, "i3c4clk-gate", soc1_ahb,
++		 SCU1_CLK_STOP, 20, 0),
++	GATE_CLK(SCU1_CLK_GATE_I3C5CLK, CLK_GATE_ASPEED, "i3c5clk-gate", soc1_ahb,
++		 SCU1_CLK_STOP, 21, 0),
++	GATE_CLK(SCU1_CLK_GATE_I3C6CLK, CLK_GATE_ASPEED, "i3c6clk-gate", soc1_ahb,
++		 SCU1_CLK_STOP, 22, 0),
++	GATE_CLK(SCU1_CLK_GATE_I3C7CLK, CLK_GATE_ASPEED, "i3c7clk-gate", soc1_ahb,
++		 SCU1_CLK_STOP, 23, 0),
++	GATE_CLK(SCU1_CLK_GATE_I3C8CLK, CLK_GATE_ASPEED, "i3c8clk-gate", soc1_ahb,
++		 SCU1_CLK_STOP, 24, 0),
++	GATE_CLK(SCU1_CLK_GATE_I3C9CLK, CLK_GATE_ASPEED, "i3c9clk-gate", soc1_ahb,
++		 SCU1_CLK_STOP, 25, 0),
++	GATE_CLK(SCU1_CLK_GATE_I3C10CLK, CLK_GATE_ASPEED, "i3c10clk-gate", soc1_ahb,
++		 SCU1_CLK_STOP, 26, 0),
++	GATE_CLK(SCU1_CLK_GATE_I3C11CLK, CLK_GATE_ASPEED, "i3c11clk-gate", soc1_ahb,
++		 SCU1_CLK_STOP, 27, 0),
++	GATE_CLK(SCU1_CLK_GATE_I3C12CLK, CLK_GATE_ASPEED, "i3c12clk-gate", soc1_ahb,
++		 SCU1_CLK_STOP, 28, 0),
++	GATE_CLK(SCU1_CLK_GATE_I3C13CLK, CLK_GATE_ASPEED, "i3c13clk-gate", soc1_ahb,
++		 SCU1_CLK_STOP, 29, 0),
++	GATE_CLK(SCU1_CLK_GATE_I3C14CLK, CLK_GATE_ASPEED, "i3c14clk-gate", soc1_ahb,
++		 SCU1_CLK_STOP, 30, 0),
++	GATE_CLK(SCU1_CLK_GATE_I3C15CLK, CLK_GATE_ASPEED, "i3c15clk-gate", soc1_ahb,
++		 SCU1_CLK_STOP, 31, 0),
++	GATE_CLK(SCU1_CLK_GATE_UART5CLK, CLK_GATE_ASPEED, "uart5clk-gate", uart5clk,
++		 SCU1_CLK_STOP2, 0, CLK_IS_CRITICAL),
++	GATE_CLK(SCU1_CLK_GATE_UART6CLK, CLK_GATE_ASPEED, "uart6clk-gate", uart6clk,
++		 SCU1_CLK_STOP2, 1, CLK_IS_CRITICAL),
++	GATE_CLK(SCU1_CLK_GATE_UART7CLK, CLK_GATE_ASPEED, "uart7clk-gate", uart7clk,
++		 SCU1_CLK_STOP2, 2, CLK_IS_CRITICAL),
++	GATE_CLK(SCU1_CLK_GATE_UART8CLK, CLK_GATE_ASPEED, "uart8clk-gate", uart8clk,
++		 SCU1_CLK_STOP2, 3, CLK_IS_CRITICAL),
++	GATE_CLK(SCU1_CLK_GATE_UART9CLK, CLK_GATE_ASPEED, "uart9clk-gate", uart9clk,
++		 SCU1_CLK_STOP2, 4, 0),
++	GATE_CLK(SCU1_CLK_GATE_UART10CLK, CLK_GATE_ASPEED, "uart10clk-gate", uart10clk,
++		 SCU1_CLK_STOP2, 5, 0),
++	GATE_CLK(SCU1_CLK_GATE_UART11CLK, CLK_GATE_ASPEED, "uart11clk-gate", uart11clk,
++		 SCU1_CLK_STOP2, 6, 0),
++	GATE_CLK(SCU1_CLK_GATE_UART12CLK, CLK_GATE_ASPEED, "uart12clk-gate", uart12clk,
++		 SCU1_CLK_STOP2, 7, 0),
++	GATE_CLK(SCU1_CLK_GATE_FSICLK, CLK_GATE_ASPEED, "fsiclk-gate", NULL, SCU1_CLK_STOP2, 8, 0),
++	GATE_CLK(SCU1_CLK_GATE_LTPIPHYCLK, CLK_GATE_ASPEED, "ltpiphyclk-gate", NULL,
++		 SCU1_CLK_STOP2, 9, 0),
++	GATE_CLK(SCU1_CLK_GATE_LTPICLK, CLK_GATE_ASPEED, "ltpiclk-gate", NULL,
++		 SCU1_CLK_STOP2, 10, 0),
++	GATE_CLK(SCU1_CLK_GATE_VGALCLK, CLK_GATE_ASPEED, "vgalclk-gate", NULL,
++		 SCU1_CLK_STOP2, 11, CLK_IS_CRITICAL),
++	GATE_CLK(SCU1_CLK_GATE_UHCICLK, CLK_GATE_ASPEED, "usbuartclk-gate", NULL,
++		 SCU1_CLK_STOP2, 12, 0),
++	GATE_CLK(SCU1_CLK_GATE_CANCLK, CLK_GATE_ASPEED, "canclk-gate", canclk,
++		 SCU1_CLK_STOP2, 13, 0),
++	GATE_CLK(SCU1_CLK_GATE_PCICLK, CLK_GATE_ASPEED, "pciclk-gate", canclk,
++		 SCU1_CLK_STOP2, 14, 0),
++	GATE_CLK(SCU1_CLK_GATE_SLICLK, CLK_GATE_ASPEED, "soc1-sliclk-gate", canclk,
++		 SCU1_CLK_STOP2, 15, CLK_IS_CRITICAL),
++	GATE_CLK(SCU1_CLK_GATE_E2MCLK, CLK_GATE_ASPEED, "soc1-e2m-gate", NULL,
++		 SCU1_CLK_STOP2, 16, CLK_IS_CRITICAL),
++	GATE_CLK(SCU1_CLK_GATE_PORTCUSB2CLK, CLK_GATE_ASPEED, "portcusb2-gate", NULL,
++		 SCU1_CLK_STOP2, 17, 0),
++	GATE_CLK(SCU1_CLK_GATE_PORTDUSB2CLK, CLK_GATE_ASPEED, "portdusb2-gate", NULL,
++		 SCU1_CLK_STOP2, 18, 0),
++	GATE_CLK(SCU1_CLK_GATE_LTPI1TXCLK, CLK_GATE_ASPEED, "ltp1tx-gate", NULL,
++		 SCU1_CLK_STOP2, 19, 0),
++};
++
++static struct clk_hw *ast2700_clk_hw_register_hpll(void __iomem *reg,
++						   const char *name, const char *parent_name,
++						   struct ast2700_clk_ctrl *clk_ctrl)
++{
++	unsigned int mult, div;
++	u32 val;
++
++	val = readl(clk_ctrl->base + SCU0_HWSTRAP1);
++	if ((readl(clk_ctrl->base) & REVISION_ID) && (val & BIT(3))) {
++		switch ((val & GENMASK(4, 2)) >> 2) {
++		case 2:
++			return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL,
++							       0, 1800 * HZ_PER_MHZ);
++		case 3:
++			return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL,
++							       0, 1700 * HZ_PER_MHZ);
++		case 6:
++			return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL,
++							       0, 1200 * HZ_PER_MHZ);
++		case 7:
++			return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL,
++							       0, 800 * HZ_PER_MHZ);
++		default:
++			return ERR_PTR(-EINVAL);
++		}
++	} else if ((val & GENMASK(3, 2)) != 0) {
++		switch ((val & GENMASK(3, 2)) >> 2) {
++		case 1:
++			return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL,
++							       0, 1900 * HZ_PER_MHZ);
++		case 2:
++			return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL,
++							       0, 1800 * HZ_PER_MHZ);
++		case 3:
++			return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL,
++							       0, 1700 * HZ_PER_MHZ);
++		default:
++			return ERR_PTR(-EINVAL);
++		}
++	} else {
++		val = readl(reg);
++
++		if (val & BIT(24)) {
++			/* Pass through mode */
++			mult = 1;
++			div = 1;
++		} else {
++			u32 m = val & 0x1fff;
++			u32 n = (val >> 13) & 0x3f;
++			u32 p = (val >> 19) & 0xf;
++
++			mult = (m + 1) / (2 * (n + 1));
++			div = (p + 1);
++		}
++	}
++
++	return devm_clk_hw_register_fixed_factor(clk_ctrl->dev, name, parent_name, 0, mult, div);
++}
++
++static struct clk_hw *ast2700_clk_hw_register_pll(int clk_idx, void __iomem *reg,
++						  const char *name, const char *parent_name,
++						  struct ast2700_clk_ctrl *clk_ctrl)
++{
++	int scu = clk_ctrl->clk_data->scu;
++	unsigned int mult, div;
++	u32 val = readl(reg);
++
++	if (val & BIT(24)) {
++		/* Pass through mode */
++		mult = 1;
++		div = 1;
++	} else {
++		u32 m = val & 0x1fff;
++		u32 n = (val >> 13) & 0x3f;
++		u32 p = (val >> 19) & 0xf;
++
++		if (scu) {
++			mult = (m + 1) / (n + 1);
++			div = (p + 1);
++		} else {
++			if (clk_idx == SCU0_CLK_MPLL) {
++				mult = m / (n + 1);
++				div = (p + 1);
++			} else {
++				mult = (m + 1) / (2 * (n + 1));
++				div = (p + 1);
++			}
++		}
++	}
++
++	return devm_clk_hw_register_fixed_factor(clk_ctrl->dev, name, parent_name, 0, mult, div);
++}
++
++static struct clk_hw *ast2700_clk_hw_register_dclk(void __iomem *reg, const char *name,
++						   struct ast2700_clk_ctrl *clk_ctrl)
++{
++	unsigned int mult, div, r, n;
++	u32 xdclk;
++	u32 val;
++
++	val = readl(clk_ctrl->base + 0x284);
++	if (val & BIT(29))
++		xdclk = 800 * HZ_PER_MHZ;
++	else
++		xdclk = 1000 * HZ_PER_MHZ;
++
++	val = readl(reg);
++	r = val & GENMASK(15, 0);
++	n = (val >> 16) & GENMASK(15, 0);
++	mult = r;
++	div = 2 * n;
++
++	return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL, 0, (xdclk * mult) / div);
++}
++
++static struct clk_hw *ast2700_clk_hw_register_uartpll(void __iomem *reg,
++						      const char *name, const char *parent_name,
++						      struct ast2700_clk_ctrl *clk_ctrl)
++{
++	unsigned int mult, div;
++	u32 val = readl(reg);
++	u32 r = val & 0xff;
++	u32 n = (val >> 8) & 0x3ff;
++
++	mult = r;
++	div = n * 2;
++
++	return devm_clk_hw_register_fixed_factor(clk_ctrl->dev, name,
++						 parent_name, 0, mult, div);
++}
++
++static struct clk_hw *ast2700_clk_hw_register_misc(int clk_idx, void __iomem *reg,
++						   const char *name, const char *parent_name,
++						   struct ast2700_clk_ctrl *clk_ctrl)
++{
++	u32 div = 0;
++
++	if (clk_idx == SCU0_CLK_MPHY) {
++		div = readl(reg) + 1;
++	} else if (clk_idx == SCU0_CLK_U2PHY_REFCLK) {
++		if (readl(clk_ctrl->base) & REVISION_ID)
++			div = (GET_USB_REFCLK_DIV(readl(reg)) + 1) << 4;
++		else
++			div = (GET_USB_REFCLK_DIV(readl(reg)) + 1) << 1;
++	} else {
++		return ERR_PTR(-EINVAL);
++	}
++
++	return devm_clk_hw_register_fixed_factor(clk_ctrl->dev, name,
++						   parent_name, 0, 1, div);
++}
++
++static int ast2700_clk_is_enabled(struct clk_hw *hw)
++{
++	struct clk_gate *gate = to_clk_gate(hw);
++	u32 clk = BIT(gate->bit_idx);
++	u32 reg;
++
++	reg = readl(gate->reg);
++
++	return !(reg & clk);
++}
++
++static int ast2700_clk_enable(struct clk_hw *hw)
++{
++	struct clk_gate *gate = to_clk_gate(hw);
++	u32 clk = BIT(gate->bit_idx);
++
++	if (readl(gate->reg) & clk)
++		writel(clk, gate->reg + 0x04);
++
++	return 0;
++}
++
++static void ast2700_clk_disable(struct clk_hw *hw)
++{
++	struct clk_gate *gate = to_clk_gate(hw);
++	u32 clk = BIT(gate->bit_idx);
++
++	/* Clock is set to enable, so use write to set register */
++	writel(clk, gate->reg);
++}
++
++static const struct clk_ops ast2700_clk_gate_ops = {
++	.enable = ast2700_clk_enable,
++	.disable = ast2700_clk_disable,
++	.is_enabled = ast2700_clk_is_enabled,
++};
++
++static struct clk_hw *ast2700_clk_hw_register_gate(struct device *dev, const char *name,
++						   const struct clk_parent_data	*parent,
++						   void __iomem *reg, u8 clock_idx,
++						   unsigned long clk_gate_flags, spinlock_t *lock)
++{
++	struct clk_gate *gate;
++	struct clk_hw *hw;
++	struct clk_init_data init;
++	int ret = -EINVAL;
++
++	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
++	if (!gate)
++		return ERR_PTR(-ENOMEM);
++
++	init.name = name;
++	init.ops = &ast2700_clk_gate_ops;
++	init.flags = clk_gate_flags;
++	init.parent_names = parent ? &parent->name : NULL;
++	init.num_parents = parent ? 1 : 0;
++
++	gate->reg = reg;
++	gate->bit_idx = clock_idx;
++	gate->flags = 0;
++	gate->lock = lock;
++	gate->hw.init = &init;
++
++	hw = &gate->hw;
++	ret = clk_hw_register(dev, hw);
++	if (ret) {
++		kfree(gate);
++		hw = ERR_PTR(ret);
++	}
++
++	return hw;
++}
++
++static void ast2700_soc1_configure_mac01_clk(struct ast2700_clk_ctrl *clk_ctrl)
++{
++	struct device_node *np = clk_ctrl->dev->of_node;
++	struct mac_delay_config mac_cfg;
++	u32 reg[3];
++	int ret;
++
++	if (readl(clk_ctrl->base + SCU1_REVISION_ID) & REVISION_ID)
++		reg[0] = AST2700_DEF_MAC12_DELAY_1G_A1;
++	else
++		reg[0] = AST2700_DEF_MAC12_DELAY_1G_A0;
++	reg[1] = AST2700_DEF_MAC12_DELAY_100M;
++	reg[2] = AST2700_DEF_MAC12_DELAY_10M;
++
++	ret = of_property_read_u32_array(np, "mac0-clk-delay", (u32 *)&mac_cfg,
++					 sizeof(mac_cfg) / sizeof(u32));
++	if (!ret) {
++		reg[0] &= ~(MAC_CLK_1G_INPUT_DELAY_1 | MAC_CLK_1G_OUTPUT_DELAY_1);
++		reg[0] |= FIELD_PREP(MAC_CLK_1G_INPUT_DELAY_1, mac_cfg.rx_delay_1000) |
++			  FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_1, mac_cfg.tx_delay_1000);
++
++		reg[1] &= ~(MAC_CLK_100M_10M_INPUT_DELAY_1 | MAC_CLK_100M_10M_OUTPUT_DELAY_1);
++		reg[1] |= FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_1, mac_cfg.rx_delay_100) |
++			  FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, mac_cfg.tx_delay_100);
++
++		reg[2] &= ~(MAC_CLK_100M_10M_INPUT_DELAY_1 | MAC_CLK_100M_10M_OUTPUT_DELAY_1);
++		reg[2] |= FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_1, mac_cfg.rx_delay_10) |
++			  FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_1, mac_cfg.tx_delay_10);
++	}
++
++	ret = of_property_read_u32_array(np, "mac1-clk-delay", (u32 *)&mac_cfg,
++					 sizeof(mac_cfg) / sizeof(u32));
++	if (!ret) {
++		reg[0] &= ~(MAC_CLK_1G_INPUT_DELAY_2 | MAC_CLK_1G_OUTPUT_DELAY_2);
++		reg[0] |= FIELD_PREP(MAC_CLK_1G_INPUT_DELAY_2, mac_cfg.rx_delay_1000) |
++			  FIELD_PREP(MAC_CLK_1G_OUTPUT_DELAY_2, mac_cfg.tx_delay_1000);
++
++		reg[1] &= ~(MAC_CLK_100M_10M_INPUT_DELAY_2 | MAC_CLK_100M_10M_OUTPUT_DELAY_2);
++		reg[1] |= FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_2, mac_cfg.rx_delay_100) |
++			  FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, mac_cfg.tx_delay_100);
++
++		reg[2] &= ~(MAC_CLK_100M_10M_INPUT_DELAY_2 | MAC_CLK_100M_10M_OUTPUT_DELAY_2);
++		reg[2] |= FIELD_PREP(MAC_CLK_100M_10M_INPUT_DELAY_2, mac_cfg.rx_delay_10) |
++			  FIELD_PREP(MAC_CLK_100M_10M_OUTPUT_DELAY_2, mac_cfg.tx_delay_10);
++	}
++
++	reg[0] |= (readl(clk_ctrl->base + SCU1_MAC12_CLK_DLY) & ~GENMASK(25, 0));
++	writel(reg[0], clk_ctrl->base + SCU1_MAC12_CLK_DLY);
++	writel(reg[1], clk_ctrl->base + SCU1_MAC12_CLK_DLY_100M);
++	writel(reg[2], clk_ctrl->base + SCU1_MAC12_CLK_DLY_10M);
++}
++
++static void ast2700_soc1_configure_i3c_clk(struct ast2700_clk_ctrl *clk_ctrl)
++{
++	if (readl(clk_ctrl->base + SCU1_REVISION_ID) & REVISION_ID)
++		/* I3C 250MHz = HPLL/4 */
++		writel((readl(clk_ctrl->base + SCU1_CLK_SEL2) &
++			~SCU1_CLK_I3C_DIV_MASK) |
++			       FIELD_PREP(SCU1_CLK_I3C_DIV_MASK,
++					  SCU1_CLK_I3C_DIV(4)),
++		       clk_ctrl->base + SCU1_CLK_SEL2);
++}
++
++static int ast2700a0_soc_clk_probe(struct platform_device *pdev)
++{
++	struct ast2700_clk_data *clk_data;
++	struct ast2700_clk_ctrl *clk_ctrl;
++	struct clk_hw_onecell_data *clk_hw_data;
++	struct device *dev = &pdev->dev;
++	u32 uart_clk_source = 0;
++	void __iomem *clk_base;
++	struct clk_hw **hws;
++	char *reset_name;
++	int ret;
++	int i;
++
++	clk_ctrl = devm_kzalloc(dev, sizeof(*clk_ctrl), GFP_KERNEL);
++	if (!clk_ctrl)
++		return -ENOMEM;
++	clk_ctrl->dev = dev;
++	dev_set_drvdata(&pdev->dev, clk_ctrl);
++
++	spin_lock_init(&clk_ctrl->lock);
++
++	clk_base = devm_platform_ioremap_resource(pdev, 0);
++	if (IS_ERR(clk_base))
++		return PTR_ERR(clk_base);
++
++	clk_ctrl->base = clk_base;
++
++	clk_data = (struct ast2700_clk_data *)device_get_match_data(dev);
++	if (!clk_data)
++		return -ENODEV;
++
++	clk_ctrl->clk_data = clk_data;
++	reset_name = devm_kasprintf(dev, GFP_KERNEL, "reset%d", clk_data->scu);
++
++	clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws, clk_data->nr_clks),
++				   GFP_KERNEL);
++	if (!clk_hw_data)
++		return -ENOMEM;
++
++	clk_hw_data->num = clk_data->nr_clks;
++	hws = clk_hw_data->hws;
++
++	if (clk_data->scu) {
++		of_property_read_u32(dev->of_node, "uart-clk-source", &uart_clk_source);
++		if (uart_clk_source) {
++			u32 val = readl(clk_base + SCU1_CLK_SEL1) & ~GENMASK(12, 0);
++
++			uart_clk_source &= GENMASK(12, 0);
++			writel(val | uart_clk_source, clk_base + SCU1_CLK_SEL1);
++		}
++
++		ast2700_soc1_configure_mac01_clk(clk_ctrl);
++		ast2700_soc1_configure_i3c_clk(clk_ctrl);
++	}
++
++	for (i = 0; i < clk_data->nr_clks; i++) {
++		const struct ast2700_clk_info *clk = &clk_data->clk_info[i];
++		void __iomem *reg = clk_ctrl->base + clk->reg;
++
++		if (clk->type == CLK_FIXED) {
++			const struct ast2700_clk_fixed_rate_data *fixed_rate = &clk->data.rate;
++
++			hws[i] = devm_clk_hw_register_fixed_rate(dev, clk->name, NULL, 0,
++								 fixed_rate->fixed_rate);
++		} else if (clk->type == CLK_FIXED_FACTOR) {
++			const struct ast2700_clk_fixed_factor_data *factor = &clk->data.factor;
++
++			hws[i] = devm_clk_hw_register_fixed_factor(dev, clk->name,
++								   factor->parent->name,
++								   0, factor->mult, factor->div);
++		} else if (clk->type == DCLK_FIXED) {
++			const struct ast2700_clk_pll_data *pll = &clk->data.pll;
++
++			reg = clk_ctrl->base + pll->reg;
++			hws[i] = ast2700_clk_hw_register_dclk(reg, clk->name, clk_ctrl);
++		} else if (clk->type == CLK_HPLL) {
++			const struct ast2700_clk_pll_data *pll = &clk->data.pll;
++
++			reg = clk_ctrl->base + pll->reg;
++			hws[i] = ast2700_clk_hw_register_hpll(reg, clk->name,
++							      pll->parent->name, clk_ctrl);
++		} else if (clk->type == CLK_PLL) {
++			const struct ast2700_clk_pll_data *pll = &clk->data.pll;
++
++			reg = clk_ctrl->base + pll->reg;
++			hws[i] = ast2700_clk_hw_register_pll(i, reg, clk->name,
++							     pll->parent->name, clk_ctrl);
++		} else if (clk->type == CLK_UART_PLL) {
++			const struct ast2700_clk_pll_data *pll = &clk->data.pll;
++
++			reg = clk_ctrl->base + pll->reg;
++			hws[i] = ast2700_clk_hw_register_uartpll(reg, clk->name,
++								 pll->parent->name, clk_ctrl);
++		} else if (clk->type == CLK_MUX) {
++			const struct ast2700_clk_mux_data *mux = &clk->data.mux;
++
++			reg = clk_ctrl->base + mux->reg;
++			hws[i] = devm_clk_hw_register_mux_parent_data_table(dev, clk->name,
++									    mux->parents,
++									    mux->num_parents, 0,
++									    reg, mux->bit_shift,
++									    mux->bit_width, 0,
++									    NULL, &clk_ctrl->lock);
++		} else if (clk->type == CLK_MISC) {
++			const struct ast2700_clk_pll_data *misc = &clk->data.pll;
++
++			reg = clk_ctrl->base + misc->reg;
++			hws[i] = ast2700_clk_hw_register_misc(i, reg, clk->name,
++							      misc->parent->name, clk_ctrl);
++		} else if (clk->type == CLK_DIVIDER) {
++			const struct ast2700_clk_div_data *div = &clk->data.div;
++
++			reg = clk_ctrl->base + div->reg;
++			hws[i] = devm_clk_hw_register_divider_table(dev, clk->name,
++								    div->parent->name, 0,
++								    reg, div->bit_shift,
++								    div->bit_width, 0,
++								    div->div_table,
++								    &clk_ctrl->lock);
++		} else if (clk->type == CLK_GATE_ASPEED) {
++			const struct ast2700_clk_gate_data *gate = &clk->data.gate;
++
++			reg = clk_ctrl->base + gate->reg;
++			hws[i] = ast2700_clk_hw_register_gate(dev, clk->name, gate->parent,
++							      reg, gate->bit, gate->flags, 0);
++
++		} else {
++			const struct ast2700_clk_gate_data *gate = &clk->data.gate;
++
++			reg = clk_ctrl->base + gate->reg;
++			hws[i] = devm_clk_hw_register_gate_parent_data(dev, clk->name, gate->parent,
++								       0, reg, clk->clk_idx, 0,
++								       &clk_ctrl->lock);
++		}
++
++		if (IS_ERR(hws[i]))
++			return PTR_ERR(hws[i]);
++	}
++
++	ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_hw_data);
++	if (ret)
++		return ret;
++
++	return aspeed_reset_controller_register(dev, clk_base, reset_name);
++}
++
++static const struct ast2700_clk_data ast2700a0_clk0_data = {
++	.scu = 0,
++	.nr_clks = ARRAY_SIZE(ast2700a0_scu0_clk_info),
++	.clk_info = ast2700a0_scu0_clk_info,
++};
++
++static const struct ast2700_clk_data ast2700a0_clk1_data = {
++	.scu = 1,
++	.nr_clks = ARRAY_SIZE(ast2700a0_scu1_clk_info),
++	.clk_info = ast2700a0_scu1_clk_info,
++};
++
++static const struct of_device_id ast2700a0_scu_match[] = {
++	{ .compatible = "aspeed,ast2700a0-scu0", .data = &ast2700a0_clk0_data },
++	{ .compatible = "aspeed,ast2700a0-scu1", .data = &ast2700a0_clk1_data },
++	{ /* sentinel */ }
++};
++
++MODULE_DEVICE_TABLE(of, ast2700a0_scu_match);
++
++static struct platform_driver ast2700a0_scu_driver = {
++	.probe = ast2700a0_soc_clk_probe,
++	.driver = {
++		.name = "clk-ast2700a0",
++		.of_match_table = ast2700a0_scu_match,
++	},
++};
++
++static int __init clk_ast2700a0_init(void)
++{
++	return platform_driver_register(&ast2700a0_scu_driver);
++}
++arch_initcall(clk_ast2700a0_init);
 -- 
 2.34.1
 
diff --git a/recipes-kernel/linux/files/0007-Add-uart-vuart-udma-drvier-for-ast2700.patch b/recipes-kernel/linux/files/0007-Add-uart-vuart-udma-drvier-for-ast2700.patch
index a8df2bf..45dd1ca 100644
--- a/recipes-kernel/linux/files/0007-Add-uart-vuart-udma-drvier-for-ast2700.patch
+++ b/recipes-kernel/linux/files/0007-Add-uart-vuart-udma-drvier-for-ast2700.patch
@@ -1,16 +1,16 @@
-From 7a9b097075af5261cf2fb7a5d9dcccaf392abd65 Mon Sep 17 00:00:00 2001
-From: "yung-sheng.huang" <yung-sheng.huang@fii-na.corp-partner.google.com>
-Date: Tue, 15 Apr 2025 11:38:42 +0800
-Subject: [PATCH 07/26] Add uart vuart udma drvier for ast2700
+From 0ce936791016c85d0e1d9ffc6e6396bcff0308c7 Mon Sep 17 00:00:00 2001
+From: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+Date: Wed, 16 Jul 2025 17:52:49 +0800
+Subject: [PATCH] Add uart vuart udma drvier for ast2700
 
-This is base on aspeed SDK 9.06.
+This is base on aspeed SDK 9.07.
 
 Source:
 AspeedTech-BMC github:
 https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/
-(cherry picked from commit v00.06.06)
+(cherry picked from commit v00.06.07)
 
-Signed-off-by: yung-sheng.huang <yung-sheng.huang@fii-na.corp-partner.google.com>
+Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
 ---
  drivers/soc/aspeed/Kconfig                  |   8 +
  drivers/soc/aspeed/Makefile                 |   1 +
diff --git a/recipes-kernel/linux/files/0007-i3c-mipi-i3c-hci-aspeed-Add-SR_P-timing-configuratio.patch b/recipes-kernel/linux/files/0007-i3c-mipi-i3c-hci-aspeed-Add-SR_P-timing-configuratio.patch
deleted file mode 100644
index daccc38..0000000
--- a/recipes-kernel/linux/files/0007-i3c-mipi-i3c-hci-aspeed-Add-SR_P-timing-configuratio.patch
+++ /dev/null
@@ -1,60 +0,0 @@
-From 617aa54bdd14250076aaf56d6c87d73d03ed0ef2 Mon Sep 17 00:00:00 2001
-From: Billy Tsai <billy_tsai@aspeedtech.com>
-Date: Mon, 21 Apr 2025 15:22:06 +0800
-Subject: [PATCH 7/9] i3c: mipi-i3c-hci: aspeed: Add SR_P timing configuration
-
-Use default SR_P hold time and align the low count with the push-pull low
-count.
-
-Signed-off-by: Billy Tsai <billy_tsai@aspeedtech.com>
-Change-Id: I3c414c210aa34e1911452feb3b3e11c9a0dccc72
----
- drivers/i3c/master/mipi-i3c-hci/core.c          | 11 ++++++++++-
- drivers/i3c/master/mipi-i3c-hci/vendor_aspeed.h |  2 +-
- 2 files changed, 11 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c
-index ee44e01cb22f..26795db6efed 100644
---- a/drivers/i3c/master/mipi-i3c-hci/core.c
-+++ b/drivers/i3c/master/mipi-i3c-hci/core.c
-@@ -189,7 +189,7 @@ static void aspeed_i3c_of_populate_bus_timing(struct i3c_hci *hci, struct device
- 	u16 hcnt, lcnt, total_cnt, min_tbit_cnt;
- 	unsigned long core_rate, core_period;
- 	u32 val, pp_high = 0, pp_low = 0, od_high = 0, od_low = 0, thd_dat = 0, internal_pu = 0;
--	u32 ctrl0, ctrl1, ctrl2;
-+	u32 ctrl0, ctrl1, ctrl2, sr_p_prepare_ctrl;
- 	u32 sdr_ctrl0_reg = aspeed_i3c_get_sdr_phy_reg(hci);
- 
- 	core_rate = clk_get_rate(hci->clk);
-@@ -246,6 +246,15 @@ static void aspeed_i3c_of_populate_bus_timing(struct i3c_hci *hci, struct device
- 	ast_phy_write(PHY_I3C_SDR0_CTRL1, ctrl1);
- 	ast_phy_write(PHY_I3C_DDR_CTRL1, ctrl1);
- 
-+	/*
-+	 * The SR_P hold time uses the default value, and the SR_P low count is
-+	 * the same as the push-pull low count.
-+	 */
-+	hcnt = DIV_ROUND_CLOSEST(PHY_I3C_SR_P_DEFAULT_HD_NS, core_period);
-+	sr_p_prepare_ctrl = FIELD_PREP(PHY_I3C_SR_P_PREPARE_CTRL_HD, hcnt) |
-+			    FIELD_PREP(PHY_I3C_SR_P_PREPARE_CTRL_SCL_L, lcnt);
-+	ast_phy_write(PHY_I3C_SR_P_PREPARE_CTRL, sr_p_prepare_ctrl);
-+
- 	if (od_high && od_low) {
- 		hcnt = DIV_ROUND_CLOSEST(od_high, core_period) - 1;
- 		lcnt = DIV_ROUND_CLOSEST(od_low, core_period) - 1;
-diff --git a/drivers/i3c/master/mipi-i3c-hci/vendor_aspeed.h b/drivers/i3c/master/mipi-i3c-hci/vendor_aspeed.h
-index 7577bfc24ba8..130829086fbf 100644
---- a/drivers/i3c/master/mipi-i3c-hci/vendor_aspeed.h
-+++ b/drivers/i3c/master/mipi-i3c-hci/vendor_aspeed.h
-@@ -340,7 +340,7 @@
- #define PHY_I3C_SR_P_PREPARE_CTRL		0x80
- #define PHY_I3C_SR_P_PREPARE_CTRL_HD		GENMASK(25, 16)
- #define PHY_I3C_SR_P_PREPARE_CTRL_SCL_L		GENMASK(9, 0)
--#define PHY_I3C_SR_P_DEFAULT_HD_NS	10
-+#define PHY_I3C_SR_P_DEFAULT_HD_NS	16
- #define PHY_I3C_SR_P_DEFAULT_SCL_L_NS	40
- 
- #define PHY_PULLUP_EN		0x98
--- 
-2.49.0.906.g1f30a19c02-goog
-
diff --git a/recipes-kernel/linux/files/0008-Add-SPI-driver-for-ast2700.patch b/recipes-kernel/linux/files/0008-Add-SPI-driver-for-ast2700.patch
index f83f6ae..5d20ea4 100644
--- a/recipes-kernel/linux/files/0008-Add-SPI-driver-for-ast2700.patch
+++ b/recipes-kernel/linux/files/0008-Add-SPI-driver-for-ast2700.patch
@@ -1,23 +1,23 @@
-From 8ee65843567f0e28cb02f08cca539133921fffd0 Mon Sep 17 00:00:00 2001
-From: "yung-sheng.huang" <yung-sheng.huang@fii-na.corp-partner.google.com>
-Date: Tue, 15 Apr 2025 11:42:30 +0800
-Subject: [PATCH 08/26] Add SPI driver for ast2700
+From 3ca2272f29b9c6c3c023f8f58c23483428d861e4 Mon Sep 17 00:00:00 2001
+From: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+Date: Wed, 16 Jul 2025 17:56:52 +0800
+Subject: [PATCH] Add SPI driver for ast2700
 
-This is base on aspeed SDK 9.06.
+This is base on aspeed SDK 9.07.
 
 Source:
 AspeedTech-BMC github:
 https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/
-(cherry picked from commit v00.06.06)
+(cherry picked from commit v00.06.07)
 
-Signed-off-by: yung-sheng.huang <yung-sheng.huang@fii-na.corp-partner.google.com>
+Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
 ---
  drivers/spi/Kconfig           |   10 +
  drivers/spi/Makefile          |    1 +
- drivers/spi/spi-aspeed-smc.c  | 1892 +++++++++++++++++++++++++++------
- drivers/spi/spi-aspeed-txrx.c |  643 +++++++++++
- 4 files changed, 2229 insertions(+), 317 deletions(-)
- create mode 100644 drivers/spi/spi-aspeed-txrx.c
+ drivers/spi/spi-aspeed-smc.c  | 1890 +++++++++++++++++++++++++++------
+ drivers/spi/spi-aspeed-txrx.c |  644 +++++++++++
+ 4 files changed, 2232 insertions(+), 313 deletions(-)
+ create mode 100755 drivers/spi/spi-aspeed-txrx.c
 
 diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
 index 3ce0fd5df..a03525a3a 100644
@@ -53,10 +53,10 @@
  obj-$(CONFIG_SPI_ATMEL_QUADSPI)		+= atmel-quadspi.o
  obj-$(CONFIG_SPI_AT91_USART)		+= spi-at91-usart.o
 diff --git a/drivers/spi/spi-aspeed-smc.c b/drivers/spi/spi-aspeed-smc.c
-index 21b0fa646..7d9beda2b 100644
+index 38a0613d4..0ccb87c2c 100644
 --- a/drivers/spi/spi-aspeed-smc.c
 +++ b/drivers/spi/spi-aspeed-smc.c
-@@ -7,10 +7,15 @@
+@@ -7,10 +7,16 @@
   */
  
  #include <linux/clk.h>
@@ -65,6 +65,7 @@
 +#include <linux/io.h>
 +#include <linux/kernel.h>
  #include <linux/module.h>
++#include <linux/mtd/spi-nor.h>
  #include <linux/of.h>
  #include <linux/of_platform.h>
  #include <linux/platform_device.h>
@@ -72,7 +73,7 @@
  #include <linux/spi/spi.h>
  #include <linux/spi/spi-mem.h>
  
-@@ -23,12 +28,21 @@
+@@ -23,12 +29,21 @@
  /* CE Control Register */
  #define CE_CTRL_REG			0x4
  
@@ -94,7 +95,7 @@
  #define   CTRL_COMMAND_SHIFT		16
  #define   CTRL_IO_ADDRESS_4B		BIT(13)	/* AST2400 SPI only */
  #define   CTRL_IO_DUMMY_SET(dummy)					\
-@@ -42,14 +56,41 @@
+@@ -42,14 +57,41 @@
  #define   CTRL_IO_MODE_WRITE		0x2
  #define   CTRL_IO_MODE_USER		0x3
  
@@ -137,7 +138,7 @@
  enum aspeed_spi_ctl_reg_value {
  	ASPEED_SPI_BASE,
  	ASPEED_SPI_READ,
-@@ -57,6 +98,13 @@ enum aspeed_spi_ctl_reg_value {
+@@ -57,6 +99,13 @@ enum aspeed_spi_ctl_reg_value {
  	ASPEED_SPI_MAX,
  };
  
@@ -151,7 +152,7 @@
  struct aspeed_spi;
  
  struct aspeed_spi_chip {
-@@ -64,7 +112,8 @@ struct aspeed_spi_chip {
+@@ -64,7 +113,8 @@ struct aspeed_spi_chip {
  	u32			 cs;
  	void __iomem		*ctl;
  	void __iomem		*ahb_base;
@@ -161,7 +162,7 @@
  	u32			 ctl_val[ASPEED_SPI_MAX];
  	u32			 clk_freq;
  };
-@@ -78,43 +127,77 @@ struct aspeed_spi_data {
+@@ -78,43 +128,77 @@ struct aspeed_spi_data {
  	u32	timing;
  	u32	hclk_mask;
  	u32	hdiv_max;
@@ -236,7 +237,7 @@
 +	if (field == SPI_OP_ALL || field == SPI_OP_CMD) {
 +		if (op->cmd.buswidth == 4)
 +			return CTRL_IO_QUAD_IO;
- 	}
++	}
 +
 +	if (field == SPI_OP_ALL || field == SPI_OP_ADDR) {
 +		if (op->addr.buswidth == 4)
@@ -250,13 +251,13 @@
 +			return CTRL_IO_QUAD_DATA;
 +		else if (op->data.buswidth == 2)
 +			return CTRL_IO_DUAL_DATA;
-+	}
+ 	}
 +
 +	return CTRL_IO_SINGLE_DATA;
  }
  
  static void aspeed_spi_set_io_mode(struct aspeed_spi_chip *chip, u32 io_mode)
-@@ -137,6 +220,7 @@ static void aspeed_spi_start_user(struct aspeed_spi_chip *chip)
+@@ -137,11 +221,12 @@ static void aspeed_spi_start_user(struct aspeed_spi_chip *chip)
  
  	ctl &= ~CTRL_CE_STOP_ACTIVE;
  	writel(ctl, chip->ctl);
@@ -264,7 +265,13 @@
  }
  
  static void aspeed_spi_stop_user(struct aspeed_spi_chip *chip)
-@@ -178,8 +262,13 @@ static int aspeed_spi_write_to_ahb(void __iomem *dst, const void *buf, size_t le
+ {
+-	u32 ctl = chip->ctl_val[ASPEED_SPI_READ] |
++	u32 ctl = chip->ctl_val[ASPEED_SPI_BASE] |
+ 		CTRL_IO_MODE_USER | CTRL_CE_STOP_ACTIVE;
+ 
+ 	writel(ctl, chip->ctl);
+@@ -178,8 +263,13 @@ static int aspeed_spi_write_to_ahb(void __iomem *dst, const void *buf, size_t le
  	return 0;
  }
  
@@ -280,7 +287,7 @@
  {
  	__be32 temp;
  	u32 cmdaddr;
-@@ -187,20 +276,18 @@ static int aspeed_spi_send_cmd_addr(struct aspeed_spi_chip *chip, u8 addr_nbytes
+@@ -187,20 +277,18 @@ static int aspeed_spi_send_cmd_addr(struct aspeed_spi_chip *chip, u8 addr_nbytes
  	switch (addr_nbytes) {
  	case 3:
  		cmdaddr = offset & 0xFFFFFF;
@@ -304,7 +311,7 @@
  	return 0;
  }
  
-@@ -230,58 +317,88 @@ static ssize_t aspeed_spi_read_user(struct aspeed_spi_chip *chip,
+@@ -230,27 +318,36 @@ static ssize_t aspeed_spi_read_user(struct aspeed_spi_chip *chip,
  				    const struct spi_mem_op *op,
  				    u64 offset, size_t len, void *buf)
  {
@@ -325,8 +332,7 @@
 +	aspeed_spi_set_io_mode(chip, io_mode);
 +	ret = aspeed_spi_send_addr(chip, op->addr.nbytes, op->addr.val);
  	if (ret < 0)
--		return ret;
-+		goto stop_user;
+ 		goto stop_user;
  
  	if (op->dummy.buswidth && op->dummy.nbytes) {
 -		for (i = 0; i < op->dummy.nbytes / op->dummy.buswidth; i++)
@@ -341,14 +347,13 @@
 -
  	aspeed_spi_read_from_ahb(buf, chip->ahb_base, len);
 +
-+stop_user:
+ stop_user:
  	aspeed_spi_stop_user(chip);
--	return 0;
 +
-+	return ret;
+ 	return ret;
  }
  
- static ssize_t aspeed_spi_write_user(struct aspeed_spi_chip *chip,
+@@ -258,32 +355,51 @@ static ssize_t aspeed_spi_write_user(struct aspeed_spi_chip *chip,
  				     const struct spi_mem_op *op)
  {
  	int ret;
@@ -365,18 +370,16 @@
 +	aspeed_spi_set_io_mode(chip, io_mode);
 +	ret = aspeed_spi_send_addr(chip, op->addr.nbytes, op->addr.val);
  	if (ret < 0)
--		return ret;
-+		goto stop_user;
+ 		goto stop_user;
 +
 +	io_mode = aspeed_spi_get_io_mode(op, SPI_OP_DATA);
 +	aspeed_spi_set_io_mode(chip, io_mode);
  	aspeed_spi_write_to_ahb(chip->ahb_base, op->data.buf.out, op->data.nbytes);
 +
-+stop_user:
+ stop_user:
  	aspeed_spi_stop_user(chip);
--	return 0;
 +
-+	return ret;
+ 	return ret;
  }
  
  /* support for 1-1-1, 1-1-2 or 1-1-4 */
@@ -405,7 +408,13 @@
  			return false;
  	}
  
-@@ -297,8 +414,6 @@ static int do_aspeed_spi_exec_op(struct spi_mem *mem, const struct spi_mem_op *o
+@@ -294,13 +410,12 @@ static bool aspeed_spi_supports_op(struct spi_mem *mem, const struct spi_mem_op
+ }
+ 
+ static const struct aspeed_spi_data ast2400_spi_data;
++static const struct aspeed_spi_data ast2500_fmc_data;
+ 
+ static int do_aspeed_spi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
  {
  	struct aspeed_spi *aspi = spi_controller_get_devdata(mem->spi->controller);
  	struct aspeed_spi_chip *chip = &aspi->chips[spi_get_chipselect(mem->spi, 0)];
@@ -414,7 +423,7 @@
  	int ret = 0;
  
  	dev_dbg(aspi->dev,
-@@ -308,40 +423,6 @@ static int do_aspeed_spi_exec_op(struct spi_mem *mem, const struct spi_mem_op *o
+@@ -310,39 +425,11 @@ static int do_aspeed_spi_exec_op(struct spi_mem *mem, const struct spi_mem_op *o
  		op->dummy.buswidth, op->data.buswidth,
  		op->addr.nbytes, op->dummy.nbytes, op->data.nbytes);
  
@@ -451,11 +460,15 @@
 -	if (addr_mode != addr_mode_backup)
 -		writel(addr_mode, aspi->regs + CE_CTRL_REG);
 -	writel(ctl_val, chip->ctl);
--
++	/* no operation for AST2500 when SW reset is executed */
++	if (aspi->data == &ast2500_fmc_data &&
++	    (op->cmd.opcode == SPINOR_OP_SRSTEN ||
++	     op->cmd.opcode == SPINOR_OP_SRST))
++		return ret;
+ 
  	if (op->data.dir == SPI_MEM_DATA_IN) {
  		if (!op->addr.nbytes)
- 			ret = aspeed_spi_read_reg(chip, op);
-@@ -356,12 +437,520 @@ static int do_aspeed_spi_exec_op(struct spi_mem *mem, const struct spi_mem_op *o
+@@ -358,12 +445,520 @@ static int do_aspeed_spi_exec_op(struct spi_mem *mem, const struct spi_mem_op *o
  	}
  
  	/* Restore defaults */
@@ -978,7 +991,7 @@
  static int aspeed_spi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
  {
  	int ret;
-@@ -381,171 +970,310 @@ static const char *aspeed_spi_get_name(struct spi_mem *mem)
+@@ -383,171 +978,310 @@ static const char *aspeed_spi_get_name(struct spi_mem *mem)
  			      spi_get_chipselect(mem->spi, 0));
  }
  
@@ -1019,7 +1032,7 @@
 -			 windows[cs].offset, windows[cs].size);
 +		if (aspi->chips[cs].ahb_base)
 +			devm_iounmap(dev, aspi->chips[cs].ahb_base);
- 	}
++	}
 +
 +	for (cs = 0; cs < aspi->data->max_cs; cs++) {
 +		seg_reg = seg_reg_base + cs * 4;
@@ -1089,7 +1102,7 @@
 +				(u64)start, (u64)end - 1);
 +			return -ENOMEM;
 +		}
-+	}
+ 	}
 +
 +	return 0;
  }
@@ -1123,19 +1136,19 @@
 -	chip->ahb_window_size = win->size;
 +	for (cs = 0; cs < aspi->num_cs; cs++)
 +		aspi->chips[cs].ahb_window_sz = aspi->data->min_window_sz;
++
++	/* Close unused CS */
++	for (cs = aspi->num_cs; cs < aspi->data->max_cs; cs++)
++		aspi->chips[cs].ahb_window_sz = 0;
  
 -	dev_dbg(aspi->dev, "CE%d default window [ 0x%.8x - 0x%.8x ] %dMB",
 -		chip->cs, aspi->ahb_base_phy + win->offset,
 -		aspi->ahb_base_phy + win->offset + win->size - 1,
 -		win->size >> 20);
-+	/* Close unused CS */
-+	for (cs = aspi->num_cs; cs < aspi->data->max_cs; cs++)
-+		aspi->chips[cs].ahb_window_sz = 0;
- 
--	return chip->ahb_window_size ? 0 : -1;
 +	if (aspi->data->adjust_window)
 +		aspi->data->adjust_window(aspi);
-+
+ 
+-	return chip->ahb_window_size ? 0 : -1;
 +	return aspeed_spi_set_window(aspi);
  }
  
@@ -1195,7 +1208,8 @@
 +
 +	return 0;
 +}
-+
+ 
+-	writel(seg_val, seg_reg);
 +static int aspeed_adjust_window_ast2400(struct aspeed_spi *aspi)
 +{
 +	int ret;
@@ -1234,49 +1248,6 @@
 +			chips[cs].ahb_window_sz = aspi->data->min_window_sz;
 +	}
  
--	writel(seg_val, seg_reg);
-+	/*
-+	 * If commnad mode or normal mode is used, the start address of a
-+	 * decoding range should be multiple of its related flash size.
-+	 * Namely, the total decoding size from flash 0 to flash N should
-+	 * be multiple of the size of flash (N + 1).
-+	 */
-+	for (cs = aspi->num_cs - 1; cs >= 0; cs--) {
-+		pre_sz = 0;
-+		for (i = 0; i < cs; i++)
-+			pre_sz += chips[i].ahb_window_sz;
-+
-+		if (chips[cs].ahb_window_sz != 0 &&
-+		    (pre_sz % chips[cs].ahb_window_sz) != 0) {
-+			extra_sz = chips[cs].ahb_window_sz -
-+				   (pre_sz % chips[cs].ahb_window_sz);
-+			chips[0].ahb_window_sz += extra_sz;
-+		}
-+	}
-+
-+	ret = aspeed_spi_trim_window_size(aspi);
-+	if (ret != 0)
-+		return ret;
-+
-+	if (aspi->data == &ast2500_spi_data)
-+		chips[1].ahb_window_sz = 0x08000000 - chips[0].ahb_window_sz;
-+
-+	return 0;
-+}
-+
-+static int aspeed_adjust_window_ast2600(struct aspeed_spi *aspi)
-+{
-+	int ret;
-+	int i;
-+	int cs;
-+	size_t pre_sz;
-+	size_t extra_sz;
-+	struct aspeed_spi_chip *chips = aspi->chips;
-+
-+	/* Close unused CS. */
-+	for (cs = aspi->num_cs; cs < aspi->data->max_cs; cs++)
-+		chips[cs].ahb_window_sz = 0;
- 
  	/*
 -	 * Restore initial value if something goes wrong else we could
 -	 * loose access to the chip.
@@ -1311,6 +1282,48 @@
 +	ret = aspeed_spi_trim_window_size(aspi);
 +	if (ret != 0)
 +		return ret;
++
++	if (aspi->data == &ast2500_spi_data)
++		chips[1].ahb_window_sz = 0x08000000 - chips[0].ahb_window_sz;
++
++	return 0;
++}
++
++static int aspeed_adjust_window_ast2600(struct aspeed_spi *aspi)
++{
++	int ret;
++	int i;
++	int cs;
++	size_t pre_sz;
++	size_t extra_sz;
++	struct aspeed_spi_chip *chips = aspi->chips;
++
++	/* Close unused CS. */
++	for (cs = aspi->num_cs; cs < aspi->data->max_cs; cs++)
++		chips[cs].ahb_window_sz = 0;
++
++	/*
++	 * If commnad mode or normal mode is used, the start address of a
++	 * decoding range should be multiple of its related flash size.
++	 * Namely, the total decoding size from flash 0 to flash N should
++	 * be multiple of the size of flash (N + 1).
++	 */
++	for (cs = aspi->num_cs - 1; cs >= 0; cs--) {
++		pre_sz = 0;
++		for (i = 0; i < cs; i++)
++			pre_sz += chips[i].ahb_window_sz;
++
++		if (chips[cs].ahb_window_sz != 0 &&
++		    (pre_sz % chips[cs].ahb_window_sz) != 0) {
++			extra_sz = chips[cs].ahb_window_sz -
++				   (pre_sz % chips[cs].ahb_window_sz);
++			chips[0].ahb_window_sz += extra_sz;
++		}
++	}
++
++	ret = aspeed_spi_trim_window_size(aspi);
++	if (ret != 0)
++		return ret;
  
  	return 0;
  }
@@ -1401,7 +1414,7 @@
  	return 0;
  }
  
-@@ -557,6 +1285,9 @@ static int aspeed_spi_dirmap_create(struct spi_mem_dirmap_desc *desc)
+@@ -559,6 +1293,9 @@ static int aspeed_spi_dirmap_create(struct spi_mem_dirmap_desc *desc)
  	struct aspeed_spi_chip *chip = &aspi->chips[spi_get_chipselect(desc->mem->spi, 0)];
  	struct spi_mem_op *op = &desc->info.op_tmpl;
  	u32 ctl_val;
@@ -1411,7 +1424,7 @@
  	int ret = 0;
  
  	dev_dbg(aspi->dev,
-@@ -569,50 +1300,108 @@ static int aspeed_spi_dirmap_create(struct spi_mem_dirmap_desc *desc)
+@@ -571,50 +1308,108 @@ static int aspeed_spi_dirmap_create(struct spi_mem_dirmap_desc *desc)
  
  	chip->clk_freq = desc->mem->spi->max_speed_hz;
  
@@ -1552,7 +1565,7 @@
  
  	return ret;
  }
-@@ -624,7 +1413,7 @@ static ssize_t aspeed_spi_dirmap_read(struct spi_mem_dirmap_desc *desc,
+@@ -626,7 +1421,7 @@ static ssize_t aspeed_spi_dirmap_read(struct spi_mem_dirmap_desc *desc,
  	struct aspeed_spi_chip *chip = &aspi->chips[spi_get_chipselect(desc->mem->spi, 0)];
  
  	/* Switch to USER command mode if mapping window is too small */
@@ -1561,7 +1574,7 @@
  		int ret;
  
  		ret = aspeed_spi_read_user(chip, &desc->info.op_tmpl, offset, len, buf);
-@@ -645,6 +1434,48 @@ static const struct spi_controller_mem_ops aspeed_spi_mem_ops = {
+@@ -647,6 +1442,48 @@ static const struct spi_controller_mem_ops aspeed_spi_mem_ops = {
  	.dirmap_read = aspeed_spi_dirmap_read,
  };
  
@@ -1610,7 +1623,7 @@
  static void aspeed_spi_chip_set_type(struct aspeed_spi *aspi, unsigned int cs, int type)
  {
  	u32 reg;
-@@ -673,6 +1504,8 @@ static int aspeed_spi_setup(struct spi_device *spi)
+@@ -675,6 +1512,8 @@ static int aspeed_spi_setup(struct spi_device *spi)
  	const struct aspeed_spi_data *data = aspi->data;
  	unsigned int cs = spi_get_chipselect(spi, 0);
  	struct aspeed_spi_chip *chip = &aspi->chips[cs];
@@ -1619,7 +1632,7 @@
  
  	chip->aspi = aspi;
  	chip->cs = cs;
-@@ -682,15 +1515,20 @@ static int aspeed_spi_setup(struct spi_device *spi)
+@@ -684,15 +1523,20 @@ static int aspeed_spi_setup(struct spi_device *spi)
  	if (data->hastype)
  		aspeed_spi_chip_set_type(aspi, cs, CONFIG_TYPE_SPI);
  
@@ -1645,7 +1658,7 @@
  	dev_dbg(aspi->dev, "CE%d setup done\n", cs);
  	return 0;
  }
-@@ -720,7 +1558,8 @@ static int aspeed_spi_probe(struct platform_device *pdev)
+@@ -722,7 +1566,8 @@ static int aspeed_spi_probe(struct platform_device *pdev)
  	struct spi_controller *ctlr;
  	struct aspeed_spi *aspi;
  	struct resource *res;
@@ -1655,7 +1668,7 @@
  
  	data = of_device_get_match_data(&pdev->dev);
  	if (!data)
-@@ -735,20 +1574,16 @@ static int aspeed_spi_probe(struct platform_device *pdev)
+@@ -737,20 +1582,16 @@ static int aspeed_spi_probe(struct platform_device *pdev)
  	aspi->data = data;
  	aspi->dev = dev;
  
@@ -1681,7 +1694,7 @@
  	if (IS_ERR(aspi->clk)) {
  		dev_err(dev, "missing clock\n");
  		return PTR_ERR(aspi->clk);
-@@ -760,31 +1595,140 @@ static int aspeed_spi_probe(struct platform_device *pdev)
+@@ -762,31 +1603,140 @@ static int aspeed_spi_probe(struct platform_device *pdev)
  		return -EINVAL;
  	}
  
@@ -1832,7 +1845,7 @@
  	return ret;
  }
  
-@@ -792,8 +1736,14 @@ static void aspeed_spi_remove(struct platform_device *pdev)
+@@ -794,8 +1744,14 @@ static void aspeed_spi_remove(struct platform_device *pdev)
  {
  	struct aspeed_spi *aspi = platform_get_drvdata(pdev);
  
@@ -1848,7 +1861,7 @@
  }
  
  /*
-@@ -805,19 +1755,20 @@ static void aspeed_spi_remove(struct platform_device *pdev)
+@@ -807,19 +1763,20 @@ static void aspeed_spi_remove(struct platform_device *pdev)
   * The address range is encoded with absolute addresses in the overall
   * mapping window.
   */
@@ -1873,7 +1886,7 @@
  }
  
  /*
-@@ -827,18 +1778,18 @@ static u32 aspeed_spi_segment_reg(struct aspeed_spi *aspi, u32 start, u32 end)
+@@ -829,18 +1786,18 @@ static u32 aspeed_spi_segment_reg(struct aspeed_spi *aspi, u32 start, u32 end)
  
  #define AST2600_SEG_ADDR_MASK 0x0ff00000
  
@@ -1896,7 +1909,7 @@
  
  	/* segment is disabled */
  	if (!end_offset)
-@@ -848,28 +1799,193 @@ static u32 aspeed_spi_segment_ast2600_end(struct aspeed_spi *aspi,
+@@ -850,28 +1807,193 @@ static u32 aspeed_spi_segment_ast2600_end(struct aspeed_spi *aspi,
  }
  
  static u32 aspeed_spi_segment_ast2600_reg(struct aspeed_spi *aspi,
@@ -2095,7 +2108,7 @@
  		memcpy_fromio(test_buf, chip->ahb_base, CALIBRATE_BUF_SIZE);
  		if (memcmp(test_buf, golden_buf, CALIBRATE_BUF_SIZE) != 0) {
  #if defined(VERBOSE_DEBUG)
-@@ -882,7 +1998,10 @@ static bool aspeed_spi_check_reads(struct aspeed_spi_chip *chip,
+@@ -884,7 +2006,10 @@ static bool aspeed_spi_check_reads(struct aspeed_spi_chip *chip,
  	return true;
  }
  
@@ -2107,7 +2120,7 @@
  
  /*
   * The timing register is shared by all devices. Only update for CE0.
-@@ -912,7 +2031,7 @@ static int aspeed_spi_calibrate(struct aspeed_spi_chip *chip, u32 hdiv,
+@@ -914,7 +2039,7 @@ static int aspeed_spi_calibrate(struct aspeed_spi_chip *chip, u32 hdiv,
  		pass = aspeed_spi_check_reads(chip, golden_buf, test_buf);
  		dev_dbg(aspi->dev,
  			"  * [%08x] %d HCLK delay, %dns DI delay : %s",
@@ -2116,7 +2129,7 @@
  			pass ? "PASS" : "FAIL");
  		if (pass) {
  			pass_count++;
-@@ -958,17 +2077,6 @@ static bool aspeed_spi_check_calib_data(const u8 *test_buf, u32 size)
+@@ -960,17 +2085,6 @@ static bool aspeed_spi_check_calib_data(const u8 *test_buf, u32 size)
  	return cnt >= 64;
  }
  
@@ -2134,7 +2147,7 @@
  static int aspeed_spi_do_calibration(struct aspeed_spi_chip *chip)
  {
  	struct aspeed_spi *aspi = chip->aspi;
-@@ -979,10 +2087,17 @@ static int aspeed_spi_do_calibration(struct aspeed_spi_chip *chip)
+@@ -981,10 +2095,17 @@ static int aspeed_spi_do_calibration(struct aspeed_spi_chip *chip)
  	u8 *golden_buf = NULL;
  	u8 *test_buf = NULL;
  	int i, rc, best_div = -1;
@@ -2152,7 +2165,7 @@
  	/*
  	 * use the related low frequency to get check calibration data
  	 * and get golden data.
-@@ -998,7 +2113,7 @@ static int aspeed_spi_do_calibration(struct aspeed_spi_chip *chip)
+@@ -1000,7 +2121,7 @@ static int aspeed_spi_do_calibration(struct aspeed_spi_chip *chip)
  
  	memcpy_fromio(golden_buf, chip->ahb_base, CALIBRATE_BUF_SIZE);
  	if (!aspeed_spi_check_calib_data(golden_buf, CALIBRATE_BUF_SIZE)) {
@@ -2161,7 +2174,7 @@
  		goto no_calib;
  	}
  
-@@ -1008,42 +2123,81 @@ static int aspeed_spi_do_calibration(struct aspeed_spi_chip *chip)
+@@ -1010,42 +2131,81 @@ static int aspeed_spi_do_calibration(struct aspeed_spi_chip *chip)
  #endif
  
  	/* Now we iterate the HCLK dividers until we find our breaking point */
@@ -2255,7 +2268,7 @@
  #define TIMING_REG_AST2600(chip)				\
  	((chip)->aspi->regs + (chip)->aspi->data->timing +	\
  	 (chip)->cs * 4)
-@@ -1051,60 +2205,104 @@ static int aspeed_spi_do_calibration(struct aspeed_spi_chip *chip)
+@@ -1053,60 +2213,104 @@ static int aspeed_spi_do_calibration(struct aspeed_spi_chip *chip)
  static int aspeed_spi_ast2600_calibrate(struct aspeed_spi_chip *chip, u32 hdiv,
  					const u8 *golden_buf, u8 *test_buf)
  {
@@ -2391,7 +2404,7 @@
  	.max_cs	       = 5,
  	.hastype       = true,
  	.we0	       = 16,
-@@ -1112,13 +2310,17 @@ static const struct aspeed_spi_data ast2400_fmc_data = {
+@@ -1114,13 +2318,17 @@ static const struct aspeed_spi_data ast2400_fmc_data = {
  	.timing	       = CE0_TIMING_COMPENSATION_REG,
  	.hclk_mask     = 0xfffff0ff,
  	.hdiv_max      = 1,
@@ -2409,7 +2422,7 @@
  	.max_cs	       = 1,
  	.hastype       = false,
  	.we0	       = 0,
-@@ -1126,11 +2328,13 @@ static const struct aspeed_spi_data ast2400_spi_data = {
+@@ -1128,11 +2336,13 @@ static const struct aspeed_spi_data ast2400_spi_data = {
  	.timing	       = 0x14,
  	.hclk_mask     = 0xfffff0ff,
  	.hdiv_max      = 1,
@@ -2423,7 +2436,7 @@
  	.max_cs	       = 3,
  	.hastype       = true,
  	.we0	       = 16,
-@@ -1138,13 +2342,17 @@ static const struct aspeed_spi_data ast2500_fmc_data = {
+@@ -1140,13 +2350,17 @@ static const struct aspeed_spi_data ast2500_fmc_data = {
  	.timing	       = CE0_TIMING_COMPENSATION_REG,
  	.hclk_mask     = 0xffffd0ff,
  	.hdiv_max      = 1,
@@ -2441,7 +2454,7 @@
  	.max_cs	       = 2,
  	.hastype       = false,
  	.we0	       = 16,
-@@ -1152,13 +2360,17 @@ static const struct aspeed_spi_data ast2500_spi_data = {
+@@ -1154,13 +2368,17 @@ static const struct aspeed_spi_data ast2500_spi_data = {
  	.timing	       = CE0_TIMING_COMPENSATION_REG,
  	.hclk_mask     = 0xffffd0ff,
  	.hdiv_max      = 1,
@@ -2459,7 +2472,7 @@
  	.max_cs	       = 3,
  	.hastype       = false,
  	.mode_bits     = SPI_RX_QUAD | SPI_TX_QUAD,
-@@ -1167,13 +2379,17 @@ static const struct aspeed_spi_data ast2600_fmc_data = {
+@@ -1169,13 +2387,17 @@ static const struct aspeed_spi_data ast2600_fmc_data = {
  	.timing	       = CE0_TIMING_COMPENSATION_REG,
  	.hclk_mask     = 0xf0fff0ff,
  	.hdiv_max      = 2,
@@ -2477,7 +2490,7 @@
  	.max_cs	       = 2,
  	.hastype       = false,
  	.mode_bits     = SPI_RX_QUAD | SPI_TX_QUAD,
-@@ -1182,10 +2398,50 @@ static const struct aspeed_spi_data ast2600_spi_data = {
+@@ -1184,10 +2406,50 @@ static const struct aspeed_spi_data ast2600_spi_data = {
  	.timing	       = CE0_TIMING_COMPENSATION_REG,
  	.hclk_mask     = 0xf0fff0ff,
  	.hdiv_max      = 2,
@@ -2528,7 +2541,7 @@
  };
  
  static const struct of_device_id aspeed_spi_matches[] = {
-@@ -1195,6 +2451,8 @@ static const struct of_device_id aspeed_spi_matches[] = {
+@@ -1197,6 +2459,8 @@ static const struct of_device_id aspeed_spi_matches[] = {
  	{ .compatible = "aspeed,ast2500-spi", .data = &ast2500_spi_data },
  	{ .compatible = "aspeed,ast2600-fmc", .data = &ast2600_fmc_data },
  	{ .compatible = "aspeed,ast2600-spi", .data = &ast2600_spi_data },
@@ -2538,11 +2551,11 @@
  };
  MODULE_DEVICE_TABLE(of, aspeed_spi_matches);
 diff --git a/drivers/spi/spi-aspeed-txrx.c b/drivers/spi/spi-aspeed-txrx.c
-new file mode 100644
-index 000000000..c8f173fd8
+new file mode 100755
+index 000000000..eed9550da
 --- /dev/null
 +++ b/drivers/spi/spi-aspeed-txrx.c
-@@ -0,0 +1,643 @@
+@@ -0,0 +1,644 @@
 +// SPDX-License-Identifier: GPL-2.0-or-later
 +/*
 + * Copyright (C) ASPEED Technology Inc.
@@ -2898,7 +2911,8 @@
 +	for (i = 0; i < len; i++) {
 +		writeb(tx_buf[i], dst);
 +
-+		if (rx_buf && (host->flag & SPI_FULL_DUPLEX)) {
++		if (rx_buf && ((host->flag & SPI_FULL_DUPLEX) ||
++			       tx_buf == rx_buf)) {
 +			rx_buf[i] = readb(host->ctrl_reg + SPI_FULL_DUPLEX_RX_REG);
 +			*full_duplex_rx = true;
 +		}
diff --git a/recipes-kernel/linux/files/0008-i3c-mipi-i3c-hci-aspeed-Modify-the-tCAS-and-tCBP.patch b/recipes-kernel/linux/files/0008-i3c-mipi-i3c-hci-aspeed-Modify-the-tCAS-and-tCBP.patch
deleted file mode 100644
index 0c43d08..0000000
--- a/recipes-kernel/linux/files/0008-i3c-mipi-i3c-hci-aspeed-Modify-the-tCAS-and-tCBP.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-From 6485af913350deb88ae903d416360225d231c04c Mon Sep 17 00:00:00 2001
-From: Billy Tsai <billy_tsai@aspeedtech.com>
-Date: Mon, 21 Apr 2025 15:51:54 +0800
-Subject: [PATCH 8/9] i3c: mipi-i3c-hci: aspeed: Modify the tCAS and tCBP
-
-Using push-pull high count as both tCAS and tCBP instead of the fixed
-40ns.
-
-Signed-off-by: Billy Tsai <billy_tsai@aspeedtech.com>
-Change-Id: I1915e1a14124a716b4f419aec879769a7bb0d50a
----
- drivers/i3c/master/mipi-i3c-hci/core.c | 7 +++----
- 1 file changed, 3 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c
-index 26795db6efed..19df976ea267 100644
---- a/drivers/i3c/master/mipi-i3c-hci/core.c
-+++ b/drivers/i3c/master/mipi-i3c-hci/core.c
-@@ -246,6 +246,9 @@ static void aspeed_i3c_of_populate_bus_timing(struct i3c_hci *hci, struct device
- 	ast_phy_write(PHY_I3C_SDR0_CTRL1, ctrl1);
- 	ast_phy_write(PHY_I3C_DDR_CTRL1, ctrl1);
- 
-+	/* The push-pull high count is used as both tCAS and tCBP. */
-+	ast_phy_write(PHY_I3C_OD_CTRL0, FIELD_PREP(PHY_I3C_OD_CTRL0_CAS, hcnt) |
-+						FIELD_PREP(PHY_I3C_OD_CTRL0_CBP, hcnt));
- 	/*
- 	 * The SR_P hold time uses the default value, and the SR_P low count is
- 	 * the same as the push-pull low count.
-@@ -283,10 +286,6 @@ static void aspeed_i3c_of_populate_bus_timing(struct i3c_hci *hci, struct device
- 	ast_phy_write(PHY_I3C_OD_CTRL3, FIELD_PREP(PHY_I3C_OD_CTRL3_HD_DAT, hcnt) |
- 						FIELD_PREP(PHY_I3C_OD_CTRL3_AHD_DAT, lcnt));
- 
--	hcnt = DIV_ROUND_CLOSEST(PHY_I3C_OD_DEFAULT_CAS_NS, core_period) - 1;
--	lcnt = DIV_ROUND_CLOSEST(PHY_I3C_OD_DEFAULT_CBP_NS, core_period) - 1;
--	ast_phy_write(PHY_I3C_OD_CTRL0, FIELD_PREP(PHY_I3C_OD_CTRL0_CAS, hcnt) |
--						FIELD_PREP(PHY_I3C_OD_CTRL0_CBP, lcnt));
- 	if (internal_pu)
- 		ast_phy_write(PHY_SW_FORCE_CTRL,
- 			      PHY_SW_FORCE_CTRL_SCL_PU_EN | PHY_SW_FORCE_CTRL_SDA_PU_EN |
--- 
-2.49.0.906.g1f30a19c02-goog
-
diff --git a/recipes-kernel/linux/files/0009-Add-watchdog-driver-for-ast2700.patch b/recipes-kernel/linux/files/0009-Add-watchdog-driver-for-ast2700.patch
index 25af4ac..ffd0c5d 100644
--- a/recipes-kernel/linux/files/0009-Add-watchdog-driver-for-ast2700.patch
+++ b/recipes-kernel/linux/files/0009-Add-watchdog-driver-for-ast2700.patch
@@ -1,58 +1,34 @@
-From 56a17e6d38fdd1c563f1929057f8ce8e3a9c4a08 Mon Sep 17 00:00:00 2001
-From: "yung-sheng.huang" <yung-sheng.huang@fii-na.corp-partner.google.com>
-Date: Tue, 15 Apr 2025 11:45:08 +0800
-Subject: [PATCH 09/26] Add watchdog driver for ast2700
+From b712351907db6890af6bec3a5d341e0830949670 Mon Sep 17 00:00:00 2001
+From: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+Date: Thu, 17 Jul 2025 08:02:29 +0800
+Subject: [PATCH] Add watchdog driver for ast2700
 
-This is base on aspeed SDK 9.06.
+This is base on aspeed SDK 9.07.
 
 Source:
 AspeedTech-BMC github:
 https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/
-(cherry picked from commit v00.06.06)
+(cherry picked from commit v00.06.07)
 
-Signed-off-by: yung-sheng.huang <yung-sheng.huang@fii-na.corp-partner.google.com>
+Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
 ---
- drivers/watchdog/aspeed_wdt.c | 185 ++++++++++++++++++++++++++++++----
- 1 file changed, 167 insertions(+), 18 deletions(-)
+ drivers/watchdog/aspeed_wdt.c | 104 ++++++++++++++++++++++++++++------
+ 1 file changed, 88 insertions(+), 16 deletions(-)
 
 diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c
-index b72a858bb..e2bf25afb 100644
+index 001b2c931..65511878d 100644
 --- a/drivers/watchdog/aspeed_wdt.c
 +++ b/drivers/watchdog/aspeed_wdt.c
-@@ -11,21 +11,32 @@
- #include <linux/io.h>
- #include <linux/kernel.h>
- #include <linux/kstrtox.h>
-+#include <linux/mfd/syscon.h>
- #include <linux/module.h>
- #include <linux/of.h>
- #include <linux/of_irq.h>
- #include <linux/platform_device.h>
-+#include <linux/regmap.h>
- #include <linux/watchdog.h>
- 
- static bool nowayout = WATCHDOG_NOWAYOUT;
- module_param(nowayout, bool, 0);
- MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
- 				__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
-+struct aspeed_wdt_scu {
-+	const char *compatible;
-+	u32 reset_status_reg;
-+	u32 wdt_reset_mask;
-+	u32 wdt_reset_mask_shift;
-+};
- 
- struct aspeed_wdt_config {
- 	u32 ext_pulse_width_mask;
+@@ -35,6 +35,8 @@ struct aspeed_wdt_config {
  	u32 irq_shift;
  	u32 irq_mask;
-+	struct aspeed_wdt_scu scu;
+ 	struct aspeed_wdt_scu scu;
 +	u32 reset_mask_num;
 +	void (*wdt_writel)(u32 val, void __iomem *addr);
  };
  
  struct aspeed_wdt {
-@@ -35,28 +46,85 @@ struct aspeed_wdt {
+@@ -44,6 +46,9 @@ struct aspeed_wdt {
  	const struct aspeed_wdt_config *cfg;
  };
  
@@ -62,41 +38,28 @@
  static const struct aspeed_wdt_config ast2400_config = {
  	.ext_pulse_width_mask = 0xff,
  	.irq_shift = 0,
- 	.irq_mask = 0,
-+	.scu = {
-+		.compatible = "aspeed,ast2400-scu",
-+		.reset_status_reg = 0x3c,
-+		.wdt_reset_mask = 0x1,
-+		.wdt_reset_mask_shift = 1,
-+	},
+@@ -54,6 +59,8 @@ static const struct aspeed_wdt_config ast2400_config = {
+ 		.wdt_reset_mask = 0x1,
+ 		.wdt_reset_mask_shift = 1,
+ 	},
 +	.reset_mask_num = 1,
 +	.wdt_writel = wdt_writel_normal,
  };
  
  static const struct aspeed_wdt_config ast2500_config = {
- 	.ext_pulse_width_mask = 0xfffff,
- 	.irq_shift = 12,
- 	.irq_mask = GENMASK(31, 12),
-+	.scu = {
-+		.compatible = "aspeed,ast2500-scu",
-+		.reset_status_reg = 0x3c,
-+		.wdt_reset_mask = 0x1,
-+		.wdt_reset_mask_shift = 2,
-+	},
+@@ -66,6 +73,8 @@ static const struct aspeed_wdt_config ast2500_config = {
+ 		.wdt_reset_mask = 0x1,
+ 		.wdt_reset_mask_shift = 2,
+ 	},
 +	.reset_mask_num = 1,
 +	.wdt_writel = wdt_writel_normal,
  };
  
  static const struct aspeed_wdt_config ast2600_config = {
- 	.ext_pulse_width_mask = 0xfffff,
- 	.irq_shift = 0,
- 	.irq_mask = GENMASK(31, 10),
-+	.scu = {
-+		.compatible = "aspeed,ast2600-scu",
-+		.reset_status_reg = 0x74,
-+		.wdt_reset_mask = 0xf,
-+		.wdt_reset_mask_shift = 16,
-+	},
+@@ -78,12 +87,44 @@ static const struct aspeed_wdt_config ast2600_config = {
+ 		.wdt_reset_mask = 0xf,
+ 		.wdt_reset_mask_shift = 16,
+ 	},
 +	.reset_mask_num = 2,
 +	.wdt_writel = wdt_writel_normal,
 +};
@@ -138,7 +101,7 @@
  	{ },
  };
  MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table);
-@@ -69,7 +137,8 @@ MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table);
+@@ -96,7 +137,8 @@ MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table);
  #define   WDT_CTRL_RESET_MODE_SOC	(0x00 << 5)
  #define   WDT_CTRL_RESET_MODE_FULL_CHIP	(0x01 << 5)
  #define   WDT_CTRL_RESET_MODE_ARM_CPU	(0x10 << 5)
@@ -148,7 +111,7 @@
  #define   WDT_CTRL_WDT_EXT		BIT(3)
  #define   WDT_CTRL_WDT_INTR		BIT(2)
  #define   WDT_CTRL_RESET_SYSTEM		BIT(1)
-@@ -79,6 +148,8 @@ MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table);
+@@ -106,6 +148,8 @@ MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table);
  #define   WDT_TIMEOUT_STATUS_BOOT_SECONDARY	BIT(1)
  #define WDT_CLEAR_TIMEOUT_STATUS	0x14
  #define   WDT_CLEAR_TIMEOUT_AND_BOOT_CODE_SELECTION	BIT(0)
@@ -157,7 +120,7 @@
  
  /*
   * WDT_RESET_WIDTH controls the characteristics of the external pulse (if
-@@ -119,6 +190,17 @@ MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table);
+@@ -146,6 +190,17 @@ MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table);
  #define WDT_DEFAULT_TIMEOUT	30
  #define WDT_RATE_1MHZ		1000000
  
@@ -175,7 +138,7 @@
  static struct aspeed_wdt *to_aspeed_wdt(struct watchdog_device *wdd)
  {
  	return container_of(wdd, struct aspeed_wdt, wdd);
-@@ -128,10 +210,10 @@ static void aspeed_wdt_enable(struct aspeed_wdt *wdt, int count)
+@@ -155,10 +210,10 @@ static void aspeed_wdt_enable(struct aspeed_wdt *wdt, int count)
  {
  	wdt->ctrl |= WDT_CTRL_ENABLE;
  
@@ -190,7 +153,7 @@
  }
  
  static int aspeed_wdt_start(struct watchdog_device *wdd)
-@@ -148,7 +230,7 @@ static int aspeed_wdt_stop(struct watchdog_device *wdd)
+@@ -175,7 +230,7 @@ static int aspeed_wdt_stop(struct watchdog_device *wdd)
  	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
  
  	wdt->ctrl &= ~WDT_CTRL_ENABLE;
@@ -199,7 +162,7 @@
  
  	return 0;
  }
-@@ -157,7 +239,7 @@ static int aspeed_wdt_ping(struct watchdog_device *wdd)
+@@ -184,7 +239,7 @@ static int aspeed_wdt_ping(struct watchdog_device *wdd)
  {
  	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
  
@@ -208,7 +171,7 @@
  
  	return 0;
  }
-@@ -172,8 +254,8 @@ static int aspeed_wdt_set_timeout(struct watchdog_device *wdd,
+@@ -199,8 +254,8 @@ static int aspeed_wdt_set_timeout(struct watchdog_device *wdd,
  
  	actual = min(timeout, wdd->max_hw_heartbeat_ms / 1000);
  
@@ -219,7 +182,7 @@
  
  	return 0;
  }
-@@ -193,7 +275,7 @@ static int aspeed_wdt_set_pretimeout(struct watchdog_device *wdd,
+@@ -220,7 +275,7 @@ static int aspeed_wdt_set_pretimeout(struct watchdog_device *wdd,
  	else
  		wdt->ctrl &= ~WDT_CTRL_WDT_INTR;
  
@@ -228,64 +191,7 @@
  
  	return 0;
  }
-@@ -211,6 +293,56 @@ static int aspeed_wdt_restart(struct watchdog_device *wdd,
- 	return 0;
- }
- 
-+static void aspeed_wdt_update_bootstatus(struct platform_device *pdev,
-+					 struct aspeed_wdt *wdt)
-+{
-+	const struct resource *res;
-+	struct aspeed_wdt_scu scu = wdt->cfg->scu;
-+	struct regmap *scu_base;
-+	u32 reset_mask_width;
-+	u32 reset_mask_shift;
-+	u32 idx = 0;
-+	u32 status;
-+	int ret;
-+
-+	if (!of_device_is_compatible(pdev->dev.of_node, "aspeed,ast2400-wdt")) {
-+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+		idx = ((intptr_t)wdt->base & 0x00000fff) / resource_size(res);
-+	}
-+
-+	scu_base = syscon_regmap_lookup_by_compatible(scu.compatible);
-+	if (IS_ERR(scu_base)) {
-+		wdt->wdd.bootstatus = WDIOS_UNKNOWN;
-+		return;
-+	}
-+
-+	ret = regmap_read(scu_base, scu.reset_status_reg, &status);
-+	if (ret) {
-+		wdt->wdd.bootstatus = WDIOS_UNKNOWN;
-+		return;
-+	}
-+
-+	reset_mask_width = hweight32(scu.wdt_reset_mask);
-+	reset_mask_shift = scu.wdt_reset_mask_shift +
-+			   reset_mask_width * idx;
-+
-+	if (status & (scu.wdt_reset_mask << reset_mask_shift))
-+		wdt->wdd.bootstatus = WDIOF_CARDRESET;
-+
-+	/* clear wdt reset event flag */
-+	if (of_device_is_compatible(pdev->dev.of_node, "aspeed,ast2400-wdt") ||
-+	    of_device_is_compatible(pdev->dev.of_node, "aspeed,ast2500-wdt")) {
-+		ret = regmap_read(scu_base, scu.reset_status_reg, &status);
-+		if (!ret) {
-+			status &= ~(scu.wdt_reset_mask << reset_mask_shift);
-+			regmap_write(scu_base, scu.reset_status_reg, status);
-+		}
-+	} else {
-+		regmap_write(scu_base, scu.reset_status_reg,
-+			     scu.wdt_reset_mask << reset_mask_shift);
-+	}
-+}
-+
- /* access_cs0 shows if cs0 is accessible, hence the reverted bit */
- static ssize_t access_cs0_show(struct device *dev,
- 			       struct device_attribute *attr, char *buf)
-@@ -296,8 +428,10 @@ static irqreturn_t aspeed_wdt_irq(int irq, void *arg)
+@@ -373,8 +428,10 @@ static irqreturn_t aspeed_wdt_irq(int irq, void *arg)
  	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
  	u32 status = readl(wdt->base + WDT_TIMEOUT_STATUS);
  
@@ -297,7 +203,7 @@
  
  	return IRQ_HANDLED;
  }
-@@ -371,13 +505,16 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
+@@ -448,13 +505,16 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
  	ret = of_property_read_string(np, "aspeed,reset-type", &reset_type);
  	if (ret) {
  		wdt->ctrl |= WDT_CTRL_RESET_MODE_SOC | WDT_CTRL_RESET_SYSTEM;
@@ -315,7 +221,7 @@
  		else if (!strcmp(reset_type, "system"))
  			wdt->ctrl |= WDT_CTRL_RESET_MODE_FULL_CHIP |
  				     WDT_CTRL_RESET_SYSTEM;
-@@ -401,8 +538,12 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
+@@ -478,8 +538,12 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
  	}
  
  	if ((of_device_is_compatible(np, "aspeed,ast2500-wdt")) ||
@@ -329,7 +235,7 @@
  
  		reg &= wdt->cfg->ext_pulse_width_mask;
  		if (of_property_read_bool(np, "aspeed,ext-active-high"))
-@@ -410,7 +551,7 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
+@@ -487,7 +551,7 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
  		else
  			reg |= WDT_ACTIVE_LOW_MAGIC;
  
@@ -338,7 +244,7 @@
  
  		reg &= wdt->cfg->ext_pulse_width_mask;
  		if (of_property_read_bool(np, "aspeed,ext-push-pull"))
-@@ -418,7 +559,15 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
+@@ -495,7 +559,15 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
  		else
  			reg |= WDT_OPEN_DRAIN_MAGIC;
  
@@ -355,7 +261,7 @@
  	}
  
  	if (!of_property_read_u32(np, "aspeed,ext-pulse-duration", &duration)) {
-@@ -444,13 +593,13 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
+@@ -521,7 +593,7 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
  		 *
  		 * This implies a value of 0 gives a 1us pulse.
  		 */
@@ -363,15 +269,7 @@
 +		wdt->cfg->wdt_writel(duration - 1, wdt->base + WDT_RESET_WIDTH);
  	}
  
-+	aspeed_wdt_update_bootstatus(pdev, wdt);
-+
- 	status = readl(wdt->base + WDT_TIMEOUT_STATUS);
- 	if (status & WDT_TIMEOUT_STATUS_BOOT_SECONDARY) {
--		wdt->wdd.bootstatus = WDIOF_CARDRESET;
--
- 		if (of_device_is_compatible(np, "aspeed,ast2400-wdt") ||
- 		    of_device_is_compatible(np, "aspeed,ast2500-wdt"))
- 			wdt->wdd.groups = bswitch_groups;
+ 	aspeed_wdt_update_bootstatus(pdev, wdt);
 -- 
 2.34.1
 
diff --git a/recipes-kernel/linux/files/0010-Add-net-ftgmac-driver-for-ast2700.patch b/recipes-kernel/linux/files/0010-Add-net-ftgmac-driver-for-ast2700.patch
index 330d580..311eb93 100644
--- a/recipes-kernel/linux/files/0010-Add-net-ftgmac-driver-for-ast2700.patch
+++ b/recipes-kernel/linux/files/0010-Add-net-ftgmac-driver-for-ast2700.patch
@@ -1,24 +1,23 @@
-From c200a032d08cff02a43c5d34d8f0731526aefbbb Mon Sep 17 00:00:00 2001
-From: "yung-sheng.huang" <yung-sheng.huang@fii-na.corp-partner.google.com>
-Date: Tue, 15 Apr 2025 12:42:33 +0800
-Subject: [PATCH 10/26] Add net ftgmac driver for ast2700
+From f12c509e5d12fcf47ccb397f210161ec0d326ccf Mon Sep 17 00:00:00 2001
+From: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+Date: Thu, 17 Jul 2025 08:13:18 +0800
+Subject: [PATCH] Add net ftgmac driver for ast2700
 
-This is base on aspeed SDK 9.06.
+This is base on aspeed SDK 9.07.
 
 Source:
 AspeedTech-BMC github:
 https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/
-(cherry picked from commit v00.06.06)
+(cherry picked from commit v00.06.07)
 
-Signed-off-by: yung-sheng.huang <yung-sheng.huang@fii-na.corp-partner.google.com>
+Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
 ---
  drivers/net/ethernet/faraday/Kconfig     |   7 +-
- drivers/net/ethernet/faraday/ftgmac100.c | 194 +++++++++++++++++------
+ drivers/net/ethernet/faraday/ftgmac100.c | 194 ++++++++++++++++++-----
  drivers/net/ethernet/faraday/ftgmac100.h |  10 ++
  drivers/net/mdio/mdio-aspeed.c           |   2 +
- drivers/net/phy/broadcom.c               |  45 ++++++
- include/linux/brcmphy.h                  |  10 ++
- 6 files changed, 215 insertions(+), 53 deletions(-)
+ include/linux/netdevice.h                |   3 +-
+ 5 files changed, 170 insertions(+), 46 deletions(-)
 
 diff --git a/drivers/net/ethernet/faraday/Kconfig b/drivers/net/ethernet/faraday/Kconfig
 index c699bd6bc..c765663c0 100644
@@ -47,7 +46,7 @@
  	help
  	  This driver supports the FTGMAC100 Gigabit Ethernet controller
 diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
-index 9135b918d..52b40f409 100644
+index 848e41a4b..d6bac24a9 100644
 --- a/drivers/net/ethernet/faraday/ftgmac100.c
 +++ b/drivers/net/ethernet/faraday/ftgmac100.c
 @@ -9,6 +9,7 @@
@@ -106,7 +105,31 @@
  };
  
  static int ftgmac100_reset_mac(struct ftgmac100 *priv, u32 maccr)
-@@ -255,10 +271,12 @@ static void ftgmac100_init_hw(struct ftgmac100 *priv)
+@@ -138,6 +154,23 @@ static int ftgmac100_reset_and_config_mac(struct ftgmac100 *priv)
+ {
+ 	u32 maccr = 0;
+ 
++	/* RMII needs SCU reset to clear status */
++	if (priv->netdev->phydev->interface == PHY_INTERFACE_MODE_RMII) {
++		int err;
++
++		err = reset_control_assert(priv->rst);
++		if (err) {
++			dev_err(priv->dev, "Failed to reset mac (%d)\n", err);
++			return err;
++		}
++		usleep_range(10000, 20000);
++		err = reset_control_deassert(priv->rst);
++		if (err) {
++			dev_err(priv->dev, "Failed to deassert mac reset (%d)\n", err);
++			return err;
++		}
++	}
++
+ 	switch (priv->cur_speed) {
+ 	case SPEED_10:
+ 	case 0: /* no link */
+@@ -255,10 +288,12 @@ static void ftgmac100_init_hw(struct ftgmac100 *priv)
  	iowrite32(reg, priv->base + FTGMAC100_OFFSET_ISR);
  
  	/* Setup RX ring buffer base */
@@ -121,7 +144,7 @@
  
  	/* Configure RX buffer size */
  	iowrite32(FTGMAC100_RBSR_SIZE(RX_BUF_SIZE),
-@@ -311,6 +329,7 @@ static void ftgmac100_init_hw(struct ftgmac100 *priv)
+@@ -311,6 +346,7 @@ static void ftgmac100_init_hw(struct ftgmac100 *priv)
  static void ftgmac100_start_hw(struct ftgmac100 *priv)
  {
  	u32 maccr = ioread32(priv->base + FTGMAC100_OFFSET_MACCR);
@@ -129,7 +152,7 @@
  
  	/* Keep the original GMAC and FAST bits */
  	maccr &= (FTGMAC100_MACCR_FAST_MODE | FTGMAC100_MACCR_GIGA_MODE);
-@@ -339,6 +358,10 @@ static void ftgmac100_start_hw(struct ftgmac100 *priv)
+@@ -339,6 +375,10 @@ static void ftgmac100_start_hw(struct ftgmac100 *priv)
  	if (priv->netdev->features & NETIF_F_HW_VLAN_CTAG_RX)
  		maccr |= FTGMAC100_MACCR_RM_VLAN;
  
@@ -140,7 +163,7 @@
  	/* Hit the HW */
  	iowrite32(maccr, priv->base + FTGMAC100_OFFSET_MACCR);
  }
-@@ -415,7 +438,9 @@ static int ftgmac100_alloc_rx_buf(struct ftgmac100 *priv, unsigned int entry,
+@@ -415,7 +455,9 @@ static int ftgmac100_alloc_rx_buf(struct ftgmac100 *priv, unsigned int entry,
  	priv->rx_skbs[entry] = skb;
  
  	/* Store DMA address into RX desc */
@@ -151,7 +174,7 @@
  
  	/* Ensure the above is ordered vs clearing the OWN bit */
  	dma_wmb();
-@@ -541,7 +566,8 @@ static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed)
+@@ -541,7 +583,8 @@ static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed)
  				       csum_vlan & 0xffff);
  
  	/* Tear down DMA mapping, do necessary cache management */
@@ -161,7 +184,7 @@
  
  #if defined(CONFIG_ARM) && !defined(CONFIG_ARM_DMA_USE_IOMMU)
  	/* When we don't have an iommu, we can save cycles by not
-@@ -553,7 +579,6 @@ static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed)
+@@ -553,7 +596,6 @@ static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed)
  	dma_unmap_single(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE);
  #endif
  
@@ -169,16 +192,7 @@
  	/* Resplenish rx ring */
  	ftgmac100_alloc_rx_buf(priv, pointer, rxdes, GFP_ATOMIC);
  	priv->rx_pointer = ftgmac100_next_rx_pointer(priv, pointer);
-@@ -572,7 +597,7 @@ static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed)
- 	(*processed)++;
- 	return true;
- 
-- drop:
-+drop:
- 	/* Clean rxdes0 (which resets own bit) */
- 	rxdes->rxdes0 = cpu_to_le32(status & priv->rxdes0_edorr_mask);
- 	priv->rx_pointer = ftgmac100_next_rx_pointer(priv, pointer);
-@@ -618,9 +643,12 @@ static void ftgmac100_free_tx_packet(struct ftgmac100 *priv,
+@@ -618,9 +660,12 @@ static void ftgmac100_free_tx_packet(struct ftgmac100 *priv,
  				     struct ftgmac100_txdes *txdes,
  				     u32 ctl_stat)
  {
@@ -192,19 +206,7 @@
  	if (ctl_stat & FTGMAC100_TXDES0_FTS) {
  		len = skb_headlen(skb);
  		dma_unmap_single(priv->dev, map, len, DMA_TO_DEVICE);
-@@ -656,6 +684,11 @@ static bool ftgmac100_tx_complete_packet(struct ftgmac100 *priv)
- 	ftgmac100_free_tx_packet(priv, pointer, skb, txdes, ctl_stat);
- 	txdes->txdes0 = cpu_to_le32(ctl_stat & priv->txdes0_edotr_mask);
- 
-+	/* Ensure the descriptor config is visible before setting the tx
-+	 * pointer.
-+	 */
-+	smp_wmb();
-+
- 	priv->tx_clean_pointer = ftgmac100_next_tx_pointer(priv, pointer);
- 
- 	return true;
-@@ -769,7 +802,9 @@ static netdev_tx_t ftgmac100_hard_start_xmit(struct sk_buff *skb,
+@@ -774,7 +819,9 @@ static netdev_tx_t ftgmac100_hard_start_xmit(struct sk_buff *skb,
  	f_ctl_stat |= FTGMAC100_TXDES0_FTS;
  	if (nfrags == 0)
  		f_ctl_stat |= FTGMAC100_TXDES0_LTS;
@@ -215,7 +217,7 @@
  	txdes->txdes1 = cpu_to_le32(csum_vlan);
  
  	/* Next descriptor */
-@@ -797,7 +832,9 @@ static netdev_tx_t ftgmac100_hard_start_xmit(struct sk_buff *skb,
+@@ -802,7 +849,9 @@ static netdev_tx_t ftgmac100_hard_start_xmit(struct sk_buff *skb,
  			ctl_stat |= FTGMAC100_TXDES0_LTS;
  		txdes->txdes0 = cpu_to_le32(ctl_stat);
  		txdes->txdes1 = 0;
@@ -226,37 +228,7 @@
  
  		/* Next one */
  		pointer = ftgmac100_next_tx_pointer(priv, pointer);
-@@ -809,6 +846,11 @@ static netdev_tx_t ftgmac100_hard_start_xmit(struct sk_buff *skb,
- 	dma_wmb();
- 	first->txdes0 = cpu_to_le32(f_ctl_stat);
- 
-+	/* Ensure the descriptor config is visible before setting the tx
-+	 * pointer.
-+	 */
-+	smp_wmb();
-+
- 	/* Update next TX pointer */
- 	priv->tx_pointer = pointer;
- 
-@@ -829,7 +871,7 @@ static netdev_tx_t ftgmac100_hard_start_xmit(struct sk_buff *skb,
- 
- 	return NETDEV_TX_OK;
- 
-- dma_err:
-+dma_err:
- 	if (net_ratelimit())
- 		netdev_err(netdev, "map tx fragment failed\n");
- 
-@@ -851,7 +893,7 @@ static netdev_tx_t ftgmac100_hard_start_xmit(struct sk_buff *skb,
- 	 * last fragment, so we know ftgmac100_free_tx_packet()
- 	 * hasn't freed the skb yet.
- 	 */
-- drop:
-+drop:
- 	/* Drop the packet */
- 	dev_kfree_skb_any(skb);
- 	netdev->stats.tx_dropped++;
-@@ -867,7 +909,10 @@ static void ftgmac100_free_buffers(struct ftgmac100 *priv)
+@@ -877,7 +926,10 @@ static void ftgmac100_free_buffers(struct ftgmac100 *priv)
  	for (i = 0; i < priv->rx_q_entries; i++) {
  		struct ftgmac100_rxdes *rxdes = &priv->rxdes[i];
  		struct sk_buff *skb = priv->rx_skbs[i];
@@ -268,7 +240,7 @@
  
  		if (!skb)
  			continue;
-@@ -966,7 +1011,9 @@ static void ftgmac100_init_rings(struct ftgmac100 *priv)
+@@ -976,7 +1028,9 @@ static void ftgmac100_init_rings(struct ftgmac100 *priv)
  	for (i = 0; i < priv->rx_q_entries; i++) {
  		rxdes = &priv->rxdes[i];
  		rxdes->rxdes0 = 0;
@@ -279,7 +251,7 @@
  	}
  	/* Mark the end of the ring */
  	rxdes->rxdes0 |= cpu_to_le32(priv->rxdes0_edorr_mask);
-@@ -1229,7 +1276,6 @@ static int ftgmac100_poll(struct napi_struct *napi, int budget)
+@@ -1239,7 +1293,6 @@ static int ftgmac100_poll(struct napi_struct *napi, int budget)
  		more = ftgmac100_rx_packet(priv, &work_done);
  	} while (more && work_done < budget);
  
@@ -287,7 +259,7 @@
  	/* The interrupt is telling us to kick the MAC back to life
  	 * after an RX overflow
  	 */
-@@ -1319,7 +1365,6 @@ static void ftgmac100_reset(struct ftgmac100 *priv)
+@@ -1329,7 +1382,6 @@ static void ftgmac100_reset(struct ftgmac100 *priv)
  	if (priv->mii_bus)
  		mutex_lock(&priv->mii_bus->mdio_lock);
  
@@ -295,16 +267,7 @@
  	/* Check if the interface is still up */
  	if (!netif_running(netdev))
  		goto bail;
-@@ -1344,7 +1389,7 @@ static void ftgmac100_reset(struct ftgmac100 *priv)
- 	ftgmac100_init_all(priv, true);
- 
- 	netdev_dbg(netdev, "Reset done !\n");
-- bail:
-+bail:
- 	if (priv->mii_bus)
- 		mutex_unlock(&priv->mii_bus->mdio_lock);
- 	if (netdev->phydev)
-@@ -1418,7 +1463,6 @@ static void ftgmac100_adjust_link(struct net_device *netdev)
+@@ -1428,7 +1480,6 @@ static void ftgmac100_adjust_link(struct net_device *netdev)
  
  	if (netdev->phydev)
  		mutex_lock(&netdev->phydev->lock);
@@ -312,7 +275,7 @@
  }
  
  static int ftgmac100_mii_probe(struct net_device *netdev)
-@@ -1531,7 +1575,8 @@ static int ftgmac100_open(struct net_device *netdev)
+@@ -1541,7 +1592,8 @@ static int ftgmac100_open(struct net_device *netdev)
  	if (netdev->phydev) {
  		/* If we have a PHY, start polling */
  		phy_start(netdev->phydev);
@@ -322,28 +285,15 @@
  		/* If using NC-SI, set our carrier on and start the stack */
  		netif_carrier_on(netdev);
  
-@@ -1543,15 +1588,16 @@ static int ftgmac100_open(struct net_device *netdev)
- 
+@@ -1554,6 +1606,7 @@ static int ftgmac100_open(struct net_device *netdev)
  	return 0;
  
-- err_ncsi:
-+err_ncsi:
+ err_ncsi:
 +	phy_stop(netdev->phydev);
  	napi_disable(&priv->napi);
  	netif_stop_queue(netdev);
-- err_alloc:
-+err_alloc:
- 	ftgmac100_free_buffers(priv);
- 	free_irq(netdev->irq, netdev);
-- err_irq:
-+err_irq:
- 	netif_napi_del(&priv->napi);
-- err_hw:
-+err_hw:
- 	iowrite32(0, priv->base + FTGMAC100_OFFSET_IER);
- 	ftgmac100_free_rings(priv);
- 	return err;
-@@ -1577,7 +1623,7 @@ static int ftgmac100_stop(struct net_device *netdev)
+ err_alloc:
+@@ -1587,7 +1640,7 @@ static int ftgmac100_stop(struct net_device *netdev)
  	netif_napi_del(&priv->napi);
  	if (netdev->phydev)
  		phy_stop(netdev->phydev);
@@ -352,7 +302,7 @@
  		ncsi_stop_dev(priv->ndev);
  
  	ftgmac100_stop_hw(priv);
-@@ -1708,13 +1754,21 @@ static int ftgmac100_setup_mdio(struct net_device *netdev)
+@@ -1718,13 +1771,21 @@ static int ftgmac100_setup_mdio(struct net_device *netdev)
  static void ftgmac100_phy_disconnect(struct net_device *netdev)
  {
  	struct ftgmac100 *priv = netdev_priv(netdev);
@@ -379,7 +329,7 @@
  }
  
  static void ftgmac100_destroy_mdio(struct net_device *netdev)
-@@ -1792,6 +1846,7 @@ static int ftgmac100_probe(struct platform_device *pdev)
+@@ -1802,6 +1863,7 @@ static int ftgmac100_probe(struct platform_device *pdev)
  	struct resource *res;
  	int irq;
  	struct net_device *netdev;
@@ -387,7 +337,7 @@
  	struct ftgmac100 *priv;
  	struct device_node *np;
  	int err = 0;
-@@ -1856,7 +1911,8 @@ static int ftgmac100_probe(struct platform_device *pdev)
+@@ -1866,7 +1928,8 @@ static int ftgmac100_probe(struct platform_device *pdev)
  	np = pdev->dev.of_node;
  	if (np && (of_device_is_compatible(np, "aspeed,ast2400-mac") ||
  		   of_device_is_compatible(np, "aspeed,ast2500-mac") ||
@@ -397,7 +347,7 @@
  		priv->rxdes0_edorr_mask = BIT(30);
  		priv->txdes0_edotr_mask = BIT(30);
  		priv->is_aspeed = true;
-@@ -1879,35 +1935,30 @@ static int ftgmac100_probe(struct platform_device *pdev)
+@@ -1889,35 +1952,30 @@ static int ftgmac100_probe(struct platform_device *pdev)
  			err = -EINVAL;
  			goto err_phy_connect;
  		}
@@ -446,7 +396,7 @@
  			err = ftgmac100_setup_mdio(netdev);
  			if (err)
  				goto err_setup_mdio;
-@@ -1944,7 +1995,6 @@ static int ftgmac100_probe(struct platform_device *pdev)
+@@ -1954,7 +2012,6 @@ static int ftgmac100_probe(struct platform_device *pdev)
  			dev_err(priv->dev, "MII probe failed!\n");
  			goto err_ncsi_dev;
  		}
@@ -454,7 +404,7 @@
  	}
  
  	if (priv->is_aspeed) {
-@@ -1953,9 +2003,49 @@ static int ftgmac100_probe(struct platform_device *pdev)
+@@ -1963,9 +2020,58 @@ static int ftgmac100_probe(struct platform_device *pdev)
  			goto err_phy_connect;
  
  		/* Disable ast2600 problematic HW arbitration */
@@ -496,16 +446,25 @@
 +	}
 +
 +	if (priv->sgmii) {
-+		/* The default is Nway on SGMII. */
-+		err = phy_init(priv->sgmii);
-+		if (err) {
-+			dev_err(priv->dev, "Failed to init sgmii phy\n");
-+			goto err_register_netdev;
++		/* If using fixed link in dts, sgmii need to be forced */
++		if (of_phy_is_fixed_link(np)) {
++			err = phy_set_speed(priv->sgmii, netdev->phydev->speed);
++			if (err) {
++				dev_err(priv->dev, "Failed to force sgmii speed\n");
++				goto err_register_netdev;
++			}
++		} else {
++			/* The phy_init is used to configure Nway */
++			err = phy_init(priv->sgmii);
++			if (err) {
++				dev_err(priv->dev, "Failed to configure sgmii Nway\n");
++				goto err_register_netdev;
++			}
 +		}
  	}
  
  	/* Default ring sizes */
-@@ -1982,6 +2072,12 @@ static int ftgmac100_probe(struct platform_device *pdev)
+@@ -1992,6 +2098,12 @@ static int ftgmac100_probe(struct platform_device *pdev)
  		netdev->hw_features &= ~(NETIF_F_HW_CSUM | NETIF_F_RXCSUM);
  	netdev->features |= netdev->hw_features;
  
@@ -571,102 +530,20 @@
  
  	return readl_poll_timeout(ctx->base + ASPEED_MDIO_CTRL, ctrl,
  				!(ctrl & ASPEED_MDIO_CTRL_FIRE),
-diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
-index 04b2e6eeb..81edddc3b 100644
---- a/drivers/net/phy/broadcom.c
-+++ b/drivers/net/phy/broadcom.c
-@@ -439,6 +439,37 @@ static int bcm54xx_config_init(struct phy_device *phydev)
- 	return 0;
- }
+diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
+index 0b0a17233..030d9de2b 100644
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -3036,7 +3036,8 @@ extern rwlock_t				dev_base_lock;		/* Device list lock */
+ #define net_device_entry(lh)	list_entry(lh, struct net_device, dev_list)
  
-+static int bcm5221_config_init(struct phy_device *phydev)
-+{
-+	int reg, err;
-+
-+	reg = phy_read(phydev, MII_BCM5221_TEST);
-+	reg |= MII_BCM5221_TEST_ENABLE_SHADOWS;
-+	err = phy_write(phydev, MII_BCM5221_TEST, reg);
-+	if (err < 0)
-+		return err;
-+
-+	reg = phy_read(phydev, MII_BCM5221_SHDOW_AUX_STAT2);
-+	reg |= MII_BCM5221_SHDOW_AUX_STAT2_APD;
-+	err = phy_write(phydev, MII_BCM5221_SHDOW_AUX_STAT2, reg);
-+	if (err < 0)
-+		return err;
-+
-+	reg = phy_read(phydev, MII_BCM5221_SHDOW_AUX_MODE4);
-+	reg |= MII_BCM5221_SHDOW_AUX_MODE4_CLKLOPWR;
-+	err = phy_write(phydev, MII_BCM5221_SHDOW_AUX_MODE4, reg);
-+	if (err < 0)
-+		return err;
-+
-+	reg = phy_read(phydev, MII_BCM5221_TEST);
-+	reg &= ~MII_BCM5221_TEST_ENABLE_SHADOWS;
-+	err = phy_write(phydev, MII_BCM5221_TEST, reg);
-+	if (err < 0)
-+		return err;
-+
-+	return 0;
-+}
-+
- static int bcm54xx_iddq_set(struct phy_device *phydev, bool enable)
+ #define for_each_netdev_dump(net, d, ifindex)				\
+-	xa_for_each_start(&(net)->dev_by_index, (ifindex), (d), (ifindex))
++	for (; (d = xa_find(&(net)->dev_by_index, &ifindex,		\
++			    ULONG_MAX, XA_PRESENT)); ifindex++)
+ 
+ static inline struct net_device *next_net_device(struct net_device *dev)
  {
- 	int ret = 0;
-@@ -1276,6 +1307,19 @@ static struct phy_driver broadcom_drivers[] = {
- 	.config_intr    = bcm_phy_config_intr,
- 	.handle_interrupt = bcm_phy_handle_interrupt,
- 	.link_change_notify	= bcm54xx_link_change_notify,
-+}, {
-+	.phy_id		= PHY_ID_BCM5221,
-+	.phy_id_mask	= 0xfffffff0,
-+	.name		= "Broadcom BCM5221",
-+	/* PHY_GBIT_FEATURES */
-+	.get_sset_count	= bcm_phy_get_sset_count,
-+	.get_strings	= bcm_phy_get_strings,
-+	.get_stats	= bcm54xx_get_stats,
-+	.probe		= bcm54xx_phy_probe,
-+	.config_init	= bcm5221_config_init,
-+	.config_intr	= bcm_phy_config_intr,
-+	.handle_interrupt = bcm_phy_handle_interrupt,
-+	.link_change_notify	= bcm54xx_link_change_notify,
- } };
- 
- module_phy_driver(broadcom_drivers);
-@@ -1296,6 +1340,7 @@ static struct mdio_device_id __maybe_unused broadcom_tbl[] = {
- 	{ PHY_ID_BCM50610M, 0xfffffff0 },
- 	{ PHY_ID_BCM57780, 0xfffffff0 },
- 	{ PHY_ID_BCMAC131, 0xfffffff0 },
-+	{ PHY_ID_BCM5221, 0xfffffff0},
- 	{ PHY_ID_BCM5241, 0xfffffff0 },
- 	{ PHY_ID_BCM5395, 0xfffffff0 },
- 	{ PHY_ID_BCM53125, 0xfffffff0 },
-diff --git a/include/linux/brcmphy.h b/include/linux/brcmphy.h
-index c55810a43..006fb9996 100644
---- a/include/linux/brcmphy.h
-+++ b/include/linux/brcmphy.h
-@@ -11,6 +11,7 @@
- 
- #define PHY_ID_BCM50610			0x0143bd60
- #define PHY_ID_BCM50610M		0x0143bd70
-+#define PHY_ID_BCM5221			0x004061e0
- #define PHY_ID_BCM5241			0x0143bc30
- #define PHY_ID_BCMAC131			0x0143bc70
- #define PHY_ID_BCM5481			0x0143bca0
-@@ -420,4 +421,13 @@
- #define BCM54XX_EXP_ECD_PAIR_D_LENGTH_RESULTS	(MII_BCM54XX_EXP_SEL_ER + 0xc5)
- #define BCM54XX_ECD_LENGTH_RESULTS_INVALID	0xffff
- 
-+/* MII BCM5221 Additional registers */
-+#define MII_BCM5221_TEST			0x1f
-+#define MII_BCM5221_TEST_ENABLE_SHADOWS		0x0080
-+#define MII_BCM5221_SHDOW_AUX_STAT2		0x1b
-+#define MII_BCM5221_SHDOW_AUX_STAT2_APD		0x0020
-+#define MII_BCM5221_SHDOW_AUX_MODE4		0x1a
-+#define MII_BCM5221_SHDOW_AUX_MODE4_IDDQMODE	0x0001
-+#define MII_BCM5221_SHDOW_AUX_MODE4_CLKLOPWR	0x0004
-+
- #endif /* _LINUX_BRCMPHY_H */
 -- 
 2.34.1
 
diff --git a/recipes-kernel/linux/files/0011-Add-gpio-sgpio-driver-for-ast2700.patch b/recipes-kernel/linux/files/0011-Add-gpio-sgpio-driver-for-ast2700.patch
index a6d5545..1ccbdf5 100644
--- a/recipes-kernel/linux/files/0011-Add-gpio-sgpio-driver-for-ast2700.patch
+++ b/recipes-kernel/linux/files/0011-Add-gpio-sgpio-driver-for-ast2700.patch
@@ -1,23 +1,23 @@
-From 65095356608cc85eaa93d8564b7754e0165f9696 Mon Sep 17 00:00:00 2001
-From: "yung-sheng.huang" <yung-sheng.huang@fii-na.corp-partner.google.com>
-Date: Tue, 15 Apr 2025 16:12:44 +0800
-Subject: [PATCH 11/26] Add gpio sgpio driver for ast2700
+From 0625f2cd6d7d90a5a9072b690c11c9f6bebd7f31 Mon Sep 17 00:00:00 2001
+From: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+Date: Thu, 17 Jul 2025 08:17:09 +0800
+Subject: [PATCH] Add gpio sgpio driver for ast2700
 
-This is base on aspeed SDK 9.06.
+This is base on aspeed SDK 9.07.
 
 Source:
 AspeedTech-BMC github:
 https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/
-(cherry picked from commit v00.06.06)
+(cherry picked from commit v00.06.07)
 
-Signed-off-by: yung-sheng.huang <yung-sheng.huang@fii-na.corp-partner.google.com>
+Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
 ---
  drivers/gpio/gpio-aspeed-sgpio.c | 466 +++++++++++++++++++----
- drivers/gpio/gpio-aspeed.c       | 621 +++++++++++++++++++------------
- 2 files changed, 789 insertions(+), 298 deletions(-)
+ drivers/gpio/gpio-aspeed.c       | 619 +++++++++++++++++++------------
+ 2 files changed, 787 insertions(+), 298 deletions(-)
 
 diff --git a/drivers/gpio/gpio-aspeed-sgpio.c b/drivers/gpio/gpio-aspeed-sgpio.c
-index 72755fee6..450d6eb87 100644
+index 72755fee6..150fbaebb 100644
 --- a/drivers/gpio/gpio-aspeed-sgpio.c
 +++ b/drivers/gpio/gpio-aspeed-sgpio.c
 @@ -18,7 +18,51 @@
@@ -363,7 +363,7 @@
 +
 +	chained_irq_enter(ic, desc);
 +
-+	banks = DIV_ROUND_UP(gpio->chip.ngpio >> 2, 32);
++	banks = DIV_ROUND_UP(gpio->chip.ngpio >> 1, 32);
 +	for (i = 0; i < banks; i++) {
 +		addr = gpio->base + SGPIO_G7_IRQ_STS_OFFSET(i);
 +
@@ -686,7 +686,7 @@
 +module_platform_driver(aspeed_sgpio_driver);
  MODULE_DESCRIPTION("Aspeed Serial GPIO Driver");
 diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
-index 58f107194..cc3d23e88 100644
+index 76468e6a2..cc3d23e88 100644
 --- a/drivers/gpio/gpio-aspeed.c
 +++ b/drivers/gpio/gpio-aspeed.c
 @@ -30,6 +30,27 @@
@@ -920,7 +920,7 @@
  }
  
  static inline bool have_input(struct aspeed_gpio *gpio, unsigned int offset)
-@@ -304,108 +378,49 @@ static inline bool have_output(struct aspeed_gpio *gpio, unsigned int offset)
+@@ -304,110 +378,49 @@ static inline bool have_output(struct aspeed_gpio *gpio, unsigned int offset)
  	return !props || (props->output & GPIO_BIT(offset));
  }
  
@@ -1041,12 +1041,13 @@
 -
 -	iowrite32(reg, addr);
 +	gpio->config->llops->reg_bit_set(gpio, offset, reg_val, val);
-+	/* Flush write */
+ 	/* Flush write */
+-	ioread32(addr);
 +	gpio->config->llops->reg_bit_get(gpio, offset, reg_val);
  }
  
  static void aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,
-@@ -413,7 +428,7 @@ static void aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,
+@@ -415,7 +428,7 @@ static void aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,
  {
  	struct aspeed_gpio *gpio = gpiochip_get_data(gc);
  	unsigned long flags;
@@ -1055,7 +1056,7 @@
  
  	raw_spin_lock_irqsave(&gpio->lock, flags);
  	copro = aspeed_gpio_copro_request(gpio, offset);
-@@ -428,22 +443,16 @@ static void aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,
+@@ -430,22 +443,16 @@ static void aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,
  static int aspeed_gpio_dir_in(struct gpio_chip *gc, unsigned int offset)
  {
  	struct aspeed_gpio *gpio = gpiochip_get_data(gc);
@@ -1080,7 +1081,7 @@
  	if (copro)
  		aspeed_gpio_copro_release(gpio, offset);
  
-@@ -456,23 +465,17 @@ static int aspeed_gpio_dir_out(struct gpio_chip *gc,
+@@ -458,23 +465,17 @@ static int aspeed_gpio_dir_out(struct gpio_chip *gc,
  			       unsigned int offset, int val)
  {
  	struct aspeed_gpio *gpio = gpiochip_get_data(gc);
@@ -1106,7 +1107,7 @@
  
  	if (copro)
  		aspeed_gpio_copro_release(gpio, offset);
-@@ -484,7 +487,6 @@ static int aspeed_gpio_dir_out(struct gpio_chip *gc,
+@@ -486,7 +487,6 @@ static int aspeed_gpio_dir_out(struct gpio_chip *gc,
  static int aspeed_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
  {
  	struct aspeed_gpio *gpio = gpiochip_get_data(gc);
@@ -1114,7 +1115,7 @@
  	unsigned long flags;
  	u32 val;
  
-@@ -496,7 +498,7 @@ static int aspeed_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
+@@ -498,7 +498,7 @@ static int aspeed_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
  
  	raw_spin_lock_irqsave(&gpio->lock, flags);
  
@@ -1123,7 +1124,7 @@
  
  	raw_spin_unlock_irqrestore(&gpio->lock, flags);
  
-@@ -505,8 +507,7 @@ static int aspeed_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
+@@ -507,8 +507,7 @@ static int aspeed_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
  
  static inline int irqd_to_aspeed_gpio_data(struct irq_data *d,
  					   struct aspeed_gpio **gpio,
@@ -1133,7 +1134,7 @@
  {
  	struct aspeed_gpio *internal;
  
-@@ -519,32 +520,25 @@ static inline int irqd_to_aspeed_gpio_data(struct irq_data *d,
+@@ -521,32 +520,25 @@ static inline int irqd_to_aspeed_gpio_data(struct irq_data *d,
  		return -ENOTSUPP;
  
  	*gpio = internal;
@@ -1169,7 +1170,7 @@
  
  	if (copro)
  		aspeed_gpio_copro_release(gpio, offset);
-@@ -553,20 +547,15 @@ static void aspeed_gpio_irq_ack(struct irq_data *d)
+@@ -555,20 +547,15 @@ static void aspeed_gpio_irq_ack(struct irq_data *d)
  
  static void aspeed_gpio_irq_set_mask(struct irq_data *d, bool set)
  {
@@ -1192,7 +1193,7 @@
  	/* Unmasking the IRQ */
  	if (set)
  		gpiochip_enable_irq(&gpio->chip, irqd_to_hwirq(d));
-@@ -574,12 +563,7 @@ static void aspeed_gpio_irq_set_mask(struct irq_data *d, bool set)
+@@ -576,12 +563,7 @@ static void aspeed_gpio_irq_set_mask(struct irq_data *d, bool set)
  	raw_spin_lock_irqsave(&gpio->lock, flags);
  	copro = aspeed_gpio_copro_request(gpio, offset);
  
@@ -1206,7 +1207,7 @@
  
  	if (copro)
  		aspeed_gpio_copro_release(gpio, offset);
-@@ -605,34 +589,31 @@ static int aspeed_gpio_set_type(struct irq_data *d, unsigned int type)
+@@ -607,34 +589,31 @@ static int aspeed_gpio_set_type(struct irq_data *d, unsigned int type)
  	u32 type0 = 0;
  	u32 type1 = 0;
  	u32 type2 = 0;
@@ -1247,7 +1248,7 @@
  		handler = handle_level_irq;
  		break;
  	default:
-@@ -642,20 +623,9 @@ static int aspeed_gpio_set_type(struct irq_data *d, unsigned int type)
+@@ -644,20 +623,9 @@ static int aspeed_gpio_set_type(struct irq_data *d, unsigned int type)
  	raw_spin_lock_irqsave(&gpio->lock, flags);
  	copro = aspeed_gpio_copro_request(gpio, offset);
  
@@ -1271,7 +1272,7 @@
  
  	if (copro)
  		aspeed_gpio_copro_release(gpio, offset);
-@@ -670,7 +640,6 @@ static void aspeed_gpio_irq_handler(struct irq_desc *desc)
+@@ -672,7 +640,6 @@ static void aspeed_gpio_irq_handler(struct irq_desc *desc)
  {
  	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
  	struct irq_chip *ic = irq_desc_get_chip(desc);
@@ -1279,7 +1280,7 @@
  	unsigned int i, p, banks;
  	unsigned long reg;
  	struct aspeed_gpio *gpio = gpiochip_get_data(gc);
-@@ -679,9 +648,7 @@ static void aspeed_gpio_irq_handler(struct irq_desc *desc)
+@@ -681,9 +648,7 @@ static void aspeed_gpio_irq_handler(struct irq_desc *desc)
  
  	banks = DIV_ROUND_UP(gpio->chip.ngpio, 32);
  	for (i = 0; i < banks; i++) {
@@ -1290,7 +1291,7 @@
  
  		for_each_set_bit(p, &reg, 32)
  			generic_handle_domain_irq(gc->irq.domain, i * 32 + p);
-@@ -720,23 +687,12 @@ static int aspeed_gpio_reset_tolerance(struct gpio_chip *chip,
+@@ -722,23 +687,12 @@ static int aspeed_gpio_reset_tolerance(struct gpio_chip *chip,
  {
  	struct aspeed_gpio *gpio = gpiochip_get_data(chip);
  	unsigned long flags;
@@ -1316,7 +1317,7 @@
  
  	if (copro)
  		aspeed_gpio_copro_release(gpio, offset);
-@@ -830,21 +786,11 @@ static inline bool timer_allocation_registered(struct aspeed_gpio *gpio,
+@@ -832,21 +786,11 @@ static inline bool timer_allocation_registered(struct aspeed_gpio *gpio,
  static void configure_timer(struct aspeed_gpio *gpio, unsigned int offset,
  		unsigned int timer)
  {
@@ -1340,7 +1341,7 @@
  }
  
  static int enable_debounce(struct gpio_chip *chip, unsigned int offset,
-@@ -875,15 +821,15 @@ static int enable_debounce(struct gpio_chip *chip, unsigned int offset,
+@@ -877,15 +821,15 @@ static int enable_debounce(struct gpio_chip *chip, unsigned int offset,
  	}
  
  	/* Try to find a timer already configured for the debounce period */
@@ -1359,7 +1360,7 @@
  		int j;
  
  		/*
-@@ -897,8 +843,8 @@ static int enable_debounce(struct gpio_chip *chip, unsigned int offset,
+@@ -899,8 +843,8 @@ static int enable_debounce(struct gpio_chip *chip, unsigned int offset,
  
  		if (j == ARRAY_SIZE(gpio->timer_users)) {
  			dev_warn(chip->parent,
@@ -1370,7 +1371,7 @@
  
  			rc = -EPERM;
  
-@@ -914,7 +860,7 @@ static int enable_debounce(struct gpio_chip *chip, unsigned int offset,
+@@ -916,7 +860,7 @@ static int enable_debounce(struct gpio_chip *chip, unsigned int offset,
  
  		i = j;
  
@@ -1379,7 +1380,7 @@
  	}
  
  	if (WARN(i == 0, "Cannot register index of disabled timer\n")) {
-@@ -1017,6 +963,9 @@ int aspeed_gpio_copro_grab_gpio(struct gpio_desc *desc,
+@@ -1019,6 +963,9 @@ int aspeed_gpio_copro_grab_gpio(struct gpio_desc *desc,
  	const struct aspeed_gpio_bank *bank = to_bank(offset);
  	unsigned long flags;
  
@@ -1389,7 +1390,7 @@
  	if (!gpio->cf_copro_bankmap)
  		gpio->cf_copro_bankmap = kzalloc(gpio->chip.ngpio >> 3, GFP_KERNEL);
  	if (!gpio->cf_copro_bankmap)
-@@ -1036,7 +985,7 @@ int aspeed_gpio_copro_grab_gpio(struct gpio_desc *desc,
+@@ -1038,7 +985,7 @@ int aspeed_gpio_copro_grab_gpio(struct gpio_desc *desc,
  
  	/* Switch command source */
  	if (gpio->cf_copro_bankmap[bindex] == 1)
@@ -1398,7 +1399,7 @@
  					      GPIO_CMDSRC_COLDFIRE);
  
  	if (vreg_offset)
-@@ -1060,9 +1009,11 @@ int aspeed_gpio_copro_release_gpio(struct gpio_desc *desc)
+@@ -1062,9 +1009,11 @@ int aspeed_gpio_copro_release_gpio(struct gpio_desc *desc)
  	struct gpio_chip *chip = gpiod_to_chip(desc);
  	struct aspeed_gpio *gpio = gpiochip_get_data(chip);
  	int rc = 0, bindex, offset = gpio_chip_hwgpio(desc);
@@ -1411,7 +1412,7 @@
  	if (!gpio->cf_copro_bankmap)
  		return -ENXIO;
  
-@@ -1081,7 +1032,7 @@ int aspeed_gpio_copro_release_gpio(struct gpio_desc *desc)
+@@ -1083,7 +1032,7 @@ int aspeed_gpio_copro_release_gpio(struct gpio_desc *desc)
  
  	/* Switch command source */
  	if (gpio->cf_copro_bankmap[bindex] == 0)
@@ -1420,7 +1421,7 @@
  					      GPIO_CMDSRC_ARM);
   bail:
  	raw_spin_unlock_irqrestore(&gpio->lock, flags);
-@@ -1091,12 +1042,10 @@ EXPORT_SYMBOL_GPL(aspeed_gpio_copro_release_gpio);
+@@ -1093,12 +1042,10 @@ EXPORT_SYMBOL_GPL(aspeed_gpio_copro_release_gpio);
  
  static void aspeed_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p)
  {
@@ -1434,7 +1435,7 @@
  	if (rc)
  		return;
  
-@@ -1113,6 +1062,173 @@ static const struct irq_chip aspeed_gpio_irq_chip = {
+@@ -1115,6 +1062,173 @@ static const struct irq_chip aspeed_gpio_irq_chip = {
  	GPIOCHIP_IRQ_RESOURCE_HELPERS,
  };
  
@@ -1608,7 +1609,7 @@
  /*
   * Any banks not specified in a struct aspeed_bank_props array are assumed to
   * have the properties:
-@@ -1129,7 +1245,14 @@ static const struct aspeed_bank_props ast2400_bank_props[] = {
+@@ -1131,7 +1245,14 @@ static const struct aspeed_bank_props ast2400_bank_props[] = {
  
  static const struct aspeed_gpio_config ast2400_config =
  	/* 220 for simplicity, really 216 with two 4-GPIO holes, four at end */
@@ -1624,7 +1625,7 @@
  
  static const struct aspeed_bank_props ast2500_bank_props[] = {
  	/*     input	  output   */
-@@ -1141,7 +1264,14 @@ static const struct aspeed_bank_props ast2500_bank_props[] = {
+@@ -1143,7 +1264,14 @@ static const struct aspeed_bank_props ast2500_bank_props[] = {
  
  static const struct aspeed_gpio_config ast2500_config =
  	/* 232 for simplicity, actual number is 228 (4-GPIO hole in GPIOAB) */
@@ -1640,7 +1641,7 @@
  
  static const struct aspeed_bank_props ast2600_bank_props[] = {
  	/*     input	  output   */
-@@ -1157,17 +1287,49 @@ static const struct aspeed_gpio_config ast2600_config =
+@@ -1159,17 +1287,49 @@ static const struct aspeed_gpio_config ast2600_config =
  	 * We expect ngpio being set in the device tree and this is a fallback
  	 * option.
  	 */
@@ -1692,16 +1693,7 @@
  {
  	const struct of_device_id *gpio_id;
  	struct gpio_irq_chip *girq;
-@@ -1191,7 +1353,7 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
- 	if (!gpio_id)
- 		return -EINVAL;
- 
--	gpio->clk = of_clk_get(pdev->dev.of_node, 0);
-+	gpio->clk = devm_clk_get_enabled(&pdev->dev, NULL);
- 	if (IS_ERR(gpio->clk)) {
- 		dev_warn(&pdev->dev,
- 				"Failed to get clock from devicetree, debouncing disabled\n");
-@@ -1200,6 +1362,10 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
+@@ -1202,6 +1362,10 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
  
  	gpio->config = gpio_id->data;
  
@@ -1712,7 +1704,7 @@
  	gpio->chip.parent = &pdev->dev;
  	err = of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpio);
  	gpio->chip.ngpio = (u16) ngpio;
-@@ -1216,27 +1382,23 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
+@@ -1218,27 +1382,23 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
  	gpio->chip.label = dev_name(&pdev->dev);
  	gpio->chip.base = -1;
  
@@ -1755,7 +1747,7 @@
  	/* Set up an irqchip */
  	irq = platform_get_irq(pdev, 0);
  	if (irq < 0)
-@@ -1268,13 +1430,14 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
+@@ -1270,13 +1430,14 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
  }
  
  static struct platform_driver aspeed_gpio_driver = {
diff --git a/recipes-kernel/linux/files/0012-Add-i2c-driver-for-ast2700.patch b/recipes-kernel/linux/files/0012-Add-i2c-driver-for-ast2700.patch
index 5a26cfa..e5bc2ab 100644
--- a/recipes-kernel/linux/files/0012-Add-i2c-driver-for-ast2700.patch
+++ b/recipes-kernel/linux/files/0012-Add-i2c-driver-for-ast2700.patch
@@ -1,32 +1,32 @@
-From 5da159d403a324e3d01cc19b20a2dc51b592505e Mon Sep 17 00:00:00 2001
-From: "yung-sheng.huang" <yung-sheng.huang@fii-na.corp-partner.google.com>
-Date: Tue, 15 Apr 2025 16:40:03 +0800
-Subject: [PATCH 12/26] Add i2c driver for ast2700
+From 020f7a0d386d6c0959f3bbb5138cd90cddc36276 Mon Sep 17 00:00:00 2001
+From: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+Date: Thu, 17 Jul 2025 08:34:35 +0800
+Subject: [PATCH] Add i2c driver for ast2700
 
-This is base on aspeed SDK 9.06.
+This is base on aspeed SDK 9.07.
 
 Source:
 AspeedTech-BMC github:
 https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/
-(cherry picked from commit v00.06.06)
+(cherry picked from commit v00.06.07)
 
-Signed-off-by: yung-sheng.huang <yung-sheng.huang@fii-na.corp-partner.google.com>
+Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
 ---
  drivers/i2c/busses/Kconfig       |   11 +
  drivers/i2c/busses/Makefile      |    1 +
- drivers/i2c/busses/i2c-aspeed.c  |   17 +-
- drivers/i2c/busses/i2c-ast2600.c | 2082 ++++++++++++++++++++++++++++++
- drivers/i2c/i2c-core-base.c      |   77 ++
+ drivers/i2c/busses/i2c-aspeed.c  |    1 +
+ drivers/i2c/busses/i2c-ast2600.c | 2422 ++++++++++++++++++++++++++++++
+ drivers/i2c/i2c-core-base.c      |   38 +
  drivers/i2c/i2c-mux.c            |   50 +
- include/linux/i2c.h              |   47 +
- 7 files changed, 2277 insertions(+), 8 deletions(-)
- create mode 100644 drivers/i2c/busses/i2c-ast2600.c
+ include/linux/i2c.h              |   42 +
+ 7 files changed, 2565 insertions(+)
+ create mode 100755 drivers/i2c/busses/i2c-ast2600.c
 
 diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
-index 97d27e01a..854131e86 100644
+index 982007a11..3e70eb1a4 100644
 --- a/drivers/i2c/busses/Kconfig
 +++ b/drivers/i2c/busses/Kconfig
-@@ -390,6 +390,17 @@ config I2C_ALTERA
+@@ -392,6 +392,17 @@ config I2C_ALTERA
  	  This driver can also be built as a module.  If so, the module
  	  will be called i2c-altera.
  
@@ -57,46 +57,9 @@
  i2c-at91-objs			:= i2c-at91-core.o i2c-at91-master.o
  ifeq ($(CONFIG_I2C_AT91_SLAVE_EXPERIMENTAL),y)
 diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
-index 5511fd46a..2a03a221e 100644
+index 83e671490..2a03a221e 100644
 --- a/drivers/i2c/busses/i2c-aspeed.c
 +++ b/drivers/i2c/busses/i2c-aspeed.c
-@@ -170,6 +170,13 @@ struct aspeed_i2c_bus {
- 
- static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus);
- 
-+/* precondition: bus.lock has been acquired. */
-+static void aspeed_i2c_do_stop(struct aspeed_i2c_bus *bus)
-+{
-+	bus->master_state = ASPEED_I2C_MASTER_STOP;
-+	writel(ASPEED_I2CD_M_STOP_CMD, bus->base + ASPEED_I2C_CMD_REG);
-+}
-+
- static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
- {
- 	unsigned long time_left, flags;
-@@ -187,7 +194,7 @@ static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
- 			command);
- 
- 		reinit_completion(&bus->cmd_complete);
--		writel(ASPEED_I2CD_M_STOP_CMD, bus->base + ASPEED_I2C_CMD_REG);
-+		aspeed_i2c_do_stop(bus);
- 		spin_unlock_irqrestore(&bus->lock, flags);
- 
- 		time_left = wait_for_completion_timeout(
-@@ -390,13 +397,6 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus)
- 	writel(command, bus->base + ASPEED_I2C_CMD_REG);
- }
- 
--/* precondition: bus.lock has been acquired. */
--static void aspeed_i2c_do_stop(struct aspeed_i2c_bus *bus)
--{
--	bus->master_state = ASPEED_I2C_MASTER_STOP;
--	writel(ASPEED_I2CD_M_STOP_CMD, bus->base + ASPEED_I2C_CMD_REG);
--}
--
- /* precondition: bus.lock has been acquired. */
- static void aspeed_i2c_next_msg_or_stop(struct aspeed_i2c_bus *bus)
- {
 @@ -445,6 +445,7 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
  			irq_status);
  		irq_handled |= (irq_status & ASPEED_I2CD_INTR_MASTER_ERRORS);
@@ -106,11 +69,11 @@
  			bus->master_state = ASPEED_I2C_MASTER_INACTIVE;
  			goto out_complete;
 diff --git a/drivers/i2c/busses/i2c-ast2600.c b/drivers/i2c/busses/i2c-ast2600.c
-new file mode 100644
-index 000000000..69e297af4
+new file mode 100755
+index 000000000..03b953822
 --- /dev/null
 +++ b/drivers/i2c/busses/i2c-ast2600.c
-@@ -0,0 +1,2082 @@
+@@ -0,0 +1,2422 @@
 +// SPDX-License-Identifier: GPL-2.0-only
 +/*
 + * ASPEED AST2600 new register set I2C controller driver
@@ -166,7 +129,9 @@
 + * I2CG10[7:0] base clk1 for Fast-mode Plus (1Mhz) min tBuf 0.5us
 + * 0x08 : 1Mhz		: 20Mhz						  : 0.8us
 + */
-+#define I2CCG_DIV_CTRL 0xC6411208
++#define AST2600_I2CCG_DIV_CTRL 0xC6411208
++#define AST2700_I2CCG_DIV_CTRL 0xC6220904
++#define AST2700_MIN_AC_TIMING 12000
 +
 +/* 0x00 : I2CC Master/Slave Function Control Register  */
 +#define AST2600_I2CC_FUN_CTRL		0x00
@@ -189,6 +154,7 @@
 +/* 0x04 : I2CC Master/Slave Clock and AC Timing Control Register #1 */
 +#define AST2600_I2CC_AC_TIMING		0x04
 +#define AST2600_I2CC_TTIMEOUT(x)			(((x) & GENMASK(4, 0)) << 24)
++#define AST2700_I2CC_TTIMEOUT(x)			(((x) & GENMASK(5, 0)) << 24)
 +#define AST2600_I2CC_TCKHIGHMIN(x)			(((x) & GENMASK(3, 0)) << 20)
 +#define AST2600_I2CC_TCKHIGH(x)			(((x) & GENMASK(3, 0)) << 16)
 +#define AST2600_I2CC_TCKLOW(x)			(((x) & GENMASK(3, 0)) << 12)
@@ -234,6 +200,7 @@
 +#define AST2600_I2CM_SDA_DL_TO			BIT(14)
 +#define AST2600_I2CM_BUS_RECOVER			BIT(13)
 +#define AST2600_I2CM_SMBUS_ALT			BIT(12)
++#define AST2700_I2CM_ABNORMAL_ACTION	BIT(8)
 +
 +#define AST2600_I2CM_SCL_LOW_TO			BIT(6)
 +#define AST2600_I2CM_ABNORMAL			BIT(5)
@@ -267,9 +234,6 @@
 +
 +/* 0x1C : I2CM Master DMA Transfer Length Register	 */
 +#define AST2600_I2CM_DMA_LEN		0x1C
-+/* Master Tx Rx support length 1 ~ 65536 */
-+#define AST2700_I2CM_SET_RX_DMA_LEN(x)	(((x) & GENMASK(15, 0)) << 16)
-+#define AST2700_I2CM_SET_TX_DMA_LEN(x)	((x) & GENMASK(15, 0))
 +/* Master Tx Rx support length 1 ~ 4096 */
 +#define AST2600_I2CM_SET_RX_DMA_LEN(x)	((((x) & GENMASK(11, 0)) << 16) | BIT(31))
 +#define AST2600_I2CM_SET_TX_DMA_LEN(x)	(((x) & GENMASK(11, 0)) | BIT(15))
@@ -292,6 +256,7 @@
 +
 +#define AST2600_I2CS_ADDR_NAK_MASK		GENMASK(22, 20)
 +#define AST2600_I2CS_ADDR_MASK			GENMASK(19, 18)
++#define AST2600_I2CS_GET_SLAVE(x)	(((x) >> 30) & 0x3)
 +#define AST2600_I2CS_PKT_ERROR			BIT(17)
 +#define AST2600_I2CS_PKT_DONE			BIT(16)
 +#define AST2600_I2CS_INACTIVE_TO			BIT(15)
@@ -370,8 +335,14 @@
 +/* 0x78 : Controller status */
 +#define MSIC_STATUS		0x78
 +
++/* 0x84 : Byte data log */
++#define BYTE_DATA_LOG	0x84
++
++#define AST2700_I2CC_GET_BUFF(x)		((x) & GENMASK(7, 0))
++
 +/* 0x8c : Slave sirq log */
 +#define AST2700_I2CC_SIRQ_LOG			0x8c
++#define SLAVE_ADDR_SHIFT		8
 +#define SLAVE_ADDR_MASK			GENMASK(15, 8)
 +#define SADDR_NACK				BIT(5)
 +#define SLAVE_PKT_DONE			BIT(4)
@@ -396,6 +367,8 @@
 +#define AST2600_I2C_TIMEOUT_CLK		0x1
 +#define AST2700_I2C_TIMEOUT_CLK		0x3
 +
++#define AST2600_I2C_SLAVE_COUNT		0x3
++
 +enum xfer_mode {
 +	BYTE_MODE,
 +	BUFF_MODE,
@@ -442,6 +415,8 @@
 +	int				slave_operate;
 +	unsigned char			*slave_dma_buf;
 +	dma_addr_t			slave_dma_addr;
++	u8 slave_attached;
++	struct i2c_client		*multi_slave[AST2600_I2C_SLAVE_COUNT];
 +	struct i2c_client		*slave;
 +#endif
 +};
@@ -492,27 +467,53 @@
 +	unsigned long base_clk;
 +	int baseclk_idx = 0;
 +	int divisor = 0;
++	u32 clk_div_reg;
 +	u32 scl_low;
 +	u32 scl_high;
 +	u32 data;
++	u8  divid_term = 0;
 +
-+	for (int i = 0; i < 0x100; i++) {
-+		base_clk = (i2c_bus->apb_clk) / (i + 1);
++	/* The i2c minmum ac-timing is 12KHz */
++	if (i2c_bus->timing_info.bus_freq_hz < AST2700_MIN_AC_TIMING) {
++		dev_err(i2c_bus->dev, "The frequency could not be lower than 12KHz.\n");
++		i2c_bus->timing_info.bus_freq_hz = AST2700_MIN_AC_TIMING;
++	}
++
++	regmap_read(i2c_bus->global_regs, AST2600_I2CG_CLK_DIV_CTRL, &clk_div_reg);
++
++	/* Find the most used ac-timing */
++	for (int i = 0; i < 3; i++) {
++		divid_term = ((clk_div_reg >> (i << 3)) & GENMASK(7, 0));
++		base_clk = (i2c_bus->apb_clk) / (divid_term + 1);
++
 +		if ((base_clk / i2c_bus->timing_info.bus_freq_hz) <= 32) {
-+			baseclk_idx = i;
++			baseclk_idx = divid_term;
 +			divisor = DIV_ROUND_UP(base_clk, i2c_bus->timing_info.bus_freq_hz);
 +			break;
 +		}
 +	}
 +
++	/* Can't find a ac-timing then search a fitting one */
++	if (baseclk_idx == 0) {
++		for (int i = 0; i < 0x100; i++) {
++			base_clk = (i2c_bus->apb_clk) / (i + 1);
++
++			if ((base_clk / i2c_bus->timing_info.bus_freq_hz) <= 32) {
++				baseclk_idx = i;
++				divisor = DIV_ROUND_UP(base_clk, i2c_bus->timing_info.bus_freq_hz);
++				break;
++			}
++		}
++	}
++
 +	baseclk_idx = min(baseclk_idx, 0xff);
 +	divisor = min(divisor, 32);
-+	scl_low = min(divisor * 9 / 16 - 1, 15);
++	scl_low = min((DIV_ROUND_UP(divisor * 9, 16)) - 1, 15);
 +	scl_high = (divisor - scl_low - 2) & GENMASK(3, 0);
 +	data = (scl_high - 1) << 20 | scl_high << 16 | scl_low << 12 | baseclk_idx;
 +	if (i2c_bus->timeout) {
 +		i2c_bus->timeout = min(i2c_bus->timeout, 255);
-+		writel(MSIC_I2C_SET_TIMEOUT(i2c_bus->timeout, i2c_bus->timeout),
++		writel(MSIC_I2C_SET_TIMEOUT(i2c_bus->timeout, 0),
 +		       i2c_bus->reg_base + MSIC_CONFIG_ACTIMING1);
 +		/* timeout_base set as 1ms */
 +		data |= AST2600_I2CC_TOUTBASECLK(AST2700_I2C_TIMEOUT_CLK);
@@ -525,7 +526,6 @@
 +{
 +	u32 state = readl(i2c_bus->reg_base + AST2600_I2CC_STS_AND_BUFF);
 +	int ret = 0;
-+	u32 ctrl;
 +	int r;
 +
 +	dev_dbg(i2c_bus->dev, "%d-bus recovery bus [%x]\n", i2c_bus->adap.nr, state);
@@ -540,7 +540,6 @@
 +		r = wait_for_completion_timeout(&i2c_bus->cmd_complete, i2c_bus->adap.timeout);
 +		if (r == 0) {
 +			dev_dbg(i2c_bus->dev, "recovery timed out\n");
-+			writel(ctrl, i2c_bus->reg_base + AST2600_I2CC_FUN_CTRL);
 +			return -ETIMEDOUT;
 +		} else if (i2c_bus->cmd_err) {
 +			dev_dbg(i2c_bus->dev, "recovery error\n");
@@ -559,6 +558,26 @@
 +}
 +
 +#if IS_ENABLED(CONFIG_I2C_SLAVE)
++static void ast2700_i2c_get_slave(struct ast2600_i2c_bus *i2c_bus, u8 addr)
++{
++	u8 i = 0;
++	bool slave_find = false;
++
++	/* find slave by address */
++	for (i = 0; i < AST2600_I2C_SLAVE_COUNT; i++) {
++		if (i2c_bus->multi_slave[i]) {
++			if (i2c_bus->multi_slave[i]->addr == addr) {
++				dev_dbg(i2c_bus->dev, "address [%x] on %d\n", addr, i);
++				i2c_bus->slave = i2c_bus->multi_slave[i];
++				slave_find = true;
++			}
++		}
++	}
++
++	if (!slave_find)
++		dev_err(i2c_bus->dev, "address [%x] could not find\n", addr);
++}
++
 +static void ast2700_i2c_slave_packet_dma_irq(struct ast2600_i2c_bus *i2c_bus, u32 isr)
 +{
 +	int slave_rx_len = 0;
@@ -575,28 +594,53 @@
 +	sts = isr & ~(AST2600_I2CS_SLAVE_PENDING | AST2600_I2CS_ADDR_NAK_MASK);
 +	/* Handle i2c slave timeout condition */
 +	if (AST2600_I2CS_INACTIVE_TO & sts) {
++		dev_dbg(i2c_bus->dev, "The slave timeout occurs isr: 0x%08x.\n", isr);
++		/* Reset time out counter */
++		u32 ac_timing = readl(i2c_bus->reg_base + AST2600_I2CC_AC_TIMING) &
++				AST2600_I2CC_AC_TIMING_MASK;
++
++		writel(ac_timing, i2c_bus->reg_base + AST2600_I2CC_AC_TIMING);
++		ac_timing |= AST2700_I2CC_TTIMEOUT(i2c_bus->timeout);
++		writel(ac_timing, i2c_bus->reg_base + AST2600_I2CC_AC_TIMING);
 +		cmd = SLAVE_TRIGGER_CMD | AST2600_I2CS_RX_DMA_EN;
 +		writel(AST2600_I2CS_SET_RX_DMA_LEN(I2C_SLAVE_MSG_BUF_SIZE),
 +		       i2c_bus->reg_base + AST2600_I2CS_DMA_LEN);
 +		writel(cmd, i2c_bus->reg_base + AST2600_I2CS_CMD_STS);
 +		/* clear sirq log */
-+		while (readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG))
-+			;
++		while (readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG)) {
++			/* assign the slave client*/
++			if (sirq_log & SADDR_HIT) {
++				if (!i2c_bus->slave)
++					ast2700_i2c_get_slave(i2c_bus, sirq_log >> SLAVE_ADDR_SHIFT);
++			}
++		};
 +		writel(isr, i2c_bus->reg_base + AST2600_I2CS_ISR);
-+		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_STOP, &value);
++		if (i2c_bus->slave) {
++			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_STOP, &value);
++			i2c_bus->slave = NULL;
++		}
 +		return;
 +	}
 +
 +	if (AST2600_I2CS_ABNOR_STOP & sts) {
++		dev_err(i2c_bus->dev, "The slave abnomal protocol occurs isr: 0x%08x.\n", isr);
 +		cmd = SLAVE_TRIGGER_CMD | AST2600_I2CS_RX_DMA_EN;
 +		writel(AST2600_I2CS_SET_RX_DMA_LEN(I2C_SLAVE_MSG_BUF_SIZE),
 +		       i2c_bus->reg_base + AST2600_I2CS_DMA_LEN);
 +		writel(cmd, i2c_bus->reg_base + AST2600_I2CS_CMD_STS);
 +		/* clear sirq log */
-+		while (readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG))
-+			;
++		while (readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG)) {
++			/* assign the slave client*/
++			if (sirq_log & SADDR_HIT) {
++				if (!i2c_bus->slave)
++					ast2700_i2c_get_slave(i2c_bus, sirq_log >> SLAVE_ADDR_SHIFT);
++			}
++		};
 +		writel(isr, i2c_bus->reg_base + AST2600_I2CS_ISR);
-+		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_STOP, &value);
++		if (i2c_bus->slave) {
++			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_STOP, &value);
++			i2c_bus->slave = NULL;
++		}
 +		return;
 +	}
 +
@@ -607,22 +651,32 @@
 +		AST2600_I2CS_SLAVE_MATCH | AST2600_I2CS_RX_DONE | AST2600_I2CS_STOP:
 +		writel(AST2600_I2CS_SLAVE_MATCH, i2c_bus->reg_base + AST2600_I2CS_ISR);
 +		isr = readl(i2c_bus->reg_base + AST2600_I2CS_ISR);
-+
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
-+		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_REQUESTED,
-+				&i2c_bus->slave_dma_buf[0]);
++		if (!i2c_bus->slave)
++			ast2700_i2c_get_slave(i2c_bus, sirq_log >> SLAVE_ADDR_SHIFT);
++		if (i2c_bus->slave) {
++			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_REQUESTED,
++					&i2c_bus->slave_dma_buf[0]);
++		}
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
 +		slave_rx_len = AST2600_I2C_GET_RX_DMA_LEN(readl(i2c_bus->reg_base +
 +							  AST2600_I2CS_DMA_LEN_STS));
 +		for (i = 0; i < slave_rx_len; i++) {
-+			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_RECEIVED,
-+					&i2c_bus->slave_dma_buf[i]);
++			if (i2c_bus->slave) {
++				i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_RECEIVED,
++						&i2c_bus->slave_dma_buf[i]);
++			}
 +		}
-+		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_STOP, &value);
-+
++		if (i2c_bus->slave)
++			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_STOP, &value);
++		i2c_bus->slave = NULL;
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
-+		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_REQUESTED,
-+				&i2c_bus->slave_dma_buf[0]);
++		if (!i2c_bus->slave)
++			ast2700_i2c_get_slave(i2c_bus, sirq_log >> SLAVE_ADDR_SHIFT);
++		if (i2c_bus->slave) {
++			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_REQUESTED,
++					&i2c_bus->slave_dma_buf[0]);
++		}
 +		writel(AST2600_I2CS_SET_RX_DMA_LEN(I2C_SLAVE_MSG_BUF_SIZE),
 +		       i2c_bus->reg_base + AST2600_I2CS_DMA_LEN);
 +		cmd = SLAVE_TRIGGER_CMD | AST2600_I2CS_RX_DMA_EN;
@@ -631,31 +685,45 @@
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
 +		/* bug workaround */
 +		if (sirq_log & SADDR_HIT) {
-+			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_REQUESTED,
-+					&i2c_bus->slave_dma_buf[0]);
++			if (!i2c_bus->slave)
++				ast2700_i2c_get_slave(i2c_bus, sirq_log >> SLAVE_ADDR_SHIFT);
++			if (i2c_bus->slave) {
++				i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_REQUESTED,
++						&i2c_bus->slave_dma_buf[0]);
++			}
 +			sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
 +		}
 +		slave_rx_len = AST2600_I2C_GET_RX_DMA_LEN(readl(i2c_bus->reg_base +
 +				      AST2600_I2CS_DMA_LEN_STS));
 +		for (i = 0; i < slave_rx_len; i++) {
-+			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_RECEIVED,
-+					&i2c_bus->slave_dma_buf[i]);
++			if (i2c_bus->slave) {
++				i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_RECEIVED,
++						&i2c_bus->slave_dma_buf[i]);
++			}
 +		}
 +		writel(AST2600_I2CS_SET_RX_DMA_LEN(I2C_SLAVE_MSG_BUF_SIZE),
 +		       i2c_bus->reg_base + AST2600_I2CS_DMA_LEN);
-+		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_STOP, &value);
++		if (i2c_bus->slave)
++			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_STOP, &value);
++		i2c_bus->slave = NULL;
 +		cmd = SLAVE_TRIGGER_CMD | AST2600_I2CS_RX_DMA_EN;
 +		break;
 +	case AST2600_I2CS_SLAVE_MATCH:
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
-+		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_REQUESTED,
-+				&i2c_bus->slave_dma_buf[0]);
++		if (!i2c_bus->slave)
++			ast2700_i2c_get_slave(i2c_bus, sirq_log >> SLAVE_ADDR_SHIFT);
++		if (i2c_bus->slave) {
++			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_REQUESTED,
++					&i2c_bus->slave_dma_buf[0]);
++		}
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
 +		slave_rx_len = AST2600_I2C_GET_RX_DMA_LEN(readl(i2c_bus->reg_base +
 +							  AST2600_I2CS_DMA_LEN_STS));
 +		for (i = 0; i < slave_rx_len; i++) {
-+			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_RECEIVED,
-+					&i2c_bus->slave_dma_buf[i]);
++			if (i2c_bus->slave) {
++				i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_RECEIVED,
++						&i2c_bus->slave_dma_buf[i]);
++			}
 +		}
 +		writel(AST2600_I2CS_SET_RX_DMA_LEN(I2C_SLAVE_MSG_BUF_SIZE),
 +		       i2c_bus->reg_base + AST2600_I2CS_DMA_LEN);
@@ -665,16 +733,24 @@
 +		AST2600_I2CS_RX_DONE | AST2600_I2CS_STOP:
 +	case AST2600_I2CS_SLAVE_MATCH | AST2600_I2CS_STOP:
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
-+		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_REQUESTED,
-+				&i2c_bus->slave_dma_buf[0]);
++		if (!i2c_bus->slave)
++			ast2700_i2c_get_slave(i2c_bus, sirq_log >> SLAVE_ADDR_SHIFT);
++		if (i2c_bus->slave) {
++			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_REQUESTED,
++					&i2c_bus->slave_dma_buf[0]);
++		}
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
 +		slave_rx_len = AST2600_I2C_GET_RX_DMA_LEN(readl(i2c_bus->reg_base +
 +							  AST2600_I2CS_DMA_LEN_STS));
 +		for (i = 0; i < slave_rx_len; i++) {
-+			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_RECEIVED,
-+					&i2c_bus->slave_dma_buf[i]);
++			if (i2c_bus->slave) {
++				i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_RECEIVED,
++						&i2c_bus->slave_dma_buf[i]);
++			}
 +		}
-+		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_STOP, &value);
++		if (i2c_bus->slave)
++			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_STOP, &value);
++		i2c_bus->slave = NULL;
 +		writel(AST2600_I2CS_SET_RX_DMA_LEN(I2C_SLAVE_MSG_BUF_SIZE),
 +		       i2c_bus->reg_base + AST2600_I2CS_DMA_LEN);
 +		cmd = SLAVE_TRIGGER_CMD | AST2600_I2CS_RX_DMA_EN;
@@ -684,20 +760,32 @@
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
 +		/* workaround: false alarm slave match check */
 +		if (sirq_log & SADDR_HIT) {
-+			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_REQUESTED,
-+					&i2c_bus->slave_dma_buf[0]);
++			if (!i2c_bus->slave)
++				ast2700_i2c_get_slave(i2c_bus, sirq_log >> SLAVE_ADDR_SHIFT);
++			if (i2c_bus->slave) {
++				i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_REQUESTED,
++						&i2c_bus->slave_dma_buf[0]);
++			}
 +			sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
 +		}
 +		slave_rx_len = AST2600_I2C_GET_RX_DMA_LEN(readl(i2c_bus->reg_base +
 +							  AST2600_I2CS_DMA_LEN_STS));
 +		for (i = 0; i < slave_rx_len; i++) {
-+			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_RECEIVED,
-+					&i2c_bus->slave_dma_buf[i]);
++			if (i2c_bus->slave) {
++				i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_RECEIVED,
++						&i2c_bus->slave_dma_buf[i]);
++			}
 +		}
-+		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_STOP, &value);
++		if (i2c_bus->slave)
++			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_STOP, &value);
++		i2c_bus->slave = NULL;
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
-+		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_REQUESTED,
-+				&i2c_bus->slave_dma_buf[0]);
++		if (!i2c_bus->slave)
++			ast2700_i2c_get_slave(i2c_bus, sirq_log >> SLAVE_ADDR_SHIFT);
++		if (i2c_bus->slave) {
++			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_REQUESTED,
++					&i2c_bus->slave_dma_buf[0]);
++		}
 +		writel(AST2600_I2CS_SET_RX_DMA_LEN(I2C_SLAVE_MSG_BUF_SIZE),
 +		       i2c_bus->reg_base + AST2600_I2CS_DMA_LEN);
 +		cmd = SLAVE_TRIGGER_CMD | AST2600_I2CS_RX_DMA_EN;
@@ -706,25 +794,39 @@
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
 +		/* workaround new slave match */
 +		if (sirq_log & SADDR_HIT) {
-+			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_REQUESTED,
-+					&i2c_bus->slave_dma_buf[0]);
++			if (!i2c_bus->slave)
++				ast2700_i2c_get_slave(i2c_bus, sirq_log >> SLAVE_ADDR_SHIFT);
++			if (i2c_bus->slave) {
++				i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_REQUESTED,
++						&i2c_bus->slave_dma_buf[0]);
++			}
 +			sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
 +		}
 +		slave_rx_len = AST2600_I2C_GET_RX_DMA_LEN(readl(i2c_bus->reg_base +
 +							  AST2600_I2CS_DMA_LEN_STS));
 +		for (i = 0; i < slave_rx_len; i++) {
-+			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_RECEIVED,
-+					&i2c_bus->slave_dma_buf[i]);
++			if (i2c_bus->slave) {
++				i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_RECEIVED,
++						&i2c_bus->slave_dma_buf[i]);
++			}
 +		}
-+		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_STOP, &value);
++		if (i2c_bus->slave)
++			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_STOP, &value);
++		i2c_bus->slave = NULL;
 +		writel(AST2600_I2CS_SET_RX_DMA_LEN(I2C_SLAVE_MSG_BUF_SIZE),
 +		       i2c_bus->reg_base + AST2600_I2CS_DMA_LEN);
 +		cmd = SLAVE_TRIGGER_CMD | AST2600_I2CS_RX_DMA_EN;
 +		break;
 +	case AST2600_I2CS_TX_NAK | AST2600_I2CS_STOP | AST2600_I2CS_SLAVE_MATCH:
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
-+		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_STOP, &value);
++		if (i2c_bus->slave)
++			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_STOP, &value);
++		i2c_bus->slave = NULL;
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
++		if (sirq_log & SADDR_HIT) {
++			if (!i2c_bus->slave)
++				ast2700_i2c_get_slave(i2c_bus, sirq_log >> SLAVE_ADDR_SHIFT);
++		}
 +		writel(AST2600_I2CS_SET_RX_DMA_LEN(I2C_SLAVE_MSG_BUF_SIZE),
 +		       i2c_bus->reg_base + AST2600_I2CS_DMA_LEN);
 +		cmd = SLAVE_TRIGGER_CMD | AST2600_I2CS_RX_DMA_EN;
@@ -733,7 +835,9 @@
 +		break;
 +	case AST2600_I2CS_TX_NAK | AST2600_I2CS_STOP:
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
-+		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_STOP, &value);
++		if (i2c_bus->slave)
++			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_STOP, &value);
++		i2c_bus->slave = NULL;
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
 +		writel(AST2600_I2CS_SET_RX_DMA_LEN(I2C_SLAVE_MSG_BUF_SIZE),
 +		       i2c_bus->reg_base + AST2600_I2CS_DMA_LEN);
@@ -743,25 +847,37 @@
 +		AST2600_I2CS_STOP | AST2600_I2CS_SLAVE_MATCH:
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
-+		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_STOP, &value);
++		if (i2c_bus->slave)
++			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_STOP, &value);
++		i2c_bus->slave = NULL;
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
-+		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_REQUESTED,
-+				&i2c_bus->slave_dma_buf[0]);
++		if (!i2c_bus->slave)
++			ast2700_i2c_get_slave(i2c_bus, sirq_log >> SLAVE_ADDR_SHIFT);
++		if (i2c_bus->slave) {
++			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_REQUESTED,
++					&i2c_bus->slave_dma_buf[0]);
++		}
 +		writel(AST2600_I2CS_SET_RX_DMA_LEN(I2C_SLAVE_MSG_BUF_SIZE),
 +		       i2c_bus->reg_base + AST2600_I2CS_DMA_LEN);
 +		cmd = SLAVE_TRIGGER_CMD | AST2600_I2CS_RX_DMA_EN;
 +		break;
 +	case AST2600_I2CS_SLAVE_MATCH | AST2600_I2CS_WAIT_TX_DMA:
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
-+		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_READ_REQUESTED,
-+				&i2c_bus->slave_dma_buf[0]);
++		if (!i2c_bus->slave)
++			ast2700_i2c_get_slave(i2c_bus, sirq_log >> SLAVE_ADDR_SHIFT);
++		if (i2c_bus->slave) {
++			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_READ_REQUESTED,
++					&i2c_bus->slave_dma_buf[0]);
++		}
 +		writel(AST2600_I2CS_SET_TX_DMA_LEN(1), i2c_bus->reg_base + AST2600_I2CS_DMA_LEN);
 +		cmd = SLAVE_TRIGGER_CMD | AST2600_I2CS_TX_DMA_EN;
 +		break;
 +	case AST2600_I2CS_TX_ACK | AST2600_I2CS_WAIT_TX_DMA:
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
-+		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_READ_PROCESSED,
-+				&i2c_bus->slave_dma_buf[0]);
++		if (i2c_bus->slave) {
++			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_READ_PROCESSED,
++					&i2c_bus->slave_dma_buf[0]);
++		}
 +		writel(AST2600_I2CS_SET_TX_DMA_LEN(1), i2c_bus->reg_base + AST2600_I2CS_DMA_LEN);
 +		cmd = SLAVE_TRIGGER_CMD | AST2600_I2CS_TX_DMA_EN;
 +		break;
@@ -771,13 +887,21 @@
 +		slave_rx_len = AST2600_I2C_GET_RX_DMA_LEN(readl(i2c_bus->reg_base +
 +								AST2600_I2CS_DMA_LEN_STS));
 +		for (i = 0; i < slave_rx_len; i++) {
-+			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_RECEIVED,
-+					&i2c_bus->slave_dma_buf[i]);
++			if (i2c_bus->slave) {
++				i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_RECEIVED,
++						&i2c_bus->slave_dma_buf[i]);
++			}
 +		}
-+		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_STOP, &value);
++		if (i2c_bus->slave)
++			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_STOP, &value);
++		i2c_bus->slave = NULL;
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
-+		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_READ_REQUESTED,
-+				&i2c_bus->slave_dma_buf[0]);
++		if (!i2c_bus->slave)
++			ast2700_i2c_get_slave(i2c_bus, sirq_log >> SLAVE_ADDR_SHIFT);
++		if (i2c_bus->slave) {
++			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_READ_REQUESTED,
++					&i2c_bus->slave_dma_buf[0]);
++		}
 +		writel(AST2600_I2CS_SET_TX_DMA_LEN(1),
 +		       i2c_bus->reg_base + AST2600_I2CS_DMA_LEN);
 +		cmd = SLAVE_TRIGGER_CMD | AST2600_I2CS_TX_DMA_EN;
@@ -787,12 +911,18 @@
 +		slave_rx_len = AST2600_I2C_GET_RX_DMA_LEN(readl(i2c_bus->reg_base +
 +							  AST2600_I2CS_DMA_LEN_STS));
 +		for (i = 0; i < slave_rx_len; i++) {
-+			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_RECEIVED,
-+					&i2c_bus->slave_dma_buf[i]);
++			if (i2c_bus->slave) {
++				i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_RECEIVED,
++						&i2c_bus->slave_dma_buf[i]);
++			}
 +		}
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
-+		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_READ_REQUESTED,
-+				&i2c_bus->slave_dma_buf[0]);
++		if (!i2c_bus->slave)
++			ast2700_i2c_get_slave(i2c_bus, sirq_log >> SLAVE_ADDR_SHIFT);
++		if (i2c_bus->slave) {
++			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_READ_REQUESTED,
++					&i2c_bus->slave_dma_buf[0]);
++		}
 +		writel(AST2600_I2CS_SET_TX_DMA_LEN(1), i2c_bus->reg_base + AST2600_I2CS_DMA_LEN);
 +		cmd = SLAVE_TRIGGER_CMD | AST2600_I2CS_TX_DMA_EN;
 +		break;
@@ -801,18 +931,28 @@
 +		writel(AST2600_I2CS_SLAVE_MATCH, i2c_bus->reg_base + AST2600_I2CS_ISR);
 +		isr = readl(i2c_bus->reg_base + AST2600_I2CS_ISR);
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
-+		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_REQUESTED,
-+				&i2c_bus->slave_dma_buf[0]);
++		if (!i2c_bus->slave)
++			ast2700_i2c_get_slave(i2c_bus, sirq_log >> SLAVE_ADDR_SHIFT);
++		if (i2c_bus->slave) {
++			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_REQUESTED,
++					&i2c_bus->slave_dma_buf[0]);
++		}
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
 +		slave_rx_len = AST2600_I2C_GET_RX_DMA_LEN(readl(i2c_bus->reg_base +
 +							  AST2600_I2CS_DMA_LEN_STS));
 +		for (i = 0; i < slave_rx_len; i++) {
-+			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_RECEIVED,
-+					&i2c_bus->slave_dma_buf[i]);
++			if (i2c_bus->slave) {
++				i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_RECEIVED,
++						&i2c_bus->slave_dma_buf[i]);
++			}
 +		}
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
-+		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_READ_REQUESTED,
-+				&i2c_bus->slave_dma_buf[0]);
++		if (!i2c_bus->slave)
++			ast2700_i2c_get_slave(i2c_bus, sirq_log >> SLAVE_ADDR_SHIFT);
++		if (i2c_bus->slave) {
++			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_READ_REQUESTED,
++					&i2c_bus->slave_dma_buf[0]);
++		}
 +		writel(AST2600_I2CS_SET_TX_DMA_LEN(1), i2c_bus->reg_base + AST2600_I2CS_DMA_LEN);
 +		cmd = SLAVE_TRIGGER_CMD | AST2600_I2CS_TX_DMA_EN;
 +		break;
@@ -821,25 +961,41 @@
 +		writel(AST2600_I2CS_SLAVE_MATCH, i2c_bus->reg_base + AST2600_I2CS_ISR);
 +		isr = readl(i2c_bus->reg_base + AST2600_I2CS_ISR);
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
-+		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_REQUESTED,
-+				&i2c_bus->slave_dma_buf[0]);
++		if (!i2c_bus->slave)
++			ast2700_i2c_get_slave(i2c_bus, sirq_log >> SLAVE_ADDR_SHIFT);
++		if (i2c_bus->slave) {
++			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_REQUESTED,
++					&i2c_bus->slave_dma_buf[0]);
++		}
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
 +		slave_rx_len = AST2600_I2C_GET_RX_DMA_LEN(readl(i2c_bus->reg_base +
 +							  AST2600_I2CS_DMA_LEN_STS));
-+		for (i = 0; i < slave_rx_len; i++)
-+			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_RECEIVED,
-+					&i2c_bus->slave_dma_buf[i]);
-+		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_STOP, &value);
++		for (i = 0; i < slave_rx_len; i++) {
++			if (i2c_bus->slave) {
++				i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_RECEIVED,
++						&i2c_bus->slave_dma_buf[i]);
++			}
++		}
++		if (i2c_bus->slave)
++			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_STOP, &value);
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
-+		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_READ_REQUESTED,
-+				&i2c_bus->slave_dma_buf[0]);
++		if (!i2c_bus->slave)
++			ast2700_i2c_get_slave(i2c_bus, sirq_log >> SLAVE_ADDR_SHIFT);
++		if (i2c_bus->slave) {
++			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_READ_REQUESTED,
++					&i2c_bus->slave_dma_buf[0]);
++		}
 +		writel(AST2600_I2CS_SET_TX_DMA_LEN(1), i2c_bus->reg_base + AST2600_I2CS_DMA_LEN);
 +		cmd = SLAVE_TRIGGER_CMD | AST2600_I2CS_TX_DMA_EN;
 +		break;
 +	case AST2600_I2CS_WAIT_TX_DMA:
 +		sirq_log = readl(i2c_bus->reg_base + AST2700_I2CC_SIRQ_LOG);
-+		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_READ_REQUESTED,
-+				&i2c_bus->slave_dma_buf[0]);
++		if (!i2c_bus->slave)
++			ast2700_i2c_get_slave(i2c_bus, sirq_log >> SLAVE_ADDR_SHIFT);
++		if (i2c_bus->slave) {
++			i2c_slave_event(i2c_bus->slave, I2C_SLAVE_READ_REQUESTED,
++					&i2c_bus->slave_dma_buf[0]);
++		}
 +		writel(AST2600_I2CS_SET_TX_DMA_LEN(1), i2c_bus->reg_base + AST2600_I2CS_DMA_LEN);
 +		cmd = SLAVE_TRIGGER_CMD | AST2600_I2CS_TX_DMA_EN;
 +		break;
@@ -869,8 +1025,18 @@
 +
 +	sts &= ~(AST2600_I2CS_SLAVE_PENDING | AST2600_I2CS_SADDR_PENDING
 +	| AST2600_I2CS_ADDR_NAK_MASK);
++
++	i2c_bus->slave = i2c_bus->multi_slave[AST2600_I2CS_GET_SLAVE(sts)];
++
 +	/* Handle i2c slave timeout condition */
 +	if (AST2600_I2CS_INACTIVE_TO & sts) {
++		/* Reset time out counter */
++		u32 ac_timing = readl(i2c_bus->reg_base + AST2600_I2CC_AC_TIMING) &
++				AST2600_I2CC_AC_TIMING_MASK;
++
++		writel(ac_timing, i2c_bus->reg_base + AST2600_I2CC_AC_TIMING);
++		ac_timing |= AST2600_I2CC_TTIMEOUT(i2c_bus->timeout);
++		writel(ac_timing, i2c_bus->reg_base + AST2600_I2CC_AC_TIMING);
 +		cmd = SLAVE_TRIGGER_CMD | AST2600_I2CS_RX_DMA_EN;
 +		writel(AST2600_I2CS_SET_RX_DMA_LEN(I2C_SLAVE_MSG_BUF_SIZE),
 +		       i2c_bus->reg_base + AST2600_I2CS_DMA_LEN);
@@ -880,11 +1046,11 @@
 +		return;
 +	}
 +
-+	sts &= ~(AST2600_I2CS_PKT_DONE | AST2600_I2CS_PKT_ERROR);
++	sts &= ~(AST2600_I2CS_PKT_DONE | AST2600_I2CS_PKT_ERROR | AST2600_I2CS_ADDR_INDICATE_MASK);
 +
 +	switch (sts) {
-+	case AST2600_I2CS_SLAVE_MATCH | AST2600_I2CS_WAIT_RX_DMA:
 +	case AST2600_I2CS_SLAVE_MATCH | AST2600_I2CS_RX_DONE | AST2600_I2CS_WAIT_RX_DMA:
++	case AST2600_I2CS_SLAVE_MATCH | AST2600_I2CS_WAIT_RX_DMA:
 +		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_REQUESTED, &value);
 +		slave_rx_len = AST2600_I2C_GET_RX_DMA_LEN(readl(i2c_bus->reg_base +
 +						      AST2600_I2CS_DMA_LEN_STS));
@@ -902,13 +1068,13 @@
 +		       i2c_bus->reg_base + AST2600_I2CS_DMA_LEN);
 +		cmd = SLAVE_TRIGGER_CMD | AST2600_I2CS_RX_DMA_EN;
 +		break;
-+	case AST2600_I2CS_RX_DONE | AST2600_I2CS_STOP:
 +	case AST2600_I2CS_SLAVE_MATCH | AST2600_I2CS_RX_DONE_NAK |
 +			AST2600_I2CS_RX_DONE | AST2600_I2CS_STOP:
 +	case AST2600_I2CS_SLAVE_MATCH | AST2600_I2CS_WAIT_RX_DMA |
 +			AST2600_I2CS_RX_DONE | AST2600_I2CS_STOP:
 +	case AST2600_I2CS_RX_DONE_NAK | AST2600_I2CS_RX_DONE | AST2600_I2CS_STOP:
 +	case AST2600_I2CS_RX_DONE | AST2600_I2CS_WAIT_RX_DMA | AST2600_I2CS_STOP:
++	case AST2600_I2CS_RX_DONE | AST2600_I2CS_STOP:
 +	case AST2600_I2CS_RX_DONE | AST2600_I2CS_WAIT_RX_DMA:
 +	case AST2600_I2CS_SLAVE_MATCH | AST2600_I2CS_RX_DONE | AST2600_I2CS_STOP:
 +		if (sts & AST2600_I2CS_SLAVE_MATCH)
@@ -1004,6 +1170,8 @@
 +		complete(&i2c_bus->cmd_complete);
 +	}
 +
++	i2c_bus->slave = i2c_bus->multi_slave[AST2600_I2CS_GET_SLAVE(sts)];
++
 +	/* Handle i2c slave timeout condition */
 +	if (AST2600_I2CS_INACTIVE_TO & sts) {
 +		/* Reset time out counter */
@@ -1021,7 +1189,7 @@
 +		return;
 +	}
 +
-+	sts &= ~(AST2600_I2CS_PKT_DONE | AST2600_I2CS_PKT_ERROR);
++	sts &= ~(AST2600_I2CS_PKT_DONE | AST2600_I2CS_PKT_ERROR | AST2600_I2CS_ADDR_INDICATE_MASK);
 +
 +	if (sts & AST2600_I2CS_SLAVE_MATCH)
 +		i2c_bus->slave_operate = 1;
@@ -1205,6 +1373,27 @@
 +	u8 byte_data;
 +	u8 value;
 +
++	i2c_bus->slave = i2c_bus->multi_slave[AST2600_I2CS_GET_SLAVE(sts)];
++
++	/* Handle i2c slave timeout condition */
++	if (AST2600_I2CS_INACTIVE_TO & sts) {
++		/* Reset time out counter */
++		u32 ac_timing = readl(i2c_bus->reg_base + AST2600_I2CC_AC_TIMING) &
++				AST2600_I2CC_AC_TIMING_MASK;
++
++		writel(ac_timing, i2c_bus->reg_base + AST2600_I2CC_AC_TIMING);
++		ac_timing |= AST2600_I2CC_TTIMEOUT(i2c_bus->timeout);
++		writel(ac_timing, i2c_bus->reg_base + AST2600_I2CC_AC_TIMING);
++		/* Clear irq and re-send slave trigger command */
++		writel(cmd, i2c_bus->reg_base + AST2600_I2CS_CMD_STS);
++		writel(sts, i2c_bus->reg_base + AST2600_I2CS_ISR);
++		readl(i2c_bus->reg_base + AST2600_I2CS_ISR);
++		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_STOP, &value);
++		return;
++	}
++
++	sts &= ~(AST2600_I2CS_ADDR_INDICATE_MASK);
++
 +	switch (sts) {
 +	case AST2600_I2CS_SLAVE_MATCH | AST2600_I2CS_RX_DONE | AST2600_I2CS_WAIT_RX_DMA:
 +		i2c_slave_event(i2c_bus->slave, I2C_SLAVE_WRITE_REQUESTED, &value);
@@ -1254,7 +1443,7 @@
 +	if (readl(i2c_bus->reg_base + AST2600_I2CM_ISR) & AST2600_I2CM_PKT_DONE)
 +		return 0;
 +
-+	isr &= ~(AST2600_I2CS_ADDR_INDICATE_MASK);
++	isr &= ~(AST2600_I2CS_ADDR_MASK);
 +
 +	if (AST2600_I2CS_PKT_DONE & isr) {
 +		if (i2c_bus->mode == DMA_MODE) {
@@ -1422,8 +1611,7 @@
 +		cmd |= MASTER_TRIGGER_LAST_STOP;
 +	}
 +
-+	writel(AST2600_I2CM_SET_RX_DMA_LEN(xfer_len - 1),
-+	       i2c_bus->reg_base + AST2600_I2CM_DMA_LEN);
++	writel(AST2600_I2CM_SET_RX_DMA_LEN(xfer_len - 1), i2c_bus->reg_base + AST2600_I2CM_DMA_LEN);
 +
 +	if (cmd & AST2600_I2CM_START_CMD) {
 +		cmd |= AST2600_I2CM_PKT_ADDR(msg->addr);
@@ -1533,6 +1721,16 @@
 +		else
 +			return ast2600_i2c_setup_byte_tx(AST2600_I2CM_START_CMD, i2c_bus);
 +	}
++}
++
++static int ast2700_i2c_irq_err_to_errno(u32 irq_status)
++{
++	if (irq_status & AST2700_I2CM_ABNORMAL_ACTION)
++		return -EAGAIN;
++	if (irq_status & (AST2600_I2CM_SDA_DL_TO | AST2600_I2CM_SCL_LOW_TO))
++		return -EBUSY;
++	if (irq_status & (AST2600_I2CM_ABNORMAL))
++		return -EPROTO;
 +
 +	return 0;
 +}
@@ -1659,8 +1857,15 @@
 +		}
 +
 +		if (msg->flags & I2C_M_RECV_LEN) {
-+			u8 recv_len = AST2600_I2CC_GET_RX_BUFF(readl(i2c_bus->reg_base
++			u8 recv_len = 0;
++
++			if (i2c_bus->version == AST2700) {
++				recv_len = AST2700_I2CC_GET_BUFF(readl(i2c_bus->reg_base
++							       + BYTE_DATA_LOG));
++			} else {
++				recv_len = AST2600_I2CC_GET_RX_BUFF(readl(i2c_bus->reg_base
 +							       + AST2600_I2CC_STS_AND_BUFF));
++			}
 +
 +			msg->len = min_t(unsigned int, recv_len, I2C_SMBUS_BLOCK_MAX);
 +			msg->len += ((msg->flags & I2C_CLIENT_PEC) ? 2 : 1);
@@ -1748,14 +1953,21 @@
 +		}
 +	}
 +
-+	i2c_bus->cmd_err = ast2600_i2c_irq_err_to_errno(sts);
-+	if (i2c_bus->cmd_err) {
-+		if (i2c_bus->version == AST2700)
++	/* handle master abnormal condition */
++	if (i2c_bus->version == AST2700) {
++		i2c_bus->cmd_err = ast2700_i2c_irq_err_to_errno(sts);
++		if (i2c_bus->cmd_err) {
 +			writel(sts, i2c_bus->reg_base + AST2600_I2CM_ISR);
-+		else
++			complete(&i2c_bus->cmd_complete);
++			return 1;
++		}
++	} else {
++		i2c_bus->cmd_err = ast2600_i2c_irq_err_to_errno(sts);
++		if (i2c_bus->cmd_err) {
 +			writel(AST2600_I2CM_PKT_DONE, i2c_bus->reg_base + AST2600_I2CM_ISR);
-+		complete(&i2c_bus->cmd_complete);
-+		return 1;
++			complete(&i2c_bus->cmd_complete);
++			return 1;
++		}
 +	}
 +
 +	if (AST2600_I2CM_PKT_DONE & sts) {
@@ -1958,27 +2170,76 @@
 +{
 +	struct ast2600_i2c_bus *i2c_bus = i2c_get_adapdata(client->adapter);
 +	u32 cmd = SLAVE_TRIGGER_CMD;
++	u32 slave_addr = readl(i2c_bus->reg_base + AST2600_I2CS_ADDR_CTRL);
++	u32 ctrl = readl(i2c_bus->reg_base + AST2600_I2CC_FUN_CTRL);
++	bool slave_reg = false;
++	u8 i = 0;
 +
-+	if (i2c_bus->slave)
++	/* check slave client input and slave counts*/
++	if (!client || i2c_bus->slave_attached == AST2600_I2C_SLAVE_COUNT)
++		return -EINVAL;
++
++	/* check duplicate address */
++	for (i = 0; i < AST2600_I2C_SLAVE_COUNT; i++) {
++		if (i2c_bus->multi_slave[i]) {
++			if (i2c_bus->multi_slave[i]->addr == client->addr) {
++				dev_dbg(i2c_bus->dev, "duplicate address [%x] on %d\n", client->addr, i);
++				return -EINVAL;
++			}
++		}
++	}
++
++	/* assign the slave into slave array */
++	for (i = 0; i < AST2600_I2C_SLAVE_COUNT; i++) {
++		if (!i2c_bus->multi_slave[i]) {
++			i2c_bus->multi_slave[i] = client;
++			slave_reg = true;
++			dev_dbg(i2c_bus->dev, "reg [%x] on %d\n", client->addr, i);
++
++			/* set slave addr by index */
++			switch (i) {
++			case 0:
++				slave_addr &= ~(AST2600_I2CS_ADDR1_MASK);
++				slave_addr |= (AST2600_I2CS_ADDR1(client->addr)
++				| AST2600_I2CS_ADDR1_ENABLE);
++				break;
++			case 1:
++				slave_addr &= ~(AST2600_I2CS_ADDR2_MASK);
++				slave_addr |= (AST2600_I2CS_ADDR2(client->addr)
++				| AST2600_I2CS_ADDR2_ENABLE);
++				break;
++			case 2:
++				slave_addr &= ~(AST2600_I2CS_ADDR3_MASK);
++				slave_addr |= (AST2600_I2CS_ADDR3(client->addr)
++				| AST2600_I2CS_ADDR3_ENABLE);
++				break;
++			}
++
++			/* Set slave addr. */
++			writel(slave_addr, i2c_bus->reg_base + AST2600_I2CS_ADDR_CTRL);
++			break;
++		}
++	}
++
++	/* don't reg slave */
++	if (!slave_reg)
 +		return -EINVAL;
 +
 +	dev_dbg(i2c_bus->dev, "slave addr %x\n", client->addr);
 +
-+	writel(0, i2c_bus->reg_base + AST2600_I2CS_ADDR_CTRL);
-+	writel(AST2600_I2CC_SLAVE_EN | readl(i2c_bus->reg_base + AST2600_I2CC_FUN_CTRL),
-+	       i2c_bus->reg_base + AST2600_I2CC_FUN_CTRL);
++	/* Turn on slave mode. */
++	if (!(ctrl & AST2600_I2CC_SLAVE_EN)) {
++		writel(ctrl | AST2600_I2CC_SLAVE_EN,
++		       i2c_bus->reg_base + AST2600_I2CC_FUN_CTRL);
++	}
 +
 +	/* trigger rx buffer */
 +	if (i2c_bus->mode == DMA_MODE) {
 +		cmd |= AST2600_I2CS_RX_DMA_EN;
-+		writel(lower_32_bits(i2c_bus->slave_dma_addr),
-+		       i2c_bus->reg_base + AST2600_I2CS_RX_DMA);
-+		writel(upper_32_bits(i2c_bus->slave_dma_addr),
-+		       i2c_bus->reg_base + AST2600_I2CS_RX_DMA_H);
-+		writel(lower_32_bits(i2c_bus->slave_dma_addr),
-+		       i2c_bus->reg_base + AST2600_I2CS_TX_DMA);
-+		writel(upper_32_bits(i2c_bus->slave_dma_addr),
-+		       i2c_bus->reg_base + AST2600_I2CS_TX_DMA_H);
++		writel(lower_32_bits(i2c_bus->slave_dma_addr), i2c_bus->reg_base + AST2600_I2CS_RX_DMA);
++		writel(upper_32_bits(i2c_bus->slave_dma_addr), i2c_bus->reg_base + AST2600_I2CS_RX_DMA_H);
++		writel(lower_32_bits(i2c_bus->slave_dma_addr), i2c_bus->reg_base + AST2600_I2CS_TX_DMA);
++		writel(upper_32_bits(i2c_bus->slave_dma_addr), i2c_bus->reg_base + AST2600_I2CS_TX_DMA_H);
 +		writel(AST2600_I2CS_SET_RX_DMA_LEN(I2C_SLAVE_MSG_BUF_SIZE),
 +		       i2c_bus->reg_base + AST2600_I2CS_DMA_LEN);
 +	} else if (i2c_bus->mode == BUFF_MODE) {
@@ -1988,25 +2249,60 @@
 +	}
 +
 +	writel(cmd, i2c_bus->reg_base + AST2600_I2CS_CMD_STS);
-+	i2c_bus->slave = client;
-+	/* Set slave addr. */
-+	writel(client->addr | AST2600_I2CS_ADDR1_ENABLE,
-+	       i2c_bus->reg_base + AST2600_I2CS_ADDR_CTRL);
 +
++	i2c_bus->slave_attached++;
 +	return 0;
 +}
 +
 +static int ast2600_i2c_unreg_slave(struct i2c_client *client)
 +{
 +	struct ast2600_i2c_bus *i2c_bus = i2c_get_adapdata(client->adapter);
++	u32 slave_addr = readl(i2c_bus->reg_base + AST2600_I2CS_ADDR_CTRL);
++	bool slave_unreg = false;
++	u8 i = 0;
++
++	/* check slave client input and salve counts*/
++	if (!client || i2c_bus->slave_attached == 0)
++		return -EINVAL;
++
++	/* remove the slave call back from array */
++	for (i = 0; i < AST2600_I2C_SLAVE_COUNT; i++) {
++		if (i2c_bus->multi_slave[i]) {
++			if (i2c_bus->multi_slave[i]->addr == client->addr) {
++				i2c_bus->multi_slave[i] = NULL;
++				slave_unreg = true;
++				dev_dbg(i2c_bus->dev, "un-reg [%x] from %d\n", client->addr, i);
++
++				/* remove slave addr by index */
++				switch (i) {
++				case 0:
++					slave_addr &= ~(AST2600_I2CS_ADDR1_MASK | AST2600_I2CS_ADDR1_ENABLE);
++					break;
++				case 1:
++					slave_addr &= ~(AST2600_I2CS_ADDR2_MASK | AST2600_I2CS_ADDR2_ENABLE);
++					break;
++				case 2:
++					slave_addr &= ~(AST2600_I2CS_ADDR3_MASK | AST2600_I2CS_ADDR3_ENABLE);
++					break;
++				}
++
++				writel(slave_addr, i2c_bus->reg_base + AST2600_I2CS_ADDR_CTRL);
++				break;
++			}
++		}
++	}
++
++	/* don't un-reg slave */
++	if (!slave_unreg)
++		return -EINVAL;
++
++	i2c_bus->slave_attached--;
 +
 +	/* Turn off slave mode. */
-+	writel(~AST2600_I2CC_SLAVE_EN & readl(i2c_bus->reg_base + AST2600_I2CC_FUN_CTRL),
-+	       i2c_bus->reg_base + AST2600_I2CC_FUN_CTRL);
-+	writel(readl(i2c_bus->reg_base + AST2600_I2CS_ADDR_CTRL) & ~AST2600_I2CS_ADDR1_MASK,
-+	       i2c_bus->reg_base + AST2600_I2CS_ADDR_CTRL);
-+
-+	i2c_bus->slave = NULL;
++	if (i2c_bus->slave_attached == 0x0) {
++		writel(~AST2600_I2CC_SLAVE_EN & readl(i2c_bus->reg_base + AST2600_I2CC_FUN_CTRL),
++		       i2c_bus->reg_base + AST2600_I2CC_FUN_CTRL);
++	}
 +
 +	return 0;
 +}
@@ -2030,6 +2326,7 @@
 +{
 +	struct device *dev = &pdev->dev;
 +	struct ast2600_i2c_bus *i2c_bus;
++	const char *xfer_mode;
 +	struct resource *res;
 +	u32 global_ctrl;
 +	int ret;
@@ -2058,33 +2355,40 @@
 +	regmap_read(i2c_bus->global_regs, AST2600_I2CG_CTRL, &global_ctrl);
 +	if ((global_ctrl & AST2600_GLOBAL_INIT) != AST2600_GLOBAL_INIT) {
 +		regmap_write(i2c_bus->global_regs, AST2600_I2CG_CTRL, AST2600_GLOBAL_INIT);
-+		regmap_write(i2c_bus->global_regs, AST2600_I2CG_CLK_DIV_CTRL, I2CCG_DIV_CTRL);
++		if (i2c_bus->version == AST2600)
++			regmap_write(i2c_bus->global_regs, AST2600_I2CG_CLK_DIV_CTRL, AST2600_I2CCG_DIV_CTRL);
++		else
++			regmap_write(i2c_bus->global_regs, AST2600_I2CG_CLK_DIV_CTRL, AST2700_I2CCG_DIV_CTRL);
 +	}
 +
 +#if IS_ENABLED(CONFIG_I2C_SLAVE)
 +	i2c_bus->slave_operate = 0;
++	i2c_bus->slave_attached = 0;
++	for (int i = 0; i < AST2600_I2C_SLAVE_COUNT; i++)
++		i2c_bus->multi_slave[i] = NULL;
 +#endif
 +	i2c_bus->dev = dev;
-+	if (i2c_bus->version == AST2600)
-+		i2c_bus->mode = BUFF_MODE;
-+	else
-+		i2c_bus->mode = DMA_MODE;
-+
-+	if (device_property_read_bool(dev, "aspeed,enable-byte"))
-+		i2c_bus->mode = BYTE_MODE;
-+
-+	if (device_property_read_bool(dev, "aspeed,enable-buff"))
++	if (i2c_bus->version == AST2600) {
 +		i2c_bus->mode = BUFF_MODE;
 +
-+	if (device_property_read_bool(dev, "aspeed,enable-dma"))
-+		i2c_bus->mode = DMA_MODE;
++		if (!device_property_read_string(dev, "aspeed,transfer-mode", &xfer_mode)) {
++			if (!strcmp(xfer_mode, "dma"))
++				i2c_bus->mode = DMA_MODE;
++			else if (!strcmp(xfer_mode, "byte"))
++				i2c_bus->mode = BYTE_MODE;
++			else
++				i2c_bus->mode = BUFF_MODE;
++		}
 +
-+	if (i2c_bus->mode == BUFF_MODE) {
-+		i2c_bus->buf_base = devm_platform_get_and_ioremap_resource(pdev, 1, &res);
-+		if (IS_ERR(i2c_bus->buf_base))
-+			i2c_bus->mode = BYTE_MODE;
-+		else
-+			i2c_bus->buf_size = resource_size(res) / 2;
++		if (i2c_bus->mode == BUFF_MODE) {
++			i2c_bus->buf_base = devm_platform_get_and_ioremap_resource(pdev, 1, &res);
++			if (IS_ERR(i2c_bus->buf_base))
++				i2c_bus->mode = BYTE_MODE;
++			else
++				i2c_bus->buf_size = resource_size(res) / 2;
++		}
++	} else {
++		i2c_bus->mode = DMA_MODE;
 +	}
 +
 +	/*
@@ -2125,9 +2429,8 @@
 +	i2c_bus->adap.algo_data = i2c_bus;
 +	strscpy(i2c_bus->adap.name, pdev->name, sizeof(i2c_bus->adap.name));
 +	i2c_set_adapdata(&i2c_bus->adap, i2c_bus);
-+#ifdef CONFIG_64BIT
 +	dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
-+#endif
++
 +	ast2600_i2c_init(i2c_bus);
 +
 +	ret = devm_request_irq(dev, i2c_bus->irq, ast2600_i2c_bus_irq, 0,
@@ -2154,7 +2457,7 @@
 +	if (ret)
 +		return ret;
 +
-+	dev_info(dev, "%s [%d]: adapter [%d khz] mode [%d] version [%d]\n",
++	dev_info(dev, "%s [%d]: adapter [%d KHz] mode [%d] version [%d]\n",
 +		 dev->of_node->name, i2c_bus->adap.nr, i2c_bus->timing_info.bus_freq_hz / 1000,
 +		 i2c_bus->mode, i2c_bus->version);
 +
@@ -2172,19 +2475,19 @@
 +	return 0;
 +}
 +
-+static const struct of_device_id aspeed_i2c_bus_of_table[] = {
++static const struct of_device_id ast2600_i2c_bus_of_table[] = {
 +	{ .compatible = "aspeed,ast2600-i2cv2",  .data = (const void *)AST2600, },
 +	{ .compatible = "aspeed,ast2700-i2c",  .data = (const void *)AST2700, },
 +	{}
 +};
-+MODULE_DEVICE_TABLE(of, aspeed_i2c_bus_of_table);
++MODULE_DEVICE_TABLE(of, ast2600_i2c_bus_of_table);
 +
 +static struct platform_driver ast2600_i2c_bus_driver = {
 +	.probe = ast2600_i2c_probe,
 +	.remove = ast2600_i2c_remove,
 +	.driver = {
 +		.name = KBUILD_MODNAME,
-+		.of_match_table = aspeed_i2c_bus_of_table,
++		.of_match_table = ast2600_i2c_bus_of_table,
 +	},
 +};
 +
@@ -2194,83 +2497,10 @@
 +MODULE_DESCRIPTION("ASPEED AST2600 I2C Controller Driver");
 +MODULE_LICENSE("GPL");
 diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
-index 1e873ff0a..9cb03d2a1 100644
+index 943f0021d..9cb03d2a1 100644
 --- a/drivers/i2c/i2c-core-base.c
 +++ b/drivers/i2c/i2c-core-base.c
-@@ -16,6 +16,7 @@
- #include <linux/acpi.h>
- #include <linux/clk/clk-conf.h>
- #include <linux/completion.h>
-+#include <linux/debugfs.h>
- #include <linux/delay.h>
- #include <linux/err.h>
- #include <linux/errno.h>
-@@ -67,6 +68,8 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver);
- static DEFINE_STATIC_KEY_FALSE(i2c_trace_msg_key);
- static bool is_registered;
- 
-+static struct dentry *i2c_debugfs_root;
-+
- int i2c_transfer_trace_reg(void)
- {
- 	static_branch_inc(&i2c_trace_msg_key);
-@@ -912,6 +915,27 @@ int i2c_dev_irq_from_resources(const struct resource *resources,
- 	return 0;
- }
- 
-+/*
-+ * Serialize device instantiation in case it can be instantiated explicitly
-+ * and by auto-detection
-+ */
-+static int i2c_lock_addr(struct i2c_adapter *adap, unsigned short addr,
-+			 unsigned short flags)
-+{
-+	if (!(flags & I2C_CLIENT_TEN) &&
-+	    test_and_set_bit(addr, adap->addrs_in_instantiation))
-+		return -EBUSY;
-+
-+	return 0;
-+}
-+
-+static void i2c_unlock_addr(struct i2c_adapter *adap, unsigned short addr,
-+			    unsigned short flags)
-+{
-+	if (!(flags & I2C_CLIENT_TEN))
-+		clear_bit(addr, adap->addrs_in_instantiation);
-+}
-+
- /**
-  * i2c_new_client_device - instantiate an i2c device
-  * @adap: the adapter managing the device
-@@ -959,6 +983,10 @@ i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *inf
- 		goto out_err_silent;
- 	}
- 
-+	status = i2c_lock_addr(adap, client->addr, client->flags);
-+	if (status)
-+		goto out_err_silent;
-+
- 	/* Check for address business */
- 	status = i2c_check_addr_busy(adap, i2c_encode_flags_to_addr(client));
- 	if (status)
-@@ -990,6 +1018,8 @@ i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *inf
- 	dev_dbg(&adap->dev, "client [%s] registered with bus id %s\n",
- 		client->name, dev_name(&client->dev));
- 
-+	i2c_unlock_addr(adap, client->addr, client->flags);
-+
- 	return client;
- 
- out_remove_swnode:
-@@ -1001,6 +1031,7 @@ i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *inf
- 	dev_err(&adap->dev,
- 		"Failed to register i2c client %s at 0x%02x (%d)\n",
- 		client->name, client->addr, status);
-+	i2c_unlock_addr(adap, client->addr, client->flags);
- out_err_silent:
- 	if (need_put)
- 		put_device(&client->dev);
-@@ -1401,6 +1432,41 @@ static const struct i2c_lock_operations i2c_adapter_lock_ops = {
+@@ -1432,6 +1432,41 @@ static const struct i2c_lock_operations i2c_adapter_lock_ops = {
  	.unlock_bus =  i2c_adapter_unlock_bus,
  };
  
@@ -2312,7 +2542,7 @@
  static void i2c_host_notify_irq_teardown(struct i2c_adapter *adap)
  {
  	struct irq_domain *domain = adap->host_notify_domain;
-@@ -1496,6 +1562,9 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
+@@ -1527,6 +1562,9 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
  	if (!adap->lock_ops)
  		adap->lock_ops = &i2c_adapter_lock_ops;
  
@@ -2322,49 +2552,6 @@
  	adap->locked_flags = 0;
  	rt_mutex_init(&adap->bus_lock);
  	rt_mutex_init(&adap->mux_lock);
-@@ -1523,6 +1592,8 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
- 		goto out_list;
- 	}
- 
-+	adap->debugfs = debugfs_create_dir(dev_name(&adap->dev), i2c_debugfs_root);
-+
- 	res = i2c_setup_smbus_alert(adap);
- 	if (res)
- 		goto out_reg;
-@@ -1562,6 +1633,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
- 	return 0;
- 
- out_reg:
-+	debugfs_remove_recursive(adap->debugfs);
- 	init_completion(&adap->dev_released);
- 	device_unregister(&adap->dev);
- 	wait_for_completion(&adap->dev_released);
-@@ -1763,6 +1835,8 @@ void i2c_del_adapter(struct i2c_adapter *adap)
- 
- 	i2c_host_notify_irq_teardown(adap);
- 
-+	debugfs_remove_recursive(adap->debugfs);
-+
- 	/* wait until all references to the device are gone
- 	 *
- 	 * FIXME: This is old code and should ideally be replaced by an
-@@ -2060,6 +2134,8 @@ static int __init i2c_init(void)
- 
- 	is_registered = true;
- 
-+	i2c_debugfs_root = debugfs_create_dir("i2c", NULL);
-+
- #ifdef CONFIG_I2C_COMPAT
- 	i2c_adapter_compat_class = class_compat_register("i2c-adapter");
- 	if (!i2c_adapter_compat_class) {
-@@ -2098,6 +2174,7 @@ static void __exit i2c_exit(void)
- #ifdef CONFIG_I2C_COMPAT
- 	class_compat_unregister(i2c_adapter_compat_class);
- #endif
-+	debugfs_remove_recursive(i2c_debugfs_root);
- 	bus_unregister(&i2c_bus_type);
- 	tracepoint_synchronize_unregister();
- }
 diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
 index 57ff09f18..3f1302bd0 100644
 --- a/drivers/i2c/i2c-mux.c
@@ -2441,7 +2628,7 @@
  	if (i2c_mux_parent_classes(parent) & class & ~I2C_CLASS_DEPRECATED)
  		dev_err(&parent->dev,
 diff --git a/include/linux/i2c.h b/include/linux/i2c.h
-index 32cf5708d..5a0c667ca 100644
+index a3166100f..5a0c667ca 100644
 --- a/include/linux/i2c.h
 +++ b/include/linux/i2c.h
 @@ -582,6 +582,26 @@ struct i2c_lock_operations {
@@ -2479,19 +2666,7 @@
  	struct rt_mutex bus_lock;
  	struct rt_mutex mux_lock;
  
-@@ -746,6 +767,11 @@ struct i2c_adapter {
- 
- 	struct irq_domain *host_notify_domain;
- 	struct regulator *bus_regulator;
-+
-+	struct dentry *debugfs;
-+
-+	/* 7bit address space */
-+	DECLARE_BITMAP(addrs_in_instantiation, 1 << 7);
- };
- #define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
- 
-@@ -816,6 +842,27 @@ i2c_unlock_bus(struct i2c_adapter *adapter, unsigned int flags)
+@@ -821,6 +842,27 @@ i2c_unlock_bus(struct i2c_adapter *adapter, unsigned int flags)
  	adapter->lock_ops->unlock_bus(adapter, flags);
  }
  
diff --git a/recipes-kernel/linux/files/0013-Add-emmc-driver-for-ast2700.patch b/recipes-kernel/linux/files/0013-Add-emmc-driver-for-ast2700.patch
index 4a415b5..dc1b8d8 100644
--- a/recipes-kernel/linux/files/0013-Add-emmc-driver-for-ast2700.patch
+++ b/recipes-kernel/linux/files/0013-Add-emmc-driver-for-ast2700.patch
@@ -1,67 +1,26 @@
-From 4eab4cebedad705f3fc49ab06e327881623d0112 Mon Sep 17 00:00:00 2001
-From: "yung-sheng.huang" <yung-sheng.huang@fii-na.corp-partner.google.com>
-Date: Tue, 15 Apr 2025 16:52:58 +0800
-Subject: [PATCH 13/26] Add emmc driver for ast2700
+From 5561c72256c1893b5ca6792de9dc0c9b7f6a9ccf Mon Sep 17 00:00:00 2001
+From: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+Date: Thu, 17 Jul 2025 08:45:59 +0800
+Subject: [PATCH] Add emmc driver for ast2700
 
-This is base on aspeed SDK 9.06.
+This is base on aspeed SDK 9.07.
 
 Source:
 AspeedTech-BMC github:
 https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/
-(cherry picked from commit v00.06.06)
+(cherry picked from commit v00.06.07)
 
-Signed-off-by: yung-sheng.huang <yung-sheng.huang@fii-na.corp-partner.google.com>
+Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
 ---
- drivers/mmc/core/bus.c             |   2 +
- drivers/mmc/core/card.h            |   7 +
- drivers/mmc/core/core.c            |   4 +-
+ drivers/mmc/core/core.c            |   1 -
  drivers/mmc/core/host.c            |  10 +-
- drivers/mmc/core/sd.c              |   2 +-
- drivers/mmc/core/sdio.c            |   2 +
  drivers/mmc/host/sdhci-of-aspeed.c | 458 +++++++++++++----------------
  drivers/mmc/host/sdhci-pltfm.c     |   2 +
- include/linux/mmc/card.h           |   1 +
  include/linux/mmc/host.h           |   2 +
- 10 files changed, 235 insertions(+), 255 deletions(-)
+ 5 files changed, 219 insertions(+), 254 deletions(-)
 
-diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
-index 0af96548e..74bc42205 100644
---- a/drivers/mmc/core/bus.c
-+++ b/drivers/mmc/core/bus.c
-@@ -149,6 +149,8 @@ static void mmc_bus_shutdown(struct device *dev)
- 	if (dev->driver && drv->shutdown)
- 		drv->shutdown(card);
- 
-+	__mmc_stop_host(host);
-+
- 	if (host->bus_ops->shutdown) {
- 		ret = host->bus_ops->shutdown(host);
- 		if (ret)
-diff --git a/drivers/mmc/core/card.h b/drivers/mmc/core/card.h
-index b7754a1b8..8476754b1 100644
---- a/drivers/mmc/core/card.h
-+++ b/drivers/mmc/core/card.h
-@@ -82,6 +82,7 @@ struct mmc_fixup {
- #define CID_MANFID_SANDISK_SD   0x3
- #define CID_MANFID_ATP          0x9
- #define CID_MANFID_TOSHIBA      0x11
-+#define CID_MANFID_GIGASTONE    0x12
- #define CID_MANFID_MICRON       0x13
- #define CID_MANFID_SAMSUNG      0x15
- #define CID_MANFID_APACER       0x27
-@@ -284,4 +285,10 @@ static inline int mmc_card_broken_cache_flush(const struct mmc_card *c)
- {
- 	return c->quirks & MMC_QUIRK_BROKEN_CACHE_FLUSH;
- }
-+
-+static inline int mmc_card_broken_sd_poweroff_notify(const struct mmc_card *c)
-+{
-+	return c->quirks & MMC_QUIRK_BROKEN_SD_POWEROFF_NOTIFY;
-+}
-+
- #endif
 diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
-index a8c17b4cd..35e05aa6b 100644
+index 39b5846db..35e05aa6b 100644
 --- a/drivers/mmc/core/core.c
 +++ b/drivers/mmc/core/core.c
 @@ -991,7 +991,6 @@ void mmc_set_initial_state(struct mmc_host *host)
@@ -72,16 +31,6 @@
  	host->ios.enhanced_strobe = false;
  
  	/*
-@@ -2296,6 +2295,9 @@ void mmc_start_host(struct mmc_host *host)
- 
- void __mmc_stop_host(struct mmc_host *host)
- {
-+	if (host->rescan_disable)
-+		return;
-+
- 	if (host->slot.cd_irq >= 0) {
- 		mmc_gpio_set_cd_wake(host, false);
- 		disable_irq(host->slot.cd_irq);
 diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
 index cf396e8f3..c8538be5a 100644
 --- a/drivers/mmc/core/host.c
@@ -107,32 +56,6 @@
  	}
  }
  
-diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
-index 240469a88..f02c3e5eb 100644
---- a/drivers/mmc/core/sd.c
-+++ b/drivers/mmc/core/sd.c
-@@ -1118,7 +1118,7 @@ static int sd_parse_ext_reg_power(struct mmc_card *card, u8 fno, u8 page,
- 	card->ext_power.rev = reg_buf[0] & 0xf;
- 
- 	/* Power Off Notification support at bit 4. */
--	if (reg_buf[1] & BIT(4))
-+	if ((reg_buf[1] & BIT(4)) && !mmc_card_broken_sd_poweroff_notify(card))
- 		card->ext_power.feature_support |= SD_EXT_POWER_OFF_NOTIFY;
- 
- 	/* Power Sustenance support at bit 5. */
-diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
-index 5914516df..cb87e8273 100644
---- a/drivers/mmc/core/sdio.c
-+++ b/drivers/mmc/core/sdio.c
-@@ -458,6 +458,8 @@ static unsigned mmc_sdio_get_max_clock(struct mmc_card *card)
- 	if (mmc_card_sd_combo(card))
- 		max_dtr = min(max_dtr, mmc_sd_get_max_clock(card));
- 
-+	max_dtr = min_not_zero(max_dtr, card->quirk_max_rate);
-+
- 	return max_dtr;
- }
- 
 diff --git a/drivers/mmc/host/sdhci-of-aspeed.c b/drivers/mmc/host/sdhci-of-aspeed.c
 index 8379a0620..e049309a9 100644
 --- a/drivers/mmc/host/sdhci-of-aspeed.c
@@ -793,18 +716,6 @@
  }
  EXPORT_SYMBOL_GPL(sdhci_get_property);
  
-diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
-index 7b12eebc5..afa575e36 100644
---- a/include/linux/mmc/card.h
-+++ b/include/linux/mmc/card.h
-@@ -296,6 +296,7 @@ struct mmc_card {
- #define MMC_QUIRK_BROKEN_SD_DISCARD	(1<<14)	/* Disable broken SD discard support */
- #define MMC_QUIRK_BROKEN_SD_CACHE	(1<<15)	/* Disable broken SD cache support */
- #define MMC_QUIRK_BROKEN_CACHE_FLUSH	(1<<16)	/* Don't flush cache until the write has occurred */
-+#define MMC_QUIRK_BROKEN_SD_POWEROFF_NOTIFY	(1<<17) /* Disable broken SD poweroff notify support */
- 
- 	bool			written_flag;	/* Indicates eMMC has been written since power on */
- 	bool			reenable_cmdq;	/* Re-enable Command Queue */
 diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
 index 62a6847a3..9836e3923 100644
 --- a/include/linux/mmc/host.h
diff --git a/recipes-kernel/linux/files/0014-Add-jtag-driver-for-ast2700.patch b/recipes-kernel/linux/files/0014-Add-jtag-driver-for-ast2700.patch
index 9703c74..9fb32ae 100644
--- a/recipes-kernel/linux/files/0014-Add-jtag-driver-for-ast2700.patch
+++ b/recipes-kernel/linux/files/0014-Add-jtag-driver-for-ast2700.patch
@@ -1,16 +1,16 @@
-From 5d5ba08baa4e227b9808813bcb3b754f05e5b5fe Mon Sep 17 00:00:00 2001
-From: "yung-sheng.huang" <yung-sheng.huang@fii-na.corp-partner.google.com>
-Date: Tue, 15 Apr 2025 17:04:30 +0800
-Subject: [PATCH 14/26] Add jtag driver for ast2700
+From d6bbc7de057492c220221ebc375721ebc6144d3f Mon Sep 17 00:00:00 2001
+From: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+Date: Thu, 17 Jul 2025 08:55:59 +0800
+Subject: [PATCH] Add jtag driver for ast2700
 
-This is base on aspeed SDK 9.06.
+This is base on aspeed SDK 9.07.
 
 Source:
 AspeedTech-BMC github:
 https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/
-(cherry picked from commit v00.06.06)
+(cherry picked from commit v00.06.07)
 
-Signed-off-by: yung-sheng.huang <yung-sheng.huang@fii-na.corp-partner.google.com>
+Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
 ---
  drivers/Kconfig            |    1 +
  drivers/Makefile           |    1 +
diff --git a/recipes-kernel/linux/files/0015-Add-ADC-driver-for-ast2700.patch b/recipes-kernel/linux/files/0015-Add-ADC-driver-for-ast2700.patch
index 0ed44b4..2fb0c3e 100644
--- a/recipes-kernel/linux/files/0015-Add-ADC-driver-for-ast2700.patch
+++ b/recipes-kernel/linux/files/0015-Add-ADC-driver-for-ast2700.patch
@@ -1,16 +1,16 @@
-From ce68cf9ddec514eebca69af3136143f1eeb54488 Mon Sep 17 00:00:00 2001
-From: "yung-sheng.huang" <yung-sheng.huang@fii-na.corp-partner.google.com>
-Date: Tue, 15 Apr 2025 17:07:29 +0800
-Subject: [PATCH 15/26] Add ADC driver for ast2700
+From 892f48a22ae091ccf61b10e0d803634d27673f2e Mon Sep 17 00:00:00 2001
+From: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+Date: Thu, 17 Jul 2025 08:58:05 +0800
+Subject: [PATCH] Add ADC driver for ast2700
 
-This is base on aspeed SDK 9.06.
+This is base on aspeed SDK 9.07.
 
 Source:
 AspeedTech-BMC github:
 https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/
-(cherry picked from commit v00.06.06)
+(cherry picked from commit v00.06.07)
 
-Signed-off-by: yung-sheng.huang <yung-sheng.huang@fii-na.corp-partner.google.com>
+Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
 ---
  drivers/iio/adc/aspeed_adc.c | 302 +++++++++++++++++++++++++++++++----
  1 file changed, 271 insertions(+), 31 deletions(-)
diff --git a/recipes-kernel/linux/files/0016-Add-RTC-driver-for-ast2700.patch b/recipes-kernel/linux/files/0016-Add-RTC-driver-for-ast2700.patch
index 2f283e8..40b3f91 100644
--- a/recipes-kernel/linux/files/0016-Add-RTC-driver-for-ast2700.patch
+++ b/recipes-kernel/linux/files/0016-Add-RTC-driver-for-ast2700.patch
@@ -1,16 +1,16 @@
-From ca306a4846057cb72e9abc64cb301995405802e7 Mon Sep 17 00:00:00 2001
-From: "yung-sheng.huang" <yung-sheng.huang@fii-na.corp-partner.google.com>
-Date: Tue, 15 Apr 2025 17:10:03 +0800
-Subject: [PATCH 16/26] Add RTC driver for ast2700
+From 50bcb28f34f613bc75aafd68ce8d4b7262303346 Mon Sep 17 00:00:00 2001
+From: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+Date: Thu, 17 Jul 2025 09:01:18 +0800
+Subject: [PATCH] Add RTC driver for ast2700
 
-This is base on aspeed SDK 9.06.
+This is base on aspeed SDK 9.07.
 
 Source:
 AspeedTech-BMC github:
 https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/
-(cherry picked from commit v00.06.06)
+(cherry picked from commit v00.06.07)
 
-Signed-off-by: yung-sheng.huang <yung-sheng.huang@fii-na.corp-partner.google.com>
+Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
 ---
  drivers/rtc/rtc-aspeed.c | 237 +++++++++++++++++++++++++++++++++++++--
  1 file changed, 230 insertions(+), 7 deletions(-)
diff --git a/recipes-kernel/linux/files/0017-Add-i3c-driver-for-ast2700.patch b/recipes-kernel/linux/files/0017-Add-i3c-driver-for-ast2700.patch
index b0bd775..c754102 100644
--- a/recipes-kernel/linux/files/0017-Add-i3c-driver-for-ast2700.patch
+++ b/recipes-kernel/linux/files/0017-Add-i3c-driver-for-ast2700.patch
@@ -1,63 +1,59 @@
-From 27f172f93a5e950f4266aee9cada5ed5f2482094 Mon Sep 17 00:00:00 2001
-From: "yung-sheng.huang" <yung-sheng.huang@fii-na.corp-partner.google.com>
-Date: Wed, 16 Apr 2025 08:01:35 +0800
-Subject: [PATCH 17/26] Add i3c driver for ast2700
+From c00ef29796c97b0789c22bf5e9bb06e5f09d0d39 Mon Sep 17 00:00:00 2001
+From: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+Date: Thu, 17 Jul 2025 09:29:25 +0800
+Subject: [PATCH] Add i3c driver for ast2700
 
-This is base on aspeed SDK 9.06.
+This is base on aspeed SDK 9.07.
 
 Source:
 AspeedTech-BMC github:
 https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/
-(cherry picked from commit v00.06.06)
+(cherry picked from commit v00.06.07)
 
-Signed-off-by: yung-sheng.huang <yung-sheng.huang@fii-na.corp-partner.google.com>
+Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
 ---
  drivers/i3c/Kconfig                           |   23 +
  drivers/i3c/Makefile                          |    3 +
- drivers/i3c/device.c                          |  382 ++++
- drivers/i3c/i3c-mux-imx3102.c                 |  227 +++
- drivers/i3c/i3cdev.c                          |  428 +++++
+ drivers/i3c/device.c                          |  382 ++++++
+ drivers/i3c/i3c-mux-imx3102.c                 |  227 ++++
+ drivers/i3c/i3cdev.c                          |  428 +++++++
  drivers/i3c/internals.h                       |   38 +-
- drivers/i3c/master.c                          | 1348 ++++++++++++--
- drivers/i3c/master/ast2600-i3c-master.c       |  609 +++++++
- drivers/i3c/master/dw-i3c-master.c            | 1555 +++++++++++++++--
- drivers/i3c/master/dw-i3c-master.h            |   60 +-
- drivers/i3c/master/i3c-master-cdns.c          |    3 +-
+ drivers/i3c/master.c                          | 1121 +++++++++++++++--
+ drivers/i3c/master/ast2600-i3c-master.c       |  609 +++++++++
  drivers/i3c/master/mipi-i3c-hci/cmd.h         |   85 +-
  drivers/i3c/master/mipi-i3c-hci/cmd_v1.c      |  198 ++-
  drivers/i3c/master/mipi-i3c-hci/cmd_v2.c      |    3 +-
- drivers/i3c/master/mipi-i3c-hci/core.c        |  813 ++++++++-
+ drivers/i3c/master/mipi-i3c-hci/core.c        |  847 ++++++++++++-
  drivers/i3c/master/mipi-i3c-hci/dat.h         |    4 +
  drivers/i3c/master/mipi-i3c-hci/dat_v1.c      |   40 +-
- drivers/i3c/master/mipi-i3c-hci/dma.c         |  290 ++-
+ drivers/i3c/master/mipi-i3c-hci/dma.c         |  308 +++--
  drivers/i3c/master/mipi-i3c-hci/ext_caps.c    |   42 +
  drivers/i3c/master/mipi-i3c-hci/ext_caps.h    |    1 +
- drivers/i3c/master/mipi-i3c-hci/hci.h         |   19 +
+ drivers/i3c/master/mipi-i3c-hci/hci.h         |   21 +
  drivers/i3c/master/mipi-i3c-hci/ibi.h         |    4 +
- drivers/i3c/master/mipi-i3c-hci/pio.c         |  271 ++-
- .../i3c/master/mipi-i3c-hci/vendor_aspeed.h   |  408 +++++
- drivers/i3c/master/svc-i3c-master.c           |  147 +-
+ drivers/i3c/master/mipi-i3c-hci/pio.c         |  271 +++-
+ .../i3c/master/mipi-i3c-hci/vendor_aspeed.h   |  408 ++++++
  drivers/i3c/mctp/Kconfig                      |   23 +
  drivers/i3c/mctp/Makefile                     |    3 +
- drivers/i3c/mctp/i3c-mctp.c                   |  697 ++++++++
- drivers/i3c/mctp/i3c-target-mctp.c            |  485 +++++
+ drivers/i3c/mctp/i3c-mctp.c                   |  697 ++++++++++
+ drivers/i3c/mctp/i3c-target-mctp.c            |  485 +++++++
  include/linux/i3c/ccc.h                       |   21 +
  include/linux/i3c/device.h                    |   95 +-
- include/linux/i3c/master.h                    |   93 +-
+ include/linux/i3c/master.h                    |   60 +-
  include/linux/i3c/mctp/i3c-mctp.h             |   50 +
  include/linux/i3c/target.h                    |   30 +
  include/uapi/linux/i3c/i3cdev.h               |   37 +
- 35 files changed, 8020 insertions(+), 515 deletions(-)
- create mode 100644 drivers/i3c/i3c-mux-imx3102.c
- create mode 100644 drivers/i3c/i3cdev.c
- create mode 100644 drivers/i3c/master/mipi-i3c-hci/vendor_aspeed.h
- create mode 100644 drivers/i3c/mctp/Kconfig
- create mode 100644 drivers/i3c/mctp/Makefile
- create mode 100644 drivers/i3c/mctp/i3c-mctp.c
- create mode 100644 drivers/i3c/mctp/i3c-target-mctp.c
- create mode 100644 include/linux/i3c/mctp/i3c-mctp.h
- create mode 100644 include/linux/i3c/target.h
- create mode 100644 include/uapi/linux/i3c/i3cdev.h
+ 31 files changed, 6306 insertions(+), 258 deletions(-)
+ create mode 100755 drivers/i3c/i3c-mux-imx3102.c
+ create mode 100755 drivers/i3c/i3cdev.c
+ create mode 100755 drivers/i3c/master/mipi-i3c-hci/vendor_aspeed.h
+ create mode 100755 drivers/i3c/mctp/Kconfig
+ create mode 100755 drivers/i3c/mctp/Makefile
+ create mode 100755 drivers/i3c/mctp/i3c-mctp.c
+ create mode 100755 drivers/i3c/mctp/i3c-target-mctp.c
+ create mode 100755 include/linux/i3c/mctp/i3c-mctp.h
+ create mode 100755 include/linux/i3c/target.h
+ create mode 100755 include/uapi/linux/i3c/i3cdev.h
 
 diff --git a/drivers/i3c/Kconfig b/drivers/i3c/Kconfig
 index 30a441506..2fd8deaf7 100644
@@ -516,7 +512,7 @@
 +}
 +EXPORT_SYMBOL_GPL(i3c_device_dbgopcode_rd_ccc);
 diff --git a/drivers/i3c/i3c-mux-imx3102.c b/drivers/i3c/i3c-mux-imx3102.c
-new file mode 100644
+new file mode 100755
 index 000000000..e134aea93
 --- /dev/null
 +++ b/drivers/i3c/i3c-mux-imx3102.c
@@ -749,7 +745,7 @@
 +MODULE_DESCRIPTION("I3C IMX3102 multiplexer driver");
 +MODULE_LICENSE("GPL");
 diff --git a/drivers/i3c/i3cdev.c b/drivers/i3c/i3cdev.c
-new file mode 100644
+new file mode 100755
 index 000000000..fa96327d5
 --- /dev/null
 +++ b/drivers/i3c/i3cdev.c
@@ -1244,7 +1240,7 @@
 +			     struct i3c_device_info *info, u16 write_len);
  #endif /* I3C_INTERNAL_H */
 diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
-index 0e9ff5500..eaa9ccd69 100644
+index 33254bc33..50be17aa0 100644
 --- a/drivers/i3c/master.c
 +++ b/drivers/i3c/master.c
 @@ -13,15 +13,18 @@
@@ -1348,7 +1344,7 @@
  
 -		ret = sprintf(buf + offset, offset ? " %s" : "%s",
 -			      hdrcap_strings[mode]);
-+		ret = sysfs_emit(buf + offset, offset ? " %s" : "%s", hdrcap_strings[mode]);
++		ret = sysfs_emit_at(buf, offset, offset ? " %s" : "%s", hdrcap_strings[mode]);
  		if (ret < 0)
  			goto out;
  
@@ -1356,7 +1352,7 @@
  	}
  
 -	ret = sprintf(buf + offset, "\n");
-+	ret = sysfs_emit(buf + offset, "\n");
++	ret = sysfs_emit_at(buf, offset, "\n");
  	if (ret < 0)
  		goto out;
  
@@ -1456,17 +1452,7 @@
  	NULL,
  };
  ATTRIBUTE_GROUPS(i3c_device);
-@@ -280,7 +342,8 @@ static int i3c_device_uevent(const struct device *dev, struct kobj_uevent_env *e
- 	struct i3c_device_info devinfo;
- 	u16 manuf, part, ext;
- 
--	i3c_device_get_info(i3cdev, &devinfo);
-+	if (i3cdev->desc)
-+		devinfo = i3cdev->desc->info;
- 	manuf = I3C_PID_MANUF_ID(devinfo.pid);
- 	part = I3C_PID_PART_ID(devinfo.pid);
- 	ext = I3C_PID_EXTRA_INFO(devinfo.pid);
-@@ -299,19 +362,31 @@ static const struct device_type i3c_device_type = {
+@@ -300,19 +362,31 @@ static const struct device_type i3c_device_type = {
  	.uevent = i3c_device_uevent,
  };
  
@@ -1501,7 +1487,7 @@
  	return 0;
  }
  
-@@ -331,21 +406,23 @@ static void i3c_device_remove(struct device *dev)
+@@ -332,15 +406,17 @@ static void i3c_device_remove(struct device *dev)
  	if (driver->remove)
  		driver->remove(i3cdev);
  
@@ -1520,103 +1506,8 @@
 +EXPORT_SYMBOL_GPL(i3c_bus_type);
  
  static enum i3c_addr_slot_status
--i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr)
-+i3c_bus_get_addr_slot_status_mask(struct i3c_bus *bus, u16 addr, u32 mask)
- {
- 	unsigned long status;
--	int bitpos = addr * 2;
-+	int bitpos = addr * I3C_ADDR_SLOT_STATUS_BITS;
- 
- 	if (addr > I2C_MAX_ADDR)
- 		return I3C_ADDR_SLOT_RSVD;
-@@ -353,22 +430,33 @@ i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr)
- 	status = bus->addrslots[bitpos / BITS_PER_LONG];
- 	status >>= bitpos % BITS_PER_LONG;
- 
--	return status & I3C_ADDR_SLOT_STATUS_MASK;
-+	return status & mask;
- }
- 
--static void i3c_bus_set_addr_slot_status(struct i3c_bus *bus, u16 addr,
--					 enum i3c_addr_slot_status status)
-+static enum i3c_addr_slot_status
-+i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr)
-+{
-+	return i3c_bus_get_addr_slot_status_mask(bus, addr, I3C_ADDR_SLOT_STATUS_MASK);
-+}
-+
-+static void i3c_bus_set_addr_slot_status_mask(struct i3c_bus *bus, u16 addr,
-+					      enum i3c_addr_slot_status status, u32 mask)
- {
--	int bitpos = addr * 2;
-+	int bitpos = addr * I3C_ADDR_SLOT_STATUS_BITS;
- 	unsigned long *ptr;
- 
- 	if (addr > I2C_MAX_ADDR)
- 		return;
- 
- 	ptr = bus->addrslots + (bitpos / BITS_PER_LONG);
--	*ptr &= ~((unsigned long)I3C_ADDR_SLOT_STATUS_MASK <<
--						(bitpos % BITS_PER_LONG));
--	*ptr |= (unsigned long)status << (bitpos % BITS_PER_LONG);
-+	*ptr &= ~((unsigned long)mask << (bitpos % BITS_PER_LONG));
-+	*ptr |= ((unsigned long)status & mask) << (bitpos % BITS_PER_LONG);
-+}
-+
-+static void i3c_bus_set_addr_slot_status(struct i3c_bus *bus, u16 addr,
-+					 enum i3c_addr_slot_status status)
-+{
-+	i3c_bus_set_addr_slot_status_mask(bus, addr, status, I3C_ADDR_SLOT_STATUS_MASK);
- }
- 
- static bool i3c_bus_dev_addr_is_avail(struct i3c_bus *bus, u8 addr)
-@@ -380,13 +468,44 @@ static bool i3c_bus_dev_addr_is_avail(struct i3c_bus *bus, u8 addr)
- 	return status == I3C_ADDR_SLOT_FREE;
- }
- 
-+/*
-+ * ┌────┬─────────────┬───┬─────────┬───┐
-+ * │S/Sr│ 7'h7E RnW=0 │ACK│ ENTDAA  │ T ├────┐
-+ * └────┴─────────────┴───┴─────────┴───┘    │
-+ * ┌─────────────────────────────────────────┘
-+ * │  ┌──┬─────────────┬───┬─────────────────┬────────────────┬───┬─────────┐
-+ * └─►│Sr│7'h7E RnW=1  │ACK│48bit UID BCR DCR│Assign 7bit Addr│PAR│ ACK/NACK│
-+ *    └──┴─────────────┴───┴─────────────────┴────────────────┴───┴─────────┘
-+ * Some master controllers (such as HCI) need to prepare the entire above transaction before
-+ * sending it out to the I3C bus. This means that a 7-bit dynamic address needs to be allocated
-+ * before knowing the target device's UID information.
-+ *
-+ * However, some I3C targets may request specific addresses (called as "init_dyn_addr"), which is
-+ * typically specified by the DT-'s assigned-address property. Lower addresses having higher IBI
-+ * priority. If it is available, i3c_bus_get_free_addr() preferably return a free address that is
-+ * not in the list of desired addresses (called as "init_dyn_addr"). This allows the device with
-+ * the "init_dyn_addr" to switch to its "init_dyn_addr" when it hot-joins the I3C bus. Otherwise,
-+ * if the "init_dyn_addr" is already in use by another I3C device, the target device will not be
-+ * able to switch to its desired address.
-+ *
-+ * If the previous step fails, fallback returning one of the remaining unassigned address,
-+ * regardless of its state in the desired list.
-+ */
- static int i3c_bus_get_free_addr(struct i3c_bus *bus, u8 start_addr)
- {
- 	enum i3c_addr_slot_status status;
- 	u8 addr;
- 
- 	for (addr = start_addr; addr < I3C_MAX_ADDR; addr++) {
--		status = i3c_bus_get_addr_slot_status(bus, addr);
-+		status = i3c_bus_get_addr_slot_status_mask(bus, addr,
-+							   I3C_ADDR_SLOT_EXT_STATUS_MASK);
-+		if (status == I3C_ADDR_SLOT_FREE)
-+			return addr;
-+	}
-+
-+	for (addr = start_addr; addr < I3C_MAX_ADDR; addr++) {
-+		status = i3c_bus_get_addr_slot_status_mask(bus, addr,
-+							   I3C_ADDR_SLOT_STATUS_MASK);
- 		if (status == I3C_ADDR_SLOT_FREE)
- 			return addr;
- 	}
-@@ -453,6 +572,36 @@ static int i3c_bus_init(struct i3c_bus *i3cbus, struct device_node *np)
+ i3c_bus_get_addr_slot_status_mask(struct i3c_bus *bus, u16 addr, u32 mask)
+@@ -496,6 +572,36 @@ static int i3c_bus_init(struct i3c_bus *i3cbus, struct device_node *np)
  	return 0;
  }
  
@@ -1653,7 +1544,7 @@
  static const char * const i3c_bus_mode_strings[] = {
  	[I3C_BUS_MODE_PURE] = "pure",
  	[I3C_BUS_MODE_MIXED_FAST] = "mixed-fast",
-@@ -460,6 +609,26 @@ static const char * const i3c_bus_mode_strings[] = {
+@@ -503,6 +609,26 @@ static const char * const i3c_bus_mode_strings[] = {
  	[I3C_BUS_MODE_MIXED_SLOW] = "mixed-slow",
  };
  
@@ -1680,7 +1571,7 @@
  static ssize_t mode_show(struct device *dev,
  			 struct device_attribute *da,
  			 char *buf)
-@@ -471,9 +640,9 @@ static ssize_t mode_show(struct device *dev,
+@@ -514,9 +640,9 @@ static ssize_t mode_show(struct device *dev,
  	if (i3cbus->mode < 0 ||
  	    i3cbus->mode >= ARRAY_SIZE(i3c_bus_mode_strings) ||
  	    !i3c_bus_mode_strings[i3cbus->mode])
@@ -1692,7 +1583,7 @@
  	i3c_bus_normaluse_unlock(i3cbus);
  
  	return ret;
-@@ -488,8 +657,8 @@ static ssize_t current_master_show(struct device *dev,
+@@ -531,8 +657,8 @@ static ssize_t current_master_show(struct device *dev,
  	ssize_t ret;
  
  	i3c_bus_normaluse_lock(i3cbus);
@@ -1703,7 +1594,7 @@
  	i3c_bus_normaluse_unlock(i3cbus);
  
  	return ret;
-@@ -504,7 +673,7 @@ static ssize_t i3c_scl_frequency_show(struct device *dev,
+@@ -547,7 +673,7 @@ static ssize_t i3c_scl_frequency_show(struct device *dev,
  	ssize_t ret;
  
  	i3c_bus_normaluse_lock(i3cbus);
@@ -1712,7 +1603,7 @@
  	i3c_bus_normaluse_unlock(i3cbus);
  
  	return ret;
-@@ -519,13 +688,151 @@ static ssize_t i2c_scl_frequency_show(struct device *dev,
+@@ -562,7 +688,7 @@ static ssize_t i2c_scl_frequency_show(struct device *dev,
  	ssize_t ret;
  
  	i3c_bus_normaluse_lock(i3cbus);
@@ -1721,95 +1612,28 @@
  	i3c_bus_normaluse_unlock(i3cbus);
  
  	return ret;
- }
- static DEVICE_ATTR_RO(i2c_scl_frequency);
+@@ -581,10 +707,15 @@ static int i3c_set_hotjoin(struct i3c_master_controller *master, bool enable)
  
-+static int i3c_set_hotjoin(struct i3c_master_controller *master, bool enable)
-+{
-+	int ret;
-+
-+	if (!master || !master->ops)
-+		return -EINVAL;
-+
-+	if (!master->ops->enable_hotjoin || !master->ops->disable_hotjoin)
-+		return -EINVAL;
-+
-+	i3c_bus_normaluse_lock(&master->bus);
-+
+ 	i3c_bus_normaluse_lock(&master->bus);
+ 
+-	if (enable)
 +	if (enable) {
-+		ret = master->ops->enable_hotjoin(master);
+ 		ret = master->ops->enable_hotjoin(master);
+-	else
 +		i3c_master_enec_locked(master, I3C_BROADCAST_ADDR,
 +				       I3C_CCC_EVENT_HJ);
 +	} else {
-+		ret = master->ops->disable_hotjoin(master);
+ 		ret = master->ops->disable_hotjoin(master);
 +		i3c_master_disec_locked(master, I3C_BROADCAST_ADDR,
 +					I3C_CCC_EVENT_HJ);
 +	}
-+
-+	master->hotjoin = enable;
-+
-+	i3c_bus_normaluse_unlock(&master->bus);
-+
-+	return ret;
-+}
-+
-+static ssize_t hotjoin_store(struct device *dev, struct device_attribute *attr,
-+			     const char *buf, size_t count)
-+{
-+	struct i3c_bus *i3cbus = dev_to_i3cbus(dev);
-+	int ret;
-+	bool res;
-+
-+	if (!i3cbus->cur_master)
-+		return -EINVAL;
-+
-+	if (kstrtobool(buf, &res))
-+		return -EINVAL;
-+
-+	ret = i3c_set_hotjoin(i3cbus->cur_master->common.master, res);
-+	if (ret)
-+		return ret;
-+
-+	return count;
-+}
-+
-+/*
-+ * i3c_master_enable_hotjoin - Enable hotjoin
-+ * @master: I3C master object
-+ *
-+ * Return: a 0 in case of success, an negative error code otherwise.
-+ */
-+int i3c_master_enable_hotjoin(struct i3c_master_controller *master)
-+{
-+	return i3c_set_hotjoin(master, true);
-+}
-+EXPORT_SYMBOL_GPL(i3c_master_enable_hotjoin);
-+
-+/*
-+ * i3c_master_disable_hotjoin - Disable hotjoin
-+ * @master: I3C master object
-+ *
-+ * Return: a 0 in case of success, an negative error code otherwise.
-+ */
-+int i3c_master_disable_hotjoin(struct i3c_master_controller *master)
-+{
-+	return i3c_set_hotjoin(master, false);
-+}
-+EXPORT_SYMBOL_GPL(i3c_master_disable_hotjoin);
-+
-+static ssize_t hotjoin_show(struct device *dev, struct device_attribute *da, char *buf)
-+{
-+	struct i3c_bus *i3cbus = dev_to_i3cbus(dev);
-+	ssize_t ret;
-+
-+	i3c_bus_normaluse_lock(i3cbus);
-+	ret = sysfs_emit(buf, "%d\n", i3cbus->cur_master->common.master->hotjoin);
-+	i3c_bus_normaluse_unlock(i3cbus);
-+
-+	return ret;
-+}
-+
-+static DEVICE_ATTR_RW(hotjoin);
+ 
+ 	master->hotjoin = enable;
+ 
+@@ -650,6 +781,57 @@ static ssize_t hotjoin_show(struct device *dev, struct device_attribute *da, cha
+ }
+ 
+ static DEVICE_ATTR_RW(hotjoin);
 +static ssize_t rescan_store(struct device *dev, struct device_attribute *attr,
 +			    const char *buf, size_t count)
 +{
@@ -1861,22 +1685,20 @@
 +	return count;
 +}
 +static DEVICE_ATTR_WO(rescan);
-+
+ 
  static struct attribute *i3c_masterdev_attrs[] = {
  	&dev_attr_mode.attr,
- 	&dev_attr_current_master.attr,
-@@ -536,6 +843,10 @@ static struct attribute *i3c_masterdev_attrs[] = {
- 	&dev_attr_pid.attr,
+@@ -662,6 +844,9 @@ static struct attribute *i3c_masterdev_attrs[] = {
  	&dev_attr_dynamic_address.attr,
  	&dev_attr_hdrcap.attr,
-+	&dev_attr_hotjoin.attr,
+ 	&dev_attr_hotjoin.attr,
 +	&dev_attr_bus_context.attr,
 +	&dev_attr_bus_reset.attr,
 +	&dev_attr_rescan.attr,
  	NULL,
  };
  ATTRIBUTE_GROUPS(i3c_masterdev);
-@@ -554,9 +865,10 @@ static void i3c_masterdev_release(struct device *dev)
+@@ -680,9 +865,10 @@ static void i3c_masterdev_release(struct device *dev)
  	of_node_put(dev->of_node);
  }
  
@@ -1888,7 +1710,7 @@
  
  static int i3c_bus_set_mode(struct i3c_bus *i3cbus, enum i3c_bus_mode mode,
  			    unsigned long max_i2c_scl_rate)
-@@ -656,13 +968,15 @@ static void i3c_ccc_cmd_dest_cleanup(struct i3c_ccc_cmd_dest *dest)
+@@ -782,13 +968,15 @@ static void i3c_ccc_cmd_dest_cleanup(struct i3c_ccc_cmd_dest *dest)
  
  static void i3c_ccc_cmd_init(struct i3c_ccc_cmd *cmd, bool rnw, u8 id,
  			     struct i3c_ccc_cmd_dest *dests,
@@ -1905,7 +1727,7 @@
  }
  
  static int i3c_master_send_ccc_cmd_locked(struct i3c_master_controller *master,
-@@ -778,8 +1092,8 @@ static int i3c_master_rstdaa_locked(struct i3c_master_controller *master,
+@@ -904,8 +1092,8 @@ static int i3c_master_rstdaa_locked(struct i3c_master_controller *master,
  
  	i3c_ccc_cmd_dest_init(&dest, addr, 0);
  	i3c_ccc_cmd_init(&cmd, false,
@@ -1916,7 +1738,7 @@
  	ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
  	i3c_ccc_cmd_dest_cleanup(&dest);
  
-@@ -809,7 +1123,7 @@ int i3c_master_entdaa_locked(struct i3c_master_controller *master)
+@@ -935,7 +1123,7 @@ int i3c_master_entdaa_locked(struct i3c_master_controller *master)
  	int ret;
  
  	i3c_ccc_cmd_dest_init(&dest, I3C_BROADCAST_ADDR, 0);
@@ -1925,7 +1747,7 @@
  	ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
  	i3c_ccc_cmd_dest_cleanup(&dest);
  
-@@ -831,10 +1145,9 @@ static int i3c_master_enec_disec_locked(struct i3c_master_controller *master,
+@@ -957,10 +1145,9 @@ static int i3c_master_enec_disec_locked(struct i3c_master_controller *master,
  
  	events->events = evts;
  	i3c_ccc_cmd_init(&cmd, false,
@@ -1939,7 +1761,7 @@
  	ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
  	i3c_ccc_cmd_dest_cleanup(&dest);
  
-@@ -967,7 +1280,7 @@ int i3c_master_defslvs_locked(struct i3c_master_controller *master)
+@@ -1093,7 +1280,7 @@ int i3c_master_defslvs_locked(struct i3c_master_controller *master)
  		desc++;
  	}
  
@@ -1948,7 +1770,7 @@
  	ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
  	i3c_ccc_cmd_dest_cleanup(&dest);
  
-@@ -975,6 +1288,43 @@ int i3c_master_defslvs_locked(struct i3c_master_controller *master)
+@@ -1101,6 +1288,43 @@ int i3c_master_defslvs_locked(struct i3c_master_controller *master)
  }
  EXPORT_SYMBOL_GPL(i3c_master_defslvs_locked);
  
@@ -1992,7 +1814,7 @@
  static int i3c_master_setda_locked(struct i3c_master_controller *master,
  				   u8 oldaddr, u8 newaddr, bool setdasa)
  {
-@@ -992,8 +1342,8 @@ static int i3c_master_setda_locked(struct i3c_master_controller *master,
+@@ -1118,8 +1342,8 @@ static int i3c_master_setda_locked(struct i3c_master_controller *master,
  
  	setda->addr = newaddr << 1;
  	i3c_ccc_cmd_init(&cmd, false,
@@ -2003,7 +1825,7 @@
  	ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
  	i3c_ccc_cmd_dest_cleanup(&dest);
  
-@@ -1012,8 +1362,8 @@ static int i3c_master_setnewda_locked(struct i3c_master_controller *master,
+@@ -1138,8 +1362,8 @@ static int i3c_master_setnewda_locked(struct i3c_master_controller *master,
  	return i3c_master_setda_locked(master, oldaddr, newaddr, false);
  }
  
@@ -2014,7 +1836,7 @@
  {
  	struct i3c_ccc_cmd_dest dest;
  	struct i3c_ccc_mrl *mrl;
-@@ -1031,7 +1381,7 @@ static int i3c_master_getmrl_locked(struct i3c_master_controller *master,
+@@ -1157,7 +1381,7 @@ static int i3c_master_getmrl_locked(struct i3c_master_controller *master,
  	if (!(info->bcr & I3C_BCR_IBI_PAYLOAD))
  		dest.payload.len -= 1;
  
@@ -2023,7 +1845,7 @@
  	ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
  	if (ret)
  		goto out;
-@@ -1054,8 +1404,8 @@ static int i3c_master_getmrl_locked(struct i3c_master_controller *master,
+@@ -1180,8 +1404,8 @@ static int i3c_master_getmrl_locked(struct i3c_master_controller *master,
  	return ret;
  }
  
@@ -2034,7 +1856,7 @@
  {
  	struct i3c_ccc_cmd_dest dest;
  	struct i3c_ccc_mwl *mwl;
-@@ -1066,7 +1416,7 @@ static int i3c_master_getmwl_locked(struct i3c_master_controller *master,
+@@ -1192,7 +1416,7 @@ static int i3c_master_getmwl_locked(struct i3c_master_controller *master,
  	if (!mwl)
  		return -ENOMEM;
  
@@ -2043,113 +1865,77 @@
  	ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
  	if (ret)
  		goto out;
-@@ -1084,61 +1434,124 @@ static int i3c_master_getmwl_locked(struct i3c_master_controller *master,
+@@ -1210,6 +1434,61 @@ static int i3c_master_getmwl_locked(struct i3c_master_controller *master,
  	return ret;
  }
  
--static int i3c_master_getmxds_locked(struct i3c_master_controller *master,
--				     struct i3c_device_info *info)
 +int i3c_master_setmrl_locked(struct i3c_master_controller *master,
 +			     struct i3c_device_info *info, u16 read_len, u8 ibi_len)
- {
--	struct i3c_ccc_getmxds *getmaxds;
- 	struct i3c_ccc_cmd_dest dest;
- 	struct i3c_ccc_cmd cmd;
++{
++	struct i3c_ccc_cmd_dest dest;
++	struct i3c_ccc_cmd cmd;
 +	struct i3c_ccc_mrl *mrl;
- 	int ret;
- 
--	getmaxds = i3c_ccc_cmd_dest_init(&dest, info->dyn_addr,
--					 sizeof(*getmaxds));
--	if (!getmaxds)
++	int ret;
++
 +	mrl = i3c_ccc_cmd_dest_init(&dest, info->dyn_addr, sizeof(*mrl));
 +	if (!mrl)
- 		return -ENOMEM;
- 
--	i3c_ccc_cmd_init(&cmd, true, I3C_CCC_GETMXDS, &dest, 1);
--	ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
--	if (ret)
--		goto out;
--
--	if (dest.payload.len != 2 && dest.payload.len != 5) {
--		ret = -EIO;
--		goto out;
--	}
++		return -ENOMEM;
++
 +	/*
 +	 * When the device does not have IBI payload SETMRL only sends 2
 +	 * bytes of data.
 +	 */
 +	if (!(info->bcr & I3C_BCR_IBI_PAYLOAD))
 +		dest.payload.len -= 1;
- 
--	info->max_read_ds = getmaxds->maxrd;
--	info->max_write_ds = getmaxds->maxwr;
--	if (dest.payload.len == 5)
--		info->max_read_turnaround = getmaxds->maxrdturn[0] |
--					    ((u32)getmaxds->maxrdturn[1] << 8) |
--					    ((u32)getmaxds->maxrdturn[2] << 16);
++
 +	mrl->read_len = cpu_to_be16(read_len);
 +	mrl->ibi_len = ibi_len;
 +	info->max_read_len = read_len;
 +	info->max_ibi_len = mrl->ibi_len;
 +	i3c_ccc_cmd_init(&cmd, false, I3C_CCC_SETMRL(false), &dest, 1, false,
 +			 0);
- 
--out:
-+	ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
- 	i3c_ccc_cmd_dest_cleanup(&dest);
- 
- 	return ret;
- }
- 
--static int i3c_master_gethdrcap_locked(struct i3c_master_controller *master,
--				       struct i3c_device_info *info)
-+int i3c_master_setmwl_locked(struct i3c_master_controller *master,
-+			     struct i3c_device_info *info, u16 write_len)
- {
--	struct i3c_ccc_gethdrcap *gethdrcap;
- 	struct i3c_ccc_cmd_dest dest;
- 	struct i3c_ccc_cmd cmd;
-+	struct i3c_ccc_mwl *mwl;
- 	int ret;
- 
--	gethdrcap = i3c_ccc_cmd_dest_init(&dest, info->dyn_addr,
--					  sizeof(*gethdrcap));
--	if (!gethdrcap)
-+	mwl = i3c_ccc_cmd_dest_init(&dest, info->dyn_addr, sizeof(*mwl));
-+	if (!mwl)
- 		return -ENOMEM;
- 
--	i3c_ccc_cmd_init(&cmd, true, I3C_CCC_GETHDRCAP, &dest, 1);
--	ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
--	if (ret)
--		goto out;
-+	mwl->len = cpu_to_be16(write_len);
-+	info->max_write_len = write_len;
-+	i3c_ccc_cmd_init(&cmd, false, I3C_CCC_SETMWL(false), &dest, 1, false,
-+			 0);
- 
--	if (dest.payload.len != 1) {
++
 +	ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
 +	i3c_ccc_cmd_dest_cleanup(&dest);
 +
 +	return ret;
 +}
 +
-+static int i3c_master_getmxds_locked(struct i3c_master_controller *master,
-+				     struct i3c_device_info *info)
++int i3c_master_setmwl_locked(struct i3c_master_controller *master,
++			     struct i3c_device_info *info, u16 write_len)
 +{
-+	struct i3c_ccc_getmxds *getmaxds;
 +	struct i3c_ccc_cmd_dest dest;
 +	struct i3c_ccc_cmd cmd;
++	struct i3c_ccc_mwl *mwl;
 +	int ret;
 +
-+	getmaxds = i3c_ccc_cmd_dest_init(&dest, info->dyn_addr,
-+					 sizeof(*getmaxds));
-+	if (!getmaxds)
++	mwl = i3c_ccc_cmd_dest_init(&dest, info->dyn_addr, sizeof(*mwl));
++	if (!mwl)
 +		return -ENOMEM;
 +
-+	i3c_ccc_cmd_init(&cmd, true, I3C_CCC_GETMXDS, &dest, 1, false, 0);
++	mwl->len = cpu_to_be16(write_len);
++	info->max_write_len = write_len;
++	i3c_ccc_cmd_init(&cmd, false, I3C_CCC_SETMWL(false), &dest, 1, false,
++			 0);
++
 +	ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
++	i3c_ccc_cmd_dest_cleanup(&dest);
++
++	return ret;
++}
++
+ static int i3c_master_getmxds_locked(struct i3c_master_controller *master,
+ 				     struct i3c_device_info *info)
+ {
+@@ -1223,10 +1502,18 @@ static int i3c_master_getmxds_locked(struct i3c_master_controller *master,
+ 	if (!getmaxds)
+ 		return -ENOMEM;
+ 
+-	i3c_ccc_cmd_init(&cmd, true, I3C_CCC_GETMXDS, &dest, 1);
++	i3c_ccc_cmd_init(&cmd, true, I3C_CCC_GETMXDS, &dest, 1, false, 0);
+ 	ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
+-	if (ret)
+-		goto out;
 +	if (ret) {
 +		/*
 +		 * Retry when the device does not support max read turnaround
@@ -2160,48 +1946,25 @@
 +		if (ret)
 +			goto out;
 +	}
-+
-+	if (dest.payload.len != 2 && dest.payload.len != 5) {
-+		ret = -EIO;
-+		goto out;
-+	}
-+
-+	info->max_read_ds = getmaxds->maxrd;
-+	info->max_write_ds = getmaxds->maxwr;
-+	if (dest.payload.len == 5)
-+		info->max_read_turnaround = getmaxds->maxrdturn[0] |
-+					    ((u32)getmaxds->maxrdturn[1] << 8) |
-+					    ((u32)getmaxds->maxrdturn[2] << 16);
-+
-+out:
-+	i3c_ccc_cmd_dest_cleanup(&dest);
-+
-+	return ret;
-+}
-+
-+static int i3c_master_gethdrcap_locked(struct i3c_master_controller *master,
-+				       struct i3c_device_info *info)
-+{
-+	struct i3c_ccc_gethdrcap *gethdrcap;
-+	struct i3c_ccc_cmd_dest dest;
-+	struct i3c_ccc_cmd cmd;
-+	int ret;
-+
-+	gethdrcap = i3c_ccc_cmd_dest_init(&dest, info->dyn_addr,
-+					  sizeof(*gethdrcap));
-+	if (!gethdrcap)
-+		return -ENOMEM;
-+
+ 
+ 	if (dest.payload.len != 2 && dest.payload.len != 5) {
+ 		ret = -EIO;
+@@ -1259,12 +1546,12 @@ static int i3c_master_gethdrcap_locked(struct i3c_master_controller *master,
+ 	if (!gethdrcap)
+ 		return -ENOMEM;
+ 
+-	i3c_ccc_cmd_init(&cmd, true, I3C_CCC_GETHDRCAP, &dest, 1);
 +	i3c_ccc_cmd_init(&cmd, true, I3C_CCC_GETHDRCAP, &dest, 1, false, 0);
-+	ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
-+	if (ret)
-+		goto out;
-+
+ 	ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
+ 	if (ret)
+ 		goto out;
+ 
+-	if (dest.payload.len != 1) {
 +	if (dest.payload.len < 1 || dest.payload.len > 4) {
  		ret = -EIO;
  		goto out;
  	}
-@@ -1163,7 +1576,7 @@ static int i3c_master_getpid_locked(struct i3c_master_controller *master,
+@@ -1289,7 +1576,7 @@ static int i3c_master_getpid_locked(struct i3c_master_controller *master,
  	if (!getpid)
  		return -ENOMEM;
  
@@ -2210,7 +1973,7 @@
  	ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
  	if (ret)
  		goto out;
-@@ -1193,7 +1606,7 @@ static int i3c_master_getbcr_locked(struct i3c_master_controller *master,
+@@ -1319,7 +1606,7 @@ static int i3c_master_getbcr_locked(struct i3c_master_controller *master,
  	if (!getbcr)
  		return -ENOMEM;
  
@@ -2219,7 +1982,7 @@
  	ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
  	if (ret)
  		goto out;
-@@ -1218,7 +1631,7 @@ static int i3c_master_getdcr_locked(struct i3c_master_controller *master,
+@@ -1344,7 +1631,7 @@ static int i3c_master_getdcr_locked(struct i3c_master_controller *master,
  	if (!getdcr)
  		return -ENOMEM;
  
@@ -2228,7 +1991,7 @@
  	ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
  	if (ret)
  		goto out;
-@@ -1231,6 +1644,76 @@ static int i3c_master_getdcr_locked(struct i3c_master_controller *master,
+@@ -1357,6 +1644,76 @@ static int i3c_master_getdcr_locked(struct i3c_master_controller *master,
  	return ret;
  }
  
@@ -2305,7 +2068,7 @@
  static int i3c_master_retrieve_dev_info(struct i3c_dev_desc *dev)
  {
  	struct i3c_master_controller *master = i3c_dev_get_master(dev);
-@@ -1267,6 +1750,19 @@ static int i3c_master_retrieve_dev_info(struct i3c_dev_desc *dev)
+@@ -1393,6 +1750,19 @@ static int i3c_master_retrieve_dev_info(struct i3c_dev_desc *dev)
  	if (dev->info.bcr & I3C_BCR_IBI_PAYLOAD)
  		dev->info.max_ibi_len = 1;
  
@@ -2325,34 +2088,7 @@
  	i3c_master_getmrl_locked(master, &dev->info);
  	i3c_master_getmwl_locked(master, &dev->info);
  
-@@ -1293,7 +1789,7 @@ static void i3c_master_put_i3c_addrs(struct i3c_dev_desc *dev)
- 					     I3C_ADDR_SLOT_FREE);
- 
- 	if (dev->boardinfo && dev->boardinfo->init_dyn_addr)
--		i3c_bus_set_addr_slot_status(&master->bus, dev->info.dyn_addr,
-+		i3c_bus_set_addr_slot_status(&master->bus, dev->boardinfo->init_dyn_addr,
- 					     I3C_ADDR_SLOT_FREE);
- }
- 
-@@ -1382,16 +1878,9 @@ static int i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev,
- 				       u8 old_dyn_addr)
- {
- 	struct i3c_master_controller *master = i3c_dev_get_master(dev);
--	enum i3c_addr_slot_status status;
- 	int ret;
- 
--	if (dev->info.dyn_addr != old_dyn_addr &&
--	    (!dev->boardinfo ||
--	     dev->info.dyn_addr != dev->boardinfo->init_dyn_addr)) {
--		status = i3c_bus_get_addr_slot_status(&master->bus,
--						      dev->info.dyn_addr);
--		if (status != I3C_ADDR_SLOT_FREE)
--			return -EBUSY;
-+	if (dev->info.dyn_addr != old_dyn_addr) {
- 		i3c_bus_set_addr_slot_status(&master->bus,
- 					     dev->info.dyn_addr,
- 					     I3C_ADDR_SLOT_I3C_DEV);
-@@ -1550,18 +2039,28 @@ i3c_master_register_new_i3c_devs(struct i3c_master_controller *master)
+@@ -1669,18 +2039,28 @@ i3c_master_register_new_i3c_devs(struct i3c_master_controller *master)
   */
  int i3c_master_do_daa(struct i3c_master_controller *master)
  {
@@ -2386,10 +2122,17 @@
  
  	return 0;
  }
-@@ -1654,6 +2153,75 @@ static void i3c_master_detach_free_devs(struct i3c_master_controller *master)
+@@ -1773,13 +2153,82 @@ static void i3c_master_detach_free_devs(struct i3c_master_controller *master)
  	}
  }
  
+-/**
+- * i3c_master_bus_init() - initialize an I3C bus
+- * @master: main master initializing the bus
+- *
+- * This function is following all initialisation steps described in the I3C
+- * specification:
+- *
 +static int i3c_master_jesd403_bus_init(struct i3c_master_controller *master)
 +{
 +	struct i3c_dev_boardinfo *i3cboardinfo;
@@ -2459,36 +2202,17 @@
 +	return i3c_master_do_daa(master);
 +}
 +
- /**
-  * i3c_master_bus_init() - initialize an I3C bus
-  * @master: main master initializing the bus
-@@ -1744,6 +2312,12 @@ static int i3c_master_bus_init(struct i3c_master_controller *master)
- 		goto err_bus_cleanup;
- 	}
- 
-+	if (master->ops->set_speed) {
-+		ret = master->ops->set_speed(master, I3C_OPEN_DRAIN_SLOW_SPEED);
-+		if (ret)
-+			goto err_bus_cleanup;
-+	}
-+
- 	/*
- 	 * Reset all dynamic address that may have been assigned before
- 	 * (assigned by the bootloader for example).
-@@ -1752,6 +2326,12 @@ static int i3c_master_bus_init(struct i3c_master_controller *master)
- 	if (ret && ret != I3C_ERROR_M2)
- 		goto err_bus_cleanup;
- 
-+	if (master->ops->set_speed) {
-+		ret = master->ops->set_speed(master, I3C_OPEN_DRAIN_NORMAL_SPEED);
-+		if (ret)
-+			goto err_bus_cleanup;
-+	}
-+
- 	/* Disable all slave events before starting DAA. */
- 	ret = i3c_master_disec_locked(master, I3C_BROADCAST_ADDR,
- 				      I3C_CCC_EVENT_SIR | I3C_CCC_EVENT_MR |
-@@ -1759,6 +2339,14 @@ static int i3c_master_bus_init(struct i3c_master_controller *master)
++/**
++ * i3c_master_bus_init() - initialize an I3C bus
++ * @master: main master initializing the bus
++ *
++ * This function is following all initialisation steps described in the I3C
++ * specification:
++ *
+  * 1. Attach I2C devs to the master so that the master can fill its internal
+  *    device table appropriately
+  *
+@@ -1890,6 +2339,14 @@ static int i3c_master_bus_init(struct i3c_master_controller *master)
  	if (ret && ret != I3C_ERROR_M2)
  		goto err_bus_cleanup;
  
@@ -2503,22 +2227,7 @@
  	/*
  	 * Reserve init_dyn_addr first, and then try to pre-assign dynamic
  	 * address and retrieve device information if needed.
-@@ -1782,9 +2370,11 @@ static int i3c_master_bus_init(struct i3c_master_controller *master)
- 			goto err_rstdaa;
- 		}
- 
--		i3c_bus_set_addr_slot_status(&master->bus,
--					     i3cboardinfo->init_dyn_addr,
--					     I3C_ADDR_SLOT_I3C_DEV);
-+		/* Do not mark as occupied until real device exist in bus */
-+		i3c_bus_set_addr_slot_status_mask(&master->bus,
-+						  i3cboardinfo->init_dyn_addr,
-+						  I3C_ADDR_SLOT_EXT_DESIRED,
-+						  I3C_ADDR_SLOT_EXT_STATUS_MASK);
- 
- 		/*
- 		 * Only try to create/attach devices that have a static
-@@ -1819,6 +2409,25 @@ static int i3c_master_bus_init(struct i3c_master_controller *master)
+@@ -1952,6 +2409,25 @@ static int i3c_master_bus_init(struct i3c_master_controller *master)
  
  static void i3c_master_bus_cleanup(struct i3c_master_controller *master)
  {
@@ -2544,7 +2253,7 @@
  	if (master->ops->bus_cleanup)
  		master->ops->bus_cleanup(master);
  
-@@ -1847,7 +2456,9 @@ i3c_master_search_i3c_dev_duplicate(struct i3c_dev_desc *refdev)
+@@ -1980,7 +2456,9 @@ i3c_master_search_i3c_dev_duplicate(struct i3c_dev_desc *refdev)
  	struct i3c_dev_desc *i3cdev;
  
  	i3c_bus_for_each_i3cdev(&master->bus, i3cdev) {
@@ -2555,7 +2264,7 @@
  			return i3cdev;
  	}
  
-@@ -1900,6 +2511,7 @@ int i3c_master_add_i3c_dev_locked(struct i3c_master_controller *master,
+@@ -2033,6 +2511,7 @@ int i3c_master_add_i3c_dev_locked(struct i3c_master_controller *master,
  	olddev = i3c_master_search_i3c_dev_duplicate(newdev);
  	if (olddev) {
  		newdev->dev = olddev->dev;
@@ -2563,24 +2272,7 @@
  		if (newdev->dev)
  			newdev->dev->desc = newdev;
  
-@@ -1915,14 +2527,29 @@ int i3c_master_add_i3c_dev_locked(struct i3c_master_controller *master,
- 			ibireq.max_payload_len = olddev->ibi->max_payload_len;
- 			ibireq.num_slots = olddev->ibi->num_slots;
- 
--			if (olddev->ibi->enabled) {
-+			if (olddev->ibi->enabled)
- 				enable_ibi = true;
--				i3c_dev_disable_ibi_locked(olddev);
--			}
--
-+			/*
-+			 * The olddev should not receive any commands on the
-+			 * i3c bus as it does not exist and has been assigned
-+			 * a new address. This will result in NACK or timeout.
-+			 * So, update the olddev->ibi->enabled flag to false
-+			 * to avoid DISEC with OldAddr.
-+			 */
-+			olddev->ibi->enabled = false;
+@@ -2061,6 +2540,16 @@ int i3c_master_add_i3c_dev_locked(struct i3c_master_controller *master,
  			i3c_dev_free_ibi_locked(olddev);
  		}
  		mutex_unlock(&olddev->ibi_lock);
@@ -2597,17 +2289,7 @@
  
  		old_dyn_addr = olddev->info.dyn_addr;
  
-@@ -1947,7 +2574,8 @@ int i3c_master_add_i3c_dev_locked(struct i3c_master_controller *master,
- 	else
- 		expected_dyn_addr = newdev->info.dyn_addr;
- 
--	if (newdev->info.dyn_addr != expected_dyn_addr) {
-+	if (newdev->info.dyn_addr != expected_dyn_addr &&
-+	    i3c_bus_get_addr_slot_status(&master->bus, expected_dyn_addr) == I3C_ADDR_SLOT_FREE) {
- 		/*
- 		 * Try to apply the expected dynamic address. If it fails, keep
- 		 * the address assigned by the master.
-@@ -2050,6 +2678,8 @@ of_i3c_master_add_i3c_boardinfo(struct i3c_master_controller *master,
+@@ -2189,6 +2678,8 @@ of_i3c_master_add_i3c_boardinfo(struct i3c_master_controller *master,
  	struct device *dev = &master->dev;
  	enum i3c_addr_slot_status addrstatus;
  	u32 init_dyn_addr = 0;
@@ -2616,7 +2298,7 @@
  
  	boardinfo = devm_kzalloc(dev, sizeof(*boardinfo), GFP_KERNEL);
  	if (!boardinfo)
-@@ -2083,6 +2713,16 @@ of_i3c_master_add_i3c_boardinfo(struct i3c_master_controller *master,
+@@ -2222,6 +2713,16 @@ of_i3c_master_add_i3c_boardinfo(struct i3c_master_controller *master,
  	    I3C_PID_RND_LOWER_32BITS(boardinfo->pid))
  		return -EINVAL;
  
@@ -2633,7 +2315,7 @@
  	boardinfo->init_dyn_addr = init_dyn_addr;
  	boardinfo->of_node = of_node_get(node);
  	list_add_tail(&boardinfo->node, &master->boardinfo.i3c);
-@@ -2120,12 +2760,29 @@ static int of_populate_i3c_bus(struct i3c_master_controller *master)
+@@ -2259,12 +2760,29 @@ static int of_populate_i3c_bus(struct i3c_master_controller *master)
  	struct device *dev = &master->dev;
  	struct device_node *i3cbus_np = dev->of_node;
  	struct device_node *node;
@@ -2664,7 +2346,7 @@
  	for_each_available_child_of_node(i3cbus_np, node) {
  		ret = of_i3c_master_add_dev(master, node);
  		if (ret) {
-@@ -2311,7 +2968,7 @@ static int i3c_master_i2c_adapter_init(struct i3c_master_controller *master)
+@@ -2450,7 +2968,7 @@ static int i3c_master_i2c_adapter_init(struct i3c_master_controller *master)
  	adap->dev.parent = master->dev.parent;
  	adap->owner = master->dev.parent->driver->owner;
  	adap->algo = &i3c_master_i2c_algo;
@@ -2673,7 +2355,7 @@
  
  	/* FIXME: Should we allow i3c masters to override these values? */
  	adap->timeout = 1000;
-@@ -2349,11 +3006,19 @@ static void i3c_master_i2c_adapter_cleanup(struct i3c_master_controller *master)
+@@ -2488,11 +3006,19 @@ static void i3c_master_i2c_adapter_cleanup(struct i3c_master_controller *master)
  static void i3c_master_unregister_i3c_devs(struct i3c_master_controller *master)
  {
  	struct i3c_dev_desc *i3cdev;
@@ -2693,16 +2375,16 @@
  		i3cdev->dev->desc = NULL;
  		if (device_is_registered(&i3cdev->dev->dev))
  			device_unregister(&i3cdev->dev->dev);
-@@ -2374,7 +3039,7 @@ static void i3c_master_unregister_i3c_devs(struct i3c_master_controller *master)
- void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct i3c_ibi_slot *slot)
- {
+@@ -2516,7 +3042,7 @@ void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct i3c_ibi_slot *slot)
+ 		return;
+ 
  	atomic_inc(&dev->ibi->pending_ibis);
 -	queue_work(dev->common.master->wq, &slot->work);
 +	queue_work(dev->ibi->wq, &slot->work);
  }
  EXPORT_SYMBOL_GPL(i3c_master_queue_ibi);
  
-@@ -2631,6 +3296,10 @@ int i3c_master_register(struct i3c_master_controller *master,
+@@ -2773,6 +3299,10 @@ int i3c_master_register(struct i3c_master_controller *master,
  	device_initialize(&master->dev);
  	dev_set_name(&master->dev, "i3c-%d", i3cbus->id);
  
@@ -2713,7 +2395,7 @@
  	ret = of_populate_i3c_bus(master);
  	if (ret)
  		goto err_put_dev;
-@@ -2684,14 +3353,18 @@ int i3c_master_register(struct i3c_master_controller *master,
+@@ -2826,14 +3356,18 @@ int i3c_master_register(struct i3c_master_controller *master,
  	if (ret)
  		goto err_del_dev;
  
@@ -2734,7 +2416,7 @@
  
  	return 0;
  
-@@ -2716,13 +3389,268 @@ EXPORT_SYMBOL_GPL(i3c_master_register);
+@@ -2858,13 +3392,274 @@ EXPORT_SYMBOL_GPL(i3c_master_register);
   */
  void i3c_master_unregister(struct i3c_master_controller *master)
  {
@@ -2926,6 +2608,12 @@
 +	master->dev.coherent_dma_mask = parent->coherent_dma_mask;
 +	master->dev.dma_parms = parent->dma_parms;
 +
++	master->wq = alloc_workqueue("%s", 0, 0, dev_name(parent));
++	if (!master->wq) {
++		ret = -ENOMEM;
++		goto err_put_device;
++	}
++
 +	ret = device_add(&master->dev);
 +	if (ret)
 +		goto err_put_device;
@@ -3003,7 +2691,7 @@
  int i3c_dev_setdasa_locked(struct i3c_dev_desc *dev)
  {
  	struct i3c_master_controller *master;
-@@ -2742,6 +3670,56 @@ int i3c_dev_setdasa_locked(struct i3c_dev_desc *dev)
+@@ -2884,6 +3679,56 @@ int i3c_dev_setdasa_locked(struct i3c_dev_desc *dev)
  						dev->boardinfo->init_dyn_addr);
  }
  
@@ -3060,7 +2748,7 @@
  int i3c_dev_do_priv_xfers_locked(struct i3c_dev_desc *dev,
  				 struct i3c_priv_xfer *xfers,
  				 int nxfers)
-@@ -2755,10 +3733,81 @@ int i3c_dev_do_priv_xfers_locked(struct i3c_dev_desc *dev,
+@@ -2897,10 +3742,81 @@ int i3c_dev_do_priv_xfers_locked(struct i3c_dev_desc *dev,
  	if (!master || !xfers)
  		return -EINVAL;
  
@@ -3145,7 +2833,7 @@
  }
  
  int i3c_dev_disable_ibi_locked(struct i3c_dev_desc *dev)
-@@ -2815,6 +3864,12 @@ int i3c_dev_request_ibi_locked(struct i3c_dev_desc *dev,
+@@ -2957,6 +3873,12 @@ int i3c_dev_request_ibi_locked(struct i3c_dev_desc *dev,
  	if (!ibi)
  		return -ENOMEM;
  
@@ -3158,7 +2846,7 @@
  	atomic_set(&ibi->pending_ibis, 0);
  	init_completion(&ibi->all_ibis_handled);
  	ibi->handler = req->handler;
-@@ -2842,10 +3897,47 @@ void i3c_dev_free_ibi_locked(struct i3c_dev_desc *dev)
+@@ -2984,10 +3906,47 @@ void i3c_dev_free_ibi_locked(struct i3c_dev_desc *dev)
  		WARN_ON(i3c_dev_disable_ibi_locked(dev));
  
  	master->ops->free_ibi(dev);
@@ -3862,2303 +3550,6 @@
  	return dw_i3c_common_probe(&i3c->dw, pdev);
  }
  
-diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c
-index 235235613..aac8f6bae 100644
---- a/drivers/i3c/master/dw-i3c-master.c
-+++ b/drivers/i3c/master/dw-i3c-master.c
-@@ -6,11 +6,13 @@
-  */
- 
- #include <linux/bitops.h>
-+#include <linux/bitfield.h>
- #include <linux/clk.h>
- #include <linux/completion.h>
- #include <linux/err.h>
- #include <linux/errno.h>
- #include <linux/i3c/master.h>
-+#include <linux/i3c/target.h>
- #include <linux/interrupt.h>
- #include <linux/ioport.h>
- #include <linux/iopoll.h>
-@@ -20,31 +22,50 @@
- #include <linux/platform_device.h>
- #include <linux/reset.h>
- #include <linux/slab.h>
-+#include <dt-bindings/i3c/i3c.h>
- 
- #include "dw-i3c-master.h"
- 
- #define DEVICE_CTRL			0x0
- #define DEV_CTRL_ENABLE			BIT(31)
- #define DEV_CTRL_RESUME			BIT(30)
-+#define DEV_CTRL_ABORT			BIT(29)
-+#define DEV_CTRL_IBI_PAYLOAD_EN		BIT(9)
- #define DEV_CTRL_HOT_JOIN_NACK		BIT(8)
- #define DEV_CTRL_I2C_SLAVE_PRESENT	BIT(7)
-+#define DEV_CTRL_IBA_INCLUDE		BIT(0)
- 
- #define DEVICE_ADDR			0x4
- #define DEV_ADDR_DYNAMIC_ADDR_VALID	BIT(31)
--#define DEV_ADDR_DYNAMIC(x)		(((x) << 16) & GENMASK(22, 16))
-+#define DEV_ADDR_DYNAMIC		GENMASK(22, 16)
- 
- #define HW_CAPABILITY			0x8
-+#define HW_CAP_SLV_HJ			BIT(18)
-+#define HW_CAP_HDR_TS			BIT(4)
-+#define HW_CAP_HDR_DDR			BIT(3)
- #define COMMAND_QUEUE_PORT		0xc
- #define COMMAND_PORT_TOC		BIT(30)
- #define COMMAND_PORT_READ_TRANSFER	BIT(28)
- #define COMMAND_PORT_SDAP		BIT(27)
- #define COMMAND_PORT_ROC		BIT(26)
-+#define COMMAND_PORT_DBP(x)		((x) << 25)
- #define COMMAND_PORT_SPEED(x)		(((x) << 21) & GENMASK(23, 21))
-+#define   SPEED_I3C_SDR0		0x0
-+#define   SPEED_I3C_SDR1		0x1
-+#define   SPEED_I3C_SDR2		0x2
-+#define   SPEED_I3C_SDR3		0x3
-+#define   SPEED_I3C_SDR4		0x4
-+#define   SPEED_I3C_HDR_TS		0x5
-+#define   SPEED_I3C_HDR_DDR		0x6
-+#define   SPEED_I3C_I2C_FM		0x7
-+#define   SPEED_I2C_FM			0x0
-+#define   SPEED_I2C_FMP			0x1
- #define COMMAND_PORT_DEV_INDEX(x)	(((x) << 16) & GENMASK(20, 16))
- #define COMMAND_PORT_CP			BIT(15)
- #define COMMAND_PORT_CMD(x)		(((x) << 7) & GENMASK(14, 7))
- #define COMMAND_PORT_TID(x)		(((x) << 3) & GENMASK(6, 3))
- 
-+#define COMMAND_PORT_ARG_DBP(x)		(((x) << 8) & GENMASK(15, 8))
- #define COMMAND_PORT_ARG_DATA_LEN(x)	(((x) << 16) & GENMASK(31, 16))
- #define COMMAND_PORT_ARG_DATA_LEN_MAX	65536
- #define COMMAND_PORT_TRANSFER_ARG	0x01
-@@ -72,10 +93,15 @@
- #define RESPONSE_ERROR_TRANSF_ABORT	8
- #define RESPONSE_ERROR_I2C_W_NACK_ERR	9
- #define RESPONSE_PORT_TID(x)		(((x) & GENMASK(27, 24)) >> 24)
-+#define   TID_TARGET_IBI		0b0001
-+#define   TID_TARGET_RD_DATA		0b0010
-+#define   TID_TARGET_MASTER_WR_DATA	0b1000
-+#define   TID_TARGET_MASTER_DEFSLVS	0b1111
- #define RESPONSE_PORT_DATA_LEN(x)	((x) & GENMASK(15, 0))
- 
- #define RX_TX_DATA_PORT			0x14
- #define IBI_QUEUE_STATUS		0x18
-+#define IBI_QUEUE_STATUS_RSP_NACK	BIT(31)
- #define IBI_QUEUE_STATUS_IBI_ID(x)	(((x) & GENMASK(15, 8)) >> 8)
- #define IBI_QUEUE_STATUS_DATA_LEN(x)	((x) & GENMASK(7, 0))
- #define IBI_QUEUE_IBI_ADDR(x)		(IBI_QUEUE_STATUS_IBI_ID(x) >> 1)
-@@ -96,7 +122,8 @@
- #define QUEUE_THLD_CTRL_RESP_BUF(x)	(((x) - 1) << 8)
- 
- #define DATA_BUFFER_THLD_CTRL		0x20
--#define DATA_BUFFER_THLD_CTRL_RX_BUF	GENMASK(11, 8)
-+#define DATA_BUFFER_THLD_TX_START	GENMASK(18, 16)
-+#define DATA_BUFFER_THLD_CTRL_RX_BUF	GENMASK(10, 8)
- 
- #define IBI_QUEUE_CTRL			0x24
- #define IBI_MR_REQ_REJECT		0x2C
-@@ -104,14 +131,29 @@
- #define IBI_REQ_REJECT_ALL		GENMASK(31, 0)
- 
- #define RESET_CTRL			0x34
-+#define RESET_CTRL_BUS			BIT(31)
-+#define RESET_CTRL_BUS_RESET_TYPE	GENMASK(30, 29)
-+#define   BUS_RESET_TYPE_EXIT		0b00
-+#define   BUS_RESET_TYPE_SCL_LOW	0b11
- #define RESET_CTRL_IBI_QUEUE		BIT(5)
- #define RESET_CTRL_RX_FIFO		BIT(4)
- #define RESET_CTRL_TX_FIFO		BIT(3)
- #define RESET_CTRL_RESP_QUEUE		BIT(2)
- #define RESET_CTRL_CMD_QUEUE		BIT(1)
- #define RESET_CTRL_SOFT			BIT(0)
-+#define RESET_CTRL_XFER_QUEUES		(RESET_CTRL_RX_FIFO |                 \
-+					 RESET_CTRL_TX_FIFO |                 \
-+					 RESET_CTRL_RESP_QUEUE |              \
-+					 RESET_CTRL_CMD_QUEUE)
-+#define RESET_CTRL_QUEUES		(RESET_CTRL_IBI_QUEUE |               \
-+					 RESET_CTRL_XFER_QUEUES)
- 
- #define SLV_EVENT_CTRL			0x38
-+#define   SLV_EVENT_CTRL_MWL_UPD	BIT(7)
-+#define   SLV_EVENT_CTRL_MRL_UPD	BIT(6)
-+#define   SLV_EVENT_CTRL_HJ_REQ		BIT(3)
-+#define   SLV_EVENT_CTRL_SIR_EN		BIT(0)
-+
- #define INTR_STATUS			0x3c
- #define INTR_STATUS_EN			0x40
- #define INTR_SIGNAL_EN			0x44
-@@ -146,6 +188,13 @@
- #define INTR_MASTER_MASK		(INTR_TRANSFER_ERR_STAT |	\
- 					 INTR_RESP_READY_STAT)
- 
-+#define INTR_TARGET_MASK		(INTR_READ_REQ_RECV_STAT |	\
-+					INTR_RESP_READY_STAT |		\
-+					INTR_IBI_UPDATED_STAT  |	\
-+					INTR_TRANSFER_ERR_STAT |	\
-+					INTR_CCC_UPDATED_STAT |         \
-+					INTR_DYN_ADDR_ASSGN_STAT)
-+
- #define QUEUE_STATUS_LEVEL		0x4c
- #define QUEUE_STATUS_IBI_STATUS_CNT(x)	(((x) & GENMASK(28, 24)) >> 24)
- #define QUEUE_STATUS_IBI_BUF_BLR(x)	(((x) & GENMASK(23, 16)) >> 16)
-@@ -156,6 +205,15 @@
- #define DATA_BUFFER_STATUS_LEVEL_TX(x)	((x) & GENMASK(7, 0))
- 
- #define PRESENT_STATE			0x54
-+#define   CM_TFR_ST_STS			GENMASK(21, 16)
-+#define     CM_TFR_ST_STS_HALT		0x13
-+#define   CM_TFR_STS			GENMASK(13, 8)
-+#define     CM_TFR_STS_MASTER_SERV_IBI	0xe
-+#define     CM_TFR_STS_MASTER_HALT	0xf
-+#define     CM_TFR_STS_SLAVE_HALT	0x6
-+#define   SDA_LINE_SIGNAL_LEVEL		BIT(1)
-+#define   SCL_LINE_SIGNAL_LEVEL		BIT(0)
-+
- #define CCC_DEVICE_STATUS		0x58
- #define DEVICE_ADDR_TABLE_POINTER	0x5c
- #define DEVICE_ADDR_TABLE_DEPTH(x)	(((x) & GENMASK(31, 16)) >> 16)
-@@ -163,27 +221,46 @@
- 
- #define DEV_CHAR_TABLE_POINTER		0x60
- #define VENDOR_SPECIFIC_REG_POINTER	0x6c
-+#define SLV_MIPI_ID_VALUE		0x70
- #define SLV_PID_VALUE			0x74
-+#define SLV_PID_HI(x)			(((x) >> 32) & GENMASK(15, 0))
-+#define SLV_PID_LO(x)			((x) & GENMASK(31, 0))
- #define SLV_CHAR_CTRL			0x78
-+#define   SLV_DCR			GENMASK(15, 8)
-+#define   SLV_BCR			GENMASK(7, 0)
-+#define     SLV_BCR_DEVICE_ROLE		GENMASK(7, 6)
-+
- #define SLV_MAX_LEN			0x7c
-+#define SLV_MAX_RD_LEN(x)		(((x) & GENMASK(31, 16)) >> 16)
-+#define SLV_MAX_WR_LEN(x)		((x) & GENMASK(15, 0))
-+
- #define MAX_READ_TURNAROUND		0x80
- #define MAX_DATA_SPEED			0x84
- #define SLV_DEBUG_STATUS		0x88
- #define SLV_INTR_REQ			0x8c
-+#define SLV_INTR_REQ_IBI_STS(x)		(((x) & GENMASK(9, 8)) >> 8)
-+#define IBI_STS_ACCEPTED		0x01
-+#define IBI_STS_NOT_ATTEMPTED		0x11
-+
- #define DEVICE_CTRL_EXTENDED		0xb0
-+#define DEVICE_CTRL_EXTENDED_MODE_MASK	GENMASK(1, 0)
-+#define DEVICE_CTRL_EXTENDED_MODE(x)	((x) & DEVICE_CTRL_EXTENDED_MODE_MASK)
-+#define DEV_OPERATION_MODE_CONTROLLER	0x00
-+#define DEV_OPERATION_MODE_TARGET	0x01
-+
- #define SCL_I3C_OD_TIMING		0xb4
- #define SCL_I3C_PP_TIMING		0xb8
--#define SCL_I3C_TIMING_HCNT(x)		(((x) << 16) & GENMASK(23, 16))
--#define SCL_I3C_TIMING_LCNT(x)		((x) & GENMASK(7, 0))
--#define SCL_I3C_TIMING_CNT_MIN		5
-+#define   SCL_I3C_TIMING_HCNT		GENMASK(23, 16)
-+#define   SCL_I3C_TIMING_LCNT		GENMASK(7, 0)
-+#define     SCL_I3C_TIMING_CNT_MIN	5
- 
- #define SCL_I2C_FM_TIMING		0xbc
--#define SCL_I2C_FM_TIMING_HCNT(x)	(((x) << 16) & GENMASK(31, 16))
--#define SCL_I2C_FM_TIMING_LCNT(x)	((x) & GENMASK(15, 0))
-+#define   SCL_I2C_FM_TIMING_HCNT	GENMASK(31, 16)
-+#define   SCL_I2C_FM_TIMING_LCNT	GENMASK(15, 0)
- 
- #define SCL_I2C_FMP_TIMING		0xc0
--#define SCL_I2C_FMP_TIMING_HCNT(x)	(((x) << 16) & GENMASK(23, 16))
--#define SCL_I2C_FMP_TIMING_LCNT(x)	((x) & GENMASK(15, 0))
-+#define   SCL_I2C_FMP_TIMING_HCNT	GENMASK(23, 16)
-+#define   SCL_I2C_FMP_TIMING_LCNT	GENMASK(15, 0)
- 
- #define SCL_EXT_LCNT_TIMING		0xc8
- #define SCL_EXT_LCNT_4(x)		(((x) << 24) & GENMASK(31, 24))
-@@ -192,32 +269,53 @@
- #define SCL_EXT_LCNT_1(x)		((x) & GENMASK(7, 0))
- 
- #define SCL_EXT_TERMN_LCNT_TIMING	0xcc
-+#define SDA_HOLD_SWITCH_DLY_TIMING	0xd0
-+#define   SDA_TX_HOLD			GENMASK(18, 16)
-+#define     SDA_TX_HOLD_MIN		0b001
-+#define     SDA_TX_HOLD_MAX		0b111
- #define BUS_FREE_TIMING			0xd4
--#define BUS_I3C_MST_FREE(x)		((x) & GENMASK(15, 0))
-+#define   BUS_AVAIL_TIME		GENMASK(31, 16)
-+#define     MAX_BUS_AVAIL_CNT		0xffffU
-+#define   BUS_I3C_MST_FREE		GENMASK(15, 0)
- 
- #define BUS_IDLE_TIMING			0xd8
-+#define SCL_LOW_MST_EXT_TIMEOUT		0xdc
- #define I3C_VER_ID			0xe0
- #define I3C_VER_TYPE			0xe4
- #define EXTENDED_CAPABILITY		0xe8
- #define SLAVE_CONFIG			0xec
- 
--#define DEV_ADDR_TABLE_IBI_MDB		BIT(12)
--#define DEV_ADDR_TABLE_SIR_REJECT	BIT(13)
- #define DEV_ADDR_TABLE_LEGACY_I2C_DEV	BIT(31)
--#define DEV_ADDR_TABLE_DYNAMIC_ADDR(x)	(((x) << 16) & GENMASK(23, 16))
--#define DEV_ADDR_TABLE_STATIC_ADDR(x)	((x) & GENMASK(6, 0))
-+#define DEV_ADDR_TABLE_DYNAMIC_ADDR	GENMASK(23, 16)
-+#define DEV_ADDR_TABLE_MR_REJECT	BIT(14)
-+#define DEV_ADDR_TABLE_SIR_REJECT	BIT(13)
-+#define DEV_ADDR_TABLE_IBI_MDB		BIT(12)
-+#define DEV_ADDR_TABLE_STATIC_ADDR	GENMASK(6, 0)
- #define DEV_ADDR_TABLE_LOC(start, idx)	((start) + ((idx) << 2))
- 
- #define I3C_BUS_SDR1_SCL_RATE		8000000
- #define I3C_BUS_SDR2_SCL_RATE		6000000
- #define I3C_BUS_SDR3_SCL_RATE		4000000
- #define I3C_BUS_SDR4_SCL_RATE		2000000
-+#define I3C_BUS_I2C_STD_SCL_RATE	100000
-+#define I3C_BUS_I2C_STD_TLOW_MIN_NS	4700
-+#define I3C_BUS_I2C_STD_THIGH_MIN_NS	4000
-+#define I3C_BUS_I2C_STD_TR_MAX_NS	1000
-+#define I3C_BUS_I2C_STD_TF_MAX_NS	300
- #define I3C_BUS_I2C_FM_TLOW_MIN_NS	1300
-+#define I3C_BUS_I2C_FM_THIGH_MIN_NS	600
-+#define I3C_BUS_I2C_FM_TR_MAX_NS	300
-+#define I3C_BUS_I2C_FM_TF_MAX_NS	300
- #define I3C_BUS_I2C_FMP_TLOW_MIN_NS	500
-+#define I3C_BUS_I2C_FMP_THIGH_MIN_NS	260
-+#define I3C_BUS_I2C_FMP_TR_MAX_NS	120
-+#define I3C_BUS_I2C_FMP_TF_MAX_NS	120
- #define I3C_BUS_THIGH_MAX_NS		41
- 
- #define XFER_TIMEOUT (msecs_to_jiffies(1000))
- 
-+#define JESD403_TIMED_RESET_NS_DEF	52428800
-+
- struct dw_i3c_cmd {
- 	u32 cmd_lo;
- 	u32 cmd_hi;
-@@ -233,12 +331,7 @@ struct dw_i3c_xfer {
- 	struct completion comp;
- 	int ret;
- 	unsigned int ncmds;
--	struct dw_i3c_cmd cmds[];
--};
--
--struct dw_i3c_i2c_dev_data {
--	u8 index;
--	struct i3c_generic_ibi_pool *ibi_pool;
-+	struct dw_i3c_cmd cmds[] __counted_by(ncmds);
- };
- 
- static u8 even_parity(u8 p)
-@@ -280,6 +373,11 @@ static bool dw_i3c_master_supports_ccc_cmd(struct i3c_master_controller *m,
- 	case I3C_CCC_GETSTATUS:
- 	case I3C_CCC_GETMXDS:
- 	case I3C_CCC_GETHDRCAP:
-+	case I3C_CCC_SETAASA:
-+	case I3C_CCC_SETHID:
-+	case I3C_CCC_DBGACTION(true):
-+	case I3C_CCC_DBGACTION(false):
-+	case I3C_CCC_DBGOPCODE:
- 		return true;
- 	default:
- 		return false;
-@@ -292,16 +390,123 @@ to_dw_i3c_master(struct i3c_master_controller *master)
- 	return container_of(master, struct dw_i3c_master, base);
- }
- 
-+static void dw_i3c_master_set_iba(struct dw_i3c_master *master, bool enable)
-+{
-+	u32 reg;
-+
-+	reg = readl(master->regs + DEVICE_CTRL);
-+	reg &= ~DEV_CTRL_IBA_INCLUDE;
-+	if (enable)
-+		reg |= DEV_CTRL_IBA_INCLUDE;
-+
-+	writel(reg, master->regs + DEVICE_CTRL);
-+}
-+
- static void dw_i3c_master_disable(struct dw_i3c_master *master)
- {
-+	if (!(readl(master->regs + DEVICE_CTRL) & DEV_CTRL_ENABLE))
-+		return;
-+
-+	if (master->base.target) {
-+		master->platform_ops->enter_sw_mode(master);
-+		master->platform_ops->gen_internal_stop(master);
-+	}
-+
- 	writel(readl(master->regs + DEVICE_CTRL) & ~DEV_CTRL_ENABLE,
- 	       master->regs + DEVICE_CTRL);
-+
-+	if (master->base.target) {
-+		master->platform_ops->toggle_scl_in(master, 8);
-+		if (readl(master->regs + DEVICE_CTRL) & DEV_CTRL_ENABLE) {
-+			dev_warn(&master->base.dev,
-+				 "Failed to disable controller");
-+			master->platform_ops->exit_sw_mode(master);
-+			return;
-+		}
-+		master->platform_ops->exit_sw_mode(master);
-+	}
- }
- 
- static void dw_i3c_master_enable(struct dw_i3c_master *master)
- {
-+	u32 wait_enable_ns, clk_count;
-+
-+	if (master->base.target) {
-+		master->platform_ops->enter_sw_mode(master);
-+		master->platform_ops->gen_internal_stop(master);
-+	}
-+
- 	writel(readl(master->regs + DEVICE_CTRL) | DEV_CTRL_ENABLE,
- 	       master->regs + DEVICE_CTRL);
-+
-+	if (master->base.target) {
-+		clk_count = FIELD_GET(BUS_AVAIL_TIME,
-+				      readl(master->regs + BUS_FREE_TIMING));
-+		clk_count = max(clk_count, readl(master->regs + BUS_IDLE_TIMING));
-+		wait_enable_ns = master->timing.core_period * clk_count;
-+		udelay(DIV_ROUND_UP(wait_enable_ns, NSEC_PER_USEC));
-+
-+		master->platform_ops->toggle_scl_in(master, 8);
-+		if (!(readl(master->regs + DEVICE_CTRL) & DEV_CTRL_ENABLE)) {
-+			dev_warn(&master->base.dev,
-+				 "Failed to enable controller");
-+			master->platform_ops->exit_sw_mode(master);
-+			return;
-+		}
-+
-+		master->platform_ops->gen_internal_stop(master);
-+		master->platform_ops->exit_sw_mode(master);
-+	}
-+}
-+
-+static int dw_i3c_master_exit_halt(struct dw_i3c_master *master)
-+{
-+	u32 status;
-+	u32 halt_state = CM_TFR_STS_MASTER_HALT;
-+	int ret;
-+
-+	if (master->base.target)
-+		halt_state = CM_TFR_STS_SLAVE_HALT;
-+
-+	writel(readl(master->regs + DEVICE_CTRL) | DEV_CTRL_RESUME,
-+	       master->regs + DEVICE_CTRL);
-+
-+	ret = readl_poll_timeout_atomic(master->regs + PRESENT_STATE, status,
-+					FIELD_GET(CM_TFR_STS, status) != halt_state,
-+					10, 1000000);
-+
-+	if (ret)
-+		dev_err(&master->base.dev,
-+			"Exit halt state failed: %d %#x %#x\n", ret,
-+			readl(master->regs + PRESENT_STATE),
-+			readl(master->regs + QUEUE_STATUS_LEVEL));
-+	return ret;
-+}
-+
-+static int dw_i3c_master_enter_halt(struct dw_i3c_master *master, bool by_sw)
-+{
-+	u32 status;
-+	u32 halt_state = CM_TFR_STS_MASTER_HALT;
-+	int ret;
-+
-+	if (master->base.target)
-+		halt_state = CM_TFR_STS_SLAVE_HALT;
-+
-+	if (by_sw)
-+		writel(readl(master->regs + DEVICE_CTRL) | DEV_CTRL_ABORT,
-+		       master->regs + DEVICE_CTRL);
-+
-+	ret = readl_poll_timeout_atomic(master->regs + PRESENT_STATE, status,
-+					FIELD_GET(CM_TFR_STS, status) == halt_state,
-+					10, 1000000);
-+
-+	if (ret)
-+		dev_err(&master->base.dev,
-+			"Enter halt state failed: %d %#x %#x\n", ret,
-+			readl(master->regs + PRESENT_STATE),
-+			readl(master->regs + QUEUE_STATUS_LEVEL));
-+
-+	return ret;
- }
- 
- static int dw_i3c_master_get_addr_pos(struct dw_i3c_master *master, u8 addr)
-@@ -481,6 +686,9 @@ static void dw_i3c_master_end_xfer_locked(struct dw_i3c_master *master, u32 isr)
- 	}
- 
- 	for (i = 0; i < nresp; i++) {
-+		if (xfer->cmds[i].error)
-+			dev_err(&master->base.dev, "xfer error: %x\n",
-+				xfer->cmds[i].error);
- 		switch (xfer->cmds[i].error) {
- 		case RESPONSE_NO_ERROR:
- 			break;
-@@ -506,9 +714,14 @@ static void dw_i3c_master_end_xfer_locked(struct dw_i3c_master *master, u32 isr)
- 	complete(&xfer->comp);
- 
- 	if (ret < 0) {
-+		/*
-+		 * The controller will enter the HALT state if an error occurs.
-+		 * Therefore, there is no need to manually halt the controller
-+		 * through software.
-+		 */
-+		dw_i3c_master_enter_halt(master, false);
- 		dw_i3c_master_dequeue_xfer_locked(master, xfer);
--		writel(readl(master->regs + DEVICE_CTRL) | DEV_CTRL_RESUME,
--		       master->regs + DEVICE_CTRL);
-+		dw_i3c_master_exit_halt(master);
- 	}
- 
- 	xfer = list_first_entry_or_null(&master->xferqueue.list,
-@@ -521,41 +734,76 @@ static void dw_i3c_master_end_xfer_locked(struct dw_i3c_master *master, u32 isr)
- 	dw_i3c_master_start_xfer_locked(master);
- }
- 
-+static int calc_i2c_clk(struct dw_i3c_master *master, unsigned long fscl,
-+			u16 *hcnt, u16 *lcnt)
-+{
-+	unsigned long core_rate, core_period;
-+	u32 period_cnt, margin;
-+	u32 hcnt_min, lcnt_min;
-+
-+	core_rate = master->timing.core_rate;
-+	core_period = master->timing.core_period;
-+
-+	if (fscl <= I3C_BUS_I2C_STD_SCL_RATE) {
-+		lcnt_min = DIV_ROUND_UP(I3C_BUS_I2C_STD_TLOW_MIN_NS +
-+						I3C_BUS_I2C_STD_TF_MAX_NS,
-+					core_period);
-+		hcnt_min = DIV_ROUND_UP(I3C_BUS_I2C_STD_THIGH_MIN_NS +
-+						I3C_BUS_I2C_STD_TR_MAX_NS,
-+					core_period);
-+	} else if (fscl <= I3C_BUS_I2C_FM_SCL_RATE) {
-+		lcnt_min = DIV_ROUND_UP(I3C_BUS_I2C_FM_TLOW_MIN_NS +
-+						I3C_BUS_I2C_FM_TF_MAX_NS,
-+					core_period);
-+		hcnt_min = DIV_ROUND_UP(I3C_BUS_I2C_FM_THIGH_MIN_NS +
-+						I3C_BUS_I2C_FM_TR_MAX_NS,
-+					core_period);
-+	} else {
-+		lcnt_min = DIV_ROUND_UP(I3C_BUS_I2C_FMP_TLOW_MIN_NS +
-+						I3C_BUS_I2C_FMP_TF_MAX_NS,
-+					core_period);
-+		hcnt_min = DIV_ROUND_UP(I3C_BUS_I2C_FMP_THIGH_MIN_NS +
-+						I3C_BUS_I2C_FMP_TR_MAX_NS,
-+					core_period);
-+	}
-+
-+	period_cnt = DIV_ROUND_UP(core_rate, fscl);
-+	margin = (period_cnt - hcnt_min - lcnt_min) >> 1;
-+	*lcnt = lcnt_min + margin;
-+	*hcnt = max(period_cnt - *lcnt, hcnt_min);
-+
-+	return 0;
-+}
-+
- static int dw_i3c_clk_cfg(struct dw_i3c_master *master)
- {
- 	unsigned long core_rate, core_period;
- 	u32 scl_timing;
- 	u8 hcnt, lcnt;
- 
--	core_rate = clk_get_rate(master->core_clk);
--	if (!core_rate)
--		return -EINVAL;
--
--	core_period = DIV_ROUND_UP(1000000000, core_rate);
--
--	hcnt = DIV_ROUND_UP(I3C_BUS_THIGH_MAX_NS, core_period) - 1;
--	if (hcnt < SCL_I3C_TIMING_CNT_MIN)
--		hcnt = SCL_I3C_TIMING_CNT_MIN;
-+	core_rate = master->timing.core_rate;
-+	core_period = master->timing.core_period;
- 
--	lcnt = DIV_ROUND_UP(core_rate, master->base.bus.scl_rate.i3c) - hcnt;
--	if (lcnt < SCL_I3C_TIMING_CNT_MIN)
--		lcnt = SCL_I3C_TIMING_CNT_MIN;
-+	if (master->timing.i3c_pp_scl_high && master->timing.i3c_pp_scl_low) {
-+		hcnt = DIV_ROUND_CLOSEST(master->timing.i3c_pp_scl_high,
-+					 core_period);
-+		lcnt = DIV_ROUND_CLOSEST(master->timing.i3c_pp_scl_low,
-+					 core_period);
-+	} else {
-+		hcnt = DIV_ROUND_UP(I3C_BUS_THIGH_MAX_NS, core_period) - 1;
-+		if (hcnt < SCL_I3C_TIMING_CNT_MIN)
-+			hcnt = SCL_I3C_TIMING_CNT_MIN;
-+
-+		lcnt = DIV_ROUND_UP(core_rate, master->base.bus.scl_rate.i3c) -
-+		       hcnt;
-+		if (lcnt < SCL_I3C_TIMING_CNT_MIN)
-+			lcnt = SCL_I3C_TIMING_CNT_MIN;
-+	}
- 
--	scl_timing = SCL_I3C_TIMING_HCNT(hcnt) | SCL_I3C_TIMING_LCNT(lcnt);
-+	scl_timing = FIELD_PREP(SCL_I3C_TIMING_HCNT, hcnt) |
-+		     FIELD_PREP(SCL_I3C_TIMING_LCNT, lcnt);
- 	writel(scl_timing, master->regs + SCL_I3C_PP_TIMING);
- 
--	/*
--	 * In pure i3c mode, MST_FREE represents tCAS. In shared mode, this
--	 * will be set up by dw_i2c_clk_cfg as tLOW.
--	 */
--	if (master->base.bus.mode == I3C_BUS_MODE_PURE)
--		writel(BUS_I3C_MST_FREE(lcnt), master->regs + BUS_FREE_TIMING);
--
--	lcnt = max_t(u8,
--		     DIV_ROUND_UP(I3C_BUS_TLOW_OD_MIN_NS, core_period), lcnt);
--	scl_timing = SCL_I3C_TIMING_HCNT(hcnt) | SCL_I3C_TIMING_LCNT(lcnt);
--	writel(scl_timing, master->regs + SCL_I3C_OD_TIMING);
--
- 	lcnt = DIV_ROUND_UP(core_rate, I3C_BUS_SDR1_SCL_RATE) - hcnt;
- 	scl_timing = SCL_EXT_LCNT_1(lcnt);
- 	lcnt = DIV_ROUND_UP(core_rate, I3C_BUS_SDR2_SCL_RATE) - hcnt;
-@@ -566,6 +814,27 @@ static int dw_i3c_clk_cfg(struct dw_i3c_master *master)
- 	scl_timing |= SCL_EXT_LCNT_4(lcnt);
- 	writel(scl_timing, master->regs + SCL_EXT_LCNT_TIMING);
- 
-+	if (master->timing.i3c_od_scl_high && master->timing.i3c_od_scl_low) {
-+		hcnt = DIV_ROUND_CLOSEST(master->timing.i3c_od_scl_high,
-+					 core_period);
-+		lcnt = DIV_ROUND_CLOSEST(master->timing.i3c_od_scl_low,
-+					 core_period);
-+	} else if (master->base.bus.context == I3C_BUS_CONTEXT_JESD403) {
-+		u16 hcnt_fmp, lcnt_fmp;
-+
-+		calc_i2c_clk(master, I3C_BUS_I2C_FM_PLUS_SCL_RATE, &hcnt_fmp,
-+			     &lcnt_fmp);
-+		hcnt = min_t(u8, hcnt_fmp, FIELD_MAX(SCL_I3C_TIMING_HCNT));
-+		lcnt = min_t(u8, lcnt_fmp, FIELD_MAX(SCL_I3C_TIMING_LCNT));
-+	} else {
-+		lcnt = max_t(u8,
-+			     DIV_ROUND_UP(I3C_BUS_TLOW_OD_MIN_NS, core_period),
-+			     lcnt);
-+	}
-+	scl_timing = FIELD_PREP(SCL_I3C_TIMING_HCNT, hcnt) |
-+		     FIELD_PREP(SCL_I3C_TIMING_LCNT, lcnt);
-+	writel(scl_timing, master->regs + SCL_I3C_OD_TIMING);
-+
- 	return 0;
- }
- 
-@@ -575,58 +844,162 @@ static int dw_i2c_clk_cfg(struct dw_i3c_master *master)
- 	u16 hcnt, lcnt;
- 	u32 scl_timing;
- 
--	core_rate = clk_get_rate(master->core_clk);
--	if (!core_rate)
--		return -EINVAL;
--
--	core_period = DIV_ROUND_UP(1000000000, core_rate);
-+	core_rate = master->timing.core_rate;
-+	core_period = master->timing.core_period;
- 
--	lcnt = DIV_ROUND_UP(I3C_BUS_I2C_FMP_TLOW_MIN_NS, core_period);
--	hcnt = DIV_ROUND_UP(core_rate, I3C_BUS_I2C_FM_PLUS_SCL_RATE) - lcnt;
--	scl_timing = SCL_I2C_FMP_TIMING_HCNT(hcnt) |
--		     SCL_I2C_FMP_TIMING_LCNT(lcnt);
-+	calc_i2c_clk(master, I3C_BUS_I2C_FM_PLUS_SCL_RATE, &hcnt, &lcnt);
-+	scl_timing = FIELD_PREP(SCL_I2C_FMP_TIMING_HCNT, hcnt) |
-+		     FIELD_PREP(SCL_I2C_FMP_TIMING_LCNT, lcnt);
- 	writel(scl_timing, master->regs + SCL_I2C_FMP_TIMING);
- 
--	lcnt = DIV_ROUND_UP(I3C_BUS_I2C_FM_TLOW_MIN_NS, core_period);
--	hcnt = DIV_ROUND_UP(core_rate, I3C_BUS_I2C_FM_SCL_RATE) - lcnt;
--	scl_timing = SCL_I2C_FM_TIMING_HCNT(hcnt) |
--		     SCL_I2C_FM_TIMING_LCNT(lcnt);
-+	calc_i2c_clk(master, master->base.bus.scl_rate.i2c, &hcnt, &lcnt);
-+	scl_timing = FIELD_PREP(SCL_I2C_FM_TIMING_HCNT, hcnt) |
-+		     FIELD_PREP(SCL_I2C_FM_TIMING_LCNT, lcnt);
- 	writel(scl_timing, master->regs + SCL_I2C_FM_TIMING);
- 
--	writel(BUS_I3C_MST_FREE(lcnt), master->regs + BUS_FREE_TIMING);
--	writel(readl(master->regs + DEVICE_CTRL) | DEV_CTRL_I2C_SLAVE_PRESENT,
--	       master->regs + DEVICE_CTRL);
-+	return 0;
-+}
-+
-+static int dw_i3c_bus_clk_cfg(struct i3c_master_controller *m)
-+{
-+	struct dw_i3c_master *master = to_dw_i3c_master(m);
-+	struct i3c_bus *bus = i3c_master_get_bus(m);
-+	int ret;
-+	u16 lcnt;
-+
-+	ret = dw_i2c_clk_cfg(master);
-+	if (ret)
-+		return ret;
-+
-+	ret = dw_i3c_clk_cfg(master);
-+	if (ret)
-+		return ret;
-+
-+	/*
-+	 * I3C register 0xd4[15:0] BUS_FREE_TIMING used to control several parameters:
-+	 * - tCAS & tCASr (tHD_STA in JESD403)
-+	 * - tCBP & tCBPr (tSU_STO in JESD403)
-+	 * - bus free time between a STOP condition and a START condition
-+	 *
-+	 * The constraints of these parameters differ in various bus contexts:
-+	 * JESD403            : BUS_FREE_TIMING = I3C OD SCL low period
-+	 * MIPI I3C, pure bus : BUS_FREE_TIMING = I3C PP SCL low period
-+	 * MIPI I3C, mixed bus: BUS_FREE_TIMING = I2C FM SCL low period
-+	 */
-+	if (bus->context == I3C_BUS_CONTEXT_JESD403) {
-+		lcnt = FIELD_GET(SCL_I3C_TIMING_LCNT,
-+				 readl(master->regs + SCL_I3C_OD_TIMING));
-+	} else {
-+		if (bus->mode == I3C_BUS_MODE_PURE) {
-+			lcnt = FIELD_GET(SCL_I3C_TIMING_LCNT,
-+					 readl(master->regs + SCL_I3C_PP_TIMING));
-+		} else {
-+			writel(readl(master->regs + DEVICE_CTRL) | DEV_CTRL_I2C_SLAVE_PRESENT,
-+			       master->regs + DEVICE_CTRL);
-+
-+			lcnt = FIELD_GET(SCL_I2C_FM_TIMING_LCNT,
-+					 readl(master->regs + SCL_I2C_FM_TIMING));
-+		}
-+	}
-+
-+	writel(FIELD_PREP(BUS_I3C_MST_FREE, lcnt), master->regs + BUS_FREE_TIMING);
-+
-+	return 0;
-+}
-+
-+static int dw_i3c_target_bus_init(struct i3c_master_controller *m)
-+{
-+	struct dw_i3c_master *master = to_dw_i3c_master(m);
-+	struct i3c_dev_desc *desc = master->base.this;
-+	void *rx_buf;
-+	u32 reg;
-+	int ret;
-+
-+	ret = dw_i3c_bus_clk_cfg(m);
-+	if (ret)
-+		return ret;
-+
-+	reg = readl(master->regs + SLV_MAX_LEN);
-+	/*
-+	 * Set max private write length value based on read-only register.
-+	 * TODO: Handle updates after receiving SETMWL CCC.
-+	 */
-+	master->target.rx.max_len = SLV_MAX_WR_LEN(reg);
-+
-+	rx_buf = kzalloc(master->target.rx.max_len, GFP_KERNEL);
-+	if (!rx_buf)
-+		return -ENOMEM;
-+
-+	master->target.rx.buf = rx_buf;
-+
-+	dw_i3c_master_disable(master);
-+
-+	reg = readl(master->regs + QUEUE_THLD_CTRL) & ~QUEUE_THLD_CTRL_RESP_BUF_MASK;
-+	writel(reg, master->regs + QUEUE_THLD_CTRL);
-+
-+	reg = readl(master->regs + DATA_BUFFER_THLD_CTRL) & ~DATA_BUFFER_THLD_CTRL_RX_BUF;
-+	writel(reg, master->regs + DATA_BUFFER_THLD_CTRL);
-+
-+	writel(INTR_ALL, master->regs + INTR_STATUS);
-+	writel(INTR_TARGET_MASK, master->regs + INTR_STATUS_EN);
-+	writel(INTR_TARGET_MASK, master->regs + INTR_SIGNAL_EN);
-+
-+	reg = readl(master->regs + DEVICE_CTRL_EXTENDED) & ~DEVICE_CTRL_EXTENDED_MODE_MASK;
-+	reg |= DEVICE_CTRL_EXTENDED_MODE(DEV_OPERATION_MODE_TARGET);
-+	writel(reg, master->regs + DEVICE_CTRL_EXTENDED);
-+
-+	writel(SLV_PID_LO(desc->info.pid), master->regs + SLV_PID_VALUE);
-+	writel(SLV_PID_HI(desc->info.pid), master->regs + SLV_MIPI_ID_VALUE);
-+
-+	reg = readl(master->regs + SLV_CHAR_CTRL);
-+	reg &= ~(SLV_DCR | SLV_BCR_DEVICE_ROLE);
-+	reg |= FIELD_PREP(SLV_DCR, desc->info.dcr) |
-+	       FIELD_PREP(SLV_BCR_DEVICE_ROLE, 0);
-+	writel(reg, master->regs + SLV_CHAR_CTRL);
-+
-+	reg = FIELD_GET(SLV_BCR, reg);
-+	if (reg & I3C_BCR_IBI_PAYLOAD) {
-+		reg = readl(master->regs + DEVICE_CTRL);
-+		reg |= DEV_CTRL_IBI_PAYLOAD_EN;
-+		writel(reg, master->regs + DEVICE_CTRL);
-+	}
-+
-+	reg = readl(master->regs + BUS_FREE_TIMING) |
-+	      FIELD_PREP(BUS_AVAIL_TIME, MAX_BUS_AVAIL_CNT);
-+	writel(reg, master->regs + BUS_FREE_TIMING);
-+	/* Clear Hot-join request before enabling the controller*/
-+	writel(0, master->regs + SLV_EVENT_CTRL);
-+
-+
-+	dw_i3c_master_enable(master);
- 
- 	return 0;
- }
- 
-+static void dw_i3c_target_bus_cleanup(struct i3c_master_controller *m)
-+{
-+	struct dw_i3c_master *master = to_dw_i3c_master(m);
-+
-+	dw_i3c_master_disable(master);
-+	kfree(master->target.rx.buf);
-+}
-+
- static int dw_i3c_master_bus_init(struct i3c_master_controller *m)
- {
- 	struct dw_i3c_master *master = to_dw_i3c_master(m);
--	struct i3c_bus *bus = i3c_master_get_bus(m);
- 	struct i3c_device_info info = { };
--	u32 thld_ctrl;
-+	u32 thld_ctrl, caps;
- 	int ret;
- 
- 	ret = master->platform_ops->init(master);
- 	if (ret)
- 		return ret;
- 
--	switch (bus->mode) {
--	case I3C_BUS_MODE_MIXED_FAST:
--	case I3C_BUS_MODE_MIXED_LIMITED:
--		ret = dw_i2c_clk_cfg(master);
--		if (ret)
--			return ret;
--		fallthrough;
--	case I3C_BUS_MODE_PURE:
--		ret = dw_i3c_clk_cfg(master);
--		if (ret)
--			return ret;
--		break;
--	default:
--		return -EINVAL;
--	}
-+	spin_lock_init(&master->devs_lock);
-+
-+	ret = dw_i3c_bus_clk_cfg(m);
-+	if (ret)
-+		return ret;
- 
- 	thld_ctrl = readl(master->regs + QUEUE_THLD_CTRL);
- 	thld_ctrl &= ~(QUEUE_THLD_CTRL_RESP_BUF_MASK |
-@@ -648,12 +1021,22 @@ static int dw_i3c_master_bus_init(struct i3c_master_controller *m)
- 	if (ret < 0)
- 		return ret;
- 
--	writel(DEV_ADDR_DYNAMIC_ADDR_VALID | DEV_ADDR_DYNAMIC(ret),
-+	writel(DEV_ADDR_DYNAMIC_ADDR_VALID | FIELD_PREP(DEV_ADDR_DYNAMIC, ret),
- 	       master->regs + DEVICE_ADDR);
- 
- 	memset(&info, 0, sizeof(info));
- 	info.dyn_addr = ret;
- 
-+	caps =  readl(master->regs + HW_CAPABILITY);
-+	if (caps & HW_CAP_HDR_DDR)
-+		info.hdr_cap |= BIT(I3C_HDR_DDR);
-+	if (caps & HW_CAP_HDR_TS) {
-+		if (readl(master->regs + DEVICE_CTRL) | DEV_CTRL_I2C_SLAVE_PRESENT)
-+			info.hdr_cap |= BIT(I3C_HDR_TSL);
-+		else
-+			info.hdr_cap |= BIT(I3C_HDR_TSP);
-+	}
-+
- 	ret = i3c_master_set_info(&master->base, &info);
- 	if (ret)
- 		return ret;
-@@ -677,17 +1060,40 @@ static void dw_i3c_master_bus_cleanup(struct i3c_master_controller *m)
- 	dw_i3c_master_disable(master);
- }
- 
-+static int dw_i3c_master_bus_reset(struct i3c_master_controller *m)
-+{
-+	struct dw_i3c_master *master = to_dw_i3c_master(m);
-+	int ret;
-+
-+	ret = dw_i3c_master_enter_halt(master, true);
-+	if (ret) {
-+		dev_err(&master->base.dev,
-+			"Failed to perform timed reset! Controller state %08x\n",
-+			readl(master->regs + PRESENT_STATE));
-+		return -EBUSY;
-+	}
-+
-+	master->platform_ops->gen_target_reset_pattern(master);
-+	dw_i3c_master_exit_halt(master);
-+
-+	return 0;
-+}
-+
- static int dw_i3c_ccc_set(struct dw_i3c_master *master,
- 			  struct i3c_ccc_cmd *ccc)
- {
- 	struct dw_i3c_xfer *xfer;
- 	struct dw_i3c_cmd *cmd;
-+	u32 sda_lvl_pre, sda_lvl_post;
- 	int ret, pos = 0;
- 
- 	if (ccc->id & I3C_CCC_DIRECT) {
--		pos = dw_i3c_master_get_addr_pos(master, ccc->dests[0].addr);
-+		pos = master->platform_ops->get_addr_pos(master,
-+							 ccc->dests[0].addr);
- 		if (pos < 0)
- 			return pos;
-+
-+		master->platform_ops->flush_dat(master, ccc->dests[0].addr);
- 	}
- 
- 	xfer = dw_i3c_master_alloc_xfer(master, 1);
-@@ -699,17 +1105,33 @@ static int dw_i3c_ccc_set(struct dw_i3c_master *master,
- 	cmd->tx_len = ccc->dests[0].payload.len;
- 
- 	cmd->cmd_hi = COMMAND_PORT_ARG_DATA_LEN(ccc->dests[0].payload.len) |
--		      COMMAND_PORT_TRANSFER_ARG;
-+		      COMMAND_PORT_TRANSFER_ARG | COMMAND_PORT_ARG_DBP(ccc->db);
- 
- 	cmd->cmd_lo = COMMAND_PORT_CP |
- 		      COMMAND_PORT_DEV_INDEX(pos) |
- 		      COMMAND_PORT_CMD(ccc->id) |
- 		      COMMAND_PORT_TOC |
--		      COMMAND_PORT_ROC;
-+		      COMMAND_PORT_ROC |
-+		      COMMAND_PORT_DBP(ccc->dbp);
-+
-+	if (ccc->id == I3C_CCC_SETHID || ccc->id == I3C_CCC_DEVCTRL)
-+		cmd->cmd_lo |= COMMAND_PORT_SPEED(SPEED_I3C_I2C_FM);
- 
-+	sda_lvl_pre = FIELD_GET(SDA_LINE_SIGNAL_LEVEL,
-+				readl(master->regs + PRESENT_STATE));
- 	dw_i3c_master_enqueue_xfer(master, xfer);
--	if (!wait_for_completion_timeout(&xfer->comp, XFER_TIMEOUT))
-+	if (!wait_for_completion_timeout(&xfer->comp, XFER_TIMEOUT)) {
-+		dw_i3c_master_enter_halt(master, true);
- 		dw_i3c_master_dequeue_xfer(master, xfer);
-+		sda_lvl_post = FIELD_GET(SDA_LINE_SIGNAL_LEVEL,
-+					 readl(master->regs + PRESENT_STATE));
-+		if (sda_lvl_pre == 0 && sda_lvl_post == 0) {
-+			dev_warn(&master->base.dev,
-+				 "SDA stuck low! Try to recover the bus...\n");
-+			master->platform_ops->bus_recovery(master);
-+		}
-+		dw_i3c_master_exit_halt(master);
-+	}
- 
- 	ret = xfer->ret;
- 	if (xfer->cmds[0].error == RESPONSE_ERROR_IBA_NACK)
-@@ -724,12 +1146,15 @@ static int dw_i3c_ccc_get(struct dw_i3c_master *master, struct i3c_ccc_cmd *ccc)
- {
- 	struct dw_i3c_xfer *xfer;
- 	struct dw_i3c_cmd *cmd;
-+	u32 sda_lvl_pre, sda_lvl_post;
- 	int ret, pos;
- 
--	pos = dw_i3c_master_get_addr_pos(master, ccc->dests[0].addr);
-+	pos = master->platform_ops->get_addr_pos(master, ccc->dests[0].addr);
- 	if (pos < 0)
- 		return pos;
- 
-+	master->platform_ops->flush_dat(master, ccc->dests[0].addr);
-+
- 	xfer = dw_i3c_master_alloc_xfer(master, 1);
- 	if (!xfer)
- 		return -ENOMEM;
-@@ -739,18 +1164,31 @@ static int dw_i3c_ccc_get(struct dw_i3c_master *master, struct i3c_ccc_cmd *ccc)
- 	cmd->rx_len = ccc->dests[0].payload.len;
- 
- 	cmd->cmd_hi = COMMAND_PORT_ARG_DATA_LEN(ccc->dests[0].payload.len) |
--		      COMMAND_PORT_TRANSFER_ARG;
-+		      COMMAND_PORT_TRANSFER_ARG | COMMAND_PORT_ARG_DBP(ccc->db);
- 
- 	cmd->cmd_lo = COMMAND_PORT_READ_TRANSFER |
- 		      COMMAND_PORT_CP |
- 		      COMMAND_PORT_DEV_INDEX(pos) |
- 		      COMMAND_PORT_CMD(ccc->id) |
- 		      COMMAND_PORT_TOC |
--		      COMMAND_PORT_ROC;
-+		      COMMAND_PORT_ROC |
-+		      COMMAND_PORT_DBP(ccc->dbp);
- 
-+	sda_lvl_pre = FIELD_GET(SDA_LINE_SIGNAL_LEVEL,
-+				readl(master->regs + PRESENT_STATE));
- 	dw_i3c_master_enqueue_xfer(master, xfer);
--	if (!wait_for_completion_timeout(&xfer->comp, XFER_TIMEOUT))
-+	if (!wait_for_completion_timeout(&xfer->comp, XFER_TIMEOUT)) {
-+		dw_i3c_master_enter_halt(master, true);
- 		dw_i3c_master_dequeue_xfer(master, xfer);
-+		sda_lvl_post = FIELD_GET(SDA_LINE_SIGNAL_LEVEL,
-+					 readl(master->regs + PRESENT_STATE));
-+		if (sda_lvl_pre == 0 && sda_lvl_post == 0) {
-+			dev_warn(&master->base.dev,
-+				 "SDA stuck low! Try to recover the bus...\n");
-+			master->platform_ops->bus_recovery(master);
-+		}
-+		dw_i3c_master_exit_halt(master);
-+	}
- 
- 	ret = xfer->ret;
- 	if (xfer->cmds[0].error == RESPONSE_ERROR_IBA_NACK)
-@@ -782,7 +1220,7 @@ static int dw_i3c_master_daa(struct i3c_master_controller *m)
- 	struct dw_i3c_master *master = to_dw_i3c_master(m);
- 	struct dw_i3c_xfer *xfer;
- 	struct dw_i3c_cmd *cmd;
--	u32 olddevs, newdevs;
-+	u32 olddevs, newdevs, sda_lvl_pre, sda_lvl_post;
- 	u8 p, last_addr = 0;
- 	int ret, pos;
- 
-@@ -802,7 +1240,7 @@ static int dw_i3c_master_daa(struct i3c_master_controller *m)
- 		last_addr = ret;
- 		ret |= (p << 7);
- 
--		writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(ret),
-+		writel(FIELD_PREP(DEV_ADDR_TABLE_DYNAMIC_ADDR, ret),
- 		       master->regs +
- 		       DEV_ADDR_TABLE_LOC(master->datstartaddr, pos));
- 	}
-@@ -825,9 +1263,21 @@ static int dw_i3c_master_daa(struct i3c_master_controller *m)
- 		      COMMAND_PORT_TOC |
- 		      COMMAND_PORT_ROC;
- 
-+	sda_lvl_pre = FIELD_GET(SDA_LINE_SIGNAL_LEVEL,
-+				readl(master->regs + PRESENT_STATE));
- 	dw_i3c_master_enqueue_xfer(master, xfer);
--	if (!wait_for_completion_timeout(&xfer->comp, XFER_TIMEOUT))
-+	if (!wait_for_completion_timeout(&xfer->comp, XFER_TIMEOUT)) {
-+		dw_i3c_master_enter_halt(master, true);
- 		dw_i3c_master_dequeue_xfer(master, xfer);
-+		sda_lvl_post = FIELD_GET(SDA_LINE_SIGNAL_LEVEL,
-+					 readl(master->regs + PRESENT_STATE));
-+		if (sda_lvl_pre == 0 && sda_lvl_post == 0) {
-+			dev_warn(&master->base.dev,
-+				 "SDA stuck low! Try to recover the bus...\n");
-+			master->platform_ops->bus_recovery(master);
-+		}
-+		dw_i3c_master_exit_halt(master);
-+	}
- 
- 	newdevs = GENMASK(master->maxdevs - cmd->rx_len - 1, 0);
- 	newdevs &= ~olddevs;
-@@ -835,6 +1285,16 @@ static int dw_i3c_master_daa(struct i3c_master_controller *m)
- 	for (pos = 0; pos < master->maxdevs; pos++) {
- 		if (newdevs & BIT(pos))
- 			i3c_master_add_i3c_dev_locked(m, master->devs[pos].addr);
-+
-+		/* cleanup the free HW DATs */
-+		if (master->free_pos & BIT(pos)) {
-+			u32 dat = DEV_ADDR_TABLE_SIR_REJECT |
-+				  DEV_ADDR_TABLE_MR_REJECT;
-+
-+			writel(dat,
-+			       master->regs +
-+			       DEV_ADDR_TABLE_LOC(master->datstartaddr, pos));
-+		}
- 	}
- 
- 	dw_i3c_master_free_xfer(xfer);
-@@ -851,6 +1311,7 @@ static int dw_i3c_master_priv_xfers(struct i3c_dev_desc *dev,
- 	struct dw_i3c_master *master = to_dw_i3c_master(m);
- 	unsigned int nrxwords = 0, ntxwords = 0;
- 	struct dw_i3c_xfer *xfer;
-+	u32 sda_lvl_pre, sda_lvl_post;
- 	int i, ret = 0;
- 
- 	if (!i3c_nxfers)
-@@ -874,6 +1335,8 @@ static int dw_i3c_master_priv_xfers(struct i3c_dev_desc *dev,
- 	if (!xfer)
- 		return -ENOMEM;
- 
-+	master->platform_ops->flush_dat(master, dev->info.dyn_addr);
-+
- 	for (i = 0; i < i3c_nxfers; i++) {
- 		struct dw_i3c_cmd *cmd = &xfer->cmds[i];
- 
-@@ -901,9 +1364,21 @@ static int dw_i3c_master_priv_xfers(struct i3c_dev_desc *dev,
- 			cmd->cmd_lo |= COMMAND_PORT_TOC;
- 	}
- 
-+	sda_lvl_pre = FIELD_GET(SDA_LINE_SIGNAL_LEVEL,
-+				readl(master->regs + PRESENT_STATE));
- 	dw_i3c_master_enqueue_xfer(master, xfer);
--	if (!wait_for_completion_timeout(&xfer->comp, XFER_TIMEOUT))
-+	if (!wait_for_completion_timeout(&xfer->comp, XFER_TIMEOUT)) {
-+		dw_i3c_master_enter_halt(master, true);
- 		dw_i3c_master_dequeue_xfer(master, xfer);
-+		sda_lvl_post = FIELD_GET(SDA_LINE_SIGNAL_LEVEL,
-+					 readl(master->regs + PRESENT_STATE));
-+		if (sda_lvl_pre == 0 && sda_lvl_post == 0) {
-+			dev_warn(&master->base.dev,
-+				 "SDA stuck low! Try to recover the bus...\n");
-+			master->platform_ops->bus_recovery(master);
-+		}
-+		dw_i3c_master_exit_halt(master);
-+	}
- 
- 	for (i = 0; i < i3c_nxfers; i++) {
- 		struct dw_i3c_cmd *cmd = &xfer->cmds[i];
-@@ -918,83 +1393,407 @@ static int dw_i3c_master_priv_xfers(struct i3c_dev_desc *dev,
- 	return ret;
- }
- 
--static int dw_i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev,
--					  u8 old_dyn_addr)
-+static int dw_i3c_master_send_hdr_cmds(struct i3c_dev_desc *dev,
-+				       struct i3c_hdr_cmd *cmds, int ncmds)
- {
--	struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev);
- 	struct i3c_master_controller *m = i3c_dev_get_master(dev);
- 	struct dw_i3c_master *master = to_dw_i3c_master(m);
--	int pos;
-+	u8 dat_index;
-+	int ret, i, ntxwords = 0, nrxwords = 0;
-+	u32 sda_lvl_pre, sda_lvl_post;
-+	struct dw_i3c_xfer *xfer;
- 
--	pos = dw_i3c_master_get_free_pos(master);
-+	if (ncmds < 1)
-+		return 0;
- 
--	if (data->index > pos && pos > 0) {
--		writel(0,
--		       master->regs +
--		       DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index));
-+	dev_dbg(&master->base.dev, "ncmds = %x", ncmds);
- 
--		master->devs[data->index].addr = 0;
--		master->free_pos |= BIT(data->index);
-+	if (ncmds > master->caps.cmdfifodepth)
-+		return -EOPNOTSUPP;
- 
--		data->index = pos;
--		master->devs[pos].addr = dev->info.dyn_addr;
--		master->free_pos &= ~BIT(pos);
-+	for (i = 0; i < ncmds; i++) {
-+		dev_dbg(&master->base.dev, "cmds[%d] mode = %x", i,
-+			cmds[i].mode);
-+		if (cmds[i].mode != I3C_HDR_DDR)
-+			return -EOPNOTSUPP;
-+		if (cmds[i].code & 0x80)
-+			nrxwords += DIV_ROUND_UP(cmds[i].ndatawords, 2);
-+		else
-+			ntxwords += DIV_ROUND_UP(cmds[i].ndatawords, 2);
- 	}
-+	dev_dbg(&master->base.dev, "ntxwords = %x, nrxwords = %x", ntxwords,
-+		nrxwords);
-+	if (ntxwords > master->caps.datafifodepth ||
-+	    nrxwords > master->caps.datafifodepth)
-+		return -EOPNOTSUPP;
- 
--	writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(dev->info.dyn_addr),
--	       master->regs +
--	       DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index));
-+	xfer = dw_i3c_master_alloc_xfer(master, ncmds);
-+	if (!xfer)
-+		return -ENOMEM;
- 
--	master->devs[data->index].addr = dev->info.dyn_addr;
-+	for (i = 0; i < ncmds; i++) {
-+		struct dw_i3c_cmd *cmd = &xfer->cmds[i];
- 
--	return 0;
--}
-+		dat_index = master->platform_ops->get_addr_pos(master, dev->info.dyn_addr);
- 
--static int dw_i3c_master_attach_i3c_dev(struct i3c_dev_desc *dev)
--{
--	struct i3c_master_controller *m = i3c_dev_get_master(dev);
--	struct dw_i3c_master *master = to_dw_i3c_master(m);
--	struct dw_i3c_i2c_dev_data *data;
--	int pos;
-+		if (dat_index < 0)
-+			return dat_index;
-+		master->platform_ops->flush_dat(master, dev->info.dyn_addr);
- 
--	pos = dw_i3c_master_get_free_pos(master);
--	if (pos < 0)
--		return pos;
-+		cmd->cmd_hi =
-+			COMMAND_PORT_ARG_DATA_LEN(cmds[i].ndatawords << 1) |
-+			COMMAND_PORT_TRANSFER_ARG;
- 
--	data = kzalloc(sizeof(*data), GFP_KERNEL);
--	if (!data)
--		return -ENOMEM;
-+		if (cmds[i].code & 0x80) {
-+			cmd->rx_buf = cmds[i].data.in;
-+			cmd->rx_len = cmds[i].ndatawords << 1;
-+			cmd->cmd_lo = COMMAND_PORT_READ_TRANSFER |
-+				      COMMAND_PORT_CP |
-+				      COMMAND_PORT_CMD(cmds[i].code) |
-+				      COMMAND_PORT_SPEED(SPEED_I3C_HDR_DDR);
- 
--	data->index = pos;
--	master->devs[pos].addr = dev->info.dyn_addr ? : dev->info.static_addr;
--	master->free_pos &= ~BIT(pos);
--	i3c_dev_set_master_data(dev, data);
-+		} else {
-+			cmd->tx_buf = cmds[i].data.out;
-+			cmd->tx_len = cmds[i].ndatawords << 1;
-+			cmd->cmd_lo = COMMAND_PORT_CP |
-+				      COMMAND_PORT_CMD(cmds[i].code) |
-+				      COMMAND_PORT_SPEED(SPEED_I3C_HDR_DDR);
-+		}
- 
--	writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(master->devs[pos].addr),
--	       master->regs +
--	       DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index));
-+		cmd->cmd_lo |= COMMAND_PORT_TID(i) |
-+			       COMMAND_PORT_DEV_INDEX(dat_index) |
-+			       COMMAND_PORT_ROC;
- 
--	return 0;
--}
-+		if (i == (ncmds - 1))
-+			cmd->cmd_lo |= COMMAND_PORT_TOC;
- 
--static void dw_i3c_master_detach_i3c_dev(struct i3c_dev_desc *dev)
--{
--	struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev);
--	struct i3c_master_controller *m = i3c_dev_get_master(dev);
--	struct dw_i3c_master *master = to_dw_i3c_master(m);
-+		dev_dbg(&master->base.dev,
-+			"%s:cmd_hi=0x%08x cmd_lo=0x%08x tx_len=%d rx_len=%d\n",
-+			__func__, cmd->cmd_hi, cmd->cmd_lo, cmd->tx_len,
-+			cmd->rx_len);
-+	}
- 
--	writel(0,
--	       master->regs +
--	       DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index));
-+	sda_lvl_pre = FIELD_GET(SDA_LINE_SIGNAL_LEVEL,
-+				readl(master->regs + PRESENT_STATE));
-+	dw_i3c_master_enqueue_xfer(master, xfer);
-+	if (!wait_for_completion_timeout(&xfer->comp, XFER_TIMEOUT)) {
-+		dw_i3c_master_enter_halt(master, true);
-+		dw_i3c_master_dequeue_xfer(master, xfer);
-+		sda_lvl_post = FIELD_GET(SDA_LINE_SIGNAL_LEVEL,
-+					 readl(master->regs + PRESENT_STATE));
-+		if (sda_lvl_pre == 0 && sda_lvl_post == 0) {
-+			dev_warn(&master->base.dev,
-+				 "SDA stuck low! Try to recover the bus...\n");
-+			master->platform_ops->bus_recovery(master);
-+		}
-+		dw_i3c_master_exit_halt(master);
-+	}
- 
--	i3c_dev_set_master_data(dev, NULL);
--	master->devs[data->index].addr = 0;
--	master->free_pos |= BIT(data->index);
-+	for (i = 0; i < ncmds; i++) {
-+		struct dw_i3c_cmd *cmd = &xfer->cmds[i];
-+
-+		if (cmds[i].code & 0x80)
-+			cmds[i].ndatawords = DIV_ROUND_UP(cmd->rx_len, 2);
-+	}
-+
-+	ret = xfer->ret;
-+	dw_i3c_master_free_xfer(xfer);
-+
-+	return ret;
-+}
-+
-+static int dw_i3c_target_priv_xfers(struct i3c_dev_desc *dev,
-+				    struct i3c_priv_xfer *i3c_xfers,
-+				    int i3c_nxfers)
-+{
-+	struct i3c_master_controller *m = i3c_dev_get_master(dev);
-+	struct dw_i3c_master *master = to_dw_i3c_master(m);
-+	struct dw_i3c_xfer *xfer;
-+	int i;
-+
-+	if (!i3c_nxfers)
-+		return 0;
-+
-+	xfer = dw_i3c_master_alloc_xfer(master, i3c_nxfers);
-+	if (!xfer)
-+		return -ENOMEM;
-+
-+	for (i = 0; i < i3c_nxfers; i++) {
-+		struct dw_i3c_cmd *cmd = &xfer->cmds[i];
-+
-+		if (!i3c_xfers[i].rnw) {
-+			cmd->tx_buf = i3c_xfers[i].data.out;
-+			cmd->tx_len = i3c_xfers[i].len;
-+			cmd->cmd_lo = 0 | (i << 3) | (cmd->tx_len << 16);
-+
-+			dw_i3c_master_wr_tx_fifo(master, cmd->tx_buf, cmd->tx_len);
-+			writel(cmd->cmd_lo, master->regs + COMMAND_QUEUE_PORT);
-+		}
-+	}
-+
-+	dw_i3c_master_free_xfer(xfer);
-+
-+	return 0;
-+}
-+
-+static int dw_i3c_target_reset_controller(struct dw_i3c_master *master)
-+{
-+	int ret;
-+
-+	ret = reset_control_assert(master->core_rst);
-+	if (ret)
-+		return ret;
-+
-+	ret = reset_control_deassert(master->core_rst);
-+	if (ret)
-+		return ret;
-+
-+	return dw_i3c_target_bus_init(&master->base);
-+}
-+
-+static int dw_i3c_target_generate_ibi(struct i3c_dev_desc *dev, const u8 *data,
-+				      int len)
-+{
-+	struct i3c_master_controller *m = i3c_dev_get_master(dev);
-+	struct dw_i3c_master *master = to_dw_i3c_master(m);
-+	u32 reg;
-+	int ret;
-+
-+	if (data || len != 0)
-+		return -EOPNOTSUPP;
-+
-+	reg = readl(master->regs + SLV_EVENT_CTRL);
-+	if ((reg & SLV_EVENT_CTRL_SIR_EN) == 0)
-+		return -EPERM;
-+
-+	init_completion(&master->target.comp);
-+	writel(1, master->regs + SLV_INTR_REQ);
-+
-+	if (!wait_for_completion_timeout(&master->target.comp, XFER_TIMEOUT)) {
-+		dev_warn(&master->base.dev, "Timeout waiting for completion: Reset controller\n");
-+		kfree(master->target.rx.buf);
-+
-+		ret = dw_i3c_target_reset_controller(master);
-+		if (ret)
-+			dev_warn(&master->base.dev, "Reset controller failure: %d\n", ret);
-+
-+		return -EINVAL;
-+	}
-+
-+	reg = readl(master->regs + SLV_INTR_REQ);
-+	if (SLV_INTR_REQ_IBI_STS(reg) != IBI_STS_ACCEPTED) {
-+		reg = readl(master->regs + SLV_EVENT_CTRL);
-+		if ((reg & SLV_EVENT_CTRL_SIR_EN) == 0)
-+			dev_warn(&master->base.dev, "SIR is disabled by master\n");
-+		return -EACCES;
-+	}
-+
-+	return 0;
-+}
-+
-+static int dw_i3c_target_reset_queue(struct dw_i3c_master *master)
-+{
-+	int ret;
-+	u32 status;
-+
-+	dw_i3c_master_disable(master);
-+	writel(RESET_CTRL_XFER_QUEUES, master->regs + RESET_CTRL);
-+	ret = readl_poll_timeout_atomic(master->regs + RESET_CTRL, status,
-+					!status, 10, 1000000);
-+	if (ret)
-+		dev_err(&master->base.dev, "Reset %#x failed: %d\n", status,
-+			ret);
-+
-+	dw_i3c_master_enable(master);
-+
-+	return ret;
-+}
-+
-+static int dw_i3c_target_pending_read_notify(struct i3c_dev_desc *dev,
-+					     struct i3c_priv_xfer *pending_read,
-+					     struct i3c_priv_xfer *ibi_notify)
-+{
-+	struct i3c_master_controller *m = i3c_dev_get_master(dev);
-+	struct dw_i3c_master *master = to_dw_i3c_master(m);
-+	struct dw_i3c_xfer *xfer;
-+	struct dw_i3c_cmd *cmd;
-+	int ret;
-+	u32 reg;
-+	u8 mdb;
-+
-+	if (!pending_read || !ibi_notify)
-+		return -EINVAL;
-+
-+	reg = readl(master->regs + SLV_EVENT_CTRL);
-+	if ((reg & SLV_EVENT_CTRL_SIR_EN) == 0)
-+		return -EPERM;
-+
-+	xfer = dw_i3c_master_alloc_xfer(master, 2);
-+	if (!xfer)
-+		return -ENOMEM;
-+
-+	mdb = *(u8 *)ibi_notify->data.out;
-+	master->platform_ops->set_ibi_mdb(master, mdb);
-+
-+	/* Put IBI command & data into the command & data queues */
-+	cmd = &xfer->cmds[0];
-+	cmd->tx_buf = ibi_notify->data.out;
-+	cmd->tx_len = ibi_notify->len;
-+	cmd->cmd_lo = COMMAND_PORT_TID(TID_TARGET_IBI) | (cmd->tx_len << 16);
-+	dw_i3c_master_wr_tx_fifo(master, cmd->tx_buf, cmd->tx_len);
-+	writel(cmd->cmd_lo, master->regs + COMMAND_QUEUE_PORT);
-+
-+	/* Put pending-read command & data into the command & data queues */
-+	cmd = &xfer->cmds[1];
-+	cmd->tx_buf = pending_read->data.out;
-+	cmd->tx_len = pending_read->len;
-+	cmd->cmd_lo = COMMAND_PORT_TID(TID_TARGET_RD_DATA) |
-+		      (cmd->tx_len << 16);
-+	dw_i3c_master_wr_tx_fifo(master, cmd->tx_buf, cmd->tx_len);
-+	writel(cmd->cmd_lo, master->regs + COMMAND_QUEUE_PORT);
-+
-+	dw_i3c_master_free_xfer(xfer);
-+	init_completion(&master->target.rdata_comp);
-+
-+	ret = dw_i3c_target_generate_ibi(dev, NULL, 0);
-+	if (ret) {
-+		dev_warn(&master->base.dev, "Timeout waiting for completion: IBI MDB\n");
-+		return -EINVAL;
-+	}
-+
-+	if (!wait_for_completion_timeout(&master->target.rdata_comp,
-+					 XFER_TIMEOUT)) {
-+		dev_warn(&master->base.dev, "Timeout waiting for completion: pending read data\n");
-+		dw_i3c_target_reset_queue(master);
-+		return -EINVAL;
-+	}
-+
-+	return 0;
-+}
-+
-+static bool dw_i3c_target_is_ibi_enabled(struct i3c_dev_desc *dev)
-+{
-+	struct i3c_master_controller *m = i3c_dev_get_master(dev);
-+	struct dw_i3c_master *master = to_dw_i3c_master(m);
-+	u32 reg;
-+
-+	reg = readl(master->regs + SLV_EVENT_CTRL);
-+	return !!(reg & SLV_EVENT_CTRL_SIR_EN);
-+}
-+
-+static u8 dw_i3c_target_get_dyn_addr(struct i3c_master_controller *m)
-+{
-+	struct dw_i3c_master *master = to_dw_i3c_master(m);
-+	u32 reg;
-+
-+	reg = readl(master->regs + DEVICE_ADDR);
-+	if (reg & DEV_ADDR_DYNAMIC_ADDR_VALID)
-+		return FIELD_GET(DEV_ADDR_DYNAMIC, reg);
-+	return 0;
-+}
-+
-+static int dw_i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev,
-+					  u8 old_dyn_addr)
-+{
-+	struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev);
-+	struct i3c_master_controller *m = i3c_dev_get_master(dev);
-+	struct dw_i3c_master *master = to_dw_i3c_master(m);
-+	int pos;
-+
-+	pos = dw_i3c_master_get_free_pos(master);
-+
-+	if (data->index > pos && pos > 0) {
-+		writel(0,
-+		       master->regs +
-+		       DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index));
-+
-+		master->devs[data->index].addr = 0;
-+		master->free_pos |= BIT(data->index);
-+
-+		data->index = pos;
-+		master->devs[pos].addr = dev->info.dyn_addr;
-+		master->free_pos &= ~BIT(pos);
-+	}
-+
-+	writel(FIELD_PREP(DEV_ADDR_TABLE_DYNAMIC_ADDR, dev->info.dyn_addr),
-+	       master->regs +
-+	       DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index));
-+
-+	master->devs[data->index].addr = dev->info.dyn_addr;
-+
-+	return 0;
-+}
-+
-+static int dw_i3c_master_attach_i3c_dev(struct i3c_dev_desc *dev)
-+{
-+	struct i3c_master_controller *m = i3c_dev_get_master(dev);
-+	struct dw_i3c_master *master = to_dw_i3c_master(m);
-+	struct dw_i3c_i2c_dev_data *data;
-+	int pos;
-+
-+	pos = dw_i3c_master_get_free_pos(master);
-+	if (pos < 0)
-+		return pos;
-+
-+	data = kzalloc(sizeof(*data), GFP_KERNEL);
-+	if (!data)
-+		return -ENOMEM;
-+
-+	data->index = pos;
-+	master->devs[pos].addr = dev->info.dyn_addr ? : dev->info.static_addr;
-+	master->free_pos &= ~BIT(pos);
-+	i3c_dev_set_master_data(dev, data);
-+
-+	writel(FIELD_PREP(DEV_ADDR_TABLE_DYNAMIC_ADDR, master->devs[pos].addr),
-+	       master->regs +
-+	       DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index));
-+
-+	return 0;
-+}
-+
-+static void dw_i3c_master_detach_i3c_dev(struct i3c_dev_desc *dev)
-+{
-+	struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev);
-+	struct i3c_master_controller *m = i3c_dev_get_master(dev);
-+	struct dw_i3c_master *master = to_dw_i3c_master(m);
-+
-+	writel(0,
-+	       master->regs +
-+	       DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index));
-+
-+	i3c_dev_set_master_data(dev, NULL);
-+	master->devs[data->index].addr = 0;
-+	master->free_pos |= BIT(data->index);
- 	kfree(data);
- }
- 
-+static int dw_i3c_common_reattach_i3c_dev(struct i3c_dev_desc *dev,
-+					  u8 old_dyn_addr)
-+{
-+	struct i3c_master_controller *m = i3c_dev_get_master(dev);
-+	struct dw_i3c_master *master = to_dw_i3c_master(m);
-+
-+	return master->platform_ops->reattach_i3c_dev(dev, old_dyn_addr);
-+}
-+
-+static int dw_i3c_common_attach_i3c_dev(struct i3c_dev_desc *dev)
-+{
-+	struct i3c_master_controller *m = i3c_dev_get_master(dev);
-+	struct dw_i3c_master *master = to_dw_i3c_master(m);
-+
-+	return master->platform_ops->attach_i3c_dev(dev);
-+}
-+
-+static void dw_i3c_common_detach_i3c_dev(struct i3c_dev_desc *dev)
-+{
-+	struct i3c_master_controller *m = i3c_dev_get_master(dev);
-+	struct dw_i3c_master *master = to_dw_i3c_master(m);
-+
-+	master->platform_ops->detach_i3c_dev(dev);
-+}
-+
- static int dw_i3c_master_i2c_xfers(struct i2c_dev_desc *dev,
--				   const struct i2c_msg *i2c_xfers,
-+				   struct i2c_msg *i2c_xfers,
- 				   int i2c_nxfers)
- {
- 	struct dw_i3c_i2c_dev_data *data = i2c_dev_get_master_data(dev);
-@@ -1002,6 +1801,7 @@ static int dw_i3c_master_i2c_xfers(struct i2c_dev_desc *dev,
- 	struct dw_i3c_master *master = to_dw_i3c_master(m);
- 	unsigned int nrxwords = 0, ntxwords = 0;
- 	struct dw_i3c_xfer *xfer;
-+	u32 sda_lvl_pre, sda_lvl_post;
- 	int i, ret = 0;
- 
- 	if (!i2c_nxfers)
-@@ -1021,10 +1821,18 @@ static int dw_i3c_master_i2c_xfers(struct i2c_dev_desc *dev,
- 	    nrxwords > master->caps.datafifodepth)
- 		return -ENOTSUPP;
- 
-+	if (ntxwords == 0 && nrxwords == 0) {
-+		dev_warn(&master->base.dev,
-+			 "Transfers w/o data bytes are not supported");
-+		return -ENOTSUPP;
-+	}
-+
- 	xfer = dw_i3c_master_alloc_xfer(master, i2c_nxfers);
- 	if (!xfer)
- 		return -ENOMEM;
- 
-+	master->platform_ops->flush_dat(master, dev->addr);
-+
- 	for (i = 0; i < i2c_nxfers; i++) {
- 		struct dw_i3c_cmd *cmd = &xfer->cmds[i];
- 
-@@ -1048,9 +1856,21 @@ static int dw_i3c_master_i2c_xfers(struct i2c_dev_desc *dev,
- 			cmd->cmd_lo |= COMMAND_PORT_TOC;
- 	}
- 
-+	sda_lvl_pre = FIELD_GET(SDA_LINE_SIGNAL_LEVEL,
-+				readl(master->regs + PRESENT_STATE));
- 	dw_i3c_master_enqueue_xfer(master, xfer);
--	if (!wait_for_completion_timeout(&xfer->comp, XFER_TIMEOUT))
-+	if (!wait_for_completion_timeout(&xfer->comp, XFER_TIMEOUT)) {
-+		dw_i3c_master_enter_halt(master, true);
- 		dw_i3c_master_dequeue_xfer(master, xfer);
-+		sda_lvl_post = FIELD_GET(SDA_LINE_SIGNAL_LEVEL,
-+					 readl(master->regs + PRESENT_STATE));
-+		if (sda_lvl_pre == 0 && sda_lvl_post == 0) {
-+			dev_warn(&master->base.dev,
-+				 "SDA stuck low! Try to recover the bus...\n");
-+			master->platform_ops->bus_recovery(master);
-+		}
-+		dw_i3c_master_exit_halt(master);
-+	}
- 
- 	ret = xfer->ret;
- 	dw_i3c_master_free_xfer(xfer);
-@@ -1079,7 +1899,7 @@ static int dw_i3c_master_attach_i2c_dev(struct i2c_dev_desc *dev)
- 	i2c_dev_set_master_data(dev, data);
- 
- 	writel(DEV_ADDR_TABLE_LEGACY_I2C_DEV |
--	       DEV_ADDR_TABLE_STATIC_ADDR(dev->addr),
-+	       FIELD_PREP(DEV_ADDR_TABLE_STATIC_ADDR, dev->addr),
- 	       master->regs +
- 	       DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index));
- 
-@@ -1102,6 +1922,22 @@ static void dw_i3c_master_detach_i2c_dev(struct i2c_dev_desc *dev)
- 	kfree(data);
- }
- 
-+static int dw_i3c_common_attach_i2c_dev(struct i2c_dev_desc *dev)
-+{
-+	struct i3c_master_controller *m = i2c_dev_get_master(dev);
-+	struct dw_i3c_master *master = to_dw_i3c_master(m);
-+
-+	return master->platform_ops->attach_i2c_dev(dev);
-+}
-+
-+static void dw_i3c_common_detach_i2c_dev(struct i2c_dev_desc *dev)
-+{
-+	struct i3c_master_controller *m = i2c_dev_get_master(dev);
-+	struct dw_i3c_master *master = to_dw_i3c_master(m);
-+
-+	master->platform_ops->detach_i2c_dev(dev);
-+}
-+
- static int dw_i3c_master_request_ibi(struct i3c_dev_desc *dev,
- 				     const struct i3c_ibi_setup *req)
- {
-@@ -1115,7 +1951,7 @@ static int dw_i3c_master_request_ibi(struct i3c_dev_desc *dev,
- 		return PTR_ERR(data->ibi_pool);
- 
- 	spin_lock_irqsave(&master->devs_lock, flags);
--	master->devs[data->index].ibi_dev = dev;
-+	master->platform_ops->set_ibi_dev(master, dev);
- 	spin_unlock_irqrestore(&master->devs_lock, flags);
- 
- 	return 0;
-@@ -1129,13 +1965,30 @@ static void dw_i3c_master_free_ibi(struct i3c_dev_desc *dev)
- 	unsigned long flags;
- 
- 	spin_lock_irqsave(&master->devs_lock, flags);
--	master->devs[data->index].ibi_dev = NULL;
-+	master->platform_ops->unset_ibi_dev(master, dev);
- 	spin_unlock_irqrestore(&master->devs_lock, flags);
- 
- 	i3c_generic_ibi_free_pool(data->ibi_pool);
- 	data->ibi_pool = NULL;
- }
- 
-+static void dw_i3c_master_enable_sir_signal(struct dw_i3c_master *master, bool enable)
-+{
-+	u32 reg;
-+
-+	reg = readl(master->regs + INTR_STATUS_EN);
-+	reg &= ~INTR_IBI_THLD_STAT;
-+	if (enable)
-+		reg |= INTR_IBI_THLD_STAT;
-+	writel(reg, master->regs + INTR_STATUS_EN);
-+
-+	reg = readl(master->regs + INTR_SIGNAL_EN);
-+	reg &= ~INTR_IBI_THLD_STAT;
-+	if (enable)
-+		reg |= INTR_IBI_THLD_STAT;
-+	writel(reg, master->regs + INTR_SIGNAL_EN);
-+}
-+
- static void dw_i3c_master_set_sir_enabled(struct dw_i3c_master *master,
- 					  struct i3c_dev_desc *dev,
- 					  u8 idx, bool enable)
-@@ -1170,23 +2023,34 @@ static void dw_i3c_master_set_sir_enabled(struct dw_i3c_master *master,
- 	}
- 	writel(reg, master->regs + IBI_SIR_REQ_REJECT);
- 
--	if (global) {
--		reg = readl(master->regs + INTR_STATUS_EN);
--		reg &= ~INTR_IBI_THLD_STAT;
--		if (enable)
--			reg |= INTR_IBI_THLD_STAT;
--		writel(reg, master->regs + INTR_STATUS_EN);
-+	if (global)
-+		dw_i3c_master_enable_sir_signal(master, enable);
- 
--		reg = readl(master->regs + INTR_SIGNAL_EN);
--		reg &= ~INTR_IBI_THLD_STAT;
--		if (enable)
--			reg |= INTR_IBI_THLD_STAT;
--		writel(reg, master->regs + INTR_SIGNAL_EN);
--	}
- 
- 	spin_unlock_irqrestore(&master->devs_lock, flags);
- }
- 
-+static int dw_i3c_master_enable_hotjoin(struct i3c_master_controller *m)
-+{
-+	struct dw_i3c_master *master = to_dw_i3c_master(m);
-+
-+	dw_i3c_master_enable_sir_signal(master, true);
-+	writel(readl(master->regs + DEVICE_CTRL) & ~DEV_CTRL_HOT_JOIN_NACK,
-+	       master->regs + DEVICE_CTRL);
-+
-+	return 0;
-+}
-+
-+static int dw_i3c_master_disable_hotjoin(struct i3c_master_controller *m)
-+{
-+	struct dw_i3c_master *master = to_dw_i3c_master(m);
-+
-+	writel(readl(master->regs + DEVICE_CTRL) | DEV_CTRL_HOT_JOIN_NACK,
-+	       master->regs + DEVICE_CTRL);
-+
-+	return 0;
-+}
-+
- static int dw_i3c_master_enable_ibi(struct i3c_dev_desc *dev)
- {
- 	struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev);
-@@ -1194,12 +2058,12 @@ static int dw_i3c_master_enable_ibi(struct i3c_dev_desc *dev)
- 	struct dw_i3c_master *master = to_dw_i3c_master(m);
- 	int rc;
- 
--	dw_i3c_master_set_sir_enabled(master, dev, data->index, true);
-+	master->platform_ops->set_sir_enabled(master, dev, data->index, true);
- 
- 	rc = i3c_master_enec_locked(m, dev->info.dyn_addr, I3C_CCC_EVENT_SIR);
- 
- 	if (rc)
--		dw_i3c_master_set_sir_enabled(master, dev, data->index, false);
-+		master->platform_ops->set_sir_enabled(master, dev, data->index, false);
- 
- 	return rc;
- }
-@@ -1209,13 +2073,9 @@ static int dw_i3c_master_disable_ibi(struct i3c_dev_desc *dev)
- 	struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev);
- 	struct i3c_master_controller *m = i3c_dev_get_master(dev);
- 	struct dw_i3c_master *master = to_dw_i3c_master(m);
--	int rc;
--
--	rc = i3c_master_disec_locked(m, dev->info.dyn_addr, I3C_CCC_EVENT_SIR);
--	if (rc)
--		return rc;
- 
--	dw_i3c_master_set_sir_enabled(master, dev, data->index, false);
-+	i3c_master_disec_locked(m, dev->info.dyn_addr, I3C_CCC_EVENT_SIR);
-+	master->platform_ops->set_sir_enabled(master, dev, data->index, false);
- 
- 	return 0;
- }
-@@ -1244,8 +2104,9 @@ static void dw_i3c_master_handle_ibi_sir(struct dw_i3c_master *master,
- 	struct i3c_ibi_slot *slot;
- 	struct i3c_dev_desc *dev;
- 	unsigned long flags;
-+	u32 state;
- 	u8 addr, len;
--	int idx;
-+	bool terminate_ibi = false;
- 
- 	addr = IBI_QUEUE_IBI_ADDR(status);
- 	len = IBI_QUEUE_STATUS_DATA_LEN(status);
-@@ -1262,17 +2123,12 @@ static void dw_i3c_master_handle_ibi_sir(struct dw_i3c_master *master,
- 	 */
- 
- 	spin_lock_irqsave(&master->devs_lock, flags);
--	idx = dw_i3c_master_get_addr_pos(master, addr);
--	if (idx < 0) {
--		dev_dbg_ratelimited(&master->base.dev,
--			 "IBI from unknown addr 0x%x\n", addr);
--		goto err_drain;
--	}
- 
--	dev = master->devs[idx].ibi_dev;
-+	dev = master->platform_ops->get_ibi_dev(master, addr);
- 	if (!dev || !dev->ibi) {
- 		dev_dbg_ratelimited(&master->base.dev,
--			 "IBI from non-requested dev idx %d\n", idx);
-+				    "IBI from non-requested dev addr %02x\n",
-+				    addr);
- 		goto err_drain;
- 	}
- 
-@@ -1288,6 +2144,7 @@ static void dw_i3c_master_handle_ibi_sir(struct dw_i3c_master *master,
- 		dev_dbg_ratelimited(&master->base.dev,
- 				    "IBI payload len %d greater than max %d\n",
- 				    len, dev->ibi->max_payload_len);
-+		terminate_ibi = true;
- 		goto err_drain;
- 	}
- 
-@@ -1303,6 +2160,9 @@ static void dw_i3c_master_handle_ibi_sir(struct dw_i3c_master *master,
- 
- err_drain:
- 	dw_i3c_master_drain_ibi_queue(master, len);
-+	state = FIELD_GET(CM_TFR_STS, readl(master->regs + PRESENT_STATE));
-+	if (terminate_ibi && state == CM_TFR_STS_MASTER_SERV_IBI)
-+		master->platform_ops->gen_tbits_in(master);
- 
- 	spin_unlock_irqrestore(&master->devs_lock, flags);
- }
-@@ -1315,17 +2175,34 @@ static void dw_i3c_master_irq_handle_ibis(struct dw_i3c_master *master)
- {
- 	unsigned int i, len, n_ibis;
- 	u32 reg;
-+	int ret;
- 
- 	reg = readl(master->regs + QUEUE_STATUS_LEVEL);
- 	n_ibis = QUEUE_STATUS_IBI_STATUS_CNT(reg);
- 	if (!n_ibis)
- 		return;
- 
-+	if (n_ibis > 16) {
-+		dev_err(&master->base.dev,
-+			"The n_ibis %d surpasses the tolerance level for the IBI buffer\n",
-+			n_ibis);
-+		goto ibi_fifo_clear;
-+	}
-+
- 	for (i = 0; i < n_ibis; i++) {
- 		reg = readl(master->regs + IBI_QUEUE_STATUS);
- 
-+		if (reg & IBI_QUEUE_STATUS_RSP_NACK) {
-+			dev_dbg_ratelimited(&master->base.dev,
-+					    "Nacked IBI from non-requested dev addr %02lx\n",
-+					    IBI_QUEUE_IBI_ADDR(reg));
-+			goto ibi_fifo_clear;
-+		}
-+
- 		if (IBI_TYPE_SIRQ(reg)) {
- 			dw_i3c_master_handle_ibi_sir(master, reg);
-+		} else if (IBI_TYPE_HJ(reg)) {
-+			queue_work(master->base.wq, &master->hj_work);
- 		} else {
- 			len = IBI_QUEUE_STATUS_DATA_LEN(reg);
- 			dev_info(&master->base.dev,
-@@ -1334,6 +2211,68 @@ static void dw_i3c_master_irq_handle_ibis(struct dw_i3c_master *master)
- 			dw_i3c_master_drain_ibi_queue(master, len);
- 		}
- 	}
-+
-+	return;
-+
-+ibi_fifo_clear:
-+	dw_i3c_master_enter_halt(master, true);
-+	writel(RESET_CTRL_IBI_QUEUE, master->regs + RESET_CTRL);
-+	ret = readl_poll_timeout_atomic(master->regs + RESET_CTRL, reg, !reg,
-+					10, 1000000);
-+	if (ret)
-+		dev_err(&master->base.dev,
-+			"Timeout waiting for IBI FIFO reset\n");
-+
-+	dw_i3c_master_exit_halt(master);
-+}
-+
-+static void dw_i3c_target_handle_ccc_update(struct dw_i3c_master *master)
-+{
-+	u32 event = readl(master->regs + SLV_EVENT_CTRL);
-+	u32 reg = readl(master->regs + SLV_MAX_LEN);
-+	u32 present_state = readl(master->regs + PRESENT_STATE);
-+
-+	if (event & SLV_EVENT_CTRL_MRL_UPD)
-+		master->base.this->info.max_read_len = SLV_MAX_RD_LEN(reg);
-+
-+	if (event & SLV_EVENT_CTRL_MWL_UPD) {
-+		master->base.this->info.max_write_len = SLV_MAX_WR_LEN(reg);
-+		master->target.rx.max_len =
-+			master->base.this->info.max_write_len;
-+	}
-+	writel(event, master->regs + SLV_EVENT_CTRL);
-+
-+	/* The I3C engine would get into halt-state if it receives SETMRL/MWL CCCs */
-+	if (FIELD_GET(CM_TFR_STS, present_state) == CM_TFR_STS_SLAVE_HALT)
-+		dw_i3c_master_exit_halt(master);
-+
-+	writel(INTR_CCC_UPDATED_STAT, master->regs + INTR_STATUS);
-+}
-+
-+static void dw_i3c_target_handle_response_ready(struct dw_i3c_master *master)
-+{
-+	struct i3c_dev_desc *desc = master->base.this;
-+	u32 reg = readl(master->regs + QUEUE_STATUS_LEVEL);
-+	u32 nresp = QUEUE_STATUS_LEVEL_RESP(reg);
-+	int i;
-+
-+	for (i = 0; i < nresp; i++) {
-+		u32 resp = readl(master->regs + RESPONSE_QUEUE_PORT);
-+		u32 nbytes = RESPONSE_PORT_DATA_LEN(resp);
-+		u8 tid = RESPONSE_PORT_TID(resp);
-+
-+		if (nbytes > master->target.rx.max_len) {
-+			dev_warn(&master->base.dev, "private write data length is larger than max\n");
-+			return;
-+		}
-+
-+		dw_i3c_master_read_rx_fifo(master, master->target.rx.buf, nbytes);
-+
-+		if (tid == TID_TARGET_MASTER_WR_DATA && desc->target_info.read_handler)
-+			desc->target_info.read_handler(desc->dev, master->target.rx.buf, nbytes);
-+		else if (tid == TID_TARGET_RD_DATA)
-+			complete(&master->target.rdata_comp);
-+	}
- }
- 
- static irqreturn_t dw_i3c_master_irq_handler(int irq, void *dev_id)
-@@ -1348,27 +2287,102 @@ static irqreturn_t dw_i3c_master_irq_handler(int irq, void *dev_id)
- 		return IRQ_NONE;
- 	}
- 
--	spin_lock(&master->xferqueue.lock);
--	dw_i3c_master_end_xfer_locked(master, status);
--	if (status & INTR_TRANSFER_ERR_STAT)
--		writel(INTR_TRANSFER_ERR_STAT, master->regs + INTR_STATUS);
--	spin_unlock(&master->xferqueue.lock);
-+	if (master->base.target) {
-+		if (status & INTR_DYN_ADDR_ASSGN_STAT) {
-+			u32 reg = readl(master->regs + DEVICE_ADDR);
- 
--	if (status & INTR_IBI_THLD_STAT)
--		dw_i3c_master_irq_handle_ibis(master);
-+			master->base.this->info.dyn_addr =
-+				FIELD_GET(DEV_ADDR_DYNAMIC, reg);
-+			writel(INTR_DYN_ADDR_ASSGN_STAT,
-+			       master->regs + INTR_STATUS);
-+		}
-+
-+		if (status & INTR_CCC_UPDATED_STAT)
-+			dw_i3c_target_handle_ccc_update(master);
-+
-+		if (status & INTR_IBI_UPDATED_STAT) {
-+			writel(INTR_IBI_UPDATED_STAT, master->regs + INTR_STATUS);
-+			complete(&master->target.comp);
-+		}
-+
-+		if (status & INTR_READ_REQ_RECV_STAT) {
-+			/*
-+			 * TODO: Pass this information to the driver to take
-+			 * appropriate action.
-+			 */
-+			dev_dbg(&master->base.dev,
-+				"private read received from controller when cmd queue is empty\n");
-+			writel(INTR_READ_REQ_RECV_STAT, master->regs + INTR_STATUS);
-+		}
-+
-+		if (status & INTR_RESP_READY_STAT)
-+			dw_i3c_target_handle_response_ready(master);
-+	} else {
-+		if (status & INTR_RESP_READY_STAT ||
-+		    status & INTR_TRANSFER_ERR_STAT) {
-+			spin_lock(&master->xferqueue.lock);
-+			dw_i3c_master_end_xfer_locked(master, status);
-+			if (status & INTR_TRANSFER_ERR_STAT)
-+				writel(INTR_TRANSFER_ERR_STAT, master->regs + INTR_STATUS);
-+			spin_unlock(&master->xferqueue.lock);
-+		}
-+
-+		if (status & INTR_IBI_THLD_STAT)
-+			dw_i3c_master_irq_handle_ibis(master);
-+	}
- 
- 	return IRQ_HANDLED;
- }
- 
-+static int dw_i3c_target_hj_req(struct i3c_dev_desc *dev)
-+{
-+	struct i3c_master_controller *m = i3c_dev_get_master(dev);
-+	struct dw_i3c_master *master = to_dw_i3c_master(m);
-+
-+	if (!(readl(master->regs + HW_CAPABILITY) & HW_CAP_SLV_HJ)) {
-+		dev_err(&master->base.dev, "HJ not supported");
-+		return -EOPNOTSUPP;
-+	}
-+
-+	if (readl(master->regs + DEVICE_ADDR) & DEV_ADDR_DYNAMIC_ADDR_VALID) {
-+		dev_err(&master->base.dev, "DA already assigned");
-+		return -EACCES;
-+	}
-+
-+	writel(SLV_EVENT_CTRL_HJ_REQ, master->regs + SLV_EVENT_CTRL);
-+
-+	return 0;
-+}
-+
-+static bool dw_i3c_target_is_hj_enabled(struct i3c_dev_desc *dev)
-+{
-+	/* DW i3c doesn't have the hardware flag to identify the hj enable status */
-+	return true;
-+}
-+
-+static const struct i3c_target_ops dw_mipi_i3c_target_ops = {
-+	.bus_init = dw_i3c_target_bus_init,
-+	.hj_req = dw_i3c_target_hj_req,
-+	.bus_cleanup = dw_i3c_target_bus_cleanup,
-+	.priv_xfers = dw_i3c_target_priv_xfers,
-+	.generate_ibi = dw_i3c_target_generate_ibi,
-+	.pending_read_notify = dw_i3c_target_pending_read_notify,
-+	.is_hj_enabled =  dw_i3c_target_is_hj_enabled,
-+	.is_ibi_enabled = dw_i3c_target_is_ibi_enabled,
-+	.get_dyn_addr = dw_i3c_target_get_dyn_addr,
-+};
-+
- static const struct i3c_master_controller_ops dw_mipi_i3c_ops = {
- 	.bus_init = dw_i3c_master_bus_init,
- 	.bus_cleanup = dw_i3c_master_bus_cleanup,
-+	.bus_reset = dw_i3c_master_bus_reset,
- 	.attach_i3c_dev = dw_i3c_master_attach_i3c_dev,
- 	.reattach_i3c_dev = dw_i3c_master_reattach_i3c_dev,
- 	.detach_i3c_dev = dw_i3c_master_detach_i3c_dev,
- 	.do_daa = dw_i3c_master_daa,
- 	.supports_ccc_cmd = dw_i3c_master_supports_ccc_cmd,
- 	.send_ccc_cmd = dw_i3c_master_send_ccc_cmd,
-+	.send_hdr_cmds = dw_i3c_master_send_hdr_cmds,
- 	.priv_xfers = dw_i3c_master_priv_xfers,
- 	.attach_i2c_dev = dw_i3c_master_attach_i2c_dev,
- 	.detach_i2c_dev = dw_i3c_master_detach_i2c_dev,
-@@ -1378,21 +2392,25 @@ static const struct i3c_master_controller_ops dw_mipi_i3c_ops = {
- static const struct i3c_master_controller_ops dw_mipi_i3c_ibi_ops = {
- 	.bus_init = dw_i3c_master_bus_init,
- 	.bus_cleanup = dw_i3c_master_bus_cleanup,
--	.attach_i3c_dev = dw_i3c_master_attach_i3c_dev,
--	.reattach_i3c_dev = dw_i3c_master_reattach_i3c_dev,
--	.detach_i3c_dev = dw_i3c_master_detach_i3c_dev,
-+	.bus_reset = dw_i3c_master_bus_reset,
-+	.attach_i3c_dev = dw_i3c_common_attach_i3c_dev,
-+	.reattach_i3c_dev = dw_i3c_common_reattach_i3c_dev,
-+	.detach_i3c_dev = dw_i3c_common_detach_i3c_dev,
- 	.do_daa = dw_i3c_master_daa,
- 	.supports_ccc_cmd = dw_i3c_master_supports_ccc_cmd,
- 	.send_ccc_cmd = dw_i3c_master_send_ccc_cmd,
-+	.send_hdr_cmds = dw_i3c_master_send_hdr_cmds,
- 	.priv_xfers = dw_i3c_master_priv_xfers,
--	.attach_i2c_dev = dw_i3c_master_attach_i2c_dev,
--	.detach_i2c_dev = dw_i3c_master_detach_i2c_dev,
-+	.attach_i2c_dev = dw_i3c_common_attach_i2c_dev,
-+	.detach_i2c_dev = dw_i3c_common_detach_i2c_dev,
- 	.i2c_xfers = dw_i3c_master_i2c_xfers,
- 	.request_ibi = dw_i3c_master_request_ibi,
- 	.free_ibi = dw_i3c_master_free_ibi,
- 	.enable_ibi = dw_i3c_master_enable_ibi,
- 	.disable_ibi = dw_i3c_master_disable_ibi,
- 	.recycle_ibi_slot = dw_i3c_master_recycle_ibi_slot,
-+	.enable_hotjoin = dw_i3c_master_enable_hotjoin,
-+	.disable_hotjoin = dw_i3c_master_disable_hotjoin,
- };
- 
- /* default platform ops implementations */
-@@ -1407,15 +2425,151 @@ static void dw_i3c_platform_set_dat_ibi_nop(struct dw_i3c_master *i3c,
- {
- }
- 
-+static void dw_i3c_platform_enter_sw_mode_nop(struct dw_i3c_master *i3c)
-+{
-+}
-+
-+static void dw_i3c_platform_exit_sw_mode_nop(struct dw_i3c_master *i3c)
-+{
-+}
-+
-+static void dw_i3c_toggle_scl_in_nop(struct dw_i3c_master *i3c, int count)
-+{
-+}
-+
-+static void dw_i3c_gen_internal_stop_nop(struct dw_i3c_master *i3c)
-+{
-+}
-+
-+static void dw_i3c_gen_target_reset_pattern_nop(struct dw_i3c_master *i3c)
-+{
-+}
-+
-+static void dw_i3c_set_ibi_mdb_nop(struct dw_i3c_master *i3c, u8 mdb)
-+{
-+}
-+
-+static int dw_i3c_master_flush_dat_nop(struct dw_i3c_master *i3c, u8 addr)
-+{
-+	return 0;
-+}
-+
-+static void dw_i3c_master_set_ibi_dev(struct dw_i3c_master *i3c,
-+				      struct i3c_dev_desc *dev)
-+{
-+	struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev);
-+
-+	i3c->devs[data->index].ibi_dev = dev;
-+}
-+
-+static void dw_i3c_master_unset_ibi_dev(struct dw_i3c_master *i3c,
-+					struct i3c_dev_desc *dev)
-+{
-+	struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev);
-+
-+	i3c->devs[data->index].ibi_dev = NULL;
-+}
-+
-+static struct i3c_dev_desc *dw_i3c_master_get_ibi_dev(struct dw_i3c_master *i3c,
-+						      u8 addr)
-+{
-+	int idx = i3c->platform_ops->get_addr_pos(i3c, addr);
-+
-+	if (idx < 0) {
-+		dev_dbg_ratelimited(&i3c->base.dev,
-+				    "IBI from unknown addr 0x%x\n", addr);
-+		return NULL;
-+	}
-+
-+	return i3c->devs[idx].ibi_dev;
-+}
-+
- static const struct dw_i3c_platform_ops dw_i3c_platform_ops_default = {
- 	.init = dw_i3c_platform_init_nop,
- 	.set_dat_ibi = dw_i3c_platform_set_dat_ibi_nop,
-+	.enter_sw_mode = dw_i3c_platform_enter_sw_mode_nop,
-+	.exit_sw_mode = dw_i3c_platform_exit_sw_mode_nop,
-+	.toggle_scl_in = dw_i3c_toggle_scl_in_nop,
-+	.gen_internal_stop = dw_i3c_gen_internal_stop_nop,
-+	.gen_target_reset_pattern = dw_i3c_gen_target_reset_pattern_nop,
-+	.set_ibi_mdb = dw_i3c_set_ibi_mdb_nop,
-+	.reattach_i3c_dev = dw_i3c_master_reattach_i3c_dev,
-+	.attach_i3c_dev = dw_i3c_master_attach_i3c_dev,
-+	.detach_i3c_dev = dw_i3c_master_detach_i3c_dev,
-+	.attach_i2c_dev = dw_i3c_master_attach_i2c_dev,
-+	.detach_i2c_dev = dw_i3c_master_detach_i2c_dev,
-+	.get_addr_pos = dw_i3c_master_get_addr_pos,
-+	.flush_dat = dw_i3c_master_flush_dat_nop,
-+	.set_sir_enabled = dw_i3c_master_set_sir_enabled,
-+	.set_ibi_dev = dw_i3c_master_set_ibi_dev,
-+	.unset_ibi_dev = dw_i3c_master_unset_ibi_dev,
-+	.get_ibi_dev = dw_i3c_master_get_ibi_dev,
- };
- 
-+static int dw_i3c_of_populate_bus_timing(struct dw_i3c_master *master,
-+					 struct device_node *np)
-+{
-+	u32 val, reg, sda_tx_hold_ns;
-+
-+	master->timing.core_rate = clk_get_rate(master->core_clk);
-+	if (!master->timing.core_rate) {
-+		dev_err(&master->base.dev, "core clock rate not found\n");
-+		return -EINVAL;
-+	}
-+
-+	/* core_period is in nanosecond */
-+	master->timing.core_period =
-+		DIV_ROUND_UP(1000000000, master->timing.core_rate);
-+
-+	/* Parse configurations from the device tree */
-+	if (!of_property_read_u32(np, "i3c-pp-scl-hi-period-ns", &val))
-+		master->timing.i3c_pp_scl_high = val;
-+
-+	if (!of_property_read_u32(np, "i3c-pp-scl-lo-period-ns", &val))
-+		master->timing.i3c_pp_scl_low = val;
-+
-+	if (!of_property_read_u32(np, "i3c-od-scl-hi-period-ns", &val))
-+		master->timing.i3c_od_scl_high = val;
-+
-+	if (!of_property_read_u32(np, "i3c-od-scl-lo-period-ns", &val))
-+		master->timing.i3c_od_scl_low = val;
-+
-+	sda_tx_hold_ns = SDA_TX_HOLD_MIN * master->timing.core_period;
-+	if (!of_property_read_u32(np, "sda-tx-hold-ns", &val))
-+		sda_tx_hold_ns = val;
-+
-+	master->timing.timed_reset_scl_low_ns = JESD403_TIMED_RESET_NS_DEF;
-+	if (!of_property_read_u32(np, "timed-reset-scl-low-ns", &val))
-+		master->timing.timed_reset_scl_low_ns = val;
-+
-+	val = clamp((u32)DIV_ROUND_CLOSEST(sda_tx_hold_ns,
-+					   master->timing.core_period),
-+		    (u32)SDA_TX_HOLD_MIN, (u32)SDA_TX_HOLD_MAX);
-+	reg = readl(master->regs + SDA_HOLD_SWITCH_DLY_TIMING);
-+	reg &= ~SDA_TX_HOLD;
-+	reg |= FIELD_PREP(SDA_TX_HOLD, val);
-+	writel(reg, master->regs + SDA_HOLD_SWITCH_DLY_TIMING);
-+
-+	val = DIV_ROUND_CLOSEST(master->timing.timed_reset_scl_low_ns,
-+				master->timing.core_period);
-+	writel(val, master->regs + SCL_LOW_MST_EXT_TIMEOUT);
-+
-+	return 0;
-+}
-+
-+static void dw_i3c_hj_work(struct work_struct *work)
-+{
-+	struct dw_i3c_master *master =
-+		container_of(work, typeof(*master), hj_work);
-+
-+	i3c_master_do_daa(&master->base);
-+}
-+
- int dw_i3c_common_probe(struct dw_i3c_master *master,
- 			struct platform_device *pdev)
- {
- 	const struct i3c_master_controller_ops *ops;
-+	struct device_node *np;
- 	int ret, irq;
- 
- 	if (!master->platform_ops)
-@@ -1430,7 +2584,7 @@ int dw_i3c_common_probe(struct dw_i3c_master *master,
- 		return PTR_ERR(master->core_clk);
- 
- 	master->core_rst = devm_reset_control_get_optional_exclusive(&pdev->dev,
--								    "core_rst");
-+								    NULL);
- 	if (IS_ERR(master->core_rst))
- 		return PTR_ERR(master->core_rst);
- 
-@@ -1453,6 +2607,11 @@ int dw_i3c_common_probe(struct dw_i3c_master *master,
- 
- 	platform_set_drvdata(pdev, master);
- 
-+	np = pdev->dev.of_node;
-+	ret = dw_i3c_of_populate_bus_timing(master, np);
-+	if (ret)
-+		goto err_assert_rst;
-+
- 	/* Information regarding the FIFOs/QUEUEs depth */
- 	ret = readl(master->regs + QUEUE_STATUS_LEVEL);
- 	master->caps.cmdfifodepth = QUEUE_STATUS_LEVEL_CMD(ret);
-@@ -1469,10 +2628,17 @@ int dw_i3c_common_probe(struct dw_i3c_master *master,
- 	if (master->ibi_capable)
- 		ops = &dw_mipi_i3c_ibi_ops;
- 
--	ret = i3c_master_register(&master->base, &pdev->dev, ops, false);
-+	INIT_WORK(&master->hj_work, dw_i3c_hj_work);
-+	ret = i3c_register(&master->base, &pdev->dev, ops,
-+			   &dw_mipi_i3c_target_ops, false);
- 	if (ret)
- 		goto err_assert_rst;
- 
-+	if (!master->base.target && master->base.bus.context != I3C_BUS_CONTEXT_JESD403) {
-+		dw_i3c_master_set_iba(master, true);
-+		dw_i3c_master_enable_hotjoin(&master->base);
-+	}
-+
- 	return 0;
- 
- err_assert_rst:
-@@ -1487,7 +2653,8 @@ EXPORT_SYMBOL_GPL(dw_i3c_common_probe);
- 
- void dw_i3c_common_remove(struct dw_i3c_master *master)
- {
--	i3c_master_unregister(&master->base);
-+	cancel_work_sync(&master->hj_work);
-+	i3c_unregister(&master->base);
- 
- 	reset_control_assert(master->core_rst);
- 
-diff --git a/drivers/i3c/master/dw-i3c-master.h b/drivers/i3c/master/dw-i3c-master.h
-index ab862c5d1..739cd8115 100644
---- a/drivers/i3c/master/dw-i3c-master.h
-+++ b/drivers/i3c/master/dw-i3c-master.h
-@@ -10,7 +10,7 @@
- #include <linux/reset.h>
- #include <linux/types.h>
- 
--#define DW_I3C_MAX_DEVS 32
-+#define DW_I3C_MAX_DEVS 128
- 
- struct dw_i3c_master_caps {
- 	u8 cmdfifodepth;
-@@ -22,6 +22,11 @@ struct dw_i3c_dat_entry {
- 	struct i3c_dev_desc *ibi_dev;
- };
- 
-+struct dw_i3c_i2c_dev_data {
-+	u8 index;
-+	struct i3c_generic_ibi_pool *ibi_pool;
-+};
-+
- struct dw_i3c_master {
- 	struct i3c_master_controller base;
- 	u16 maxdevs;
-@@ -57,6 +62,29 @@ struct dw_i3c_master {
- 
- 	/* platform-specific data */
- 	const struct dw_i3c_platform_ops *platform_ops;
-+
-+	/* target mode data */
-+	struct {
-+		struct completion comp;
-+		struct completion rdata_comp;
-+
-+		/* Used for handling private write */
-+		struct {
-+			void *buf;
-+			u16 max_len;
-+		} rx;
-+	} target;
-+
-+	struct {
-+		unsigned long core_rate;
-+		unsigned long core_period;
-+		u32 i3c_od_scl_low;
-+		u32 i3c_od_scl_high;
-+		u32 i3c_pp_scl_low;
-+		u32 i3c_pp_scl_high;
-+		u32 timed_reset_scl_low_ns;
-+	} timing;
-+	struct work_struct hj_work;
- };
- 
- struct dw_i3c_platform_ops {
-@@ -76,6 +104,36 @@ struct dw_i3c_platform_ops {
- 	 */
- 	void (*set_dat_ibi)(struct dw_i3c_master *i3c,
- 			    struct i3c_dev_desc *dev, bool enable, u32 *reg);
-+	void (*set_sir_enabled)(struct dw_i3c_master *i3c,
-+				struct i3c_dev_desc *dev, u8 idx, bool enable);
-+
-+	/* Enter the software force mode by isolating the SCL and SDA pins */
-+	void (*enter_sw_mode)(struct dw_i3c_master *i3c);
-+
-+	/* Exit the software force mode */
-+	void (*exit_sw_mode)(struct dw_i3c_master *i3c);
-+	void (*toggle_scl_in)(struct dw_i3c_master *i3c, int count);
-+	void (*gen_internal_stop)(struct dw_i3c_master *i3c);
-+	void (*gen_target_reset_pattern)(struct dw_i3c_master *i3c);
-+	void (*gen_tbits_in)(struct dw_i3c_master *i3c);
-+	int (*bus_recovery)(struct dw_i3c_master *i3c);
-+
-+	/* For target mode, pending read notification */
-+	void (*set_ibi_mdb)(struct dw_i3c_master *i3c, u8 mdb);
-+
-+	/* DAT handling */
-+	int (*reattach_i3c_dev)(struct i3c_dev_desc *dev, u8 old_dyn_addr);
-+	int (*attach_i3c_dev)(struct i3c_dev_desc *dev);
-+	void (*detach_i3c_dev)(struct i3c_dev_desc *dev);
-+	int (*attach_i2c_dev)(struct i2c_dev_desc *dev);
-+	void (*detach_i2c_dev)(struct i2c_dev_desc *dev);
-+	int (*get_addr_pos)(struct dw_i3c_master *i3c, u8 addr);
-+	int (*flush_dat)(struct dw_i3c_master *i3c, u8 addr);
-+	void (*set_ibi_dev)(struct dw_i3c_master *i3c,
-+			    struct i3c_dev_desc *dev);
-+	void (*unset_ibi_dev)(struct dw_i3c_master *i3c,
-+			      struct i3c_dev_desc *dev);
-+	struct i3c_dev_desc *(*get_ibi_dev)(struct dw_i3c_master *i3c, u8 addr);
- };
- 
- extern int dw_i3c_common_probe(struct dw_i3c_master *master,
-diff --git a/drivers/i3c/master/i3c-master-cdns.c b/drivers/i3c/master/i3c-master-cdns.c
-index fa5aaaf44..7bbdde201 100644
---- a/drivers/i3c/master/i3c-master-cdns.c
-+++ b/drivers/i3c/master/i3c-master-cdns.c
-@@ -813,7 +813,7 @@ static int cdns_i3c_master_priv_xfers(struct i3c_dev_desc *dev,
- }
- 
- static int cdns_i3c_master_i2c_xfers(struct i2c_dev_desc *dev,
--				     const struct i2c_msg *xfers, int nxfers)
-+				     struct i2c_msg *xfers, int nxfers)
- {
- 	struct i3c_master_controller *m = i2c_dev_get_master(dev);
- 	struct cdns_i3c_master *master = to_cdns_i3c_master(m);
-@@ -1666,6 +1666,7 @@ static void cdns_i3c_master_remove(struct platform_device *pdev)
- {
- 	struct cdns_i3c_master *master = platform_get_drvdata(pdev);
- 
-+	cancel_work_sync(&master->hj_work);
- 	i3c_master_unregister(&master->base);
- 
- 	clk_disable_unprepare(master->sysclk);
 diff --git a/drivers/i3c/master/mipi-i3c-hci/cmd.h b/drivers/i3c/master/mipi-i3c-hci/cmd.h
 index 1d6dd2c5d..e3f207e32 100644
 --- a/drivers/i3c/master/mipi-i3c-hci/cmd.h
@@ -6649,7 +4040,7 @@
  	unsigned int mode = XFERMODE_IDX_I3C_SDR;
  	unsigned int rate = get_i3c_rate_idx(hci);
 diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c
-index 837af83c8..ee44e01cb 100644
+index 837af83c8..d85bafa5c 100644
 --- a/drivers/i3c/master/mipi-i3c-hci/core.c
 +++ b/drivers/i3c/master/mipi-i3c-hci/core.c
 @@ -10,17 +10,23 @@
@@ -6676,7 +4067,7 @@
  
  
  /*
-@@ -117,6 +123,168 @@
+@@ -117,6 +123,176 @@
  #define DEV_CTX_BASE_LO			0x60
  #define DEV_CTX_BASE_HI			0x64
  
@@ -6746,7 +4137,7 @@
 +	u16 hcnt, lcnt, total_cnt, min_tbit_cnt;
 +	unsigned long core_rate, core_period;
 +	u32 val, pp_high = 0, pp_low = 0, od_high = 0, od_low = 0, thd_dat = 0, internal_pu = 0;
-+	u32 ctrl0, ctrl1, ctrl2;
++	u32 ctrl0, ctrl1, ctrl2, sr_p_prepare_ctrl;
 +	u32 sdr_ctrl0_reg = aspeed_i3c_get_sdr_phy_reg(hci);
 +
 +	core_rate = clk_get_rate(hci->clk);
@@ -6803,6 +4194,18 @@
 +	ast_phy_write(PHY_I3C_SDR0_CTRL1, ctrl1);
 +	ast_phy_write(PHY_I3C_DDR_CTRL1, ctrl1);
 +
++	/* The push-pull high count is used as both tCAS and tCBP. */
++	ast_phy_write(PHY_I3C_OD_CTRL0, FIELD_PREP(PHY_I3C_OD_CTRL0_CAS, hcnt) |
++						FIELD_PREP(PHY_I3C_OD_CTRL0_CBP, hcnt));
++	/*
++	 * The SR_P hold time uses the default value, and the SR_P low count is
++	 * the same as the push-pull low count.
++	 */
++	hcnt = DIV_ROUND_CLOSEST(PHY_I3C_SR_P_DEFAULT_HD_NS, core_period);
++	sr_p_prepare_ctrl = FIELD_PREP(PHY_I3C_SR_P_PREPARE_CTRL_HD, hcnt) |
++			    FIELD_PREP(PHY_I3C_SR_P_PREPARE_CTRL_SCL_L, lcnt);
++	ast_phy_write(PHY_I3C_SR_P_PREPARE_CTRL, sr_p_prepare_ctrl);
++
 +	if (od_high && od_low) {
 +		hcnt = DIV_ROUND_CLOSEST(od_high, core_period) - 1;
 +		lcnt = DIV_ROUND_CLOSEST(od_low, core_period) - 1;
@@ -6831,10 +4234,6 @@
 +	ast_phy_write(PHY_I3C_OD_CTRL3, FIELD_PREP(PHY_I3C_OD_CTRL3_HD_DAT, hcnt) |
 +						FIELD_PREP(PHY_I3C_OD_CTRL3_AHD_DAT, lcnt));
 +
-+	hcnt = DIV_ROUND_CLOSEST(PHY_I3C_OD_DEFAULT_CAS_NS, core_period) - 1;
-+	lcnt = DIV_ROUND_CLOSEST(PHY_I3C_OD_DEFAULT_CBP_NS, core_period) - 1;
-+	ast_phy_write(PHY_I3C_OD_CTRL0, FIELD_PREP(PHY_I3C_OD_CTRL0_CAS, hcnt) |
-+						FIELD_PREP(PHY_I3C_OD_CTRL0_CBP, lcnt));
 +	if (internal_pu)
 +		ast_phy_write(PHY_SW_FORCE_CTRL,
 +			      PHY_SW_FORCE_CTRL_SCL_PU_EN | PHY_SW_FORCE_CTRL_SDA_PU_EN |
@@ -6845,7 +4244,7 @@
  
  static inline struct i3c_hci *to_i3c_hci(struct i3c_master_controller *m)
  {
-@@ -130,6 +298,16 @@ static int i3c_hci_bus_init(struct i3c_master_controller *m)
+@@ -130,6 +306,16 @@ static int i3c_hci_bus_init(struct i3c_master_controller *m)
  	int ret;
  
  	DBG("");
@@ -6862,7 +4261,7 @@
  
  	if (hci->cmd == &mipi_i3c_hci_cmd_v1) {
  		ret = mipi_i3c_hci_dat_v1.init(hci);
-@@ -144,6 +322,16 @@ static int i3c_hci_bus_init(struct i3c_master_controller *m)
+@@ -144,6 +330,16 @@ static int i3c_hci_bus_init(struct i3c_master_controller *m)
  		  MASTER_DYNAMIC_ADDR(ret) | MASTER_DYNAMIC_ADDR_VALID);
  	memset(&info, 0, sizeof(info));
  	info.dyn_addr = ret;
@@ -6879,7 +4278,7 @@
  	ret = i3c_master_set_info(m, &info);
  	if (ret)
  		return ret;
-@@ -161,25 +349,74 @@ static int i3c_hci_bus_init(struct i3c_master_controller *m)
+@@ -161,25 +357,80 @@ static int i3c_hci_bus_init(struct i3c_master_controller *m)
  static void i3c_hci_bus_cleanup(struct i3c_master_controller *m)
  {
  	struct i3c_hci *hci = to_i3c_hci(m);
@@ -6954,17 +4353,23 @@
 -	reg_write(RESET_CONTROL, RX_FIFO_RST | TX_FIFO_RST | RESP_QUEUE_RST);
 +	reg_write(RESET_CONTROL,
 +		  RX_FIFO_RST | TX_FIFO_RST | RESP_QUEUE_RST | CMD_QUEUE_RST);
++}
++
++/* located here rather than pio.c because needed bits are in core reg space */
++void mipi_i3c_hci_pio_ibi_reset(struct i3c_hci *hci)
++{
++	reg_write(RESET_CONTROL, IBI_QUEUE_RST);
  }
  
  /* located here rather than dct.c because needed bits are in core reg space */
-@@ -188,6 +425,28 @@ void mipi_i3c_hci_dct_index_reset(struct i3c_hci *hci)
+@@ -188,6 +439,28 @@ void mipi_i3c_hci_dct_index_reset(struct i3c_hci *hci)
  	reg_write(DCT_SECTION, FIELD_PREP(DCT_TABLE_INDEX, 0));
  }
  
 +static int i3c_hci_enable_hotjoin(struct i3c_master_controller *m)
 +{
 +	struct i3c_hci *hci = to_i3c_hci(m);
-+	int ret;
++	int ret = 0;
 +
 +	if (hci->io->request_hj)
 +		ret = hci->io->request_hj(hci);
@@ -6986,7 +4391,7 @@
  static int i3c_hci_send_ccc_cmd(struct i3c_master_controller *m,
  				struct i3c_ccc_cmd *ccc)
  {
-@@ -199,8 +458,9 @@ static int i3c_hci_send_ccc_cmd(struct i3c_master_controller *m,
+@@ -199,8 +472,9 @@ static int i3c_hci_send_ccc_cmd(struct i3c_master_controller *m,
  	DECLARE_COMPLETION_ONSTACK(done);
  	int i, last, ret = 0;
  
@@ -6998,7 +4403,7 @@
  
  	xfer = hci_alloc_xfer(nxfers);
  	if (!xfer)
-@@ -210,8 +470,8 @@ static int i3c_hci_send_ccc_cmd(struct i3c_master_controller *m,
+@@ -210,8 +484,8 @@ static int i3c_hci_send_ccc_cmd(struct i3c_master_controller *m,
  		xfer->data = NULL;
  		xfer->data_len = 0;
  		xfer->rnw = false;
@@ -7009,7 +4414,7 @@
  		xfer++;
  	}
  
-@@ -220,7 +480,7 @@ static int i3c_hci_send_ccc_cmd(struct i3c_master_controller *m,
+@@ -220,7 +494,7 @@ static int i3c_hci_send_ccc_cmd(struct i3c_master_controller *m,
  		xfer[i].data_len = ccc->dests[i].payload.len;
  		xfer[i].rnw = ccc->rnw;
  		ret = hci->cmd->prep_ccc(hci, &xfer[i], ccc->dests[i].addr,
@@ -7018,7 +4423,7 @@
  		if (ret)
  			goto out;
  		xfer[i].cmd_desc[0] |= CMD_0_ROC;
-@@ -244,7 +504,16 @@ static int i3c_hci_send_ccc_cmd(struct i3c_master_controller *m,
+@@ -244,7 +518,16 @@ static int i3c_hci_send_ccc_cmd(struct i3c_master_controller *m,
  		if (ccc->rnw)
  			ccc->dests[i - prefixed].payload.len =
  				RESP_DATA_LENGTH(xfer[i].response);
@@ -7036,7 +4441,7 @@
  			ret = -EIO;
  			goto out;
  		}
-@@ -268,6 +537,34 @@ static int i3c_hci_daa(struct i3c_master_controller *m)
+@@ -268,6 +551,34 @@ static int i3c_hci_daa(struct i3c_master_controller *m)
  	return hci->cmd->perform_daa(hci);
  }
  
@@ -7071,7 +4476,7 @@
  static int i3c_hci_priv_xfers(struct i3c_dev_desc *dev,
  			      struct i3c_priv_xfer *i3c_xfers,
  			      int nxfers)
-@@ -301,6 +598,9 @@ static int i3c_hci_priv_xfers(struct i3c_dev_desc *dev,
+@@ -301,6 +612,9 @@ static int i3c_hci_priv_xfers(struct i3c_dev_desc *dev,
  		}
  		hci->cmd->prep_i3c_xfer(hci, dev, &xfer[i]);
  		xfer[i].cmd_desc[0] |= CMD_0_ROC;
@@ -7081,7 +4486,7 @@
  	}
  	last = i - 1;
  	xfer[last].cmd_desc[0] |= CMD_0_TOC;
-@@ -318,18 +618,88 @@ static int i3c_hci_priv_xfers(struct i3c_dev_desc *dev,
+@@ -318,18 +632,88 @@ static int i3c_hci_priv_xfers(struct i3c_dev_desc *dev,
  		if (i3c_xfers[i].rnw)
  			i3c_xfers[i].len = RESP_DATA_LENGTH(xfer[i].response);
  		if (RESP_STATUS(xfer[i].response) != RESP_SUCCESS) {
@@ -7171,7 +4576,7 @@
  {
  	struct i3c_master_controller *m = i2c_dev_get_master(dev);
  	struct i3c_hci *hci = to_i3c_hci(m);
-@@ -344,7 +714,7 @@ static int i3c_hci_i2c_xfers(struct i2c_dev_desc *dev,
+@@ -344,7 +728,7 @@ static int i3c_hci_i2c_xfers(struct i2c_dev_desc *dev,
  		return -ENOMEM;
  
  	for (i = 0; i < nxfers; i++) {
@@ -7180,7 +4585,7 @@
  		xfer[i].data_len = i2c_xfers[i].len;
  		xfer[i].rnw = i2c_xfers[i].flags & I2C_M_RD;
  		hci->cmd->prep_i2c_xfer(hci, dev, &xfer[i]);
-@@ -364,12 +734,18 @@ static int i3c_hci_i2c_xfers(struct i2c_dev_desc *dev,
+@@ -364,12 +748,18 @@ static int i3c_hci_i2c_xfers(struct i2c_dev_desc *dev,
  	}
  	for (i = 0; i < nxfers; i++) {
  		if (RESP_STATUS(xfer[i].response) != RESP_SUCCESS) {
@@ -7199,7 +4604,7 @@
  	hci_free_xfer(xfer, nxfers);
  	return ret;
  }
-@@ -387,12 +763,18 @@ static int i3c_hci_attach_i3c_dev(struct i3c_dev_desc *dev)
+@@ -387,12 +777,18 @@ static int i3c_hci_attach_i3c_dev(struct i3c_dev_desc *dev)
  	if (!dev_data)
  		return -ENOMEM;
  	if (hci->cmd == &mipi_i3c_hci_cmd_v1) {
@@ -7219,7 +4624,7 @@
  		dev_data->dat_idx = ret;
  	}
  	i3c_dev_set_master_data(dev, dev_data);
-@@ -410,6 +792,9 @@ static int i3c_hci_reattach_i3c_dev(struct i3c_dev_desc *dev, u8 old_dyn_addr)
+@@ -410,6 +806,9 @@ static int i3c_hci_reattach_i3c_dev(struct i3c_dev_desc *dev, u8 old_dyn_addr)
  	if (hci->cmd == &mipi_i3c_hci_cmd_v1)
  		mipi_i3c_hci_dat_v1.set_dynamic_addr(hci, dev_data->dat_idx,
  					     dev->info.dyn_addr);
@@ -7229,7 +4634,7 @@
  	return 0;
  }
  
-@@ -441,7 +826,11 @@ static int i3c_hci_attach_i2c_dev(struct i2c_dev_desc *dev)
+@@ -441,7 +840,11 @@ static int i3c_hci_attach_i2c_dev(struct i2c_dev_desc *dev)
  	dev_data = kzalloc(sizeof(*dev_data), GFP_KERNEL);
  	if (!dev_data)
  		return -ENOMEM;
@@ -7242,7 +4647,7 @@
  	if (ret < 0) {
  		kfree(dev_data);
  		return ret;
-@@ -524,8 +913,10 @@ static void i3c_hci_recycle_ibi_slot(struct i3c_dev_desc *dev,
+@@ -524,8 +927,10 @@ static void i3c_hci_recycle_ibi_slot(struct i3c_dev_desc *dev,
  static const struct i3c_master_controller_ops i3c_hci_ops = {
  	.bus_init		= i3c_hci_bus_init,
  	.bus_cleanup		= i3c_hci_bus_cleanup,
@@ -7253,7 +4658,7 @@
  	.priv_xfers		= i3c_hci_priv_xfers,
  	.i2c_xfers		= i3c_hci_i2c_xfers,
  	.attach_i3c_dev		= i3c_hci_attach_i3c_dev,
-@@ -538,6 +929,269 @@ static const struct i3c_master_controller_ops i3c_hci_ops = {
+@@ -538,6 +943,282 @@ static const struct i3c_master_controller_ops i3c_hci_ops = {
  	.enable_ibi		= i3c_hci_enable_ibi,
  	.disable_ibi		= i3c_hci_disable_ibi,
  	.recycle_ibi_slot	= i3c_hci_recycle_ibi_slot,
@@ -7261,6 +4666,15 @@
 +	.disable_hotjoin	= i3c_hci_disable_hotjoin,
 +};
 +
++static void i3c_hci_halt_rst_work(struct work_struct *work)
++{
++	struct i3c_hci *hci;
++
++	hci = container_of(work, struct i3c_hci, halt_rst_work);
++	hci->io->dequeue_xfer(hci, NULL, 0);
++	reg_write(INTR_SIGNAL_ENABLE, INTR_HC_INTERNAL_ERR);
++}
++
 +static int ast2700_i3c_target_bus_init(struct i3c_master_controller *m)
 +{
 +	struct i3c_hci *hci = to_i3c_hci(m);
@@ -7311,6 +4725,10 @@
 +	if (ret)
 +		return ret;
 +
++	/* Enable internal error interrupt to detect the i3c halt caused by the hardware error */
++	reg_write(INTR_SIGNAL_ENABLE, INTR_HC_INTERNAL_ERR);
++	INIT_WORK(&hci->halt_rst_work, i3c_hci_halt_rst_work);
++
 +	reg_set(HC_CONTROL, HC_CONTROL_BUS_ENABLE);
 +	DBG("HC_CONTROL = %#x", reg_read(HC_CONTROL));
 +
@@ -7523,8 +4941,17 @@
  };
  
  static irqreturn_t i3c_hci_irq_handler(int irq, void *dev_id)
-@@ -564,25 +1218,68 @@ static irqreturn_t i3c_hci_irq_handler(int irq, void *dev_id)
- 		dev_err(&hci->master.dev, "Host Controller Internal Error\n");
+@@ -561,28 +1242,76 @@ static irqreturn_t i3c_hci_irq_handler(int irq, void *dev_id)
+ 		val &= ~INTR_HC_RESET_CANCEL;
+ 	}
+ 	if (val & INTR_HC_INTERNAL_ERR) {
+-		dev_err(&hci->master.dev, "Host Controller Internal Error\n");
++		if (hci->master.target) {
++			/* Disable the signal enable to avoid the interrupt storm */
++			reg_write(INTR_SIGNAL_ENABLE, 0x0);
++			reg_write(INTR_STATUS, INTR_HC_INTERNAL_ERR);
++			queue_work(hci->master.wq, &hci->halt_rst_work);
++		}
  		val &= ~INTR_HC_INTERNAL_ERR;
  	}
 -	if (val & INTR_HC_PIO) {
@@ -7553,7 +4980,10 @@
  		hci->io->irq_handler(hci, 0);
 -		val &= ~INTR_HC_PIO;
 +		val &= ~ASPEED_INTR_SUM_PIO;
-+	}
+ 	}
+-	if (val & INTR_HC_RINGS) {
+-		hci->io->irq_handler(hci, val & INTR_HC_RINGS);
+-		val &= ~INTR_HC_RINGS;
 +	if (val & ASPEED_INTR_SUM_RHS) {
 +		/*
 +		 * ASPEED only has one ring, and HCI v1.2 doesn't have a register to indicate which
@@ -7562,16 +4992,13 @@
 +		hci->io->irq_handler(hci, 1);
 +		val &= ~ASPEED_INTR_SUM_RHS;
  	}
--	if (val & INTR_HC_RINGS) {
--		hci->io->irq_handler(hci, val & INTR_HC_RINGS);
--		val &= ~INTR_HC_RINGS;
 +	if (val & ASPEED_INTR_SUM_INHOUSE) {
 +		inhouse_val = ast_inhouse_read(ASPEED_I3C_INTR_STATUS);
 +		DBG("Inhouse INTR_STATUS = %#x/%#x\n", inhouse_val,
 +		    ast_inhouse_read(ASPEED_I3C_INTR_SIGNAL_ENABLE));
 +		ast_inhouse_write(ASPEED_I3C_INTR_STATUS, inhouse_val);
 +		val &= ~ASPEED_INTR_SUM_INHOUSE;
- 	}
++	}
 +
  	if (val)
 -		dev_err(&hci->master.dev, "unexpected INTR_STATUS %#x\n", val);
@@ -7598,7 +5025,7 @@
  	int ret;
  
  	/* Validate HCI hardware version */
-@@ -604,23 +1301,30 @@ static int i3c_hci_init(struct i3c_hci *hci)
+@@ -604,23 +1333,30 @@ static int i3c_hci_init(struct i3c_hci *hci)
  	}
  
  	hci->caps = reg_read(HC_CAPABILITIES);
@@ -7634,7 +5061,7 @@
  
  	regval = reg_read(RING_HEADERS_SECTION);
  	offset = FIELD_GET(RING_HEADERS_OFFSET, regval);
-@@ -659,6 +1363,10 @@ static int i3c_hci_init(struct i3c_hci *hci)
+@@ -659,6 +1395,10 @@ static int i3c_hci_init(struct i3c_hci *hci)
  	/* Disable all interrupts and allow all signal updates */
  	reg_write(INTR_SIGNAL_ENABLE, 0x0);
  	reg_write(INTR_STATUS_ENABLE, 0xffffffff);
@@ -7645,7 +5072,7 @@
  
  	/* Make sure our data ordering fits the host's */
  	regval = reg_read(HC_CONTROL);
-@@ -703,9 +1411,19 @@ static int i3c_hci_init(struct i3c_hci *hci)
+@@ -703,9 +1443,19 @@ static int i3c_hci_init(struct i3c_hci *hci)
  		if (reg_read(HC_CONTROL) & HC_CONTROL_PIO_MODE) {
  			dev_err(&hci->master.dev, "PIO mode is stuck\n");
  			ret = -EIO;
@@ -7665,7 +5092,7 @@
  		}
  	}
  
-@@ -731,6 +1449,14 @@ static int i3c_hci_init(struct i3c_hci *hci)
+@@ -731,6 +1481,14 @@ static int i3c_hci_init(struct i3c_hci *hci)
  	return 0;
  }
  
@@ -7680,7 +5107,7 @@
  static int i3c_hci_probe(struct platform_device *pdev)
  {
  	struct i3c_hci *hci;
-@@ -747,20 +1473,49 @@ static int i3c_hci_probe(struct platform_device *pdev)
+@@ -747,20 +1505,49 @@ static int i3c_hci_probe(struct platform_device *pdev)
  	/* temporary for dev_printk's, to be replaced in i3c_master_register */
  	hci->master.dev.init_name = dev_name(&pdev->dev);
  
@@ -7733,7 +5160,7 @@
  
  	return 0;
  }
-@@ -769,11 +1524,12 @@ static void i3c_hci_remove(struct platform_device *pdev)
+@@ -769,11 +1556,12 @@ static void i3c_hci_remove(struct platform_device *pdev)
  {
  	struct i3c_hci *hci = platform_get_drvdata(pdev);
  
@@ -7747,7 +5174,7 @@
  	{},
  };
  MODULE_DEVICE_TABLE(of, i3c_hci_of_match);
-@@ -787,6 +1543,7 @@ static struct platform_driver i3c_hci_driver = {
+@@ -787,6 +1575,7 @@ static struct platform_driver i3c_hci_driver = {
  	},
  };
  module_platform_driver(i3c_hci_driver);
@@ -7858,7 +5285,7 @@
  	return -ENODEV;
  }
 diff --git a/drivers/i3c/master/mipi-i3c-hci/dma.c b/drivers/i3c/master/mipi-i3c-hci/dma.c
-index edc3a69bf..777fa911a 100644
+index bcc0c7d41..8735df026 100644
 --- a/drivers/i3c/master/mipi-i3c-hci/dma.c
 +++ b/drivers/i3c/master/mipi-i3c-hci/dma.c
 @@ -18,7 +18,7 @@
@@ -7901,18 +5328,6 @@
  static void hci_dma_cleanup(struct i3c_hci *hci)
  {
  	struct hci_rings_data *rings = hci->io_data;
-@@ -174,10 +159,10 @@ static void hci_dma_cleanup(struct i3c_hci *hci)
- 	for (i = 0; i < rings->total; i++) {
- 		rh = &rings->headers[i];
- 
-+		rh_reg_write(INTR_SIGNAL_ENABLE, 0);
- 		rh_reg_write(RING_CONTROL, 0);
- 		rh_reg_write(CR_SETUP, 0);
- 		rh_reg_write(IBI_SETUP, 0);
--		rh_reg_write(INTR_SIGNAL_ENABLE, 0);
- 
- 		if (rh->xfer)
- 			dma_free_coherent(&hci->master.dev,
 @@ -229,6 +214,9 @@ static int hci_dma_init(struct i3c_hci *hci)
  	hci->io_data = rings;
  	rings->total = nr_rings;
@@ -8092,11 +5507,15 @@
  
  	return 0;
  }
-@@ -448,9 +482,11 @@ static bool hci_dma_dequeue_xfer(struct i3c_hci *hci,
- 	struct hci_rh_data *rh = &rings->headers[xfer_list[0].ring_number];
+@@ -445,12 +479,14 @@ static bool hci_dma_dequeue_xfer(struct i3c_hci *hci,
+ 				 struct hci_xfer *xfer_list, int n)
+ {
+ 	struct hci_rings_data *rings = hci->io_data;
+-	struct hci_rh_data *rh = &rings->headers[xfer_list[0].ring_number];
++	struct hci_rh_data *rh = &rings->headers[xfer_list ? xfer_list[0].ring_number : 0];
  	unsigned int i;
  	bool did_unqueue = false;
-+	u32 ring_ctrl_val;
++	u32 ring_ctrl_val, op1_val, done_ptr;
  
 +	ring_ctrl_val = rh_reg_read(RING_CONTROL);
  	/* stop the ring */
@@ -8105,16 +5524,27 @@
  	if (wait_for_completion_timeout(&rh->op_done, HZ) == 0) {
  		/*
  		 * We're deep in it if ever this condition is ever met.
-@@ -491,7 +527,7 @@ static bool hci_dma_dequeue_xfer(struct i3c_hci *hci,
+@@ -490,8 +526,18 @@ static bool hci_dma_dequeue_xfer(struct i3c_hci *hci,
+ 		}
  	}
  
++	/* update the software dequeue pointer to the enqueue pointer */
++	spin_lock(&rh->lock);
++	op1_val = rh_reg_read(RING_OPERATION1);
++	op1_val &= ~RING_OP1_CR_ENQ_PTR;
++	done_ptr = FIELD_GET(RING_OP1_CR_SW_DEQ_PTR, op1_val);
++	op1_val |= FIELD_PREP(RING_OP1_CR_ENQ_PTR, done_ptr);
++	DBG("Write RING_OPERATION1 = %x", op1_val);
++	rh_reg_write(RING_OPERATION1, op1_val);
++	spin_unlock(&rh->lock);
++
  	/* restart the ring */
 -	rh_reg_write(RING_CONTROL, RING_CTRL_ENABLE);
 +	rh_reg_write(RING_CONTROL, RING_CTRL_ENABLE | RING_CTRL_RUN_STOP);
  
  	return did_unqueue;
  }
-@@ -504,6 +540,7 @@ static void hci_dma_xfer_done(struct i3c_hci *hci, struct hci_rh_data *rh)
+@@ -504,6 +550,7 @@ static void hci_dma_xfer_done(struct i3c_hci *hci, struct hci_rh_data *rh)
  
  	for (;;) {
  		op2_val = rh_reg_read(RING_OPERATION2);
@@ -8122,7 +5552,7 @@
  		if (done_ptr == FIELD_GET(RING_OP2_CR_DEQ_PTR, op2_val))
  			break;
  
-@@ -511,7 +548,27 @@ static void hci_dma_xfer_done(struct i3c_hci *hci, struct hci_rh_data *rh)
+@@ -511,7 +558,27 @@ static void hci_dma_xfer_done(struct i3c_hci *hci, struct hci_rh_data *rh)
  		resp = *ring_resp;
  		tid = RESP_TID(resp);
  		DBG("resp = 0x%08x", resp);
@@ -8150,7 +5580,7 @@
  		xfer = rh->src_xfers[done_ptr];
  		if (!xfer) {
  			DBG("orphaned ring entry");
-@@ -528,7 +585,6 @@ static void hci_dma_xfer_done(struct i3c_hci *hci, struct hci_rh_data *rh)
+@@ -528,7 +595,6 @@ static void hci_dma_xfer_done(struct i3c_hci *hci, struct hci_rh_data *rh)
  			if (xfer->completion)
  				complete(xfer->completion);
  		}
@@ -8158,7 +5588,7 @@
  		done_ptr = (done_ptr + 1) % rh->xfer_entries;
  		rh->done_ptr = done_ptr;
  	}
-@@ -538,6 +594,7 @@ static void hci_dma_xfer_done(struct i3c_hci *hci, struct hci_rh_data *rh)
+@@ -538,6 +604,7 @@ static void hci_dma_xfer_done(struct i3c_hci *hci, struct hci_rh_data *rh)
  	op1_val = rh_reg_read(RING_OPERATION1);
  	op1_val &= ~RING_OP1_CR_SW_DEQ_PTR;
  	op1_val |= FIELD_PREP(RING_OP1_CR_SW_DEQ_PTR, done_ptr);
@@ -8166,7 +5596,7 @@
  	rh_reg_write(RING_OPERATION1, op1_val);
  	spin_unlock(&rh->lock);
  }
-@@ -593,8 +650,11 @@ static void hci_dma_process_ibi(struct i3c_hci *hci, struct hci_rh_data *rh)
+@@ -593,8 +660,11 @@ static void hci_dma_process_ibi(struct i3c_hci *hci, struct hci_rh_data *rh)
  	unsigned int ptr, enq_ptr, deq_ptr;
  	unsigned int ibi_size, ibi_chunks, ibi_data_offset, first_part;
  	int ibi_addr, last_ptr;
@@ -8178,7 +5608,7 @@
  
  	op1_val = rh_reg_read(RING_OPERATION1);
  	deq_ptr = FIELD_GET(RING_OP1_IBI_DEQ_PTR, op1_val);
-@@ -602,6 +662,9 @@ static void hci_dma_process_ibi(struct i3c_hci *hci, struct hci_rh_data *rh)
+@@ -602,6 +672,9 @@ static void hci_dma_process_ibi(struct i3c_hci *hci, struct hci_rh_data *rh)
  	op2_val = rh_reg_read(RING_OPERATION2);
  	enq_ptr = FIELD_GET(RING_OP2_IBI_ENQ_PTR, op2_val);
  
@@ -8188,7 +5618,7 @@
  	ibi_status_error = 0;
  	ibi_addr = -1;
  	ibi_chunks = 0;
-@@ -611,13 +674,27 @@ static void hci_dma_process_ibi(struct i3c_hci *hci, struct hci_rh_data *rh)
+@@ -611,13 +684,27 @@ static void hci_dma_process_ibi(struct i3c_hci *hci, struct hci_rh_data *rh)
  	/* let's find all we can about this IBI */
  	for (ptr = deq_ptr; ptr != enq_ptr;
  	     ptr = (ptr + 1) % rh->ibi_status_entries) {
@@ -8221,7 +5651,7 @@
  		if (ibi_status_error) {
  			/* we no longer care */
  		} else if (ibi_status & IBI_ERROR) {
-@@ -628,6 +705,7 @@ static void hci_dma_process_ibi(struct i3c_hci *hci, struct hci_rh_data *rh)
+@@ -628,6 +715,7 @@ static void hci_dma_process_ibi(struct i3c_hci *hci, struct hci_rh_data *rh)
  			/* the address changed unexpectedly */
  			ibi_status_error = ibi_status;
  		}
@@ -8229,7 +5659,7 @@
  
  		chunks = FIELD_GET(IBI_CHUNKS, ibi_status);
  		ibi_chunks += chunks;
-@@ -649,44 +727,55 @@ static void hci_dma_process_ibi(struct i3c_hci *hci, struct hci_rh_data *rh)
+@@ -649,44 +737,55 @@ static void hci_dma_process_ibi(struct i3c_hci *hci, struct hci_rh_data *rh)
  	}
  	deq_ptr = last_ptr + 1;
  	deq_ptr %= rh->ibi_status_entries;
@@ -8319,7 +5749,7 @@
  	/* copy first part of the payload */
  	ibi_data_offset = rh->ibi_chunk_sz * rh->ibi_chunk_ptr;
  	ring_ibi_data = rh->ibi_data + ibi_data_offset;
-@@ -695,10 +784,17 @@ static void hci_dma_process_ibi(struct i3c_hci *hci, struct hci_rh_data *rh)
+@@ -695,10 +794,17 @@ static void hci_dma_process_ibi(struct i3c_hci *hci, struct hci_rh_data *rh)
  			* rh->ibi_chunk_sz;
  	if (first_part > ibi_size)
  		first_part = ibi_size;
@@ -8339,7 +5769,7 @@
  	/* copy second part if any */
  	if (ibi_size > first_part) {
  		/* we wrap back to the start and copy remaining data */
-@@ -706,14 +802,33 @@ static void hci_dma_process_ibi(struct i3c_hci *hci, struct hci_rh_data *rh)
+@@ -706,14 +812,33 @@ static void hci_dma_process_ibi(struct i3c_hci *hci, struct hci_rh_data *rh)
  		ring_ibi_data_dma = rh->ibi_data_dma;
  		dma_sync_single_for_cpu(&hci->master.dev, ring_ibi_data_dma,
  					ibi_size - first_part, DMA_FROM_DEVICE);
@@ -8380,7 +5810,7 @@
  
  done:
  	/* take care to update the ibi dequeue pointer atomically */
-@@ -721,12 +836,15 @@ static void hci_dma_process_ibi(struct i3c_hci *hci, struct hci_rh_data *rh)
+@@ -721,12 +846,15 @@ static void hci_dma_process_ibi(struct i3c_hci *hci, struct hci_rh_data *rh)
  	op1_val = rh_reg_read(RING_OPERATION1);
  	op1_val &= ~RING_OP1_IBI_DEQ_PTR;
  	op1_val |= FIELD_PREP(RING_OP1_IBI_DEQ_PTR, deq_ptr);
@@ -8396,7 +5826,7 @@
  
  	/* and tell the hardware about freed chunks */
  	rh_reg_write(CHUNK_CONTROL, rh_reg_read(CHUNK_CONTROL) + ibi_chunks);
-@@ -755,14 +873,22 @@ static bool hci_dma_irq_handler(struct i3c_hci *hci, unsigned int mask)
+@@ -755,14 +883,30 @@ static bool hci_dma_irq_handler(struct i3c_hci *hci, unsigned int mask)
  
  		if (status & INTR_IBI_READY)
  			hci_dma_process_ibi(hci, rh);
@@ -8416,6 +5846,14 @@
 +		if (status & INTR_TRANSFER_ABORT) {
  			dev_notice_ratelimited(&hci->master.dev,
  				"ring %d: Transfer Aborted\n", i);
++#ifdef CONFIG_ARCH_ASPEED
++			/*
++			 * Aspeed i3c controller will reuse the PIO fifo in DMA mode,
++			 * so we need to reset the PIO fifo when the transfer is aborted.
++			 */
++			mipi_i3c_hci_pio_ibi_reset(hci);
++			mipi_i3c_hci_pio_reset(hci);
++#endif
 +			mipi_i3c_hci_resume(hci);
 +		}
  		if (status & INTR_WARN_INS_STOP_MODE)
@@ -8515,7 +5953,7 @@
  
  int i3c_hci_parse_ext_caps(struct i3c_hci *hci);
 diff --git a/drivers/i3c/master/mipi-i3c-hci/hci.h b/drivers/i3c/master/mipi-i3c-hci/hci.h
-index f109923f6..b1a1614e6 100644
+index f109923f6..a6b556840 100644
 --- a/drivers/i3c/master/mipi-i3c-hci/hci.h
 +++ b/drivers/i3c/master/mipi-i3c-hci/hci.h
 @@ -32,12 +32,18 @@ struct hci_cmd_ops;
@@ -8537,13 +5975,14 @@
  	void __iomem *AUTOCMD_regs;
  	void __iomem *DEBUG_regs;
  	const struct hci_io_ops *io;
-@@ -58,6 +64,15 @@ struct i3c_hci {
+@@ -58,6 +64,16 @@ struct i3c_hci {
  	u32 vendor_version_id;
  	u32 vendor_product_id;
  	void *vendor_data;
 +	struct completion ibi_comp;
 +	struct completion pending_r_comp;
 +	struct work_struct hj_work;
++	struct work_struct halt_rst_work;
 +
 +	/* Used for handling private write */
 +	struct {
@@ -8553,7 +5992,7 @@
  };
  
  
-@@ -90,6 +105,7 @@ struct hci_xfer {
+@@ -90,6 +106,7 @@ struct hci_xfer {
  		struct {
  			/* DMA specific */
  			dma_addr_t data_dma;
@@ -8561,7 +6000,7 @@
  			int ring_number;
  			int ring_entry;
  		};
-@@ -115,6 +131,8 @@ struct hci_io_ops {
+@@ -115,6 +132,8 @@ struct hci_io_ops {
  	int (*request_ibi)(struct i3c_hci *hci, struct i3c_dev_desc *dev,
  			   const struct i3c_ibi_setup *req);
  	void (*free_ibi)(struct i3c_hci *hci, struct i3c_dev_desc *dev);
@@ -8570,9 +6009,11 @@
  	void (*recycle_ibi_slot)(struct i3c_hci *hci, struct i3c_dev_desc *dev,
  				struct i3c_ibi_slot *slot);
  	int (*init)(struct i3c_hci *hci);
-@@ -140,5 +158,6 @@ struct i3c_hci_dev_data {
+@@ -139,6 +158,8 @@ struct i3c_hci_dev_data {
+ /* global functions */
  void mipi_i3c_hci_resume(struct i3c_hci *hci);
  void mipi_i3c_hci_pio_reset(struct i3c_hci *hci);
++void mipi_i3c_hci_pio_ibi_reset(struct i3c_hci *hci);
  void mipi_i3c_hci_dct_index_reset(struct i3c_hci *hci);
 +void mipi_i3c_hci_hj_ctrl(struct i3c_hci *hci, bool ack_nack);
  
@@ -9045,8 +6486,8 @@
 +	.free_hj		= hci_pio_free_hj,
  };
 diff --git a/drivers/i3c/master/mipi-i3c-hci/vendor_aspeed.h b/drivers/i3c/master/mipi-i3c-hci/vendor_aspeed.h
-new file mode 100644
-index 000000000..7577bfc24
+new file mode 100755
+index 000000000..130829086
 --- /dev/null
 +++ b/drivers/i3c/master/mipi-i3c-hci/vendor_aspeed.h
 @@ -0,0 +1,408 @@
@@ -9392,7 +6833,7 @@
 +#define PHY_I3C_SR_P_PREPARE_CTRL		0x80
 +#define PHY_I3C_SR_P_PREPARE_CTRL_HD		GENMASK(25, 16)
 +#define PHY_I3C_SR_P_PREPARE_CTRL_SCL_L		GENMASK(9, 0)
-+#define PHY_I3C_SR_P_DEFAULT_HD_NS	10
++#define PHY_I3C_SR_P_DEFAULT_HD_NS	16
 +#define PHY_I3C_SR_P_DEFAULT_SCL_L_NS	40
 +
 +#define PHY_PULLUP_EN		0x98
@@ -9458,284 +6899,8 @@
 +}
 +
 +#endif
-diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
-index acc937275..f3784764d 100644
---- a/drivers/i3c/master/svc-i3c-master.c
-+++ b/drivers/i3c/master/svc-i3c-master.c
-@@ -128,6 +128,9 @@
- /* This parameter depends on the implementation and may be tuned */
- #define SVC_I3C_FIFO_SIZE 16
- 
-+#define SVC_I3C_EVENT_IBI	GENMASK(7, 0)
-+#define SVC_I3C_EVENT_HOTJOIN	BIT(31)
-+
- struct svc_i3c_cmd {
- 	u8 addr;
- 	bool rnw;
-@@ -178,6 +181,8 @@ struct svc_i3c_regs_save {
-  * @ibi.tbq_slot: To be queued IBI slot
-  * @ibi.lock: IBI lock
-  * @lock: Transfer lock, protect between IBI work thread and callbacks from master
-+ * @enabled_events: Bit masks for enable events (IBI, HotJoin).
-+ * @mctrl_config: Configuration value in SVC_I3C_MCTRL for setting speed back.
-  */
- struct svc_i3c_master {
- 	struct i3c_master_controller base;
-@@ -207,6 +212,8 @@ struct svc_i3c_master {
- 		spinlock_t lock;
- 	} ibi;
- 	struct mutex lock;
-+	u32 enabled_events;
-+	u32 mctrl_config;
- };
- 
- /**
-@@ -221,6 +228,11 @@ struct svc_i3c_i2c_dev_data {
- 	struct i3c_generic_ibi_pool *ibi_pool;
- };
- 
-+static inline bool is_events_enabled(struct svc_i3c_master *master, u32 mask)
-+{
-+	return !!(master->enabled_events & mask);
-+}
-+
- static bool svc_i3c_master_error(struct svc_i3c_master *master)
- {
- 	u32 mstatus, merrwarn;
-@@ -440,13 +452,16 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
- 	switch (ibitype) {
- 	case SVC_I3C_MSTATUS_IBITYPE_IBI:
- 		dev = svc_i3c_master_dev_from_addr(master, ibiaddr);
--		if (!dev)
-+		if (!dev || !is_events_enabled(master, SVC_I3C_EVENT_IBI))
- 			svc_i3c_master_nack_ibi(master);
- 		else
- 			svc_i3c_master_handle_ibi(master, dev);
- 		break;
- 	case SVC_I3C_MSTATUS_IBITYPE_HOT_JOIN:
--		svc_i3c_master_ack_ibi(master, false);
-+		if (is_events_enabled(master, SVC_I3C_EVENT_HOTJOIN))
-+			svc_i3c_master_ack_ibi(master, false);
-+		else
-+			svc_i3c_master_nack_ibi(master);
- 		break;
- 	case SVC_I3C_MSTATUS_IBITYPE_MASTER_REQUEST:
- 		svc_i3c_master_nack_ibi(master);
-@@ -483,7 +498,9 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
- 		svc_i3c_master_emit_stop(master);
- 		break;
- 	case SVC_I3C_MSTATUS_IBITYPE_HOT_JOIN:
--		queue_work(master->base.wq, &master->hj_work);
-+		svc_i3c_master_emit_stop(master);
-+		if (is_events_enabled(master, SVC_I3C_EVENT_HOTJOIN))
-+			queue_work(master->base.wq, &master->hj_work);
- 		break;
- 	case SVC_I3C_MSTATUS_IBITYPE_MASTER_REQUEST:
- 	default:
-@@ -514,6 +531,54 @@ static irqreturn_t svc_i3c_master_irq_handler(int irq, void *dev_id)
- 	return IRQ_HANDLED;
- }
- 
-+static int svc_i3c_master_set_speed(struct i3c_master_controller *m,
-+				     enum i3c_open_drain_speed speed)
-+{
-+	struct svc_i3c_master *master = to_svc_i3c_master(m);
-+	struct i3c_bus *bus = i3c_master_get_bus(&master->base);
-+	u32 ppbaud, odbaud, odhpp, mconfig;
-+	unsigned long fclk_rate;
-+	int ret;
-+
-+	ret = pm_runtime_resume_and_get(master->dev);
-+	if (ret < 0) {
-+		dev_err(master->dev, "<%s> Cannot get runtime PM.\n", __func__);
-+		return ret;
-+	}
-+
-+	switch (speed) {
-+	case I3C_OPEN_DRAIN_SLOW_SPEED:
-+		fclk_rate = clk_get_rate(master->fclk);
-+		if (!fclk_rate) {
-+			ret = -EINVAL;
-+			goto rpm_out;
-+		}
-+		/*
-+		 * Set 50% duty-cycle I2C speed to I3C OPEN-DRAIN mode, so the first
-+		 * broadcast address is visible to all I2C/I3C devices on the I3C bus.
-+		 * I3C device working as a I2C device will turn off its 50ns Spike
-+		 * Filter to change to I3C mode.
-+		 */
-+		mconfig = master->mctrl_config;
-+		ppbaud = FIELD_GET(GENMASK(11, 8), mconfig);
-+		odhpp = 0;
-+		odbaud = DIV_ROUND_UP(fclk_rate, bus->scl_rate.i2c * (2 + 2 * ppbaud)) - 1;
-+		mconfig &= ~GENMASK(24, 16);
-+		mconfig |= SVC_I3C_MCONFIG_ODBAUD(odbaud) | SVC_I3C_MCONFIG_ODHPP(odhpp);
-+		writel(mconfig, master->regs + SVC_I3C_MCONFIG);
-+		break;
-+	case I3C_OPEN_DRAIN_NORMAL_SPEED:
-+		writel(master->mctrl_config, master->regs + SVC_I3C_MCONFIG);
-+		break;
-+	}
-+
-+rpm_out:
-+	pm_runtime_mark_last_busy(master->dev);
-+	pm_runtime_put_autosuspend(master->dev);
-+
-+	return ret;
-+}
-+
- static int svc_i3c_master_bus_init(struct i3c_master_controller *m)
- {
- 	struct svc_i3c_master *master = to_svc_i3c_master(m);
-@@ -596,6 +661,7 @@ static int svc_i3c_master_bus_init(struct i3c_master_controller *m)
- 	      SVC_I3C_MCONFIG_I2CBAUD(i2cbaud);
- 	writel(reg, master->regs + SVC_I3C_MCONFIG);
- 
-+	master->mctrl_config = reg;
- 	/* Master core's registration */
- 	ret = i3c_master_get_free_addr(m, 0);
- 	if (ret < 0)
-@@ -798,7 +864,7 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
- 			u8 data[6];
- 
- 			/*
--			 * We only care about the 48-bit provisional ID yet to
-+			 * We only care about the 48-bit provisioned ID yet to
- 			 * be sure a device does not nack an address twice.
- 			 * Otherwise, we would just need to flush the RX FIFO.
- 			 */
-@@ -952,12 +1018,27 @@ static int svc_i3c_master_do_daa(struct i3c_master_controller *m)
- 		goto rpm_out;
- 	}
- 
--	/* Register all devices who participated to the core */
--	for (i = 0; i < dev_nb; i++) {
--		ret = i3c_master_add_i3c_dev_locked(m, addrs[i]);
--		if (ret)
--			goto rpm_out;
--	}
-+	/*
-+	 * Register all devices who participated to the core
-+	 *
-+	 * If two devices (A and B) are detected in DAA and address 0xa is assigned to
-+	 * device A and 0xb to device B, a failure in i3c_master_add_i3c_dev_locked()
-+	 * for device A (addr: 0xa) could prevent device B (addr: 0xb) from being
-+	 * registered on the bus. The I3C stack might still consider 0xb a free
-+	 * address. If a subsequent Hotjoin occurs, 0xb might be assigned to Device A,
-+	 * causing both devices A and B to use the same address 0xb, violating the I3C
-+	 * specification.
-+	 *
-+	 * The return value for i3c_master_add_i3c_dev_locked() should not be checked
-+	 * because subsequent steps will scan the entire I3C bus, independent of
-+	 * whether i3c_master_add_i3c_dev_locked() returns success.
-+	 *
-+	 * If device A registration fails, there is still a chance to register device
-+	 * B. i3c_master_add_i3c_dev_locked() can reset DAA if a failure occurs while
-+	 * retrieving device information.
-+	 */
-+	for (i = 0; i < dev_nb; i++)
-+		i3c_master_add_i3c_dev_locked(m, addrs[i]);
- 
- 	/* Configure IBI auto-rules */
- 	ret = svc_i3c_update_ibirules(master);
-@@ -1416,7 +1497,7 @@ static int svc_i3c_master_priv_xfers(struct i3c_dev_desc *dev,
- }
- 
- static int svc_i3c_master_i2c_xfers(struct i2c_dev_desc *dev,
--				    const struct i2c_msg *xfers,
-+				    struct i2c_msg *xfers,
- 				    int nxfers)
- {
- 	struct i3c_master_controller *m = i2c_dev_get_master(dev);
-@@ -1520,6 +1601,7 @@ static int svc_i3c_master_enable_ibi(struct i3c_dev_desc *dev)
- 		return ret;
- 	}
- 
-+	master->enabled_events++;
- 	svc_i3c_master_enable_interrupts(master, SVC_I3C_MINT_SLVSTART);
- 
- 	return i3c_master_enec_locked(m, dev->info.dyn_addr, I3C_CCC_EVENT_SIR);
-@@ -1531,7 +1613,9 @@ static int svc_i3c_master_disable_ibi(struct i3c_dev_desc *dev)
- 	struct svc_i3c_master *master = to_svc_i3c_master(m);
- 	int ret;
- 
--	svc_i3c_master_disable_interrupts(master);
-+	master->enabled_events--;
-+	if (!master->enabled_events)
-+		svc_i3c_master_disable_interrupts(master);
- 
- 	ret = i3c_master_disec_locked(m, dev->info.dyn_addr, I3C_CCC_EVENT_SIR);
- 
-@@ -1541,6 +1625,39 @@ static int svc_i3c_master_disable_ibi(struct i3c_dev_desc *dev)
- 	return ret;
- }
- 
-+static int svc_i3c_master_enable_hotjoin(struct i3c_master_controller *m)
-+{
-+	struct svc_i3c_master *master = to_svc_i3c_master(m);
-+	int ret;
-+
-+	ret = pm_runtime_resume_and_get(master->dev);
-+	if (ret < 0) {
-+		dev_err(master->dev, "<%s> Cannot get runtime PM.\n", __func__);
-+		return ret;
-+	}
-+
-+	master->enabled_events |= SVC_I3C_EVENT_HOTJOIN;
-+
-+	svc_i3c_master_enable_interrupts(master, SVC_I3C_MINT_SLVSTART);
-+
-+	return 0;
-+}
-+
-+static int svc_i3c_master_disable_hotjoin(struct i3c_master_controller *m)
-+{
-+	struct svc_i3c_master *master = to_svc_i3c_master(m);
-+
-+	master->enabled_events &= ~SVC_I3C_EVENT_HOTJOIN;
-+
-+	if (!master->enabled_events)
-+		svc_i3c_master_disable_interrupts(master);
-+
-+	pm_runtime_mark_last_busy(master->dev);
-+	pm_runtime_put_autosuspend(master->dev);
-+
-+	return 0;
-+}
-+
- static void svc_i3c_master_recycle_ibi_slot(struct i3c_dev_desc *dev,
- 					    struct i3c_ibi_slot *slot)
- {
-@@ -1567,6 +1684,9 @@ static const struct i3c_master_controller_ops svc_i3c_master_ops = {
- 	.recycle_ibi_slot = svc_i3c_master_recycle_ibi_slot,
- 	.enable_ibi = svc_i3c_master_enable_ibi,
- 	.disable_ibi = svc_i3c_master_disable_ibi,
-+	.enable_hotjoin = svc_i3c_master_enable_hotjoin,
-+	.disable_hotjoin = svc_i3c_master_disable_hotjoin,
-+	.set_speed = svc_i3c_master_set_speed,
- };
- 
- static int svc_i3c_master_prepare_clks(struct svc_i3c_master *master)
-@@ -1684,8 +1804,8 @@ static int svc_i3c_master_probe(struct platform_device *pdev)
- rpm_disable:
- 	pm_runtime_dont_use_autosuspend(&pdev->dev);
- 	pm_runtime_put_noidle(&pdev->dev);
--	pm_runtime_set_suspended(&pdev->dev);
- 	pm_runtime_disable(&pdev->dev);
-+	pm_runtime_set_suspended(&pdev->dev);
- 
- err_disable_clks:
- 	svc_i3c_master_unprepare_clks(master);
-@@ -1697,6 +1817,7 @@ static void svc_i3c_master_remove(struct platform_device *pdev)
- {
- 	struct svc_i3c_master *master = platform_get_drvdata(pdev);
- 
-+	cancel_work_sync(&master->hj_work);
- 	i3c_master_unregister(&master->base);
- 
- 	pm_runtime_dont_use_autosuspend(&pdev->dev);
 diff --git a/drivers/i3c/mctp/Kconfig b/drivers/i3c/mctp/Kconfig
-new file mode 100644
+new file mode 100755
 index 000000000..c272bca7e
 --- /dev/null
 +++ b/drivers/i3c/mctp/Kconfig
@@ -9764,7 +6929,7 @@
 +    Say yes here to enable the I3C MCTP driver for I3C HW that is
 +    configured as an I3C Target Device on the I3C Bus.
 diff --git a/drivers/i3c/mctp/Makefile b/drivers/i3c/mctp/Makefile
-new file mode 100644
+new file mode 100755
 index 000000000..05eb78684
 --- /dev/null
 +++ b/drivers/i3c/mctp/Makefile
@@ -9773,7 +6938,7 @@
 +obj-$(CONFIG_I3C_MCTP)		+= i3c-mctp.o
 +obj-$(CONFIG_I3C_TARGET_MCTP)	+= i3c-target-mctp.o
 diff --git a/drivers/i3c/mctp/i3c-mctp.c b/drivers/i3c/mctp/i3c-mctp.c
-new file mode 100644
+new file mode 100755
 index 000000000..c4758de7c
 --- /dev/null
 +++ b/drivers/i3c/mctp/i3c-mctp.c
@@ -10476,7 +7641,7 @@
 +MODULE_DESCRIPTION("I3C MCTP driver");
 +MODULE_LICENSE("GPL");
 diff --git a/drivers/i3c/mctp/i3c-target-mctp.c b/drivers/i3c/mctp/i3c-target-mctp.c
-new file mode 100644
+new file mode 100755
 index 000000000..28645bb15
 --- /dev/null
 +++ b/drivers/i3c/mctp/i3c-target-mctp.c
@@ -11199,7 +8364,7 @@
  
  #endif /* I3C_DEV_H */
 diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
-index 0b52da4f2..1575bdae4 100644
+index f2eb2452f..1575bdae4 100644
 --- a/include/linux/i3c/master.h
 +++ b/include/linux/i3c/master.h
 @@ -24,6 +24,13 @@
@@ -11298,60 +8463,7 @@
  
  /**
   * enum i3c_bus_mode - I3C bus mode
-@@ -269,6 +295,20 @@ enum i3c_bus_mode {
- 	I3C_BUS_MODE_MIXED_SLOW,
- };
- 
-+/**
-+ * enum i3c_open_drain_speed - I3C open-drain speed
-+ * @I3C_OPEN_DRAIN_SLOW_SPEED: Slow open-drain speed for sending the first
-+ *				broadcast address. The first broadcast address at this speed
-+ *				will be visible to all devices on the I3C bus. I3C devices
-+ *				working in I2C mode will turn off their spike filter when
-+ *				switching into I3C mode.
-+ * @I3C_OPEN_DRAIN_NORMAL_SPEED: Normal open-drain speed in I3C bus mode.
-+ */
-+enum i3c_open_drain_speed {
-+	I3C_OPEN_DRAIN_SLOW_SPEED,
-+	I3C_OPEN_DRAIN_NORMAL_SPEED,
-+};
-+
- /**
-  * enum i3c_addr_slot_status - I3C address slot status
-  * @I3C_ADDR_SLOT_FREE: address is free
-@@ -276,7 +316,8 @@ enum i3c_bus_mode {
-  * @I3C_ADDR_SLOT_I2C_DEV: address is assigned to an I2C device
-  * @I3C_ADDR_SLOT_I3C_DEV: address is assigned to an I3C device
-  * @I3C_ADDR_SLOT_STATUS_MASK: address slot mask
-- *
-+ * @I3C_ADDR_SLOT_EXT_DESIRED: the bitmask represents addresses that are preferred by some devices,
-+ *			       such as the "assigned-address" property in a device tree source.
-  * On an I3C bus, addresses are assigned dynamically, and we need to know which
-  * addresses are free to use and which ones are already assigned.
-  *
-@@ -289,8 +330,12 @@ enum i3c_addr_slot_status {
- 	I3C_ADDR_SLOT_I2C_DEV,
- 	I3C_ADDR_SLOT_I3C_DEV,
- 	I3C_ADDR_SLOT_STATUS_MASK = 3,
-+	I3C_ADDR_SLOT_EXT_STATUS_MASK = 7,
-+	I3C_ADDR_SLOT_EXT_DESIRED = BIT(2),
- };
- 
-+#define I3C_ADDR_SLOT_STATUS_BITS 4
-+
- /**
-  * struct i3c_bus - I3C bus object
-  * @cur_master: I3C master currently driving the bus. Since I3C is multi-master
-@@ -332,7 +377,7 @@ enum i3c_addr_slot_status {
- struct i3c_bus {
- 	struct i3c_dev_desc *cur_master;
- 	int id;
--	unsigned long addrslots[((I2C_MAX_ADDR + 1) * 2) / BITS_PER_LONG];
-+	unsigned long addrslots[((I2C_MAX_ADDR + 1) * I3C_ADDR_SLOT_STATUS_BITS) / BITS_PER_LONG];
- 	enum i3c_bus_mode mode;
- 	struct {
- 		unsigned long i3c;
-@@ -343,6 +388,7 @@ struct i3c_bus {
+@@ -362,6 +388,7 @@ struct i3c_bus {
  		struct list_head i2c;
  	} devs;
  	struct rw_semaphore lock;
@@ -11359,7 +8471,7 @@
  };
  
  /**
-@@ -384,6 +430,9 @@ struct i3c_bus {
+@@ -403,6 +430,9 @@ struct i3c_bus {
   *		      all CCC commands are supported.
   * @send_ccc_cmd: send a CCC command
   *		  This method is mandatory.
@@ -11369,14 +8481,7 @@
   * @priv_xfers: do one or several private I3C SDR transfers
   *		This method is mandatory.
   * @attach_i2c_dev: called every time an I2C device is attached to the bus.
-@@ -426,10 +475,14 @@ struct i3c_bus {
-  *		      for a future IBI
-  *		      This method is mandatory only if ->request_ibi is not
-  *		      NULL.
-+ * @enable_hotjoin: enable hot join event detect.
-+ * @disable_hotjoin: disable hot join event detect.
-+ * @set_speed: adjust I3C open drain mode timing.
-  */
+@@ -452,6 +482,7 @@ struct i3c_bus {
  struct i3c_master_controller_ops {
  	int (*bus_init)(struct i3c_master_controller *master);
  	void (*bus_cleanup)(struct i3c_master_controller *master);
@@ -11384,7 +8489,7 @@
  	int (*attach_i3c_dev)(struct i3c_dev_desc *dev);
  	int (*reattach_i3c_dev)(struct i3c_dev_desc *dev, u8 old_dyn_addr);
  	void (*detach_i3c_dev)(struct i3c_dev_desc *dev);
-@@ -438,13 +491,15 @@ struct i3c_master_controller_ops {
+@@ -460,13 +491,15 @@ struct i3c_master_controller_ops {
  				 const struct i3c_ccc_cmd *cmd);
  	int (*send_ccc_cmd)(struct i3c_master_controller *master,
  			    struct i3c_ccc_cmd *cmd);
@@ -11401,17 +8506,7 @@
  	int (*request_ibi)(struct i3c_dev_desc *dev,
  			   const struct i3c_ibi_setup *req);
  	void (*free_ibi)(struct i3c_dev_desc *dev);
-@@ -452,6 +507,9 @@ struct i3c_master_controller_ops {
- 	int (*disable_ibi)(struct i3c_dev_desc *dev);
- 	void (*recycle_ibi_slot)(struct i3c_dev_desc *dev,
- 				 struct i3c_ibi_slot *slot);
-+	int (*enable_hotjoin)(struct i3c_master_controller *master);
-+	int (*disable_hotjoin)(struct i3c_master_controller *master);
-+	int (*set_speed)(struct i3c_master_controller *master, enum i3c_open_drain_speed speed);
- };
- 
- /**
-@@ -463,13 +521,16 @@ struct i3c_master_controller_ops {
+@@ -488,6 +521,8 @@ struct i3c_master_controller_ops {
   *	 registered to the I2C subsystem to be as transparent as possible to
   *	 existing I2C drivers
   * @ops: master operations. See &struct i3c_master_controller_ops
@@ -11419,8 +8514,8 @@
 + * @target: true if the underlying I3C device acts as a target on I3C bus
   * @secondary: true if the master is a secondary master
   * @init_done: true when the bus initialization is done
-+ * @hotjoin: true if the master support hotjoin
-  * @boardinfo.i3c: list of I3C  boardinfo objects
+  * @hotjoin: true if the master support hotjoin
+@@ -495,7 +530,7 @@ struct i3c_master_controller_ops {
   * @boardinfo.i2c: list of I2C boardinfo objects
   * @boardinfo: board-level information attached to devices connected on the bus
   * @bus: I3C bus exposed by this master
@@ -11429,7 +8524,7 @@
   *	drivers if they need to postpone operations that need to take place
   *	in a thread context. Typical examples are Hot Join processing which
   *	requires taking the bus lock in maintenance, which in turn, can only
-@@ -485,8 +546,12 @@ struct i3c_master_controller {
+@@ -511,6 +546,9 @@ struct i3c_master_controller {
  	struct i3c_dev_desc *this;
  	struct i2c_adapter i2c;
  	const struct i3c_master_controller_ops *ops;
@@ -11438,11 +8533,8 @@
 +	unsigned int target : 1;
  	unsigned int secondary : 1;
  	unsigned int init_done : 1;
-+	unsigned int hotjoin: 1;
- 	struct {
- 		struct list_head i3c;
- 		struct list_head i2c;
-@@ -525,7 +590,12 @@ int i3c_master_disec_locked(struct i3c_master_controller *master, u8 addr,
+ 	unsigned int hotjoin: 1;
+@@ -552,7 +590,12 @@ int i3c_master_disec_locked(struct i3c_master_controller *master, u8 addr,
  			    u8 evts);
  int i3c_master_enec_locked(struct i3c_master_controller *master, u8 addr,
  			   u8 evts);
@@ -11455,7 +8547,7 @@
  int i3c_master_defslvs_locked(struct i3c_master_controller *master);
  
  int i3c_master_get_free_addr(struct i3c_master_controller *master,
-@@ -543,6 +613,14 @@ int i3c_master_register(struct i3c_master_controller *master,
+@@ -570,6 +613,12 @@ int i3c_master_register(struct i3c_master_controller *master,
  			const struct i3c_master_controller_ops *ops,
  			bool secondary);
  void i3c_master_unregister(struct i3c_master_controller *master);
@@ -11465,12 +8557,10 @@
 +		 const struct i3c_target_ops *target_ops,
 +		 bool secondary);
 +int i3c_unregister(struct i3c_master_controller *master);
-+int i3c_master_enable_hotjoin(struct i3c_master_controller *master);
-+int i3c_master_disable_hotjoin(struct i3c_master_controller *master);
+ int i3c_master_enable_hotjoin(struct i3c_master_controller *master);
+ int i3c_master_disable_hotjoin(struct i3c_master_controller *master);
  
- /**
-  * i3c_dev_get_master_data() - get master private data attached to an I3C
-@@ -652,4 +730,9 @@ void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct i3c_ibi_slot *slot);
+@@ -681,4 +730,9 @@ void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct i3c_ibi_slot *slot);
  
  struct i3c_ibi_slot *i3c_master_get_free_ibi_slot(struct i3c_dev_desc *dev);
  
@@ -11481,7 +8571,7 @@
 +
  #endif /* I3C_MASTER_H */
 diff --git a/include/linux/i3c/mctp/i3c-mctp.h b/include/linux/i3c/mctp/i3c-mctp.h
-new file mode 100644
+new file mode 100755
 index 000000000..dd20750d7
 --- /dev/null
 +++ b/include/linux/i3c/mctp/i3c-mctp.h
@@ -11537,7 +8627,7 @@
 +
 +#endif /* I3C_MCTP_H */
 diff --git a/include/linux/i3c/target.h b/include/linux/i3c/target.h
-new file mode 100644
+new file mode 100755
 index 000000000..6025b8c2f
 --- /dev/null
 +++ b/include/linux/i3c/target.h
@@ -11573,7 +8663,7 @@
 +
 +#endif
 diff --git a/include/uapi/linux/i3c/i3cdev.h b/include/uapi/linux/i3c/i3cdev.h
-new file mode 100644
+new file mode 100755
 index 000000000..5adc1e3e7
 --- /dev/null
 +++ b/include/uapi/linux/i3c/i3cdev.h
diff --git a/recipes-kernel/linux/files/0018-Add-SOC-drivers-for-ast2700.patch b/recipes-kernel/linux/files/0018-Add-SOC-drivers-for-ast2700.patch
index c410c15..6aa7e89 100644
--- a/recipes-kernel/linux/files/0018-Add-SOC-drivers-for-ast2700.patch
+++ b/recipes-kernel/linux/files/0018-Add-SOC-drivers-for-ast2700.patch
@@ -1,107 +1,64 @@
-From cce4ee8cbd8608ddb5eb34d3ae284e538be60cda Mon Sep 17 00:00:00 2001
-From: "yung-sheng.huang" <yung-sheng.huang@fii-na.corp-partner.google.com>
-Date: Wed, 16 Apr 2025 09:20:36 +0800
-Subject: [PATCH 18/26] Add SOC drivers for ast2700
+From 920f9c75d302d7fff589987ae483b94a6cc5dc2d Mon Sep 17 00:00:00 2001
+From: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+Date: Thu, 17 Jul 2025 16:30:02 +0800
+Subject: [PATCH] Add SOC drivers for ast2700
 
 Refer to SDK user guide about these drivers usage.
-This is base on aspeed SDK 9.06.
+This is base on aspeed SDK 9.07.
 
-Source:
-AspeedTech-BMC github:
-https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/
-(cherry picked from commit v00.06.06)
-
-Signed-off-by: yung-sheng.huang <yung-sheng.huang@fii-na.corp-partner.google.com>
+Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
 ---
- drivers/soc/aspeed/Kconfig                 |  114 +
- drivers/soc/aspeed/Makefile                |   18 +
- drivers/soc/aspeed/aspeed-bmc-dev.c        |  727 ++++++
- drivers/soc/aspeed/aspeed-disp-intf.c      |  255 ++
- drivers/soc/aspeed/aspeed-espi-comm.h      |  196 ++
- drivers/soc/aspeed/aspeed-host-bmc-dev.c   |  803 +++++++
- drivers/soc/aspeed/aspeed-lpc-ctrl.c       |    6 +-
- drivers/soc/aspeed/aspeed-lpc-mbox.c       |  439 ++++
- drivers/soc/aspeed/aspeed-lpc-pcc.c        |  442 ++++
- drivers/soc/aspeed/aspeed-lpc-snoop.c      |  251 +-
- drivers/soc/aspeed/aspeed-mctp.c           | 2523 ++++++++++++++++++++
- drivers/soc/aspeed/aspeed-p2a-ctrl.c       |    6 +-
- drivers/soc/aspeed/aspeed-pcie-mmbi.c      |  383 +++
- drivers/soc/aspeed/aspeed-pcie-mmbi.h      |   20 +
- drivers/soc/aspeed/aspeed-sbc.c            |   73 +
- drivers/soc/aspeed/aspeed-socinfo.c        |   16 +-
- drivers/soc/aspeed/aspeed-ssp.c            |  277 +++
- drivers/soc/aspeed/aspeed-uart-routing.c   |  430 +++-
- drivers/soc/aspeed/aspeed-usb-hp.c         |  153 ++
- drivers/soc/aspeed/aspeed-usb-phy.c        |  113 +
- drivers/soc/aspeed/aspeed-xdma.c           | 1436 +++++++++++
- drivers/soc/aspeed/ast2500-espi.c          | 1739 ++++++++++++++
- drivers/soc/aspeed/ast2500-espi.h          |  250 ++
- drivers/soc/aspeed/ast2600-espi.c          | 2157 +++++++++++++++++
- drivers/soc/aspeed/ast2600-espi.h          |  297 +++
- drivers/soc/aspeed/ast2600-otp.c           |  640 +++++
- drivers/soc/aspeed/ast2700-espi.c          | 2228 +++++++++++++++++
- drivers/soc/aspeed/ast2700-espi.h          |  280 +++
- drivers/soc/aspeed/ast2700-otp.c           |  567 +++++
- drivers/soc/aspeed/rvas/Kconfig            |    9 +
- drivers/soc/aspeed/rvas/Makefile           |    3 +
- drivers/soc/aspeed/rvas/hardware_engines.c | 2203 +++++++++++++++++
- drivers/soc/aspeed/rvas/hardware_engines.h |  551 +++++
- drivers/soc/aspeed/rvas/video.h            |   41 +
- drivers/soc/aspeed/rvas/video_debug.h      |   35 +
- drivers/soc/aspeed/rvas/video_engine.c     | 1338 +++++++++++
- drivers/soc/aspeed/rvas/video_engine.h     |  270 +++
- drivers/soc/aspeed/rvas/video_ioctl.h      |  275 +++
- drivers/soc/aspeed/rvas/video_main.c       | 1850 ++++++++++++++
- include/linux/aspeed-mctp.h                |  155 ++
- include/linux/soc/aspeed/aspeed-otp.h      |   11 +
- include/trace/events/xdma.h                |  139 ++
- include/uapi/linux/aspeed-mctp.h           |  136 ++
- include/uapi/linux/aspeed-xdma.h           |   42 +
- include/uapi/linux/otp_ast2600.h           |   39 +
- include/uapi/linux/otp_ast2700.h           |   47 +
- 46 files changed, 23830 insertions(+), 153 deletions(-)
- create mode 100644 drivers/soc/aspeed/aspeed-bmc-dev.c
- create mode 100644 drivers/soc/aspeed/aspeed-disp-intf.c
- create mode 100644 drivers/soc/aspeed/aspeed-espi-comm.h
- create mode 100644 drivers/soc/aspeed/aspeed-host-bmc-dev.c
- create mode 100644 drivers/soc/aspeed/aspeed-lpc-mbox.c
- create mode 100644 drivers/soc/aspeed/aspeed-lpc-pcc.c
- create mode 100644 drivers/soc/aspeed/aspeed-mctp.c
- create mode 100644 drivers/soc/aspeed/aspeed-pcie-mmbi.c
- create mode 100644 drivers/soc/aspeed/aspeed-pcie-mmbi.h
- create mode 100644 drivers/soc/aspeed/aspeed-sbc.c
- create mode 100644 drivers/soc/aspeed/aspeed-ssp.c
- create mode 100644 drivers/soc/aspeed/aspeed-usb-hp.c
- create mode 100644 drivers/soc/aspeed/aspeed-usb-phy.c
- create mode 100644 drivers/soc/aspeed/aspeed-xdma.c
- create mode 100644 drivers/soc/aspeed/ast2500-espi.c
- create mode 100644 drivers/soc/aspeed/ast2500-espi.h
- create mode 100644 drivers/soc/aspeed/ast2600-espi.c
- create mode 100644 drivers/soc/aspeed/ast2600-espi.h
- create mode 100644 drivers/soc/aspeed/ast2600-otp.c
- create mode 100644 drivers/soc/aspeed/ast2700-espi.c
- create mode 100644 drivers/soc/aspeed/ast2700-espi.h
- create mode 100644 drivers/soc/aspeed/ast2700-otp.c
- create mode 100644 drivers/soc/aspeed/rvas/Kconfig
- create mode 100644 drivers/soc/aspeed/rvas/Makefile
- create mode 100644 drivers/soc/aspeed/rvas/hardware_engines.c
- create mode 100644 drivers/soc/aspeed/rvas/hardware_engines.h
- create mode 100644 drivers/soc/aspeed/rvas/video.h
- create mode 100644 drivers/soc/aspeed/rvas/video_debug.h
- create mode 100644 drivers/soc/aspeed/rvas/video_engine.c
- create mode 100644 drivers/soc/aspeed/rvas/video_engine.h
- create mode 100644 drivers/soc/aspeed/rvas/video_ioctl.h
- create mode 100644 drivers/soc/aspeed/rvas/video_main.c
- create mode 100644 include/linux/aspeed-mctp.h
- create mode 100644 include/linux/soc/aspeed/aspeed-otp.h
- create mode 100644 include/trace/events/xdma.h
- create mode 100644 include/uapi/linux/aspeed-mctp.h
- create mode 100644 include/uapi/linux/aspeed-xdma.h
- create mode 100644 include/uapi/linux/otp_ast2600.h
- create mode 100644 include/uapi/linux/otp_ast2700.h
+ drivers/soc/aspeed/Kconfig               |   68 +
+ drivers/soc/aspeed/Makefile              |   11 +
+ drivers/soc/aspeed/aspeed-bmc-dev.c      |  716 ++++++
+ drivers/soc/aspeed/aspeed-espi-comm.h    |  196 ++
+ drivers/soc/aspeed/aspeed-host-bmc-dev.c | 1434 ++++++++++++
+ drivers/soc/aspeed/aspeed-lpc-ctrl.c     |    6 +-
+ drivers/soc/aspeed/aspeed-lpc-mbox.c     |  439 ++++
+ drivers/soc/aspeed/aspeed-lpc-pcc.c      |  440 ++++
+ drivers/soc/aspeed/aspeed-lpc-snoop.c    |  262 +--
+ drivers/soc/aspeed/aspeed-mctp.c         | 2579 ++++++++++++++++++++++
+ drivers/soc/aspeed/aspeed-pcie-mmbi.c    |  964 ++++++++
+ drivers/soc/aspeed/aspeed-pcie-mmbi.h    |  141 ++
+ drivers/soc/aspeed/aspeed-socinfo.c      |   16 +-
+ drivers/soc/aspeed/aspeed-uart-routing.c |  430 +++-
+ drivers/soc/aspeed/aspeed-usb-hp.c       |  153 ++
+ drivers/soc/aspeed/aspeed-usb-phy.c      |  113 +
+ drivers/soc/aspeed/aspeed-xdma.c         | 1436 ++++++++++++
+ drivers/soc/aspeed/ast2700-espi.c        | 2262 +++++++++++++++++++
+ drivers/soc/aspeed/ast2700-espi.h        |  281 +++
+ drivers/soc/aspeed/ast2700-otp.c         |  567 +++++
+ include/linux/aspeed-mctp.h              |  164 ++
+ include/linux/soc/aspeed/aspeed-otp.h    |   11 +
+ include/trace/events/xdma.h              |  139 ++
+ include/uapi/linux/aspeed-mctp.h         |  136 ++
+ include/uapi/linux/aspeed-xdma.h         |   42 +
+ include/uapi/linux/otp_ast2700.h         |   47 +
+ 26 files changed, 12902 insertions(+), 151 deletions(-)
+ create mode 100755 drivers/soc/aspeed/aspeed-bmc-dev.c
+ create mode 100755 drivers/soc/aspeed/aspeed-espi-comm.h
+ create mode 100755 drivers/soc/aspeed/aspeed-host-bmc-dev.c
+ mode change 100644 => 100755 drivers/soc/aspeed/aspeed-lpc-ctrl.c
+ create mode 100755 drivers/soc/aspeed/aspeed-lpc-mbox.c
+ create mode 100755 drivers/soc/aspeed/aspeed-lpc-pcc.c
+ create mode 100755 drivers/soc/aspeed/aspeed-mctp.c
+ create mode 100755 drivers/soc/aspeed/aspeed-pcie-mmbi.c
+ create mode 100755 drivers/soc/aspeed/aspeed-pcie-mmbi.h
+ create mode 100755 drivers/soc/aspeed/aspeed-usb-hp.c
+ create mode 100755 drivers/soc/aspeed/aspeed-usb-phy.c
+ create mode 100755 drivers/soc/aspeed/aspeed-xdma.c
+ create mode 100755 drivers/soc/aspeed/ast2700-espi.c
+ create mode 100755 drivers/soc/aspeed/ast2700-espi.h
+ create mode 100755 drivers/soc/aspeed/ast2700-otp.c
+ create mode 100755 include/linux/aspeed-mctp.h
+ create mode 100755 include/linux/soc/aspeed/aspeed-otp.h
+ create mode 100755 include/trace/events/xdma.h
+ create mode 100755 include/uapi/linux/aspeed-mctp.h
+ create mode 100755 include/uapi/linux/aspeed-xdma.h
+ create mode 100755 include/uapi/linux/otp_ast2700.h
 
 diff --git a/drivers/soc/aspeed/Kconfig b/drivers/soc/aspeed/Kconfig
-index 0d949ee63..98149a48a 100644
+index 0d949ee63..f56780331 100644
 --- a/drivers/soc/aspeed/Kconfig
 +++ b/drivers/soc/aspeed/Kconfig
 @@ -4,6 +4,12 @@ if ARCH_ASPEED || COMPILE_TEST
@@ -117,16 +74,10 @@
  config ASPEED_LPC_CTRL
  	tristate "ASPEED LPC firmware cycle control"
  	select REGMAP
-@@ -24,6 +30,20 @@ config ASPEED_LPC_SNOOP
+@@ -24,6 +30,14 @@ config ASPEED_LPC_SNOOP
  	  allows the BMC to listen on and save the data written by
  	  the host to an arbitrary LPC I/O port.
  
-+config ASPEED_SSP
-+	tristate "ASPEED SSP loader"
-+	default n
-+	help
-+	  Driver for loading secondary-service-processor binary
-+
 +config ASPEED_MCTP
 +	tristate "Aspeed ast2600 MCTP Controller support"
 +	depends on REGMAP && MFD_SYSCON
@@ -138,7 +89,7 @@
  config ASPEED_UART_ROUTING
  	tristate "ASPEED uart routing control"
  	select REGMAP
-@@ -34,6 +54,16 @@ config ASPEED_UART_ROUTING
+@@ -34,6 +48,16 @@ config ASPEED_UART_ROUTING
  	  users to perform runtime configuration of the RX muxes among
  	  the UART controllers and I/O pins.
  
@@ -155,7 +106,7 @@
  config ASPEED_P2A_CTRL
  	tristate "ASPEED P2A (VGA MMIO to BMC) bridge control"
  	select REGMAP
-@@ -52,6 +82,55 @@ config ASPEED_SOCINFO
+@@ -52,6 +76,32 @@ config ASPEED_SOCINFO
  	help
  	  Say yes to support decoding of ASPEED BMC information.
  
@@ -169,29 +120,6 @@
 +	  SoCs. The XDMA engine can perform PCIe DMA operations between the BMC
 +	  and a host processor.
 +
-+config ASPEED_SBC
-+	bool "ASPEED Secure Boot Controller driver"
-+	default MACH_ASPEED_G6
-+	help
-+	  Say yes to provide information about the secure boot controller in
-+	  debugfs.
-+
-+config AST2500_ESPI
-+	tristate "ASPEED AST2500 eSPI slave driver"
-+	help
-+	  Enable driver support for Aspeed AST2500 eSPI engine. The eSPI engine
-+	  plays as a slave device in BMC to communicate with the Host over
-+	  the eSPI interface. The four eSPI channels, namely peripheral,
-+	  virtual wire, out-of-band, and flash are supported.
-+
-+config AST2600_ESPI
-+	tristate "ASPEED AST2600 eSPI slave driver"
-+	help
-+	  Enable driver support for Aspeed AST2600 eSPI engine. The eSPI engine
-+	  plays as a slave device in BMC to communicate with the Host over
-+	  the eSPI interface. The four eSPI channels, namely peripheral,
-+	  virtual wire, out-of-band, and flash are supported.
-+
 +config AST2700_ESPI
 +	tristate "ASPEED AST2700 eSPI slave driver"
 +	help
@@ -211,7 +139,7 @@
  config ASPEED_UDMA
  	tristate "Aspeed UDMA Engine Driver"
  	depends on ARCH_ASPEED && REGMAP && MFD_SYSCON && HAS_DMA
-@@ -60,6 +139,41 @@ config ASPEED_UDMA
+@@ -60,6 +110,24 @@ config ASPEED_UDMA
  	  SOCs. The UDMA engine can perform UART DMA operations between the memory
  	  buffer and the UART/VUART devices.
  
@@ -223,13 +151,6 @@
 +	  The OTP driver performs basic read/program operations of
 +	  OTP memory.
 +
-+config AST2600_OTP
-+	tristate "AST2600 OTP Driver"
-+	select ASPEED_OTP
-+	depends on ARCH_ASPEED
-+	help
-+	  Enable driver support for Aspeed AST2600 OTP driver.
-+
 +config AST2700_OTP
 +	tristate "AST2700 OTP Driver"
 +	select ASPEED_OTP
@@ -237,58 +158,41 @@
 +	help
 +	  Enable driver support for Aspeed AST2700 OTP driver.
 +
-+config ASPEED_DISP_INTF
-+	bool "ASPEED Display Interface driver"
-+	select REGMAP
-+	select MFD_SYSCON
-+	default ARCH_ASPEED
-+	help
-+	  Say yes to support control the display interface of ASPEED BMC.
-+
 +config ASPEED_PCIE_MMBI
 +	tristate "ASPEED PCIE MMBI"
 +
-+source "drivers/soc/aspeed/rvas/Kconfig"
-+
  endmenu
  
  endif
 diff --git a/drivers/soc/aspeed/Makefile b/drivers/soc/aspeed/Makefile
-index 5aeabafee..0dcc9ac2a 100644
+index 5aeabafee..e71b40ad0 100644
 --- a/drivers/soc/aspeed/Makefile
 +++ b/drivers/soc/aspeed/Makefile
-@@ -1,7 +1,25 @@
+@@ -1,7 +1,18 @@
  # SPDX-License-Identifier: GPL-2.0-only
 +obj-$(CONFIG_ASPEED_BMC_DEV)		+= aspeed-bmc-dev.o
 +obj-$(CONFIG_ASPEED_HOST_BMC_DEV)	+= aspeed-host-bmc-dev.o
  obj-$(CONFIG_ASPEED_LPC_CTRL)		+= aspeed-lpc-ctrl.o
  obj-$(CONFIG_ASPEED_LPC_SNOOP)		+= aspeed-lpc-snoop.o
  obj-$(CONFIG_ASPEED_UART_ROUTING)	+= aspeed-uart-routing.o
-+obj-$(CONFIG_ASPEED_SSP)		+= aspeed-ssp.o
  obj-$(CONFIG_ASPEED_P2A_CTRL)		+= aspeed-p2a-ctrl.o
  obj-$(CONFIG_ASPEED_SOCINFO)		+= aspeed-socinfo.o
-+obj-$(CONFIG_ASPEED_SBC)		+= aspeed-sbc.o
 +obj-$(CONFIG_ASPEED_XDMA)		+= aspeed-xdma.o
-+obj-$(CONFIG_AST2500_ESPI)		+= ast2500-espi.o
-+obj-$(CONFIG_AST2600_ESPI)		+= ast2600-espi.o
 +obj-$(CONFIG_AST2700_ESPI)		+= ast2700-espi.o
 +obj-$(CONFIG_ASPEED_LPC_MAILBOX)	+= aspeed-lpc-mbox.o
 +obj-$(CONFIG_ASPEED_LPC_PCC)		+= aspeed-lpc-pcc.o
-+obj-$(CONFIG_ASPEED_RVAS)		+= rvas/
  obj-$(CONFIG_ASPEED_UDMA)		+= aspeed-udma.o
 +obj-$(CONFIG_ARCH_ASPEED)		+= aspeed-usb-phy.o
 +obj-$(CONFIG_ARCH_ASPEED)		+= aspeed-usb-hp.o
 +obj-$(CONFIG_ASPEED_MCTP)		+= aspeed-mctp.o
-+obj-$(CONFIG_AST2600_OTP)		+= ast2600-otp.o
 +obj-$(CONFIG_AST2700_OTP)		+= ast2700-otp.o
-+obj-$(CONFIG_ASPEED_DISP_INTF)		+= aspeed-disp-intf.o
 +obj-$(CONFIG_ASPEED_PCIE_MMBI)		+= aspeed-pcie-mmbi.o
 diff --git a/drivers/soc/aspeed/aspeed-bmc-dev.c b/drivers/soc/aspeed/aspeed-bmc-dev.c
-new file mode 100644
-index 000000000..60d99239c
+new file mode 100755
+index 000000000..7036932c4
 --- /dev/null
 +++ b/drivers/soc/aspeed/aspeed-bmc-dev.c
-@@ -0,0 +1,727 @@
+@@ -0,0 +1,716 @@
 +// SPDX-License-Identifier: GPL-2.0-or-later
 +// Copyright (C) ASPEED Technology Inc.
 +
@@ -313,8 +217,6 @@
 +#include <linux/dma-mapping.h>
 +#include <linux/miscdevice.h>
 +
-+static DEFINE_IDA(bmc_device_ida);
-+
 +#define SCU_TRIGGER_MSI
 +
 +/* AST2600 SCU */
@@ -690,8 +592,7 @@
 +{
 +	struct aspeed_bmc_device *bmc_device = platform_get_drvdata(pdev);
 +	struct device *dev = &pdev->dev;
-+	u32 pcie_config_ctl = SCU_PCIE_CONF_BMC_DEV_EN_IRQ |
-+			      SCU_PCIE_CONF_BMC_DEV_EN_MMIO | SCU_PCIE_CONF_BMC_DEV_EN;
++	u32 pcie_config_ctl;
 +	u32 scu_id;
 +	int i;
 +
@@ -719,31 +620,30 @@
 +		return PTR_ERR(bmc_device->scu);
 +	}
 +
-+	if (bmc_device->pcie2lpc)
-+		pcie_config_ctl |= SCU_PCIE_CONF_BMC_DEV_EN_E2L |
-+				   SCU_PCIE_CONF_BMC_DEV_EN_LPC_DECODE;
-+
-+	regmap_update_bits(bmc_device->config, 0x10, pcie_config_ctl, pcie_config_ctl);
++	if (bmc_device->pcie2lpc) {
++		pcie_config_ctl = SCU_PCIE_CONF_BMC_DEV_EN_E2L |
++				  SCU_PCIE_CONF_BMC_DEV_EN_LPC_DECODE;
++		regmap_update_bits(bmc_device->config, 0x10, pcie_config_ctl, pcie_config_ctl);
++	}
 +
 +	/* update class code to others as it is a MFD device */
 +	regmap_write(bmc_device->device, 0x18, 0xff000027);
 +
-+	//MSI
++	/* MSI */
 +	regmap_update_bits(bmc_device->device, 0x74, GENMASK(7, 4), BIT(7) | (5 << 4));
-+
-+	//EnPCIaMSI_EnPCIaIntA_EnPCIaMst_EnPCIaDev
-+	//Disable MSI[bit25] in ast2700A0 int only
++	/* EnPCIaMSI:BIT(25), EnPCIaIntA:BIT(17), EnPCIaMst:BIT(9), EnPCIaDev:BIT(1) */
 +	regmap_read(bmc_device->scu, SCU0_REVISION_ID, &scu_id);
 +	if (scu_id & REVISION_ID)
 +		regmap_update_bits(bmc_device->device, 0x70,
 +				   BIT(25) | BIT(17) | BIT(9) | BIT(1),
 +				   BIT(25) | BIT(17) | BIT(9) | BIT(1));
 +	else
++		/* Disable MSI[bit25] in ast2700A0 int only */
 +		regmap_update_bits(bmc_device->device, 0x70,
 +				   BIT(17) | BIT(9) | BIT(1),
 +				   BIT(25) | BIT(17) | BIT(9) | BIT(1));
 +
-+	//bar size check for 4k align
++	/* bar size check for 4k align */
 +	for (i = 1; i < 16; i++) {
 +		if ((bmc_device->bmc_mem_size / 4096) == (1 << (i - 1)))
 +			break;
@@ -760,21 +660,14 @@
 +	 */
 +	regmap_write(bmc_device->device, 0x1c, ((bmc_device->bmc_mem_phy) >> 4) | i);
 +
-+	/*
-+	 * BAR assign in e2m
-+	 * e2m0:12c21000
-+	 * 108:host2bmc-0 for pcie0
-+	 * 128:host2bmc-1 for pcie0
-+	 * e2m1:12c22000
-+	 * 108:host2bmc-0 for pcie1
-+	 * 128:host2bmc-1 for pcie1
-+	 */
-+	if (bmc_device->id)
-+		regmap_write(bmc_device->e2m, 0x128, ((bmc_device->bmc_mem_phy) >> 4) | i);
-+	else
++	if (bmc_device->id == 0)
++		/* Node 0 Bar 0 */
 +		regmap_write(bmc_device->e2m, 0x108, ((bmc_device->bmc_mem_phy) >> 4) | i);
++	else
++		/* Node 1 Bar 0 */
++		regmap_write(bmc_device->e2m, 0x128, ((bmc_device->bmc_mem_phy) >> 4) | i);
 +
-+	//Setting BMC to Host Q register
++	/* Setting BMC to Host Q register */
 +	writel(BMC2HOST_Q2_FULL_UNMASK | BMC2HOST_Q1_FULL_UNMASK | BMC2HOST_ENABLE_INTB,
 +	       bmc_device->reg_base + ASPEED_BMC_BMC2HOST_STS);
 +	writel(HOST2BMC_Q2_FULL_UNMASK | HOST2BMC_Q1_FULL_UNMASK | HOST2BMC_ENABLE_INTB,
@@ -882,9 +775,9 @@
 +
 +	bmc_device->platform = md;
 +
-+	bmc_device->id = ida_simple_get(&bmc_device_ida, 0, 0, GFP_KERNEL);
++	bmc_device->id = of_alias_get_id(dev->of_node, "bmcdev");
 +	if (bmc_device->id < 0)
-+		goto out_region;
++		bmc_device->id = 0;
 +
 +	bmc_device->dev = dev;
 +	bmc_device->reg_base = devm_platform_ioremap_resource(pdev, 0);
@@ -1016,269 +909,8 @@
 +MODULE_AUTHOR("Ryan Chen <ryan_chen@aspeedtech.com>");
 +MODULE_DESCRIPTION("ASPEED BMC DEVICE Driver");
 +MODULE_LICENSE("GPL");
-diff --git a/drivers/soc/aspeed/aspeed-disp-intf.c b/drivers/soc/aspeed/aspeed-disp-intf.c
-new file mode 100644
-index 000000000..a2fc811a5
---- /dev/null
-+++ b/drivers/soc/aspeed/aspeed-disp-intf.c
-@@ -0,0 +1,255 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+// Copyright (C) ASPEED Technology Inc.
-+#include <linux/bitfield.h>
-+#include <linux/clk.h>
-+#include <linux/log2.h>
-+#include <linux/mfd/syscon.h>
-+#include <linux/miscdevice.h>
-+#include <linux/mm.h>
-+#include <linux/module.h>
-+#include <linux/of_address.h>
-+#include <linux/platform_device.h>
-+#include <linux/poll.h>
-+#include <linux/regmap.h>
-+
-+#define DEVICE_NAME	"aspeed-disp-intf"
-+
-+#define AST2700_SCU_CHIP_ID		0x0
-+#define  SCU_CPU_REVISION_ID_HW		GENMASK(23, 16)
-+
-+#define AST2700_SCU_PIN_SEL		0x414
-+#define  AST2700_SCU_D1PLL_SEL		GENMASK(13, 12)
-+#define  AST2700_SCU_DAC_SRC_SEL	GENMASK(11, 10)
-+#define  AST2700_SCU_DP_SRC_SEL		GENMASK(9, 8)
-+
-+#define AST2600_SCU_PIN_SEL		0x0C0
-+#define  AST2600_SCU_DP_SRC_SEL		BIT(18)
-+#define  AST2600_SCU_DAC_SRC_SEL	BIT(16)
-+
-+struct aspeed_disp_intf_config {
-+	u8 version;
-+	u32 dac_src_sel;
-+	u32 dac_src_max;
-+	u32 dac_src_min;
-+	u32 dp_src_sel;
-+	u32 dp_src_max;
-+	u32 dp_src_min;
-+};
-+
-+struct aspeed_disp_intf {
-+	struct device *dev;
-+	struct miscdevice miscdev;
-+	struct regmap *scu;
-+	const struct aspeed_disp_intf_config *config;
-+};
-+
-+static int dac_src, dp_src;
-+
-+static const struct aspeed_disp_intf_config ast2600_config = {
-+	.version = 6,
-+	.dac_src_sel = AST2600_SCU_PIN_SEL,
-+	.dac_src_max = 1,
-+	.dac_src_min = 0,
-+	.dp_src_sel = AST2600_SCU_PIN_SEL,
-+	.dp_src_max = 1,
-+	.dp_src_min = 0,
-+};
-+
-+static const struct aspeed_disp_intf_config ast2700_config = {
-+	.version = 7,
-+	.dac_src_sel = AST2700_SCU_PIN_SEL,
-+	.dac_src_max = 2,
-+	.dac_src_min = 0,
-+	.dp_src_sel = AST2700_SCU_PIN_SEL,
-+	.dp_src_max = 2,
-+	.dp_src_min = 0,
-+};
-+
-+static ssize_t dac_src_show(struct device *dev,
-+			    struct device_attribute *attr, char *buf)
-+{
-+	struct aspeed_disp_intf *intf = dev_get_drvdata(dev);
-+	const struct aspeed_disp_intf_config *config = intf->config;
-+	u32 val;
-+
-+	regmap_read(intf->scu, config->dac_src_sel, &val);
-+	dac_src = (config->version == 6)
-+		? FIELD_GET(AST2600_SCU_DAC_SRC_SEL, val)
-+		: FIELD_GET(AST2700_SCU_DAC_SRC_SEL, val);
-+	return sysfs_emit(buf, "%d\n", dac_src);
-+}
-+
-+static ssize_t dac_src_store(struct device *dev,
-+			     struct device_attribute *attr, const char *buf, size_t count)
-+{
-+	struct aspeed_disp_intf *intf = dev_get_drvdata(dev);
-+	const struct aspeed_disp_intf_config *config = intf->config;
-+	int src, res;
-+
-+	res = kstrtoint(buf, 0, &src);
-+	if (res)
-+		return res;
-+
-+	if (src < config->dac_src_min || src > config->dac_src_max) {
-+		dev_err(intf->dev, "Invalid dac_src(max:%d, min:%d)\n",
-+			config->dac_src_max, config->dac_src_min);
-+		return -1;
-+	}
-+
-+	dac_src = src;
-+	if (config->version == 6) {
-+		regmap_update_bits(intf->scu, config->dac_src_sel, AST2600_SCU_DAC_SRC_SEL,
-+				   FIELD_PREP(AST2600_SCU_DAC_SRC_SEL, src));
-+	} else {
-+		u32 id;
-+		u32 mask = AST2700_SCU_DAC_SRC_SEL;
-+		u32 val = FIELD_PREP(AST2700_SCU_DAC_SRC_SEL, src);
-+
-+		// D1PLL used in A0 only
-+		regmap_read(intf->scu, AST2700_SCU_CHIP_ID, &id);
-+		if (FIELD_GET(SCU_CPU_REVISION_ID_HW, id) != 0) {
-+			mask |= AST2700_SCU_D1PLL_SEL;
-+			val |= FIELD_PREP(AST2700_SCU_D1PLL_SEL, src);
-+		}
-+
-+		regmap_update_bits(intf->scu, config->dac_src_sel, mask, val);
-+	}
-+	return count;
-+}
-+
-+static DEVICE_ATTR_RW(dac_src);
-+
-+static ssize_t dp_src_show(struct device *dev, struct device_attribute *attr,
-+			   char *buf)
-+{
-+	struct aspeed_disp_intf *intf = dev_get_drvdata(dev);
-+	const struct aspeed_disp_intf_config *config = intf->config;
-+	u32 val;
-+
-+	regmap_read(intf->scu, config->dp_src_sel, &val);
-+	dp_src = (config->version == 6)
-+		? FIELD_GET(AST2600_SCU_DP_SRC_SEL, val)
-+		: FIELD_GET(AST2700_SCU_DP_SRC_SEL, val);
-+	return sysfs_emit(buf, "%d\n", dp_src);
-+}
-+
-+static ssize_t dp_src_store(struct device *dev, struct device_attribute *attr,
-+			    const char *buf, size_t count)
-+{
-+	struct aspeed_disp_intf *intf = dev_get_drvdata(dev);
-+	const struct aspeed_disp_intf_config *config = intf->config;
-+	int src, res;
-+
-+	res = kstrtoint(buf, 0, &src);
-+	if (res)
-+		return res;
-+
-+	if (src < config->dp_src_min || src > config->dp_src_max) {
-+		dev_err(intf->dev, "Invalid dp_src(max:%d, min:%d)\n",
-+			config->dp_src_max, config->dp_src_min);
-+		return -1;
-+	}
-+
-+	dp_src = src;
-+	if (config->version == 6) {
-+		regmap_update_bits(intf->scu, config->dp_src_sel, AST2600_SCU_DP_SRC_SEL,
-+				   FIELD_PREP(AST2600_SCU_DP_SRC_SEL, src));
-+	} else {
-+		u32 val;
-+
-+		regmap_update_bits(intf->scu, config->dp_src_sel, AST2700_SCU_DP_SRC_SEL,
-+				   FIELD_PREP(AST2700_SCU_DP_SRC_SEL, src));
-+
-+		// D1PLL used in A0 only
-+		regmap_read(intf->scu, AST2700_SCU_CHIP_ID, &val);
-+		if (FIELD_GET(SCU_CPU_REVISION_ID_HW, val) == 0) {
-+			regmap_update_bits(intf->scu, config->dp_src_sel, AST2700_SCU_D1PLL_SEL,
-+					   FIELD_PREP(AST2700_SCU_D1PLL_SEL, src));
-+		}
-+	}
-+
-+	return count;
-+}
-+
-+static DEVICE_ATTR_RW(dp_src);
-+
-+static struct attribute *aspeed_disp_intf_attrs[] = {
-+	&dev_attr_dac_src.attr,
-+	&dev_attr_dp_src.attr,
-+	NULL,
-+};
-+
-+static const struct attribute_group aspeed_disp_intf_attgrp = {
-+	.name = NULL,
-+	.attrs = aspeed_disp_intf_attrs,
-+};
-+
-+static int aspeed_disp_intf_probe(struct platform_device *pdev)
-+{
-+	struct aspeed_disp_intf *intf;
-+	struct device *dev = &pdev->dev;
-+	int ret;
-+
-+	intf = devm_kzalloc(&pdev->dev, sizeof(struct aspeed_disp_intf), GFP_KERNEL);
-+	if (!intf)
-+		return -ENOMEM;
-+
-+	dev_set_drvdata(&pdev->dev, intf);
-+
-+	intf->config = of_device_get_match_data(&pdev->dev);
-+	if (!intf->config)
-+		return -ENODEV;
-+
-+	intf->dev = dev;
-+	intf->scu = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon");
-+	if (IS_ERR(intf->scu)) {
-+		dev_err(dev, "failed to find SCU regmap\n");
-+		return PTR_ERR(intf->scu);
-+	}
-+
-+	intf->miscdev.minor = MISC_DYNAMIC_MINOR;
-+	intf->miscdev.name = DEVICE_NAME;
-+	intf->miscdev.parent = dev;
-+	ret = misc_register(&intf->miscdev);
-+	if (ret) {
-+		dev_err(dev, "Unable to register device\n");
-+		return ret;
-+	}
-+
-+	ret = sysfs_create_group(&dev->kobj, &aspeed_disp_intf_attgrp);
-+	if (ret != 0)
-+		dev_warn(dev, "failed to register attributes\n");
-+
-+	return 0;
-+}
-+
-+static void aspeed_disp_intf_remove(struct platform_device *pdev)
-+{
-+	struct aspeed_disp_intf *intf = platform_get_drvdata(pdev);
-+
-+	sysfs_remove_group(&intf->dev->kobj, &aspeed_disp_intf_attgrp);
-+	misc_deregister(&intf->miscdev);
-+	devm_kfree(&pdev->dev, intf);
-+}
-+
-+static const struct of_device_id aspeed_disp_intf_of_matches[] = {
-+	{ .compatible = "aspeed,ast2600-disp-intf", .data = &ast2600_config },
-+	{ .compatible = "aspeed,ast2700-disp-intf", .data = &ast2700_config },
-+	{},
-+};
-+
-+static struct platform_driver aspeed_disp_intf_driver = {
-+	.probe		= aspeed_disp_intf_probe,
-+	.remove_new	= aspeed_disp_intf_remove,
-+	.driver		= {
-+		.name	= DEVICE_NAME,
-+		.of_match_table = aspeed_disp_intf_of_matches,
-+	},
-+};
-+
-+module_platform_driver(aspeed_disp_intf_driver);
-+
-+MODULE_DEVICE_TABLE(of, aspeed_disp_intf_of_matches);
-+MODULE_AUTHOR("Jammy Huang <jammy_huang@aspeedtech.com>");
-+MODULE_DESCRIPTION("ASPEED Display Interface Driver");
-+MODULE_LICENSE("GPL");
 diff --git a/drivers/soc/aspeed/aspeed-espi-comm.h b/drivers/soc/aspeed/aspeed-espi-comm.h
-new file mode 100644
+new file mode 100755
 index 000000000..b50393c80
 --- /dev/null
 +++ b/drivers/soc/aspeed/aspeed-espi-comm.h
@@ -1480,11 +1112,11 @@
 +
 +#endif
 diff --git a/drivers/soc/aspeed/aspeed-host-bmc-dev.c b/drivers/soc/aspeed/aspeed-host-bmc-dev.c
-new file mode 100644
-index 000000000..e2dd49498
+new file mode 100755
+index 000000000..44525ba12
 --- /dev/null
 +++ b/drivers/soc/aspeed/aspeed-host-bmc-dev.c
-@@ -0,0 +1,803 @@
+@@ -0,0 +1,1434 @@
 +// SPDX-License-Identifier: GPL-2.0-or-later
 +// Copyright (C) ASPEED Technology Inc.
 +
@@ -1504,6 +1136,15 @@
 +#include <linux/serial_core.h>
 +#include <linux/serial_8250.h>
 +#include <linux/poll.h>
++#include <linux/bitfield.h>
++
++#include <linux/if_arp.h>
++#include <linux/skbuff.h>
++#include <linux/mctp.h>
++#include <net/mctp.h>
++#include <net/pkt_sched.h>
++
++#include "aspeed-pcie-mmbi.h"
 +
 +#define PCI_BMC_HOST2BMC_Q1		0x30000
 +#define PCI_BMC_HOST2BMC_Q2		0x30010
@@ -1582,15 +1223,15 @@
 +	struct aspeed_pci_bmc_dev *pci_bmc_device;
 +};
 +
-+struct aspeed_pci_mmbi {
-+	unsigned long base;
-+	unsigned long size;
++struct aspeed_pcie_mmbi {
++	resource_size_t base;
++	resource_size_t mem_size;
 +	void __iomem *mem;
-+	struct miscdevice mdev;
-+	bool bmc_rwp_update;
-+	wait_queue_head_t wq;
 +	u32 segment_size;
 +	int irq;
++	int id;
++	struct aspeed_mmbi_channel chan;
++	const char *dev_name;
 +};
 +
 +struct aspeed_pci_bmc_dev {
@@ -1624,7 +1265,7 @@
 +	bool ast2700_soc1;
 +
 +	/* AST2700 MMBI */
-+	struct aspeed_pci_mmbi mmbi[MMBI_MAX_INST];
++	struct aspeed_pcie_mmbi mmbi[MMBI_MAX_INST];
 +	int mmbi_start_msi;
 +};
 +
@@ -1633,43 +1274,463 @@
 +
 +#define DRIVER_NAME "aspeed-host-bmc-dev"
 +
-+static int aspeed_pci_mmbi_mmap(struct file *fp, struct vm_area_struct *vma)
++static int mmbi_desc_init(struct aspeed_mmbi_channel *chan);
++
++static u8 mmbi_get_bmc_rdy(struct aspeed_mmbi_channel *chan)
 +{
-+	struct aspeed_pci_mmbi *mmbi;
-+	unsigned long vm_size;
-+	pgprot_t prot;
++	struct host_ros hros;
 +
-+	mmbi = container_of(fp->private_data, struct aspeed_pci_mmbi, mdev);
++	memcpy_fromio(&hros, chan->hros_vmem, sizeof(hros));
 +
-+	vm_size = vma->vm_end - vma->vm_start;
-+	prot = vma->vm_page_prot;
++	return hros.b_rdy;
++}
 +
-+	if (((vma->vm_pgoff << PAGE_SHIFT) + vm_size) > mmbi->size)
-+		return -EINVAL;
++static u8 mmbi_get_bmc_up(struct aspeed_mmbi_channel *chan)
++{
++	struct host_ros hros;
 +
-+	prot = pgprot_noncached(prot);
++	memcpy_fromio(&hros, chan->hros_vmem, sizeof(hros));
 +
-+	if (remap_pfn_range(vma, vma->vm_start, (mmbi->base >> PAGE_SHIFT) + vma->vm_pgoff, vm_size,
-+			    prot))
-+		return -EAGAIN;
++	return hros.b_up;
++}
++
++static u8 mmbi_get_bmc_rst(struct aspeed_mmbi_channel *chan)
++{
++	struct host_ros hros;
++
++	memcpy_fromio(&hros, chan->hros_vmem, sizeof(hros));
++
++	return hros.b_rst;
++}
++
++static u8 mmbi_get_host_rst(struct aspeed_mmbi_channel *chan)
++{
++	struct host_rws hrws;
++
++	memcpy_fromio(&hrws, chan->hrws_vmem, sizeof(hrws));
++
++	return hrws.h_rst;
++}
++
++static u8 mmbi_get_host_up(struct aspeed_mmbi_channel *chan)
++{
++	struct host_rws hrws;
++
++	memcpy_fromio(&hrws, chan->hrws_vmem, sizeof(hrws));
++
++	return hrws.h_up;
++}
++
++static void mmbi_set_host_rst(struct aspeed_mmbi_channel *chan, bool set)
++{
++	struct host_rws hrws;
++
++	memcpy_fromio(&hrws, chan->hrws_vmem, sizeof(hrws));
++	hrws.h_rst = set;
++	memcpy_toio(chan->hrws_vmem, &hrws, sizeof(hrws));
++}
++
++static void mmbi_set_host_rdy(struct aspeed_mmbi_channel *chan, bool set)
++{
++	struct host_rws hrws;
++
++	memcpy_fromio(&hrws, chan->hrws_vmem, sizeof(hrws));
++	hrws.h_rdy = set;
++	memcpy_toio(chan->hrws_vmem, &hrws, sizeof(hrws));
++}
++
++static void mmbi_set_host_up(struct aspeed_mmbi_channel *chan, bool set)
++{
++	struct host_rws hrws;
++
++	memcpy_fromio(&hrws, chan->hrws_vmem, sizeof(hrws));
++	hrws.h_up = set;
++	memcpy_toio(chan->hrws_vmem, &hrws, sizeof(hrws));
++}
++
++static void get_h2b_avail_buf_len(struct aspeed_mmbi_channel *chan, ssize_t *avail_buf_len)
++{
++	struct device *dev = chan->dev;
++	u32 h2b_rp, h2b_wp;
++
++	h2b_rp = GET_H2B_READ_POINTER(chan);
++	h2b_wp = GET_H2B_WRITE_POINTER(chan);
++	dev_dbg(dev, "MMBI HRWS - h2b_rp: 0x%0x, h2b_wp: 0x%0x\n", h2b_rp, h2b_wp);
++
++	if (h2b_wp >= h2b_rp)
++		*avail_buf_len = chan->h2b_cb_size - h2b_wp + h2b_rp;
++	else
++		*avail_buf_len = h2b_rp - h2b_wp;
++}
++
++static u8 mmbi_get_state(struct aspeed_mmbi_channel *chan)
++{
++	u8 state = 0;
++
++	state = mmbi_get_bmc_up(chan) << 3;
++	state |= mmbi_get_bmc_rst(chan) << 2;
++	state |= mmbi_get_host_up(chan) << 1;
++	state |= mmbi_get_host_rst(chan);
++
++	dev_dbg(chan->dev, "MMBI state: 0x%x\n", state);
++
++	return state;
++}
++
++static void raise_h2b_interrupt(struct aspeed_mmbi_channel *chan)
++{
++	if (!chan->bmc_int_en)
++		return;
++
++	writeb(chan->bmc_int_value, chan->desc_vmem + chan->bmc_int_location);
++}
++
++static int mmbi_state_check(struct aspeed_mmbi_channel *chan)
++{
++	enum mmbi_state current_state = mmbi_get_state(chan);
++	struct device *dev = chan->dev;
++	int ret;
++
++	switch (current_state) {
++	case INIT_COMPLETED:
++		dev_dbg(dev, "Get INIT_COMPLETED state from BMC");
++
++		ret = mmbi_desc_init(chan);
++		if (ret) {
++			dev_warn(dev, "Check MMBI signature timeout\n");
++			raise_h2b_interrupt(chan);
++		}
++		return 1;
++	case RESET_REQ_BY_BMC:
++		dev_dbg(dev, "Get RESET_REQ_BY_BMC state from BMC");
++
++		/* Change state to RESET_ACKED */
++		mmbi_set_host_rst(chan, 1);
++
++		dev_dbg(dev, "Change state to RESET_ACKED to BMC");
++		raise_h2b_interrupt(chan);
++	default:
++		break;
++	}
 +
 +	return 0;
 +}
 +
-+static __poll_t aspeed_pci_mmbi_poll(struct file *fp, struct poll_table_struct *pt)
++static int mmbi_bmc_up_check(struct aspeed_mmbi_channel *chan)
 +{
-+	struct aspeed_pci_mmbi *mmbi;
++	u64 __timeout_us = 1000;
++	ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us);
 +
-+	mmbi = container_of(fp->private_data, struct aspeed_pci_mmbi, mdev);
++	for (;;) {
++		enum mmbi_state current_state = mmbi_get_state(chan);
 +
-+	poll_wait(fp, &mmbi->wq, pt);
++		if (current_state == INIT_COMPLETED)
++			break;
++		if (__timeout_us && ktime_compare(ktime_get(), __timeout) > 0)
++			return -EAGAIN;
++	}
 +
-+	if (!mmbi->bmc_rwp_update)
-+		return 0;
++	return 0;
++}
 +
-+	mmbi->bmc_rwp_update = false;
++static void update_host_rws(struct aspeed_mmbi_channel *chan, unsigned int w_len,
++			    unsigned int r_len)
++{
++	struct device *dev = chan->dev;
++	struct host_rws hrws;
++	u32 h2b_wp, b2h_rp;
 +
-+	return EPOLLIN;
++	h2b_wp = GET_H2B_WRITE_POINTER(chan);
++	b2h_rp = GET_B2H_READ_POINTER(chan);
++
++	dev_dbg(dev, "MMBI HRWS - b2h_rp: 0x%0x, h2b_wp: 0x%0x\n", b2h_rp, h2b_wp);
++
++	/* Advance the H2B CB offset for next write */
++	if ((h2b_wp + w_len) <= chan->h2b_cb_size)
++		h2b_wp += w_len;
++	else
++		h2b_wp = h2b_wp + w_len - chan->h2b_cb_size;
++
++	/* Advance the B2H CB offset till where BMC read data */
++	if ((b2h_rp + r_len) <= chan->b2h_cb_size)
++		b2h_rp += r_len;
++	else
++		b2h_rp = b2h_rp + r_len - chan->b2h_cb_size;
++
++	memcpy_fromio(&hrws, chan->hrws_vmem, sizeof(hrws));
++
++	hrws.h2b_wp = FIELD_GET(H2B_WRITE_POINTER_MASK, h2b_wp);
++	hrws.b2h_rp = FIELD_GET(B2H_READ_POINTER_MASK, b2h_rp);
++	memcpy_toio(chan->hrws_vmem, &hrws, sizeof(hrws));
++	dev_dbg(dev, "Updating HRWS - b2h_rp: 0x%0x, h2b_wp: 0x%0x\n", b2h_rp, h2b_wp);
++
++	if (w_len != 0)
++		raise_h2b_interrupt(chan);
++}
++
++static int get_mmbi_header(struct aspeed_mmbi_channel *chan, u32 *data_length, u8 *type,
++			   u32 *unread_data_len, u8 *padding)
++{
++	u32 h2b_wp, h2b_rp, b2h_wp, b2h_rp;
++	struct mmbi_header header;
++
++	h2b_wp = GET_H2B_WRITE_POINTER(chan);
++	h2b_rp = GET_H2B_READ_POINTER(chan);
++	b2h_wp = GET_B2H_WRITE_POINTER(chan);
++	b2h_rp = GET_B2H_READ_POINTER(chan);
++	dev_dbg(chan->dev, "MMBI HRWS - h2b_wp: 0x%0x, b2h_rp: 0x%0x\n", h2b_wp, b2h_rp);
++	dev_dbg(chan->dev, "MMBI HROS - b2h_wp: 0x%0x, h2b_rp: 0x%0x\n", b2h_wp, h2b_rp);
++
++	if (b2h_wp >= b2h_rp)
++		*unread_data_len = b2h_wp - b2h_rp;
++	else
++		*unread_data_len = chan->b2h_cb_size - b2h_rp + b2h_wp;
++
++	if (*unread_data_len < sizeof(struct mmbi_header)) {
++		dev_dbg(chan->dev, "No data to read(%d - %d)\n", b2h_wp, b2h_rp);
++		return -EAGAIN;
++	}
++
++	dev_dbg(chan->dev, "READ MMBI header from: %p\n", chan->b2h_cb_vmem + b2h_rp);
++
++	/* Extract MMBI protocol - protocol type and length */
++	if ((b2h_rp + sizeof(header)) <= chan->b2h_cb_size) {
++		memcpy_fromio(&header, chan->b2h_cb_vmem + b2h_rp, sizeof(header));
++	} else {
++		ssize_t chunk_len = chan->b2h_cb_size - b2h_rp;
++
++		memcpy_fromio(&header, chan->b2h_cb_vmem + b2h_rp, chunk_len);
++		memcpy_fromio(((u8 *)&header) + chunk_len, chan->b2h_cb_vmem,
++			      sizeof(header) - chunk_len);
++	}
++
++	*data_length = (header.pkt_len << 2) - sizeof(header) - header.pkt_pad;
++	*padding = header.pkt_pad;
++	*type = header.pkt_type;
++
++	return 0;
++}
++
++static int aspeed_mmbi_write(struct aspeed_mmbi_channel *chan, const char *buffer, size_t len,
++			     protocol_type type)
++{
++	struct device *dev = chan->dev;
++	struct mmbi_header header = {0};
++	ssize_t avail_buf_len;
++	ssize_t total_len;
++	ssize_t wt_offset;
++	ssize_t chunk_len;
++	ssize_t end_offset;
++	u8 padding = 0;
++
++	/* If BMC READY bit is not set, Just discard the write. */
++	if (!GET_BMC_READY_BIT(chan)) {
++		dev_dbg(dev, "Host not ready, discarding request...\n");
++		return -EAGAIN;
++	}
++
++	get_h2b_avail_buf_len(chan, &avail_buf_len);
++
++	dev_dbg(dev, "H2B buffer empty space: %zd\n", avail_buf_len);
++
++	/* Header size */
++	total_len = len + 4;
++
++	padding = total_len & 0x3;
++	if (padding)
++		padding = 4 - padding;
++	total_len += padding;
++
++	/* Empty space should be more than write request data size */
++	if (avail_buf_len <= sizeof(header) || (total_len > (avail_buf_len - sizeof(header))))
++		return -ENOSPC;
++
++	/* Fill multi-protocol header */
++	header.pkt_type = type;
++	header.pkt_len = total_len >> 2;
++	header.pkt_pad = padding;
++
++	wt_offset = GET_H2B_WRITE_POINTER(chan);
++	end_offset = chan->h2b_cb_size;
++
++	/* Copy Header */
++	if ((end_offset - wt_offset) >= sizeof(header)) {
++		memcpy_toio(chan->h2b_cb_vmem + wt_offset, &header, sizeof(header));
++		wt_offset += sizeof(header);
++	} else {
++		chunk_len = end_offset - wt_offset;
++		dev_dbg(dev, "Write header chunk_len: %zd\n", chunk_len);
++		memcpy_toio(chan->h2b_cb_vmem + wt_offset, &header, chunk_len);
++		memcpy_toio(chan->h2b_cb_vmem, (u8 *)&header + chunk_len,
++			    (sizeof(header) - chunk_len));
++		wt_offset = (sizeof(header) - chunk_len);
++	}
++
++	/* Write the data */
++	if ((end_offset - wt_offset) >= len) {
++		memcpy_toio(&chan->h2b_cb_vmem[wt_offset], buffer, len);
++		wt_offset += len;
++	} else {
++		chunk_len = end_offset - wt_offset;
++		dev_dbg(dev, "Write data chunk_len: %zd\n", chunk_len);
++		memcpy_toio(&chan->h2b_cb_vmem[wt_offset], buffer, chunk_len);
++		wt_offset = 0;
++		memcpy_toio(&chan->h2b_cb_vmem[wt_offset], buffer + chunk_len, len - chunk_len);
++		wt_offset += len - chunk_len;
++	}
++
++	update_host_rws(chan, total_len, 0);
++
++	return 0;
++}
++
++static void aspeed_mmbi_read(struct aspeed_mmbi_channel *chan, char *buffer, size_t len, u8 padding)
++{
++	struct device *dev = chan->dev;
++	ssize_t rd_offset;
++	u32 b2h_rp;
++
++	b2h_rp = GET_B2H_READ_POINTER(chan);
++	if ((b2h_rp + sizeof(struct mmbi_header)) <= chan->b2h_cb_size)
++		rd_offset = b2h_rp + sizeof(struct mmbi_header);
++	else
++		rd_offset = b2h_rp + sizeof(struct mmbi_header) - chan->b2h_cb_size;
++
++	/* Extract data and copy to user space application */
++	dev_dbg(dev, "READ MMBI Data from: %p and length: %zd\n",
++		chan->b2h_cb_vmem + rd_offset, len);
++
++	if ((chan->b2h_cb_size - rd_offset) >= len) {
++		memcpy_fromio(buffer, chan->b2h_cb_vmem + rd_offset, len);
++		rd_offset += len;
++	} else {
++		ssize_t chunk_len;
++
++		chunk_len = chan->b2h_cb_size - rd_offset;
++		dev_dbg(dev, "Read data chunk_len: %zd\n", chunk_len);
++		memcpy_fromio(buffer, chan->b2h_cb_vmem + rd_offset, chunk_len);
++
++		rd_offset = 0;
++		memcpy_fromio(buffer + chunk_len, chan->b2h_cb_vmem + rd_offset,
++			      len - chunk_len);
++	}
++
++	update_host_rws(chan, 0, len + sizeof(struct mmbi_header) + padding);
++}
++
++static void mctp_mmbi_rx(struct aspeed_mmbi_channel *chan)
++{
++	struct net_device *ndev;
++	struct sk_buff *skb;
++	struct mctp_skb_cb *cb;
++	u32 req_data_len, unread_data_len;
++	u8 type, padding;
++	int status;
++
++	if (get_mmbi_header(chan, &req_data_len, &type, &unread_data_len, &padding) != 0)
++		return;
++
++	dev_dbg(chan->dev, "%s: Length: 0x%0x, Protocol Type: %d, Unread data: %d\n", __func__,
++		req_data_len, type, unread_data_len);
++
++	ndev = chan->ndev;
++
++	skb = netdev_alloc_skb(ndev, req_data_len);
++	if (!skb) {
++		ndev->stats.rx_dropped++;
++		update_host_rws(chan, 0, req_data_len + sizeof(struct mmbi_header));
++		return;
++	}
++
++	skb->protocol = htons(ETH_P_MCTP);
++	aspeed_mmbi_read(chan, skb_put(skb, req_data_len), req_data_len, padding);
++	skb_reset_network_header(skb);
++
++	cb = __mctp_cb(skb);
++	cb->halen = 0;
++
++	status = netif_rx(skb);
++	if (status == NET_RX_SUCCESS) {
++		ndev->stats.rx_packets++;
++		ndev->stats.rx_bytes += req_data_len;
++	} else {
++		ndev->stats.rx_dropped++;
++	}
++}
++
++static netdev_tx_t mctp_mmbi_tx(struct sk_buff *skb, struct net_device *ndev)
++{
++	struct aspeed_mmbi_mctp *mctp = netdev_priv(ndev);
++	int ret;
++
++	if (!mmbi_get_bmc_rdy(&mctp->mmbi->chan) || skb->len > MCTP_MMBI_MTU_MAX) {
++		ndev->stats.tx_dropped++;
++		goto out;
++	}
++
++	ret = aspeed_mmbi_write(&mctp->mmbi->chan, skb->data, skb->len, MMBI_PROTOCOL_MCTP);
++	if (ret) {
++		netif_stop_queue(ndev);
++		return NETDEV_TX_BUSY;
++	}
++
++	ndev->stats.tx_packets++;
++	ndev->stats.tx_bytes += skb->len;
++out:
++	kfree_skb(skb);
++	return NETDEV_TX_OK;
++}
++
++static const struct net_device_ops mctp_mmbi_netdev_ops = {
++	.ndo_start_xmit = mctp_mmbi_tx,
++};
++
++static void aspeed_mctp_mmbi_setup(struct net_device *ndev)
++{
++	ndev->type = ARPHRD_MCTP;
++
++	/* we limit at the fixed MTU, which is also the MCTP-standard
++	 * baseline MTU, so is also our minimum
++	 */
++	ndev->mtu = MCTP_MMBI_MTU;
++	ndev->max_mtu = MCTP_MMBI_MTU_MAX;
++	ndev->min_mtu = MCTP_MMBI_MTU_MIN;
++
++	ndev->hard_header_len = 0;
++	ndev->addr_len = 0;
++	ndev->tx_queue_len = DEFAULT_TX_QUEUE_LEN;
++	ndev->flags = IFF_NOARP;
++	ndev->netdev_ops = &mctp_mmbi_netdev_ops;
++	ndev->needs_free_netdev = true;
++}
++
++static int aspeed_mmbi_mctp_init(struct aspeed_mmbi_channel *chan)
++{
++	struct aspeed_mmbi_mctp *mctp;
++	struct net_device *ndev;
++	char name[32];
++	int ret;
++
++	snprintf(name, sizeof(name), "mctpmmbi%d", chan->mmbi->id);
++	ndev = alloc_netdev(sizeof(*mctp), name, NET_NAME_ENUM, aspeed_mctp_mmbi_setup);
++	if (!ndev)
++		return -ENOMEM;
++	mctp = netdev_priv(ndev);
++	mctp->ndev = ndev;
++	mctp->mmbi = chan->mmbi;
++
++	chan->ndev = ndev;
++
++	ret = register_netdev(ndev);
++	if (ret)
++		goto free_netdev;
++
++	return 0;
++
++free_netdev:
++	free_netdev(ndev);
++
++	return ret;
 +}
 +
 +static struct aspeed_pci_bmc_dev *file_aspeed_bmc_device(struct file *file)
@@ -1701,12 +1762,6 @@
 +	.mmap		= aspeed_pci_bmc_dev_mmap,
 +};
 +
-+static const struct file_operations aspeed_pci_mmbi_fops = {
-+	.owner = THIS_MODULE,
-+	.mmap = aspeed_pci_mmbi_mmap,
-+	.poll = aspeed_pci_mmbi_poll,
-+};
-+
 +static ssize_t aspeed_queue_rx(struct file *filp, struct kobject *kobj, struct bin_attribute *attr,
 +			       char *buf, loff_t off, size_t count)
 +{
@@ -1804,12 +1859,51 @@
 +	return IRQ_HANDLED;
 +}
 +
++static void aspeed_mmbi_work_func(struct work_struct *workq)
++{
++	struct aspeed_mmbi_channel *chan = container_of(workq, struct aspeed_mmbi_channel, work);
++	u32 weight = 256, req_data_len, unread_data_len;
++	u8 type, padding;
++	int i;
++
++	for (i = 0; i < weight; i++) {
++		if (get_mmbi_header(chan, &req_data_len, &type, &unread_data_len, &padding) != 0)
++			return;
++
++		dev_dbg(chan->dev, "%s: Length: 0x%0x, Protocol Type: %d\n",
++			__func__, req_data_len, type);
++
++		if (type == MMBI_PROTOCOL_MCTP)
++			mctp_mmbi_rx(chan);
++		else
++			/* Discard data and advance the hrws */
++			update_host_rws(chan, 0, req_data_len + sizeof(struct mmbi_header) + padding);
++
++		raise_h2b_interrupt(chan);
++	}
++
++	if (get_mmbi_header(chan, &req_data_len, &type, &unread_data_len, &padding) != 0)
++		queue_work(system_unbound_wq, &chan->work);
++}
++
 +static irqreturn_t aspeed_pci_mmbi_isr(int irq, void *dev_id)
 +{
-+	struct aspeed_pci_mmbi *mmbi = dev_id;
++	struct aspeed_pcie_mmbi *mmbi = dev_id;
++	struct aspeed_mmbi_channel *chan = &mmbi->chan;
++	ssize_t avail_buf_len;
 +
-+	mmbi->bmc_rwp_update = true;
-+	wake_up_interruptible(&mmbi->wq);
++	get_h2b_avail_buf_len(chan, &avail_buf_len);
++	if (avail_buf_len > MCTP_MMBI_MTU_MAX) {
++		if (netif_queue_stopped(chan->ndev)) {
++			dev_dbg(chan->dev, "Wake up mctp net device\n");
++			netif_wake_queue(chan->ndev);
++		}
++	}
++
++	if (mmbi_state_check(chan))
++		return IRQ_HANDLED;
++
++	queue_work(system_unbound_wq, &chan->work);
 +
 +	return IRQ_HANDLED;
 +}
@@ -1971,6 +2065,163 @@
 +	return 0;
 +}
 +
++static int mmbi_signature_check(struct aspeed_mmbi_channel *chan)
++{
++	u8 signature[6];
++	u64 __timeout_us = 1000;
++	ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us);
++
++	for (;;) {
++		memcpy_fromio(signature, chan->desc_vmem, 6);
++		if (!memcmp(MMBI_SIGNATURE, signature, 6))
++			break;
++		if (__timeout_us && ktime_compare(ktime_get(), __timeout) > 0)
++			return -ETIMEDOUT;
++	}
++	return 0;
++}
++
++static int mmbi_desc_init(struct aspeed_mmbi_channel *chan)
++{
++	struct aspeed_pcie_mmbi *mmbi = chan->mmbi;
++	struct device *dev = chan->dev;
++	struct mmbi_cap_desc desc;
++	u8 __iomem *desc_base = chan->desc_vmem;
++	int ret;
++
++	/* First, check mmbi signature "#MMBI$" */
++	ret = mmbi_signature_check(chan);
++	if (ret) {
++		dev_warn(dev, "Check MMBI signature timeout\n");
++		return ret;
++	}
++
++	memcpy_fromio(&desc, chan->desc_vmem, sizeof(desc));
++
++	/* HROS */
++	if (((desc.bt_desc.h_ros_p << 3) + sizeof(struct host_ros)) >= mmbi->mem_size) {
++		dev_warn(dev, "HROS is out of range");
++		return -EINVAL;
++	}
++	chan->hros_vmem = desc_base + (desc.bt_desc.h_ros_p << 3);
++
++	/* HRWS */
++	if (((desc.bt_desc.h_rws_p << 3) + sizeof(struct host_rws)) >= mmbi->mem_size) {
++		dev_warn(dev, "HRWS is out of range");
++		return -EINVAL;
++	}
++	chan->hrws_vmem = desc_base + (desc.bt_desc.h_rws_p << 3);
++
++	ret = mmbi_bmc_up_check(chan);
++	if (ret) {
++		dev_warn(dev, "Check BMC up timeout\n");
++		return ret;
++	}
++
++	/* Implementations of MMBI described in this document shall indicate version 1 of MMBI */
++	if (desc.version != 1) {
++		dev_warn(dev, "MMBI version must be 1");
++		goto err_mismatch;
++	}
++
++	/* This MMBI interface is intended for OS use */
++	if (desc.os_use != 1) {
++		dev_warn(dev, "This MMBI does not provide for OS");
++		goto err_mismatch;
++	}
++
++	/* Current application is only MMBI Variable Packet Size Circular Buffers (VPSCB) v1 */
++	if (desc.buffer_type != 1) {
++		dev_warn(dev, "The buffer type is not VPSCB: (%d)", desc.buffer_type);
++		goto err_mismatch;
++	}
++
++	/* B2H Buffer */
++	if (((desc.b2h_ba << 3) + desc.b2h_l) > mmbi->mem_size) {
++		dev_warn(dev, "B2H buffer is out of range");
++		goto err_mismatch;
++	}
++	chan->b2h_cb_vmem = desc_base + (desc.b2h_ba << 3);
++	chan->b2h_cb_size = desc.b2h_l;
++
++	/* H2B Buffer */
++	if (((desc.h2b_ba << 3) + desc.h2b_l) > mmbi->mem_size) {
++		dev_warn(dev, "H2B buffer is out of range");
++		goto err_mismatch;
++	}
++	chan->h2b_cb_vmem = desc_base + (desc.h2b_ba << 3);
++	chan->h2b_cb_size = desc.h2b_l;
++
++	dev_dbg(dev, "B2H mapped addr - desc: %p, hros: %p, b2h_cb: %p\n",
++		chan->desc_vmem, chan->hros_vmem, chan->b2h_cb_vmem);
++	dev_dbg(dev, "H2B mapped addr - hrws: %p, h2b_cb: %p\n", chan->hrws_vmem,
++		chan->h2b_cb_vmem);
++
++	dev_dbg(dev, "B2H buffer size: 0x%0x\n", chan->b2h_cb_size);
++	dev_dbg(dev, "H2B buffer size: 0x%0x\n", chan->h2b_cb_size);
++
++	/* Host Interrupt */
++	chan->host_int_en = !!desc.bt_desc.h_int_t;
++	if (chan->host_int_en) {
++		/* 1 for PCIe */
++		if (desc.bt_desc.h_int_t != 1)
++			chan->host_int_en = 0;
++		else
++			chan->host_int_location = desc.bt_desc.h_int_l;
++	}
++
++	/* BMC Interrupt */
++	chan->bmc_int_en = !!desc.bt_desc.bmc_int_t;
++	if (chan->bmc_int_en) {
++		if (desc.bt_desc.bmc_int_t != 1) {
++			chan->bmc_int_en = 0;
++		} else {
++			chan->bmc_int_location = desc.bt_desc.bmc_int_l;
++			chan->bmc_int_vmem = desc_base + chan->bmc_int_location;
++			chan->bmc_int_value = desc.bt_desc.bmc_int_v;
++		}
++	}
++
++	INIT_WORK(&chan->work, aspeed_mmbi_work_func);
++
++	return 0;
++err_mismatch:
++	/* Change state to INIT_MISMATCH */
++	mmbi_set_host_rst(chan, 1);
++	return -EINVAL;
++}
++
++static int aspeed_pci_mmbi_init(struct aspeed_pcie_mmbi *mmbi)
++{
++	struct aspeed_mmbi_channel *chan = &mmbi->chan;
++	struct device *dev = chan->dev;
++	int ret;
++
++	chan->desc_vmem = mmbi->mem;
++	chan->mmbi = mmbi;
++
++	ret = mmbi_desc_init(chan);
++	if (ret) {
++		dev_err(dev, "Unable to init mmbi desc\n");
++		return ret;
++	}
++
++	/* Initialize MTCP function */
++	ret = aspeed_mmbi_mctp_init(chan);
++	if (ret) {
++		dev_err(dev, "Unable to init mctp\n");
++		return ret;
++	}
++
++	/* Change state to NORMAL_RUNTIME */
++	mmbi_set_host_up(chan, 1);
++	mmbi_set_host_rdy(chan, 1);
++	/* Trigger BMC to finish normal runtime state */
++	raise_h2b_interrupt(chan);
++
++	return 0;
++}
++
 +/* AST2700 PCIe MMBI
 + * SoC : |  0          |  1                |
 + * BAR : |  2  3  4  5 |  0  1  2  3  4  5 |
@@ -1979,10 +2230,11 @@
 +static void aspeed_pci_bmc_device_setup_mmbi(struct pci_dev *pdev)
 +{
 +	struct aspeed_pci_bmc_dev *pci_bmc_dev = pci_get_drvdata(pdev);
-+	struct aspeed_pci_mmbi *mmbi;
++	struct aspeed_pcie_mmbi *mmbi;
 +	u32 start_bar = 2, mmbi_max_inst = 4, start_msi = MMBI0_MSI;	/* AST2700 SoC0 */
 +	int i, rc = 0;
 +
++	/* AST2700 A1 supports MMBI */
 +	if (pdev->revision != 0x27)
 +		return;
 +
@@ -1998,45 +2250,43 @@
 +
 +		/* Get MMBI BAR resource */
 +		mmbi->base = pci_resource_start(pdev, start_bar + i);
-+		mmbi->size = pci_resource_len(pdev, start_bar + i);
++		mmbi->mem_size = pci_resource_len(pdev, start_bar + i);
 +
-+		if (mmbi->size == 0)
++		/* Check if there is bar */
++		if (!mmbi->mem_size)
 +			continue;
 +
 +		mmbi->mem = pci_ioremap_bar(pdev, start_bar + i);
 +		if (!mmbi->mem) {
-+			mmbi->size = 0;
++			mmbi->mem_size = 0;
 +			continue;
 +		}
 +
-+		mmbi->mdev.parent = &pdev->dev;
-+		mmbi->mdev.minor = MISC_DYNAMIC_MINOR;
-+		mmbi->mdev.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
-+						 "aspeed-pcie%d-mmbi%d",
-+						 pci_bmc_dev->id, i);
-+		mmbi->mdev.fops = &aspeed_pci_mmbi_fops;
-+		rc = misc_register(&mmbi->mdev);
-+		if (rc) {
-+			dev_err(&pdev->dev, "Cannot register device %s (err=%d)\n",
-+				mmbi->mdev.name, rc);
-+			mmbi->size = 0;
-+			iounmap(mmbi->mem);
-+			continue;
++		mmbi->chan.dev = &pdev->dev;
++		mmbi->dev_name = devm_kasprintf(mmbi->chan.dev, GFP_KERNEL, "pci-mmbi%d", i);
++		mmbi->id = i;
++		rc = aspeed_pci_mmbi_init(mmbi);
++		if (rc < 0) {
++			pr_err("Initialize MMBI device failed.\n");
++			goto free_ioremap;
 +		}
 +
-+		mmbi->irq = pci_irq_vector(pdev, pci_bmc_dev->msi_idx_table[start_msi + i]);
-+		rc = devm_request_irq(&pdev->dev, mmbi->irq, aspeed_pci_mmbi_isr, IRQF_SHARED,
-+				      mmbi->mdev.name, mmbi);
-+		if (rc) {
-+			pr_err("MMBI device %s unable to get IRQ %d\n", mmbi->mdev.name, rc);
-+			misc_deregister(&mmbi->mdev);
-+			mmbi->size = 0;
-+			iounmap(mmbi->mem);
-+			continue;
++		if (mmbi->chan.host_int_en) {
++			mmbi->irq = pci_irq_vector(pdev, pci_bmc_dev->msi_idx_table[start_msi + i]);
++			rc = devm_request_irq(&pdev->dev, mmbi->irq, aspeed_pci_mmbi_isr,
++					      IRQF_SHARED, mmbi->dev_name, mmbi);
++			if (rc) {
++				pr_err("MMBI device %s unable to get IRQ %d\n", mmbi->dev_name, rc);
++				mmbi->irq = 0;
++				goto free_ioremap;
++			}
++		} else {
++			mmbi->irq = 0;
 +		}
-+
-+		mmbi->bmc_rwp_update = false;
-+		init_waitqueue_head(&mmbi->wq);
++		continue;
++free_ioremap:
++		mmbi->mem_size = 0;
++		pci_iounmap(pdev, mmbi->mem);
 +	}
 +}
 +
@@ -2071,7 +2321,7 @@
 +static void aspeed_pci_release_mmbi(struct pci_dev *pdev)
 +{
 +	struct aspeed_pci_bmc_dev *pci_bmc_dev = pci_get_drvdata(pdev);
-+	struct aspeed_pci_mmbi *mmbi;
++	struct aspeed_pcie_mmbi *mmbi;
 +	int i;
 +
 +	if (pdev->revision != 0x27)
@@ -2080,10 +2330,20 @@
 +	for (i = 0; i < MMBI_MAX_INST; i++) {
 +		mmbi = &pci_bmc_dev->mmbi[i];
 +
-+		if (mmbi->size == 0)
++		if (mmbi->mem_size == 0)
 +			continue;
-+		misc_deregister(&mmbi->mdev);
-+		devm_free_irq(&pdev->dev, mmbi->irq, mmbi);
++
++		cancel_work_sync(&mmbi->chan.work);
++
++		mmbi_set_host_rdy(&mmbi->chan, 0);
++		mmbi_set_host_up(&mmbi->chan, 0);
++
++		unregister_netdev(mmbi->chan.ndev);
++
++		if (mmbi->mem)
++			pci_iounmap(pdev, mmbi->mem);
++		if (mmbi->irq != 0)
++			devm_free_irq(&pdev->dev, mmbi->irq, mmbi);
 +	}
 +}
 +
@@ -2144,7 +2404,7 @@
 +		goto out_free_uart;
 +	}
 +
-+	/* Setup AST2700 SoC0 MMBI device */
++	/* Setup AST2700 PCIe MMBI device */
 +	aspeed_pci_bmc_device_setup_mmbi(pdev);
 +
 +	return 0;
@@ -2159,9 +2419,9 @@
 +out_free_queue:
 +	aspeed_pci_host_bmc_device_release_queue(pdev);
 +out_free1:
-+	iounmap(pci_bmc_dev->msg_bar_reg);
++	pci_iounmap(pdev, pci_bmc_dev->msg_bar_reg);
 +out_free0:
-+	iounmap(pci_bmc_dev->mem_bar_reg);
++	pci_iounmap(pdev, pci_bmc_dev->mem_bar_reg);
 +
 +	pci_release_regions(pdev);
 +	return rc;
@@ -2241,6 +2501,9 @@
 +
 +	ida_simple_remove(&bmc_device_ida, pci_bmc_dev->id);
 +
++	pci_iounmap(pdev, pci_bmc_dev->msg_bar_reg);
++	pci_iounmap(pdev, pci_bmc_dev->mem_bar_reg);
++
 +	pci_free_irq_vectors(pdev);
 +	pci_release_regions(pdev);
 +	pci_disable_device(pdev);
@@ -2289,7 +2552,9 @@
 +MODULE_DESCRIPTION("ASPEED Host BMC DEVICE Driver");
 +MODULE_LICENSE("GPL");
 diff --git a/drivers/soc/aspeed/aspeed-lpc-ctrl.c b/drivers/soc/aspeed/aspeed-lpc-ctrl.c
-index 258894ed2..e87038009 100644
+old mode 100644
+new mode 100755
+index 258894ed2..e87038009
 --- a/drivers/soc/aspeed/aspeed-lpc-ctrl.c
 +++ b/drivers/soc/aspeed/aspeed-lpc-ctrl.c
 @@ -332,14 +332,12 @@ static int aspeed_lpc_ctrl_probe(struct platform_device *pdev)
@@ -2318,7 +2583,7 @@
  
  module_platform_driver(aspeed_lpc_ctrl_driver);
 diff --git a/drivers/soc/aspeed/aspeed-lpc-mbox.c b/drivers/soc/aspeed/aspeed-lpc-mbox.c
-new file mode 100644
+new file mode 100755
 index 000000000..4b6a1693e
 --- /dev/null
 +++ b/drivers/soc/aspeed/aspeed-lpc-mbox.c
@@ -2763,11 +3028,11 @@
 +MODULE_AUTHOR("Chia-Wei Wang <chiawei_wang@aspeedtech.com");
 +MODULE_DESCRIPTION("Aspeed mailbox device driver");
 diff --git a/drivers/soc/aspeed/aspeed-lpc-pcc.c b/drivers/soc/aspeed/aspeed-lpc-pcc.c
-new file mode 100644
-index 000000000..eecf596da
+new file mode 100755
+index 000000000..4cba37a17
 --- /dev/null
 +++ b/drivers/soc/aspeed/aspeed-lpc-pcc.c
-@@ -0,0 +1,442 @@
+@@ -0,0 +1,440 @@
 +// SPDX-License-Identifier: GPL-2.0
 +/*
 + * Copyright (C) ASPEED Technology Inc.
@@ -3087,15 +3352,13 @@
 +		return -ENOMEM;
 +
 +	pcc->regmap = syscon_node_to_regmap(dev->parent->of_node);
-+	if (IS_ERR(pcc->regmap)) {
-+		dev_err(dev, "Couldn't get regmap\n");
-+		return -ENODEV;
-+	}
++	if (IS_ERR(pcc->regmap))
++		return dev_err_probe(dev, PTR_ERR(pcc->regmap), "Couldn't get regmap\n");
 +
 +	rc = of_property_read_u32(dev->of_node, "pcc-ports", &pcc->port);
 +	if (rc) {
 +		dev_err(dev, "no pcc ports configured\n");
-+		return -ENODEV;
++		return rc;
 +	}
 +
 +	rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
@@ -3116,9 +3379,8 @@
 +
 +	fifo_size = roundup(pcc->dma.size, PAGE_SIZE);
 +	rc = kfifo_alloc(&pcc->fifo, fifo_size, GFP_KERNEL);
-+	if (rc) {
-+		return -ENOMEM;
-+	}
++	if (rc)
++		return rc;
 +
 +	/* Disable PCC to clean up DMA buffer before request IRQ. */
 +	rc = aspeed_pcc_disable(pcc);
@@ -3194,6 +3456,7 @@
 +
 +static const struct of_device_id aspeed_pcc_table[] = {
 +	{ .compatible = "aspeed,ast2600-lpc-pcc" },
++	{ },
 +};
 +
 +static struct platform_driver aspeed_pcc_driver = {
@@ -3211,7 +3474,7 @@
 +MODULE_LICENSE("GPL");
 +MODULE_DESCRIPTION("Driver for Aspeed Post Code Capture");
 diff --git a/drivers/soc/aspeed/aspeed-lpc-snoop.c b/drivers/soc/aspeed/aspeed-lpc-snoop.c
-index 773dbcbc0..48b6cbda2 100644
+index 773dbcbc0..2a100ab87 100644
 --- a/drivers/soc/aspeed/aspeed-lpc-snoop.c
 +++ b/drivers/soc/aspeed/aspeed-lpc-snoop.c
 @@ -1,17 +1,10 @@
@@ -3435,10 +3698,11 @@
 -	lpc_snoop->chan[channel].miscdev.parent = dev;
 -	rc = misc_register(&lpc_snoop->chan[channel].miscdev);
 -	if (rc)
+-		return rc;
 +	chan->id = ida_alloc(&aspeed_lpc_snoop_ida, GFP_KERNEL);
 +	if (chan->id < 0) {
 +		dev_err(dev, "cannot allocate ID\n");
-+		return chan->id;
++		goto err_free_fifo;
 +	}
 +
 +	chan->mdev.parent = dev;
@@ -3449,7 +3713,7 @@
 +	rc = misc_register(&chan->mdev);
 +	if (rc) {
 +		dev_err(dev, "cannot register misc device\n");
- 		return rc;
++		goto err_free_fifo;
 +	}
  
  	/* Enable LPC snoop channel at requested port */
@@ -3458,8 +3722,13 @@
  	case 0:
  		hicr5_en = HICR5_EN_SNP0W | HICR5_ENINT_SNP0W;
  		snpwadr_mask = SNPWADR_CH0_MASK;
-@@ -224,27 +219,26 @@ static int aspeed_lpc_enable_snoop(struct aspeed_lpc_snoop *lpc_snoop,
- 		return -EINVAL;
+@@ -221,30 +216,36 @@ static int aspeed_lpc_enable_snoop(struct aspeed_lpc_snoop *lpc_snoop,
+ 		hicrb_en = HICRB_ENSNP1D;
+ 		break;
+ 	default:
+-		return -EINVAL;
++		rc = -EINVAL;
++		goto err_misc_deregister;
  	}
  
 -	regmap_update_bits(lpc_snoop->regmap, HICR5, hicr5_en, hicr5_en);
@@ -3473,6 +3742,12 @@
 -				hicrb_en, hicrb_en);
 +		regmap_update_bits(snoop->regmap, HICRB, hicrb_en, hicrb_en);
  
++	return 0;
++
++err_misc_deregister:
++	misc_deregister(&chan->mdev);
++err_free_fifo:
++	kfifo_free(&chan->fifo);
  	return rc;
  }
  
@@ -3495,7 +3770,7 @@
  				   HICR5_EN_SNP1W | HICR5_ENINT_SNP1W,
  				   0);
  		break;
-@@ -252,96 +246,74 @@ static void aspeed_lpc_disable_snoop(struct aspeed_lpc_snoop *lpc_snoop,
+@@ -252,96 +253,74 @@ static void aspeed_lpc_disable_snoop(struct aspeed_lpc_snoop *lpc_snoop,
  		return;
  	}
  
@@ -3628,7 +3903,7 @@
  }
  
  static const struct aspeed_lpc_snoop_model_data ast2400_model_data = {
-@@ -368,7 +340,7 @@ static struct platform_driver aspeed_lpc_snoop_driver = {
+@@ -368,7 +347,7 @@ static struct platform_driver aspeed_lpc_snoop_driver = {
  		.of_match_table = aspeed_lpc_snoop_match,
  	},
  	.probe = aspeed_lpc_snoop_probe,
@@ -3637,18 +3912,18 @@
  };
  
  module_platform_driver(aspeed_lpc_snoop_driver);
-@@ -376,4 +348,5 @@ module_platform_driver(aspeed_lpc_snoop_driver);
+@@ -376,4 +355,5 @@ module_platform_driver(aspeed_lpc_snoop_driver);
  MODULE_DEVICE_TABLE(of, aspeed_lpc_snoop_match);
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("Robert Lippert <rlippert@google.com>");
 +MODULE_AUTHOR("Chia-Wei Wang <chiawei_wang@aspeedtech.com>");
  MODULE_DESCRIPTION("Linux driver to control Aspeed LPC snoop functionality");
 diff --git a/drivers/soc/aspeed/aspeed-mctp.c b/drivers/soc/aspeed/aspeed-mctp.c
-new file mode 100644
-index 000000000..68b22d1df
+new file mode 100755
+index 000000000..642a66df0
 --- /dev/null
 +++ b/drivers/soc/aspeed/aspeed-mctp.c
-@@ -0,0 +1,2523 @@
+@@ -0,0 +1,2579 @@
 +// SPDX-License-Identifier: GPL-2.0
 +// Copyright (c) 2020, Intel Corporation.
 +
@@ -4047,6 +4322,25 @@
 +}
 +EXPORT_SYMBOL_GPL(aspeed_mctp_packet_free);
 +
++static BLOCKING_NOTIFIER_HEAD(mctp_pcie_vdm_notifier);
++
++int mctp_pcie_vdm_register_notifier(struct notifier_block *nb)
++{
++	return blocking_notifier_chain_register(&mctp_pcie_vdm_notifier, nb);
++}
++EXPORT_SYMBOL_GPL(mctp_pcie_vdm_register_notifier);
++
++int mctp_pcie_vdm_unregister_notifier(struct notifier_block *nb)
++{
++	return blocking_notifier_chain_unregister(&mctp_pcie_vdm_notifier, nb);
++}
++EXPORT_SYMBOL_GPL(mctp_pcie_vdm_unregister_notifier);
++
++static void mctp_pcie_vdm_notify(void *data, unsigned int action)
++{
++	blocking_notifier_call_chain(&mctp_pcie_vdm_notifier, action, data);
++}
++
 +static int _get_bdf(struct aspeed_mctp *priv)
 +{
 +	u32 reg;
@@ -4418,6 +4712,7 @@
 +		} else {
 +			wake_up_all(&client->wait_queue);
 +		}
++		mctp_pcie_vdm_notify(client, MCTP_PCIE_VDM_NOTIFY_RECV);
 +		aspeed_mctp_client_put(client);
 +	} else {
 +		dev_dbg(priv->dev, "Failed to dispatch RX packet\n");
@@ -4521,6 +4816,7 @@
 +	struct aspeed_mctp_rx_cmd *rx_cmd;
 +	u32 hw_read_ptr;
 +	u32 *hdr, *payload;
++	bool rx_full;
 +
 +	if (priv->match_data->vdm_hdr_direct_xfer && priv->match_data->fifo_auto_surround) {
 +		struct mctp_pcie_packet_data *rx_buf;
@@ -4530,6 +4826,12 @@
 +		regmap_write(priv->map, ASPEED_MCTP_RX_BUF_RD_PTR, UPDATE_RX_RD_PTR);
 +
 +		/*
++		 * rx->stopped indicates if rx ring is full or not.
++		 * Use rx_full to note ring status before consuming packet.
++		 */
++		rx_full = rx->stopped;
++
++		/*
 +		 * XXX: Using rd_ptr obtained from HW is unreliable so we need to
 +		 * maintain the state of buffer on our own by peeking into the buffer
 +		 * and checking where the packet was written.
@@ -4685,9 +4987,26 @@
 +
 +	/* Kick RX if it was stopped due to ring full condition */
 +	if (rx->stopped) {
-+		regmap_update_bits(priv->map, ASPEED_MCTP_CTRL, RX_CMD_READY,
-+				   RX_CMD_READY);
-+		rx->stopped = false;
++		if (!rx_full) {
++			/*
++			 * RX ring may still be full in here as the HW keeps producing when Tasklet consumes the packets.
++			 * Use rx_full to detect if RX ring is already full before or after Tasklet consumption.
++			 * Schedule another tasklet here to consume RX ring before restarting reception if ring is full after the while loop,
++			 * in case that RX_CMD_NO_MORE_INT interrupts tasklet after tasklet consumes packets.
++			 * Use flag cause we cannot control if ASPEED_MCTP_RX_BUF_WR_PTR can be updated before ring full occurs.
++			 * Example of problematic scenario:
++			 * 1. Tasklet executing, found *hdr==0 at wr_ptr=14, break the while loop and going forward.
++			 * 2. After leaving the loop, Tasklet spend time doing some time-consuming stuffs like printing log.
++			 * 3. HW keep receiving during step2, and triggered RX_CMD_NO_MORE_INT to set rx->stopped to true in the IRQ handler.
++			 * 4. CPU returns to Tasklet, after step2 the tasklet sees rx->stopped == true, therefore kick RX_READY to restart RX.
++			 * 5. Issue reproduced, RX restarted without stored packets consumed, and get overwritten later.
++			 */
++			tasklet_hi_schedule(&priv->rx.tasklet);
++		} else {
++			rx->stopped = false;
++			regmap_update_bits(priv->map, ASPEED_MCTP_CTRL, RX_CMD_READY,
++					   RX_CMD_READY);
++		}
 +	}
 +}
 +
@@ -5104,7 +5423,8 @@
 +	return ret;
 +}
 +
-+static int aspeed_mctp_register_default_handler(struct mctp_client *client)
++EXPORT_SYMBOL_GPL(aspeed_mctp_register_default_handler);
++int aspeed_mctp_register_default_handler(struct mctp_client *client)
 +{
 +	struct aspeed_mctp *priv = client->priv;
 +	int ret = 0;
@@ -5605,6 +5925,7 @@
 +{
 +	int ret;
 +	u8 tx_max_payload_size;
++	u8 rx_max_payload_size;
 +	struct kobject *kobj = &priv->mctp_miscdev.this_device->kobj;
 +
 +	ret = _get_bdf(priv);
@@ -5614,24 +5935,33 @@
 +		if (priv->match_data->need_address_mapping)
 +			regmap_update_bits(priv->map, ASPEED_MCTP_EID,
 +					   MEMORY_SPACE_MAPPING, BIT(31));
-+		if (priv->match_data->dma_need_64bits_width)
++		if (priv->match_data->dma_need_64bits_width) {
 +			tx_max_payload_size =
 +				FIELD_GET(TX_MAX_PAYLOAD_SIZE_MASK,
 +					  ilog2(ASPEED_MCTP_MTU >> 6));
-+		else
-+		/*
-+		 * In ast2600, tx som and eom will not match expected result.
-+		 * e.g. When Maximum Transmit Unit (MTU) set to 64 byte, and then transfer
-+		 * size set between 61 ~ 124 (MTU-3 ~ 2*MTU-4), the engine will set all
-+		 * packet vdm header eom to 1, no matter what it setted. To fix that
-+		 * issue, the driver set MTU to next level(e.g. 64 to 128).
-+		 */
++			rx_max_payload_size =
++				FIELD_GET(RX_MAX_PAYLOAD_SIZE_MASK,
++					  (ilog2(ASPEED_MCTP_MTU >> 6)) << RX_MAX_PAYLOAD_SIZE_SHIFT);
++		} else {
++			/*
++			 * In ast2600, tx som and eom will not match expected result.
++			 * e.g. When Maximum Transmit Unit (MTU) set to 64 byte, and then transfer
++			 * size set between 61 ~ 124 (MTU-3 ~ 2*MTU-4), the engine will set all
++			 * packet vdm header eom to 1, no matter what it setted. To fix that
++			 * issue, the driver set MTU to next level(e.g. 64 to 128).
++			 */
 +			tx_max_payload_size =
 +				FIELD_GET(TX_MAX_PAYLOAD_SIZE_MASK,
-+					  fls(ASPEED_MCTP_MTU >> 6));
++						fls(ASPEED_MCTP_MTU >> 6));
++			rx_max_payload_size =
++				FIELD_GET(RX_MAX_PAYLOAD_SIZE_MASK,
++					   (fls(ASPEED_MCTP_MTU >> 6)) << RX_MAX_PAYLOAD_SIZE_SHIFT);
++		}
++
 +		regmap_update_bits(priv->map, ASPEED_MCTP_ENGINE_CTRL,
-+				   TX_MAX_PAYLOAD_SIZE_MASK,
-+				   tx_max_payload_size);
++				   TX_MAX_PAYLOAD_SIZE_MASK | RX_MAX_PAYLOAD_SIZE_MASK,
++				   (rx_max_payload_size << RX_MAX_PAYLOAD_SIZE_SHIFT) | tx_max_payload_size);
++
 +		aspeed_mctp_flush_all_tx_queues(priv);
 +		if (!priv->miss_mctp_int) {
 +			aspeed_mctp_irq_enable(priv);
@@ -5690,7 +6020,7 @@
 +	if (status & TX_CMD_SENT_INT) {
 +		tasklet_hi_schedule(&priv->tx.tasklet);
 +		if (!priv->match_data->fifo_auto_surround)
-+			priv->tx.rd_ptr = priv->tx.rd_ptr + 1 % TX_PACKET_COUNT;
++			priv->tx.rd_ptr = (priv->tx.rd_ptr + 1) % TX_PACKET_COUNT;
 +		handled |= TX_CMD_SENT_INT;
 +	}
 +
@@ -5848,7 +6178,7 @@
 +		dma_alloc_coherent(priv->dev, alloc_size, &rx->data.dma_handle, GFP_KERNEL);
 +
 +	if (!rx->data.vaddr)
-+		return ret;
++		return -ENOMEM;
 +
 +	alloc_size = PAGE_ALIGN(priv->rx_packet_count * priv->match_data->rx_cmd_size);
 +	rx->cmd.vaddr = dma_alloc_coherent(priv->dev, alloc_size, &rx->cmd.dma_handle, GFP_KERNEL);
@@ -5887,7 +6217,7 @@
 +	dma_free_coherent(priv->dev, alloc_size, rx->data.vaddr,
 +			  rx->data.dma_handle);
 +
-+	return ret;
++	return -ENOMEM;
 +}
 +
 +static void aspeed_mctp_dma_fini(struct aspeed_mctp *priv)
@@ -6147,6 +6477,7 @@
 +
 +static int __init aspeed_mctp_init(void)
 +{
++	pr_info("aspeed_mctp_init\n");
 +	packet_cache =
 +		kmem_cache_create_usercopy("mctp-packet",
 +					   sizeof(struct mctp_pcie_packet),
@@ -6172,40 +6503,12 @@
 +MODULE_LICENSE("GPL");
 +MODULE_AUTHOR("Iwona Winiarska <iwona.winiarska@intel.com>");
 +MODULE_DESCRIPTION("Aspeed MCTP driver");
-diff --git a/drivers/soc/aspeed/aspeed-p2a-ctrl.c b/drivers/soc/aspeed/aspeed-p2a-ctrl.c
-index 548f44da2..8610ddacc 100644
---- a/drivers/soc/aspeed/aspeed-p2a-ctrl.c
-+++ b/drivers/soc/aspeed/aspeed-p2a-ctrl.c
-@@ -383,13 +383,11 @@ static int aspeed_p2a_ctrl_probe(struct platform_device *pdev)
- 	return rc;
- }
- 
--static int aspeed_p2a_ctrl_remove(struct platform_device *pdev)
-+static void aspeed_p2a_ctrl_remove(struct platform_device *pdev)
- {
- 	struct aspeed_p2a_ctrl *p2a_ctrl = dev_get_drvdata(&pdev->dev);
- 
- 	misc_deregister(&p2a_ctrl->miscdev);
--
--	return 0;
- }
- 
- #define SCU2C_DRAM	BIT(25)
-@@ -433,7 +431,7 @@ static struct platform_driver aspeed_p2a_ctrl_driver = {
- 		.of_match_table = aspeed_p2a_ctrl_match,
- 	},
- 	.probe = aspeed_p2a_ctrl_probe,
--	.remove = aspeed_p2a_ctrl_remove,
-+	.remove_new = aspeed_p2a_ctrl_remove,
- };
- 
- module_platform_driver(aspeed_p2a_ctrl_driver);
 diff --git a/drivers/soc/aspeed/aspeed-pcie-mmbi.c b/drivers/soc/aspeed/aspeed-pcie-mmbi.c
-new file mode 100644
-index 000000000..0169e318e
+new file mode 100755
+index 000000000..6d4a4fd4f
 --- /dev/null
 +++ b/drivers/soc/aspeed/aspeed-pcie-mmbi.c
-@@ -0,0 +1,383 @@
+@@ -0,0 +1,964 @@
 +// SPDX-License-Identifier: GPL-2.0-or-later
 +// Copyright (C) ASPEED Technology Inc.
 +
@@ -6231,23 +6534,29 @@
 +#include <linux/miscdevice.h>
 +#include <linux/poll.h>
 +
++#include <linux/if_arp.h>
++#include <linux/skbuff.h>
++#include <linux/mctp.h>
++#include <net/mctp.h>
++#include <net/pkt_sched.h>
++
 +#include "aspeed-pcie-mmbi.h"
 +
 +/* AST2700 E2M */
-+#define ASPEED_E2M_EVENT		0x0D0
-+#define ASPEED_E2M_EVENT_SET		0x0D4
-+#define ASPEED_E2M_EVENT_CLR		0x0D8
-+#define ASPEED_E2M_EVENT_EN		0x0DC
-+#define ASPEED_E2M_ADRMAP00		0x100
-+#define ASPEED_E2M_WIRQA0		0x180
-+#define ASPEED_E2M_WIRQV0		0x1C0
-+#define ASPEED_E2M_SPROT_SIDG0		0x210
-+#define ASPEED_E2M_SPROT_CTL0		0x280
-+#define ASPEED_E2M_SPROT_ADR0		0x2C0
++#define ASPEED_E2M_EVENT 0x0D0
++#define ASPEED_E2M_EVENT_SET 0x0D4
++#define ASPEED_E2M_EVENT_CLR 0x0D8
++#define ASPEED_E2M_EVENT_EN 0x0DC
++#define ASPEED_E2M_ADRMAP00 0x100
++#define ASPEED_E2M_WIRQA0 0x180
++#define ASPEED_E2M_WIRQV0 0x1C0
++#define ASPEED_E2M_SPROT_SIDG0 0x210
++#define ASPEED_E2M_SPROT_CTL0 0x280
++#define ASPEED_E2M_SPROT_ADR0 0x2C0
 +
 +/* AST2700 SCU */
-+#define ASPEED_SCU_DECODE_DEV		BIT(18)
-+#define ASPEED_SCU_INT_EN		BIT(23)
++#define ASPEED_SCU_DECODE_DEV BIT(18)
++#define ASPEED_SCU_INT_EN BIT(23)
 +struct aspeed_platform {
 +	int (*mmbi_init)(struct platform_device *pdev);
 +};
@@ -6263,91 +6572,660 @@
 +	int pid;
 +	int scu_bar_offset;
 +	int e2m_index;
-+
-+	/* MISC */
-+	struct miscdevice mdev;
-+	wait_queue_head_t wq;
++	int e2m_h2b_int;
 +
 +	/* Memory Mapping */
 +	void __iomem *mem_virt;
 +	dma_addr_t mem_phy;
 +	phys_addr_t mem_size;
 +
-+	/* BMC Interrupt */
-+	bool bmc_int_en;
-+	u8 bmc_int_byte;
-+	u32 bmc_int_offset;
-+	bool bmc_int_update;
-+	wait_queue_head_t bmc_int_wq;
++	struct aspeed_mmbi_channel chan;
 +};
 +
-+static struct aspeed_pcie_mmbi *file_aspeed_pcie_mmbi(struct file *file)
++static void mmbi_desc_init(struct aspeed_mmbi_channel *chan);
++
++static u8 mmbi_get_bmc_up(struct aspeed_mmbi_channel *chan)
 +{
-+	return container_of(file->private_data, struct aspeed_pcie_mmbi, mdev);
++	struct host_ros hros;
++
++	memcpy_fromio(&hros, chan->hros_vmem, sizeof(hros));
++
++	return hros.b_up;
 +}
 +
-+static int aspeed_pcie_mmbi_mmap(struct file *file, struct vm_area_struct *vma)
++static u8 mmbi_get_bmc_rdy(struct aspeed_mmbi_channel *chan)
 +{
-+	struct aspeed_pcie_mmbi *mmbi = file_aspeed_pcie_mmbi(file);
-+	unsigned long vsize = vma->vm_end - vma->vm_start;
-+	pgprot_t prot = vma->vm_page_prot;
++	struct host_ros hros;
 +
-+	if (((vma->vm_pgoff << PAGE_SHIFT) + vsize) > mmbi->mem_size)
-+		return -EINVAL;
++	memcpy_fromio(&hros, chan->hros_vmem, sizeof(hros));
 +
-+	prot = pgprot_noncached(prot);
++	return hros.b_rdy;
++}
 +
-+	if (remap_pfn_range(vma, vma->vm_start,
-+			    (mmbi->mem_phy >> PAGE_SHIFT) + vma->vm_pgoff, vsize, prot))
++static u8 mmbi_get_bmc_rst(struct aspeed_mmbi_channel *chan)
++{
++	struct host_ros hros;
++
++	memcpy_fromio(&hros, chan->hros_vmem, sizeof(hros));
++
++	return hros.b_rst;
++}
++
++static u8 mmbi_get_host_rst(struct aspeed_mmbi_channel *chan)
++{
++	struct host_rws hrws;
++
++	memcpy_fromio(&hrws, chan->hrws_vmem, sizeof(hrws));
++
++	return hrws.h_rst;
++}
++
++static u8 mmbi_get_host_rdy(struct aspeed_mmbi_channel *chan)
++{
++	struct host_rws hrws;
++
++	memcpy_fromio(&hrws, chan->hrws_vmem, sizeof(hrws));
++
++	return hrws.h_rdy;
++}
++
++static u8 mmbi_get_host_up(struct aspeed_mmbi_channel *chan)
++{
++	struct host_rws hrws;
++
++	memcpy_fromio(&hrws, chan->hrws_vmem, sizeof(hrws));
++
++	return hrws.h_up;
++}
++
++static void mmbi_set_bmc_rst(struct aspeed_mmbi_channel *chan, bool set)
++{
++	struct host_ros hros;
++
++	memcpy_fromio(&hros, chan->hros_vmem, sizeof(hros));
++	hros.b_rst = set;
++	memcpy_toio(chan->hros_vmem, &hros, sizeof(hros));
++}
++
++static void mmbi_set_bmc_rdy(struct aspeed_mmbi_channel *chan, bool set)
++{
++	struct host_ros hros;
++
++	memcpy_fromio(&hros, chan->hros_vmem, sizeof(hros));
++	hros.b_rdy = set;
++	memcpy_toio(chan->hros_vmem, &hros, sizeof(hros));
++}
++
++static void mmbi_set_bmc_up(struct aspeed_mmbi_channel *chan, bool set)
++{
++	struct host_ros hros;
++
++	memcpy_fromio(&hros, chan->hros_vmem, sizeof(hros));
++	hros.b_up = set;
++	memcpy_toio(chan->hros_vmem, &hros, sizeof(hros));
++}
++
++static void raise_b2h_interrupt(struct aspeed_mmbi_channel *chan)
++{
++	if (!chan->host_int_en)
++		return;
++
++	regmap_write(chan->mmbi->e2m, ASPEED_E2M_EVENT_SET, BIT(chan->mmbi->e2m_h2b_int));
++}
++
++static void mmbi_clear_hros(struct aspeed_mmbi_channel *chan)
++{
++	memset_io(chan->hros_vmem, 0, sizeof(struct host_ros));
++}
++
++static void mmbi_clear_hrws(struct aspeed_mmbi_channel *chan)
++{
++	memset_io(chan->hrws_vmem, 0, sizeof(struct host_rws));
++}
++
++static void get_b2h_avail_buf_len(struct aspeed_mmbi_channel *chan, ssize_t *avail_buf_len)
++{
++	struct device *dev = chan->dev;
++	u32 b2h_rp, b2h_wp;
++
++	b2h_rp = GET_B2H_READ_POINTER(chan);
++	b2h_wp = GET_B2H_WRITE_POINTER(chan);
++	dev_dbg(dev, "MMBI B2H - b2h_rp: 0x%0x, b2h_wp: 0x%0x\n", b2h_rp, b2h_wp);
++
++	if (b2h_wp >= b2h_rp)
++		*avail_buf_len = chan->b2h_cb_size - b2h_wp + b2h_rp;
++	else
++		*avail_buf_len = b2h_rp - b2h_wp;
++}
++
++static u8 mmbi_get_state(struct aspeed_mmbi_channel *chan)
++{
++	u8 state = 0;
++
++	state = mmbi_get_bmc_up(chan) << 3;
++	state |= mmbi_get_bmc_rst(chan) << 2;
++	state |= mmbi_get_host_up(chan) << 1;
++	state |= mmbi_get_host_rst(chan);
++
++	return state;
++}
++
++static int get_mmbi_header(struct aspeed_mmbi_channel *chan, u32 *data_length,
++			   u8 *type, u32 *unread_data_len, u8 *padding)
++{
++	u32 h2b_wp, h2b_rp, b2h_wp, b2h_rp;
++	struct device *dev = chan->dev;
++	struct mmbi_header header;
++
++	h2b_wp = GET_H2B_WRITE_POINTER(chan);
++	h2b_rp = GET_H2B_READ_POINTER(chan);
++	b2h_wp = GET_B2H_WRITE_POINTER(chan);
++	b2h_rp = GET_B2H_READ_POINTER(chan);
++	dev_dbg(dev, "MMBI HRWS - h2b_wp: 0x%0x, b2h_rp: 0x%0x\n", h2b_wp,
++		b2h_rp);
++	dev_dbg(dev, "MMBI HROS - b2h_wp: 0x%0x, h2b_rp: 0x%0x\n", b2h_wp,
++		h2b_rp);
++
++	if (h2b_wp >= h2b_rp)
++		*unread_data_len = h2b_wp - h2b_rp;
++	else
++		*unread_data_len = chan->h2b_cb_size - h2b_rp + h2b_wp;
++
++	if (*unread_data_len < sizeof(struct mmbi_header)) {
++		dev_dbg(dev, "No data to read(%d - %d)\n", h2b_wp, h2b_rp);
 +		return -EAGAIN;
++	}
++
++	dev_dbg(dev, "READ MMBI header from: 0x%lx\n",
++		(ssize_t)(chan->h2b_cb_vmem + h2b_rp));
++
++	/* Extract MMBI protocol - protocol type and length */
++	if ((h2b_rp + sizeof(header)) <= chan->h2b_cb_size) {
++		memcpy_fromio(&header, chan->h2b_cb_vmem + h2b_rp,
++			      sizeof(header));
++	} else {
++		ssize_t chunk_len = chan->h2b_cb_size - h2b_rp;
++
++		memcpy_fromio(&header, chan->h2b_cb_vmem + h2b_rp, chunk_len);
++		memcpy_fromio(((u8 *)&header) + chunk_len, chan->h2b_cb_vmem,
++			      sizeof(header) - chunk_len);
++	}
++
++	*data_length = (header.pkt_len << 2) - sizeof(header) - header.pkt_pad;
++	*padding = header.pkt_pad;
++	*type = header.pkt_type;
 +
 +	return 0;
 +}
 +
-+static __poll_t aspeed_pcie_mmbi_poll(struct file *file, struct poll_table_struct *pt)
++static int mmbi_state_check(struct aspeed_mmbi_channel *chan)
 +{
-+	struct aspeed_pcie_mmbi *mmbi = file_aspeed_pcie_mmbi(file);
++	enum mmbi_state current_state = mmbi_get_state(chan);
++	struct device *dev = chan->dev;
++	u32 req_data_len, unread_data_len;
++	u8 type, padding;
 +
-+	poll_wait(file, &mmbi->bmc_int_wq, pt);
++	switch (current_state) {
++	case INIT_MISMATCH:
++		dev_dbg(dev, "Get INIT_MISMATCH state from HOST");
++		/* Reset MMBI data structure */
++		mmbi_desc_init(chan);
++		/* Translat state to INIT_IN_PROGRESS */
++		mmbi_clear_hros(chan);
++		mmbi_clear_hrws(chan);
++		/* Translat state to INIT_COMPLETED*/
++		mmbi_set_bmc_up(chan, 1);
 +
-+	if (!mmbi->bmc_int_update)
-+		return 0;
++		dev_dbg(dev, "Change state to INIT_COMPLETED to HOST");
++		raise_b2h_interrupt(chan);
++		return 1;
++	case NORMAL_RUNTIME:
++		if (mmbi_get_bmc_rdy(chan))
++			return 0;
++		dev_dbg(dev, "Get NORMAL_RUNTIME state from HOST");
++		mmbi_set_bmc_rdy(chan, 1);
++		return 1;
++	case RESET_REQ_BY_HOST:
++		dev_dbg(dev, "Get RESET_REQ_BY_HOST state from HOST");
++		/* Stop operation */
++		mmbi_set_bmc_rdy(chan, 0);
++		/* Change state to RESET_ACKED */
++		mmbi_set_bmc_rst(chan, 1);
++		raise_b2h_interrupt(chan);
++		/* Change state to TRANS_TO_INIT */
++		mmbi_set_bmc_up(chan, 0);
++		/* Reset MMBI data structure */
++		mmbi_desc_init(chan);
++		/* Translat state to INIT_IN_PROGRESS */
++		mmbi_clear_hros(chan);
++		mmbi_clear_hrws(chan);
++		/* Translat state to INIT_COMPLETED*/
++		mmbi_set_bmc_up(chan, 1);
 +
-+	mmbi->bmc_int_update = false;
++		dev_dbg(dev, "Change state to INIT_COMPLETED to HOST");
++		raise_b2h_interrupt(chan);
++		return 1;
++	case RESET_ACKED:
++		/* Receive all packet from Host */
++		while (get_mmbi_header(chan, &req_data_len, &type, &unread_data_len, &padding) == 0 &&
++		       mmbi_get_state(chan) == RESET_ACKED)
++			;
++		/* Change state to TRANS_TO_INIT */
++		mmbi_set_bmc_up(chan, 0);
++		/* Reset MMBI data structure */
++		mmbi_desc_init(chan);
++		/* Translat state to INIT_IN_PROGRESS */
++		mmbi_clear_hros(chan);
++		mmbi_clear_hrws(chan);
++		/* Translat state to INIT_COMPLETED*/
++		mmbi_set_bmc_up(chan, 1);
 +
-+	return EPOLLIN;
++		dev_dbg(dev, "Change state to INIT_COMPLETED to HOST");
++		raise_b2h_interrupt(chan);
++	default:
++		break;
++	}
++
++	return 0;
 +}
 +
-+static const struct file_operations aspeed_pcie_mmbi_fops = {
-+	.owner		= THIS_MODULE,
-+	.mmap		= aspeed_pcie_mmbi_mmap,
-+	.poll		= aspeed_pcie_mmbi_poll,
++static void update_host_ros(struct aspeed_mmbi_channel *chan, unsigned int w_len,
++			    unsigned int r_len)
++{
++	struct device *dev = chan->dev;
++	struct host_ros hros;
++	u32 h2b_rp, b2h_wp;
++
++	b2h_wp = GET_B2H_WRITE_POINTER(chan);
++	h2b_rp = GET_H2B_READ_POINTER(chan);
++
++	/* Advance the B2H CB offset for next write */
++	if ((b2h_wp + w_len) <= chan->b2h_cb_size)
++		b2h_wp += w_len;
++	else
++		b2h_wp = b2h_wp + w_len - chan->b2h_cb_size;
++
++	/* Advance the H2B CB offset till where BMC read data */
++	if ((h2b_rp + r_len) <= chan->h2b_cb_size)
++		h2b_rp += r_len;
++	else
++		h2b_rp = h2b_rp + r_len - chan->h2b_cb_size;
++
++	memcpy_fromio(&hros, chan->hros_vmem, sizeof(hros));
++	hros.b2h_wp = FIELD_GET(B2H_WRITE_POINTER_MASK, b2h_wp);
++	hros.h2b_rp = FIELD_GET(H2B_READ_POINTER_MASK, h2b_rp);
++	memcpy_toio(chan->hros_vmem, &hros, sizeof(hros));
++	dev_dbg(dev, "Updating HROS - h2b_rp: 0x%0x, b2h_wp: 0x%0x\n", h2b_rp, b2h_wp);
++
++	if (w_len != 0)
++		raise_b2h_interrupt(chan);
++}
++
++static int aspeed_mmbi_write(struct aspeed_mmbi_channel *chan, char *buffer, size_t len,
++			     protocol_type type)
++{
++	struct device *dev = chan->dev;
++	struct mmbi_header header = { 0 };
++	ssize_t avail_buf_len;
++	ssize_t total_len;
++	ssize_t wt_offset;
++	ssize_t chunk_len;
++	ssize_t end_offset;
++	u8 padding = 0;
++
++	/* If HOST READY bit is not set, Just discard the write. */
++	if (!GET_HOST_READY_BIT(chan)) {
++		dev_dbg(dev, "Host not ready, discarding request...\n");
++		return -EAGAIN;
++	}
++
++	get_b2h_avail_buf_len(chan, &avail_buf_len);
++
++	dev_dbg(dev, "B2H buffer empty space: %ld\n", avail_buf_len);
++
++	/* Header size */
++	total_len = len + 4;
++
++	padding = total_len & 0x3;
++	if (padding)
++		padding = 4 - padding;
++	total_len += padding;
++
++	/* Empty space should be more than write request data size */
++	if (avail_buf_len <= sizeof(header) || (total_len > (avail_buf_len - sizeof(header))))
++		return -ENOSPC;
++
++	/* Fill multi-protocol header */
++	header.pkt_type = type;
++	header.pkt_len = total_len >> 2;
++	header.pkt_pad = padding;
++
++	wt_offset = GET_B2H_WRITE_POINTER(chan);
++	end_offset = chan->b2h_cb_size;
++
++	/* Copy Header */
++	if ((end_offset - wt_offset) >= sizeof(header)) {
++		memcpy_toio(chan->b2h_cb_vmem + wt_offset, &header, sizeof(header));
++		wt_offset += sizeof(header);
++	} else {
++		chunk_len = end_offset - wt_offset;
++		memcpy_toio(chan->b2h_cb_vmem + wt_offset, &header, chunk_len);
++		memcpy_toio(chan->b2h_cb_vmem, &header + chunk_len, (sizeof(header) - chunk_len));
++		wt_offset = (sizeof(header) - chunk_len);
++	}
++
++	/* Write the data */
++	if ((end_offset - wt_offset) >= len) {
++		memcpy_toio(&chan->b2h_cb_vmem[wt_offset], buffer, len);
++		wt_offset += len;
++	} else {
++		chunk_len = end_offset - wt_offset;
++		dev_dbg(dev, "Write data chunk_len: %ld\n", chunk_len);
++		memcpy_toio(&chan->b2h_cb_vmem[wt_offset], buffer, chunk_len);
++
++		wt_offset = 0;
++		memcpy_toio(&chan->b2h_cb_vmem[wt_offset], buffer + chunk_len, len - chunk_len);
++		wt_offset += len - chunk_len;
++	}
++
++	update_host_ros(chan, total_len, 0);
++
++	return 0;
++}
++
++static void aspeed_mmbi_read(struct aspeed_mmbi_channel *chan, char *buffer, size_t len, u8 padding)
++{
++	struct device *dev = chan->dev;
++	ssize_t rd_offset;
++	u32 h2b_rp;
++
++	h2b_rp = GET_H2B_READ_POINTER(chan);
++	if ((h2b_rp + sizeof(struct mmbi_header)) <= chan->h2b_cb_size)
++		rd_offset = h2b_rp + sizeof(struct mmbi_header);
++	else
++		rd_offset = h2b_rp + sizeof(struct mmbi_header) - chan->h2b_cb_size;
++
++	/* Extract data and copy to user space application */
++	dev_dbg(dev, "READ MMBI Data from: 0x%0lx and length: %ld\n",
++		(ssize_t)(chan->h2b_cb_vmem + rd_offset), len);
++
++	if ((chan->h2b_cb_size - rd_offset) >= len) {
++		memcpy_fromio(buffer, chan->h2b_cb_vmem + rd_offset, len);
++		rd_offset += len;
++	} else {
++		ssize_t chunk_len;
++
++		chunk_len = chan->h2b_cb_size - rd_offset;
++		dev_dbg(dev, "Read data chunk_len: %ld\n", chunk_len);
++		memcpy_fromio(buffer, chan->h2b_cb_vmem + rd_offset, chunk_len);
++
++		rd_offset = 0;
++		memcpy_fromio(buffer + chunk_len, chan->h2b_cb_vmem + rd_offset, len - chunk_len);
++	}
++
++	update_host_ros(chan, 0, len + sizeof(struct mmbi_header) + padding);
++}
++
++static void mctp_mmbi_rx(struct aspeed_mmbi_channel *chan)
++{
++	struct net_device *ndev = chan->ndev;
++	struct sk_buff *skb;
++	struct mctp_skb_cb *cb;
++	u32 req_data_len, unread_data_len;
++	u8 type, padding;
++	int status;
++
++	if (get_mmbi_header(chan, &req_data_len, &type, &unread_data_len, &padding) != 0)
++		return;
++
++	dev_dbg(chan->dev, "%s: Length: 0x%0x, Protocol Type: %d, Unread data: %d\n", __func__,
++		req_data_len, type, unread_data_len);
++
++	skb = netdev_alloc_skb(ndev, req_data_len);
++	if (!skb) {
++		ndev->stats.rx_dropped++;
++		update_host_ros(chan, 0, req_data_len + sizeof(struct mmbi_header));
++		return;
++	}
++
++	skb->protocol = htons(ETH_P_MCTP);
++	aspeed_mmbi_read(chan, skb_put(skb, req_data_len), req_data_len, padding);
++	skb_reset_network_header(skb);
++
++	cb = __mctp_cb(skb);
++	cb->halen = 0;
++
++	status = netif_rx(skb);
++	if (status == NET_RX_SUCCESS) {
++		ndev->stats.rx_packets++;
++		ndev->stats.rx_bytes += req_data_len;
++	} else {
++		ndev->stats.rx_dropped++;
++	}
++}
++
++static netdev_tx_t mctp_mmbi_tx(struct sk_buff *skb, struct net_device *ndev)
++{
++	struct aspeed_mmbi_mctp *mctp = netdev_priv(ndev);
++	int ret;
++
++	if (!mmbi_get_host_rdy(&mctp->mmbi->chan) || skb->len > MCTP_MMBI_MTU_MAX) {
++		ndev->stats.tx_dropped++;
++		goto out;
++	}
++
++	ret = aspeed_mmbi_write(&mctp->mmbi->chan, skb->data, skb->len, MMBI_PROTOCOL_MCTP);
++	if (ret) {
++		netif_stop_queue(ndev);
++		return NETDEV_TX_BUSY;
++	}
++
++	ndev->stats.tx_packets++;
++	ndev->stats.tx_bytes += skb->len;
++out:
++	kfree_skb(skb);
++	return NETDEV_TX_OK;
++}
++
++static const struct net_device_ops mctp_mmbi_netdev_ops = {
++	.ndo_start_xmit = mctp_mmbi_tx,
 +};
 +
++static void aspeed_mctp_mmbi_setup(struct net_device *ndev)
++{
++	ndev->type = ARPHRD_MCTP;
++
++	/* we limit at the fixed MTU, which is also the MCTP-standard
++	 * baseline MTU, so is also our minimum
++	 */
++	ndev->mtu = MCTP_MMBI_MTU;
++	ndev->max_mtu = MCTP_MMBI_MTU_MAX;
++	ndev->min_mtu = MCTP_MMBI_MTU_MIN;
++
++	ndev->hard_header_len = 0;
++	ndev->addr_len = 0;
++	ndev->tx_queue_len = DEFAULT_TX_QUEUE_LEN;
++	ndev->flags = IFF_NOARP;
++	ndev->netdev_ops = &mctp_mmbi_netdev_ops;
++	ndev->needs_free_netdev = true;
++}
++
++static int aspeed_mmbi_mctp_init(struct aspeed_mmbi_channel *chan)
++{
++	struct aspeed_mmbi_mctp *mctp;
++	struct net_device *ndev;
++	char name[32];
++	int ret;
++
++	snprintf(name, sizeof(name), "mctpmmbi%d%d", chan->mmbi->id, chan->mmbi->e2m_index);
++	ndev = alloc_netdev(sizeof(*mctp), name, NET_NAME_ENUM, aspeed_mctp_mmbi_setup);
++	if (!ndev)
++		return -ENOMEM;
++
++	mctp = netdev_priv(ndev);
++	mctp->ndev = ndev;
++	mctp->mmbi = chan->mmbi;
++
++	chan->ndev = ndev;
++
++	ret = register_netdev(ndev);
++	if (ret)
++		goto free_netdev;
++
++	return 0;
++
++free_netdev:
++	free_netdev(ndev);
++
++	return ret;
++}
++
++static void aspeed_mmbi_work_func(struct work_struct *workq)
++{
++	struct aspeed_mmbi_channel *chan = container_of(workq, struct aspeed_mmbi_channel, work);
++	u32 weight = 256, req_data_len, unread_data_len;
++	u8 type, padding;
++	int i;
++
++	for (i = 0; i < weight; i++) {
++		if (get_mmbi_header(chan, &req_data_len, &type, &unread_data_len, &padding) != 0)
++			return;
++
++		dev_dbg(chan->dev, "%s: Length: 0x%0x, Protocol Type: %d\n",
++			__func__, req_data_len, type);
++
++		if (type == MMBI_PROTOCOL_MCTP)
++			mctp_mmbi_rx(chan);
++		else
++			/* Discard data and advance the hrws */
++			update_host_ros(chan, 0, req_data_len + sizeof(struct mmbi_header) + padding);
++
++		raise_b2h_interrupt(chan);
++	}
++
++	if (get_mmbi_header(chan, &req_data_len, &type, &unread_data_len, &padding) != 0)
++		queue_work(system_unbound_wq, &chan->work);
++}
++
 +static irqreturn_t aspeed_pcie_mmbi_isr(int irq, void *dev_id)
 +{
 +	struct aspeed_pcie_mmbi *mmbi = dev_id;
++	struct aspeed_mmbi_channel *chan = &mmbi->chan;
++	ssize_t avail_buf_len;
 +
-+	mmbi->bmc_int_update = true;
-+	wake_up_interruptible(&mmbi->bmc_int_wq);
++	get_b2h_avail_buf_len(chan, &avail_buf_len);
++	if (avail_buf_len > MCTP_MMBI_MTU_MAX) {
++		if (netif_queue_stopped(chan->ndev)) {
++			dev_dbg(chan->dev, "Wake up mctp net device\n");
++			netif_wake_queue(chan->ndev);
++		}
++	}
++
++	if (mmbi_state_check(chan))
++		return IRQ_HANDLED;
++
++	queue_work(system_unbound_wq, &chan->work);
 +
 +	return IRQ_HANDLED;
 +}
 +
++static void mmbi_desc_init(struct aspeed_mmbi_channel *chan)
++{
++	struct mmbi_cap_desc desc;
++
++	memset(&desc, 0, sizeof(struct mmbi_cap_desc));
++
++	desc.version = 1;
++	/* This MMBI interface is intended for OS use */
++	desc.os_use = 1;
++	desc.b2h_ba = (chan->b2h_cb_vmem - chan->desc_vmem) >> 3;
++	desc.h2b_ba = (chan->h2b_cb_vmem - chan->desc_vmem) >> 3;
++	/* Make sure the buffer size is 4 byte aligmnent */
++	desc.b2h_l = chan->b2h_cb_size & ~0x3;
++	desc.h2b_l = chan->h2b_cb_size & ~0x3;
++	/* Variable Packet Size Circular Buffers (VPSCB) v1 */
++	desc.buffer_type = 0x01;
++	desc.bt_desc.h_ros_p = (chan->hros_vmem - chan->desc_vmem) >> 3;
++	desc.bt_desc.h_rws_p = (chan->hrws_vmem - chan->desc_vmem) >> 3;
++	/* PCIe Interrupt */
++	desc.bt_desc.h_int_t = 0x01;
++	desc.bt_desc.h_int_l = chan->host_int_location;
++	desc.bt_desc.h_int_v = 0; /* Skip for PCIe Interrupt */
++	desc.bt_desc.bmc_int_t = 0x01; /* relative memory space address */
++	desc.bt_desc.bmc_int_l = chan->bmc_int_location;
++	desc.bt_desc.bmc_int_v = chan->bmc_int_value;
++
++	/* Per MMBI protoco spec, Set it to "#MMBI$" */
++	memcpy(desc.signature, MMBI_SIGNATURE, sizeof(desc.signature));
++
++	memcpy_toio(chan->desc_vmem, &desc, sizeof(desc));
++}
++
++static int aspeed_pcie_mmbi_init(struct aspeed_pcie_mmbi *mmbi)
++{
++	struct aspeed_mmbi_channel *chan = &mmbi->chan;
++	struct device *dev = chan->dev;
++	u32 b2h_size = mmbi->mem_size >> 1;
++	u32 h2b_size = mmbi->mem_size >> 1;
++	u8 *h2b_vaddr, *b2h_vaddr;
++	int ret;
++
++	b2h_vaddr = mmbi->mem_virt;
++	h2b_vaddr = b2h_vaddr + b2h_size;
++
++	chan->dev = dev;
++	chan->desc_vmem = b2h_vaddr;
++	chan->hros_vmem = b2h_vaddr + sizeof(struct mmbi_cap_desc);
++	chan->b2h_cb_vmem = b2h_vaddr + sizeof(struct mmbi_cap_desc) + sizeof(struct host_ros);
++	chan->b2h_cb_size = b2h_size - sizeof(struct mmbi_cap_desc) - sizeof(struct host_ros);
++
++	chan->hrws_vmem = h2b_vaddr;
++	chan->h2b_cb_vmem = h2b_vaddr + sizeof(struct host_rws);
++	chan->h2b_cb_size = h2b_size - sizeof(struct host_rws);
++
++	dev_dbg(dev, "B2H mapped addr - desc: 0x%0lx, hros: 0x%0lx, b2h_cb: 0x%0lx\n",
++		(size_t)chan->desc_vmem, (size_t)chan->hros_vmem, (size_t)chan->b2h_cb_vmem);
++	dev_dbg(dev, "H2B mapped addr - hrws: 0x%0lx, h2b_cb: 0x%0lx\n", (size_t)chan->hrws_vmem,
++		(size_t)chan->h2b_cb_vmem);
++
++	dev_dbg(dev, "B2H buffer size: 0x%0lx\n", (size_t)chan->b2h_cb_size);
++	dev_dbg(dev, "H2B buffer size: 0x%0lx\n", (size_t)chan->h2b_cb_size);
++
++	/* Initialize the MMBI channel descriptor */
++	mmbi_desc_init(chan);
++
++	/* Clear HRWS & HROS */
++	mmbi_clear_hros(chan);
++	mmbi_clear_hrws(chan);
++
++	/* Initialize MTCP function */
++	ret = aspeed_mmbi_mctp_init(chan);
++	if (ret) {
++		dev_err(dev, "Unable to init mctp\n");
++		return ret;
++	}
++
++	/* Set BMC UP bit */
++	mmbi_set_bmc_up(chan, 1);
++
++	return 0;
++}
++
 +/*
 + * AST2700 PCIe MMBI (SCU & E2M)
-+ * SoC      |    0                                    |    1                          |
-+ * PCI class|    MFD (0xFF_00_00)                     |    MMBI (0x0C_0C_00)          |
-+ * Node     |    0                   1                |    0                          |
-+ * Alias id |    0    1    2    3    4    5    6    7 |    8    9   10   11   12   13 |
-+ * PID      |    3    4    5    6   11   12   13   14 |    2    3    4    5    6    7 |
-+ * E2M index|    0    1    2    3    4    5    6    7 |    0    1    2    3    4    5 |
-+ * BAR index|    2    3    4    5    2    3    4    5 |    0    1    2    3    4    5 |
-+ * SCU BAR  |   3c   4c   5c   6c   3c   4c   5c   6c |   1c   50   3c   4c   5c   6c |
++ * SoC         |    0                                    |    1                          |
++ * PCI class   |    MFD (0xFF_00_00)                     |    MMBI (0x0C_0C_00)          |
++ * Node        |    0                   1                |    0                          |
++ * PID         |    3    4    5    6   11   12   13   14 |    2    3    4    5    6    7 |
++ * E2M index   |    0    1    2    3    4    5    6    7 |    0    1    2    3    4    5 |
++ * BAR index   |    2    3    4    5    2    3    4    5 |    0    1    2    3    4    5 |
++ * SCU BAR     |   3c   4c   5c   6c   3c   4c   5c   6c |   1c   50   3c   4c   5c   6c |
++ * E2M H2B Int |    0    1    2    3    0    1    2    3 |    0    1    2    3    4    5 | (bit)
 + */
 +static int aspeed_ast2700_pcie_mmbi_init(struct platform_device *pdev)
 +{
 +	struct aspeed_pcie_mmbi *mmbi = platform_get_drvdata(pdev);
++	struct aspeed_mmbi_channel *chan = &mmbi->chan;
 +	struct device *dev = &pdev->dev;
 +	u32 value, sprot_size, e2m_index, pid;
 +	struct resource res;
@@ -6368,7 +7246,7 @@
 +	else if (res.start == 0x12c22000)
 +		mmbi->id = 1;
 +	else
-+		mmbi->id = 0;	/* 0x12c21000 */
++		mmbi->id = 0; /* 0x12c21000 */
 +
 +	mmbi->device = syscon_regmap_lookup_by_phandle(dev->of_node->parent, "aspeed,device");
 +	if (IS_ERR(mmbi->device)) {
@@ -6396,6 +7274,7 @@
 +
 +	e2m_index = mmbi->e2m_index;
 +	pid = mmbi->pid;
++	mmbi->e2m_h2b_int += mmbi->e2m_index;
 +	if (mmbi->id < 2) {
 +		/* PCIe device class, sub-class, protocol and reversion */
 +		regmap_write(mmbi->device, 0x18, 0xFF000027);
@@ -6407,23 +7286,9 @@
 +	/* MSI */
 +	regmap_update_bits(mmbi->device, 0x74, GENMASK(7, 4), BIT(7) | (5 << 4));
 +
-+	regmap_update_bits(mmbi->device, 0x70,
-+			   BIT(25) | BIT(17) | BIT(9) | BIT(1),
++	regmap_update_bits(mmbi->device, 0x70, BIT(25) | BIT(17) | BIT(9) | BIT(1),
 +			   BIT(25) | BIT(17) | BIT(9) | BIT(1));
 +
-+	/* Create MISC device for MMBI */
-+	mmbi->mdev.parent = dev;
-+	mmbi->mdev.minor = MISC_DYNAMIC_MINOR;
-+	mmbi->mdev.name =
-+		devm_kasprintf(dev, GFP_KERNEL, "pcie%d-mmbi%d", mmbi->id, e2m_index);
-+	mmbi->mdev.fops = &aspeed_pcie_mmbi_fops;
-+	ret = misc_register(&mmbi->mdev);
-+	if (ret) {
-+		dev_err(dev, "cannot register device %s\n", mmbi->mdev.name);
-+		return ret;
-+	}
-+	init_waitqueue_head(&mmbi->wq);
-+
 +	/* Calculate the BAR Size */
 +	for (i = 1; i < 16; i++) {
 +		/* bar size check for 4k align */
@@ -6432,23 +7297,22 @@
 +	}
 +	if (i == 16) {
 +		i = 0;
-+		dev_warn(dev, "Bar size not align for 4K : %dK\n",
-+			 (u32)mmbi->mem_size / 1024);
++		dev_warn(dev, "Bar size not align for 4K : %dK\n", (u32)mmbi->mem_size / 1024);
 +	}
 +	regmap_write(mmbi->device, mmbi->scu_bar_offset, (mmbi->mem_phy >> 4) | i);
 +	regmap_write(mmbi->e2m, ASPEED_E2M_ADRMAP00 + (4 * pid), (mmbi->mem_phy >> 4) | i);
 +
 +	/* BMC Interrupt */
-+	if (mmbi->bmc_int_en) {
-+		value = mmbi->mem_phy + mmbi->bmc_int_offset;
++	if (chan->bmc_int_en) {
++		value = mmbi->mem_phy + chan->bmc_int_location;
 +		regmap_write(mmbi->e2m, ASPEED_E2M_WIRQA0 + (4 * e2m_index), value);
-+		value = (BIT(16) << pid) | mmbi->bmc_int_byte;
++		value = (BIT(16) << pid) | chan->bmc_int_value;
 +		regmap_write(mmbi->e2m, ASPEED_E2M_WIRQV0 + (4 * e2m_index), value);
 +	}
 +
 +	/* HOST Interrupt: MSI */
 +	regmap_read(mmbi->e2m, ASPEED_E2M_EVENT_EN, &value);
-+	value |= BIT(e2m_index);
++	value |= BIT(mmbi->e2m_h2b_int);
 +	regmap_write(mmbi->e2m, ASPEED_E2M_EVENT_EN, value);
 +
 +	/* B2H Write Protect */
@@ -6463,6 +7327,16 @@
 +	value |= pid << (8 * (e2m_index % 4));
 +	regmap_write(mmbi->e2m, ASPEED_E2M_SPROT_SIDG0 + (4 * (e2m_index / 4)), value);
 +
++	mmbi->chan.dev = dev;
++	mmbi->chan.mmbi = mmbi;
++	ret = aspeed_pcie_mmbi_init(mmbi);
++	if (ret < 0) {
++		dev_err(dev, "Initialize MMBI device failed.\n");
++		return ret;
++	}
++
++	INIT_WORK(&chan->work, aspeed_mmbi_work_func);
++
 +	return 0;
 +}
 +
@@ -6479,6 +7353,7 @@
 +static int aspeed_pcie_mmbi_probe(struct platform_device *pdev)
 +{
 +	struct aspeed_pcie_mmbi *mmbi;
++	struct aspeed_mmbi_channel *chan;
 +	struct device *dev = &pdev->dev;
 +	struct resource res;
 +	struct device_node *np;
@@ -6509,7 +7384,7 @@
 +
 +	mmbi->mem_phy = res.start;
 +	mmbi->mem_size = resource_size(&res);
-+	mmbi->mem_virt = devm_ioremap_resource(dev, &res);
++	mmbi->mem_virt = ioremap(mmbi->mem_phy, mmbi->mem_size);
 +	if (!mmbi->mem_virt) {
 +		dev_err(dev, "cannot map mmbi memory region\n");
 +		ret = -ENOMEM;
@@ -6522,26 +7397,34 @@
 +		dev_err(&pdev->dev, "platform get of irq[=%d] failed!\n", mmbi->irq);
 +		goto out_unmap;
 +	}
-+	ret = devm_request_irq(&pdev->dev, mmbi->irq, aspeed_pcie_mmbi_isr, 0,
-+			       dev_name(&pdev->dev), mmbi);
++	ret = devm_request_irq(&pdev->dev, mmbi->irq, aspeed_pcie_mmbi_isr, 0, dev_name(&pdev->dev),
++			       mmbi);
 +	if (ret) {
 +		dev_err(dev, "pcie mmbi unable to get IRQ");
 +		goto out_unmap;
 +	}
 +
-+	init_waitqueue_head(&mmbi->bmc_int_wq);
++	chan = &mmbi->chan;
++	memset(chan, 0, sizeof(struct aspeed_mmbi_channel));
 +
-+	mmbi->bmc_int_en = true;
++	chan->bmc_int_en = true;
 +	/* H2B Interrupt */
-+	ret = of_property_read_u8(dev->of_node, "mmbi-bmc-int-value", &mmbi->bmc_int_byte);
++	ret = of_property_read_u8(dev->of_node, "bmc-int-value", &chan->bmc_int_value);
 +	if (ret) {
-+		dev_err(dev, "cannot get valid MMBI H2B interrupt byte\n");
-+		mmbi->bmc_int_en = false;
++		dev_err(dev, "cannot get valid MMBI H2B interrupt value\n");
++		chan->bmc_int_en = false;
 +	}
-+	ret = of_property_read_u32(dev->of_node, "mmbi-bmc-int-offset", &mmbi->bmc_int_offset);
++	ret = of_property_read_u32(dev->of_node, "bmc-int-location", &chan->bmc_int_location);
 +	if (ret) {
-+		dev_err(dev, "cannot get valid MMBI H2B interrupt offset\n");
-+		mmbi->bmc_int_en = false;
++		dev_err(dev, "cannot get valid MMBI H2B interrupt location\n");
++		chan->bmc_int_en = false;
++	}
++	/* B2H Interrupt */
++	chan->host_int_en = true;
++	ret = of_property_read_u8(dev->of_node, "msi", &chan->host_int_value);
++	if (ret) {
++		dev_err(dev, "cannot get valid MMBI B2H interrupt location\n");
++		chan->host_int_en = false;
 +	}
 +
 +	ret = mmbi->platform->mmbi_init(pdev);
@@ -6556,20 +7439,21 @@
 +out_irq:
 +	devm_free_irq(dev, mmbi->irq, mmbi);
 +out_unmap:
-+	devm_iounmap(dev, mmbi->mem_virt);
++	iounmap(mmbi->mem_virt);
 +out_region:
 +	devm_kfree(dev, mmbi);
 +	dev_warn(dev, "aspeed bmc device: driver init failed (ret=%d)!\n", ret);
 +	return ret;
 +}
 +
-+static int  aspeed_pcie_mmbi_remove(struct platform_device *pdev)
++static int aspeed_pcie_mmbi_remove(struct platform_device *pdev)
 +{
 +	struct aspeed_pcie_mmbi *mmbi = platform_get_drvdata(pdev);
 +
-+	misc_deregister(&mmbi->mdev);
++	cancel_work_sync(&mmbi->chan.work);
++	unregister_netdev(mmbi->chan.ndev);
 +	devm_free_irq(&pdev->dev, mmbi->irq, mmbi);
-+	devm_iounmap(&pdev->dev, mmbi->mem_virt);
++	iounmap(mmbi->mem_virt);
 +	devm_kfree(&pdev->dev, mmbi);
 +
 +	return 0;
@@ -6590,11 +7474,11 @@
 +MODULE_DESCRIPTION("ASPEED PCI-E MMBI Driver");
 +MODULE_LICENSE("GPL");
 diff --git a/drivers/soc/aspeed/aspeed-pcie-mmbi.h b/drivers/soc/aspeed/aspeed-pcie-mmbi.h
-new file mode 100644
-index 000000000..0685c9796
+new file mode 100755
+index 000000000..d7e470bc2
 --- /dev/null
 +++ b/drivers/soc/aspeed/aspeed-pcie-mmbi.h
-@@ -0,0 +1,20 @@
+@@ -0,0 +1,141 @@
 +/* SPDX-License-Identifier: GPL-2.0+ */
 +/*
 + * Copyright 2024 Aspeed Technology Inc.
@@ -6602,98 +7486,140 @@
 +#ifndef __ASPEED_PCIE_MMBI_H__
 +#define __ASPEED_PCIE_MMBI_H__
 +
-+#include <linux/ioctl.h>
-+#include <linux/types.h>
++#define MMBI_SIGNATURE "#MMBI$"
 +
-+#define __ASPEED_PCIE_MMBI_MAGIC	0xb8
++//This definitions are as per MMBI specification.
++#define MMBI_PROTOCOL_IPMI 1
++#define MMBI_PROTOCOL_SEAMLESS 2
++#define MMBI_PROTOCOL_RAS_OFFLOAD 3
++#define MMBI_PROTOCOL_MCTP 4
++#define MMBI_PROTOCOL_NODE_MANAGER 5
 +
-+/*
-+ *  - ASPEED_PCIE_MMBI_HOST_INT
-+ *      Triggle Host interrupt
-+ */
-+#define ASPEED_PCIE_MMBI_HOST_INT	_IO(__ASPEED_PCIE_MMBI_MAGIC, \
-+					     0x00)
++#define MMBI_HRWS0(x)	readl((x)->hrws_vmem)
++#define MMBI_HRWS1(x)	readl((x)->hrws_vmem + 4)
++#define MMBI_HROS0(x)	readl((x)->hros_vmem)
++#define MMBI_HROS1(x)	readl((x)->hros_vmem + 4)
 +
-+#endif
-diff --git a/drivers/soc/aspeed/aspeed-sbc.c b/drivers/soc/aspeed/aspeed-sbc.c
-new file mode 100644
-index 000000000..be4497b41
---- /dev/null
-+++ b/drivers/soc/aspeed/aspeed-sbc.c
-@@ -0,0 +1,73 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/* Copyright 2022 IBM Corp. */
++#define H2B_WRITE_POINTER_MASK GENMASK(31, 2)
++#define H2B_READ_POINTER_MASK GENMASK(31, 2)
++#define B2H_WRITE_POINTER_MASK GENMASK(31, 2)
++#define B2H_READ_POINTER_MASK GENMASK(31, 2)
 +
-+#include <linux/io.h>
-+#include <linux/of.h>
-+#include <linux/of_address.h>
-+#include <linux/of_platform.h>
-+#include <linux/debugfs.h>
++#define GET_H2B_WRITE_POINTER(x) (MMBI_HRWS0(x) & H2B_WRITE_POINTER_MASK)
++#define GET_H2B_READ_POINTER(x) (MMBI_HROS1(x) & H2B_READ_POINTER_MASK)
++#define GET_B2H_WRITE_POINTER(x) (MMBI_HROS0(x) & B2H_WRITE_POINTER_MASK)
++#define GET_B2H_READ_POINTER(x) (MMBI_HRWS1(x) & B2H_READ_POINTER_MASK)
 +
-+#define SEC_STATUS		0x14
-+#define ABR_IMAGE_SOURCE	BIT(13)
-+#define OTP_PROTECTED		BIT(8)
-+#define LOW_SEC_KEY		BIT(7)
-+#define SECURE_BOOT		BIT(6)
-+#define UART_BOOT		BIT(5)
++#define GET_HOST_READY_BIT(x) (MMBI_HRWS1(x) & 0x01)
++#define GET_BMC_READY_BIT(x) (MMBI_HROS1(x) & 0x01)
 +
-+struct sbe {
-+	u8 abr_image;
-+	u8 low_security_key;
-+	u8 otp_protected;
-+	u8 secure_boot;
-+	u8 invert;
-+	u8 uart_boot;
++typedef u8 protocol_type;
++
++enum mmbi_state {				/* B_U B_R H_U H_R */
++	INIT_IN_PROGRESS	= 0x00,		/* 0   0   0   0   */
++	INIT_COMPLETED		= 0x08,		/* 1   0   0   0   */
++	NORMAL_RUNTIME		= 0x0A,		/* 1   0   1   0   */
++	RESET_REQ_BY_BMC	= 0x0E,		/* 1   1   1   0   */
++	RESET_REQ_BY_HOST	= 0x0B,		/* 1   0   1   1   */
++	RESET_ACKED		= 0x0F,		/* 1   1   1   1   */
++	TRANS_TO_INIT		= 0x07,		/* 0   1   1   1   */
++	INIT_MISMATCH		= 0x09,		/* 1   0   0   1   */
++	POWER_UP_OR_ERROR	= 0x80000000,
 +};
 +
-+static struct sbe sbe;
++struct mmbi_header {
++	u32 pkt_pad	: 2;
++	u32 pkt_len	: 22;
++	u32 pkt_type	: 4;
++	u32 reserved	: 4;
++};
 +
-+static int __init aspeed_sbc_init(void)
-+{
-+	struct device_node *np;
-+	void __iomem *base;
-+	struct dentry *sbc_dir;
-+	u32 security_status;
++struct host_ros {
++	u32 b_rst	: 1;		/* BMC Reset Request */
++	u32 b_up	: 1;		/* BMC Interface Up */
++	u32 b2h_wp	: 30;		/* B2H Write Pointer */
++	u32 b_rdy	: 1;		/* BMC Ready */
++	u32 reserved1	: 1;
++	u32 h2b_rp	: 30;		/* H2B Read Pointer */
++};
 +
-+	/* AST2600 only */
-+	np = of_find_compatible_node(NULL, NULL, "aspeed,ast2600-sbc");
-+	if (!of_device_is_available(np))
-+		return -ENODEV;
++struct host_rws {
++	u32 h_rst	: 1;		/* Host Reset Request */
++	u32 h_up	: 1;		/* Host Interface Up */
++	u32 h2b_wp	: 30;		/* H2B Write Pointer */
++	u32 h_rdy	: 1;		/* Host Ready */
++	u32 reserved1	: 1;
++	u32 b2h_rp	: 30;		/* B2H Read Pointer */
++};
 +
-+	base = of_iomap(np, 0);
-+	if (!base) {
-+		of_node_put(np);
-+		return -ENODEV;
-+	}
++struct buffer_type_desc {
++	u32 h_ros_p;			/* Host Read-Only Structure Pointer */
++	u32 h_rws_p;			/* Host Read-Write Structure Pointer */
++	u8 h_int_t;			/* Host Interrupt Type */
++	u8 h_int_l;			/* Host Interrupt Location */
++	u8 reserved1[3];
++	u8 h_int_v;			/* Host Interrupt Value */
++	u8 bmc_int_t;			/* BMC Interrupt Type */
++	u32 bmc_int_l;			/* BMC Interrupt Location */
++	u8 reserved2[4];
++	u8 bmc_int_v;			/* BMC Interrupt Value */
++} __packed;
 +
-+	security_status = readl(base + SEC_STATUS);
++struct mmbi_cap_desc {
++	u8 signature[6];
++	u8 version;
++	u8 os_use;
++	u32 b2h_ba;			/* B2H Buffer Base Address */
++	u32 h2b_ba;			/* H2B Buffer Base Address */
++	u32 b2h_l;			/* B2H Buffer Length */
++	u32 h2b_l;			/* H2B Buffer Length */
++	u8 buffer_type;
++	u8 reserved1[7];
++	struct buffer_type_desc bt_desc;
++	u8 reserved2[8];
++} __packed;
 +
-+	iounmap(base);
-+	of_node_put(np);
++struct aspeed_pcie_mmbi;
 +
-+	sbe.abr_image = !!(security_status & ABR_IMAGE_SOURCE);
-+	sbe.low_security_key = !!(security_status & LOW_SEC_KEY);
-+	sbe.otp_protected = !!(security_status & OTP_PROTECTED);
-+	sbe.secure_boot = !!(security_status & SECURE_BOOT);
-+	/* Invert the bit, as 1 is boot from SPI/eMMC */
-+	sbe.uart_boot =  !(security_status & UART_BOOT);
++#define MCTP_MMBI_MTU		65536
++#define MCTP_MMBI_MTU_MIN	68	/* base mtu (64) + mctp header */
++#define MCTP_MMBI_MTU_MAX	65536
 +
-+	pr_info("AST2600 secure boot %s\n", sbe.secure_boot ? "enabled" : "disabled");
++struct aspeed_mmbi_mctp {
++	struct aspeed_pcie_mmbi *mmbi;
++	struct net_device *ndev;
++};
 +
-+	sbc_dir = debugfs_create_dir("sbc", arch_debugfs_dir);
-+	if (IS_ERR(sbc_dir))
-+		return PTR_ERR(sbc_dir);
++struct aspeed_mmbi_channel {
++	struct aspeed_pcie_mmbi *mmbi;
++	struct device *dev;
 +
-+	debugfs_create_u8("abr_image", 0444, sbc_dir, &sbe.abr_image);
-+	debugfs_create_u8("low_security_key", 0444, sbc_dir, &sbe.low_security_key);
-+	debugfs_create_u8("otp_protected", 0444, sbc_dir, &sbe.otp_protected);
-+	debugfs_create_u8("uart_boot", 0444, sbc_dir, &sbe.uart_boot);
-+	debugfs_create_u8("secure_boot", 0444, sbc_dir, &sbe.secure_boot);
++	u32 b2h_cb_size;
++	u32 h2b_cb_size;
++	u8 __iomem *desc_vmem;
++	u8 __iomem *hros_vmem;
++	u8 __iomem *b2h_cb_vmem;
++	u8 __iomem *hrws_vmem;
++	u8 __iomem *h2b_cb_vmem;
 +
-+	return 0;
-+}
++	bool bmc_int_en;
++	u8 bmc_int_value;
++	u32 bmc_int_location;
++	u8 __iomem *bmc_int_vmem;
 +
-+subsys_initcall(aspeed_sbc_init);
++	bool host_int_en;
++	u8 host_int_location;
++	u8 host_int_value;
++
++	enum mmbi_state state;
++
++	/* MCTP */
++	struct net_device *ndev;
++
++	struct work_struct work;
++};
++
++#endif
 diff --git a/drivers/soc/aspeed/aspeed-socinfo.c b/drivers/soc/aspeed/aspeed-socinfo.c
 index 3f759121d..7ee7f2911 100644
 --- a/drivers/soc/aspeed/aspeed-socinfo.c
@@ -6742,289 +7668,6 @@
  	}
  
  	return "??";
-diff --git a/drivers/soc/aspeed/aspeed-ssp.c b/drivers/soc/aspeed/aspeed-ssp.c
-new file mode 100644
-index 000000000..359b3ae85
---- /dev/null
-+++ b/drivers/soc/aspeed/aspeed-ssp.c
-@@ -0,0 +1,277 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+// Copyright (C) ASPEED Technology Inc.
-+
-+#include <linux/io.h>
-+#include <linux/fs.h>
-+#include <linux/mod_devicetable.h>
-+#include <linux/module.h>
-+#include <linux/miscdevice.h>
-+#include <linux/delay.h>
-+#include <linux/init.h>
-+#include <linux/firmware.h>
-+#include <linux/platform_device.h>
-+#include <linux/interrupt.h>
-+#include <linux/of.h>
-+#include <linux/of_reserved_mem.h>
-+#include <linux/of_address.h>
-+#include <linux/of_irq.h>
-+#include <linux/mfd/syscon.h>
-+#include <linux/regmap.h>
-+#include <linux/dma-direct.h>
-+
-+#define SSP_FILE_NAME			"ast2600_ssp.bin"
-+#define AST2600_CVIC_TRIGGER		0x28
-+#define AST2600_CVIC_PENDING_STATUS	0x18
-+#define AST2600_CVIC_PENDING_CLEAR	0x1C
-+
-+#define SSP_CTRL_REG			0xa00
-+#define SSP_CTRL_RESET_ASSERT		BIT(1)
-+#define SSP_CTRL_EN			BIT(0)
-+
-+#define SSP_MEM_BASE_REG		0xa04
-+#define SSP_IMEM_LIMIT_REG		0xa08
-+#define SSP_DMEM_LIMIT_REG		0xa0c
-+#define SSP_CACHE_RANGE_REG		0xa40
-+#define SSP_CACHE_INVALID_REG		0xa44
-+#define SSP_CACHE_CTRL_REG		0xa48
-+#define SSP_CACHE_CLEAR_ICACHE		BIT(2)
-+#define SSP_CACHE_CLEAR_DCACHE		BIT(1)
-+#define SSP_CACHE_EN			BIT(0)
-+
-+#define SSP_TOTAL_MEM_SZ		(32 * 1024 * 1024)
-+#define SSP_CACHED_MEM_SZ		(16 * 1024 * 1024)
-+#define SSP_UNCACHED_MEM_SZ		(SSP_TOTAL_MEM_SZ - SSP_CACHED_MEM_SZ)
-+#define SSP_CACHE_1ST_16MB_ENABLE	BIT(0)
-+
-+struct ast2600_ssp {
-+	struct device	*dev;
-+	struct regmap	*scu;
-+	dma_addr_t	ssp_mem_phy_addr;
-+	void __iomem	*ssp_mem_vir_addr;
-+	dma_addr_t	ssp_shared_mem_phy_addr;
-+	void __iomem	*ssp_shared_mem_vir_addr;
-+	int		ssp_shared_mem_size;
-+	void __iomem	*cvic;
-+	int		irq[16];
-+	int		n_irq;
-+};
-+
-+static int ast_ssp_open(struct inode *inode, struct file *file)
-+{
-+	return 0;
-+}
-+
-+static int ast_ssp_release(struct inode *inode, struct file *file)
-+{
-+	return 0;
-+}
-+
-+static const struct file_operations ast_ssp_fops = {
-+	.owner		= THIS_MODULE,
-+	.open		= ast_ssp_open,
-+	.release	= ast_ssp_release,
-+	.llseek		= no_llseek,
-+};
-+
-+struct miscdevice ast_ssp_misc = {
-+	.minor = MISC_DYNAMIC_MINOR,
-+	.name = "ast-ssp",
-+	.fops = &ast_ssp_fops,
-+};
-+
-+static irqreturn_t ast2600_ssp_interrupt(int irq, void *dev_id)
-+{
-+	u32 i;
-+	struct ast2600_ssp *priv = dev_id;
-+	u32 isr = readl(priv->cvic + AST2600_CVIC_PENDING_STATUS);
-+	u32 ssp_shared_rx_tx_size = priv->ssp_shared_mem_size / 2;
-+	u32 *ssp_shared_mem_tx = priv->ssp_shared_mem_vir_addr;
-+	u32 *ssp_shared_mem_rx = priv->ssp_shared_mem_vir_addr + ssp_shared_rx_tx_size;
-+
-+	dev_info(priv->dev, "isr %x\n", isr);
-+	writel(isr, priv->cvic + AST2600_CVIC_PENDING_CLEAR);
-+
-+	dev_info(priv->dev, "[CA7] rx addr:%08x, tx addr:%08x\n",
-+		 (u32)ssp_shared_mem_rx, (u32)ssp_shared_mem_tx);
-+
-+	/* Check the CA7 RX data from CM3 TX data. */
-+	dev_info(priv->dev, "CA7 RX data from CM3 TX data: ");
-+	for (i = 0; i < ssp_shared_rx_tx_size / 4; i++) {
-+		if (readl(ssp_shared_mem_rx + i) != 0) {
-+			dev_info(priv->dev, "[%08x] %08x ",
-+				 (u32)(ssp_shared_mem_rx + i), readl(ssp_shared_mem_rx + i));
-+		} else {
-+			break;
-+		}
-+	}
-+
-+	return IRQ_HANDLED;
-+}
-+
-+static int ast_ssp_probe(struct platform_device *pdev)
-+{
-+	struct device_node *np, *mnode = dev_of_node(&pdev->dev);
-+	const struct firmware *firmware;
-+	struct ast2600_ssp *priv;
-+	struct reserved_mem *rmem;
-+	int i, ret;
-+
-+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-+	if (!priv) {
-+		ret = -ENOMEM;
-+		goto finish;
-+	}
-+
-+	priv->dev = &pdev->dev;
-+	priv->scu = syscon_regmap_lookup_by_phandle(priv->dev->of_node, "aspeed,scu");
-+	if (IS_ERR(priv->scu)) {
-+		dev_err(priv->dev, "failed to find SCU regmap\n");
-+		ret = -EINVAL;
-+		goto finish;
-+	}
-+	platform_set_drvdata(pdev, priv);
-+
-+	ret = misc_register(&ast_ssp_misc);
-+	if (ret) {
-+		pr_err("can't misc_register :(\n");
-+		ret = -EIO;
-+		goto finish;
-+	}
-+	dev_set_drvdata(ast_ssp_misc.this_device, pdev);
-+
-+	ret = of_reserved_mem_device_init(&pdev->dev);
-+	if (ret) {
-+		dev_err(priv->dev,
-+			"failed to initialize reserved mem: %d\n", ret);
-+		ret = -ENOMEM;
-+		goto finish;
-+	}
-+
-+	np = of_parse_phandle(priv->dev->of_node, "memory-region", 0);
-+	if (!np) {
-+		dev_err(priv->dev, "can't find memory-region node\n");
-+		ret = -ENOMEM;
-+		goto finish;
-+	}
-+
-+	rmem = of_reserved_mem_lookup(np);
-+	of_node_put(np);
-+	if (!rmem) {
-+		dev_err(priv->dev, "can't find reserved memory.\n");
-+		ret = -ENOMEM;
-+		goto finish;
-+	} else {
-+		priv->ssp_mem_phy_addr = rmem->base;
-+		priv->ssp_mem_vir_addr = devm_ioremap(priv->dev, priv->ssp_mem_phy_addr, SSP_TOTAL_MEM_SZ);
-+		if (!priv->ssp_mem_vir_addr) {
-+			dev_err(priv->dev, "can't create reserved memory.\n");
-+			ret = -ENOMEM;
-+			goto finish;
-+		} else {
-+			dev_info(priv->dev, "\nSSP memory: virt(0x%08x), phys(0x%08x)\n",
-+				 (uint32_t)priv->ssp_mem_vir_addr, priv->ssp_mem_phy_addr);
-+		}
-+	}
-+
-+	if (of_property_read_u32(np, "shm-size", &priv->ssp_shared_mem_size)) {
-+		dev_err(priv->dev, "can't find shm-size property\n");
-+		ret = -ENOMEM;
-+		goto finish;
-+	}
-+
-+	priv->ssp_shared_mem_vir_addr = priv->ssp_mem_vir_addr + SSP_TOTAL_MEM_SZ
-+				    - priv->ssp_shared_mem_size;
-+	priv->ssp_shared_mem_phy_addr = priv->ssp_mem_phy_addr + SSP_TOTAL_MEM_SZ
-+					- priv->ssp_shared_mem_size;
-+	dev_info(priv->dev, "\nSSP shared memory: virt(0x%08x), phys(0x%08x), size(0x%08x)\n",
-+		 (uint32_t)priv->ssp_shared_mem_vir_addr, priv->ssp_shared_mem_phy_addr,
-+		 priv->ssp_shared_mem_size);
-+
-+	if (request_firmware(&firmware, SSP_FILE_NAME, priv->dev) < 0) {
-+		dev_err(priv->dev, "don't have %s\n", SSP_FILE_NAME);
-+		release_firmware(firmware);
-+		ret = -EINVAL;
-+		goto finish;
-+	}
-+
-+	memcpy(priv->ssp_mem_vir_addr, (void *)firmware->data, firmware->size);
-+	release_firmware(firmware);
-+
-+	np = of_parse_phandle(mnode, "aspeed,cvic", 0);
-+	if (!np) {
-+		dev_err(priv->dev, "can't find CVIC\n");
-+		ret = -EINVAL;
-+		goto finish;
-+	}
-+
-+	priv->cvic = devm_of_iomap(priv->dev, np, 0, NULL);
-+	if (IS_ERR(priv->cvic)) {
-+		dev_err(priv->dev, "can't map CVIC\n");
-+		ret = -EINVAL;
-+		goto finish;
-+	}
-+
-+	i = 0;
-+	while (0 != (priv->irq[i] = irq_of_parse_and_map(mnode, i))) {
-+		ret = request_irq(priv->irq[i], ast2600_ssp_interrupt, 0,
-+				  "ssp-sw-irq", priv);
-+		i++;
-+	}
-+	priv->n_irq = i;
-+	dev_info(priv->dev, "%d ISRs registered\n", priv->n_irq);
-+
-+	regmap_write(priv->scu, SSP_CTRL_REG, 0);
-+	mdelay(1);
-+	regmap_write(priv->scu, SSP_MEM_BASE_REG, priv->ssp_mem_phy_addr);
-+	regmap_write(priv->scu, SSP_IMEM_LIMIT_REG, priv->ssp_mem_phy_addr + SSP_CACHED_MEM_SZ);
-+	regmap_write(priv->scu, SSP_DMEM_LIMIT_REG, priv->ssp_mem_phy_addr + SSP_TOTAL_MEM_SZ);
-+
-+	regmap_write(priv->scu, SSP_CACHE_RANGE_REG, SSP_CACHE_1ST_16MB_ENABLE);
-+
-+	regmap_write(priv->scu, SSP_CTRL_REG, SSP_CTRL_RESET_ASSERT);
-+	mdelay(1);
-+	regmap_write(priv->scu, SSP_CTRL_REG, 0);
-+	mdelay(1);
-+	regmap_write(priv->scu, SSP_CTRL_REG, SSP_CTRL_EN);
-+
-+	dev_info(priv->dev, "Init successful\n");
-+	ret = 0;
-+finish:
-+	return ret;
-+}
-+
-+static int ast_ssp_remove(struct platform_device *pdev)
-+{
-+	struct ast2600_ssp *priv = platform_get_drvdata(pdev);
-+	int i;
-+
-+	dev_info(priv->dev, "SSP module removed\n");
-+	regmap_write(priv->scu, SSP_CTRL_REG, 0);
-+	for (i = 0; i < priv->n_irq; i++)
-+		free_irq(priv->irq[i], priv);
-+
-+	kfree(priv);
-+
-+	misc_deregister((struct miscdevice *)&ast_ssp_misc);
-+
-+	return 0;
-+}
-+
-+static const struct of_device_id of_ast_ssp_match_table[] = {
-+	{ .compatible = "aspeed,ast2600-ssp", },
-+	{},
-+};
-+MODULE_DEVICE_TABLE(of, of_ast_ssp_match_table);
-+
-+static struct platform_driver ast_ssp_driver = {
-+	.probe		= ast_ssp_probe,
-+	.remove		= ast_ssp_remove,
-+	.driver		= {
-+		.name	= KBUILD_MODNAME,
-+		.of_match_table = of_ast_ssp_match_table,
-+	},
-+};
-+
-+module_platform_driver(ast_ssp_driver);
-+
-+MODULE_LICENSE("Dual BSD/GPL");
 diff --git a/drivers/soc/aspeed/aspeed-uart-routing.c b/drivers/soc/aspeed/aspeed-uart-routing.c
 index 3a4c1f28c..5453a7bf3 100644
 --- a/drivers/soc/aspeed/aspeed-uart-routing.c
@@ -7514,7 +8157,7 @@
  
  module_platform_driver(aspeed_uart_routing_driver);
 diff --git a/drivers/soc/aspeed/aspeed-usb-hp.c b/drivers/soc/aspeed/aspeed-usb-hp.c
-new file mode 100644
+new file mode 100755
 index 000000000..756e3b331
 --- /dev/null
 +++ b/drivers/soc/aspeed/aspeed-usb-hp.c
@@ -7673,7 +8316,7 @@
 +MODULE_LICENSE("GPL");
 +MODULE_AUTHOR("Neal Liu <neal_liu@aspeedtech.com>");
 diff --git a/drivers/soc/aspeed/aspeed-usb-phy.c b/drivers/soc/aspeed/aspeed-usb-phy.c
-new file mode 100644
+new file mode 100755
 index 000000000..7aa7b484b
 --- /dev/null
 +++ b/drivers/soc/aspeed/aspeed-usb-phy.c
@@ -7792,7 +8435,7 @@
 +MODULE_LICENSE("GPL");
 +MODULE_AUTHOR("Neal Liu <neal_liu@aspeedtech.com>");
 diff --git a/drivers/soc/aspeed/aspeed-xdma.c b/drivers/soc/aspeed/aspeed-xdma.c
-new file mode 100644
+new file mode 100755
 index 000000000..6ad6d7250
 --- /dev/null
 +++ b/drivers/soc/aspeed/aspeed-xdma.c
@@ -9233,5125 +9876,12 @@
 +MODULE_AUTHOR("Eddie James");
 +MODULE_DESCRIPTION("ASPEED XDMA Engine Driver");
 +MODULE_LICENSE("GPL v2");
-diff --git a/drivers/soc/aspeed/ast2500-espi.c b/drivers/soc/aspeed/ast2500-espi.c
-new file mode 100644
-index 000000000..a9de566f7
---- /dev/null
-+++ b/drivers/soc/aspeed/ast2500-espi.c
-@@ -0,0 +1,1739 @@
-+// SPDX-License-Identifier: GPL-2.0+
-+/*
-+ * Copyright 2023 Aspeed Technology Inc.
-+ */
-+#include <linux/io.h>
-+#include <linux/irq.h>
-+#include <linux/clk.h>
-+#include <linux/sizes.h>
-+#include <linux/module.h>
-+#include <linux/bitfield.h>
-+#include <linux/of_device.h>
-+#include <linux/interrupt.h>
-+#include <linux/platform_device.h>
-+#include <linux/miscdevice.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/uaccess.h>
-+#include <linux/vmalloc.h>
-+#include <linux/poll.h>
-+#include <linux/delay.h>
-+
-+#include "ast2500-espi.h"
-+
-+#define DEVICE_NAME		"aspeed-espi"
-+
-+#define PERIF_MCYC_UNLOCK	0xfedc756e
-+#define PERIF_MCYC_ALIGN	SZ_64K
-+
-+#define FLASH_SAFS_ALIGN	SZ_16M
-+
-+struct ast2500_espi_perif {
-+	struct {
-+		bool enable;
-+		void *virt;
-+		dma_addr_t taddr;
-+		uint32_t saddr;
-+		uint32_t size;
-+	} mcyc;
-+
-+	struct {
-+		bool enable;
-+		void *np_tx_virt;
-+		dma_addr_t np_tx_addr;
-+		void *pc_tx_virt;
-+		dma_addr_t pc_tx_addr;
-+		void *pc_rx_virt;
-+		dma_addr_t pc_rx_addr;
-+	} dma;
-+
-+	bool rx_ready;
-+	wait_queue_head_t wq;
-+
-+	spinlock_t lock;
-+	struct mutex np_tx_mtx;
-+	struct mutex pc_tx_mtx;
-+	struct mutex pc_rx_mtx;
-+
-+	struct miscdevice mdev;
-+};
-+
-+struct ast2500_espi_vw {
-+	struct {
-+		bool hw_mode;
-+		uint32_t val;
-+	} gpio;
-+
-+	struct miscdevice mdev;
-+};
-+
-+struct ast2500_espi_oob {
-+	struct {
-+		bool enable;
-+		void *tx_virt;
-+		dma_addr_t tx_addr;
-+		void *rx_virt;
-+		dma_addr_t rx_addr;
-+	} dma;
-+
-+	bool rx_ready;
-+	wait_queue_head_t wq;
-+
-+	spinlock_t lock;
-+	struct mutex tx_mtx;
-+	struct mutex rx_mtx;
-+
-+	struct miscdevice mdev;
-+};
-+
-+struct ast2500_espi_flash {
-+	struct {
-+		uint32_t mode;
-+		phys_addr_t taddr;
-+		uint32_t size;
-+	} safs;
-+
-+	struct {
-+		bool enable;
-+		void *tx_virt;
-+		dma_addr_t tx_addr;
-+		void *rx_virt;
-+		dma_addr_t rx_addr;
-+	} dma;
-+
-+	bool rx_ready;
-+	wait_queue_head_t wq;
-+
-+	spinlock_t lock;
-+	struct mutex rx_mtx;
-+	struct mutex tx_mtx;
-+
-+	struct miscdevice mdev;
-+};
-+
-+struct ast2500_espi {
-+	struct device *dev;
-+	void __iomem *regs;
-+	struct clk *clk;
-+	int irq;
-+
-+	struct ast2500_espi_perif perif;
-+	struct ast2500_espi_vw vw;
-+	struct ast2500_espi_oob oob;
-+	struct ast2500_espi_flash flash;
-+};
-+
-+/* peripheral channel (CH0) */
-+static long ast2500_espi_perif_pc_get_rx(struct file *fp,
-+					 struct ast2500_espi_perif *perif,
-+					 struct aspeed_espi_ioc *ioc)
-+{
-+	uint32_t reg, cyc, tag, len;
-+	struct ast2500_espi *espi;
-+	struct espi_comm_hdr *hdr;
-+	unsigned long flags;
-+	uint32_t pkt_len;
-+	uint8_t *pkt;
-+	int i, rc;
-+
-+	espi = container_of(perif, struct ast2500_espi, perif);
-+
-+	if (fp->f_flags & O_NONBLOCK) {
-+		if (!mutex_trylock(&perif->pc_rx_mtx))
-+			return -EAGAIN;
-+
-+		if (!perif->rx_ready) {
-+			rc = -ENODATA;
-+			goto unlock_mtx_n_out;
-+		}
-+	} else {
-+		mutex_lock(&perif->pc_rx_mtx);
-+
-+		if (!perif->rx_ready) {
-+			rc = wait_event_interruptible(perif->wq, perif->rx_ready);
-+			if (rc == -ERESTARTSYS) {
-+				rc = -EINTR;
-+				goto unlock_mtx_n_out;
-+			}
-+		}
-+	}
-+
-+	/*
-+	 * common header (i.e. cycle type, tag, and length)
-+	 * part is written to HW registers
-+	 */
-+	reg = readl(espi->regs + ESPI_PERIF_PC_RX_CTRL);
-+	cyc = FIELD_GET(ESPI_PERIF_PC_RX_CTRL_CYC, reg);
-+	tag = FIELD_GET(ESPI_PERIF_PC_RX_CTRL_TAG, reg);
-+	len = FIELD_GET(ESPI_PERIF_PC_RX_CTRL_LEN, reg);
-+
-+	/*
-+	 * calculate the length of the rest part of the
-+	 * eSPI packet to be read from HW and copied to
-+	 * user space.
-+	 */
-+	switch (cyc) {
-+	case ESPI_PERIF_MSG:
-+		pkt_len = sizeof(struct espi_perif_msg);
-+		break;
-+	case ESPI_PERIF_MSG_D:
-+		pkt_len = ((len) ? len : ESPI_MAX_PLD_LEN) +
-+			  sizeof(struct espi_perif_msg);
-+		break;
-+	case ESPI_PERIF_SUC_CMPLT_D_MIDDLE:
-+	case ESPI_PERIF_SUC_CMPLT_D_FIRST:
-+	case ESPI_PERIF_SUC_CMPLT_D_LAST:
-+	case ESPI_PERIF_SUC_CMPLT_D_ONLY:
-+		pkt_len = ((len) ? len : ESPI_MAX_PLD_LEN) +
-+			  sizeof(struct espi_perif_cmplt);
-+		break;
-+	case ESPI_PERIF_SUC_CMPLT:
-+	case ESPI_PERIF_UNSUC_CMPLT:
-+		pkt_len = sizeof(struct espi_perif_cmplt);
-+		break;
-+	default:
-+		rc = -EFAULT;
-+		goto unlock_mtx_n_out;
-+	}
-+
-+	if (ioc->pkt_len < pkt_len) {
-+		rc = -EINVAL;
-+		goto unlock_mtx_n_out;
-+	}
-+
-+	pkt = vmalloc(pkt_len);
-+	if (!pkt) {
-+		rc = -ENOMEM;
-+		goto unlock_mtx_n_out;
-+	}
-+
-+	hdr = (struct espi_comm_hdr *)pkt;
-+	hdr->cyc = cyc;
-+	hdr->tag = tag;
-+	hdr->len_h = len >> 8;
-+	hdr->len_l = len & 0xff;
-+
-+	if (perif->dma.enable) {
-+		memcpy(hdr + 1, perif->dma.pc_rx_virt, pkt_len - sizeof(*hdr));
-+	} else {
-+		for (i = sizeof(*hdr); i < pkt_len; ++i)
-+			reg = readl(espi->regs + ESPI_PERIF_PC_RX_DATA) & 0xff;
-+	}
-+
-+	if (copy_to_user((void __user *)ioc->pkt, pkt, pkt_len)) {
-+		rc = -EFAULT;
-+		goto free_n_out;
-+	}
-+
-+	spin_lock_irqsave(&perif->lock, flags);
-+
-+	writel(ESPI_PERIF_PC_RX_CTRL_SERV_PEND, espi->regs + ESPI_PERIF_PC_RX_CTRL);
-+	perif->rx_ready = 0;
-+
-+	spin_unlock_irqrestore(&perif->lock, flags);
-+
-+	rc = 0;
-+
-+free_n_out:
-+	vfree(pkt);
-+
-+unlock_mtx_n_out:
-+	mutex_unlock(&perif->pc_rx_mtx);
-+
-+	return rc;
-+}
-+
-+static long ast2500_espi_perif_pc_put_tx(struct file *fp,
-+					 struct ast2500_espi_perif *perif,
-+					 struct aspeed_espi_ioc *ioc)
-+{
-+	uint32_t reg, cyc, tag, len;
-+	struct ast2500_espi *espi;
-+	struct espi_comm_hdr *hdr;
-+	uint8_t *pkt;
-+	int i, rc;
-+
-+	espi = container_of(perif, struct ast2500_espi, perif);
-+
-+	if (!mutex_trylock(&perif->pc_tx_mtx))
-+		return -EAGAIN;
-+
-+	reg = readl(espi->regs + ESPI_PERIF_PC_TX_CTRL);
-+	if (reg & ESPI_PERIF_PC_TX_CTRL_TRIG_PEND) {
-+		rc = -EBUSY;
-+		goto unlock_n_out;
-+	}
-+
-+	pkt = vmalloc(ioc->pkt_len);
-+	if (!pkt) {
-+		rc = -ENOMEM;
-+		goto unlock_n_out;
-+	}
-+
-+	hdr = (struct espi_comm_hdr *)pkt;
-+
-+	if (copy_from_user(pkt, (void __user *)ioc->pkt, ioc->pkt_len)) {
-+		rc = -EFAULT;
-+		goto free_n_out;
-+	}
-+
-+	/*
-+	 * common header (i.e. cycle type, tag, and length)
-+	 * part is written to HW registers
-+	 */
-+	if (perif->dma.enable) {
-+		memcpy(perif->dma.pc_tx_virt, hdr + 1, ioc->pkt_len - sizeof(*hdr));
-+		dma_wmb();
-+	} else {
-+		for (i = sizeof(*hdr); i < ioc->pkt_len; ++i)
-+			writel(pkt[i], espi->regs + ESPI_PERIF_PC_TX_DATA);
-+	}
-+
-+	cyc = hdr->cyc;
-+	tag = hdr->tag;
-+	len = (hdr->len_h << 8) | (hdr->len_l & 0xff);
-+
-+	reg = FIELD_PREP(ESPI_PERIF_PC_TX_CTRL_CYC, cyc)
-+	      | FIELD_PREP(ESPI_PERIF_PC_TX_CTRL_TAG, tag)
-+	      | FIELD_PREP(ESPI_PERIF_PC_TX_CTRL_LEN, len)
-+	      | ESPI_PERIF_PC_TX_CTRL_TRIG_PEND;
-+	writel(reg, espi->regs + ESPI_PERIF_PC_TX_CTRL);
-+
-+	rc = 0;
-+
-+free_n_out:
-+	vfree(pkt);
-+
-+unlock_n_out:
-+	mutex_unlock(&perif->pc_tx_mtx);
-+
-+	return rc;
-+}
-+
-+static long ast2500_espi_perif_np_put_tx(struct file *fp,
-+					 struct ast2500_espi_perif *perif,
-+					 struct aspeed_espi_ioc *ioc)
-+{
-+	uint32_t reg, cyc, tag, len;
-+	struct ast2500_espi *espi;
-+	struct espi_comm_hdr *hdr;
-+	uint8_t *pkt;
-+	int i, rc;
-+
-+	espi = container_of(perif, struct ast2500_espi, perif);
-+
-+	if (!mutex_trylock(&perif->np_tx_mtx))
-+		return -EAGAIN;
-+
-+	reg = readl(espi->regs + ESPI_PERIF_NP_TX_CTRL);
-+	if (reg & ESPI_PERIF_NP_TX_CTRL_TRIG_PEND) {
-+		rc = -EBUSY;
-+		goto unlock_n_out;
-+	}
-+
-+	pkt = vmalloc(ioc->pkt_len);
-+	if (!pkt) {
-+		rc = -ENOMEM;
-+		goto unlock_n_out;
-+	}
-+
-+	hdr = (struct espi_comm_hdr *)pkt;
-+
-+	if (copy_from_user(pkt, (void __user *)ioc->pkt, ioc->pkt_len)) {
-+		rc = -EFAULT;
-+		goto free_n_out;
-+	}
-+
-+	/*
-+	 * common header (i.e. cycle type, tag, and length)
-+	 * part is written to HW registers
-+	 */
-+	if (perif->dma.enable) {
-+		memcpy(perif->dma.np_tx_virt, hdr + 1, ioc->pkt_len - sizeof(*hdr));
-+		dma_wmb();
-+	} else {
-+		for (i = sizeof(*hdr); i < ioc->pkt_len; ++i)
-+			writel(pkt[i], espi->regs + ESPI_PERIF_NP_TX_DATA);
-+	}
-+
-+	cyc = hdr->cyc;
-+	tag = hdr->tag;
-+	len = (hdr->len_h << 8) | (hdr->len_l & 0xff);
-+
-+	reg = FIELD_PREP(ESPI_PERIF_NP_TX_CTRL_CYC, cyc)
-+	      | FIELD_PREP(ESPI_PERIF_NP_TX_CTRL_TAG, tag)
-+	      | FIELD_PREP(ESPI_PERIF_NP_TX_CTRL_LEN, len)
-+	      | ESPI_PERIF_NP_TX_CTRL_TRIG_PEND;
-+	writel(reg, espi->regs + ESPI_PERIF_NP_TX_CTRL);
-+
-+	rc = 0;
-+
-+free_n_out:
-+	vfree(pkt);
-+
-+unlock_n_out:
-+	mutex_unlock(&perif->np_tx_mtx);
-+
-+	return rc;
-+}
-+
-+static long ast2500_espi_perif_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
-+{
-+	struct ast2500_espi_perif *perif;
-+	struct aspeed_espi_ioc ioc;
-+
-+	perif = container_of(fp->private_data, struct ast2500_espi_perif, mdev);
-+
-+	if (copy_from_user(&ioc, (void __user *)arg, sizeof(ioc)))
-+		return -EFAULT;
-+
-+	if (ioc.pkt_len > ESPI_MAX_PKT_LEN)
-+		return -EINVAL;
-+
-+	switch (cmd) {
-+	case ASPEED_ESPI_PERIF_PC_GET_RX:
-+		return ast2500_espi_perif_pc_get_rx(fp, perif, &ioc);
-+	case ASPEED_ESPI_PERIF_PC_PUT_TX:
-+		return ast2500_espi_perif_pc_put_tx(fp, perif, &ioc);
-+	case ASPEED_ESPI_PERIF_NP_PUT_TX:
-+		return ast2500_espi_perif_np_put_tx(fp, perif, &ioc);
-+	default:
-+		break;
-+	};
-+
-+	return -EINVAL;
-+}
-+
-+static int ast2500_espi_perif_mmap(struct file *fp, struct vm_area_struct *vma)
-+{
-+	struct ast2500_espi_perif *perif;
-+	unsigned long vm_size;
-+	pgprot_t vm_prot;
-+
-+	perif = container_of(fp->private_data, struct ast2500_espi_perif, mdev);
-+	if (!perif->mcyc.enable)
-+		return -EPERM;
-+
-+	vm_size = vma->vm_end - vma->vm_start;
-+	vm_prot = vma->vm_page_prot;
-+
-+	if (((vma->vm_pgoff << PAGE_SHIFT) + vm_size) > perif->mcyc.size)
-+		return -EINVAL;
-+
-+	vm_prot = pgprot_noncached(vm_prot);
-+
-+	if (remap_pfn_range(vma, vma->vm_start,
-+			    (perif->mcyc.taddr >> PAGE_SHIFT) + vma->vm_pgoff,
-+			    vm_size, vm_prot))
-+		return -EAGAIN;
-+
-+	return 0;
-+}
-+
-+static const struct file_operations ast2500_espi_perif_fops = {
-+	.owner = THIS_MODULE,
-+	.mmap = ast2500_espi_perif_mmap,
-+	.unlocked_ioctl = ast2500_espi_perif_ioctl,
-+};
-+
-+static void ast2500_espi_perif_isr(struct ast2500_espi *espi)
-+{
-+	struct ast2500_espi_perif *perif;
-+	unsigned long flags;
-+	uint32_t sts;
-+
-+	perif = &espi->perif;
-+
-+	sts = readl(espi->regs + ESPI_INT_STS);
-+
-+	if (sts & ESPI_INT_STS_PERIF_PC_RX_CMPLT) {
-+		writel(ESPI_INT_STS_PERIF_PC_RX_CMPLT, espi->regs + ESPI_INT_STS);
-+
-+		spin_lock_irqsave(&perif->lock, flags);
-+		perif->rx_ready = true;
-+		spin_unlock_irqrestore(&perif->lock, flags);
-+
-+		wake_up_interruptible(&perif->wq);
-+	}
-+}
-+
-+static void ast2500_espi_perif_reset(struct ast2500_espi *espi)
-+{
-+	struct ast2500_espi_perif *perif;
-+	struct device *dev;
-+	uint32_t reg, mask;
-+
-+	dev = espi->dev;
-+
-+	perif = &espi->perif;
-+
-+	reg = readl(espi->regs + ESPI_INT_EN);
-+	reg &= ~(ESPI_INT_EN_PERIF);
-+	writel(reg, espi->regs + ESPI_INT_EN);
-+	writel(ESPI_INT_STS_PERIF, espi->regs + ESPI_INT_STS);
-+
-+	reg = readl(espi->regs + ESPI_CTRL);
-+	reg &= ~(ESPI_CTRL_PERIF_NP_TX_SW_RST
-+		 | ESPI_CTRL_PERIF_NP_RX_SW_RST
-+		 | ESPI_CTRL_PERIF_PC_TX_SW_RST
-+		 | ESPI_CTRL_PERIF_PC_RX_SW_RST
-+		 | ESPI_CTRL_PERIF_NP_TX_DMA_EN
-+		 | ESPI_CTRL_PERIF_PC_TX_DMA_EN
-+		 | ESPI_CTRL_PERIF_PC_RX_DMA_EN
-+		 | ESPI_CTRL_PERIF_SW_RDY);
-+	writel(reg, espi->regs + ESPI_CTRL);
-+
-+	udelay(1);
-+
-+	reg |= (ESPI_CTRL_PERIF_NP_TX_SW_RST
-+		| ESPI_CTRL_PERIF_NP_RX_SW_RST
-+		| ESPI_CTRL_PERIF_PC_TX_SW_RST
-+		| ESPI_CTRL_PERIF_PC_RX_SW_RST);
-+	writel(reg, espi->regs + ESPI_CTRL);
-+
-+	if (perif->mcyc.enable) {
-+		mask = ~(perif->mcyc.size - 1);
-+		writel(PERIF_MCYC_UNLOCK, espi->regs + ESPI_PERIF_MCYC_MASK);
-+		writel(mask, espi->regs + ESPI_PERIF_MCYC_MASK);
-+
-+		writel(perif->mcyc.saddr, espi->regs + ESPI_PERIF_MCYC_SADDR);
-+		writel(perif->mcyc.taddr, espi->regs + ESPI_PERIF_MCYC_TADDR);
-+	}
-+
-+	if (perif->dma.enable) {
-+		writel(perif->dma.np_tx_addr, espi->regs + ESPI_PERIF_NP_TX_DMA);
-+		writel(perif->dma.pc_tx_addr, espi->regs + ESPI_PERIF_PC_TX_DMA);
-+		writel(perif->dma.pc_rx_addr, espi->regs + ESPI_PERIF_PC_RX_DMA);
-+
-+		reg = readl(espi->regs + ESPI_CTRL)
-+		      | ESPI_CTRL_PERIF_NP_TX_DMA_EN
-+		      | ESPI_CTRL_PERIF_PC_TX_DMA_EN
-+		      | ESPI_CTRL_PERIF_PC_RX_DMA_EN;
-+		writel(reg, espi->regs + ESPI_CTRL);
-+	}
-+
-+	reg = readl(espi->regs + ESPI_INT_EN) | ESPI_INT_EN_PERIF_PC_RX_CMPLT;
-+	writel(reg, espi->regs + ESPI_INT_EN);
-+
-+	reg = readl(espi->regs + ESPI_CTRL) | ESPI_CTRL_PERIF_SW_RDY;
-+	writel(reg, espi->regs + ESPI_CTRL);
-+}
-+
-+static int ast2500_espi_perif_probe(struct ast2500_espi *espi)
-+{
-+	struct ast2500_espi_perif *perif;
-+	struct device *dev;
-+	int rc;
-+
-+	dev = espi->dev;
-+
-+	perif = &espi->perif;
-+
-+	init_waitqueue_head(&perif->wq);
-+
-+	spin_lock_init(&perif->lock);
-+
-+	mutex_init(&perif->np_tx_mtx);
-+	mutex_init(&perif->pc_tx_mtx);
-+	mutex_init(&perif->pc_rx_mtx);
-+
-+	perif->mcyc.enable = of_property_read_bool(dev->of_node, "perif-mcyc-enable");
-+	if (perif->mcyc.enable) {
-+		rc = of_property_read_u32(dev->of_node, "perif-mcyc-src-addr", &perif->mcyc.saddr);
-+		if (rc || !IS_ALIGNED(perif->mcyc.saddr, PERIF_MCYC_ALIGN)) {
-+			dev_err(dev, "cannot get 64KB-aligned memory cycle host address\n");
-+			return -ENODEV;
-+		}
-+
-+		rc = of_property_read_u32(dev->of_node, "perif-mcyc-size", &perif->mcyc.size);
-+		if (rc || !IS_ALIGNED(perif->mcyc.size, PERIF_MCYC_ALIGN)) {
-+			dev_err(dev, "cannot get 64KB-aligned memory cycle size\n");
-+			return -EINVAL;
-+		}
-+
-+		perif->mcyc.virt = dmam_alloc_coherent(dev, perif->mcyc.size,
-+						       &perif->mcyc.taddr, GFP_KERNEL);
-+		if (!perif->mcyc.virt) {
-+			dev_err(dev, "cannot allocate memory cycle\n");
-+			return -ENOMEM;
-+		}
-+	}
-+
-+	perif->dma.enable = of_property_read_bool(dev->of_node, "perif-dma-mode");
-+	if (perif->dma.enable) {
-+		perif->dma.pc_tx_virt = dmam_alloc_coherent(dev, PAGE_SIZE,
-+							    &perif->dma.pc_tx_addr, GFP_KERNEL);
-+		if (!perif->dma.pc_tx_virt) {
-+			dev_err(dev, "cannot allocate posted TX DMA buffer\n");
-+			return -ENOMEM;
-+		}
-+
-+		perif->dma.pc_rx_virt = dmam_alloc_coherent(dev, PAGE_SIZE,
-+							    &perif->dma.pc_rx_addr, GFP_KERNEL);
-+		if (!perif->dma.pc_rx_virt) {
-+			dev_err(dev, "cannot allocate posted RX DMA buffer\n");
-+			return -ENOMEM;
-+		}
-+
-+		perif->dma.np_tx_virt = dmam_alloc_coherent(dev, PAGE_SIZE,
-+							    &perif->dma.np_tx_addr, GFP_KERNEL);
-+		if (!perif->dma.np_tx_virt) {
-+			dev_err(dev, "cannot allocate non-posted TX DMA buffer\n");
-+			return -ENOMEM;
-+		}
-+	}
-+
-+	perif->mdev.parent = dev;
-+	perif->mdev.minor = MISC_DYNAMIC_MINOR;
-+	perif->mdev.name = devm_kasprintf(dev, GFP_KERNEL, "%s-peripheral", DEVICE_NAME);
-+	perif->mdev.fops = &ast2500_espi_perif_fops;
-+	rc = misc_register(&perif->mdev);
-+	if (rc) {
-+		dev_err(dev, "cannot register device %s\n", perif->mdev.name);
-+		return rc;
-+	}
-+
-+	ast2500_espi_perif_reset(espi);
-+
-+	return 0;
-+}
-+
-+static int ast2500_espi_perif_remove(struct ast2500_espi *espi)
-+{
-+	struct ast2500_espi_perif *perif;
-+	struct device *dev;
-+	uint32_t reg;
-+
-+	dev = espi->dev;
-+
-+	perif = &espi->perif;
-+
-+	reg = readl(espi->regs + ESPI_INT_EN);
-+	reg &= ~(ESPI_INT_EN_PERIF);
-+	writel(reg, espi->regs + ESPI_INT_EN);
-+
-+	reg = readl(espi->regs + ESPI_CTRL);
-+	reg &= ~(ESPI_CTRL_PERIF_NP_TX_DMA_EN
-+		 | ESPI_CTRL_PERIF_PC_TX_DMA_EN
-+		 | ESPI_CTRL_PERIF_PC_RX_DMA_EN
-+		 | ESPI_CTRL_PERIF_SW_RDY);
-+	writel(reg, espi->regs + ESPI_CTRL);
-+
-+	if (perif->mcyc.enable)
-+		dmam_free_coherent(dev, perif->mcyc.size, perif->mcyc.virt,
-+				   perif->mcyc.taddr);
-+
-+	if (perif->dma.enable) {
-+		dmam_free_coherent(dev, PAGE_SIZE, perif->dma.np_tx_virt,
-+				   perif->dma.np_tx_addr);
-+		dmam_free_coherent(dev, PAGE_SIZE, perif->dma.pc_tx_virt,
-+				   perif->dma.pc_tx_addr);
-+		dmam_free_coherent(dev, PAGE_SIZE, perif->dma.pc_rx_virt,
-+				   perif->dma.pc_rx_addr);
-+	}
-+
-+	mutex_destroy(&perif->np_tx_mtx);
-+	mutex_destroy(&perif->pc_tx_mtx);
-+	mutex_destroy(&perif->pc_rx_mtx);
-+
-+	misc_deregister(&perif->mdev);
-+
-+	return 0;
-+}
-+
-+/* virtual wire channel (CH1) */
-+static long ast2500_espi_vw_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
-+{
-+	struct ast2500_espi_vw *vw;
-+	struct ast2500_espi *espi;
-+	uint32_t gpio;
-+
-+	vw = container_of(fp->private_data, struct ast2500_espi_vw, mdev);
-+	espi = container_of(vw, struct ast2500_espi, vw);
-+	gpio = vw->gpio.val;
-+
-+	switch (cmd) {
-+	case ASPEED_ESPI_VW_GET_GPIO_VAL:
-+		if (put_user(gpio, (uint32_t __user *)arg))
-+			return -EFAULT;
-+		break;
-+	case ASPEED_ESPI_VW_PUT_GPIO_VAL:
-+		if (get_user(gpio, (uint32_t __user *)arg))
-+			return -EFAULT;
-+
-+		writel(gpio, espi->regs + ESPI_VW_GPIO_VAL);
-+		break;
-+	default:
-+		return -EINVAL;
-+	};
-+
-+	return 0;
-+}
-+
-+static const struct file_operations ast2500_espi_vw_fops = {
-+	.owner = THIS_MODULE,
-+	.unlocked_ioctl = ast2500_espi_vw_ioctl,
-+};
-+
-+static void ast2500_espi_vw_isr(struct ast2500_espi *espi)
-+{
-+	struct ast2500_espi_vw *vw;
-+	uint32_t reg, sts, sts_sysevt;
-+
-+	vw = &espi->vw;
-+
-+	sts = readl(espi->regs + ESPI_INT_STS);
-+
-+	if (sts & ESPI_INT_STS_VW_SYSEVT) {
-+		sts_sysevt = readl(espi->regs + ESPI_VW_SYSEVT_INT_STS);
-+
-+		if (sts_sysevt & ESPI_VW_SYSEVT_INT_STS_HOST_RST_WARN) {
-+			reg = readl(espi->regs + ESPI_VW_SYSEVT) | ESPI_VW_SYSEVT_HOST_RST_ACK;
-+			writel(reg, espi->regs + ESPI_VW_SYSEVT);
-+			writel(ESPI_VW_SYSEVT_INT_STS_HOST_RST_WARN, espi->regs + ESPI_VW_SYSEVT_INT_STS);
-+		}
-+
-+		if (sts_sysevt & ESPI_VW_SYSEVT_INT_STS_OOB_RST_WARN) {
-+			reg = readl(espi->regs + ESPI_VW_SYSEVT) | ESPI_VW_SYSEVT_OOB_RST_ACK;
-+			writel(reg, espi->regs + ESPI_VW_SYSEVT);
-+			writel(ESPI_VW_SYSEVT_INT_STS_OOB_RST_WARN, espi->regs + ESPI_VW_SYSEVT_INT_STS);
-+		}
-+
-+		writel(ESPI_INT_STS_VW_SYSEVT, espi->regs + ESPI_INT_STS);
-+	}
-+
-+	if (sts & ESPI_INT_STS_VW_SYSEVT1) {
-+		sts_sysevt = readl(espi->regs + ESPI_VW_SYSEVT1_INT_STS);
-+
-+		if (sts_sysevt & ESPI_VW_SYSEVT1_INT_STS_SUSPEND_WARN) {
-+			reg = readl(espi->regs + ESPI_VW_SYSEVT1) | ESPI_VW_SYSEVT1_SUSPEND_ACK;
-+			writel(reg, espi->regs + ESPI_VW_SYSEVT1);
-+			writel(ESPI_VW_SYSEVT1_INT_STS_SUSPEND_WARN, espi->regs + ESPI_VW_SYSEVT1_INT_STS);
-+		}
-+
-+		writel(ESPI_INT_STS_VW_SYSEVT1, espi->regs + ESPI_INT_STS);
-+	}
-+
-+	if (sts & ESPI_INT_STS_VW_GPIO) {
-+		vw->gpio.val = readl(espi->regs + ESPI_VW_GPIO_VAL);
-+		writel(ESPI_INT_STS_VW_GPIO, espi->regs + ESPI_INT_STS);
-+	}
-+}
-+
-+static void ast2500_espi_vw_reset(struct ast2500_espi *espi)
-+{
-+	uint32_t reg;
-+	struct ast2500_espi_vw *vw = &espi->vw;
-+
-+	reg = readl(espi->regs + ESPI_INT_EN);
-+	reg &= ~(ESPI_INT_EN_VW);
-+	writel(reg, espi->regs + ESPI_INT_EN);
-+	writel(ESPI_INT_STS_VW, espi->regs + ESPI_INT_STS);
-+
-+	vw->gpio.val = readl(espi->regs + ESPI_VW_GPIO_VAL);
-+
-+	/* Host Reset Warn and OOB Reset Warn system events */
-+	reg = readl(espi->regs + ESPI_VW_SYSEVT_INT_T2)
-+	      | ESPI_VW_SYSEVT_INT_T2_HOST_RST_WARN
-+	      | ESPI_VW_SYSEVT_INT_T2_OOB_RST_WARN;
-+	writel(reg, espi->regs + ESPI_VW_SYSEVT_INT_T2);
-+
-+	reg = readl(espi->regs + ESPI_VW_SYSEVT_INT_EN)
-+	      | ESPI_VW_SYSEVT_INT_EN_HOST_RST_WARN
-+	      | ESPI_VW_SYSEVT_INT_EN_OOB_RST_WARN;
-+	writel(reg, espi->regs + ESPI_VW_SYSEVT_INT_EN);
-+
-+	/* Suspend Warn system event */
-+	reg = readl(espi->regs + ESPI_VW_SYSEVT1_INT_T0) | ESPI_VW_SYSEVT1_INT_T0_SUSPEND_WARN;
-+	writel(reg, espi->regs + ESPI_VW_SYSEVT1_INT_T0);
-+
-+	reg = readl(espi->regs + ESPI_VW_SYSEVT1_INT_EN) | ESPI_VW_SYSEVT1_INT_EN_SUSPEND_WARN;
-+	writel(reg, espi->regs + ESPI_VW_SYSEVT1_INT_EN);
-+
-+	reg = readl(espi->regs + ESPI_INT_EN)
-+	      | ESPI_INT_EN_VW_GPIO
-+	      | ESPI_INT_EN_VW_SYSEVT
-+	      | ESPI_INT_EN_VW_SYSEVT1;
-+	writel(reg, espi->regs + ESPI_INT_EN);
-+
-+	reg = readl(espi->regs + ESPI_VW_SYSEVT)
-+	      | ESPI_VW_SYSEVT_SLV_BOOT_STS
-+	      | ESPI_VW_SYSEVT_SLV_BOOT_DONE;
-+	writel(reg, espi->regs + ESPI_VW_SYSEVT);
-+
-+	reg = readl(espi->regs + ESPI_CTRL)
-+	      | ((vw->gpio.hw_mode) ? 0 : ESPI_CTRL_VW_GPIO_SW)
-+	      | ESPI_CTRL_VW_SW_RDY;
-+	writel(reg, espi->regs + ESPI_CTRL);
-+}
-+
-+static int ast2500_espi_vw_probe(struct ast2500_espi *espi)
-+{
-+	int rc;
-+	struct device *dev = espi->dev;
-+	struct ast2500_espi_vw *vw = &espi->vw;
-+
-+	writel(0x0, espi->regs + ESPI_VW_SYSEVT_INT_EN);
-+	writel(0xffffffff, espi->regs + ESPI_VW_SYSEVT_INT_STS);
-+
-+	writel(0x0, espi->regs + ESPI_VW_SYSEVT1_INT_EN);
-+	writel(0xffffffff, espi->regs + ESPI_VW_SYSEVT1_INT_STS);
-+
-+	vw->gpio.hw_mode = of_property_read_bool(dev->of_node, "vw-gpio-hw-mode");
-+
-+	vw->mdev.parent = dev;
-+	vw->mdev.minor = MISC_DYNAMIC_MINOR;
-+	vw->mdev.name = devm_kasprintf(dev, GFP_KERNEL, "%s-vw", DEVICE_NAME);
-+	vw->mdev.fops = &ast2500_espi_vw_fops;
-+	rc = misc_register(&vw->mdev);
-+	if (rc) {
-+		dev_err(dev, "cannot register device %s\n", vw->mdev.name);
-+		return rc;
-+	}
-+
-+	ast2500_espi_vw_reset(espi);
-+
-+	return 0;
-+}
-+
-+static int ast2500_espi_vw_remove(struct ast2500_espi *espi)
-+{
-+	struct ast2500_espi_vw *vw;
-+	uint32_t reg;
-+
-+	vw = &espi->vw;
-+
-+	reg = readl(espi->regs + ESPI_INT_EN);
-+	reg &= ~(ESPI_INT_EN_VW);
-+	writel(reg, espi->regs + ESPI_INT_EN);
-+
-+	misc_deregister(&vw->mdev);
-+
-+	return 0;
-+}
-+
-+/* out-of-band channel (CH2) */
-+static long ast2500_espi_oob_get_rx(struct file *fp,
-+				    struct ast2500_espi_oob *oob,
-+				    struct aspeed_espi_ioc *ioc)
-+{
-+	uint32_t reg, cyc, tag, len;
-+	struct ast2500_espi *espi;
-+	struct espi_comm_hdr *hdr;
-+	unsigned long flags;
-+	uint32_t pkt_len;
-+	uint8_t *pkt;
-+	int i, rc;
-+
-+	espi = container_of(oob, struct ast2500_espi, oob);
-+
-+	if (fp->f_flags & O_NONBLOCK) {
-+		if (!mutex_trylock(&oob->rx_mtx))
-+			return -EAGAIN;
-+
-+		if (!oob->rx_ready) {
-+			rc = -ENODATA;
-+			goto unlock_mtx_n_out;
-+		}
-+	} else {
-+		mutex_lock(&oob->rx_mtx);
-+
-+		if (!oob->rx_ready) {
-+			rc = wait_event_interruptible(oob->wq, oob->rx_ready);
-+			if (rc == -ERESTARTSYS) {
-+				rc = -EINTR;
-+				goto unlock_mtx_n_out;
-+			}
-+		}
-+	}
-+
-+	/*
-+	 * common header (i.e. cycle type, tag, and length)
-+	 * part is written to HW registers
-+	 */
-+	reg = readl(espi->regs + ESPI_OOB_RX_CTRL);
-+	cyc = FIELD_GET(ESPI_OOB_RX_CTRL_CYC, reg);
-+	tag = FIELD_GET(ESPI_OOB_RX_CTRL_TAG, reg);
-+	len = FIELD_GET(ESPI_OOB_RX_CTRL_LEN, reg);
-+
-+	/*
-+	 * calculate the length of the rest part of the
-+	 * eSPI packet to be read from HW and copied to
-+	 * user space.
-+	 */
-+	pkt_len = ((len) ? len : ESPI_MAX_PLD_LEN) + sizeof(struct espi_comm_hdr);
-+
-+	if (ioc->pkt_len < pkt_len) {
-+		rc = -EINVAL;
-+		goto unlock_mtx_n_out;
-+	}
-+
-+	pkt = vmalloc(pkt_len);
-+	if (!pkt) {
-+		rc = -ENOMEM;
-+		goto unlock_mtx_n_out;
-+	}
-+
-+	hdr = (struct espi_comm_hdr *)pkt;
-+	hdr->cyc = cyc;
-+	hdr->tag = tag;
-+	hdr->len_h = len >> 8;
-+	hdr->len_l = len & 0xff;
-+
-+	if (oob->dma.enable) {
-+		memcpy(hdr + 1, oob->dma.rx_virt, pkt_len - sizeof(*hdr));
-+	} else {
-+		for (i = sizeof(*hdr); i < pkt_len; ++i)
-+			pkt[i] = readl(espi->regs + ESPI_OOB_RX_DATA) & 0xff;
-+	}
-+
-+	if (copy_to_user((void __user *)ioc->pkt, pkt, pkt_len)) {
-+		rc = -EFAULT;
-+		goto free_n_out;
-+	}
-+
-+	spin_lock_irqsave(&oob->lock, flags);
-+
-+	writel(ESPI_OOB_RX_CTRL_SERV_PEND, espi->regs + ESPI_OOB_RX_CTRL);
-+	oob->rx_ready = 0;
-+
-+	spin_unlock_irqrestore(&oob->lock, flags);
-+
-+	rc = 0;
-+
-+free_n_out:
-+	vfree(pkt);
-+
-+unlock_mtx_n_out:
-+	mutex_unlock(&oob->rx_mtx);
-+
-+	return rc;
-+}
-+
-+static long ast2500_espi_oob_put_tx(struct file *fp,
-+				    struct ast2500_espi_oob *oob,
-+				    struct aspeed_espi_ioc *ioc)
-+{
-+	uint32_t reg, cyc, tag, len;
-+	struct ast2500_espi *espi;
-+	struct espi_comm_hdr *hdr;
-+	uint8_t *pkt;
-+	int i, rc;
-+
-+	espi = container_of(oob, struct ast2500_espi, oob);
-+
-+	if (!mutex_trylock(&oob->tx_mtx))
-+		return -EAGAIN;
-+
-+	reg = readl(espi->regs + ESPI_OOB_TX_CTRL);
-+	if (reg & ESPI_OOB_TX_CTRL_TRIG_PEND) {
-+		rc = -EBUSY;
-+		goto unlock_mtx_n_out;
-+	}
-+
-+	if (ioc->pkt_len > ESPI_MAX_PKT_LEN) {
-+		rc = -EINVAL;
-+		goto unlock_mtx_n_out;
-+	}
-+
-+	pkt = vmalloc(ioc->pkt_len);
-+	if (!pkt) {
-+		rc = -ENOMEM;
-+		goto unlock_mtx_n_out;
-+	}
-+
-+	hdr = (struct espi_comm_hdr *)pkt;
-+
-+	if (copy_from_user(pkt, (void __user *)ioc->pkt, ioc->pkt_len)) {
-+		rc = -EFAULT;
-+		goto free_n_out;
-+	}
-+
-+	/*
-+	 * common header (i.e. cycle type, tag, and length)
-+	 * part is written to HW registers
-+	 */
-+	if (oob->dma.enable) {
-+		memcpy(oob->dma.tx_virt, hdr + 1, ioc->pkt_len - sizeof(*hdr));
-+		dma_wmb();
-+	} else {
-+		for (i = sizeof(*hdr); i < ioc->pkt_len; ++i)
-+			writel(pkt[i], espi->regs + ESPI_OOB_TX_DATA);
-+	}
-+
-+	cyc = hdr->cyc;
-+	tag = hdr->tag;
-+	len = (hdr->len_h << 8) | (hdr->len_l & 0xff);
-+
-+	reg = FIELD_PREP(ESPI_OOB_TX_CTRL_CYC, cyc)
-+	      | FIELD_PREP(ESPI_OOB_TX_CTRL_TAG, tag)
-+	      | FIELD_PREP(ESPI_OOB_TX_CTRL_LEN, len)
-+	      | ESPI_OOB_TX_CTRL_TRIG_PEND;
-+	writel(reg, espi->regs + ESPI_OOB_TX_CTRL);
-+
-+	rc = 0;
-+
-+free_n_out:
-+	vfree(pkt);
-+
-+unlock_mtx_n_out:
-+	mutex_unlock(&oob->tx_mtx);
-+
-+	return rc;
-+}
-+
-+static long ast2500_espi_oob_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
-+{
-+	struct ast2500_espi_oob *oob;
-+	struct aspeed_espi_ioc ioc;
-+
-+	oob = container_of(fp->private_data, struct ast2500_espi_oob, mdev);
-+
-+	if (copy_from_user(&ioc, (void __user *)arg, sizeof(ioc)))
-+		return -EFAULT;
-+
-+	if (ioc.pkt_len > ESPI_MAX_PKT_LEN)
-+		return -EINVAL;
-+
-+	switch (cmd) {
-+	case ASPEED_ESPI_OOB_GET_RX:
-+		return ast2500_espi_oob_get_rx(fp, oob, &ioc);
-+	case ASPEED_ESPI_OOB_PUT_TX:
-+		return ast2500_espi_oob_put_tx(fp, oob, &ioc);
-+	default:
-+		break;
-+	};
-+
-+	return -EINVAL;
-+}
-+
-+static const struct file_operations ast2500_espi_oob_fops = {
-+	.owner = THIS_MODULE,
-+	.unlocked_ioctl = ast2500_espi_oob_ioctl,
-+};
-+
-+static void ast2500_espi_oob_isr(struct ast2500_espi *espi)
-+{
-+	struct ast2500_espi_oob *oob;
-+	unsigned long flags;
-+	uint32_t sts;
-+
-+	oob = &espi->oob;
-+
-+	sts = readl(espi->regs + ESPI_INT_STS);
-+
-+	if (sts & ESPI_INT_STS_OOB_RX_CMPLT) {
-+		writel(ESPI_INT_STS_OOB_RX_CMPLT, espi->regs + ESPI_INT_STS);
-+
-+		spin_lock_irqsave(&oob->lock, flags);
-+		oob->rx_ready = true;
-+		spin_unlock_irqrestore(&oob->lock, flags);
-+
-+		wake_up_interruptible(&oob->wq);
-+	}
-+}
-+
-+static void ast2500_espi_oob_reset(struct ast2500_espi *espi)
-+{
-+	struct ast2500_espi_oob *oob;
-+	uint32_t reg;
-+
-+	oob = &espi->oob;
-+
-+	reg = readl(espi->regs + ESPI_INT_EN);
-+	reg &= ~(ESPI_INT_EN_OOB);
-+	writel(reg, espi->regs + ESPI_INT_EN);
-+	writel(ESPI_INT_STS_OOB, espi->regs + ESPI_INT_STS);
-+
-+	reg = readl(espi->regs + ESPI_CTRL);
-+	reg &= ~(ESPI_CTRL_OOB_TX_SW_RST
-+		 | ESPI_CTRL_OOB_RX_SW_RST
-+		 | ESPI_CTRL_OOB_TX_DMA_EN
-+		 | ESPI_CTRL_OOB_RX_DMA_EN
-+		 | ESPI_CTRL_OOB_SW_RDY);
-+	writel(reg, espi->regs + ESPI_CTRL);
-+
-+	udelay(1);
-+
-+	reg |= (ESPI_CTRL_OOB_TX_SW_RST | ESPI_CTRL_OOB_RX_SW_RST);
-+	writel(reg, espi->regs + ESPI_CTRL);
-+
-+	if (oob->dma.enable) {
-+		writel(oob->dma.tx_addr, espi->regs + ESPI_OOB_TX_DMA);
-+		writel(oob->dma.rx_addr, espi->regs + ESPI_OOB_RX_DMA);
-+
-+		reg = readl(espi->regs + ESPI_CTRL)
-+		      | ESPI_CTRL_OOB_TX_DMA_EN
-+		      | ESPI_CTRL_OOB_RX_DMA_EN;
-+		writel(reg, espi->regs + ESPI_CTRL);
-+	}
-+
-+	reg = readl(espi->regs + ESPI_INT_EN) | ESPI_INT_EN_OOB_RX_CMPLT;
-+	writel(reg, espi->regs + ESPI_INT_EN);
-+
-+	reg = readl(espi->regs + ESPI_CTRL) | ESPI_CTRL_OOB_SW_RDY;
-+	writel(reg, espi->regs + ESPI_CTRL);
-+}
-+
-+static int ast2500_espi_oob_probe(struct ast2500_espi *espi)
-+{
-+	struct ast2500_espi_oob *oob;
-+	struct device *dev;
-+	int rc;
-+
-+	dev = espi->dev;
-+
-+	oob = &espi->oob;
-+
-+	init_waitqueue_head(&oob->wq);
-+
-+	spin_lock_init(&oob->lock);
-+
-+	mutex_init(&oob->tx_mtx);
-+	mutex_init(&oob->rx_mtx);
-+
-+	oob->dma.enable = of_property_read_bool(dev->of_node, "oob-dma-mode");
-+	if (oob->dma.enable) {
-+		oob->dma.tx_virt = dmam_alloc_coherent(dev, PAGE_SIZE, &oob->dma.tx_addr, GFP_KERNEL);
-+		if (!oob->dma.tx_virt) {
-+			dev_err(dev, "cannot allocate DMA TX buffer\n");
-+			return -ENOMEM;
-+		}
-+
-+		oob->dma.rx_virt = dmam_alloc_coherent(dev, PAGE_SIZE, &oob->dma.rx_addr, GFP_KERNEL);
-+		if (!oob->dma.rx_virt) {
-+			dev_err(dev, "cannot allocate DMA TX buffer\n");
-+			return -ENOMEM;
-+		}
-+	}
-+
-+	oob->mdev.parent = dev;
-+	oob->mdev.minor = MISC_DYNAMIC_MINOR;
-+	oob->mdev.name = devm_kasprintf(dev, GFP_KERNEL, "%s-oob", DEVICE_NAME);
-+	oob->mdev.fops = &ast2500_espi_oob_fops;
-+	rc = misc_register(&oob->mdev);
-+	if (rc) {
-+		dev_err(dev, "cannot register device %s\n", oob->mdev.name);
-+		return rc;
-+	}
-+
-+	ast2500_espi_oob_reset(espi);
-+
-+	return 0;
-+}
-+
-+static int ast2500_espi_oob_remove(struct ast2500_espi *espi)
-+{
-+	struct ast2500_espi_oob *oob;
-+	struct device *dev;
-+	uint32_t reg;
-+
-+	dev = espi->dev;
-+
-+	oob = &espi->oob;
-+
-+	reg = readl(espi->regs + ESPI_INT_EN);
-+	reg &= ~(ESPI_INT_EN_OOB);
-+	writel(reg, espi->regs + ESPI_INT_EN);
-+
-+	reg = readl(espi->regs + ESPI_CTRL);
-+	reg &= ~(ESPI_CTRL_OOB_TX_DMA_EN
-+		 | ESPI_CTRL_OOB_RX_DMA_EN
-+		 | ESPI_CTRL_OOB_SW_RDY);
-+	writel(reg, espi->regs + ESPI_CTRL);
-+
-+	if (oob->dma.enable) {
-+		dmam_free_coherent(dev, PAGE_SIZE, oob->dma.tx_virt, oob->dma.tx_addr);
-+		dmam_free_coherent(dev, PAGE_SIZE, oob->dma.rx_virt, oob->dma.rx_addr);
-+	}
-+
-+	mutex_destroy(&oob->tx_mtx);
-+	mutex_destroy(&oob->rx_mtx);
-+
-+	misc_deregister(&oob->mdev);
-+
-+	return 0;
-+}
-+
-+/* flash channel (CH3) */
-+static long ast2500_espi_flash_get_rx(struct file *fp,
-+				      struct ast2500_espi_flash *flash,
-+				      struct aspeed_espi_ioc *ioc)
-+{
-+	uint32_t reg, cyc, tag, len;
-+	struct ast2500_espi *espi;
-+	struct espi_comm_hdr *hdr;
-+	unsigned long flags;
-+	uint32_t pkt_len;
-+	uint8_t *pkt;
-+	int i, rc;
-+
-+	rc = 0;
-+
-+	espi = container_of(flash, struct ast2500_espi, flash);
-+
-+	if (fp->f_flags & O_NONBLOCK) {
-+		if (!mutex_trylock(&flash->rx_mtx))
-+			return -EAGAIN;
-+
-+		if (!flash->rx_ready) {
-+			rc = -ENODATA;
-+			goto unlock_mtx_n_out;
-+		}
-+	} else {
-+		mutex_lock(&flash->rx_mtx);
-+
-+		if (!flash->rx_ready) {
-+			rc = wait_event_interruptible(flash->wq, flash->rx_ready);
-+			if (rc == -ERESTARTSYS) {
-+				rc = -EINTR;
-+				goto unlock_mtx_n_out;
-+			}
-+		}
-+	}
-+
-+	/*
-+	 * common header (i.e. cycle type, tag, and length)
-+	 * part is written to HW registers
-+	 */
-+	reg = readl(espi->regs + ESPI_FLASH_RX_CTRL);
-+	cyc = FIELD_GET(ESPI_FLASH_RX_CTRL_CYC, reg);
-+	tag = FIELD_GET(ESPI_FLASH_RX_CTRL_TAG, reg);
-+	len = FIELD_GET(ESPI_FLASH_RX_CTRL_LEN, reg);
-+
-+	/*
-+	 * calculate the length of the rest part of the
-+	 * eSPI packet to be read from HW and copied to
-+	 * user space.
-+	 */
-+	switch (cyc) {
-+	case ESPI_FLASH_WRITE:
-+		pkt_len = ((len) ? len : ESPI_MAX_PLD_LEN) +
-+			  sizeof(struct espi_flash_rwe);
-+		break;
-+	case ESPI_FLASH_READ:
-+	case ESPI_FLASH_ERASE:
-+		pkt_len = sizeof(struct espi_flash_rwe);
-+		break;
-+	case ESPI_FLASH_SUC_CMPLT_D_MIDDLE:
-+	case ESPI_FLASH_SUC_CMPLT_D_FIRST:
-+	case ESPI_FLASH_SUC_CMPLT_D_LAST:
-+	case ESPI_FLASH_SUC_CMPLT_D_ONLY:
-+		pkt_len = ((len) ? len : ESPI_MAX_PLD_LEN) +
-+			  sizeof(struct espi_flash_cmplt);
-+		break;
-+	case ESPI_FLASH_SUC_CMPLT:
-+	case ESPI_FLASH_UNSUC_CMPLT:
-+		pkt_len = sizeof(struct espi_flash_cmplt);
-+		break;
-+	default:
-+		rc = -EFAULT;
-+		goto unlock_mtx_n_out;
-+	}
-+
-+	if (ioc->pkt_len < pkt_len) {
-+		rc = -EINVAL;
-+		goto unlock_mtx_n_out;
-+	}
-+
-+	pkt = vmalloc(pkt_len);
-+	if (!pkt) {
-+		rc = -ENOMEM;
-+		goto unlock_mtx_n_out;
-+	}
-+
-+	hdr = (struct espi_comm_hdr *)pkt;
-+	hdr->cyc = cyc;
-+	hdr->tag = tag;
-+	hdr->len_h = len >> 8;
-+	hdr->len_l = len & 0xff;
-+
-+	if (flash->dma.enable) {
-+		memcpy(hdr + 1, flash->dma.rx_virt, pkt_len - sizeof(*hdr));
-+	} else {
-+		for (i = sizeof(*hdr); i < pkt_len; ++i)
-+			pkt[i] = readl(espi->regs + ESPI_FLASH_RX_DATA) & 0xff;
-+	}
-+
-+	if (copy_to_user((void __user *)ioc->pkt, pkt, pkt_len)) {
-+		rc = -EFAULT;
-+		goto free_n_out;
-+	}
-+
-+	spin_lock_irqsave(&flash->lock, flags);
-+
-+	writel(ESPI_FLASH_RX_CTRL_SERV_PEND, espi->regs + ESPI_FLASH_RX_CTRL);
-+	flash->rx_ready = 0;
-+
-+	spin_unlock_irqrestore(&flash->lock, flags);
-+
-+	rc = 0;
-+
-+free_n_out:
-+	vfree(pkt);
-+
-+unlock_mtx_n_out:
-+	mutex_unlock(&flash->rx_mtx);
-+
-+	return rc;
-+}
-+
-+static long ast2500_espi_flash_put_tx(struct file *fp,
-+				      struct ast2500_espi_flash *flash,
-+				      struct aspeed_espi_ioc *ioc)
-+{
-+	uint32_t reg, cyc, tag, len;
-+	struct ast2500_espi *espi;
-+	struct espi_comm_hdr *hdr;
-+	uint8_t *pkt;
-+	int i, rc;
-+
-+	espi = container_of(flash, struct ast2500_espi, flash);
-+
-+	if (!mutex_trylock(&flash->tx_mtx))
-+		return -EAGAIN;
-+
-+	reg = readl(espi->regs + ESPI_FLASH_TX_CTRL);
-+	if (reg & ESPI_FLASH_TX_CTRL_TRIG_PEND) {
-+		rc = -EBUSY;
-+		goto unlock_mtx_n_out;
-+	}
-+
-+	pkt = vmalloc(ioc->pkt_len);
-+	if (!pkt) {
-+		rc = -ENOMEM;
-+		goto unlock_mtx_n_out;
-+	}
-+
-+	hdr = (struct espi_comm_hdr *)pkt;
-+
-+	if (copy_from_user(pkt, (void __user *)ioc->pkt, ioc->pkt_len)) {
-+		rc = -EFAULT;
-+		goto free_n_out;
-+	}
-+
-+	/*
-+	 * common header (i.e. cycle type, tag, and length)
-+	 * part is written to HW registers
-+	 */
-+	if (flash->dma.enable) {
-+		memcpy(flash->dma.tx_virt, hdr + 1, ioc->pkt_len - sizeof(*hdr));
-+		dma_wmb();
-+	} else {
-+		for (i = sizeof(*hdr); i < ioc->pkt_len; ++i)
-+			writel(pkt[i], espi->regs + ESPI_FLASH_TX_DATA);
-+	}
-+
-+	cyc = hdr->cyc;
-+	tag = hdr->tag;
-+	len = (hdr->len_h << 8) | (hdr->len_l & 0xff);
-+
-+	reg = FIELD_PREP(ESPI_FLASH_TX_CTRL_CYC, cyc)
-+	      | FIELD_PREP(ESPI_FLASH_TX_CTRL_TAG, tag)
-+	      | FIELD_PREP(ESPI_FLASH_TX_CTRL_LEN, len)
-+	      | ESPI_FLASH_TX_CTRL_TRIG_PEND;
-+	writel(reg, espi->regs + ESPI_FLASH_TX_CTRL);
-+
-+	rc = 0;
-+
-+free_n_out:
-+	vfree(pkt);
-+
-+unlock_mtx_n_out:
-+	mutex_unlock(&flash->tx_mtx);
-+
-+	return rc;
-+}
-+
-+static long ast2500_espi_flash_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
-+{
-+	struct ast2500_espi_flash *flash;
-+	struct aspeed_espi_ioc ioc;
-+
-+	flash = container_of(fp->private_data, struct ast2500_espi_flash, mdev);
-+
-+	if (copy_from_user(&ioc, (void __user *)arg, sizeof(ioc)))
-+		return -EFAULT;
-+
-+	if (ioc.pkt_len > ESPI_MAX_PKT_LEN)
-+		return -EINVAL;
-+
-+	switch (cmd) {
-+	case ASPEED_ESPI_FLASH_GET_RX:
-+		return ast2500_espi_flash_get_rx(fp, flash, &ioc);
-+	case ASPEED_ESPI_FLASH_PUT_TX:
-+		return ast2500_espi_flash_put_tx(fp, flash, &ioc);
-+	default:
-+		break;
-+	};
-+
-+	return -EINVAL;
-+}
-+
-+static const struct file_operations ast2500_espi_flash_fops = {
-+	.owner = THIS_MODULE,
-+	.unlocked_ioctl = ast2500_espi_flash_ioctl,
-+};
-+
-+static void ast2500_espi_flash_isr(struct ast2500_espi *espi)
-+{
-+	struct ast2500_espi_flash *flash;
-+	unsigned long flags;
-+	uint32_t sts;
-+
-+	flash = &espi->flash;
-+
-+	sts = readl(espi->regs + ESPI_INT_STS);
-+
-+	if (sts & ESPI_INT_STS_FLASH_RX_CMPLT) {
-+		spin_lock_irqsave(&flash->lock, flags);
-+		flash->rx_ready = true;
-+		spin_unlock_irqrestore(&flash->lock, flags);
-+
-+		wake_up_interruptible(&flash->wq);
-+
-+		writel(ESPI_INT_STS_FLASH_RX_CMPLT, espi->regs + ESPI_INT_STS);
-+	}
-+}
-+
-+static void ast2500_espi_flash_reset(struct ast2500_espi *espi)
-+{
-+	struct ast2500_espi_flash *flash = &espi->flash;
-+	uint32_t reg;
-+
-+	reg = readl(espi->regs + ESPI_INT_EN);
-+	reg &= ~(ESPI_INT_EN_FLASH);
-+	writel(reg, espi->regs + ESPI_INT_EN);
-+	writel(ESPI_INT_STS_FLASH, espi->regs + ESPI_INT_STS);
-+
-+	reg = readl(espi->regs + ESPI_CTRL);
-+	reg &= ~(ESPI_CTRL_FLASH_TX_SW_RST
-+		 | ESPI_CTRL_FLASH_RX_SW_RST
-+		 | ESPI_CTRL_FLASH_TX_DMA_EN
-+		 | ESPI_CTRL_FLASH_RX_DMA_EN
-+		 | ESPI_CTRL_FLASH_SW_RDY);
-+	writel(reg, espi->regs + ESPI_CTRL);
-+
-+	udelay(1);
-+
-+	reg |= (ESPI_CTRL_FLASH_TX_SW_RST | ESPI_CTRL_FLASH_RX_SW_RST);
-+	writel(reg, espi->regs + ESPI_CTRL);
-+
-+	if (flash->safs.mode == SAFS_MODE_MIX) {
-+		reg = FIELD_PREP(ESPI_FLASH_SAFS_TADDR_BASE, flash->safs.taddr >> 24)
-+			| FIELD_PREP(ESPI_FLASH_SAFS_TADDR_MASK, (~(flash->safs.size - 1)) >> 24);
-+		writel(reg, espi->regs + ESPI_FLASH_SAFS_TADDR);
-+	} else {
-+		reg = readl(espi->regs + ESPI_CTRL) | ESPI_CTRL_FLASH_SAFS_SW_MODE;
-+		writel(reg, espi->regs + ESPI_CTRL);
-+	}
-+
-+	if (flash->dma.enable) {
-+		writel(flash->dma.tx_addr, espi->regs + ESPI_FLASH_TX_DMA);
-+		writel(flash->dma.rx_addr, espi->regs + ESPI_FLASH_RX_DMA);
-+
-+		reg = readl(espi->regs + ESPI_CTRL)
-+		      | ESPI_CTRL_FLASH_TX_DMA_EN
-+			  | ESPI_CTRL_FLASH_RX_DMA_EN;
-+		writel(reg, espi->regs + ESPI_CTRL);
-+	}
-+
-+	reg = readl(espi->regs + ESPI_INT_EN) | ESPI_INT_EN_FLASH_RX_CMPLT;
-+	writel(reg, espi->regs + ESPI_INT_EN);
-+
-+	reg = readl(espi->regs + ESPI_CTRL) | ESPI_CTRL_FLASH_SW_RDY;
-+	writel(reg, espi->regs + ESPI_CTRL);
-+}
-+
-+static int ast2500_espi_flash_probe(struct ast2500_espi *espi)
-+{
-+	struct ast2500_espi_flash *flash;
-+	struct device *dev;
-+	int rc;
-+
-+	dev = espi->dev;
-+
-+	flash = &espi->flash;
-+
-+	init_waitqueue_head(&flash->wq);
-+
-+	spin_lock_init(&flash->lock);
-+
-+	mutex_init(&flash->tx_mtx);
-+	mutex_init(&flash->rx_mtx);
-+
-+	flash->safs.mode = SAFS_MODE_MIX;
-+
-+	of_property_read_u32(dev->of_node, "flash-safs-mode", &flash->safs.mode);
-+	if (flash->safs.mode == SAFS_MODE_MIX) {
-+		rc = of_property_read_u32(dev->of_node, "flash-safs-tgt-addr", &flash->safs.taddr);
-+		if (rc || !IS_ALIGNED(flash->safs.taddr, FLASH_SAFS_ALIGN)) {
-+			dev_err(dev, "cannot get 16MB-aligned SAFS target address\n");
-+			return -ENODEV;
-+		}
-+
-+		rc = of_property_read_u32(dev->of_node, "flash-safs-size", &flash->safs.size);
-+		if (rc || !IS_ALIGNED(flash->safs.size, FLASH_SAFS_ALIGN)) {
-+			dev_err(dev, "cannot get 16MB-aligned SAFS size\n");
-+			return -ENODEV;
-+		}
-+	}
-+
-+	flash->dma.enable = of_property_read_bool(dev->of_node, "flash-dma-mode");
-+	if (flash->dma.enable) {
-+		flash->dma.tx_virt = dmam_alloc_coherent(dev, PAGE_SIZE, &flash->dma.tx_addr, GFP_KERNEL);
-+		if (!flash->dma.tx_virt) {
-+			dev_err(dev, "cannot allocate DMA TX buffer\n");
-+			return -ENOMEM;
-+		}
-+
-+		flash->dma.rx_virt = dmam_alloc_coherent(dev, PAGE_SIZE, &flash->dma.rx_addr, GFP_KERNEL);
-+		if (!flash->dma.rx_virt) {
-+			dev_err(dev, "cannot allocate DMA RX buffer\n");
-+			return -ENOMEM;
-+		}
-+	}
-+
-+	flash->mdev.parent = dev;
-+	flash->mdev.minor = MISC_DYNAMIC_MINOR;
-+	flash->mdev.name = devm_kasprintf(dev, GFP_KERNEL, "%s-flash", DEVICE_NAME);
-+	flash->mdev.fops = &ast2500_espi_flash_fops;
-+	rc = misc_register(&flash->mdev);
-+	if (rc) {
-+		dev_err(dev, "cannot register device %s\n", flash->mdev.name);
-+		return rc;
-+	}
-+
-+	ast2500_espi_flash_reset(espi);
-+
-+	return 0;
-+}
-+
-+static int ast2500_espi_flash_remove(struct ast2500_espi *espi)
-+{
-+	struct ast2500_espi_flash *flash;
-+	struct device *dev;
-+	uint32_t reg;
-+
-+	dev = espi->dev;
-+
-+	flash = &espi->flash;
-+
-+	reg = readl(espi->regs + ESPI_INT_EN);
-+	reg &= ~(ESPI_INT_EN_FLASH);
-+	writel(reg, espi->regs + ESPI_INT_EN);
-+
-+	reg = readl(espi->regs + ESPI_CTRL);
-+	reg &= ~(ESPI_CTRL_FLASH_TX_DMA_EN
-+		 | ESPI_CTRL_FLASH_RX_DMA_EN
-+		 | ESPI_CTRL_FLASH_SW_RDY);
-+	writel(reg, espi->regs + ESPI_CTRL);
-+
-+	if (flash->dma.enable) {
-+		dmam_free_coherent(dev, PAGE_SIZE, flash->dma.tx_virt, flash->dma.tx_addr);
-+		dmam_free_coherent(dev, PAGE_SIZE, flash->dma.rx_virt, flash->dma.rx_addr);
-+	}
-+
-+	mutex_destroy(&flash->tx_mtx);
-+	mutex_destroy(&flash->rx_mtx);
-+
-+	misc_deregister(&flash->mdev);
-+
-+	return 0;
-+}
-+
-+/* global control */
-+static irqreturn_t ast2500_espi_isr(int irq, void *arg)
-+{
-+	struct ast2500_espi *espi;
-+	uint32_t sts;
-+
-+	espi = (struct ast2500_espi *)arg;
-+
-+	sts = readl(espi->regs + ESPI_INT_STS);
-+	if (!sts)
-+		return IRQ_NONE;
-+
-+	if (sts & ESPI_INT_STS_PERIF)
-+		ast2500_espi_perif_isr(espi);
-+
-+	if (sts & ESPI_INT_STS_VW)
-+		ast2500_espi_vw_isr(espi);
-+
-+	if (sts & ESPI_INT_STS_OOB)
-+		ast2500_espi_oob_isr(espi);
-+
-+	if (sts & ESPI_INT_STS_FLASH)
-+		ast2500_espi_flash_isr(espi);
-+
-+	if (sts & ESPI_INT_STS_RST_DEASSERT) {
-+		ast2500_espi_perif_reset(espi);
-+		ast2500_espi_vw_reset(espi);
-+		ast2500_espi_oob_reset(espi);
-+		ast2500_espi_flash_reset(espi);
-+		writel(ESPI_INT_STS_RST_DEASSERT, espi->regs + ESPI_INT_STS);
-+	}
-+
-+	return IRQ_HANDLED;
-+}
-+
-+static int ast2500_espi_probe(struct platform_device *pdev)
-+{
-+	struct ast2500_espi *espi;
-+	struct resource *res;
-+	struct device *dev;
-+	uint32_t reg;
-+	int rc;
-+
-+	dev = &pdev->dev;
-+
-+	espi = devm_kzalloc(dev, sizeof(*espi), GFP_KERNEL);
-+	if (!espi)
-+		return -ENOMEM;
-+
-+	espi->dev = dev;
-+
-+	rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
-+	if (rc) {
-+		dev_err(dev, "cannot set 64-bits DMA mask\n");
-+		return rc;
-+	}
-+
-+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+	if (!res) {
-+		dev_err(dev, "cannot get resource\n");
-+		return -ENODEV;
-+	}
-+
-+	espi->regs = devm_ioremap_resource(dev, res);
-+	if (IS_ERR(espi->regs)) {
-+		dev_err(dev, "cannot map registers\n");
-+		return PTR_ERR(espi->regs);
-+	}
-+
-+	espi->irq = platform_get_irq(pdev, 0);
-+	if (espi->irq < 0) {
-+		dev_err(dev, "cannot get IRQ number\n");
-+		return -ENODEV;
-+	}
-+
-+	espi->clk = devm_clk_get(dev, NULL);
-+	if (IS_ERR(espi->clk)) {
-+		dev_err(dev, "cannot get clock control\n");
-+		return PTR_ERR(espi->clk);
-+	}
-+
-+	rc = clk_prepare_enable(espi->clk);
-+	if (rc) {
-+		dev_err(dev, "cannot enable clocks\n");
-+		return rc;
-+	}
-+
-+	reg = readl(espi->regs + ESPI_INT_EN);
-+	reg &= ~ESPI_INT_EN_RST_DEASSERT;
-+	writel(reg, espi->regs + ESPI_INT_EN);
-+
-+	rc = ast2500_espi_perif_probe(espi);
-+	if (rc) {
-+		dev_err(dev, "cannot init peripheral channel, rc=%d\n", rc);
-+		return rc;
-+	}
-+
-+	rc = ast2500_espi_vw_probe(espi);
-+	if (rc) {
-+		dev_err(dev, "cannot init vw channel, rc=%d\n", rc);
-+		goto err_remove_perif;
-+	}
-+
-+	rc = ast2500_espi_oob_probe(espi);
-+	if (rc) {
-+		dev_err(dev, "cannot init oob channel, rc=%d\n", rc);
-+		goto err_remove_vw;
-+	}
-+
-+	rc = ast2500_espi_flash_probe(espi);
-+	if (rc) {
-+		dev_err(dev, "cannot init flash channel, rc=%d\n", rc);
-+		goto err_remove_oob;
-+	}
-+
-+	rc = devm_request_irq(dev, espi->irq, ast2500_espi_isr, 0, dev_name(dev), espi);
-+	if (rc) {
-+		dev_err(dev, "cannot request IRQ\n");
-+		goto err_remove_flash;
-+	}
-+
-+	reg = readl(espi->regs + ESPI_INT_EN);
-+	reg |= ESPI_INT_EN_RST_DEASSERT;
-+	writel(reg, espi->regs + ESPI_INT_EN);
-+
-+	dev_set_drvdata(dev, espi);
-+
-+	dev_info(dev, "module loaded\n");
-+
-+	return 0;
-+
-+err_remove_flash:
-+	ast2500_espi_flash_remove(espi);
-+err_remove_oob:
-+	ast2500_espi_oob_remove(espi);
-+err_remove_vw:
-+	ast2500_espi_vw_remove(espi);
-+err_remove_perif:
-+	ast2500_espi_perif_remove(espi);
-+
-+	return rc;
-+}
-+
-+static int ast2500_espi_remove(struct platform_device *pdev)
-+{
-+	struct ast2500_espi *espi;
-+	struct device *dev;
-+	uint32_t reg;
-+	int rc;
-+
-+	dev = &pdev->dev;
-+
-+	espi = (struct ast2500_espi *)dev_get_drvdata(dev);
-+
-+	reg = readl(espi->regs + ESPI_INT_EN);
-+	reg &= ~(ESPI_INT_EN_RST_DEASSERT);
-+	writel(reg, espi->regs + ESPI_INT_EN);
-+
-+	rc = ast2500_espi_perif_remove(espi);
-+	if (rc)
-+		dev_warn(dev, "cannot remove peripheral channel, rc=%d\n", rc);
-+
-+	rc = ast2500_espi_vw_remove(espi);
-+	if (rc)
-+		dev_warn(dev, "cannot remove peripheral channel, rc=%d\n", rc);
-+
-+	rc = ast2500_espi_oob_remove(espi);
-+	if (rc)
-+		dev_warn(dev, "cannot remove peripheral channel, rc=%d\n", rc);
-+
-+	rc = ast2500_espi_flash_remove(espi);
-+	if (rc)
-+		dev_warn(dev, "cannot remove peripheral channel, rc=%d\n", rc);
-+
-+	return 0;
-+}
-+
-+static const struct of_device_id ast2500_espi_of_matches[] = {
-+	{ .compatible = "aspeed,ast2500-espi" },
-+	{ },
-+};
-+
-+static struct platform_driver ast2500_espi_driver = {
-+	.driver = {
-+		.name = "ast2500-espi",
-+		.of_match_table = ast2500_espi_of_matches,
-+	},
-+	.probe = ast2500_espi_probe,
-+	.remove = ast2500_espi_remove,
-+};
-+
-+module_platform_driver(ast2500_espi_driver);
-+
-+MODULE_AUTHOR("Chia-Wei Wang <chiawei_wang@aspeedtech.com>");
-+MODULE_DESCRIPTION("Control of AST2500 eSPI Device");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/soc/aspeed/ast2500-espi.h b/drivers/soc/aspeed/ast2500-espi.h
-new file mode 100644
-index 000000000..b4ee0bc25
---- /dev/null
-+++ b/drivers/soc/aspeed/ast2500-espi.h
-@@ -0,0 +1,250 @@
-+/* SPDX-License-Identifier: GPL-2.0+ */
-+/*
-+ * Copyright 2023 Aspeed Technology Inc.
-+ */
-+#ifndef _AST2500_ESPI_H_
-+#define _AST2500_ESPI_H_
-+
-+#include <linux/bits.h>
-+#include "aspeed-espi-comm.h"
-+
-+/* registers */
-+#define ESPI_CTRL				0x000
-+#define   ESPI_CTRL_FLASH_TX_SW_RST		BIT(31)
-+#define   ESPI_CTRL_FLASH_RX_SW_RST		BIT(30)
-+#define   ESPI_CTRL_OOB_TX_SW_RST		BIT(29)
-+#define   ESPI_CTRL_OOB_RX_SW_RST		BIT(28)
-+#define   ESPI_CTRL_PERIF_NP_TX_SW_RST		BIT(27)
-+#define   ESPI_CTRL_PERIF_NP_RX_SW_RST		BIT(26)
-+#define   ESPI_CTRL_PERIF_PC_TX_SW_RST		BIT(25)
-+#define   ESPI_CTRL_PERIF_PC_RX_SW_RST		BIT(24)
-+#define   ESPI_CTRL_FLASH_TX_DMA_EN		BIT(23)
-+#define   ESPI_CTRL_FLASH_RX_DMA_EN		BIT(22)
-+#define   ESPI_CTRL_OOB_TX_DMA_EN		BIT(21)
-+#define   ESPI_CTRL_OOB_RX_DMA_EN		BIT(20)
-+#define   ESPI_CTRL_PERIF_NP_TX_DMA_EN		BIT(19)
-+#define   ESPI_CTRL_PERIF_PC_TX_DMA_EN		BIT(17)
-+#define   ESPI_CTRL_PERIF_PC_RX_DMA_EN		BIT(16)
-+#define   ESPI_CTRL_FLASH_SAFS_SW_MODE		BIT(10)
-+#define   ESPI_CTRL_VW_GPIO_SW			BIT(9)
-+#define   ESPI_CTRL_FLASH_SW_RDY		BIT(7)
-+#define   ESPI_CTRL_OOB_SW_RDY			BIT(4)
-+#define   ESPI_CTRL_VW_SW_RDY			BIT(3)
-+#define   ESPI_CTRL_PERIF_SW_RDY		BIT(1)
-+#define ESPI_STS				0x004
-+#define ESPI_INT_STS				0x008
-+#define   ESPI_INT_STS_RST_DEASSERT		BIT(31)
-+#define   ESPI_INT_STS_OOB_RX_TMOUT		BIT(23)
-+#define   ESPI_INT_STS_VW_SYSEVT1		BIT(22)
-+#define   ESPI_INT_STS_FLASH_TX_ERR		BIT(21)
-+#define   ESPI_INT_STS_OOB_TX_ERR		BIT(20)
-+#define   ESPI_INT_STS_FLASH_TX_ABT		BIT(19)
-+#define   ESPI_INT_STS_OOB_TX_ABT		BIT(18)
-+#define   ESPI_INT_STS_PERIF_NP_TX_ABT		BIT(17)
-+#define   ESPI_INT_STS_PERIF_PC_TX_ABT		BIT(16)
-+#define   ESPI_INT_STS_FLASH_RX_ABT		BIT(15)
-+#define   ESPI_INT_STS_OOB_RX_ABT		BIT(14)
-+#define   ESPI_INT_STS_PERIF_NP_RX_ABT		BIT(13)
-+#define   ESPI_INT_STS_PERIF_PC_RX_ABT		BIT(12)
-+#define   ESPI_INT_STS_PERIF_NP_TX_ERR		BIT(11)
-+#define   ESPI_INT_STS_PERIF_PC_TX_ERR		BIT(10)
-+#define   ESPI_INT_STS_VW_GPIO			BIT(9)
-+#define   ESPI_INT_STS_VW_SYSEVT		BIT(8)
-+#define   ESPI_INT_STS_FLASH_TX_CMPLT		BIT(7)
-+#define   ESPI_INT_STS_FLASH_RX_CMPLT		BIT(6)
-+#define   ESPI_INT_STS_OOB_TX_CMPLT		BIT(5)
-+#define   ESPI_INT_STS_OOB_RX_CMPLT		BIT(4)
-+#define   ESPI_INT_STS_PERIF_NP_TX_CMPLT	BIT(3)
-+#define   ESPI_INT_STS_PERIF_PC_TX_CMPLT	BIT(1)
-+#define   ESPI_INT_STS_PERIF_PC_RX_CMPLT	BIT(0)
-+#define ESPI_INT_EN				0x00c
-+#define   ESPI_INT_EN_RST_DEASSERT		BIT(31)
-+#define   ESPI_INT_EN_OOB_RX_TMOUT		BIT(23)
-+#define   ESPI_INT_EN_VW_SYSEVT1		BIT(22)
-+#define   ESPI_INT_EN_FLASH_TX_ERR		BIT(21)
-+#define   ESPI_INT_EN_OOB_TX_ERR		BIT(20)
-+#define   ESPI_INT_EN_FLASH_TX_ABT		BIT(19)
-+#define   ESPI_INT_EN_OOB_TX_ABT		BIT(18)
-+#define   ESPI_INT_EN_PERIF_NP_TX_ABT		BIT(17)
-+#define   ESPI_INT_EN_PERIF_PC_TX_ABT		BIT(16)
-+#define   ESPI_INT_EN_FLASH_RX_ABT		BIT(15)
-+#define   ESPI_INT_EN_OOB_RX_ABT		BIT(14)
-+#define   ESPI_INT_EN_PERIF_NP_RX_ABT		BIT(13)
-+#define   ESPI_INT_EN_PERIF_PC_RX_ABT		BIT(12)
-+#define   ESPI_INT_EN_PERIF_NP_TX_ERR		BIT(11)
-+#define   ESPI_INT_EN_PERIF_PC_TX_ERR		BIT(10)
-+#define   ESPI_INT_EN_VW_GPIO			BIT(9)
-+#define   ESPI_INT_EN_VW_SYSEVT			BIT(8)
-+#define   ESPI_INT_EN_FLASH_TX_CMPLT		BIT(7)
-+#define   ESPI_INT_EN_FLASH_RX_CMPLT		BIT(6)
-+#define   ESPI_INT_EN_OOB_TX_CMPLT		BIT(5)
-+#define   ESPI_INT_EN_OOB_RX_CMPLT		BIT(4)
-+#define   ESPI_INT_EN_PERIF_NP_TX_CMPLT		BIT(3)
-+#define   ESPI_INT_EN_PERIF_PC_TX_CMPLT		BIT(1)
-+#define   ESPI_INT_EN_PERIF_PC_RX_CMPLT		BIT(0)
-+#define ESPI_PERIF_PC_RX_DMA			0x010
-+#define ESPI_PERIF_PC_RX_CTRL			0x014
-+#define   ESPI_PERIF_PC_RX_CTRL_SERV_PEND	BIT(31)
-+#define   ESPI_PERIF_PC_RX_CTRL_LEN		GENMASK(23, 12)
-+#define   ESPI_PERIF_PC_RX_CTRL_TAG		GENMASK(11, 8)
-+#define   ESPI_PERIF_PC_RX_CTRL_CYC		GENMASK(7, 0)
-+#define ESPI_PERIF_PC_RX_DATA			0x018
-+#define ESPI_PERIF_PC_TX_DMA			0x020
-+#define ESPI_PERIF_PC_TX_CTRL			0x024
-+#define	  ESPI_PERIF_PC_TX_CTRL_TRIG_PEND	BIT(31)
-+#define	  ESPI_PERIF_PC_TX_CTRL_LEN		GENMASK(23, 12)
-+#define	  ESPI_PERIF_PC_TX_CTRL_TAG		GENMASK(11, 8)
-+#define	  ESPI_PERIF_PC_TX_CTRL_CYC		GENMASK(7, 0)
-+#define ESPI_PERIF_PC_TX_DATA			0x028
-+#define ESPI_PERIF_NP_TX_DMA			0x030
-+#define ESPI_PERIF_NP_TX_CTRL			0x034
-+#define   ESPI_PERIF_NP_TX_CTRL_TRIG_PEND	BIT(31)
-+#define	  ESPI_PERIF_NP_TX_CTRL_LEN		GENMASK(23, 12)
-+#define	  ESPI_PERIF_NP_TX_CTRL_TAG		GENMASK(11, 8)
-+#define	  ESPI_PERIF_NP_TX_CTRL_CYC		GENMASK(7, 0)
-+#define ESPI_PERIF_NP_TX_DATA			0x038
-+#define ESPI_OOB_RX_DMA				0x040
-+#define ESPI_OOB_RX_CTRL			0x044
-+#define	  ESPI_OOB_RX_CTRL_SERV_PEND		BIT(31)
-+#define	  ESPI_OOB_RX_CTRL_LEN			GENMASK(23, 12)
-+#define	  ESPI_OOB_RX_CTRL_TAG			GENMASK(11, 8)
-+#define	  ESPI_OOB_RX_CTRL_CYC			GENMASK(7, 0)
-+#define ESPI_OOB_RX_DATA			0x048
-+#define ESPI_OOB_TX_DMA				0x050
-+#define ESPI_OOB_TX_CTRL			0x054
-+#define	  ESPI_OOB_TX_CTRL_TRIG_PEND		BIT(31)
-+#define	  ESPI_OOB_TX_CTRL_LEN			GENMASK(23, 12)
-+#define	  ESPI_OOB_TX_CTRL_TAG			GENMASK(11, 8)
-+#define	  ESPI_OOB_TX_CTRL_CYC			GENMASK(7, 0)
-+#define ESPI_OOB_TX_DATA			0x058
-+#define ESPI_FLASH_RX_DMA			0x060
-+#define ESPI_FLASH_RX_CTRL			0x064
-+#define	  ESPI_FLASH_RX_CTRL_SERV_PEND		BIT(31)
-+#define	  ESPI_FLASH_RX_CTRL_LEN		GENMASK(23, 12)
-+#define	  ESPI_FLASH_RX_CTRL_TAG		GENMASK(11, 8)
-+#define	  ESPI_FLASH_RX_CTRL_CYC		GENMASK(7, 0)
-+#define ESPI_FLASH_RX_DATA			0x068
-+#define ESPI_FLASH_TX_DMA			0x070
-+#define ESPI_FLASH_TX_CTRL			0x074
-+#define	  ESPI_FLASH_TX_CTRL_TRIG_PEND		BIT(31)
-+#define	  ESPI_FLASH_TX_CTRL_LEN		GENMASK(23, 12)
-+#define	  ESPI_FLASH_TX_CTRL_TAG		GENMASK(11, 8)
-+#define	  ESPI_FLASH_TX_CTRL_CYC		GENMASK(7, 0)
-+#define ESPI_FLASH_TX_DATA			0x078
-+#define ESPI_PERIF_MCYC_SADDR			0x084
-+#define ESPI_PERIF_MCYC_TADDR			0x088
-+#define ESPI_PERIF_MCYC_MASK			0x08c
-+#define ESPI_FLASH_SAFS_TADDR			0x090
-+#define   ESPI_FLASH_SAFS_TADDR_BASE		GENMASK(31, 24)
-+#define   ESPI_FLASH_SAFS_TADDR_MASK		GENMASK(15, 8)
-+#define ESPI_VW_SYSEVT_INT_EN			0x094
-+#define   ESPI_VW_SYSEVT_INT_EN_HOST_RST_WARN	BIT(8)
-+#define   ESPI_VW_SYSEVT_INT_EN_OOB_RST_WARN	BIT(6)
-+#define ESPI_VW_SYSEVT				0x098
-+#define   ESPI_VW_SYSEVT_HOST_RST_ACK		BIT(27)
-+#define   ESPI_VW_SYSEVT_SLV_BOOT_STS		BIT(23)
-+#define   ESPI_VW_SYSEVT_SLV_BOOT_DONE		BIT(20)
-+#define   ESPI_VW_SYSEVT_OOB_RST_ACK		BIT(16)
-+#define   ESPI_VW_SYSEVT_HOST_RST_WARN		BIT(8)
-+#define   ESPI_VW_SYSEVT_OOB_RST_WARN		BIT(6)
-+#define ESPI_VW_GPIO_VAL			0x09c
-+#define ESPI_GEN_CAP_N_CONF			0x0a0
-+#define ESPI_CH0_CAP_N_CONF			0x0a4
-+#define ESPI_CH1_CAP_N_CONF			0x0a8
-+#define ESPI_CH2_CAP_N_CONF			0x0ac
-+#define ESPI_CH3_CAP_N_CONF			0x0b0
-+#define ESPI_CH3_CAP_N_CONF2			0x0b4
-+#define ESPI_VW_GPIO_DIR			0x0c0
-+#define ESPI_VW_GPIO_GRP			0x0c4
-+#define ESPI_VW_SYSEVT1_INT_EN			0x100
-+#define   ESPI_VW_SYSEVT1_INT_EN_SUSPEND_WARN	BIT(0)
-+#define ESPI_VW_SYSEVT1				0x104
-+#define   ESPI_VW_SYSEVT1_SUSPEND_ACK		BIT(20)
-+#define   ESPI_VW_SYSEVT1_SUSPEND_WARN		BIT(0)
-+#define ESPI_VW_SYSEVT_INT_T0			0x110
-+#define ESPI_VW_SYSEVT_INT_T1			0x114
-+#define ESPI_VW_SYSEVT_INT_T2			0x118
-+#define   ESPI_VW_SYSEVT_INT_T2_HOST_RST_WARN	BIT(8)
-+#define   ESPI_VW_SYSEVT_INT_T2_OOB_RST_WARN	BIT(6)
-+#define ESPI_VW_SYSEVT_INT_STS			0x11c
-+#define   ESPI_VW_SYSEVT_INT_STS_HOST_RST_WARN	BIT(8)
-+#define   ESPI_VW_SYSEVT_INT_STS_OOB_RST_WARN	BIT(6)
-+#define ESPI_VW_SYSEVT1_INT_T0			0x120
-+#define   ESPI_VW_SYSEVT1_INT_T0_SUSPEND_WARN	BIT(0)
-+#define ESPI_VW_SYSEVT1_INT_T1			0x124
-+#define ESPI_VW_SYSEVT1_INT_T2			0x128
-+#define ESPI_VW_SYSEVT1_INT_STS			0x12c
-+#define   ESPI_VW_SYSEVT1_INT_STS_SUSPEND_WARN	BIT(0)
-+
-+/* collect ESPI_INT_EN bits for convenience */
-+#define ESPI_INT_EN_PERIF			\
-+	(ESPI_INT_EN_PERIF_NP_TX_ABT |		\
-+	 ESPI_INT_EN_PERIF_PC_TX_ABT |		\
-+	 ESPI_INT_EN_PERIF_NP_RX_ABT |		\
-+	 ESPI_INT_EN_PERIF_PC_RX_ABT |		\
-+	 ESPI_INT_EN_PERIF_NP_TX_ERR |		\
-+	 ESPI_INT_EN_PERIF_PC_TX_ERR |		\
-+	 ESPI_INT_EN_PERIF_NP_TX_CMPLT |	\
-+	 ESPI_INT_EN_PERIF_PC_TX_CMPLT |	\
-+	 ESPI_INT_EN_PERIF_PC_RX_CMPLT)
-+
-+#define ESPI_INT_EN_VW			\
-+	(ESPI_INT_EN_VW_SYSEVT1 |	\
-+	 ESPI_INT_EN_VW_GPIO    |	\
-+	 ESPI_INT_EN_VW_SYSEVT)
-+
-+#define ESPI_INT_EN_OOB		\
-+	(ESPI_INT_EN_OOB_RX_TMOUT |	\
-+	 ESPI_INT_EN_OOB_TX_ERR |	\
-+	 ESPI_INT_EN_OOB_TX_ABT |	\
-+	 ESPI_INT_EN_OOB_RX_ABT |	\
-+	 ESPI_INT_EN_OOB_TX_CMPLT |	\
-+	 ESPI_INT_EN_OOB_RX_CMPLT)
-+
-+#define ESPI_INT_EN_FLASH		\
-+	(ESPI_INT_EN_FLASH_TX_ERR |	\
-+	 ESPI_INT_EN_FLASH_TX_ABT |	\
-+	 ESPI_INT_EN_FLASH_RX_ABT |	\
-+	 ESPI_INT_EN_FLASH_TX_CMPLT |	\
-+	 ESPI_INT_EN_FLASH_RX_CMPLT)
-+
-+/* collect ESPI_INT_STS bits for convenience */
-+#define ESPI_INT_STS_PERIF			\
-+	(ESPI_INT_STS_PERIF_NP_TX_ABT |		\
-+	 ESPI_INT_STS_PERIF_PC_TX_ABT |		\
-+	 ESPI_INT_STS_PERIF_NP_RX_ABT |		\
-+	 ESPI_INT_STS_PERIF_PC_RX_ABT |		\
-+	 ESPI_INT_STS_PERIF_NP_TX_ERR |		\
-+	 ESPI_INT_STS_PERIF_PC_TX_ERR |		\
-+	 ESPI_INT_STS_PERIF_NP_TX_CMPLT |	\
-+	 ESPI_INT_STS_PERIF_PC_TX_CMPLT |	\
-+	 ESPI_INT_STS_PERIF_PC_RX_CMPLT)
-+
-+#define ESPI_INT_STS_VW			\
-+	(ESPI_INT_STS_VW_SYSEVT1 |	\
-+	 ESPI_INT_STS_VW_GPIO    |	\
-+	 ESPI_INT_STS_VW_SYSEVT)
-+
-+#define ESPI_INT_STS_OOB		\
-+	(ESPI_INT_STS_OOB_RX_TMOUT |	\
-+	 ESPI_INT_STS_OOB_TX_ERR |	\
-+	 ESPI_INT_STS_OOB_TX_ABT |	\
-+	 ESPI_INT_STS_OOB_RX_ABT |	\
-+	 ESPI_INT_STS_OOB_TX_CMPLT |	\
-+	 ESPI_INT_STS_OOB_RX_CMPLT)
-+
-+#define ESPI_INT_STS_FLASH		\
-+	(ESPI_INT_STS_FLASH_TX_ERR |	\
-+	 ESPI_INT_STS_FLASH_TX_ABT |	\
-+	 ESPI_INT_STS_FLASH_RX_ABT |	\
-+	 ESPI_INT_STS_FLASH_TX_CMPLT |	\
-+	 ESPI_INT_STS_FLASH_RX_CMPLT)
-+
-+/* consistent with DTS property "flash-safs-mode" */
-+enum ast2500_safs_mode {
-+	SAFS_MODE_MIX = 0x0,
-+	SAFS_MODE_SW,
-+	SAFS_MODES,
-+};
-+
-+#endif
-diff --git a/drivers/soc/aspeed/ast2600-espi.c b/drivers/soc/aspeed/ast2600-espi.c
-new file mode 100644
-index 000000000..283c1eabb
---- /dev/null
-+++ b/drivers/soc/aspeed/ast2600-espi.c
-@@ -0,0 +1,2157 @@
-+// SPDX-License-Identifier: GPL-2.0+
-+/*
-+ * Copyright 2023 Aspeed Technology Inc.
-+ */
-+#include <linux/io.h>
-+#include <linux/irq.h>
-+#include <linux/clk.h>
-+#include <linux/sizes.h>
-+#include <linux/module.h>
-+#include <linux/bitfield.h>
-+#include <linux/of_device.h>
-+#include <linux/interrupt.h>
-+#include <linux/platform_device.h>
-+#include <linux/miscdevice.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/uaccess.h>
-+#include <linux/vmalloc.h>
-+#include <linux/poll.h>
-+#include <linux/delay.h>
-+#include <linux/reset.h>
-+
-+#include "ast2600-espi.h"
-+
-+#define DEVICE_NAME		"aspeed-espi"
-+
-+#define PERIF_MCYC_ALIGN	SZ_64K
-+#define PERIF_MMBI_ALIGN	SZ_64K
-+#define PERIF_MMBI_INST_NUM	8
-+
-+#define OOB_DMA_RPTR_KEY	0x45538073
-+#define OOB_DMA_DESC_NUM	8
-+#define OOB_DMA_DESC_CUSTOM	0x4
-+
-+#define FLASH_SAFS_ALIGN	SZ_16M
-+
-+struct ast2600_espi_perif_mmbi {
-+	void *b2h_virt;
-+	void *h2b_virt;
-+	dma_addr_t b2h_addr;
-+	dma_addr_t h2b_addr;
-+	struct miscdevice b2h_mdev;
-+	struct miscdevice h2b_mdev;
-+	bool host_rwp_update;
-+	wait_queue_head_t wq;
-+	struct ast2600_espi_perif *perif;
-+};
-+
-+struct ast2600_espi_perif {
-+	struct {
-+		bool enable;
-+		int irq;
-+		void *virt;
-+		dma_addr_t taddr;
-+		uint32_t saddr;
-+		uint32_t size;
-+		uint32_t inst_size;
-+		struct ast2600_espi_perif_mmbi inst[PERIF_MMBI_INST_NUM];
-+	} mmbi;
-+
-+	struct {
-+		bool enable;
-+		void *virt;
-+		dma_addr_t taddr;
-+		uint32_t saddr;
-+		uint32_t size;
-+	} mcyc;
-+
-+	struct {
-+		bool enable;
-+		void *np_tx_virt;
-+		dma_addr_t np_tx_addr;
-+		void *pc_tx_virt;
-+		dma_addr_t pc_tx_addr;
-+		void *pc_rx_virt;
-+		dma_addr_t pc_rx_addr;
-+	} dma;
-+
-+	bool rx_ready;
-+	wait_queue_head_t wq;
-+
-+	spinlock_t lock;
-+	struct mutex np_tx_mtx;
-+	struct mutex pc_tx_mtx;
-+	struct mutex pc_rx_mtx;
-+
-+	struct miscdevice mdev;
-+};
-+
-+struct ast2600_espi_vw {
-+	struct {
-+		bool hw_mode;
-+		uint32_t dir;
-+		uint32_t val;
-+	} gpio;
-+
-+	struct miscdevice mdev;
-+};
-+
-+struct ast2600_espi_oob_dma_tx_desc {
-+	uint32_t data_addr;
-+	uint8_t cyc;
-+	uint16_t tag : 4;
-+	uint16_t len : 12;
-+	uint8_t msg_type : 3;
-+	uint8_t raz0 : 1;
-+	uint8_t pec : 1;
-+	uint8_t int_en : 1;
-+	uint8_t pause : 1;
-+	uint8_t raz1 : 1;
-+	uint32_t raz2;
-+	uint32_t raz3;
-+} __packed;
-+
-+struct ast2600_espi_oob_dma_rx_desc {
-+	uint32_t data_addr;
-+	uint8_t cyc;
-+	uint16_t tag : 4;
-+	uint16_t len : 12;
-+	uint8_t raz : 7;
-+	uint8_t dirty : 1;
-+} __packed;
-+
-+struct ast2600_espi_oob {
-+	struct {
-+		bool enable;
-+		struct ast2600_espi_oob_dma_tx_desc *txd_virt;
-+		dma_addr_t txd_addr;
-+		struct ast2600_espi_oob_dma_rx_desc *rxd_virt;
-+		dma_addr_t rxd_addr;
-+		void *tx_virt;
-+		dma_addr_t tx_addr;
-+		void *rx_virt;
-+		dma_addr_t rx_addr;
-+	} dma;
-+
-+	bool rx_ready;
-+	wait_queue_head_t wq;
-+
-+	spinlock_t lock;
-+	struct mutex tx_mtx;
-+	struct mutex rx_mtx;
-+
-+	struct miscdevice mdev;
-+};
-+
-+struct ast2600_espi_flash {
-+	struct {
-+		uint32_t mode;
-+		phys_addr_t taddr;
-+		uint32_t size;
-+	} safs;
-+
-+	struct {
-+		bool enable;
-+		void *tx_virt;
-+		dma_addr_t tx_addr;
-+		void *rx_virt;
-+		dma_addr_t rx_addr;
-+	} dma;
-+
-+	bool rx_ready;
-+	wait_queue_head_t wq;
-+
-+	spinlock_t lock;
-+	struct mutex rx_mtx;
-+	struct mutex tx_mtx;
-+
-+	struct miscdevice mdev;
-+};
-+
-+struct ast2600_espi {
-+	struct device *dev;
-+	void __iomem *regs;
-+	struct reset_control *rst;
-+	struct clk *clk;
-+	int irq;
-+
-+	struct ast2600_espi_perif perif;
-+	struct ast2600_espi_vw vw;
-+	struct ast2600_espi_oob oob;
-+	struct ast2600_espi_flash flash;
-+};
-+
-+/* peripheral channel (CH0) */
-+static int ast2600_espi_mmbi_b2h_mmap(struct file *fp, struct vm_area_struct *vma)
-+{
-+	struct ast2600_espi_perif_mmbi *mmbi;
-+	struct ast2600_espi_perif *perif;
-+	struct ast2600_espi *espi;
-+	unsigned long vm_size;
-+	pgprot_t prot;
-+
-+	mmbi = container_of(fp->private_data, struct ast2600_espi_perif_mmbi, b2h_mdev);
-+
-+	perif = mmbi->perif;
-+
-+	espi = container_of(perif, struct ast2600_espi, perif);
-+
-+	vm_size = vma->vm_end - vma->vm_start;
-+	prot = vma->vm_page_prot;
-+
-+	if (((vma->vm_pgoff << PAGE_SHIFT) + vm_size) > (SZ_4K << perif->mmbi.inst_size))
-+		return -EINVAL;
-+
-+	prot = pgprot_noncached(prot);
-+
-+	if (remap_pfn_range(vma, vma->vm_start,
-+			    (mmbi->b2h_addr >> PAGE_SHIFT) + vma->vm_pgoff,
-+			    vm_size, prot))
-+		return -EAGAIN;
-+
-+	return 0;
-+}
-+
-+static int ast2600_espi_mmbi_h2b_mmap(struct file *fp, struct vm_area_struct *vma)
-+{
-+	struct ast2600_espi_perif_mmbi *mmbi;
-+	struct ast2600_espi_perif *perif;
-+	struct ast2600_espi *espi;
-+	unsigned long vm_size;
-+	pgprot_t prot;
-+
-+	mmbi = container_of(fp->private_data, struct ast2600_espi_perif_mmbi, h2b_mdev);
-+
-+	perif = mmbi->perif;
-+
-+	espi = container_of(perif, struct ast2600_espi, perif);
-+
-+	vm_size = vma->vm_end - vma->vm_start;
-+	prot = vma->vm_page_prot;
-+
-+	if (((vma->vm_pgoff << PAGE_SHIFT) + vm_size) > (SZ_4K << perif->mmbi.inst_size))
-+		return -EINVAL;
-+
-+	prot = pgprot_noncached(prot);
-+
-+	if (remap_pfn_range(vma, vma->vm_start,
-+			    (mmbi->h2b_addr >> PAGE_SHIFT) + vma->vm_pgoff,
-+			    vm_size, prot))
-+		return -EAGAIN;
-+
-+	return 0;
-+}
-+
-+static __poll_t ast2600_espi_mmbi_h2b_poll(struct file *fp, struct poll_table_struct *pt)
-+{
-+	struct ast2600_espi_perif_mmbi *mmbi;
-+
-+	mmbi = container_of(fp->private_data, struct ast2600_espi_perif_mmbi, h2b_mdev);
-+
-+	poll_wait(fp, &mmbi->wq, pt);
-+
-+	if (!mmbi->host_rwp_update)
-+		return 0;
-+
-+	mmbi->host_rwp_update = false;
-+
-+	return EPOLLIN;
-+}
-+
-+static long ast2600_espi_perif_pc_get_rx(struct file *fp,
-+					 struct ast2600_espi_perif *perif,
-+					 struct aspeed_espi_ioc *ioc)
-+{
-+	uint32_t reg, cyc, tag, len;
-+	struct ast2600_espi *espi;
-+	struct espi_comm_hdr *hdr;
-+	unsigned long flags;
-+	uint32_t pkt_len;
-+	uint8_t *pkt;
-+	int i, rc;
-+
-+	espi = container_of(perif, struct ast2600_espi, perif);
-+
-+	if (fp->f_flags & O_NONBLOCK) {
-+		if (!mutex_trylock(&perif->pc_rx_mtx))
-+			return -EAGAIN;
-+
-+		if (!perif->rx_ready) {
-+			rc = -ENODATA;
-+			goto unlock_mtx_n_out;
-+		}
-+	} else {
-+		mutex_lock(&perif->pc_rx_mtx);
-+
-+		if (!perif->rx_ready) {
-+			rc = wait_event_interruptible(perif->wq, perif->rx_ready);
-+			if (rc == -ERESTARTSYS) {
-+				rc = -EINTR;
-+				goto unlock_mtx_n_out;
-+			}
-+		}
-+	}
-+
-+	/*
-+	 * common header (i.e. cycle type, tag, and length)
-+	 * part is written to HW registers
-+	 */
-+	reg = readl(espi->regs + ESPI_PERIF_PC_RX_CTRL);
-+	cyc = FIELD_GET(ESPI_PERIF_PC_RX_CTRL_CYC, reg);
-+	tag = FIELD_GET(ESPI_PERIF_PC_RX_CTRL_TAG, reg);
-+	len = FIELD_GET(ESPI_PERIF_PC_RX_CTRL_LEN, reg);
-+
-+	/*
-+	 * calculate the length of the rest part of the
-+	 * eSPI packet to be read from HW and copied to
-+	 * user space.
-+	 */
-+	switch (cyc) {
-+	case ESPI_PERIF_MSG:
-+		pkt_len = sizeof(struct espi_perif_msg);
-+		break;
-+	case ESPI_PERIF_MSG_D:
-+		pkt_len = ((len) ? len : ESPI_MAX_PLD_LEN) +
-+			  sizeof(struct espi_perif_msg);
-+		break;
-+	case ESPI_PERIF_SUC_CMPLT_D_MIDDLE:
-+	case ESPI_PERIF_SUC_CMPLT_D_FIRST:
-+	case ESPI_PERIF_SUC_CMPLT_D_LAST:
-+	case ESPI_PERIF_SUC_CMPLT_D_ONLY:
-+		pkt_len = ((len) ? len : ESPI_MAX_PLD_LEN) +
-+			  sizeof(struct espi_perif_cmplt);
-+		break;
-+	case ESPI_PERIF_SUC_CMPLT:
-+	case ESPI_PERIF_UNSUC_CMPLT:
-+		pkt_len = sizeof(struct espi_perif_cmplt);
-+		break;
-+	default:
-+		rc = -EFAULT;
-+		goto unlock_mtx_n_out;
-+	}
-+
-+	if (ioc->pkt_len < pkt_len) {
-+		rc = -EINVAL;
-+		goto unlock_mtx_n_out;
-+	}
-+
-+	pkt = vmalloc(pkt_len);
-+	if (!pkt) {
-+		rc = -ENOMEM;
-+		goto unlock_mtx_n_out;
-+	}
-+
-+	hdr = (struct espi_comm_hdr *)pkt;
-+	hdr->cyc = cyc;
-+	hdr->tag = tag;
-+	hdr->len_h = len >> 8;
-+	hdr->len_l = len & 0xff;
-+
-+	if (perif->dma.enable) {
-+		memcpy(hdr + 1, perif->dma.pc_rx_virt, pkt_len - sizeof(*hdr));
-+	} else {
-+		for (i = sizeof(*hdr); i < pkt_len; ++i)
-+			reg = readl(espi->regs + ESPI_PERIF_PC_RX_DATA) & 0xff;
-+	}
-+
-+	if (copy_to_user((void __user *)ioc->pkt, pkt, pkt_len)) {
-+		rc = -EFAULT;
-+		goto free_n_out;
-+	}
-+
-+	spin_lock_irqsave(&perif->lock, flags);
-+
-+	writel(ESPI_PERIF_PC_RX_CTRL_SERV_PEND, espi->regs + ESPI_PERIF_PC_RX_CTRL);
-+	perif->rx_ready = 0;
-+
-+	spin_unlock_irqrestore(&perif->lock, flags);
-+
-+	rc = 0;
-+
-+free_n_out:
-+	vfree(pkt);
-+
-+unlock_mtx_n_out:
-+	mutex_unlock(&perif->pc_rx_mtx);
-+
-+	return rc;
-+}
-+
-+static long ast2600_espi_perif_pc_put_tx(struct file *fp,
-+					 struct ast2600_espi_perif *perif,
-+					 struct aspeed_espi_ioc *ioc)
-+{
-+	uint32_t reg, cyc, tag, len;
-+	struct ast2600_espi *espi;
-+	struct espi_comm_hdr *hdr;
-+	uint8_t *pkt;
-+	int i, rc;
-+
-+	espi = container_of(perif, struct ast2600_espi, perif);
-+
-+	if (!mutex_trylock(&perif->pc_tx_mtx))
-+		return -EAGAIN;
-+
-+	reg = readl(espi->regs + ESPI_PERIF_PC_TX_CTRL);
-+	if (reg & ESPI_PERIF_PC_TX_CTRL_TRIG_PEND) {
-+		rc = -EBUSY;
-+		goto unlock_n_out;
-+	}
-+
-+	pkt = vmalloc(ioc->pkt_len);
-+	if (!pkt) {
-+		rc = -ENOMEM;
-+		goto unlock_n_out;
-+	}
-+
-+	hdr = (struct espi_comm_hdr *)pkt;
-+
-+	if (copy_from_user(pkt, (void __user *)ioc->pkt, ioc->pkt_len)) {
-+		rc = -EFAULT;
-+		goto free_n_out;
-+	}
-+
-+	/*
-+	 * common header (i.e. cycle type, tag, and length)
-+	 * part is written to HW registers
-+	 */
-+	if (perif->dma.enable) {
-+		memcpy(perif->dma.pc_tx_virt, hdr + 1, ioc->pkt_len - sizeof(*hdr));
-+		dma_wmb();
-+	} else {
-+		for (i = sizeof(*hdr); i < ioc->pkt_len; ++i)
-+			writel(pkt[i], espi->regs + ESPI_PERIF_PC_TX_DATA);
-+	}
-+
-+	cyc = hdr->cyc;
-+	tag = hdr->tag;
-+	len = (hdr->len_h << 8) | (hdr->len_l & 0xff);
-+
-+	reg = FIELD_PREP(ESPI_PERIF_PC_TX_CTRL_CYC, cyc)
-+	      | FIELD_PREP(ESPI_PERIF_PC_TX_CTRL_TAG, tag)
-+	      | FIELD_PREP(ESPI_PERIF_PC_TX_CTRL_LEN, len)
-+	      | ESPI_PERIF_PC_TX_CTRL_TRIG_PEND;
-+	writel(reg, espi->regs + ESPI_PERIF_PC_TX_CTRL);
-+
-+	rc = 0;
-+
-+free_n_out:
-+	vfree(pkt);
-+
-+unlock_n_out:
-+	mutex_unlock(&perif->pc_tx_mtx);
-+
-+	return rc;
-+}
-+
-+static long ast2600_espi_perif_np_put_tx(struct file *fp,
-+					 struct ast2600_espi_perif *perif,
-+					 struct aspeed_espi_ioc *ioc)
-+{
-+	uint32_t reg, cyc, tag, len;
-+	struct ast2600_espi *espi;
-+	struct espi_comm_hdr *hdr;
-+	uint8_t *pkt;
-+	int i, rc;
-+
-+	espi = container_of(perif, struct ast2600_espi, perif);
-+
-+	if (!mutex_trylock(&perif->np_tx_mtx))
-+		return -EAGAIN;
-+
-+	reg = readl(espi->regs + ESPI_PERIF_NP_TX_CTRL);
-+	if (reg & ESPI_PERIF_NP_TX_CTRL_TRIG_PEND) {
-+		rc = -EBUSY;
-+		goto unlock_n_out;
-+	}
-+
-+	pkt = vmalloc(ioc->pkt_len);
-+	if (!pkt) {
-+		rc = -ENOMEM;
-+		goto unlock_n_out;
-+	}
-+
-+	hdr = (struct espi_comm_hdr *)pkt;
-+
-+	if (copy_from_user(pkt, (void __user *)ioc->pkt, ioc->pkt_len)) {
-+		rc = -EFAULT;
-+		goto free_n_out;
-+	}
-+
-+	/*
-+	 * common header (i.e. cycle type, tag, and length)
-+	 * part is written to HW registers
-+	 */
-+	if (perif->dma.enable) {
-+		memcpy(perif->dma.np_tx_virt, hdr + 1, ioc->pkt_len - sizeof(*hdr));
-+		dma_wmb();
-+	} else {
-+		for (i = sizeof(*hdr); i < ioc->pkt_len; ++i)
-+			writel(pkt[i], espi->regs + ESPI_PERIF_NP_TX_DATA);
-+	}
-+
-+	cyc = hdr->cyc;
-+	tag = hdr->tag;
-+	len = (hdr->len_h << 8) | (hdr->len_l & 0xff);
-+
-+	reg = FIELD_PREP(ESPI_PERIF_NP_TX_CTRL_CYC, cyc)
-+	      | FIELD_PREP(ESPI_PERIF_NP_TX_CTRL_TAG, tag)
-+	      | FIELD_PREP(ESPI_PERIF_NP_TX_CTRL_LEN, len)
-+	      | ESPI_PERIF_NP_TX_CTRL_TRIG_PEND;
-+	writel(reg, espi->regs + ESPI_PERIF_NP_TX_CTRL);
-+
-+	rc = 0;
-+
-+free_n_out:
-+	vfree(pkt);
-+
-+unlock_n_out:
-+	mutex_unlock(&perif->np_tx_mtx);
-+
-+	return rc;
-+}
-+
-+static long ast2600_espi_perif_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
-+{
-+	struct ast2600_espi_perif *perif;
-+	struct aspeed_espi_ioc ioc;
-+
-+	perif = container_of(fp->private_data, struct ast2600_espi_perif, mdev);
-+
-+	if (copy_from_user(&ioc, (void __user *)arg, sizeof(ioc)))
-+		return -EFAULT;
-+
-+	if (ioc.pkt_len > ESPI_MAX_PKT_LEN)
-+		return -EINVAL;
-+
-+	switch (cmd) {
-+	case ASPEED_ESPI_PERIF_PC_GET_RX:
-+		return ast2600_espi_perif_pc_get_rx(fp, perif, &ioc);
-+	case ASPEED_ESPI_PERIF_PC_PUT_TX:
-+		return ast2600_espi_perif_pc_put_tx(fp, perif, &ioc);
-+	case ASPEED_ESPI_PERIF_NP_PUT_TX:
-+		return ast2600_espi_perif_np_put_tx(fp, perif, &ioc);
-+	default:
-+		break;
-+	};
-+
-+	return -EINVAL;
-+}
-+
-+static int ast2600_espi_perif_mmap(struct file *fp, struct vm_area_struct *vma)
-+{
-+	struct ast2600_espi_perif *perif;
-+	unsigned long vm_size;
-+	pgprot_t vm_prot;
-+
-+	perif = container_of(fp->private_data, struct ast2600_espi_perif, mdev);
-+	if (!perif->mcyc.enable)
-+		return -EPERM;
-+
-+	vm_size = vma->vm_end - vma->vm_start;
-+	vm_prot = vma->vm_page_prot;
-+
-+	if (((vma->vm_pgoff << PAGE_SHIFT) + vm_size) > perif->mcyc.size)
-+		return -EINVAL;
-+
-+	vm_prot = pgprot_noncached(vm_prot);
-+
-+	if (remap_pfn_range(vma, vma->vm_start,
-+			    (perif->mcyc.taddr >> PAGE_SHIFT) + vma->vm_pgoff,
-+			    vm_size, vm_prot))
-+		return -EAGAIN;
-+
-+	return 0;
-+}
-+
-+static const struct file_operations ast2600_espi_mmbi_b2h_fops = {
-+	.owner = THIS_MODULE,
-+	.mmap = ast2600_espi_mmbi_b2h_mmap,
-+};
-+
-+static const struct file_operations ast2600_espi_mmbi_h2b_fops = {
-+	.owner = THIS_MODULE,
-+	.mmap = ast2600_espi_mmbi_h2b_mmap,
-+	.poll = ast2600_espi_mmbi_h2b_poll,
-+};
-+
-+static const struct file_operations ast2600_espi_perif_fops = {
-+	.owner = THIS_MODULE,
-+	.mmap = ast2600_espi_perif_mmap,
-+	.unlocked_ioctl = ast2600_espi_perif_ioctl,
-+};
-+
-+static irqreturn_t ast2600_espi_perif_mmbi_isr(int irq, void *arg)
-+{
-+	struct ast2600_espi_perif_mmbi *mmbi;
-+	struct ast2600_espi_perif *perif;
-+	struct ast2600_espi *espi;
-+	uint32_t sts, tmp;
-+	uint32_t *p;
-+	int i;
-+
-+	espi = (struct ast2600_espi *)arg;
-+
-+	perif = &espi->perif;
-+
-+	sts = readl(espi->regs + ESPI_MMBI_INT_STS);
-+	if (!sts)
-+		return IRQ_NONE;
-+
-+	for (i = 0, tmp = sts; i < PERIF_MMBI_INST_NUM; ++i, tmp >>= 2) {
-+		if (!(tmp & 0x3))
-+			continue;
-+
-+		mmbi = &perif->mmbi.inst[i];
-+
-+		p = (uint32_t *)mmbi->h2b_virt;
-+		p[0] = readl(espi->regs + ESPI_MMBI_HOST_RWP(i));
-+		p[1] = readl(espi->regs + ESPI_MMBI_HOST_RWP(i) + 4);
-+
-+		mmbi->host_rwp_update = true;
-+
-+		wake_up_interruptible(&mmbi->wq);
-+	}
-+
-+	writel(sts, espi->regs + ESPI_MMBI_INT_STS);
-+
-+	return IRQ_HANDLED;
-+}
-+
-+static void ast2600_espi_perif_isr(struct ast2600_espi *espi)
-+{
-+	struct ast2600_espi_perif *perif;
-+	unsigned long flags;
-+	uint32_t sts;
-+
-+	perif = &espi->perif;
-+
-+	sts = readl(espi->regs + ESPI_INT_STS);
-+
-+	if (sts & ESPI_INT_STS_PERIF_PC_RX_CMPLT) {
-+		writel(ESPI_INT_STS_PERIF_PC_RX_CMPLT, espi->regs + ESPI_INT_STS);
-+
-+		spin_lock_irqsave(&perif->lock, flags);
-+		perif->rx_ready = true;
-+		spin_unlock_irqrestore(&perif->lock, flags);
-+
-+		wake_up_interruptible(&perif->wq);
-+	}
-+}
-+
-+static void ast2600_espi_perif_sw_reset(struct ast2600_espi *espi)
-+{
-+	struct device *dev;
-+	uint32_t reg;
-+
-+	dev = espi->dev;
-+
-+	reg = readl(espi->regs + ESPI_CTRL);
-+	reg &= ~(ESPI_CTRL_PERIF_NP_TX_SW_RST
-+		 | ESPI_CTRL_PERIF_NP_RX_SW_RST
-+		 | ESPI_CTRL_PERIF_PC_TX_SW_RST
-+		 | ESPI_CTRL_PERIF_PC_RX_SW_RST
-+		 | ESPI_CTRL_PERIF_NP_TX_DMA_EN
-+		 | ESPI_CTRL_PERIF_PC_TX_DMA_EN
-+		 | ESPI_CTRL_PERIF_PC_RX_DMA_EN
-+		 | ESPI_CTRL_PERIF_SW_RDY);
-+	writel(reg, espi->regs + ESPI_CTRL);
-+
-+	udelay(1);
-+
-+	reg |= (ESPI_CTRL_PERIF_NP_TX_SW_RST
-+		| ESPI_CTRL_PERIF_NP_RX_SW_RST
-+		| ESPI_CTRL_PERIF_PC_TX_SW_RST
-+		| ESPI_CTRL_PERIF_PC_RX_SW_RST);
-+	writel(reg, espi->regs + ESPI_CTRL);
-+}
-+
-+static void ast2600_espi_perif_reset(struct ast2600_espi *espi)
-+{
-+	struct ast2600_espi_perif *perif;
-+	struct device *dev;
-+	uint32_t reg, mask;
-+
-+	dev = espi->dev;
-+
-+	perif = &espi->perif;
-+
-+	writel(ESPI_INT_EN_PERIF, espi->regs + ESPI_INT_EN_CLR);
-+	writel(ESPI_INT_STS_PERIF, espi->regs + ESPI_INT_STS);
-+
-+	writel(0x0, espi->regs + ESPI_MMBI_INT_EN);
-+	writel(0xffffffff, espi->regs + ESPI_MMBI_INT_STS);
-+
-+	reg = readl(espi->regs + ESPI_CTRL2);
-+	reg &= ~(ESPI_CTRL2_MCYC_RD_DIS_WDT | ESPI_CTRL2_MCYC_WR_DIS_WDT);
-+	writel(reg, espi->regs + ESPI_CTRL2);
-+
-+	reg = readl(espi->regs + ESPI_CTRL);
-+	reg &= ~(ESPI_CTRL_PERIF_NP_TX_DMA_EN
-+		 | ESPI_CTRL_PERIF_PC_TX_DMA_EN
-+		 | ESPI_CTRL_PERIF_PC_RX_DMA_EN
-+		 | ESPI_CTRL_PERIF_SW_RDY);
-+	writel(reg, espi->regs + ESPI_CTRL);
-+
-+	if (perif->mmbi.enable) {
-+		reg = readl(espi->regs + ESPI_MMBI_CTRL);
-+		reg &= ~(ESPI_MMBI_CTRL_EN);
-+		writel(reg, espi->regs + ESPI_MMBI_CTRL);
-+
-+		mask = ~(perif->mmbi.size - 1);
-+		writel(mask, espi->regs + ESPI_PERIF_MMBI_MASK);
-+		writel(perif->mmbi.saddr, espi->regs + ESPI_PERIF_MMBI_SADDR);
-+		writel(perif->mmbi.taddr, espi->regs + ESPI_PERIF_MMBI_TADDR);
-+
-+		writel(0xffffffff, espi->regs + ESPI_MMBI_INT_EN);
-+
-+		reg = FIELD_PREP(ESPI_MMBI_CTRL_INST_SZ, perif->mmbi.inst_size)
-+			| FIELD_PREP(ESPI_MMBI_CTRL_TOTAL_SZ, perif->mmbi.inst_size)
-+			| ESPI_MMBI_CTRL_EN;
-+		writel(reg, espi->regs + ESPI_MMBI_CTRL);
-+
-+		reg = readl(espi->regs + ESPI_CTRL2) & ~(ESPI_CTRL2_MMBI_RD_DIS | ESPI_CTRL2_MMBI_WR_DIS);
-+		writel(reg, espi->regs + ESPI_CTRL2);
-+	}
-+
-+	if (perif->mcyc.enable) {
-+		mask = ~(perif->mcyc.size - 1);
-+		writel(mask, espi->regs + ESPI_PERIF_MCYC_MASK);
-+		writel(perif->mcyc.saddr, espi->regs + ESPI_PERIF_MCYC_SADDR);
-+		writel(perif->mcyc.taddr, espi->regs + ESPI_PERIF_MCYC_TADDR);
-+
-+		reg = readl(espi->regs + ESPI_CTRL2) & ~(ESPI_CTRL2_MCYC_RD_DIS | ESPI_CTRL2_MCYC_WR_DIS);
-+		writel(reg, espi->regs + ESPI_CTRL2);
-+	}
-+
-+	if (perif->dma.enable) {
-+		writel(perif->dma.np_tx_addr, espi->regs + ESPI_PERIF_NP_TX_DMA);
-+		writel(perif->dma.pc_tx_addr, espi->regs + ESPI_PERIF_PC_TX_DMA);
-+		writel(perif->dma.pc_rx_addr, espi->regs + ESPI_PERIF_PC_RX_DMA);
-+
-+		reg = readl(espi->regs + ESPI_CTRL)
-+		      | ESPI_CTRL_PERIF_NP_TX_DMA_EN
-+		      | ESPI_CTRL_PERIF_PC_TX_DMA_EN
-+		      | ESPI_CTRL_PERIF_PC_RX_DMA_EN;
-+		writel(reg, espi->regs + ESPI_CTRL);
-+	}
-+
-+	writel(ESPI_INT_EN_PERIF_PC_RX_CMPLT, espi->regs + ESPI_INT_EN);
-+
-+	reg = readl(espi->regs + ESPI_CTRL) | ESPI_CTRL_PERIF_SW_RDY;
-+	writel(reg, espi->regs + ESPI_CTRL);
-+}
-+
-+static int ast2600_espi_perif_probe(struct ast2600_espi *espi)
-+{
-+	struct ast2600_espi_perif_mmbi *mmbi;
-+	struct ast2600_espi_perif *perif;
-+	struct platform_device *pdev;
-+	struct device *dev;
-+	int i, rc;
-+
-+	dev = espi->dev;
-+
-+	perif = &espi->perif;
-+
-+	init_waitqueue_head(&perif->wq);
-+
-+	spin_lock_init(&perif->lock);
-+
-+	mutex_init(&perif->np_tx_mtx);
-+	mutex_init(&perif->pc_tx_mtx);
-+	mutex_init(&perif->pc_rx_mtx);
-+
-+	perif->mmbi.enable = of_property_read_bool(dev->of_node, "perif-mmbi-enable");
-+	if (perif->mmbi.enable) {
-+		pdev = container_of(dev, struct platform_device, dev);
-+
-+		perif->mmbi.irq = platform_get_irq(pdev, 1);
-+		if (perif->mmbi.irq < 0) {
-+			dev_err(dev, "cannot get MMBI IRQ number\n");
-+			return -ENODEV;
-+		}
-+
-+		rc = of_property_read_u32(dev->of_node, "perif-mmbi-src-addr", &perif->mmbi.saddr);
-+		if (rc || !IS_ALIGNED(perif->mmbi.saddr, PERIF_MMBI_ALIGN)) {
-+			dev_err(dev, "cannot get 64KB-aligned MMBI host address\n");
-+			return -ENODEV;
-+		}
-+
-+		rc = of_property_read_u32(dev->of_node, "perif-mmbi-instance-size", &perif->mmbi.inst_size);
-+		if (rc || perif->mmbi.inst_size >= MMBI_INST_SIZE_TYPES) {
-+			dev_err(dev, "cannot get valid MMBI instance size\n");
-+			return -EINVAL;
-+		}
-+
-+		perif->mmbi.size = (SZ_8K << perif->mmbi.inst_size) * PERIF_MMBI_INST_NUM;
-+		perif->mmbi.virt = dmam_alloc_coherent(dev, perif->mmbi.size,
-+						       &perif->mmbi.taddr, GFP_KERNEL);
-+		if (!perif->mmbi.virt) {
-+			dev_err(dev, "cannot allocate MMBI\n");
-+			return -ENOMEM;
-+		}
-+
-+		for (i = 0; i < PERIF_MMBI_INST_NUM; ++i) {
-+			mmbi = &perif->mmbi.inst[i];
-+
-+			init_waitqueue_head(&mmbi->wq);
-+
-+			mmbi->perif = perif;
-+			mmbi->host_rwp_update = false;
-+
-+			mmbi->b2h_virt = perif->mmbi.virt + ((SZ_4K << perif->mmbi.inst_size) * i);
-+			mmbi->b2h_addr = perif->mmbi.taddr + ((SZ_4K << perif->mmbi.inst_size) * i);
-+			mmbi->b2h_mdev.parent = dev;
-+			mmbi->b2h_mdev.minor = MISC_DYNAMIC_MINOR;
-+			mmbi->b2h_mdev.name = devm_kasprintf(dev, GFP_KERNEL, "%s-mmbi-b2h%d", DEVICE_NAME, i);
-+			mmbi->b2h_mdev.fops = &ast2600_espi_mmbi_b2h_fops;
-+			rc = misc_register(&mmbi->b2h_mdev);
-+			if (rc) {
-+				dev_err(dev, "cannot register device %s\n", mmbi->b2h_mdev.name);
-+				return rc;
-+			}
-+
-+			mmbi->h2b_virt = perif->mmbi.virt + ((SZ_4K << perif->mmbi.inst_size) * (i + PERIF_MMBI_INST_NUM));
-+			mmbi->h2b_addr = perif->mmbi.taddr + ((SZ_4K << perif->mmbi.inst_size) * (i + PERIF_MMBI_INST_NUM));
-+			mmbi->h2b_mdev.parent = dev;
-+			mmbi->h2b_mdev.minor = MISC_DYNAMIC_MINOR;
-+			mmbi->h2b_mdev.name = devm_kasprintf(dev, GFP_KERNEL, "%s-mmbi-h2b%d", DEVICE_NAME, i);
-+			mmbi->h2b_mdev.fops = &ast2600_espi_mmbi_h2b_fops;
-+			rc = misc_register(&mmbi->h2b_mdev);
-+			if (rc) {
-+				dev_err(dev, "cannot register device %s\n", mmbi->h2b_mdev.name);
-+				return rc;
-+			}
-+		}
-+	}
-+
-+	perif->mcyc.enable = of_property_read_bool(dev->of_node, "perif-mcyc-enable");
-+	if (perif->mcyc.enable) {
-+		if (perif->mmbi.enable) {
-+			dev_err(dev, "cannot enable memory cycle, occupied by MMBI\n");
-+			return -EPERM;
-+		}
-+
-+		rc = of_property_read_u32(dev->of_node, "perif-mcyc-src-addr", &perif->mcyc.saddr);
-+		if (rc || !IS_ALIGNED(perif->mcyc.saddr, PERIF_MCYC_ALIGN)) {
-+			dev_err(dev, "cannot get 64KB-aligned memory cycle host address\n");
-+			return -ENODEV;
-+		}
-+
-+		rc = of_property_read_u32(dev->of_node, "perif-mcyc-size", &perif->mcyc.size);
-+		if (rc || !IS_ALIGNED(perif->mcyc.size, PERIF_MCYC_ALIGN)) {
-+			dev_err(dev, "cannot get 64KB-aligned memory cycle size\n");
-+			return -EINVAL;
-+		}
-+
-+		perif->mcyc.virt = dmam_alloc_coherent(dev, perif->mcyc.size,
-+						       &perif->mcyc.taddr, GFP_KERNEL);
-+		if (!perif->mcyc.virt) {
-+			dev_err(dev, "cannot allocate memory cycle\n");
-+			return -ENOMEM;
-+		}
-+	}
-+
-+	perif->dma.enable = of_property_read_bool(dev->of_node, "perif-dma-mode");
-+	if (perif->dma.enable) {
-+		perif->dma.pc_tx_virt = dmam_alloc_coherent(dev, PAGE_SIZE,
-+							    &perif->dma.pc_tx_addr, GFP_KERNEL);
-+		if (!perif->dma.pc_tx_virt) {
-+			dev_err(dev, "cannot allocate posted TX DMA buffer\n");
-+			return -ENOMEM;
-+		}
-+
-+		perif->dma.pc_rx_virt = dmam_alloc_coherent(dev, PAGE_SIZE,
-+							    &perif->dma.pc_rx_addr, GFP_KERNEL);
-+		if (!perif->dma.pc_rx_virt) {
-+			dev_err(dev, "cannot allocate posted RX DMA buffer\n");
-+			return -ENOMEM;
-+		}
-+
-+		perif->dma.np_tx_virt = dmam_alloc_coherent(dev, PAGE_SIZE,
-+							    &perif->dma.np_tx_addr, GFP_KERNEL);
-+		if (!perif->dma.np_tx_virt) {
-+			dev_err(dev, "cannot allocate non-posted TX DMA buffer\n");
-+			return -ENOMEM;
-+		}
-+	}
-+
-+	perif->mdev.parent = dev;
-+	perif->mdev.minor = MISC_DYNAMIC_MINOR;
-+	perif->mdev.name = devm_kasprintf(dev, GFP_KERNEL, "%s-peripheral", DEVICE_NAME);
-+	perif->mdev.fops = &ast2600_espi_perif_fops;
-+	rc = misc_register(&perif->mdev);
-+	if (rc) {
-+		dev_err(dev, "cannot register device %s\n", perif->mdev.name);
-+		return rc;
-+	}
-+
-+	ast2600_espi_perif_reset(espi);
-+
-+	if (perif->mmbi.enable) {
-+		rc = devm_request_irq(dev, espi->perif.mmbi.irq,
-+				      ast2600_espi_perif_mmbi_isr, 0, dev_name(dev), espi);
-+		if (rc) {
-+			dev_err(dev, "cannot request MMBI IRQ\n");
-+			return rc;
-+		}
-+	}
-+
-+	return 0;
-+}
-+
-+static int ast2600_espi_perif_remove(struct ast2600_espi *espi)
-+{
-+	struct ast2600_espi_perif_mmbi *mmbi;
-+	struct ast2600_espi_perif *perif;
-+	struct device *dev;
-+	uint32_t reg;
-+	int i;
-+
-+	dev = espi->dev;
-+
-+	perif = &espi->perif;
-+
-+	writel(ESPI_INT_EN_PERIF, espi->regs + ESPI_INT_EN_CLR);
-+
-+	reg = readl(espi->regs + ESPI_CTRL2);
-+	reg |= (ESPI_CTRL2_MCYC_RD_DIS | ESPI_CTRL2_MCYC_WR_DIS);
-+	writel(reg, espi->regs + ESPI_CTRL2);
-+
-+	reg = readl(espi->regs + ESPI_CTRL);
-+	reg &= ~(ESPI_CTRL_PERIF_NP_TX_DMA_EN
-+		 | ESPI_CTRL_PERIF_PC_TX_DMA_EN
-+		 | ESPI_CTRL_PERIF_PC_RX_DMA_EN
-+		 | ESPI_CTRL_PERIF_SW_RDY);
-+	writel(reg, espi->regs + ESPI_CTRL);
-+
-+	if (perif->mmbi.enable) {
-+		reg = readl(espi->regs + ESPI_MMBI_CTRL);
-+		reg &= ~ESPI_MMBI_CTRL_EN;
-+		writel(reg, espi->regs + ESPI_MMBI_CTRL);
-+
-+		for (i = 0; i < PERIF_MMBI_INST_NUM; ++i) {
-+			mmbi = &perif->mmbi.inst[i];
-+			misc_deregister(&mmbi->b2h_mdev);
-+			misc_deregister(&mmbi->h2b_mdev);
-+		}
-+
-+		dmam_free_coherent(dev, perif->mmbi.size, perif->mmbi.virt,
-+				   perif->mmbi.taddr);
-+	}
-+
-+	if (perif->mcyc.enable)
-+		dmam_free_coherent(dev, perif->mcyc.size, perif->mcyc.virt,
-+				   perif->mcyc.taddr);
-+
-+	if (perif->dma.enable) {
-+		dmam_free_coherent(dev, PAGE_SIZE, perif->dma.np_tx_virt,
-+				   perif->dma.np_tx_addr);
-+		dmam_free_coherent(dev, PAGE_SIZE, perif->dma.pc_tx_virt,
-+				   perif->dma.pc_tx_addr);
-+		dmam_free_coherent(dev, PAGE_SIZE, perif->dma.pc_rx_virt,
-+				   perif->dma.pc_rx_addr);
-+	}
-+
-+	mutex_destroy(&perif->np_tx_mtx);
-+	mutex_destroy(&perif->pc_tx_mtx);
-+	mutex_destroy(&perif->pc_rx_mtx);
-+
-+	misc_deregister(&perif->mdev);
-+
-+	return 0;
-+}
-+
-+/* virtual wire channel (CH1) */
-+static long ast2600_espi_vw_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
-+{
-+	struct ast2600_espi_vw *vw;
-+	struct ast2600_espi *espi;
-+	uint32_t gpio;
-+
-+	vw = container_of(fp->private_data, struct ast2600_espi_vw, mdev);
-+	espi = container_of(vw, struct ast2600_espi, vw);
-+	gpio = vw->gpio.val;
-+
-+	switch (cmd) {
-+	case ASPEED_ESPI_VW_GET_GPIO_VAL:
-+		if (put_user(gpio, (uint32_t __user *)arg))
-+			return -EFAULT;
-+		break;
-+	case ASPEED_ESPI_VW_PUT_GPIO_VAL:
-+		if (get_user(gpio, (uint32_t __user *)arg))
-+			return -EFAULT;
-+
-+		writel(gpio, espi->regs + ESPI_VW_GPIO_VAL);
-+		break;
-+	default:
-+		return -EINVAL;
-+	};
-+
-+	return 0;
-+}
-+
-+static const struct file_operations ast2600_espi_vw_fops = {
-+	.owner = THIS_MODULE,
-+	.unlocked_ioctl = ast2600_espi_vw_ioctl,
-+};
-+
-+static void ast2600_espi_vw_isr(struct ast2600_espi *espi)
-+{
-+	struct ast2600_espi_vw *vw;
-+	uint32_t sts;
-+
-+	vw = &espi->vw;
-+
-+	sts = readl(espi->regs + ESPI_INT_STS);
-+
-+	if (sts & ESPI_INT_STS_VW_GPIO) {
-+		vw->gpio.val = readl(espi->regs + ESPI_VW_GPIO_VAL);
-+		writel(ESPI_INT_STS_VW_GPIO, espi->regs + ESPI_INT_STS);
-+	}
-+}
-+
-+static void ast2600_espi_vw_reset(struct ast2600_espi *espi)
-+{
-+	uint32_t reg;
-+	struct ast2600_espi_vw *vw = &espi->vw;
-+
-+	writel(ESPI_INT_EN_VW, espi->regs + ESPI_INT_EN_CLR);
-+	writel(ESPI_INT_STS_VW, espi->regs + ESPI_INT_STS);
-+
-+	writel(vw->gpio.dir, espi->regs + ESPI_VW_GPIO_DIR);
-+
-+	vw->gpio.val = readl(espi->regs + ESPI_VW_GPIO_VAL);
-+
-+	reg = readl(espi->regs + ESPI_CTRL2) & ~(ESPI_CTRL2_VW_TX_SORT);
-+	writel(reg, espi->regs + ESPI_CTRL2);
-+
-+	writel(ESPI_INT_EN_VW_GPIO, espi->regs + ESPI_INT_EN);
-+
-+	reg = readl(espi->regs + ESPI_CTRL)
-+	      | ((vw->gpio.hw_mode) ? 0 : ESPI_CTRL_VW_GPIO_SW)
-+	      | ESPI_CTRL_VW_SW_RDY;
-+	writel(reg, espi->regs + ESPI_CTRL);
-+}
-+
-+static int ast2600_espi_vw_probe(struct ast2600_espi *espi)
-+{
-+	int rc;
-+	struct device *dev = espi->dev;
-+	struct ast2600_espi_vw *vw = &espi->vw;
-+
-+	vw->gpio.hw_mode = of_property_read_bool(dev->of_node, "vw-gpio-hw-mode");
-+	of_property_read_u32(dev->of_node, "vw-gpio-direction", &vw->gpio.dir);
-+
-+	vw->mdev.parent = dev;
-+	vw->mdev.minor = MISC_DYNAMIC_MINOR;
-+	vw->mdev.name = devm_kasprintf(dev, GFP_KERNEL, "%s-vw", DEVICE_NAME);
-+	vw->mdev.fops = &ast2600_espi_vw_fops;
-+	rc = misc_register(&vw->mdev);
-+	if (rc) {
-+		dev_err(dev, "cannot register device %s\n", vw->mdev.name);
-+		return rc;
-+	}
-+
-+	ast2600_espi_vw_reset(espi);
-+
-+	return 0;
-+}
-+
-+static int ast2600_espi_vw_remove(struct ast2600_espi *espi)
-+{
-+	struct ast2600_espi_vw *vw;
-+
-+	vw = &espi->vw;
-+
-+	writel(ESPI_INT_EN_VW, espi->regs + ESPI_INT_EN_CLR);
-+
-+	misc_deregister(&vw->mdev);
-+
-+	return 0;
-+}
-+
-+/* out-of-band channel (CH2) */
-+static long ast2600_espi_oob_dma_get_rx(struct file *fp,
-+					struct ast2600_espi_oob *oob,
-+					struct aspeed_espi_ioc *ioc)
-+{
-+	struct ast2600_espi_oob_dma_rx_desc *d;
-+	struct ast2600_espi *espi;
-+	struct espi_comm_hdr *hdr;
-+	uint32_t wptr, pkt_len;
-+	unsigned long flags;
-+	uint8_t *pkt;
-+	int rc;
-+
-+	espi = container_of(oob, struct ast2600_espi, oob);
-+
-+	wptr = FIELD_PREP(ESPI_OOB_RX_DESC_WPTR_WP, readl(espi->regs + ESPI_OOB_RX_DESC_WPTR));
-+
-+	d = &oob->dma.rxd_virt[wptr];
-+
-+	if (!d->dirty)
-+		return -EFAULT;
-+
-+	pkt_len = ((d->len) ? d->len : ESPI_MAX_PLD_LEN) + sizeof(struct espi_comm_hdr);
-+
-+	if (ioc->pkt_len < pkt_len)
-+		return -EINVAL;
-+
-+	pkt = vmalloc(pkt_len);
-+	if (!pkt)
-+		return -ENOMEM;
-+
-+	hdr = (struct espi_comm_hdr *)pkt;
-+	hdr->cyc = d->cyc;
-+	hdr->tag = d->tag;
-+	hdr->len_h = d->len >> 8;
-+	hdr->len_l = d->len & 0xff;
-+	memcpy(hdr + 1, oob->dma.rx_virt + (PAGE_SIZE * wptr), pkt_len - sizeof(*hdr));
-+
-+	if (copy_to_user((void __user *)ioc->pkt, pkt, pkt_len)) {
-+		rc = -EFAULT;
-+		goto free_n_out;
-+	}
-+
-+	spin_lock_irqsave(&oob->lock, flags);
-+
-+	/* make current descriptor available again */
-+	d->dirty = 0;
-+
-+	wptr = (wptr + 1) % OOB_DMA_DESC_NUM;
-+	writel(wptr | ESPI_OOB_RX_DESC_WPTR_RECV_EN, espi->regs + ESPI_OOB_RX_DESC_WPTR);
-+
-+	/* set ready flag base on the next RX descriptor */
-+	oob->rx_ready = oob->dma.rxd_virt[wptr].dirty;
-+
-+	spin_unlock_irqrestore(&oob->lock, flags);
-+
-+	rc = 0;
-+
-+free_n_out:
-+	vfree(pkt);
-+
-+	return rc;
-+}
-+
-+static long ast2600_espi_oob_get_rx(struct file *fp,
-+				    struct ast2600_espi_oob *oob,
-+				    struct aspeed_espi_ioc *ioc)
-+{
-+	uint32_t reg, cyc, tag, len;
-+	struct ast2600_espi *espi;
-+	struct espi_comm_hdr *hdr;
-+	unsigned long flags;
-+	uint32_t pkt_len;
-+	uint8_t *pkt;
-+	int i, rc;
-+
-+	espi = container_of(oob, struct ast2600_espi, oob);
-+
-+	if (fp->f_flags & O_NONBLOCK) {
-+		if (!mutex_trylock(&oob->rx_mtx))
-+			return -EAGAIN;
-+
-+		if (!oob->rx_ready) {
-+			rc = -ENODATA;
-+			goto unlock_mtx_n_out;
-+		}
-+	} else {
-+		mutex_lock(&oob->rx_mtx);
-+
-+		if (!oob->rx_ready) {
-+			rc = wait_event_interruptible(oob->wq, oob->rx_ready);
-+			if (rc == -ERESTARTSYS) {
-+				rc = -EINTR;
-+				goto unlock_mtx_n_out;
-+			}
-+		}
-+	}
-+
-+	if (oob->dma.enable) {
-+		rc = ast2600_espi_oob_dma_get_rx(fp, oob, ioc);
-+		goto unlock_mtx_n_out;
-+	}
-+
-+	/*
-+	 * common header (i.e. cycle type, tag, and length)
-+	 * part is written to HW registers
-+	 */
-+	reg = readl(espi->regs + ESPI_OOB_RX_CTRL);
-+	cyc = FIELD_GET(ESPI_OOB_RX_CTRL_CYC, reg);
-+	tag = FIELD_GET(ESPI_OOB_RX_CTRL_TAG, reg);
-+	len = FIELD_GET(ESPI_OOB_RX_CTRL_LEN, reg);
-+
-+	/*
-+	 * calculate the length of the rest part of the
-+	 * eSPI packet to be read from HW and copied to
-+	 * user space.
-+	 */
-+	pkt_len = ((len) ? len : ESPI_MAX_PLD_LEN) + sizeof(struct espi_comm_hdr);
-+
-+	if (ioc->pkt_len < pkt_len) {
-+		rc = -EINVAL;
-+		goto unlock_mtx_n_out;
-+	}
-+
-+	pkt = vmalloc(pkt_len);
-+	if (!pkt) {
-+		rc = -ENOMEM;
-+		goto unlock_mtx_n_out;
-+	}
-+
-+	hdr = (struct espi_comm_hdr *)pkt;
-+	hdr->cyc = cyc;
-+	hdr->tag = tag;
-+	hdr->len_h = len >> 8;
-+	hdr->len_l = len & 0xff;
-+
-+	for (i = sizeof(*hdr); i < pkt_len; ++i)
-+		pkt[i] = readl(espi->regs + ESPI_OOB_RX_DATA) & 0xff;
-+
-+	if (copy_to_user((void __user *)ioc->pkt, pkt, pkt_len)) {
-+		rc = -EFAULT;
-+		goto free_n_out;
-+	}
-+
-+	spin_lock_irqsave(&oob->lock, flags);
-+
-+	writel(ESPI_OOB_RX_CTRL_SERV_PEND, espi->regs + ESPI_OOB_RX_CTRL);
-+	oob->rx_ready = 0;
-+
-+	spin_unlock_irqrestore(&oob->lock, flags);
-+
-+	rc = 0;
-+
-+free_n_out:
-+	vfree(pkt);
-+
-+unlock_mtx_n_out:
-+	mutex_unlock(&oob->rx_mtx);
-+
-+	return rc;
-+}
-+
-+static long ast2600_espi_oob_dma_put_tx(struct file *fp,
-+					struct ast2600_espi_oob *oob,
-+					struct aspeed_espi_ioc *ioc)
-+{
-+	struct ast2600_espi_oob_dma_tx_desc *d;
-+	struct ast2600_espi *espi;
-+	struct espi_comm_hdr *hdr;
-+	uint32_t rptr, wptr;
-+	uint8_t *pkt;
-+	int rc;
-+
-+	espi = container_of(oob, struct ast2600_espi, oob);
-+
-+	pkt = vzalloc(ioc->pkt_len);
-+	if (!pkt)
-+		return -ENOMEM;
-+
-+	hdr = (struct espi_comm_hdr *)pkt;
-+
-+	if (copy_from_user(pkt, (void __user *)ioc->pkt, ioc->pkt_len)) {
-+		rc = -EFAULT;
-+		goto free_n_out;
-+	}
-+
-+	/* kick HW to update descriptor read/write pointer */
-+	writel(ESPI_OOB_TX_DESC_RPTR_UPDATE, espi->regs + ESPI_OOB_TX_DESC_RPTR);
-+
-+	rptr = readl(espi->regs + ESPI_OOB_TX_DESC_RPTR);
-+	wptr = readl(espi->regs + ESPI_OOB_TX_DESC_WPTR);
-+
-+	if (((wptr + 1) % OOB_DMA_DESC_NUM) == rptr) {
-+		rc = -EBUSY;
-+		goto free_n_out;
-+	}
-+
-+	d = &oob->dma.txd_virt[wptr];
-+	d->cyc = hdr->cyc;
-+	d->tag = hdr->tag;
-+	d->len = (hdr->len_h << 8) | (hdr->len_l & 0xff);
-+	d->msg_type = OOB_DMA_DESC_CUSTOM;
-+
-+	memcpy(oob->dma.tx_virt + (PAGE_SIZE * wptr), hdr + 1,  ioc->pkt_len - sizeof(*hdr));
-+
-+	dma_wmb();
-+
-+	wptr = (wptr + 1) % OOB_DMA_DESC_NUM;
-+	writel(wptr | ESPI_OOB_TX_DESC_WPTR_SEND_EN, espi->regs + ESPI_OOB_TX_DESC_WPTR);
-+
-+	rc = 0;
-+
-+free_n_out:
-+	vfree(pkt);
-+
-+	return rc;
-+}
-+
-+static long ast2600_espi_oob_put_tx(struct file *fp,
-+				    struct ast2600_espi_oob *oob,
-+				    struct aspeed_espi_ioc *ioc)
-+{
-+	uint32_t reg, cyc, tag, len;
-+	struct ast2600_espi *espi;
-+	struct espi_comm_hdr *hdr;
-+	uint8_t *pkt;
-+	int i, rc;
-+
-+	espi = container_of(oob, struct ast2600_espi, oob);
-+
-+	if (!mutex_trylock(&oob->tx_mtx))
-+		return -EAGAIN;
-+
-+	if (oob->dma.enable) {
-+		rc = ast2600_espi_oob_dma_put_tx(fp, oob, ioc);
-+		goto unlock_mtx_n_out;
-+	}
-+
-+	reg = readl(espi->regs + ESPI_OOB_TX_CTRL);
-+	if (reg & ESPI_OOB_TX_CTRL_TRIG_PEND) {
-+		rc = -EBUSY;
-+		goto unlock_mtx_n_out;
-+	}
-+
-+	if (ioc->pkt_len > ESPI_MAX_PKT_LEN) {
-+		rc = -EINVAL;
-+		goto unlock_mtx_n_out;
-+	}
-+
-+	pkt = vmalloc(ioc->pkt_len);
-+	if (!pkt) {
-+		rc = -ENOMEM;
-+		goto unlock_mtx_n_out;
-+	}
-+
-+	hdr = (struct espi_comm_hdr *)pkt;
-+
-+	if (copy_from_user(pkt, (void __user *)ioc->pkt, ioc->pkt_len)) {
-+		rc = -EFAULT;
-+		goto free_n_out;
-+	}
-+
-+	/*
-+	 * common header (i.e. cycle type, tag, and length)
-+	 * part is written to HW registers
-+	 */
-+	for (i = sizeof(*hdr); i < ioc->pkt_len; ++i)
-+		writel(pkt[i], espi->regs + ESPI_OOB_TX_DATA);
-+
-+	cyc = hdr->cyc;
-+	tag = hdr->tag;
-+	len = (hdr->len_h << 8) | (hdr->len_l & 0xff);
-+
-+	reg = FIELD_PREP(ESPI_OOB_TX_CTRL_CYC, cyc)
-+	      | FIELD_PREP(ESPI_OOB_TX_CTRL_TAG, tag)
-+	      | FIELD_PREP(ESPI_OOB_TX_CTRL_LEN, len)
-+	      | ESPI_OOB_TX_CTRL_TRIG_PEND;
-+	writel(reg, espi->regs + ESPI_OOB_TX_CTRL);
-+
-+	rc = 0;
-+
-+free_n_out:
-+	vfree(pkt);
-+
-+unlock_mtx_n_out:
-+	mutex_unlock(&oob->tx_mtx);
-+
-+	return rc;
-+}
-+
-+static long ast2600_espi_oob_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
-+{
-+	struct ast2600_espi_oob *oob;
-+	struct aspeed_espi_ioc ioc;
-+
-+	oob = container_of(fp->private_data, struct ast2600_espi_oob, mdev);
-+
-+	if (copy_from_user(&ioc, (void __user *)arg, sizeof(ioc)))
-+		return -EFAULT;
-+
-+	if (ioc.pkt_len > ESPI_MAX_PKT_LEN)
-+		return -EINVAL;
-+
-+	switch (cmd) {
-+	case ASPEED_ESPI_OOB_GET_RX:
-+		return ast2600_espi_oob_get_rx(fp, oob, &ioc);
-+	case ASPEED_ESPI_OOB_PUT_TX:
-+		return ast2600_espi_oob_put_tx(fp, oob, &ioc);
-+	};
-+
-+	return -EINVAL;
-+}
-+
-+static const struct file_operations ast2600_espi_oob_fops = {
-+	.owner = THIS_MODULE,
-+	.unlocked_ioctl = ast2600_espi_oob_ioctl,
-+};
-+
-+static void ast2600_espi_oob_isr(struct ast2600_espi *espi)
-+{
-+	struct ast2600_espi_oob *oob;
-+	unsigned long flags;
-+	uint32_t sts;
-+
-+	oob = &espi->oob;
-+
-+	sts = readl(espi->regs + ESPI_INT_STS);
-+
-+	if (sts & ESPI_INT_STS_OOB_RX_CMPLT) {
-+		writel(ESPI_INT_STS_OOB_RX_CMPLT, espi->regs + ESPI_INT_STS);
-+
-+		spin_lock_irqsave(&oob->lock, flags);
-+		oob->rx_ready = true;
-+		spin_unlock_irqrestore(&oob->lock, flags);
-+
-+		wake_up_interruptible(&oob->wq);
-+	}
-+}
-+
-+static void ast2600_espi_oob_reset(struct ast2600_espi *espi)
-+{
-+	struct ast2600_espi_oob *oob;
-+	dma_addr_t tx_addr, rx_addr;
-+	uint32_t reg;
-+	int i;
-+
-+	writel(ESPI_INT_EN_OOB, espi->regs + ESPI_INT_EN_CLR);
-+	writel(ESPI_INT_STS_OOB, espi->regs + ESPI_INT_STS);
-+
-+	reg = readl(espi->regs + ESPI_CTRL);
-+	reg &= ~(ESPI_CTRL_OOB_TX_SW_RST
-+		 | ESPI_CTRL_OOB_RX_SW_RST
-+		 | ESPI_CTRL_OOB_TX_DMA_EN
-+		 | ESPI_CTRL_OOB_RX_DMA_EN
-+		 | ESPI_CTRL_OOB_SW_RDY);
-+	writel(reg, espi->regs + ESPI_CTRL);
-+
-+	udelay(1);
-+
-+	reg |= (ESPI_CTRL_OOB_TX_SW_RST | ESPI_CTRL_OOB_RX_SW_RST);
-+	writel(reg, espi->regs + ESPI_CTRL);
-+
-+	oob = &espi->oob;
-+
-+	if (oob->dma.enable) {
-+		tx_addr = oob->dma.tx_addr;
-+		rx_addr = oob->dma.rx_addr;
-+
-+		for (i = 0; i < OOB_DMA_DESC_NUM; ++i) {
-+			oob->dma.txd_virt[i].data_addr = tx_addr;
-+			tx_addr += PAGE_SIZE;
-+
-+			oob->dma.rxd_virt[i].data_addr = rx_addr;
-+			oob->dma.rxd_virt[i].dirty = 0;
-+			rx_addr += PAGE_SIZE;
-+		}
-+
-+		writel(oob->dma.txd_addr, espi->regs + ESPI_OOB_TX_DMA);
-+		writel(OOB_DMA_RPTR_KEY, espi->regs + ESPI_OOB_TX_DESC_RPTR);
-+		writel(0x0, espi->regs + ESPI_OOB_TX_DESC_WPTR);
-+		writel(OOB_DMA_DESC_NUM, espi->regs + ESPI_OOB_TX_DESC_NUM);
-+
-+		writel(oob->dma.rxd_addr, espi->regs + ESPI_OOB_RX_DMA);
-+		writel(OOB_DMA_RPTR_KEY, espi->regs + ESPI_OOB_RX_DESC_RPTR);
-+		writel(0x0, espi->regs + ESPI_OOB_RX_DESC_WPTR);
-+		writel(OOB_DMA_DESC_NUM, espi->regs + ESPI_OOB_RX_DESC_NUM);
-+
-+		reg = readl(espi->regs + ESPI_CTRL)
-+		      | ESPI_CTRL_OOB_TX_DMA_EN
-+		      | ESPI_CTRL_OOB_RX_DMA_EN;
-+		writel(reg, espi->regs + ESPI_CTRL);
-+
-+		/* activate RX DMA to make OOB_FREE */
-+		writel(ESPI_OOB_RX_DESC_WPTR_RECV_EN, espi->regs + ESPI_OOB_RX_DESC_WPTR);
-+	}
-+
-+	writel(ESPI_INT_EN_OOB_RX_CMPLT, espi->regs + ESPI_INT_EN);
-+
-+	reg = readl(espi->regs + ESPI_CTRL) | ESPI_CTRL_OOB_SW_RDY;
-+	writel(reg, espi->regs + ESPI_CTRL);
-+}
-+
-+static int ast2600_espi_oob_probe(struct ast2600_espi *espi)
-+{
-+	struct ast2600_espi_oob *oob;
-+	struct device *dev;
-+	int rc;
-+
-+	dev = espi->dev;
-+
-+	oob = &espi->oob;
-+
-+	init_waitqueue_head(&oob->wq);
-+
-+	spin_lock_init(&oob->lock);
-+
-+	mutex_init(&oob->tx_mtx);
-+	mutex_init(&oob->rx_mtx);
-+
-+	oob->dma.enable = of_property_read_bool(dev->of_node, "oob-dma-mode");
-+	if (oob->dma.enable) {
-+		oob->dma.txd_virt = dmam_alloc_coherent(dev, sizeof(*oob->dma.txd_virt) * OOB_DMA_DESC_NUM, &oob->dma.txd_addr, GFP_KERNEL);
-+		if (!oob->dma.txd_virt) {
-+			dev_err(dev, "cannot allocate DMA TX descriptor\n");
-+			return -ENOMEM;
-+		}
-+		oob->dma.tx_virt = dmam_alloc_coherent(dev, PAGE_SIZE * OOB_DMA_DESC_NUM, &oob->dma.tx_addr, GFP_KERNEL);
-+		if (!oob->dma.tx_virt) {
-+			dev_err(dev, "cannot allocate DMA TX buffer\n");
-+			return -ENOMEM;
-+		}
-+
-+		oob->dma.rxd_virt = dmam_alloc_coherent(dev, sizeof(*oob->dma.rxd_virt) * OOB_DMA_DESC_NUM, &oob->dma.rxd_addr, GFP_KERNEL);
-+		if (!oob->dma.rxd_virt) {
-+			dev_err(dev, "cannot allocate DMA RX descriptor\n");
-+			return -ENOMEM;
-+		}
-+
-+		oob->dma.rx_virt = dmam_alloc_coherent(dev, PAGE_SIZE * OOB_DMA_DESC_NUM, &oob->dma.rx_addr, GFP_KERNEL);
-+		if (!oob->dma.rx_virt) {
-+			dev_err(dev, "cannot allocate DMA TX buffer\n");
-+			return -ENOMEM;
-+		}
-+	}
-+
-+	oob->mdev.parent = dev;
-+	oob->mdev.minor = MISC_DYNAMIC_MINOR;
-+	oob->mdev.name = devm_kasprintf(dev, GFP_KERNEL, "%s-oob", DEVICE_NAME);
-+	oob->mdev.fops = &ast2600_espi_oob_fops;
-+	rc = misc_register(&oob->mdev);
-+	if (rc) {
-+		dev_err(dev, "cannot register device %s\n", oob->mdev.name);
-+		return rc;
-+	}
-+
-+	ast2600_espi_oob_reset(espi);
-+
-+	return 0;
-+}
-+
-+static int ast2600_espi_oob_remove(struct ast2600_espi *espi)
-+{
-+	struct ast2600_espi_oob *oob;
-+	struct device *dev;
-+	uint32_t reg;
-+
-+	dev = espi->dev;
-+
-+	oob = &espi->oob;
-+
-+	writel(ESPI_INT_EN_OOB, espi->regs + ESPI_INT_EN_CLR);
-+
-+	reg = readl(espi->regs + ESPI_CTRL);
-+	reg &= ~(ESPI_CTRL_OOB_TX_DMA_EN
-+		 | ESPI_CTRL_OOB_RX_DMA_EN
-+		 | ESPI_CTRL_OOB_SW_RDY);
-+	writel(reg, espi->regs + ESPI_CTRL);
-+
-+	if (oob->dma.enable) {
-+		dmam_free_coherent(dev, sizeof(*oob->dma.txd_virt) * OOB_DMA_DESC_NUM,
-+				   oob->dma.txd_virt, oob->dma.txd_addr);
-+		dmam_free_coherent(dev, PAGE_SIZE * OOB_DMA_DESC_NUM,
-+				   oob->dma.tx_virt, oob->dma.tx_addr);
-+		dmam_free_coherent(dev, sizeof(*oob->dma.rxd_virt) * OOB_DMA_DESC_NUM,
-+				   oob->dma.rxd_virt, oob->dma.rxd_addr);
-+		dmam_free_coherent(dev, PAGE_SIZE * OOB_DMA_DESC_NUM,
-+				   oob->dma.rx_virt, oob->dma.rx_addr);
-+	}
-+
-+	mutex_destroy(&oob->tx_mtx);
-+	mutex_destroy(&oob->rx_mtx);
-+
-+	misc_deregister(&oob->mdev);
-+
-+	return 0;
-+}
-+
-+/* flash channel (CH3) */
-+static long ast2600_espi_flash_get_rx(struct file *fp,
-+				      struct ast2600_espi_flash *flash,
-+				      struct aspeed_espi_ioc *ioc)
-+{
-+	uint32_t reg, cyc, tag, len;
-+	struct ast2600_espi *espi;
-+	struct espi_comm_hdr *hdr;
-+	unsigned long flags;
-+	uint32_t pkt_len;
-+	uint8_t *pkt;
-+	int i, rc;
-+
-+	rc = 0;
-+
-+	espi = container_of(flash, struct ast2600_espi, flash);
-+
-+	if (fp->f_flags & O_NONBLOCK) {
-+		if (!mutex_trylock(&flash->rx_mtx))
-+			return -EAGAIN;
-+
-+		if (!flash->rx_ready) {
-+			rc = -ENODATA;
-+			goto unlock_mtx_n_out;
-+		}
-+	} else {
-+		mutex_lock(&flash->rx_mtx);
-+
-+		if (!flash->rx_ready) {
-+			rc = wait_event_interruptible(flash->wq, flash->rx_ready);
-+			if (rc == -ERESTARTSYS) {
-+				rc = -EINTR;
-+				goto unlock_mtx_n_out;
-+			}
-+		}
-+	}
-+
-+	/*
-+	 * common header (i.e. cycle type, tag, and length)
-+	 * part is written to HW registers
-+	 */
-+	reg = readl(espi->regs + ESPI_FLASH_RX_CTRL);
-+	cyc = FIELD_GET(ESPI_FLASH_RX_CTRL_CYC, reg);
-+	tag = FIELD_GET(ESPI_FLASH_RX_CTRL_TAG, reg);
-+	len = FIELD_GET(ESPI_FLASH_RX_CTRL_LEN, reg);
-+
-+	/*
-+	 * calculate the length of the rest part of the
-+	 * eSPI packet to be read from HW and copied to
-+	 * user space.
-+	 */
-+	switch (cyc) {
-+	case ESPI_FLASH_WRITE:
-+		pkt_len = ((len) ? len : ESPI_MAX_PLD_LEN) +
-+			  sizeof(struct espi_flash_rwe);
-+		break;
-+	case ESPI_FLASH_READ:
-+	case ESPI_FLASH_ERASE:
-+		pkt_len = sizeof(struct espi_flash_rwe);
-+		break;
-+	case ESPI_FLASH_SUC_CMPLT_D_MIDDLE:
-+	case ESPI_FLASH_SUC_CMPLT_D_FIRST:
-+	case ESPI_FLASH_SUC_CMPLT_D_LAST:
-+	case ESPI_FLASH_SUC_CMPLT_D_ONLY:
-+		pkt_len = ((len) ? len : ESPI_MAX_PLD_LEN) +
-+			  sizeof(struct espi_flash_cmplt);
-+		break;
-+	case ESPI_FLASH_SUC_CMPLT:
-+	case ESPI_FLASH_UNSUC_CMPLT:
-+		pkt_len = sizeof(struct espi_flash_cmplt);
-+		break;
-+	default:
-+		rc = -EFAULT;
-+		goto unlock_mtx_n_out;
-+	}
-+
-+	if (ioc->pkt_len < pkt_len) {
-+		rc = -EINVAL;
-+		goto unlock_mtx_n_out;
-+	}
-+
-+	pkt = vmalloc(pkt_len);
-+	if (!pkt) {
-+		rc = -ENOMEM;
-+		goto unlock_mtx_n_out;
-+	}
-+
-+	hdr = (struct espi_comm_hdr *)pkt;
-+	hdr->cyc = cyc;
-+	hdr->tag = tag;
-+	hdr->len_h = len >> 8;
-+	hdr->len_l = len & 0xff;
-+
-+	if (flash->dma.enable) {
-+		memcpy(hdr + 1, flash->dma.rx_virt, pkt_len - sizeof(*hdr));
-+	} else {
-+		for (i = sizeof(*hdr); i < pkt_len; ++i)
-+			pkt[i] = readl(espi->regs + ESPI_FLASH_RX_DATA) & 0xff;
-+	}
-+
-+	if (copy_to_user((void __user *)ioc->pkt, pkt, pkt_len)) {
-+		rc = -EFAULT;
-+		goto free_n_out;
-+	}
-+
-+	spin_lock_irqsave(&flash->lock, flags);
-+
-+	writel(ESPI_FLASH_RX_CTRL_SERV_PEND, espi->regs + ESPI_FLASH_RX_CTRL);
-+	flash->rx_ready = 0;
-+
-+	spin_unlock_irqrestore(&flash->lock, flags);
-+
-+	rc = 0;
-+
-+free_n_out:
-+	vfree(pkt);
-+
-+unlock_mtx_n_out:
-+	mutex_unlock(&flash->rx_mtx);
-+
-+	return rc;
-+}
-+
-+static long ast2600_espi_flash_put_tx(struct file *fp,
-+				      struct ast2600_espi_flash *flash,
-+				      struct aspeed_espi_ioc *ioc)
-+{
-+	uint32_t reg, cyc, tag, len;
-+	struct ast2600_espi *espi;
-+	struct espi_comm_hdr *hdr;
-+	uint8_t *pkt;
-+	int i, rc;
-+
-+	espi = container_of(flash, struct ast2600_espi, flash);
-+
-+	if (!mutex_trylock(&flash->tx_mtx))
-+		return -EAGAIN;
-+
-+	reg = readl(espi->regs + ESPI_FLASH_TX_CTRL);
-+	if (reg & ESPI_FLASH_TX_CTRL_TRIG_PEND) {
-+		rc = -EBUSY;
-+		goto unlock_mtx_n_out;
-+	}
-+
-+	pkt = vmalloc(ioc->pkt_len);
-+	if (!pkt) {
-+		rc = -ENOMEM;
-+		goto unlock_mtx_n_out;
-+	}
-+
-+	hdr = (struct espi_comm_hdr *)pkt;
-+
-+	if (copy_from_user(pkt, (void __user *)ioc->pkt, ioc->pkt_len)) {
-+		rc = -EFAULT;
-+		goto free_n_out;
-+	}
-+
-+	/*
-+	 * common header (i.e. cycle type, tag, and length)
-+	 * part is written to HW registers
-+	 */
-+	if (flash->dma.enable) {
-+		memcpy(flash->dma.tx_virt, hdr + 1, ioc->pkt_len - sizeof(*hdr));
-+		dma_wmb();
-+	} else {
-+		for (i = sizeof(*hdr); i < ioc->pkt_len; ++i)
-+			writel(pkt[i], espi->regs + ESPI_FLASH_TX_DATA);
-+	}
-+
-+	cyc = hdr->cyc;
-+	tag = hdr->tag;
-+	len = (hdr->len_h << 8) | (hdr->len_l & 0xff);
-+
-+	reg = FIELD_PREP(ESPI_FLASH_TX_CTRL_CYC, cyc)
-+	      | FIELD_PREP(ESPI_FLASH_TX_CTRL_TAG, tag)
-+	      | FIELD_PREP(ESPI_FLASH_TX_CTRL_LEN, len)
-+	      | ESPI_FLASH_TX_CTRL_TRIG_PEND;
-+	writel(reg, espi->regs + ESPI_FLASH_TX_CTRL);
-+
-+	rc = 0;
-+
-+free_n_out:
-+	vfree(pkt);
-+
-+unlock_mtx_n_out:
-+	mutex_unlock(&flash->tx_mtx);
-+
-+	return rc;
-+}
-+
-+static long ast2600_espi_flash_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
-+{
-+	struct ast2600_espi_flash *flash;
-+	struct aspeed_espi_ioc ioc;
-+
-+	flash = container_of(fp->private_data, struct ast2600_espi_flash, mdev);
-+
-+	if (copy_from_user(&ioc, (void __user *)arg, sizeof(ioc)))
-+		return -EFAULT;
-+
-+	if (ioc.pkt_len > ESPI_MAX_PKT_LEN)
-+		return -EINVAL;
-+
-+	switch (cmd) {
-+	case ASPEED_ESPI_FLASH_GET_RX:
-+		return ast2600_espi_flash_get_rx(fp, flash, &ioc);
-+	case ASPEED_ESPI_FLASH_PUT_TX:
-+		return ast2600_espi_flash_put_tx(fp, flash, &ioc);
-+	default:
-+		break;
-+	};
-+
-+	return -EINVAL;
-+}
-+
-+static const struct file_operations ast2600_espi_flash_fops = {
-+	.owner = THIS_MODULE,
-+	.unlocked_ioctl = ast2600_espi_flash_ioctl,
-+};
-+
-+static void ast2600_espi_flash_isr(struct ast2600_espi *espi)
-+{
-+	struct ast2600_espi_flash *flash;
-+	unsigned long flags;
-+	uint32_t sts;
-+
-+	flash = &espi->flash;
-+
-+	sts = readl(espi->regs + ESPI_INT_STS);
-+
-+	if (sts & ESPI_INT_STS_FLASH_RX_CMPLT) {
-+		writel(ESPI_INT_STS_FLASH_RX_CMPLT, espi->regs + ESPI_INT_STS);
-+
-+		spin_lock_irqsave(&flash->lock, flags);
-+		flash->rx_ready = true;
-+		spin_unlock_irqrestore(&flash->lock, flags);
-+
-+		wake_up_interruptible(&flash->wq);
-+	}
-+}
-+
-+static void ast2600_espi_flash_reset(struct ast2600_espi *espi)
-+{
-+	struct ast2600_espi_flash *flash;
-+	uint32_t reg;
-+
-+	flash = &espi->flash;
-+
-+	writel(ESPI_INT_EN_FLASH, espi->regs + ESPI_INT_EN_CLR);
-+	writel(ESPI_INT_STS_FLASH, espi->regs + ESPI_INT_STS);
-+
-+	reg = readl(espi->regs + ESPI_CTRL);
-+	reg &= ~(ESPI_CTRL_FLASH_TX_SW_RST
-+		 | ESPI_CTRL_FLASH_RX_SW_RST
-+		 | ESPI_CTRL_FLASH_TX_DMA_EN
-+		 | ESPI_CTRL_FLASH_RX_DMA_EN
-+		 | ESPI_CTRL_FLASH_SW_RDY);
-+	writel(reg, espi->regs + ESPI_CTRL);
-+
-+	udelay(1);
-+
-+	reg |= (ESPI_CTRL_FLASH_TX_SW_RST | ESPI_CTRL_FLASH_RX_SW_RST);
-+	writel(reg, espi->regs + ESPI_CTRL);
-+
-+	reg = readl(espi->regs + ESPI_CTRL) & ~ESPI_CTRL_FLASH_SAFS_MODE;
-+	reg |= FIELD_PREP(ESPI_CTRL_FLASH_SAFS_MODE, flash->safs.mode);
-+	writel(reg, espi->regs + ESPI_CTRL);
-+
-+	if (flash->safs.mode == SAFS_MODE_MIX) {
-+		reg = FIELD_PREP(ESPI_FLASH_SAFS_TADDR_BASE, flash->safs.taddr >> 24)
-+		      | FIELD_PREP(ESPI_FLASH_SAFS_TADDR_MASK, (~(flash->safs.size - 1)) >> 24);
-+		writel(reg, espi->regs + ESPI_FLASH_SAFS_TADDR);
-+	}
-+
-+	if (flash->dma.enable) {
-+		writel(flash->dma.tx_addr, espi->regs + ESPI_FLASH_TX_DMA);
-+		writel(flash->dma.rx_addr, espi->regs + ESPI_FLASH_RX_DMA);
-+
-+		reg = readl(espi->regs + ESPI_CTRL)
-+		      | ESPI_CTRL_FLASH_TX_DMA_EN
-+		      | ESPI_CTRL_FLASH_RX_DMA_EN;
-+		writel(reg, espi->regs + ESPI_CTRL);
-+	}
-+
-+	writel(ESPI_INT_EN_FLASH_RX_CMPLT, espi->regs + ESPI_INT_EN);
-+
-+	reg = readl(espi->regs + ESPI_CTRL) | ESPI_CTRL_FLASH_SW_RDY;
-+	writel(reg, espi->regs + ESPI_CTRL);
-+}
-+
-+static int ast2600_espi_flash_probe(struct ast2600_espi *espi)
-+{
-+	struct ast2600_espi_flash *flash;
-+	struct device *dev;
-+	int rc;
-+
-+	dev = espi->dev;
-+
-+	flash = &espi->flash;
-+
-+	init_waitqueue_head(&flash->wq);
-+
-+	spin_lock_init(&flash->lock);
-+
-+	mutex_init(&flash->tx_mtx);
-+	mutex_init(&flash->rx_mtx);
-+
-+	flash->safs.mode = SAFS_MODE_HW;
-+
-+	of_property_read_u32(dev->of_node, "flash-safs-mode", &flash->safs.mode);
-+	if (flash->safs.mode == SAFS_MODE_MIX) {
-+		rc = of_property_read_u32(dev->of_node, "flash-safs-tgt-addr", &flash->safs.taddr);
-+		if (rc || !IS_ALIGNED(flash->safs.taddr, FLASH_SAFS_ALIGN)) {
-+			dev_err(dev, "cannot get 16MB-aligned SAFS target address\n");
-+			return -ENODEV;
-+		}
-+
-+		rc = of_property_read_u32(dev->of_node, "flash-safs-size", &flash->safs.size);
-+		if (rc || !IS_ALIGNED(flash->safs.size, FLASH_SAFS_ALIGN)) {
-+			dev_err(dev, "cannot get 16MB-aligned SAFS size\n");
-+			return -ENODEV;
-+		}
-+	}
-+
-+	flash->dma.enable = of_property_read_bool(dev->of_node, "flash-dma-mode");
-+	if (flash->dma.enable) {
-+		flash->dma.tx_virt = dmam_alloc_coherent(dev, PAGE_SIZE, &flash->dma.tx_addr, GFP_KERNEL);
-+		if (!flash->dma.tx_virt) {
-+			dev_err(dev, "cannot allocate DMA TX buffer\n");
-+			return -ENOMEM;
-+		}
-+
-+		flash->dma.rx_virt = dmam_alloc_coherent(dev, PAGE_SIZE, &flash->dma.rx_addr, GFP_KERNEL);
-+		if (!flash->dma.rx_virt) {
-+			dev_err(dev, "cannot allocate DMA RX buffer\n");
-+			return -ENOMEM;
-+		}
-+	}
-+
-+	flash->mdev.parent = dev;
-+	flash->mdev.minor = MISC_DYNAMIC_MINOR;
-+	flash->mdev.name = devm_kasprintf(dev, GFP_KERNEL, "%s-flash", DEVICE_NAME);
-+	flash->mdev.fops = &ast2600_espi_flash_fops;
-+	rc = misc_register(&flash->mdev);
-+	if (rc) {
-+		dev_err(dev, "cannot register device %s\n", flash->mdev.name);
-+		return rc;
-+	}
-+
-+	ast2600_espi_flash_reset(espi);
-+
-+	return 0;
-+}
-+
-+static int ast2600_espi_flash_remove(struct ast2600_espi *espi)
-+{
-+	struct ast2600_espi_flash *flash;
-+	struct device *dev;
-+	uint32_t reg;
-+
-+	dev = espi->dev;
-+
-+	flash = &espi->flash;
-+
-+	writel(ESPI_INT_EN_FLASH, espi->regs + ESPI_INT_EN_CLR);
-+
-+	reg = readl(espi->regs + ESPI_CTRL);
-+	reg &= ~(ESPI_CTRL_FLASH_TX_DMA_EN
-+		 | ESPI_CTRL_FLASH_RX_DMA_EN
-+		 | ESPI_CTRL_FLASH_SW_RDY);
-+	writel(reg, espi->regs + ESPI_CTRL);
-+
-+	if (flash->dma.enable) {
-+		dmam_free_coherent(dev, PAGE_SIZE, flash->dma.tx_virt, flash->dma.tx_addr);
-+		dmam_free_coherent(dev, PAGE_SIZE, flash->dma.rx_virt, flash->dma.rx_addr);
-+	}
-+
-+	mutex_destroy(&flash->tx_mtx);
-+	mutex_destroy(&flash->rx_mtx);
-+
-+	misc_deregister(&flash->mdev);
-+
-+	return 0;
-+}
-+
-+/* global control */
-+static irqreturn_t ast2600_espi_isr(int irq, void *arg)
-+{
-+	struct ast2600_espi *espi;
-+	uint32_t sts;
-+
-+	espi = (struct ast2600_espi *)arg;
-+
-+	sts = readl(espi->regs + ESPI_INT_STS);
-+	if (!sts)
-+		return IRQ_NONE;
-+
-+	if (sts & ESPI_INT_STS_PERIF)
-+		ast2600_espi_perif_isr(espi);
-+
-+	if (sts & ESPI_INT_STS_VW)
-+		ast2600_espi_vw_isr(espi);
-+
-+	if (sts & ESPI_INT_STS_OOB)
-+		ast2600_espi_oob_isr(espi);
-+
-+	if (sts & ESPI_INT_STS_FLASH)
-+		ast2600_espi_flash_isr(espi);
-+
-+	if (sts & ESPI_INT_STS_RST_DEASSERT) {
-+		/* this will clear all interrupt enable and status */
-+		reset_control_assert(espi->rst);
-+		reset_control_deassert(espi->rst);
-+
-+		ast2600_espi_perif_sw_reset(espi);
-+		ast2600_espi_perif_reset(espi);
-+		ast2600_espi_vw_reset(espi);
-+		ast2600_espi_oob_reset(espi);
-+		ast2600_espi_flash_reset(espi);
-+
-+		/* re-enable eSPI_RESET# interrupt */
-+		writel(ESPI_INT_EN_RST_DEASSERT, espi->regs + ESPI_INT_EN);
-+	}
-+
-+	return IRQ_HANDLED;
-+}
-+
-+static int ast2600_espi_probe(struct platform_device *pdev)
-+{
-+	struct ast2600_espi *espi;
-+	struct resource *res;
-+	struct device *dev;
-+	int rc;
-+
-+	dev = &pdev->dev;
-+
-+	espi = devm_kzalloc(dev, sizeof(*espi), GFP_KERNEL);
-+	if (!espi)
-+		return -ENOMEM;
-+
-+	espi->dev = dev;
-+
-+	rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
-+	if (rc) {
-+		dev_err(dev, "cannot set 64-bits DMA mask\n");
-+		return rc;
-+	}
-+
-+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+	if (!res) {
-+		dev_err(dev, "cannot get resource\n");
-+		return -ENODEV;
-+	}
-+
-+	espi->regs = devm_ioremap_resource(dev, res);
-+	if (IS_ERR(espi->regs)) {
-+		dev_err(dev, "cannot map registers\n");
-+		return PTR_ERR(espi->regs);
-+	}
-+
-+	espi->irq = platform_get_irq(pdev, 0);
-+	if (espi->irq < 0) {
-+		dev_err(dev, "cannot get IRQ number\n");
-+		return -ENODEV;
-+	}
-+
-+	espi->rst = devm_reset_control_get_exclusive_by_index(dev, 0);
-+	if (IS_ERR(espi->rst)) {
-+		dev_err(dev, "cannot get reset control\n");
-+		return PTR_ERR(espi->rst);
-+	}
-+
-+	espi->clk = devm_clk_get(dev, NULL);
-+	if (IS_ERR(espi->clk)) {
-+		dev_err(dev, "cannot get clock control\n");
-+		return PTR_ERR(espi->clk);
-+	}
-+
-+	rc = clk_prepare_enable(espi->clk);
-+	if (rc) {
-+		dev_err(dev, "cannot enable clocks\n");
-+		return rc;
-+	}
-+
-+	writel(ESPI_INT_EN_RST_DEASSERT, espi->regs + ESPI_INT_EN_CLR);
-+
-+	rc = ast2600_espi_perif_probe(espi);
-+	if (rc) {
-+		dev_err(dev, "cannot init peripheral channel, rc=%d\n", rc);
-+		return rc;
-+	}
-+
-+	rc = ast2600_espi_vw_probe(espi);
-+	if (rc) {
-+		dev_err(dev, "cannot init vw channel, rc=%d\n", rc);
-+		goto err_remove_perif;
-+	}
-+
-+	rc = ast2600_espi_oob_probe(espi);
-+	if (rc) {
-+		dev_err(dev, "cannot init oob channel, rc=%d\n", rc);
-+		goto err_remove_vw;
-+	}
-+
-+	rc = ast2600_espi_flash_probe(espi);
-+	if (rc) {
-+		dev_err(dev, "cannot init flash channel, rc=%d\n", rc);
-+		goto err_remove_oob;
-+	}
-+
-+	rc = devm_request_irq(dev, espi->irq, ast2600_espi_isr, 0, dev_name(dev), espi);
-+	if (rc) {
-+		dev_err(dev, "cannot request IRQ\n");
-+		goto err_remove_flash;
-+	}
-+
-+	writel(ESPI_INT_EN_RST_DEASSERT, espi->regs + ESPI_INT_EN);
-+
-+	dev_set_drvdata(dev, espi);
-+
-+	dev_info(dev, "module loaded\n");
-+
-+	return 0;
-+
-+err_remove_flash:
-+	ast2600_espi_flash_remove(espi);
-+err_remove_oob:
-+	ast2600_espi_oob_remove(espi);
-+err_remove_vw:
-+	ast2600_espi_vw_remove(espi);
-+err_remove_perif:
-+	ast2600_espi_perif_remove(espi);
-+
-+	return rc;
-+}
-+
-+static int ast2600_espi_remove(struct platform_device *pdev)
-+{
-+	struct ast2600_espi *espi;
-+	struct device *dev;
-+	int rc;
-+
-+	dev = &pdev->dev;
-+
-+	espi = (struct ast2600_espi *)dev_get_drvdata(dev);
-+
-+	writel(ESPI_INT_EN_RST_DEASSERT, espi->regs + ESPI_INT_EN_CLR);
-+
-+	rc = ast2600_espi_perif_remove(espi);
-+	if (rc)
-+		dev_warn(dev, "cannot remove peripheral channel, rc=%d\n", rc);
-+
-+	rc = ast2600_espi_vw_remove(espi);
-+	if (rc)
-+		dev_warn(dev, "cannot remove peripheral channel, rc=%d\n", rc);
-+
-+	rc = ast2600_espi_oob_remove(espi);
-+	if (rc)
-+		dev_warn(dev, "cannot remove peripheral channel, rc=%d\n", rc);
-+
-+	rc = ast2600_espi_flash_remove(espi);
-+	if (rc)
-+		dev_warn(dev, "cannot remove peripheral channel, rc=%d\n", rc);
-+
-+	return 0;
-+}
-+
-+static const struct of_device_id ast2600_espi_of_matches[] = {
-+	{ .compatible = "aspeed,ast2600-espi" },
-+	{ },
-+};
-+
-+static struct platform_driver ast2600_espi_driver = {
-+	.driver = {
-+		.name = "ast2600-espi",
-+		.of_match_table = ast2600_espi_of_matches,
-+	},
-+	.probe = ast2600_espi_probe,
-+	.remove = ast2600_espi_remove,
-+};
-+
-+module_platform_driver(ast2600_espi_driver);
-+
-+MODULE_AUTHOR("Chia-Wei Wang <chiawei_wang@aspeedtech.com>");
-+MODULE_DESCRIPTION("Control of AST2600 eSPI Device");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/soc/aspeed/ast2600-espi.h b/drivers/soc/aspeed/ast2600-espi.h
-new file mode 100644
-index 000000000..eb826f225
---- /dev/null
-+++ b/drivers/soc/aspeed/ast2600-espi.h
-@@ -0,0 +1,297 @@
-+/* SPDX-License-Identifier: GPL-2.0+ */
-+/*
-+ * Copyright 2023 Aspeed Technology Inc.
-+ */
-+#ifndef _AST2600_ESPI_H_
-+#define _AST2600_ESPI_H_
-+
-+#include <linux/bits.h>
-+#include "aspeed-espi-comm.h"
-+
-+/* registers */
-+#define ESPI_CTRL				0x000
-+#define   ESPI_CTRL_FLASH_TX_SW_RST		BIT(31)
-+#define   ESPI_CTRL_FLASH_RX_SW_RST		BIT(30)
-+#define   ESPI_CTRL_OOB_TX_SW_RST		BIT(29)
-+#define   ESPI_CTRL_OOB_RX_SW_RST		BIT(28)
-+#define   ESPI_CTRL_PERIF_NP_TX_SW_RST		BIT(27)
-+#define   ESPI_CTRL_PERIF_NP_RX_SW_RST		BIT(26)
-+#define   ESPI_CTRL_PERIF_PC_TX_SW_RST		BIT(25)
-+#define   ESPI_CTRL_PERIF_PC_RX_SW_RST		BIT(24)
-+#define   ESPI_CTRL_FLASH_TX_DMA_EN		BIT(23)
-+#define   ESPI_CTRL_FLASH_RX_DMA_EN		BIT(22)
-+#define   ESPI_CTRL_OOB_TX_DMA_EN		BIT(21)
-+#define   ESPI_CTRL_OOB_RX_DMA_EN		BIT(20)
-+#define   ESPI_CTRL_PERIF_NP_TX_DMA_EN		BIT(19)
-+#define   ESPI_CTRL_PERIF_PC_TX_DMA_EN		BIT(17)
-+#define   ESPI_CTRL_PERIF_PC_RX_DMA_EN		BIT(16)
-+#define   ESPI_CTRL_FLASH_SAFS_MODE		GENMASK(11, 10)
-+#define   ESPI_CTRL_VW_GPIO_SW			BIT(9)
-+#define   ESPI_CTRL_FLASH_SW_RDY		BIT(7)
-+#define   ESPI_CTRL_OOB_SW_RDY			BIT(4)
-+#define   ESPI_CTRL_VW_SW_RDY			BIT(3)
-+#define   ESPI_CTRL_PERIF_SW_RDY		BIT(1)
-+#define ESPI_STS				0x004
-+#define ESPI_INT_STS				0x008
-+#define   ESPI_INT_STS_RST_DEASSERT		BIT(31)
-+#define   ESPI_INT_STS_OOB_RX_TMOUT		BIT(23)
-+#define   ESPI_INT_STS_VW_SYSEVT1		BIT(22)
-+#define   ESPI_INT_STS_FLASH_TX_ERR		BIT(21)
-+#define   ESPI_INT_STS_OOB_TX_ERR		BIT(20)
-+#define   ESPI_INT_STS_FLASH_TX_ABT		BIT(19)
-+#define   ESPI_INT_STS_OOB_TX_ABT		BIT(18)
-+#define   ESPI_INT_STS_PERIF_NP_TX_ABT		BIT(17)
-+#define   ESPI_INT_STS_PERIF_PC_TX_ABT		BIT(16)
-+#define   ESPI_INT_STS_FLASH_RX_ABT		BIT(15)
-+#define   ESPI_INT_STS_OOB_RX_ABT		BIT(14)
-+#define   ESPI_INT_STS_PERIF_NP_RX_ABT		BIT(13)
-+#define   ESPI_INT_STS_PERIF_PC_RX_ABT		BIT(12)
-+#define   ESPI_INT_STS_PERIF_NP_TX_ERR		BIT(11)
-+#define   ESPI_INT_STS_PERIF_PC_TX_ERR		BIT(10)
-+#define   ESPI_INT_STS_VW_GPIO			BIT(9)
-+#define   ESPI_INT_STS_VW_SYSEVT		BIT(8)
-+#define   ESPI_INT_STS_FLASH_TX_CMPLT		BIT(7)
-+#define   ESPI_INT_STS_FLASH_RX_CMPLT		BIT(6)
-+#define   ESPI_INT_STS_OOB_TX_CMPLT		BIT(5)
-+#define   ESPI_INT_STS_OOB_RX_CMPLT		BIT(4)
-+#define   ESPI_INT_STS_PERIF_NP_TX_CMPLT	BIT(3)
-+#define   ESPI_INT_STS_PERIF_PC_TX_CMPLT	BIT(1)
-+#define   ESPI_INT_STS_PERIF_PC_RX_CMPLT	BIT(0)
-+#define ESPI_INT_EN				0x00c
-+#define   ESPI_INT_EN_RST_DEASSERT		BIT(31)
-+#define   ESPI_INT_EN_OOB_RX_TMOUT		BIT(23)
-+#define   ESPI_INT_EN_VW_SYSEVT1		BIT(22)
-+#define   ESPI_INT_EN_FLASH_TX_ERR		BIT(21)
-+#define   ESPI_INT_EN_OOB_TX_ERR		BIT(20)
-+#define   ESPI_INT_EN_FLASH_TX_ABT		BIT(19)
-+#define   ESPI_INT_EN_OOB_TX_ABT		BIT(18)
-+#define   ESPI_INT_EN_PERIF_NP_TX_ABT		BIT(17)
-+#define   ESPI_INT_EN_PERIF_PC_TX_ABT		BIT(16)
-+#define   ESPI_INT_EN_FLASH_RX_ABT		BIT(15)
-+#define   ESPI_INT_EN_OOB_RX_ABT		BIT(14)
-+#define   ESPI_INT_EN_PERIF_NP_RX_ABT		BIT(13)
-+#define   ESPI_INT_EN_PERIF_PC_RX_ABT		BIT(12)
-+#define   ESPI_INT_EN_PERIF_NP_TX_ERR		BIT(11)
-+#define   ESPI_INT_EN_PERIF_PC_TX_ERR		BIT(10)
-+#define   ESPI_INT_EN_VW_GPIO			BIT(9)
-+#define   ESPI_INT_EN_VW_SYSEVT			BIT(8)
-+#define   ESPI_INT_EN_FLASH_TX_CMPLT		BIT(7)
-+#define   ESPI_INT_EN_FLASH_RX_CMPLT		BIT(6)
-+#define   ESPI_INT_EN_OOB_TX_CMPLT		BIT(5)
-+#define   ESPI_INT_EN_OOB_RX_CMPLT		BIT(4)
-+#define   ESPI_INT_EN_PERIF_NP_TX_CMPLT		BIT(3)
-+#define   ESPI_INT_EN_PERIF_PC_TX_CMPLT		BIT(1)
-+#define   ESPI_INT_EN_PERIF_PC_RX_CMPLT		BIT(0)
-+#define ESPI_PERIF_PC_RX_DMA			0x010
-+#define ESPI_PERIF_PC_RX_CTRL			0x014
-+#define   ESPI_PERIF_PC_RX_CTRL_SERV_PEND	BIT(31)
-+#define   ESPI_PERIF_PC_RX_CTRL_LEN		GENMASK(23, 12)
-+#define   ESPI_PERIF_PC_RX_CTRL_TAG		GENMASK(11, 8)
-+#define   ESPI_PERIF_PC_RX_CTRL_CYC		GENMASK(7, 0)
-+#define ESPI_PERIF_PC_RX_DATA			0x018
-+#define ESPI_PERIF_PC_TX_DMA			0x020
-+#define ESPI_PERIF_PC_TX_CTRL			0x024
-+#define	  ESPI_PERIF_PC_TX_CTRL_TRIG_PEND	BIT(31)
-+#define	  ESPI_PERIF_PC_TX_CTRL_LEN		GENMASK(23, 12)
-+#define	  ESPI_PERIF_PC_TX_CTRL_TAG		GENMASK(11, 8)
-+#define	  ESPI_PERIF_PC_TX_CTRL_CYC		GENMASK(7, 0)
-+#define ESPI_PERIF_PC_TX_DATA			0x028
-+#define ESPI_PERIF_NP_TX_DMA			0x030
-+#define ESPI_PERIF_NP_TX_CTRL			0x034
-+#define   ESPI_PERIF_NP_TX_CTRL_TRIG_PEND	BIT(31)
-+#define	  ESPI_PERIF_NP_TX_CTRL_LEN		GENMASK(23, 12)
-+#define	  ESPI_PERIF_NP_TX_CTRL_TAG		GENMASK(11, 8)
-+#define	  ESPI_PERIF_NP_TX_CTRL_CYC		GENMASK(7, 0)
-+#define ESPI_PERIF_NP_TX_DATA			0x038
-+#define ESPI_OOB_RX_DMA				0x040
-+#define ESPI_OOB_RX_CTRL			0x044
-+#define	  ESPI_OOB_RX_CTRL_SERV_PEND		BIT(31)
-+#define	  ESPI_OOB_RX_CTRL_LEN			GENMASK(23, 12)
-+#define	  ESPI_OOB_RX_CTRL_TAG			GENMASK(11, 8)
-+#define	  ESPI_OOB_RX_CTRL_CYC			GENMASK(7, 0)
-+#define ESPI_OOB_RX_DATA			0x048
-+#define ESPI_OOB_TX_DMA				0x050
-+#define ESPI_OOB_TX_CTRL			0x054
-+#define	  ESPI_OOB_TX_CTRL_TRIG_PEND		BIT(31)
-+#define	  ESPI_OOB_TX_CTRL_LEN			GENMASK(23, 12)
-+#define	  ESPI_OOB_TX_CTRL_TAG			GENMASK(11, 8)
-+#define	  ESPI_OOB_TX_CTRL_CYC			GENMASK(7, 0)
-+#define ESPI_OOB_TX_DATA			0x058
-+#define ESPI_FLASH_RX_DMA			0x060
-+#define ESPI_FLASH_RX_CTRL			0x064
-+#define	  ESPI_FLASH_RX_CTRL_SERV_PEND		BIT(31)
-+#define	  ESPI_FLASH_RX_CTRL_LEN		GENMASK(23, 12)
-+#define	  ESPI_FLASH_RX_CTRL_TAG		GENMASK(11, 8)
-+#define	  ESPI_FLASH_RX_CTRL_CYC		GENMASK(7, 0)
-+#define ESPI_FLASH_RX_DATA			0x068
-+#define ESPI_FLASH_TX_DMA			0x070
-+#define ESPI_FLASH_TX_CTRL			0x074
-+#define	  ESPI_FLASH_TX_CTRL_TRIG_PEND		BIT(31)
-+#define	  ESPI_FLASH_TX_CTRL_LEN		GENMASK(23, 12)
-+#define	  ESPI_FLASH_TX_CTRL_TAG		GENMASK(11, 8)
-+#define	  ESPI_FLASH_TX_CTRL_CYC		GENMASK(7, 0)
-+#define ESPI_FLASH_TX_DATA			0x078
-+#define ESPI_CTRL2				0x080
-+#define   ESPI_CTRL2_VW_TX_SORT			BIT(30)
-+#define   ESPI_CTRL2_MCYC_RD_DIS_WDT		BIT(11)
-+#define   ESPI_CTRL2_MCYC_WR_DIS_WDT		BIT(10)
-+#define   ESPI_CTRL2_MCYC_RD_DIS		BIT(6)
-+#define   ESPI_CTRL2_MMBI_RD_DIS		ESPI_CTRL2_MCYC_RD_DIS
-+#define   ESPI_CTRL2_MCYC_WR_DIS		BIT(4)
-+#define   ESPI_CTRL2_MMBI_WR_DIS		ESPI_CTRL2_MCYC_WR_DIS
-+#define ESPI_PERIF_MCYC_SADDR			0x084
-+#define ESPI_PERIF_MMBI_SADDR			ESPI_PERIF_MCYC_SADDR
-+#define ESPI_PERIF_MCYC_TADDR			0x088
-+#define ESPI_PERIF_MMBI_TADDR			ESPI_PERIF_MCYC_TADDR
-+#define ESPI_PERIF_MCYC_MASK			0x08c
-+#define ESPI_PERIF_MMBI_MASK			ESPI_PERIF_MCYC_MASK
-+#define ESPI_FLASH_SAFS_TADDR			0x090
-+#define   ESPI_FLASH_SAFS_TADDR_BASE		GENMASK(31, 24)
-+#define   ESPI_FLASH_SAFS_TADDR_MASK		GENMASK(15, 8)
-+#define ESPI_VW_SYSEVT_INT_EN			0x094
-+#define ESPI_VW_SYSEVT				0x098
-+#define   ESPI_VW_SYSEVT_HOST_RST_ACK		BIT(27)
-+#define   ESPI_VW_SYSEVT_RST_CPU_INIT		BIT(26)
-+#define   ESPI_VW_SYSEVT_SLV_BOOT_STS		BIT(23)
-+#define   ESPI_VW_SYSEVT_NON_FATAL_ERR		BIT(22)
-+#define   ESPI_VW_SYSEVT_FATAL_ERR		BIT(21)
-+#define   ESPI_VW_SYSEVT_SLV_BOOT_DONE		BIT(20)
-+#define   ESPI_VW_SYSEVT_OOB_RST_ACK		BIT(16)
-+#define   ESPI_VW_SYSEVT_NMI_OUT		BIT(10)
-+#define   ESPI_VW_SYSEVT_SMI_OUT		BIT(9)
-+#define   ESPI_VW_SYSEVT_HOST_RST_WARN		BIT(8)
-+#define   ESPI_VW_SYSEVT_OOB_RST_WARN		BIT(6)
-+#define   ESPI_VW_SYSEVT_PLTRSTN		BIT(5)
-+#define   ESPI_VW_SYSEVT_SUSPEND		BIT(4)
-+#define   ESPI_VW_SYSEVT_S5_SLEEP		BIT(2)
-+#define   ESPI_VW_SYSEVT_S4_SLEEP		BIT(1)
-+#define   ESPI_VW_SYSEVT_S3_SLEEP		BIT(0)
-+#define ESPI_VW_GPIO_VAL			0x09c
-+#define ESPI_GEN_CAP_N_CONF			0x0a0
-+#define ESPI_CH0_CAP_N_CONF			0x0a4
-+#define ESPI_CH1_CAP_N_CONF			0x0a8
-+#define ESPI_CH2_CAP_N_CONF			0x0ac
-+#define ESPI_CH3_CAP_N_CONF			0x0b0
-+#define ESPI_CH3_CAP_N_CONF2			0x0b4
-+#define ESPI_VW_GPIO_DIR			0x0c0
-+#define ESPI_VW_GPIO_GRP			0x0c4
-+#define ESPI_INT_EN_CLR				0x0fc
-+#define ESPI_VW_SYSEVT1_INT_EN			0x100
-+#define ESPI_VW_SYSEVT1				0x104
-+#define   ESPI_VW_SYSEVT1_SUSPEND_ACK		BIT(20)
-+#define   ESPI_VW_SYSEVT1_SUSPEND_WARN		BIT(0)
-+#define ESPI_VW_SYSEVT_INT_T0			0x110
-+#define ESPI_VW_SYSEVT_INT_T1			0x114
-+#define ESPI_VW_SYSEVT_INT_T2			0x118
-+#define ESPI_VW_SYSEVT_INT_STS			0x11c
-+#define ESPI_VW_SYSEVT1_INT_T0			0x120
-+#define ESPI_VW_SYSEVT1_INT_T1			0x124
-+#define ESPI_VW_SYSEVT1_INT_T2			0x128
-+#define ESPI_VW_SYSEVT1_INT_STS			0x12c
-+#define ESPI_OOB_RX_DESC_NUM			0x130
-+#define ESPI_OOB_RX_DESC_RPTR			0x134
-+#define	  ESPI_OOB_RX_DESC_RPTR_UPDATE		BIT(31)
-+#define   ESPI_OOB_RX_DESC_RPTR_RP		GENMASK(11, 0)
-+#define ESPI_OOB_RX_DESC_WPTR			0x138
-+#define   ESPI_OOB_RX_DESC_WPTR_RECV_EN		BIT(31)
-+#define   ESPI_OOB_RX_DESC_WPTR_SP		GENMASK(27, 16)
-+#define   ESPI_OOB_RX_DESC_WPTR_WP		GENMASK(11, 0)
-+#define ESPI_OOB_TX_DESC_NUM			0x140
-+#define ESPI_OOB_TX_DESC_RPTR			0x144
-+#define	  ESPI_OOB_TX_DESC_RPTR_UPDATE		BIT(31)
-+#define ESPI_OOB_TX_DESC_WPTR			0x148
-+#define	  ESPI_OOB_TX_DESC_WPTR_SEND_EN		BIT(31)
-+#define ESPI_MMBI_CTRL				0x800
-+#define   ESPI_MMBI_CTRL_INST_SZ		GENMASK(10, 8)
-+#define   ESPI_MMBI_CTRL_TOTAL_SZ		GENMASK(6, 4)
-+#define   ESPI_MMBI_CTRL_EN			BIT(0)
-+#define ESPI_MMBI_INT_STS			0x808
-+#define ESPI_MMBI_INT_EN			0x80c
-+#define ESPI_MMBI_HOST_RWP(x)			(0x810 + ((x) << 3))
-+
-+/* collect ESPI_INT_EN bits for convenience */
-+#define ESPI_INT_EN_PERIF			\
-+	(ESPI_INT_EN_PERIF_NP_TX_ABT |		\
-+	 ESPI_INT_EN_PERIF_PC_TX_ABT |		\
-+	 ESPI_INT_EN_PERIF_NP_RX_ABT |		\
-+	 ESPI_INT_EN_PERIF_PC_RX_ABT |		\
-+	 ESPI_INT_EN_PERIF_NP_TX_ERR |		\
-+	 ESPI_INT_EN_PERIF_PC_TX_ERR |		\
-+	 ESPI_INT_EN_PERIF_NP_TX_CMPLT |	\
-+	 ESPI_INT_EN_PERIF_PC_TX_CMPLT |	\
-+	 ESPI_INT_EN_PERIF_PC_RX_CMPLT)
-+
-+#define ESPI_INT_EN_VW			\
-+	(ESPI_INT_EN_VW_SYSEVT1 |	\
-+	 ESPI_INT_EN_VW_GPIO    |	\
-+	 ESPI_INT_EN_VW_SYSEVT)
-+
-+#define ESPI_INT_EN_OOB		\
-+	(ESPI_INT_EN_OOB_RX_TMOUT |	\
-+	 ESPI_INT_EN_OOB_TX_ERR |	\
-+	 ESPI_INT_EN_OOB_TX_ABT |	\
-+	 ESPI_INT_EN_OOB_RX_ABT |	\
-+	 ESPI_INT_EN_OOB_TX_CMPLT |	\
-+	 ESPI_INT_EN_OOB_RX_CMPLT)
-+
-+#define ESPI_INT_EN_FLASH		\
-+	(ESPI_INT_EN_FLASH_TX_ERR |	\
-+	 ESPI_INT_EN_FLASH_TX_ABT |	\
-+	 ESPI_INT_EN_FLASH_RX_ABT |	\
-+	 ESPI_INT_EN_FLASH_TX_CMPLT |	\
-+	 ESPI_INT_EN_FLASH_RX_CMPLT)
-+
-+/* collect ESPI_INT_STS bits for convenience */
-+#define ESPI_INT_STS_PERIF			\
-+	(ESPI_INT_STS_PERIF_NP_TX_ABT |		\
-+	 ESPI_INT_STS_PERIF_PC_TX_ABT |		\
-+	 ESPI_INT_STS_PERIF_NP_RX_ABT |		\
-+	 ESPI_INT_STS_PERIF_PC_RX_ABT |		\
-+	 ESPI_INT_STS_PERIF_NP_TX_ERR |		\
-+	 ESPI_INT_STS_PERIF_PC_TX_ERR |		\
-+	 ESPI_INT_STS_PERIF_NP_TX_CMPLT |	\
-+	 ESPI_INT_STS_PERIF_PC_TX_CMPLT |	\
-+	 ESPI_INT_STS_PERIF_PC_RX_CMPLT)
-+
-+#define ESPI_INT_STS_VW			\
-+	(ESPI_INT_STS_VW_SYSEVT1 |	\
-+	 ESPI_INT_STS_VW_GPIO    |	\
-+	 ESPI_INT_STS_VW_SYSEVT)
-+
-+#define ESPI_INT_STS_OOB		\
-+	(ESPI_INT_STS_OOB_RX_TMOUT |	\
-+	 ESPI_INT_STS_OOB_TX_ERR |	\
-+	 ESPI_INT_STS_OOB_TX_ABT |	\
-+	 ESPI_INT_STS_OOB_RX_ABT |	\
-+	 ESPI_INT_STS_OOB_TX_CMPLT |	\
-+	 ESPI_INT_STS_OOB_RX_CMPLT)
-+
-+#define ESPI_INT_STS_FLASH		\
-+	(ESPI_INT_STS_FLASH_TX_ERR |	\
-+	 ESPI_INT_STS_FLASH_TX_ABT |	\
-+	 ESPI_INT_STS_FLASH_RX_ABT |	\
-+	 ESPI_INT_STS_FLASH_TX_CMPLT |	\
-+	 ESPI_INT_STS_FLASH_RX_CMPLT)
-+
-+/* consistent with DTS property "flash-safs-mode" */
-+enum ast2600_safs_mode {
-+	SAFS_MODE_MIX = 0x0,
-+	SAFS_MODE_SW,
-+	SAFS_MODE_HW,
-+	SAFS_MODES,
-+};
-+
-+/* consistent with DTS property "perif-mmbi-instance-size" */
-+enum ast2600_mmbi_instance_size {
-+	MMBI_INST_SIZE_8KB = 0x0,
-+	MMBI_INST_SIZE_16KB,
-+	MMBI_INST_SIZE_32KB,
-+	MMBI_INST_SIZE_64KB,
-+	MMBI_INST_SIZE_128KB,
-+	MMBI_INST_SIZE_256KB,
-+	MMBI_INST_SIZE_512KB,
-+	MMBI_INST_SIZE_1024KB,
-+	MMBI_INST_SIZE_TYPES,
-+};
-+
-+#endif
-diff --git a/drivers/soc/aspeed/ast2600-otp.c b/drivers/soc/aspeed/ast2600-otp.c
-new file mode 100644
-index 000000000..abe3a108f
---- /dev/null
-+++ b/drivers/soc/aspeed/ast2600-otp.c
-@@ -0,0 +1,640 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Copyright (C) ASPEED Technology Inc.
-+ */
-+
-+#include <linux/errno.h>
-+#include <linux/fs.h>
-+#include <linux/miscdevice.h>
-+#include <linux/slab.h>
-+#include <linux/platform_device.h>
-+#include <linux/regmap.h>
-+#include <linux/spinlock.h>
-+#include <linux/uaccess.h>
-+#include <linux/mfd/syscon.h>
-+#include <linux/of.h>
-+#include <linux/module.h>
-+#include <asm/io.h>
-+#include <uapi/linux/otp_ast2600.h>
-+#include <linux/soc/aspeed/aspeed-otp.h>
-+
-+#define ASPEED_REVISION_ID0	0x04
-+#define ASPEED_REVISION_ID1	0x14
-+#define ID0_AST2600A0	0x05000303
-+#define ID1_AST2600A0	0x05000303
-+#define ID0_AST2600A1	0x05010303
-+#define ID1_AST2600A1	0x05010303
-+#define ID0_AST2600A2	0x05010303
-+#define ID1_AST2600A2	0x05020303
-+#define ID0_AST2600A3	0x05030303
-+#define ID1_AST2600A3	0x05030303
-+#define ID0_AST2620A1	0x05010203
-+#define ID1_AST2620A1	0x05010203
-+#define ID0_AST2620A2	0x05010203
-+#define ID1_AST2620A2	0x05020203
-+#define ID0_AST2620A3	0x05030203
-+#define ID1_AST2620A3	0x05030203
-+#define ID0_AST2605A2	0x05010103
-+#define ID1_AST2605A2	0x05020103
-+#define ID0_AST2605A3	0x05030103
-+#define ID1_AST2605A3	0x05030103
-+#define ID0_AST2625A3	0x05030403
-+#define ID1_AST2625A3	0x05030403
-+
-+#define OTP_PROTECT_KEY	0x0
-+#define  OTP_PASSWD	0x349fe38a
-+#define OTP_COMMAND	0x4
-+#define OTP_TIMING	0x8
-+#define OTP_ADDR	0x10
-+#define OTP_STATUS	0x14
-+#define OTP_COMPARE_1	0x20
-+#define OTP_COMPARE_2	0x24
-+#define OTP_COMPARE_3	0x28
-+#define OTP_COMPARE_4	0x2c
-+#define SW_REV_ID0	0x68
-+#define SW_REV_ID1	0x6c
-+#define SEC_KEY_NUM	0x78
-+#define RETRY		20
-+
-+struct aspeed_otp {
-+	struct miscdevice miscdev;
-+	void __iomem *reg_base;
-+	bool is_open;
-+	u32 otp_ver;
-+	u32 *data;
-+};
-+
-+static DEFINE_SPINLOCK(otp_state_lock);
-+
-+static inline u32 aspeed_otp_read(struct aspeed_otp *ctx, u32 reg)
-+{
-+	int val;
-+
-+	val = readl(ctx->reg_base + reg);
-+	// printk("read:reg = 0x%08x, val = 0x%08x\n", reg, val);
-+	return val;
-+}
-+
-+static inline void aspeed_otp_write(struct aspeed_otp *ctx, u32 val, u32 reg)
-+{
-+	// printk("write:reg = 0x%08x, val = 0x%08x\n", reg, val);
-+	writel(val, ctx->reg_base + reg);
-+}
-+
-+static uint32_t chip_version(u32 revid0, u32 revid1)
-+{
-+	if (revid0 == ID0_AST2600A0 && revid1 == ID1_AST2600A0) {
-+		/* AST2600-A0 */
-+		return OTP_A0;
-+	} else if (revid0 == ID0_AST2600A1 && revid1 == ID1_AST2600A1) {
-+		/* AST2600-A1 */
-+		return OTP_A1;
-+	} else if (revid0 == ID0_AST2600A2 && revid1 == ID1_AST2600A2) {
-+		/* AST2600-A2 */
-+		return OTP_A2;
-+	} else if (revid0 == ID0_AST2600A3 && revid1 == ID1_AST2600A3) {
-+		/* AST2600-A3 */
-+		return OTP_A3;
-+	} else if (revid0 == ID0_AST2620A1 && revid1 == ID1_AST2620A1) {
-+		/* AST2620-A1 */
-+		return OTP_A1;
-+	} else if (revid0 == ID0_AST2620A2 && revid1 == ID1_AST2620A2) {
-+		/* AST2620-A2 */
-+		return OTP_A2;
-+	} else if (revid0 == ID0_AST2620A3 && revid1 == ID1_AST2620A3) {
-+		/* AST2620-A3 */
-+		return OTP_A3;
-+	} else if (revid0 == ID0_AST2605A2 && revid1 == ID1_AST2605A2) {
-+		/* AST2605-A2 */
-+		return OTP_A2;
-+	} else if (revid0 == ID0_AST2605A3 && revid1 == ID1_AST2605A3) {
-+		/* AST2605-A3 */
-+		return OTP_A3;
-+	} else if (revid0 == ID0_AST2625A3 && revid1 == ID1_AST2625A3) {
-+		/* AST2605-A3 */
-+		return OTP_A3;
-+	}
-+	return -1;
-+}
-+
-+static void wait_complete(struct aspeed_otp *ctx)
-+{
-+	int reg;
-+	int i = 0;
-+
-+	do {
-+		reg = aspeed_otp_read(ctx, OTP_STATUS);
-+		if ((reg & 0x6) == 0x6)
-+			i++;
-+	} while (i != 2);
-+}
-+
-+static void otp_write(struct aspeed_otp *ctx, u32 otp_addr, u32 val)
-+{
-+	aspeed_otp_write(ctx, otp_addr, OTP_ADDR); //write address
-+	aspeed_otp_write(ctx, val, OTP_COMPARE_1); //write val
-+	aspeed_otp_write(ctx, 0x23b1e362, OTP_COMMAND); //write command
-+	wait_complete(ctx);
-+}
-+
-+static void otp_soak(struct aspeed_otp *ctx, int soak)
-+{
-+	if (ctx->otp_ver == OTP_A2 || ctx->otp_ver == OTP_A3) {
-+		switch (soak) {
-+		case 0: //default
-+			otp_write(ctx, 0x3000, 0x0); // Write MRA
-+			otp_write(ctx, 0x5000, 0x0); // Write MRB
-+			otp_write(ctx, 0x1000, 0x0); // Write MR
-+			break;
-+		case 1: //normal program
-+			otp_write(ctx, 0x3000, 0x1320); // Write MRA
-+			otp_write(ctx, 0x5000, 0x1008); // Write MRB
-+			otp_write(ctx, 0x1000, 0x0024); // Write MR
-+			aspeed_otp_write(ctx, 0x04191388, OTP_TIMING); // 200us
-+			break;
-+		case 2: //soak program
-+			otp_write(ctx, 0x3000, 0x1320); // Write MRA
-+			otp_write(ctx, 0x5000, 0x0007); // Write MRB
-+			otp_write(ctx, 0x1000, 0x0100); // Write MR
-+			aspeed_otp_write(ctx, 0x04193a98, OTP_TIMING); // 600us
-+			break;
-+		}
-+	} else {
-+		switch (soak) {
-+		case 0: //default
-+			otp_write(ctx, 0x3000, 0x0); // Write MRA
-+			otp_write(ctx, 0x5000, 0x0); // Write MRB
-+			otp_write(ctx, 0x1000, 0x0); // Write MR
-+			break;
-+		case 1: //normal program
-+			otp_write(ctx, 0x3000, 0x4021); // Write MRA
-+			otp_write(ctx, 0x5000, 0x302f); // Write MRB
-+			otp_write(ctx, 0x1000, 0x4020); // Write MR
-+			aspeed_otp_write(ctx, 0x04190760, OTP_TIMING); // 75us
-+			break;
-+		case 2: //soak program
-+			otp_write(ctx, 0x3000, 0x4021); // Write MRA
-+			otp_write(ctx, 0x5000, 0x1027); // Write MRB
-+			otp_write(ctx, 0x1000, 0x4820); // Write MR
-+			aspeed_otp_write(ctx, 0x041930d4, OTP_TIMING); // 500us
-+			break;
-+		}
-+	}
-+
-+	wait_complete(ctx);
-+}
-+
-+static int verify_bit(struct aspeed_otp *ctx, u32 otp_addr, int bit_offset, int value)
-+{
-+	u32 ret[2];
-+
-+	if (otp_addr % 2 == 0)
-+		aspeed_otp_write(ctx, otp_addr, OTP_ADDR); //Read address
-+	else
-+		aspeed_otp_write(ctx, otp_addr - 1, OTP_ADDR); //Read address
-+
-+	aspeed_otp_write(ctx, 0x23b1e361, OTP_COMMAND); //trigger read
-+	wait_complete(ctx);
-+	ret[0] = aspeed_otp_read(ctx, OTP_COMPARE_1);
-+	ret[1] = aspeed_otp_read(ctx, OTP_COMPARE_2);
-+
-+	if (otp_addr % 2 == 0) {
-+		if (((ret[0] >> bit_offset) & 1) == value)
-+			return 0;
-+		else
-+			return -1;
-+	} else {
-+		if (((ret[1] >> bit_offset) & 1) == value)
-+			return 0;
-+		else
-+			return -1;
-+	}
-+}
-+
-+static void otp_prog(struct aspeed_otp *ctx, u32 otp_addr, u32 prog_bit)
-+{
-+	otp_write(ctx, 0x0, prog_bit);
-+	aspeed_otp_write(ctx, otp_addr, OTP_ADDR); //write address
-+	aspeed_otp_write(ctx, prog_bit, OTP_COMPARE_1); //write data
-+	aspeed_otp_write(ctx, 0x23b1e364, OTP_COMMAND); //write command
-+	wait_complete(ctx);
-+}
-+
-+static void _otp_prog_bit(struct aspeed_otp *ctx, u32 value, u32 prog_address, u32 bit_offset)
-+{
-+	int prog_bit;
-+
-+	if (prog_address % 2 == 0) {
-+		if (value)
-+			prog_bit = ~(0x1 << bit_offset);
-+		else
-+			return;
-+	} else {
-+		if (ctx->otp_ver != OTP_A3)
-+			prog_address |= 1 << 15;
-+		if (!value)
-+			prog_bit = 0x1 << bit_offset;
-+		else
-+			return;
-+	}
-+	otp_prog(ctx, prog_address, prog_bit);
-+}
-+
-+static int otp_prog_bit(struct aspeed_otp *ctx, u32 value, u32 prog_address, u32 bit_offset)
-+{
-+	int pass;
-+	int i;
-+
-+	otp_soak(ctx, 1);
-+	_otp_prog_bit(ctx, value, prog_address, bit_offset);
-+	pass = 0;
-+
-+	for (i = 0; i < RETRY; i++) {
-+		if (verify_bit(ctx, prog_address, bit_offset, value) != 0) {
-+			otp_soak(ctx, 2);
-+			_otp_prog_bit(ctx, value, prog_address, bit_offset);
-+			if (verify_bit(ctx, prog_address, bit_offset, value) != 0) {
-+				otp_soak(ctx, 1);
-+			} else {
-+				pass = 1;
-+				break;
-+			}
-+		} else {
-+			pass = 1;
-+			break;
-+		}
-+	}
-+	otp_soak(ctx, 0);
-+	return pass;
-+}
-+
-+static void otp_read_conf_dw(struct aspeed_otp *ctx, u32 offset, u32 *buf)
-+{
-+	u32 config_offset;
-+
-+	config_offset = 0x800;
-+	config_offset |= (offset / 8) * 0x200;
-+	config_offset |= (offset % 8) * 0x2;
-+
-+	aspeed_otp_write(ctx, config_offset, OTP_ADDR); //Read address
-+	aspeed_otp_write(ctx, 0x23b1e361, OTP_COMMAND); //trigger read
-+	wait_complete(ctx);
-+	buf[0] = aspeed_otp_read(ctx, OTP_COMPARE_1);
-+}
-+
-+static void otp_read_conf(struct aspeed_otp *ctx, u32 offset, u32 len)
-+{
-+	int i, j;
-+
-+	otp_soak(ctx, 0);
-+	for (i = offset, j = 0; j < len; i++, j++)
-+		otp_read_conf_dw(ctx, i, &ctx->data[j]);
-+}
-+
-+static void otp_read_data_2dw(struct aspeed_otp *ctx, u32 offset, u32 *buf)
-+{
-+	aspeed_otp_write(ctx, offset, OTP_ADDR); //Read address
-+	aspeed_otp_write(ctx, 0x23b1e361, OTP_COMMAND); //trigger read
-+	wait_complete(ctx);
-+	buf[0] = aspeed_otp_read(ctx, OTP_COMPARE_1);
-+	buf[1] = aspeed_otp_read(ctx, OTP_COMPARE_2);
-+}
-+
-+static void otp_read_data(struct aspeed_otp *ctx, u32 offset, u32 len)
-+{
-+	int i, j;
-+	u32 ret[2];
-+
-+	otp_soak(ctx, 0);
-+
-+	i = offset;
-+	j = 0;
-+	if (offset % 2) {
-+		otp_read_data_2dw(ctx, i - 1, ret);
-+		ctx->data[0] = ret[1];
-+		i++;
-+		j++;
-+	}
-+	for (; j < len; i += 2, j += 2)
-+		otp_read_data_2dw(ctx, i, &ctx->data[j]);
-+}
-+
-+static int otp_prog_data(struct aspeed_otp *ctx, u32 value, u32 dw_offset, u32 bit_offset)
-+{
-+	u32 read[2];
-+	int otp_bit;
-+
-+	if (dw_offset % 2 == 0) {
-+		otp_read_data_2dw(ctx, dw_offset, read);
-+		otp_bit = (read[0] >> bit_offset) & 0x1;
-+
-+		if (otp_bit == 1 && value == 0) {
-+			pr_err("OTPDATA%X[%X] = 1\n", dw_offset, bit_offset);
-+			pr_err("OTP is programed, which can't be cleaned\n");
-+			return -EINVAL;
-+		}
-+	} else {
-+		otp_read_data_2dw(ctx, dw_offset - 1, read);
-+		otp_bit = (read[1] >> bit_offset) & 0x1;
-+
-+		if (otp_bit == 0 && value == 1) {
-+			pr_err("OTPDATA%X[%X] = 1\n", dw_offset, bit_offset);
-+			pr_err("OTP is programed, which can't be writen\n");
-+			return -EINVAL;
-+		}
-+	}
-+	if (otp_bit == value) {
-+		pr_err("OTPDATA%X[%X] = %d\n", dw_offset, bit_offset, value);
-+		pr_err("No need to program\n");
-+		return 0;
-+	}
-+
-+	return otp_prog_bit(ctx, value, dw_offset, bit_offset);
-+}
-+
-+static int otp_prog_conf(struct aspeed_otp *ctx, u32 value, u32 dw_offset, u32 bit_offset)
-+{
-+	u32 read;
-+	u32 prog_address = 0;
-+	int otp_bit;
-+
-+	otp_read_conf_dw(ctx, dw_offset, &read);
-+
-+	prog_address = 0x800;
-+	prog_address |= (dw_offset / 8) * 0x200;
-+	prog_address |= (dw_offset % 8) * 0x2;
-+	otp_bit = (read >> bit_offset) & 0x1;
-+	if (otp_bit == value) {
-+		pr_err("OTPCFG%X[%X] = %d\n", dw_offset, bit_offset, value);
-+		pr_err("No need to program\n");
-+		return 0;
-+	}
-+	if (otp_bit == 1 && value == 0) {
-+		pr_err("OTPCFG%X[%X] = 1\n", dw_offset, bit_offset);
-+		pr_err("OTP is programed, which can't be clean\n");
-+		return -EINVAL;
-+	}
-+
-+	return otp_prog_bit(ctx, value, prog_address, bit_offset);
-+}
-+
-+struct aspeed_otp *glob_ctx;
-+
-+void otp_read_data_buf(u32 offset, u32 *buf, u32 len)
-+{
-+	int i, j;
-+	u32 ret[2];
-+
-+	aspeed_otp_write(glob_ctx, OTP_PASSWD, OTP_PROTECT_KEY);
-+
-+	otp_soak(glob_ctx, 0);
-+
-+	i = offset;
-+	j = 0;
-+	if (offset % 2) {
-+		otp_read_data_2dw(glob_ctx, i - 1, ret);
-+		buf[0] = ret[1];
-+		i++;
-+		j++;
-+	}
-+	for (; j < len; i += 2, j += 2)
-+		otp_read_data_2dw(glob_ctx, i, &buf[j]);
-+	aspeed_otp_write(glob_ctx, 0, OTP_PROTECT_KEY);
-+}
-+EXPORT_SYMBOL(otp_read_data_buf);
-+
-+void otp_read_conf_buf(u32 offset, u32 *buf, u32 len)
-+{
-+	int i, j;
-+
-+	aspeed_otp_write(glob_ctx, OTP_PASSWD, OTP_PROTECT_KEY);
-+	otp_soak(glob_ctx, 0);
-+	for (i = offset, j = 0; j < len; i++, j++)
-+		otp_read_conf_dw(glob_ctx, i, &buf[j]);
-+	aspeed_otp_write(glob_ctx, 0, OTP_PROTECT_KEY);
-+}
-+EXPORT_SYMBOL(otp_read_conf_buf);
-+
-+static long otp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-+{
-+	struct miscdevice *c = file->private_data;
-+	struct aspeed_otp *ctx = container_of(c, struct aspeed_otp, miscdev);
-+	void __user *argp = (void __user *)arg;
-+	struct otp_read xfer;
-+	struct otp_prog prog;
-+	u32 reg_read[2];
-+	int ret = 0;
-+
-+	switch (cmd) {
-+	case ASPEED_OTP_READ_DATA:
-+		if (copy_from_user(&xfer, argp, sizeof(struct otp_read)))
-+			return -EFAULT;
-+		if ((xfer.offset + xfer.len) > 0x800) {
-+			pr_err("out of range");
-+			return -EINVAL;
-+		}
-+
-+		aspeed_otp_write(ctx, OTP_PASSWD, OTP_PROTECT_KEY);
-+		otp_read_data(ctx, xfer.offset, xfer.len);
-+		aspeed_otp_write(ctx, 0, OTP_PROTECT_KEY);
-+
-+		if (copy_to_user(xfer.data, ctx->data, xfer.len * 4))
-+			return -EFAULT;
-+		if (copy_to_user(argp, &xfer, sizeof(struct otp_read)))
-+			return -EFAULT;
-+		break;
-+	case ASPEED_OTP_READ_CONF:
-+		if (copy_from_user(&xfer, argp, sizeof(struct otp_read)))
-+			return -EFAULT;
-+		if ((xfer.offset + xfer.len) > 0x800) {
-+			pr_err("out of range");
-+			return -EINVAL;
-+		}
-+
-+		aspeed_otp_write(ctx, OTP_PASSWD, OTP_PROTECT_KEY);
-+		otp_read_conf(ctx, xfer.offset, xfer.len);
-+		aspeed_otp_write(ctx, 0, OTP_PROTECT_KEY);
-+
-+		if (copy_to_user(xfer.data, ctx->data, xfer.len * 4))
-+			return -EFAULT;
-+		if (copy_to_user(argp, &xfer, sizeof(struct otp_read)))
-+			return -EFAULT;
-+		break;
-+	case ASPEED_OTP_PROG_DATA:
-+		if (copy_from_user(&prog, argp, sizeof(struct otp_prog)))
-+			return -EFAULT;
-+		if (prog.bit_offset >= 32 || (prog.value != 0 && prog.value != 1)) {
-+			pr_err("out of range");
-+			return -EINVAL;
-+		}
-+		if (prog.dw_offset >= 0x800) {
-+			pr_err("out of range");
-+			return -EINVAL;
-+		}
-+		aspeed_otp_write(ctx, OTP_PASSWD, OTP_PROTECT_KEY);
-+		ret = otp_prog_data(ctx, prog.value, prog.dw_offset, prog.bit_offset);
-+		break;
-+	case ASPEED_OTP_PROG_CONF:
-+		if (copy_from_user(&prog, argp, sizeof(struct otp_prog)))
-+			return -EFAULT;
-+		if (prog.bit_offset >= 32 || (prog.value != 0 && prog.value != 1)) {
-+			pr_err("out of range");
-+			return -EINVAL;
-+		}
-+		if (prog.dw_offset >= 0x20) {
-+			pr_err("out of range");
-+			return -EINVAL;
-+		}
-+		aspeed_otp_write(ctx, OTP_PASSWD, OTP_PROTECT_KEY);
-+		ret = otp_prog_conf(ctx, prog.value, prog.dw_offset, prog.bit_offset);
-+		break;
-+	case ASPEED_OTP_VER:
-+		if (copy_to_user(argp, &ctx->otp_ver, sizeof(u32)))
-+			return -EFAULT;
-+		break;
-+	case ASPEED_OTP_SW_RID:
-+		reg_read[0] = aspeed_otp_read(ctx, SW_REV_ID0);
-+		reg_read[1] = aspeed_otp_read(ctx, SW_REV_ID1);
-+		if (copy_to_user(argp, reg_read, sizeof(u32) * 2))
-+			return -EFAULT;
-+		break;
-+	case ASPEED_SEC_KEY_NUM:
-+		reg_read[0] = aspeed_otp_read(ctx, SEC_KEY_NUM) & 7;
-+		if (copy_to_user(argp, reg_read, sizeof(u32)))
-+			return -EFAULT;
-+		break;
-+	}
-+	return ret;
-+}
-+
-+static int otp_open(struct inode *inode, struct file *file)
-+{
-+	struct miscdevice *c = file->private_data;
-+	struct aspeed_otp *ctx = container_of(c, struct aspeed_otp, miscdev);
-+
-+	spin_lock(&otp_state_lock);
-+
-+	if (ctx->is_open) {
-+		spin_unlock(&otp_state_lock);
-+		return -EBUSY;
-+	}
-+
-+	ctx->is_open = true;
-+
-+	spin_unlock(&otp_state_lock);
-+
-+	return 0;
-+}
-+
-+static int otp_release(struct inode *inode, struct file *file)
-+{
-+	struct miscdevice *c = file->private_data;
-+	struct aspeed_otp *ctx = container_of(c, struct aspeed_otp, miscdev);
-+
-+	spin_lock(&otp_state_lock);
-+
-+	ctx->is_open = false;
-+
-+	spin_unlock(&otp_state_lock);
-+
-+	return 0;
-+}
-+
-+static const struct file_operations otp_fops = {
-+	.owner =		THIS_MODULE,
-+	.unlocked_ioctl =	otp_ioctl,
-+	.open =			otp_open,
-+	.release =		otp_release,
-+};
-+
-+static const struct of_device_id aspeed_otp_of_matches[] = {
-+	{ .compatible = "aspeed,ast2600-sbc" },
-+	{ }
-+};
-+MODULE_DEVICE_TABLE(of, aspeed_otp_of_matches);
-+
-+static int aspeed_otp_probe(struct platform_device *pdev)
-+{
-+	struct device *dev = &pdev->dev;
-+	struct regmap *scu;
-+	struct aspeed_otp *priv;
-+	struct resource *res;
-+	u32 revid0, revid1;
-+	int rc;
-+
-+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-+	glob_ctx = priv;
-+	if (!priv)
-+		return -ENOMEM;
-+
-+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+	if (!res) {
-+		dev_err(&pdev->dev, "cannot get IORESOURCE_MEM\n");
-+		return -ENOENT;
-+	}
-+
-+	priv->reg_base = devm_ioremap_resource(&pdev->dev, res);
-+	if (!priv->reg_base)
-+		return -EIO;
-+
-+	scu = syscon_regmap_lookup_by_phandle(dev->of_node, "aspeed,scu");
-+	if (IS_ERR(scu)) {
-+		dev_err(dev, "failed to find 2600 SCU regmap\n");
-+		return PTR_ERR(scu);
-+	}
-+
-+	regmap_read(scu, ASPEED_REVISION_ID0, &revid0);
-+	regmap_read(scu, ASPEED_REVISION_ID1, &revid1);
-+
-+	priv->otp_ver = chip_version(revid0, revid1);
-+
-+	if (priv->otp_ver == -1) {
-+		dev_err(dev, "invalid SCU\n");
-+		return -EINVAL;
-+	}
-+
-+	priv->data = kmalloc(8192, GFP_KERNEL);
-+	if (!priv->data)
-+		return -ENOMEM;
-+
-+	dev_set_drvdata(dev, priv);
-+
-+	/* Set up the miscdevice */
-+	priv->miscdev.minor = MISC_DYNAMIC_MINOR;
-+	priv->miscdev.name = "aspeed-otp";
-+	priv->miscdev.fops = &otp_fops;
-+
-+	/* Register the device */
-+	rc = misc_register(&priv->miscdev);
-+	if (rc) {
-+		dev_err(dev, "Unable to register device\n");
-+		return rc;
-+	}
-+
-+	return 0;
-+}
-+
-+static int aspeed_otp_remove(struct platform_device *pdev)
-+{
-+	struct aspeed_otp *ctx = dev_get_drvdata(&pdev->dev);
-+
-+	kfree(ctx->data);
-+	misc_deregister(&ctx->miscdev);
-+
-+	return 0;
-+}
-+
-+static struct platform_driver aspeed_otp_driver = {
-+	.probe = aspeed_otp_probe,
-+	.remove = aspeed_otp_remove,
-+	.driver = {
-+		.name = KBUILD_MODNAME,
-+		.of_match_table = aspeed_otp_of_matches,
-+	},
-+};
-+
-+module_platform_driver(aspeed_otp_driver);
-+
-+MODULE_AUTHOR("Neal Liu <neal_liu@aspeedtech.com>");
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("ASPEED OTP Driver");
 diff --git a/drivers/soc/aspeed/ast2700-espi.c b/drivers/soc/aspeed/ast2700-espi.c
-new file mode 100644
-index 000000000..bd5f3dae9
+new file mode 100755
+index 000000000..c5dd2c093
 --- /dev/null
 +++ b/drivers/soc/aspeed/ast2700-espi.c
-@@ -0,0 +1,2228 @@
+@@ -0,0 +1,2262 @@
 +// SPDX-License-Identifier: GPL-2.0+
 +/*
 + * Copyright 2023 Aspeed Technology Inc.
@@ -14435,6 +9965,7 @@
 +		dma_addr_t pc_rx_addr;
 +	} dma;
 +
++	bool rtc_enable;
 +	bool rx_ready;
 +	wait_queue_head_t wq;
 +
@@ -15006,6 +10537,33 @@
 +	}
 +}
 +
++static void ast2700_espi_perif_sw_reset(struct ast2700_espi *espi)
++{
++	struct device *dev;
++	uint32_t reg;
++
++	dev = espi->dev;
++
++	reg = readl(espi->regs + ESPI_CH0_CTRL);
++	reg &= ~(ESPI_CH0_CTRL_NP_TX_RST
++		 | ESPI_CH0_CTRL_NP_RX_RST
++		 | ESPI_CH0_CTRL_PC_TX_RST
++		 | ESPI_CH0_CTRL_PC_RX_RST
++		 | ESPI_CH0_CTRL_NP_TX_DMA_EN
++		 | ESPI_CH0_CTRL_PC_TX_DMA_EN
++		 | ESPI_CH0_CTRL_PC_RX_DMA_EN
++		 | ESPI_CH0_CTRL_SW_RDY);
++	writel(reg, espi->regs + ESPI_CH0_CTRL);
++
++	udelay(1);
++
++	reg |= (ESPI_CH0_CTRL_NP_TX_RST
++		| ESPI_CH0_CTRL_NP_RX_RST
++		| ESPI_CH0_CTRL_PC_TX_RST
++		| ESPI_CH0_CTRL_PC_RX_RST);
++	writel(reg, espi->regs + ESPI_CH0_CTRL);
++}
++
 +static void ast2700_espi_perif_reset(struct ast2700_espi *espi)
 +{
 +	struct ast2700_espi_perif *perif;
@@ -15037,24 +10595,12 @@
 +
 +	reg = readl(espi->regs + ESPI_CH0_CTRL);
 +	reg |= (ESPI_CH0_CTRL_MCYC_RD_DIS | ESPI_CH0_CTRL_MCYC_WR_DIS);
-+	reg &= ~(ESPI_CH0_CTRL_NP_TX_RST
-+		 | ESPI_CH0_CTRL_NP_RX_RST
-+		 | ESPI_CH0_CTRL_PC_TX_RST
-+		 | ESPI_CH0_CTRL_PC_RX_RST
-+		 | ESPI_CH0_CTRL_NP_TX_DMA_EN
++	reg &= ~(ESPI_CH0_CTRL_NP_TX_DMA_EN
 +		 | ESPI_CH0_CTRL_PC_TX_DMA_EN
 +		 | ESPI_CH0_CTRL_PC_RX_DMA_EN
 +		 | ESPI_CH0_CTRL_SW_RDY);
 +	writel(reg, espi->regs + ESPI_CH0_CTRL);
 +
-+	udelay(1);
-+
-+	reg |= (ESPI_CH0_CTRL_NP_TX_RST
-+		| ESPI_CH0_CTRL_NP_RX_RST
-+		| ESPI_CH0_CTRL_PC_TX_RST
-+		| ESPI_CH0_CTRL_PC_RX_RST);
-+	writel(reg, espi->regs + ESPI_CH0_CTRL);
-+
 +	if (perif->mmbi.enable) {
 +		reg = readl(espi->regs + ESPI_MMBI_CTRL);
 +		reg &= ~ESPI_MMBI_CTRL_EN;
@@ -15113,6 +10659,11 @@
 +		      | ESPI_CH0_CTRL_PC_RX_DMA_EN;
 +		writel(reg, espi->regs + ESPI_CH0_CTRL);
 +	}
++	if (perif->rtc_enable) {
++		reg = readl(espi->regs + ESPI_CAP_GEN)
++		      | ESPI_CAP_GEN_RTC_SUP;
++		writel(reg, espi->regs + ESPI_CAP_GEN);
++	}
 +
 +	writel(ESPI_CH0_INT_EN_PC_RX_CMPLT, espi->regs + ESPI_CH0_INT_EN);
 +
@@ -15273,6 +10824,7 @@
 +			return -ENOMEM;
 +		}
 +	}
++	perif->rtc_enable = of_property_read_bool(dev->of_node, "perif-rtc-enable");
 +
 +	perif->mdev.parent = dev;
 +	perif->mdev.minor = MISC_DYNAMIC_MINOR;
@@ -16278,7 +11830,10 @@
 +static int ast2700_espi_flash_probe(struct ast2700_espi *espi)
 +{
 +	struct ast2700_espi_flash *flash;
++	struct device_node *np;
++	struct resource res;
 +	struct device *dev;
++	void *virt;
 +	int rc;
 +
 +	dev = espi->dev;
@@ -16295,18 +11850,26 @@
 +	flash->edaf.mode = EDAF_MODE_HW;
 +
 +	of_property_read_u32(dev->of_node, "flash-edaf-mode", &flash->edaf.mode);
++	dev_err(dev, "eDAF mode: 0x%x\n", flash->edaf.mode);
 +	if (flash->edaf.mode == EDAF_MODE_MIX) {
-+		rc = of_property_read_u64(dev->of_node, "flash-edaf-tgt-addr", &flash->edaf.taddr);
-+		if (rc || !IS_ALIGNED(flash->edaf.taddr, FLASH_EDAF_ALIGN)) {
-+			dev_err(dev, "cannot get 16MB-aligned eDAF address\n");
++		np = of_parse_phandle(dev->of_node, "flash-edaf-tgt-addr", 0);
++		if (!np || of_address_to_resource(np, 0, &res)) {
++			dev_err(dev, "cannot get eDAF memory region\n");
 +			return -ENODEV;
 +		}
 +
-+		rc = of_property_read_u64(dev->of_node, "flash-edaf-size", &flash->edaf.size);
-+		if (rc || !IS_ALIGNED(flash->edaf.size, FLASH_EDAF_ALIGN)) {
-+			dev_err(dev, "cannot get 16MB-aligned eDAF size\n");
-+			return -ENODEV;
-+		}
++		of_node_put(np);
++
++		flash->edaf.taddr = res.start;
++		flash->edaf.size = resource_size(&res);
++		dev_err(dev, "eDAF address: 0x%llx\n", flash->edaf.taddr);
++		dev_err(dev, "eDAF size: 0x%llx\n", flash->edaf.size);
++	}
++
++	virt = devm_ioremap_resource(dev, &res);
++	if (!virt) {
++		dev_err(dev, "cannot map MMBI memory region\n");
++		return -ENOMEM;
 +	}
 +
 +	flash->dma.enable = of_property_read_bool(dev->of_node, "flash-dma-mode");
@@ -16393,6 +11956,7 @@
 +		ast2700_espi_flash_isr(espi);
 +
 +	if (sts & ESPI_INT_STS_RST_DEASSERT) {
++		ast2700_espi_perif_sw_reset(espi);
 +		ast2700_espi_perif_reset(espi);
 +		ast2700_espi_vw_reset(espi);
 +		ast2700_espi_oob_reset(espi);
@@ -16581,11 +12145,11 @@
 +MODULE_DESCRIPTION("Control of AST2700 eSPI Device");
 +MODULE_LICENSE("GPL");
 diff --git a/drivers/soc/aspeed/ast2700-espi.h b/drivers/soc/aspeed/ast2700-espi.h
-new file mode 100644
-index 000000000..24ad5ec7c
+new file mode 100755
+index 000000000..7601f8a4f
 --- /dev/null
 +++ b/drivers/soc/aspeed/ast2700-espi.h
-@@ -0,0 +1,280 @@
+@@ -0,0 +1,281 @@
 +/* SPDX-License-Identifier: GPL-2.0+ */
 +/*
 + * Copyright 2023 Aspeed Technology Inc.
@@ -16616,6 +12180,7 @@
 +#define   ESPI_INT_EN_RST_ASSERT	BIT(30)
 +#define ESPI_DEV_ID			0x010
 +#define ESPI_CAP_GEN			0x014
++#define   ESPI_CAP_GEN_RTC_SUP		BIT(29)
 +#define ESPI_CAP_CH0			0x018
 +#define ESPI_CAP_CH1			0x01c
 +#define ESPI_CAP_CH2			0x020
@@ -16867,7 +12432,7 @@
 +
 +#endif
 diff --git a/drivers/soc/aspeed/ast2700-otp.c b/drivers/soc/aspeed/ast2700-otp.c
-new file mode 100644
+new file mode 100755
 index 000000000..af7b80040
 --- /dev/null
 +++ b/drivers/soc/aspeed/ast2700-otp.c
@@ -17439,6647 +13004,12 @@
 +MODULE_AUTHOR("Neal Liu <neal_liu@aspeedtech.com>");
 +MODULE_LICENSE("GPL");
 +MODULE_DESCRIPTION("ASPEED OTP Driver");
-diff --git a/drivers/soc/aspeed/rvas/Kconfig b/drivers/soc/aspeed/rvas/Kconfig
-new file mode 100644
-index 000000000..ef02e1b76
---- /dev/null
-+++ b/drivers/soc/aspeed/rvas/Kconfig
-@@ -0,0 +1,9 @@
-+menu "ASPEED RVAS drivers"
-+
-+config ASPEED_RVAS
-+	tristate "ASPEED RVAS driver"
-+	default n
-+	help
-+	  Driver for ASPEED RVAS Engine
-+
-+endmenu
-diff --git a/drivers/soc/aspeed/rvas/Makefile b/drivers/soc/aspeed/rvas/Makefile
-new file mode 100644
-index 000000000..1cccd7e37
---- /dev/null
-+++ b/drivers/soc/aspeed/rvas/Makefile
-@@ -0,0 +1,3 @@
-+obj-$(CONFIG_ASPEED_RVAS) += rvas.o
-+rvas-y := video_main.o hardware_engines.o video_engine.o
-+
-diff --git a/drivers/soc/aspeed/rvas/hardware_engines.c b/drivers/soc/aspeed/rvas/hardware_engines.c
-new file mode 100644
-index 000000000..25b644044
---- /dev/null
-+++ b/drivers/soc/aspeed/rvas/hardware_engines.c
-@@ -0,0 +1,2203 @@
-+// SPDX-License-Identifier: GPL-2.0+
-+/*
-+ * File Name     : hardware_engines.c
-+ * Description   : AST2600 frame grabber hardware engines
-+ *
-+ * Copyright (C) 2019-2021 ASPEED Technology Inc. All rights reserved.
-+ *
-+ * 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; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/mm.h>
-+#include <asm/cacheflush.h>
-+#include <linux/time.h>
-+
-+#include "hardware_engines.h"
-+#include "video.h"
-+#include "video_debug.h"
-+
-+static u32 dwBucketSizeRegOffset[BSE_MAX_BUCKET_SIZE_REGS] = { 0x20, 0x24, 0x28,
-+	0x2c, 0x30, 0x34, 0x38, 0x3c, 0x40, 0x44, 0x48, 0x4c, 0x50, 0x54, 0x58,
-+	0x5c };
-+static u32 arrBuckSizeRegIndex[16] = { 3, 5, 8, 6, 1, 7, 11, 10, 14, 13, 2, 4,
-+	9, 12, 0, 15 };
-+
-+static struct Resolution resTable1[0x3B - 0x30 + 1] = { { 800, 600 }, { 1024, 768 }, {
-+	1280, 1024 }, { 1600, 1200 }, { 1920, 1200 }, { 1280, 800 },
-+	{ 1440, 900 }, { 1680, 1050 }, { 1920, 1080 }, { 1366, 768 }, { 1600,
-+		900 }, { 1152, 864 }, };
-+
-+static struct Resolution resTable2[0x52 - 0x50 + 1] = { { 320, 240 }, { 400, 300 }, {
-+	512, 384 }, };
-+
-+static void prepare_bse_descriptor_2(struct Descriptor *pDAddress,
-+				     phys_addr_t source_addr,
-+				     phys_addr_t dest_addr,
-+				     bool bNotLastEntry,
-+				     u16 wStride,
-+				     u8 bytesPerPixel,
-+				     u32 dwFetchWidthPixels,
-+				     u32 dwFetchHeight,
-+				     bool bInterrupt,
-+				     u8 byBuckSizeRegIndex);
-+
-+static struct BSEAggregateRegister set_up_bse_bucket_2(struct AstRVAS *pAstRVAS,
-+						       u8 *abyBitIndexes,
-+							   u8 byTotalBucketCount,
-+							   u8 byBSBytesPerPixel,
-+						       u32 dwFetchWidthPixels,
-+							   u32 dwFetchHeight,
-+							   u32 dwBucketSizeIndex);
-+
-+static inline u32 ast_video_read(void __iomem *video_reg_base, u32 reg)
-+{
-+	u32 val = readl(video_reg_base + reg);
-+
-+	return val;
-+}
-+
-+// Get color depth
-+static void ast_video_get_color_mode(u8 byNewColorMode, struct VideoGeometry *pvg)
-+{
-+	switch (byNewColorMode) {
-+	case MODE_EGA:
-+		pvg->gmt = VGAGraphicsMode; //4pp mode12/mode6A
-+		pvg->byBitsPerPixel = 4;
-+		break;
-+
-+	case MODE_VGA:
-+		pvg->gmt = VGAGraphicsMode; //mode 13
-+		pvg->byBitsPerPixel = 8;
-+		break;
-+
-+	case MODE_BPP16:
-+		pvg->gmt = AGAGraphicsMode;
-+		pvg->byBitsPerPixel = 16;
-+		break;
-+
-+	case MODE_BPP32:
-+		pvg->gmt = AGAGraphicsMode;
-+		pvg->byBitsPerPixel = 32;
-+		break;
-+
-+	case MODE_TEXT:
-+		pvg->gmt = TextMode;
-+		pvg->byBitsPerPixel = 0;
-+		break;
-+
-+	case MODE_CGA:
-+		break;
-+
-+	default:
-+		pvg->byBitsPerPixel = 8;
-+		break;
-+	}
-+}
-+
-+//Mode ID mapping - use ID as index to the resolution table
-+static void ast_video_get_indexed_mode(struct ModeInfo *pModeInfo, struct VideoGeometry *pvg)
-+{
-+	u8 byModeIndex = (pModeInfo->byModeID & 0xf0);
-+
-+	HW_ENG_DBG("Mode ID %#x\n", pModeInfo->byModeID);
-+		  pvg->byModeID = pModeInfo->byModeID;
-+
-+	if (pModeInfo->byModeID == 0x12) {
-+		pvg->wScreenWidth = 640;
-+		pvg->wScreenHeight = 480;
-+	} else if (byModeIndex == 0x20) {
-+		pvg->wScreenWidth = 640;
-+		pvg->wScreenHeight = 480;
-+	} else if (byModeIndex == 0x30) {
-+		pvg->wScreenWidth =
-+			resTable1[pModeInfo->byModeID & 0x0f].wWidth;
-+		pvg->wScreenHeight =
-+			resTable1[pModeInfo->byModeID & 0x0f].wHeight;
-+	} else if (byModeIndex == 0x50) {
-+		pvg->wScreenWidth =
-+			resTable2[pModeInfo->byModeID & 0x03].wWidth;
-+		pvg->wScreenHeight =
-+			resTable2[pModeInfo->byModeID & 0x03].wHeight;
-+	} else if (byModeIndex == 0x60) {
-+		pvg->wScreenWidth = 800;
-+		pvg->wScreenHeight = 600;
-+	} else {
-+		HW_ENG_DBG("Mode ID %#x\n", pModeInfo->byModeID);
-+			  pvg->wScreenWidth = 0;
-+			  pvg->wScreenHeight = 0;
-+	}
-+}
-+
-+//check special modes
-+static void ast_video_set_special_modes(struct ModeInfo *pModeInfo, struct AstRVAS *pAstRVAS)
-+{
-+	u8 byVGACR1 = readb(pAstRVAS->grce_reg_base + GRCE_CRTC_OFFSET + 0x1); //number of chars per line
-+	u8 byVGACR7 = readb(pAstRVAS->grce_reg_base + GRCE_CRTC_OFFSET + 0x7);
-+	u8 byVGACR12 = readb(pAstRVAS->grce_reg_base + GRCE_CRTC_OFFSET + 0x12);
-+	u8 byVGASR1 = readb(pAstRVAS->grce_reg_base + GRCE_SEQ_OFFSET + 0x1);
-+	struct VideoGeometry *pvg = &pAstRVAS->current_vg;
-+	u32 dwHorizontalDisplayEnd = 0;
-+	u32 dwVerticalDisplayEnd = 0;
-+
-+	dwHorizontalDisplayEnd = (byVGACR1 + 1) << 3;
-+	dwVerticalDisplayEnd = (((byVGACR7 & 0x40) << 3)
-+		| ((byVGACR7 & 0x2) << 7) | byVGACR12) + 1;
-+
-+	HW_ENG_DBG("byVGACR1=0x%x,byVGACR7=0x%x,byVGACR12=0x%x\n", byVGACR1,
-+		   byVGACR7, byVGACR12);
-+	HW_ENG_DBG("Mode ID %#x, dwHorizontalDisplayEnd 0x%x, dwVerticalDisplayEnd 0x%x\n",
-+		   pModeInfo->byModeID, dwHorizontalDisplayEnd,
-+		   dwVerticalDisplayEnd);
-+
-+	// set up special mode
-+	if (VGAGraphicsMode == pvg->gmt && pvg->byBitsPerPixel == 8) { // mode 13
-+		pvg->wScreenHeight = 200;
-+		pvg->wScreenWidth = 320;
-+		pvg->wStride = 320;
-+	} else if (TextMode == pvg->gmt) { // text mode
-+		pvg->wScreenHeight = dwVerticalDisplayEnd;
-+		pvg->wScreenWidth = dwHorizontalDisplayEnd;
-+
-+		if (!(byVGASR1 & 0x1))
-+			pvg->wScreenWidth += (byVGACR1 + 1);
-+
-+		pvg->wStride = pvg->wScreenWidth;
-+	} else if (pvg->byBitsPerPixel == 4) {
-+		pvg->wStride = pvg->wScreenWidth;
-+	}
-+}
-+
-+static u32 ast_video_get_pitch(struct AstRVAS *pAstRVAS)
-+{
-+	u32 dwPitch = 0;
-+	u8 byVGACR13 = 0;
-+	u8 byVGACR14 = 0;
-+	u8 byVGACR17 = 0;
-+	u16 wOffsetUpper = 0;
-+	u16 wOffset = 0;
-+	struct VideoGeometry *pvg = &pAstRVAS->current_vg;
-+
-+	//read actual register
-+	byVGACR13 = readb(pAstRVAS->grce_reg_base + GRCE_CRTC_OFFSET + 0x13);
-+	byVGACR14 = readb(pAstRVAS->grce_reg_base + GRCE_CRTC_OFFSET + 0x14);
-+	byVGACR17 = readb(pAstRVAS->grce_reg_base + GRCE_CRTC_OFFSET + 0x17);
-+	wOffsetUpper = readb(pAstRVAS->grce_reg_base + 0xb0);
-+
-+	wOffset = (wOffsetUpper << 8) | byVGACR13;
-+	HW_ENG_DBG("wOffsetUpper= %#x, byVGACR13= %#x, byVGACR14= %#x, byVGACR17= %#x, wOffset= %#x\n",
-+		   wOffsetUpper, byVGACR13, byVGACR14, byVGACR17, wOffset);
-+
-+	if (byVGACR14 & 0x40)
-+		dwPitch = wOffset << 3; //DW mode
-+	else if (byVGACR17 & 0x40)
-+		dwPitch = wOffset << 1; //byte mode
-+	else
-+		dwPitch = wOffset << 2; //word mode
-+
-+	if (pvg->gmt != TextMode) {
-+		u8 byBppPowerOfTwo = 0;
-+
-+		if (pvg->byBitsPerPixel == 32)
-+			byBppPowerOfTwo = 2;
-+		else if (pvg->byBitsPerPixel == 16)
-+			byBppPowerOfTwo = 1;
-+		else if (pvg->byBitsPerPixel == 8)
-+			byBppPowerOfTwo = 0;
-+		else
-+			byBppPowerOfTwo = 3;	// 4bpp
-+
-+		//convert it to logic width in pixel
-+		if (pvg->byBitsPerPixel > 4)
-+			dwPitch >>= byBppPowerOfTwo;
-+		else
-+			dwPitch <<= byBppPowerOfTwo;
-+	}
-+
-+	return dwPitch;
-+}
-+
-+void update_video_geometry(struct AstRVAS *ast_rvas)
-+{
-+	struct ModeInfo *pModeInfo;
-+	struct NewModeInfoHeader *pNMIH;
-+	struct DisplayEnd *pDE;
-+	u8 byNewColorMode = 0;
-+	u32 VGA_Scratch_Register_350 = 0; //VIDEO_NEW_MODE_INFO_HEADER
-+	u32 VGA_Scratch_Register_354 = 0; //VIDEO_HDE
-+	u32 VGA_Scratch_Register_34C = 0; //VIDEO_HDE
-+	struct VideoGeometry *cur_vg = &ast_rvas->current_vg;
-+
-+	VGA_Scratch_Register_350 = ast_video_read(ast_rvas->grce_reg_base,
-+						  AST_VIDEO_SCRATCH_350);
-+	VGA_Scratch_Register_34C = ast_video_read(ast_rvas->grce_reg_base,
-+						  AST_VIDEO_SCRATCH_34C);
-+	VGA_Scratch_Register_354 = ast_video_read(ast_rvas->grce_reg_base,
-+						  AST_VIDEO_SCRATCH_354);
-+
-+	pModeInfo = (struct ModeInfo *)(&VGA_Scratch_Register_34C);
-+	pNMIH = (struct NewModeInfoHeader *)(&VGA_Scratch_Register_350);
-+	pDE = (struct DisplayEnd *)(&VGA_Scratch_Register_354);
-+	HW_ENG_DBG("pModeInfo: byColorMode: %#x byModeID: %#x byRefreshRateIndex: %#x byScanLines: %#x\n",
-+		   pModeInfo->byColorMode, pModeInfo->byModeID,
-+		   pModeInfo->byRefreshRateIndex, pModeInfo->byScanLines);
-+	HW_ENG_DBG("pNMIH: byColorDepth: %#x byDisplayInfo: %#x byMhzPixelClock: %#x byReserved: %#x\n",
-+		   pNMIH->byColorDepth, pNMIH->byDisplayInfo,
-+		   pNMIH->byMhzPixelClock, pNMIH->byReserved);
-+	HW_ENG_DBG("pDE: HDE: %#x VDE: %#x\n", pDE->HDE, pDE->VDE);
-+
-+	byNewColorMode = ((pModeInfo->byColorMode) & 0xf0) >> 4;
-+	HW_ENG_DBG("byNewColorMode= %#x,byModeID=0x%x\n", byNewColorMode,
-+		   pModeInfo->byModeID);
-+	ast_video_get_color_mode(byNewColorMode, cur_vg);
-+
-+	if (pNMIH->byDisplayInfo == MODE_GET_INFO_DE) {
-+		cur_vg->wScreenWidth = pDE->HDE;
-+		cur_vg->wScreenHeight = pDE->VDE;
-+		cur_vg->byBitsPerPixel = pNMIH->byColorDepth;
-+		cur_vg->byModeID = pModeInfo->byModeID;
-+	} else {
-+		ast_video_get_indexed_mode(pModeInfo, cur_vg);
-+	}
-+
-+	cur_vg->wStride = (u16)ast_video_get_pitch(ast_rvas);
-+	HW_ENG_DBG("Calculated pitch in pixels= %u\n", cur_vg->wStride);
-+
-+	if (cur_vg->wStride < cur_vg->wScreenWidth)
-+		cur_vg->wStride = cur_vg->wScreenWidth;
-+
-+	HW_ENG_DBG("Before current display width %u, height %u, pitch %u, color depth %u, mode %d\n",
-+		   cur_vg->wScreenWidth, cur_vg->wScreenHeight,
-+		   cur_vg->wStride, cur_vg->byBitsPerPixel, cur_vg->gmt);
-+
-+	if (cur_vg->gmt == TextMode ||
-+	    (cur_vg->gmt == VGAGraphicsMode && pModeInfo->byModeID == 0x13)) {
-+		ast_video_set_special_modes(pModeInfo, ast_rvas);
-+	}
-+
-+	//mode transition
-+	if (cur_vg->wScreenHeight < 200 || cur_vg->wScreenWidth < 320)
-+		cur_vg->gmt = InvalidMode;
-+
-+	if (cur_vg->gmt == TextMode) {
-+		u8 byVGACR9 = readb(ast_rvas->grce_reg_base + GRCE_CRTC_OFFSET + 0x9);
-+		u32 dwCharacterHeight = ((byVGACR9) & 0x1f) + 1;
-+
-+		HW_ENG_DBG("byModeID=0x%x,dwCharacterHeight=%d\n",
-+			   cur_vg->byModeID, dwCharacterHeight);
-+
-+		if (dwCharacterHeight != 8 && dwCharacterHeight != 14 &&
-+		    dwCharacterHeight != 16)
-+			cur_vg->gmt = InvalidMode;
-+
-+		if (cur_vg->wScreenWidth > 720 || cur_vg->wScreenHeight > 400)
-+			cur_vg->gmt = InvalidMode;
-+	}
-+
-+	HW_ENG_DBG("current display width %u, height %u, pitch %u, color depth %u, mode %d\n",
-+		   cur_vg->wScreenWidth, cur_vg->wScreenHeight,
-+		   cur_vg->wStride, cur_vg->byBitsPerPixel, cur_vg->gmt);
-+}
-+
-+//check and update current video geometry
-+bool video_geometry_change(struct AstRVAS *ast_rvas, u32 dwGRCEStatus)
-+{
-+	bool b_geometry_changed = false;
-+	struct VideoGeometry *cur_vg = &ast_rvas->current_vg;
-+	struct VideoGeometry pre_vg;
-+
-+	memcpy(&pre_vg, cur_vg, sizeof(pre_vg));
-+	update_video_geometry(ast_rvas);
-+	b_geometry_changed = memcmp(&pre_vg, cur_vg, sizeof(struct VideoGeometry))
-+			!= 0;
-+	HW_ENG_DBG("b_geometry_changed: %d\n", b_geometry_changed);
-+	return b_geometry_changed;
-+}
-+
-+void ioctl_get_video_geometry(struct RvasIoctl *ri, struct AstRVAS *ast_rvas)
-+{
-+	memcpy(&ri->vg, &ast_rvas->current_vg, sizeof(struct VideoGeometry));
-+//	HW_ENG_DBG("b_geometry_changed: %d\n", b_geometry_changed);
-+}
-+
-+void print_frame_buffer(u32 dwSizeByBytes, struct VGAMemInfo FBInfo)
-+{
-+	u32 iter = 0;
-+	phys_addr_t *frame_buffer_base = NULL;
-+	u32 dwNumMappedPages = 0;
-+
-+	dwNumMappedPages = ((dwSizeByBytes + 4095) >> 12);
-+	frame_buffer_base = (phys_addr_t *)ioremap(FBInfo.qwFBPhysStart, dwNumMappedPages << 12);
-+
-+	if (frame_buffer_base) {
-+		HW_ENG_DBG("==============%s===========\n", __func__);
-+
-+		for (iter = 0; iter < (dwSizeByBytes >> 2); iter++) {
-+			HW_ENG_DBG("0x%x, ", frame_buffer_base[iter]);
-+
-+			if ((iter % 16) == 0)
-+				HW_ENG_DBG("\n");
-+		}
-+
-+		HW_ENG_DBG("===========END=============\n");
-+		iounmap((void *)frame_buffer_base);
-+	}
-+}
-+
-+void ioctl_get_grc_register(struct RvasIoctl *ri, struct AstRVAS *pAstRVAS)
-+{
-+	void *virt_add = 0;
-+	u32 size = 0;
-+
-+	HW_ENG_DBG("Start\n");
-+	virt_add = get_virt_add_rsvd_mem((u32)ri->rmh, pAstRVAS);
-+	size = ri->rmh1_mem_size;
-+
-+	if (virt_is_valid_rsvd_mem((u32)ri->rmh, size, pAstRVAS)) {
-+		memcpy((void *)virt_add,
-+		       (const void *)(pAstRVAS->grce_reg_base), 0x40);
-+		memset((void *)(((u8 *)virt_add) + 0x40), 0x0, 0x20);
-+		memcpy((void *)(((u8 *)virt_add) + 0x60),
-+		       (const void *)(pAstRVAS->grce_reg_base + 0x60),
-+		       GRCE_SIZE - 0x60);
-+		ri->rs = SuccessStatus;
-+	} else {
-+		ri->rs = InvalidMemoryHandle;
-+	}
-+}
-+
-+void ioctl_read_snoop_map(struct RvasIoctl *ri, struct AstRVAS *pAstRVAS)
-+{
-+	struct ContextTable *pct = get_context_entry(ri->rc, pAstRVAS);
-+	void *virt_add = 0;
-+	u32 size = 0;
-+
-+	virt_add = get_virt_add_rsvd_mem((u32)ri->rmh, pAstRVAS);
-+	size = ri->rmh_mem_size;
-+
-+	disable_grce_tse_interrupt(pAstRVAS);
-+	HW_ENG_DBG("Start\n");
-+
-+	if (pct) {
-+		if (virt_is_valid_rsvd_mem((u32)ri->rmh, size, pAstRVAS)) {
-+			update_all_snoop_context(pAstRVAS);
-+			memcpy((void *)virt_add, pct->aqwSnoopMap,
-+			       sizeof(pct->aqwSnoopMap));
-+
-+			if (ri->flag) {
-+				///get the context snoop address
-+				memset(pct->aqwSnoopMap, 0x00,
-+				       sizeof(pct->aqwSnoopMap));
-+				memset(&pct->sa, 0x00, sizeof(pct->sa));
-+			}
-+			ri->rs = SuccessStatus;
-+		} else {
-+			ri->rs = InvalidMemoryHandle;
-+		}
-+	} else {
-+		ri->rs = InvalidContextHandle;
-+	}
-+
-+	enable_grce_tse_interrupt(pAstRVAS);
-+}
-+
-+void ioctl_read_snoop_aggregate(struct RvasIoctl *ri, struct AstRVAS *pAstRVAS)
-+{
-+	struct ContextTable *pct = get_context_entry(ri->rc, pAstRVAS);
-+
-+	disable_grce_tse_interrupt(pAstRVAS);
-+
-+	if (pct) {
-+		update_all_snoop_context(pAstRVAS);
-+		memcpy(&ri->sa, &pct->sa, sizeof(pct->sa));
-+		HW_ENG_DBG("ri->sa.qwCol: %#llx qwRow: %#llx flag: %u\n",
-+			   ri->sa.qwCol, ri->sa.qwRow, ri->flag);
-+
-+		if (ri->flag)
-+			memset(&pct->sa, 0x00, sizeof(pct->sa));
-+
-+		ri->rs = SuccessStatus;
-+	} else {
-+		ri->rs = InvalidContextHandle;
-+		HW_ENG_DBG("Invalid Context\n");
-+	}
-+
-+	enable_grce_tse_interrupt(pAstRVAS);
-+}
-+
-+void ioctl_set_tse_tsicr(struct RvasIoctl *ri, struct AstRVAS *pAstRVAS)
-+{
-+	void __iomem *addrTSICR;
-+
-+	pAstRVAS->tse_tsicr = ri->tse_counter;
-+	addrTSICR = pAstRVAS->fg_reg_base + TSE_TileSnoop_Interrupt_Count;
-+	writel(pAstRVAS->tse_tsicr, addrTSICR);// max wait time before interrupt
-+	ri->rs = SuccessStatus;
-+}
-+
-+void ioctl_get_tse_tsicr(struct RvasIoctl *ri, struct AstRVAS *pAstRVAS)
-+{
-+	ri->tse_counter = pAstRVAS->tse_tsicr;
-+	ri->rs = SuccessStatus;
-+}
-+
-+// Get the screen offset from the GRC registers
-+u32 get_screen_offset(struct AstRVAS *pAstRVAS)
-+{
-+	u32 dwScreenOffset = 0;
-+	void __iomem *addrVGACRC = pAstRVAS->grce_reg_base + GRCE_CRTC + 0xC; // Ch
-+	void __iomem *addrVGACRD = pAstRVAS->grce_reg_base + GRCE_CRTC + 0xD; // Dh
-+	void __iomem *addrVGACRAF = pAstRVAS->grce_reg_base + GRCE_CRTCEXT + 0x2F;
-+
-+	if (pAstRVAS->current_vg.gmt == AGAGraphicsMode) {
-+		dwScreenOffset = ((readb(addrVGACRAF) << 16) | ((readb(addrVGACRC)) << 8) |
-+				(readb(addrVGACRD)));
-+		dwScreenOffset *= pAstRVAS->current_vg.byBitsPerPixel >> 3;
-+	}
-+
-+	HW_ENG_DBG("ScreenOffset: %#8.8x\n", dwScreenOffset);
-+
-+	return dwScreenOffset;
-+}
-+
-+void reset_snoop_engine(struct AstRVAS *pAstRVAS)
-+{
-+	void __iomem *addr_snoop = pAstRVAS->fg_reg_base + TSE_SnoopMap_Offset;
-+	u32 reg_value = 0;
-+	u32 iter;
-+
-+	writel(0x0, pAstRVAS->fg_reg_base + TSE_SnoopCommand_Register_Offset);
-+	writel(0x3, pAstRVAS->fg_reg_base + TSE_Status_Register_Offset);
-+	reg_value = readl(pAstRVAS->fg_reg_base + TSE_Status_Register_Offset);
-+	reg_value = readl(pAstRVAS->fg_reg_base + TSE_CS0Reg);
-+	reg_value = readl(pAstRVAS->fg_reg_base + TSE_CS1Reg);
-+	reg_value = readl(pAstRVAS->fg_reg_base + TSE_RS0Reg);
-+	reg_value = readl(pAstRVAS->fg_reg_base + TSE_RS1Reg);
-+
-+	//Clear TSRR00 to TSRR126 (TSRR01 to TSRR127), Snoop Map
-+	for (iter = 0; iter < 0x80; ++iter) {
-+		reg_value = readl(addr_snoop) + 1;
-+		writel(reg_value, addr_snoop);
-+	}
-+
-+	reg_value = readl(pAstRVAS->fg_reg_base + TSE_TileCount_Register_Offset);
-+}
-+
-+void set_snoop_engine(bool b_geom_chg, struct AstRVAS *pAstRVAS)
-+{
-+	void __iomem *tscmd_reg = pAstRVAS->fg_reg_base + TSE_SnoopCommand_Register_Offset;
-+	void __iomem *tsfbsa_reg = pAstRVAS->fg_reg_base + TSE_FrameBuffer_Offset;
-+	void __iomem *tsulr_reg = pAstRVAS->fg_reg_base + TSE_UpperLimit_Offset;
-+	u32 new_tsfbsa = 0;
-+	u32 tscmd = 0;
-+	u8 byBytesPerPixel = 0x0;
-+	u8 byTSCMDBytesPerPixel = 0x0;
-+	int cContext;
-+	u32 dwStride;
-+	struct ContextTable **ppctContextTable = pAstRVAS->ppctContextTable;
-+
-+	// Calculate Start Address into the Frame Buffer
-+	new_tsfbsa = get_screen_offset(pAstRVAS);
-+	tscmd = readl(tscmd_reg);
-+
-+	tscmd &= (1 << TSCMD_INT_ENBL_BIT);
-+
-+	HW_ENG_DBG("Latest TSFBSA: %#8.8x\n", new_tsfbsa);
-+	HW_ENG_DBG("pAstRVAS->current_vg: bpp %u Mode:%#x gmt:%d Width:%u Height:%u Stride:%u\n",
-+		   pAstRVAS->current_vg.byBitsPerPixel,
-+		   pAstRVAS->current_vg.byModeID, pAstRVAS->current_vg.gmt,
-+		   pAstRVAS->current_vg.wScreenWidth,
-+		   pAstRVAS->current_vg.wScreenHeight,
-+		   pAstRVAS->current_vg.wStride);
-+
-+	if (b_geom_chg || (readl(tsfbsa_reg) != new_tsfbsa)) {
-+		byBytesPerPixel = pAstRVAS->current_vg.byBitsPerPixel >> 3;
-+
-+		if (pAstRVAS->current_vg.gmt == VGAGraphicsMode ||
-+		    pAstRVAS->current_vg.byBitsPerPixel == 4) {
-+			byTSCMDBytesPerPixel = 0;
-+		} else {
-+			switch (byBytesPerPixel) {
-+			case 1:
-+				byTSCMDBytesPerPixel = 0;
-+				break;
-+
-+			case 2:
-+				byTSCMDBytesPerPixel = 1;
-+				break;
-+
-+			case 3:
-+			case 4:
-+				byTSCMDBytesPerPixel = 2;
-+				break;
-+			}
-+		}
-+		dwStride = pAstRVAS->current_vg.wStride;
-+
-+		if (byBytesPerPixel == 3)
-+			dwStride = (dwStride + dwStride + dwStride) >> 2;
-+		else if (pAstRVAS->current_vg.byBitsPerPixel == 4)
-+			dwStride >>= 1;
-+
-+		// set TSE SCR
-+		// start the tile snoop engine
-+		// flip the 15 bit
-+		if (!(readl(tscmd_reg) & TSCMD_SCREEN_OWNER))
-+			tscmd |= TSCMD_SCREEN_OWNER;
-+
-+		tscmd |= (dwStride << TSCMD_PITCH_BIT) | (1 << TSCMD_CPT_BIT)
-+			| (1 << TSCMD_RPT_BIT)
-+			| (byTSCMDBytesPerPixel << TSCMD_BPP_BIT)
-+			| (1 << TSCMD_VGA_MODE_BIT) | (1 << TSCMD_TSE_ENBL_BIT);
-+		HW_ENG_DBG("tscmd: %#8.8x\n", tscmd);
-+		// set the TSFBSA & TSULR
-+		writel(new_tsfbsa, tsfbsa_reg);
-+		writel(BSE_UPPER_LIMIT, tsulr_reg);
-+		writel(tscmd, tscmd_reg);
-+		//reset snoop information
-+		get_snoop_map_data(pAstRVAS);
-+		memset((void *)pAstRVAS->accrued_sm, 0,
-+		       sizeof(pAstRVAS->accrued_sm));
-+		memset((void *)&pAstRVAS->accrued_sa, 0,
-+		       sizeof(pAstRVAS->accrued_sa));
-+
-+		for (cContext = 0; cContext < MAX_NUM_CONTEXT; cContext++) {
-+			if (ppctContextTable[cContext]) {
-+				memset(ppctContextTable[cContext]->aqwSnoopMap,
-+				       0,
-+				       sizeof(ppctContextTable[cContext]->aqwSnoopMap));
-+				memset(&ppctContextTable[cContext]->sa, 0,
-+				       sizeof(ppctContextTable[cContext]->sa));
-+			}
-+		}      // for each context
-+	} // if
-+}
-+
-+//
-+// ReadSnoopMap to Clear
-+//
-+void get_snoop_map_data(struct AstRVAS *pAstRVAS)
-+{
-+	u32 dwSMDword;
-+	u64 aqwSnoopMap[SNOOP_MAP_QWORD_COUNT];
-+	//u32 dw_iter;
-+
-+	get_snoop_aggregate(pAstRVAS);
-+	memcpy((void *)aqwSnoopMap,
-+	       (const void *)(pAstRVAS->fg_reg_base + TSE_SnoopMap_Offset),
-+	       sizeof(aqwSnoopMap));
-+
-+	//HW_ENG_DBG("Snoop Map:\n");
-+	//HW_ENG_DBG("==========\n");
-+
-+	//for (dw_iter = 0; dw_iter < SNOOP_MAP_QWORD_COUNT; ++dw_iter)
-+		//HW_ENG_DBG("[%2u]: 0x%16.16llx\n", dw_iter, aqwSnoopMap[dw_iter]);
-+
-+	//HW_ENG_DBG("==========\n\n");
-+
-+	// copy 512 snoop map
-+	for (dwSMDword = 0; dwSMDword < SNOOP_MAP_QWORD_COUNT; ++dwSMDword)
-+		pAstRVAS->accrued_sm[dwSMDword] |= aqwSnoopMap[dwSMDword];
-+}
-+
-+void get_snoop_aggregate(struct AstRVAS *pAstRVAS)
-+{
-+	u64 qwRow = 0;
-+	u64 qwCol = 0;
-+
-+	// copy the snoop aggregate,row 64 bits
-+	qwRow = readl(pAstRVAS->fg_reg_base + TSE_RS1Reg);
-+	qwRow = qwRow << 32;
-+	qwRow |= readl(pAstRVAS->fg_reg_base + TSE_RS0Reg);
-+
-+	// column
-+	qwCol = readl(pAstRVAS->fg_reg_base + TSE_CS1Reg);
-+	qwCol = qwCol << 32;
-+	qwCol |= readl(pAstRVAS->fg_reg_base + TSE_CS0Reg);
-+
-+	HW_ENG_DBG("Snoop Aggregate Row: 0x%16.16llx\n", qwRow);
-+	HW_ENG_DBG("Snoop Aggregate Col: 0x%16.16llx\n", qwCol);
-+	HW_ENG_DBG("DRIVER:: %s\n", __func__);
-+	HW_ENG_DBG("DRIVER:: row [%#llx]\n", qwRow);
-+	HW_ENG_DBG("DRIVER:: col [%#llx]\n", qwCol);
-+
-+	pAstRVAS->accrued_sa.qwCol |= qwCol;
-+	pAstRVAS->accrued_sa.qwRow |= qwRow;
-+}
-+
-+u64 reinterpret_32bpp_snoop_row_as_24bpp(u64 theSnoopRow)
-+{
-+	u64 qwResult = 0;
-+	u64 qwSourceBit = 1;
-+	u32 cSourceBit;
-+	u64 qwBitResult = 0;
-+
-+	for (cSourceBit = 0; cSourceBit < 64; ++cSourceBit) {
-+		if (theSnoopRow & qwSourceBit) {
-+			qwBitResult = ((cSourceBit * 128) / 96);
-+			qwResult |= (((u64)3) << qwBitResult);
-+		}
-+
-+		qwSourceBit <<= 1;
-+	}
-+
-+	return qwResult;
-+}
-+
-+//
-+//one tile: 32x32,
-+//
-+void convert_snoop_map(struct AstRVAS *pAstRVAS)
-+{
-+	u32 dwAllRows = (pAstRVAS->current_vg.wScreenHeight + 31) >> 5;
-+	u32 cRow;
-+
-+	for (cRow = 0; cRow < dwAllRows; ++cRow)
-+		pAstRVAS->accrued_sm[cRow] =
-+		reinterpret_32bpp_snoop_row_as_24bpp(pAstRVAS->accrued_sm[cRow]);
-+
-+	pAstRVAS->accrued_sa.qwCol =
-+	reinterpret_32bpp_snoop_row_as_24bpp(pAstRVAS->accrued_sa.qwCol);
-+}
-+
-+void update_all_snoop_context(struct AstRVAS *pAstRVAS)
-+{
-+	u32 cContext;
-+	u32 iSMDword;
-+	struct ContextTable **ppctContextTable = pAstRVAS->ppctContextTable;
-+
-+	if (pAstRVAS->current_vg.byBitsPerPixel == 24)
-+		convert_snoop_map(pAstRVAS);
-+
-+	for (cContext = 0; cContext < MAX_NUM_CONTEXT; cContext++)
-+		if (ppctContextTable[cContext]) {
-+			for (iSMDword = 0; iSMDword < SNOOP_MAP_QWORD_COUNT;
-+				iSMDword++)
-+				ppctContextTable[cContext]->aqwSnoopMap[iSMDword] |=
-+					pAstRVAS->accrued_sm[iSMDword];
-+
-+			ppctContextTable[cContext]->sa.qwRow |=
-+				pAstRVAS->accrued_sa.qwRow;
-+			ppctContextTable[cContext]->sa.qwCol |=
-+				pAstRVAS->accrued_sa.qwCol;
-+		}
-+
-+	//reset snoop map and aggregate
-+	memset((void *)pAstRVAS->accrued_sm, 0, sizeof(pAstRVAS->accrued_sm));
-+	memset((void *)&pAstRVAS->accrued_sa, 0x00,
-+	       sizeof(pAstRVAS->accrued_sa));
-+}
-+
-+static u32 setup_tfe_cr(struct FetchOperation *pfo)
-+{
-+	u32 dwTFECR = 0;
-+
-+	if (pfo->bEnableRLE)
-+		dwTFECR = (pfo->byRLETripletCode << 24)
-+			| (pfo->byRLERepeatCode << 16);
-+
-+	dwTFECR &= TFCTL_DESCRIPTOR_IN_DDR_MASK;
-+	dwTFECR |= 1;
-+	dwTFECR |= 1 << 1; // enabled IRQ
-+	HW_ENG_DBG("dwTFECR: %#x\n", dwTFECR);
-+	return dwTFECR;
-+}
-+
-+static void start_skip_mode_skip(struct Descriptor *desc_virt,
-+				 phys_addr_t desc_phys,
-+				 phys_addr_t source_phys, phys_addr_t dest_addr, u16 wStride,
-+				 u8 bytesPerPixel, u32 dwFetchWidthPixels,
-+				 u32 dwFetchHeight, bool bRLEOverFLow)
-+{
-+	struct Descriptor *pVirtDesc = desc_virt;
-+
-+	// Fetch Skipping data to a temp buffer
-+	prepare_tfe_descriptor(pVirtDesc, source_phys, dest_addr, true, 1,
-+			       false, wStride, bytesPerPixel,
-+			       dwFetchWidthPixels, dwFetchHeight,
-+			       LowByteMode, bRLEOverFLow, 0);
-+
-+	dest_addr += dwFetchWidthPixels * dwFetchHeight;
-+	pVirtDesc++;
-+
-+	if (bytesPerPixel == 3 || bytesPerPixel == 4) {
-+		prepare_tfe_descriptor(pVirtDesc, source_phys, dest_addr,
-+				       true, 1, false, wStride, bytesPerPixel,
-+				       dwFetchWidthPixels, dwFetchHeight,
-+				       MiddleByteMode, bRLEOverFLow, 0);
-+
-+		dest_addr += dwFetchWidthPixels * dwFetchHeight;
-+		pVirtDesc++;
-+	}
-+
-+	prepare_tfe_descriptor(pVirtDesc, source_phys, dest_addr, false, 1,
-+			       false, wStride, bytesPerPixel,
-+			       dwFetchWidthPixels, dwFetchHeight,
-+			       TopByteMode, bRLEOverFLow, 1);
-+}
-+
-+// calculate pure fetch size
-+static u32 calculate_fetch_size(enum SelectedByteMode sbm, u8 bytesPerPixel,
-+				u32 dwFetchWidthPixels, u32 dwFetchHeight)
-+{
-+	u32 dwFetchSize = 0;
-+
-+	switch (sbm) {
-+	case AllBytesMode:
-+		dwFetchSize = dwFetchWidthPixels * dwFetchHeight
-+			* bytesPerPixel;
-+		break;
-+
-+	case SkipMode:
-+		if (bytesPerPixel == 3 || bytesPerPixel == 4)
-+			dwFetchSize = dwFetchWidthPixels * dwFetchHeight * 3;
-+		else
-+			dwFetchSize = dwFetchWidthPixels * dwFetchHeight
-+				* bytesPerPixel;
-+		break;
-+
-+	case PlanarToPackedMode:
-+		dwFetchSize = (dwFetchWidthPixels * dwFetchHeight);
-+		break;
-+
-+	case PackedToPackedMode:
-+		break;
-+
-+	default:
-+		HW_ENG_DBG("Mode= %d is not supported\n", sbm);
-+		break;
-+	} //switch
-+	return dwFetchSize;
-+}
-+
-+static void display_fetch_info(struct FetchVideoTilesArg *pFVTDescriptor, u32 dwCD)
-+{
-+	struct FetchRegion *pfr = NULL;
-+
-+	pfr = &pFVTDescriptor->pfo[dwCD].fr;
-+	HW_ENG_DBG("FETCH - 1 dwCD: %u\n", dwCD);
-+	HW_ENG_DBG("pfr->wLeftX :%d\n", pfr->wLeftX);
-+	HW_ENG_DBG("pfr->wTopY :%d\n", pfr->wTopY);
-+	HW_ENG_DBG("pfr->wRightX :%d\n", pfr->wRightX);
-+	HW_ENG_DBG("pfr->wBottomY :%d\n", pfr->wBottomY);
-+	HW_ENG_DBG(" bEanbleRLE %d\n", pFVTDescriptor->pfo[dwCD].bEnableRLE);
-+	HW_ENG_DBG("Stride : %d\n", pFVTDescriptor->vg.wStride);
-+}
-+
-+void ioctl_fetch_video_tiles(struct RvasIoctl *ri, struct AstRVAS *pAstRVAS)
-+{
-+	struct FetchVideoTilesArg *pFVTDescriptor;
-+	u32 dwCD = 0;
-+	struct Descriptor *pdesc_virt;
-+	phys_addr_t qw_desc_phys;
-+	phys_addr_t qw_source_phys;
-+	phys_addr_t qw_destination_phys;
-+	u8 bytesPerPixel;
-+	struct FetchRegion *pfr;
-+	bool bNotLastEntry = false;
-+	u32 dwTFECR = 0;
-+	u32 dwTotalFetchSize = 0;
-+	u32 dwRLESize = 0;
-+	bool bRLEOverFLow = false;
-+	u32 dwFetchWidthPixels = 0;
-+	u32 dwFetchHeight = 0;
-+	phys_addr_t arg_phys = 0;
-+	phys_addr_t data_phys_out = 0;
-+	phys_addr_t data_phys_temp = 0;
-+	u16 stride = 0;
-+	bool bSkippingMode = false;
-+	void *desc_virt = NULL;
-+	phys_addr_t desc_phy = 0;
-+	struct ContextTable *ctx_entry = NULL;
-+
-+	HW_ENG_DBG("DRIVER:::: TILE FETCH CHAINING\n");
-+	ctx_entry = get_context_entry(ri->rc, pAstRVAS);
-+
-+	if (ctx_entry) {
-+		desc_virt = ctx_entry->desc_virt;
-+		desc_phy = ctx_entry->desc_phy;
-+	} else {
-+		HW_ENG_DBG("Returning with invalid Context handle: 0x%p\n", ri->rc);
-+		ri->rs = InvalidContextHandle;
-+		return;
-+	}
-+
-+	ri->rs = SuccessStatus;
-+	//struct FetchVideoTilesArg buffer
-+	arg_phys = get_phys_add_rsvd_mem((u32)ri->rmh, pAstRVAS);
-+	//Fetch final dest buffer
-+	data_phys_out = get_phys_add_rsvd_mem((u32)ri->rmh1, pAstRVAS);
-+	//Intermediate Buffer
-+	data_phys_temp = get_phys_add_rsvd_mem((u32)ri->rmh2, pAstRVAS);
-+
-+	qw_destination_phys = data_phys_out;
-+	pFVTDescriptor = (struct FetchVideoTilesArg *)get_virt_add_rsvd_mem((u32)ri->rmh, pAstRVAS);
-+	HW_ENG_DBG("Destination virtual Add: 0x%llx\n", get_virt_add_rsvd_mem((u32)ri->rmh, pAstRVAS));
-+	HW_ENG_DBG("Destination Physical Add: %llx\n", qw_destination_phys);
-+	memset(desc_virt, 0x00, PAGE_SIZE);
-+
-+	if (arg_phys && data_phys_out && data_phys_temp) {
-+		pdesc_virt = (struct Descriptor *)desc_virt;
-+		qw_desc_phys = desc_phy;
-+		HW_ENG_DBG("Descriptor Virtual Addr: %llx\n",
-+			   (phys_addr_t)desc_virt);
-+		HW_ENG_DBG("Descriptor Physical Addr: %llx\n", qw_desc_phys);
-+		stride = pFVTDescriptor->vg.wStride;
-+
-+		if (pFVTDescriptor->vg.byBitsPerPixel == 4) {
-+			bytesPerPixel = 1;
-+			stride >>= 1;
-+		} else {
-+			bytesPerPixel = pFVTDescriptor->vg.byBitsPerPixel >> 3;
-+		}
-+
-+		HW_ENG_DBG("u8 per pixel:%u\n", bytesPerPixel);
-+		// fetch all data to Destination 1 without RLE
-+		HW_ENG_DBG("FETCH - 0\n");
-+		HW_ENG_DBG("COUNT OF Operation: %u\n", pFVTDescriptor->cfo);
-+
-+		for (dwCD = 0; dwCD < pFVTDescriptor->cfo; dwCD++) {
-+			display_fetch_info(pFVTDescriptor, dwCD);
-+			// Set up Control Register.
-+			dwTFECR = setup_tfe_cr(&pFVTDescriptor->pfo[dwCD]);
-+			pfr = &pFVTDescriptor->pfo[dwCD].fr;
-+			// find Source Address
-+			if (pFVTDescriptor->vg.byBitsPerPixel == 4) {
-+				qw_source_phys = get_phy_fb_start_address(pAstRVAS)
-+								+ ((pfr->wLeftX * bytesPerPixel) >> 1)
-+								+ pfr->wTopY * stride
-+								* bytesPerPixel;
-+
-+				dwFetchWidthPixels = (pfr->wRightX - pfr->wLeftX + 1) >> 1;
-+			} else {
-+				qw_source_phys = get_phy_fb_start_address(pAstRVAS)
-+						+ pfr->wLeftX * bytesPerPixel
-+						+ pfr->wTopY * stride
-+						* bytesPerPixel;
-+
-+				dwFetchWidthPixels = (pfr->wRightX - pfr->wLeftX + 1);
-+			}
-+			HW_ENG_DBG("dwCD: %u qw_source_phys: %#x\n", dwCD,
-+				   qw_source_phys);
-+			dwFetchHeight = pfr->wBottomY - pfr->wTopY + 1;
-+
-+			HW_ENG_DBG("DESCRIPTOR virtual ADDRESS: 0x%p\n",
-+				   pdesc_virt);
-+			if (pFVTDescriptor->vg.byBitsPerPixel == 4)
-+				pFVTDescriptor->pfo[dwCD].sbm =
-+					PlanarToPackedMode;
-+
-+			pFVTDescriptor->pfo[dwCD].dwFetchSize =
-+				calculate_fetch_size(pFVTDescriptor->pfo[dwCD].sbm,
-+						     bytesPerPixel, dwFetchWidthPixels,
-+						     dwFetchHeight);
-+			bSkippingMode =
-+				(pFVTDescriptor->pfo[dwCD].sbm == SkipMode) ?
-+				true : false;
-+
-+			if (bSkippingMode && bytesPerPixel > 1) {
-+				u32 skipSrcAddr = qw_source_phys;
-+				u32 skipDestAddr = qw_destination_phys;
-+				u8 byPostBytesPerPixel =
-+					(bytesPerPixel == 2) ? 2 : 3;
-+				HW_ENG_DBG("In SkippingMode...\n");
-+
-+				if (pFVTDescriptor->pfo[dwCD].bEnableRLE) {
-+					//skip data to intermediate buffer
-+					skipDestAddr = data_phys_temp;
-+				}
-+
-+				start_skip_mode_skip(pdesc_virt,
-+						     qw_desc_phys, skipSrcAddr,
-+						     skipDestAddr,
-+						     pFVTDescriptor->vg.wStride,
-+						     bytesPerPixel, dwFetchWidthPixels,
-+						     dwFetchHeight, bRLEOverFLow);
-+
-+				if (pFVTDescriptor->pfo[dwCD].bEnableRLE) {
-+					u32 rleSrcAddr = skipDestAddr;
-+					u32 rleDesAddr = qw_destination_phys;
-+
-+					///// take second look at skip mode for using map single
-+					if (sleep_on_tfe_busy(pAstRVAS,
-+							      qw_desc_phys, // Descriptor physical Address
-+							      dwTFECR, // control register value
-+							      pFVTDescriptor->pfo[dwCD].dwFetchSize, // bandwidth limitor value
-+							      &dwRLESize,    // out:: rle size
-+							      &pFVTDescriptor->pfo[dwCD].dwCheckSum
-+							      ) == false) { // out:: cs size
-+						ri->rs = GenericError;
-+						return;
-+					}
-+
-+					// perform RLE from Temp buffer to qw_destination_phys
-+					//HW_ENG_DBG("skip rle\n");
-+					prepare_tfe_descriptor(pdesc_virt,
-+							       rleSrcAddr, rleDesAddr,
-+							       bNotLastEntry, 1,
-+							       pFVTDescriptor->pfo[dwCD].bEnableRLE,
-+							       dwFetchWidthPixels,
-+							       byPostBytesPerPixel,
-+							       dwFetchWidthPixels,
-+							       dwFetchHeight, AllBytesMode,
-+							       bRLEOverFLow, 1);
-+				}
-+			} else {
-+				HW_ENG_DBG("Preparing TFE Descriptor with no skipping...\n");
-+				prepare_tfe_descriptor(pdesc_virt,
-+						       qw_source_phys, qw_destination_phys,
-+						       bNotLastEntry, 1,
-+						       pFVTDescriptor->pfo[dwCD].bEnableRLE,
-+						       stride, bytesPerPixel,
-+						       dwFetchWidthPixels, dwFetchHeight,
-+						       pFVTDescriptor->pfo[dwCD].sbm,
-+						       bRLEOverFLow, 1);
-+				HW_ENG_DBG("Successfully prepared TFE Descriptor with no skipping\n");
-+			}
-+			HW_ENG_DBG("Sleeping while TFE is busy...\n");
-+
-+			if (sleep_on_tfe_busy(pAstRVAS, qw_desc_phys, // Descriptor physical Address
-+					      dwTFECR,               // control register value
-+					      pFVTDescriptor->pfo[dwCD].dwFetchSize, // bandwidth limitor value
-+					      &dwRLESize,                    // out:: rle size
-+					      &pFVTDescriptor->pfo[dwCD].dwCheckSum
-+					      ) == false) {  // out:: cs size
-+				ri->rs = GenericError;
-+				return;
-+			}
-+
-+			HW_ENG_DBG("After sleep where TFE was busy\n");
-+
-+			//HW_ENG_DBG("skip rle end\n");
-+			if (!pFVTDescriptor->pfo[dwCD].bEnableRLE) { // RLE not enabled
-+				HW_ENG_DBG("RLE is off\n");
-+				pFVTDescriptor->pfo[dwCD].bRLEFailed = false;
-+				dwRLESize =
-+					pFVTDescriptor->pfo[dwCD].dwFetchSize;
-+				dwTotalFetchSize +=
-+					pFVTDescriptor->pfo[dwCD].dwFetchSize;
-+			} else { // RLE enabled
-+				HW_ENG_DBG("RLE Enabled\n");
-+				if (dwRLESize
-+					>= pFVTDescriptor->pfo[dwCD].dwFetchSize) { // FAILED
-+					HW_ENG_DBG("DRVIER:: RLE failed RLE: %u > %u\n",
-+						   dwRLESize,
-+						   pFVTDescriptor->pfo[dwCD].dwFetchSize);
-+					pFVTDescriptor->pfo[dwCD].bRLEFailed =
-+						true;
-+
-+					if (bSkippingMode) {
-+						phys_addr_t skip_source_addr =
-+							qw_source_phys;
-+						phys_addr_t skip_dest_addr =
-+							qw_destination_phys;
-+
-+						start_skip_mode_skip(pdesc_virt,
-+								     qw_desc_phys,
-+								     skip_source_addr,
-+								     skip_dest_addr,
-+								     pFVTDescriptor->vg.wStride,
-+								     bytesPerPixel,
-+								     dwFetchWidthPixels,
-+								     dwFetchHeight,
-+								     bRLEOverFLow);
-+					} else {
-+						HW_ENG_DBG(" FETCH - 4\n");
-+						prepare_tfe_descriptor(pdesc_virt,
-+								       qw_source_phys,
-+								       qw_destination_phys,
-+								       bNotLastEntry, 1, false,
-+								       pFVTDescriptor->vg.wStride,
-+								       bytesPerPixel,
-+								       dwFetchWidthPixels,
-+								       dwFetchHeight,
-+								       pFVTDescriptor->pfo[dwCD].sbm,
-+								       bRLEOverFLow, 1);
-+					}
-+
-+					if (sleep_on_tfe_busy(pAstRVAS,
-+							      qw_desc_phys, // Descriptor physical Address
-+							      dwTFECR, // control register value
-+							      pFVTDescriptor->pfo[dwCD].dwFetchSize, // bandwidth limitor value
-+							      &dwRLESize,    // out:: rle size
-+							      &pFVTDescriptor->pfo[dwCD].dwCheckSum
-+							      ) == false) {  // out:: cs size
-+						ri->rs = GenericError;
-+						return;
-+					}
-+
-+					dwTotalFetchSize +=
-+						pFVTDescriptor->pfo[dwCD].dwFetchSize;
-+					dwRLESize =
-+						pFVTDescriptor->pfo[dwCD].dwFetchSize;
-+				}  else { //RLE successful
-+					pFVTDescriptor->pfo[dwCD].bRLEFailed =
-+						false;
-+					dwTotalFetchSize += dwRLESize;
-+					dwTotalFetchSize = (dwTotalFetchSize
-+						+ 0x3) & 0xfffffffc;
-+				}
-+			} //RLE Enabled
-+
-+			pFVTDescriptor->pfo[dwCD].dwFetchRLESize = dwRLESize;
-+			HW_ENG_DBG("DRIVER:: RLE: %u, nonRLE: %u\n", dwRLESize,
-+				   pFVTDescriptor->pfo[dwCD].dwFetchSize);
-+			HW_ENG_DBG("FETCH:: loop FETCH size: %u\n", dwTotalFetchSize);
-+				   qw_destination_phys = data_phys_out + dwTotalFetchSize;
-+		} //for TFE
-+
-+		pFVTDescriptor->dwTotalOutputSize = dwTotalFetchSize;
-+		HW_ENG_DBG("Fetch Size: %#x\n", dwTotalFetchSize);
-+	} else {
-+		dev_err(pAstRVAS->pdev, "Memory allocation failure\n");
-+		ri->rs = InvalidMemoryHandle;
-+	}
-+} // End - ioctl_fetch_video_tiles
-+
-+void prepare_ldma_descriptor(struct Descriptor *pDAddress, phys_addr_t source_addr,
-+			     phys_addr_t dest_addr, u32 dwLDMASize, u8 byNotLastEntry)
-+{
-+	u8 byInterrupt = 0;
-+
-+	HW_ENG_DBG("pDAddress: 0x%p\n", pDAddress);
-+
-+	// initialize to 0
-+	pDAddress->dw0General = 0x00;
-+	pDAddress->dw1FetchWidthLine = 0x00;
-+	pDAddress->dw2SourceAddr = 0x00;
-+	pDAddress->dw3DestinationAddr = 0x00;
-+
-+	// initialize to 0
-+	if (!byNotLastEntry)
-+		byInterrupt = 0x1;
-+
-+	pDAddress->dw0General = ((dwLDMASize - 1) << 8) | (byNotLastEntry << 1)
-+		| byInterrupt;
-+	pDAddress->dw2SourceAddr = (u32)source_addr;
-+	pDAddress->dw3DestinationAddr = (u32)dest_addr;
-+
-+	HW_ENG_DBG("u32 0: 0x%x\n", pDAddress->dw0General);
-+	HW_ENG_DBG("u32 1: 0x%x\n", pDAddress->dw1FetchWidthLine);
-+	HW_ENG_DBG("u32 2: 0x%x\n", pDAddress->dw2SourceAddr);
-+	HW_ENG_DBG("u32 3: 0x%x\n", pDAddress->dw3DestinationAddr);
-+}
-+
-+//
-+// ioctl_run_length_encode_data - encode buffer data
-+//
-+void ioctl_run_length_encode_data(struct RvasIoctl *ri, struct AstRVAS *pAstRVAS)
-+{
-+	struct Descriptor *pDescriptorAdd = NULL;
-+	struct Descriptor *pDescriptorAddPhys = NULL;
-+	u8 bytesPerPixel;
-+	bool bNotLastEntry = true;
-+	u32 dwTFECR = 0;
-+	bool bRLEOverFLow = false;
-+	u32 dwFetchWidthPixels = 0;
-+	u32 dwFetchHeight = 0;
-+	u32 dwPhysAddIn;
-+	u32 dwPhysAddOut;
-+	u32 data_size = 0;
-+	void *desc_virt = NULL;
-+	u32 desc_phy = 0;
-+	struct ContextTable *ctx_entry = NULL;
-+
-+	ctx_entry = get_context_entry(ri->rc, pAstRVAS);
-+	if (ctx_entry) {
-+		desc_virt = ctx_entry->desc_virt;
-+		desc_phy = ctx_entry->desc_phy;
-+	} else {
-+		ri->rs = InvalidContextHandle;
-+		return;
-+	}
-+
-+	ri->rs = SuccessStatus;
-+
-+	dwPhysAddIn = get_phys_add_rsvd_mem((u32)ri->rmh, pAstRVAS);
-+	dwPhysAddOut = get_phys_add_rsvd_mem((u32)ri->rmh1, pAstRVAS);
-+
-+	data_size = ri->rmh_mem_size;
-+	pDescriptorAdd = (struct Descriptor *)ctx_entry->desc_virt;
-+	pDescriptorAddPhys = (struct Descriptor *)ctx_entry->desc_phy;
-+
-+	HW_ENG_DBG("pDescriptorAdd=%#x, phy=%#x\n", (u32)pDescriptorAdd,
-+		   (u32)pDescriptorAddPhys);
-+
-+	if (dwPhysAddIn && dwPhysAddOut) {
-+		// Enable TFE
-+		dwTFECR = (ri->encode & 0xffff0000) << 16;
-+		dwTFECR |= 1;
-+		dwTFECR &= TFCTL_DESCRIPTOR_IN_DDR_MASK;
-+
-+		// triplet code and repeat code
-+		bNotLastEntry = false;
-+		bRLEOverFLow = true;
-+		dwFetchWidthPixels = TILE_SIZE;
-+		dwFetchHeight = data_size / TILE_SIZE;
-+		bytesPerPixel = 1;
-+
-+		prepare_tfe_descriptor(pDescriptorAdd, dwPhysAddIn,
-+				       dwPhysAddOut, bNotLastEntry, 1,
-+				       1, dwFetchWidthPixels,
-+				       bytesPerPixel, dwFetchWidthPixels,
-+				       dwFetchHeight, AllBytesMode, bRLEOverFLow, 1);
-+
-+		if (sleep_on_tfe_busy(pAstRVAS, (phys_addr_t)pDescriptorAddPhys,
-+				      dwTFECR, data_size, &ri->rle_len,
-+				      &ri->rle_checksum) == false) {
-+			ri->rs = GenericError;
-+			dev_err(pAstRVAS->pdev, "%s sleep_on_tfe_busy ERROR\n", __func__);
-+			return;
-+		}
-+	} else {
-+		ri->rs = InvalidMemoryHandle;
-+	}
-+}
-+
-+static u32 get_video_slice_fetch_width(u8 cBuckets)
-+{
-+	u32 dwFetchWidthPixels = 0;
-+
-+	switch (cBuckets) {
-+	case 3:
-+		dwFetchWidthPixels = ((TILE_SIZE << 5) * 3) >> 3;
-+		break;
-+
-+	case 8:
-+		dwFetchWidthPixels = TILE_SIZE << 5;
-+		break;
-+
-+	case 16:
-+		dwFetchWidthPixels = (TILE_SIZE << 5) * 2;
-+		break;
-+
-+	case 24:
-+		dwFetchWidthPixels = (TILE_SIZE << 5) * 3;
-+		break;
-+
-+	default:
-+		dwFetchWidthPixels = TILE_SIZE << 2;
-+		break;
-+	}
-+
-+	return dwFetchWidthPixels;
-+}
-+
-+void ioctl_fetch_video_slices(struct RvasIoctl *ri, struct AstRVAS *pAstRVAS)
-+{
-+	struct FetchVideoSlicesArg *pFVSA;
-+	u32 dwCD;
-+	struct Descriptor *pdesc_virt;
-+	phys_addr_t qw_desc_phys;
-+	phys_addr_t source_addr;
-+	phys_addr_t slice_dest_addr;
-+	u8 bytesPerPixel;
-+	bool bNotLastEntry = true;
-+	bool bInterrupt = false;
-+	u32 dwTFECR = 0;
-+	u32 dwFetchSize = 0;
-+	bool bRLEOverFLow = false;
-+	u32 dwFetchWidthPixels = 0;
-+	u32 dwFetchHeight = 0;
-+	phys_addr_t arg_phys = 0;
-+	phys_addr_t data_phys_out = 0;
-+	phys_addr_t data_phys_rle = 0;
-+	struct BSEAggregateRegister aBSEAR;
-+	struct Descriptor *pNextDescriptor = 0;
-+	phys_addr_t dest_next_addr = 0;
-+	u32 dwBucketSizeIter = 0;
-+	bool bBucketSizeEnable = 0;
-+	void __iomem *addrBSCR = pAstRVAS->fg_reg_base + BSE_Command_Register;
-+	void *desc_virt = NULL;
-+	phys_addr_t desc_phy = 0;
-+	struct ContextTable *ctx_entry = get_context_entry(ri->rc, pAstRVAS);
-+
-+	HW_ENG_DBG("Start\n");
-+
-+	if (ctx_entry) {
-+		desc_virt = ctx_entry->desc_virt;
-+		desc_phy = ctx_entry->desc_phy;
-+	} else {
-+		pr_err("BSE: Cannot get valid context\n");
-+		ri->rs = InvalidContextHandle;
-+		return;
-+	}
-+
-+	arg_phys = get_phys_add_rsvd_mem((u32)ri->rmh, pAstRVAS);
-+	data_phys_out = get_phys_add_rsvd_mem((u32)ri->rmh1, pAstRVAS);
-+	data_phys_rle = get_phys_add_rsvd_mem((u32)ri->rmh2, pAstRVAS);
-+
-+	if (!arg_phys || !data_phys_out || !data_phys_rle) {
-+		pr_err("BSE: Invalid memory handle\n");
-+		ri->rs = InvalidMemoryHandle;
-+		return;
-+	}
-+	ri->rs = SuccessStatus;
-+	slice_dest_addr = data_phys_out;
-+	pFVSA = (struct FetchVideoSlicesArg *)get_virt_add_rsvd_mem((u32)ri->rmh, pAstRVAS);
-+
-+	HW_ENG_DBG("bEnableRLE: %d cBuckets: %u cfr: %u\n", pFVSA->bEnableRLE,
-+		   pFVSA->cBuckets, pFVSA->cfr);
-+
-+	if (pFVSA->cfr > 1) {
-+		writel(readl(addrBSCR) | BSE_ENABLE_MULT_BUCKET_SZS, addrBSCR);
-+		bBucketSizeEnable = 1;
-+	} else {
-+		writel(readl(addrBSCR) & (~BSE_ENABLE_MULT_BUCKET_SZS), addrBSCR);
-+		bBucketSizeEnable = 0;
-+	}
-+
-+	HW_ENG_DBG("*pdwBSCR: %#x bBucketSizeEnable: %d\n", readl(addrBSCR),
-+		   bBucketSizeEnable);
-+
-+	pdesc_virt = ctx_entry->desc_virt;
-+	qw_desc_phys = ctx_entry->desc_phy;
-+	bytesPerPixel = pFVSA->vg.byBitsPerPixel >> 3;
-+
-+	HW_ENG_DBG("BSE:: u8 per pixel: %d\n", bytesPerPixel);
-+	HW_ENG_DBG("BSE:: cfr: %u bucket size: %d\n", pFVSA->cfr, pFVSA->cBuckets);
-+
-+	pNextDescriptor = pdesc_virt;
-+	dest_next_addr = slice_dest_addr;
-+	// Prepare BSE Descriptors for all Regions
-+	HW_ENG_DBG("pNextDescriptor 0x%p dest_next_addr: %#x\n", pNextDescriptor,
-+		   dest_next_addr);
-+
-+	for (dwCD = 0; dwCD < pFVSA->cfr; dwCD++) {
-+		HW_ENG_DBG("dwCD: %u\n", dwCD);
-+		HW_ENG_DBG("pfr->wLeftX :%d\n", pFVSA->pfr[dwCD].wLeftX);
-+		HW_ENG_DBG("pfr->wTopY :%d\n", pFVSA->pfr[dwCD].wTopY);
-+		HW_ENG_DBG("pfr->wRightX :%d\n", pFVSA->pfr[dwCD].wRightX);
-+		HW_ENG_DBG("pfr->wBottomY :%d\n", pFVSA->pfr[dwCD].wBottomY);
-+
-+		source_addr = get_phy_fb_start_address(pAstRVAS)
-+			+ pFVSA->pfr[dwCD].wLeftX * bytesPerPixel
-+			+ pFVSA->pfr[dwCD].wTopY * pFVSA->vg.wStride
-+			* bytesPerPixel;
-+		dwFetchWidthPixels = (pFVSA->pfr[dwCD].wRightX
-+			- pFVSA->pfr[dwCD].wLeftX + 1);
-+		dwFetchHeight = pFVSA->pfr[dwCD].wBottomY
-+			- pFVSA->pfr[dwCD].wTopY + 1;
-+
-+		HW_ENG_DBG("BSE Width in Pixel: %d\n", dwFetchWidthPixels);
-+		HW_ENG_DBG("BSE Height: %d bBucketSizeEnable: %d\n", dwFetchHeight,
-+			   bBucketSizeEnable);
-+
-+		if (!bBucketSizeEnable) {
-+			bNotLastEntry = false;
-+			bInterrupt = true;
-+			prepare_bse_descriptor(pdesc_virt,
-+					       source_addr, slice_dest_addr,
-+					       bNotLastEntry, pFVSA->vg.wStride, bytesPerPixel,
-+					       dwFetchWidthPixels, dwFetchHeight, bInterrupt);
-+			dwFetchSize += (pFVSA->cBuckets
-+				* (dwFetchWidthPixels * dwFetchHeight) >> 3);
-+			aBSEAR = setUp_bse_bucket(pFVSA->abyBitIndexes,
-+						  pFVSA->cBuckets, bytesPerPixel,
-+						  dwFetchWidthPixels, dwFetchHeight);
-+
-+		} else {
-+			if (dwCD == pFVSA->cfr - 1) {
-+				bNotLastEntry = false;
-+				bInterrupt = true;
-+			} else {
-+				bNotLastEntry = true;
-+				bInterrupt = false;
-+			}
-+
-+			prepare_bse_descriptor_2(pNextDescriptor,
-+						 source_addr,
-+						 dest_next_addr, bNotLastEntry,
-+						 pFVSA->vg.wStride, bytesPerPixel,
-+						 dwFetchWidthPixels, dwFetchHeight,
-+						 bInterrupt,
-+						 arrBuckSizeRegIndex[dwBucketSizeIter]);
-+
-+			aBSEAR = set_up_bse_bucket_2(pAstRVAS,
-+						     pFVSA->abyBitIndexes, pFVSA->cBuckets,
-+						     bytesPerPixel, dwFetchWidthPixels,
-+						     dwFetchHeight,
-+						     arrBuckSizeRegIndex[dwBucketSizeIter]);
-+
-+			dwBucketSizeIter++;
-+			pNextDescriptor++;
-+			dwFetchSize += pFVSA->cBuckets
-+				* ((dwFetchWidthPixels * dwFetchHeight) >> 3); //each bucket size
-+			dest_next_addr = slice_dest_addr
-+				+ dwFetchSize;
-+		}
-+	}
-+
-+	//bse now
-+	if (pFVSA->cBuckets <= FULL_BUCKETS_COUNT) {
-+		if (bBucketSizeEnable)
-+			aBSEAR.dwBSDBS = 0x80000000;
-+
-+		HW_ENG_DBG("Sleeping on BSE to complete\n");
-+
-+		if (sleep_on_bse_busy(pAstRVAS, qw_desc_phys, aBSEAR,
-+				      dwFetchSize) == false) {
-+			dev_err(pAstRVAS->pdev, ".....BSE Timeout\n");
-+			ri->rs = GenericError;
-+			return;
-+		}
-+	}
-+	HW_ENG_DBG("Fetched the bit slices\n");
-+	//RLE
-+	pFVSA->dwSlicedSize = dwFetchSize;
-+	pFVSA->dwSlicedRLESize = pFVSA->dwSlicedSize;
-+
-+	// do RLE if RLE is on. Fetch from Destination 1 to Destination 2 with RLE on
-+	bNotLastEntry = false;
-+
-+	if (pFVSA->bEnableRLE) {
-+		HW_ENG_DBG("BSE - 3 (RLE Enabled)\n");
-+		// Enable TFE
-+		dwTFECR = ((pFVSA->byRLETripletCode << 24)
-+			| (pFVSA->byRLERepeatCode << 16));
-+		dwTFECR |= ((0x1 << 1) | 1);
-+		dwTFECR &= TFCTL_DESCRIPTOR_IN_DDR_MASK;
-+
-+		bRLEOverFLow = true;
-+		bytesPerPixel = 1;
-+
-+		dwFetchWidthPixels = get_video_slice_fetch_width(pFVSA->cBuckets);
-+		dwFetchHeight = dwFetchSize / dwFetchWidthPixels;
-+
-+		prepare_tfe_descriptor(pdesc_virt, data_phys_out,
-+				       data_phys_rle, bNotLastEntry, 1, pFVSA->bEnableRLE,
-+				       dwFetchWidthPixels, bytesPerPixel, dwFetchWidthPixels,
-+				       dwFetchHeight, 0, bRLEOverFLow, 1);
-+
-+		HW_ENG_DBG("TFE-RLE Control Register value: 0x%x\n", dwTFECR);
-+
-+		if (sleep_on_tfe_busy(pAstRVAS, qw_desc_phys, // Descriptor physical Address
-+			dwTFECR,               // control register value
-+			dwFetchSize,          // bandwidth limiter value
-+			&pFVSA->dwSlicedRLESize,       // out:: rle size
-+			&pFVSA->dwCheckSum
-+			) == false) {
-+			ri->rs = GenericError;
-+			return;
-+		}
-+
-+		HW_ENG_DBG("Finishing RLE Fetching\n");
-+
-+		if (pFVSA->dwSlicedRLESize >= pFVSA->dwSlicedSize)
-+			pFVSA->bRLEFailed = true;
-+		else
-+			pFVSA->bRLEFailed = false;
-+	} // RLE enabled
-+
-+	memcpy((void *)&dwFetchSize, (void *)&pFVSA->dwSlicedRLESize, 4);
-+}
-+
-+void ioctl_fetch_text_data(struct RvasIoctl *ri, struct AstRVAS *pAstRVAS)
-+{
-+	bool bRLEOn = ri->tfm.bEnableRLE;
-+
-+	ri->rs = SuccessStatus;
-+
-+	// first time fetch
-+	on_fetch_text_data(ri, bRLEOn, pAstRVAS);
-+}
-+
-+void on_fetch_text_data(struct RvasIoctl *ri, bool bRLEOn, struct AstRVAS *pAstRVAS)
-+{
-+	struct Descriptor *pDescriptorAdd;
-+	struct Descriptor *pDescriptorAddPhys;
-+	u32 dwScreenOffset = 0x00;
-+	phys_addr_t source_addr = get_phy_fb_start_address(pAstRVAS);
-+	phys_addr_t dest_addr;
-+	bool bRLEOverFlow = false;
-+	bool bInterrupt = true;
-+	u32 wFetchLines = 0;
-+	u8 byCharacterPerLine = 0;
-+	u16 wFetchWidthInBytes = 0;
-+	phys_addr_t data_phys = 0;
-+	phys_addr_t data_phys_rle = 0;
-+	phys_addr_t data_phys_temp = 0;
-+	u32 dwCtrlRegValue = 0;
-+	u32 dwMinBufSize = 0;
-+	void *desc_virt = NULL;
-+	phys_addr_t desc_phy = 0;
-+	struct ContextTable *ctx_entry = NULL;
-+
-+	HW_ENG_DBG("Start\n");
-+	ctx_entry = get_context_entry(ri->rc, pAstRVAS);
-+	if (ctx_entry) {
-+		desc_virt = ctx_entry->desc_virt;
-+		desc_phy = ctx_entry->desc_phy;
-+	} else {
-+		ri->rs = InvalidContextHandle;
-+		return;
-+	}
-+
-+	wFetchLines = get_text_mode_fetch_lines(pAstRVAS, ri->vg.wScreenHeight);
-+	byCharacterPerLine = get_text_mode_character_per_line(pAstRVAS,
-+							      ri->vg.wScreenWidth);
-+
-+	data_phys = get_phys_add_rsvd_mem((u32)ri->rmh, pAstRVAS);
-+	data_phys_rle = get_phys_add_rsvd_mem((u32)ri->rmh1, pAstRVAS);
-+
-+	if (!data_phys || !data_phys_rle) {
-+		ri->rs = InvalidMemoryHandle;
-+		dev_err(pAstRVAS->pdev, "Fetch Text: Invalid Memoryhandle\n");
-+		return;
-+	}
-+
-+	dwMinBufSize = (byCharacterPerLine * wFetchLines) << 1;
-+
-+	if (ri->rmh_mem_size < dwMinBufSize) {
-+		//either buffer is too small or invalid data in registers
-+		ri->rs = GenericError;
-+		dev_err(pAstRVAS->pdev, "Fetch Text: required buffer len:0x%x\n", dwMinBufSize);
-+		return;
-+	}
-+	memset(desc_virt, 0x00, MAX_DESC_SIZE);
-+	pDescriptorAdd = desc_virt;
-+	pDescriptorAddPhys = (struct Descriptor *)desc_phy;
-+	dest_addr = data_phys;
-+
-+	// Enable TFE
-+	dwCtrlRegValue |= 1;
-+	dwCtrlRegValue &= TFCTL_DESCRIPTOR_IN_DDR_MASK;
-+	// set up the text alignment
-+	dwScreenOffset = get_screen_offset(pAstRVAS);
-+	source_addr += dwScreenOffset;
-+	HW_ENG_DBG("screen offset:%#x, Source start Addr: %%llx\n", dwScreenOffset,
-+		   source_addr);
-+	if (ri->tfm.dpm == AttrMode) { // ATTR and ASCII
-+		data_phys_temp = data_phys_rle;
-+		wFetchWidthInBytes = byCharacterPerLine << 3;
-+		// must fetch both ascii & attr
-+		HW_ENG_DBG("Attribute and ASCII\n");
-+		prepare_tfe_text_descriptor(desc_virt, source_addr,
-+					    data_phys_temp,
-+					    false, wFetchWidthInBytes, wFetchLines,
-+					    ri->tfm.dpm, bRLEOverFlow, bInterrupt);
-+		ri->tfm.dwFetchSize = (byCharacterPerLine * wFetchLines) << 1;
-+	} else if (ri->tfm.dpm == AsciiOnlyMode) {
-+		wFetchWidthInBytes = byCharacterPerLine << 3;
-+		HW_ENG_DBG("ASCII Only\n");
-+		prepare_tfe_text_descriptor(desc_virt, source_addr,
-+					    dest_addr,
-+					    false, wFetchWidthInBytes, wFetchLines,
-+					    ri->tfm.dpm, bRLEOverFlow, bInterrupt);
-+		ri->tfm.dwFetchSize = byCharacterPerLine * wFetchLines;
-+	} else if (ri->tfm.dpm == FontFetchMode) {
-+		wFetchWidthInBytes = byCharacterPerLine << 2;
-+		HW_ENG_DBG("Font Only\n");
-+		prepare_tfe_text_descriptor(desc_virt, source_addr,
-+					    dest_addr,
-+					    false, wFetchWidthInBytes,
-+					    wFetchLines + 256,
-+					    ri->tfm.dpm, bRLEOverFlow, bInterrupt);
-+
-+		ri->tfm.dwFetchSize = MAX_TEXT_DATA_SIZE;
-+	}
-+	dwCtrlRegValue |= 1 << 1; // enabled IRQ
-+	if (ri->tfm.dpm == AttrMode) {
-+		if (sleep_on_tfe_text_busy(pAstRVAS, desc_phy, dwCtrlRegValue, // control register value
-+					   ri->tfm.dwFetchSize,        // bandwidth limitor value
-+					   &ri->tfm.dwFetchRLESize,        // out:: rle size
-+					   &ri->tfm.dwCheckSum) == false) {
-+			dev_err(pAstRVAS->pdev, "Could not sleep_on_tfe_busy for attributes\n");
-+			ri->rs = GenericError;
-+			return;
-+		}
-+	} else {
-+		if (sleep_on_tfe_text_busy(pAstRVAS, desc_phy, dwCtrlRegValue,
-+					   ri->tfm.dwFetchSize, &ri->tfm.dwFetchRLESize,
-+					   &ri->tfm.dwCheckSum) == false) {
-+			ri->rs = GenericError;
-+			dev_err(pAstRVAS->pdev, "Could not sleep_on_tfe_busy for others\n");
-+			return;
-+		}
-+	}
-+
-+	if (ri->tfm.dpm == AttrMode) {
-+		//separate ATTR from ATTR+ASCII
-+		source_addr = data_phys_temp;
-+		dest_addr = data_phys;
-+		prepare_tfe_descriptor(desc_virt, data_phys_temp, data_phys,
-+				       false,        //not last entry?
-+				       1,        //checksum
-+				       false,        //RLE?
-+				       byCharacterPerLine,
-+				       2,        //byBpp,
-+				       byCharacterPerLine, wFetchLines, TopByteMode,
-+				       bRLEOverFlow, bInterrupt);
-+
-+		ri->tfm.dwFetchSize = byCharacterPerLine * wFetchLines;
-+
-+		dwCtrlRegValue |= 1 << 1;        // enabled IRQ
-+		if (sleep_on_tfe_text_busy(pAstRVAS, (phys_addr_t)pDescriptorAddPhys,
-+					   dwCtrlRegValue, ri->tfm.dwFetchSize,
-+					   &ri->tfm.dwFetchRLESize, &ri->tfm.dwCheckSum) == false) {
-+			dev_err(pAstRVAS->pdev, "Could not sleep_on_tfe_busy for attributes # 2\n");
-+			ri->rs = GenericError;
-+			return;
-+		}
-+	}
-+	// RLE enabled
-+	if (bRLEOn) {
-+		bRLEOverFlow = true;
-+		dwCtrlRegValue = 1;
-+		dwCtrlRegValue |= (ri->tfm.byRLETripletCode << 24)
-+			| (ri->tfm.byRLERepeatCode << 16);
-+		source_addr = dest_addr;
-+		dest_addr = data_phys_rle;
-+
-+		// RLE only
-+		prepare_tfe_descriptor(pDescriptorAdd, source_addr,
-+				       dest_addr,
-+				       false,        //not last entry?
-+				       1,        //checksum
-+				       bRLEOn,        //RLE?
-+				       ri->tfm.dwFetchSize / wFetchLines, 1,
-+				       ri->tfm.dwFetchSize / wFetchLines, wFetchLines,
-+				       AllBytesMode, bRLEOverFlow, bInterrupt);
-+
-+		dwCtrlRegValue |= 1 << 1;        // enabled IRQ
-+
-+		if (sleep_on_tfe_busy(pAstRVAS, (phys_addr_t)pDescriptorAddPhys, // Descriptor physical Address
-+				      dwCtrlRegValue,        // control register value
-+				      ri->tfm.dwFetchSize,        // bandwidth limitor value
-+				      &ri->tfm.dwFetchRLESize,        // out:: rle size
-+				      &ri->tfm.dwCheckSum) == false) { // out:: cs size
-+			dev_err(pAstRVAS->pdev, "Could not sleep_on_tfe_busy for RLE for Text Mode\n");
-+			ri->rs = GenericError;
-+			return;
-+		}     //sleeponTFEBusy
-+	}
-+	if (bRLEOn) {
-+		ri->tfm.bRLEFailed =
-+			(ri->tfm.dwFetchRLESize < ri->tfm.dwFetchSize) ?
-+			false : true;
-+	}
-+}
-+
-+u8 get_text_mode_character_per_line(struct AstRVAS *pAstRVAS, u16 wScreenWidth)
-+{
-+	u8 byCharPerLine = 0x00;
-+	u8 byCharWidth = 0;
-+	u8 byVGASR1 = readb(pAstRVAS->grce_reg_base + GRCE_SEQ + 0x1);
-+
-+	byCharWidth = (byVGASR1 & 0x1) ? 8 : 9;
-+	byCharPerLine = wScreenWidth / byCharWidth;
-+
-+	return byCharPerLine;
-+}
-+
-+u16 get_text_mode_fetch_lines(struct AstRVAS *pAstRVAS, u16 wScreenHeight)
-+{
-+	u8 byVGACR9 = readb(pAstRVAS->grce_reg_base + GRCE_CRTC + 0x9);
-+	u8 byFontHeight = (byVGACR9 & 0x1F) + 1;
-+	u16 wFetchLines;
-+
-+	wFetchLines = wScreenHeight / byFontHeight;
-+
-+	return wFetchLines;
-+}
-+
-+//
-+// HELPER Functions
-+//
-+
-+void prepare_bse_descriptor(struct Descriptor *pDAddress, phys_addr_t source_addr,
-+			    phys_addr_t dest_addr, bool bNotLastEntry,
-+			    u16 wStride, u8 bytesPerPixel,
-+			    u32 dwFetchWidthPixels, u32 dwFetchHeight,
-+			    bool bInterrupt)
-+{
-+	u16 wDestinationStride;
-+
-+	// initialize to 0
-+	pDAddress->dw0General = 0x00;
-+	pDAddress->dw1FetchWidthLine = 0x00;
-+	pDAddress->dw2SourceAddr = 0x00;
-+	pDAddress->dw3DestinationAddr = 0x00;
-+
-+	wDestinationStride = dwFetchWidthPixels >> 3;
-+
-+	// initialize to 0
-+	pDAddress->dw0General = ((wStride * bytesPerPixel) << 16)
-+		| (wDestinationStride << 8) | (bNotLastEntry << 1) | bInterrupt;
-+	pDAddress->dw1FetchWidthLine = ((dwFetchHeight - 1) << 16)
-+		| (dwFetchWidthPixels * bytesPerPixel - 1);
-+	pDAddress->dw2SourceAddr = (u32)source_addr & 0xfffffffc;
-+	pDAddress->dw3DestinationAddr = (u32)dest_addr & 0xfffffffc;
-+
-+	HW_ENG_DBG("After SETTING BSE Descriptor\n");
-+	HW_ENG_DBG("u32 0: 0x%x\n", pDAddress->dw0General);
-+	HW_ENG_DBG("u32 1: 0x%x\n", pDAddress->dw1FetchWidthLine);
-+	HW_ENG_DBG("u32 2: 0x%x\n", pDAddress->dw2SourceAddr);
-+	HW_ENG_DBG("u32 3: 0x%x\n", pDAddress->dw3DestinationAddr);
-+}
-+
-+//for descriptor chaining
-+void prepare_bse_descriptor_2(struct Descriptor *pDAddress, phys_addr_t source_addr,
-+			      phys_addr_t dest_addr, bool bNotLastEntry,
-+			      u16 wStride, u8 bytesPerPixel,
-+			      u32 dwFetchWidthPixels, u32 dwFetchHeight,
-+			      bool bInterrupt, u8 byBuckSizeRegIndex)
-+{
-+	u16 wDestinationStride;
-+
-+	// initialize to 0
-+	pDAddress->dw0General = 0x00;
-+	pDAddress->dw1FetchWidthLine = 0x00;
-+	pDAddress->dw2SourceAddr = 0x00;
-+	pDAddress->dw3DestinationAddr = 0x00;
-+
-+	wDestinationStride = dwFetchWidthPixels >> 3;
-+
-+	// initialize to 0
-+	pDAddress->dw0General = ((wStride * bytesPerPixel) << 16)
-+		| (wDestinationStride << 8)
-+		| (byBuckSizeRegIndex << BSE_BUCK_SZ_INDEX_POS)
-+		| (bNotLastEntry << 1) | bInterrupt;
-+	pDAddress->dw1FetchWidthLine = ((dwFetchHeight - 1) << 16)
-+		| (dwFetchWidthPixels * bytesPerPixel - 1);
-+	pDAddress->dw2SourceAddr = (u32)source_addr & 0xfffffffc;
-+	pDAddress->dw3DestinationAddr = (u32)dest_addr & 0xfffffffc;
-+
-+	HW_ENG_DBG("AFter SETTING BSE Descriptor\n");
-+	HW_ENG_DBG("u32 0: 0x%x\n", pDAddress->dw0General);
-+	HW_ENG_DBG("u32 1: 0x%x\n", pDAddress->dw1FetchWidthLine);
-+	HW_ENG_DBG("u32 2: 0x%x\n", pDAddress->dw2SourceAddr);
-+	HW_ENG_DBG("u32 3: 0x%x\n", pDAddress->dw3DestinationAddr);
-+}
-+
-+struct BSEAggregateRegister set_up_bse_bucket_2(struct AstRVAS *pAstRVAS, u8 *abyBitIndexes,
-+						u8 byTotalBucketCount, u8 byBSBytesPerPixel,
-+						u32 dwFetchWidthPixels, u32 dwFetchHeight,
-+						u32 dwBucketSizeIndex)
-+{
-+	struct BSEAggregateRegister aBSEAR = { 0 };
-+	void __iomem *addrBSDBS = 0;
-+	void __iomem *addrBSCR = pAstRVAS->fg_reg_base + BSE_Command_Register;
-+
-+	if (dwBucketSizeIndex >= BSE_MAX_BUCKET_SIZE_REGS) {
-+		dev_err(pAstRVAS->pdev, "Video::BSE bucket size index %d too big!",
-+			dwBucketSizeIndex);
-+		return aBSEAR;
-+	}
-+
-+	addrBSDBS = pAstRVAS->fg_reg_base + BSE_REG_BASE + dwBucketSizeRegOffset[dwBucketSizeIndex];
-+
-+	// initialize
-+	memset((void *)&aBSEAR, 0x00, sizeof(struct BSEAggregateRegister));
-+	aBSEAR = setUp_bse_bucket(abyBitIndexes, byTotalBucketCount,
-+				  byBSBytesPerPixel, dwFetchWidthPixels, dwFetchHeight);
-+
-+	writel(aBSEAR.dwBSDBS, addrBSDBS);
-+	aBSEAR.dwBSCR |= readl(addrBSCR) & (BSE_ENABLE_MULT_BUCKET_SZS);
-+	HW_ENG_DBG("BSE Bucket size register index %d, [%#x], readback 0x%x\n",
-+		   dwBucketSizeIndex, aBSEAR.dwBSDBS, readl(addrBSCR));
-+
-+	return aBSEAR;
-+}
-+
-+struct BSEAggregateRegister setUp_bse_bucket(u8 *abyBitIndexes, u8 byTotalBucketCount,
-+					     u8 byBSBytesPerPixel, u32 dwFetchWidthPixels,
-+					     u32 dwFetchHeight)
-+{
-+	struct BSEAggregateRegister aBSEAR;
-+	u32 dwSrcBucketSize = MAX_LMEM_BUCKET_SIZE;
-+	u32 dwDestBucketSize = dwFetchWidthPixels * dwFetchHeight >> 3; //each bucket size
-+	u8 byRegisterPosition = 0;
-+	u8 cBucket;
-+
-+	// initialize
-+	memset((void *)&aBSEAR, 0x00, sizeof(struct BSEAggregateRegister));
-+
-+	for (cBucket = 0; cBucket < byTotalBucketCount; cBucket++) {
-+		if (cBucket < 6) {
-+			HW_ENG_DBG("BUCKET: 0x%x, Bit Position: 0x%x\n", cBucket,
-+				   abyBitIndexes[cBucket]);
-+			HW_ENG_DBG("BSBPS0 Position: 0x%x\n", byRegisterPosition);
-+				   aBSEAR.adwBSBPS[0] |= abyBitIndexes[cBucket]
-+				   << byRegisterPosition;
-+
-+			byRegisterPosition += 5;
-+		} else if (cBucket >= 6 && cBucket < 12) {
-+			if (cBucket == 6)
-+				byRegisterPosition = 0;
-+
-+			HW_ENG_DBG("BUCKET: 0x%x, Bit Position: 0x%x\n", cBucket,
-+				   abyBitIndexes[cBucket]);
-+			HW_ENG_DBG("BSBPS1 Position: 0x%x\n", byRegisterPosition);
-+				   aBSEAR.adwBSBPS[1] |= abyBitIndexes[cBucket]
-+				   << byRegisterPosition;
-+			byRegisterPosition += 5;
-+		} else {
-+			if (cBucket == 12)
-+				byRegisterPosition = 0;
-+
-+			HW_ENG_DBG("BUCKET: 0x%x, Bit Position: 0x%x\n", cBucket,
-+				   abyBitIndexes[cBucket]);
-+			HW_ENG_DBG("BSBPS2 Position: 0x%x\n", byRegisterPosition);
-+				   aBSEAR.adwBSBPS[2] |= abyBitIndexes[cBucket]
-+				   << byRegisterPosition;
-+			byRegisterPosition += 5;
-+		}
-+	}
-+
-+	aBSEAR.dwBSCR = (((byTotalBucketCount - 1) << 8)
-+			| ((byBSBytesPerPixel - 1) << 4) | (0x0 << 3)
-+			| (0x1 << 1) | 0x1) & BSCMD_MASK;
-+	aBSEAR.dwBSDBS = ((dwSrcBucketSize << 24) | dwDestBucketSize)
-+		& 0xfcfffffc;
-+
-+	HW_ENG_DBG("dwFetchWidthPixels [%#x], dwFetchHeight [%#x]\n",
-+		   dwFetchWidthPixels, dwFetchHeight);
-+	HW_ENG_DBG("BSE Destination Bucket Size [%#x]\n", dwDestBucketSize);
-+	HW_ENG_DBG("BSE Control [%#x]\n", aBSEAR.dwBSCR);
-+	HW_ENG_DBG("BSE BSDBS [%#x]\n", aBSEAR.dwBSDBS);
-+	HW_ENG_DBG("BSE BSBPS0 [%#x]\n", aBSEAR.adwBSBPS[0]);
-+	HW_ENG_DBG("BSE BSBPS1 [%#x]\n", aBSEAR.adwBSBPS[1]);
-+	HW_ENG_DBG("BSE BSBPS2 [%#x]\n", aBSEAR.adwBSBPS[2]);
-+
-+	return aBSEAR;
-+}
-+
-+void prepare_tfe_descriptor(struct Descriptor *pDAddress, phys_addr_t source_addr,
-+			    phys_addr_t dest_addr, bool bNotLastEntry, u8 bCheckSum,
-+			    bool bEnabledRLE, u16 wStride, u8 bytesPerPixel,
-+			    u32 dwFetchWidthPixels, u32 dwFetchHeight,
-+			    enum SelectedByteMode sbm, bool bRLEOverFLow,
-+			    bool bInterrupt)
-+{
-+	enum SkipByteMode skipBM = NoByteSkip;
-+	enum DataProccessMode dpm = NormalTileMode;
-+	enum StartBytePosition sbp = StartFromByte0;
-+
-+	HW_ENG_DBG("BEFORE SETTING TFE Descriptor\n");
-+	// initialize to 0
-+	pDAddress->dw0General = 0x00;
-+	pDAddress->dw1FetchWidthLine = 0x00;
-+	pDAddress->dw2SourceAddr = 0x00;
-+	pDAddress->dw3DestinationAddr = 0x00;
-+
-+	if (dwFetchHeight & 0x3)
-+		dwFetchHeight = ((dwFetchHeight + 3) >> 2) << 2;
-+
-+	switch (sbm) {
-+	case AllBytesMode:
-+		break;
-+
-+	case LowByteMode:
-+		dpm = SplitByteMode;
-+		if (bytesPerPixel == 2)
-+			skipBM = SkipOneByte;
-+		else if (bytesPerPixel == 3)
-+			skipBM = SkipTwoByte;
-+		else if (bytesPerPixel == 4)
-+			skipBM = SkipThreeByte;
-+		break;
-+
-+	case MiddleByteMode:
-+		dpm = SplitByteMode;
-+		if (bytesPerPixel == 2) {
-+			skipBM = SkipOneByte;
-+			sbp = StartFromByte1;
-+		} else if (bytesPerPixel == 3) {
-+			skipBM = SkipTwoByte;
-+			sbp = StartFromByte1;
-+		} else if (bytesPerPixel == 4) {
-+			skipBM = SkipThreeByte;
-+			sbp = StartFromByte1;
-+		}
-+		break;
-+
-+	case TopByteMode:
-+		dpm = SplitByteMode;
-+		if (bytesPerPixel == 2) {
-+			skipBM = SkipOneByte;
-+			sbp = StartFromByte1;
-+		} else if (bytesPerPixel == 3) {
-+			skipBM = SkipTwoByte;
-+			sbp = StartFromByte2;
-+		} else if (bytesPerPixel == 4) {
-+			skipBM = SkipThreeByte;
-+			sbp = StartFromByte2;
-+		}
-+		break;
-+
-+	case PlanarToPackedMode:
-+		dpm = FourBitPlanarMode;
-+		break;
-+
-+	case PackedToPackedMode:
-+		dpm = FourBitPackedMode;
-+		break;
-+
-+	default:
-+		break;
-+	}
-+
-+	if (dwFetchWidthPixels > wStride)
-+		wStride = dwFetchWidthPixels;
-+
-+	pDAddress->dw0General = ((wStride * bytesPerPixel) << 16) | (dpm << 13)
-+		| (sbp << 10) | (skipBM << 8) | (bRLEOverFLow << 7)
-+		| (bCheckSum << 5) | (bEnabledRLE << 4) | (bNotLastEntry << 1)
-+		| bInterrupt;
-+	pDAddress->dw1FetchWidthLine = ((dwFetchHeight - 1) << 16)
-+		| (dwFetchWidthPixels * bytesPerPixel - 1);
-+	pDAddress->dw2SourceAddr = (u32)source_addr & 0xfffffffc;
-+	pDAddress->dw3DestinationAddr = (u32)dest_addr & 0xfffffffc;
-+
-+	HW_ENG_DBG("After SETTING TFE Descriptor\n");
-+	HW_ENG_DBG("u32 0: 0x%x\n", pDAddress->dw0General);
-+	HW_ENG_DBG("u32 1: 0x%x\n", pDAddress->dw1FetchWidthLine);
-+	HW_ENG_DBG("u32 2: 0x%x\n", pDAddress->dw2SourceAddr);
-+	HW_ENG_DBG("u32 3: 0x%x\n", pDAddress->dw3DestinationAddr);
-+}
-+
-+void prepare_tfe_text_descriptor(struct Descriptor *pDAddress, phys_addr_t source_addr,
-+				 phys_addr_t dest_addr, bool bEnabledRLE, u32 dwFetchWidth,
-+				 u32 dwFetchHeight, enum DataProccessMode dpm,
-+				 bool bRLEOverFLow, bool bInterrupt)
-+{
-+	// initialize to 0
-+	pDAddress->dw0General = 0x00;
-+	pDAddress->dw1FetchWidthLine = 0x00;
-+	pDAddress->dw2SourceAddr = 0x00;
-+	pDAddress->dw3DestinationAddr = 0x00;
-+
-+	if (dwFetchHeight & 0x3)
-+		dwFetchHeight = ((dwFetchHeight + 3) >> 2) << 2;
-+
-+	pDAddress->dw0General = (dwFetchWidth << 16) | (dpm << 13)
-+		| (bRLEOverFLow << 7) | (1 << 5) | (bEnabledRLE << 4)
-+		| bInterrupt;
-+	pDAddress->dw1FetchWidthLine = ((dwFetchHeight - 1) << 16)
-+		| (dwFetchWidth - 1);
-+	pDAddress->dw2SourceAddr = (u32)source_addr & 0xfffffffc;
-+	pDAddress->dw3DestinationAddr = (u32)dest_addr & 0xfffffffc;
-+
-+	HW_ENG_DBG("u32 0: 0x%x\n", pDAddress->dw0General);
-+	HW_ENG_DBG("u32 1: 0x%x\n", pDAddress->dw1FetchWidthLine);
-+	HW_ENG_DBG("u32 2: 0x%x\n", pDAddress->dw2SourceAddr);
-+	HW_ENG_DBG("u32 3: 0x%x\n", pDAddress->dw3DestinationAddr);
-+}
-+
-+void on_fetch_mode_13_data(struct AstRVAS *pAstRVAS, struct RvasIoctl *ri, bool bRLEOn)
-+{
-+	struct Descriptor *pDescriptorAdd;
-+	struct Descriptor *pDescriptorAddPhys;
-+	phys_addr_t source_addr = get_phy_fb_start_address(pAstRVAS);
-+	phys_addr_t dest_addr;
-+	bool bRLEOverFlow = false;
-+	bool bNotLastEntry = false;
-+	bool bInterrupt = 1;
-+	u32 dwFetchHeight = MODE13_HEIGHT;
-+	u32 dwFetchWidth = MODE13_WIDTH;
-+	phys_addr_t data_phys = 0;
-+	phys_addr_t data_phys_rle = 0;
-+	u32 dwCtrlRegValue = 0x55AA0080;
-+	void *desc_virt = NULL;
-+	phys_addr_t desc_phy = 0;
-+	struct ContextTable *ctx_entry = NULL;
-+
-+	HW_ENG_DBG("Start, bRLEOn: %d\n", bRLEOn);
-+
-+	ctx_entry = get_context_entry(ri->rc, pAstRVAS);
-+
-+	if (ctx_entry) {
-+		desc_virt = ctx_entry->desc_virt;
-+		desc_phy = ctx_entry->desc_phy;
-+	} else {
-+		pr_err("Mode 13: Failed to get context\n");
-+		ri->rs = InvalidContextHandle;
-+		return;
-+	}
-+
-+	ri->tfm.dwFetchSize = MODE13_HEIGHT * MODE13_WIDTH;
-+
-+	data_phys = get_phys_add_rsvd_mem((u32)ri->rmh, pAstRVAS);
-+	data_phys_rle = get_phys_add_rsvd_mem((u32)ri->rmh1, pAstRVAS);
-+
-+	if (!data_phys || !data_phys_rle) {
-+		ri->rs = InvalidMemoryHandle;
-+		dev_err(pAstRVAS->pdev, "Fetch Text: Invalid Memoryhandle\n");
-+		return;
-+	}
-+	if (!data_phys || (bRLEOn && !data_phys_rle)) {
-+		pr_err("Mode 13: Invalid memory handle\n");
-+		ri->rs = InvalidMemoryHandle;
-+		return;
-+	}
-+
-+	pDescriptorAdd = desc_virt;
-+	pDescriptorAddPhys = (struct Descriptor *)desc_phy;
-+
-+	HW_ENG_DBG("\n===========MODE 13 FETCHED DATA===========\n");
-+
-+	// Enable TFE
-+	dwCtrlRegValue |= 1;
-+	dwCtrlRegValue &= TFCTL_DESCRIPTOR_IN_DDR_MASK;
-+	dest_addr = data_phys;
-+	prepare_tfe_descriptor(pDescriptorAdd, source_addr,
-+			       dest_addr,
-+			       false, //is last entry
-+			       1,     //checksum
-+			       false, //No RLE
-+			       dwFetchWidth,
-+			       1,		//bytes per pixel
-+			       dwFetchWidth, dwFetchHeight,
-+			       PackedToPackedMode, bRLEOverFlow,
-+			       1);
-+
-+	dwCtrlRegValue |= 1 << 1; // enabled IRQ
-+
-+	if (sleep_on_tfe_busy(pAstRVAS, (phys_addr_t)pDescriptorAddPhys, // Descriptor physical Address
-+			      dwCtrlRegValue,           // control register value
-+			      ri->tfm.dwFetchSize,         // bandwidth limitor value
-+			      &ri->tfm.dwFetchRLESize,     // out:: rle size
-+			      &ri->tfm.dwCheckSum) == false) {     // out:: cs size
-+		ri->rs = GenericError;
-+		return;
-+	}
-+
-+	// RLE enabled
-+	if (bRLEOn) {
-+		bRLEOverFlow = true;
-+		dwCtrlRegValue = 1;
-+		dwCtrlRegValue |= (ri->tfm.byRLETripletCode << 24)
-+		| (ri->tfm.byRLERepeatCode << 16);
-+		source_addr = data_phys;
-+		dest_addr = data_phys_rle;
-+		HW_ENG_DBG("RLE is on\n");
-+
-+		prepare_tfe_descriptor(pDescriptorAdd, source_addr,
-+				       dest_addr,
-+				       bNotLastEntry,  //not last entry?
-+				       1,				//checksum
-+				       bRLEOn,		//RLE?
-+				       dwFetchWidth, 1, dwFetchWidth, dwFetchHeight,
-+				       AllBytesMode, bRLEOverFlow, bInterrupt);
-+
-+		dwCtrlRegValue |= 1 << 1; // enabled IRQ
-+
-+		if (sleep_on_tfe_busy(pAstRVAS, (phys_addr_t)pDescriptorAddPhys, // Descriptor physical Address
-+				      dwCtrlRegValue,           // control register value
-+				      ri->tfm.dwFetchSize,          // bandwidth limitor value
-+				      &ri->tfm.dwFetchRLESize,     // out:: rle size
-+				      &ri->tfm.dwCheckSum) == false) {    // out:: cs size
-+			ri->rs = GenericError;
-+			return;
-+		}    //sleeponTFEBusy
-+	}
-+
-+	if (bRLEOn)
-+		ri->tfm.bRLEFailed =
-+			(ri->tfm.dwFetchRLESize < ri->tfm.dwFetchSize) ?
-+			false : true;
-+}
-+
-+void ioctl_fetch_mode_13_data(struct RvasIoctl *ri, struct AstRVAS *pAstRVAS)
-+{
-+	bool bRLEOn = ri->tfm.bEnableRLE;
-+
-+	ri->rs = SuccessStatus;
-+
-+	// first time fetch
-+	on_fetch_mode_13_data(pAstRVAS, ri, bRLEOn);
-+
-+	if (ri->rs != SuccessStatus)
-+		return;
-+
-+	//if RLE fail. need to TFE without RLE to first buffer
-+	if (ri->tfm.bEnableRLE & ri->tfm.bRLEFailed) {
-+		bRLEOn = false;
-+		on_fetch_mode_13_data(pAstRVAS, ri, bRLEOn);
-+	}
-+}
-+
-+
-+
-+// Enable Snoop Interrupts and TSE, Disable FIQ
-+static void enable_tse_interrupt(struct AstRVAS *pAstRVAS)
-+{
-+	u32 reg_val = 0;
-+	void __iomem *reg_addr = pAstRVAS->fg_reg_base
-+		+ TSE_SnoopCommand_Register_Offset;
-+
-+	reg_val = readl(reg_addr);
-+	reg_val |= SNOOP_IRQ_MASK;
-+	reg_val &= ~SNOOP_FIQ_MASK;
-+
-+	HW_ENG_DBG("Enabled TSE Interrupts[%#X]\n", reg_val);
-+	writel(reg_val, reg_addr);
-+	pAstRVAS->tse_tsicr = TSE_INTR_COUNT;
-+	reg_addr = pAstRVAS->fg_reg_base
-+			+ TSE_TileSnoop_Interrupt_Count;
-+	//set max wait time before interrupt
-+	writel(pAstRVAS->tse_tsicr, reg_addr);
-+}
-+
-+//disable tse interrupt
-+static void disable_tse_interrupt(struct AstRVAS *pAstRVAS)
-+{
-+	u32 reg_val = 0;
-+	void __iomem *reg_addr = pAstRVAS->fg_reg_base + TSE_SnoopCommand_Register_Offset;
-+
-+	// Disable Snoop Interrupts and TSE, Disable FIQ
-+	reg_val = readl(reg_addr);
-+	HW_ENG_DBG("disable interrupt\n");
-+	reg_val &= ~(SNOOP_IRQ_MASK | SNOOP_FIQ_MASK);
-+	writel(reg_val, reg_addr);
-+}
-+
-+static void enable_grce_interrupt(struct AstRVAS *pAstRVAS)
-+{
-+	u32 reg_val = 0;
-+	void __iomem *reg_addr = pAstRVAS->grce_reg_base + GRCE_CTL0;
-+
-+	reg_val = readl(reg_addr);
-+	reg_val |= GRC_IRQ_MASK;
-+	writel(reg_val, reg_addr);
-+	HW_ENG_DBG("Enabled GRC Interrupts[%#X]\n", reg_val);
-+}
-+
-+//enable all interrupts
-+void enable_grce_tse_interrupt(struct AstRVAS *pAstRVAS)
-+{
-+	enable_grce_interrupt(pAstRVAS);
-+	enable_tse_interrupt(pAstRVAS);
-+}
-+
-+void disable_grce_tse_interrupt(struct AstRVAS *pAstRVAS)
-+{
-+	u32 reg_val = 0;
-+
-+	HW_ENG_DBG("disable_interrupts- grce_reg_base: %p GRCE_CTL0: %#x\n",
-+		   pAstRVAS->grce_reg_base, GRCE_CTL0);
-+	reg_val = readl(pAstRVAS->grce_reg_base + GRCE_CTL0);
-+	writel(reg_val & (~GRC_IRQ_MASK), pAstRVAS->grce_reg_base + GRCE_CTL0);
-+	disable_tse_interrupt(pAstRVAS);
-+}
-+
-+u32 clear_tse_interrupt(struct AstRVAS *pAstRVAS)
-+{
-+	u32 tse_sts = 0;
-+	u32 tse_tile_status = 0;
-+	u32 tse_snoop_ctrl = 0;
-+	void __iomem *tse_ctrl_addr = pAstRVAS->fg_reg_base + TSE_SnoopCommand_Register_Offset;
-+
-+	HW_ENG_DBG("clear tse inerrupt");
-+	tse_sts = readl(pAstRVAS->fg_reg_base + TSE_Status_Register_Offset);
-+	tse_snoop_ctrl = readl(pAstRVAS->fg_reg_base + TSE_SnoopCommand_Register_Offset);
-+
-+	if (tse_sts & (TSSTS_TC_SCREEN0 | TSSTS_TC_SCREEN1)) {
-+		if (tse_sts & TSSTS_TC_SCREEN0) {
-+			HW_ENG_DBG("Snoop** Update Screen 0\n");
-+			 // clear interrupt and switch to screen 1
-+			tse_snoop_ctrl |= TSCMD_SCREEN_OWNER;
-+			writel(tse_sts, pAstRVAS->fg_reg_base + TSE_Status_Register_Offset);
-+			writel(tse_snoop_ctrl, tse_ctrl_addr);
-+
-+		} else if (tse_sts & TSSTS_TC_SCREEN1) {
-+			HW_ENG_DBG("Snoop** Update Screen 1\n");
-+			tse_snoop_ctrl &= ~TSCMD_SCREEN_OWNER; // snap shutter
-+			// clear status
-+			writel(tse_sts, pAstRVAS->fg_reg_base + TSE_Status_Register_Offset);
-+			 // clear interrupt and switch to screen 1
-+			writel(tse_snoop_ctrl, tse_ctrl_addr);
-+		}
-+		// read clear interrupt
-+		tse_tile_status = readl(pAstRVAS->fg_reg_base
-+				+ TSE_TileCount_Register_Offset);
-+
-+		if (tse_sts & TSSTS_FIFO_OVFL) {
-+			//need to send full frame
-+			dev_err(pAstRVAS->pdev, "TSE snoop fifo overflow\n");
-+			writel(TSSTS_FIFO_OVFL, pAstRVAS->fg_reg_base + TSE_Status_Register_Offset);
-+			memset((void *)pAstRVAS->accrued_sm, 0xff, sizeof(pAstRVAS->accrued_sm));
-+			memset((void *)&pAstRVAS->accrued_sa, 0xff,
-+			       sizeof(pAstRVAS->accrued_sa));
-+		} else {
-+			get_snoop_map_data(pAstRVAS);
-+		}
-+	}
-+	return tse_sts;
-+}
-+
-+// LDMA interrupt
-+bool clear_ldma_interrupt(struct AstRVAS *pAstRVAS)
-+{
-+	u32 ldma_sts = 0;
-+
-+	ldma_sts = readl(pAstRVAS->fg_reg_base + LDMA_Status_Register);
-+
-+	if (ldma_sts & 0x02) {
-+		//HW_ENG_DBG("Got a LDMA interrupt\n");
-+		// write 1 to clear the interrupt
-+		writel(0x2, pAstRVAS->fg_reg_base + LDMA_Status_Register);
-+		return true;
-+	}
-+	return false;
-+}
-+
-+bool clear_tfe_interrupt(struct AstRVAS *pAstRVAS)
-+{
-+	u32 tfe_sts = 0;
-+
-+	tfe_sts = readl(pAstRVAS->fg_reg_base + TFE_Status_Register);
-+
-+	if (tfe_sts & 0x02) {
-+		// HW_ENG_DBG("Debug: TFSTS Interrupt is triggered\n");
-+		writel(0x2, pAstRVAS->fg_reg_base + TFE_Status_Register);
-+		return true;
-+	}
-+	return false;
-+}
-+
-+bool clear_bse_interrupt(struct AstRVAS *pAstRVAS)
-+{
-+	u32 bse_sts = 0;
-+
-+	bse_sts = readl(pAstRVAS->fg_reg_base + BSE_Status_Register);
-+
-+	if (bse_sts & 0x02) {
-+		writel(0x2, pAstRVAS->fg_reg_base + BSE_Status_Register);
-+		return true;
-+	}
-+	return false;
-+}
-+
-+void setup_lmem(struct AstRVAS *pAstRVAS)
-+{
-+	writel(0x0, pAstRVAS->fg_reg_base + LMEM_BASE_REG_3);
-+	writel(0x2000, pAstRVAS->fg_reg_base + LMEM_LIMIT_REG_3);
-+	writel(0x9c89c8, pAstRVAS->fg_reg_base + LMEM11_P0);
-+	writel(0x9c89c8, pAstRVAS->fg_reg_base + LMEM12_P0);
-+	writel(0xf3cf3c, pAstRVAS->fg_reg_base + LMEM11_P1);
-+	writel(0x067201, pAstRVAS->fg_reg_base + LMEM11_P2);
-+	writel(0x00F3CF3C, pAstRVAS->fg_reg_base + LMEM10_P1);
-+	writel(0x00067201, pAstRVAS->fg_reg_base + LMEM10_P2);
-+}
-+
-+bool host_suspended(struct AstRVAS *pAstRVAS)
-+{
-+	u32 GRCE18 = readl(pAstRVAS->grce_reg_base + GRCE_ATTR_VGAIR0_OFFSET);
-+
-+	// VGAER is GRCE19
-+	// VGAER bit[0]:0 - vga disabled (host suspended)
-+	// 1 - vga enabled
-+	HW_ENG_DBG("GRCE18:%#x\n", GRCE18);
-+	if (GRCE18 & 0x100)
-+		return false;
-+	else
-+		return true;
-+}
-+
-diff --git a/drivers/soc/aspeed/rvas/hardware_engines.h b/drivers/soc/aspeed/rvas/hardware_engines.h
-new file mode 100644
-index 000000000..a0564052b
---- /dev/null
-+++ b/drivers/soc/aspeed/rvas/hardware_engines.h
-@@ -0,0 +1,551 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * This file is part of the ASPEED Linux Device Driver for ASPEED Baseboard Management Controller.
-+ * Refer to the README file included with this package for driver version and adapter compatibility.
-+ *
-+ * Copyright (C) 2019-2021 ASPEED Technology Inc. All rights reserved.
-+ */
-+
-+#ifndef __HARDWAREENGINES_H__
-+#define __HARDWAREENGINES_H__
-+
-+#include <linux/semaphore.h>
-+#include <linux/miscdevice.h>
-+#include "video_ioctl.h"
-+
-+#define MAX_NUM_CONTEXT				(8)
-+#define MAX_NUM_MEM_TBL				(24)//each context has 3
-+
-+#define MAX_DESC_SIZE				(PAGE_SIZE) // (0x400)
-+
-+#define ENGINE_TIMEOUT_IN_SECONDS		(3)
-+#define TFE_TIMEOUT_IN_MS			(750)
-+#define DESCRIPTOR_SIZE				(16)
-+#define TILE_SIZE				(32)
-+#define MAX_LMEM_BUCKET_SIZE			(0x80)
-+
-+#define EIGHT_BYTE_ALIGNMENT_MASK		(0xfffffff7)
-+#define SIXTEEN_BYTE_ALIGNMENT_MASK		(0x8)
-+#define TFCTL_DESCRIPTOR_IN_DDR_MASK		(0xffffff7f)
-+#define BSCMD_MASK				(0xffff0f37)
-+
-+#define TEXT_MODE_BUFFER_ALIGNMENT		(16)
-+#define MODE_13_CHAR_WIDTH			(32)
-+#define BSE_MEMORY_ACCESS_MASK			(0x00ffffff)
-+#define MEM_TABLE_SIZE_INCR			(8)
-+#define MEMORY_TABLE_GROW_INCR			(8)
-+
-+#define MAX_TEXT_DATA_SIZE			(8192)
-+
-+
-+// For 2700
-+//#define SCU200_System_Reset_Control_Register (0x200)
-+#define SCU204_System_Reset_Control_Clear_Register (0x204)
-+#define SCU240_Clock_Stop_Control_Register (0x240)
-+#define SCU244_Clock_Stop_Control_Clear_Register (0x244)
-+//#define SCU500_Hardware_Strap1_Register (0x500)
-+//TO DO local monitor on off
-+//single node - vga and dp
-+//dual node- node 0- vga only, node 1- dp only
-+#define SCU000_Silicon_Revision_ID (0x0)
-+#define SCU448_Pin_Ctrl (0x448)
-+//#define SCU0C0_Misc1_Ctrl (0x0C0)
-+//#define SCU0D0_Misc3_Ctrl (0x0D0)
-+ //SCU448 IO
-+#define VGAVS_ENBL_27			(0x70000000)
-+#define VGAHS_ENBL_27			(0x7000000)
-+//SCU0C0
-+#define VGA0_CRT_DISBL			BIT(1)
-+#define VGA1_CRT_DISBL			BIT(2)
-+//SCU0D0 IO
-+#define VGA0_PWR_OFF_VDAC			BIT(2)
-+#define VGA1_PWR_OFF_VDAC			BIT(3)
-+
-+#define SCU_RVAS1_ENGINE_BIT		BIT(10)
-+#define SCU_RVAS0_ENGINE_BIT		BIT(9)
-+#define SCU_RVAS1_STOP_CLOCK_BIT		BIT(28)
-+#define SCU_RVAS0_STOP_CLOCK_BIT		BIT(25)
-+
-+// For 2600
-+//SCU
-+#define SCU000_Protection_Key_Register	(0x000)
-+#define SCU040_Module_Reset_Control_Register_Set_1 (0x040)
-+#define SCU044_Module_Reset_Control_Clear_Register_1 (0x044)
-+#define SCU080_Clock_Stop_Control_Register_Set_1 (0x080)
-+#define SCU084_Clock_Stop_Control_Clear_Register (0x084)
-+#define SCU500_Hardware_Strap1_Register (0x500)
-+#define SCU418_Pin_Ctrl (0x418)
-+#define SCU0C0_Misc1_Ctrl (0x0C0)
-+#define SCU0D0_Misc3_Ctrl (0x0D0)
-+//SCU418
-+#define VGAVS_ENBL			BIT(31)
-+#define VGAHS_ENBL			BIT(30)
-+//SCU0C0
-+#define VGA_CRT_DISBL			BIT(6)
-+//SCU0D0
-+#define PWR_OFF_VDAC			BIT(3)
-+
-+#define SCU_UNLOCK_PWD			(0x1688A8A8)
-+#define SCU_RVAS_ENGINE_BIT		BIT(9)
-+#define SCU_RVAS_STOP_CLOCK_BIT		BIT(25)
-+//
-+//MCR -edac
-+#define MCR_CONF	0x04 /* configuration register */
-+
-+//DP
-+#define DPTX_Configuration_Register			(0x100)
-+#define DPTX_PHY_Configuration_Register		(0x104)
-+//DPTX100
-+#define AUX_RESETN							(24)
-+//DPTX104
-+#define DP_TX_I_MAIN_ON						(8)
-+
-+//TOP REG
-+#define TOP_REG_OFFSET				(0x0)
-+#define TOP_REG_CTL				(TOP_REG_OFFSET + 0x00)
-+#define TOP_REG_STS				(TOP_REG_OFFSET + 0x04)
-+#define LMEM_BASE_REG_3				(TOP_REG_OFFSET + 0x2c)
-+#define LMEM_LIMIT_REG_3			(TOP_REG_OFFSET + 0x3c)
-+#define LMEM11_P0				(TOP_REG_OFFSET + 0x4c)
-+#define LMEM12_P0				(TOP_REG_OFFSET + 0x50)
-+#define LMEM10_P1				(TOP_REG_OFFSET + 0x80)
-+#define LMEM11_P1				(TOP_REG_OFFSET + 0x84)
-+#define LMEM10_P2				(TOP_REG_OFFSET + 0xA0)
-+#define LMEM11_P2				(TOP_REG_OFFSET + 0xA4)
-+
-+#define TSE_SnoopCommand_Register_Offset	(0x0400)
-+#define TSE_TileCount_Register_Offset		(0x0418)
-+#define TSE_Status_Register_Offset		(0x0404)
-+#define TSE_CS0Reg				(0x0408)
-+#define TSE_CS1Reg				(0x040c)
-+#define TSE_RS0Reg				(0x0410)
-+#define TSE_RS1Reg				(0x0414)
-+#define TSE_TileSnoop_Interrupt_Count		(0x0420)
-+#define TSE_FrameBuffer_Offset			(0x041c)
-+#define TSE_UpperLimit_Offset		(0x0424)
-+#define TSE_SnoopMap_Offset			(0x0600)
-+
-+#define TFE_Descriptor_Table_Offset		(0x0108)
-+#define TFE_Descriptor_Control_Resgister	(0x0100)
-+#define TFE_Status_Register			(0x0104)
-+#define TFE_RLE_CheckSum			(0x010C)
-+#define TFE_RLE_Byte_Count			(0x0110)
-+#define TFE_RLE_LIMITOR				(0x0114)
-+
-+#define BSE_REG_BASE				(0x0200)
-+#define BSE_Command_Register			(0x0200)
-+#define BSE_Status_Register			(0x0204)
-+#define BSE_Descriptor_Table_Base_Register	(0x0208)
-+#define BSE_Destination_Buket_Size_Resgister	(0x020c)
-+#define BSE_Bit_Position_Register_0		(0x0210)
-+#define BSE_Bit_Position_Register_1		(0x0214)
-+#define BSE_Bit_Position_Register_2		(0x0218)
-+#define BSE_LMEM_Temp_Buffer_Offset		(0x0000)
-+#define BSE_ENABLE_MULT_BUCKET_SZS		BIT(12)
-+#define BSE_BUCK_SZ_INDEX_POS			(4)
-+#define BSE_MAX_BUCKET_SIZE_REGS		(16)
-+#define BSE_BIT_MASK_Register_Offset		(0x54)
-+
-+#define LDMA_Control_Register			(0x0300)
-+#define LDMA_Status_Register			(0x0304)
-+#define LDMA_Descriptor_Table_Base_Register	(0x0308)
-+#define LDMA_CheckSum_Register			(0x030c)
-+#define LDMA_LMEM_Descriptor_Offset		(0x4000)
-+
-+//Shadow
-+#define GRCE_SIZE				(0x800)
-+#define GRCE_ATTR_OFFSET			(0x0)
-+#define GRCE_ATTR_VGAIR0_OFFSET	(0x18)
-+#define GRCE_SEQ_OFFSET				(0x20)
-+#define GRCE_GCTL_OFFSET			(0x30)
-+#define GRCE_GRCCTL0_OFFSET			(0x58)
-+#define GRCE_GRCSTS_OFFSET			(0x5c)
-+#define GRCE_CRTC_OFFSET			(0x60)
-+#define GRCE_CRTCEXT_OFFSET			(0x80)
-+#define GRCE_XCURCTL_OFFSET			(0xc8)
-+#define GRCE_PAL_OFFSET				(0x400)
-+//size
-+#define GRCELT_RAM_SIZE				(0x400)
-+#define GRCE_XCURCOL_SIZE			(0x40)
-+#define GRCE_XCURCTL_SIZE			(0x40)
-+#define GRCE_CRTC_SIZE				(0x40)
-+#define GRCE_CRTCEXT_SIZE			(0x8)
-+#define GRCE_SEQ_SIZE				(0x8)
-+#define GRCE_GCTL_SIZE				(0x8)
-+#define GRCE_ATTR_SIZE				(0x20)
-+
-+#define GRCELT_RAM				(GRCE_PAL_OFFSET)
-+#define GRCE_XCURCTL				(GRCE_XCURCTL_OFFSET)
-+#define GRCE_CRTC				(GRCE_CRTC_OFFSET)
-+#define GRCE_CRTCEXT				(GRCE_CRTCEXT_OFFSET)
-+#define GRCE_SEQ				(GRCE_SEQ_OFFSET)
-+#define GRCE_GCTL				(GRCE_GCTL_OFFSET)
-+#define GRCE_CTL0				(GRCE_GRCCTL0_OFFSET)
-+#define GRCE_STATUS_REGISTER			(GRCE_GRCSTS_OFFSET)
-+#define GRCE_ATTR				(GRCE_ATTR_OFFSET)
-+#define AST_VIDEO_SCRATCH_34C			(0x8c)
-+#define AST_VIDEO_SCRATCH_350			(0x90)
-+#define AST_VIDEO_SCRATCH_354			(0x94)
-+#define MODE_GET_INFO_DE			(0xA8)
-+
-+//GRC interrupt
-+#define GRC_FIQ_MASK				(0x000003ff)
-+#define GRC_IRQ_MASK				(0x000003ff)
-+#define GRC_INT_STS_MASK			(0x000003ff)
-+#define GRCSTS_XCUR_POS				BIT(9)
-+#define GRCSTS_XCUR_DDR				BIT(8)
-+#define GRCSTS_XCUR_CTL				BIT(7)
-+#define GRCSTS_PLT_RAM				BIT(6)
-+#define GRCSTS_XCRTC				BIT(5)
-+#define GRCSTS_CRTC				BIT(4)
-+#define GRCSTS_GCTL				BIT(3)
-+#define GRCSTS_SEQ				BIT(2)
-+#define GRCSTS_ATTR1				BIT(1)
-+#define GRCSTS_ATTR0				BIT(0)
-+#define SNOOP_RESTART (GRCSTS_XCUR_CTL | GRCSTS_XCRTC | GRCSTS_CRTC | GRCSTS_GCTL)
-+
-+//snoop TSE
-+#define SNOOP_TSE_MASK				(0x00000001)
-+#define SNOOP_IRQ_MASK				(0x00000100)
-+#define SNOOP_FIQ_MASK				(0x00000200)
-+#define	TSCMD_SCREEN_OWNER			BIT(15)
-+#define TSCMD_PITCH_BIT				(16)
-+#define TSCMD_INT_ENBL_BIT			(8)
-+#define TSCMD_CPT_BIT				(6)
-+#define TSCMD_RPT_BIT				(4)
-+#define TSCMD_BPP_BIT				(2)
-+#define TSCMD_VGA_MODE_BIT			(1)
-+#define TSCMD_TSE_ENBL_BIT			(0)
-+#define TSSTS_FIFO_OVFL				BIT(5)
-+#define TSSTS_FONT				BIT(4)
-+#define TSSTS_ATTR				BIT(3)
-+#define TSSTS_ASCII				BIT(2)
-+#define TSSTS_TC_SCREEN1			BIT(1)
-+#define TSSTS_TC_SCREEN0			BIT(0)
-+#define TSSTS_ALL				(0x3f)
-+
-+#define TSE_INTR_COUNT				(0xCB700)	//50MHz clock ~1/60 sec
-+//#define TSE_INTR_COUNT			(0x196E00)	//50MHz clock ~1/30 sec
-+#define TIMER_INTR_COUNT			(0x65000)	// 25MHz clock ~1/60 sec
-+
-+#ifdef CONFIG_MACH_ASPEED_G6
-+//Timer
-+/* Register byte offsets */
-+// AST2600 Timer registers
-+#define TIMER_STATUS_BIT(x)			(1 << ((x) - 1))
-+
-+#define OFFSET_TIMER1         0x00                      /* * timer 1 offset */
-+#define OFFSET_TIMER2         0x10                      /* * timer 2 offset */
-+#define OFFSET_TIMER3         0x20                      /* * timer 3 offset */
-+#define OFFSET_TIMER4         0x40                      /* * timer 4 offset */
-+#define OFFSET_TIMER5         0x50                      /* * timer 5 offset */
-+#define OFFSET_TIMER6         0x60                      /* * timer 6 offset */
-+#define OFFSET_TIMER7         0x70                      /* * timer 7 offset */
-+#define OFFSET_TIMER8         0x80                      /* * timer 8 offset */
-+
-+#define OFF_TIMER_REG_CURR_CNT   0x00
-+#define OFF_TIMER_REG_LOAD_CNT   0x04
-+#define OFF_TIMER_REG_EO0        0x08                    /* Read to clear interrupt */
-+#define OFF_TIMER_REG_EOI        0x0c                    /* Read to clear interrupt */
-+#define OFF_TIMER_REG_STAT       0x10                    /* Timer Interrupt Status */
-+#define OFF_TIMER_REG_CONTROL    0x30							/* Control Register */
-+#define OFF_TIMER_REG_STATUS     0x34							/* Status Register */
-+#define OFF_TIMER_REG_CLEAR_CONTROL    0x3C							/* Control Register */
-+#define RB_OFF_TIMERS_STAT       0xA0                    /* * timers status offset */
-+
-+#define CTRL_TIMER1           (0)
-+#define CTRL_TIMER2           (4)
-+#define CTRL_TIMER3           (8)
-+#define CTRL_TIMER4           (12)
-+#define CTRL_TIMER5           (16)
-+#define CTRL_TIMER6           (20)
-+#define CTRL_TIMER7           (24)
-+#define CTRL_TIMER8           (28)
-+#define BIT_TIMER_ENBL           BIT(0)
-+#define BIT_TIMER_CLK_SEL        BIT(1)
-+#define BIT_INTERRUPT_ENBL       BIT(2)
-+#define BIT_TIMER_STAT           BIT(0)
-+#endif
-+
-+#define SNOOP_MAP_QWORD_COUNT			(64)
-+#define BSE_UPPER_LIMIT				(0x900000) //(0x540000)
-+#define FULL_BUCKETS_COUNT			(16)
-+#define MODE13_HEIGHT				(200)
-+#define MODE13_WIDTH				(320)
-+
-+#define NUM_SNOOP_ROWS				(64)
-+
-+//vga memory information
-+#define DDR_SIZE_CONFIG_BITS				(0x3)
-+#define VGA_MEM_SIZE_CONFIG_BITS			(0x3)
-+#define DDR_BASE_27					(0x400000000)
-+#define DDR_BASE					(0x80000000)
-+
-+//grce
-+#define VGACR0_REG					(0x60)
-+#define VGACR9F_REG					(0x9F)
-+
-+//display out
-+#define VGA_OUT						BIT(0)
-+#define DP_OUT						BIT(1)
-+
-+struct ContextTable {
-+	struct inode *pin;
-+	struct file *pf;
-+	struct SnoopAggregate sa;
-+	u64 aqwSnoopMap[NUM_SNOOP_ROWS];
-+	void *rc;
-+	struct EventMap emEventWaiting;
-+	struct EventMap emEventReceived;
-+	u32 dwEventWaitInMs;
-+	void *desc_virt;
-+	phys_addr_t desc_phy;
-+};
-+
-+struct MemoryMapTable {
-+	struct file *pf;
-+	void *pvVirtualAddr;
-+	dma_addr_t mem_phys;
-+	u32 dwLength;
-+	u8 byDmaAlloc;
-+	u8 byReserved[3];
-+};
-+
-+union EmDwordUnion {
-+	struct EventMap em;
-+	u32 dw;
-+};
-+
-+struct Descriptor {
-+	u32 dw0General;
-+	u32 dw1FetchWidthLine;
-+	u32 dw2SourceAddr;
-+	u32 dw3DestinationAddr;
-+};
-+
-+struct BSEAggregateRegister {
-+	u32 dwBSCR;
-+	u32 dwBSDBS;
-+	u32 adwBSBPS[3];
-+};
-+
-+enum SkipByteMode {
-+	NoByteSkip = 0, SkipOneByte = 1, SkipTwoByte = 2, SkipThreeByte = 3
-+};
-+
-+enum StartBytePosition {
-+	StartFromByte0 = 0,
-+	StartFromByte1 = 1,
-+	StartFromByte2 = 2,
-+	StartFromByte3 = 3
-+};
-+
-+struct VGAMemInfo {
-+	u32 dwVGASize;
-+	u32 dwDRAMSize;
-+	phys_addr_t qwFBPhysStart;
-+};
-+
-+struct VideoDataBufferInfo {
-+	u32 dwSize;
-+	phys_addr_t dwPhys;
-+	phys_addr_t dwVirt;
-+};
-+
-+enum ColorMode {
-+	MODE_EGA = 0x0, //4bpp eg. mode 12/6A
-+	MODE_VGA = 0x1, //mode 13
-+	MODE_BPP15 = 0x2,
-+	MODE_BPP16 = 0x3,
-+	MODE_BPP32 = 0x4,
-+	MODE_TEXT = 0xE,
-+	MODE_CGA = 0xF
-+};
-+
-+struct ModeInfo {
-+	u8 byColorMode;
-+	u8 byRefreshRateIndex;
-+	u8 byModeID;
-+	u8 byScanLines;
-+};
-+
-+struct NewModeInfoHeader {
-+	u8 byReserved;
-+	u8 byDisplayInfo;
-+	u8 byColorDepth;
-+	u8 byMhzPixelClock;
-+};
-+
-+struct DisplayEnd {
-+	u16 HDE;
-+	u16 VDE;
-+};
-+
-+struct Resolution {
-+	u16 wWidth;
-+	u16 wHeight;
-+};
-+
-+struct Video_OsSleepStruct {
-+	wait_queue_head_t queue;
-+	struct timer_list tim;
-+	u8 Timeout;
-+};
-+
-+struct EngineInfo {
-+	struct semaphore sem;
-+	struct Video_OsSleepStruct wait;
-+	u8 finished;
-+};
-+
-+struct VideoMem {
-+	dma_addr_t	phy;
-+	void *pVirt;
-+	u32 size;
-+};
-+
-+struct VideoEngineMem {
-+	struct VideoMem captureBuf0;
-+	struct VideoMem captureBuf1;
-+	struct VideoMem jpegTable;
-+};
-+
-+struct aspeed_rvas_config {
-+	u8 version;
-+	const u32 *dram_table;
-+};
-+
-+struct AstRVAS {
-+	struct miscdevice rvas_dev;
-+	struct aspeed_rvas_config *config;
-+	void *pdev;
-+	int irq_fge;	//FrameGrabber IRQ number
-+	int irq_vga; // VGA IRQ number
-+	int irq_video;
-+	void __iomem *fg_reg_base;
-+	void __iomem *grce_reg_base;
-+	void __iomem *video_reg_base;
-+	struct regmap *scu;
-+	struct regmap *scu_io;
-+	struct reset_control *rvas_reset;
-+	struct reset_control *video_engine_reset;
-+	struct VGAMemInfo FBInfo;
-+	u64 accrued_sm[SNOOP_MAP_QWORD_COUNT];
-+	struct SnoopAggregate accrued_sa;
-+	struct VideoGeometry current_vg;
-+	u32 snoop_stride;
-+	u32 tse_tsicr;
-+	struct EngineInfo tfe_engine;
-+	struct EngineInfo bse_engine;
-+	struct EngineInfo ldma_engine;
-+	struct EngineInfo video_engine;
-+	struct semaphore mem_sem;
-+	struct semaphore context_sem;
-+	struct Video_OsSleepStruct video_wait;
-+	u8 video_intr_occurred;
-+	u8 timer_irq_requested;
-+	u8 display_out;
-+	u8 rvas_index;
-+	struct ContextTable *ppctContextTable[MAX_NUM_CONTEXT];
-+	u32 dwMemoryTableSize;
-+	u32 dwScreenOffset;
-+	struct MemoryMapTable *ppmmtMemoryTable[MAX_NUM_MEM_TBL];
-+	struct completion  video_compression_complete;
-+	struct completion  video_capture_complete;
-+	struct clk *vclk;
-+	struct clk *eclk;
-+	struct clk *rvasclk;
-+	void __iomem *dp_base;
-+	u32 sequence;
-+	struct VideoEngineMem vem;
-+	u8 veClkOn;
-+};
-+
-+//
-+// IOCTL functions
-+//
-+void ioctl_get_video_geometry(struct RvasIoctl *ri, struct AstRVAS *ast_rvas);
-+void ioctl_wait_for_video_event(struct RvasIoctl *ri, struct AstRVAS *ast_rvas);
-+void ioctl_get_grc_register(struct RvasIoctl *ri, struct AstRVAS *ast_rvas);
-+void ioctl_read_snoop_map(struct RvasIoctl *ri, struct AstRVAS *ast_rvas);
-+void ioctl_read_snoop_aggregate(struct RvasIoctl *ri, struct AstRVAS *ast_rvas);
-+void ioctl_set_tse_tsicr(struct RvasIoctl *ri, struct AstRVAS *ast_rvas);
-+void ioctl_get_tse_tsicr(struct RvasIoctl *ri, struct AstRVAS *ast_rvas);
-+void ioctl_reset_video_engine(struct RvasIoctl *ri, struct AstRVAS *ast_rvas);
-+
-+//vidoe fetch functions
-+void ioctl_fetch_video_tiles(struct RvasIoctl *ri, struct AstRVAS *ast_rvas);
-+void ioctl_fetch_video_slices(struct RvasIoctl *ri, struct AstRVAS *ast_rvas);
-+void ioctl_run_length_encode_data(struct RvasIoctl *ri, struct AstRVAS *ast_rvas);
-+void ioctl_fetch_text_data(struct RvasIoctl *ri, struct AstRVAS *ast_rvas);
-+void ioctl_fetch_mode_13_data(struct RvasIoctl *ri, struct AstRVAS *ast_rvas);
-+phys_addr_t get_phy_fb_start_address(struct AstRVAS *ast_rvas);
-+bool video_geometry_change(struct AstRVAS *ast_rvas, u32 dwGRCEStatus);
-+void update_video_geometry(struct AstRVAS *ast_rvas);
-+
-+//interrupts
-+void enable_grce_tse_interrupt(struct AstRVAS *ast_rvas);
-+void disable_grce_tse_interrupt(struct AstRVAS *ast_rvas);
-+u32 clear_tse_interrupt(struct AstRVAS *ast_rvas);
-+bool clear_ldma_interrupt(struct AstRVAS *ast_rvas);
-+bool clear_tfe_interrupt(struct AstRVAS *ast_rvas);
-+bool clear_bse_interrupt(struct AstRVAS *ast_rvas);
-+u32 get_screen_offset(struct AstRVAS *ast_rvas);
-+//
-+void setup_lmem(struct AstRVAS *ast_rvas);
-+//
-+// helper functions
-+//
-+
-+struct BSEAggregateRegister setUp_bse_bucket(u8 *abyBitIndexes, u8 byTotalBucketCount,
-+					     u8 byBSBytesPerPixel, u32 dwFetchWidthPixels,
-+					     u32 dwFetchHeight);
-+void prepare_bse_descriptor(struct Descriptor *pDAddress, phys_addr_t source_addr,
-+			    phys_addr_t dest_addr, bool bNotLastEntry,
-+			    u16 wStride, u8 bytesPerPixel,
-+			    u32 dwFetchWidthPixels, u32 dwFetchHeight,
-+			    bool bInterrupt);
-+
-+void prepare_tfe_descriptor(struct Descriptor *pDAddress, phys_addr_t source_addr,
-+			    phys_addr_t dest_addr, bool bNotLastEntry, u8 bCheckSum,
-+			    bool bEnabledRLE, u16 wStride, u8 bytesPerPixel,
-+			    u32 dwFetchWidthPixels, u32 dwFetchHeight,
-+			    enum SelectedByteMode sbm, bool bRLEOverFLow,
-+			    bool bInterrupt);
-+void prepare_tfe_text_descriptor(struct Descriptor *pDAddress, phys_addr_t source_addr,
-+				 phys_addr_t dest_addr, bool bEnabledRLE, u32 dwFetchWidth,
-+				 u32 dwFetchHeight, enum DataProccessMode dpm,
-+				 bool bRLEOverFLow, bool bInterrupt);
-+void prepare_ldma_descriptor(struct Descriptor *pDAddress, phys_addr_t source_addr,
-+			     phys_addr_t dest_addr, u32 dwLDMASize, u8 byNotLastEntry);
-+
-+u8 get_text_mode_character_per_line(struct AstRVAS *ast_rvas, u16 wScreenWidth);
-+u16 get_text_mode_fetch_lines(struct AstRVAS *ast_rvas, u16 wScreenHeight);
-+void on_fetch_text_data(struct RvasIoctl *ri, bool bRLEOn, struct AstRVAS *ast_rvas);
-+
-+void reset_snoop_engine(struct AstRVAS *ast_rvas);
-+void set_snoop_engine(bool b_geom_chg, struct AstRVAS *ast_rvas);
-+u64 reinterpret_32bpp_snoop_row_as_24bpp(u64 theSnoopRow);
-+
-+void convert_snoop_map(struct AstRVAS *ast_rvas);
-+void update_all_snoop_context(struct AstRVAS *ast_rvas);
-+void get_snoop_map_data(struct AstRVAS *ast_rvas);
-+void get_snoop_aggregate(struct AstRVAS *ast_rvas);
-+
-+void sleep_on_ldma_busy(struct AstRVAS *ast_rvas, phys_addr_t desc_addr_phys);
-+bool sleep_on_tfe_busy(struct AstRVAS *ast_rvas, phys_addr_t desc_addr_phys,
-+		       u32 dwTFEControlR, u32 dwTFERleLimitor, u32 *pdwRLESize,
-+		       u32 *pdwCheckSum);
-+
-+bool sleep_on_tfe_text_busy(struct AstRVAS *ast_rvas, phys_addr_t desc_addr_phys,
-+			    u32 dwTFEControlR, u32 dwTFERleLimitor, u32 *pdwRLESize,
-+			    u32 *pdwCheckSum);
-+
-+bool sleep_on_bse_busy(struct AstRVAS *ast_rvas, phys_addr_t desc_addr_phys,
-+		       struct BSEAggregateRegister aBSEAR, u32 size);
-+
-+void enable_grce_tse_interrupt(struct AstRVAS *ast_rvas);
-+void disable_grce_tse_interrupt(struct AstRVAS *ast_rvas);
-+
-+bool host_suspended(struct AstRVAS *pAstRVAS);
-+#endif // __HARDWAREENGINES_H__
-diff --git a/drivers/soc/aspeed/rvas/video.h b/drivers/soc/aspeed/rvas/video.h
-new file mode 100644
-index 000000000..cafd941e8
---- /dev/null
-+++ b/drivers/soc/aspeed/rvas/video.h
-@@ -0,0 +1,41 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/******************************************************************************
-+ * video.h
-+ *
-+ * This file is part of the ASPEED Linux Device Driver for ASPEED Baseboard Management Controller.
-+ * Refer to the README file included with this package for driver version and adapter compatibility.
-+ *
-+ * Copyright (C) 2019-2021 ASPEED Technology Inc. All rights reserved.
-+ */
-+
-+#ifndef __RVAS_VIDEO_H__
-+#define __RVAS_VIDEO_H__
-+
-+#define RVAS_DRIVER_NAME "rvas"
-+#define Stringify(x) #x
-+
-+//
-+//functions
-+//
-+void ioctl_new_context(struct file *file, struct RvasIoctl *pri, struct AstRVAS *pAstRVAS);
-+void ioctl_delete_context(struct RvasIoctl *pri, struct AstRVAS *pAstRVAS);
-+void ioctl_alloc(struct file *file, struct RvasIoctl *pri, struct AstRVAS *pAstRVAS);
-+void ioctl_free(struct RvasIoctl *pri, struct AstRVAS *pAstRVAS);
-+void ioctl_update_lms(u8 lms_on, struct AstRVAS *ast_rvas);
-+void ioctl_update_lms_2700(u8 lms_on, struct AstRVAS *ast_rvas);
-+u32 ioctl_get_lm_status(struct AstRVAS *ast_rvas);
-+u32 ioctl_get_lm_status_2700(struct AstRVAS *ast_rvas);
-+
-+//void* get_from_rsvd_mem(u32 size, u32 *phys_add, struct AstRVAS *pAstRVAS);
-+void *get_virt_add_rsvd_mem(u32 index, struct AstRVAS *pAstRVAS);
-+dma_addr_t get_phys_add_rsvd_mem(u32 index, struct AstRVAS *pAstRVAS);
-+u32 get_len_rsvd_mem(u32 index, struct AstRVAS *pAstRVAS);
-+
-+//int release_rsvd_mem(u32 size, u32 phys_add);
-+bool virt_is_valid_rsvd_mem(u32 index, u32 size, struct AstRVAS *pAstRVAS);
-+
-+struct ContextTable *get_new_context_table_entry(struct AstRVAS *pAstRVAS);
-+struct ContextTable *get_context_entry(const void *crc, struct AstRVAS *pAstRVAS);
-+bool remove_context_table_entry(const void *crmh, struct AstRVAS *pAstRVAS);
-+
-+#endif // __RVAS_VIDEO_H__
-diff --git a/drivers/soc/aspeed/rvas/video_debug.h b/drivers/soc/aspeed/rvas/video_debug.h
-new file mode 100644
-index 000000000..dbf620207
---- /dev/null
-+++ b/drivers/soc/aspeed/rvas/video_debug.h
-@@ -0,0 +1,35 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (C) 2019-2021  ASPEED Technology Inc.
-+ */
-+
-+#ifndef AST_VIDEO_DEBUG_H_
-+#define AST_VIDEO_DEBUG_H_
-+
-+#include <linux/string.h>
-+#include <linux/types.h>
-+#include <linux/fcntl.h>
-+
-+//#define RVAS_VIDEO_DEBUG
-+//#define VIDEO_ENGINE_DEBUG
-+//#define HARDWARE_ENGINE_DEBUG
-+
-+#ifdef RVAS_VIDEO_DEBUG
-+#define VIDEO_DBG(fmt, args...) ({ dev_printk(KERNEL_INFO, pAstRVAS->pdev, "%s() " fmt, __func__, ## args); })
-+#else
-+#define VIDEO_DBG(fmt, args...) do; while (0)
-+#endif // RVAS_VIDEO_DEBUG
-+
-+#ifdef VIDEO_ENGINE_DEBUG
-+#define VIDEO_ENG_DBG(fmt, args...) ({ dev_printk(KERNEL_INFO, pAstRVAS->pdev, "%s() " fmt, __func__, ## args); })
-+#else
-+#define VIDEO_ENG_DBG(fmt, args...) do; while (0)
-+#endif // RVAS_VIDEO_DEBUG
-+
-+#ifdef HARDWARE_ENGINE_DEBUG
-+#define HW_ENG_DBG(fmt, args...) ({ dev_printk(KERNEL_INFO, pAstRVAS->pdev, "%s() " fmt, __func__, ## args); })
-+#else
-+#define HW_ENG_DBG(fmt, args...) do; while (0)
-+#endif // RVAS_VIDEO_DEBUG
-+
-+#endif // AST_VIDEO_DEBUG_H_
-diff --git a/drivers/soc/aspeed/rvas/video_engine.c b/drivers/soc/aspeed/rvas/video_engine.c
-new file mode 100644
-index 000000000..bd408d48d
---- /dev/null
-+++ b/drivers/soc/aspeed/rvas/video_engine.c
-@@ -0,0 +1,1338 @@
-+// SPDX-License-Identifier: GPL-2.0+
-+/*
-+ * File Name     : video_engines.c
-+ * Description   : AST2600 video  engines
-+ *
-+ * Copyright (C) 2019-2021 ASPEED Technology Inc. All rights reserved.
-+ *
-+ * 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; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+#include <linux/poll.h>
-+#include <linux/slab.h>
-+#include <linux/sched.h>
-+#include <linux/clk.h>
-+#include <linux/reset.h>
-+
-+#include <linux/module.h>
-+#include <linux/fs.h>
-+#include <linux/init.h>
-+#include <linux/platform_device.h>
-+#include <linux/types.h>
-+#include <linux/interrupt.h>
-+#include <linux/mm.h>
-+#include <linux/delay.h>
-+#include <linux/miscdevice.h>
-+#include <linux/hwmon-sysfs.h>
-+#include <linux/regmap.h>
-+#include <linux/mfd/syscon.h>
-+#include <linux/dma-mapping.h>
-+#include <asm/io.h>
-+#include <linux/of.h>
-+#include <linux/of_reserved_mem.h>
-+#include <asm/uaccess.h>
-+
-+#include "video_ioctl.h"
-+#include "video_engine.h"
-+#include "video_debug.h"
-+#include "hardware_engines.h"
-+
-+//
-+//functions
-+//
-+static inline void video_write(struct AstRVAS *pAstRVAS, u32 val, u32 reg);
-+static inline u32 video_read(struct AstRVAS *pAstRVAS, u32 reg);
-+
-+static u32 get_vga_mem_base(struct AstRVAS *pAstRVAS);
-+static int reserve_video_engine_memory(struct AstRVAS *pAstRVAS);
-+static void init_jpeg_table(struct AstRVAS *pAstRVAS);
-+static void video_set_scaling(struct AstRVAS *pAstRVAS);
-+static int video_capture_trigger(struct AstRVAS *pAstRVAS);
-+static void dump_buffer(phys_addr_t qwPhyStreamAddress, u32 size);
-+
-+//
-+// function definitions
-+//
-+/**
-+ * _make_addr - make address fit for ast2700
-+ * @addr: dma address for hardware to work
-+ *
-+ * Return: 32bit format of address
-+ */
-+static inline u32 _make_addr(dma_addr_t addr)
-+{
-+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-+	// In ast2700, it store higt byte[35:32] in low byte[3:0]
-+	return (addr >> 32) | (u32)(addr);
-+#else
-+	return addr;
-+#endif
-+}
-+
-+void ioctl_get_video_engine_config(struct VideoConfig *pVideoConfig, struct AstRVAS *pAstRVAS)
-+{
-+	u32 VR004_SeqCtrl = video_read(pAstRVAS, AST_VIDEO_SEQ_CTRL);
-+	u32 VR060_ComCtrl = video_read(pAstRVAS, AST_VIDEO_COMPRESS_CTRL);
-+
-+	// status
-+	pVideoConfig->rs = SuccessStatus;
-+
-+	pVideoConfig->engine = 0;	// engine = 1 is Video Management
-+	pVideoConfig->capture_format = 0;
-+	pVideoConfig->compression_mode = 0;
-+
-+	pVideoConfig->compression_format = (VR004_SeqCtrl >> 13) & 0x1;
-+	pVideoConfig->YUV420_mode = (VR004_SeqCtrl >> 10) & 0x3;
-+	pVideoConfig->AutoMode = (VR004_SeqCtrl >> 5) & 0x1;
-+
-+	pVideoConfig->rc4_enable = (VR060_ComCtrl >> 5) & 0x1;
-+	pVideoConfig->Visual_Lossless = (VR060_ComCtrl >> 16) & 0x1;
-+	pVideoConfig->Y_JPEGTableSelector = VIDEO_GET_DCT_LUM(VR060_ComCtrl);
-+	pVideoConfig->AdvanceTableSelector = (VR060_ComCtrl >> 27) & 0xf;
-+}
-+
-+void ioctl_set_video_engine_config(struct VideoConfig  *pVideoConfig, struct AstRVAS *pAstRVAS)
-+{
-+	int i, base = 0;
-+	u32 ctrl = 0;	//for VR004, VR204
-+	u32 compress_ctrl = 0x00080000;
-+	u32 *tlb_table = pAstRVAS->vem.jpegTable.pVirt;
-+
-+	// status
-+	pVideoConfig->rs = SuccessStatus;
-+
-+	VIDEO_ENG_DBG("\n");
-+
-+	ctrl = video_read(pAstRVAS, AST_VIDEO_SEQ_CTRL);
-+
-+	video_write(pAstRVAS, video_read(pAstRVAS, AST_VIDEO_PASS_CTRL) &
-+				~(G6_VIDEO_FRAME_CT_MASK | G6_VIDEO_MULTI_JPEG_MODE | G6_VIDEO_MULTI_JPEG_FLAG_MODE), AST_VIDEO_PASS_CTRL);
-+
-+	ctrl &= ~VIDEO_AUTO_COMPRESS;
-+	ctrl |= G5_VIDEO_COMPRESS_JPEG_MODE;
-+	ctrl &= ~VIDEO_COMPRESS_FORMAT_MASK; //~(3<<10) bit 4 is set to 0
-+
-+	if (pVideoConfig->YUV420_mode)
-+		ctrl |= VIDEO_COMPRESS_FORMAT(YUV420);
-+
-+	if (pVideoConfig->rc4_enable)
-+		compress_ctrl |= VIDEO_ENCRYP_ENABLE;
-+
-+	switch (pVideoConfig->compression_mode) {
-+	case 0:	//DCT only
-+			compress_ctrl |= VIDEO_DCT_ONLY_ENCODE;
-+			break;
-+	case 1:	//DCT VQ mix 2-color
-+			compress_ctrl &= ~(VIDEO_4COLOR_VQ_ENCODE | VIDEO_DCT_ONLY_ENCODE);
-+			break;
-+	case 2:	//DCT VQ mix 4-color
-+			compress_ctrl |= VIDEO_4COLOR_VQ_ENCODE;
-+			break;
-+	default:
-+			dev_err(pAstRVAS->pdev, "unknown compression mode:%d\n", pVideoConfig->compression_mode);
-+			break;
-+	}
-+
-+	if (pVideoConfig->Visual_Lossless) {
-+		compress_ctrl |= VIDEO_HQ_ENABLE;
-+		compress_ctrl |= VIDEO_HQ_DCT_LUM(pVideoConfig->AdvanceTableSelector);
-+		compress_ctrl |= VIDEO_HQ_DCT_CHROM((pVideoConfig->AdvanceTableSelector + 16));
-+	} else {
-+		compress_ctrl &= ~VIDEO_HQ_ENABLE;
-+	}
-+
-+	video_write(pAstRVAS, ctrl, AST_VIDEO_SEQ_CTRL);
-+	// we are using chrominance quantization table instead of luminance quantization table
-+	video_write(pAstRVAS, compress_ctrl | VIDEO_DCT_LUM(pVideoConfig->Y_JPEGTableSelector) | VIDEO_DCT_CHROM(pVideoConfig->Y_JPEGTableSelector + 16), AST_VIDEO_COMPRESS_CTRL);
-+	VIDEO_ENG_DBG("VR04: %#X\n", video_read(pAstRVAS, AST_VIDEO_SEQ_CTRL));
-+	VIDEO_ENG_DBG("VR60: %#X\n", video_read(pAstRVAS, AST_VIDEO_COMPRESS_CTRL));
-+
-+	// chose a table for JPEG or multi-JPEG
-+	if (pVideoConfig->compression_format >= 1) {
-+		VIDEO_ENG_DBG("Choose a JPEG Table\n");
-+		for (i = 0; i < 12; i++) {
-+			base = (1024 * i);
-+			//base = (256 * i);
-+			if (pVideoConfig->YUV420_mode)	//yuv420
-+				tlb_table[base + 46] = 0x00220103; //for YUV420 mode
-+			else
-+				tlb_table[base + 46] = 0x00110103; //for YUV444 mode)
-+		}
-+	}
-+
-+	video_set_scaling(pAstRVAS);
-+}
-+
-+//
-+void ioctl_get_video_engine_data_2700(struct MultiJpegConfig *pArrayMJConfig, struct AstRVAS *pAstRVAS, dma_addr_t dwPhyStreamAddress)
-+{
-+	u32 yuv_shift;
-+	u32 scan_lines;
-+	int timeout = 0;
-+	u32 x0;
-+	u32 y0;
-+	phys_addr_t start_addr;
-+	u32 frame_count = 0;
-+	u32 old_src_addr, new_src_addr;
-+	u32 offset;
-+
-+	pArrayMJConfig->rs = SuccessStatus;
-+
-+	VIDEO_ENG_DBG("\n");
-+	VIDEO_ENG_DBG("before Stream buffer: %#llx\n", dwPhyStreamAddress);
-+	//dump_buffer(dwPhyStreamAddress,100);
-+
-+	video_write(pAstRVAS, _make_addr(dwPhyStreamAddress), AST_VIDEO_STREAM_BUFF);
-+
-+	if (host_suspended(pAstRVAS)) {
-+		pArrayMJConfig->rs = HostSuspended;
-+		VIDEO_ENG_DBG("HostSuspended Timeout\n");
-+		return;
-+	}
-+
-+	VIDEO_ENG_DBG("irq status: %#x\n", video_read(pAstRVAS, AST_VIDEO_INT_STS));
-+
-+#ifdef AUTO_COMPRESS
-+	if (video_cc_auto_trigger(pAstRVAS) == 0) {
-+		VIDEO_ENG_DBG("auto Ccc Timeout\n");
-+		pArrayMJConfig->multi_jpeg_frames = 0;
-+		pArrayMJConfig->rs = CompressionTimedOut;
-+		return;
-+	}
-+#else
-+	if (video_capture_trigger(pAstRVAS) == 0) {
-+		dev_err(pAstRVAS->pdev, " capture timeout sts %x\n", video_read(pAstRVAS, AST_VIDEO_INT_STS));
-+		pArrayMJConfig->multi_jpeg_frames = 0;
-+		pArrayMJConfig->rs = CaptureTimedOut;
-+		return;
-+	}
-+	// clear all the interrupt since there is a bug in HW engine ast2700
-+	// only capture interrupt is enable, but compression intterupt is generated
-+	video_write(pAstRVAS, VIDEO_CAPTURE_COMPLETE | VIDEO_COMPRESS_COMPLETE, AST_VIDEO_INT_STS);
-+#endif
-+
-+	// start compression setup
-+	video_write(pAstRVAS, VIDEO_COMPRESS_COMPLETE, AST_VIDEO_INT_EN);
-+	init_completion(&pAstRVAS->video_compression_complete);
-+
-+	scan_lines = video_read(pAstRVAS, AST_VIDEO_SOURCE_SCAN_LINE);
-+	frame_count = video_read(pAstRVAS, AST_VIDEO_COMPRESS_FRAME_COUNT_RB);
-+
-+	// VR07C odd , get source from 0x4C
-+	// VR07C even, get source from 0x44
-+	old_src_addr = (frame_count & 0x01) ? AST_VIDEO_SOURCE_BUFF0 : AST_VIDEO_SOURCE_BUFF1;
-+	new_src_addr = (frame_count & 0x01) ? AST_VIDEO_SOURCE_BUFF1 : AST_VIDEO_SOURCE_BUFF0;
-+
-+	start_addr = video_read(pAstRVAS, old_src_addr);
-+	// make sure BCD is disable
-+	video_write(pAstRVAS, video_read(pAstRVAS, AST_VIDEO_BCD_CTRL) & ~VIDEO_BCD_CHG_EN, AST_VIDEO_BCD_CTRL);
-+
-+	if (video_read(pAstRVAS, AST_VIDEO_SEQ_CTRL) & VIDEO_COMPRESS_FORMAT(YUV420)) {
-+		// YUV 420
-+		VIDEO_ENG_DBG("Debug: YUV420\n");
-+		yuv_shift = 4;
-+	} else {
-+		VIDEO_ENG_DBG("Debug: YUV444\n");
-+		yuv_shift = 3;
-+	}
-+
-+	//update compress window
-+	video_write(pAstRVAS,
-+		    pArrayMJConfig->frame[0].wWidthPixels << 16 |
-+		    pArrayMJConfig->frame[0].wHeightPixels, AST_VIDEO_COMPRESS_WIN);
-+
-+	x0 = pArrayMJConfig->frame[0].wXPixels;
-+	y0 = pArrayMJConfig->frame[0].wYPixels;
-+
-+	offset = (scan_lines * y0) + ((256 * x0) >> yuv_shift);
-+
-+	video_write(pAstRVAS, start_addr + offset, new_src_addr);
-+	VIDEO_ENG_DBG("write to %#x, with address: %#x", start_addr + offset, new_src_addr);
-+	// trigger compression
-+	VIDEO_ENG_DBG("trigger compression\n");
-+	video_write(pAstRVAS, video_read(pAstRVAS, AST_VIDEO_SEQ_CTRL) |
-+		    VIDEO_COMPRESS_TRIGGER, AST_VIDEO_SEQ_CTRL);
-+
-+	timeout = wait_for_completion_interruptible_timeout(&pAstRVAS->video_compression_complete, HZ);
-+
-+	if (timeout == 0) {
-+		dev_err(pAstRVAS->pdev, " compression timeout sts %x\n", video_read(pAstRVAS, AST_VIDEO_INT_STS));
-+		pArrayMJConfig->multi_jpeg_frames = 0;
-+		pArrayMJConfig->rs = CompressionTimedOut;
-+	}
-+	pArrayMJConfig->multi_jpeg_frames = 1;
-+	pArrayMJConfig->frame[0].dwSizeInBytes = video_read(pAstRVAS, AST_VIDEO_JPEG_SIZE);
-+
-+	VIDEO_ENG_DBG("compressed size: %d\n", pArrayMJConfig->frame[0].dwSizeInBytes);
-+
-+	//clear
-+	video_write(pAstRVAS, (video_read(pAstRVAS, AST_VIDEO_SEQ_CTRL) &
-+			~(G5_VIDEO_COMPRESS_JPEG_MODE | VIDEO_CAPTURE_MULTI_FRAME | VIDEO_COMPRESS_TRIGGER))
-+			, AST_VIDEO_SEQ_CTRL);
-+
-+	pAstRVAS->sequence++;
-+	if (pAstRVAS->sequence & 0x01) {
-+		video_write(pAstRVAS, _make_addr(pAstRVAS->vem.captureBuf1.phy), AST_VIDEO_SOURCE_BUFF0);//44h
-+		video_write(pAstRVAS, _make_addr(pAstRVAS->vem.captureBuf0.phy), AST_VIDEO_SOURCE_BUFF1);//4Ch
-+	} else {
-+		video_write(pAstRVAS, _make_addr(pAstRVAS->vem.captureBuf0.phy), AST_VIDEO_SOURCE_BUFF0);//44h
-+		video_write(pAstRVAS, _make_addr(pAstRVAS->vem.captureBuf1.phy), AST_VIDEO_SOURCE_BUFF1);//4Ch
-+	}
-+	VIDEO_ENG_DBG("[%#x]: %#x\n", AST_VIDEO_SOURCE_BUFF0, video_read(pAstRVAS, AST_VIDEO_SOURCE_BUFF0));
-+	VIDEO_ENG_DBG("[%#x]: %#x\n", AST_VIDEO_SOURCE_BUFF1, video_read(pAstRVAS, AST_VIDEO_SOURCE_BUFF1));
-+
-+	//TODO: kernel dump here...
-+	//dump_buffer(dwPhyStreamAddress,100);
-+}
-+
-+void ioctl_get_video_engine_data(struct MultiJpegConfig *pArrayMJConfig, struct AstRVAS *pAstRVAS, phys_addr_t dwPhyStreamAddress)
-+{
-+	u32 yuv_shift;
-+	u32 yuv_msk;
-+	u32 scan_lines;
-+	int timeout = 0;
-+	u32 x0;
-+	u32 y0;
-+	int i = 0;
-+	u32 dw_w_h;
-+	phys_addr_t start_addr;
-+	u32 multi_jpeg_data = 0;
-+	u32 VR044;
-+	u32 nextFrameOffset = 0;
-+
-+	pArrayMJConfig->rs = SuccessStatus;
-+
-+	VIDEO_ENG_DBG("\n");
-+	VIDEO_ENG_DBG("before Stream buffer:\n");
-+	//dump_buffer(dwPhyStreamAddress,100);
-+
-+	video_write(pAstRVAS, dwPhyStreamAddress, AST_VIDEO_STREAM_BUFF);
-+
-+	if (host_suspended(pAstRVAS)) {
-+		pArrayMJConfig->rs = HostSuspended;
-+		VIDEO_ENG_DBG("HostSuspended Timeout\n");
-+		return;
-+	}
-+
-+	if (video_capture_trigger(pAstRVAS) == 0) {
-+		pArrayMJConfig->rs = CaptureTimedOut;
-+		VIDEO_ENG_DBG("Capture Timeout\n");
-+		return;
-+	}
-+	//dump_buffer(dwPhyStreamAddress,100);
-+		// start compression setup
-+	video_write(pAstRVAS, VIDEO_COMPRESS_COMPLETE, AST_VIDEO_INT_EN);
-+	init_completion(&pAstRVAS->video_compression_complete);
-+	VIDEO_ENG_DBG("capture complete buffer:\n");
-+
-+	//dump_buffer(vem.captureBuf0.phy,100);
-+	VR044 = video_read(pAstRVAS, AST_VIDEO_SOURCE_BUFF0);
-+
-+	scan_lines = video_read(pAstRVAS, AST_VIDEO_SOURCE_SCAN_LINE);
-+	VIDEO_ENG_DBG("scan_lines: %#x\n", scan_lines);
-+
-+	if (video_read(pAstRVAS, AST_VIDEO_SEQ_CTRL) & VIDEO_COMPRESS_FORMAT(YUV420)) {
-+		// YUV 420
-+		VIDEO_ENG_DBG("Debug: YUV420\n");
-+		yuv_shift = 4;
-+		yuv_msk = 0xf;
-+	} else {
-+		// YUV 444
-+		VIDEO_ENG_DBG("Debug: YUV444\n");
-+		yuv_shift = 3;
-+		yuv_msk = 0x7;
-+	}
-+
-+	video_write(pAstRVAS, video_read(pAstRVAS, AST_VIDEO_PASS_CTRL) | G6_VIDEO_MULTI_JPEG_FLAG_MODE |
-+			(G6_VIDEO_JPEG__COUNT(pArrayMJConfig->multi_jpeg_frames - 1) | G6_VIDEO_MULTI_JPEG_MODE), AST_VIDEO_PASS_CTRL);
-+
-+	video_write(pAstRVAS, video_read(pAstRVAS, AST_VIDEO_BCD_CTRL) & ~VIDEO_BCD_CHG_EN, AST_VIDEO_BCD_CTRL);
-+
-+	video_write(pAstRVAS, video_read(pAstRVAS, AST_VIDEO_CTRL) | VIDEO_CTRL_ADDRESS_MAP_MULTI_JPEG, AST_VIDEO_CTRL);
-+
-+	for (i = 0; i < pArrayMJConfig->multi_jpeg_frames; i++) {
-+		VIDEO_ENG_DBG("Debug: Before: [%d]: x: %#x y: %#x w: %#x h: %#x\n", i,
-+			      pArrayMJConfig->frame[i].wXPixels,
-+			      pArrayMJConfig->frame[i].wYPixels,
-+			      pArrayMJConfig->frame[i].wWidthPixels,
-+			      pArrayMJConfig->frame[i].wHeightPixels);
-+		x0 = pArrayMJConfig->frame[i].wXPixels;
-+		y0 = pArrayMJConfig->frame[i].wYPixels;
-+		dw_w_h = SET_FRAME_W_H(pArrayMJConfig->frame[i].wWidthPixels, pArrayMJConfig->frame[i].wHeightPixels);
-+
-+		start_addr = VR044 + (scan_lines * y0) + ((256 * x0) / (1 << yuv_shift));
-+
-+		VIDEO_ENG_DBG("VR%x dw_w_h: %#x, VR%x : addr : %#x, x0 %d, y0 %d\n",
-+			      AST_VIDEO_MULTI_JPEG_SRAM + (8 * i), dw_w_h,
-+			      AST_VIDEO_MULTI_JPEG_SRAM + (8 * i) + 4, start_addr, x0, y0);
-+		video_write(pAstRVAS, dw_w_h, AST_VIDEO_MULTI_JPEG_SRAM + (8 * i));
-+		video_write(pAstRVAS, start_addr, AST_VIDEO_MULTI_JPEG_SRAM + (8 * i) + 4);
-+	}
-+
-+	video_write(pAstRVAS, video_read(pAstRVAS, AST_VIDEO_SEQ_CTRL) & ~(VIDEO_CAPTURE_TRIGGER | VIDEO_COMPRESS_FORCE_IDLE | VIDEO_COMPRESS_TRIGGER), AST_VIDEO_SEQ_CTRL);
-+
-+	//set mode for multi-jpeg mode VR004[5:3]
-+	video_write(pAstRVAS, (video_read(pAstRVAS, AST_VIDEO_SEQ_CTRL) & ~VIDEO_AUTO_COMPRESS)
-+				| VIDEO_CAPTURE_MULTI_FRAME | G5_VIDEO_COMPRESS_JPEG_MODE, AST_VIDEO_SEQ_CTRL);
-+
-+	//If CPU is too fast, pleas read back and trigger
-+	video_write(pAstRVAS, video_read(pAstRVAS, AST_VIDEO_SEQ_CTRL) | VIDEO_COMPRESS_TRIGGER, AST_VIDEO_SEQ_CTRL);
-+	VIDEO_ENG_DBG("wait_for_completion_interruptible_timeout...\n");
-+
-+	timeout = wait_for_completion_interruptible_timeout(&pAstRVAS->video_compression_complete, HZ / 2);
-+
-+	if (timeout == 0) {
-+		dev_err(pAstRVAS->pdev, "multi compression timeout sts %x\n", video_read(pAstRVAS, AST_VIDEO_INT_STS));
-+		pArrayMJConfig->multi_jpeg_frames = 0;
-+		pArrayMJConfig->rs = CompressionTimedOut;
-+	} else {
-+		VIDEO_ENG_DBG("400 %x , 404 %x\n", video_read(pAstRVAS, AST_VIDEO_MULTI_JPEG_SRAM), video_read(pAstRVAS, AST_VIDEO_MULTI_JPEG_SRAM + 4));
-+		VIDEO_ENG_DBG("408 %x , 40c %x\n", video_read(pAstRVAS, AST_VIDEO_MULTI_JPEG_SRAM + 8), video_read(pAstRVAS, AST_VIDEO_MULTI_JPEG_SRAM + 0xC));
-+		VIDEO_ENG_DBG("done reading 408\n");
-+
-+		for (i = 0; i < pArrayMJConfig->multi_jpeg_frames; i++) {
-+			pArrayMJConfig->frame[i].dwOffsetInBytes = nextFrameOffset;
-+
-+			multi_jpeg_data = video_read(pAstRVAS, AST_VIDEO_MULTI_JPEG_SRAM + (8 * i) + 4);
-+			if (multi_jpeg_data & BIT(7)) {
-+				pArrayMJConfig->frame[i].dwSizeInBytes = video_read(pAstRVAS, AST_VIDEO_MULTI_JPEG_SRAM + (8 * i)) & 0xffffff;
-+				nextFrameOffset = (multi_jpeg_data & ~BIT(7)) >> 1;
-+			} else {
-+				pArrayMJConfig->frame[i].dwSizeInBytes = 0;
-+				nextFrameOffset = 0;
-+			}
-+			VIDEO_ENG_DBG("[%d] size %d, dwOffsetInBytes %x\n", i, pArrayMJConfig->frame[i].dwSizeInBytes, pArrayMJConfig->frame[i].dwOffsetInBytes);
-+		} //for
-+	}
-+
-+	video_write(pAstRVAS, (video_read(pAstRVAS, AST_VIDEO_SEQ_CTRL) & ~(G5_VIDEO_COMPRESS_JPEG_MODE | VIDEO_CAPTURE_MULTI_FRAME))
-+			| VIDEO_AUTO_COMPRESS, AST_VIDEO_SEQ_CTRL);
-+	video_write(pAstRVAS, video_read(pAstRVAS, AST_VIDEO_PASS_CTRL) &
-+			~(G6_VIDEO_FRAME_CT_MASK | G6_VIDEO_MULTI_JPEG_MODE), AST_VIDEO_PASS_CTRL);
-+
-+	//VIDEO_ENG_DBG("after Stream buffer:\n");
-+	//dump_buffer(dwPhyStreamAddress,100);
-+}
-+
-+irqreturn_t ast_video_isr(int this_irq, void *dev_id)
-+{
-+	u32 status;
-+	u32 enabled_irq;
-+	struct AstRVAS *pAstRVAS = dev_id;
-+
-+	status = video_read(pAstRVAS, AST_VIDEO_INT_STS);
-+	enabled_irq = video_read(pAstRVAS, AST_VIDEO_INT_EN);
-+
-+	VIDEO_ENG_DBG("sts: %#x enabled: %#x\n", status, enabled_irq);
-+
-+	status &= enabled_irq;
-+	if (status & VIDEO_COMPRESS_COMPLETE) {
-+		video_write(pAstRVAS, VIDEO_COMPRESS_COMPLETE, AST_VIDEO_INT_STS);
-+		complete(&pAstRVAS->video_compression_complete);
-+	}
-+	if (status & VIDEO_CAPTURE_COMPLETE) {
-+		video_write(pAstRVAS, VIDEO_CAPTURE_COMPLETE, AST_VIDEO_INT_STS);
-+		VIDEO_ENG_DBG("capture complete\n");
-+		complete(&pAstRVAS->video_capture_complete);
-+	}
-+
-+	return IRQ_HANDLED;
-+}
-+
-+void enable_video_interrupt(struct AstRVAS *pAstRVAS)
-+{
-+	u32 intCtrReg = video_read(pAstRVAS, AST_VIDEO_INT_EN);
-+
-+	intCtrReg = (VIDEO_COMPRESS_COMPLETE | VIDEO_CAPTURE_COMPLETE);
-+	video_write(pAstRVAS, intCtrReg, AST_VIDEO_INT_EN);
-+}
-+
-+void disable_video_interrupt(struct AstRVAS *pAstRVAS)
-+{
-+	video_write(pAstRVAS, 0, AST_VIDEO_INT_EN);
-+	video_write(pAstRVAS, 0xffffffff, AST_VIDEO_INT_STS);
-+}
-+
-+void video_engine_rc4Reset(struct AstRVAS *pAstRVAS)
-+{
-+	//rc4 init reset ..
-+	video_write(pAstRVAS, video_read(pAstRVAS, AST_VIDEO_CTRL) | VIDEO_CTRL_RC4_RST, AST_VIDEO_CTRL);
-+	video_write(pAstRVAS, video_read(pAstRVAS, AST_VIDEO_CTRL) & ~VIDEO_CTRL_RC4_RST, AST_VIDEO_CTRL);
-+}
-+
-+// setup functions
-+int video_engine_reserveMem(struct AstRVAS *pAstRVAS)
-+{
-+	int result = 0;
-+
-+	// reserve mem
-+	result = reserve_video_engine_memory(pAstRVAS);
-+	if (result < 0) {
-+		dev_err(pAstRVAS->pdev, "Error Reserving Video Engine Memory\n");
-+		return result;
-+	}
-+	return 0;
-+}
-+
-+int free_video_engine_memory(struct AstRVAS *pAstRVAS)
-+{
-+	int size = pAstRVAS->vem.captureBuf0.size + pAstRVAS->vem.captureBuf1.size + pAstRVAS->vem.jpegTable.size;
-+
-+	if (size && pAstRVAS->vem.captureBuf0.pVirt) {
-+		dma_free_coherent(pAstRVAS->pdev, size,
-+				  pAstRVAS->vem.captureBuf0.pVirt,
-+				  pAstRVAS->vem.captureBuf0.phy);
-+	} else {
-+		return -1;
-+	}
-+	VIDEO_ENG_DBG("After dma_free_coherent\n");
-+
-+	return 0;
-+}
-+
-+// this function needs to be called when graphic mode change
-+void video_set_Window(struct AstRVAS *pAstRVAS)
-+{
-+	u32 scan_line;
-+	u32 screenHeightAligned = ((pAstRVAS->current_vg.wScreenHeight + 0x1f) & (~0x1f));
-+
-+	VIDEO_ENG_DBG("\n");
-+
-+	//set direct mode
-+	if (pAstRVAS->config->version == 7) {
-+		video_write(pAstRVAS, video_read(pAstRVAS, AST_VIDEO_PASS_CTRL) & ~(VIDEO_AUTO_FETCH | VIDEO_DIRECT_FETCH), AST_VIDEO_PASS_CTRL);
-+		video_write(pAstRVAS, video_read(pAstRVAS, AST_VIDEO_PASS_CTRL) | VIDEO_AUTO_FETCH | VIDEO_DIRECT_FETCH, AST_VIDEO_PASS_CTRL);
-+		video_write(pAstRVAS, _make_addr(get_vga_mem_base(pAstRVAS)), AST_VIDEO_DIRECT_BASE);
-+		video_write(pAstRVAS, VIDEO_FETCH_TIMING(0) | VIDEO_FETCH_LINE_OFFSET(pAstRVAS->current_vg.wStride * 4), AST_VIDEO_DIRECT_CTRL);
-+	}
-+	//compression x,y
-+	video_write(pAstRVAS, VIDEO_COMPRESS_H(pAstRVAS->current_vg.wStride) | VIDEO_COMPRESS_V(screenHeightAligned), AST_VIDEO_COMPRESS_WIN);
-+	VIDEO_ENG_DBG("reg offset[%#x]: %#x\n", AST_VIDEO_COMPRESS_WIN, video_read(pAstRVAS, AST_VIDEO_COMPRESS_WIN));
-+
-+	if (pAstRVAS->current_vg.wStride == 1680)
-+		video_write(pAstRVAS, VIDEO_CAPTURE_H(1728) | VIDEO_CAPTURE_V(screenHeightAligned), AST_VIDEO_CAPTURE_WIN);
-+	else
-+		video_write(pAstRVAS, VIDEO_CAPTURE_H(pAstRVAS->current_vg.wStride) | VIDEO_CAPTURE_V(screenHeightAligned), AST_VIDEO_CAPTURE_WIN);
-+
-+	VIDEO_ENG_DBG("reg offset[%#x]: %#x\n", AST_VIDEO_CAPTURE_WIN, video_read(pAstRVAS, AST_VIDEO_CAPTURE_WIN));
-+
-+	// set scan_line VR048
-+	if ((pAstRVAS->current_vg.wStride % 8) == 0) {
-+		video_write(pAstRVAS, pAstRVAS->current_vg.wStride * 4, AST_VIDEO_SOURCE_SCAN_LINE);
-+	} else {
-+		scan_line = pAstRVAS->current_vg.wStride;
-+		scan_line = scan_line + 16 - (scan_line % 16);
-+		scan_line = scan_line * 4;
-+		video_write(pAstRVAS, scan_line, AST_VIDEO_SOURCE_SCAN_LINE);
-+	}
-+}
-+
-+void set_direct_mode(struct AstRVAS *pAstRVAS)
-+{
-+	int Direct_Mode = 0;
-+	u32 ColorDepthIndex;
-+	u32 VGA_Scratch_Register_350, VGA_Scratch_Register_354, VGA_Scratch_Register_34C, Color_Depth;
-+
-+	VIDEO_ENG_DBG("\n");
-+	video_write(pAstRVAS, video_read(pAstRVAS, AST_VIDEO_PASS_CTRL) & ~(VIDEO_AUTO_FETCH | VIDEO_DIRECT_FETCH), AST_VIDEO_PASS_CTRL);
-+
-+	VGA_Scratch_Register_350 = video_read(pAstRVAS, AST_VIDEO_E_SCRATCH_350);
-+	VGA_Scratch_Register_34C = video_read(pAstRVAS, AST_VIDEO_E_SCRATCH_34C);
-+	VGA_Scratch_Register_354 = video_read(pAstRVAS, AST_VIDEO_E_SCRATCH_354);
-+
-+	if (((VGA_Scratch_Register_350 & 0xff00) >> 8) == 0xA8) {
-+		Color_Depth = ((VGA_Scratch_Register_350 & 0xff0000) >> 16);
-+
-+		if (Color_Depth < 15)
-+			Direct_Mode = 0;
-+		else
-+			Direct_Mode = 1;
-+
-+	} else { //Original mode information
-+		ColorDepthIndex = (VGA_Scratch_Register_34C >> 4) & 0x0F;
-+
-+		if (ColorDepthIndex == 0xe || ColorDepthIndex == 0xf) {
-+			Direct_Mode = 0;
-+		} else {
-+			if (ColorDepthIndex > 2)
-+				Direct_Mode = 1;
-+			else
-+				Direct_Mode = 0;
-+		}
-+	}
-+
-+	if (Direct_Mode) {
-+		VIDEO_ENG_DBG("Direct Mode\n");
-+		video_write(pAstRVAS, video_read(pAstRVAS, AST_VIDEO_PASS_CTRL) | VIDEO_AUTO_FETCH | VIDEO_DIRECT_FETCH, AST_VIDEO_PASS_CTRL);
-+		video_write(pAstRVAS, _make_addr(get_vga_mem_base(pAstRVAS)), AST_VIDEO_DIRECT_BASE);
-+		video_write(pAstRVAS, VIDEO_FETCH_TIMING(0) | VIDEO_FETCH_LINE_OFFSET(pAstRVAS->current_vg.wStride * 4), AST_VIDEO_DIRECT_CTRL);
-+	} else {
-+		VIDEO_ENG_DBG("Sync None Direct Mode\n");
-+		video_write(pAstRVAS, video_read(pAstRVAS, AST_VIDEO_PASS_CTRL) & ~(VIDEO_AUTO_FETCH | VIDEO_DIRECT_FETCH), AST_VIDEO_PASS_CTRL);
-+	}
-+}
-+
-+// return timeout 0 - timeout; non 0 is successful
-+static int video_capture_trigger(struct AstRVAS *pAstRVAS)
-+{
-+	int timeout = 0;
-+
-+	VIDEO_ENG_DBG("\n");
-+
-+	// only enable capture interrupt
-+	video_write(pAstRVAS, VIDEO_CAPTURE_COMPLETE, AST_VIDEO_INT_EN);
-+
-+	init_completion(&pAstRVAS->video_capture_complete);
-+	video_write(pAstRVAS, video_read(pAstRVAS, AST_VIDEO_PASS_CTRL) |
-+		VIDEO_SET_CAPTURE_FORMAT(1) | VIDEO_DIRECT_FETCH, AST_VIDEO_PASS_CTRL);
-+
-+	video_write(pAstRVAS, video_read(pAstRVAS, AST_VIDEO_BCD_CTRL) & ~VIDEO_BCD_CHG_EN, AST_VIDEO_BCD_CTRL);
-+	video_write(pAstRVAS, video_read(pAstRVAS, AST_VIDEO_SEQ_CTRL) & ~(VIDEO_CAPTURE_TRIGGER | VIDEO_COMPRESS_FORCE_IDLE | VIDEO_COMPRESS_TRIGGER | VIDEO_AUTO_COMPRESS), AST_VIDEO_SEQ_CTRL);
-+	//If CPU is too fast, pleas read back and trigger
-+	video_write(pAstRVAS, video_read(pAstRVAS, AST_VIDEO_SEQ_CTRL) | G5_VIDEO_COMPRESS_JPEG_MODE | VIDEO_CAPTURE_TRIGGER, AST_VIDEO_SEQ_CTRL);
-+
-+	timeout = wait_for_completion_interruptible_timeout(&pAstRVAS->video_capture_complete, HZ / 2);
-+
-+	if (timeout == 0)
-+		dev_err(pAstRVAS->pdev, "Capture timeout sts %x\n", video_read(pAstRVAS, AST_VIDEO_INT_STS));
-+
-+	//clear
-+	video_write(pAstRVAS, video_read(pAstRVAS, AST_VIDEO_SEQ_CTRL) & ~(VIDEO_CAPTURE_TRIGGER | VIDEO_COMPRESS_FORCE_IDLE | VIDEO_COMPRESS_TRIGGER | VIDEO_AUTO_COMPRESS), AST_VIDEO_SEQ_CTRL);
-+
-+	//dump_buffer(pAstRVAS->vem.captureBuf0.phy, 1024);
-+	return timeout;
-+}
-+
-+//
-+// static functions
-+//
-+static u32 get_vga_mem_base(struct AstRVAS *pAstRVAS)
-+{
-+	u32 vga_mem_size, mem_size;
-+
-+	mem_size = pAstRVAS->FBInfo.dwDRAMSize;
-+	vga_mem_size = pAstRVAS->FBInfo.dwVGASize;
-+	VIDEO_ENG_DBG("VGA Info : MEM Size %dMB, VGA Mem Size %dMB\n", mem_size / 1024 / 1024, vga_mem_size / 1024 / 1024);
-+	return (mem_size - vga_mem_size);
-+}
-+
-+static void dump_buffer(phys_addr_t dwPhyStreamAddress, u32 size)
-+{
-+	u32 iC;
-+	u32 val = 0;
-+
-+	for (iC = 0; iC < size; iC += 4) {
-+		val = readl((void *)(dwPhyStreamAddress + iC));
-+		VIDEO_ENG_DBG("%#x, ", val);
-+	}
-+}
-+
-+static void video_set_scaling(struct AstRVAS *pAstRVAS)
-+{
-+	u32 ctrl = video_read(pAstRVAS, AST_VIDEO_CTRL);
-+	//no scaling
-+	ctrl &= ~VIDEO_CTRL_DWN_SCALING_MASK;
-+
-+	VIDEO_ENG_DBG("Scaling Disable\n");
-+	video_write(pAstRVAS, 0x00200000, AST_VIDEO_SCALING0);
-+	video_write(pAstRVAS, 0x00200000, AST_VIDEO_SCALING1);
-+	video_write(pAstRVAS, 0x00200000, AST_VIDEO_SCALING2);
-+	video_write(pAstRVAS, 0x00200000, AST_VIDEO_SCALING3);
-+
-+	video_write(pAstRVAS, 0x10001000, AST_VIDEO_SCAL_FACTOR);
-+	video_write(pAstRVAS, ctrl, AST_VIDEO_CTRL);
-+
-+	video_set_Window(pAstRVAS);
-+}
-+
-+void video_ctrl_init(struct AstRVAS *pAstRVAS)
-+{
-+	u8 inputdelay = 0x4;
-+
-+	VIDEO_ENG_DBG("\n");
-+	if (pAstRVAS->config->version == 7) {
-+		VIDEO_ENG_DBG("reg address: 0x%llx\n", pAstRVAS->video_reg_base);
-+		/* Unlock VE registers */
-+		video_write(pAstRVAS, VIDEO_PROTECT_UNLOCK, AST_VIDEO_PROTECT);
-+		inputdelay = 0x1;
-+		/* Clear the offset */
-+		video_write(pAstRVAS, 0, AST_VIDEO_COMPRESS_PRO);
-+		video_write(pAstRVAS, 0, AST_VIDEO_COMPRESS_READ);
-+	}
-+
-+	/* disable interrupts */
-+	video_write(pAstRVAS, 0, AST_VIDEO_INT_EN);
-+	video_write(pAstRVAS, 0xffffffff, AST_VIDEO_INT_STS);
-+	video_write(pAstRVAS, 0, AST_VIDEO_BCD_CTRL);
-+
-+	/*write src addr and jped addr to register*/
-+	pAstRVAS->sequence = 1;
-+	video_write(pAstRVAS, _make_addr(pAstRVAS->vem.captureBuf0.phy), AST_VIDEO_SOURCE_BUFF0);//44h
-+	video_write(pAstRVAS, _make_addr(pAstRVAS->vem.captureBuf1.phy), AST_VIDEO_SOURCE_BUFF1);//4Ch
-+	video_write(pAstRVAS, pAstRVAS->vem.jpegTable.phy, AST_VIDEO_JPEG_HEADER_BUFF); //40h
-+	video_write(pAstRVAS, 0, AST_VIDEO_COMPRESS_READ); //3Ch
-+
-+	// =============================  JPEG init ===========================================
-+	init_jpeg_table(pAstRVAS);
-+	VIDEO_ENG_DBG("JpegTable in Memory:0x%llx\n", pAstRVAS->vem.jpegTable.pVirt);
-+	//dump_buffer(pAstRVAS->vem.jpegTable.phy, 80);
-+
-+	// ===================================================================================
-+	//Specification define bit 12:13 must always 0;
-+	video_write(pAstRVAS, (video_read(pAstRVAS, AST_VIDEO_PASS_CTRL) &
-+								~(VIDEO_DUAL_EDGE_MODE | VIDEO_18BIT_SINGLE_EDGE)) |
-+								VIDEO_DVO_INPUT_DELAY(inputdelay),
-+								AST_VIDEO_PASS_CTRL);
-+
-+	video_write(pAstRVAS, VIDEO_STREAM_PKT_N(STREAM_32_PKTS) |
-+					VIDEO_STREAM_PKT_SIZE(STREAM_128KB), AST_VIDEO_STREAM_SIZE);
-+	//rc4 init reset ..
-+	video_write(pAstRVAS, video_read(pAstRVAS, AST_VIDEO_CTRL) | VIDEO_CTRL_RC4_RST, AST_VIDEO_CTRL);
-+	video_write(pAstRVAS, video_read(pAstRVAS, AST_VIDEO_CTRL) & ~VIDEO_CTRL_RC4_RST, AST_VIDEO_CTRL);
-+
-+	//CRC/REDUCE_BIT register clear
-+	video_write(pAstRVAS, 0, AST_VIDEO_CRC1);
-+	video_write(pAstRVAS, 0, AST_VIDEO_CRC2);
-+	video_write(pAstRVAS, 0, AST_VIDEO_DATA_TRUNCA);
-+	video_write(pAstRVAS, 0, AST_VIDEO_COMPRESS_READ);
-+}
-+
-+static int reserve_video_engine_memory(struct AstRVAS *pAstRVAS)
-+{
-+	u32 size;
-+	dma_addr_t phys_add = 0;
-+	void *virt_add = 0;
-+
-+	memset(&pAstRVAS->vem, 0, sizeof(struct VideoEngineMem));
-+	pAstRVAS->vem.captureBuf0.size = VIDEO_CAPTURE_BUFFER_SIZE; //size 10M
-+	pAstRVAS->vem.captureBuf1.size = VIDEO_CAPTURE_BUFFER_SIZE; //size 10M
-+	pAstRVAS->vem.jpegTable.size =  VIDEO_JPEG_TABLE_SIZE; //size 1M
-+
-+	size = pAstRVAS->vem.captureBuf0.size + pAstRVAS->vem.captureBuf1.size + pAstRVAS->vem.jpegTable.size;
-+	VIDEO_ENG_DBG("Allocating memory size: 0x%x\n", size);
-+	virt_add = dma_alloc_coherent(pAstRVAS->pdev, size, &phys_add,
-+				      GFP_KERNEL);
-+
-+	if (!virt_add) {
-+		pr_err("Cannot alloc buffer for video engine\n");
-+		return -ENOMEM;
-+	}
-+
-+	pAstRVAS->vem.captureBuf0.phy =  phys_add;
-+	pAstRVAS->vem.captureBuf1.phy =  phys_add + pAstRVAS->vem.captureBuf0.size;
-+	pAstRVAS->vem.jpegTable.phy = phys_add + pAstRVAS->vem.captureBuf0.size + pAstRVAS->vem.captureBuf1.size;
-+
-+	pAstRVAS->vem.captureBuf0.pVirt = (void *)virt_add;
-+	pAstRVAS->vem.captureBuf1.pVirt = (void *)(virt_add + pAstRVAS->vem.captureBuf0.size);
-+	pAstRVAS->vem.jpegTable.pVirt = (void *)(virt_add + pAstRVAS->vem.captureBuf0.size + pAstRVAS->vem.captureBuf1.size);
-+
-+	VIDEO_ENG_DBG("Allocated: phys: 0x%llx\n", phys_add);
-+	VIDEO_ENG_DBG("Phy: Buf0:0x%llx; Buf1:0x%llx; jpegT:0x%llx\n", pAstRVAS->vem.captureBuf0.phy, pAstRVAS->vem.captureBuf1.phy, pAstRVAS->vem.jpegTable.phy);
-+	VIDEO_ENG_DBG("Virt: Buf0:0x%llx; Buf1:0x%llx; JpegT:0x%llx\n", pAstRVAS->vem.captureBuf0.pVirt, pAstRVAS->vem.captureBuf1.pVirt, pAstRVAS->vem.jpegTable.pVirt);
-+
-+	return 0;
-+}
-+
-+/************************************************ JPEG ***************************************************************************************/
-+static void init_jpeg_table(struct AstRVAS *pAstRVAS)
-+{
-+	int i = 0;
-+	int base = 0;
-+	u32 *tlb_table = pAstRVAS->vem.jpegTable.pVirt;
-+
-+	//JPEG header default value:
-+	for (i = 0; i < 12; i++) {
-+		base = (256 * i);
-+		tlb_table[base + 0] = 0xE0FFD8FF;
-+		tlb_table[base + 1] = 0x464A1000;
-+		tlb_table[base + 2] = 0x01004649;
-+		tlb_table[base + 3] = 0x60000101;
-+		tlb_table[base + 4] = 0x00006000;
-+		tlb_table[base + 5] = 0x0F00FEFF;
-+		tlb_table[base + 6] = 0x00002D05;
-+		tlb_table[base + 7] = 0x00000000;
-+		tlb_table[base + 8] = 0x00000000;
-+		tlb_table[base + 9] = 0x00DBFF00;
-+		tlb_table[base + 44] = 0x081100C0;
-+		tlb_table[base + 45] = 0x00000000;
-+		tlb_table[base + 47] = 0x03011102;
-+		tlb_table[base + 48] = 0xC4FF0111;
-+		tlb_table[base + 49] = 0x00001F00;
-+		tlb_table[base + 50] = 0x01010501;
-+		tlb_table[base + 51] = 0x01010101;
-+		tlb_table[base + 52] = 0x00000000;
-+		tlb_table[base + 53] = 0x00000000;
-+		tlb_table[base + 54] = 0x04030201;
-+		tlb_table[base + 55] = 0x08070605;
-+		tlb_table[base + 56] = 0xFF0B0A09;
-+		tlb_table[base + 57] = 0x10B500C4;
-+		tlb_table[base + 58] = 0x03010200;
-+		tlb_table[base + 59] = 0x03040203;
-+		tlb_table[base + 60] = 0x04040505;
-+		tlb_table[base + 61] = 0x7D010000;
-+		tlb_table[base + 62] = 0x00030201;
-+		tlb_table[base + 63] = 0x12051104;
-+		tlb_table[base + 64] = 0x06413121;
-+		tlb_table[base + 65] = 0x07615113;
-+		tlb_table[base + 66] = 0x32147122;
-+		tlb_table[base + 67] = 0x08A19181;
-+		tlb_table[base + 68] = 0xC1B14223;
-+		tlb_table[base + 69] = 0xF0D15215;
-+		tlb_table[base + 70] = 0x72623324;
-+		tlb_table[base + 71] = 0x160A0982;
-+		tlb_table[base + 72] = 0x1A191817;
-+		tlb_table[base + 73] = 0x28272625;
-+		tlb_table[base + 74] = 0x35342A29;
-+		tlb_table[base + 75] = 0x39383736;
-+		tlb_table[base + 76] = 0x4544433A;
-+		tlb_table[base + 77] = 0x49484746;
-+		tlb_table[base + 78] = 0x5554534A;
-+		tlb_table[base + 79] = 0x59585756;
-+		tlb_table[base + 80] = 0x6564635A;
-+		tlb_table[base + 81] = 0x69686766;
-+		tlb_table[base + 82] = 0x7574736A;
-+		tlb_table[base + 83] = 0x79787776;
-+		tlb_table[base + 84] = 0x8584837A;
-+		tlb_table[base + 85] = 0x89888786;
-+		tlb_table[base + 86] = 0x9493928A;
-+		tlb_table[base + 87] = 0x98979695;
-+		tlb_table[base + 88] = 0xA3A29A99;
-+		tlb_table[base + 89] = 0xA7A6A5A4;
-+		tlb_table[base + 90] = 0xB2AAA9A8;
-+		tlb_table[base + 91] = 0xB6B5B4B3;
-+		tlb_table[base + 92] = 0xBAB9B8B7;
-+		tlb_table[base + 93] = 0xC5C4C3C2;
-+		tlb_table[base + 94] = 0xC9C8C7C6;
-+		tlb_table[base + 95] = 0xD4D3D2CA;
-+		tlb_table[base + 96] = 0xD8D7D6D5;
-+		tlb_table[base + 97] = 0xE2E1DAD9;
-+		tlb_table[base + 98] = 0xE6E5E4E3;
-+		tlb_table[base + 99] = 0xEAE9E8E7;
-+		tlb_table[base + 100] = 0xF4F3F2F1;
-+		tlb_table[base + 101] = 0xF8F7F6F5;
-+		tlb_table[base + 102] = 0xC4FFFAF9;
-+		tlb_table[base + 103] = 0x00011F00;
-+		tlb_table[base + 104] = 0x01010103;
-+		tlb_table[base + 105] = 0x01010101;
-+		tlb_table[base + 106] = 0x00000101;
-+		tlb_table[base + 107] = 0x00000000;
-+		tlb_table[base + 108] = 0x04030201;
-+		tlb_table[base + 109] = 0x08070605;
-+		tlb_table[base + 110] = 0xFF0B0A09;
-+		tlb_table[base + 111] = 0x11B500C4;
-+		tlb_table[base + 112] = 0x02010200;
-+		tlb_table[base + 113] = 0x04030404;
-+		tlb_table[base + 114] = 0x04040507;
-+		tlb_table[base + 115] = 0x77020100;
-+		tlb_table[base + 116] = 0x03020100;
-+		tlb_table[base + 117] = 0x21050411;
-+		tlb_table[base + 118] = 0x41120631;
-+		tlb_table[base + 119] = 0x71610751;
-+		tlb_table[base + 120] = 0x81322213;
-+		tlb_table[base + 121] = 0x91421408;
-+		tlb_table[base + 122] = 0x09C1B1A1;
-+		tlb_table[base + 123] = 0xF0523323;
-+		tlb_table[base + 124] = 0xD1726215;
-+		tlb_table[base + 125] = 0x3424160A;
-+		tlb_table[base + 126] = 0x17F125E1;
-+		tlb_table[base + 127] = 0x261A1918;
-+		tlb_table[base + 128] = 0x2A292827;
-+		tlb_table[base + 129] = 0x38373635;
-+		tlb_table[base + 130] = 0x44433A39;
-+		tlb_table[base + 131] = 0x48474645;
-+		tlb_table[base + 132] = 0x54534A49;
-+		tlb_table[base + 133] = 0x58575655;
-+		tlb_table[base + 134] = 0x64635A59;
-+		tlb_table[base + 135] = 0x68676665;
-+		tlb_table[base + 136] = 0x74736A69;
-+		tlb_table[base + 137] = 0x78777675;
-+		tlb_table[base + 138] = 0x83827A79;
-+		tlb_table[base + 139] = 0x87868584;
-+		tlb_table[base + 140] = 0x928A8988;
-+		tlb_table[base + 141] = 0x96959493;
-+		tlb_table[base + 142] = 0x9A999897;
-+		tlb_table[base + 143] = 0xA5A4A3A2;
-+		tlb_table[base + 144] = 0xA9A8A7A6;
-+		tlb_table[base + 145] = 0xB4B3B2AA;
-+		tlb_table[base + 146] = 0xB8B7B6B5;
-+		tlb_table[base + 147] = 0xC3C2BAB9;
-+		tlb_table[base + 148] = 0xC7C6C5C4;
-+		tlb_table[base + 149] = 0xD2CAC9C8;
-+		tlb_table[base + 150] = 0xD6D5D4D3;
-+		tlb_table[base + 151] = 0xDAD9D8D7;
-+		tlb_table[base + 152] = 0xE5E4E3E2;
-+		tlb_table[base + 153] = 0xE9E8E7E6;
-+		tlb_table[base + 154] = 0xF4F3F2EA;
-+		tlb_table[base + 155] = 0xF8F7F6F5;
-+		tlb_table[base + 156] = 0xDAFFFAF9;
-+		tlb_table[base + 157] = 0x01030C00;
-+		tlb_table[base + 158] = 0x03110200;
-+		tlb_table[base + 159] = 0x003F0011;
-+
-+		//Table 0
-+		if (i == 0) {
-+			tlb_table[base + 10] = 0x0D140043;
-+			tlb_table[base + 11] = 0x0C0F110F;
-+			tlb_table[base + 12] = 0x11101114;
-+			tlb_table[base + 13] = 0x17141516;
-+			tlb_table[base + 14] = 0x1E20321E;
-+			tlb_table[base + 15] = 0x3D1E1B1B;
-+			tlb_table[base + 16] = 0x32242E2B;
-+			tlb_table[base + 17] = 0x4B4C3F48;
-+			tlb_table[base + 18] = 0x44463F47;
-+			tlb_table[base + 19] = 0x61735A50;
-+			tlb_table[base + 20] = 0x566C5550;
-+			tlb_table[base + 21] = 0x88644644;
-+			tlb_table[base + 22] = 0x7A766C65;
-+			tlb_table[base + 23] = 0x4D808280;
-+			tlb_table[base + 24] = 0x8C978D60;
-+			tlb_table[base + 25] = 0x7E73967D;
-+			tlb_table[base + 26] = 0xDBFF7B80;
-+			tlb_table[base + 27] = 0x1F014300;
-+			tlb_table[base + 28] = 0x272D2121;
-+			tlb_table[base + 29] = 0x3030582D;
-+			tlb_table[base + 30] = 0x697BB958;
-+			tlb_table[base + 31] = 0xB8B9B97B;
-+			tlb_table[base + 32] = 0xB9B8A6A6;
-+			tlb_table[base + 33] = 0xB9B9B9B9;
-+			tlb_table[base + 34] = 0xB9B9B9B9;
-+			tlb_table[base + 35] = 0xB9B9B9B9;
-+			tlb_table[base + 36] = 0xB9B9B9B9;
-+			tlb_table[base + 37] = 0xB9B9B9B9;
-+			tlb_table[base + 38] = 0xB9B9B9B9;
-+			tlb_table[base + 39] = 0xB9B9B9B9;
-+			tlb_table[base + 40] = 0xB9B9B9B9;
-+			tlb_table[base + 41] = 0xB9B9B9B9;
-+			tlb_table[base + 42] = 0xB9B9B9B9;
-+			tlb_table[base + 43] = 0xFFB9B9B9;
-+		}
-+		//Table 1
-+		if (i == 1) {
-+			tlb_table[base + 10] = 0x0C110043;
-+			tlb_table[base + 11] = 0x0A0D0F0D;
-+			tlb_table[base + 12] = 0x0F0E0F11;
-+			tlb_table[base + 13] = 0x14111213;
-+			tlb_table[base + 14] = 0x1A1C2B1A;
-+			tlb_table[base + 15] = 0x351A1818;
-+			tlb_table[base + 16] = 0x2B1F2826;
-+			tlb_table[base + 17] = 0x4142373F;
-+			tlb_table[base + 18] = 0x3C3D373E;
-+			tlb_table[base + 19] = 0x55644E46;
-+			tlb_table[base + 20] = 0x4B5F4A46;
-+			tlb_table[base + 21] = 0x77573D3C;
-+			tlb_table[base + 22] = 0x6B675F58;
-+			tlb_table[base + 23] = 0x43707170;
-+			tlb_table[base + 24] = 0x7A847B54;
-+			tlb_table[base + 25] = 0x6E64836D;
-+			tlb_table[base + 26] = 0xDBFF6C70;
-+			tlb_table[base + 27] = 0x1B014300;
-+			tlb_table[base + 28] = 0x22271D1D;
-+			tlb_table[base + 29] = 0x2A2A4C27;
-+			tlb_table[base + 30] = 0x5B6BA04C;
-+			tlb_table[base + 31] = 0xA0A0A06B;
-+			tlb_table[base + 32] = 0xA0A0A0A0;
-+			tlb_table[base + 33] = 0xA0A0A0A0;
-+			tlb_table[base + 34] = 0xA0A0A0A0;
-+			tlb_table[base + 35] = 0xA0A0A0A0;
-+			tlb_table[base + 36] = 0xA0A0A0A0;
-+			tlb_table[base + 37] = 0xA0A0A0A0;
-+			tlb_table[base + 38] = 0xA0A0A0A0;
-+			tlb_table[base + 39] = 0xA0A0A0A0;
-+			tlb_table[base + 40] = 0xA0A0A0A0;
-+			tlb_table[base + 41] = 0xA0A0A0A0;
-+			tlb_table[base + 42] = 0xA0A0A0A0;
-+			tlb_table[base + 43] = 0xFFA0A0A0;
-+		}
-+		//Table 2
-+		if (i == 2) {
-+			tlb_table[base + 10] = 0x090E0043;
-+			tlb_table[base + 11] = 0x090A0C0A;
-+			tlb_table[base + 12] = 0x0C0B0C0E;
-+			tlb_table[base + 13] = 0x110E0F10;
-+			tlb_table[base + 14] = 0x15172415;
-+			tlb_table[base + 15] = 0x2C151313;
-+			tlb_table[base + 16] = 0x241A211F;
-+			tlb_table[base + 17] = 0x36372E34;
-+			tlb_table[base + 18] = 0x31322E33;
-+			tlb_table[base + 19] = 0x4653413A;
-+			tlb_table[base + 20] = 0x3E4E3D3A;
-+			tlb_table[base + 21] = 0x62483231;
-+			tlb_table[base + 22] = 0x58564E49;
-+			tlb_table[base + 23] = 0x385D5E5D;
-+			tlb_table[base + 24] = 0x656D6645;
-+			tlb_table[base + 25] = 0x5B536C5A;
-+			tlb_table[base + 26] = 0xDBFF595D;
-+			tlb_table[base + 27] = 0x16014300;
-+			tlb_table[base + 28] = 0x1C201818;
-+			tlb_table[base + 29] = 0x22223F20;
-+			tlb_table[base + 30] = 0x4B58853F;
-+			tlb_table[base + 31] = 0x85858558;
-+			tlb_table[base + 32] = 0x85858585;
-+			tlb_table[base + 33] = 0x85858585;
-+			tlb_table[base + 34] = 0x85858585;
-+			tlb_table[base + 35] = 0x85858585;
-+			tlb_table[base + 36] = 0x85858585;
-+			tlb_table[base + 37] = 0x85858585;
-+			tlb_table[base + 38] = 0x85858585;
-+			tlb_table[base + 39] = 0x85858585;
-+			tlb_table[base + 40] = 0x85858585;
-+			tlb_table[base + 41] = 0x85858585;
-+			tlb_table[base + 42] = 0x85858585;
-+			tlb_table[base + 43] = 0xFF858585;
-+		}
-+		//Table 3
-+		if (i == 3) {
-+			tlb_table[base + 10] = 0x070B0043;
-+			tlb_table[base + 11] = 0x07080A08;
-+			tlb_table[base + 12] = 0x0A090A0B;
-+			tlb_table[base + 13] = 0x0D0B0C0C;
-+			tlb_table[base + 14] = 0x11121C11;
-+			tlb_table[base + 15] = 0x23110F0F;
-+			tlb_table[base + 16] = 0x1C141A19;
-+			tlb_table[base + 17] = 0x2B2B2429;
-+			tlb_table[base + 18] = 0x27282428;
-+			tlb_table[base + 19] = 0x3842332E;
-+			tlb_table[base + 20] = 0x313E302E;
-+			tlb_table[base + 21] = 0x4E392827;
-+			tlb_table[base + 22] = 0x46443E3A;
-+			tlb_table[base + 23] = 0x2C4A4A4A;
-+			tlb_table[base + 24] = 0x50565137;
-+			tlb_table[base + 25] = 0x48425647;
-+			tlb_table[base + 26] = 0xDBFF474A;
-+			tlb_table[base + 27] = 0x12014300;
-+			tlb_table[base + 28] = 0x161A1313;
-+			tlb_table[base + 29] = 0x1C1C331A;
-+			tlb_table[base + 30] = 0x3D486C33;
-+			tlb_table[base + 31] = 0x6C6C6C48;
-+			tlb_table[base + 32] = 0x6C6C6C6C;
-+			tlb_table[base + 33] = 0x6C6C6C6C;
-+			tlb_table[base + 34] = 0x6C6C6C6C;
-+			tlb_table[base + 35] = 0x6C6C6C6C;
-+			tlb_table[base + 36] = 0x6C6C6C6C;
-+			tlb_table[base + 37] = 0x6C6C6C6C;
-+			tlb_table[base + 38] = 0x6C6C6C6C;
-+			tlb_table[base + 39] = 0x6C6C6C6C;
-+			tlb_table[base + 40] = 0x6C6C6C6C;
-+			tlb_table[base + 41] = 0x6C6C6C6C;
-+			tlb_table[base + 42] = 0x6C6C6C6C;
-+			tlb_table[base + 43] = 0xFF6C6C6C;
-+		}
-+		//Table 4
-+		if (i == 4) {
-+			tlb_table[base + 10] = 0x06090043;
-+			tlb_table[base + 11] = 0x05060706;
-+			tlb_table[base + 12] = 0x07070709;
-+			tlb_table[base + 13] = 0x0A09090A;
-+			tlb_table[base + 14] = 0x0D0E160D;
-+			tlb_table[base + 15] = 0x1B0D0C0C;
-+			tlb_table[base + 16] = 0x16101413;
-+			tlb_table[base + 17] = 0x21221C20;
-+			tlb_table[base + 18] = 0x1E1F1C20;
-+			tlb_table[base + 19] = 0x2B332824;
-+			tlb_table[base + 20] = 0x26302624;
-+			tlb_table[base + 21] = 0x3D2D1F1E;
-+			tlb_table[base + 22] = 0x3735302D;
-+			tlb_table[base + 23] = 0x22393A39;
-+			tlb_table[base + 24] = 0x3F443F2B;
-+			tlb_table[base + 25] = 0x38334338;
-+			tlb_table[base + 26] = 0xDBFF3739;
-+			tlb_table[base + 27] = 0x0D014300;
-+			tlb_table[base + 28] = 0x11130E0E;
-+			tlb_table[base + 29] = 0x15152613;
-+			tlb_table[base + 30] = 0x2D355026;
-+			tlb_table[base + 31] = 0x50505035;
-+			tlb_table[base + 32] = 0x50505050;
-+			tlb_table[base + 33] = 0x50505050;
-+			tlb_table[base + 34] = 0x50505050;
-+			tlb_table[base + 35] = 0x50505050;
-+			tlb_table[base + 36] = 0x50505050;
-+			tlb_table[base + 37] = 0x50505050;
-+			tlb_table[base + 38] = 0x50505050;
-+			tlb_table[base + 39] = 0x50505050;
-+			tlb_table[base + 40] = 0x50505050;
-+			tlb_table[base + 41] = 0x50505050;
-+			tlb_table[base + 42] = 0x50505050;
-+			tlb_table[base + 43] = 0xFF505050;
-+		}
-+		//Table 5
-+		if (i == 5) {
-+			tlb_table[base + 10] = 0x04060043;
-+			tlb_table[base + 11] = 0x03040504;
-+			tlb_table[base + 12] = 0x05040506;
-+			tlb_table[base + 13] = 0x07060606;
-+			tlb_table[base + 14] = 0x09090F09;
-+			tlb_table[base + 15] = 0x12090808;
-+			tlb_table[base + 16] = 0x0F0A0D0D;
-+			tlb_table[base + 17] = 0x16161315;
-+			tlb_table[base + 18] = 0x14151315;
-+			tlb_table[base + 19] = 0x1D221B18;
-+			tlb_table[base + 20] = 0x19201918;
-+			tlb_table[base + 21] = 0x281E1514;
-+			tlb_table[base + 22] = 0x2423201E;
-+			tlb_table[base + 23] = 0x17262726;
-+			tlb_table[base + 24] = 0x2A2D2A1C;
-+			tlb_table[base + 25] = 0x25222D25;
-+			tlb_table[base + 26] = 0xDBFF2526;
-+			tlb_table[base + 27] = 0x09014300;
-+			tlb_table[base + 28] = 0x0B0D0A0A;
-+			tlb_table[base + 29] = 0x0E0E1A0D;
-+			tlb_table[base + 30] = 0x1F25371A;
-+			tlb_table[base + 31] = 0x37373725;
-+			tlb_table[base + 32] = 0x37373737;
-+			tlb_table[base + 33] = 0x37373737;
-+			tlb_table[base + 34] = 0x37373737;
-+			tlb_table[base + 35] = 0x37373737;
-+			tlb_table[base + 36] = 0x37373737;
-+			tlb_table[base + 37] = 0x37373737;
-+			tlb_table[base + 38] = 0x37373737;
-+			tlb_table[base + 39] = 0x37373737;
-+			tlb_table[base + 40] = 0x37373737;
-+			tlb_table[base + 41] = 0x37373737;
-+			tlb_table[base + 42] = 0x37373737;
-+			tlb_table[base + 43] = 0xFF373737;
-+		}
-+		//Table 6
-+		if (i == 6) {
-+			tlb_table[base + 10] = 0x02030043;
-+			tlb_table[base + 11] = 0x01020202;
-+			tlb_table[base + 12] = 0x02020203;
-+			tlb_table[base + 13] = 0x03030303;
-+			tlb_table[base + 14] = 0x04040704;
-+			tlb_table[base + 15] = 0x09040404;
-+			tlb_table[base + 16] = 0x07050606;
-+			tlb_table[base + 17] = 0x0B0B090A;
-+			tlb_table[base + 18] = 0x0A0A090A;
-+			tlb_table[base + 19] = 0x0E110D0C;
-+			tlb_table[base + 20] = 0x0C100C0C;
-+			tlb_table[base + 21] = 0x140F0A0A;
-+			tlb_table[base + 22] = 0x1211100F;
-+			tlb_table[base + 23] = 0x0B131313;
-+			tlb_table[base + 24] = 0x1516150E;
-+			tlb_table[base + 25] = 0x12111612;
-+			tlb_table[base + 26] = 0xDBFF1213;
-+			tlb_table[base + 27] = 0x04014300;
-+			tlb_table[base + 28] = 0x05060505;
-+			tlb_table[base + 29] = 0x07070D06;
-+			tlb_table[base + 30] = 0x0F121B0D;
-+			tlb_table[base + 31] = 0x1B1B1B12;
-+			tlb_table[base + 32] = 0x1B1B1B1B;
-+			tlb_table[base + 33] = 0x1B1B1B1B;
-+			tlb_table[base + 34] = 0x1B1B1B1B;
-+			tlb_table[base + 35] = 0x1B1B1B1B;
-+			tlb_table[base + 36] = 0x1B1B1B1B;
-+			tlb_table[base + 37] = 0x1B1B1B1B;
-+			tlb_table[base + 38] = 0x1B1B1B1B;
-+			tlb_table[base + 39] = 0x1B1B1B1B;
-+			tlb_table[base + 40] = 0x1B1B1B1B;
-+			tlb_table[base + 41] = 0x1B1B1B1B;
-+			tlb_table[base + 42] = 0x1B1B1B1B;
-+			tlb_table[base + 43] = 0xFF1B1B1B;
-+		}
-+		//Table 7
-+		if (i == 7) {
-+			tlb_table[base + 10] = 0x01020043;
-+			tlb_table[base + 11] = 0x01010101;
-+			tlb_table[base + 12] = 0x01010102;
-+			tlb_table[base + 13] = 0x02020202;
-+			tlb_table[base + 14] = 0x03030503;
-+			tlb_table[base + 15] = 0x06030202;
-+			tlb_table[base + 16] = 0x05030404;
-+			tlb_table[base + 17] = 0x07070607;
-+			tlb_table[base + 18] = 0x06070607;
-+			tlb_table[base + 19] = 0x090B0908;
-+			tlb_table[base + 20] = 0x080A0808;
-+			tlb_table[base + 21] = 0x0D0A0706;
-+			tlb_table[base + 22] = 0x0C0B0A0A;
-+			tlb_table[base + 23] = 0x070C0D0C;
-+			tlb_table[base + 24] = 0x0E0F0E09;
-+			tlb_table[base + 25] = 0x0C0B0F0C;
-+			tlb_table[base + 26] = 0xDBFF0C0C;
-+			tlb_table[base + 27] = 0x03014300;
-+			tlb_table[base + 28] = 0x03040303;
-+			tlb_table[base + 29] = 0x04040804;
-+			tlb_table[base + 30] = 0x0A0C1208;
-+			tlb_table[base + 31] = 0x1212120C;
-+			tlb_table[base + 32] = 0x12121212;
-+			tlb_table[base + 33] = 0x12121212;
-+			tlb_table[base + 34] = 0x12121212;
-+			tlb_table[base + 35] = 0x12121212;
-+			tlb_table[base + 36] = 0x12121212;
-+			tlb_table[base + 37] = 0x12121212;
-+			tlb_table[base + 38] = 0x12121212;
-+			tlb_table[base + 39] = 0x12121212;
-+			tlb_table[base + 40] = 0x12121212;
-+			tlb_table[base + 41] = 0x12121212;
-+			tlb_table[base + 42] = 0x12121212;
-+			tlb_table[base + 43] = 0xFF121212;
-+		}
-+		//Table 8
-+		if (i == 8) {
-+			tlb_table[base + 10] = 0x01020043;
-+			tlb_table[base + 11] = 0x01010101;
-+			tlb_table[base + 12] = 0x01010102;
-+			tlb_table[base + 13] = 0x02020202;
-+			tlb_table[base + 14] = 0x03030503;
-+			tlb_table[base + 15] = 0x06030202;
-+			tlb_table[base + 16] = 0x05030404;
-+			tlb_table[base + 17] = 0x07070607;
-+			tlb_table[base + 18] = 0x06070607;
-+			tlb_table[base + 19] = 0x090B0908;
-+			tlb_table[base + 20] = 0x080A0808;
-+			tlb_table[base + 21] = 0x0D0A0706;
-+			tlb_table[base + 22] = 0x0C0B0A0A;
-+			tlb_table[base + 23] = 0x070C0D0C;
-+			tlb_table[base + 24] = 0x0E0F0E09;
-+			tlb_table[base + 25] = 0x0C0B0F0C;
-+			tlb_table[base + 26] = 0xDBFF0C0C;
-+			tlb_table[base + 27] = 0x02014300;
-+			tlb_table[base + 28] = 0x03030202;
-+			tlb_table[base + 29] = 0x04040703;
-+			tlb_table[base + 30] = 0x080A0F07;
-+			tlb_table[base + 31] = 0x0F0F0F0A;
-+			tlb_table[base + 32] = 0x0F0F0F0F;
-+			tlb_table[base + 33] = 0x0F0F0F0F;
-+			tlb_table[base + 34] = 0x0F0F0F0F;
-+			tlb_table[base + 35] = 0x0F0F0F0F;
-+			tlb_table[base + 36] = 0x0F0F0F0F;
-+			tlb_table[base + 37] = 0x0F0F0F0F;
-+			tlb_table[base + 38] = 0x0F0F0F0F;
-+			tlb_table[base + 39] = 0x0F0F0F0F;
-+			tlb_table[base + 40] = 0x0F0F0F0F;
-+			tlb_table[base + 41] = 0x0F0F0F0F;
-+			tlb_table[base + 42] = 0x0F0F0F0F;
-+			tlb_table[base + 43] = 0xFF0F0F0F;
-+		}
-+		//Table 9
-+		if (i == 9) {
-+			tlb_table[base + 10] = 0x01010043;
-+			tlb_table[base + 11] = 0x01010101;
-+			tlb_table[base + 12] = 0x01010101;
-+			tlb_table[base + 13] = 0x01010101;
-+			tlb_table[base + 14] = 0x02020302;
-+			tlb_table[base + 15] = 0x04020202;
-+			tlb_table[base + 16] = 0x03020303;
-+			tlb_table[base + 17] = 0x05050405;
-+			tlb_table[base + 18] = 0x05050405;
-+			tlb_table[base + 19] = 0x07080606;
-+			tlb_table[base + 20] = 0x06080606;
-+			tlb_table[base + 21] = 0x0A070505;
-+			tlb_table[base + 22] = 0x09080807;
-+			tlb_table[base + 23] = 0x05090909;
-+			tlb_table[base + 24] = 0x0A0B0A07;
-+			tlb_table[base + 25] = 0x09080B09;
-+			tlb_table[base + 26] = 0xDBFF0909;
-+			tlb_table[base + 27] = 0x02014300;
-+			tlb_table[base + 28] = 0x02030202;
-+			tlb_table[base + 29] = 0x03030503;
-+			tlb_table[base + 30] = 0x07080C05;
-+			tlb_table[base + 31] = 0x0C0C0C08;
-+			tlb_table[base + 32] = 0x0C0C0C0C;
-+			tlb_table[base + 33] = 0x0C0C0C0C;
-+			tlb_table[base + 34] = 0x0C0C0C0C;
-+			tlb_table[base + 35] = 0x0C0C0C0C;
-+			tlb_table[base + 36] = 0x0C0C0C0C;
-+			tlb_table[base + 37] = 0x0C0C0C0C;
-+			tlb_table[base + 38] = 0x0C0C0C0C;
-+			tlb_table[base + 39] = 0x0C0C0C0C;
-+			tlb_table[base + 40] = 0x0C0C0C0C;
-+			tlb_table[base + 41] = 0x0C0C0C0C;
-+			tlb_table[base + 42] = 0x0C0C0C0C;
-+			tlb_table[base + 43] = 0xFF0C0C0C;
-+		}
-+		//Table 10
-+		if (i == 10) {
-+			tlb_table[base + 10] = 0x01010043;
-+			tlb_table[base + 11] = 0x01010101;
-+			tlb_table[base + 12] = 0x01010101;
-+			tlb_table[base + 13] = 0x01010101;
-+			tlb_table[base + 14] = 0x01010201;
-+			tlb_table[base + 15] = 0x03010101;
-+			tlb_table[base + 16] = 0x02010202;
-+			tlb_table[base + 17] = 0x03030303;
-+			tlb_table[base + 18] = 0x03030303;
-+			tlb_table[base + 19] = 0x04050404;
-+			tlb_table[base + 20] = 0x04050404;
-+			tlb_table[base + 21] = 0x06050303;
-+			tlb_table[base + 22] = 0x06050505;
-+			tlb_table[base + 23] = 0x03060606;
-+			tlb_table[base + 24] = 0x07070704;
-+			tlb_table[base + 25] = 0x06050706;
-+			tlb_table[base + 26] = 0xDBFF0606;
-+			tlb_table[base + 27] = 0x01014300;
-+			tlb_table[base + 28] = 0x01020101;
-+			tlb_table[base + 29] = 0x02020402;
-+			tlb_table[base + 30] = 0x05060904;
-+			tlb_table[base + 31] = 0x09090906;
-+			tlb_table[base + 32] = 0x09090909;
-+			tlb_table[base + 33] = 0x09090909;
-+			tlb_table[base + 34] = 0x09090909;
-+			tlb_table[base + 35] = 0x09090909;
-+			tlb_table[base + 36] = 0x09090909;
-+			tlb_table[base + 37] = 0x09090909;
-+			tlb_table[base + 38] = 0x09090909;
-+			tlb_table[base + 39] = 0x09090909;
-+			tlb_table[base + 40] = 0x09090909;
-+			tlb_table[base + 41] = 0x09090909;
-+			tlb_table[base + 42] = 0x09090909;
-+			tlb_table[base + 43] = 0xFF090909;
-+		}
-+		//Table 11
-+		if (i == 11) {
-+			tlb_table[base + 10] = 0x01010043;
-+			tlb_table[base + 11] = 0x01010101;
-+			tlb_table[base + 12] = 0x01010101;
-+			tlb_table[base + 13] = 0x01010101;
-+			tlb_table[base + 14] = 0x01010101;
-+			tlb_table[base + 15] = 0x01010101;
-+			tlb_table[base + 16] = 0x01010101;
-+			tlb_table[base + 17] = 0x01010101;
-+			tlb_table[base + 18] = 0x01010101;
-+			tlb_table[base + 19] = 0x02020202;
-+			tlb_table[base + 20] = 0x02020202;
-+			tlb_table[base + 21] = 0x03020101;
-+			tlb_table[base + 22] = 0x03020202;
-+			tlb_table[base + 23] = 0x01030303;
-+			tlb_table[base + 24] = 0x03030302;
-+			tlb_table[base + 25] = 0x03020303;
-+			tlb_table[base + 26] = 0xDBFF0403;
-+			tlb_table[base + 27] = 0x01014300;
-+			tlb_table[base + 28] = 0x01010101;
-+			tlb_table[base + 29] = 0x01010201;
-+			tlb_table[base + 30] = 0x03040602;
-+			tlb_table[base + 31] = 0x06060604;
-+			tlb_table[base + 32] = 0x06060606;
-+			tlb_table[base + 33] = 0x06060606;
-+			tlb_table[base + 34] = 0x06060606;
-+			tlb_table[base + 35] = 0x06060606;
-+			tlb_table[base + 36] = 0x06060606;
-+			tlb_table[base + 37] = 0x06060606;
-+			tlb_table[base + 38] = 0x06060606;
-+			tlb_table[base + 39] = 0x06060606;
-+			tlb_table[base + 40] = 0x06060606;
-+			tlb_table[base + 41] = 0x06060606;
-+			tlb_table[base + 42] = 0x06060606;
-+			tlb_table[base + 43] = 0xFF060606;
-+		}
-+	}
-+}
-+
-+static inline void
-+video_write(struct AstRVAS *pAstRVAS, u32 val, u32 reg)
-+{
-+	VIDEO_ENG_DBG("write offset: %x, val: %x\n", reg, val);
-+	//Video is lock after reset, need always unlock
-+	//unlock
-+	writel(VIDEO_PROTECT_UNLOCK, pAstRVAS->video_reg_base);
-+	writel(val, pAstRVAS->video_reg_base + reg);
-+}
-+
-+static inline u32
-+video_read(struct AstRVAS *pAstRVAS, u32 reg)
-+{
-+	u32 val = readl(pAstRVAS->video_reg_base + reg);
-+
-+	VIDEO_ENG_DBG("read offset: %x, val: %x\n", reg, val);
-+	return val;
-+}
-diff --git a/drivers/soc/aspeed/rvas/video_engine.h b/drivers/soc/aspeed/rvas/video_engine.h
-new file mode 100644
-index 000000000..a1042b8ba
---- /dev/null
-+++ b/drivers/soc/aspeed/rvas/video_engine.h
-@@ -0,0 +1,270 @@
-+/* SPDX-License-Identifier: GPL-2.0+ */
-+/*
-+ * File Name     : video_engines.h
-+ * Description   : AST2600 video  engines
-+ *
-+ * Copyright (C) 2019-2021 ASPEED Technology Inc. All rights reserved.
-+ *
-+ * 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; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+#ifndef __VIDEO_ENGINE_H__
-+#define __VIDEO_ENGINE_H__
-+
-+#include "video_ioctl.h"
-+#include "hardware_engines.h"
-+
-+#define VIDEO_STREAM_BUFFER_SIZE	(0x400000) //4M
-+#define VIDEO_CAPTURE_BUFFER_SIZE	(0xA00000) //10M
-+#define VIDEO_JPEG_TABLE_SIZE		(0x100000) //1M
-+
-+#define SCU_VIDEO_ENGINE_BIT						BIT(6)
-+#define SCU_VIDEO_CAPTURE_STOP_CLOCK_BIT			BIT(3)
-+#define SCU_VIDEO_ENGINE_STOP_CLOCK_BIT				BIT(1)
-+/***********************************************************************/
-+/* Register for VIDEO */
-+#define AST_VIDEO_PROTECT			0x000		/*	protection key register	*/
-+#define AST_VIDEO_SEQ_CTRL			0x004		/*	Video Sequence Control register	*/
-+#define AST_VIDEO_PASS_CTRL		0x008		/*	Video Pass 1 Control register	*/
-+
-+//VR008[5]=1
-+#define AST_VIDEO_DIRECT_BASE		0x00C		/*	Video Direct Frame buffer mode control Register VR008[5]=1 */
-+#define AST_VIDEO_DIRECT_CTRL		0x010		/*	Video Direct Frame buffer mode control Register VR008[5]=1 */
-+
-+//VR008[5]=0
-+#define AST_VIDEO_TIMING_H			0x00C		/*	Video Timing Generation Setting Register */
-+#define AST_VIDEO_TIMING_V			0x010		/*	Video Timing Generation Setting Register */
-+#define AST_VIDEO_SCAL_FACTOR		0x014		/*	Video Scaling Factor Register */
-+
-+#define AST_VIDEO_SCALING0		0x018		/*	Video Scaling Filter Parameter Register #0 */
-+#define AST_VIDEO_SCALING1		0x01C		/*	Video Scaling Filter Parameter Register #1 */
-+#define AST_VIDEO_SCALING2		0x020		/*	Video Scaling Filter Parameter Register #2 */
-+#define AST_VIDEO_SCALING3		0x024		/*	Video Scaling Filter Parameter Register #3 */
-+
-+#define AST_VIDEO_BCD_CTRL			0x02C		/*	Video BCD Control Register */
-+#define AST_VIDEO_CAPTURE_WIN		0x030		/*	 Video Capturing Window Setting Register */
-+#define AST_VIDEO_COMPRESS_WIN	0x034		/*	 Video Compression Window Setting Register */
-+
-+#define AST_VIDEO_COMPRESS_PRO	0x038		/* Video Compression Stream Buffer Processing Offset Register */
-+#define AST_VIDEO_COMPRESS_READ	0x03C		/* Video Compression Stream Buffer Read Offset Register */
-+
-+#define AST_VIDEO_JPEG_HEADER_BUFF	0x040		/*	Video Based Address of JPEG Header Buffer Register */
-+#define AST_VIDEO_SOURCE_BUFF0		0x044		/*	Video Based Address of Video Source Buffer #1 Register */
-+#define AST_VIDEO_SOURCE_SCAN_LINE	0x048		/*	Video Scan Line Offset of Video Source Buffer Register */
-+#define AST_VIDEO_SOURCE_BUFF1		0x04C		/*	Video Based Address of Video Source Buffer #2 Register */
-+#define AST_VIDEO_BCD_BUFF				0x050		/*	Video Base Address of BCD Flag Buffer Register */
-+#define AST_VIDEO_STREAM_BUFF			0x054		/*	Video Base Address of Compressed Video Stream Buffer Register */
-+#define AST_VIDEO_STREAM_SIZE			0x058		/*	Video Stream Buffer Size Register */
-+
-+#define AST_VIDEO_COMPRESS_CTRL				0x060		/* Video Compression Control Register */
-+
-+#define AST_VIDEO_COMPRESS_DATA_COUNT		0x070		/* Video Total Size of Compressed Video Stream Read Back Register */
-+#define AST_VIDEO_COMPRESS_BLOCK_COUNT		0x074		/* Video Total Number of Compressed Video Block Read Back Register */
-+#define AST_VIDEO_COMPRESS_FRAME_END		0x078		/* Video Frame-end offset of compressed video stream buffer read back Register */
-+#define AST_VIDEO_COMPRESS_FRAME_COUNT_RB	0x7C
-+#define AST_VIDEO_JPEG_SIZE			        0x084
-+
-+#define AST_VIDEO_CTRL			0x300		/* Video Control Register */
-+#define AST_VIDEO_INT_EN		0x304		/* Video interrupt Enable */
-+#define AST_VIDEO_INT_STS		0x308		/* Video interrupt status */
-+#define AST_VIDEO_MODE_DETECT	0x30C		/* Video Mode Detection Parameter Register */
-+
-+#define AST_VIDEO_CRC1			0x320		/* Primary CRC Parameter Register */
-+#define AST_VIDEO_CRC2			0x324		/* Second CRC Parameter Register */
-+#define AST_VIDEO_DATA_TRUNCA	0x328		/* Video Data Truncation Register */
-+
-+#define AST_VIDEO_E_SCRATCH_34C	0x34C		/* Video Scratch Remap Read Back */
-+#define AST_VIDEO_E_SCRATCH_350	0x350		/* Video Scratch Remap Read Back */
-+#define AST_VIDEO_E_SCRATCH_354	0x354		/* Video Scratch Remap Read Back */
-+
-+//multi jpeg
-+#define AST_VIDEO_ENCRYPT_SRAM		0x400		/* Video RC4/AES128 Encryption Key Register #0 ~ #63 */
-+#define AST_VIDEO_MULTI_JPEG_SRAM	(AST_VIDEO_ENCRYPT_SRAM)		/* Multi JPEG registers */
-+
-+#define REG_32_BIT_SZ_IN_BYTES (sizeof(u32))
-+
-+#define SET_FRAME_W_H(w, h) ((((u32)(h)) & 0x1fff) | ((((u32)(w)) & 0x1fff) << 13))
-+#define SET_FRAME_START_ADDR(addr) ((addr) & 0x7fffff80)
-+
-+/////////////////////////////////////////////////////////////////////////////
-+
-+/*	AST_VIDEO_PROTECT: 0x000  - protection key register */
-+#define VIDEO_PROTECT_UNLOCK				0x1A038AA8
-+
-+/*	AST_VIDEO_SEQ_CTRL		0x004		Video Sequence Control register	*/
-+#define VIDEO_HALT_ENG_STS				BIT(21)
-+#define VIDEO_COMPRESS_BUSY				BIT(18)
-+#define VIDEO_CAPTURE_BUSY				BIT(16)
-+#define VIDEO_HALT_ENG_TRIGGER				BIT(12)
-+#define VIDEO_COMPRESS_FORMAT_MASK				BIT(10)
-+#define VIDEO_GET_COMPRESS_FORMAT(x)		(((x) >> 10) & 0x3)   // 0 YUV444
-+#define VIDEO_COMPRESS_FORMAT(x)			((x) << 10)	// 0 YUV444
-+#define YUV420		1
-+
-+#define G5_VIDEO_COMPRESS_JPEG_MODE			BIT(13)
-+#define VIDEO_YUV2RGB_DITHER_EN			BIT(8)
-+
-+#define VIDEO_COMPRESS_JPEG_MODE			BIT(8)
-+
-+//if bit 0 : 1
-+#define VIDEO_INPUT_MODE_CHG_WDT			BIT(7)
-+#define VIDEO_INSERT_FULL_COMPRESS			BIT(6)
-+#define VIDEO_AUTO_COMPRESS			BIT(5)
-+#define VIDEO_COMPRESS_TRIGGER			BIT(4)
-+#define VIDEO_CAPTURE_MULTI_FRAME			BIT(3)
-+#define VIDEO_COMPRESS_FORCE_IDLE			BIT(2)
-+#define VIDEO_CAPTURE_TRIGGER			BIT(1)
-+#define VIDEO_DETECT_TRIGGER			BIT(0)
-+
-+#define VIDEO_HALT_ENG_RB			BIT(21)
-+
-+#define VIDEO_ABCD_CHG_EN			BIT(1)
-+#define VIDEO_BCD_CHG_EN			(1)
-+
-+/*	AST_VIDEO_PASS_CTRL			0x008		Video Pass1 Control register	*/
-+#define G6_VIDEO_MULTI_JPEG_FLAG_MODE		BIT(31)
-+#define G6_VIDEO_MULTI_JPEG_MODE			BIT(30)
-+#define G6_VIDEO_JPEG__COUNT(x)			((x) << 24)
-+#define G6_VIDEO_FRAME_CT_MASK			(0x3f << 24)
-+//x * source frame rate / 60
-+#define VIDEO_FRAME_RATE_CTRL(x)			((x) << 16)
-+#define VIDEO_HSYNC_POLARITY_CTRL			BIT(15)
-+#define VIDEO_INTERLANCE_MODE			BIT(14)
-+#define VIDEO_DUAL_EDGE_MODE			BIT(13)	//0 : Single edage
-+#define VIDEO_18BIT_SINGLE_EDGE			BIT(12)	//0: 24bits
-+#define VIDEO_DVO_INPUT_DELAY_MASK			(7 << 9)
-+#define VIDEO_DVO_INPUT_DELAY(x)			((x) << 9) //0 : no delay , 1: 1ns, 2: 2ns, 3:3ns, 4: inversed clock but no delay
-+// if bit 5 : 0
-+#define VIDEO_HW_CURSOR_DIS			BIT(8)
-+// if bit 5 : 1
-+#define VIDEO_AUTO_FETCH			BIT(8)	//
-+#define VIDEO_CAPTURE_FORMATE_MASK		(3 << 6)
-+
-+#define VIDEO_SET_CAPTURE_FORMAT(x)		((x) << 6)
-+#define JPEG_MODE		1
-+#define RGB_MODE		2
-+#define GRAY_MODE		3
-+#define VIDEO_DIRECT_FETCH				BIT(5)
-+// if bit 5 : 0
-+#define VIDEO_INTERNAL_DE				BIT(4)
-+#define VIDEO_EXT_ADC_ATTRIBUTE				BIT(3)
-+
-+/*	AST_VIDEO_DIRECT_CTRL	0x010		Video Direct Frame buffer mode control Register VR008[5]=1 */
-+#define VIDEO_FETCH_TIMING(x)			((x) << 16)
-+#define VIDEO_FETCH_LINE_OFFSET(x)		((x) & 0xffff)
-+
-+/*	 AST_VIDEO_CAPTURE_WIN	0x030		Video Capturing Window Setting Register */
-+#define VIDEO_CAPTURE_V(x)				((x) & 0x7ff)
-+#define VIDEO_CAPTURE_H(x)				(((x) & 0x7ff) << 16)
-+
-+/*	 AST_VIDEO_COMPRESS_WIN	0x034		Video Compression Window Setting Register */
-+#define VIDEO_COMPRESS_V(x)			((x) & 0x7ff)
-+#define VIDEO_GET_COMPRESS_V(x)			((x) & 0x7ff)
-+#define VIDEO_COMPRESS_H(x)			(((x) & 0x7ff) << 16)
-+#define VIDEO_GET_COMPRESS_H(x)			(((x) >> 16) & 0x7ff)
-+
-+/*	AST_VIDEO_STREAM_SIZE	0x058		Video Stream Buffer Size Register */
-+#define VIDEO_STREAM_PKT_N(x)			((x) << 3)
-+#define STREAM_4_PKTS		0
-+#define STREAM_8_PKTS		1
-+#define STREAM_16_PKTS		2
-+#define STREAM_32_PKTS		3
-+#define STREAM_64_PKTS		4
-+#define STREAM_128_PKTS		5
-+
-+#define VIDEO_STREAM_PKT_SIZE(x)		(x)
-+#define STREAM_1KB		0
-+#define STREAM_2KB		1
-+#define STREAM_4KB		2
-+#define STREAM_8KB		3
-+#define STREAM_16KB		4
-+#define STREAM_32KB		5
-+#define STREAM_64KB		6
-+#define STREAM_128KB	7
-+
-+/* AST_VIDEO_COMPRESS_CTRL	0x060		Video Compression Control Register */
-+#define VIDEO_DCT_CQT_SELECTION			(0xf << 6)  // bit 6-9, bit 10 for which quantization is referred
-+#define VIDEO_DCT_HQ_CQT_SELECTION		(0xf << 27) // bit 27-30, bit 31 for which quantization is referred
-+
-+#define VIDEO_HQ_DCT_LUM(x)			((x) << 27)
-+#define VIDEO_GET_HQ_DCT_LUM(x)			(((x) >> 27) & 0x1f)
-+#define VIDEO_HQ_DCT_CHROM(x)			((x) << 22)
-+#define VIDEO_GET_HQ_DCT_CHROM(x)			(((x) >> 22) & 0x1f)
-+#define VIDEO_HQ_DCT_MASK			(0x3ff << 22)
-+#define VIDEO_DCT_HUFFMAN_ENCODE(x)			((x) << 20)
-+#define VIDEO_DCT_RESET				BIT(17)
-+#define VIDEO_HQ_ENABLE				BIT(16)
-+#define VIDEO_GET_HQ_ENABLE(x)			(((x) >> 16) & 0x1)
-+#define VIDEO_DCT_LUM(x)			((x) << 11)
-+#define VIDEO_GET_DCT_LUM(x)			(((x) >> 11) & 0x1f)
-+#define VIDEO_DCT_CHROM(x)			((x) << 6)
-+#define VIDEO_GET_DCT_CHROM(x)			(((x) >> 6) & 0x1f)
-+#define VIDEO_DCT_MASK				(0x3ff << 6)
-+#define VIDEO_ENCRYP_ENABLE			BIT(5)
-+#define VIDEO_COMPRESS_QUANTIZ_MODE			BIT(2)
-+#define VIDEO_4COLOR_VQ_ENCODE			BIT(1)
-+#define VIDEO_DCT_ONLY_ENCODE				(1)
-+#define VIDEO_DCT_VQ_MASK					(0x3)
-+
-+#define VIDEO_CTRL_RC4_TEST_MODE		BIT(9)
-+#define VIDEO_CTRL_RC4_RST		BIT(8)
-+
-+#define VIDEO_CTRL_ADDRESS_MAP_MULTI_JPEG	(0x3 << 30)
-+
-+#define VIDEO_CTRL_DWN_SCALING_MASK		(0x3 << 4)
-+#define VIDEO_CTRL_DWN_SCALING_ENABLE_LINE_BUFFER		BIT(4)
-+
-+/* AST_VIDEO_INT_EN			0x304		Video interrupt Enable */
-+/* AST_VIDEO_INT_STS		0x308		Video interrupt status */
-+#define VM_COMPRESS_COMPLETE			BIT(17)
-+#define VM_CAPTURE_COMPLETE			BIT(16)
-+
-+#define VIDEO_FRAME_COMPLETE			BIT(5)
-+#define VIDEO_MODE_DETECT_RDY			BIT(4)
-+#define VIDEO_COMPRESS_COMPLETE			BIT(3)
-+#define VIDEO_COMPRESS_PKT_COMPLETE			BIT(2)
-+#define VIDEO_CAPTURE_COMPLETE			BIT(1)
-+#define VIDEO_MODE_DETECT_WDT			BIT(0)
-+
-+/***********************************************************************/
-+struct ast_capture_mode {
-+	u8	engine_idx;					//set 0: engine 0, engine 1
-+	u8	differential;					//set 0: full, 1:diff frame
-+	u8	mode_change;				//get 0: no, 1:change
-+};
-+
-+struct ast_compression_mode {
-+	u8	engine_idx;					//set 0: engine 0, engine 1
-+	u8	mode_change;				//get 0: no, 1:change
-+	u32	total_size;					//get
-+	u32	block_count;					//get
-+};
-+
-+/***********************************************************************/
-+struct INTERNAL_MODE {
-+	u16 HorizontalActive;
-+	u16 VerticalActive;
-+	u16 RefreshRateIndex;
-+	u32 PixelClock;
-+};
-+
-+// ioctl functions
-+void ioctl_get_video_engine_config(struct VideoConfig  *pVideoConfig, struct AstRVAS *pAstRVAS);
-+void ioctl_set_video_engine_config(struct VideoConfig  *pVideoConfig, struct AstRVAS *pAstRVAS);
-+void ioctl_get_video_engine_data(struct MultiJpegConfig *pArrayMJConfig, struct AstRVAS *pAstRVAS,  phys_addr_t dwPhyStreamAddress);
-+void ioctl_get_video_engine_data_2700(struct MultiJpegConfig *pArrayMJConfig, struct AstRVAS *pAstRVAS, dma_addr_t dwPhyStreamAddress);
-+
-+//local functions
-+irqreturn_t ast_video_isr(int this_irq, void *dev_id);
-+int video_engine_reserveMem(struct AstRVAS *pAstRVAS);
-+void enable_video_interrupt(struct AstRVAS *pAstRVAS);
-+void disable_video_interrupt(struct AstRVAS *pAstRVAS);
-+void video_set_Window(struct AstRVAS *pAstRVAS);
-+int free_video_engine_memory(struct AstRVAS *pAstRVAS);
-+void video_ctrl_init(struct AstRVAS *pAstRVAS);
-+void video_engine_rc4Reset(struct AstRVAS *pAstRVAS);
-+void set_direct_mode(struct AstRVAS *pAstRVAS);
-+
-+#endif // __VIDEO_ENGINE_H__
-diff --git a/drivers/soc/aspeed/rvas/video_ioctl.h b/drivers/soc/aspeed/rvas/video_ioctl.h
-new file mode 100644
-index 000000000..36443294f
---- /dev/null
-+++ b/drivers/soc/aspeed/rvas/video_ioctl.h
-@@ -0,0 +1,275 @@
-+/* SPDX-License-Identifier: GPL-2.0+ */
-+/*
-+ * This file is part of the ASPEED Linux Device Driver for ASPEED Baseboard Management Controller.
-+ * Refer to the README file included with this package for driver version and adapter compatibility.
-+ *
-+ * Copyright (C) 2019-2021 ASPEED Technology Inc. All rights reserved.
-+ *
-+ */
-+
-+#ifndef _VIDEO_IOCTL_H
-+#define _VIDEO_IOCTL_H
-+
-+#include <linux/types.h>
-+
-+#define RVAS_MAGIC				('b')
-+#define CMD_IOCTL_TURN_LOCAL_MONITOR_ON		_IOR(RVAS_MAGIC, IOCTL_TURN_LOCAL_MONITOR_ON, struct RvasIoctl)
-+#define CMD_IOCTL_TURN_LOCAL_MONITOR_OFF	_IOR(RVAS_MAGIC, IOCTL_TURN_LOCAL_MONITOR_OFF, struct RvasIoctl)
-+#define CMD_IOCTL_IS_LOCAL_MONITOR_ENABLED	_IOR(RVAS_MAGIC, IOCTL_IS_LOCAL_MONITOR_ENABLED, struct RvasIoctl)
-+#define CMD_IOCTL_GET_VIDEO_GEOMETRY		_IOWR(RVAS_MAGIC, IOCTL_GET_VIDEO_GEOMETRY, struct RvasIoctl)
-+#define CMD_IOCTL_WAIT_FOR_VIDEO_EVENT		_IOWR(RVAS_MAGIC, IOCTL_WAIT_FOR_VIDEO_EVENT, struct RvasIoctl)
-+#define CMD_IOCTL_GET_GRC_REGIESTERS		_IOWR(RVAS_MAGIC, IOCTL_GET_GRC_REGIESTERS, struct RvasIoctl)
-+#define CMD_IOCTL_READ_SNOOP_MAP		_IOWR(RVAS_MAGIC, IOCTL_READ_SNOOP_MAP, struct RvasIoctl)
-+#define CMD_IOCTL_READ_SNOOP_AGGREGATE		_IOWR(RVAS_MAGIC, IOCTL_READ_SNOOP_AGGREGATE, struct RvasIoctl)
-+#define CMD_IOCTL_FETCH_VIDEO_TILES		_IOWR(RVAS_MAGIC, IOCTL_FETCH_VIDEO_TILES, struct RvasIoctl)
-+#define CMD_IOCTL_FETCH_VIDEO_SLICES		_IOWR(RVAS_MAGIC, IOCTL_FETCH_VIDEO_SLICES, struct RvasIoctl)
-+#define CMD_IOCTL_RUN_LENGTH_ENCODE_DATA	_IOWR(RVAS_MAGIC, IOCTL_RUN_LENGTH_ENCODE_DATA, struct RvasIoctl)
-+#define CMD_IOCTL_FETCH_TEXT_DATA		_IOWR(RVAS_MAGIC, IOCTL_FETCH_TEXT_DATA, struct RvasIoctl)
-+#define CMD_IOCTL_FETCH_MODE13_DATA		_IOWR(RVAS_MAGIC, IOCTL_FETCH_MODE13_DATA, struct RvasIoctl)
-+#define CMD_IOCTL_NEW_CONTEXT			_IOWR(RVAS_MAGIC, IOCTL_NEW_CONTEXT, struct RvasIoctl)
-+#define CMD_IOCTL_DEL_CONTEXT			_IOWR(RVAS_MAGIC, IOCTL_DEL_CONTEXT, struct RvasIoctl)
-+#define CMD_IOCTL_ALLOC				_IOWR(RVAS_MAGIC, IOCTL_ALLOC, struct RvasIoctl)
-+#define CMD_IOCTL_FREE				_IOWR(RVAS_MAGIC, IOCTL_FREE, struct RvasIoctl)
-+#define CMD_IOCTL_SET_TSE_COUNTER		_IOWR(RVAS_MAGIC, IOCTL_SET_TSE_COUNTER, struct RvasIoctl)
-+#define CMD_IOCTL_GET_TSE_COUNTER		_IOWR(RVAS_MAGIC, IOCTL_GET_TSE_COUNTER, struct RvasIoctl)
-+#define CMD_IOCTL_VIDEO_ENGINE_RESET		_IOWR(RVAS_MAGIC, IOCTL_VIDEO_ENGINE_RESET, struct RvasIoctl)
-+//jpeg
-+#define CMD_IOCTL_SET_VIDEO_ENGINE_CONFIG	_IOW(RVAS_MAGIC, IOCTL_SET_VIDEO_ENGINE_CONFIG, struct VideoConfig*)
-+#define CMD_IOCTL_GET_VIDEO_ENGINE_CONFIG	_IOW(RVAS_MAGIC, IOCTL_GET_VIDEO_ENGINE_CONFIG, struct VideoConfig*)
-+#define CMD_IOCTL_GET_VIDEO_ENGINE_DATA		_IOWR(RVAS_MAGIC, IOCTL_GET_VIDEO_ENGINE_DATA, struct MultiJpegConfig*)
-+
-+enum  HARD_WARE_ENGINE_IOCTL {
-+	IOCTL_TURN_LOCAL_MONITOR_ON = 20, //REMOTE VIDEO GENERAL IOCTL
-+	IOCTL_TURN_LOCAL_MONITOR_OFF,
-+	IOCTL_IS_LOCAL_MONITOR_ENABLED,
-+
-+	IOCTL_GET_VIDEO_GEOMETRY = 40, // REMOTE VIDEO
-+	IOCTL_WAIT_FOR_VIDEO_EVENT,
-+	IOCTL_GET_GRC_REGIESTERS,
-+	IOCTL_READ_SNOOP_MAP,
-+	IOCTL_READ_SNOOP_AGGREGATE,
-+	IOCTL_FETCH_VIDEO_TILES,
-+	IOCTL_FETCH_VIDEO_SLICES,
-+	IOCTL_RUN_LENGTH_ENCODE_DATA,
-+	IOCTL_FETCH_TEXT_DATA,
-+	IOCTL_FETCH_MODE13_DATA,
-+	IOCTL_NEW_CONTEXT,
-+	IOCTL_DEL_CONTEXT,
-+	IOCTL_ALLOC,
-+	IOCTL_FREE,
-+	IOCTL_SET_TSE_COUNTER,
-+	IOCTL_GET_TSE_COUNTER,
-+	IOCTL_VIDEO_ENGINE_RESET,
-+	IOCTL_SET_VIDEO_ENGINE_CONFIG,
-+	IOCTL_GET_VIDEO_ENGINE_CONFIG,
-+	IOCTL_GET_VIDEO_ENGINE_DATA,
-+};
-+
-+enum GraphicsModeType {
-+	InvalidMode = 0, TextMode = 1, VGAGraphicsMode = 2, AGAGraphicsMode = 3
-+};
-+
-+enum RVASStatus {
-+	SuccessStatus = 0,
-+	GenericError = 1,
-+	MemoryAllocError = 2,
-+	InvalidMemoryHandle = 3,
-+	CannotMapMemory = 4,
-+	CannotUnMapMemory = 5,
-+	TimedOut = 6,
-+	InvalidContextHandle = 7,
-+	CaptureTimedOut = 8,
-+	CompressionTimedOut = 9,
-+	HostSuspended
-+};
-+
-+enum SelectedByteMode {
-+	AllBytesMode = 0,
-+	SkipMode = 1,
-+	PlanarToPackedMode,
-+	PackedToPackedMode,
-+	LowByteMode,
-+	MiddleByteMode,
-+	TopByteMode
-+};
-+
-+enum DataProccessMode {
-+	NormalTileMode = 0,
-+	FourBitPlanarMode = 1,
-+	FourBitPackedMode = 2,
-+	AttrMode = 3,
-+	AsciiOnlyMode = 4,
-+	FontFetchMode = 5,
-+	SplitByteMode = 6
-+};
-+
-+enum ResetEngineMode {
-+	ResetAll = 0,
-+	ResetRvasEngine = 1,
-+	ResetVeEngine = 2
-+};
-+
-+struct VideoGeometry {
-+	u16 wScreenWidth;
-+	u16 wScreenHeight;
-+	u16 wStride;
-+	u8 byBitsPerPixel;
-+	u8 byModeID;
-+	enum GraphicsModeType gmt;
-+};
-+
-+struct EventMap {
-+	u32 bPaletteChanged :1;
-+	u32 bATTRChanged :1;
-+	u32 bSEQChanged :1;
-+	u32 bGCTLChanged :1;
-+	u32 bCRTCChanged :1;
-+	u32 bCRTCEXTChanged :1;
-+	u32 bPLTRAMChanged :1;
-+	u32 bXCURCOLChanged :1;
-+	u32 bXCURCTLChanged :1;
-+	u32 bXCURPOSChanged :1;
-+	u32 bDoorbellA :1;
-+	u32 bDoorbellB :1;
-+	u32 bGeometryChanged :1;
-+	u32 bSnoopChanged :1;
-+	u32 bTextFontChanged :1;
-+	u32 bTextATTRChanged :1;
-+	u32 bTextASCIIChanged :1;
-+};
-+
-+struct FetchMap {
-+	//in parameters
-+	bool bEnableRLE;
-+	u8 bTextAlignDouble; // 0 - 8 byte, 1 - 16 byte
-+	u8 byRLETripletCode;
-+	u8 byRLERepeatCode;
-+	enum DataProccessMode dpm;
-+	//out parameters
-+	u32 dwFetchSize;
-+	u32 dwFetchRLESize;
-+	u32 dwCheckSum;
-+	bool bRLEFailed;
-+	u8 rsvd[3];
-+};
-+
-+struct SnoopAggregate {
-+	u64 qwRow;
-+	u64 qwCol;
-+};
-+
-+struct FetchRegion {
-+	u16 wTopY;
-+	u16 wLeftX;
-+	u16 wBottomY;
-+	u16 wRightX;
-+};
-+
-+struct FetchOperation {
-+	struct FetchRegion fr;
-+	enum SelectedByteMode sbm;
-+	u32 dwFetchSize;
-+	u32 dwFetchRLESize;
-+	u32 dwCheckSum;
-+	bool bRLEFailed;
-+	bool bEnableRLE;
-+	u8 byRLETripletCode;
-+	u8 byRLERepeatCode;
-+	u8 byVGATextAlignment; //0-8bytes, 1-16bytes.
-+	u8 rsvd[3];
-+};
-+
-+struct FetchVideoTilesArg {
-+	struct VideoGeometry vg;
-+	u32 dwTotalOutputSize;
-+	u32 cfo;
-+	struct FetchOperation pfo[4];
-+};
-+
-+struct FetchVideoSlicesArg {
-+	struct VideoGeometry vg;
-+	u32 dwSlicedSize;
-+	u32 dwSlicedRLESize;
-+	u32 dwCheckSum;
-+	bool bEnableRLE;
-+	bool bRLEFailed;
-+	u8 byRLETripletCode;
-+	u8 byRLERepeatCode;
-+	u8 cBuckets;
-+	u8 rsvd[3];
-+	u8 abyBitIndexes[24];
-+	u32 cfr;
-+	struct FetchRegion pfr[4];
-+};
-+
-+struct RVASBuffer {
-+	void *pv;
-+	size_t cb;
-+};
-+
-+struct RvasIoctl {
-+	enum RVASStatus rs;
-+	void *rc;
-+	struct RVASBuffer rvb;
-+	void *rmh;
-+	void *rmh1;
-+	void *rmh2;
-+	u32 rmh_mem_size;
-+	u32 rmh1_mem_size;
-+	u32 rmh2_mem_size;
-+	struct VideoGeometry vg;
-+	struct EventMap em;
-+	struct SnoopAggregate sa;
-+	union {
-+		u32 tse_counter;
-+		u32 req_mem_size;
-+		u32 encode;
-+		u32 time_out;
-+	};
-+	u32 rle_len;  // RLE Length
-+	u32 rle_checksum;
-+	struct FetchMap tfm;
-+	u8 flag;
-+	u8 lms;
-+	u8 resetMode;
-+	u8 rsvd;
-+};
-+
-+//
-+// Video Engine
-+//
-+
-+#define MAX_MULTI_FRAME_CT (32)
-+
-+struct VideoConfig {
-+	u8 engine;					//0: engine 0 - normal engine, engine 1 - VM legacy engine
-+	u8 compression_mode;	//0:DCT, 1:DCT_VQ mix VQ-2 color, 2:DCT_VQ mix VQ-4 color		9:
-+	u8 compression_format;	//0:ASPEED 1:JPEG
-+	u8 capture_format;		//0:CCIR601-2 YUV, 1:JPEG YUV, 2:RGB for ASPEED mode only, 3:Gray
-+	u8 rc4_enable;				//0:disable 1:enable
-+	u8 YUV420_mode;			//0:YUV444, 1:YUV420
-+	u8 Visual_Lossless;
-+	u8 Y_JPEGTableSelector;
-+	u8 AdvanceTableSelector;
-+	u8 AutoMode;
-+	u8 rsvd[2];
-+	enum RVASStatus rs;
-+};
-+
-+struct MultiJpegFrame {
-+	u32 dwSizeInBytes;			// Image size in bytes
-+	u32 dwOffsetInBytes;			// Offset in bytes
-+	u16 wXPixels;					// In: X coordinate
-+	u16 wYPixels;					// In: Y coordinate
-+	u16 wWidthPixels;				// In: Width for Fetch
-+	u16 wHeightPixels;			// In: Height for Fetch
-+};
-+
-+struct MultiJpegConfig {
-+	unsigned char multi_jpeg_frames;				// frame count
-+	struct MultiJpegFrame frame[MAX_MULTI_FRAME_CT];	// The Multi Frames
-+	void *aStreamHandle;
-+	enum RVASStatus rs;
-+};
-+
-+#endif // _VIDEO_IOCTL_H
-diff --git a/drivers/soc/aspeed/rvas/video_main.c b/drivers/soc/aspeed/rvas/video_main.c
-new file mode 100644
-index 000000000..e8ee1cde7
---- /dev/null
-+++ b/drivers/soc/aspeed/rvas/video_main.c
-@@ -0,0 +1,1850 @@
-+// SPDX-License-Identifier: GPL-2.0+
-+/*
-+ * File Name     : video_main.c
-+ * Description   : AST2600 RVAS hardware engines
-+ *
-+ * Copyright (C) ASPEED Technology Inc.
-+ *
-+ * 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; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/version.h>
-+#include <linux/interrupt.h>
-+#include <linux/device.h>
-+#include <linux/reset.h>
-+#include <asm/uaccess.h>
-+#include <linux/string.h>
-+#include <linux/errno.h>
-+#include <linux/fs.h>
-+#include <linux/platform_device.h>
-+#include <linux/cdev.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/miscdevice.h>
-+#include <linux/slab.h>
-+#include <linux/wait.h>
-+#include <linux/sched.h>
-+#include <linux/of.h>
-+#include <linux/of_address.h>
-+#include <linux/mm.h>
-+#include <linux/of_reserved_mem.h>
-+#include <linux/regmap.h>
-+#include <linux/mfd/syscon.h>
-+#include <linux/clk.h>
-+
-+#include "video_ioctl.h"
-+#include "hardware_engines.h"
-+#include "video.h"
-+#include "video_debug.h"
-+#include "video_engine.h"
-+
-+#define TEST_GRCE_DETECT_RESOLUTION_CHG
-+
-+static long video_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
-+static int video_open(struct inode *inode, struct file *file);
-+static int video_release(struct inode *inode, struct file *file);
-+static irqreturn_t fge_handler(int irq, void *dev_id);
-+static void video_off(struct AstRVAS *pAstRVAS);
-+static void video_on(struct AstRVAS *pAstRVAS);
-+
-+static void video_os_init_sleep_struct(struct Video_OsSleepStruct *Sleep);
-+static void video_ss_wakeup_on_timeout(struct Video_OsSleepStruct *Sleep);
-+static void enable_rvas_engines(struct AstRVAS *pAstRVAS);
-+static void video_engine_init(struct AstRVAS *pAstRVAS);
-+static void rvas_init(struct AstRVAS *pAstRVAS);
-+static void reset_rvas_engine(struct AstRVAS *pAstRVAS);
-+static void reset_video_engine(struct AstRVAS *pAstRVAS);
-+static void set_FBInfo_size(struct AstRVAS *pAstRVAS, void __iomem *mcr_base);
-+
-+static long video_os_sleep_on_timeout(struct Video_OsSleepStruct *Sleep, u8 *Var, long msecs);
-+
-+static struct AstRVAS *file_ast_rvas(struct file *file)
-+{
-+	return container_of(file->private_data, struct AstRVAS, rvas_dev);
-+}
-+
-+static long video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-+{
-+	int iResult = 0;
-+	struct RvasIoctl ri;
-+	struct VideoConfig video_config;
-+	struct MultiJpegConfig multi_jpeg;
-+	u8 bVideoCmd = 0;
-+	dma_addr_t dw_phys = 0;
-+	struct AstRVAS *pAstRVAS = file_ast_rvas(file);
-+
-+	VIDEO_DBG("Start\n");
-+	VIDEO_DBG("pAstRVAS: 0x%p\n", pAstRVAS);
-+	memset(&ri, 0, sizeof(ri));
-+
-+	if (cmd != CMD_IOCTL_SET_VIDEO_ENGINE_CONFIG &&
-+	    cmd != CMD_IOCTL_GET_VIDEO_ENGINE_CONFIG &&
-+	    cmd != CMD_IOCTL_GET_VIDEO_ENGINE_DATA) {
-+		if (raw_copy_from_user(&ri, (void *)arg, sizeof(struct RvasIoctl))) {
-+			dev_err(pAstRVAS->pdev, "Copy from user buffer Failed\n");
-+			return -EINVAL;
-+		}
-+
-+		ri.rs = SuccessStatus;
-+		bVideoCmd = 0;
-+	} else {
-+		bVideoCmd = 1;
-+	}
-+
-+	VIDEO_DBG(" Command = 0x%x\n", cmd);
-+
-+	switch (cmd) {
-+	case CMD_IOCTL_TURN_LOCAL_MONITOR_ON:
-+		if (pAstRVAS->config->version == 7)
-+			ioctl_update_lms_2700(0x1, pAstRVAS);
-+		else
-+			ioctl_update_lms(0x1, pAstRVAS);
-+		break;
-+
-+	case CMD_IOCTL_TURN_LOCAL_MONITOR_OFF:
-+		if (pAstRVAS->config->version == 7)
-+			ioctl_update_lms_2700(0x0, pAstRVAS);
-+		else
-+			ioctl_update_lms(0x0, pAstRVAS);
-+		break;
-+
-+	case CMD_IOCTL_IS_LOCAL_MONITOR_ENABLED:
-+		u32 status;
-+
-+		if (pAstRVAS->config->version == 7)
-+			status = ioctl_get_lm_status_2700(pAstRVAS);
-+		else
-+			status = ioctl_get_lm_status(pAstRVAS);
-+
-+		if (status)
-+			ri.lms = 0x1;
-+		else
-+			ri.lms = 0x0;
-+		break;
-+
-+	case CMD_IOCTL_GET_VIDEO_GEOMETRY:
-+		VIDEO_DBG(" Command CMD_IOCTL_GET_VIDEO_GEOMETRY\n");
-+		ioctl_get_video_geometry(&ri, pAstRVAS);
-+		break;
-+
-+	case CMD_IOCTL_WAIT_FOR_VIDEO_EVENT:
-+		VIDEO_DBG(" Command CMD_IOCTL_WAIT_FOR_VIDEO_EVENT\n");
-+		ioctl_wait_for_video_event(&ri, pAstRVAS);
-+		break;
-+
-+	case CMD_IOCTL_GET_GRC_REGIESTERS:
-+		VIDEO_DBG(" Command CMD_IOCTL_GET_GRC_REGIESTERS\n");
-+		ioctl_get_grc_register(&ri, pAstRVAS);
-+		break;
-+
-+	case CMD_IOCTL_READ_SNOOP_MAP:
-+		VIDEO_DBG(" Command CMD_IOCTL_READ_SNOOP_MAP\n");
-+		ioctl_read_snoop_map(&ri, pAstRVAS);
-+		break;
-+
-+	case CMD_IOCTL_READ_SNOOP_AGGREGATE:
-+		VIDEO_DBG(" Command CMD_IOCTL_READ_SNOOP_AGGREGATE\n");
-+		ioctl_read_snoop_aggregate(&ri, pAstRVAS);
-+		break;
-+
-+	case CMD_IOCTL_FETCH_VIDEO_TILES: ///
-+		VIDEO_DBG("CMD_IOCTL_FETCH_VIDEO_TILES\n");
-+		ioctl_fetch_video_tiles(&ri, pAstRVAS);
-+		break;
-+
-+	case CMD_IOCTL_FETCH_VIDEO_SLICES:
-+		VIDEO_DBG(" Command CMD_IOCTL_FETCH_VIDEO_SLICES\n");
-+		ioctl_fetch_video_slices(&ri, pAstRVAS);
-+		break;
-+
-+	case CMD_IOCTL_RUN_LENGTH_ENCODE_DATA:
-+		VIDEO_DBG(" Command CMD_IOCTL_RUN_LENGTH_ENCODE_DATA\n");
-+		ioctl_run_length_encode_data(&ri, pAstRVAS);
-+		break;
-+
-+	case CMD_IOCTL_FETCH_TEXT_DATA:
-+		VIDEO_DBG(" Command CMD_IOCTL_FETCH_TEXT_DATA\n");
-+		ioctl_fetch_text_data(&ri, pAstRVAS);
-+		break;
-+
-+	case CMD_IOCTL_FETCH_MODE13_DATA:
-+		VIDEO_DBG(" Command CMD_IOCTL_FETCH_MODE13_DATA\n");
-+		ioctl_fetch_mode_13_data(&ri, pAstRVAS);
-+		break;
-+
-+	case CMD_IOCTL_ALLOC:
-+		VIDEO_DBG(" Command CMD_IOCTL_ALLOC\n");
-+		ioctl_alloc(file, &ri, pAstRVAS);
-+		break;
-+
-+	case CMD_IOCTL_FREE:
-+		VIDEO_DBG(" Command CMD_IOCTL_FREE\n");
-+		ioctl_free(&ri, pAstRVAS);
-+		break;
-+
-+	case CMD_IOCTL_NEW_CONTEXT:
-+		VIDEO_DBG(" Command CMD_IOCTL_NEW_CONTEXT\n");
-+		ioctl_new_context(file, &ri, pAstRVAS);
-+		break;
-+
-+	case CMD_IOCTL_DEL_CONTEXT:
-+		VIDEO_DBG(" Command CMD_IOCTL_DEL_CONTEXT\n");
-+		ioctl_delete_context(&ri, pAstRVAS);
-+		break;
-+
-+	case CMD_IOCTL_SET_TSE_COUNTER:
-+		VIDEO_DBG(" Command CMD_IOCTL_SET_TSE_COUNTER\n");
-+		ioctl_set_tse_tsicr(&ri, pAstRVAS);
-+		break;
-+
-+	case CMD_IOCTL_GET_TSE_COUNTER:
-+		VIDEO_DBG(" Command CMD_IOCTL_GET_TSE_COUNTER\n");
-+		ioctl_get_tse_tsicr(&ri, pAstRVAS);
-+		break;
-+
-+	case CMD_IOCTL_VIDEO_ENGINE_RESET:
-+		VIDEO_ENG_DBG(" Command CMD_IOCTL_VIDEO_ENGINE_RESET\n");
-+		ioctl_reset_video_engine(&ri, pAstRVAS);
-+		break;
-+	case CMD_IOCTL_GET_VIDEO_ENGINE_CONFIG:
-+		VIDEO_DBG(" Command CMD_IOCTL_GET_VIDEO_ENGINE_CONFIG\n");
-+		ioctl_get_video_engine_config(&video_config, pAstRVAS);
-+
-+		iResult = raw_copy_to_user((void *)arg, &video_config, sizeof(video_config));
-+		break;
-+	case CMD_IOCTL_SET_VIDEO_ENGINE_CONFIG:
-+		VIDEO_DBG(" Command CMD_IOCTL_SET_VIDEO_ENGINE_CONFIG\n");
-+		iResult = raw_copy_from_user(&video_config, (void *)arg, sizeof(video_config));
-+
-+		ioctl_set_video_engine_config(&video_config, pAstRVAS);
-+		break;
-+	case CMD_IOCTL_GET_VIDEO_ENGINE_DATA:
-+		VIDEO_DBG(" Command CMD_IOCTL_GET_VIDEO_ENGINE_DATA\n");
-+		iResult = raw_copy_from_user(&multi_jpeg, (void *)arg, sizeof(multi_jpeg));
-+		dw_phys = get_phys_add_rsvd_mem((u32)multi_jpeg.aStreamHandle, pAstRVAS);
-+		VIDEO_DBG("physical stream address: %#llx\n", dw_phys);
-+
-+		if (dw_phys == 0) {
-+			dev_err(pAstRVAS->pdev, "Error of getting stream buffer address\n");
-+		} else {
-+			if (pAstRVAS->config->version == 7)
-+				ioctl_get_video_engine_data_2700(&multi_jpeg, pAstRVAS, dw_phys);
-+			else
-+				ioctl_get_video_engine_data(&multi_jpeg, pAstRVAS, dw_phys);
-+		}
-+
-+		iResult = raw_copy_to_user((void *)arg, &multi_jpeg, sizeof(multi_jpeg));
-+		break;
-+	default:
-+		dev_err(pAstRVAS->pdev, "Unknown Ioctl: %#x\n", cmd);
-+		iResult = -EINVAL;
-+		break;
-+	}
-+
-+	if (!iResult && !bVideoCmd)
-+		if (raw_copy_to_user((void *)arg, &ri, sizeof(struct RvasIoctl))) {
-+			dev_err(pAstRVAS->pdev, "Copy to user buffer Failed\n");
-+			iResult = -EINVAL;
-+		}
-+
-+	return iResult;
-+}
-+
-+phys_addr_t get_phy_fb_start_address(struct AstRVAS *pAstRVAS)
-+{
-+	u32 dw_offset = get_screen_offset(pAstRVAS);
-+
-+	pAstRVAS->FBInfo.qwFBPhysStart = (pAstRVAS->config->version == 7)
-+				       ? DDR_BASE_27
-+				       : DDR_BASE;
-+	pAstRVAS->FBInfo.qwFBPhysStart += pAstRVAS->FBInfo.dwDRAMSize - pAstRVAS->FBInfo.dwVGASize + dw_offset;
-+	if (pAstRVAS->rvas_index == 1)
-+		pAstRVAS->FBInfo.qwFBPhysStart -= pAstRVAS->FBInfo.dwVGASize;
-+
-+	HW_ENG_DBG("Frame buffer start address: %#x, dram size: %#x, vga size: %#x\n",
-+		   pAstRVAS->FBInfo.qwFBPhysStart,
-+		   pAstRVAS->FBInfo.dwDRAMSize,
-+		   pAstRVAS->FBInfo.dwVGASize);
-+
-+	return pAstRVAS->FBInfo.qwFBPhysStart;
-+}
-+
-+static int video_mmap(struct file *file, struct vm_area_struct *vma)
-+{
-+	size_t size;
-+	u32 dw_index;
-+	u8 found = 0;
-+	struct AstRVAS *pAstRVAS = file_ast_rvas(file);
-+
-+	struct MemoryMapTable **pmmt = pAstRVAS->ppmmtMemoryTable;
-+
-+	size = vma->vm_end - vma->vm_start;
-+	vma->vm_private_data = pAstRVAS;
-+	VIDEO_DBG("vma->vm_start 0x%lx, vma->vm_end 0x%lx, vma->vm_pgoff=0x%llx\n",
-+		  vma->vm_start,
-+		  vma->vm_end,
-+		  vma->vm_pgoff);
-+	VIDEO_DBG("(vma->vm_pgoff << PAGE_SHIFT) = 0x%llx\n", (vma->vm_pgoff << PAGE_SHIFT));
-+	for (dw_index = 0; dw_index < MAX_NUM_MEM_TBL; ++dw_index) {
-+		if (pmmt[dw_index]) {
-+			VIDEO_DBG("index %d, phys_addr=0x%llx, virt_addr=%p, length=0x%x\n",
-+				  dw_index,
-+				  pmmt[dw_index]->mem_phys,
-+				  pmmt[dw_index]->pvVirtualAddr,
-+				  pmmt[dw_index]->dwLength);
-+			if ((vma->vm_pgoff << PAGE_SHIFT) == pmmt[dw_index]->mem_phys) {
-+				found = 1;
-+				if (size > pmmt[dw_index]->dwLength) {
-+					pr_err("required size exceed alloc size\n");
-+					return -EAGAIN;
-+				}
-+				break;
-+			}
-+		}
-+	}
-+	if (!found) {
-+		pr_err("no match mem entry\n");
-+		return -EAGAIN;
-+	}
-+
-+	vm_flags_set(vma, VM_IO);
-+	if (pAstRVAS->config->version == 7)
-+		vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
-+	else
-+		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-+
-+	if (io_remap_pfn_range(vma, vma->vm_start,
-+			       ((u32)vma->vm_pgoff), size,
-+			       vma->vm_page_prot)) {
-+		pr_err("remap_pfn_range fail at %s()\n", __func__);
-+		return -EAGAIN;
-+	}
-+
-+	return 0;
-+}
-+
-+static int video_open(struct inode *pin, struct file *file)
-+{
-+	struct AstRVAS *pAstRVAS = file_ast_rvas(file);
-+
-+	VIDEO_DBG("\n");
-+
-+	// make sure the rvas clk is running.
-+	//	 if it's already enabled, clk_enable will just return.
-+	clk_enable(pAstRVAS->rvasclk);
-+
-+	return 0;
-+}
-+
-+void free_all_mem_entries(struct AstRVAS *pAstRVAS)
-+{
-+	u32 dw_index;
-+	struct MemoryMapTable **pmmt = pAstRVAS->ppmmtMemoryTable;
-+	void *virt_add;
-+	dma_addr_t dw_phys;
-+	u32 len;
-+
-+	VIDEO_DBG("Removing mem map entries...\n");
-+	for (dw_index = 0; dw_index < MAX_NUM_MEM_TBL; ++dw_index) {
-+		if (pmmt[dw_index]) {
-+			if (pmmt[dw_index]->mem_phys) {
-+				virt_add = get_virt_add_rsvd_mem(dw_index, pAstRVAS);
-+				dw_phys = get_phys_add_rsvd_mem(dw_index, pAstRVAS);
-+				len = get_len_rsvd_mem(dw_index, pAstRVAS);
-+				dma_free_coherent(pAstRVAS->pdev, len, virt_add, dw_phys);
-+			}
-+			pmmt[dw_index]->pf = NULL;
-+			kfree(pmmt[dw_index]);
-+			pmmt[dw_index] = NULL;
-+		}
-+	}
-+}
-+
-+static int video_release(struct inode *inode, struct file *file)
-+{
-+	u32 dw_index;
-+	struct AstRVAS *pAstRVAS = file_ast_rvas(file);
-+	struct ContextTable **ppctContextTable = pAstRVAS->ppctContextTable;
-+
-+	VIDEO_DBG("Start\n");
-+
-+	free_all_mem_entries(pAstRVAS);
-+
-+	VIDEO_DBG("ppctContextTable: 0x%p\n", ppctContextTable);
-+
-+	disable_grce_tse_interrupt(pAstRVAS);
-+
-+	for (dw_index = 0; dw_index < MAX_NUM_CONTEXT; ++dw_index) {
-+		if (ppctContextTable[dw_index]) {
-+			VIDEO_DBG("Releasing Context dw_index: %u\n", dw_index);
-+			kfree(ppctContextTable[dw_index]);
-+			ppctContextTable[dw_index] = NULL;
-+		}
-+	}
-+	enable_grce_tse_interrupt(pAstRVAS);
-+	VIDEO_DBG("End\n");
-+
-+	return 0;
-+}
-+
-+static struct file_operations video_module_ops = { .compat_ioctl = video_ioctl,
-+	.unlocked_ioctl = video_ioctl, .open = video_open, .release =
-+		video_release, .mmap = video_mmap, .owner = THIS_MODULE, };
-+
-+static struct miscdevice video_misc = { .minor = MISC_DYNAMIC_MINOR, .name =
-+	RVAS_DRIVER_NAME, .fops = &video_module_ops, };
-+
-+void ioctl_new_context(struct file *file, struct RvasIoctl *pri, struct AstRVAS *pAstRVAS)
-+{
-+	struct ContextTable *pct;
-+
-+	VIDEO_DBG("Start\n");
-+	pct = get_new_context_table_entry(pAstRVAS);
-+
-+	if (pct) {
-+		pct->desc_virt = dma_alloc_coherent(pAstRVAS->pdev, PAGE_SIZE, (dma_addr_t *)&pct->desc_phy, GFP_KERNEL);
-+		if (!pct->desc_virt) {
-+			pri->rs = MemoryAllocError;
-+			return;
-+		}
-+		pri->rc = pct->rc;
-+	} else {
-+		pri->rs = MemoryAllocError;
-+	}
-+
-+	VIDEO_DBG("end: return status: %d\n", pri->rs);
-+}
-+
-+void ioctl_delete_context(struct RvasIoctl *pri, struct AstRVAS *pAstRVAS)
-+{
-+	VIDEO_DBG("Start\n");
-+
-+	VIDEO_DBG("pri->rc: %d\n", pri->rc);
-+	if (remove_context_table_entry(pri->rc, pAstRVAS)) {
-+		VIDEO_DBG("Success in removing\n");
-+		pri->rs = SuccessStatus;
-+	} else {
-+		VIDEO_DBG("Failed in removing\n");
-+		pri->rs = InvalidMemoryHandle;
-+	}
-+}
-+
-+int get_mem_entry(struct AstRVAS *pAstRVAS)
-+{
-+	int index = 0;
-+	u32 dw_size = 0;
-+	bool found = false;
-+
-+	down(&pAstRVAS->mem_sem);
-+	do {
-+		if (pAstRVAS->ppmmtMemoryTable[index]) {
-+			index++;
-+		} else {
-+			found = true;
-+			break;
-+		}
-+
-+	} while (!found && (index < MAX_NUM_MEM_TBL));
-+
-+	if (found) {
-+		dw_size = sizeof(struct MemoryMapTable);
-+		pAstRVAS->ppmmtMemoryTable[index] = kmalloc(dw_size, GFP_KERNEL);
-+		if (!pAstRVAS->ppmmtMemoryTable[index])
-+			index = -1;
-+	} else {
-+		index = -1;
-+	}
-+
-+	up(&pAstRVAS->mem_sem);
-+	return index;
-+}
-+
-+bool delete_mem_entry(const void *crmh, struct AstRVAS *pAstRVAS)
-+{
-+	bool b_ret = false;
-+	u32 dw_index = (u32)crmh;
-+
-+	VIDEO_DBG("Start, dw_index: %#x\n", dw_index);
-+
-+	down(&pAstRVAS->mem_sem);
-+	if (dw_index < MAX_NUM_MEM_TBL && pAstRVAS->ppmmtMemoryTable[dw_index]) {
-+		VIDEO_DBG("mem: 0x%p\n", pAstRVAS->ppmmtMemoryTable[dw_index]);
-+		kfree(pAstRVAS->ppmmtMemoryTable[dw_index]);
-+		pAstRVAS->ppmmtMemoryTable[dw_index] = NULL;
-+		b_ret = true;
-+	}
-+	up(&pAstRVAS->mem_sem);
-+	VIDEO_DBG("End\n");
-+	return b_ret;
-+}
-+
-+void *get_virt_add_rsvd_mem(u32 index, struct AstRVAS *pAstRVAS)
-+{
-+	if (index < MAX_NUM_MEM_TBL && pAstRVAS->ppmmtMemoryTable[index])
-+		return pAstRVAS->ppmmtMemoryTable[index]->pvVirtualAddr;
-+
-+	return 0;
-+}
-+
-+dma_addr_t get_phys_add_rsvd_mem(u32 index, struct AstRVAS *pAstRVAS)
-+{
-+	if (index < MAX_NUM_MEM_TBL && pAstRVAS->ppmmtMemoryTable[index])
-+		return pAstRVAS->ppmmtMemoryTable[index]->mem_phys;
-+
-+	return 0;
-+}
-+
-+u32 get_len_rsvd_mem(u32 index, struct AstRVAS *pAstRVAS)
-+{
-+	u32 len = 0;
-+
-+	if (index < MAX_NUM_MEM_TBL && pAstRVAS->ppmmtMemoryTable[index])
-+		len = pAstRVAS->ppmmtMemoryTable[index]->dwLength;
-+
-+	return len;
-+}
-+
-+bool virt_is_valid_rsvd_mem(u32 index, u32 size, struct AstRVAS *pAstRVAS)
-+{
-+	if (index < MAX_NUM_MEM_TBL &&
-+	    pAstRVAS->ppmmtMemoryTable[index] &&
-+	    pAstRVAS->ppmmtMemoryTable[index]->dwLength)
-+		return true;
-+
-+	return false;
-+}
-+
-+void ioctl_alloc(struct file *file, struct RvasIoctl *pri, struct AstRVAS *pAstRVAS)
-+{
-+	u32 size;
-+	dma_addr_t phys_add = 0;
-+	void *virt_add = 0;
-+	u32 index = get_mem_entry(pAstRVAS);
-+
-+	if (index < 0 || index >= MAX_NUM_MEM_TBL) {
-+		pri->rs = MemoryAllocError;
-+		return;
-+	}
-+	if (pri->req_mem_size < PAGE_SIZE)
-+		pri->req_mem_size = PAGE_SIZE;
-+
-+	size = pri->req_mem_size;
-+
-+	VIDEO_DBG("Allocating memory size: 0x%x\n", size);
-+	virt_add = dma_alloc_coherent(pAstRVAS->pdev, size, &phys_add,
-+				      GFP_KERNEL);
-+	if (virt_add) {
-+		pri->rmh = (void *)index;
-+		pri->rvb.pv = (void *)phys_add;
-+		pri->rvb.cb = size;
-+		pri->rs = SuccessStatus;
-+		pAstRVAS->ppmmtMemoryTable[index]->pf = file;
-+		pAstRVAS->ppmmtMemoryTable[index]->mem_phys = phys_add;
-+		pAstRVAS->ppmmtMemoryTable[index]->pvVirtualAddr = (void *)virt_add;
-+		pAstRVAS->ppmmtMemoryTable[index]->dwLength = size;
-+		pAstRVAS->ppmmtMemoryTable[index]->byDmaAlloc = 1;
-+	} else {
-+		if (pAstRVAS->ppmmtMemoryTable[index])
-+			delete_mem_entry((void *)index, pAstRVAS);
-+
-+		pr_err("Cannot alloc video destination data buffer\n");
-+		pri->rs = MemoryAllocError;
-+	}
-+	VIDEO_DBG("Allocated: index: 0x%x phys: %llx cb: 0x%x\n", index,
-+		  phys_add, pri->rvb.cb);
-+}
-+
-+void ioctl_free(struct RvasIoctl *pri, struct AstRVAS *pAstRVAS)
-+{
-+	void *virt_add = get_virt_add_rsvd_mem((u32)pri->rmh, pAstRVAS);
-+	dma_addr_t dw_phys = get_phys_add_rsvd_mem((u32)pri->rmh, pAstRVAS);
-+	u32 len = get_len_rsvd_mem((u32)pri->rmh, pAstRVAS);
-+
-+	VIDEO_DBG("Start\n");
-+	VIDEO_DBG("Freeing: rmh: 0x%p, phys: 0x%x, size 0x%x virt_add: 0x%p len: %u\n",
-+		  pri->rmh, dw_phys, pri->rvb.cb, virt_add, len);
-+
-+	delete_mem_entry(pri->rmh, pAstRVAS);
-+	VIDEO_DBG("After delete_mem_entry\n");
-+
-+	dma_free_coherent(pAstRVAS->pdev, len,
-+			  virt_add,
-+			  dw_phys);
-+	VIDEO_DBG("After dma_free_coherent\n");
-+}
-+
-+//AST2700 has both VGA output and DP out.
-+//AST2750 has VGA output for host node 0/VGA0 and DP output for host node 1/VGA1.
-+void ioctl_update_lms_2700(u8 lms_on, struct AstRVAS *pAstRVAS)
-+{
-+	u32 reg_scu000 = 0;
-+	u32 reg_scu448 = 0;
-+	u32 reg_scu0C0 = 0;
-+	u32 reg_scu0D0 = 0;
-+	u32 reg_dptx100 = 0;
-+	u32 reg_dptx104 = 0;
-+	u32 chip_efuse_option = 0;
-+	u32 vga_crt_disbl = 0;
-+	u32 vga_pwr_off_vdac = 0;
-+
-+	if (pAstRVAS->rvas_index == 0x0) {
-+		vga_crt_disbl = VGA0_CRT_DISBL;
-+		vga_pwr_off_vdac = VGA0_PWR_OFF_VDAC;
-+	} else {
-+		vga_crt_disbl = VGA1_CRT_DISBL;
-+		vga_pwr_off_vdac = VGA1_PWR_OFF_VDAC;
-+	}
-+
-+	regmap_read(pAstRVAS->scu, SCU000_Silicon_Revision_ID, &reg_scu000);
-+	chip_efuse_option = (reg_scu000 & 0xff00) >> 8;
-+	regmap_read(pAstRVAS->scu_io, SCU448_Pin_Ctrl, &reg_scu448);
-+	regmap_read(pAstRVAS->scu, SCU0C0_Misc1_Ctrl, &reg_scu0C0);
-+	regmap_read(pAstRVAS->scu_io, SCU0D0_Misc3_Ctrl, &reg_scu0D0);
-+	if ((chip_efuse_option == 0 && pAstRVAS->rvas_index == 0x1) || chip_efuse_option == 1) {
-+		if (pAstRVAS->dp_base) {
-+			reg_dptx100 = readl(pAstRVAS->dp_base + DPTX_Configuration_Register);
-+			reg_dptx104 = readl(pAstRVAS->dp_base + DPTX_PHY_Configuration_Register);
-+		}
-+	}
-+
-+	if (lms_on) {
-+		if ((reg_scu448 & VGAVS_ENBL_27) == 0 && (reg_scu448 & VGAHS_ENBL_27) == 0) {
-+			reg_scu448 |= (VGAVS_ENBL_27 | VGAHS_ENBL_27);
-+			regmap_write(pAstRVAS->scu_io, SCU448_Pin_Ctrl, reg_scu448);
-+		}
-+		if (reg_scu0C0 & vga_crt_disbl) {
-+			reg_scu0C0 &= ~vga_crt_disbl;
-+			regmap_write(pAstRVAS->scu, SCU0C0_Misc1_Ctrl, reg_scu0C0);
-+		}
-+		if (reg_scu0D0 & vga_pwr_off_vdac) {
-+			reg_scu0D0 &= ~vga_pwr_off_vdac;
-+			regmap_write(pAstRVAS->scu_io, SCU0D0_Misc3_Ctrl, reg_scu0D0);
-+		}
-+		//dp output
-+		if (pAstRVAS->dp_base) {
-+			reg_dptx100 |= 1 << AUX_RESETN;
-+			writel(reg_dptx100, pAstRVAS->dp_base + DPTX_Configuration_Register);
-+		}
-+	} else { //turn off
-+		if ((reg_scu448 & VGAVS_ENBL_27) == 1 || (reg_scu448 & VGAHS_ENBL_27) == 1) {
-+			reg_scu448 &= ~(VGAVS_ENBL_27 | VGAHS_ENBL_27);
-+			regmap_write(pAstRVAS->scu_io, SCU448_Pin_Ctrl, reg_scu448);
-+		}
-+		if (!(reg_scu0C0 & vga_crt_disbl)) {
-+			reg_scu0C0 |= vga_crt_disbl;
-+			regmap_write(pAstRVAS->scu, SCU0C0_Misc1_Ctrl, reg_scu0C0);
-+		}
-+		if (!(reg_scu0D0 & vga_pwr_off_vdac)) {
-+			reg_scu0D0 |= vga_pwr_off_vdac;
-+			regmap_write(pAstRVAS->scu_io, SCU0D0_Misc3_Ctrl, reg_scu0D0);
-+		}
-+		//dp output
-+		if ((chip_efuse_option == 0 && pAstRVAS->rvas_index == 0x1) || chip_efuse_option == 1) {
-+			if (pAstRVAS->dp_base) {
-+				reg_dptx100 &= ~(1 << AUX_RESETN);
-+				writel(reg_dptx100, pAstRVAS->dp_base + DPTX_Configuration_Register);
-+				reg_dptx104 &= ~(1 << DP_TX_I_MAIN_ON);
-+				writel(reg_dptx104, pAstRVAS->dp_base + DPTX_PHY_Configuration_Register);
-+			}
-+		}
-+	}
-+}
-+
-+u32 ioctl_get_lm_status_2700(struct AstRVAS *pAstRVAS)
-+{
-+	u32 reg_val = 0;
-+
-+	regmap_read(pAstRVAS->scu_io, SCU448_Pin_Ctrl, &reg_val);
-+	if ((reg_val & VGAVS_ENBL_27) == 1 || (reg_val & VGAHS_ENBL_27) == 1) {
-+		regmap_read(pAstRVAS->scu, SCU0C0_Misc1_Ctrl, &reg_val);
-+		if (pAstRVAS->rvas_index == 0x0) {
-+			if (!(reg_val & VGA0_CRT_DISBL)) {
-+				regmap_read(pAstRVAS->scu_io, SCU0D0_Misc3_Ctrl, &reg_val);
-+				if (!(reg_val & VGA0_PWR_OFF_VDAC))
-+					return 1;
-+			}
-+		} else {
-+			if (!(reg_val & VGA1_CRT_DISBL)) {
-+				regmap_read(pAstRVAS->scu_io, SCU0D0_Misc3_Ctrl, &reg_val);
-+				if (!(reg_val & VGA1_PWR_OFF_VDAC))
-+					return 1;
-+			}
-+		}
-+	}
-+	return 0;
-+}
-+
-+void ioctl_update_lms(u8 lms_on, struct AstRVAS *pAstRVAS)
-+{
-+	u32 reg_scu418 = 0;
-+	u32 reg_scu0C0 = 0;
-+	u32 reg_scu0D0 = 0;
-+	u32 reg_dptx100 = 0;
-+	u32 reg_dptx104 = 0;
-+
-+	regmap_read(pAstRVAS->scu, SCU418_Pin_Ctrl, &reg_scu418);
-+	regmap_read(pAstRVAS->scu, SCU0C0_Misc1_Ctrl, &reg_scu0C0);
-+	regmap_read(pAstRVAS->scu, SCU0D0_Misc3_Ctrl, &reg_scu0D0);
-+	if (pAstRVAS->dp_base) {
-+		reg_dptx100 = readl(pAstRVAS->dp_base + DPTX_Configuration_Register);
-+		reg_dptx104 = readl(pAstRVAS->dp_base + DPTX_PHY_Configuration_Register);
-+	}
-+
-+	if (lms_on) {
-+		if (!(reg_scu418 & (VGAVS_ENBL | VGAHS_ENBL))) {
-+			reg_scu418 |= (VGAVS_ENBL | VGAHS_ENBL);
-+			regmap_write(pAstRVAS->scu, SCU418_Pin_Ctrl, reg_scu418);
-+		}
-+		if (reg_scu0C0 & VGA_CRT_DISBL) {
-+			reg_scu0C0 &= ~VGA_CRT_DISBL;
-+			regmap_write(pAstRVAS->scu, SCU0C0_Misc1_Ctrl, reg_scu0C0);
-+		}
-+		if (reg_scu0D0 & PWR_OFF_VDAC) {
-+			reg_scu0D0 &= ~PWR_OFF_VDAC;
-+			regmap_write(pAstRVAS->scu, SCU0D0_Misc3_Ctrl, reg_scu0D0);
-+		}
-+		//dp output
-+		if (pAstRVAS->dp_base) {
-+			reg_dptx100 |= 1 << AUX_RESETN;
-+			writel(reg_dptx100, pAstRVAS->dp_base + DPTX_Configuration_Register);
-+		}
-+	} else { //turn off
-+		if (reg_scu418 & (VGAVS_ENBL | VGAHS_ENBL)) {
-+			reg_scu418 &= ~(VGAVS_ENBL | VGAHS_ENBL);
-+			regmap_write(pAstRVAS->scu, SCU418_Pin_Ctrl, reg_scu418);
-+		}
-+		if (!(reg_scu0C0 & VGA_CRT_DISBL)) {
-+			reg_scu0C0 |= VGA_CRT_DISBL;
-+			regmap_write(pAstRVAS->scu, SCU0C0_Misc1_Ctrl, reg_scu0C0);
-+		}
-+		if (!(reg_scu0D0 & PWR_OFF_VDAC)) {
-+			reg_scu0D0 |= PWR_OFF_VDAC;
-+			regmap_write(pAstRVAS->scu, SCU0D0_Misc3_Ctrl, reg_scu0D0);
-+		}
-+		//dp output
-+		if (pAstRVAS->dp_base) {
-+			reg_dptx100 &= ~(1 << AUX_RESETN);
-+			writel(reg_dptx100, pAstRVAS->dp_base + DPTX_Configuration_Register);
-+			reg_dptx104 &= ~(1 << DP_TX_I_MAIN_ON);
-+			writel(reg_dptx104, pAstRVAS->dp_base + DPTX_PHY_Configuration_Register);
-+		}
-+	}
-+}
-+
-+u32 ioctl_get_lm_status(struct AstRVAS *pAstRVAS)
-+{
-+	u32 reg_val = 0;
-+
-+	regmap_read(pAstRVAS->scu, SCU418_Pin_Ctrl, &reg_val);
-+	if (reg_val & (VGAVS_ENBL | VGAHS_ENBL)) {
-+		regmap_read(pAstRVAS->scu, SCU0C0_Misc1_Ctrl, &reg_val);
-+		if (!(reg_val & VGA_CRT_DISBL)) {
-+			regmap_read(pAstRVAS->scu, SCU0D0_Misc3_Ctrl, &reg_val);
-+			if (!(reg_val & PWR_OFF_VDAC))
-+				return 1;
-+
-+		}
-+	}
-+	return 0;
-+}
-+
-+void init_osr_es(struct AstRVAS *pAstRVAS)
-+{
-+	VIDEO_DBG("Start\n");
-+	sema_init(&pAstRVAS->mem_sem, 1);
-+	sema_init(&pAstRVAS->context_sem, 1);
-+
-+	video_os_init_sleep_struct(&pAstRVAS->video_wait);
-+
-+	memset(&pAstRVAS->tfe_engine, 0x00, sizeof(struct EngineInfo));
-+	memset(&pAstRVAS->bse_engine, 0x00, sizeof(struct EngineInfo));
-+	memset(&pAstRVAS->ldma_engine, 0x00, sizeof(struct EngineInfo));
-+	sema_init(&pAstRVAS->tfe_engine.sem, 1);
-+	sema_init(&pAstRVAS->bse_engine.sem, 1);
-+	sema_init(&pAstRVAS->ldma_engine.sem, 1);
-+	video_os_init_sleep_struct(&pAstRVAS->tfe_engine.wait);
-+	video_os_init_sleep_struct(&pAstRVAS->bse_engine.wait);
-+	video_os_init_sleep_struct(&pAstRVAS->ldma_engine.wait);
-+
-+	memset(pAstRVAS->ppctContextTable, 0x00, MAX_NUM_CONTEXT * sizeof(u32));
-+	pAstRVAS->dwMemoryTableSize = MAX_NUM_MEM_TBL;
-+	memset(pAstRVAS->ppmmtMemoryTable, 0x00, MAX_NUM_MEM_TBL * sizeof(u32));
-+	VIDEO_DBG("End\n");
-+}
-+
-+void release_osr_es(struct AstRVAS *pAstRVAS)
-+{
-+	u32 dw_index;
-+	struct ContextTable **ppctContextTable = pAstRVAS->ppctContextTable;
-+
-+	VIDEO_DBG("Removing contexts...\n");
-+	for (dw_index = 0; dw_index < MAX_NUM_CONTEXT; ++dw_index) {
-+		//if (ppctContextTable[dw_index]) {
-+		kfree(ppctContextTable[dw_index]);
-+		ppctContextTable[dw_index] = NULL;
-+		//} kfree(NULL) is safe and this check is probably not require
-+	}
-+
-+	free_all_mem_entries(pAstRVAS);
-+}
-+
-+//Retrieve a context entry
-+struct ContextTable *get_context_entry(const void *crc, struct AstRVAS *pAstRVAS)
-+{
-+	struct ContextTable *pct = NULL;
-+	u32 dw_index = (u32)crc;
-+	struct ContextTable **ppctContextTable = pAstRVAS->ppctContextTable;
-+
-+	if (dw_index < MAX_NUM_CONTEXT && ppctContextTable[dw_index] &&
-+	    ppctContextTable[dw_index]->rc == crc)
-+		pct = ppctContextTable[dw_index];
-+
-+	return pct;
-+}
-+
-+struct ContextTable *get_new_context_table_entry(struct AstRVAS *pAstRVAS)
-+{
-+	struct ContextTable *pct = NULL;
-+	u32 dw_index = 0;
-+	bool b_found = false;
-+	u32 dw_size = 0;
-+	struct ContextTable **ppctContextTable = pAstRVAS->ppctContextTable;
-+
-+	disable_grce_tse_interrupt(pAstRVAS);
-+	down(&pAstRVAS->context_sem);
-+	while (!b_found && (dw_index < MAX_NUM_CONTEXT)) {
-+		if (!(ppctContextTable[dw_index]))
-+			b_found = true;
-+		else
-+			++dw_index;
-+	}
-+	if (b_found) {
-+		dw_size = sizeof(struct ContextTable);
-+		pct = kmalloc(dw_size, GFP_KERNEL);
-+
-+		if (pct) {
-+			memset(pct, 0x00, sizeof(struct ContextTable));
-+			pct->rc = (void *)dw_index;
-+			memset(&pct->aqwSnoopMap, 0xff,
-+			       sizeof(pct->aqwSnoopMap));
-+			memset(&pct->sa, 0xff, sizeof(pct->sa));
-+			ppctContextTable[dw_index] = pct;
-+		}
-+	}
-+	up(&pAstRVAS->context_sem);
-+	enable_grce_tse_interrupt(pAstRVAS);
-+
-+	return pct;
-+}
-+
-+bool remove_context_table_entry(const void *crc, struct AstRVAS *pAstRVAS)
-+{
-+	bool b_ret = false;
-+	u32 dw_index = (u32)crc;
-+	struct ContextTable *ctx_entry;
-+
-+	VIDEO_DBG("Start\n");
-+
-+	VIDEO_DBG("dw_index: %u\n", dw_index);
-+
-+	if (dw_index < MAX_NUM_CONTEXT) {
-+		ctx_entry = pAstRVAS->ppctContextTable[dw_index];
-+		VIDEO_DBG("ctx_entry: 0x%p\n", ctx_entry);
-+
-+		if (ctx_entry) {
-+			disable_grce_tse_interrupt(pAstRVAS);
-+			if (!ctx_entry->desc_virt) {
-+				VIDEO_DBG("Removing memory, virt: 0x%p phys: %#x\n",
-+					  ctx_entry->desc_virt,
-+					  ctx_entry->desc_phy);
-+
-+				dma_free_coherent(pAstRVAS->pdev, PAGE_SIZE, ctx_entry->desc_virt, ctx_entry->desc_phy);
-+			}
-+			VIDEO_DBG("Removing memory: 0x%p\n", ctx_entry);
-+			pAstRVAS->ppctContextTable[dw_index] = NULL;
-+			kfree(ctx_entry);
-+			b_ret = true;
-+			enable_grce_tse_interrupt(pAstRVAS);
-+		}
-+	}
-+	return b_ret;
-+}
-+
-+void display_event_map(const struct EventMap *pem)
-+{
-+	VIDEO_DBG("EM:\n");
-+	VIDEO_DBG("*************************\n");
-+	VIDEO_DBG("  bATTRChanged=      %u\n", pem->bATTRChanged);
-+	VIDEO_DBG("  bCRTCChanged=      %u\n", pem->bCRTCChanged);
-+	VIDEO_DBG("  bCRTCEXTChanged=   %u\n", pem->bCRTCEXTChanged);
-+	VIDEO_DBG("  bDoorbellA=        %u\n", pem->bDoorbellA);
-+	VIDEO_DBG("  bDoorbellB=        %u\n", pem->bDoorbellB);
-+	VIDEO_DBG("  bGCTLChanged=      %u\n", pem->bGCTLChanged);
-+	VIDEO_DBG("  bGeometryChanged=  %u\n", pem->bGeometryChanged);
-+	VIDEO_DBG("  bPLTRAMChanged=    %u\n", pem->bPLTRAMChanged);
-+	VIDEO_DBG("  bPaletteChanged=   %u\n", pem->bPaletteChanged);
-+	VIDEO_DBG("  bSEQChanged=       %u\n", pem->bSEQChanged);
-+	VIDEO_DBG("  bSnoopChanged=     %u\n", pem->bSnoopChanged);
-+	VIDEO_DBG("  bTextASCIIChanged= %u\n", pem->bTextASCIIChanged);
-+	VIDEO_DBG("  bTextATTRChanged=  %u\n", pem->bTextATTRChanged);
-+	VIDEO_DBG("  bTextFontChanged=  %u\n", pem->bTextFontChanged);
-+	VIDEO_DBG("  bXCURCOLChanged=   %u\n", pem->bXCURCOLChanged);
-+	VIDEO_DBG("  bXCURCTLChanged=   %u\n", pem->bXCURCTLChanged);
-+	VIDEO_DBG("  bXCURPOSChanged=   %u\n", pem->bXCURPOSChanged);
-+	VIDEO_DBG("*************************\n");
-+}
-+
-+void ioctl_wait_for_video_event(struct RvasIoctl *ri, struct AstRVAS *pAstRVAS)
-+{
-+	union EmDwordUnion eduRequested;
-+	union EmDwordUnion eduReturned;
-+	union EmDwordUnion eduChanged;
-+	struct EventMap anEm;
-+	u32 result = 1;
-+	int iTimerRemaining = ri->time_out;
-+	unsigned long ulTimeStart, ulTimeEnd, ulElapsedTime;
-+	struct ContextTable **ppctContextTable = pAstRVAS->ppctContextTable;
-+
-+	memset(&anEm, 0x0, sizeof(struct EventMap));
-+
-+	VIDEO_DBG("Calling VideoSleepOnTimeout\n");
-+
-+	eduRequested.em = ri->em;
-+	VIDEO_DBG("eduRequested.em:\n");
-+	//display_event_map(&eduRequested.em);
-+	eduChanged.em = ppctContextTable[(int)ri->rc]->emEventReceived;
-+	VIDEO_DBG("eduChanged.em:\n");
-+	//display_event_map(&eduChanged.em);
-+
-+	// While event has not occurred and there is still time remaining for wait
-+	while (!(eduChanged.dw & eduRequested.dw) && (iTimerRemaining > 0) &&
-+	       result) {
-+		pAstRVAS->video_intr_occurred = 0;
-+		ulTimeStart = jiffies_to_msecs(jiffies);
-+		result = video_os_sleep_on_timeout(&pAstRVAS->video_wait,
-+						   &pAstRVAS->video_intr_occurred,
-+						   iTimerRemaining);
-+		ulTimeEnd = jiffies_to_msecs(jiffies);
-+		ulElapsedTime = (ulTimeEnd - ulTimeStart);
-+		iTimerRemaining -= (int)ulElapsedTime;
-+		eduChanged.em = ppctContextTable[(int)ri->rc]->emEventReceived;
-+//    VIDEO_DBG("Elapsedtime [%u], timestart[%u], timeend[%u]\n", dwElapsedTime, dwTimeStart, dwTimeEnd);
-+
-+		VIDEO_DBG("ulElapsedTime [%lu], ulTimeStart[%lu], ulTimeEnd[%lu]\n",
-+			  ulElapsedTime, ulTimeStart, ulTimeEnd);
-+		VIDEO_DBG("HZ [%ul]\n", HZ);
-+		VIDEO_DBG("result [%u], iTimerRemaining [%d]\n", result,
-+			  iTimerRemaining);
-+	}
-+
-+	if (result == 0 && ri->time_out != 0) {
-+		VIDEO_DBG("IOCTL Timedout\n");
-+		ri->rs = TimedOut;
-+		memset(&ri->em, 0x0, sizeof(struct EventMap));
-+	} else {
-+		eduChanged.em = ppctContextTable[(int)ri->rc]->emEventReceived;
-+		VIDEO_DBG("Event Received[%X]\n", eduChanged.dw);
-+		// Mask out the changes we are waiting on
-+		eduReturned.dw = eduChanged.dw & eduRequested.dw;
-+
-+		// Reset flags of changes that have been returned
-+		eduChanged.dw &= ~(eduReturned.dw);
-+		VIDEO_DBG("Event Reset[%X]\n", eduChanged.dw);
-+		ppctContextTable[(int)ri->rc]->emEventReceived = eduChanged.em;
-+
-+		// Copy changes back to ri
-+		ri->em = eduReturned.em;
-+		VIDEO_DBG("ri->em:\n");
-+		//display_event_map(&ri->em);
-+		ri->rs = SuccessStatus;
-+		VIDEO_DBG("Success [%x]\n",
-+			  eduReturned.dw);
-+	}
-+}
-+
-+static void update_context_events(struct AstRVAS *pAstRVAS,
-+				  union EmDwordUnion eduFge_status)
-+{
-+	union EmDwordUnion eduEmReceived;
-+	u32 dwIter = 0;
-+	struct ContextTable **ppctContextTable = pAstRVAS->ppctContextTable;
-+	// VIDEO_DBG("Setting up context\n");
-+	for (dwIter = 0; dwIter < MAX_NUM_CONTEXT; ++dwIter) {
-+		if (ppctContextTable[dwIter]) {
-+			//          VIDEO_DBG ("Copying EventMap to RVAS Context\n");
-+			memcpy((void *)&eduEmReceived,
-+			       (void *)&ppctContextTable[dwIter]->emEventReceived,
-+			       sizeof(union EmDwordUnion));
-+			eduEmReceived.dw |= eduFge_status.dw;
-+			memcpy((void *)&ppctContextTable[dwIter]->emEventReceived,
-+			       (void *)&eduEmReceived,
-+			       sizeof(union EmDwordUnion));
-+		}
-+	}
-+	pAstRVAS->video_intr_occurred = 1;
-+	video_ss_wakeup_on_timeout(&pAstRVAS->video_wait);
-+}
-+
-+static irqreturn_t fge_handler(int irq, void *dev_id)
-+{
-+	union EmDwordUnion eduFge_status;
-+	u32 tse_sts = 0;
-+	u32 dwGRCEStatus = 0;
-+	bool bFgeItr = false;
-+	bool bTfeItr = false;
-+	bool bBSEItr = false;
-+	bool bLdmaItr = false;
-+	bool vg_changed = false;
-+	u32 dw_screen_offset = 0;
-+	struct AstRVAS *pAstRVAS = (struct AstRVAS *)dev_id;
-+	struct VideoGeometry *cur_vg = NULL;
-+
-+	memset(&eduFge_status, 0x0, sizeof(union EmDwordUnion));
-+	bFgeItr = false;
-+
-+	// Checking for GRC status changes
-+	dwGRCEStatus = readl(pAstRVAS->grce_reg_base + GRCE_STATUS_REGISTER);
-+	if (dwGRCEStatus & GRC_INT_STS_MASK) {
-+		VIDEO_DBG("GRC Status Changed: %#x\n", dwGRCEStatus);
-+		eduFge_status.dw |= dwGRCEStatus & GRC_INT_STS_MASK;
-+		bFgeItr = true;
-+
-+		if (dwGRCEStatus & 0x30) {
-+			dw_screen_offset = get_screen_offset(pAstRVAS);
-+
-+			if (pAstRVAS->dwScreenOffset != dw_screen_offset) {
-+				pAstRVAS->dwScreenOffset = dw_screen_offset;
-+				vg_changed = true;
-+			}
-+		}
-+	}
-+	vg_changed |= video_geometry_change(pAstRVAS, dwGRCEStatus);
-+	if (vg_changed) {
-+		eduFge_status.em.bGeometryChanged = true;
-+		bFgeItr = true;
-+		set_snoop_engine(vg_changed, pAstRVAS);
-+		video_set_Window(pAstRVAS);
-+		VIDEO_DBG("Geometry has changed\n");
-+		VIDEO_DBG("Reconfigure TSE\n");
-+	}
-+	// Checking and clear TSE Intr Status
-+	tse_sts = clear_tse_interrupt(pAstRVAS);
-+
-+	if (tse_sts & TSSTS_ALL) {
-+		bFgeItr = true;
-+		if (tse_sts & (TSSTS_TC_SCREEN0 | TSSTS_TC_SCREEN1)) {
-+			eduFge_status.em.bSnoopChanged = 1;
-+			cur_vg = &pAstRVAS->current_vg;
-+
-+			if (cur_vg->gmt == TextMode) {
-+				eduFge_status.em.bTextASCIIChanged = 1;
-+				eduFge_status.em.bTextATTRChanged = 1;
-+				eduFge_status.em.bTextFontChanged = 1;
-+			}
-+		}
-+		if (tse_sts & TSSTS_ASCII) {
-+			//VIDEO_DBG("Text Ascii Changed\n");
-+			eduFge_status.em.bTextASCIIChanged = 1;
-+		}
-+
-+		if (tse_sts & TSSTS_ATTR) {
-+			//VIDEO_DBG("Text Attr Changed\n");
-+			eduFge_status.em.bTextATTRChanged = 1;
-+		}
-+
-+		if (tse_sts & TSSTS_FONT) {
-+			//VIDEO_DBG("Text Font Changed\n");
-+			eduFge_status.em.bTextFontChanged = 1;
-+		}
-+	}
-+
-+	if (clear_ldma_interrupt(pAstRVAS)) {
-+		bLdmaItr = true;
-+		pAstRVAS->ldma_engine.finished = 1;
-+		video_ss_wakeup_on_timeout(&pAstRVAS->ldma_engine.wait);
-+	}
-+
-+	if (clear_tfe_interrupt(pAstRVAS)) {
-+		bTfeItr = true;
-+		pAstRVAS->tfe_engine.finished = 1;
-+		video_ss_wakeup_on_timeout(&pAstRVAS->tfe_engine.wait);
-+	}
-+
-+	if (clear_bse_interrupt(pAstRVAS)) {
-+		bBSEItr = true;
-+		pAstRVAS->bse_engine.finished = 1;
-+		video_ss_wakeup_on_timeout(&pAstRVAS->bse_engine.wait);
-+	}
-+
-+	if (!bFgeItr && !bTfeItr && !bBSEItr && !bLdmaItr) {
-+		//VIDEO_DBG(" Unknown Interrupt\n");
-+//      VIDEO_DBG("TFE CRT [%#x].", *fge_intr);
-+		return IRQ_NONE;
-+	}
-+
-+	if (bFgeItr) {
-+		update_context_events(pAstRVAS, eduFge_status);
-+		pAstRVAS->video_intr_occurred = 1;
-+		video_ss_wakeup_on_timeout(&pAstRVAS->video_wait);
-+	}
-+
-+	return IRQ_HANDLED;
-+}
-+
-+/*Sleep and Wakeup Functions*/
-+
-+void video_os_init_sleep_struct(struct Video_OsSleepStruct *Sleep)
-+{
-+	init_waitqueue_head(&Sleep->queue);
-+	Sleep->Timeout = 0;
-+}
-+
-+void video_ss_wakeup_on_timeout(struct Video_OsSleepStruct *Sleep)
-+{
-+	/* Wakeup Process and Kill timeout handler */
-+	wake_up(&Sleep->queue);
-+}
-+
-+long video_os_sleep_on_timeout(struct Video_OsSleepStruct *Sleep, u8 *Var, long msecs)
-+{
-+	long timeout; /* In jiffies */
-+	u8 *Condition = Var;
-+	/* Sleep on the Condition for a wakeup */
-+	timeout = wait_event_interruptible_timeout(Sleep->queue,
-+						   (*Condition == 1),
-+						   msecs_to_jiffies(msecs));
-+
-+	return timeout;
-+}
-+
-+void disable_video_engines(struct AstRVAS *pAstRVAS)
-+{
-+	clk_disable(pAstRVAS->eclk);
-+	clk_disable(pAstRVAS->vclk);
-+}
-+
-+void enable_video_engines(struct AstRVAS *pAstRVAS)
-+{
-+	clk_enable(pAstRVAS->eclk);
-+	clk_enable(pAstRVAS->vclk);
-+}
-+
-+void disable_rvas_engines(struct AstRVAS *pAstRVAS)
-+{
-+	clk_disable(pAstRVAS->rvasclk);
-+}
-+
-+void enable_rvas_engines(struct AstRVAS *pAstRVAS)
-+{
-+	//  ast2600 clk enable does
-+	//	reset engine reset at SCU040
-+	//	delay 100 us
-+	//	enable clock at SCU080
-+	//	delay 10ms
-+	//	disable engine reset at SCU040
-+
-+	// ast2700 clk enable only enable clock at SCU240
-+	clk_enable(pAstRVAS->rvasclk);
-+}
-+
-+static void reset_rvas_engine(struct AstRVAS *pAstRVAS)
-+{
-+	disable_rvas_engines(pAstRVAS);
-+	if (pAstRVAS->config->version == 7)
-+		reset_control_deassert(pAstRVAS->rvas_reset);
-+	enable_rvas_engines(pAstRVAS);
-+	rvas_init(pAstRVAS);
-+}
-+
-+static void video_on(struct AstRVAS *pAstRVAS)
-+{
-+	if (pAstRVAS->config->version == 7) {
-+		// enable clk
-+		regmap_write(pAstRVAS->scu, 0x200, 0x40);
-+		mdelay(200);
-+		regmap_write(pAstRVAS->scu, 0x244, 0x2);
-+		regmap_write(pAstRVAS->scu, 0x244, 0x8);
-+		mdelay(100);
-+		regmap_write(pAstRVAS->scu, 0x204, 0x40);
-+	} else {
-+		video_engine_init(pAstRVAS);
-+	}
-+}
-+
-+static void video_off(struct AstRVAS *pAstRVAS)
-+{
-+	if (pAstRVAS->config->version == 7) {
-+		disable_video_interrupt(pAstRVAS);
-+		// stop clock
-+		regmap_write(pAstRVAS->scu, 0x240, 0x2);
-+		regmap_write(pAstRVAS->scu, 0x240, 0x8);
-+		mdelay(100);
-+	} else {
-+		disable_video_engines(pAstRVAS);
-+		enable_video_engines(pAstRVAS);
-+	}
-+}
-+
-+static void reset_video_engine(struct AstRVAS *pAstRVAS)
-+{
-+	video_off(pAstRVAS);
-+	video_on(pAstRVAS);
-+}
-+
-+void ioctl_reset_video_engine(struct RvasIoctl *ri, struct AstRVAS *pAstRVAS)
-+{
-+	enum ResetEngineMode resetMode = ri->resetMode;
-+
-+	switch (resetMode) {
-+	case  ResetAll:
-+		VIDEO_DBG("reset all engine\n");
-+		reset_rvas_engine(pAstRVAS);
-+		reset_video_engine(pAstRVAS);
-+		break;
-+	case ResetRvasEngine:
-+		VIDEO_DBG("reset rvas engine\n");
-+		reset_rvas_engine(pAstRVAS);
-+		break;
-+	case ResetVeEngine:
-+		VIDEO_DBG("reset video engine\n");
-+		reset_video_engine(pAstRVAS);
-+		break;
-+	default:
-+		dev_err(pAstRVAS->pdev, "Error resetting: no such mode: %d\n", resetMode);
-+		break;
-+	}
-+
-+	if (ri)
-+		ri->rs = SuccessStatus;
-+}
-+
-+static ssize_t rvas_reset_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-+{
-+	struct AstRVAS *pAstRVAS = dev_get_drvdata(dev);
-+	u32 val = kstrtoul(buf, 10, NULL);
-+
-+	if (val)
-+		ioctl_reset_video_engine(NULL, pAstRVAS);
-+
-+	return count;
-+}
-+
-+static DEVICE_ATTR_WO(rvas_reset);
-+
-+static struct attribute *ast_rvas_attributes[] = {
-+	&dev_attr_rvas_reset.attr,
-+	NULL
-+};
-+
-+static const struct attribute_group rvas_attribute_group = {
-+	.attrs = ast_rvas_attributes
-+};
-+
-+bool sleep_on_tfe_busy(struct AstRVAS *pAstRVAS, phys_addr_t desc_addr_phys,
-+		       u32 dwTFEControlR, u32 dwTFERleLimitor,
-+		       u32 *pdwRLESize,	u32 *pdwCheckSum)
-+{
-+	void __iomem *addrTFEDTBR = pAstRVAS->fg_reg_base + TFE_Descriptor_Table_Offset;
-+	void __iomem *addrTFECR = pAstRVAS->fg_reg_base + TFE_Descriptor_Control_Resgister;
-+	void __iomem *addrTFERleL = pAstRVAS->fg_reg_base + TFE_RLE_LIMITOR;
-+	void __iomem *addrTFERSTS = pAstRVAS->fg_reg_base + TFE_Status_Register;
-+	bool bResult = true;
-+
-+	down(&pAstRVAS->tfe_engine.sem);
-+	VIDEO_DBG("In Busy Semaphore......\n");
-+
-+	VIDEO_DBG("Before change, TFECR: %#x\n", readl(addrTFECR));
-+	writel(dwTFEControlR, addrTFECR);
-+	VIDEO_DBG("After change, TFECR: %#x\n", readl(addrTFECR));
-+	writel(dwTFERleLimitor, addrTFERleL);
-+	VIDEO_DBG("dwTFEControlR: %#x\n", dwTFEControlR);
-+	VIDEO_DBG("dwTFERleLimitor: %#x\n", dwTFERleLimitor);
-+	VIDEO_DBG("desc_addr_phys: %#x\n", desc_addr_phys);
-+	// put descriptor add to TBR and Fetch start
-+	writel((u32)desc_addr_phys, addrTFEDTBR);
-+	//wTFETiles = 1;
-+	pAstRVAS->tfe_engine.finished = 0;
-+	video_os_sleep_on_timeout(&pAstRVAS->tfe_engine.wait,
-+				  &pAstRVAS->tfe_engine.finished,
-+				  TFE_TIMEOUT_IN_MS);
-+
-+	if (!pAstRVAS->tfe_engine.finished) {
-+		dev_err(pAstRVAS->pdev, "Video TFE failed\n");
-+		writel(0x00, addrTFERSTS);
-+		pAstRVAS->tfe_engine.finished = 1;
-+		bResult = false;
-+	}
-+
-+	writel((readl(addrTFECR) & (~0x3)), addrTFECR); // Disable IRQ and Turn off TFE when done
-+	*pdwRLESize = readl(pAstRVAS->fg_reg_base + TFE_RLE_Byte_Count);
-+	*pdwCheckSum = readl(pAstRVAS->fg_reg_base + TFE_RLE_CheckSum);
-+
-+	up(&pAstRVAS->tfe_engine.sem);
-+	VIDEO_DBG("Done Busy: bResult: %d\n", bResult);
-+
-+	return bResult;
-+}
-+
-+bool sleep_on_tfe_text_busy(struct AstRVAS *pAstRVAS, phys_addr_t desc_addr_phys,
-+			    u32 dwTFEControlR, u32 dwTFERleLimitor, u32 *pdwRLESize,
-+			    u32 *pdwCheckSum)
-+{
-+	void __iomem *addrTFEDTBR = pAstRVAS->fg_reg_base + TFE_Descriptor_Table_Offset;
-+	void __iomem *addrTFECR = pAstRVAS->fg_reg_base + TFE_Descriptor_Control_Resgister;
-+	void __iomem *addrTFERleL = pAstRVAS->fg_reg_base + TFE_RLE_LIMITOR;
-+	void __iomem *addrTFERSTS = pAstRVAS->fg_reg_base + TFE_Status_Register;
-+	bool bResult = true;
-+
-+	down(&pAstRVAS->tfe_engine.sem);
-+	VIDEO_DBG("In Busy Semaphore......\n");
-+
-+	VIDEO_DBG("Before change, TFECR: %#x\n", readl(addrTFECR));
-+	writel(dwTFEControlR, addrTFECR);
-+	VIDEO_DBG("After change, TFECR: %#x\n", readl(addrTFECR));
-+	writel(dwTFERleLimitor, addrTFERleL);
-+	VIDEO_DBG("dwTFEControlR: %#x\n", dwTFEControlR);
-+	VIDEO_DBG("dwTFERleLimitor: %#x\n", dwTFERleLimitor);
-+	VIDEO_DBG("desc_addr_phys: %#x\n", desc_addr_phys);
-+	// put descriptor add to TBR and Fetch start
-+	writel((u32)desc_addr_phys, addrTFEDTBR);
-+	//wTFETiles = 1;
-+	pAstRVAS->tfe_engine.finished = 0;
-+	video_os_sleep_on_timeout(&pAstRVAS->tfe_engine.wait,
-+				  &pAstRVAS->tfe_engine.finished, TFE_TIMEOUT_IN_MS);
-+
-+	if (!pAstRVAS->tfe_engine.finished) {
-+		dev_err(pAstRVAS->pdev, "Video TFE failed\n");
-+		writel(0x00, addrTFERSTS);
-+		pAstRVAS->tfe_engine.finished = 1;
-+		bResult = false;
-+	}
-+
-+	writel((readl(addrTFECR) & (~0x3)), addrTFECR);// Disable IRQ and Turn off TFE when done
-+	writel((readl(addrTFERSTS) | 0x2), addrTFERSTS); // clear status bit
-+	*pdwRLESize = readl(pAstRVAS->fg_reg_base + TFE_RLE_Byte_Count);
-+	*pdwCheckSum = readl(pAstRVAS->fg_reg_base + TFE_RLE_CheckSum);
-+
-+	up(&pAstRVAS->tfe_engine.sem);
-+	VIDEO_DBG("Done Busy: bResult: %d\n", bResult);
-+
-+	return bResult;
-+}
-+
-+bool sleep_on_bse_busy(struct AstRVAS *pAstRVAS, phys_addr_t desc_addr_phys,
-+		       struct BSEAggregateRegister aBSEAR, u32 size)
-+{
-+	void __iomem *addrBSEDTBR = pAstRVAS->fg_reg_base + BSE_Descriptor_Table_Base_Register;
-+	void __iomem *addrBSCR = pAstRVAS->fg_reg_base + BSE_Command_Register;
-+	void __iomem *addrBSDBS = pAstRVAS->fg_reg_base + BSE_Destination_Buket_Size_Resgister;
-+	void __iomem *addrBSBPS0 = pAstRVAS->fg_reg_base + BSE_Bit_Position_Register_0;
-+	void __iomem *addrBSBPS1 = pAstRVAS->fg_reg_base + BSE_Bit_Position_Register_1;
-+	void __iomem *addrBSBPS2 = pAstRVAS->fg_reg_base + BSE_Bit_Position_Register_2;
-+	void __iomem *addrBSESSTS = pAstRVAS->fg_reg_base + BSE_Status_Register;
-+	u8 byCounter = 0;
-+	bool bResult = true;
-+
-+	down(&pAstRVAS->bse_engine.sem);
-+	pAstRVAS->bse_engine.finished = 0;
-+
-+    // Set BSE Temp buffer address, and clear lower u16
-+	writel(BSE_LMEM_Temp_Buffer_Offset << 16, addrBSCR);
-+	writel(readl(addrBSCR) | (aBSEAR.dwBSCR & 0X00000FFF), addrBSCR);
-+	writel(aBSEAR.dwBSDBS, addrBSDBS);
-+	writel(aBSEAR.adwBSBPS[0], addrBSBPS0);
-+	writel(aBSEAR.adwBSBPS[1], addrBSBPS1);
-+	writel(aBSEAR.adwBSBPS[2], addrBSBPS2);
-+
-+	writel((u32)desc_addr_phys, addrBSEDTBR);
-+
-+	while (!pAstRVAS->bse_engine.finished) {
-+		VIDEO_DBG("BSE Sleeping...\n");
-+		video_os_sleep_on_timeout(&pAstRVAS->bse_engine.wait,
-+								 &pAstRVAS->bse_engine.finished,
-+								 1000); // loop if bse timedout
-+		byCounter++;
-+		VIDEO_DBG("Back from BSE Sleeping, finished: %u\n",
-+				 pAstRVAS->bse_engine.finished);
-+
-+		if (byCounter == ENGINE_TIMEOUT_IN_SECONDS) {
-+			writel(0x00, addrBSESSTS);
-+			pAstRVAS->bse_engine.finished = 1;
-+			dev_err(pAstRVAS->pdev, "TIMEOUT::Waiting BSE\n");
-+			bResult = false;
-+		}
-+	}
-+
-+	VIDEO_DBG("*pdwBSESSTS = %#x\n", readl(addrBSESSTS));
-+	writel(readl(addrBSCR) & (~0x3), addrBSCR);
-+
-+	up(&pAstRVAS->bse_engine.sem);
-+
-+	return bResult;
-+}
-+
-+void sleep_on_ldma_busy(struct AstRVAS *pAstRVAS, phys_addr_t desc_addr_phys)
-+{
-+	void __iomem *addrLDMADTBR = pAstRVAS->fg_reg_base + LDMA_Descriptor_Table_Base_Register;
-+	void __iomem *addrLDMAControlR = pAstRVAS->fg_reg_base + LDMA_Control_Register;
-+
-+	VIDEO_DBG("In sleepONldma busy\n");
-+
-+	down(&pAstRVAS->ldma_engine.sem);
-+
-+	pAstRVAS->ldma_engine.finished = 0;
-+
-+	writel(0x83, addrLDMAControlR);// descriptor can only in LMEM FOR LDMA
-+	writel((u32)desc_addr_phys, addrLDMADTBR);
-+	VIDEO_DBG("LDMA: control [%#x]\n", readl(addrLDMAControlR));
-+	VIDEO_DBG("LDMA:  DTBR  [%#x]\n", readl(addrLDMADTBR));
-+
-+	while (!pAstRVAS->ldma_engine.finished)
-+		video_os_sleep_on_timeout(&pAstRVAS->ldma_engine.wait, (u8 *)&pAstRVAS->ldma_engine.finished, 1000); // loop if bse timedout
-+
-+	VIDEO_DBG("LDMA wake up\n");
-+	writel(readl(addrLDMAControlR) & (~0x3), addrLDMAControlR);
-+	up(&pAstRVAS->ldma_engine.sem);
-+}
-+
-+static int video_drv_get_resources(struct platform_device *pdev)
-+{
-+	int result = 0;
-+	struct resource *io_fg;
-+	struct resource *io_grc;
-+	struct resource *io_video;
-+	struct AstRVAS *pAstRVAS = platform_get_drvdata(pdev);
-+
-+	//get resources from platform
-+	io_fg = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+	VIDEO_DBG("io_fg: 0x%p\n", io_fg);
-+
-+	if (!io_fg) {
-+		dev_err(&pdev->dev, "No Frame Grabber IORESOURCE_MEM entry\n");
-+		return -ENOENT;
-+	}
-+	io_grc = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-+	VIDEO_DBG("io_grc: 0x%p\n", io_grc);
-+	if (!io_grc) {
-+		dev_err(&pdev->dev, "No GRCE IORESOURCE_MEM entry\n");
-+		return -ENOENT;
-+	}
-+	io_video = platform_get_resource(pdev, IORESOURCE_MEM, 2);
-+	VIDEO_DBG("io_video: 0x%p\n", io_video);
-+	if (!io_video) {
-+		dev_err(&pdev->dev, "No video compression IORESOURCE_MEM entry\n");
-+		return -ENOENT;
-+	}
-+
-+	//map resource by device
-+	pAstRVAS->fg_reg_base = devm_ioremap_resource(&pdev->dev, io_fg);
-+	VIDEO_DBG("fg_reg_base: %p\n", pAstRVAS->fg_reg_base);
-+	if (IS_ERR((void *)pAstRVAS->fg_reg_base)) {
-+		result = PTR_ERR((void *)pAstRVAS->fg_reg_base);
-+		dev_err(&pdev->dev, "Cannot map FG registers\n");
-+		pAstRVAS->fg_reg_base = 0;
-+		return result;
-+	}
-+	pAstRVAS->grce_reg_base = devm_ioremap_resource(&pdev->dev, io_grc);
-+	VIDEO_DBG("grce_reg_base: %p\n", pAstRVAS->grce_reg_base);
-+	if (IS_ERR((void *)pAstRVAS->grce_reg_base)) {
-+		result = PTR_ERR((void *)pAstRVAS->grce_reg_base);
-+		dev_err(&pdev->dev, "Cannot map GRC registers\n");
-+		pAstRVAS->grce_reg_base = 0;
-+		return result;
-+	}
-+	pAstRVAS->video_reg_base = devm_ioremap_resource(&pdev->dev, io_video);
-+	VIDEO_DBG("video_reg_base: %p\n", pAstRVAS->video_reg_base);
-+	if (IS_ERR((void *)pAstRVAS->video_reg_base)) {
-+		result = PTR_ERR((void *)pAstRVAS->video_reg_base);
-+		dev_err(&pdev->dev, "Cannot map video registers\n");
-+		pAstRVAS->video_reg_base = 0;
-+		return result;
-+	}
-+
-+	pAstRVAS->config = of_device_get_match_data(&pdev->dev);
-+	if (!pAstRVAS->config)
-+		return -ENODEV;
-+	return 0;
-+}
-+
-+static int video_drv_get_irqs(struct platform_device *pdev)
-+{
-+	struct AstRVAS *pAstRVAS = platform_get_drvdata(pdev);
-+
-+	pAstRVAS->irq_fge = platform_get_irq(pdev, 0);
-+	VIDEO_DBG("irq_fge: %#x\n", pAstRVAS->irq_fge);
-+	if (pAstRVAS->irq_fge < 0) {
-+		dev_err(&pdev->dev, "NO FGE irq entry\n");
-+		return -ENOENT;
-+	}
-+	pAstRVAS->irq_vga = platform_get_irq(pdev, 1);
-+	VIDEO_DBG("irq_vga: %#x\n", pAstRVAS->irq_vga);
-+		if (pAstRVAS->irq_vga < 0) {
-+			dev_err(&pdev->dev, "NO VGA irq entry\n");
-+			return -ENOENT;
-+		}
-+	pAstRVAS->irq_video = platform_get_irq(pdev, 2);
-+	VIDEO_DBG("irq_video: %#x\n", pAstRVAS->irq_video);
-+	if (pAstRVAS->irq_video < 0) {
-+		dev_err(&pdev->dev, "NO video compression entry\n");
-+		return -ENOENT;
-+	}
-+	return 0;
-+}
-+
-+static int video_drv_get_clock(struct platform_device *pdev)
-+{
-+	struct AstRVAS *pAstRVAS = platform_get_drvdata(pdev);
-+
-+	pAstRVAS->eclk = devm_clk_get(&pdev->dev, "eclk");
-+	if (IS_ERR(pAstRVAS->eclk)) {
-+		dev_err(&pdev->dev, "no eclk clock defined\n");
-+		return PTR_ERR(pAstRVAS->eclk);
-+	}
-+
-+	clk_prepare_enable(pAstRVAS->eclk);
-+
-+	pAstRVAS->vclk = devm_clk_get(&pdev->dev, "vclk");
-+	if (IS_ERR(pAstRVAS->vclk)) {
-+		dev_err(&pdev->dev, "no vclk clock defined\n");
-+		return PTR_ERR(pAstRVAS->vclk);
-+	}
-+
-+	clk_prepare_enable(pAstRVAS->vclk);
-+
-+	if (pAstRVAS->config->version == 7) {
-+		pAstRVAS->rvasclk = devm_clk_get(&pdev->dev, "rvasclk");
-+		if (IS_ERR(pAstRVAS->rvasclk)) {
-+			pAstRVAS->rvasclk = devm_clk_get(&pdev->dev, "rvas2clk");
-+			if (IS_ERR(pAstRVAS->rvasclk)) {
-+				dev_err(&pdev->dev, "no rvasclk or rvas2clk clock defined\n");
-+				return PTR_ERR(pAstRVAS->rvasclk);
-+			}
-+		}
-+	} else {
-+		pAstRVAS->rvasclk = devm_clk_get(&pdev->dev, "rvasclk-gate");
-+		if (IS_ERR(pAstRVAS->rvasclk)) {
-+			dev_err(&pdev->dev, "no rvasclk clock defined\n");
-+			return PTR_ERR(pAstRVAS->rvasclk);
-+		}
-+	}
-+	clk_prepare_enable(pAstRVAS->rvasclk);
-+	return 0;
-+}
-+
-+static int video_drv_map_irqs(struct platform_device *pdev)
-+{
-+	int result = 0;
-+	struct AstRVAS *pAstRVAS = platform_get_drvdata(pdev);
-+	//Map IRQS to handler
-+	VIDEO_DBG("Requesting IRQs, irq_fge: %d, irq_vga: %d, irq_video: %d\n",
-+			 pAstRVAS->irq_fge, pAstRVAS->irq_vga, pAstRVAS->irq_video);
-+
-+	result = devm_request_irq(&pdev->dev, pAstRVAS->irq_fge, fge_handler, 0,
-+							 dev_name(&pdev->dev), pAstRVAS);
-+	if (result) {
-+		pr_err("Error in requesting IRQ\n");
-+		pr_err("RVAS: Failed request FGE irq %d\n", pAstRVAS->irq_fge);
-+		misc_deregister(&pAstRVAS->rvas_dev);
-+		return result;
-+	}
-+
-+	result = devm_request_irq(&pdev->dev, pAstRVAS->irq_vga, fge_handler, 0,
-+				  dev_name(&pdev->dev), pAstRVAS);
-+	if (result) {
-+		pr_err("Error in requesting IRQ\n");
-+		pr_err("RVAS: Failed request vga irq %d\n", pAstRVAS->irq_vga);
-+		misc_deregister(&pAstRVAS->rvas_dev);
-+		return result;
-+	}
-+
-+	result = devm_request_irq(&pdev->dev, pAstRVAS->irq_video, ast_video_isr, 0,
-+				  dev_name(&pdev->dev), pAstRVAS);
-+	if (result) {
-+		pr_err("Error in requesting IRQ\n");
-+		pr_err("RVAS: Failed request video irq %d\n", pAstRVAS->irq_video);
-+		misc_deregister(&pAstRVAS->rvas_dev);
-+		return result;
-+	}
-+
-+	return result;
-+}
-+
-+//
-+//
-+//
-+static int video_drv_probe(struct platform_device *pdev)
-+{
-+	int result = 0;
-+	struct AstRVAS *pAstRVAS;
-+	struct regmap *sdram_scu;
-+	struct device_node *dp_node;
-+	struct device_node *edac_node;
-+	void __iomem *mcr_base;
-+
-+	pr_info("RVAS driver probe\n");
-+	pAstRVAS = devm_kzalloc(&pdev->dev, sizeof(struct AstRVAS), GFP_KERNEL);
-+	VIDEO_DBG("pAstRVAS: 0x%llx\n", pAstRVAS);
-+
-+	if (!pAstRVAS) {
-+		dev_err(pAstRVAS->pdev, "Cannot allocate device structure\n");
-+		return -ENOMEM;
-+	}
-+	dev_set_drvdata(&pdev->dev, pAstRVAS);
-+	pAstRVAS->pdev = (void *)&pdev->dev;
-+
-+	// Get resources
-+	result = video_drv_get_resources(pdev);
-+	if (result < 0) {
-+		dev_err(pAstRVAS->pdev, "video_probe: Error getting resources\n");
-+		return result;
-+	}
-+
-+	if (pAstRVAS->config->version == 7)
-+		result = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
-+	else
-+		result = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
-+
-+	if (result) {
-+		dev_err(&pdev->dev, "Failed to set DMA mask\n");
-+		of_reserved_mem_device_release(&pdev->dev);
-+	}
-+
-+	//get irqs
-+	result = video_drv_get_irqs(pdev);
-+	if (result < 0) {
-+		dev_err(pAstRVAS->pdev, "video_probe: Error getting irqs\n");
-+		return result;
-+	}
-+
-+	pAstRVAS->rvas_reset = devm_reset_control_get_by_index(&pdev->dev, 0);
-+	if (IS_ERR(pAstRVAS->rvas_reset)) {
-+		dev_err(&pdev->dev, "can't get rvas reset\n");
-+		return -ENOENT;
-+	}
-+	if (pAstRVAS->config->version == 7)
-+		reset_control_deassert(pAstRVAS->rvas_reset);
-+	pAstRVAS->video_engine_reset = devm_reset_control_get_shared_by_index(&pdev->dev, 1);
-+	if (IS_ERR(pAstRVAS->video_engine_reset)) {
-+		dev_err(&pdev->dev, "can't get video engine reset\n");
-+		return -ENOENT;
-+	}
-+
-+	//prepare video engine clock
-+	result = video_drv_get_clock(pdev);
-+	if (result < 0) {
-+		dev_err(pAstRVAS->pdev, "video_probe: Error getting clocks\n");
-+		return result;
-+	}
-+
-+	dp_node = of_find_compatible_node(NULL, NULL, "aspeed,ast2600-displayport");
-+	if (!dp_node) {
-+		dev_err(&pdev->dev, "cannot find dp node\n");
-+	} else {
-+		pAstRVAS->dp_base = of_iomap(dp_node, 0);
-+		if (!pAstRVAS->dp_base)
-+			dev_err(&pdev->dev, "failed to iomem of display port\n");
-+	}
-+	if (pAstRVAS->config->version == 7) {
-+		pAstRVAS->FBInfo.dwDRAMSize = 0x40000000; // 1GB
-+		// VGA size is fixed with 32MB
-+		pAstRVAS->FBInfo.dwVGASize = 0x2000000;
-+	} else {
-+		edac_node = of_find_compatible_node(NULL, NULL, "aspeed,ast2600-sdram-edac");
-+		if (!edac_node) {
-+			dev_err(&pdev->dev, "cannot find edac node\n");
-+		} else {
-+			mcr_base = of_iomap(edac_node, 0);
-+			if (!mcr_base)
-+				dev_err(&pdev->dev, "failed to iomem of MCR\n");
-+		}
-+
-+		set_FBInfo_size(pAstRVAS, mcr_base);
-+	}
-+	//scu
-+	if (pAstRVAS->config->version == 7) {
-+		sdram_scu = syscon_regmap_lookup_by_compatible("aspeed,ast2700-scu0");
-+		VIDEO_DBG("sdram_scu: 0x%llx\n", sdram_scu);
-+		if (IS_ERR(sdram_scu)) {
-+			dev_err(&pdev->dev, "failed to find ast2700-scu0 regmap\n");
-+			return PTR_ERR(sdram_scu);
-+		}
-+		pAstRVAS->scu = sdram_scu;
-+
-+		sdram_scu = syscon_regmap_lookup_by_compatible("aspeed,ast2700-scu1");
-+		VIDEO_DBG("sdram_scu: 0x%llx\n", sdram_scu);
-+		if (IS_ERR(sdram_scu)) {
-+			dev_err(&pdev->dev, "failed to find ast2700-scu0 regmap\n");
-+			return PTR_ERR(sdram_scu);
-+		}
-+		pAstRVAS->scu_io = sdram_scu;
-+	} else {
-+		sdram_scu = syscon_regmap_lookup_by_compatible("aspeed,ast2600-scu");
-+		VIDEO_DBG("sdram_scu: 0x%llx\n", sdram_scu);
-+		if (IS_ERR(sdram_scu)) {
-+			dev_err(&pdev->dev, "failed to find ast2600-scu regmap\n");
-+			return PTR_ERR(sdram_scu);
-+		}
-+		pAstRVAS->scu = sdram_scu;
-+	}
-+	pAstRVAS->rvas_dev = video_misc;
-+	if (pAstRVAS->config->version == 7) {
-+		if (of_alias_get_id(pdev->dev.of_node, "rvas") == 1) {
-+			pAstRVAS->rvas_index = 1;
-+			pAstRVAS->rvas_dev.name = "rvas1";
-+		} else {
-+			pAstRVAS->rvas_index = 0;
-+		}
-+	}
-+	pAstRVAS->rvas_dev.parent = &pdev->dev;
-+	result = misc_register(&pAstRVAS->rvas_dev);
-+	if (result) {
-+		pr_err("Failed in rvas misc device register (err: %d)\n", result);
-+		return result;
-+	}
-+	pr_info("Video misc minor %d\n", pAstRVAS->rvas_dev.minor);
-+	VIDEO_DBG("pdev: 0x%llx dev: 0x%llx pAstRVAS: 0x%llx rvas_dev: 0x%llx\n", pdev,
-+		  &pdev->dev, pAstRVAS, pAstRVAS->rvas_dev);
-+
-+	if (sysfs_create_group(&pdev->dev.kobj, &rvas_attribute_group)) {
-+		pr_err("Failed in creating group\n");
-+		return -1;
-+	}
-+
-+	VIDEO_DBG("Disabling interrupts...\n");
-+	disable_grce_tse_interrupt(pAstRVAS);
-+
-+	//reserve memory
-+	of_reserved_mem_device_init(&pdev->dev);
-+
-+	// map irqs to irq_handlers
-+	result = video_drv_map_irqs(pdev);
-+	if (result < 0) {
-+		dev_err(pAstRVAS->pdev, "video_probe: Error mapping irqs\n");
-+		return result;
-+	}
-+	VIDEO_DBG("After IRQ registration\n");
-+
-+	init_osr_es(pAstRVAS);
-+	rvas_init(pAstRVAS);
-+	video_engine_reserveMem(pAstRVAS);
-+	video_on(pAstRVAS);
-+
-+	pr_info("RVAS: driver successfully loaded.\n");
-+	return result;
-+}
-+
-+static void rvas_init(struct AstRVAS *pAstRVAS)
-+{
-+	VIDEO_ENG_DBG("\n");
-+
-+	reset_snoop_engine(pAstRVAS);
-+	update_video_geometry(pAstRVAS);
-+
-+	set_snoop_engine(true, pAstRVAS);
-+	enable_grce_tse_interrupt(pAstRVAS);
-+}
-+
-+static void video_engine_init(struct AstRVAS *pAstRVAS)
-+{
-+	VIDEO_ENG_DBG("\n");
-+	// video engine
-+	video_ctrl_init(pAstRVAS);
-+	video_engine_rc4Reset(pAstRVAS);
-+	set_direct_mode(pAstRVAS);
-+	video_set_Window(pAstRVAS);
-+	enable_video_interrupt(pAstRVAS);
-+}
-+
-+static int video_drv_remove(struct platform_device *pdev)
-+{
-+	struct AstRVAS *pAstRVAS = NULL;
-+
-+	VIDEO_DBG("\n");
-+	pAstRVAS = platform_get_drvdata(pdev);
-+	video_off(pAstRVAS);
-+	VIDEO_DBG("disable_grce_tse_interrupt...\n");
-+	disable_grce_tse_interrupt(pAstRVAS);
-+	disable_video_interrupt(pAstRVAS);
-+
-+	sysfs_remove_group(&pdev->dev.kobj, &rvas_attribute_group);
-+
-+	VIDEO_DBG("misc_deregister...\n");
-+	misc_deregister(&pAstRVAS->rvas_dev);
-+
-+	VIDEO_DBG("Releasing OSRes...\n");
-+	release_osr_es(pAstRVAS);
-+
-+	free_video_engine_memory(pAstRVAS);
-+	pr_info("RVAS: driver successfully unloaded.\n");
-+	return 0;
-+}
-+
-+static const u32 ast2400_dram_table[] = {
-+	0x04000000,     //64MB
-+	0x08000000,     //128MB
-+	0x10000000,     //256MB
-+	0x20000000,     //512MB
-+};
-+
-+static const u32 ast2500_dram_table[] = {
-+	0x08000000,     //128MB
-+	0x10000000,     //256MB
-+	0x20000000,     //512MB
-+	0x40000000,     //1024MB
-+};
-+
-+static const u32 ast2600_dram_table[] = {
-+	0x10000000,     //256MB
-+	0x20000000,     //512MB
-+	0x40000000,     //1024MB
-+	0x80000000,     //2048MB
-+};
-+
-+static const u32 aspeed_vga_table[] = {
-+	0x800000,       //8MB
-+	0x1000000,      //16MB
-+	0x2000000,      //32MB
-+	0x4000000,      //64MB
-+};
-+
-+static const struct aspeed_rvas_config ast2600_config = {
-+	.version = 6,
-+	.dram_table = ast2600_dram_table,
-+};
-+
-+static const struct aspeed_rvas_config ast2700_config = {
-+	.version = 7,
-+	.dram_table = ast2600_dram_table,
-+};
-+
-+static void set_FBInfo_size(struct AstRVAS *pAstRVAS, void __iomem *mcr_base)
-+{
-+	u32 reg_mcr004 = readl(mcr_base + MCR_CONF);
-+
-+	pAstRVAS->FBInfo.dwDRAMSize = pAstRVAS->config->dram_table[reg_mcr004 & 0x3];
-+
-+	pAstRVAS->FBInfo.dwVGASize = aspeed_vga_table[((reg_mcr004 & 0xC) >> 2)];
-+}
-+
-+static const struct of_device_id ast_rvas_match[] = {
-+	{ .compatible = "aspeed,ast2700-rvas", .data = &ast2700_config },
-+	{ .compatible = "aspeed,ast2600-rvas", .data = &ast2600_config },
-+	{ },
-+};
-+
-+MODULE_DEVICE_TABLE(of, ast_rvas_match);
-+
-+static struct platform_driver video_driver = {
-+	.probe = video_drv_probe,
-+	.remove = video_drv_remove,
-+	.driver = { .of_match_table = of_match_ptr(ast_rvas_match), .name =
-+		RVAS_DRIVER_NAME, .owner = THIS_MODULE, }, };
-+
-+module_platform_driver(video_driver);
-+
-+MODULE_AUTHOR("ASPEED Technology");
-+MODULE_DESCRIPTION("RVAS video driver module for AST2600");
-+MODULE_LICENSE("GPL");
 diff --git a/include/linux/aspeed-mctp.h b/include/linux/aspeed-mctp.h
-new file mode 100644
-index 000000000..7fbbf301b
+new file mode 100755
+index 000000000..143a5233d
 --- /dev/null
 +++ b/include/linux/aspeed-mctp.h
-@@ -0,0 +1,155 @@
+@@ -0,0 +1,164 @@
 +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 +/* Copyright (c) 2020 Intel Corporation */
 +
@@ -24087,6 +13017,7 @@
 +#define __LINUX_ASPEED_MCTP_H
 +
 +#include <linux/types.h>
++#include <linux/notifier.h>
 +
 +struct mctp_client;
 +struct aspeed_mctp;
@@ -24133,6 +13064,10 @@
 +	u32 size;
 +};
 +
++enum {
++	MCTP_PCIE_VDM_NOTIFY_RECV,
++};
++
 +/**
 + * aspeed_mctp_add_type_handler() - register for the given MCTP message type
 + * @client: pointer to the existing mctp_client context
@@ -24234,9 +13169,13 @@
 +void *aspeed_mctp_packet_alloc(gfp_t flags);
 +void aspeed_mctp_packet_free(void *packet);
 +
++int aspeed_mctp_register_default_handler(struct mctp_client *client);
++int mctp_pcie_vdm_register_notifier(struct notifier_block *nb);
++int mctp_pcie_vdm_unregister_notifier(struct notifier_block *nb);
++
 +#endif /* __LINUX_ASPEED_MCTP_H */
 diff --git a/include/linux/soc/aspeed/aspeed-otp.h b/include/linux/soc/aspeed/aspeed-otp.h
-new file mode 100644
+new file mode 100755
 index 000000000..17695ea40
 --- /dev/null
 +++ b/include/linux/soc/aspeed/aspeed-otp.h
@@ -24253,7 +13192,7 @@
 +
 +#endif /* _LINUX_ASPEED_OTP_H */
 diff --git a/include/trace/events/xdma.h b/include/trace/events/xdma.h
-new file mode 100644
+new file mode 100755
 index 000000000..bf515ad3d
 --- /dev/null
 +++ b/include/trace/events/xdma.h
@@ -24398,7 +13337,7 @@
 +
 +#include <trace/define_trace.h>
 diff --git a/include/uapi/linux/aspeed-mctp.h b/include/uapi/linux/aspeed-mctp.h
-new file mode 100644
+new file mode 100755
 index 000000000..3bac75294
 --- /dev/null
 +++ b/include/uapi/linux/aspeed-mctp.h
@@ -24540,7 +13479,7 @@
 +
 +#endif /* _UAPI_LINUX_ASPEED_MCTP_H */
 diff --git a/include/uapi/linux/aspeed-xdma.h b/include/uapi/linux/aspeed-xdma.h
-new file mode 100644
+new file mode 100755
 index 000000000..3a3646fd1
 --- /dev/null
 +++ b/include/uapi/linux/aspeed-xdma.h
@@ -24587,53 +13526,8 @@
 +};
 +
 +#endif /* _UAPI_LINUX_ASPEED_XDMA_H_ */
-diff --git a/include/uapi/linux/otp_ast2600.h b/include/uapi/linux/otp_ast2600.h
-new file mode 100644
-index 000000000..f19eac305
---- /dev/null
-+++ b/include/uapi/linux/otp_ast2600.h
-@@ -0,0 +1,39 @@
-+/* SPDX-License-Identifier: GPL-2.0-or-later WITH Linux-syscall-note */
-+/*
-+ * Copyright (C) 2021 ASPEED Technology Inc.
-+ */
-+
-+#ifndef _UAPI_LINUX_OTP_AST2600_H
-+#define _UAPI_LINUX_OTP_AST2600_H
-+
-+#include <linux/ioctl.h>
-+#include <linux/types.h>
-+
-+struct otp_read {
-+	unsigned int offset;
-+	unsigned int len;
-+	unsigned int *data;
-+};
-+
-+struct otp_prog {
-+	unsigned int dw_offset;
-+	unsigned int bit_offset;
-+	unsigned int value;
-+};
-+
-+#define OTP_A0				0
-+#define OTP_A1				1
-+#define OTP_A2				2
-+#define OTP_A3				3
-+
-+#define OTPIOC_BASE			'O'
-+
-+#define ASPEED_OTP_READ_DATA		_IOR(OTPIOC_BASE, 0, struct otp_read)
-+#define ASPEED_OTP_READ_CONF		_IOR(OTPIOC_BASE, 1, struct otp_read)
-+#define ASPEED_OTP_PROG_DATA		_IOW(OTPIOC_BASE, 2, struct otp_prog)
-+#define ASPEED_OTP_PROG_CONF		_IOW(OTPIOC_BASE, 3, struct otp_prog)
-+#define ASPEED_OTP_VER			_IOR(OTPIOC_BASE, 4, unsigned int)
-+#define ASPEED_OTP_SW_RID		_IOR(OTPIOC_BASE, 5, u32 *)
-+#define ASPEED_SEC_KEY_NUM		_IOR(OTPIOC_BASE, 6, u32 *)
-+
-+#endif /* _UAPI_LINUX_OTP_AST2600_H */
 diff --git a/include/uapi/linux/otp_ast2700.h b/include/uapi/linux/otp_ast2700.h
-new file mode 100644
+new file mode 100755
 index 000000000..769b13aab
 --- /dev/null
 +++ b/include/uapi/linux/otp_ast2700.h
diff --git a/recipes-kernel/linux/files/0019-Add-RNG-driver-for-ast2700.patch b/recipes-kernel/linux/files/0019-Add-RNG-driver-for-ast2700.patch
index 22e7fee..622e7c2 100644
--- a/recipes-kernel/linux/files/0019-Add-RNG-driver-for-ast2700.patch
+++ b/recipes-kernel/linux/files/0019-Add-RNG-driver-for-ast2700.patch
@@ -1,16 +1,16 @@
-From f1061e7fbd573651fd0bf03e2b1ec4578c1810ff Mon Sep 17 00:00:00 2001
-From: "yung-sheng.huang" <yung-sheng.huang@fii-na.corp-partner.google.com>
-Date: Wed, 16 Apr 2025 08:17:34 +0800
-Subject: [PATCH 19/26] Add RNG driver for ast2700
+From 3e11f13d9f7402d6540e342e867dff9c0425e978 Mon Sep 17 00:00:00 2001
+From: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+Date: Thu, 17 Jul 2025 11:41:24 +0800
+Subject: [PATCH] Add RNG driver for ast2700
 
-This is base on aspeed SDK 9.06.
+This is base on aspeed SDK 9.07.
 
 Source:
 AspeedTech-BMC github:
 https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/
-(cherry picked from commit v00.06.06)
+(cherry picked from commit v00.06.07)
 
-Signed-off-by: yung-sheng.huang <yung-sheng.huang@fii-na.corp-partner.google.com>
+Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
 ---
  drivers/char/hw_random/Kconfig                |   15 +
  drivers/char/hw_random/Makefile               |    2 +
diff --git a/recipes-kernel/linux/files/0020-Add-crypto-driver-for-ast2700.patch b/recipes-kernel/linux/files/0020-Add-crypto-driver-for-ast2700.patch
index 7dbe279..5bdf638 100644
--- a/recipes-kernel/linux/files/0020-Add-crypto-driver-for-ast2700.patch
+++ b/recipes-kernel/linux/files/0020-Add-crypto-driver-for-ast2700.patch
@@ -1,16 +1,16 @@
-From f8f7504d5c0841733db6fcf39f4c795b29fc5876 Mon Sep 17 00:00:00 2001
-From: "yung-sheng.huang" <yung-sheng.huang@fii-na.corp-partner.google.com>
-Date: Wed, 16 Apr 2025 08:22:50 +0800
-Subject: [PATCH 20/26] Add crypto driver for ast2700
+From 91fcfdf85600117a52e0dddc55f13faee7da3802 Mon Sep 17 00:00:00 2001
+From: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+Date: Thu, 17 Jul 2025 11:46:00 +0800
+Subject: [PATCH] Add crypto driver for ast2700
 
-This is base on aspeed SDK 9.06.
+This is base on aspeed SDK 9.07.
 
 Source:
 AspeedTech-BMC github:
 https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/
-(cherry picked from commit v00.06.06)
+(cherry picked from commit v00.06.07)
 
-Signed-off-by: yung-sheng.huang <yung-sheng.huang@fii-na.corp-partner.google.com>
+Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
 ---
  drivers/crypto/aspeed/Kconfig              |  57 +-
  drivers/crypto/aspeed/Makefile             |   9 +-
diff --git a/recipes-kernel/linux/files/0021-Add-USB-uhci-ehci-driver-for-ast2700.patch b/recipes-kernel/linux/files/0021-Add-USB-uhci-ehci-driver-for-ast2700.patch
index 23034f0..b308bd7 100644
--- a/recipes-kernel/linux/files/0021-Add-USB-uhci-ehci-driver-for-ast2700.patch
+++ b/recipes-kernel/linux/files/0021-Add-USB-uhci-ehci-driver-for-ast2700.patch
@@ -1,30 +1,23 @@
-From 17c272debee7620d87984253c28738a9e1bda94a Mon Sep 17 00:00:00 2001
-From: "yung-sheng.huang" <yung-sheng.huang@fii-na.corp-partner.google.com>
-Date: Wed, 16 Apr 2025 10:48:32 +0800
-Subject: [PATCH 21/26] Add USB uhci ehci driver for ast2700
+From 99d20b60e7d739efad2dd75740b68b8b69eec042 Mon Sep 17 00:00:00 2001
+From: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+Date: Thu, 17 Jul 2025 13:27:38 +0800
+Subject: [PATCH] Add USB uhci ehci driver for ast2700
 
-This is base on aspeed SDK 9.06.
+This is base on aspeed SDK 9.07.
 
 Source:
 AspeedTech-BMC github:
 https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/
-(cherry picked from commit v00.06.06)
+(cherry picked from commit v00.06.07)
 
-Signed-off-by: yung-sheng.huang <yung-sheng.huang@fii-na.corp-partner.google.com>
+Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
 ---
  drivers/usb/host/ehci-platform.c |   9 +-
- drivers/usb/host/uhci-hcd.c      |   9 +-
- drivers/usb/host/uhci-hcd.h      |   3 +-
- drivers/usb/host/uhci-platform.c |  15 +-
- drivers/usb/host/xhci-caps.h     |  85 ++++++++++
- drivers/usb/host/xhci-mem.c      |   5 +-
- drivers/usb/host/xhci-port.h     | 176 ++++++++++++++++++++
- drivers/usb/host/xhci-ring.c     | 124 +++++++++++---
- drivers/usb/host/xhci.c          |  40 ++++-
- drivers/usb/host/xhci.h          | 274 ++-----------------------------
- 10 files changed, 441 insertions(+), 299 deletions(-)
- create mode 100644 drivers/usb/host/xhci-caps.h
- create mode 100644 drivers/usb/host/xhci-port.h
+ drivers/usb/host/uhci-hcd.c      |  31 +++++-
+ drivers/usb/host/uhci-hcd.h      |   7 +-
+ drivers/usb/host/uhci-platform.c |  15 ++-
+ drivers/usb/host/uhci-q.c        | 171 ++++++++++++++++++++++++++++++-
+ 5 files changed, 223 insertions(+), 10 deletions(-)
 
 diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
 index 98b073185..a45f711fb 100644
@@ -61,7 +54,7 @@
  	device_enable_async_suspend(hcd->self.controller);
  	platform_set_drvdata(dev, hcd);
 diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
-index fd2408b55..4ecf3d1be 100644
+index fd2408b55..ad4c4f0c3 100644
 --- a/drivers/usb/host/uhci-hcd.c
 +++ b/drivers/usb/host/uhci-hcd.c
 @@ -42,6 +42,7 @@
@@ -72,7 +65,28 @@
  
  #include <linux/uaccess.h>
  #include <asm/io.h>
-@@ -593,6 +594,12 @@ static int uhci_start(struct usb_hcd *hcd)
+@@ -87,6 +88,10 @@ static char *errbuf;
+ 
+ #define ERRBUF_LEN    (32 * 1024)
+ 
++/* Aspeed SoC needs some DMA bounce buffers for workaround */
++#define BOUNCE_BUF_SIZE   64      /* Bounce buffer size */
++#define BOUNCE_BUF_ALIGN  64      /* Alignment within page */
++
+ static struct kmem_cache *uhci_up_cachep;	/* urb_priv */
+ 
+ static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state);
+@@ -548,6 +553,9 @@ static void release_uhci(struct uhci_hcd *uhci)
+ 
+ 	dma_pool_destroy(uhci->td_pool);
+ 
++	if (uhci_is_aspeed(uhci))
++		uhci_bounce_pool_destroy(uhci);
++
+ 	kfree(uhci->frame_cpu);
+ 
+ 	dma_free_coherent(uhci_dev(uhci),
+@@ -593,6 +601,12 @@ static int uhci_start(struct usb_hcd *hcd)
  	debugfs_create_file(hcd->self.bus_name, S_IFREG|S_IRUGO|S_IWUSR,
  			    uhci_debugfs_root, uhci, &uhci_debug_operations);
  #endif
@@ -85,7 +99,36 @@
  
  	uhci->frame = dma_alloc_coherent(uhci_dev(uhci),
  					 UHCI_NUMFRAMES * sizeof(*uhci->frame),
-@@ -917,7 +924,7 @@ static int __init uhci_hcd_init(void)
+@@ -608,6 +622,17 @@ static int uhci_start(struct usb_hcd *hcd)
+ 	if (!uhci->frame_cpu)
+ 		goto err_alloc_frame_cpu;
+ 
++	if (uhci_is_aspeed(uhci)) {
++		uhci->bounce_pool = dma_pool_create("uhci_bounce", uhci_dev(uhci),
++						    BOUNCE_BUF_SIZE,
++						    BOUNCE_BUF_ALIGN, 0);
++		if (!uhci->bounce_pool) {
++			dev_err(uhci_dev(uhci), "unable to create bounce dma_pool\n");
++			goto err_create_bounce_pool;
++		}
++		INIT_LIST_HEAD(&uhci->bounce_blacklist);
++	}
++
+ 	uhci->td_pool = dma_pool_create("uhci_td", uhci_dev(uhci),
+ 			sizeof(struct uhci_td), 16, 0);
+ 	if (!uhci->td_pool) {
+@@ -692,6 +717,10 @@ static int uhci_start(struct usb_hcd *hcd)
+ 	dma_pool_destroy(uhci->td_pool);
+ 
+ err_create_td_pool:
++	if (uhci_is_aspeed(uhci))
++		uhci_bounce_pool_destroy(uhci);
++
++err_create_bounce_pool:
+ 	kfree(uhci->frame_cpu);
+ 
+ err_alloc_frame_cpu:
+@@ -917,7 +946,7 @@ static int __init uhci_hcd_init(void)
  	return retval;
  }
  
@@ -95,7 +138,7 @@
  #ifdef PLATFORM_DRIVER
  	platform_driver_unregister(&PLATFORM_DRIVER);
 diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
-index 13ee2a614..8b5057dc0 100644
+index 13ee2a614..66b2d8e6e 100644
 --- a/drivers/usb/host/uhci-hcd.h
 +++ b/drivers/usb/host/uhci-hcd.h
 @@ -354,7 +354,7 @@ struct uhci_td {
@@ -107,7 +150,16 @@
   * (Note that the AUTO_STOPPED state won't be necessary once the hub
   * driver learns to autosuspend.)
   */
-@@ -445,6 +445,7 @@ struct uhci_hcd {
+@@ -389,6 +389,8 @@ struct uhci_hcd {
+ 
+ 	struct dma_pool *qh_pool;
+ 	struct dma_pool *td_pool;
++	struct dma_pool *bounce_pool;
++	struct list_head bounce_blacklist;
+ 
+ 	struct uhci_td *term_td;	/* Terminating TD, see UHCI bug */
+ 	struct uhci_qh *skelqh[UHCI_NUM_SKELQH];	/* Skeleton QHs */
+@@ -445,6 +447,7 @@ struct uhci_hcd {
  	short load[MAX_PHASE];			/* Periodic allocations */
  
  	struct clk *clk;			/* (optional) clock source */
@@ -115,8 +167,17 @@
  
  	/* Reset host controller */
  	void	(*reset_hc) (struct uhci_hcd *uhci);
+@@ -483,7 +486,7 @@ struct urb_priv {
+ 
+ 	struct uhci_qh *qh;		/* QH for this URB */
+ 	struct list_head td_list;
+-
++	struct list_head bounce_list;
+ 	unsigned fsbr:1;		/* URB wants FSBR */
+ };
+ 
 diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c
-index 3dec5dd3a..94d404276 100644
+index 712389599..c91cec205 100644
 --- a/drivers/usb/host/uhci-platform.c
 +++ b/drivers/usb/host/uhci-platform.c
 @@ -11,6 +11,7 @@
@@ -162,957 +223,235 @@
  	ret = platform_get_irq(pdev, 0);
  	if (ret < 0)
  		goto err_clk;
-diff --git a/drivers/usb/host/xhci-caps.h b/drivers/usb/host/xhci-caps.h
-new file mode 100644
-index 000000000..9e94cebf4
---- /dev/null
-+++ b/drivers/usb/host/xhci-caps.h
-@@ -0,0 +1,85 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+
-+/* hc_capbase bitmasks */
-+/* bits 7:0 - how long is the Capabilities register */
-+#define HC_LENGTH(p)		XHCI_HC_LENGTH(p)
-+/* bits 31:16	*/
-+#define HC_VERSION(p)		(((p) >> 16) & 0xffff)
-+
-+/* HCSPARAMS1 - hcs_params1 - bitmasks */
-+/* bits 0:7, Max Device Slots */
-+#define HCS_MAX_SLOTS(p)	(((p) >> 0) & 0xff)
-+#define HCS_SLOTS_MASK		0xff
-+/* bits 8:18, Max Interrupters */
-+#define HCS_MAX_INTRS(p)	(((p) >> 8) & 0x7ff)
-+/* bits 24:31, Max Ports - max value is 0x7F = 127 ports */
-+#define HCS_MAX_PORTS(p)	(((p) >> 24) & 0x7f)
-+
-+/* HCSPARAMS2 - hcs_params2 - bitmasks */
-+/* bits 0:3, frames or uframes that SW needs to queue transactions
-+ * ahead of the HW to meet periodic deadlines */
-+#define HCS_IST(p)		(((p) >> 0) & 0xf)
-+/* bits 4:7, max number of Event Ring segments */
-+#define HCS_ERST_MAX(p)		(((p) >> 4) & 0xf)
-+/* bits 21:25 Hi 5 bits of Scratchpad buffers SW must allocate for the HW */
-+/* bit 26 Scratchpad restore - for save/restore HW state - not used yet */
-+/* bits 27:31 Lo 5 bits of Scratchpad buffers SW must allocate for the HW */
-+#define HCS_MAX_SCRATCHPAD(p)   ((((p) >> 16) & 0x3e0) | (((p) >> 27) & 0x1f))
-+
-+/* HCSPARAMS3 - hcs_params3 - bitmasks */
-+/* bits 0:7, Max U1 to U0 latency for the roothub ports */
-+#define HCS_U1_LATENCY(p)	(((p) >> 0) & 0xff)
-+/* bits 16:31, Max U2 to U0 latency for the roothub ports */
-+#define HCS_U2_LATENCY(p)	(((p) >> 16) & 0xffff)
-+
-+/* HCCPARAMS - hcc_params - bitmasks */
-+/* true: HC can use 64-bit address pointers */
-+#define HCC_64BIT_ADDR(p)	((p) & (1 << 0))
-+/* true: HC can do bandwidth negotiation */
-+#define HCC_BANDWIDTH_NEG(p)	((p) & (1 << 1))
-+/* true: HC uses 64-byte Device Context structures
-+ * FIXME 64-byte context structures aren't supported yet.
-+ */
-+#define HCC_64BYTE_CONTEXT(p)	((p) & (1 << 2))
-+/* true: HC has port power switches */
-+#define HCC_PPC(p)		((p) & (1 << 3))
-+/* true: HC has port indicators */
-+#define HCS_INDICATOR(p)	((p) & (1 << 4))
-+/* true: HC has Light HC Reset Capability */
-+#define HCC_LIGHT_RESET(p)	((p) & (1 << 5))
-+/* true: HC supports latency tolerance messaging */
-+#define HCC_LTC(p)		((p) & (1 << 6))
-+/* true: no secondary Stream ID Support */
-+#define HCC_NSS(p)		((p) & (1 << 7))
-+/* true: HC supports Stopped - Short Packet */
-+#define HCC_SPC(p)		((p) & (1 << 9))
-+/* true: HC has Contiguous Frame ID Capability */
-+#define HCC_CFC(p)		((p) & (1 << 11))
-+/* Max size for Primary Stream Arrays - 2^(n+1), where n is bits 12:15 */
-+#define HCC_MAX_PSA(p)		(1 << ((((p) >> 12) & 0xf) + 1))
-+/* Extended Capabilities pointer from PCI base - section 5.3.6 */
-+#define HCC_EXT_CAPS(p)		XHCI_HCC_EXT_CAPS(p)
-+
-+#define CTX_SIZE(_hcc)		(HCC_64BYTE_CONTEXT(_hcc) ? 64 : 32)
-+
-+/* db_off bitmask - bits 0:1 reserved */
-+#define	DBOFF_MASK	(~0x3)
-+
-+/* run_regs_off bitmask - bits 0:4 reserved */
-+#define	RTSOFF_MASK	(~0x1f)
-+
-+/* HCCPARAMS2 - hcc_params2 - bitmasks */
-+/* true: HC supports U3 entry Capability */
-+#define	HCC2_U3C(p)		((p) & (1 << 0))
-+/* true: HC supports Configure endpoint command Max exit latency too large */
-+#define	HCC2_CMC(p)		((p) & (1 << 1))
-+/* true: HC supports Force Save context Capability */
-+#define	HCC2_FSC(p)		((p) & (1 << 2))
-+/* true: HC supports Compliance Transition Capability */
-+#define	HCC2_CTC(p)		((p) & (1 << 3))
-+/* true: HC support Large ESIT payload Capability > 48k */
-+#define	HCC2_LEC(p)		((p) & (1 << 4))
-+/* true: HC support Configuration Information Capability */
-+#define	HCC2_CIC(p)		((p) & (1 << 5))
-+/* true: HC support Extended TBC Capability, Isoc burst count > 65535 */
-+#define	HCC2_ETC(p)		((p) & (1 << 6))
-diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
-index b1e3fa54c..54c47463c 100644
---- a/drivers/usb/host/xhci-mem.c
-+++ b/drivers/usb/host/xhci-mem.c
-@@ -2289,7 +2289,10 @@ xhci_add_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir,
- 	erst_base = xhci_read_64(xhci, &ir->ir_set->erst_base);
- 	erst_base &= ERST_BASE_RSVDP;
- 	erst_base |= ir->erst.erst_dma_addr & ~ERST_BASE_RSVDP;
--	xhci_write_64(xhci, erst_base, &ir->ir_set->erst_base);
-+	if (xhci->quirks & XHCI_WRITE_64_HI_LO)
-+		hi_lo_writeq(erst_base, &ir->ir_set->erst_base);
-+	else
-+		xhci_write_64(xhci, erst_base, &ir->ir_set->erst_base);
- 
- 	/* Set the event ring dequeue address of this interrupter */
- 	xhci_set_hc_event_deq(xhci, ir);
-diff --git a/drivers/usb/host/xhci-port.h b/drivers/usb/host/xhci-port.h
-new file mode 100644
-index 000000000..f19efb966
---- /dev/null
-+++ b/drivers/usb/host/xhci-port.h
-@@ -0,0 +1,176 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+
-+/* PORTSC - Port Status and Control Register - port_status_base bitmasks */
-+/* true: device connected */
-+#define PORT_CONNECT	(1 << 0)
-+/* true: port enabled */
-+#define PORT_PE		(1 << 1)
-+/* bit 2 reserved and zeroed */
-+/* true: port has an over-current condition */
-+#define PORT_OC		(1 << 3)
-+/* true: port reset signaling asserted */
-+#define PORT_RESET	(1 << 4)
-+/* Port Link State - bits 5:8
-+ * A read gives the current link PM state of the port,
-+ * a write with Link State Write Strobe set sets the link state.
-+ */
-+#define PORT_PLS_MASK	(0xf << 5)
-+#define XDEV_U0		(0x0 << 5)
-+#define XDEV_U1		(0x1 << 5)
-+#define XDEV_U2		(0x2 << 5)
-+#define XDEV_U3		(0x3 << 5)
-+#define XDEV_DISABLED	(0x4 << 5)
-+#define XDEV_RXDETECT	(0x5 << 5)
-+#define XDEV_INACTIVE	(0x6 << 5)
-+#define XDEV_POLLING	(0x7 << 5)
-+#define XDEV_RECOVERY	(0x8 << 5)
-+#define XDEV_HOT_RESET	(0x9 << 5)
-+#define XDEV_COMP_MODE	(0xa << 5)
-+#define XDEV_TEST_MODE	(0xb << 5)
-+#define XDEV_RESUME	(0xf << 5)
-+
-+/* true: port has power (see HCC_PPC) */
-+#define PORT_POWER	(1 << 9)
-+/* bits 10:13 indicate device speed:
-+ * 0 - undefined speed - port hasn't be initialized by a reset yet
-+ * 1 - full speed
-+ * 2 - low speed
-+ * 3 - high speed
-+ * 4 - super speed
-+ * 5-15 reserved
-+ */
-+#define DEV_SPEED_MASK		(0xf << 10)
-+#define	XDEV_FS			(0x1 << 10)
-+#define	XDEV_LS			(0x2 << 10)
-+#define	XDEV_HS			(0x3 << 10)
-+#define	XDEV_SS			(0x4 << 10)
-+#define	XDEV_SSP		(0x5 << 10)
-+#define DEV_UNDEFSPEED(p)	(((p) & DEV_SPEED_MASK) == (0x0<<10))
-+#define DEV_FULLSPEED(p)	(((p) & DEV_SPEED_MASK) == XDEV_FS)
-+#define DEV_LOWSPEED(p)		(((p) & DEV_SPEED_MASK) == XDEV_LS)
-+#define DEV_HIGHSPEED(p)	(((p) & DEV_SPEED_MASK) == XDEV_HS)
-+#define DEV_SUPERSPEED(p)	(((p) & DEV_SPEED_MASK) == XDEV_SS)
-+#define DEV_SUPERSPEEDPLUS(p)	(((p) & DEV_SPEED_MASK) == XDEV_SSP)
-+#define DEV_SUPERSPEED_ANY(p)	(((p) & DEV_SPEED_MASK) >= XDEV_SS)
-+#define DEV_PORT_SPEED(p)	(((p) >> 10) & 0x0f)
-+
-+/* Bits 20:23 in the Slot Context are the speed for the device */
-+#define	SLOT_SPEED_FS		(XDEV_FS << 10)
-+#define	SLOT_SPEED_LS		(XDEV_LS << 10)
-+#define	SLOT_SPEED_HS		(XDEV_HS << 10)
-+#define	SLOT_SPEED_SS		(XDEV_SS << 10)
-+#define	SLOT_SPEED_SSP		(XDEV_SSP << 10)
-+/* Port Indicator Control */
-+#define PORT_LED_OFF	(0 << 14)
-+#define PORT_LED_AMBER	(1 << 14)
-+#define PORT_LED_GREEN	(2 << 14)
-+#define PORT_LED_MASK	(3 << 14)
-+/* Port Link State Write Strobe - set this when changing link state */
-+#define PORT_LINK_STROBE	(1 << 16)
-+/* true: connect status change */
-+#define PORT_CSC	(1 << 17)
-+/* true: port enable change */
-+#define PORT_PEC	(1 << 18)
-+/* true: warm reset for a USB 3.0 device is done.  A "hot" reset puts the port
-+ * into an enabled state, and the device into the default state.  A "warm" reset
-+ * also resets the link, forcing the device through the link training sequence.
-+ * SW can also look at the Port Reset register to see when warm reset is done.
-+ */
-+#define PORT_WRC	(1 << 19)
-+/* true: over-current change */
-+#define PORT_OCC	(1 << 20)
-+/* true: reset change - 1 to 0 transition of PORT_RESET */
-+#define PORT_RC		(1 << 21)
-+/* port link status change - set on some port link state transitions:
-+ *  Transition				Reason
-+ *  ------------------------------------------------------------------------------
-+ *  - U3 to Resume			Wakeup signaling from a device
-+ *  - Resume to Recovery to U0		USB 3.0 device resume
-+ *  - Resume to U0			USB 2.0 device resume
-+ *  - U3 to Recovery to U0		Software resume of USB 3.0 device complete
-+ *  - U3 to U0				Software resume of USB 2.0 device complete
-+ *  - U2 to U0				L1 resume of USB 2.1 device complete
-+ *  - U0 to U0 (???)			L1 entry rejection by USB 2.1 device
-+ *  - U0 to disabled			L1 entry error with USB 2.1 device
-+ *  - Any state to inactive		Error on USB 3.0 port
-+ */
-+#define PORT_PLC	(1 << 22)
-+/* port configure error change - port failed to configure its link partner */
-+#define PORT_CEC	(1 << 23)
-+#define PORT_CHANGE_MASK	(PORT_CSC | PORT_PEC | PORT_WRC | PORT_OCC | \
-+				 PORT_RC | PORT_PLC | PORT_CEC)
-+
-+
-+/* Cold Attach Status - xHC can set this bit to report device attached during
-+ * Sx state. Warm port reset should be perfomed to clear this bit and move port
-+ * to connected state.
-+ */
-+#define PORT_CAS	(1 << 24)
-+/* wake on connect (enable) */
-+#define PORT_WKCONN_E	(1 << 25)
-+/* wake on disconnect (enable) */
-+#define PORT_WKDISC_E	(1 << 26)
-+/* wake on over-current (enable) */
-+#define PORT_WKOC_E	(1 << 27)
-+/* bits 28:29 reserved */
-+/* true: device is non-removable - for USB 3.0 roothub emulation */
-+#define PORT_DEV_REMOVE	(1 << 30)
-+/* Initiate a warm port reset - complete when PORT_WRC is '1' */
-+#define PORT_WR		(1 << 31)
-+
-+/* We mark duplicate entries with -1 */
-+#define DUPLICATE_ENTRY ((u8)(-1))
-+
-+/* Port Power Management Status and Control - port_power_base bitmasks */
-+/* Inactivity timer value for transitions into U1, in microseconds.
-+ * Timeout can be up to 127us.  0xFF means an infinite timeout.
-+ */
-+#define PORT_U1_TIMEOUT(p)	((p) & 0xff)
-+#define PORT_U1_TIMEOUT_MASK	0xff
-+/* Inactivity timer value for transitions into U2 */
-+#define PORT_U2_TIMEOUT(p)	(((p) & 0xff) << 8)
-+#define PORT_U2_TIMEOUT_MASK	(0xff << 8)
-+/* Bits 24:31 for port testing */
-+
-+/* USB2 Protocol PORTSPMSC */
-+#define	PORT_L1S_MASK		7
-+#define	PORT_L1S_SUCCESS	1
-+#define	PORT_RWE		(1 << 3)
-+#define	PORT_HIRD(p)		(((p) & 0xf) << 4)
-+#define	PORT_HIRD_MASK		(0xf << 4)
-+#define	PORT_L1DS_MASK		(0xff << 8)
-+#define	PORT_L1DS(p)		(((p) & 0xff) << 8)
-+#define	PORT_HLE		(1 << 16)
-+#define PORT_TEST_MODE_SHIFT	28
-+
-+/* USB3 Protocol PORTLI  Port Link Information */
-+#define PORT_RX_LANES(p)	(((p) >> 16) & 0xf)
-+#define PORT_TX_LANES(p)	(((p) >> 20) & 0xf)
-+
-+/* USB2 Protocol PORTHLPMC */
-+#define PORT_HIRDM(p)((p) & 3)
-+#define PORT_L1_TIMEOUT(p)(((p) & 0xff) << 2)
-+#define PORT_BESLD(p)(((p) & 0xf) << 10)
-+
-+/* use 512 microseconds as USB2 LPM L1 default timeout. */
-+#define XHCI_L1_TIMEOUT		512
-+
-+/* Set default HIRD/BESL value to 4 (350/400us) for USB2 L1 LPM resume latency.
-+ * Safe to use with mixed HIRD and BESL systems (host and device) and is used
-+ * by other operating systems.
-+ *
-+ * XHCI 1.0 errata 8/14/12 Table 13 notes:
-+ * "Software should choose xHC BESL/BESLD field values that do not violate a
-+ * device's resume latency requirements,
-+ * e.g. not program values > '4' if BLC = '1' and a HIRD device is attached,
-+ * or not program values < '4' if BLC = '0' and a BESL device is attached.
-+ */
-+#define XHCI_DEFAULT_BESL	4
-+
-+/*
-+ * USB3 specification define a 360ms tPollingLFPSTiemout for USB3 ports
-+ * to complete link training. usually link trainig completes much faster
-+ * so check status 10 times with 36ms sleep in places we need to wait for
-+ * polling to complete.
-+ */
-+#define XHCI_PORT_POLLING_LFPS_TIME  36
-diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
-index 8dd85221c..4a081685a 100644
---- a/drivers/usb/host/xhci-ring.c
-+++ b/drivers/usb/host/xhci-ring.c
-@@ -52,6 +52,7 @@
-  *   endpoint rings; it generates events on the event ring for these.
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 35fcb8261..f8ebb217b 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -17,7 +17,98 @@
+  * (C) Copyright 2004-2007 Alan Stern, stern@rowland.harvard.edu
   */
  
-+#include <linux/jiffies.h>
- #include <linux/scatterlist.h>
- #include <linux/slab.h>
- #include <linux/dma-mapping.h>
-@@ -419,7 +420,8 @@ static void xhci_handle_stopped_cmd_ring(struct xhci_hcd *xhci,
- 	if ((xhci->cmd_ring->dequeue != xhci->cmd_ring->enqueue) &&
- 	    !(xhci->xhc_state & XHCI_STATE_DYING)) {
- 		xhci->current_cmd = cur_cmd;
--		xhci_mod_cmd_timer(xhci);
-+		if (cur_cmd)
-+			xhci_mod_cmd_timer(xhci);
- 		xhci_ring_cmd_db(xhci);
- 	}
- }
-@@ -994,6 +996,13 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep)
- 	unsigned int		slot_id = ep->vdev->slot_id;
- 	int			err;
- 
-+	/*
-+	 * This is not going to work if the hardware is changing its dequeue
-+	 * pointers as we look at them. Completion handler will call us later.
-+	 */
-+	if (ep->ep_state & SET_DEQ_PENDING)
-+		return 0;
++/* ASPEED UHCI: Forbidden DMA region (0x3F8 - 0x3FF) */
++#define FORBIDDEN_START	  0x3F8
++#define FORBIDDEN_END	  0x3FF
++/* ASPEED UHCI: Number of allowed retries */
++#define BOUNCE_RETRIES 3
 +
- 	xhci = ep->xhci;
- 
- 	list_for_each_entry_safe(td, tmp_td, &ep->cancelled_td_list, cancelled_td_list) {
-@@ -1046,7 +1055,7 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep)
- 					td_to_noop(xhci, ring, cached_td, false);
- 					cached_td->cancel_status = TD_CLEARED;
- 				}
--
-+				td_to_noop(xhci, ring, td, false);
- 				td->cancel_status = TD_CLEARING_CACHE;
- 				cached_td = td;
- 				break;
-@@ -1084,6 +1093,19 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep)
- 	return 0;
- }
- 
-+/*
-+ * Erase queued TDs from transfer ring(s) and give back those the xHC didn't
-+ * stop on. If necessary, queue commands to move the xHC off cancelled TDs it
-+ * stopped on. Those will be given back later when the commands complete.
-+ *
-+ * Call under xhci->lock on a stopped endpoint.
++/* Bounce buffer tracking info (per segment) */
++/**
++ * struct uhci_bounce_info - Bounce buffer descriptor for a TD segment
++ * @safe_buf: Pointer to allocated buffer from dma_pool
++ * @safe_dma: DMA address of safe_buf
++ * @len:      Valid length of this segment
++ * @list:     Link in urb_priv bounce_list
 + */
-+void xhci_process_cancelled_tds(struct xhci_virt_ep *ep)
++struct uhci_bounce_info {
++	void *safe_buf;
++	dma_addr_t safe_dma;
++	unsigned int len;
++	struct list_head list;
++};
++
++/**
++ * uhci_alloc_safe_dma_buffer - Allocate bounce buffer using DMA pool
++ * @uhci: UHCI controller
++ * @len: Required data length (must be <= BOUNCE_BUF_SIZE)
++ *
++ * Return: Pointer to newly allocated uhci_bounce_info, or NULL on failure
++ */
++static struct uhci_bounce_info *uhci_alloc_safe_dma_buffer(struct uhci_hcd *uhci, size_t len)
 +{
-+	xhci_invalidate_cancelled_tds(ep);
-+	xhci_giveback_invalidated_tds(ep);
++	struct uhci_bounce_info *bi;
++	dma_addr_t dma;
++	void *buf;
++
++	if (len > BOUNCE_BUF_SIZE)
++		return NULL;
++
++	buf = dma_pool_alloc(uhci->bounce_pool, GFP_ATOMIC, &dma);
++	if (!buf) {
++		dev_err(uhci_dev(uhci), "%s: dma_pool_alloc failed\n", __func__);
++		return NULL;
++	}
++
++	bi = kzalloc(sizeof(*bi), GFP_ATOMIC);
++	if (!bi) {
++		dma_pool_free(uhci->bounce_pool, buf, dma);
++		return NULL;
++	}
++
++	bi->safe_buf = buf;
++	bi->safe_dma = dma;
++	INIT_LIST_HEAD(&bi->list);
++	return bi;
 +}
 +
++/**
++ * uhci_free_safe_dma_buffer - Free bounce buffer and metadata
++ * @uhci: UHCI controller
++ * @bi: Bounce descriptor to free
++ */
++static void uhci_free_safe_dma_buffer(struct uhci_hcd *uhci, struct uhci_bounce_info *bi)
++{
++	dma_pool_free(uhci->bounce_pool, bi->safe_buf, bi->safe_dma);
++	kfree(bi);
++}
++
++/* Complete all bounce buffer segments: free memory */
++static void uhci_complete_bounce_buffers(struct uhci_hcd *uhci, struct urb_priv *urbp)
++{
++	struct uhci_bounce_info *bi, *tmp;
++
++	list_for_each_entry_safe(bi, tmp, &urbp->bounce_list, list) {
++		dev_dbg(uhci_dev(uhci), "Free bounce TD at DMA: %pad len %u\n",
++			&bi->safe_dma, bi->len);
++		uhci_free_safe_dma_buffer(uhci, bi);
++	}
++}
++
++/**
++ * uhci_bounce_pool_destroy - Destroy UHCI bounce buffer DMA pool
++ */
++void uhci_bounce_pool_destroy(struct uhci_hcd *uhci)
++{
++	struct uhci_bounce_info *bi, *tmp;
+ 
++	list_for_each_entry_safe(bi, tmp, &uhci->bounce_blacklist, list) {
++		list_del(&bi->list);
++		uhci_free_safe_dma_buffer(uhci, bi);
++	}
++
++	dma_pool_destroy(uhci->bounce_pool);
++}
  /*
-  * Returns the TD the endpoint ring halted on.
-  * Only call for non-running rings without streams.
-@@ -1173,9 +1195,35 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id,
- 				break;
- 			ep->ep_state &= ~EP_STOP_CMD_PENDING;
- 			return;
-+		case EP_STATE_STOPPED:
-+			/*
-+			 * Per xHCI 4.6.9, Stop Endpoint command on a Stopped
-+			 * EP is a Context State Error, and EP stays Stopped.
-+			 *
-+			 * But maybe it failed on Halted, and somebody ran Reset
-+			 * Endpoint later. EP state is now Stopped and EP_HALTED
-+			 * still set because Reset EP handler will run after us.
-+			 */
-+			if (ep->ep_state & EP_HALTED)
-+				break;
-+			/*
-+			 * On some HCs EP state remains Stopped for some tens of
-+			 * us to a few ms or more after a doorbell ring, and any
-+			 * new Stop Endpoint fails without aborting the restart.
-+			 * This handler may run quickly enough to still see this
-+			 * Stopped state, but it will soon change to Running.
-+			 *
-+			 * Assume this bug on unexpected Stop Endpoint failures.
-+			 * Keep retrying until the EP starts and stops again, on
-+			 * chips where this is known to help. Wait for 100ms.
-+			 */
-+			if (time_is_before_jiffies(ep->stop_time + msecs_to_jiffies(100)))
-+				break;
-+			fallthrough;
- 		case EP_STATE_RUNNING:
- 			/* Race, HW handled stop ep cmd before ep was running */
--			xhci_dbg(xhci, "Stop ep completion ctx error, ep is running\n");
-+			xhci_dbg(xhci, "Stop ep completion ctx error, ctx_state %d\n",
-+					GET_EP_CTX_STATE(ep_ctx));
+  * Technically, updating td->status here is a race, but it's not really a
+  * problem. The worst that can happen is that we set the IOC bit again
+@@ -733,6 +824,7 @@ static inline struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci,
  
- 			command = xhci_alloc_command(xhci, false, GFP_ATOMIC);
- 			if (!command) {
-@@ -1354,7 +1402,6 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
- 	struct xhci_ep_ctx *ep_ctx;
- 	struct xhci_slot_ctx *slot_ctx;
- 	struct xhci_td *td, *tmp_td;
--	bool deferred = false;
+ 	INIT_LIST_HEAD(&urbp->node);
+ 	INIT_LIST_HEAD(&urbp->td_list);
++	INIT_LIST_HEAD(&urbp->bounce_list);
  
- 	ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3]));
- 	stream_id = TRB_TO_STREAM_ID(le32_to_cpu(trb->generic.field[2]));
-@@ -1414,6 +1461,20 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
- 			struct xhci_stream_ctx *ctx =
- 				&ep->stream_info->stream_ctx_array[stream_id];
- 			deq = le64_to_cpu(ctx->stream_ring) & SCTX_DEQ_MASK;
-+
-+			/*
-+			 * Cadence xHCI controllers store some endpoint state
-+			 * information within Rsvd0 fields of Stream Endpoint
-+			 * context. This field is not cleared during Set TR
-+			 * Dequeue Pointer command which causes XDMA to skip
-+			 * over transfer ring and leads to data loss on stream
-+			 * pipe.
-+			 * To fix this issue driver must clear Rsvd0 field.
-+			 */
-+			if (xhci->quirks & XHCI_CDNS_SCTX_QUIRK) {
-+				ctx->reserved[0] = 0;
-+				ctx->reserved[1] = 0;
-+			}
- 		} else {
- 			deq = le64_to_cpu(ep_ctx->deq) & ~EP_CTX_CYCLE_MASK;
- 		}
-@@ -1441,8 +1502,6 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
- 			xhci_dbg(ep->xhci, "%s: Giveback cancelled URB %p TD\n",
- 				 __func__, td->urb);
- 			xhci_td_cleanup(ep->xhci, td, ep_ring, td->status);
--		} else if (td->cancel_status == TD_CLEARING_CACHE_DEFERRED) {
--			deferred = true;
- 		} else {
- 			xhci_dbg(ep->xhci, "%s: Keep cancelled URB %p TD as cancel_status is %d\n",
- 				 __func__, td->urb, td->cancel_status);
-@@ -1453,11 +1512,15 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
- 	ep->queued_deq_seg = NULL;
- 	ep->queued_deq_ptr = NULL;
- 
--	if (deferred) {
--		/* We have more streams to clear */
-+	/* Check for deferred or newly cancelled TDs */
-+	if (!list_empty(&ep->cancelled_td_list)) {
- 		xhci_dbg(ep->xhci, "%s: Pending TDs to clear, continuing with invalidation\n",
- 			 __func__);
- 		xhci_invalidate_cancelled_tds(ep);
-+		/* Try to restart the endpoint if all is done */
-+		ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
-+		/* Start giving back any TDs invalidated above */
-+		xhci_giveback_invalidated_tds(ep);
- 	} else {
- 		/* Restart any rings with pending URBs */
- 		xhci_dbg(ep->xhci, "%s: All TDs cleared, ring doorbell\n", __func__);
-@@ -1720,6 +1783,14 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
- 
- 	trace_xhci_handle_command(xhci->cmd_ring, &cmd_trb->generic);
- 
-+	cmd_comp_code = GET_COMP_CODE(le32_to_cpu(event->status));
-+
-+	/* If CMD ring stopped we own the trbs between enqueue and dequeue */
-+	if (cmd_comp_code == COMP_COMMAND_RING_STOPPED) {
-+		complete_all(&xhci->cmd_ring_stop_completion);
-+		return;
-+	}
-+
- 	cmd_dequeue_dma = xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
- 			cmd_trb);
- 	/*
-@@ -1736,14 +1807,6 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
- 
- 	cancel_delayed_work(&xhci->cmd_timer);
- 
--	cmd_comp_code = GET_COMP_CODE(le32_to_cpu(event->status));
--
--	/* If CMD ring stopped we own the trbs between enqueue and dequeue */
--	if (cmd_comp_code == COMP_COMMAND_RING_STOPPED) {
--		complete_all(&xhci->cmd_ring_stop_completion);
--		return;
--	}
--
- 	if (cmd->command_trb != xhci->cmd_ring->dequeue) {
- 		xhci_err(xhci,
- 			 "Command completion event does not match command\n");
-@@ -2421,8 +2484,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
- 			break;
- 		if (remaining) {
- 			frame->status = short_framestatus;
--			if (xhci->quirks & XHCI_TRUST_TX_LENGTH)
--				sum_trbs_for_length = true;
-+			sum_trbs_for_length = true;
- 			break;
- 		}
- 		frame->status = 0;
-@@ -2671,15 +2733,11 @@ static int handle_tx_event(struct xhci_hcd *xhci,
- 	 * transfer type
- 	 */
- 	case COMP_SUCCESS:
--		if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0)
--			break;
--		if (xhci->quirks & XHCI_TRUST_TX_LENGTH ||
--		    ep_ring->last_td_was_short)
-+		if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
- 			trb_comp_code = COMP_SHORT_PACKET;
--		else
--			xhci_warn_ratelimited(xhci,
--					      "WARN Successful completion on short TX for slot %u ep %u: needs XHCI_TRUST_TX_LENGTH quirk?\n",
--					      slot_id, ep_index);
-+			xhci_dbg(xhci, "Successful completion on short TX for slot %u ep %u with last td short %d\n",
-+				 slot_id, ep_index, ep_ring->last_td_was_short);
-+		}
- 		break;
- 	case COMP_SHORT_PACKET:
- 		break;
-@@ -3811,6 +3869,20 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
- 	if (!urb->setup_packet)
- 		return -EINVAL;
- 
-+	if ((xhci->quirks & XHCI_ETRON_HOST) &&
-+	    urb->dev->speed >= USB_SPEED_SUPER) {
-+		/*
-+		 * If next available TRB is the Link TRB in the ring segment then
-+		 * enqueue a No Op TRB, this can prevent the Setup and Data Stage
-+		 * TRB to be breaked by the Link TRB.
-+		 */
-+		if (trb_is_link(ep_ring->enqueue + 1)) {
-+			field = TRB_TYPE(TRB_TR_NOOP) | ep_ring->cycle_state;
-+			queue_trb(xhci, ep_ring, false, 0, 0,
-+					TRB_INTR_TARGET(0), field);
-+		}
-+	}
-+
- 	/* 1 TRB for setup, 1 for status */
- 	num_trbs = 2;
- 	/*
-diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
-index f005ce1f9..70e6c240a 100644
---- a/drivers/usb/host/xhci.c
-+++ b/drivers/usb/host/xhci.c
-@@ -8,6 +8,7 @@
-  * Some code borrowed from the Linux EHCI driver.
-  */
- 
-+#include <linux/jiffies.h>
- #include <linux/pci.h>
- #include <linux/iommu.h>
- #include <linux/iopoll.h>
-@@ -1737,15 +1738,27 @@ static int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
- 		}
+ 	return urbp;
+ }
+@@ -751,6 +843,8 @@ static void uhci_free_urb_priv(struct uhci_hcd *uhci,
+ 		uhci_free_td(uhci, td);
  	}
  
--	/* Queue a stop endpoint command, but only if this is
--	 * the first cancellation to be handled.
--	 */
--	if (!(ep->ep_state & EP_STOP_CMD_PENDING)) {
-+	/* These completion handlers will sort out cancelled TDs for us */
-+	if (ep->ep_state & (EP_STOP_CMD_PENDING | EP_HALTED | SET_DEQ_PENDING)) {
-+		xhci_dbg(xhci, "Not queuing Stop Endpoint on slot %d ep %d in state 0x%x\n",
-+				urb->dev->slot_id, ep_index, ep->ep_state);
-+		goto done;
-+	}
++	uhci_complete_bounce_buffers(uhci, urbp);
 +
-+	/* In this case no commands are pending but the endpoint is stopped */
-+	if (ep->ep_state & EP_CLEARING_TT) {
-+		/* and cancelled TDs can be given back right away */
-+		xhci_dbg(xhci, "Invalidating TDs instantly on slot %d ep %d in state 0x%x\n",
-+				urb->dev->slot_id, ep_index, ep->ep_state);
-+		xhci_process_cancelled_tds(ep);
-+	} else {
-+		/* Otherwise, queue a new Stop Endpoint command */
- 		command = xhci_alloc_command(xhci, false, GFP_ATOMIC);
- 		if (!command) {
- 			ret = -ENOMEM;
- 			goto done;
- 		}
-+		ep->stop_time = jiffies;
- 		ep->ep_state |= EP_STOP_CMD_PENDING;
- 		xhci_queue_stop_endpoint(xhci, command, urb->dev->slot_id,
- 					 ep_index, 0);
-@@ -3642,6 +3655,8 @@ void xhci_free_device_endpoint_resources(struct xhci_hcd *xhci,
- 				xhci->num_active_eps);
+ 	kmem_cache_free(uhci_up_cachep, urbp);
  }
  
-+static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev);
-+
- /*
-  * This submits a Reset Device Command, which will set the device state to 0,
-  * set the device address to 0, and disable all the endpoints except the default
-@@ -3712,6 +3727,23 @@ static int xhci_discover_or_reset_device(struct usb_hcd *hcd,
- 						SLOT_STATE_DISABLED)
- 		return 0;
+@@ -920,12 +1014,14 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
+ 	int maxsze = usb_endpoint_maxp(&qh->hep->desc);
+ 	int len = urb->transfer_buffer_length;
+ 	int this_sg_len;
++	void *urb_buf = urb->transfer_buffer;
+ 	dma_addr_t data;
+ 	__hc32 *plink;
+ 	struct urb_priv *urbp = urb->hcpriv;
+ 	unsigned int toggle;
+ 	struct scatterlist  *sg;
+ 	int i;
++	bool aspeed_out_xfer = usb_pipeout(urb->pipe) && uhci_is_aspeed(uhci);
  
-+	if (xhci->quirks & XHCI_ETRON_HOST) {
-+		/*
-+		 * Obtaining a new device slot to inform the xHCI host that
-+		 * the USB device has been reset.
+ 	if (len < 0)
+ 		return -EINVAL;
+@@ -963,6 +1059,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
+ 	td = qh->dummy_td;
+ 	for (;;) {	/* Allow zero length packets */
+ 		int pktsze = maxsze;
++		unsigned int offset = data & 0x3FF;
+ 
+ 		if (len <= pktsze) {		/* The last packet */
+ 			pktsze = len;
+@@ -977,15 +1074,81 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
+ 			*plink = LINK_TO_TD(uhci, td);
+ 		}
+ 		uhci_add_td_to_urbp(td, urbp);
+-		uhci_fill_td(uhci, td, status,
+-				destination | uhci_explen(pktsze) |
+-					(toggle << TD_TOKEN_TOGGLE_SHIFT),
+-				data);
++
++		/* ASPEED OUT Transfer HW restriction:
++		 *  Avoid any access that overlaps forbidden region [0x3F8 - 0x3FF].
++		 *  Driver bounces any TD that ends in or beyond forbidden range.
 +		 */
-+		ret = xhci_disable_slot(xhci, udev->slot_id);
-+		xhci_free_virt_device(xhci, udev->slot_id);
-+		if (!ret) {
-+			ret = xhci_alloc_dev(hcd, udev);
-+			if (ret == 1)
-+				ret = 0;
-+			else
-+				ret = -EINVAL;
++		unsigned int end = offset + pktsze - 1;
++
++		if (aspeed_out_xfer && end >= FORBIDDEN_START) {
++			int retry = 0;
++			struct uhci_bounce_info *bi = NULL;
++
++			while (retry++ < BOUNCE_RETRIES) {
++				bi = uhci_alloc_safe_dma_buffer(uhci, pktsze);
++				if (!bi) {
++					dev_err(uhci_dev(uhci), "Allocate bounce buffer failed\n");
++					goto nomem;
++				}
++
++				unsigned int safe_offset = bi->safe_dma & 0x3FF;
++				unsigned int safe_end = safe_offset + pktsze - 1;
++
++				if (safe_end < FORBIDDEN_START)
++					break;
++
++				dev_dbg(uhci_dev(uhci), "(%d) Retry to allocate bounce (Forbidden DMA: %pad len: %u)\n",
++					retry, &bi->safe_dma, pktsze);
++				/* Save to black list for cleanup at uhci driver removal */
++				list_add_tail(&bi->list, &uhci->bounce_blacklist);
++				bi = NULL;
++			}
++			if (!bi) {
++				dev_err(uhci_dev(uhci), "Allocate safe bounce buffer failed after retry %d times\n", BOUNCE_RETRIES);
++				goto nomem;
++			}
++
++			/*
++			 * Copy data into bounce buffer segment:
++			 * - If URB uses scatter-gather (SG), use sg_pcopy_to_buffer to copy the correct portion
++			 * - If URB uses a linear buffer, use memcpy
++			 * - If neither is available, report error
++			 */
++			if (urb->sg && urb->num_mapped_sgs > 0) {
++				if (sg_pcopy_to_buffer(urb->sg, urb->num_mapped_sgs,
++						       bi->safe_buf, pktsze,
++						       urb->transfer_buffer_length - len) != pktsze) {
++					dev_err(uhci_dev(uhci), "sg_pcopy_to_buffer to safe bounce buffer failed\n");
++					return -EIO;
++				}
++			} else if (urb->transfer_buffer) {
++				memcpy(bi->safe_buf, urb_buf, pktsze);
++			} else {
++				dev_err(uhci_dev(uhci), "Cannot copy to bounce buffer: no data source\n");
++				return -EINVAL;
++			}
++
++			uhci_fill_td(uhci, td, status,
++				     destination | uhci_explen(pktsze) |
++				     (toggle << TD_TOKEN_TOGGLE_SHIFT),
++				     bi->safe_dma);
++			bi->len = pktsze;
++			list_add_tail(&bi->list, &urbp->bounce_list);
++			dev_dbg(uhci_dev(uhci), "Bounce TD at DMA safe: %pad len %u offset 0x%x\n",
++				&bi->safe_dma, pktsze, offset);
++		} else {
++			uhci_fill_td(uhci, td, status,
++				     destination | uhci_explen(pktsze) |
++				     (toggle << TD_TOKEN_TOGGLE_SHIFT),
++				     data);
 +		}
-+		return ret;
-+	}
-+
- 	trace_xhci_discover_or_reset_device(slot_ctx);
+ 		plink = &td->link;
+ 		status |= TD_CTRL_ACTIVE;
  
- 	xhci_dbg(xhci, "Resetting device with slot ID %u\n", slot_id);
-diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
-index b29fe4716..fddb3a90d 100644
---- a/drivers/usb/host/xhci.h
-+++ b/drivers/usb/host/xhci.h
-@@ -17,11 +17,15 @@
- #include <linux/kernel.h>
- #include <linux/usb/hcd.h>
- #include <linux/io-64-nonatomic-lo-hi.h>
-+#include <linux/io-64-nonatomic-hi-lo.h>
- 
- /* Code sharing between pci-quirks and xhci hcd */
- #include	"xhci-ext-caps.h"
- #include "pci-quirks.h"
- 
-+#include "xhci-port.h"
-+#include "xhci-caps.h"
-+
- /* max buffer size for trace and debug messages */
- #define XHCI_MSG_MAX		500
- 
-@@ -62,90 +66,6 @@ struct xhci_cap_regs {
- 	/* Reserved up to (CAPLENGTH - 0x1C) */
- };
- 
--/* hc_capbase bitmasks */
--/* bits 7:0 - how long is the Capabilities register */
--#define HC_LENGTH(p)		XHCI_HC_LENGTH(p)
--/* bits 31:16	*/
--#define HC_VERSION(p)		(((p) >> 16) & 0xffff)
--
--/* HCSPARAMS1 - hcs_params1 - bitmasks */
--/* bits 0:7, Max Device Slots */
--#define HCS_MAX_SLOTS(p)	(((p) >> 0) & 0xff)
--#define HCS_SLOTS_MASK		0xff
--/* bits 8:18, Max Interrupters */
--#define HCS_MAX_INTRS(p)	(((p) >> 8) & 0x7ff)
--/* bits 24:31, Max Ports - max value is 0x7F = 127 ports */
--#define HCS_MAX_PORTS(p)	(((p) >> 24) & 0x7f)
--
--/* HCSPARAMS2 - hcs_params2 - bitmasks */
--/* bits 0:3, frames or uframes that SW needs to queue transactions
-- * ahead of the HW to meet periodic deadlines */
--#define HCS_IST(p)		(((p) >> 0) & 0xf)
--/* bits 4:7, max number of Event Ring segments */
--#define HCS_ERST_MAX(p)		(((p) >> 4) & 0xf)
--/* bits 21:25 Hi 5 bits of Scratchpad buffers SW must allocate for the HW */
--/* bit 26 Scratchpad restore - for save/restore HW state - not used yet */
--/* bits 27:31 Lo 5 bits of Scratchpad buffers SW must allocate for the HW */
--#define HCS_MAX_SCRATCHPAD(p)   ((((p) >> 16) & 0x3e0) | (((p) >> 27) & 0x1f))
--
--/* HCSPARAMS3 - hcs_params3 - bitmasks */
--/* bits 0:7, Max U1 to U0 latency for the roothub ports */
--#define HCS_U1_LATENCY(p)	(((p) >> 0) & 0xff)
--/* bits 16:31, Max U2 to U0 latency for the roothub ports */
--#define HCS_U2_LATENCY(p)	(((p) >> 16) & 0xffff)
--
--/* HCCPARAMS - hcc_params - bitmasks */
--/* true: HC can use 64-bit address pointers */
--#define HCC_64BIT_ADDR(p)	((p) & (1 << 0))
--/* true: HC can do bandwidth negotiation */
--#define HCC_BANDWIDTH_NEG(p)	((p) & (1 << 1))
--/* true: HC uses 64-byte Device Context structures
-- * FIXME 64-byte context structures aren't supported yet.
-- */
--#define HCC_64BYTE_CONTEXT(p)	((p) & (1 << 2))
--/* true: HC has port power switches */
--#define HCC_PPC(p)		((p) & (1 << 3))
--/* true: HC has port indicators */
--#define HCS_INDICATOR(p)	((p) & (1 << 4))
--/* true: HC has Light HC Reset Capability */
--#define HCC_LIGHT_RESET(p)	((p) & (1 << 5))
--/* true: HC supports latency tolerance messaging */
--#define HCC_LTC(p)		((p) & (1 << 6))
--/* true: no secondary Stream ID Support */
--#define HCC_NSS(p)		((p) & (1 << 7))
--/* true: HC supports Stopped - Short Packet */
--#define HCC_SPC(p)		((p) & (1 << 9))
--/* true: HC has Contiguous Frame ID Capability */
--#define HCC_CFC(p)		((p) & (1 << 11))
--/* Max size for Primary Stream Arrays - 2^(n+1), where n is bits 12:15 */
--#define HCC_MAX_PSA(p)		(1 << ((((p) >> 12) & 0xf) + 1))
--/* Extended Capabilities pointer from PCI base - section 5.3.6 */
--#define HCC_EXT_CAPS(p)		XHCI_HCC_EXT_CAPS(p)
--
--#define CTX_SIZE(_hcc)		(HCC_64BYTE_CONTEXT(_hcc) ? 64 : 32)
--
--/* db_off bitmask - bits 0:1 reserved */
--#define	DBOFF_MASK	(~0x3)
--
--/* run_regs_off bitmask - bits 0:4 reserved */
--#define	RTSOFF_MASK	(~0x1f)
--
--/* HCCPARAMS2 - hcc_params2 - bitmasks */
--/* true: HC supports U3 entry Capability */
--#define	HCC2_U3C(p)		((p) & (1 << 0))
--/* true: HC supports Configure endpoint command Max exit latency too large */
--#define	HCC2_CMC(p)		((p) & (1 << 1))
--/* true: HC supports Force Save context Capability */
--#define	HCC2_FSC(p)		((p) & (1 << 2))
--/* true: HC supports Compliance Transition Capability */
--#define	HCC2_CTC(p)		((p) & (1 << 3))
--/* true: HC support Large ESIT payload Capability > 48k */
--#define	HCC2_LEC(p)		((p) & (1 << 4))
--/* true: HC support Configuration Information Capability */
--#define	HCC2_CIC(p)		((p) & (1 << 5))
--/* true: HC support Extended TBC Capability, Isoc burst count > 65535 */
--#define	HCC2_ETC(p)		((p) & (1 << 6))
--
- /* Number of registers per port */
- #define	NUM_PORT_REGS	4
- 
-@@ -291,181 +211,6 @@ struct xhci_op_regs {
- #define CONFIG_CIE		(1 << 9)
- /* bits 10:31 - reserved and should be preserved */
- 
--/* PORTSC - Port Status and Control Register - port_status_base bitmasks */
--/* true: device connected */
--#define PORT_CONNECT	(1 << 0)
--/* true: port enabled */
--#define PORT_PE		(1 << 1)
--/* bit 2 reserved and zeroed */
--/* true: port has an over-current condition */
--#define PORT_OC		(1 << 3)
--/* true: port reset signaling asserted */
--#define PORT_RESET	(1 << 4)
--/* Port Link State - bits 5:8
-- * A read gives the current link PM state of the port,
-- * a write with Link State Write Strobe set sets the link state.
-- */
--#define PORT_PLS_MASK	(0xf << 5)
--#define XDEV_U0		(0x0 << 5)
--#define XDEV_U1		(0x1 << 5)
--#define XDEV_U2		(0x2 << 5)
--#define XDEV_U3		(0x3 << 5)
--#define XDEV_DISABLED	(0x4 << 5)
--#define XDEV_RXDETECT	(0x5 << 5)
--#define XDEV_INACTIVE	(0x6 << 5)
--#define XDEV_POLLING	(0x7 << 5)
--#define XDEV_RECOVERY	(0x8 << 5)
--#define XDEV_HOT_RESET	(0x9 << 5)
--#define XDEV_COMP_MODE	(0xa << 5)
--#define XDEV_TEST_MODE	(0xb << 5)
--#define XDEV_RESUME	(0xf << 5)
--
--/* true: port has power (see HCC_PPC) */
--#define PORT_POWER	(1 << 9)
--/* bits 10:13 indicate device speed:
-- * 0 - undefined speed - port hasn't be initialized by a reset yet
-- * 1 - full speed
-- * 2 - low speed
-- * 3 - high speed
-- * 4 - super speed
-- * 5-15 reserved
-- */
--#define DEV_SPEED_MASK		(0xf << 10)
--#define	XDEV_FS			(0x1 << 10)
--#define	XDEV_LS			(0x2 << 10)
--#define	XDEV_HS			(0x3 << 10)
--#define	XDEV_SS			(0x4 << 10)
--#define	XDEV_SSP		(0x5 << 10)
--#define DEV_UNDEFSPEED(p)	(((p) & DEV_SPEED_MASK) == (0x0<<10))
--#define DEV_FULLSPEED(p)	(((p) & DEV_SPEED_MASK) == XDEV_FS)
--#define DEV_LOWSPEED(p)		(((p) & DEV_SPEED_MASK) == XDEV_LS)
--#define DEV_HIGHSPEED(p)	(((p) & DEV_SPEED_MASK) == XDEV_HS)
--#define DEV_SUPERSPEED(p)	(((p) & DEV_SPEED_MASK) == XDEV_SS)
--#define DEV_SUPERSPEEDPLUS(p)	(((p) & DEV_SPEED_MASK) == XDEV_SSP)
--#define DEV_SUPERSPEED_ANY(p)	(((p) & DEV_SPEED_MASK) >= XDEV_SS)
--#define DEV_PORT_SPEED(p)	(((p) >> 10) & 0x0f)
--
--/* Bits 20:23 in the Slot Context are the speed for the device */
--#define	SLOT_SPEED_FS		(XDEV_FS << 10)
--#define	SLOT_SPEED_LS		(XDEV_LS << 10)
--#define	SLOT_SPEED_HS		(XDEV_HS << 10)
--#define	SLOT_SPEED_SS		(XDEV_SS << 10)
--#define	SLOT_SPEED_SSP		(XDEV_SSP << 10)
--/* Port Indicator Control */
--#define PORT_LED_OFF	(0 << 14)
--#define PORT_LED_AMBER	(1 << 14)
--#define PORT_LED_GREEN	(2 << 14)
--#define PORT_LED_MASK	(3 << 14)
--/* Port Link State Write Strobe - set this when changing link state */
--#define PORT_LINK_STROBE	(1 << 16)
--/* true: connect status change */
--#define PORT_CSC	(1 << 17)
--/* true: port enable change */
--#define PORT_PEC	(1 << 18)
--/* true: warm reset for a USB 3.0 device is done.  A "hot" reset puts the port
-- * into an enabled state, and the device into the default state.  A "warm" reset
-- * also resets the link, forcing the device through the link training sequence.
-- * SW can also look at the Port Reset register to see when warm reset is done.
-- */
--#define PORT_WRC	(1 << 19)
--/* true: over-current change */
--#define PORT_OCC	(1 << 20)
--/* true: reset change - 1 to 0 transition of PORT_RESET */
--#define PORT_RC		(1 << 21)
--/* port link status change - set on some port link state transitions:
-- *  Transition				Reason
-- *  ------------------------------------------------------------------------------
-- *  - U3 to Resume			Wakeup signaling from a device
-- *  - Resume to Recovery to U0		USB 3.0 device resume
-- *  - Resume to U0			USB 2.0 device resume
-- *  - U3 to Recovery to U0		Software resume of USB 3.0 device complete
-- *  - U3 to U0				Software resume of USB 2.0 device complete
-- *  - U2 to U0				L1 resume of USB 2.1 device complete
-- *  - U0 to U0 (???)			L1 entry rejection by USB 2.1 device
-- *  - U0 to disabled			L1 entry error with USB 2.1 device
-- *  - Any state to inactive		Error on USB 3.0 port
-- */
--#define PORT_PLC	(1 << 22)
--/* port configure error change - port failed to configure its link partner */
--#define PORT_CEC	(1 << 23)
--#define PORT_CHANGE_MASK	(PORT_CSC | PORT_PEC | PORT_WRC | PORT_OCC | \
--				 PORT_RC | PORT_PLC | PORT_CEC)
--
--
--/* Cold Attach Status - xHC can set this bit to report device attached during
-- * Sx state. Warm port reset should be perfomed to clear this bit and move port
-- * to connected state.
-- */
--#define PORT_CAS	(1 << 24)
--/* wake on connect (enable) */
--#define PORT_WKCONN_E	(1 << 25)
--/* wake on disconnect (enable) */
--#define PORT_WKDISC_E	(1 << 26)
--/* wake on over-current (enable) */
--#define PORT_WKOC_E	(1 << 27)
--/* bits 28:29 reserved */
--/* true: device is non-removable - for USB 3.0 roothub emulation */
--#define PORT_DEV_REMOVE	(1 << 30)
--/* Initiate a warm port reset - complete when PORT_WRC is '1' */
--#define PORT_WR		(1 << 31)
--
--/* We mark duplicate entries with -1 */
--#define DUPLICATE_ENTRY ((u8)(-1))
--
--/* Port Power Management Status and Control - port_power_base bitmasks */
--/* Inactivity timer value for transitions into U1, in microseconds.
-- * Timeout can be up to 127us.  0xFF means an infinite timeout.
-- */
--#define PORT_U1_TIMEOUT(p)	((p) & 0xff)
--#define PORT_U1_TIMEOUT_MASK	0xff
--/* Inactivity timer value for transitions into U2 */
--#define PORT_U2_TIMEOUT(p)	(((p) & 0xff) << 8)
--#define PORT_U2_TIMEOUT_MASK	(0xff << 8)
--/* Bits 24:31 for port testing */
--
--/* USB2 Protocol PORTSPMSC */
--#define	PORT_L1S_MASK		7
--#define	PORT_L1S_SUCCESS	1
--#define	PORT_RWE		(1 << 3)
--#define	PORT_HIRD(p)		(((p) & 0xf) << 4)
--#define	PORT_HIRD_MASK		(0xf << 4)
--#define	PORT_L1DS_MASK		(0xff << 8)
--#define	PORT_L1DS(p)		(((p) & 0xff) << 8)
--#define	PORT_HLE		(1 << 16)
--#define PORT_TEST_MODE_SHIFT	28
--
--/* USB3 Protocol PORTLI  Port Link Information */
--#define PORT_RX_LANES(p)	(((p) >> 16) & 0xf)
--#define PORT_TX_LANES(p)	(((p) >> 20) & 0xf)
--
--/* USB2 Protocol PORTHLPMC */
--#define PORT_HIRDM(p)((p) & 3)
--#define PORT_L1_TIMEOUT(p)(((p) & 0xff) << 2)
--#define PORT_BESLD(p)(((p) & 0xf) << 10)
--
--/* use 512 microseconds as USB2 LPM L1 default timeout. */
--#define XHCI_L1_TIMEOUT		512
--
--/* Set default HIRD/BESL value to 4 (350/400us) for USB2 L1 LPM resume latency.
-- * Safe to use with mixed HIRD and BESL systems (host and device) and is used
-- * by other operating systems.
-- *
-- * XHCI 1.0 errata 8/14/12 Table 13 notes:
-- * "Software should choose xHC BESL/BESLD field values that do not violate a
-- * device's resume latency requirements,
-- * e.g. not program values > '4' if BLC = '1' and a HIRD device is attached,
-- * or not program values < '4' if BLC = '0' and a BESL device is attached.
-- */
--#define XHCI_DEFAULT_BESL	4
--
--/*
-- * USB3 specification define a 360ms tPollingLFPSTiemout for USB3 ports
-- * to complete link training. usually link trainig completes much faster
-- * so check status 10 times with 36ms sleep in places we need to wait for
-- * polling to complete.
-- */
--#define XHCI_PORT_POLLING_LFPS_TIME  36
--
- /**
-  * struct xhci_intr_reg - Interrupt Register Set
-  * @irq_pending:	IMAN - Interrupt Management Register.  Used to enable
-@@ -972,6 +717,7 @@ struct xhci_virt_ep {
- 	/* Bandwidth checking storage */
- 	struct xhci_bw_info	bw_info;
- 	struct list_head	bw_endpoint_list;
-+	unsigned long		stop_time;
- 	/* Isoch Frame ID checking storage */
- 	int			next_frame_id;
- 	/* Use new Isoch TRB layout needed for extended TBC support */
-@@ -1285,7 +1031,7 @@ enum xhci_setup_dev {
- /* Set TR Dequeue Pointer command TRB fields, 6.4.3.9 */
- #define TRB_TO_STREAM_ID(p)		((((p) & (0xffff << 16)) >> 16))
- #define STREAM_ID_FOR_TRB(p)		((((p)) & 0xffff) << 16)
--#define SCT_FOR_TRB(p)			(((p) << 1) & 0x7)
-+#define SCT_FOR_TRB(p)			(((p) & 0x7) << 1)
- 
- /* Link TRB specific fields */
- #define TRB_TC			(1<<1)
-@@ -1874,7 +1620,7 @@ struct xhci_hcd {
- #define XHCI_RESET_ON_RESUME	BIT_ULL(7)
- #define	XHCI_SW_BW_CHECKING	BIT_ULL(8)
- #define XHCI_AMD_0x96_HOST	BIT_ULL(9)
--#define XHCI_TRUST_TX_LENGTH	BIT_ULL(10)
-+#define XHCI_TRUST_TX_LENGTH	BIT_ULL(10) /* Deprecated */
- #define XHCI_LPM_SUPPORT	BIT_ULL(11)
- #define XHCI_INTEL_HOST		BIT_ULL(12)
- #define XHCI_SPURIOUS_REBOOT	BIT_ULL(13)
-@@ -1913,6 +1659,9 @@ struct xhci_hcd {
- #define XHCI_RESET_TO_DEFAULT	BIT_ULL(44)
- #define XHCI_ZHAOXIN_TRB_FETCH	BIT_ULL(45)
- #define XHCI_ZHAOXIN_HOST	BIT_ULL(46)
-+#define XHCI_WRITE_64_HI_LO	BIT_ULL(47)
-+#define XHCI_CDNS_SCTX_QUIRK	BIT_ULL(48)
-+#define XHCI_ETRON_HOST	BIT_ULL(49)
- 
- 	unsigned int		num_active_eps;
- 	unsigned int		limit_active_eps;
-@@ -2014,8 +1763,6 @@ static inline bool xhci_has_one_roothub(struct xhci_hcd *xhci)
- 	dev_err(xhci_to_hcd(xhci)->self.controller , fmt , ## args)
- #define xhci_warn(xhci, fmt, args...) \
- 	dev_warn(xhci_to_hcd(xhci)->self.controller , fmt , ## args)
--#define xhci_warn_ratelimited(xhci, fmt, args...) \
--	dev_warn_ratelimited(xhci_to_hcd(xhci)->self.controller , fmt , ## args)
- #define xhci_info(xhci, fmt, args...) \
- 	dev_info(xhci_to_hcd(xhci)->self.controller , fmt , ## args)
- 
-@@ -2205,6 +1952,7 @@ void xhci_ring_doorbell_for_active_rings(struct xhci_hcd *xhci,
- void xhci_cleanup_command_queue(struct xhci_hcd *xhci);
- void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring);
- unsigned int count_trbs(u64 addr, u64 len);
-+void xhci_process_cancelled_tds(struct xhci_virt_ep *ep);
- 
- /* xHCI roothub code */
- void xhci_set_link_state(struct xhci_hcd *xhci, struct xhci_port *port,
+ 		toggle ^= 1;
+ 		data += pktsze;
++		urb_buf += pktsze;
+ 		this_sg_len -= pktsze;
+ 		len -= maxsze;
+ 		if (this_sg_len <= 0) {
 -- 
 2.34.1
 
diff --git a/recipes-kernel/linux/files/0022-Add-USB-Virtual-Hub-Controller-driver-for-ast2700.patch b/recipes-kernel/linux/files/0022-Add-USB-Virtual-Hub-Controller-driver-for-ast2700.patch
index 8cb4b24..218e16f 100644
--- a/recipes-kernel/linux/files/0022-Add-USB-Virtual-Hub-Controller-driver-for-ast2700.patch
+++ b/recipes-kernel/linux/files/0022-Add-USB-Virtual-Hub-Controller-driver-for-ast2700.patch
@@ -1,16 +1,16 @@
-From 1f9ef31b7955d1173da998447903db05f6a7356c Mon Sep 17 00:00:00 2001
-From: "yung-sheng.huang" <yung-sheng.huang@fii-na.corp-partner.google.com>
-Date: Wed, 16 Apr 2025 09:50:26 +0800
-Subject: [PATCH 22/26] Add USB Virtual Hub Controller driver for ast2700
+From 126c380af01e0b348a0681834d190a0ac0f57f00 Mon Sep 17 00:00:00 2001
+From: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+Date: Thu, 17 Jul 2025 13:31:16 +0800
+Subject: [PATCH] Add USB Virtual Hub Controller driver for ast2700
 
-This is base on aspeed SDK 9.06.
+This is base on aspeed SDK 9.07.
 
 Source:
 AspeedTech-BMC github:
 https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/
-(cherry picked from commit v00.06.06)
+(cherry picked from commit v00.06.07)
 
-Signed-off-by: yung-sheng.huang <yung-sheng.huang@fii-na.corp-partner.google.com>
+Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
 ---
  drivers/usb/gadget/udc/aspeed-vhub/Kconfig |   5 +-
  drivers/usb/gadget/udc/aspeed-vhub/core.c  | 180 +++++++++++++++++++++
@@ -299,7 +299,7 @@
  	{ }
  };
 diff --git a/drivers/usb/gadget/udc/aspeed-vhub/dev.c b/drivers/usb/gadget/udc/aspeed-vhub/dev.c
-index 573109ca5..32fe010ec 100644
+index a09f72772..f5de980d2 100644
 --- a/drivers/usb/gadget/udc/aspeed-vhub/dev.c
 +++ b/drivers/usb/gadget/udc/aspeed-vhub/dev.c
 @@ -116,10 +116,14 @@ static int ast_vhub_dev_feature(struct ast_vhub_dev *d,
diff --git a/recipes-kernel/linux/files/0023-Add-PCIe-RC-driver-for-ast2700.patch b/recipes-kernel/linux/files/0023-Add-PCIe-RC-driver-for-ast2700.patch
index 92dc68c..a09552c 100644
--- a/recipes-kernel/linux/files/0023-Add-PCIe-RC-driver-for-ast2700.patch
+++ b/recipes-kernel/linux/files/0023-Add-PCIe-RC-driver-for-ast2700.patch
@@ -1,23 +1,21 @@
-From 8a77841d549ce03cbadfa900bddb24e0b83fce33 Mon Sep 17 00:00:00 2001
-From: "yung-sheng.huang" <yung-sheng.huang@fii-na.corp-partner.google.com>
-Date: Wed, 16 Apr 2025 09:53:36 +0800
-Subject: [PATCH 23/26] Add PCIe RC driver for ast2700
+From 7c221f84ce7721ad62d3eca28c2603bcec240364 Mon Sep 17 00:00:00 2001
+From: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+Date: Thu, 17 Jul 2025 13:38:21 +0800
+Subject: [PATCH] Add PCIe RC driver for ast2700
 
-This is base on aspeed SDK 9.06.
+This is base on aspeed SDK 9.07.
 
 Source:
 AspeedTech-BMC github:
 https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/
-(cherry picked from commit v00.06.06)
+(cherry picked from commit v00.06.07)
 
-Signed-off-by: yung-sheng.huang <yung-sheng.huang@fii-na.corp-partner.google.com>
+Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
 ---
- drivers/pci/controller/Kconfig          |    9 +
- drivers/pci/controller/Makefile         |    1 +
- drivers/pci/controller/aspeed_pciecfg.c |  135 +++
- drivers/pci/controller/pcie-aspeed.c    | 1375 +++++++++++++++++++++++
- 4 files changed, 1520 insertions(+)
- create mode 100644 drivers/pci/controller/aspeed_pciecfg.c
+ drivers/pci/controller/Kconfig       |    9 +
+ drivers/pci/controller/Makefile      |    1 +
+ drivers/pci/controller/pcie-aspeed.c | 1168 ++++++++++++++++++++++++++
+ 3 files changed, 1178 insertions(+)
  create mode 100644 drivers/pci/controller/pcie-aspeed.c
 
 diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
@@ -52,153 +50,12 @@
  obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o
  obj-$(CONFIG_PCIE_ROCKCHIP_EP) += pcie-rockchip-ep.o
  obj-$(CONFIG_PCIE_ROCKCHIP_HOST) += pcie-rockchip-host.o
-diff --git a/drivers/pci/controller/aspeed_pciecfg.c b/drivers/pci/controller/aspeed_pciecfg.c
-new file mode 100644
-index 000000000..718f814ce
---- /dev/null
-+++ b/drivers/pci/controller/aspeed_pciecfg.c
-@@ -0,0 +1,135 @@
-+// SPDX-License-Identifier: GPL-2.0+
-+/*
-+ * PCIe host controller driver for ASPEED PCIe Bridge
-+ *
-+ */
-+#include <linux/of_platform.h>
-+#include <linux/mfd/syscon.h>
-+#include <linux/regmap.h>
-+#include <linux/irqdomain.h>
-+#include <linux/kernel.h>
-+#include <linux/reset.h>
-+#include <linux/of.h>
-+#include <linux/of_irq.h>
-+#include <linux/of_address.h>
-+#include <linux/gpio/consumer.h>
-+
-+struct aspeed_pciecfg {
-+	void __iomem *reg;
-+	struct regmap *ahbc;
-+	struct reset_control *rst;
-+	struct reset_control *rc_low_rst;
-+	struct reset_control *rc_high_rst;
-+	struct gpio_desc *rc_low_rst_gpio;
-+	struct gpio_desc *rc_high_rst_gpio;
-+};
-+
-+static const struct of_device_id aspeed_pciecfg_of_match[] = {
-+	{ .compatible = "aspeed,ast2600-pciecfg", },
-+	{}
-+};
-+
-+#define AHBC_UNLOCK	0xAEED1A03
-+static void aspeed_pciecfg_init(struct aspeed_pciecfg *pciecfg)
-+{
-+	reset_control_assert(pciecfg->rst);
-+
-+	if (pciecfg->rc_low_rst_gpio) {
-+		gpiod_set_value(pciecfg->rc_low_rst_gpio, 1);
-+		gpiod_set_value(pciecfg->rc_low_rst_gpio, 0);
-+	} else if (pciecfg->rc_low_rst) {
-+		reset_control_deassert(pciecfg->rc_low_rst);
-+		reset_control_assert(pciecfg->rc_low_rst);
-+	}
-+
-+	if (pciecfg->rc_high_rst_gpio) {
-+		gpiod_set_value(pciecfg->rc_high_rst_gpio, 1);
-+		gpiod_set_value(pciecfg->rc_high_rst_gpio, 0);
-+	} else if (pciecfg->rc_high_rst) {
-+		reset_control_deassert(pciecfg->rc_high_rst);
-+		reset_control_assert(pciecfg->rc_high_rst);
-+	}
-+
-+	mdelay(5);
-+	reset_control_deassert(pciecfg->rst);
-+
-+	//workaround : Send vender define message for avoid when PCIE RESET send unknown message out
-+	writel(0x34000000, pciecfg->reg + 0x10);
-+	writel(0x0000007f, pciecfg->reg + 0x14);
-+	writel(0x00001a03, pciecfg->reg + 0x18);
-+	writel(0x00000000, pciecfg->reg + 0x1C);
-+
-+	regmap_write(pciecfg->ahbc, 0x00, AHBC_UNLOCK);
-+	regmap_update_bits(pciecfg->ahbc, 0x8C, BIT(5), BIT(5));
-+	regmap_write(pciecfg->ahbc, 0x00, 0x1);
-+
-+	//ahb to pcie rc
-+	writel(0xe0006000, pciecfg->reg + 0x60);
-+	writel(0x00000000, pciecfg->reg + 0x64);
-+	writel(0xFFFFFFFF, pciecfg->reg + 0x68);
-+
-+	//PCIe Host Enable
-+	writel(BIT(0), pciecfg->reg + 0x00);
-+}
-+
-+static int aspeed_pciecfg_probe(struct platform_device *pdev)
-+{
-+	struct aspeed_pciecfg *pciecfg;
-+	struct device *dev = &pdev->dev;
-+
-+	pciecfg = devm_kzalloc(&pdev->dev, sizeof(*pciecfg), GFP_KERNEL);
-+	if (!pciecfg)
-+		return -ENOMEM;
-+
-+	pciecfg->reg = devm_platform_ioremap_resource(pdev, 0);
-+	if (IS_ERR(pciecfg->reg))
-+		return PTR_ERR(pciecfg->reg);
-+
-+	pciecfg->rst = devm_reset_control_get_exclusive(&pdev->dev, NULL);
-+	if (IS_ERR(pciecfg->rst)) {
-+		dev_err(&pdev->dev, "can't get pcie reset\n");
-+		return PTR_ERR(pciecfg->rst);
-+	}
-+
-+	pciecfg->rc_low_rst = NULL;
-+	if (of_device_is_available(of_parse_phandle(dev->of_node, "aspeed,pcie0", 0))) {
-+		pciecfg->rc_low_rst_gpio =
-+			devm_gpiod_get_optional(dev, "pcie0-perst",
-+						GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
-+		if (!pciecfg->rc_low_rst_gpio) {
-+			pciecfg->rc_low_rst = devm_reset_control_get_shared(&pdev->dev, "rc_low");
-+			if (IS_ERR(pciecfg->rc_low_rst))
-+				dev_info(&pdev->dev, "No RC low reset\n");
-+		}
-+	}
-+
-+	pciecfg->rc_high_rst = NULL;
-+	if (of_device_is_available(of_parse_phandle(dev->of_node, "aspeed,pcie1", 0))) {
-+		pciecfg->rc_high_rst_gpio =
-+			devm_gpiod_get_optional(dev, "pcie1-perst",
-+						GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
-+		if (!pciecfg->rc_high_rst_gpio) {
-+			pciecfg->rc_high_rst = devm_reset_control_get_shared(&pdev->dev, "rc_high");
-+			if (IS_ERR(pciecfg->rc_high_rst))
-+				dev_info(&pdev->dev, "No RC high reset\n");
-+		}
-+	}
-+
-+	pciecfg->ahbc = syscon_regmap_lookup_by_compatible("aspeed,aspeed-ahbc");
-+	if (IS_ERR(pciecfg->ahbc))
-+		return IS_ERR(pciecfg->ahbc);
-+
-+	aspeed_pciecfg_init(pciecfg);
-+
-+	return 0;
-+}
-+
-+static struct platform_driver aspeed_pciecfg_driver = {
-+	.driver = {
-+		.name = "aspeed-pciecfg",
-+		.suppress_bind_attrs = true,
-+		.of_match_table = aspeed_pciecfg_of_match,
-+	},
-+	.probe = aspeed_pciecfg_probe,
-+};
-+builtin_platform_driver(aspeed_pciecfg_driver);
 diff --git a/drivers/pci/controller/pcie-aspeed.c b/drivers/pci/controller/pcie-aspeed.c
 new file mode 100644
-index 000000000..fd2d4c38e
+index 000000000..e19a6f553
 --- /dev/null
 +++ b/drivers/pci/controller/pcie-aspeed.c
-@@ -0,0 +1,1375 @@
+@@ -0,0 +1,1168 @@
 +// SPDX-License-Identifier: GPL-2.0+
 +/*
 + * PCIe host controller driver for ASPEED PCIe Bridge
@@ -225,75 +82,63 @@
 +#include <linux/bitfield.h>
 +#include <linux/clk.h>
 +
-+/*	PCI Host Controller registers */
-+#define ASPEED_PCIE_CLASS_CODE		0x04
-+#define ASPEED_PCIE_GLOBAL			0x30
-+#define ASPEED_PCIE_CFG_DIN			0x50
-+#define ASPEED_PCIE_CFG3			0x58
-+#define ASPEED_PCIE_LOCK			0x7C
-+#define ASPEED_PCIE_LINK			0xC0
-+#define ASPEED_PCIE_INT				0xC4
-+#define ASPEED_PCIE_LINK_STS		0xD0
-+/*	AST_PCIE_CFG2			0x04 */
-+#define PCIE_CFG_CLASS_CODE(x)	((x) << 8)
-+#define PCIE_CFG_REV_ID(x)		(x)
-+/*	PEHR10: Miscellaneous Control 10H Register */
-+#define DATALINK_REPORT_CAPABLE	BIT(4)
-+/*	PEHR14: Miscellaneous Control 14H Register */
-+#define HOTPLUG_CAPABLE_ENABLE	BIT(6)
-+#define HOTPLUG_SURPRISE_ENABLE	BIT(5)
-+#define ATTENTION_BUTTON_ENALBE	BIT(0)
-+/*	PEHR30: Miscellaneous Control 30H Register */
-+/* Disable RC synchronous reset when link up to link down*/
-+#define RC_SYNC_RESET_DISABLE	BIT(20)
-+#define ROOT_COMPLEX_ID(x)		((x) << 4)
++#define MAX_MSI_HOST_IRQS	64
++
++/* AST2600 AHBC Registers */
++#define AHBC_KEY		0x00
++#define AHBC_UNLOCK			0xAEED1A03
++#define AHBC_ADDR_MAPPING	0x8C
++#define PCIE_RC_MEMORY_EN		BIT(5)
++
++/* AST2600 PCIe Host Controller Registers */
++#define PEHR_MISC_10		0x10
++#define DATALINK_REPORT_CAPABLE		BIT(4)
++#define PEHR_MISC_14		0x14
++#define HOTPLUG_CAPABLE_ENABLE		BIT(6)
++#define HOTPLUG_SURPRISE_ENABLE		BIT(5)
++#define ATTENTION_BUTTON_ENALBE		BIT(0)
++#define PEHR_GLOBAL		0x30
++#define RC_SYNC_RESET_DISABLE		BIT(20)
 +#define PCIE_RC_SLOT_ENABLE		BIT(1)
-+/*	AST_PCIE_LOCK			0x7C */
-+#define PCIE_UNLOCK				0xa8
-+/*	AST_PCIE_LINK			0xC0 */
++#define ROOT_COMPLEX_ID(x)		((x) << 4)
++#define PEHR_LOCK		0x7C
++#define PCIE_UNLOCK			0xa8
++#define PEHR_LINK		0xC0
 +#define PCIE_LINK_STS			BIT(5)
-+/*  ASPEED_PCIE_LINK_STS	0xD0 */
-+#define PCIE_LINK_5G			BIT(17)
-+#define PCIE_LINK_2_5G			BIT(16)
 +
-+/*	H2X Controller registers */
-+/* reg 0x08 */
++/* AST2600 H2X Controller Registers */
++/* Common Registers*/
++#define H2X_INT_STS		0x08
 +#define PCIE_TX_IDLE_CLEAR		BIT(0)
-+
-+/* reg 0x24 */
++#define H2X_TX_DESC0		0x10
++#define H2X_TX_DESC1		0x14
++#define H2X_TX_DESC2		0x18
++#define H2X_TX_DESC3		0x1C
++#define H2X_TX_DESC_DATA	0x20
++#define H2X_STS			0x24
 +#define PCIE_TX_IDLE			BIT(31)
-+
 +#define PCIE_STATUS_OF_TX		GENMASK(25, 24)
-+#define	PCIE_RC_TX_COMPLETE		0
-+#define	PCIE_RC_L_TX_COMPLETE	BIT(24)
-+#define	PCIE_RC_H_TX_COMPLETE	BIT(25)
-+
++#define	PCIE_RC_L_TX_COMPLETE		BIT(24)
++#define	PCIE_RC_H_TX_COMPLETE		BIT(25)
 +#define PCIE_TRIGGER_TX			BIT(0)
-+
-+/* reg 0x80, 0xC0 */
-+#define PCIE_RX_TAG_MASK		GENMASK(23, 16)
++#define H2X_AHB_ADDR_CONFIG0	0x60
++#define H2X_AHB_ADDR_CONFIG1	0x64
++#define H2X_AHB_ADDR_CONFIG2	0x68
++/* Device Registers */
++#define H2X_DEV_CTRL		0x00
 +#define PCIE_RX_DMA_EN			BIT(9)
 +#define PCIE_RX_LINEAR			BIT(8)
 +#define PCIE_RX_MSI_SEL			BIT(7)
 +#define PCIE_RX_MSI_EN			BIT(6)
-+#define PCIE_1M_ADDRESS_EN		BIT(5)
 +#define PCIE_UNLOCK_RX_BUFF		BIT(4)
-+#define PCIE_RX_TLP_TAG_MATCH	BIT(3)
-+#define PCIE_Wait_RX_TLP_CLR	BIT(2)
++#define PCIE_Wait_RX_TLP_CLR		BIT(2)
 +#define PCIE_RC_RX_ENABLE		BIT(1)
 +#define PCIE_RC_ENABLE			BIT(0)
-+
-+/* reg 0x88, 0xC8 : RC ISR */
-+#define PCIE_RC_CPLCA_ISR		BIT(6)
-+#define PCIE_RC_CPLUR_ISR		BIT(5)
++#define H2X_DEV_STS		0x08
 +#define PCIE_RC_RX_DONE_ISR		BIT(4)
-+
-+#define PCIE_RC_INTD_ISR		BIT(3)
-+#define PCIE_RC_INTC_ISR		BIT(2)
-+#define PCIE_RC_INTB_ISR		BIT(1)
-+#define PCIE_RC_INTA_ISR		BIT(0)
-+
-+#define MAX_MSI_HOST_IRQS		64
++#define H2X_DEV_RX_DESC_DATA	0x0C
++#define H2X_DEV_RX_DESC1	0x14
++#define H2X_DEV_TX_TAG		0x3C
 +
 +/* AST2700 H2X */
 +#define H2X_CTRL		0x00
@@ -359,34 +204,31 @@
 +struct aspeed_pcie {
 +	struct pci_host_bridge *host;
 +	struct device *dev;
-+	void __iomem *reg;	//rc slot base
++	void __iomem *reg;
 +	struct regmap *ahbc;
-+	struct regmap *device;
++	struct regmap *cfg;
++	struct regmap *pciephy;
++	struct clk *clock;
++	const struct aspeed_pcie_rc_platform *platform;
++
 +	int domain;
-+	char name[10];
 +	u32 msi_address;
-+	int irq;
 +	u8 tx_tag;
-+	struct regmap *cfg;	//pciecfg
-+	struct regmap *pciephy; //pcie_phy
++
 +	struct reset_control *h2xrst;
 +	struct reset_control *perst;
-+	/* INTx */
-+	struct irq_domain *irq_domain;	//irq_domain
-+	// msi
-+	struct irq_domain *dev_domain;	//inner_domain
++
++	struct irq_domain *irq_domain;
++	struct irq_domain *dev_domain;
 +	struct irq_domain *msi_domain;
-+	struct mutex lock;  /* protect bitmap variable */
++	struct mutex lock;
++
 +	int hotplug_event;
 +	struct gpio_desc *perst_ep_in;
 +	struct gpio_desc *perst_rc_out;
 +	struct gpio_desc *perst_owner;
 +	struct delayed_work rst_dwork;
 +	DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_HOST_IRQS);
-+	struct clk *clock;
-+
-+	const struct aspeed_pcie_rc_platform *platform;
-+	bool support_msi;
 +};
 +
 +static void aspeed_pcie_intx_ack_irq(struct irq_data *d)
@@ -430,23 +272,19 @@
 +	return 0;
 +}
 +
-+/* INTx IRQ Domain operations */
 +static const struct irq_domain_ops aspeed_intx_domain_ops = {
 +	.map = aspeed_pcie_intx_map,
 +};
 +
-+static void aspeed_pcie_intr_handler(struct irq_desc *desc)
++static irqreturn_t aspeed_pcie_intr_handler(int irq, void *dev_id)
 +{
-+	struct aspeed_pcie *pcie = irq_desc_get_handler_data(desc);
-+	struct irq_chip *irqchip = irq_desc_get_chip(desc);
++	struct aspeed_pcie *pcie = dev_id;
 +	const struct aspeed_pcie_rc_platform *platform = pcie->platform;
 +	unsigned long status;
 +	unsigned long intx;
 +	u32 bit;
 +	int i;
 +
-+	chained_irq_enter(irqchip, desc);
-+
 +	intx = readl(pcie->reg + platform->reg_intx_sts) & 0xf;
 +	if (intx) {
 +		for_each_set_bit(bit, &intx, PCI_NUM_INTX)
@@ -467,10 +305,10 @@
 +			}
 +		}
 +	}
-+	chained_irq_exit(irqchip, desc);
++
++	return IRQ_HANDLED;
 +}
 +
-+//optional : set_slot_power_limit
 +void aspeed_pcie_set_slot_power_limit(struct aspeed_pcie *pcie)
 +{
 +	u32 cfg_val, isr;
@@ -479,45 +317,33 @@
 +	writel(BIT(4) | readl(pcie->reg), pcie->reg);
 +
 +	pcie->tx_tag %= 0x7;
-+	regmap_write(pcie->cfg, 0x10, 0x74000001);
-+	switch (pcie->domain) {
-+	case 0: //write for 0.8.0
-+		regmap_write(pcie->cfg, 0x14, 0x00400050 | (pcie->tx_tag << 8));
-+		break;
-+	case 1: //write for 0.4.0
-+		regmap_write(pcie->cfg, 0x14, 0x00200050 | (pcie->tx_tag << 8));
-+		break;
-+	}
++	regmap_write(pcie->cfg, H2X_TX_DESC0, 0x74000001);
++	regmap_write(pcie->cfg, H2X_TX_DESC1, 0x00200050 | (pcie->tx_tag << 8));
++	regmap_write(pcie->cfg, H2X_TX_DESC2, 0);
++	regmap_write(pcie->cfg, H2X_TX_DESC3, 0);
++	regmap_write(pcie->cfg, H2X_TX_DESC_DATA, 0x1a);
 +
-+	regmap_write(pcie->cfg, 0x18, 0);
-+	regmap_write(pcie->cfg, 0x1C, 0);
-+	regmap_write(pcie->cfg, 0x20, 0x1a);
++	regmap_write_bits(pcie->cfg, H2X_STS, PCIE_TRIGGER_TX, PCIE_TRIGGER_TX);
 +
-+	//trigger tx
-+	regmap_write_bits(pcie->cfg, 0x24, PCIE_TRIGGER_TX, PCIE_TRIGGER_TX);
-+
-+	//wait tx idle
-+	ret = regmap_read_poll_timeout(pcie->cfg, 0x24, cfg_val,
-+				       (cfg_val & PCIE_TX_IDLE), 0, 10);
++	ret = regmap_read_poll_timeout(pcie->cfg, H2X_STS, cfg_val,
++				       (cfg_val & PCIE_TX_IDLE), 0, 50);
 +	if (ret)
 +		goto out;
 +
-+	//write clr tx idle
-+	regmap_write_bits(pcie->cfg, 0x08, PCIE_TX_IDLE_CLEAR,
++	regmap_write_bits(pcie->cfg, H2X_INT_STS, PCIE_TX_IDLE_CLEAR,
 +			  PCIE_TX_IDLE_CLEAR);
 +
-+	//check tx status
-+	regmap_read(pcie->cfg, 0x24, &cfg_val);
++	regmap_read(pcie->cfg, H2X_STS, &cfg_val);
 +	switch (cfg_val & PCIE_STATUS_OF_TX) {
 +	case PCIE_RC_L_TX_COMPLETE:
 +	case PCIE_RC_H_TX_COMPLETE:
-+		ret = readl_poll_timeout(pcie->reg + 0x08, isr,
-+					 (isr & PCIE_RC_RX_DONE_ISR), 0, 10);
++		ret = readl_poll_timeout(pcie->reg + H2X_DEV_STS, isr,
++					 (isr & PCIE_RC_RX_DONE_ISR), 0, 50);
 +		if (ret)
 +			dev_err(pcie->dev, "[%d] : tx timeout [%x]\n",
 +				pcie->domain, isr);
 +
-+		writel(readl(pcie->reg + 0x08), pcie->reg + 0x08);
++		writel(readl(pcie->reg + H2X_DEV_STS), pcie->reg + H2X_DEV_STS);
 +		break;
 +	}
 +out:
@@ -529,61 +355,23 @@
 +{
 +	struct aspeed_pcie *pcie = bus->sysdata;
 +	u32 bdf_offset;
-+	int rx_done_fail = 0;
++	int rx_done_fail = 0, slot = PCI_SLOT(devfn);
 +	u32 cfg_val, isr, type = 0;
 +	u32 link_sts = 0;
 +	int ret;
 +
-+	//H2X80[4] (unlock) is write-only.
-+	//Driver may set H2X80[4]=1 before triggering next TX config.
-+	writel(BIT(4) | readl(pcie->reg), pcie->reg);
++	/* Driver may set unlock RX buffere before triggering next TX config */
++	writel(PCIE_UNLOCK_RX_BUFF | readl(pcie->reg + H2X_DEV_CTRL),
++	       pcie->reg + H2X_DEV_CTRL);
 +
-+	switch (pcie->domain) {
-+	case 0:
-+		if (!bus->number) {
-+			switch (PCI_SLOT(devfn)) {
-+			case 0:
-+			case 4:
-+				break;
-+			default:
-+				*val = 0xffffffff;
-+				return PCIBIOS_SUCCESSFUL;
-+			}
-+		}
-+
-+		if (bus->number)
-+			type = 1;
-+		else
-+			type = 0;
-+		break;
-+	case 1:
-+		if (bus->number == 128) {
-+			switch (PCI_SLOT(devfn)) {
-+			case 0:
-+			case 8:
-+				break;
-+			default:
-+				*val = 0xffffffff;
-+				return PCIBIOS_SUCCESSFUL;
-+			}
-+		}
-+
-+		if (bus->number > 128)
-+			type = 1;
-+		else
-+			type = 0;
-+		break;
-+	}
-+
-+	dev_dbg(pcie->dev, "[%d]R:b d f [%d:%d:%d] devfn %x\n",
-+		pcie->domain, bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), devfn);
++	if (bus->number == 128 && slot != 0 && slot != 8)
++		return PCIBIOS_DEVICE_NOT_FOUND;
++	type = (bus->number > 128);
 +
 +	if (type) {
-+		regmap_read(pcie->pciephy, ASPEED_PCIE_LINK, &link_sts);
-+		if (!(link_sts & PCIE_LINK_STS)) {
-+			*val = 0xffffffff;
-+			return PCIBIOS_SUCCESSFUL;
-+		}
++		regmap_read(pcie->pciephy, PEHR_LINK, &link_sts);
++		if (!(link_sts & PCIE_LINK_STS))
++			return PCIBIOS_DEVICE_NOT_FOUND;
 +	}
 +
 +	bdf_offset = ((bus->number) << 24) | (PCI_SLOT(devfn) << 19) |
@@ -591,62 +379,55 @@
 +
 +	pcie->tx_tag %= 0x7;
 +
-+	regmap_write(pcie->cfg, 0x10, 0x04000001 | (type << 24));
-+	regmap_write(pcie->cfg, 0x14, 0x0000200f | (pcie->tx_tag << 8));
-+	regmap_write(pcie->cfg, 0x18, bdf_offset);
-+	regmap_write(pcie->cfg, 0x1C, 0x00000000);
++	regmap_write(pcie->cfg, H2X_TX_DESC0, 0x04000001 | (type << 24));
++	regmap_write(pcie->cfg, H2X_TX_DESC1, 0x0000200f | (pcie->tx_tag << 8));
++	regmap_write(pcie->cfg, H2X_TX_DESC2, bdf_offset);
++	regmap_write(pcie->cfg, H2X_TX_DESC3, 0x00000000);
 +
-+	//trigger tx
-+	regmap_write_bits(pcie->cfg, 0x24, PCIE_TRIGGER_TX, PCIE_TRIGGER_TX);
++	regmap_write_bits(pcie->cfg, H2X_STS, PCIE_TRIGGER_TX, PCIE_TRIGGER_TX);
 +
-+	//wait tx idle
-+	//todo find timeout and time period
-+	ret = regmap_read_poll_timeout(pcie->cfg, 0x24, cfg_val,
-+				       (cfg_val & PCIE_TX_IDLE), 0, 10);
++	ret = regmap_read_poll_timeout(pcie->cfg, H2X_STS, cfg_val,
++				       (cfg_val & PCIE_TX_IDLE), 0, 50);
 +	if (ret) {
-+		dev_err(pcie->dev, "[%d] : tx idle timeout [%x]\n",
-+			pcie->domain, cfg_val);
-+		*val = 0xffffffff;
++		dev_err(pcie->dev,
++			"[%X:%02X:%02X.%02X]CR tx timeout sts: 0x%08x\n",
++			pcie->domain, bus->number, PCI_SLOT(devfn),
++			PCI_FUNC(devfn), cfg_val);
 +		goto out;
 +	}
 +
-+	//write clr tx idle
-+	regmap_write_bits(pcie->cfg, 0x08, PCIE_TX_IDLE_CLEAR,
++	regmap_write_bits(pcie->cfg, H2X_INT_STS, PCIE_TX_IDLE_CLEAR,
 +			  PCIE_TX_IDLE_CLEAR);
 +
-+	//check tx status
-+	regmap_read(pcie->cfg, 0x24, &cfg_val);
-+
++	regmap_read(pcie->cfg, H2X_STS, &cfg_val);
 +	switch (cfg_val & PCIE_STATUS_OF_TX) {
-+	case PCIE_RC_L_TX_COMPLETE: //domain 0
-+		if (pcie->domain != 0)
-+			dev_err(pcie->dev, "[%d] : tx complete no correct\n",
-+				pcie->domain);
-+		fallthrough;
-+	case PCIE_RC_H_TX_COMPLETE: //domain 1
-+		ret = readl_poll_timeout(pcie->reg + 0x08, isr,
-+					 (isr & PCIE_RC_RX_DONE_ISR), 0, 10);
++	case PCIE_RC_L_TX_COMPLETE:
++	case PCIE_RC_H_TX_COMPLETE:
++		ret = readl_poll_timeout(pcie->reg + H2X_DEV_STS, isr,
++					 (isr & PCIE_RC_RX_DONE_ISR), 0, 50);
 +		if (ret) {
-+			dev_err(pcie->dev, "[%d] : rx done timeout\n",
-+				pcie->domain);
++			dev_err(pcie->dev,
++				"[%X:%02X:%02X.%02X]CR rx timeoutsts: 0x%08x\n",
++				pcie->domain, bus->number, PCI_SLOT(devfn),
++				PCI_FUNC(devfn), isr);
 +			rx_done_fail = 1;
-+			*val = 0xffffffff;
++			*val = ~0;
 +		}
 +		if (!rx_done_fail) {
-+			if (readl(pcie->reg + 0x14) & BIT(13))
-+				*val = 0xffffffff;
++			if (readl(pcie->reg + H2X_DEV_RX_DESC1) & BIT(13))
++				*val = ~0;
 +			else
-+				*val = readl(pcie->reg + 0x0C);
++				*val = readl(pcie->reg + H2X_DEV_RX_DESC_DATA);
 +		}
 +
-+		writel(BIT(4) | readl(pcie->reg), pcie->reg);
-+		writel(readl(pcie->reg + 0x08), pcie->reg + 0x08);
++		writel(PCIE_UNLOCK_RX_BUFF | readl(pcie->reg + H2X_DEV_CTRL),
++		       pcie->reg + H2X_DEV_CTRL);
 +		break;
 +	case PCIE_STATUS_OF_TX:
-+		*val = 0xffffffff;
++		*val = ~0;
 +		break;
-+	default: //read rc data
-+		regmap_read(pcie->cfg, 0x0C, &cfg_val);
++	default:
++		regmap_read(pcie->cfg, H2X_DEV_RX_DESC_DATA, &cfg_val);
 +		*val = cfg_val;
 +		break;
 +	}
@@ -660,28 +441,16 @@
 +		break;
 +	}
 +
-+	dev_dbg(pcie->dev, "R:b d f [%d:%d:%d] where:%x : %x\n",
-+		bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where, *val);
-+
 +#ifdef CONFIG_HOTPLUG_PCI
-+	switch (pcie->domain) {
-+	case 0:
-+		if (where == 0x9a && bus->number == 0x0 &&
-+		    (PCI_SLOT(devfn) == 0x4) && (PCI_FUNC(devfn) == 0x0) &&
-+		    pcie->hotplug_event)
-+			*val |= PCI_EXP_SLTSTA_ABP;
-+		break;
-+	case 1:
-+		if (where == 0x9a && bus->number == 128 &&
-+		    (PCI_SLOT(devfn) == 0x8) && (PCI_FUNC(devfn) == 0x0) &&
-+		    pcie->hotplug_event)
-+			*val |= PCI_EXP_SLTSTA_ABP;
-+		break;
-+	}
++	if (where == 0x9a && bus->number == 128 && (PCI_SLOT(devfn) == 0x8) &&
++	    (PCI_FUNC(devfn) == 0x0) && pcie->hotplug_event)
++		*val |= PCI_EXP_SLTSTA_ABP;
 +#endif
++	ret = PCIBIOS_SUCCESSFUL;
 +out:
++	writel(readl(pcie->reg + H2X_DEV_STS), pcie->reg + H2X_DEV_STS);
 +	pcie->tx_tag++;
-+	return PCIBIOS_SUCCESSFUL;
++	return ret;
 +}
 +
 +static int aspeed_ast2600_wr_conf(struct pci_bus *bus, unsigned int devfn,
@@ -696,60 +465,25 @@
 +	int ret;
 +
 +#ifdef CONFIG_HOTPLUG_PCI
-+	switch (pcie->domain) {
-+	case 0:
-+		if (where == 0x9a && bus->number == 0x0 &&
-+		    (PCI_SLOT(devfn) == 0x4) && (PCI_FUNC(devfn) == 0x0) &&
-+		    pcie->hotplug_event && (val & PCI_EXP_SLTSTA_ABP)) {
-+			pcie->hotplug_event = 0;
-+			return PCIBIOS_SUCCESSFUL;
-+		}
-+		break;
-+	case 1:
-+		if (where == 0x9a && bus->number == 128 &&
-+		    (PCI_SLOT(devfn) == 0x8) && (PCI_FUNC(devfn) == 0x0) &&
-+		    pcie->hotplug_event && (val & PCI_EXP_SLTSTA_ABP)) {
-+			pcie->hotplug_event = 0;
-+			return PCIBIOS_SUCCESSFUL;
-+		}
-+		break;
++	if (where == 0x9a && bus->number == 128 && (PCI_SLOT(devfn) == 0x8) &&
++	    (PCI_FUNC(devfn) == 0x0) && pcie->hotplug_event &&
++	    (val & PCI_EXP_SLTSTA_ABP)) {
++		pcie->hotplug_event = 0;
++		return PCIBIOS_SUCCESSFUL;
 +	}
 +#endif
 +
-+	dev_dbg(pcie->dev, "W b d f [%d:%d:%d] : where %x : val %x\n",
-+		bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where, val);
-+
-+	//H2X80[4] (unlock) is write-only.
-+	//Driver may set H2X80[4]=1 before triggering next TX config.
-+	writel(BIT(4) | readl(pcie->reg), pcie->reg);
++	/* Driver may set unlock RX buffere before triggering next TX config */
++	writel(PCIE_UNLOCK_RX_BUFF | readl(pcie->reg + H2X_DEV_CTRL),
++	       pcie->reg + H2X_DEV_CTRL);
 +
 +	switch (size) {
 +	case 1:
-+		switch (where % 4) {
-+		case 0:
-+			byte_en = 0x1;
-+			break;
-+		case 1:
-+			byte_en = 0x2;
-+			break;
-+		case 2:
-+			byte_en = 0x4;
-+			break;
-+		case 3:
-+			byte_en = 0x8;
-+			break;
-+		}
++		byte_en = 1 << (where % 4);
 +		val = (val & 0xff) << shift;
 +		break;
 +	case 2:
-+		switch ((where >> 1) % 2) {
-+		case 0:
-+			byte_en = 0x3;
-+			break;
-+		case 1:
-+			byte_en = 0xc;
-+			break;
-+		}
++		byte_en = 0x3 << (2 * ((where >> 1) % 2));
 +		val = (val & 0xffff) << shift;
 +		break;
 +	default:
@@ -757,67 +491,56 @@
 +		break;
 +	}
 +
-+	switch (pcie->domain) {
-+	case 0:
-+		if (bus->number)
-+			type = 1;
-+		else
-+			type = 0;
-+		break;
-+	case 1:
-+		if (bus->number > 128)
-+			type = 1;
-+		else
-+			type = 0;
-+		break;
-+	}
++	type = (bus->number > 128);
 +
 +	bdf_offset = (bus->number << 24) | (PCI_SLOT(devfn) << 19) |
 +		     (PCI_FUNC(devfn) << 16) | (where & ~3);
 +	pcie->tx_tag %= 0x7;
 +
-+	regmap_write(pcie->cfg, 0x10, 0x44000001 | (type << 24));
-+	regmap_write(pcie->cfg, 0x14,
++	regmap_write(pcie->cfg, H2X_TX_DESC0, 0x44000001 | (type << 24));
++	regmap_write(pcie->cfg, H2X_TX_DESC1,
 +		     0x00002000 | (pcie->tx_tag << 8) | byte_en);
-+	regmap_write(pcie->cfg, 0x18, bdf_offset);
-+	regmap_write(pcie->cfg, 0x1C, 0x00000000);
-+	regmap_write(pcie->cfg, 0x20, val);
++	regmap_write(pcie->cfg, H2X_TX_DESC2, bdf_offset);
++	regmap_write(pcie->cfg, H2X_TX_DESC3, 0x00000000);
++	regmap_write(pcie->cfg, H2X_TX_DESC_DATA, val);
 +
-+	//trigger tx
-+	regmap_write_bits(pcie->cfg, 0x24, PCIE_TRIGGER_TX, PCIE_TRIGGER_TX);
++	regmap_write_bits(pcie->cfg, H2X_STS, PCIE_TRIGGER_TX, PCIE_TRIGGER_TX);
 +
-+	//wait tx idle
-+	//todo find timeout and time period
-+	ret = regmap_read_poll_timeout(pcie->cfg, 0x24, cfg_val,
-+				       (cfg_val & PCIE_TX_IDLE), 0, 10);
++	ret = regmap_read_poll_timeout(pcie->cfg, H2X_STS, cfg_val,
++				       (cfg_val & PCIE_TX_IDLE), 0, 50);
 +	if (ret) {
-+		dev_err(pcie->dev, "[%d] : tx idle timeout [%x]\n",
-+			pcie->domain, cfg_val);
++		dev_err(pcie->dev,
++			"[%X:%02X:%02X.%02X]CT tx timeout sts: 0x%08x\n",
++			pcie->domain, bus->number, PCI_SLOT(devfn),
++			PCI_FUNC(devfn), cfg_val);
++		ret = PCIBIOS_SET_FAILED;
 +		goto out;
 +	}
 +
-+	//write clr tx idle
-+	regmap_write_bits(pcie->cfg, 0x08, PCIE_TX_IDLE_CLEAR,
++	regmap_write_bits(pcie->cfg, H2X_INT_STS, PCIE_TX_IDLE_CLEAR,
 +			  PCIE_TX_IDLE_CLEAR);
 +
-+	//check tx status
-+	regmap_read(pcie->cfg, 0x24, &cfg_val);
-+
++	regmap_read(pcie->cfg, H2X_STS, &cfg_val);
 +	switch (cfg_val & PCIE_STATUS_OF_TX) {
 +	case PCIE_RC_L_TX_COMPLETE:
 +	case PCIE_RC_H_TX_COMPLETE:
-+		ret = readl_poll_timeout(pcie->reg + 0x08, isr,
-+					 (isr & PCIE_RC_RX_DONE_ISR), 0, 10);
-+		if (ret)
-+			dev_err(pcie->dev, "[%d] : tx timeout\n", pcie->domain);
-+
-+		writel(readl(pcie->reg + 0x08), pcie->reg + 0x08);
++		ret = readl_poll_timeout(pcie->reg + H2X_DEV_STS, isr,
++					 (isr & PCIE_RC_RX_DONE_ISR), 0, 50);
++		if (ret) {
++			dev_err(pcie->dev,
++				"[%X:%02X:%02X.%02X]CT rx timeout sts: 0x%08x\n",
++				pcie->domain, bus->number, PCI_SLOT(devfn),
++				PCI_FUNC(devfn), isr);
++			ret = PCIBIOS_SET_FAILED;
++			goto out;
++		}
 +		break;
 +	}
-+
++	ret = PCIBIOS_SUCCESSFUL;
 +out:
++	writel(readl(pcie->reg + H2X_DEV_STS), pcie->reg + H2X_DEV_STS);
 +	pcie->tx_tag++;
-+	return PCIBIOS_SUCCESSFUL;
++	return ret;
 +}
 +
 +static bool aspeed_ast2700_get_link(struct aspeed_pcie *pcie)
@@ -844,10 +567,8 @@
 +	u8 type;
 +	int ret;
 +
-+	if ((bus->number == 0 && devfn != 0) || !aspeed_ast2700_get_link(pcie)) {
-+		*val = 0xffffffff;
-+		return PCIBIOS_SUCCESSFUL;
-+	}
++	if ((bus->number == 0 && devfn != 0))
++		return PCIBIOS_DEVICE_NOT_FOUND;
 +
 +	if (bus->number == 0) {
 +		/* Internal access to bridge */
@@ -855,6 +576,9 @@
 +		writel(CFGI_TLP_FIRE, pcie->reg + H2X_CFGI_CTRL);
 +		*val = readl(pcie->reg + H2X_CFGI_RET_DATA);
 +	} else {
++		if (!aspeed_ast2700_get_link(pcie))
++			return PCIBIOS_DEVICE_NOT_FOUND;
++
 +		bdf_offset = ((bus->number) << 24) | (PCI_SLOT(devfn) << 19) |
 +			     (PCI_FUNC(devfn) << 16) | (where & ~3);
 +
@@ -862,16 +586,12 @@
 +
 +		type = (bus->number == 1) ? PCI_HEADER_TYPE_NORMAL : PCI_HEADER_TYPE_BRIDGE;
 +
-+		/* Prepare TLP */
 +		writel(CRG_READ_FMTTYPE(type) | CRG_PAYLOAD_SIZE, pcie->reg + H2X_CFGE_TLP_1ST);
 +		writel(0x40100F | (pcie->tx_tag << 8), pcie->reg + H2X_CFGE_TLP_NEXT);
 +		writel(bdf_offset, pcie->reg + H2X_CFGE_TLP_NEXT);
-+		/* Clear tx & rx status */
 +		writel(CFGE_TX_IDLE | CFGE_RX_BUSY, pcie->reg + H2X_CFGE_INT_STS);
-+		/* Issue command */
 +		writel(CFGE_TLP_FIRE, pcie->reg + H2X_CFGE_CTRL);
 +
-+		/* Check TX */
 +		ret = readl_poll_timeout(pcie->reg + H2X_CFGE_INT_STS, status,
 +					 (status & CFGE_TX_IDLE), 0, 50);
 +		if (ret) {
@@ -879,11 +599,9 @@
 +				"[%X:%02X:%02X.%02X]CR tx timeout sts: 0x%08x\n",
 +				pcie->domain, bus->number, PCI_SLOT(devfn),
 +				PCI_FUNC(devfn), status);
-+			*val = 0xffffffff;
 +			goto out;
 +		}
 +
-+		/* Check RX */
 +		ret = readl_poll_timeout(pcie->reg + H2X_CFGE_INT_STS, status,
 +					 (status & CFGE_RX_BUSY), 0, 50000);
 +		if (ret) {
@@ -891,7 +609,6 @@
 +				"[%X:%02X:%02X.%02X]CR rx timeoutsts: 0x%08x\n",
 +				pcie->domain, bus->number, PCI_SLOT(devfn),
 +				PCI_FUNC(devfn), status);
-+			*val = 0xffffffff;
 +			goto out;
 +		}
 +		*val = readl(pcie->reg + H2X_CFGE_RET_DATA);
@@ -906,11 +623,14 @@
 +		break;
 +	}
 +
-+out:
-+	/* Clear status */
 +	writel(status, pcie->reg + H2X_CFGE_INT_STS);
 +	pcie->tx_tag++;
 +	return PCIBIOS_SUCCESSFUL;
++out:
++	*val = ~0;
++	writel(status, pcie->reg + H2X_CFGE_INT_STS);
++	pcie->tx_tag++;
++	return PCIBIOS_SET_FAILED;
 +}
 +
 +static int aspeed_ast2700_wr_conf(struct pci_bus *bus, unsigned int devfn,
@@ -922,8 +642,8 @@
 +	u32 bdf_offset, status, type;
 +	int ret;
 +
-+	if ((bus->number == 0 && devfn != 0) || !aspeed_ast2700_get_link(pcie))
-+		return PCIBIOS_SUCCESSFUL;
++	if ((bus->number == 0 && devfn != 0))
++		return PCIBIOS_DEVICE_NOT_FOUND;
 +
 +	switch (size) {
 +	case 1:
@@ -931,7 +651,7 @@
 +		val = (val & 0xff) << shift;
 +		break;
 +	case 2:
-+		byte_en = (((where >> 1) % 2) == 0) ? 0x3 : 0xc;
++		byte_en = 0x3 << (2 * ((where >> 1) % 2));
 +		val = (val & 0xffff) << shift;
 +		break;
 +	default:
@@ -945,50 +665,53 @@
 +		writel(val, pcie->reg + H2X_CFGI_WR_DATA);
 +		writel(CFGI_TLP_FIRE, pcie->reg + H2X_CFGI_CTRL);
 +	} else {
++		if (!aspeed_ast2700_get_link(pcie))
++			return PCIBIOS_SET_FAILED;
++
 +		bdf_offset = (bus->number << 24) | (PCI_SLOT(devfn) << 19) |
 +			     (PCI_FUNC(devfn) << 16) | (where & ~3);
 +		pcie->tx_tag %= 0xF;
 +
 +		type = (bus->number == 1) ? PCI_HEADER_TYPE_NORMAL : PCI_HEADER_TYPE_BRIDGE;
 +
-+		/* Prepare TLP */
 +		writel(CRG_WRITE_FMTTYPE(type) | CRG_PAYLOAD_SIZE, pcie->reg + H2X_CFGE_TLP_1ST);
 +		writel(0x401000 | (pcie->tx_tag << 8) | byte_en, pcie->reg + H2X_CFGE_TLP_NEXT);
 +		writel(bdf_offset, pcie->reg + H2X_CFGE_TLP_NEXT);
 +		writel(val, pcie->reg + H2X_CFGE_TLP_NEXT);
-+		/* Clear tx & rx status */
 +		writel(CFGE_TX_IDLE | CFGE_RX_BUSY, pcie->reg + H2X_CFGE_INT_STS);
-+		/* Issue command */
 +		writel(CFGE_TLP_FIRE, pcie->reg + H2X_CFGE_CTRL);
 +
-+		/* Check TX */
 +		ret = readl_poll_timeout(pcie->reg + H2X_CFGE_INT_STS, status,
 +					 (status & CFGE_TX_IDLE), 0, 50);
-+		if (ret)
++		if (ret) {
 +			dev_err(pcie->dev,
 +				"[%X:%02X:%02X.%02X]CT tx timeout sts: 0x%08x\n",
 +				pcie->domain, bus->number, PCI_SLOT(devfn),
 +				PCI_FUNC(devfn), status);
++			ret = PCIBIOS_SET_FAILED;
++			goto out;
++		}
 +
-+		/* Check RX */
 +		ret = readl_poll_timeout(pcie->reg + H2X_CFGE_INT_STS, status,
 +					 (status & CFGE_RX_BUSY), 0, 50000);
-+		if (ret)
++		if (ret) {
 +			dev_err(pcie->dev,
 +				"[%X:%02X:%02X.%02X]CT rx timeout sts: 0x%08x\n",
 +				pcie->domain, bus->number, PCI_SLOT(devfn),
 +				PCI_FUNC(devfn), status);
++			ret = PCIBIOS_SET_FAILED;
++			goto out;
++		}
 +
 +		(void)readl(pcie->reg + H2X_CFGE_RET_DATA);
 +	}
-+
-+	/* Clear status */
++	ret = PCIBIOS_SUCCESSFUL;
++out:
 +	writel(status, pcie->reg + H2X_CFGE_INT_STS);
 +	pcie->tx_tag++;
-+	return PCIBIOS_SUCCESSFUL;
++	return ret;
 +}
 +
-+/* PCIe operations */
 +static struct pci_ops aspeed_ast2600_pcie_ops = {
 +	.read = aspeed_ast2600_rd_conf,
 +	.write = aspeed_ast2600_wr_conf,
@@ -1064,12 +787,6 @@
 +	mutex_unlock(&pcie->lock);
 +}
 +
-+static void aspeed_pcie_msi_enable(struct aspeed_pcie *pcie)
-+{
-+	writel(0xffffffff, pcie->reg + pcie->platform->reg_msi_en);
-+	writel(0xffffffff, pcie->reg + pcie->platform->reg_msi_en + 0x04);
-+}
-+
 +static const struct irq_domain_ops aspeed_msi_domain_ops = {
 +	.alloc = aspeed_irq_msi_domain_alloc,
 +	.free = aspeed_irq_msi_domain_free,
@@ -1085,80 +802,94 @@
 +
 +static struct msi_domain_info aspeed_msi_domain_info = {
 +	.flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
-+		  MSI_FLAG_MULTI_PCI_MSI),
++		  MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX),
 +	.chip = &aspeed_msi_irq_chip,
 +};
 +#endif
 +
++static void aspeed_pcie_irq_domain_free(struct aspeed_pcie *pcie)
++{
++	if (pcie->irq_domain) {
++		irq_domain_remove(pcie->irq_domain);
++		pcie->irq_domain = NULL;
++	}
++#ifdef CONFIG_PCI_MSI
++	if (pcie->msi_domain) {
++		irq_domain_remove(pcie->msi_domain);
++		pcie->msi_domain = NULL;
++	}
++
++	if (pcie->dev_domain) {
++		irq_domain_remove(pcie->dev_domain);
++		pcie->dev_domain = NULL;
++	}
++#endif
++}
++
 +static int aspeed_pcie_init_irq_domain(struct aspeed_pcie *pcie)
 +{
 +	struct device *dev = pcie->dev;
 +	struct device_node *node = dev->of_node;
 +	struct device_node *pcie_intc_node;
-+#ifdef CONFIG_PCI_MSI
-+	struct fwnode_handle *fwnode = dev_fwnode(pcie->dev);
-+	struct irq_domain *parent;
-+#endif
++	int ret;
 +
-+	/* Setup INTx */
 +	pcie_intc_node = of_get_next_child(node, NULL);
-+	if (!pcie_intc_node) {
-+		dev_err(dev, "No PCIe Intc node found\n");
-+		return -ENODEV;
-+	}
++	if (!pcie_intc_node)
++		return dev_err_probe(dev, -ENODEV, "No PCIe Intc node found\n");
 +
 +	pcie->irq_domain =
 +		irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX, &aspeed_intx_domain_ops, pcie);
-+
++	of_node_put(pcie_intc_node);
 +	if (!pcie->irq_domain) {
-+		dev_err(dev, "failed to get an INTx IRQ domain\n");
-+		return -ENOMEM;
++		ret = dev_err_probe(dev, -ENOMEM, "failed to get an INTx IRQ domain\n");
++		goto err;
 +	}
 +
-+	of_node_put(pcie_intc_node);
-+
-+	if (!pcie->support_msi)
-+		return 0;
++	writel(0, pcie->reg + pcie->platform->reg_intx_en);
++	writel(~0, pcie->reg + pcie->platform->reg_intx_sts);
 +
 +#ifdef CONFIG_PCI_MSI
 +	pcie->dev_domain =
 +		irq_domain_add_linear(NULL, MAX_MSI_HOST_IRQS, &aspeed_msi_domain_ops, pcie);
 +	if (!pcie->dev_domain) {
-+		dev_err(pcie->dev, "failed to create IRQ domain\n");
-+		return -ENOMEM;
++		ret = dev_err_probe(pcie->dev, -ENOMEM, "failed to create IRQ domain\n");
++		goto err;
 +	}
 +
-+	pcie->msi_domain =
-+		pci_msi_create_irq_domain(fwnode, &aspeed_msi_domain_info, pcie->dev_domain);
++	pcie->msi_domain = pci_msi_create_irq_domain(dev_fwnode(pcie->dev), &aspeed_msi_domain_info,
++						     pcie->dev_domain);
 +	if (!pcie->msi_domain) {
-+		dev_err(pcie->dev, "failed to create MSI domain\n");
-+		irq_domain_remove(parent);
-+		return -ENOMEM;
++		ret = dev_err_probe(pcie->dev, -ENOMEM, "failed to create MSI domain\n");
++		goto err;
 +	}
-+	aspeed_pcie_msi_enable(pcie);
-+#endif
 +
++	writel(~0, pcie->reg + pcie->platform->reg_msi_en);
++	writel(~0, pcie->reg + pcie->platform->reg_msi_en + 0x04);
++	writel(~0, pcie->reg + pcie->platform->reg_msi_sts);
++	writel(~0, pcie->reg + pcie->platform->reg_msi_sts + 0x04);
++#endif
 +	return 0;
++err:
++	aspeed_pcie_irq_domain_free(pcie);
++	return ret;
 +}
 +
 +static void aspeed_pcie_port_init(struct aspeed_pcie *pcie)
 +{
 +	u32 link_sts = 0;
 +
-+	//plda init
-+	regmap_write(pcie->pciephy, ASPEED_PCIE_LOCK, PCIE_UNLOCK);
++	regmap_write(pcie->pciephy, PEHR_LOCK, PCIE_UNLOCK);
 +#ifdef CONFIG_HOTPLUG_PCI
-+	regmap_write(pcie->pciephy, ASPEED_PCIE_GLOBAL,
++	regmap_write(pcie->pciephy, PEHR_GLOBAL,
 +		     RC_SYNC_RESET_DISABLE | ROOT_COMPLEX_ID(0x3) |
 +			     PCIE_RC_SLOT_ENABLE);
-+	regmap_write(pcie->pciephy, 0x10, 0xd7040022 | DATALINK_REPORT_CAPABLE);
-+	regmap_write(pcie->pciephy, 0x14,
++	regmap_write(pcie->pciephy, PEHR_MISC_10, 0xd7040022 | DATALINK_REPORT_CAPABLE);
++	regmap_write(pcie->pciephy, PEHR_MISC_14,
 +		     HOTPLUG_CAPABLE_ENABLE | HOTPLUG_SURPRISE_ENABLE |
 +			     ATTENTION_BUTTON_ENALBE);
 +#else
-+	regmap_write(pcie->pciephy, ASPEED_PCIE_GLOBAL, ROOT_COMPLEX_ID(0x3));
++	regmap_write(pcie->pciephy, PEHR_GLOBAL, ROOT_COMPLEX_ID(0x3));
 +#endif
-+	/* Toggle the gpio to reset the devices on RC bus */
 +	if (pcie->perst_rc_out) {
 +		mdelay(100);
 +		gpiod_set_value(pcie->perst_rc_out, 1);
@@ -1167,40 +898,18 @@
 +	reset_control_deassert(pcie->perst);
 +	mdelay(500);
 +
-+	//clr intx isr
-+	writel(0x0, pcie->reg + 0x04);
++	writel(PCIE_RX_DMA_EN | PCIE_RX_LINEAR | PCIE_RX_MSI_SEL | PCIE_RX_MSI_EN |
++	       PCIE_Wait_RX_TLP_CLR | PCIE_RC_RX_ENABLE | PCIE_RC_ENABLE,
++	       pcie->reg + H2X_DEV_CTRL);
 +
-+	//clr msi isr
-+	writel(0xFFFFFFFF, pcie->reg + 0x28);
-+	writel(0xFFFFFFFF, pcie->reg + 0x2c);
++	writel(0x28, pcie->reg + H2X_DEV_TX_TAG);
 +
-+	//rc_l
-+	//	0x80: 040 set bit7 0
-+	//	0xC0: 080 set bit7 1
-+	if (pcie->domain)
-+		writel(PCIE_RX_DMA_EN | PCIE_RX_LINEAR | PCIE_RX_MSI_SEL |
-+			       PCIE_RX_MSI_EN | PCIE_Wait_RX_TLP_CLR |
-+			       PCIE_RC_RX_ENABLE | PCIE_RC_ENABLE,
-+		       pcie->reg);
-+	else
-+		writel(PCIE_RX_DMA_EN | PCIE_RX_LINEAR | PCIE_RX_MSI_EN |
-+			       PCIE_Wait_RX_TLP_CLR | PCIE_RC_RX_ENABLE |
-+			       PCIE_RC_ENABLE,
-+		       pcie->reg);
-+
-+	//assign debug tx tag
-+	writel(0x28, pcie->reg + 0x3C);
-+
-+	regmap_read(pcie->pciephy, ASPEED_PCIE_LINK, &link_sts);
-+	if (link_sts & PCIE_LINK_STS) {
-+		//		aspeed_pcie_set_slot_power_limit(pcie);
++	regmap_read(pcie->pciephy, PEHR_LINK, &link_sts);
++	if (link_sts & PCIE_LINK_STS)
++		// aspeed_pcie_set_slot_power_limit(pcie);
 +		dev_info(pcie->dev, "PCIE- Link up\n");
-+		//		if (readl(pcie->pciereg_base
-+		//				+ ASPEED_PCIE_LINK_STS) & PCIE_LINK_2_5G)
-+		//			dev_info(pcie->dev, "PCIE- Link up : 2.5G\n");
-+	} else {
++	else
 +		dev_info(pcie->dev, "PCIE- Link down\n");
-+	}
 +}
 +
 +
@@ -1263,7 +972,7 @@
 +	}
 +	mdelay(10);
 +
-+	regmap_read(pcie->pciephy, ASPEED_PCIE_LINK, &link_sts);
++	regmap_read(pcie->pciephy, PEHR_LINK, &link_sts);
 +	if (link_sts & PCIE_LINK_STS)
 +		dev_info(pcie->dev, "PCIE- Link up\n");
 +	else
@@ -1282,91 +991,50 @@
 +	return IRQ_HANDLED;
 +}
 +
-+#define AHBC_UNLOCK	0xAEED1A03
 +static int aspeed_ast2600_setup(struct platform_device *pdev)
 +{
 +	struct aspeed_pcie *pcie = platform_get_drvdata(pdev);
-+	struct device_node *cfg_node;
-+	int err;
++	struct device *dev = pcie->dev;
++	int ret;
 +
-+	pcie->perst_rc_out =
-+		devm_gpiod_get_optional(pcie->dev, "perst-rc-out",
-+					GPIOD_OUT_LOW |
-+					GPIOD_FLAGS_BIT_NONEXCLUSIVE);
-+
-+	pcie->perst = devm_reset_control_get_exclusive(pcie->dev, NULL);
-+	if (IS_ERR(pcie->perst)) {
-+		dev_err(&pdev->dev, "can't get pcie phy reset\n");
-+		return PTR_ERR(pcie->perst);
-+	}
-+	reset_control_assert(pcie->perst);
-+
-+	pcie->ahbc = syscon_regmap_lookup_by_compatible("aspeed,aspeed-ahbc");
++	pcie->ahbc = syscon_regmap_lookup_by_phandle(dev->of_node, "aspeed,ahbc");
 +	if (IS_ERR(pcie->ahbc))
-+		return IS_ERR(pcie->ahbc);
++		return dev_err_probe(dev, PTR_ERR(pcie->ahbc), "failed to map ahbc base\n");
 +
-+	cfg_node =
-+		of_find_compatible_node(NULL, NULL, "aspeed,ast2600-pciecfg");
-+	if (cfg_node) {
-+		pcie->cfg = syscon_node_to_regmap(cfg_node);
-+		if (IS_ERR(pcie->cfg))
-+			return PTR_ERR(pcie->cfg);
-+	}
++	reset_control_assert(pcie->h2xrst);
++	mdelay(5);
++	reset_control_deassert(pcie->h2xrst);
 +
-+	//workaround : Send vender define message for avoid when PCIE RESET send unknown message out
-+	regmap_write(pcie->cfg, 0x10, 0x34000000);
-+	regmap_write(pcie->cfg, 0x14, 0x0000007f);
-+	regmap_write(pcie->cfg, 0x18, 0x00001a03);
-+	regmap_write(pcie->cfg, 0x1c, 0x00000000);
++	regmap_write(pcie->ahbc, AHBC_KEY, AHBC_UNLOCK);
++	regmap_update_bits(pcie->ahbc, AHBC_ADDR_MAPPING, PCIE_RC_MEMORY_EN, PCIE_RC_MEMORY_EN);
++	regmap_write(pcie->ahbc, AHBC_KEY, 0x1);
 +
-+	regmap_write(pcie->ahbc, 0x00, AHBC_UNLOCK);
-+	regmap_update_bits(pcie->ahbc, 0x8C, BIT(5), BIT(5));
-+	regmap_write(pcie->ahbc, 0x00, 0x1);
++	regmap_write(pcie->cfg, H2X_AHB_ADDR_CONFIG0, 0xe0006000);
++	regmap_write(pcie->cfg, H2X_AHB_ADDR_CONFIG1, 0);
++	regmap_write(pcie->cfg, H2X_AHB_ADDR_CONFIG2, ~0);
 +
-+	//ahb to pcie rc
-+	regmap_write(pcie->cfg, 0x60, 0xe0006000);
-+	regmap_write(pcie->cfg, 0x64, 0x00000000);
-+	regmap_write(pcie->cfg, 0x68, 0xFFFFFFFF);
-+
-+	//PCIe Host Enable
-+	regmap_write(pcie->cfg, 0x00, BIT(0));
-+
-+	//080 can't config for msi
-+	pcie->support_msi = (pcie->domain) ? false : true;
++	regmap_write(pcie->cfg, H2X_CTRL, H2X_BRIDGE_EN);
 +
 +	aspeed_pcie_port_init(pcie);
 +
 +	pcie->host->ops = &aspeed_ast2600_pcie_ops;
 +
-+	err = sysfs_create_file(&pdev->dev.kobj, &dev_attr_hotplug.attr);
-+	if (err) {
-+		dev_err(&pdev->dev, "unable to create sysfs interface\n");
-+		return err;
-+	}
++	ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_hotplug.attr);
++	if (ret)
++		return dev_err_probe(&pdev->dev, ret, "unable to create sysfs interface\n");
 +
-+	if (pcie->domain) {
-+		pcie->perst_ep_in =
-+			devm_gpiod_get_optional(pcie->dev, "perst-ep-in", GPIOD_IN);
-+		if (pcie->perst_ep_in) {
-+			gpiod_set_debounce(pcie->perst_ep_in, 100);
-+			irq_set_irq_type(gpiod_to_irq(pcie->perst_ep_in),
-+					 IRQ_TYPE_EDGE_BOTH);
-+			err = devm_request_irq(pcie->dev,
-+					       gpiod_to_irq(pcie->perst_ep_in),
-+					       pcie_rst_irq_handler,
-+					       IRQF_SHARED, "PERST monitor",
-+					       pcie);
-+			if (err) {
-+				dev_err(pcie->dev,
-+					"Failed to request gpio irq %d\n", err);
-+				return err;
-+			}
-+			INIT_DELAYED_WORK(&pcie->rst_dwork,
-+					  aspeed_pcie_reset_work);
-+		}
-+		pcie->perst_owner =
-+			devm_gpiod_get_optional(pcie->dev, "perst-owner", GPIOD_OUT_HIGH);
++	pcie->perst_ep_in = devm_gpiod_get_optional(pcie->dev, "perst-ep-in", GPIOD_IN);
++	if (pcie->perst_ep_in) {
++		gpiod_set_debounce(pcie->perst_ep_in, 100);
++		irq_set_irq_type(gpiod_to_irq(pcie->perst_ep_in), IRQ_TYPE_EDGE_BOTH);
++		ret = devm_request_irq(pcie->dev, gpiod_to_irq(pcie->perst_ep_in),
++				       pcie_rst_irq_handler, IRQF_SHARED, "PERST monitor", pcie);
++		if (ret)
++			return dev_err_probe(pcie->dev, ret, "Failed to request gpio irq\n");
++		INIT_DELAYED_WORK(&pcie->rst_dwork, aspeed_pcie_reset_work);
 +	}
++	pcie->perst_owner =
++		devm_gpiod_get_optional(pcie->dev, "perst-owner", GPIOD_OUT_HIGH);
 +
 +	return 0;
 +}
@@ -1376,64 +1044,38 @@
 +	struct aspeed_pcie *pcie = platform_get_drvdata(pdev);
 +	struct device *dev = pcie->dev;
 +	u32 cfg_val;
-+	int ret;
-+
-+	pcie->h2xrst = devm_reset_control_get(dev, "h2x");
-+	if (IS_ERR(pcie->h2xrst))
-+		return dev_err_probe(dev, PTR_ERR(pcie->h2xrst), "failed to get h2x reset\n");
-+
-+	pcie->perst = devm_reset_control_get(dev, "perst");
-+	if (IS_ERR(pcie->perst))
-+		return dev_err_probe(dev, PTR_ERR(pcie->perst), "failed to get perst reset\n");
-+
-+	pcie->device = syscon_regmap_lookup_by_phandle(dev->of_node, "aspeed,device");
-+	if (IS_ERR(pcie->device))
-+		return dev_err_probe(dev, PTR_ERR(pcie->device), "failed to map device base\n");
-+
-+	pcie->clock = clk_get(dev, NULL);
-+	if (IS_ERR(pcie->clock))
-+		return dev_err_probe(dev, PTR_ERR(pcie->clock), "failed to request clock\n");
-+
-+	ret = clk_prepare_enable(pcie->clock);
-+	if (ret) {
-+		dev_err(dev, "Failed to enable the clock.\n");
-+		goto out_clk_free;
-+	}
 +
 +	reset_control_assert(pcie->perst);
 +
-+	regmap_write(pcie->pciephy, PEHR_VID_DID, 0x11501a02);
 +	regmap_write(pcie->pciephy, PEHR_MISC_70, 0xa00c0);
 +	regmap_write(pcie->pciephy, PEHR_MISC_78, 0x80030);
 +	regmap_write(pcie->pciephy, PEHR_MISC_58, LOCAL_SCALE_SUP);
 +
-+	regmap_update_bits(pcie->device, SCU_60,
++	regmap_update_bits(pcie->cfg, SCU_60,
 +			   RC_E2M_PATH_EN | RC_H2XS_PATH_EN | RC_H2XD_PATH_EN | RC_H2XX_PATH_EN |
 +				   RC_UPSTREAM_MEM_EN,
 +			   RC_E2M_PATH_EN | RC_H2XS_PATH_EN | RC_H2XD_PATH_EN | RC_H2XX_PATH_EN |
 +				   RC_UPSTREAM_MEM_EN);
-+	regmap_write(pcie->device, SCU_64, 0xff00ff00);
-+	regmap_write(pcie->device, SCU_70, 0);
-+	regmap_write(pcie->device, SCU_78, (pcie->domain == 1) ? BIT(31) : 0);
++	regmap_write(pcie->cfg, SCU_64, 0xff00ff00);
++	regmap_write(pcie->cfg, SCU_70, 0);
++	regmap_write(pcie->cfg, SCU_78, (pcie->domain == 1) ? BIT(31) : 0);
 +
 +	reset_control_assert(pcie->h2xrst);
 +	mdelay(10);
 +	reset_control_deassert(pcie->h2xrst);
 +
 +	regmap_write(pcie->pciephy, PEHR_MISC_5C, 0x40000000);
-+	/* Configure to Root port */
 +	regmap_read(pcie->pciephy, PEHR_MISC_60, &cfg_val);
 +	regmap_write(pcie->pciephy, PEHR_MISC_60,
 +		     (cfg_val & ~PORT_TPYE) | FIELD_PREP(PORT_TPYE, PORT_TYPE_ROOT));
 +
-+	/* PCIe Host Enable */
 +	writel(0, pcie->reg + H2X_CTRL);
 +	writel(H2X_BRIDGE_EN | H2X_BRIDGE_DIRECT_EN, pcie->reg + H2X_CTRL);
 +
 +	/* The BAR mapping:
-+	 * CPU Node0: 0x60000000
-+	 * CPU Node1: 0x80000000
-+	 * IO       : 0xa0000000
++	 * CPU Node0(domain 0): 0x60000000
++	 * CPU Node1(domain 1): 0x80000000
++	 * IO       (domain 2): 0xa0000000
 +	 */
 +	writel(0x60000000 + (0x20000000 * pcie->domain), pcie->reg + H2X_REMAP_DIRECT_ADDR);
 +
@@ -1441,34 +1083,18 @@
 +	writel(0x3, pcie->reg + H2X_REMAP_PREF_ADDR);
 +
 +	reset_control_deassert(pcie->perst);
++	if (pcie->perst_rc_out)
++		gpiod_set_value(pcie->perst_rc_out, 1);
 +	mdelay(1000);
 +
-+	/* Clear INTx isr */
-+	writel(0, pcie->reg + pcie->platform->reg_intx_sts);
-+
-+	/* Clear MSI/MSI-X isr */
-+	writel(~0, pcie->reg + pcie->platform->reg_msi_sts);
-+	writel(~0, pcie->reg + pcie->platform->reg_msi_sts + 0x04);
-+
 +	pcie->host->ops = &aspeed_ast2700_pcie_ops;
 +
-+	aspeed_msi_domain_info.flags |= MSI_FLAG_PCI_MSIX;
-+	pcie->support_msi = true;
-+
-+	if (!aspeed_ast2700_get_link(pcie)) {
++	if (!aspeed_ast2700_get_link(pcie))
 +		dev_info(dev, "PCIe Link DOWN");
-+		ret = -ENODEV;
-+		goto out_dis_clk;
-+	}
++	else
++		dev_info(dev, "PCIe Link UP");
 +
-+	dev_info(dev, "PCIe Link UP");
 +	return 0;
-+out_dis_clk:
-+	clk_disable_unprepare(pcie->clock);
-+out_clk_free:
-+	if (pcie->clock)
-+		clk_put(pcie->clock);
-+	return ret;
 +}
 +
 +static int aspeed_pcie_probe(struct platform_device *pdev)
@@ -1478,7 +1104,7 @@
 +	struct aspeed_pcie *pcie;
 +	struct device_node *node = dev->of_node;
 +	const void *md = of_device_get_match_data(dev);
-+	int err;
++	int irq, ret;
 +
 +	if (!md)
 +		return -ENODEV;
@@ -1500,32 +1126,53 @@
 +	of_property_read_u32(node, "msi_address", &pcie->msi_address);
 +	of_property_read_u32(node, "linux,pci-domain", &pcie->domain);
 +
-+	pcie->pciephy = syscon_regmap_lookup_by_phandle(node, "pciephy");
-+	if (IS_ERR(pcie->pciephy))
-+		return dev_err_probe(dev, PTR_ERR(pcie->pciephy), "failed to map pciephy base\n");
++	pcie->cfg = syscon_regmap_lookup_by_phandle(dev->of_node, "aspeed,pciecfg");
++	if (IS_ERR(pcie->cfg))
++		return dev_err_probe(dev, PTR_ERR(pcie->cfg), "Failed to map pciecfg base\n");
 +
-+	err = pcie->platform->setup(pdev);
-+	if (err) {
-+		dev_err(dev, "Setup PCIe RC failed\n");
-+		return err;
-+	}
++	pcie->pciephy = syscon_regmap_lookup_by_phandle(node, "aspeed,pciephy");
++	if (IS_ERR(pcie->pciephy))
++		return dev_err_probe(dev, PTR_ERR(pcie->pciephy), "Failed to map pciephy base\n");
++
++	pcie->h2xrst = devm_reset_control_get_exclusive(dev, "h2x");
++	if (IS_ERR(pcie->h2xrst))
++		return dev_err_probe(dev, PTR_ERR(pcie->h2xrst), "Failed to get h2x reset\n");
++
++	pcie->perst = devm_reset_control_get_exclusive(dev, "perst");
++	if (IS_ERR(pcie->perst))
++		return dev_err_probe(dev, PTR_ERR(pcie->perst), "Failed to get perst reset\n");
++
++	pcie->perst_rc_out = devm_gpiod_get_optional(dev, "perst-rc-out",
++						     GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
++
++	ret = pcie->platform->setup(pdev);
++	if (ret)
++		return dev_err_probe(dev, ret, "Failed to setup PCIe RC\n");
 +
 +	host->sysdata = pcie;
 +
-+	pcie->irq = irq_of_parse_and_map(node, 0);
-+	if (pcie->irq < 0) {
-+		dev_err(dev, "Mapping IRQ failed\n");
-+		return pcie->irq;
-+	}
++	ret = aspeed_pcie_init_irq_domain(pcie);
++	if (ret)
++		return dev_err_probe(dev, ret, "Failed to initialize IntX/MSI domain\n");
 +
-+	err = aspeed_pcie_init_irq_domain(pcie);
-+	if (err) {
-+		dev_err(dev, "failed to init PCIe IRQ domain\n");
-+		return err;
-+	}
++	irq = platform_get_irq(pdev, 0);
++	if (irq < 0)
++		return dev_err_probe(dev, irq, "Failed to get IRQ\n");
 +
-+	irq_set_chained_handler_and_data(pcie->irq, aspeed_pcie_intr_handler,
-+					 pcie);
++	ret = devm_request_irq(dev, irq, aspeed_pcie_intr_handler, IRQF_SHARED,
++			       dev_name(dev), pcie);
++	if (ret)
++		return dev_err_probe(dev, ret, "Failed to request IRQ\n");
++
++	pcie->clock = clk_get(dev, NULL);
++	if (IS_ERR(pcie->clock))
++		return dev_err_probe(dev, PTR_ERR(pcie->clock), "Failed to request clock\n");
++
++	ret = clk_prepare_enable(pcie->clock);
++	if (ret) {
++		clk_put(pcie->clock);
++		return dev_err_probe(dev, ret, "Failed to enable the clock\n");
++	}
 +
 +	return pci_host_probe(host);
 +}
@@ -1534,11 +1181,14 @@
 +{
 +	struct aspeed_pcie *pcie = platform_get_drvdata(pdev);
 +
++	if (pcie->clock) {
++		clk_disable_unprepare(pcie->clock);
++		clk_put(pcie->clock);
++	}
++
 +	pci_stop_root_bus(pcie->host->bus);
 +	pci_remove_root_bus(pcie->host->bus);
-+	irq_domain_remove(pcie->irq_domain);
-+	irq_domain_remove(pcie->msi_domain);
-+	irq_domain_remove(pcie->dev_domain);
++	aspeed_pcie_irq_domain_free(pcie);
 +}
 +
 +static struct aspeed_pcie_rc_platform pcie_rc_ast2600 = {
diff --git a/recipes-kernel/linux/files/0024-Add-SGMII-and-USB3-phy-driver-for-ast2700.patch b/recipes-kernel/linux/files/0024-Add-SGMII-and-USB3-phy-driver-for-ast2700.patch
index 0b1481c..fcddf44 100644
--- a/recipes-kernel/linux/files/0024-Add-SGMII-and-USB3-phy-driver-for-ast2700.patch
+++ b/recipes-kernel/linux/files/0024-Add-SGMII-and-USB3-phy-driver-for-ast2700.patch
@@ -1,24 +1,24 @@
-From 53799ea518257a02c7a1b695cbe7f81b6fe42087 Mon Sep 17 00:00:00 2001
-From: "yung-sheng.huang" <yung-sheng.huang@fii-na.corp-partner.google.com>
-Date: Wed, 16 Apr 2025 09:56:18 +0800
-Subject: [PATCH 24/26] Add SGMII and USB3 phy driver for ast2700
+From 7cc42b59a0903c0f476a2ce6012aae544be8ed82 Mon Sep 17 00:00:00 2001
+From: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+Date: Thu, 17 Jul 2025 13:41:14 +0800
+Subject: [PATCH] Add SGMII and USB3 phy driver for ast2700
 
-This is base on aspeed SDK 9.06.
+This is base on aspeed SDK 9.07.
 
 Source:
 AspeedTech-BMC github:
 https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/
-(cherry picked from commit v00.06.06)
+(cherry picked from commit v00.06.07)
 
-Signed-off-by: yung-sheng.huang <yung-sheng.huang@fii-na.corp-partner.google.com>
+Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
 ---
  drivers/phy/Kconfig                  |   1 +
  drivers/phy/Makefile                 |   1 +
  drivers/phy/aspeed/Kconfig           |  23 +++
  drivers/phy/aspeed/Makefile          |   4 +
- drivers/phy/aspeed/aspeed-sgmii.c    | 163 +++++++++++++++++
+ drivers/phy/aspeed/aspeed-sgmii.c    | 203 +++++++++++++++++++++
  drivers/phy/aspeed/aspeed-usb-phy3.c | 258 +++++++++++++++++++++++++++
- 6 files changed, 450 insertions(+)
+ 6 files changed, 490 insertions(+)
  create mode 100644 drivers/phy/aspeed/Kconfig
  create mode 100644 drivers/phy/aspeed/Makefile
  create mode 100644 drivers/phy/aspeed/aspeed-sgmii.c
@@ -90,10 +90,10 @@
 \ No newline at end of file
 diff --git a/drivers/phy/aspeed/aspeed-sgmii.c b/drivers/phy/aspeed/aspeed-sgmii.c
 new file mode 100644
-index 000000000..2b653926f
+index 000000000..19e3c9b17
 --- /dev/null
 +++ b/drivers/phy/aspeed/aspeed-sgmii.c
-@@ -0,0 +1,163 @@
+@@ -0,0 +1,203 @@
 +// SPDX-License-Identifier: GPL-2.0+
 +/*
 + * Copyright 2023 Aspeed Technology Inc.
@@ -107,6 +107,7 @@
 +#include <linux/ethtool.h>
 +
 +#define SGMII_CFG			0x00
++#define SGMII_PHY_CFG1			0x18
 +#define SGMII_PHY_PIPE_CTL		0x20
 +#define SGMII_FIFO_DELAY_THREHOLD	0x28
 +#define SGMII_MODE			0x30
@@ -155,7 +156,7 @@
 +	reg = SGMII_CFG_AN_ENABLE;
 +	writel(reg, sgmii->regs + SGMII_CFG);
 +
-+	writel(0x0a, sgmii->regs + SGMII_FIFO_DELAY_THREHOLD);
++	writel(0x0c, sgmii->regs + SGMII_FIFO_DELAY_THREHOLD);
 +
 +	writel(SGMII_PCTL_TX_DEEMPH_3_5DB, sgmii->regs + SGMII_PHY_PIPE_CTL);
 +	reg = SGMII_MODE_ENABLE;
@@ -179,8 +180,47 @@
 +	return 0;
 +}
 +
++static int aspeed_sgmii_phy_set_speed(struct phy *phy, int speed)
++{
++	struct aspeed_sgmii *sgmii = phy_get_drvdata(phy);
++	u32 reg;
++
++	reg = PLDA_CLK_SEL_INTERNAL_25M | FIELD_PREP(PLDA_CLK_FREQ_MULTI, 0x2b);
++	regmap_write(sgmii->plda_regmap, PLDA_CLK, reg);
++
++	switch (speed) {
++	case SPEED_10:
++		reg = SGMII_CFG_SPEED_10M;
++		break;
++	case SPEED_100:
++		reg = SGMII_CFG_SPEED_100M;
++		break;
++	case SPEED_1000:
++		reg = SGMII_CFG_SPEED_1G;
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	writel(0, sgmii->regs + SGMII_MODE);
++
++	writel((reg >> 2), sgmii->regs + SGMII_PHY_CFG1);
++
++	writel(0, sgmii->regs + SGMII_CFG);
++	writel(SGMII_CFG_SW_RESET | SGMII_CFG_PWR_DOWN, sgmii->regs + SGMII_CFG);
++	writel(reg, sgmii->regs + SGMII_CFG);
++
++	writel(0x0c, sgmii->regs + SGMII_FIFO_DELAY_THREHOLD);
++	writel(SGMII_PCTL_TX_DEEMPH_3_5DB, sgmii->regs + SGMII_PHY_PIPE_CTL);
++
++	writel(SGMII_MODE_ENABLE | SGMII_MODE_USE_LOCAL_CONFIG, sgmii->regs + SGMII_MODE);
++
++	return 0;
++}
++
 +static const struct phy_ops aspeed_sgmii_phyops = {
 +	.init		= aspeed_sgmii_phy_init,
++	.set_speed	= aspeed_sgmii_phy_set_speed,
 +	.exit		= aspeed_sgmii_phy_exit,
 +	.owner		= THIS_MODULE,
 +};
diff --git a/recipes-kernel/linux/files/0025-bus-Add-Aspeed-LTPI-bus-controller-driver.patch b/recipes-kernel/linux/files/0025-bus-Add-Aspeed-LTPI-bus-controller-driver.patch
index 037f1ae..f52e6cc 100644
--- a/recipes-kernel/linux/files/0025-bus-Add-Aspeed-LTPI-bus-controller-driver.patch
+++ b/recipes-kernel/linux/files/0025-bus-Add-Aspeed-LTPI-bus-controller-driver.patch
@@ -1,22 +1,22 @@
-From 211c9addd74794652d1ec3e1b775805b55f27b1e Mon Sep 17 00:00:00 2001
-From: "yung-sheng.huang" <yung-sheng.huang@fii-na.corp-partner.google.com>
-Date: Wed, 16 Apr 2025 11:07:06 +0800
-Subject: [PATCH 25/26] bus: Add Aspeed LTPI bus controller driver
+From 00eba48c2b17c333a23ac60c9d4f686a8da9467c Mon Sep 17 00:00:00 2001
+From: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+Date: Thu, 17 Jul 2025 13:44:01 +0800
+Subject: [PATCH] bus: Add Aspeed LTPI bus controller driver
 
 Add Aspeed LTPI bus controller driver to ungate the LTPI clock.
-This is base on aspeed SDK 9.06.
+This is base on aspeed SDK 9.07.
 
 Source:
 AspeedTech-BMC github:
 https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/
-(cherry picked from commit v00.06.06)
+(cherry picked from commit v00.06.07)
 
-Signed-off-by: yung-sheng.huang <yung-sheng.huang@fii-na.corp-partner.google.com>
+Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
 ---
  drivers/bus/Kconfig       |   7 ++
  drivers/bus/Makefile      |   1 +
- drivers/bus/aspeed-ltpi.c | 210 ++++++++++++++++++++++++++++++++++++++
- 3 files changed, 218 insertions(+)
+ drivers/bus/aspeed-ltpi.c | 215 ++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 223 insertions(+)
  create mode 100644 drivers/bus/aspeed-ltpi.c
 
 diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
@@ -51,10 +51,10 @@
  obj-y				+= mhi/
 diff --git a/drivers/bus/aspeed-ltpi.c b/drivers/bus/aspeed-ltpi.c
 new file mode 100644
-index 000000000..ca6d4b951
+index 000000000..6630ee4bd
 --- /dev/null
 +++ b/drivers/bus/aspeed-ltpi.c
-@@ -0,0 +1,210 @@
+@@ -0,0 +1,215 @@
 +// SPDX-License-Identifier: GPL-2.0-or-later
 +// Copyright ASPEED Technology
 +
@@ -172,17 +172,22 @@
 +	if (IS_ERR(priv->regs))
 +		return PTR_ERR(priv->regs);
 +
-+	priv->ltpi_clk = devm_clk_get(&pdev->dev, "ahb");
-+	if (IS_ERR(priv->ltpi_clk))
-+		return PTR_ERR(priv->ltpi_clk);
++	priv->ltpi_clk = devm_clk_get(&pdev->dev, "ltpi");
++	if (IS_ERR(priv->ltpi_clk)) {
++		priv->ltpi_clk = devm_clk_get(&pdev->dev, "ahb");
++		if (IS_ERR(priv->ltpi_clk))
++			return PTR_ERR(priv->ltpi_clk);
 +
-+	clk_prepare_enable(priv->ltpi_clk);
++		clk_prepare_enable(priv->ltpi_clk);
 +
-+	priv->ltpi_phyclk = devm_clk_get(&pdev->dev, "phy");
-+	if (IS_ERR(priv->ltpi_phyclk))
-+		return PTR_ERR(priv->ltpi_phyclk);
++		priv->ltpi_phyclk = devm_clk_get(&pdev->dev, "phy");
++		if (IS_ERR(priv->ltpi_phyclk))
++			return PTR_ERR(priv->ltpi_phyclk);
 +
-+	clk_prepare_enable(priv->ltpi_phyclk);
++		clk_prepare_enable(priv->ltpi_phyclk);
++	} else {
++		priv->ltpi_phyclk = NULL;
++	}
 +
 +	priv->ltpi_rst = devm_reset_control_get_optional_shared(&pdev->dev, NULL);
 +	if (IS_ERR(priv->ltpi_rst))
diff --git a/recipes-kernel/linux/files/0026-Add-LTPI-GPIO-driver-for-ast2700.patch b/recipes-kernel/linux/files/0026-Add-LTPI-GPIO-driver-for-ast2700.patch
index 053fec3..5daf71b 100644
--- a/recipes-kernel/linux/files/0026-Add-LTPI-GPIO-driver-for-ast2700.patch
+++ b/recipes-kernel/linux/files/0026-Add-LTPI-GPIO-driver-for-ast2700.patch
@@ -1,16 +1,18 @@
-From 52dc5074f9dc5430191f1c03563d758e860afdda Mon Sep 17 00:00:00 2001
-From: "yung-sheng.huang" <yung-sheng.huang@fii-na.corp-partner.google.com>
-Date: Wed, 16 Apr 2025 11:11:08 +0800
-Subject: [PATCH 26/26] Add LTPI GPIO driver for ast2700
+From 1aa82d7843486992356e5ce5e5e3e8f3a338c0f5 Mon Sep 17 00:00:00 2001
+From: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+Date: Thu, 17 Jul 2025 13:46:30 +0800
+Subject: [PATCH] Add LTPI GPIO driver for ast2700
 
-This is base on aspeed SDK 9.06.
+This is base on aspeed SDK 9.07.
 
 Source:
 AspeedTech-BMC github:
 https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/
-(cherry picked from commit v00.06.06)
+(cherry picked from commit v00.06.07)
 
-Signed-off-by: yung-sheng.huang <yung-sheng.huang@fii-na.corp-partner.google.com>
+Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+
+Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
 ---
  drivers/gpio/Kconfig            |   8 +
  drivers/gpio/Makefile           |   1 +
diff --git a/recipes-kernel/linux/files/0027-Add-DRAM-EDAC-driver-for-ast2700.patch b/recipes-kernel/linux/files/0027-Add-DRAM-EDAC-driver-for-ast2700.patch
new file mode 100644
index 0000000..a252d49
--- /dev/null
+++ b/recipes-kernel/linux/files/0027-Add-DRAM-EDAC-driver-for-ast2700.patch
@@ -0,0 +1,417 @@
+From 767751711d0ed9ce899b23926a17349654f9d902 Mon Sep 17 00:00:00 2001
+From: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+Date: Thu, 17 Jul 2025 13:49:24 +0800
+Subject: [PATCH] Add DRAM EDAC driver for ast2700
+
+This is base on aspeed SDK 9.07.
+
+Source:
+AspeedTech-BMC github:
+https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/
+(cherry picked from commit v00.06.07)
+
+Signed-off-by: Alan Hung <yung-sheng.huang@fii-na.corp-partner.google.com>
+---
+ drivers/edac/Kconfig        |   9 +
+ drivers/edac/Makefile       |   1 +
+ drivers/edac/edac_ast2700.c | 356 ++++++++++++++++++++++++++++++++++++
+ 3 files changed, 366 insertions(+)
+ create mode 100755 drivers/edac/edac_ast2700.c
+
+diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
+index 110e99b86..6854dddda 100644
+--- a/drivers/edac/Kconfig
++++ b/drivers/edac/Kconfig
+@@ -528,6 +528,15 @@ config EDAC_ASPEED
+ 	  First, ECC must be configured in the bootloader. Then, this driver
+ 	  will expose error counters via the EDAC kernel framework.
+ 
++config EDAC_AST2700
++	tristate "Aspeed AST2700 BMC SoC"
++	depends on ARCH_ASPEED
++	help
++	  Support for error detection and correction on the Aspeed AST2700
++
++	  First, ECC must be configured in the bootloader. Then, this driver
++	  will expose error counters via the EDAC kernel framework.
++
+ config EDAC_BLUEFIELD
+ 	tristate "Mellanox BlueField Memory ECC"
+ 	depends on ARM64 && ((MELLANOX_PLATFORM && ACPI) || COMPILE_TEST)
+diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
+index 446364264..7c69a394a 100644
+--- a/drivers/edac/Makefile
++++ b/drivers/edac/Makefile
+@@ -84,6 +84,7 @@ obj-$(CONFIG_EDAC_XGENE)		+= xgene_edac.o
+ obj-$(CONFIG_EDAC_TI)			+= ti_edac.o
+ obj-$(CONFIG_EDAC_QCOM)			+= qcom_edac.o
+ obj-$(CONFIG_EDAC_ASPEED)		+= aspeed_edac.o
++obj-$(CONFIG_EDAC_AST2700)		+= edac_ast2700.o
+ obj-$(CONFIG_EDAC_BLUEFIELD)		+= bluefield_edac.o
+ obj-$(CONFIG_EDAC_DMC520)		+= dmc520_edac.o
+ obj-$(CONFIG_EDAC_NPCM)			+= npcm_edac.o
+diff --git a/drivers/edac/edac_ast2700.c b/drivers/edac/edac_ast2700.c
+new file mode 100755
+index 000000000..26f45bb60
+--- /dev/null
++++ b/drivers/edac/edac_ast2700.c
+@@ -0,0 +1,356 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Copyright 2018, 2019 Cisco Systems
++ */
++
++#include <linux/edac.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <linux/stop_machine.h>
++#include <linux/io.h>
++#include <linux/of_address.h>
++#include <linux/regmap.h>
++#include "edac_module.h"
++
++#define DRV_NAME "aspeed-edac"
++
++#define DRAMC_PROT			0x00 /* protection key register */
++#define DRAMC_INT_STS			0x04 /* interrupt status register */
++#define  INT_STS_ECC_REC		BIT(5) /* ECC recoverable error interrupt */
++#define  INT_STS_ECC_ERR		BIT(4) /* ECC error interrupt */
++#define DRAMC_INT_CLR			0x08 /* interrupt clear register */
++#define DRAMC_INT_MASK			0x0c /* interrupt mask register */
++#define DRAMC_MCFG			0x10 /* main configuration register */
++#define   MCFG_ECC_ENABLE		BIT(6)
++#define   MCFG_DRAM_SIZE_MASK		GENMASK(5, 4) /* 2=1GB, 3=2GB, 4=4GB, 5=8GB */
++#define   MCFG_DRAM_SIZE_SHIFT		(2)
++#define   MCFG_DRAM_TYPE		BIT(0) /* 0=DDR4, 1=DDR5 */
++
++#define DRAMC_ECC_STS			0x78 /* ECC status register */
++#define  ECC_STS_REC_CNT_MASK		GENMASK(15, 8) /* recoverable error count */
++#define  ECC_STS_REC_CNT_SHIFT		(8)
++#define  ECC_STS_UNREC_CNT_MASK		GENMASK(7, 0) /* unrecoverable error count */
++#define  ECC_STS_UNREC_CNT_SHIFT	(0)
++#define DRAMC_ECC_FAIL_ADDR		0x7c /* ECC fail address register */
++
++static struct regmap *aspeed_regmap;
++
++static int regmap_reg_write(void *context, unsigned int reg, unsigned int val)
++{
++	void __iomem *regs = (void __iomem *)context;
++
++	writel(val, regs + reg);
++
++	return 0;
++}
++
++static int regmap_reg_read(void *context, unsigned int reg, unsigned int *val)
++{
++	void __iomem *regs = (void __iomem *)context;
++
++	*val = readl(regs + reg);
++
++	return 0;
++}
++
++static bool regmap_is_volatile(struct device *dev, unsigned int reg)
++{
++	return 1;
++}
++
++static const struct regmap_config aspeed_regmap_config = {
++	.reg_bits = 32,
++	.val_bits = 32,
++	.reg_stride = 4,
++	.max_register = DRAMC_ECC_FAIL_ADDR,
++	.reg_write = regmap_reg_write,
++	.reg_read = regmap_reg_read,
++	.volatile_reg = regmap_is_volatile,
++	.fast_io = true,
++};
++
++static void count_rec(struct mem_ctl_info *mci, u8 rec_cnt, u32 rec_addr)
++{
++	struct csrow_info *csrow = mci->csrows[0];
++	u32 page, offset, syndrome;
++
++	if (!rec_cnt)
++		return;
++
++	/* report first few errors (if there are) */
++	/* note: no addresses are recorded */
++	if (rec_cnt > 1) {
++		/* page, offset and syndrome are not available */
++		page = 0;
++		offset = 0;
++		syndrome = 0;
++		edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, rec_cnt - 1,
++				     page, offset, syndrome, 0, 0, -1,
++				     "address(es) not available", "");
++	}
++
++	/* report last error */
++	/* note: rec_addr is the last recoverable error addr */
++	page = rec_addr >> PAGE_SHIFT;
++	offset = rec_addr & ~PAGE_MASK;
++	/* syndrome is not available */
++	syndrome = 0;
++	edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
++			     csrow->first_page + page, offset, syndrome,
++			     0, 0, -1, "", "");
++}
++
++static void count_un_rec(struct mem_ctl_info *mci, u8 un_rec_cnt,
++			 u32 un_rec_addr)
++{
++	struct csrow_info *csrow = mci->csrows[0];
++	u32 page, offset, syndrome;
++
++	if (!un_rec_cnt)
++		return;
++
++	/* report 1. error */
++	/* note: un_rec_addr is the first unrecoverable error addr */
++	page = un_rec_addr >> PAGE_SHIFT;
++	offset = un_rec_addr & ~PAGE_MASK;
++	/* syndrome is not available */
++	syndrome = 0;
++	edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
++			     csrow->first_page + page, offset, syndrome,
++			     0, 0, -1, "", "");
++
++	/* report further errors (if there are) */
++	/* note: no addresses are recorded */
++	if (un_rec_cnt > 1) {
++		/* page, offset and syndrome are not available */
++		page = 0;
++		offset = 0;
++		syndrome = 0;
++		edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, un_rec_cnt - 1,
++				     page, offset, syndrome, 0, 0, -1,
++				     "address(es) not available", "");
++	}
++}
++
++static irqreturn_t mcr_isr(int irq, void *arg)
++{
++	struct mem_ctl_info *mci = arg;
++	u32 reg, ecc_sts, ecc_fail_addr;
++	u16  rec_cnt, un_rec_cnt;
++
++	regmap_read(aspeed_regmap, DRAMC_INT_STS, &reg);
++
++	regmap_read(aspeed_regmap, DRAMC_ECC_STS, &ecc_sts);
++
++	/* collect data about recoverable and unrecoverable errors */
++	rec_cnt = (ecc_sts & ECC_STS_REC_CNT_MASK) >> ECC_STS_REC_CNT_SHIFT;
++	un_rec_cnt = (ecc_sts & ECC_STS_UNREC_CNT_MASK) >> ECC_STS_UNREC_CNT_SHIFT;
++
++	regmap_read(aspeed_regmap, DRAMC_ECC_FAIL_ADDR, &ecc_fail_addr);
++
++	/* clear interrupt flags */
++	regmap_update_bits(aspeed_regmap, DRAMC_INT_CLR,
++			   reg, reg);
++
++	/* process recoverable and unrecoverable errors */
++	count_rec(mci, rec_cnt, ecc_fail_addr);
++	count_un_rec(mci, un_rec_cnt, ecc_fail_addr);
++
++	return IRQ_HANDLED;
++}
++
++static int config_irq(void *ctx, struct platform_device *pdev)
++{
++	int irq;
++	int rc;
++
++	/* register interrupt handler */
++	irq = platform_get_irq(pdev, 0);
++	dev_dbg(&pdev->dev, "got irq %d\n", irq);
++	if (irq < 0)
++		return irq;
++
++	rc = devm_request_irq(&pdev->dev, irq, mcr_isr, IRQF_TRIGGER_HIGH,
++			      DRV_NAME, ctx);
++	if (rc) {
++		dev_err(&pdev->dev, "unable to request irq %d\n", irq);
++		return rc;
++	}
++
++	/* enable interrupts */
++	regmap_clear_bits(aspeed_regmap, DRAMC_INT_MASK,
++			  INT_STS_ECC_REC | INT_STS_ECC_ERR);
++
++	return 0;
++}
++
++static int init_csrows(struct mem_ctl_info *mci)
++{
++	struct csrow_info *csrow = mci->csrows[0];
++	u32 nr_pages, dram_type;
++	struct dimm_info *dimm;
++	struct device_node *np;
++	struct resource r;
++	u32 reg04;
++	int rc;
++
++	pr_info("%s: initializing csrows\n", DRV_NAME);
++
++	/* retrieve info about physical memory from device tree */
++	np = of_find_node_by_name(NULL, "memory");
++	if (!np) {
++		dev_err(mci->pdev, "dt: missing /memory node\n");
++		return -ENODEV;
++	}
++
++	rc = of_address_to_resource(np, 0, &r);
++
++	of_node_put(np);
++
++	if (rc) {
++		dev_err(mci->pdev, "dt: failed requesting resource for /memory node\n");
++		return rc;
++	}
++
++	dev_dbg(mci->pdev, "dt: /memory node resources: first page %pR, PAGE_SHIFT macro=0x%x\n",
++		&r, PAGE_SHIFT);
++
++	csrow->first_page = r.start >> PAGE_SHIFT;
++	nr_pages = resource_size(&r) >> PAGE_SHIFT;
++	csrow->last_page = csrow->first_page + nr_pages - 1;
++
++	regmap_read(aspeed_regmap, DRAMC_MCFG, &reg04);
++	dram_type = (reg04 & MCFG_DRAM_TYPE) ? MEM_DDR5 : MEM_DDR4;
++
++	dimm = csrow->channels[0]->dimm;
++	dimm->mtype = dram_type;
++	dimm->edac_mode = EDAC_SECDED;
++	dimm->nr_pages = nr_pages / csrow->nr_channels;
++
++	dev_dbg(mci->pdev, "initialized dimm with first_page=0x%lx and nr_pages=0x%x\n",
++		csrow->first_page, nr_pages);
++
++	return 0;
++}
++
++static int aspeed_probe(struct platform_device *pdev)
++{
++	struct device *dev = &pdev->dev;
++	struct edac_mc_layer layers[2];
++	struct mem_ctl_info *mci;
++	void __iomem *regs;
++	//u32 reg04;
++	u32 reg;
++	int rc;
++
++	regs = devm_platform_ioremap_resource(pdev, 0);
++	if (IS_ERR(regs))
++		return PTR_ERR(regs);
++
++	aspeed_regmap = devm_regmap_init(dev, NULL, (__force void *)regs,
++					 &aspeed_regmap_config);
++	if (IS_ERR(aspeed_regmap))
++		return PTR_ERR(aspeed_regmap);
++
++	/* bail out if ECC mode is not configured */
++	regmap_read(aspeed_regmap, DRAMC_MCFG, &reg);
++	if (!(reg & MCFG_ECC_ENABLE)) {
++		dev_err(&pdev->dev, "ECC mode is not configured in u-boot\n");
++		return -EPERM;
++	}
++
++	edac_op_state = EDAC_OPSTATE_INT;
++
++	/* allocate & init EDAC MC data structure */
++	layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
++	layers[0].size = 1;
++	layers[0].is_virt_csrow = true;
++	layers[1].type = EDAC_MC_LAYER_CHANNEL;
++	layers[1].size = 1;
++	layers[1].is_virt_csrow = false;
++
++	mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, 0);
++	if (!mci)
++		return -ENOMEM;
++
++	mci->pdev = &pdev->dev;
++	mci->mtype_cap = MEM_FLAG_DDR4 | MEM_FLAG_DDR5;
++	mci->edac_ctl_cap = EDAC_FLAG_SECDED;
++	mci->edac_cap = EDAC_FLAG_SECDED;
++	mci->scrub_cap = SCRUB_FLAG_HW_SRC;
++	mci->scrub_mode = SCRUB_HW_SRC;
++	mci->mod_name = DRV_NAME;
++	mci->ctl_name = "MIC";
++	mci->dev_name = dev_name(&pdev->dev);
++
++	rc = init_csrows(mci);
++	if (rc) {
++		dev_err(&pdev->dev, "failed to init csrows\n");
++		goto probe_exit02;
++	}
++
++	platform_set_drvdata(pdev, mci);
++
++	/* register with edac core */
++	rc = edac_mc_add_mc(mci);
++	if (rc) {
++		dev_err(&pdev->dev, "failed to register with EDAC core\n");
++		goto probe_exit02;
++	}
++
++	/* register interrupt handler and enable interrupts */
++	rc = config_irq(mci, pdev);
++	if (rc) {
++		dev_err(&pdev->dev, "failed setting up irq\n");
++		goto probe_exit01;
++	}
++
++	return 0;
++
++probe_exit01:
++	edac_mc_del_mc(&pdev->dev);
++probe_exit02:
++	edac_mc_free(mci);
++	return rc;
++}
++
++static int aspeed_remove(struct platform_device *pdev)
++{
++	struct mem_ctl_info *mci;
++
++	/* disable interrupts */
++	regmap_update_bits(aspeed_regmap, DRAMC_INT_MASK,
++			   INT_STS_ECC_REC | INT_STS_ECC_ERR,
++			   INT_STS_ECC_REC | INT_STS_ECC_ERR);
++
++	/* free resources */
++	mci = edac_mc_del_mc(&pdev->dev);
++	if (mci)
++		edac_mc_free(mci);
++
++	return 0;
++}
++
++static const struct of_device_id aspeed_of_match[] = {
++	{ .compatible = "aspeed,ast2700-sdram-edac" },
++	{},
++};
++
++MODULE_DEVICE_TABLE(of, aspeed_of_match);
++
++static struct platform_driver aspeed_driver = {
++	.driver		= {
++		.name	= DRV_NAME,
++		.of_match_table = aspeed_of_match
++	},
++	.probe		= aspeed_probe,
++	.remove		= aspeed_remove
++};
++module_platform_driver(aspeed_driver);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Stefan Schaeckeler <sschaeck@cisco.com>");
++MODULE_DESCRIPTION("Aspeed BMC SoC EDAC driver");
++MODULE_VERSION("1.0");
+-- 
+2.34.1
+
diff --git a/recipes-kernel/linux/files/0027-Add-crypto-user-api-for-ast2700.patch b/recipes-kernel/linux/files/0027-Add-crypto-user-api-for-ast2700.patch
deleted file mode 100644
index 6551224..0000000
--- a/recipes-kernel/linux/files/0027-Add-crypto-user-api-for-ast2700.patch
+++ /dev/null
@@ -1,844 +0,0 @@
-From d3d8a395180667428fe988fc5c6ae82d3b268cb0 Mon Sep 17 00:00:00 2001
-From: "yung-sheng.huang" <yung-sheng.huang@fii-na.corp-partner.google.com>
-Date: Wed, 16 Apr 2025 13:55:00 +0800
-Subject: [PATCH] Add crypto user api for ast2700
-
-Aspeed defconfig enables user api crypto.
-This is base on aspeed SDK 9.06.
-
-Source:
-AspeedTech-BMC github:
-https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/
-(cherry picked from commit v00.06.06)
-
-Signed-off-by: yung-sheng.huang <yung-sheng.huang@fii-na.corp-partner.google.com>
----
- crypto/Kconfig              |   9 +
- crypto/Makefile             |   1 +
- crypto/af_alg.c             |  30 ++-
- crypto/algapi.c             |   2 +-
- crypto/algif_aead.c         |  46 ++--
- crypto/algif_akcipher.c     | 457 ++++++++++++++++++++++++++++++++++++
- crypto/algif_skcipher.c     |  35 ++-
- include/crypto/if_alg.h     |   7 +-
- include/uapi/linux/if_alg.h |   3 +
- 9 files changed, 548 insertions(+), 42 deletions(-)
- create mode 100644 crypto/algif_akcipher.c
-
-diff --git a/crypto/Kconfig b/crypto/Kconfig
-index fc0f75d8b..149b72322 100644
---- a/crypto/Kconfig
-+++ b/crypto/Kconfig
-@@ -1387,6 +1387,15 @@ config CRYPTO_USER_API_AEAD
- 	  See Documentation/crypto/userspace-if.rst and
- 	  https://www.chronox.de/libkcapi/html/index.html
- 
-+config CRYPTO_USER_API_AKCIPHER
-+	tristate "User-space interface for asymmetric key cipher algorithms"
-+	depends on NET
-+	select CRYPTO_AKCIPHER2
-+	select CRYPTO_USER_API
-+	help
-+	  This option enables the user-spaces interface for asymmetric
-+	  key cipher algorithms.
-+
- config CRYPTO_USER_API_ENABLE_OBSOLETE
- 	bool "Obsolete cryptographic algorithms"
- 	depends on CRYPTO_USER_API
-diff --git a/crypto/Makefile b/crypto/Makefile
-index 953a7e105..35fb9f1bf 100644
---- a/crypto/Makefile
-+++ b/crypto/Makefile
-@@ -181,6 +181,7 @@ obj-$(CONFIG_CRYPTO_USER_API_HASH) += algif_hash.o
- obj-$(CONFIG_CRYPTO_USER_API_SKCIPHER) += algif_skcipher.o
- obj-$(CONFIG_CRYPTO_USER_API_RNG) += algif_rng.o
- obj-$(CONFIG_CRYPTO_USER_API_AEAD) += algif_aead.o
-+obj-$(CONFIG_CRYPTO_USER_API_AKCIPHER) += algif_akcipher.o
- obj-$(CONFIG_CRYPTO_ZSTD) += zstd.o
- obj-$(CONFIG_CRYPTO_OFB) += ofb.o
- obj-$(CONFIG_CRYPTO_ECC) += ecc.o
-diff --git a/crypto/af_alg.c b/crypto/af_alg.c
-index 68cc9290c..b92ad73b3 100644
---- a/crypto/af_alg.c
-+++ b/crypto/af_alg.c
-@@ -205,13 +205,17 @@ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
- 	return err;
- }
- 
--static int alg_setkey(struct sock *sk, sockptr_t ukey, unsigned int keylen)
-+static int alg_setkey(struct sock *sk, sockptr_t ukey, unsigned int keylen,
-+		      int (*setkey)(void *private, const u8 *key,
-+				    unsigned int keylen))
- {
- 	struct alg_sock *ask = alg_sk(sk);
--	const struct af_alg_type *type = ask->type;
- 	u8 *key;
- 	int err;
- 
-+	if (!setkey)
-+		return -ENOPROTOOPT;
-+
- 	key = sock_kmalloc(sk, keylen, GFP_KERNEL);
- 	if (!key)
- 		return -ENOMEM;
-@@ -220,7 +224,7 @@ static int alg_setkey(struct sock *sk, sockptr_t ukey, unsigned int keylen)
- 	if (copy_from_sockptr(key, ukey, keylen))
- 		goto out;
- 
--	err = type->setkey(ask->private, key, keylen);
-+	err = setkey(ask->private, key, keylen);
- 
- out:
- 	sock_kzfree_s(sk, key, keylen);
-@@ -377,13 +381,17 @@ static int alg_setsockopt(struct socket *sock, int level, int optname,
- 	case ALG_SET_KEY_BY_KEY_SERIAL:
- 		if (sock->state == SS_CONNECTED)
- 			goto unlock;
--		if (!type->setkey)
--			goto unlock;
- 
- 		if (optname == ALG_SET_KEY_BY_KEY_SERIAL)
- 			err = alg_setkey_by_key_serial(ask, optval, optlen);
- 		else
--			err = alg_setkey(sk, optval, optlen);
-+			err = alg_setkey(sk, optval, optlen, type->setkey);
-+		break;
-+	case ALG_SET_PUBKEY:
-+		if (sock->state == SS_CONNECTED)
-+			goto unlock;
-+
-+		err = alg_setkey(sk, optval, optlen, type->setpubkey);
- 		break;
- 	case ALG_SET_AEAD_AUTHSIZE:
- 		if (sock->state == SS_CONNECTED)
-@@ -943,9 +951,9 @@ int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size,
- 	struct af_alg_tsgl *sgl;
- 	struct af_alg_control con = {};
- 	long copied = 0;
--	bool enc = false;
- 	bool init = false;
- 	int err = 0;
-+	int op = 0;
- 
- 	if (msg->msg_controllen) {
- 		err = af_alg_cmsg_send(msg, &con);
-@@ -954,11 +962,11 @@ int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size,
- 
- 		init = true;
- 		switch (con.op) {
-+		case ALG_OP_VERIFY:
-+		case ALG_OP_SIGN:
- 		case ALG_OP_ENCRYPT:
--			enc = true;
--			break;
- 		case ALG_OP_DECRYPT:
--			enc = false;
-+			op = con.op;
- 			break;
- 		default:
- 			return -EINVAL;
-@@ -982,7 +990,7 @@ int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size,
- 	ctx->init = true;
- 
- 	if (init) {
--		ctx->enc = enc;
-+		ctx->op = op;
- 		if (con.iv)
- 			memcpy(ctx->iv, con.iv->iv, ivsize);
- 
-diff --git a/crypto/algapi.c b/crypto/algapi.c
-index 85bc279b4..b3a608604 100644
---- a/crypto/algapi.c
-+++ b/crypto/algapi.c
-@@ -396,7 +396,7 @@ void crypto_alg_tested(const char *name, int err)
- 	q->cra_flags |= CRYPTO_ALG_DEAD;
- 	alg = test->adult;
- 
--	if (list_empty(&alg->cra_list))
-+	if (crypto_is_dead(alg))
- 		goto complete;
- 
- 	if (err == -ECANCELED)
-diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c
-index 7d58cbbce..839f8c8f2 100644
---- a/crypto/algif_aead.c
-+++ b/crypto/algif_aead.c
-@@ -55,7 +55,7 @@ static inline bool aead_sufficient_data(struct sock *sk)
- 	 * The minimum amount of memory needed for an AEAD cipher is
- 	 * the AAD and in case of decryption the tag.
- 	 */
--	return ctx->used >= ctx->aead_assoclen + (ctx->enc ? 0 : as);
-+	return ctx->used >= ctx->aead_assoclen + (ctx->op ? 0 : as);
- }
- 
- static int aead_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
-@@ -138,7 +138,7 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
- 	 * buffer provides the tag which is consumed resulting in only the
- 	 * plaintext without a buffer for the tag returned to the caller.
- 	 */
--	if (ctx->enc)
-+	if (ctx->op)
- 		outlen = used + as;
- 	else
- 		outlen = used - as;
-@@ -212,7 +212,7 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
- 	/* Use the RX SGL as source (and destination) for crypto op. */
- 	rsgl_src = areq->first_rsgl.sgl.sgt.sgl;
- 
--	if (ctx->enc) {
-+	if (ctx->op == ALG_OP_ENCRYPT) {
- 		/*
- 		 * Encryption operation - The in-place cipher operation is
- 		 * achieved by the following operation:
-@@ -229,7 +229,7 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
- 		if (err)
- 			goto free;
- 		af_alg_pull_tsgl(sk, processed, NULL, 0);
--	} else {
-+	} else if (ctx->op == ALG_OP_DECRYPT) {
- 		/*
- 		 * Decryption operation - To achieve an in-place cipher
- 		 * operation, the following  SGL structure is used:
-@@ -276,6 +276,9 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
- 		} else
- 			/* no RX SGL present (e.g. authentication only) */
- 			rsgl_src = areq->tsgl;
-+	} else {
-+		err = -EOPNOTSUPP;
-+		goto free;
- 	}
- 
- 	/* Initialize the crypto operation */
-@@ -295,26 +298,37 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
- 		aead_request_set_callback(&areq->cra_u.aead_req,
- 					  CRYPTO_TFM_REQ_MAY_SLEEP,
- 					  af_alg_async_cb, areq);
--		err = ctx->enc ? crypto_aead_encrypt(&areq->cra_u.aead_req) :
--				 crypto_aead_decrypt(&areq->cra_u.aead_req);
--
--		/* AIO operation in progress */
--		if (err == -EINPROGRESS)
--			return -EIOCBQUEUED;
--
--		sock_put(sk);
- 	} else {
- 		/* Synchronous operation */
- 		aead_request_set_callback(&areq->cra_u.aead_req,
- 					  CRYPTO_TFM_REQ_MAY_SLEEP |
- 					  CRYPTO_TFM_REQ_MAY_BACKLOG,
- 					  crypto_req_done, &ctx->wait);
--		err = crypto_wait_req(ctx->enc ?
--				crypto_aead_encrypt(&areq->cra_u.aead_req) :
--				crypto_aead_decrypt(&areq->cra_u.aead_req),
--				&ctx->wait);
- 	}
- 
-+	switch (ctx->op) {
-+	case ALG_OP_ENCRYPT:
-+		err = crypto_aead_encrypt(&areq->cra_u.aead_req);
-+		break;
-+	case ALG_OP_DECRYPT:
-+		err = crypto_aead_decrypt(&areq->cra_u.aead_req);
-+		break;
-+	default:
-+		err = -EOPNOTSUPP;
-+		goto free;
-+	}
-+
-+	if (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) {
-+		/* AIO operation in progress */
-+		if (err == -EINPROGRESS)
-+			return -EIOCBQUEUED;
-+
-+		sock_put(sk);
-+
-+	} else {
-+		/* Wait for synchronous operation completion */
-+		err = crypto_wait_req(err, &ctx->wait);
-+	}
- 
- free:
- 	af_alg_free_resources(areq);
-diff --git a/crypto/algif_akcipher.c b/crypto/algif_akcipher.c
-new file mode 100644
-index 000000000..a0fbee0aa
---- /dev/null
-+++ b/crypto/algif_akcipher.c
-@@ -0,0 +1,457 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * algif_akcipher: User-space interface for asymmetric cipher algorithms
-+ *
-+ * Copyright (C) 2017, Stephan Mueller <smueller@chronox.de>
-+ *
-+ * This file provides the user-space API for asymmetric ciphers.
-+ *
-+ * 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; either version 2 of the License, or (at your option)
-+ * any later version.
-+ *
-+ * The following concept of the memory management is used:
-+ *
-+ * The kernel maintains two SGLs, the TX SGL and the RX SGL. The TX SGL is
-+ * filled by user space with the data submitted via sendpage/sendmsg. Filling
-+ * up the TX SGL does not cause a crypto operation -- the data will only be
-+ * tracked by the kernel. Upon receipt of one recvmsg call, the caller must
-+ * provide a buffer which is tracked with the RX SGL.
-+ *
-+ * During the processing of the recvmsg operation, the cipher request is
-+ * allocated and prepared. As part of the recvmsg operation, the processed
-+ * TX buffers are extracted from the TX SGL into a separate SGL.
-+ *
-+ * After the completion of the crypto operation, the RX SGL and the cipher
-+ * request is released. The extracted TX SGL parts are released together with
-+ * the RX SGL release.
-+ */
-+
-+#include <crypto/akcipher.h>
-+#include <crypto/scatterwalk.h>
-+#include <crypto/if_alg.h>
-+#include <linux/init.h>
-+#include <linux/list.h>
-+#include <linux/kernel.h>
-+#include <linux/mm.h>
-+#include <linux/module.h>
-+#include <linux/net.h>
-+#include <net/sock.h>
-+
-+struct akcipher_tfm {
-+	struct crypto_akcipher *akcipher;
-+	bool has_key;
-+};
-+
-+static int akcipher_sendmsg(struct socket *sock, struct msghdr *msg,
-+			    size_t size)
-+{
-+	return af_alg_sendmsg(sock, msg, size, 0);
-+}
-+
-+static int _akcipher_recvmsg(struct socket *sock, struct msghdr *msg,
-+			     size_t ignored, int flags)
-+{
-+	struct sock *sk = sock->sk;
-+	struct alg_sock *ask = alg_sk(sk);
-+	struct sock *psk = ask->parent;
-+	struct alg_sock *pask = alg_sk(psk);
-+	struct af_alg_ctx *ctx = ask->private;
-+	struct akcipher_tfm *akc = pask->private;
-+	struct crypto_akcipher *tfm = akc->akcipher;
-+	struct af_alg_async_req *areq;
-+	int err = 0;
-+	int maxsize;
-+	size_t len = 0;
-+	size_t used = 0;
-+
-+	maxsize = crypto_akcipher_maxsize(tfm);
-+	if (maxsize < 0)
-+		return maxsize;
-+
-+	/* Allocate cipher request for current operation. */
-+	areq = af_alg_alloc_areq(sk, sizeof(struct af_alg_async_req) +
-+				     crypto_akcipher_reqsize(tfm));
-+	if (IS_ERR(areq))
-+		return PTR_ERR(areq);
-+
-+	/* convert iovecs of output buffers into RX SGL */
-+	err = af_alg_get_rsgl(sk, msg, flags, areq, maxsize, &len);
-+	if (err)
-+		goto free;
-+
-+	/* ensure output buffer is sufficiently large */
-+	if (len < maxsize) {
-+		pr_err("%s: output buffer is not large enough. len:%zu, maxsize:0x%x\n",
-+		       __func__, len, maxsize);
-+		err = -EMSGSIZE;
-+		goto free;
-+	}
-+
-+	/*
-+	 * Create a per request TX SGL for this request which tracks the
-+	 * SG entries from the global TX SGL.
-+	 */
-+	used = ctx->used;
-+	areq->tsgl_entries = af_alg_count_tsgl(sk, used, 0);
-+	if (!areq->tsgl_entries)
-+		areq->tsgl_entries = 1;
-+	areq->tsgl = sock_kmalloc(sk, sizeof(*areq->tsgl) * areq->tsgl_entries,
-+				  GFP_KERNEL);
-+	if (!areq->tsgl) {
-+		err = -ENOMEM;
-+		goto free;
-+	}
-+	sg_init_table(areq->tsgl, areq->tsgl_entries);
-+	af_alg_pull_tsgl(sk, used, areq->tsgl, 0);
-+
-+	/* Handle specific operation: verify op */
-+	if (ctx->op == ALG_OP_VERIFY)
-+		used -= len;
-+
-+	/* Initialize the crypto operation */
-+	akcipher_request_set_tfm(&areq->cra_u.akcipher_req, tfm);
-+	akcipher_request_set_crypt(&areq->cra_u.akcipher_req, areq->tsgl,
-+				   areq->first_rsgl.sgl.sgt.sgl, used, len);
-+
-+	if (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) {
-+		/* AIO operation */
-+		areq->iocb = msg->msg_iocb;
-+		akcipher_request_set_callback(&areq->cra_u.akcipher_req,
-+					      CRYPTO_TFM_REQ_MAY_SLEEP,
-+					      af_alg_async_cb, areq);
-+	} else {
-+		/* Synchronous operation */
-+		akcipher_request_set_callback(&areq->cra_u.akcipher_req,
-+					      CRYPTO_TFM_REQ_MAY_SLEEP |
-+					      CRYPTO_TFM_REQ_MAY_BACKLOG,
-+					      crypto_req_done,
-+					      &ctx->wait);
-+	}
-+
-+	switch (ctx->op) {
-+	case ALG_OP_ENCRYPT:
-+		err = crypto_akcipher_encrypt(&areq->cra_u.akcipher_req);
-+		break;
-+	case ALG_OP_DECRYPT:
-+		err = crypto_akcipher_decrypt(&areq->cra_u.akcipher_req);
-+		break;
-+	case ALG_OP_SIGN:
-+		err = crypto_akcipher_sign(&areq->cra_u.akcipher_req);
-+		break;
-+	case ALG_OP_VERIFY:
-+		err = crypto_akcipher_verify(&areq->cra_u.akcipher_req);
-+		break;
-+	default:
-+		err = -EOPNOTSUPP;
-+		goto free;
-+	}
-+
-+	if (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) {
-+		/* AIO operation in progress */
-+		if (err == -EINPROGRESS) {
-+			pr_info("%s: AIO operation in progress\n", __func__);
-+			sock_hold(sk);
-+
-+			/* Remember output size that will be generated. */
-+			areq->outlen = areq->cra_u.akcipher_req.dst_len;
-+
-+			return -EIOCBQUEUED;
-+		}
-+	} else {
-+		/* Wait for synchronous operation completion */
-+		err = crypto_wait_req(err, &ctx->wait);
-+	}
-+
-+free:
-+	af_alg_free_resources(areq);
-+
-+	return err ? err : areq->cra_u.akcipher_req.dst_len;
-+}
-+
-+static int akcipher_recvmsg(struct socket *sock, struct msghdr *msg,
-+			    size_t ignored, int flags)
-+{
-+	struct sock *sk = sock->sk;
-+	struct alg_sock *ask = alg_sk(sk);
-+	struct sock *psk = ask->parent;
-+	struct alg_sock *pask = alg_sk(psk);
-+	struct akcipher_tfm *akc = pask->private;
-+	struct crypto_akcipher *tfm = akc->akcipher;
-+
-+	int ret = 0;
-+
-+	lock_sock(sk);
-+
-+	while (msg_data_left(msg)) {
-+		int err = _akcipher_recvmsg(sock, msg, ignored, flags);
-+
-+		/*
-+		 * This error covers -EIOCBQUEUED which implies that we can
-+		 * only handle one AIO request. If the caller wants to have
-+		 * multiple AIO requests in parallel, he must make multiple
-+		 * separate AIO calls.
-+		 */
-+		if (err <= 0) {
-+			if (err == -EIOCBQUEUED || err == -EBADMSG || !ret)
-+				ret = err;
-+			goto out;
-+		}
-+
-+		ret += err;
-+
-+		/*
-+		 * The caller must provide crypto_akcipher_maxsize per request.
-+		 * If he provides more, we conclude that multiple akcipher
-+		 * operations are requested.
-+		 */
-+		iov_iter_advance(&msg->msg_iter,
-+				 crypto_akcipher_maxsize(tfm) - err);
-+	}
-+
-+out:
-+	af_alg_wmem_wakeup(sk);
-+	release_sock(sk);
-+	return ret;
-+}
-+
-+static struct proto_ops algif_akcipher_ops = {
-+	.family		=	PF_ALG,
-+
-+	.connect	=	sock_no_connect,
-+	.socketpair	=	sock_no_socketpair,
-+	.getname	=	sock_no_getname,
-+	.ioctl		=	sock_no_ioctl,
-+	.listen		=	sock_no_listen,
-+	.shutdown	=	sock_no_shutdown,
-+	.mmap		=	sock_no_mmap,
-+	.bind		=	sock_no_bind,
-+	.accept		=	sock_no_accept,
-+
-+	.release	=	af_alg_release,
-+	.sendmsg	=	akcipher_sendmsg,
-+	.recvmsg	=	akcipher_recvmsg,
-+	.poll		=	af_alg_poll,
-+};
-+
-+static int akcipher_check_key(struct socket *sock)
-+{
-+	int err = 0;
-+	struct sock *psk;
-+	struct alg_sock *pask;
-+	struct akcipher_tfm *tfm;
-+	struct sock *sk = sock->sk;
-+	struct alg_sock *ask = alg_sk(sk);
-+
-+	lock_sock(sk);
-+	if (atomic_read(&ask->refcnt))
-+		goto unlock_child;
-+
-+	psk = ask->parent;
-+	pask = alg_sk(ask->parent);
-+	tfm = pask->private;
-+
-+	err = -ENOKEY;
-+	lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
-+	if (!tfm->has_key)
-+		goto unlock;
-+
-+	atomic_inc(&pask->refcnt);
-+	if (!atomic_read(&pask->refcnt))
-+		sock_hold(psk);
-+
-+	atomic_set(&ask->refcnt, 1);
-+	sock_put(psk);
-+
-+	err = 0;
-+
-+unlock:
-+	release_sock(psk);
-+unlock_child:
-+	release_sock(sk);
-+
-+	return err;
-+}
-+
-+static int akcipher_sendmsg_nokey(struct socket *sock, struct msghdr *msg,
-+				  size_t size)
-+{
-+	int err;
-+
-+	err = akcipher_check_key(sock);
-+	if (err)
-+		return err;
-+
-+	return akcipher_sendmsg(sock, msg, size);
-+}
-+
-+static int akcipher_recvmsg_nokey(struct socket *sock, struct msghdr *msg,
-+				  size_t ignored, int flags)
-+{
-+	int err;
-+
-+	err = akcipher_check_key(sock);
-+	if (err)
-+		return err;
-+
-+	return akcipher_recvmsg(sock, msg, ignored, flags);
-+}
-+
-+static struct proto_ops algif_akcipher_ops_nokey = {
-+	.family		=	PF_ALG,
-+
-+	.connect	=	sock_no_connect,
-+	.socketpair	=	sock_no_socketpair,
-+	.getname	=	sock_no_getname,
-+	.ioctl		=	sock_no_ioctl,
-+	.listen		=	sock_no_listen,
-+	.shutdown	=	sock_no_shutdown,
-+	.mmap		=	sock_no_mmap,
-+	.bind		=	sock_no_bind,
-+	.accept		=	sock_no_accept,
-+
-+	.release	=	af_alg_release,
-+	.sendmsg	=	akcipher_sendmsg_nokey,
-+	.recvmsg	=	akcipher_recvmsg_nokey,
-+	.poll		=	af_alg_poll,
-+};
-+
-+static void *akcipher_bind(const char *name, u32 type, u32 mask)
-+{
-+	struct akcipher_tfm *tfm;
-+	struct crypto_akcipher *akcipher;
-+
-+	tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
-+	if (!tfm)
-+		return ERR_PTR(-ENOMEM);
-+
-+	akcipher = crypto_alloc_akcipher(name, type, mask);
-+	if (IS_ERR(akcipher)) {
-+		kfree(tfm);
-+		return ERR_CAST(akcipher);
-+	}
-+
-+	tfm->akcipher = akcipher;
-+
-+	return tfm;
-+}
-+
-+static void akcipher_release(void *private)
-+{
-+	struct akcipher_tfm *tfm = private;
-+	struct crypto_akcipher *akcipher = tfm->akcipher;
-+
-+	crypto_free_akcipher(akcipher);
-+	kfree(tfm);
-+}
-+
-+static int akcipher_setprivkey(void *private, const u8 *key,
-+			       unsigned int keylen)
-+{
-+	struct akcipher_tfm *tfm = private;
-+	struct crypto_akcipher *akcipher = tfm->akcipher;
-+	int err;
-+
-+	err = crypto_akcipher_set_priv_key(akcipher, key, keylen);
-+	tfm->has_key = !err;
-+
-+	/* Return the maximum size of the akcipher operation. */
-+	if (!err)
-+		err = crypto_akcipher_maxsize(akcipher);
-+
-+	return err;
-+}
-+
-+static int akcipher_setpubkey(void *private, const u8 *key, unsigned int keylen)
-+{
-+	struct akcipher_tfm *tfm = private;
-+	struct crypto_akcipher *akcipher = tfm->akcipher;
-+	int err;
-+
-+	err = crypto_akcipher_set_pub_key(akcipher, key, keylen);
-+	tfm->has_key = !err;
-+
-+	/* Return the maximum size of the akcipher operation. */
-+	if (!err)
-+		err = crypto_akcipher_maxsize(akcipher);
-+
-+	return err;
-+}
-+
-+static void akcipher_sock_destruct(struct sock *sk)
-+{
-+	struct alg_sock *ask = alg_sk(sk);
-+	struct af_alg_ctx *ctx = ask->private;
-+
-+	af_alg_pull_tsgl(sk, ctx->used, NULL, 0);
-+	sock_kfree_s(sk, ctx, ctx->len);
-+	af_alg_release_parent(sk);
-+}
-+
-+static int akcipher_accept_parent_nokey(void *private, struct sock *sk)
-+{
-+	struct af_alg_ctx *ctx;
-+	struct alg_sock *ask = alg_sk(sk);
-+	unsigned int len = sizeof(*ctx);
-+
-+	ctx = sock_kmalloc(sk, len, GFP_KERNEL);
-+	if (!ctx)
-+		return -ENOMEM;
-+	memset(ctx, 0, len);
-+
-+	INIT_LIST_HEAD(&ctx->tsgl_list);
-+	ctx->len = len;
-+	ctx->used = 0;
-+	atomic_set(&ctx->rcvused, 0);
-+	ctx->more = 0;
-+	ctx->merge = 0;
-+	ctx->op = 0;
-+	crypto_init_wait(&ctx->wait);
-+
-+	ask->private = ctx;
-+
-+	sk->sk_destruct = akcipher_sock_destruct;
-+
-+	return 0;
-+}
-+
-+static int akcipher_accept_parent(void *private, struct sock *sk)
-+{
-+	struct akcipher_tfm *tfm = private;
-+
-+	if (!tfm->has_key)
-+		return -ENOKEY;
-+
-+	return akcipher_accept_parent_nokey(private, sk);
-+}
-+
-+static const struct af_alg_type algif_type_akcipher = {
-+	.bind		=	akcipher_bind,
-+	.release	=	akcipher_release,
-+	.setkey		=	akcipher_setprivkey,
-+	.setpubkey	=	akcipher_setpubkey,
-+	.setauthsize	=	NULL,
-+	.accept		=	akcipher_accept_parent,
-+	.accept_nokey	=	akcipher_accept_parent_nokey,
-+	.ops		=	&algif_akcipher_ops,
-+	.ops_nokey	=	&algif_akcipher_ops_nokey,
-+	.name		=	"akcipher",
-+	.owner		=	THIS_MODULE
-+};
-+
-+static int __init algif_akcipher_init(void)
-+{
-+	return af_alg_register_type(&algif_type_akcipher);
-+}
-+
-+static void __exit algif_akcipher_exit(void)
-+{
-+	af_alg_unregister_type(&algif_type_akcipher);
-+}
-+
-+module_init(algif_akcipher_init);
-+module_exit(algif_akcipher_exit);
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
-+MODULE_DESCRIPTION("Asymmetric kernel crypto API user space interface");
-diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
-index 9ada9b741..5064d7fc6 100644
---- a/crypto/algif_skcipher.c
-+++ b/crypto/algif_skcipher.c
-@@ -118,25 +118,36 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
- 		skcipher_request_set_callback(&areq->cra_u.skcipher_req,
- 					      CRYPTO_TFM_REQ_MAY_SLEEP,
- 					      af_alg_async_cb, areq);
--		err = ctx->enc ?
--			crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
--			crypto_skcipher_decrypt(&areq->cra_u.skcipher_req);
-+	} else {
-+		/* Synchronous operation */
-+		skcipher_request_set_callback(&areq->cra_u.skcipher_req,
-+					      CRYPTO_TFM_REQ_MAY_SLEEP |
-+					      CRYPTO_TFM_REQ_MAY_BACKLOG,
-+					      crypto_req_done, &ctx->wait);
-+	}
- 
-+	switch (ctx->op) {
-+	case ALG_OP_ENCRYPT:
-+		err = crypto_skcipher_encrypt(&areq->cra_u.skcipher_req);
-+		break;
-+	case ALG_OP_DECRYPT:
-+		err = crypto_skcipher_decrypt(&areq->cra_u.skcipher_req);
-+		break;
-+	default:
-+		err = -EOPNOTSUPP;
-+		goto free;
-+	}
-+
-+	if (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) {
- 		/* AIO operation in progress */
- 		if (err == -EINPROGRESS)
- 			return -EIOCBQUEUED;
- 
- 		sock_put(sk);
-+
- 	} else {
--		/* Synchronous operation */
--		skcipher_request_set_callback(&areq->cra_u.skcipher_req,
--					      CRYPTO_TFM_REQ_MAY_SLEEP |
--					      CRYPTO_TFM_REQ_MAY_BACKLOG,
--					      crypto_req_done, &ctx->wait);
--		err = crypto_wait_req(ctx->enc ?
--			crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
--			crypto_skcipher_decrypt(&areq->cra_u.skcipher_req),
--						 &ctx->wait);
-+		/* Wait for synchronous operation completion */
-+		err = crypto_wait_req(err, &ctx->wait);
- 	}
- 
- 
-diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h
-index 08b803a4f..9004a83ab 100644
---- a/include/crypto/if_alg.h
-+++ b/include/crypto/if_alg.h
-@@ -18,6 +18,7 @@
- 
- #include <crypto/aead.h>
- #include <crypto/skcipher.h>
-+#include <crypto/akcipher.h>
- 
- #define ALG_MAX_PAGES			16
- 
-@@ -44,6 +45,7 @@ struct af_alg_type {
- 	void *(*bind)(const char *name, u32 type, u32 mask);
- 	void (*release)(void *private);
- 	int (*setkey)(void *private, const u8 *key, unsigned int keylen);
-+	int (*setpubkey)(void *private, const u8 *key, unsigned int keylen);
- 	int (*setentropy)(void *private, sockptr_t entropy, unsigned int len);
- 	int (*accept)(void *private, struct sock *sk);
- 	int (*accept_nokey)(void *private, struct sock *sk);
-@@ -108,6 +110,7 @@ struct af_alg_async_req {
- 	union {
- 		struct aead_request aead_req;
- 		struct skcipher_request skcipher_req;
-+		struct akcipher_request akcipher_req;
- 	} cra_u;
- 
- 	/* req ctx trails this struct */
-@@ -132,7 +135,7 @@ struct af_alg_async_req {
-  * @more:		More data to be expected from user space?
-  * @merge:		Shall new data from user space be merged into existing
-  *			SG?
-- * @enc:		Cryptographic operation to be performed when
-+ * @op:			Cryptographic operation to be performed when
-  *			recvmsg is invoked.
-  * @init:		True if metadata has been sent.
-  * @len:		Length of memory allocated for this data structure.
-@@ -151,8 +154,8 @@ struct af_alg_ctx {
- 
- 	bool more;
- 	bool merge;
--	bool enc;
- 	bool init;
-+	int op;
- 
- 	unsigned int len;
- 
-diff --git a/include/uapi/linux/if_alg.h b/include/uapi/linux/if_alg.h
-index 0824fbc02..7c40be624 100644
---- a/include/uapi/linux/if_alg.h
-+++ b/include/uapi/linux/if_alg.h
-@@ -53,9 +53,12 @@ struct af_alg_iv {
- #define ALG_SET_AEAD_AUTHSIZE		5
- #define ALG_SET_DRBG_ENTROPY		6
- #define ALG_SET_KEY_BY_KEY_SERIAL	7
-+#define ALG_SET_PUBKEY			8
- 
- /* Operations */
- #define ALG_OP_DECRYPT			0
- #define ALG_OP_ENCRYPT			1
-+#define ALG_OP_SIGN			2
-+#define ALG_OP_VERIFY			3
- 
- #endif	/* _LINUX_IF_ALG_H */
--- 
-2.34.1
-
diff --git a/recipes-kernel/linux/linux-gbmc_aspeedg7.bb b/recipes-kernel/linux/linux-gbmc_aspeedg7.bb
index f73b0a0..6932b18 100644
--- a/recipes-kernel/linux/linux-gbmc_aspeedg7.bb
+++ b/recipes-kernel/linux/linux-gbmc_aspeedg7.bb
@@ -2,7 +2,7 @@
 
 KERNEL_VERSION_SANITY_SKIP = "1"
 LINUX_MAJOR = "6.6"
-LINUX_VERSION = "${LINUX_MAJOR}.52"
+LINUX_VERSION = "${LINUX_MAJOR}.93"
 PV = "aspeedg7-${LINUX_VERSION}"
 LIC_FILES_CHKSUM = "file://COPYING;md5=6bc538ed5bd9a7fc9398086aedcd7e46"
 
@@ -10,7 +10,7 @@
 
 SRC_URI:prepend = " \
   ${KERNELORG_MIRROR}/linux/kernel/v6.x/linux-${LINUX_MAJOR}.tar.xz;sha256sum=d926a06c63dd8ac7df3f86ee1ffc2ce2a3b81a2d168484e76b5b389aba8e56d0 \
-  ${KERNELORG_MIRROR}/linux/kernel/v6.x/patch-${LINUX_VERSION}.xz;sha256sum=e6c027a20241a81991134448fc6af5805942264b981db718a4f16c3398606f9f \
+  ${KERNELORG_MIRROR}/linux/kernel/v6.x/patch-${LINUX_VERSION}.xz;sha256sum=5cf8db0daba2311c9dc3cfe95d7895e7217896520c49927f6e3dd2b6538b81f1 \
   "
 
 SRC_URI:append = " \
@@ -28,9 +28,9 @@
   "
 
 # TODO(b/386134258): ask Aspeed to upstream below
-# All these dirvers are porting from SDK v09.06 kernel
+# All these dirvers are porting from SDK v09.07 kernel
 # https://github.com/AspeedTech-BMC/linux/commits/aspeed-master-v6.6/
-# SHA: 882b09bd4db0ee14985070d0c7e413b8e4247ef1
+# SHA: e6cd1b0ff7798c191ddfddeec0b600374a5d2ed9
 SRC_URI:append:aspeed-g7 = " \
     file://0001-Add-arch-files-for-ast2700.patch \
     file://0002-Add-dt-bindings-head-file-for-ast2700.patch \
@@ -58,7 +58,7 @@
     file://0024-Add-SGMII-and-USB3-phy-driver-for-ast2700.patch \
     file://0025-bus-Add-Aspeed-LTPI-bus-controller-driver.patch \
     file://0026-Add-LTPI-GPIO-driver-for-ast2700.patch \
-    file://0027-Add-crypto-user-api-for-ast2700.patch \
+    file://0027-Add-DRAM-EDAC-driver-for-ast2700.patch \
     file://0028-mctp-i3c-MCTP-I3C-driver.patch \
 "
 
@@ -68,8 +68,6 @@
     file://0004-i3c-i3c-hub-Finish-all-work-before-adding-i2c-adapte.patch \
     file://0005-i3c-i3c-hub-Wait-rx-done-instead-of-tx-done.patch \
     file://0006-i3c-hub-Fix-compilation-error.patch \
-    file://0007-i3c-mipi-i3c-hci-aspeed-Add-SR_P-timing-configuratio.patch \
-    file://0008-i3c-mipi-i3c-hci-aspeed-Modify-the-tCAS-and-tCBP.patch \
     file://0009-mipi-i3c-hci-disable-DMA-experimental.patch \
     file://0010-Fix-the-i3c-hub-node-mismatch-issue.patch \
     file://i3c-hub.cfg \
@@ -83,3 +81,34 @@
 KCONFIG_MODE="--allnoconfig"
 # TODO(b/373416015) Remove this to enable CONFIGCHECK
 GBMC_CONFIGCHECK = "0"
+
+# Override poky/meta/classes-recipe/kernel-yocto.bbclass
+# Note: Applying patch-${LINUX_VERSION}.xz requires the presence of .gitignore
+# in the kernel source. We do not remove this file.
+do_kernel_checkout() {
+	set +e
+
+	source_dir=`echo ${S} | sed 's%/$%%'`
+	source_workdir="${WORKDIR}/git"
+
+	# case: we have no git repository at all. 
+	# To support low bandwidth options for building the kernel, we'll just 
+	# convert the tree to a git repo and let the rest of the process work unchanged
+
+	# if ${S} hasn't been set to the proper subdirectory a default of "linux" is 
+	# used, but we can't initialize that empty directory. So check it and throw a
+	# clear error
+
+	cd ${S}
+	if [ ! -f "Makefile" ]; then
+		bberror "S is not set to the linux source directory. Check "
+		bbfatal "the recipe and set S to the proper extracted subdirectory"
+	fi
+	git init
+	check_git_config
+	git add .
+	git commit -q -n -m "baseline commit: creating repo for ${PN}-${PV}"
+	git clean -d -f
+
+	set -e
+}