RZ-G/RZ-G2 BSP Porting

From Renesas.info

RZ/G2 BSP Porting This page is to highlight important things to consider when porting the Renesas BSP to your own custom board.

Overview

One preliminary point to underline is that you may NOT want to use Yocto at the beginning, rather clone the repositories, modify the code and build it using a cross toolchain.

The paragraph order in this page is intentional. They represent the steps you normally do when you want to port the Renesas BSP, i.e. you absolutely want to start from Flash Writer. When you get your first custom board samples the non-volatile memories are virgin and the first goals is to program them with bootloaders. One of the first thing you need to do is to adjust the DDR configuration to your own. Debugging DDR may be tricky but have it working is a major step toward success. You can test the DDR using some hidden Flash Writer commands. After that you may need to change the SPI configuration.

Finally you can use Flash Writer to program the bootloaders: Arm Trusted Firmware (ATF) BL2 (aka IPL, Initial Program Loader), BL31 (Secure Monitor) and u-boot (BL33). BL32 is not strictly needed at the beginning, since it is the Trusted OS (optional). Bootloaders can be programmed into QSPI FLASH or eMMC, then of course the boot mode of the SoC shall be adjusted accordingly. ATF may also need to be configured depending on the non-volatile memory type. You may need to program separately (e.g. different files for each BL) or you can have a BL2 file and a FIP (Firmware Image Package) that includes all BL3x.

You do not normally need to modify many things in ATF and in any case only what is in the "plat/renesas/rz" folder. One of the first things ATF BL2 does is to configure the DDR. You would need to use the same (working) configuration used with Flash Writer, so there should be no surprise here, if the DDR works with Flash Writer then it will work with ATF as well.


sci-usb boot.png-------------------------------


Then ATF loads BL31(image id=3), BL32 (again optionally, image id=4) and BL33 (u-boot, image id=5) from either QSPI or eMMC. Assuming everything goes fine u-boot prompt is finally reachable.

The next step is to port the Linux CIP Kernel, by "porting" we mainly mean that the reference board device tree gets modified to reflect the HW available on the custom board.

Finally you can use Yocto to generate the root file system including all the bits and bobs you need to run your custom application.

Flash Writer

Cloning repository

SoC: RZ/G2E, RZ/G2N, RZ/G2M, RZ/G2H

git clone https://github.com/renesas-rz/rzg2_flash_writer

Then what you may want to do is to create a new branch for your own experiments, e.g.:

git checkout -b my_custom_board_branch

SoC: RZ/G2L, RZ/V2L

git clone https://github.com/renesas-rz/rzg2_flash_writer
git checkout origin/rz_g2l

Then what you may want to do is to create a new branch for your own experiments, e.g.:

git switch -c my_custom_board_branch

Add New DDR Settings

SoC: RZ/G2N, RZ/G2M, RZ/G2H

Flash Writer version: v1.50+

  • DDR settings for each board are stored in a "struct _boardcnf" that is used by the DDR initialization code.
  • For Renesas evaluation boards, the Flash writer source contains an array of all the possible evaluation boards.
  • When porting Flash Writer to your own custom board, you will need to create your own "struct _boardcnf" that matches the DDR memory on your board.
  • In general, only the structure is needed (no DDR init executable code needs to be modified).
  • In Flash Writer, the function boardcnf_get_brd_type() is declared as '__attribute__((weak))' such that you can provide your own version of this function and gcc will ignore the function provided in the Flash Writer code that is specific for Renesas evaluation boards. This method allows you to not modify source files that might be updated later by Renesas as new evaluation boards are added and might cause merge conflicts with your local modification.
  • A sample DDR configuration structure has been provided. Please refer to file ddr/lpddr4/boot_init_dram_config-preset.c for example configurations used by Renesas evaluation boards.

Instructions:
1. Make a copy of the template file ddr/lpddr4/my_boot_dram_config.c

$ cp ddr/lpddr4/my_boot_dram_config.c  ddr/lpddr4/xyz_boot_dram_config.c

2. Add your new file to the build system by editing the makefile ddr/lpddr4/ddr.mk

SRC_FILE += ddr/lpddr4/boot_init_dram.c ddr/lpddr4/boot_init_dram_config-preset.c
# SRC_FILE += ddr/lpddr4/my_boot_dram_config.c
SRC_FILE += ddr/lpddr4/xyz_boot_dram_config.c             <<<<<<<<<<<< Example <<<<<<<<<<

