Board Bringup

This document provides guidance for board bring-up in IoT Yocto.

Before starting software bring-up, please verify the hardware status of the board. The following hardware components and interfaces should be inspected according to your board design:

  • Power source & voltage

  • Clock frequency

  • Voltage in different outputs

  • LEDs status

Check Boot ROM

Connect the board to serial port (UART0) and start serial communication using a baud rate of 115200. If the board is well powered, ROM code logs should appear in the serial interface from UART0 port.

If not, please check whether the hardware is well powered or a powering problem has occurred. The following is an example of Boot ROM log for MT8395:

F0: 102B 0000
F3: 1006 0033 [0200]
F3: 4001 00E0 [0200]
F3: 0000 0000
V0: 0000 0000 [0001]
00: 0000 0000
BP: 0C00 0241 [0000]
G0: 1190 0000
EC: 0080 0000 [0000]
S7: 0000 0000 [0000]
T0: 0000 01AA [100F]
Jump to BL

Different SoC have different Boot ROM log, but the format should be similar.

Create New Yocto Layer

After confirming the SoC is well powered, you can now create new software configurations for your board. To do so, you need to add new layers on top of the meta-mediatek-bsp and meta-rity layers provided by IoT Yocto.

  1. Download IoT Yocto layers by referring to Get Started with IoT Yocto.

  2. Create a meta-<board_name> layer with the following basic architecture:

    meta-<board_name>
    ├── conf
    │   ├── machine
    │   │   └── <machine_name>.conf    # an MACHINE identifier for your board
    │   ├── layer.conf                 #
    │   ├── local.conf.sample          # example configuration for users of your board
    │   └── bblayers.conf.sample       # the layers you'd like to include by default
    │
    ├── recipes-bsp
    │   ├── libdram
    │   │   ├── files/                 # patches to add board support
    │   │   ├── libdram-lk.bbappend    # apply patches to libdram-lk.bb
    │   │   └── libdram.bbappend       # symlink to add the patches to libdram.bb
    │   │
    │   └── u-boot
    │       ├── files/                 # patches to add board support
    │       └── u-boot_%.bbappend      # add device-tree and config patches
    │
    ├── recipes-kernel
    │   └── linux-mtk
    │       ├── files/                 # patches to add device-tree kernel modification and configuration
    │       └── linux-mtk_%.bbappend   # apply the patches to linux kernel
    │
    ├── recipes-core
    │
    └── wic
        └── custom.wks.in              # Partitionning
    

Each recipe could extend or override the definition of existing BSP and RITY layers.

Add New Machine Configuration

For board bring-up, it usually involves adding a new machine configuration to specify the following configurations:

  • DRAM configuration

  • U-Boot device driver and configuration

  • Kernel device driver and configuration

  • Boot process configuration

  • Additional Yocto package and image customization

In meta-<board_name>/conf/machine, add a <machine_name>.conf file. The content should be:

  1. Include SoC-recipe include files. For example,

    require conf/machine/include/mtxxxx.inc
    

    You can refer to existing machine configurations in meta-mediatek-bsp layer to know which include files should be used.

    For example,

    • conf/machine/mt8395-evb-ufs.conf provides configuration for UFS boot and storage configurations for MT8395 EVK mounted with UFS storage.

    • conf/machine/mt8395-demo.conf provides configuration for the MT8395 P1V6 (Genio 1200) demo board, which uses EMMC storage.

  2. Set LIBDRAM_BOARD_NAME, See Libdram configuration

  3. Set kernel device-tree: KERNEL_DEVICETREE, See Kernel device tree

  4. Set u-boot configuration: UBOOT_MACHINE, See U-boot device tree

  5. Set OP-TEE DRAM size: OPTEE_DRAM_SIZE, See OP-TEE DRAM size configuration

  6. Set overrides via MACHINEOVERRIDES variable.

  7. Add machine and distro features using DISTRO_FEATURES_append and MACHINE_FEATURES_append.

The following sections show how to achieve this by modifying different recipes.

