Browse Source

Merge branch 'CR_6790_MergeUboot_hal.feng' into 'jh7110-master'

CR_6790_MergeUboot_hal.feng

See merge request sdk/u-boot!74
andy.hu 5 months ago
parent
commit
918eb904cf
63 changed files with 7021 additions and 771 deletions
  1. 7 3
      arch/riscv/Kconfig
  2. 2 1
      arch/riscv/dts/Makefile
  3. 8 0
      arch/riscv/dts/jh7110-u-boot.dtsi
  4. 47 17
      arch/riscv/dts/jh7110.dtsi
  5. 0 9
      arch/riscv/dts/starfive_devkits-u-boot.dtsi
  6. 371 0
      arch/riscv/dts/starfive_devkits.dts
  7. 1 1
      arch/riscv/dts/starfive_evb.dts
  8. 0 104
      arch/riscv/dts/starfive_visionfive.dts
  9. 45 0
      arch/riscv/dts/starfive_visionfive2-u-boot.dtsi
  10. 477 0
      arch/riscv/dts/starfive_visionfive2.dts
  11. 14 0
      arch/riscv/include/asm/arch-jh7110/eeprom.h
  12. 3 3
      board/starfive/devkits/Kconfig
  13. 7 0
      board/starfive/devkits/MAINTAINERS
  14. 10 0
      board/starfive/devkits/Makefile
  15. 758 0
      board/starfive/devkits/devkits-i2c-eeprom.c
  16. 166 0
      board/starfive/devkits/spl.c
  17. 482 0
      board/starfive/devkits/starfive_devkits.c
  18. 0 7
      board/starfive/visionfive/MAINTAINERS
  19. 0 85
      board/starfive/visionfive/spl.c
  20. 0 207
      board/starfive/visionfive/starfive_visionfive.c
  21. 52 0
      board/starfive/visionfive2/Kconfig
  22. 7 0
      board/starfive/visionfive2/MAINTAINERS
  23. 2 2
      board/starfive/visionfive2/Makefile
  24. 189 0
      board/starfive/visionfive2/spl.c
  25. 547 0
      board/starfive/visionfive2/starfive_visionfive2.c
  26. 832 0
      board/starfive/visionfive2/visionfive2-i2c-eeprom.c
  27. 31 0
      cmd/Kconfig
  28. 14 29
      cmd/eeprom.c
  29. 1 1
      cmd/i2c.c
  30. 3 0
      common/board_r.c
  31. 171 0
      configs/starfive_devkits_defconfig
  32. 168 0
      configs/starfive_visionfive2_defconfig
  33. 0 75
      configs/starfive_visionfive_defconfig
  34. 52 18
      drivers/clk/starfive/clk-jh7110.c
  35. 7 0
      drivers/i2c/Kconfig
  36. 1 1
      drivers/i2c/Makefile
  37. 4 0
      drivers/mmc/dw_mmc.c
  38. 13 0
      drivers/net/dwc_eth_qos.c
  39. 8 4
      drivers/net/phy/motorcomm.c
  40. 30 5
      drivers/pci/pcie_starfive.c
  41. 13 2
      drivers/pinctrl/starfive/Kconfig
  42. 2 5
      drivers/pinctrl/starfive/Makefile
  43. 14 1
      drivers/pinctrl/starfive/pinctrl-jh7110-sys.c
  44. 9 0
      drivers/video/Kconfig
  45. 2 1
      drivers/video/Makefile
  46. 34 17
      drivers/video/starfive/mipi_dsi_host.c
  47. 38 9
      drivers/video/starfive/sf_mipi.c
  48. 1 0
      drivers/video/starfive/sf_mipi.h
  49. 139 3
      drivers/video/starfive/sf_vop.c
  50. 1302 0
      drivers/video/starfive_edp.c
  51. 24 9
      drivers/video/starfive_seeed_panel.c
  52. 1 1
      drivers/video/video-uclass.c
  53. 405 0
      include/configs/starfive-devkits.h
  54. 0 151
      include/configs/starfive-visionfive.h
  55. 374 0
      include/configs/starfive-visionfive2.h
  56. 25 0
      include/efi_api.h
  57. 4 0
      include/efi_loader.h
  58. 24 0
      include/efi_riscv.h
  59. 3 0
      include/init.h
  60. 10 0
      lib/efi_loader/Kconfig
  61. 1 0
      lib/efi_loader/Makefile
  62. 60 0
      lib/efi_loader/efi_riscv.c
  63. 6 0
      lib/efi_loader/efi_setup.c

+ 7 - 3
arch/riscv/Kconfig

@@ -23,8 +23,11 @@ config TARGET_SIFIVE_UNLEASHED
 config TARGET_SIFIVE_UNMATCHED
 	bool "Support SiFive Unmatched Board"
 
-config TARGET_STARFIVE_VISIONFIVE
-	bool "Support StarFive VisionFive Board"
+config TARGET_STARFIVE_DEVKITS
+	bool "Support StarFive DevKits Board"
+
+config TARGET_STARFIVE_VISIONFIVE2
+	bool "Support StarFive VisionFive2 Board"
 
 config TARGET_STARFIVE_EVB
 	bool "Support StarFive Evb Board"
@@ -71,7 +74,8 @@ source "board/sifive/unleashed/Kconfig"
 source "board/sifive/unmatched/Kconfig"
 source "board/openpiton/riscv64/Kconfig"
 source "board/sipeed/maix/Kconfig"
-source "board/starfive/visionfive/Kconfig"
+source "board/starfive/devkits/Kconfig"
+source "board/starfive/visionfive2/Kconfig"
 source "board/starfive/evb/Kconfig"
 
 # platform-specific options below

+ 2 - 1
arch/riscv/dts/Makefile

@@ -7,7 +7,8 @@ dtb-$(CONFIG_TARGET_OPENPITON_RISCV64) += openpiton-riscv64.dtb
 dtb-$(CONFIG_TARGET_SIFIVE_UNLEASHED) += hifive-unleashed-a00.dtb
 dtb-$(CONFIG_TARGET_SIFIVE_UNMATCHED) += hifive-unmatched-a00.dtb
 dtb-$(CONFIG_TARGET_SIPEED_MAIX) += k210-maix-bit.dtb
-dtb-$(CONFIG_TARGET_STARFIVE_VISIONFIVE) += starfive_visionfive.dtb
+dtb-$(CONFIG_TARGET_STARFIVE_DEVKITS) += starfive_devkits.dtb
+dtb-$(CONFIG_TARGET_STARFIVE_VISIONFIVE2) += starfive_visionfive2.dtb
 dtb-$(CONFIG_TARGET_STARFIVE_EVB) += starfive_evb.dtb
 
 targets += $(dtb-y)

+ 8 - 0
arch/riscv/dts/jh7110-u-boot.dtsi

@@ -129,3 +129,11 @@
 &gmac0_rmii_refin {
 	u-boot,dm-spl;
 };
+
+&gpio {
+	u-boot,dm-spl;
+};
+
+&gpioa {
+	u-boot,dm-spl;
+};

+ 47 - 17
arch/riscv/dts/jh7110.dtsi

@@ -623,19 +623,6 @@
 			status = "disabled";
 		};
 
-		i2c6: i2c@12060000 {
-			compatible = "snps,designware-i2c";
-			reg = <0x0 0x12060000 0x0 0x10000>;
-			clocks = <&clkgen JH7110_I2C6_CLK_CORE>,
-				 <&clkgen JH7110_I2C6_CLK_APB>;
-			clock-names = "ref", "pclk";
-			resets = <&rstgen RSTN_U6_DW_I2C_APB>;
-			interrupts = <51>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			status = "disabled";
-		};
-
 		i2c0: i2c@10030000 {
 			compatible = "snps,designware-i2c";
 			reg = <0x0 0x10030000 0x0 0x10000>;
@@ -675,6 +662,32 @@
 			status = "disabled";
 		};
 
+		i2c3: i2c@12030000 {
+			compatible = "snps,designware-i2c";
+			reg = <0x0 0x12030000 0x0 0x10000>;
+			clocks = <&clkgen JH7110_I2C3_CLK_CORE>,
+				 <&clkgen JH7110_I2C3_CLK_APB>;
+			clock-names = "ref", "pclk";
+			resets = <&rstgen RSTN_U3_DW_I2C_APB>;
+			interrupts = <48>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		i2c4: i2c@12040000 {
+			compatible = "snps,designware-i2c";
+			reg = <0x0 0x12040000 0x0 0x10000>;
+			clocks = <&clkgen JH7110_I2C4_CLK_CORE>,
+				 <&clkgen JH7110_I2C4_CLK_APB>;
+			clock-names = "ref", "pclk";
+			resets = <&rstgen RSTN_U4_DW_I2C_APB>;
+			interrupts = <49>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
 		i2c5: i2c@12050000 {
 			compatible = "snps,designware-i2c";
 			reg = <0x0 0x12050000 0x0 0x10000>;
@@ -688,6 +701,19 @@
 			status = "disabled";
 		};
 
+		i2c6: i2c@12060000 {
+			compatible = "snps,designware-i2c";
+			reg = <0x0 0x12060000 0x0 0x10000>;
+			clocks = <&clkgen JH7110_I2C6_CLK_CORE>,
+				 <&clkgen JH7110_I2C6_CLK_APB>;
+			clock-names = "ref", "pclk";
+			resets = <&rstgen RSTN_U6_DW_I2C_APB>;
+			interrupts = <51>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
 		/* unremovable emmc as mmcblk0 */
 		sdio0: sdio0@16010000 {
 			compatible = "snps,dw-mshc";
@@ -856,13 +882,15 @@
 				"ptp_ref",
 				"stmmaceth",
 				"pclk",
-				"gtxc";
+				"gtxc",
+				"rmii_rtx";
 			clocks = <&clkgen JH7110_GMAC0_GTXCLK>,
 				 <&clkgen JH7110_U0_GMAC5_CLK_TX>,
 				 <&clkgen JH7110_GMAC0_PTP>,
 				 <&clkgen JH7110_U0_GMAC5_CLK_AHB>,
 				 <&clkgen JH7110_U0_GMAC5_CLK_AXI>,
-				 <&clkgen JH7110_GMAC0_GTXC>;
+				 <&clkgen JH7110_GMAC0_GTXC>,
+				 <&clkgen JH7110_GMAC0_RMII_RTX>;
 			resets = <&rstgen RSTN_U0_DW_GMAC5_AXI64_AHB>,
 				 <&rstgen RSTN_U0_DW_GMAC5_AXI64_AXI>;
 			reset-names = "ahb", "stmmaceth";
@@ -897,13 +925,15 @@
 				"ptp_ref",
 				"stmmaceth",
 				"pclk",
-				"gtxc";
+				"gtxc",
+				"rmii_rtx";
 			clocks = <&clkgen JH7110_GMAC1_GTXCLK>,
 				 <&clkgen JH7110_GMAC5_CLK_TX>,
 				 <&clkgen JH7110_GMAC5_CLK_PTP>,
 				 <&clkgen JH7110_GMAC5_CLK_AHB>,
 				 <&clkgen JH7110_GMAC5_CLK_AXI>,
-				 <&clkgen JH7110_GMAC1_GTXC>;
+				 <&clkgen JH7110_GMAC1_GTXC>,
+				 <&clkgen JH7110_GMAC1_RMII_RTX>;
 			resets = <&rstgen RSTN_U1_DW_GMAC5_AXI64_H_N>,
 				 <&rstgen RSTN_U1_DW_GMAC5_AXI64_A_I>;
 			reset-names = "ahb", "stmmaceth";

+ 0 - 9
arch/riscv/dts/starfive_visionfive-u-boot.dtsi → arch/riscv/dts/starfive_devkits-u-boot.dtsi

@@ -27,12 +27,3 @@
 	};
 };
 
-&sdio0 {
-	clock-frequency = <4000000>;
-	max-frequency = <1000000>;
-};
-
-&sdio1 {
-	clock-frequency = <4000000>;
-	max-frequency = <1000000>;
-};

+ 371 - 0
arch/riscv/dts/starfive_devkits.dts

@@ -0,0 +1,371 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
+ */
+
+/dts-v1/;
+
+#include "jh7110.dtsi"
+#include <dt-bindings/pinctrl/pinctrl-starfive-jh7110.h>
+#include <dt-bindings/gpio/gpio.h>
+/ {
+	#address-cells = <2>;
+	#size-cells = <2>;
+	model = "StarFive JH7110 DevKits";
+	compatible = "starfive,jh7110";
+
+	aliases {
+		spi0="/soc/spi@13010000";
+		gpio0="/soc/gpio@13040000";
+		ethernet0=&gmac0;
+		ethernet1=&gmac1;
+		mmc0=&sdio0;
+		mmc1=&sdio1;
+		i2c5=&i2c5;
+	};
+
+	chosen {
+			stdout-path = "/soc/serial@10000000:115200";
+			starfive,boot-hart-id = <1>;
+	};
+
+
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0x0 0x40000000 0x1 0x0>;
+	};
+
+	soc {
+	};
+
+	gpio-restart {
+		compatible = "gpio-restart";
+		gpios = <&gpio 35 GPIO_ACTIVE_HIGH>;
+	};
+};
+
+&cpu0 {
+	status = "okay";
+};
+
+&clkgen {
+	clocks = <&osc>, <&gmac1_rmii_refin>,
+		<&stg_apb>, <&gmac0_rmii_refin>;
+	clock-names = "osc", "gmac1_rmii_refin",
+		"stg_apb", "gmac0_rmii_refin";
+};
+
+&gpio {
+	status = "okay";
+	gpio-controller;
+
+	i2c2_pins: i2c2-0 {
+		i2c-pins {
+			pinmux = <GPIOMUX(3, GPOUT_LOW,
+					     GPOEN_SYS_I2C2_CLK,
+					     GPI_SYS_I2C2_CLK)>,
+				 <GPIOMUX(2, GPOUT_LOW,
+					     GPOEN_SYS_I2C2_DATA,
+					     GPI_SYS_I2C2_DATA)>;
+			bias-disable; /* external pull-up */
+			input-enable;
+			input-schmitt-enable;
+		};
+	};
+
+	i2c5_pins: i2c5-0 {
+		i2c-pins {
+			pinmux = <GPIOMUX(19, GPOUT_LOW,
+					      GPOEN_SYS_I2C5_CLK,
+					      GPI_SYS_I2C5_CLK)>,
+				 <GPIOMUX(20, GPOUT_LOW,
+					      GPOEN_SYS_I2C5_DATA,
+					      GPI_SYS_I2C5_DATA)>;
+			bias-disable; /* external pull-up */
+			input-enable;
+			input-schmitt-enable;
+		};
+	};
+
+	mmc0_pins: mmc0-pins {
+		 mmc0-pins-rest {
+			pinmux = <GPIOMUX(22, GPOUT_SYS_SDIO0_RST,
+						GPOEN_ENABLE, GPI_NONE)>;
+			bias-pull-up;
+			drive-strength = <12>;
+			input-disable;
+			input-schmitt-disable;
+			slew-rate = <0>;
+		};
+	};
+
+	sdcard1_pins: sdcard1-pins {
+		sdcard1-pins0 {
+			pinmux = <GPIOMUX(10, GPOUT_SYS_SDIO1_CLK,
+						GPOEN_ENABLE, GPI_NONE)>;
+			bias-pull-up;
+			drive-strength = <12>;
+			input-disable;
+			input-schmitt-disable;
+			slew-rate = <0>;
+		};
+
+		sdcard1-pins1 {
+			pinmux = <GPIOMUX(9, GPOUT_SYS_SDIO1_CMD,
+						GPOEN_SYS_SDIO1_CMD, GPI_SYS_SDIO1_CMD)>;
+			bias-pull-up;
+			drive-strength = <12>;
+			input-enable;
+			input-schmitt-enable;
+			slew-rate = <0>;
+		};
+
+		sdcard1-pins2 {
+			pinmux = <GPIOMUX(11, GPOUT_SYS_SDIO1_DATA0,
+						GPOEN_SYS_SDIO1_DATA0, GPI_SYS_SDIO1_DATA0)>;
+			bias-pull-up;
+			drive-strength = <12>;
+			input-enable;
+			input-schmitt-enable;
+			slew-rate = <0>;
+		};
+
+		sdcard1-pins3 {
+			pinmux = <GPIOMUX(12, GPOUT_SYS_SDIO1_DATA1,
+						GPOEN_SYS_SDIO1_DATA1, GPI_SYS_SDIO1_DATA1)>;
+			bias-pull-up;
+			drive-strength = <12>;
+			input-enable;
+			input-schmitt-enable;
+			slew-rate = <0>;
+		};
+
+		sdcard1-pins4 {
+			pinmux = <GPIOMUX(7, GPOUT_SYS_SDIO1_DATA2,
+						GPOEN_SYS_SDIO1_DATA2, GPI_SYS_SDIO1_DATA2)>;
+			bias-pull-up;
+			drive-strength = <12>;
+			input-enable;
+			input-schmitt-enable;
+			slew-rate = <0>;
+		};
+
+		sdcard1-pins5 {
+			pinmux = <GPIOMUX(8, GPOUT_SYS_SDIO1_DATA3,
+						GPOEN_SYS_SDIO1_DATA3, GPI_SYS_SDIO1_DATA3)>;
+			bias-pull-up;
+			drive-strength = <12>;
+			input-enable;
+			input-schmitt-enable;
+			slew-rate = <0>;
+		};
+	};
+
+	hdmi_pins: hdmi-0 {
+		i2c-pins {
+			pinmux = <GPIOMUX(0, GPOUT_SYS_HDMI_DDC_SCL,
+				  GPOEN_SYS_HDMI_DDC_SCL,
+				  GPI_SYS_HDMI_DDC_SCL)>,
+				 <GPIOMUX(1, GPOUT_SYS_HDMI_DDC_SDA,
+				  GPOEN_SYS_HDMI_DDC_SDA,
+				  GPI_SYS_HDMI_DDC_SDA)>;
+			bias-pull-up;
+			input-enable;
+		};
+
+		cec-pins {
+			pinmux = <GPIOMUX(14, GPOUT_SYS_HDMI_CEC_SDA,
+				  GPOEN_SYS_HDMI_CEC_SDA,
+				  GPI_SYS_HDMI_CEC_SDA)>;
+			bias-pull-up;
+			input-enable;
+		};
+
+		hpd-pins {
+			pinmux = <GPIOMUX(15, GPOUT_LOW,
+				  GPOEN_DISABLE,
+				  GPI_SYS_HDMI_HPD)>;
+			input-enable;
+		};
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	i2c-sda-hold-time-ns = <300>;
+	i2c-sda-falling-time-ns = <510>;
+	i2c-scl-falling-time-ns = <510>;
+	auto_calc_scl_lhcnt;
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_pins>;
+	status = "okay";
+
+	seeed_panel: seeed_panel@45 {
+		compatible = "starfive,seeed";
+		reg = <0x45>;
+		sel-gpios = <&ext_gpio 5 GPIO_ACTIVE_LOW>;
+	};
+
+	lt8911exb_i2c@29 {
+		compatible = "lontium,lt8911exb";
+		reg = <0x29>;
+		reset-gpios = <&gpio 41 1>;
+		pwm-gpios = <&gpio 33 1>;
+		bl-gpios = <&ext_gpio 6 GPIO_ACTIVE_LOW>;
+
+	};
+};
+
+&i2c5 {
+	clock-frequency = <100000>;
+	i2c-sda-hold-time-ns = <300>;
+	i2c-sda-falling-time-ns = <510>;
+	i2c-scl-falling-time-ns = <510>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c5_pins>;
+	status = "okay";
+
+	pmic_axp15060: axp15060_reg@36 {
+		compatible = "stf,axp15060-regulator";
+		reg = <0x36>;
+	};
+
+	eeprom@50 {
+		compatible = "atmel,24c04";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+
+	ext_gpio: ext_gpio@74 {
+		compatible = "ti,tca9539";
+		reg = <0x74>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+};
+
+&sdio0 {
+	assigned-clocks = <&clkgen JH7110_SDIO0_CLK_SDCARD>;
+	assigned-clock-rates = <50000000>;
+	fifo-depth = <32>;
+	bus-width = <4>;
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_pins>;
+};
+
+&sdio1 {
+	assigned-clocks = <&clkgen JH7110_SDIO1_CLK_SDCARD>;
+	assigned-clock-rates = <50000000>;
+	fifo-depth = <32>;
+	bus-width = <4>;
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdcard1_pins>;
+};
+
+&gmac0 {
+	status = "okay";
+	#address-cells = <1>;
+	#size-cells = <0>;
+	phy0: ethernet-phy@0 {
+		rxc_dly_en = <0>;
+		rx_delay_sel = <0xb>;
+		tx_delay_sel_fe = <5>;
+		tx_delay_sel = <0xa>;
+		tx_inverted_10 = <0x1>;
+		tx_inverted_100 = <0x1>;
+		tx_inverted_1000 = <0x1>;
+	};
+};
+
+&gmac1 {
+	status = "okay";
+	#address-cells = <1>;
+	#size-cells = <0>;
+	phy1: ethernet-phy@1 {
+		rgmii_sw_dr_2 = <0x0>;
+		rgmii_sw_dr = <0x3>;
+		rgmii_sw_dr_rxc = <0x7>;
+		tx_delay_sel_fe = <5>;
+		tx_delay_sel = <0>;
+		rxc_dly_en = <0>;
+		rx_delay_sel = <0x2>;
+		tx_inverted_10 = <0x1>;
+		tx_inverted_100 = <0x1>;
+		tx_inverted_1000 = <0x0>;
+	};
+};
+
+&uart0 {
+	reg-offset = <0>;
+	current-speed = <115200>;
+	status = "okay";
+};
+
+&gpioa {
+	status = "disabled";
+};
+
+&usbdrd30 {
+	clocks = <&clkgen JH7110_USB_125M>,
+		 <&clkgen JH7110_USB0_CLK_APP_125>,
+		 <&clkgen JH7110_USB0_CLK_LPM>,
+		 <&clkgen JH7110_USB0_CLK_STB>,
+		 <&clkgen JH7110_USB0_CLK_USB_APB>,
+		 <&clkgen JH7110_USB0_CLK_AXI>,
+		 <&clkgen JH7110_USB0_CLK_UTMI_APB>,
+		 <&clkgen JH7110_PCIE0_CLK_APB>;
+	clock-names = "125m","app","lpm","stb","apb","axi","utmi", "phy";
+	resets = <&rstgen RSTN_U0_CDN_USB_PWRUP>,
+		 <&rstgen RSTN_U0_CDN_USB_APB>,
+		 <&rstgen RSTN_U0_CDN_USB_AXI>,
+		 <&rstgen RSTN_U0_CDN_USB_UTMI_APB>,
+		 <&rstgen RSTN_U0_PLDA_PCIE_APB>;
+	reset-names = "pwrup","apb","axi","utmi", "phy";
+	starfive,usb2-only = <0>;
+	status = "okay";
+};
+
+&usbdrd_cdns3 {
+	dr_mode = "unknown";
+	dr_num_mode = <1>;
+};
+
+&timer {
+	status = "disabled";
+};
+
+&wdog {
+	status = "disabled";
+};
+
+&clkvout {
+	status = "okay";
+};
+
+&pdm {
+	status = "disabled";
+};
+
+&dc8200 {
+	status = "okay";
+};
+&mipi_dsi0 {
+	status = "okay";
+	rockchip,panel = <&seeed_panel>;
+	data-lanes-num = <1>;
+	status = "okay";
+};
+
+&hdmi{
+	pinctrl-names = "default";
+	pinctrl-0 = <&hdmi_pins>;
+	status = "okay";
+};
+
+&pcie1 {
+	power-gpios = <&ext_gpio 0 GPIO_ACTIVE_HIGH>;
+	reset-gpios = <&gpio 18 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};

+ 1 - 1
arch/riscv/dts/starfive_evb.dts

@@ -399,7 +399,7 @@
 	status = "okay";
 
 	rm68200_panel: rm68200_panel@45 {
-		compatible = "raydium,rm68200";
+		compatible = "starfive,seeed";
 		reg = <0x45>;
 
 	};

+ 0 - 104
arch/riscv/dts/starfive_visionfive.dts

@@ -1,104 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0 OR MIT
-/*
- * Copyright (C) 2022 StarFive Technology Co., Ltd.
- */
-
-/dts-v1/;
-
-#include "jh7110.dtsi"
-/ {
-	#address-cells = <2>;
-	#size-cells = <2>;
-	model = "StarFive VisionFive V2";
-	compatible = "starfive,jh7110";
-
-	aliases {
-		spi0="/soc/spi@13010000";
-		gpio0="/soc/gpio@13040000";
-		ethernet0="/soc/ethernet@16030000";
-		mmc0="/soc/sdio0@16010000";
-		mmc1="/soc/sdio1@16020000";
-	};
-
-	chosen {
-			stdout-path = "/soc/serial@10000000:115200";
-	};
-
-
-	memory@80000000 {
-		device_type = "memory";
-		reg = <0x0 0x40000000 0x1 0x0>;
-	};
-
-	soc {
-	};
-};
-
-&cpu0 {
-	status = "okay";
-};
-
-&clkgen {
-	clocks = <&osc>, <&gmac1_rmii_refin>,
-		<&stg_apb>, <&gmac0_rmii_refin>;
-	clock-names = "osc", "gmac1_rmii_refin",
-		"stg_apb", "gmac0_rmii_refin";
-};
-
-&sdio0 {
-	clock-frequency = <4000000>;
-	max-frequency = <1000000>;
-	bus-width = <8>;
-	status = "okay";
-};
-
-&sdio1 {
-	clock-frequency = <4000000>;
-	max-frequency = <1000000>;
-	bus-width = <4>;
-	status = "okay";
-};
-
-&gmac0 {
-	phy-reset-gpios = <&gpio 63 0>;
-	status = "okay";
-};
-
-&gpio {
-	compatible = "starfive,jh7110-gpio";
-	gpio-controller;
-};
-
-&uart0 {
-	reg-offset = <0>;
-	current-speed = <115200>;
-	status = "okay";
-};
-
-&gpioa {
-	status = "disabled";
-};
-
-&usbdrd30 {
-	status = "okay";
-};
-
-&usbdrd_cdns3 {
-	dr_mode = "host";
-};
-
-&timer {
-	status = "disabled";
-};
-
-&wdog {
-	status = "disabled";
-};
-
-&clkvout {
-	status = "disabled";
-};
-
-&pdm {
-	status = "disabled";
-};

+ 45 - 0
arch/riscv/dts/starfive_visionfive2-u-boot.dtsi

@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
+ */
+
+#include "jh7110-u-boot.dtsi"
+/ {
+	chosen {
+			stdout-path = "/soc/serial@10000000:115200";
+			u-boot,dm-spl;
+	};
+
+	firmware {
+		spi0="/soc/qspi@11860000";
+		u-boot,dm-spl;
+	};
+
+	config {
+		u-boot,dm-spl;
+		u-boot,spl-payload-offset = <0x100000>; /* loader2 @1044KB */
+	};
+
+	memory@80000000 {
+		u-boot,dm-spl;
+		device_type = "memory";
+		reg = <0x0 0x40000000 0x1 0x0>;
+	};
+};
+
+&i2c5 {
+	clock-frequency = <100000>;
+	i2c-sda-hold-time-ns = <300>;
+	i2c-sda-falling-time-ns = <3000>;
+	i2c-scl-falling-time-ns = <3000>;
+	auto_calc_scl_lhcnt;
+	status = "okay";
+	u-boot,dm-spl;
+
+	eeprom@50 {
+		compatible = "atmel,24c04";
+		reg = <0x50>;
+		pagesize = <16>;
+		u-boot,dm-spl;
+	};
+};

+ 477 - 0
arch/riscv/dts/starfive_visionfive2.dts

@@ -0,0 +1,477 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
+ */
+
+/dts-v1/;
+
+#include "jh7110.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/pinctrl-starfive-jh7110.h>
+/ {
+	#address-cells = <2>;
+	#size-cells = <2>;
+	model = "StarFive VisionFive V2";
+	compatible = "starfive,jh7110";
+
+	aliases {
+		spi0="/soc/spi@13010000";
+		gpio0="/soc/gpio@13040000";
+		ethernet0=&gmac0;
+		ethernet1=&gmac1;
+		mmc0=&sdio0;
+		mmc1=&sdio1;
+		i2c0 = &i2c5;
+	};
+
+	chosen {
+			stdout-path = "/soc/serial@10000000:115200";
+			starfive,boot-hart-id = <1>;
+	};
+
+
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0x0 0x40000000 0x1 0x0>;
+	};
+
+	reserved-memory {
+			#size-cells = <2>;
+			#address-cells = <2>;
+			ranges;
+
+			opensbi {
+				reg = <0x00 0x40000000 0x00 0x80000>;
+				no-map;
+			};
+	};
+
+	soc {
+	};
+
+	gpio-restart {
+		compatible = "gpio-restart";
+		gpios = <&gpio 35 GPIO_ACTIVE_HIGH>;
+	};
+};
+
+&cpu0 {
+	status = "okay";
+};
+
+&clkgen {
+	clocks = <&osc>, <&gmac1_rmii_refin>,
+		<&stg_apb>, <&gmac0_rmii_refin>;
+	clock-names = "osc", "gmac1_rmii_refin",
+		"stg_apb", "gmac0_rmii_refin";
+};
+
+&gpio {
+	status = "okay";
+	gpio-controller;
+	uart0_pins: uart0-0 {
+		tx-pins {
+			pinmux = <GPIOMUX(5, GPOUT_SYS_UART0_TX,
+						GPOEN_ENABLE, GPI_NONE)>;
+			bias-disable;
+			drive-strength = <12>;
+			input-disable;
+			input-schmitt-disable;
+			slew-rate = <0>;
+		};
+
+		rx-pins {
+			pinmux = <GPIOMUX(6, GPOUT_LOW,
+						GPOEN_DISABLE, GPI_SYS_UART0_RX)>;
+			bias-pull-up;
+			drive-strength = <2>;
+			input-enable;
+			input-schmitt-enable;
+			slew-rate = <0>;
+		};
+	};
+
+	mmc0_pins: mmc0-pins {
+		 mmc0-pins-rest {
+			pinmux = <GPIOMUX(62, GPOUT_SYS_SDIO0_RST,
+						GPOEN_ENABLE, GPI_NONE)>;
+			bias-pull-up;
+			drive-strength = <12>;
+			input-disable;
+			input-schmitt-disable;
+			slew-rate = <0>;
+		};
+	};
+
+	sdcard1_pins: sdcard1-pins {
+		sdcard1-pins0 {
+			pinmux = <GPIOMUX(10, GPOUT_SYS_SDIO1_CLK,
+						GPOEN_ENABLE, GPI_NONE)>;
+			bias-pull-up;
+			drive-strength = <12>;
+			input-disable;
+			input-schmitt-disable;
+			slew-rate = <0>;
+		};
+
+		sdcard1-pins1 {
+			pinmux = <GPIOMUX(9, GPOUT_SYS_SDIO1_CMD,
+						GPOEN_SYS_SDIO1_CMD, GPI_SYS_SDIO1_CMD)>;
+			bias-pull-up;
+			drive-strength = <12>;
+			input-enable;
+			input-schmitt-enable;
+			slew-rate = <0>;
+		};
+
+		sdcard1-pins2 {
+			pinmux = <GPIOMUX(11, GPOUT_SYS_SDIO1_DATA0,
+						GPOEN_SYS_SDIO1_DATA0, GPI_SYS_SDIO1_DATA0)>;
+			bias-pull-up;
+			drive-strength = <12>;
+			input-enable;
+			input-schmitt-enable;
+			slew-rate = <0>;
+		};
+
+		sdcard1-pins3 {
+			pinmux = <GPIOMUX(12, GPOUT_SYS_SDIO1_DATA1,
+						GPOEN_SYS_SDIO1_DATA1, GPI_SYS_SDIO1_DATA1)>;
+			bias-pull-up;
+			drive-strength = <12>;
+			input-enable;
+			input-schmitt-enable;
+			slew-rate = <0>;
+		};
+
+		sdcard1-pins4 {
+			pinmux = <GPIOMUX(7, GPOUT_SYS_SDIO1_DATA2,
+						GPOEN_SYS_SDIO1_DATA2, GPI_SYS_SDIO1_DATA2)>;
+			bias-pull-up;
+			drive-strength = <12>;
+			input-enable;
+			input-schmitt-enable;
+			slew-rate = <0>;
+		};
+
+		sdcard1-pins5 {
+			pinmux = <GPIOMUX(8, GPOUT_SYS_SDIO1_DATA3,
+						GPOEN_SYS_SDIO1_DATA3, GPI_SYS_SDIO1_DATA3)>;
+			bias-pull-up;
+			drive-strength = <12>;
+			input-enable;
+			input-schmitt-enable;
+			slew-rate = <0>;
+		};
+	};
+
+	pcie0_perst_default: pcie0_perst_default {
+		perst-pins {
+			pinmux = <GPIOMUX(26, GPOUT_HIGH, GPOEN_ENABLE, GPI_NONE)>;
+			drive-strength = <2>;
+			input-disable;
+			input-schmitt-disable;
+			slew-rate = <0>;
+		};
+	};
+
+	pcie0_perst_active: pcie0_perst_active {
+		perst-pins {
+			pinmux = <GPIOMUX(26, GPOUT_LOW, GPOEN_ENABLE, GPI_NONE)>;
+			drive-strength = <2>;
+			input-disable;
+			input-schmitt-disable;
+			slew-rate = <0>;
+		};
+	};
+
+	pcie0_wake_default: pcie0_wake_default {
+		wake-pins {
+			pinmux = <GPIOMUX(32, GPOUT_HIGH, GPOEN_ENABLE, GPI_NONE)>;
+			drive-strength = <2>;
+			input-enable;
+			input-schmitt-disable;
+			slew-rate = <0>;
+		};
+	};
+
+	pcie0_clkreq_default: pcie0_clkreq_default {
+		clkreq-pins {
+			pinmux = <GPIOMUX(27, GPOUT_HIGH, GPOEN_ENABLE, GPI_NONE)>;
+			drive-strength = <2>;
+			input-enable;
+			input-schmitt-disable;
+			slew-rate = <0>;
+		};
+	};
+
+	pcie1_perst_default: pcie1_perst_default {
+		perst-pins {
+			pinmux = <GPIOMUX(28, GPOUT_HIGH, GPOEN_ENABLE, GPI_NONE)>;
+			drive-strength = <2>;
+			input-disable;
+			input-schmitt-disable;
+			slew-rate = <0>;
+		};
+	};
+
+	pcie1_perst_active: pcie1_perst_active {
+		perst-pins {
+			pinmux = <GPIOMUX(28, GPOUT_LOW, GPOEN_ENABLE, GPI_NONE)>;
+			drive-strength = <2>;
+			input-disable;
+			input-schmitt-disable;
+			slew-rate = <0>;
+		};
+	};
+
+	pcie1_wake_default: pcie1_wake_default {
+		wake-pins {
+			pinmux = <GPIOMUX(21, GPOUT_HIGH, GPOEN_ENABLE, GPI_NONE)>;
+			drive-strength = <2>;
+			input-enable;
+			input-schmitt-disable;
+			slew-rate = <0>;
+		};
+	};
+
+	pcie1_clkreq_default: pcie1_clkreq_default {
+		clkreq-pins {
+			pinmux = <GPIOMUX(29, GPOUT_HIGH, GPOEN_ENABLE, GPI_NONE)>;
+			drive-strength = <2>;
+			input-enable;
+			input-schmitt-disable;
+			slew-rate = <0>;
+		};
+	};
+
+	i2c2_pins: i2c2-0 {
+		i2c-pins {
+			pinmux = <GPIOMUX(3, GPOUT_LOW,
+				  GPOEN_SYS_I2C2_CLK,
+				  GPI_SYS_I2C2_CLK)>,
+				 <GPIOMUX(2, GPOUT_LOW,
+				  GPOEN_SYS_I2C2_DATA,
+				  GPI_SYS_I2C2_DATA)>;
+			bias-disable; /* external pull-up */
+			input-enable;
+			input-schmitt-enable;
+		};
+	};
+
+	i2c5_pins: i2c5-0 {
+		i2c-pins {
+			pinmux = <GPIOMUX(19, GPOUT_LOW,
+				  GPOEN_SYS_I2C5_CLK,
+				  GPI_SYS_I2C5_CLK)>,
+				 <GPIOMUX(20, GPOUT_LOW,
+				  GPOEN_SYS_I2C5_DATA,
+				  GPI_SYS_I2C5_DATA)>;
+			bias-disable; /* external pull-up */
+			input-enable;
+			input-schmitt-enable;
+		};
+	};
+
+	hdmi_pins: hdmi-0 {
+
+
+		cec-pins {
+			pinmux = <GPIOMUX(14, GPOUT_SYS_HDMI_CEC_SDA,
+				  GPOEN_SYS_HDMI_CEC_SDA,
+				  GPI_SYS_HDMI_CEC_SDA)>;
+			bias-pull-up;
+			input-enable;
+		};
+
+		hpd-pins {
+			pinmux = <GPIOMUX(15, GPOUT_LOW,
+				  GPOEN_DISABLE,
+				  GPI_SYS_HDMI_HPD)>;
+			input-enable;
+		};
+	};
+};
+
+&sdio0 {
+	assigned-clocks = <&clkgen JH7110_SDIO0_CLK_SDCARD>;
+	assigned-clock-rates = <50000000>;
+	fifo-depth = <32>;
+	bus-width = <8>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_pins>;
+	status = "okay";
+};
+
+&sdio1 {
+	assigned-clocks = <&clkgen JH7110_SDIO1_CLK_SDCARD>;
+	assigned-clock-rates = <50000000>;
+	fifo-depth = <32>;
+	bus-width = <4>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdcard1_pins>;
+	status = "okay";
+};
+
+&gmac0 {
+	status = "okay";
+	#address-cells = <1>;
+	#size-cells = <0>;
+	phy0: ethernet-phy@0 {
+		rgmii_sw_dr_2 = <0x0>;
+		rgmii_sw_dr = <0x3>;
+		rgmii_sw_dr_rxc = <0x6>;
+		rxc_dly_en = <0>;
+		rx_delay_sel = <0xa>;
+		tx_delay_sel_fe = <5>;
+		tx_delay_sel = <0xa>;
+		tx_inverted_10 = <0x1>;
+		tx_inverted_100 = <0x1>;
+		tx_inverted_1000 = <0x1>;
+	};
+};
+
+&gmac1 {
+	status = "okay";
+	#address-cells = <1>;
+	#size-cells = <0>;
+	phy1: ethernet-phy@1 {
+		rgmii_sw_dr_2 = <0x0>;
+		rgmii_sw_dr = <0x3>;
+		rgmii_sw_dr_rxc = <0x6>;
+		tx_delay_sel_fe = <5>;
+		tx_delay_sel = <0>;
+		rxc_dly_en = <0>;
+		rx_delay_sel = <0x2>;
+		tx_inverted_10 = <0x1>;
+		tx_inverted_100 = <0x1>;
+		tx_inverted_1000 = <0x0>;
+	};
+};
+
+&uart0 {
+	reg-offset = <0>;
+	current-speed = <115200>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+	status = "okay";
+};
+
+&i2c5 {
+	clock-frequency = <100000>;
+	i2c-sda-hold-time-ns = <300>;
+	i2c-sda-falling-time-ns = <3000>;
+	i2c-scl-falling-time-ns = <3000>;
+	auto_calc_scl_lhcnt;
+	status = "okay";
+
+	eeprom@50 {
+		compatible = "atmel,24c04";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+
+	pmic: axp15060_reg@36 {
+               compatible = "stf,axp15060-regulator";
+               reg = <0x36>;
+	};
+
+};
+
+&gpioa {
+	status = "disabled";
+};
+
+&usbdrd30 {
+	starfive,usb2-only = <1>;
+	status = "okay";
+};
+
+&usbdrd_cdns3 {
+	dr_mode = "peripheral";
+};
+
+&pcie0 {
+	pinctrl-names = "perst-default", "perst-active", "wake-default", "clkreq-default";
+	pinctrl-0 = <&pcie0_perst_default>;
+	pinctrl-1 = <&pcie0_perst_active>;
+	pinctrl-2 = <&pcie0_wake_default>;
+	pinctrl-3 = <&pcie0_clkreq_default>;
+	status = "okay";
+};
+
+&pcie1 {
+	pinctrl-names = "perst-default", "perst-active", "wake-default", "clkreq-default";
+	pinctrl-0 = <&pcie1_perst_default>;
+	pinctrl-1 = <&pcie1_perst_active>;
+	pinctrl-2 = <&pcie1_wake_default>;
+	pinctrl-3 = <&pcie1_clkreq_default>;
+	status = "okay";
+};
+
+&timer {
+	status = "disabled";
+};
+
+&wdog {
+	status = "disabled";
+};
+
+&clkvout {
+	status = "okay";
+};
+
+&pdm {
+	status = "disabled";
+};
+
+&mipi_dsi0 {
+	status = "okay";
+	rockchip,panel = <&rm68200_panel>;
+	data-lanes-num = <1>;
+	display-timings {
+		timing0 {
+		bits-per-pixel = <24>;
+		clock-frequency = <160000000>;
+		hfront-porch = <120>;
+		hsync-len = <20>;
+		hback-porch = <21>;
+		hactive = <1200>;
+		vfront-porch = <21>;
+		vsync-len = <3>;
+		vback-porch = <18>;
+		vactive = <1920>;
+		hsync-active = <0>;
+		vsync-active = <0>;
+		de-active = <1>;
+		pixelclk-active = <0>;
+		};
+	};
+
+};
+
+&hdmi{
+	pinctrl-names = "default";
+	pinctrl-0 = <&hdmi_pins>;
+	status = "okay";
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	i2c-sda-hold-time-ns = <300>;
+	i2c-sda-falling-time-ns = <3000>;
+	i2c-scl-falling-time-ns = <3000>;
+	auto_calc_scl_lhcnt;
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_pins>;
+	status = "okay";
+
+	rm68200_panel: rm68200_panel@45 {
+		compatible = "starfive,seeed";
+		reg = <0x45>;
+
+	};
+
+
+};
+

+ 14 - 0
arch/riscv/include/asm/arch-jh7110/eeprom.h

@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2021 StarFive Technology Co., Ltd.
+ *
+ * Author: Jianlong Huang <jianlong.huang@starfivetech.com>
+ */
+
+#ifndef _ASM_RISCV_EEPROM_H
+#define _ASM_RISCV_EEPROM_H
+
+u8 get_pcb_revision_from_eeprom(void);
+int get_data_from_eeprom(int offset, int len, unsigned char *data);
+
+#endif /* _ASM_RISCV_EEPROM_H */

+ 3 - 3
board/starfive/visionfive/Kconfig → board/starfive/devkits/Kconfig

@@ -1,16 +1,16 @@
-if TARGET_STARFIVE_VISIONFIVE
+if TARGET_STARFIVE_DEVKITS
 
 config SYS_CPU
 	default "jh7110"
 
 config SYS_BOARD
-	default "visionfive"
+	default "devkits"
 
 config SYS_VENDOR
 	default "starfive"
 
 config SYS_CONFIG_NAME
-	default "starfive-visionfive"
+	default "starfive-devkits"
 
 config ENV_SIZE
 	default 0x2000 if ENV_IS_IN_SPI_FLASH

+ 7 - 0
board/starfive/devkits/MAINTAINERS

@@ -0,0 +1,7 @@
+STARFIVE JH7110 DevKits BOARD
+M:	Yanhong Wang <yanhong.wang@starfivetech.com>
+S:	Maintained
+F:	arch/riscv/include/asm/arch-jh7110/
+F:	board/starfive/devkits/
+F:	include/configs/starfive-devkits.h
+F:	configs/starfive_devkits_defconfig

+ 10 - 0
board/starfive/devkits/Makefile

@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2021 Shanghai StarFive Technology Co., Ltd.
+#
+
+obj-y	:= starfive_devkits.o
+
+obj-$(CONFIG_SPL_BUILD) += spl.o
+
+obj-$(CONFIG_ID_EEPROM) += devkits-i2c-eeprom.o

+ 758 - 0
board/starfive/devkits/devkits-i2c-eeprom.c

@@ -0,0 +1,758 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved.
+ * Written by Wei Fu (wefu@redhat.com)
+ */
+
+
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <i2c.h>
+#include <init.h>
+#include <linux/ctype.h>
+#include <linux/delay.h>
+//#include <u-boot/crc.h>
+/*
+ * MAGIC_NUMBER_BYTES: number of bytes used by the magic number
+ */
+#define MAGIC_NUMBER_BYTES			4
+
+/*
+ * SERIAL_NUMBER_BYTES: number of bytes used by the board serial
+ * number
+ */
+//#define SERIAL_NUMBER_BYTES			16
+
+/*
+ * MAC_ADDR_BYTES: number of bytes used by the Ethernet MAC address
+ */
+#define MAC_ADDR_BYTES				6
+
+/*
+ * MAC_ADDR_STRLEN: length of mac address string
+ */
+#define MAC_ADDR_STRLEN				17
+
+/*
+ * Atom Types
+ * 0x0000 = invalid
+ * 0x0001 = vendor info
+ * 0x0002 = GPIO map
+ * 0x0003 = Linux device tree blob
+ * 0x0004 = manufacturer custom data
+ * 0x0005-0xfffe = reserved for future use
+ * 0xffff = invalid
+ */
+
+#define HATS_ATOM_INVALID	0x0000
+#define HATS_ATOM_VENDOR	0x0001
+#define HATS_ATOM_GPIO		0x0002
+#define HATS_ATOM_DTB		0x0003
+#define HATS_ATOM_CUSTOM	0x0004
+#define HATS_ATOM_INVALID_END	0xffff
+
+struct eeprom_hats_header {
+	char signature[MAGIC_NUMBER_BYTES];	/* ASCII table signature */
+	u8 version;		/* EEPROM data format version */
+				/* (0x00 reserved, 0x01 = first version) */
+	u8 reversed;		/* 0x00, Reserved field */
+	u16 numatoms;		/* total atoms in EEPROM */
+	u32 eeplen;		/* total length in bytes of all eeprom data */
+				/* (including this header) */
+};
+
+struct eeprom_hats_atom_header {
+	u16 type;
+	u16 count;
+	u32 dlen;
+};
+
+/**
+ * static eeprom: EEPROM layout for the StarFive platform I2C format
+ */
+struct starfive_eeprom_atom1_data {
+	u8 uuid[16];
+	u16 pid;
+	u16 pver;
+	u8 vslen;
+	u8 pslen;
+	uchar vstr[STARFIVE_EEPROM_ATOM1_VSTR_SIZE];
+	uchar pstr[STARFIVE_EEPROM_ATOM1_PSTR_SIZE]; /* product SN */
+};
+
+struct starfive_eeprom_atom1 {
+	struct eeprom_hats_atom_header header;
+	struct starfive_eeprom_atom1_data data;
+	u16 crc16;
+};
+
+struct starfive_eeprom_atom4_v1_data {
+	u16 version;
+	u8 pcb_revision;		/* PCB version */
+	u8 bom_revision;		/* BOM version */
+	u8 mac0_addr[MAC_ADDR_BYTES];	/* Ethernet0 MAC */
+	u8 mac1_addr[MAC_ADDR_BYTES];	/* Ethernet1 MAC */
+	u8 reserved[2];
+};
+
+struct starfive_eeprom_atom4_v1 {
+	struct eeprom_hats_atom_header header;
+	struct starfive_eeprom_atom4_v1_data data;
+	u16 crc16;
+};
+
+/* Set to 1 if we've read EEPROM into memory
+ * Set to -1 if EEPROM data is wrong
+ */
+static int has_been_read;
+
+/**
+ * helper struct for getting info from the local EEPROM copy.
+ * most of the items are pointers to the eeprom_wp_buff.
+ * ONLY serialnum is the u32 from the last 8 Bytes of product string
+ */
+struct starfive_eeprom_info {
+	char *vstr;		/* Vendor string in ATOM1 */
+	char *pstr;		/* product string in ATOM1 */
+	u32 serialnum;		/* serial number from in product string*/
+	u16 *version;		/* custom data version in ATOM4 */
+	u8 *pcb_revision;	/* PCB version in ATOM4 */
+	u8 *bom_revision;	/* BOM version in ATOM4 */
+	u8 *mac0_addr;		/* Ethernet0 MAC in ATOM4 */
+	u8 *mac1_addr;		/* Ethernet1 MAC in ATOM4 */
+};
+static struct starfive_eeprom_info einfo;
+
+
+static uchar eeprom_wp_buff[STARFIVE_EEPROM_HATS_SIZE_MAX];
+static struct eeprom_hats_header starfive_eeprom_hats_header_default = {
+	.signature = STARFIVE_EEPROM_HATS_SIG,
+	.version = FORMAT_VERSION,
+	.numatoms = 2,
+	.eeplen = sizeof(struct eeprom_hats_header) +
+		  sizeof(struct starfive_eeprom_atom1) +
+		  sizeof(struct starfive_eeprom_atom4_v1)
+};
+static struct starfive_eeprom_atom1 starfive_eeprom_atom1_default = {
+	.header = {
+		.type = HATS_ATOM_VENDOR,
+		.count = 1,
+		.dlen = sizeof(struct starfive_eeprom_atom1_data) + sizeof(u16)
+	},
+	.data = {
+		.uuid = {0},
+		.pid = 0,
+		.pver = 0,
+		.vslen = STARFIVE_EEPROM_ATOM1_VSTR_SIZE,
+		.pslen = STARFIVE_EEPROM_ATOM1_PSTR_SIZE,
+		.vstr = STARFIVE_EEPROM_ATOM1_VSTR,
+		.pstr = STARFIVE_EEPROM_ATOM1_PSTR
+	}
+};
+static struct starfive_eeprom_atom4_v1 starfive_eeprom_atom4_v1_default = {
+	.header = {
+		.type = HATS_ATOM_CUSTOM,
+		.count = 2,
+		.dlen = sizeof(struct starfive_eeprom_atom4_v1_data) + sizeof(u16)
+	},
+	.data = {
+		.version = FORMAT_VERSION,
+		.pcb_revision = PCB_VERSION,
+		.bom_revision = BOM_VERSION,
+		.mac0_addr = STARFIVE_DEFAULT_MAC0,
+		.mac1_addr = STARFIVE_DEFAULT_MAC1,
+		.reserved = {0}
+	}
+};
+
+//static u8 starfive_default_mac[MAC_ADDR_BYTES] = STARFIVE_DEFAULT_MAC;
+
+/**
+ * is_match_magic() - Does the magic number match that of a StarFive EEPROM?
+ *
+ * @hats:		the pointer of eeprom_hats_header
+ * Return:		status code, 0: Yes, non-0: NO
+ */
+static inline int is_match_magic(char *hats)
+{
+	return strncmp(hats, STARFIVE_EEPROM_HATS_SIG, MAGIC_NUMBER_BYTES);
+}
+
+/**
+ * calculate_crc16() - Calculate the current CRC for atom
+ * Porting from  https://github.com/raspberrypi/hats, getcrc
+ * @data:		the pointer of eeprom_hats_atom_header
+ * @size:		total length in bytes of the entire atom
+ * 			(type, count, dlen, data)
+ * Return:		result: crc16 code
+ */
+#define CRC16 0x8005
+static u16 calculate_crc16(uchar* data, unsigned int size)
+{
+	int i, j = 0x0001;
+	u16 out = 0, crc = 0;
+	int bits_read = 0, bit_flag;
+
+	/* Sanity check: */
+	if((data == NULL) || size == 0)
+		return 0;
+
+	while(size > 0) {
+		bit_flag = out >> 15;
+
+		/* Get next bit: */
+		out <<= 1;
+		// item a) work from the least significant bits
+		out |= (*data >> bits_read) & 1;
+
+		/* Increment bit counter: */
+		bits_read++;
+		if(bits_read > 7) {
+			bits_read = 0;
+			data++;
+			size--;
+		}
+
+		/* Cycle check: */
+		if(bit_flag)
+			out ^= CRC16;
+	}
+
+	// item b) "push out" the last 16 bits
+	for (i = 0; i < 16; ++i) {
+		bit_flag = out >> 15;
+		out <<= 1;
+		if(bit_flag)
+			out ^= CRC16;
+	}
+
+	// item c) reverse the bits
+	for (i = 0x8000; i != 0; i >>=1, j <<= 1) {
+		if (i & out)
+			crc |= j;
+	}
+
+	return crc;
+}
+
+/* This function should be called after each update to any EEPROM ATOM */
+static inline void update_crc(struct eeprom_hats_atom_header *atom)
+{
+	uint atom_crc_offset = sizeof(struct eeprom_hats_atom_header) +
+			       atom->dlen - sizeof(u16);
+	u16 *atom_crc_p = (void *) atom + atom_crc_offset;
+	*atom_crc_p = calculate_crc16((uchar*) atom, atom_crc_offset);
+}
+
+/**
+ * dump_raw_eeprom - display the raw contents of the EEPROM
+ */
+static void dump_raw_eeprom(u8 *e, unsigned int size)
+{
+	unsigned int i;
+
+	printf("EEPROM dump: (0x%x bytes)\n", size);
+
+	for (i = 0; i < size; i++) {
+		if (!(i % 0x10))
+			printf("%02X: ", i);
+
+		printf("%02X ", e[i]);
+
+		if (((i % 16) == 15) || (i == size - 1))
+			printf("\n");
+	}
+
+	return;
+}
+
+static int hats_atom_crc_check(struct eeprom_hats_atom_header *atom)
+{
+	u16 atom_crc, data_crc;
+	uint atom_crc_offset = sizeof(struct eeprom_hats_atom_header) +
+			       atom->dlen - sizeof(atom_crc);
+	u16 *atom_crc_p = (void *) atom + atom_crc_offset;
+
+	atom_crc = *atom_crc_p;
+	data_crc = calculate_crc16((uchar *) atom, atom_crc_offset);
+	if (atom_crc == data_crc)
+		return 0;
+
+	printf("EEPROM HATs: CRC ERROR in atom %x type %x, (%x!=%x)\n",
+		atom->count, atom->type, atom_crc, data_crc);
+	return -1;
+}
+
+static void *hats_get_atom(struct eeprom_hats_header *header, u16 type)
+ {
+	struct eeprom_hats_atom_header *atom;
+	void *hats_eeprom_max = (void *)header + header->eeplen;
+	void *temp = (void *)header + sizeof(struct eeprom_hats_header);
+
+	for (int numatoms = (int)header->numatoms; numatoms > 0; numatoms--) {
+		atom = (struct eeprom_hats_atom_header *)temp;
+		if (hats_atom_crc_check(atom))
+			return NULL;
+		if (atom->type == type)
+			return (void *)atom;
+		/* go to next atom */
+		temp = (void *)atom + sizeof(struct eeprom_hats_atom_header) +
+		       atom->dlen;
+		if (temp > hats_eeprom_max) {
+			printf("EEPROM HATs: table overflow next@%p, max@%p\n",
+				temp, hats_eeprom_max);
+			break;
+		}
+	}
+
+	/* fail to get atom */
+	return NULL;
+}
+
+/**
+ * show_eeprom - display the contents of the EEPROM
+ */
+static void show_eeprom(struct starfive_eeprom_info *einfo)
+{
+	if (has_been_read != 1)
+		return;
+
+	printf("\n--------EEPROM INFO--------\n");
+	printf("Vendor : %s\n", einfo->vstr);
+	printf("Product full SN: %s\n", einfo->pstr);
+	printf("data version: 0x%x\n", *einfo->version);
+	if (1 == *einfo->version) {
+		printf("PCB revision: 0x%x\n", *einfo->pcb_revision);
+		printf("BOM revision: %c\n", *einfo->bom_revision);
+		printf("Ethernet MAC0 address: %02x:%02x:%02x:%02x:%02x:%02x\n",
+		       einfo->mac0_addr[0], einfo->mac0_addr[1],
+		       einfo->mac0_addr[2], einfo->mac0_addr[3],
+		       einfo->mac0_addr[4], einfo->mac0_addr[5]);
+		printf("Ethernet MAC1 address: %02x:%02x:%02x:%02x:%02x:%02x\n",
+		       einfo->mac1_addr[0], einfo->mac1_addr[1],
+		       einfo->mac1_addr[2], einfo->mac1_addr[3],
+		       einfo->mac1_addr[4], einfo->mac1_addr[5]);
+	} else {
+		printf("Custom data v%d is not Supported\n", *einfo->version);
+	}
+	printf("--------EEPROM INFO--------\n\n");
+}
+
+/**
+ * parse_eeprom_info - parse the contents of the EEPROM
+ * If everthing gose right,
+ * 1, set has_been_read to 1
+ * 2, display info
+ *
+ * If anything goes wrong,
+ * 1, set has_been_read to -1
+ * 2, dump data by hex for debug
+ *
+ * @buf:		the pointer of eeprom_hats_header in memory
+ * Return:		status code, 0: Success, non-0: Fail
+ *
+ */
+static int parse_eeprom_info(struct eeprom_hats_header *buf)
+{
+	struct eeprom_hats_atom_header *atom;
+	void *atom_data;
+	struct starfive_eeprom_atom1_data *atom1 = NULL;
+	struct starfive_eeprom_atom4_v1_data *atom4_v1 = NULL;
+
+	if (is_match_magic((char *)buf)) {
+		printf("Not a StarFive EEPROM data format - magic error\n");
+		goto error;
+	};
+
+	printf("StarFive EEPROM format v%u\n", buf->version);
+
+	// parse atom1(verdor)
+	atom = (struct eeprom_hats_atom_header *)
+		hats_get_atom(buf, HATS_ATOM_VENDOR);
+	if (atom) {
+		atom_data = (void *)atom +
+			    sizeof(struct eeprom_hats_atom_header);
+		atom1 = (struct starfive_eeprom_atom1_data *)atom_data;
+		einfo.vstr = atom1->vstr;
+		einfo.pstr = atom1->pstr;
+		einfo.serialnum = (u32)hextoul((void *)atom1->pstr +
+					STARFIVE_EEPROM_ATOM1_SN_OFFSET,
+					NULL);
+	} else  {
+		printf("fail to get vendor atom\n");
+		goto error;
+	};
+
+	// parse atom4(custom)
+	atom = (struct eeprom_hats_atom_header *)
+		hats_get_atom(buf, HATS_ATOM_CUSTOM);
+	if (atom) {
+		atom_data = (void *)atom +
+			    sizeof(struct eeprom_hats_atom_header);
+		atom4_v1 = (struct starfive_eeprom_atom4_v1_data *)atom_data;
+		einfo.version = &atom4_v1->version;
+		if (*einfo.version == 1) {
+			einfo.pcb_revision = &atom4_v1->pcb_revision;
+			einfo.bom_revision = &atom4_v1->bom_revision;
+			einfo.mac0_addr =  atom4_v1->mac0_addr;
+			einfo.mac1_addr =  atom4_v1->mac1_addr;
+		}
+	} else  {
+		printf("fail to get custom data atom\n");
+		goto error;
+	};
+
+	// everthing gose right
+	has_been_read = 1;
+	show_eeprom(&einfo);
+	return 0;
+
+error:
+	has_been_read = -1;
+	dump_raw_eeprom(eeprom_wp_buff,
+			STARFIVE_EEPROM_HATS_SIZE_MAX);
+	return -1;
+}
+
+/**
+ * read_eeprom() - read the EEPROM into memory, if it hasn't been read yet
+ * @buf:		the pointer of eeprom data buff
+ * Return:		status code, 0: Success, non-0: Fail
+ * Note: depend on	CONFIG_SYS_EEPROM_BUS_NUM
+ * 			CONFIG_SYS_I2C_EEPROM_ADDR
+ * 			STARFIVE_EEPROM_WP_OFFSET
+ * 			STARFIVE_EEPROM_HATS_SIZE_MAX
+ */
+static int read_eeprom(uint8_t *buf)
+{
+	int ret;
+	struct udevice *dev;
+
+	if (has_been_read == 1)
+		return 0;
+
+	ret = i2c_get_chip_for_busnum(CONFIG_SYS_EEPROM_BUS_NUM,
+				      CONFIG_SYS_I2C_EEPROM_ADDR,
+				      CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
+				      &dev);
+	if (!ret) {
+		ret = dm_i2c_read(dev, STARFIVE_EEPROM_WP_OFFSET,
+				  buf, STARFIVE_EEPROM_HATS_SIZE_MAX);
+	}
+
+	if (ret) {
+		printf("fail to read EEPROM.\n");
+		return ret;
+	}
+
+	return parse_eeprom_info((struct eeprom_hats_header *)buf);
+}
+
+/**
+ * prog_eeprom() - write the EEPROM from memory
+ */
+static int prog_eeprom(uint8_t *buf, unsigned int size)
+{
+	unsigned int i;
+	void *p;
+	uchar tmp_buff[STARFIVE_EEPROM_HATS_SIZE_MAX];
+	struct udevice *dev;
+	int ret = i2c_get_chip_for_busnum(CONFIG_SYS_EEPROM_BUS_NUM,
+					  CONFIG_SYS_I2C_EEPROM_ADDR,
+					  CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
+					  &dev);
+
+	if (is_match_magic(buf)) {
+		printf("MAGIC ERROR, Please check the data@%p.\n", buf);
+		return -1;
+	}
+
+	for (i = 0, p = buf; i < size;
+	     i += BYTES_PER_EEPROM_PAGE, p += BYTES_PER_EEPROM_PAGE) {
+		if (!ret)
+			ret = dm_i2c_write(dev,
+					   i + STARFIVE_EEPROM_WP_OFFSET,
+					   p, min((int)(size - i),
+					   BYTES_PER_EEPROM_PAGE));
+		if (ret)
+			break;
+		udelay(EEPROM_WRITE_DELAY_MS);
+	}
+
+	if (!ret) {
+		/* Verify the write by reading back the EEPROM and comparing */
+		ret = dm_i2c_read(dev,
+				  STARFIVE_EEPROM_WP_OFFSET,
+				  tmp_buff,
+				  STARFIVE_EEPROM_HATS_SIZE_MAX);
+		if (!ret && memcmp((void *)buf, (void *)tmp_buff,
+				   STARFIVE_EEPROM_HATS_SIZE_MAX))
+			ret = -1;
+	}
+
+	if (ret) {
+		has_been_read = -1;
+		printf("Programming failed.Temp buff:\n");
+		dump_raw_eeprom(tmp_buff,
+				STARFIVE_EEPROM_HATS_SIZE_MAX);
+		return -1;
+	}
+
+	printf("Programming passed.\n");
+	return 0;
+}
+
+/**
+ * set_mac_address() - stores a MAC address into the local EEPROM copy
+ *
+ * This function takes a pointer to MAC address string
+ * (i.e."XX:XX:XX:XX:XX:XX", where "XX" is a two-digit hex number),
+ * stores it in the MAC address field of the EEPROM local copy, and
+ * updates the local copy of the CRC.
+ */
+static void set_mac_address(char *string, int index)
+{
+	unsigned int i;
+	struct eeprom_hats_atom_header *atom4;
+	atom4 = (struct eeprom_hats_atom_header *)
+		hats_get_atom((struct eeprom_hats_header *)eeprom_wp_buff,
+			      HATS_ATOM_CUSTOM);
+
+	if (strncasecmp(STARFIVE_OUI_PREFIX, string,
+			strlen(STARFIVE_OUI_PREFIX))) {
+		printf("The MAC address doesn't match StarFive OUI %s\n",
+		       STARFIVE_OUI_PREFIX);
+		return;
+	}
+
+	for (i = 0; *string && (i < MAC_ADDR_BYTES); i++) {
+		if (index == 0) {
+			einfo.mac0_addr[i] = hextoul(string, &string);
+		} else {
+			einfo.mac1_addr[i] = hextoul(string, &string);
+		}
+		if (*string == ':')
+			string++;
+	}
+
+	update_crc(atom4);
+}
+
+/**
+ * set_pcb_revision() - stores a StarFive PCB revision into the local EEPROM copy
+ *
+ * Takes a pointer to a string representing the numeric PCB revision in
+ * decimal ("0" - "255"), stores it in the pcb_revision field of the
+ * EEPROM local copy, and updates the CRC of the local copy.
+ */
+static void set_pcb_revision(char *string)
+{
+	u8 p;
+	uint base = 16;
+	struct eeprom_hats_atom_header *atom4;
+	atom4 = (struct eeprom_hats_atom_header *)
+		hats_get_atom((struct eeprom_hats_header *)eeprom_wp_buff,
+			      HATS_ATOM_CUSTOM);
+
+	p = (u8)simple_strtoul(string, NULL, base);
+	if (p > U8_MAX) {
+		printf("%s must not be greater than %d\n", "PCB revision",
+		       U8_MAX);
+		return;
+	}
+
+	*einfo.pcb_revision = p;
+
+	update_crc(atom4);
+}
+
+/**
+ * set_bom_revision() - stores a StarFive BOM revision into the local EEPROM copy
+ *
+ * Takes a pointer to a uppercase ASCII character representing the BOM
+ * revision ("A" - "Z"), stores it in the bom_revision field of the
+ * EEPROM local copy, and updates the CRC of the local copy.
+ */
+static void set_bom_revision(char *string)
+{
+	struct eeprom_hats_atom_header *atom4;
+	atom4 = (struct eeprom_hats_atom_header *)
+		hats_get_atom((struct eeprom_hats_header *)eeprom_wp_buff,
+			      HATS_ATOM_CUSTOM);
+
+	if (string[0] < 'A' || string[0] > 'Z') {
+		printf("BOM revision must be an uppercase letter between A and Z\n");
+		return;
+	}
+
+	*einfo.bom_revision = string[0];
+
+	update_crc(atom4);
+}
+
+/**
+ * set_product_id() - stores a StarFive product ID into the local EEPROM copy
+ *
+ * Takes a pointer to a string representing the numeric product ID  in
+ * string ("DK7110B1-2150-D104EC32-00000001\0"), stores it in the product string
+ * field of the EEPROM local copy, and updates the CRC of the local copy.
+ */
+static void set_product_id(char *string)
+{
+	struct eeprom_hats_atom_header *atom1;
+	atom1 = (struct eeprom_hats_atom_header *)
+		hats_get_atom((struct eeprom_hats_header *)eeprom_wp_buff,
+			      HATS_ATOM_VENDOR);
+
+	memcpy((void *)einfo.pstr, (void *)string,
+		STARFIVE_EEPROM_ATOM1_PSTR_SIZE);
+
+	update_crc(atom1);
+}
+
+/**
+ * init_local_copy() - initialize the in-memory EEPROM copy
+ *
+ * Initialize the in-memory EEPROM copy with the magic number.  Must
+ * be done when preparing to initialize a blank EEPROM, or overwrite
+ * one with a corrupted magic number.
+ */
+static void init_local_copy(uchar *buff)
+{
+	struct eeprom_hats_header *hats = (struct eeprom_hats_header *)buff;
+	struct eeprom_hats_atom_header *atom1 = (void *)hats +
+					sizeof(struct eeprom_hats_header);
+	struct eeprom_hats_atom_header *atom4_v1 = (void *)atom1 +
+					sizeof(struct starfive_eeprom_atom1);
+
+	memcpy((void *)hats, (void *)&starfive_eeprom_hats_header_default,
+	       sizeof(struct eeprom_hats_header));
+	memcpy((void *)atom1, (void *)&starfive_eeprom_atom1_default,
+	       sizeof(struct starfive_eeprom_atom1));
+	memcpy((void *)atom4_v1, (void *)&starfive_eeprom_atom4_v1_default,
+	       sizeof(struct starfive_eeprom_atom4_v1));
+
+	update_crc(atom1);
+	update_crc(atom4_v1);
+}
+
+static int print_usage(void)
+{
+	printf("display and program the system ID and MAC addresses in EEPROM\n"
+	"[read_eeprom|initialize|write_eeprom|mac_address|pcb_revision|bom_revision|product_id]\n"
+	"mac read_eeprom\n"
+	"    - read EEPROM content into memory data structure\n"
+	"mac write_eeprom\n"
+	"    - save memory data structure to the EEPROM\n"
+	"mac initialize\n"
+	"    - initialize the in-memory EEPROM copy with default data\n"
+	"mac mac0_address <xx:xx:xx:xx:xx:xx>\n"
+	"    - stores a MAC0 address into the local EEPROM copy\n"
+	"mac mac1_address <xx:xx:xx:xx:xx:xx>\n"
+	"    - stores a MAC1 address into the local EEPROM copy\n"
+	"mac pcb_revision <?>\n"
+	"    - stores a StarFive PCB revision into the local EEPROM copy\n"
+	"mac bom_revision <A>\n"
+	"    - stores a StarFive BOM revision into the local EEPROM copy\n"
+	"mac product_id <DK7110B1-2150-D104EC32-xxxxxxxx>\n"
+	"    - stores a StarFive product ID into the local EEPROM copy\n");
+	return 0;
+}
+
+int do_mac(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	char *cmd;
+
+	if (argc == 1) {
+		show_eeprom(&einfo);
+		return 0;
+	}
+
+	if (argc > 3)
+		return print_usage();
+
+	cmd = argv[1];
+
+	/* Commands with no argument */
+	if (!strcmp(cmd, "read_eeprom")) {
+		has_been_read = 0;
+		return read_eeprom(eeprom_wp_buff);
+	} else if (!strcmp(cmd, "initialize")) {
+		init_local_copy(eeprom_wp_buff);
+		return 0;
+	} else if (!strcmp(cmd, "write_eeprom")) {
+		return prog_eeprom(eeprom_wp_buff,
+				   STARFIVE_EEPROM_HATS_SIZE_MAX);
+	}
+
+	if (argc != 3)
+		return print_usage();
+
+	if (is_match_magic(eeprom_wp_buff)) {
+		printf("Please read the EEPROM ('read_eeprom') and/or initialize the EEPROM ('initialize') first.\n");
+		return 0;
+	}
+
+	if (!strcmp(cmd, "mac0_address")) {
+		set_mac_address(argv[2], 0);
+		return 0;
+	} else if (!strcmp(cmd, "mac1_address")) {
+		set_mac_address(argv[2], 1);
+		return 0;
+	} else if (!strcmp(cmd, "pcb_revision")) {
+		set_pcb_revision(argv[2]);
+		return 0;
+	} else if (!strcmp(cmd, "bom_revision")) {
+		set_bom_revision(argv[2]);
+		return 0;
+	} else if (!strcmp(cmd, "product_id")) {
+		set_product_id(argv[2]);
+		return 0;
+	}
+
+	return print_usage();
+}
+
+/**
+ * mac_read_from_eeprom() - read the MAC address & the serial number in EEPROM
+ *
+ * This function reads the MAC address and the serial number from EEPROM and
+ * sets the appropriate environment variables for each one read.
+ *
+ * The environment variables are only set if they haven't been set already.
+ * This ensures that any user-saved variables are never overwritten.
+ *
+ * If CONFIG_ID_EEPROM is enabled, this function will be called in
+ * "static init_fnc_t init_sequence_r[]" of u-boot/common/board_r.c.
+ */
+int mac_read_from_eeprom(void)
+{
+	/**
+	 * try to fill the buff from EEPROM,
+	 * always return SUCCESS, even some error happens.
+	 */
+	if (read_eeprom(eeprom_wp_buff))
+		return 0;
+
+	// 1, setup ethaddr env
+	eth_env_set_enetaddr("eth0addr", einfo.mac0_addr);
+	eth_env_set_enetaddr("eth1addr", einfo.mac1_addr);
+
+	/**
+	 * 2, setup serial# env, reference to hifive-platform-i2c-eeprom.c,
+	 * serial# can be a ASCII string, but not just a hex number, so we
+	 * setup serial# in the 32Byte format:
+	 * "DK7110B1-2150-D104EC32-00000001\0;"
+	 * "<product>-<date>-<DDR&eMMC>-<serial_number>"
+	 * <date>: 4Byte, should be the output of `date +%y%W`
+	 * <DDR&eMMC>: 8Byte, "D008" means 8GB, "D01T" means 1TB;
+	 *     "E000" means no eMMC,"E032" means 32GB, "E01T" means 1TB.
+	 * <serial_number>: 8Byte, the Unique Identifier of board in hex.
+	 */
+	if (!env_get("serial#"))
+		env_set("serial#", einfo.pstr);
+
+	return 0;
+}
+

+ 166 - 0
board/starfive/devkits/spl.c

@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022-2023 StarFive Technology Co., Ltd.
+ * Author:	yanhong <yanhong.wang@starfivetech.com>
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <asm/arch/spl.h>
+#include <asm/io.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/jh7110-regs.h>
+#include <asm/arch/clk.h>
+#include <image.h>
+#include <log.h>
+#include <spl.h>
+
+#define MODE_SELECT_REG		0x1702002c
+
+int spl_board_init_f(void)
+{
+	int ret;
+
+	ret = spl_soc_init();
+	if (ret) {
+		debug("JH7110 SPL init failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+u32 spl_boot_device(void)
+{
+	int boot_mode = 0;
+
+	boot_mode = readl((const volatile void *)MODE_SELECT_REG) & 0x3;
+	switch (boot_mode) {
+	case 0:
+		return BOOT_DEVICE_SPI;
+	case 1:
+		return BOOT_DEVICE_MMC2;
+	case 2:
+		return BOOT_DEVICE_MMC1;
+	case 3:
+		return BOOT_DEVICE_UART;
+	default:
+		debug("Unsupported boot device 0x%x.\n",
+		      boot_mode);
+		return BOOT_DEVICE_NONE;
+	}
+}
+
+struct image_header *spl_get_load_buffer(ssize_t offset, size_t size)
+{
+	return (struct image_header *)(STARFIVE_SPL_BOOT_LOAD_ADDR);
+}
+
+void board_init_f(ulong dummy)
+{
+	int ret;
+
+	/* Adjust cpu frequency, the default is 1.0GHz */
+	starfive_jh7110_pll_set_rate(PLL0, 1000000000);
+
+	/*change pll2 to 1188MHz*/
+	starfive_jh7110_pll_set_rate(PLL2, 1188000000);
+
+	/*DDR control depend clk init*/
+	clrsetbits_le32(SYS_CRG_BASE, CLK_CPU_ROOT_SW_MASK,
+		BIT(CLK_CPU_ROOT_SW_SHIFT) & CLK_CPU_ROOT_SW_MASK);
+
+	clrsetbits_le32(SYS_CRG_BASE + CLK_BUS_ROOT_OFFSET,
+		CLK_BUS_ROOT_SW_MASK,
+		BIT(CLK_BUS_ROOT_SW_SHIFT) & CLK_BUS_ROOT_SW_MASK);
+
+	/*Set clk_perh_root clk default mux sel to pll2*/
+	clrsetbits_le32(SYS_CRG_BASE + CLK_PERH_ROOT_OFFSET,
+		CLK_PERH_ROOT_MASK,
+		BIT(CLK_PERH_ROOT_SHIFT) & CLK_PERH_ROOT_MASK);
+
+	clrsetbits_le32(SYS_CRG_BASE + CLK_NOC_BUS_STG_AXI_OFFSET,
+		CLK_NOC_BUS_STG_AXI_EN_MASK,
+		BIT(CLK_NOC_BUS_STG_AXI_EN_SHIFT)
+		& CLK_NOC_BUS_STG_AXI_EN_MASK);
+
+	clrsetbits_le32(AON_CRG_BASE + CLK_AON_APB_FUNC_OFFSET,
+		CLK_AON_APB_FUNC_SW_MASK,
+		BIT(CLK_AON_APB_FUNC_SW_SHIFT) & CLK_AON_APB_FUNC_SW_MASK);
+
+	/* switch qspi clk to pll0 */
+	clrsetbits_le32(SYS_CRG_BASE + CLK_QSPI_REF_OFFSET,
+			CLK_QSPI_REF_SW_MASK,
+			BIT(CLK_QSPI_REF_SW_SHIFT) & CLK_QSPI_REF_SW_MASK);
+
+	/*set GPIO to 3.3v*/
+	setbits_le32(SYS_SYSCON_BASE + 0xC, 0x0);
+
+	/* Improved GMAC0 TX I/O PAD capability */
+	clrsetbits_le32(AON_IOMUX_BASE + 0x78, 0x3, BIT(0) & 0x3);
+	clrsetbits_le32(AON_IOMUX_BASE + 0x7c, 0x3, BIT(0) & 0x3);
+	clrsetbits_le32(AON_IOMUX_BASE + 0x80, 0x3, BIT(0) & 0x3);
+	clrsetbits_le32(AON_IOMUX_BASE + 0x84, 0x3, BIT(0) & 0x3);
+	clrsetbits_le32(AON_IOMUX_BASE + 0x88, 0x3, BIT(0) & 0x3);
+
+	/* Improved GMAC1 TX I/O PAD capability */
+	clrsetbits_le32(SYS_IOMUX_BASE + 0x26c, 0x3, BIT(0) & 0x3);
+	clrsetbits_le32(SYS_IOMUX_BASE + 0x270, 0x3, BIT(0) & 0x3);
+	clrsetbits_le32(SYS_IOMUX_BASE + 0x274, 0x3, BIT(0) & 0x3);
+	clrsetbits_le32(SYS_IOMUX_BASE + 0x278, 0x3, BIT(0) & 0x3);
+	clrsetbits_le32(SYS_IOMUX_BASE + 0x27c, 0x3, BIT(0) & 0x3);
+
+	SYS_IOMUX_DOEN(62, LOW);
+	SYS_IOMUX_DOUT(62, 19);
+	SYS_IOMUX_SET_DS(64, 2);
+	SYS_IOMUX_SET_SLEW(64, 1);
+	SYS_IOMUX_SET_DS(65, 1);
+	SYS_IOMUX_SET_DS(66, 1);
+	SYS_IOMUX_SET_DS(67, 1);
+	SYS_IOMUX_SET_DS(68, 1);
+	SYS_IOMUX_SET_DS(69, 1);
+	SYS_IOMUX_SET_DS(70, 1);
+	SYS_IOMUX_SET_DS(71, 1);
+	SYS_IOMUX_SET_DS(72, 1);
+	SYS_IOMUX_SET_DS(73, 1);
+
+	SYS_IOMUX_DOEN(10, LOW);
+	SYS_IOMUX_DOUT(10, 55);
+	SYS_IOMUX_SET_SLEW(10, 1);
+	SYS_IOMUX_SET_DS(10, 2);
+	SYS_IOMUX_COMPLEX(9, 44, 57, 19);
+	SYS_IOMUX_SET_DS(9, 1);
+	SYS_IOMUX_COMPLEX(11, 45, 58, 20);
+	SYS_IOMUX_SET_DS(11, 1);
+	SYS_IOMUX_COMPLEX(12, 46, 59, 21);
+	SYS_IOMUX_SET_DS(12, 1);
+	SYS_IOMUX_COMPLEX(7, 47, 60, 22);
+	SYS_IOMUX_SET_DS(7, 1);
+	SYS_IOMUX_COMPLEX(8, 48, 61, 23);
+	SYS_IOMUX_SET_DS(8, 1);
+
+	ret = spl_early_init();
+	if (ret)
+		panic("spl_early_init() failed: %d\n", ret);
+
+	arch_cpu_init_dm();
+
+	preloader_console_init();
+
+	ret = spl_board_init_f();
+	if (ret) {
+		debug("spl_board_init_f init failed: %d\n", ret);
+		return;
+	}
+}
+
+#ifdef CONFIG_SPL_LOAD_FIT
+int board_fit_config_name_match(const char *name)
+{
+	/* boot using first FIT config */
+	return 0;
+}
+#endif
+
+

+ 482 - 0
board/starfive/devkits/starfive_devkits.c

@@ -0,0 +1,482 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022-2023 StarFive Technology Co., Ltd.
+ * Author:	yanhong <yanhong.wang@starfivetech.com>
+ *
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/jh7110-regs.h>
+#include <asm/gpio.h>
+#include <cpu_func.h>
+#include <dm/uclass.h>
+#include <dm/device.h>
+#include <env.h>
+#include <i2c.h>
+#include <inttypes.h>
+#include <misc.h>
+#include <linux/bitops.h>
+#include <asm/arch/gpio.h>
+#include <bmp_logo.h>
+#include <video.h>
+#include <splash.h>
+#include <asm/gpio.h>
+#include <linux/err.h>
+
+
+#define SYS_CLOCK_ENABLE(clk) \
+	setbits_le32(SYS_CRG_BASE + clk, CLK_ENABLE_MASK)
+
+#define CPU_VOL_BINNING_OFFSET 0x7fc
+enum {
+	BOOT_FLASH =	0,
+	BOOT_SD,
+	BOOT_EMMC,
+	BOOT_UART,
+};
+enum cpu_voltage_type_t {
+	CPU_VOL_1020 = 0xef0,
+	CPU_VOL_1040 = 0xfff,
+	CPU_VOL_1060 = 0xff0,
+	CPU_VOL_1000  = 0x8f0,
+};
+#define CPU_VOL_MASK	0xfff
+
+static void sys_reset_clear(ulong assert, ulong status, u32 rst)
+{
+	u32 value;
+
+	clrbits_le32(SYS_CRG_BASE + assert, BIT(rst));
+	do {
+		value = in_le32(SYS_CRG_BASE + status);
+	} while ((value & BIT(rst)) != BIT(rst));
+}
+
+static void jh7110_timer_init(void)
+{
+	SYS_CLOCK_ENABLE(TIMER_CLK_APB_SHIFT);
+	SYS_CLOCK_ENABLE(TIMER_CLK_TIMER0_SHIFT);
+	SYS_CLOCK_ENABLE(TIMER_CLK_TIMER1_SHIFT);
+	SYS_CLOCK_ENABLE(TIMER_CLK_TIMER2_SHIFT);
+	SYS_CLOCK_ENABLE(TIMER_CLK_TIMER3_SHIFT);
+
+	sys_reset_clear(SYS_CRG_RESET_ASSERT3_SHIFT,
+			SYS_CRG_RESET_STATUS3_SHIFT, TIMER_RSTN_APB_SHIFT);
+	sys_reset_clear(SYS_CRG_RESET_ASSERT3_SHIFT,
+			SYS_CRG_RESET_STATUS3_SHIFT, TIMER_RSTN_TIMER0_SHIFT);
+	sys_reset_clear(SYS_CRG_RESET_ASSERT3_SHIFT,
+			SYS_CRG_RESET_STATUS3_SHIFT, TIMER_RSTN_TIMER1_SHIFT);
+	sys_reset_clear(SYS_CRG_RESET_ASSERT3_SHIFT,
+			SYS_CRG_RESET_STATUS3_SHIFT, TIMER_RSTN_TIMER2_SHIFT);
+	sys_reset_clear(SYS_CRG_RESET_ASSERT3_SHIFT,
+			SYS_CRG_RESET_STATUS3_SHIFT, TIMER_RSTN_TIMER3_SHIFT);
+}
+
+static void jh7110_i2c_init (int id)
+{
+	switch (id) {
+	case 5:
+		//scl
+		SYS_IOMUX_COMPLEX(19, 79, 0, 42);
+		//sda
+		SYS_IOMUX_COMPLEX(20, 80, 0, 43);
+
+		break;
+
+	default:
+		break;
+	}
+}
+
+static void jh7110_gmac_sel_tx_to_rgmii(int id)
+{
+	switch (id) {
+	case 0:
+		clrsetbits_le32(AON_CRG_BASE + GMAC5_0_CLK_TX_SHIFT,
+		GMAC5_0_CLK_TX_MASK,
+		BIT(GMAC5_0_CLK_TX_BIT) & GMAC5_0_CLK_TX_MASK);
+		break;
+	case 1:
+		clrsetbits_le32(SYS_CRG_BASE + GMAC5_1_CLK_TX_SHIFT,
+		GMAC5_1_CLK_TX_MASK,
+		BIT(GMAC5_1_CLK_TX_BIT) & GMAC5_1_CLK_TX_MASK);
+		break;
+	default:
+		break;
+	}
+}
+
+static void jh7110_gmac_io_pad(int id)
+{
+	u32 cap = BIT(0); /* 2.5V */
+
+	switch (id) {
+	case 0:
+		/* Improved GMAC0 TX I/O PAD capability */
+		clrsetbits_le32(AON_IOMUX_BASE + 0x78, 0x3, cap & 0x3);
+		clrsetbits_le32(AON_IOMUX_BASE + 0x7c, 0x3, cap & 0x3);
+		clrsetbits_le32(AON_IOMUX_BASE + 0x80, 0x3, cap & 0x3);
+		clrsetbits_le32(AON_IOMUX_BASE + 0x84, 0x3, cap & 0x3);
+		clrsetbits_le32(AON_IOMUX_BASE + 0x88, 0x3, cap & 0x3);
+		break;
+	case 1:
+		/* Improved GMAC1 TX I/O PAD capability */
+		clrsetbits_le32(SYS_IOMUX_BASE + 0x26c, 0x3, cap & 0x3);
+		clrsetbits_le32(SYS_IOMUX_BASE + 0x270, 0x3, cap & 0x3);
+		clrsetbits_le32(SYS_IOMUX_BASE + 0x274, 0x3, cap & 0x3);
+		clrsetbits_le32(SYS_IOMUX_BASE + 0x278, 0x3, cap & 0x3);
+		clrsetbits_le32(SYS_IOMUX_BASE + 0x27c, 0x3, cap & 0x3);
+		break;
+	}
+}
+
+static void jh7110_gmac_init(int id)
+{
+	jh7110_gmac_sel_tx_to_rgmii(id);
+	jh7110_gmac_io_pad(id);
+}
+
+static void jh7110_usb_init(bool usb2_enable)
+{
+	if (usb2_enable) {
+		/*usb 2.0 utmi phy init*/
+		clrsetbits_le32(STG_SYSCON_BASE  + STG_SYSCON_4,
+			USB_MODE_STRAP_MASK,
+			(2<<USB_MODE_STRAP_SHIFT) &
+			USB_MODE_STRAP_MASK);/*2:host mode, 4:device mode*/
+		clrsetbits_le32(STG_SYSCON_BASE + STG_SYSCON_4,
+			USB_OTG_SUSPENDM_BYPS_MASK,
+			BIT(USB_OTG_SUSPENDM_BYPS_SHIFT)
+			& USB_OTG_SUSPENDM_BYPS_MASK);
+		clrsetbits_le32(STG_SYSCON_BASE + STG_SYSCON_4,
+			USB_OTG_SUSPENDM_MASK,
+			BIT(USB_OTG_SUSPENDM_SHIFT) &
+			USB_OTG_SUSPENDM_MASK);/*HOST = 1. DEVICE = 0;*/
+		clrsetbits_le32(STG_SYSCON_BASE + STG_SYSCON_4,
+			USB_PLL_EN_MASK,
+			BIT(USB_PLL_EN_SHIFT) & USB_PLL_EN_MASK);
+		clrsetbits_le32(STG_SYSCON_BASE + STG_SYSCON_4,
+			USB_REFCLK_MODE_MASK,
+			BIT(USB_REFCLK_MODE_SHIFT) & USB_REFCLK_MODE_MASK);
+		/* usb 2.0 phy mode,REPLACE USB3.0 PHY module = 1;else = 0*/
+		clrsetbits_le32(SYS_SYSCON_BASE + SYS_SYSCON_24,
+			PDRSTN_SPLIT_MASK,
+			BIT(PDRSTN_SPLIT_SHIFT) &
+			PDRSTN_SPLIT_MASK);
+	} else {
+		/*usb 3.0 pipe phy config*/
+		clrsetbits_le32(STG_SYSCON_BASE  + STG_SYSCON_196,
+			PCIE_CKREF_SRC_MASK,
+			(0<<PCIE_CKREF_SRC_SHIFT) & PCIE_CKREF_SRC_MASK);
+		clrsetbits_le32(STG_SYSCON_BASE  + STG_SYSCON_196,
+			PCIE_CLK_SEL_MASK,
+			(0<<PCIE_CLK_SEL_SHIFT) & PCIE_CLK_SEL_MASK);
+		clrsetbits_le32(STG_SYSCON_BASE  + STG_SYSCON_328,
+			PCIE_PHY_MODE_MASK,
+			BIT(PCIE_PHY_MODE_SHIFT) & PCIE_PHY_MODE_MASK);
+		clrsetbits_le32(STG_SYSCON_BASE  + STG_SYSCON_500,
+			PCIE_USB3_BUS_WIDTH_MASK,
+			(0 << PCIE_USB3_BUS_WIDTH_SHIFT) &
+			PCIE_USB3_BUS_WIDTH_MASK);
+		clrsetbits_le32(STG_SYSCON_BASE  + STG_SYSCON_500,
+			PCIE_USB3_RATE_MASK,
+			(0 << PCIE_USB3_RATE_SHIFT) & PCIE_USB3_RATE_MASK);
+		clrsetbits_le32(STG_SYSCON_BASE  + STG_SYSCON_500,
+			PCIE_USB3_RX_STANDBY_MASK,
+			(0 << PCIE_USB3_RX_STANDBY_SHIFT)
+			& PCIE_USB3_RX_STANDBY_MASK);
+		clrsetbits_le32(STG_SYSCON_BASE  + STG_SYSCON_500,
+			PCIE_USB3_PHY_ENABLE_MASK,
+			BIT(PCIE_USB3_PHY_ENABLE_SHIFT)
+			& PCIE_USB3_PHY_ENABLE_MASK);
+
+		/* usb 3.0 phy mode,REPLACE USB3.0 PHY module = 1;else = 0*/
+		clrsetbits_le32(SYS_SYSCON_BASE + SYS_SYSCON_24,
+			PDRSTN_SPLIT_MASK,
+			(0 << PDRSTN_SPLIT_SHIFT) & PDRSTN_SPLIT_MASK);
+	}
+}
+
+#if CONFIG_IS_ENABLED(STARFIVE_OTP)
+static void get_cpu_voltage_type(struct udevice *dev)
+{
+	int ret;
+	u32 buf = CPU_VOL_1040;
+
+	ret = misc_read(dev, CPU_VOL_BINNING_OFFSET, &buf, sizeof(buf));
+	if (ret != sizeof(buf))
+		printf("%s: error reading CPU vol from OTP\n", __func__);
+	else {
+		switch ((buf & CPU_VOL_MASK)) {
+		case CPU_VOL_1000:
+			env_set("cpu_max_vol", "1000000");
+			break;
+		case CPU_VOL_1060:
+			env_set("cpu_max_vol", "1060000");
+			break;
+		case CPU_VOL_1020:
+			env_set("cpu_max_vol", "1020000");
+			break;
+		default:
+			env_set("cpu_max_vol", "1040000");
+			break;
+		}
+	}
+}
+#endif
+
+static void get_boot_mode(void)
+{
+	u32 value;
+
+	value = in_le32(AON_IOMUX_BASE + AON_GPIO_DIN_REG);
+	switch (value & 0x03) {
+		case BOOT_FLASH:
+			env_set("bootmode", "flash");
+			env_set("devnum", "1");
+			break;
+
+		case BOOT_SD:
+			env_set("bootmode", "sd");
+			env_set("devnum", "1");
+			break;
+
+		case BOOT_EMMC:
+			env_set("bootmode", "emmc");
+			env_set("devnum", "0");
+			break;
+
+		default:
+			env_set("bootmode", "uart");
+			env_set("devnum", "1");
+			break;
+	}
+}
+
+#define CONFIG_SYS_PMIC_BUS_NUM			5
+#define CONFIG_SYS_I2C_PMIC_ADDR		0x36
+#define CONFIG_SYS_I2C_PMIC_ADDR_LEN		1
+#define AXP15060_DCDC_MODE_CTRL_2		0x1b
+#define AXP15060_DCDC5_MODE_BIT			BIT(4)
+#define AXP15060_PWR_SEQUENCE_CTRL		0X32
+#define AXP15060_RST_PMIC_BY_PWROK_BIT		BIT(4)
+
+int set_pmic(void)
+{
+	int ret;
+	struct udevice *dev;
+	u8 temp_buf;
+
+	ret = i2c_get_chip_for_busnum(CONFIG_SYS_PMIC_BUS_NUM,
+				      CONFIG_SYS_I2C_PMIC_ADDR,
+				      CONFIG_SYS_I2C_PMIC_ADDR_LEN,
+				      &dev);
+
+	if (!ret) {
+		/* Set Pmic DCDC5 Mode as PWM */
+		ret = dm_i2c_read(dev,
+				  AXP15060_DCDC_MODE_CTRL_2,
+				  &temp_buf,
+				  sizeof(temp_buf));
+		if (ret)
+			printf("%s: can't read pmic dcdc5 mode register\n",
+                                 __func__);
+
+		temp_buf = temp_buf | AXP15060_DCDC5_MODE_BIT;
+		ret = dm_i2c_write(dev,
+				AXP15060_DCDC_MODE_CTRL_2,
+				&temp_buf,
+				sizeof(temp_buf));
+		if (ret)
+			printf("%s: can't write pmic dcdc5 mode register\n",
+                                 __func__);
+
+		/* Enable PWROK in PMIC */
+		ret = dm_i2c_read(dev,
+				  AXP15060_PWR_SEQUENCE_CTRL,
+				  &temp_buf,
+				  sizeof(temp_buf));
+		if (ret)
+                        printf("%s: can't read pmic power disbale & down sequence register\n",
+                                 __func__);
+
+		temp_buf = temp_buf | AXP15060_RST_PMIC_BY_PWROK_BIT;
+		ret = dm_i2c_write(dev,
+                                AXP15060_PWR_SEQUENCE_CTRL,
+                                &temp_buf,
+                                sizeof(temp_buf));
+		if (ret)
+                        printf("%s: can't write pmic power disbale & down sequence register\n",
+                                 __func__);
+
+	}
+
+	return 0;
+}
+
+int board_init(void)
+{
+	enable_caches();
+
+	jh7110_timer_init();
+	jh7110_usb_init(true);
+	jh7110_gmac_init(0);
+	jh7110_gmac_init(1);
+	jh7110_i2c_init(5);
+
+	return 0;
+}
+
+#ifdef CONFIG_MISC_INIT_R
+
+int misc_init_r(void)
+{
+	char mac0[6] = {0x6c, 0xcf, 0x39, 0x6c, 0xde, 0xad};
+	char mac1[6] = {0x6c, 0xcf, 0x39, 0x7c, 0xae, 0x5d};
+
+#if CONFIG_IS_ENABLED(STARFIVE_OTP)
+	struct udevice *dev;
+	char buf[16];
+	int ret;
+#define MACADDR_OFFSET 0x8
+
+	ret = uclass_get_device_by_driver(UCLASS_MISC,
+				DM_DRIVER_GET(starfive_otp), &dev);
+	if (ret) {
+		debug("%s: could not find otp device\n", __func__);
+		goto err;
+	}
+
+	ret = misc_read(dev, MACADDR_OFFSET, buf, sizeof(buf));
+	if (ret != sizeof(buf))
+		printf("%s: error reading mac from OTP\n", __func__);
+	else
+		if (buf[0] != 0xff) {
+			memcpy(mac0, buf, 6);
+			memcpy(mac1, &buf[8], 6);
+		}
+err:
+#endif
+	eth_env_set_enetaddr("eth0addr", mac0);
+	eth_env_set_enetaddr("eth1addr", mac1);
+
+#if CONFIG_IS_ENABLED(STARFIVE_OTP)
+	get_cpu_voltage_type(dev);
+#endif
+	return 0;
+}
+#endif
+
+int board_late_init(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	get_boot_mode();
+
+	env_set("chip_vision", "B");
+
+	/*
+	 * save the memory info by environment variable in u-boot,
+	 * It will used to update the memory configuration in dts,
+	 * which passed to kernel lately.
+	 */
+	env_set_hex("memory_addr", gd->ram_base);
+	env_set_hex("memory_size", gd->ram_size);
+
+	ret = uclass_get_device(UCLASS_VIDEO, 0, &dev);
+	if (ret)
+		return ret;
+
+	ret = video_bmp_display(dev, (ulong)&bmp_logo_bitmap[0], BMP_ALIGN_CENTER, BMP_ALIGN_CENTER, true);
+	if (ret)
+		goto err;
+
+err:
+		return 0;
+
+}
+
+static int jh7110_get_gpio_val(u32 gpio)
+{
+	int ret;
+
+	ret = gpio_request(gpio, "ddr_gpio");
+	if (!ret) {
+		ret = gpio_direction_input(gpio);
+		if (!ret)
+			ret = gpio_get_value(gpio);
+
+		gpio_free(gpio);
+	}
+
+	return ret;
+}
+
+int board_ddr_size(void)
+{
+	int val, ret;
+
+	val = jh7110_get_gpio_val(21);
+	if (IS_ERR_VALUE(val))
+		return val;
+
+	ret = jh7110_get_gpio_val(22);
+	if (IS_ERR_VALUE(ret))
+		return ret;
+
+	val |= (ret << 1);
+
+	switch (val) {
+	case 0x0:
+		ret = 8; //8GB
+		break;
+	case 0x1:
+		ret = 4; //4GB
+		break;
+	case 0x2:
+		ret = 2; //2GB
+		break;
+	case 0x3:
+		ret = 1; //1GB
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	};
+
+	return ret;
+}
+
+static int starfive_get_gpio_val(u32 gpio)
+{
+	int ret;
+
+	ret = gpio_request(gpio, "ddr_gpio");
+	if (!ret) {
+		ret = gpio_direction_input(gpio);
+		if (!ret)
+			ret = gpio_get_value(gpio);
+
+		gpio_free(gpio);
+	}
+
+	return ret;
+}
+
+/* get ddr type from GPIO23,GPIO24 DDR4 or LPDDR4 */
+int starfive_get_ddr_type(void)
+{
+	int val, ret;
+
+	val = starfive_get_gpio_val(23);
+	if (IS_ERR_VALUE(val))
+		return val;
+
+	ret = starfive_get_gpio_val(24);
+	if (IS_ERR_VALUE(ret))
+		return ret;
+
+	return val | (ret << 1);
+}

+ 0 - 7
board/starfive/visionfive/MAINTAINERS

@@ -1,7 +0,0 @@
-STARFIVE JH7110 VISIONFIVE BOARD
-M: startfive
-S:	Maintained
-F:	arch/riscv/include/asm/arch-jh7110/
-F:	board/starfive/visionfive/
-F:	include/configs/starfive-visionfive.h
-F:	configs/starfive_visionfive_defconfig

+ 0 - 85
board/starfive/visionfive/spl.c

@@ -1,85 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2022-2023 StarFive Technology Co., Ltd.
- * Author:	yanhong <yanhong.wang@starfivetech.com>
- *
- */
-
-#include <common.h>
-#include <init.h>
-#include <spl.h>
-#include <log.h>
-#include <linux/delay.h>
-#include <image.h>
-#include <asm/arch/spl.h>
-#include <asm/io.h>
-
-#define MODE_SELECT_REG		0x1702002c
-
-int spl_board_init_f(void)
-{
-	int ret;
-
-	ret = spl_soc_init();
-	if (ret) {
-		debug("JH7110 SPL init failed: %d\n", ret);
-		return ret;
-	}
-
-	return 0;
-}
-
-u32 spl_boot_device(void)
-{
-	int boot_mode = 0;
-
-	boot_mode = readl((const volatile void *)MODE_SELECT_REG) & 0xF;
-	switch (boot_mode) {
-	case 0:
-		return BOOT_DEVICE_SPI;
-	case 1:
-		return BOOT_DEVICE_MMC2;
-	case 2:
-		return BOOT_DEVICE_MMC1;
-	case 4:
-		return BOOT_DEVICE_UART;
-	default:
-		debug("Unsupported boot device 0x%x.\n",
-		      boot_mode);
-		return BOOT_DEVICE_NONE;
-	}
-}
-
-struct image_header *spl_get_load_buffer(ssize_t offset, size_t size)
-{
-	return (struct image_header *)(STARFIVE_SPL_BOOT_LOAD_ADDR);
-}
-
-void board_init_f(ulong dummy)
-{
-	int ret;
-
-	ret = spl_early_init();
-	if (ret)
-		panic("spl_early_init() failed: %d\n", ret);
-
-	arch_cpu_init_dm();
-
-	preloader_console_init();
-
-	ret = spl_board_init_f();
-	if (ret) {
-		debug("spl_board_init_f init failed: %d\n", ret);
-		return;
-	}
-}
-
-#ifdef CONFIG_SPL_LOAD_FIT
-int board_fit_config_name_match(const char *name)
-{
-	/* boot using first FIT config */
-	return 0;
-}
-#endif
-
-

+ 0 - 207
board/starfive/visionfive/starfive_visionfive.c

@@ -1,207 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
- * Author:	yanhong <yanhong.wang@starfivetech.com>
- *
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <asm/arch/jh7110-regs.h>
-#include <cpu_func.h>
-#include <dm/uclass.h>
-#include <dm/device.h>
-#include <env.h>
-#include <inttypes.h>
-#include <misc.h>
-#include <linux/bitops.h>
-#include <asm/arch/gpio.h>
-
-#define SYS_IOMUX_DOEN(gpio, oen) \
-	clrsetbits_le32(SYS_IOMUX_BASE+GPIO_OFFSET(gpio), \
-		GPIO_DOEN_MASK <<  GPIO_SHIFT(gpio), \
-		(oen) << GPIO_SHIFT(gpio))
-
-#define SYS_IOMUX_DOUT(gpio, gpo) \
-	clrsetbits_le32(SYS_IOMUX_BASE + GPIO_DOUT + GPIO_OFFSET(gpio),\
-		GPIO_DOUT_MASK << GPIO_SHIFT(gpio),\
-		((gpo) & GPIO_DOUT_MASK) << GPIO_SHIFT(gpio))
-
-#define SYS_IOMUX_DIN(gpio, gpi)\
-	clrsetbits_le32(SYS_IOMUX_BASE + GPIO_DIN + GPIO_OFFSET(gpi),\
-		GPIO_DIN_MASK << GPIO_SHIFT(gpi),\
-		((gpio+2) & GPIO_DIN_MASK) << GPIO_SHIFT(gpi))
-
-#define SYS_IOMUX_COMPLEX(gpio, gpi, gpo, oen) do {\
-	SYS_IOMUX_DOEN(gpio, oen);\
-	SYS_IOMUX_DOUT(gpio, gpo);\
-	SYS_IOMUX_DIN(gpio, gpi); }while(0)
-
-#define SYS_CLOCK_ENABLE(clk) \
-	setbits_le32(SYS_CRG_BASE + clk, CLK_ENABLE_MASK)
-
-static void sys_reset_clear(ulong assert, ulong status, u32 rst)
-{
-	volatile u32 value;
-
-	clrbits_le32(SYS_CRG_BASE + assert, BIT(rst));
-	do{
-		value = in_le32(SYS_CRG_BASE + status);
-	}while((value & BIT(rst)) != BIT(rst));
-}
-
-static void jh7110_timer_init(void)
-{
-	SYS_CLOCK_ENABLE(TIMER_CLK_APB_SHIFT);
-	SYS_CLOCK_ENABLE(TIMER_CLK_TIMER0_SHIFT);
-	SYS_CLOCK_ENABLE(TIMER_CLK_TIMER1_SHIFT);
-	SYS_CLOCK_ENABLE(TIMER_CLK_TIMER2_SHIFT);
-	SYS_CLOCK_ENABLE(TIMER_CLK_TIMER3_SHIFT);
-
-	sys_reset_clear(SYS_CRG_RESET_ASSERT3_SHIFT,
-			SYS_CRG_RESET_STATUS3_SHIFT, TIMER_RSTN_APB_SHIFT);
-	sys_reset_clear(SYS_CRG_RESET_ASSERT3_SHIFT,
-			SYS_CRG_RESET_STATUS3_SHIFT, TIMER_RSTN_TIMER0_SHIFT);
-	sys_reset_clear(SYS_CRG_RESET_ASSERT3_SHIFT,
-			SYS_CRG_RESET_STATUS3_SHIFT, TIMER_RSTN_TIMER1_SHIFT);
-	sys_reset_clear(SYS_CRG_RESET_ASSERT3_SHIFT,
-			SYS_CRG_RESET_STATUS3_SHIFT, TIMER_RSTN_TIMER2_SHIFT);
-	sys_reset_clear(SYS_CRG_RESET_ASSERT3_SHIFT,
-			SYS_CRG_RESET_STATUS3_SHIFT, TIMER_RSTN_TIMER3_SHIFT);
-}
-
-static void jh7110_gmac_init(int id)
-{
-	switch (id) {
-	case 0:
-		clrsetbits_le32(AON_SYSCON_BASE + AON_SYSCFG_12,
-			GMAC5_0_SEL_I_MASK,
-			BIT(GMAC5_0_SEL_I_SHIFT) & GMAC5_0_SEL_I_MASK);
-		break;
-
-	case 1:
-		clrsetbits_le32(SYS_SYSCON_BASE + SYS_SYSCON_144,
-			GMAC5_1_SEL_I_MASK,
-			BIT(GMAC5_1_SEL_I_SHIFT) & GMAC5_1_SEL_I_MASK);
-		break;
-
-	default:
-		break;
-	}
-}
-
-static void jh7110_usb_init(void)
-{
-	clrsetbits_le32(STG_SYSCON_BASE  + STG_SYSCON_4,
-		USB_MODE_STRAP_MASK,
-		(2<<USB_MODE_STRAP_SHIFT) & USB_MODE_STRAP_MASK);
-	clrsetbits_le32(STG_SYSCON_BASE + STG_SYSCON_4,
-		USB_OTG_SUSPENDM_BYPS_MASK,
-		BIT(USB_OTG_SUSPENDM_BYPS_SHIFT)
-		& USB_OTG_SUSPENDM_BYPS_MASK);
-
-	clrsetbits_le32(STG_SYSCON_BASE + STG_SYSCON_4,
-		USB_OTG_SUSPENDM_MASK,
-		BIT(USB_OTG_SUSPENDM_SHIFT) & USB_OTG_SUSPENDM_MASK);
-	clrsetbits_le32(STG_SYSCON_BASE + STG_SYSCON_4,
-		USB_PLL_EN_MASK,
-		BIT(USB_PLL_EN_SHIFT) & USB_PLL_EN_MASK);
-	clrsetbits_le32(STG_SYSCON_BASE + STG_SYSCON_4,
-		USB_REFCLK_MODE_MASK,
-		BIT(USB_REFCLK_MODE_SHIFT) & USB_REFCLK_MODE_MASK);
-
-	clrsetbits_le32(SYS_SYSCON_BASE + SYS_SYSCON_24,
-		PDRSTN_SPLIT_MASK,
-		BIT(PDRSTN_SPLIT_SHIFT) & PDRSTN_SPLIT_MASK);
-	clrsetbits_le32(SYS_IOMUX_BASE + SYS_IOMUX_32,
-		IOMUX_USB_MASK,
-		BIT(IOMUX_USB_SHIFT) & IOMUX_USB_MASK);
-}
-
-static void jh7110_mmc_init(int id)
-{
-	if (id == 0) {
-		SYS_IOMUX_DOEN(62, LOW);
-		SYS_IOMUX_DOUT(62, 19);
-	} else {
-		SYS_IOMUX_DOEN(10, LOW);
-		SYS_IOMUX_DOUT(10, 55);
-		SYS_IOMUX_COMPLEX(9, 44, 57, 19);
-		SYS_IOMUX_COMPLEX(11, 45, 58, 20);
-		SYS_IOMUX_COMPLEX(12, 46, 59, 21);
-		SYS_IOMUX_COMPLEX(7, 47, 60, 22);
-		SYS_IOMUX_COMPLEX(8, 48, 61, 23);
-	}
-}
-
-/*enable U74-mc hart1~hart4 prefetcher*/
-static void enable_prefetcher(void)
-{
-	u32 hart;
-	u32 *reg;
-#define L2_PREFETCHER_BASE_ADDR	0x2030000
-#define L2_PREFETCHER_OFFSET	0x2000
-
-	/*hart1~hart4*/
-	for (hart = 1; hart < 5; hart++) {
-		reg = (u32 *)((u64)(L2_PREFETCHER_BASE_ADDR
-			+ hart*L2_PREFETCHER_OFFSET));
-
-		mb(); /* memory barrier */
-		setbits_le32(reg, 0x1);
-		mb(); /* memory barrier */
-	}
-}
-
-int board_init(void)
-{
-	enable_caches();
-
-	/*enable hart1-hart4 prefetcher*/
-//	enable_prefetcher();
-
-	jh7110_gmac_init(0);
-	jh7110_gmac_init(1);
-	jh7110_timer_init();
-
-	jh7110_usb_init();
-
-	jh7110_mmc_init(0);
-	jh7110_mmc_init(1);
-
-	return 0;
-}
-
-#ifdef CONFIG_MISC_INIT_R
-
-int misc_init_r(void)
-{
-	char mac[6] = {0x66, 0x34, 0xb0, 0x6c, 0xde, 0xad };
-
-#if CONFIG_IS_ENABLED(STARFIVE_OTP)
-	struct udevice *dev;
-	char buf[8];
-	int ret;
-#define MACADDR_OFFSET 0x8
-
-	ret = uclass_get_device_by_driver(UCLASS_MISC,
-				DM_DRIVER_GET(starfive_otp), &dev);
-	if (ret) {
-		debug("%s: could not find otp device\n", __func__);
-		goto err;
-	}
-
-	ret = misc_read(dev, MACADDR_OFFSET, buf, sizeof(buf));
-	if (ret != sizeof(buf))
-		printf("%s: error reading mac from OTP\n", __func__);
-	else
-		if (buf[0] != 0xff)
-			memcpy(mac, buf, 6);
-err:
-#endif
-	eth_env_set_enetaddr("ethaddr", mac);
-
-	return 0;
-}
-#endif
-

+ 52 - 0
board/starfive/visionfive2/Kconfig

@@ -0,0 +1,52 @@
+if TARGET_STARFIVE_VISIONFIVE2
+
+config SYS_CPU
+	default "jh7110"
+
+config SYS_BOARD
+	default "visionfive2"
+
+config SYS_VENDOR
+	default "starfive"
+
+config SYS_CONFIG_NAME
+	default "starfive-visionfive2"
+
+config ENV_SIZE
+	default 0x2000 if ENV_IS_IN_SPI_FLASH
+
+config ENV_OFFSET
+	default 0x140000 if ENV_IS_IN_SPI_FLASH
+
+config SYS_TEXT_BASE
+	default 0x40200000 if SPL
+	default 0x40000000 if !RISCV_SMODE
+	default 0x40200000 if RISCV_SMODE
+
+config SPL_TEXT_BASE
+	default 0x08000000
+
+config SPL_OPENSBI_LOAD_ADDR
+	default 0x80000000
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+	def_bool y
+	select STARFIVE_JH7110
+	imply CMD_DHCP
+	imply CMD_EXT2
+	imply CMD_EXT4
+	imply CMD_FAT
+	imply CMD_FS_GENERIC
+	imply CMD_GPT
+	imply PARTITION_TYPE_GUID
+	imply CMD_NET
+	imply CMD_PING
+	imply CMD_SF
+	imply DOS_PARTITION
+	imply EFI_PARTITION
+	imply IP_DYN
+	imply ISO_PARTITION
+	imply PHY_LIB
+	imply PHY_MSCC
+
+endif

+ 7 - 0
board/starfive/visionfive2/MAINTAINERS

@@ -0,0 +1,7 @@
+STARFIVE JH7110 VISIONFIVE2 BOARD
+M:	Yanhong Wang <yanhong.wang@starfivetech.com>
+S:	Maintained
+F:	arch/riscv/include/asm/arch-jh7110/
+F:	board/starfive/visionfive2/
+F:	include/configs/starfive-visionfive2.h
+F:	configs/starfive_visionfive2_defconfig

+ 2 - 2
board/starfive/visionfive/Makefile → board/starfive/visionfive2/Makefile

@@ -3,7 +3,7 @@
 # Copyright (C) 2022-2023 StarFive Technology Co., Ltd.
 #
 
-obj-y	:= starfive_visionfive.o
+obj-y	:= starfive_visionfive2.o
 
 obj-$(CONFIG_SPL_BUILD) += spl.o
-
+obj-$(CONFIG_ID_EEPROM) += visionfive2-i2c-eeprom.o

+ 189 - 0
board/starfive/visionfive2/spl.c

@@ -0,0 +1,189 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022 Starfive, Inc.
+ * Author:	yanhong <yanhong.wang@starfivetech.com>
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <asm/arch/spl.h>
+#include <asm/io.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/jh7110-regs.h>
+#include <asm/arch/clk.h>
+#include <image.h>
+#include <log.h>
+#include <spl.h>
+
+#define MODE_SELECT_REG		0x1702002c
+
+int spl_board_init_f(void)
+{
+	int ret;
+
+	ret = spl_soc_init();
+	if (ret) {
+		debug("JH7110 SPL init failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+u32 spl_boot_device(void)
+{
+	int boot_mode = 0;
+
+	boot_mode = readl((const volatile void *)MODE_SELECT_REG) & 0x3;
+	switch (boot_mode) {
+	case 0:
+		return BOOT_DEVICE_SPI;
+	case 1:
+		return BOOT_DEVICE_MMC2;
+	case 2:
+		return BOOT_DEVICE_MMC1;
+	case 3:
+		return BOOT_DEVICE_UART;
+	default:
+		debug("Unsupported boot device 0x%x.\n",
+		      boot_mode);
+		return BOOT_DEVICE_NONE;
+	}
+}
+
+struct image_header *spl_get_load_buffer(ssize_t offset, size_t size)
+{
+	return (struct image_header *)(STARFIVE_SPL_BOOT_LOAD_ADDR);
+}
+
+void board_init_f(ulong dummy)
+{
+	int ret;
+
+	/* Set pll0 cpufreq to 1000M */
+	starfive_jh7110_pll_set_rate(PLL0, 1000000000);
+
+	/*change pll2 to 1188MHz*/
+	starfive_jh7110_pll_set_rate(PLL2, 1188000000);
+
+	/*DDR control depend clk init*/
+	clrsetbits_le32(SYS_CRG_BASE, CLK_CPU_ROOT_SW_MASK,
+		BIT(CLK_CPU_ROOT_SW_SHIFT) & CLK_CPU_ROOT_SW_MASK);
+
+	clrsetbits_le32(SYS_CRG_BASE + CLK_BUS_ROOT_OFFSET,
+		CLK_BUS_ROOT_SW_MASK,
+		BIT(CLK_BUS_ROOT_SW_SHIFT) & CLK_BUS_ROOT_SW_MASK);
+
+	/*Set clk_perh_root clk default mux sel to pll2*/
+	clrsetbits_le32(SYS_CRG_BASE + CLK_PERH_ROOT_OFFSET,
+		CLK_PERH_ROOT_MASK,
+		BIT(CLK_PERH_ROOT_SHIFT) & CLK_PERH_ROOT_MASK);
+
+	clrsetbits_le32(SYS_CRG_BASE + CLK_NOC_BUS_STG_AXI_OFFSET,
+		CLK_NOC_BUS_STG_AXI_EN_MASK,
+		BIT(CLK_NOC_BUS_STG_AXI_EN_SHIFT)
+		& CLK_NOC_BUS_STG_AXI_EN_MASK);
+
+	clrsetbits_le32(AON_CRG_BASE + CLK_AON_APB_FUNC_OFFSET,
+		CLK_AON_APB_FUNC_SW_MASK,
+		BIT(CLK_AON_APB_FUNC_SW_SHIFT) & CLK_AON_APB_FUNC_SW_MASK);
+
+	clrsetbits_le32(SYS_CRG_BASE + CLK_QSPI_REF_OFFSET,
+		CLK_QSPI_REF_SW_MASK,
+		(1 << CLK_QSPI_REF_SW_SHIFT) & CLK_QSPI_REF_SW_MASK);
+
+	/* Improved GMAC0 TX I/O PAD capability */
+	clrsetbits_le32(AON_IOMUX_BASE + 0x78, 0x3, BIT(0) & 0x3);
+	clrsetbits_le32(AON_IOMUX_BASE + 0x7c, 0x3, BIT(0) & 0x3);
+	clrsetbits_le32(AON_IOMUX_BASE + 0x80, 0x3, BIT(0) & 0x3);
+	clrsetbits_le32(AON_IOMUX_BASE + 0x84, 0x3, BIT(0) & 0x3);
+	clrsetbits_le32(AON_IOMUX_BASE + 0x88, 0x3, BIT(0) & 0x3);
+
+	/* Improved GMAC1 TX I/O PAD capability */
+	clrsetbits_le32(SYS_IOMUX_BASE + 0x26c, 0x3, BIT(0) & 0x3);
+	clrsetbits_le32(SYS_IOMUX_BASE + 0x270, 0x3, BIT(0) & 0x3);
+	clrsetbits_le32(SYS_IOMUX_BASE + 0x274, 0x3, BIT(0) & 0x3);
+	clrsetbits_le32(SYS_IOMUX_BASE + 0x278, 0x3, BIT(0) & 0x3);
+	clrsetbits_le32(SYS_IOMUX_BASE + 0x27c, 0x3, BIT(0) & 0x3);
+
+	/*set GPIO to 3.3v*/
+	setbits_le32(SYS_SYSCON_BASE + 0xC, 0x0);
+
+	/*uart0 tx*/
+	SYS_IOMUX_DOEN(5, LOW);
+	SYS_IOMUX_DOUT(5, 20);
+	/*uart0 rx*/
+	SYS_IOMUX_DOEN(6, HIGH);
+	SYS_IOMUX_DIN(6, 14);
+
+	/*jtag*/
+	SYS_IOMUX_DOEN(36, HIGH);
+	SYS_IOMUX_DIN(36, 4);
+	SYS_IOMUX_DOEN(61, HIGH);
+	SYS_IOMUX_DIN(61, 19);
+	SYS_IOMUX_DOEN(63, HIGH);
+	SYS_IOMUX_DIN(63, 20);
+	SYS_IOMUX_DOEN(60, HIGH);
+	SYS_IOMUX_DIN(60, 29);
+	SYS_IOMUX_DOEN(44, 8);
+	SYS_IOMUX_DOUT(44, 22);
+
+	/* reset emmc */
+	SYS_IOMUX_DOEN(62, LOW);
+	SYS_IOMUX_DOUT(62, 19);
+	SYS_IOMUX_SET_DS(64, 2);
+	SYS_IOMUX_SET_SLEW(64, 1);
+	SYS_IOMUX_SET_DS(65, 1);
+	SYS_IOMUX_SET_DS(66, 1);
+	SYS_IOMUX_SET_DS(67, 1);
+	SYS_IOMUX_SET_DS(68, 1);
+	SYS_IOMUX_SET_DS(69, 1);
+	SYS_IOMUX_SET_DS(70, 1);
+	SYS_IOMUX_SET_DS(71, 1);
+	SYS_IOMUX_SET_DS(72, 1);
+	SYS_IOMUX_SET_DS(73, 1);
+	/* reset sdio */
+	SYS_IOMUX_DOEN(10, LOW);
+	SYS_IOMUX_DOUT(10, 55);
+	SYS_IOMUX_SET_DS(10, 2);
+	SYS_IOMUX_SET_SLEW(10, 1);
+	SYS_IOMUX_COMPLEX(9, 44, 57, 19);
+	SYS_IOMUX_SET_DS(9, 1);
+	SYS_IOMUX_COMPLEX(11, 45, 58, 20);
+	SYS_IOMUX_SET_DS(11, 1);
+	SYS_IOMUX_COMPLEX(12, 46, 59, 21);
+	SYS_IOMUX_SET_DS(12, 1);
+	SYS_IOMUX_COMPLEX(7, 47, 60, 22);
+	SYS_IOMUX_SET_DS(7, 1);
+	SYS_IOMUX_COMPLEX(8, 48, 61, 23);
+	SYS_IOMUX_SET_DS(8, 1);
+
+	/*i2c5*/
+	SYS_IOMUX_COMPLEX(19, 79, 0, 42);//scl
+	SYS_IOMUX_COMPLEX(20, 80, 0, 43);//sda
+
+	ret = spl_early_init();
+	if (ret)
+		panic("spl_early_init() failed: %d\n", ret);
+
+	arch_cpu_init_dm();
+
+	preloader_console_init();
+
+	ret = spl_board_init_f();
+	if (ret) {
+		debug("spl_board_init_f init failed: %d\n", ret);
+		return;
+	}
+}
+
+#ifdef CONFIG_SPL_LOAD_FIT
+int board_fit_config_name_match(const char *name)
+{
+	/* boot using first FIT config */
+	return 0;
+}
+#endif
+
+

+ 547 - 0
board/starfive/visionfive2/starfive_visionfive2.c

@@ -0,0 +1,547 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022 Starfive, Inc.
+ * Author:	yanhong <yanhong.wang@starfivetech.com>
+ *
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/eeprom.h>
+#include <asm/arch/jh7110-regs.h>
+#include <cpu_func.h>
+#include <dm/uclass.h>
+#include <dm/device.h>
+#include <env.h>
+#include <inttypes.h>
+#include <misc.h>
+#include <linux/bitops.h>
+#include <asm/arch/gpio.h>
+#include <bmp_logo.h>
+#include <video.h>
+#include <splash.h>
+
+#define SYS_CLOCK_ENABLE(clk) \
+	setbits_le32(SYS_CRG_BASE + clk, CLK_ENABLE_MASK)
+
+#define PCB_REVISION_MASK	0xF0
+#define PCB_REVISION_SHIFT	4
+#define PCB_REVISION_A		0x0A
+#define PCB_REVISION_B		0x0B
+#define CHIP_REVISION_SHIFT	80
+
+#define CPU_VOL_BINNING_OFFSET 0x7fc
+
+enum {
+	BOOT_FLASH =	0,
+	BOOT_SD,
+	BOOT_EMMC,
+	BOOT_UART,
+};
+
+enum chip_type_t {
+	CHIP_A = 0,
+	CHIP_B,
+	CHIP_MAX,
+};
+
+enum board_type_t {
+	BOARD_1000M_1000M = 0,
+	BOARD_1000M_100M,
+	BOARD_TYPE_MAX,
+};
+
+
+enum cpu_voltage_type_t {
+	CPU_VOL_1020 = 0xef0,
+	CPU_VOL_1040 = 0xfff,
+	CPU_VOL_1060 = 0xff0,
+	CPU_VOL_1000  = 0x8f0,
+};
+#define CPU_VOL_MASK	0xfff
+
+static void sys_reset_clear(ulong assert, ulong status, u32 rst)
+{
+	u32 value;
+
+	clrbits_le32(SYS_CRG_BASE + assert, BIT(rst));
+	do {
+		value = in_le32(SYS_CRG_BASE + status);
+	} while ((value & BIT(rst)) != BIT(rst));
+}
+
+static void jh7110_timer_init(void)
+{
+	SYS_CLOCK_ENABLE(TIMER_CLK_APB_SHIFT);
+	SYS_CLOCK_ENABLE(TIMER_CLK_TIMER0_SHIFT);
+	SYS_CLOCK_ENABLE(TIMER_CLK_TIMER1_SHIFT);
+	SYS_CLOCK_ENABLE(TIMER_CLK_TIMER2_SHIFT);
+	SYS_CLOCK_ENABLE(TIMER_CLK_TIMER3_SHIFT);
+
+	sys_reset_clear(SYS_CRG_RESET_ASSERT3_SHIFT,
+			SYS_CRG_RESET_STATUS3_SHIFT, TIMER_RSTN_APB_SHIFT);
+	sys_reset_clear(SYS_CRG_RESET_ASSERT3_SHIFT,
+			SYS_CRG_RESET_STATUS3_SHIFT, TIMER_RSTN_TIMER0_SHIFT);
+	sys_reset_clear(SYS_CRG_RESET_ASSERT3_SHIFT,
+			SYS_CRG_RESET_STATUS3_SHIFT, TIMER_RSTN_TIMER1_SHIFT);
+	sys_reset_clear(SYS_CRG_RESET_ASSERT3_SHIFT,
+			SYS_CRG_RESET_STATUS3_SHIFT, TIMER_RSTN_TIMER2_SHIFT);
+	sys_reset_clear(SYS_CRG_RESET_ASSERT3_SHIFT,
+			SYS_CRG_RESET_STATUS3_SHIFT, TIMER_RSTN_TIMER3_SHIFT);
+}
+
+static void jh7110_gmac_init_1000M(int id)
+{
+	switch (id) {
+	case 0:
+		clrsetbits_le32(AON_SYSCON_BASE + AON_SYSCFG_12,
+			GMAC5_0_SEL_I_MASK,
+			BIT(GMAC5_0_SEL_I_SHIFT) & GMAC5_0_SEL_I_MASK);
+		break;
+
+	case 1:
+		clrsetbits_le32(SYS_SYSCON_BASE + SYS_SYSCON_144,
+			GMAC5_1_SEL_I_MASK,
+			BIT(GMAC5_1_SEL_I_SHIFT) & GMAC5_1_SEL_I_MASK);
+		break;
+
+	default:
+		break;
+	}
+}
+
+static void jh7110_gmac_init_100M(int id)
+{
+	switch (id) {
+	case 0:
+		clrsetbits_le32(AON_SYSCON_BASE + AON_SYSCFG_12,
+			GMAC5_0_SEL_I_MASK,
+			(4 << GMAC5_0_SEL_I_SHIFT) & GMAC5_0_SEL_I_MASK);
+		setbits_le32(AON_CRG_BASE + GMAC5_0_CLK_TX_SHIFT, 0x1000000);
+		setbits_le32(AON_CRG_BASE + GMAC5_0_CLK_RX_SHIFT, 0x1000000);
+		break;
+
+	case 1:
+		clrsetbits_le32(SYS_SYSCON_BASE + SYS_SYSCON_144,
+			GMAC5_1_SEL_I_MASK,
+			(4 << GMAC5_1_SEL_I_SHIFT) & GMAC5_1_SEL_I_MASK);
+		setbits_le32(SYS_CRG_BASE + GMAC5_1_CLK_TX_SHIFT, 0x1000000);
+		setbits_le32(SYS_CRG_BASE + GMAC5_1_CLK_RX_SHIFT, 0x1000000);
+		break;
+
+	default:
+		break;
+	}
+}
+
+static void jh7110_gmac_sel_tx_to_rgmii(int id)
+{
+	switch (id) {
+	case 0:
+		clrsetbits_le32(AON_CRG_BASE + GMAC5_0_CLK_TX_SHIFT,
+			GMAC5_0_CLK_TX_MASK,
+			BIT(GMAC5_0_CLK_TX_BIT) & GMAC5_0_CLK_TX_MASK);
+		break;
+
+	case 1:
+		clrsetbits_le32(SYS_CRG_BASE + GMAC5_1_CLK_TX_SHIFT,
+			GMAC5_1_CLK_TX_MASK,
+			BIT(GMAC5_1_CLK_TX_BIT) & GMAC5_1_CLK_TX_MASK);
+		break;
+
+	default:
+		break;
+	}
+}
+
+static void set_uboot_fdt_addr_env(void)
+{
+	char str[17];
+	ulong fdt_addr = (ulong)gd->fdt_blob;
+
+	sprintf(str, "0x%lx", fdt_addr);
+	env_set("uboot_fdt_addr", str);
+}
+
+static int get_chip_type(void)
+{
+	int type;
+	int len = -1;
+	u8 data;
+
+	len = get_data_from_eeprom(CHIP_REVISION_SHIFT, 1, &data);
+	if (len <= 0) {
+		env_set("chip_vision", "UNKOWN");
+		return -EINVAL;
+	}
+
+	switch (data) {
+	case 'a':
+	case 'A':
+		type = CHIP_A;
+		env_set("chip_vision", "A");
+		break;
+	case 'b':
+	case 'B':
+		type = CHIP_B;
+		env_set("chip_vision", "B");
+		break;
+	default:
+		type = CHIP_MAX;
+		env_set("chip_vision", "UNKOWN");
+		break;
+	}
+	return type;
+}
+static int get_board_type(void)
+{
+	u8 pv;
+	int type;
+
+	pv = get_pcb_revision_from_eeprom();
+	pv = (pv & PCB_REVISION_MASK) >> PCB_REVISION_SHIFT;
+
+	if (pv == PCB_REVISION_A) {
+		type = BOARD_1000M_100M;
+	} else if (pv == PCB_REVISION_B) {
+		type = BOARD_1000M_1000M;
+	} else {
+		type = BOARD_TYPE_MAX;
+	}
+
+	return type;
+}
+
+static void jh7110_gmac_init(int chip_type, int pcb_type)
+{
+	switch (chip_type) {
+		case CHIP_A:
+			break;
+		case CHIP_B:
+		default:
+			jh7110_gmac_sel_tx_to_rgmii(0);
+			jh7110_gmac_sel_tx_to_rgmii(1);
+			break;
+	}
+
+	switch (pcb_type) {
+		case BOARD_1000M_100M:
+			jh7110_gmac_init_1000M(0);
+			jh7110_gmac_init_100M(1);
+			break;
+
+		case BOARD_1000M_1000M:
+		default:
+			jh7110_gmac_init_1000M(0);
+			jh7110_gmac_init_1000M(1);
+			break;
+	}
+}
+
+static void jh7110_usb_init(bool usb2_enable)
+{
+	if (usb2_enable) {
+		/*usb 2.0 utmi phy init*/
+		clrsetbits_le32(STG_SYSCON_BASE  + STG_SYSCON_4,
+			USB_MODE_STRAP_MASK,
+			(2<<USB_MODE_STRAP_SHIFT) &
+			USB_MODE_STRAP_MASK);/*2:host mode, 4:device mode*/
+		clrsetbits_le32(STG_SYSCON_BASE + STG_SYSCON_4,
+			USB_OTG_SUSPENDM_BYPS_MASK,
+			BIT(USB_OTG_SUSPENDM_BYPS_SHIFT)
+			& USB_OTG_SUSPENDM_BYPS_MASK);
+		clrsetbits_le32(STG_SYSCON_BASE + STG_SYSCON_4,
+			USB_OTG_SUSPENDM_MASK,
+			BIT(USB_OTG_SUSPENDM_SHIFT) &
+			USB_OTG_SUSPENDM_MASK);/*HOST = 1. DEVICE = 0;*/
+		clrsetbits_le32(STG_SYSCON_BASE + STG_SYSCON_4,
+			USB_PLL_EN_MASK,
+			BIT(USB_PLL_EN_SHIFT) & USB_PLL_EN_MASK);
+		clrsetbits_le32(STG_SYSCON_BASE + STG_SYSCON_4,
+			USB_REFCLK_MODE_MASK,
+			BIT(USB_REFCLK_MODE_SHIFT) & USB_REFCLK_MODE_MASK);
+		/* usb 2.0 phy mode,REPLACE USB3.0 PHY module = 1;else = 0*/
+		clrsetbits_le32(SYS_SYSCON_BASE + SYS_SYSCON_24,
+			PDRSTN_SPLIT_MASK,
+			BIT(PDRSTN_SPLIT_SHIFT) &
+			PDRSTN_SPLIT_MASK);
+	} else {
+		/*usb 3.0 pipe phy config*/
+		clrsetbits_le32(STG_SYSCON_BASE  + STG_SYSCON_196,
+			PCIE_CKREF_SRC_MASK,
+			(0<<PCIE_CKREF_SRC_SHIFT) & PCIE_CKREF_SRC_MASK);
+		clrsetbits_le32(STG_SYSCON_BASE  + STG_SYSCON_196,
+			PCIE_CLK_SEL_MASK,
+			(0<<PCIE_CLK_SEL_SHIFT) & PCIE_CLK_SEL_MASK);
+		clrsetbits_le32(STG_SYSCON_BASE  + STG_SYSCON_328,
+			PCIE_PHY_MODE_MASK,
+			BIT(PCIE_PHY_MODE_SHIFT) & PCIE_PHY_MODE_MASK);
+		clrsetbits_le32(STG_SYSCON_BASE  + STG_SYSCON_500,
+			PCIE_USB3_BUS_WIDTH_MASK,
+			(0 << PCIE_USB3_BUS_WIDTH_SHIFT) &
+			PCIE_USB3_BUS_WIDTH_MASK);
+		clrsetbits_le32(STG_SYSCON_BASE  + STG_SYSCON_500,
+			PCIE_USB3_RATE_MASK,
+			(0 << PCIE_USB3_RATE_SHIFT) & PCIE_USB3_RATE_MASK);
+		clrsetbits_le32(STG_SYSCON_BASE  + STG_SYSCON_500,
+			PCIE_USB3_RX_STANDBY_MASK,
+			(0 << PCIE_USB3_RX_STANDBY_SHIFT)
+			& PCIE_USB3_RX_STANDBY_MASK);
+		clrsetbits_le32(STG_SYSCON_BASE  + STG_SYSCON_500,
+			PCIE_USB3_PHY_ENABLE_MASK,
+			BIT(PCIE_USB3_PHY_ENABLE_SHIFT)
+			& PCIE_USB3_PHY_ENABLE_MASK);
+
+		/* usb 3.0 phy mode,REPLACE USB3.0 PHY module = 1;else = 0*/
+		clrsetbits_le32(SYS_SYSCON_BASE + SYS_SYSCON_24,
+			PDRSTN_SPLIT_MASK,
+			(0 << PDRSTN_SPLIT_SHIFT) & PDRSTN_SPLIT_MASK);
+	}
+	SYS_IOMUX_DOEN(25, LOW);
+	SYS_IOMUX_DOUT(25, 7);
+}
+
+#if CONFIG_IS_ENABLED(STARFIVE_OTP)
+static void get_cpu_voltage_type(struct udevice *dev)
+{
+	int ret;
+	u32 buf = CPU_VOL_1040;
+
+	ret = misc_read(dev, CPU_VOL_BINNING_OFFSET, &buf, sizeof(buf));
+	if (ret != sizeof(buf))
+		printf("%s: error reading CPU vol from OTP\n", __func__);
+	else {
+		switch ((buf & CPU_VOL_MASK)) {
+		case CPU_VOL_1000:
+			env_set("cpu_max_vol", "1000000");
+			break;
+		case CPU_VOL_1060:
+			env_set("cpu_max_vol", "1060000");
+			break;
+		case CPU_VOL_1020:
+			env_set("cpu_max_vol", "1020000");
+			break;
+		default:
+			env_set("cpu_max_vol", "1040000");
+			break;
+		}
+	}
+}
+#endif
+
+static void jh7110_jtag_init(void)
+{
+	/*jtag*/
+	SYS_IOMUX_DOEN(36, HIGH);
+	SYS_IOMUX_DIN(36, 4);
+	SYS_IOMUX_DOEN(61, HIGH);
+	SYS_IOMUX_DIN(61, 19);
+	SYS_IOMUX_DOEN(63, HIGH);
+	SYS_IOMUX_DIN(63, 20);
+	SYS_IOMUX_DOEN(60, HIGH);
+	SYS_IOMUX_DIN(60, 29);
+	SYS_IOMUX_DOEN(44, 8);
+	SYS_IOMUX_DOUT(44, 22);
+}
+
+static void jh7110_i2c_init(int id)
+{
+	switch (id) {
+	case 5:
+		//scl
+		SYS_IOMUX_COMPLEX(19, 79, 0, 42);
+		//sda
+		SYS_IOMUX_COMPLEX(20, 80, 0, 43);
+
+		break;
+
+	default:
+		break;
+	}
+}
+
+static void get_boot_mode(void)
+{
+	u32 value;
+
+	value = in_le32(AON_IOMUX_BASE + AON_GPIO_DIN_REG);
+	switch (value & 0x03) {
+		case BOOT_FLASH:
+			env_set("bootmode", "flash");
+			env_set("devnum", "1");
+			break;
+
+		case BOOT_SD:
+			env_set("bootmode", "sd");
+			env_set("devnum", "1");
+			break;
+
+		case BOOT_EMMC:
+			env_set("bootmode", "emmc");
+			env_set("devnum", "0");
+			break;
+
+		default:
+			env_set("bootmode", "uart");
+			env_set("devnum", "1");
+			break;
+	}
+}
+
+static void jh7110_gpio_init(void)
+{
+	/* This is for fixing don't detect wm8960 occasionally.
+	 * Set scl/sda gpio output enable
+	 * Set drive strength to 12mA
+	 * Set gpio pull up
+	 */
+	SYS_IOMUX_COMPLEX(57, 9, 0, 1);
+	SYS_IOMUX_SET_DS(57, 3);
+	SYS_IOMUX_SET_PULL(57, GPIO_PULL_UP);
+
+	SYS_IOMUX_COMPLEX(58, 10, 0, 1);
+	SYS_IOMUX_SET_DS(58, 3);
+	SYS_IOMUX_SET_PULL(58, GPIO_PULL_UP);
+}
+
+int board_init(void)
+{
+	enable_caches();
+
+	jh7110_jtag_init();
+	jh7110_timer_init();
+
+	jh7110_usb_init(true);
+
+	jh7110_i2c_init(5);
+	jh7110_gpio_init();
+
+	return 0;
+}
+
+#ifdef CONFIG_BOARD_LATE_INIT
+int board_late_init(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	get_boot_mode();
+
+	jh7110_gmac_init(get_chip_type(), get_board_type());
+	/*
+	 * save the memory info by environment variable in u-boot,
+	 * It will used to update the memory configuration in dts,
+	 * which passed to kernel lately.
+	 */
+	env_set_hex("memory_addr", gd->ram_base);
+	env_set_hex("memory_size", gd->ram_size);
+
+	ret = uclass_get_device(UCLASS_VIDEO, 0, &dev);
+	if (ret)
+		return ret;
+
+	ret = video_bmp_display(dev, (ulong)&bmp_logo_bitmap[0], BMP_ALIGN_CENTER, BMP_ALIGN_CENTER, true);
+	if (ret)
+		goto err;
+
+err:
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_MISC_INIT_R
+
+int misc_init_r(void)
+{
+	char mac0[6] = {0x6c, 0xcf, 0x39, 0x6c, 0xde, 0xad};
+	char mac1[6] = {0x6c, 0xcf, 0x39, 0x7c, 0xae, 0x5d};
+
+#if CONFIG_IS_ENABLED(STARFIVE_OTP)
+	struct udevice *dev;
+	char buf[16];
+	int ret;
+#define MACADDR_OFFSET 0x8
+
+	ret = uclass_get_device_by_driver(UCLASS_MISC,
+				DM_DRIVER_GET(starfive_otp), &dev);
+	if (ret) {
+		debug("%s: could not find otp device\n", __func__);
+		goto err;
+	}
+
+	ret = misc_read(dev, MACADDR_OFFSET, buf, sizeof(buf));
+	if (ret != sizeof(buf))
+		printf("%s: error reading mac from OTP\n", __func__);
+	else
+		if (buf[0] != 0xff) {
+			memcpy(mac0, buf, 6);
+			memcpy(mac1, &buf[8], 6);
+		}
+err:
+#endif
+	eth_env_set_enetaddr("eth0addr", mac0);
+	eth_env_set_enetaddr("eth1addr", mac1);
+
+	get_chip_type();
+	set_uboot_fdt_addr_env();
+#if CONFIG_IS_ENABLED(STARFIVE_OTP)
+	get_cpu_voltage_type(dev);
+#endif
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_ID_EEPROM
+
+#include <asm/arch/eeprom.h>
+#define STARFIVE_JH7110_EEPROM_DDRINFO_OFFSET	91
+
+static bool check_eeprom_dram_info(ulong size)
+{
+	switch (size) {
+	case 1:
+	case 2:
+	case 4:
+	case 8:
+	case 16:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static int resize_ddr_from_eeprom(void)
+{
+	struct udevice *dev;
+	ulong size;
+	u32 len = 1;
+	u8 data = 0;
+	int ret;
+
+	/* I2C init */
+	ret = uclass_get_device(UCLASS_I2C, 0, &dev);
+	if (ret) {
+		debug("I2C init failed: %d\n", ret);
+		return 0;
+	}
+
+	/* read memory size info */
+	ret = get_data_from_eeprom(STARFIVE_JH7110_EEPROM_DDRINFO_OFFSET, len, &data);
+	if (ret == len) {
+		size = hextoul(&data, NULL);
+		if (check_eeprom_dram_info(size))
+			return size;
+	}
+	return 0;
+}
+#else
+static int resize_ddr_from_eeprom(void)
+{
+	return 0;
+}
+#endif /* CONFIG_ID_EEPROM */
+
+int board_ddr_size(void)
+{
+	return resize_ddr_from_eeprom();
+}

+ 832 - 0
board/starfive/visionfive2/visionfive2-i2c-eeprom.c

@@ -0,0 +1,832 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved.
+ * Written by Wei Fu (wefu@redhat.com)
+ */
+ 
+
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <i2c.h>
+#include <init.h>
+#include <linux/ctype.h>
+#include <linux/delay.h>
+
+#define CONFIG_SYS_EEPROM_BUS_NUM		0
+
+#define FORMAT_VERSION				0x2
+#define PCB_VERSION				0xB1
+#define BOM_VERSION				'A'
+/*
+ * BYTES_PER_EEPROM_PAGE: the 24FC04H datasheet says that data can
+ * only be written in page mode, which means 16 bytes at a time:
+ * 16-Byte Page Write Buffer
+ */
+#define BYTES_PER_EEPROM_PAGE			16
+
+/*
+ * EEPROM_WRITE_DELAY_MS: the 24FC04H datasheet says it takes up to
+ * 5ms to complete a given write:
+ * Write Cycle Time (byte or page) ro Page Write Time 5 ms, Maximum
+ */
+#define EEPROM_WRITE_DELAY_MS			5000
+/*
+ * StarFive OUI. Registration Date is 20xx-xx-xx
+ */
+#define STARFIVE_OUI_PREFIX			"6C:CF:39:"
+#define STARFIVE_DEFAULT_MAC0			{0x6c, 0xcf, 0x39, 0x6c, 0xde, 0xad}
+#define STARFIVE_DEFAULT_MAC1			{0x6c, 0xcf, 0x39, 0x7c, 0xae, 0x5d}
+
+/* Magic number at the first four bytes of EEPROM HATs */
+#define STARFIVE_EEPROM_HATS_SIG	"SFVF" /* StarFive VisionFive */
+
+#define STARFIVE_EEPROM_HATS_SIZE_MAX	256 /* Header + Atom1&4(v1) */
+#define STARFIVE_EEPROM_WP_OFFSET	0 /* Read only field */
+#define STARFIVE_EEPROM_ATOM1_PSTR	"VF7110A1-2228-D008E000-00000001\0"
+#define STARFIVE_EEPROM_ATOM1_PSTR_SIZE	32
+#define STARFIVE_EEPROM_ATOM1_SN_OFFSET	23
+#define STARFIVE_EEPROM_ATOM1_VSTR	"StarFive Technology Co., Ltd.\0\0\0"
+#define STARFIVE_EEPROM_ATOM1_VSTR_SIZE	32
+
+/*
+ * MAGIC_NUMBER_BYTES: number of bytes used by the magic number
+ */
+#define MAGIC_NUMBER_BYTES			4
+
+/*
+ * MAC_ADDR_BYTES: number of bytes used by the Ethernet MAC address
+ */
+#define MAC_ADDR_BYTES				6
+
+/*
+ * MAC_ADDR_STRLEN: length of mac address string
+ */
+#define MAC_ADDR_STRLEN				17
+
+/*
+ * Atom Types
+ * 0x0000 = invalid
+ * 0x0001 = vendor info
+ * 0x0002 = GPIO map
+ * 0x0003 = Linux device tree blob
+ * 0x0004 = manufacturer custom data
+ * 0x0005-0xfffe = reserved for future use
+ * 0xffff = invalid
+ */
+
+#define HATS_ATOM_INVALID	0x0000
+#define HATS_ATOM_VENDOR	0x0001
+#define HATS_ATOM_GPIO		0x0002
+#define HATS_ATOM_DTB		0x0003
+#define HATS_ATOM_CUSTOM	0x0004
+#define HATS_ATOM_INVALID_END	0xffff
+
+struct eeprom_hats_header {
+	char signature[MAGIC_NUMBER_BYTES];	/* ASCII table signature */
+	u8 version;		/* EEPROM data format version */
+				/* (0x00 reserved, 0x01 = first version) */
+	u8 reversed;		/* 0x00, Reserved field */
+	u16 numatoms;		/* total atoms in EEPROM */
+	u32 eeplen;		/* total length in bytes of all eeprom data */
+				/* (including this header) */
+};
+
+struct eeprom_hats_atom_header {
+	u16 type;
+	u16 count;
+	u32 dlen;
+};
+
+/**
+ * static eeprom: EEPROM layout for the StarFive platform I2C format
+ */
+struct starfive_eeprom_atom1_data {
+	u8 uuid[16];
+	u16 pid;
+	u16 pver;
+	u8 vslen;
+	u8 pslen;
+	uchar vstr[STARFIVE_EEPROM_ATOM1_VSTR_SIZE];
+	uchar pstr[STARFIVE_EEPROM_ATOM1_PSTR_SIZE]; /* product SN */
+};
+
+struct starfive_eeprom_atom1 {
+	struct eeprom_hats_atom_header header;
+	struct starfive_eeprom_atom1_data data;
+	u16 crc16;
+};
+
+struct starfive_eeprom_atom4_v1_data {
+	u16 version;
+	u8 pcb_revision;		/* PCB version */
+	u8 bom_revision;		/* BOM version */
+	u8 mac0_addr[MAC_ADDR_BYTES];	/* Ethernet0 MAC */
+	u8 mac1_addr[MAC_ADDR_BYTES];	/* Ethernet1 MAC */
+	u8 reserved[2];
+};
+
+struct starfive_eeprom_atom4_v1 {
+	struct eeprom_hats_atom_header header;
+	struct starfive_eeprom_atom4_v1_data data;
+	u16 crc16;
+};
+
+/* Set to 1 if we've read EEPROM into memory
+ * Set to -1 if EEPROM data is wrong
+ */
+static int has_been_read;
+
+/**
+ * helper struct for getting info from the local EEPROM copy.
+ * most of the items are pointers to the eeprom_wp_buff.
+ * ONLY serialnum is the u32 from the last 8 Bytes of product string
+ */
+struct starfive_eeprom_info {
+	char *vstr;		/* Vendor string in ATOM1 */
+	char *pstr;		/* product string in ATOM1 */
+	u32 serialnum;		/* serial number from in product string*/
+	u16 *version;		/* custom data version in ATOM4 */
+	u8 *pcb_revision;	/* PCB version in ATOM4 */
+	u8 *bom_revision;	/* BOM version in ATOM4 */
+	u8 *mac0_addr;		/* Ethernet0 MAC in ATOM4 */
+	u8 *mac1_addr;		/* Ethernet1 MAC in ATOM4 */
+};
+static struct starfive_eeprom_info einfo;
+
+
+static uchar eeprom_wp_buff[STARFIVE_EEPROM_HATS_SIZE_MAX];
+static struct eeprom_hats_header starfive_eeprom_hats_header_default = {
+	.signature = STARFIVE_EEPROM_HATS_SIG,
+	.version = FORMAT_VERSION,
+	.numatoms = 2,
+	.eeplen = sizeof(struct eeprom_hats_header) +
+		  sizeof(struct starfive_eeprom_atom1) +
+		  sizeof(struct starfive_eeprom_atom4_v1)
+};
+static struct starfive_eeprom_atom1 starfive_eeprom_atom1_default = {
+	.header = {
+		.type = HATS_ATOM_VENDOR,
+		.count = 1,
+		.dlen = sizeof(struct starfive_eeprom_atom1_data) + sizeof(u16)
+	},
+	.data = {
+		.uuid = {0},
+		.pid = 0,
+		.pver = 0,
+		.vslen = STARFIVE_EEPROM_ATOM1_VSTR_SIZE,
+		.pslen = STARFIVE_EEPROM_ATOM1_PSTR_SIZE,
+		.vstr = STARFIVE_EEPROM_ATOM1_VSTR,
+		.pstr = STARFIVE_EEPROM_ATOM1_PSTR
+	}
+};
+static struct starfive_eeprom_atom4_v1 starfive_eeprom_atom4_v1_default = {
+	.header = {
+		.type = HATS_ATOM_CUSTOM,
+		.count = 2,
+		.dlen = sizeof(struct starfive_eeprom_atom4_v1_data) + sizeof(u16)
+	},
+	.data = {
+		.version = FORMAT_VERSION,
+		.pcb_revision = PCB_VERSION,
+		.bom_revision = BOM_VERSION,
+		.mac0_addr = STARFIVE_DEFAULT_MAC0,
+		.mac1_addr = STARFIVE_DEFAULT_MAC1,
+		.reserved = {0}
+	}
+};
+
+//static u8 starfive_default_mac[MAC_ADDR_BYTES] = STARFIVE_DEFAULT_MAC;
+
+/**
+ * is_match_magic() - Does the magic number match that of a StarFive EEPROM?
+ *
+ * @hats:		the pointer of eeprom_hats_header
+ * Return:		status code, 0: Yes, non-0: NO
+ */
+static inline int is_match_magic(char *hats)
+{
+	return strncmp(hats, STARFIVE_EEPROM_HATS_SIG, MAGIC_NUMBER_BYTES);
+}
+
+/**
+ * calculate_crc16() - Calculate the current CRC for atom
+ * Porting from  https://github.com/raspberrypi/hats, getcrc
+ * @data:		the pointer of eeprom_hats_atom_header
+ * @size:		total length in bytes of the entire atom
+ * 			(type, count, dlen, data)
+ * Return:		result: crc16 code
+ */
+#define CRC16 0x8005
+static u16 calculate_crc16(uchar* data, unsigned int size)
+{
+	int i, j = 0x0001;
+	u16 out = 0, crc = 0;
+	int bits_read = 0, bit_flag;
+
+	/* Sanity check: */
+	if((data == NULL) || size == 0)
+		return 0;
+
+	while(size > 0) {
+		bit_flag = out >> 15;
+
+		/* Get next bit: */
+		out <<= 1;
+		// item a) work from the least significant bits
+		out |= (*data >> bits_read) & 1;
+
+		/* Increment bit counter: */
+		bits_read++;
+		if(bits_read > 7) {
+			bits_read = 0;
+			data++;
+			size--;
+		}
+
+		/* Cycle check: */
+		if(bit_flag)
+			out ^= CRC16;
+	}
+
+	// item b) "push out" the last 16 bits
+	for (i = 0; i < 16; ++i) {
+		bit_flag = out >> 15;
+		out <<= 1;
+		if(bit_flag)
+			out ^= CRC16;
+	}
+
+	// item c) reverse the bits
+	for (i = 0x8000; i != 0; i >>=1, j <<= 1) {
+		if (i & out)
+			crc |= j;
+	}
+
+	return crc;
+}
+
+/* This function should be called after each update to any EEPROM ATOM */
+static inline void update_crc(struct eeprom_hats_atom_header *atom)
+{
+	uint atom_crc_offset = sizeof(struct eeprom_hats_atom_header) +
+			       atom->dlen - sizeof(u16);
+	u16 *atom_crc_p = (void *) atom + atom_crc_offset;
+	*atom_crc_p = calculate_crc16((uchar*) atom, atom_crc_offset);
+}
+
+/**
+ * dump_raw_eeprom - display the raw contents of the EEPROM
+ */
+static void dump_raw_eeprom(u8 *e, unsigned int size)
+{
+	unsigned int i;
+
+	printf("EEPROM dump: (0x%x bytes)\n", size);
+
+	for (i = 0; i < size; i++) {
+		if (!(i % 0x10))
+			printf("%02X: ", i);
+
+		printf("%02X ", e[i]);
+
+		if (((i % 16) == 15) || (i == size - 1))
+			printf("\n");
+	}
+
+	return;
+}
+
+static int hats_atom_crc_check(struct eeprom_hats_atom_header *atom)
+{
+	u16 atom_crc, data_crc;
+	uint atom_crc_offset = sizeof(struct eeprom_hats_atom_header) +
+			       atom->dlen - sizeof(atom_crc);
+	u16 *atom_crc_p = (void *) atom + atom_crc_offset;
+
+	atom_crc = *atom_crc_p;
+	data_crc = calculate_crc16((uchar *) atom, atom_crc_offset);
+	if (atom_crc == data_crc)
+		return 0;
+
+	printf("EEPROM HATs: CRC ERROR in atom %x type %x, (%x!=%x)\n",
+		atom->count, atom->type, atom_crc, data_crc);
+	return -1;
+}
+
+static void *hats_get_atom(struct eeprom_hats_header *header, u16 type)
+ {
+	struct eeprom_hats_atom_header *atom;
+	void *hats_eeprom_max = (void *)header + header->eeplen;
+	void *temp = (void *)header + sizeof(struct eeprom_hats_header);
+
+	for (int numatoms = (int)header->numatoms; numatoms > 0; numatoms--) {
+		atom = (struct eeprom_hats_atom_header *)temp;
+		if (hats_atom_crc_check(atom))
+			return NULL;
+		if (atom->type == type)
+			return (void *)atom;
+		/* go to next atom */
+		temp = (void *)atom + sizeof(struct eeprom_hats_atom_header) +
+		       atom->dlen;
+		if (temp > hats_eeprom_max) {
+			printf("EEPROM HATs: table overflow next@%p, max@%p\n",
+				temp, hats_eeprom_max);
+			break;
+		}
+	}
+
+	/* fail to get atom */
+	return NULL;
+}
+
+/**
+ * show_eeprom - display the contents of the EEPROM
+ */
+static void show_eeprom(struct starfive_eeprom_info *einfo)
+{
+	if (has_been_read != 1)
+		return;
+
+	printf("\n--------EEPROM INFO--------\n");
+	printf("Vendor : %s\n", einfo->vstr);
+	printf("Product full SN: %s\n", einfo->pstr);
+	printf("data version: 0x%x\n", *einfo->version);
+	if (2 == *einfo->version) {
+		printf("PCB revision: 0x%x\n", *einfo->pcb_revision);
+		printf("BOM revision: %c\n", *einfo->bom_revision);
+		printf("Ethernet MAC0 address: %02x:%02x:%02x:%02x:%02x:%02x\n",
+		       einfo->mac0_addr[0], einfo->mac0_addr[1],
+		       einfo->mac0_addr[2], einfo->mac0_addr[3],
+		       einfo->mac0_addr[4], einfo->mac0_addr[5]);
+		printf("Ethernet MAC1 address: %02x:%02x:%02x:%02x:%02x:%02x\n",
+		       einfo->mac1_addr[0], einfo->mac1_addr[1],
+		       einfo->mac1_addr[2], einfo->mac1_addr[3],
+		       einfo->mac1_addr[4], einfo->mac1_addr[5]);
+	} else {
+		printf("Custom data v%d is not Supported\n", *einfo->version);
+	}
+	printf("--------EEPROM INFO--------\n\n");
+}
+
+/**
+ * parse_eeprom_info - parse the contents of the EEPROM
+ * If everthing gose right,
+ * 1, set has_been_read to 1
+ * 2, display info
+ *
+ * If anything goes wrong,
+ * 1, set has_been_read to -1
+ * 2, dump data by hex for debug
+ *
+ * @buf:		the pointer of eeprom_hats_header in memory
+ * Return:		status code, 0: Success, non-0: Fail
+ *
+ */
+static int parse_eeprom_info(struct eeprom_hats_header *buf)
+{
+	struct eeprom_hats_atom_header *atom;
+	void *atom_data;
+	struct starfive_eeprom_atom1_data *atom1 = NULL;
+	struct starfive_eeprom_atom4_v1_data *atom4_v1 = NULL;
+
+	if (is_match_magic((char *)buf)) {
+		printf("Not a StarFive EEPROM data format - magic error\n");
+		goto error;
+	};
+
+	// parse atom1(verdor)
+	atom = (struct eeprom_hats_atom_header *)
+		hats_get_atom(buf, HATS_ATOM_VENDOR);
+	if (atom) {
+		atom_data = (void *)atom +
+			    sizeof(struct eeprom_hats_atom_header);
+		atom1 = (struct starfive_eeprom_atom1_data *)atom_data;
+		einfo.vstr = atom1->vstr;
+		einfo.pstr = atom1->pstr;
+		einfo.serialnum = (u32)hextoul((void *)atom1->pstr +
+					STARFIVE_EEPROM_ATOM1_SN_OFFSET,
+					NULL);
+	} else  {
+		printf("fail to get vendor atom\n");
+		goto error;
+	};
+
+	// parse atom4(custom)
+	atom = (struct eeprom_hats_atom_header *)
+		hats_get_atom(buf, HATS_ATOM_CUSTOM);
+	if (atom) {
+		atom_data = (void *)atom +
+			    sizeof(struct eeprom_hats_atom_header);
+		atom4_v1 = (struct starfive_eeprom_atom4_v1_data *)atom_data;
+		einfo.version = &atom4_v1->version;
+		if (*einfo.version == 2) {
+			einfo.pcb_revision = &atom4_v1->pcb_revision;
+			einfo.bom_revision = &atom4_v1->bom_revision;
+			einfo.mac0_addr =  atom4_v1->mac0_addr;
+			einfo.mac1_addr =  atom4_v1->mac1_addr;
+		}
+	} else  {
+		printf("fail to get custom data atom\n");
+		goto error;
+	};
+
+	// everthing gose right
+	has_been_read = 1;
+
+	return 0;
+
+error:
+	has_been_read = -1;
+	return -1;
+}
+
+/**
+ * read_eeprom() - read the EEPROM into memory, if it hasn't been read yet
+ * @buf:		the pointer of eeprom data buff
+ * Return:		status code, 0: Success, non-0: Fail
+ * Note: depend on	CONFIG_SYS_EEPROM_BUS_NUM
+ * 			CONFIG_SYS_I2C_EEPROM_ADDR
+ * 			STARFIVE_EEPROM_WP_OFFSET
+ * 			STARFIVE_EEPROM_HATS_SIZE_MAX
+ */
+static int read_eeprom(uint8_t *buf)
+{
+	int ret;
+	struct udevice *dev;
+
+	if (has_been_read == 1)
+		return 0;
+
+	ret = i2c_get_chip_for_busnum(CONFIG_SYS_EEPROM_BUS_NUM,
+				      CONFIG_SYS_I2C_EEPROM_ADDR,
+				      CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
+				      &dev);
+	if (!ret) {
+		ret = dm_i2c_read(dev, STARFIVE_EEPROM_WP_OFFSET,
+				  buf, STARFIVE_EEPROM_HATS_SIZE_MAX);
+	}
+
+	if (ret) {
+		printf("fail to read EEPROM.\n");
+		return ret;
+	}
+
+	return parse_eeprom_info((struct eeprom_hats_header *)buf);
+}
+
+/**
+ * prog_eeprom() - write the EEPROM from memory
+ */
+static int prog_eeprom(uint8_t *buf, unsigned int size)
+{
+	unsigned int i;
+	void *p;
+	uchar tmp_buff[STARFIVE_EEPROM_HATS_SIZE_MAX];
+	struct udevice *dev;
+	int ret = i2c_get_chip_for_busnum(CONFIG_SYS_EEPROM_BUS_NUM,
+					  CONFIG_SYS_I2C_EEPROM_ADDR,
+					  CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
+					  &dev);
+
+	if (is_match_magic(buf)) {
+		printf("MAGIC ERROR, Please check the data@%p.\n", buf);
+		return -1;
+	}
+
+	for (i = 0, p = buf; i < size;
+	     i += BYTES_PER_EEPROM_PAGE, p += BYTES_PER_EEPROM_PAGE) {
+		if (!ret)
+			ret = dm_i2c_write(dev,
+					   i + STARFIVE_EEPROM_WP_OFFSET,
+					   p, min((int)(size - i),
+					   BYTES_PER_EEPROM_PAGE));
+		if (ret)
+			break;
+		udelay(EEPROM_WRITE_DELAY_MS);
+	}
+
+	if (!ret) {
+		/* Verify the write by reading back the EEPROM and comparing */
+		ret = dm_i2c_read(dev,
+				  STARFIVE_EEPROM_WP_OFFSET,
+				  tmp_buff,
+				  STARFIVE_EEPROM_HATS_SIZE_MAX);
+		if (!ret && memcmp((void *)buf, (void *)tmp_buff,
+				   STARFIVE_EEPROM_HATS_SIZE_MAX))
+			ret = -1;
+	}
+
+	if (ret) {
+		has_been_read = -1;
+		printf("Programming failed.Temp buff:\n");
+		dump_raw_eeprom(tmp_buff,
+				STARFIVE_EEPROM_HATS_SIZE_MAX);
+		return -1;
+	}
+
+	printf("Programming passed.\n");
+	return 0;
+}
+
+/**
+ * set_mac_address() - stores a MAC address into the local EEPROM copy
+ *
+ * This function takes a pointer to MAC address string
+ * (i.e."XX:XX:XX:XX:XX:XX", where "XX" is a two-digit hex number),
+ * stores it in the MAC address field of the EEPROM local copy, and
+ * updates the local copy of the CRC.
+ */
+static void set_mac_address(char *string, int index)
+{
+	unsigned int i;
+	struct eeprom_hats_atom_header *atom4;
+	atom4 = (struct eeprom_hats_atom_header *)
+		hats_get_atom((struct eeprom_hats_header *)eeprom_wp_buff,
+			      HATS_ATOM_CUSTOM);
+
+	if (strncasecmp(STARFIVE_OUI_PREFIX, string,
+			strlen(STARFIVE_OUI_PREFIX))) {
+		printf("The MAC address doesn't match StarFive OUI %s\n",
+		       STARFIVE_OUI_PREFIX);
+		return;
+	}
+
+	for (i = 0; *string && (i < MAC_ADDR_BYTES); i++) {
+		if (index == 0) {
+			einfo.mac0_addr[i] = hextoul(string, &string);
+		} else {
+			einfo.mac1_addr[i] = hextoul(string, &string);
+		}
+		if (*string == ':')
+			string++;
+	}
+
+	update_crc(atom4);
+}
+
+/**
+ * set_pcb_revision() - stores a StarFive PCB revision into the local EEPROM copy
+ *
+ * Takes a pointer to a string representing the numeric PCB revision in
+ * decimal ("0" - "255"), stores it in the pcb_revision field of the
+ * EEPROM local copy, and updates the CRC of the local copy.
+ */
+static void set_pcb_revision(char *string)
+{
+	u8 p;
+	uint base = 16;
+	struct eeprom_hats_atom_header *atom4;
+	atom4 = (struct eeprom_hats_atom_header *)
+		hats_get_atom((struct eeprom_hats_header *)eeprom_wp_buff,
+			      HATS_ATOM_CUSTOM);
+
+	p = (u8)simple_strtoul(string, NULL, base);
+	if (p > U8_MAX) {
+		printf("%s must not be greater than %d\n", "PCB revision",
+		       U8_MAX);
+		return;
+	}
+
+	*einfo.pcb_revision = p;
+
+	update_crc(atom4);
+}
+
+/**
+ * set_bom_revision() - stores a StarFive BOM revision into the local EEPROM copy
+ *
+ * Takes a pointer to a uppercase ASCII character representing the BOM
+ * revision ("A" - "Z"), stores it in the bom_revision field of the
+ * EEPROM local copy, and updates the CRC of the local copy.
+ */
+static void set_bom_revision(char *string)
+{
+	struct eeprom_hats_atom_header *atom4;
+	atom4 = (struct eeprom_hats_atom_header *)
+		hats_get_atom((struct eeprom_hats_header *)eeprom_wp_buff,
+			      HATS_ATOM_CUSTOM);
+
+	if (string[0] < 'A' || string[0] > 'Z') {
+		printf("BOM revision must be an uppercase letter between A and Z\n");
+		return;
+	}
+
+	*einfo.bom_revision = string[0];
+
+	update_crc(atom4);
+}
+
+/**
+ * set_product_id() - stores a StarFive product ID into the local EEPROM copy
+ *
+ * Takes a pointer to a string representing the numeric product ID  in
+ * string ("VF7100A1-2150-D008E000-00000001\0"), stores it in the product string
+ * field of the EEPROM local copy, and updates the CRC of the local copy.
+ */
+static void set_product_id(char *string)
+{
+	struct eeprom_hats_atom_header *atom1;
+	atom1 = (struct eeprom_hats_atom_header *)
+		hats_get_atom((struct eeprom_hats_header *)eeprom_wp_buff,
+			      HATS_ATOM_VENDOR);
+
+	memcpy((void *)einfo.pstr, (void *)string,
+		STARFIVE_EEPROM_ATOM1_PSTR_SIZE);
+
+	update_crc(atom1);
+}
+
+/**
+ * init_local_copy() - initialize the in-memory EEPROM copy
+ *
+ * Initialize the in-memory EEPROM copy with the magic number.  Must
+ * be done when preparing to initialize a blank EEPROM, or overwrite
+ * one with a corrupted magic number.
+ */
+static void init_local_copy(uchar *buff)
+{
+	struct eeprom_hats_header *hats = (struct eeprom_hats_header *)buff;
+	struct eeprom_hats_atom_header *atom1 = (void *)hats +
+					sizeof(struct eeprom_hats_header);
+	struct eeprom_hats_atom_header *atom4_v1 = (void *)atom1 +
+					sizeof(struct starfive_eeprom_atom1);
+
+	memcpy((void *)hats, (void *)&starfive_eeprom_hats_header_default,
+	       sizeof(struct eeprom_hats_header));
+	memcpy((void *)atom1, (void *)&starfive_eeprom_atom1_default,
+	       sizeof(struct starfive_eeprom_atom1));
+	memcpy((void *)atom4_v1, (void *)&starfive_eeprom_atom4_v1_default,
+	       sizeof(struct starfive_eeprom_atom4_v1));
+
+	update_crc(atom1);
+	update_crc(atom4_v1);
+}
+
+static int print_usage(void)
+{
+	printf("display and program the system ID and MAC addresses in EEPROM\n"
+	"[read_eeprom|initialize|write_eeprom|mac_address|pcb_revision|bom_revision|product_id]\n"
+	"mac read_eeprom\n"
+	"    - read EEPROM content into memory data structure\n"
+	"mac write_eeprom\n"
+	"    - save memory data structure to the EEPROM\n"
+	"mac initialize\n"
+	"    - initialize the in-memory EEPROM copy with default data\n"
+	"mac mac0_address <xx:xx:xx:xx:xx:xx>\n"
+	"    - stores a MAC0 address into the local EEPROM copy\n"
+	"mac mac1_address <xx:xx:xx:xx:xx:xx>\n"
+	"    - stores a MAC1 address into the local EEPROM copy\n"
+	"mac pcb_revision <?>\n"
+	"    - stores a StarFive PCB revision into the local EEPROM copy\n"
+	"mac bom_revision <A>\n"
+	"    - stores a StarFive BOM revision into the local EEPROM copy\n"
+	"mac product_id <VF7110A1-2228-D008E000-xxxxxxxx>\n"
+	"    - stores a StarFive product ID into the local EEPROM copy\n");
+	return 0;
+}
+
+int do_mac(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	char *cmd;
+
+	if (argc == 1) {
+		show_eeprom(&einfo);
+		return 0;
+	}
+
+	if (argc > 3)
+		return print_usage();
+
+	cmd = argv[1];
+
+	/* Commands with no argument */
+	if (!strcmp(cmd, "read_eeprom")) {
+		has_been_read = 0;
+		return read_eeprom(eeprom_wp_buff);
+	} else if (!strcmp(cmd, "initialize")) {
+		init_local_copy(eeprom_wp_buff);
+		return 0;
+	} else if (!strcmp(cmd, "write_eeprom")) {
+		return prog_eeprom(eeprom_wp_buff,
+				   STARFIVE_EEPROM_HATS_SIZE_MAX);
+	}
+
+	if (argc != 3)
+		return print_usage();
+
+	if (is_match_magic(eeprom_wp_buff)) {
+		printf("Please read the EEPROM ('read_eeprom') and/or initialize the EEPROM ('initialize') first.\n");
+		return 0;
+	}
+
+	if (!strcmp(cmd, "mac0_address")) {
+		set_mac_address(argv[2], 0);
+		return 0;
+	} else if (!strcmp(cmd, "mac1_address")) {
+		set_mac_address(argv[2], 1);
+		return 0;
+	} else if (!strcmp(cmd, "pcb_revision")) {
+		set_pcb_revision(argv[2]);
+		return 0;
+	} else if (!strcmp(cmd, "bom_revision")) {
+		set_bom_revision(argv[2]);
+		return 0;
+	} else if (!strcmp(cmd, "product_id")) {
+		set_product_id(argv[2]);
+		return 0;
+	}
+
+	return print_usage();
+}
+
+/**
+ * mac_read_from_eeprom() - read the MAC address & the serial number in EEPROM
+ *
+ * This function reads the MAC address and the serial number from EEPROM and
+ * sets the appropriate environment variables for each one read.
+ *
+ * The environment variables are only set if they haven't been set already.
+ * This ensures that any user-saved variables are never overwritten.
+ *
+ * If CONFIG_ID_EEPROM is enabled, this function will be called in
+ * "static init_fnc_t init_sequence_r[]" of u-boot/common/board_r.c.
+ */
+int mac_read_from_eeprom(void)
+{
+	/**
+	 * try to fill the buff from EEPROM,
+	 * always return SUCCESS, even some error happens.
+	 */
+	if (read_eeprom(eeprom_wp_buff)) {
+		dump_raw_eeprom(eeprom_wp_buff, STARFIVE_EEPROM_HATS_SIZE_MAX);
+		return 0;
+	}
+
+	// 1, setup ethaddr env
+	eth_env_set_enetaddr("eth0addr", einfo.mac0_addr);
+	eth_env_set_enetaddr("eth1addr", einfo.mac1_addr);
+
+	/**
+	 * 2, setup serial# env, reference to hifive-platform-i2c-eeprom.c,
+	 * serial# can be a ASCII string, but not just a hex number, so we
+	 * setup serial# in the 32Byte format:
+	 * "VF7100A1-2201-D008E000-00000001;"
+	 * "<product>-<date>-<DDR&eMMC>-<serial_number>"
+	 * <date>: 4Byte, should be the output of `date +%y%W`
+	 * <DDR&eMMC>: 8Byte, "D008" means 8GB, "D01T" means 1TB;
+	 *     "E000" means no eMMC,"E032" means 32GB, "E01T" means 1TB.
+	 * <serial_number>: 8Byte, the Unique Identifier of board in hex.
+	 */
+	if (!env_get("serial#"))
+		env_set("serial#", einfo.pstr);
+
+	printf("StarFive EEPROM format v%u\n", *einfo.version);
+	show_eeprom(&einfo);
+	return 0;
+}
+
+/**
+ * get_pcb_revision_from_eeprom - get the PCB revision
+ *
+ * Read the EEPROM to determine the board revision.
+ */
+u8 get_pcb_revision_from_eeprom(void)
+{
+	u8 pv = 0xFF;
+
+	if (read_eeprom(eeprom_wp_buff))
+		return pv;
+
+	if (einfo.pcb_revision) {
+		pv = *einfo.pcb_revision;
+	}
+	return pv;
+}
+
+/**
+ * get_data_from_eeprom
+ *
+ * Read data from eeprom, must use int mac_read_from_eeprom(void) first
+ *
+ * offset: offset of eeprom
+ * len: count of data
+ * data: return data
+ *
+ * return the len of valid data
+ */
+int get_data_from_eeprom(int offset, int len, unsigned char *data)
+{
+	int cp_len = -1;
+
+	if (read_eeprom(eeprom_wp_buff))
+		return cp_len;
+
+	if (offset < STARFIVE_EEPROM_HATS_SIZE_MAX) {
+		cp_len = (offset + len > STARFIVE_EEPROM_HATS_SIZE_MAX) ?
+			(offset + len - STARFIVE_EEPROM_HATS_SIZE_MAX) : len;
+		memcpy(data, &eeprom_wp_buff[offset], cp_len);
+	}
+
+	return cp_len;
+}

+ 31 - 0
cmd/Kconfig

@@ -614,6 +614,37 @@ config EEPROM_LAYOUT_HELP_STRING
 	    Help printed with the LAYOUT VERSIONS part of the 'eeprom'
 	    command's help.
 
+config SYS_I2C_EEPROM_BUS
+	int "I2C bus of the EEPROM device."
+	depends on CMD_EEPROM
+	default 0
+
+config SYS_I2C_EEPROM_ADDR_LEN
+	int "Length in bytes of the EEPROM memory array address"
+	depends on CMD_EEPROM || ID_EEPROM
+	default 1
+	range 1 2
+	help
+	  Note: This is NOT the chip address length!
+
+config SYS_EEPROM_SIZE
+	depends on CMD_EEPROM
+	int "Size in bytes of the EEPROM device"
+	default 256
+
+config SYS_EEPROM_PAGE_WRITE_BITS
+	int "Number of bits used to address bytes in a single page"
+	depends on CMD_EEPROM
+	default 8
+	help
+	  The EEPROM page size is 2^SYS_EEPROM_PAGE_WRITE_BITS.
+	  A 64 byte page, for example would require six bits.
+
+config SYS_EEPROM_PAGE_WRITE_DELAY_MS
+	int "Number of milliseconds to delay between page writes"
+	depends on CMD_EEPROM || CMD_I2C
+	default 0
+
 config LOOPW
 	bool "loopw"
 	help

+ 14 - 29
cmd/eeprom.c

@@ -15,7 +15,7 @@
  * degradation (typical for EEPROM) is incured for FRAM memory:
  *
  * #define CONFIG_SYS_I2C_FRAM
- * #undef CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS
+ * Set CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS to 0
  *
  */
 
@@ -31,14 +31,6 @@
 #define	CONFIG_SYS_I2C_SPEED	50000
 #endif
 
-#ifndef CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS
-#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS	0
-#endif
-
-#ifndef CONFIG_SYS_EEPROM_PAGE_WRITE_BITS
-#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS	8
-#endif
-
 #ifndef	I2C_RXTX_LEN
 #define I2C_RXTX_LEN	128
 #endif
@@ -46,21 +38,6 @@
 #define	EEPROM_PAGE_SIZE	(1 << CONFIG_SYS_EEPROM_PAGE_WRITE_BITS)
 #define	EEPROM_PAGE_OFFSET(x)	((x) & (EEPROM_PAGE_SIZE - 1))
 
-/*
- * for CONFIG_SYS_I2C_EEPROM_ADDR_LEN == 2 (16-bit EEPROM address) offset is
- *   0x000nxxxx for EEPROM address selectors at n, offset xxxx in EEPROM.
- *
- * for CONFIG_SYS_I2C_EEPROM_ADDR_LEN == 1 (8-bit EEPROM page address) offset is
- *   0x00000nxx for EEPROM address selectors and page number at n.
- */
-#if !defined(CONFIG_SPI) || defined(CONFIG_ENV_EEPROM_IS_ON_I2C)
-#if !defined(CONFIG_SYS_I2C_EEPROM_ADDR_LEN) || \
-	(CONFIG_SYS_I2C_EEPROM_ADDR_LEN < 1) || \
-	(CONFIG_SYS_I2C_EEPROM_ADDR_LEN > 2)
-#error CONFIG_SYS_I2C_EEPROM_ADDR_LEN must be 1 or 2
-#endif
-#endif
-
 #if CONFIG_IS_ENABLED(DM_I2C)
 static int eeprom_i2c_bus;
 #endif
@@ -82,6 +59,13 @@ void eeprom_init(int bus)
 #endif
 }
 
+/*
+ * for CONFIG_SYS_I2C_EEPROM_ADDR_LEN == 2 (16-bit EEPROM address) offset is
+ *   0x000nxxxx for EEPROM address selectors at n, offset xxxx in EEPROM.
+ *
+ * for CONFIG_SYS_I2C_EEPROM_ADDR_LEN == 1 (8-bit EEPROM page address) offset is
+ *   0x00000nxx for EEPROM address selectors and page number at n.
+ */
 static int eeprom_addr(unsigned dev_addr, unsigned offset, uchar *addr)
 {
 	unsigned blk_off;
@@ -183,10 +167,11 @@ static int eeprom_rw(unsigned dev_addr, unsigned offset, uchar *buffer,
 		buffer += len;
 		offset += len;
 
+#if CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS > 0
 		if (!read)
 			udelay(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
 	}
-
+#endif
 	return rcode;
 }
 
@@ -218,10 +203,10 @@ int eeprom_write(unsigned dev_addr, unsigned offset,
 	return ret;
 }
 
-static int parse_numeric_param(char *str)
+static long parse_numeric_param(char *str)
 {
 	char *endptr;
-	int value = simple_strtol(str, &endptr, 16);
+	long value = simple_strtol(str, &endptr, 16);
 
 	return (*endptr != '\0') ? -1 : value;
 }
@@ -243,10 +228,10 @@ static int parse_i2c_bus_addr(int *i2c_bus, ulong *i2c_addr, int argc,
 	int argc_no_bus = argc_no_bus_addr + 1;
 	int argc_bus_addr = argc_no_bus_addr + 2;
 
-#ifdef CONFIG_SYS_DEF_EEPROM_ADDR
+#ifdef CONFIG_SYS_I2C_EEPROM_ADDR
 	if (argc == argc_no_bus_addr) {
 		*i2c_bus = -1;
-		*i2c_addr = CONFIG_SYS_DEF_EEPROM_ADDR;
+		*i2c_addr = CONFIG_SYS_I2C_EEPROM_ADDR;
 
 		return 0;
 	}

+ 1 - 1
cmd/i2c.c

@@ -922,7 +922,7 @@ static int mod_i2c_mem(struct cmd_tbl *cmdtp, int incrflag, int flag, int argc,
 				if (ret)
 					return i2c_report_err(ret,
 							      I2C_ERR_WRITE);
-#ifdef CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS
+#if CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS > 0
 				udelay(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
 #endif
 				if (incrflag)

+ 3 - 0
common/board_r.c

@@ -689,6 +689,9 @@ static init_fnc_t init_sequence_r[] = {
 #endif
 #ifdef CONFIG_ARCH_EARLY_INIT_R
 	arch_early_init_r,
+#endif
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_DEVKITS)
+	set_pmic,
 #endif
 	power_init_board,
 #ifdef CONFIG_MTD_NOR_FLASH

+ 171 - 0
configs/starfive_devkits_defconfig

@@ -0,0 +1,171 @@
+CONFIG_RISCV=y
+CONFIG_SPL_GPIO=y
+CONFIG_SYS_MALLOC_F_LEN=0x10000
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_ENV_SIZE=0x10000
+CONFIG_ENV_OFFSET=0xF0000
+CONFIG_SPL_DM_SPI=y
+CONFIG_DEFAULT_DEVICE_TREE="starfive_devkits"
+CONFIG_SPL_MMC_SUPPORT=y
+CONFIG_SPL=y
+CONFIG_SPL_SPI_FLASH_SUPPORT=y
+CONFIG_SPL_SPI_SUPPORT=y
+CONFIG_BUILD_TARGET=""
+CONFIG_TARGET_STARFIVE_DEVKITS=y
+CONFIG_SPL_OPENSBI_LOAD_ADDR=0x40000000
+CONFIG_NR_CPUS=5
+CONFIG_FPGA_GMAC_SPEED_AUTO=y
+CONFIG_STARFIVE_JH7110_L2CC_FLUSH=y
+CONFIG_ARCH_RV64I=y
+CONFIG_CMODEL_MEDANY=y
+CONFIG_RISCV_SMODE=y
+CONFIG_SHOW_REGS=y
+# CONFIG_OF_BOARD_FIXUP is not set
+# CONFIG_ANDROID_BOOT_IMAGE is not set
+CONFIG_FIT=y
+CONFIG_SUPPORT_RAW_INITRD=y
+CONFIG_QSPI_BOOT=y
+CONFIG_SD_BOOT=y
+CONFIG_SPI_BOOT=y
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="console=tty1 console=ttyS0,115200  debug rootwait  earlycon=sbi"
+CONFIG_USE_BOOTCOMMAND=y
+CONFIG_BOOTCOMMAND="run sdk_boot_env; run distro_boot_env;"
+CONFIG_USE_PREBOOT=y
+CONFIG_PREBOOT="run chipa_set_uboot"
+CONFIG_DEFAULT_FDT_FILE="starfive/jh7110-devkits.dtb"
+CONFIG_LOG_MAX_LEVEL=4
+CONFIG_SPL_LOG=y
+CONFIG_DISPLAY_CPUINFO=y
+CONFIG_DISPLAY_BOARDINFO=y
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_BOARD_LATE_INIT=y
+CONFIG_MISC_INIT_R=y
+CONFIG_SPL_SEPARATE_BSS=y
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION=y
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION=0x2
+CONFIG_SPL_DM_SPI_FLASH=y
+CONFIG_SPL_DM_RESET=y
+CONFIG_SPL_SPI_LOAD=y
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="StarFive # "
+CONFIG_CMD_CONFIG=y
+CONFIG_CMD_ERASEENV=y
+CONFIG_CMD_EEPROM=y
+CONFIG_SYS_I2C_EEPROM_BUS=5
+CONFIG_SYS_EEPROM_SIZE=512
+CONFIG_SYS_EEPROM_PAGE_WRITE_BITS=4
+CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS=5
+CONFIG_CMD_GPT_RENAME=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MISC=y
+CONFIG_CMD_PART=y
+CONFIG_CMD_PCI=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_TFTPPUT=y
+CONFIG_CMD_SYSBOOT=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FS_UUID=y
+CONFIG_CMD_LOG=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_VERSION_VARIABLE=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_SPL_CLK_COMPOSITE_CCF=y
+CONFIG_CLK_CCF=y
+CONFIG_CLK_COMPOSITE_CCF=y
+CONFIG_SPL_CLK_JH7110=y
+CONFIG_USB_FUNCTION_FASTBOOT=y
+CONFIG_FASTBOOT_BUF_ADDR=0x60000000
+CONFIG_FASTBOOT_BUF_SIZE=0x80000000
+CONFIG_FASTBOOT_USB_DEV=1
+CONFIG_FASTBOOT_FLASH=y
+CONFIG_FASTBOOT_UUU_SUPPORT=y
+CONFIG_FASTBOOT_FLASH_MMC_DEV=0
+CONFIG_FASTBOOT_MMC_BOOT_SUPPORT=y
+CONFIG_FASTBOOT_MMC_USER_SUPPORT=y
+CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
+CONFIG_FASTBOOT_STARFIVE_MAX_BLK_WRITE=8192
+# CONFIG_STARFIVE_GPIO is not set
+CONFIG_DM_PCA953X=y
+CONFIG_SYS_I2C_DW=y
+CONFIG_I2C_EEPROM=y
+CONFIG_SYS_I2C_EEPROM_ADDR=0x50
+CONFIG_MMC_HS200_SUPPORT=y
+CONFIG_SPL_MMC_HS200_SUPPORT=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_SNPS=y
+CONFIG_SF_DEFAULT_MODE=0x0
+CONFIG_SF_DEFAULT_SPEED=100000000
+CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_PHY_MARVELL=y
+CONFIG_PHY_MICREL=y
+CONFIG_PHY_MICREL_KSZ90X1=y
+# CONFIG_PHY_MSCC is not set
+CONFIG_PHY_YUTAI=y
+CONFIG_DWC_ETH_QOS=y
+CONFIG_DWC_ETH_QOS_STARFIVE=y
+CONFIG_RGMII=y
+CONFIG_RTL8169=y
+CONFIG_NVME=y
+CONFIG_PCI=y
+CONFIG_DM_PCI_COMPAT=y
+CONFIG_PCI_REGION_MULTI_ENTRY=y
+CONFIG_PINCTRL=y
+CONFIG_PINCONF=y
+CONFIG_SPL_PINCTRL=y
+CONFIG_SPL_PINCONF=y
+CONFIG_SPL_PINCTRL_STARFIVE=y
+CONFIG_SPL_PINCTRL_STARFIVE_JH7110=y
+CONFIG_PINCTRL_STARFIVE=y
+CONFIG_PINCTRL_STARFIVE_JH7110=y
+CONFIG_POWER_DOMAIN=y
+CONFIG_STARFIVE_POWER_DOMAIN=y
+CONFIG_DM_PMIC=y
+CONFIG_PMIC_STARFIVE=y
+CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_STARFIVE=y
+CONFIG_RAM=y
+CONFIG_SPL_RAM=y
+# CONFIG_RAM_SIFIVE is not set
+CONFIG_SPL_STARFIVE_DDR=y
+CONFIG_DM_RESET=y
+CONFIG_SPECIFY_CONSOLE_INDEX=y
+CONFIG_SYS_NS16550=y
+CONFIG_SPI=y
+CONFIG_CADENCE_QSPI=y
+CONFIG_SYSRESET=y
+CONFIG_SYSRESET_SBI=y
+CONFIG_USB=y
+CONFIG_DM_USB_GADGET=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_CDNS3=y
+CONFIG_USB_CDNS3_GADGET=y
+CONFIG_USB_CDNS3_HOST=y
+# CONFIG_USB_CDNS3_TI is not set
+CONFIG_USB_CDNS3_STARFIVE=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VENDOR_NUM=0x18d1
+CONFIG_USB_GADGET_PRODUCT_NUM=0x0d02
+CONFIG_DM_VIDEO=y
+CONFIG_VIDEO_PCI_DEFAULT_FB_SIZE=0x8000000
+CONFIG_VIDEO_COPY=y
+CONFIG_VIDEO_LCD_STARFIVE_SEEED=y
+CONFIG_VIDEO_SF_MIPI2EDP=y
+CONFIG_DISPLAY=y
+CONFIG_NXP_TDA19988=y
+CONFIG_VIDEO_BRIDGE=y
+CONFIG_VIDEO_STARFIVE=y
+CONFIG_DISPLAY_STARFIVE_EDP=y
+CONFIG_DISPLAY_STARFIVE_LVDS=y
+CONFIG_DISPLAY_STARFIVE_HDMI=y
+CONFIG_DISPLAY_STARFIVE_MIPI=y
+CONFIG_VIDEO_NW_MIPI_DSI=y
+CONFIG_OF_LIBFDT_OVERLAY=y
+# CONFIG_EFI_UNICODE_COLLATION_PROTOCOL2 is not set
+# CONFIG_EFI_LOAD_FILE2_INITRD is not set

+ 168 - 0
configs/starfive_visionfive2_defconfig

@@ -0,0 +1,168 @@
+CONFIG_RISCV=y
+CONFIG_SYS_MALLOC_F_LEN=0x10000
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_ENV_SIZE=0x10000
+CONFIG_ENV_OFFSET=0xF0000
+CONFIG_SPL_DM_SPI=y
+CONFIG_DEFAULT_DEVICE_TREE="starfive_visionfive2"
+CONFIG_SPL_MMC_SUPPORT=y
+CONFIG_SPL_DRIVERS_MISC=y
+CONFIG_SPL=y
+CONFIG_SPL_SPI_FLASH_SUPPORT=y
+CONFIG_SPL_SPI_SUPPORT=y
+CONFIG_BUILD_TARGET=""
+CONFIG_TARGET_STARFIVE_VISIONFIVE2=y
+CONFIG_SPL_OPENSBI_LOAD_ADDR=0x40000000
+CONFIG_NR_CPUS=5
+CONFIG_FPGA_GMAC_SPEED_AUTO=y
+CONFIG_STARFIVE_JH7110_L2CC_FLUSH=y
+CONFIG_ARCH_RV64I=y
+CONFIG_CMODEL_MEDANY=y
+CONFIG_RISCV_SMODE=y
+CONFIG_SHOW_REGS=y
+# CONFIG_ANDROID_BOOT_IMAGE is not set
+CONFIG_FIT=y
+CONFIG_SPL_FIT_SOURCE="jh7110-uboot-fit-image.its"
+CONFIG_SUPPORT_RAW_INITRD=y
+CONFIG_QSPI_BOOT=y
+CONFIG_SD_BOOT=y
+CONFIG_SPI_BOOT=y
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="console=tty1 console=ttyS0,115200  debug rootwait  earlycon=sbi"
+CONFIG_USE_BOOTCOMMAND=y
+CONFIG_BOOTCOMMAND="run sdk_boot_env; run distro_boot_env"
+CONFIG_USE_PREBOOT=y
+CONFIG_PREBOOT="run chipa_set_uboot;"
+CONFIG_DEFAULT_FDT_FILE="starfive/jh7110-visionfive-v2.dtb"
+CONFIG_LOG_MAX_LEVEL=4
+CONFIG_SPL_LOG=y
+CONFIG_DISPLAY_CPUINFO=y
+CONFIG_DISPLAY_BOARDINFO=y
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_BOARD_LATE_INIT=y
+CONFIG_MISC_INIT_R=y
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION=y
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION=0x2
+CONFIG_SPL_I2C=y
+CONFIG_SPL_DM_SPI_FLASH=y
+CONFIG_SPL_DM_RESET=y
+CONFIG_SPL_SPI_LOAD=y
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="StarFive # "
+CONFIG_CMD_CONFIG=y
+CONFIG_CMD_SBI=y
+CONFIG_CMD_ERASEENV=y
+CONFIG_CMD_NVEDIT_EFI=y
+CONFIG_CMD_EEPROM=y
+CONFIG_SYS_EEPROM_SIZE=512
+CONFIG_SYS_EEPROM_PAGE_WRITE_BITS=4
+CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS=5
+CONFIG_CMD_GPT_RENAME=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MISC=y
+CONFIG_CMD_PART=y
+CONFIG_CMD_PCI=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_TFTPPUT=y
+CONFIG_CMD_EFIDEBUG=y
+CONFIG_CMD_SYSBOOT=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FS_UUID=y
+CONFIG_CMD_LOG=y
+CONFIG_OF_EMBED=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_VERSION_VARIABLE=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_SPL_CLK_COMPOSITE_CCF=y
+CONFIG_CLK_CCF=y
+CONFIG_CLK_COMPOSITE_CCF=y
+CONFIG_SPL_CLK_JH7110=y
+CONFIG_USB_FUNCTION_FASTBOOT=y
+CONFIG_FASTBOOT_BUF_ADDR=0x60000000
+CONFIG_FASTBOOT_BUF_SIZE=0x80000000
+CONFIG_FASTBOOT_USB_DEV=1
+CONFIG_FASTBOOT_FLASH=y
+CONFIG_FASTBOOT_UUU_SUPPORT=y
+CONFIG_FASTBOOT_FLASH_MMC_DEV=0
+CONFIG_FASTBOOT_MMC_BOOT_SUPPORT=y
+CONFIG_FASTBOOT_MMC_USER_SUPPORT=y
+CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
+CONFIG_FASTBOOT_STARFIVE_MAX_BLK_WRITE=8192
+CONFIG_SYS_I2C_DW=y
+CONFIG_SPL_SYS_I2C_DW=y
+CONFIG_I2C_EEPROM=y
+CONFIG_SPL_I2C_EEPROM=y
+CONFIG_SYS_I2C_EEPROM_ADDR=0x50
+CONFIG_MMC_HS200_SUPPORT=y
+CONFIG_SPL_MMC_HS200_SUPPORT=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_SNPS=y
+CONFIG_SF_DEFAULT_MODE=0x0
+CONFIG_SF_DEFAULT_SPEED=100000000
+CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_PHY_MARVELL=y
+CONFIG_PHY_MICREL=y
+CONFIG_PHY_MICREL_KSZ90X1=y
+# CONFIG_PHY_MSCC is not set
+CONFIG_PHY_YUTAI=y
+CONFIG_DM_ETH_PHY=y
+CONFIG_DWC_ETH_QOS=y
+CONFIG_DWC_ETH_QOS_STARFIVE=y
+CONFIG_RGMII=y
+CONFIG_RTL8169=y
+CONFIG_NVME=y
+CONFIG_PCI=y
+CONFIG_DM_PCI_COMPAT=y
+CONFIG_PCI_REGION_MULTI_ENTRY=y
+CONFIG_PINCTRL=y
+CONFIG_PINCONF=y
+CONFIG_PINCTRL_STARFIVE=y
+CONFIG_PINCTRL_STARFIVE_JH7110=y
+CONFIG_POWER_DOMAIN=y
+CONFIG_STARFIVE_POWER_DOMAIN=y
+CONFIG_DM_PMIC=y
+CONFIG_PMIC_STARFIVE=y
+CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_STARFIVE=y
+CONFIG_RAM=y
+CONFIG_SPL_RAM=y
+# CONFIG_RAM_SIFIVE is not set
+CONFIG_SPL_STARFIVE_DDR=y
+CONFIG_DM_RESET=y
+CONFIG_SPECIFY_CONSOLE_INDEX=y
+CONFIG_SYS_NS16550=y
+CONFIG_SPI=y
+CONFIG_CADENCE_QSPI=y
+CONFIG_SYSRESET=y
+CONFIG_SYSRESET_SBI=y
+CONFIG_USB=y
+CONFIG_DM_USB_GADGET=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_PCI=y
+CONFIG_USB_CDNS3=y
+CONFIG_USB_CDNS3_GADGET=y
+# CONFIG_USB_CDNS3_TI is not set
+CONFIG_USB_CDNS3_STARFIVE=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VENDOR_NUM=0x18d1
+CONFIG_USB_GADGET_PRODUCT_NUM=0x0d02
+CONFIG_DM_VIDEO=y
+CONFIG_VIDEO_PCI_DEFAULT_FB_SIZE=0x8000000
+CONFIG_VIDEO_COPY=y
+CONFIG_VIDEO_LCD_STARFIVE_SEEED=y
+CONFIG_DISPLAY=y
+CONFIG_NXP_TDA19988=y
+CONFIG_VIDEO_BRIDGE=y
+CONFIG_VIDEO_STARFIVE=y
+CONFIG_DISPLAY_STARFIVE_EDP=y
+CONFIG_DISPLAY_STARFIVE_LVDS=y
+CONFIG_DISPLAY_STARFIVE_HDMI=y
+CONFIG_DISPLAY_STARFIVE_MIPI=y
+CONFIG_VIDEO_NW_MIPI_DSI=y
+CONFIG_OF_LIBFDT_OVERLAY=y

+ 0 - 75
configs/starfive_visionfive_defconfig

@@ -1,75 +0,0 @@
-CONFIG_RISCV=y
-CONFIG_SYS_MALLOC_F_LEN=0x8000
-CONFIG_NR_DRAM_BANKS=1
-CONFIG_SPL_DM_SPI=y
-CONFIG_DEFAULT_DEVICE_TREE="starfive_visionfive"
-CONFIG_SPL_MMC_SUPPORT=y
-CONFIG_SPL=y
-CONFIG_SPL_SPI_FLASH_SUPPORT=y
-CONFIG_SPL_SPI_SUPPORT=y
-CONFIG_BUILD_TARGET=""
-CONFIG_TARGET_STARFIVE_VISIONFIVE=y
-CONFIG_NR_CPUS=5
-CONFIG_ARCH_RV64I=y
-CONFIG_CMODEL_MEDANY=y
-CONFIG_RISCV_SMODE=y
-CONFIG_SHOW_REGS=y
-CONFIG_FIT=y
-CONFIG_SPL_FIT_SOURCE="jh7110-uboot-fit-image.its"
-CONFIG_SUPPORT_RAW_INITRD=y
-CONFIG_QSPI_BOOT=y
-CONFIG_SD_BOOT=y
-CONFIG_SPI_BOOT=y
-CONFIG_USE_BOOTARGS=y
-CONFIG_BOOTARGS="console=tty1 console=ttyS0,115200  debug rootwait  earlycon=sbi"
-CONFIG_USE_BOOTCOMMAND=y
-CONFIG_LOG_MAX_LEVEL=4
-CONFIG_SPL_LOG=y
-CONFIG_DISPLAY_CPUINFO=y
-CONFIG_DISPLAY_BOARDINFO=y
-CONFIG_DISPLAY_BOARDINFO_LATE=y
-CONFIG_MISC_INIT_R=y
-CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y
-CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x1800
-CONFIG_SPL_DM_SPI_FLASH=y
-CONFIG_SPL_SPI_LOAD=y
-CONFIG_HUSH_PARSER=y
-CONFIG_SYS_PROMPT="StarFive # "
-CONFIG_CMD_CONFIG=y
-CONFIG_CMD_GPT_RENAME=y
-CONFIG_CMD_MISC=y
-CONFIG_CMD_PART=y
-CONFIG_CMD_USB=y
-CONFIG_CMD_TFTPPUT=y
-CONFIG_CMD_SYSBOOT=y
-CONFIG_CMD_EXT4_WRITE=y
-CONFIG_CMD_FS_UUID=y
-CONFIG_CMD_LOG=y
-CONFIG_OF_EMBED=y
-CONFIG_VERSION_VARIABLE=y
-CONFIG_NET_RANDOM_ETHADDR=y
-CONFIG_SPL_CLK_COMPOSITE_CCF=y
-CONFIG_CLK_CCF=y
-CONFIG_CLK_COMPOSITE_CCF=y
-CONFIG_SPL_CLK_JH7110=y
-CONFIG_MMC_DW=y
-CONFIG_MMC_DW_SNPS=y
-CONFIG_SF_DEFAULT_MODE=0x0
-CONFIG_SF_DEFAULT_SPEED=50000000
-CONFIG_SPI_FLASH_GIGADEVICE=y
-CONFIG_SPI_FLASH_SPANSION=y
-CONFIG_PHY_MARVELL=y
-CONFIG_DWC_ETH_QOS=y
-CONFIG_DWC_ETH_QOS_STARFIVE=y
-CONFIG_RGMII=y
-CONFIG_DM_RESET=y
-CONFIG_SPECIFY_CONSOLE_INDEX=y
-CONFIG_SYS_NS16550=y
-CONFIG_SPI=y
-CONFIG_CADENCE_QSPI=y
-CONFIG_USB=y
-CONFIG_USB_XHCI_HCD=y
-CONFIG_USB_CDNS3=y
-CONFIG_USB_CDNS3_HOST=y
-CONFIG_USB_STORAGE=y
-CONFIG_OF_LIBFDT_OVERLAY=y

+ 52 - 18
drivers/clk/starfive/clk-jh7110.c

@@ -425,6 +425,58 @@ static int jh7110_clk_init(struct udevice *dev)
 	       starfive_clk_divider(priv->sys,
 				    "nocstg_bus", "bus_root",
 				    SYS_OFFSET(JH7110_NOCSTG_BUS), 3));
+
+	/*I2C*/
+	clk_dm(JH7110_I2C0_CLK_APB,
+	       starfive_clk_gate(priv->sys,
+				 "u0_dw_i2c_clk_apb", "apb0",
+				 SYS_OFFSET(JH7110_I2C0_CLK_APB)));
+	clk_dm(JH7110_I2C0_CLK_CORE,
+	       starfive_clk_fix_factor(priv->sys,
+				       "u0_dw_i2c_clk_core", "u0_dw_i2c_clk_apb", 1, 1));
+	clk_dm(JH7110_I2C1_CLK_APB,
+	       starfive_clk_gate(priv->sys,
+				 "u1_dw_i2c_clk_apb", "apb0",
+				 SYS_OFFSET(JH7110_I2C1_CLK_APB)));
+	clk_dm(JH7110_I2C1_CLK_CORE,
+	       starfive_clk_fix_factor(priv->sys,
+				       "u1_dw_i2c_clk_core", "u1_dw_i2c_clk_apb", 1, 1));
+	clk_dm(JH7110_I2C2_CLK_APB,
+	       starfive_clk_gate(priv->sys,
+				 "u2_dw_i2c_clk_apb", "apb0",
+				 SYS_OFFSET(JH7110_I2C2_CLK_APB)));
+	clk_dm(JH7110_I2C2_CLK_CORE,
+	       starfive_clk_fix_factor(priv->sys,
+				       "u2_dw_i2c_clk_core", "u2_dw_i2c_clk_apb", 1, 1));
+	clk_dm(JH7110_I2C3_CLK_APB,
+	       starfive_clk_gate(priv->sys,
+				 "u3_dw_i2c_clk_apb", "apb12",
+				 SYS_OFFSET(JH7110_I2C3_CLK_APB)));
+	clk_dm(JH7110_I2C3_CLK_CORE,
+	       starfive_clk_fix_factor(priv->sys,
+				       "u3_dw_i2c_clk_core", "u3_dw_i2c_clk_apb", 1, 1));
+	clk_dm(JH7110_I2C4_CLK_APB,
+	       starfive_clk_gate(priv->sys,
+				 "u4_dw_i2c_clk_apb", "apb12",
+				 SYS_OFFSET(JH7110_I2C4_CLK_APB)));
+	clk_dm(JH7110_I2C4_CLK_CORE,
+	       starfive_clk_fix_factor(priv->sys,
+				       "u4_dw_i2c_clk_core", "u4_dw_i2c_clk_apb", 1, 1));
+	clk_dm(JH7110_I2C5_CLK_APB,
+	       starfive_clk_gate(priv->sys,
+				 "u5_dw_i2c_clk_apb", "apb12",
+				 SYS_OFFSET(JH7110_I2C5_CLK_APB)));
+	clk_dm(JH7110_I2C5_CLK_CORE,
+	       starfive_clk_fix_factor(priv->sys,
+				       "u5_dw_i2c_clk_core", "u5_dw_i2c_clk_apb", 1, 1));
+	clk_dm(JH7110_I2C6_CLK_APB,
+	       starfive_clk_gate(priv->sys,
+				 "u6_dw_i2c_clk_apb", "apb12",
+				 SYS_OFFSET(JH7110_I2C6_CLK_APB)));
+	clk_dm(JH7110_I2C6_CLK_CORE,
+	       starfive_clk_fix_factor(priv->sys,
+				       "u6_dw_i2c_clk_core", "u6_dw_i2c_clk_apb", 1, 1));
+
 	/*QSPI*/
 	clk_dm(JH7110_QSPI_CLK_AHB,
 	       starfive_clk_gate(priv->sys,
@@ -699,24 +751,6 @@ static int jh7110_clk_init(struct udevice *dev)
 				    "u0_dom_vout_top_clk_mipiphy_ref", "osc",
 				    SYS_OFFSET(JH7110_MCLK_INNER), 2));
 
-	/*i2c5*/
-	clk_dm(JH7110_I2C5_CLK_APB,
-		starfive_clk_gate(priv->sys,
-			"u5_dw_i2c_clk_apb", "apb0",
-			SYS_OFFSET(JH7110_I2C5_CLK_APB)));
-	clk_dm(JH7110_I2C5_CLK_CORE,
-		starfive_clk_fix_factor(priv->sys,
-			"u5_dw_i2c_clk_core", "u5_dw_i2c_clk_apb", 1, 1));
-
-	/*i2c2*/
-	clk_dm(JH7110_I2C2_CLK_APB,
-		starfive_clk_gate(priv->sys,
-			"u2_dw_i2c_clk_apb", "apb0",
-			SYS_OFFSET(JH7110_I2C2_CLK_APB)));
-	clk_dm(JH7110_I2C2_CLK_CORE,
-		starfive_clk_fix_factor(priv->sys,
-			"u2_dw_i2c_clk_core", "u2_dw_i2c_clk_apb", 1, 1));
-
 	/*pcie0*/
 	clk_dm(JH7110_PCIE0_CLK_TL,
 		starfive_clk_gate(priv->stg,

+ 7 - 0
drivers/i2c/Kconfig

@@ -158,6 +158,13 @@ config SYS_I2C_DW
 	  controller is used in various SoCs, e.g. the ST SPEAr, Altera
 	  SoCFPGA, Synopsys ARC700 and some Intel x86 SoCs.
 
+config SPL_SYS_I2C_DW
+	bool "Designware I2C Controller in SPL"
+	default n
+	help
+	  Say yes here to select the Designware I2C Host Controller in SPL. This
+	  controller is used in StarFive JH7110 SoC.
+
 config SYS_I2C_ASPEED
 	bool "Aspeed I2C Controller"
 	depends on DM_I2C && ARCH_ASPEED

+ 1 - 1
drivers/i2c/Makefile

@@ -17,7 +17,7 @@ obj-$(CONFIG_SYS_I2C_AT91) += at91_i2c.o
 obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
 obj-$(CONFIG_SYS_I2C_CA) += i2c-cortina.o
 obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
-obj-$(CONFIG_SYS_I2C_DW) += designware_i2c.o
+obj-$(CONFIG_$(SPL_)SYS_I2C_DW) += designware_i2c.o
 ifdef CONFIG_ACPIGEN
 ifdef CONFIG_PCI
 obj-$(CONFIG_SYS_I2C_DW) += designware_i2c_pci.o

+ 4 - 0
drivers/mmc/dw_mmc.c

@@ -685,7 +685,11 @@ void dwmci_setup_cfg(struct mmc_config *cfg, struct dwmci_host *host,
 		cfg->host_caps |= MMC_MODE_4BIT;
 		cfg->host_caps &= ~MMC_MODE_8BIT;
 	}
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_VISIONFIVE2)
+	cfg->host_caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_HS200;
+#else
 	cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS200;
+#endif
 
 	cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 }

+ 13 - 0
drivers/net/dwc_eth_qos.c

@@ -321,6 +321,7 @@ struct eqos_priv {
 	bool clk_ck_enabled;
 	struct reset_ctl_bulk reset_bulk;
 	struct clk_bulk clk_bulk;
+	struct clk rmii_rtx;
 };
 
 /*
@@ -1006,6 +1007,10 @@ static int eqos_set_tx_clk_speed_jh7110(struct udevice *dev)
 		return ret;
 	}
 
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_VISIONFIVE2)
+	clk_set_rate(&eqos->rmii_rtx, rate);
+#endif
+
 	return 0;
 }
 
@@ -1909,6 +1914,14 @@ static int eqos_probe_resources_jh7110(struct udevice *dev)
 		goto err_free_reset_eqos;
 	}
 
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_VISIONFIVE2)
+	ret = clk_get_by_name(dev, "rmii_rtx", &eqos->rmii_rtx);
+	if (ret) {
+		pr_err("clk_get_by_name(rmii_rtx) failed: %d", ret);
+		goto err_free_reset_eqos;
+	}
+#endif
+
 	ret = clk_get_bulk(dev, &eqos->clk_bulk);
 	if (ret) {
 		pr_err("clk_get_bulk failed: %d", ret);

+ 8 - 4
drivers/net/phy/motorcomm.c

@@ -96,6 +96,8 @@ static const struct ytphy_reg_field ytphy_rxden_grp[] = {
 	{ "rxc_dly_en", 1, 8, 0x1 }
 };
 
+static int ytphy_of_config(struct phy_device *phydev);
+
 static int ytphy_read_ext(struct phy_device *phydev, u32 regnum)
 {
 	int ret;
@@ -194,6 +196,11 @@ static int ytphy_startup(struct phy_device *phydev)
 {
 	int retval;
 
+	/*set delay config*/
+	retval = ytphy_of_config(phydev);
+	if (retval < 0)
+		return retval;
+
 	retval = genphy_update_link(phydev);
 	if (retval)
 		return retval;
@@ -256,6 +263,7 @@ static int ytphy_of_config(struct phy_device *phydev)
 
 		cfg = ofnode_read_u32_default(node,
 			ytphy_rxtxd_grp[i].name, ~0);
+
 		cfg = (cfg != -1) ? cfg : ytphy_rxtxd_grp[i].dflt;
 
 		/*check the cfg overflow or not*/
@@ -369,10 +377,6 @@ static int yt8531_config(struct phy_device *phydev)
 	ret = 0;
 	genphy_config_aneg(phydev);
 
-	/*set delay config*/
-	ret = ytphy_of_config(phydev);
-	if (ret < 0)
-		return ret;
 	return 0;
 }
 

+ 30 - 5
drivers/pci/pcie_starfive.c

@@ -103,6 +103,8 @@ struct starfive_pcie {
 
 	int atr_table_num;
 	int first_busno;
+	struct gpio_desc *power_gpio;
+	struct gpio_desc *reset_gpio;
 };
 
 static int starfive_pcie_addr_valid(pci_dev_t bdf, int first_busno)
@@ -371,15 +373,32 @@ static int starfive_pcie_init_port(struct udevice *dev)
 		goto err_deassert_clk;
 	}
 
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_EVB) || CONFIG_IS_ENABLED(TARGET_STARFIVE_DEVKITS)
 	ret = pinctrl_select_state(dev, "power-active");
 	if (ret) {
-		dev_err(dev, "Set power-acvtive pinctrl failed: %d\n", ret);
-		goto err_deassert_reset;
+		priv->power_gpio =
+			devm_gpiod_get_optional(dev, "power", GPIOD_IS_OUT);
+		if (IS_ERR(priv->power_gpio)) {
+			dev_err(dev, "Get power-acvtive gpio failed: %d\n", ret);
+			goto err_deassert_reset;
+		}
+		dm_gpio_set_value(priv->power_gpio, 1);
 	}
+#endif
+
 	ret = pinctrl_select_state(dev, "perst-active");
 	if (ret) {
-		dev_err(dev, "Set perst-active pinctrl failed: %d\n", ret);
-		goto err_release_power_pin;
+		priv->reset_gpio =
+			devm_gpiod_get_optional(dev, "reset", GPIOD_IS_OUT);
+		if (IS_ERR(priv->reset_gpio)) {
+			dev_err(dev, "Set perst-active gpio failed: %d\n", ret);
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_EVB) || CONFIG_IS_ENABLED(TARGET_STARFIVE_DEVKITS)
+			goto err_release_power_pin;
+#else
+			goto err_deassert_reset;
+#endif
+		}
+		dm_gpio_set_value(priv->reset_gpio, 1);
 	}
 
 	/* Disable physical functions except #0 */
@@ -440,14 +459,20 @@ static int starfive_pcie_init_port(struct udevice *dev)
 	mdelay(100);
 	ret = pinctrl_select_state(dev, "perst-default");
 	if (ret) {
-		dev_err(dev, "Set perst-default pinctrl failed: %d\n", ret);
+		if (priv->reset_gpio) {
+			dm_gpio_set_value(priv->reset_gpio, 0);
+			return 0;
+		} else
+			dev_err(dev, "Set perst-default pinctrl failed: %d\n", ret);
 		return ret;
 	}
 
 	return 0;
 
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_EVB) || CONFIG_IS_ENABLED(TARGET_STARFIVE_DEVKITS)
 err_release_power_pin:
 	pinctrl_select_state(dev, "power-default");
+#endif
 err_deassert_reset:
 	reset_assert_bulk(&priv->rsts);
 err_deassert_clk:

+ 13 - 2
drivers/pinctrl/starfive/Kconfig

@@ -1,8 +1,20 @@
 # SPDX-License-Identifier: GPL-2.0-only
 
+config SPL_PINCTRL_STARFIVE
+	bool "Support Pinctrl driver for StarFive SoC in SPL"
+	depends on SPL_PINCTRL_FULL && STARFIVE_JH7110
+	help
+	  Enable support pin control driver for StarFive SoC.
+
+config SPL_PINCTRL_STARFIVE_JH7110
+	bool "Support Pinctrl and GPIO driver for StarFive JH7110 SoC in SPL"
+	depends on  SPL_PINCTRL_STARFIVE
+	help
+	  Enable support pinctrl and gpio driver for StarFive JH7110 in SPL.
+
 config PINCTRL_STARFIVE
 	bool "Pinctrl driver for StarFive SoC"
-	depends on PINCTRL_FULL
+	depends on PINCTRL_FULL && STARFIVE_JH7110
 	help
 	  Say yes here to support pin control on the StarFive RISC-V SoC.
 	  This also provides an interface to the GPIO pins not used by other
@@ -14,4 +26,3 @@ config PINCTRL_STARFIVE_JH7110
 	depends on  PINCTRL_STARFIVE
 	help
 	  This selects the pinctrl driver for JH7110 starfive.
-

+ 2 - 5
drivers/pinctrl/starfive/Makefile

@@ -1,9 +1,6 @@
 
 # SPDX-License-Identifier: GPL-2.0
 # Core
-obj-$(CONFIG_PINCTRL_STARFIVE) += pinctrl-starfive.o
+obj-$(CONFIG_$(SPL_TPL_)PINCTRL_STARFIVE) += pinctrl-starfive.o
 # SoC Drivers
-obj-$(CONFIG_PINCTRL_STARFIVE_JH7110)	+= pinctrl-jh7110-sys.o pinctrl-jh7110-aon.o
-
-
-
+obj-$(CONFIG_$(SPL_TPL_)PINCTRL_STARFIVE_JH7110)	+= pinctrl-jh7110-sys.o pinctrl-jh7110-aon.o

+ 14 - 1
drivers/pinctrl/starfive/pinctrl-jh7110-sys.c

@@ -376,10 +376,23 @@ const struct starfive_pinctrl_soc_info jh7110_sys_pinctrl_info = {
 
 static int jh7110_sys_pinctrl_probe(struct udevice *dev)
 {
+	u32 value;
+	int ret;
 	struct starfive_pinctrl_soc_info *info =
 		(struct starfive_pinctrl_soc_info *)dev_get_driver_data(dev);
+	struct starfive_pinctrl_priv *priv = dev_get_priv(dev);
+
+	ret = starfive_pinctrl_probe(dev, info);
+
+	/* Set up the usb controller overcurrent signal. */
+	if (!ret) {
+		value = readl(priv->base + JH7110_SYS_GPI);
+		value &= ~(0x7f << 16);
+		value |= BIT(16);
+		writel(value, priv->base + JH7110_SYS_GPI);
+	}
 
-	return starfive_pinctrl_probe(dev, info);
+	return ret;
 }
 
 static const struct udevice_id jh7110_sys_pinctrl_ids[] = {

+ 9 - 0
drivers/video/Kconfig

@@ -439,6 +439,15 @@ config VIDEO_LCD_STARFIVE_SEEED
 	Say Y here if you want to enable support for seeed
 	800X480 DSI video mode panel.
 
+config VIDEO_SF_MIPI2EDP
+	bool "mipi to edp LCD panel support"
+	depends on DM_VIDEO
+	select VIDEO_MIPI_DSI
+	default n
+	help
+	Say Y here if you want to enable support for edp
+	1920X1080 DSI video mode panel.
+
 config VIDEO_LCD_SSD2828
 	bool "SSD2828 bridge chip"
 	default n

+ 2 - 1
drivers/video/Makefile

@@ -57,7 +57,8 @@ obj-$(CONFIG_VIDEO_LCD_ANX9804) += anx9804.o
 obj-$(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM) += hitachi_tx18d42vm_lcd.o
 obj-$(CONFIG_VIDEO_LCD_ORISETECH_OTM8009A) += orisetech_otm8009a.o
 obj-$(CONFIG_VIDEO_LCD_RAYDIUM_RM68200) += raydium-rm68200.o
-obj-$(CONFIG_VIDEO_LCD_STARFIVE_SEEED) += raydium-rm68200-starfive.o
+obj-$(CONFIG_VIDEO_LCD_STARFIVE_SEEED) += starfive_seeed_panel.o
+obj-$(CONFIG_VIDEO_SF_MIPI2EDP) += starfive_edp.o
 obj-$(CONFIG_VIDEO_LCD_SSD2828) += ssd2828.o
 obj-$(CONFIG_VIDEO_LCD_TDO_TL070WSH30) += tdo-tl070wsh30.o
 obj-$(CONFIG_VIDEO_MCDE_SIMPLE) += mcde_simple.o

+ 34 - 17
drivers/video/starfive/mipi_dsi_host.c

@@ -220,7 +220,7 @@ static ssize_t cdns_dsi_transfer(struct mipi_dsi_host *host,
 
 	ret = wait_for_send_done(dsi, MIPI_FIFO_TIMEOUT);
 	if (!ret) {
-		printf("wait tx done timeout!\n");
+		debug("wait tx done timeout!\n");
 		return -ETIMEDOUT;
 	}
 	udelay(10);
@@ -285,7 +285,7 @@ static int mipi_dsi_northwest_init(struct udevice *dev,
 	priv->phy_base = (void *)dev_read_addr_name(device->dev, "phy");
 
 	if ((fdt_addr_t)priv->dsi_base == FDT_ADDR_T_NONE || (fdt_addr_t)priv->phy_base == FDT_ADDR_T_NONE) {
-		printf("dsi dt register address error\n");
+		debug("dsi dt register address error\n");
 		return -EINVAL;
 	}
 	priv->link_initialized = false;
@@ -300,21 +300,38 @@ static int mipi_dsi_enable(struct udevice *dev)
 	priv->phy_ops->init(priv->device);
 	priv->phy_ops->post_set_mode(priv->device, MIPI_DSI_MODE_VIDEO);
 	cdns_dsi_init_link(priv, priv->device);
-
-	writel(0x00670067, priv->dsi_base + 0x000000c0);
-	writel(0x00cb0960, priv->dsi_base + 0x000000c4);
-	writel(0x0003b145, priv->dsi_base + 0x000000b4);
-	writel(0x000001e0, priv->dsi_base + 0x000000b8);
-	writel(0x00000a9e, priv->dsi_base + 0x000000d0);
-	writel(0x0a980000, priv->dsi_base + 0x000000f8);
-	writel(0x00000b0f, priv->dsi_base + 0x000000cc);
-	writel(0x7c3c0aae, priv->dsi_base + 0x000000dc);
-	writel(0x0032dcd3, priv->dsi_base + 0x00000014);
-	writel(0x00032dcd, priv->dsi_base + 0x00000018);
-	writel(0x80b8fe00, priv->dsi_base + 0x000000b0);
-	writel(0x00020027, priv->dsi_base + 0x00000004);
-	writel(0x00004018, priv->dsi_base + 0x0000000c);
-
+	debug("priv->timings.hactive.typ %d----\n",priv->timings.hactive.typ);
+	debug("priv->timings.vactive.typ %d----\n",priv->timings.vactive.typ);
+	if (priv->timings.hactive.typ == 800)
+	{
+		writel(0x00670067, priv->dsi_base + 0x000000c0);
+		writel(0x00cb0960, priv->dsi_base + 0x000000c4);
+		writel(0x0003b145, priv->dsi_base + 0x000000b4);
+		writel(0x000001e0, priv->dsi_base + 0x000000b8);
+		writel(0x00000a9e, priv->dsi_base + 0x000000d0);
+		writel(0x0a980000, priv->dsi_base + 0x000000f8);
+		writel(0x00000b0f, priv->dsi_base + 0x000000cc);
+		writel(0x7c3c0aae, priv->dsi_base + 0x000000dc);
+		writel(0x0032dcd3, priv->dsi_base + 0x00000014);
+		writel(0x00032dcd, priv->dsi_base + 0x00000018);
+		writel(0x80b8fe00, priv->dsi_base + 0x000000b0);
+		writel(0x00020027, priv->dsi_base + 0x00000004);
+		writel(0x00004018, priv->dsi_base + 0x0000000c);
+	}else if (priv->timings.hactive.typ == 1920){
+		writel(0x01d30081, priv->dsi_base + 0x000000c0);
+		writel(0x01171680, priv->dsi_base + 0x000000c4);
+		writel(0x00003905, priv->dsi_base + 0x000000b4);
+		writel(0x00000438, priv->dsi_base + 0x000000b8);
+		writel(0x00001976, priv->dsi_base + 0x000000d0);
+		writel(0x19700000, priv->dsi_base + 0x000000f8);
+		writel(0x00001a01, priv->dsi_base + 0x000000cc);
+		writel(0x98900661, priv->dsi_base + 0x000000dc);
+		writel(0x003f9403, priv->dsi_base + 0x00000014);
+		writel(0x0003f940, priv->dsi_base + 0x00000018);
+		writel(0x80b8fe00, priv->dsi_base + 0x000000b0);
+		writel(0x00020027, priv->dsi_base + 0x00000004);
+		writel(0x000040f8, priv->dsi_base + 0x0000000c);
+	}
 	return 0;
 }
 

+ 38 - 9
drivers/video/starfive/sf_mipi.c

@@ -114,7 +114,13 @@ static void dsi_phy_post_set_mode(void *priv_data, unsigned long mode_flags)
 	if (!priv)
 		return;
 
-	bitrate = 750000000;//1188M 60fps
+	// bitrate = 750000000;//1188M 60fps
+	debug("dsi_phy_post_set_mode priv->timings.hactive.typ %d----\n",priv->timings.hactive.typ);
+	debug("dsi_phy_post_set_mode priv->timings.vactive.typ %d----\n",priv->timings.vactive.typ);
+	if (priv->timings.hactive.typ == 800)
+		bitrate = 750000000;
+	else if(priv->timings.hactive.typ == 1920)
+		bitrate = 900000000;//1188M 60fps
 
 	sf_dphy_set_reg(priv->phy_reg + 0x8, 0x10,
 					RG_CDTX_L0N_HSTX_RES_SHIFT, RG_CDTX_L0N_HSTX_RES_MASK);
@@ -159,12 +165,21 @@ static void dsi_phy_post_set_mode(void *priv_data, unsigned long mode_flags)
 							CFG_L0_SWAP_SEL_SHIFT, CFG_L0_SWAP_SEL_MASK);//Lane setting
 			sf_dphy_set_reg(priv->phy_reg, 0x1,
 							CFG_L1_SWAP_SEL_SHIFT, CFG_L1_SWAP_SEL_MASK);
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_EVB)
 			sf_dphy_set_reg(priv->phy_reg, 0x4,
 							CFG_L2_SWAP_SEL_SHIFT, CFG_L2_SWAP_SEL_MASK);
 			sf_dphy_set_reg(priv->phy_reg, 0x2,
 							CFG_L3_SWAP_SEL_SHIFT, CFG_L3_SWAP_SEL_MASK);
 			sf_dphy_set_reg(priv->phy_reg, 0x3,
 							CFG_L4_SWAP_SEL_SHIFT, CFG_L4_SWAP_SEL_MASK);
+#else
+			sf_dphy_set_reg(priv->phy_reg, 0x2,
+							CFG_L2_SWAP_SEL_SHIFT, CFG_L2_SWAP_SEL_MASK);
+			sf_dphy_set_reg(priv->phy_reg, 0x3,
+							CFG_L3_SWAP_SEL_SHIFT, CFG_L3_SWAP_SEL_MASK);
+			sf_dphy_set_reg(priv->phy_reg, 0x4,
+							CFG_L4_SWAP_SEL_SHIFT, CFG_L4_SWAP_SEL_MASK);
+#endif
 			//PLL setting
 			sf_dphy_set_reg(priv->phy_reg + 0x1c, 0x0,
 							RG_CDTX_PLL_SSC_EN_SHIFT, RG_CDTX_PLL_SSC_EN_MASK);
@@ -246,11 +261,24 @@ static int dsi_sf_attach(struct udevice *dev)
 	struct display_timing timings;
 	int ret;
 
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_DEVKITS)
+	ret = uclass_get_device_by_name(UCLASS_PANEL, "seeed_panel@45", &priv->panel);
+	if (ret) {
+		debug("Could not get seeed_panel@45: %d\n", ret);
+		ret = uclass_get_device_by_name(UCLASS_PANEL, "lt8911exb_i2c@29", &priv->panel);
+		if (ret) {
+			debug("Could not get lt8911exb_i2c@29: %d\n", ret);
+			return ret;
+		}
+	}
+#else
 	ret = uclass_first_device(UCLASS_PANEL, &priv->panel);
 	if (ret) {
 		debug("panel device error %d\n", ret);
 		return ret;
 	}
+#endif
+
 	debug("%s,priv->panel->name = %s\n", __func__,priv->panel->name);
 
 	mplat = dev_get_plat(priv->panel);
@@ -264,14 +292,15 @@ static int dsi_sf_attach(struct udevice *dev)
 		ret = ofnode_decode_display_timing(dev_ofnode(priv->panel),
 						   0, &timings);
 		if (ret) {
-			printf("decode display timing error %d\n", ret);
+			debug("decode display timing error %d\n", ret);
 			return ret;
 		}
 	}
+	priv->timings = timings;
 
 	ret = uclass_get_device(UCLASS_DSI_HOST, 0, &priv->dsi_host);
 	if (ret) {
-		printf("No video dsi host detected %d\n", ret);
+		debug("No video dsi host detected %d\n", ret);
 		return ret;
 	}
 
@@ -279,7 +308,7 @@ static int dsi_sf_attach(struct udevice *dev)
 			mplat->lanes,
 			&dsi_stm_phy_ops);
 	if (ret) {
-		printf("failed to initialize mipi dsi host\n");
+		debug("failed to initialize mipi dsi host\n");
 		return ret;
 	}
 
@@ -293,13 +322,13 @@ static int dsi_sf_set_backlight(struct udevice *dev, int percent)
 
 	ret = dsi_host_enable(priv->dsi_host);
 	if (ret) {
-		printf("failed to enable mipi dsi host\n");
+		debug("failed to enable mipi dsi host\n");
 		return ret;
 	}
 
 	ret = panel_enable_backlight(priv->panel);
 	if (ret) {
-		printf("panel %s enable backlight error %d\n",
+		debug("panel %s enable backlight error %d\n",
 			priv->panel->name, ret);
 		return ret;
 	}
@@ -433,7 +462,7 @@ static int dsi_sf_probe(struct udevice *dev)
 
 	ret = dev_read_u32(dev, "data-lanes-num", &priv->data_lanes);
 	if (ret) {
-		printf("fail to get data lanes property %d\n", ret);
+		debug("fail to get data lanes property %d\n", ret);
 		return 0;
 	}
 
@@ -499,13 +528,13 @@ static int dsi_sf_probe(struct udevice *dev)
 
 	debug("%s ok: ID_REG val = %08x\n", __func__, val);
 	if (REV_VENDOR_ID(val) != 0xcad) {
-		printf("invalid vendor id\n");
+		debug("invalid vendor id\n");
 		ret = -EINVAL;
 	}
 
 	ret = cdns_check_register_access(dev);
     if (ret) {
-        printf("error: r/w test generic reg failed\n");
+        debug("error: r/w test generic reg failed\n");
     }
 
 	val = readl(priv->dsi_reg + IP_CONF);

+ 1 - 0
drivers/video/starfive/sf_mipi.h

@@ -786,6 +786,7 @@ struct dsi_sf_priv {
 	struct udevice *panel;
 	struct udevice *dsi_host;
 	unsigned int data_lanes;
+	struct display_timing timings;
 
 	struct clk dsi_sys_clk;
 	struct clk apb_clk;

+ 139 - 3
drivers/video/starfive/sf_vop.c

@@ -29,6 +29,7 @@
 #include <panel.h>
 
 #include "sf_vop.h"
+#include "sf_mipi.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -43,7 +44,6 @@ static void iotrace_writel(ulong value, void *ptr)
 static int sf_vop_power_off(struct udevice *dev)
 {
 	struct udevice *dev_power;
-	struct udevice *dev_pmic;
 	struct power_domain_ops *ops;
 	struct power_domain power_domain;
 	int ret;
@@ -76,7 +76,9 @@ static int sf_vop_power_off(struct udevice *dev)
 static int sf_vop_power(struct udevice *dev)
 {
 	struct udevice *dev_power;
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_EVB)
 	struct udevice *dev_pmic;
+#endif
 	struct power_domain_ops *ops;
 	struct power_domain power_domain;
 	int ret;
@@ -108,6 +110,7 @@ static int sf_vop_power(struct udevice *dev)
 		return ret;
 	}
 
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_EVB)
 	ret = uclass_get_device_by_driver(UCLASS_PMIC,
 			  DM_DRIVER_GET(pmic_starfive), &dev_pmic);
 	if (ret) {
@@ -120,6 +123,7 @@ static int sf_vop_power(struct udevice *dev)
 		pr_err("failed to update SD control register: %d", ret);
 		return ret;
 	}
+#endif
 
 	return 0;
 }
@@ -395,7 +399,9 @@ static int sf_display_init(struct udevice *dev, ulong fbbase, ofnode ep_node)
 	debug("%s(%s, 0x%lx, %s)\n", __func__,
 			  dev_read_name(dev), fbbase, ofnode_get_name(ep_node));
 
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_EVB) || CONFIG_IS_ENABLED(TARGET_STARFIVE_VISIONFIVE2)
 	struct udevice *panel = NULL;
+#endif
 
 	ret = ofnode_read_u32(ep_node, "remote-endpoint", &remote_phandle);
 	if (ret)
@@ -576,6 +582,7 @@ static int sf_display_init(struct udevice *dev, ulong fbbase, ofnode ep_node)
 			return ret;
 		}
 
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_EVB) || CONFIG_IS_ENABLED(TARGET_STARFIVE_VISIONFIVE2)
 		ret = uclass_first_device_err(UCLASS_PANEL, &panel);
 		if (ret) {
 			if (ret != -ENODEV)
@@ -592,6 +599,7 @@ static int sf_display_init(struct udevice *dev, ulong fbbase, ofnode ep_node)
 				return ret;
 			}
 		}
+#endif
 
 		int err = clk_set_parent(&priv->dc_pix0, &priv->dc_pix_src);
 		if (err) {
@@ -600,17 +608,40 @@ static int sf_display_init(struct udevice *dev, ulong fbbase, ofnode ep_node)
 			return err;
 		}
 
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_EVB) || CONFIG_IS_ENABLED(TARGET_STARFIVE_VISIONFIVE2)
 		ulong new_rate = clk_set_rate(&priv->dc_pix_src, timing.pixelclock.typ);
 		debug("new_rate  %ld\n", new_rate);
+#endif
 
 		dc_hw_init(dev);
 
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_EVB) || CONFIG_IS_ENABLED(TARGET_STARFIVE_VISIONFIVE2)
 		uc_priv->xsize = timing.hactive.typ;
 		uc_priv->ysize = timing.vactive.typ;
 
 		if (IS_ENABLED(CONFIG_VIDEO_COPY))
 			uc_plat->copy_base = uc_plat->base - uc_plat->size / 2;
+#else
+		struct dsi_sf_priv *private = dev_get_priv(disp);
+
+		uc_priv->xsize = private->timings.hactive.typ;
+		uc_priv->ysize = private->timings.vactive.typ;
+		debug("uc_priv->xsize  %d\n", uc_priv->xsize);
+		debug("uc_priv->ysize  %d\n", uc_priv->ysize);
+
+		if(uc_priv->xsize == 800)
+		{
+			ulong new_rate = clk_set_rate(&priv->dc_pix_src, 29700000);
+			debug("new_rate  %ld\n", new_rate);
+		}
+		if(uc_priv->xsize == 1920)
+		{
+			ulong new_rate = clk_set_rate(&priv->dc_pix_src, 148500000);
+			debug("new_rate  %ld\n", new_rate);
+		}
+#endif
 
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_EVB) || CONFIG_IS_ENABLED(TARGET_STARFIVE_VISIONFIVE2)
 		writel(0xc0001fff, priv->regs_hi+0x00000014); //csr_reg
 		writel(0x000000e8, priv->regs_hi+0x00001a38); //csr_reg
 		writel(0x00002000, priv->regs_hi+0x00001cc0); //csr_reg
@@ -660,10 +691,115 @@ static int sf_display_init(struct udevice *dev, ulong fbbase, ofnode ep_node)
 		writel(0x00000000, priv->regs_hi+0x000024fc); //csr_reg
 		writel(0x00011b25, priv->regs_hi+0x000024e8); //csr_reg
 		writel(0x00000001, priv->regs_hi+0x00001ccc); //csr_reg
-		priv->mipi_logo = true;
-		return 0;
+#else
+		if(uc_priv->xsize == 800)
+		{
+			writel(0xc0001fff, priv->regs_hi+0x00000014); //csr_reg
+			writel(0x000000e8, priv->regs_hi+0x00001a38); //csr_reg
+			writel(0x00002000, priv->regs_hi+0x00001cc0); //csr_reg
+			writel(0x00000000, priv->regs_hi+0x000024d8); //csr_reg
+			writel(0x03c00438, priv->regs_hi+0x000024e0); //csr_reg
+			writel(0x03c00438, priv->regs_hi+0x00001810); //csr_reg
+			writel(uc_plat->base, priv->regs_hi+0x00001400);
+			writel(0x000010e0, priv->regs_hi+0x00001408); //csr_reg
+			writel(0x000fb00b, priv->regs_hi+0x00001ce8); //csr_reg
+			writel(0x0000a9a3, priv->regs_hi+0x00002510); //csr_reg
+			writel(0x2c4e6f06, priv->regs_hi+0x00002508); //csr_reg
+			writel(0xe6daec4f, priv->regs_hi+0x00002500); //csr_reg
+			writel(0x18220000, priv->regs_hi+0x00001518); //csr_reg
+			writel(0x00003000, priv->regs_hi+0x00001cc0); //csr_reg
+			writel(0x00030000, priv->regs_hi+0x00001cc4); //csr_reg
+			writel(0x00030000, priv->regs_hi+0x00001cc4); //csr_reg
+			writel(0x00050c1a, priv->regs_hi+0x00001540); //csr_reg
+			writel(0x00000001, priv->regs_hi+0x00002540); //csr_reg
+			writel(0x00050c1a, priv->regs_hi+0x00001540); //csr_reg
+			writel(0x4016120c, priv->regs_hi+0x00001544); //csr_reg
+			writel(0x00000002, priv->regs_hi+0x00002544); //csr_reg
+			writel(0x4016120c, priv->regs_hi+0x00001544); //csr_reg
+			writel(0x001b1208, priv->regs_hi+0x00001548); //csr_reg
+			writel(0x00000004, priv->regs_hi+0x00002548); //csr_reg
+			writel(0x001b1208, priv->regs_hi+0x00001548); //csr_reg
+			writel(0x0016110e, priv->regs_hi+0x0000154c); //csr_reg
+			writel(0x00000005, priv->regs_hi+0x0000254c); //csr_reg
+			writel(0x0016110e, priv->regs_hi+0x0000154c); //csr_reg
+			writel(0x00000001, priv->regs_hi+0x00002518); //csr_reg
+			writel(0x00000000, priv->regs_hi+0x00001a28); //csr_reg
+			writel(0x03840320, priv->regs_hi+0x00001430); //csr_reg, hsize, htotal
+			writel(0xc1bf837a, priv->regs_hi+0x00001438); //csr_reg, hsize blanking
+			writel(0x022601e0, priv->regs_hi+0x00001440); //csr_reg, vsize
+			writel(0xc110021c, priv->regs_hi+0x00001448); //csr_reg, vsize blanking
+			writel(0x00000000, priv->regs_hi+0x000014b0); //csr_reg
+			writel(0x000000e2, priv->regs_hi+0x00001cd0); //csr_reg
+			writel(0x000000af, priv->regs_hi+0x000014d0); //csr_reg
+			writel(0x00000005, priv->regs_hi+0x000014b8); //csr_reg
+			writel(0x8dd0b774, priv->regs_hi+0x00001528); //csr_reg
+			writel(0x00001111, priv->regs_hi+0x00001418); //csr_reg
+			writel(0x00000000, priv->regs_hi+0x00001410); //csr_reg
+			writel(0x00000000, priv->regs_hi+0x00002518); //csr_reg
+			writel(0x00000006, priv->regs_hi+0x00001468); //csr_reg
+			writel(0x00000000, priv->regs_hi+0x00001484); //csr_reg
+			writel(0x00000006, priv->regs_hi+0x00001468); //csr_reg
+			writel(0x00011b25, priv->regs_hi+0x000024e8); //csr_reg
+			writel(0x00000000, priv->regs_hi+0x000024fc); //csr_reg
+			writel(0x00011b25, priv->regs_hi+0x000024e8); //csr_reg
+			writel(0x00000001, priv->regs_hi+0x00001ccc); //csr_reg
+		}
+		if(uc_priv->xsize == 1920)
+		{
+			writel(0xc0001fff, priv->regs_hi+0x00000014);
+			writel(0x000000e8, priv->regs_hi+0x00001a38);
+			writel(0x00002000, priv->regs_hi+0x00001cc0);
+			writel(0x00000000, priv->regs_hi+0x000024d8);
+			writel(0x04380780, priv->regs_hi+0x000024e0);
+			writel(0x04380780, priv->regs_hi+0x00001810);
+			writel(uc_plat->base, priv->regs_hi+0x00001400);
+			writel(0x00001e00, priv->regs_hi+0x00001408);
+			writel(0x00000000, priv->regs_hi+0x00001ce8);
+			writel(0x0000a9a3, priv->regs_hi+0x00002510);
+			writel(0x2c4e6f06, priv->regs_hi+0x00002508);
+			writel(0xe6daec4f, priv->regs_hi+0x00002500);
+			writel(0x18220000, priv->regs_hi+0x00001518);
+			writel(0x00003000, priv->regs_hi+0x00001cc0);
+			writel(0x00030000, priv->regs_hi+0x00001cc4);
+			writel(0x00030000, priv->regs_hi+0x00001cc4);
+			writel(0x00050c1a, priv->regs_hi+0x00001540);
+			writel(0x00000001, priv->regs_hi+0x00002540);
+			writel(0x00050c1a, priv->regs_hi+0x00001540);
+			writel(0x4016120c, priv->regs_hi+0x00001544);
+			writel(0x00000002, priv->regs_hi+0x00002544);
+			writel(0x4016120c, priv->regs_hi+0x00001544);
+			writel(0x001b1208, priv->regs_hi+0x00001548);
+			writel(0x00000004, priv->regs_hi+0x00002548);
+			writel(0x001b1208, priv->regs_hi+0x00001548);
+			writel(0x0016110e, priv->regs_hi+0x0000154c);
+			writel(0x00000005, priv->regs_hi+0x0000254c);
+			writel(0x0016110e, priv->regs_hi+0x0000154c);
+			writel(0x00000001, priv->regs_hi+0x00002518);
+			writel(0x00000000, priv->regs_hi+0x00001a28);
+			writel(0x08980780, priv->regs_hi+0x00001430);
+			writel(0xc40207d8, priv->regs_hi+0x00001438);
+			writel(0x04650438, priv->regs_hi+0x00001440);
+			writel(0xc220843c, priv->regs_hi+0x00001448);
+			writel(0x00000000, priv->regs_hi+0x000014b0);
+			writel(0x000000e2, priv->regs_hi+0x00001cd0);
+			writel(0x000000af, priv->regs_hi+0x000014d0);
+			writel(0x00000005, priv->regs_hi+0x000014b8);
+			writel(0x8dd0b774, priv->regs_hi+0x00001528);
+			writel(0x00001111, priv->regs_hi+0x00001418);
+			writel(0x00000000, priv->regs_hi+0x00001410);
+			writel(0x00000000, priv->regs_hi+0x00002518);
+			writel(0x00000006, priv->regs_hi+0x00001468);
+			writel(0x00000000, priv->regs_hi+0x00001484);
+			writel(0x00000006, priv->regs_hi+0x00001468);
+			writel(0x00011b25, priv->regs_hi+0x000024e8);
+			writel(0x00000000, priv->regs_hi+0x000024fc);
+			writel(0x00011b25, priv->regs_hi+0x000024e8);
+			writel(0x00000001, priv->regs_hi+0x00001ccc);
+		}
+#endif
 	}
 
+	priv->mipi_logo = true;
 	return 0;
 }
 

+ 1302 - 0
drivers/video/starfive_edp.c

@@ -0,0 +1,1302 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 STMicroelectronics - All Rights Reserved
+ * Author(s): Yannick Fertre <yannick.fertre@st.com> for STMicroelectronics.
+ *            Philippe Cornu <philippe.cornu@st.com> for STMicroelectronics.
+ *
+ * This edp panel driver is inspired from the Linux Kernel driver
+ * drivers/gpu/drm/panel/panel-raydium-edp.c.
+ */
+#include <common.h>
+#include <backlight.h>
+#include <dm.h>
+#include <mipi_dsi.h>
+#include <panel.h>
+#include <asm/gpio.h>
+#include <dm/device_compat.h>
+#include <linux/delay.h>
+#include <power/regulator.h>
+#include <i2c.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/jh7110-regs.h>
+#include <asm/io.h>
+
+
+#define	UART_DEBUG
+#define TEST_EDID // read eDP panel EDID
+#define EDP_2G7
+#define LINK_TRAIN_ENABLE
+#define LT8911EXB_RST_PIN GPIO41
+#define BOE_14INCH_MAX_LANES 4
+
+#define _1080P_eDP_Panel_
+#define _MIPI_Lane_ 4   // 3 /2 / 1
+#define _MIPI_data_PN_Swap_En	0xF0
+#define _MIPI_data_PN_Swap_Dis	0x00
+#define _MIPI_data_PN_ _MIPI_data_PN_Swap_Dis
+
+#define	NO_SWAP				0x00    // 3210 default
+#define MIPI_DATA_3210		0       // default
+#define MIPI_DATA_0123		21
+#define MIPI_DATA_2103		20
+
+#define MIPI_DATA_SEQ 		NO_SWAP
+
+#define _Nvid 0         // 0: 0x0080,default
+static int Nvid_Val[] = { 0x0080, 0x0800 };
+#define usleep_range(a, b) udelay((b))
+
+#ifdef _1080P_eDP_Panel_
+
+#define eDP_lane		2
+#define PCR_PLL_PREDIV	0x40
+
+static int MIPI_Timing[] =
+{ 88, 	44, 148, 	1920, 	2200, 	4, 		5, 	36, 	1080, 	1125, 		14850 };   // VESA
+
+
+//#define _6bit_ // eDP panel Color Depth,262K color
+#define _8bit_                                              // eDP panel Color Depth,16.7M color
+
+#endif
+
+enum {
+	hfp = 0,
+	hs,
+	hbp,
+	hact,
+	htotal,
+	vfp,
+	vs,
+	vbp,
+	vact,
+	vtotal,
+	pclk_10khz
+};
+
+u8		Read_DPCD010A = 0x00;
+bool	ScrambleMode = 0;
+bool	flag_mipi_on = 0;
+#ifdef TEST_EDID // read eDP panel EDID
+u8		EDID_DATA[128] = { 0 };
+u16		EDID_Timing[11] = { 0 };
+bool	EDID_Reply = 0;
+#endif
+
+static inline void sys_modl(void *addr, uint32_t mask, uint32_t val)
+{
+	uint32_t tmp;
+
+	tmp = readl(addr);
+	tmp &= ~mask;
+	tmp |= (val & mask);
+
+	debug("tmp 0x%x\n", tmp);
+	writel(tmp, addr);
+}
+
+struct edp_panel_priv {
+	struct udevice *reg;
+	struct udevice *backlight;
+
+	struct gpio_desc *reset_gpio;   //reset
+	struct gpio_desc *pwm_gpio;  	//power
+	struct gpio_desc *bl_gpio;  	//backlight
+};
+
+static const struct display_timing default_timing = {
+	.pixelclock.typ		= 148500000,
+	.hactive.typ		= 1920,
+	.hfront_porch.typ	= 88,
+	.hback_porch.typ	= 148,
+	.hsync_len.typ		= 44,
+	.vactive.typ		= 1080,
+	.vfront_porch.typ	= 34,
+	.vback_porch.typ	= 6,
+	.vsync_len.typ		= 5,
+};
+
+static int edp_panel_i2c_write(struct udevice *dev, uint addr, uint8_t data)
+{
+	uint8_t valb;
+	int err;
+	valb = data;
+
+	err = dm_i2c_write(dev, addr, &valb, 1);
+	return err;
+}
+
+static int edp_panel_i2c_read(struct udevice *dev, uint8_t addr, uint8_t *data)
+{
+	uint8_t valb;
+	int err;
+
+	err = dm_i2c_read(dev, addr, &valb, 1);
+	if (err)
+		return err;
+
+	*data = (int)valb;
+	return 0;
+}
+
+static u8 LT8911EXB_IIC_Read_byte(struct udevice *dev, u8 reg)
+{
+	uint8_t valb;
+	int err;
+
+	err = dm_i2c_read(dev, reg, &valb, 1);
+	if (err)
+		return err;
+	udelay(10);
+
+	return (int)valb;
+
+}
+
+static void LT8911EXB_IIC_Write_byte(struct udevice *dev,u8 reg, u8 val)
+{
+	dm_i2c_write(dev, reg, &val, 1);
+	udelay(10);
+}
+
+u8 boe_i2c_read(struct udevice *dev,u8 reg){
+	return LT8911EXB_IIC_Read_byte(dev,reg);
+}
+
+void boe_i2c_write(struct udevice *dev,u8 reg, u8 val){
+	LT8911EXB_IIC_Write_byte(dev,reg,val);
+}
+
+void Reset_LT8911EXB(struct udevice *dev)
+{
+	struct edp_panel_priv *priv = dev_get_priv(dev);
+
+	dm_gpio_set_value(priv->pwm_gpio, 0);
+	dm_gpio_set_value(priv->bl_gpio, 0);
+
+	dm_gpio_set_value(priv->reset_gpio, 0);
+
+}
+
+void LT8911EX_ChipID(struct udevice *dev)                                         
+{
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x81 );
+	LT8911EXB_IIC_Write_byte(dev, 0x08, 0x7f );
+
+#ifdef UART_DEBUG
+	debug( "\r\nLT8911EXB chip ID: 0x%x", LT8911EXB_IIC_Read_byte(dev, 0x00 ) );
+	debug( ",0x%x", LT8911EXB_IIC_Read_byte(dev, 0x01 ) );
+	debug( ",0x%x", LT8911EXB_IIC_Read_byte(dev, 0x02 ) );
+#endif
+}
+
+void LT8911EXB_read_edid(struct udevice *dev)
+{
+#ifdef TEST_EDID
+	u8 reg, i, j;
+//	bool	aux_reply, aux_ack, aux_nack, aux_defer;
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0xac );
+	LT8911EXB_IIC_Write_byte(dev, 0x00, 0x20 ); //Soft Link train
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0xa6 );
+	LT8911EXB_IIC_Write_byte(dev, 0x2a, 0x01 );
+
+	/*set edid offset addr*/
+	LT8911EXB_IIC_Write_byte(dev, 0x2b, 0x40 ); //CMD
+	LT8911EXB_IIC_Write_byte(dev, 0x2b, 0x00 ); //addr[15:8]
+	LT8911EXB_IIC_Write_byte(dev, 0x2b, 0x50 ); //addr[7:0]
+	LT8911EXB_IIC_Write_byte(dev, 0x2b, 0x00 ); //data lenth
+	LT8911EXB_IIC_Write_byte(dev, 0x2b, 0x00 ); //data lenth
+	LT8911EXB_IIC_Write_byte(dev, 0x2c, 0x00 ); //start Aux read edid
+
+#ifdef UART_DEBUG
+	debug( "\r\n" );
+	debug( "\r\nRead eDP EDID......" );
+#endif
+
+	mdelay( 20 ); //more than 10ms
+	reg = LT8911EXB_IIC_Read_byte(dev, 0x25);
+	
+	debug( "\r\nRead eDP EDID.reg = %02x.....\n", reg);
+	if( ( reg & 0x0f ) == 0x0c )
+	{
+		for( j = 0; j < 8; j++ )
+		{
+			if( j == 7 )
+			{
+				LT8911EXB_IIC_Write_byte(dev, 0x2b, 0x10 ); //MOT
+			}else
+			{
+				LT8911EXB_IIC_Write_byte(dev, 0x2b, 0x50 );
+			}
+
+			LT8911EXB_IIC_Write_byte(dev, 0x2b, 0x00 );
+			LT8911EXB_IIC_Write_byte(dev, 0x2b, 0x50 );
+			LT8911EXB_IIC_Write_byte(dev, 0x2b, 0x0f );
+			LT8911EXB_IIC_Write_byte(dev, 0x2c, 0x00 ); //start Aux read edid
+			mdelay( 50 );                         //more than 50ms
+
+			if( LT8911EXB_IIC_Read_byte(dev, 0x39 ) == 0x31 )
+			{
+				LT8911EXB_IIC_Read_byte(dev, 0x2b );
+				for( i = 0; i < 16; i++ )
+				{
+					EDID_DATA[j * 16 + i] = LT8911EXB_IIC_Read_byte(dev, 0x2b );
+				}
+
+				EDID_Reply = 1;
+			}else
+			{
+				EDID_Reply = 0;
+#ifdef UART_DEBUG
+				debug( "\r\nno_reply" );
+				debug( "\r\n" );
+#endif
+				debug("\r\n*************End***************");
+				return;
+			}
+		}
+
+#ifdef UART_DEBUG
+
+		for( i = 0; i < 128; i++ ) //print edid data
+		{
+			if( ( i % 16 ) == 0 )
+			{
+				debug( "\r\n" );
+			}
+			debug( "%d, ", EDID_DATA[i] );
+		}
+
+		EDID_Timing[hfp] = ( ( EDID_DATA[0x41] & 0xC0 ) * 4 + EDID_DATA[0x3e] );
+
+		EDID_Timing[hs] = ( ( EDID_DATA[0x41] & 0x30 ) * 16 + EDID_DATA[0x3f] );
+
+		EDID_Timing[hbp] = ( ( ( EDID_DATA[0x3a] & 0x0f ) * 0x100 + EDID_DATA[0x39] ) - ( ( EDID_DATA[0x41] & 0x30 ) * 16 + EDID_DATA[0x3f] ) - ( ( EDID_DATA[0x41] & 0xC0 ) * 4 + EDID_DATA[0x3e] ) );
+
+		EDID_Timing[hact] = ( ( EDID_DATA[0x3a] & 0xf0 ) * 16 + EDID_DATA[0x38] );
+
+		EDID_Timing[htotal] = ( ( EDID_DATA[0x3a] & 0xf0 ) * 16 + EDID_DATA[0x38] + ( ( EDID_DATA[0x3a] & 0x0f ) * 0x100 + EDID_DATA[0x39] ) );
+
+		EDID_Timing[vfp] = ( ( EDID_DATA[0x41] & 0x0c ) * 4 + ( EDID_DATA[0x40] & 0xf0 ) / 16 );
+
+		EDID_Timing[vs] = ( ( EDID_DATA[0x41] & 0x03 ) * 16 + (EDID_DATA[0x40] & 0x0f) );
+
+		EDID_Timing[vbp] = ( ( ( EDID_DATA[0x3d] & 0x03 ) * 0x100 + EDID_DATA[0x3c] ) - ( ( EDID_DATA[0x41] & 0x03 ) * 16 + ( EDID_DATA[0x40] & 0x0f ) ) - ( ( EDID_DATA[0x41] & 0x0c ) * 4 + ( EDID_DATA[0x40] & 0xf0 ) / 16 ) );
+
+		EDID_Timing[vact] = ( ( EDID_DATA[0x3d] & 0xf0 ) * 16 + EDID_DATA[0x3b] );
+
+		EDID_Timing[vtotal] = ( ( EDID_DATA[0x3d] & 0xf0 ) * 16 + EDID_DATA[0x3b] + ( ( EDID_DATA[0x3d] & 0x03 ) * 0x100 + EDID_DATA[0x3c] ) );
+
+		EDID_Timing[pclk_10khz] = ( EDID_DATA[0x37] * 0x100 + EDID_DATA[0x36] );
+#endif
+	}
+
+	return;
+
+#endif
+}
+
+void LT8911EXB_MIPI_Video_Timing(struct udevice *dev)                                    // ( struct video_timing *video_format )
+{
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0xd0 );
+	LT8911EXB_IIC_Write_byte(dev, 0x0d, (u8)( MIPI_Timing[vtotal] / 256 ) );
+	LT8911EXB_IIC_Write_byte(dev, 0x0e, (u8)( MIPI_Timing[vtotal] % 256 ) );    //vtotal
+	LT8911EXB_IIC_Write_byte(dev, 0x0f, (u8)( MIPI_Timing[vact] / 256 ) );
+	LT8911EXB_IIC_Write_byte(dev, 0x10, (u8)( MIPI_Timing[vact] % 256 ) );      //vactive
+
+	LT8911EXB_IIC_Write_byte(dev, 0x11, (u8)( MIPI_Timing[htotal] / 256 ) );
+	LT8911EXB_IIC_Write_byte(dev, 0x12, (u8)( MIPI_Timing[htotal] % 256 ) );    //htotal
+	LT8911EXB_IIC_Write_byte(dev, 0x13, (u8)( MIPI_Timing[hact] / 256 ) );
+	LT8911EXB_IIC_Write_byte(dev, 0x14, (u8)( MIPI_Timing[hact] % 256 ) );      //hactive
+
+	LT8911EXB_IIC_Write_byte(dev, 0x15, (u8)( MIPI_Timing[vs] % 256 ) );        //vsa
+	LT8911EXB_IIC_Write_byte(dev, 0x16, (u8)( MIPI_Timing[hs] % 256 ) );        //hsa
+	LT8911EXB_IIC_Write_byte(dev, 0x17, (u8)( MIPI_Timing[vfp] / 256 ) );
+	LT8911EXB_IIC_Write_byte(dev, 0x18, (u8)( MIPI_Timing[vfp] % 256 ) );       //vfp
+
+	LT8911EXB_IIC_Write_byte(dev, 0x19, (u8)( MIPI_Timing[hfp] / 256 ) );
+	LT8911EXB_IIC_Write_byte(dev, 0x1a, (u8)( MIPI_Timing[hfp] % 256 ) );       //hfp
+}
+
+void LT8911EXB_eDP_Video_cfg(struct udevice *dev)                                        // ( struct video_timing *video_format )
+{
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0xa8 );
+	LT8911EXB_IIC_Write_byte(dev, 0x2d, 0x88 );                                 // MSA from register
+
+#ifdef _Msa_Active_Only_
+	LT8911EXB_IIC_Write_byte(dev, 0x05, 0x00 );
+	LT8911EXB_IIC_Write_byte(dev, 0x06, 0x00 );                                 //htotal
+	LT8911EXB_IIC_Write_byte(dev, 0x07, 0x00 );
+	LT8911EXB_IIC_Write_byte(dev, 0x08, 0x00 );                                 //h_start
+
+	LT8911EXB_IIC_Write_byte(dev, 0x09, 0x00 );
+	LT8911EXB_IIC_Write_byte(dev, 0x0a, 0x00 );                                 //hsa
+	LT8911EXB_IIC_Write_byte(dev, 0x0b, (u8)( MIPI_Timing[hact] / 256 ) );
+	LT8911EXB_IIC_Write_byte(dev, 0x0c, (u8)( MIPI_Timing[hact] % 256 ) );      //hactive
+
+	LT8911EXB_IIC_Write_byte(dev, 0x0d, 0x00 );
+	LT8911EXB_IIC_Write_byte(dev, 0x0e, 0x00 );                                 //vtotal
+
+	LT8911EXB_IIC_Write_byte(dev, 0x11, 0x00 );
+	LT8911EXB_IIC_Write_byte(dev, 0x12, 0x00 );
+	LT8911EXB_IIC_Write_byte(dev, 0x14, 0x00 );
+	LT8911EXB_IIC_Write_byte(dev, 0x15, (u8)( MIPI_Timing[vact] / 256 ) );
+	LT8911EXB_IIC_Write_byte(dev, 0x16, (u8)( MIPI_Timing[vact] % 256 ) );      //vactive
+
+#else
+
+	LT8911EXB_IIC_Write_byte(dev, 0x05, (u8)( MIPI_Timing[htotal] / 256 ) );
+	LT8911EXB_IIC_Write_byte(dev, 0x06, (u8)( MIPI_Timing[htotal] % 256 ) );
+	LT8911EXB_IIC_Write_byte(dev, 0x07, (u8)( ( MIPI_Timing[hs] + MIPI_Timing[hbp] ) / 256 ) );
+	LT8911EXB_IIC_Write_byte(dev, 0x08, (u8)( ( MIPI_Timing[hs] + MIPI_Timing[hbp] ) % 256 ) );
+	LT8911EXB_IIC_Write_byte(dev, 0x09, (u8)( MIPI_Timing[hs] / 256 ) );
+	LT8911EXB_IIC_Write_byte(dev, 0x0a, (u8)( MIPI_Timing[hs] % 256 ) );
+	LT8911EXB_IIC_Write_byte(dev, 0x0b, (u8)( MIPI_Timing[hact] / 256 ) );
+	LT8911EXB_IIC_Write_byte(dev, 0x0c, (u8)( MIPI_Timing[hact] % 256 ) );
+	LT8911EXB_IIC_Write_byte(dev, 0x0d, (u8)( MIPI_Timing[vtotal] / 256 ) );
+	LT8911EXB_IIC_Write_byte(dev, 0x0e, (u8)( MIPI_Timing[vtotal] % 256 ) );
+	LT8911EXB_IIC_Write_byte(dev, 0x11, (u8)( ( MIPI_Timing[vs] + MIPI_Timing[vbp] ) / 256 ) );
+	LT8911EXB_IIC_Write_byte(dev, 0x12, (u8)( ( MIPI_Timing[vs] + MIPI_Timing[vbp] ) % 256 ) );
+	LT8911EXB_IIC_Write_byte(dev, 0x14, (u8)( MIPI_Timing[vs] % 256 ) );
+	LT8911EXB_IIC_Write_byte(dev, 0x15, (u8)( MIPI_Timing[vact] / 256 ) );
+	LT8911EXB_IIC_Write_byte(dev, 0x16, (u8)( MIPI_Timing[vact] % 256 ) );
+#endif
+}
+
+void LT8911EXB_init(struct udevice *dev)
+{
+	u8	i;
+	u8	pcr_pll_postdiv;
+	u8	pcr_m;
+	u16 Temp16;
+
+	/* init */
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x81 ); // Change Reg bank
+	LT8911EXB_IIC_Write_byte(dev, 0x08, 0x7f ); // i2c over aux issue
+	LT8911EXB_IIC_Write_byte(dev, 0x49, 0xff ); // enable 0x87xx
+
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x82 ); // Change Reg bank
+	LT8911EXB_IIC_Write_byte(dev, 0x5a, 0x0e ); // GPIO test output
+
+	//for power consumption//
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x81 );
+	LT8911EXB_IIC_Write_byte(dev, 0x05, 0x06 );
+	LT8911EXB_IIC_Write_byte(dev, 0x43, 0x00 );
+	LT8911EXB_IIC_Write_byte(dev, 0x44, 0x1f );
+	LT8911EXB_IIC_Write_byte(dev, 0x45, 0xf7 );
+	LT8911EXB_IIC_Write_byte(dev, 0x46, 0xf6 );
+	LT8911EXB_IIC_Write_byte(dev, 0x49, 0x7f );
+
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x82 );
+#if ( eDP_lane == 2 )
+	{
+		LT8911EXB_IIC_Write_byte(dev, 0x12, 0x33 );
+	}
+#elif ( eDP_lane == 1 )
+	{
+		LT8911EXB_IIC_Write_byte(dev, 0x12, 0x11 );
+	}
+#endif
+
+	/* mipi Rx analog */
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x82 ); // Change Reg bank
+	LT8911EXB_IIC_Write_byte(dev, 0x32, 0x51 );
+	LT8911EXB_IIC_Write_byte(dev, 0x35, 0x22 ); //EQ current 0x22/0x42/0x62/0x82/0xA2/0xC2/0xe2
+	LT8911EXB_IIC_Write_byte(dev, 0x3a, 0x77 ); //EQ 12.5db
+	LT8911EXB_IIC_Write_byte(dev, 0x3b, 0x77 ); //EQ 12.5db
+
+	LT8911EXB_IIC_Write_byte(dev, 0x4c, 0x0c );
+	LT8911EXB_IIC_Write_byte(dev, 0x4d, 0x00 );
+
+	/* dessc_pcr  pll analog */
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x82 ); // Change Reg bank
+	LT8911EXB_IIC_Write_byte(dev, 0x6a, 0x40 );
+	LT8911EXB_IIC_Write_byte(dev, 0x6b, PCR_PLL_PREDIV );
+
+	Temp16 = MIPI_Timing[pclk_10khz];
+
+	if( MIPI_Timing[pclk_10khz] < 8800 )
+	{
+		LT8911EXB_IIC_Write_byte(dev, 0x6e, 0x82 ); //0x44:pre-div = 2 ,pixel_clk=44~ 88MHz
+		pcr_pll_postdiv = 0x08;
+	}else
+	if( MIPI_Timing[pclk_10khz] < 17600 )
+	{
+		LT8911EXB_IIC_Write_byte(dev, 0x6e, 0x81 ); //0x40:pre-div = 1, pixel_clk =88~176MHz
+		pcr_pll_postdiv = 0x04;
+	}else
+	{
+		LT8911EXB_IIC_Write_byte(dev, 0x6e, 0x80 ); //0x40:pre-div = 0, pixel_clk =176~200MHz
+		pcr_pll_postdiv = 0x02;
+	}
+
+	pcr_m = (u8)( Temp16 * pcr_pll_postdiv / 25 / 100 );
+
+	/* dessc pll digital */
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x85 );     // Change Reg bank
+	LT8911EXB_IIC_Write_byte(dev, 0xa9, 0x31 );
+	LT8911EXB_IIC_Write_byte(dev, 0xaa, 0x17 );
+	LT8911EXB_IIC_Write_byte(dev, 0xab, 0xba );
+	LT8911EXB_IIC_Write_byte(dev, 0xac, 0xe1 );
+	LT8911EXB_IIC_Write_byte(dev, 0xad, 0x47 );
+	LT8911EXB_IIC_Write_byte(dev, 0xae, 0x01 );
+	LT8911EXB_IIC_Write_byte(dev, 0xae, 0x11 );
+
+	/* Digital Top */
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x85 );                             // Change Reg bank
+	LT8911EXB_IIC_Write_byte(dev, 0xc0, 0x01 );                             //select mipi Rx
+#ifdef _6bit_
+	LT8911EXB_IIC_Write_byte(dev, 0xb0, 0xd0 );                             //enable dither
+#else
+	LT8911EXB_IIC_Write_byte(dev, 0xb0, 0x00 );                             // disable dither
+#endif
+
+	/* mipi Rx Digital */
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0xd0 );                             // Change Reg bank
+	LT8911EXB_IIC_Write_byte(dev, 0x00, _MIPI_data_PN_ + _MIPI_Lane_ % 4 ); // 0: 4 Lane / 1: 1 Lane / 2 : 2 Lane / 3: 3 Lane
+	LT8911EXB_IIC_Write_byte(dev, 0x02, 0x08 );                             //settle
+	LT8911EXB_IIC_Write_byte(dev, 0x03, MIPI_DATA_SEQ );             // default is 0x00
+	LT8911EXB_IIC_Write_byte(dev, 0x08, 0x00 );
+//	LT8911EXB_IIC_Write_byte(dev, 0x0a, 0x12 );               //pcr mode
+
+	LT8911EXB_IIC_Write_byte(dev, 0x0c, 0x80 );                             //fifo position
+	LT8911EXB_IIC_Write_byte(dev, 0x1c, 0x80 );                             //fifo position
+
+	//	hs mode:MIPI行采样;vs mode:MIPI帧采样
+	LT8911EXB_IIC_Write_byte(dev, 0x24, 0x70 );                             // 0x30  [3:0]  line limit	  //pcr mode( de hs vs)
+
+	LT8911EXB_IIC_Write_byte(dev, 0x31, 0x0a );
+
+	/*stage1 hs mode*/
+	LT8911EXB_IIC_Write_byte(dev, 0x25, 0x90 );                             // 0x80		   // line limit
+	LT8911EXB_IIC_Write_byte(dev, 0x2a, 0x3a );                             // 0x04		   // step in limit
+	LT8911EXB_IIC_Write_byte(dev, 0x21, 0x4f );                             // hs_step
+	LT8911EXB_IIC_Write_byte(dev, 0x22, 0xff );
+
+	/*stage2 de mode*/
+	LT8911EXB_IIC_Write_byte(dev, 0x0a, 0x02 );                             //de adjust pre line
+	LT8911EXB_IIC_Write_byte(dev, 0x38, 0x02 );                             //de_threshold 1
+	LT8911EXB_IIC_Write_byte(dev, 0x39, 0x04 );                             //de_threshold 2
+	LT8911EXB_IIC_Write_byte(dev, 0x3a, 0x08 );                             //de_threshold 3
+	LT8911EXB_IIC_Write_byte(dev, 0x3b, 0x10 );                             //de_threshold 4
+
+	LT8911EXB_IIC_Write_byte(dev, 0x3f, 0x04 );                             //de_step 1
+	LT8911EXB_IIC_Write_byte(dev, 0x40, 0x08 );                             //de_step 2
+	LT8911EXB_IIC_Write_byte(dev, 0x41, 0x10 );                             //de_step 3
+	LT8911EXB_IIC_Write_byte(dev, 0x42, 0x60 );                             //de_step 4
+
+	/*stage2 hs mode*/
+	LT8911EXB_IIC_Write_byte(dev, 0x1e, 0x0A );//LT8911EXB_IIC_Write_byte(dev, 0x1e, 0x01 );                             // 0x11
+	LT8911EXB_IIC_Write_byte(dev, 0x23, 0xf0 );                             // 0x80			   //
+
+	LT8911EXB_IIC_Write_byte(dev, 0x2b, 0x80 );                             // 0xa0
+
+#ifdef _Test_Pattern_
+	LT8911EXB_IIC_Write_byte(dev, 0x26, ( pcr_m | 0x80 ) );
+#else
+
+	LT8911EXB_IIC_Write_byte(dev, 0x26, pcr_m );
+
+#endif
+
+	LT8911EXB_MIPI_Video_Timing(dev);         //defualt setting is 1080P
+
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x81 ); // Change Reg bank
+	LT8911EXB_IIC_Write_byte(dev, 0x03, 0x7b ); //PCR reset
+	LT8911EXB_IIC_Write_byte(dev, 0x03, 0xff );
+
+#ifdef EDP_2G7
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x87 );
+	LT8911EXB_IIC_Write_byte(dev, 0x19, 0x31 );
+	LT8911EXB_IIC_Write_byte(dev, 0x1a, 0x36 ); // sync m
+	LT8911EXB_IIC_Write_byte(dev, 0x1b, 0x00 ); // sync_k [7:0]
+	LT8911EXB_IIC_Write_byte(dev, 0x1c, 0x00 ); // sync_k [13:8]
+
+	// txpll Analog
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x82 );
+	LT8911EXB_IIC_Write_byte(dev, 0x09, 0x00 ); // div hardware mode, for ssc.
+
+//	LT8911EXB_IIC_Write_byte(dev, 0x01, 0x18 );// default : 0x18
+	LT8911EXB_IIC_Write_byte(dev, 0x02, 0x42 );
+	LT8911EXB_IIC_Write_byte(dev, 0x03, 0x00 ); // txpll en = 0
+	LT8911EXB_IIC_Write_byte(dev, 0x03, 0x01 ); // txpll en = 1
+//	LT8911EXB_IIC_Write_byte(dev, 0x04, 0x3a );// default : 0x3A
+
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x87 );
+	LT8911EXB_IIC_Write_byte(dev, 0x0c, 0x10 ); // cal en = 0
+
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x81 );
+	LT8911EXB_IIC_Write_byte(dev, 0x09, 0xfc );
+	LT8911EXB_IIC_Write_byte(dev, 0x09, 0xfd );
+
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x87 );
+	LT8911EXB_IIC_Write_byte(dev, 0x0c, 0x11 ); // cal en = 1
+
+	// ssc
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x87 );
+	LT8911EXB_IIC_Write_byte(dev, 0x13, 0x83 );
+	LT8911EXB_IIC_Write_byte(dev, 0x14, 0x41 );
+	LT8911EXB_IIC_Write_byte(dev, 0x16, 0x0a );
+	LT8911EXB_IIC_Write_byte(dev, 0x18, 0x0a );
+	LT8911EXB_IIC_Write_byte(dev, 0x19, 0x33 );
+#endif
+
+#ifdef _eDP_1G62_
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x87 );
+	LT8911EXB_IIC_Write_byte(dev, 0x19, 0x31 );
+	LT8911EXB_IIC_Write_byte(dev, 0x1a, 0x20 ); // sync m
+	LT8911EXB_IIC_Write_byte(dev, 0x1b, 0x19 ); // sync_k [7:0]
+	LT8911EXB_IIC_Write_byte(dev, 0x1c, 0x99 ); // sync_k [13:8]
+
+	// txpll Analog
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x82 );
+	LT8911EXB_IIC_Write_byte(dev, 0x09, 0x00 ); // div hardware mode, for ssc.
+	//	LT8911EXB_IIC_Write_byte(dev, 0x01, 0x18 );// default : 0x18
+	LT8911EXB_IIC_Write_byte(dev, 0x02, 0x42 );
+	LT8911EXB_IIC_Write_byte(dev, 0x03, 0x00 ); // txpll en = 0
+	LT8911EXB_IIC_Write_byte(dev, 0x03, 0x01 ); // txpll en = 1
+	//	LT8911EXB_IIC_Write_byte(dev, 0x04, 0x3a );// default : 0x3A
+
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x87 );
+	LT8911EXB_IIC_Write_byte(dev, 0x0c, 0x10 ); // cal en = 0
+
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x81 );
+	LT8911EXB_IIC_Write_byte(dev, 0x09, 0xfc );
+	LT8911EXB_IIC_Write_byte(dev, 0x09, 0xfd );
+
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x87 );
+	LT8911EXB_IIC_Write_byte(dev, 0x0c, 0x11 ); // cal en = 1
+
+	//ssc
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x87 );
+	LT8911EXB_IIC_Write_byte(dev, 0x13, 0x83 );
+	LT8911EXB_IIC_Write_byte(dev, 0x14, 0x41 );
+	LT8911EXB_IIC_Write_byte(dev, 0x16, 0x0a );
+	LT8911EXB_IIC_Write_byte(dev, 0x18, 0x0a );
+	LT8911EXB_IIC_Write_byte(dev, 0x19, 0x33 );
+#endif
+
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x87 );
+
+	for( i = 0; i < 5; i++ ) //Check Tx PLL
+	{
+		mdelay( 5 );
+		if( LT8911EXB_IIC_Read_byte(dev, 0x37 ) & 0x02 )
+		{
+			debug( "\r\nLT8911 tx pll locked" );
+			break;
+		}else
+		{
+			debug( "\r\nLT8911 tx pll unlocked" );
+			LT8911EXB_IIC_Write_byte(dev, 0xff, 0x81 );
+			LT8911EXB_IIC_Write_byte(dev, 0x09, 0xfc );
+			LT8911EXB_IIC_Write_byte(dev, 0x09, 0xfd );
+
+			LT8911EXB_IIC_Write_byte(dev, 0xff, 0x87 );
+			LT8911EXB_IIC_Write_byte(dev, 0x0c, 0x10 );
+			LT8911EXB_IIC_Write_byte(dev, 0x0c, 0x11 );
+		}
+	}
+
+	// AUX reset
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x81 ); // Change Reg bank
+	LT8911EXB_IIC_Write_byte(dev, 0x07, 0xfe );
+	LT8911EXB_IIC_Write_byte(dev, 0x07, 0xff );
+	LT8911EXB_IIC_Write_byte(dev, 0x0a, 0xfc );
+	LT8911EXB_IIC_Write_byte(dev, 0x0a, 0xfe );
+
+	/* tx phy */
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x82 ); // Change Reg bank
+	LT8911EXB_IIC_Write_byte(dev, 0x11, 0x00 );
+	LT8911EXB_IIC_Write_byte(dev, 0x13, 0x10 );
+	LT8911EXB_IIC_Write_byte(dev, 0x14, 0x0c );
+	LT8911EXB_IIC_Write_byte(dev, 0x14, 0x08 );
+	LT8911EXB_IIC_Write_byte(dev, 0x13, 0x20 );
+
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x82 ); // Change Reg bank
+	LT8911EXB_IIC_Write_byte(dev, 0x0e, 0x35 );
+//	LT8911EXB_IIC_Write_byte(dev, 0x12, 0xff );
+//	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x80 );
+//	LT8911EXB_IIC_Write_byte(dev, 0x40, 0x22 );
+
+	/*eDP Tx Digital */
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0xa8 ); // Change Reg bank
+
+#ifdef _Test_Pattern_
+
+	LT8911EXB_IIC_Write_byte(dev, 0x24, 0x50 ); // bit2 ~ bit 0 : test panttern image mode
+	LT8911EXB_IIC_Write_byte(dev, 0x25, 0x70 ); // bit6 ~ bit 4 : test Pattern color
+	LT8911EXB_IIC_Write_byte(dev, 0x27, 0x50 ); //0x50:Pattern; 0x10:mipi video
+
+//	LT8911EXB_IIC_Write_byte(dev, 0x2d, 0x00 ); //  pure color setting
+//	LT8911EXB_IIC_Write_byte(dev, 0x2d, 0x84 ); // black color
+	LT8911EXB_IIC_Write_byte(dev, 0x2d, 0x88 ); //  block
+
+#else
+	LT8911EXB_IIC_Write_byte(dev, 0x27, 0x10 ); //0x50:Pattern; 0x10:mipi video
+#endif
+
+#ifdef _6bit_
+	LT8911EXB_IIC_Write_byte(dev, 0x17, 0x00 );
+	LT8911EXB_IIC_Write_byte(dev, 0x18, 0x00 );
+#else
+	// _8bit_
+	LT8911EXB_IIC_Write_byte(dev, 0x17, 0x10 );
+	LT8911EXB_IIC_Write_byte(dev, 0x18, 0x20 );
+#endif
+
+	/* nvid */
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0xa0 );                             // Change Reg bank
+	LT8911EXB_IIC_Write_byte(dev, 0x00, (u8)( Nvid_Val[_Nvid] / 256 ) );    // 0x08
+	LT8911EXB_IIC_Write_byte(dev, 0x01, (u8)( Nvid_Val[_Nvid] % 256 ) );    // 0x00
+}
+
+void LT8911EXB_video_check(struct udevice *dev)
+{
+	u32 reg = 0x00;
+	/* mipi byte clk check*/
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x85 );     // Change Reg bank
+	LT8911EXB_IIC_Write_byte(dev, 0x1d, 0x00 );     //FM select byte clk
+	LT8911EXB_IIC_Write_byte(dev, 0x40, 0xf7 );
+	LT8911EXB_IIC_Write_byte(dev, 0x41, 0x30 );
+
+	//#ifdef _eDP_scramble_
+	if( ScrambleMode )
+	{
+		LT8911EXB_IIC_Write_byte(dev, 0xa1, 0x82 ); //eDP scramble mode;
+	}
+	//#else
+	else
+	{
+		LT8911EXB_IIC_Write_byte(dev, 0xa1, 0x02 ); // DP scramble mode;
+	}
+	//#endif
+
+//	LT8911EXB_IIC_Write_byte(dev, 0x17, 0xf0 ); // 0xf0:Close scramble; 0xD0 : Open scramble
+
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x81 );
+	LT8911EXB_IIC_Write_byte(dev, 0x09, 0x7d );
+	LT8911EXB_IIC_Write_byte(dev, 0x09, 0xfd );
+
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x85 );
+	mdelay(20);
+	if( LT8911EXB_IIC_Read_byte(dev, 0x50 ) == 0x03 )
+	{
+		reg	   = LT8911EXB_IIC_Read_byte(dev, 0x4d );
+		reg	   = reg * 256 + LT8911EXB_IIC_Read_byte(dev, 0x4e );
+		reg	   = reg * 256 + LT8911EXB_IIC_Read_byte(dev, 0x4f );
+
+		debug( "\r\nvideo check: mipi byteclk = %d ", reg ); // mipi byteclk = reg * 1000
+		debug( "\r\nvideo check: mipi bitrate = %d ", reg * 8 ); // mipi byteclk = reg * 1000
+		debug( "\r\nvideo check: mipi pclk = %d ", reg /3 * 4 * 1000 ); // mipi byteclk = reg * 1000
+	}else
+	{
+		debug( "\r\nvideo check: mipi clk unstable" );
+	}
+
+	/* mipi vtotal check*/
+	reg	   = LT8911EXB_IIC_Read_byte(dev, 0x76 );
+	reg	   = reg * 256 + LT8911EXB_IIC_Read_byte(dev, 0x77 );
+
+	debug( "\r\nvideo check: Vtotal =  %d", reg);
+
+	/* mipi word count check*/
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0xd0 );
+	reg	   = LT8911EXB_IIC_Read_byte(dev, 0x82 );
+	reg	   = reg * 256 + LT8911EXB_IIC_Read_byte(dev, 0x83 );
+	reg	   = reg / 3;
+
+	debug( "\r\nvideo check: Hact(word counter) =  %d", reg);
+
+	/* mipi Vact check*/
+	reg	   = LT8911EXB_IIC_Read_byte(dev, 0x85 );
+	reg	   = reg * 256 + LT8911EXB_IIC_Read_byte(dev, 0x86 );
+
+	debug( "\r\nvideo check: Vact = %d", reg);
+}
+
+void DpcdWrite(struct udevice *dev, u32 Address, u8 Data )
+{
+	/***************************
+	   注意大小端的问题!
+	   这里默认是大端模式
+
+	   Pay attention to the Big-Endian and Little-Endian!
+	   The default mode is Big-Endian here.
+
+	 ****************************/
+	u8	AddressH   = 0x0f & ( Address >> 16 );
+	u8	AddressM   = 0xff & ( Address >> 8 );
+	u8	AddressL   = 0xff & Address;
+
+	u8	reg;
+
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0xa6 );
+	LT8911EXB_IIC_Write_byte(dev, 0x2b, ( 0x80 | AddressH ) );  //CMD
+	LT8911EXB_IIC_Write_byte(dev, 0x2b, AddressM );             //addr[15:8]
+	LT8911EXB_IIC_Write_byte(dev, 0x2b, AddressL );             //addr[7:0]
+	LT8911EXB_IIC_Write_byte(dev, 0x2b, 0x00 );                 //data lenth
+	LT8911EXB_IIC_Write_byte(dev, 0x2b, Data );                 //data
+	LT8911EXB_IIC_Write_byte(dev, 0x2c, 0x00 );                 //start Aux
+
+	mdelay( 20 );                                         //more than 10ms
+	reg = LT8911EXB_IIC_Read_byte(dev, 0x25 );
+
+	if( ( reg & 0x0f ) == 0x0c )
+	{
+		return;
+	}
+}
+
+u8 DpcdRead(struct udevice *dev, u32 Address )
+{
+	/***************************
+	   注意大小端的问题!
+	   这里默认是大端模式
+
+	   Pay attention to the Big-Endian and Little-Endian!
+	   The default mode is Big-Endian here.
+
+	 ****************************/
+
+	u8	DpcdValue  = 0x00;
+	u8	AddressH   = 0x0f & ( Address >> 16 );
+	u8	AddressM   = 0xff & ( Address >> 8 );
+	u8	AddressL   = 0xff & Address;
+	u8	reg;
+
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0xac );
+	LT8911EXB_IIC_Write_byte(dev, 0x00, 0x20 );                 //Soft Link train
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0xa6 );
+	LT8911EXB_IIC_Write_byte(dev, 0x2a, 0x01 );
+
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0xa6 );
+	LT8911EXB_IIC_Write_byte(dev, 0x2b, ( 0x90 | AddressH ) );  //CMD
+	LT8911EXB_IIC_Write_byte(dev, 0x2b, AddressM );             //addr[15:8]
+	LT8911EXB_IIC_Write_byte(dev, 0x2b, AddressL );             //addr[7:0]
+	LT8911EXB_IIC_Write_byte(dev, 0x2b, 0x00 );                 //data lenth
+	LT8911EXB_IIC_Write_byte(dev, 0x2c, 0x00 );                 //start Aux read edid
+
+	mdelay( 50 );                                         //more than 10ms
+	reg = LT8911EXB_IIC_Read_byte(dev, 0x25 );
+	if( ( reg & 0x0f ) == 0x0c )
+	{
+		if( LT8911EXB_IIC_Read_byte(dev, 0x39 ) == 0x22 )
+		{
+			LT8911EXB_IIC_Read_byte(dev, 0x2b );
+			DpcdValue = LT8911EXB_IIC_Read_byte(dev, 0x2b );
+		}
+
+
+		/*
+		   else
+		   {
+		   //	goto no_reply;
+		   //	DpcdValue = 0xff;
+		   return DpcdValue;
+		   }//*/
+	}else
+	{
+		LT8911EXB_IIC_Write_byte(dev, 0xff, 0x81 ); // change bank
+		LT8911EXB_IIC_Write_byte(dev, 0x07, 0xfe );
+		LT8911EXB_IIC_Write_byte(dev, 0x07, 0xff );
+		LT8911EXB_IIC_Write_byte(dev, 0x0a, 0xfc );
+		LT8911EXB_IIC_Write_byte(dev, 0x0a, 0xfe );
+	}
+
+	return DpcdValue;
+}
+
+void LT8911EX_link_train(struct udevice *dev)
+{
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x81 );
+	LT8911EXB_IIC_Write_byte(dev, 0x06, 0xdf ); // rset VID TX
+	LT8911EXB_IIC_Write_byte(dev, 0x06, 0xff );
+
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x85 );
+
+	if( ScrambleMode )
+	{
+		LT8911EXB_IIC_Write_byte(dev, 0xa1, 0x82 ); // eDP scramble mode;
+		LT8911EXB_IIC_Write_byte(dev, 0xff, 0xac );
+		LT8911EXB_IIC_Write_byte(dev, 0x00, 0x20 ); //Soft Link train
+		LT8911EXB_IIC_Write_byte(dev, 0xff, 0xa6 );
+		LT8911EXB_IIC_Write_byte(dev, 0x2a, 0x01 );
+
+		DpcdWrite(dev, 0x010a, 0x01 );
+		mdelay(10);
+		DpcdWrite(dev, 0x0102, 0x00 );
+		mdelay(10);
+		DpcdWrite(dev, 0x010a, 0x01 );
+
+		mdelay(10);
+		//*/
+	}
+//#else
+	else
+	{
+		LT8911EXB_IIC_Write_byte(dev, 0xa1, 0x02 ); // DP scramble mode;
+	}
+//#endif
+
+	/* Aux setup */
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0xac );
+	LT8911EXB_IIC_Write_byte(dev, 0x00, 0x60 );     //Soft Link train
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0xa6 );
+	LT8911EXB_IIC_Write_byte(dev, 0x2a, 0x00 );
+
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x81 );
+	LT8911EXB_IIC_Write_byte(dev, 0x07, 0xfe );
+	LT8911EXB_IIC_Write_byte(dev, 0x07, 0xff );
+	LT8911EXB_IIC_Write_byte(dev, 0x0a, 0xfc );
+	LT8911EXB_IIC_Write_byte(dev, 0x0a, 0xfe );
+
+	/* link train */
+
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x85 );
+	LT8911EXB_IIC_Write_byte(dev, 0x1a, eDP_lane );
+
+#ifdef LINK_TRAIN_ENABLE
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0xac );
+	LT8911EXB_IIC_Write_byte(dev, 0x00, 0x64 );
+	LT8911EXB_IIC_Write_byte(dev, 0x01, 0x0a );
+	LT8911EXB_IIC_Write_byte(dev, 0x0c, 0x85 );
+	LT8911EXB_IIC_Write_byte(dev, 0x0c, 0xc5 );
+#else
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0xac );
+	LT8911EXB_IIC_Write_byte(dev, 0x00, 0x00 );
+	LT8911EXB_IIC_Write_byte(dev, 0x01, 0x0a );
+	LT8911EXB_IIC_Write_byte(dev, 0x14, 0x80 );
+	LT8911EXB_IIC_Write_byte(dev, 0x14, 0x81 );
+	mdelay( 50 );
+	LT8911EXB_IIC_Write_byte(dev, 0x14, 0x84 );
+	mdelay( 50 );
+	LT8911EXB_IIC_Write_byte(dev, 0x14, 0xc0 );
+#endif
+}
+
+static int LT8911EX_link_train_result(struct udevice *dev)
+{
+	u8 i, reg;
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0xac );
+	for( i = 0; i < 10; i++ )
+	{
+		reg = LT8911EXB_IIC_Read_byte(dev, 0x82 );
+		//  Debug_DispStrNum( "\r\n0x82 = ", reg );
+		if( reg & 0x20 )
+		{
+			if( ( reg & 0x1f ) == 0x1e )
+			{
+				debug( "\r\nLink train success, 0x82 = 0x%x", reg );
+				debug( "\r\npanel link rate: 0x%x", LT8911EXB_IIC_Read_byte(dev, 0x83 ) );
+				debug( "\r\npanel link count: 0x%x", LT8911EXB_IIC_Read_byte(dev, 0x84 ) );
+				mdelay( 10 );
+				return 0;
+			} else{
+				debug( "\r\nLink train fail, 0x82 = 0x%x", reg );
+				debug( "\r\npanel link rate: 0x%x", LT8911EXB_IIC_Read_byte(dev, 0x83 ) );
+				debug( "\r\npanel link count: 0x%x", LT8911EXB_IIC_Read_byte(dev, 0x84 ) );
+				mdelay( 10 );
+				return -1;
+			}
+
+		}
+		else{
+			debug( "\r\nlink trian on going..." );
+			mdelay( 1 );
+		}
+		
+	}
+	return -1;
+}
+
+void LT8911EXB_MainLoop(struct udevice *dev)
+{
+#ifndef _Test_Pattern_
+	u16 reg;
+
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x85 );
+	//LT8911EXB_IIC_Write_byte(0x1d,0x00); //FM select byte clk
+	//LT8911EXB_IIC_Write_byte(0x40,0xf7);
+	//LT8911EXB_IIC_Write_byte(0x41,0x30);
+
+	if( ScrambleMode )
+	{
+		LT8911EXB_IIC_Write_byte(dev, 0xa1, 0x82 ); //
+	}else
+	{
+		LT8911EXB_IIC_Write_byte(dev, 0xa1, 0x02 ); //
+	}
+
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x81 );     //video check rst
+	LT8911EXB_IIC_Write_byte(dev, 0x09, 0x7d );
+	LT8911EXB_IIC_Write_byte(dev, 0x09, 0xfd );
+	mdelay(10);
+
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x85 );
+	reg	   = LT8911EXB_IIC_Read_byte(dev, 0x76 );
+	reg	   = reg * 256 + LT8911EXB_IIC_Read_byte(dev, 0x77 );
+
+//	if( reg == MIPI_Timing[vtotal] )
+	if( ( reg > ( MIPI_Timing[vtotal] - 5 ) ) && ( reg < ( MIPI_Timing[vtotal] + 5 ) ) )
+	{
+		if( !flag_mipi_on )
+		{
+			LT8911EXB_IIC_Write_byte(dev, 0xff, 0x81 ); //PCR reset
+			LT8911EXB_IIC_Write_byte(dev, 0x03, 0x7b );
+			LT8911EXB_IIC_Write_byte(dev, 0x03, 0xff );
+
+			LT8911EXB_IIC_Write_byte(dev, 0xff, 0xa8 );
+			LT8911EXB_IIC_Write_byte(dev, 0x2d, 0x88 );
+			flag_mipi_on = 1;
+			debug( "\r\nPCR reset" );
+		}
+	}else
+	{
+		LT8911EXB_IIC_Write_byte(dev, 0xff, 0xa8 );
+		LT8911EXB_IIC_Write_byte(dev, 0x2d, 0x8c ); //edp output idle pattern;
+		flag_mipi_on = 0;
+	}
+
+#ifdef UART_DEBUG
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0xd0 );
+	reg = LT8911EXB_IIC_Read_byte(dev, 0x87 );
+//	reg	   = reg * 256 + HDMI_ReadI2C_Byte( 0x77 );
+	if( reg & 0x10 )
+	{
+		debug( "\r\nPCR Clock stable" );
+	}else
+	{
+		debug( "\r\nPCR Clock unstable" );
+	}
+	debug( "\r\n " );
+#endif
+
+#endif
+}
+
+enum
+{
+	_Level0_ = 0,                                               // 27.8 mA  0x83/0x00
+	_Level1_,                                                   // 26.2 mA  0x82/0xe0
+	_Level2_,                                                   // 24.6 mA  0x82/0xc0
+	_Level3_,                                                   // 23 mA    0x82/0xa0
+	_Level4_,                                                   // 21.4 mA  0x82/0x80
+	_Level5_,                                                   // 18.2 mA  0x82/0x40
+	_Level6_,                                                   // 16.6 mA  0x82/0x20
+	_Level7_,                                                   // 15mA     0x82/0x00  // level 1
+	_Level8_,                                                   // 12.8mA   0x81/0x00  // level 2
+	_Level9_,                                                   // 11.2mA   0x80/0xe0  // level 3
+	_Level10_,                                                  // 9.6mA    0x80/0xc0  // level 4
+	_Level11_,                                                  // 8mA      0x80/0xa0  // level 5
+	_Level12_,                                                  // 6mA      0x80/0x80  // level 6
+};
+
+u8	Swing_Setting1[] = { 0x83, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x81, 0x80, 0x80, 0x80, 0x80 };
+u8	Swing_Setting2[] = { 0x00, 0xe0, 0xc0, 0xa0, 0x80, 0x40, 0x20, 0x00, 0x00, 0xe0, 0xc0, 0xa0, 0x80 };
+
+u8	Level = _Level7_;   
+
+void LT8911EX_TxSwingPreSet(struct udevice *dev)
+{
+	LT8911EXB_IIC_Write_byte(dev, 0xFF, 0x82 );
+	LT8911EXB_IIC_Write_byte(dev, 0x22, Swing_Setting1[Level] );    //lane 0 tap0
+	LT8911EXB_IIC_Write_byte(dev, 0x23, Swing_Setting2[Level] );
+	LT8911EXB_IIC_Write_byte(dev, 0x24, 0x80 );                     //lane 0 tap1
+	LT8911EXB_IIC_Write_byte(dev, 0x25, 0x00 );
+
+#if ( eDP_lane == 2 )
+	LT8911EXB_IIC_Write_byte(dev, 0x26, Swing_Setting1[Level] );    //lane 1 tap0
+	LT8911EXB_IIC_Write_byte(dev, 0x27, Swing_Setting2[Level] );
+	LT8911EXB_IIC_Write_byte(dev, 0x28, 0x80 );                     //lane 1 tap1
+	LT8911EXB_IIC_Write_byte(dev, 0x29, 0x00 );
+#endif
+}
+
+void PCR_Status(struct udevice *dev)                                         // for debug
+{
+#ifdef UART_DEBUG
+	u8 reg;
+
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0xd0 );
+	reg = LT8911EXB_IIC_Read_byte(dev, 0x87 );
+
+	debug( "\r\nReg0xD087 =	");
+	debug( " 0x%x ", reg );
+	debug( "\r\n " );
+	if( reg & 0x10 )
+	{
+		debug( "\r\nPCR Clock stable" );
+	}else
+	{
+		debug( "\r\nPCR Clock unstable" );
+	}
+	debug( "\r\n " );
+#endif
+}
+
+void LT8911_MainLoop(struct udevice *dev)
+{
+	u16 reg, H_act, V_act;
+//	bool	flag_mipi_on = 0;
+
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x85 );
+
+	if( ScrambleMode )
+	{
+		LT8911EXB_IIC_Write_byte(dev, 0xa1, 0x82 ); //video check from mipi
+	}else
+	{
+		LT8911EXB_IIC_Write_byte(dev, 0xa1, 0x02 );
+	}
+
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x81 );     //video check rst
+	LT8911EXB_IIC_Write_byte(dev, 0x09, 0x7d );
+	LT8911EXB_IIC_Write_byte(dev, 0x09, 0xfd );
+	mdelay(10);
+
+	/* mipi word count check*/
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0xd0 );
+	reg	   = LT8911EXB_IIC_Read_byte(dev, 0x82 );
+	reg	   = reg * 256 + LT8911EXB_IIC_Read_byte(dev, 0x83 );
+	H_act  = reg / 3;
+
+#ifdef UART_DEBUG
+
+	debug( "\r\nHact(word counter) =  %d\r\n", H_act ); // H active = word counter / 3
+
+#endif
+
+	/* mipi Vact check*/
+	reg	   = LT8911EXB_IIC_Read_byte(dev, 0x85 );
+	V_act  = reg * 256 + LT8911EXB_IIC_Read_byte(dev, 0x86 );
+
+#ifdef UART_DEBUG
+
+	debug( "\r\nVact = %d\r\n ",V_act );
+#endif
+
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0x85 );
+	reg	   = LT8911EXB_IIC_Read_byte(dev, 0x76 );
+	reg	   = reg * 256 + LT8911EXB_IIC_Read_byte(dev, 0x77 );
+
+#ifdef UART_DEBUG
+	debug( "\r\nvideo check: Vtotal = %d\r\n ",reg );
+#endif
+
+//	if( reg == MIPI_Timing[vtotal] )
+	if( ( reg > ( MIPI_Timing[vtotal] - 5 ) ) && ( reg < ( MIPI_Timing[vtotal] + 5 ) ) )
+	{
+		if( !flag_mipi_on )
+		{
+			LT8911EXB_IIC_Write_byte(dev, 0xff, 0x81 ); //PCR reset
+			LT8911EXB_IIC_Write_byte(dev, 0x03, 0x7b );
+			LT8911EXB_IIC_Write_byte(dev, 0x03, 0xff );
+
+			LT8911EXB_IIC_Write_byte(dev, 0xff, 0xa8 );
+			LT8911EXB_IIC_Write_byte(dev, 0x2d, 0x88 );
+			flag_mipi_on = 1;
+#ifdef UART_DEBUG
+			debug( "\r\nPCR reset" );
+#endif
+		}
+	}else
+	{
+		LT8911EXB_IIC_Write_byte(dev, 0xff, 0xa8 );
+		LT8911EXB_IIC_Write_byte(dev, 0x2d, 0x8c ); //edp output idle pattern;
+		flag_mipi_on = 0;
+	}
+
+#ifdef UART_DEBUG
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0xd0 );
+	reg = LT8911EXB_IIC_Read_byte(dev, 0x87 );
+
+	debug( "\r\nReg0xD087 = 0x%x\r\n ",reg );
+
+	if( reg & 0x10 )
+	{
+		debug( "\r\nPCR Clock stable" );
+	}else
+	{
+		debug( "\r\nPCR Clock unstable" );
+	}
+	debug( "\r\n " );
+#endif
+}
+
+/***********************************************************/
+
+void LT8911EXB_LinkTrainResultCheck(struct udevice *dev)
+{
+#ifdef LINK_TRAIN_ENABLE
+	u8	i;
+	u8	val;
+	//int ret;
+
+	LT8911EXB_IIC_Write_byte(dev, 0xff, 0xac );
+	for( i = 0; i < 10; i++ )
+	{
+		val = LT8911EXB_IIC_Read_byte(dev, 0x82 );
+		if( val & 0x20 )
+		{
+			if( ( val & 0x1f ) == 0x1e )
+			{
+#ifdef UART_DEBUG
+				//   debug("\r\nLT8911_LinkTrainResultCheck: edp link train successed: 0x%bx", val);
+				debug( "\r\nedp link train successed: 0x%x", val );
+#endif
+				return;
+			}else
+			{
+#ifdef UART_DEBUG
+				//debug("\r\nLT8911_LinkTrainResultCheck: edp link train failed: 0x%bx", val);
+				debug( "\r\nedp link train failed: 0x%x", val );
+#endif
+				LT8911EXB_IIC_Write_byte(dev, 0xff, 0xac );
+				LT8911EXB_IIC_Write_byte(dev, 0x00, 0x00 );
+				LT8911EXB_IIC_Write_byte(dev, 0x01, 0x0a );
+				LT8911EXB_IIC_Write_byte(dev, 0x14, 0x80 );
+				LT8911EXB_IIC_Write_byte(dev, 0x14, 0x81 );
+				mdelay(10);
+				LT8911EXB_IIC_Write_byte(dev, 0x14, 0x84 );
+				mdelay(10);
+				LT8911EXB_IIC_Write_byte(dev, 0x14, 0xc0 );
+				//debug("\r\nLT8911_LinkTrainResultCheck: Enable eDP video output while linktrian fail");
+			}
+
+#ifdef UART_DEBUG
+
+			val = LT8911EXB_IIC_Read_byte(dev, 0x83 );
+			//debug("\r\nLT8911_LinkTrainResultCheck: panel link rate: 0x%bx",val);
+			debug( "\r\npanel link rate: 0x%x", val );
+			val = LT8911EXB_IIC_Read_byte(dev, 0x84 );
+			//debug("\r\nLT8911_LinkTrainResultCheck: panel link count: 0x%bx",val);
+			debug( "\r\npanel link count:0x%x ", val );
+#endif
+			mdelay( 10 ); // return;
+		}else
+		{
+			//debug("\r\nLT8911_LinkTrainResultCheck: link trian on going...");
+			mdelay( 10 );
+		}
+	}
+#endif
+}
+
+static int edp_panel_enable_backlight(struct udevice *dev)
+{
+	struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+	struct mipi_dsi_device *device = plat->device;
+	int ret;
+
+	debug("\r\nedp_panel_enable_backlight\r\n");
+
+	ret = mipi_dsi_attach(device);
+	if (ret < 0)
+		return ret;
+	Reset_LT8911EXB(dev);     // 先Reset LT8911EXB ,用GPIO 先拉低LT8911EXB的复位脚 100ms左右,再拉高,保持100ms。
+
+	LT8911EX_ChipID(dev);     // read Chip ID
+
+	LT8911EXB_eDP_Video_cfg(dev);
+	
+	LT8911EXB_init(dev);
+
+	ScrambleMode = 0;
+	
+	LT8911EX_TxSwingPreSet(dev);
+
+	LT8911EX_link_train(dev);
+
+	LT8911EXB_LinkTrainResultCheck(dev);
+//======================================//
+	ret = LT8911EX_link_train_result(dev);	// for debug
+	if (ret < 0)
+		return ret;
+
+	LT8911EXB_video_check(dev);		// just for Check MIPI Input
+
+	debug("\r\nDpcdRead(0x0202) = 0x%x\r\n",DpcdRead(dev,0x0202));
+
+	PCR_Status(dev);					// just for Check PCR CLK
+
+	return 0;
+}
+
+static int edp_panel_get_display_timing(struct udevice *dev,
+					    struct display_timing *timings)
+{
+	memcpy(timings, &default_timing, sizeof(*timings));
+	return 0;
+}
+
+static int edp_panel_of_to_plat(struct udevice *dev)
+{
+	return 0;
+}
+
+static int edp_panel_probe(struct udevice *dev)
+{
+	struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+	struct edp_panel_priv *priv = dev_get_priv(dev);
+	u8 regval;
+
+	/* fill characteristics of DSI data link */
+	plat->lanes = 4;
+	plat->format = MIPI_DSI_FMT_RGB888;
+	plat->mode_flags = MIPI_DSI_MODE_VIDEO |
+			   MIPI_DSI_MODE_VIDEO_BURST |
+			   MIPI_DSI_MODE_LPM;
+
+	priv->reset_gpio = devm_gpiod_get_optional(dev, "reset",
+						GPIOD_IS_IN);
+	if (IS_ERR(priv->reset_gpio)) {
+		pr_err("Failed get reset gpio41\n");
+		return PTR_ERR(priv->reset_gpio);
+	}
+
+	priv->pwm_gpio = devm_gpiod_get_optional(dev, "pwm",
+						GPIOD_IS_OUT);
+	if (IS_ERR(priv->pwm_gpio)) {
+		pr_err("Failed get power gpio33\n");
+		return PTR_ERR(priv->pwm_gpio);
+	}
+
+	priv->bl_gpio = devm_gpiod_get_optional(dev, "bl",
+						GPIOD_IS_OUT);
+	if (IS_ERR(priv->bl_gpio)) {
+		pr_err("Failed get bl\n");
+		return PTR_ERR(priv->bl_gpio);
+	}
+
+	LT8911EXB_init(dev);
+	regval = DpcdRead(dev, 0x0101);
+	debug("0x0101 DpcdRead regval = 0x%x\n", regval);
+	if (regval == 0x00 || regval == 0xff ){
+		pr_err("no screen connected\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static const struct panel_ops edp_panel_ops = {
+	.enable_backlight = edp_panel_enable_backlight,
+	.get_display_timing = edp_panel_get_display_timing,
+};
+
+static const struct udevice_id edp_panel_ids[] = {
+	{ .compatible = "lontium,lt8911exb" },
+	{ }
+};
+
+U_BOOT_DRIVER(edp_panel) = {
+	.name			  = "edp_panel",
+	.id			  	  = UCLASS_PANEL,
+	.of_match		  = edp_panel_ids,
+	.ops			  = &edp_panel_ops,
+	.of_to_plat	      = edp_panel_of_to_plat,
+	.probe			  = edp_panel_probe,
+	.plat_auto	      = sizeof(struct mipi_dsi_panel_plat),
+	.priv_auto	      = sizeof(struct edp_panel_priv),
+};

+ 24 - 9
drivers/video/raydium-rm68200-starfive.c → drivers/video/starfive_seeed_panel.c

@@ -4,8 +4,8 @@
  * Author(s): Yannick Fertre <yannick.fertre@st.com> for STMicroelectronics.
  *            Philippe Cornu <philippe.cornu@st.com> for STMicroelectronics.
  *
- * This rm68200 panel driver is inspired from the Linux Kernel driver
- * drivers/gpu/drm/panel/panel-raydium-rm68200.c.
+ * This seeed panel driver is inspired from the Linux Kernel driver
+ * drivers/gpu/drm/panel/panel-raydium-seeed.c.
  */
 #include <common.h>
 #include <backlight.h>
@@ -145,15 +145,16 @@ enum REG_ADDR {
 /* Chip/Rev Registers */
 #define IDREG 0x04A0
 
-/* Debug Registers */
+/* printf Registers */
 #define WCMDQUEUE 0x0500
 #define RCMDQUEUE 0x0504
 
 
-struct rm68200_panel_priv {
+struct seeed_panel_priv {
 	struct udevice *reg;
 	struct udevice *backlight;
-	struct gpio_desc reset;
+	struct gpio_desc *sel_gpio;   //select
+
 };
 
 static const struct display_timing default_timing = {
@@ -292,6 +293,9 @@ static int rm68200_panel_of_to_plat(struct udevice *dev)
 static int rm68200_panel_probe(struct udevice *dev)
 {
 	struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_DEVKITS)
+	struct seeed_panel_priv *priv = dev_get_priv(dev);
+#endif
 
 	u8 reg_value = 0;
 
@@ -315,6 +319,17 @@ static int rm68200_panel_probe(struct udevice *dev)
 		   return -ENODEV;
 	}
 
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_DEVKITS)
+	priv->sel_gpio = devm_gpiod_get_optional(dev, "sel", GPIOD_IS_OUT);
+
+	if (IS_ERR(priv->sel_gpio)) {
+		pr_err("Failed get reset sel gpio\n");
+		return PTR_ERR(priv->sel_gpio);
+	}
+
+	dm_gpio_set_value(priv->sel_gpio, 0);
+#endif
+
 	return 0;
 }
 
@@ -324,17 +339,17 @@ static const struct panel_ops rm68200_panel_ops = {
 };
 
 static const struct udevice_id rm68200_panel_ids[] = {
-	{ .compatible = "raydium,rm68200" },
+	{ .compatible = "starfive,seeed" },
 	{ }
 };
 
-U_BOOT_DRIVER(rm68200_panel) = {
-	.name			  = "rm68200_panel",
+U_BOOT_DRIVER(seeed_panel) = {
+	.name			  = "seeed_panel",
 	.id			  = UCLASS_PANEL,
 	.of_match		  = rm68200_panel_ids,
 	.ops			  = &rm68200_panel_ops,
 	.of_to_plat	  = rm68200_panel_of_to_plat,
 	.probe			  = rm68200_panel_probe,
 	.plat_auto	= sizeof(struct mipi_dsi_panel_plat),
-	.priv_auto	= sizeof(struct rm68200_panel_priv),
+	.priv_auto	= sizeof(struct seeed_panel_priv),
 };

+ 1 - 1
drivers/video/video-uclass.c

@@ -265,7 +265,7 @@ int video_sync_copy(struct udevice *dev, void *from, void *to)
 		 * frame buffer
 		 */
 		if (offset < -priv->fb_size || offset > 2 * priv->fb_size) {
-#if DEBUG
+#ifdef DEBUG
 			char str[80];
 
 			snprintf(str, sizeof(str),

+ 405 - 0
include/configs/starfive-devkits.h

@@ -0,0 +1,405 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2021 Shanghai StarFive Technology Co., Ltd.
+ * YanHong  Wang <yanhong.wang@starfivetech.com>
+ */
+
+#ifndef _STARFIVE_DEVKITS_H
+#define _STARFIVE_DEVKITS_H
+
+#include <version.h>
+#include <linux/sizes.h>
+
+#ifdef CONFIG_SPL
+
+#define CONFIG_SPL_MAX_SIZE		0x00040000
+#define CONFIG_SPL_BSS_START_ADDR	0x08040000
+#define CONFIG_SPL_BSS_MAX_SIZE		0x00010000
+#define CONFIG_SYS_SPL_MALLOC_START	0x42000000
+#define CONFIG_SYS_SPL_MALLOC_SIZE	0x00800000
+
+#define CONFIG_SPL_STACK		(0x08000000 + 0x00180000 - \
+					GENERATED_GBL_DATA_SIZE)
+
+#define STARFIVE_SPL_BOOT_LOAD_ADDR	0x60000000
+#endif
+
+#define CONFIG_SYS_BOOTM_LEN            SZ_64M
+
+#define CONFIG_SYS_CACHELINE_SIZE 64
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CONFIG_SYS_CBSIZE	1024	/* Console I/O Buffer Size */
+
+/*
+ * Print Buffer Size
+ */
+#define CONFIG_SYS_PBSIZE					\
+	(CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+
+/*
+ * max number of command args
+ */
+#define CONFIG_SYS_MAXARGS	16
+
+/*
+ * Boot Argument Buffer Size
+ */
+#define CONFIG_SYS_BARGSIZE	CONFIG_SYS_CBSIZE
+
+/*
+ * Size of malloc() pool
+ * 512kB is suggested, (CONFIG_ENV_SIZE + 128 * 1024) was not enough
+ */
+#define CONFIG_SYS_MALLOC_LEN		SZ_8M
+
+#define CONFIG_SYS_SDRAM_BASE		0x40000000
+
+/* Init Stack Pointer */
+#define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_SDRAM_BASE + SZ_8M)
+
+#define CONFIG_SYS_LOAD_ADDR		(CONFIG_SYS_SDRAM_BASE + SZ_16M)
+#define CONFIG_STANDALONE_LOAD_ADDR	(CONFIG_SYS_SDRAM_BASE + SZ_16M)
+
+/*
+ * Ethernet
+ */
+#ifdef CONFIG_CMD_NET
+#define CONFIG_DW_ALTDESCRIPTOR
+#define DWC_NET_PHYADDR		0
+#define CONFIG_ARP_TIMEOUT	500
+#define PHY_ANEG_TIMEOUT	8000 /* PHY needs longer aneg time */
+#define CONFIG_NETMASK		255.255.255.0
+#define CONFIG_IPADDR		192.168.120.230
+#define CONFIG_IP_DEFRAG
+#ifndef CONFIG_NET_MAXDEFRAG
+#define CONFIG_NET_MAXDEFRAG	16384
+#endif
+#endif
+
+/* HACK these should have '#if defined (stuff) around them like zynqp*/
+#define BOOT_TARGET_DEVICES(func) func(DHCP, dhcp, na)	func(MMC, mmc, 0)
+
+#include <config_distro_bootcmd.h>
+
+
+#include <environment/distro/sf.h>
+
+#define TYPE_GUID_LOADER1	"5B193300-FC78-40CD-8002-E86C45580B47"
+#define TYPE_GUID_LOADER2	"2E54B353-1271-4842-806F-E436D6AF6985"
+#define TYPE_GUID_SYSTEM	"0FC63DAF-8483-4772-8E79-3D69D8477DE4"
+
+#define CPU_VOL_1020_SET \
+	"cpu_vol_1020_set=" 			\
+	"fdt set /opp-table-0/opp-1500000000 opp-microvolt <1020000>;\0"
+
+#define CPU_VOL_1040_SET \
+	"cpu_vol_1040_set="			\
+	"fdt set /opp-table-0/opp-1500000000 opp-microvolt <1040000>;\0"
+
+#define CPU_VOL_1060_SET \
+	"cpu_vol_1060_set="			\
+	"fdt set /opp-table-0/opp-1500000000 opp-microvolt <1060000>;\0"
+
+#define CPU_SPEED_1250_SET \
+	"cpu_speed_1250_set="			\
+	"fdt rm /opp-table-0/opp-375000000;"	\
+	"fdt rm /opp-table-0/opp-500000000;"	\
+	"fdt rm /opp-table-0/opp-750000000;"	\
+	"fdt rm /opp-table-0/opp-1500000000;\0"
+
+#define CPU_SPEED_1500_SET \
+	"cpu_speed_1500_set="			\
+	"fdt rm /opp-table-0/opp-312500000;"	\
+	"fdt rm /opp-table-0/opp-417000000;"	\
+	"fdt rm /opp-table-0/opp-625000000;"	\
+	"fdt rm /opp-table-0/opp-1250000000;\0"
+
+#define CMA_SIZE_SET \
+	"cma_start=70000000\0"					\
+	"cma_1g=b000000\0"					\
+	"cma_2g=20000000\0"					\
+	"cma_4g=40000000\0"					\
+	"cma_8g=60000000\0"					\
+	"cma_node=/reserved-memory/linux,cma\0" 		\
+	"cma_ddr1g_set="					\
+	"fdt set ${cma_node} size <0x0 0x${cma_1g}>;"		\
+	"fdt set ${cma_node} alloc-ranges <0x0 0x${cma_start} 0x0 0x${cma_1g}>;\0" \
+	"cma_ddr2g_set="					\
+	"fdt set ${cma_node} size <0x0 0x${cma_2g}>;"		\
+	"fdt set ${cma_node} alloc-ranges <0x0 0x${cma_start} 0x0 0x${cma_2g}>;\0" \
+	"cma_ddr4g_set="					\
+	"fdt set ${cma_node} size <0x0 0x${cma_4g}>;"		\
+	"fdt set ${cma_node} alloc-ranges <0x0 0x${cma_start} 0x0 0x${cma_4g}>;\0" \
+	"cma_ddr8g_set="					\
+	"fdt set ${cma_node} size <0x0 0x${cma_8g}>;"		\
+	"fdt set ${cma_node} alloc-ranges <0x0 0x${cma_start} 0x0 0x${cma_8g}>;\0" \
+	"cma_resize="						\
+	"if test ${memory_size} -eq 40000000; then "		\
+		"run cma_ddr1g_set;"				\
+	"elif test ${memory_size} -eq 80000000; then "		\
+		"run cma_ddr2g_set;"				\
+	"elif test ${memory_size} -eq 100000000; then " 	\
+		"run cma_ddr4g_set;"				\
+	"elif test ${memory_size} -ge 200000000; then " 	\
+		"run cma_ddr8g_set;"				\
+	"fi; \0 "
+
+#define CPU_FREQ_VOL_SET \
+	"cpu_vol_set="						\
+	"if test ${cpu_max_vol} = 1000000; then "		\
+		"run cpu_speed_1250_set; "			\
+	"else "							\
+		"run cpu_speed_1500_set; "			\
+		"if test ${cpu_max_vol} = 1060000; then "	\
+			"run cpu_vol_1060_set; "		\
+		"elif test ${cpu_max_vol} = 1020000; then "	\
+			"run cpu_vol_1020_set; "		\
+		"else "						\
+			"run cpu_vol_1040_set; "		\
+		"fi; "						\
+	"fi; \0"
+
+#define DEVKITS_MEM_SET	\
+	"devkits_mem_set="	\
+	"fdt memory ${memory_addr} ${memory_size};" \
+	"run cma_resize; \0"
+
+#define CHIPA_GMAC_SET \
+	"chipa_gmac_set="	\
+	"fdt set /soc/ethernet@16030000/ethernet-phy@0 tx_inverted_10 <0x1>;"	\
+	"fdt set /soc/ethernet@16030000/ethernet-phy@0 tx_inverted_100 <0x1>;"	\
+	"fdt set /soc/ethernet@16030000/ethernet-phy@0 tx_inverted_1000 <0x1>;\0"
+
+#define CHIPA_SET	\
+	"chipa_set="				\
+	"if test ${chip_vision} = B; then "	\
+		"run chipa_gmac_set;"		\
+	"fi; \0"				\
+	"chipa_set_uboot="			\
+	"fdt addr ${fdtcontroladdr};"		\
+	"run chipa_set;\0"			\
+	"chipa_set_linux="			\
+	"fdt addr ${fdt_addr_r};"		\
+	"run devkits_mem_set;"			\
+	"run chipa_set;\0"
+
+#define PARTS_DEFAULT							\
+	"name=loader1,start=17K,size=1M,type=${type_guid_gpt_loader1};" \
+	"name=loader2,size=4MB,type=${type_guid_gpt_loader2};"		\
+	"name=system,size=-,bootable,type=${type_guid_gpt_system};"
+
+#define JH7110_SDK_BOOTENV		\
+	"bootdir=/boot\0"		\
+	"bootpart=3\0"			\
+	"rootpart=4\0"			\
+	"load_sdk_uenv="		\
+		"fatload ${bootdev} ${devnum}:${bootpart} ${loadaddr} ${bootenv_sdk};"	\
+		"env import -t ${loadaddr} ${filesize}; \0"				\
+	"mmc_test_and_boot="				\
+		"if mmc dev ${devnum}; then "	\
+			"echo Try booting from MMC${devnum} ...; "	\
+			"setenv sdev_blk mmcblk${devnum}p${rootpart};"	\
+			"run load_sdk_uenv; run boot2;" \
+		"fi;\0" 						\
+	"bootenv_mmc="					\
+		"setenv bootdev mmc;"			\
+		"if test ${bootmode} = flash; then "	\
+			"for mmc_devnum in ${mmc_devnum_l}; do " \
+				"setenv devnum ${mmc_devnum}; " \
+				"run mmc_test_and_boot;"	\
+			"done;" 				\
+		"fi; "						\
+		"if test ${bootmode} = sd; then "	\
+			"setenv devnum ${sd_devnum};"	\
+			"run mmc_test_and_boot;"	\
+		"fi; "					\
+		"if test ${bootmode} = emmc; then "	\
+			"setenv devnum	${emmc_devnum};"\
+			"run mmc_test_and_boot;"	\
+		"fi; \0"				\
+	"bootenv_nvme=" 				\
+		"if test ${bootmode} = flash; then "	\
+			"for nvme_devnum in ${nvme_devnum_l}; do " \
+				"setenv devnum ${nvme_devnum};" \
+				"if pci enum; then "		\
+					"nvme scan; "		\
+				"fi; "				\
+				"if nvme dev ${devnum}; then "	\
+					"echo Try booting from NVME${devnum} ...; "	\
+					"setenv bootdev nvme;"	\
+					"setenv sdev_blk nvme${devnum}n1p${rootpart};"	\
+					"run load_sdk_uenv; run boot2;" \
+				"fi; "				\
+			"done; "				\
+		"fi; \0"					\
+	"sdk_boot_env=" 		\
+		"for bootdev_s in ${boot_devs}; do "	\
+		"run bootenv_${bootdev_s}; "		\
+		"done;\0"				\
+	"fdtfile=" CONFIG_DEFAULT_FDT_FILE "\0"
+
+#define DEVKITS_SDK_BOOTENV		\
+	"bootenv=uEnv.txt\0"		\
+	"bootenv_sdk=devkits_uEnv.txt\0"\
+	"boot_devs=mmc nvme\0"		\
+	"emmc_devnum=0\0"		\
+	"sd_devnum=1\0" 		\
+	"mmc_devnum_l=1 0\0"		\
+	"nvme_devnum_l=0 0\0"
+
+#define JH7110_DISTRO_BOOTENV	\
+	"bootdir=/boot\0"	\
+	"bootpart=3\0"		\
+	"rootpart=4\0"		\
+	"load_distro_uenv="						\
+		"fatload ${bootdev} ${devnum}:${bootpart} ${loadaddr} /${bootenv}; " \
+		"env import ${loadaddr} ${filesize}; \0" \
+	"fdt_loaddtb="		\
+		"fatload ${bootdev} ${devnum}:${bootpart} ${fdt_addr_r} /dtbs/${fdtfile}; fdt addr ${fdt_addr_r}; \0" \
+	"fdt_sizecheck="	\
+		"fatsize ${bootdev} ${devnum}:${bootpart} /dtbs/${fdtfile}; \0" \
+	"set_fdt_distro="	\
+		"run chipa_set_linux; run cpu_vol_set;" \
+		"fatwrite ${bootdev} ${devnum}:${bootpart} ${fdt_addr_r} /dtbs/${fdtfile} ${filesize}; \0" \
+	"bootcmd_distro="	\
+		"run load_distro_uenv; " \
+		"run fdt_loaddtb; run fdt_sizecheck; run set_fdt_distro; "	\
+		"sysboot ${bootdev} ${devnum}:${bootpart} fat ${scriptaddr} /${boot_syslinux_conf}; \0" \
+	"distro_mmc_test_and_boot="					\
+		"if mmc dev ${devnum}; then "				\
+			"echo Try booting from MMC${devnum} ...; "	\
+			"run bootcmd_distro;"				\
+		"fi;\0" 						\
+	"distro_bootenv_mmc="					\
+		"setenv bootdev mmc;"			\
+		"if test ${bootmode} = flash; then "	\
+			"for mmc_devnum in ${mmc_devnum_l}; do "\
+				"setenv devnum ${mmc_devnum}; " \
+				"run distro_mmc_test_and_boot;" \
+			"done;" 				\
+		"fi; "						\
+		"if test ${bootmode} = sd; then "	\
+			"setenv devnum ${sd_devnum};"	\
+			"run distro_mmc_test_and_boot;" \
+		"fi; "					\
+		"if test ${bootmode} = emmc; then "	\
+			"setenv devnum	${emmc_devnum};"\
+			"run distro_mmc_test_and_boot;" \
+		"fi; \0"				\
+	"distro_bootenv_nvme="				\
+		"if test ${bootmode} = flash; then "	\
+			"for nvme_devnum in ${nvme_devnum_l}; do " \
+				"setenv devnum ${nvme_devnum};" \
+				"if pci enum; then "		\
+					"nvme scan; "		\
+				"fi; "				\
+				"if nvme dev ${devnum}; then "	\
+					"echo Try booting from NVME${devnum} ...; "	\
+					"setenv bootdev nvme;"	\
+					"run bootcmd_distro; "	\
+				"fi; "				\
+			"done; "				\
+		"fi; \0"					\
+	"distro_boot_env="		\
+		"echo Tring booting distro ...;"		\
+		"for bootdev_s in ${boot_devs}; do "		\
+			"run distro_bootenv_${bootdev_s}; "	\
+		"done; \0"
+
+#define CONFIG_EXTRA_ENV_SETTINGS			\
+	"fdt_high=0xffffffffffffffff\0"			\
+	"initrd_high=0xffffffffffffffff\0"		\
+	"kernel_addr_r=0x40200000\0"			\
+	"kernel_comp_addr_r=0x5a000000\0"		\
+	"kernel_comp_size=0x4000000\0"			\
+	"fdt_addr_r=0x46000000\0"			\
+	"scriptaddr=0x43900000\0"			\
+	"script_offset_f=0x1fff000\0"			\
+	"script_size_f=0x1000\0"			\
+	"pxefile_addr_r=0x45900000\0"			\
+	"ramdisk_addr_r=0x46100000\0"			\
+	"fdtoverlay_addr_r=0x4f000000\0"		\
+	"loadaddr=0x60000000\0"				\
+	CHIPA_GMAC_SET					\
+	CHIPA_SET					\
+	CPU_VOL_1020_SET				\
+	CPU_VOL_1040_SET				\
+	CPU_VOL_1060_SET				\
+	CPU_SPEED_1250_SET				\
+	CPU_SPEED_1500_SET				\
+	CPU_FREQ_VOL_SET				\
+	DEVKITS_MEM_SET					\
+	DEVKITS_SDK_BOOTENV				\
+	CMA_SIZE_SET					\
+	JH7110_SDK_BOOTENV				\
+	JH7110_DISTRO_BOOTENV				\
+	"type_guid_gpt_loader1=" TYPE_GUID_LOADER1 "\0" \
+	"type_guid_gpt_loader2=" TYPE_GUID_LOADER2 "\0" \
+	"type_guid_gpt_system=" TYPE_GUID_SYSTEM "\0"	\
+	"partitions=" PARTS_DEFAULT "\0"		\
+	BOOTENV						\
+	BOOTENV_SF
+
+#define CONFIG_SYS_BAUDRATE_TABLE {9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600}
+#define CONFIG_SYS_LOADS_BAUD_CHANGE 1		/* allow baudrate change */
+
+/* 6.25MHz RTC clock, StarFive JH7110*/
+#define CONFIG_SYS_HZ_CLOCK	4000000
+
+#define __io
+
+#define memset_io(c, v, l)	memset((c), (v), (l))
+#define memcpy_fromio(a, c, l)	memcpy((a), (c), (l))
+#define memcpy_toio(c, a, l)	memcpy((c), (a), (l))
+
+#define CONFIG_ID_EEPROM
+
+#ifdef CONFIG_ID_EEPROM		/* EEPROM for SN and MAC */
+#define CONFIG_SYS_EEPROM_BUS_NUM		5
+
+#define FORMAT_VERSION				0x01
+#define PCB_VERSION				0xB0
+#define BOM_VERSION				'A'
+/*
+ * BYTES_PER_EEPROM_PAGE: the 24FC04H datasheet says that data can
+ * only be written in page mode, which means 16 bytes at a time:
+ * 16-Byte Page Write Buffer
+ */
+#define BYTES_PER_EEPROM_PAGE			16
+
+/*
+ * EEPROM_WRITE_DELAY_MS: the 24FC04H datasheet says it takes up to
+ * 5ms to complete a given write:
+ * Write Cycle Time (byte or page) ro Page Write Time 5 ms, Maximum
+ */
+#define EEPROM_WRITE_DELAY_MS			5000
+/*
+ * StarFive OUI. Registration Date is 20xx-xx-xx
+ */
+#define STARFIVE_OUI_PREFIX			"6C:CF:39:"
+#define STARFIVE_DEFAULT_MAC0			{0x6c, 0xcf, 0x39, 0x6c, 0xde, 0xad}
+#define STARFIVE_DEFAULT_MAC1			{0x6c, 0xcf, 0x39, 0x7c, 0xae, 0x5d}
+
+/* Magic number at the first four bytes of EEPROM HATs */
+#define STARFIVE_EEPROM_HATS_SIG	"SFDK" /* StarFive VisionFive */
+
+#define STARFIVE_EEPROM_HATS_SIZE_MAX	256 /* Header + Atom1&4(v1) */
+#define STARFIVE_EEPROM_WP_OFFSET	0 /* Read only field */
+#define STARFIVE_EEPROM_ATOM1_PSTR	"DK7110B1-2150-D104EC32-00000001\0"
+
+#define STARFIVE_EEPROM_ATOM1_PSTR_SIZE	32
+#define STARFIVE_EEPROM_ATOM1_SN_OFFSET	23
+#define STARFIVE_EEPROM_ATOM1_VSTR	"StarFive Technology Co., Ltd.\0\0\0"
+#define STARFIVE_EEPROM_ATOM1_VSTR_SIZE	32
+#endif
+
+#define CONFIG_VIDEO_BMP_LOGO
+#define CONFIG_VIDEO_LOGO
+#define CONFIG_BMP_16BPP
+#define CONFIG_BMP_24BPP
+#define CONFIG_BMP_32BPP
+
+#endif /* _STARFIVE_DEVKITS_H */

+ 0 - 151
include/configs/starfive-visionfive.h

@@ -1,151 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
- * YanHong  Wang <yanhong.wang@starfivetech.com>
- */
-
-
-#ifndef _STARFIVE_VISIONFIVE_H
-#define _STARFIVE_VISIONFIVE_H
-
-#include <version.h>
-#include <linux/sizes.h>
-
-#ifdef CONFIG_SPL
-
-#define CONFIG_SPL_MAX_SIZE		0x00040000
-#define CONFIG_SPL_BSS_START_ADDR	0x08040000
-#define CONFIG_SPL_BSS_MAX_SIZE		0x00010000
-#define CONFIG_SYS_SPL_MALLOC_START	(CONFIG_SPL_BSS_START_ADDR +	\
-					 CONFIG_SPL_BSS_MAX_SIZE)
-#define CONFIG_SYS_SPL_MALLOC_SIZE	0x00100000
-
-#define CONFIG_SPL_STACK	(0x08000000 + 0x00180000 -	\
-				 GENERATED_GBL_DATA_SIZE)
-
-#define STARFIVE_SPL_BOOT_LOAD_ADDR 0xa0000000
-#endif
-
-
-#define CONFIG_SYS_CACHELINE_SIZE 64
-
-/*
- * Miscellaneous configurable options
- */
-#define CONFIG_SYS_CBSIZE	1024	/* Console I/O Buffer Size */
-#define CONFIG_SYS_BOOTM_LEN (32 << 20) /* 32MB */
-
-/*
- * Print Buffer Size
- */
-#define CONFIG_SYS_PBSIZE					\
-	(CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
-
-/*
- * max number of command args
- */
-#define CONFIG_SYS_MAXARGS	16
-
-/*
- * Boot Argument Buffer Size
- */
-#define CONFIG_SYS_BARGSIZE	CONFIG_SYS_CBSIZE
-
-/*
- * Size of malloc() pool
- * 512kB is suggested, (CONFIG_ENV_SIZE + 128 * 1024) was not enough
- */
-#define CONFIG_SYS_MALLOC_LEN		SZ_8M
-
-#define CONFIG_NR_DRAM_BANKS	1
-
-#define PHYS_SDRAM_0		0x40000000	/* SDRAM Bank #1 */
-#define PHYS_SDRAM_0_SIZE	0x100000000	/* 8 GB */
-
-#define CONFIG_SYS_SDRAM_BASE	(PHYS_SDRAM_0)
-
-
-/* Init Stack Pointer */
-#define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_SDRAM_BASE + SZ_2M)
-
-#define CONFIG_SYS_LOAD_ADDR		(CONFIG_SYS_SDRAM_BASE + SZ_16M)
-#define CONFIG_STANDALONE_LOAD_ADDR	0x41000000
-
-/*
- * Ethernet
- */
-#ifdef CONFIG_CMD_NET
-#define CONFIG_DW_ALTDESCRIPTOR
-#define DWC_NET_PHYADDR		0
-#define CONFIG_ARP_TIMEOUT	500
-#define CONFIG_NETMASK		255.255.255.0
-#define CONFIG_IPADDR		192.168.120.230
-#define CONFIG_IP_DEFRAG
-#ifndef CONFIG_NET_MAXDEFRAG
-#define CONFIG_NET_MAXDEFRAG	16384
-#endif
-#endif
-
-/* allow to overwrite serial and ethaddr */
-#define CONFIG_ENV_OVERWRITE
-
-/* HACK these should have '#if defined (stuff) around them like zynqp*/
-#define BOOT_TARGET_DEVICES(func) func(DHCP, dhcp, na)	func(MMC, mmc, 0)
-
-#include <config_distro_bootcmd.h>
-
-
-#include <environment/distro/sf.h>
-
-#define TYPE_GUID_LOADER1	"5B193300-FC78-40CD-8002-E86C45580B47"
-#define TYPE_GUID_LOADER2	"2E54B353-1271-4842-806F-E436D6AF6985"
-#define TYPE_GUID_SYSTEM	"0FC63DAF-8483-4772-8E79-3D69D8477DE4"
-
-#define PARTS_DEFAULT							\
-	"name=loader1,start=17K,size=1M,type=${type_guid_gpt_loader1};" \
-	"name=loader2,size=4MB,type=${type_guid_gpt_loader2};"		\
-	"name=system,size=-,bootable,type=${type_guid_gpt_system};"
-
-#define CONFIG_EXTRA_ENV_SETTINGS			\
-	"fdt_high=0xffffffffffffffff\0"			\
-	"initrd_high=0xffffffffffffffff\0"		\
-	"kernel_addr_r=0x44000000\0"			\
-	"fdt_addr_r=0x46000000\0"			\
-	"scriptaddr=0x88100000\0"			\
-	"script_offset_f=0x1fff000\0"			\
-	"script_size_f=0x1000\0"			\
-	"pxefile_addr_r=0x88200000\0"			\
-	"ramdisk_addr_r=0x88300000\0"			\
-	"type_guid_gpt_loader1=" TYPE_GUID_LOADER1 "\0" \
-	"type_guid_gpt_loader2=" TYPE_GUID_LOADER2 "\0" \
-	"type_guid_gpt_system=" TYPE_GUID_SYSTEM "\0"	\
-	"partitions=" PARTS_DEFAULT "\0"		\
-	BOOTENV						\
-	BOOTENV_SF
-
-/*
- * memtest works on 1.9 MB in DRAM
- */
-#define CONFIG_SYS_MEMTEST_START	PHYS_SDRAM_0
-#define CONFIG_SYS_MEMTEST_END		(PHYS_SDRAM_0 + PHYS_SDRAM_0_SIZE)
-
-#define CONFIG_SYS_BAUDRATE_TABLE {9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600}
-#define CONFIG_SYS_LOADS_BAUD_CHANGE 1		/* allow baudrate change */
-
-/* 6.25MHz RTC clock, StarFive JH7110*/
-#define CONFIG_SYS_HZ_CLOCK	4000000
-
-#define __io
-
-#define memset_io(c, v, l)	memset((c), (v), (l))
-#define memcpy_fromio(a, c, l)	memcpy((a), (c), (l))
-#define memcpy_toio(c, a, l)	memcpy((c), (a), (l))
-
-#define CONFIG_VIDEO_BMP_LOGO
-#define CONFIG_VIDEO_LOGO
-#define CONFIG_BMP_16BPP
-#define CONFIG_BMP_24BPP
-#define CONFIG_BMP_32BPP
-
-#endif /* _STARFIVE_EVB_H */
-

+ 374 - 0
include/configs/starfive-visionfive2.h

@@ -0,0 +1,374 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2021 Shanghai StarFive Technology Co., Ltd.
+ * YanHong  Wang <yanhong.wang@starfivetech.com>
+ */
+
+
+#ifndef _STARFIVE_VISIONFIVE2_H
+#define _STARFIVE_VISIONFIVE2_H
+
+#include <version.h>
+#include <linux/sizes.h>
+
+#ifdef CONFIG_SPL
+
+#define CONFIG_SPL_MAX_SIZE		0x00040000
+#define CONFIG_SPL_BSS_START_ADDR	0x08040000
+#define CONFIG_SPL_BSS_MAX_SIZE		0x00010000
+#define CONFIG_SYS_SPL_MALLOC_START	0x42000000
+
+#define CONFIG_SYS_SPL_MALLOC_SIZE	0x00800000
+
+#define CONFIG_SPL_STACK		(0x08000000 + 0x00180000 - \
+					 GENERATED_GBL_DATA_SIZE)
+#define STARFIVE_SPL_BOOT_LOAD_ADDR	0x60000000
+#endif
+
+#define CONFIG_SYS_BOOTM_LEN            SZ_64M
+
+
+#define CONFIG_SYS_CACHELINE_SIZE 64
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CONFIG_SYS_CBSIZE	1024	/* Console I/O Buffer Size */
+
+/*
+ * Print Buffer Size
+ */
+#define CONFIG_SYS_PBSIZE					\
+	(CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+
+/*
+ * max number of command args
+ */
+#define CONFIG_SYS_MAXARGS	16
+
+/*
+ * Boot Argument Buffer Size
+ */
+#define CONFIG_SYS_BARGSIZE	CONFIG_SYS_CBSIZE
+
+/*
+ * Size of malloc() pool
+ * 512kB is suggested, (CONFIG_ENV_SIZE + 128 * 1024) was not enough
+ */
+#define CONFIG_SYS_MALLOC_LEN		SZ_8M
+
+#define CONFIG_SYS_SDRAM_BASE		0x40000000
+
+/* Init Stack Pointer */
+#define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_SDRAM_BASE + SZ_8M)
+
+#define CONFIG_SYS_LOAD_ADDR		(CONFIG_SYS_SDRAM_BASE + SZ_16M)
+#define CONFIG_STANDALONE_LOAD_ADDR	(CONFIG_SYS_SDRAM_BASE + SZ_16M)
+
+#define CONFIG_SYS_PCI_64BIT		/* enable 64-bit PCI resources */
+
+/*
+ * Ethernet
+ */
+#ifdef CONFIG_CMD_NET
+#define CONFIG_DW_ALTDESCRIPTOR
+#define CONFIG_ARP_TIMEOUT	500
+#define CONFIG_NETMASK		255.255.255.0
+#define CONFIG_IPADDR		192.168.120.230
+#define CONFIG_IP_DEFRAG
+#ifndef CONFIG_NET_MAXDEFRAG
+#define CONFIG_NET_MAXDEFRAG	16384
+#endif
+#endif
+
+/* HACK these should have '#if defined (stuff) around them like zynqp*/
+#define BOOT_TARGET_DEVICES(func) func(MMC, mmc, 0) func(DHCP, dhcp, na)
+
+#include <config_distro_bootcmd.h>
+
+
+#include <environment/distro/sf.h>
+
+#define TYPE_GUID_LOADER1	"5B193300-FC78-40CD-8002-E86C45580B47"
+#define TYPE_GUID_LOADER2	"2E54B353-1271-4842-806F-E436D6AF6985"
+#define TYPE_GUID_SYSTEM	"0FC63DAF-8483-4772-8E79-3D69D8477DE4"
+
+#define CPU_VOL_1020_SET \
+	"cpu_vol_1020_set=" 			\
+	"fdt set /opp-table-0/opp-1500000000 opp-microvolt <1020000>;\0"
+
+#define CPU_VOL_1040_SET \
+	"cpu_vol_1040_set="			\
+	"fdt set /opp-table-0/opp-1500000000 opp-microvolt <1040000>;\0"
+
+#define CPU_VOL_1060_SET \
+	"cpu_vol_1060_set="			\
+	"fdt set /opp-table-0/opp-1500000000 opp-microvolt <1060000>;\0"
+
+#define CPU_SPEED_1250_SET \
+	"cpu_speed_1250_set="			\
+	"fdt rm /opp-table-0/opp-375000000;"	\
+	"fdt rm /opp-table-0/opp-500000000;"	\
+	"fdt rm /opp-table-0/opp-750000000;"	\
+	"fdt rm /opp-table-0/opp-1500000000;\0"
+
+#define CPU_SPEED_1500_SET \
+	"cpu_speed_1500_set="			\
+	"fdt rm /opp-table-0/opp-312500000;"	\
+	"fdt rm /opp-table-0/opp-417000000;"	\
+	"fdt rm /opp-table-0/opp-625000000;"	\
+	"fdt rm /opp-table-0/opp-1250000000;\0"
+
+#define CPU_FREQ_VOL_SET \
+	"cpu_vol_set="						\
+	"if test ${cpu_max_vol} = 1000000; then "		\
+		"run cpu_speed_1250_set; "			\
+	"else "							\
+		"run cpu_speed_1500_set; "			\
+		"if test ${cpu_max_vol} = 1060000; then "	\
+			"run cpu_vol_1060_set; "		\
+		"elif test ${cpu_max_vol} = 1020000; then "	\
+			"run cpu_vol_1020_set; "		\
+		"else "						\
+			"run cpu_vol_1040_set; "		\
+		"fi; "						\
+	"fi; \0"
+
+#define CMA_SIZE_SET \
+	"cma_start=70000000\0"					\
+	"cma_1g=b000000\0"					\
+	"cma_2g=20000000\0"					\
+	"cma_4g=40000000\0"	 				\
+	"cma_8g=60000000\0"					\
+	"cma_node=/reserved-memory/linux,cma\0"			\
+	"cma_ddr1g_set="					\
+	"fdt set ${cma_node} size <0x0 0x${cma_1g}>;"		\
+	"fdt set ${cma_node} alloc-ranges <0x0 0x${cma_start} 0x0 0x${cma_1g}>;\0" \
+	"cma_ddr2g_set="					\
+	"fdt set ${cma_node} size <0x0 0x${cma_2g}>;"		\
+	"fdt set ${cma_node} alloc-ranges <0x0 0x${cma_start} 0x0 0x${cma_2g}>;\0" \
+	"cma_ddr4g_set="					\
+	"fdt set ${cma_node} size <0x0 0x${cma_4g}>;"		\
+	"fdt set ${cma_node} alloc-ranges <0x0 0x${cma_start} 0x0 0x${cma_4g}>;\0" \
+	"cma_ddr8g_set="					\
+	"fdt set ${cma_node} size <0x0 0x${cma_8g}>;"		\
+	"fdt set ${cma_node} alloc-ranges <0x0 0x${cma_start} 0x0 0x${cma_8g}>;\0" \
+	"cma_resize="						\
+	"if test ${memory_size} -eq 40000000; then "		\
+		"run cma_ddr1g_set;"				\
+	"elif test ${memory_size} -eq 80000000; then "		\
+		"run cma_ddr2g_set;"				\
+	"elif test ${memory_size} -eq 100000000; then "		\
+		"run cma_ddr4g_set;"				\
+	"elif test ${memory_size} -ge 200000000; then "		\
+		"run cma_ddr8g_set;"				\
+	"fi; \0 "
+
+#define PARTS_DEFAULT							\
+	"name=loader1,start=17K,size=1M,type=${type_guid_gpt_loader1};" \
+	"name=loader2,size=4MB,type=${type_guid_gpt_loader2};"		\
+	"name=system,size=-,bootable,type=${type_guid_gpt_system};"
+
+#define CHIPA_GMAC_SET	\
+	"chipa_gmac_set="	\
+	"fdt set /soc/ethernet@16030000/ethernet-phy@0 tx_inverted_10 <0x0>;"	\
+	"fdt set /soc/ethernet@16030000/ethernet-phy@0 tx_inverted_100 <0x0>;"	\
+	"fdt set /soc/ethernet@16030000/ethernet-phy@0 tx_inverted_1000 <0x0>;"	\
+	"fdt set /soc/ethernet@16030000/ethernet-phy@0 tx_delay_sel <0x9>;"	\
+	"fdt set /soc/ethernet@16040000/ethernet-phy@1 tx_inverted_10 <0x0>;"	\
+	"fdt set /soc/ethernet@16040000/ethernet-phy@1 tx_inverted_100 <0x0>;"	\
+	"fdt set /soc/ethernet@16040000/ethernet-phy@1 tx_inverted_1000 <0x0>;"	\
+	"fdt set /soc/ethernet@16040000/ethernet-phy@1 tx_delay_sel <0x9> \0"
+
+#define VISIONFIVE2_MEM_SET	\
+	"visionfive2_mem_set="	\
+	"fdt memory ${memory_addr} ${memory_size};" \
+	"run cma_resize; \0"
+
+#define CHIPA_SET	\
+	"chipa_set="				\
+	"if test ${chip_vision} = A; then "	\
+		"run chipa_gmac_set;"		\
+	"fi; \0"				\
+	"chipa_set_uboot="			\
+	"fdt addr ${uboot_fdt_addr};"		\
+	"run chipa_set;\0"			\
+	"chipa_set_linux="			\
+	"fdt addr ${fdt_addr_r};"		\
+	"run visionfive2_mem_set;"		\
+	"run chipa_set;\0"
+
+#define VF2_SDK_BOOTENV			\
+	"bootenv=uEnv.txt\0"		\
+	"bootenv_sdk=vf2_uEnv.txt\0"	\
+	"boot_devs=mmc nvme\0"		\
+	"emmc_devnum=0\0" 		\
+	"sd_devnum=1\0"			\
+	"mmc_devnum_l=1 0\0"		\
+	"nvme_devnum_l=0 0\0"
+
+#define JH7110_SDK_BOOTENV		\
+	"bootdir=/boot\0"		\
+	"bootpart=3\0"			\
+	"rootpart=4\0"			\
+	"load_sdk_uenv="		\
+		"fatload ${bootdev} ${devnum}:${bootpart} ${loadaddr} ${bootenv_sdk};"	\
+		"env import -t ${loadaddr} ${filesize}; \0"				\
+	"mmc_test_and_boot="				\
+		"if mmc dev ${devnum}; then "	\
+			"echo Try booting from MMC${devnum} ...; "	\
+			"setenv sdev_blk mmcblk${devnum}p${rootpart};"	\
+			"run load_sdk_uenv; run boot2;"	\
+		"fi;\0"							\
+	"bootenv_mmc="					\
+		"setenv bootdev mmc;"			\
+		"if test ${bootmode} = flash; then "	\
+			"for mmc_devnum in ${mmc_devnum_l}; do " \
+				"setenv devnum ${mmc_devnum}; " \
+				"run mmc_test_and_boot;"	\
+			"done;"					\
+		"fi; "						\
+		"if test ${bootmode} = sd; then "	\
+			"setenv devnum ${sd_devnum};" 	\
+			"run mmc_test_and_boot;"	\
+		"fi; " 					\
+		"if test ${bootmode} = emmc; then "	\
+			"setenv devnum  ${emmc_devnum};"\
+			"run mmc_test_and_boot;"	\
+		"fi; \0"				\
+	"bootenv_nvme="					\
+		"if test ${bootmode} = flash; then "	\
+			"for nvme_devnum in ${nvme_devnum_l}; do " \
+				"setenv devnum ${nvme_devnum};" \
+				"if pci enum; then "		\
+					"nvme scan; "		\
+				"fi; "				\
+				"if nvme dev ${devnum}; then "	\
+					"echo Try booting from NVME${devnum} ...; "	\
+					"setenv bootdev nvme;"	\
+					"setenv sdev_blk nvme${devnum}n1p${rootpart};"	\
+					"run load_sdk_uenv; run boot2;"	\
+				"fi; "				\
+			"done; "				\
+		"fi; \0"					\
+	"sdk_boot_env="			\
+		"for bootdev_s in ${boot_devs}; do "	\
+		"run bootenv_${bootdev_s}; "		\
+		"done;\0"				\
+	"fdtfile=" CONFIG_DEFAULT_FDT_FILE "\0"
+
+#define JH7110_DISTRO_BOOTENV	\
+	"bootdir=/boot\0"	\
+	"bootpart=3\0"		\
+	"rootpart=4\0"		\
+	"load_distro_uenv="						\
+		"fatload ${bootdev} ${devnum}:${bootpart} ${loadaddr} /${bootenv}; " \
+		"env import ${loadaddr} ${filesize}; \0" \
+	"fdt_loaddtb="		\
+		"fatload ${bootdev} ${devnum}:${bootpart} ${fdt_addr_r} /dtbs/${fdtfile}; fdt addr ${fdt_addr_r}; \0" \
+	"fdt_sizecheck="	\
+		"fatsize ${bootdev} ${devnum}:${bootpart} /dtbs/${fdtfile}; \0" \
+	"set_fdt_distro="	\
+		"run chipa_set_linux; run cpu_vol_set;" \
+		"fatwrite ${bootdev} ${devnum}:${bootpart} ${fdt_addr_r} /dtbs/${fdtfile} ${filesize}; \0" \
+	"bootcmd_distro="	\
+		"run load_distro_uenv; " \
+		"run fdt_loaddtb; run fdt_sizecheck; run set_fdt_distro; "	\
+		"sysboot ${bootdev} ${devnum}:${bootpart} fat ${scriptaddr} /${boot_syslinux_conf}; \0" \
+	"distro_mmc_test_and_boot="					\
+		"if mmc dev ${devnum}; then "				\
+			"echo Try booting from MMC${devnum} ...; "	\
+			"run bootcmd_distro;"				\
+		"fi;\0" 						\
+	"distro_bootenv_mmc="					\
+		"setenv bootdev mmc;"			\
+		"if test ${bootmode} = flash; then "	\
+			"for mmc_devnum in ${mmc_devnum_l}; do "\
+				"setenv devnum ${mmc_devnum}; " \
+				"run distro_mmc_test_and_boot;" \
+			"done;" 				\
+		"fi; "						\
+		"if test ${bootmode} = sd; then "	\
+			"setenv devnum ${sd_devnum};"	\
+			"run distro_mmc_test_and_boot;" \
+		"fi; "					\
+		"if test ${bootmode} = emmc; then "	\
+			"setenv devnum	${emmc_devnum};"\
+			"run distro_mmc_test_and_boot;" \
+		"fi; \0"				\
+	"distro_bootenv_nvme="				\
+		"if test ${bootmode} = flash; then "	\
+			"for nvme_devnum in ${nvme_devnum_l}; do " \
+				"setenv devnum ${nvme_devnum};" \
+				"if pci enum; then "		\
+					"nvme scan; "		\
+				"fi; "				\
+				"if nvme dev ${devnum}; then "	\
+					"echo Try booting from NVME${devnum} ...; "	\
+					"setenv bootdev nvme;"	\
+					"run bootcmd_distro; "	\
+				"fi; "				\
+			"done; "				\
+		"fi; \0"					\
+	"distro_boot_env="		\
+		"echo Tring booting distro ...;"		\
+		"for bootdev_s in ${boot_devs}; do "		\
+			"run distro_bootenv_${bootdev_s}; "	\
+		"done; \0"
+
+#define CONFIG_EXTRA_ENV_SETTINGS			\
+	"fdt_high=0xffffffffffffffff\0"			\
+	"initrd_high=0xffffffffffffffff\0"		\
+	"kernel_addr_r=0x40200000\0"			\
+	"kernel_comp_addr_r=0x5a000000\0"		\
+	"kernel_comp_size=0x4000000\0"			\
+	"fdt_addr_r=0x46000000\0"			\
+	"scriptaddr=0x43900000\0"			\
+	"script_offset_f=0x1fff000\0"			\
+	"script_size_f=0x1000\0"			\
+	"pxefile_addr_r=0x45900000\0"			\
+	"ramdisk_addr_r=0x46100000\0"			\
+	"fdtoverlay_addr_r=0x4f000000\0"		\
+	"loadaddr=0x60000000\0"				\
+	VF2_SDK_BOOTENV					\
+	JH7110_SDK_BOOTENV				\
+	JH7110_DISTRO_BOOTENV				\
+	CHIPA_GMAC_SET					\
+	CHIPA_SET					\
+	CPU_VOL_1020_SET				\
+	CPU_VOL_1040_SET				\
+	CPU_VOL_1060_SET				\
+	CPU_SPEED_1250_SET				\
+	CPU_SPEED_1500_SET				\
+	CPU_FREQ_VOL_SET				\
+	CMA_SIZE_SET					\
+	VISIONFIVE2_MEM_SET				\
+	"type_guid_gpt_loader1=" TYPE_GUID_LOADER1 "\0" \
+	"type_guid_gpt_loader2=" TYPE_GUID_LOADER2 "\0" \
+	"type_guid_gpt_system=" TYPE_GUID_SYSTEM "\0"	\
+	"partitions=" PARTS_DEFAULT "\0"		\
+	BOOTENV						\
+	BOOTENV_SF
+
+#define CONFIG_SYS_BAUDRATE_TABLE {9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600}
+#define CONFIG_SYS_LOADS_BAUD_CHANGE 1		/* allow baudrate change */
+
+/* 6.25MHz RTC clock, StarFive JH7110*/
+#define CONFIG_SYS_HZ_CLOCK	4000000
+
+#define __io
+
+#define memset_io(c, v, l)	memset((c), (v), (l))
+#define memcpy_fromio(a, c, l)	memcpy((a), (c), (l))
+#define memcpy_toio(c, a, l)	memcpy((c), (a), (l))
+
+#define CONFIG_VIDEO_BMP_LOGO
+#define CONFIG_VIDEO_LOGO
+#define CONFIG_BMP_16BPP
+#define CONFIG_BMP_24BPP
+#define CONFIG_BMP_32BPP
+
+#define CONFIG_ID_EEPROM
+
+#endif /* _STARFIVE_VISIONFIVE2_H */
+

+ 25 - 0
include/efi_api.h

@@ -417,6 +417,31 @@ struct efi_runtime_services {
 	EFI_GUID(0x1e2ed096, 0x30e2, 0x4254, 0xbd, \
 		 0x89, 0x86, 0x3b, 0xbe, 0xf8, 0x23, 0x25)
 
+#define EFI_RNG_PROTOCOL_GUID \
+	EFI_GUID(0x3152bca5, 0xeade, 0x433d, 0x86, 0x2e, \
+		 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44)
+
+#define EFI_DT_FIXUP_PROTOCOL_GUID \
+	EFI_GUID(0xe617d64c, 0xfe08, 0x46da, 0xf4, 0xdc, \
+		 0xbb, 0xd5, 0x87, 0x0c, 0x73, 0x00)
+
+#define EFI_TCG2_PROTOCOL_GUID \
+	EFI_GUID(0x607f766c, 0x7455, 0x42be, 0x93, \
+		 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f)
+
+#define RISCV_EFI_BOOT_PROTOCOL_GUID \
+	EFI_GUID(0xccd15fec, 0x6f73, 0x4eec, 0x83, \
+		 0x95, 0x3e, 0x69, 0xe4, 0xb9, 0x40, 0xbf)
+
+/**
+ * struct efi_configuration_table - EFI Configuration Table
+ *
+ * This table contains a set of GUID/pointer pairs.
+ * The EFI Configuration Table may contain at most one instance of each table type.
+ *
+ * @guid:		GUID that uniquely identifies the system configuration table
+ * @table:		A pointer to the table associated with guid
+ */
 struct efi_configuration_table {
 	efi_guid_t guid;
 	void *table;

+ 4 - 0
include/efi_loader.h

@@ -523,6 +523,10 @@ efi_status_t efi_disk_register(void);
 efi_status_t efi_rng_register(void);
 /* Called by efi_init_obj_list() to install EFI_TCG2_PROTOCOL */
 efi_status_t efi_tcg2_register(void);
+/* Called by efi_init_obj_list() to install RISCV_EFI_BOOT_PROTOCOL */
+efi_status_t efi_riscv_register(void);
+/* Called by efi_init_obj_list() to do initial measurement */
+efi_status_t efi_tcg2_do_initial_measurement(void);
 /* measure the pe-coff image, extend PCR and add Event Log */
 efi_status_t tcg2_measure_pe_image(void *efi, u64 efi_size,
 				   struct efi_loaded_image_obj *handle,

+ 24 - 0
include/efi_riscv.h

@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * RISCV_EFI_BOOT_PROTOCOL
+ *
+ * Copyright (c) 2022 Ventana Micro Systems Inc
+ */
+
+#include <efi_api.h>
+
+#define RISCV_EFI_BOOT_PROTOCOL_REVISION 0x00010000
+
+/**
+ * struct riscv_efi_boot_protocol - RISCV_EFI_BOOT_PROTOCOL
+ * @revision:		Version of the protocol implemented
+ * @get_boot_hartid:	Get the boot hart ID
+ */
+struct riscv_efi_boot_protocol {
+	u64 revision;
+
+	efi_status_t (EFIAPI * get_boot_hartid) (struct riscv_efi_boot_protocol *this,
+						 efi_uintn_t *boot_hartid);
+};
+
+extern struct riscv_efi_boot_protocol riscv_efi_boot_prot;

+ 3 - 0
include/init.h

@@ -267,6 +267,9 @@ int cpu_init_r(void);
 int last_stage_init(void);
 int mac_read_from_eeprom(void);
 int set_cpu_clk_info(void);
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_DEVKITS)
+int set_pmic(void);
+#endif
 int update_flash_size(int flash_size);
 int arch_early_init_r(void);
 int misc_init_r(void);

+ 10 - 0
lib/efi_loader/Kconfig

@@ -374,4 +374,14 @@ config EFI_ESRT
 	help
 	  Enabling this option creates the ESRT UEFI system table.
 
+config EFI_RISCV_BOOT_PROTOCOL
+	bool "RISCV_EFI_BOOT_PROTOCOL support"
+	default y
+	depends on RISCV
+	help
+	  The EFI_RISCV_BOOT_PROTOCOL is used to transfer the boot hart ID
+	  to the next boot stage. It should be enabled as it is meant to
+	  replace the transfer via the device-tree. The latter is not
+	  possible on systems using ACPI.
+
 endif

+ 1 - 0
lib/efi_loader/Makefile

@@ -62,6 +62,7 @@ obj-$(CONFIG_GENERATE_ACPI_TABLE) += efi_acpi.o
 obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += efi_smbios.o
 obj-$(CONFIG_EFI_RNG_PROTOCOL) += efi_rng.o
 obj-$(CONFIG_EFI_TCG2_PROTOCOL) += efi_tcg2.o
+obj-$(CONFIG_EFI_RISCV_BOOT_PROTOCOL) += efi_riscv.o
 obj-$(CONFIG_EFI_LOAD_FILE2_INITRD) += efi_load_initrd.o
 obj-$(CONFIG_EFI_SIGNATURE_SUPPORT) += efi_signature.o
 

+ 60 - 0
lib/efi_loader/efi_riscv.c

@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Defines APIs that allow an OS to interact with UEFI firmware to query
+ * information about the boot hart ID.
+ *
+ * Copyright (c) 2022, Ventana Micro Systems Inc
+ */
+
+#define LOG_CATEGORY LOGC_EFI
+#include <common.h>
+#include <efi_loader.h>
+#include <efi_variable.h>
+#include <log.h>
+#include <asm/global_data.h>
+#include <efi_riscv.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const efi_guid_t efi_guid_riscv_boot_protocol = RISCV_EFI_BOOT_PROTOCOL_GUID;
+
+/**
+ * efi_riscv_get_boot_hartid() - return boot hart ID
+ * @this:		RISCV_EFI_BOOT_PROTOCOL instance
+ * @boot_hartid:	caller allocated memory to return boot hart id
+ * Return:		status code
+ */
+static efi_status_t EFIAPI
+efi_riscv_get_boot_hartid(struct riscv_efi_boot_protocol *this,
+			  efi_uintn_t *boot_hartid)
+{
+	EFI_ENTRY("%p, %p",  this, boot_hartid);
+
+	if (this != &riscv_efi_boot_prot || !boot_hartid)
+		return EFI_INVALID_PARAMETER;
+
+	*boot_hartid = gd->arch.boot_hart;
+
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+struct riscv_efi_boot_protocol riscv_efi_boot_prot = {
+	.revision = RISCV_EFI_BOOT_PROTOCOL_REVISION,
+	.get_boot_hartid = efi_riscv_get_boot_hartid
+};
+
+/**
+ * efi_riscv_register() - register RISCV_EFI_BOOT_PROTOCOL
+ *
+ * Return:	status code
+ */
+efi_status_t efi_riscv_register(void)
+{
+	efi_status_t ret = EFI_SUCCESS;
+
+	ret = efi_add_protocol(efi_root, &efi_guid_riscv_boot_protocol,
+			       (void *)&riscv_efi_boot_prot);
+	if (ret != EFI_SUCCESS)
+		log_err("Cannot install RISCV_EFI_BOOT_PROTOCOL\n");
+	return ret;
+}

+ 6 - 0
lib/efi_loader/efi_setup.c

@@ -273,6 +273,12 @@ efi_status_t efi_init_obj_list(void)
 			goto out;
 	}
 
+	if (IS_ENABLED(CONFIG_EFI_RISCV_BOOT_PROTOCOL)) {
+		ret = efi_riscv_register();
+		if (ret != EFI_SUCCESS)
+			goto out;
+	}
+
 	/* Secure boot */
 	ret = efi_init_secure_boot();
 	if (ret != EFI_SUCCESS)