浏览代码

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 月之前
父节点
当前提交
918eb904cf
共有 63 个文件被更改,包括 7021 次插入771 次删除
  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
 config TARGET_SIFIVE_UNMATCHED
 	bool "Support SiFive Unmatched Board"
 	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
 config TARGET_STARFIVE_EVB
 	bool "Support StarFive Evb Board"
 	bool "Support StarFive Evb Board"
@@ -71,7 +74,8 @@ source "board/sifive/unleashed/Kconfig"
 source "board/sifive/unmatched/Kconfig"
 source "board/sifive/unmatched/Kconfig"
 source "board/openpiton/riscv64/Kconfig"
 source "board/openpiton/riscv64/Kconfig"
 source "board/sipeed/maix/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"
 source "board/starfive/evb/Kconfig"
 
 
 # platform-specific options below
 # 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_UNLEASHED) += hifive-unleashed-a00.dtb
 dtb-$(CONFIG_TARGET_SIFIVE_UNMATCHED) += hifive-unmatched-a00.dtb
 dtb-$(CONFIG_TARGET_SIFIVE_UNMATCHED) += hifive-unmatched-a00.dtb
 dtb-$(CONFIG_TARGET_SIPEED_MAIX) += k210-maix-bit.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
 dtb-$(CONFIG_TARGET_STARFIVE_EVB) += starfive_evb.dtb
 
 
 targets += $(dtb-y)
 targets += $(dtb-y)

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

