#@TYPE: Machine
#@NAME: zynqmp-generic
#@DESCRIPTION: Machine configuration for the zynqmp-generic devices

#### Preamble
MACHINEOVERRIDES =. "${@['', 'zynqmp-generic:']['zynqmp-generic' != '${MACHINE}']}"
#### Regular settings follow

# Variables that changes based on hw design or board specific requirement must be
# defined before calling the required inclusion file else pre-expansion value
# defined in local.conf without machine override will not be reflected.

# Yocto device-tree variables
YAML_CONSOLE_DEVICE_CONFIG:pn-device-tree ?= "psu_uart_0"
YAML_MAIN_MEMORY_CONFIG:pn-device-tree ?= "PSU_DDR_0"
DT_PADDING_SIZE:pn-device-tree ?= "0x1000"
DTC_FLAGS:pn-device-tree = "-@"
YAML_DT_BOARD_FLAGS ?= "{BOARD zcu102-rev1.0}"

# Yocto ZynqMP u-boot-xlnx variables
UBOOT_MACHINE ?= "xilinx_zynqmp_virt_defconfig"
BOOTMODE ?= "generic.root"

# By default U-boot SPL boot is disabled
SPL_BINARY ?= ""

# If user needs U-boot SPL boot, then enable SPL from local.conf as shown below.
# SPL_BINARY = "spl/boot.bin"

# Yocto ZynqMP arm-trusted-firmware(TF-A) variables
TFA_BL33_LOAD ?= "0x8000000"

# Yocto ZynqMP PMUFW variables
YAML_SERIAL_CONSOLE_STDIN:pn-pmu-firmware ?= "psu_uart_0"
YAML_SERIAL_CONSOLE_STDOUT:pn-pmu-firmware ?= "psu_uart_0"

# Yocto ZynqMP FSBL variables
YAML_SERIAL_CONSOLE_STDIN:pn-fsbl-firmware ?= "psu_uart_0"
YAML_SERIAL_CONSOLE_STDOUT:pn-fsbl-firmware ?= "psu_uart_0"

# Yocto ZynqMP KERNEL Variables
UBOOT_ENTRYPOINT  ?= "0x200000"
UBOOT_LOADADDRESS ?= "0x200000"

# ZynqMP Serial Console
SERIAL_CONSOLES ?= "115200;ttyPS0"
YAML_SERIAL_CONSOLE_BAUDRATE ?= "115200"

require conf/machine/include/soc-zynqmp.inc
require conf/machine/include/machine-xilinx-default.inc
require conf/machine/include/machine-xilinx-qemu.inc

# zynqmp-generic.conf uses zcu102-zynqmp xsa as reference input.
# User can override with custom xsa using HDF_BASE and HDF_PATH variables from
# local.conf.
HDF_MACHINE = "zcu102-zynqmp"

# Machine features must result in a superset
# Basic features:
MACHINE_FEATURES += "rtc ext2 ext3 vfat usbhost usbgadget wifi bluetooth"

# Default SD image build onfiguration, use qemu-sd to pad
IMAGE_CLASSES += "image-types-xilinx-qemu"
# Add wic.qemu-sd only if initramfs_image not set due to circular dependecies
IMAGE_FSTYPES += "${@'wic.qemu-sd' if (d.getVar('INITRAMFS_IMAGE') or '') == '' else 'cpio.gz.u-boot'}"

MACHINE_ESSENTIAL_EXTRA_RDEPENDS += "${PREFERRED_PROVIDER_virtual/dtb}"

EXTRA_IMAGEDEPENDS += " \
    libyaml-native \
    python3-cython-native \
    python3-pyyaml-native \
    virtual/fsbl \
    virtual/pmu-firmware \
    arm-trusted-firmware \
    virtual/boot-bin \
    virtual/bootloader \
    qemu-devicetrees \
    u-boot-xlnx-uenv \
    u-boot-xlnx-scr \
    "

