diff options
142 files changed, 3916 insertions, 521 deletions
@@ -205,11 +205,6 @@ TF_CFLAGS += $(CPPFLAGS) $(TF_CFLAGS_$(ARCH)) \ -Os -ffunction-sections -fdata-sections GCC_V_OUTPUT := $(shell $(CC) -v 2>&1) -PIE_FOUND := $(findstring --enable-default-pie,${GCC_V_OUTPUT}) - -ifneq ($(PIE_FOUND),) -TF_CFLAGS += -fno-PIE -endif # Force the compiler to include the frame pointer ifeq (${ENABLE_BACKTRACE},1) @@ -335,6 +330,16 @@ ifeq (${ARM_ARCH_MAJOR},7) include make_helpers/armv7-a-cpus.mk endif +ifeq ($(ENABLE_PIE),1) + TF_CFLAGS += -fpie + TF_LDFLAGS += -pie +else + PIE_FOUND := $(findstring --enable-default-pie,${GCC_V_OUTPUT}) + ifneq ($(PIE_FOUND),) + TF_CFLAGS += -fno-PIE + endif +endif + # Include the CPU specific operations makefile, which provides default # values for all CPU errata workarounds and CPU specific optimisations. # This can be overridden by the platform. @@ -565,6 +570,7 @@ $(eval $(call assert_boolean,ENABLE_AMU)) $(eval $(call assert_boolean,ENABLE_ASSERTIONS)) $(eval $(call assert_boolean,ENABLE_BACKTRACE)) $(eval $(call assert_boolean,ENABLE_MPAM_FOR_LOWER_ELS)) +$(eval $(call assert_boolean,ENABLE_PIE)) $(eval $(call assert_boolean,ENABLE_PMF)) $(eval $(call assert_boolean,ENABLE_PSCI_STAT)) $(eval $(call assert_boolean,ENABLE_RUNTIME_INSTRUMENTATION)) @@ -615,6 +621,7 @@ $(eval $(call add_define,ENABLE_AMU)) $(eval $(call add_define,ENABLE_ASSERTIONS)) $(eval $(call add_define,ENABLE_BACKTRACE)) $(eval $(call add_define,ENABLE_MPAM_FOR_LOWER_ELS)) +$(eval $(call add_define,ENABLE_PIE)) $(eval $(call add_define,ENABLE_PMF)) $(eval $(call add_define,ENABLE_PSCI_STAT)) $(eval $(call add_define,ENABLE_RUNTIME_INSTRUMENTATION)) diff --git a/bl2/aarch64/bl2_entrypoint.S b/bl2/aarch64/bl2_entrypoint.S index bc8cbfd65..30a5c599a 100644 --- a/bl2/aarch64/bl2_entrypoint.S +++ b/bl2/aarch64/bl2_entrypoint.S @@ -70,13 +70,19 @@ func bl2_entrypoint * - the coherent memory section. * --------------------------------------------- */ - ldr x0, =__BSS_START__ - ldr x1, =__BSS_SIZE__ + adrp x0, __BSS_START__ + add x0, x0, :lo12:__BSS_START__ + adrp x1, __BSS_END__ + add x1, x1, :lo12:__BSS_END__ + sub x1, x1, x0 bl zeromem #if USE_COHERENT_MEM - ldr x0, =__COHERENT_RAM_START__ - ldr x1, =__COHERENT_RAM_UNALIGNED_SIZE__ + adrp x0, __COHERENT_RAM_START__ + add x0, x0, :lo12:__COHERENT_RAM_START__ + adrp x1, __COHERENT_RAM_END_UNALIGNED__ + add x1, x1, :lo12:__COHERENT_RAM_END_UNALIGNED__ + sub x1, x1, x0 bl zeromem #endif diff --git a/bl31/aarch64/bl31_entrypoint.S b/bl31/aarch64/bl31_entrypoint.S index 3a45e53f4..7c116a2e0 100644 --- a/bl31/aarch64/bl31_entrypoint.S +++ b/bl31/aarch64/bl31_entrypoint.S @@ -7,6 +7,7 @@ #include <arch.h> #include <bl_common.h> #include <el3_common_macros.S> +#include <platform_def.h> #include <pmf_asm_macros.S> #include <runtime_instr.h> #include <xlat_mmu_helpers.h> @@ -73,6 +74,18 @@ func bl31_entrypoint mov x22, 0 mov x23, 0 #endif /* RESET_TO_BL31 */ + + /* -------------------------------------------------------------------- + * If PIE is enabled, fixup the Global descriptor Table and dynamic + * relocations + * -------------------------------------------------------------------- + */ +#if ENABLE_PIE + mov_imm x0, BL31_BASE + mov_imm x1, BL31_LIMIT + bl fixup_gdt_reloc +#endif /* ENABLE_PIE */ + /* --------------------------------------------- * Perform platform specific early arch. setup * --------------------------------------------- diff --git a/bl31/bl31.ld.S b/bl31/bl31.ld.S index 81e7ba3a3..43d0ed440 100644 --- a/bl31/bl31.ld.S +++ b/bl31/bl31.ld.S @@ -26,6 +26,8 @@ SECTIONS ASSERT(. == ALIGN(PAGE_SIZE), "BL31_BASE address is not aligned on a page boundary.") + __BL31_START__ = .; + #if SEPARATE_CODE_AND_RODATA .text . : { __TEXT_START__ = .; @@ -63,6 +65,16 @@ SECTIONS KEEP(*(cpu_ops)) __CPU_OPS_END__ = .; + /* + * Keep the .got section in the RO section as the it is patched + * prior to enabling the MMU and having the .got in RO is better for + * security. + */ + . = ALIGN(16); + __GOT_START__ = .; + *(.got) + __GOT_END__ = .; + /* Place pubsub sections for events */ . = ALIGN(8); #include <pubsub_events.h> @@ -153,6 +165,16 @@ SECTIONS __DATA_END__ = .; } >RAM + . = ALIGN(16); + /* + * .rela.dyn needs to come after .data for the read-elf utility to parse + * this section correctly. + */ + __RELA_START__ = .; + .rela.dyn . : { + } >RAM + __RELA_END__ = .; + #ifdef BL31_PROGBITS_LIMIT ASSERT(. <= BL31_PROGBITS_LIMIT, "BL31 progbits has exceeded its limit.") #endif @@ -265,11 +287,5 @@ SECTIONS __RW_END__ = .; __BL31_END__ = .; - __BSS_SIZE__ = SIZEOF(.bss); -#if USE_COHERENT_MEM - __COHERENT_RAM_UNALIGNED_SIZE__ = - __COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__; -#endif - ASSERT(. <= BL31_LIMIT, "BL31 image has exceeded its limit.") } diff --git a/docs/plat/meson-gxbb.rst b/docs/plat/meson-gxbb.rst new file mode 100644 index 000000000..f909e9933 --- /dev/null +++ b/docs/plat/meson-gxbb.rst @@ -0,0 +1,26 @@ +Trusted Firmware-A for Amlogic Meson S905 (GXBB) +================================================ + +The Amlogic Meson S905 is a SoC with a quad core Arm Cortex-A53 running at +1.5Ghz. It also contains a Cortex-M3 used as SCP. + +This port is a minimal implementation of BL31 capable of booting mainline U-Boot +and Linux: + +- SCPI support. +- Basic PSCI support (CPU_ON, CPU_OFF, SYSTEM_RESET, SYSTEM_OFF). Note that CPU0 + can't be turned off, so there is a workaround to hide this from the caller. +- GICv2 driver set up. +- Basic SIP services (read efuse data, enable/disable JTAG). + +In order to build it: + +:: + + CROSS_COMPILE=aarch64-linux-gnu- make DEBUG=1 PLAT=gxbb bl31 + +This port has been tested in a ODROID-C2. After building it, follow the +instructions in the `U-Boot repository`_, replacing the mentioned **bl31.bin** +by the one built from this port. + +.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/board/amlogic/odroid-c2/README diff --git a/docs/plat/stm32mp1.rst b/docs/plat/stm32mp1.rst index 9e731a419..f8379b4eb 100644 --- a/docs/plat/stm32mp1.rst +++ b/docs/plat/stm32mp1.rst @@ -76,7 +76,23 @@ To build: .. code:: bash make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 AARCH32_SP=sp_min + cd <u-boot_directory> + make stm32mp15_basic_defconfig + make DEVICE_TREE=stm32mp157c_ev1 all + ./tools/mkimage -T stm32image -a 0xC0100000 -e 0xC0100000 -d u-boot.bin u-boot.stm32 The following build options are supported: - ``ENABLE_STACK_PROTECTOR``: To enable the stack protection. + + +Populate SD-card +---------------- + +The SD-card has to be formated with GPT. +It should contain at least those partitions: + +- fsbl: to copy the tf-a-stm32mp157c-ev1.stm32 binary +- ssbl: to copy the u-boot.stm32 binary + +Usually, two copies of fsbl are used (fsbl1 and fsbl2) instead of one partition fsbl. diff --git a/docs/user-guide.rst b/docs/user-guide.rst index f4ef85d2a..52cb45c09 100644 --- a/docs/user-guide.rst +++ b/docs/user-guide.rst @@ -371,6 +371,10 @@ Common build options partitioning in EL3, however. Platform initialisation code should configure and use partitions in EL3 as required. This option defaults to ``0``. +- ``ENABLE_PIE``: Boolean option to enable Position Independent Executable(PIE) + support within generic code in TF-A. This option is currently only supported + in BL31. Default is 0. + - ``ENABLE_PMF``: Boolean option to enable support for optional Performance Measurement Framework(PMF). Default is 0. diff --git a/drivers/allwinner/sunxi_rsb.c b/drivers/allwinner/sunxi_rsb.c new file mode 100644 index 000000000..7075c674d --- /dev/null +++ b/drivers/allwinner/sunxi_rsb.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2017-2018 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <debug.h> +#include <delay_timer.h> +#include <errno.h> +#include <mmio.h> +#include <sunxi_mmap.h> + +#define RSB_CTRL 0x00 +#define RSB_CCR 0x04 +#define RSB_INTE 0x08 +#define RSB_STAT 0x0c +#define RSB_DADDR0 0x10 +#define RSB_DLEN 0x18 +#define RSB_DATA0 0x1c +#define RSB_LCR 0x24 +#define RSB_PMCR 0x28 +#define RSB_CMD 0x2c +#define RSB_SADDR 0x30 + +#define RSBCMD_SRTA 0xE8 +#define RSBCMD_RD8 0x8B +#define RSBCMD_RD16 0x9C +#define RSBCMD_RD32 0xA6 +#define RSBCMD_WR8 0x4E +#define RSBCMD_WR16 0x59 +#define RSBCMD_WR32 0x63 + +#define MAX_TRIES 100000 + +static int rsb_wait_bit(const char *desc, unsigned int offset, uint32_t mask) +{ + uint32_t reg, tries = MAX_TRIES; + + do + reg = mmio_read_32(SUNXI_R_RSB_BASE + offset); + while ((reg & mask) && --tries); /* transaction in progress */ + if (reg & mask) { + ERROR("%s: timed out\n", desc); + return -ETIMEDOUT; + } + + return 0; +} + +static int rsb_wait_stat(const char *desc) +{ + uint32_t reg; + int ret = rsb_wait_bit(desc, RSB_CTRL, BIT(7)); + + if (ret) + return ret; + + reg = mmio_read_32(SUNXI_R_RSB_BASE + RSB_STAT); + if (reg == 0x01) + return 0; + + ERROR("%s: 0x%x\n", desc, reg); + return -reg; +} + +/* Initialize the RSB controller. */ +int rsb_init_controller(void) +{ + mmio_write_32(SUNXI_R_RSB_BASE + RSB_CTRL, 0x01); /* soft reset */ + + return rsb_wait_bit("RSB: reset controller", RSB_CTRL, BIT(0)); +} + +int rsb_read(uint8_t rt_addr, uint8_t reg_addr) +{ + int ret; + + mmio_write_32(SUNXI_R_RSB_BASE + RSB_CMD, RSBCMD_RD8); /* read a byte */ + mmio_write_32(SUNXI_R_RSB_BASE + RSB_SADDR, rt_addr << 16); + mmio_write_32(SUNXI_R_RSB_BASE + RSB_DADDR0, reg_addr); + mmio_write_32(SUNXI_R_RSB_BASE + RSB_CTRL, 0x80);/* start transaction */ + + ret = rsb_wait_stat("RSB: read command"); + if (ret) + return ret; + + return mmio_read_32(SUNXI_R_RSB_BASE + RSB_DATA0) & 0xff; /* result */ +} + +int rsb_write(uint8_t rt_addr, uint8_t reg_addr, uint8_t value) +{ + mmio_write_32(SUNXI_R_RSB_BASE + RSB_CMD, RSBCMD_WR8); /* byte write */ + mmio_write_32(SUNXI_R_RSB_BASE + RSB_SADDR, rt_addr << 16); + mmio_write_32(SUNXI_R_RSB_BASE + RSB_DADDR0, reg_addr); + mmio_write_32(SUNXI_R_RSB_BASE + RSB_DATA0, value); + mmio_write_32(SUNXI_R_RSB_BASE + RSB_CTRL, 0x80);/* start transaction */ + + return rsb_wait_stat("RSB: write command"); +} + +int rsb_set_device_mode(uint32_t device_mode) +{ + mmio_write_32(SUNXI_R_RSB_BASE + RSB_PMCR, + (device_mode & 0x00ffffff) | BIT(31)); + + return rsb_wait_bit("RSB: set device to RSB", RSB_PMCR, BIT(31)); +} + +int rsb_set_bus_speed(uint32_t source_freq, uint32_t bus_freq) +{ + uint32_t reg; + + if (bus_freq == 0) + return -EINVAL; + + reg = source_freq / bus_freq; + if (reg < 2) + return -EINVAL; + + reg = reg / 2 - 1; + reg |= (1U << 8); /* one cycle of CD output delay */ + + mmio_write_32(SUNXI_R_RSB_BASE + RSB_CCR, reg); + + return 0; +} + +/* Initialize the RSB PMIC connection. */ +int rsb_assign_runtime_address(uint16_t hw_addr, uint8_t rt_addr) +{ + mmio_write_32(SUNXI_R_RSB_BASE + RSB_SADDR, hw_addr | (rt_addr << 16)); + mmio_write_32(SUNXI_R_RSB_BASE + RSB_CMD, RSBCMD_SRTA); + mmio_write_32(SUNXI_R_RSB_BASE + RSB_CTRL, 0x80); + + return rsb_wait_stat("RSB: set run-time address"); +} diff --git a/drivers/meson/console/aarch64/meson_console.S b/drivers/meson/console/aarch64/meson_console.S new file mode 100644 index 000000000..eaee10ef1 --- /dev/null +++ b/drivers/meson/console/aarch64/meson_console.S @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <asm_macros.S> +#include <assert_macros.S> +#define USE_FINISH_CONSOLE_REG_2 +#include <console_macros.S> +#include <meson_console.h> + + .globl console_meson_register + .globl console_meson_init + .globl console_meson_putc + .globl console_meson_getc + .globl console_meson_flush + .globl console_meson_core_putc + .globl console_meson_core_getc + .globl console_meson_core_flush + + /* ----------------------------------------------- + * Hardware definitions + * ----------------------------------------------- + */ +#define MESON_WFIFO_OFFSET 0x0 +#define MESON_RFIFO_OFFSET 0x4 +#define MESON_CONTROL_OFFSET 0x8 +#define MESON_STATUS_OFFSET 0xC +#define MESON_MISC_OFFSET 0x10 +#define MESON_REG5_OFFSET 0x14 + +#define MESON_CONTROL_CLR_ERROR_BIT 24 +#define MESON_CONTROL_RX_RESET_BIT 23 +#define MESON_CONTROL_TX_RESET_BIT 22 +#define MESON_CONTROL_RX_ENABLE_BIT 13 +#define MESON_CONTROL_TX_ENABLE_BIT 12 + +#define MESON_STATUS_RX_EMPTY_BIT 20 +#define MESON_STATUS_TX_FULL_BIT 21 +#define MESON_STATUS_TX_EMPTY_BIT 22 + +#define MESON_REG5_USE_XTAL_CLK_BIT 24 +#define MESON_REG5_USE_NEW_RATE_BIT 23 +#define MESON_REG5_NEW_BAUD_RATE_MASK 0x7FFFFF + + /* ----------------------------------------------- + * int console_meson_register(uintptr_t base, + * uint32_t clk, uint32_t baud, + * console_meson_t *console); + * Function to initialize and register a new MESON + * console. Storage passed in for the console struct + * *must* be persistent (i.e. not from the stack). + * In: x0 - UART register base address + * w1 - UART clock in Hz + * w2 - Baud rate + * x3 - pointer to empty console_meson_t struct + * Out: return 1 on success, 0 on error + * Clobber list : x0, x1, x2, x6, x7, x14 + * ----------------------------------------------- + */ +func console_meson_register + mov x7, x30 + mov x6, x3 + cbz x6, register_fail + str x0, [x6, #CONSOLE_T_MESON_BASE] + + bl console_meson_init + cbz x0, register_fail + + mov x0, x6 + mov x30, x7 + finish_console_register meson putc=1, getc=1, flush=1 + +register_fail: + ret x7 +endfunc console_meson_register + + /* ----------------------------------------------- + * int console_meson_init(uintptr_t base_addr, + * unsigned int uart_clk, unsigned int baud_rate) + * Function to initialize the console without a + * C Runtime to print debug information. This + * function will be accessed by console_init and + * crash reporting. + * In: x0 - console base address + * w1 - Uart clock in Hz + * w2 - Baud rate + * Out: return 1 on success else 0 on error + * Clobber list : x0-x3 + * ----------------------------------------------- + */ +func console_meson_init + cmp w0, #0 + beq init_fail + mov_imm w3, 24000000 /* TODO: This only works with a 24 MHz clock. */ + cmp w1, w3 + bne init_fail + cmp w2, #0 + beq init_fail + /* Set baud rate: value = ((clock / 3) / baudrate) - 1 */ + mov w3, #3 + udiv w3, w1, w3 + udiv w3, w3, w2 + sub w3, w3, #1 + orr w3, w3, #((1 << MESON_REG5_USE_XTAL_CLK_BIT) | \ + (1 << MESON_REG5_USE_NEW_RATE_BIT)) + str w3, [x0, #MESON_REG5_OFFSET] + /* Reset UART and clear error flag */ + ldr w3, [x0, #MESON_CONTROL_OFFSET] + orr w3, w3, #((1 << MESON_CONTROL_CLR_ERROR_BIT) | \ + (1 << MESON_CONTROL_RX_RESET_BIT) | \ + (1 << MESON_CONTROL_TX_RESET_BIT)) + str w3, [x0, #MESON_CONTROL_OFFSET] + bic w3, w3, #((1 << MESON_CONTROL_CLR_ERROR_BIT) | \ + (1 << MESON_CONTROL_RX_RESET_BIT) | \ + (1 << MESON_CONTROL_TX_RESET_BIT)) + str w3, [x0, #MESON_CONTROL_OFFSET] + /* Enable transfer and receive FIFO */ + orr w3, w3, #((1 << MESON_CONTROL_RX_ENABLE_BIT) | \ + (1 << MESON_CONTROL_TX_ENABLE_BIT)) + str w3, [x0, #MESON_CONTROL_OFFSET] + /* Success */ + mov w0, #1 + ret +init_fail: + mov w0, wzr + ret +endfunc console_meson_init + + /* -------------------------------------------------------- + * int console_meson_putc(int c, console_meson_t *console) + * Function to output a character over the console. It + * returns the character printed on success or -1 on error. + * In : w0 - character to be printed + * x1 - pointer to console_t structure + * Out : return -1 on error else return character. + * Clobber list : x2 + * -------------------------------------------------------- + */ +func console_meson_putc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x1, [x1, #CONSOLE_T_MESON_BASE] + b console_meson_core_putc +endfunc console_meson_putc + + /* -------------------------------------------------------- + * int console_meson_core_putc(int c, uintptr_t base_addr) + * Function to output a character over the console. It + * returns the character printed on success or -1 on error. + * In : w0 - character to be printed + * x1 - console base address + * Out : return -1 on error else return character. + * Clobber list : x2 + * -------------------------------------------------------- + */ +func console_meson_core_putc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif + /* Prepend '\r' to '\n' */ + cmp w0, #0xA + b.ne 2f + /* Wait until the transmit FIFO isn't full */ +1: ldr w2, [x1, #MESON_STATUS_OFFSET] + tbnz w2, #MESON_STATUS_TX_FULL_BIT, 1b + /* Write '\r' if needed */ + mov w2, #0xD + str w2, [x1, #MESON_WFIFO_OFFSET] + /* Wait until the transmit FIFO isn't full */ +2: ldr w2, [x1, #MESON_STATUS_OFFSET] + tbnz w2, #MESON_STATUS_TX_FULL_BIT, 2b + /* Write input character */ + str w0, [x1, #MESON_WFIFO_OFFSET] + ret +endfunc console_meson_core_putc + + /* --------------------------------------------- + * int console_meson_getc(console_meson_t *console) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 if no character is available. + * In : x0 - pointer to console_t structure + * Out: w0 - character if available, else -1 + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_meson_getc +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x0, [x0, #CONSOLE_T_MESON_BASE] + b console_meson_core_getc +endfunc console_meson_getc + + /* --------------------------------------------- + * int console_meson_core_getc(uintptr_t base_addr) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 if no character is available. + * In : x0 - console base address + * Out: w0 - character if available, else -1 + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_meson_core_getc +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif + /* Is the receive FIFO empty? */ + ldr w1, [x0, #MESON_STATUS_OFFSET] + tbnz w1, #MESON_STATUS_RX_EMPTY_BIT, 1f + /* Read one character from the RX FIFO */ + ldr w0, [x0, #MESON_RFIFO_OFFSET] + ret +1: + mov w0, #ERROR_NO_PENDING_CHAR + ret +endfunc console_meson_core_getc + + /* --------------------------------------------- + * int console_meson_flush(console_meson_t *console) + * Function to force a write of all buffered + * data that hasn't been output. + * In : x0 - pointer to console_t structure + * Out : return -1 on error else return 0. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_meson_flush +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x0, [x0, #CONSOLE_T_MESON_BASE] + b console_meson_core_flush +endfunc console_meson_flush + + /* --------------------------------------------- + * int console_meson_core_flush(uintptr_t base_addr) + * Function to force a write of all buffered + * data that hasn't been output. + * In : x0 - console base address + * Out : return -1 on error else return 0. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_meson_core_flush +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif + /* Wait until the transmit FIFO is empty */ +1: ldr w1, [x0, #MESON_STATUS_OFFSET] + tbz w1, #MESON_STATUS_TX_EMPTY_BIT, 1b + mov w0, #0 + ret +endfunc console_meson_core_flush diff --git a/include/common/aarch64/asm_macros.S b/include/common/aarch64/asm_macros.S index 9621a1c02..91416e4e4 100644 --- a/include/common/aarch64/asm_macros.S +++ b/include/common/aarch64/asm_macros.S @@ -105,8 +105,9 @@ * Clobber: X30, X1, X2 */ .macro get_my_mp_stack _name, _size - bl plat_my_core_pos - ldr x2, =(\_name + \_size) + bl plat_my_core_pos + adrp x2, (\_name + \_size) + add x2, x2, :lo12:(\_name + \_size) mov x1, #\_size madd x0, x0, x1, x2 .endm @@ -117,7 +118,8 @@ * Out: X0 = physical address of stack base */ .macro get_up_stack _name, _size - ldr x0, =(\_name + \_size) + adrp x0, (\_name + \_size) + add x0, x0, :lo12:(\_name + \_size) .endm /* diff --git a/include/common/aarch64/el3_common_macros.S b/include/common/aarch64/el3_common_macros.S index 143c70c39..4902583b1 100644 --- a/include/common/aarch64/el3_common_macros.S +++ b/include/common/aarch64/el3_common_macros.S @@ -283,26 +283,38 @@ * an earlier boot loader stage. * ------------------------------------------------------------- */ - ldr x0, =__RW_START__ - ldr x1, =__RW_END__ + adrp x0, __RW_START__ + add x0, x0, :lo12:__RW_START__ + adrp x1, __RW_END__ + add x1, x1, :lo12:__RW_END__ sub x1, x1, x0 bl inv_dcache_range #endif + adrp x0, __BSS_START__ + add x0, x0, :lo12:__BSS_START__ - ldr x0, =__BSS_START__ - ldr x1, =__BSS_SIZE__ + adrp x1, __BSS_END__ + add x1, x1, :lo12:__BSS_END__ + sub x1, x1, x0 bl zeromem #if USE_COHERENT_MEM - ldr x0, =__COHERENT_RAM_START__ - ldr x1, =__COHERENT_RAM_UNALIGNED_SIZE__ + adrp x0, __COHERENT_RAM_START__ + add x0, x0, :lo12:__COHERENT_RAM_START__ + adrp x1, __COHERENT_RAM_END_UNALIGNED__ + add x1, x1, :lo12: __COHERENT_RAM_END_UNALIGNED__ + sub x1, x1, x0 bl zeromem #endif #if defined(IMAGE_BL1) || (defined(IMAGE_BL2) && BL2_IN_XIP_MEM) - ldr x0, =__DATA_RAM_START__ - ldr x1, =__DATA_ROM_START__ - ldr x2, =__DATA_SIZE__ + adrp x0, __DATA_RAM_START__ + add x0, x0, :lo12:__DATA_RAM_START__ + adrp x1, __DATA_ROM_START__ + add x1, x1, :lo12:__DATA_ROM_START__ + adrp x2, __DATA_RAM_END__ + add x2, x2, :lo12:__DATA_RAM_END__ + sub x2, x2, x0 bl memcpy16 #endif .endif /* _init_c_runtime */ diff --git a/include/common/bl_common.h b/include/common/bl_common.h index af598d0da..6a79dc33f 100644 --- a/include/common/bl_common.h +++ b/include/common/bl_common.h @@ -83,6 +83,7 @@ IMPORT_SYM(unsigned long, __BL2_END__, BL2_END); #elif defined(IMAGE_BL2U) IMPORT_SYM(unsigned long, __BL2U_END__, BL2U_END); #elif defined(IMAGE_BL31) +IMPORT_SYM(unsigned long, __BL31_START__, BL31_START); IMPORT_SYM(unsigned long, __BL31_END__, BL31_END); #elif defined(IMAGE_BL32) IMPORT_SYM(unsigned long, __BL32_END__, BL32_END); @@ -193,6 +194,11 @@ extern const char version_string[]; void print_entry_point_info(const entry_point_info_t *ep_info); uintptr_t page_align(uintptr_t value, unsigned dir); +struct mmap_region; + +void setup_page_tables(const struct mmap_region *bl_regions, + const struct mmap_region *plat_regions); + #endif /*__ASSEMBLY__*/ #endif /* __BL_COMMON_H__ */ diff --git a/include/drivers/allwinner/sunxi_rsb.h b/include/drivers/allwinner/sunxi_rsb.h new file mode 100644 index 000000000..5a69d35f2 --- /dev/null +++ b/include/drivers/allwinner/sunxi_rsb.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2017-2018 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SUNXI_RSB_H +#define SUNXI_RSB_H + +#include <stdint.h> + +int rsb_init_controller(void); +int rsb_set_bus_speed(uint32_t source_freq, uint32_t bus_freq); +int rsb_set_device_mode(uint32_t device_mode); +int rsb_assign_runtime_address(uint16_t hw_addr, uint8_t rt_addr); + +int rsb_read(uint8_t rt_addr, uint8_t reg_addr); +int rsb_write(uint8_t rt_addr, uint8_t reg_addr, uint8_t value); + +#endif diff --git a/include/drivers/meson/meson_console.h b/include/drivers/meson/meson_console.h new file mode 100644 index 000000000..759571dda --- /dev/null +++ b/include/drivers/meson/meson_console.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MESON_CONSOLE_H +#define MESON_CONSOLE_H + +#include <console.h> + +#define CONSOLE_T_MESON_BASE CONSOLE_T_DRVDATA + +#ifndef __ASSEMBLY__ + +#include <stdint.h> + +typedef struct { + console_t console; + uintptr_t base; +} console_meson_t; + +/* + * Initialize a new meson console instance and register it with the console + * framework. The |console| pointer must point to storage that will be valid + * for the lifetime of the console, such as a global or static local variable. + * Its contents will be reinitialized from scratch. + * + * NOTE: The clock is actually fixed to 24 MHz. The argument is only there in + * order to make this function future-proof. + */ +int console_meson_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud, + console_meson_t *console); + +#endif /*__ASSEMBLY__*/ + +#endif /* MESON_CONSOLE_H */ diff --git a/include/lib/cpus/aarch32/cpu_macros.S b/include/lib/cpus/aarch32/cpu_macros.S index 525e18caf..aa728b241 100644 --- a/include/lib/cpus/aarch32/cpu_macros.S +++ b/include/lib/cpus/aarch32/cpu_macros.S @@ -161,10 +161,9 @@ .endif /* - * Weakly-bound, optional errata status printing function for CPUs of + * Mandatory errata status printing function for CPUs of * this class. */ - .weak \_name\()_errata_report .word \_name\()_errata_report #ifdef IMAGE_BL32 diff --git a/include/lib/cpus/aarch64/cortex_a75.h b/include/lib/cpus/aarch64/cortex_a75.h index 493c7d472..f68f98f63 100644 --- a/include/lib/cpus/aarch64/cortex_a75.h +++ b/include/lib/cpus/aarch64/cortex_a75.h @@ -4,11 +4,13 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef __CORTEX_A75_H__ -#define __CORTEX_A75_H__ +#ifndef CORTEX_A75_H +#define CORTEX_A75_H + +#include <utils_def.h> /* Cortex-A75 MIDR */ -#define CORTEX_A75_MIDR 0x410fd0a0 +#define CORTEX_A75_MIDR U(0x410fd0a0) /******************************************************************************* * CPU Extended Control register specific definitions. @@ -24,7 +26,7 @@ #define CORTEX_A75_CPUACTLR_EL1_DISABLE_LOAD_PASS_STORE (1 << 35) /* Definitions of register field mask in CORTEX_A75_CPUPWRCTLR_EL1 */ -#define CORTEX_A75_CORE_PWRDN_EN_MASK 0x1 +#define CORTEX_A75_CORE_PWRDN_EN_MASK U(0x1) #define CORTEX_A75_ACTLR_AMEN_BIT (U(1) << 4) @@ -50,4 +52,4 @@ void cortex_a75_amu_write_cpuamcntenset_el0(unsigned int mask); void cortex_a75_amu_write_cpuamcntenclr_el0(unsigned int mask); #endif /* __ASSEMBLY__ */ -#endif /* __CORTEX_A75_H__ */ +#endif /* CORTEX_A75_H */ diff --git a/include/lib/cpus/aarch64/cortex_ares.h b/include/lib/cpus/aarch64/cortex_ares.h index 84955b181..4f3e81296 100644 --- a/include/lib/cpus/aarch64/cortex_ares.h +++ b/include/lib/cpus/aarch64/cortex_ares.h @@ -4,11 +4,13 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef __CORTEX_ARES_H__ -#define __CORTEX_ARES_H__ +#ifndef CORTEX_ARES_H +#define CORTEX_ARES_H + +#include <utils_def.h> /* Cortex-ARES MIDR for revision 0 */ -#define CORTEX_ARES_MIDR 0x410fd0c0 +#define CORTEX_ARES_MIDR U(0x410fd0c0) /******************************************************************************* * CPU Extended Control register specific definitions. @@ -17,7 +19,7 @@ #define CORTEX_ARES_CPUECTLR_EL1 S3_0_C15_C1_4 /* Definitions of register field mask in CORTEX_ARES_CPUPWRCTLR_EL1 */ -#define CORTEX_ARES_CORE_PWRDN_EN_MASK 0x1 +#define CORTEX_ARES_CORE_PWRDN_EN_MASK U(0x1) #define CORTEX_ARES_ACTLR_AMEN_BIT (U(1) << 4) @@ -30,4 +32,4 @@ #define CPUPOR_EL3 S3_6_C15_C8_2 #define CPUPMR_EL3 S3_6_C15_C8_3 -#endif /* __CORTEX_ARES_H__ */ +#endif /* CORTEX_ARES_H */ diff --git a/include/lib/cpus/aarch64/cpu_macros.S b/include/lib/cpus/aarch64/cpu_macros.S index 4672cbc06..14616ace4 100644 --- a/include/lib/cpus/aarch64/cpu_macros.S +++ b/include/lib/cpus/aarch64/cpu_macros.S @@ -183,10 +183,9 @@ .endif /* - * Weakly-bound, optional errata status printing function for CPUs of + * Mandatory errata status printing function for CPUs of * this class. */ - .weak \_name\()_errata_report .quad \_name\()_errata_report #ifdef IMAGE_BL31 diff --git a/include/lib/cpus/aarch64/cpuamu.h b/include/lib/cpus/aarch64/cpuamu.h index 960a52484..921abdbd4 100644 --- a/include/lib/cpus/aarch64/cpuamu.h +++ b/include/lib/cpus/aarch64/cpuamu.h @@ -4,8 +4,8 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef __CPUAMU_H__ -#define __CPUAMU_H__ +#ifndef CPUAMU_H +#define CPUAMU_H /******************************************************************************* * CPU Activity Monitor Unit register specific definitions. @@ -32,8 +32,8 @@ #ifndef __ASSEMBLY__ #include <stdint.h> -uint64_t cpuamu_cnt_read(int idx); -void cpuamu_cnt_write(int idx, uint64_t val); +uint64_t cpuamu_cnt_read(unsigned int idx); +void cpuamu_cnt_write(unsigned int idx, uint64_t val); unsigned int cpuamu_read_cpuamcntenset_el0(void); unsigned int cpuamu_read_cpuamcntenclr_el0(void); void cpuamu_write_cpuamcntenset_el0(unsigned int mask); @@ -45,4 +45,4 @@ void cpuamu_context_restore(unsigned int nr_counters); #endif /* __ASSEMBLY__ */ -#endif /* __CPUAMU_H__ */ +#endif /* CPUAMU_H */ diff --git a/include/lib/cpus/errata_report.h b/include/lib/cpus/errata_report.h index d2138bf55..c97d4c247 100644 --- a/include/lib/cpus/errata_report.h +++ b/include/lib/cpus/errata_report.h @@ -4,8 +4,8 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef __ERRATA_H__ -#define __ERRATA_H__ +#ifndef ERRATA_REPORT_H +#define ERRATA_REPORT_H #ifndef __ASSEMBLY__ @@ -30,5 +30,4 @@ int errata_needs_reporting(spinlock_t *lock, uint32_t *reported); #define ERRATA_APPLIES 1 #define ERRATA_MISSING 2 -#endif /* __ERRATA_H__ */ - +#endif /* ERRATA_REPORT_H */ diff --git a/include/lib/cpus/wa_cve_2017_5715.h b/include/lib/cpus/wa_cve_2017_5715.h index 0a65a5692..940fc659e 100644 --- a/include/lib/cpus/wa_cve_2017_5715.h +++ b/include/lib/cpus/wa_cve_2017_5715.h @@ -4,9 +4,9 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef __WA_CVE_2017_5715_H__ -#define __WA_CVE_2017_5715_H__ +#ifndef WA_CVE_2017_5715_H +#define WA_CVE_2017_5715_H int check_wa_cve_2017_5715(void); -#endif /* __WA_CVE_2017_5715_H__ */ +#endif /* WA_CVE_2017_5715_H */ diff --git a/include/lib/cpus/wa_cve_2018_3639.h b/include/lib/cpus/wa_cve_2018_3639.h index 36546f70d..e37db377e 100644 --- a/include/lib/cpus/wa_cve_2018_3639.h +++ b/include/lib/cpus/wa_cve_2018_3639.h @@ -4,9 +4,9 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef __WA_CVE_2018_3639_H__ -#define __WA_CVE_2018_3639_H__ +#ifndef WA_CVE_2018_3639_H +#define WA_CVE_2018_3639_H void *wa_cve_2018_3639_get_disable_ptr(void); -#endif /* __WA_CVE_2018_3639_H__ */ +#endif /* WA_CVE_2018_3639_H */ diff --git a/include/lib/el3_runtime/cpu_data.h b/include/lib/el3_runtime/cpu_data.h index 15d34ebf8..b6959509c 100644 --- a/include/lib/el3_runtime/cpu_data.h +++ b/include/lib/el3_runtime/cpu_data.h @@ -4,8 +4,8 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef __CPU_DATA_H__ -#define __CPU_DATA_H__ +#ifndef CPU_DATA_H +#define CPU_DATA_H #include <ehf.h> #include <platform_def.h> /* CACHE_WRITEBACK_GRANULE required */ @@ -161,4 +161,4 @@ void init_cpu_ops(void); #endif /* __ASSEMBLY__ */ -#endif /* __CPU_DATA_H__ */ +#endif /* CPU_DATA_H */ diff --git a/include/lib/extensions/amu.h b/include/lib/extensions/amu.h index 46d5e1593..1836fe5ae 100644 --- a/include/lib/extensions/amu.h +++ b/include/lib/extensions/amu.h @@ -4,33 +4,35 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef __AMU_H__ -#define __AMU_H__ +#ifndef AMU_H +#define AMU_H #include <cassert.h> #include <platform_def.h> +#include <stdbool.h> #include <stdint.h> +#include <utils_def.h> /* All group 0 counters */ -#define AMU_GROUP0_COUNTERS_MASK 0xf +#define AMU_GROUP0_COUNTERS_MASK U(0xf) #ifdef PLAT_AMU_GROUP1_COUNTERS_MASK #define AMU_GROUP1_COUNTERS_MASK PLAT_AMU_GROUP1_COUNTERS_MASK #else -#define AMU_GROUP1_COUNTERS_MASK 0 +#define AMU_GROUP1_COUNTERS_MASK U(0) #endif #ifdef PLAT_AMU_GROUP1_NR_COUNTERS #define AMU_GROUP1_NR_COUNTERS PLAT_AMU_GROUP1_NR_COUNTERS #else -#define AMU_GROUP1_NR_COUNTERS 0 +#define AMU_GROUP1_NR_COUNTERS U(0) #endif CASSERT(AMU_GROUP1_COUNTERS_MASK <= 0xffff, invalid_amu_group1_counters_mask); CASSERT(AMU_GROUP1_NR_COUNTERS <= 16, invalid_amu_group1_nr_counters); -int amu_supported(void); -void amu_enable(int el2_unused); +bool amu_supported(void); +void amu_enable(bool el2_unused); /* Group 0 configuration helpers */ uint64_t amu_group0_cnt_read(int idx); @@ -41,4 +43,4 @@ uint64_t amu_group1_cnt_read(int idx); void amu_group1_cnt_write(int idx, uint64_t val); void amu_group1_set_evtype(int idx, unsigned int val); -#endif /* __AMU_H__ */ +#endif /* AMU_H */ diff --git a/include/lib/extensions/amu_private.h b/include/lib/extensions/amu_private.h index 0c660bb83..ab4e6aaba 100644 --- a/include/lib/extensions/amu_private.h +++ b/include/lib/extensions/amu_private.h @@ -1,19 +1,19 @@ /* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef __AMU_PRIVATE_H__ -#define __AMU_PRIVATE_H__ +#ifndef AMU_PRIVATE_H +#define AMU_PRIVATE_H #include <stdint.h> uint64_t amu_group0_cnt_read_internal(int idx); -void amu_group0_cnt_write_internal(int idx, uint64_t); +void amu_group0_cnt_write_internal(int idx, uint64_t val); uint64_t amu_group1_cnt_read_internal(int idx); -void amu_group1_cnt_write_internal(int idx, uint64_t); +void amu_group1_cnt_write_internal(int idx, uint64_t val); void amu_group1_set_evtype_internal(int idx, unsigned int val); -#endif /* __AMU_PRIVATE_H__ */ +#endif /* AMU_PRIVATE_H */ diff --git a/include/lib/extensions/mpam.h b/include/lib/extensions/mpam.h index 571b96b65..ac8c00a43 100644 --- a/include/lib/extensions/mpam.h +++ b/include/lib/extensions/mpam.h @@ -10,6 +10,6 @@ #include <stdbool.h> bool mpam_supported(void); -void mpam_enable(int el2_unused); +void mpam_enable(bool el2_unused); #endif /* MPAM_H */ diff --git a/include/lib/extensions/spe.h b/include/lib/extensions/spe.h index b2b188ef5..d4b925fe4 100644 --- a/include/lib/extensions/spe.h +++ b/include/lib/extensions/spe.h @@ -4,11 +4,13 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef __SPE_H__ -#define __SPE_H__ +#ifndef SPE_H +#define SPE_H -int spe_supported(void); -void spe_enable(int el2_unused); +#include <stdbool.h> + +bool spe_supported(void); +void spe_enable(bool el2_unused); void spe_disable(void); -#endif /* __SPE_H__ */ +#endif /* SPE_H */ diff --git a/include/lib/extensions/sve.h b/include/lib/extensions/sve.h index 9c7f37f26..83df1775e 100644 --- a/include/lib/extensions/sve.h +++ b/include/lib/extensions/sve.h @@ -4,10 +4,12 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef __SVE_H__ -#define __SVE_H__ +#ifndef SVE_H +#define SVE_H -int sve_supported(void); -void sve_enable(int el2_unused); +#include <stdbool.h> -#endif /* __SVE_H__ */ +bool sve_supported(void); +void sve_enable(bool el2_unused); + +#endif /* SVE_H */ diff --git a/include/lib/pmf/pmf.h b/include/lib/pmf/pmf.h index a3812fbf2..18ef0a559 100644 --- a/include/lib/pmf/pmf.h +++ b/include/lib/pmf/pmf.h @@ -9,17 +9,18 @@ #include <cassert.h> #include <pmf_helpers.h> +#include <utils_def.h> /* * Constants used for/by PMF services. */ -#define PMF_ARM_TIF_IMPL_ID 0x41 +#define PMF_ARM_TIF_IMPL_ID U(0x41) #define PMF_TID_SHIFT 0 -#define PMF_TID_MASK (0xFF << PMF_TID_SHIFT) +#define PMF_TID_MASK (U(0xFF) << PMF_TID_SHIFT) #define PMF_SVC_ID_SHIFT 10 -#define PMF_SVC_ID_MASK (0x3F << PMF_SVC_ID_SHIFT) +#define PMF_SVC_ID_MASK (U(0x3F) << PMF_SVC_ID_SHIFT) #define PMF_IMPL_ID_SHIFT 24 -#define PMF_IMPL_ID_MASK (0xFFU << PMF_IMPL_ID_SHIFT) +#define PMF_IMPL_ID_MASK (U(0xFF) << PMF_IMPL_ID_SHIFT) /* * Flags passed to PMF_REGISTER_SERVICE @@ -37,16 +38,16 @@ /* * Defines for PMF SMC function ids. */ -#define PMF_SMC_GET_TIMESTAMP_32 0x82000010u -#define PMF_SMC_GET_TIMESTAMP_64 0xC2000010u +#define PMF_SMC_GET_TIMESTAMP_32 U(0x82000010) +#define PMF_SMC_GET_TIMESTAMP_64 U(0xC2000010) #define PMF_NUM_SMC_CALLS 2 /* * The macros below are used to identify * PMF calls from the SMC function ID. */ -#define PMF_FID_MASK 0xffe0u -#define PMF_FID_VALUE 0u +#define PMF_FID_MASK U(0xffe0) +#define PMF_FID_VALUE U(0) #define is_pmf_fid(_fid) (((_fid) & PMF_FID_MASK) == PMF_FID_VALUE) /* Following are the supported PMF service IDs */ diff --git a/include/lib/pmf/pmf_asm_macros.S b/include/lib/pmf/pmf_asm_macros.S index d58829eec..5e19e62f7 100644 --- a/include/lib/pmf/pmf_asm_macros.S +++ b/include/lib/pmf/pmf_asm_macros.S @@ -18,10 +18,12 @@ mov x9, x30 bl plat_my_core_pos mov x30, x9 - ldr x1, =__PERCPU_TIMESTAMP_SIZE__ + adr x2, __PMF_PERCPU_TIMESTAMP_END__ + adr x1, __PMF_TIMESTAMP_START__ + sub x1, x2, x1 mov x2, #(\_tid * PMF_TS_SIZE) madd x0, x0, x1, x2 - ldr x1, =pmf_ts_mem_\_name + adr x1, pmf_ts_mem_\_name add x0, x0, x1 .endm diff --git a/include/lib/pmf/pmf_helpers.h b/include/lib/pmf/pmf_helpers.h index b9757de07..c535b222d 100644 --- a/include/lib/pmf/pmf_helpers.h +++ b/include/lib/pmf/pmf_helpers.h @@ -11,7 +11,6 @@ #include <assert.h> #include <bl_common.h> #include <platform.h> -#include <pmf.h> #include <stddef.h> #include <stdint.h> diff --git a/include/lib/utils.h b/include/lib/utils.h index d46d8461d..f324a9909 100644 --- a/include/lib/utils.h +++ b/include/lib/utils.h @@ -67,6 +67,29 @@ void zero_normalmem(void *mem, u_register_t length); * zeroing. */ void zeromem(void *mem, u_register_t length); + +/* + * Utility function to return the address of a symbol. By default, the + * compiler generates adr/adrp instruction pair to return the reference + * to the symbol and this utility is used to override this compiler + * generated to code to use `ldr` instruction. + * + * This helps when Position Independent Executable needs to reference a symbol + * which is constant and does not depend on the execute address of the binary. + */ +#define DEFINE_LOAD_SYM_ADDR(_name) \ +static inline u_register_t load_addr_## _name(void) \ +{ \ + u_register_t v; \ + /* Create a void reference to silence compiler */ \ + (void) _name; \ + __asm__ volatile ("ldr %0, =" #_name : "=r" (v)); \ + return v; \ +} + +/* Helper to invoke the function defined by DEFINE_LOAD_SYM_ADDR() */ +#define LOAD_ADDR_OF(_name) (typeof(_name) *) load_addr_## _name() + #endif /* !(defined(__LINKER__) || defined(__ASSEMBLY__)) */ #endif /* __UTILS_H__ */ diff --git a/include/lib/xlat_tables/xlat_tables_compat.h b/include/lib/xlat_tables/xlat_tables_compat.h new file mode 100644 index 000000000..4650a8c6f --- /dev/null +++ b/include/lib/xlat_tables/xlat_tables_compat.h @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if XLAT_TABLES_LIB_V2 +#include <xlat_tables_v2.h> +#else +#include <xlat_tables.h> +#endif diff --git a/include/plat/arm/board/common/v2m_def.h b/include/plat/arm/board/common/v2m_def.h index 02c349418..4a1d43c85 100644 --- a/include/plat/arm/board/common/v2m_def.h +++ b/include/plat/arm/board/common/v2m_def.h @@ -6,8 +6,7 @@ #ifndef V2M_DEF_H #define V2M_DEF_H -#include <arm_xlat_tables.h> - +#include <xlat_tables_compat.h> /* V2M motherboard system registers & offsets */ #define V2M_SYSREGS_BASE UL(0x1c010000) diff --git a/include/plat/arm/common/arm_sip_svc.h b/include/plat/arm/common/arm_sip_svc.h index 68375afae..3e25cbc6a 100644 --- a/include/plat/arm/common/arm_sip_svc.h +++ b/include/plat/arm/common/arm_sip_svc.h @@ -1,24 +1,26 @@ /* - * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef __ARM_SIP_SVC_H__ -#define __ARM_SIP_SVC_H__ +#ifndef ARM_SIP_SVC_H +#define ARM_SIP_SVC_H + +#include <utils_def.h> /* SMC function IDs for SiP Service queries */ -#define ARM_SIP_SVC_CALL_COUNT 0x8200ff00 -#define ARM_SIP_SVC_UID 0x8200ff01 -/* 0x8200ff02 is reserved */ -#define ARM_SIP_SVC_VERSION 0x8200ff03 +#define ARM_SIP_SVC_CALL_COUNT U(0x8200ff00) +#define ARM_SIP_SVC_UID U(0x8200ff01) +/* U(0x8200ff02) is reserved */ +#define ARM_SIP_SVC_VERSION U(0x8200ff03) /* Function ID for requesting state switch of lower EL */ -#define ARM_SIP_SVC_EXE_STATE_SWITCH 0x82000020 +#define ARM_SIP_SVC_EXE_STATE_SWITCH U(0x82000020) /* ARM SiP Service Calls version numbers */ -#define ARM_SIP_SVC_VERSION_MAJOR 0x0 -#define ARM_SIP_SVC_VERSION_MINOR 0x2 +#define ARM_SIP_SVC_VERSION_MAJOR U(0x0) +#define ARM_SIP_SVC_VERSION_MINOR U(0x2) -#endif /* __ARM_SIP_SVC_H__ */ +#endif /* ARM_SIP_SVC_H */ diff --git a/include/plat/arm/common/arm_xlat_tables.h b/include/plat/arm/common/arm_xlat_tables.h deleted file mode 100644 index 0923ad8a1..000000000 --- a/include/plat/arm/common/arm_xlat_tables.h +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#if ARM_XLAT_TABLES_LIB_V1 -#include <xlat_tables.h> -#else -#include <xlat_tables_v2.h> -#endif /* ARM_XLAT_TABLES_LIB_V1 */ diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h index 773c3603e..e7082d080 100644 --- a/include/plat/arm/common/plat_arm.h +++ b/include/plat/arm/common/plat_arm.h @@ -3,10 +3,9 @@ * * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef __PLAT_ARM_H__ -#define __PLAT_ARM_H__ +#ifndef PLAT_ARM_H +#define PLAT_ARM_H -#include <arm_xlat_tables.h> #include <bakery_lock.h> #include <cassert.h> #include <cpu_data.h> @@ -14,6 +13,7 @@ #include <spinlock.h> #include <tzc_common.h> #include <utils_def.h> +#include <xlat_tables_compat.h> /******************************************************************************* * Forward declarations @@ -66,12 +66,6 @@ typedef struct arm_tzc_regions_info { <= MAX_MMAP_REGIONS, \ assert_max_mmap_regions); -/* - * Utility functions common to ARM standard platforms - */ -void arm_setup_page_tables(const mmap_region_t bl_regions[], - const mmap_region_t plat_regions[]); - void arm_setup_romlib(void); #if defined(IMAGE_BL31) || (defined(AARCH32) && defined(IMAGE_BL32)) @@ -298,4 +292,4 @@ extern plat_psci_ops_t plat_arm_psci_pm_ops; extern const mmap_region_t plat_arm_mmap[]; extern const unsigned int arm_pm_idle_states[]; -#endif /* __PLAT_ARM_H__ */ +#endif /* PLAT_ARM_H */ diff --git a/lib/aarch64/misc_helpers.S b/lib/aarch64/misc_helpers.S index 1a075aa5a..002942e8d 100644 --- a/lib/aarch64/misc_helpers.S +++ b/lib/aarch64/misc_helpers.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -7,6 +7,7 @@ #include <arch.h> #include <asm_macros.S> #include <assert_macros.S> +#include <xlat_tables_defs.h> .globl get_afflvl_shift .globl mpidr_mask_lower_afflvls @@ -23,6 +24,8 @@ .globl disable_mmu_icache_el1 .globl disable_mmu_icache_el3 + .globl fixup_gdt_reloc + #if SUPPORT_VFP .globl enable_vfp #endif @@ -497,3 +500,114 @@ func enable_vfp ret endfunc enable_vfp #endif + +/* --------------------------------------------------------------------------- + * Helper to fixup Global Descriptor table (GDT) and dynamic relocations + * (.rela.dyn) at runtime. + * + * This function is meant to be used when the firmware is compiled with -fpie + * and linked with -pie options. We rely on the linker script exporting + * appropriate markers for start and end of the section. For GOT, we + * expect __GOT_START__ and __GOT_END__. Similarly for .rela.dyn, we expect + * __RELA_START__ and __RELA_END__. + * + * The function takes the limits of the memory to apply fixups to as + * arguments (which is usually the limits of the relocable BL image). + * x0 - the start of the fixup region + * x1 - the limit of the fixup region + * These addresses have to be page (4KB aligned). + * --------------------------------------------------------------------------- + */ +func fixup_gdt_reloc + mov x6, x0 + mov x7, x1 + + /* Test if the limits are 4K aligned */ +#if ENABLE_ASSERTIONS + orr x0, x0, x1 + tst x0, #(PAGE_SIZE - 1) + ASM_ASSERT(eq) +#endif + /* + * Calculate the offset based on return address in x30. + * Assume that this funtion is called within a page of the start of + * of fixup region. + */ + and x2, x30, #~(PAGE_SIZE - 1) + sub x0, x2, x6 /* Diff(S) = Current Address - Compiled Address */ + + adrp x1, __GOT_START__ + add x1, x1, :lo12:__GOT_START__ + adrp x2, __GOT_END__ + add x2, x2, :lo12:__GOT_END__ + + /* + * GOT is an array of 64_bit addresses which must be fixed up as + * new_addr = old_addr + Diff(S). + * The new_addr is the address currently the binary is executing from + * and old_addr is the address at compile time. + */ +1: + ldr x3, [x1] + /* Skip adding offset if address is < lower limit */ + cmp x3, x6 + b.lo 2f + /* Skip adding offset if address is >= upper limit */ + cmp x3, x7 + b.ge 2f + add x3, x3, x0 + str x3, [x1] +2: + add x1, x1, #8 + cmp x1, x2 + b.lo 1b + + /* Starting dynamic relocations. Use adrp/adr to get RELA_START and END */ + adrp x1, __RELA_START__ + add x1, x1, :lo12:__RELA_START__ + adrp x2, __RELA_END__ + add x2, x2, :lo12:__RELA_END__ + /* + * According to ELF-64 specification, the RELA data structure is as + * follows: + * typedef struct + * { + * Elf64_Addr r_offset; + * Elf64_Xword r_info; + * Elf64_Sxword r_addend; + * } Elf64_Rela; + * + * r_offset is address of reference + * r_info is symbol index and type of relocation (in this case + * 0x403 which corresponds to R_AARCH64_RELATIV). + * r_addend is constant part of expression. + * + * Size of Elf64_Rela structure is 24 bytes. + */ +1: + /* Assert that the relocation type is R_AARCH64_RELATIV */ +#if ENABLE_ASSERTIONS + ldr x3, [x1, #8] + cmp x3, #0x403 + ASM_ASSERT(eq) +#endif + ldr x3, [x1] /* r_offset */ + add x3, x0, x3 + ldr x4, [x1, #16] /* r_addend */ + + /* Skip adding offset if r_addend is < lower limit */ + cmp x4, x6 + b.lo 2f + /* Skip adding offset if r_addend entry is >= upper limit */ + cmp x4, x7 + b.ge 2f + + add x4, x0, x4 /* Diff(S) + r_addend */ + str x4, [x3] + +2: add x1, x1, #24 + cmp x1, x2 + b.lo 1b + + ret +endfunc fixup_gdt_reloc diff --git a/lib/cpus/aarch32/aem_generic.S b/lib/cpus/aarch32/aem_generic.S index 5f3d74470..7bd586ad9 100644 --- a/lib/cpus/aarch32/aem_generic.S +++ b/lib/cpus/aarch32/aem_generic.S @@ -40,6 +40,15 @@ func aem_generic_cluster_pwr_dwn b dcsw_op_all endfunc aem_generic_cluster_pwr_dwn +#if REPORT_ERRATA +/* + * Errata printing function for AEM. Must follow AAPCS. + */ +func aem_generic_errata_report + bx lr +endfunc aem_generic_errata_report +#endif + /* cpu_ops for Base AEM FVP */ declare_cpu_ops aem_generic, BASE_AEM_MIDR, CPU_NO_RESET_FUNC, \ aem_generic_core_pwr_dwn, \ diff --git a/lib/cpus/aarch32/cortex_a12.S b/lib/cpus/aarch32/cortex_a12.S index 73c975072..5300fe009 100644 --- a/lib/cpus/aarch32/cortex_a12.S +++ b/lib/cpus/aarch32/cortex_a12.S @@ -69,6 +69,15 @@ func cortex_a12_cluster_pwr_dwn b cortex_a12_disable_smp endfunc cortex_a12_cluster_pwr_dwn +#if REPORT_ERRATA +/* + * Errata printing function for Cortex-A12. Must follow AAPCS. + */ +func cortex_a12_errata_report + bx lr +endfunc cortex_a12_errata_report +#endif + declare_cpu_ops cortex_a12, CORTEX_A12_MIDR, \ cortex_a12_reset_func, \ cortex_a12_core_pwr_dwn, \ diff --git a/lib/cpus/aarch32/cortex_a32.S b/lib/cpus/aarch32/cortex_a32.S index 2b6df272d..c26227622 100644 --- a/lib/cpus/aarch32/cortex_a32.S +++ b/lib/cpus/aarch32/cortex_a32.S @@ -117,6 +117,15 @@ func cortex_a32_cluster_pwr_dwn b cortex_a32_disable_smp endfunc cortex_a32_cluster_pwr_dwn +#if REPORT_ERRATA +/* + * Errata printing function for Cortex-A32. Must follow AAPCS. + */ +func cortex_a32_errata_report + bx lr +endfunc cortex_a32_errata_report +#endif + declare_cpu_ops cortex_a32, CORTEX_A32_MIDR, \ cortex_a32_reset_func, \ cortex_a32_core_pwr_dwn, \ diff --git a/lib/cpus/aarch32/cortex_a5.S b/lib/cpus/aarch32/cortex_a5.S index c07c13ea1..8abb66f0e 100644 --- a/lib/cpus/aarch32/cortex_a5.S +++ b/lib/cpus/aarch32/cortex_a5.S @@ -69,6 +69,15 @@ func cortex_a5_cluster_pwr_dwn b cortex_a5_disable_smp endfunc cortex_a5_cluster_pwr_dwn +#if REPORT_ERRATA +/* + * Errata printing function for Cortex-A5. Must follow AAPCS. + */ +func cortex_a5_errata_report + bx lr +endfunc cortex_a5_errata_report +#endif + declare_cpu_ops cortex_a5, CORTEX_A5_MIDR, \ cortex_a5_reset_func, \ cortex_a5_core_pwr_dwn, \ diff --git a/lib/cpus/aarch32/cortex_a7.S b/lib/cpus/aarch32/cortex_a7.S index 0278d1fda..4d4bb77bb 100644 --- a/lib/cpus/aarch32/cortex_a7.S +++ b/lib/cpus/aarch32/cortex_a7.S @@ -69,6 +69,15 @@ func cortex_a7_cluster_pwr_dwn b cortex_a7_disable_smp endfunc cortex_a7_cluster_pwr_dwn +#if REPORT_ERRATA +/* + * Errata printing function for Cortex-A7. Must follow AAPCS. + */ +func cortex_a7_errata_report + bx lr +endfunc cortex_a7_errata_report +#endif + declare_cpu_ops cortex_a7, CORTEX_A7_MIDR, \ cortex_a7_reset_func, \ cortex_a7_core_pwr_dwn, \ diff --git a/lib/cpus/aarch64/aem_generic.S b/lib/cpus/aarch64/aem_generic.S index 7592e3dc9..51b5ce91c 100644 --- a/lib/cpus/aarch64/aem_generic.S +++ b/lib/cpus/aarch64/aem_generic.S @@ -46,6 +46,15 @@ func aem_generic_cluster_pwr_dwn b dcsw_op_all endfunc aem_generic_cluster_pwr_dwn +#if REPORT_ERRATA +/* + * Errata printing function for AEM. Must follow AAPCS. + */ +func aem_generic_errata_report + ret +endfunc aem_generic_errata_report +#endif + /* --------------------------------------------- * This function provides cpu specific * register information for crash reporting. diff --git a/lib/cpus/aarch64/cortex_a35.S b/lib/cpus/aarch64/cortex_a35.S index b22189c80..2e0d63161 100644 --- a/lib/cpus/aarch64/cortex_a35.S +++ b/lib/cpus/aarch64/cortex_a35.S @@ -114,6 +114,16 @@ func cortex_a35_cluster_pwr_dwn b cortex_a35_disable_smp endfunc cortex_a35_cluster_pwr_dwn +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A35. Must follow AAPCS. + */ +func cortex_a35_errata_report + ret +endfunc cortex_a35_errata_report +#endif + + /* --------------------------------------------- * This function provides cortex_a35 specific * register information for crash reporting. diff --git a/lib/cpus/aarch64/cortex_a75_pubsub.c b/lib/cpus/aarch64/cortex_a75_pubsub.c index 16f62f472..f4ca48606 100644 --- a/lib/cpus/aarch64/cortex_a75_pubsub.c +++ b/lib/cpus/aarch64/cortex_a75_pubsub.c @@ -12,14 +12,16 @@ static void *cortex_a75_context_save(const void *arg) { if (midr_match(CORTEX_A75_MIDR) != 0) cpuamu_context_save(CORTEX_A75_AMU_NR_COUNTERS); - return 0; + + return (void *)0; } static void *cortex_a75_context_restore(const void *arg) { if (midr_match(CORTEX_A75_MIDR) != 0) cpuamu_context_restore(CORTEX_A75_AMU_NR_COUNTERS); - return 0; + + return (void *)0; } SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, cortex_a75_context_save); diff --git a/lib/cpus/aarch64/cortex_ares_pubsub.c b/lib/cpus/aarch64/cortex_ares_pubsub.c index c7d850a00..9566223f2 100644 --- a/lib/cpus/aarch64/cortex_ares_pubsub.c +++ b/lib/cpus/aarch64/cortex_ares_pubsub.c @@ -12,14 +12,16 @@ static void *cortex_ares_context_save(const void *arg) { if (midr_match(CORTEX_ARES_MIDR) != 0) cpuamu_context_save(CORTEX_ARES_AMU_NR_COUNTERS); - return 0; + + return (void *)0; } static void *cortex_ares_context_restore(const void *arg) { if (midr_match(CORTEX_ARES_MIDR) != 0) cpuamu_context_restore(CORTEX_ARES_AMU_NR_COUNTERS); - return 0; + + return (void *)0; } SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, cortex_ares_context_save); diff --git a/lib/cpus/aarch64/cortex_deimos.S b/lib/cpus/aarch64/cortex_deimos.S index aec62a287..cad906f65 100644 --- a/lib/cpus/aarch64/cortex_deimos.S +++ b/lib/cpus/aarch64/cortex_deimos.S @@ -27,6 +27,16 @@ func cortex_deimos_core_pwr_dwn ret endfunc cortex_deimos_core_pwr_dwn +#if REPORT_ERRATA +/* + * Errata printing function for Cortex Deimos. Must follow AAPCS. + */ +func cortex_deimos_errata_report + ret +endfunc cortex_deimos_errata_report +#endif + + /* --------------------------------------------- * This function provides Cortex-Deimos specific * register information for crash reporting. diff --git a/lib/cpus/aarch64/cortex_helios.S b/lib/cpus/aarch64/cortex_helios.S index bcda74114..4812ac47c 100644 --- a/lib/cpus/aarch64/cortex_helios.S +++ b/lib/cpus/aarch64/cortex_helios.S @@ -19,6 +19,16 @@ func cortex_helios_cpu_pwr_dwn ret endfunc cortex_helios_cpu_pwr_dwn +#if REPORT_ERRATA +/* + * Errata printing function for Cortex Helios. Must follow AAPCS. + */ +func cortex_helios_errata_report + ret +endfunc cortex_helios_errata_report +#endif + + .section .rodata.cortex_helios_regs, "aS" cortex_helios_regs: /* The ascii list of register names to be reported */ .asciz "cpuectlr_el1", "" diff --git a/lib/cpus/aarch64/cpuamu_helpers.S b/lib/cpus/aarch64/cpuamu_helpers.S index 8965d6d09..79b72883b 100644 --- a/lib/cpus/aarch64/cpuamu_helpers.S +++ b/lib/cpus/aarch64/cpuamu_helpers.S @@ -16,7 +16,7 @@ .globl cpuamu_write_cpuamcntenclr_el0 /* - * uint64_t cpuamu_cnt_read(int idx); + * uint64_t cpuamu_cnt_read(unsigned int idx); * * Given `idx`, read the corresponding AMU counter * and return it in `x0`. @@ -41,7 +41,7 @@ func cpuamu_cnt_read endfunc cpuamu_cnt_read /* - * void cpuamu_cnt_write(int idx, uint64_t val); + * void cpuamu_cnt_write(unsigned int idx, uint64_t val); * * Given `idx`, write `val` to the corresponding AMU counter. */ diff --git a/lib/cpus/errata_report.c b/lib/cpus/errata_report.c index c679336c1..42603cb6d 100644 --- a/lib/cpus/errata_report.c +++ b/lib/cpus/errata_report.c @@ -12,6 +12,7 @@ #include <debug.h> #include <errata_report.h> #include <spinlock.h> +#include <stdbool.h> #include <utils.h> #ifdef IMAGE_BL1 @@ -35,10 +36,10 @@ */ int errata_needs_reporting(spinlock_t *lock, uint32_t *reported) { - int report_now; + bool report_now; /* If already reported, return false. */ - if (*reported) + if (*reported != 0U) return 0; /* @@ -46,7 +47,7 @@ int errata_needs_reporting(spinlock_t *lock, uint32_t *reported) * report status to true. */ spin_lock(lock); - report_now = !(*reported); + report_now = (*reported == 0U); if (report_now) *reported = 1; spin_unlock(lock); @@ -75,8 +76,8 @@ void errata_print_msg(unsigned int status, const char *cpu, const char *id) assert(status < ARRAY_SIZE(errata_status_str)); - assert(cpu); - assert(id); + assert(cpu != NULL); + assert(id != NULL); msg = errata_status_str[status]; diff --git a/lib/el3_runtime/aarch32/context_mgmt.c b/lib/el3_runtime/aarch32/context_mgmt.c index 11ef6e5f4..80cea2847 100644 --- a/lib/el3_runtime/aarch32/context_mgmt.c +++ b/lib/el3_runtime/aarch32/context_mgmt.c @@ -14,6 +14,7 @@ #include <platform.h> #include <platform_def.h> #include <smccc_helpers.h> +#include <stdbool.h> #include <string.h> #include <utils.h> @@ -129,7 +130,7 @@ void cm_setup_context(cpu_context_t *ctx, const entry_point_info_t *ep) * When EL2 is implemented but unused `el2_unused` is non-zero, otherwise * it is zero. ******************************************************************************/ -static void enable_extensions_nonsecure(int el2_unused) +static void enable_extensions_nonsecure(bool el2_unused) { #if IMAGE_BL32 #if ENABLE_AMU @@ -175,7 +176,7 @@ void cm_prepare_el3_exit(uint32_t security_state) { uint32_t hsctlr, scr; cpu_context_t *ctx = cm_get_context(security_state); - int el2_unused = 0; + bool el2_unused = false; assert(ctx); @@ -200,7 +201,7 @@ void cm_prepare_el3_exit(uint32_t security_state) isb(); } else if (read_id_pfr1() & (ID_PFR1_VIRTEXT_MASK << ID_PFR1_VIRTEXT_SHIFT)) { - el2_unused = 1; + el2_unused = true; /* * Set the NS bit to access NS copies of certain banked diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c index d3984a289..f037e18a4 100644 --- a/lib/el3_runtime/aarch64/context_mgmt.c +++ b/lib/el3_runtime/aarch64/context_mgmt.c @@ -18,6 +18,7 @@ #include <pubsub_events.h> #include <smccc_helpers.h> #include <spe.h> +#include <stdbool.h> #include <string.h> #include <sve.h> #include <utils.h> @@ -231,7 +232,7 @@ void cm_setup_context(cpu_context_t *ctx, const entry_point_info_t *ep) * When EL2 is implemented but unused `el2_unused` is non-zero, otherwise * it is zero. ******************************************************************************/ -static void enable_extensions_nonsecure(int el2_unused) +static void enable_extensions_nonsecure(bool el2_unused) { #if IMAGE_BL31 #if ENABLE_SPE_FOR_LOWER_ELS @@ -289,7 +290,7 @@ void cm_prepare_el3_exit(uint32_t security_state) { uint32_t sctlr_elx, scr_el3, mdcr_el2; cpu_context_t *ctx = cm_get_context(security_state); - int el2_unused = 0; + bool el2_unused = false; uint64_t hcr_el2 = 0; assert(ctx); @@ -304,7 +305,7 @@ void cm_prepare_el3_exit(uint32_t security_state) sctlr_elx |= SCTLR_EL2_RES1; write_sctlr_el2(sctlr_elx); } else if (EL_IMPLEMENTED(2)) { - el2_unused = 1; + el2_unused = true; /* * EL2 present but unused, need to disable safely. diff --git a/lib/extensions/amu/aarch32/amu.c b/lib/extensions/amu/aarch32/amu.c index 05c98f1cd..585d908f7 100644 --- a/lib/extensions/amu/aarch32/amu.c +++ b/lib/extensions/amu/aarch32/amu.c @@ -10,6 +10,7 @@ #include <arch_helpers.h> #include <platform.h> #include <pubsub_events.h> +#include <stdbool.h> #define AMU_GROUP0_NR_COUNTERS 4 @@ -20,17 +21,17 @@ struct amu_ctx { static struct amu_ctx amu_ctxs[PLATFORM_CORE_COUNT]; -int amu_supported(void) +bool amu_supported(void) { uint64_t features; features = read_id_pfr0() >> ID_PFR0_AMU_SHIFT; - return (features & ID_PFR0_AMU_MASK) == 1; + return (features & ID_PFR0_AMU_MASK) == 1U; } -void amu_enable(int el2_unused) +void amu_enable(bool el2_unused) { - if (amu_supported() == 0) + if (!amu_supported()) return; if (el2_unused) { @@ -54,8 +55,8 @@ void amu_enable(int el2_unused) /* Read the group 0 counter identified by the given `idx`. */ uint64_t amu_group0_cnt_read(int idx) { - assert(amu_supported() != 0); - assert(idx >= 0 && idx < AMU_GROUP0_NR_COUNTERS); + assert(amu_supported()); + assert((idx >= 0) && (idx < AMU_GROUP0_NR_COUNTERS)); return amu_group0_cnt_read_internal(idx); } @@ -63,8 +64,8 @@ uint64_t amu_group0_cnt_read(int idx) /* Write the group 0 counter identified by the given `idx` with `val`. */ void amu_group0_cnt_write(int idx, uint64_t val) { - assert(amu_supported() != 0); - assert(idx >= 0 && idx < AMU_GROUP0_NR_COUNTERS); + assert(amu_supported()); + assert((idx >= 0) && (idx < AMU_GROUP0_NR_COUNTERS)); amu_group0_cnt_write_internal(idx, val); isb(); @@ -73,8 +74,8 @@ void amu_group0_cnt_write(int idx, uint64_t val) /* Read the group 1 counter identified by the given `idx`. */ uint64_t amu_group1_cnt_read(int idx) { - assert(amu_supported() != 0); - assert(idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS); + assert(amu_supported()); + assert((idx >= 0) && (idx < AMU_GROUP1_NR_COUNTERS)); return amu_group1_cnt_read_internal(idx); } @@ -82,8 +83,8 @@ uint64_t amu_group1_cnt_read(int idx) /* Write the group 1 counter identified by the given `idx` with `val`. */ void amu_group1_cnt_write(int idx, uint64_t val) { - assert(amu_supported() != 0); - assert(idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS); + assert(amu_supported()); + assert((idx >= 0) && (idx < AMU_GROUP1_NR_COUNTERS)); amu_group1_cnt_write_internal(idx, val); isb(); @@ -91,8 +92,8 @@ void amu_group1_cnt_write(int idx, uint64_t val) void amu_group1_set_evtype(int idx, unsigned int val) { - assert(amu_supported() != 0); - assert(idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS); + assert(amu_supported()); + assert((idx >= 0) && (idx < AMU_GROUP1_NR_COUNTERS)); amu_group1_set_evtype_internal(idx, val); isb(); @@ -103,7 +104,7 @@ static void *amu_context_save(const void *arg) struct amu_ctx *ctx; int i; - if (amu_supported() == 0) + if (!amu_supported()) return (void *)-1; ctx = &amu_ctxs[plat_my_core_pos()]; @@ -126,7 +127,7 @@ static void *amu_context_save(const void *arg) for (i = 0; i < AMU_GROUP1_NR_COUNTERS; i++) ctx->group1_cnts[i] = amu_group1_cnt_read(i); - return 0; + return (void *)0; } static void *amu_context_restore(const void *arg) @@ -134,13 +135,13 @@ static void *amu_context_restore(const void *arg) struct amu_ctx *ctx; int i; - if (amu_supported() == 0) + if (!amu_supported()) return (void *)-1; ctx = &amu_ctxs[plat_my_core_pos()]; /* Counters were disabled in `amu_context_save()` */ - assert(read_amcntenset0() == 0 && read_amcntenset1() == 0); + assert((read_amcntenset0() == 0U) && (read_amcntenset1() == 0U)); /* Restore group 0 counters */ for (i = 0; i < AMU_GROUP0_NR_COUNTERS; i++) @@ -153,7 +154,7 @@ static void *amu_context_restore(const void *arg) /* Enable group 1 counters */ write_amcntenset1(AMU_GROUP1_COUNTERS_MASK); - return 0; + return (void *)0; } SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, amu_context_save); diff --git a/lib/extensions/amu/aarch64/amu.c b/lib/extensions/amu/aarch64/amu.c index 5d556e5d3..1564e8402 100644 --- a/lib/extensions/amu/aarch64/amu.c +++ b/lib/extensions/amu/aarch64/amu.c @@ -11,6 +11,7 @@ #include <assert.h> #include <platform.h> #include <pubsub_events.h> +#include <stdbool.h> #define AMU_GROUP0_NR_COUNTERS 4 @@ -21,23 +22,23 @@ struct amu_ctx { static struct amu_ctx amu_ctxs[PLATFORM_CORE_COUNT]; -int amu_supported(void) +bool amu_supported(void) { uint64_t features; features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_AMU_SHIFT; - return (features & ID_AA64PFR0_AMU_MASK) == 1; + return (features & ID_AA64PFR0_AMU_MASK) == 1U; } /* * Enable counters. This function is meant to be invoked * by the context management library before exiting from EL3. */ -void amu_enable(int el2_unused) +void amu_enable(bool el2_unused) { uint64_t v; - if (amu_supported() == 0) + if (!amu_supported()) return; if (el2_unused) { @@ -67,8 +68,8 @@ void amu_enable(int el2_unused) /* Read the group 0 counter identified by the given `idx`. */ uint64_t amu_group0_cnt_read(int idx) { - assert(amu_supported() != 0); - assert(idx >= 0 && idx < AMU_GROUP0_NR_COUNTERS); + assert(amu_supported()); + assert((idx >= 0) && (idx < AMU_GROUP0_NR_COUNTERS)); return amu_group0_cnt_read_internal(idx); } @@ -76,8 +77,8 @@ uint64_t amu_group0_cnt_read(int idx) /* Write the group 0 counter identified by the given `idx` with `val`. */ void amu_group0_cnt_write(int idx, uint64_t val) { - assert(amu_supported() != 0); - assert(idx >= 0 && idx < AMU_GROUP0_NR_COUNTERS); + assert(amu_supported()); + assert((idx >= 0) && (idx < AMU_GROUP0_NR_COUNTERS)); amu_group0_cnt_write_internal(idx, val); isb(); @@ -86,8 +87,8 @@ void amu_group0_cnt_write(int idx, uint64_t val) /* Read the group 1 counter identified by the given `idx`. */ uint64_t amu_group1_cnt_read(int idx) { - assert(amu_supported() != 0); - assert(idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS); + assert(amu_supported()); + assert((idx >= 0) && (idx < AMU_GROUP1_NR_COUNTERS)); return amu_group1_cnt_read_internal(idx); } @@ -95,8 +96,8 @@ uint64_t amu_group1_cnt_read(int idx) /* Write the group 1 counter identified by the given `idx` with `val`. */ void amu_group1_cnt_write(int idx, uint64_t val) { - assert(amu_supported() != 0); - assert(idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS); + assert(amu_supported()); + assert((idx >= 0) && (idx < AMU_GROUP1_NR_COUNTERS)); amu_group1_cnt_write_internal(idx, val); isb(); @@ -108,8 +109,8 @@ void amu_group1_cnt_write(int idx, uint64_t val) */ void amu_group1_set_evtype(int idx, unsigned int val) { - assert(amu_supported() != 0); - assert (idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS); + assert(amu_supported()); + assert((idx >= 0) && (idx < AMU_GROUP1_NR_COUNTERS)); amu_group1_set_evtype_internal(idx, val); isb(); @@ -120,14 +121,14 @@ static void *amu_context_save(const void *arg) struct amu_ctx *ctx = &amu_ctxs[plat_my_core_pos()]; int i; - if (amu_supported() == 0) + if (!amu_supported()) return (void *)-1; /* Assert that group 0/1 counter configuration is what we expect */ - assert(read_amcntenset0_el0() == AMU_GROUP0_COUNTERS_MASK && - read_amcntenset1_el0() == AMU_GROUP1_COUNTERS_MASK); + assert((read_amcntenset0_el0() == AMU_GROUP0_COUNTERS_MASK) && + (read_amcntenset1_el0() == AMU_GROUP1_COUNTERS_MASK)); - assert((sizeof(int) * 8) - __builtin_clz(AMU_GROUP1_COUNTERS_MASK) + assert(((sizeof(int) * 8) - __builtin_clz(AMU_GROUP1_COUNTERS_MASK)) <= AMU_GROUP1_NR_COUNTERS); /* @@ -146,7 +147,7 @@ static void *amu_context_save(const void *arg) for (i = 0; i < AMU_GROUP1_NR_COUNTERS; i++) ctx->group1_cnts[i] = amu_group1_cnt_read(i); - return 0; + return (void *)0; } static void *amu_context_restore(const void *arg) @@ -154,30 +155,30 @@ static void *amu_context_restore(const void *arg) struct amu_ctx *ctx = &amu_ctxs[plat_my_core_pos()]; int i; - if (amu_supported() == 0) + if (!amu_supported()) return (void *)-1; /* Counters were disabled in `amu_context_save()` */ - assert(read_amcntenset0_el0() == 0 && read_amcntenset1_el0() == 0); + assert((read_amcntenset0_el0() == 0U) && (read_amcntenset1_el0() == 0U)); - assert((sizeof(int) * 8) - __builtin_clz(AMU_GROUP1_COUNTERS_MASK) + assert(((sizeof(int) * 8U) - __builtin_clz(AMU_GROUP1_COUNTERS_MASK)) <= AMU_GROUP1_NR_COUNTERS); /* Restore group 0 counters */ for (i = 0; i < AMU_GROUP0_NR_COUNTERS; i++) - if (AMU_GROUP0_COUNTERS_MASK & (1U << i)) + if ((AMU_GROUP0_COUNTERS_MASK & (1U << i)) != 0U) amu_group0_cnt_write(i, ctx->group0_cnts[i]); /* Restore group 1 counters */ for (i = 0; i < AMU_GROUP1_NR_COUNTERS; i++) - if (AMU_GROUP1_COUNTERS_MASK & (1U << i)) + if ((AMU_GROUP1_COUNTERS_MASK & (1U << i)) != 0U) amu_group1_cnt_write(i, ctx->group1_cnts[i]); /* Restore group 0/1 counter configuration */ write_amcntenset0_el0(AMU_GROUP0_COUNTERS_MASK); write_amcntenset1_el0(AMU_GROUP1_COUNTERS_MASK); - return 0; + return (void *)0; } SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, amu_context_save); diff --git a/lib/extensions/mpam/mpam.c b/lib/extensions/mpam/mpam.c index e628827bf..d57bb470b 100644 --- a/lib/extensions/mpam/mpam.c +++ b/lib/extensions/mpam/mpam.c @@ -16,7 +16,7 @@ bool mpam_supported(void) return ((features & ID_AA64PFR0_MPAM_MASK) != 0U); } -void mpam_enable(int el2_unused) +void mpam_enable(bool el2_unused) { if (!mpam_supported()) return; @@ -31,7 +31,7 @@ void mpam_enable(int el2_unused) * If EL2 is implemented but unused, disable trapping to EL2 when lower * ELs access their own MPAM registers. */ - if (el2_unused != 0) { + if (el2_unused) { write_mpam2_el2(0); if ((read_mpamidr_el1() & MPAMIDR_HAS_HCR_BIT) != 0U) diff --git a/lib/extensions/spe/spe.c b/lib/extensions/spe/spe.c index dc3584037..e5df015b0 100644 --- a/lib/extensions/spe/spe.c +++ b/lib/extensions/spe/spe.c @@ -8,26 +8,30 @@ #include <arch_helpers.h> #include <pubsub.h> #include <spe.h> +#include <stdbool.h> -/* - * The assembler does not yet understand the psb csync mnemonic - * so use the equivalent hint instruction. - */ -#define psb_csync() asm volatile("hint #17") +static inline void psb_csync(void) +{ + /* + * The assembler does not yet understand the psb csync mnemonic + * so use the equivalent hint instruction. + */ + __asm__ volatile("hint #17"); +} -int spe_supported(void) +bool spe_supported(void) { uint64_t features; features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_PMS_SHIFT; - return (features & ID_AA64DFR0_PMS_MASK) == 1; + return (features & ID_AA64DFR0_PMS_MASK) == 1U; } -void spe_enable(int el2_unused) +void spe_enable(bool el2_unused) { uint64_t v; - if (spe_supported() == 0) + if (!spe_supported()) return; if (el2_unused) { @@ -59,7 +63,7 @@ void spe_disable(void) { uint64_t v; - if (spe_supported() == 0) + if (!spe_supported()) return; /* Drain buffered data */ @@ -75,13 +79,14 @@ void spe_disable(void) static void *spe_drain_buffers_hook(const void *arg) { - if (spe_supported() == 0) + if (!spe_supported()) return (void *)-1; /* Drain buffered data */ psb_csync(); dsbnsh(); - return 0; + + return (void *)0; } SUBSCRIBE_TO_EVENT(cm_entering_secure_world, spe_drain_buffers_hook); diff --git a/lib/extensions/sve/sve.c b/lib/extensions/sve/sve.c index 644248780..e031bf61b 100644 --- a/lib/extensions/sve/sve.c +++ b/lib/extensions/sve/sve.c @@ -7,21 +7,22 @@ #include <arch.h> #include <arch_helpers.h> #include <pubsub.h> +#include <stdbool.h> #include <sve.h> -int sve_supported(void) +bool sve_supported(void) { uint64_t features; features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT; - return (features & ID_AA64PFR0_SVE_MASK) == 1; + return (features & ID_AA64PFR0_SVE_MASK) == 1U; } static void *disable_sve_hook(const void *arg) { uint64_t cptr; - if (sve_supported() == 0) + if (!sve_supported()) return (void *)-1; /* @@ -39,14 +40,14 @@ static void *disable_sve_hook(const void *arg) * No explicit ISB required here as ERET to switch to Secure * world covers it */ - return 0; + return (void *)0; } static void *enable_sve_hook(const void *arg) { uint64_t cptr; - if (sve_supported() == 0) + if (!sve_supported()) return (void *)-1; /* @@ -60,14 +61,14 @@ static void *enable_sve_hook(const void *arg) * No explicit ISB required here as ERET to switch to Non-secure * world covers it */ - return 0; + return (void *)0; } -void sve_enable(int el2_unused) +void sve_enable(bool el2_unused) { uint64_t cptr; - if (sve_supported() == 0) + if (!sve_supported()) return; #if CTX_INCLUDE_FPREGS diff --git a/lib/pmf/pmf_main.c b/lib/pmf/pmf_main.c index a02086008..fe7bb7423 100644 --- a/lib/pmf/pmf_main.c +++ b/lib/pmf/pmf_main.c @@ -25,9 +25,10 @@ IMPORT_SYM(uintptr_t, __PMF_SVC_DESCS_START__, PMF_SVC_DESCS_START); IMPORT_SYM(uintptr_t, __PMF_SVC_DESCS_END__, PMF_SVC_DESCS_END); -IMPORT_SYM(uintptr_t, __PERCPU_TIMESTAMP_SIZE__, PMF_PERCPU_TIMESTAMP_SIZE); -IMPORT_SYM(intptr_t, __PMF_TIMESTAMP_START__, PMF_TIMESTAMP_ARRAY_START); -IMPORT_SYM(uintptr_t, __PMF_TIMESTAMP_END__, PMF_TIMESTAMP_ARRAY_END); +IMPORT_SYM(uintptr_t, __PMF_PERCPU_TIMESTAMP_END__, PMF_PERCPU_TIMESTAMP_END); +IMPORT_SYM(uintptr_t, __PMF_TIMESTAMP_START__, PMF_TIMESTAMP_ARRAY_START); + +#define PMF_PERCPU_TIMESTAMP_SIZE (PMF_PERCPU_TIMESTAMP_END - PMF_TIMESTAMP_ARRAY_START) #define PMF_SVC_DESCS_MAX 10 @@ -66,15 +67,15 @@ int pmf_setup(void) pmf_svc_descs = (pmf_svc_desc_t *) PMF_SVC_DESCS_START; for (ii = 0; ii < pmf_svc_descs_num; ii++) { - assert(pmf_svc_descs[ii].get_ts); + assert(pmf_svc_descs[ii].get_ts != NULL); /* * Call the initialization routine for this * PMF service, if it is defined. */ - if (pmf_svc_descs[ii].init) { + if (pmf_svc_descs[ii].init != NULL) { rc = pmf_svc_descs[ii].init(); - if (rc) { + if (rc != 0) { WARN("Could not initialize PMF" "service %s - skipping \n", pmf_svc_descs[ii].name); @@ -124,7 +125,7 @@ static pmf_svc_desc_t *get_service(unsigned int tid) if (pmf_num_services == 0) return NULL; - assert(pmf_svc_descs); + assert(pmf_svc_descs != NULL); do { mid = (low + high) / 2; @@ -157,7 +158,7 @@ int pmf_get_timestamp_smc(unsigned int tid, unsigned long long *ts_value) { pmf_svc_desc_t *svc_desc; - assert(ts_value); + assert(ts_value != NULL); /* Search for registered service. */ svc_desc = get_service(tid); @@ -246,7 +247,7 @@ unsigned long long __pmf_get_timestamp(uintptr_t base_addr, unsigned long long *ts_addr = (unsigned long long *)calc_ts_addr(base_addr, tid, cpuid); - if (flags & PMF_CACHE_MAINT) + if ((flags & PMF_CACHE_MAINT) != 0U) inv_dcache_range((uintptr_t)ts_addr, sizeof(unsigned long long)); return *ts_addr; diff --git a/lib/pmf/pmf_smc.c b/lib/pmf/pmf_smc.c index e86611802..4c5b14f93 100644 --- a/lib/pmf/pmf_smc.c +++ b/lib/pmf/pmf_smc.c @@ -37,7 +37,8 @@ uintptr_t pmf_smc_handler(unsigned int smc_fid, * x0 --> error code. * x1 - x2 --> time-stamp value. */ - rc = pmf_get_timestamp_smc(x1, x2, x3, &ts_value); + rc = pmf_get_timestamp_smc((unsigned int)x1, x2, + (unsigned int)x3, &ts_value); SMC_RET3(handle, rc, (uint32_t)ts_value, (uint32_t)(ts_value >> 32)); } @@ -49,7 +50,8 @@ uintptr_t pmf_smc_handler(unsigned int smc_fid, * x0 --> error code. * x1 --> time-stamp value. */ - rc = pmf_get_timestamp_smc(x1, x2, x3, &ts_value); + rc = pmf_get_timestamp_smc((unsigned int)x1, x2, + (unsigned int)x3, &ts_value); SMC_RET2(handle, rc, ts_value); } } diff --git a/lib/romlib/init.s b/lib/romlib/init.s index 5cf2aca04..7d97e4d1d 100644 --- a/lib/romlib/init.s +++ b/lib/romlib/init.s @@ -5,7 +5,7 @@ */ .globl rom_lib_init - .extern __DATA_RAM_START__, __DATA_ROM_START__, __DATA_SIZE__ + .extern __DATA_RAM_START__, __DATA_ROM_START__, __DATA_RAM_END__ .extern memset, memcpy rom_lib_init: @@ -16,13 +16,19 @@ rom_lib_init: 1: stp x29, x30, [sp, #-16]! adrp x0, __DATA_RAM_START__ - ldr x1,= __DATA_ROM_START__ - ldr x2, =__DATA_SIZE__ + adrp x1, __DATA_ROM_START__ + add x1, x1, :lo12:__DATA_ROM_START__ + adrp x2, __DATA_RAM_END__ + add x2, x2, :lo12:__DATA_RAM_END__ + sub x2, x2, x0 bl memcpy - ldr x0, =__BSS_START__ + adrp x0,__BSS_START__ + add x0, x0, :lo12:__BSS_START__ mov x1, #0 - ldr x2, =__BSS_SIZE__ + adrp x2, __BSS_END__ + add x2, x2, :lo12:__BSS_END__ + sub x2, x2, x0 bl memset ldp x29, x30, [sp], #16 diff --git a/lib/xlat_tables_v2/aarch64/enable_mmu.S b/lib/xlat_tables_v2/aarch64/enable_mmu.S index 21717d28a..504c03c15 100644 --- a/lib/xlat_tables_v2/aarch64/enable_mmu.S +++ b/lib/xlat_tables_v2/aarch64/enable_mmu.S @@ -45,7 +45,8 @@ tlbi_invalidate_all \el mov x7, x0 - ldr x0, =mmu_cfg_params + adrp x0, mmu_cfg_params + add x0, x0, :lo12:mmu_cfg_params /* MAIR */ ldr x1, [x0, #(MMU_CFG_MAIR << 3)] diff --git a/lib/xlat_tables_v2/xlat_tables.mk b/lib/xlat_tables_v2/xlat_tables.mk index 9507ad715..c946315bf 100644 --- a/lib/xlat_tables_v2/xlat_tables.mk +++ b/lib/xlat_tables_v2/xlat_tables.mk @@ -10,3 +10,6 @@ XLAT_TABLES_LIB_SRCS := $(addprefix lib/xlat_tables_v2/, \ xlat_tables_context.c \ xlat_tables_core.c \ xlat_tables_utils.c) + +XLAT_TABLES_LIB_V2 := 1 +$(eval $(call add_define,XLAT_TABLES_LIB_V2)) diff --git a/maintainers.rst b/maintainers.rst index 5fb44943b..6d649c3c7 100644 --- a/maintainers.rst +++ b/maintainers.rst @@ -26,6 +26,14 @@ Allwinner ARMv8 platform port :F: plat/allwinner/ :F: drivers/allwinner/ +Amlogic Meson S905 (GXBB) platform port +--------------------------------------- +:M: Antonio Niño DÃaz <antonio.ninodiaz@arm.com> +:G: `antonio-nino-diaz-arm`_ +:F: docs/plat/meson-gxbb.rst +:F: drivers/meson/ +:F: plat/meson/gxbb/ + Armv7-A architecture port ------------------------- :M: Etienne Carriere <etienne.carriere@linaro.org> diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk index 435de20e3..4a3f54116 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -64,6 +64,9 @@ DYN_DISABLE_AUTH := 0 # Build option to enable MPAM for lower ELs ENABLE_MPAM_FOR_LOWER_ELS := 0 +# Flag to Enable Position Independant support (PIE) +ENABLE_PIE := 0 + # Flag to enable Performance Measurement Framework ENABLE_PMF := 0 diff --git a/plat/allwinner/common/allwinner-common.mk b/plat/allwinner/common/allwinner-common.mk new file mode 100644 index 000000000..2dc058f54 --- /dev/null +++ b/plat/allwinner/common/allwinner-common.mk @@ -0,0 +1,59 @@ +# +# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include lib/xlat_tables_v2/xlat_tables.mk + +AW_PLAT := plat/allwinner + +PLAT_INCLUDES := -Iinclude/plat/arm/common \ + -Iinclude/plat/arm/common/aarch64 \ + -I${AW_PLAT}/common/include \ + -I${AW_PLAT}/${PLAT}/include + +include lib/libfdt/libfdt.mk + +PLAT_BL_COMMON_SOURCES := drivers/console/${ARCH}/console.S \ + drivers/ti/uart/${ARCH}/16550_console.S \ + ${XLAT_TABLES_LIB_SRCS} \ + ${AW_PLAT}/common/plat_helpers.S \ + ${AW_PLAT}/common/sunxi_common.c + +BL31_SOURCES += drivers/arm/gic/common/gic_common.c \ + drivers/arm/gic/v2/gicv2_helpers.c \ + drivers/arm/gic/v2/gicv2_main.c \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + lib/cpus/${ARCH}/cortex_a53.S \ + plat/common/plat_gicv2.c \ + plat/common/plat_psci_common.c \ + ${AW_PLAT}/common/sunxi_bl31_setup.c \ + ${AW_PLAT}/common/sunxi_cpu_ops.c \ + ${AW_PLAT}/common/sunxi_pm.c \ + ${AW_PLAT}/${PLAT}/sunxi_power.c \ + ${AW_PLAT}/common/sunxi_security.c \ + ${AW_PLAT}/common/sunxi_topology.c + +# The bootloader is guaranteed to only run on CPU 0 by the boot ROM. +COLD_BOOT_SINGLE_CPU := 1 + +# Enable workarounds for Cortex-A53 errata. Allwinner uses at least r0p4. +ERRATA_A53_835769 := 1 +ERRATA_A53_843419 := 1 +ERRATA_A53_855873 := 1 + +MULTI_CONSOLE_API := 1 + +# The reset vector can be changed for each CPU. +PROGRAMMABLE_RESET_ADDRESS := 1 + +# Allow mapping read-only data as execute-never. +SEPARATE_CODE_AND_RODATA := 1 + +# BL31 gets loaded alongside BL33 (U-Boot) by U-Boot's SPL +RESET_TO_BL31 := 1 + +# We are short on memory, so save 3.5KB by not having an extra coherent page. +USE_COHERENT_MEM := 0 diff --git a/plat/allwinner/common/arisc_off.S b/plat/allwinner/common/arisc_off.S new file mode 100644 index 000000000..ed10832c9 --- /dev/null +++ b/plat/allwinner/common/arisc_off.S @@ -0,0 +1,115 @@ +# turn_off_core.S +# +# Copyright (c) 2018, Andre Przywara <osp@andrep.de> +# SPDX-License-Identifier: BSD-3-Clause +# +# OpenRISC assembly to turn off an ARM core on an Allwinner SoC from +# the arisc management controller. +# Generate a binary representation with: +# $ or1k-elf-as -c -o turn_off_core.o turn_off_core.S +# $ or1k-elf-objcopy -O binary --reverse-bytes=4 turn_off_core.o \ +# turn_off_core.bin +# The encoded instructions go into an array defined in +# plat/allwinner/sun50i_*/include/core_off_arisc.h, to be handed off to +# the arisc processor. +# +# This routine is meant to be called directly from arisc reset (put the +# start address in the reset vector), to be actually triggered by that +# very ARM core to be turned off. +# It expects the core number presented as a mask in the upper half of +# r3, so to be patched in the lower 16 bits of the first instruction, +# overwriting the 0 in this code here. +# The code will do the following: +# - Read the C_CPU_STATUS register, which contains the status of the WFI +# lines of each of the four A53 cores. +# - Loop until the core in question reaches WFI. +# - Using that mask, activate the core output clamps by setting the +# respective core bit in CPUX_PWROFF_GATING_REG (0x1f01500). +# Note that the clamp for core 0 covers more than just the core, activating +# it hangs the whole system. So we skip this step for core 0. +# - Using the negated mask, assert the core's reset line by clearing the +# respective bit in C_RST_CTRL (0x1f01c30). +# - Finally turn off the core's power switch by writing 0xff to the +# respective CPUx_PWR_SWITCH_REG (0x1f01540 ff.) +# - Assert the arisc's own reset to end execution. +# This also signals other arisc users that the chip is free again. +# So in C this would look like: +# while (!(readl(0x1700030) & (1U << core_nr))) +# ; +# if (core_nr != 0) +# writel(readl(0x1f01500) | (1U << core_nr), 0x1f01500); +# writel(readl(0x1f01c30) & ~(1U << core_nr), 0x1f01c30); +# writel(0xff, 0x1f01540 + (core_nr * 4)); +# (using A64/H5 addresses) + +.text +_start: + l.movhi r3, 0 # FIXUP! with core mask + l.movhi r0, 0 # clear r0 + l.movhi r13, 0x170 # r13: CPU_CFG_BASE=0x01700000 +wait_wfi: + l.lwz r5, 0x30(r13) # load C_CPU_STATUS + l.and r5, r5, r3 # mask requested core + l.sfeq r5, r0 # is it not yet in WFI? + l.bf wait_wfi # try again + + l.srli r6, r3, 16 # move mask to lower 16 bits + l.sfeqi r6, 1 # core 0 is special + l.bf 1f # don't touch the bit for core 0 + l.movhi r13, 0x1f0 # address of R_CPUCFG (delay) + l.lwz r5, 0x1500(r13) # core output clamps + l.or r5, r5, r6 # set bit to ... + l.sw 0x1500(r13), r5 # ... activate for our core + +1: l.lwz r5, 0x1c30(r13) # CPU power-on reset + l.xori r6, r6, -1 # negate core mask + l.and r5, r5, r6 # clear bit to ... + l.sw 0x1c30(r13), r5 # ... assert for our core + + l.ff1 r6, r3 # get core number from high mask + l.addi r6, r6, -17 # convert to 0-3 + l.slli r6, r6, 2 # r5: core number*4 (0-12) + l.add r6, r6, r13 # add to base address + l.ori r5, r0, 0xff # 0xff means all switches off + l.sw 0x1540(r6), r5 # core power switch registers + +reset: l.sw 0x1c00(r13),r0 # pull down our own reset line + + l.j reset # just in case .... + l.nop 0x0 # (delay slot) + +# same as above, but with the MMIO addresses matching the H6 SoC +_start_h6: + l.movhi r3, 0 # FIXUP! with core mask + l.movhi r0, 0 # clear r0 + l.movhi r13, 0x901 # r13: CPU_CFG_BASE=0x09010000 +1: + l.lwz r5, 0x80(r13) # load C_CPU_STATUS + l.and r5, r5, r3 # mask requested core + l.sfeq r5, r0 # is it not yet in WFI? + l.bf 1b # try again + + l.srli r6, r3, 16 # move mask to lower 16 bits(ds) + l.sfeqi r6, 1 # core 0 is special + l.bf 1f # don't touch the bit for core 0 + l.movhi r13, 0x700 # address of R_CPUCFG (ds) + l.lwz r5, 0x0444(r13) # core output clamps + l.or r5, r5, r6 # set bit to ... + l.sw 0x0444(r13), r5 # ... activate for our core + +1: l.lwz r5, 0x0440(r13) # CPU power-on reset + l.xori r6, r6, -1 # negate core mask + l.and r5, r5, r6 # clear bit to ... + l.sw 0x0440(r13), r5 # ... assert for our core + + l.ff1 r6, r3 # get core number from high mask + l.addi r6, r6, -17 # convert to 0-3 + l.slli r6, r6, 2 # r5: core number*4 (0-12) + l.add r6, r6, r13 # add to base address + l.ori r5, r0, 0xff # 0xff means all switches off + l.sw 0x0450(r6), r5 # core power switch registers + +1: l.sw 0x0400(r13),r0 # pull down our own reset line + + l.j 1b # just in case ... + l.nop 0x0 # (delay slot) diff --git a/plat/allwinner/common/include/platform_def.h b/plat/allwinner/common/include/platform_def.h index b46d41016..08eb5cf2b 100644 --- a/plat/allwinner/common/include/platform_def.h +++ b/plat/allwinner/common/include/platform_def.h @@ -18,11 +18,17 @@ /* The traditional U-Boot load address is 160MB into DRAM, so at 0x4a000000 */ #define PLAT_SUNXI_NS_IMAGE_OFFSET (SUNXI_DRAM_BASE + (160U << 20)) +/* How much memory to reserve as secure for BL32, if configured */ +#define SUNXI_DRAM_SEC_SIZE (32U << 20) + +/* How much DRAM to map (to map BL33, for fetching the DTB from U-Boot) */ +#define SUNXI_DRAM_MAP_SIZE (64U << 20) + #define CACHE_WRITEBACK_SHIFT 6 #define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) -#define MAX_MMAP_REGIONS (4 + PLATFORM_MMAP_REGIONS) -#define MAX_XLAT_TABLES 2 +#define MAX_MMAP_REGIONS (3 + PLATFORM_MMAP_REGIONS) +#define MAX_XLAT_TABLES 1 #define PLAT_MAX_PWR_LVL_STATES U(2) #define PLAT_MAX_RET_STATE U(1) @@ -34,13 +40,13 @@ PLATFORM_CORE_COUNT) #define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) -#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 28) #define PLATFORM_CLUSTER_COUNT 1 #define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \ PLATFORM_MAX_CPUS_PER_CLUSTER) #define PLATFORM_MAX_CPUS_PER_CLUSTER 4 -#define PLATFORM_MMAP_REGIONS 3 +#define PLATFORM_MMAP_REGIONS 4 #define PLATFORM_STACK_SIZE (0x1000 / PLATFORM_CORE_COUNT) #ifndef SPD_none diff --git a/plat/allwinner/common/include/sunxi_def.h b/plat/allwinner/common/include/sunxi_def.h index e68fbe463..da87b2389 100644 --- a/plat/allwinner/common/include/sunxi_def.h +++ b/plat/allwinner/common/include/sunxi_def.h @@ -14,4 +14,8 @@ #define SUNXI_UART0_BAUDRATE 115200 #define SUNXI_UART0_CLK_IN_HZ SUNXI_OSC24M_CLK_IN_HZ +#define SUNXI_SOC_A64 0x1689 +#define SUNXI_SOC_H5 0x1718 +#define SUNXI_SOC_H6 0x1728 + #endif /* __SUNXI_DEF_H__ */ diff --git a/plat/allwinner/common/sunxi_private.h b/plat/allwinner/common/include/sunxi_private.h index 20fa23e62..1e1b0a4d1 100644 --- a/plat/allwinner/common/sunxi_private.h +++ b/plat/allwinner/common/include/sunxi_private.h @@ -4,19 +4,23 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef __SUNXI_PRIVATE_H__ -#define __SUNXI_PRIVATE_H__ +#ifndef SUNXI_PRIVATE_H +#define SUNXI_PRIVATE_H void sunxi_configure_mmu_el3(int flags); -void sunxi_cpu_off(unsigned int cluster, unsigned int core); + void sunxi_cpu_on(unsigned int cluster, unsigned int core); +void sunxi_cpu_off(unsigned int cluster, unsigned int core); void sunxi_disable_secondary_cpus(unsigned int primary_cpu); +void __dead2 sunxi_power_down(void); -uint16_t sunxi_read_soc_id(void); - -void sunxi_pmic_setup(void); +int sunxi_pmic_setup(uint16_t socid, const void *fdt); void sunxi_security_setup(void); -void __dead2 sunxi_power_down(void); +uint16_t sunxi_read_soc_id(void); +void sunxi_set_gpio_out(char port, int pin, bool level_high); +int sunxi_init_platform_r_twi(uint16_t socid, bool use_rsb); +void sunxi_execute_arisc_code(uint32_t *code, size_t size, + int patch_offset, uint16_t param); -#endif /* __SUNXI_PRIVATE_H__ */ +#endif /* SUNXI_PRIVATE_H */ diff --git a/plat/allwinner/common/sunxi_bl31_setup.c b/plat/allwinner/common/sunxi_bl31_setup.c index 7e11cecf5..8f597c39e 100644 --- a/plat/allwinner/common/sunxi_bl31_setup.c +++ b/plat/allwinner/common/sunxi_bl31_setup.c @@ -10,13 +10,14 @@ #include <debug.h> #include <generic_delay_timer.h> #include <gicv2.h> +#include <libfdt.h> #include <platform.h> #include <platform_def.h> #include <sunxi_def.h> #include <sunxi_mmap.h> +#include <sunxi_private.h> #include <uart_16550.h> -#include "sunxi_private.h" static entry_point_info_t bl32_image_ep_info; static entry_point_info_t bl33_image_ep_info; @@ -28,6 +29,47 @@ static const gicv2_driver_data_t sunxi_gic_data = { .gicc_base = SUNXI_GICC_BASE, }; +/* + * Try to find a DTB loaded in memory by previous stages. + * + * At the moment we implement a heuristic to find the DTB attached to U-Boot: + * U-Boot appends its DTB to the end of the image. Assuming that BL33 is + * U-Boot, try to find the size of the U-Boot image to learn the DTB address. + * The generic ARMv8 U-Boot image contains the load address and its size + * as u64 variables at the beginning of the image. There might be padding + * or other headers before that data, so scan the first 2KB after the BL33 + * entry point to find the load address, which should be followed by the + * size. Adding those together gives us the address of the DTB. + */ +static void *sunxi_find_dtb(void) +{ + uint64_t *u_boot_base; + int i; + + u_boot_base = (void *)(SUNXI_DRAM_VIRT_BASE + SUNXI_DRAM_SEC_SIZE); + + for (i = 0; i < 2048 / sizeof(uint64_t); i++) { + uint32_t *dtb_base; + + if (u_boot_base[i] != PLAT_SUNXI_NS_IMAGE_OFFSET) + continue; + + /* Does the suspected U-Boot size look anyhow reasonable? */ + if (u_boot_base[i + 1] >= 256 * 1024 * 1024) + continue; + + /* end of the image: base address + size */ + dtb_base = (void *)((char *)u_boot_base + u_boot_base[i + 1]); + + if (fdt_check_header(dtb_base) != 0) + continue; + + return dtb_base; + } + + return NULL; +} + void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3) { @@ -66,15 +108,16 @@ void bl31_platform_setup(void) { const char *soc_name; uint16_t soc_id = sunxi_read_soc_id(); + void *fdt; switch (soc_id) { - case 0x1689: + case SUNXI_SOC_A64: soc_name = "A64/H64/R18"; break; - case 0x1718: + case SUNXI_SOC_H5: soc_name = "H5"; break; - case 0x1728: + case SUNXI_SOC_H6: soc_name = "H6"; break; default: @@ -85,6 +128,18 @@ void bl31_platform_setup(void) generic_delay_timer_init(); + fdt = sunxi_find_dtb(); + if (fdt) { + const char *model; + int length; + + model = fdt_getprop(fdt, 0, "model", &length); + NOTICE("BL31: Found U-Boot DTB at %p, model: %s\n", fdt, + model ?: "unknown"); + } else { + NOTICE("BL31: No DTB found.\n"); + } + /* Configure the interrupt controller */ gicv2_driver_init(&sunxi_gic_data); gicv2_distif_init(); @@ -93,7 +148,7 @@ void bl31_platform_setup(void) sunxi_security_setup(); - sunxi_pmic_setup(); + sunxi_pmic_setup(soc_id, fdt); INFO("BL31: Platform setup done\n"); } diff --git a/plat/allwinner/common/sunxi_common.c b/plat/allwinner/common/sunxi_common.c index fc9bf2097..2eb26a91b 100644 --- a/plat/allwinner/common/sunxi_common.c +++ b/plat/allwinner/common/sunxi_common.c @@ -4,21 +4,28 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include <arch_helpers.h> +#include <debug.h> +#include <errno.h> #include <mmio.h> #include <platform.h> #include <platform_def.h> #include <sunxi_def.h> +#include <sunxi_mmap.h> +#include <sunxi_private.h> #include <xlat_tables_v2.h> -#include "sunxi_private.h" - static mmap_region_t sunxi_mmap[PLATFORM_MMAP_REGIONS + 1] = { MAP_REGION_FLAT(SUNXI_SRAM_BASE, SUNXI_SRAM_SIZE, MT_MEMORY | MT_RW | MT_SECURE), MAP_REGION_FLAT(SUNXI_DEV_BASE, SUNXI_DEV_SIZE, MT_DEVICE | MT_RW | MT_SECURE), - MAP_REGION_FLAT(SUNXI_DRAM_BASE, SUNXI_DRAM_SIZE, - MT_MEMORY | MT_RW | MT_NS), + MAP_REGION(SUNXI_DRAM_BASE, SUNXI_DRAM_VIRT_BASE, SUNXI_DRAM_SEC_SIZE, + MT_MEMORY | MT_RW | MT_SECURE), + MAP_REGION(PLAT_SUNXI_NS_IMAGE_OFFSET, + SUNXI_DRAM_VIRT_BASE + SUNXI_DRAM_SEC_SIZE, + SUNXI_DRAM_MAP_SIZE, + MT_MEMORY | MT_RO | MT_NS), {}, }; @@ -47,9 +54,6 @@ void sunxi_configure_mmu_el3(int flags) mmap_add_region(BL_RO_DATA_BASE, BL_RO_DATA_BASE, BL_RO_DATA_END - BL_RO_DATA_BASE, MT_RO_DATA | MT_SECURE); - mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE, - BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, - MT_DEVICE | MT_RW | MT_SECURE); mmap_add(sunxi_mmap); init_xlat_tables(); @@ -71,3 +75,136 @@ uint16_t sunxi_read_soc_id(void) return reg >> 16; } + +/* + * Configure a given pin to the GPIO-OUT function and sets its level. + * The port is given as a capital letter, the pin is the number within + * this port group. + * So to set pin PC7 to high, use: sunxi_set_gpio_out('C', 7, true); + */ +void sunxi_set_gpio_out(char port, int pin, bool level_high) +{ + uintptr_t port_base; + + if (port < 'A' || port > 'L') + return; + if (port == 'L') + port_base = SUNXI_R_PIO_BASE; + else + port_base = SUNXI_PIO_BASE + (port - 'A') * 0x24; + + /* Set the new level first before configuring the pin. */ + if (level_high) + mmio_setbits_32(port_base + 0x10, BIT(pin)); + else + mmio_clrbits_32(port_base + 0x10, BIT(pin)); + + /* configure pin as GPIO out (4(3) bits per pin, 1: GPIO out */ + mmio_clrsetbits_32(port_base + (pin / 8) * 4, + 0x7 << ((pin % 8) * 4), + 0x1 << ((pin % 8) * 4)); +} + +int sunxi_init_platform_r_twi(uint16_t socid, bool use_rsb) +{ + uint32_t pin_func = 0x77; + uint32_t device_bit; + unsigned int reset_offset = 0xb0; + + switch (socid) { + case SUNXI_SOC_H5: + if (use_rsb) + return -ENODEV; + pin_func = 0x22; + device_bit = BIT(6); + break; + case SUNXI_SOC_H6: + if (use_rsb) + return -ENODEV; + pin_func = 0x33; + device_bit = BIT(16); + reset_offset = 0x19c; + break; + case SUNXI_SOC_A64: + pin_func = use_rsb ? 0x22 : 0x33; + device_bit = use_rsb ? BIT(3) : BIT(6); + break; + default: + INFO("R_I2C/RSB on Allwinner 0x%x SoC not supported\n", socid); + return -ENODEV; + } + + /* un-gate R_PIO clock */ + if (socid != SUNXI_SOC_H6) + mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x28, BIT(0)); + + /* switch pins PL0 and PL1 to the desired function */ + mmio_clrsetbits_32(SUNXI_R_PIO_BASE + 0x00, 0xffU, pin_func); + + /* level 2 drive strength */ + mmio_clrsetbits_32(SUNXI_R_PIO_BASE + 0x14, 0x0fU, 0xaU); + + /* set both pins to pull-up */ + mmio_clrsetbits_32(SUNXI_R_PIO_BASE + 0x1c, 0x0fU, 0x5U); + + /* assert, then de-assert reset of I2C/RSB controller */ + mmio_clrbits_32(SUNXI_R_PRCM_BASE + reset_offset, device_bit); + mmio_setbits_32(SUNXI_R_PRCM_BASE + reset_offset, device_bit); + + /* un-gate clock */ + if (socid != SUNXI_SOC_H6) + mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x28, device_bit); + else + mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x19c, device_bit | BIT(0)); + + return 0; +} + +/* This lock synchronises access to the arisc management processor. */ +DEFINE_BAKERY_LOCK(arisc_lock); + +/* + * Tell the "arisc" SCP core (an OpenRISC core) to execute some code. + * We don't have any service running there, so we place some OpenRISC code + * in SRAM, put the address of that into the reset vector and release the + * arisc reset line. The SCP will execute that code and pull the line up again. + */ +void sunxi_execute_arisc_code(uint32_t *code, size_t size, + int patch_offset, uint16_t param) +{ + uintptr_t arisc_reset_vec = SUNXI_SRAM_A2_BASE - 0x4000 + 0x100; + + do { + bakery_lock_get(&arisc_lock); + /* Wait until the arisc is in reset state. */ + if (!(mmio_read_32(SUNXI_R_CPUCFG_BASE) & BIT(0))) + break; + + bakery_lock_release(&arisc_lock); + } while (1); + + /* Patch up the code to feed in an input parameter. */ + if (patch_offset >= 0 && patch_offset <= (size - 4)) + code[patch_offset] = (code[patch_offset] & ~0xffff) | param; + clean_dcache_range((uintptr_t)code, size); + + /* + * The OpenRISC unconditional branch has opcode 0, the branch offset + * is in the lower 26 bits, containing the distance to the target, + * in instruction granularity (32 bits). + */ + mmio_write_32(arisc_reset_vec, ((uintptr_t)code - arisc_reset_vec) / 4); + clean_dcache_range(arisc_reset_vec, 4); + + /* De-assert the arisc reset line to let it run. */ + mmio_setbits_32(SUNXI_R_CPUCFG_BASE, BIT(0)); + + /* + * We release the lock here, although the arisc is still busy. + * But as long as it runs, the reset line is high, so other users + * won't leave the loop above. + * Once it has finished, the code is supposed to clear the reset line, + * to signal this to other users. + */ + bakery_lock_release(&arisc_lock); +} diff --git a/plat/allwinner/common/sunxi_cpu_ops.c b/plat/allwinner/common/sunxi_cpu_ops.c index aaee65c66..3b732b5d1 100644 --- a/plat/allwinner/common/sunxi_cpu_ops.c +++ b/plat/allwinner/common/sunxi_cpu_ops.c @@ -4,15 +4,19 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include <arch_helpers.h> +#include <assert.h> +#include <core_off_arisc.h> #include <debug.h> +#include <delay_timer.h> #include <mmio.h> +#include <platform.h> #include <platform_def.h> -#include <sunxi_mmap.h> #include <sunxi_cpucfg.h> +#include <sunxi_mmap.h> +#include <sunxi_private.h> #include <utils_def.h> -#include "sunxi_private.h" - static void sunxi_cpu_disable_power(unsigned int cluster, unsigned int core) { if (mmio_read_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core)) == 0xff) @@ -40,16 +44,37 @@ static void sunxi_cpu_enable_power(unsigned int cluster, unsigned int core) void sunxi_cpu_off(unsigned int cluster, unsigned int core) { + int corenr = cluster * PLATFORM_MAX_CPUS_PER_CLUSTER + core; + VERBOSE("PSCI: Powering off cluster %d core %d\n", cluster, core); /* Deassert DBGPWRDUP */ mmio_clrbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core)); - /* Activate the core output clamps */ - mmio_setbits_32(SUNXI_POWEROFF_GATING_REG(cluster), BIT(core)); - /* Assert CPU power-on reset */ - mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core)); - /* Remove power from the CPU */ - sunxi_cpu_disable_power(cluster, core); + + /* We can't turn ourself off like this, but it works for other cores. */ + if (plat_my_core_pos() != corenr) { + /* Activate the core output clamps, but not for core 0. */ + if (corenr != 0) + mmio_setbits_32(SUNXI_POWEROFF_GATING_REG(cluster), + BIT(core)); + /* Assert CPU power-on reset */ + mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core)); + /* Remove power from the CPU */ + sunxi_cpu_disable_power(cluster, core); + + return; + } + + /* Simplifies assembly, all SoCs so far are single cluster anyway. */ + assert(cluster == 0); + + /* + * If we are supposed to turn ourself off, tell the arisc SCP + * to do that work for us. The code expects the core mask to be + * patched into the first instruction. + */ + sunxi_execute_arisc_code(arisc_core_off, sizeof(arisc_core_off), + 0, BIT_32(core)); } void sunxi_cpu_on(unsigned int cluster, unsigned int core) diff --git a/plat/allwinner/common/sunxi_pm.c b/plat/allwinner/common/sunxi_pm.c index e4bb58229..7d13cdad1 100644 --- a/plat/allwinner/common/sunxi_pm.c +++ b/plat/allwinner/common/sunxi_pm.c @@ -13,15 +13,14 @@ #include <platform.h> #include <platform_def.h> #include <psci.h> -#include <sunxi_mmap.h> #include <sunxi_cpucfg.h> +#include <sunxi_mmap.h> +#include <sunxi_private.h> #define SUNXI_WDOG0_CTRL_REG (SUNXI_WDOG_BASE + 0x0010) #define SUNXI_WDOG0_CFG_REG (SUNXI_WDOG_BASE + 0x0014) #define SUNXI_WDOG0_MODE_REG (SUNXI_WDOG_BASE + 0x0018) -#include "sunxi_private.h" - #define mpidr_is_valid(mpidr) ( \ MPIDR_AFFLVL3_VAL(mpidr) == 0 && \ MPIDR_AFFLVL2_VAL(mpidr) == 0 && \ @@ -43,6 +42,16 @@ static void sunxi_pwr_domain_off(const psci_power_state_t *target_state) gicv2_cpuif_disable(); } +static void __dead2 sunxi_pwr_down_wfi(const psci_power_state_t *target_state) +{ + u_register_t mpidr = read_mpidr(); + + sunxi_cpu_off(MPIDR_AFFLVL1_VAL(mpidr), MPIDR_AFFLVL0_VAL(mpidr)); + + while (1) + wfi(); +} + static void sunxi_pwr_domain_on_finish(const psci_power_state_t *target_state) { gicv2_pcpu_distif_init(); @@ -83,6 +92,7 @@ static int sunxi_validate_ns_entrypoint(uintptr_t ns_entrypoint) static plat_psci_ops_t sunxi_psci_ops = { .pwr_domain_on = sunxi_pwr_domain_on, .pwr_domain_off = sunxi_pwr_domain_off, + .pwr_domain_pwr_down_wfi = sunxi_pwr_down_wfi, .pwr_domain_on_finish = sunxi_pwr_domain_on_finish, .system_off = sunxi_system_off, .system_reset = sunxi_system_reset, diff --git a/plat/allwinner/common/sunxi_security.c b/plat/allwinner/common/sunxi_security.c index 80fed6ad0..905372887 100644 --- a/plat/allwinner/common/sunxi_security.c +++ b/plat/allwinner/common/sunxi_security.c @@ -7,6 +7,7 @@ #include <debug.h> #include <mmio.h> #include <sunxi_mmap.h> +#include <sunxi_private.h> #ifdef SUNXI_SPC_BASE #define SPC_DECPORT_STA_REG(p) (SUNXI_SPC_BASE + ((p) * 0x0c) + 0x4) diff --git a/plat/allwinner/sun50i_a64/include/core_off_arisc.h b/plat/allwinner/sun50i_a64/include/core_off_arisc.h new file mode 100644 index 000000000..ae436ca1b --- /dev/null +++ b/plat/allwinner/sun50i_a64/include/core_off_arisc.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint32_t arisc_core_off[] = { + 0x18600000, /* l.movhi r3, <corenr> */ + 0x18000000, /* l.movhi r0, 0x0 */ + 0x19a00170, /* l.movhi r13, 0x170 */ + 0x84ad0030, /* l.lwz r5, 0x30(r13) */ + 0xe0a51803, /* l.and r5, r5, r3 */ + 0xe4050000, /* l.sfeq r5, r0 */ + 0x13fffffd, /* l.bf -12 */ + + 0xb8c30050, /* l.srli r6, r3, 16 */ + 0xbc060001, /* l.sfeqi r6, 1 */ + 0x10000005, /* l.bf +20 */ + 0x19a001f0, /* l.movhi r13, 0x1f0 */ + 0x84ad1500, /* l.lwz r5, 0x1500(r13) */ + 0xe0a53004, /* l.or r5, r5, r6 */ + 0xd44d2d00, /* l.sw 0x1500(r13), r5 */ + + 0x84ad1c30, /* l.lwz r5, 0x1c30(r13) */ + 0xacc6ffff, /* l.xori r6, r6, -1 */ + 0xe0a53003, /* l.and r5, r5, r6 */ + 0xd46d2c30, /* l.sw 0x1c30(r13), r5 */ + + 0xe0c3000f, /* l.ff1 r6, r3 */ + 0x9cc6ffef, /* l.addi r6, r6, -17 */ + 0xb8c60002, /* l.slli r6, r6, 2 */ + 0xe0c66800, /* l.add r6, r6, r13 */ + 0xa8a000ff, /* l.ori r5, r0, 0xff */ + 0xd4462d40, /* l.sw 0x1540(r6), r5 */ + + 0xd46d0400, /* l.sw 0x1c00(r13), r0 */ + 0x03ffffff, /* l.j -1 */ + 0x15000000, /* l.nop */ +}; diff --git a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h index 7d46487dc..28b1dd3b8 100644 --- a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h +++ b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h @@ -21,7 +21,7 @@ #define SUNXI_DEV_BASE 0x01000000 #define SUNXI_DEV_SIZE 0x01000000 #define SUNXI_DRAM_BASE 0x40000000 -#define SUNXI_DRAM_SIZE 0x80000000 +#define SUNXI_DRAM_VIRT_BASE 0x02000000 /* Memory-mapped devices */ #define SUNXI_CPU_MBIST_BASE 0x01502000 diff --git a/plat/allwinner/sun50i_a64/platform.mk b/plat/allwinner/sun50i_a64/platform.mk index 221665471..b46fbc2d1 100644 --- a/plat/allwinner/sun50i_a64/platform.mk +++ b/plat/allwinner/sun50i_a64/platform.mk @@ -4,51 +4,7 @@ # SPDX-License-Identifier: BSD-3-Clause # -include lib/xlat_tables_v2/xlat_tables.mk +# The differences between the platform are covered by the include files. +include plat/allwinner/common/allwinner-common.mk -AW_PLAT := plat/allwinner - -PLAT_INCLUDES := -Iinclude/plat/arm/common/ \ - -Iinclude/plat/arm/common/aarch64 \ - -I${AW_PLAT}/common/include \ - -I${AW_PLAT}/${PLAT}/include - -PLAT_BL_COMMON_SOURCES := drivers/console/${ARCH}/console.S \ - drivers/ti/uart/${ARCH}/16550_console.S \ - ${XLAT_TABLES_LIB_SRCS} \ - ${AW_PLAT}/common/plat_helpers.S \ - ${AW_PLAT}/common/sunxi_common.c - -BL31_SOURCES += drivers/arm/gic/common/gic_common.c \ - drivers/arm/gic/v2/gicv2_helpers.c \ - drivers/arm/gic/v2/gicv2_main.c \ - drivers/delay_timer/delay_timer.c \ - drivers/delay_timer/generic_delay_timer.c \ - lib/cpus/${ARCH}/cortex_a53.S \ - plat/common/plat_gicv2.c \ - plat/common/plat_psci_common.c \ - ${AW_PLAT}/common/sunxi_bl31_setup.c \ - ${AW_PLAT}/common/sunxi_cpu_ops.c \ - ${AW_PLAT}/common/sunxi_pm.c \ - ${AW_PLAT}/sun50i_a64/sunxi_power.c \ - ${AW_PLAT}/common/sunxi_security.c \ - ${AW_PLAT}/common/sunxi_topology.c - -# The bootloader is guaranteed to only run on CPU 0 by the boot ROM. -COLD_BOOT_SINGLE_CPU := 1 - -# Enable workarounds for Cortex-A53 errata. Allwinner uses at least r0p4. -ERRATA_A53_835769 := 1 -ERRATA_A53_843419 := 1 -ERRATA_A53_855873 := 1 - -MULTI_CONSOLE_API := 1 - -# The reset vector can be changed for each CPU. -PROGRAMMABLE_RESET_ADDRESS := 1 - -# Allow mapping read-only data as execute-never. -SEPARATE_CODE_AND_RODATA := 1 - -# BL31 gets loaded alongside BL33 (U-Boot) by U-Boot's SPL -RESET_TO_BL31 := 1 +PLAT_BL_COMMON_SOURCES += drivers/allwinner/sunxi_rsb.c diff --git a/plat/allwinner/sun50i_a64/sunxi_power.c b/plat/allwinner/sun50i_a64/sunxi_power.c index c1907d6d2..af3047731 100644 --- a/plat/allwinner/sun50i_a64/sunxi_power.c +++ b/plat/allwinner/sun50i_a64/sunxi_power.c @@ -5,20 +5,350 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include <allwinner/sunxi_rsb.h> #include <arch_helpers.h> #include <debug.h> +#include <delay_timer.h> +#include <errno.h> +#include <libfdt.h> +#include <mmio.h> +#include <platform_def.h> +#include <sunxi_def.h> +#include <sunxi_mmap.h> +#include <sunxi_private.h> -int sunxi_pmic_setup(void) +static enum pmic_type { + GENERIC_H5, + GENERIC_A64, + REF_DESIGN_H5, /* regulators controlled by GPIO pins on port L */ + AXP803_RSB, /* PMIC connected via RSB on most A64 boards */ +} pmic; + +#define AXP803_HW_ADDR 0x3a3 +#define AXP803_RT_ADDR 0x2d + +/* + * On boards without a proper PMIC we struggle to turn off the system properly. + * Try to turn off as much off the system as we can, to reduce power + * consumption. This should be entered with only one core running and SMP + * disabled. + * This function only cares about peripherals. + */ +void sunxi_turn_off_soc(uint16_t socid) +{ + int i; + + /** Turn off most peripherals, most importantly DRAM users. **/ + /* Keep DRAM controller running for now. */ + mmio_clrbits_32(SUNXI_CCU_BASE + 0x2c0, ~BIT_32(14)); + mmio_clrbits_32(SUNXI_CCU_BASE + 0x60, ~BIT_32(14)); + /* Contains msgbox (bit 21) and spinlock (bit 22) */ + mmio_write_32(SUNXI_CCU_BASE + 0x2c4, 0); + mmio_write_32(SUNXI_CCU_BASE + 0x64, 0); + mmio_write_32(SUNXI_CCU_BASE + 0x2c8, 0); + /* Keep PIO controller running for now. */ + mmio_clrbits_32(SUNXI_CCU_BASE + 0x68, ~(BIT_32(5))); + mmio_write_32(SUNXI_CCU_BASE + 0x2d0, 0); + /* Contains UART0 (bit 16) */ + mmio_write_32(SUNXI_CCU_BASE + 0x2d8, 0); + mmio_write_32(SUNXI_CCU_BASE + 0x6c, 0); + mmio_write_32(SUNXI_CCU_BASE + 0x70, 0); + + /** Turn off DRAM controller. **/ + mmio_clrbits_32(SUNXI_CCU_BASE + 0x2c0, BIT_32(14)); + mmio_clrbits_32(SUNXI_CCU_BASE + 0x60, BIT_32(14)); + + /** Migrate CPU and bus clocks away from the PLLs. **/ + /* AHB1: use OSC24M/1, APB1 = AHB1 / 2 */ + mmio_write_32(SUNXI_CCU_BASE + 0x54, 0x1000); + /* APB2: use OSC24M */ + mmio_write_32(SUNXI_CCU_BASE + 0x58, 0x1000000); + /* AHB2: use AHB1 clock */ + mmio_write_32(SUNXI_CCU_BASE + 0x5c, 0); + /* CPU: use OSC24M */ + mmio_write_32(SUNXI_CCU_BASE + 0x50, 0x10000); + + /** Turn off PLLs. **/ + for (i = 0; i < 6; i++) + mmio_clrbits_32(SUNXI_CCU_BASE + i * 8, BIT(31)); + switch (socid) { + case SUNXI_SOC_H5: + mmio_clrbits_32(SUNXI_CCU_BASE + 0x44, BIT(31)); + break; + case SUNXI_SOC_A64: + mmio_clrbits_32(SUNXI_CCU_BASE + 0x2c, BIT(31)); + mmio_clrbits_32(SUNXI_CCU_BASE + 0x4c, BIT(31)); + break; + } +} + +static int rsb_init(void) +{ + int ret; + + ret = rsb_init_controller(); + if (ret) + return ret; + + /* Start with 400 KHz to issue the I2C->RSB switch command. */ + ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 400000); + if (ret) + return ret; + + /* + * Initiate an I2C transaction to write 0x7c into register 0x3e, + * switching the PMIC to RSB mode. + */ + ret = rsb_set_device_mode(0x7c3e00); + if (ret) + return ret; + + /* Now in RSB mode, switch to the recommended 3 MHz. */ + ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000); + if (ret) + return ret; + + /* Associate the 8-bit runtime address with the 12-bit bus address. */ + return rsb_assign_runtime_address(AXP803_HW_ADDR, + AXP803_RT_ADDR); +} + +static int axp_write(uint8_t reg, uint8_t val) +{ + return rsb_write(AXP803_RT_ADDR, reg, val); +} + +static int axp_setbits(uint8_t reg, uint8_t set_mask) +{ + uint8_t regval; + int ret; + + ret = rsb_read(AXP803_RT_ADDR, reg); + if (ret < 0) + return ret; + + regval = ret | set_mask; + + return rsb_write(AXP803_RT_ADDR, reg, regval); +} + +static bool should_enable_regulator(const void *fdt, int node) { - /* STUB */ - NOTICE("BL31: STUB PMIC setup code called\n"); + if (fdt_getprop(fdt, node, "phandle", NULL) != NULL) + return true; + if (fdt_getprop(fdt, node, "regulator-always-on", NULL) != NULL) + return true; + return false; +} + +/* + * Retrieve the voltage from a given regulator DTB node. + * Both the regulator-{min,max}-microvolt properties must be present and + * have the same value. Return that value in millivolts. + */ +static int fdt_get_regulator_millivolt(const void *fdt, int node) +{ + const fdt32_t *prop; + uint32_t min_volt; + + prop = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL); + if (prop == NULL) + return -EINVAL; + min_volt = fdt32_to_cpu(*prop); + + prop = fdt_getprop(fdt, node, "regulator-max-microvolt", NULL); + if (prop == NULL) + return -EINVAL; + + if (fdt32_to_cpu(*prop) != min_volt) + return -EINVAL; + + return min_volt / 1000; +} + +#define NO_SPLIT 0xff + +struct axp_regulator { + char *dt_name; + uint16_t min_volt; + uint16_t max_volt; + uint16_t step; + unsigned char split; + unsigned char volt_reg; + unsigned char switch_reg; + unsigned char switch_bit; +} regulators[] = { + {"dcdc1", 1600, 3400, 100, NO_SPLIT, 0x20, 0xff, 9}, + {"dcdc5", 800, 1840, 10, 32, 0x24, 0xff, 9}, + {"dldo1", 700, 3300, 100, NO_SPLIT, 0x15, 0x12, 3}, + {"dldo2", 700, 4200, 100, 27, 0x16, 0x12, 4}, + {"dldo3", 700, 3300, 100, NO_SPLIT, 0x17, 0x12, 5}, + {"fldo1", 700, 1450, 50, NO_SPLIT, 0x1c, 0x13, 2}, + {} +}; + +static int setup_regulator(const void *fdt, int node, + const struct axp_regulator *reg) +{ + int mvolt; + uint8_t regval; + + if (!should_enable_regulator(fdt, node)) + return -ENOENT; + + mvolt = fdt_get_regulator_millivolt(fdt, node); + if (mvolt < reg->min_volt || mvolt > reg->max_volt) + return -EINVAL; + + regval = (mvolt / reg->step) - (reg->min_volt / reg->step); + if (regval > reg->split) + regval = ((regval - reg->split) / 2) + reg->split; + + axp_write(reg->volt_reg, regval); + if (reg->switch_reg < 0xff) + axp_setbits(reg->switch_reg, BIT(reg->switch_bit)); + + INFO("PMIC: AXP803: %s voltage: %d.%03dV\n", reg->dt_name, + mvolt / 1000, mvolt % 1000); return 0; } +static void setup_axp803_rails(const void *fdt) +{ + int node; + bool dc1sw = false; + + /* locate the PMIC DT node, bail out if not found */ + node = fdt_node_offset_by_compatible(fdt, -1, "x-powers,axp803"); + if (node == -FDT_ERR_NOTFOUND) { + WARN("BL31: PMIC: No AXP803 DT node, skipping initial setup.\n"); + return; + } + + if (fdt_getprop(fdt, node, "x-powers,drive-vbus-en", NULL)) + axp_setbits(0x8f, BIT(4)); + + /* descend into the "regulators" subnode */ + node = fdt_first_subnode(fdt, node); + + /* iterate over all regulators to find used ones */ + for (node = fdt_first_subnode(fdt, node); + node != -FDT_ERR_NOTFOUND; + node = fdt_next_subnode(fdt, node)) { + struct axp_regulator *reg; + const char *name; + int length; + + /* We only care if it's always on or referenced. */ + if (!should_enable_regulator(fdt, node)) + continue; + + name = fdt_get_name(fdt, node, &length); + for (reg = regulators; reg->dt_name; reg++) { + if (!strncmp(name, reg->dt_name, length)) { + setup_regulator(fdt, node, reg); + break; + } + } + + if (!strncmp(name, "dc1sw", length)) { + /* Delay DC1SW enablement to avoid overheating. */ + dc1sw = true; + continue; + } + } + /* + * If DLDO2 is enabled after DC1SW, the PMIC overheats and shuts + * down. So always enable DC1SW as the very last regulator. + */ + if (dc1sw) { + INFO("PMIC: AXP803: Enabling DC1SW\n"); + axp_setbits(0x12, BIT(7)); + } +} + +int sunxi_pmic_setup(uint16_t socid, const void *fdt) +{ + int ret; + + switch (socid) { + case SUNXI_SOC_H5: + pmic = REF_DESIGN_H5; + NOTICE("BL31: PMIC: Defaulting to PortL GPIO according to H5 reference design.\n"); + break; + case SUNXI_SOC_A64: + pmic = GENERIC_A64; + ret = sunxi_init_platform_r_twi(socid, true); + if (ret) + return ret; + + ret = rsb_init(); + if (ret) + return ret; + + pmic = AXP803_RSB; + NOTICE("BL31: PMIC: Detected AXP803 on RSB.\n"); + + if (fdt) + setup_axp803_rails(fdt); + + break; + default: + NOTICE("BL31: PMIC: No support for Allwinner %x SoC.\n", socid); + return -ENODEV; + } + return 0; +} + void __dead2 sunxi_power_down(void) { - ERROR("PSCI: Full shutdown not implemented, halting\n"); + switch (pmic) { + case GENERIC_H5: + /* Turn off as many peripherals and clocks as we can. */ + sunxi_turn_off_soc(SUNXI_SOC_H5); + /* Turn off the pin controller now. */ + mmio_write_32(SUNXI_CCU_BASE + 0x68, 0); + break; + case GENERIC_A64: + /* Turn off as many peripherals and clocks as we can. */ + sunxi_turn_off_soc(SUNXI_SOC_A64); + /* Turn off the pin controller now. */ + mmio_write_32(SUNXI_CCU_BASE + 0x68, 0); + break; + case REF_DESIGN_H5: + sunxi_turn_off_soc(SUNXI_SOC_H5); + + /* + * Switch PL pins to power off the board: + * - PL5 (VCC_IO) -> high + * - PL8 (PWR-STB = CPU power supply) -> low + * - PL9 (PWR-DRAM) ->low + * - PL10 (power LED) -> low + * Note: Clearing PL8 will reset the board, so keep it up. + */ + sunxi_set_gpio_out('L', 5, 1); + sunxi_set_gpio_out('L', 9, 0); + sunxi_set_gpio_out('L', 10, 0); + + /* Turn off pin controller now. */ + mmio_write_32(SUNXI_CCU_BASE + 0x68, 0); + + break; + case AXP803_RSB: + /* (Re-)init RSB in case the rich OS has disabled it. */ + sunxi_init_platform_r_twi(SUNXI_SOC_A64, true); + rsb_init(); + + /* Set "power disable control" bit */ + axp_setbits(0x32, BIT(7)); + break; + default: + break; + } + + udelay(1000); + ERROR("PSCI: Cannot turn off system, halting.\n"); wfi(); panic(); } diff --git a/plat/allwinner/sun50i_h6/include/core_off_arisc.h b/plat/allwinner/sun50i_h6/include/core_off_arisc.h new file mode 100644 index 000000000..63a5d8d96 --- /dev/null +++ b/plat/allwinner/sun50i_h6/include/core_off_arisc.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint32_t arisc_core_off[] = { + 0x18600000, /* l.movhi r3, <corenr> */ + 0x18000000, /* l.movhi r0, 0x0 */ + 0x19a00901, /* l.movhi r13, 0x901 */ + 0x84ad0080, /* l.lwz r5, 0x80(r13) */ + 0xe0a51803, /* l.and r5, r5, r3 */ + 0xe4050000, /* l.sfeq r5, r0 */ + 0x13fffffd, /* l.bf -12 */ + 0xb8c30050, /* l.srli r6, r3, 16 */ + + 0xbc060001, /* l.sfeqi r6, 1 */ + 0x10000005, /* l.bf +20 */ + 0x19a00700, /* l.movhi r13, 0x700 */ + 0x84ad0444, /* l.lwz r5, 0x0444(r13) */ + 0xe0a53004, /* l.or r5, r5, r6 */ + 0xd40d2c44, /* l.sw 0x0444(r13), r5 */ + + 0x84ad0440, /* l.lwz r5, 0x0440(r13) */ + 0xacc6ffff, /* l.xori r6, r6, -1 */ + 0xe0a53003, /* l.and r5, r5, r6 */ + 0xd40d2c40, /* l.sw 0x0440(r13), r5 */ + + 0xe0c3000f, /* l.ff1 r6, r3 */ + 0x9cc6ffef, /* l.addi r6, r6, -17 */ + 0xb8c60002, /* l.slli r6, r6, 2 */ + 0xe0c66800, /* l.add r6, r6, r13 */ + 0xa8a000ff, /* l.ori r5, r0, 0xff */ + 0xd4062c50, /* l.sw 0x0450(r6), r5 */ + + 0xd40d0400, /* l.sw 0x0400(r13), r0 */ + 0x03ffffff, /* l.j -1 */ + 0x15000000, /* l.nop */ +}; diff --git a/plat/allwinner/sun50i_h6/include/sunxi_mmap.h b/plat/allwinner/sun50i_h6/include/sunxi_mmap.h index f2d5aed6b..ff1eb61e9 100644 --- a/plat/allwinner/sun50i_h6/include/sunxi_mmap.h +++ b/plat/allwinner/sun50i_h6/include/sunxi_mmap.h @@ -11,7 +11,7 @@ #define SUNXI_ROM_BASE 0x00000000 #define SUNXI_ROM_SIZE 0x00010000 #define SUNXI_SRAM_BASE 0x00020000 -#define SUNXI_SRAM_SIZE 0x00098000 +#define SUNXI_SRAM_SIZE 0x000f8000 #define SUNXI_SRAM_A1_BASE 0x00020000 #define SUNXI_SRAM_A1_SIZE 0x00008000 #define SUNXI_SRAM_A2_BASE 0x00104000 @@ -21,7 +21,7 @@ #define SUNXI_DEV_BASE 0x01000000 #define SUNXI_DEV_SIZE 0x09000000 #define SUNXI_DRAM_BASE 0x40000000 -#define SUNXI_DRAM_SIZE 0xc0000000 +#define SUNXI_DRAM_VIRT_BASE 0x0a000000 /* Memory-mapped devices */ #define SUNXI_SYSCON_BASE 0x03000000 diff --git a/plat/allwinner/sun50i_h6/platform.mk b/plat/allwinner/sun50i_h6/platform.mk index 4fb8986d6..5c21eadb2 100644 --- a/plat/allwinner/sun50i_h6/platform.mk +++ b/plat/allwinner/sun50i_h6/platform.mk @@ -4,53 +4,7 @@ # SPDX-License-Identifier: BSD-3-Clause # -include lib/xlat_tables_v2/xlat_tables.mk +# The differences between the platform are covered by the include files. +include plat/allwinner/common/allwinner-common.mk -AW_PLAT := plat/allwinner -AW_DRIVERS := drivers/allwinner - -PLAT_INCLUDES := -Iinclude/plat/arm/common \ - -Iinclude/plat/arm/common/aarch64 \ - -I${AW_PLAT}/common/include \ - -I${AW_PLAT}/${PLAT}/include - -PLAT_BL_COMMON_SOURCES := drivers/console/${ARCH}/console.S \ - drivers/mentor/i2c/mi2cv.c \ - drivers/ti/uart/${ARCH}/16550_console.S \ - ${XLAT_TABLES_LIB_SRCS} \ - ${AW_PLAT}/common/plat_helpers.S \ - ${AW_PLAT}/common/sunxi_common.c - -BL31_SOURCES += drivers/arm/gic/common/gic_common.c \ - drivers/arm/gic/v2/gicv2_helpers.c \ - drivers/arm/gic/v2/gicv2_main.c \ - drivers/delay_timer/delay_timer.c \ - drivers/delay_timer/generic_delay_timer.c \ - lib/cpus/${ARCH}/cortex_a53.S \ - plat/common/plat_gicv2.c \ - plat/common/plat_psci_common.c \ - ${AW_PLAT}/common/sunxi_bl31_setup.c \ - ${AW_PLAT}/common/sunxi_cpu_ops.c \ - ${AW_PLAT}/common/sunxi_pm.c \ - ${AW_PLAT}/sun50i_h6/sunxi_power.c \ - ${AW_PLAT}/common/sunxi_security.c \ - ${AW_PLAT}/common/sunxi_topology.c - -# The bootloader is guaranteed to only run on CPU 0 by the boot ROM. -COLD_BOOT_SINGLE_CPU := 1 - -# Enable workarounds for Cortex-A53 errata. Allwinner uses at least r0p4. -ERRATA_A53_835769 := 1 -ERRATA_A53_843419 := 1 -ERRATA_A53_855873 := 1 - -MULTI_CONSOLE_API := 1 - -# The reset vector can be changed for each CPU. -PROGRAMMABLE_RESET_ADDRESS := 1 - -# Allow mapping read-only data as execute-never. -SEPARATE_CODE_AND_RODATA := 1 - -# BL31 gets loaded alongside BL33 (U-Boot) by U-Boot's SPL -RESET_TO_BL31 := 1 +PLAT_BL_COMMON_SOURCES += drivers/mentor/i2c/mi2cv.c diff --git a/plat/allwinner/sun50i_h6/sunxi_power.c b/plat/allwinner/sun50i_h6/sunxi_power.c index 12438b339..7bdac8ab0 100644 --- a/plat/allwinner/sun50i_h6/sunxi_power.c +++ b/plat/allwinner/sun50i_h6/sunxi_power.c @@ -12,7 +12,9 @@ #include <mmio.h> #include <mentor/mi2cv.h> #include <string.h> +#include <sunxi_def.h> #include <sunxi_mmap.h> +#include <sunxi_private.h> #define AXP805_ADDR 0x36 #define AXP805_ID 0x03 @@ -24,36 +26,6 @@ enum pmic_type { enum pmic_type pmic; -static int sunxi_init_r_i2c(void) -{ - uint32_t reg; - - /* switch pins PL0 and PL1 to I2C */ - reg = mmio_read_32(SUNXI_R_PIO_BASE + 0x00); - mmio_write_32(SUNXI_R_PIO_BASE + 0x00, (reg & ~0xff) | 0x33); - - /* level 2 drive strength */ - reg = mmio_read_32(SUNXI_R_PIO_BASE + 0x14); - mmio_write_32(SUNXI_R_PIO_BASE + 0x14, (reg & ~0x0f) | 0xa); - - /* set both ports to pull-up */ - reg = mmio_read_32(SUNXI_R_PIO_BASE + 0x1c); - mmio_write_32(SUNXI_R_PIO_BASE + 0x1c, (reg & ~0x0f) | 0x5); - - /* assert & de-assert reset of R_I2C */ - reg = mmio_read_32(SUNXI_R_PRCM_BASE + 0x19c); - mmio_write_32(SUNXI_R_PRCM_BASE + 0x19c, reg & ~BIT(16)); - mmio_write_32(SUNXI_R_PRCM_BASE + 0x19c, reg | BIT(16)); - - /* un-gate R_I2C clock */ - mmio_write_32(SUNXI_R_PRCM_BASE + 0x19c, reg | BIT(16) | BIT(0)); - - /* call mi2cv driver */ - i2c_init((void *)SUNXI_R_I2C_BASE); - - return 0; -} - int axp_i2c_read(uint8_t chip, uint8_t reg, uint8_t *val) { int ret; @@ -96,11 +68,13 @@ static int axp805_probe(void) return 0; } -int sunxi_pmic_setup(void) +int sunxi_pmic_setup(uint16_t socid, const void *fdt) { int ret; - sunxi_init_r_i2c(); + sunxi_init_platform_r_twi(SUNXI_SOC_H6, false); + /* initialise mi2cv driver */ + i2c_init((void *)SUNXI_R_I2C_BASE); NOTICE("PMIC: Probing AXP805\n"); pmic = AXP805; @@ -120,7 +94,10 @@ void __dead2 sunxi_power_down(void) switch (pmic) { case AXP805: - sunxi_init_r_i2c(); + /* Re-initialise after rich OS might have used it. */ + sunxi_init_platform_r_twi(SUNXI_SOC_H6, false); + /* initialise mi2cv driver */ + i2c_init((void *)SUNXI_R_I2C_BASE); axp_i2c_read(AXP805_ADDR, 0x32, &val); axp_i2c_write(AXP805_ADDR, 0x32, val | 0x80); break; diff --git a/plat/arm/board/fvp/aarch64/fvp_helpers.S b/plat/arm/board/fvp/aarch64/fvp_helpers.S index 88fcdb1b0..abc3ceb00 100644 --- a/plat/arm/board/fvp/aarch64/fvp_helpers.S +++ b/plat/arm/board/fvp/aarch64/fvp_helpers.S @@ -19,7 +19,7 @@ .globl plat_arm_calc_core_pos .macro fvp_choose_gicmmap param1, param2, x_tmp, w_tmp, res - ldr \x_tmp, =V2M_SYSREGS_BASE + V2M_SYS_ID + mov_imm \x_tmp, V2M_SYSREGS_BASE + V2M_SYS_ID ldr \w_tmp, [\x_tmp] ubfx \w_tmp, \w_tmp, #V2M_SYS_ID_BLD_SHIFT, #V2M_SYS_ID_BLD_LENGTH cmp \w_tmp, #BLD_GIC_VE_MMAP @@ -48,7 +48,7 @@ func plat_secondary_cold_boot_setup * --------------------------------------------- */ mrs x0, mpidr_el1 - ldr x1, =PWRC_BASE + mov_imm x1, PWRC_BASE str w0, [x1, #PPOFFR_OFF] /* --------------------------------------------- @@ -72,8 +72,8 @@ func plat_secondary_cold_boot_setup b secondary_cold_boot_wait gicv2_bypass_disable: - ldr x0, =VE_GICC_BASE - ldr x1, =BASE_GICC_BASE + mov_imm x0, VE_GICC_BASE + mov_imm x1, BASE_GICC_BASE fvp_choose_gicmmap x0, x1, x2, w2, x1 mov w0, #(IRQ_BYP_DIS_GRP1 | FIQ_BYP_DIS_GRP1) orr w0, w0, #(IRQ_BYP_DIS_GRP0 | FIQ_BYP_DIS_GRP0) @@ -128,7 +128,7 @@ func plat_get_my_entrypoint * --------------------------------------------------------------------- */ mrs x2, mpidr_el1 - ldr x1, =PWRC_BASE + mov_imm x1, PWRC_BASE str w2, [x1, #PSYSR_OFF] ldr w2, [x1, #PSYSR_OFF] ubfx w2, w2, #PSYSR_WK_SHIFT, #PSYSR_WK_WIDTH @@ -171,7 +171,7 @@ endfunc plat_get_my_entrypoint */ func plat_is_my_cpu_primary mrs x0, mpidr_el1 - ldr x1, =MPIDR_AFFINITY_MASK + mov_imm x1, MPIDR_AFFINITY_MASK and x0, x0, x1 cmp x0, #FVP_PRIMARY_CPU cset w0, eq diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c index aa4f8398d..f5198f686 100644 --- a/plat/arm/board/fvp/fvp_common.c +++ b/plat/arm/board/fvp/fvp_common.c @@ -7,7 +7,6 @@ #include <arm_config.h> #include <arm_def.h> #include <arm_spm_def.h> -#include <arm_xlat_tables.h> #include <assert.h> #include <cci.h> #include <ccn.h> @@ -18,6 +17,8 @@ #include <platform.h> #include <secure_partition.h> #include <v2m_def.h> +#include <xlat_tables_compat.h> + #include "../fvp_def.h" #include "fvp_private.h" @@ -52,8 +53,8 @@ arm_config_t arm_config; /* * Table of memory regions for various BL stages to map using the MMU. - * This doesn't include Trusted SRAM as arm_setup_page_tables() already - * takes care of mapping it. + * This doesn't include Trusted SRAM as setup_page_tables() already takes care + * of mapping it. * * The flash needs to be mapped as writable in order to erase the FIP's Table of * Contents in case of unrecoverable error (see plat_error_handler()). diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index 332df4d44..3d858c20e 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -202,7 +202,9 @@ ENABLE_AMU := 1 DYNAMIC_WORKAROUND_CVE_2018_3639 := 1 # Enable reclaiming of BL31 initialisation code for secondary cores stacks for FVP +ifneq (${RESET_TO_BL31},1) RECLAIM_INIT_CODE := 1 +endif ifeq (${ENABLE_AMU},1) BL31_SOURCES += lib/cpus/aarch64/cortex_a75_pubsub.c \ diff --git a/plat/arm/board/juno/juno_common.c b/plat/arm/board/juno/juno_common.c index 40b1a275a..2e6b01134 100644 --- a/plat/arm/board/juno/juno_common.c +++ b/plat/arm/board/juno/juno_common.c @@ -8,8 +8,8 @@ /* * Table of memory regions for different BL stages to map using the MMU. - * This doesn't include Trusted SRAM as arm_setup_page_tables() already - * takes care of mapping it. + * This doesn't include Trusted SRAM as setup_page_tables() already takes care + * of mapping it. */ #ifdef IMAGE_BL1 const mmap_region_t plat_arm_mmap[] = { diff --git a/plat/arm/board/n1sdp/aarch64/n1sdp_helper.S b/plat/arm/board/n1sdp/aarch64/n1sdp_helper.S new file mode 100644 index 000000000..6eb01aa57 --- /dev/null +++ b/plat/arm/board/n1sdp/aarch64/n1sdp_helper.S @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <cortex_ares.h> +#include <cpu_macros.S> +#include <platform_def.h> + + .globl plat_arm_calc_core_pos + .globl plat_reset_handler + + /* ----------------------------------------------------- + * unsigned int plat_arm_calc_core_pos(u_register_t mpidr) + * + * Helper function to calculate the core position. + * (ClusterId * N1SDP_MAX_CPUS_PER_CLUSTER * N1SDP_MAX_PE_PER_CPU) + + * (CPUId * N1SDP_MAX_PE_PER_CPU) + + * ThreadId + * + * which can be simplified as: + * + * ((ClusterId * N1SDP_MAX_CPUS_PER_CLUSTER + CPUId) * + * N1SDP_MAX_PE_PER_CPU) + ThreadId + * ------------------------------------------------------ + */ + +func plat_arm_calc_core_pos + mov x3, x0 + + /* + * The MT bit in MPIDR is always set for n1sdp and the + * affinity level 0 corresponds to thread affinity level. + */ + + /* Extract individual affinity fields from MPIDR */ + ubfx x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS + + /* Compute linear position */ + mov x4, #N1SDP_MAX_CPUS_PER_CLUSTER + madd x1, x2, x4, x1 + mov x5, #N1SDP_MAX_PE_PER_CPU + madd x0, x1, x5, x0 + ret +endfunc plat_arm_calc_core_pos + + /* ----------------------------------------------------- + * void plat_reset_handler(void); + * + * Determine the CPU MIDR and disable power down bit for + * that CPU. + * ----------------------------------------------------- + */ + +func plat_reset_handler + jump_if_cpu_midr CORTEX_ARES_MIDR, ARES + ret + + /* ----------------------------------------------------- + * Disable CPU power down bit in power control register + * ----------------------------------------------------- + */ +ARES: + mrs x0, CORTEX_ARES_CPUPWRCTLR_EL1 + bic x0, x0, #CORTEX_ARES_CORE_PWRDN_EN_MASK + msr CORTEX_ARES_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc plat_reset_handler diff --git a/plat/arm/board/n1sdp/include/plat_macros.S b/plat/arm/board/n1sdp/include/plat_macros.S new file mode 100644 index 000000000..fe9a66c3d --- /dev/null +++ b/plat/arm/board/n1sdp/include/plat_macros.S @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef __PLAT_MACROS_S__ +#define __PLAT_MACROS_S__ + +#include <css_macros.S> + +/* --------------------------------------------- + * The below required platform porting macro + * prints out relevant platform registers + * whenever an unhandled exception is taken in + * BL31. + * + * There are currently no platform specific regs + * to print. + * --------------------------------------------- + */ + .macro plat_crash_print_regs + .endm +#endif /* __PLAT_MACROS_S__ */ diff --git a/plat/arm/board/n1sdp/include/platform_def.h b/plat/arm/board/n1sdp/include/platform_def.h new file mode 100644 index 000000000..d26f55921 --- /dev/null +++ b/plat/arm/board/n1sdp/include/platform_def.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PLATFORM_DEF_H__ +#define __PLATFORM_DEF_H__ + +#include <arm_def.h> +#include <board_css_def.h> +#include <css_def.h> + +#if CSS_USE_SCMI_SDS_DRIVER +#define N1SDP_SCMI_PAYLOAD_BASE 0x45400000 +#else +#define PLAT_CSS_SCP_COM_SHARED_MEM_BASE 0x45400000 +#endif + +#define PLAT_ARM_TRUSTED_SRAM_SIZE 0x00080000 /* 512 KB */ +#define PLAT_ARM_MAX_BL31_SIZE 0X20000 + + +/******************************************************************************* + * N1SDP topology related constants + ******************************************************************************/ +#define N1SDP_MAX_CPUS_PER_CLUSTER 2 +#define PLAT_ARM_CLUSTER_COUNT 2 +#define N1SDP_MAX_PE_PER_CPU 1 + +#define PLATFORM_CORE_COUNT (PLAT_ARM_CLUSTER_COUNT * \ + N1SDP_MAX_CPUS_PER_CLUSTER * \ + N1SDP_MAX_PE_PER_CPU) + + +/* + * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the + * plat_arm_mmap array defined for each BL stage. + */ +#define PLAT_ARM_MMAP_ENTRIES 3 +#define MAX_XLAT_TABLES 4 + +#define PLATFORM_STACK_SIZE 0x400 + +#define PLAT_ARM_NSTIMER_FRAME_ID 0 +#define PLAT_CSS_MHU_BASE 0x45000000 +#define PLAT_MAX_PWR_LVL 1 + +#define PLAT_ARM_G1S_IRQS ARM_G1S_IRQS, \ + CSS_IRQ_MHU +#define PLAT_ARM_G0_IRQS ARM_G0_IRQS + +#define PLAT_ARM_G1S_IRQ_PROPS(grp) CSS_G1S_IRQ_PROPS(grp) +#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp) + + +#define N1SDP_DEVICE_BASE (0x20000000) +#define N1SDP_DEVICE_SIZE (0x20000000) +#define N1SDP_MAP_DEVICE MAP_REGION_FLAT( \ + N1SDP_DEVICE_BASE, \ + N1SDP_DEVICE_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/* GIC related constants */ +#define PLAT_ARM_GICD_BASE 0x30000000 +#define PLAT_ARM_GICC_BASE 0x2C000000 +#define PLAT_ARM_GICR_BASE 0x300C0000 + +/* Platform ID address */ +#define SSC_VERSION (SSC_REG_BASE + SSC_VERSION_OFFSET) +#endif /* __PLATFORM_DEF_H__ */ diff --git a/plat/arm/board/n1sdp/n1sdp_bl31_setup.c b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c new file mode 100644 index 000000000..65aad9cf2 --- /dev/null +++ b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "../../css/drivers/scmi/scmi.h" +#include "../../css/drivers/mhu/css_mhu_doorbell.h" +#include <platform_def.h> + +static scmi_channel_plat_info_t n1sdp_scmi_plat_info = { + .scmi_mbx_mem = N1SDP_SCMI_PAYLOAD_BASE, + .db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF, + .db_preserve_mask = 0xfffffffe, + .db_modify_mask = 0x1, + .ring_doorbell = &mhu_ring_doorbell, +}; + +scmi_channel_plat_info_t *plat_css_get_scmi_info() +{ + return &n1sdp_scmi_plat_info; +} diff --git a/plat/arm/board/n1sdp/n1sdp_interconnect.c b/plat/arm/board/n1sdp/n1sdp_interconnect.c new file mode 100644 index 000000000..908f41c39 --- /dev/null +++ b/plat/arm/board/n1sdp/n1sdp_interconnect.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +/* + * For N1SDP which support FCM (with automatic interconnect enter/exit), + * we should not do anything in these interface functions. + * They are used to override the weak functions in cci drivers. + */ + +/****************************************************************************** + * Helper function to initialize ARM interconnect driver. + *****************************************************************************/ +void plat_arm_interconnect_init(void) +{ +} + +/****************************************************************************** + * Helper function to place current master into coherency + *****************************************************************************/ +void plat_arm_interconnect_enter_coherency(void) +{ +} + +/****************************************************************************** + * Helper function to remove current master from coherency + *****************************************************************************/ +void plat_arm_interconnect_exit_coherency(void) +{ +} diff --git a/plat/arm/board/n1sdp/n1sdp_plat.c b/plat/arm/board/n1sdp/n1sdp_plat.c new file mode 100644 index 000000000..8c057c55e --- /dev/null +++ b/plat/arm/board/n1sdp/n1sdp_plat.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arm_def.h> +#include <bl_common.h> +#include <debug.h> +#include <plat_arm.h> +#include <platform.h> +#include <platform_def.h> + +/* + * Table of regions to map using the MMU. + * Replace or extend the below regions as required + */ + +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + N1SDP_MAP_DEVICE, + SOC_CSS_MAP_DEVICE, + {0} +}; + diff --git a/plat/arm/board/n1sdp/n1sdp_security.c b/plat/arm/board/n1sdp/n1sdp_security.c new file mode 100644 index 000000000..d2a187ba1 --- /dev/null +++ b/plat/arm/board/n1sdp/n1sdp_security.c @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * TZC programming is currently not done. + */ +void plat_arm_security_setup(void) +{ +} diff --git a/plat/arm/board/n1sdp/n1sdp_topology.c b/plat/arm/board/n1sdp/n1sdp_topology.c new file mode 100644 index 000000000..c3b4550d0 --- /dev/null +++ b/plat/arm/board/n1sdp/n1sdp_topology.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat_arm.h> + +/* Topology */ +typedef struct n1sdp_topology { + const unsigned char *power_tree; + unsigned int plat_cluster_core_count; +} n1sdp_topology_t; + +/* + * The power domain tree descriptor. The cluster power domains are + * arranged so that when the PSCI generic code creates the power domain tree, + * the indices of the CPU power domain nodes it allocates match the linear + * indices returned by plat_core_pos_by_mpidr(). + */ +const unsigned char n1sdp_pd_tree_desc[] = { + PLAT_ARM_CLUSTER_COUNT, + N1SDP_MAX_CPUS_PER_CLUSTER, + N1SDP_MAX_CPUS_PER_CLUSTER +}; + +/* Topology configuration for n1sdp */ +const n1sdp_topology_t n1sdp_topology = { + .power_tree = n1sdp_pd_tree_desc, + .plat_cluster_core_count = N1SDP_MAX_CPUS_PER_CLUSTER +}; + +/******************************************************************************* + * This function returns the topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return n1sdp_topology.power_tree; +} + +/******************************************************************************* + * This function returns the core count within the cluster corresponding to + * `mpidr`. + ******************************************************************************/ +unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr) +{ + return n1sdp_topology.plat_cluster_core_count; +} + +/******************************************************************************* + * The array mapping platform core position (implemented by plat_my_core_pos()) + * to the SCMI power domain ID implemented by SCP. + ******************************************************************************/ +const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[PLATFORM_CORE_COUNT] = { + 0, 1, 2, 3}; diff --git a/plat/arm/board/n1sdp/platform.mk b/plat/arm/board/n1sdp/platform.mk new file mode 100644 index 000000000..c9acb4911 --- /dev/null +++ b/plat/arm/board/n1sdp/platform.mk @@ -0,0 +1,67 @@ +# +# Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + + +N1SDP_BASE := plat/arm/board/n1sdp + +INTERCONNECT_SOURCES := ${N1SDP_BASE}/n1sdp_interconnect.c + +PLAT_INCLUDES := -I${N1SDP_BASE}/include + + +N1SDP_CPU_SOURCES := lib/cpus/aarch64/cortex_ares.S + + +N1SDP_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \ + drivers/arm/gic/v3/gicv3_main.c \ + drivers/arm/gic/v3/gicv3_helpers.c \ + plat/common/plat_gicv3.c \ + plat/arm/common/arm_gicv3.c \ + drivers/arm/gic/v3/gic600.c + +PLAT_BL_COMMON_SOURCES := ${N1SDP_BASE}/n1sdp_plat.c \ + ${N1SDP_BASE}/aarch64/n1sdp_helper.S + + +BL31_SOURCES := ${N1SDP_CPU_SOURCES} \ + ${INTERCONNECT_SOURCES} \ + ${N1SDP_GIC_SOURCES} \ + ${N1SDP_BASE}/n1sdp_bl31_setup.c \ + ${N1SDP_BASE}/n1sdp_topology.c \ + ${N1SDP_BASE}/n1sdp_security.c + + +# TF-A not required to load the SCP Images +override CSS_LOAD_SCP_IMAGES := 0 + +# BL1/BL2 Image not a part of the capsule Image for n1sdp +override NEED_BL1 := no +override NEED_BL2 := no +override NEED_BL2U := no + +#TFA for n1sdp starts from BL31 +override RESET_TO_BL31 := 1 + +# 32 bit mode not supported +override CTX_INCLUDE_AARCH32_REGS := 0 + +override ARM_PLAT_MT := 1 + +# Select SCMI/SDS drivers instead of SCPI/BOM driver for communicating with the +# SCP during power management operations and for SCP RAM Firmware transfer. +CSS_USE_SCMI_SDS_DRIVER := 1 + +# System coherency is managed in hardware +HW_ASSISTED_COHERENCY := 1 + +# When building for systems with hardware-assisted coherency, there's no need to +# use USE_COHERENT_MEM. Require that USE_COHERENT_MEM must be set to 0 too. +USE_COHERENT_MEM := 0 +include plat/arm/common/arm_common.mk +include plat/arm/css/common/css_common.mk +include plat/arm/soc/common/soc_css.mk +include plat/arm/board/common/board_common.mk + diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c index 717e96f85..f760e18dc 100644 --- a/plat/arm/common/arm_bl1_setup.c +++ b/plat/arm/common/arm_bl1_setup.c @@ -6,7 +6,6 @@ #include <arch.h> #include <arm_def.h> -#include <arm_xlat_tables.h> #include <assert.h> #include <bl1.h> #include <bl_common.h> @@ -15,6 +14,8 @@ #include <platform_def.h> #include <sp805.h> #include <utils.h> +#include <xlat_tables_compat.h> + #include "../../../bl1/bl1_private.h" /* Weak definitions may be overridden in specific ARM standard platform */ @@ -122,7 +123,7 @@ void arm_bl1_plat_arch_setup(void) {0} }; - arm_setup_page_tables(bl_regions, plat_arm_get_mmap()); + setup_page_tables(bl_regions, plat_arm_get_mmap()); #ifdef AARCH32 enable_mmu_svc_mon(0); #else diff --git a/plat/arm/common/arm_bl2_el3_setup.c b/plat/arm/common/arm_bl2_el3_setup.c index c67ab4914..4f5e6a9e6 100644 --- a/plat/arm/common/arm_bl2_el3_setup.c +++ b/plat/arm/common/arm_bl2_el3_setup.c @@ -79,7 +79,7 @@ void arm_bl2_el3_plat_arch_setup(void) {0} }; - arm_setup_page_tables(bl_regions, plat_arm_get_mmap()); + setup_page_tables(bl_regions, plat_arm_get_mmap()); #ifdef AARCH32 enable_mmu_svc_mon(0); diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c index d31f6dc3c..628a50def 100644 --- a/plat/arm/common/arm_bl2_setup.c +++ b/plat/arm/common/arm_bl2_setup.c @@ -125,7 +125,7 @@ void arm_bl2_plat_arch_setup(void) {0} }; - arm_setup_page_tables(bl_regions, plat_arm_get_mmap()); + setup_page_tables(bl_regions, plat_arm_get_mmap()); #ifdef AARCH32 enable_mmu_svc_mon(0); diff --git a/plat/arm/common/arm_bl2u_setup.c b/plat/arm/common/arm_bl2u_setup.c index b518f0f62..3848aa065 100644 --- a/plat/arm/common/arm_bl2u_setup.c +++ b/plat/arm/common/arm_bl2u_setup.c @@ -80,7 +80,7 @@ void arm_bl2u_plat_arch_setup(void) {0} }; - arm_setup_page_tables(bl_regions, plat_arm_get_mmap()); + setup_page_tables(bl_regions, plat_arm_get_mmap()); #ifdef AARCH32 enable_mmu_svc_mon(0); diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c index e218c2f05..1b05f46e9 100644 --- a/plat/arm/common/arm_bl31_setup.c +++ b/plat/arm/common/arm_bl31_setup.c @@ -16,7 +16,7 @@ #include <platform.h> #include <ras.h> #include <utils.h> -#include <arm_xlat_tables.h> +#include <xlat_tables_compat.h> /* * Placeholder variables for copying the arguments that have been passed to @@ -25,11 +25,13 @@ 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_TB_FW_CONFIG_LIMIT. The reserved page * is required for SOC_FW_CONFIG/TOS_FW_CONFIG passed from BL2. */ CASSERT(BL31_BASE >= ARM_TB_FW_CONFIG_LIMIT, assert_bl31_base_overflows); +#endif /* Weak definitions may be overridden in specific ARM standard platform */ #pragma weak bl31_early_platform_setup2 @@ -38,8 +40,8 @@ CASSERT(BL31_BASE >= ARM_TB_FW_CONFIG_LIMIT, assert_bl31_base_overflows); #pragma weak bl31_plat_get_next_image_ep_info #define MAP_BL31_TOTAL MAP_REGION_FLAT( \ - BL31_BASE, \ - BL31_END - BL31_BASE, \ + BL31_START, \ + BL31_END - BL31_START, \ MT_MEMORY | MT_RW | MT_SECURE) #if RECLAIM_INIT_CODE IMPORT_SYM(unsigned long, __INIT_CODE_START__, BL_INIT_CODE_BASE); @@ -302,7 +304,7 @@ void __init arm_bl31_plat_arch_setup(void) {0} }; - arm_setup_page_tables(bl_regions, plat_arm_get_mmap()); + setup_page_tables(bl_regions, plat_arm_get_mmap()); enable_mmu_el3(0); diff --git a/plat/arm/common/arm_common.c b/plat/arm/common/arm_common.c index a21d189e9..6b1478545 100644 --- a/plat/arm/common/arm_common.c +++ b/plat/arm/common/arm_common.c @@ -5,7 +5,6 @@ */ #include <arch.h> #include <arch_helpers.h> -#include <arm_xlat_tables.h> #include <assert.h> #include <debug.h> #include <mmio.h> @@ -14,6 +13,7 @@ #include <platform_def.h> #include <romlib.h> #include <secure_partition.h> +#include <xlat_tables_compat.h> /* Weak definitions may be overridden in specific ARM standard platform */ #pragma weak plat_get_ns_image_entrypoint @@ -32,42 +32,6 @@ void arm_setup_romlib(void) #endif } -/* - * Set up the page tables for the generic and platform-specific memory regions. - * The size of the Trusted SRAM seen by the BL image must be specified as well - * as an array specifying the generic memory regions which can be; - * - Code section; - * - Read-only data section; - * - Init code section, if applicable - * - Coherent memory region, if applicable. - */ - -void __init arm_setup_page_tables(const mmap_region_t bl_regions[], - const mmap_region_t plat_regions[]) -{ -#if LOG_LEVEL >= LOG_LEVEL_VERBOSE - const mmap_region_t *regions = bl_regions; - - while (regions->size != 0U) { - VERBOSE("Region: 0x%lx - 0x%lx has attributes 0x%x\n", - regions->base_va, - (regions->base_va + regions->size), - regions->attr); - regions++; - } -#endif - /* - * Map the Trusted SRAM with appropriate memory attributes. - * Subsequent mappings will adjust the attributes for specific regions. - */ - mmap_add(bl_regions); - /* Now (re-)map the platform-specific memory regions */ - mmap_add(plat_regions); - - /* Create the page tables to reflect the above mappings */ - init_xlat_tables(); -} - uintptr_t plat_get_ns_image_entrypoint(void) { #ifdef PRELOADED_BL33_BASE diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk index 3fb1eff2d..23777fb7b 100644 --- a/plat/arm/common/arm_common.mk +++ b/plat/arm/common/arm_common.mk @@ -130,6 +130,11 @@ 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) diff --git a/plat/arm/common/arm_gicv3.c b/plat/arm/common/arm_gicv3.c index e9e8a74d9..a43bff3d4 100644 --- a/plat/arm/common/arm_gicv3.c +++ b/plat/arm/common/arm_gicv3.c @@ -10,6 +10,7 @@ #include <plat_arm.h> #include <platform.h> #include <platform_def.h> +#include <utils.h> /****************************************************************************** * The following functions are defined as weak to allow a platform to override @@ -33,10 +34,16 @@ static const interrupt_prop_t arm_interrupt_props[] = { /* * We save and restore the GICv3 context on system suspend. Allocate the - * data in the designated EL3 Secure carve-out memory + * data in the designated EL3 Secure carve-out memory. The `volatile` + * is used to prevent the compiler from removing the gicv3 contexts even + * though the DEFINE_LOAD_SYM_ADDR creates a dummy reference to it. */ -static gicv3_redist_ctx_t rdist_ctx __section("arm_el3_tzc_dram"); -static gicv3_dist_ctx_t dist_ctx __section("arm_el3_tzc_dram"); +static volatile gicv3_redist_ctx_t rdist_ctx __section("arm_el3_tzc_dram"); +static volatile gicv3_dist_ctx_t dist_ctx __section("arm_el3_tzc_dram"); + +/* Define accessor function to get reference to the GICv3 context */ +DEFINE_LOAD_SYM_ADDR(rdist_ctx) +DEFINE_LOAD_SYM_ADDR(dist_ctx) /* * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register @@ -134,6 +141,10 @@ void plat_arm_gic_redistif_off(void) *****************************************************************************/ void plat_arm_gic_save(void) { + gicv3_redist_ctx_t * const rdist_context = + (gicv3_redist_ctx_t *)LOAD_ADDR_OF(rdist_ctx); + gicv3_dist_ctx_t * const dist_context = + (gicv3_dist_ctx_t *)LOAD_ADDR_OF(dist_ctx); /* * If an ITS is available, save its context before @@ -149,10 +160,10 @@ void plat_arm_gic_save(void) * we only need to save the context of the CPU that is issuing * the SYSTEM SUSPEND call, i.e. the current CPU. */ - gicv3_rdistif_save(plat_my_core_pos(), &rdist_ctx); + gicv3_rdistif_save(plat_my_core_pos(), rdist_context); /* Save the GIC Distributor context */ - gicv3_distif_save(&dist_ctx); + gicv3_distif_save(dist_context); /* * From here, all the components of the GIC can be safely powered down @@ -163,8 +174,13 @@ void plat_arm_gic_save(void) void plat_arm_gic_resume(void) { + const gicv3_redist_ctx_t *rdist_context = + (gicv3_redist_ctx_t *)LOAD_ADDR_OF(rdist_ctx); + const gicv3_dist_ctx_t *dist_context = + (gicv3_dist_ctx_t *)LOAD_ADDR_OF(dist_ctx); + /* Restore the GIC Distributor context */ - gicv3_distif_init_restore(&dist_ctx); + gicv3_distif_init_restore(dist_context); /* * Restore the GIC Redistributor and ITS contexts after the @@ -172,7 +188,7 @@ void plat_arm_gic_resume(void) * we only need to restore the context of the CPU that issued * the SYSTEM SUSPEND call. */ - gicv3_rdistif_init_restore(plat_my_core_pos(), &rdist_ctx); + gicv3_rdistif_init_restore(plat_my_core_pos(), rdist_context); /* * If an ITS is available, restore its context after diff --git a/plat/arm/common/arm_sip_svc.c b/plat/arm/common/arm_sip_svc.c index e450c6f94..e482a8945 100644 --- a/plat/arm/common/arm_sip_svc.c +++ b/plat/arm/common/arm_sip_svc.c @@ -58,7 +58,7 @@ static uintptr_t arm_sip_handler(unsigned int smc_fid, /* Validate supplied entry point */ pc = (u_register_t) ((x1 << 32) | (uint32_t) x2); - if (arm_validate_ns_entrypoint(pc)) + if (arm_validate_ns_entrypoint(pc) != 0) SMC_RET1(handle, STATE_SW_E_PARAM); /* diff --git a/plat/arm/common/sp_min/arm_sp_min_setup.c b/plat/arm/common/sp_min/arm_sp_min_setup.c index b8234c186..e151073f7 100644 --- a/plat/arm/common/sp_min/arm_sp_min_setup.c +++ b/plat/arm/common/sp_min/arm_sp_min_setup.c @@ -208,7 +208,7 @@ void sp_min_plat_arch_setup(void) {0} }; - arm_setup_page_tables(bl_regions, plat_arm_get_mmap()); + setup_page_tables(bl_regions, plat_arm_get_mmap()); enable_mmu_svc_mon(0); } diff --git a/plat/arm/common/tsp/arm_tsp_setup.c b/plat/arm/common/tsp/arm_tsp_setup.c index 2d42d8e00..3cf88251f 100644 --- a/plat/arm/common/tsp/arm_tsp_setup.c +++ b/plat/arm/common/tsp/arm_tsp_setup.c @@ -85,6 +85,6 @@ void tsp_plat_arch_setup(void) {0} }; - arm_setup_page_tables(bl_regions, plat_arm_get_mmap()); + setup_page_tables(bl_regions, plat_arm_get_mmap()); enable_mmu_el1(0); } diff --git a/plat/arm/css/common/aarch64/css_helpers.S b/plat/arm/css/common/aarch64/css_helpers.S index 59d920650..5096d8d95 100644 --- a/plat/arm/css/common/aarch64/css_helpers.S +++ b/plat/arm/css/common/aarch64/css_helpers.S @@ -108,7 +108,7 @@ endfunc plat_is_my_cpu_primary func plat_is_my_cpu_primary mov x9, x30 bl plat_my_core_pos - ldr x1, =SCP_BOOT_CFG_ADDR + mov_imm x1, SCP_BOOT_CFG_ADDR ldr x1, [x1] ubfx x1, x1, #PLAT_CSS_PRIMARY_CPU_SHIFT, \ #PLAT_CSS_PRIMARY_CPU_BIT_WIDTH diff --git a/plat/common/plat_bl_common.c b/plat/common/plat_bl_common.c index 264d5180d..4cf1cc573 100644 --- a/plat/common/plat_bl_common.c +++ b/plat/common/plat_bl_common.c @@ -13,6 +13,7 @@ #include <mbedtls_config.h> #endif #include <platform.h> +#include <xlat_tables_compat.h> /* * The following platform functions are weakly defined. The Platforms @@ -72,3 +73,40 @@ int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) return 0; } #endif /* TRUSTED_BOARD_BOOT */ + +/* + * Set up the page tables for the generic and platform-specific memory regions. + * The size of the Trusted SRAM seen by the BL image must be specified as well + * as an array specifying the generic memory regions which can be; + * - Code section; + * - Read-only data section; + * - Init code section, if applicable + * - Coherent memory region, if applicable. + */ + +void __init setup_page_tables(const mmap_region_t *bl_regions, + const mmap_region_t *plat_regions) +{ +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + const mmap_region_t *regions = bl_regions; + + while (regions->size != 0U) { + VERBOSE("Region: 0x%lx - 0x%lx has attributes 0x%x\n", + regions->base_va, + regions->base_va + regions->size, + regions->attr); + regions++; + } +#endif + /* + * Map the Trusted SRAM with appropriate memory attributes. + * Subsequent mappings will adjust the attributes for specific regions. + */ + mmap_add(bl_regions); + + /* Now (re-)map the platform-specific memory regions */ + mmap_add(plat_regions); + + /* Create the page tables to reflect the above mappings */ + init_xlat_tables(); +} diff --git a/plat/hisilicon/poplar/aarch64/poplar_helpers.S b/plat/hisilicon/poplar/aarch64/poplar_helpers.S new file mode 100644 index 000000000..928dbefcc --- /dev/null +++ b/plat/hisilicon/poplar/aarch64/poplar_helpers.S @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include <asm_macros.S> +#include <platform_def.h> + + .globl plat_my_core_pos + .globl poplar_calc_core_pos + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl platform_mem_init + + /* ----------------------------------------------------- + * unsigned int plat_my_core_pos(void) + * This function uses poplar_calc_core_pos() + * definition to get the index of the calling CPU. + * ----------------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + b poplar_calc_core_pos +endfunc plat_my_core_pos + + /* ----------------------------------------------------- + * unsigned int poplar_calc_core_pos(u_register_t mpidr) + * Helper function to calculate the core position. + * With this function: CorePos = (ClusterId * 4) + + * CoreId + * ----------------------------------------------------- + */ +func poplar_calc_core_pos + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret +endfunc poplar_calc_core_pos + + /* --------------------------------------------- + * int plat_crash_console_init(void) + * Function to initialize the crash console + * without a C Runtime to print crash report. + * Clobber list : x0 - x4 + * --------------------------------------------- + */ +func plat_crash_console_init + mov_imm x0, POPLAR_CRASH_UART_BASE + mov_imm x1, POPLAR_CRASH_UART_CLK_IN_HZ + mov_imm x2, POPLAR_CONSOLE_BAUDRATE + b console_pl011_core_init +endfunc plat_crash_console_init + + /* --------------------------------------------- + * int plat_crash_console_putc(int c) + * Function to print a character on the crash + * console without a C Runtime. + * Clobber list : x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_putc + mov_imm x1, POPLAR_CRASH_UART_BASE + b console_pl011_core_putc +endfunc plat_crash_console_putc + + /* --------------------------------------------- + * int plat_crash_console_flush() + * Function to force a write of all buffered + * data that hasn't been output. + * Out : return -1 on error else return 0. + * Clobber list : r0 + * --------------------------------------------- + */ +func plat_crash_console_flush + mov_imm x0, POPLAR_CRASH_UART_BASE + b console_pl011_core_flush +endfunc plat_crash_console_flush + + /* --------------------------------------------------------------------- + * We don't need to carry out any memory initialization on ARM + * platforms. The Secure RAM is accessible straight away. + * --------------------------------------------------------------------- + */ +func platform_mem_init + ret +endfunc platform_mem_init diff --git a/plat/hisilicon/poplar/bl31_plat_setup.c b/plat/hisilicon/poplar/bl31_plat_setup.c index 83803a66a..20a613d5f 100644 --- a/plat/hisilicon/poplar/bl31_plat_setup.c +++ b/plat/hisilicon/poplar/bl31_plat_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -15,13 +15,12 @@ #include <errno.h> #include <generic_delay_timer.h> #include <mmio.h> -#include <plat_arm.h> #include <platform.h> +#include <platform_def.h> #include <stddef.h> #include <string.h> #include "hi3798cv200.h" #include "plat_private.h" -#include "platform_def.h" /* Memory ranges for code and RO data sections */ #define BL31_RO_BASE (unsigned long)(&__RO_START__) @@ -113,8 +112,8 @@ void bl31_platform_setup(void) generic_delay_timer_init(); /* Init GIC distributor and CPU interface */ - plat_arm_gic_driver_init(); - plat_arm_gic_init(); + poplar_gic_driver_init(); + poplar_gic_init(); /* Init security properties of IP blocks */ hisi_tzpc_sec_init(); diff --git a/plat/hisilicon/poplar/include/plat_private.h b/plat/hisilicon/poplar/include/plat_private.h index 845b1bd79..63b7d766f 100644 --- a/plat/hisilicon/poplar/include/plat_private.h +++ b/plat/hisilicon/poplar/include/plat_private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -26,4 +26,11 @@ void plat_configure_mmu_el1(unsigned long total_base, void plat_io_setup(void); +unsigned int poplar_calc_core_pos(u_register_t mpidr); + +void poplar_gic_driver_init(void); +void poplar_gic_init(void); +void poplar_gic_cpuif_enable(void); +void poplar_gic_pcpu_init(void); + #endif /* __PLAT_PRIVATE_H__ */ diff --git a/plat/hisilicon/poplar/include/platform_def.h b/plat/hisilicon/poplar/include/platform_def.h index 99fd99637..6287a76aa 100644 --- a/plat/hisilicon/poplar/include/platform_def.h +++ b/plat/hisilicon/poplar/include/platform_def.h @@ -22,9 +22,9 @@ #define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" #define PLATFORM_LINKER_ARCH aarch64 -#define PLAT_ARM_CRASH_UART_BASE PL011_UART0_BASE -#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PL011_UART0_CLK_IN_HZ -#define ARM_CONSOLE_BAUDRATE PL011_BAUDRATE +#define POPLAR_CRASH_UART_BASE PL011_UART0_BASE +#define POPLAR_CRASH_UART_CLK_IN_HZ PL011_UART0_CLK_IN_HZ +#define POPLAR_CONSOLE_BAUDRATE PL011_BAUDRATE /* Generic platform constants */ #define PLATFORM_STACK_SIZE (0x800) @@ -134,10 +134,10 @@ #define PLAT_MAX_RET_STATE U(1) /* Interrupt controller */ -#define PLAT_ARM_GICD_BASE GICD_BASE -#define PLAT_ARM_GICC_BASE GICC_BASE +#define POPLAR_GICD_BASE GICD_BASE +#define POPLAR_GICC_BASE GICC_BASE -#define PLAT_ARM_G1S_IRQ_PROPS(grp) \ +#define POPLAR_G1S_IRQ_PROPS(grp) \ INTR_PROP_DESC(HISI_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, grp, \ GIC_INTR_CFG_LEVEL), \ INTR_PROP_DESC(HISI_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, grp, \ @@ -165,6 +165,6 @@ INTR_PROP_DESC(HISI_IRQ_SEC_AXI, GIC_HIGHEST_SEC_PRIORITY, grp, \ GIC_INTR_CFG_LEVEL) -#define PLAT_ARM_G0_IRQ_PROPS(grp) +#define POPLAR_G0_IRQ_PROPS(grp) #endif /* PLATFORM_DEF_H */ diff --git a/plat/hisilicon/poplar/plat_pm.c b/plat/hisilicon/poplar/plat_pm.c index e59cac94c..dcbcec4a1 100644 --- a/plat/hisilicon/poplar/plat_pm.c +++ b/plat/hisilicon/poplar/plat_pm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -12,12 +12,11 @@ #include <context_mgmt.h> #include <debug.h> #include <mmio.h> -#include <plat_arm.h> #include <platform.h> +#include <platform_def.h> #include <psci.h> #include "hi3798cv200.h" #include "plat_private.h" -#include "platform_def.h" #define REG_PERI_CPU_RVBARADDR 0xF8A80034 #define REG_PERI_CPU_AARCH_MODE 0xF8A80030 @@ -76,10 +75,10 @@ static void poplar_pwr_domain_on_finish(const psci_power_state_t *target_state) PLAT_MAX_OFF_STATE); /* Enable the gic cpu interface */ - plat_arm_gic_pcpu_init(); + poplar_gic_pcpu_init(); /* Program the gic per-cpu distributor or re-distributor interface */ - plat_arm_gic_cpuif_enable(); + poplar_gic_cpuif_enable(); } static void poplar_pwr_domain_suspend_finish( diff --git a/plat/hisilicon/poplar/plat_topology.c b/plat/hisilicon/poplar/plat_topology.c index 3dd818e03..bb53c6b1f 100644 --- a/plat/hisilicon/poplar/plat_topology.c +++ b/plat/hisilicon/poplar/plat_topology.c @@ -1,13 +1,13 @@ /* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include <arch.h> -#include <plat_arm.h> #include <psci.h> #include "platform_def.h" +#include "plat_private.h" const unsigned char hisi_power_domain_tree_desc[] = { PLATFORM_CLUSTER_COUNT, @@ -27,5 +27,5 @@ int plat_core_pos_by_mpidr(u_register_t mpidr) if ((mpidr & MPIDR_CPU_MASK) >= PLATFORM_CORE_COUNT) return -1; - return plat_arm_calc_core_pos(mpidr); + return poplar_calc_core_pos(mpidr); } diff --git a/plat/hisilicon/poplar/platform.mk b/plat/hisilicon/poplar/platform.mk index 9d2b61700..de262adca 100644 --- a/plat/hisilicon/poplar/platform.mk +++ b/plat/hisilicon/poplar/platform.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -53,7 +53,6 @@ PLAT_PL061_MAX_GPIOS := 104 $(eval $(call add_define,PLAT_PL061_MAX_GPIOS)) PLAT_INCLUDES := -Iplat/hisilicon/poplar/include \ - -Iinclude/plat/arm/common/ \ -Iplat/hisilicon/poplar \ -Iinclude/common/tbbr \ -Iinclude/drivers/synopsys \ @@ -68,10 +67,10 @@ PLAT_BL_COMMON_SOURCES := \ drivers/delay_timer/delay_timer.c \ drivers/arm/pl011/aarch64/pl011_console.S \ drivers/arm/gic/v2/gicv2_main.c \ - plat/arm/common/aarch64/arm_helpers.S \ - plat/arm/common/arm_gicv2.c \ plat/common/plat_gicv2.c \ - plat/hisilicon/poplar/aarch64/platform_common.c + plat/hisilicon/poplar/aarch64/platform_common.c \ + plat/hisilicon/poplar/aarch64/poplar_helpers.S \ + plat/hisilicon/poplar/poplar_gicv2.c BL1_SOURCES += \ lib/cpus/aarch64/cortex_a53.S \ diff --git a/plat/hisilicon/poplar/poplar_gicv2.c b/plat/hisilicon/poplar/poplar_gicv2.c new file mode 100644 index 000000000..1c1be47fb --- /dev/null +++ b/plat/hisilicon/poplar/poplar_gicv2.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <gicv2.h> +#include <platform.h> +#include <platform_def.h> + +/****************************************************************************** + * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0 + * interrupts. + *****************************************************************************/ +static const interrupt_prop_t poplar_interrupt_props[] = { + POPLAR_G1S_IRQ_PROPS(GICV2_INTR_GROUP0), + POPLAR_G0_IRQ_PROPS(GICV2_INTR_GROUP0) +}; + +static unsigned int target_mask_array[PLATFORM_CORE_COUNT]; + +static const gicv2_driver_data_t poplar_gic_data = { + .gicd_base = POPLAR_GICD_BASE, + .gicc_base = POPLAR_GICC_BASE, + .interrupt_props = poplar_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(poplar_interrupt_props), + .target_masks = target_mask_array, + .target_masks_num = ARRAY_SIZE(target_mask_array), +}; + +/****************************************************************************** + * Helper to initialize the GICv2 only driver. + *****************************************************************************/ +void poplar_gic_driver_init(void) +{ + gicv2_driver_init(&poplar_gic_data); +} + +void poplar_gic_init(void) +{ + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_set_pe_target_mask(plat_my_core_pos()); + gicv2_cpuif_enable(); +} + +/****************************************************************************** + * Helper to enable the GICv2 CPU interface + *****************************************************************************/ +void poplar_gic_cpuif_enable(void) +{ + gicv2_cpuif_enable(); +} + +/****************************************************************************** + * Helper to initialize the per cpu distributor interface in GICv2 + *****************************************************************************/ +void poplar_gic_pcpu_init(void) +{ + gicv2_pcpu_distif_init(); + gicv2_set_pe_target_mask(plat_my_core_pos()); +} diff --git a/plat/imx/imx7/warp7/platform.mk b/plat/imx/imx7/warp7/platform.mk index deb4c4115..a77186582 100644 --- a/plat/imx/imx7/warp7/platform.mk +++ b/plat/imx/imx7/warp7/platform.mk @@ -22,7 +22,6 @@ endif # Platform PLAT_INCLUDES := -Idrivers/imx/uart \ -Iinclude/common/tbbr \ - -Iinclude/plat/arm/common/ \ -Iplat/imx/common/include/ \ -Iplat/imx/imx7/warp7/include \ -Idrivers/imx/timer \ diff --git a/plat/layerscape/board/ls1043/platform.mk b/plat/layerscape/board/ls1043/platform.mk index c554ac30d..678205cd3 100644 --- a/plat/layerscape/board/ls1043/platform.mk +++ b/plat/layerscape/board/ls1043/platform.mk @@ -22,7 +22,6 @@ LS1043_SECURITY_SOURCES := plat/layerscape/common/ls_tzc380.c \ plat/layerscape/board/ls1043/ls1043_security.c PLAT_INCLUDES := -Iplat/layerscape/board/ls1043/include \ - -Iinclude/plat/arm/common \ -Iplat/layerscape/common/include \ -Iinclude/drivers/arm \ -Iinclude/lib \ diff --git a/plat/meson/gxbb/aarch64/gxbb_helpers.S b/plat/meson/gxbb/aarch64/gxbb_helpers.S new file mode 100644 index 000000000..760d6c46d --- /dev/null +++ b/plat/meson/gxbb/aarch64/gxbb_helpers.S @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <assert_macros.S> +#include <platform_def.h> + + .globl plat_crash_console_flush + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl platform_mem_init + .globl plat_is_my_cpu_primary + .globl plat_my_core_pos + .globl plat_reset_handler + .globl plat_gxbb_calc_core_pos + + /* ----------------------------------------------------- + * unsigned int plat_my_core_pos(void); + * ----------------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + b plat_gxbb_calc_core_pos +endfunc plat_my_core_pos + + /* ----------------------------------------------------- + * unsigned int plat_gxbb_calc_core_pos(u_register_t mpidr); + * ----------------------------------------------------- + */ +func plat_gxbb_calc_core_pos + and x0, x0, #MPIDR_CPU_MASK + ret +endfunc plat_gxbb_calc_core_pos + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary(void); + * ----------------------------------------------------- + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, #GXBB_PRIMARY_CPU + cset w0, eq + ret +endfunc plat_is_my_cpu_primary + + /* --------------------------------------------- + * void platform_mem_init(void); + * --------------------------------------------- + */ +func platform_mem_init + ret +endfunc platform_mem_init + + /* --------------------------------------------- + * int plat_crash_console_init(void) + * --------------------------------------------- + */ +func plat_crash_console_init + mov_imm x0, GXBB_UART0_AO_BASE + mov_imm x1, GXBB_UART0_AO_CLK_IN_HZ + mov_imm x2, GXBB_UART_BAUDRATE + b console_meson_init +endfunc plat_crash_console_init + + /* --------------------------------------------- + * int plat_crash_console_putc(int c) + * Clobber list : x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_putc + mov_imm x1, GXBB_UART0_AO_BASE + b console_meson_core_putc +endfunc plat_crash_console_putc + + /* --------------------------------------------- + * int plat_crash_console_flush() + * Out : return -1 on error else return 0. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func plat_crash_console_flush + mov_imm x0, GXBB_UART0_AO_BASE + b console_meson_core_flush +endfunc plat_crash_console_flush + + /* --------------------------------------------- + * void plat_reset_handler(void); + * --------------------------------------------- + */ +func plat_reset_handler + ret +endfunc plat_reset_handler diff --git a/plat/meson/gxbb/gxbb_bl31_setup.c b/plat/meson/gxbb/gxbb_bl31_setup.c new file mode 100644 index 000000000..3e176f9a0 --- /dev/null +++ b/plat/meson/gxbb/gxbb_bl31_setup.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <bl_common.h> +#include <gicv2.h> +#include <interrupt_props.h> +#include <platform.h> +#include <platform_def.h> +#include <xlat_mmu_helpers.h> + +#include "gxbb_private.h" + +/* + * Placeholder variables for copying the arguments that have been passed to + * BL31 from BL2. + */ +static entry_point_info_t bl33_image_ep_info; + +/******************************************************************************* + * 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. + ******************************************************************************/ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + assert(type == NON_SECURE); + + next_image_info = &bl33_image_ep_info; + + /* None of the images can have 0x0 as the entrypoint. */ + if (next_image_info->pc != 0U) { + return next_image_info; + } else { + return NULL; + } +} + +/******************************************************************************* + * Perform any BL31 early platform setup. Here is an opportunity to copy + * parameters passed by the calling EL (S-EL1 in BL2 & S-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. + ******************************************************************************/ +struct gxbb_bl31_param { + param_header_t h; + image_info_t *bl31_image_info; + entry_point_info_t *bl32_ep_info; + image_info_t *bl32_image_info; + entry_point_info_t *bl33_ep_info; + image_info_t *bl33_image_info; +}; + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + struct gxbb_bl31_param *from_bl2; + + /* Initialize the console to provide early debug support */ + gxbb_console_init(); + + /* + * In debug builds, we pass a special value in 'arg1' to verify platform + * parameters from BL2 to BL31. In release builds it's not used. + */ + assert(arg1 == GXBB_BL31_PLAT_PARAM_VAL); + + /* Check that params passed from BL2 are not NULL. */ + from_bl2 = (struct gxbb_bl31_param *) arg0; + + /* Check params passed from BL2 are not NULL. */ + assert(from_bl2 != NULL); + assert(from_bl2->h.type == PARAM_BL31); + assert(from_bl2->h.version >= VERSION_1); + + /* + * Copy BL33 entry point information. It is stored in Secure RAM, in + * BL2's address space. + */ + bl33_image_ep_info = *from_bl2->bl33_ep_info; + + if (bl33_image_ep_info.pc == 0U) { + ERROR("BL31: BL33 entrypoint not obtained from BL2\n"); + panic(); + } +} + +void bl31_plat_arch_setup(void) +{ + gxbb_setup_page_tables(); + + enable_mmu_el3(0); +} + +/******************************************************************************* + * GICv2 driver setup information + ******************************************************************************/ +static const interrupt_prop_t gxbb_interrupt_props[] = { + INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), +}; + +static const gicv2_driver_data_t gxbb_gic_data = { + .gicd_base = GXBB_GICD_BASE, + .gicc_base = GXBB_GICC_BASE, + .interrupt_props = gxbb_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(gxbb_interrupt_props), +}; + +void bl31_platform_setup(void) +{ + mhu_secure_init(); + + gicv2_driver_init(&gxbb_gic_data); + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); + + gxbb_thermal_unknown(); +} diff --git a/plat/meson/gxbb/gxbb_common.c b/plat/meson/gxbb/gxbb_common.c new file mode 100644 index 000000000..349d02f9e --- /dev/null +++ b/plat/meson/gxbb/gxbb_common.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <bl_common.h> +#include <debug.h> +#include <ep_info.h> +#include <interrupt_mgmt.h> +#include <meson_console.h> +#include <mmio.h> +#include <platform_def.h> +#include <stdint.h> +#include <xlat_tables_v2.h> + +/******************************************************************************* + * Platform memory map regions + ******************************************************************************/ +#define MAP_NSDRAM0 MAP_REGION_FLAT(GXBB_NSDRAM0_BASE, \ + GXBB_NSDRAM0_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_NSDRAM1 MAP_REGION_FLAT(GXBB_NSDRAM1_BASE, \ + GXBB_NSDRAM1_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_SEC_DEVICE0 MAP_REGION_FLAT(GXBB_SEC_DEVICE0_BASE, \ + GXBB_SEC_DEVICE0_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_SEC_DEVICE1 MAP_REGION_FLAT(GXBB_SEC_DEVICE1_BASE, \ + GXBB_SEC_DEVICE1_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_TZRAM MAP_REGION_FLAT(GXBB_TZRAM_BASE, \ + GXBB_TZRAM_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_SEC_DEVICE2 MAP_REGION_FLAT(GXBB_SEC_DEVICE2_BASE, \ + GXBB_SEC_DEVICE2_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_SEC_DEVICE3 MAP_REGION_FLAT(GXBB_SEC_DEVICE3_BASE, \ + GXBB_SEC_DEVICE3_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +static const mmap_region_t gxbb_mmap[] = { + MAP_NSDRAM0, + MAP_NSDRAM1, + MAP_SEC_DEVICE0, + MAP_SEC_DEVICE1, + MAP_TZRAM, + MAP_SEC_DEVICE2, + MAP_SEC_DEVICE3, + {0} +}; + +/******************************************************************************* + * Per-image regions + ******************************************************************************/ +#define MAP_BL31 MAP_REGION_FLAT(BL31_BASE, \ + BL31_END - BL31_BASE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define MAP_BL_CODE MAP_REGION_FLAT(BL_CODE_BASE, \ + BL_CODE_END - BL_CODE_BASE, \ + MT_CODE | MT_SECURE) + +#define MAP_BL_RO_DATA MAP_REGION_FLAT(BL_RO_DATA_BASE, \ + BL_RO_DATA_END - BL_RO_DATA_BASE, \ + MT_RO_DATA | MT_SECURE) + +#define MAP_BL_COHERENT MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, \ + BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/******************************************************************************* + * Function that sets up the translation tables. + ******************************************************************************/ +void gxbb_setup_page_tables(void) +{ +#if IMAGE_BL31 + const mmap_region_t gxbb_bl_mmap[] = { + MAP_BL31, + MAP_BL_CODE, + MAP_BL_RO_DATA, +#if USE_COHERENT_MEM + MAP_BL_COHERENT, +#endif + {0} + }; +#endif + + mmap_add(gxbb_bl_mmap); + + mmap_add(gxbb_mmap); + + init_xlat_tables(); +} + +/******************************************************************************* + * Function that sets up the console + ******************************************************************************/ +static console_meson_t gxbb_console; + +void gxbb_console_init(void) +{ + int rc = console_meson_register(GXBB_UART0_AO_BASE, + GXBB_UART0_AO_CLK_IN_HZ, + GXBB_UART_BAUDRATE, + &gxbb_console); + if (rc == 0) { + /* + * The crash console doesn't use the multi console API, it uses + * the core console functions directly. It is safe to call panic + * and let it print debug information. + */ + panic(); + } + + console_set_scope(&gxbb_console.console, + CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME); +} + +/******************************************************************************* + * Function that returns the system counter frequency + ******************************************************************************/ +unsigned int plat_get_syscnt_freq2(void) +{ + uint32_t val; + + val = mmio_read_32(GXBB_SYS_CPU_CFG7); + val &= 0xFDFFFFFF; + mmio_write_32(GXBB_SYS_CPU_CFG7, val); + + val = mmio_read_32(GXBB_AO_TIMESTAMP_CNTL); + val &= 0xFFFFFE00; + mmio_write_32(GXBB_AO_TIMESTAMP_CNTL, val); + + return GXBB_OSC24M_CLK_IN_HZ; +} diff --git a/plat/meson/gxbb/gxbb_def.h b/plat/meson/gxbb/gxbb_def.h new file mode 100644 index 000000000..0c73ac082 --- /dev/null +++ b/plat/meson/gxbb/gxbb_def.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GXBB_DEF_H +#define GXBB_DEF_H + +#include <utils_def.h> + +/******************************************************************************* + * System oscillator + ******************************************************************************/ +#define GXBB_OSC24M_CLK_IN_HZ ULL(24000000) /* 24 MHz */ + +/******************************************************************************* + * Memory regions + ******************************************************************************/ +#define GXBB_NSDRAM0_BASE UL(0x01000000) +#define GXBB_NSDRAM0_SIZE UL(0x0F000000) + +#define GXBB_NSDRAM1_BASE UL(0x10000000) +#define GXBB_NSDRAM1_SIZE UL(0x00100000) + +#define BL31_BASE UL(0x10100000) +#define BL31_SIZE UL(0x000C0000) +#define BL31_LIMIT (BL31_BASE + BL31_SIZE) + +/* Shared memory used for SMC services */ +#define GXBB_SHARE_MEM_INPUT_BASE UL(0x100FE000) +#define GXBB_SHARE_MEM_OUTPUT_BASE UL(0x100FF000) + +#define GXBB_SEC_DEVICE0_BASE UL(0xC0000000) +#define GXBB_SEC_DEVICE0_SIZE UL(0x09000000) + +#define GXBB_SEC_DEVICE1_BASE UL(0xD0040000) +#define GXBB_SEC_DEVICE1_SIZE UL(0x00008000) + +#define GXBB_TZRAM_BASE UL(0xD9000000) +#define GXBB_TZRAM_SIZE UL(0x00014000) +/* Top 0xC000 bytes (up to 0xD9020000) used by BL2 */ + +/* Mailboxes */ +#define GXBB_MHU_SECURE_SCP_TO_AP_PAYLOAD UL(0xD9013800) +#define GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD UL(0xD9013A00) +#define GXBB_PSCI_MAILBOX_BASE UL(0xD9013F00) + +#define GXBB_TZROM_BASE UL(0xD9040000) +#define GXBB_TZROM_SIZE UL(0x00010000) + +#define GXBB_SEC_DEVICE2_BASE UL(0xDA000000) +#define GXBB_SEC_DEVICE2_SIZE UL(0x00200000) + +#define GXBB_SEC_DEVICE3_BASE UL(0xDA800000) +#define GXBB_SEC_DEVICE3_SIZE UL(0x00200000) + +/******************************************************************************* + * GIC-400 and interrupt handling related constants + ******************************************************************************/ +#define GXBB_GICD_BASE UL(0xC4301000) +#define GXBB_GICC_BASE UL(0xC4302000) + +#define IRQ_SEC_PHY_TIMER 29 + +#define IRQ_SEC_SGI_0 8 +#define IRQ_SEC_SGI_1 9 +#define IRQ_SEC_SGI_2 10 +#define IRQ_SEC_SGI_3 11 +#define IRQ_SEC_SGI_4 12 +#define IRQ_SEC_SGI_5 13 +#define IRQ_SEC_SGI_6 14 +#define IRQ_SEC_SGI_7 15 + +/******************************************************************************* + * UART definitions + ******************************************************************************/ +#define GXBB_UART0_AO_BASE UL(0xC81004C0) +#define GXBB_UART0_AO_CLK_IN_HZ GXBB_OSC24M_CLK_IN_HZ +#define GXBB_UART_BAUDRATE U(115200) + +/******************************************************************************* + * Memory-mapped I/O Registers + ******************************************************************************/ +#define GXBB_AO_TIMESTAMP_CNTL UL(0xC81000B4) + +#define GXBB_SYS_CPU_CFG7 UL(0xC8834664) + +#define GXBB_AO_RTI_STATUS_REG3 UL(0xDA10001C) + +#define GXBB_HIU_MAILBOX_SET_0 UL(0xDA83C404) +#define GXBB_HIU_MAILBOX_STAT_0 UL(0xDA83C408) +#define GXBB_HIU_MAILBOX_CLR_0 UL(0xDA83C40C) +#define GXBB_HIU_MAILBOX_SET_3 UL(0xDA83C428) +#define GXBB_HIU_MAILBOX_STAT_3 UL(0xDA83C42C) +#define GXBB_HIU_MAILBOX_CLR_3 UL(0xDA83C430) + +/******************************************************************************* + * System Monitor Call IDs and arguments + ******************************************************************************/ +#define GXBB_SM_GET_SHARE_MEM_INPUT_BASE U(0x82000020) +#define GXBB_SM_GET_SHARE_MEM_OUTPUT_BASE U(0x82000021) + +#define GXBB_SM_EFUSE_READ U(0x82000030) +#define GXBB_SM_EFUSE_USER_MAX U(0x82000033) + +#define GXBB_SM_JTAG_ON U(0x82000040) +#define GXBB_SM_JTAG_OFF U(0x82000041) + +#define GXBB_JTAG_STATE_ON U(0) +#define GXBB_JTAG_STATE_OFF U(1) + +#define GXBB_JTAG_M3_AO U(0) +#define GXBB_JTAG_M3_EE U(1) +#define GXBB_JTAG_A53_AO U(2) +#define GXBB_JTAG_A53_EE U(3) + +#endif /* GXBB_DEF_H */ diff --git a/plat/meson/gxbb/gxbb_efuse.c b/plat/meson/gxbb/gxbb_efuse.c new file mode 100644 index 000000000..edea5426c --- /dev/null +++ b/plat/meson/gxbb/gxbb_efuse.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdint.h> + +#include "gxbb_private.h" + +#define EFUSE_BASE 0x140 +#define EFUSE_SIZE 0xC0 + +uint64_t gxbb_efuse_read(void *dst, uint32_t offset, uint32_t size) +{ + if ((uint64_t)(offset + size) > (uint64_t)EFUSE_SIZE) + return 0; + + return scpi_efuse_read(dst, offset + EFUSE_BASE, size); +} + +uint64_t gxbb_efuse_user_max(void) +{ + return EFUSE_SIZE; +} diff --git a/plat/meson/gxbb/gxbb_mhu.c b/plat/meson/gxbb/gxbb_mhu.c new file mode 100644 index 000000000..78b895c52 --- /dev/null +++ b/plat/meson/gxbb/gxbb_mhu.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <bakery_lock.h> +#include <mmio.h> +#include <platform_def.h> + +static DEFINE_BAKERY_LOCK(mhu_lock); + +void mhu_secure_message_start(void) +{ + bakery_lock_get(&mhu_lock); + + while (mmio_read_32(GXBB_HIU_MAILBOX_STAT_3) != 0) + ; +} + +void mhu_secure_message_send(uint32_t msg) +{ + mmio_write_32(GXBB_HIU_MAILBOX_SET_3, msg); + + while (mmio_read_32(GXBB_HIU_MAILBOX_STAT_3) != 0) + ; +} + +uint32_t mhu_secure_message_wait(void) +{ + uint32_t val; + + do { + val = mmio_read_32(GXBB_HIU_MAILBOX_STAT_0); + } while (val == 0); + + return val; +} + +void mhu_secure_message_end(void) +{ + mmio_write_32(GXBB_HIU_MAILBOX_CLR_0, 0xFFFFFFFF); + + bakery_lock_release(&mhu_lock); +} + +void mhu_secure_init(void) +{ + bakery_lock_init(&mhu_lock); + + mmio_write_32(GXBB_HIU_MAILBOX_CLR_3, 0xFFFFFFFF); +} diff --git a/plat/meson/gxbb/gxbb_pm.c b/plat/meson/gxbb/gxbb_pm.c new file mode 100644 index 000000000..930b5e168 --- /dev/null +++ b/plat/meson/gxbb/gxbb_pm.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <assert.h> +#include <console.h> +#include <debug.h> +#include <errno.h> +#include <gicv2.h> +#include <mmio.h> +#include <platform.h> +#include <platform_def.h> +#include <psci.h> + +#include "gxbb_private.h" + +#define SCPI_POWER_ON 0 +#define SCPI_POWER_RETENTION 1 +#define SCPI_POWER_OFF 3 + +#define SCPI_SYSTEM_SHUTDOWN 0 +#define SCPI_SYSTEM_REBOOT 1 + +static uintptr_t gxbb_sec_entrypoint; +static volatile uint32_t gxbb_cpu0_go; + +static void gxbb_program_mailbox(u_register_t mpidr, uint64_t value) +{ + unsigned int core = plat_gxbb_calc_core_pos(mpidr); + uintptr_t cpu_mailbox_addr = GXBB_PSCI_MAILBOX_BASE + (core << 4); + + mmio_write_64(cpu_mailbox_addr, value); + flush_dcache_range(cpu_mailbox_addr, sizeof(uint64_t)); +} + +static void __dead2 gxbb_system_reset(void) +{ + INFO("BL31: PSCI_SYSTEM_RESET\n"); + + uint32_t status = mmio_read_32(GXBB_AO_RTI_STATUS_REG3); + + NOTICE("BL31: Reboot reason: 0x%x\n", status); + + status &= 0xFFFF0FF0; + + console_flush(); + + mmio_write_32(GXBB_AO_RTI_STATUS_REG3, status); + + int ret = scpi_sys_power_state(SCPI_SYSTEM_REBOOT); + + if (ret != 0) { + ERROR("BL31: PSCI_SYSTEM_RESET: SCP error: %u\n", ret); + panic(); + } + + wfi(); + + ERROR("BL31: PSCI_SYSTEM_RESET: Operation not handled\n"); + panic(); +} + +static void __dead2 gxbb_system_off(void) +{ + INFO("BL31: PSCI_SYSTEM_OFF\n"); + + unsigned int ret = scpi_sys_power_state(SCPI_SYSTEM_SHUTDOWN); + + if (ret != 0) { + ERROR("BL31: PSCI_SYSTEM_OFF: SCP error %u\n", ret); + panic(); + } + + gxbb_program_mailbox(read_mpidr_el1(), 0); + + wfi(); + + ERROR("BL31: PSCI_SYSTEM_OFF: Operation not handled\n"); + panic(); +} + +static int32_t gxbb_pwr_domain_on(u_register_t mpidr) +{ + unsigned int core = plat_gxbb_calc_core_pos(mpidr); + + /* CPU0 can't be turned OFF, emulate it with a WFE loop */ + if (core == GXBB_PRIMARY_CPU) { + VERBOSE("BL31: Releasing CPU0 from wait loop...\n"); + + gxbb_cpu0_go = 1; + flush_dcache_range((uintptr_t)&gxbb_cpu0_go, sizeof(gxbb_cpu0_go)); + dsb(); + isb(); + + sev(); + + return PSCI_E_SUCCESS; + } + + gxbb_program_mailbox(mpidr, gxbb_sec_entrypoint); + scpi_set_css_power_state(mpidr, + SCPI_POWER_ON, SCPI_POWER_ON, SCPI_POWER_ON); + dmbsy(); + sev(); + + return PSCI_E_SUCCESS; +} + +static void gxbb_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + unsigned int core = plat_gxbb_calc_core_pos(read_mpidr_el1()); + + assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] == + PLAT_LOCAL_STATE_OFF); + + if (core == GXBB_PRIMARY_CPU) { + gxbb_cpu0_go = 0; + flush_dcache_range((uintptr_t)&gxbb_cpu0_go, sizeof(gxbb_cpu0_go)); + dsb(); + isb(); + } + + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} + +static void gxbb_pwr_domain_off(const psci_power_state_t *target_state) +{ + u_register_t mpidr = read_mpidr_el1(); + unsigned int core = plat_gxbb_calc_core_pos(mpidr); + uintptr_t addr = GXBB_PSCI_MAILBOX_BASE + 8 + (core << 4); + + mmio_write_32(addr, 0xFFFFFFFF); + flush_dcache_range(addr, sizeof(uint32_t)); + + gicv2_cpuif_disable(); + + /* CPU0 can't be turned OFF, emulate it with a WFE loop */ + if (core == GXBB_PRIMARY_CPU) + return; + + scpi_set_css_power_state(mpidr, + SCPI_POWER_OFF, SCPI_POWER_ON, SCPI_POWER_ON); +} + +static void __dead2 gxbb_pwr_domain_pwr_down_wfi(const psci_power_state_t + *target_state) +{ + unsigned int core = plat_gxbb_calc_core_pos(read_mpidr_el1()); + + /* CPU0 can't be turned OFF, emulate it with a WFE loop */ + if (core == GXBB_PRIMARY_CPU) { + VERBOSE("BL31: CPU0 entering wait loop...\n"); + + while (gxbb_cpu0_go == 0) + wfe(); + + VERBOSE("BL31: CPU0 resumed.\n"); + + write_rmr_el3(RMR_EL3_RR_BIT | RMR_EL3_AA64_BIT); + } + + dsbsy(); + + for (;;) + wfi(); +} + +/******************************************************************************* + * Platform handlers and setup function. + ******************************************************************************/ +static const plat_psci_ops_t gxbb_ops = { + .pwr_domain_on = gxbb_pwr_domain_on, + .pwr_domain_on_finish = gxbb_pwr_domain_on_finish, + .pwr_domain_off = gxbb_pwr_domain_off, + .pwr_domain_pwr_down_wfi = gxbb_pwr_domain_pwr_down_wfi, + .system_off = gxbb_system_off, + .system_reset = gxbb_system_reset, +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + gxbb_sec_entrypoint = sec_entrypoint; + *psci_ops = &gxbb_ops; + gxbb_cpu0_go = 0; + return 0; +} diff --git a/plat/meson/gxbb/gxbb_private.h b/plat/meson/gxbb/gxbb_private.h new file mode 100644 index 000000000..910a42c1c --- /dev/null +++ b/plat/meson/gxbb/gxbb_private.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GXBB_PRIVATE_H +#define GXBB_PRIVATE_H + +#include <stdint.h> + +/* Utility functions */ +unsigned int plat_gxbb_calc_core_pos(u_register_t mpidr); +void gxbb_console_init(void); +void gxbb_setup_page_tables(void); + +/* MHU functions */ +void mhu_secure_message_start(void); +void mhu_secure_message_send(uint32_t msg); +uint32_t mhu_secure_message_wait(void); +void mhu_secure_message_end(void); +void mhu_secure_init(void); + +/* SCPI functions */ +void scpi_set_css_power_state(u_register_t mpidr, uint32_t cpu_state, + uint32_t cluster_state, uint32_t css_state); +uint32_t scpi_sys_power_state(uint64_t system_state); +void scpi_jtag_set_state(uint32_t state, uint8_t select); +uint32_t scpi_efuse_read(void *dst, uint32_t base, uint32_t size); +void scpi_unknown_thermal(uint32_t arg0, uint32_t arg1, + uint32_t arg2, uint32_t arg3); + +/* Peripherals */ +void gxbb_thermal_unknown(void); +uint64_t gxbb_efuse_read(void *dst, uint32_t offset, uint32_t size); +uint64_t gxbb_efuse_user_max(void); + +#endif /* GXBB_PRIVATE_H */ diff --git a/plat/meson/gxbb/gxbb_scpi.c b/plat/meson/gxbb/gxbb_scpi.c new file mode 100644 index 000000000..2390bcad8 --- /dev/null +++ b/plat/meson/gxbb/gxbb_scpi.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <mmio.h> +#include <platform.h> +#include <platform_def.h> +#include <string.h> + +#include "gxbb_private.h" + +#define SIZE_SHIFT 20 +#define SIZE_MASK 0x1FF + +/* + * Note: The Amlogic SCP firmware uses the legacy SCPI protocol. + */ +#define SCPI_CMD_SET_CSS_POWER_STATE 0x04 +#define SCPI_CMD_SET_SYS_POWER_STATE 0x08 + +#define SCPI_CMD_JTAG_SET_STATE 0xC0 +#define SCPI_CMD_EFUSE_READ 0xC2 + +static inline uint32_t scpi_cmd(uint32_t command, uint32_t size) +{ + return command | (size << SIZE_SHIFT); +} + +void scpi_secure_message_send(uint32_t command, uint32_t size) +{ + mhu_secure_message_send(scpi_cmd(command, size)); +} + +uint32_t scpi_secure_message_receive(void **message_out, size_t *size_out) +{ + uint32_t response = mhu_secure_message_wait(); + + size_t size = (response >> SIZE_SHIFT) & SIZE_MASK; + + response &= ~(SIZE_MASK << SIZE_SHIFT); + + if (size_out != NULL) + *size_out = size; + + if (message_out != NULL) + *message_out = (void *)GXBB_MHU_SECURE_SCP_TO_AP_PAYLOAD; + + return response; +} + +void scpi_set_css_power_state(u_register_t mpidr, uint32_t cpu_state, + uint32_t cluster_state, uint32_t css_state) +{ + uint32_t state = (mpidr & 0x0F) | /* CPU ID */ + ((mpidr & 0xF00) >> 4) | /* Cluster ID */ + (cpu_state << 8) | + (cluster_state << 12) | + (css_state << 16); + + mhu_secure_message_start(); + mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD, state); + mhu_secure_message_send(scpi_cmd(SCPI_CMD_SET_CSS_POWER_STATE, 4)); + mhu_secure_message_wait(); + mhu_secure_message_end(); +} + +uint32_t scpi_sys_power_state(uint64_t system_state) +{ + uint32_t *response; + size_t size; + + mhu_secure_message_start(); + mmio_write_8(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD, system_state); + mhu_secure_message_send(scpi_cmd(SCPI_CMD_SET_SYS_POWER_STATE, 1)); + scpi_secure_message_receive((void *)&response, &size); + mhu_secure_message_end(); + + return *response; +} + +void scpi_jtag_set_state(uint32_t state, uint8_t select) +{ + assert(state <= GXBB_JTAG_STATE_OFF); + + if (select > GXBB_JTAG_A53_EE) { + WARN("BL31: Invalid JTAG select (0x%x).\n", select); + return; + } + + mhu_secure_message_start(); + mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD, + (state << 8) | (uint32_t)select); + mhu_secure_message_send(scpi_cmd(SCPI_CMD_JTAG_SET_STATE, 4)); + mhu_secure_message_wait(); + mhu_secure_message_end(); +} + +uint32_t scpi_efuse_read(void *dst, uint32_t base, uint32_t size) +{ + uint32_t *response; + size_t resp_size; + + if (size > 0x1FC) + return 0; + + mhu_secure_message_start(); + mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD, base); + mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD + 4, size); + mhu_secure_message_send(scpi_cmd(SCPI_CMD_EFUSE_READ, 8)); + scpi_secure_message_receive((void *)&response, &resp_size); + mhu_secure_message_end(); + + /* + * response[0] is the size of the response message. + * response[1 ... N] are the contents. + */ + if (*response != 0) + memcpy(dst, response + 1, *response); + + return *response; +} + +void scpi_unknown_thermal(uint32_t arg0, uint32_t arg1, + uint32_t arg2, uint32_t arg3) +{ + mhu_secure_message_start(); + mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0x0, arg0); + mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0x4, arg1); + mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0x8, arg2); + mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0xC, arg3); + mhu_secure_message_send(scpi_cmd(0xC3, 16)); + mhu_secure_message_wait(); + mhu_secure_message_end(); +} diff --git a/plat/meson/gxbb/gxbb_sip_svc.c b/plat/meson/gxbb/gxbb_sip_svc.c new file mode 100644 index 000000000..82ed44935 --- /dev/null +++ b/plat/meson/gxbb/gxbb_sip_svc.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <debug.h> +#include <mmio.h> +#include <platform_def.h> +#include <runtime_svc.h> +#include <stdint.h> + +#include "gxbb_private.h" + +/******************************************************************************* + * This function is responsible for handling all SiP calls + ******************************************************************************/ +static uintptr_t gxbb_sip_handler(uint32_t smc_fid, + u_register_t x1, u_register_t x2, + u_register_t x3, u_register_t x4, + void *cookie, void *handle, + u_register_t flags) +{ + switch (smc_fid) { + + case GXBB_SM_GET_SHARE_MEM_INPUT_BASE: + SMC_RET1(handle, GXBB_SHARE_MEM_INPUT_BASE); + + case GXBB_SM_GET_SHARE_MEM_OUTPUT_BASE: + SMC_RET1(handle, GXBB_SHARE_MEM_OUTPUT_BASE); + + case GXBB_SM_EFUSE_READ: + { + void *dst = (void *)GXBB_SHARE_MEM_OUTPUT_BASE; + uint64_t ret = gxbb_efuse_read(dst, (uint32_t)x1, x2); + + SMC_RET1(handle, ret); + } + case GXBB_SM_EFUSE_USER_MAX: + SMC_RET1(handle, gxbb_efuse_user_max()); + + case GXBB_SM_JTAG_ON: + scpi_jtag_set_state(GXBB_JTAG_STATE_ON, x1); + SMC_RET1(handle, 0); + + case GXBB_SM_JTAG_OFF: + scpi_jtag_set_state(GXBB_JTAG_STATE_OFF, x1); + SMC_RET1(handle, 0); + + default: + ERROR("BL31: Unhandled SIP SMC: 0x%08x\n", smc_fid); + break; + } + + SMC_RET1(handle, SMC_UNK); +} + +DECLARE_RT_SVC( + gxbb_sip_handler, + + OEN_SIP_START, + OEN_SIP_END, + SMC_TYPE_FAST, + NULL, + gxbb_sip_handler +); diff --git a/plat/meson/gxbb/gxbb_thermal.c b/plat/meson/gxbb/gxbb_thermal.c new file mode 100644 index 000000000..b6048eee4 --- /dev/null +++ b/plat/meson/gxbb/gxbb_thermal.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdint.h> + +#include "gxbb_private.h" + +static int32_t modules_initialized = -1; + +/******************************************************************************* + * Unknown commands related to something thermal-related + ******************************************************************************/ +void gxbb_thermal_unknown(void) +{ + uint16_t ret; + + if (modules_initialized == -1) { + scpi_efuse_read(&ret, 0, 2); + modules_initialized = ret; + } + + scpi_unknown_thermal(10, 2, /* thermal */ + 13, 1); /* thermalver */ +} diff --git a/plat/meson/gxbb/gxbb_topology.c b/plat/meson/gxbb/gxbb_topology.c new file mode 100644 index 000000000..49bb2dcad --- /dev/null +++ b/plat/meson/gxbb/gxbb_topology.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <platform_def.h> +#include <stdint.h> + +#include "gxbb_private.h" + +/* The power domain tree descriptor */ +static unsigned char power_domain_tree_desc[] = { + /* Number of root nodes */ + PLATFORM_CLUSTER_COUNT, + /* Number of children for the first node */ + PLATFORM_CLUSTER0_CORE_COUNT +}; + +/******************************************************************************* + * This function returns the ARM default topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return power_domain_tree_desc; +} + +/******************************************************************************* + * This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + ******************************************************************************/ +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 = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + + if (cluster_id >= PLATFORM_CLUSTER_COUNT) + return -1; + + if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) + return -1; + + return plat_gxbb_calc_core_pos(mpidr); +} diff --git a/plat/meson/gxbb/include/plat_macros.S b/plat/meson/gxbb/include/plat_macros.S new file mode 100644 index 000000000..948b5f98f --- /dev/null +++ b/plat/meson/gxbb/include/plat_macros.S @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include <gicv2.h> +#include <platform_def.h> + +.section .rodata.gic_reg_name, "aS" + +gicc_regs: + .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", "" +gicd_pend_reg: + .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n" +newline: + .asciz "\n" +spacer: + .asciz ":\t\t0x" + + /* --------------------------------------------- + * The below required platform porting macro + * prints out relevant GIC and CCI registers + * whenever an unhandled exception is taken in + * BL31. + * Clobbers: x0 - x10, x16, x17, sp + * --------------------------------------------- + */ + .macro plat_crash_print_regs + + /* GICC registers */ + + mov_imm x17, GXBB_GICC_BASE + + adr x6, gicc_regs + ldr w8, [x17, #GICC_HPPIR] + ldr w9, [x17, #GICC_AHPPIR] + ldr w10, [x17, #GICC_CTLR] + bl str_in_crash_buf_print + + /* GICD registers */ + + mov_imm x16, GXBB_GICD_BASE + + add x7, x16, #GICD_ISPENDR + adr x4, gicd_pend_reg + bl asm_print_str + +gicd_ispendr_loop: + sub x4, x7, x16 + cmp x4, #0x280 + b.eq exit_print_gic_regs + bl asm_print_hex + + adr x4, spacer + bl asm_print_str + + ldr x4, [x7], #8 + bl asm_print_hex + + adr x4, newline + bl asm_print_str + b gicd_ispendr_loop +exit_print_gic_regs: + + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/plat/meson/gxbb/include/platform_def.h b/plat/meson/gxbb/include/platform_def.h new file mode 100644 index 000000000..a85637fe2 --- /dev/null +++ b/plat/meson/gxbb/include/platform_def.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <arch.h> +#include <utils_def.h> + +#include "../gxbb_def.h" + +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +/* Special value used to verify platform parameters from BL2 to BL31 */ +#define GXBB_BL31_PLAT_PARAM_VAL ULL(0x0F1E2D3C4B5A6978) + +#define PLATFORM_STACK_SIZE UL(0x1000) + +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER +#define PLATFORM_CORE_COUNT PLATFORM_CLUSTER0_CORE_COUNT + +#define GXBB_PRIMARY_CPU U(0) + +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1 +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(2) + +/* 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 power-down. Valid for CPU and cluster power domains. */ +#define PLAT_LOCAL_STATE_OFF U(2) + +/* + * Macros used to parse state information from State-ID if it is using the + * recommended encoding for State-ID. + */ +#define PLAT_LOCAL_PSTATE_WIDTH U(4) +#define PLAT_LOCAL_PSTATE_MASK ((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1) + +/* + * 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. + */ +#define CACHE_WRITEBACK_SHIFT U(6) +#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT) + +/* Memory-related defines */ +#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32) + +#define MAX_MMAP_REGIONS 12 +#define MAX_XLAT_TABLES 5 + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/meson/gxbb/platform.mk b/plat/meson/gxbb/platform.mk new file mode 100644 index 000000000..e6f5ae489 --- /dev/null +++ b/plat/meson/gxbb/platform.mk @@ -0,0 +1,78 @@ +# +# Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include lib/xlat_tables_v2/xlat_tables.mk + +PLAT_INCLUDES := -Iinclude/drivers/meson/ \ + -Iplat/meson/gxbb/include + +GXBB_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \ + drivers/arm/gic/v2/gicv2_main.c \ + drivers/arm/gic/v2/gicv2_helpers.c \ + plat/common/plat_gicv2.c + +PLAT_BL_COMMON_SOURCES := drivers/console/aarch64/multi_console.S \ + drivers/meson/console/aarch64/meson_console.S \ + plat/meson/gxbb/gxbb_common.c \ + plat/meson/gxbb/gxbb_topology.c \ + ${XLAT_TABLES_LIB_SRCS} + +BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \ + plat/common/plat_psci_common.c \ + plat/meson/gxbb/aarch64/gxbb_helpers.S \ + plat/meson/gxbb/gxbb_bl31_setup.c \ + plat/meson/gxbb/gxbb_efuse.c \ + plat/meson/gxbb/gxbb_mhu.c \ + plat/meson/gxbb/gxbb_pm.c \ + plat/meson/gxbb/gxbb_scpi.c \ + plat/meson/gxbb/gxbb_sip_svc.c \ + plat/meson/gxbb/gxbb_thermal.c \ + ${GXBB_GIC_SOURCES} + +# Tune compiler for Cortex-A53 +ifeq ($(notdir $(CC)),armclang) + TF_CFLAGS_aarch64 += -mcpu=cortex-a53 +else ifneq ($(findstring clang,$(notdir $(CC))),) + TF_CFLAGS_aarch64 += -mcpu=cortex-a53 +else + TF_CFLAGS_aarch64 += -mtune=cortex-a53 +endif + +# Build config flags +# ------------------ + +# Enable all errata workarounds for Cortex-A53 +ERRATA_A53_826319 := 1 +ERRATA_A53_835769 := 1 +ERRATA_A53_836870 := 1 +ERRATA_A53_843419 := 1 +ERRATA_A53_855873 := 1 + +WORKAROUND_CVE_2017_5715 := 0 + +# Have different sections for code and rodata +SEPARATE_CODE_AND_RODATA := 1 + +# Use Coherent memory +USE_COHERENT_MEM := 1 + +# Use multi console API +MULTI_CONSOLE_API := 1 + +# Verify build config +# ------------------- + +ifneq (${MULTI_CONSOLE_API}, 1) + $(error Error: gxbb needs MULTI_CONSOLE_API=1) +endif + +ifneq (${RESET_TO_BL31}, 0) + $(error Error: gxbb needs RESET_TO_BL31=0) +endif + +ifeq (${ARCH},aarch32) + $(error Error: AArch32 not supported on gxbb) +endif diff --git a/plat/qemu/platform.mk b/plat/qemu/platform.mk index 9167c9fcf..982886a93 100644 --- a/plat/qemu/platform.mk +++ b/plat/qemu/platform.mk @@ -38,24 +38,12 @@ ifeq (${ARM_ARCH_MAJOR},8) PLAT_INCLUDES += -Iinclude/plat/arm/common/${ARCH} endif -# 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)) - - PLAT_BL_COMMON_SOURCES := plat/qemu/qemu_common.c \ plat/qemu/qemu_console.c \ drivers/arm/pl011/${ARCH}/pl011_console.S \ -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 ifneq (${TRUSTED_BOARD_BOOT},0) diff --git a/plat/qemu/qemu_common.c b/plat/qemu/qemu_common.c index 376ff2f11..43a3f7012 100644 --- a/plat/qemu/qemu_common.c +++ b/plat/qemu/qemu_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -7,7 +7,8 @@ #include <arch_helpers.h> #include <bl_common.h> #include <platform_def.h> -#include <arm_xlat_tables.h> +#include <xlat_tables_v2.h> + #include "qemu_private.h" #define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \ diff --git a/plat/ti/k3/common/k3_bl31_setup.c b/plat/ti/k3/common/k3_bl31_setup.c index f84b9d449..e438dc36c 100644 --- a/plat/ti/k3/common/k3_bl31_setup.c +++ b/plat/ti/k3/common/k3_bl31_setup.c @@ -108,7 +108,7 @@ void bl31_plat_arch_setup(void) {0} }; - arm_setup_page_tables(bl_regions, plat_arm_get_mmap()); + setup_page_tables(bl_regions, plat_arm_get_mmap()); enable_mmu_el3(0); } diff --git a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c index a14388f56..01634500a 100644 --- a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c +++ b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -193,6 +193,6 @@ void bl31_plat_arch_setup(void) {0} }; - arm_setup_page_tables(bl_regions, plat_arm_get_mmap()); + setup_page_tables(bl_regions, plat_arm_get_mmap()); enable_mmu_el3(0); } diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk index 33859ee5e..35c8983cd 100644 --- a/plat/xilinx/zynqmp/platform.mk +++ b/plat/xilinx/zynqmp/platform.mk @@ -16,10 +16,6 @@ ENABLE_SVE_FOR_NS := 0 WORKAROUND_CVE_2017_5715 := 0 -ARM_XLAT_TABLES_LIB_V1 := 1 -$(eval $(call assert_boolean,ARM_XLAT_TABLES_LIB_V1)) -$(eval $(call add_define,ARM_XLAT_TABLES_LIB_V1)) - ifdef ZYNQMP_ATF_MEM_BASE $(eval $(call add_define,ZYNQMP_ATF_MEM_BASE)) diff --git a/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c b/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c index 52d4bf8cc..a27f34b45 100644 --- a/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c +++ b/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -57,6 +57,6 @@ void tsp_plat_arch_setup(void) {0} }; - arm_setup_page_tables(bl_regions, plat_arm_get_mmap()); + setup_page_tables(bl_regions, plat_arm_get_mmap()); enable_mmu_el1(0); } diff --git a/readme.rst b/readme.rst index f2a7a0007..e7fbfb430 100644 --- a/readme.rst +++ b/readme.rst @@ -193,6 +193,7 @@ All the above platforms have been tested with `Linaro Release 18.04`_. This release also contains the following platform support: - Allwinner sun50i_64 and sun50i_h6 +- Amlogic Meson S905 (GXBB) - ARM SGI-575 and SGM-775 - HiKey, HiKey960 and Poplar boards - Marvell Armada 8K diff --git a/services/std_svc/sdei/sdei_private.h b/services/std_svc/sdei/sdei_private.h index f5197c616..821266740 100644 --- a/services/std_svc/sdei/sdei_private.h +++ b/services/std_svc/sdei/sdei_private.h @@ -8,6 +8,7 @@ #define SDEI_PRIVATE_H #include <arch_helpers.h> +#include <context.h> #include <context_mgmt.h> #include <debug.h> #include <errno.h> |