3. Edit your new file and adjust the settings for your DDR memory on your board.

SoC: RZ/G2E

Flash Writer version: TBD

Content: DDR3L instead of LPDDR4.

SoC: RZ/G2L, RZ/V2L

Flash Writer version: 1.0+

Unless the DDR RAM you have on the custom board, connection and topology is exactly the same of the reference board, you have to adapt the parameters. In order to do so, please get from Renesas the RZ/G2L DDR configuration generation tool (RZ-G2L_DDR_config_generation_tool_Rev.X.YZ_rN.xlsm). Using this excel sheet you can generate two files (param_mc.c and param_swizzle.c) that have to be added to Flash Writer.

Copy param_swizzle.c in the ddr/common folder and param_mc.c in the ddr/g2l (or ddr/v2l) folder.

Add the following lines at the beginning of ddr.c in the ddr/common folder:

#if (BOARD == CUSTOM)
#include "param_mc.c"
#include "param_swizzle.c"
#endif

And comment out the error clauses "Unknown size" and "Unknown swizzle".

Add Support for New SPI Flash

SoC: All

  • Flash writer version: All

Flash Writer will read the device ID of the SPI flash device in order to determine what SPI commands it should use as well as the flash block size. Therefore, the specific ID of your flash device needs to be part of the flash writer source code.

The RZ/G2 Flash writer code is posted here. Please review the following files and code and modify as needed.

include/dgmodul4.h

  • Confirm that the Manufacture ID for your flash devices is listed. For example, you will see these vendors already listed:
#define	CYPRESS_MANUFACTURER_ID		0x01	/* Cypress	*/
#define	WINBOND_MANUFACTURER_ID		0xEF	/* Winbond	*/
#define	MACRONIX_MANUFACTURER_ID	0xC2	/* Macronix	*/
#define	MICRON_MANUFACTURER_ID		0x20	/* Micron	*/
  • Confirm if the Device ID for your flash devices is listed. If not, then add it.
#define	DEVICE_ID_S25FS128S		0x2018

dgmodul4.c

  • If you added a new SPI flash in dgmodule4.h, then you must add it to function CheckQspiFlashId()
  • Add new case statement using your DEVICE_ID_xxx that you created in dgmodule.h
  • Print out the part number of your SPI Flash using PutStr()
  • Set the Flash sector erase size as gQspi_sa_size
  • Set the address of the last Flash sector as gQspi_end_addess
	case DEVICE_ID_S25FS512S:
			PutStr("S25FS512S", 1);
			gQspi_sa_size    = SA_256KB;
			gQspi_end_addess = TOTAL_SIZE_64MB - 0x8000 - 1;
	break;

🎈 If you successfully added a new SPI Flash device, please let us know so we can update the code for everyone πŸ§‘β€πŸ€β€πŸ§‘. You can submit a new issue on the github site, or send an email to renesas-rz@renesas.com. Thank you.

Building and debugging

SoC: RZ/G2E, RZ/G2N, RZ/G2M, RZ/G2H

Content: TBD

SoC: RZ/G2L, RZ/V2L

You can build Flash Writer by following the Readme, the only difference is that you have to use BOARD=CUSTOM (or the name you chose) as per these instructions.

It is worth to note that in order to enable Flash Writer to program eMMC, it has to be built with a specific flag: EMMC=ENABLE.

You can also use Eclipse to build and debug Flash Writer using OpenOCD as documented here. Obviously there is always the possibility to debug using the good old printf (PutStr function in Flash Writer).

Arm Trusted Firmware

Cloning repository

SoC: RZ/G2E, RZ/G2N, RZ/G2M, RZ/G2H

git clone https://github.com/renesas-rz/rzg_trusted-firmware-a/
git checkout remotes/origin/v2.5/rzg2

Then what you may want to do is to create a new branch for your own experiments, e.g.:

git checkout -b my_custom_board_branch

SoC: RZ/G2L, RZ/V2L

git clone https://github.com/renesas-rz/rzg_trusted-firmware-a/
git checkout remotes/origin/v2.5/rzg2l

Then what you may want to do is to create a new branch for your own experiments, e.g.:

git switch -c my_custom_board_branch

DDR configuration

SoC: RZ/G2N, RZ/G2M, RZ/G2H

Content: TBD

SoC: RZ/G2E

Content: TBD

SoC: RZ/G2L, RZ/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.

Non-volatile memories

SoC: RZ/G2E, RZ/G2N, RZ/G2M, RZ/G2H

Content: TBD

SoC: RZ/G2L, RZ/V2L

Quad SPI Flash Read Command 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 no code changes are 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 file plat/renesas/rz/common/plat_storage.c contains the function rz_io_setup(). This function should be modified to match your SPI flash device.
  • The arguments for function spi_multi_setup() should be modified to match your SPI flash device.
spi_multi_setup(SPI_MULTI_ADDR_WIDES_24, SPI_MULTI_DQ_WIDES_1_4_4, SPI_MULTI_DUMMY_10CYCLE)
  • You will 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/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_##CYCLE: Specify that ## 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/spi_multi_regs.h". If your SPI Flash uses a different hex value, you will need to make changes.
  • We recommend that you start with this line below. It is the most simple and commonly supported on most SPI Flash devices.
/* Use FAST_READ command, only 1-bit for command, address and data. An 8-bit dummy cycle is inserted between address and reading data */
spi_multi_setup(SPI_MULTI_ADDR_WIDES_24, SPI_MULTI_DQ_WIDES_1_1_1, SPI_MULTI_DUMMY_8CYCLE);
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

SoC: RZ/G2E, RZ/G2N, RZ/G2M, RZ/G2H

Content: TBD

It is worth to note that in order to build ATF with eMMC boot support, it has to be built with the flag RZG_SA6_TYPE=1.

SoC: RZ/G2L, RZ/V2L

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

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

Please note that, 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.

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.bina; 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" ]b; 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.

u-boot

Cloning repository

SoC: RZ/G2E, RZ/G2N, RZ/G2M, RZ/G2H

git clone https://github.com/renesas-rz/renesas-u-boot-cip
git checkout remotes/origin/v2020.10/rzg2

Then what you may want to do is to create a new branch for your own experiments, e.g.:

git checkout -b my_custom_board_branch

SoC: RZ/G2L, RZ/V2L

git clone https://github.com/renesas-rz/renesas-u-boot-cip
git checkout remotes/origin/v2020.10/rzg2l

Then what you may want to do is to create a new branch for your own experiments, e.g.:

git switch -c my_custom_board_branch

Add custom board files

SoC: RZ/G2E, RZ/G2N, RZ/G2M, RZ/G2H

Content: TBD

SoC: RZ/G2L, RZ/V2L

1) Add you custom board device tree file in the arch/arm/dts folder: my_custom_board.dts. You do not need to create this file from scratch, you can copy the Renesas board file as template:

cp arch/arm/dts/smarc-rzg2l.dts arch/arm/dts/my_custom_board.dts

and edit the file arch/arm/dts/Makefile:

[...] 
	rzg2lc-dev.dtb \
-	smarc-rzg2lc.dtb
+	smarc-rzg2lc.dtb \
+	my_custom_board.dtb
 
 ifdef CONFIG_RCAR_GEN3

[...]

2) You need to create the custom board support directory: board/<vendor>/my_custom_board, that would need to be populated with Kconfig, Makefile and my_custom_board.c:

mkdir -p board/<vendor>/my_custom_board
cp board/renesas/rzg2l-dev/* board/<vendor>/my_custom_board
mv board/<vendor>/my_custom_board/rzg2l-dev.c board/<vendor>/my_custom_board/my_custom_board.c

3) Edit the newly created files, board/<vendor>/my_custom_board/Kconfig:

if TARGET_MY_CUSTOM_BOARD

config SYS_SOC
        default "rmobile"

config SYS_BOARD
        default "my_custom_board"

config SYS_VENDOR
        default "<vendor>"

config SYS_CONFIG_NAME
        default "my_custom_board"

endif

Now board/<vendor>/my_custom_board/Makefile to rename the object file related to the .c file:

#
# board/<vendor>/my_custom_board/Makefile
#
# Copyright (C) 2015 Renesas Electronics Corporation
#
# SPDX-License-Identifier: GPL-2.0+
#

ifdef CONFIG_SPL_BUILD
obj-y   := ../../renesas/rcar-common/gen3-spl.o
else
obj-y   := my_custom_board.o ../../renesas/rcar-common/common.o
endif

Then board/<vendor>/my_custom_board.c file could be left unchanged, at least at the first stages. Of course you might need to modify it later on.

4) Next step is the board configuration:

cp configs/rzg2l-dev_defconfig configs/<vendor>_my_custom_board_defconfig 

5) Finally board header file: include/configs/my_board.h. Again, you can take the Renesas files as template:

cp include/configs/smarc-rzg2l.h include/configs/my_custom_board.h

This is the file you want to edit to configure, among other things, different parameters like default extra u-boot environment variables and boot command.

6) Now that we created all the new custom board files, we have to modify the arch Kconfig, arch/arm/mach-rmobile/Kconfig.64, to include your board:

[...]
 config TARGET_SMARC_RZG2LC
 	bool "RZ/G2LC SMARC board"
 	help
           Support for Renesas RZ/G2LC Dev Platform
 
+config TARGET_MY_CUSTOM_BOARD
+        bool "RZ/G2L my stunning custom board"
+        help
+          This is a test custom board with RZ/G2L
+
 endchoice
 
 config SYS_SOC
 	default "rmobile"

[...]
 
 source "board/renesas/ulcb/Kconfig"
 source "board/beacon/beacon-rzg2m/Kconfig"
 source "board/renesas/rzg2l-dev/Kconfig"
 source "board/renesas/rzv2l-dev/Kconfig"
 source "board/renesas/rzg2lc-dev/Kconfig"
+source "board/<vendor>/my_custom_board/Kconfig"

Now we have to create the default configuration, assuming we want to use the .out as output directory:

make <vendor>_my_custom_board_defconfig O=.out

Configuration

SoC: RZ/G2E, RZ/G2N, RZ/G2M, RZ/G2H

Content: TBD

SoC: RZ/G2L, RZ/V2L

Regarding u-boot configuration, similarly to the Linux kernel U-boot can be configured by giving the following command:

make menuconfig O=.out

U-boot menuconfig.png

You can search by typing "/" (slash). Firstly you need to change the default fdt file (search DEFAULT_FDT_FILE) to reflect the board name:

u-boot fdt.png

And select your custom board as target (search MY_CUSTOM_BOARD):

u-boot board selection.png

Select also my_custom_board as default device tree (search DEFAULT_DEVICE_TREE):

u-boot default device tree.png

In general this is how you can opt in and out any u-boot feature. For example let's assume we also want to enable QSPI support for your custom board, similarly to what just done we have to make sure that all the following features are enabled:

SPI_FLASH 
SPI_FLASH_BAR 
SPI_FLASH_USE_4K_SECTORS 
SPI 
DM_SPI 
SPI_FLASH_WINBOND
RENESAS_RPC_SPI
CMD_SF 
CMD_SPI 
SPI_FLASH_STMICRO
DM_SPI_FLASH

Once you're happy with the configuration changes, you can save the configuration file:

make savedefconfig O=.out
cp .out/defconfig configs/<vendor>_my_custom_board_defconfig

u-boot environment variables

In the configuration it is also possible to specify some options about environment variables:

CONFIG_ENV_IS_IN_MMC=y
CONFIG_SYS_MMC_ENV_DEV=0
CONFIG_SYS_MMC_ENV_PART=2
CONFIG_ENV_SIZE=0x20000
CONFIG_ENV_OFFSET=0xFFFE0000

CONFIG_SYS_MMC_ENV_DEV: It specifies which MMC device has to be used to store the environment variables;

CONFIG_SYS_MMC_ENV_PART: which MMC area (0=user, 1=boot 1, 2=boot 2);

CONFIG_ENV_SIZE: as the name suggests, size;

CONFIG_ENV_OFFSET: this is the offset in the partition chosen, a negative value is treated as a backwards offset from the end of the eMMC device/partition, rather than a forwards offset from the start.

Note that it is also possible to store them into other memories, e.g QSPI.

U-boot menuconfig env variables.png

Device tree

SoC: RZ/G2E, RZ/G2N, RZ/G2M, RZ/G2H

Content: TBD

SoC: RZ/G2L, RZ/V2L

Apart from features that can be enabled/disabled using menuconfig, another very common thing you may need to touch is the device tree, in a similar fashion you would do for the Linux kernel.

Here below an example on how your custom device tree should be modified to enable the SPI Multi I/O Bus Controller (aka RPC) in the RZ/G2L BSP v1.3 that does not officially support it. Newer versions may have these changes already implemented but the example per se is still valid.

The device trees are stored in the folder arch/arm/dts. In this example we have to modify my_custom_board.dts (patch style) as per below:

[...]

aliases {
 		serial0 = &scif0; 
+		spi0 = &spibsc; 	
}; 

[...]

+&spibsc { 
+	num-cs = <1>; 
+	status = "okay"; 
+	spi-max-frequency = <40000000>; 
+	#address-cells = <1>; +	#size-cells = <0>; 
+ 
+	flash0: spi-flash@0 { 
+		#address-cells = <1>; 
+		#size-cells = <1>; 
+		compatible = "spi-flash", "jedec,spi-nor"; 
+		spi-max-frequency = <40000000>; 
+		spi-tx-bus-width = <1>; 
+		spi-rx-bus-width = <1>; 
+		reg = <0>; 
+		status = "okay"; 
+	}; 
+};

[...] 

Source code modification

SoC: RZ/G2E, RZ/G2N, RZ/G2M, RZ/G2H

Content: TBD

SoC: RZ/G2L, RZ/V2L

Sometimes, but not very often, you may need to modify u-boot source code, maybe to modify an existing driver. Following the same example as the previous section, in order to get the QSPI working we have to modify the RPC driver (drivers/spi/renesas_rpc_spi.c) and add a line for RZ/G2L:

[...]
 
	{ .compatible = "renesas,rpc-r8a77995" },
 	{ .compatible = "renesas,rpc-r7s72100" },
+	{ .compatible = "renesas,r9a07g044l-spibsc" },
 	{ }
 };

[...] 

u-boot environment variables

Among many other other parameters, u-boot default environment variables can be configured in the already mentioned:

include/configs/my_custom_board.h

CONFIG_EXTRA_ENV_SETTINGS and CONFIG_BOOTCOMMAND are what you might want to customize.

Building and debugging

SoC: RZ/G2E, RZ/G2N, RZ/G2M, RZ/G2H

Content: TBD

SoC: RZ/G2L, RZ/V2L

Once we are happy with the modifications (configuration, device tree, source code), to build u-boot simply:

make -j$(nproc) O=.out

The binaries will be located in the .out folder and u-boot.bin is the file you want to combine with bl31.bin using the fip tool, please refer to this section.

Linux Kernel

Cloning repository

SoC: RZ/G2E, RZ/G2N, RZ/G2M, RZ/G2H

Content: TBD

SoC: RZ/G2L, RZ/V2L

Content: TBD

Device tree

SoC: RZ/G2E, RZ/G2N, RZ/G2M, RZ/G2H

Content: TBD

SoC: RZ/G2L, RZ/V2L

Content: TBD

Source code modification

SoC: RZ/G2E, RZ/G2N, RZ/G2M, RZ/G2H

Content: TBD

SoC: RZ/G2L, RZ/V2L

Content: TBD

Multimedia modules

SoC: RZ/G2E, RZ/G2N, RZ/G2M, RZ/G2H

During development you do not normally want to use Yocto to build your kernel but instead do it outside of Yocto in a separate repository. Once the kernel has been built you need to make sure that the kernel modules are built against the newly compiled kernel.

A series of scripts have been developed to ease this process. You can refer to this Readme for more information, here below a summary of the operations to build the RZ/G2E-N-M-H multimedia modules.

git clone https://github.com/renesas-rz/rz_linux-cip; cd rz_linux-cip ; git checkout -b rzg2_bsp_v1.0.9 ba8ac89871d7 ; cd ..

The line above is for the kernel version included in BSP v1.0.9. Then board and build options can be chosen by giving the following command:

./build.sh s

You can choose one of the hihope boards or the ek874. Then:

./build.sh k defconfig

The generic script supports different toolchains as per this text document, however the multimedia modules can only be built with the SDK, so option 1 must be selected and the SDK must be installed in the path shown. If the path does not correspond you need to change it manually in the board.ini file. Now we are ready to build the kernel:

./build.sh k _all

Now you have to download the multimedia package from the Renesas website. Then:

mkdir mm_packages

and copy the file downloaded file in the directory just created. We are finally ready to build the multimedia modules:

./build.sh m

The .ko files are copied in the build directory inside the mmp temporary folder. Once done you can safely remove this folder. The modules built have to be copied on the target root file system in the location /lib/modules/KERNEL_VERSION/extra. At the first boot of the target you would need to give the following commands:

depmod
ldcconfig

Alternatively the script can install automatically the files into the target, you have to edit the board.ini and append the following lines:

TARGET_INSTALL=TRUE
TARGET_IP_ADDRESS=IP_ADDRESS

and make sure to configure "IP_ADDRESS" accordingly.

SoC: RZ/G2L, RZ/V2L

Content:TBD

SD Card Speed

SoC: All

When first testing the board and booting off SD Card, it might be helpful to set the clock speed to 50MHz. If you use a SD card that is capable of higher speeds, such as an Ultra SD Card, Linux might try to run at speeds and voltages that might not be supported by your design. So it's better to restrict the speed to the lower class. Add this setting to the device tree for your SD Card.

max-frequency = <50000000>

Yocto

SoC: All

Memory Map

  • This section explains how DDR Memory is divided and configured. Since all software components (boot loaders and Linux) needs to have the same settings, we will discuss all the software components in this section.

Description of Areas

Secure Area:

  • In order to use Trust Zone and OP-TEE in your system, the secure area must be hidden from Linux. This means early in boot in the ARM Trusted Firmware code (BL2), the memory sections are configure so that non-secure code (u-boot and kernel) cannot access them.
  • By default, the BSP allocates 128MB of space at the beginning of DDR Memory. That is why in the Device Tree settings for u-boot and kernel, the starting memory address is not the begging of physical DDR space because we are trying 'hide' this from Linux. In fact, even if the CPU tries to access this area, a hardware fault will occur.

CR7 and CM33 Area:

  • The DDR area for the the sub-cores should be mapped below the memory allocated for the Linux kernel.
  • The DDR location can be in Secure or non-Secure area.
  • The default non-secure physical DDR address for the CR7 is 0x40040000
  • The default non-secure physical DDR address for the CM33 is 0x40010000

H.264 Encode/Decode Area:

  • The H.264 video codec drivers require dedicated memory. This is allocated in the "mmp_reserved: linux, multimedia" area of the kernel Device Tree.
  • The size of this area depends on the resolution of the images being encoded and decoded.

LCD Frame Buffer area

  • The LCD Frame buffer require dedicated memory. This is allocated in the "linux,cma" area of the kernel Device Tree.
  • The size of this area depends on the resolution of LCD.

DDR Restricted Area (beginning of DDR)

  • The first 64 bytes of DDR Address space (0x40000000) are restricted from being used.
  • The reason is that the DDR3/DDR4 controller uses these address locations.
  • Please do not allocate or use the beginning of the DDR address area.
  • Please refer to the SoC Hardware Manuals for more details.
Default RZ/G2L Memory Map in the BSP    
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”0x40000000
β”‚   unused (DDR controller)             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€0x40010000
β”‚   CM33                                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€0x43F00000
β”‚   BL31 Secure Monitor (2MB)           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€0x44100000
β”‚   BL32 (OP-TEE)  (61MB)               β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€0x47E00000
β”‚   unused                              β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€0x48000000
β”‚   BL33 (u-boot) and Linux (1.99GB)    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜0x80000000


How to modify ARM Trusted Firmware

  • This section explains how to modify the code for ARM Trusted Firmware.
  • Trusted Firmware (BL31) and OP-TEE should reside in the Secure Area. The will allow HW protection from non-secure code such as Linux.
  • Configure the settings in file plat/renesas/rz/common/include/plat_tzc_def.h

Start Address and size of Trusted Firmware (BL31):

/* Trusted Firmware(BL31) secure DRAM 0x43F00000 - 0x440FFFFF */
#define PLAT_FW_TZC_PROT_DRAM1_BASE		(0x43F00000)
#define PLAT_FW_TZC_PROT_DRAM1_SIZE		(0x00200000)
  • Configure the settings in file plat/renesas/rz/common/include/platform_def.h
