硬件方案是基于RK3588S自研平板方案实现。
CPU: RK3588S
DDR: LPDDR5 8GB
NOR: SPI接口 32MB容量
SSD: PCIE接口 256GB容量
软件基于RK3588 Android12 SDK实现,启动流程如下图
其中:NOR中存放loader和uboot,RK3588从NOR中加载前级loader,前级loader再引导uboot,在uboot阶段进行SSD的初始化,并引导主系统;主系统的kernel和andorid固件存放在SSD中,由uboot引导启动。
整个启动流程在SDK中已经实现,只需配置PCIE接口即可,具体修改如下:
pcie配置,根据实际的硬件设计进行配置修改,这里配置的是pcie2.0 x 1lane的接口。
@sys2_206:~/4_Android12_29_sdk/u-boot$
diff --git a/arch/arm/dts/rk3588-u-boot.dtsi b/arch/arm/dts/rk3588-u-boot.dtsi
index 3fe8054aac..5894d63a5e 100644
--- a/arch/arm/dts/rk3588-u-boot.dtsi
+++ b/arch/arm/dts/rk3588-u-boot.dtsi
@@ -14,7 +14,7 @@
chosen {
stdout-path = &uart2;
- u-boot,spl-boot-order = &sdmmc, &sdhci, &spi_nand, &spi_nor;
+ u-boot,spl-boot-order = &sdhci, &spi_nand, &spi_nor;
};
secure-otp@fe3a0000 {
@@ -22,6 +22,33 @@
compatible = "rockchip,rk3588-secure-otp";
reg = <0x0 0xfe3a0000 0x0 0x4000>;
};
+
+ vcc12v_dcin: vcc12v-dcin {
+ u-boot,dm-pre-reloc;
+ compatible = "regulator-fixed";
+ regulator-name = "vcc12v_dcin";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <12000000>;
+ regulator-max-microvolt = <12000000>;
+ };
+
+ vcc3v3_pcie20: vcc3v3-pcie20 {
+ u-boot,dm-pre-reloc;
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3_pcie20";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ enable-active-high;
+ gpio = <&gpio4 RK_PB1 GPIO_ACTIVE_HIGH>;
+ startup-delay-us = <5000>;
+ vin-supply = <&vcc12v_dcin>;
+ };
+};
+
+&combphy2_psu {
+ u-boot,dm-pre-reloc;
+ status = "okay";
};
&firmware {
@@ -201,6 +228,13 @@
u-boot,dm-spl;
};
+&pcie2x1l1 {
+ u-boot,dm-pre-reloc;
+ reset-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_pcie20>;
+ status = "okay";
+};
+
&pinctrl {
u-boot,dm-spl;
/delete-node/ sdmmc;
diff --git a/configs/rk3588_defconfig b/configs/rk3588_defconfig
index fd6c9114f0..48708dc4c0 100644
--- a/configs/rk3588_defconfig
+++ b/configs/rk3588_defconfig
@@ -223,3 +223,15 @@ CONFIG_RK_AVB_LIBAVB_USER=y
CONFIG_OPTEE_CLIENT=y
CONFIG_OPTEE_V2=y
CONFIG_OPTEE_ALWAYS_USE_SECURITY_PARTITION=y
+CONFIG_CMD_PCI=y
+CONFIG_NVME=y
+CONFIG_PCI=y
+CONFIG_DM_PCI=y
+CONFIG_DM_PCI_COMPAT=y
+CONFIG_PCIE_DW_ROCKCHIP=y
+CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY=y
+CONFIG_PHY_ROCKCHIP_SNPS_PCIE3=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_ROCKCHIP_BOOTDEV="nvme 0"
+CONFIG_EMBED_KERNEL_DTB_ALWAYS=y
+CONFIG_SPL_FIT_IMAGE_KB=2560
因为pcie的配置不是通用的配置,uboot启动的时候需要加在kernel的dtb用来初始化pcie,所以在编译uboot的时候需要把kernel的dtb一起编译到uboot.img中,具体修改是把kernel中编译出来的dtb文件拷贝到uboot/dts/kern.dtb 下面:
@sys2_206:~/4_Android12_29_sdk/u-boot$ cp ../kernel-5.10/arch/arm64/boot/dts/rockchip/rk3588s-tablet-ssd.dtb dts/kern.dtb
kernel部分也只要DTS配置PCIE,让PCIE正常工作即可。
@sys2_206:~/4_Android12_29_sdk/kernel-5.10$ vim arch/arm64/boot/dts/rockchip/rk3588s-tablet-ssd.dts
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2021 Rockchip Electronics Co., Ltd.
*
*/
/dts-v1/;
#include "rk3588s-tablet.dtsi"
/ {
model = "Rockchip RK3588S TABLET SSD Board";
compatible = "rockchip,rk3588s-tablet-SSD", "rockchip,rk3588";
vcc3v3_pcie20: vcc3v3-pcie20 {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_pcie20";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
enable-active-high;
gpios = <&gpio4 RK_PB1 GPIO_ACTIVE_HIGH>;
startup-delay-us = <5000>;
vin-supply = <&vcc5v0_sys>;
};
};
&chosen {
bootargs = "earlycon=uart8250,mmio32,0xfeb50000 console=ttyFIQ0 irqchip.gicv3_pseudo_nmi=1 bootdeay=10";
};
&combphy2_psu {
status = "okay";
};
&pcie2x1l1 {
reset-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>;
vpcie3v3-supply = <&vcc3v3_pcie20>;
status = "okay";
};
Android中修改存储介质为pcie,用于分区挂载。
@sys2_206:~/4_Android12_29_sdk/device/rockchip/rk3588$ git diff
--- a/BoardConfig.mk
+++ b/BoardConfig.mk
@@ -25,7 +25,7 @@ PRODUCT_KERNEL_CONFIG ?= rockchip_defconfig pcie_wifi.config
#BOARD_AVB_ENABLE := true
# used for fstab_generator, sdmmc controller address
-PRODUCT_BOOT_DEVICE := fe2e0000.mmc
+PRODUCT_BOOT_DEVICE := fe180000.pcie
PRODUCT_SDMMC_DEVICE := fe2c0000.mmc
SF_PRIMARY_DISPLAY_ORIENTATION := 0
SSD中的存放的固件中不需要uboot和loader分区,所以下面的修改是去掉parameter中的uboot分区
@sys2_206:~/4_Android12_29_sdk/device/rockchip/common$ git diff
diff --git a/build/rockchip/RebuildParameter.mk b/build/rockchip/RebuildParameter.mk
index 4e120e0e..0e04b559 100644
--- a/build/rockchip/RebuildParameter.mk
+++ b/build/rockchip/RebuildParameter.mk
@@ -5,7 +5,7 @@ $(info build parameter.txt with $(PRODUCT_PARAMETER_TEMPLATE)....)
ifeq ($(strip $(BOARD_USES_AB_IMAGE)), true)
partition_list := security:4M,uboot_a:4M,trust_a:4M,misc:4M
else
-partition_list := security:4M,uboot:4M,trust:4M,misc:4M
+partition_list := security:4M,misc:4M
endif # BOARD_USES_AB_IMAGE
ifeq ($(strip $(BOARD_USES_AB_IMAGE)), true)
SPI-NOR需要一个独立的分区表来配置分区信息,所以单独提供一个parameter_nor.txt文件作为spi-nor的分区表,这个文件放在产品目录下,这里以rk3588s_s为例说明,parameter的内容如下,需要手动拷贝并新建:
@sys2_206:~/4_Android12_29_sdk/device/rockchip/rk3588/rk3588s_s$ vim parameter_nor.txt
FIRMWARE_VER: 1.0
MACHINE_MODEL: RK3588
MACHINE_ID: 007
MANUFACTURER: RK3588
MAGIC: 0x5041524B
ATAG: 0x00200800
MACHINE: 0xffffffff
CHECK_MASK: 0x80
PWR_HLD: 0,0,A,0,1
TYPE: GPT
CMDLINE: mtdparts=rk29xxnand:0x00002800@0x00004000(uboot)
以下修改是把parameter_nor.txt 文件在编译的时候拷贝到rockdev下面
@sys2_206:~/4_Android12_29_sdk/device/rockchip/common$ git diff
diff --git a/mkimage.sh b/mkimage.sh
index 69b733e0..288c2456 100755
--- a/mkimage.sh
+++ b/mkimage.sh
@@ -193,6 +193,7 @@ then
else
if [ -f $OUT/parameter.txt ]; then
cp -a $OUT/parameter.txt $IMAGE_PATH/parameter.txt
+ cp -a ${TARGET_DEVICE_DIR}/parameter_nor.txt $IMAGE_PATH/parameter_nor.txt
else
echo "$PARAMETER not fount!"
fi
修改完需要手动把mkimage.sh拷贝替换到SDK根目录下的mkimage.sh
@sys2_206:~/4_Android12_29_sdk$ cp -rf device/rockchip/common/mkimage.sh mkimage.sh
spinor+pcie ssd的固件打包方式跟单独emmc的不一样,需要配置要烧写的固件的存储介质如spinor或者pcie,所以在打包update.img的流程会不一样,下面是打包脚本的修改:
注意:rkImageMaker的版本需要在v2.1及以上的版本
@sys2_206:~/4_Android12_29_sdk/RKTools$ git diff linux/Linux_Pack_Firmware/rockdev/mkupdate.sh
diff --git a/linux/Linux_Pack_Firmware/rockdev/mkupdate.sh b/linux/Linux_Pack_Firmware/rockdev/mkupdate.sh
index 0e00949..7a691dd 100755
--- a/linux/Linux_Pack_Firmware/rockdev/mkupdate.sh
+++ b/linux/Linux_Pack_Firmware/rockdev/mkupdate.sh
@@ -40,8 +40,30 @@ if [ -f "$PACKAGE_FILE" ]; then
fi
./gen-package-file.sh $IMAGE_PATH > $PACKAGE_FILE
-echo "start to make update.img..."
+echo "start to make pcie update.img..."
+
./afptool -pack ./ $IMAGE_PATH/update.img $PACKAGE_FILE || pause
-./rkImageMaker ${vendor_id_map[$PLATFORM]} $IMAGE_PATH/MiniLoaderAll.bin $IMAGE_PATH/update.img update.img -os_type:androidos || pause
-echo "Making update.img OK."
+./rkImageMaker ${vendor_id_map[$PLATFORM]} $IMAGE_PATH/MiniLoaderAll.bin $IMAGE_PATH/update.img pcie_update.img -os_type:androidos -storage:pcie || pause
+echo "Making $IMAGE_PATH/pcie_update.img OK."
+
+
+echo "regenernate $PACKAGE_FILE..."
+if [ -f "$PACKAGE_FILE" ]; then
+ rm -rf $PACKAGE_FILE
+fi
+cp $IMAGE_PATH/parameter.txt $IMAGE_PATH/parameter.txt.bak
+cp $IMAGE_PATH/parameter_nor.txt $IMAGE_PATH/parameter.txt
+
+./gen-package-file.sh $IMAGE_PATH > $PACKAGE_FILE
+
+echo "start to make spinor update.img..."
+
+./afptool -pack ./ $IMAGE_PATH/update.img $PACKAGE_FILE || pause
+./rkImageMaker ${vendor_id_map[$PLATFORM]} $IMAGE_PATH/MiniLoaderAll.bin $IMAGE_PATH/update.img spinor_update.img -os_type:androidos -storage:spinor || pause
+echo "Making $IMAGE_PATH/spi_update.img OK."
+
+./rkImageMaker -merge ./update.img ./spinor_update.img ./pcie_update.img
+
+
+mv $IMAGE_PATH/parameter.txt.bak $IMAGE_PATH/parameter.txt
以上修改后可以通过build.sh -AUCKu
编译出合并完的update.img,可以直用瑞芯微开发工具进行烧写。
固件分为两个部分:
spi-nor里面的固件,需要在maskrom模式下才能升级,烧写loader、uboot、parameter_nor.txt三个固件,烧写时需要在工具中的存储
栏中选择存储介质,这里选SOINOR,每个烧写固件都需要选择。
说明:在loader模式下可以通过烧写工具的高级功能切换到maskrom模式:
pcie ssd里面的固件,需要在bootloader模式下才能升级,烧写除loader、uboot以外的其他固件,主要parameter是不包含uboot分区的parameter.txt。烧写时需要在工具中的存储
栏中选择存储介质,这里选PCIE,每个烧写固件都需要选择。
通过update.img烧写,update.img烧写方式与emmc的相同,推荐使用update.img烧写,需要在maskrom模式下烧写,这样才能更新spinor中的固件。