From patchwork Wed May 5 12:50:00 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Simek X-Patchwork-Id: 1474282 X-Patchwork-Delegate: monstr@monstr.eu Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=monstr-eu.20150623.gappssmtp.com header.i=@monstr-eu.20150623.gappssmtp.com header.a=rsa-sha256 header.s=20150623 header.b=h+fB3cSH; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FZxQH06Bzz9s1l for ; Wed, 5 May 2021 22:50:30 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id F180182CEB; Wed, 5 May 2021 14:50:13 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=xilinx.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=monstr-eu.20150623.gappssmtp.com header.i=@monstr-eu.20150623.gappssmtp.com header.b="h+fB3cSH"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 9524182CE3; Wed, 5 May 2021 14:50:12 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,SPF_HELO_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wr1-x435.google.com (mail-wr1-x435.google.com [IPv6:2a00:1450:4864:20::435]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id C105F82CC0 for ; Wed, 5 May 2021 14:50:07 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=xilinx.com Authentication-Results: phobos.denx.de; spf=none smtp.mailfrom=monstr@monstr.eu Received: by mail-wr1-x435.google.com with SMTP id a4so1712607wrr.2 for ; Wed, 05 May 2021 05:50:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=monstr-eu.20150623.gappssmtp.com; s=20150623; h=sender:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=zg0tSfsgaD6oXAbredJjXeiQTic8URjVmal7gxbu5qI=; b=h+fB3cSHghwaFq4diAdPK4irqQIy2eHqUMUweLi2t49wNbZ1ddap0LQuDt5yc2yZJK WcPaT10eeWwE0ihsPTwUf/lDoaK8OEKVINJENDPIpmzZDieeb16BKHMTPgbDGARjX/3y a0bZiqTxFDExubB+YZZtgC8nFT6bx1oMtQkf6DZ6XQKIfo6TxcGRzh90SI3mqsIlMSLM JAlJVXTaHTjUb44LAhZSBzEgMsIBqMJa3LSxm+EJXTaOkjiimwdchmNSzep9F0rc+04u Hkix9kc+sB3DY/rrNmg1bomxEptmE/p+qjZKfKQl8bamfDPqLNarnnTVJDuv9yTEIu0S tulA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :mime-version:content-transfer-encoding; bh=zg0tSfsgaD6oXAbredJjXeiQTic8URjVmal7gxbu5qI=; b=ENvgmRCjp0dXdHxG7XPAsw/5KvnfRp1USSx8HXVFr3FFdE7krt3bhvyij/mJ5eKhkt xFAvHIfpW7QnlP5Td3VdgHPwPFpUMKc0T5wKoW/UWzI9f60tzrcup2kiXJGWcjF12G5C UDkWbU/Ye50e4pB78VzOIxmG2adqh/ZsPQ1tFR2O+V4Z2hj/89vFgi3inDq8KjEHleyu EByMEzgcVupqggG3JyUnmeXD+6IBxj3l9KR1Zqqb4+tf4nYP9gACz8Oy/5GlAdu4IpKz E9u6OElo7Og0xJnWCFUHGC2CmjOzVYICDrl2LOcFqoXD6Tb5Rc8Tum0pRS9GeEnOi4hj 14vA== X-Gm-Message-State: AOAM5328R6ZwFstHWK5q7bFdDgUkWoogopKAGIpR9nPBcgDVe0Ob1BUQ aJn8aOcu/lRVctrCaeclt50I3WNu5KBw83m6 X-Google-Smtp-Source: ABdhPJztQzwsRVpCQ1pBd40Sy8c7I1HHEdRPeLpJimsw2RNDEQt6kKSXshNz/z2sUgJYf1mM9W41pQ== X-Received: by 2002:a05:6000:2ae:: with SMTP id l14mr36800336wry.155.1620219006926; Wed, 05 May 2021 05:50:06 -0700 (PDT) Received: from localhost ([2a02:768:2307:40d6:f666:9af6:3fed:e53b]) by smtp.gmail.com with ESMTPSA id a9sm6009275wmj.1.2021.05.05.05.50.06 (version=TLS1_2 cipher=ECDHE-ECDSA-CHACHA20-POLY1305 bits=256/256); Wed, 05 May 2021 05:50:06 -0700 (PDT) From: Michal Simek To: u-boot@lists.denx.de, git@xilinx.com Cc: Ibai Erkiaga , Luca Ceresoli , Simon Glass , Siva Durga Prasad Paladugu , T Karthik Reddy Subject: [RFC PATCH] arm64: zynqmp: Add support for placing TFA from beginning of OCM Date: Wed, 5 May 2021 14:50:00 +0200 Message-Id: <3c0f0fd2b41c2f995360b55c29e3eb397a32f22d.1620218998.git.michal.simek@xilinx.com> X-Mailer: git-send-email 2.31.1 MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.4 at phobos.denx.de X-Virus-Status: Clean Xilinx TFA is normally placed to OCM at 0xfffea000 with a max size of 88kB. By adding new and new features to TFA this split is reaching its limit that there would be a need to change structures a little bit. The idea is to resort SPL (potentially also Xilinx first stage bootloader FSBL) that the beginning of the binary contains only the initcode which is called only once before loading other images. The way how this can be done is to use custom linker script and mark early functions with __splinit to place them at the beginning of OCM. Also make sure that space is bigger than current 88kB. The patch is doing a barrier at 96kB just to prove that it is possible to do so. Code which is marked with __splinit is only coming from Xilinx Zynqmp code but I would expect there is also generic code which can be marked like that. Signed-off-by: Michal Simek --- Hi, I am sending this series to start discussion how this can be done in a better/generic way. Right now I have marked only the part of zynqmp code which is just 0x3d54 = ~15kB of code. And then there is 81kB empty space followed by generic code. Linux is marking this code with __init and this is pretty much a similar idea to have it in the same location and being able to reuse that location for different purposes I expect all functions in include/init.h are exactly like that and there will be likely others too. Thanks, Michal --- arch/arm/mach-zynqmp/Kconfig | 3 + arch/arm/mach-zynqmp/clk.c | 4 +- arch/arm/mach-zynqmp/cpu.c | 6 +- arch/arm/mach-zynqmp/handoff.c | 4 +- .../mach-zynqmp/include/mach/psu_init_gpl.h | 21 ++--- arch/arm/mach-zynqmp/include/mach/sys_proto.h | 6 ++ arch/arm/mach-zynqmp/spl.c | 12 +-- arch/arm/mach-zynqmp/u-boot-spl.lds | 88 +++++++++++++++++++ board/xilinx/zynqmp/pm_cfg_obj.h | 4 +- board/xilinx/zynqmp/zynqmp.c | 22 ++--- drivers/firmware/firmware-zynqmp.c | 4 +- 11 files changed, 136 insertions(+), 38 deletions(-) create mode 100644 arch/arm/mach-zynqmp/u-boot-spl.lds diff --git a/arch/arm/mach-zynqmp/Kconfig b/arch/arm/mach-zynqmp/Kconfig index f1301f6661a1..8578c6910701 100644 --- a/arch/arm/mach-zynqmp/Kconfig +++ b/arch/arm/mach-zynqmp/Kconfig @@ -1,5 +1,8 @@ if ARCH_ZYNQMP +config SPL_LDSCRIPT + default "arch/arm/mach-zynqmp/u-boot-spl.lds" + config SPL_FS_FAT default y diff --git a/arch/arm/mach-zynqmp/clk.c b/arch/arm/mach-zynqmp/clk.c index 1e6e726e8792..ad2636169a1a 100644 --- a/arch/arm/mach-zynqmp/clk.c +++ b/arch/arm/mach-zynqmp/clk.c @@ -14,7 +14,7 @@ DECLARE_GLOBAL_DATA_PTR; -unsigned long zynqmp_get_system_timer_freq(void) +unsigned long __splinit zynqmp_get_system_timer_freq(void) { u32 ver = zynqmp_get_silicon_version(); @@ -35,7 +35,7 @@ unsigned long zynqmp_get_system_timer_freq(void) * clock framework. The framework must not be used before this function had been * called. */ -int set_cpu_clk_info(void) +int __splinit set_cpu_clk_info(void) { gd->cpu_clk = get_tbclk(); diff --git a/arch/arm/mach-zynqmp/cpu.c b/arch/arm/mach-zynqmp/cpu.c index 29743cae5aab..fa2d6e730cba 100644 --- a/arch/arm/mach-zynqmp/cpu.c +++ b/arch/arm/mach-zynqmp/cpu.c @@ -105,7 +105,7 @@ void mem_map_fill(void) struct mm_region *mem_map = zynqmp_mem_map; -u64 get_page_table_size(void) +u64 __splinit get_page_table_size(void) { return 0x14000; } @@ -130,7 +130,7 @@ int arm_reserve_mmu(void) } #endif -static unsigned int zynqmp_get_silicon_version_secure(void) +static unsigned int __splinit zynqmp_get_silicon_version_secure(void) { u32 ver; @@ -141,7 +141,7 @@ static unsigned int zynqmp_get_silicon_version_secure(void) return ver; } -unsigned int zynqmp_get_silicon_version(void) +unsigned int __splinit zynqmp_get_silicon_version(void) { if (current_el() == 3) return zynqmp_get_silicon_version_secure(); diff --git a/arch/arm/mach-zynqmp/handoff.c b/arch/arm/mach-zynqmp/handoff.c index 7d7ab9da6ec2..4c5a81fc4cad 100644 --- a/arch/arm/mach-zynqmp/handoff.c +++ b/arch/arm/mach-zynqmp/handoff.c @@ -72,7 +72,7 @@ struct bl31_params *bl2_plat_get_bl31_params(uintptr_t bl32_entry, { struct xfsbl_atf_handoff_params *atfhandoffparams; - atfhandoffparams = (void *)CONFIG_SPL_TEXT_BASE; + atfhandoffparams = (void *)0xfffe0000; atfhandoffparams->magic[0] = 'X'; atfhandoffparams->magic[1] = 'L'; atfhandoffparams->magic[2] = 'N'; @@ -86,7 +86,7 @@ struct bl31_params *bl2_plat_get_bl31_params(uintptr_t bl32_entry, atfhandoffparams->num_entries++; } - writel(CONFIG_SPL_TEXT_BASE, &pmu_base->gen_storage6); + writel(0xfffe0000, &pmu_base->gen_storage6); return NULL; } diff --git a/arch/arm/mach-zynqmp/include/mach/psu_init_gpl.h b/arch/arm/mach-zynqmp/include/mach/psu_init_gpl.h index e37acda2f89e..9cccd2139700 100644 --- a/arch/arm/mach-zynqmp/include/mach/psu_init_gpl.h +++ b/arch/arm/mach-zynqmp/include/mach/psu_init_gpl.h @@ -5,22 +5,23 @@ #include #include +#include -int mask_pollonvalue(unsigned long add, u32 mask, u32 value); +int __splinit mask_pollonvalue(unsigned long add, u32 mask, u32 value); -int mask_poll(u32 add, u32 mask); +int __splinit mask_poll(u32 add, u32 mask); -u32 mask_read(u32 add, u32 mask); +u32 __splinit mask_read(u32 add, u32 mask); -void mask_delay(u32 delay); +void __splinit mask_delay(u32 delay); -void psu_mask_write(unsigned long offset, unsigned long mask, - unsigned long val); +void __splinit psu_mask_write(unsigned long offset, unsigned long mask, + unsigned long val); -void prog_reg(unsigned long addr, unsigned long mask, - unsigned long shift, unsigned long value); +void __splinit prog_reg(unsigned long addr, unsigned long mask, + unsigned long shift, unsigned long value); -int psu_init(void); -unsigned long psu_post_config_data(void); +int __splinit psu_init(void); +unsigned long __splinit psu_post_config_data(void); #endif /* _PSU_INIT_GPL_H_ */ diff --git a/arch/arm/mach-zynqmp/include/mach/sys_proto.h b/arch/arm/mach-zynqmp/include/mach/sys_proto.h index 1c12eac715e5..c1ab685c3ce4 100644 --- a/arch/arm/mach-zynqmp/include/mach/sys_proto.h +++ b/arch/arm/mach-zynqmp/include/mach/sys_proto.h @@ -7,6 +7,12 @@ #ifndef _ASM_ARCH_SYS_PROTO_H #define _ASM_ARCH_SYS_PROTO_H +#if CONFIG_SPL_BUILD +#define __splinit __section(.splinit) +#else +#define __splinit +#endif + #define ZYNQMP_CSU_SILICON_VER_MASK 0xF #define KEY_PTR_LEN 32 #define IV_SIZE 12 diff --git a/arch/arm/mach-zynqmp/spl.c b/arch/arm/mach-zynqmp/spl.c index 88386b23e5da..f57835143041 100644 --- a/arch/arm/mach-zynqmp/spl.c +++ b/arch/arm/mach-zynqmp/spl.c @@ -18,13 +18,13 @@ #include #include -void board_init_f(ulong dummy) +void __splinit board_init_f(ulong dummy) { board_early_init_f(); board_early_init_r(); } -static void ps_mode_reset(ulong mode) +static void __splinit ps_mode_reset(ulong mode) { writel(mode << ZYNQMP_CRL_APB_BOOT_PIN_CTRL_OUT_EN_SHIFT, &crlapb_base->boot_pin_ctrl); @@ -43,7 +43,7 @@ static void ps_mode_reset(ulong mode) #endif #ifdef CONFIG_SPL_BOARD_INIT -void spl_board_init(void) +void __splinit spl_board_init(void) { preloader_console_init(); ps_mode_reset(MODE_RESET); @@ -52,7 +52,7 @@ void spl_board_init(void) } #endif -void board_boot_order(u32 *spl_boot_list) +void __splinit board_boot_order(u32 *spl_boot_list) { spl_boot_list[0] = spl_boot_device(); @@ -64,7 +64,7 @@ void board_boot_order(u32 *spl_boot_list) spl_boot_list[2] = BOOT_DEVICE_RAM; } -u32 spl_boot_device(void) +u32 __splinit spl_boot_device(void) { u32 reg = 0; u8 bootmode; @@ -114,7 +114,7 @@ u32 spl_boot_device(void) } #ifdef CONFIG_SPL_OS_BOOT -int spl_start_uboot(void) +int __splinit spl_start_uboot(void) { return 0; } diff --git a/arch/arm/mach-zynqmp/u-boot-spl.lds b/arch/arm/mach-zynqmp/u-boot-spl.lds new file mode 100644 index 000000000000..5b71d5a35142 --- /dev/null +++ b/arch/arm/mach-zynqmp/u-boot-spl.lds @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2013 + * David Feng + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * (C) Copyright 2010 + * Texas Instruments, + * Aneesh V + */ + +MEMORY { .sram : ORIGIN = IMAGE_TEXT_BASE, + LENGTH = IMAGE_MAX_SIZE } +MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, + LENGTH = CONFIG_SPL_BSS_MAX_SIZE } + +OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64") +OUTPUT_ARCH(aarch64) +ENTRY(_start) +SECTIONS +{ + .text : { + . = ALIGN(8); + *(.__image_copy_start) + CPUDIR/start.o (.text*) + *(.splinit*) + . = ALIGN(0x18000); + *(.text*) + } >.sram + + .rodata : { + . = ALIGN(8); + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) + } >.sram + + .data : { + . = ALIGN(8); + *(.data*) + } >.sram + +#ifdef CONFIG_SPL_RECOVER_DATA_SECTION + .data_save : { + *(.__data_save_start) + . = SIZEOF(.data); + *(.__data_save_end) + } >.sram +#endif + + .u_boot_list : { + . = ALIGN(8); + KEEP(*(SORT(.u_boot_list*))); + } >.sram + + .image_copy_end : { + . = ALIGN(8); + *(.__image_copy_end) + } >.sram + + .end : { + . = ALIGN(8); + *(.__end) + } >.sram + + _image_binary_end = .; + + .bss_start (NOLOAD) : { + . = ALIGN(8); + KEEP(*(.__bss_start)); + } >.sdram + + .bss (NOLOAD) : { + *(.bss*) + . = ALIGN(8); + } >.sdram + + .bss_end (NOLOAD) : { + KEEP(*(.__bss_end)); + } >.sdram + + /DISCARD/ : { *(.dynsym) } + /DISCARD/ : { *(.dynstr*) } + /DISCARD/ : { *(.dynamic*) } + /DISCARD/ : { *(.plt*) } + /DISCARD/ : { *(.interp*) } + /DISCARD/ : { *(.gnu*) } +} diff --git a/board/xilinx/zynqmp/pm_cfg_obj.h b/board/xilinx/zynqmp/pm_cfg_obj.h index 86e785490ced..232dcd0ce116 100644 --- a/board/xilinx/zynqmp/pm_cfg_obj.h +++ b/board/xilinx/zynqmp/pm_cfg_obj.h @@ -5,5 +5,5 @@ * Declaration of PMU config object binary blob linked in at build time. */ -extern const u32 zynqmp_pm_cfg_obj[]; -extern const int zynqmp_pm_cfg_obj_size; +extern const u32 __splinit zynqmp_pm_cfg_obj[]; +extern const int __splinit zynqmp_pm_cfg_obj_size; diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c index d05f0b2e1202..e56cfa2cc520 100644 --- a/board/xilinx/zynqmp/zynqmp.c +++ b/board/xilinx/zynqmp/zynqmp.c @@ -185,7 +185,7 @@ static const struct { }, }; -static char *zynqmp_get_silicon_idcode_name(void) +static char __splinit *zynqmp_get_silicon_idcode_name(void) { u32 i; u32 idcode, idcode2; @@ -278,7 +278,7 @@ static char *zynqmp_get_silicon_idcode_name(void) } #endif -int board_early_init_f(void) +int __splinit board_early_init_f(void) { #if defined(CONFIG_ZYNQMP_PSU_INIT_ENABLED) int ret; @@ -300,7 +300,7 @@ int board_early_init_f(void) return 0; } -static int multi_boot(void) +static int __splinit multi_boot(void) { u32 multiboot; @@ -314,7 +314,7 @@ static int multi_boot(void) #define PS_SYSMON_ANALOG_BUS_VAL 0x3210 #define PS_SYSMON_ANALOG_BUS_REG 0xFFA50914 -int board_init(void) +int __splinit board_init(void) { #if defined(CONFIG_ZYNQMP_FIRMWARE) struct udevice *dev; @@ -353,7 +353,7 @@ int board_init(void) return 0; } -int board_early_init_r(void) +int __splinit board_early_init_r(void) { u32 val; @@ -396,7 +396,7 @@ unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc, } #if !defined(CONFIG_SYS_SDRAM_BASE) && !defined(CONFIG_SYS_SDRAM_SIZE) -int dram_init_banksize(void) +int __splinit dram_init_banksize(void) { int ret; @@ -409,7 +409,7 @@ int dram_init_banksize(void) return 0; } -int dram_init(void) +int __splinit dram_init(void) { if (fdtdec_setup_mem_size_base() != 0) return -EINVAL; @@ -417,7 +417,7 @@ int dram_init(void) return 0; } #else -int dram_init_banksize(void) +int __splinit dram_init_banksize(void) { gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; gd->bd->bi_dram[0].size = get_effective_memsize(); @@ -427,7 +427,7 @@ int dram_init_banksize(void) return 0; } -int dram_init(void) +int __splinit dram_init(void) { gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE, CONFIG_SYS_SDRAM_SIZE); @@ -440,7 +440,7 @@ void reset_cpu(void) { } -static u8 __maybe_unused zynqmp_get_bootmode(void) +static u8 __maybe_unused __splinit zynqmp_get_bootmode(void) { u8 bootmode; u32 reg = 0; @@ -473,7 +473,7 @@ static const struct { {} }; -static int reset_reason(void) +static int __splinit reset_reason(void) { u32 reg; int i, ret; diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c index d4dc856bafa4..08bcdf5bb024 100644 --- a/drivers/firmware/firmware-zynqmp.c +++ b/drivers/firmware/firmware-zynqmp.c @@ -55,7 +55,7 @@ static int ipi_req(const u32 *req, size_t req_len, u32 *res, size_t res_maxlen) return ret; } -unsigned int zynqmp_firmware_version(void) +unsigned int __splinit zynqmp_firmware_version(void) { int ret; u32 ret_payload[PAYLOAD_ARG_CNT]; @@ -88,7 +88,7 @@ unsigned int zynqmp_firmware_version(void) * @cfg_obj: Pointer to the configuration object * @size: Size of @cfg_obj in bytes */ -void zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size) +void __splinit zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size) { int err; u32 ret_payload[PAYLOAD_ARG_CNT];