diff options
Diffstat (limited to 'plat')
131 files changed, 3840 insertions, 529 deletions
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/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h index 0e5c6d9ac..d4a77f027 100644 --- a/plat/arm/board/juno/include/platform_def.h +++ b/plat/arm/board/juno/include/platform_def.h @@ -142,7 +142,7 @@ # define PLAT_ARM_MAX_BL2_SIZE 0x1C000 #endif #else -# define PLAT_ARM_MAX_BL2_SIZE 0xE000 +# define PLAT_ARM_MAX_BL2_SIZE 0xF000 #endif /* 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/juno/juno_topology.c b/plat/arm/board/juno/juno_topology.c index 72bb92e00..6d8fc05ce 100644 --- a/plat/arm/board/juno/juno_topology.c +++ b/plat/arm/board/juno/juno_topology.c @@ -9,6 +9,21 @@ #include <plat_arm.h> #include <platform.h> #include "juno_def.h" +#include "../../css/drivers/scmi/scmi.h" +#include "../../css/drivers/mhu/css_mhu_doorbell.h" + +static scmi_channel_plat_info_t juno_scmi_plat_info = { + .scmi_mbx_mem = CSS_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 &juno_scmi_plat_info; +} /* * On Juno, the system power level is the highest power level. 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/css/sgi/fdts/sgi575.dts b/plat/arm/board/n1sdp/n1sdp_security.c index be9920cbc..d2a187ba1 100644 --- a/plat/arm/css/sgi/fdts/sgi575.dts +++ b/plat/arm/board/n1sdp/n1sdp_security.c @@ -4,8 +4,9 @@ * SPDX-License-Identifier: BSD-3-Clause */ -/dts-v1/; -/ { - /* compatible string */ - compatible = "arm,sgi575"; -}; +/* + * 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/board/sgi575/fdts/sgi575.dts b/plat/arm/board/sgi575/fdts/sgi575.dts new file mode 100644 index 000000000..1e1ea14b0 --- /dev/null +++ b/plat/arm/board/sgi575/fdts/sgi575.dts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; +/ { + /* compatible string */ + compatible = "arm,sgi575"; + + /* + * Place holder for system-id node with default values. The + * value of platform-id and config-id will be set to the + * correct values during the BL2 stage of boot. + */ + system-id { + platform-id = <0x0>; + config-id = <0x0>; + }; +}; diff --git a/plat/arm/css/sgi/fdts/sgi575_tb_fw_config.dts b/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts index 315fa6999..315fa6999 100644 --- a/plat/arm/css/sgi/fdts/sgi575_tb_fw_config.dts +++ b/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts diff --git a/plat/arm/board/sgi575/include/platform_def.h b/plat/arm/board/sgi575/include/platform_def.h new file mode 100644 index 000000000..1870fc78a --- /dev/null +++ b/plat/arm/board/sgi575/include/platform_def.h @@ -0,0 +1,18 @@ +/* + * 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 <sgi_base_platform_def.h> + +#define PLAT_ARM_CLUSTER_COUNT 2 +#define CSS_SGI_MAX_CPUS_PER_CLUSTER 4 +#define CSS_SGI_MAX_PE_PER_CPU 1 + +#define PLAT_CSS_MHU_BASE 0x45000000 + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/arm/board/sgi575/platform.mk b/plat/arm/board/sgi575/platform.mk index 078f393c9..8df8b1292 100644 --- a/plat/arm/board/sgi575/platform.mk +++ b/plat/arm/board/sgi575/platform.mk @@ -6,9 +6,31 @@ include plat/arm/css/sgi/sgi-common.mk +SGI575_BASE = plat/arm/board/sgi575 + +PLAT_INCLUDES += -I${SGI575_BASE}/include/ + +SGI_CPU_SOURCES := lib/cpus/aarch64/cortex_a75.S + +BL1_SOURCES += ${SGI_CPU_SOURCES} + BL2_SOURCES += lib/utils/mem_region.c \ plat/arm/common/arm_nor_psci_mem_protect.c -BL31_SOURCES += drivers/cfi/v2m/v2m_flash.c \ +BL31_SOURCES += ${SGI_CPU_SOURCES} \ + drivers/cfi/v2m/v2m_flash.c \ lib/utils/mem_region.c \ plat/arm/common/arm_nor_psci_mem_protect.c + +# Add the FDT_SOURCES and options for Dynamic Config +FDT_SOURCES += ${SGI575_BASE}/fdts/${PLAT}_tb_fw_config.dts +TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb + +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config)) + +FDT_SOURCES += ${SGI575_BASE}/fdts/${PLAT}.dts +HW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}.dtb + +# Add the HW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${HW_CONFIG},--hw-config)) diff --git a/plat/arm/board/sgiclarka/fdts/sgiclarka.dts b/plat/arm/board/sgiclarka/fdts/sgiclarka.dts new file mode 100644 index 000000000..43bd85692 --- /dev/null +++ b/plat/arm/board/sgiclarka/fdts/sgiclarka.dts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; +/ { + /* compatible string */ + compatible = "arm,sgi-clark"; + + /* + * Place holder for system-id node with default values. The + * value of platform-id and config-id will be set to the + * correct values during the BL2 stage of boot. + */ + system-id { + platform-id = <0x0>; + config-id = <0x0>; + }; +}; diff --git a/plat/arm/board/sgiclarka/fdts/sgiclarka_tb_fw_config.dts b/plat/arm/board/sgiclarka/fdts/sgiclarka_tb_fw_config.dts new file mode 100644 index 000000000..315fa6999 --- /dev/null +++ b/plat/arm/board/sgiclarka/fdts/sgiclarka_tb_fw_config.dts @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + /* Platform Config */ + compatible = "arm,tb_fw"; + hw_config_addr = <0x0 0xFEF00000>; + hw_config_max_size = <0x0100000>; + /* + * The following two entries are placeholders for Mbed TLS + * heap information. The default values don't matter since + * they will be overwritten by BL1. + * In case of having shared Mbed TLS heap between BL1 and BL2, + * BL1 will populate these two properties with the respective + * info about the shared heap. This info will be available for + * BL2 in order to locate and re-use the heap. + */ + mbedtls_heap_addr = <0x0 0x0>; + mbedtls_heap_size = <0x0>; +}; diff --git a/plat/arm/board/sgiclarka/include/platform_def.h b/plat/arm/board/sgiclarka/include/platform_def.h new file mode 100644 index 000000000..abc48d84c --- /dev/null +++ b/plat/arm/board/sgiclarka/include/platform_def.h @@ -0,0 +1,18 @@ +/* + * 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 <sgi_base_platform_def.h> + +#define PLAT_ARM_CLUSTER_COUNT 2 +#define CSS_SGI_MAX_CPUS_PER_CLUSTER 4 +#define CSS_SGI_MAX_PE_PER_CPU 1 + +#define PLAT_CSS_MHU_BASE 0x45400000 + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/arm/board/sgiclarka/platform.mk b/plat/arm/board/sgiclarka/platform.mk new file mode 100644 index 000000000..fc2f76670 --- /dev/null +++ b/plat/arm/board/sgiclarka/platform.mk @@ -0,0 +1,38 @@ +# +# Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include plat/arm/css/sgi/sgi-common.mk + +SGICLARKA_BASE = plat/arm/board/sgiclarka + +PLAT_INCLUDES += -I${SGICLARKA_BASE}/include/ + +SGI_CPU_SOURCES := lib/cpus/aarch64/cortex_ares.S + +BL1_SOURCES += ${SGI_CPU_SOURCES} + +BL2_SOURCES += lib/utils/mem_region.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +BL31_SOURCES += ${SGI_CPU_SOURCES} \ + drivers/cfi/v2m/v2m_flash.c \ + lib/utils/mem_region.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +# Add the FDT_SOURCES and options for Dynamic Config +FDT_SOURCES += ${SGICLARKA_BASE}/fdts/${PLAT}_tb_fw_config.dts +TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb + +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config)) + +FDT_SOURCES += ${SGICLARKA_BASE}/fdts/${PLAT}.dts +HW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}.dtb + +# Add the HW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${HW_CONFIG},--hw-config)) + +override CTX_INCLUDE_AARCH32_REGS := 0 diff --git a/plat/arm/common/aarch64/arm_helpers.S b/plat/arm/common/aarch64/arm_helpers.S index 752929db5..06720589a 100644 --- a/plat/arm/common/aarch64/arm_helpers.S +++ b/plat/arm/common/aarch64/arm_helpers.S @@ -8,9 +8,9 @@ .weak plat_arm_calc_core_pos .weak plat_my_core_pos - .weak plat_crash_console_init - .weak plat_crash_console_putc - .weak plat_crash_console_flush + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush .globl platform_mem_init 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/arm_tzc400.c b/plat/arm/common/arm_tzc400.c index a32736c3a..2ae084c7b 100644 --- a/plat/arm/common/arm_tzc400.c +++ b/plat/arm/common/arm_tzc400.c @@ -24,7 +24,7 @@ void arm_tzc400_setup(const arm_tzc_regions_info_t *tzc_regions) { #ifndef EL3_PAYLOAD_BASE - int region_index = 1; + unsigned int region_index = 1U; const arm_tzc_regions_info_t *p; const arm_tzc_regions_info_t init_tzc_regions[] = { ARM_TZC_REGIONS_DEF, @@ -55,7 +55,7 @@ void arm_tzc400_setup(const arm_tzc_regions_info_t *tzc_regions) region_index++; } - INFO("Total %d regions set.\n", region_index); + INFO("Total %u regions set.\n", region_index); #else /* if defined(EL3_PAYLOAD_BASE) */ diff --git a/plat/arm/common/arm_tzc_dmc500.c b/plat/arm/common/arm_tzc_dmc500.c index 8cb81e7ae..6bd771b0e 100644 --- a/plat/arm/common/arm_tzc_dmc500.c +++ b/plat/arm/common/arm_tzc_dmc500.c @@ -20,7 +20,7 @@ void arm_tzc_dmc500_setup(tzc_dmc500_driver_data_t *plat_driver_data, const arm_tzc_regions_info_t *tzc_regions) { #ifndef EL3_PAYLOAD_BASE - int region_index = 1; + unsigned int region_index = 1U; const arm_tzc_regions_info_t *p; const arm_tzc_regions_info_t init_tzc_regions[] = { ARM_TZC_REGIONS_DEF, @@ -50,7 +50,7 @@ void arm_tzc_dmc500_setup(tzc_dmc500_driver_data_t *plat_driver_data, region_index++; } - INFO("Total %d regions set.\n", region_index); + INFO("Total %u regions set.\n", region_index); #else /* Allow secure access only to DRAM for EL3 payloads */ 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/arm/css/drivers/scmi/scmi.h b/plat/arm/css/drivers/scmi/scmi.h index 71a8c2d02..7f8922910 100644 --- a/plat/arm/css/drivers/scmi/scmi.h +++ b/plat/arm/css/drivers/scmi/scmi.h @@ -159,4 +159,7 @@ int scmi_sys_pwr_state_get(void *p, uint32_t *system_state); int scmi_ap_core_set_reset_addr(void *p, uint64_t reset_addr, uint32_t attr); int scmi_ap_core_get_reset_addr(void *p, uint64_t *reset_addr, uint32_t *attr); +/* API to get the platform specific SCMI channel information. */ +scmi_channel_plat_info_t *plat_css_get_scmi_info(); + #endif /* __CSS_SCMI_H__ */ diff --git a/plat/arm/css/drivers/scp/css_pm_scmi.c b/plat/arm/css/drivers/scp/css_pm_scmi.c index 9297e9fe4..956f583c0 100644 --- a/plat/arm/css/drivers/scp/css_pm_scmi.c +++ b/plat/arm/css/drivers/scp/css_pm_scmi.c @@ -13,7 +13,6 @@ #include <platform.h> #include <string.h> #include "../scmi/scmi.h" -#include "../mhu/css_mhu_doorbell.h" #include "css_scp.h" /* @@ -298,14 +297,6 @@ void __dead2 css_scp_sys_reboot(void) css_scp_system_off(SCMI_SYS_PWR_COLD_RESET); } -static scmi_channel_plat_info_t plat_css_scmi_plat_info = { - .scmi_mbx_mem = CSS_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, -}; - static int scmi_ap_core_init(scmi_channel_t *ch) { #if PROGRAMMABLE_RESET_ADDRESS @@ -330,7 +321,7 @@ static int scmi_ap_core_init(scmi_channel_t *ch) void __init plat_arm_pwrc_setup(void) { - channel.info = &plat_css_scmi_plat_info; + channel.info = plat_css_get_scmi_info(); channel.lock = ARM_SCMI_LOCK_GET_INSTANCE; scmi_handle = scmi_init(&channel); if (scmi_handle == NULL) { diff --git a/plat/arm/css/sgi/aarch64/sgi_helper.S b/plat/arm/css/sgi/aarch64/sgi_helper.S index 27bae43cf..d79f1aa21 100644 --- a/plat/arm/css/sgi/aarch64/sgi_helper.S +++ b/plat/arm/css/sgi/aarch64/sgi_helper.S @@ -8,6 +8,7 @@ #include <asm_macros.S> #include <platform_def.h> #include <cortex_a75.h> +#include <cortex_ares.h> #include <cpu_macros.S> .globl plat_arm_calc_core_pos @@ -58,6 +59,7 @@ endfunc plat_arm_calc_core_pos */ func plat_reset_handler jump_if_cpu_midr CORTEX_A75_MIDR, A75 + jump_if_cpu_midr CORTEX_ARES_MIDR, ARES ret /* ----------------------------------------------------- @@ -70,4 +72,11 @@ A75: msr CORTEX_A75_CPUPWRCTLR_EL1, x0 isb ret + +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/css/sgi/include/platform_def.h b/plat/arm/css/sgi/include/sgi_base_platform_def.h index 629749056..90eb3360b 100644 --- a/plat/arm/css/sgi/include/platform_def.h +++ b/plat/arm/css/sgi/include/sgi_base_platform_def.h @@ -4,8 +4,8 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef PLATFORM_DEF_H -#define PLATFORM_DEF_H +#ifndef SGI_BASE_PLATFORM_DEF_H +#define SGI_BASE_PLATFORM_DEF_H #include <arm_def.h> #include <arm_spm_def.h> @@ -17,11 +17,6 @@ #include <v2m_def.h> #include <xlat_tables_defs.h> -#define CSS_SGI_MAX_CPUS_PER_CLUSTER 4 - -/* CPU topology */ -#define PLAT_ARM_CLUSTER_COUNT 2 -#define CSS_SGI_MAX_PE_PER_CPU 1 #define PLATFORM_CORE_COUNT (PLAT_ARM_CLUSTER_COUNT * \ CSS_SGI_MAX_CPUS_PER_CLUSTER * \ CSS_SGI_MAX_PE_PER_CPU) @@ -118,8 +113,6 @@ #define PLAT_ARM_NSTIMER_FRAME_ID 0 -#define PLAT_CSS_MHU_BASE 0x45000000 - #define PLAT_ARM_TRUSTED_ROM_BASE 0x0 #define PLAT_ARM_TRUSTED_ROM_SIZE 0x00080000 /* 512KB */ @@ -216,4 +209,4 @@ V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE) -#endif /* PLATFORM_DEF_H */ +#endif /* SGI_BASE_PLATFORM_DEF_H */ diff --git a/plat/arm/css/sgi/include/sgi_plat_config.h b/plat/arm/css/sgi/include/sgi_plat_config.h deleted file mode 100644 index 9b29d74e4..000000000 --- a/plat/arm/css/sgi/include/sgi_plat_config.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#ifndef __SGI_PLAT_CONFIG_H__ -#define __SGI_PLAT_CONFIG_H__ - -#include <ccn.h> -#include <gicv3.h> - -/* The type of interconnect */ -typedef enum { - ARM_CCI = 0, - ARM_CCN, - ARM_CMN -} css_inteconn_type_t; - -typedef ccn_desc_t inteconn_desc_t; - -/* Interconnect configurations */ -typedef struct css_inteconn_config { - css_inteconn_type_t ip_type; - const inteconn_desc_t *plat_inteconn_desc; -} css_inteconn_config_t; - -/* Topology configurations */ -typedef struct css_topology { - const unsigned char *power_tree; - unsigned int plat_cluster_core_count; -} css_topology_t; - -typedef struct css_plat_config { - const gicv3_driver_data_t *gic_data; - const css_inteconn_config_t *inteconn; - const css_topology_t *topology; -} css_plat_config_t; - -void plat_config_init(void); -css_plat_config_t *get_plat_config(void); - -#endif /* __SGI_PLAT_CONFIG_H__ */ diff --git a/plat/arm/css/sgi/include/sgi_variant.h b/plat/arm/css/sgi/include/sgi_variant.h index 5698d0abd..dea580be2 100644 --- a/plat/arm/css/sgi/include/sgi_variant.h +++ b/plat/arm/css/sgi/include/sgi_variant.h @@ -4,10 +4,21 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef __SGI_VARIANT_H__ -#define __SGI_VARIANT_H__ +#ifndef SGI_VARIANT_H +#define SGI_VARIANT_H /* SSC_VERSION values for SGI575 */ #define SGI575_SSC_VER_PART_NUM 0x0783 -#endif /* __SGI_VARIANT_H__ */ +/* SID Version values for SGI-Clark */ +#define SGI_CLARK_SID_VER_PART_NUM 0x0786 + +/* Structure containing SGI platform variant information */ +typedef struct sgi_platform_info { + unsigned int platform_id; /* Part Number of the platform */ + unsigned int config_id; /* Config Id of the platform */ +} sgi_platform_info_t; + +extern sgi_platform_info_t sgi_plat_info; + +#endif /* SGI_VARIANT_H */ diff --git a/plat/arm/css/sgi/sgi-common.mk b/plat/arm/css/sgi/sgi-common.mk index 24f03dd4b..d6e5448de 100644 --- a/plat/arm/css/sgi/sgi-common.mk +++ b/plat/arm/css/sgi/sgi-common.mk @@ -22,8 +22,6 @@ INTERCONNECT_SOURCES := ${CSS_ENT_BASE}/sgi_interconnect.c PLAT_INCLUDES += -I${CSS_ENT_BASE}/include -ENT_CPU_SOURCES := lib/cpus/aarch64/cortex_a75.S - ENT_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \ drivers/arm/gic/v3/gicv3_main.c \ drivers/arm/gic/v3/gicv3_helpers.c \ @@ -35,38 +33,20 @@ ENT_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \ PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/sgi_plat.c \ ${CSS_ENT_BASE}/aarch64/sgi_helper.S -BL1_SOURCES += ${INTERCONNECT_SOURCES} \ - ${ENT_CPU_SOURCES} \ - ${CSS_ENT_BASE}/sgi_bl1_setup.c \ - ${CSS_ENT_BASE}/sgi_plat_config.c +BL1_SOURCES += ${INTERCONNECT_SOURCES} BL2_SOURCES += ${CSS_ENT_BASE}/sgi_security.c \ ${CSS_ENT_BASE}/sgi_image_load.c -BL31_SOURCES += ${ENT_CPU_SOURCES} \ - ${INTERCONNECT_SOURCES} \ +BL31_SOURCES += ${INTERCONNECT_SOURCES} \ ${ENT_GIC_SOURCES} \ ${CSS_ENT_BASE}/sgi_bl31_setup.c \ - ${CSS_ENT_BASE}/sgi_topology.c \ - ${CSS_ENT_BASE}/sgi_plat_config.c + ${CSS_ENT_BASE}/sgi_topology.c ifeq (${RAS_EXTENSION},1) BL31_SOURCES += ${CSS_ENT_BASE}/sgi_ras.c endif -# Add the FDT_SOURCES and options for Dynamic Config -FDT_SOURCES += ${CSS_ENT_BASE}/fdts/${PLAT}_tb_fw_config.dts -TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb - -# Add the TB_FW_CONFIG to FIP and specify the same to certtool -$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config)) - -FDT_SOURCES += ${CSS_ENT_BASE}/fdts/${PLAT}.dts -HW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}.dtb - -# Add the HW_CONFIG to FIP and specify the same to certtool -$(eval $(call TOOL_ADD_PAYLOAD,${HW_CONFIG},--hw-config)) - ifneq (${RESET_TO_BL31},0) $(error "Using BL31 as the reset vector is not supported on ${PLATFORM} platform. \ Please set RESET_TO_BL31 to 0.") diff --git a/plat/arm/css/sgi/sgi_bl1_setup.c b/plat/arm/css/sgi/sgi_bl1_setup.c deleted file mode 100644 index d3d98d92a..000000000 --- a/plat/arm/css/sgi/sgi_bl1_setup.c +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include <bl_common.h> -#include <debug.h> -#include <plat_arm.h> -#include <sgi_plat_config.h> -#include <soc_css.h> - -void bl1_early_platform_setup(void) -{ - /* Initialize the platform configuration structure */ - plat_config_init(); - - arm_bl1_early_platform_setup(); -} diff --git a/plat/arm/css/sgi/sgi_bl31_setup.c b/plat/arm/css/sgi/sgi_bl31_setup.c index 09f493edd..ce8502699 100644 --- a/plat/arm/css/sgi/sgi_bl31_setup.c +++ b/plat/arm/css/sgi/sgi_bl31_setup.c @@ -4,17 +4,91 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include <assert.h> #include <bl_common.h> #include <debug.h> +#include <libfdt.h> #include <plat_arm.h> -#include <sgi_plat_config.h> #include <sgi_ras.h> +#include <sgi_variant.h> +#include "../../css/drivers/scmi/scmi.h" +#include "../../css/drivers/mhu/css_mhu_doorbell.h" + +sgi_platform_info_t sgi_plat_info; + +static scmi_channel_plat_info_t sgi575_scmi_plat_info = { + .scmi_mbx_mem = CSS_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, +}; + +static scmi_channel_plat_info_t sgi_clark_scmi_plat_info = { + .scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE, + .db_reg_addr = PLAT_CSS_MHU_BASE + SENDER_REG_SET(0), + .db_preserve_mask = 0xfffffffe, + .db_modify_mask = 0x1, + .ring_doorbell = &mhuv2_ring_doorbell, +}; + +scmi_channel_plat_info_t *plat_css_get_scmi_info() +{ + if (sgi_plat_info.platform_id == SGI_CLARK_SID_VER_PART_NUM) + return &sgi_clark_scmi_plat_info; + else if (sgi_plat_info.platform_id == SGI575_SSC_VER_PART_NUM) + return &sgi575_scmi_plat_info; + else + panic(); +}; + +/******************************************************************************* + * This function sets the sgi_platform_id and sgi_config_id + ******************************************************************************/ +int sgi_identify_platform(unsigned long hw_config) +{ + void *fdt; + int nodeoffset; + const unsigned int *property; + + fdt = (void *)hw_config; + + /* Check the validity of the fdt */ + assert(fdt_check_header(fdt) == 0); + + nodeoffset = fdt_subnode_offset(fdt, 0, "system-id"); + if (nodeoffset < 0) { + ERROR("Failed to get system-id node offset\n"); + return -1; + } + + property = fdt_getprop(fdt, nodeoffset, "platform-id", NULL); + if (property == NULL) { + ERROR("Failed to get platform-id property\n"); + return -1; + } + + sgi_plat_info.platform_id = fdt32_to_cpu(*property); + + property = fdt_getprop(fdt, nodeoffset, "config-id", NULL); + if (property == NULL) { + ERROR("Failed to get config-id property\n"); + return -1; + } + + sgi_plat_info.config_id = fdt32_to_cpu(*property); + + return 0; +} void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3) { - /* Initialize the platform configuration structure */ - plat_config_init(); + int ret; + + ret = sgi_identify_platform(arg2); + if (ret == -1) + panic(); arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3); } diff --git a/plat/arm/css/sgi/sgi_image_load.c b/plat/arm/css/sgi/sgi_image_load.c index 09403f884..d97583ef9 100644 --- a/plat/arm/css/sgi/sgi_image_load.c +++ b/plat/arm/css/sgi/sgi_image_load.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include <arch_helpers.h> #include <debug.h> #include <desc_image_load.h> #include <libfdt.h> @@ -13,6 +14,7 @@ * This function inserts Platform information via device tree nodes as, * system-id { * platform-id = <0>; + * config-id = <0>; * } ******************************************************************************/ static int plat_sgi_append_config_node(void) @@ -20,7 +22,7 @@ static int plat_sgi_append_config_node(void) bl_mem_params_node_t *mem_params; void *fdt; int nodeoffset, err; - unsigned int platid = 0; + unsigned int platid = 0, platcfg = 0; char *platform_name; mem_params = get_bl_mem_params_node(HW_CONFIG_ID); @@ -45,31 +47,38 @@ static int plat_sgi_append_config_node(void) } if (strcmp(platform_name, "arm,sgi575") == 0) { - platid = mmio_read_32(SSC_VERSION); + platid = mmio_read_32(SSC_VERSION) & SSC_VERSION_PART_NUM_MASK; + platcfg = (mmio_read_32(SSC_VERSION) >> SSC_VERSION_CONFIG_SHIFT) + & SSC_VERSION_CONFIG_MASK; + } else if (strcmp(platform_name, "arm,sgi-clark") == 0) { + platid = mmio_read_32(SID_REG_BASE + SID_SYSTEM_ID_OFFSET) + & SID_SYSTEM_ID_PART_NUM_MASK; + platcfg = mmio_read_32(SID_REG_BASE + SID_SYSTEM_CFG_OFFSET); } else { WARN("Invalid platform\n"); return -1; } - /* Increase DTB blob by 512 byte */ - err = fdt_open_into(fdt, fdt, mem_params->image_info.image_size + 512); - if (err < 0) { - ERROR("Failed to open HW_CONFIG DTB\n"); + nodeoffset = fdt_subnode_offset(fdt, 0, "system-id"); + if (nodeoffset < 0) { + ERROR("Failed to get system-id node offset\n"); return -1; } - /* Create "/system-id" node */ - nodeoffset = fdt_add_subnode(fdt, 0, "system-id"); - if (nodeoffset < 0) { - ERROR("Failed to add node system-id\n"); + err = fdt_setprop_u32(fdt, nodeoffset, "platform-id", platid); + if (err < 0) { + ERROR("Failed to set platform-id\n"); return -1; } - err = fdt_setprop_u32(fdt, nodeoffset, "platform-id", platid); + err = fdt_setprop_u32(fdt, nodeoffset, "config-id", platcfg); if (err < 0) { - ERROR("Failed to add node platform-id\n"); + ERROR("Failed to set config-id\n"); return -1; } + + flush_dcache_range((uintptr_t)fdt, mem_params->image_info.image_size); + return 0; } diff --git a/plat/arm/css/sgi/sgi_interconnect.c b/plat/arm/css/sgi/sgi_interconnect.c index 325b5b152..074f8a274 100644 --- a/plat/arm/css/sgi/sgi_interconnect.c +++ b/plat/arm/css/sgi/sgi_interconnect.c @@ -6,7 +6,6 @@ #include <arch_helpers.h> #include <debug.h> -#include <sgi_plat_config.h> /* * For SGI575 which support FCM (with automatic interconnect enter/exit), diff --git a/plat/arm/css/sgi/sgi_plat_config.c b/plat/arm/css/sgi/sgi_plat_config.c deleted file mode 100644 index 29b99a3c2..000000000 --- a/plat/arm/css/sgi/sgi_plat_config.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include <assert.h> -#include <debug.h> -#include <plat_arm.h> -#include <platform_def.h> -#include <sgi_variant.h> -#include <sgi_plat_config.h> -#include <string.h> - -static css_plat_config_t *css_plat_info; - -/* GIC */ -/* The GICv3 driver only needs to be initialized in EL3 */ -uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT]; - -/* Interconnect configuration for SGI575 */ -const css_inteconn_config_t sgi575_inteconn = { - .ip_type = ARM_CMN, - .plat_inteconn_desc = NULL -}; - -/* Configuration structure for SGI575 */ -css_plat_config_t sgi575_config = { - .inteconn = &sgi575_inteconn, -}; - -/******************************************************************************* - * This function initializes the platform sturcture. - ******************************************************************************/ -void plat_config_init(void) -{ - /* Get the platform configurations */ - switch (GET_SGI_PART_NUM) { - case SGI575_SSC_VER_PART_NUM: - css_plat_info = &sgi575_config; - break; - default: - ERROR("Not a valid sgi variant!\n"); - panic(); - } -} - -/******************************************************************************* - * This function returns the platform structure pointer. - ******************************************************************************/ -css_plat_config_t *get_plat_config(void) -{ - assert(css_plat_info != NULL); - return css_plat_info; -} diff --git a/plat/arm/css/sgi/sgi_topology.c b/plat/arm/css/sgi/sgi_topology.c index 3f6357bd1..3b7a57ad2 100644 --- a/plat/arm/css/sgi/sgi_topology.c +++ b/plat/arm/css/sgi/sgi_topology.c @@ -5,7 +5,6 @@ */ #include <plat_arm.h> -#include <sgi_plat_config.h> /* Topology */ /* @@ -20,18 +19,12 @@ const unsigned char sgi_pd_tree_desc[] = { CSS_SGI_MAX_CPUS_PER_CLUSTER }; -/* Topology configuration for sgi platform */ -const css_topology_t sgi_topology = { - .power_tree = sgi_pd_tree_desc, - .plat_cluster_core_count = CSS_SGI_MAX_CPUS_PER_CLUSTER -}; - /******************************************************************************* * This function returns the topology tree information. ******************************************************************************/ const unsigned char *plat_get_power_domain_tree_desc(void) { - return sgi_topology.power_tree; + return sgi_pd_tree_desc; } /******************************************************************************* @@ -40,7 +33,7 @@ const unsigned char *plat_get_power_domain_tree_desc(void) ******************************************************************************/ unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr) { - return sgi_topology.plat_cluster_core_count; + return CSS_SGI_MAX_CPUS_PER_CLUSTER; } /******************************************************************************* diff --git a/plat/arm/css/sgm/sgm_bl31_setup.c b/plat/arm/css/sgm/sgm_bl31_setup.c index a55176a74..29c32e7cf 100644 --- a/plat/arm/css/sgm/sgm_bl31_setup.c +++ b/plat/arm/css/sgm/sgm_bl31_setup.c @@ -8,6 +8,21 @@ #include <debug.h> #include <plat_arm.h> #include <sgm_plat_config.h> +#include "../../css/drivers/scmi/scmi.h" +#include "../../css/drivers/mhu/css_mhu_doorbell.h" + +static scmi_channel_plat_info_t sgm775_scmi_plat_info = { + .scmi_mbx_mem = CSS_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 &sgm775_scmi_plat_info; +} void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3) diff --git a/plat/common/aarch32/crash_console_helpers.S b/plat/common/aarch32/crash_console_helpers.S new file mode 100644 index 000000000..fc37c08fa --- /dev/null +++ b/plat/common/aarch32/crash_console_helpers.S @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * If a platform wishes to use the functions in this file it has to be added to + * the Makefile of the platform. It is not included in the common Makefile. + */ + +#include <asm_macros.S> +#include <console.h> + + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + +#if MULTI_CONSOLE_API + + /* ----------------------------------------------------- + * int plat_crash_console_init(void) + * Use normal console by default. Switch it to crash + * mode so serial consoles become active again. + * NOTE: This default implementation will only work for + * crashes that occur after a normal console (marked + * valid for the crash state) has been registered with + * the console framework. To debug crashes that occur + * earlier, the platform has to override these functions + * with an implementation that initializes a console + * driver with hardcoded parameters. See + * docs/porting-guide.rst for more information. + * ----------------------------------------------------- + */ +func plat_crash_console_init +#if defined(IMAGE_BL1) + /* + * BL1 code can possibly crash so early that the data segment is not yet + * accessible. Don't risk undefined behavior by trying to run the normal + * console framework. Platforms that want to debug BL1 will need to + * override this with custom functions that can run from registers only. + */ + mov r0, #0 + bx lr +#else /* IMAGE_BL1 */ + mov r3, lr + mov r0, #CONSOLE_FLAG_CRASH + bl console_switch_state + mov r0, #1 + bx r3 +#endif +endfunc plat_crash_console_init + + /* ----------------------------------------------------- + * void plat_crash_console_putc(int character) + * Output through the normal console by default. + * ----------------------------------------------------- + */ +func plat_crash_console_putc + b console_putc +endfunc plat_crash_console_putc + + /* ----------------------------------------------------- + * void plat_crash_console_flush(void) + * Flush normal console by default. + * ----------------------------------------------------- + */ +func plat_crash_console_flush + b console_flush +endfunc plat_crash_console_flush + +#else /* MULTI_CONSOLE_API */ + + /* ----------------------------------------------------- + * In the old API these are all no-op stubs that need to + * be overridden by the platform to be useful. + * ----------------------------------------------------- + */ +func plat_crash_console_init + mov r0, #0 + bx lr +endfunc plat_crash_console_init + +func plat_crash_console_putc + bx lr +endfunc plat_crash_console_putc + +func plat_crash_console_flush + bx lr +endfunc plat_crash_console_flush + +#endif diff --git a/plat/common/aarch32/platform_helpers.S b/plat/common/aarch32/platform_helpers.S index d61853942..e1e2a6f58 100644 --- a/plat/common/aarch32/platform_helpers.S +++ b/plat/common/aarch32/platform_helpers.S @@ -8,9 +8,11 @@ #include <asm_macros.S> .weak plat_report_exception +#if !ERROR_DEPRECATED .weak plat_crash_console_init .weak plat_crash_console_putc .weak plat_crash_console_flush +#endif .weak plat_reset_handler .weak plat_disable_acp .weak bl1_plat_prepare_exit @@ -26,6 +28,7 @@ func plat_report_exception bx lr endfunc plat_report_exception +#if !ERROR_DEPRECATED /* ----------------------------------------------------- * Placeholder function which should be redefined by * each platform. @@ -54,6 +57,7 @@ func plat_crash_console_flush mov r0, #0 bx lr endfunc plat_crash_console_flush +#endif /* ----------------------------------------------------- * Placeholder function which should be redefined by diff --git a/plat/common/aarch64/crash_console_helpers.S b/plat/common/aarch64/crash_console_helpers.S new file mode 100644 index 000000000..5af8db252 --- /dev/null +++ b/plat/common/aarch64/crash_console_helpers.S @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * If a platform wishes to use the functions in this file it has to be added to + * the Makefile of the platform. It is not included in the common Makefile. + */ + +#include <asm_macros.S> +#include <console.h> + + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + +#if MULTI_CONSOLE_API + + /* ----------------------------------------------------- + * int plat_crash_console_init(void) + * Use normal console by default. Switch it to crash + * mode so serial consoles become active again. + * NOTE: This default implementation will only work for + * crashes that occur after a normal console (marked + * valid for the crash state) has been registered with + * the console framework. To debug crashes that occur + * earlier, the platform has to override these functions + * with an implementation that initializes a console + * driver with hardcoded parameters. See + * docs/porting-guide.rst for more information. + * ----------------------------------------------------- + */ +func plat_crash_console_init +#if defined(IMAGE_BL1) + /* + * BL1 code can possibly crash so early that the data segment is not yet + * accessible. Don't risk undefined behavior by trying to run the normal + * console framework. Platforms that want to debug BL1 will need to + * override this with custom functions that can run from registers only. + */ + mov x0, #0 + ret +#else /* IMAGE_BL1 */ + mov x3, x30 + mov x0, #CONSOLE_FLAG_CRASH + bl console_switch_state + mov x0, #1 + ret x3 +#endif +endfunc plat_crash_console_init + + /* ----------------------------------------------------- + * void plat_crash_console_putc(int character) + * Output through the normal console by default. + * ----------------------------------------------------- + */ +func plat_crash_console_putc + b console_putc +endfunc plat_crash_console_putc + + /* ----------------------------------------------------- + * void plat_crash_console_flush(void) + * Flush normal console by default. + * ----------------------------------------------------- + */ +func plat_crash_console_flush + b console_flush +endfunc plat_crash_console_flush + +#else /* MULTI_CONSOLE_API */ + + /* ----------------------------------------------------- + * In the old API these are all no-op stubs that need to + * be overridden by the platform to be useful. + * ----------------------------------------------------- + */ +func plat_crash_console_init + mov x0, #0 + ret +endfunc plat_crash_console_init + +func plat_crash_console_putc + ret +endfunc plat_crash_console_putc + +func plat_crash_console_flush + ret +endfunc plat_crash_console_flush + +#endif diff --git a/plat/common/aarch64/platform_helpers.S b/plat/common/aarch64/platform_helpers.S index 7214588a6..d3ffcaf19 100644 --- a/plat/common/aarch64/platform_helpers.S +++ b/plat/common/aarch64/platform_helpers.S @@ -10,9 +10,11 @@ #include <platform_def.h> .weak plat_report_exception +#if !ERROR_DEPRECATED .weak plat_crash_console_init .weak plat_crash_console_putc .weak plat_crash_console_flush +#endif .weak plat_reset_handler .weak plat_disable_acp .weak bl1_plat_prepare_exit @@ -37,6 +39,7 @@ func plat_report_exception ret endfunc plat_report_exception +#if !ERROR_DEPRECATED #if MULTI_CONSOLE_API /* ----------------------------------------------------- * int plat_crash_console_init(void) @@ -109,6 +112,7 @@ func plat_crash_console_flush ret endfunc plat_crash_console_flush #endif +#endif /* ERROR_DEPRECATED */ /* ----------------------------------------------------- * Placeholder function which should be redefined by 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/hikey/aarch64/hikey_helpers.S b/plat/hisilicon/hikey/aarch64/hikey_helpers.S index 32ff8b40c..9dfdae49c 100644 --- a/plat/hisilicon/hikey/aarch64/hikey_helpers.S +++ b/plat/hisilicon/hikey/aarch64/hikey_helpers.S @@ -12,6 +12,7 @@ .globl platform_mem_init .globl plat_crash_console_init .globl plat_crash_console_putc + .globl plat_crash_console_flush .globl plat_report_exception .globl plat_reset_handler @@ -61,6 +62,19 @@ func plat_crash_console_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 : x0, x1 + * --------------------------------------------- + */ +func plat_crash_console_flush + mov_imm x0, CRASH_CONSOLE_BASE + b console_core_flush +endfunc plat_crash_console_flush + + /* --------------------------------------------- * void plat_report_exception(unsigned int type) * Function to report an unhandled exception * with platform-specific means. diff --git a/plat/hisilicon/hikey960/aarch64/hikey960_helpers.S b/plat/hisilicon/hikey960/aarch64/hikey960_helpers.S index d18399fbf..550c5604b 100644 --- a/plat/hisilicon/hikey960/aarch64/hikey960_helpers.S +++ b/plat/hisilicon/hikey960/aarch64/hikey960_helpers.S @@ -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 */ @@ -14,6 +14,7 @@ .globl platform_mem_init .globl plat_crash_console_init .globl plat_crash_console_putc + .globl plat_crash_console_flush .globl plat_report_exception .globl plat_reset_handler .globl clr_ex @@ -65,6 +66,19 @@ func plat_crash_console_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 : x0, x1 + * --------------------------------------------- + */ +func plat_crash_console_flush + mov_imm x0, CRASH_CONSOLE_BASE + b console_core_flush +endfunc plat_crash_console_flush + + /* --------------------------------------------- * void plat_report_exception(unsigned int type) * Function to report an unhandled exception * with platform-specific means. 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/common/imx8_helpers.S b/plat/imx/common/imx8_helpers.S index b89d346c6..19293bfe7 100644 --- a/plat/imx/common/imx8_helpers.S +++ b/plat/imx/common/imx8_helpers.S @@ -16,6 +16,7 @@ .globl plat_secondary_cold_boot_setup .globl plat_crash_console_init .globl plat_crash_console_putc + .globl plat_crash_console_flush .globl platform_mem_init .globl imx_mailbox_init @@ -106,6 +107,7 @@ func plat_secondary_cold_boot_setup endfunc plat_secondary_cold_boot_setup func plat_crash_console_init + mov x0, #1 ret endfunc plat_crash_console_init @@ -113,6 +115,11 @@ func plat_crash_console_putc ret endfunc plat_crash_console_putc +func plat_crash_console_flush + mov x0, #0 + ret +endfunc plat_crash_console_flush + func platform_mem_init ret endfunc platform_mem_init diff --git a/plat/imx/common/lpuart_console.S b/plat/imx/common/lpuart_console.S index ad71b89f2..668fd6249 100644 --- a/plat/imx/common/lpuart_console.S +++ b/plat/imx/common/lpuart_console.S @@ -6,6 +6,7 @@ #include <arch.h> #include <asm_macros.S> +#define USE_FINISH_CONSOLE_REG_2 #include <console_macros.S> #include <assert_macros.S> #include "imx8_lpuart.h" @@ -26,7 +27,7 @@ func console_lpuart_register mov x0, x6 mov x30, x7 - finish_console_register lpuart + finish_console_register lpuart putc=1, getc=1 register_fail: ret x7 diff --git a/plat/imx/imx7/warp7/aarch32/warp7_helpers.S b/plat/imx/imx7/warp7/aarch32/warp7_helpers.S index b1921cc38..3695b32db 100644 --- a/plat/imx/imx7/warp7/aarch32/warp7_helpers.S +++ b/plat/imx/imx7/warp7/aarch32/warp7_helpers.S @@ -14,6 +14,7 @@ .globl plat_get_my_entrypoint .globl plat_crash_console_init .globl plat_crash_console_putc + .globl plat_crash_console_flush .globl plat_panic_handler /* --------------------------------------------- @@ -45,6 +46,12 @@ func plat_crash_console_putc b imx_crash_uart_putc endfunc plat_crash_console_putc +func plat_crash_console_flush + /* Placeholder */ + mov r0, #0 + bx lr +endfunc plat_crash_console_flush + func plat_panic_handler mov r3, #HAB_ROM_VECTOR_TABLE_FAILSAFE ldr r3, [r3, #0] 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/layerscape/common/aarch64/ls_console.S b/plat/layerscape/common/aarch64/ls_console.S index 5c87465eb..ec4390a69 100644 --- a/plat/layerscape/common/aarch64/ls_console.S +++ b/plat/layerscape/common/aarch64/ls_console.S @@ -6,6 +6,7 @@ #include <arch.h> #include <asm_macros.S> +#define USE_FINISH_CONSOLE_REG_2 #include <console_macros.S> #include <assert_macros.S> #include "ls_16550.h" @@ -106,7 +107,7 @@ func console_ls_16550_register mov x0, x6 mov x30, x7 - finish_console_register ls_16550 + finish_console_register ls_16550 putc=1, getc=1, flush=1 register_fail: ret x7 diff --git a/plat/marvell/common/aarch64/marvell_helpers.S b/plat/marvell/common/aarch64/marvell_helpers.S index a3dc917c6..128c3ab69 100644 --- a/plat/marvell/common/aarch64/marvell_helpers.S +++ b/plat/marvell/common/aarch64/marvell_helpers.S @@ -18,6 +18,7 @@ .weak plat_my_core_pos .globl plat_crash_console_init .globl plat_crash_console_putc + .globl plat_crash_console_flush .globl platform_mem_init .globl disable_mmu_dcache .globl invalidate_tlb_all @@ -79,6 +80,19 @@ func plat_crash_console_putc b console_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 : x0, x1 + * --------------------------------------------- + */ +func plat_crash_console_flush + mov_imm x0, PLAT_MARVELL_CRASH_UART_BASE + b console_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. 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/nvidia/tegra/common/aarch64/tegra_helpers.S b/plat/nvidia/tegra/common/aarch64/tegra_helpers.S index 3c490d078..0476ba826 100644 --- a/plat/nvidia/tegra/common/aarch64/tegra_helpers.S +++ b/plat/nvidia/tegra/common/aarch64/tegra_helpers.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -36,6 +36,7 @@ .globl platform_mem_init .globl plat_crash_console_init .globl plat_crash_console_putc + .globl plat_crash_console_flush .globl tegra_secure_entrypoint .globl plat_reset_handler @@ -240,6 +241,20 @@ func plat_crash_console_putc b console_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 : x0, x1 + * --------------------------------------------- + */ +func plat_crash_console_flush + adr x0, tegra_console_base + ldr x0, [x0] + b console_core_flush +endfunc plat_crash_console_flush + /* --------------------------------------------------- * Function to handle a platform reset and store * input parameters passed by BL2. diff --git a/plat/qemu/include/platform_def.h b/plat/qemu/include/platform_def.h index 55252c380..c2289bc56 100644 --- a/plat/qemu/include/platform_def.h +++ b/plat/qemu/include/platform_def.h @@ -223,7 +223,7 @@ * DT related constants */ #define PLAT_QEMU_DT_BASE NS_DRAM0_BASE -#define PLAT_QEMU_DT_MAX_SIZE 0x10000 +#define PLAT_QEMU_DT_MAX_SIZE 0x100000 /* * System counter 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/rockchip/rk3328/platform.mk b/plat/rockchip/rk3328/platform.mk index 560cccae6..785f64036 100644 --- a/plat/rockchip/rk3328/platform.mk +++ b/plat/rockchip/rk3328/platform.mk @@ -29,6 +29,7 @@ RK_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \ PLAT_BL_COMMON_SOURCES := lib/xlat_tables/aarch64/xlat_tables.c \ lib/xlat_tables/xlat_tables_common.c \ + plat/common/aarch64/crash_console_helpers.S \ plat/common/plat_psci_common.c BL31_SOURCES += ${RK_GIC_SOURCES} \ diff --git a/plat/rockchip/rk3368/platform.mk b/plat/rockchip/rk3368/platform.mk index 050a2c423..a3e593e60 100644 --- a/plat/rockchip/rk3368/platform.mk +++ b/plat/rockchip/rk3368/platform.mk @@ -26,6 +26,7 @@ RK_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \ PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \ lib/xlat_tables/aarch64/xlat_tables.c \ + plat/common/aarch64/crash_console_helpers.S \ plat/common/plat_psci_common.c BL31_SOURCES += ${RK_GIC_SOURCES} \ diff --git a/plat/rockchip/rk3399/platform.mk b/plat/rockchip/rk3399/platform.mk index 912041928..eccf1cc85 100644 --- a/plat/rockchip/rk3399/platform.mk +++ b/plat/rockchip/rk3399/platform.mk @@ -32,6 +32,7 @@ RK_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \ PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \ lib/xlat_tables/aarch64/xlat_tables.c \ + plat/common/aarch64/crash_console_helpers.S \ plat/common/plat_psci_common.c BL31_SOURCES += ${RK_GIC_SOURCES} \ diff --git a/plat/rpi3/platform.mk b/plat/rpi3/platform.mk index a7b0991fb..36c1ee2b4 100644 --- a/plat/rpi3/platform.mk +++ b/plat/rpi3/platform.mk @@ -4,12 +4,16 @@ # SPDX-License-Identifier: BSD-3-Clause # +include lib/libfdt/libfdt.mk +include lib/xlat_tables_v2/xlat_tables.mk + PLAT_INCLUDES := -Iinclude/common/tbbr \ -Iplat/rpi3/include PLAT_BL_COMMON_SOURCES := drivers/console/aarch64/console.S \ drivers/ti/uart/aarch64/16550_console.S \ - plat/rpi3/rpi3_common.c + plat/rpi3/rpi3_common.c \ + ${XLAT_TABLES_LIB_SRCS} BL1_SOURCES += drivers/io/io_fip.c \ drivers/io/io_memmap.c \ @@ -37,12 +41,8 @@ BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \ plat/rpi3/aarch64/plat_helpers.S \ plat/rpi3/rpi3_bl31_setup.c \ plat/rpi3/rpi3_pm.c \ - plat/rpi3/rpi3_topology.c - -# Translation tables library -include lib/xlat_tables_v2/xlat_tables.mk - -PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} + plat/rpi3/rpi3_topology.c \ + ${LIBFDT_SRCS} # Tune compiler for Cortex-A53 ifeq ($(notdir $(CC)),armclang) diff --git a/plat/rpi3/rpi3_bl31_setup.c b/plat/rpi3/rpi3_bl31_setup.c index 0ae783e12..483d150f0 100644 --- a/plat/rpi3/rpi3_bl31_setup.c +++ b/plat/rpi3/rpi3_bl31_setup.c @@ -6,6 +6,7 @@ #include <assert.h> #include <bl_common.h> +#include <libfdt.h> #include <platform.h> #include <platform_def.h> #include <xlat_mmu_helpers.h> @@ -137,12 +138,74 @@ void bl31_plat_arch_setup(void) enable_mmu_el3(0); } -void bl31_platform_setup(void) +/* + * Add information to the device tree (if any) about the reserved DRAM used by + * the Trusted Firmware. + */ +static void rpi3_dtb_add_mem_rsv(void) { + int i, regions, rc; + uint64_t addr, size; + void *dtb = (void *)RPI3_PRELOADED_DTB_BASE; + + INFO("rpi3: Checking DTB...\n"); + + /* Return if no device tree is detected */ + if (fdt_check_header(dtb) != 0) + return; + + regions = fdt_num_mem_rsv(dtb); + + VERBOSE("rpi3: Found %d mem reserve region(s)\n", regions); + + /* We expect to find one reserved region that we can modify */ + if (regions < 1) + return; + + /* + * Look for the region that corresponds to the default boot firmware. It + * starts at address 0, and it is not needed when the default firmware + * is replaced by this port of the Trusted Firmware. + */ + for (i = 0; i < regions; i++) { + if (fdt_get_mem_rsv(dtb, i, &addr, &size) != 0) + continue; + + if (addr != 0x0) + continue; + + VERBOSE("rpi3: Firmware mem reserve region found\n"); + + rc = fdt_del_mem_rsv(dtb, i); + if (rc != 0) { + INFO("rpi3: Can't remove mem reserve region (%d)\n", rc); + } + + break; + } + + if (i == regions) { + VERBOSE("rpi3: Firmware mem reserve region not found\n"); + } + /* - * Do initial security configuration to allow DRAM/device access - * (if earlier BL has not already done so). + * Reserve all SRAM. As said in the documentation, this isn't actually + * secure memory, so it is needed to tell BL33 that this is a reserved + * memory region. It doesn't guarantee it won't use it, though. */ + rc = fdt_add_mem_rsv(dtb, SEC_SRAM_BASE, SEC_SRAM_SIZE); + if (rc != 0) { + WARN("rpi3: Can't add mem reserve region (%d)\n", rc); + } + + INFO("rpi3: Reserved 0x%llx - 0x%llx in DTB\n", SEC_SRAM_BASE, + SEC_SRAM_BASE + SEC_SRAM_SIZE); +} - return; +void bl31_platform_setup(void) +{ +#ifdef RPI3_PRELOADED_DTB_BASE + /* Only modify a DTB if we know where to look for it */ + rpi3_dtb_add_mem_rsv(); +#endif } diff --git a/plat/rpi3/rpi3_common.c b/plat/rpi3/rpi3_common.c index 98cf534c7..18ff1c82e 100644 --- a/plat/rpi3/rpi3_common.c +++ b/plat/rpi3/rpi3_common.c @@ -23,7 +23,12 @@ #define MAP_SHARED_RAM MAP_REGION_FLAT(SHARED_RAM_BASE, \ SHARED_RAM_SIZE, \ - MT_DEVICE | MT_RW | MT_SECURE) + MT_DEVICE | MT_RW | MT_SECURE) + +#ifdef RPI3_PRELOADED_DTB_BASE +#define MAP_NS_DTB MAP_REGION_FLAT(RPI3_PRELOADED_DTB_BASE, 0x10000, \ + MT_MEMORY | MT_RW | MT_NS) +#endif #define MAP_NS_DRAM0 MAP_REGION_FLAT(NS_DRAM0_BASE, NS_DRAM0_SIZE, \ MT_MEMORY | MT_RW | MT_NS) @@ -74,6 +79,9 @@ static const mmap_region_t plat_rpi3_mmap[] = { static const mmap_region_t plat_rpi3_mmap[] = { MAP_SHARED_RAM, MAP_DEVICE0, +#ifdef RPI3_PRELOADED_DTB_BASE + MAP_NS_DTB, +#endif #ifdef BL32_BASE MAP_BL32_MEM, #endif diff --git a/plat/st/stm32mp1/bl2_io_storage.c b/plat/st/stm32mp1/bl2_io_storage.c index 7346c0cf3..9a023124c 100644 --- a/plat/st/stm32mp1/bl2_io_storage.c +++ b/plat/st/stm32mp1/bl2_io_storage.c @@ -8,12 +8,18 @@ #include <assert.h> #include <boot_api.h> #include <debug.h> +#include <io_block.h> #include <io_driver.h> #include <io_dummy.h> +#include <io_mmc.h> +#include <io_stm32image.h> #include <io_storage.h> +#include <mmc.h> #include <mmio.h> +#include <partition.h> #include <platform.h> #include <platform_def.h> +#include <stm32_sdmmc2.h> #include <stm32mp1_private.h> #include <stm32mp1_rcc.h> #include <string.h> @@ -24,6 +30,50 @@ static const io_dev_connector_t *dummy_dev_con; static uintptr_t dummy_dev_handle; static uintptr_t dummy_dev_spec; +static uintptr_t image_dev_handle; + +static io_block_spec_t gpt_block_spec = { + .offset = 0, + .length = 34 * MMC_BLOCK_SIZE, /* Size of GPT table */ +}; + +uint32_t block_buffer[MMC_BLOCK_SIZE] __aligned(MMC_BLOCK_SIZE); + +static const io_block_dev_spec_t mmc_block_dev_spec = { + /* It's used as temp buffer in block driver */ + .buffer = { + .offset = (size_t)&block_buffer, + .length = MMC_BLOCK_SIZE, + }, + .ops = { + .read = mmc_read_blocks, + .write = NULL, + }, + .block_size = MMC_BLOCK_SIZE, +}; + +static uintptr_t storage_dev_handle; +static const io_dev_connector_t *mmc_dev_con; + +#define IMG_IDX_BL33 0 + +static const struct stm32image_part_info bl33_partition_spec = { + .name = BL33_IMAGE_NAME, + .binary_type = BL33_BINARY_TYPE, +}; + +static struct stm32image_device_info stm32image_dev_info_spec = { + .lba_size = MMC_BLOCK_SIZE, + .part_info[IMG_IDX_BL33] = { + .name = BL33_IMAGE_NAME, + .binary_type = BL33_BINARY_TYPE, + }, +}; + +static io_block_spec_t stm32image_block_spec; + +static const io_dev_connector_t *stm32image_dev_con; + static const io_block_spec_t bl32_block_spec = { .offset = BL32_BASE, .length = STM32MP1_BL32_SIZE @@ -35,6 +85,8 @@ static const io_block_spec_t bl2_block_spec = { }; static int open_dummy(const uintptr_t spec); +static int open_image(const uintptr_t spec); +static int open_storage(const uintptr_t spec); struct plat_io_policy { uintptr_t *dev_handle; @@ -53,6 +105,21 @@ static const struct plat_io_policy policies[] = { .image_spec = (uintptr_t)&bl32_block_spec, .check = open_dummy }, + [BL33_IMAGE_ID] = { + .dev_handle = &image_dev_handle, + .image_spec = (uintptr_t)&bl33_partition_spec, + .check = open_image + }, + [GPT_IMAGE_ID] = { + .dev_handle = &storage_dev_handle, + .image_spec = (uintptr_t)&gpt_block_spec, + .check = open_storage + }, + [STM32_IMAGE_ID] = { + .dev_handle = &storage_dev_handle, + .image_spec = (uintptr_t)&stm32image_block_spec, + .check = open_storage + } }; static int open_dummy(const uintptr_t spec) @@ -60,6 +127,16 @@ static int open_dummy(const uintptr_t spec) return io_dev_init(dummy_dev_handle, 0); } +static int open_image(const uintptr_t spec) +{ + return io_dev_init(image_dev_handle, 0); +} + +static int open_storage(const uintptr_t spec) +{ + return io_dev_init(storage_dev_handle, 0); +} + static void print_boot_device(boot_api_context_t *boot_context) { switch (boot_context->boot_interface_selected) { @@ -149,6 +226,9 @@ static void print_reset_reason(void) void stm32mp1_io_setup(void) { int io_result __unused; + struct stm32_sdmmc2_params params; + struct mmc_device_info device_info; + uintptr_t mmc_default_instance; boot_api_context_t *boot_context = (boot_api_context_t *)stm32mp1_get_boot_ctx_address(); @@ -168,6 +248,93 @@ void stm32mp1_io_setup(void) io_result = io_dev_open(dummy_dev_con, dummy_dev_spec, &dummy_dev_handle); assert(io_result == 0); + + switch (boot_context->boot_interface_selected) { + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD: + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC: + dmb(); + + memset(¶ms, 0, sizeof(struct stm32_sdmmc2_params)); + + if (boot_context->boot_interface_selected == + BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC) { + device_info.mmc_dev_type = MMC_IS_EMMC; + mmc_default_instance = STM32MP1_SDMMC2_BASE; + } else { + device_info.mmc_dev_type = MMC_IS_SD; + mmc_default_instance = STM32MP1_SDMMC1_BASE; + } + + switch (boot_context->boot_interface_instance) { + case 1: + params.reg_base = STM32MP1_SDMMC1_BASE; + break; + case 2: + params.reg_base = STM32MP1_SDMMC2_BASE; + break; + case 3: + params.reg_base = STM32MP1_SDMMC3_BASE; + break; + default: + WARN("SDMMC instance not found, using default\n"); + params.reg_base = mmc_default_instance; + break; + } + + params.device_info = &device_info; + stm32_sdmmc2_mmc_init(¶ms); + + /* Open MMC as a block device to read GPT table */ + io_result = register_io_dev_block(&mmc_dev_con); + if (io_result != 0) { + panic(); + } + + io_result = io_dev_open(mmc_dev_con, + (uintptr_t)&mmc_block_dev_spec, + &storage_dev_handle); + assert(io_result == 0); + + partition_init(GPT_IMAGE_ID); + + io_result = io_dev_close(storage_dev_handle); + assert(io_result == 0); + + stm32image_dev_info_spec.device_size = + stm32_sdmmc2_mmc_get_device_size(); + stm32image_dev_info_spec.part_info[IMG_IDX_BL33].part_offset = + get_partition_entry(BL33_IMAGE_NAME)->start; + stm32image_dev_info_spec.part_info[IMG_IDX_BL33].bkp_offset = + get_partition_entry(BL33_IMAGE_NAME)->length; + + stm32image_block_spec.offset = 0; + stm32image_block_spec.length = + get_partition_entry(BL33_IMAGE_NAME)->length; + + /* + * Re-open MMC with io_mmc, for better perfs compared to + * io_block. + */ + io_result = register_io_dev_mmc(&mmc_dev_con); + assert(io_result == 0); + + io_result = io_dev_open(mmc_dev_con, 0, &storage_dev_handle); + assert(io_result == 0); + + io_result = register_io_dev_stm32image(&stm32image_dev_con); + assert(io_result == 0); + + io_result = io_dev_open(stm32image_dev_con, + (uintptr_t)&stm32image_dev_info_spec, + &image_dev_handle); + assert(io_result == 0); + break; + + default: + ERROR("Boot interface %d not supported\n", + boot_context->boot_interface_selected); + break; + } } /* diff --git a/plat/st/stm32mp1/include/boot_api.h b/plat/st/stm32mp1/include/boot_api.h index 71c359347..e019cffcc 100644 --- a/plat/st/stm32mp1/include/boot_api.h +++ b/plat/st/stm32mp1/include/boot_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, STMicroelectronics - All Rights Reserved + * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: BSD-3-Clause */ @@ -8,6 +8,7 @@ #define __BOOT_API_H #include <stdint.h> +#include <stdio.h> /* * Possible value of boot context field 'boot_interface_sel' @@ -229,7 +230,9 @@ typedef struct { */ uint8_t ecc_pubk[BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES]; /* Pad up to 256 byte total size */ - uint8_t pad[84]; + uint8_t pad[83]; + /* Add binary type information */ + uint8_t binary_type; } __packed boot_api_image_header_t; #endif /* __BOOT_API_H */ diff --git a/plat/st/stm32mp1/include/platform_def.h b/plat/st/stm32mp1/include/platform_def.h index 47e1ffcf5..2ba6cc64a 100644 --- a/plat/st/stm32mp1/include/platform_def.h +++ b/plat/st/stm32mp1/include/platform_def.h @@ -26,6 +26,7 @@ /* SSBL = second stage boot loader */ #define BL33_IMAGE_NAME "ssbl" +#define BL33_BINARY_TYPE U(0x0) #define STM32MP1_PRIMARY_CPU U(0x0) @@ -39,6 +40,7 @@ #define MAX_IO_DEVICES 4 #define MAX_IO_HANDLES 4 +#define MAX_IO_BLOCK_DEVICES 1 /******************************************************************************* * BL2 specific defines. diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk index 30b293296..678a8528e 100644 --- a/plat/st/stm32mp1/platform.mk +++ b/plat/st/stm32mp1/platform.mk @@ -14,8 +14,15 @@ STM32_TF_VERSION ?= 0 # Not needed for Cortex-A7 WORKAROUND_CVE_2017_5715:= 0 +# Number of TF-A copies in the device +STM32_TF_A_COPIES := 2 +$(eval $(call add_define,STM32_TF_A_COPIES)) +PLAT_PARTITION_MAX_ENTRIES := $(shell echo $$(($(STM32_TF_A_COPIES) + 1))) +$(eval $(call add_define,PLAT_PARTITION_MAX_ENTRIES)) + PLAT_INCLUDES := -Iplat/st/stm32mp1/include/ PLAT_INCLUDES += -Iinclude/common/tbbr +PLAT_INCLUDES += -Iinclude/drivers/partition PLAT_INCLUDES += -Iinclude/drivers/st # Device tree @@ -56,11 +63,19 @@ PLAT_BL_COMMON_SOURCES += ${LIBFDT_SRCS} \ plat/st/stm32mp1/stm32mp1_helper.S \ plat/st/stm32mp1/stm32mp1_security.c -BL2_SOURCES += drivers/io/io_dummy.c \ +BL2_SOURCES += drivers/io/io_block.c \ + drivers/io/io_dummy.c \ drivers/io/io_storage.c \ + drivers/st/io/io_stm32image.c \ plat/st/stm32mp1/bl2_io_storage.c \ plat/st/stm32mp1/bl2_plat_setup.c +BL2_SOURCES += drivers/mmc/mmc.c \ + drivers/partition/gpt.c \ + drivers/partition/partition.c \ + drivers/st/io/io_mmc.c \ + drivers/st/mmc/stm32_sdmmc2.c + BL2_SOURCES += drivers/st/ddr/stm32mp1_ddr.c \ drivers/st/ddr/stm32mp1_ram.c diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h index bb3fecf6d..222449837 100644 --- a/plat/st/stm32mp1/stm32mp1_def.h +++ b/plat/st/stm32mp1/stm32mp1_def.h @@ -155,10 +155,9 @@ enum ddr_type { #define STM32MP1_SDMMC2_BASE U(0x58007000) #define STM32MP1_SDMMC3_BASE U(0x48004000) -#define STM32MP1_SD_INIT_FREQ 400000 /*400 KHz*/ +#define STM32MP1_MMC_INIT_FREQ 400000 /*400 KHz*/ #define STM32MP1_SD_NORMAL_SPEED_MAX_FREQ 25000000 /*25 MHz*/ #define STM32MP1_SD_HIGH_SPEED_MAX_FREQ 50000000 /*50 MHz*/ -#define STM32MP1_EMMC_INIT_FREQ STM32MP1_SD_INIT_FREQ #define STM32MP1_EMMC_NORMAL_SPEED_MAX_FREQ 26000000 /*26 MHz*/ #define STM32MP1_EMMC_HIGH_SPEED_MAX_FREQ 52000000 /*52 MHz*/ 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/ti/k3/common/k3_helpers.S b/plat/ti/k3/common/k3_helpers.S index c95e9c367..3dfdda4bd 100644 --- a/plat/ti/k3/common/k3_helpers.S +++ b/plat/ti/k3/common/k3_helpers.S @@ -100,13 +100,13 @@ endfunc plat_my_core_pos * Clobber list : x0 - x4 * --------------------------------------------- */ + .globl plat_crash_console_init func plat_crash_console_init mov_imm x0, CRASH_CONSOLE_BASE mov_imm x1, CRASH_CONSOLE_CLK mov_imm x2, CRASH_CONSOLE_BAUD_RATE mov w3, #0x0 - b console_core_init - + b console_16550_core_init endfunc plat_crash_console_init /* --------------------------------------------- @@ -116,7 +116,22 @@ endfunc plat_crash_console_init * Clobber list : x1, x2 * --------------------------------------------- */ + .globl plat_crash_console_putc func plat_crash_console_putc mov_imm x1, CRASH_CONSOLE_BASE - b console_core_putc + b console_16550_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 : x0, x1 + * --------------------------------------------- + */ + .globl plat_crash_console_flush +func plat_crash_console_flush + mov_imm x0, CRASH_CONSOLE_BASE + b console_16550_core_flush +endfunc plat_crash_console_flush diff --git a/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S b/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S index ad960f493..969d8faa1 100644 --- a/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S +++ b/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S @@ -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 */ @@ -10,6 +10,12 @@ .globl plat_secondary_cold_boot_setup .globl plat_is_my_cpu_primary + .globl zynqmp_calc_core_pos + .globl plat_my_core_pos + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl platform_mem_init /* ----------------------------------------------------- * void plat_secondary_cold_boot_setup (void); @@ -47,3 +53,76 @@ func plat_is_my_cpu_primary cset x0, eq ret x9 endfunc plat_is_my_cpu_primary + + /* ----------------------------------------------------- + * unsigned int plat_my_core_pos(void) + * This function uses the zynqmp_calc_core_pos() + * definition to get the index of the calling CPU. + * ----------------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + b zynqmp_calc_core_pos +endfunc plat_my_core_pos + + /* ----------------------------------------------------- + * unsigned int zynqmp_calc_core_pos(u_register_t mpidr) + * Helper function to calculate the core position. + * With this function: CorePos = (ClusterId * 4) + + * CoreId + * ----------------------------------------------------- + */ +func zynqmp_calc_core_pos + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret +endfunc zynqmp_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, ZYNQMP_CRASH_UART_BASE + mov_imm x1, ZYNQMP_CRASH_UART_CLK_IN_HZ + mov_imm x2, ZYNQMP_UART_BAUDRATE + b console_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, ZYNQMP_CRASH_UART_BASE + b console_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, ZYNQMP_CRASH_UART_BASE + b console_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/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/plat_zynqmp.c b/plat/xilinx/zynqmp/plat_zynqmp.c index cbfa935c2..2441630bd 100644 --- a/plat/xilinx/zynqmp/plat_zynqmp.c +++ b/plat/xilinx/zynqmp/plat_zynqmp.c @@ -1,10 +1,11 @@ /* - * 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 */ -#include <plat_arm.h> +#include <platform.h> +#include "zynqmp_private.h" int plat_core_pos_by_mpidr(u_register_t mpidr) { @@ -14,5 +15,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 zynqmp_calc_core_pos(mpidr); } diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk index 53d93c326..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)) @@ -64,7 +60,6 @@ PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \ drivers/arm/gic/v2/gicv2_helpers.c \ drivers/cadence/uart/aarch64/cdns_console.S \ drivers/console/aarch64/console.S \ - plat/arm/common/aarch64/arm_helpers.S \ plat/arm/common/arm_cci.c \ plat/arm/common/arm_common.c \ plat/arm/common/arm_gicv2.c \ 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/plat/xilinx/zynqmp/zynqmp_def.h b/plat/xilinx/zynqmp/zynqmp_def.h index 50a733176..9d19b1bbd 100644 --- a/plat/xilinx/zynqmp/zynqmp_def.h +++ b/plat/xilinx/zynqmp/zynqmp_def.h @@ -145,13 +145,11 @@ # error "invalid ZYNQMP_CONSOLE" #endif -#define PLAT_ARM_CRASH_UART_BASE ZYNQMP_UART_BASE +#define ZYNQMP_CRASH_UART_BASE ZYNQMP_UART_BASE /* impossible to call C routine how it is done now - hardcode any value */ -#define PLAT_ARM_CRASH_UART_CLK_IN_HZ 100000000 /* FIXME */ - +#define ZYNQMP_CRASH_UART_CLK_IN_HZ 100000000 /* FIXME */ /* Must be non zero */ -#define ZYNQMP_UART_BAUDRATE 115200 -#define ARM_CONSOLE_BAUDRATE ZYNQMP_UART_BAUDRATE +#define ZYNQMP_UART_BAUDRATE 115200 /* Silicon version detection */ #define ZYNQMP_SILICON_VER_MASK 0xF000 diff --git a/plat/xilinx/zynqmp/zynqmp_private.h b/plat/xilinx/zynqmp/zynqmp_private.h index 08a54107a..d5024c3ec 100644 --- a/plat/xilinx/zynqmp/zynqmp_private.h +++ b/plat/xilinx/zynqmp/zynqmp_private.h @@ -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 */ @@ -9,9 +9,12 @@ #include <bl_common.h> #include <interrupt_mgmt.h> +#include <stdint.h> void zynqmp_config_setup(void); +unsigned int zynqmp_calc_core_pos(u_register_t mpidr); + /* ZynqMP specific functions */ unsigned int zynqmp_get_uart_clk(void); unsigned int zynqmp_get_bootmode(void); |