RZ/G2 BSP Porting - ARM Trusted Firmware

From Renesas.info
Revision as of 15:19, 17 May 2023 by Seebe (talk | contribs) (→‎/G2E)

← Back to RZ-G/RZ-G2_BSP_Porting

Read First

On this page, please note the following:

  • "RZ/G2L" = RZ/G2L, RZ/G2LC, RZ/G2UL. The instructions are the same.

Purpose

Since arm-trusted-firmware is the first software to run after RESET, a minimal set of peripherals need to be configured and used.

Some required configurations are as follows:

  • PFC: For pin control setting to change from default GPIO pins to peripheral pins
  • DBSC4, AXI: For memory DDR setting, and QoS setting
  • GPIO, I2C: For controlling PMIC
  • SCIF: For output message to debug serial
  • WDT: If timeout detection is being used
  • CPG: For enabling above modules
  • SPI: If the bootloader images are stored in SPI flash
  • SDHI, MMC: If the bootloader images are stored in SD card or eMMC.


Source Code Repository

The source code for TrustedFirmware-A is stored on github.

Refer to the table in the wiki section of the repository to determine which branch you should use based on your SoC.

After you clone the repository and check out the correct branch, you may want to do is to create a new branch for your edits. This will make it easier to pull in future updates.

Example:

$ git clone https://github.com/renesas-rz/rzg_trusted-firmware-a
$ cd rzg_trusted-firmware-a
$ git checkout v2.7/rz
$ git checkout -b my_board     # This will make a new branch named 'my_board'

DDR Configuration

/G2N, /G2M, /G2H

  • The DDR is configured by creating an entry in the table boardcnfs[ ] (when RZG_SOC == 1) in file drivers/renesas/common/ddr/ddr_b/boot_init_dram_config.c
  • The table entry is then select by function boardcnf_get_brd_type() in the same file (boot_init_dram_config.c).
  • For your custom board (ie, not a Renesas EVK board), comment out this line near the top of the file.
#define BOARD_JUDGE_AUTO
  • Then, the function boardcnf_get_brd_type() will simply return '1' as the table index of your entry. To make things simple, you can just modify entry boardcnfs[1] to match your board.
//#define BOARD_JUDGE_AUTO     <<<<<<<<<< comment out this line like this

#ifdef BOARD_JUDGE_AUTO
static uint32_t _board_judge(void);

static uint32_t boardcnf_get_brd_type(void)
{
	return _board_judge();
}
#else
static uint32_t boardcnf_get_brd_type(void)
{
	return 1;                <<<<<<<<<< will select boardcnfs[1] every time
}
#endif
  • The boardcnf_get_brd_type() function is called from function rcar_dram_init() in file drivers/renesas/common/ddr/ddr_b/boot_init_dram.c

/G2E

This is the DDR driver for the RZ/G2E, but you should not have to edit it.

  • drivers/renesas/common/ddr/ddr_a/ddr_init_e3.c

Memory Size

The size of the DDR is set by setting defining RCAR_DRAM_DDR3L_MEMCONF at compile time.

  • RCAR_DRAM_DDR3L_MEMCONF
    • 0 = 1GB (512MBx2)
    • 1 = 2GB (512MBx4)


  • You can see this in file ddr_init_3e.c
#if RCAR_DRAM_DDR3L_MEMCONF == 0
	mmio_write_32(DBSC_DBMEMCONF_0_0, 0x0f030a02);	/* 1GB */ /* (rows=15, banks=8, cols=10, Data Bus=32-bit) */
#else
	mmio_write_32(DBSC_DBMEMCONF_0_0, 0x10030a02);	/* 2GB(default) */ /* (rows=16, banks=8, cols=10, Data Bus=32-bit) */
#endif


Chip Count

The number of the DDR memories connected on the board is set by setting defining RCAR_DRAM_DDR3L_MEMDUAL at compile time.

  • RCAR_DRAM_DDR3L_MEMDUAL
    • 0 = CS0, ODT0 enable and CS1, ODT1 disable (SDRAM 2 pieces)
    • 1 = CS0, ODT0, CS1, ODT1 enable (SDRAM 4 pieces)


