.. include:: /keyword.rst ============== Board Bring Up ============== This document provides guidance for board bring up in |IOT-YOCTO|. .. contents:: Sections :local: :depth: 1 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 .. _boot-rom-log: 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: .. code-block:: text 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 :doc:`/sw/yocto/get-started`. 2. Create a ``meta-`` layer with the following basic architecture: .. code-block:: meta- ├── conf │ ├── machine │ │ └── .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 # Partitioning Each recipe could extend or override the definition of existing BSP and RITY layers. .. _new-machine-config: 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-/conf/machine``, add a **.conf** file. The content should be: 1. Include SoC-recipe include files. For example, .. code:: require conf/machine/include/mtxxxx.inc You can refer to existing board configurations in ``meta-mediatek-bsp`` layer to know which include files that should be used. For example, * ``conf/machine/genio-1200-evk.conf`` provides configuration for the |G1200-EVK| which uses eMMC storage by default. * ``conf/machine/genio-1200-evk-ufs.conf`` provides configuration for UFS boot and storage configurations for Genio 1200 EVK configured for UFS storage. 2. Set ``LIBDRAM_BOARD_NAME``, **See** :ref:`Libdram configuration ` 3. Set kernel device-tree: ``KERNEL_DEVICETREE``, **See** :ref:`Kernel device tree ` 4. Set U-Boot configuration: ``UBOOT_MACHINE``, **See** :ref:`U-Boot device tree ` 5. Set OP-TEE DRAM size: ``OPTEE_DRAM_SIZE``, **See** :ref:`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: `libdram` Configuration ======================= .. note:: Only **MT8365** (Genio 350) requires modification to ``libdram``. For other SoCs, please skip this section. .. important:: 1. Modifying DRAM component requires proprietary software ``libdram`` from MediaTek. You need to get the source code from MediaTek partners and distributors. 2. The DRAM driver will determine the bank size and bank number based on the voltage of the AUXIN1 pin. Please refer to the hardware design notice and reference design document for guidance, and set the AUXIN1 pin to the correct voltage. .. important:: ``libdram`` is used by the bl2 and the download agent (`lk`). If you make modifications to the source code locally, you need to modify both the ``libdram`` and ``libdram-lk``. Using the following commands to obtain the source code. .. code-block:: devtool modify libdram devtool modify libdram-lk And also you need to modify both ``build/workspace/sources/libdram/`` and ``build/workspace/sources/libdram-lk/``. Then rebuild ``rity-demo-image`` and ``lk``. In ``libdram/boards/``, add a ``meson.build`` file that contains the reference for DDR configuration: https://gitlab.com/mediatek/aiot/nda/libdram .. code-block:: :emphasize-lines: 4-4 libdram ├── board │ └── │ └── meson.build ├── src │ └── mtxxxx │ ├── ddr │ │ └── .cfg │ └── driver │ └── tools In ``meson.build``: .. code-block:: SoC = 'mtxxxx' ddr = [ '', ] MediaTek supports different DDR type and provide some default configurations(refer to ``libdram/src//ddr`` : https://gitlab.com/mediatek/aiot/nda/libdram/-/tree/main/src). - Please select the ``ddrtype_default.cfg`` base on your DDR type. - Please define the DDR type you are using and comment out other types. .. code-block:: #add_project_arguments('-DCOMBO_LPDDR3_178BALL', language: 'c') add_project_arguments('-DCOMBO_LPDDR4', language: 'c') #add_project_arguments('-DCOMBO_PCDDR3_32BIT', language: 'c') #add_project_arguments('-DCOMBO_PCDDR4_32BIT', language: 'c') Patch the modified ``libdram`` sources as a ``libdram`` patch file. After adding a new machine in |IOT-YOCTO| project (refer to :ref:`new-machine-config`), set **LIBDRAM_BOARD_NAME** in machine configuration file. .. code-block:: :emphasize-lines: 4-4 meta-mediatek-bsp └─── conf └── machine └── .cfg .. code:: ... # libdram LIBDRAM_BOARD_NAME = "" ... * Add the ``libdram`` patch file to ``meta-/recipes-bsp/libdram/files/``. * Add the patch path to ``SRC_URI`` variable in **libdram-lk.bbappend**. * Add symbolic link to **libdram.bbappend**. .. code-block:: :emphasize-lines: 4-6 meta- ├── 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-dts: U-Boot Device tree ------------------ 1. Add the device tree to **u-boot/arch/arm/dts/.dts**. .. code-block:: :emphasize-lines: 5-5 u-boot └── arch └── arm └── dts └── .dts 2. Include the SoC device tree : **mtxxxx.dtsi**. 3. Refer to already existing device tree with the same SoC. 4. Configure eMMC : frequency, bus-width ... 5. 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. .. code:: 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 : .. code:: reg = <0 0x40000000 1 0x00000000>; # meaning '0x0000000100000000'. * 6. Add **.dtb** to ``u-boot/arch/arm/dts/Makefile``. .. code:: ... dtb-$(CONFIG_ARCH_MEDIATEK) += \ .dtb ... * 7. Patch U-Boot sources and add the patch to ``meta-/recipes-bsp/u-boot/files/``. * 8. Add the patch PATH to ``SRC_URI`` variable in ``meta-/recipes-bsp/u-boot/u-boot_%.bbappend``. .. code-block:: :emphasize-lines: 4-5 meta- ├──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`` .. code-block:: :emphasize-lines: 3-3 u-boot └── configs └── * 2. Patch U-Boot sources and add the patch to ``meta-/recipes-bsp/u-boot/files/``. * 3. Add the patch PATH to ``SRC_URI`` variable in ``meta-/recipes-bsp/u-boot/u-boot_%.bbappend``. .. code-block:: :emphasize-lines: 4-5 meta- ├──recipes-bsp │ └── u-boot │ ├── files/ # patches to add board support │ └── u-boot_%.bbappend # add device-tree and config patches * 4. Set ``UBOOT_MACHINE`` variable in ``.conf`` .. code-block:: :emphasize-lines: 4-4 meta- ├── conf │ ├── machine │ │ └── .conf # │ ├── layer.conf # │ ├── local.conf.sample # │ └── bblayers.conf.sample # ... .. code:: UBOOT_MACHINE = "mtxxxx_board_defconfig" OP-TEE configuration ==================== .. _optee-dram-size: 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 ``/core/arch/arm/plat-mediatek/conf.mk``. .. code-block:: :emphasize-lines: 6-6 optee-os └── core └── arch └── arm └── plat-mediatek └── conf.mk .. code-block:: ifeq ($(PLATFORM_FLAVOR),) $(call force,CFG_CORE_ARM64_PA_BITS,36) endif * 2. Patch OP-TEE sources and add the patch to ``meta-/recipes-security/optee-os/files/``. * 3. Add the patch PATH to ``SRC_URI`` variable in ``meta-/recipes-security/optee-os/optee-os_%.bbappend``. .. code-block:: :emphasize-lines: 4-5 meta- ├──recipes-security │ └── optee-os │ ├── files/ # patches to add board support │ └── optee-os_%.bbappend # add DRAM PA bits patch * 4. Set ``OPTEE_DRAM_SIZE`` variable in ``.conf`` .. code-block:: :emphasize-lines: 4-4 meta- ├── conf │ ├── machine │ │ └── .conf # │ ├── layer.conf # │ ├── local.conf.sample # │ └── bblayers.conf.sample # ... | With 2GB of DRAM use : .. code:: OPTEE_DRAM_SIZE = "0x80000000" # meaning '0x000000080000000'. | With 8GB of DRAM use : .. code:: OPTEE_DRAM_SIZE = "0x200000000" # meaning '0x0000000200000000'. Kernel Configurations ===================== .. _kernel-dts: 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 ``.dts`` * 2. Refer to already existing device tree with the same SoC * 3. Include necessary ``.dtsi`` file and configure RAM size .. code:: memory@40000000 { device_type = "memory"; reg = <0 0x40000000 0 0x80000000>; }; * 4. Do pin muxing and eMMC configuration, such as frequency. * 5. Add ``.dtb`` to ``arch/arm64/boot/dts/mediatek/Makefile`` .. code:: dtb-$(CONFIG_ARCH_MEDIATEK) += .dtb * 6. Patch kernel sources and add the patch to ``meta-/recipes-kernel/linux-mtk/files/``. * 7. Add the patch path to ``SRC_URI`` variable in ``meta-/recipes-kernel/linux-mtk/linux-mtk_%.bbappend``. .. code-block:: :emphasize-lines: 4-5 meta- ├── 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 :ref:`extra-kernel-config` and :doc:`/sw/yocto/kernel-dev` in order to add extra kernel configuration. Yocto and Image customization ============================= Add new prebuilt so/:spelling:ignore:`ko` for drivers ----------------------------------------------------- * In recipes-kernel/, create **/src** folder and add **.ko**. * Create a recipe file **.bb** in ``meta-/recipes-kernel//`` in order to add the module to ``SRC_URI`` variable. .. code-block:: :emphasize-lines: 7-11 meta- ├── recipes-kernel │ ├── linux-mtk │ │ ├── files/ # patches to add device-tree kernel modification and configuration │ │ └── linux-mtk_%.bbappend # apply the patches to linux kernel │ │ │ └── │ ├── src/ │ │ └── .ko │ │ │ └── .bb ... An example of what the recipe may look like: .. code:: SUMMARY = "Example of how to add prebuilt module" DESCRIPTION = "${SUMMARY}" FILESEXTRAPATHS:prepend := "${THISDIR}/src:" inherit linux-kernel-base S = "${WORKDIR}" SRC_URI = "file://.ko\" S = "${WORKDIR}" do_install() { install -m 755 ${S}/.ko } .. _extra-kernel-config: Add extra kernel configuration ------------------------------ In order to add extra kernel configuration: * Add new **.cfg** in ``meta-/recipes-kernel/linux-mtk/files/``. * Create **linux-mtk_%.bbappend** in ``meta-/recipes-kernel/linux-mtk/``. .. code-block:: :emphasize-lines: 5-6 meta- ├── recipes-kernel │ └── linux-mtk │ ├── files/ # config files and patches to add device-tree kernel modification and configuration │ │ └── .cfg │ └── linux-mtk_%.bbappend # apply the patches to linux kernel ... * Append ``.cfg`` to ``SRC_URI`` variable in ``linux-mtk_%.bbappend``. .. code:: FILESEXTRAPATHS:prepend := "${THISDIR}/files:" SRC_URI:append = " \ file://.cfg \ " Layer configuration ------------------- Detailed explanation is given in **Create your own layer** section. * Add the created layer to ``meta-/conf/bblayers.conf.sample``. | Example of **bblayers.conf.sample** .. code:: # 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- \ " * Add ``meta-/conf/layer.conf`` file and set layer information, priority, dependency ... | Example of **layer.conf** .. code:: # 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 += "" BBFILE_PATTERN: = "^${LAYERDIR}/" BBFILE_PRIORITY: = "12" # This should only be incremented on significant changes that will # cause compatibility issues with other layers LAYERVERSION: = "1" LAYERDEPENDS: = "" # Yocto 3.1, codename: Dunfell (LTS) # Yocto 3.2, codename: Gatesgarth (Stable) # Yocto 3.3, codename: Hardknott (Stable) LAYERSERIES_COMPAT: = "dunfell" Adjust storage partition ======================== * Add ``custom.wks.in`` to ``meta-/wic/``. .. code-block:: :emphasize-lines: 3-3 meta- └── wic └── custom.wks.in # Partitioning * Add the `wks` file to ``meta-/conf/local.conf.sample`` .. code:: WKS_FILE:forcevariable = "custom.wks.in" An example of image partitioning : .. code:: # 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 information about using wic, please 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 MT8365 (Genio 350), MT8370 (Genio 510), MT8390 (Genio 700) and MT8395 (Genio 1200) are shown as follows: .. figure:: /_asset/sw_yocto_board-bringup_mem.png :align: center :width: 1000px 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**: * `platform_def.h `_ for MT8395 (Genio 1200) : .. code:: #define TZRAM_BASE (0x54600000) #define TZRAM_SIZE (0x00200000) * `mt8195-demo.dts `_ for MT8395 (Genio 1200) : .. code:: 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: * `platform_def.h `_ for MT8395 (Genio 1200) : .. code:: #define BL32_BASE (0x43200000) #define BL32_LIMIT (0x00c00000) * `mt8195-demo.dts `_ for MT8395 (Genio 1200) : .. code:: optee_reserved: optee@43200000 { no-map; reg = <0 0x43200000 0 0x00c00000>; }; * `mediatek-common.inc `_ for MT8395 (Genio 1200) : .. code:: OPTEE_TZDRAM_START ?= "0x43200000" OPTEE_TZDRAM_SIZE ?= "0x00c00000" You might need to change the memory reserved regions to fit the kernel size changes during development. The default memory address for Genio 350, Genio 510, Genio 700 and Genio 1200 are aligned to 0x64000000, but this is not mandatory and can be adjusted to fit the size of your kernel. The default configuration of |IOT-YOCTO| allows kernel to be relocated. If you would like to adjust the Linux Kernel, you could find the definition in **meta-mediatek-bsp** layer: * `mediatek-common.inc `_ for MT8395(Genio 1200) : .. code:: UBOOT_ENTRYPOINT = "0x64000000" UBOOT_LOADADDRESS = "0x64000000" * When the kernel size is too big, the error messages could happen as follows: .. code:: ERROR: reserving fdt memory region failed (addr=43200000 size=c00000 flags=4) .. note:: | Please make sure the start address and size of memory reserved regions could not overlap. Testing Memory Region Configuration ----------------------------------- If you've updated the reserved region settings in board DTS or in bootloader, we recommend you to check for the consistency of memory region settings between bootloader and kernel. Therefore, you should run the kernel `memtest `__ after any memory configuration update. To run kernel `memtest`, you can: 1. Make sure the kernel config ``CONFIG_MEMTEST=y`` is set to enabled. 2. Add a kernel boot command line parameter ``memtest=1``. You can do this in U-Boot console, or use the ``fw_setenv`` utility: .. code:: bash fw_setenv bootargs "memtest=1" reboot 3. Reboot the system, and during kernel startup, a kernel message ``early_memtest`` should appear: .. code:: text [ 0.000000] early_memtest: # of tests: 2 [ 0.000000] 0x0000000040000000 - 0x0000000043200000 pattern ffffffffffffffff [ 0.000000] 0x0000000043e00000 - 0x0000000050000000 pattern ffffffffffffffff [ 0.000000] 0x0000000052900000 - 0x0000000053000000 pattern ffffffffffffffff [ 0.000000] 0x0000000054400000 - 0x0000000054600000 pattern ffffffffffffffff [ 0.000000] 0x0000000054800000 - 0x0000000060000000 pattern ffffffffffffffff If you see ``bad mem addr``, then this might indicate an incorrect DRAM configuration, or mismatched memory region between bootloader and kernel: .. code:: text [ 0.000000] ffffffffffffffff bad mem addr 0x0000000054800740 - 0x0000000054800780 reserved [ 0.000000] ffffffffffffffff bad mem addr 0x00000000548009c0 - 0x0000000054800a00 reserved [ 0.000000] ffffffffffffffff bad mem addr 0x0000000054800fc0 - 0x0000000054801000 reserved [ 0.000000] ffffffffffffffff bad mem addr 0x0000000054801540 - 0x0000000054801580 reserved [ 0.000000] ffffffffffffffff bad mem addr 0x0000000054801740 - 0x0000000054801780 reserved [ 0.000000] ffffffffffffffff bad mem addr 0x0000000054801880 - 0x00000000548018c0 reserved Boot process (`systemd`) customization ====================================== Enable `systemd` ---------------- .. note:: https://wiki.koansoftware.com/index.php/Add_a_systemd_service_file_into_a_Yocto_image Add the following lines to enable `systemd` by default: .. code-block:: :emphasize-lines: 6-6 meta- ├── conf │ ├── machine │ │ └── .conf # │ ├── layer.conf # │ ├── local.conf.sample # │ └── bblayers.conf.sample # .. code:: 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-/recipes-core/systemd/files`` * Add service files ``.service`` to ``/files`` * Add ``systemd_%.bbappend`` recipe to integrate the service to `systemd` configuration. .. code-block:: :emphasize-lines: 3-6 meta- ├── recipes-core │ └── systemd │ ├── files/ │ │ └── .service │ └── systemd_%.bbappend ... Hardware documentation ====================== Please refer to MediaTek Online or request hardware documentation from your MediaTek contact window.