diff options
author | Tom Rini <trini@konsulko.com> | 2021-01-15 07:23:50 -0500 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2021-01-15 07:55:11 -0500 |
commit | 83e13c3469c710af03bf43f53aede0f9b7ba2dd0 (patch) | |
tree | 411d6bc9f7f2dbe605fcc979f680b286fabba695 | |
parent | 35772ff4f63a302e0b873096372c70292fb0af79 (diff) | |
parent | 40551cf99c237f93d9e0e07b6dd8f31b3868a0f0 (diff) | |
download | u-boot-83e13c3469c710af03bf43f53aede0f9b7ba2dd0.tar.gz |
Merge branch '2021.04-rc' of https://github.com/lftan/u-bootWIP/15Jan2021
- Add ATF flow for SoC64 devices
- Update socfpgaimage to support print header and update padding flow
32 files changed, 1449 insertions, 37 deletions
@@ -1583,7 +1583,10 @@ u-boot.spr: spl/u-boot-spl.img u-boot.img FORCE ifneq ($(CONFIG_ARCH_SOCFPGA),) quiet_cmd_gensplx4 = GENSPLX4 $@ -cmd_gensplx4 = cat spl/u-boot-spl.sfp spl/u-boot-spl.sfp \ +cmd_gensplx4 = $(OBJCOPY) -I binary -O binary --gap-fill=0x0 \ + --pad-to=$(CONFIG_SPL_PAD_TO) \ + spl/u-boot-spl.sfp spl/u-boot-spl.sfp && \ + cat spl/u-boot-spl.sfp spl/u-boot-spl.sfp \ spl/u-boot-spl.sfp spl/u-boot-spl.sfp > $@ || { rm -f $@; false; } spl/u-boot-splx4.sfp: spl/u-boot-spl.sfp FORCE $(call if_changed,gensplx4) diff --git a/arch/arm/dts/socfpga_agilex-u-boot.dtsi b/arch/arm/dts/socfpga_agilex-u-boot.dtsi index f0528a9ad9..08f7cf7f7a 100644 --- a/arch/arm/dts/socfpga_agilex-u-boot.dtsi +++ b/arch/arm/dts/socfpga_agilex-u-boot.dtsi @@ -2,9 +2,11 @@ /* * U-Boot additions * - * Copyright (C) 2019 Intel Corporation <www.intel.com> + * Copyright (C) 2019-2020 Intel Corporation <www.intel.com> */ +#include "socfpga_soc64_fit-u-boot.dtsi" + /{ memory { #address-cells = <2>; diff --git a/arch/arm/dts/socfpga_soc64_fit-u-boot.dtsi b/arch/arm/dts/socfpga_soc64_fit-u-boot.dtsi new file mode 100644 index 0000000000..cf365590a8 --- /dev/null +++ b/arch/arm/dts/socfpga_soc64_fit-u-boot.dtsi @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * U-Boot additions + * + * Copyright (C) 2020 Intel Corporation <www.intel.com> + */ + +#if defined(CONFIG_FIT) + +/ { + binman: binman { + multiple-images; + }; +}; + +&binman { + u-boot { + filename = "u-boot.itb"; + fit { + fit,external-offset = <CONFIG_FIT_EXTERNAL_OFFSET>; + description = "FIT with firmware and bootloader"; + #address-cells = <1>; + + images { + uboot { + description = "U-Boot SoC64"; + type = "standalone"; + os = "U-Boot"; + arch = "arm64"; + compression = "none"; + load = <0x00200000>; + + uboot_blob: blob-ext { + filename = "u-boot-nodtb.bin"; + }; + }; + + atf { + description = "ARM Trusted Firmware"; + type = "firmware"; + os = "arm-trusted-firmware"; + arch = "arm64"; + compression = "none"; + load = <0x00001000>; + entry = <0x00001000>; + + atf_blob: blob-ext { + filename = "bl31.bin"; + }; + }; + + fdt { + description = "U-Boot SoC64 flat device-tree"; + type = "flat_dt"; + compression = "none"; + + uboot_fdt_blob: blob-ext { + filename = "u-boot.dtb"; + }; + }; + }; + + configurations { + default = "conf"; + conf { + description = "Intel SoC64 FPGA"; + firmware = "atf"; + loadables = "uboot"; + fdt = "fdt"; + }; + }; + }; + }; + + kernel { + filename = "kernel.itb"; + fit { + description = "FIT with Linux kernel image and FDT blob"; + #address-cells = <1>; + + images { + kernel { + description = "Linux Kernel"; + type = "kernel"; + arch = "arm64"; + os = "linux"; + compression = "none"; + load = <0x4080000>; + entry = <0x4080000>; + + kernel_blob: blob-ext { + filename = "Image"; + }; + }; + + fdt { + description = "Linux DTB"; + type = "flat_dt"; + arch = "arm64"; + compression = "none"; + + kernel_fdt_blob: blob-ext { + filename = "linux.dtb"; + }; + }; + }; + + configurations { + default = "conf"; + conf { + description = "Intel SoC64 FPGA"; + kernel = "kernel"; + fdt = "fdt"; + }; + }; + }; + }; +}; + +#endif diff --git a/arch/arm/dts/socfpga_stratix10-u-boot.dtsi b/arch/arm/dts/socfpga_stratix10-u-boot.dtsi new file mode 100644 index 0000000000..3e3a378046 --- /dev/null +++ b/arch/arm/dts/socfpga_stratix10-u-boot.dtsi @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * U-Boot additions + * + * Copyright (C) 2020 Intel Corporation <www.intel.com> + */ + +#include "socfpga_soc64_fit-u-boot.dtsi" diff --git a/arch/arm/dts/socfpga_stratix10_socdk-u-boot.dtsi b/arch/arm/dts/socfpga_stratix10_socdk-u-boot.dtsi index 2669abb383..61df425f14 100755 --- a/arch/arm/dts/socfpga_stratix10_socdk-u-boot.dtsi +++ b/arch/arm/dts/socfpga_stratix10_socdk-u-boot.dtsi @@ -2,9 +2,11 @@ /* * U-Boot additions * - * Copyright (C) 2019 Intel Corporation <www.intel.com> + * Copyright (C) 2019-2020 Intel Corporation <www.intel.com> */ +#include "socfpga_stratix10-u-boot.dtsi" + /{ aliases { spi0 = &qspi; diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig index 26f2cf8e47..4d4ff16337 100644 --- a/arch/arm/mach-socfpga/Kconfig +++ b/arch/arm/mach-socfpga/Kconfig @@ -33,7 +33,7 @@ config TARGET_SOCFPGA_AGILEX bool select ARMV8_MULTIENTRY select ARMV8_SET_SMPEN - select ARMV8_SPIN_TABLE + select BINMAN if SPL_ATF select CLK select FPGA_INTEL_SDM_MAILBOX select NCORE_CACHE @@ -79,7 +79,7 @@ config TARGET_SOCFPGA_STRATIX10 bool select ARMV8_MULTIENTRY select ARMV8_SET_SMPEN - select ARMV8_SPIN_TABLE + select BINMAN if SPL_ATF select FPGA_INTEL_SDM_MAILBOX choice diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach-socfpga/Makefile index 418f543b20..82b681d870 100644 --- a/arch/arm/mach-socfpga/Makefile +++ b/arch/arm/mach-socfpga/Makefile @@ -29,6 +29,7 @@ endif ifdef CONFIG_TARGET_SOCFPGA_STRATIX10 obj-y += clock_manager_s10.o +obj-y += lowlevel_init_soc64.o obj-y += mailbox_s10.o obj-y += misc_s10.o obj-y += mmu-arm64_s10.o @@ -41,6 +42,7 @@ endif ifdef CONFIG_TARGET_SOCFPGA_AGILEX obj-y += clock_manager_agilex.o +obj-y += lowlevel_init_soc64.o obj-y += mailbox_s10.o obj-y += misc_s10.o obj-y += mmu-arm64_s10.o @@ -70,6 +72,9 @@ ifdef CONFIG_TARGET_SOCFPGA_AGILEX obj-y += firewall.o obj-y += spl_agilex.o endif +else +obj-$(CONFIG_SPL_ATF) += secure_reg_helper.o +obj-$(CONFIG_SPL_ATF) += smc_api.o endif ifdef CONFIG_TARGET_SOCFPGA_GEN5 diff --git a/arch/arm/mach-socfpga/board.c b/arch/arm/mach-socfpga/board.c index 340abf9305..7993c27646 100644 --- a/arch/arm/mach-socfpga/board.c +++ b/arch/arm/mach-socfpga/board.c @@ -13,7 +13,7 @@ #include <asm/arch/clock_manager.h> #include <asm/arch/misc.h> #include <asm/io.h> - +#include <log.h> #include <usb.h> #include <usb/dwc2_udc.h> @@ -87,3 +87,13 @@ int g_dnl_board_usb_cable_connected(void) return 1; } #endif + +#ifdef CONFIG_SPL_BUILD +__weak int board_fit_config_name_match(const char *name) +{ + /* Just empty function now - can't decide what to choose */ + debug("%s: %s\n", __func__, name); + + return 0; +} +#endif diff --git a/arch/arm/mach-socfpga/include/mach/secure_reg_helper.h b/arch/arm/mach-socfpga/include/mach/secure_reg_helper.h new file mode 100644 index 0000000000..d5a11122c7 --- /dev/null +++ b/arch/arm/mach-socfpga/include/mach/secure_reg_helper.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2020 Intel Corporation <www.intel.com> + * + */ + +#ifndef _SECURE_REG_HELPER_H_ +#define _SECURE_REG_HELPER_H_ + +#define SOCFPGA_SECURE_REG_SYSMGR_SOC64_SDMMC 1 +#define SOCFPGA_SECURE_REG_SYSMGR_SOC64_EMAC0 2 +#define SOCFPGA_SECURE_REG_SYSMGR_SOC64_EMAC1 3 +#define SOCFPGA_SECURE_REG_SYSMGR_SOC64_EMAC2 4 + +int socfpga_secure_reg_read32(u32 id, u32 *val); +int socfpga_secure_reg_write32(u32 id, u32 val); +int socfpga_secure_reg_update32(u32 id, u32 mask, u32 val); + +#endif /* _SECURE_REG_HELPER_H_ */ diff --git a/arch/arm/mach-socfpga/include/mach/smc_api.h b/arch/arm/mach-socfpga/include/mach/smc_api.h new file mode 100644 index 0000000000..bbefdd8dd9 --- /dev/null +++ b/arch/arm/mach-socfpga/include/mach/smc_api.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2020 Intel Corporation + */ + +#ifndef _SMC_API_H_ +#define _SMC_API_H_ + +int invoke_smc(u32 func_id, u64 *args, int arg_len, u64 *ret_arg, int ret_len); +int smc_send_mailbox(u32 cmd, u32 len, u32 *arg, u8 urgent, u32 *resp_buf_len, + u32 *resp_buf); + +#endif /* _SMC_API_H_ */ diff --git a/arch/arm/mach-socfpga/lowlevel_init_soc64.S b/arch/arm/mach-socfpga/lowlevel_init_soc64.S new file mode 100644 index 0000000000..612ea8a037 --- /dev/null +++ b/arch/arm/mach-socfpga/lowlevel_init_soc64.S @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2020 Intel Corporation. All rights reserved + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <asm-offsets.h> +#include <config.h> +#include <linux/linkage.h> +#include <asm/macro.h> + +ENTRY(lowlevel_init) + mov x29, lr /* Save LR */ + +#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3) +#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_ATF) +wait_for_atf: + ldr x4, =CPU_RELEASE_ADDR + ldr x5, [x4] + cbz x5, slave_wait_atf + br x5 +slave_wait_atf: + branch_if_slave x0, wait_for_atf +#else + branch_if_slave x0, 1f +#endif + ldr x0, =GICD_BASE + bl gic_init_secure +1: +#if defined(CONFIG_GICV3) + ldr x0, =GICR_BASE + bl gic_init_secure_percpu +#elif defined(CONFIG_GICV2) + ldr x0, =GICD_BASE + ldr x1, =GICC_BASE + bl gic_init_secure_percpu +#endif +#endif + +#ifdef CONFIG_ARMV8_MULTIENTRY + branch_if_master x0, x1, 2f + + /* + * Slave should wait for master clearing spin table. + * This sync prevent slaves observing incorrect + * value of spin table and jumping to wrong place. + */ +#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3) +#ifdef CONFIG_GICV2 + ldr x0, =GICC_BASE +#endif + bl gic_wait_for_interrupt +#endif + + /* + * All slaves will enter EL2 and optionally EL1. + */ + adr x4, lowlevel_in_el2 + ldr x5, =ES_TO_AARCH64 + bl armv8_switch_to_el2 + +lowlevel_in_el2: +#ifdef CONFIG_ARMV8_SWITCH_TO_EL1 + adr x4, lowlevel_in_el1 + ldr x5, =ES_TO_AARCH64 + bl armv8_switch_to_el1 + +lowlevel_in_el1: +#endif + +#endif /* CONFIG_ARMV8_MULTIENTRY */ + +2: + mov lr, x29 /* Restore LR */ + ret +ENDPROC(lowlevel_init) diff --git a/arch/arm/mach-socfpga/mailbox_s10.c b/arch/arm/mach-socfpga/mailbox_s10.c index 18d44924e6..429444f069 100644 --- a/arch/arm/mach-socfpga/mailbox_s10.c +++ b/arch/arm/mach-socfpga/mailbox_s10.c @@ -11,6 +11,7 @@ #include <asm/arch/mailbox_s10.h> #include <asm/arch/system_manager.h> #include <asm/secure.h> +#include <asm/system.h> DECLARE_GLOBAL_DATA_PTR; @@ -398,6 +399,9 @@ error: int mbox_reset_cold(void) { +#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_ATF) + psci_system_reset(); +#else int ret; ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_REBOOT_HPS, MBOX_CMD_DIRECT, @@ -406,6 +410,7 @@ int mbox_reset_cold(void) /* mailbox sent failure, wait for watchdog to kick in */ hang(); } +#endif return 0; } diff --git a/arch/arm/mach-socfpga/reset_manager_s10.c b/arch/arm/mach-socfpga/reset_manager_s10.c index 3746e6a60c..af8f2c0873 100644 --- a/arch/arm/mach-socfpga/reset_manager_s10.c +++ b/arch/arm/mach-socfpga/reset_manager_s10.c @@ -5,11 +5,14 @@ */ #include <common.h> +#include <hang.h> #include <asm/io.h> #include <asm/arch/reset_manager.h> +#include <asm/arch/smc_api.h> #include <asm/arch/system_manager.h> #include <dt-bindings/reset/altr,rst-mgr-s10.h> #include <linux/iopoll.h> +#include <linux/intel-smc.h> DECLARE_GLOBAL_DATA_PTR; @@ -55,6 +58,15 @@ void socfpga_per_reset_all(void) void socfpga_bridges_reset(int enable) { +#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_ATF) + u64 arg = enable; + + int ret = invoke_smc(INTEL_SIP_SMC_HPS_SET_BRIDGES, &arg, 1, NULL, 0); + if (ret) { + printf("SMC call failed with error %d in %s.\n", ret, __func__); + return; + } +#else u32 reg; if (enable) { @@ -101,6 +113,7 @@ void socfpga_bridges_reset(int enable) /* Disable NOC timeout */ writel(0, socfpga_get_sysmgr_addr() + SYSMGR_SOC64_NOC_TIMEOUT); } +#endif } /* diff --git a/arch/arm/mach-socfpga/secure_reg_helper.c b/arch/arm/mach-socfpga/secure_reg_helper.c new file mode 100644 index 0000000000..0d4f45f33d --- /dev/null +++ b/arch/arm/mach-socfpga/secure_reg_helper.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Intel Corporation <www.intel.com> + * + */ + +#include <common.h> +#include <hang.h> +#include <asm/io.h> +#include <asm/system.h> +#include <asm/arch/misc.h> +#include <asm/arch/secure_reg_helper.h> +#include <asm/arch/smc_api.h> +#include <asm/arch/system_manager.h> +#include <linux/errno.h> +#include <linux/intel-smc.h> + +int socfpga_secure_convert_reg_id_to_addr(u32 id, phys_addr_t *reg_addr) +{ + switch (id) { + case SOCFPGA_SECURE_REG_SYSMGR_SOC64_SDMMC: + *reg_addr = socfpga_get_sysmgr_addr() + SYSMGR_SOC64_SDMMC; + break; + case SOCFPGA_SECURE_REG_SYSMGR_SOC64_EMAC0: + *reg_addr = socfpga_get_sysmgr_addr() + SYSMGR_SOC64_EMAC0; + break; + case SOCFPGA_SECURE_REG_SYSMGR_SOC64_EMAC1: + *reg_addr = socfpga_get_sysmgr_addr() + SYSMGR_SOC64_EMAC1; + break; + case SOCFPGA_SECURE_REG_SYSMGR_SOC64_EMAC2: + *reg_addr = socfpga_get_sysmgr_addr() + SYSMGR_SOC64_EMAC2; + break; + default: + return -EADDRNOTAVAIL; + } + return 0; +} + +int socfpga_secure_reg_read32(u32 id, u32 *val) +{ + int ret; + u64 ret_arg; + u64 args[1]; + + phys_addr_t reg_addr; + ret = socfpga_secure_convert_reg_id_to_addr(id, ®_addr); + if (ret) + return ret; + + args[0] = (u64)reg_addr; + ret = invoke_smc(INTEL_SIP_SMC_REG_READ, args, 1, &ret_arg, 1); + if (ret) + return ret; + + *val = (u32)ret_arg; + + return 0; +} + +int socfpga_secure_reg_write32(u32 id, u32 val) +{ + int ret; + u64 args[2]; + + phys_addr_t reg_addr; + ret = socfpga_secure_convert_reg_id_to_addr(id, ®_addr); + if (ret) + return ret; + + args[0] = (u64)reg_addr; + args[1] = val; + return invoke_smc(INTEL_SIP_SMC_REG_WRITE, args, 2, NULL, 0); +} + +int socfpga_secure_reg_update32(u32 id, u32 mask, u32 val) +{ + int ret; + u64 args[3]; + + phys_addr_t reg_addr; + ret = socfpga_secure_convert_reg_id_to_addr(id, ®_addr); + if (ret) + return ret; + + args[0] = (u64)reg_addr; + args[1] = mask; + args[2] = val; + return invoke_smc(INTEL_SIP_SMC_REG_UPDATE, args, 3, NULL, 0); +} diff --git a/arch/arm/mach-socfpga/smc_api.c b/arch/arm/mach-socfpga/smc_api.c new file mode 100644 index 0000000000..085daba162 --- /dev/null +++ b/arch/arm/mach-socfpga/smc_api.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Intel Corporation <www.intel.com> + * + */ + +#include <common.h> +#include <asm/ptrace.h> +#include <asm/system.h> +#include <linux/intel-smc.h> + +int invoke_smc(u32 func_id, u64 *args, int arg_len, u64 *ret_arg, int ret_len) +{ + struct pt_regs regs; + + memset(®s, 0, sizeof(regs)); + regs.regs[0] = func_id; + + if (args) + memcpy(®s.regs[1], args, arg_len * sizeof(*args)); + + smc_call(®s); + + if (ret_arg) + memcpy(ret_arg, ®s.regs[1], ret_len * sizeof(*ret_arg)); + + return regs.regs[0]; +} + +int smc_send_mailbox(u32 cmd, u32 len, u32 *arg, u8 urgent, u32 *resp_buf_len, + u32 *resp_buf) +{ + int ret; + u64 args[6]; + u64 resp[3]; + + args[0] = cmd; + args[1] = (u64)arg; + args[2] = len; + args[3] = urgent; + args[4] = (u64)resp_buf; + if (resp_buf_len) + args[5] = *resp_buf_len; + else + args[5] = 0; + + ret = invoke_smc(INTEL_SIP_SMC_MBOX_SEND_CMD, args, ARRAY_SIZE(args), + resp, ARRAY_SIZE(resp)); + + if (ret == INTEL_SIP_SMC_STATUS_OK && resp_buf && resp_buf_len) { + if (!resp[0]) + *resp_buf_len = resp[1]; + } + + return (int)resp[0]; +} diff --git a/arch/arm/mach-socfpga/wrap_pll_config_s10.c b/arch/arm/mach-socfpga/wrap_pll_config_s10.c index 3da85791a1..049c5711a8 100644 --- a/arch/arm/mach-socfpga/wrap_pll_config_s10.c +++ b/arch/arm/mach-socfpga/wrap_pll_config_s10.c @@ -12,6 +12,7 @@ const struct cm_config * const cm_get_default_config(void) { +#ifdef CONFIG_SPL_BUILD struct cm_config *cm_handoff_cfg = (struct cm_config *) (S10_HANDOFF_CLOCK + S10_HANDOFF_OFFSET_DATA); u32 *conversion = (u32 *)cm_handoff_cfg; @@ -26,7 +27,7 @@ const struct cm_config * const cm_get_default_config(void) } else if (handoff_clk == S10_HANDOFF_MAGIC_CLOCK) { return cm_handoff_cfg; } - +#endif return NULL; } diff --git a/board/altera/stratix10-socdk/MAINTAINERS b/board/altera/stratix10-socdk/MAINTAINERS index 6192bc9174..6efd0cfc05 100644 --- a/board/altera/stratix10-socdk/MAINTAINERS +++ b/board/altera/stratix10-socdk/MAINTAINERS @@ -4,4 +4,5 @@ M: Dinh Nguyen <dinh.nguyen@intel.com> S: Maintained F: board/altera/stratix10-socdk/ F: include/configs/socfpga_stratix10_socdk.h +F: configs/socfpga_stratix10_atf_defconfig F: configs/socfpga_stratix10_defconfig diff --git a/board/intel/agilex-socdk/MAINTAINERS b/board/intel/agilex-socdk/MAINTAINERS index b8e28f0b24..18edbdcd2f 100644 --- a/board/intel/agilex-socdk/MAINTAINERS +++ b/board/intel/agilex-socdk/MAINTAINERS @@ -4,4 +4,5 @@ M: Chee Hong Ang <chee.hong.ang@intel.com> S: Maintained F: board/intel/agilex-socdk/ F: include/configs/socfpga_agilex_socdk.h +F: configs/socfpga_agilex_atf_defconfig F: configs/socfpga_agilex_defconfig diff --git a/configs/socfpga_agilex_atf_defconfig b/configs/socfpga_agilex_atf_defconfig new file mode 100644 index 0000000000..ad87a8098f --- /dev/null +++ b/configs/socfpga_agilex_atf_defconfig @@ -0,0 +1,72 @@ +CONFIG_ARM=y +CONFIG_ARM_SMCCC=y +CONFIG_SPL_LDSCRIPT="arch/arm/mach-socfpga/u-boot-spl-soc64.lds" +CONFIG_ARCH_SOCFPGA=y +CONFIG_SYS_TEXT_BASE=0x200000 +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_ENV_SIZE=0x1000 +CONFIG_ENV_OFFSET=0x200 +CONFIG_DM_GPIO=y +CONFIG_NR_DRAM_BANKS=2 +CONFIG_TARGET_SOCFPGA_AGILEX_SOCDK=y +CONFIG_IDENT_STRING="socfpga_agilex" +CONFIG_SPL_FS_FAT=y +CONFIG_SPL_TEXT_BASE=0xFFE00000 +CONFIG_FIT=y +CONFIG_SPL_LOAD_FIT=y +CONFIG_SPL_LOAD_FIT_ADDRESS=0x02000000 +# CONFIG_USE_SPL_FIT_GENERATOR is not set +CONFIG_BOOTDELAY=5 +CONFIG_USE_BOOTARGS=y +CONFIG_BOOTARGS="earlycon" +CONFIG_SPL_CACHE=y +CONFIG_SPL_SPI_LOAD=y +CONFIG_SYS_SPI_U_BOOT_OFFS=0x02000000 +CONFIG_SPL_ATF=y +CONFIG_SPL_ATF_NO_PLATFORM_PARAM=y +CONFIG_HUSH_PARSER=y +CONFIG_SYS_PROMPT="SOCFPGA_AGILEX # " +CONFIG_CMD_MEMTEST=y +CONFIG_CMD_GPIO=y +CONFIG_CMD_I2C=y +CONFIG_CMD_MMC=y +CONFIG_CMD_SPI=y +CONFIG_CMD_USB=y +CONFIG_CMD_DHCP=y +CONFIG_CMD_MII=y +CONFIG_CMD_PING=y +CONFIG_CMD_CACHE=y +CONFIG_CMD_EXT4=y +CONFIG_CMD_FAT=y +CONFIG_CMD_FS_GENERIC=y +CONFIG_DEFAULT_DEVICE_TREE="socfpga_agilex_socdk" +CONFIG_ENV_IS_IN_MMC=y +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_SPL_ALTERA_SDRAM=y +CONFIG_DWAPB_GPIO=y +CONFIG_DM_I2C=y +CONFIG_SYS_I2C_DW=y +CONFIG_DM_MMC=y +CONFIG_MMC_DW=y +CONFIG_MTD=y +CONFIG_SF_DEFAULT_MODE=0x2003 +CONFIG_SPI_FLASH_SPANSION=y +CONFIG_SPI_FLASH_STMICRO=y +CONFIG_PHY_MICREL=y +CONFIG_PHY_MICREL_KSZ90X1=y +CONFIG_DM_ETH=y +CONFIG_ETH_DESIGNWARE=y +CONFIG_MII=y +CONFIG_DM_RESET=y +CONFIG_SPI=y +CONFIG_CADENCE_QSPI=y +CONFIG_DESIGNWARE_SPI=y +CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_USB_DWC2=y +CONFIG_USB_STORAGE=y +CONFIG_DESIGNWARE_WATCHDOG=y +CONFIG_WDT=y +# CONFIG_SPL_USE_TINY_PRINTF is not set +CONFIG_PANIC_HANG=y diff --git a/configs/socfpga_stratix10_atf_defconfig b/configs/socfpga_stratix10_atf_defconfig new file mode 100644 index 0000000000..1005ba979e --- /dev/null +++ b/configs/socfpga_stratix10_atf_defconfig @@ -0,0 +1,74 @@ +CONFIG_ARM=y +CONFIG_ARM_SMCCC=y +CONFIG_SPL_LDSCRIPT="arch/arm/mach-socfpga/u-boot-spl-soc64.lds" +CONFIG_ARCH_SOCFPGA=y +CONFIG_SYS_TEXT_BASE=0x200000 +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_ENV_SIZE=0x1000 +CONFIG_ENV_OFFSET=0x200 +CONFIG_DM_GPIO=y +CONFIG_NR_DRAM_BANKS=2 +CONFIG_TARGET_SOCFPGA_STRATIX10_SOCDK=y +CONFIG_IDENT_STRING="socfpga_stratix10" +CONFIG_SPL_FS_FAT=y +CONFIG_SPL_TEXT_BASE=0xFFE00000 +CONFIG_FIT=y +CONFIG_SPL_LOAD_FIT=y +CONFIG_SPL_LOAD_FIT_ADDRESS=0x02000000 +# CONFIG_USE_SPL_FIT_GENERATOR is not set +CONFIG_BOOTDELAY=5 +CONFIG_USE_BOOTARGS=y +CONFIG_BOOTARGS="earlycon" +CONFIG_SPL_SPI_LOAD=y +CONFIG_SYS_SPI_U_BOOT_OFFS=0x02000000 +CONFIG_SPL_ATF=y +CONFIG_SPL_ATF_NO_PLATFORM_PARAM=y +CONFIG_HUSH_PARSER=y +CONFIG_SYS_PROMPT="SOCFPGA_STRATIX10 # " +CONFIG_CMD_MEMTEST=y +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_GPIO=y +CONFIG_CMD_I2C=y +CONFIG_CMD_MMC=y +CONFIG_CMD_SPI=y +CONFIG_CMD_USB=y +CONFIG_CMD_DHCP=y +CONFIG_CMD_MII=y +CONFIG_CMD_PING=y +CONFIG_CMD_CACHE=y +CONFIG_CMD_EXT4=y +CONFIG_CMD_FAT=y +CONFIG_CMD_FS_GENERIC=y +CONFIG_DEFAULT_DEVICE_TREE="socfpga_stratix10_socdk" +CONFIG_ENV_IS_IN_MMC=y +CONFIG_SYS_RELOC_GD_ENV_ADDR=y +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_SPL_ALTERA_SDRAM=y +CONFIG_FPGA_INTEL_PR=y +CONFIG_DWAPB_GPIO=y +CONFIG_DM_I2C=y +CONFIG_SYS_I2C_DW=y +CONFIG_DM_MMC=y +CONFIG_MMC_DW=y +CONFIG_MTD=y +CONFIG_SF_DEFAULT_MODE=0x2003 +CONFIG_SPI_FLASH_SPANSION=y +CONFIG_SPI_FLASH_STMICRO=y +CONFIG_PHY_MICREL=y +CONFIG_PHY_MICREL_KSZ90X1=y +CONFIG_DM_ETH=y +CONFIG_ETH_DESIGNWARE=y +CONFIG_MII=y +CONFIG_DM_RESET=y +CONFIG_SPI=y +CONFIG_CADENCE_QSPI=y +CONFIG_DESIGNWARE_SPI=y +CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_USB_DWC2=y +CONFIG_USB_STORAGE=y +CONFIG_DESIGNWARE_WATCHDOG=y +CONFIG_WDT=y +# CONFIG_SPL_USE_TINY_PRINTF is not set +CONFIG_PANIC_HANG=y diff --git a/drivers/fpga/intel_sdm_mb.c b/drivers/fpga/intel_sdm_mb.c index 9a1dc2c0c8..f5fd9a14c2 100644 --- a/drivers/fpga/intel_sdm_mb.c +++ b/drivers/fpga/intel_sdm_mb.c @@ -8,11 +8,149 @@ #include <log.h> #include <watchdog.h> #include <asm/arch/mailbox_s10.h> +#include <asm/arch/smc_api.h> #include <linux/delay.h> +#include <linux/intel-smc.h> #define RECONFIG_STATUS_POLL_RESP_TIMEOUT_MS 60000 #define RECONFIG_STATUS_INTERVAL_DELAY_US 1000000 +#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_ATF) + +#define BITSTREAM_CHUNK_SIZE 0xFFFF0 +#define RECONFIG_STATUS_POLL_RETRY_MAX 100 + +/* + * Polling the FPGA configuration status. + * Return 0 for success, non-zero for error. + */ +static int reconfig_status_polling_resp(void) +{ + int ret; + unsigned long start = get_timer(0); + + while (1) { + ret = invoke_smc(INTEL_SIP_SMC_FPGA_CONFIG_ISDONE, NULL, 0, + NULL, 0); + + if (!ret) + return 0; /* configuration success */ + + if (ret != INTEL_SIP_SMC_STATUS_BUSY) + return ret; + + if (get_timer(start) > RECONFIG_STATUS_POLL_RESP_TIMEOUT_MS) + return -ETIMEDOUT; /* time out */ + + puts("."); + udelay(RECONFIG_STATUS_INTERVAL_DELAY_US); + WATCHDOG_RESET(); + } + + return -ETIMEDOUT; +} + +static int send_bitstream(const void *rbf_data, size_t rbf_size) +{ + int i; + u64 res_buf[3]; + u64 args[2]; + u32 xfer_count = 0; + int ret, wr_ret = 0, retry = 0; + size_t buf_size = (rbf_size > BITSTREAM_CHUNK_SIZE) ? + BITSTREAM_CHUNK_SIZE : rbf_size; + + while (rbf_size || xfer_count) { + if (!wr_ret && rbf_size) { + args[0] = (u64)rbf_data; + args[1] = buf_size; + wr_ret = invoke_smc(INTEL_SIP_SMC_FPGA_CONFIG_WRITE, + args, 2, NULL, 0); + + debug("wr_ret = %d, rbf_data = %p, buf_size = %08lx\n", + wr_ret, rbf_data, buf_size); + + if (wr_ret) + continue; + + rbf_size -= buf_size; + rbf_data += buf_size; + + if (buf_size >= rbf_size) + buf_size = rbf_size; + + xfer_count++; + puts("."); + } else { + ret = invoke_smc( + INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE, + NULL, 0, res_buf, ARRAY_SIZE(res_buf)); + if (!ret) { + for (i = 0; i < ARRAY_SIZE(res_buf); i++) { + if (!res_buf[i]) + break; + xfer_count--; + wr_ret = 0; + retry = 0; + } + } else if (ret != + INTEL_SIP_SMC_STATUS_BUSY) + return ret; + else if (!xfer_count) + return INTEL_SIP_SMC_STATUS_ERROR; + + if (++retry >= RECONFIG_STATUS_POLL_RETRY_MAX) + return -ETIMEDOUT; + + udelay(20000); + } + WATCHDOG_RESET(); + } + + return 0; +} + +/* + * This is the interface used by FPGA driver. + * Return 0 for success, non-zero for error. + */ +int intel_sdm_mb_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size) +{ + int ret; + u64 arg = 1; + + debug("Invoking FPGA_CONFIG_START...\n"); + + ret = invoke_smc(INTEL_SIP_SMC_FPGA_CONFIG_START, &arg, 1, NULL, 0); + + if (ret) { + puts("Failure in RECONFIG mailbox command!\n"); + return ret; + } + + ret = send_bitstream(rbf_data, rbf_size); + if (ret) { + puts("Error sending bitstream!\n"); + return ret; + } + + /* Make sure we don't send MBOX_RECONFIG_STATUS too fast */ + udelay(RECONFIG_STATUS_INTERVAL_DELAY_US); + + debug("Polling with MBOX_RECONFIG_STATUS...\n"); + ret = reconfig_status_polling_resp(); + if (ret) { + puts("FPGA reconfiguration failed!"); + return ret; + } + + puts("FPGA reconfiguration OK!\n"); + + return ret; +} + +#else + static const struct mbox_cfgstat_state { int err_no; const char *error_name; @@ -286,3 +424,4 @@ int intel_sdm_mb_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size) return ret; } +#endif diff --git a/drivers/mmc/ca_dw_mmc.c b/drivers/mmc/ca_dw_mmc.c index fad2ff5aaf..2b79356a20 100644 --- a/drivers/mmc/ca_dw_mmc.c +++ b/drivers/mmc/ca_dw_mmc.c @@ -40,7 +40,7 @@ struct ca_dwmmc_priv_data { u8 ds; }; -static void ca_dwmci_clksel(struct dwmci_host *host) +static int ca_dwmci_clksel(struct dwmci_host *host) { struct ca_dwmmc_priv_data *priv = host->priv; u32 val = readl(priv->sd_dll_reg); @@ -52,6 +52,8 @@ static void ca_dwmci_clksel(struct dwmci_host *host) val |= SD_CLK_SEL_100MHZ; writel(val, priv->sd_dll_reg); + + return 0; } static void ca_dwmci_board_init(struct dwmci_host *host) diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index 7702f4be3f..7c8a312fa7 100644 --- a/drivers/mmc/dw_mmc.c +++ b/drivers/mmc/dw_mmc.c @@ -496,8 +496,13 @@ static int dwmci_set_ios(struct mmc *mmc) dwmci_writel(host, DWMCI_UHS_REG, regs); - if (host->clksel) - host->clksel(host); + if (host->clksel) { + int ret; + + ret = host->clksel(host); + if (ret) + return ret; + } #if CONFIG_IS_ENABLED(DM_REGULATOR) if (mmc->vqmmc_supply) { diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c index 3aa9fb3c89..2fc1ef18c7 100644 --- a/drivers/mmc/exynos_dw_mmc.c +++ b/drivers/mmc/exynos_dw_mmc.c @@ -44,7 +44,7 @@ struct dwmci_exynos_priv_data { * Function used as callback function to initialise the * CLKSEL register for every mmc channel. */ -static void exynos_dwmci_clksel(struct dwmci_host *host) +static int exynos_dwmci_clksel(struct dwmci_host *host) { #ifdef CONFIG_DM_MMC struct dwmci_exynos_priv_data *priv = @@ -53,6 +53,8 @@ static void exynos_dwmci_clksel(struct dwmci_host *host) struct dwmci_exynos_priv_data *priv = host->priv; #endif dwmci_writel(host, DWMCI_CLKSEL, priv->sdr_timing); + + return 0; } unsigned int exynos_dwmci_get_clk(struct dwmci_host *host, uint freq) diff --git a/drivers/mmc/nexell_dw_mmc.c b/drivers/mmc/nexell_dw_mmc.c index 753c89d278..2723e4887c 100644 --- a/drivers/mmc/nexell_dw_mmc.c +++ b/drivers/mmc/nexell_dw_mmc.c @@ -51,7 +51,7 @@ struct nexell_dwmmc_priv { struct clk *clk_get(const char *id); -static void nx_dw_mmc_clksel(struct dwmci_host *host) +static int nx_dw_mmc_clksel(struct dwmci_host *host) { /* host->priv is pointer to "struct udevice" */ struct nexell_dwmmc_priv *priv = dev_get_priv(host->priv); @@ -65,6 +65,8 @@ static void nx_dw_mmc_clksel(struct dwmci_host *host) DWMCI_SET_DRV_CLK(DWMCI_SHIFT_0) | DWMCI_SET_DIV_RATIO(3); dwmci_writel(host, DWMCI_CLKSEL, val); + + return 0; } static void nx_dw_mmc_reset(int ch) diff --git a/drivers/mmc/socfpga_dw_mmc.c b/drivers/mmc/socfpga_dw_mmc.c index dc008c5e2f..aa0d3a2222 100644 --- a/drivers/mmc/socfpga_dw_mmc.c +++ b/drivers/mmc/socfpga_dw_mmc.c @@ -6,6 +6,7 @@ #include <common.h> #include <log.h> #include <asm/arch/clock_manager.h> +#include <asm/arch/secure_reg_helper.h> #include <asm/arch/system_manager.h> #include <clk.h> #include <dm.h> @@ -13,6 +14,7 @@ #include <errno.h> #include <fdtdec.h> #include <dm/device_compat.h> +#include <linux/intel-smc.h> #include <linux/libfdt.h> #include <linux/err.h> #include <malloc.h> @@ -46,7 +48,7 @@ static void socfpga_dwmci_reset(struct udevice *dev) reset_deassert_bulk(&reset_bulk); } -static void socfpga_dwmci_clksel(struct dwmci_host *host) +static int socfpga_dwmci_clksel(struct dwmci_host *host) { struct dwmci_socfpga_priv_data *priv = host->priv; u32 sdmmc_mask = ((priv->smplsel & 0x7) << SYSMGR_SDMMC_SMPLSEL_SHIFT) | @@ -58,14 +60,28 @@ static void socfpga_dwmci_clksel(struct dwmci_host *host) debug("%s: drvsel %d smplsel %d\n", __func__, priv->drvsel, priv->smplsel); + +#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_ATF) + int ret; + + ret = socfpga_secure_reg_write32(SOCFPGA_SECURE_REG_SYSMGR_SOC64_SDMMC, + sdmmc_mask); + if (ret) { + printf("DWMMC: Failed to set clksel via SMC call"); + return ret; + } +#else writel(sdmmc_mask, socfpga_get_sysmgr_addr() + SYSMGR_SDMMC); debug("%s: SYSMGR_SDMMCGRP_CTRL_REG = 0x%x\n", __func__, readl(socfpga_get_sysmgr_addr() + SYSMGR_SDMMC)); +#endif /* Enable SDMMC clock */ setbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_PERPLL_EN, CLKMGR_PERPLLGRP_EN_SDMMCCLK_MASK); + + return 0; } static int socfpga_dwmmc_get_clk_rate(struct udevice *dev) diff --git a/drivers/net/dwmac_socfpga.c b/drivers/net/dwmac_socfpga.c index 939f199b1f..82fdff51da 100644 --- a/drivers/net/dwmac_socfpga.c +++ b/drivers/net/dwmac_socfpga.c @@ -6,6 +6,8 @@ */ #include <common.h> +#include <asm/arch/secure_reg_helper.h> +#include <asm/arch/system_manager.h> #include <asm/io.h> #include <dm.h> #include <clk.h> @@ -17,8 +19,6 @@ #include <dm/device_compat.h> #include <linux/err.h> -#include <asm/arch/system_manager.h> - struct dwmac_socfpga_plat { struct dw_eth_pdata dw_eth_pdata; void *phy_intf; @@ -64,6 +64,32 @@ static int dwmac_socfpga_of_to_plat(struct udevice *dev) return designware_eth_of_to_plat(dev); } +static int dwmac_socfpga_do_setphy(struct udevice *dev, u32 modereg) +{ + struct dwmac_socfpga_plat *pdata = dev_get_plat(dev); + u32 modemask = SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << pdata->reg_shift; + +#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_ATF) + u32 index = ((u64)pdata->phy_intf - socfpga_get_sysmgr_addr() - + SYSMGR_SOC64_EMAC0) >> 2; + + u32 id = SOCFPGA_SECURE_REG_SYSMGR_SOC64_EMAC0 + index; + + int ret = socfpga_secure_reg_update32(id, + modemask, + modereg << pdata->reg_shift); + if (ret) { + dev_err(dev, "Failed to set PHY register via SMC call\n"); + return ret; + } +#else + clrsetbits_le32(pdata->phy_intf, modemask, + modereg << pdata->reg_shift); +#endif + + return 0; +} + static int dwmac_socfpga_probe(struct udevice *dev) { struct dwmac_socfpga_plat *pdata = dev_get_plat(dev); @@ -71,7 +97,6 @@ static int dwmac_socfpga_probe(struct udevice *dev) struct reset_ctl_bulk reset_bulk; int ret; u32 modereg; - u32 modemask; switch (edata->phy_interface) { case PHY_INTERFACE_MODE_MII: @@ -97,9 +122,9 @@ static int dwmac_socfpga_probe(struct udevice *dev) reset_assert_bulk(&reset_bulk); - modemask = SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << pdata->reg_shift; - clrsetbits_le32(pdata->phy_intf, modemask, - modereg << pdata->reg_shift); + ret = dwmac_socfpga_do_setphy(dev, modereg); + if (ret) + return ret; reset_release_bulk(&reset_bulk); diff --git a/include/configs/socfpga_common.h b/include/configs/socfpga_common.h index 3d71759da4..62b327cd6e 100644 --- a/include/configs/socfpga_common.h +++ b/include/configs/socfpga_common.h @@ -22,8 +22,10 @@ #if defined(CONFIG_TARGET_SOCFPGA_GEN5) #define CONFIG_SYS_INIT_RAM_ADDR 0xFFFF0000 #define CONFIG_SYS_INIT_RAM_SIZE SOCFPGA_PHYS_OCRAM_SIZE +#define CONFIG_SPL_PAD_TO 0x10000 #elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10) #define CONFIG_SYS_INIT_RAM_ADDR 0xFFE00000 +#define CONFIG_SPL_PAD_TO 0x40000 /* SPL memory allocation configuration, this is for FAT implementation */ #ifndef CONFIG_SYS_SPL_MALLOC_SIZE #define CONFIG_SYS_SPL_MALLOC_SIZE 0x10000 diff --git a/include/configs/socfpga_soc64_common.h b/include/configs/socfpga_soc64_common.h index fb5e2e8aaf..fdcd7d3e9a 100644 --- a/include/configs/socfpga_soc64_common.h +++ b/include/configs/socfpga_soc64_common.h @@ -40,9 +40,14 @@ */ #define CONFIG_SYS_INIT_RAM_ADDR 0xFFE00000 #define CONFIG_SYS_INIT_RAM_SIZE 0x40000 +#ifdef CONFIG_SPL_BUILD #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_INIT_RAM_ADDR \ + CONFIG_SYS_INIT_RAM_SIZE \ - S10_HANDOFF_SIZE) +#else +#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_TEXT_BASE \ + + 0x100000) +#endif #define CONFIG_SYS_INIT_SP_OFFSET (CONFIG_SYS_INIT_SP_ADDR) #define CONFIG_SYS_MALLOC_LEN (5 * 1024 * 1024) @@ -78,12 +83,20 @@ unsigned int cm_get_qspi_controller_clk_hz(void); * CONFIG_BOOTARGS goes into the environment value "bootargs". * Do note the value will override also the chosen node in FDT blob. */ + +#ifdef CONFIG_FIT +#define CONFIG_BOOTFILE "kernel.itb" +#define CONFIG_BOOTCOMMAND "run fatscript; run mmcfitload;run linux_qspi_enable;" \ + "run mmcfitboot" +#else +#define CONFIG_BOOTFILE "Image" #define CONFIG_BOOTCOMMAND "run fatscript; run mmcload;run linux_qspi_enable;" \ "run mmcboot" +#endif #define CONFIG_EXTRA_ENV_SETTINGS \ "loadaddr=" __stringify(CONFIG_SYS_LOAD_ADDR) "\0" \ - "bootfile=Image\0" \ + "bootfile=" CONFIG_BOOTFILE "\0" \ "fdt_addr=8000000\0" \ "fdtimage=" CONFIG_DEFAULT_DEVICE_TREE ".dtb\0" \ "mmcroot=/dev/mmcblk0p2\0" \ @@ -93,6 +106,11 @@ unsigned int cm_get_qspi_controller_clk_hz(void); "mmcload=mmc rescan;" \ "load mmc 0:1 ${loadaddr} ${bootfile};" \ "load mmc 0:1 ${fdt_addr} ${fdtimage}\0" \ + "mmcfitboot=setenv bootargs " CONFIG_BOOTARGS \ + " root=${mmcroot} rw rootwait;" \ + "bootm ${loadaddr}\0" \ + "mmcfitload=mmc rescan;" \ + "load mmc 0:1 ${loadaddr} ${bootfile}\0" \ "linux_qspi_enable=if sf probe; then " \ "echo Enabling QSPI at Linux DTB...;" \ "fdt addr ${fdt_addr}; fdt resize;" \ @@ -193,6 +211,10 @@ unsigned int cm_get_l4_sys_free_clk_hz(void); - CONFIG_SYS_SPL_MALLOC_SIZE) /* SPL SDMMC boot support */ +#ifdef CONFIG_SPL_LOAD_FIT +#define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME "u-boot.itb" +#else #define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME "u-boot.img" +#endif #endif /* __CONFIG_SOCFPGA_SOC64_COMMON_H__ */ diff --git a/include/dwmmc.h b/include/dwmmc.h index 51ab74ead3..5fc8ed8395 100644 --- a/include/dwmmc.h +++ b/include/dwmmc.h @@ -174,7 +174,7 @@ struct dwmci_host { struct mmc *mmc; void *priv; - void (*clksel)(struct dwmci_host *host); + int (*clksel)(struct dwmci_host *host); void (*board_init)(struct dwmci_host *host); /** diff --git a/include/linux/intel-smc.h b/include/linux/intel-smc.h new file mode 100644 index 0000000000..cacb410691 --- /dev/null +++ b/include/linux/intel-smc.h @@ -0,0 +1,573 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2017-2018, Intel Corporation + */ + +#ifndef __INTEL_SMC_H +#define __INTEL_SMC_H + +#include <linux/arm-smccc.h> +#include <linux/bitops.h> + +/* + * This file defines the Secure Monitor Call (SMC) message protocol used for + * service layer driver in normal world (EL1) to communicate with secure + * monitor software in Secure Monitor Exception Level 3 (EL3). + * + * This file is shared with secure firmware (FW) which is out of u-boot tree. + * + * An ARM SMC instruction takes a function identifier and up to 6 64-bit + * register values as arguments, and can return up to 4 64-bit register + * values. The operation of the secure monitor is determined by the parameter + * values passed in through registers. + + * EL1 and EL3 communicates pointer as physical address rather than the + * virtual address. + */ + +/* + * Functions specified by ARM SMC Calling convention: + * + * FAST call executes atomic operations, returns when the requested operation + * has completed. + * STD call starts a operation which can be preempted by a non-secure + * interrupt. The call can return before the requested operation has + * completed. + * + * a0..a7 is used as register names in the descriptions below, on arm32 + * that translates to r0..r7 and on arm64 to w0..w7. + */ + +#define INTEL_SIP_SMC_STD_CALL_VAL(func_num) \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL, ARM_SMCCC_SMC_64, \ + ARM_SMCCC_OWNER_SIP, (func_num)) + +#define INTEL_SIP_SMC_FAST_CALL_VAL(func_num) \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64, \ + ARM_SMCCC_OWNER_SIP, (func_num)) + +/* + * Return values in INTEL_SIP_SMC_* call + * + * INTEL_SIP_SMC_RETURN_UNKNOWN_FUNCTION: + * Secure monitor software doesn't recognize the request. + * + * INTEL_SIP_SMC_STATUS_OK: + * SMC call completed successfully, + * In case of FPGA configuration write operation, it means secure monitor + * software can accept the next chunk of FPGA configuration data. + * + * INTEL_SIP_SMC_STATUS_BUSY: + * In case of FPGA configuration write operation, it means secure monitor + * software is still processing previous data & can't accept the next chunk + * of data. Service driver needs to issue + * INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE call to query the + * completed block(s). + * + * INTEL_SIP_SMC_STATUS_ERROR: + * There is error during the SMC call process. + * + * INTEL_SIP_SMC_REG_ERROR: + * There is error during a read or write operation of the protected + * registers. + */ +#define INTEL_SIP_SMC_RETURN_UNKNOWN_FUNCTION 0xFFFFFFFF +#define INTEL_SIP_SMC_STATUS_OK 0x0 +#define INTEL_SIP_SMC_STATUS_BUSY 0x1 +#define INTEL_SIP_SMC_STATUS_REJECTED 0x2 +#define INTEL_SIP_SMC_STATUS_ERROR 0x4 +#define INTEL_SIP_SMC_REG_ERROR 0x5 +#define INTEL_SIP_SMC_RSU_ERROR 0x7 + +/* + * Request INTEL_SIP_SMC_FPGA_CONFIG_START + * + * Sync call used by service driver at EL1 to request the FPGA in EL3 to + * be prepare to receive a new configuration. + * + * Call register usage: + * a0: INTEL_SIP_SMC_FPGA_CONFIG_START. + * a1: flag for full or partial configuration + * 0 full reconfiguration. + * 1 partial reconfiguration. + * a2-7: not used. + * + * Return status: + * a0: INTEL_SIP_SMC_STATUS_OK, or INTEL_SIP_SMC_STATUS_ERROR. + * a1-3: not used. + */ +#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_START 1 +#define INTEL_SIP_SMC_FPGA_CONFIG_START \ + INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_START) + +/* + * Request INTEL_SIP_SMC_FPGA_CONFIG_WRITE + * + * Async call used by service driver at EL1 to provide FPGA configuration data + * to secure world. + * + * Call register usage: + * a0: INTEL_SIP_SMC_FPGA_CONFIG_WRITE. + * a1: 64bit physical address of the configuration data memory block + * a2: Size of configuration data block. + * a3-7: not used. + * + * Return status: + * a0: INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_STATUS_BUSY, + * INTEL_SIP_SMC_STATUS_REJECTED or INTEL_SIP_SMC_STATUS_ERROR. + * a1: 64bit physical address of 1st completed memory block if any completed + * block, otherwise zero value. + * a2: 64bit physical address of 2nd completed memory block if any completed + * block, otherwise zero value. + * a3: 64bit physical address of 3rd completed memory block if any completed + * block, otherwise zero value. + */ +#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_WRITE 2 +#define INTEL_SIP_SMC_FPGA_CONFIG_WRITE \ + INTEL_SIP_SMC_STD_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_WRITE) + +/* + * Request INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE + * + * Sync call used by service driver at EL1 to track the completed write + * transactions. This request is called after INTEL_SIP_SMC_FPGA_CONFIG_WRITE + * call returns INTEL_SIP_SMC_STATUS_BUSY. + * + * Call register usage: + * a0: INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE. + * a1-7: not used. + * + * Return status: + * a0: INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_STATUS_BUSY or + * INTEL_SIP_SMC_STATUS_ERROR. + * a1: 64bit physical address of 1st completed memory block. + * a2: 64bit physical address of 2nd completed memory block if + * any completed block, otherwise zero value. + * a3: 64bit physical address of 3rd completed memory block if + * any completed block, otherwise zero value. + */ +#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_COMPLETED_WRITE 3 +#define INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE \ +INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_COMPLETED_WRITE) + +/* + * Request INTEL_SIP_SMC_FPGA_CONFIG_ISDONE + * + * Sync call used by service driver at EL1 to inform secure world that all + * data are sent, to check whether or not the secure world had completed + * the FPGA configuration process. + * + * Call register usage: + * a0: INTEL_SIP_SMC_FPGA_CONFIG_ISDONE. + * a1-7: not used. + * + * Return status: + * a0: INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_STATUS_BUSY or + * INTEL_SIP_SMC_STATUS_ERROR. + * a1-3: not used. + */ +#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_ISDONE 4 +#define INTEL_SIP_SMC_FPGA_CONFIG_ISDONE \ + INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_ISDONE) + +/* + * Request INTEL_SIP_SMC_FPGA_CONFIG_GET_MEM + * + * Sync call used by service driver at EL1 to query the physical address of + * memory block reserved by secure monitor software. + * + * Call register usage: + * a0:INTEL_SIP_SMC_FPGA_CONFIG_GET_MEM. + * a1-7: not used. + * + * Return status: + * a0: INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_STATUS_ERROR. + * a1: start of physical address of reserved memory block. + * a2: size of reserved memory block. + * a3: not used. + */ +#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_GET_MEM 5 +#define INTEL_SIP_SMC_FPGA_CONFIG_GET_MEM \ + INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_GET_MEM) + +/* + * Request INTEL_SIP_SMC_FPGA_CONFIG_LOOPBACK + * + * For SMC loop-back mode only, used for internal integration, debugging + * or troubleshooting. + * + * Call register usage: + * a0: INTEL_SIP_SMC_FPGA_CONFIG_LOOPBACK. + * a1-7: not used. + * + * Return status: + * a0: INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_STATUS_ERROR. + * a1-3: not used. + */ +#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_LOOPBACK 6 +#define INTEL_SIP_SMC_FPGA_CONFIG_LOOPBACK \ + INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_LOOPBACK) + +/* + * Request INTEL_SIP_SMC_REG_READ + * + * Read a protected register using SMCCC + * + * Call register usage: + * a0: INTEL_SIP_SMC_REG_READ. + * a1: register address. + * a2-7: not used. + * + * Return status: + * a0: INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_REG_ERROR. + * a1: Value in the register + * a2-3: not used. + */ +#define INTEL_SIP_SMC_FUNCID_REG_READ 7 +#define INTEL_SIP_SMC_REG_READ \ + INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_REG_READ) + +/* + * Request INTEL_SIP_SMC_REG_WRITE + * + * Write a protected register using SMCCC + * + * Call register usage: + * a0: INTEL_SIP_SMC_REG_WRITE. + * a1: register address + * a2: value to program into register. + * a3-7: not used. + * + * Return status: + * a0: INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_REG_ERROR. + * a1-3: not used. + */ +#define INTEL_SIP_SMC_FUNCID_REG_WRITE 8 +#define INTEL_SIP_SMC_REG_WRITE \ + INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_REG_WRITE) + +/* + * Request INTEL_SIP_SMC_FUNCID_REG_UPDATE + * + * Update one or more bits in a protected register using a + * read-modify-write operation. + * + * Call register usage: + * a0: INTEL_SIP_SMC_REG_UPDATE. + * a1: register address + * a2: Write Mask. + * a3: Value to write. + * a4-7: not used. + * + * Return status: + * a0: INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_REG_ERROR. + * a1-3: Not used. + */ +#define INTEL_SIP_SMC_FUNCID_REG_UPDATE 9 +#define INTEL_SIP_SMC_REG_UPDATE \ + INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_REG_UPDATE) + +/* +* Request INTEL_SIP_SMC_RSU_STATUS +* +* Sync call used by service driver at EL1 to query the RSU status +* +* Call register usage: +* a0 INTEL_SIP_SMC_RSU_STATUS +* a1-7 not used +* +* Return status +* a0: Current Image +* a1: Last Failing Image +* a2: Version [width 32 bit] | State [width 32 bit] +* a3: Error details [width 32 bit] | Error location [width 32 bit] +* +* Or +* +* a0: INTEL_SIP_SMC_RSU_ERROR +*/ +#define INTEL_SIP_SMC_FUNCID_RSU_STATUS 11 +#define INTEL_SIP_SMC_RSU_STATUS \ + INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_STATUS) + +/* +* Request INTEL_SIP_SMC_RSU_UPDATE +* +* Sync call used by service driver at EL1 to tell you next reboot is RSU_UPDATE +* +* Call register usage: +* a0 INTEL_SIP_SMC_RSU_UPDATE +* a1 64bit physical address of the configuration data memory in flash +* a2-7 not used +* +* Return status + * a0 INTEL_SIP_SMC_STATUS_OK +*/ +#define INTEL_SIP_SMC_FUNCID_RSU_UPDATE 12 +#define INTEL_SIP_SMC_RSU_UPDATE \ + INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_UPDATE) + +/* + * Request INTEL_SIP_SMC_ECC_DBE + * + * Sync call used by service driver at EL1 alert EL3 that a Double Bit + * ECC error has occurred. + * + * Call register usage: + * a0 INTEL_SIP_SMC_ECC_DBE + * a1 SysManager Double Bit Error value + * a2-7 not used + * + * Return status + * a0 INTEL_SIP_SMC_STATUS_OK + */ +#define INTEL_SIP_SMC_FUNCID_ECC_DBE 13 +#define INTEL_SIP_SMC_ECC_DBE \ + INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_ECC_DBE) + +/* +* Request INTEL_SIP_SMC_RSU_NOTIFY +* +* Sync call used by service driver at EL1 to report HPS software execution stage +* +* Call register usage: +* a0 INTEL_SIP_SMC_RSU_NOTIFY +* a1 32bit HPS software execution stage +* a2-7 not used +* +* Return status + * a0 INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_REG_ERROR. +*/ +#define INTEL_SIP_SMC_FUNCID_RSU_NOTIFY 14 +#define INTEL_SIP_SMC_RSU_NOTIFY \ + INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_NOTIFY) + +/* + * Request INTEL_SIP_SMC_RSU_RETRY_COUNTER + * + * Sync call used by service driver at EL1 to query the RSU retry counter + * + * Call register usage: + * a0 INTEL_SIP_SMC_RSU_RETRY_COUNTER + * a1-7 not used + * + * Return status + * a0 INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_RSU_ERROR. + * a1 retry counter +*/ +#define INTEL_SIP_SMC_FUNCID_RSU_RETRY_COUNTER 15 +#define INTEL_SIP_SMC_RSU_RETRY_COUNTER \ + INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_RETRY_COUNTER) + +/* + * Request INTEL_SIP_SMC_RSU_DCMF_VERSION + * + * Sync call used by service driver at EL1 to query DCMF version + * + * Call register usage: + * a0 INTEL_SIP_SMC_RSU_DCMF_VERSION + * a1-7 not used + * + * Return status + * a0 INTEL_SIP_SMC_STATUS_OK + * a1 dcmf1 version | dcmf0 version + * a2 dcmf3 version | dcmf2 version + * + * Or + * + * a0 INTEL_SIP_SMC_RSU_ERROR + */ +#define INTEL_SIP_SMC_FUNCID_RSU_DCMF_VERSION 16 +#define INTEL_SIP_SMC_RSU_DCMF_VERSION \ + INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_DCMF_VERSION) + +/* + * Request INTEL_SIP_SMC_RSU_COPY_DCMF_VERSION + * + * Sync call used by SSBL (EL2) to copy DCMF version to ATF memory + * + * Call register usage: + * a0 INTEL_SIP_SMC_RSU_COPY_DCMF_VERSION + * a1 dcmf1 version | dcmf0 version + * a2 dcmf3 version | dcmf2 version + * + * Return status + * a0 INTEL_SIP_SMC_STATUS_OK + */ +#define INTEL_SIP_SMC_FUNCID_RSU_COPY_DCMF_VERSION 17 +#define INTEL_SIP_SMC_RSU_COPY_DCMF_VERSION \ + INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_COPY_DCMF_VERSION) + +/* + * Request INTEL_SIP_SMC_RSU_MAX_RETRY + * + * Sync call used by service driver at EL1 to query max_retry parameter + * + * Call register usage: + * a0 INTEL_SIP_SMC_RSU_MAX_RETRY + * a1-7 not used + * + * Return status + * a0 INTEL_SIP_SMC_STATUS_OK + * a1 max_retry + * + * Or + * + * a0 INTEL_SIP_SMC_RSU_ERROR + */ +#define INTEL_SIP_SMC_FUNCID_RSU_MAX_RETRY 18 +#define INTEL_SIP_SMC_RSU_MAX_RETRY \ + INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_MAX_RETRY) + +/* + * Request INTEL_SIP_SMC_RSU_COPY_MAX_RETRY + * + * Sync call used by SSBL (EL2) to copy RSU 'max retry' to ATF memory + * + * Call register usage: + * a0 INTEL_SIP_SMC_RSU_COPY_MAX_RETRY + * a1 max retry + * a2-7 not used + * + * Return status + * a0 INTEL_SIP_SMC_STATUS_OK + */ +#define INTEL_SIP_SMC_FUNCID_RSU_COPY_MAX_RETRY 19 +#define INTEL_SIP_SMC_RSU_COPY_MAX_RETRY \ + INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_COPY_MAX_RETRY) + +/* + * Request INTEL_SIP_SMC_RSU_DCMF_STATUS + * + * Sync call used by service driver at EL1 to query DCMF status + * + * Call register usage: + * a0 INTEL_SIP_SMC_RSU_DCMF_STATUS + * a1-7 not used + * + * Return status + * a0 INTEL_SIP_SMC_STATUS_OK + * a1 dcmf3 status | dcmf2 status | dcmf1 status | dcmf0 status + * + * Or + * + * a0 INTEL_SIP_SMC_RSU_ERROR + */ +#define INTEL_SIP_SMC_FUNCID_RSU_DCMF_STATUS 20 +#define INTEL_SIP_SMC_RSU_DCMF_STATUS \ + INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_DCMF_STATUS) + +/* + * Request INTEL_SIP_SMC_RSU_COPY_DCMF_STATUS + * + * Sync call used by SSBL (EL2) to copy RSU 'dcmf status' to ATF memory + * + * Call register usage: + * a0 INTEL_SIP_SMC_RSU_COPY_DCMF_STATUS + * a1 dcmf status + * a2-7 not used + * + * Return status + * a0 INTEL_SIP_SMC_STATUS_OK + */ +#define INTEL_SIP_SMC_FUNCID_RSU_COPY_DCMF_STATUS 21 +#define INTEL_SIP_SMC_RSU_COPY_DCMF_STATUS \ + INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_COPY_DCMF_STATUS) + +/* + * Request INTEL_SIP_SMC_HPS_SET_BRIDGES + * + * Enable/disable the SoC FPGA bridges + * + * Call register usage: + * a0 INTEL_SIP_SMC_HPS_SET_BRIDGES + * a1 Set bridges status: + * 0 - Disable + * 1 - Enable + * a2-7 not used + * + * Return status + * a0 INTEL_SIP_SMC_STATUS_OK + */ +#define INTEL_SIP_SMC_FUNCID_HPS_SET_BRIDGES 50 +#define INTEL_SIP_SMC_HPS_SET_BRIDGES \ + INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_HPS_SET_BRIDGES) + +/* + * Request INTEL_SIP_SMC_MBOX_SEND_CMD + * + * Send mailbox command to SDM + * + * Call register usage: + * a0 INTEL_SIP_SMC_MBOX_SEND_CMD + * a1 Mailbox command + * a2 64bit physical address pointer to command's arguments + * a3 Length of the argument + * a4 Urgent command: + * 0 - Disable + * 1 - Enable + * a5 64bit physical address pointer to a buffer for receiving responses + * a6 Length of the buffer + * + * Return status + * a0 INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_STATUS_ERROR + * a1 Status of mailbox response + * a2 Received length in the buffer + */ +#define INTEL_SIP_SMC_FUNCID_MBOX_SEND_CMD 60 +#define INTEL_SIP_SMC_MBOX_SEND_CMD \ + INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_MBOX_SEND_CMD) + +/* + * Request INTEL_SIP_SMC_HPS_SET_PHYINTF + * + * Select EMACx PHY interface + * + * Call register usage: + * a0 INTEL_SIP_SMC_HPS_SET_PHYINTF + * a1 EMAC number: + * 0 - EMAC0 + * 1 - EMAC1 + * 2 - EMAC2 + * a2 Type of PHY interface: + * 0 - GMII_MII + * 1 - RGMII + * 2 - RMII + * 3 - RESET + * a3-7 not used + * + * Return status + * a0 INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_STATUS_ERROR + */ +#define INTEL_SIP_SMC_FUNCID_HPS_SET_PHYINTF 61 +#define INTEL_SIP_SMC_HPS_SET_PHYINTF \ + INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_HPS_SET_PHYINTF) + +/* + * Request INTEL_SIP_SMC_HPS_SET_SDMMC_CCLK + * + * Select which phase shift of the clocks (drvsel & smplsel) for SDMMC + * + * Call register usage: + * a0 INTEL_SIP_SMC_HPS_SET_SDMMC_CCLK + * a1 Select which phase shift of the clock for cclk_in_drv (drvsel): + * 0 - 0 degree + * 1 - 45 degrees + * 2 - 90 degrees + * 3 - 135 degrees + * 4 - 180 degrees + * 5 - 225 degrees + * 6 - 270 degrees + * 7 - 315 degrees + * a2 Select which phase shift of the clock for cclk_in_sample (smplsel): + * (Same as above) + * a3-7 not used + * + * Return status + * a0 INTEL_SIP_SMC_STATUS_OK + */ +#define INTEL_SIP_SMC_FUNCID_HPS_SET_SDMMC_CCLK 62 +#define INTEL_SIP_SMC_HPS_SET_SDMMC_CCLK \ + INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_HPS_SET_SDMMC_CCLK) + +#endif diff --git a/tools/socfpgaimage.c b/tools/socfpgaimage.c index 3ba3c93af1..eba812fec9 100644 --- a/tools/socfpgaimage.c +++ b/tools/socfpgaimage.c @@ -61,6 +61,7 @@ #define HEADER_OFFSET 0x40 #define VALIDATION_WORD 0x31305341 +#define IMAGE_ALIGN 16 /* Minimum and default entry point offset */ #define ENTRY_POINT_OFFSET 0x14 @@ -97,7 +98,7 @@ static unsigned int sfp_hdr_size(uint8_t ver) return 0; } -static unsigned int sfp_pad_size(uint8_t ver) +static unsigned int sfp_max_size(uint8_t ver) { if (ver == 0) return sizeof(buffer_v0); @@ -106,6 +107,12 @@ static unsigned int sfp_pad_size(uint8_t ver) return 0; } +static unsigned int sfp_aligned_len(uint32_t size) +{ + /* Add 4 bytes for CRC and align to 16 bytes */ + return ALIGN(size + sizeof(uint32_t), IMAGE_ALIGN); +} + /* * The header checksum is just a very simple checksum over * the header area. @@ -208,22 +215,24 @@ static int sfp_sign_buffer(uint8_t *buf, uint8_t ver, uint8_t flags, struct image_tool_params *params) { uint32_t calc_crc; + uint32_t crc_off; /* Align the length up */ - len = ALIGN(len, 4); + len = sfp_aligned_len(len); - /* Build header, adding 4 bytes to length to hold the CRC32. */ - sfp_build_header(buf + HEADER_OFFSET, ver, flags, len + 4, params); + /* Build header */ + sfp_build_header(buf + HEADER_OFFSET, ver, flags, len, params); /* Calculate and apply the CRC */ - calc_crc = ~pbl_crc32(0, (char *)buf, len); + crc_off = len - sizeof(uint32_t); /* at last 4 bytes of image */ + calc_crc = ~pbl_crc32(0, (char *)buf, crc_off); - *((uint32_t *)(buf + len)) = cpu_to_le32(calc_crc); + *((uint32_t *)(buf + crc_off)) = cpu_to_le32(calc_crc); if (!pad_64k) return len + 4; - return sfp_pad_size(ver); + return sfp_max_size(ver); } /* Verify that the buffer looks sane */ @@ -240,7 +249,7 @@ static int sfp_verify_buffer(const uint8_t *buf) return -1; } - if (len < HEADER_OFFSET || len > sfp_pad_size(ver)) { + if (len < HEADER_OFFSET || len > sfp_max_size(ver)) { debug("Invalid header length (%i)\n", len); return -1; } @@ -274,12 +283,51 @@ static int socfpgaimage_verify_header(unsigned char *ptr, int image_size, return sfp_verify_buffer(ptr); } +static void socfpgaimage_print_header_v0(struct socfpga_header_v0 *header) +{ + printf("Image Type\t: Cyclone V / Arria V SoC Image\n"); + printf("Validation word\t: 0x%08x\n", + le32_to_cpu(header->validation)); + printf("Version\t\t: 0x%08x\n", header->version); + printf("Flags\t\t: 0x%08x\n", header->flags); + printf("Program length\t: 0x%08x\n", + le16_to_cpu(header->length_u32)); + printf("Header checksum\t: 0x%08x\n", + le16_to_cpu(header->checksum)); +} + +static void socfpgaimage_print_header_v1(struct socfpga_header_v1 *header) +{ + printf("Image Type\t: Arria 10 SoC Image\n"); + printf("Validation word\t: 0x%08x\n", + le32_to_cpu(header->validation)); + printf("Version\t\t: 0x%08x\n", header->version); + printf("Flags\t\t: 0x%08x\n", header->flags); + printf("Header length\t: 0x%08x\n", + le16_to_cpu(header->header_u8)); + printf("Program length\t: 0x%08x\n", + le32_to_cpu(header->length_u8)); + printf("Program entry\t: 0x%08x\n", + le32_to_cpu(header->entry_offset)); + printf("Header checksum\t: 0x%08x\n", + le16_to_cpu(header->checksum)); +} + static void socfpgaimage_print_header(const void *ptr) { - if (sfp_verify_buffer(ptr) == 0) - printf("Looks like a sane SOCFPGA preloader\n"); - else + const void *header = ptr + HEADER_OFFSET; + struct socfpga_header_v0 *header_v0; + + if (sfp_verify_buffer(ptr) == 0) { + header_v0 = (struct socfpga_header_v0 *)header; + + if (header_v0->version == 0) + socfpgaimage_print_header_v0(header_v0); + else + socfpgaimage_print_header_v1((struct socfpga_header_v1 *)header); + } else { printf("Not a sane SOCFPGA preloader\n"); + } } static int socfpgaimage_check_params_v0(struct image_tool_params *params) @@ -328,19 +376,25 @@ static int socfpgaimage_check_image_types_v1(uint8_t type) * To work in with the mkimage framework, we do some ugly stuff... * * First, socfpgaimage_vrec_header() is called. - * We prepend a fake header big enough to make the file sfp_pad_size(). + * We prepend a fake header big enough to include crc32 and align image to 16 + * bytes. * This gives us enough space to do what we want later. * * Next, socfpgaimage_set_header() is called. * We fix up the buffer by moving the image to the start of the buffer. - * We now have some room to do what we need (add CRC and padding). + * We now have some room to do what we need (add CRC). */ static int data_size; static int sfp_fake_header_size(unsigned int size, uint8_t ver) { - return sfp_pad_size(ver) - size; + unsigned int align_size; + + align_size = sfp_aligned_len(size); + + /* extra bytes needed */ + return align_size - size; } static int sfp_vrec_header(struct image_tool_params *params, @@ -350,7 +404,7 @@ static int sfp_vrec_header(struct image_tool_params *params, if (params->datafile && stat(params->datafile, &sbuf) == 0 && - sbuf.st_size <= (sfp_pad_size(ver) - sizeof(uint32_t))) { + sbuf.st_size <= (sfp_max_size(ver) - sizeof(uint32_t))) { data_size = sbuf.st_size; tparams->header_size = sfp_fake_header_size(data_size, ver); } @@ -378,7 +432,7 @@ static void sfp_set_header(void *ptr, unsigned char ver, /* * This function is called after vrec_header() has been called. * At this stage we have the sfp_fake_header_size() dummy bytes - * followed by data_size image bytes. Total = sfp_pad_size(). + * followed by data_size image bytes. * We need to fix the buffer by moving the image bytes back to * the beginning of the buffer, then actually do the signing stuff... */ |