Merge pull request #1088 from soby-mathew/sm/sds_scmi

Introduce SDS Driver
This commit is contained in:
davidcunado-arm 2017-09-12 08:43:38 +01:00 committed by GitHub
commit 487c869d31
24 changed files with 841 additions and 77 deletions

View File

@ -676,9 +676,10 @@ ARM CSS platform specific build options
SCP\_BL2U to the FIP and FWU\_FIP respectively, and enables them to be loaded
during boot. Default is 1.
- ``CSS_USE_SCMI_DRIVER``: Boolean flag which selects SCMI driver instead of
SCPI driver for communicating with the SCP during power management operations.
If this option is set to 1, then SCMI driver will be used. Default is 0.
- ``CSS_USE_SCMI_SDS_DRIVER``: Boolean flag which selects SCMI/SDS drivers
instead of SCPI/BOM driver for communicating with the SCP during power
management operations and for SCP RAM Firmware transfer. If this option
is set to 1, then SCMI/SDS drivers will be used. Default is 0.
ARM FVP platform specific build options
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -266,7 +266,7 @@
/*******************************************************************************
* BL2 specific defines.
******************************************************************************/
#if ARM_BL31_IN_DRAM || defined(AARCH32)
#if ARM_BL31_IN_DRAM || (defined(AARCH32) && !defined(JUNO_AARCH32_EL3_RUNTIME))
/*
* For AArch32 BL31 is not applicable.
* For AArch64 BL31 is loaded in the DRAM.
@ -353,7 +353,7 @@
* FWU Images: NS_BL1U, BL2U & NS_BL2U defines.
******************************************************************************/
#define BL2U_BASE BL2_BASE
#if ARM_BL31_IN_DRAM || defined(AARCH32)
#if ARM_BL31_IN_DRAM || (defined(AARCH32) && !defined(JUNO_AARCH32_EL3_RUNTIME))
/*
* For AArch32 BL31 is not applicable.
* For AArch64 BL31 is loaded in the DRAM.

View File

@ -37,6 +37,9 @@
#define CSS_IRQ_TZ_WDOG 86
#define CSS_IRQ_SEC_SYS_TIMER 91
/* MHU register offsets */
#define MHU_CPU_INTR_S_SET_OFFSET 0x308
/*
* Define a list of Group 1 Secure interrupts as per GICv3 terminology. On a
* GICv2 system or mode, the interrupts will be treated as Group 0 interrupts.
@ -47,17 +50,24 @@
CSS_IRQ_TZ_WDOG, \
CSS_IRQ_SEC_SYS_TIMER
#if CSS_USE_SCMI_SDS_DRIVER
/* Memory region for shared data storage */
#define PLAT_ARM_SDS_MEM_BASE ARM_SHARED_RAM_BASE
#define PLAT_ARM_SDS_MEM_SIZE_MAX 0xDC0 /* 3520 bytes */
/*
* The lower Non-secure MHU channel is being used for SCMI for ARM Trusted
* Firmware.
* TODO: Move SCMI to Secure channel once the migration to SCMI in SCP is
* complete.
* The SCMI Channel is placed right after the SDS region
*/
#define MHU_CPU_INTR_L_SET_OFFSET 0x108
#define MHU_CPU_INTR_H_SET_OFFSET 0x128
#define CSS_SCMI_PAYLOAD_BASE (NSRAM_BASE + 0x500)
#define CSS_SCMI_MHU_DB_REG_OFF MHU_CPU_INTR_L_SET_OFFSET
#define CSS_SCMI_PAYLOAD_BASE (PLAT_ARM_SDS_MEM_BASE + PLAT_ARM_SDS_MEM_SIZE_MAX)
#define CSS_SCMI_MHU_DB_REG_OFF MHU_CPU_INTR_S_SET_OFFSET
/* Trusted mailbox base address common to all CSS */
/* If SDS is present, then mailbox is at top of SRAM */
#define PLAT_ARM_TRUSTED_MAILBOX_BASE (ARM_SHARED_RAM_BASE + ARM_SHARED_RAM_SIZE - 0x8)
/* Number of retries for SCP_RAM_READY flag */
#define CSS_SCP_READY_10US_RETRIES 1000000 /* Effective timeout of 10000 ms */
#else
/*
* SCP <=> AP boot configuration
*
@ -69,6 +79,12 @@
*/
#define SCP_BOOT_CFG_ADDR PLAT_CSS_SCP_COM_SHARED_MEM_BASE
/* Trusted mailbox base address common to all CSS */
/* If SDS is not present, then the mailbox is at the bottom of SRAM */
#define PLAT_ARM_TRUSTED_MAILBOX_BASE ARM_TRUSTED_SRAM_BASE
#endif /* CSS_USE_SCMI_SDS_DRIVER */
#define CSS_MAP_DEVICE MAP_REGION_FLAT( \
CSS_DEVICE_BASE, \
CSS_DEVICE_SIZE, \
@ -152,9 +168,6 @@
/* TZC related constants */
#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT_ALL
/* Trusted mailbox base address common to all CSS */
#define PLAT_ARM_TRUSTED_MAILBOX_BASE ARM_TRUSTED_SRAM_BASE
/*
* Parsing of CPU and Cluster states, as returned by 'Get CSS Power State' SCP
* command

View File

@ -56,15 +56,6 @@ const mmap_region_t plat_arm_mmap[] = {
ARM_MAP_SHARED_RAM,
V2M_MAP_IOFPGA,
CSS_MAP_DEVICE,
#if CSS_USE_SCMI_DRIVER
/*
* The SCMI payload area is currently in the Non Secure SRAM. This is
* a potential security risk but this will be resolved once SCP
* completely replaces SCPI with SCMI as the only communication
* protocol.
*/
CSS_MAP_NSRAM,
#endif
SOC_CSS_MAP_DEVICE,
{0}
};

View File