IMAGE_BOOT_FILES += " \
    boot.bin \
    ${@bb.utils.contains('PREFERRED_PROVIDER_virtual/dtb', 'device-tree', 'system.dtb', '', d)} \
    boot.scr \
    Image \
    "

# ZynqMP QEMU Configurations
# This machine has a QEMU model, runqemu setup:
QB_MEM = "-m 4096"
# Iteration appears to be eth3, eth2, eth1, eth0
QB_NETWORK_DEVICE = "-net nic -net nic -net nic -net nic,netdev=net0,macaddr=@MAC@"

# Set variables for QEMU DTB PATH, PS DTB and PMU DTB for zynqmp_generic, this
# allows user to use different QEMU HW DTB to match their board.
QEMU_HW_DTB_PATH = "${DEPLOY_DIR_IMAGE}/qemu-hw-devicetrees/multiarch"
QEMU_HW_DTB_PS = "${QEMU_HW_DTB_PATH}/zcu102-arm.dtb"
QEMU_HW_DTB_PMU = "${QEMU_HW_DTB_PATH}/zynqmp-pmu.dtb"

# Replicate BootROM like behaviour, having loaded SPL and PMU(ROM+FW)
#
# In an actual device the FSBL will run first, load ATF and setup the
# following data structure to tell ATF what to continue booting with.
#
# In QEMU emulation we start booting directly from ATF, so we need to
# setup the structure ourselves.
#
# Write to OCM (See UG1085 for more information), address 0xfffc0000
# the address to boot from (where u-boot is):
# fffc0000  58 4c 4e 58  01 00 00 00  |XLNX....|
# fffc0008  00 00 00 08  00 00 00 00  |........|
# fffc0010  10 00 00 00  00 00 00 00  |........|
#
# Then write that address (fffc0000) to 0xffd80048 so ATF can find this block
#
# fffc0008 defines the u-boot load address as 0x8000000, if u-boot is
# expected to be elsewhere in memory, you must adjust the value.
#
# We write the structure as big endian to make it easier to match/read
# the table above.  Remember the CPU is running in little endian mode,
# with the default resulting in:
# 00000000fffc0000: 0x584e4c58 0x00000001 0x08000000 0x00000000
# 00000000fffc0010: 0x00000010 0x00000000
#
QB_OPT_APPEND = " \
    -hw-dtb ${QEMU_HW_DTB_PS} \
    ${@qemu_zynqmp_unhalt(d, True)} \
    -device loader,addr=0xfffc0000,data=0x584c4e5801000000,data-be=true,data-len=8 \
    -device loader,addr=0xfffc0008,data=0x0000000800000000,data-be=true,data-len=8 \
    -device loader,addr=0xfffc0010,data=0x1000000000000000,data-be=true,data-len=8 \
    -device loader,addr=0xffd80048,data=0xfffc0000,data-len=4,attrs-secure=on \
    -device loader,file=${DEPLOY_DIR_IMAGE}/arm-trusted-firmware.elf,cpu-num=0 \
    -device loader,file=${DEPLOY_DIR_IMAGE}/u-boot.elf \
    -device loader,file=${DEPLOY_DIR_IMAGE}/system.dtb,addr=0x100000,force-raw=on \
    ${@qemu_add_extra_args(d)} \
    "

QB_PMU_OPT = " \
    -M microblaze-fdt \
    -display none \
    -hw-dtb ${QEMU_HW_DTB_PMU} \
    -kernel ${PMU_ROM} \
    -device loader,file=${PMU_FIRMWARE_DEPLOY_DIR}/${PMU_FIRMWARE_IMAGE_NAME}.elf \
    -device loader,addr=0xfd1a0074,data=0x1011003,data-len=4 \
    -device loader,addr=0xfd1a007C,data=0x1010f03,data-len=4 \
    "

QB_OPT_APPEND += " -pmu-args '${QB_PMU_OPT}'"

#### No additional settings should be after the Postamble
#### Postamble
PACKAGE_EXTRA_ARCHS:append = "${@['', ' zynqmp_generic']['zynqmp-generic' != "${MACHINE}"]}"
