User Tools

Site Tools


u-boot_porting_board

Overview

Quick run-through of the supporting content and files for a specific board; in this case, the Zynq Zedboard.

Based on:

  • ARCH=arm
  • CPU=armv7
  • VENDOR=xilinx
  • BOARD=zynq

along with some common content across all Zynq variations. Writeup here.

Files/directories

Note that while all of the following, in some way, contribute to U-Boot support of the Zynq Zedboard, a lot of that could already be there if you already supported Zynq-based boards, so you would need to add only the Zedboard-related stuff.

  • configs/
    • zynq_zed_defconfig
  • include/
    • configs/
      • zynq-common.h
  • arch/
    • arm/
      • Kconfig
      • Makefile
      • mach-zynq/
  • board/
    • xilinx/
      • zynq/
        • Kconfig
        • Makefile
        • board.c
        • cmds.c
        • zynq-zed/
      • common/
        • board.c

configs/zynq_zed_defconfig

Board-specific config settings.

include/configs/

zynq-common.h

 * Common configuration options for all Zynq boards.
 */

#ifndef __CONFIG_ZYNQ_COMMON_H
#define __CONFIG_ZYNQ_COMMON_H

/* CPU clock */
#ifndef CONFIG_CPU_FREQ_HZ
# define CONFIG_CPU_FREQ_HZ     800000000
#endif

#define CONFIG_REMAKE_ELF

/* Cache options */
#define CONFIG_SYS_L2CACHE_OFF
#ifndef CONFIG_SYS_L2CACHE_OFF
# define CONFIG_SYS_L2_PL310
# define CONFIG_SYS_PL310_BASE          0xf8f02000
#endif

#define ZYNQ_SCUTIMER_BASEADDR          0xF8F00600
#define CONFIG_SYS_TIMERBASE            ZYNQ_SCUTIMER_BASEADDR
#define CONFIG_SYS_TIMER_COUNTS_DOWN
#define CONFIG_SYS_TIMER_COUNTER        (CONFIG_SYS_TIMERBASE + 0x4)

... etc etc ...

arch/arm/

Things you should find under here:

  • DTS config
  • CPU initialization
  • pinmux controller
  • DRAM
  • clocks

Kconfig

config ARCH_ZYNQ
        bool "Xilinx Zynq based platform"
        select BOARD_EARLY_INIT_F if WDT
        select CLK
        select CLK_ZYNQ
        select CPU_V7A
        select DM
        select DM_ETH if NET
        select DM_MMC if MMC
        select DM_SERIAL
        select DM_SPI
        select DM_SPI_FLASH
        select DM_USB if USB
        select OF_CONTROL
        select SPI
        select SPL_BOARD_INIT if SPL
        select SPL_CLK if SPL
        select SPL_DM if SPL
        select SPL_OF_CONTROL if SPL
        select SPL_SEPARATE_BSS if SPL
        select SUPPORT_SPL
        imply ARCH_EARLY_INIT_R
        imply BOARD_LATE_INIT
        imply CMD_CLK
        imply CMD_DM
        imply CMD_SPL
        imply FAT_WRITE

Makefile

machine-$(CONFIG_ARCH_ZYNQ)             += zynq
machine-$(CONFIG_ARCH_ZYNQMP)           += zynqmp

mach-zynq/

clk.c
cpu.c
ddrc.c
include
Kconfig
lowlevel_init.S
Makefile
ps7_spl_init.c
slcr.c
spl.c
timer.c
u-boot.lds
u-boot-spl.lds

board/xilinx/zynq/

Kconfig

if ARCH_ZYNQ

config CMD_ZYNQ
        bool "Enable Zynq specific commands"
        default y
        help
          Enables Zynq specific commands.

config CMD_ZYNQ_AES
        bool "Enable zynq aes command for decryption of encrypted images"
        depends on CMD_ZYNQ
        depends on FPGA_ZYNQPL
        help
          Decrypts the encrypted image present in source address
          and places the decrypted image at destination address.

config CMD_ZYNQ_RSA
        bool "Enable zynq rsa command for loading secure images"
        default y
        depends on CMD_ZYNQ
        depends on CMD_ZYNQ_AES
        help
          Enabling this will support zynq secure image verification.
          The secure image is a xilinx specific BOOT.BIN with
          either authentication or encryption or both encryption
          and authentication feature enabled while generating
          BOOT.BIN using Xilinx bootgen tool.

endif

Makefile

obj-y   := board.o
obj-y   += ../common/board.o

ifneq ($(CONFIG_XILINX_PS_INIT_FILE),"")
PS_INIT_FILE := $(shell cd $(srctree); readlink -f $(CONFIG_XILINX_PS_INIT_FILE))
init-objs := ps_init_gpl.o
spl/board/xilinx/zynq/ps_init_gpl.o board/xilinx/zynq/ps_init_gpl.o: $(PS_INIT_FILE)
        $(CC) $(c_flags) -I $(srctree)/$(src) -c -o $@ $^