@ -117,7 +117,6 @@ BL1_SOURCES += drivers/io/io_semihosting.c \
BL2_SOURCES += drivers/io/io_semihosting.c \
drivers/delay_timer/delay_timer.c \
lib/semihosting/semihosting.c \
lib/semihosting/${ARCH}/semihosting_call.S \
plat/arm/board/fvp/fvp_bl2_setup.c \
@ -128,8 +127,6 @@ BL2_SOURCES += drivers/io/io_semihosting.c \
ifeq (${FVP_USE_SP804_TIMER},1)
BL2_SOURCES += drivers/arm/sp804/sp804_delay_timer.c
else
BL2_SOURCES += drivers/delay_timer/generic_delay_timer.c
endif
BL2U_SOURCES += plat/arm/board/fvp/fvp_bl2u_setup.c \

View File

@ -82,13 +82,8 @@
#endif
#ifdef IMAGE_BL31
# if CSS_USE_SCMI_DRIVER
# define PLAT_ARM_MMAP_ENTRIES 6
# define MAX_XLAT_TABLES 3
# else
# define PLAT_ARM_MMAP_ENTRIES 5
# define MAX_XLAT_TABLES 2
# endif
#endif
#ifdef IMAGE_BL32
@ -168,7 +163,9 @@
/*
* Base address of the first memory region used for communication between AP
* and SCP. Used by the BOM and SCPI protocols.
*
*/
#if !CSS_USE_SCMI_SDS_DRIVER
/*
* Note that this is located at the same address as SCP_BOOT_CFG_ADDR, which
* means the SCP/AP configuration data gets overwritten when the AP initiates
* communication with the SCP. The configuration data is expected to be a
@ -178,6 +175,7 @@
#define PLAT_CSS_SCP_COM_SHARED_MEM_BASE (ARM_TRUSTED_SRAM_BASE + 0x80)
#define PLAT_CSS_PRIMARY_CPU_SHIFT 8
#define PLAT_CSS_PRIMARY_CPU_BIT_WIDTH 4
#endif
/*
* PLAT_CSS_MAX_SCP_BL2_SIZE is calculated using the current

View File

@ -30,9 +30,12 @@ int bl2_plat_handle_post_image_load(unsigned int image_id)
return err;
}
#if !CSS_USE_SCMI_SDS_DRIVER
/*
* We need to override some of the platform functions when booting SP_MIN
* on Juno AArch32.
* on Juno AArch32. These needs to be done only for SCPI/BOM SCP systems as
* in case of SDS, the structures remain in memory and doesn't need to be
* overwritten.
*/
static unsigned int scp_boot_config;
@ -53,4 +56,6 @@ void bl2_platform_setup(void)
mmio_write_32(SCP_BOOT_CFG_ADDR, scp_boot_config);
VERBOSE("BL2: Restored SCP Boot config = 0x%x\n", scp_boot_config);
}
#endif
#endif /* JUNO_AARCH32_EL3_RUNTIME */

View File

@ -9,14 +9,10 @@ BL32_SOURCES += lib/cpus/aarch32/cortex_a53.S \
lib/cpus/aarch32/cortex_a57.S \
lib/cpus/aarch32/cortex_a72.S \
plat/arm/board/juno/juno_topology.c \
plat/arm/css/common/css_pm.c \
plat/arm/css/common/css_topology.c \
plat/arm/soc/common/soc_css_security.c \
plat/arm/css/drivers/scp/css_pm_scpi.c \
plat/arm/css/drivers/scpi/css_mhu.c \
plat/arm/css/drivers/scpi/css_scpi.c \
${JUNO_GIC_SOURCES} \
${JUNO_INTERCONNECT_SOURCES} \
${JUNO_SECURITY_SOURCES}
include plat/arm/common/sp_min/arm_sp_min.mk
include plat/arm/css/common/sp_min/css_sp_min.mk

View File

@ -11,6 +11,7 @@
#include <console.h>
#include <debug.h>
#include <desc_image_load.h>
#include <generic_delay_timer.h>
#ifdef SPD_opteed
#include <optee_utils.h>
#endif
@ -182,6 +183,7 @@ void arm_bl2_early_platform_setup(meminfo_t *mem_layout)
void bl2_early_platform_setup(meminfo_t *mem_layout)
{
arm_bl2_early_platform_setup(mem_layout);
generic_delay_timer_init();
}
/*

View File

@ -139,7 +139,9 @@ ifdef EL3_PAYLOAD_BASE
BL1_SOURCES += plat/arm/common/arm_pm.c
endif
BL2_SOURCES += drivers/io/io_fip.c \
BL2_SOURCES += drivers/delay_timer/delay_timer.c \
drivers/delay_timer/generic_delay_timer.c \
drivers/io/io_fip.c \
drivers/io/io_memmap.c \
drivers/io/io_storage.c \
plat/arm/common/arm_bl2_setup.c \
@ -159,7 +161,9 @@ BL2_SOURCES += lib/optee/optee_utils.c
endif
endif
BL2U_SOURCES += plat/arm/common/arm_bl2u_setup.c
BL2U_SOURCES += drivers/delay_timer/delay_timer.c \
drivers/delay_timer/generic_delay_timer.c \
plat/arm/common/arm_bl2u_setup.c
BL31_SOURCES += plat/arm/common/arm_bl31_setup.c \
plat/arm/common/arm_pm.c \

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -68,6 +68,24 @@ endfunc css_calc_core_pos_swap_cluster
* cpu (applicable ony after a cold boot)
* -----------------------------------------------------
*/
#if CSS_USE_SCMI_SDS_DRIVER
func plat_is_my_cpu_primary
mov r10, lr
bl plat_my_core_pos
mov r4, r0
bl sds_get_primary_cpu_id
/* Check for error */
mov r1, #0xffffffff
cmp r0, r1
beq 1f
cmp r0, r4
moveq r0, #1
movne r0, #0
bx r10
1:
no_ret plat_panic_handler
endfunc plat_is_my_cpu_primary
#else
func plat_is_my_cpu_primary
mov r10, lr
bl plat_my_core_pos
@ -80,3 +98,4 @@ func plat_is_my_cpu_primary
movne r0, #0
bx r10
endfunc plat_is_my_cpu_primary
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -88,6 +88,23 @@ endfunc css_calc_core_pos_swap_cluster
* cpu (applicable ony after a cold boot)
* -----------------------------------------------------
*/
#if CSS_USE_SCMI_SDS_DRIVER
func plat_is_my_cpu_primary
mov x9, x30
bl plat_my_core_pos
mov x4, x0
bl sds_get_primary_cpu_id
/* Check for error */
mov x1, #0xffffffff
cmp x0, x1
b.eq 1f
cmp x0, x4
cset w0, eq
ret x9
1:
no_ret plat_panic_handler
endfunc plat_is_my_cpu_primary
#else
func plat_is_my_cpu_primary
mov x9, x30
bl plat_my_core_pos
@ -99,3 +116,4 @@ func plat_is_my_cpu_primary
cset w0, eq
ret x9
endfunc plat_is_my_cpu_primary
#endif