/*******************************************************************************
 * BL31 specific defines.
 ******************************************************************************/
#define BL31_BASE				(0x44000000)
#define BL31_LIMIT				(0x44040000)

Start Address and size of OP-TEE (BL32):

/* OP-TEE secure DRAM 0x44100000 - 0x47DFFFFF */
#define PLAT_TEE_TZC_PROT_DRAM1_BASE	(0x44100000)
#define PLAT_TEE_TZC_PROT_DRAM1_SIZE	(0x03D00000)
/*******************************************************************************
 * BL32 specific defines.
 ******************************************************************************/
#ifndef SPD_none
#define BL32_BASE				(0x44100000)
#define BL32_LIMIT				(BL32_BASE + 0x100000)
#endif

Remove OP-TEE Area (optional)

  • If you will not be using OP-TEE at all, you can comment out the code that configures that area in file plat_security.c.
diff --git a/plat/renesas/rz/common/plat_security.c b/plat/renesas/rz/common/plat_security.c
index 4e9c96f81..35a4910c0 100755
--- a/plat/renesas/rz/common/plat_security.c
+++ b/plat/renesas/rz/common/plat_security.c
@@ -115,8 +115,10 @@ static void bl2_security_setup(void)
     const arm_tzc_regions_info_t ddr_tzc_regions[] = {
         {PLAT_FW_TZC_PROT_DRAM1_BASE, PLAT_FW_TZC_PROT_DRAM1_END,
             TZC_REGION_S_RDWR, PLAT_TZC_REGION_ACCESS_S_UNPRIV},
+#if 0
         {PLAT_TEE_TZC_PROT_DRAM1_BASE, PLAT_TEE_TZC_PROT_DRAM1_END,
             TZC_REGION_S_RDWR,  PLAT_TZC_REGION_ACCESS_S_UNPRIV},
+#endif
         {}
     };