endif

ifeq ($(init-objs),)
hw-platform-y :=$(shell echo $(CONFIG_DEFAULT_DEVICE_TREE))
init-objs := $(if $(wildcard $(srctree)/$(src)/$(hw-platform-y)/ps7_init_gpl.c),\
        $(hw-platform-y)/ps7_init_gpl.o)
endif

ifeq ($(init-objs),)
ifneq ($(wildcard $(srctree)/$(src)/ps7_init_gpl.c),)
init-objs := ps7_init_gpl.o
$(if $(CONFIG_SPL_BUILD),\
$(warning Put custom ps7_init_gpl.c/h to board/xilinx/zynq/custom_hw_platform/))
endif
endif

ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_CMD_ZYNQ) += cmds.o
obj-$(CONFIG_CMD_ZYNQ_RSA) += bootimg.o
endif

obj-$(CONFIG_SPL_BUILD) += $(init-objs)

# Suppress "warning: function declaration isn't a prototype"
CFLAGS_REMOVE_ps7_init_gpl.o := -Wstrict-prototypes

# To include xil_io.h
CFLAGS_ps7_init_gpl.o := -I$(srctree)/$(src)

board.c

Probably need access to global data gd:

DECLARE_GLOBAL_DATA_PTR;
int board_init(void)
{
#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT)
        if (uclass_get_device_by_seq(UCLASS_WDT, 0, &watchdog_dev)) {
                debug("Watchdog: Not found by seq!\n");
                if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) {
                        puts("Watchdog: Not found!\n");
                        return 0;
                }
        }

        wdt_start(watchdog_dev, 0, 0);
        puts("Watchdog: Started\n");
# endif

        return 0;
}
int board_late_init(void)
{
...
}
#if !defined(CONFIG_SYS_SDRAM_BASE) && !defined(CONFIG_SYS_SDRAM_SIZE)
int dram_init_banksize(void)
{
        return fdtdec_setup_memory_banksize();
}

int dram_init(void)
{
        if (fdtdec_setup_mem_size_base() != 0)
                return -EINVAL;

        zynq_ddrc_init();

        return 0;
}
#else
int dram_init(void)
{
        gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE,
                                    CONFIG_SYS_SDRAM_SIZE);

        zynq_ddrc_init();

        return 0;
}
#endif
#if defined(CONFIG_WATCHDOG)
/* Called by macro WATCHDOG_RESET */
void watchdog_reset(void)
{
# if !defined(CONFIG_SPL_BUILD)
        static ulong next_reset;
        ulong now;

        if (!watchdog_dev)
                return;

        now = timer_get_us();

        /* Do not reset the watchdog too often */
        if (now > next_reset) {
                wdt_reset(watchdog_dev);
                next_reset = now + 1000;
        }
# endif
}

cmds.c

static cmd_tbl_t zynq_commands[] = {
#ifdef CONFIG_CMD_ZYNQ_RSA
        U_BOOT_CMD_MKENT(rsa, 3, 1, do_zynq_rsa, "", ""),
#endif
#ifdef CONFIG_CMD_ZYNQ_AES
        U_BOOT_CMD_MKENT(aes, 6, 1, zynq_decrypt_image, "", ""),
#endif
};

static int do_zynq(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
        cmd_tbl_t *zynq_cmd;
        int ret;

        if (!ARRAY_SIZE(zynq_commands)) {
                puts("No zynq specific command enabled\n");
                return CMD_RET_USAGE;
        }

        if (argc < 2)
                return CMD_RET_USAGE;
        zynq_cmd = find_cmd_tbl(argv[1], zynq_commands,
                                ARRAY_SIZE(zynq_commands));
        if (!zynq_cmd || argc != zynq_cmd->maxargs)
                return CMD_RET_USAGE;

        ret = zynq_cmd->cmd(zynq_cmd, flag, argc, argv);

        return cmd_process_error(zynq_cmd, ret);
}

#ifdef CONFIG_SYS_LONGHELP
static char zynq_help_text[] =
        ""
#ifdef CONFIG_CMD_ZYNQ_RSA
        "rsa <baseaddr>  - Verifies the authenticated and encrypted\n"
        "                  zynq images and loads them back to load\n"
        "                  addresses as specified in BOOT image(BOOT.BIN)\n"
#endif
#ifdef CONFIG_CMD_ZYNQ_AES
        "aes <srcaddr> <srclen> <dstaddr> <dstlen>\n"
        "                - Decrypts the encrypted image present in source\n"
        "                  address and places the decrypted image at\n"
        "                  destination address\n"
#endif
        ;
#endif

U_BOOT_CMD(zynq,        6,      0,      do_zynq,
           "Zynq specific commands", zynq_help_text
);

board/xilinx/common/

board.c

u-boot_porting_board.txt · Last modified: 2019/04/09 11:44 by rpjday