@@ -129,3 +129,11 @@
 &gmac0_rmii_refin {
 &gmac0_rmii_refin {
 	u-boot,dm-spl;
 	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";
 			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 {
 		i2c0: i2c@10030000 {
 			compatible = "snps,designware-i2c";
 			compatible = "snps,designware-i2c";
 			reg = <0x0 0x10030000 0x0 0x10000>;
 			reg = <0x0 0x10030000 0x0 0x10000>;
@@ -675,6 +662,32 @@
 			status = "disabled";
 			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 {
 		i2c5: i2c@12050000 {
 			compatible = "snps,designware-i2c";
 			compatible = "snps,designware-i2c";
 			reg = <0x0 0x12050000 0x0 0x10000>;
 			reg = <0x0 0x12050000 0x0 0x10000>;
@@ -688,6 +701,19 @@
 			status = "disabled";
 			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 */
 		/* unremovable emmc as mmcblk0 */
 		sdio0: sdio0@16010000 {
 		sdio0: sdio0@16010000 {
 			compatible = "snps,dw-mshc";
 			compatible = "snps,dw-mshc";
@@ -856,13 +882,15 @@
 				"ptp_ref",
 				"ptp_ref",
 				"stmmaceth",
 				"stmmaceth",
 				"pclk",
 				"pclk",
-				"gtxc";
+				"gtxc",
+				"rmii_rtx";
 			clocks = <&clkgen JH7110_GMAC0_GTXCLK>,
 			clocks = <&clkgen JH7110_GMAC0_GTXCLK>,
 				 <&clkgen JH7110_U0_GMAC5_CLK_TX>,
 				 <&clkgen JH7110_U0_GMAC5_CLK_TX>,
 				 <&clkgen JH7110_GMAC0_PTP>,
 				 <&clkgen JH7110_GMAC0_PTP>,
 				 <&clkgen JH7110_U0_GMAC5_CLK_AHB>,
 				 <&clkgen JH7110_U0_GMAC5_CLK_AHB>,
 				 <&clkgen JH7110_U0_GMAC5_CLK_AXI>,
 				 <&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>,
 			resets = <&rstgen RSTN_U0_DW_GMAC5_AXI64_AHB>,
 				 <&rstgen RSTN_U0_DW_GMAC5_AXI64_AXI>;
 				 <&rstgen RSTN_U0_DW_GMAC5_AXI64_AXI>;
 			reset-names = "ahb", "stmmaceth";
 			reset-names = "ahb", "stmmaceth";
@@ -897,13 +925,15 @@
 				"ptp_ref",
 				"ptp_ref",
 				"stmmaceth",
 				"stmmaceth",
 				"pclk",
 				"pclk",
-				"gtxc";
+				"gtxc",
+				"rmii_rtx";
 			clocks = <&clkgen JH7110_GMAC1_GTXCLK>,
 			clocks = <&clkgen JH7110_GMAC1_GTXCLK>,
 				 <&clkgen JH7110_GMAC5_CLK_TX>,
 				 <&clkgen JH7110_GMAC5_CLK_TX>,
 				 <&clkgen JH7110_GMAC5_CLK_PTP>,
 				 <&clkgen JH7110_GMAC5_CLK_PTP>,
 				 <&clkgen JH7110_GMAC5_CLK_AHB>,
 				 <&clkgen JH7110_GMAC5_CLK_AHB>,
 				 <&clkgen JH7110_GMAC5_CLK_AXI>,
 				 <&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>,
 			resets = <&rstgen RSTN_U1_DW_GMAC5_AXI64_H_N>,
 				 <&rstgen RSTN_U1_DW_GMAC5_AXI64_A_I>;
 				 <&rstgen RSTN_U1_DW_GMAC5_AXI64_A_I>;
 			reset-names = "ahb", "stmmaceth";
 			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";
 	status = "okay";
 
 
 	rm68200_panel: rm68200_panel@45 {
 	rm68200_panel: rm68200_panel@45 {
-		compatible = "raydium,rm68200";
+		compatible = "starfive,seeed";
 		reg = <0x45>;
 		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
 config SYS_CPU
 	default "jh7110"
 	default "jh7110"
 
 
 config SYS_BOARD
 config SYS_BOARD
-	default "visionfive"
+	default "devkits"
 
 
 config SYS_VENDOR
 config SYS_VENDOR
 	default "starfive"
 	default "starfive"
 
 
 config SYS_CONFIG_NAME
 config SYS_CONFIG_NAME
-	default "starfive-visionfive"
+	default "starfive-devkits"
 
 
 config ENV_SIZE
 config ENV_SIZE
 	default 0x2000 if ENV_IS_IN_SPI_FLASH
 	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.
 # 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_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'
 	    Help printed with the LAYOUT VERSIONS part of the 'eeprom'
 	    command's help.
 	    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
 config LOOPW
 	bool "loopw"
 	bool "loopw"
 	help
 	help

+ 14 - 29
cmd/eeprom.c

@@ -15,7 +15,7 @@
  * degradation (typical for EEPROM) is incured for FRAM memory:
  * degradation (typical for EEPROM) is incured for FRAM memory:
  *
  *
  * #define CONFIG_SYS_I2C_FRAM
  * #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
 #define	CONFIG_SYS_I2C_SPEED	50000
 #endif
 #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
 #ifndef	I2C_RXTX_LEN
 #define I2C_RXTX_LEN	128
 #define I2C_RXTX_LEN	128
 #endif
 #endif
@@ -46,21 +38,6 @@
 #define	EEPROM_PAGE_SIZE	(1 << CONFIG_SYS_EEPROM_PAGE_WRITE_BITS)
 #define	EEPROM_PAGE_SIZE	(1 << CONFIG_SYS_EEPROM_PAGE_WRITE_BITS)
 #define	EEPROM_PAGE_OFFSET(x)	((x) & (EEPROM_PAGE_SIZE - 1))
 #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)
 #if CONFIG_IS_ENABLED(DM_I2C)
 static int eeprom_i2c_bus;
 static int eeprom_i2c_bus;
 #endif
 #endif
@@ -82,6 +59,13 @@ void eeprom_init(int bus)
 #endif
 #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)
 static int eeprom_addr(unsigned dev_addr, unsigned offset, uchar *addr)
 {
 {
 	unsigned blk_off;
 	unsigned blk_off;
@@ -183,10 +167,11 @@ static int eeprom_rw(unsigned dev_addr, unsigned offset, uchar *buffer,
 		buffer += len;
 		buffer += len;
 		offset += len;
 		offset += len;
 
 
+#if CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS > 0
 		if (!read)
 		if (!read)
 			udelay(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
 			udelay(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
 	}
 	}
-
+#endif
 	return rcode;
 	return rcode;
 }
 }
 
 
@@ -218,10 +203,10 @@ int eeprom_write(unsigned dev_addr, unsigned offset,
 	return ret;
 	return ret;
 }
 }
 
 
-static int parse_numeric_param(char *str)
+static long parse_numeric_param(char *str)
 {
 {
 	char *endptr;
 	char *endptr;
-	int value = simple_strtol(str, &endptr, 16);
+	long value = simple_strtol(str, &endptr, 16);
 
 
 	return (*endptr != '\0') ? -1 : value;
 	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_no_bus = argc_no_bus_addr + 1;
 	int argc_bus_addr = argc_no_bus_addr + 2;
 	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) {
 	if (argc == argc_no_bus_addr) {
 		*i2c_bus = -1;
 		*i2c_bus = -1;
-		*i2c_addr = CONFIG_SYS_DEF_EEPROM_ADDR;
+		*i2c_addr = CONFIG_SYS_I2C_EEPROM_ADDR;
 
 
 		return 0;
 		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)
 				if (ret)
 					return i2c_report_err(ret,
 					return i2c_report_err(ret,
 							      I2C_ERR_WRITE);
 							      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);
 				udelay(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
 #endif
 #endif
 				if (incrflag)
 				if (incrflag)

+ 3 - 0
common/board_r.c

@@ -689,6 +689,9 @@ static init_fnc_t init_sequence_r[] = {
 #endif
 #endif
 #ifdef CONFIG_ARCH_EARLY_INIT_R
 #ifdef CONFIG_ARCH_EARLY_INIT_R
 	arch_early_init_r,
 	arch_early_init_r,
+#endif
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_DEVKITS)
+	set_pmic,
 #endif
 #endif
 	power_init_board,
 	power_init_board,
 #ifdef CONFIG_MTD_NOR_FLASH
 #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,
 	       starfive_clk_divider(priv->sys,
 				    "nocstg_bus", "bus_root",
 				    "nocstg_bus", "bus_root",
 				    SYS_OFFSET(JH7110_NOCSTG_BUS), 3));
 				    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*/
 	/*QSPI*/
 	clk_dm(JH7110_QSPI_CLK_AHB,
 	clk_dm(JH7110_QSPI_CLK_AHB,
 	       starfive_clk_gate(priv->sys,
 	       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",
 				    "u0_dom_vout_top_clk_mipiphy_ref", "osc",
 				    SYS_OFFSET(JH7110_MCLK_INNER), 2));
 				    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*/
 	/*pcie0*/
 	clk_dm(JH7110_PCIE0_CLK_TL,
 	clk_dm(JH7110_PCIE0_CLK_TL,
 		starfive_clk_gate(priv->stg,
 		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
 	  controller is used in various SoCs, e.g. the ST SPEAr, Altera
 	  SoCFPGA, Synopsys ARC700 and some Intel x86 SoCs.
 	  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
 config SYS_I2C_ASPEED
 	bool "Aspeed I2C Controller"
 	bool "Aspeed I2C Controller"
 	depends on DM_I2C && ARCH_ASPEED
 	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_CADENCE) += i2c-cdns.o
 obj-$(CONFIG_SYS_I2C_CA) += i2c-cortina.o
 obj-$(CONFIG_SYS_I2C_CA) += i2c-cortina.o
 obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.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_ACPIGEN
 ifdef CONFIG_PCI
 ifdef CONFIG_PCI
 obj-$(CONFIG_SYS_I2C_DW) += designware_i2c_pci.o
 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_4BIT;
 		cfg->host_caps &= ~MMC_MODE_8BIT;
 		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;
 	cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS200;
+#endif
 
 
 	cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 	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;
 	bool clk_ck_enabled;
 	struct reset_ctl_bulk reset_bulk;
 	struct reset_ctl_bulk reset_bulk;
 	struct clk_bulk clk_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;
 		return ret;
 	}
 	}
 
 
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_VISIONFIVE2)
+	clk_set_rate(&eqos->rmii_rtx, rate);
+#endif
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1909,6 +1914,14 @@ static int eqos_probe_resources_jh7110(struct udevice *dev)
 		goto err_free_reset_eqos;
 		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);
 	ret = clk_get_bulk(dev, &eqos->clk_bulk);
 	if (ret) {
 	if (ret) {
 		pr_err("clk_get_bulk failed: %d", 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 }
 	{ "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)
 static int ytphy_read_ext(struct phy_device *phydev, u32 regnum)
 {
 {
 	int ret;
 	int ret;
@@ -194,6 +196,11 @@ static int ytphy_startup(struct phy_device *phydev)
 {
 {
 	int retval;
 	int retval;
 
 
+	/*set delay config*/
+	retval = ytphy_of_config(phydev);
+	if (retval < 0)
+		return retval;
+
 	retval = genphy_update_link(phydev);
 	retval = genphy_update_link(phydev);
 	if (retval)
 	if (retval)
 		return retval;
 		return retval;
@@ -256,6 +263,7 @@ static int ytphy_of_config(struct phy_device *phydev)
 
 
 		cfg = ofnode_read_u32_default(node,
 		cfg = ofnode_read_u32_default(node,
 			ytphy_rxtxd_grp[i].name, ~0);
 			ytphy_rxtxd_grp[i].name, ~0);
+
 		cfg = (cfg != -1) ? cfg : ytphy_rxtxd_grp[i].dflt;
 		cfg = (cfg != -1) ? cfg : ytphy_rxtxd_grp[i].dflt;
 
 
 		/*check the cfg overflow or not*/
 		/*check the cfg overflow or not*/
@@ -369,10 +377,6 @@ static int yt8531_config(struct phy_device *phydev)
 	ret = 0;
 	ret = 0;
 	genphy_config_aneg(phydev);
 	genphy_config_aneg(phydev);
 
 
-	/*set delay config*/
-	ret = ytphy_of_config(phydev);
-	if (ret < 0)
-		return ret;
 	return 0;
 	return 0;
 }
 }
 
 

+ 30 - 5
drivers/pci/pcie_starfive.c

@@ -103,6 +103,8 @@ struct starfive_pcie {
 
 
 	int atr_table_num;
 	int atr_table_num;
 	int first_busno;
 	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)
 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;
 		goto err_deassert_clk;
 	}
 	}
 
 
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_EVB) || CONFIG_IS_ENABLED(TARGET_STARFIVE_DEVKITS)
 	ret = pinctrl_select_state(dev, "power-active");
 	ret = pinctrl_select_state(dev, "power-active");
 	if (ret) {
 	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");
 	ret = pinctrl_select_state(dev, "perst-active");
 	if (ret) {
 	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 */
 	/* Disable physical functions except #0 */
@@ -440,14 +459,20 @@ static int starfive_pcie_init_port(struct udevice *dev)
 	mdelay(100);
 	mdelay(100);
 	ret = pinctrl_select_state(dev, "perst-default");
 	ret = pinctrl_select_state(dev, "perst-default");
 	if (ret) {
 	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 ret;
 	}
 	}
 
 
 	return 0;
 	return 0;
 
 
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_EVB) || CONFIG_IS_ENABLED(TARGET_STARFIVE_DEVKITS)
 err_release_power_pin:
 err_release_power_pin:
 	pinctrl_select_state(dev, "power-default");
 	pinctrl_select_state(dev, "power-default");
+#endif
 err_deassert_reset:
 err_deassert_reset:
 	reset_assert_bulk(&priv->rsts);
 	reset_assert_bulk(&priv->rsts);
 err_deassert_clk:
 err_deassert_clk:

+ 13 - 2
drivers/pinctrl/starfive/Kconfig

@@ -1,8 +1,20 @@
 # SPDX-License-Identifier: GPL-2.0-only
 # 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
 config PINCTRL_STARFIVE
 	bool "Pinctrl driver for StarFive SoC"
 	bool "Pinctrl driver for StarFive SoC"
-	depends on PINCTRL_FULL
+	depends on PINCTRL_FULL && STARFIVE_JH7110
 	help
 	help
 	  Say yes here to support pin control on the StarFive RISC-V SoC.
 	  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
 	  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
 	depends on  PINCTRL_STARFIVE
 	help
 	help
 	  This selects the pinctrl driver for JH7110 starfive.
 	  This selects the pinctrl driver for JH7110 starfive.
-

+ 2 - 5
drivers/pinctrl/starfive/Makefile

@@ -1,9 +1,6 @@
 
 
 # SPDX-License-Identifier: GPL-2.0
 # SPDX-License-Identifier: GPL-2.0
 # Core
 # Core
-obj-$(CONFIG_PINCTRL_STARFIVE) += pinctrl-starfive.o
+obj-$(CONFIG_$(SPL_TPL_)PINCTRL_STARFIVE) += pinctrl-starfive.o
 # SoC Drivers
 # 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)
 static int jh7110_sys_pinctrl_probe(struct udevice *dev)
 {
 {
+	u32 value;
+	int ret;
 	struct starfive_pinctrl_soc_info *info =
 	struct starfive_pinctrl_soc_info *info =
 		(struct starfive_pinctrl_soc_info *)dev_get_driver_data(dev);
 		(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[] = {
 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
 	Say Y here if you want to enable support for seeed
 	800X480 DSI video mode panel.
 	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
 config VIDEO_LCD_SSD2828
 	bool "SSD2828 bridge chip"
 	bool "SSD2828 bridge chip"
 	default n
 	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_HITACHI_TX18D42VM) += hitachi_tx18d42vm_lcd.o
 obj-$(CONFIG_VIDEO_LCD_ORISETECH_OTM8009A) += orisetech_otm8009a.o
 obj-$(CONFIG_VIDEO_LCD_ORISETECH_OTM8009A) += orisetech_otm8009a.o
 obj-$(CONFIG_VIDEO_LCD_RAYDIUM_RM68200) += raydium-rm68200.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_SSD2828) += ssd2828.o
 obj-$(CONFIG_VIDEO_LCD_TDO_TL070WSH30) += tdo-tl070wsh30.o
 obj-$(CONFIG_VIDEO_LCD_TDO_TL070WSH30) += tdo-tl070wsh30.o
 obj-$(CONFIG_VIDEO_MCDE_SIMPLE) += mcde_simple.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);
 	ret = wait_for_send_done(dsi, MIPI_FIFO_TIMEOUT);
 	if (!ret) {
 	if (!ret) {
-		printf("wait tx done timeout!\n");
+		debug("wait tx done timeout!\n");
 		return -ETIMEDOUT;
 		return -ETIMEDOUT;
 	}
 	}
 	udelay(10);
 	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");
 	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) {
 	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;
 		return -EINVAL;
 	}
 	}
 	priv->link_initialized = false;
 	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->init(priv->device);
 	priv->phy_ops->post_set_mode(priv->device, MIPI_DSI_MODE_VIDEO);
 	priv->phy_ops->post_set_mode(priv->device, MIPI_DSI_MODE_VIDEO);
 	cdns_dsi_init_link(priv, priv->device);
 	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;
 	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)
 	if (!priv)
 		return;
 		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,
 	sf_dphy_set_reg(priv->phy_reg + 0x8, 0x10,
 					RG_CDTX_L0N_HSTX_RES_SHIFT, RG_CDTX_L0N_HSTX_RES_MASK);
 					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
 							CFG_L0_SWAP_SEL_SHIFT, CFG_L0_SWAP_SEL_MASK);//Lane setting
 			sf_dphy_set_reg(priv->phy_reg, 0x1,
 			sf_dphy_set_reg(priv->phy_reg, 0x1,
 							CFG_L1_SWAP_SEL_SHIFT, CFG_L1_SWAP_SEL_MASK);
 							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,
 			sf_dphy_set_reg(priv->phy_reg, 0x4,
 							CFG_L2_SWAP_SEL_SHIFT, CFG_L2_SWAP_SEL_MASK);
 							CFG_L2_SWAP_SEL_SHIFT, CFG_L2_SWAP_SEL_MASK);
 			sf_dphy_set_reg(priv->phy_reg, 0x2,
 			sf_dphy_set_reg(priv->phy_reg, 0x2,
 							CFG_L3_SWAP_SEL_SHIFT, CFG_L3_SWAP_SEL_MASK);
 							CFG_L3_SWAP_SEL_SHIFT, CFG_L3_SWAP_SEL_MASK);
 			sf_dphy_set_reg(priv->phy_reg, 0x3,
 			sf_dphy_set_reg(priv->phy_reg, 0x3,
 							CFG_L4_SWAP_SEL_SHIFT, CFG_L4_SWAP_SEL_MASK);
 							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
 			//PLL setting
 			sf_dphy_set_reg(priv->phy_reg + 0x1c, 0x0,
 			sf_dphy_set_reg(priv->phy_reg + 0x1c, 0x0,
 							RG_CDTX_PLL_SSC_EN_SHIFT, RG_CDTX_PLL_SSC_EN_MASK);
 							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;
 	struct display_timing timings;
 	int ret;
 	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);
 	ret = uclass_first_device(UCLASS_PANEL, &priv->panel);
 	if (ret) {
 	if (ret) {
 		debug("panel device error %d\n", ret);
 		debug("panel device error %d\n", ret);
 		return ret;
 		return ret;
 	}
 	}
+#endif
+
 	debug("%s,priv->panel->name = %s\n", __func__,priv->panel->name);
 	debug("%s,priv->panel->name = %s\n", __func__,priv->panel->name);
 
 
 	mplat = dev_get_plat(priv->panel);
 	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),
 		ret = ofnode_decode_display_timing(dev_ofnode(priv->panel),
 						   0, &timings);
 						   0, &timings);
 		if (ret) {
 		if (ret) {
-			printf("decode display timing error %d\n", ret);
+			debug("decode display timing error %d\n", ret);
 			return ret;
 			return ret;
 		}
 		}
 	}
 	}
+	priv->timings = timings;
 
 
 	ret = uclass_get_device(UCLASS_DSI_HOST, 0, &priv->dsi_host);
 	ret = uclass_get_device(UCLASS_DSI_HOST, 0, &priv->dsi_host);
 	if (ret) {
 	if (ret) {
-		printf("No video dsi host detected %d\n", ret);
+		debug("No video dsi host detected %d\n", ret);
 		return ret;
 		return ret;
 	}
 	}
 
 
@@ -279,7 +308,7 @@ static int dsi_sf_attach(struct udevice *dev)
 			mplat->lanes,
 			mplat->lanes,
 			&dsi_stm_phy_ops);
 			&dsi_stm_phy_ops);
 	if (ret) {
 	if (ret) {
-		printf("failed to initialize mipi dsi host\n");
+		debug("failed to initialize mipi dsi host\n");
 		return ret;
 		return ret;
 	}
 	}
 
 
@@ -293,13 +322,13 @@ static int dsi_sf_set_backlight(struct udevice *dev, int percent)
 
 
 	ret = dsi_host_enable(priv->dsi_host);
 	ret = dsi_host_enable(priv->dsi_host);
 	if (ret) {
 	if (ret) {
-		printf("failed to enable mipi dsi host\n");
+		debug("failed to enable mipi dsi host\n");
 		return ret;
 		return ret;
 	}
 	}
 
 
 	ret = panel_enable_backlight(priv->panel);
 	ret = panel_enable_backlight(priv->panel);
 	if (ret) {
 	if (ret) {
-		printf("panel %s enable backlight error %d\n",
+		debug("panel %s enable backlight error %d\n",
 			priv->panel->name, ret);
 			priv->panel->name, ret);
 		return 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);
 	ret = dev_read_u32(dev, "data-lanes-num", &priv->data_lanes);
 	if (ret) {
 	if (ret) {
-		printf("fail to get data lanes property %d\n", ret);
+		debug("fail to get data lanes property %d\n", ret);
 		return 0;
 		return 0;
 	}
 	}
 
 
@@ -499,13 +528,13 @@ static int dsi_sf_probe(struct udevice *dev)
 
 
 	debug("%s ok: ID_REG val = %08x\n", __func__, val);
 	debug("%s ok: ID_REG val = %08x\n", __func__, val);
 	if (REV_VENDOR_ID(val) != 0xcad) {
 	if (REV_VENDOR_ID(val) != 0xcad) {
-		printf("invalid vendor id\n");
+		debug("invalid vendor id\n");
 		ret = -EINVAL;
 		ret = -EINVAL;
 	}
 	}
 
 
 	ret = cdns_check_register_access(dev);
 	ret = cdns_check_register_access(dev);
     if (ret) {
     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);
 	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 *panel;
 	struct udevice *dsi_host;
 	struct udevice *dsi_host;
 	unsigned int data_lanes;
 	unsigned int data_lanes;
+	struct display_timing timings;
 
 
 	struct clk dsi_sys_clk;
 	struct clk dsi_sys_clk;
 	struct clk apb_clk;
 	struct clk apb_clk;

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

@@ -29,6 +29,7 @@
 #include <panel.h>
 #include <panel.h>
 
 
 #include "sf_vop.h"
 #include "sf_vop.h"
+#include "sf_mipi.h"
 
 
 DECLARE_GLOBAL_DATA_PTR;
 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)
 static int sf_vop_power_off(struct udevice *dev)
 {
 {
 	struct udevice *dev_power;
 	struct udevice *dev_power;
-	struct udevice *dev_pmic;
 	struct power_domain_ops *ops;
 	struct power_domain_ops *ops;
 	struct power_domain power_domain;
 	struct power_domain power_domain;
 	int ret;
 	int ret;
@@ -76,7 +76,9 @@ static int sf_vop_power_off(struct udevice *dev)
 static int sf_vop_power(struct udevice *dev)
 static int sf_vop_power(struct udevice *dev)
 {
 {
 	struct udevice *dev_power;
 	struct udevice *dev_power;
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_EVB)
 	struct udevice *dev_pmic;
 	struct udevice *dev_pmic;
+#endif
 	struct power_domain_ops *ops;
 	struct power_domain_ops *ops;
 	struct power_domain power_domain;
 	struct power_domain power_domain;
 	int ret;
 	int ret;
@@ -108,6 +110,7 @@ static int sf_vop_power(struct udevice *dev)
 		return ret;
 		return ret;
 	}
 	}
 
 
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_EVB)
 	ret = uclass_get_device_by_driver(UCLASS_PMIC,
 	ret = uclass_get_device_by_driver(UCLASS_PMIC,
 			  DM_DRIVER_GET(pmic_starfive), &dev_pmic);
 			  DM_DRIVER_GET(pmic_starfive), &dev_pmic);
 	if (ret) {
 	if (ret) {
@@ -120,6 +123,7 @@ static int sf_vop_power(struct udevice *dev)
 		pr_err("failed to update SD control register: %d", ret);
 		pr_err("failed to update SD control register: %d", ret);
 		return ret;
 		return ret;
 	}
 	}
+#endif
 
 
 	return 0;
 	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__,
 	debug("%s(%s, 0x%lx, %s)\n", __func__,
 			  dev_read_name(dev), fbbase, ofnode_get_name(ep_node));
 			  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;
 	struct udevice *panel = NULL;
+#endif
 
 
 	ret = ofnode_read_u32(ep_node, "remote-endpoint", &remote_phandle);
 	ret = ofnode_read_u32(ep_node, "remote-endpoint", &remote_phandle);
 	if (ret)
 	if (ret)
@@ -576,6 +582,7 @@ static int sf_display_init(struct udevice *dev, ulong fbbase, ofnode ep_node)
 			return ret;
 			return ret;
 		}
 		}
 
 
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_EVB) || CONFIG_IS_ENABLED(TARGET_STARFIVE_VISIONFIVE2)
 		ret = uclass_first_device_err(UCLASS_PANEL, &panel);
 		ret = uclass_first_device_err(UCLASS_PANEL, &panel);
 		if (ret) {
 		if (ret) {
 			if (ret != -ENODEV)
 			if (ret != -ENODEV)
@@ -592,6 +599,7 @@ static int sf_display_init(struct udevice *dev, ulong fbbase, ofnode ep_node)
 				return ret;
 				return ret;
 			}
 			}
 		}
 		}