View File

@ -48,10 +48,14 @@ int bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info)
return ret;
}
#ifdef EL3_PAYLOAD_BASE
#if !CSS_USE_SCMI_SDS_DRIVER
# ifdef EL3_PAYLOAD_BASE
/*
* We need to override some of the platform functions when booting an EL3
* payload.
* payload. These needs to be done only for SCPI/BOM SCP systems as
* in case of SDS, the structures remain in memory and doesn't need to be
* overwritten.
*/
static unsigned int scp_boot_config;
@ -82,4 +86,7 @@ void bl2_platform_setup(void)
zeromem((void *) ARM_SHARED_RAM_BASE, 128);
mmio_write_32(SCP_BOOT_CFG_ADDR, scp_boot_config);
}
#endif /* EL3_PAYLOAD_BASE */
# endif /* EL3_PAYLOAD_BASE */
#endif /* CSS_USE_SCMI_SDS_DRIVER */

View File

@ -9,7 +9,7 @@
CSS_LOAD_SCP_IMAGES ?= 1
# By default, SCMI driver is disabled for CSS platforms
CSS_USE_SCMI_DRIVER ?= 0
CSS_USE_SCMI_SDS_DRIVER ?= 0
PLAT_INCLUDES += -Iinclude/plat/arm/css/common \
-Iinclude/plat/arm/css/common/aarch64
@ -19,18 +19,14 @@ PLAT_BL_COMMON_SOURCES += plat/arm/css/common/${ARCH}/css_helpers.S
BL1_SOURCES += plat/arm/css/common/css_bl1_setup.c
BL2_SOURCES += plat/arm/css/common/css_bl2_setup.c \
plat/arm/css/drivers/scpi/css_mhu.c \
plat/arm/css/drivers/scpi/css_scpi.c
BL2_SOURCES += plat/arm/css/common/css_bl2_setup.c
BL2U_SOURCES += plat/arm/css/common/css_bl2u_setup.c \
plat/arm/css/drivers/scpi/css_mhu.c \
plat/arm/css/drivers/scpi/css_scpi.c
BL2U_SOURCES += plat/arm/css/common/css_bl2u_setup.c
BL31_SOURCES += plat/arm/css/common/css_pm.c \
plat/arm/css/common/css_topology.c
ifeq (${CSS_USE_SCMI_DRIVER},0)
ifeq (${CSS_USE_SCMI_SDS_DRIVER},0)
BL31_SOURCES += plat/arm/css/drivers/scp/css_pm_scpi.c \
plat/arm/css/drivers/scpi/css_mhu.c \
plat/arm/css/drivers/scpi/css_scpi.c
@ -56,19 +52,34 @@ ifeq (${CSS_LOAD_SCP_IMAGES},1)
$(eval $(call FWU_FIP_ADD_IMG,SCP_BL2U,--scp-fwu-cfg))
endif
BL2U_SOURCES += plat/arm/css/drivers/scp/css_bom_bootloader.c
BL2_SOURCES += plat/arm/css/drivers/scp/css_bom_bootloader.c
ifeq (${CSS_USE_SCMI_SDS_DRIVER},1)
BL2U_SOURCES += plat/arm/css/drivers/scp/css_sds.c \
plat/arm/css/drivers/sds/sds.c
BL2_SOURCES += plat/arm/css/drivers/scp/css_sds.c \
plat/arm/css/drivers/sds/sds.c
else
BL2U_SOURCES += plat/arm/css/drivers/scp/css_bom_bootloader.c \
plat/arm/css/drivers/scpi/css_mhu.c \
plat/arm/css/drivers/scpi/css_scpi.c
BL2_SOURCES += plat/arm/css/drivers/scp/css_bom_bootloader.c \
plat/arm/css/drivers/scpi/css_mhu.c \
plat/arm/css/drivers/scpi/css_scpi.c
# Enable option to detect whether the SCP ROM firmware in use predates version
# 1.7.0 and therefore, is incompatible.
CSS_DETECT_PRE_1_7_0_SCP := 1
# Process CSS_DETECT_PRE_1_7_0_SCP flag
$(eval $(call assert_boolean,CSS_DETECT_PRE_1_7_0_SCP))
$(eval $(call add_define,CSS_DETECT_PRE_1_7_0_SCP))
endif
endif
# Enable option to detect whether the SCP ROM firmware in use predates version
# 1.7.0 and therefore, is incompatible.
CSS_DETECT_PRE_1_7_0_SCP := 1
# Process CSS_DETECT_PRE_1_7_0_SCP flag
$(eval $(call assert_boolean,CSS_DETECT_PRE_1_7_0_SCP))
$(eval $(call add_define,CSS_DETECT_PRE_1_7_0_SCP))
# Process CSS_USE_SCMI_DRIVER flag
$(eval $(call assert_boolean,CSS_USE_SCMI_DRIVER))
$(eval $(call add_define,CSS_USE_SCMI_DRIVER))
ifeq (${CSS_USE_SCMI_SDS_DRIVER},1)
PLAT_BL_COMMON_SOURCES += plat/arm/css/drivers/sds/${ARCH}/sds_helpers.S
endif
# Process CSS_USE_SCMI_SDS_DRIVER flag
$(eval $(call assert_boolean,CSS_USE_SCMI_SDS_DRIVER))
$(eval $(call add_define,CSS_USE_SCMI_SDS_DRIVER))