Example Settings

Memory Settings
4pcs x 8bit 2GB RCAR_DRAM_DDR3L_MEMCONF=1 RCAR_DRAM_DDR3L_MEMDUAL=1
2pcs x 16bit 2GB RCAR_DRAM_DDR3L_MEMCONF=1 RCAR_DRAM_DDR3L_MEMDUAL=0
2pcs x 16bit 1GB RCAR_DRAM_DDR3L_MEMCONF=0 RCAR_DRAM_DDR3L_MEMDUAL=0


Setting in Yocto

You can force your settings in Yocto by modifying file:

meta-renesas/meta-rzg2h/recipes-bsp/trusted-firmware-a/trusted-firmware-a.bbappend

And edit the line: ATFW_OPT_r8a774c0 = " "

For example:

ATFW_OPT_r8a774c0 = "LSI=G2E RCAR_SA0_SIZE=0 RCAR_DRAM_DDR3L_MEMCONF=1 RCAR_DRAM_DDR3L_MEMDUAL=1 SPD="none"".

/G2L, /V2L

The DDR configuration files (param_mc.c and param_swizzle.c) to be used with ATF are the same as Flash Writer.

First of all create a new folder for your custom board in the platform folder:

mkdir -p plat/renesas/rz/board/custom

Copy one of the existing .mk files as template:

cp plat/renesas/rz/board/smarc_2/rz_board.mk plat/renesas/rz/board/custom/rz_board.mk

Edit the content of this newly created file:

#
# SPDX-License-Identifier: BSD-3-Clause
#

DDR_SOURCES +=  plat/renesas/rz/soc/${PLAT}/drivers/ddr/param_mc.c \
                plat/renesas/rz/common/drivers/ddr/param_swizzle.c

DDR_PLL4    := 1600
$(eval $(call add_define,DDR_PLL4))

Note that DDR_PLL4 define have to match the DDR type (e.g. 1600 for DDR4 and 1333 for DDR3L).

Copy param_mc.c and param_swizzle.c in the folders pointed by the .mk just edited.

QSPI Flash Configuration

  • After RESET, the internal Mask-ROM inside the device will read BL2 from SPI flash into internal memory. This process should work for almost all SPI flash devices and because the standard SPI Flash read command (0x03) is used and no code changes should be needed.
  • When BL2 runs, it will copy additional binaries into DDR (BL31, BL33, FIP, u-boot, etc..). However, the BL2 software will first reconfigure the SPI Flash controller to run in a memory mapped (XIP) mode in order to make the operation faster.
  • Quad SPI flash devices from different vendors behave differently. Therefore, code changes will be needed. If the settings do not match your SPI flash, you will not boot.
  • The follow instructions apply to BSP version after v3.0.0

Selecting a SPI Flash

  • The SPI Flash that you are using is defined (hard coded) during the build process using the "SPI_FLASH" define. There is no 'auto-detect'.
  • If "SPI_FLASH" is not defined, MT25QU512ABB is selected by default (see plat/renesas/rz/common/rz_common.mk)
  • The value of "SPI_FLASH" should be set to the name of a directory where your SPI flash settings file (spi_multi_reg_values.h) is located.
    • Example when "SPI_FLASH" is set to "MT25QU512ABB"
    • rzg_trusted-firmware-a/plat/renesas/rz/common/include/drivers/spi_multi/MT25QU512ABB/spi_multi_reg_values.h

Adding a New SPI Flash

  • If you are using a different SPI Flash, make a new directory and a new spi_multi_reg_values.h file. Set the name of that directory in the plat/renesas/rz/common/rz_common.mk file:
ifndef SPI_FLASH
  #SPI_FLASH = MT25QU512ABB  ### <<< I commented out this line
  SPI_FLASH = S25L256XYZ     ### <<< I added this new line