+#endif
 
 
 		int err = clk_set_parent(&priv->dc_pix0, &priv->dc_pix_src);
 		int err = clk_set_parent(&priv->dc_pix0, &priv->dc_pix_src);
 		if (err) {
 		if (err) {
@@ -600,17 +608,40 @@ static int sf_display_init(struct udevice *dev, ulong fbbase, ofnode ep_node)
 			return err;
 			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);
 		ulong new_rate = clk_set_rate(&priv->dc_pix_src, timing.pixelclock.typ);
 		debug("new_rate  %ld\n", new_rate);
 		debug("new_rate  %ld\n", new_rate);
+#endif
 
 
 		dc_hw_init(dev);
 		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->xsize = timing.hactive.typ;
 		uc_priv->ysize = timing.vactive.typ;
 		uc_priv->ysize = timing.vactive.typ;
 
 
 		if (IS_ENABLED(CONFIG_VIDEO_COPY))
 		if (IS_ENABLED(CONFIG_VIDEO_COPY))
 			uc_plat->copy_base = uc_plat->base - uc_plat->size / 2;
 			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(0xc0001fff, priv->regs_hi+0x00000014); //csr_reg
 		writel(0x000000e8, priv->regs_hi+0x00001a38); //csr_reg
 		writel(0x000000e8, priv->regs_hi+0x00001a38); //csr_reg
 		writel(0x00002000, priv->regs_hi+0x00001cc0); //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(0x00000000, priv->regs_hi+0x000024fc); //csr_reg
 		writel(0x00011b25, priv->regs_hi+0x000024e8); //csr_reg
 		writel(0x00011b25, priv->regs_hi+0x000024e8); //csr_reg
 		writel(0x00000001, priv->regs_hi+0x00001ccc); //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;
 	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.
  * Author(s): Yannick Fertre <yannick.fertre@st.com> for STMicroelectronics.
  *            Philippe Cornu <philippe.cornu@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 <common.h>
 #include <backlight.h>
 #include <backlight.h>
@@ -145,15 +145,16 @@ enum REG_ADDR {
 /* Chip/Rev Registers */
 /* Chip/Rev Registers */
 #define IDREG 0x04A0
 #define IDREG 0x04A0
 
 
-/* Debug Registers */
+/* printf Registers */
 #define WCMDQUEUE 0x0500
 #define WCMDQUEUE 0x0500
 #define RCMDQUEUE 0x0504
 #define RCMDQUEUE 0x0504
 
 
 
 
-struct rm68200_panel_priv {
+struct seeed_panel_priv {
 	struct udevice *reg;
 	struct udevice *reg;
 	struct udevice *backlight;
 	struct udevice *backlight;
-	struct gpio_desc reset;
+	struct gpio_desc *sel_gpio;   //select
+
 };
 };
 
 
 static const struct display_timing default_timing = {
 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)
 static int rm68200_panel_probe(struct udevice *dev)
 {
 {
 	struct mipi_dsi_panel_plat *plat = dev_get_plat(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;
 	u8 reg_value = 0;
 
 
@@ -315,6 +319,17 @@ static int rm68200_panel_probe(struct udevice *dev)
 		   return -ENODEV;
 		   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;
 	return 0;
 }
 }
 
 
@@ -324,17 +339,17 @@ static const struct panel_ops rm68200_panel_ops = {
 };
 };
 
 
 static const struct udevice_id rm68200_panel_ids[] = {
 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,
 	.id			  = UCLASS_PANEL,
 	.of_match		  = rm68200_panel_ids,
 	.of_match		  = rm68200_panel_ids,
 	.ops			  = &rm68200_panel_ops,
 	.ops			  = &rm68200_panel_ops,
 	.of_to_plat	  = rm68200_panel_of_to_plat,
 	.of_to_plat	  = rm68200_panel_of_to_plat,
 	.probe			  = rm68200_panel_probe,
 	.probe			  = rm68200_panel_probe,
 	.plat_auto	= sizeof(struct mipi_dsi_panel_plat),
 	.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
 		 * frame buffer
 		 */
 		 */
 		if (offset < -priv->fb_size || offset > 2 * priv->fb_size) {
 		if (offset < -priv->fb_size || offset > 2 * priv->fb_size) {
-#if DEBUG
+#ifdef DEBUG
 			char str[80];
 			char str[80];
 
 
 			snprintf(str, sizeof(str),
 			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, \
 	EFI_GUID(0x1e2ed096, 0x30e2, 0x4254, 0xbd, \
 		 0x89, 0x86, 0x3b, 0xbe, 0xf8, 0x23, 0x25)
 		 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 {
 struct efi_configuration_table {
 	efi_guid_t guid;
 	efi_guid_t guid;
 	void *table;
 	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);
 efi_status_t efi_rng_register(void);
 /* Called by efi_init_obj_list() to install EFI_TCG2_PROTOCOL */
 /* Called by efi_init_obj_list() to install EFI_TCG2_PROTOCOL */
 efi_status_t efi_tcg2_register(void);
 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 */
 /* measure the pe-coff image, extend PCR and add Event Log */
 efi_status_t tcg2_measure_pe_image(void *efi, u64 efi_size,
 efi_status_t tcg2_measure_pe_image(void *efi, u64 efi_size,
 				   struct efi_loaded_image_obj *handle,
 				   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 last_stage_init(void);
 int mac_read_from_eeprom(void);
 int mac_read_from_eeprom(void);
 int set_cpu_clk_info(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 update_flash_size(int flash_size);
 int arch_early_init_r(void);
 int arch_early_init_r(void);
 int misc_init_r(void);
 int misc_init_r(void);

+ 10 - 0
lib/efi_loader/Kconfig

@@ -374,4 +374,14 @@ config EFI_ESRT
 	help
 	help
 	  Enabling this option creates the ESRT UEFI system table.
 	  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
 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_GENERATE_SMBIOS_TABLE) += efi_smbios.o
 obj-$(CONFIG_EFI_RNG_PROTOCOL) += efi_rng.o
 obj-$(CONFIG_EFI_RNG_PROTOCOL) += efi_rng.o
 obj-$(CONFIG_EFI_TCG2_PROTOCOL) += efi_tcg2.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_LOAD_FILE2_INITRD) += efi_load_initrd.o
 obj-$(CONFIG_EFI_SIGNATURE_SUPPORT) += efi_signature.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;
 			goto out;
 	}
 	}
 
 
+	if (IS_ENABLED(CONFIG_EFI_RISCV_BOOT_PROTOCOL)) {
+		ret = efi_riscv_register();
+		if (ret != EFI_SUCCESS)
+			goto out;
+	}
+
 	/* Secure boot */
 	/* Secure boot */
 	ret = efi_init_secure_boot();
 	ret = efi_init_secure_boot();
 	if (ret != EFI_SUCCESS)
 	if (ret != EFI_SUCCESS)