How to modify u-boot

  • This section explains how to modify the code for u-boot.
  • U-boot uses a Device Tree file to configure the memory size. There is a 'memory' node that configures the start address and size of DDR memory to use.
  • For example:
	memory@48000000 {
 		device_type = "memory";
		/* first 128MB is reserved for secure area. */
		reg = <0 0x48000000 0 0x78000000>;
 	};
  • ⚠ The 'memory' node in the Device Tree of u-boot is used for u-boot and is also used for the kernel Device Tree. When u-boot boots the kernel, it automatically overwrites the value in the kernel's Device Tree. This means that what you put in the kernel memory node in the kernel Device Tree will have no effect.
  • There is also a define DRAM_RSV_SIZE that needs to be modified. This will be in the config file for your board. Set it to the size of your secure area that will be hidden from u-boot and Linux.
  • For example, for the RZ/G2L SMARC board, that is file include/configs/smarc-rzg2l.h
#define DRAM_RSV_SIZE			0x80000000

How to modify kernel

  • This section explains how to modify the code for the Linux.
  • You should only need to modify the Device Tree files
  • ⚠ Note that modifying memory node in the kernel device tree has no effect. The reason is that before boot, u-boot will overwrite the values in the kernel device tree. This means it is important that you set the device tree in u-boot to the setting you want the kernel to have. However, the other settings such as "linux,cma" and "linux,multimedia" are only set in the kernel device tree.

