RK3588 Android平台SPI NOR+PCIE SSD实现大容量存储方案

RK3588 Android平台SPI NOR+PCIE SSD实现大容量存储方案

硬件配置

硬件方案是基于RK3588S自研平板方案实现。
CPU: RK3588S
DDR: LPDDR5 8GB
NOR: SPI接口 32MB容量
SSD: PCIE接口 256GB容量

软件版本要求

  • RK3588 Android12 SDK 升级到RKR8及以上版本
  • RKTools/linux/Linux_Pack_Firmware/rockdev/rkImageMaker 工具需要ver 2.1及以上版本
  • 固件烧写工具:瑞芯微开发工具需要V2.93及以上版本

软件实现

软件基于RK3588 Android12 SDK实现,启动流程如下图
RK3588 Android平台SPI NOR+PCIE SSD实现大容量存储方案_第1张图片
其中:NOR中存放loader和uboot,RK3588从NOR中加载前级loader,前级loader再引导uboot,在uboot阶段进行SSD的初始化,并引导主系统;主系统的kernel和andorid固件存放在SSD中,由uboot引导启动。
整个启动流程在SDK中已经实现,只需配置PCIE接口即可,具体修改如下:

uboot部分

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部分

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部分

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,每个烧写固件都需要选择。
    RK3588 Android平台SPI NOR+PCIE SSD实现大容量存储方案_第2张图片
    说明:在loader模式下可以通过烧写工具的高级功能切换到maskrom模式:
    RK3588 Android平台SPI NOR+PCIE SSD实现大容量存储方案_第3张图片

  • pcie ssd里面的固件,需要在bootloader模式下才能升级,烧写除loader、uboot以外的其他固件,主要parameter是不包含uboot分区的parameter.txt。烧写时需要在工具中的存储栏中选择存储介质,这里选PCIE,每个烧写固件都需要选择。
    RK3588 Android平台SPI NOR+PCIE SSD实现大容量存储方案_第4张图片

  • 一次性完整烧写所有的固件,需要在maskrom模式下进行烧写,可以同时烧写spinor和pcie ssd固件
    RK3588 Android平台SPI NOR+PCIE SSD实现大容量存储方案_第5张图片

  • 通过update.img烧写,update.img烧写方式与emmc的相同,推荐使用update.img烧写,需要在maskrom模式下烧写,这样才能更新spinor中的固件。
    RK3588 Android平台SPI NOR+PCIE SSD实现大容量存储方案_第6张图片

你可能感兴趣的:(RK3588,android,SSD,NOR,RK3588,arm开发)