View File

@ -0,0 +1,20 @@
#
# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
# SP MIN source files common to CSS platforms
BL32_SOURCES += plat/arm/css/common/css_pm.c \
plat/arm/css/common/css_topology.c
ifeq (${CSS_USE_SCMI_SDS_DRIVER},0)
BL32_SOURCES += plat/arm/css/drivers/scp/css_pm_scpi.c \
plat/arm/css/drivers/scpi/css_mhu.c \
plat/arm/css/drivers/scpi/css_scpi.c
else
BL32_SOURCES += plat/arm/css/drivers/scp/css_pm_scmi.c \
plat/arm/css/drivers/scmi/scmi_common.c \
plat/arm/css/drivers/scmi/scmi_pwr_dmn_proto.c \
plat/arm/css/drivers/scmi/scmi_sys_pwr_proto.c
endif

View File

@ -6,12 +6,12 @@
#include <arch_helpers.h>
#include <assert.h>
#include <cassert.h>
#include <css_def.h>
#include <debug.h>
#include <platform.h>
#include <stdint.h>
#include "../scpi/css_mhu.h"
#include "../scpi/css_scpi.h"
/* ID of the MHU slot used for the BOM protocol */
#define BOM_MHU_SLOT_ID 0
@ -183,3 +183,11 @@ int css_scp_boot_image_xfer(void *image, unsigned int image_size)
return 0;
}
int css_scp_boot_ready(void)
{
VERBOSE("Waiting for SCP to signal it is ready to go on\n");
/* Wait for SCP to signal it's ready */
return scpi_wait_ready();
}

View File

@ -324,8 +324,8 @@ void __dead2 css_scp_sys_reboot(void)
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 = 0xfffffffd,
.db_modify_mask = 0x2,
.db_preserve_mask = 0xfffffffe,
.db_modify_mask = 0x1,
};
void plat_arm_pwrc_setup(void)

View File

@ -7,8 +7,9 @@
#ifndef __CSS_SCP_H__
#define __CSS_SCP_H__
#include <cassert.h>
#include <platform_def.h>
#include <types.h>
#include "../scpi/css_scpi.h"
/* Forward declarations */
struct psci_power_state;
@ -28,10 +29,20 @@ int css_scp_boot_image_xfer(void *image, unsigned int image_size);
* API to wait for SCP to signal till it's ready after booting the transferred
* image.
*/
static inline int css_scp_boot_ready(void)
{
VERBOSE("Waiting for SCP to signal it is ready to go on\n");
return scpi_wait_ready();
}
int css_scp_boot_ready(void);
#if CSS_LOAD_SCP_IMAGES
/*
* All CSS platforms load SCP_BL2/SCP_BL2U just below BL rw-data and above
* BL2/BL2U (this is where BL31 usually resides except when ARM_BL31_IN_DRAM is
* set. Ensure that SCP_BL2/SCP_BL2U do not overflow into BL1 rw-data nor
* BL2/BL2U.
*/
CASSERT(SCP_BL2_LIMIT <= BL1_RW_BASE, assert_scp_bl2_limit_overwrite_bl1);
CASSERT(SCP_BL2U_LIMIT <= BL1_RW_BASE, assert_scp_bl2u_limit_overwrite_bl1);
CASSERT(SCP_BL2_BASE >= BL2_LIMIT, assert_scp_bl2_overwrite_bl2);
CASSERT(SCP_BL2U_BASE >= BL2U_LIMIT, assert_scp_bl2u_overwrite_bl2u);
#endif
#endif /* __CSS_SCP_H__ */

View File