memory Node

  • Defines the total memory for the Linux System
  • Should match what you put in u-boot Device Tree
  • Has no effect (overwritten by u-boot before boot)
	memory@48000000 {
		device_type = "memory";
		/* first 128MB is reserved for secure area. */
		reg = <0x0 0x48000000 0x0 0x78000000>;
	};

linux,cma Node

  • CMA stands for "Contiguous Memory Allocator"
  • Allow allocation of big, physically-contiguous memory blocks used for things like DMA transfers or LCD Frame Buffer.
  • Depending on the size (resolution) of your LCD, you will increase or decrease this size.
  • If you are transferring a lot of data over a network (Ethernet) or USB, you might need to includes this area to have enough buffer area.
	reserved-memory {
		#address-cells = <2>;
		#size-cells = <2>;
		ranges;

		reserved: linux,cma@58000000 {
			compatible = "shared-dma-pool";
			linux,cma-default;
			reusable;
			reg = <0x0 0x58000000 0x0 0x10000000>;
		};
	};

linux,multimedia Node

  • This area is used for H.264 encode or decode.
  • Depending on the resolution of your frames, you many need to increase or decrease this area.
	reserved-memory {
		#address-cells = <2>;
		#size-cells = <2>;
		ranges;

		mmp_reserved: linux,multimedia {
			compatible = "shared-dma-pool";
			reusable;
			reg = <0x00000000 0x68000000 0x0 0x8000000>;
		};
	};

