summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandy.hu <andy.hu@starfivetech.com>2023-11-29 12:13:51 +0300
committerandy.hu <andy.hu@starfivetech.com>2023-11-29 12:13:51 +0300
commit918eb904cfbc79a48552fe4c842938a94fd3c1d5 (patch)
treeb8370976a4fb56985bd6a974b1e864ae1240922e
parentb9ea242a49cd2e7d84ca0ea9086e8a76cd92e485 (diff)
parent4bf24b47175bd55813612f0d162defcb65b94d13 (diff)
downloadu-boot-918eb904cfbc79a48552fe4c842938a94fd3c1d5.tar.xz
Merge branch 'CR_6790_MergeUboot_hal.feng' into 'jh7110-master'
CR_6790_MergeUboot_hal.feng See merge request sdk/u-boot!74
-rw-r--r--arch/riscv/Kconfig10
-rw-r--r--arch/riscv/dts/Makefile3
-rw-r--r--arch/riscv/dts/jh7110-u-boot.dtsi8
-rw-r--r--arch/riscv/dts/jh7110.dtsi64
-rw-r--r--arch/riscv/dts/starfive_devkits-u-boot.dtsi (renamed from arch/riscv/dts/starfive_visionfive-u-boot.dtsi)9
-rw-r--r--arch/riscv/dts/starfive_devkits.dts371
-rw-r--r--arch/riscv/dts/starfive_evb.dts2
-rw-r--r--arch/riscv/dts/starfive_visionfive.dts104
-rw-r--r--arch/riscv/dts/starfive_visionfive2-u-boot.dtsi45
-rw-r--r--arch/riscv/dts/starfive_visionfive2.dts477
-rw-r--r--arch/riscv/include/asm/arch-jh7110/eeprom.h14
-rw-r--r--board/starfive/devkits/Kconfig (renamed from board/starfive/visionfive/Kconfig)6
-rw-r--r--board/starfive/devkits/MAINTAINERS7
-rw-r--r--board/starfive/devkits/Makefile10
-rw-r--r--board/starfive/devkits/devkits-i2c-eeprom.c758
-rw-r--r--board/starfive/devkits/spl.c166
-rw-r--r--board/starfive/devkits/starfive_devkits.c482
-rw-r--r--board/starfive/visionfive/MAINTAINERS7
-rw-r--r--board/starfive/visionfive/spl.c85
-rwxr-xr-xboard/starfive/visionfive/starfive_visionfive.c207
-rw-r--r--board/starfive/visionfive2/Kconfig52
-rw-r--r--board/starfive/visionfive2/MAINTAINERS7
-rw-r--r--board/starfive/visionfive2/Makefile (renamed from board/starfive/visionfive/Makefile)4
-rw-r--r--board/starfive/visionfive2/spl.c189
-rw-r--r--board/starfive/visionfive2/starfive_visionfive2.c547
-rw-r--r--board/starfive/visionfive2/visionfive2-i2c-eeprom.c832
-rw-r--r--cmd/Kconfig31
-rw-r--r--cmd/eeprom.c43
-rw-r--r--cmd/i2c.c2
-rw-r--r--common/board_r.c3
-rw-r--r--configs/starfive_devkits_defconfig171
-rw-r--r--configs/starfive_visionfive2_defconfig168
-rw-r--r--configs/starfive_visionfive_defconfig75
-rw-r--r--drivers/clk/starfive/clk-jh7110.c70
-rw-r--r--drivers/i2c/Kconfig7
-rw-r--r--drivers/i2c/Makefile2
-rw-r--r--drivers/mmc/dw_mmc.c4
-rw-r--r--drivers/net/dwc_eth_qos.c13
-rw-r--r--drivers/net/phy/motorcomm.c12
-rw-r--r--drivers/pci/pcie_starfive.c35
-rw-r--r--drivers/pinctrl/starfive/Kconfig15
-rw-r--r--drivers/pinctrl/starfive/Makefile7
-rwxr-xr-xdrivers/pinctrl/starfive/pinctrl-jh7110-sys.c15
-rw-r--r--drivers/video/Kconfig9
-rw-r--r--drivers/video/Makefile3
-rw-r--r--drivers/video/starfive/mipi_dsi_host.c51
-rw-r--r--drivers/video/starfive/sf_mipi.c47
-rw-r--r--drivers/video/starfive/sf_mipi.h1
-rw-r--r--drivers/video/starfive/sf_vop.c142
-rw-r--r--drivers/video/starfive_edp.c1302
-rw-r--r--drivers/video/starfive_seeed_panel.c (renamed from drivers/video/raydium-rm68200-starfive.c)33
-rw-r--r--drivers/video/video-uclass.c2
-rw-r--r--include/configs/starfive-devkits.h405
-rw-r--r--include/configs/starfive-visionfive.h151
-rw-r--r--include/configs/starfive-visionfive2.h374
-rw-r--r--include/efi_api.h25
-rw-r--r--include/efi_loader.h4
-rw-r--r--include/efi_riscv.h24
-rw-r--r--include/init.h3
-rw-r--r--lib/efi_loader/Kconfig10
-rw-r--r--lib/efi_loader/Makefile1
-rw-r--r--lib/efi_loader/efi_riscv.c60
-rw-r--r--lib/efi_loader/efi_setup.c6
63 files changed, 7021 insertions, 771 deletions
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 2cff0d9536..b8adf6ba36 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -23,8 +23,11 @@ config TARGET_SIFIVE_UNLEASHED
config TARGET_SIFIVE_UNMATCHED
bool "Support SiFive Unmatched Board"
-config TARGET_STARFIVE_VISIONFIVE
- bool "Support StarFive VisionFive Board"
+config TARGET_STARFIVE_DEVKITS
+ bool "Support StarFive DevKits Board"
+
+config TARGET_STARFIVE_VISIONFIVE2
+ bool "Support StarFive VisionFive2 Board"
config TARGET_STARFIVE_EVB
bool "Support StarFive Evb Board"
@@ -71,7 +74,8 @@ source "board/sifive/unleashed/Kconfig"
source "board/sifive/unmatched/Kconfig"
source "board/openpiton/riscv64/Kconfig"
source "board/sipeed/maix/Kconfig"
-source "board/starfive/visionfive/Kconfig"
+source "board/starfive/devkits/Kconfig"
+source "board/starfive/visionfive2/Kconfig"
source "board/starfive/evb/Kconfig"
# platform-specific options below
diff --git a/arch/riscv/dts/Makefile b/arch/riscv/dts/Makefile
index d433afa6f4..79679c91ad 100644
--- a/arch/riscv/dts/Makefile
+++ b/arch/riscv/dts/Makefile
@@ -7,7 +7,8 @@ dtb-$(CONFIG_TARGET_OPENPITON_RISCV64) += openpiton-riscv64.dtb
dtb-$(CONFIG_TARGET_SIFIVE_UNLEASHED) += hifive-unleashed-a00.dtb
dtb-$(CONFIG_TARGET_SIFIVE_UNMATCHED) += hifive-unmatched-a00.dtb
dtb-$(CONFIG_TARGET_SIPEED_MAIX) += k210-maix-bit.dtb
-dtb-$(CONFIG_TARGET_STARFIVE_VISIONFIVE) += starfive_visionfive.dtb
+dtb-$(CONFIG_TARGET_STARFIVE_DEVKITS) += starfive_devkits.dtb
+dtb-$(CONFIG_TARGET_STARFIVE_VISIONFIVE2) += starfive_visionfive2.dtb
dtb-$(CONFIG_TARGET_STARFIVE_EVB) += starfive_evb.dtb
targets += $(dtb-y)
diff --git a/arch/riscv/dts/jh7110-u-boot.dtsi b/arch/riscv/dts/jh7110-u-boot.dtsi
index e45b6cde3b..37586fdc15 100644
--- a/arch/riscv/dts/jh7110-u-boot.dtsi
+++ b/arch/riscv/dts/jh7110-u-boot.dtsi
@@ -129,3 +129,11 @@
&gmac0_rmii_refin {
u-boot,dm-spl;
};
+
+&gpio {
+ u-boot,dm-spl;
+};
+
+&gpioa {
+ u-boot,dm-spl;
+};
diff --git a/arch/riscv/dts/jh7110.dtsi b/arch/riscv/dts/jh7110.dtsi
index 3f3098b96b..d8f62454fd 100644
--- a/arch/riscv/dts/jh7110.dtsi
+++ b/arch/riscv/dts/jh7110.dtsi
@@ -623,19 +623,6 @@
status = "disabled";
};
- i2c6: i2c@12060000 {
- compatible = "snps,designware-i2c";
- reg = <0x0 0x12060000 0x0 0x10000>;
- clocks = <&clkgen JH7110_I2C6_CLK_CORE>,
- <&clkgen JH7110_I2C6_CLK_APB>;
- clock-names = "ref", "pclk";
- resets = <&rstgen RSTN_U6_DW_I2C_APB>;
- interrupts = <51>;
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
- };
-
i2c0: i2c@10030000 {
compatible = "snps,designware-i2c";
reg = <0x0 0x10030000 0x0 0x10000>;
@@ -675,6 +662,32 @@
status = "disabled";
};
+ i2c3: i2c@12030000 {
+ compatible = "snps,designware-i2c";
+ reg = <0x0 0x12030000 0x0 0x10000>;
+ clocks = <&clkgen JH7110_I2C3_CLK_CORE>,
+ <&clkgen JH7110_I2C3_CLK_APB>;
+ clock-names = "ref", "pclk";
+ resets = <&rstgen RSTN_U3_DW_I2C_APB>;
+ interrupts = <48>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c4: i2c@12040000 {
+ compatible = "snps,designware-i2c";
+ reg = <0x0 0x12040000 0x0 0x10000>;
+ clocks = <&clkgen JH7110_I2C4_CLK_CORE>,
+ <&clkgen JH7110_I2C4_CLK_APB>;
+ clock-names = "ref", "pclk";
+ resets = <&rstgen RSTN_U4_DW_I2C_APB>;
+ interrupts = <49>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
i2c5: i2c@12050000 {
compatible = "snps,designware-i2c";
reg = <0x0 0x12050000 0x0 0x10000>;
@@ -688,6 +701,19 @@
status = "disabled";
};
+ i2c6: i2c@12060000 {
+ compatible = "snps,designware-i2c";
+ reg = <0x0 0x12060000 0x0 0x10000>;
+ clocks = <&clkgen JH7110_I2C6_CLK_CORE>,
+ <&clkgen JH7110_I2C6_CLK_APB>;
+ clock-names = "ref", "pclk";
+ resets = <&rstgen RSTN_U6_DW_I2C_APB>;
+ interrupts = <51>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
/* unremovable emmc as mmcblk0 */
sdio0: sdio0@16010000 {
compatible = "snps,dw-mshc";
@@ -856,13 +882,15 @@
"ptp_ref",
"stmmaceth",
"pclk",
- "gtxc";
+ "gtxc",
+ "rmii_rtx";
clocks = <&clkgen JH7110_GMAC0_GTXCLK>,
<&clkgen JH7110_U0_GMAC5_CLK_TX>,
<&clkgen JH7110_GMAC0_PTP>,
<&clkgen JH7110_U0_GMAC5_CLK_AHB>,
<&clkgen JH7110_U0_GMAC5_CLK_AXI>,
- <&clkgen JH7110_GMAC0_GTXC>;
+ <&clkgen JH7110_GMAC0_GTXC>,
+ <&clkgen JH7110_GMAC0_RMII_RTX>;
resets = <&rstgen RSTN_U0_DW_GMAC5_AXI64_AHB>,
<&rstgen RSTN_U0_DW_GMAC5_AXI64_AXI>;
reset-names = "ahb", "stmmaceth";
@@ -897,13 +925,15 @@
"ptp_ref",
"stmmaceth",
"pclk",
- "gtxc";
+ "gtxc",
+ "rmii_rtx";
clocks = <&clkgen JH7110_GMAC1_GTXCLK>,
<&clkgen JH7110_GMAC5_CLK_TX>,
<&clkgen JH7110_GMAC5_CLK_PTP>,
<&clkgen JH7110_GMAC5_CLK_AHB>,
<&clkgen JH7110_GMAC5_CLK_AXI>,
- <&clkgen JH7110_GMAC1_GTXC>;
+ <&clkgen JH7110_GMAC1_GTXC>,
+ <&clkgen JH7110_GMAC1_RMII_RTX>;
resets = <&rstgen RSTN_U1_DW_GMAC5_AXI64_H_N>,
<&rstgen RSTN_U1_DW_GMAC5_AXI64_A_I>;
reset-names = "ahb", "stmmaceth";
diff --git a/arch/riscv/dts/starfive_visionfive-u-boot.dtsi b/arch/riscv/dts/starfive_devkits-u-boot.dtsi
index a3efa43b5e..f508ab3554 100644
--- a/arch/riscv/dts/starfive_visionfive-u-boot.dtsi
+++ b/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>;
-}; \ No newline at end of file
diff --git a/arch/riscv/dts/starfive_devkits.dts b/arch/riscv/dts/starfive_devkits.dts
new file mode 100644
index 0000000000..489a8f90be
--- /dev/null
+++ b/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";
+};
diff --git a/arch/riscv/dts/starfive_evb.dts b/arch/riscv/dts/starfive_evb.dts
index b62f79b362..2241073470 100644
--- a/arch/riscv/dts/starfive_evb.dts
+++ b/arch/riscv/dts/starfive_evb.dts
@@ -399,7 +399,7 @@
status = "okay";
rm68200_panel: rm68200_panel@45 {
- compatible = "raydium,rm68200";
+ compatible = "starfive,seeed";
reg = <0x45>;
};
diff --git a/arch/riscv/dts/starfive_visionfive.dts b/arch/riscv/dts/starfive_visionfive.dts
deleted file mode 100644
index 70eb2567b8..0000000000
--- a/arch/riscv/dts/starfive_visionfive.dts
+++ /dev/null
@@ -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";
-};
diff --git a/arch/riscv/dts/starfive_visionfive2-u-boot.dtsi b/arch/riscv/dts/starfive_visionfive2-u-boot.dtsi
new file mode 100644
index 0000000000..7da12cf29f
--- /dev/null
+++ b/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;
+ };
+};
diff --git a/arch/riscv/dts/starfive_visionfive2.dts b/arch/riscv/dts/starfive_visionfive2.dts
new file mode 100644
index 0000000000..ec8538d9dd
--- /dev/null
+++ b/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>;
+
+ };
+
+
+};
+
diff --git a/arch/riscv/include/asm/arch-jh7110/eeprom.h b/arch/riscv/include/asm/arch-jh7110/eeprom.h
new file mode 100644
index 0000000000..bae918f153
--- /dev/null
+++ b/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 */
diff --git a/board/starfive/visionfive/Kconfig b/board/starfive/devkits/Kconfig
index d0ed065307..b5db828ae2 100644
--- a/board/starfive/visionfive/Kconfig
+++ b/board/starfive/devkits/Kconfig
@@ -1,16 +1,16 @@
-if TARGET_STARFIVE_VISIONFIVE
+if TARGET_STARFIVE_DEVKITS
config SYS_CPU
default "jh7110"
config SYS_BOARD
- default "visionfive"
+ default "devkits"
config SYS_VENDOR
default "starfive"
config SYS_CONFIG_NAME
- default "starfive-visionfive"
+ default "starfive-devkits"
config ENV_SIZE
default 0x2000 if ENV_IS_IN_SPI_FLASH
diff --git a/board/starfive/devkits/MAINTAINERS b/board/starfive/devkits/MAINTAINERS
new file mode 100644
index 0000000000..f6eee7e833
--- /dev/null
+++ b/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
diff --git a/board/starfive/devkits/Makefile b/board/starfive/devkits/Makefile
new file mode 100644
index 0000000000..40dc09b706
--- /dev/null
+++ b/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
diff --git a/board/starfive/devkits/devkits-i2c-eeprom.c b/board/starfive/devkits/devkits-i2c-eeprom.c
new file mode 100644
index 0000000000..55fbda3bcf
--- /dev/null
+++ b/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;
+}
+
diff --git a/board/starfive/devkits/spl.c b/board/starfive/devkits/spl.c
new file mode 100644
index 0000000000..d5f43b4747
--- /dev/null
+++ b/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
+
+
diff --git a/board/starfive/devkits/starfive_devkits.c b/board/starfive/devkits/starfive_devkits.c
new file mode 100644
index 0000000000..741c190d2e
--- /dev/null
+++ b/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);
+}
diff --git a/board/starfive/visionfive/MAINTAINERS b/board/starfive/visionfive/MAINTAINERS
deleted file mode 100644
index 437f6c2d24..0000000000
--- a/board/starfive/visionfive/MAINTAINERS
+++ /dev/null
@@ -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
diff --git a/board/starfive/visionfive/spl.c b/board/starfive/visionfive/spl.c
deleted file mode 100644
index 13e934de4b..0000000000
--- a/board/starfive/visionfive/spl.c
+++ /dev/null
@@ -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
-
-
diff --git a/board/starfive/visionfive/starfive_visionfive.c b/board/starfive/visionfive/starfive_visionfive.c
deleted file mode 100755
index 462781a526..0000000000
--- a/board/starfive/visionfive/starfive_visionfive.c
+++ /dev/null
@@ -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
-
diff --git a/board/starfive/visionfive2/Kconfig b/board/starfive/visionfive2/Kconfig
new file mode 100644
index 0000000000..28bde2a09b
--- /dev/null
+++ b/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
diff --git a/board/starfive/visionfive2/MAINTAINERS b/board/starfive/visionfive2/MAINTAINERS
new file mode 100644
index 0000000000..600ff9575b
--- /dev/null
+++ b/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
diff --git a/board/starfive/visionfive/Makefile b/board/starfive/visionfive2/Makefile
index 841d5d9b2d..080eed87b2 100644
--- a/board/starfive/visionfive/Makefile
+++ b/board/starfive/visionfive2/Makefile
@@ -3,7 +3,7 @@
# Copyright (C) 2022-2023 StarFive Technology Co., Ltd.
#
-obj-y := starfive_visionfive.o
+obj-y := starfive_visionfive2.o
obj-$(CONFIG_SPL_BUILD) += spl.o
-
+obj-$(CONFIG_ID_EEPROM) += visionfive2-i2c-eeprom.o
diff --git a/board/starfive/visionfive2/spl.c b/board/starfive/visionfive2/spl.c
new file mode 100644
index 0000000000..2149fc519f
--- /dev/null
+++ b/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
+
+
diff --git a/board/starfive/visionfive2/starfive_visionfive2.c b/board/starfive/visionfive2/starfive_visionfive2.c
new file mode 100644
index 0000000000..1d14c618dc
--- /dev/null
+++ b/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();
+}
diff --git a/board/starfive/visionfive2/visionfive2-i2c-eeprom.c b/board/starfive/visionfive2/visionfive2-i2c-eeprom.c
new file mode 100644
index 0000000000..5f2e698ad9
--- /dev/null
+++ b/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;
+}
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 3a857b3f6e..b2ea74de8e 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -614,6 +614,37 @@ config EEPROM_LAYOUT_HELP_STRING
Help printed with the LAYOUT VERSIONS part of the 'eeprom'
command's help.
+config SYS_I2C_EEPROM_BUS
+ int "I2C bus of the EEPROM device."
+ depends on CMD_EEPROM
+ default 0
+
+config SYS_I2C_EEPROM_ADDR_LEN
+ int "Length in bytes of the EEPROM memory array address"
+ depends on CMD_EEPROM || ID_EEPROM
+ default 1
+ range 1 2
+ help
+ Note: This is NOT the chip address length!
+
+config SYS_EEPROM_SIZE
+ depends on CMD_EEPROM
+ int "Size in bytes of the EEPROM device"
+ default 256
+
+config SYS_EEPROM_PAGE_WRITE_BITS
+ int "Number of bits used to address bytes in a single page"
+ depends on CMD_EEPROM
+ default 8
+ help
+ The EEPROM page size is 2^SYS_EEPROM_PAGE_WRITE_BITS.
+ A 64 byte page, for example would require six bits.
+
+config SYS_EEPROM_PAGE_WRITE_DELAY_MS
+ int "Number of milliseconds to delay between page writes"
+ depends on CMD_EEPROM || CMD_I2C
+ default 0
+
config LOOPW
bool "loopw"
help
diff --git a/cmd/eeprom.c b/cmd/eeprom.c
index efd6f3ac03..60b30a6946 100644
--- a/cmd/eeprom.c
+++ b/cmd/eeprom.c
@@ -15,7 +15,7 @@
* degradation (typical for EEPROM) is incured for FRAM memory:
*
* #define CONFIG_SYS_I2C_FRAM
- * #undef CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS
+ * Set CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS to 0
*
*/
@@ -31,14 +31,6 @@
#define CONFIG_SYS_I2C_SPEED 50000
#endif
-#ifndef CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS
-#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 0
-#endif
-
-#ifndef CONFIG_SYS_EEPROM_PAGE_WRITE_BITS
-#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 8
-#endif
-
#ifndef I2C_RXTX_LEN
#define I2C_RXTX_LEN 128
#endif
@@ -46,21 +38,6 @@
#define EEPROM_PAGE_SIZE (1 << CONFIG_SYS_EEPROM_PAGE_WRITE_BITS)
#define EEPROM_PAGE_OFFSET(x) ((x) & (EEPROM_PAGE_SIZE - 1))
-/*
- * for CONFIG_SYS_I2C_EEPROM_ADDR_LEN == 2 (16-bit EEPROM address) offset is
- * 0x000nxxxx for EEPROM address selectors at n, offset xxxx in EEPROM.
- *
- * for CONFIG_SYS_I2C_EEPROM_ADDR_LEN == 1 (8-bit EEPROM page address) offset is
- * 0x00000nxx for EEPROM address selectors and page number at n.
- */
-#if !defined(CONFIG_SPI) || defined(CONFIG_ENV_EEPROM_IS_ON_I2C)
-#if !defined(CONFIG_SYS_I2C_EEPROM_ADDR_LEN) || \
- (CONFIG_SYS_I2C_EEPROM_ADDR_LEN < 1) || \
- (CONFIG_SYS_I2C_EEPROM_ADDR_LEN > 2)
-#error CONFIG_SYS_I2C_EEPROM_ADDR_LEN must be 1 or 2
-#endif
-#endif
-
#if CONFIG_IS_ENABLED(DM_I2C)
static int eeprom_i2c_bus;
#endif
@@ -82,6 +59,13 @@ void eeprom_init(int bus)
#endif
}
+/*
+ * for CONFIG_SYS_I2C_EEPROM_ADDR_LEN == 2 (16-bit EEPROM address) offset is
+ * 0x000nxxxx for EEPROM address selectors at n, offset xxxx in EEPROM.
+ *
+ * for CONFIG_SYS_I2C_EEPROM_ADDR_LEN == 1 (8-bit EEPROM page address) offset is
+ * 0x00000nxx for EEPROM address selectors and page number at n.
+ */
static int eeprom_addr(unsigned dev_addr, unsigned offset, uchar *addr)
{
unsigned blk_off;
@@ -183,10 +167,11 @@ static int eeprom_rw(unsigned dev_addr, unsigned offset, uchar *buffer,
buffer += len;
offset += len;
+#if CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS > 0
if (!read)
udelay(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
}
-
+#endif
return rcode;
}
@@ -218,10 +203,10 @@ int eeprom_write(unsigned dev_addr, unsigned offset,
return ret;
}
-static int parse_numeric_param(char *str)
+static long parse_numeric_param(char *str)
{
char *endptr;
- int value = simple_strtol(str, &endptr, 16);
+ long value = simple_strtol(str, &endptr, 16);
return (*endptr != '\0') ? -1 : value;
}
@@ -243,10 +228,10 @@ static int parse_i2c_bus_addr(int *i2c_bus, ulong *i2c_addr, int argc,
int argc_no_bus = argc_no_bus_addr + 1;
int argc_bus_addr = argc_no_bus_addr + 2;
-#ifdef CONFIG_SYS_DEF_EEPROM_ADDR
+#ifdef CONFIG_SYS_I2C_EEPROM_ADDR
if (argc == argc_no_bus_addr) {
*i2c_bus = -1;
- *i2c_addr = CONFIG_SYS_DEF_EEPROM_ADDR;
+ *i2c_addr = CONFIG_SYS_I2C_EEPROM_ADDR;
return 0;
}
diff --git a/cmd/i2c.c b/cmd/i2c.c
index c7c08c4e32..cbc8bd008b 100644
--- a/cmd/i2c.c
+++ b/cmd/i2c.c
@@ -922,7 +922,7 @@ static int mod_i2c_mem(struct cmd_tbl *cmdtp, int incrflag, int flag, int argc,
if (ret)
return i2c_report_err(ret,
I2C_ERR_WRITE);
-#ifdef CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS
+#if CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS > 0
udelay(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
#endif
if (incrflag)
diff --git a/common/board_r.c b/common/board_r.c
index 630c2451a2..e75efc97ad 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -690,6 +690,9 @@ static init_fnc_t init_sequence_r[] = {
#ifdef CONFIG_ARCH_EARLY_INIT_R
arch_early_init_r,
#endif
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_DEVKITS)
+ set_pmic,
+#endif
power_init_board,
#ifdef CONFIG_MTD_NOR_FLASH
initr_flash,
diff --git a/configs/starfive_devkits_defconfig b/configs/starfive_devkits_defconfig
new file mode 100644
index 0000000000..26483b9690
--- /dev/null
+++ b/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
diff --git a/configs/starfive_visionfive2_defconfig b/configs/starfive_visionfive2_defconfig
new file mode 100644
index 0000000000..07bb1955d9
--- /dev/null
+++ b/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
diff --git a/configs/starfive_visionfive_defconfig b/configs/starfive_visionfive_defconfig
deleted file mode 100644
index 94a190cbb5..0000000000
--- a/configs/starfive_visionfive_defconfig
+++ /dev/null
@@ -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
diff --git a/drivers/clk/starfive/clk-jh7110.c b/drivers/clk/starfive/clk-jh7110.c
index 249eb130f1..5311633c4f 100644
--- a/drivers/clk/starfive/clk-jh7110.c
+++ b/drivers/clk/starfive/clk-jh7110.c
@@ -425,6 +425,58 @@ static int jh7110_clk_init(struct udevice *dev)
starfive_clk_divider(priv->sys,
"nocstg_bus", "bus_root",
SYS_OFFSET(JH7110_NOCSTG_BUS), 3));
+
+ /*I2C*/
+ clk_dm(JH7110_I2C0_CLK_APB,
+ starfive_clk_gate(priv->sys,
+ "u0_dw_i2c_clk_apb", "apb0",
+ SYS_OFFSET(JH7110_I2C0_CLK_APB)));
+ clk_dm(JH7110_I2C0_CLK_CORE,
+ starfive_clk_fix_factor(priv->sys,
+ "u0_dw_i2c_clk_core", "u0_dw_i2c_clk_apb", 1, 1));
+ clk_dm(JH7110_I2C1_CLK_APB,
+ starfive_clk_gate(priv->sys,
+ "u1_dw_i2c_clk_apb", "apb0",
+ SYS_OFFSET(JH7110_I2C1_CLK_APB)));
+ clk_dm(JH7110_I2C1_CLK_CORE,
+ starfive_clk_fix_factor(priv->sys,
+ "u1_dw_i2c_clk_core", "u1_dw_i2c_clk_apb", 1, 1));
+ clk_dm(JH7110_I2C2_CLK_APB,
+ starfive_clk_gate(priv->sys,
+ "u2_dw_i2c_clk_apb", "apb0",
+ SYS_OFFSET(JH7110_I2C2_CLK_APB)));
+ clk_dm(JH7110_I2C2_CLK_CORE,
+ starfive_clk_fix_factor(priv->sys,
+ "u2_dw_i2c_clk_core", "u2_dw_i2c_clk_apb", 1, 1));
+ clk_dm(JH7110_I2C3_CLK_APB,
+ starfive_clk_gate(priv->sys,
+ "u3_dw_i2c_clk_apb", "apb12",
+ SYS_OFFSET(JH7110_I2C3_CLK_APB)));
+ clk_dm(JH7110_I2C3_CLK_CORE,
+ starfive_clk_fix_factor(priv->sys,
+ "u3_dw_i2c_clk_core", "u3_dw_i2c_clk_apb", 1, 1));
+ clk_dm(JH7110_I2C4_CLK_APB,
+ starfive_clk_gate(priv->sys,
+ "u4_dw_i2c_clk_apb", "apb12",
+ SYS_OFFSET(JH7110_I2C4_CLK_APB)));
+ clk_dm(JH7110_I2C4_CLK_CORE,
+ starfive_clk_fix_factor(priv->sys,
+ "u4_dw_i2c_clk_core", "u4_dw_i2c_clk_apb", 1, 1));
+ clk_dm(JH7110_I2C5_CLK_APB,
+ starfive_clk_gate(priv->sys,
+ "u5_dw_i2c_clk_apb", "apb12",
+ SYS_OFFSET(JH7110_I2C5_CLK_APB)));
+ clk_dm(JH7110_I2C5_CLK_CORE,
+ starfive_clk_fix_factor(priv->sys,
+ "u5_dw_i2c_clk_core", "u5_dw_i2c_clk_apb", 1, 1));
+ clk_dm(JH7110_I2C6_CLK_APB,
+ starfive_clk_gate(priv->sys,
+ "u6_dw_i2c_clk_apb", "apb12",
+ SYS_OFFSET(JH7110_I2C6_CLK_APB)));
+ clk_dm(JH7110_I2C6_CLK_CORE,
+ starfive_clk_fix_factor(priv->sys,
+ "u6_dw_i2c_clk_core", "u6_dw_i2c_clk_apb", 1, 1));
+
/*QSPI*/
clk_dm(JH7110_QSPI_CLK_AHB,
starfive_clk_gate(priv->sys,
@@ -699,24 +751,6 @@ static int jh7110_clk_init(struct udevice *dev)
"u0_dom_vout_top_clk_mipiphy_ref", "osc",
SYS_OFFSET(JH7110_MCLK_INNER), 2));
- /*i2c5*/
- clk_dm(JH7110_I2C5_CLK_APB,
- starfive_clk_gate(priv->sys,
- "u5_dw_i2c_clk_apb", "apb0",
- SYS_OFFSET(JH7110_I2C5_CLK_APB)));
- clk_dm(JH7110_I2C5_CLK_CORE,
- starfive_clk_fix_factor(priv->sys,
- "u5_dw_i2c_clk_core", "u5_dw_i2c_clk_apb", 1, 1));
-
- /*i2c2*/
- clk_dm(JH7110_I2C2_CLK_APB,
- starfive_clk_gate(priv->sys,
- "u2_dw_i2c_clk_apb", "apb0",
- SYS_OFFSET(JH7110_I2C2_CLK_APB)));
- clk_dm(JH7110_I2C2_CLK_CORE,
- starfive_clk_fix_factor(priv->sys,
- "u2_dw_i2c_clk_core", "u2_dw_i2c_clk_apb", 1, 1));
-
/*pcie0*/
clk_dm(JH7110_PCIE0_CLK_TL,
starfive_clk_gate(priv->stg,
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 63d03a3ceb..a19370c8a1 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -158,6 +158,13 @@ config SYS_I2C_DW
controller is used in various SoCs, e.g. the ST SPEAr, Altera
SoCFPGA, Synopsys ARC700 and some Intel x86 SoCs.
+config SPL_SYS_I2C_DW
+ bool "Designware I2C Controller in SPL"
+ default n
+ help
+ Say yes here to select the Designware I2C Host Controller in SPL. This
+ controller is used in StarFive JH7110 SoC.
+
config SYS_I2C_ASPEED
bool "Aspeed I2C Controller"
depends on DM_I2C && ARCH_ASPEED
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 69bd27c7cd..d25ddbe05d 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -17,7 +17,7 @@ obj-$(CONFIG_SYS_I2C_AT91) += at91_i2c.o
obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
obj-$(CONFIG_SYS_I2C_CA) += i2c-cortina.o
obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
-obj-$(CONFIG_SYS_I2C_DW) += designware_i2c.o
+obj-$(CONFIG_$(SPL_)SYS_I2C_DW) += designware_i2c.o
ifdef CONFIG_ACPIGEN
ifdef CONFIG_PCI
obj-$(CONFIG_SYS_I2C_DW) += designware_i2c_pci.o
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index b3b69fabd4..c3236967f7 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -685,7 +685,11 @@ void dwmci_setup_cfg(struct mmc_config *cfg, struct dwmci_host *host,
cfg->host_caps |= MMC_MODE_4BIT;
cfg->host_caps &= ~MMC_MODE_8BIT;
}
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_VISIONFIVE2)
+ cfg->host_caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_HS200;
+#else
cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS200;
+#endif
cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
}
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index 84ad47d5bc..2910affc0c 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/drivers/net/dwc_eth_qos.c
@@ -321,6 +321,7 @@ struct eqos_priv {
bool clk_ck_enabled;
struct reset_ctl_bulk reset_bulk;
struct clk_bulk clk_bulk;
+ struct clk rmii_rtx;
};
/*
@@ -1006,6 +1007,10 @@ static int eqos_set_tx_clk_speed_jh7110(struct udevice *dev)
return ret;
}
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_VISIONFIVE2)
+ clk_set_rate(&eqos->rmii_rtx, rate);
+#endif
+
return 0;
}
@@ -1909,6 +1914,14 @@ static int eqos_probe_resources_jh7110(struct udevice *dev)
goto err_free_reset_eqos;
}
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_VISIONFIVE2)
+ ret = clk_get_by_name(dev, "rmii_rtx", &eqos->rmii_rtx);
+ if (ret) {
+ pr_err("clk_get_by_name(rmii_rtx) failed: %d", ret);
+ goto err_free_reset_eqos;
+ }
+#endif
+
ret = clk_get_bulk(dev, &eqos->clk_bulk);
if (ret) {
pr_err("clk_get_bulk failed: %d", ret);
diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c
index 94142a5a5a..6e8beac30e 100644
--- a/drivers/net/phy/motorcomm.c
+++ b/drivers/net/phy/motorcomm.c
@@ -96,6 +96,8 @@ static const struct ytphy_reg_field ytphy_rxden_grp[] = {
{ "rxc_dly_en", 1, 8, 0x1 }
};
+static int ytphy_of_config(struct phy_device *phydev);
+
static int ytphy_read_ext(struct phy_device *phydev, u32 regnum)
{
int ret;
@@ -194,6 +196,11 @@ static int ytphy_startup(struct phy_device *phydev)
{
int retval;
+ /*set delay config*/
+ retval = ytphy_of_config(phydev);
+ if (retval < 0)
+ return retval;
+
retval = genphy_update_link(phydev);
if (retval)
return retval;
@@ -256,6 +263,7 @@ static int ytphy_of_config(struct phy_device *phydev)
cfg = ofnode_read_u32_default(node,
ytphy_rxtxd_grp[i].name, ~0);
+
cfg = (cfg != -1) ? cfg : ytphy_rxtxd_grp[i].dflt;
/*check the cfg overflow or not*/
@@ -369,10 +377,6 @@ static int yt8531_config(struct phy_device *phydev)
ret = 0;
genphy_config_aneg(phydev);
- /*set delay config*/
- ret = ytphy_of_config(phydev);
- if (ret < 0)
- return ret;
return 0;
}
diff --git a/drivers/pci/pcie_starfive.c b/drivers/pci/pcie_starfive.c
index d5a812d36a..d8de9a5997 100644
--- a/drivers/pci/pcie_starfive.c
+++ b/drivers/pci/pcie_starfive.c
@@ -103,6 +103,8 @@ struct starfive_pcie {
int atr_table_num;
int first_busno;
+ struct gpio_desc *power_gpio;
+ struct gpio_desc *reset_gpio;
};
static int starfive_pcie_addr_valid(pci_dev_t bdf, int first_busno)
@@ -371,15 +373,32 @@ static int starfive_pcie_init_port(struct udevice *dev)
goto err_deassert_clk;
}
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_EVB) || CONFIG_IS_ENABLED(TARGET_STARFIVE_DEVKITS)
ret = pinctrl_select_state(dev, "power-active");
if (ret) {
- dev_err(dev, "Set power-acvtive pinctrl failed: %d\n", ret);
- goto err_deassert_reset;
+ priv->power_gpio =
+ devm_gpiod_get_optional(dev, "power", GPIOD_IS_OUT);
+ if (IS_ERR(priv->power_gpio)) {
+ dev_err(dev, "Get power-acvtive gpio failed: %d\n", ret);
+ goto err_deassert_reset;
+ }
+ dm_gpio_set_value(priv->power_gpio, 1);
}
+#endif
+
ret = pinctrl_select_state(dev, "perst-active");
if (ret) {
- dev_err(dev, "Set perst-active pinctrl failed: %d\n", ret);
- goto err_release_power_pin;
+ priv->reset_gpio =
+ devm_gpiod_get_optional(dev, "reset", GPIOD_IS_OUT);
+ if (IS_ERR(priv->reset_gpio)) {
+ dev_err(dev, "Set perst-active gpio failed: %d\n", ret);
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_EVB) || CONFIG_IS_ENABLED(TARGET_STARFIVE_DEVKITS)
+ goto err_release_power_pin;
+#else
+ goto err_deassert_reset;
+#endif
+ }
+ dm_gpio_set_value(priv->reset_gpio, 1);
}
/* Disable physical functions except #0 */
@@ -440,14 +459,20 @@ static int starfive_pcie_init_port(struct udevice *dev)
mdelay(100);
ret = pinctrl_select_state(dev, "perst-default");
if (ret) {
- dev_err(dev, "Set perst-default pinctrl failed: %d\n", ret);
+ if (priv->reset_gpio) {
+ dm_gpio_set_value(priv->reset_gpio, 0);
+ return 0;
+ } else
+ dev_err(dev, "Set perst-default pinctrl failed: %d\n", ret);
return ret;
}
return 0;
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_EVB) || CONFIG_IS_ENABLED(TARGET_STARFIVE_DEVKITS)
err_release_power_pin:
pinctrl_select_state(dev, "power-default");
+#endif
err_deassert_reset:
reset_assert_bulk(&priv->rsts);
err_deassert_clk:
diff --git a/drivers/pinctrl/starfive/Kconfig b/drivers/pinctrl/starfive/Kconfig
index 4a3afadec3..1b859c863e 100644
--- a/drivers/pinctrl/starfive/Kconfig
+++ b/drivers/pinctrl/starfive/Kconfig
@@ -1,8 +1,20 @@
# SPDX-License-Identifier: GPL-2.0-only
+config SPL_PINCTRL_STARFIVE
+ bool "Support Pinctrl driver for StarFive SoC in SPL"
+ depends on SPL_PINCTRL_FULL && STARFIVE_JH7110
+ help
+ Enable support pin control driver for StarFive SoC.
+
+config SPL_PINCTRL_STARFIVE_JH7110
+ bool "Support Pinctrl and GPIO driver for StarFive JH7110 SoC in SPL"
+ depends on SPL_PINCTRL_STARFIVE
+ help
+ Enable support pinctrl and gpio driver for StarFive JH7110 in SPL.
+
config PINCTRL_STARFIVE
bool "Pinctrl driver for StarFive SoC"
- depends on PINCTRL_FULL
+ depends on PINCTRL_FULL && STARFIVE_JH7110
help
Say yes here to support pin control on the StarFive RISC-V SoC.
This also provides an interface to the GPIO pins not used by other
@@ -14,4 +26,3 @@ config PINCTRL_STARFIVE_JH7110
depends on PINCTRL_STARFIVE
help
This selects the pinctrl driver for JH7110 starfive.
-
diff --git a/drivers/pinctrl/starfive/Makefile b/drivers/pinctrl/starfive/Makefile
index 2eac219d36..a4a12069b3 100644
--- a/drivers/pinctrl/starfive/Makefile
+++ b/drivers/pinctrl/starfive/Makefile
@@ -1,9 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
# Core
-obj-$(CONFIG_PINCTRL_STARFIVE) += pinctrl-starfive.o
+obj-$(CONFIG_$(SPL_TPL_)PINCTRL_STARFIVE) += pinctrl-starfive.o
# SoC Drivers
-obj-$(CONFIG_PINCTRL_STARFIVE_JH7110) += pinctrl-jh7110-sys.o pinctrl-jh7110-aon.o
-
-
-
+obj-$(CONFIG_$(SPL_TPL_)PINCTRL_STARFIVE_JH7110) += pinctrl-jh7110-sys.o pinctrl-jh7110-aon.o
diff --git a/drivers/pinctrl/starfive/pinctrl-jh7110-sys.c b/drivers/pinctrl/starfive/pinctrl-jh7110-sys.c
index 4e761641eb..13c1a81e92 100755
--- a/drivers/pinctrl/starfive/pinctrl-jh7110-sys.c
+++ b/drivers/pinctrl/starfive/pinctrl-jh7110-sys.c
@@ -376,10 +376,23 @@ const struct starfive_pinctrl_soc_info jh7110_sys_pinctrl_info = {
static int jh7110_sys_pinctrl_probe(struct udevice *dev)
{
+ u32 value;
+ int ret;
struct starfive_pinctrl_soc_info *info =
(struct starfive_pinctrl_soc_info *)dev_get_driver_data(dev);
+ struct starfive_pinctrl_priv *priv = dev_get_priv(dev);
+
+ ret = starfive_pinctrl_probe(dev, info);
+
+ /* Set up the usb controller overcurrent signal. */
+ if (!ret) {
+ value = readl(priv->base + JH7110_SYS_GPI);
+ value &= ~(0x7f << 16);
+ value |= BIT(16);
+ writel(value, priv->base + JH7110_SYS_GPI);
+ }
- return starfive_pinctrl_probe(dev, info);
+ return ret;
}
static const struct udevice_id jh7110_sys_pinctrl_ids[] = {
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 41d11e5daa..5116ade32a 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -439,6 +439,15 @@ config VIDEO_LCD_STARFIVE_SEEED
Say Y here if you want to enable support for seeed
800X480 DSI video mode panel.
+config VIDEO_SF_MIPI2EDP
+ bool "mipi to edp LCD panel support"
+ depends on DM_VIDEO
+ select VIDEO_MIPI_DSI
+ default n
+ help
+ Say Y here if you want to enable support for edp
+ 1920X1080 DSI video mode panel.
+
config VIDEO_LCD_SSD2828
bool "SSD2828 bridge chip"
default n
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index e84280a04f..bfab1e3d9c 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -57,7 +57,8 @@ obj-$(CONFIG_VIDEO_LCD_ANX9804) += anx9804.o
obj-$(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM) += hitachi_tx18d42vm_lcd.o
obj-$(CONFIG_VIDEO_LCD_ORISETECH_OTM8009A) += orisetech_otm8009a.o
obj-$(CONFIG_VIDEO_LCD_RAYDIUM_RM68200) += raydium-rm68200.o
-obj-$(CONFIG_VIDEO_LCD_STARFIVE_SEEED) += raydium-rm68200-starfive.o
+obj-$(CONFIG_VIDEO_LCD_STARFIVE_SEEED) += starfive_seeed_panel.o
+obj-$(CONFIG_VIDEO_SF_MIPI2EDP) += starfive_edp.o
obj-$(CONFIG_VIDEO_LCD_SSD2828) += ssd2828.o
obj-$(CONFIG_VIDEO_LCD_TDO_TL070WSH30) += tdo-tl070wsh30.o
obj-$(CONFIG_VIDEO_MCDE_SIMPLE) += mcde_simple.o
diff --git a/drivers/video/starfive/mipi_dsi_host.c b/drivers/video/starfive/mipi_dsi_host.c
index 2736eb329f..4960a22ee5 100644
--- a/drivers/video/starfive/mipi_dsi_host.c
+++ b/drivers/video/starfive/mipi_dsi_host.c
@@ -220,7 +220,7 @@ static ssize_t cdns_dsi_transfer(struct mipi_dsi_host *host,
ret = wait_for_send_done(dsi, MIPI_FIFO_TIMEOUT);
if (!ret) {
- printf("wait tx done timeout!\n");
+ debug("wait tx done timeout!\n");
return -ETIMEDOUT;
}
udelay(10);
@@ -285,7 +285,7 @@ static int mipi_dsi_northwest_init(struct udevice *dev,
priv->phy_base = (void *)dev_read_addr_name(device->dev, "phy");
if ((fdt_addr_t)priv->dsi_base == FDT_ADDR_T_NONE || (fdt_addr_t)priv->phy_base == FDT_ADDR_T_NONE) {
- printf("dsi dt register address error\n");
+ debug("dsi dt register address error\n");
return -EINVAL;
}
priv->link_initialized = false;
@@ -300,21 +300,38 @@ static int mipi_dsi_enable(struct udevice *dev)
priv->phy_ops->init(priv->device);
priv->phy_ops->post_set_mode(priv->device, MIPI_DSI_MODE_VIDEO);
cdns_dsi_init_link(priv, priv->device);
-
- writel(0x00670067, priv->dsi_base + 0x000000c0);
- writel(0x00cb0960, priv->dsi_base + 0x000000c4);
- writel(0x0003b145, priv->dsi_base + 0x000000b4);
- writel(0x000001e0, priv->dsi_base + 0x000000b8);
- writel(0x00000a9e, priv->dsi_base + 0x000000d0);
- writel(0x0a980000, priv->dsi_base + 0x000000f8);
- writel(0x00000b0f, priv->dsi_base + 0x000000cc);
- writel(0x7c3c0aae, priv->dsi_base + 0x000000dc);
- writel(0x0032dcd3, priv->dsi_base + 0x00000014);
- writel(0x00032dcd, priv->dsi_base + 0x00000018);
- writel(0x80b8fe00, priv->dsi_base + 0x000000b0);
- writel(0x00020027, priv->dsi_base + 0x00000004);
- writel(0x00004018, priv->dsi_base + 0x0000000c);
-
+ debug("priv->timings.hactive.typ %d----\n",priv->timings.hactive.typ);
+ debug("priv->timings.vactive.typ %d----\n",priv->timings.vactive.typ);
+ if (priv->timings.hactive.typ == 800)
+ {
+ writel(0x00670067, priv->dsi_base + 0x000000c0);
+ writel(0x00cb0960, priv->dsi_base + 0x000000c4);
+ writel(0x0003b145, priv->dsi_base + 0x000000b4);
+ writel(0x000001e0, priv->dsi_base + 0x000000b8);
+ writel(0x00000a9e, priv->dsi_base + 0x000000d0);
+ writel(0x0a980000, priv->dsi_base + 0x000000f8);
+ writel(0x00000b0f, priv->dsi_base + 0x000000cc);
+ writel(0x7c3c0aae, priv->dsi_base + 0x000000dc);
+ writel(0x0032dcd3, priv->dsi_base + 0x00000014);
+ writel(0x00032dcd, priv->dsi_base + 0x00000018);
+ writel(0x80b8fe00, priv->dsi_base + 0x000000b0);
+ writel(0x00020027, priv->dsi_base + 0x00000004);
+ writel(0x00004018, priv->dsi_base + 0x0000000c);
+ }else if (priv->timings.hactive.typ == 1920){
+ writel(0x01d30081, priv->dsi_base + 0x000000c0);
+ writel(0x01171680, priv->dsi_base + 0x000000c4);
+ writel(0x00003905, priv->dsi_base + 0x000000b4);
+ writel(0x00000438, priv->dsi_base + 0x000000b8);
+ writel(0x00001976, priv->dsi_base + 0x000000d0);
+ writel(0x19700000, priv->dsi_base + 0x000000f8);
+ writel(0x00001a01, priv->dsi_base + 0x000000cc);
+ writel(0x98900661, priv->dsi_base + 0x000000dc);
+ writel(0x003f9403, priv->dsi_base + 0x00000014);
+ writel(0x0003f940, priv->dsi_base + 0x00000018);
+ writel(0x80b8fe00, priv->dsi_base + 0x000000b0);
+ writel(0x00020027, priv->dsi_base + 0x00000004);
+ writel(0x000040f8, priv->dsi_base + 0x0000000c);
+ }
return 0;
}
diff --git a/drivers/video/starfive/sf_mipi.c b/drivers/video/starfive/sf_mipi.c
index 4521f7c869..d9300c5879 100644
--- a/drivers/video/starfive/sf_mipi.c
+++ b/drivers/video/starfive/sf_mipi.c
@@ -114,7 +114,13 @@ static void dsi_phy_post_set_mode(void *priv_data, unsigned long mode_flags)
if (!priv)
return;
- bitrate = 750000000;//1188M 60fps
+ // bitrate = 750000000;//1188M 60fps
+ debug("dsi_phy_post_set_mode priv->timings.hactive.typ %d----\n",priv->timings.hactive.typ);
+ debug("dsi_phy_post_set_mode priv->timings.vactive.typ %d----\n",priv->timings.vactive.typ);
+ if (priv->timings.hactive.typ == 800)
+ bitrate = 750000000;
+ else if(priv->timings.hactive.typ == 1920)
+ bitrate = 900000000;//1188M 60fps
sf_dphy_set_reg(priv->phy_reg + 0x8, 0x10,
RG_CDTX_L0N_HSTX_RES_SHIFT, RG_CDTX_L0N_HSTX_RES_MASK);
@@ -159,12 +165,21 @@ static void dsi_phy_post_set_mode(void *priv_data, unsigned long mode_flags)
CFG_L0_SWAP_SEL_SHIFT, CFG_L0_SWAP_SEL_MASK);//Lane setting
sf_dphy_set_reg(priv->phy_reg, 0x1,
CFG_L1_SWAP_SEL_SHIFT, CFG_L1_SWAP_SEL_MASK);
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_EVB)
sf_dphy_set_reg(priv->phy_reg, 0x4,
CFG_L2_SWAP_SEL_SHIFT, CFG_L2_SWAP_SEL_MASK);
sf_dphy_set_reg(priv->phy_reg, 0x2,
CFG_L3_SWAP_SEL_SHIFT, CFG_L3_SWAP_SEL_MASK);
sf_dphy_set_reg(priv->phy_reg, 0x3,
CFG_L4_SWAP_SEL_SHIFT, CFG_L4_SWAP_SEL_MASK);
+#else
+ sf_dphy_set_reg(priv->phy_reg, 0x2,
+ CFG_L2_SWAP_SEL_SHIFT, CFG_L2_SWAP_SEL_MASK);
+ sf_dphy_set_reg(priv->phy_reg, 0x3,
+ CFG_L3_SWAP_SEL_SHIFT, CFG_L3_SWAP_SEL_MASK);
+ sf_dphy_set_reg(priv->phy_reg, 0x4,
+ CFG_L4_SWAP_SEL_SHIFT, CFG_L4_SWAP_SEL_MASK);
+#endif
//PLL setting
sf_dphy_set_reg(priv->phy_reg + 0x1c, 0x0,
RG_CDTX_PLL_SSC_EN_SHIFT, RG_CDTX_PLL_SSC_EN_MASK);
@@ -246,11 +261,24 @@ static int dsi_sf_attach(struct udevice *dev)
struct display_timing timings;
int ret;
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_DEVKITS)
+ ret = uclass_get_device_by_name(UCLASS_PANEL, "seeed_panel@45", &priv->panel);
+ if (ret) {
+ debug("Could not get seeed_panel@45: %d\n", ret);
+ ret = uclass_get_device_by_name(UCLASS_PANEL, "lt8911exb_i2c@29", &priv->panel);
+ if (ret) {
+ debug("Could not get lt8911exb_i2c@29: %d\n", ret);
+ return ret;
+ }
+ }
+#else
ret = uclass_first_device(UCLASS_PANEL, &priv->panel);
if (ret) {
debug("panel device error %d\n", ret);
return ret;
}
+#endif
+
debug("%s,priv->panel->name = %s\n", __func__,priv->panel->name);
mplat = dev_get_plat(priv->panel);
@@ -264,14 +292,15 @@ static int dsi_sf_attach(struct udevice *dev)
ret = ofnode_decode_display_timing(dev_ofnode(priv->panel),
0, &timings);
if (ret) {
- printf("decode display timing error %d\n", ret);
+ debug("decode display timing error %d\n", ret);
return ret;
}
}
+ priv->timings = timings;
ret = uclass_get_device(UCLASS_DSI_HOST, 0, &priv->dsi_host);
if (ret) {
- printf("No video dsi host detected %d\n", ret);
+ debug("No video dsi host detected %d\n", ret);
return ret;
}
@@ -279,7 +308,7 @@ static int dsi_sf_attach(struct udevice *dev)
mplat->lanes,
&dsi_stm_phy_ops);
if (ret) {
- printf("failed to initialize mipi dsi host\n");
+ debug("failed to initialize mipi dsi host\n");
return ret;
}
@@ -293,13 +322,13 @@ static int dsi_sf_set_backlight(struct udevice *dev, int percent)
ret = dsi_host_enable(priv->dsi_host);
if (ret) {
- printf("failed to enable mipi dsi host\n");
+ debug("failed to enable mipi dsi host\n");
return ret;
}
ret = panel_enable_backlight(priv->panel);
if (ret) {
- printf("panel %s enable backlight error %d\n",
+ debug("panel %s enable backlight error %d\n",
priv->panel->name, ret);
return ret;
}
@@ -433,7 +462,7 @@ static int dsi_sf_probe(struct udevice *dev)
ret = dev_read_u32(dev, "data-lanes-num", &priv->data_lanes);
if (ret) {
- printf("fail to get data lanes property %d\n", ret);
+ debug("fail to get data lanes property %d\n", ret);
return 0;
}
@@ -499,13 +528,13 @@ static int dsi_sf_probe(struct udevice *dev)
debug("%s ok: ID_REG val = %08x\n", __func__, val);
if (REV_VENDOR_ID(val) != 0xcad) {
- printf("invalid vendor id\n");
+ debug("invalid vendor id\n");
ret = -EINVAL;
}
ret = cdns_check_register_access(dev);
if (ret) {
- printf("error: r/w test generic reg failed\n");
+ debug("error: r/w test generic reg failed\n");
}
val = readl(priv->dsi_reg + IP_CONF);
diff --git a/drivers/video/starfive/sf_mipi.h b/drivers/video/starfive/sf_mipi.h
index 21c82340ba..dbf7f0d246 100644
--- a/drivers/video/starfive/sf_mipi.h
+++ b/drivers/video/starfive/sf_mipi.h
@@ -786,6 +786,7 @@ struct dsi_sf_priv {
struct udevice *panel;
struct udevice *dsi_host;
unsigned int data_lanes;
+ struct display_timing timings;
struct clk dsi_sys_clk;
struct clk apb_clk;
diff --git a/drivers/video/starfive/sf_vop.c b/drivers/video/starfive/sf_vop.c
index e786032429..a167341cd9 100644
--- a/drivers/video/starfive/sf_vop.c
+++ b/drivers/video/starfive/sf_vop.c
@@ -29,6 +29,7 @@
#include <panel.h>
#include "sf_vop.h"
+#include "sf_mipi.h"
DECLARE_GLOBAL_DATA_PTR;
@@ -43,7 +44,6 @@ static void iotrace_writel(ulong value, void *ptr)
static int sf_vop_power_off(struct udevice *dev)
{
struct udevice *dev_power;
- struct udevice *dev_pmic;
struct power_domain_ops *ops;
struct power_domain power_domain;
int ret;
@@ -76,7 +76,9 @@ static int sf_vop_power_off(struct udevice *dev)
static int sf_vop_power(struct udevice *dev)
{
struct udevice *dev_power;
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_EVB)
struct udevice *dev_pmic;
+#endif
struct power_domain_ops *ops;
struct power_domain power_domain;
int ret;
@@ -108,6 +110,7 @@ static int sf_vop_power(struct udevice *dev)
return ret;
}
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_EVB)
ret = uclass_get_device_by_driver(UCLASS_PMIC,
DM_DRIVER_GET(pmic_starfive), &dev_pmic);
if (ret) {
@@ -120,6 +123,7 @@ static int sf_vop_power(struct udevice *dev)
pr_err("failed to update SD control register: %d", ret);
return ret;
}
+#endif
return 0;
}
@@ -395,7 +399,9 @@ static int sf_display_init(struct udevice *dev, ulong fbbase, ofnode ep_node)
debug("%s(%s, 0x%lx, %s)\n", __func__,
dev_read_name(dev), fbbase, ofnode_get_name(ep_node));
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_EVB) || CONFIG_IS_ENABLED(TARGET_STARFIVE_VISIONFIVE2)
struct udevice *panel = NULL;
+#endif
ret = ofnode_read_u32(ep_node, "remote-endpoint", &remote_phandle);
if (ret)
@@ -576,6 +582,7 @@ static int sf_display_init(struct udevice *dev, ulong fbbase, ofnode ep_node)
return ret;
}
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_EVB) || CONFIG_IS_ENABLED(TARGET_STARFIVE_VISIONFIVE2)
ret = uclass_first_device_err(UCLASS_PANEL, &panel);
if (ret) {
if (ret != -ENODEV)
@@ -592,6 +599,7 @@ static int sf_display_init(struct udevice *dev, ulong fbbase, ofnode ep_node)
return ret;
}
}
+#endif
int err = clk_set_parent(&priv->dc_pix0, &priv->dc_pix_src);
if (err) {
@@ -600,17 +608,40 @@ static int sf_display_init(struct udevice *dev, ulong fbbase, ofnode ep_node)
return err;
}
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_EVB) || CONFIG_IS_ENABLED(TARGET_STARFIVE_VISIONFIVE2)
ulong new_rate = clk_set_rate(&priv->dc_pix_src, timing.pixelclock.typ);
debug("new_rate %ld\n", new_rate);
+#endif
dc_hw_init(dev);
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_EVB) || CONFIG_IS_ENABLED(TARGET_STARFIVE_VISIONFIVE2)
uc_priv->xsize = timing.hactive.typ;
uc_priv->ysize = timing.vactive.typ;
if (IS_ENABLED(CONFIG_VIDEO_COPY))
uc_plat->copy_base = uc_plat->base - uc_plat->size / 2;
+#else
+ struct dsi_sf_priv *private = dev_get_priv(disp);
+
+ uc_priv->xsize = private->timings.hactive.typ;
+ uc_priv->ysize = private->timings.vactive.typ;
+ debug("uc_priv->xsize %d\n", uc_priv->xsize);
+ debug("uc_priv->ysize %d\n", uc_priv->ysize);
+
+ if(uc_priv->xsize == 800)
+ {
+ ulong new_rate = clk_set_rate(&priv->dc_pix_src, 29700000);
+ debug("new_rate %ld\n", new_rate);
+ }
+ if(uc_priv->xsize == 1920)
+ {
+ ulong new_rate = clk_set_rate(&priv->dc_pix_src, 148500000);
+ debug("new_rate %ld\n", new_rate);
+ }
+#endif
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_EVB) || CONFIG_IS_ENABLED(TARGET_STARFIVE_VISIONFIVE2)
writel(0xc0001fff, priv->regs_hi+0x00000014); //csr_reg
writel(0x000000e8, priv->regs_hi+0x00001a38); //csr_reg
writel(0x00002000, priv->regs_hi+0x00001cc0); //csr_reg
@@ -660,10 +691,115 @@ static int sf_display_init(struct udevice *dev, ulong fbbase, ofnode ep_node)
writel(0x00000000, priv->regs_hi+0x000024fc); //csr_reg
writel(0x00011b25, priv->regs_hi+0x000024e8); //csr_reg
writel(0x00000001, priv->regs_hi+0x00001ccc); //csr_reg
- priv->mipi_logo = true;
- return 0;
+#else
+ if(uc_priv->xsize == 800)
+ {
+ writel(0xc0001fff, priv->regs_hi+0x00000014); //csr_reg
+ writel(0x000000e8, priv->regs_hi+0x00001a38); //csr_reg
+ writel(0x00002000, priv->regs_hi+0x00001cc0); //csr_reg
+ writel(0x00000000, priv->regs_hi+0x000024d8); //csr_reg
+ writel(0x03c00438, priv->regs_hi+0x000024e0); //csr_reg
+ writel(0x03c00438, priv->regs_hi+0x00001810); //csr_reg
+ writel(uc_plat->base, priv->regs_hi+0x00001400);
+ writel(0x000010e0, priv->regs_hi+0x00001408); //csr_reg
+ writel(0x000fb00b, priv->regs_hi+0x00001ce8); //csr_reg
+ writel(0x0000a9a3, priv->regs_hi+0x00002510); //csr_reg
+ writel(0x2c4e6f06, priv->regs_hi+0x00002508); //csr_reg
+ writel(0xe6daec4f, priv->regs_hi+0x00002500); //csr_reg
+ writel(0x18220000, priv->regs_hi+0x00001518); //csr_reg
+ writel(0x00003000, priv->regs_hi+0x00001cc0); //csr_reg
+ writel(0x00030000, priv->regs_hi+0x00001cc4); //csr_reg
+ writel(0x00030000, priv->regs_hi+0x00001cc4); //csr_reg
+ writel(0x00050c1a, priv->regs_hi+0x00001540); //csr_reg
+ writel(0x00000001, priv->regs_hi+0x00002540); //csr_reg
+ writel(0x00050c1a, priv->regs_hi+0x00001540); //csr_reg
+ writel(0x4016120c, priv->regs_hi+0x00001544); //csr_reg
+ writel(0x00000002, priv->regs_hi+0x00002544); //csr_reg
+ writel(0x4016120c, priv->regs_hi+0x00001544); //csr_reg
+ writel(0x001b1208, priv->regs_hi+0x00001548); //csr_reg
+ writel(0x00000004, priv->regs_hi+0x00002548); //csr_reg
+ writel(0x001b1208, priv->regs_hi+0x00001548); //csr_reg
+ writel(0x0016110e, priv->regs_hi+0x0000154c); //csr_reg
+ writel(0x00000005, priv->regs_hi+0x0000254c); //csr_reg
+ writel(0x0016110e, priv->regs_hi+0x0000154c); //csr_reg
+ writel(0x00000001, priv->regs_hi+0x00002518); //csr_reg
+ writel(0x00000000, priv->regs_hi+0x00001a28); //csr_reg
+ writel(0x03840320, priv->regs_hi+0x00001430); //csr_reg, hsize, htotal
+ writel(0xc1bf837a, priv->regs_hi+0x00001438); //csr_reg, hsize blanking
+ writel(0x022601e0, priv->regs_hi+0x00001440); //csr_reg, vsize
+ writel(0xc110021c, priv->regs_hi+0x00001448); //csr_reg, vsize blanking
+ writel(0x00000000, priv->regs_hi+0x000014b0); //csr_reg
+ writel(0x000000e2, priv->regs_hi+0x00001cd0); //csr_reg
+ writel(0x000000af, priv->regs_hi+0x000014d0); //csr_reg
+ writel(0x00000005, priv->regs_hi+0x000014b8); //csr_reg
+ writel(0x8dd0b774, priv->regs_hi+0x00001528); //csr_reg
+ writel(0x00001111, priv->regs_hi+0x00001418); //csr_reg
+ writel(0x00000000, priv->regs_hi+0x00001410); //csr_reg
+ writel(0x00000000, priv->regs_hi+0x00002518); //csr_reg
+ writel(0x00000006, priv->regs_hi+0x00001468); //csr_reg
+ writel(0x00000000, priv->regs_hi+0x00001484); //csr_reg
+ writel(0x00000006, priv->regs_hi+0x00001468); //csr_reg
+ writel(0x00011b25, priv->regs_hi+0x000024e8); //csr_reg
+ writel(0x00000000, priv->regs_hi+0x000024fc); //csr_reg
+ writel(0x00011b25, priv->regs_hi+0x000024e8); //csr_reg
+ writel(0x00000001, priv->regs_hi+0x00001ccc); //csr_reg
+ }
+ if(uc_priv->xsize == 1920)
+ {
+ writel(0xc0001fff, priv->regs_hi+0x00000014);
+ writel(0x000000e8, priv->regs_hi+0x00001a38);
+ writel(0x00002000, priv->regs_hi+0x00001cc0);
+ writel(0x00000000, priv->regs_hi+0x000024d8);
+ writel(0x04380780, priv->regs_hi+0x000024e0);
+ writel(0x04380780, priv->regs_hi+0x00001810);
+ writel(uc_plat->base, priv->regs_hi+0x00001400);
+ writel(0x00001e00, priv->regs_hi+0x00001408);
+ writel(0x00000000, priv->regs_hi+0x00001ce8);
+ writel(0x0000a9a3, priv->regs_hi+0x00002510);
+ writel(0x2c4e6f06, priv->regs_hi+0x00002508);
+ writel(0xe6daec4f, priv->regs_hi+0x00002500);
+ writel(0x18220000, priv->regs_hi+0x00001518);
+ writel(0x00003000, priv->regs_hi+0x00001cc0);
+ writel(0x00030000, priv->regs_hi+0x00001cc4);
+ writel(0x00030000, priv->regs_hi+0x00001cc4);
+ writel(0x00050c1a, priv->regs_hi+0x00001540);
+ writel(0x00000001, priv->regs_hi+0x00002540);
+ writel(0x00050c1a, priv->regs_hi+0x00001540);
+ writel(0x4016120c, priv->regs_hi+0x00001544);
+ writel(0x00000002, priv->regs_hi+0x00002544);
+ writel(0x4016120c, priv->regs_hi+0x00001544);
+ writel(0x001b1208, priv->regs_hi+0x00001548);
+ writel(0x00000004, priv->regs_hi+0x00002548);
+ writel(0x001b1208, priv->regs_hi+0x00001548);
+ writel(0x0016110e, priv->regs_hi+0x0000154c);
+ writel(0x00000005, priv->regs_hi+0x0000254c);
+ writel(0x0016110e, priv->regs_hi+0x0000154c);
+ writel(0x00000001, priv->regs_hi+0x00002518);
+ writel(0x00000000, priv->regs_hi+0x00001a28);
+ writel(0x08980780, priv->regs_hi+0x00001430);
+ writel(0xc40207d8, priv->regs_hi+0x00001438);
+ writel(0x04650438, priv->regs_hi+0x00001440);
+ writel(0xc220843c, priv->regs_hi+0x00001448);
+ writel(0x00000000, priv->regs_hi+0x000014b0);
+ writel(0x000000e2, priv->regs_hi+0x00001cd0);
+ writel(0x000000af, priv->regs_hi+0x000014d0);
+ writel(0x00000005, priv->regs_hi+0x000014b8);
+ writel(0x8dd0b774, priv->regs_hi+0x00001528);
+ writel(0x00001111, priv->regs_hi+0x00001418);
+ writel(0x00000000, priv->regs_hi+0x00001410);
+ writel(0x00000000, priv->regs_hi+0x00002518);
+ writel(0x00000006, priv->regs_hi+0x00001468);
+ writel(0x00000000, priv->regs_hi+0x00001484);
+ writel(0x00000006, priv->regs_hi+0x00001468);
+ writel(0x00011b25, priv->regs_hi+0x000024e8);
+ writel(0x00000000, priv->regs_hi+0x000024fc);
+ writel(0x00011b25, priv->regs_hi+0x000024e8);
+ writel(0x00000001, priv->regs_hi+0x00001ccc);
+ }
+#endif
}
+ priv->mipi_logo = true;
return 0;
}
diff --git a/drivers/video/starfive_edp.c b/drivers/video/starfive_edp.c
new file mode 100644
index 0000000000..67f63235b4
--- /dev/null
+++ b/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),
+};
diff --git a/drivers/video/raydium-rm68200-starfive.c b/drivers/video/starfive_seeed_panel.c
index c4234d58f2..636974fd7e 100644
--- a/drivers/video/raydium-rm68200-starfive.c
+++ b/drivers/video/starfive_seeed_panel.c
@@ -4,8 +4,8 @@
* Author(s): Yannick Fertre <yannick.fertre@st.com> for STMicroelectronics.
* Philippe Cornu <philippe.cornu@st.com> for STMicroelectronics.
*
- * This rm68200 panel driver is inspired from the Linux Kernel driver
- * drivers/gpu/drm/panel/panel-raydium-rm68200.c.
+ * This seeed panel driver is inspired from the Linux Kernel driver
+ * drivers/gpu/drm/panel/panel-raydium-seeed.c.
*/
#include <common.h>
#include <backlight.h>
@@ -145,15 +145,16 @@ enum REG_ADDR {
/* Chip/Rev Registers */
#define IDREG 0x04A0
-/* Debug Registers */
+/* printf Registers */
#define WCMDQUEUE 0x0500
#define RCMDQUEUE 0x0504
-struct rm68200_panel_priv {
+struct seeed_panel_priv {
struct udevice *reg;
struct udevice *backlight;
- struct gpio_desc reset;
+ struct gpio_desc *sel_gpio; //select
+
};
static const struct display_timing default_timing = {
@@ -292,6 +293,9 @@ static int rm68200_panel_of_to_plat(struct udevice *dev)
static int rm68200_panel_probe(struct udevice *dev)
{
struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_DEVKITS)
+ struct seeed_panel_priv *priv = dev_get_priv(dev);
+#endif
u8 reg_value = 0;
@@ -315,6 +319,17 @@ static int rm68200_panel_probe(struct udevice *dev)
return -ENODEV;
}
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_DEVKITS)
+ priv->sel_gpio = devm_gpiod_get_optional(dev, "sel", GPIOD_IS_OUT);
+
+ if (IS_ERR(priv->sel_gpio)) {
+ pr_err("Failed get reset sel gpio\n");
+ return PTR_ERR(priv->sel_gpio);
+ }
+
+ dm_gpio_set_value(priv->sel_gpio, 0);
+#endif
+
return 0;
}
@@ -324,17 +339,17 @@ static const struct panel_ops rm68200_panel_ops = {
};
static const struct udevice_id rm68200_panel_ids[] = {
- { .compatible = "raydium,rm68200" },
+ { .compatible = "starfive,seeed" },
{ }
};
-U_BOOT_DRIVER(rm68200_panel) = {
- .name = "rm68200_panel",
+U_BOOT_DRIVER(seeed_panel) = {
+ .name = "seeed_panel",
.id = UCLASS_PANEL,
.of_match = rm68200_panel_ids,
.ops = &rm68200_panel_ops,
.of_to_plat = rm68200_panel_of_to_plat,
.probe = rm68200_panel_probe,
.plat_auto = sizeof(struct mipi_dsi_panel_plat),
- .priv_auto = sizeof(struct rm68200_panel_priv),
+ .priv_auto = sizeof(struct seeed_panel_priv),
};
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c
index 52a1d94743..f1fdabdfae 100644
--- a/drivers/video/video-uclass.c
+++ b/drivers/video/video-uclass.c
@@ -265,7 +265,7 @@ int video_sync_copy(struct udevice *dev, void *from, void *to)
* frame buffer
*/
if (offset < -priv->fb_size || offset > 2 * priv->fb_size) {
-#if DEBUG
+#ifdef DEBUG
char str[80];
snprintf(str, sizeof(str),
diff --git a/include/configs/starfive-devkits.h b/include/configs/starfive-devkits.h
new file mode 100644
index 0000000000..b7547d8064
--- /dev/null
+++ b/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 */
diff --git a/include/configs/starfive-visionfive.h b/include/configs/starfive-visionfive.h
deleted file mode 100644
index 956c6a7d12..0000000000
--- a/include/configs/starfive-visionfive.h
+++ /dev/null
@@ -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 */
-
diff --git a/include/configs/starfive-visionfive2.h b/include/configs/starfive-visionfive2.h
new file mode 100644
index 0000000000..37a51004ca
--- /dev/null
+++ b/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 */
+
diff --git a/include/efi_api.h b/include/efi_api.h
index c8f959bb72..4b9b8112e1 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -417,6 +417,31 @@ struct efi_runtime_services {
EFI_GUID(0x1e2ed096, 0x30e2, 0x4254, 0xbd, \
0x89, 0x86, 0x3b, 0xbe, 0xf8, 0x23, 0x25)
+#define EFI_RNG_PROTOCOL_GUID \
+ EFI_GUID(0x3152bca5, 0xeade, 0x433d, 0x86, 0x2e, \
+ 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44)
+
+#define EFI_DT_FIXUP_PROTOCOL_GUID \
+ EFI_GUID(0xe617d64c, 0xfe08, 0x46da, 0xf4, 0xdc, \
+ 0xbb, 0xd5, 0x87, 0x0c, 0x73, 0x00)
+
+#define EFI_TCG2_PROTOCOL_GUID \
+ EFI_GUID(0x607f766c, 0x7455, 0x42be, 0x93, \
+ 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f)
+
+#define RISCV_EFI_BOOT_PROTOCOL_GUID \
+ EFI_GUID(0xccd15fec, 0x6f73, 0x4eec, 0x83, \
+ 0x95, 0x3e, 0x69, 0xe4, 0xb9, 0x40, 0xbf)
+
+/**
+ * struct efi_configuration_table - EFI Configuration Table
+ *
+ * This table contains a set of GUID/pointer pairs.
+ * The EFI Configuration Table may contain at most one instance of each table type.
+ *
+ * @guid: GUID that uniquely identifies the system configuration table
+ * @table: A pointer to the table associated with guid
+ */
struct efi_configuration_table {
efi_guid_t guid;
void *table;
diff --git a/include/efi_loader.h b/include/efi_loader.h
index c440962fe5..432a57e7ea 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -523,6 +523,10 @@ efi_status_t efi_disk_register(void);
efi_status_t efi_rng_register(void);
/* Called by efi_init_obj_list() to install EFI_TCG2_PROTOCOL */
efi_status_t efi_tcg2_register(void);
+/* Called by efi_init_obj_list() to install RISCV_EFI_BOOT_PROTOCOL */
+efi_status_t efi_riscv_register(void);
+/* Called by efi_init_obj_list() to do initial measurement */
+efi_status_t efi_tcg2_do_initial_measurement(void);
/* measure the pe-coff image, extend PCR and add Event Log */
efi_status_t tcg2_measure_pe_image(void *efi, u64 efi_size,
struct efi_loaded_image_obj *handle,
diff --git a/include/efi_riscv.h b/include/efi_riscv.h
new file mode 100644
index 0000000000..4bd39c4366
--- /dev/null
+++ b/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;
diff --git a/include/init.h b/include/init.h
index c781789e36..b29b6ecd98 100644
--- a/include/init.h
+++ b/include/init.h
@@ -267,6 +267,9 @@ int cpu_init_r(void);
int last_stage_init(void);
int mac_read_from_eeprom(void);
int set_cpu_clk_info(void);
+#if CONFIG_IS_ENABLED(TARGET_STARFIVE_DEVKITS)
+int set_pmic(void);
+#endif
int update_flash_size(int flash_size);
int arch_early_init_r(void);
int misc_init_r(void);
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index f48d9e8b51..3e910921d0 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -374,4 +374,14 @@ config EFI_ESRT
help
Enabling this option creates the ESRT UEFI system table.
+config EFI_RISCV_BOOT_PROTOCOL
+ bool "RISCV_EFI_BOOT_PROTOCOL support"
+ default y
+ depends on RISCV
+ help
+ The EFI_RISCV_BOOT_PROTOCOL is used to transfer the boot hart ID
+ to the next boot stage. It should be enabled as it is meant to
+ replace the transfer via the device-tree. The latter is not
+ possible on systems using ACPI.
+
endif
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
index fd344cea29..b2c664d108 100644
--- a/lib/efi_loader/Makefile
+++ b/lib/efi_loader/Makefile
@@ -62,6 +62,7 @@ obj-$(CONFIG_GENERATE_ACPI_TABLE) += efi_acpi.o
obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += efi_smbios.o
obj-$(CONFIG_EFI_RNG_PROTOCOL) += efi_rng.o
obj-$(CONFIG_EFI_TCG2_PROTOCOL) += efi_tcg2.o
+obj-$(CONFIG_EFI_RISCV_BOOT_PROTOCOL) += efi_riscv.o
obj-$(CONFIG_EFI_LOAD_FILE2_INITRD) += efi_load_initrd.o
obj-$(CONFIG_EFI_SIGNATURE_SUPPORT) += efi_signature.o
diff --git a/lib/efi_loader/efi_riscv.c b/lib/efi_loader/efi_riscv.c
new file mode 100644
index 0000000000..bccfefd8fb
--- /dev/null
+++ b/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;
+}
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
index a2338d74af..7c6f032651 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -273,6 +273,12 @@ efi_status_t efi_init_obj_list(void)
goto out;
}
+ if (IS_ENABLED(CONFIG_EFI_RISCV_BOOT_PROTOCOL)) {
+ ret = efi_riscv_register();
+ if (ret != EFI_SUCCESS)
+ goto out;
+ }
+
/* Secure boot */
ret = efi_init_secure_boot();
if (ret != EFI_SUCCESS)