@ -0,0 +1,93 @@
/*
* Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <assert.h>
#include <css_def.h>
#include <debug.h>
#include <delay_timer.h>
#include <platform.h>
#include <stdint.h>
#include "../sds/sds.h"
int css_scp_boot_image_xfer(void *image, unsigned int image_size)
{
int ret;
unsigned int image_offset, image_flags;
ret = sds_init();
if (ret != SDS_OK) {
ERROR("SCP SDS initialization failed\n");
panic();
}
VERBOSE("Writing SCP image metadata\n");
image_offset = (uintptr_t) image - ARM_TRUSTED_SRAM_BASE;
ret = sds_struct_write(SDS_SCP_IMG_STRUCT_ID, SDS_SCP_IMG_ADDR_OFFSET,
&image_offset, SDS_SCP_IMG_ADDR_SIZE,
SDS_ACCESS_MODE_NON_CACHED);
if (ret != SDS_OK)
goto sds_fail;
ret = sds_struct_write(SDS_SCP_IMG_STRUCT_ID, SDS_SCP_IMG_SIZE_OFFSET,
&image_size, SDS_SCP_IMG_SIZE_SIZE,
SDS_ACCESS_MODE_NON_CACHED);
if (ret != SDS_OK)
goto sds_fail;
VERBOSE("Marking SCP image metadata as valid\n");
image_flags = SDS_SCP_IMG_VALID_FLAG_BIT;
ret = sds_struct_write(SDS_SCP_IMG_STRUCT_ID, SDS_SCP_IMG_FLAG_OFFSET,
&image_flags, SDS_SCP_IMG_FLAG_SIZE,
SDS_ACCESS_MODE_NON_CACHED);
if (ret != SDS_OK)
goto sds_fail;
return 0;
sds_fail:
ERROR("SCP SDS write to SCP IMG struct failed\n");
panic();
}
/*
* API to wait for SCP to signal till it's ready after booting the transferred
* image.
*/
int css_scp_boot_ready(void)
{
uint32_t scp_feature_availability_flags;
int ret, retry = CSS_SCP_READY_10US_RETRIES;
VERBOSE("Waiting for SCP RAM to complete its initialization process\n");
/* Wait for the SCP RAM Firmware to complete its initialization process */
while (retry > 0) {
ret = sds_struct_read(SDS_FEATURE_AVAIL_STRUCT_ID, 0,
&scp_feature_availability_flags,
SDS_FEATURE_AVAIL_SIZE,
SDS_ACCESS_MODE_NON_CACHED);
if (ret == SDS_ERR_STRUCT_NOT_FINALIZED)
continue;
if (ret != SDS_OK) {
ERROR(" sds_struct_read failed\n");
panic();
}
if (scp_feature_availability_flags &
SDS_FEATURE_AVAIL_SCP_RAM_READY_BIT)
return 0;
udelay(10);
retry--;
}
ERROR("Timeout of %d ms expired waiting for SCP RAM Ready flag\n",
CSS_SCP_READY_10US_RETRIES/100);
plat_panic_handler();
}

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
#include <asm_macros.S>
#include <platform_def.h>
#include "../sds.h"
#include "../sds_private.h"
.globl sds_get_primary_cpu_id
/*
* int sds_get_primary_cpu_id(void);
* Return the primary CPU ID from SDS Structure
* Returns CPUID on success or -1 on failure
*/
func sds_get_primary_cpu_id
ldr r0, =PLAT_ARM_SDS_MEM_BASE
ldr r2, =SDS_REGION_SIGNATURE
ldr r1, [r0]
ubfx r3, r1, #0, #16
/* Check if the SDS region signature found */
cmp r2, r3
bne 2f
/* Get the structure count from region descriptor in r1 */
ubfx r1, r1, #SDS_REGION_STRUCT_COUNT_SHIFT, #SDS_REGION_STRUCT_COUNT_WIDTH
cmp r1, #0
beq 2f
add r0, r0, #SDS_REGION_DESC_SIZE
/* Initialize the loop iterator count in r3 */
mov r3, #0
loop_begin:
ldrh r2, [r0]
cmp r2, #SDS_AP_CPU_INFO_STRUCT_ID
bne continue_loop
/* We have found the required structure */
ldr r0, [r0,#(SDS_HEADER_SIZE + SDS_AP_CPU_INFO_PRIMARY_CPUID_OFFSET)]
bx lr
continue_loop:
/* Increment the loop counter and exit loop if counter == structure count */
add r3, r3, #0x1
cmp r1, r3
beq 2f
/* Read the 2nd word in header */
ldr r2, [r0,#4]
/* Get the structure size from header */
ubfx r2, r2, #SDS_HEADER_STRUCT_SIZE_SHIFT, #SDS_HEADER_STRUCT_SIZE_WIDTH
/* Add the structure size and SDS HEADER SIZE to point to next header */
add r2, r2, #SDS_HEADER_SIZE
add r0, r0, r2
b loop_begin
2:
mov r0, #0xffffffff
bx lr
endfunc sds_get_primary_cpu_id

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
#include <asm_macros.S>
#include <platform_def.h>
#include "../sds.h"
#include "../sds_private.h"
.globl sds_get_primary_cpu_id
/*
* int sds_get_primary_cpu_id(void);
* Return the primary CPI ID from SDS Structure
* Returns CPUID on success or -1 on failure
*/
func sds_get_primary_cpu_id
mov_imm x0, PLAT_ARM_SDS_MEM_BASE
mov w2, #SDS_REGION_SIGNATURE
ldr w1, [x0]
/* Check if the SDS region signature found */
cmp w2, w1, uxth
b.ne 2f
/* Get the structure count from region descriptor in `w1 */
ubfx w1, w1, #SDS_REGION_STRUCT_COUNT_SHIFT, #SDS_REGION_STRUCT_COUNT_WIDTH
cbz w1, 2f
add x0, x0, #SDS_REGION_DESC_SIZE
/* Initialize the loop iterator count in w3 */
mov w3, #0
loop_begin:
ldrh w2, [x0]
cmp w2, #SDS_AP_CPU_INFO_STRUCT_ID
b.ne continue_loop
/* We have found the required structure */
ldr w0, [x0,#(SDS_HEADER_SIZE + SDS_AP_CPU_INFO_PRIMARY_CPUID_OFFSET)]
ret
continue_loop:
/* Increment the loop counter and exit loop if counter == structure count */
add w3, w3, #0x1
cmp w1, w3
b.eq 2f
/* Read the 2nd word in header */
ldr w2, [x0,#4]
/* Get the structure size from header */
ubfx x2, x2, #SDS_HEADER_STRUCT_SIZE_SHIFT, #SDS_HEADER_STRUCT_SIZE_WIDTH
/* Add the structure size and SDS HEADER SIZE to point to next header */
add x2, x2, #SDS_HEADER_SIZE
add x0, x0, x2
b loop_begin
2:
mov w0, #0xffffffff
ret
endfunc sds_get_primary_cpu_id

View File

@ -0,0 +1,258 @@
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <assert.h>
#include <debug.h>
#include <css_def.h>
#include <stdint.h>
#include <string.h>
#include "sds.h"
#include "sds_private.h"
/*
* Variables used to track and maintain the state of the memory region reserved
* for usage by the SDS framework.
*/
/* Pointer to the base of the SDS memory region */
static uintptr_t sds_mem_base;
/* Size of the SDS memory region in bytes */
static size_t sds_mem_size;
/*
* Perform some non-exhaustive tests to determine whether any of the fields
* within a Structure Header contain obviously invalid data.
* Returns SDS_OK on success, SDS_ERR_FAIL on error.
*/
static int sds_struct_is_valid(uintptr_t header)
{
size_t struct_size = GET_SDS_HEADER_STRUCT_SIZE(header);
/* Zero is not a valid identifier */
if (GET_SDS_HEADER_ID(header) == 0)
return SDS_ERR_FAIL;
/* Check SDS Schema version */
if (GET_SDS_HEADER_VERSION(header) == SDS_REGION_SCH_VERSION)
return SDS_ERR_FAIL;
/* The SDS Structure sizes have to be multiple of 8 */
if ((struct_size == 0) || ((struct_size % 8) != 0))
return SDS_ERR_FAIL;
if (struct_size > sds_mem_size)
return SDS_ERR_FAIL;
return SDS_OK;
}
/*
* Validate the SDS structure headers.
* Returns SDS_OK on success, SDS_ERR_FAIL on error.
*/
static int validate_sds_struct_headers(void)
{
unsigned int i, structure_count;
uintptr_t header;
structure_count = GET_SDS_REGION_STRUCTURE_COUNT(sds_mem_base);
if (structure_count == 0)
return SDS_ERR_FAIL;
header = sds_mem_base + SDS_REGION_DESC_SIZE;
/* Iterate over structure headers and validate each one */
for (i = 0; i < structure_count; i++) {
if (sds_struct_is_valid(header) != SDS_OK) {
WARN("SDS: Invalid structure header detected\n");
return SDS_ERR_FAIL;
}
header += GET_SDS_HEADER_STRUCT_SIZE(header) + SDS_HEADER_SIZE;
}
return SDS_OK;
}
/*
* Get the structure header pointer corresponding to the structure ID.
* Returns SDS_OK on success, SDS_ERR_STRUCT_NOT_FOUND on error.
*/
static int get_struct_header(uint32_t structure_id, struct_header_t **header)
{
unsigned int i, structure_count;
uintptr_t current_header;
assert(header);
structure_count = GET_SDS_REGION_STRUCTURE_COUNT(sds_mem_base);
if (structure_count == 0)
return SDS_ERR_STRUCT_NOT_FOUND;
current_header = ((uintptr_t)sds_mem_base) + SDS_REGION_DESC_SIZE;
/* Iterate over structure headers to find one with a matching ID */
for (i = 0; i < structure_count; i++) {
if (GET_SDS_HEADER_ID(current_header) == structure_id) {
*header = (struct_header_t *)current_header;
return SDS_OK;
}
current_header += GET_SDS_HEADER_STRUCT_SIZE(current_header) +
SDS_HEADER_SIZE;
}
*header = NULL;
return SDS_ERR_STRUCT_NOT_FOUND;
}
/*
* Check if a structure header corresponding to the structure ID exists.
* Returns SDS_OK if structure header exists else SDS_ERR_STRUCT_NOT_FOUND
* if not found.
*/
int sds_struct_exists(unsigned int structure_id)
{
struct_header_t *header = NULL;
int ret;
ret = get_struct_header(structure_id, &header);
if (ret == SDS_OK) {
assert(header);
}
return ret;
}
/*
* Read from field in the structure corresponding to `structure_id`.
* `fld_off` is the offset to the field in the structure and `mode`
* indicates whether cache maintenance need to performed prior to the read.
* The `data` is the pointer to store the read data of size specified by `size`.
* Returns SDS_OK on success or corresponding error codes on failure.
*/
int sds_struct_read(uint32_t structure_id, unsigned int fld_off,
void *data, size_t size, sds_access_mode_t mode)
{
int status;
uintptr_t field_base;
struct_header_t *header = NULL;
if (!data)
return SDS_ERR_INVALID_PARAMS;
/* Check if a structure with this ID exists */
status = get_struct_header(structure_id, &header);
if (status != SDS_OK)
return status;
assert(header);
if (mode == SDS_ACCESS_MODE_CACHED)
inv_dcache_range((uintptr_t)header, SDS_HEADER_SIZE + size);
if (!IS_SDS_HEADER_VALID(header)) {
WARN("SDS: Reading from un-finalized structure 0x%x\n",
structure_id);
return SDS_ERR_STRUCT_NOT_FINALIZED;
}
if ((fld_off + size) > GET_SDS_HEADER_STRUCT_SIZE(header))
return SDS_ERR_FAIL;
field_base = (uintptr_t)header + SDS_HEADER_SIZE + fld_off;
if (check_uptr_overflow(field_base, size - 1))
return SDS_ERR_FAIL;
/* Copy the required field in the struct */
memcpy(data, (void *)field_base, size);
return SDS_OK;
}
/*
* Write to the field in the structure corresponding to `structure_id`.
* `fld_off` is the offset to the field in the structure and `mode`
* indicates whether cache maintenance need to performed for the write.
* The `data` is the pointer to data of size specified by `size`.
* Returns SDS_OK on success or corresponding error codes on failure.
*/
int sds_struct_write(uint32_t structure_id, unsigned int fld_off,
void *data, size_t size, sds_access_mode_t mode)
{
int status;
uintptr_t field_base;
struct_header_t *header = NULL;
if (!data)
return SDS_ERR_INVALID_PARAMS;
/* Check if a structure with this ID exists */
status = get_struct_header(structure_id, &header);
if (status != SDS_OK)
return status;
assert(header);
if (mode == SDS_ACCESS_MODE_CACHED)
inv_dcache_range((uintptr_t)header, SDS_HEADER_SIZE + size);
if (!IS_SDS_HEADER_VALID(header)) {
WARN("SDS: Writing to un-finalized structure 0x%x\n",
structure_id);
return SDS_ERR_STRUCT_NOT_FINALIZED;
}
if ((fld_off + size) > GET_SDS_HEADER_STRUCT_SIZE(header))
return SDS_ERR_FAIL;
field_base = (uintptr_t)header + SDS_HEADER_SIZE + fld_off;
if (check_uptr_overflow(field_base, size - 1))
return SDS_ERR_FAIL;
/* Copy the required field in the struct */
memcpy((void *)field_base, data, size);
if (mode == SDS_ACCESS_MODE_CACHED)
flush_dcache_range((uintptr_t)field_base, size);
return SDS_OK;
}
/*
* Initialize the SDS driver. Also verifies the SDS version and sanity of
* the SDS structure headers.
* Returns SDS_OK on success, SDS_ERR_FAIL on error.
*/
int sds_init(void)
{
sds_mem_base = (uintptr_t)PLAT_ARM_SDS_MEM_BASE;
if (!IS_SDS_REGION_VALID(sds_mem_base)) {
WARN("SDS: No valid SDS Memory Region found\n");
return SDS_ERR_FAIL;
}
if (GET_SDS_REGION_SCHEMA_VERSION(sds_mem_base)
!= SDS_REGION_SCH_VERSION) {
WARN("SDS: Unsupported SDS schema version\n");
return SDS_ERR_FAIL;
}
sds_mem_size = GET_SDS_REGION_SIZE(sds_mem_base);
if (sds_mem_size > PLAT_ARM_SDS_MEM_SIZE_MAX) {
WARN("SDS: SDS Memory Region exceeds size limit\n");
return SDS_ERR_FAIL;
}
INFO("SDS: Detected SDS Memory Region (%zu bytes)\n", sds_mem_size);
if (validate_sds_struct_headers() != SDS_OK)
return SDS_ERR_FAIL;
return SDS_OK;
}

View File

@ -0,0 +1,89 @@
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __SDS_H__
#define __SDS_H__
/* SDS Structure Identifier defines */
/* AP CPU INFO defines */
#define SDS_AP_CPU_INFO_STRUCT_ID 1
#define SDS_AP_CPU_INFO_PRIMARY_CPUID_OFFSET 0x0
#define SDS_AP_CPU_INFO_PRIMARY_CPUID_SIZE 0x4
/* ROM Firmware Version defines */
#define SDS_ROM_VERSION_STRUCT_ID 2
#define SDS_ROM_VERSION_OFFSET 0x0
#define SDS_ROM_VERSION_SIZE 0x4
/* RAM Firmware version defines */
#define SDS_RAM_VERSION_STRUCT_ID 3
#define SDS_RAM_VERSION_OFFSET 0x0
#define SDS_RAM_VERSION_SIZE 0x4
/* Platform Identity defines */
#define SDS_PLATFORM_IDENTITY_STRUCT_ID 4
#define SDS_PLATFORM_IDENTITY_ID_OFFSET 0x0
#define SDS_PLATFORM_IDENTITY_ID_SIZE 0x4
#define SDS_PLATFORM_IDENTITY_ID_CONFIG_SHIFT 28
#define SDS_PLATFORM_IDENTITY_ID_CONFIG_WIDTH 4
#define SDS_PLATFORM_IDENTITY_ID_CONFIG_MASK \
((1 << SDS_PLATFORM_IDENTITY_ID_CONFIG_WIDTH) - 1)
#define SDS_PLATFORM_IDENTITY_PLAT_TYPE_OFFSET 0x4
#define SDS_PLATFORM_IDENTITY_PLAT_TYPE_SIZE 0x4
/* Reset Syndrome defines */
#define SDS_RESET_SYNDROME_STRUCT_ID 5
#define SDS_RESET_SYNDROME_OFFSET 0
#define SDS_RESET_SYNDROME_SIZE 4
#define SDS_RESET_SYNDROME_POW_ON_RESET_BIT (1 << 0)
#define SDS_RESET_SYNDROME_SCP_WD_RESET_BIT (1 << 1)
#define SDS_RESET_SYNDROME_AP_WD_RESET_BIT (1 << 2)
#define SDS_RESET_SYNDROME_SYS_RESET_REQ_BIT (1 << 3)
#define SDS_RESET_SYNDROME_M3_LOCKUP_BIT (1 << 4)
/* SCP Firmware Feature Availability defines */
#define SDS_FEATURE_AVAIL_STRUCT_ID 6
#define SDS_FEATURE_AVAIL_OFFSET 0
#define SDS_FEATURE_AVAIL_SIZE 4
#define SDS_FEATURE_AVAIL_SCP_RAM_READY_BIT (1 << 0)
#define SDS_FEATURE_AVAIL_DMC_READY_BIT (1 << 1)
#define SDS_FEATURE_AVAIL_MSG_IF_READY_BIT (1 << 2)
/* SCP BL2 Image Metadata defines */
#define SDS_SCP_IMG_STRUCT_ID 9
#define SDS_SCP_IMG_FLAG_OFFSET 0
#define SDS_SCP_IMG_FLAG_SIZE 4
#define SDS_SCP_IMG_VALID_FLAG_BIT (1 << 0)
#define SDS_SCP_IMG_ADDR_OFFSET 4
#define SDS_SCP_IMG_ADDR_SIZE 4
#define SDS_SCP_IMG_SIZE_OFFSET 8
#define SDS_SCP_IMG_SIZE_SIZE 4
/* SDS Driver Error Codes */
#define SDS_OK 0
#define SDS_ERR_FAIL -1
#define SDS_ERR_INVALID_PARAMS -2
#define SDS_ERR_STRUCT_NOT_FOUND -3
#define SDS_ERR_STRUCT_NOT_FINALIZED -4
#ifndef __ASSEMBLY__
#include <stddef.h>
#include <stdint.h>
typedef enum {
SDS_ACCESS_MODE_NON_CACHED,
SDS_ACCESS_MODE_CACHED,
} sds_access_mode_t;
int sds_init(void);
int sds_struct_exists(uint32_t structure_id);
int sds_struct_read(uint32_t structure_id, unsigned int fld_off, void *data,
size_t size, sds_access_mode_t mode);
int sds_struct_write(uint32_t structure_id, unsigned int fld_off, void *data,
size_t size, sds_access_mode_t mode);
#endif /*__ASSEMBLY__ */
#endif /* __SDS_H__ */

View File

@ -0,0 +1,99 @@
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __SDS_PRIVATE_H__
#define __SDS_PRIVATE_H__
/* SDS Header defines */
#define SDS_HEADER_ID_SHIFT 0
#define SDS_HEADER_ID_WIDTH 16
#define SDS_HEADER_ID_MASK ((1 << SDS_HEADER_ID_WIDTH) - 1)
#define SDS_HEADER_MINOR_VERSION_WIDTH 8
#define SDS_HEADER_MINOR_VERSION_SHIFT 16
#define SDS_HEADER_MAJOR_VERSION_WIDTH 8
#define MAKE_SDS_HEADER_VERSION(major, minor) \
(((((major) & 0xff) << SDS_HEADER_MINOR_VERSION_WIDTH) | ((minor) & 0xff)))
#define SDS_HEADER_VERSION_MASK \
((1 << (SDS_HEADER_MINOR_VERSION_WIDTH + SDS_HEADER_MAJOR_VERSION_WIDTH)) - 1)
#define SDS_HEADER_VERSION MAKE_SDS_HEADER_VERSION(1, 0)
#define SDS_HEADER_STRUCT_SIZE_WIDTH 23
#define SDS_HEADER_STRUCT_SIZE_SHIFT 1
#define SDS_HEADER_STRUCT_SIZE_MASK ((1 << SDS_HEADER_STRUCT_SIZE_WIDTH) - 1)
#define SDS_HEADER_VALID_MASK 0x1
#define SDS_HEADER_VALID_SHIFT 0
#define SDS_HEADER_SIZE 0x8
/* Arbitrary, 16 bit value that indicates a valid SDS Memory Region */
#define SDS_REGION_SIGNATURE 0xAA7A
#define SDS_REGION_SIGNATURE_WIDTH 16
#define SDS_REGION_SIGNATURE_SHIFT 0
#define SDS_REGION_SIGNATURE_MASK ((1 << SDS_REGION_SIGNATURE_WIDTH) - 1)
#define SDS_REGION_STRUCT_COUNT_SHIFT 16
#define SDS_REGION_STRUCT_COUNT_WIDTH 8
#define SDS_REGION_STRUCT_COUNT_MASK ((1 << SDS_REGION_STRUCT_COUNT_WIDTH) - 1)
#define SDS_REGION_SCH_MINOR_SHIFT 24
#define SDS_REGION_SCH_MINOR_WIDTH 4
#define SDS_REGION_SCH_MINOR_MASK ((1 << SDS_REGION_SCH_MINOR_WIDTH) - 1)
#define SDS_REGION_SCH_MAJOR_SHIFT 28
#define SDS_REGION_SCH_MAJOR_WIDTH 4
#define SDS_REGION_SCH_MAJOR_MASK ((1 << SDS_REGION_SCH_MAJOR_WIDTH) - 1)
#define SDS_REGION_SCH_VERSION_MASK \
((1 << (SDS_REGION_SCH_MINOR_WIDTH + SDS_REGION_SCH_MAJOR_WIDTH)) - 1)
#define MAKE_SDS_REGION_SCH_VERSION(maj, min) \
((((maj) & SDS_REGION_SCH_MAJOR_MASK) << SDS_REGION_SCH_MINOR_WIDTH) | \
((min) & SDS_REGION_SCH_MINOR_MASK))
#define SDS_REGION_SCH_VERSION MAKE_SDS_REGION_SCH_VERSION(1, 0)
#define SDS_REGION_REGIONSIZE_OFFSET 0x4
#define SDS_REGION_DESC_SIZE 0x8
#ifndef __ASSEMBLY__
#include <stddef.h>
#include <stdint.h>
/* Header containing Shared Data Structure metadata */
typedef struct structure_header {
uint32_t reg[2];
} struct_header_t;
#define GET_SDS_HEADER_ID(header) \
((((struct_header_t *)(header))->reg[0]) & SDS_HEADER_ID_MASK)
#define GET_SDS_HEADER_VERSION(header) \
(((((struct_header_t *)(header))->reg[0]) >> SDS_HEADER_MINOR_VERSION_SHIFT)\
& SDS_HEADER_VERSION_MASK)
#define GET_SDS_HEADER_STRUCT_SIZE(header) \
(((((struct_header_t *)(header))->reg[1]) >> SDS_HEADER_STRUCT_SIZE_SHIFT)\
& SDS_HEADER_STRUCT_SIZE_MASK)
#define IS_SDS_HEADER_VALID(header) \
((((struct_header_t *)(header))->reg[1]) & SDS_HEADER_VALID_MASK)
#define GET_SDS_STRUCT_FIELD(header, field_offset) \
((((uint8_t *)(header)) + sizeof(struct_header_t)) + (field_offset))
/* Region Descriptor describing the SDS Memory Region */
typedef struct region_descriptor {
uint32_t reg[2];
} region_desc_t;
#define IS_SDS_REGION_VALID(region) \
(((((region_desc_t *)(region))->reg[0]) & SDS_REGION_SIGNATURE_MASK) == SDS_REGION_SIGNATURE)
#define GET_SDS_REGION_STRUCTURE_COUNT(region) \
(((((region_desc_t *)(region))->reg[0]) >> SDS_REGION_STRUCT_COUNT_SHIFT)\
& SDS_REGION_STRUCT_COUNT_MASK)
#define GET_SDS_REGION_SCHEMA_VERSION(region) \
(((((region_desc_t *)(region))->reg[0]) >> SDS_REGION_SCH_MINOR_SHIFT)\
& SDS_REGION_SCH_VERSION_MASK)
#define GET_SDS_REGION_SIZE(region) ((((region_desc_t *)(region))->reg[1]))
#endif /* __ASSEMBLY__ */
#endif /* __SDS_PRIVATE_H__ */