Examples

Reduce reserved area for RZ/G2L SMARC board

  • If you are not evaluating security (OP-TEE) or sub-core (CM33), you can reduce the reserved area from 128MB to 2MB.
  • The Linux kernel must be aligned on a 2MB address boundary, so that is our minimum reserved area size.
  • Move BL31 0x43F00000 >> 0x40001000
  • Reduce BL31 size 0x200000 >> 0xFE000
  • Move BL32 (OP-TEE) 0x44100000 >> 0x400FF000
  • Reduce BL32 (OP-TEE) size 0x100000 >> 0x1000 (too small to be used)
  • Move u-boot and kernel 0x48000000 >> 40200000 (skip beginning of 2MB of DDR) and increase size by 126MB
  • Expand below to show what files need to be modified.
RZ/G2L: Reduce reserved area in Linux from 128MB to 2MB      

Trusted Firmware-A

File: plat/renesas/rz/common/include/plat_tzc_def.h

-/* Trusted Firmware(BL31) secure DRAM 0x43F00000 - 0x440FFFFF */
-#define PLAT_FW_TZC_PROT_DRAM1_BASE            (0x43F00000)
-#define PLAT_FW_TZC_PROT_DRAM1_SIZE            (0x00200000)
+/* Trusted Firmware(BL31) secure DRAM 0x40001000 - 0x400FEFFF */
+#define PLAT_FW_TZC_PROT_DRAM1_BASE            (0x40001000)
+#define PLAT_FW_TZC_PROT_DRAM1_SIZE            (0x000FE000)
-/* OP-TEE secure DRAM 0x44100000 - 0x47DFFFFF */
-#define PLAT_TEE_TZC_PROT_DRAM1_BASE   (0x44100000)
-#define PLAT_TEE_TZC_PROT_DRAM1_SIZE   (0x03D00000)
+/* OP-TEE secure DRAM 0x400FF000 - 0x400FFFFF */
+#define PLAT_TEE_TZC_PROT_DRAM1_BASE   (0x400FF000)
+#define PLAT_TEE_TZC_PROT_DRAM1_SIZE   (0x00001000)

File: plat/renesas/rz/common/include/platform_def.h

-#define BL31_BASE                              (0x44000000)
-#define BL31_LIMIT                             (0x44040000)
+#define BL31_BASE                              (0x40001000)
+#define BL31_LIMIT                             (BL31_BASE + 0xFE000)
-#define BL32_BASE                              (0x44100000)
-#define BL32_LIMIT                             (BL32_BASE + 0x100000)
+#define BL32_BASE                              (0x400FF000)
+#define BL32_LIMIT                             (BL32_BASE + 0x1000)

u-boot

File: include/configs/smarc-rzg2l.h

-#define DRAM_RSV_SIZE			0x08000000
+#define DRAM_RSV_SIZE			0x00200000

File: arch/arm/dts/smarc-rzg2l.dts

        memory@40200000 {
                device_type = "memory";
                /* first 2MB is reserved */
                reg = <0x0 0x40200000 0x0 0x7FE00000>;
        };

kernel

  • Note that this change has no effect because u-boot overwrites it anyway.

File: arch/arm64/boot/dts/renesas/r9a07g044l2-smarc.dts

        memory@40200000 {
                device_type = "memory";
                /* first 2MB is reserved */
                reg = <0x0 0x40200000 0x0 0x7FE00000>;
        };

New Boot Command:

  • Remember that you have to load the kernel and device tree to a different location in DDR
  • Load your kernel Image to 0x40280000
  • Load your Device Tree Blob (dtb) to 0x40200000
  • Use new addresses for booti command
=> set sd_boot1 'mmc dev 1 ; fatload mmc 1:1 0x40280000 Image ; fatload mmc 1:1 0x40200000 /r9a07g044l2-smarc.dtb'
=> set sd_boot2 'setenv bootargs root=/dev/mmcblk1p2 rootwait ; booti 0x40280000 - 0x40200000'
=> saveenv