libdram Configuration

Note

MT8395 (Genio 1200) does not require modification to libdram. You can use the same libdram binary as in MACHINE=i1200-demo. For other SoCs, please continue to read.

Important

Modifying DRAM component requires proprietary software libdram from MediaTek. You need to get the source code from MediaTek partners and distributors.

In libdram/boards/<board_name>, add a meson.build file that contains the reference for DDR configuration: https://gitlab.com/mediatek/aiot/nda/libdram

libdram
├── board
│    └── <board_name>
│             └── meson.build
├── src
│    └── mtxxxx
│         ├── ddr
│         │    └── <ddr_name>.cfg
│         └── driver
│
└── tools

In meson.build:

SoC = 'mtxxxx'

ddr = [
        '<ddr_name>',
]

MediaTek supports different DDR (refer to libdram/src/<SOC>/ddr : https://gitlab.com/mediatek/aiot/nda/libdram/-/tree/main/src).

  • If the used DDR is supported by MediaTek, it can directly be referenced in libdram/boards/<board_name>.

  • If not, please do the following step to add the new DDR configuration.

In libdram/src/<SoC>/ddr, add a configuration file that contains the DDR config <ddr_name>.cfg.

  • The configuration file should configure DDR registers as ‘EMI_CONA_VAL’ and ‘DRAM RANK SIZE’ …

  • Please refer to the used DDR datasheet to find informations about the registers.

  • Note that depending on the DDR used, the DDR driver in libdram/src/<SoC>/driver may need to be updated.

  • New libdram sources are to be listed in meson.build in libdram/src/<SoC>/.

Patch the modified libdram sources as a libdram patch file.

After adding a new machine in IoT Yocto project (refer to Add New Machine Configuration), set LIBDRAM_BOARD_NAME in machine configuration file.

meta-mediatek-bsp
└─── conf
        └── machine
            └── <board_name>.cfg
...
# libdram
LIBDRAM_BOARD_NAME = "<board_name>"
...
  • Add the libdram patch file to meta-<board_name>/recipes-bsp/libdram/files/.

  • Add the patch PATH to SRC_URI variable in libdram-lk.bbappend.

  • Add symbolic link to libdram.bbappend.

meta-<board_name>
├── recipes-bsp
│   ├── libdram
│   │   ├── files/                 # patches to add board support
│   │   ├── libdram-lk.bbappend    # apply patches to libdram-lk.bb
│   │   └── libdram.bbappend       # symbolic link to add the patches to libdram.bb
... ...

U-Boot configuration

U-Boot Device tree

  1. Add the device tree to u-boot/arch/arm/dts/<mtxxxx-board_name>.dts.

u-boot
└── arch
    └── arm
        └── dts
            └── <mtxxxx-board_name>.dts
  1. Include the SoC device tree : mtxxxx.dtsi.

  2. Refer to already existing device tree with the same SoC.

  3. Configure emmc : frequency, bus-width …

  4. Configure DDR size :

    It is not mandatory to change the default DDR size in u-boot device tree since u-boot only need few MB of memory at most and does not need to use the whole DDR.

memory@40000000 {
            device_type = "memory";
            reg = <0 0x40000000 0 0x80000000>;
    } ;
  • 0 0x40000000 is the address of the DDR in memory coded in 64 Bits, meaning that 0x0000000040000000 is the actual DDR address. This value should not be changed.

  • 0 0x80000000 is the RAM size. In this example, it refers to 2GB of RAM.

With 4GB of RAM use :
reg = <0 0x40000000 1 0x00000000>;  # meaning '0x0000000100000000'.
    1. Add <mtxxxx-board_name>.dtb to u-boot/arch/arm/dts/Makefile.

...
dtb-$(CONFIG_ARCH_MEDIATEK) += \
        <mtxxxx-board_name>.dtb
...
    1. Patch u-boot sources and add the patch to meta-<board_name>/recipes-bsp/u-boot/files/.

    1. Add the patch PATH to SRC_URI variable in meta-<board_name>/recipes-bsp/u-boot/u-boot_%.bbappend.

meta-<board_name>
├──recipes-bsp
│  └── u-boot
│      ├── files/                 # patches to add board support
│      └── u-boot_%.bbappend      # add device-tree and config patches
...

U-Boot Machine Configuration

Use already existing SoC-matching defconfig if no changes are to be added (jump to step 4).

To create a board specific u-boot defconfig please follow the next steps:
    1. Create a <mtxxxx_board_defconfig> that contains u-boot configuration in /configs

u-boot
└── configs
    └── <mtxxxx_board_defconfig>
    1. Patch u-boot sources and add the patch to meta-<board_name>/recipes-bsp/u-boot/files/.

    1. Add the patch PATH to SRC_URI variable in meta-<board_name>/recipes-bsp/u-boot/u-boot_%.bbappend.

meta-<board_name>
├──recipes-bsp
│   └── u-boot
│       ├── files/                 # patches to add board support
│       └── u-boot_%.bbappend      # add device-tree and config patches
    1. Set UBOOT_MACHINE variable in <machine_name>.conf

    meta-<board_name>
    ├── conf
    │   ├── machine
    │   │   └── <machine_name>.conf    #
    │   ├── layer.conf                 #
    │   ├── local.conf.sample          #
    │   └── bblayers.conf.sample       #
...
UBOOT_MACHINE = "mtxxxx_board_defconfig"

OP-TEE configuration

OP-TEE DRAM Size Configuration

Use already existing SoC-matching machine config if no changes are to be added (jump to step 4).

Important

The OP-TEE DRAM size must be equal to the DRAM size configured in kernel device tree.

    1. (Optional) If the DRAM size is large than 4GB, set CFG_CORE_ARM64_PA_BITS,36 in <OP-TEE>/core/arch/arm/plat-mediatek/conf.mk.

optee-os
└── core
    └── arch
        └── arm
            └── plat-mediatek
                └── conf.mk
ifeq ($(PLATFORM_FLAVOR),<platform_name>)
$(call force,CFG_CORE_ARM64_PA_BITS,36)
endif
    1. Patch optee-os sources and add the patch to meta-<board_name>/recipes-security/optee-os/files/.

    1. Add the patch PATH to SRC_URI variable in meta-<board_name>/recipes-security/optee-os/optee-os_%.bbappend.

meta-<board_name>
├──recipes-security
│   └── optee-os
│       ├── files/                 # patches to add board support
│       └── optee-os_%.bbappend    # add DRAM PA bits patch
    1. Set OPTEE_DRAM_SIZE variable in <machine_name>.conf

    meta-<board_name>
    ├── conf
    │   ├── machine
    │   │   └── <machine_name>.conf    #
    │   ├── layer.conf                 #
    │   ├── local.conf.sample          #
    │   └── bblayers.conf.sample       #
...
With 2GB of DRAM use :
OPTEE_DRAM_SIZE = "0x80000000"  # meaning '0x000000080000000'.
With 8GB of DRAM use :
OPTEE_DRAM_SIZE = "0x200000000"  # meaning '0x0000000200000000'.

Kernel Configurations

Kernel Device Tree

Kernel device tree should be added to arch/arm64/boot/dts/mediatek/ in kernel source tree.

    1. Create a device tree file <mtxxxx-board_name>.dts

    1. Refer to already existing device tree with the same SoC

    1. Include necessary .dtsi file and configure RAM size (see uboot device tree configuration)

    1. Do pin muxing and emmc configuration, such as frequency.

    1. Add <mtxxxx-board_name>.dtb to arch/arm64/boot/dts/mediatek/Makefile

dtb-$(CONFIG_ARCH_MEDIATEK) += <mtxxxx-board_name>.dtb
    1. Patch kernel sources and add the patch to meta-<board_name>/recipes-kernel/linux-mtk/files/.

    1. Add the patch path to SRC_URI variable in meta-<board_name>/recipes-kernel/linux-mtk/linux-mtk_%.bbappend.

meta-<board_name>
├── recipes-kernel
│   └── linux-mtk
│       ├── files/                 # patches to add device-tree kernel modification and configuration
│       └── linux-mtk_%.bbappend   # apply the patches to linux kernel

Kernel Configuration

The kernel configuration used by yocto is a merge of the Linux ARM64 defconfig in arch/arm64/configs/defconfig and config fragments that can be found in recipes-kernel/linux-mtk/files.

Note

Please refer to Add extra kernel configuration and Kernel Development in order to add extra kernel configuration.

Yocto and Image customization

Add new prebuilt so/ko for drivers

  • In recipes-kernel/, create <module_name>/src folder and add <module_name>.ko.

  • Create a recipe file <recipe_name>.bb in meta-<board_name>/recipes-kernel/<module_name>/ in order to add the module to SRC_URI variable.

meta-<board_name>
├── recipes-kernel
│   ├── linux-mtk
│   │   ├── files/                 # patches to add device-tree kernel modification and configuration
│   │   └── linux-mtk_%.bbappend   # apply the patches to linux kernel
│   │
│   └── <module_name>
│       ├── src/
│       │    └── <module_name>.ko
│       │
│       └── <recipe_name>.bb
...

An example of what the recipe may look like:

SUMMARY = "Example of how to add prebuilt module"
DESCRIPTION = "${SUMMARY}"

FILESEXTRAPATHS:prepend := "${THISDIR}/src:"

inherit linux-kernel-base

S = "${WORKDIR}"

SRC_URI = "file://<module_name>.ko\"

S = "${WORKDIR}"

do_install() {
        install -m 755 ${S}/<module_name>.ko
}

Add extra kernel configuration

In order to add extra kernel configuration:

  • Add new <board>.cfg in meta-<board_name>/recipes-kernel/linux-mtk/files/.

  • Create linux-mtk_%.bbappend in meta-<board_name>/recipes-kernel/linux-mtk/.

meta-<board_name>
├── recipes-kernel
│   └── linux-mtk
│       ├── files/                 # config files and patches to add device-tree kernel modification and configuration
│       │   └── <board>.cfg
│       └── linux-mtk_%.bbappend   # apply the patches to linux kernel
...
  • Append <board>.cfg to SRC_URI variable in linux-mtk_%.bbappend.

FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
SRC_URI:append = " \
        file://<board>.cfg \
    "

Layer configuration

Detailed explanation is given in Create your own layer section.

  • Add the created layer to meta-<board_name>/conf/bblayers.conf.sample.

Example of bblayers.conf.sample
# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf
# changes incompatibly
POKY_BBLAYERS_CONF_VERSION = "2"

BBPATH = "${TOPDIR}"
BBFILES ?= ""

BBLAYERS ?= " \
    ##OEROOT##/meta \
    ##OEROOT##/meta-poky \
    ##OEROOT##/meta-yocto-bsp \
    ##OEROOT##/../meta-arm/meta-arm \
    ##OEROOT##/../meta-arm/meta-arm-toolchain \
    ##OEROOT##/../meta-mediatek-bsp \
    ##OEROOT##/../meta-openembedded/meta-oe \
    ##OEROOT##/../meta-openembedded/meta-python \
    ##OEROOT##/../meta-rity/meta \
    ##OEROOT##/../meta-rity/meta-rity-bringup \
    ##OEROOT##/../meta-<board_name> \
"
  • Add meta-<board_name>/conf/layer.conf file and set layer information, priority, dependency …

Example of layer.conf
# We have a conf and classes directory, add to BBPATH
BBPATH .= ":${LAYERDIR}"

# We have recipes-* directories, add to BBFILES
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend"

BBFILE_COLLECTIONS += "<board_name>"
BBFILE_PATTERN:<board_name> = "^${LAYERDIR}/"
BBFILE_PRIORITY:<board_name> = "12"

# This should only be incremented on significant changes that will
# cause compatibility issues with other layers
LAYERVERSION:<board_name> = "1"

LAYERDEPENDS:<board_name> = ""

# Yocto 3.1, codename: Dunfell (LTS)
# Yocto 3.2, codename: Gatesgarth (Stable)
# Yocto 3.3, codename: Hardknott (Stable)
LAYERSERIES_COMPAT:<board_name> = "dunfell"

Adjust storage partition

  • Add custom.wks.in to meta-<board_name>/wic/.

        meta-<board_name>
        └── wic
            └── custom.wks.in              # Partitioning
  • Add the wks file to meta-<board_name>/conf/local.conf.sample

WKS_FILE:forcevariable = "custom.wks.in"

An example of image partitioning :

# SHORT-description: Create an image for MediaTek SoC based boards
# long-description: Creates a partitioned image for MediaTek SoC based boards.

bootloader --ptable gpt --timeout=0
part --source rawcopy --sourceparams="file=fip.bin" --part-name bootloaders --align 512 --fixed-size 4M
part --source rawcopy --sourceparams="file=fitImage" --part-name kernel --size 15M
part / --source rootfs --fstype=ext4 --label rootfs --part-name rootfs --part-type B921B045-1DF0-41C3-AF44-4C6F280D3FAE --active --exclude-path=home/
part /home --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/home --fstype=ext4 --label home --part-name home --part-type 933AC7E1-2EB4-4F13-B844-0E14E2AEF915 --use-uuid --size ${IMAGE_HOME_SIZE} --mkfs-extraopts "-b ${WIC_BLOCK_SIZE}"

Note

For further informations about using wic, plese refer to Yocto documentation :

Yocto Documentation

Please see ‘ Frequently Asked Questions ‘ section to change rootfs / home size ..

Memory reserved regions

The size of memory reserved regions used by IoT Yocto SDK is not mandatory to be changed. The memory mapping for MT8395(Genio 1200) and MT8365(Genio 350) are shown as follows:

../../_images/sw_yocto_board-bringup_mem.png

For example if you would like to adjust the TF-A(BL31) start address and size, you could find the definition in trusted-firmware-a source and dts:

#define TZRAM_BASE          (0x54600000)
#define TZRAM_SIZE          (0x00200000)
bl31_secmon_reserved: secmon@54600000 {
        no-map;
        reg = <0 0x54600000 0x0 0x200000>;
};

For example if you would like to adjust the OP-TEE(BL32), you could find the definition in trusted-firmware-a source, dts and machine configurations in meta-mediatek-bsp layer:

#define BL32_BASE              (0x43200000)
#define BL32_LIMIT             (0x00c00000)
optee_reserved: optee@43200000 {
        no-map;
        reg = <0 0x43200000 0 0x00c00000>;
};
OPTEE_TZDRAM_START ?= "0x43200000"
OPTEE_TZDRAM_SIZE  ?= "0x00c00000"

Note

Please make sure the start address and size of memory reserved regions could not overlap.

Boot process (systemd) customization

Enable Systemd

Add the following lines to enable systemd by default:

meta-<board_name>
├── conf
│   ├── machine
│   │   └── <machine_name>.conf    #
│   ├── layer.conf                 #
│   ├── local.conf.sample          #
│   └── bblayers.conf.sample       #
DISTRO_FEATURES_append = " systemd"
DISTRO_FEATURES_BACKFILL_CONSIDERED += "sysvinit"
VIRTUAL-RUNTIME_init_manager = "systemd"
VIRTUAL-RUNTIME_initscripts = "systemd-compat-units"

Add Systemd Services File

  • Create meta-<board_name>/recipes-core/systemd/files

  • Add service files <service_name>,service to /files

  • Add systemd_%.bbappend recipe to integrate the service to systemd configuration.

 meta-<board_name>
 ├── recipes-core
 │   └── systemd
 │       ├── files/
 │       │   └── <service_name>.service
 │       └── systemd_%.bbappend
...

Hardware documentation

Please refer to MediaTek Online or request hardware documentation from your MediaTek contact window.