From patchwork Thu Dec 4 15:19:48 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Hugues KAMBA MPIANA X-Patchwork-Id: 75894 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 309B9D21696 for ; Thu, 4 Dec 2025 15:25:17 +0000 (UTC) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.46097.1764861914255241626 for ; Thu, 04 Dec 2025 07:25:14 -0800 Authentication-Results: mx.groups.io; dkim=none (message not signed); spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: hugues.kambampiana@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 8CE841575; Thu, 4 Dec 2025 07:25:06 -0800 (PST) Received: from LXKV206JHX.arm.com (unknown [10.57.43.122]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 07EE33F59E; Thu, 4 Dec 2025 07:25:12 -0800 (PST) From: Hugues KAMBA MPIANA To: meta-arm@lists.yoctoproject.org Cc: Hugues KAMBA MPIANA , Michael Safwat , Frazer Carsley Subject: [PATCH 1/6] =?utf-8?q?machine/corstone1000=3A_Add_Cortex=E2=80=91A3?= =?utf-8?q?20_support?= Date: Thu, 4 Dec 2025 15:19:48 +0000 Message-ID: <20251204152500.78818-2-hugues.kambampiana@arm.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20251204152500.78818-1-hugues.kambampiana@arm.com> References: <20251204152500.78818-1-hugues.kambampiana@arm.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Thu, 04 Dec 2025 15:25:17 -0000 X-Groupsio-URL: https://lists.yoctoproject.org/g/meta-arm/message/6780 Enable the Corstone‑1000 Cortex‑A320 variant by: - Introduce `machine/include/corstone1000-a320.inc` to configure the default Ethos‑U MAC count when `cortexa320` is in MACHINE_FEATURES, and allow override via `ETHOSU_NUM_MACS`. - Add a KAS profile at `kas/corstone1000-a320.yml` for Cortex‑A320 FVP-based builds. - Extend corstone1000.inc to detect MACHINE_FEATURES (cortexa320) and pull in the matching tune-.inc (default still Cortex-A35). - Add the `meta-ethos` layer as a dependency of `meta-arm-bsp` for Cortex‑A320 builds and define a new KMachine override to pull in the Ethos‑U driver recipe. - In `conf/machine/corstone1000-fvp.conf`, inspect `MACHINE_FEATURES` and set `FVP_EXE` to `FVP_Corstone-1000_with_Cortex-A320` when `cortexa320` is enabled, otherwise fall back to `FVP_Corstone-1000`. - In `recipes-devtools/fvp/fvp-corstone1000.bb`, add a `SRC_URI:cortexa320` entry (with checksums) for the Cortex‑A320 FVP build archive. - Disable the rootfs CPIO file compression so it is not compressed twice when bundled with the kernel Signed-off-by: Michael Safwat Signed-off-by: Frazer Carsley Signed-off-by: Hugues KAMBA MPIANA --- kas/corstone1000-a320.yml | 17 +++++++++++++ meta-arm-bsp/conf/layer.conf | 1 + .../conf/machine/corstone1000-fvp.conf | 4 ++++ .../machine/include/corstone1000-a320.inc | 5 ++++ .../conf/machine/include/corstone1000.inc | 4 +++- .../linux/files/corstone1000/defconfig | 1 + .../linux/linux-arm-platforms.inc | 22 +++++++++++++++-- .../recipes-devtools/fvp/fvp-corstone1000.bb | 24 +++++++++++++++---- 8 files changed, 70 insertions(+), 8 deletions(-) create mode 100644 kas/corstone1000-a320.yml create mode 100644 meta-arm-bsp/conf/machine/include/corstone1000-a320.inc diff --git a/kas/corstone1000-a320.yml b/kas/corstone1000-a320.yml new file mode 100644 index 00000000..8a7739af --- /dev/null +++ b/kas/corstone1000-a320.yml @@ -0,0 +1,17 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/siemens/kas/master/kas/schema-kas.json + +header: + version: 14 + +local_conf_header: + a320: | + MACHINE_FEATURES += "cortexa320" + OVERRIDES .= ":cortexa320" + +repos: + meta-ethos: + url: https://gitlab.arm.com/iot/meta-ethos.git + branch: whinlatter + meta-sca: + url: https://github.com/priv-kweihmann/meta-sca.git + branch: master diff --git a/meta-arm-bsp/conf/layer.conf b/meta-arm-bsp/conf/layer.conf index 655a8c96..a06d27d9 100644 --- a/meta-arm-bsp/conf/layer.conf +++ b/meta-arm-bsp/conf/layer.conf @@ -14,6 +14,7 @@ LAYERSERIES_COMPAT_meta-arm-bsp = "walnascar whinlatter" LAYERDEPENDS_meta-arm-bsp = "core meta-arm" # This won't be used by layerindex-fetch, but works everywhere else LAYERDEPENDS_meta-arm-bsp:append:corstone1000 = " meta-python openembedded-layer efi-secure-boot" +LAYERDEPENDS_meta-arm-bsp:append:corstone1000:cortexa320 = " meta-ethos" LAYERDEPENDS_meta-arm-bsp:append:musca-b1 = " meta-python" LAYERDEPENDS_meta-arm-bsp:append:musca-s1 = " meta-python" diff --git a/meta-arm-bsp/conf/machine/corstone1000-fvp.conf b/meta-arm-bsp/conf/machine/corstone1000-fvp.conf index c951de68..9fa2a63d 100644 --- a/meta-arm-bsp/conf/machine/corstone1000-fvp.conf +++ b/meta-arm-bsp/conf/machine/corstone1000-fvp.conf @@ -6,6 +6,9 @@ require conf/machine/include/corstone1000.inc require ${@bb.utils.contains('MACHINE_FEATURES', 'corstone1000-extsys', \ 'conf/machine/include/corstone1000-extsys.inc', '', d)} +require ${@bb.utils.contains('MACHINE_FEATURES', 'cortexa320', \ + 'conf/machine/include/corstone1000-a320.inc', '', d)} + TFA_TARGET_PLATFORM = "fvp" TFM_PLATFORM_IS_FVP = "TRUE" @@ -20,6 +23,7 @@ DEFAULT_TEST_SUITES:append = " fvp_boot fvp_devices" # FVP Config FVP_PROVIDER ?= "fvp-corstone1000-native" FVP_EXE ?= "FVP_Corstone-1000" +FVP_EXE:cortexa320 = "FVP_Corstone-1000-A320" FVP_CONSOLES[default] = "host_terminal_0" FVP_CONSOLES[tf-a] = "host_terminal_1" FVP_CONSOLES[se] = "secenc_terminal" diff --git a/meta-arm-bsp/conf/machine/include/corstone1000-a320.inc b/meta-arm-bsp/conf/machine/include/corstone1000-a320.inc new file mode 100644 index 00000000..c7ff2df7 --- /dev/null +++ b/meta-arm-bsp/conf/machine/include/corstone1000-a320.inc @@ -0,0 +1,5 @@ +ETHOSU_NUM_MACS ?= "256" + +FVP_CONFIG[host.ethosu.num_macs] = "${ETHOSU_NUM_MACS}" + +IMAGE_INSTALL:append = " arm-npu-ethosu" diff --git a/meta-arm-bsp/conf/machine/include/corstone1000.inc b/meta-arm-bsp/conf/machine/include/corstone1000.inc index 6027b633..09468c7c 100644 --- a/meta-arm-bsp/conf/machine/include/corstone1000.inc +++ b/meta-arm-bsp/conf/machine/include/corstone1000.inc @@ -1,4 +1,6 @@ -require conf/machine/include/arm/armv8a/tune-cortexa35.inc +TUNE_FILE = "conf/machine/include/arm/armv8a/tune-cortexa35.inc" +TUNE_FILE:cortexa320 = "conf/machine/include/arm/arch-armv9-2a.inc" +require ${TUNE_FILE} MACHINEOVERRIDES =. "corstone1000:" diff --git a/meta-arm-bsp/recipes-kernel/linux/files/corstone1000/defconfig b/meta-arm-bsp/recipes-kernel/linux/files/corstone1000/defconfig index d67e9484..bf4be697 100644 --- a/meta-arm-bsp/recipes-kernel/linux/files/corstone1000/defconfig +++ b/meta-arm-bsp/recipes-kernel/linux/files/corstone1000/defconfig @@ -122,3 +122,4 @@ CONFIG_EXT4_FS=y # CONFIG_EXT4_FS_POSIX_ACL is not set # CONFIG_EXT4_FS_SECURITY is not set # CONFIG_EXT4_DEBUG is not set +CONFIG_INITRAMFS_COMPRESSION_NONE=y diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc b/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc index 8e964e17..ff19169e 100644 --- a/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc +++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc @@ -24,8 +24,6 @@ COMPATIBLE_MACHINE:corstone1000 = "${MACHINE}" KCONFIG_MODE:corstone1000 = "--alldefconfig" KMACHINE:corstone1000 = "corstone1000" LINUX_KERNEL_TYPE:corstone1000 = "standard" -#disabling the rootfs cpio file compression so it is not compressed twice when bundled with the kernel -KERNEL_EXTRA_ARGS:corstone1000 += "CONFIG_INITRAMFS_COMPRESSION_NONE=y" SRC_URI:append:corstone1000 = " \ file://defconfig \ " @@ -57,6 +55,26 @@ SRC_URI:append:corstone1000 = " \ KERNEL_EXTRA_FEATURES:corstone1000 = "" KERNEL_FEATURES:corstone1000 = "" +# +# Corstone1000 with CORTEX-A320 KMACHINE +# +FILESEXTRAPATHS:prepend:cortexa320 := "${ARMBSPFILESPATHS}" +COMPATIBLE_MACHINE:corstone1000:cortexa320 = "${MACHINE}" +KCONFIG_MODE:corstone1000:cortexa320 = "--alldefconfig" +KMACHINE:corstone1000:cortexa320 = "corstone1000-a320" +LINUX_KERNEL_TYPE:corstone1000:cortexa320 = "standard" +SRC_URI:append:corstone1000:cortexa320 = " \ + file://defconfig \ +" + +# Default kernel features not needed for Corstone-1000 with +# Cortex-A320; otherwise the extra kernel modules will +# increase the rootfs size but the board has limited flash +# memory constraints +KERNEL_EXTRA_FEATURES:corstone1000:cortexa320 = "" +KERNEL_FEATURES:corstone1000:cortexa320 = "" + + # # FVP BASE KMACHINE # diff --git a/meta-arm/recipes-devtools/fvp/fvp-corstone1000.bb b/meta-arm/recipes-devtools/fvp/fvp-corstone1000.bb index e200d94c..1cf8a457 100644 --- a/meta-arm/recipes-devtools/fvp/fvp-corstone1000.bb +++ b/meta-arm/recipes-devtools/fvp/fvp-corstone1000.bb @@ -1,17 +1,31 @@ require fvp-ecosystem.inc MODEL = "Corstone-1000" +MODEL:cortexa320 = "Corstone-1000-with-Cortex-A320" MODEL_CODE = "FVP_Corstone_1000" +MODEL_CODE:cortexa320 = "FVP_Corstone_1000-A320" PV = "11.23.25" +PV:cortexa320 = "11.30.27" + +FVP_AARCH64_SHA256SUM = "e299e81d5fa8b3d2afee0850fd03be31c1a1c3fad07f79849c63e46ee5e36acc" +FVP_AARCH64_SHA256SUM:cortexa320 = "a45898fead5549779153263c3544fa1032c285d532275eb678f58cae3317b01f" +FVP_X86_64_SHA256SUM = "ec34c9564ccb5b1eb62fc2757673343a353db1d116a7cb1b5f82f9d985d99cdf" +FVP_X86_64_SHA256SUM:cortexa320 = "d57b248a1c1bc5a6040605d50af94a5151adc4da26ec9acc456ec86b819ffb76" + +SRC_URI = "https://developer.arm.com/-/cdn-downloads/permalink/FVPs-Corstone-IoT/${MODEL}/${MODEL_CODE}_${PV_URL}_${FVP_ARCH}.tgz;subdir=${BP};name=fvp-${HOST_ARCH}" +SRC_URI[fvp-aarch64.sha256sum] = "${FVP_AARCH64_SHA256SUM}" +SRC_URI[fvp-x86_64.sha256sum] = "${FVP_X86_64_SHA256SUM}" -SRC_URI = "https://developer.arm.com/-/media/Arm%20Developer%20Community/Downloads/OSS/FVP/${MODEL}/${MODEL_CODE}_${PV_URL}_${FVP_ARCH}.tgz;subdir=${BP};name=fvp-${HOST_ARCH}" -SRC_URI[fvp-aarch64.sha256sum] = "e299e81d5fa8b3d2afee0850fd03be31c1a1c3fad07f79849c63e46ee5e36acc" -SRC_URI[fvp-x86_64.sha256sum] = "ec34c9564ccb5b1eb62fc2757673343a353db1d116a7cb1b5f82f9d985d99cdf" # The CSS used in the FVP homepage make it too difficult to query with the tooling currently in Yocto UPSTREAM_VERSION_UNKNOWN = "1" -LIC_FILES_CHKSUM = "file://license_terms/license_agreement.txt;md5=1a33828e132ba71861c11688dbb0bd16 \ - file://license_terms/third_party_licenses/third_party_licenses.txt;md5=0c32ac6f58ebff83065105042ab98211" +LIC_FILES_CHKSUM_MD5 = "0c32ac6f58ebff83065105042ab98211" +LIC_FILES_CHKSUM_MD5:cortexa320 = "a5ce56e117d0ab63791fbb7c35ec2211" + +LIC_FILES_CHKSUM = "\ + file://license_terms/license_agreement.txt;md5=1a33828e132ba71861c11688dbb0bd16 \ + file://license_terms/third_party_licenses/third_party_licenses.txt;md5=${LIC_FILES_CHKSUM_MD5} \ +" COMPATIBLE_HOST = "(aarch64|x86_64).*-linux" From patchwork Thu Dec 4 15:19:49 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Hugues KAMBA MPIANA X-Patchwork-Id: 75896 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3E316D21697 for ; Thu, 4 Dec 2025 15:25:17 +0000 (UTC) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.46100.1764861915523256825 for ; Thu, 04 Dec 2025 07:25:15 -0800 Authentication-Results: mx.groups.io; dkim=none (message not signed); spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: hugues.kambampiana@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 99DB3339; Thu, 4 Dec 2025 07:25:07 -0800 (PST) Received: from LXKV206JHX.arm.com (unknown [10.57.43.122]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 3BDCA3F59E; Thu, 4 Dec 2025 07:25:14 -0800 (PST) From: Hugues KAMBA MPIANA To: meta-arm@lists.yoctoproject.org Cc: Hugues KAMBA MPIANA , Harsimran Singh Tungal Subject: [PATCH 2/6] arm-bsp/optee-os:corstone1000: Add Cortex-A320 support Date: Thu, 4 Dec 2025 15:19:49 +0000 Message-ID: <20251204152500.78818-3-hugues.kambampiana@arm.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20251204152500.78818-1-hugues.kambampiana@arm.com> References: <20251204152500.78818-1-hugues.kambampiana@arm.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Thu, 04 Dec 2025 15:25:17 -0000 X-Groupsio-URL: https://lists.yoctoproject.org/g/meta-arm/message/6781 Update the OP-TEE OS build logic to detect `MACHINE_FEATURES` and append the appropriate `arm64-platform-cpuarch` value to `EXTRA_OEMAKE`, instead of hard-coding `cortex-a35`. This change ensures that when `MACHINE_FEATURES` includes `cortexa320`, the OP-TEE build receives the matching `core-arch` flag, while maintaining `cortex-a35` as the default. The new Corstone-1000 variant with Cortex-A320 replaces the original GIC-400 (v2) interrupt controller with a GIC-600, which is architecturally compliant with GICv3. Since OP-TEE already provides a generic GICv3 driver, only minimal platform changes are needed to expose the updated register map and initialize the GICv3 interface. Signed-off-by: Hugues KAMBA MPIANA Signed-off-by: Harsimran Singh Tungal --- ...corstone1000-Add-Cortex-A320-support.patch | 143 ++++++++++++++++++ .../optee/optee-os-corstone1000-common.inc | 9 ++ 2 files changed, 152 insertions(+) create mode 100644 meta-arm-bsp/recipes-security/optee/files/optee-os/corstone1000/0001-plat-corstone1000-Add-Cortex-A320-support.patch diff --git a/meta-arm-bsp/recipes-security/optee/files/optee-os/corstone1000/0001-plat-corstone1000-Add-Cortex-A320-support.patch b/meta-arm-bsp/recipes-security/optee/files/optee-os/corstone1000/0001-plat-corstone1000-Add-Cortex-A320-support.patch new file mode 100644 index 00000000..4d4847a5 --- /dev/null +++ b/meta-arm-bsp/recipes-security/optee/files/optee-os/corstone1000/0001-plat-corstone1000-Add-Cortex-A320-support.patch @@ -0,0 +1,143 @@ +From 4a8fa965a39879d98eac1626c4c756043985726d Mon Sep 17 00:00:00 2001 +From: Hugues KAMBA MPIANA +Date: Tue, 11 Nov 2025 08:09:40 +0000 +Subject: [PATCH] plat-corstone1000: Add Cortex-A320 support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Convert arm64-platform-cpuarch from a hard-coded cortex-a35 into a “?=” +(default) assignment so users can override it (for example to +cortex-a320) via the make command line. + +The Cortex-A320 core is not yet supported via -mcpu=cortex-a320. +When arm64-platform-cpuarch is set to cortex-a320, switch to +-march=armv9.2-a. + +The new Corstone-1000 variant with Cortex-A320 replaces the original +GIC-400 (v2) interrupt controller with a GIC-600, which is +architecturally compliant with GICv3. Since OP-TEE already provides +a generic GICv3 driver, only minimal platform changes are needed +to expose the updated register map and initialize the GICv3 interface. + +**Changes introduced** + +* When `cortex-a320` is selected: + * Force `CFG_ARM_GICV3=y`. + * Introduce `CFG_CORSTONE1000_CORTEX_A320` to guard + Cortex-A320–specific code. +* Map the Redistributor region (`GICR_BASE`). +* Use `gic_init_v3(…)` instead of the v2 helper for Cortex-A320 builds. +* Add `GICR_BASE`, `GIC_REDIST_REG_SIZE`, and related offsets. +* Retain legacy `GICC_BASE` definitions under the GICv2 path so that + the Cortex-A35 + GIC-400 variant continues to build unchanged. + +Upstream-Status: Submitted (https://github.com/OP-TEE/optee_os/pull/7627) +Signed-off-by: Hugues KAMBA MPIANA +Signed-off-by: Harsimran Singh Tungal +--- + core/arch/arm/plat-corstone1000/conf.mk | 11 ++++++++++- + core/arch/arm/plat-corstone1000/main.c | 11 ++++++++++- + .../arm/plat-corstone1000/platform_config.h | 19 +++++++++++++++++-- + 3 files changed, 37 insertions(+), 4 deletions(-) + +diff --git a/core/arch/arm/plat-corstone1000/conf.mk b/core/arch/arm/plat-corstone1000/conf.mk +index 86b8d8480..147b6972f 100644 +--- a/core/arch/arm/plat-corstone1000/conf.mk ++++ b/core/arch/arm/plat-corstone1000/conf.mk +@@ -23,9 +23,18 @@ $(call force,CFG_PL011,y) + $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) + $(call force,CFG_ARM64_core,y) + +-arm64-platform-cpuarch := cortex-a35 ++# Default CPU core for Corstone1000 platform; override for other cores (e.g. cortex-a320) ++arm64-platform-cpuarch ?= cortex-a35 ++ ++ifeq ($(arm64-platform-cpuarch),cortex-a320) ++arm64-platform-cflags += -march=armv9.2-a ++arm64-platform-aflags += -march=armv9.2-a ++$(call force,CFG_ARM_GICV3,y) ++$(call force,CFG_CORSTONE1000_CORTEX_A320,y) ++else + arm64-platform-cflags += -mcpu=$(arm64-platform-cpuarch) + arm64-platform-aflags += -mcpu=$(arm64-platform-cpuarch) ++endif + + CFG_WITH_STATS ?= y + CFG_WITH_ARM_TRUSTED_FW ?= y +diff --git a/core/arch/arm/plat-corstone1000/main.c b/core/arch/arm/plat-corstone1000/main.c +index 9e1482a7b..fd2dd888c 100644 +--- a/core/arch/arm/plat-corstone1000/main.c ++++ b/core/arch/arm/plat-corstone1000/main.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: BSD-2-Clause + /* +- * Copyright (c) 2022, Arm Limited ++ * Copyright (c) 2022, 2025, Arm Limited + */ + + #include +@@ -18,11 +18,20 @@ register_ddr(DRAM0_BASE, DRAM0_SIZE); + + register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, PL011_REG_SIZE); + register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, GIC_DIST_REG_SIZE); ++ ++#if defined(CFG_CORSTONE1000_CORTEX_A320) && defined(CFG_ARM_GICV3) ++register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICR_BASE, GIC_REDIST_REG_SIZE); ++#else + register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICC_BASE, GIC_CPU_REG_SIZE); ++#endif + + void boot_primary_init_intc(void) + { ++#if defined(CFG_CORSTONE1000_CORTEX_A320) && defined(CFG_ARM_GICV3) ++ gic_init_v3(0, GICD_BASE, GICR_BASE); ++#else + gic_init(GICC_BASE, GICD_BASE); ++#endif + } + + void boot_secondary_init_intc(void) +diff --git a/core/arch/arm/plat-corstone1000/platform_config.h b/core/arch/arm/plat-corstone1000/platform_config.h +index f59c93a14..600b2c02e 100644 +--- a/core/arch/arm/plat-corstone1000/platform_config.h ++++ b/core/arch/arm/plat-corstone1000/platform_config.h +@@ -1,6 +1,6 @@ + /* SPDX-License-Identifier: BSD-2-Clause */ + /* +- * Copyright (c) 2022, Arm Limited ++ * Copyright (c) 2022, 2025 Arm Limited + */ + + #ifndef PLATFORM_CONFIG_H +@@ -20,11 +20,26 @@ + #define DRAM0_BASE 0x80000000 + #define DRAM0_SIZE CFG_DDR_SIZE + ++#if defined(CFG_CORSTONE1000_CORTEX_A320) && defined(CFG_ARM_GICV3) ++#define GICR_SIZE_PER_CORE 0x20000 ++#define GIC_REDIST_REG_SIZE (GICR_SIZE_PER_CORE * CFG_TEE_CORE_NB_CORE) ++#endif ++ ++#if defined(CFG_CORSTONE1000_CORTEX_A320) && defined(CFG_ARM_GICV3) ++/* Corstone-1000 with Cortex-A320 uses GIC-v3 which supports GICR */ ++#define GICD_OFFSET 0x00000 ++#define GICR_OFFSET 0x40000 ++#else + #define GICD_OFFSET 0x10000 + #define GICC_OFFSET 0x2F000 ++#endif + +-#define GICD_BASE (GIC_BASE + GICD_OFFSET) ++#if defined(CFG_CORSTONE1000_CORTEX_A320) && defined(CFG_ARM_GICV3) ++#define GICR_BASE (GIC_BASE + GICR_OFFSET) ++#else + #define GICC_BASE (GIC_BASE + GICC_OFFSET) ++#endif ++#define GICD_BASE (GIC_BASE + GICD_OFFSET) + + #define UART_BAUDRATE 115200 + #define CONSOLE_BAUDRATE UART_BAUDRATE +-- +2.50.1 + diff --git a/meta-arm-bsp/recipes-security/optee/optee-os-corstone1000-common.inc b/meta-arm-bsp/recipes-security/optee/optee-os-corstone1000-common.inc index 7e849c45..028027f5 100644 --- a/meta-arm-bsp/recipes-security/optee/optee-os-corstone1000-common.inc +++ b/meta-arm-bsp/recipes-security/optee/optee-os-corstone1000-common.inc @@ -1,5 +1,9 @@ FILESEXTRAPATHS:prepend := "${THISDIR}/files/optee-os/corstone1000:" +SRC_URI:append = " \ + file://0001-plat-corstone1000-Add-Cortex-A320-support.patch \ +" + COMPATIBLE_MACHINE = "corstone1000" OPTEEMACHINE = "corstone1000" @@ -14,3 +18,8 @@ EXTRA_OEMAKE += " CFG_CORE_SEL1_SPMC=y CFG_CORE_FFA=y" EXTRA_OEMAKE += " CFG_WITH_SP=y" EXTRA_OEMAKE:append:corstone1000-fvp = "${@bb.utils.contains('MACHINE_FEATURES', 'corstone1000_fvp_smp', ' CFG_TEE_CORE_NB_CORE=4', '', d)}" + +# Override OP-TEE OS ARM64 core architecture based on MACHINE_FEATURES +CPUARCH = "cortex-a35" +CPUARCH:cortexa320 = "cortex-a320" +EXTRA_OEMAKE:append:corstone1000 = " arm64-platform-cpuarch=${CPUARCH}" From patchwork Thu Dec 4 15:19:50 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Hugues KAMBA MPIANA X-Patchwork-Id: 75895 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2EF1AD21695 for ; Thu, 4 Dec 2025 15:25:17 +0000 (UTC) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.46101.1764861916302605805 for ; Thu, 04 Dec 2025 07:25:16 -0800 Authentication-Results: mx.groups.io; dkim=none (message not signed); spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: hugues.kambampiana@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 628371762; Thu, 4 Dec 2025 07:25:08 -0800 (PST) Received: from LXKV206JHX.arm.com (unknown [10.57.43.122]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 493253F59E; Thu, 4 Dec 2025 07:25:15 -0800 (PST) From: Hugues KAMBA MPIANA To: meta-arm@lists.yoctoproject.org Cc: Harsimran Singh Tungal Subject: [PATCH 3/6] arm-bsp/tf-m:corstone1000: Add Cortex-A320 support Date: Thu, 4 Dec 2025 15:19:50 +0000 Message-ID: <20251204152500.78818-4-hugues.kambampiana@arm.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20251204152500.78818-1-hugues.kambampiana@arm.com> References: <20251204152500.78818-1-hugues.kambampiana@arm.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Thu, 04 Dec 2025 15:25:17 -0000 X-Groupsio-URL: https://lists.yoctoproject.org/g/meta-arm/message/6782 From: Harsimran Singh Tungal Enable full Corstone‑1000 Cortex‑A320 DSU‑120T platform support in TF‑M: - Reserve a 4 MiB Host SRAM region at 0x0240_0000 for the Cortex‑A320 normal world and open it in the CVM firewall (region 2), gated by `CORSTONE1000_CORTEX_A320``. - Introduce a DSU‑120T Power-Policy Unit driver plus a `CORSTONE1000_DSU_120T` CMake option to power on the Cortex‑A320 host cluster with proper secure-enclave firewall and memory-map setup. - Add a CMake platform define that auto‑activates when the `cortexa320` machine feature is present, injecting DSU‑120T‑specific compile definitions. Signed-off-by: Harsimran Singh Tungal --- ...0-Add-support-for-Cortex-A320-varian.patch | 490 ++++++++++++++++++ .../trusted-firmware-m-corstone1000.inc | 9 + 2 files changed, 499 insertions(+) create mode 100644 meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0010-plat-corstone1000-Add-support-for-Cortex-A320-varian.patch diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0010-plat-corstone1000-Add-support-for-Cortex-A320-varian.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0010-plat-corstone1000-Add-support-for-Cortex-A320-varian.patch new file mode 100644 index 00000000..1792474b --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0010-plat-corstone1000-Add-support-for-Cortex-A320-varian.patch @@ -0,0 +1,490 @@ +From 2f09a03bc8396164c8075ac802751b6150b8a6c0 Mon Sep 17 00:00:00 2001 +From: Harsimran Singh Tungal +Date: Tue, 29 Jul 2025 15:09:45 +0000 +Subject: [PATCH] plat: corstone1000: Add support for Cortex-A320 variant +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add support for powering on the Cortex-A320 host in the DSU-120T +cluster and reserve Host SRAM for the normal world on the +Corstone-1000 platform. These changes enable secure-enclave firmware +control of the Cortex-A320 power domain and memory access +configuration. + +**DSU-120T Power-Policy Unit (PPU) driver** + +* Introduce a minimal driver to program the DSU-120T Power-Policy + Units, allowing the secure-enclave firmware to bring the + Cortex-A320 host cluster out of reset. +* The DSU utility-bus registers are located at: + * `0x6091_0000` in the Host memory map. + * `0xC091_0000` in the Secure-Enclave memory map. +* The FC1 firewall is configured so that only the Secure Enclave may + write to this window. +* Add new CMake option `CORSTONE1000_DSU_120T` and platform define to + enable Cortex-A320 DSU-120T–specific code. + +**Host SRAM allocation** + +* Reserve a 4 MiB block of Host SRAM at `0x0240_0000` for the + Cortex-A320 normal world. +* Open the same region in the Host-side firewall (CVM, region 2) + to allow non-secure access. +* This configuration is compiled in when `CORSTONE1000_CORTEX_A320` + is defined. + +These updates prepare the Corstone-1000 platform for Cortex-A320 +integration with proper cluster power management and normal-world +memory accessibility. + +Upstream-Status: Submitted (https://review.trustedfirmware.org/c/TF-M/trusted-firmware-m/+/45749) +Signed-off-by: Harsimran Singh Tungal +--- + .../target/arm/corstone1000/CMakeLists.txt | 31 +++ + .../Device/Include/platform_base_address.h | 8 +- + .../arm/corstone1000/bl1/boot_hal_bl1_1.c | 50 ++++- + .../target/arm/corstone1000/dsu-120t/ppu.c | 40 ++++ + .../target/arm/corstone1000/dsu-120t/ppu.h | 185 ++++++++++++++++++ + .../arm/corstone1000/tfm_hal_multi_core.c | 28 ++- + 6 files changed, 339 insertions(+), 3 deletions(-) + create mode 100644 platform/ext/target/arm/corstone1000/dsu-120t/ppu.c + create mode 100644 platform/ext/target/arm/corstone1000/dsu-120t/ppu.h + +diff --git a/platform/ext/target/arm/corstone1000/CMakeLists.txt b/platform/ext/target/arm/corstone1000/CMakeLists.txt +index 91bf197d8..993c51591 100644 +--- a/platform/ext/target/arm/corstone1000/CMakeLists.txt ++++ b/platform/ext/target/arm/corstone1000/CMakeLists.txt +@@ -423,6 +423,37 @@ target_sources(tfm_spm + $<$:${CMAKE_CURRENT_SOURCE_DIR}/target_cfg.c> + ) + ++#========================= DSU-120T ============================================# ++if (CORSTONE1000_DSU_120T) ++ target_sources(tfm_psa_rot_partition_ns_agent_mailbox ++ PUBLIC ++ dsu-120t/ppu.c ++ ) ++ ++ target_compile_definitions(tfm_psa_rot_partition_ns_agent_mailbox ++ PUBLIC ++ CORSTONE1000_DSU_120T ++ ) ++ ++ target_compile_definitions(platform_bl1_1 ++ PUBLIC ++ CORSTONE1000_DSU_120T ++ ) ++ ++ target_include_directories(tfm_psa_rot_partition_ns_agent_mailbox ++ PUBLIC ++ dsu-120t ++ ) ++endif() ++ ++#========================= Ethos-U NPU =========================================# ++if (CORSTONE1000_CORTEX_A320) ++ target_compile_definitions(platform_bl1_1 ++ PUBLIC ++ CORSTONE1000_CORTEX_A320 ++ ) ++endif() ++ + #========================= tfm_adac ============================================# + + if (${PLATFORM_PSA_ADAC_SECURE_DEBUG}) +diff --git a/platform/ext/target/arm/corstone1000/Device/Include/platform_base_address.h b/platform/ext/target/arm/corstone1000/Device/Include/platform_base_address.h +index 5f9f03ddc..3908d69bc 100644 +--- a/platform/ext/target/arm/corstone1000/Device/Include/platform_base_address.h ++++ b/platform/ext/target/arm/corstone1000/Device/Include/platform_base_address.h +@@ -1,5 +1,7 @@ + /* +- * Copyright (c) 2017-2024 Arm Limited. All rights reserved. ++ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors ++ * ++ * SPDX-License-Identifier: BSD-3-Clause + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. +@@ -79,6 +81,10 @@ + #define CORSTONE1000_HOST_AXI_QSPI_CTRL_REG_BASE_SE_SECURE_FLASH (0x90010000U) /* AXI QSPI Controller for SE FLash */ + #define CORSTONE1000_HOST_DRAM_UEFI_CAPSULE (0xA0000000U) /* 1.5 GB DDR */ + ++#ifdef CORSTONE1000_DSU_120T ++#define CORSTONE1000_HOST_DSU_120T_BASE (0xC0910000U) /* DSU-120T PPU */ ++#endif ++ + /* Map Component definitions to Corstone definitions */ + #define CC3XX_BASE_S CORSTONE1000_CRYPTO_ACCELERATOR_BASE + +diff --git a/platform/ext/target/arm/corstone1000/bl1/boot_hal_bl1_1.c b/platform/ext/target/arm/corstone1000/bl1/boot_hal_bl1_1.c +index b51a233e9..1a5e98ad3 100644 +--- a/platform/ext/target/arm/corstone1000/bl1/boot_hal_bl1_1.c ++++ b/platform/ext/target/arm/corstone1000/bl1/boot_hal_bl1_1.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2019-2024, Arm Limited. All rights reserved. ++ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors + * + * SPDX-License-Identifier: BSD-3-Clause + * +@@ -48,6 +48,15 @@ REGION_DECLARE(Image$$, ARM_LIB_HEAP, $$ZI$$Limit)[]; + #define HOST_SE_SECURE_FLASH_BASE_FVP 0x60010000 + #define HOST_AXI_QSPI_CTRL_REG_BASE_SE_SECURE_FLASH 0x60010000 + ++#ifdef CORSTONE1000_DSU_120T ++#define HOST_DSU_120T_BASE 0x60910000 ++#endif ++ ++#ifdef CORSTONE1000_CORTEX_A320 ++#define HOST_SECURE_SRAM_SIZE 0x400000 ++#define HOST_NONSECURE_SRAM_BASE (HOST_TRUSTED_RAM_BASE + HOST_SECURE_SRAM_SIZE) ++#endif ++ + #define HOST_DRAM_BASE 0x80000000 + #define HOST_DRAM_UEFI_CAPSULE 0x80000000 + +@@ -286,6 +295,25 @@ static void setup_se_firewall(void) + fc_enable_regions(); + #endif + ++#ifdef CORSTONE1000_DSU_120T ++#if (PLATFORM_IS_FVP) ++ fc_select_region(7); ++ fc_disable_regions(); ++ fc_disable_mpe(RGN_MPE0); ++ fc_prog_rgn(RGN_SIZE_16MB, CORSTONE1000_HOST_DSU_120T_BASE); ++ fc_prog_rgn_upper_addr(HOST_DSU_120T_BASE); ++ fc_enable_addr_trans(); ++ fc_init_mpl(RGN_MPE0); ++ ++ mpl_rights = (RGN_MPL_SECURE_READ_MASK | ++ RGN_MPL_SECURE_WRITE_MASK); ++ ++ fc_enable_mpl(RGN_MPE0, mpl_rights); ++ fc_prog_mid(RGN_MPE0, SE_MID); ++ fc_enable_mpe(RGN_MPE0); ++ fc_enable_regions(); ++#endif ++#endif + fc_pe_enable(); + } + +@@ -369,6 +397,26 @@ static void setup_host_firewall(void) + fc_enable_regions(); + fc_rgn_lock(); + ++#ifdef CORSTONE1000_CORTEX_A320 ++ /* CVM - Non Secure RAM */ ++ fc_select_region(2); ++ fc_disable_regions(); ++ fc_disable_mpe(RGN_MPE0); ++ fc_prog_rgn(RGN_SIZE_4MB, HOST_NONSECURE_SRAM_BASE); ++ fc_init_mpl(RGN_MPE0); ++ ++ mpl_rights = (RGN_MPL_ANY_MST_MASK | RGN_MPL_NONSECURE_READ_MASK | ++ RGN_MPL_NONSECURE_WRITE_MASK | ++ RGN_MPL_NONSECURE_EXECUTE_MASK); ++ ++ fc_enable_mpl(RGN_MPE0, mpl_rights); ++ fc_disable_mpl(RGN_MPE0, ~mpl_rights); ++ ++ fc_enable_mpe(RGN_MPE0); ++ fc_enable_regions(); ++ fc_rgn_lock(); ++#endif ++ + fc_pe_enable(); + + /* DDR */ +diff --git a/platform/ext/target/arm/corstone1000/dsu-120t/ppu.c b/platform/ext/target/arm/corstone1000/dsu-120t/ppu.c +new file mode 100644 +index 000000000..d6be5982a +--- /dev/null ++++ b/platform/ext/target/arm/corstone1000/dsu-120t/ppu.c +@@ -0,0 +1,40 @@ ++/* ++ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ * ++ */ ++ ++#include ++#include "ppu.h" ++ ++void PPU_SetPowerPolicy(PPU_TypeDef *ppu, PPU_PowerPolicy_Type policy, bool isDynamic) ++{ ++ uint32_t regval = ppu->PWPR; ++ ++ regval &= ~(PPU_PWPR_PWR_POLICY_Msk | PPU_PWPR_PWR_DYN_EN_Msk); ++ ++ regval |= ((policy << PPU_PWPR_PWR_POLICY_Pos) & PPU_PWPR_PWR_POLICY_Msk); ++ ++ if (isDynamic) { ++ regval |= PPU_PWPR_PWR_DYN_EN_Msk; ++ } ++ ++ ppu->PWPR = regval; ++} ++ ++void PPU_SetOperatingPolicy(PPU_TypeDef *ppu, PPU_OperatingPolicy_Type policy, bool isDynamic) ++{ ++ uint32_t regval = ppu->PWPR; ++ ++ regval &= ~(PPU_PWPR_OP_POLICY_Msk | PPU_PWPR_OP_DYN_EN_Msk); ++ ++ regval |= ((policy << PPU_PWPR_OP_POLICY_Pos) & PPU_PWPR_OP_POLICY_Msk); ++ ++ if (isDynamic) { ++ regval |= PPU_PWPR_OP_DYN_EN_Msk; ++ } ++ ++ ppu->PWPR = regval; ++} ++ +diff --git a/platform/ext/target/arm/corstone1000/dsu-120t/ppu.h b/platform/ext/target/arm/corstone1000/dsu-120t/ppu.h +new file mode 100644 +index 000000000..05470df9a +--- /dev/null ++++ b/platform/ext/target/arm/corstone1000/dsu-120t/ppu.h +@@ -0,0 +1,185 @@ ++/* ++ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ * ++ */ ++#ifndef PPU_H ++#define PPU_H ++ ++#include ++#include ++#include "platform_base_address.h" ++ ++// Bit definition for PPU_PWPR register ++#define PPU_PWPR_PWR_POLICY_Pos (0U) // Power mode policy ++#define PPU_PWPR_PWR_POLICY_Msk (0xFUL << PPU_PWPR_PWR_POLICY_Pos) // 4 bits ++#define PPU_PWPR_PWR_POLICY_OFF (0UL << PPU_PWPR_PWR_POLICY_Pos) // Logic off and RAM off. ++#define PPU_PWPR_PWR_POLICY_OFF_EMU (1UL << PPU_PWPR_PWR_POLICY_Pos) // Emulated Off. Logic on with RAM on. This mode is used to emulate the functional condition of OFF without removing ++#define PPU_PWPR_PWR_POLICY_MEM_RET (2UL << PPU_PWPR_PWR_POLICY_Pos) // Memory Retention. Logic off with RAM retained. ++#define PPU_PWPR_PWR_POLICY_MEM_RET_EMU (3UL << PPU_PWPR_PWR_POLICY_Pos) // Emulated Memory Retention. Logic on with RAM on. This mode is used to emulate the functional condition of ++#define PPU_PWPR_PWR_POLICY_FULL_RET (5UL << PPU_PWPR_PWR_POLICY_Pos) // Full Retention. Slice logic off with RAM contents retained. ++#define PPU_PWPR_PWR_POLICY_FUNC_RET (7UL << PPU_PWPR_PWR_POLICY_Pos) // Functional Retention. Logic on with L3 Cache and Snoop Filter retained. ++#define PPU_PWPR_PWR_POLICY_ON (8UL << PPU_PWPR_PWR_POLICY_Pos) // Logic on with RAM on, cluster is functional. ++#define PPU_PWPR_PWR_POLICY_WARM_RST (9UL << PPU_PWPR_PWR_POLICY_Pos) // Warm Reset. Warm reset application with logic and RAM on. ++#define PPU_PWPR_PWR_POLICY_DBG_RECOV (10UL << PPU_PWPR_PWR_POLICY_Pos) // Debug Recovery Reset. Warm reset application with logic and RAM on. ++#define PPU_PWPR_PWR_DYN_EN_Pos (8U) // Power mode dynamic transition enable. ++#define PPU_PWPR_PWR_DYN_EN_Msk (0x1UL << PPU_PWPR_PWR_DYN_EN_Pos) // 1 bit ++#define PPU_PWPR_LOCK_EN_Pos (12U) // Lock enable bit for OFF, OFF_EMU, MEM_RET and MEM_RET_EMU power modes. ++#define PPU_PWPR_LOCK_EN_Msk (0x1UL << PPU_PWPR_LOCK_EN_Pos) // 1 bit ++#define PPU_PWPR_OP_POLICY_Pos (16U) // Operating mode policy ++#define PPU_PWPR_OP_POLICY_Msk (0xFUL << PPU_PWPR_OP_POLICY_Pos) // 4 bits ++#define PPU_PWPR_OP_POLICY_OPMODE_00 (0UL << PPU_PWPR_OP_POLICY_Pos) // ONE_SLICE_SF_ONLY_ON: One L3 Cache slice is operational, the Cache RAM is powered down. ++#define PPU_PWPR_OP_POLICY_OPMODE_01 (1UL << PPU_PWPR_OP_POLICY_Pos) // ONE_SLICE_HALF_RAM_ON: One L3 Cache slice is operational, half of the Cache RAMs are powered on. ++#define PPU_PWPR_OP_POLICY_OPMODE_03 (3UL << PPU_PWPR_OP_POLICY_Pos) // ONE_SLICE_FULL_RAM_ON: One L3 Cache slice is operational, all of the Cache RAMs are powered on. ++#define PPU_PWPR_OP_POLICY_OPMODE_04 (4UL << PPU_PWPR_OP_POLICY_Pos) // ALL_SLICE_SF_ONLY_ON: All L3 Cache slices are operational, the Cache RAMs in each slice are powered down. ++#define PPU_PWPR_OP_POLICY_OPMODE_05 (5UL << PPU_PWPR_OP_POLICY_Pos) // ALL_SLICE_HALF_RAM_ON: All L3 Cache slices are operational, half of the Cache RAMs are powered on. ++#define PPU_PWPR_OP_POLICY_OPMODE_07 (7UL << PPU_PWPR_OP_POLICY_Pos) // ALL_SLICE_FULL_RAM_ON: All L3 Cache slices are operational, all of the Cache RAMs are powered on. ++#define PPU_PWPR_OP_POLICY_OPMODE_08 (8UL << PPU_PWPR_OP_POLICY_Pos) // HALF_SLICE_SF_ONLY_ON: Half L3 Cache slices are operational, the Cache RAMs in each slice are powered down. ++#define PPU_PWPR_OP_POLICY_OPMODE_09 (9UL << PPU_PWPR_OP_POLICY_Pos) // HALF_SLICE_HALF_RAM_ON: Half L3 Cache slices are operational, half of the Cache RAMs are powered on. ++#define PPU_PWPR_OP_POLICY_OPMODE_0B (11UL << PPU_PWPR_PWR_POLICY_Pos) // HALF_SLICE_FULL_RAM_ON: Half L3 Cache slices are operational, all of the Cache RAMs are powered on. ++#define PPU_PWPR_OP_DYN_EN_Pos (24U) // Operating mode dynamic transition enable. ++#define PPU_PWPR_OP_DYN_EN_Msk (0x1UL << PPU_PWPR_OP_DYN_EN_Pos) // 1 bit ++ ++// Bit definition for PPU_PWSR register ++#define PPU_PWSR_PWR_STATUS_Pos (0U) ++#define PPU_PWSR_PWR_STATUS_Msk (0xFUL << PPU_PWSR_PWR_STATUS_Pos) // 4 bits ++#define PPU_PWSR_PWR_STATUS_OFF (0UL << PPU_PWSR_PWR_STATUS_Pos) // Logic off and RAM off. ++#define PPU_PWSR_PWR_STATUS_OFF_EMU (1UL << PPU_PWSR_PWR_STATUS_Pos) // Emulated Off. Logic on with RAM on. This mode is used to emulate the functional condition of OFF without removing ++#define PPU_PWSR_PWR_STATUS_MEM_RET (2UL << PPU_PWSR_PWR_STATUS_Pos) // Memory Retention. Logic off with RAM retained. ++#define PPU_PWSR_PWR_STATUS_MEM_RET_EMU (3UL << PPU_PWSR_PWR_STATUS_Pos) // Emulated Memory Retention. Logic on with RAM on. This mode is used to emulate the functional condition of ++#define PPU_PWSR_PWR_STATUS_FULL_RET (5UL << PPU_PWSR_PWR_STATUS_Pos) // Full Retention. Slice logic off with RAM contents retained. ++#define PPU_PWSR_PWR_STATUS_FUNC_RET (7UL << PPU_PWSR_PWR_STATUS_Pos) // Functional Retention. Logic on with L3 Cache and Snoop Filter retained. ++#define PPU_PWSR_PWR_STATUS_ON (8UL << PPU_PWSR_PWR_STATUS_Pos) // Logic on with RAM on, cluster is functional. ++#define PPU_PWSR_PWR_STATUS_WARM_RST (9UL << PPU_PWSR_PWR_STATUS_Pos) // Warm Reset. Warm reset application with logic and RAM on. ++#define PPU_PWSR_PWR_STATUS_DBG_RECOV (10UL << PPU_PWSR_PWR_STATUS_Pos) // Debug Recovery Reset. Warm reset application with logic and RAM on. ++#define PPU_PWSR_PWR_DYN_STATUS_Pos (8U) // Power mode dynamic transition enable. ++#define PPU_PWSR_PWR_DYN_STATUS_Msk (0x1UL << PPU_PWSR_PWR_DYN_STATUS_Pos) // 1 bit ++#define PPU_PWSR_LOCK_STATUS_Pos (12U) // Lock enable bit for OFF, OFF_EMU, MEM_RET and MEM_RET_EMU power modes. ++#define PPU_PWSR_LOCK_STATUS_Msk (0x1UL << PPU_PWSR_LOCK_STATUS_Pos) // 1 bit ++#define PPU_PWSR_OP_STATUS_Pos (16U) // Operating mode policy ++#define PPU_PWSR_OP_STATUS_Msk (0xFUL << PPU_PWSR_OP_STATUS_Pos) // 4 bits ++#define PPU_PWSR_OP_STATUS_OPMODE_00 (0UL << PPU_PWSR_OP_STATUS_Pos) // ONE_SLICE_SF_ONLY_ON: One L3 Cache slice is operational, only the snoop filter RAM instances are active in the slice ++#define PPU_PWSR_OP_STATUS_OPMODE_01 (1UL << PPU_PWSR_OP_STATUS_Pos) // ONE_SLICE_HALF_RAM_ON: One L3 Cache slice is operational, half of the Cache RAMs are powered on. ++#define PPU_PWSR_OP_STATUS_OPMODE_03 (3UL << PPU_PWSR_OP_STATUS_Pos) // ONE_SLICE_FULL_RAM_ON: One L3 Cache slice is operational, all of the Cache RAMs are powered on. ++#define PPU_PWSR_OP_STATUS_OPMODE_04 (4UL << PPU_PWSR_OP_STATUS_Pos) // ALL_SLICE_SF_ONLY_ON: All L3 Cache slices are operational, the Cache RAMs in each slice are powered down. ++#define PPU_PWSR_OP_STATUS_OPMODE_05 (5UL << PPU_PWSR_OP_STATUS_Pos) // ALL_SLICE_HALF_RAM_ON: All L3 Cache slices are operational, half of the Cache RAMs are powered on. ++#define PPU_PWSR_OP_STATUS_OPMODE_07 (7UL << PPU_PWSR_OP_STATUS_Pos) // ALL_SLICE_FULL_RAM_ON: All L3 Cache slices are operational, all of the Cache RAMs are powered on. ++#define PPU_PWSR_OP_STATUS_OPMODE_08 (8UL << PPU_PWSR_OP_STATUS_Pos) // HALF_SLICE_SF_ONLY_ON: Half L3 Cache slices are operational, the Cache RAMs in each slice are powered down. ++#define PPU_PWSR_OP_STATUS_OPMODE_09 (9UL << PPU_PWSR_OP_STATUS_Pos) // HALF_SLICE_HALF_RAM_ON: Half L3 Cache slices are operational, half of the Cache RAMs are powered on. ++#define PPU_PWSR_OP_STATUS_OPMODE_0B (11UL << PPU_PWSR_OP_STATUS_Pos) // HALF_SLICE_FULL_RAM_ON: Half L3 Cache slices are operational, all of the Cache RAMs are powered on. ++#define PPU_PWSR_OP_DYN_STATUS_Pos (24U) // Operating mode dynamic transition enable. ++#define PPU_PWSR_OP_DYN_STATUS_Msk (0x1UL << PPU_PWSR_OP_DYN_STATUS_Pos) // 1 bit ++ ++/*!< PPU memory offsets */ ++#define DSU_120T_CLUSTER_PPU_OFFSET 0x030000 ++#define DSU_120T_CORE0_PPU_OFFSET 0x080000 ++#define DSU_120T_CORE1_PPU_OFFSET 0x180000 ++#define DSU_120T_CORE2_PPU_OFFSET 0x280000 ++#define DSU_120T_CORE3_PPU_OFFSET 0x380000 ++ ++/*!< PPU memory map */ ++#define CLUSTER_PPU_BASE (CORSTONE1000_HOST_DSU_120T_BASE + DSU_120T_CLUSTER_PPU_OFFSET) ++#define CORE0_PPU_BASE (CORSTONE1000_HOST_DSU_120T_BASE + DSU_120T_CORE0_PPU_OFFSET) ++#define CORE1_PPU_BASE (CORSTONE1000_HOST_DSU_120T_BASE + DSU_120T_CORE1_PPU_OFFSET) ++#define CORE2_PPU_BASE (CORSTONE1000_HOST_DSU_120T_BASE + DSU_120T_CORE2_PPU_OFFSET) ++#define CORE3_PPU_BASE (CORSTONE1000_HOST_DSU_120T_BASE + DSU_120T_CORE3_PPU_OFFSET) ++ ++/*!< PPU declarations */ ++#define CLUSTER_PPU ((PPU_TypeDef *) CLUSTER_PPU_BASE) ++#define CORE0_PPU ((PPU_TypeDef *) CORE0_PPU_BASE) ++#define CORE1_PPU ((PPU_TypeDef *) CORE1_PPU_BASE) ++#define CORE2_PPU ((PPU_TypeDef *) CORE2_PPU_BASE) ++#define CORE3_PPU ((PPU_TypeDef *) CORE3_PPU_BASE) ++ ++typedef struct ++{ ++ volatile uint32_t PWPR; /*!< PPU Power Policy Register, Address offset: 0x00 */ ++ volatile uint32_t PMER; /*!< PPU Power Mode Emulation Enable Register, Address offset: 0x04 */ ++ volatile uint32_t PWSR; /*!< PPU Power Status Register, Address offset: 0x08 */ ++ volatile uint32_t RESERVED0; /*!< Reserved, Address offset: 0x0C */ ++ volatile uint32_t DISR; /*!< PPU Device Interface Input Current Status Register, Address offset: 0x10 */ ++ volatile uint32_t MISR; /*!< PPU Miscellaneous Input Current Status Register, Address offset: 0x14 */ ++ volatile uint32_t STSR; /*!< PPU Stored Status Register, Address offset: 0x18 */ ++ volatile uint32_t UNLK; /*!< PPU Unlock Register, Address offset: 0x1C */ ++ volatile uint32_t PWCR; /*!< PPU Power Configuration Register, Address offset: 0x20 */ ++ volatile uint32_t PTCR; /*!< PPU Power Mode Transition Register, Address offsets: 0x24 */ ++ volatile uint32_t RESERVED1[2]; /*!< Reserved: Address offsets 0x28 - 0x2C */ ++ volatile uint32_t IMR; /*!< PPU Interrupt Mask Register, Address offsets: 0x30 */ ++ volatile uint32_t AIMR; /*!< PPU Additional Interrupt Mask Register, Address offsets: 0x34 */ ++ volatile uint32_t ISR; /*!< PPU Interrupt Status Register, Address offsets: 0x38 */ ++ volatile uint32_t AISR; /*!< PPU Additional Interrupt Status Register, Address offsets: 0x3C */ ++ volatile uint32_t IESR; /*!< PPU Input Edge Sensitivity Register Address offsets: 0x040 */ ++ volatile uint32_t OPSR; /*!< PPU Operating Mode Active Edge Sensitivity Register Address offsets: 0x044 */ ++ volatile uint32_t RESERVED2[2]; /*!< Reserved: Address offsets 0x48 - 0x4C */ ++ volatile uint32_t FUNRR; /*!< Functional Retention RAM Configuration Register Address offsets: 0x050 */ ++ volatile uint32_t FULRR; /*!< Full Retention RAM Configuration Register Address offsets: 0x054 */ ++ volatile uint32_t MEMRR; /*!< Memory Retention RAM Configuration Register Address offsets: 0x058 */ ++ volatile uint32_t RESERVED3[69]; /*!< Reserved: Address offsets 0x5C - 0x16C */ ++ volatile uint32_t DCDR0; /*!< Device Control Delay Configuration Register 0 Address offsets: 0x170 */ ++ volatile uint32_t DCDR1; /*!< Device Control Delay Configuration Register 1 Address offsets: 0x174 */ ++ volatile uint32_t RESERVED4[910]; /*!< Reserved, offsets 0x178 - 0xFAC */ ++ volatile uint32_t IDR0; /*!< PPU Identification Register 0, Address offsets: 0xFB0 */ ++ volatile uint32_t IDR1; /*!< PPU Identification Register 1, Address offsets: 0xFB4 */ ++ volatile uint32_t RESERVED5[4]; /*!< Reserved, offsets 0xFB8 - 0xFC4 */ ++ volatile uint32_t IIDR; /*!< PPU Implementation Identification Register, Address offsets: 0xFC8 */ ++ volatile uint32_t AIDR; /*!< PPU Architecture Identification Register, Address offsets: 0xFCC */ ++ volatile uint32_t PIDR4; /*!< PPU Peripheral Identification Register 4, Address offsets: 0xFD0 */ ++ volatile uint32_t PIDR5; /*!< PPU Peripheral Identification Register 5, Address offsets: 0xFD4 */ ++ volatile uint32_t PIDR6; /*!< PPU Peripheral Identification Register 6, Address offsets: 0xFD8 */ ++ volatile uint32_t PIDR7; /*!< PPU Peripheral Identification Register 7, Address offsets: 0xFDC */ ++ volatile uint32_t PIDR0; /*!< PPU Peripheral Identification Register 0, Address offsets: 0xFE0 */ ++ volatile uint32_t PIDR1; /*!< PPU Peripheral Identification Register 1, Address offsets: 0xFE4 */ ++ volatile uint32_t PIDR2; /*!< PPU Peripheral Identification Register 2, Address offsets: 0xFE8 */ ++ volatile uint32_t PIDR3; /*!< PPU Peripheral Identification Register 3, Address offsets: 0xFEC */ ++ volatile uint32_t CIDR0; /*!< PPU Component Identification Register 0, Address offsets: 0xFF0 */ ++ volatile uint32_t CIDR1; /*!< PPU Component Identification Register 1, Address offsets: 0xFF4 */ ++ volatile uint32_t CIDR2; /*!< PPU Component Identification Register 2, Address offsets: 0xFF8 */ ++ volatile uint32_t CIDR3; /*!< PPU Component Identification Register 3, Address offsets: 0xFFC */ ++} PPU_TypeDef; ++ ++typedef enum { ++ PPU_PWR_MODE_OFF = 0, // Logic off and RAM off. ++ PPU_PWR_MODE_OFF_EMU = 1, // Emulated Off. Logic on with RAM on. This mode is used to emulate the functional condition of OFF without removing ++ PPU_PWR_MODE_MEM_RET = 2, // Memory Retention. Logic off with RAM retained. ++ PPU_PWR_MODE_MEM_RET_EMU = 3, // Emulated Memory Retention. Logic on with RAM on. This mode is used to emulate the functional condition of ++ PPU_PWR_MODE_FULL_RET = 5, // Full Retention. Slice logic off with RAM contents retained. ++ PPU_PWR_MODE_FUNC_RET = 7, // Functional Retention. Logic on with L3 Cache and Snoop Filter retained. ++ PPU_PWR_MODE_ON = 8, // Logic on with RAM on, cluster is functional. ++ PPU_PWR_MODE_WARM_RST = 9, // Warm Reset. Warm reset application with logic and RAM on. ++ PPU_PWR_MODE_DBG_RECOV = 10 // Debug Recovery Reset. Warm reset application with logic and RAM on. ++} PPU_PowerPolicy_Type; ++ ++typedef enum { ++ PPU_OP_MODE_ONE_SLICE_SF_ONLY_ON = 0, // One L3 Cache slice is operational, only the snoop filter RAM instances are active in the slice ++ PPU_OP_MODE_ONE_SLICE_HALF_RAM_ON = 1, // One L3 Cache slice is operational, half of the Cache RAMs are powered on. ++ PPU_OP_MODE_ONE_SLICE_FULL_RAM_ON = 3, // One L3 Cache slice is operational, all of the Cache RAMs are powered on. ++ PPU_OP_MODE_ALL_SLICE_SF_ONLY_ON = 4, // All L3 Cache slices are operational, the Cache RAMs in each slice are powered down. ++ PPU_OP_MODE_ALL_SLICE_HALF_RAM_ON = 5, // All L3 Cache slices are operational, half of the Cache RAMs are powered on. ++ PPU_OP_MODE_ALL_SLICE_FULL_RAM_ON = 7, // All L3 Cache slices are operational, all of the Cache RAMs are powered on. ++ PPU_OP_MODE_HALF_SLICE_SF_ONLY_ON = 8, // Half L3 Cache slices are operational, the Cache RAMs in each slice are powered down. ++ PPU_OP_MODE_HALF_SLICE_HALF_RAM_ON = 9, // Half L3 Cache slices are operational, half of the Cache RAMs are powered on. ++ PPU_OP_MODE_HALF_SLICE_FULL_RAM_ON = 11 // Half L3 Cache slices are operational, all of the Cache RAMs are powered on. ++} PPU_OperatingPolicy_Type; ++ ++/** ++ * @brief Set the power policy for a given PPU instance. ++ * Only modifies PWR_POLICY and PWR_DYN_EN bits. ++ * @param ppu: Pointer to the PPU instance (e.g., CLUSTER_PPU, CORE0_PPU1) ++ * @param policy: Power mode policy (e.g., PPU_PWR_MODE_ON) ++ * @param dynamic: Enable dynamic transitions enabled for power modes, allowing transitions to be initiated by changes on power mode DEVACTIVE inputs if non-zero ++ * @retval None ++ */ ++void PPU_SetPowerPolicy(PPU_TypeDef *ppu, PPU_PowerPolicy_Type policy, bool isDynamic); ++ ++/** ++ * @brief Set the operating mode policy for a given PPU instance. ++* Only modifies OP_POLICY and OP_DYN_EN bits. ++ * @param ppu: Pointer to the PPU instance (e.g., CLUSTER_PPU, CORE0_PPU) ++ * @param policy: Operating mode policy (e.g., PPU_OP_MODE_ONE_SLICE_SF_ONLY_ON) ++ * @param dynamic: Enable dynamic transitions enabled for operating modes, allowing transitions to be initiated by changes on operating mode DEVACTIVE inputs if non-zero ++ * @retval None ++ */ ++void PPU_SetOperatingPolicy(PPU_TypeDef *ppu, PPU_OperatingPolicy_Type policy, bool isDynamic); ++ ++#endif /* PPU_H */ +diff --git a/platform/ext/target/arm/corstone1000/tfm_hal_multi_core.c b/platform/ext/target/arm/corstone1000/tfm_hal_multi_core.c +index d0c6b8d59..10c66ac41 100644 +--- a/platform/ext/target/arm/corstone1000/tfm_hal_multi_core.c ++++ b/platform/ext/target/arm/corstone1000/tfm_hal_multi_core.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018-2024 Arm Limited. All rights reserved. ++ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors + * + * SPDX-License-Identifier: BSD-3-Clause + * +@@ -11,6 +11,10 @@ + #include "tfm_hal_multi_core.h" + #include "fwu_agent.h" + ++#ifdef CORSTONE1000_DSU_120T ++#include "ppu.h" ++#endif ++ + #define HOST_SYS_RST_CTRL_OFFSET 0x000 + #define HOST_CPU_PE0_CONFIG_OFFSET 0x010 + #define HOST_CPU_PE1_CONFIG_OFFSET 0x020 +@@ -98,6 +102,28 @@ void tfm_hal_boot_ns_cpu(uintptr_t start_addr) + + (void) start_addr; + ++#ifdef CORSTONE1000_DSU_120T ++ /* Power on DSU-120T cluster */ ++ PPU_SetOperatingPolicy(CLUSTER_PPU, PPU_OP_MODE_ONE_SLICE_SF_ONLY_ON, false); ++ PPU_SetPowerPolicy(CLUSTER_PPU, PPU_PWR_MODE_ON, false); ++ ++ /* Power on Cortex-A320 core0 in DSU-120T Cluster */ ++ PPU_SetOperatingPolicy(CORE0_PPU, PPU_OP_MODE_ONE_SLICE_SF_ONLY_ON, false); ++ PPU_SetPowerPolicy(CORE0_PPU, PPU_PWR_MODE_ON, false); ++ ++#if CORSTONE1000_FVP_MULTICORE ++ /* Power on all Cortex-A320 cores in DSU-120T Cluster */ ++ PPU_SetOperatingPolicy(CORE1_PPU, PPU_OP_MODE_ONE_SLICE_SF_ONLY_ON, false); ++ PPU_SetPowerPolicy(CORE1_PPU, PPU_PWR_MODE_ON, false); ++ ++ PPU_SetOperatingPolicy(CORE2_PPU, PPU_OP_MODE_ONE_SLICE_SF_ONLY_ON, false); ++ PPU_SetPowerPolicy(CORE2_PPU, PPU_PWR_MODE_ON, false); ++ ++ PPU_SetOperatingPolicy(CORE3_PPU, PPU_OP_MODE_ONE_SLICE_SF_ONLY_ON, false); ++ PPU_SetPowerPolicy(CORE3_PPU, PPU_PWR_MODE_ON, false); ++#endif ++#endif ++ + #ifdef EXTERNAL_SYSTEM_SUPPORT + /*release EXT SYS out of reset*/ + tfm_external_system_boot(); +-- +2.50.1 + diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-corstone1000.inc b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-corstone1000.inc index a9521fbf..a355e844 100644 --- a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-corstone1000.inc +++ b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-corstone1000.inc @@ -12,6 +12,14 @@ DEPENDS:append = " clang-native python3-rich-native python3-pyelftools-native" ## Default is the MPS3 board TFM_PLATFORM_IS_FVP ?= "FALSE" + +## Default is Cortex-A35 +## Cortex-A320 is implemented inside a DynamIQ Shared Unit-120T (DSU-120T) cluster +EXTRA_OECMAKE:append:cortexa320 = " \ + -DCORSTONE1000_CORTEX_A320=TRUE \ + -DCORSTONE1000_DSU_120T=TRUE \ +" + EXTRA_OECMAKE += "-DPLATFORM_IS_FVP=${TFM_PLATFORM_IS_FVP}" EXTRA_OECMAKE += "-DCC312_LEGACY_DRIVER_API_ENABLED=OFF" EXTRA_OECMAKE:append:corstone1000-fvp = " -DENABLE_MULTICORE=${@bb.utils.contains('MACHINE_FEATURES', 'corstone1000_fvp_smp', 'TRUE', 'FALSE', d)}" @@ -33,6 +41,7 @@ SRC_URI:append:corstone1000 = " \ file://0007-Platform-Corstone1000-Remove-duplicate-configuration.patch \ file://0008-Platform-Corstone1000-Increase-BL1-size-and-align-bi.patch \ file://0009-Platform-CS1K-Adapt-ADAC-enabled-build-to-the-new-BL.patch \ + file://0010-plat-corstone1000-Add-support-for-Cortex-A320-varian.patch \ " FILESEXTRAPATHS:prepend:corstone1000-mps3 := "${THISDIR}/files/corstone1000/psa-adac:" From patchwork Thu Dec 4 15:19:51 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hugues KAMBA MPIANA X-Patchwork-Id: 75898 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4E3C0D21699 for ; Thu, 4 Dec 2025 15:25:27 +0000 (UTC) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.46102.1764861917493574310 for ; Thu, 04 Dec 2025 07:25:17 -0800 Authentication-Results: mx.groups.io; dkim=none (message not signed); spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: hugues.kambampiana@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 98E9D339; Thu, 4 Dec 2025 07:25:09 -0800 (PST) Received: from LXKV206JHX.arm.com (unknown [10.57.43.122]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 112F33F59E; Thu, 4 Dec 2025 07:25:15 -0800 (PST) From: Hugues KAMBA MPIANA To: meta-arm@lists.yoctoproject.org Cc: Michael Safwat , Harsimran Singh Tungal , Frazer Carsley Subject: [PATCH 4/6] =?utf-8?q?arm-bsp/tf-a=3Acorstone1000=3A_Add_Cortex?= =?utf-8?q?=E2=80=91A320_support?= Date: Thu, 4 Dec 2025 15:19:51 +0000 Message-ID: <20251204152500.78818-5-hugues.kambampiana@arm.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20251204152500.78818-1-hugues.kambampiana@arm.com> References: <20251204152500.78818-1-hugues.kambampiana@arm.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Thu, 04 Dec 2025 15:25:27 -0000 X-Groupsio-URL: https://lists.yoctoproject.org/g/meta-arm/message/6783 From: Michael Safwat Enable Trusted Firmware-A for Corstone-1000 platforms with Cortex-A320 and switch the interrupt controller from GICv2/GIC-400 to GICv3/GIC-600. **Platform/feature enablement** * Map Ethos-U85 NPU registers (`0x1A050000`, 16 KiB) and its SRAM region (`0x02400000`, 4 MiB) into Normal World (`MT_DEVICE | MT_RW | MT_NS` / `MT_MEMORY | MT_RW | MT_NS`). * Force Cortex-A320 feature selection: enable Armv9 features, disable Cortex-A35 errata, and select the `cortexa320` override in `trusted-firmware-a-corstone1000.inc`. * Build TF-A-Tests with `CORSTONE1000_CORTEX_A320=1` to skip non-applicable FF-A, PSCI, and CPU-extension tests on Cortex-A320. **GICv3/GIC-600 transition (A320 builds)** * Update `plat_my_core_pos()` and `plat_arm_calc_core_pos()` to compute the linear core position using the Cortex-A320 MPIDR_EL1 affinity layout. * Add an A320-specific core-position routine in assembly, guarded by `CORSTONE1000_CORTEX_A320`. * Switch to the GICv3 driver with GIC-600 extensions: * Update platform GIC base addresses to the GIC-600 layout. * Use GICv3 APIs; set `USE_GIC_DRIVER=3`, `GICV3_SUPPORT_GIC600=1`, and `GIC_ENABLE_V4_EXTN=1`. * Keep conditional GIC versioning so Cortex-A35 continues to use GICv2/GIC-400. These changes ensure correct GIC configuration and reliable secondary-core bring-up on Cortex-A320 while preserving existing Cortex-A35 behavior. Signed-off-by: Harsimran Singh Tungal Signed-off-by: Frazer Carsley Signed-off-by: Michael Safwat --- ...corstone1000-add-Cortex-A320-support.patch | 241 ++++++++++++++++++ ...corstone1000-Add-Cortex-A320-support.patch | 163 ++++++++++++ .../trusted-firmware-a/tf-a-tests_%.bbappend | 9 + .../trusted-firmware-a-corstone1000.inc | 30 ++- 4 files changed, 440 insertions(+), 3 deletions(-) create mode 100644 meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/corstone1000/0002-plat-corstone1000-add-Cortex-A320-support.patch create mode 100644 meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/corstone1000/tf-a-tests/0002-plat-corstone1000-Add-Cortex-A320-support.patch diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/corstone1000/0002-plat-corstone1000-add-Cortex-A320-support.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/corstone1000/0002-plat-corstone1000-add-Cortex-A320-support.patch new file mode 100644 index 00000000..1a9f24e3 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/corstone1000/0002-plat-corstone1000-add-Cortex-A320-support.patch @@ -0,0 +1,241 @@ +From 977f06e10e549d01a641a62a1d4850a06d6f0df4 Mon Sep 17 00:00:00 2001 +From: Harsimran Singh Tungal +Date: Thu, 7 Aug 2025 10:05:02 +0000 +Subject: [PATCH] plat: corstone1000: add Cortex-A320 support + +Introduce `CORSTONE1000_CORTEX_A320` to enable Cortex-A320 on +Corstone-1000 while keeping Cortex-A35 as the default. When the +define is enabled, the build switches from `cortex_a35.S` to +`cortex_a320.S`, maintaining compatibility with existing A35-based +designs. + +Also add Normal-World mappings for the Ethos-U85 NPU and its SRAM +on Cortex-A320 platforms so U-Boot and other non-secure software +can safely access these regions: + +* **Ethos-U85 registers**: base `0x1A050000`, size `0x00004000` (16 KB), + attrs `MT_DEVICE | MT_RW | MT_NS` +* **Non-secure SRAM**: base `0x02400000`, size `0x00400000` (4 MB), + attrs `MT_MEMORY | MT_RW | MT_NS` + +Enable GICv3 with GIC-600 when building for Cortex-A320 (retain +GICv2/GIC-400 for Cortex-A35): + +* Update `plat_my_core_pos()` and `plat_arm_calc_core_pos()` to use + the Cortex-A320 MPIDR_EL1 affinity layout. +* Add an A320-specific core-position routine in assembly guarded by + `CORSTONE1000_CORTEX_A320`. +* Switch to the GICv3 driver with GIC-600 extensions: update GIC base + addresses, use GICv3 APIs, and set `USE_GIC_DRIVER=3`, + `GICV3_SUPPORT_GIC600=1`, `GIC_ENABLE_V4_EXTN=1`. + +These changes prepare the platform for Cortex-A320 integration and +ensure correct GIC configuration and secondary-core bring-up, while +preserving A35 behavior. + +Upstream-Status: Submitted (https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/45729) +Signed-off-by: Harsimran Singh Tungal +Signed-off-by: Frazer Carsley +Signed-off-by: Michael Safwat +--- + .../common/corstone1000_helpers.S | 35 ++++++++++++++++++- + .../corstone1000/common/corstone1000_plat.c | 4 +++ + .../corstone1000/common/corstone1000_pm.c | 8 +++++ + .../common/include/platform_def.h | 28 ++++++++++++++- + plat/arm/board/corstone1000/platform.mk | 11 ++++++ + 5 files changed, 84 insertions(+), 2 deletions(-) + +diff --git a/plat/arm/board/corstone1000/common/corstone1000_helpers.S b/plat/arm/board/corstone1000/common/corstone1000_helpers.S +index a4ca9fe98..665dbc61a 100644 +--- a/plat/arm/board/corstone1000/common/corstone1000_helpers.S ++++ b/plat/arm/board/corstone1000/common/corstone1000_helpers.S +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2021-2024 Arm Limited and Contributors. All rights reserved. ++ * Copyright (c) 2021-2025 Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -13,6 +13,39 @@ + .globl plat_is_my_cpu_primary + .globl plat_arm_calc_core_pos + ++#ifdef CORSTONE1000_CORTEX_A320 ++ .globl plat_my_core_pos ++ ++func plat_my_core_pos ++ mrs x0, mpidr_el1 ++ b plat_arm_calc_core_pos ++endfunc plat_my_core_pos ++ ++func plat_arm_calc_core_pos ++ /* Aff0 is always 0 for Cortex-A320 ++ MPIDR format: https://developer.arm.com/documentation/109551/0001/AArch64-registers/AArch64-Identification-registers-summary/MPIDR-EL1--Multiprocessor-Affinity-Register?lang=en ++ */ ++ /* Extract Aff1 (core ID) */ ++ ubfx x1, x0, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS ++ ++ /* Extract Aff2 (cluster lower bits) */ ++ ubfx x2, x0, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS ++ ++ /* Extract Aff3 (cluster upper bits) */ ++ ubfx x3, x0, #MPIDR_AFF3_SHIFT, #MPIDR_AFFINITY_BITS ++ ++ /* cluster_id = (Aff3 << 8) | Aff2 */ ++ lsl x3, x3, #MPIDR_AFFINITY_BITS ++ orr x3, x3, x2 ++ ++ /* core_pos = core_id + (cluster_id * FVP_MAX_CPUS_PER_CLUSTER) */ ++ mov x4, #CORSTONE1000_MAX_CPUS_PER_CLUSTER ++ madd x0, x3, x4, x1 ++ ++ ret ++endfunc plat_arm_calc_core_pos ++#endif ++ + /* -------------------------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * +diff --git a/plat/arm/board/corstone1000/common/corstone1000_plat.c b/plat/arm/board/corstone1000/common/corstone1000_plat.c +index e388c82f3..d34e80b29 100644 +--- a/plat/arm/board/corstone1000/common/corstone1000_plat.c ++++ b/plat/arm/board/corstone1000/common/corstone1000_plat.c +@@ -26,6 +26,10 @@ const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_NS_DRAM1, + CORSTONE1000_MAP_DEVICE, + CORSTONE1000_EXTERNAL_FLASH, ++#ifdef CORSTONE1000_CORTEX_A320 ++ ARM_MAP_ETHOS_U85, ++ ARM_MAP_NONSECURE_SRAM, ++#endif + {0} + }; + +diff --git a/plat/arm/board/corstone1000/common/corstone1000_pm.c b/plat/arm/board/corstone1000/common/corstone1000_pm.c +index ac808873b..a87697e97 100644 +--- a/plat/arm/board/corstone1000/common/corstone1000_pm.c ++++ b/plat/arm/board/corstone1000/common/corstone1000_pm.c +@@ -8,7 +8,11 @@ + #include + #include + #include ++#ifdef CORSTONE1000_CORTEX_A320 ++#include ++#else + #include ++#endif + /******************************************************************************* + * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard + * platform layer will take care of registering the handlers with PSCI. +@@ -24,7 +28,11 @@ static void corstone1000_system_reset(void) + * Disable GIC CPU interface to prevent pending interrupt + * from waking up the AP from WFI. + */ ++#ifdef CORSTONE1000_CORTEX_A320 ++ gicv3_cpuif_disable(plat_my_core_pos()); ++#else + gicv2_cpuif_disable(); ++#endif + + /* Flush and invalidate data cache */ + dcsw_op_all(DCCISW); +diff --git a/plat/arm/board/corstone1000/common/include/platform_def.h b/plat/arm/board/corstone1000/common/include/platform_def.h +index caf3d462f..ee0babbf8 100644 +--- a/plat/arm/board/corstone1000/common/include/platform_def.h ++++ b/plat/arm/board/corstone1000/common/include/platform_def.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2021-2024, Arm Limited and Contributors. All rights reserved. ++ * Copyright (c) 2021-2025, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -112,12 +112,19 @@ + #define ARM_SHARED_RAM_SIZE (SZ_8K) /* 8 KB */ + #define ARM_SHARED_RAM_BASE ARM_TRUSTED_SRAM_BASE + ++#ifdef CORSTONE1000_CORTEX_A320 ++#define TOTAL_SECURE_SRAM_SIZE (SZ_4M) ++#define TOTAL_NONSECURE_SRAM_SIZE (SZ_4M) ++#define PLAT_ARM_TRUSTED_SRAM_SIZE (TOTAL_SECURE_SRAM_SIZE - \ ++ ARM_SHARED_RAM_SIZE) ++#else + /* The remaining Trusted SRAM is used to load the BL images */ + #define TOTAL_SRAM_SIZE (SZ_4M) /* 4 MB */ + + + #define PLAT_ARM_TRUSTED_SRAM_SIZE (TOTAL_SRAM_SIZE - \ + ARM_SHARED_RAM_SIZE) ++#endif + + #define PLAT_ARM_MAX_BL2_SIZE (180 * SZ_1K) /* 180 KB */ + +@@ -209,8 +216,13 @@ + #define MAX_IO_BLOCK_DEVICES 1 + + /* GIC related constants */ ++#ifdef CORSTONE1000_CORTEX_A320 ++#define PLAT_ARM_GICD_BASE 0x1C000000 ++#define PLAT_ARM_GICR_BASE 0x1C040000 ++#else + #define PLAT_ARM_GICD_BASE 0x1C010000 + #define PLAT_ARM_GICC_BASE 0x1C02F000 ++#endif + + /* MHUv2 Secure Channel receiver and sender */ + #define PLAT_SDK700_MHU0_SEND 0x1B800000 +@@ -335,6 +347,20 @@ + CORSTONE1000_DEVICE_BASE, \ + CORSTONE1000_DEVICE_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) ++#ifdef CORSTONE1000_CORTEX_A320 ++#define ARM_ETHOS_U85_BASE UL(0x1A050000) ++#define ARM_ETHOS_U85_SIZE UL(0x4000) ++#define ARM_MAP_ETHOS_U85 MAP_REGION_FLAT( \ ++ ARM_ETHOS_U85_BASE, \ ++ ARM_ETHOS_U85_SIZE, \ ++ MT_DEVICE | MT_RW | MT_NS) ++ ++#define ARM_NONSECURE_SRAM_BASE (ARM_TRUSTED_SRAM_BASE + TOTAL_SECURE_SRAM_SIZE) ++#define ARM_MAP_NONSECURE_SRAM MAP_REGION_FLAT( \ ++ ARM_NONSECURE_SRAM_BASE, \ ++ TOTAL_NONSECURE_SRAM_SIZE, \ ++ MT_MEMORY | MT_RW | MT_NS) ++#endif + + #define ARM_IRQ_SEC_PHY_TIMER 29 + +diff --git a/plat/arm/board/corstone1000/platform.mk b/plat/arm/board/corstone1000/platform.mk +index 65be9c1f5..fe3e94865 100644 +--- a/plat/arm/board/corstone1000/platform.mk ++++ b/plat/arm/board/corstone1000/platform.mk +@@ -9,7 +9,14 @@ ifeq ($(filter ${TARGET_PLATFORM}, fpga fvp),) + $(error TARGET_PLATFORM must be fpga or fvp) + endif + ++ifdef CORSTONE1000_CORTEX_A320 ++CORSTONE1000_CPU_LIBS +=lib/cpus/aarch64/cortex_a320.S ++$(eval $(call add_define,CORSTONE1000_CORTEX_A320)) ++GIC_ENABLE_V4_EXTN := 1 ++GICV3_SUPPORT_GIC600 := 1 ++else + CORSTONE1000_CPU_LIBS +=lib/cpus/aarch64/cortex_a35.S ++endif + + PLAT_INCLUDES := -Iplat/arm/board/corstone1000/common/include \ + -Iplat/arm/board/corstone1000/include \ +@@ -43,7 +50,11 @@ $(eval $(call add_define,CORSTONE1000_FVP_MULTICORE)) + endif + endif + ++ifdef CORSTONE1000_CORTEX_A320 ++USE_GIC_DRIVER := 3 ++else + USE_GIC_DRIVER := 2 ++endif + + BL2_SOURCES += plat/arm/board/corstone1000/common/corstone1000_security.c \ + plat/arm/board/corstone1000/common/corstone1000_err.c \ +-- +2.50.1 + diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/corstone1000/tf-a-tests/0002-plat-corstone1000-Add-Cortex-A320-support.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/corstone1000/tf-a-tests/0002-plat-corstone1000-Add-Cortex-A320-support.patch new file mode 100644 index 00000000..2ee2506f --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/corstone1000/tf-a-tests/0002-plat-corstone1000-Add-Cortex-A320-support.patch @@ -0,0 +1,163 @@ +From 82ca3fcf5c323aec4ce8191c349fd7e00a840e02 Mon Sep 17 00:00:00 2001 +From: Michael Safwat +Date: Tue, 26 Aug 2025 11:20:01 +0000 +Subject: [PATCH] plat: corstone1000: Add Cortex-A320 support + +Switch platform to GICv3 (GIC-600) for Corstone-1000 with Cortex-A320 +depending on CORSTONE1000_CORTEX_A320: + - Define GICD and GICR bases. + - Update the platform sources to include the GIC-V3 files. + +Move the NVM offset to prevent overlap with the TFTF firmware, +which starts at 0x80000000 (TFTF_BASE). + +Introduce a new skip file tests_to_skip_cortex_a320 to be used when building +TF-A-Tests with CORSTONE1000_CORTEX_A320=1. This ensures that tests which +are not supported or cause traps on Corstone-1000 with Cortex-A320 are +consistently skipped during execution. + +Skipped entries: + CPU extensions/AMUv1 suspend/resume + CPU extensions/Use trace buffer control Registers + +Signed-off-by: Michael Safwat +Signed-off-by: Harsimran Singh Tungal +Upstream-Status: Submitted (https://review.trustedfirmware.org/c/TF-A/tf-a-tests/+/42352) +--- + plat/arm/corstone1000/corstone1000_def.h | 12 +++++++++- + plat/arm/corstone1000/include/platform_def.h | 11 +++++---- + plat/arm/corstone1000/platform.mk | 23 +++++++++++++++++++ + .../tests_to_skip_cortex_a320.txt | 21 +++++++++++++++++ + 4 files changed, 61 insertions(+), 6 deletions(-) + create mode 100644 plat/arm/corstone1000/tests_to_skip_cortex_a320.txt + +diff --git a/plat/arm/corstone1000/corstone1000_def.h b/plat/arm/corstone1000/corstone1000_def.h +index 3e6f036a..c4fa9a3b 100644 +--- a/plat/arm/corstone1000/corstone1000_def.h ++++ b/plat/arm/corstone1000/corstone1000_def.h +@@ -26,13 +26,23 @@ + * GIC-400 & interrupt handling related constants + ******************************************************************************/ + /* GIC memory map */ ++#ifdef CORSTONE1000_CORTEX_A320 ++#define GICD_BASE 0x1C000000 ++#define GICR_BASE 0x1C040000 ++ ++/* GIC re-distributor doesn't exits on gic-600, but we still need to ++ * provide GICC_BASE as the gic driver needs it ++ */ ++#define GICC_BASE 0x0 ++#else ++ + #define GICD_BASE 0x1C010000 + #define GICC_BASE 0x1C02F000 + /* GIC re-distributor doesn't exits on gic-400, but we still need to + * provide GICR_BASE as the gic driver needs it + */ + #define GICR_BASE 0x0 +- ++#endif + /******************************************************************************* + * PL011 related constants + ******************************************************************************/ +diff --git a/plat/arm/corstone1000/include/platform_def.h b/plat/arm/corstone1000/include/platform_def.h +index a0d6f7b3..1fc505d0 100644 +--- a/plat/arm/corstone1000/include/platform_def.h ++++ b/plat/arm/corstone1000/include/platform_def.h +@@ -98,12 +98,13 @@ + #endif + + /* +- * USE 0x200000 DRAM offset to store TFTF data +- * +- * Please note that this won't be suitable for all test scenarios and +- * for this reason some tests will be disabled in this configuration. ++ * When USE_NVM = 0, TFTF_NVM_OFFSET marks the DRAM region ++ * used as NVM. This region must not overlap the memory where ++ * the TFTF image is loaded. The load address is given by ++ * the TFTF_BASE macro. Set TFTF_NVM_OFFSET to leave enough ++ * space for the TFTF image. + */ +-#define TFTF_NVM_OFFSET 0x40000 ++#define TFTF_NVM_OFFSET 0x80000 + #define TFTF_NVM_SIZE (128 * SZ_1M) /* 128 MB */ + + /******************************************************************************* +diff --git a/plat/arm/corstone1000/platform.mk b/plat/arm/corstone1000/platform.mk +index a5a011d5..fd98724a 100644 +--- a/plat/arm/corstone1000/platform.mk ++++ b/plat/arm/corstone1000/platform.mk +@@ -6,6 +6,19 @@ + + PLAT_INCLUDES := -Iplat/arm/corstone1000/include/ + ++CORSTONE1000_CORTEX_A320 := 0 ++ifeq (${CORSTONE1000_CORTEX_A320},1) ++PLAT_SOURCES := drivers/arm/gic/arm_gic_v2v3.c \ ++ drivers/arm/gic/gic_v2.c \ ++ drivers/arm/gic/gic_v3.c \ ++ drivers/arm/timer/private_timer.c \ ++ drivers/arm/timer/system_timer.c \ ++ plat/arm/corstone1000/plat_helpers.S \ ++ plat/arm/corstone1000/corstone1000_pwr_state.c \ ++ plat/arm/corstone1000/corstone1000_topology.c \ ++ plat/arm/corstone1000/corstone1000_mem_prot.c \ ++ plat/arm/corstone1000/plat_setup.c ++else + PLAT_SOURCES := drivers/arm/gic/arm_gic_v2.c \ + drivers/arm/gic/gic_v2.c \ + drivers/arm/timer/private_timer.c \ +@@ -15,6 +28,7 @@ PLAT_SOURCES := drivers/arm/gic/arm_gic_v2.c \ + plat/arm/corstone1000/corstone1000_topology.c \ + plat/arm/corstone1000/corstone1000_mem_prot.c \ + plat/arm/corstone1000/plat_setup.c ++endif + + PLAT_SUPPORTS_NS_RESET := 1 + +@@ -23,6 +37,15 @@ $(eval $(call assert_boolean,PLAT_SUPPORTS_NS_RESET)) + $(eval $(call add_define,TFTF_DEFINES,PLAT_SUPPORTS_NS_RESET)) + + FIRMWARE_UPDATE := 0 ++ ++ifeq ($(CORSTONE1000_CORTEX_A320),1) ++$(eval $(call add_define,TFTF_DEFINES,CORSTONE1000_CORTEX_A320)) ++endif ++ ++ifeq (${CORSTONE1000_CORTEX_A320},1) ++PLAT_TESTS_SKIP_LIST := plat/arm/corstone1000/tests_to_skip_cortex_a320.txt ++else + PLAT_TESTS_SKIP_LIST := plat/arm/corstone1000/tests_to_skip.txt ++endif + + include plat/arm/common/arm_common.mk +diff --git a/plat/arm/corstone1000/tests_to_skip_cortex_a320.txt b/plat/arm/corstone1000/tests_to_skip_cortex_a320.txt +new file mode 100644 +index 00000000..87b9241d +--- /dev/null ++++ b/plat/arm/corstone1000/tests_to_skip_cortex_a320.txt +@@ -0,0 +1,21 @@ ++Realm payload tests ++Realm payload boot ++Realm payload multi CPU request ++Realm payload Delegate and Undelegate ++Multi CPU Realm payload Delegate and Undelegate ++Testing delegation fails ++Realm testing with SPM tests ++PSCI System Suspend Validation ++PSCI STAT/Stats test cases after system suspend ++IRQ support in TSP/Resume preempted STD SMC after PSCI SYSTEM SUSPEND ++PSCI SYSTEM SUSPEND stress tests ++Timer framework Validation/Verify the timer interrupt generation ++CPU Hotplug/CPU hotplug ++PSCI CPU Suspend ++PSCI CPU Suspend in OSI mode ++PSCI STAT/for valid composite state CPU suspend ++FF-A Setup and Discovery/FF-A RXTX remap unmapped region success ++FF-A Memory Sharing/Normal World VM retrieve request into SPMC ++Boot requirement tests ++CPU extensions/AMUv1 suspend/resume ++CPU extensions/Use trace buffer control Registers +-- +2.43.0 + diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-a/tf-a-tests_%.bbappend b/meta-arm-bsp/recipes-bsp/trusted-firmware-a/tf-a-tests_%.bbappend index 344c9f8b..c1490c9f 100644 --- a/meta-arm-bsp/recipes-bsp/trusted-firmware-a/tf-a-tests_%.bbappend +++ b/meta-arm-bsp/recipes-bsp/trusted-firmware-a/tf-a-tests_%.bbappend @@ -3,9 +3,18 @@ COMPATIBLE_MACHINE:corstone1000 = "corstone1000" EXTRA_OEMAKE:append:corstone1000 = " DEBUG=0" EXTRA_OEMAKE:append:corstone1000 = " LOG_LEVEL=30" + +# Add Cortex-A320 specific configurations +EXTRA_OEMAKE:append:cortexa320 = " \ + CORSTONE1000_CORTEX_A320=1 \ + " TFTF_MODE:corstone1000 = "release" FILESEXTRAPATHS:prepend:corstone1000 := "${THISDIR}/files/corstone1000/tf-a-tests:" SRC_URI:append:corstone1000 = " \ file://0001-fix-exclude-Boot-requirement-tests-for-Corstone-1000.patch \ " + +SRC_URI:append:corstone1000 = " \ + file://0002-plat-corstone1000-Add-Cortex-A320-support.patch \ + " diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-corstone1000.inc b/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-corstone1000.inc index 97a9e55b..5e219a28 100644 --- a/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-corstone1000.inc +++ b/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-corstone1000.inc @@ -5,7 +5,8 @@ COMPATIBLE_MACHINE = "(corstone1000)" FILESEXTRAPATHS:prepend := "${THISDIR}/files/corstone1000:" SRC_URI:append = " \ file://0001-Fix-FF-A-version-in-SPMC-manifest.patch \ - " + file://0002-plat-corstone1000-add-Cortex-A320-support.patch \ +" TFA_DEBUG = "1" TFA_UBOOT ?= "1" @@ -21,6 +22,13 @@ TFA_SPMD_SPM_AT_SEL2 = "0" # BL2 loads BL32 (optee). So, optee needs to be built first: DEPENDS += "optee-os" +ENABLE_CORTEX_A35_ERRATA = " \ + ERRATA_A35_855472=1 \ +" +ENABLE_CORTEX_A35_ERRATA:cortexta320 = "" +FVP_GIC_DRIVER ?= "FVP_GICV2" +FVP_GIC_DRIVER:cortexa320 = "FVP_GICV3" + # Note: Regarding the build option: LOG_LEVEL. # There seems to be an issue when setting it # to 50 (LOG_LEVEL_VERBOSE), where the kernel @@ -45,13 +53,29 @@ EXTRA_OEMAKE:append = " \ NR_OF_IMAGES_IN_FW_BANK=4 \ COT=tbbr \ ARM_ROTPK_LOCATION=devel_rsa \ - ERRATA_A35_855472=1 \ + ${ENABLE_CORTEX_A35_ERRATA} \ ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \ BL32=${RECIPE_SYSROOT}/${nonarch_base_libdir}/firmware/tee-pager_v2.bin \ - FVP_USE_GIC_DRIVER=FVP_GICV2 \ + FVP_USE_GIC_DRIVER=${FVP_GIC_DRIVER} \ " EXTRA_OEMAKE:append:corstone1000-fvp = "${@bb.utils.contains('MACHINE_FEATURES', 'corstone1000_fvp_smp', ' ENABLE_MULTICORE=1', '', d)}" +# Add Cortex-A320 specific configurations +EXTRA_OEMAKE:append:cortexa320 = " \ + CORSTONE1000_CORTEX_A320=1 \ + HW_ASSISTED_COHERENCY=1 \ + USE_COHERENT_MEM=0 \ + CTX_INCLUDE_AARCH32_REGS=0 \ + ENABLE_FEAT_HCX=1 \ + ENABLE_FEAT_FGT=1 \ + ENABLE_FEAT_ECV=1 \ + ENABLE_FEAT_MTE2=1 \ + ENABLE_FEAT_AMU=1 \ + ENABLE_FEAT_CSV2_2=1 \ + ENABLE_SVE_FOR_NS=1 \ + ENABLE_SVE_FOR_SWD=1 \ +" + # If GENERATE_COT is set, then TF-A will try to use local poetry install # to run the python cot-dt2c command. Disable the local poetry and use # the provided cot-dt2c. From patchwork Thu Dec 4 15:19:52 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Hugues KAMBA MPIANA X-Patchwork-Id: 75897 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 42AA6D21696 for ; Thu, 4 Dec 2025 15:25:27 +0000 (UTC) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.46103.1764861918517249225 for ; Thu, 04 Dec 2025 07:25:18 -0800 Authentication-Results: mx.groups.io; dkim=none (message not signed); spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: hugues.kambampiana@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id B14D2339; Thu, 4 Dec 2025 07:25:10 -0800 (PST) Received: from LXKV206JHX.arm.com (unknown [10.57.43.122]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 484DA3F59E; Thu, 4 Dec 2025 07:25:17 -0800 (PST) From: Hugues KAMBA MPIANA To: meta-arm@lists.yoctoproject.org Cc: Frazer Carsley , Harsimran Singh Tungal Subject: [PATCH 5/6] arm-bsp/u-boot:corstone1000: Add Cortex-A320 suppport Date: Thu, 4 Dec 2025 15:19:52 +0000 Message-ID: <20251204152500.78818-6-hugues.kambampiana@arm.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20251204152500.78818-1-hugues.kambampiana@arm.com> References: <20251204152500.78818-1-hugues.kambampiana@arm.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Thu, 04 Dec 2025 15:25:27 -0000 X-Groupsio-URL: https://lists.yoctoproject.org/g/meta-arm/message/6784 From: Frazer Carsley Update Corstone-1000 U-Boot device tree for the Cortex-A320 variant and enable GICv3/GIC-600, while keeping compatibility with the existing GIC-400 setup. A single DT image now supports either configuration via Kconfig guards. **Device-tree updates (Cortex-A320)** * Map Ethos-U85 NPU registers at `0x1A050000` (16 KiB) and its SRAM at `0x02400000` (2 MiB, no-map), plus a 32 MiB DDR carve-out for DMA. * Add `/ethosu@1a050000` with interrupts, `dma-ranges`, `cs-region`, and `ethosu-mem-config` for driver probe. * Guard the NPU node behind `CONFIG_ETHOS_U85`. * Add a Cortex-A320 compatible string to the Corstone-1000 DTS downstream. **GICv3/GIC-600 selection** * Introduce `CONFIG_GIC_V3` to select the new interrupt controller. * Add a full GICv3/GIC-600 node guarded by `#ifdef CONFIG_GIC_V3`. * When GICv3 is enabled, set `cpu@1..3` `reg` to `0x100/0x200/0x300` (retain `0x1/0x2/0x3` for GIC-400). * Update the Ethos-U85 interrupt to **SPI 16** to match the interrupt map. Signed-off-by: Frazer Carsley Signed-off-by: Harsimran Singh Tungal --- .../u-boot/u-boot-corstone1000.inc | 10 + ...e1000-Add-Cortex-A320-support-on-FVP.patch | 223 ++++++++++++++++++ .../u-boot/corstone1000/corstone1000-a320.cfg | 2 + 3 files changed, 235 insertions(+) create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0039-corstone1000-Add-Cortex-A320-support-on-FVP.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/corstone1000-a320.cfg diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot-corstone1000.inc b/meta-arm-bsp/recipes-bsp/u-boot/u-boot-corstone1000.inc index b33a5bcb..52e0acaf 100644 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot-corstone1000.inc +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot-corstone1000.inc @@ -74,6 +74,16 @@ SRC_URI:append = " \ file://0040-corstone1000-dts-use-32-bit-cells-for-reserved-memor.patch \ " +# Add Cortex-a320 support +SRC_URI:append = " \ + file://0039-corstone1000-Add-Cortex-A320-support-on-FVP.patch \ +" + +# Add Cortex-a320 specific configurations +SRC_URI:append:cortexa320 = " \ + file://corstone1000-a320.cfg \ +" + uboot_configure_config:append() { openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=CRT/ -keyout ${B}/CRT.key -out $builddir/CRT.crt -nodes -days 365 } diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0039-corstone1000-Add-Cortex-A320-support-on-FVP.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0039-corstone1000-Add-Cortex-A320-support-on-FVP.patch new file mode 100644 index 00000000..ecd96c45 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0039-corstone1000-Add-Cortex-A320-support-on-FVP.patch @@ -0,0 +1,223 @@ +From 6a1e76a1c0e52c11e9abdcb5990002468650bd81 Mon Sep 17 00:00:00 2001 +From: Frazer Carsley +Date: Fri, 15 Aug 2025 09:22:26 +0100 +Subject: [PATCH] corstone1000: Add Cortex-A320 support on FVP +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Enable Cortex-A320 support on the Corstone-1000 platform +(including FVP) and update the device tree to support the integrated +Ethos-U85 NPU and GIC-600 interrupt controller. These updates make +the platform fully compatible with Cortex-A320 while retaining +backward compatibility with Cortex-A35 and GIC-400. + +**Cortex-A320 enablement** + +* Extend Corstone-1000 compatibility list to include `cortex-a320`. +* Ensure build and device-tree logic support both Cortex-A35 and + Cortex-A320 configurations. + +**Ethos-U85 integration** + +* Add `/ethosu@1a050000` node describing the NPU register block at + `0x1A050000`. +* Introduce associated reserved memory regions: + * `ethosu_sram@02400000`: 2 MiB on-chip SRAM (`no-map`). + * `ethosu_reserved@A0000000`: 32 MiB DDR carve-out + (`shared-dma-pool`). +* Connect memory regions through `memory-region` and `sram` phandles. +* Add `dma-ranges`, interrupt spec, `region-cfgs`, `cs-region`, and + `ethosu-mem-config` for full driver support. +* Enable the NPU node conditionally via `CONFIG_ETHOS_U85`. + +**GICv3/GIC-600 support** + +* Introduce `CONFIG_GIC_V3` to toggle between GIC-400 (v2) and + GIC-600 (v3). +* Add full GICv3 node guarded by `#ifdef CONFIG_GIC_V3`. +* Adjust `cpu@1..3` `reg` values to `0x100/0x200/0x300` under + GICv3 (keep `0x1/0x2/0x3` for GIC-400). +* Update Ethos-U85 interrupt assignment to **SPI 16** to align with + the new interrupt map. + +These updates align the Corstone-1000 platform with Arm’s latest +Cortex-A320 and Ethos-U85 configurations and ensure proper interrupt +and memory mapping for both secure and non-secure domains. + +Upstream-Status: Submitted (https://lore.kernel.org/all/20251127154752.589691-1-frazer.carsley@arm.com/) +Signed-off-by: Frazer Carsley +Signed-off-by: Harsimran Singh Tungal +--- + arch/arm/dts/corstone1000-fvp-u-boot.dtsi | 18 +++++- + arch/arm/dts/corstone1000-u-boot.dtsi | 76 +++++++++++++++++++++++ + arch/arm/include/asm/armv8/cpu.h | 1 + + board/armltd/corstone1000/Kconfig | 7 +++ + 4 files changed, 99 insertions(+), 3 deletions(-) + +diff --git a/arch/arm/dts/corstone1000-fvp-u-boot.dtsi b/arch/arm/dts/corstone1000-fvp-u-boot.dtsi +index 6b89d653417..0539e6c092a 100644 +--- a/arch/arm/dts/corstone1000-fvp-u-boot.dtsi ++++ b/arch/arm/dts/corstone1000-fvp-u-boot.dtsi +@@ -17,24 +17,36 @@ + &{/cpus} { + cpu1: cpu@1 { + device_type = "cpu"; +- compatible = "arm,cortex-a35"; ++ compatible = "arm,cortex-a35","arm,cortex-a320"; ++#ifdef CONFIG_GIC_V3 ++ reg = <0x100>; ++#else + reg = <0x1>; ++#endif + enable-method = "psci"; + next-level-cache = <&L2_0>; + }; + + cpu2: cpu@2 { + device_type = "cpu"; +- compatible = "arm,cortex-a35"; ++ compatible = "arm,cortex-a35","arm,cortex-a320"; ++#ifdef CONFIG_GIC_V3 ++ reg = <0x200>; ++#else + reg = <0x2>; ++#endif + enable-method = "psci"; + next-level-cache = <&L2_0>; + }; + + cpu3: cpu@3 { + device_type = "cpu"; +- compatible = "arm,cortex-a35"; ++ compatible = "arm,cortex-a35","arm,cortex-a320"; ++#ifdef CONFIG_GIC_V3 ++ reg = <0x300>; ++#else + reg = <0x3>; ++#endif + enable-method = "psci"; + next-level-cache = <&L2_0>; + }; +diff --git a/arch/arm/dts/corstone1000-u-boot.dtsi b/arch/arm/dts/corstone1000-u-boot.dtsi +index b29ac74217e..206403ea9a5 100644 +--- a/arch/arm/dts/corstone1000-u-boot.dtsi ++++ b/arch/arm/dts/corstone1000-u-boot.dtsi +@@ -29,6 +29,15 @@ + }; + }; + ++&{/cpus} { ++ cpu: cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a35","arm,cortex-a320"; ++ reg = <0>; ++ next-level-cache = <&L2_0>; ++ }; ++}; ++ + &{/soc} { + extsys0: remoteproc@1a010310 { + compatible = "arm,corstone1000-extsys"; +@@ -37,3 +46,70 @@ + firmware-name = "es_flashfw.elf"; + }; + }; ++ ++#ifdef CONFIG_ETHOS_U85 ++&{/reserved-memory} { ++ ethosu_sram: ethosu_sram@02400000 { ++ reg = <0x02400000 0x200000>; ++ no-map; ++ }; ++ ++ ethosu_reserved: ethosu_reserved@A0000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0xA0000000 0x02000000>; ++ no-map; ++ }; ++}; ++ ++/ { ++ ethosu: ethosu@1A050000 { ++ compatible = "arm,ethosu-direct"; ++ ++ // Base address and size of NPU registers ++ reg = <0x1A050000 0x4000>; ++ ++ memory-region = <ðosu_reserved>; ++ sram = <ðosu_sram>; ++ ++ // Address mappings to translate between bus addresses (NPU) and physical host CPU addresses ++ dma-ranges = <0x02400000 0x02400000 0x200000>, ++ <0xA0000000 0xA0000000 0x02000000>; ++ ++ interrupts = <0 16 4>; ++ interrupt-names = "irq"; ++ ++ // Memory region configuration ++ region-cfgs = <3 3 0 3 3 3 3 3>; ++ ++ // Memory regions used for the command stream ++ cs-region = <2>; ++ ++ // Memory interface configuration for Ethos-U85 ++ ethosu_mem_config { ++ compatible = "arm,ethosu-mem-config"; ++ // ++ sram = <0 64 32>; ++ ext = <1 64 32>; ++ // ++ configs = <0 0 0>, ++ <0 0 0>, ++ <0 0 1>, ++ <0 0 1>; ++ }; ++ }; ++}; ++#endif ++#ifdef CONFIG_GIC_V3 ++gic: &{/interrupt-controller@1c000000} { ++ compatible = "arm,gic-v3"; ++ #interrupt-cells = <3>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ interrupt-controller; ++ reg = <0x1c000000 0x00010000>, ++ <0x1c040000 0x00080000>; ++ interrupts = ; ++ }; ++#endif ++ +diff --git a/arch/arm/include/asm/armv8/cpu.h b/arch/arm/include/asm/armv8/cpu.h +index 4dbb589aab8..ffd8f8f358f 100644 +--- a/arch/arm/include/asm/armv8/cpu.h ++++ b/arch/arm/include/asm/armv8/cpu.h +@@ -8,6 +8,7 @@ + #define MIDR_PARTNUM_CORTEX_A57 0xD07 + #define MIDR_PARTNUM_CORTEX_A72 0xD08 + #define MIDR_PARTNUM_CORTEX_A76 0xD0B ++#define MIDR_PARTNUM_CORTEX_A320 0xD8F + #define MIDR_PARTNUM_SHIFT 0x4 + #define MIDR_PARTNUM_MASK (0xFFF << MIDR_PARTNUM_SHIFT) + +diff --git a/board/armltd/corstone1000/Kconfig b/board/armltd/corstone1000/Kconfig +index 709674d4cf7..9476d64d0b0 100644 +--- a/board/armltd/corstone1000/Kconfig ++++ b/board/armltd/corstone1000/Kconfig +@@ -9,4 +9,11 @@ config SYS_VENDOR + config SYS_CONFIG_NAME + default "corstone1000" + ++config ETHOS_U85 ++ bool "Enable Arm Ethos-U85 NPU support" ++ default n ++ ++config GIC_V3 ++ bool "Enable GIC v3 support" ++ default n + endif +-- +2.50.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/corstone1000-a320.cfg b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/corstone1000-a320.cfg new file mode 100644 index 00000000..866b983f --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/corstone1000-a320.cfg @@ -0,0 +1,2 @@ +CONFIG_ETHOS_U85=y +CONFIG_GIC_V3=y From patchwork Thu Dec 4 15:19:53 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Hugues KAMBA MPIANA X-Patchwork-Id: 75899 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 54CA0D206B5 for ; Thu, 4 Dec 2025 15:25:27 +0000 (UTC) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.46553.1764861919421893607 for ; Thu, 04 Dec 2025 07:25:19 -0800 Authentication-Results: mx.groups.io; dkim=none (message not signed); spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: hugues.kambampiana@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id A53BA339; Thu, 4 Dec 2025 07:25:11 -0800 (PST) Received: from LXKV206JHX.arm.com (unknown [10.57.43.122]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 60E723F59E; Thu, 4 Dec 2025 07:25:18 -0800 (PST) From: Hugues KAMBA MPIANA To: meta-arm@lists.yoctoproject.org Cc: Hugues KAMBA MPIANA Subject: [PATCH 6/6] arm-bsp/docs:corstone1000: Add Corstone-1000 with Cortex-A320 Date: Thu, 4 Dec 2025 15:19:53 +0000 Message-ID: <20251204152500.78818-7-hugues.kambampiana@arm.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20251204152500.78818-1-hugues.kambampiana@arm.com> References: <20251204152500.78818-1-hugues.kambampiana@arm.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Thu, 04 Dec 2025 15:25:27 -0000 X-Groupsio-URL: https://lists.yoctoproject.org/g/meta-arm/message/6785 - Document Corstone‑1000 platform architecture based on the Cortex‑A320 core - Add test specification and guide for Corstone‑1000 with Cortex‑A320 Signed-off-by: Hugues KAMBA MPIANA --- .../images/CorstoneA320Subsystems.png | Bin 0 -> 55372 bytes .../corstone1000/software-architecture.rst | 13 ++ .../documentation/corstone1000/user-guide.rst | 126 ++++++++++++++++-- 3 files changed, 129 insertions(+), 10 deletions(-) create mode 100644 meta-arm-bsp/documentation/corstone1000/images/CorstoneA320Subsystems.png diff --git a/meta-arm-bsp/documentation/corstone1000/images/CorstoneA320Subsystems.png b/meta-arm-bsp/documentation/corstone1000/images/CorstoneA320Subsystems.png new file mode 100644 index 0000000000000000000000000000000000000000..d3022a16379ce149c19d63b6a29c34a036fb159f GIT binary patch literal 55372 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 literal 0 HcmV?d00001 diff --git a/meta-arm-bsp/documentation/corstone1000/software-architecture.rst b/meta-arm-bsp/documentation/corstone1000/software-architecture.rst index c5bfea33..e4f407d8 100644 --- a/meta-arm-bsp/documentation/corstone1000/software-architecture.rst +++ b/meta-arm-bsp/documentation/corstone1000/software-architecture.rst @@ -116,6 +116,19 @@ The Corstone-1000 architecture is designed to cover a range of `Power, Performance, and Area (PPA) `__ applications, and enable extension for use-case specific applications, for example, sensors, cloud connectivity, and edge computing. +************************************** +Corstone-1000 with Cortex-A320 Variant +************************************** + +This variant of the Corstone-1000 platform replaces the Host System's Cortex-A35 processor +with a Cortex-A320. In this configuration, the optional External System (previously a Cortex-M3) +is replaced by an Arm Ethos-U85 Neural Processing Unit (NPU). +The Ethos-U85 runs in the direct drive configuration, where the Host System is responsible for managing the NPU directly. + +.. image:: images/CorstoneA320Subsystems.png + :width: 720 + :alt: CorstoneA320Subsystems + ***************** Secure Boot Chain ***************** diff --git a/meta-arm-bsp/documentation/corstone1000/user-guide.rst b/meta-arm-bsp/documentation/corstone1000/user-guide.rst index a6834a34..e22406a0 100644 --- a/meta-arm-bsp/documentation/corstone1000/user-guide.rst +++ b/meta-arm-bsp/documentation/corstone1000/user-guide.rst @@ -223,7 +223,7 @@ Build .. code-block:: console cd ${WORKSPACE} - git clone https://git.yoctoproject.org/git/meta-arm -b CORSTONE1000-2025.05 + git clone https://git.yoctoproject.org/git/meta-arm -b CORSTONE1000-2025.12 #. Build a Corstone-1000 image: @@ -243,13 +243,28 @@ Build .. warning:: + **The External System Processor is not available on the Corstone-1000 with Cortex-A320 FVP.** + Access to the External System Processor is disabled by default. + To build the Corstone-1000 image with External System Processor enabled, run: .. code-block:: console kas build meta-arm/kas/corstone1000-${TARGET}.yml:meta-arm/ci/debug.yml:meta-arm/kas/corstone1000-extsys.yml + .. warning:: + + **The Ethos-U85 Neural Processing Unit (NPU) is only available on + the Corstone-1000 with Cortex-A320 FVP.** + + To build the Corstone-1000 image with the Ethos-U85 NPU enabled, run: + + .. code-block:: console + + kas build meta-arm/kas/corstone1000-fvp.yml:meta-arm/ci/debug.yml:meta-arm/kas/corstone1000-a320.yml + + A clean build takes a significant amount of time given that all of the development machine utilities are also built along with the target images. Those development machine utilities include executables (Python, CMake, etc.) and the required toolchains. @@ -442,9 +457,14 @@ Corstone-1000 FVP software image. A Yocto recipe is provided to download the latest supported FVP version. The recipe is located at ``${WORKSPACE}/meta-arm/meta-arm/recipes-devtools/fvp/fvp-corstone1000.bb``. +This recipe supports selecting different Corstone‑1000 FVP models via MACHINE_FEATURES: -The latest FVP version is ``11.23.25`` and is automatically downloaded and installed when using the -``runfvp`` command as detailed below. +- ``cortexa320`` use the Cortex-A320 Host Processor with Ethos U85 enabled FVP build +- (default) use the Cortex-A35 Host Processor with Cortex-M3 External System FVP build + +The latest FVP version is ``11.23.25`` for Corstone-1000 with Cortex-A35 and ``11.30.27`` for +Corstone-1000 with Cortex-A320, and each model is automatically downloaded and installed when using +the ``runfvp`` command as detailed below. .. note:: @@ -496,8 +516,8 @@ Tests Reports ------- -Reports for the tests conducted on the `Corstone-1000 software (CORSTONE1000-2025.05) `__ -release are available for reference `here `__. +Reports for the tests conducted on the `Corstone-1000 software (CORSTONE1000-2025.12) `__ +release are available for reference `here `__. .. _clean-secure-flash: @@ -516,7 +536,7 @@ Clean Secure Flash .. code-block:: console cd ${WORKSPACE} - git clone https://git.gitlab.arm.com/arm-reference-solutions/systemready-patch.git -b CORSTONE1000-2025.05 + git clone https://git.gitlab.arm.com/arm-reference-solutions/systemready-patch.git -b CORSTONE1000-2025.12 #. Copy the secure flash cleaning Git patch file to your copy of `meta-arm`. @@ -838,6 +858,33 @@ The results can be fetched from the `acs_results` folder in the ``BOOT`` partiti Capsule Update -------------- +.. warning:: + + The **Corstone-1000 with Cortex-A320 FVP** becomes unresponsive when the Linux kernel driver for the + Ethos-U85 NPU loads automatically after a software reboot. + This behavior results from a power reset control issue in the **Corstone-1000 with Cortex-A320 FVP** model. + To prevent the failure and complete the test successfully, + rebuild the **Corstone-1000 with Cortex-A320** firmware image using the following steps: + + + #. Clone the `systemready-patch` repository to your ``${WORKSPACE}``. + + .. code-block:: console + + cd ${WORKSPACE} + git clone https://git.gitlab.arm.com/arm-reference-solutions/systemready-patch.git \ + -b CORSTONE1000-2025.12 + + + #. Re-Build the **Corstone-1000 with Cortex-A320 FVP** software stack as follows: + + .. code-block:: console + + kas build meta-arm/kas/corstone1000-fvp.yml:meta-arm/ci/debug.yml:meta-arm/kas/corstone1000-a320.yml:\ + systemready-patch/embedded-a/corstone1000/disable_module_autoloading/disable_module_autoloading.yml + + + The following section describes the steps to update the firmware using Capsule Update as the Corstone-1000 supports UEFI. @@ -866,10 +913,10 @@ Generate Capsules `EDK II's `__ ``GenerateCapsule`` tool is used to generate capsules and is built automatically for the host machine during the firmware image building process. -The tool can be found in the ``${WORKSPACE}/build/tmp/sysroots-components/aarch64/edk2-basetools-native/usr/bin/edk2-BaseTools/BinWrappers/PosixLike/GenerateCapsule`` directory. +The tool can be found at ``${WORKSPACE}/build/tmp/sysroots-components/aarch64/edk2-basetools-native/usr/bin/edk2-BaseTools/BinWrappers/PosixLike/GenerateCapsule``. A JSON file containing metadata about the capsule payloads needs to be created using the script -found at ``${WORKSPACE}/meta-arm/scripts/generate_capsule_json_multiple.py``. +found at ``${WORKSPACE}/meta-arm/meta-arm/scripts/generate_capsule_json_multiple.py``. This JSON file is required by EDK II's ``GenerateCapsule`` tool to generate the capsule. The capsule's default metadata passed can be found in the ``${WORKSPACE}/meta-arm/meta-arm-bsp/recipes-bsp/images/corstone1000-flash-firmware-image.bb`` @@ -1712,7 +1759,7 @@ Generate Keys, Signed Image and Unsigned Image git clone https://gitlab.arm.com/arm-reference-solutions/systemready-patch \ - -b CORSTONE1000-2025.05 + -b CORSTONE1000-2025.12 #. Set the current working directory to build directory's subdirectory containing the software stack build images. @@ -2011,7 +2058,7 @@ Symmetric Multiprocessing .. warning:: - Symmetric multiprocessing (SMP) mode is only supported on FVP but is disabled by default. + Symmetric multiprocessing (SMP) mode is only supported on Corstone-1000 with Cortex-A35 FVP but is disabled by default. #. Build the software stack with SMP mode enabled: @@ -2035,6 +2082,65 @@ Symmetric Multiprocessing nproc 4 # number of processing units +Ethos-U85 NPU +------------- + +.. warning:: + + The Ethos-U85 NPU is only supported on Corstone-1000 with Cortex-A320 FVP. + + +#. Clone the `systemready-patch` repository to your ``${WORKSPACE}``. + + .. code-block:: console + + cd ${WORKSPACE} + git clone https://git.gitlab.arm.com/arm-reference-solutions/systemready-patch.git \ + -b CORSTONE1000-2025.12 + +#. Re-Build the Corstone-1000 with Cortex-A320 FVP software stack as follows: + + .. code-block:: console + + kas build meta-arm/kas/corstone1000-fvp.yml:meta-arm/ci/debug.yml:meta-arm/kas/corstone1000-a320.yml:\ + systemready-patch/embedded-a/corstone1000/ethos-u85_test/ethos-u85_test.yml + +#. Run the Corstone-1000 with Cortex-320 FVP: + + .. code-block:: console + + kas shell meta-arm/kas/corstone1000-fvp.yml:meta-arm/ci/debug.yml:meta-arm/kas/corstone1000-a320.yml:\ + systemready-patch/embedded-a/corstone1000/ethos-u85_test/ethos-u85_test.yml \ + -c "../meta-arm/scripts/runfvp" + +#. To verify you are running the Corstone-1000 with Cortex-A320, build and run the FVP and inspect the CPU model + reported in ``/proc/cpuinfo`` as shown below. Inside the FVP shell, confirm the core type: + + + .. code-block:: console + + grep -E 'CPU part|model name' /proc/cpuinfo + # Expect: CPU part : 0xd8f (which corresponds to Cortex-A320) + +#. Run the `delegate_runner` test application inside the FVP shell as follows: + + .. code-block:: console + + delegate_runner -l /usr/lib/libethosu_op_delegate.so \ + -n /usr/share/ethosu/mobilenet_v2_1.0_224_INT8_vela.tflite \ + -i /usr/share/ethosu/input_data0.bin \ + -o /usr/share/ethosu/actual_output_data0.bin + + The test completes in approximately one minute. + +#. Run the following command to compare the generated output binary with the expected output binary: + + .. code-block:: console + + cmp -s /usr/share/ethosu/expected_output_data0.bin /usr/share/ethosu/actual_output_data0.bin + + The two binary files should be identical. + Secure Debug ------------