endif
  • You will need to define how to read data for the SPI flash. This means you are only concerned with the read commands in the SPI flash data sheet. You can decide if you want to use 1-bit access or 4-bit access.
  • Options are defined in file plat/renesas/rz/common/include/drivers/spi_multi/spi_multi.h
    • SPI_MULTI_ADDR_WIDES_24: Use 24-bit (3 byte) addressing commands. Addressing is limited to 16MB
    • SPI_MULTI_ADDR_WIDES_32: Use 32-bit (4 byte) addressing commands. Not all SPI flash supports these commands.
    • SPI_MULTI_DQ_WIDES_1_1_1: Command is 1-bit, Address is 1-bit, Data is 1-bit. The FAST_READ command 0x0B(24-bit) or 0x0C(32-bit) is used.
    • SPI_MULTI_DQ_WIDES_1_1_4: Command is 1-bit, Address is 4-bit, Data is 4-bit. The Quad Output FAST_READ command 0x6B(24-bit) or 0x6C(32-bit) is used
    • SPI_MULTI_DQ_WIDES_1_4_4: Command is 1-bit, Address is 4-bit, Data is 4-bit. The Quad Input/Output FAST_READ command 0xEB(24-bit) or 0xEC(32-bit) is used
    • SPI_MULTI_DUMMY_{2-20}CYCLE: Specify that (2,3,4....20) number of 1-bit dummy cycles are added after the address is sent, but before data is read. These are hard requirements by the SPI flash vendor, and each vendor is different.
  • The hex values for the SPI Flash Read commands for FAST_READ selected by SPI_MULTI_DQ_WIDES_x_x_x are defined in file plat/renesas/rz/common/include/drivers/spi_multi/spi_multi_regs.h. If your SPI Flash uses a different hex value, you will need to make changes.

Note on QE bit

As mentioned in the previous paragraph, the SPI_MULTI_DQ_WIDES_1_1_1 is normally always supported. In some cases the Quad SPI flash device comes into a small package (e.g. 8-WSON). In this low pin count package SIO2 and SIO3 are multiplexed with other signals, WP# and RESET# respectively, and this is the factory default. In order to use Quad commands, the non-volatile QE bit in the Status Register need to be set. Being non-volatile this setting has to be done once and it will be kept until changed back to zero. As of today ATF code does not do that, so it has to be modified to do it or the QE bit has to be set by other means.

Building and Debugging

/G2E, /G2N, /G2M, /G2H

Boot from eMMC:

  • By default, TF-A will boot from SPI Flash. In order to build ATF to boot directly form eMMC Flash, it has to be built with the flag RZG_SA6_TYPE=1.


/G2L, /V2L

  • In this section we use g2l as platform but the same steps are valid for v2l.

Boot from SPI Flash vs eMMC Flash:

  • Compared to RZ/G2E-N-M-H, for RZ/G2L and RZ/V2L there is no need to add any specific flag to enable eMMC boot in ATF. Both are supported by default. During boot, the code will read a register to determine where it should load BL2 from (SPI Flash or eMMC Flash).

Build Commands: ATF (release) can be built by giving the following command:

make -j$(nproc) PLAT=g2l BOARD=custom all

ATF (debug) instead:

make -j$(nproc) PLAT=g2l BOARD=custom DEBUG=1 all

Binaries (bl2.bin and bl31.bin) are located in the build/g2l/release|debug folder.

