diff --git a/changelog.yaml b/changelog.yaml index 47cfc1e4f..3534cb01b 100644 --- a/changelog.yaml +++ b/changelog.yaml @@ -628,6 +628,13 @@ subsections: - plat/zynqmp - plat/xilinx/zynqmp + - title: Nuvoton + scope: nuvoton + + subsections: + - title: npcm845x + scope: npcm845x + - title: Bootloader Images scope: bl diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst index 3de09c716..20c56fd60 100644 --- a/docs/about/maintainers.rst +++ b/docs/about/maintainers.rst @@ -585,6 +585,20 @@ Marvell platform ports and SoC drivers :|F|: drivers/marvell/ :|F|: tools/marvell/ +Nuvoton npcm845x platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Hila Miranda-Kuzi +:|G|: `hilamirandakuzi1`_ +:|M|: Margarita Glushkin +:|G|: `rutigl`_ +:|M|: Avi Fishman +:|G|: `avifishman`_ +:|F|: docs/plat/npcm845x.rst +:|F|: drivers/nuvoton/ +:|F|: include/drivers/nuvoton/ +:|F|: include/plat/nuvoton/ +:|F|: plat/nuvoton/ + NVidia platform ports ^^^^^^^^^^^^^^^^^^^^^ :|M|: Varun Wadekar @@ -1002,3 +1016,6 @@ Conventional Changelog Extensions .. _Neal-liu: https://github.com/neal-liu .. _amit-nagal: https://github.com/amit-nagal .. _Akshay-Belsare: https://github.com/Akshay-Belsare +.. _hilamirandakuzi1: https://github.com/hilamirandakuzi1 +.. _rutigl: https://github.com/rutigl +.. _avifishman: https://github.com/avifishman diff --git a/docs/plat/index.rst b/docs/plat/index.rst index fe2cc444a..2eec68cf9 100644 --- a/docs/plat/index.rst +++ b/docs/plat/index.rst @@ -28,6 +28,7 @@ Platform Ports imx8 imx8m imx9 + npcm845x nxp/index poplar qemu diff --git a/docs/plat/npcm845x.rst b/docs/plat/npcm845x.rst new file mode 100644 index 000000000..91dbfd9b4 --- /dev/null +++ b/docs/plat/npcm845x.rst @@ -0,0 +1,21 @@ +Nuvoton NPCM845X +================ + +Nuvoton NPCM845X is the Nuvoton Arbel NPCM8XX Board Management controller (BMC) SoC. + +The Nuvoton Arbel NPCM845X SoC is a fourth-generation BMC. +The NPCM845X computing subsystem comprises a quadcore Arm Cortex-A35 CPU. + +This SoC includes secured components, i.e., bootblock stored in ROM, +u-boot, OPTEE-OS, trusted-firmware-a and Linux. +Every stage is measured and validated by the bootblock. +This SoC was tested on the Arbel NPCM845X evaluation board. + + +How to Build +------------ + +.. code:: shell + + make CROSS_COMPILE=aarch64-none-elf- PLAT=npcm845x all SPD=opteed + diff --git a/include/drivers/nuvoton/npcm845x/npcm845x_clock.h b/include/drivers/nuvoton/npcm845x/npcm845x_clock.h new file mode 100644 index 000000000..3c457d7a6 --- /dev/null +++ b/include/drivers/nuvoton/npcm845x/npcm845x_clock.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2017-2023 Nuvoton Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __ARBEL_CLOCK_H_ +#define __ARBEL_CLOCK_H_ + +struct clk_ctl { + unsigned int clken1; + unsigned int clksel; + unsigned int clkdiv1; + unsigned int pllcon0; + unsigned int pllcon1; + unsigned int swrstr; + unsigned char res1[0x8]; + unsigned int ipsrst1; + unsigned int ipsrst2; + unsigned int clken2; + unsigned int clkdiv2; + unsigned int clken3; + unsigned int ipsrst3; + unsigned int wd0rcr; + unsigned int wd1rcr; + unsigned int wd2rcr; + unsigned int swrstc1; + unsigned int swrstc2; + unsigned int swrstc3; + unsigned int tiprstc; + unsigned int pllcon2; + unsigned int clkdiv3; + unsigned int corstc; + unsigned int pllcong; + unsigned int ahbckfi; + unsigned int seccnt; + unsigned int cntr25m; + unsigned int clken4; + unsigned int ipsrst4; + unsigned int busto; + unsigned int clkdiv4; + unsigned int wd0rcrb; + unsigned int wd1rcrb; + unsigned int wd2rcrb; + unsigned int swrstc1b; + unsigned int swrstc2b; + unsigned int swrstc3b; + unsigned int tiprstcb; + unsigned int corstcb; + unsigned int ipsrstdis1; + unsigned int ipsrstdis2; + unsigned int ipsrstdis3; + unsigned int ipsrstdis4; + unsigned char res2[0x10]; + unsigned int thrtl_cnt; +}; + +#endif /* __ARBEL_CLOCK_H_ */ diff --git a/include/drivers/nuvoton/npcm845x/npcm845x_gcr.h b/include/drivers/nuvoton/npcm845x/npcm845x_gcr.h new file mode 100644 index 000000000..b9f3048cd --- /dev/null +++ b/include/drivers/nuvoton/npcm845x/npcm845x_gcr.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2022-2023 Nuvoton Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __NPCM845x_GCR_H_ +#define __NPCM845x_GCR_H_ + +struct npcm845x_gcr { + unsigned int pdid; + unsigned int pwron; + unsigned int swstrps; + unsigned int rsvd1[2]; + unsigned int miscpe; + unsigned int spldcnt; + unsigned int rsvd2[1]; + unsigned int flockr2; + unsigned int flockr3; + unsigned int rsvd3[3]; + unsigned int a35_mode; + unsigned int spswc; + unsigned int intcr; + unsigned int intsr; + unsigned int obscr1; + unsigned int obsdr1; + unsigned int rsvd4[1]; + unsigned int hifcr; + unsigned int rsvd5[3]; + unsigned int intcr2; + unsigned int rsvd6[1]; + unsigned int srcnt; + unsigned int ressr; + unsigned int rlockr1; + unsigned int flockr1; + unsigned int dscnt; + unsigned int mdlr; + unsigned int scrpad_c; + unsigned int scrpad_b; + unsigned int rsvd7[4]; + unsigned int daclvlr; + unsigned int intcr3; + unsigned int pcirctl; + unsigned int rsvd8[2]; + unsigned int vsintr; + unsigned int rsvd9[1]; + unsigned int sd2sur1; + unsigned int sd2sur2; + unsigned int sd2irv3; + unsigned int intcr4; + unsigned int obscr2; + unsigned int obsdr2; + unsigned int rsvd10[5]; + unsigned int i2csegsel; + unsigned int i2csegctl; + unsigned int vsrcr; + unsigned int mlockr; + unsigned int rsvd11[8]; + unsigned int etsr; + unsigned int dft1r; + unsigned int dft2r; + unsigned int dft3r; + unsigned int edffsr; + unsigned int rsvd12[1]; + unsigned int intcrpce3; + unsigned int intcrpce2; + unsigned int intcrpce0; + unsigned int intcrpce1; + unsigned int dactest; + unsigned int scrpad; + unsigned int usb1phyctl; + unsigned int usb2phyctl; + unsigned int usb3phyctl; + unsigned int intsr2; + unsigned int intcrpce2b; + unsigned int intcrpce0b; + unsigned int intcrpce1b; + unsigned int intcrpce3b; + unsigned int rsvd13[4]; + unsigned int intcrpce2c; + unsigned int intcrpce0c; + unsigned int intcrpce1c; + unsigned int intcrpce3c; + unsigned int rsvd14[40]; + unsigned int sd2irv4; + unsigned int sd2irv5; + unsigned int sd2irv6; + unsigned int sd2irv7; + unsigned int sd2irv8; + unsigned int sd2irv9; + unsigned int sd2irv10; + unsigned int sd2irv11; + unsigned int rsvd15[8]; + unsigned int mfsel1; + unsigned int mfsel2; + unsigned int mfsel3; + unsigned int mfsel4; + unsigned int mfsel5; + unsigned int mfsel6; + unsigned int mfsel7; + unsigned int rsvd16[1]; + unsigned int mfsel_lk1; + unsigned int mfsel_lk2; + unsigned int mfsel_lk3; + unsigned int mfsel_lk4; + unsigned int mfsel_lk5; + unsigned int mfsel_lk6; + unsigned int mfsel_lk7; + unsigned int rsvd17[1]; + unsigned int mfsel_set1; + unsigned int mfsel_set2; + unsigned int mfsel_set3; + unsigned int mfsel_set4; + unsigned int mfsel_set5; + unsigned int mfsel_set6; + unsigned int mfsel_set7; + unsigned int rsvd18[1]; + unsigned int mfsel_clr1; + unsigned int mfsel_clr2; + unsigned int mfsel_clr3; + unsigned int mfsel_clr4; + unsigned int mfsel_clr5; + unsigned int mfsel_clr6; + unsigned int mfsel_clr7; +}; + +#endif diff --git a/include/drivers/nuvoton/npcm845x/npcm845x_lpuart.h b/include/drivers/nuvoton/npcm845x/npcm845x_lpuart.h new file mode 100644 index 000000000..8962b904b --- /dev/null +++ b/include/drivers/nuvoton/npcm845x/npcm845x_lpuart.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2015-2023, ARM Limited and Contributors. All rights reserved. + * + * Copyright (C) 2022-2023 Nuvoton Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __ASM_ARCH_UART_H_ +#define __ASM_ARCH_UART_H_ + +#ifndef __ASSEMBLY__ + +struct npcmX50_uart { + union { + unsigned int rbr; + unsigned int thr; + unsigned int dll; + }; + union { + unsigned int ier; + unsigned int dlm; + }; + union { + unsigned int iir; + unsigned int fcr; + }; + unsigned int lcr; + unsigned int mcr; + unsigned int lsr; + unsigned int msr; + unsigned int tor; +}; + +typedef enum { + /* + * UART0 is a general UART block without modem-I/O-control + * connection to external signals. + */ + UART0_DEV = 0, + /* + * UART1-3 are each a general UART with modem-I/O-control + * connection to external signals. + */ + UART1_DEV, + UART2_DEV, + UART3_DEV, +} UART_DEV_T; + +typedef enum { + /* + * 0 0 0: Mode 1: + * HSP1 connected to SI2, + * HSP2 connected to UART2, + * UART1 snoops HSP1, + * UART3 snoops SI2 + */ + UART_MUX_MODE1 = 0, + /* + * 0 0 1: Mode 2: + * HSP1 connected to UART1, + * HSP2 connected to SI2, + * UART2 snoops HSP2, + * UART3 snoops SI2 + */ + UART_MUX_MODE2, + /* + * 0 1 0: Mode 3: + * HSP1 connected to UART1, + * HSP2 connected to UART2, + * UART3 connected to SI2 + */ + UART_MUX_MODE3, + /* + * 0 1 1: Mode 4: + * HSP1 connected to SI1, + * HSP2 connected to SI2, + * UART1 snoops SI1, + * UART3 snoops SI2, + * UART2 snoops HSP1 (default) + */ + UART_MUX_MODE4, + /* + * 1 0 0: Mode 5: + * HSP1 connected to SI1, + * HSP2 connected to UART2, + * UART1 snoops HSP1, + * UART3 snoops SI1 + */ + UART_MUX_MODE5, + /* + * 1 0 1: Mode 6: + * HSP1 connected to SI1, + * HSP2 connected to SI2, + * UART1 snoops SI1, + * UART3 snoops SI2, + * UART2 snoops HSP2 + */ + UART_MUX_MODE6, + /* + * 1 1 0: Mode 7: + * HSP1 connected to SI1, + * HSP2 connected to UART2, + * UART1 snoops HSP1, + * UART3 connected to SI2 + */ + UART_MUX_MODE7, + /* Skip UART mode configuration. */ + UART_MUX_RESERVED, + /* + * A SW option to allow config of UART + * without touching the UART mux. + */ + UART_MUX_SKIP_CONFIG +} UART_MUX_T; + +/*---------------------------------------------------------------------------*/ +/* Common baudrate definitions */ +/*---------------------------------------------------------------------------*/ +typedef enum { + UART_BAUDRATE_110 = 110, + UART_BAUDRATE_300 = 300, + UART_BAUDRATE_600 = 600, + UART_BAUDRATE_1200 = 1200, + UART_BAUDRATE_2400 = 2400, + UART_BAUDRATE_4800 = 4800, + UART_BAUDRATE_9600 = 9600, + UART_BAUDRATE_14400 = 14400, + UART_BAUDRATE_19200 = 19200, + UART_BAUDRATE_38400 = 38400, + UART_BAUDRATE_57600 = 57600, + UART_BAUDRATE_115200 = 115200, + UART_BAUDRATE_230400 = 230400, + UART_BAUDRATE_380400 = 380400, + UART_BAUDRATE_460800 = 460800, +} UART_BAUDRATE_T; + +/*---------------------------------------------------------------------------*/ +/* UART parity types */ +/*---------------------------------------------------------------------------*/ +typedef enum { + UART_PARITY_NONE = 0, + UART_PARITY_EVEN, + UART_PARITY_ODD, +} UART_PARITY_T; + +/*---------------------------------------------------------------------------*/ +/* Uart stop bits */ +/*---------------------------------------------------------------------------*/ +typedef enum { + UART_STOPBIT_1 = 0x00, + UART_STOPBIT_DYNAMIC, +} UART_STOPBIT_T; + +enum FCR_RFITL_TYPE { + FCR_RFITL_1B = 0x0, + FCR_RFITL_4B = 0x4, + FCR_RFITL_8B = 0x8, + FCR_RFITL_14B = 0xC, +}; + +enum LCR_WLS_TYPE { + LCR_WLS_5bit = 0x0, + LCR_WLS_6bit = 0x1, + LCR_WLS_7bit = 0x2, + LCR_WLS_8bit = 0x3, +}; + +#define IER_DBGACK (1 << 4) +#define IER_MSIE (1 << 3) +#define IER_RLSE (1 << 2) +#define IER_THREIE (1 << 1) +#define IER_RDAIE (1 << 0) + +#define IIR_FMES (1 << 7) +#define IIR_RFTLS (1 << 5) +#define IIR_DMS (1 << 4) +#define IIR_IID (1 << 1) +#define IIR_NIP (1 << 0) + +#define FCR_RFITL_1B (0 << 4) +#define FCR_RFITL_4B (4 << 4) +#define FCR_RFITL_8B (8 << 4) +#define FCR_RFITL_14B (12 << 4) +#define FCR_DMS (1 << 3) +#define FCR_TFR (1 << 2) +#define FCR_RFR (1 << 1) +#define FCR_FME (1 << 0) + +#define LCR_DLAB (1 << 7) +#define LCR_BCB (1 << 6) +#define LCR_SPE (1 << 5) +#define LCR_EPS (1 << 4) +#define LCR_PBE (1 << 3) +#define LCR_NSB (1 << 2) +#define LCR_WLS_8b (3 << 0) +#define LCR_WLS_7b (2 << 0) +#define LCR_WLS_6b (1 << 0) +#define LCR_WLS_5b (0 << 0) + +#define MCR_LBME (1 << 4) +#define MCR_OUT2 (1 << 3) +#define MCR_RTS (1 << 1) +#define MCR_DTR (1 << 0) + +#define LSR_ERR_RX (1 << 7) +#define LSR_TE (1 << 6) +#define LSR_THRE (1 << 5) +#define LSR_BII (1 << 4) +#define LSR_FEI (1 << 3) +#define LSR_PEI (1 << 2) +#define LSR_OEI (1 << 1) +#define LSR_RFDR (1 << 0) + +#define MSR_DCD (1 << 7) +#define MSR_RI (1 << 6) +#define MSR_DSR (1 << 5) +#define MSR_CTS (1 << 4) +#define MSR_DDCD (1 << 3) +#define MSR_DRI (1 << 2) +#define MSR_DDSR (1 << 1) +#define MSR_DCTS (1 << 0) + +#endif /* __ASSEMBLY__ */ + +uintptr_t npcm845x_get_base_uart(UART_DEV_T dev); +void CLK_ResetUART(void); +int UART_Init(UART_DEV_T devNum, UART_BAUDRATE_T baudRate); + +#endif /* __ASM_ARCH_UART_H_ */ diff --git a/include/plat/nuvoton/common/npcm845x_arm_def.h b/include/plat/nuvoton/common/npcm845x_arm_def.h new file mode 100644 index 000000000..faddb88c2 --- /dev/null +++ b/include/plat/nuvoton/common/npcm845x_arm_def.h @@ -0,0 +1,576 @@ +/* + * Copyright (c) 2015-2023, ARM Limited and Contributors. All rights reserved. + * + * Copyright (C) 2017-2023 Nuvoton Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef NPCM845x_ARM_DEF_H +#define NPCM845x_ARM_DEF_H + +#include +#include +#include +#include +#include +#include +#include +#include + +/* This flag will add zones to the MMU so that it will be possible to debug */ +#ifdef NPCM845X_DEBUG +#define ALLOW_DEBUG_MMU +#undef ALLOW_DEBUG_MMU +#endif /* NPCM845X_DEBUG */ + +#undef CONFIG_TARGET_ARBEL_PALLADIUM +/****************************************************************************** + * Definitions common to all ARM standard platforms + *****************************************************************************/ + +/* + * Root of trust key hash lengths + */ +#define ARM_ROTPK_HEADER_LEN 19 +#define ARM_ROTPK_HASH_LEN 32 + +/* Special value used to verify platform parameters from BL2 to BL31 */ +#define ARM_BL31_PLAT_PARAM_VAL ULL(0x0f1e2d3c4b5a6978) + +/* No need for system because we have only one cluster */ +#define ARM_SYSTEM_COUNT U(0) + +#define ARM_CACHE_WRITEBACK_SHIFT 6 + +/* + * Macros mapping the MPIDR Affinity levels to ARM Platform Power levels. + * The power levels have a 1:1 mapping with the MPIDR affinity levels. + */ +/* In NPCM845x - refers to cores */ +#define ARM_PWR_LVL0 MPIDR_AFFLVL0 + +/* In NPCM845x - refers to cluster */ +#define ARM_PWR_LVL1 MPIDR_AFFLVL1 + +/* No need for additional settings because the platform doesn't have system */ + +/* + * Macros for local power states in ARM platforms encoded by State-ID field + * within the power-state parameter. + */ +#define NPCM845x_PLAT_PRIMARY_CPU U(0x0) +#define NPCM845x_CLUSTER_COUNT U(1) + +#ifdef SECONDARY_BRINGUP +#define NPCM845x_MAX_CPU_PER_CLUSTER U(2) +#define NPCM845x_PLATFORM_CORE_COUNT U(2) +#define NPCM845x_PLATFORM_CLUSTER0_CORE_COUNT U(2) +#else +#define NPCM845x_MAX_CPU_PER_CLUSTER U(4) +#define NPCM845x_PLATFORM_CORE_COUNT U(4) +#define NPCM845x_PLATFORM_CLUSTER0_CORE_COUNT U(4) +#endif /* SECONDARY_BRINGUP */ + +#define NPCM845x_SYSTEM_COUNT U(0) + +/* Memory mapping for NPCM845x */ +#define NPCM845x_REG_BASE 0xf0000000 +#define NPCM845x_REG_SIZE 0x0ff16000 + +/* + * DRAM + * 0x3fffffff +-------------+ + * | BL33 | (non-secure) + * 0x06200000 +-------------+ + * | BL32 SHARED | (non-secure) + * 0x06000000 +-------------+ + * | BL32 | (secure) + * 0x02100000 +-------------+ + * | BL31 | (secure) + * 0x02000000 +-------------+ + * | | (non-secure) + * 0x00000000 +-------------+ + * + * Trusted ROM + * 0xfff50000 +-------------+ + * | BL1 (ro) | + * 0xfff40000 +-------------+ + */ + +#define ARM_DRAM1_BASE ULL(0x00000000) +#ifndef CONFIG_TARGET_ARBEL_PALLADIUM +/* + * Although npcm845x is 4G, + * consider only 2G Trusted Firmware memory allocation + */ +#define ARM_DRAM1_SIZE ULL(0x37000000) +#else +#define ARM_DRAM1_SIZE ULL(0x10000000) +#define ARM_DRAM1_END (ARM_DRAM1_BASE + ARM_DRAM1_SIZE - 1U) +#endif /* CONFIG_TARGET_ARBEL_PALLADIUM */ + +/* + * The top 16MB of DRAM1 is configured as secure access only using the TZC + * - SCP TZC DRAM: If present, DRAM reserved for SCP use + * - AP TZC DRAM: The remaining TZC secured DRAM reserved for AP use + */ + +/* Check for redundancy */ +#ifdef NPCM845X_DEBUG +#define PLAT_ARM_NS_IMAGE_BASE 0x0 +#endif /* NPCM845X_DEBUG */ + +#define ARM_TZC_DRAM1_SIZE UL(0x01000000) +#define ARM_SCP_TZC_DRAM1_SIZE PLAT_ARM_SCP_TZC_DRAM1_SIZE +#define ARM_SCP_TZC_DRAM1_END (ARM_SCP_TZC_DRAM1_BASE + \ + ARM_SCP_TZC_DRAM1_SIZE - 1U) + +/* + * Define a 2MB region within the TZC secured DRAM for use by EL3 runtime + * firmware. This region is meant to be NOLOAD and will not be zero + * initialized. Data sections with the attribute `arm_el3_tzc_dram` + * will be placed here. + * + * NPCM845x - Currently the platform doesn't have EL3 implementation + * on secured DRAM. + */ +#define ARM_EL3_TZC_DRAM1_BASE (ARM_SCP_TZC_DRAM1_BASE - \ + ARM_EL3_TZC_DRAM1_SIZE) +#define ARM_EL3_TZC_DRAM1_SIZE UL(0x00200000) /* 2 MB */ +#define ARM_EL3_TZC_DRAM1_END (ARM_EL3_TZC_DRAM1_BASE + \ + ARM_EL3_TZC_DRAM1_SIZE - 1U) + +#define ARM_AP_TZC_DRAM1_BASE 0x02100000 +#define ARM_AP_TZC_DRAM1_SIZE (ARM_TZC_DRAM1_SIZE - \ + (ARM_SCP_TZC_DRAM1_SIZE + \ + ARM_EL3_TZC_DRAM1_SIZE)) +#define ARM_AP_TZC_DRAM1_END (ARM_AP_TZC_DRAM1_BASE + \ + ARM_AP_TZC_DRAM1_SIZE - 1U) + +/* Define the Access permissions for Secure peripherals to NS_DRAM */ +#if ARM_CRYPTOCELL_INTEG +/* + * Allow Secure peripheral to read NS DRAM when integrated with CryptoCell. + * This is required by CryptoCell to authenticate BL33 which is loaded + * into the Non Secure DDR. + */ +#define ARM_TZC_NS_DRAM_S_ACCESS TZC_REGION_S_RD +#else +#define ARM_TZC_NS_DRAM_S_ACCESS TZC_REGION_S_NONE +#endif /* ARM_CRYPTOCELL_INTEG */ + +#ifdef SPD_opteed +/* + * BL2 needs to map 4MB at the end of TZC_DRAM1 in order to + * load/authenticate the trusted os extra image. The first 512KB of + * TZC_DRAM1 are reserved for trusted os (OPTEE). The extra image loading + * for OPTEE is paged image which only include the paging part using + * virtual memory but without "init" data. OPTEE will copy the "init" data + * (from pager image) to the first 512KB of TZC_DRAM, and then copy the + * extra image behind the "init" data. + */ +#define TSP_SEC_MEM_BASE ARM_AP_TZC_DRAM1_BASE +#define TSP_SEC_MEM_SIZE ARM_AP_TZC_DRAM1_SIZE +#define BL32_BASE ARM_AP_TZC_DRAM1_BASE +#define BL32_LIMIT (ARM_AP_TZC_DRAM1_BASE + \ + ARM_AP_TZC_DRAM1_SIZE) + +#define ARM_OPTEE_PAGEABLE_LOAD_BASE ( \ + ARM_AP_TZC_DRAM1_BASE + ARM_AP_TZC_DRAM1_SIZE - \ + ARM_OPTEE_PAGEABLE_LOAD_SIZE) +#define ARM_OPTEE_PAGEABLE_LOAD_SIZE UL(0x400000) +#define ARM_OPTEE_PAGEABLE_LOAD_MEM MAP_REGION_FLAT( \ + ARM_OPTEE_PAGEABLE_LOAD_BASE, \ + ARM_OPTEE_PAGEABLE_LOAD_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +/* + * Map the memory for the OP-TEE core (also known as OP-TEE pager + * when paging support is enabled). + */ +#define ARM_MAP_OPTEE_CORE_MEM MAP_REGION_FLAT( \ + BL32_BASE, BL32_LIMIT - BL32_BASE, \ + MT_MEMORY | MT_RW | MT_SECURE) +#endif /* SPD_opteed */ + +#define ARM_NS_DRAM1_BASE ARM_DRAM1_BASE +#define ARM_NS_DRAM1_SIZE (ARM_DRAM1_SIZE - \ + ARM_TZC_DRAM1_SIZE) +#define ARM_NS_DRAM1_END (ARM_NS_DRAM1_BASE + \ + ARM_NS_DRAM1_SIZE - 1U) + +/* The platform doesn't use DRAM2 but it has to have a value for calculation */ +#define ARM_DRAM2_BASE 0 /* PLAT_ARM_DRAM_BASE */ +#define ARM_DRAM2_SIZE 1 /* PLAT_ARM_DRAM_SIZE */ +#define ARM_DRAM2_END (ARM_DRAM2_BASE + ARM_DRAM2_SIZE - 1U) + +#define FIRST_EXT_INTERRUPT_NUM U(32) +#define ARM_IRQ_SEC_PHY_TIMER (U(29) + FIRST_EXT_INTERRUPT_NUM) + +#define ARM_IRQ_SEC_SGI_0 8 +#define ARM_IRQ_SEC_SGI_1 9 +#define ARM_IRQ_SEC_SGI_2 10 +#define ARM_IRQ_SEC_SGI_3 11 +#define ARM_IRQ_SEC_SGI_4 12 +#define ARM_IRQ_SEC_SGI_5 13 +#define ARM_IRQ_SEC_SGI_6 14 +#define ARM_IRQ_SEC_SGI_7 15 + +/* + * Define a list of Group 1 Secure and Group 0 interrupt properties + * as per GICv3 terminology. On a GICv2 system or mode, + * the lists will be merged and treated as Group 0 interrupts. + */ +#define ARM_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, \ + GIC_HIGHEST_SEC_PRIORITY, (grp), GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, \ + GIC_HIGHEST_SEC_PRIORITY, (grp), GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, \ + GIC_HIGHEST_SEC_PRIORITY, (grp), GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, \ + GIC_HIGHEST_SEC_PRIORITY, (grp), GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, \ + GIC_HIGHEST_SEC_PRIORITY, (grp), GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, \ + GIC_HIGHEST_SEC_PRIORITY, (grp), GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, \ + GIC_HIGHEST_SEC_PRIORITY, (grp), GIC_INTR_CFG_EDGE) + +#define ARM_G0_IRQ_PROPS(grp) \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0, \ + PLAT_SDEI_NORMAL_PRI, (grp), GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, \ + GIC_HIGHEST_SEC_PRIORITY, (grp), GIC_INTR_CFG_EDGE) + +#define ARM_MAP_SHARED_RAM MAP_REGION_FLAT( \ + ARM_SHARED_RAM_BASE, ARM_SHARED_RAM_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#ifdef ALLOW_DEBUG_MMU +/* In order to be able to debug, + * the platform needs to add BL33 and BL32 to MMU as well. + */ +#define ARM_MAP_NS_DRAM1 MAP_REGION_FLAT( \ + ARM_NS_DRAM1_BASE, ARM_NS_DRAM1_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#ifdef BL32_BASE +#define ARM_MAP_BL32_CORE_MEM MAP_REGION_FLAT( \ + BL32_BASE, BL32_LIMIT - BL32_BASE, \ + MT_MEMORY | MT_RW | MT_SECURE) +#endif /* BL32_BASE */ + +#ifdef NPCM845X_DEBUG +#define ARM_MAP_SEC_BB_MEM MAP_REGION_FLAT( \ + 0xFFFB0000, 0x20000, \ + MT_MEMORY | MT_RW | MT_NS) +#endif /* NPCM845X_DEBUG */ +#endif /* BL32_BASE */ + +#define ARM_MAP_DRAM2 MAP_REGION_FLAT( \ + ARM_DRAM2_BASE, ARM_DRAM2_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define ARM_MAP_TSP_SEC_MEM MAP_REGION_FLAT( \ + TSP_SEC_MEM_BASE, TSP_SEC_MEM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#if ARM_BL31_IN_DRAM +#define ARM_MAP_BL31_SEC_DRAM MAP_REGION_FLAT( \ + BL31_BASE, PLAT_ARM_MAX_BL31_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) +#endif /* ARM_BL31_IN_DRAM */ + +/* Currently the platform doesn't have EL3 implementation on secured DRAM. */ +#define ARM_MAP_EL3_TZC_DRAM MAP_REGION_FLAT( \ + ARM_EL3_TZC_DRAM1_BASE, \ + ARM_EL3_TZC_DRAM1_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#if defined(SPD_spmd) +#define ARM_MAP_TRUSTED_DRAM MAP_REGION_FLAT( \ + PLAT_ARM_TRUSTED_DRAM_BASE, \ + PLAT_ARM_TRUSTED_DRAM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) +#endif /* SPD_spmd */ + +/* + * Mapping for the BL1 RW region. This mapping is needed by BL2 + * in order to share the Mbed TLS heap. Since the heap is allocated + * inside BL1, it resides in the BL1 RW region. Hence, BL2 needs access + * to the BL1 RW region in order to be able to access the heap. + */ +#define ARM_MAP_BL1_RW MAP_REGION_FLAT( \ + BL1_RW_BASE, BL1_RW_LIMIT - BL1_RW_BASE, \ + MT_MEMORY | MT_RW | EL3_PAS) + +/* + * If SEPARATE_CODE_AND_RODATA=1 the platform will define a region + * for each section, otherwise one region containing both sections + * is defined. + */ +#if SEPARATE_CODE_AND_RODATA +#define ARM_MAP_BL_RO MAP_REGION_FLAT( \ + BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE, \ + MT_CODE | EL3_PAS), \ + MAP_REGION_FLAT(BL_RO_DATA_BASE, \ + BL_RO_DATA_END - BL_RO_DATA_BASE, \ + MT_RO_DATA | EL3_PAS) +#else +#define ARM_MAP_BL_RO MAP_REGION_FLAT( \ + BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE, \ + MT_CODE | EL3_PAS) +#endif /* SEPARATE_CODE_AND_RODATA */ + +#if USE_COHERENT_MEM +#define ARM_MAP_BL_COHERENT_RAM MAP_REGION_FLAT( \ + BL_COHERENT_RAM_BASE, \ + BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, \ + MT_DEVICE | MT_RW | EL3_PAS) +#endif /* USE_COHERENT_MEM */ + +#if USE_ROMLIB +#define ARM_MAP_ROMLIB_CODE MAP_REGION_FLAT( \ + ROMLIB_RO_BASE, \ + ROMLIB_RO_LIMIT - ROMLIB_RO_BASE, \ + MT_CODE | MT_SECURE) + +#define ARM_MAP_ROMLIB_DATA MAP_REGION_FLAT( \ + ROMLIB_RW_BASE, \ + ROMLIB_RW_END - ROMLIB_RW_BASE, \ + MT_MEMORY | MT_RW | MT_SECURE) +#endif /* USE_ROMLIB */ + +/* + * Map mem_protect flash region with read and write permissions + */ +#define ARM_V2M_MAP_MEM_PROTECT MAP_REGION_FLAT( \ + PLAT_ARM_MEM_PROT_ADDR, \ + V2M_FLASH_BLOCK_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) +/* + * Map the region for device tree configuration with read and write permissions + */ +#define ARM_MAP_BL_CONFIG_REGION MAP_REGION_FLAT( \ + ARM_BL_RAM_BASE, \ + (ARM_FW_CONFIGS_LIMIT - ARM_BL_RAM_BASE), \ + MT_MEMORY | MT_RW | MT_SECURE) + +/* + * The max number of regions like RO(code), coherent and data required by + * different BL stages which need to be mapped in the MMU. + */ +#define ARM_BL_REGIONS 10 + +#define MAX_MMAP_REGIONS ( \ + PLAT_ARM_MMAP_ENTRIES + ARM_BL_REGIONS) + +/* Memory mapped Generic timer interfaces */ +#define ARM_SYS_CNTCTL_BASE UL(0XF07FC000) + +#define ARM_CONSOLE_BAUDRATE 115200 + +/* + * The TBBR document specifies a watchdog timeout of 256 seconds. SP805 + * asserts reset after two consecutive countdowns (2 x 128 = 256 sec) + */ +#define ARM_TWDG_TIMEOUT_SEC 128 +#define ARM_TWDG_LOAD_VAL (ARM_SP805_TWDG_CLK_HZ * \ + ARM_TWDG_TIMEOUT_SEC) + +/****************************************************************************** + * Required platform porting definitions common to all ARM standard platforms + *****************************************************************************/ + +/* + * Some data must be aligned on the biggest cache line size in the platform. + * This is known only to the platform as it might have a combination of + * integrated and external caches (64 on Arbel). + */ +#define CACHE_WRITEBACK_GRANULE (U(1) << ARM_CACHE_WRITEBACK_SHIFT) + +/* + * To enable FW_CONFIG to be loaded by BL1, define the corresponding base + * and limit. Leave enough space of BL2 meminfo. + */ +#define ARM_FW_CONFIG_BASE (ARM_BL_RAM_BASE + sizeof(meminfo_t)) +#define ARM_FW_CONFIG_LIMIT ( \ + (ARM_BL_RAM_BASE + PAGE_SIZE) + (PAGE_SIZE / 2U)) + +/* + * Boot parameters passed from BL2 to BL31/BL32 are stored here + */ +#define ARM_BL2_MEM_DESC_BASE (ARM_FW_CONFIG_LIMIT) +#define ARM_BL2_MEM_DESC_LIMIT ( \ + ARM_BL2_MEM_DESC_BASE + (PAGE_SIZE / 2U)) + +/* + * Define limit of firmware configuration memory: + * ARM_FW_CONFIG + ARM_BL2_MEM_DESC memory + */ +#define ARM_FW_CONFIGS_LIMIT (ARM_BL_RAM_BASE + (PAGE_SIZE * 2)) + +/******************************************************************************* + * BL1 specific defines. + * BL1 RW data is relocated from ROM to RAM at runtime so we need + * two sets of addresses. + ******************************************************************************/ +#define BL1_RO_BASE PLAT_ARM_TRUSTED_ROM_BASE +#define BL1_RO_LIMIT (PLAT_ARM_TRUSTED_ROM_BASE + \ + (PLAT_ARM_TRUSTED_ROM_SIZE - PLAT_ARM_MAX_ROMLIB_RO_SIZE)) +/* + * Put BL1 RW at the top of the Trusted SRAM. + */ +#define BL1_RW_BASE (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE - \ + (PLAT_ARM_MAX_BL1_RW_SIZE + PLAT_ARM_MAX_ROMLIB_RW_SIZE)) +#define BL1_RW_LIMIT (ARM_BL_RAM_BASE + \ + (ARM_BL_RAM_SIZE - PLAT_ARM_MAX_ROMLIB_RW_SIZE)) + +#define ROMLIB_RO_BASE BL1_RO_LIMIT +#define ROMLIB_RO_LIMIT ( \ + PLAT_ARM_TRUSTED_ROM_BASE + PLAT_ARM_TRUSTED_ROM_SIZE) + +#define ROMLIB_RW_BASE (BL1_RW_BASE + PLAT_ARM_MAX_BL1_RW_SIZE) +#define ROMLIB_RW_END ( \ + ROMLIB_RW_BASE + PLAT_ARM_MAX_ROMLIB_RW_SIZE) + +/****************************************************************************** + * BL2 specific defines. + *****************************************************************************/ +#if BL2_AT_EL3 +/* Put BL2 towards the middle of the Trusted SRAM */ +#define BL2_BASE (ARM_TRUSTED_SRAM_BASE + \ + PLAT_ARM_TRUSTED_SRAM_SIZE >> 1) + 0x2000) +#define BL2_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE) +#else +/* + * Put BL2 just below BL1. + */ +#define BL2_BASE (BL1_RW_BASE - PLAT_ARM_MAX_BL2_SIZE) +#define BL2_LIMIT BL1_RW_BASE +#endif /* BL2_AT_EL3 */ + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +#if ARM_BL31_IN_DRAM || SEPARATE_NOBITS_REGION +/* + * Put BL31 at the bottom of TZC secured DRAM + */ +#define BL31_BASE ARM_AP_TZC_DRAM1_BASE +#define BL31_LIMIT ( \ + ARM_AP_TZC_DRAM1_BASE + PLAT_ARM_MAX_BL31_SIZE) + +/* + * For SEPARATE_NOBITS_REGION, BL31 PROGBITS are loaded in TZC secured DRAM. + * And BL31 NOBITS are loaded in Trusted SRAM such that BL2 is overwritten. + */ +#if SEPARATE_NOBITS_REGION +#define BL31_NOBITS_BASE BL2_BASE +#define BL31_NOBITS_LIMIT BL2_LIMIT +#endif /* SEPARATE_NOBITS_REGION */ +#elif (RESET_TO_BL31) +/* Ensure Position Independent support (PIE) is enabled for this config.*/ +#if !ENABLE_PIE +#error "BL31 must be a PIE if RESET_TO_BL31=1." +#endif /* !ENABLE_PIE */ +/* + * Since this is PIE, we can define BL31_BASE to 0x0 since this macro is solely + * used for building BL31 and not used for loading BL31. + */ +#define NEW_SRAM_ALLOCATION + +#ifdef NEW_SRAM_ALLOCATION + #define BL31_BASE 0x20001000 +#else + #define BL31_BASE 0x20001000 +#endif /* NEW_SRAM_ALLOCATION */ + +#define BL31_LIMIT BL2_BASE /* PLAT_ARM_MAX_BL31_SIZE */ +#else +/* Put BL31 below BL2 in the Trusted SRAM.*/ +#define BL31_BASE ((ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE) - \ + PLAT_ARM_MAX_BL31_SIZE) +#define BL31_PROGBITS_LIMIT BL2_BASE + +/* + * For BL2_AT_EL3 make sure the BL31 can grow up until BL2_BASE. + * This is because in the BL2_AT_EL3 configuration, BL2 is always resident. + */ +#if BL2_AT_EL3 +#define BL31_LIMIT BL2_BASE +#else +#define BL31_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE) +#endif /* BL2_AT_EL3 */ +#endif /* ARM_BL31_IN_DRAM || SEPARATE_NOBITS_REGION */ + +/* + * BL32 is mandatory in AArch32. In AArch64, undefine BL32_BASE if there is + * no SPD and no SPM-MM, as they are the only ones that can be used as BL32. + */ +#if defined(SPD_none) && !SPM_MM +#undef BL32_BASE +#endif /* SPD_none && !SPM_MM */ + +/****************************************************************************** + * FWU Images: NS_BL1U, BL2U & NS_BL2U defines. + *****************************************************************************/ +#define BL2U_BASE BL2_BASE +#define BL2U_LIMIT BL2_LIMIT + +#define NS_BL2U_BASE ARM_NS_DRAM1_BASE +#define NS_BL1U_BASE (PLAT_ARM_NVM_BASE + UL(0x03EB8000)) + +/* + * ID of the secure physical generic timer interrupt used by the TSP. + */ +#define TSP_IRQ_SEC_PHY_TIMER ARM_IRQ_SEC_PHY_TIMER + +/* + * One cache line needed for bakery locks on ARM platforms + */ +#define PLAT_PERCPU_BAKERY_LOCK_SIZE (1 * CACHE_WRITEBACK_GRANULE) + +/* Priority levels for ARM platforms */ +#define PLAT_RAS_PRI 0x10 +#define PLAT_SDEI_CRITICAL_PRI 0x60 +#define PLAT_SDEI_NORMAL_PRI 0x70 + +/* ARM platforms use 3 upper bits of secure interrupt priority */ +#define ARM_PRI_BITS 3 + +/* SGI used for SDEI signalling */ +#define ARM_SDEI_SGI ARM_IRQ_SEC_SGI_0 + +#if SDEI_IN_FCONF +/* ARM SDEI dynamic private event max count */ +#define ARM_SDEI_DP_EVENT_MAX_CNT 3 + +/* ARM SDEI dynamic shared event max count */ +#define ARM_SDEI_DS_EVENT_MAX_CNT 3 +#else +/* ARM SDEI dynamic private event numbers */ +#define ARM_SDEI_DP_EVENT_0 1000 +#define ARM_SDEI_DP_EVENT_1 1001 +#define ARM_SDEI_DP_EVENT_2 1002 + +/* ARM SDEI dynamic shared event numbers */ +#define ARM_SDEI_DS_EVENT_0 2000 +#define ARM_SDEI_DS_EVENT_1 2001 +#define ARM_SDEI_DS_EVENT_2 2002 + +#define ARM_SDEI_PRIVATE_EVENTS \ + SDEI_DEFINE_EVENT_0(ARM_SDEI_SGI), \ + SDEI_PRIVATE_EVENT(ARM_SDEI_DP_EVENT_0, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), \ + SDEI_PRIVATE_EVENT(ARM_SDEI_DP_EVENT_1, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), \ + SDEI_PRIVATE_EVENT(ARM_SDEI_DP_EVENT_2, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC) + +#define ARM_SDEI_SHARED_EVENTS \ + SDEI_SHARED_EVENT(ARM_SDEI_DS_EVENT_0, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), \ + SDEI_SHARED_EVENT(ARM_SDEI_DS_EVENT_1, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), \ + SDEI_SHARED_EVENT(ARM_SDEI_DS_EVENT_2, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC) +#endif /* SDEI_IN_FCONF */ + +#endif /* ARM_DEF_H */ diff --git a/include/plat/nuvoton/common/plat_macros.S b/include/plat/nuvoton/common/plat_macros.S new file mode 100644 index 000000000..08f9feb71 --- /dev/null +++ b/include/plat/nuvoton/common/plat_macros.S @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2015-2023, ARM Limited and Contributors. All rights reserved. + * + * Copyright (c) 2017-2023 Nuvoton Technology Corp. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include +#include +#include + +/* + * The below macro prints out relevant GIC + * registers whenever an unhandled exception is + * taken in BL3-1. + * Clobbers: x0 - x10, x16, x17, sp + */ +.macro plat_print_gic_regs +mov_imm x17, BASE_GICC_BASE +mov_imm x16, BASE_GICD_BASE +arm_print_gic_regs +.endm + +/* + * the below macros print out relevant interconnect + * registers whenever an unhandled exception is + * taken in BL3-1 + */ +.macro plat_print_interconnect_regs + /* TODO */ +.endm + +/* + * The below required platform porting macro + * prints out relevant platform registers + * whenever an unhandled exception is taken in + * BL31. + */ +.macro plat_crash_print_regs + /* TODO */ +.endm + +#endif /* PLAT_MACROS_S */ diff --git a/include/plat/nuvoton/common/plat_npcm845x.h b/include/plat/nuvoton/common/plat_npcm845x.h new file mode 100644 index 000000000..d90952a83 --- /dev/null +++ b/include/plat/nuvoton/common/plat_npcm845x.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2015-2023, ARM Limited and Contributors. All rights reserved. + * + * Copyright (c) 2017-2023 Nuvoton Technology Corp. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_NPCM845X_H +#define PLAT_NPCM845X_H + +#include +#include + +unsigned int plat_calc_core_pos(uint64_t mpidr); +void npcm845x_mailbox_init(uintptr_t base_addr); +void plat_gic_driver_init(void); +void plat_gic_init(void); +void plat_gic_cpuif_enable(void); +void plat_gic_cpuif_disable(void); +void plat_gic_pcpu_init(void); + +void __dead2 npcm845x_system_off(void); +void __dead2 npcm845x_system_reset(void); +void npcm845x_pwr_domain_on_finish(const psci_power_state_t *target_state); +bool npcm845x_is_wakeup_src_irqsteer(void); +void __dead2 npcm845x_pwr_down_wfi(const psci_power_state_t *target_state); +void npcm845x_cpu_standby(plat_local_state_t cpu_state); +int npcm845x_validate_ns_entrypoint(uintptr_t entrypoint); +int npcm845x_pwr_domain_on(u_register_t mpidr); +int npcm845x_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state); + +#if !ARM_BL31_IN_DRAM +void npcm845x_get_sys_suspend_power_state(psci_power_state_t *req_state); +#endif + +void __dead2 npcm845x_pwr_domain_pwr_down_wfi( + const psci_power_state_t *target_state); +void npcm845x_pwr_domain_suspend_finish(const psci_power_state_t *target_state); +void npcm845x_pwr_domain_suspend(const psci_power_state_t *target_state); +void npcm845x_pwr_domain_off(const psci_power_state_t *target_state); +void __init npcm845x_bl31_plat_arch_setup(void); + +#endif /* PLAT_NPCM845X_H */ diff --git a/include/plat/nuvoton/npcm845x/platform_def.h b/include/plat/nuvoton/npcm845x/platform_def.h new file mode 100644 index 000000000..09da36ba1 --- /dev/null +++ b/include/plat/nuvoton/npcm845x/platform_def.h @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2015-2023, ARM Limited and Contributors. All rights reserved. + * + * Copyright (c) 2017-2023 Nuvoton Technology Corp. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define VALUE_TO_STRING(x) #x +#define VALUE(x) VALUE_TO_STRING(x) +#define VAR_NAME_VALUE(var) #var "=" VALUE(var) + +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +#define PLATFORM_STACK_SIZE 0x400 + +#define PLATFORM_CORE_COUNT NPCM845x_PLATFORM_CORE_COUNT +#define PLATFORM_CLUSTER_COUNT NPCM845x_CLUSTER_COUNT +#define PLATFORM_MAX_CPU_PER_CLUSTER NPCM845x_MAX_CPU_PER_CLUSTER +#define PLAT_PRIMARY_CPU NPCM845x_PLAT_PRIMARY_CPU +#define PLATFORM_SYSTEM_COUNT NPCM845x_SYSTEM_COUNT + +/* Local power state for power domains in Run state. */ +#define PLAT_LOCAL_STATE_RUN U(0) +/* Local power state for retention. Valid only for CPU power domains */ +#define PLAT_LOCAL_STATE_RET U(1) +/* + * Local power state for OFF/power-down. Valid for CPU and cluster power + * domains. + */ +#define PLAT_LOCAL_STATE_OFF U(2) + +/* + * This macro defines the deepest power down states possible. Any state ID + * higher than this is invalid. + */ +#define PLAT_MAX_OFF_STATE PLAT_LOCAL_STATE_OFF +#define PLAT_MAX_RET_STATE PLAT_LOCAL_STATE_RET + +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + PLATFORM_CORE_COUNT) +#define NPCM845x_MAX_PWR_LVL ARM_PWR_LVL1 + +/* + * Macros used to parse state information from State-ID if it is using the + * recommended encoding for State-ID. + */ +#define PLAT_LOCAL_PSTATE_WIDTH 4 +#define PLAT_LOCAL_PSTATE_MASK ((1 << PLAT_LOCAL_PSTATE_WIDTH) - 1) + +/* + * Required ARM standard platform porting definitions + */ +#define PLAT_ARM_CLUSTER_COUNT PLATFORM_CLUSTER_COUNT + +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + PLATFORM_CORE_COUNT) +#define PLAT_MAX_PWR_LVL NPCM845x_MAX_PWR_LVL + +#define PLAT_LOCAL_PSTATE_WIDTH 4 +#define PLAT_LOCAL_PSTATE_MASK ((1 << PLAT_LOCAL_PSTATE_WIDTH) - 1) + +#ifdef BL32_BASE + +#ifndef CONFIG_TARGET_ARBEL_PALLADIUM +#define PLAT_ARM_TRUSTED_DRAM_BASE BL32_BASE +#else +#define PLAT_ARM_TRUSTED_DRAM_BASE BL32_BASE +#endif /* CONFIG_TARGET_ARBEL_PALLADIUM */ + +#define PLAT_ARM_TRUSTED_DRAM_SIZE UL(0x02000000) /* 32 MB */ +#endif /* BL32_BASE */ + +#define PWR_DOMAIN_AT_MAX_LVL U(1) + +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 32) +#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32) +#define MAX_XLAT_TABLES 16 +#define PLAT_ARM_MMAP_ENTRIES 17 + +#ifdef NPCM845X_DEBUG +#define MAX_MMAP_REGIONS 8 +#define NPCM845X_TZ1_BASE 0xFFFB0000 +#endif /* NPCM845X_DEBUG */ + +#define FIQ_SMP_CALL_SGI 10 + +/* (0x00040000) 128 KB, the rest 128K if it is non secured */ +#define PLAT_ARM_TRUSTED_SRAM_SIZE UL(0x00020000) + +#define ARM_SHARED_RAM_SIZE UL(0x00001000) /* 4 KB */ + +/* UL(0xfffCE000) add calc ARM_TRUSTED_SRAM_BASE */ +#define ARM_SHARED_RAM_BASE (BL31_BASE + 0x00020000 - ARM_SHARED_RAM_SIZE) + +/* The remaining Trusted SRAM is used to load the BL images */ +#define ARM_BL_RAM_BASE (ARM_SHARED_RAM_BASE + ARM_SHARED_RAM_SIZE) + +/* + * PLAT_ARM_TRUSTED_SRAM_SIZE is taken from platform_def.h 0x20000 + * because only half is secured in this specific implementation + */ +#define ARM_BL_RAM_SIZE (PLAT_ARM_TRUSTED_SRAM_SIZE - ARM_SHARED_RAM_SIZE) + +#if RESET_TO_BL31 +/* Size of Trusted SRAM - the first 4KB of shared memory */ +#define PLAT_ARM_MAX_BL31_SIZE \ + (PLAT_ARM_TRUSTED_SRAM_SIZE - ARM_SHARED_RAM_SIZE) +#else +/* + * Since BL31 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL31_SIZE + * is calculated using the current BL31 PROGBITS debug size plus the sizes + * of BL2 and BL1-RW + */ +#define PLAT_ARM_MAX_BL31_SIZE \ + (PLAT_ARM_TRUSTED_SRAM_SIZE - ARM_SHARED_RAM_SIZE) +#endif /* RESET_TO_BL31 */ +/* + * Load address of BL33 for this platform port + */ +#define PLAT_ARM_NS_IMAGE_BASE (ARM_DRAM1_BASE + UL(0x6208000)) + +#ifdef NPCM845X_DEBUG +#define COUNTER_FREQUENCY 0x07735940 /* f/4 = 125MHz */ +#endif /* NPCM845X_DEBUG */ + +#define COUNTER_FREQUENCY 0x0EE6B280 /* f/2 = 250MHz */ +#define PLAT_ARM_NSTIMER_FRAME_ID U(1) + +/* GIC parameters */ + +/* Base compatible GIC memory map */ +#define NT_GIC_BASE (0xDFFF8000) +#define BASE_GICD_BASE (NT_GIC_BASE + 0x1000) +#define BASE_GICC_BASE (NT_GIC_BASE + 0x2000) +#define BASE_GICR_BASE (NT_GIC_BASE + 0x200000) +#define BASE_GICH_BASE (NT_GIC_BASE + 0x4000) +#define BASE_GICV_BASE (NT_GIC_BASE + 0x6000) + +#define DEVICE1_BASE BASE_GICD_BASE +#define DEVICE1_SIZE 0x7000 + +#ifdef NPCM845X_DEBUG +/* ((BASE_GICR_BASE - BASE_GICD_BASE) + (PLATFORM_CORE_COUNT * 0x20000)) */ +#define ARM_CPU_START_ADDRESS(m) UL(0xf0800e00 + 0x10 + m * 4) +#endif /* NPCM845X_DEBUG */ + +#define PLAT_REG_BASE NPCM845x_REG_BASE +#define PLAT_REG_SIZE NPCM845x_REG_SIZE + +/* MMU entry for internal (register) space access */ +#define MAP_DEVICE0 \ + MAP_REGION_FLAT(PLAT_REG_BASE, PLAT_REG_SIZE, MT_DEVICE | MT_RW | MT_NS) + +#define MAP_DEVICE1 \ + MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/* + * Define a list of Group 1 Secure and Group 0 interrupt properties + * as per GICv3 terminology. On a GICv2 system or mode, + * the lists will be merged and treated as Group 0 interrupts. + */ +#define PLAT_ARM_GICD_BASE BASE_GICD_BASE +#define PLAT_ARM_GICC_BASE BASE_GICC_BASE + +#define PLAT_ARM_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_EDGE) + +#define PLAT_ARM_G0_IRQ_PROPS(grp) + +/* Required for compilation: */ + +/* + * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size + * plus a little space for growth. + */ +#define PLAT_ARM_MAX_BL1_RW_SIZE 0 /* UL(0xB000) */ +#if USE_ROMLIB +#define PLAT_ARM_MAX_ROMLIB_RW_SIZE UL(0x1000) +#define PLAT_ARM_MAX_ROMLIB_RO_SIZE UL(0xe000) +#define FVP_BL2_ROMLIB_OPTIMIZATION UL(0x6000) +#else +#define PLAT_ARM_MAX_ROMLIB_RW_SIZE UL(0) +#define PLAT_ARM_MAX_ROMLIB_RO_SIZE UL(0) +#define FVP_BL2_ROMLIB_OPTIMIZATION UL(0) +#endif /* USE_ROMLIB */ + +/* + * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size + * plus a little space for growth. + */ +#if TRUSTED_BOARD_BOOT +#define PLAT_ARM_MAX_BL2_SIZE (UL(0x1D000) * FVP_BL2_ROMLIB_OPTIMIZATION) +#else +/* (UL(0x13000) - FVP_BL2_ROMLIB_OPTIMIZATION) */ +#define PLAT_ARM_MAX_BL2_SIZE 0 +#endif /* TRUSTED_BOARD_BOOT */ + +#undef NPCM_PRINT_ONCE +#ifdef NPCM_PRINT_ONCE +#define PRINT_ONLY_ONCE +#pragma message(VAR_NAME_VALUE(ARM_AP_TZC_DRAM1_BASE)) +#pragma message(VAR_NAME_VALUE(BL31_BASE)) +#pragma message(VAR_NAME_VALUE(BL31_LIMIT)) +#pragma message(VAR_NAME_VALUE(PLAT_ARM_MAX_BL31_SIZE)) +#pragma message(VAR_NAME_VALUE(BL32_BASE)) +#pragma message(VAR_NAME_VALUE(BL32_LIMIT)) +#pragma message(VAR_NAME_VALUE(PLAT_ARM_MAX_BL32_SIZE) +#pragma message(VAR_NAME_VALUE(SPMD_SPM_AT_SEL2_KKO)) +#endif /* NPCM_PRINT_ONCE */ + +#define MAX_IO_DEVICES 4 +#define MAX_IO_HANDLES 4 + +#define PLAT_ARM_FIP_BASE 0x0 +#define PLAT_ARM_FIP_MAX_SIZE PLAT_ARM_MAX_BL31_SIZE + +#define PLAT_ARM_BOOT_UART_BASE 0xF0000000 +#define PLAT_ARM_BOOT_UART_CLK_IN_HZ 115200 +#define PLAT_ARM_RUN_UART_BASE 0xF0000000 +#define PLAT_ARM_RUN_UART_CLK_IN_HZ 115200 +#define PLAT_ARM_CRASH_UART_BASE 0xF0000000 +#define PLAT_ARM_CRASH_UART_CLK_IN_HZ 115200 + +/* + * Mailbox to control the secondary cores.All secondary cores are held in a wait + * loop in cold boot. To release them perform the following steps (plus any + * additional barriers that may be needed): + * + * uint64_t *entrypoint = (uint64_t *)PLAT_NPCM_TM_ENTRYPOINT; + * *entrypoint = ADDRESS_TO_JUMP_TO; + * + * uint64_t *mbox_entry = (uint64_t *)PLAT_NPCM_TM_HOLD_BASE; + * mbox_entry[cpu_id] = PLAT_NPCM_TM_HOLD_BASE; + * + * sev(); + */ +#define PLAT_NPCM_TRUSTED_MAILBOX_BASE ARM_SHARED_RAM_BASE + +/* The secure entry point to be used on warm reset by all CPUs. */ +#define PLAT_NPCM_TM_ENTRYPOINT PLAT_NPCM_TRUSTED_MAILBOX_BASE +#define PLAT_NPCM_TM_ENTRYPOINT_SIZE ULL(8) + +/* Hold entries for each CPU. */ +#define PLAT_NPCM_TM_HOLD_BASE \ + (PLAT_NPCM_TM_ENTRYPOINT + PLAT_NPCM_TM_ENTRYPOINT_SIZE) +#define PLAT_NPCM_TM_HOLD_ENTRY_SIZE ULL(8) +#define PLAT_NPCM_TM_HOLD_SIZE \ + (PLAT_NPCM_TM_HOLD_ENTRY_SIZE * PLATFORM_CORE_COUNT) +#define PLAT_NPCM_TRUSTED_NOTIFICATION_BASE \ + (PLAT_NPCM_TM_ENTRYPOINT_SIZE + PLAT_NPCM_TM_HOLD_SIZE) + +#define PLAT_NPCM_TRUSTED_NOTIFICATION_ENTRY_SIZE ULL(8) + +#define PLAT_NPCM_TRUSTED_NOTIFICATION_SIZE \ + (PLAT_NPCM_TRUSTED_NOTIFICATION_ENTRY_SIZE * PLATFORM_CORE_COUNT) + +#define PLAT_NPCM_TRUSTED_MAILBOX_SIZE \ + (PLAT_NPCM_TM_ENTRYPOINT_SIZE + PLAT_NPCM_TM_HOLD_SIZE + \ + PLAT_NPCM_TRUSTED_NOTIFICATION_ENTRY_SIZE) + +#define PLAT_NPCM_TM_HOLD_STATE_WAIT ULL(0) +#define PLAT_NPCM_TM_HOLD_STATE_GO ULL(1) +#define PLAT_NPCM_TM_HOLD_STATE_BSP_OFF ULL(2) + +#define PLAT_NPCM_TM_NOTIFICATION_START ULL(0xAA) +#define PLAT_NPCM_TM_NOTIFICATION_BR ULL(0xCC) + +#ifdef NPCM845X_DEBUG +#define PLAT_ARM_TRUSTED_MAILBOX_BASE 0xfffB0000 +#endif /* NPCM845X_DEBUG */ + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/nuvoton/common/nuvoton_helpers.S b/plat/nuvoton/common/nuvoton_helpers.S new file mode 100644 index 000000000..09035a19b --- /dev/null +++ b/plat/nuvoton/common/nuvoton_helpers.S @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2015-2023, ARM Limited and Contributors. All rights reserved. + * + * Copyright (C) 2022-2023 Nuvoton Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef NUVOTON_HELPERS_S +#define NUVOTON_HELPERS_S + +#include +#include +#include + + .globl plat_is_my_cpu_primary + .globl plat_my_core_pos + .globl plat_calc_core_pos + .globl plat_reset_handler + .globl plat_get_my_entrypoint + .globl plat_secondary_cold_boot_setup + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl platform_mem_init + .globl npcm845x_mailbox_init + + /* -------------------------------------------------------------------- + * Helper macro that reads the part number of the current CPU and jumps + * to the given label if it matches the CPU MIDR provided. + * + * Clobbers x0. + * -------------------------------------------------------------------- + */ + .macro jump_if_cpu_midr _cpu_midr, _label + + mrs x0, midr_el1 + ubfx x0, x0, MIDR_PN_SHIFT, #12 + cmp w0, #((\_cpu_midr >> MIDR_PN_SHIFT) & MIDR_PN_MASK) + b.eq \_label + + .endm + + /* ---------------------------------------------- + * The mailbox_base is used to distinguish warm/cold + * reset. The mailbox_base is in the data section, not + * in .bss, this allows function to start using this + * variable before the runtime memory is initialized. + * ---------------------------------------------- + */ + .section .data.mailbox_base + .align 3 + mailbox_base: .quad 0x0 + + /* --------------------------------------------- + * void plat_reset_handler(void); + * + * To add: Determine the SoC type and call the appropriate + * reset handler. + *----------------------------------------------- */ + +func plat_reset_handler + ret +endfunc plat_reset_handler + + /* ---------------------------------------------- + * unsigned int plat_is_my_cpu_primary(void); + * This function checks if this is the primary CPU + * ---------------------------------------------- + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + and x0, x0, #(MPIDR_CPU_MASK) + cmp x0, #PLAT_PRIMARY_CPU + cset x0, eq + ret +endfunc plat_is_my_cpu_primary + + /* ---------------------------------------------- + * unsigned int plat_my_core_pos(void) + * This Function uses the plat_calc_core_pos() + * to get the index of the calling CPU. + * ---------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret +endfunc plat_my_core_pos + + /* + * unsigned int plat_calc_core_pos(uint64_t mpidr) + * helper function to calculate the core position. + * With this function. + */ +func plat_calc_core_pos + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret +endfunc plat_calc_core_pos + + /* --------------------------------------------- + * function to get the entrypoint. + * --------------------------------------------- + */ + /* --------------------------------------------------------------------- + * uintptr_t plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish between a cold and a warm + * boot. + * + * This functions returns: + * - 0 for a cold boot. + * - Any other value for a warm boot. + * --------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + mov x1, x30 + bl plat_is_my_cpu_primary + /* + * Secondaries always cold boot. + */ + cbz w0, 1f + /* + * Primaries warm boot if they are requested + * to power off. + */ + mov_imm x0, PLAT_NPCM_TM_HOLD_BASE + ldr x0, [x0] + cmp x0, PLAT_NPCM_TM_HOLD_STATE_BSP_OFF + adr x0, plat_wait_for_warm_boot + csel x0, x0, xzr, eq + ret x1 +1: mov x0, #0 + ret x1 +endfunc plat_get_my_entrypoint + +func npcm845x_mailbox_init + adrp x1, mailbox_base + str x0, [x1, :lo12:mailbox_base] + ret +endfunc npcm845x_mailbox_init + +func plat_wait_for_warm_boot + /* + * Calculate address of our hold entry. + * As the function will never return, there is no need to save LR. + */ + bl plat_my_core_pos + lsl x0, x0, #3 + mov x8, x0 + mov_imm x2, PLAT_NPCM_TM_HOLD_BASE + add x0, x0, x2 + mov_imm x2, PLAT_NPCM_TRUSTED_NOTIFICATION_BASE + add x8, x8, x2 + /* + * This code runs way before requesting the warmboot of this core, + * so it is possible to clear the mailbox before getting a request + * to boot. + */ + mov x1, PLAT_NPCM_TM_HOLD_STATE_WAIT + str x1,[x0] + + /* Notify that core is in pending state - do not use x0!, uses x7 and x8! */ + mov x7, PLAT_NPCM_TM_NOTIFICATION_START + str x7,[x8] + /* + * This code runs way before requesting the warmboot of this core, + * so it is possible to clear the mailbox before getting a request + * to boot. + */ + mov x1, PLAT_NPCM_TM_HOLD_STATE_WAIT + str x1,[x0] + /* Wait until we have a go */ +poll_mailbox: + wfe + ldr x1, [x0] + cmp x1, PLAT_NPCM_TM_HOLD_STATE_GO + bne poll_mailbox + + mov x7, PLAT_NPCM_TM_NOTIFICATION_BR + str x7,[x8] + /* Jump to the provided entrypoint */ + mov_imm x0, PLAT_NPCM_TM_ENTRYPOINT + ldr x1, [x0] + br x1 +endfunc plat_wait_for_warm_boot + +func plat_secondary_cold_boot_setup + b plat_wait_for_warm_boot +endfunc plat_secondary_cold_boot_setup + +func plat_crash_console_init + mov x0, #1 + ret +endfunc plat_crash_console_init + +func plat_crash_console_putc + ret +endfunc plat_crash_console_putc + +func plat_crash_console_flush + mov x0, #0 + ret +endfunc plat_crash_console_flush + +func platform_mem_init + ret +endfunc platform_mem_init + +#endif /* NUVOTON_HELPERS_S */ diff --git a/plat/nuvoton/common/nuvoton_pm.c b/plat/nuvoton/common/nuvoton_pm.c new file mode 100644 index 000000000..833ebfb6f --- /dev/null +++ b/plat/nuvoton/common/nuvoton_pm.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2015-2023, ARM Limited and Contributors. All rights reserved. + * + * Copyright (C) 2023 Nuvoton Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + + +/* Allow npcm845x to override these functions */ +#pragma weak plat_arm_program_trusted_mailbox +#pragma weak plat_setup_psci_ops /* changed to weak */ + + +/******************************************************************************* + * ARM standard platform handler called to check the validity of the non secure + * entrypoint. Returns 0 if the entrypoint is valid, or -1 otherwise. + ******************************************************************************/ +int arm_validate_ns_entrypoint(uintptr_t entrypoint) +{ + /* + * Check if the non secure entrypoint lies within the non + * secure DRAM. + */ + if ((entrypoint >= ARM_NS_DRAM1_BASE) && + (entrypoint < (ARM_NS_DRAM1_BASE + ARM_NS_DRAM1_SIZE))) { + return 0; + } +#ifdef __aarch64__ + if ((entrypoint >= ARM_DRAM2_BASE) && + (entrypoint < (ARM_DRAM2_BASE + ARM_DRAM2_SIZE))) { + return 0; + } +#endif + + return -1; +} + +int arm_validate_psci_entrypoint(uintptr_t entrypoint) +{ + return (arm_validate_ns_entrypoint(entrypoint) == 0) ? PSCI_E_SUCCESS : + PSCI_E_INVALID_ADDRESS; +} + +/****************************************************************************** + * Helper function to save the platform state before a system suspend. Save the + * state of the system components which are not in the Always ON power domain. + *****************************************************************************/ +void arm_system_pwr_domain_save(void) +{ + /* Assert system power domain is available on the platform */ + assert(PLAT_MAX_PWR_LVL > ARM_PWR_LVL1); + + plat_arm_gic_save(); + + /* + * Unregister console now so that it is not registered for a second + * time during resume. + */ + arm_console_runtime_end(); + + /* + * All the other peripheral which are configured by TF-A are + * re-initialized on resume from system suspend. Hence we + * don't save their state here. + */ +} diff --git a/plat/nuvoton/common/nuvoton_topology.c b/plat/nuvoton/common/nuvoton_topology.c new file mode 100644 index 000000000..892d9e218 --- /dev/null +++ b/plat/nuvoton/common/nuvoton_topology.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015-2023, ARM Limited and Contributors. All rights reserved. + * + * Copyright (C) 2022-2023 Nuvoton Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +/* + * Since NPCM845 have only powered/non-powered state, + * the tree is structure of level 0 + * (Single cluster == 0) and 4 representing a "leaf" for every CPU + */ +const unsigned char npcm845x_power_domain_tree_desc[] = { + PLATFORM_CLUSTER_COUNT, + PLATFORM_MAX_CPU_PER_CLUSTER +}; + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + /* A single cluster with 4 CPUs */ + return npcm845x_power_domain_tree_desc; +} + +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + mpidr &= MPIDR_AFFINITY_MASK; + + if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) { + return -1; + } + + cluster_id = (unsigned int)MPIDR_AFFLVL1_VAL(mpidr); + cpu_id = (unsigned int)MPIDR_AFFLVL0_VAL(mpidr); + + if (cluster_id > PLATFORM_CLUSTER_COUNT || + cpu_id > PLATFORM_MAX_CPU_PER_CLUSTER) { + return -1; + } + + return (int)(cpu_id + (cluster_id * 4)); +} diff --git a/plat/nuvoton/common/plat_nuvoton_gic.c b/plat/nuvoton/common/plat_nuvoton_gic.c new file mode 100644 index 000000000..300670dec --- /dev/null +++ b/plat/nuvoton/common/plat_nuvoton_gic.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016-2023, ARM Limited and Contributors. All rights reserved. + * + * Copyright (C) 2022-2023 Nuvoton Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +static const interrupt_prop_t g0_interrupt_props[] = { + INTR_PROP_DESC(FIQ_SMP_CALL_SGI, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), +}; + +gicv2_driver_data_t arm_gic_data = { + .gicd_base = BASE_GICD_BASE, + .gicc_base = BASE_GICC_BASE, + .interrupt_props = g0_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(g0_interrupt_props), +}; + +void plat_gic_driver_init(void) +{ + gicv2_driver_init(&arm_gic_data); +} + +void plat_gic_init(void) +{ + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} + +void plat_gic_cpuif_enable(void) +{ + gicv2_cpuif_enable(); +} + +void plat_gic_cpuif_disable(void) +{ + gicv2_cpuif_disable(); +} + +void plat_gic_pcpu_init(void) +{ + gicv2_pcpu_distif_init(); +} diff --git a/plat/nuvoton/npcm845x/npcm845x_bl31_setup.c b/plat/nuvoton/npcm845x/npcm845x_bl31_setup.c new file mode 100644 index 000000000..26ddb4b53 --- /dev/null +++ b/plat/nuvoton/npcm845x/npcm845x_bl31_setup.c @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2015-2023, ARM Limited and Contributors. All rights reserved. + * + * Copyright (C) 2017-2023 Nuvoton Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Placeholder variables for copying the arguments that have been passed to + * BL31 from BL2. + */ +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +#if !RESET_TO_BL31 +/* + * Check that BL31_BASE is above ARM_FW_CONFIG_LIMIT. The reserved page + * is required for SOC_FW_CONFIG/TOS_FW_CONFIG passed from BL2. + */ +/* CASSERT(BL31_BASE >= ARM_FW_CONFIG_LIMIT, assert_bl31_base_overflows); */ +#endif /* !RESET_TO_BL31 */ + +#define MAP_BL31_TOTAL MAP_REGION_FLAT( \ + BL31_START, \ + BL31_END - BL31_START, \ + MT_MEMORY | MT_RW | EL3_PAS) + +#if RECLAIM_INIT_CODE +IMPORT_SYM(unsigned long, __INIT_CODE_START__, BL_INIT_CODE_BASE); +IMPORT_SYM(unsigned long, __INIT_CODE_END__, BL_CODE_END_UNALIGNED); + +#define BL_INIT_CODE_END ((BL_CODE_END_UNALIGNED + PAGE_SIZE - 1) & \ + ~(PAGE_SIZE - 1)) + +#define MAP_BL_INIT_CODE MAP_REGION_FLAT( \ + BL_INIT_CODE_BASE, \ + BL_INIT_CODE_END - \ + BL_INIT_CODE_BASE, \ + MT_CODE | MT_SECURE) +#endif /* RECLAIM_INIT_CODE */ + +#if SEPARATE_NOBITS_REGION +#define MAP_BL31_NOBITS MAP_REGION_FLAT( \ + BL31_NOBITS_BASE, \ + BL31_NOBITS_LIMIT - \ + BL31_NOBITS_BASE, \ + MT_MEMORY | MT_RW | EL3_PAS) + +#endif /* SEPARATE_NOBITS_REGION */ + +/****************************************************************************** + * Return a pointer to the 'entry_point_info' structure of the next image + * for the security state specified. BL33 corresponds to the non-secure + * image type while BL32 corresponds to the secure image type. + * A NULL pointer is returned if the image does not exist. + *****************************************************************************/ +struct entry_point_info *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + assert(sec_state_is_valid(type)); + next_image_info = (type == NON_SECURE) + ? &bl33_image_ep_info : &bl32_image_ep_info; +/* + * None of the images on the ARM development platforms can have 0x0 + * as the entrypoint + */ + if (next_image_info->pc) { + return next_image_info; + } else { + return NULL; + } +} + +int board_uart_init(void) +{ + unsigned long UART_BASE_ADDR; + static console_t console; + +#ifdef CONFIG_TARGET_ARBEL_PALLADIUM + UART_Init(UART0_DEV, UART_MUX_MODE1, + UART_BAUDRATE_115200); + UART_BASE_ADDR = npcm845x_get_base_uart(UART0_DEV); +#else + UART_BASE_ADDR = npcm845x_get_base_uart(UART0_DEV); +#endif /* CONFIG_TARGET_ARBEL_PALLADIUM */ + +/* + * Register UART w/o initialization - + * A clock rate of zero means to skip the initialisation. + */ + console_16550_register((uintptr_t)UART_BASE_ADDR, 0, 0, &console); + + return 0; +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return (unsigned int)COUNTER_FREQUENCY; +} + +/****************************************************************************** + * Perform any BL31 early platform setup common to ARM standard platforms. + * Here is an opportunity to copy parameters passed by the calling EL (S-EL1 + * in BL2 & EL3 in BL1) before they are lost (potentially). This needs to be + * done before the MMU is initialized so that the memory layout can be used + * while creating page tables. BL2 has flushed this information to memory, + * so we are guaranteed to pick up good data. + *****************************************************************************/ +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ +#if RESET_TO_BL31 + void *from_bl2 = (void *)arg0; + void *plat_params_from_bl2 = (void *)arg3; + + if (from_bl2 != NULL) { + assert(from_bl2 == NULL); + } + + if (plat_params_from_bl2 != NULL) { + assert(plat_params_from_bl2 == NULL); + } +#endif /* RESET_TO_BL31 */ + +/* Initialize Delay timer */ + generic_delay_timer_init(); + +/* Do Specific Board/Chip initializations */ + board_uart_init(); + +#if RESET_TO_BL31 + /* There are no parameters from BL2 if BL31 is a reset vector */ + assert(from_bl2 == NULL); + assert(plat_params_from_bl2 == NULL); + +#ifdef BL32_BASE + /* Populate entry point information for BL32 */ + SET_PARAM_HEAD(&bl32_image_ep_info, + PARAM_EP, + VERSION_1, + 0); + SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE); + bl32_image_ep_info.pc = BL32_BASE; + bl32_image_ep_info.spsr = arm_get_spsr_for_bl32_entry(); + +#if defined(SPD_spmd) +/* + * SPM (hafnium in secure world) expects SPM Core manifest base address + * in x0, which in !RESET_TO_BL31 case loaded after base of non shared + * SRAM(after 4KB offset of SRAM). But in RESET_TO_BL31 case all non + * shared SRAM is allocated to BL31, so to avoid overwriting of manifest + * keep it in the last page. + */ + bl32_image_ep_info.args.arg0 = ARM_TRUSTED_SRAM_BASE + + PLAT_ARM_TRUSTED_SRAM_SIZE - PAGE_SIZE; +#endif /* SPD_spmd */ +#endif /* BL32_BASE */ + +/* Populate entry point information for BL33 */ + SET_PARAM_HEAD(&bl33_image_ep_info, + PARAM_EP, + VERSION_1, + 0); + +/* + * Tell BL31 where the non-trusted software image + * is located and the entry state information + */ + bl33_image_ep_info.pc = plat_get_ns_image_entrypoint(); + /* Generic ARM code will switch to EL2, revert to EL1 */ + bl33_image_ep_info.spsr = arm_get_spsr_for_bl33_entry(); + bl33_image_ep_info.spsr &= ~0x8; + bl33_image_ep_info.spsr |= 0x4; + + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, (uint32_t)NON_SECURE); + +#if defined(SPD_spmd) && !(ARM_LINUX_KERNEL_AS_BL33) +/* + * Hafnium in normal world expects its manifest address in x0, + * which is loaded at base of DRAM. + */ + bl33_image_ep_info.args.arg0 = (u_register_t)ARM_DRAM1_BASE; +#endif /* SPD_spmd && !ARM_LINUX_KERNEL_AS_BL33 */ + +#if ARM_LINUX_KERNEL_AS_BL33 +/* + * According to the file ``Documentation/arm64/booting.txt`` of the + * Linux kernel tree, Linux expects the physical address of the device + * tree blob (DTB) in x0, while x1-x3 are reserved for future use and + * must be 0. + */ + bl33_image_ep_info.args.arg0 = (u_register_t)ARM_PRELOADED_DTB_BASE; + bl33_image_ep_info.args.arg1 = 0U; + bl33_image_ep_info.args.arg2 = 0U; + bl33_image_ep_info.args.arg3 = 0U; +#endif /* ARM_LINUX_KERNEL_AS_BL33 */ + +#else /* RESET_TO_BL31 */ +/* + * In debug builds, we pass a special value in 'plat_params_from_bl2' + * to verify platform parameters from BL2 to BL31. + * In release builds, it's not used. + */ + assert(((unsigned long long)plat_params_from_bl2) == + ARM_BL31_PLAT_PARAM_VAL); + +/* + * Check params passed from BL2 should not be NULL, + */ + bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2; + + assert(params_from_bl2 != NULL); + assert(params_from_bl2->h.type == PARAM_BL_PARAMS); + assert(params_from_bl2->h.version >= VERSION_2); + + bl_params_node_t *bl_params = params_from_bl2->head; + +/* + * Copy BL33 and BL32 (if present), entry point information. + * They are stored in Secure RAM, in BL2's address space. + */ + while (bl_params != NULL) { + if (bl_params->image_id == BL32_IMAGE_ID) { + bl32_image_ep_info = *bl_params->ep_info; + } + + if (bl_params->image_id == BL33_IMAGE_ID) { + bl33_image_ep_info = *bl_params->ep_info; + } + + bl_params = bl_params->next_params_info; + } + + if (bl33_image_ep_info.pc == 0U) { + panic(); + } +#endif /* RESET_TO_BL31 */ +} + +/******************************************************************************* + * Perform any BL31 platform setup common to ARM standard platforms + ******************************************************************************/ +void bl31_platform_setup(void) +{ +/* Initialize the GIC driver, cpu and distributor interfaces */ + plat_gic_driver_init(); + plat_gic_init(); + +#if RESET_TO_BL31 +#if defined(PLAT_ARM_MEM_PROT_ADDR) + arm_nor_psci_do_dyn_mem_protect(); +#endif /* PLAT_ARM_MEM_PROT_ADDR */ +#else +/* + * In this soluction, we also do the security initialzation + * even when BL31 is not in the reset vector + */ + npcm845x_security_setup(); +#endif /* RESET_TO_BL31 */ + +/* Enable and initialize the System level generic timer */ + mmio_write_32(ARM_SYS_CNTCTL_BASE + CNTCR_OFF, + CNTCR_FCREQ(0U) | CNTCR_EN); + +/* Initialize power controller before setting up topology */ + plat_arm_pwrc_setup(); + +#if RAS_EXTENSION + ras_init(); +#endif + +#if USE_DEBUGFS + debugfs_init(); +#endif /* USE_DEBUGFS */ +} + +void arm_console_runtime_init(void) +{ +/* Added in order to ignore the original weak function */ +} + +void plat_arm_program_trusted_mailbox(uintptr_t address) +{ +/* + * now we don't use ARM mailbox, + * so that function added to ignore the weak one + */ +} + +void __init bl31_plat_arch_setup(void) +{ + npcm845x_bl31_plat_arch_setup(); +} + +void __init plat_arm_pwrc_setup(void) +{ +/* NPCM850 is always powered so no need for power control */ +} + +void __init npcm845x_bl31_plat_arch_setup(void) +{ + const mmap_region_t bl_regions[] = { + MAP_BL31_TOTAL, +#if RECLAIM_INIT_CODE + MAP_BL_INIT_CODE, +#endif /* RECLAIM_INIT_CODE */ +#if SEPARATE_NOBITS_REGION + MAP_BL31_NOBITS, +#endif /* SEPARATE_NOBITS_REGION */ + ARM_MAP_BL_RO, +#if USE_ROMLIB + ARM_MAP_ROMLIB_CODE, + ARM_MAP_ROMLIB_DATA, +#endif /* USE_ROMLIB */ +#if USE_COHERENT_MEM + ARM_MAP_BL_COHERENT_RAM, +#endif /* USE_COHERENT_MEM */ + ARM_MAP_SHARED_RAM, +#ifdef SECONDARY_BRINGUP + ARM_MAP_NS_DRAM1, + #ifdef BL32_BASE + ARM_MAP_BL32_CORE_MEM + #endif /* BL32_BASE */ +#endif /* SECONDARY_BRINGUP */ + {0} + }; + setup_page_tables(bl_regions, plat_arm_get_mmap()); + enable_mmu_el3(0U); +} diff --git a/plat/nuvoton/npcm845x/npcm845x_common.c b/plat/nuvoton/npcm845x/npcm845x_common.c new file mode 100644 index 000000000..fc393fdfb --- /dev/null +++ b/plat/nuvoton/npcm845x/npcm845x_common.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2015-2023, ARM Limited and Contributors. All rights reserved. + * + * Copyright (C) 2022-2023 Nuvoton Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +const mmap_region_t plat_arm_mmap[] = { + MAP_DEVICE0, + MAP_DEVICE1, + {0} +}; diff --git a/plat/nuvoton/npcm845x/npcm845x_psci.c b/plat/nuvoton/npcm845x/npcm845x_psci.c new file mode 100644 index 000000000..a954265dd --- /dev/null +++ b/plat/nuvoton/npcm845x/npcm845x_psci.c @@ -0,0 +1,436 @@ +/* + * Copyright (c) 2015-2023, ARM Limited and Contributors. All rights reserved. + * + * Copyright (C) 2017-2023 Nuvoton Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ADP_STOPPED_APPLICATION_EXIT 0x20026 + +/* Make composite power state parameter till power level 0 */ +#if PSCI_EXTENDED_STATE_ID +/* Not Extended */ +#define npcm845x_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \ + (((lvl0_state) << PSTATE_ID_SHIFT) | \ + ((type) << PSTATE_TYPE_SHIFT)) +#else +#define npcm845x_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \ + (((lvl0_state) << PSTATE_ID_SHIFT) | \ + ((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \ + ((type) << PSTATE_TYPE_SHIFT)) +#endif /* PSCI_EXTENDED_STATE_ID */ + +#define npcm845x_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \ + (((lvl1_state) << PLAT_LOCAL_PSTATE_WIDTH) | \ + npcm845x_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type)) + +/* + * The table storing the valid idle power states. Ensure that the + * array entries are populated in ascending order of state-id to + * enable us to use binary search during power state validation. + * The table must be terminated by a NULL entry. + */ +static const unsigned int npcm845x_pm_idle_states[] = { +/* + * Cluster = 0 (RUN) CPU=1 (RET, higest in idle) - + * Retention. The Power state is Stand-by + */ + +/* State-id - 0x01 */ + npcm845x_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_RET, + MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY), + +/* + * For testing purposes. + * Only CPU suspend to standby is supported by NPCM845x + */ + /* State-id - 0x02 */ + npcm845x_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_OFF, + MPIDR_AFFLVL0, PSTATE_TYPE_POWERDOWN), + 0, +}; + +/******************************************************************************* + * Platform handler called to check the validity of the non secure + * entrypoint. + ******************************************************************************/ +int npcm845x_validate_ns_entrypoint(uintptr_t entrypoint) +{ + /* + * Check if the non secure entrypoint lies within the non + * secure DRAM. + */ + NOTICE("%s() nuvoton_psci\n", __func__); +#ifdef PLAT_ARM_TRUSTED_DRAM_BASE + if ((entrypoint >= PLAT_ARM_TRUSTED_DRAM_BASE) && + (entrypoint < (PLAT_ARM_TRUSTED_DRAM_BASE + + PLAT_ARM_TRUSTED_DRAM_SIZE))) { + return PSCI_E_INVALID_ADDRESS; + } +#endif /* PLAT_ARM_TRUSTED_DRAM_BASE */ + /* For TFTS purposes, '0' is also illegal */ + #ifdef SPD_tspd + if (entrypoint == 0) { + return PSCI_E_INVALID_ADDRESS; + } + #endif /* SPD_tspd */ + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Platform handler called when a CPU is about to enter standby. + ******************************************************************************/ +void npcm845x_cpu_standby(plat_local_state_t cpu_state) +{ + NOTICE("%s() nuvoton_psci\n", __func__); + + uint64_t scr; + + scr = read_scr_el3(); + write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT); + + /* + * Enter standby state + * dsb is good practice before using wfi to enter low power states + */ + isb(); + dsb(); + wfi(); + + /* Once awake */ + write_scr_el3(scr); +} + +/******************************************************************************* + * Platform handler called when a power domain is about to be turned on. The + * mpidr determines the CPU to be turned on. + ******************************************************************************/ +int npcm845x_pwr_domain_on(u_register_t mpidr) +{ + int rc = PSCI_E_SUCCESS; + int cpu_id = plat_core_pos_by_mpidr(mpidr); + + if ((unsigned int)cpu_id >= PLATFORM_CORE_COUNT) { + ERROR("%s() CPU 0x%X\n", __func__, cpu_id); + return PSCI_E_INVALID_PARAMS; + } + + if (cpu_id == -1) { + /* domain on was not called by a CPU */ + ERROR("%s() was not per CPU 0x%X\n", __func__, cpu_id); + return PSCI_E_INVALID_PARAMS; + } + + unsigned int pos = (unsigned int)plat_core_pos_by_mpidr(mpidr); + uintptr_t hold_base = PLAT_NPCM_TM_HOLD_BASE; + + assert(pos < PLATFORM_CORE_COUNT); + + hold_base += pos * PLAT_NPCM_TM_HOLD_ENTRY_SIZE; + + mmio_write_64(hold_base, PLAT_NPCM_TM_HOLD_STATE_GO); + /* No cache maintenance here, hold_base is mapped as device memory. */ + + /* Make sure that the write has completed */ + dsb(); + isb(); + + sev(); + + return rc; +} + + +/******************************************************************************* + * Platform handler called when a power domain is about to be suspended. The + * target_state encodes the power state that each level should transition to. + ******************************************************************************/ +void npcm845x_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + NOTICE("%s() nuvoton_psci\n", __func__); + + for (size_t i = 0; (uint64_t)i <= PLAT_MAX_PWR_LVL; i++) { + INFO("%s: target_state->pwr_domain_state[%lu]=%x\n", + __func__, i, target_state->pwr_domain_state[i]); + } + + gicv2_cpuif_disable(); + + NOTICE("%s() Out of suspend\n", __func__); +} + + +/******************************************************************************* + * Platform handler called when a power domain has just been powered on after + * being turned off earlier. The target_state encodes the low power state that + * each level has woken up from. + ******************************************************************************/ +void npcm845x_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + NOTICE("%s() nuvoton_psci\n", __func__); + + for (size_t i = 0; (uint64_t)i <= PLAT_MAX_PWR_LVL; i++) { + INFO("%s: target_state->pwr_domain_state[%lu]=%x\n", + __func__, i, target_state->pwr_domain_state[i]); + } + + assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] == + PLAT_LOCAL_STATE_OFF); + + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} + + +/******************************************************************************* + * Platform handler called when a power domain has just been powered on after + * having been suspended earlier. The target_state encodes the low power state + * that each level has woken up from. + ******************************************************************************/ +void npcm845x_pwr_domain_suspend_finish(const psci_power_state_t *target_state) +{ + NOTICE("%s() nuvoton_psci\n", __func__); + + for (size_t i = 0; (uint64_t)i <= PLAT_MAX_PWR_LVL; i++) { + INFO("%s: target_state->pwr_domain_state[%lu]=%x\n", + __func__, i, target_state->pwr_domain_state[i]); + } + + assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] == + PLAT_LOCAL_STATE_OFF); + + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} + + +void __dead2 npcm845x_system_reset(void) +{ + uintptr_t RESET_BASE_ADDR; + uint32_t val; + + NOTICE("%s() nuvoton_psci\n", __func__); + console_flush(); + + dsbsy(); + isb(); + + /* + * In future - support all reset types. For now, SW1 reset + * Enable software reset 1 to reboot the BMC + */ + RESET_BASE_ADDR = (uintptr_t)0xF0801000; + + /* Read SW1 control register */ + val = mmio_read_32(RESET_BASE_ADDR + 0x44); + /* Keep SPI BMC & MC persist*/ + val &= 0xFBFFFFDF; + /* Setting SW1 control register */ + mmio_write_32(RESET_BASE_ADDR + 0x44, val); + /* Set SW1 reset */ + mmio_write_32(RESET_BASE_ADDR + 0x14, 0x8); + dsb(); + + while (1) { + ; + } +} + +int npcm845x_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + unsigned int state_id; + int i; + + NOTICE("%s() nuvoton_psci\n", __func__); + assert(req_state); + + /* + * Currently we are using a linear search for finding the matching + * entry in the idle power state array. This can be made a binary + * search if the number of entries justify the additional complexity. + */ + for (i = 0; !!npcm845x_pm_idle_states[i]; i++) { + if (power_state == npcm845x_pm_idle_states[i]) { + break; + } + } + + /* Return error if entry not found in the idle state array */ + if (!npcm845x_pm_idle_states[i]) { + return PSCI_E_INVALID_PARAMS; + } + + i = 0; + state_id = psci_get_pstate_id(power_state); + + /* Parse the State ID and populate the state info parameter */ + while (state_id) { + req_state->pwr_domain_state[i++] = (uint8_t)state_id & + PLAT_LOCAL_PSTATE_MASK; + state_id >>= PLAT_LOCAL_PSTATE_WIDTH; + } + + return PSCI_E_SUCCESS; +} + +/* + * The NPCM845 doesn't truly support power management at SYSTEM power domain. + * The SYSTEM_SUSPEND will be down-graded to the cluster level within + * the platform layer. The `fake` SYSTEM_SUSPEND allows us to validate + * some of the driver save and restore sequences on FVP. + */ +#if !ARM_BL31_IN_DRAM +void npcm845x_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + unsigned int i; + + NOTICE("%s() nuvoton_psci\n", __func__); + + for (i = ARM_PWR_LVL0; (uint64_t)i <= PLAT_MAX_PWR_LVL; i++) { + req_state->pwr_domain_state[i] = (uint8_t)PLAT_LOCAL_STATE_OFF; + } +} +#endif /* !ARM_BL31_IN_DRAM */ + +/* + * The rest of the PSCI implementation are for testing purposes only. + * Not supported in Arbel + */ +void __dead2 npcm845x_system_off(void) +{ + console_flush(); + + dsbsy(); + isb(); + + /* NPCM845 doesn't allow real system off, Do reaset instead */ + /* Do reset here TBD which, in the meanwhile SW1 reset */ + for (;;) { + wfi(); + } +} + +void __dead2 plat_secondary_cold_boot_setup(void); + +void __dead2 npcm845x_pwr_down_wfi( + const psci_power_state_t *target_state) +{ + uintptr_t hold_base = PLAT_NPCM_TM_HOLD_BASE; + unsigned int pos = plat_my_core_pos(); + + if (pos == 0) { + /* + * The secondaries will always be in a wait + * for warm boot on reset, but the BSP needs + * to be able to distinguish between waiting + * for warm boot (e.g. after psci_off, waiting + * for psci_on) and a cold boot. + */ + mmio_write_64(hold_base, PLAT_NPCM_TM_HOLD_STATE_BSP_OFF); + /* No cache maintenance here, we run with caches off already. */ + dsb(); + isb(); + } + + wfe(); + + while (1) { + ; + } +} + +/******************************************************************************* + * Platform handler called when a power domain is about to be turned off. The + * target_state encodes the power state that each level should transition to. + ******************************************************************************/ +void npcm845x_pwr_domain_off(const psci_power_state_t *target_state) +{ + NOTICE("%s() nuvoton_psci\n", __func__); + + for (size_t i = 0; (uint64_t)i <= PLAT_MAX_PWR_LVL; i++) { + INFO("%s: target_state->pwr_domain_state[%lu]=%x\n", + __func__, i, target_state->pwr_domain_state[i]); + } + + plat_secondary_cold_boot_setup(); +} + +static const plat_psci_ops_t npcm845x_plat_psci_ops = { + .cpu_standby = npcm845x_cpu_standby, + .pwr_domain_on = npcm845x_pwr_domain_on, + .pwr_domain_suspend = npcm845x_pwr_domain_suspend, + .pwr_domain_on_finish = npcm845x_pwr_domain_on_finish, + .pwr_domain_suspend_finish = npcm845x_pwr_domain_suspend_finish, + .system_reset = npcm845x_system_reset, + .validate_power_state = npcm845x_validate_power_state, + .validate_ns_entrypoint = npcm845x_validate_ns_entrypoint, + + /* For testing purposes only This PSCI states are not supported */ + .pwr_domain_off = npcm845x_pwr_domain_off, + .pwr_domain_pwr_down_wfi = npcm845x_pwr_down_wfi, +}; + +/* For reference only + * typedef struct plat_psci_ops { + * void (*cpu_standby)(plat_local_state_t cpu_state); + * int (*pwr_domain_on)(u_register_t mpidr); + * void (*pwr_domain_off)(const psci_power_state_t *target_state); + * void (*pwr_domain_suspend_pwrdown_early)( + * const psci_power_state_t *target_state); + * void (*pwr_domain_suspend)(const psci_power_state_t *target_state); + * void (*pwr_domain_on_finish)(const psci_power_state_t *target_state); + * void (*pwr_domain_on_finish_late)( + * const psci_power_state_t *target_state); + * void (*pwr_domain_suspend_finish)( + * const psci_power_state_t *target_state); + * void __dead2 (*pwr_domain_pwr_down_wfi)( + * const psci_power_state_t *target_state); + * void __dead2 (*system_off)(void); + * void __dead2 (*system_reset)(void); + * int (*validate_power_state)(unsigned int power_state, + * psci_power_state_t *req_state); + * int (*validate_ns_entrypoint)(uintptr_t ns_entrypoint); + * void (*get_sys_suspend_power_state)( + * psci_power_state_t *req_state); + * int (*get_pwr_lvl_state_idx)(plat_local_state_t pwr_domain_state, + * int pwrlvl); + * int (*translate_power_state_by_mpidr)(u_register_t mpidr, + * unsigned int power_state, + * psci_power_state_t *output_state); + * int (*get_node_hw_state)(u_register_t mpidr, unsigned int power_level); + * int (*mem_protect_chk)(uintptr_t base, u_register_t length); + * int (*read_mem_protect)(int *val); + * int (*write_mem_protect)(int val); + * int (*system_reset2)(int is_vendor, + * int reset_type, u_register_t cookie); + * } plat_psci_ops_t; + */ + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + uintptr_t *entrypoint = (void *)PLAT_NPCM_TM_ENTRYPOINT; + + *entrypoint = sec_entrypoint; + + *psci_ops = &npcm845x_plat_psci_ops; + + return 0; +} diff --git a/plat/nuvoton/npcm845x/npcm845x_serial_port.c b/plat/nuvoton/npcm845x/npcm845x_serial_port.c new file mode 100644 index 000000000..946e9d076 --- /dev/null +++ b/plat/nuvoton/npcm845x/npcm845x_serial_port.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2015-2023, ARM Limited and Contributors. All rights reserved. + * + * Copyright (C) 2017-2023 Nuvoton Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +uintptr_t npcm845x_get_base_uart(UART_DEV_T devNum) +{ + return 0xF0000000 + devNum * 0x1000; +} + +uintptr_t npcm845x_get_base_clk(void) +{ + return 0xF0801000; +} + +uintptr_t npcm845x_get_base_gcr(void) +{ + return 0xF0800000; +} + +void npcm845x_wait_for_empty(int uart_n) +{ + volatile struct npcmX50_uart *uart = (struct npcmX50_uart *)npcm845x_get_base_uart(uart_n); + + while ((*(uint8_t *)(uintptr_t)(&uart->lsr) & 0x40) == 0x00) { +/* + * wait for THRE (Transmitter Holding Register Empty) + * and TSR (Transmitter Shift Register) to be empty. + * Some delay. notice needed some delay so UartUpdateTool + * will pass w/o error log + */ + } + + volatile int delay; + + for (delay = 0; delay < 10000; delay++) { + ; + } +} + +int UART_Init(UART_DEV_T devNum, UART_BAUDRATE_T baudRate) +{ + uint32_t val = 0; + uintptr_t clk_base = npcm845x_get_base_clk(); + uintptr_t gcr_base = npcm845x_get_base_gcr(); + uintptr_t uart_base = npcm845x_get_base_uart(devNum); + volatile struct npcmX50_uart *uart = (struct npcmX50_uart *)uart_base; + +/* Use CLKREF to be independent of CPU frequency */ + volatile struct clk_ctl *clk_ctl_obj = (struct clk_ctl *)clk_base; + volatile struct npcm845x_gcr *gcr_ctl_obj = + (struct npcm845x_gcr *)gcr_base; + + clk_ctl_obj->clksel = clk_ctl_obj->clksel & ~(0x3 << 8); + clk_ctl_obj->clksel = clk_ctl_obj->clksel | (0x2 << 8); + + /* Set devider according to baudrate */ + clk_ctl_obj->clkdiv1 = + (unsigned int)(clk_ctl_obj->clkdiv1 & ~(0x1F << 16)); + + /* clear bits 11-15 - set value 0 */ + if (devNum == UART3_DEV) { + clk_ctl_obj->clkdiv2 = + (unsigned int)(clk_ctl_obj->clkdiv2 & ~(0x1F << 11)); + } + + npcm845x_wait_for_empty(devNum); + + val = (uint32_t)LCR_WLS_8bit; + mmio_write_8((uintptr_t)&uart->lcr, (uint8_t)val); + + /* disable all interrupts */ + mmio_write_8((uintptr_t)&uart->ier, 0); + + /* + * Set the RX FIFO trigger level, reset RX, TX FIFO + */ + val = (uint32_t)(FCR_FME | FCR_RFR | FCR_TFR | FCR_RFITL_4B); + + /* reset TX and RX FIFO */ + mmio_write_8((uintptr_t)(&uart->fcr), (uint8_t)val); + + /* Set port for 8 bit, 1 stop, no parity */ + val = (uint32_t)LCR_WLS_8bit; + + /* Set DLAB bit; Accesses the Divisor Latch Registers (DLL, DLM). */ + val |= 0x80; + mmio_write_8((uintptr_t)(&uart->lcr), (uint8_t)val); + + /* Baud Rate = UART Clock 24MHz / (16 * (11+2)) = 115384 */ + mmio_write_8((uintptr_t)(&uart->dll), 11); + mmio_write_8((uintptr_t)(&uart->dlm), 0x00); + + val = mmio_read_8((uintptr_t)&uart->lcr); + + /* Clear DLAB bit; Accesses RBR, THR or IER registers. */ + val &= 0x7F; + mmio_write_8((uintptr_t)(&uart->lcr), (uint8_t)val); + + if (devNum == UART0_DEV) { + gcr_ctl_obj->mfsel4 &= ~(1 << 1); + gcr_ctl_obj->mfsel1 |= 1 << 9; + } else if (devNum == UART3_DEV) { + /* Pin Mux */ + gcr_ctl_obj->mfsel4 &= ~(1 << 1); + gcr_ctl_obj->mfsel1 |= 1 << 11; + gcr_ctl_obj->spswc &= (7 << 0); + gcr_ctl_obj->spswc |= (2 << 0); + } else { + /* halt */ + while (1) { + ; + } + } + + return 0; +} diff --git a/plat/nuvoton/npcm845x/platform.mk b/plat/nuvoton/npcm845x/platform.mk new file mode 100644 index 000000000..f38ae2907 --- /dev/null +++ b/plat/nuvoton/npcm845x/platform.mk @@ -0,0 +1,397 @@ +# +# Copyright (c) 2015-2023, ARM Limited and Contributors. All rights reserved. +# +# Copyright (c) 2017-2023 Nuvoton Ltd. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# This is a debug flag for bring-up. It allows reducing CPU numbers +# SECONDARY_BRINGUP := 1 +RESET_TO_BL31 := 1 +PMD_SPM_AT_SEL2 := 0 +#temporary until the RAM size is reduced +USE_COHERENT_MEM := 1 + + +$(eval $(call add_define,RESET_TO_BL31)) + +ifeq (${ARCH}, aarch64) +# On ARM standard platorms, the TSP can execute from Trusted SRAM, +# Trusted DRAM (if available) or the TZC secured area of DRAM. +# TZC secured DRAM is the default. + +ARM_TSP_RAM_LOCATION ?= dram + +ifeq (${ARM_TSP_RAM_LOCATION}, tsram) +ARM_TSP_RAM_LOCATION_ID = ARM_TRUSTED_SRAM_ID +else ifeq (${ARM_TSP_RAM_LOCATION}, tdram) +ARM_TSP_RAM_LOCATION_ID = ARM_TRUSTED_DRAM_ID +else ifeq (${ARM_TSP_RAM_LOCATION}, dram) +ARM_TSP_RAM_LOCATION_ID = ARM_DRAM_ID +else +$(error "Unsupported ARM_TSP_RAM_LOCATION value") +endif + +# Process flags +# Process ARM_BL31_IN_DRAM flag +ARM_BL31_IN_DRAM := 0 +$(eval $(call assert_boolean,ARM_BL31_IN_DRAM)) +$(eval $(call add_define,ARM_BL31_IN_DRAM)) +else +ARM_TSP_RAM_LOCATION_ID = ARM_TRUSTED_SRAM_ID +endif + +$(eval $(call add_define,ARM_TSP_RAM_LOCATION_ID)) + +# For the original power-state parameter format, the State-ID can be encoded +# according to the recommended encoding or zero. This flag determines which +# State-ID encoding to be parsed. +ARM_RECOM_STATE_ID_ENC := 0 + +# If the PSCI_EXTENDED_STATE_ID is set, then ARM_RECOM_STATE_ID_ENC +# need to be set. Else throw a build error. +ifeq (${PSCI_EXTENDED_STATE_ID}, 1) +ifeq (${ARM_RECOM_STATE_ID_ENC}, 0) +$(error Build option ARM_RECOM_STATE_ID_ENC needs to be set if \ + PSCI_EXTENDED_STATE_ID is set for ARM platforms) +endif +endif + +# Process ARM_RECOM_STATE_ID_ENC flag +$(eval $(call assert_boolean,ARM_RECOM_STATE_ID_ENC)) +$(eval $(call add_define,ARM_RECOM_STATE_ID_ENC)) + +# Process ARM_DISABLE_TRUSTED_WDOG flag +# By default, Trusted Watchdog is always enabled unless SPIN_ON_BL1_EXIT is set +ARM_DISABLE_TRUSTED_WDOG := 0 +ifeq (${SPIN_ON_BL1_EXIT}, 1) +ARM_DISABLE_TRUSTED_WDOG := 1 +endif +$(eval $(call assert_boolean,ARM_DISABLE_TRUSTED_WDOG)) +$(eval $(call add_define,ARM_DISABLE_TRUSTED_WDOG)) + +# Process ARM_CONFIG_CNTACR +ARM_CONFIG_CNTACR := 1 +$(eval $(call assert_boolean,ARM_CONFIG_CNTACR)) +$(eval $(call add_define,ARM_CONFIG_CNTACR)) + +# Process ARM_BL31_IN_DRAM flag +ARM_BL31_IN_DRAM := 0 +$(eval $(call assert_boolean,ARM_BL31_IN_DRAM)) +$(eval $(call add_define,ARM_BL31_IN_DRAM)) + +# Process ARM_PLAT_MT flag +ARM_PLAT_MT := 0 +$(eval $(call assert_boolean,ARM_PLAT_MT)) +$(eval $(call add_define,ARM_PLAT_MT)) + +# Use translation tables library v2 by default +ARM_XLAT_TABLES_LIB_V1 := 0 +$(eval $(call assert_boolean,ARM_XLAT_TABLES_LIB_V1)) +$(eval $(call add_define,ARM_XLAT_TABLES_LIB_V1)) + +# Don't have the Linux kernel as a BL33 image by default +ARM_LINUX_KERNEL_AS_BL33 := 0 +$(eval $(call assert_boolean,ARM_LINUX_KERNEL_AS_BL33)) +$(eval $(call add_define,ARM_LINUX_KERNEL_AS_BL33)) + +ifeq (${ARM_LINUX_KERNEL_AS_BL33},1) +ifeq (${ARCH},aarch64) +ifneq (${RESET_TO_BL31},1) +$(error "ARM_LINUX_KERNEL_AS_BL33 is only available if RESET_TO_BL31=1.") +endif +else +ifneq (${RESET_TO_SP_MIN},1) +$(error "ARM_LINUX_KERNEL_AS_BL33 is only available if RESET_TO_SP_MIN=1.") +endif +endif + +ifndef PRELOADED_BL33_BASE +$(error "PRELOADED_BL33_BASE must be set if ARM_LINUX_KERNEL_AS_BL33 is used.") +endif + +ifndef ARM_PRELOADED_DTB_BASE +$(error "ARM_PRELOADED_DTB_BASE must be set if ARM_LINUX_KERNEL_AS_BL33 is used.") +endif + +$(eval $(call add_define,ARM_PRELOADED_DTB_BASE)) +endif + +# Use an implementation of SHA-256 with a smaller memory footprint +# but reduced speed. +$(eval $(call add_define,MBEDTLS_SHA256_SMALLER)) + +# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images +# in the FIP if the platform requires. +ifneq ($(BL32_EXTRA1),) +$(eval $(call TOOL_ADD_IMG,bl32_extra1,--tos-fw-extra1)) +endif +ifneq ($(BL32_EXTRA2),) +$(eval $(call TOOL_ADD_IMG,bl32_extra2,--tos-fw-extra2)) +endif + +# Enable PSCI_STAT_COUNT/RESIDENCY APIs on ARM platforms +ENABLE_PSCI_STAT := 1 +ENABLE_PMF := 1 + +# On ARM platforms, separate the code and read-only data sections to allow +# mapping the former as executable and the latter as execute-never. +SEPARATE_CODE_AND_RODATA := 1 + +# On ARM platforms, disable SEPARATE_NOBITS_REGION by default. Both PROGBITS +# and NOBITS sections of BL31 image are adjacent to each other and loaded +# into Trusted SRAM. +SEPARATE_NOBITS_REGION := 0 + +# In order to support SEPARATE_NOBITS_REGION for Arm platforms, we need to load +# BL31 PROGBITS into secure DRAM space and BL31 NOBITS into SRAM. Hence mandate +# the build to require that ARM_BL31_IN_DRAM is enabled as well. +ifeq ($(SEPARATE_NOBITS_REGION),1) +ifneq ($(ARM_BL31_IN_DRAM),1) +$(error For SEPARATE_NOBITS_REGION, ARM_BL31_IN_DRAM must be enabled) +endif + +ifneq ($(RECLAIM_INIT_CODE),0) +$(error For SEPARATE_NOBITS_REGION, RECLAIM_INIT_CODE cannot be supported) +endif +endif + +# Disable ARM Cryptocell by default +ARM_CRYPTOCELL_INTEG := 0 +$(eval $(call assert_boolean,ARM_CRYPTOCELL_INTEG)) +$(eval $(call add_define,ARM_CRYPTOCELL_INTEG)) + +# Enable PIE support for RESET_TO_BL31 case +ifeq (${RESET_TO_BL31},1) +ENABLE_PIE := 1 +endif + +# CryptoCell integration relies on coherent buffers for passing data from +# the AP CPU to the CryptoCell + +ifeq (${ARM_CRYPTOCELL_INTEG},1) +ifeq (${USE_COHERENT_MEM},0) +$(error "ARM_CRYPTOCELL_INTEG needs USE_COHERENT_MEM to be set.") +endif +endif + +PLAT_INCLUDES := -Iinclude/plat/nuvoton/npcm845x \ + -Iinclude/plat/nuvoton/common \ + -Iinclude/drivers/nuvoton/npcm845x \ + +ifeq (${ARCH}, aarch64) +PLAT_INCLUDES += -Iinclude/plat/arm/common/aarch64 +endif + +# Include GICv3 driver files +include drivers/arm/gic/v2/gicv2.mk + +NPCM850_GIC_SOURCES := ${GICV2_SOURCES} + +BL31_SOURCES +=lib/cpus/aarch64/cortex_a35.S \ + plat/common/plat_psci_common.c \ + drivers/ti/uart/aarch64/16550_console.S \ + plat/nuvoton/npcm845x/npcm845x_psci.c \ + plat/nuvoton/npcm845x/npcm845x_serial_port.c \ + plat/nuvoton/common/nuvoton_topology.c \ + plat/nuvoton/npcm845x/npcm845x_bl31_setup.c + +PLAT_BL_COMMON_SOURCES := drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + plat/common/plat_gicv2.c \ + plat/arm/common/arm_gicv2.c \ + plat/nuvoton/common/plat_nuvoton_gic.c \ + ${NPCM850_GIC_SOURCES} \ + plat/nuvoton/npcm845x/npcm845x_common.c \ + plat/nuvoton/common/nuvoton_helpers.S \ + lib/semihosting/semihosting.c \ + lib/semihosting/${ARCH}/semihosting_call.S \ + plat/arm/common/arm_common.c \ + plat/arm/common/arm_console.c + +ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1) +PLAT_BL_COMMON_SOURCES += lib/xlat_tables/xlat_tables_common.c \ + lib/xlat_tables/${ARCH}/xlat_tables.c +else +include lib/xlat_tables_v2/xlat_tables.mk + +PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} +endif + +ARM_IO_SOURCES += plat/arm/common/arm_io_storage.c \ + plat/arm/common/fconf/arm_fconf_io.c + +ifeq (${SPD},spmd) +ifeq (${SPMD_SPM_AT_SEL2},1) +ARM_IO_SOURCES += plat/arm/common/fconf/arm_fconf_sp.c +endif +endif + +BL1_SOURCES += drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + plat/arm/common/arm_bl1_setup.c \ + plat/arm/common/arm_err.c \ + ${ARM_IO_SOURCES} + +ifdef EL3_PAYLOAD_BASE +# Need the plat_arm_program_trusted_mailbox() function to release secondary CPUs +# from their holding pen +BL1_SOURCES += plat/arm/common/arm_pm.c +endif + +BL2_SOURCES += drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + plat/arm/common/arm_bl2_setup.c \ + plat/arm/common/arm_err.c \ + ${ARM_IO_SOURCES} + +# Firmware Configuration Framework sources +include lib/fconf/fconf.mk + +# Add `libfdt` and Arm common helpers required for Dynamic Config +include lib/libfdt/libfdt.mk + +DYN_CFG_SOURCES += plat/arm/common/arm_dyn_cfg.c \ + plat/arm/common/arm_dyn_cfg_helpers.c \ + common/fdt_wrappers.c + +BL1_SOURCES += ${DYN_CFG_SOURCES} +BL2_SOURCES += ${DYN_CFG_SOURCES} + +ifeq (${BL2_AT_EL3},1) +BL2_SOURCES += plat/arm/common/arm_bl2_el3_setup.c +endif + +# Because BL1/BL2 execute in AArch64 mode but BL32 in AArch32 we need to use +# the AArch32 descriptors. +BL2_SOURCES += plat/arm/common/${ARCH}/arm_bl2_mem_params_desc.c +BL2_SOURCES += plat/arm/common/arm_image_load.c \ + common/desc_image_load.c + +ifeq (${SPD},opteed) +BL2_SOURCES += lib/optee/optee_utils.c +endif + +BL2U_SOURCES += drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + plat/arm/common/arm_bl2u_setup.c + +BL31_SOURCES += plat/arm/common/arm_bl31_setup.c \ + plat/nuvoton/common/nuvoton_pm.c \ + plat/nuvoton/common/nuvoton_topology.c \ + plat/common/plat_psci_common.c + +ifeq (${ENABLE_PMF}, 1) +ifeq (${ARCH}, aarch64) +BL31_SOURCES += plat/arm/common/aarch64/execution_state_switch.c \ + plat/arm/common/arm_sip_svc.c \ + lib/pmf/pmf_smc.c +else +BL32_SOURCES += plat/arm/common/arm_sip_svc.c \ + lib/pmf/pmf_smc.c +endif +endif + +ifeq (${EL3_EXCEPTION_HANDLING},1) +BL31_SOURCES += plat/arm/common/aarch64/arm_ehf.c +endif + +ifeq (${SDEI_SUPPORT},1) +BL31_SOURCES += plat/arm/common/aarch64/arm_sdei.c +ifeq (${SDEI_IN_FCONF},1) +BL31_SOURCES += plat/arm/common/fconf/fconf_sdei_getter.c +endif +endif + +# RAS sources +ifeq (${RAS_EXTENSION},1) +BL31_SOURCES += lib/extensions/ras/std_err_record.c \ + lib/extensions/ras/ras_common.c +endif + +# Pointer Authentication sources +ifeq (${ENABLE_PAUTH}, 1) +PLAT_BL_COMMON_SOURCES += plat/arm/common/aarch64/arm_pauth.c \ + lib/extensions/pauth/pauth_helpers.S +endif + +ifeq (${SPD},spmd) +BL31_SOURCES += plat/common/plat_spmd_manifest.c \ + common/fdt_wrappers.c \ + ${LIBFDT_SRCS} +endif + +ifneq (${TRUSTED_BOARD_BOOT},0) +# Include common TBB sources +AUTH_SOURCES := drivers/auth/auth_mod.c \ + drivers/auth/crypto_mod.c \ + drivers/auth/img_parser_mod.c \ + lib/fconf/fconf_tbbr_getter.c + +# Include the selected chain of trust sources. +ifeq (${COT},tbbr) +AUTH_SOURCES += drivers/auth/tbbr/tbbr_cot_common.c +BL1_SOURCES += drivers/auth/tbbr/tbbr_cot_bl1.c +BL2_SOURCES += drivers/auth/tbbr/tbbr_cot_bl2.c +else ifeq (${COT},dualroot) +AUTH_SOURCES += drivers/auth/dualroot/cot.c +else +$(error Unknown chain of trust ${COT}) +endif + +BL1_SOURCES += ${AUTH_SOURCES} \ + bl1/tbbr/tbbr_img_desc.c \ + plat/arm/common/arm_bl1_fwu.c \ + plat/common/tbbr/plat_tbbr.c + +BL2_SOURCES += ${AUTH_SOURCES} \ + plat/common/tbbr/plat_tbbr.c + +$(eval $(call TOOL_ADD_IMG,ns_bl2u,--fwu,FWU_)) + +# We expect to locate the *.mk files under the directories specified below +ifeq (${ARM_CRYPTOCELL_INTEG},0) +CRYPTO_LIB_MK := drivers/auth/mbedtls/mbedtls_crypto.mk +else +CRYPTO_LIB_MK := drivers/auth/cryptocell/cryptocell_crypto.mk +endif + +IMG_PARSER_LIB_MK := drivers/auth/mbedtls/mbedtls_x509.mk + +$(info Including ${CRYPTO_LIB_MK}) +include ${CRYPTO_LIB_MK} + +$(info Including ${IMG_PARSER_LIB_MK}) +include ${IMG_PARSER_LIB_MK} +endif + +ifeq (${RECLAIM_INIT_CODE}, 1) +ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1) +$(error "To reclaim init code xlat tables v2 must be used") +endif +endif + +ifeq (${MEASURED_BOOT},1) +MEASURED_BOOT_MK := drivers/measured_boot/measured_boot.mk +$(info Including ${MEASURED_BOOT_MK}) +include ${MEASURED_BOOT_MK} +endif + +ifeq (${EL3_EXCEPTION_HANDLING},1) +BL31_SOURCES += plat/arm/common/aarch64/arm_ehf.c +endif + +BL1_SOURCES := +BL2_SOURCES := +BL2U_SOURCES := + +DEBUG_CONSOLE ?= 0 +$(eval $(call add_define,DEBUG_CONSOLE)) + +$(eval $(call add_define,ARM_TSP_RAM_LOCATION_ID)) +