We have to combine bl2.bin with boot parameters, we can use this simple bash script to do that:

  #!/bin/bash
  echo -e "\n[Creating bootparams.bin]"
  SIZE=$(stat -L --printf="%s" bl2.bin)
  SIZE_ALIGNED=$(expr $SIZE + 3)
  SIZE_ALIGNED2=$((SIZE_ALIGNED & 0xFFFFFFFC))
  SIZE_HEX=$(printf '%08x\n' $SIZE_ALIGNED2)
  echo "  bl2.bin size=$SIZE, Aligned size=$SIZE_ALIGNED2 (0x${SIZE_HEX})"
  STRING=$(echo \\x${SIZE_HEX:6:2}\\x${SIZE_HEX:4:2}\\x${SIZE_HEX:2:2}\\x${SIZE_HEX:0:2})
  printf "$STRING" > bootparams.bin
  for i in `seq 1 506`e ; do printf '\xff' >> bootparams.bin ; done
  printf '\x55\xaa' >> bootparams.bin
  # Combine bootparams.bin and bl2.bin into single binary
  # Only if a new version of bl2.bin is created
  if [ "bl2.bin" -nt "bl2_bp.bin" ] || [p! -e "bl2_bp.bin" ] ; then
    echo -e "\n[Adding bootparams.bin to bl2.bin]"
    cat bootparams.bin bl2.bin > bl2_bp.bin
  fi  

Make the fip creation tool:

cd tools/fiptool
make -j$(nproc) plat=g2l

Now we can create the fip file by combining the bl31.bin and u-boot.bin (refer to this section and copy the .bin in the ATF root folder):

cd ../..
tools/fiptool/fiptool create --align 16 --soc-fw build/g2l/release|debug/bl31.bin --nt-fw u-boot.bin fip.bin

bl2_bp.bin and fip.bin are the files that have to be programmed using Flash Writer. Actually .srec may be more handy, they can be converted by using the following commands:

${CROSS_COMPILE}objcopy -I binary -O srec --adjust-vma=0x00011E00 --srec-forceS3 bl2_bp.bin bl2_bp.srec
${CROSS_COMPILE}objcopy -I binary -O srec --adjust-vma=0x00000000 --srec-forceS3 fip.bin fip.srec

ATF BL2 is what you more often might need to debug, since this is the part that includes most of the system specific options. Obviously it is possible to use the various log options (INFO, NOTICE, DEBUG, etc), however especially during the first stages or if something is difficult to catch, it might be just more convenient to use a JTAG debugger and OpenOCD. In this way you do not need to reflash the bootloaders every time since the new image is just loaded in the internal RAM directly. You can refer to this section, that shows how to setup the OpenOCD Eclipse plugin to debug BL2.

Memory Sections

  • The defines for the memory sections are located in the tools directory:
    • rzg_trusted-firmware-a/tools/renesas/rzg_layout_create/

RAM (DDR) Areas

  • Since the partitioning of DDR during boot and run-time span across TF-A, u-boot and kernel, that is explained here on page RZ-G/RZ-G2_BSP_MemoryMap.

eMMC partitions

  • All eMMC Flash devices contain 3 separate Flash sections in hardware: 2 boot partitions and 1 main flash area.
  • The boot partitions in eMMC Flash devices are usually about 4MB each. The partitions are selected as part of the eMMC command protocols.
  • BL2: The Initial Program Loader (IPL) which is 'BL2' of the ARM Trusted Firmware is required to be located in eMMC boot partition 1.
  • u-boot: RZ/G2H,/G2N,/G2M,/G2E Only: By default of the BSP code, u-boot (BL33) is stored in eMMC boot partition 2. However, you can change the code to store u-boot some place else if you like.
  • FIP: RZ/G2L, RZ/V2L Only: Since u-boot is part of the FIP image, it is stored in eMMC boot partition 1 along with BL2.
  • By default on Renesas evaluation boards, u-boot is set up to use boot partition 2 for its environment variable area (even if it boots from SPI Flash)

SA0

  • This only applies for RZ/G2E, /G2N, /G2M, /G2H
  • rzg_trusted-firmware-a/tools/renesas/rzg_layout_create/sa0.c
  • This is the header that is loaded by the internal ROM code inside the RZ devices. It is used to specify how much should be read in for BL2 into internal RAM.
  • Generally you do not have to edit this file.

SA6

  • This only applies for RZ/G2E, /G2N, /G2M, /G2H
  • rzg_trusted-firmware-a/tools/renesas/rzg_layout_create/sa6.c
  • File sa6.c defines for all the flash locations for both SPI boot and eMMC boot.