Merge pull request #582 from jcastillo-arm/jc/fip_extract
fip_create: add support for image unpacking
diff --git a/.gitignore b/.gitignore
index cc5cbfb..7447227 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,6 +11,12 @@
# Ignore build products from tools
tools/**/*.o
tools/fip_create/fip_create
+tools/fip_create/fip_create.exe
tools/cert_create/src/*.o
tools/cert_create/src/**/*.o
tools/cert_create/cert_create
+tools/cert_create/cert_create.exe
+
+# Ignore header files copied.
+tools/fip_create/firmware_image_package.h
+tools/fip_create/uuid.h
diff --git a/Makefile b/Makefile
index ac688ba..b2ca916 100644
--- a/Makefile
+++ b/Makefile
@@ -37,7 +37,9 @@
# Default goal is build all images
.DEFAULT_GOAL := all
-include make_helpers/build_macros.mk
+MAKE_HELPERS_DIRECTORY := make_helpers/
+include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
+include ${MAKE_HELPERS_DIRECTORY}build_env.mk
################################################################################
# Default values for build configurations
@@ -111,9 +113,10 @@
CHECKPATCH_ARGS := --no-tree --no-signoff ${CHECK_IGNORE}
CHECKCODE_ARGS := --no-patch --no-tree --no-signoff ${CHECK_IGNORE}
# Do not check the coding style on C library files
-CHECK_PATHS := $(shell ls -I include -I lib) \
- $(addprefix include/,$(shell ls -I stdlib include)) \
- $(addprefix lib/,$(shell ls -I stdlib lib))
+INCLUDE_DIRS_TO_CHECK := $(sort $(filter-out include/stdlib, $(wildcard include/*)))
+LIB_DIRS_TO_CHECK := $(sort $(filter-out lib/stdlib, $(wildcard lib/*)))
+ROOT_DIRS_TO_CHECK := $(sort $(filter-out lib include, $(wildcard *))))
+CHECK_PATHS := ${ROOT_DIRS_TO_CHECK} ${INCLUDE_DIRS_TO_CHECK} ${LIB_DIRS_TO_CHECK}
################################################################################
@@ -122,10 +125,10 @@
# Verbose flag
ifeq (${V},0)
- Q=@
+ Q:=@
CHECKCODE_ARGS += --no-summary --terse
else
- Q=
+ Q:=
endif
export Q
@@ -196,8 +199,19 @@
common/aarch64/debug.S \
lib/aarch64/cache_helpers.S \
lib/aarch64/misc_helpers.S \
- lib/aarch64/xlat_helpers.c \
- lib/stdlib/std.c \
+ lib/stdlib/abort.c \
+ lib/stdlib/assert.c \
+ lib/stdlib/exit.c \
+ lib/stdlib/mem.c \
+ lib/stdlib/printf.c \
+ lib/stdlib/putchar.c \
+ lib/stdlib/puts.c \
+ lib/stdlib/sscanf.c \
+ lib/stdlib/strchr.c \
+ lib/stdlib/strcmp.c \
+ lib/stdlib/strlen.c \
+ lib/stdlib/strncmp.c \
+ lib/stdlib/subr_prf.c \
plat/common/aarch64/platform_helpers.S
INCLUDES += -Iinclude/bl1 \
@@ -223,17 +237,12 @@
# Generic definitions
################################################################################
+include ${MAKE_HELPERS_DIRECTORY}plat_helpers.mk
+
BUILD_BASE := ./build
BUILD_PLAT := ${BUILD_BASE}/${PLAT}/${BUILD_TYPE}
-PLAT_MAKEFILE := platform.mk
-# Generate the platforms list by recursively searching for all directories
-# under /plat containing a PLAT_MAKEFILE. Append each platform with a `|`
-# char and strip out the final '|'.
-PLATFORMS := $(shell find plat/ -name '${PLAT_MAKEFILE}' -print0 | \
- sed -r 's%[^\x00]*\/([^/]*)\/${PLAT_MAKEFILE}\x00%\1|%g' | \
- sed -r 's/\|$$//')
-SPDS := $(shell ls -I none services/spd)
+SPDS := $(sort $(filter-out none, $(patsubst services/spd/%,%,$(wildcard services/spd/*))))
# Platforms providing their own TBB makefile may override this value
INCLUDE_TBBR_MK := 1
@@ -249,7 +258,7 @@
$(warning "The SPD and its BL32 companion will be present but ignored.")
endif
# We expect to locate an spd.mk under the specified SPD directory
- SPD_MAKE := $(shell m="services/spd/${SPD}/${SPD}.mk"; [ -f "$$m" ] && echo "$$m")
+ SPD_MAKE := $(wildcard services/spd/${SPD}/${SPD}.mk)
ifeq (${SPD_MAKE},)
$(error Error: No services/spd/${SPD}/${SPD}.mk located)
@@ -274,14 +283,6 @@
# makefile may use all previous definitions in this file)
################################################################################
-ifeq (${PLAT},)
- $(error "Error: Unknown platform. Please use PLAT=<platform name> to specify the platform")
-endif
-PLAT_MAKEFILE_FULL := $(shell find plat/ -wholename '*/${PLAT}/${PLAT_MAKEFILE}')
-ifeq ($(PLAT_MAKEFILE_FULL),)
- $(error "Error: Invalid platform. The following platforms are available: ${PLATFORMS}")
-endif
-
include ${PLAT_MAKEFILE_FULL}
# If the platform has not defined ENABLE_PLAT_COMPAT, then enable it by default
@@ -301,6 +302,29 @@
################################################################################
+# Check incompatible options
+################################################################################
+
+ifdef EL3_PAYLOAD_BASE
+ ifdef BL33_BASE
+ $(warning "BL33_BASE and EL3_PAYLOAD_BASE are incompatible \
+ build options. EL3_PAYLOAD_BASE has priority.")
+ endif
+endif
+
+ifeq (${NEED_BL33},yes)
+ ifdef EL3_PAYLOAD_BASE
+ $(warning "BL33 image is not needed when option \
+ BL33_PAYLOAD_BASE is used and won't be added to the FIP file.")
+ endif
+ ifdef BL33_BASE
+ $(warning "BL33 image is not needed when option BL33_BASE is \
+ used and won't be added to the FIP file.")
+ endif
+endif
+
+
+################################################################################
# Process platform overrideable behaviour
################################################################################
@@ -313,12 +337,19 @@
# supplied for the FIP and Certificate generation tools. This flag can be
# overridden by the platform.
ifdef BL2_SOURCES
-ifndef EL3_PAYLOAD_BASE
-NEED_BL33 ?= yes
-else
-# The BL33 image is not needed when booting an EL3 payload.
-NEED_BL33 := no
-endif
+ ifdef EL3_PAYLOAD_BASE
+ # If booting an EL3 payload there is no need for a BL33 image
+ # in the FIP file.
+ NEED_BL33 := no
+ else
+ ifdef BL33_BASE
+ # If booting a BL33 preloaded image there is no need of
+ # another one in the FIP file.
+ NEED_BL33 := no
+ else
+ NEED_BL33 ?= yes
+ endif
+ endif
endif
# Process TBB related flags
@@ -345,11 +376,11 @@
# Variables for use with Certificate Generation Tool
CRTTOOLPATH ?= tools/cert_create
-CRTTOOL ?= ${CRTTOOLPATH}/cert_create
+CRTTOOL ?= ${CRTTOOLPATH}/cert_create${BIN_EXT}
# Variables for use with Firmware Image Package
FIPTOOLPATH ?= tools/fip_create
-FIPTOOL ?= ${FIPTOOLPATH}/fip_create
+FIPTOOL ?= ${FIPTOOLPATH}/fip_create${BIN_EXT}
################################################################################
@@ -398,11 +429,17 @@
$(eval $(call add_define,ERROR_DEPRECATED))
$(eval $(call add_define,ENABLE_PLAT_COMPAT))
$(eval $(call add_define,SPIN_ON_BL1_EXIT))
+$(eval $(call add_define,PL011_GENERIC_UART))
# Define the EL3_PAYLOAD_BASE flag only if it is provided.
ifdef EL3_PAYLOAD_BASE
-$(eval $(call add_define,EL3_PAYLOAD_BASE))
+ $(eval $(call add_define,EL3_PAYLOAD_BASE))
+else
+ # Define the BL33_BASE flag only if it is provided and EL3_PAYLOAD_BASE
+ # is not defined, as it has priority.
+ ifdef BL33_BASE
+ $(eval $(call add_define,BL33_BASE))
+ endif
endif
-$(eval $(call add_define,PL011_GENERIC_UART))
################################################################################
@@ -498,14 +535,14 @@
clean:
@echo " CLEAN"
- ${Q}rm -rf ${BUILD_PLAT}
+ $(call SHELL_REMOVE_DIR,${BUILD_PLAT})
${Q}${MAKE} --no-print-directory -C ${FIPTOOLPATH} clean
${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${CRTTOOLPATH} clean
realclean distclean:
@echo " REALCLEAN"
- ${Q}rm -rf ${BUILD_BASE}
- ${Q}rm -f ${CURDIR}/cscope.*
+ $(call SHELL_REMOVE_DIR,${BUILD_BASE})
+ $(call SHELL_DELETE_ALL, ${CURDIR}/cscope.*)
${Q}${MAKE} --no-print-directory -C ${FIPTOOLPATH} clean
${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${CRTTOOLPATH} clean
@@ -526,24 +563,24 @@
.PHONY: ${CRTTOOL}
${CRTTOOL}:
${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${CRTTOOLPATH}
- @echo
+ @${ECHO_BLANK_LINE}
@echo "Built $@ successfully"
- @echo
+ @${ECHO_BLANK_LINE}
ifneq (${GENERATE_COT},0)
certificates: ${CRT_DEPS} ${CRTTOOL}
${Q}${CRTTOOL} ${CRT_ARGS}
- @echo
+ @${ECHO_BLANK_LINE}
@echo "Built $@ successfully"
@echo "Certificates can be found in ${BUILD_PLAT}"
- @echo
+ @${ECHO_BLANK_LINE}
endif
${BUILD_PLAT}/${FIP_NAME}: ${FIP_DEPS} ${FIPTOOL}
${Q}${FIPTOOL} --dump ${FIP_ARGS} $@
- @echo
+ @${ECHO_BLANK_LINE}
@echo "Built $@ successfully"
- @echo
+ @${ECHO_BLANK_LINE}
ifneq (${GENERATE_COT},0)
fwu_certificates: ${FWU_CRT_DEPS} ${CRTTOOL}
@@ -574,7 +611,7 @@
${Q}cscope -b -q -k
help:
- @echo "usage: ${MAKE} PLAT=<${PLATFORMS}> [OPTIONS] [TARGET]"
+ @echo "usage: ${MAKE} PLAT=<${PLATFORM_LIST}> [OPTIONS] [TARGET]"
@echo ""
@echo "PLAT is used to specify which platform you wish to build."
@echo "If no platform is specified, PLAT defaults to: ${DEFAULT_PLAT}"
diff --git a/bl1/aarch64/bl1_arch_setup.c b/bl1/aarch64/bl1_arch_setup.c
index 6a3f062..61c01e1 100644
--- a/bl1/aarch64/bl1_arch_setup.c
+++ b/bl1/aarch64/bl1_arch_setup.c
@@ -38,7 +38,7 @@
void bl1_arch_setup(void)
{
/* Set the next EL to be AArch64 */
- write_scr_el3(SCR_RES1_BITS | SCR_RW_BIT);
+ write_scr_el3(read_scr_el3() | SCR_RW_BIT);
}
/*******************************************************************************
diff --git a/bl1/bl1_context_mgmt.c b/bl1/bl1_context_mgmt.c
index 6355190..bd40608 100644
--- a/bl1/bl1_context_mgmt.c
+++ b/bl1/bl1_context_mgmt.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -74,7 +74,7 @@
next_bl_ep = &image_desc->ep_info;
/* Get the image security state. */
- security_state = GET_SEC_STATE(next_bl_ep->h.attr);
+ security_state = GET_SECURITY_STATE(next_bl_ep->h.attr);
/* Setup the Secure/Non-Secure context if not done already. */
if (!cm_get_context(security_state))
diff --git a/bl1/bl1_fwu.c b/bl1/bl1_fwu.c
index 80ce831..f333805 100644
--- a/bl1/bl1_fwu.c
+++ b/bl1/bl1_fwu.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -135,8 +135,8 @@
}
/* Only Normal world is allowed to copy a Secure image. */
- if ((GET_SEC_STATE(flags) == SECURE) ||
- (GET_SEC_STATE(image_desc->ep_info.h.attr) == NON_SECURE)) {
+ if ((GET_SECURITY_STATE(flags) == SECURE) ||
+ (GET_SECURITY_STATE(image_desc->ep_info.h.attr) == NON_SECURE)) {
WARN("BL1-FWU: Copy not allowed for Non-Secure "
"image from Secure-world\n");
return -EPERM;
@@ -156,10 +156,10 @@
* If last block is more than expected then
* clip the block to the required image size.
*/
- if (image_desc->image_info.copied_size + block_size >
+ if (image_desc->copied_size + block_size >
image_desc->image_info.image_size) {
block_size = image_desc->image_info.image_size -
- image_desc->image_info.copied_size;
+ image_desc->copied_size;
WARN("BL1-FWU: Copy argument block_size > remaining image size."
" Clipping block_size\n");
}
@@ -173,13 +173,13 @@
INFO("BL1-FWU: Continuing image copy in blocks\n");
/* Copy image for given block size. */
- base_addr += image_desc->image_info.copied_size;
- image_desc->image_info.copied_size += block_size;
+ base_addr += image_desc->copied_size;
+ image_desc->copied_size += block_size;
memcpy((void *)base_addr, (const void *)image_src, block_size);
flush_dcache_range(base_addr, block_size);
/* Update the state if last block. */
- if (image_desc->image_info.copied_size ==
+ if (image_desc->copied_size ==
image_desc->image_info.image_size) {
image_desc->state = IMAGE_STATE_COPIED;
INFO("BL1-FWU: Image copy in blocks completed\n");
@@ -234,7 +234,7 @@
INFO("BL1-FWU: Started image copy in blocks\n");
}
- image_desc->image_info.copied_size = block_size;
+ image_desc->copied_size = block_size;
}
return 0;
@@ -257,14 +257,14 @@
if (!image_desc)
return -EPERM;
- if (GET_SEC_STATE(flags) == SECURE) {
+ if (GET_SECURITY_STATE(flags) == SECURE) {
if (image_desc->state != IMAGE_STATE_RESET) {
WARN("BL1-FWU: Authentication from secure world "
"while in invalid state\n");
return -EPERM;
}
} else {
- if (GET_SEC_STATE(image_desc->ep_info.h.attr) == SECURE) {
+ if (GET_SECURITY_STATE(image_desc->ep_info.h.attr) == SECURE) {
if (image_desc->state != IMAGE_STATE_COPIED) {
WARN("BL1-FWU: Authentication of secure image "
"from non-secure world while not in copied state\n");
@@ -369,10 +369,10 @@
* Image is NOT in AUTHENTICATED state.
*/
if ((!image_desc) ||
- (GET_SEC_STATE(flags) == SECURE) ||
- (GET_SEC_STATE(image_desc->ep_info.h.attr) == NON_SECURE) ||
- (GET_EXEC_STATE(image_desc->image_info.h.attr) == NON_EXECUTABLE) ||
- (image_desc->state != IMAGE_STATE_AUTHENTICATED)) {
+ (GET_SECURITY_STATE(flags) == SECURE) ||
+ (GET_SECURITY_STATE(image_desc->ep_info.h.attr) == NON_SECURE) ||
+ (EP_GET_EXE(image_desc->ep_info.h.attr) == NON_EXECUTABLE) ||
+ (image_desc->state != IMAGE_STATE_AUTHENTICATED)) {
WARN("BL1-FWU: Execution not allowed due to invalid state/args\n");
return -EPERM;
}
@@ -402,7 +402,7 @@
{
image_desc_t *image_desc;
unsigned int resume_sec_state;
- unsigned int caller_sec_state = GET_SEC_STATE(flags);
+ unsigned int caller_sec_state = GET_SECURITY_STATE(flags);
/* Get the image descriptor for last executed secure image id. */
image_desc = bl1_plat_get_image_desc(sec_exec_image_id);
@@ -417,8 +417,8 @@
assert(image_desc);
}
- assert(GET_SEC_STATE(image_desc->ep_info.h.attr) == SECURE);
- assert(GET_EXEC_STATE(image_desc->image_info.h.attr) == EXECUTABLE);
+ assert(GET_SECURITY_STATE(image_desc->ep_info.h.attr) == SECURE);
+ assert(EP_GET_EXE(image_desc->ep_info.h.attr) == EXECUTABLE);
if (caller_sec_state == SECURE) {
assert(image_desc->state == IMAGE_STATE_EXECUTED);
@@ -458,7 +458,7 @@
image_desc_t *image_desc;
/* Make sure caller is from the secure world */
- if (GET_SEC_STATE(flags) == NON_SECURE) {
+ if (GET_SECURITY_STATE(flags) == NON_SECURE) {
WARN("BL1-FWU: Image done not allowed from normal world\n");
return -EPERM;
}
@@ -468,8 +468,8 @@
/* image_desc must correspond to a valid secure executing image */
assert(image_desc);
- assert(GET_SEC_STATE(image_desc->ep_info.h.attr) == SECURE);
- assert(GET_EXEC_STATE(image_desc->image_info.h.attr) == EXECUTABLE);
+ assert(GET_SECURITY_STATE(image_desc->ep_info.h.attr) == SECURE);
+ assert(EP_GET_EXE(image_desc->ep_info.h.attr) == EXECUTABLE);
assert(image_desc->state == IMAGE_STATE_EXECUTED);
/* Update the flags. */
diff --git a/bl1/tbbr/tbbr_img_desc.c b/bl1/tbbr/tbbr_img_desc.c
index 42de851..7651f1c 100644
--- a/bl1/tbbr/tbbr_img_desc.c
+++ b/bl1/tbbr/tbbr_img_desc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -35,42 +35,46 @@
image_desc_t bl1_tbbr_image_descs[] = {
{
.image_id = FWU_CERT_ID,
- .image_info.h.attr = SET_EXEC_STATE(NON_EXECUTABLE),
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_1, image_info_t, 0),
.image_info.image_base = BL2_BASE,
- .ep_info.h.attr = SET_SEC_STATE(SECURE),
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+ VERSION_1, entry_point_info_t, SECURE),
},
#if NS_BL1U_BASE
{
.image_id = NS_BL1U_IMAGE_ID,
- .image_info.h.attr = SET_EXEC_STATE(EXECUTABLE),
- .image_info.image_base = NS_BL1U_BASE,
- .ep_info.h.attr = SET_SEC_STATE(NON_SECURE),
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_1, entry_point_info_t, NON_SECURE | EXECUTABLE),
.ep_info.pc = NS_BL1U_BASE,
},
#endif
#if SCP_BL2U_BASE
{
.image_id = SCP_BL2U_IMAGE_ID,
- .image_info.h.attr = SET_EXEC_STATE(NON_EXECUTABLE),
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_1, image_info_t, 0),
.image_info.image_base = SCP_BL2U_BASE,
- .ep_info.h.attr = SET_SEC_STATE(SECURE),
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+ VERSION_1, entry_point_info_t, SECURE),
},
#endif
#if BL2U_BASE
{
.image_id = BL2U_IMAGE_ID,
- .image_info.h.attr = SET_EXEC_STATE(EXECUTABLE),
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_1, image_info_t, 0),
.image_info.image_base = BL2U_BASE,
- .ep_info.h.attr = SET_SEC_STATE(SECURE),
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_1, entry_point_info_t, SECURE | EXECUTABLE),
.ep_info.pc = BL2U_BASE,
},
#endif
#if NS_BL2U_BASE
{
.image_id = NS_BL2U_IMAGE_ID,
- .image_info.h.attr = SET_EXEC_STATE(NON_EXECUTABLE),
- .image_info.image_base = NS_BL2U_BASE,
- .ep_info.h.attr = SET_SEC_STATE(NON_SECURE),
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_1, entry_point_info_t, NON_SECURE),
},
#endif
BL2_IMAGE_DESC,
diff --git a/bl2/aarch64/bl2_entrypoint.S b/bl2/aarch64/bl2_entrypoint.S
index 75eb02a..476efe8 100644
--- a/bl2/aarch64/bl2_entrypoint.S
+++ b/bl2/aarch64/bl2_entrypoint.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -43,8 +43,8 @@
* available to BL2 for future use.
* x0 is not currently used.
* ---------------------------------------------
- */
- mov x20, x1
+ */
+ mov x20, x1
/* ---------------------------------------------
* Set the exception vector to something sane.
@@ -126,6 +126,11 @@
* ---------------------------------------------
*/
bl bl2_main
-_panic:
- b _panic
+
+ /* ---------------------------------------------
+ * Should never reach this point.
+ * ---------------------------------------------
+ */
+ bl plat_panic_handler
+
endfunc bl2_entrypoint
diff --git a/bl2/bl2_main.c b/bl2/bl2_main.c
index 9ff75d2..73781dd 100644
--- a/bl2/bl2_main.c
+++ b/bl2/bl2_main.c
@@ -169,6 +169,7 @@
return e;
}
+#ifndef BL33_BASE
/*******************************************************************************
* Load the BL33 image.
* The bl2_to_bl31_params param will be updated with the relevant BL33
@@ -199,6 +200,8 @@
return e;
}
+#endif /* BL33_BASE */
+
#endif /* EL3_PAYLOAD_BASE */
/*******************************************************************************
@@ -253,7 +256,7 @@
* bl31_params_t structure makes sense in the context of EL3 payloads.
* This will be refined in the future.
*/
- VERBOSE("BL2: Populating the entrypoint info for the EL3 payload\n");
+ INFO("BL2: Populating the entrypoint info for the EL3 payload\n");
bl31_ep_info->pc = EL3_PAYLOAD_BASE;
bl31_ep_info->args.arg0 = (unsigned long) bl2_to_bl31_params;
bl2_plat_set_bl31_ep_info(NULL, bl31_ep_info);
@@ -274,11 +277,22 @@
}
}
+#ifdef BL33_BASE
+ /*
+ * In this case, don't load the BL33 image as it's already loaded in
+ * memory. Update BL33 entrypoint information.
+ */
+ INFO("BL2: Populating the entrypoint info for the preloaded BL33\n");
+ bl2_to_bl31_params->bl33_ep_info->pc = BL33_BASE;
+ bl2_plat_set_bl33_ep_info(NULL, bl2_to_bl31_params->bl33_ep_info);
+#else
e = load_bl33(bl2_to_bl31_params);
if (e) {
ERROR("Failed to load BL33 (%i)\n", e);
plat_error_handler(e);
}
+#endif /* BL33_BASE */
+
#endif /* EL3_PAYLOAD_BASE */
/* Flush the params to be passed to memory */
diff --git a/bl2u/aarch64/bl2u_entrypoint.S b/bl2u/aarch64/bl2u_entrypoint.S
index c9aad81..ef3db92 100644
--- a/bl2u/aarch64/bl2u_entrypoint.S
+++ b/bl2u/aarch64/bl2u_entrypoint.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -122,6 +122,10 @@
*/
bl bl2u_main
-_panic:
- b _panic
+ /* ---------------------------------------------
+ * Should never reach this point.
+ * ---------------------------------------------
+ */
+ bl plat_panic_handler
+
endfunc bl2u_entrypoint
diff --git a/bl31/aarch64/bl31_arch_setup.c b/bl31/aarch64/bl31_arch_setup.c
index edf1018..0871b41 100644
--- a/bl31/aarch64/bl31_arch_setup.c
+++ b/bl31/aarch64/bl31_arch_setup.c
@@ -43,9 +43,6 @@
******************************************************************************/
void bl31_arch_setup(void)
{
- /* Set the RES1 bits in the SCR_EL3 */
- write_scr_el3(SCR_RES1_BITS);
-
/* Program the counter frequency */
write_cntfrq_el0(plat_get_syscnt_freq());
diff --git a/bl31/aarch64/crash_reporting.S b/bl31/aarch64/crash_reporting.S
index 1d1e60d..b22ce71 100644
--- a/bl31/aarch64/crash_reporting.S
+++ b/bl31/aarch64/crash_reporting.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -70,7 +70,8 @@
"tpidrro_el0", "dacr32_el2", "ifsr32_el2", "par_el1",\
"mpidr_el1", "afsr0_el1", "afsr1_el1", "contextidr_el1",\
"vbar_el1", "cntp_ctl_el0", "cntp_cval_el0", "cntv_ctl_el0",\
- "cntv_cval_el0", "cntkctl_el1", "fpexc32_el2", "sp_el0", ""
+ "cntv_cval_el0", "cntkctl_el1", "fpexc32_el2", "sp_el0",\
+ "isr_el1", ""
panic_msg:
.asciz "PANIC in EL3 at x30 = 0x"
@@ -338,6 +339,7 @@
mrs x8, cntkctl_el1
mrs x9, fpexc32_el2
mrs x10, sp_el0
+ mrs x11, isr_el1
bl str_in_crash_buf_print
/* Get the cpu specific registers to report */
@@ -351,17 +353,17 @@
plat_print_interconnect_regs
/* Done reporting */
- b crash_panic
+ bl plat_panic_handler
endfunc do_crash_reporting
#else /* CRASH_REPORTING */
func report_unhandled_exception
report_unhandled_interrupt:
- b crash_panic
+ bl plat_panic_handler
endfunc report_unhandled_exception
#endif /* CRASH_REPORTING */
func crash_panic
- b crash_panic
-endfunc crash_panic
\ No newline at end of file
+ bl plat_panic_handler
+endfunc crash_panic
diff --git a/bl31/runtime_svc.c b/bl31/runtime_svc.c
index 5b7a21c..f011f11 100644
--- a/bl31/runtime_svc.c
+++ b/bl31/runtime_svc.c
@@ -103,8 +103,8 @@
*/
rc = validate_rt_svc_desc(&rt_svc_descs[index]);
if (rc) {
- ERROR("Invalid runtime service descriptor 0x%lx (%s)\n",
- (uintptr_t) &rt_svc_descs[index],
+ ERROR("Invalid runtime service descriptor %p (%s)\n",
+ (void *) &rt_svc_descs[index],
rt_svc_descs[index].name);
goto error;
}
diff --git a/bl32/tsp/aarch64/tsp_entrypoint.S b/bl32/tsp/aarch64/tsp_entrypoint.S
index 531ab9b..453d2c1 100644
--- a/bl32/tsp/aarch64/tsp_entrypoint.S
+++ b/bl32/tsp/aarch64/tsp_entrypoint.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -391,7 +391,7 @@
/* Should never reach here */
tsp_sel1_int_entry_panic:
- b tsp_sel1_int_entry_panic
+ bl plat_panic_handler
endfunc tsp_sel1_intr_entry
/*---------------------------------------------
@@ -407,8 +407,9 @@
func tsp_cpu_resume_entry
bl tsp_cpu_resume_main
restore_args_call_smc
-tsp_cpu_resume_panic:
- b tsp_cpu_resume_panic
+
+ /* Should never reach here */
+ bl plat_panic_handler
endfunc tsp_cpu_resume_entry
/*---------------------------------------------
@@ -419,8 +420,9 @@
func tsp_fast_smc_entry
bl tsp_smc_handler
restore_args_call_smc
-tsp_fast_smc_entry_panic:
- b tsp_fast_smc_entry_panic
+
+ /* Should never reach here */
+ bl plat_panic_handler
endfunc tsp_fast_smc_entry
/*---------------------------------------------
@@ -435,6 +437,7 @@
bl tsp_smc_handler
msr daifset, #DAIF_FIQ_BIT | DAIF_IRQ_BIT
restore_args_call_smc
-tsp_std_smc_entry_panic:
- b tsp_std_smc_entry_panic
+
+ /* Should never reach here */
+ bl plat_panic_handler
endfunc tsp_std_smc_entry
diff --git a/bl32/tsp/aarch64/tsp_exceptions.S b/bl32/tsp/aarch64/tsp_exceptions.S
index d5e089f..edcfb71 100644
--- a/bl32/tsp/aarch64/tsp_exceptions.S
+++ b/bl32/tsp/aarch64/tsp_exceptions.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -108,24 +108,23 @@
* -----------------------------------------------------
*/
sync_exception_sp_el0:
- wfi
- b sync_exception_sp_el0
+ bl plat_panic_handler
check_vector_size sync_exception_sp_el0
.align 7
irq_sp_el0:
- b irq_sp_el0
+ bl plat_panic_handler
check_vector_size irq_sp_el0
.align 7
fiq_sp_el0:
- b fiq_sp_el0
+ bl plat_panic_handler
check_vector_size fiq_sp_el0
.align 7
serror_sp_el0:
- b serror_sp_el0
+ bl plat_panic_handler
check_vector_size serror_sp_el0
@@ -136,8 +135,7 @@
*/
.align 7
sync_exception_sp_elx:
- wfi
- b sync_exception_sp_elx
+ bl plat_panic_handler
check_vector_size sync_exception_sp_elx
.align 7
@@ -152,7 +150,7 @@
.align 7
serror_sp_elx:
- b serror_sp_elx
+ bl plat_panic_handler
check_vector_size serror_sp_elx
@@ -163,23 +161,22 @@
*/
.align 7
sync_exception_aarch64:
- wfi
- b sync_exception_aarch64
+ bl plat_panic_handler
check_vector_size sync_exception_aarch64
.align 7
irq_aarch64:
- b irq_aarch64
+ bl plat_panic_handler
check_vector_size irq_aarch64
.align 7
fiq_aarch64:
- b fiq_aarch64
+ bl plat_panic_handler
check_vector_size fiq_aarch64
.align 7
serror_aarch64:
- b serror_aarch64
+ bl plat_panic_handler
check_vector_size serror_aarch64
@@ -190,22 +187,21 @@
*/
.align 7
sync_exception_aarch32:
- wfi
- b sync_exception_aarch32
+ bl plat_panic_handler
check_vector_size sync_exception_aarch32
.align 7
irq_aarch32:
- b irq_aarch32
+ bl plat_panic_handler
check_vector_size irq_aarch32
.align 7
fiq_aarch32:
- b fiq_aarch32
+ bl plat_panic_handler
check_vector_size fiq_aarch32
.align 7
serror_aarch32:
- b serror_aarch32
+ bl plat_panic_handler
check_vector_size serror_aarch32
.align 7
diff --git a/bl32/tsp/tsp.mk b/bl32/tsp/tsp.mk
index 9919fe4..a502428 100644
--- a/bl32/tsp/tsp.mk
+++ b/bl32/tsp/tsp.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
@@ -52,8 +52,8 @@
# Include the platform-specific TSP Makefile
# If no platform-specific TSP Makefile exists, it means TSP is not supported
# on this platform.
-TSP_PLAT_MAKEFILE := $(shell find plat/ -wholename '*/${PLAT}/tsp/tsp-${PLAT}.mk')
-ifeq (,$(wildcard ${TSP_PLAT_MAKEFILE}))
+TSP_PLAT_MAKEFILE := $(wildcard ${PLAT_DIR}/tsp/tsp-${PLAT}.mk)
+ifeq (,${TSP_PLAT_MAKEFILE})
$(error TSP is not supported on platform ${PLAT})
else
include ${TSP_PLAT_MAKEFILE}
diff --git a/common/aarch64/debug.S b/common/aarch64/debug.S
index b3caafb..d353879 100644
--- a/common/aarch64/debug.S
+++ b/common/aarch64/debug.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -120,7 +120,7 @@
/*
* This function prints a hexadecimal number in x4.
* In: x4 = the hexadecimal to print.
- * Clobber: x30, x0, x5, x1, x2, x3
+ * Clobber: x30, x0 - x3, x5
*/
func asm_print_hex
mov x3, x30
@@ -178,7 +178,7 @@
mov x6, x30
bl plat_crash_console_init
/* Check if the console is initialized */
- cbz x0, _panic_loop
+ cbz x0, _panic_handler
/* The console is initialized */
adr x4, panic_msg
bl asm_print_str
@@ -186,7 +186,10 @@
/* The panic location is lr -4 */
sub x4, x4, #4
bl asm_print_hex
-_panic_loop:
- b _panic_loop
-endfunc do_panic
+_panic_handler:
+ /* Pass to plat_panic_handler the address from where el3_panic was
+ * called, not the address of the call from el3_panic. */
+ mov x30,x6
+ b plat_panic_handler
+endfunc do_panic
diff --git a/common/bl_common.c b/common/bl_common.c
index 0eeef83..d5b095a 100644
--- a/common/bl_common.c
+++ b/common/bl_common.c
@@ -229,7 +229,8 @@
return io_result;
}
- INFO("Loading image id=%u at address 0x%lx\n", image_id, image_base);
+ INFO("Loading image id=%u at address %p\n", image_id,
+ (void *) image_base);
/* Find the size of the image */
io_result = io_size(image_handle, &image_size);
@@ -242,8 +243,8 @@
/* Check that the memory where the image will be loaded is free */
if (!is_mem_free(mem_layout->free_base, mem_layout->free_size,
image_base, image_size)) {
- WARN("Failed to reserve memory: 0x%lx - 0x%lx\n",
- image_base, image_base + image_size);
+ WARN("Failed to reserve memory: %p - %p\n", (void *) image_base,
+ (void *) (image_base + image_size));
dump_load_info(image_base, image_size, mem_layout);
io_result = -ENOMEM;
goto exit;
@@ -268,8 +269,8 @@
reserve_mem(&mem_layout->free_base, &mem_layout->free_size,
image_base, image_size);
} else {
- INFO("Skip reserving memory: 0x%lx - 0x%lx\n",
- image_base, image_base + image_size);
+ INFO("Skip reserving memory: %p - %p\n", (void *) image_base,
+ (void *) (image_base + image_size));
}
image_data->image_base = image_base;
@@ -284,8 +285,8 @@
*/
flush_dcache_range(image_base, image_size);
- INFO("Image id=%u loaded: 0x%lx - 0x%lx\n", image_id, image_base,
- image_base + image_size);
+ INFO("Image id=%u loaded: %p - %p\n", image_id, (void *) image_base,
+ (void *) (image_base + image_size));
exit:
io_close(image_handle);
diff --git a/common/context_mgmt.c b/common/context_mgmt.c
index 68ec894..586d42a 100644
--- a/common/context_mgmt.c
+++ b/common/context_mgmt.c
@@ -111,6 +111,11 @@
if (EP_GET_ST(ep->h.attr))
scr_el3 |= SCR_ST_BIT;
+#ifndef HANDLE_EA_EL3_FIRST
+ /* Explicitly stop to trap aborts from lower exception levels. */
+ scr_el3 &= ~SCR_EA_BIT;
+#endif
+
#if IMAGE_BL31
/*
* IRQ/FIQ bits only need setting if interrupt routing
diff --git a/common/tf_printf.c b/common/tf_printf.c
index c68b990..9a7667a 100644
--- a/common/tf_printf.c
+++ b/common/tf_printf.c
@@ -68,6 +68,8 @@
* %u - unsigned 32 bit decimal format
* %ld and %lld - signed 64 bit decimal format
* %lu and %llu - unsigned 64 bit decimal format
+ * %p - pointer format
+ * %z - size_t format
* Exits on all other formats.
*******************************************************************/
@@ -107,6 +109,14 @@
str = va_arg(args, char *);
string_print(str);
break;
+ case 'p':
+ unum = (uint64_t)va_arg(args, void *);
+
+ if (unum)
+ string_print("0x");
+
+ unsigned_num_print(unum, 16);
+ break;
case 'x':
if (bit64)
unum = va_arg(args, uint64_t);
@@ -115,6 +125,11 @@
unsigned_num_print(unum, 16);
break;
+ case 'z':
+ if (sizeof(size_t) == 8)
+ bit64 = 1;
+ fmt++;
+ goto loop;
case 'l':
bit64 = 1;
fmt++;
diff --git a/docs/cpu-specific-build-macros.md b/docs/cpu-specific-build-macros.md
index e7185aa..c57dc7e 100644
--- a/docs/cpu-specific-build-macros.md
+++ b/docs/cpu-specific-build-macros.md
@@ -85,8 +85,12 @@
* `A57_DISABLE_NON_TEMPORAL_HINT`: This flag has the same behaviour as
`A53_DISABLE_NON_TEMPORAL_HINT` but for Cortex-A57. This needs to be
- enabled only for revisions <= r1p2 of the CPU and is enabled by default.
+ enabled only for revisions <= r1p2 of the CPU and is enabled by default,
+ as recommended in section "4.7 Non-Temporal Loads/Stores" of the
+ [Cortex-A57 Software Optimization Guide][A57 SW Optimization Guide].
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved._
+
+[A57 SW Optimization Guide]: http://infocenter.arm.com/help/topic/com.arm.doc.uan0015b/Cortex_A57_Software_Optimization_Guide_external.pdf
diff --git a/docs/diagrams/default_reset_code.png b/docs/diagrams/default_reset_code.png
index e7e0d85..d8675e4 100644
--- a/docs/diagrams/default_reset_code.png
+++ b/docs/diagrams/default_reset_code.png
Binary files differ
diff --git a/docs/diagrams/reset_code_flow.dia b/docs/diagrams/reset_code_flow.dia
index 5de00da..133c9cf 100644
--- a/docs/diagrams/reset_code_flow.dia
+++ b/docs/diagrams/reset_code_flow.dia
Binary files differ
diff --git a/docs/diagrams/reset_code_no_boot_type_check.png b/docs/diagrams/reset_code_no_boot_type_check.png
index 8ce7e97..23e865f 100644
--- a/docs/diagrams/reset_code_no_boot_type_check.png
+++ b/docs/diagrams/reset_code_no_boot_type_check.png
Binary files differ
diff --git a/docs/diagrams/reset_code_no_checks.png b/docs/diagrams/reset_code_no_checks.png
index 8a02f0f..26a179b 100644
--- a/docs/diagrams/reset_code_no_checks.png
+++ b/docs/diagrams/reset_code_no_checks.png
Binary files differ
diff --git a/docs/diagrams/reset_code_no_cpu_check.png b/docs/diagrams/reset_code_no_cpu_check.png
index 8b05ea4..4150dbe 100644
--- a/docs/diagrams/reset_code_no_cpu_check.png
+++ b/docs/diagrams/reset_code_no_cpu_check.png
Binary files differ
diff --git a/docs/firmware-design.md b/docs/firmware-design.md
index d0cb399..fe3c3f0 100644
--- a/docs/firmware-design.md
+++ b/docs/firmware-design.md
@@ -152,11 +152,15 @@
CLCD window of the FVP.
BL1 does not expect to receive any exceptions other than the SMC exception.
- For the latter, BL1 installs a simple stub. The stub expects to receive
- only a single type of SMC (determined by its function ID in the general
- purpose register `X0`). This SMC is raised by BL2 to make BL1 pass control
- to BL31 (loaded by BL2) at EL3. Any other SMC leads to an assertion
- failure.
+ For the latter, BL1 installs a simple stub. The stub expects to receive a
+ limited set of SMC types (determined by their function IDs in the general
+ purpose register `X0`):
+ - `BL1_SMC_RUN_IMAGE`: This SMC is raised by BL2 to make BL1 pass control
+ to BL31 (loaded by BL2) at EL3.
+ - All SMCs listed in section "BL1 SMC Interface" in the [Firmware Update]
+ Design Guide.
+
+ Any other SMC leads to an assertion failure.
* CPU initialization
@@ -164,20 +168,15 @@
specific reset handler function (see the section: "CPU specific operations
framework").
-* MMU setup
-
- BL1 sets up EL3 memory translation by creating page tables to cover the
- first 4GB of physical address space. This covers all the memories and
- peripherals needed by BL1.
-
* Control register setup
- `SCTLR_EL3`. Instruction cache is enabled by setting the `SCTLR_EL3.I`
bit. Alignment and stack alignment checking is enabled by setting the
`SCTLR_EL3.A` and `SCTLR_EL3.SA` bits. Exception endianness is set to
little-endian by clearing the `SCTLR_EL3.EE` bit.
- - `SCR_EL3`. The register width of the next lower exception level is set to
- AArch64 by setting the `SCR.RW` bit.
+ - `SCR_EL3`. The register width of the next lower exception level is set
+ to AArch64 by setting the `SCR.RW` bit. The `SCR.EA` bit is set to trap
+ both External Aborts and SError Interrupts in EL3.
- `CPTR_EL3`. Accesses to the `CPACR_EL1` register from EL1 or EL2, or the
`CPTR_EL2` register from EL2 are configured to not trap to EL3 by
@@ -187,12 +186,19 @@
and Advanced SIMD execution are configured to not trap to EL3 by
clearing the `CPTR_EL3.TFP` bit.
+ - `DAIF`. The SError interrupt is enabled by clearing the SError interrupt
+ mask bit.
+
#### Platform initialization
-BL1 enables issuing of snoop and DVM (Distributed Virtual Memory) requests to
-the CCI slave interface corresponding to the cluster that includes the
-primary CPU. BL1 also initializes a UART (PL011 console), which enables access
-to the `printf` family of functions in BL1.
+On ARM platforms, BL1 performs the following platform initializations:
+
+* Enable the Trusted Watchdog.
+* Initialize the console.
+* Configure the Interconnect to enable hardware coherency.
+* Enable the MMU and map the memory it needs to access.
+* Configure any required platform storage to load the next bootloader image
+ (BL2).
#### Firmware Update detection and execution
@@ -210,7 +216,12 @@
In the normal boot flow, BL1 execution continues as follows:
-1. BL1 determines the amount of free trusted SRAM memory available by
+1. BL1 prints the following string from the primary CPU to indicate successful
+ execution of the BL1 stage:
+
+ "Booting Trusted Firmware"
+
+2. BL1 determines the amount of free trusted SRAM memory available by
calculating the extent of its own data section, which also resides in
trusted SRAM. BL1 loads a BL2 raw binary image from platform storage, at a
platform-specific base address. If the BL2 image file is not present or if
@@ -225,11 +236,6 @@
provided as a base address in the platform header. Further description of
the memory layout can be found later in this document.
-2. BL1 prints the following string from the primary CPU to indicate successful
- execution of the BL1 stage:
-
- "Booting Trusted Firmware"
-
3. BL1 passes control to the BL2 image at Secure EL1, starting from its load
address.
@@ -247,23 +253,23 @@
#### Architectural initialization
BL2 performs minimal architectural initialization required for subsequent
-stages of the ARM Trusted Firmware and normal world software. It sets up
-Secure EL1 memory translation by creating page tables to address the first 4GB
-of the physical address space in a similar way to BL1. EL1 and EL0 are given
-access to Floating Point & Advanced SIMD registers by clearing the `CPACR.FPEN`
-bits.
+stages of the ARM Trusted Firmware and normal world software. EL1 and EL0 are
+given access to Floating Point & Advanced SIMD registers by clearing the
+`CPACR.FPEN` bits.
#### Platform initialization
+On ARM platforms, BL2 performs the following platform initializations:
+
-BL2 copies the information regarding the trusted SRAM populated by BL1 using a
-platform-specific mechanism. It calculates the limits of DRAM (main memory)
-to determine whether there is enough space to load the BL33 image. A platform
-defined base address is used to specify the load address for the BL31 image.
-It also defines the extents of memory available for use by the BL32 image.
-BL2 also initializes a UART (PL011 console), which enables access to the
-`printf` family of functions in BL2. Platform security is initialized to allow
-access to controlled components. The storage abstraction layer is initialized
-which is used to load further bootloader images.
+* Initialize the console.
+* Configure any required platform storage to allow loading further bootloader
+ images.
+* Enable the MMU and map the memory it needs to access.
+* Perform platform security setup to allow access to controlled components.
+* Reserve some memory for passing information to the next bootloader image
+ (BL31) and populate it.
+* Define the extents of memory available for loading each subsequent
+ bootloader image.
#### SCP_BL2 (System Control Processor Firmware) image load
@@ -334,89 +340,75 @@
Currently, BL31 performs a similar architectural initialization to BL1 as
far as system register settings are concerned. Since BL1 code resides in ROM,
architectural initialization in BL31 allows override of any previous
-initialization done by BL1. BL31 creates page tables to address the first
-4GB of physical address space and initializes the MMU accordingly. It initializes
-a buffer of frequently used pointers, called per-CPU pointer cache, in memory for
-faster access. Currently the per-CPU pointer cache contains only the pointer
-to crash stack. It then replaces the exception vectors populated by BL1 with its
-own. BL31 exception vectors implement more elaborate support for
-handling SMCs since this is the only mechanism to access the runtime services
-implemented by BL31 (PSCI for example). BL31 checks each SMC for validity as
-specified by the [SMC calling convention PDD][SMCCC] before passing control to
-the required SMC handler routine. BL31 programs the `CNTFRQ_EL0` register with
-the clock frequency of the system counter, which is provided by the platform.
+initialization done by BL1.
-#### Platform initialization
+BL31 initializes the per-CPU data framework, which provides a cache of
+frequently accessed per-CPU data optimised for fast, concurrent manipulation
+on different CPUs. This buffer includes pointers to per-CPU contexts, crash
+buffer, CPU reset and power down operations, PSCI data, platform data and so on.
-BL31 performs detailed platform initialization, which enables normal world
-software to function correctly. It also retrieves entrypoint information for
-the BL33 image loaded by BL2 from the platform defined memory address populated
-by BL2. It enables issuing of snoop and DVM (Distributed Virtual Memory)
-requests to the CCI slave interface corresponding to the cluster that includes
-the primary CPU. BL31 also initializes a UART (PL011 console), which enables
-access to the `printf` family of functions in BL31. It enables the system
-level implementation of the generic timer through the memory mapped interface.
+It then replaces the exception vectors populated by BL1 with its own. BL31
+exception vectors implement more elaborate support for handling SMCs since this
+is the only mechanism to access the runtime services implemented by BL31 (PSCI
+for example). BL31 checks each SMC for validity as specified by the
+[SMC calling convention PDD][SMCCC] before passing control to the required SMC
+handler routine.
-* GICv2 initialization:
+BL31 programs the `CNTFRQ_EL0` register with the clock frequency of the system
+counter, which is provided by the platform.
- - Enable group0 interrupts in the GIC CPU interface.
- - Configure group0 interrupts to be asserted as FIQs.
- - Disable the legacy interrupt bypass mechanism.
- - Configure the priority mask register to allow interrupts of all
- priorities to be signaled to the CPU interface.
- - Mark SGIs 8-15 and the other secure interrupts on the platform
- as group0 (secure).
- - Target all secure SPIs to CPU0.
- - Enable these group0 interrupts in the GIC distributor.
- - Configure all other interrupts as group1 (non-secure).
- - Enable signaling of group0 interrupts in the GIC distributor.
+#### Platform initialization
-* GICv3 initialization:
+BL31 performs detailed platform initialization, which enables normal world
+software to function correctly.
- If a GICv3 implementation is available in the platform, BL31 initializes
- the GICv3 in GICv2 emulation mode with settings as described for GICv2
- above.
+On ARM platforms, this consists of the following:
-* Power management initialization:
+* Initialize the console.
+* Configure the Interconnect to enable hardware coherency.
+* Enable the MMU and map the memory it needs to access.
+* Initialize the generic interrupt controller.
+* Initialize the power controller device.
+* Detect the system topology.
- BL31 implements a state machine to track CPU and cluster state. The state
- can be one of `OFF`, `ON_PENDING`, `SUSPEND` or `ON`. All secondary CPUs are
- initially in the `OFF` state. The cluster that the primary CPU belongs to is
- `ON`; any other cluster is `OFF`. BL31 initializes the data structures that
- implement the state machine, including the locks that protect them. BL31
- accesses the state of a CPU or cluster immediately after reset and before
- the data cache is enabled in the warm boot path. It is not currently
- possible to use 'exclusive' based spinlocks, therefore BL31 uses locks
- based on Lamport's Bakery algorithm instead. BL31 allocates these locks in
- device memory by default.
+#### Runtime services initialization
-* Runtime services initialization:
+BL31 is responsible for initializing the runtime services. One of them is PSCI.
- The runtime service framework and its initialization is described in the
- "EL3 runtime services framework" section below.
+As part of the PSCI initializations, BL31 detects the system topology. It also
+initializes the data structures that implement the state machine used to track
+the state of power domain nodes. The state can be one of `OFF`, `RUN` or
+`RETENTION`. All secondary CPUs are initially in the `OFF` state. The cluster
+that the primary CPU belongs to is `ON`; any other cluster is `OFF`. It also
+initializes the locks that protect them. BL31 accesses the state of a CPU or
+cluster immediately after reset and before the data cache is enabled in the
+warm boot path. It is not currently possible to use 'exclusive' based spinlocks,
+therefore BL31 uses locks based on Lamport's Bakery algorithm instead.
- Details about the PSCI service are provided in the "Power State Coordination
- Interface" section below.
+The runtime service framework and its initialization is described in more
+detail in the "EL3 runtime services framework" section below.
-* BL32 (Secure-EL1 Payload) image initialization
+Details about the status of the PSCI implementation are provided in the
+"Power State Coordination Interface" section below.
- If a BL32 image is present then there must be a matching Secure-EL1 Payload
- Dispatcher (SPD) service (see later for details). During initialization
- that service must register a function to carry out initialization of BL32
- once the runtime services are fully initialized. BL31 invokes such a
- registered function to initialize BL32 before running BL33.
+#### BL32 (Secure-EL1 Payload) image initialization
- Details on BL32 initialization and the SPD's role are described in the
- "Secure-EL1 Payloads and Dispatchers" section below.
+If a BL32 image is present then there must be a matching Secure-EL1 Payload
+Dispatcher (SPD) service (see later for details). During initialization
+that service must register a function to carry out initialization of BL32
+once the runtime services are fully initialized. BL31 invokes such a
+registered function to initialize BL32 before running BL33.
-* BL33 (Non-trusted Firmware) execution
+Details on BL32 initialization and the SPD's role are described in the
+"Secure-EL1 Payloads and Dispatchers" section below.
- BL31 initializes the EL2 or EL1 processor context for normal-world cold
- boot, ensuring that no secure state information finds its way into the
- non-secure execution state. BL31 uses the entrypoint information provided
- by BL2 to jump to the Non-trusted firmware image (BL33) at the highest
- available Exception Level (EL2 if available, otherwise EL1).
+#### BL33 (Non-trusted Firmware) execution
+BL31 initializes the EL2 or EL1 processor context for normal-world cold
+boot, ensuring that no secure state information finds its way into the
+non-secure execution state. BL31 uses the entrypoint information provided
+by BL2 to jump to the Non-trusted firmware image (BL33) at the highest
+available Exception Level (EL2 if available, otherwise EL1).
### Using alternative Trusted Boot Firmware in place of BL1 and BL2
@@ -558,9 +550,6 @@
Coordination Interface ([PSCI]) is the first set of standard service calls
defined by ARM (see PSCI section later).
- NOTE: Currently this service is called PSCI since there are no other
- defined standard service calls.
-
2. Secure-EL1 Payload Dispatcher service
If a system runs a Trusted OS or other Secure-EL1 Payload (SP) then
@@ -1194,6 +1183,72 @@
on FVP, BL31 and TSP need to know the limit address that their PROGBITS
sections must not overstep. The platform code must provide those.
+Trusted Firmware provides a mechanism to verify at boot time that the memory
+to load a new image is free to prevent overwriting a previously loaded image.
+For this mechanism to work, the platform must specify the memory available in
+the system as regions, where each region consists of base address, total size
+and the free area within it (as defined in the `meminfo_t` structure). Trusted
+Firmware retrieves these memory regions by calling the corresponding platform
+API:
+
+* `meminfo_t *bl1_plat_sec_mem_layout(void)`
+* `meminfo_t *bl2_plat_sec_mem_layout(void)`
+* `void bl2_plat_get_scp_bl2_meminfo(meminfo_t *scp_bl2_meminfo)`
+* `void bl2_plat_get_bl32_meminfo(meminfo_t *bl32_meminfo)`
+* `void bl2_plat_get_bl33_meminfo(meminfo_t *bl33_meminfo)`
+
+For example, in the case of BL1 loading BL2, `bl1_plat_sec_mem_layout()` will
+return the region defined by the platform where BL1 intends to load BL2. The
+`load_image()` function will check that the memory where BL2 will be loaded is
+within the specified region and marked as free.
+
+The actual number of regions and their base addresses and sizes is platform
+specific. The platform may return the same region or define a different one for
+each API. However, the overlap verification mechanism applies only to a single
+region. Hence, it is the platform responsibility to guarantee that different
+regions do not overlap, or that if they do, the overlapping images are not
+accessed at the same time. This could be used, for example, to load temporary
+images (e.g. certificates) or firmware images prior to being transfered to its
+corresponding processor (e.g. the SCP BL2 image).
+
+To reduce fragmentation and simplify the tracking of free memory, all the free
+memory within a region is always located in one single buffer defined by its
+base address and size. Trusted Firmware implements a top/bottom load approach:
+after a new image is loaded, it checks how much memory remains free above and
+below the image. The smallest area is marked as unavailable, while the larger
+area becomes the new free memory buffer. Platforms should take this behaviour
+into account when defining the base address for each of the images. For example,
+if an image is loaded near the middle of the region, small changes in image size
+could cause a flip between a top load and a bottom load, which may result in an
+unexpected memory layout.
+
+The following diagram is an example of an image loaded in the bottom part of
+the memory region. The region is initially free (nothing has been loaded yet):
+
+ Memory region
+ +----------+
+ | |
+ | | <<<<<<<<<<<<< Free
+ | |
+ |----------| +------------+
+ | image | <<<<<<<<<<<<< | image |
+ |----------| +------------+
+ | xxxxxxxx | <<<<<<<<<<<<< Marked as unavailable
+ +----------+
+
+And the following diagram is an example of an image loaded in the top part:
+
+ Memory region
+ +----------+
+ | xxxxxxxx | <<<<<<<<<<<<< Marked as unavailable
+ |----------| +------------+
+ | image | <<<<<<<<<<<<< | image |
+ |----------| +------------+
+ | |
+ | | <<<<<<<<<<<<< Free
+ | |
+ +----------+
+
#### Memory layout on ARM development platforms
@@ -1229,9 +1284,47 @@
* Secure region of DRAM (top 16MB of DRAM configured by the TrustZone
controller)
+ When BL32 is loaded into Trusted SRAM, its NOBITS sections are allowed to
+ overlay BL2. This memory layout is designed to give the BL32 image as much
+ memory as possible when it is loaded into Trusted SRAM.
+
-When BL32 is loaded into Trusted SRAM, its NOBITS sections are allowed to
-overlay BL2. This memory layout is designed to give the BL32 image as much
-memory as possible when it is loaded into Trusted SRAM.
+The memory regions for the overlap detection mechanism at boot time are
+defined as follows (shown per API):
+
+* `meminfo_t *bl1_plat_sec_mem_layout(void)`
+
+ This region corresponds to the whole Trusted SRAM except for the shared
+ memory at the base. This region is initially free. At boot time, BL1 will
+ mark the BL1(rw) section within this region as occupied. The BL1(rw) section
+ is placed at the top of Trusted SRAM.
+
+* `meminfo_t *bl2_plat_sec_mem_layout(void)`
+
+ This region corresponds to the whole Trusted SRAM as defined by
+ `bl1_plat_sec_mem_layout()`, but with the BL1(rw) section marked as
+ occupied. This memory region is used to check that BL2 and BL31 do not
+ overlap with each other. BL2_BASE and BL1_RW_BASE are carefully chosen so
+ that the memory for BL31 is top loaded above BL2.
+
+* `void bl2_plat_get_scp_bl2_meminfo(meminfo_t *scp_bl2_meminfo)`
+
+ This region is an exact copy of the region defined by
+ `bl2_plat_sec_mem_layout()`. Being a disconnected copy means that all the
+ changes made to this region by the Trusted Firmware will not be propagated.
+ This approach is valid because the SCP BL2 image is loaded temporarily
+ while it is being transferred to the SCP, so this memory is reused
+ afterwards.
+
+* `void bl2_plat_get_bl32_meminfo(meminfo_t *bl32_meminfo)`
+
+ This region depends on the location of the BL32 image. Currently, ARM
+ platforms support three different locations (detailed below): Trusted SRAM,
+ Trusted DRAM and the TZC-Secured DRAM.
+
+* `void bl2_plat_get_bl33_meminfo(meminfo_t *bl33_meminfo)`
+
+ This region corresponds to the Non-Secure DDR-DRAM, excluding the
+ TZC-Secured area.
The location of the BL32 image will result in different memory maps. This is
illustrated for both FVP and Juno in the following diagrams, using the TSP as
@@ -1729,7 +1822,7 @@
- - - - - - - - - - - - - - - - - - - - - - - - - -
-_Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved._
+_Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved._
[ARM ARM]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0487a.e/index.html "ARMv8-A Reference Manual (ARM DDI0487A.E)"
[PSCI]: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf "Power State Coordination Interface PDD (ARM DEN 0022C)"
diff --git a/docs/porting-guide.md b/docs/porting-guide.md
index 56ddbb1..3b6e242 100644
--- a/docs/porting-guide.md
+++ b/docs/porting-guide.md
@@ -76,12 +76,12 @@
A platform port must enable the Memory Management Unit (MMU) as well as the
instruction and data caches for each BL stage. Setting up the translation
tables is the responsibility of the platform port because memory maps differ
-across platforms. A memory translation library (see `lib/aarch64/xlat_helpers.c`
-and `lib/aarch64/xlat_tables.c`) is provided to help in this setup. Note that
-although this library supports non-identity mappings, this is intended only for
-re-mapping peripheral physical addresses and allows platforms with high I/O
-addresses to reduce their virtual address space. All other addresses
-corresponding to code and data must currently use an identity mapping.
+across platforms. A memory translation library (see `lib/aarch64/xlat_tables.c`)
+is provided to help in this setup. Note that although this library supports
+non-identity mappings, this is intended only for re-mapping peripheral physical
+addresses and allows platforms with high I/O addresses to reduce their virtual
+address space. All other addresses corresponding to code and data must currently
+use an identity mapping.
In ARM standard platforms, each BL stage configures the MMU in the
platform-specific architecture setup function, `blX_plat_arch_setup()`, and uses
@@ -230,11 +230,6 @@
Defines the maximum address in secure RAM that the BL31 image can occupy.
-* **#define : NS_IMAGE_OFFSET**
-
- Defines the base address in non-secure DRAM where BL2 loads the BL33 binary
- image. Must be aligned on a page-size boundary.
-
For every image, the platform must define individual identifiers that will be
used by BL1 or BL2 to load the corresponding image into memory from non-volatile
storage. For the sake of performance, integer numbers will be used as
@@ -476,6 +471,18 @@
Defines the maximum address that the TSP's progbits sections can occupy.
+If the platform port uses the PL061 GPIO driver, the following constant may
+optionally be defined:
+
+* **PLAT_PL061_MAX_GPIOS**
+ Maximum number of GPIOs required by the platform. This allows control how
+ much memory is allocated for PL061 GPIO controllers. The default value is
+ 32.
+ [For example, define the build flag in platform.mk]:
+ PLAT_PL061_MAX_GPIOS := 160
+ $(eval $(call add_define,PLAT_PL061_MAX_GPIOS))
+
+
### File : plat_macros.S [mandatory]
Each platform must ensure a file of this name is in the system include path with
@@ -625,6 +632,35 @@
retrieved from the platform. The function also reports extra information related
to the ROTPK in the flags parameter.
+
+### Function: plat_get_nv_ctr()
+
+ Argument : void *, unsigned int *
+ Return : int
+
+This function is mandatory when Trusted Board Boot is enabled. It returns the
+non-volatile counter value stored in the platform in the second argument. The
+cookie in the first argument may be used to select the counter in case the
+platform provides more than one (for example, on platforms that use the default
+TBBR CoT, the cookie will correspond to the OID values defined in
+TRUSTED_FW_NVCOUNTER_OID or NON_TRUSTED_FW_NVCOUNTER_OID).
+
+The function returns 0 on success. Any other value means the counter value could
+not be retrieved from the platform.
+
+
+### Function: plat_set_nv_ctr()
+
+ Argument : void *, unsigned int
+ Return : int
+
+This function is mandatory when Trusted Board Boot is enabled. It sets a new
+counter value in the platform. The cookie in the first argument may be used to
+select the counter (as explained in plat_get_nv_ctr()).
+
+The function returns 0 on success. Any other value means the counter value could
+not be updated.
+
2.3 Common mandatory modifications
---------------------------------
@@ -642,7 +678,8 @@
per-CPU stacks). This function will be invoked very early in the
initialization sequence which mandates that this function should be
implemented in assembly and should not rely on the avalability of a C
-runtime environment.
+runtime environment. This function can clobber x0 - x8 and must preserve
+x9 - x29.
This function plays a crucial role in the power domain topology framework in
PSCI and details of this can be found in [Power Domain Topology Design].
@@ -770,6 +807,20 @@
The default implementation simply spins.
+### Function : plat_panic_handler()
+
+ Argument : void
+ Return : void
+
+This API is called when the generic code encounters an unexpected error
+situation from which it cannot recover. This function must not return,
+and must be implemented in assembly because it may be called before the C
+environment is initialized.
+
+Note: The address from where it was called is stored in x30 (Link Register).
+
+The default implementation simply spins.
+
3. Modifications specific to a Boot Loader stage
-------------------------------------------------
@@ -827,8 +878,16 @@
This function executes with the MMU and data caches disabled. It is only called
by the primary CPU.
+On ARM standard platforms, this function:
+
+* Enables a secure instance of SP805 to act as the Trusted Watchdog.
+
-In ARM standard platforms, this function initializes the console and enables
-snoop requests into the primary CPU's cluster.
+* Initializes a UART (PL011 console), which enables access to the `printf`
+ family of functions in BL1.
+
+* Enables issuing of snoop and DVM (Distributed Virtual Memory) requests to
+ the CCI slave interface corresponding to the cluster that includes the
+ primary CPU.
### Function : bl1_plat_arch_setup() [mandatory]
@@ -1012,10 +1071,10 @@
structure in memory provided by the platform with information about how
BL31 should pass control to the BL32 image.
-5. Loading the normal world BL33 binary image into non-secure DRAM from
- platform storage and arranging for BL31 to pass control to this image. This
- address is determined using the `plat_get_ns_image_entrypoint()` function
- described below.
+5. (Optional) Loading the normal world BL33 binary image (if not loaded by
+ other means) into non-secure DRAM from platform storage and arranging for
+ BL31 to pass control to this image. This address is determined using the
+ `plat_get_ns_image_entrypoint()` function described below.
6. BL2 populates an `entry_point_info` structure in memory provided by the
platform with information about how BL31 should pass control to the
@@ -1034,15 +1093,19 @@
by the primary CPU. The arguments to this function is the address of the
`meminfo` structure populated by BL1.
-The platform must copy the contents of the `meminfo` structure into a private
+The platform may copy the contents of the `meminfo` structure into a private
variable as the original memory may be subsequently overwritten by BL2. The
copied structure is made available to all BL2 code through the
`bl2_plat_sec_mem_layout()` function.
+On ARM standard platforms, this function also:
+
+* Initializes a UART (PL011 console), which enables access to the `printf`
+ family of functions in BL2.
+
-In ARM standard platforms, this function also initializes the storage
-abstraction layer used to load further bootloader images. It is necessary to do
-this early on platforms with a SCP_BL2 image, since the later
-`bl2_platform_setup` must be done after SCP_BL2 is loaded.
+* Initializes the storage abstraction layer used to load further bootloader
+ images. It is necessary to do this early on platforms with a SCP_BL2 image,
+ since the later `bl2_platform_setup` must be done after SCP_BL2 is loaded.
### Function : bl2_plat_arch_setup() [mandatory]
@@ -1054,9 +1117,9 @@
by the primary CPU.
The purpose of this function is to perform any architectural initialization
-that varies across platforms, for example enabling the MMU (since the memory
-map differs across platforms).
+that varies across platforms.
+On ARM standard platforms, this function enables the MMU.
### Function : bl2_platform_setup() [mandatory]
@@ -1183,6 +1246,10 @@
overwrite the entry point set by loader and also set the security state
and SPSR which represents the entry point system state for BL33.
+In the preloaded BL33 alternative boot flow, this function is called after
+populating its entry point address. It is passed a null pointer as its first
+argument in this case.
+
### Function : bl2_plat_get_bl32_meminfo() [mandatory]
@@ -1204,6 +1271,9 @@
validate whether the BL33 image can be loaded with in the given
memory from the given base.
+This function isn't needed if either `BL33_BASE` or `EL3_PAYLOAD_BASE` build
+options are used.
+
### Function : bl2_plat_flush_bl31_params() [mandatory]
Argument : void
@@ -1218,7 +1288,7 @@
### Function : plat_get_ns_image_entrypoint() [mandatory]
Argument : void
- Return : unsigned long
+ Return : uintptr_t
As previously described, BL2 is responsible for arranging for control to be
passed to a normal world BL image through BL31. This function returns the
@@ -1226,6 +1296,9 @@
BL2 is responsible for loading the normal world BL33 image (e.g. UEFI).
+This function isn't needed if either `BL33_BASE` or `EL3_PAYLOAD_BASE` build
+options are used.
+
3.3 FWU Boot Loader Stage 2 (BL2U)
----------------------------------
@@ -1257,7 +1330,7 @@
called by the primary CPU. The arguments to this function is the address
of the `meminfo` structure and platform specific info provided by BL1.
-The platform must copy the contents of the `mem_info` and `plat_info` into
+The platform may copy the contents of the `mem_info` and `plat_info` into
private storage as the original memory may be subsequently overwritten by BL2U.
On ARM CSS platforms `plat_info` is interpreted as an `image_info_t` structure,
@@ -1359,8 +1432,15 @@
In ARM standard platforms, BL2 passes a pointer to a `bl31_params` structure
in BL2 memory. BL31 copies the information in this pointer to internal data
-structures.
+structures. It also performs the following:
+* Initialize a UART (PL011 console), which enables access to the `printf`
+ family of functions in BL31.
+
+* Enable issuing of snoop and DVM (Distributed Virtual Memory) requests to the
+ CCI slave interface corresponding to the cluster that includes the primary
+ CPU.
+
### Function : bl31_plat_arch_setup() [mandatory]
@@ -1371,9 +1451,10 @@
by the primary CPU.
The purpose of this function is to perform any architectural initialization
-that varies across platforms, for example enabling the MMU (since the memory
-map differs across platforms).
+that varies across platforms.
+On ARM standard platforms, this function enables the MMU.
+
### Function : bl31_platform_setup() [mandatory]
@@ -1387,13 +1468,33 @@
The purpose of this function is to complete platform initialization so that both
BL31 runtime services and normal world software can function correctly.
+On ARM standard platforms, this function does the following:
+
-In ARM standard platforms, this function does the following:
-* Initializes the generic interrupt controller.
-* Enables system-level implementation of the generic timer counter.
-* Grants access to the system counter timer module
-* Initializes the power controller device
-* Detects the system topology.
+* Initialize the generic interrupt controller.
+ Depending on the GIC driver selected by the platform, the appropriate GICv2
+ or GICv3 initialization will be done, which mainly consists of:
+
+ - Enable secure interrupts in the GIC CPU interface.
+ - Disable the legacy interrupt bypass mechanism.
+ - Configure the priority mask register to allow interrupts of all priorities
+ to be signaled to the CPU interface.
+ - Mark SGIs 8-15 and the other secure interrupts on the platform as secure.
+ - Target all secure SPIs to CPU0.
+ - Enable these secure interrupts in the GIC distributor.
+ - Configure all other interrupts as non-secure.
+ - Enable signaling of secure interrupts in the GIC distributor.
+
+* Enable system-level implementation of the generic timer counter through the
+ memory mapped interface.
+
+* Grant access to the system counter timer module
+
+* Initialize the power controller device.
+
+ In particular, initialise the locks that prevent concurrent accesses to the
+ power controller device.
+
### Function : bl31_plat_runtime_setup() [optional]
@@ -1899,9 +2000,10 @@
* **NEED_BL33**
By default, this flag is defined `yes` by the build system and `BL33`
- build option should be supplied as a build option. The platform has the option
- of excluding the BL33 image in the `fip` image by defining this flag to
- `no`.
+ build option should be supplied as a build option. The platform has the
+ option of excluding the BL33 image in the `fip` image by defining this flag
+ to `no`. If any of the options `EL3_PAYLOAD_BASE` or `BL33_BASE` are used,
+ this flag will be set to `no` automatically.
5. C Library
-------------
@@ -1993,7 +2095,7 @@
- - - - - - - - - - - - - - - - - - - - - - - - - -
-_Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved._
+_Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved._
[ARM GIC Architecture Specification 2.0]: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0048b/index.html
diff --git a/docs/user-guide.md b/docs/user-guide.md
index e692913..8d7376d 100644
--- a/docs/user-guide.md
+++ b/docs/user-guide.md
@@ -10,10 +10,11 @@
5. [Building the Trusted Firmware](#5--building-the-trusted-firmware)
6. [Building the rest of the software stack](#6--building-the-rest-of-the-software-stack)
7. [EL3 payloads alternative boot flow](#7--el3-payloads-alternative-boot-flow)
-8. [Preparing the images to run on FVP](#8--preparing-the-images-to-run-on-fvp)
-9. [Running the software on FVP](#9--running-the-software-on-fvp)
-10. [Running the software on Juno](#10--running-the-software-on-juno)
-11. [Changes required for booting Linux on FVP in GICv3 mode](#11--changes-required-for-booting-linux-on-fvp-in-gicv3-mode)
+8. [Preloaded BL33 alternative boot flow](#8--preloaded-bl33-alternative-boot-flow)
+9. [Preparing the images to run on FVP](#9--preparing-the-images-to-run-on-fvp)
+10. [Running the software on FVP](#10--running-the-software-on-fvp)
+11. [Running the software on Juno](#11--running-the-software-on-juno)
+12. [Changes required for booting Linux on FVP in GICv3 mode](#12--changes-required-for-booting-linux-on-fvp-in-gicv3-mode)
1. Introduction
@@ -41,6 +42,9 @@
building the software were installed from that distribution unless otherwise
specified.
+The software has also been built on Windows 7 Enterprise SP1, using CMD.EXE,
+Cygwin, and Msys (MinGW) shells, using version 4.9.1 of the GNU toolchain.
+
3. Tools
---------
@@ -407,12 +411,40 @@
payload. Please refer to the "Booting an EL3 payload" section for more
details.
+* `BL33_BASE`: This option enables booting a preloaded BL33 image instead of
+ the normal boot flow. When defined, it must specify the entry point address
+ for the preloaded BL33 image. This option is incompatible with
+ `EL3_PAYLOAD_BASE`. If both are defined, `EL3_PAYLOAD_BASE` has priority
+ over `BL33_BASE`.
+
* `PL011_GENERIC_UART`: Boolean option to indicate the PL011 driver that
the underlying hardware is not a full PL011 UART but a minimally compliant
generic UART, which is a subset of the PL011. The driver will not access
any register that is not part of the SBSA generic UART specification.
Default value is 0 (a full PL011 compliant UART is present).
+* `CTX_INCLUDE_FPREGS`: Boolean option that, when set to 1, will cause the FP
+ registers to be included when saving and restoring the CPU context. Default
+ is 0.
+
+* `DISABLE_PEDANTIC`: When set to 1 it will disable the -pedantic option in
+ the GCC command line. Default is 0.
+
+* `BUILD_STRING`: Input string for VERSION_STRING, which allows the TF build
+ to be uniquely identified. Defaults to the current git commit id.
+
+* `VERSION_STRING`: String used in the log output for each TF image. Defaults
+ to a string formed by concatenating the version number, build type and build
+ string.
+
+* `BUILD_MESSAGE_TIMESTAMP`: String used to identify the time and date of the
+ compilation of each build. It must be set to a C string (including quotes
+ where applicable). Defaults to a string that contains the time and date of
+ the compilation.
+
+* `HANDLE_EA_EL3_FIRST`: When defined External Aborts and SError Interrupts
+ will be always trapped in EL3 i.e. in BL31 at runtime.
+
#### ARM development platform specific build options
* `ARM_TSP_RAM_LOCATION`: location of the TSP binary. Options:
@@ -462,6 +494,19 @@
match the frame used by the Non-Secure image (normally the Linux kernel).
Default is true (access to the frame is allowed).
+* `ARM_BOARD_OPTIMISE_MMAP`: Boolean option to enable or disable optimisation
+ of page table and MMU related macros `PLAT_ARM_MMAP_ENTRIES` and
+ `MAX_XLAT_TABLES`. By default this flag is 0, which means it uses the
+ default unoptimised values for these macros. ARM development platforms
+ that wish to optimise memory usage for page tables need to set this flag to 1
+ and must override the related macros.
+
+* 'ARM_BL31_IN_DRAM': Boolean option to select loading of BL31 in TZC secured
+ DRAM. By default, BL31 is in the secure SRAM. Set this flag to 1 to load
+ BL31 in TZC secured DRAM. If TSP is present, then setting this option also
+ sets the TSP location to DRAM and ignores the `ARM_TSP_RAM_LOCATION` build
+ flag.
+
#### ARM CSS platform specific build options
* `CSS_DETECT_PRE_1_7_0_SCP`: Boolean flag to detect SCP version
@@ -471,6 +516,10 @@
set to 1 then Trusted Firmware will detect if an earlier version is in use.
Default is 1.
+* `CSS_LOAD_SCP_IMAGES`: Boolean flag, which when set, adds SCP_BL2 and
+ SCP_BL2U to the FIP and FWU_FIP respectively, and enables them to be loaded
+ during boot. Default is 1.
+
#### ARM FVP platform specific build options
* `FVP_USE_GIC_DRIVER` : Selects the GIC driver to be built. Options:
@@ -482,6 +531,11 @@
Trusted Firmware must be compiled with GICv2 only driver using
`FVP_USE_GIC_DRIVER=FVP_GICV2` build option.
+* `FVP_CLUSTER_COUNT` : Configures the cluster count to be used to
+ build the topology tree within Trusted Firmware. By default the
+ Trusted Firmware is configured for dual cluster topology and this option
+ can be used to override the default value.
+
### Creating a Firmware Image Package
FIPs are automatically created as part of the build instructions described in
@@ -937,8 +991,56 @@
Alternatively, the same DS-5 command mentioned in the FVP section above can
be used to load the EL3 payload's ELF file over JTAG on Juno.
+
+8. Preloaded BL33 alternative boot flow
+----------------------------------------
-8. Preparing the images to run on FVP
+Some platforms have the ability to preload BL33 into memory instead of relying
+on Trusted Firmware to load it. This may simplify packaging of the normal world
+code and improve performance in a development environment. When secure world
+cold boot is complete, Trusted Firmware simply jumps to a BL33 base address
+provided at build time.
+
+For this option to be used, the `BL33_BASE` build option has to be used when
+compiling the Trusted Firmware. For example, the following command will create
+a FIP without a BL33 and prepare to jump to a BL33 image loaded at address
+0x80000000:
+
+ CROSS_COMPILE=<path-to>/bin/aarch64-linux-gnu- \
+ make BL33_BASE=0x80000000 PLAT=fvp all fip
+
+#### Boot of a preloaded bootwrapped kernel image on Base FVP
+
+The following example uses the AArch64 boot wrapper. This simplifies normal
+world booting while also making use of TF features. It can be obtained from its
+repository with:
+
+ git clone git://git.kernel.org/pub/scm/linux/kernel/git/mark/boot-wrapper-aarch64.git
+
+After compiling it, an ELF file is generated. It can be loaded with the
+following command:
+
+ <path-to>/FVP_Base_AEMv8A-AEMv8A \
+ -C bp.secureflashloader.fname=bl1.bin \
+ -C bp.flashloader0.fname=fip.bin \
+ -a cluster0.cpu0=<bootwrapped-kernel.elf> \
+ --start cluster0.cpu0=0x0
+
+The `-a cluster0.cpu0=<bootwrapped-kernel.elf>` option loads the ELF file. It
+also sets the PC register to the ELF entry point address, which is not the
+desired behaviour, so the `--start cluster0.cpu0=0x0` option forces the PC back
+to 0x0 (the BL1 entry point address) on CPU #0. The `BL33_BASE` define used when
+compiling the FIP must match the ELF entry point.
+
+#### Boot of a preloaded bootwrapped kernel image on Juno
+
+The procedure to obtain and compile the boot wrapper is very similar to the case
+of the FVP. Once compiled, the `SPIN_ON_BL1_EXIT=1` loading method explained
+above in the EL3 payload boot flow section may be used to load the ELF file over
+JTAG on Juno.
+
+
+9. Preparing the images to run on FVP
--------------------------------------
Note: This section can be ignored when booting an EL3 payload, as no Flattened
@@ -991,20 +1093,21 @@
which the FVP is launched. Alternatively a symbolic link may be used.
-9. Running the software on FVP
--------------------------------
+10. Running the software on FVP
+--------------------------------
This version of the ARM Trusted Firmware has been tested on the following ARM
FVPs (64-bit versions only).
-* `Foundation_Platform` (Version 9.4, Build 9.4.59)
-* `FVP_Base_AEMv8A-AEMv8A` (Version 7.0, Build 0.8.7004)
-* `FVP_Base_Cortex-A57x4-A53x4` (Version 7.0, Build 0.8.7004)
-* `FVP_Base_Cortex-A57x1-A53x1` (Version 7.0, Build 0.8.7004)
-* `FVP_Base_Cortex-A57x2-A53x4` (Version 7.0, Build 0.8.7004)
+* `Foundation_Platform` (Version 9.5, Build 9.5.40)
+* `FVP_Base_AEMv8A-AEMv8A` (Version 7.2, Build 0.8.7202)
+* `FVP_Base_Cortex-A57x4-A53x4` (Version 7.2, Build 0.8.7202)
+* `FVP_Base_Cortex-A57x1-A53x1` (Version 7.2, Build 0.8.7202)
+* `FVP_Base_Cortex-A57x2-A53x4` (Version 7.2, Build 0.8.7202)
NOTE: The build numbers quoted above are those reported by launching the FVP
-with the `--version` parameter.
+with the `--version` parameter. `Foundation_Platform` tarball for `--version`
+9.5.40 is labeled as version 9.5.41.
NOTE: The software will not work on Version 1.0 of the Foundation FVP.
The commands below would report an `unhandled argument` error in this case.
@@ -1290,7 +1393,7 @@
detect the legacy VE memory map while configuring the GIC.
-10. Running the software on Juno
+11. Running the software on Juno
---------------------------------
This version of the ARM Trusted Firmware has been tested on Juno r0 and Juno r1.
@@ -1372,7 +1475,7 @@
wakeup interrupt from RTC.
-11. Changes required for booting Linux on FVP in GICv3 mode
+12. Changes required for booting Linux on FVP in GICv3 mode
------------------------------------------------------------
In case the TF FVP port is built with the build option
diff --git a/drivers/arm/gic/common/gic_common.c b/drivers/arm/gic/common/gic_common.c
index 17be61d..cfa0d23 100644
--- a/drivers/arm/gic/common/gic_common.c
+++ b/drivers/arm/gic/common/gic_common.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -31,6 +31,7 @@
#include <assert.h>
#include <gic_common.h>
#include <mmio.h>
+#include "gic_common_private.h"
/*******************************************************************************
* GIC Distributor interface accessors for reading entire registers
@@ -239,7 +240,10 @@
}
/*******************************************************************************
- * GIC Distributor interface accessors for individual interrupt manipulation
+ * GIC Distributor functions for accessing the GIC registers
+ * corresponding to a single interrupt ID. These functions use bitwise
+ * operations or appropriate register accesses to modify or return
+ * the bit-field corresponding the single interrupt ID.
******************************************************************************/
unsigned int gicd_get_igroupr(uintptr_t base, unsigned int id)
{
@@ -306,3 +310,8 @@
gicd_write_icactiver(base, id, (1 << bit_num));
}
+
+void gicd_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri)
+{
+ mmio_write_8(base + GICD_IPRIORITYR + id, pri & GIC_PRI_MASK);
+}
diff --git a/drivers/arm/gic/common/gic_common_private.h b/drivers/arm/gic/common/gic_common_private.h
new file mode 100644
index 0000000..2919b7f
--- /dev/null
+++ b/drivers/arm/gic/common/gic_common_private.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GIC_COMMON_PRIVATE_H_
+#define GIC_COMMON_PRIVATE_H_
+
+#include <gic_common.h>
+#include <mmio.h>
+#include <stdint.h>
+
+/*******************************************************************************
+ * GIC Distributor interface register accessors that are common to GICv3 & GICv2
+ ******************************************************************************/
+static inline unsigned int gicd_read_ctlr(uintptr_t base)
+{
+ return mmio_read_32(base + GICD_CTLR);
+}
+
+static inline unsigned int gicd_read_typer(uintptr_t base)
+{
+ return mmio_read_32(base + GICD_TYPER);
+}
+
+static inline unsigned int gicd_read_iidr(uintptr_t base)
+{
+ return mmio_read_32(base + GICD_IIDR);
+}
+
+static inline void gicd_write_ctlr(uintptr_t base, unsigned int val)
+{
+ mmio_write_32(base + GICD_CTLR, val);
+}
+
+/*******************************************************************************
+ * GIC Distributor function prototypes for accessing entire registers.
+ * Note: The raw register values correspond to multiple interrupt IDs and
+ * the number of interrupt IDs involved depends on the register accessed.
+ ******************************************************************************/
+unsigned int gicd_read_igroupr(uintptr_t base, unsigned int id);
+unsigned int gicd_read_isenabler(uintptr_t base, unsigned int id);
+unsigned int gicd_read_icenabler(uintptr_t base, unsigned int id);
+unsigned int gicd_read_ispendr(uintptr_t base, unsigned int id);
+unsigned int gicd_read_icpendr(uintptr_t base, unsigned int id);
+unsigned int gicd_read_isactiver(uintptr_t base, unsigned int id);
+unsigned int gicd_read_icactiver(uintptr_t base, unsigned int id);
+unsigned int gicd_read_ipriorityr(uintptr_t base, unsigned int id);
+unsigned int gicd_read_icfgr(uintptr_t base, unsigned int id);
+unsigned int gicd_read_nsacr(uintptr_t base, unsigned int id);
+void gicd_write_igroupr(uintptr_t base, unsigned int id, unsigned int val);
+void gicd_write_isenabler(uintptr_t base, unsigned int id, unsigned int val);
+void gicd_write_icenabler(uintptr_t base, unsigned int id, unsigned int val);
+void gicd_write_ispendr(uintptr_t base, unsigned int id, unsigned int val);
+void gicd_write_icpendr(uintptr_t base, unsigned int id, unsigned int val);
+void gicd_write_isactiver(uintptr_t base, unsigned int id, unsigned int val);
+void gicd_write_icactiver(uintptr_t base, unsigned int id, unsigned int val);
+void gicd_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val);
+void gicd_write_icfgr(uintptr_t base, unsigned int id, unsigned int val);
+void gicd_write_nsacr(uintptr_t base, unsigned int id, unsigned int val);
+
+/*******************************************************************************
+ * GIC Distributor function prototypes for accessing the GIC registers
+ * corresponding to a single interrupt ID. These functions use bitwise
+ * operations or appropriate register accesses to modify or return
+ * the bit-field corresponding the single interrupt ID.
+ ******************************************************************************/
+unsigned int gicd_get_igroupr(uintptr_t base, unsigned int id);
+void gicd_set_igroupr(uintptr_t base, unsigned int id);
+void gicd_clr_igroupr(uintptr_t base, unsigned int id);
+void gicd_set_isenabler(uintptr_t base, unsigned int id);
+void gicd_set_icenabler(uintptr_t base, unsigned int id);
+void gicd_set_ispendr(uintptr_t base, unsigned int id);
+void gicd_set_icpendr(uintptr_t base, unsigned int id);
+void gicd_set_isactiver(uintptr_t base, unsigned int id);
+void gicd_set_icactiver(uintptr_t base, unsigned int id);
+void gicd_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri);
+
+#endif /* GIC_COMMON_PRIVATE_H_ */
diff --git a/drivers/arm/gic/gic_v2.c b/drivers/arm/gic/gic_v2.c
index dc5dc08..05399c3 100644
--- a/drivers/arm/gic/gic_v2.c
+++ b/drivers/arm/gic/gic_v2.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -261,10 +261,6 @@
*/
void gicd_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri)
{
- unsigned int reg = base + GICD_IPRIORITYR + (id & ~3);
- unsigned int shift = (id & 3) << 3;
- unsigned int reg_val = mmio_read_32(reg);
-
/*
* Enforce ARM recommendation to manage priority values such
* that group1 interrupts always have a lower priority than
@@ -278,17 +274,12 @@
pri >= GIC_HIGHEST_SEC_PRIORITY &&
pri <= GIC_LOWEST_SEC_PRIORITY);
- reg_val &= ~(GIC_PRI_MASK << shift);
- reg_val |= (pri & GIC_PRI_MASK) << shift;
- mmio_write_32(reg, reg_val);
+ mmio_write_8(base + GICD_IPRIORITYR + id, pri & GIC_PRI_MASK);
}
void gicd_set_itargetsr(uintptr_t base, unsigned int id, unsigned int target)
{
- unsigned byte_off = id & ((1 << ITARGETSR_SHIFT) - 1);
- unsigned int reg_val = gicd_read_itargetsr(base, id);
-
- gicd_write_itargetsr(base, id, reg_val | (target << (byte_off << 3)));
+ mmio_write_8(base + GICD_ITARGETSR + id, target & GIC_TARGET_CPU_MASK);
}
/*******************************************************************************
diff --git a/drivers/arm/gic/gic_v3.c b/drivers/arm/gic/gic_v3.c
index f429662..11185b2 100644
--- a/drivers/arm/gic/gic_v3.c
+++ b/drivers/arm/gic/gic_v3.c
@@ -60,8 +60,8 @@
/* Disable this print for now as it appears every time
* when using PSCI CPU_SUSPEND.
* TODO: Print this only the first time for each CPU.
- * INFO("GICv3 - Found RDIST for MPIDR(0x%lx) at 0x%lx\n",
- * mpidr, addr);
+ * INFO("GICv3 - Found RDIST for MPIDR(0x%lx) at %p\n",
+ * mpidr, (void *) addr);
*/
return addr;
}
diff --git a/drivers/arm/gic/v2/gicv2_helpers.c b/drivers/arm/gic/v2/gicv2_helpers.c
index 1f904c5..b60a5cd 100644
--- a/drivers/arm/gic/v2/gicv2_helpers.c
+++ b/drivers/arm/gic/v2/gicv2_helpers.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -33,6 +33,7 @@
#include <assert.h>
#include <debug.h>
#include <gic_common.h>
+#include "../common/gic_common_private.h"
#include "gicv2_private.h"
/*
@@ -101,10 +102,7 @@
*/
void gicd_set_itargetsr(uintptr_t base, unsigned int id, unsigned int target)
{
- unsigned byte_off = id & ((1 << ITARGETSR_SHIFT) - 1);
- unsigned int reg_val = gicd_read_itargetsr(base, id);
-
- gicd_write_itargetsr(base, id, reg_val | (target << (byte_off << 3)));
+ mmio_write_8(base + GICD_ITARGETSR + id, target & GIC_TARGET_CPU_MASK);
}
/*******************************************************************************
@@ -166,7 +164,7 @@
gicd_clr_igroupr(gicd_base, irq_num);
/* Set the priority of this interrupt */
- gicd_write_ipriorityr(gicd_base,
+ gicd_set_ipriorityr(gicd_base,
irq_num,
GIC_HIGHEST_SEC_PRIORITY);
@@ -213,7 +211,7 @@
sec_ppi_sgi_mask |= 1U << irq_num;
/* Set the priority of this interrupt */
- gicd_write_ipriorityr(gicd_base,
+ gicd_set_ipriorityr(gicd_base,
irq_num,
GIC_HIGHEST_SEC_PRIORITY);
}
diff --git a/drivers/arm/gic/v2/gicv2_main.c b/drivers/arm/gic/v2/gicv2_main.c
index cf93926..305a8b0 100644
--- a/drivers/arm/gic/v2/gicv2_main.c
+++ b/drivers/arm/gic/v2/gicv2_main.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -34,6 +34,7 @@
#include <debug.h>
#include <gic_common.h>
#include <gicv2.h>
+#include "../common/gic_common_private.h"
#include "gicv2_private.h"
static const gicv2_driver_data_t *driver_data;
diff --git a/drivers/arm/gic/v3/gicv3_helpers.c b/drivers/arm/gic/v3/gicv3_helpers.c
index 2fb98cb..07ae54c 100644
--- a/drivers/arm/gic/v3/gicv3_helpers.c
+++ b/drivers/arm/gic/v3/gicv3_helpers.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -33,6 +33,7 @@
#include <assert.h>
#include <debug.h>
#include <gic_common.h>
+#include "../common/gic_common_private.h"
#include "gicv3_private.h"
/*
@@ -194,6 +195,15 @@
gicr_write_isenabler0(base, (1 << bit_num));
}
+/*
+ * Accessor to set the byte corresponding to interrupt ID
+ * in GIC Re-distributor IPRIORITYR.
+ */
+void gicr_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri)
+{
+ mmio_write_8(base + GICR_IPRIORITYR + id, pri & GIC_PRI_MASK);
+}
+
/******************************************************************************
* This function marks the core as awake in the re-distributor and
* ensures that the interface is active.
@@ -330,7 +340,7 @@
gicd_clr_igrpmodr(gicd_base, irq_num);
/* Set the priority of this interrupt */
- gicd_write_ipriorityr(gicd_base,
+ gicd_set_ipriorityr(gicd_base,
irq_num,
GIC_HIGHEST_SEC_PRIORITY);
@@ -404,7 +414,7 @@
gicr_clr_igrpmodr0(gicr_base, irq_num);
/* Set the priority of this interrupt */
- gicr_write_ipriorityr(gicr_base,
+ gicr_set_ipriorityr(gicr_base,
irq_num,
GIC_HIGHEST_SEC_PRIORITY);
diff --git a/drivers/arm/gic/v3/gicv3_main.c b/drivers/arm/gic/v3/gicv3_main.c
index d5cd0ed..6c6c7af 100644
--- a/drivers/arm/gic/v3/gicv3_main.c
+++ b/drivers/arm/gic/v3/gicv3_main.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -34,6 +34,7 @@
#include <debug.h>
#include <gic_common.h>
#include <gicv3.h>
+#include "../common/gic_common_private.h"
#include "gicv3_private.h"
static const gicv3_driver_data_t *driver_data;
diff --git a/drivers/arm/gic/v3/gicv3_private.h b/drivers/arm/gic/v3/gicv3_private.h
index c8b311a..5e2409f 100644
--- a/drivers/arm/gic/v3/gicv3_private.h
+++ b/drivers/arm/gic/v3/gicv3_private.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -84,16 +84,24 @@
((typer_val >> 32) & 0xffffff))
/*******************************************************************************
- * Private function prototypes
+ * Private GICv3 function prototypes for accessing entire registers.
+ * Note: The raw register values correspond to multiple interrupt IDs and
+ * the number of interrupt IDs involved depends on the register accessed.
******************************************************************************/
unsigned int gicd_read_igrpmodr(uintptr_t base, unsigned int id);
unsigned int gicr_read_ipriorityr(uintptr_t base, unsigned int id);
+void gicd_write_igrpmodr(uintptr_t base, unsigned int id, unsigned int val);
+void gicr_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val);
+
+/*******************************************************************************
+ * Private GICv3 function prototypes for accessing the GIC registers
+ * corresponding to a single interrupt ID. These functions use bitwise
+ * operations or appropriate register accesses to modify or return
+ * the bit-field corresponding the single interrupt ID.
+ ******************************************************************************/
unsigned int gicd_get_igrpmodr(uintptr_t base, unsigned int id);
unsigned int gicr_get_igrpmodr0(uintptr_t base, unsigned int id);
unsigned int gicr_get_igroupr0(uintptr_t base, unsigned int id);
-unsigned int gicv3_get_pending_grp1_interrupt_id(unsigned int pending_grp);
-void gicd_write_igrpmodr(uintptr_t base, unsigned int id, unsigned int val);
-void gicr_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val);
void gicd_set_igrpmodr(uintptr_t base, unsigned int id);
void gicr_set_igrpmodr0(uintptr_t base, unsigned int id);
void gicr_set_isenabler0(uintptr_t base, unsigned int id);
@@ -101,6 +109,11 @@
void gicd_clr_igrpmodr(uintptr_t base, unsigned int id);
void gicr_clr_igrpmodr0(uintptr_t base, unsigned int id);
void gicr_clr_igroupr0(uintptr_t base, unsigned int id);
+void gicr_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri);
+
+/*******************************************************************************
+ * Private GICv3 helper function prototypes
+ ******************************************************************************/
void gicv3_spis_configure_defaults(uintptr_t gicd_base);
void gicv3_ppi_sgi_configure_defaults(uintptr_t gicr_base);
void gicv3_secure_spis_configure(uintptr_t gicd_base,
@@ -179,6 +192,11 @@
mmio_write_32(base + GICR_WAKER, val);
}
+/*******************************************************************************
+ * GIC Re-distributor functions for accessing entire registers.
+ * Note: The raw register values correspond to multiple interrupt IDs and
+ * the number of interrupt IDs involved depends on the register accessed.
+ ******************************************************************************/
static inline unsigned int gicr_read_icenabler0(uintptr_t base)
{
return mmio_read_32(base + GICR_ICENABLER0);
diff --git a/drivers/arm/pl011/pl011_console.S b/drivers/arm/pl011/pl011_console.S
index f29f895..5e97e91 100644
--- a/drivers/arm/pl011/pl011_console.S
+++ b/drivers/arm/pl011/pl011_console.S
@@ -69,15 +69,6 @@
mov w4, #PL011_UARTCR_UARTEN
bic w3, w3, w4
str w3, [x0, #UARTCR]
- /* Flush the transmit FIFO */
- ldr w3, [x0, #UARTLCR_H]
- mov w4, #PL011_UARTLCR_H_FEN
- bic w3, w3, w4
- str w3, [x0, #UARTLCR_H]
- /* Wait for the end of Tx of current character */
-busy_loop:
- ldr w3, [x0, #UARTFR]
- tbnz w3, #PL011_UARTFR_BUSY_BIT, busy_loop
/* Program the baudrate */
/* Divisor = (Uart clock * 4) / baudrate */
lsl w1, w1, #2
diff --git a/drivers/arm/pl061/pl061_gpio.c b/drivers/arm/pl061/pl061_gpio.c
new file mode 100644
index 0000000..fca0056
--- /dev/null
+++ b/drivers/arm/pl061/pl061_gpio.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ARM PL061 GPIO Driver.
+ * Reference to ARM DDI 0190B document.
+ *
+ */
+
+#include <assert.h>
+#include <cassert.h>
+#include <debug.h>
+#include <errno.h>
+#include <gpio.h>
+#include <mmio.h>
+#include <pl061_gpio.h>
+
+#if !PLAT_PL061_MAX_GPIOS
+# define PLAT_PL061_MAX_GPIOS 32
+#endif /* PLAT_PL061_MAX_GPIOS */
+
+CASSERT(PLAT_PL061_MAX_GPIOS > 0, assert_plat_pl061_max_gpios);
+
+#define MAX_GPIO_DEVICES ((PLAT_PL061_MAX_GPIOS + \
+ (GPIOS_PER_PL061 - 1)) / GPIOS_PER_PL061)
+
+#define PL061_GPIO_DIR 0x400
+
+#define GPIOS_PER_PL061 8
+#define BIT(nr) (1UL << (nr))
+
+static int pl061_get_direction(int gpio);
+static void pl061_set_direction(int gpio, int direction);
+static int pl061_get_value(int gpio);
+static void pl061_set_value(int gpio, int value);
+
+static uintptr_t pl061_reg_base[MAX_GPIO_DEVICES];
+
+static const gpio_ops_t pl061_gpio_ops = {
+ .get_direction = pl061_get_direction,
+ .set_direction = pl061_set_direction,
+ .get_value = pl061_get_value,
+ .set_value = pl061_set_value,
+};
+
+static int pl061_get_direction(int gpio)
+{
+ uintptr_t base_addr;
+ unsigned int data, offset;
+
+ assert((gpio >= 0) && (gpio < PLAT_PL061_MAX_GPIOS));
+
+ base_addr = pl061_reg_base[gpio / GPIOS_PER_PL061];
+ offset = gpio % GPIOS_PER_PL061;
+ data = mmio_read_8(base_addr + PL061_GPIO_DIR);
+ if (data & BIT(offset))
+ return GPIO_DIR_OUT;
+ return GPIO_DIR_IN;
+}
+
+static void pl061_set_direction(int gpio, int direction)
+{
+ uintptr_t base_addr;
+ unsigned int data, offset;
+
+ assert((gpio >= 0) && (gpio < PLAT_PL061_MAX_GPIOS));
+
+ base_addr = pl061_reg_base[gpio / GPIOS_PER_PL061];
+ offset = gpio % GPIOS_PER_PL061;
+ if (direction == GPIO_DIR_OUT) {
+ data = mmio_read_8(base_addr + PL061_GPIO_DIR) | BIT(offset);
+ mmio_write_8(base_addr + PL061_GPIO_DIR, data);
+ } else {
+ data = mmio_read_8(base_addr + PL061_GPIO_DIR) & ~BIT(offset);
+ mmio_write_8(base_addr + PL061_GPIO_DIR, data);
+ }
+}
+
+/*
+ * The offset of GPIODATA register is 0.
+ * The values read from GPIODATA are determined for each bit, by the mask bit
+ * derived from the address used to access the data register, PADDR[9:2].
+ * Bits that are 1 in the address mask cause the corresponding bits in GPIODATA
+ * to be read, and bits that are 0 in the address mask cause the corresponding
+ * bits in GPIODATA to be read as 0, regardless of their value.
+ */
+static int pl061_get_value(int gpio)
+{
+ uintptr_t base_addr;
+ unsigned int offset;
+
+ assert((gpio >= 0) && (gpio < PLAT_PL061_MAX_GPIOS));
+
+ base_addr = pl061_reg_base[gpio / GPIOS_PER_PL061];
+ offset = gpio % GPIOS_PER_PL061;
+ if (mmio_read_8(base_addr + BIT(offset + 2)))
+ return GPIO_LEVEL_HIGH;
+ return GPIO_LEVEL_LOW;
+}
+
+/*
+ * In order to write GPIODATA, the corresponding bits in the mask, resulting
+ * from the address bus, PADDR[9:2], must be HIGH. Otherwise the bit values
+ * remain unchanged by the write.
+ */
+static void pl061_set_value(int gpio, int value)
+{
+ uintptr_t base_addr;
+ int offset;
+
+ assert((gpio >= 0) && (gpio < PLAT_PL061_MAX_GPIOS));
+
+ base_addr = pl061_reg_base[gpio / GPIOS_PER_PL061];
+ offset = gpio % GPIOS_PER_PL061;
+ if (value == GPIO_LEVEL_HIGH)
+ mmio_write_8(base_addr + BIT(offset + 2), BIT(offset));
+ else
+ mmio_write_8(base_addr + BIT(offset + 2), 0);
+}
+
+
+/*
+ * Register the PL061 GPIO controller with a base address and the offset
+ * of start pin in this GPIO controller.
+ * This function is called after pl061_gpio_ops_init().
+ */
+void pl061_gpio_register(uintptr_t base_addr, int gpio_dev)
+{
+ assert((gpio_dev >= 0) && (gpio_dev < MAX_GPIO_DEVICES));
+
+ pl061_reg_base[gpio_dev] = base_addr;
+}
+
+/*
+ * Initialize PL061 GPIO controller with the total GPIO numbers in SoC.
+ */
+void pl061_gpio_init(void)
+{
+ gpio_init(&pl061_gpio_ops);
+}
diff --git a/drivers/arm/tzc/tzc400.c b/drivers/arm/tzc/tzc400.c
new file mode 100644
index 0000000..ee6bf8d
--- /dev/null
+++ b/drivers/arm/tzc/tzc400.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <mmio.h>
+#include <stddef.h>
+#include <tzc400.h>
+#include "tzc_common_private.c"
+
+/*
+ * Macros which will be used by common core functions.
+ */
+#define TZC_400_REGION_BASE_LOW_0_OFFSET 0x100
+#define TZC_400_REGION_BASE_HIGH_0_OFFSET 0x104
+#define TZC_400_REGION_TOP_LOW_0_OFFSET 0x108
+#define TZC_400_REGION_TOP_HIGH_0_OFFSET 0x10c
+#define TZC_400_REGION_ATTR_0_OFFSET 0x110
+#define TZC_400_REGION_ID_ACCESS_0_OFFSET 0x114
+
+/*
+ * Implementation defined values used to validate inputs later.
+ * Filters : max of 4 ; 0 to 3
+ * Regions : max of 9 ; 0 to 8
+ * Address width : Values between 32 to 64
+ */
+typedef struct tzc400_instance {
+ uintptr_t base;
+ uint8_t addr_width;
+ uint8_t num_filters;
+ uint8_t num_regions;
+} tzc400_instance_t;
+
+tzc400_instance_t tzc400;
+
+static inline unsigned int _tzc400_read_build_config(uintptr_t base)
+{
+ return mmio_read_32(base + BUILD_CONFIG_OFF);
+}
+
+static inline unsigned int _tzc400_read_gate_keeper(uintptr_t base)
+{
+ return mmio_read_32(base + GATE_KEEPER_OFF);
+}
+
+static inline void _tzc400_write_gate_keeper(uintptr_t base, unsigned int val)
+{
+ mmio_write_32(base + GATE_KEEPER_OFF, val);
+}
+
+/*
+ * Get the open status information for all filter units.
+ */
+#define get_gate_keeper_os(base) ((_tzc400_read_gate_keeper(base) >> \
+ GATE_KEEPER_OS_SHIFT) & \
+ GATE_KEEPER_OS_MASK)
+
+
+/* Define common core functions used across different TZC peripherals. */
+DEFINE_TZC_COMMON_WRITE_ACTION(400, 400)
+DEFINE_TZC_COMMON_WRITE_REGION_BASE(400, 400)
+DEFINE_TZC_COMMON_WRITE_REGION_TOP(400, 400)
+DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(400, 400)
+DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(400, 400)
+DEFINE_TZC_COMMON_CONFIGURE_REGION0(400)
+DEFINE_TZC_COMMON_CONFIGURE_REGION(400)
+
+static unsigned int _tzc400_get_gate_keeper(uintptr_t base,
+ unsigned int filter)
+{
+ unsigned int open_status;
+
+ open_status = get_gate_keeper_os(base);
+
+ return (open_status >> filter) & GATE_KEEPER_FILTER_MASK;
+}
+
+/* This function is not MP safe. */
+static void _tzc400_set_gate_keeper(uintptr_t base,
+ unsigned int filter,
+ int val)
+{
+ unsigned int open_status;
+
+ /* Upper half is current state. Lower half is requested state. */
+ open_status = get_gate_keeper_os(base);
+
+ if (val)
+ open_status |= (1 << filter);
+ else
+ open_status &= ~(1 << filter);
+
+ _tzc400_write_gate_keeper(base, (open_status & GATE_KEEPER_OR_MASK) <<
+ GATE_KEEPER_OR_SHIFT);
+
+ /* Wait here until we see the change reflected in the TZC status. */
+ while ((get_gate_keeper_os(base)) != open_status)
+ ;
+}
+
+void tzc400_set_action(tzc_action_t action)
+{
+ assert(tzc400.base);
+ assert(action <= TZC_ACTION_ERR_INT);
+
+ /*
+ * - Currently no handler is provided to trap an error via interrupt
+ * or exception.
+ * - The interrupt action has not been tested.
+ */
+ _tzc400_write_action(tzc400.base, action);
+}
+
+void tzc400_init(uintptr_t base)
+{
+#if DEBUG
+ unsigned int tzc400_id;
+#endif
+ unsigned int tzc400_build;
+
+ assert(base);
+ tzc400.base = base;
+
+#if DEBUG
+ tzc400_id = _tzc_read_peripheral_id(base);
+ if (tzc400_id != TZC_400_PERIPHERAL_ID) {
+ ERROR("TZC-400 : Wrong device ID (0x%x).\n", tzc400_id);
+ panic();
+ }
+#endif
+
+ /* Save values we will use later. */
+ tzc400_build = _tzc400_read_build_config(tzc400.base);
+ tzc400.num_filters = ((tzc400_build >> BUILD_CONFIG_NF_SHIFT) &
+ BUILD_CONFIG_NF_MASK) + 1;
+ tzc400.addr_width = ((tzc400_build >> BUILD_CONFIG_AW_SHIFT) &
+ BUILD_CONFIG_AW_MASK) + 1;
+ tzc400.num_regions = ((tzc400_build >> BUILD_CONFIG_NR_SHIFT) &
+ BUILD_CONFIG_NR_MASK) + 1;
+}
+
+/*
+ * `tzc400_configure_region0` is used to program region 0 into the TrustZone
+ * controller. Region 0 covers the whole address space that is not mapped
+ * to any other region, and is enabled on all filters; this cannot be
+ * changed. This function only changes the access permissions.
+ */
+void tzc400_configure_region0(tzc_region_attributes_t sec_attr,
+ unsigned int ns_device_access)
+{
+ assert(tzc400.base);
+ assert(sec_attr <= TZC_REGION_S_RDWR);
+
+ _tzc400_configure_region0(tzc400.base, sec_attr, ns_device_access);
+}
+
+/*
+ * `tzc400_configure_region` is used to program regions into the TrustZone
+ * controller. A region can be associated with more than one filter. The
+ * associated filters are passed in as a bitmap (bit0 = filter0).
+ * NOTE:
+ * Region 0 is special; it is preferable to use tzc400_configure_region0
+ * for this region (see comment for that function).
+ */
+void tzc400_configure_region(unsigned int filters,
+ int region,
+ uintptr_t region_base,
+ uintptr_t region_top,
+ tzc_region_attributes_t sec_attr,
+ unsigned int nsaid_permissions)
+{
+ assert(tzc400.base);
+
+ /* Do range checks on filters and regions. */
+ assert(((filters >> tzc400.num_filters) == 0) &&
+ (region >= 0) && (region < tzc400.num_regions));
+
+ /*
+ * Do address range check based on TZC configuration. A 64bit address is
+ * the max and expected case.
+ */
+ assert(((region_top <= (UINT64_MAX >> (64 - tzc400.addr_width))) &&
+ (region_base < region_top)));
+
+ /* region_base and (region_top + 1) must be 4KB aligned */
+ assert(((region_base | (region_top + 1)) & (4096 - 1)) == 0);
+
+ assert(sec_attr <= TZC_REGION_S_RDWR);
+
+ _tzc400_configure_region(tzc400.base, filters, region, region_base,
+ region_top,
+ sec_attr, nsaid_permissions);
+}
+
+void tzc400_enable_filters(void)
+{
+ unsigned int state;
+ unsigned int filter;
+
+ assert(tzc400.base);
+
+ for (filter = 0; filter < tzc400.num_filters; filter++) {
+ state = _tzc400_get_gate_keeper(tzc400.base, filter);
+ if (state) {
+ /* The TZC filter is already configured. Changing the
+ * programmer's view in an active system can cause
+ * unpredictable behavior therefore panic for now rather
+ * than try to determine whether this is safe in this
+ * instance. See:
+ * http://infocenter.arm.com/help/index.jsp?\
+ * topic=/com.arm.doc.ddi0504c/CJHHECBF.html */
+ ERROR("TZC-400 : Filter %d Gatekeeper already"
+ " enabled.\n", filter);
+ panic();
+ }
+ _tzc400_set_gate_keeper(tzc400.base, filter, 1);
+ }
+}
+
+void tzc400_disable_filters(void)
+{
+ unsigned int filter;
+
+ assert(tzc400.base);
+
+ /*
+ * We don't do the same state check as above as the Gatekeepers are
+ * disabled after reset.
+ */
+ for (filter = 0; filter < tzc400.num_filters; filter++)
+ _tzc400_set_gate_keeper(tzc400.base, filter, 0);
+}
diff --git a/drivers/arm/tzc/tzc_common_private.c b/drivers/arm/tzc/tzc_common_private.c
new file mode 100644
index 0000000..f570daf
--- /dev/null
+++ b/drivers/arm/tzc/tzc_common_private.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <mmio.h>
+#include <tzc_common.h>
+
+#define DEFINE_TZC_COMMON_WRITE_ACTION(fn_name, macro_name) \
+ static inline void _tzc##fn_name##_write_action( \
+ uintptr_t base, \
+ tzc_action_t action) \
+ { \
+ mmio_write_32(base + TZC_##macro_name##_ACTION_OFF, \
+ action); \
+ }
+
+#define DEFINE_TZC_COMMON_WRITE_REGION_BASE(fn_name, macro_name) \
+ static inline void _tzc##fn_name##_write_region_base( \
+ uintptr_t base, \
+ int region_no, \
+ uintptr_t region_base) \
+ { \
+ mmio_write_32(base + \
+ TZC_REGION_OFFSET( \
+ TZC_##macro_name##_REGION_SIZE, \
+ region_no) + \
+ TZC_##macro_name##_REGION_BASE_LOW_0_OFFSET, \
+ (unsigned int)region_base); \
+ mmio_write_32(base + \
+ TZC_REGION_OFFSET( \
+ TZC_##macro_name##_REGION_SIZE, \
+ region_no) + \
+ TZC_##macro_name##_REGION_BASE_HIGH_0_OFFSET, \
+ (unsigned int)(region_base >> 32)); \
+ }
+
+#define DEFINE_TZC_COMMON_WRITE_REGION_TOP(fn_name, macro_name) \
+ static inline void _tzc##fn_name##_write_region_top( \
+ uintptr_t base, \
+ int region_no, \
+ uintptr_t region_top) \
+ { \
+ mmio_write_32(base + \
+ TZC_REGION_OFFSET \
+ (TZC_##macro_name##_REGION_SIZE, \
+ region_no) + \
+ TZC_##macro_name##_REGION_TOP_LOW_0_OFFSET, \
+ (unsigned int)region_top); \
+ mmio_write_32(base + \
+ TZC_REGION_OFFSET( \
+ TZC_##macro_name##_REGION_SIZE, \
+ region_no) + \
+ TZC_##macro_name##_REGION_TOP_HIGH_0_OFFSET, \
+ (unsigned int)(region_top >> 32)); \
+ }
+
+#define DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(fn_name, macro_name) \
+ static inline void _tzc##fn_name##_write_region_attributes( \
+ uintptr_t base, \
+ int region_no, \
+ unsigned int attr) \
+ { \
+ mmio_write_32(base + \
+ TZC_REGION_OFFSET( \
+ TZC_##macro_name##_REGION_SIZE, \
+ region_no) + \
+ TZC_##macro_name##_REGION_ATTR_0_OFFSET, \
+ attr); \
+ }
+
+#define DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(fn_name, macro_name) \
+ static inline void _tzc##fn_name##_write_region_id_access( \
+ uintptr_t base, \
+ int region_no, \
+ unsigned int val) \
+ { \
+ mmio_write_32(base + \
+ TZC_REGION_OFFSET( \
+ TZC_##macro_name##_REGION_SIZE, \
+ region_no) + \
+ TZC_##macro_name##_REGION_ID_ACCESS_0_OFFSET, \
+ val); \
+ }
+
+/*
+ * It is used to program region 0 ATTRIBUTES and ACCESS register.
+ */
+#define DEFINE_TZC_COMMON_CONFIGURE_REGION0(fn_name) \
+ void _tzc##fn_name##_configure_region0(uintptr_t base, \
+ tzc_region_attributes_t sec_attr, \
+ unsigned int ns_device_access) \
+ { \
+ assert(base); \
+ VERBOSE("TrustZone : Configuring region 0 " \
+ "(TZC Interface Base=%p sec_attr=0x%x," \
+ " ns_devs=0x%x)\n", (void *)base, \
+ sec_attr, ns_device_access); \
+ \
+ /* Set secure attributes on region 0 */ \
+ _tzc##fn_name##_write_region_attributes(base, 0, \
+ sec_attr << TZC_REGION_ATTR_SEC_SHIFT); \
+ \
+ /***************************************************/ \
+ /* Specify which non-secure devices have permission*/ \
+ /* to access region 0. */ \
+ /***************************************************/ \
+ _tzc##fn_name##_write_region_id_access(base, \
+ 0, \
+ ns_device_access); \
+ }
+
+/*
+ * It is used to program a region from 1 to 8 in the TrustZone controller.
+ * NOTE:
+ * Region 0 is special; it is preferable to use
+ * ##fn_name##_configure_region0 for this region (see comment for
+ * that function).
+ */
+#define DEFINE_TZC_COMMON_CONFIGURE_REGION(fn_name) \
+ void _tzc##fn_name##_configure_region(uintptr_t base, \
+ unsigned int filters, \
+ int region_no, \
+ uintptr_t region_base, \
+ uintptr_t region_top, \
+ tzc_region_attributes_t sec_attr, \
+ unsigned int nsaid_permissions) \
+ { \
+ assert(base); \
+ VERBOSE("TrustZone : Configuring region " \
+ "(TZC Interface Base: %p, region_no = %d)" \
+ "...\n", (void *)base, region_no); \
+ VERBOSE("TrustZone : ... base = %p, top = %p," \
+ "\n", (void *)region_base, (void *)region_top);\
+ VERBOSE("TrustZone : ... sec_attr = 0x%x," \
+ " ns_devs = 0x%x)\n", \
+ sec_attr, nsaid_permissions); \
+ \
+ /***************************************************/ \
+ /* Inputs look ok, start programming registers. */ \
+ /* All the address registers are 32 bits wide and */ \
+ /* have a LOW and HIGH */ \
+ /* component used to construct an address up to a */ \
+ /* 64bit. */ \
+ /***************************************************/ \
+ _tzc##fn_name##_write_region_base(base, \
+ region_no, region_base); \
+ _tzc##fn_name##_write_region_top(base, \
+ region_no, region_top); \
+ \
+ /* Enable filter to the region and set secure attributes */\
+ _tzc##fn_name##_write_region_attributes(base, \
+ region_no, \
+ (sec_attr << TZC_REGION_ATTR_SEC_SHIFT) |\
+ (filters << TZC_REGION_ATTR_F_EN_SHIFT));\
+ \
+ /***************************************************/ \
+ /* Specify which non-secure devices have permission*/ \
+ /* to access this region. */ \
+ /***************************************************/ \
+ _tzc##fn_name##_write_region_id_access(base, \
+ region_no, \
+ nsaid_permissions); \
+ }
+
+#if DEBUG
+static unsigned int _tzc_read_peripheral_id(uintptr_t base)
+{
+ unsigned int id;
+
+ id = mmio_read_32(base + PID0_OFF);
+ /* Masks DESC part in PID1 */
+ id |= ((mmio_read_32(base + PID1_OFF) & 0xF) << 8);
+
+ return id;
+}
+#endif
diff --git a/drivers/arm/tzc/tzc_dmc500.c b/drivers/arm/tzc/tzc_dmc500.c
new file mode 100644
index 0000000..16a53a4
--- /dev/null
+++ b/drivers/arm/tzc/tzc_dmc500.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <mmio.h>
+#include <tzc_dmc500.h>
+#include "tzc_common.h"
+#include "tzc_common_private.c"
+
+/*
+ * Macros which will be used by common core functions.
+ */
+#define TZC_DMC500_REGION_BASE_LOW_0_OFFSET 0x054
+#define TZC_DMC500_REGION_BASE_HIGH_0_OFFSET 0x058
+#define TZC_DMC500_REGION_TOP_LOW_0_OFFSET 0x05C
+#define TZC_DMC500_REGION_TOP_HIGH_0_OFFSET 0x060
+#define TZC_DMC500_REGION_ATTR_0_OFFSET 0x064
+#define TZC_DMC500_REGION_ID_ACCESS_0_OFFSET 0x068
+
+#define TZC_DMC500_ACTION_OFF 0x50
+
+/* Pointer to the tzc_dmc500_driver_data structure populated by the platform */
+static const tzc_dmc500_driver_data_t *g_driver_data;
+
+#define verify_region_attr(region, attr) \
+ ((g_conf_regions[(region)].sec_attr == \
+ ((attr) >> TZC_REGION_ATTR_SEC_SHIFT)) \
+ && ((attr) & (0x1 << TZC_REGION_ATTR_F_EN_SHIFT)))
+
+/*
+ * Structure for configured regions attributes in DMC500.
+ */
+typedef struct tzc_dmc500_regions {
+ tzc_region_attributes_t sec_attr;
+ int is_enabled;
+} tzc_dmc500_regions_t;
+
+/*
+ * Array storing the attributes of the configured regions. This array
+ * will be used by the `tzc_dmc500_verify_complete` to verify the flush
+ * completion.
+ */
+static tzc_dmc500_regions_t g_conf_regions[MAX_REGION_VAL + 1];
+
+/* Helper Macros for making the code readable */
+#define DMC_INST_BASE_ADDR(instance) (g_driver_data->dmc_base[instance])
+#define DMC_INST_SI_BASE(instance, interface) \
+ (DMC_INST_BASE_ADDR(instance) + IFACE_OFFSET(interface))
+
+DEFINE_TZC_COMMON_WRITE_ACTION(_dmc500, DMC500)
+DEFINE_TZC_COMMON_WRITE_REGION_BASE(_dmc500, DMC500)
+DEFINE_TZC_COMMON_WRITE_REGION_TOP(_dmc500, DMC500)
+DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(_dmc500, DMC500)
+DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(_dmc500, DMC500)
+
+DEFINE_TZC_COMMON_CONFIGURE_REGION0(_dmc500)
+DEFINE_TZC_COMMON_CONFIGURE_REGION(_dmc500)
+
+static inline unsigned int _tzc_dmc500_read_region_attr_0(
+ uintptr_t dmc_si_base,
+ int region_no)
+{
+ return mmio_read_32(dmc_si_base +
+ TZC_REGION_OFFSET(TZC_DMC500_REGION_SIZE, region_no) +
+ TZC_DMC500_REGION_ATTR_0_OFFSET);
+}
+
+static inline void _tzc_dmc500_write_flush_control(uintptr_t dmc_si_base)
+{
+ mmio_write_32(dmc_si_base + SI_FLUSH_CTRL_OFFSET, 1);
+}
+
+/*
+ * Sets the Flush controls for all the DMC Instances and System Interfaces.
+ * This initiates the flush of configuration settings from the shadow
+ * registers to the actual configuration register. The caller should poll
+ * changed register to confirm update.
+ */
+void tzc_dmc500_config_complete(void)
+{
+ int dmc_inst, sys_if;
+
+ assert(g_driver_data);
+
+ for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) {
+ assert(DMC_INST_BASE_ADDR(dmc_inst));
+ for (sys_if = 0; sys_if < MAX_SYS_IF_COUNT; sys_if++)
+ _tzc_dmc500_write_flush_control(
+ DMC_INST_SI_BASE(dmc_inst, sys_if));
+ }
+}
+
+/*
+ * This function reads back the secure attributes from the configuration
+ * register for each DMC Instance and System Interface and compares it with
+ * the configured value. The successful verification of the region attributes
+ * confirms that the flush operation has completed.
+ * If the verification fails, the caller is expected to invoke this API again
+ * till it succeeds.
+ * Returns 0 on success and 1 on failure.
+ */
+int tzc_dmc500_verify_complete(void)
+{
+ int dmc_inst, sys_if, region_no;
+ unsigned int attr;
+
+ assert(g_driver_data);
+ /* Region 0 must be configured */
+ assert(g_conf_regions[0].is_enabled);
+
+ /* Iterate over all configured regions */
+ for (region_no = 0; region_no <= MAX_REGION_VAL; region_no++) {
+ if (!g_conf_regions[region_no].is_enabled)
+ continue;
+ for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count;
+ dmc_inst++) {
+ assert(DMC_INST_BASE_ADDR(dmc_inst));
+ for (sys_if = 0; sys_if < MAX_SYS_IF_COUNT;
+ sys_if++) {
+ attr = _tzc_dmc500_read_region_attr_0(
+ DMC_INST_SI_BASE(dmc_inst, sys_if),
+ region_no);
+ VERBOSE("Verifying DMC500 region:%d"
+ " dmc_inst:%d sys_if:%d attr:%x\n",
+ region_no, dmc_inst, sys_if, attr);
+ if (!verify_region_attr(region_no, attr))
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * `tzc_dmc500_configure_region0` is used to program region 0 in both the
+ * system interfaces of all the DMC-500 instances. Region 0 covers the whole
+ * address space that is not mapped to any other region for a system interface,
+ * and is always enabled; this cannot be changed. This function only changes
+ * the access permissions.
+ */
+void tzc_dmc500_configure_region0(tzc_region_attributes_t sec_attr,
+ unsigned int nsaid_permissions)
+{
+ int dmc_inst, sys_if;
+
+ /* Assert if DMC-500 is not initialized */
+ assert(g_driver_data);
+
+ /* Configure region_0 in all DMC instances */
+ for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) {
+ assert(DMC_INST_BASE_ADDR(dmc_inst));
+ for (sys_if = 0; sys_if < MAX_SYS_IF_COUNT; sys_if++)
+ _tzc_dmc500_configure_region0(
+ DMC_INST_SI_BASE(dmc_inst, sys_if),
+ sec_attr, nsaid_permissions);
+ }
+
+ g_conf_regions[0].sec_attr = sec_attr;
+ g_conf_regions[0].is_enabled = 1;
+}
+
+/*
+ * `tzc_dmc500_configure_region` is used to program a region into all system
+ * interfaces of all the DMC instances.
+ * NOTE:
+ * Region 0 is special; it is preferable to use tzc_dmc500_configure_region0
+ * for this region (see comment for that function).
+ */
+void tzc_dmc500_configure_region(int region_no,
+ uintptr_t region_base,
+ uintptr_t region_top,
+ tzc_region_attributes_t sec_attr,
+ unsigned int nsaid_permissions)
+{
+ int dmc_inst, sys_if;
+
+ assert(g_driver_data);
+ /* Do range checks on regions. */
+ assert(region_no >= 0 && region_no <= MAX_REGION_VAL);
+
+ /*
+ * Do address range check based on DMC-TZ configuration. A 43bit address
+ * is the max and expected case.
+ */
+ assert(((region_top <= (UINT64_MAX >> (64 - 43))) &&
+ (region_base < region_top)));
+
+ /* region_base and (region_top + 1) must be 4KB aligned */
+ assert(((region_base | (region_top + 1)) & (4096 - 1)) == 0);
+
+ for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) {
+ assert(DMC_INST_BASE_ADDR(dmc_inst));
+ for (sys_if = 0; sys_if < MAX_SYS_IF_COUNT; sys_if++)
+ _tzc_dmc500_configure_region(
+ DMC_INST_SI_BASE(dmc_inst, sys_if),
+ TZC_DMC500_REGION_ATTR_F_EN_MASK,
+ region_no, region_base, region_top,
+ sec_attr, nsaid_permissions);
+ }
+
+ g_conf_regions[region_no].sec_attr = sec_attr;
+ g_conf_regions[region_no].is_enabled = 1;
+}
+
+/* Sets the action value for all the DMC instances */
+void tzc_dmc500_set_action(tzc_action_t action)
+{
+ int dmc_inst;
+
+ assert(g_driver_data);
+
+ for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) {
+ assert(DMC_INST_BASE_ADDR(dmc_inst));
+ /*
+ * - Currently no handler is provided to trap an error via
+ * interrupt or exception.
+ * - The interrupt action has not been tested.
+ */
+ _tzc_dmc500_write_action(DMC_INST_BASE_ADDR(dmc_inst), action);
+ }
+}
+
+/*
+ * A DMC-500 instance must be present at each base address provided by the
+ * platform. It also expects platform to pass at least one instance of
+ * DMC-500.
+ */
+static void validate_plat_driver_data(
+ const tzc_dmc500_driver_data_t *plat_driver_data)
+{
+#if DEBUG
+ int i;
+ unsigned int dmc_id;
+ uintptr_t dmc_base;
+
+ assert(plat_driver_data);
+ assert(plat_driver_data->dmc_count > 0 &&
+ (plat_driver_data->dmc_count <= MAX_DMC_COUNT));
+
+ for (i = 0; i < plat_driver_data->dmc_count; i++) {
+ dmc_base = plat_driver_data->dmc_base[i];
+ assert(dmc_base);
+
+ dmc_id = _tzc_read_peripheral_id(dmc_base);
+ assert(dmc_id == DMC500_PERIPHERAL_ID);
+ }
+#endif /* DEBUG */
+}
+
+
+/*
+ * Initializes the base address and count of DMC instances.
+ *
+ * Note : Only pointer to plat_driver_data is saved, so it is caller's
+ * responsibility to keep it valid until the driver is used.
+ */
+void tzc_dmc500_driver_init(const tzc_dmc500_driver_data_t *plat_driver_data)
+{
+ /* Check valid pointer is passed */
+ assert(plat_driver_data);
+
+ /*
+ * NOTE: This driver expects the DMC-500 controller is already in
+ * READY state. Hence, it uses the reconfiguration method for
+ * programming TrustZone regions
+ */
+ /* Validates the information passed by platform */
+ validate_plat_driver_data(plat_driver_data);
+ g_driver_data = plat_driver_data;
+}
diff --git a/drivers/arm/tzc400/tzc400.c b/drivers/arm/tzc400/tzc400.c
index 7194443..97adf81 100644
--- a/drivers/arm/tzc400/tzc400.c
+++ b/drivers/arm/tzc400/tzc400.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -28,313 +28,8 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <assert.h>
-#include <debug.h>
-#include <mmio.h>
-#include <stddef.h>
-#include <tzc400.h>
-
-/*
- * Implementation defined values used to validate inputs later.
- * Filters : max of 4 ; 0 to 3
- * Regions : max of 9 ; 0 to 8
- * Address width : Values between 32 to 64
- */
-typedef struct tzc_instance {
- uintptr_t base;
- uint8_t addr_width;
- uint8_t num_filters;
- uint8_t num_regions;
-} tzc_instance_t;
-
-tzc_instance_t tzc;
-
-
-static inline uint32_t tzc_read_build_config(uintptr_t base)
-{
- return mmio_read_32(base + BUILD_CONFIG_OFF);
-}
-
-static inline uint32_t tzc_read_gate_keeper(uintptr_t base)
-{
- return mmio_read_32(base + GATE_KEEPER_OFF);
-}
-
-static inline void tzc_write_gate_keeper(uintptr_t base, uint32_t val)
-{
- mmio_write_32(base + GATE_KEEPER_OFF, val);
-}
-
-static inline void tzc_write_action(uintptr_t base, tzc_action_t action)
-{
- mmio_write_32(base + ACTION_OFF, action);
-}
-
-static inline void tzc_write_region_base_low(uintptr_t base,
- uint32_t region,
- uint32_t val)
-{
- mmio_write_32(base + REGION_BASE_LOW_OFF +
- REGION_NUM_OFF(region), val);
-}
-
-static inline void tzc_write_region_base_high(uintptr_t base,
- uint32_t region,
- uint32_t val)
-{
- mmio_write_32(base + REGION_BASE_HIGH_OFF +
- REGION_NUM_OFF(region), val);
-}
-
-static inline void tzc_write_region_top_low(uintptr_t base,
- uint32_t region,
- uint32_t val)
-{
- mmio_write_32(base + REGION_TOP_LOW_OFF +
- REGION_NUM_OFF(region), val);
-}
-
-static inline void tzc_write_region_top_high(uintptr_t base,
- uint32_t region,
- uint32_t val)
-{
- mmio_write_32(base + REGION_TOP_HIGH_OFF +
- REGION_NUM_OFF(region), val);
-}
-
-static inline void tzc_write_region_attributes(uintptr_t base,
- uint32_t region,
- uint32_t val)
-{
- mmio_write_32(base + REGION_ATTRIBUTES_OFF +
- REGION_NUM_OFF(region), val);
-}
-
-static inline void tzc_write_region_id_access(uintptr_t base,
- uint32_t region,
- uint32_t val)
-{
- mmio_write_32(base + REGION_ID_ACCESS_OFF +
- REGION_NUM_OFF(region), val);
-}
-
-static unsigned int tzc_read_peripheral_id(uintptr_t base)
-{
- unsigned int id;
-
- id = mmio_read_8(base + PID0_OFF);
- /* Masks jep106_id_3_0 part in PID1 */
- id |= ((mmio_read_8(base + PID1_OFF) & 0xF) << 8);
-
- return id;
-}
-
-static uint32_t tzc_get_gate_keeper(uintptr_t base, uint8_t filter)
-{
- uint32_t tmp;
-
- tmp = (tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
- GATE_KEEPER_OS_MASK;
-
- return (tmp >> filter) & GATE_KEEPER_FILTER_MASK;
-}
-
-/* This function is not MP safe. */
-static void tzc_set_gate_keeper(uintptr_t base, uint8_t filter, uint32_t val)
-{
- uint32_t tmp;
-
- /* Upper half is current state. Lower half is requested state. */
- tmp = (tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
- GATE_KEEPER_OS_MASK;
-
- if (val)
- tmp |= (1 << filter);
- else
- tmp &= ~(1 << filter);
-
- tzc_write_gate_keeper(base, (tmp & GATE_KEEPER_OR_MASK) <<
- GATE_KEEPER_OR_SHIFT);
-
- /* Wait here until we see the change reflected in the TZC status. */
- while (((tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
- GATE_KEEPER_OS_MASK) != tmp)
- ;
-}
-
-
-void tzc_init(uintptr_t base)
-{
- unsigned int tzc_id;
- unsigned int tzc_build;
-
- assert(base);
-
- tzc.base = base;
-
- /*
- * We expect to see a tzc400. Check peripheral ID.
- */
- tzc_id = tzc_read_peripheral_id(tzc.base);
- if (tzc_id != TZC400_PERIPHERAL_ID) {
- ERROR("TZC : Wrong device ID (0x%x).\n", tzc_id);
- panic();
- }
-
- /* Save values we will use later. */
- tzc_build = tzc_read_build_config(tzc.base);
- tzc.num_filters = ((tzc_build >> BUILD_CONFIG_NF_SHIFT) &
- BUILD_CONFIG_NF_MASK) + 1;
- tzc.addr_width = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) &
- BUILD_CONFIG_AW_MASK) + 1;
- tzc.num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) &
- BUILD_CONFIG_NR_MASK) + 1;
-}
-
-/*
- * `tzc_configure_region0` is used to program region 0 into the TrustZone
- * controller. Region 0 covers the whole address space that is not mapped
- * to any other region, and is enabled on all filters; this cannot be
- * changed. This function only changes the access permissions.
- */
-void tzc_configure_region0(tzc_region_attributes_t sec_attr,
- uint32_t ns_device_access)
-{
- assert(tzc.base);
-
- VERBOSE("TZC : Configuring region 0 (sec_attr=0x%x, ns_devs=0x%x)\n",
- sec_attr, ns_device_access);
-
- assert(sec_attr <= TZC_REGION_S_RDWR);
-
- /* Set secure attributes on region 0 */
- tzc_write_region_attributes(tzc.base, 0,
- sec_attr << REG_ATTR_SEC_SHIFT);
-
- /*
- * Specify which non-secure devices have permission to access
- * region 0.
- */
- tzc_write_region_id_access(tzc.base, 0, ns_device_access);
-}
-
-
-/*
- * `tzc_configure_region` is used to program regions into the TrustZone
- * controller. A region can be associated with more than one filter. The
- * associated filters are passed in as a bitmap (bit0 = filter0).
- * NOTE:
- * Region 0 is special; it is preferable to use tzc_configure_region0
- * for this region (see comment for that function).
- */
-void tzc_configure_region(uint32_t filters,
- uint8_t region,
- uint64_t region_base,
- uint64_t region_top,
- tzc_region_attributes_t sec_attr,
- uint32_t ns_device_access)
-{
- assert(tzc.base);
-
- VERBOSE("TZC : Configuring region (filters=0x%x, region=%d, ...\n",
- filters, region);
- VERBOSE("TZC : ... base=0x%lx, top=0x%lx, ...\n",
- region_base, region_top);
- VERBOSE("TZC : ... sec_attr=0x%x, ns_devs=0x%x)\n",
- sec_attr, ns_device_access);
-
- /* Do range checks on filters and regions. */
- assert(((filters >> tzc.num_filters) == 0) &&
- (region < tzc.num_regions));
-
- /*
- * Do address range check based on TZC configuration. A 64bit address is
- * the max and expected case.
- */
- assert(((region_top <= (UINT64_MAX >> (64 - tzc.addr_width))) &&
- (region_base < region_top)));
-
- /* region_base and (region_top + 1) must be 4KB aligned */
- assert(((region_base | (region_top + 1)) & (4096 - 1)) == 0);
-
- assert(sec_attr <= TZC_REGION_S_RDWR);
-
- /*
- * Inputs look ok, start programming registers.
- * All the address registers are 32 bits wide and have a LOW and HIGH
- * component used to construct a up to a 64bit address.
- */
- tzc_write_region_base_low(tzc.base, region,
- (uint32_t)(region_base));
- tzc_write_region_base_high(tzc.base, region,
- (uint32_t)(region_base >> 32));
-
- tzc_write_region_top_low(tzc.base, region,
- (uint32_t)(region_top));
- tzc_write_region_top_high(tzc.base, region,
- (uint32_t)(region_top >> 32));
-
- /* Assign the region to a filter and set secure attributes */
- tzc_write_region_attributes(tzc.base, region,
- (sec_attr << REG_ATTR_SEC_SHIFT) | filters);
-
- /*
- * Specify which non-secure devices have permission to access this
- * region.
- */
- tzc_write_region_id_access(tzc.base, region, ns_device_access);
-}
-
-
-void tzc_set_action(tzc_action_t action)
-{
- assert(tzc.base);
-
- /*
- * - Currently no handler is provided to trap an error via interrupt
- * or exception.
- * - The interrupt action has not been tested.
- */
- tzc_write_action(tzc.base, action);
-}
-
-
-void tzc_enable_filters(void)
-{
- uint32_t state;
- uint32_t filter;
-
- assert(tzc.base);
-
- for (filter = 0; filter < tzc.num_filters; filter++) {
- state = tzc_get_gate_keeper(tzc.base, filter);
- if (state) {
- /* The TZC filter is already configured. Changing the
- * programmer's view in an active system can cause
- * unpredictable behavior therefore panic for now rather
- * than try to determine whether this is safe in this
- * instance. See:
- * http://infocenter.arm.com/help/index.jsp?\
- * topic=/com.arm.doc.ddi0504c/CJHHECBF.html */
- ERROR("TZC : Filter %d Gatekeeper already enabled.\n",
- filter);
- panic();
- }
- tzc_set_gate_keeper(tzc.base, filter, 1);
- }
-}
-
-
-void tzc_disable_filters(void)
-{
- uint32_t filter;
-
- assert(tzc.base);
-
- /*
- * We don't do the same state check as above as the Gatekeepers are
- * disabled after reset.
- */
- for (filter = 0; filter < tzc.num_filters; filter++)
- tzc_set_gate_keeper(tzc.base, filter, 0);
-}
+#if ERROR_DEPRECATED
+#error "Using deprecated TZC-400 source file"
+#else
+#include "../tzc/tzc400.c"
+#endif /* ERROR_DEPRECATED */
diff --git a/drivers/auth/auth_mod.c b/drivers/auth/auth_mod.c
index bdd3c5a..4184556 100644
--- a/drivers/auth/auth_mod.c
+++ b/drivers/auth/auth_mod.c
@@ -40,6 +40,9 @@
#include <stdint.h>
#include <string.h>
+/* ASN.1 tags */
+#define ASN1_INTEGER 0x02
+
#define return_if_error(rc) \
do { \
if (rc != 0) { \
@@ -227,6 +230,83 @@
}
/*
+ * Authenticate by Non-Volatile counter
+ *
+ * To protect the system against rollback, the platform includes a non-volatile
+ * counter whose value can only be increased. All certificates include a counter
+ * value that should not be lower than the value stored in the platform. If the
+ * value is larger, the counter in the platform must be updated to the new
+ * value.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+static int auth_nvctr(const auth_method_param_nv_ctr_t *param,
+ const auth_img_desc_t *img_desc,
+ void *img, unsigned int img_len)
+{
+ char *p;
+ void *data_ptr = NULL;
+ unsigned int data_len, len, i;
+ unsigned int cert_nv_ctr, plat_nv_ctr;
+ int rc = 0;
+
+ /* Get the counter value from current image. The AM expects the IPM
+ * to return the counter value as a DER encoded integer */
+ rc = img_parser_get_auth_param(img_desc->img_type, param->cert_nv_ctr,
+ img, img_len, &data_ptr, &data_len);
+ return_if_error(rc);
+
+ /* Parse the DER encoded integer */
+ assert(data_ptr);
+ p = (char *)data_ptr;
+ if (*p != ASN1_INTEGER) {
+ /* Invalid ASN.1 integer */
+ return 1;
+ }
+ p++;
+
+ /* NV-counters are unsigned integers up to 32-bit */
+ len = (unsigned int)(*p & 0x7f);
+ if ((*p & 0x80) || (len > 4)) {
+ return 1;
+ }
+ p++;
+
+ /* Check the number is not negative */
+ if (*p & 0x80) {
+ return 1;
+ }
+
+ /* Convert to unsigned int. This code is for a little-endian CPU */
+ cert_nv_ctr = 0;
+ for (i = 0; i < len; i++) {
+ cert_nv_ctr = (cert_nv_ctr << 8) | *p++;
+ }
+
+ /* Get the counter from the platform */
+ rc = plat_get_nv_ctr(param->plat_nv_ctr->cookie, &plat_nv_ctr);
+ return_if_error(rc);
+
+ if (cert_nv_ctr < plat_nv_ctr) {
+ /* Invalid NV-counter */
+ return 1;
+ } else if (cert_nv_ctr > plat_nv_ctr) {
+ if (img_desc->parent == NULL) {
+ /* This certificate has been signed with the ROT key.
+ * Update the platform counter value */
+ rc = plat_set_nv_ctr(param->plat_nv_ctr->cookie,
+ cert_nv_ctr);
+ return_if_error(rc);
+ } else {
+ /* Secondary certificates cannot modify the counter */
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/*
* Return the parent id in the output parameter '*parent_id'
*
* Return value:
@@ -310,6 +390,10 @@
rc = auth_signature(&auth_method->param.sig,
img_desc, img_ptr, img_len);
break;
+ case AUTH_METHOD_NV_CTR:
+ rc = auth_nvctr(&auth_method->param.nv_ctr,
+ img_desc, img_ptr, img_len);
+ break;
default:
/* Unknown authentication method */
rc = 1;
diff --git a/drivers/auth/mbedtls/mbedtls_x509_parser.c b/drivers/auth/mbedtls/mbedtls_x509_parser.c
index 52e6971..1a6a9a7 100644
--- a/drivers/auth/mbedtls/mbedtls_x509_parser.c
+++ b/drivers/auth/mbedtls/mbedtls_x509_parser.c
@@ -405,6 +405,13 @@
/*
* Extract an authentication parameter from an X509v3 certificate
+ *
+ * This function returns a pointer to the extracted data and its length.
+ * Depending on the type of parameter, a pointer to the data stored in the
+ * certificate may be returned (i.e. an octet string containing a hash). Other
+ * data may need to be copied and formatted (i.e. integers). In the later case,
+ * a buffer of the correct type needs to be statically allocated, filled and
+ * returned.
*/
static int get_auth_param(const auth_param_type_desc_t *type_desc,
void *img, unsigned int img_len,
@@ -422,6 +429,7 @@
*param_len = (unsigned int)tbs.len;
break;
case AUTH_PARAM_HASH:
+ case AUTH_PARAM_NV_CTR:
/* All these parameters are included as X509v3 extensions */
rc = get_ext(type_desc->cookie, param, param_len);
break;
diff --git a/drivers/auth/tbbr/tbbr_cot.c b/drivers/auth/tbbr/tbbr_cot.c
index 6023c78..dae35d1 100644
--- a/drivers/auth/tbbr/tbbr_cot.c
+++ b/drivers/auth/tbbr/tbbr_cot.c
@@ -56,6 +56,11 @@
/*
* Parameter type descriptors
*/
+static auth_param_type_desc_t trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_NV_CTR, TRUSTED_FW_NVCOUNTER_OID);
+static auth_param_type_desc_t non_trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_NV_CTR, NON_TRUSTED_FW_NVCOUNTER_OID);
+
static auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_PUB_KEY, 0);
static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC(
@@ -116,6 +121,13 @@
.alg = &sig_alg,
.data = &raw_data,
}
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
}
},
.authenticated_data = {
@@ -158,6 +170,13 @@
.alg = &sig_alg,
.data = &raw_data,
}
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
}
},
.authenticated_data = {
@@ -193,6 +212,13 @@
.alg = &sig_alg,
.data = &raw_data,
}
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
}
},
.authenticated_data = {
@@ -218,6 +244,13 @@
.alg = &sig_alg,
.data = &raw_data,
}
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
}
},
.authenticated_data = {
@@ -260,6 +293,13 @@
.alg = &sig_alg,
.data = &raw_data,
}
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
}
},
.authenticated_data = {
@@ -285,6 +325,13 @@
.alg = &sig_alg,
.data = &raw_data,
}
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
}
},
.authenticated_data = {
@@ -327,6 +374,13 @@
.alg = &sig_alg,
.data = &raw_data,
}
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
}
},
.authenticated_data = {
@@ -352,6 +406,13 @@
.alg = &sig_alg,
.data = &raw_data,
}
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
}
},
.authenticated_data = {
@@ -394,6 +455,13 @@
.alg = &sig_alg,
.data = &raw_data,
}
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &non_trusted_nv_ctr,
+ .plat_nv_ctr = &non_trusted_nv_ctr
+ }
}
},
.authenticated_data = {
@@ -419,6 +487,13 @@
.alg = &sig_alg,
.data = &raw_data,
}
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &non_trusted_nv_ctr,
+ .plat_nv_ctr = &non_trusted_nv_ctr
+ }
}
},
.authenticated_data = {
diff --git a/drivers/gpio/gpio.c b/drivers/gpio/gpio.c
new file mode 100644
index 0000000..c06172f
--- /dev/null
+++ b/drivers/gpio/gpio.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * GPIO -- General Purpose Input/Output
+ *
+ * Defines a simple and generic interface to access GPIO device.
+ *
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <gpio.h>
+
+/*
+ * The gpio implementation
+ */
+static const gpio_ops_t *ops;
+
+int gpio_get_direction(int gpio)
+{
+ assert(ops);
+ assert(ops->get_direction != 0);
+ assert(gpio >= 0);
+
+ return ops->get_direction(gpio);
+}
+
+void gpio_set_direction(int gpio, int direction)
+{
+ assert(ops);
+ assert(ops->set_direction != 0);
+ assert((direction == GPIO_DIR_OUT) || (direction == GPIO_DIR_IN));
+ assert(gpio >= 0);
+
+ ops->set_direction(gpio, direction);
+}
+
+int gpio_get_value(int gpio)
+{
+ assert(ops);
+ assert(ops->get_value != 0);
+ assert(gpio >= 0);
+
+ return ops->get_value(gpio);
+}
+
+void gpio_set_value(int gpio, int value)
+{
+ assert(ops);
+ assert(ops->set_value != 0);
+ assert((value == GPIO_LEVEL_LOW) || (value == GPIO_LEVEL_HIGH));
+ assert(gpio >= 0);
+
+ ops->set_value(gpio, value);
+}
+
+/*
+ * Initialize the gpio. The fields in the provided gpio
+ * ops pointer must be valid.
+ */
+void gpio_init(const gpio_ops_t *ops_ptr)
+{
+ assert(ops_ptr != 0 &&
+ (ops_ptr->get_direction != 0) &&
+ (ops_ptr->set_direction != 0) &&
+ (ops_ptr->get_value != 0) &&
+ (ops_ptr->set_value != 0));
+
+ ops = ops_ptr;
+}
diff --git a/drivers/io/io_memmap.c b/drivers/io/io_memmap.c
index ff4efa8..fe39652 100644
--- a/drivers/io/io_memmap.c
+++ b/drivers/io/io_memmap.c
@@ -45,6 +45,7 @@
int in_use;
uintptr_t base;
size_t file_pos;
+ size_t size;
} file_state_t;
static file_state_t current_file = {0};
@@ -61,6 +62,7 @@
io_entity_t *entity);
static int memmap_block_seek(io_entity_t *entity, int mode,
ssize_t offset);
+static int memmap_block_len(io_entity_t *entity, size_t *length);
static int memmap_block_read(io_entity_t *entity, uintptr_t buffer,
size_t length, size_t *length_read);
static int memmap_block_write(io_entity_t *entity, const uintptr_t buffer,
@@ -78,7 +80,7 @@
.type = device_type_memmap,
.open = memmap_block_open,
.seek = memmap_block_seek,
- .size = NULL,
+ .size = memmap_block_len,
.read = memmap_block_read,
.write = memmap_block_write,
.close = memmap_block_close,
@@ -135,6 +137,7 @@
current_file.base = block_spec->offset;
/* File cursor offset for seek and incremental reads etc. */
current_file.file_pos = 0;
+ current_file.size = block_spec->length;
entity->info = (uintptr_t)¤t_file;
result = 0;
} else {
@@ -163,6 +166,18 @@
}
+/* Return the size of a file on the memmap device */
+static int memmap_block_len(io_entity_t *entity, size_t *length)
+{
+ assert(entity != NULL);
+ assert(length != NULL);
+
+ *length = ((file_state_t *)entity->info)->size;
+
+ return 0;
+}
+
+
/* Read data from a file on the memmap device */
static int memmap_block_read(io_entity_t *entity, uintptr_t buffer,
size_t length, size_t *length_read)
diff --git a/fdts/fvp-base-gicv2-psci.dtb b/fdts/fvp-base-gicv2-psci.dtb
index 89318c1..245a6c3 100644
--- a/fdts/fvp-base-gicv2-psci.dtb
+++ b/fdts/fvp-base-gicv2-psci.dtb
Binary files differ
diff --git a/fdts/fvp-base-gicv2-psci.dts b/fdts/fvp-base-gicv2-psci.dts
index 1d26541..fc343ba 100644
--- a/fdts/fvp-base-gicv2-psci.dts
+++ b/fdts/fvp-base-gicv2-psci.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -125,6 +125,7 @@
reg = <0x0 0x0>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU1:cpu@1 {
@@ -133,6 +134,7 @@
reg = <0x0 0x1>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU2:cpu@2 {
@@ -141,6 +143,7 @@
reg = <0x0 0x2>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU3:cpu@3 {
@@ -149,6 +152,7 @@
reg = <0x0 0x3>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU4:cpu@100 {
@@ -157,6 +161,7 @@
reg = <0x0 0x100>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU5:cpu@101 {
@@ -165,6 +170,7 @@
reg = <0x0 0x101>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU6:cpu@102 {
@@ -173,6 +179,7 @@
reg = <0x0 0x102>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU7:cpu@103 {
@@ -181,6 +188,11 @@
reg = <0x0 0x103>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
+ };
+
+ L2_0: l2-cache0 {
+ compatible = "cache";
};
};
diff --git a/fdts/fvp-base-gicv2legacy-psci.dtb b/fdts/fvp-base-gicv2legacy-psci.dtb
index 0d17620..4c6f37a 100644
--- a/fdts/fvp-base-gicv2legacy-psci.dtb
+++ b/fdts/fvp-base-gicv2legacy-psci.dtb
Binary files differ
diff --git a/fdts/fvp-base-gicv2legacy-psci.dts b/fdts/fvp-base-gicv2legacy-psci.dts
index 58d3159..5a7ce2f 100644
--- a/fdts/fvp-base-gicv2legacy-psci.dts
+++ b/fdts/fvp-base-gicv2legacy-psci.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -125,6 +125,7 @@
reg = <0x0 0x0>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU1:cpu@1 {
@@ -133,6 +134,7 @@
reg = <0x0 0x1>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU2:cpu@2 {
@@ -141,6 +143,7 @@
reg = <0x0 0x2>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU3:cpu@3 {
@@ -149,6 +152,7 @@
reg = <0x0 0x3>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU4:cpu@100 {
@@ -157,6 +161,7 @@
reg = <0x0 0x100>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU5:cpu@101 {
@@ -165,6 +170,7 @@
reg = <0x0 0x101>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU6:cpu@102 {
@@ -173,6 +179,7 @@
reg = <0x0 0x102>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU7:cpu@103 {
@@ -181,6 +188,11 @@
reg = <0x0 0x103>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
+ };
+
+ L2_0: l2-cache0 {
+ compatible = "cache";
};
};
diff --git a/fdts/fvp-base-gicv3-psci.dtb b/fdts/fvp-base-gicv3-psci.dtb
index f1dc75e..0acbe17 100644
--- a/fdts/fvp-base-gicv3-psci.dtb
+++ b/fdts/fvp-base-gicv3-psci.dtb
Binary files differ
diff --git a/fdts/fvp-base-gicv3-psci.dts b/fdts/fvp-base-gicv3-psci.dts
index da090f5..5d54dbf 100644
--- a/fdts/fvp-base-gicv3-psci.dts
+++ b/fdts/fvp-base-gicv3-psci.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -123,6 +123,7 @@
reg = <0x0 0x0>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU1:cpu@1 {
@@ -131,6 +132,7 @@
reg = <0x0 0x1>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU2:cpu@2 {
@@ -139,6 +141,7 @@
reg = <0x0 0x2>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU3:cpu@3 {
@@ -147,6 +150,7 @@
reg = <0x0 0x3>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU4:cpu@100 {
@@ -155,6 +159,7 @@
reg = <0x0 0x100>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU5:cpu@101 {
@@ -163,6 +168,7 @@
reg = <0x0 0x101>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU6:cpu@102 {
@@ -171,6 +177,7 @@
reg = <0x0 0x102>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU7:cpu@103 {
@@ -179,6 +186,11 @@
reg = <0x0 0x103>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
+ };
+
+ L2_0: l2-cache0 {
+ compatible = "cache";
};
};
diff --git a/fdts/fvp-foundation-gicv2-psci.dtb b/fdts/fvp-foundation-gicv2-psci.dtb
index e457918..5acb139 100644
--- a/fdts/fvp-foundation-gicv2-psci.dtb
+++ b/fdts/fvp-foundation-gicv2-psci.dtb
Binary files differ
diff --git a/fdts/fvp-foundation-gicv2-psci.dts b/fdts/fvp-foundation-gicv2-psci.dts
index 5f93daa..d5c2dfb 100644
--- a/fdts/fvp-foundation-gicv2-psci.dts
+++ b/fdts/fvp-foundation-gicv2-psci.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -110,6 +110,7 @@
reg = <0x0 0x0>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU1:cpu@1 {
@@ -118,6 +119,7 @@
reg = <0x0 0x1>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU2:cpu@2 {
@@ -126,6 +128,7 @@
reg = <0x0 0x2>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU3:cpu@3 {
@@ -134,6 +137,11 @@
reg = <0x0 0x3>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
+ };
+
+ L2_0: l2-cache0 {
+ compatible = "cache";
};
};
diff --git a/fdts/fvp-foundation-gicv2legacy-psci.dtb b/fdts/fvp-foundation-gicv2legacy-psci.dtb
index ac7555d..efded44 100644
--- a/fdts/fvp-foundation-gicv2legacy-psci.dtb
+++ b/fdts/fvp-foundation-gicv2legacy-psci.dtb
Binary files differ
diff --git a/fdts/fvp-foundation-gicv2legacy-psci.dts b/fdts/fvp-foundation-gicv2legacy-psci.dts
index 4238b33..e6e4012 100644
--- a/fdts/fvp-foundation-gicv2legacy-psci.dts
+++ b/fdts/fvp-foundation-gicv2legacy-psci.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -110,6 +110,7 @@
reg = <0x0 0x0>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU1:cpu@1 {
@@ -118,6 +119,7 @@
reg = <0x0 0x1>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU2:cpu@2 {
@@ -126,6 +128,7 @@
reg = <0x0 0x2>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU3:cpu@3 {
@@ -134,6 +137,11 @@
reg = <0x0 0x3>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
+ };
+
+ L2_0: l2-cache0 {
+ compatible = "cache";
};
};
diff --git a/fdts/fvp-foundation-gicv3-psci.dtb b/fdts/fvp-foundation-gicv3-psci.dtb
index f3e0c5d..4402436 100644
--- a/fdts/fvp-foundation-gicv3-psci.dtb
+++ b/fdts/fvp-foundation-gicv3-psci.dtb
Binary files differ
diff --git a/fdts/fvp-foundation-gicv3-psci.dts b/fdts/fvp-foundation-gicv3-psci.dts
index daad1fb..45c699a 100644
--- a/fdts/fvp-foundation-gicv3-psci.dts
+++ b/fdts/fvp-foundation-gicv3-psci.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -108,6 +108,7 @@
reg = <0x0 0x0>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU1:cpu@1 {
@@ -116,6 +117,7 @@
reg = <0x0 0x1>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU2:cpu@2 {
@@ -124,6 +126,7 @@
reg = <0x0 0x2>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
};
CPU3:cpu@3 {
@@ -132,6 +135,11 @@
reg = <0x0 0x3>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ next-level-cache = <&L2_0>;
+ };
+
+ L2_0: l2-cache0 {
+ compatible = "cache";
};
};
diff --git a/include/common/bl_common.h b/include/common/bl_common.h
index e5e6717..f13dc31 100644
--- a/include/common/bl_common.h
+++ b/include/common/bl_common.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -53,28 +53,12 @@
#define ENTRY_POINT_INFO_ARGS_OFFSET 0x18
/* The following are used to set/get image attributes. */
-#define EXECUTABLE (0x1)
-#define NON_EXECUTABLE (0x0)
-#define PARAM_EP_EXECUTE_MASK (0x1)
-#define PARAM_EP_EXECUTE_SHIFT (0x1)
#define PARAM_EP_SECURITY_MASK (0x1)
-#define PARAM_EP_SECURITY_SHIFT (0x0)
#define GET_SECURITY_STATE(x) (x & PARAM_EP_SECURITY_MASK)
#define SET_SECURITY_STATE(x, security) \
((x) = ((x) & ~PARAM_EP_SECURITY_MASK) | (security))
-#define GET_EXEC_STATE(x) \
- (((x) >> PARAM_EP_EXECUTE_SHIFT) & PARAM_EP_EXECUTE_MASK)
-
-#define SET_EXEC_STATE(x) \
- (((x) & PARAM_EP_EXECUTE_MASK) << PARAM_EP_EXECUTE_SHIFT)
-
-#define GET_SEC_STATE(x) \
- (((x) >> PARAM_EP_SECURITY_SHIFT) & PARAM_EP_SECURITY_MASK)
-
-#define SET_SEC_STATE(x) \
- (((x) & PARAM_EP_SECURITY_MASK) << PARAM_EP_SECURITY_SHIFT)
/*
* The following are used for image state attributes.
@@ -99,11 +83,17 @@
#define EP_GET_ST(x) (x & EP_ST_MASK)
#define EP_SET_ST(x, ee) ((x) = ((x) & ~EP_ST_MASK) | (ee))
+#define EP_EXE_MASK 0x8
+#define NON_EXECUTABLE 0x0
+#define EXECUTABLE 0x8
+#define EP_GET_EXE(x) (x & EP_EXE_MASK)
+#define EP_SET_EXE(x, ee) ((x) = ((x) & ~EP_EXE_MASK) | (ee))
+
-#define PARAM_EP 0x01
-#define PARAM_IMAGE_BINARY 0x02
-#define PARAM_BL31 0x03
+#define PARAM_EP 0x01
+#define PARAM_IMAGE_BINARY 0x02
+#define PARAM_BL31 0x03
-#define VERSION_1 0x01
+#define VERSION_1 0x01
#define INVALID_IMAGE_ID (0xFFFFFFFF)
@@ -114,6 +104,14 @@
(_p)->h.attr = (uint32_t)(_attr) ; \
} while (0)
+/* Following is used for populating structure members statically. */
+#define SET_STATIC_PARAM_HEAD(_p, _type, _ver, _p_type, _attr) \
+ ._p.h.type = (uint8_t)(_type), \
+ ._p.h.version = (uint8_t)(_ver), \
+ ._p.h.size = (uint16_t)sizeof(_p_type), \
+ ._p.h.attr = (uint32_t)(_attr)
+
+
/*******************************************************************************
* Constants to indicate type of exception to the common exception handler.
******************************************************************************/
@@ -224,7 +222,6 @@
param_header_t h;
uintptr_t image_base; /* physical address of base of image */
uint32_t image_size; /* bytes read from image file */
- uint32_t copied_size; /* image size copied in blocks */
} image_info_t;
/*****************************************************************************
@@ -238,6 +235,7 @@
* Refer IMAGE_STATE_XXX defined above.
*/
unsigned int state;
+ uint32_t copied_size; /* image size copied in blocks */
image_info_t image_info;
entry_point_info_t ep_info;
} image_desc_t;
diff --git a/include/common/debug.h b/include/common/debug.h
index d198c32..41c8df0 100644
--- a/include/common/debug.h
+++ b/include/common/debug.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -31,8 +31,6 @@
#ifndef __DEBUG_H__
#define __DEBUG_H__
-#include <stdio.h>
-
/* The log output macros print output to the console. These macros produce
* compiled log output only if the LOG_LEVEL defined in the makefile (or the
* make command line) is greater or equal than the level required for that
@@ -49,6 +47,8 @@
#define LOG_LEVEL_INFO 40
#define LOG_LEVEL_VERBOSE 50
+#ifndef __ASSEMBLY__
+#include <stdio.h>
#if LOG_LEVEL >= LOG_LEVEL_NOTICE
# define NOTICE(...) tf_printf("NOTICE: " __VA_ARGS__)
@@ -86,4 +86,5 @@
void tf_printf(const char *fmt, ...) __printflike(1, 2);
+#endif /* __ASSEMBLY__ */
#endif /* __DEBUG_H__ */
diff --git a/include/common/el3_common_macros.S b/include/common/el3_common_macros.S
index 6f7136f..ba80d95 100644
--- a/include/common/el3_common_macros.S
+++ b/include/common/el3_common_macros.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -70,10 +70,17 @@
isb
/* ---------------------------------------------------------------------
- * Enable the SError interrupt now that the exception vectors have been
- * setup.
+ * Early set RES1 bits in SCR_EL3. Set EA bit as well to catch both
+ * External Aborts and SError Interrupts in EL3.
* ---------------------------------------------------------------------
*/
+ mov x0, #(SCR_RES1_BITS | SCR_EA_BIT)
+ msr scr_el3, x0
+ /* ---------------------------------------------------------------------
+ * Enable External Aborts and SError Interrupts now that the exception
+ * vectors have been setup.
+ * ---------------------------------------------------------------------
+ */
msr daifclr, #DAIF_ABT_BIT
/* ---------------------------------------------------------------------
@@ -171,9 +178,19 @@
do_cold_boot:
.endif /* _warm_boot_mailbox */
+ /* ---------------------------------------------------------------------
+ * It is a cold boot.
+ * Perform any processor specific actions upon reset e.g. cache, TLB
+ * invalidations etc.
+ * ---------------------------------------------------------------------
+ */
+ bl reset_handler
+
+ el3_arch_init_common \_exception_vectors
+
.if \_secondary_cold_boot
/* -------------------------------------------------------------
- * It is a cold boot.
+ * Check if this is a primary or secondary CPU cold boot.
* The primary CPU will set up the platform while the
* secondaries are placed in a platform-specific state until the
* primary CPU performs the necessary actions to bring them out
@@ -186,20 +203,16 @@
/* This is a cold boot on a secondary CPU */
bl plat_secondary_cold_boot_setup
/* plat_secondary_cold_boot_setup() is not supposed to return */
- secondary_panic:
- b secondary_panic
+ bl el3_panic
do_primary_cold_boot:
.endif /* _secondary_cold_boot */
/* ---------------------------------------------------------------------
- * Perform any processor specific actions upon reset e.g. cache, TLB
- * invalidations etc.
+ * Initialize memory now. Secondary CPU initialization won't get to this
+ * point.
* ---------------------------------------------------------------------
*/
- bl reset_handler
-
- el3_arch_init_common \_exception_vectors
.if \_init_memory
bl platform_mem_init
diff --git a/include/drivers/arm/gic_common.h b/include/drivers/arm/gic_common.h
index 6a322a2..dd8efdc 100644
--- a/include/drivers/arm/gic_common.h
+++ b/include/drivers/arm/gic_common.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -107,67 +107,4 @@
(GIC_HIGHEST_NS_PRIORITY << 16) | \
(GIC_HIGHEST_NS_PRIORITY << 24))
-#ifndef __ASSEMBLY__
-
-#include <mmio.h>
-#include <stdint.h>
-
-/*******************************************************************************
- * GIC Distributor interface register accessors that are common to GICv3 & GICv2
- ******************************************************************************/
-static inline unsigned int gicd_read_ctlr(uintptr_t base)
-{
- return mmio_read_32(base + GICD_CTLR);
-}
-
-static inline unsigned int gicd_read_typer(uintptr_t base)
-{
- return mmio_read_32(base + GICD_TYPER);
-}
-
-static inline unsigned int gicd_read_iidr(uintptr_t base)
-{
- return mmio_read_32(base + GICD_IIDR);
-}
-
-static inline void gicd_write_ctlr(uintptr_t base, unsigned int val)
-{
- mmio_write_32(base + GICD_CTLR, val);
-}
-
-/*******************************************************************************
- * GIC Distributor function prototypes
- ******************************************************************************/
-unsigned int gicd_read_igroupr(uintptr_t base, unsigned int id);
-unsigned int gicd_read_isenabler(uintptr_t base, unsigned int id);
-unsigned int gicd_read_icenabler(uintptr_t base, unsigned int id);
-unsigned int gicd_read_ispendr(uintptr_t base, unsigned int id);
-unsigned int gicd_read_icpendr(uintptr_t base, unsigned int id);
-unsigned int gicd_read_isactiver(uintptr_t base, unsigned int id);
-unsigned int gicd_read_icactiver(uintptr_t base, unsigned int id);
-unsigned int gicd_read_ipriorityr(uintptr_t base, unsigned int id);
-unsigned int gicd_read_icfgr(uintptr_t base, unsigned int id);
-unsigned int gicd_read_nsacr(uintptr_t base, unsigned int id);
-void gicd_write_igroupr(uintptr_t base, unsigned int id, unsigned int val);
-void gicd_write_isenabler(uintptr_t base, unsigned int id, unsigned int val);
-void gicd_write_icenabler(uintptr_t base, unsigned int id, unsigned int val);
-void gicd_write_ispendr(uintptr_t base, unsigned int id, unsigned int val);
-void gicd_write_icpendr(uintptr_t base, unsigned int id, unsigned int val);
-void gicd_write_isactiver(uintptr_t base, unsigned int id, unsigned int val);
-void gicd_write_icactiver(uintptr_t base, unsigned int id, unsigned int val);
-void gicd_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val);
-void gicd_write_icfgr(uintptr_t base, unsigned int id, unsigned int val);
-void gicd_write_nsacr(uintptr_t base, unsigned int id, unsigned int val);
-unsigned int gicd_get_igroupr(uintptr_t base, unsigned int id);
-void gicd_set_igroupr(uintptr_t base, unsigned int id);
-void gicd_clr_igroupr(uintptr_t base, unsigned int id);
-void gicd_set_isenabler(uintptr_t base, unsigned int id);
-void gicd_set_icenabler(uintptr_t base, unsigned int id);
-void gicd_set_ispendr(uintptr_t base, unsigned int id);
-void gicd_set_icpendr(uintptr_t base, unsigned int id);
-void gicd_set_isactiver(uintptr_t base, unsigned int id);
-void gicd_set_icactiver(uintptr_t base, unsigned int id);
-
-
-#endif /* __ASSEMBLY__ */
#endif /* __GIC_COMMON_H__ */
diff --git a/lib/stdlib/std.c b/include/drivers/arm/pl061_gpio.h
similarity index 78%
rename from lib/stdlib/std.c
rename to include/drivers/arm/pl061_gpio.h
index 5f6ef75..ca79630 100644
--- a/lib/stdlib/std.c
+++ b/include/drivers/arm/pl061_gpio.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -28,18 +28,12 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef __PL061_GPIO_H__
+#define __PL061_GPIO_H__
+
+#include <gpio.h>
+
+void pl061_gpio_register(uintptr_t base_addr, int gpio_dev);
+void pl061_gpio_init(void);
-/* Include the various implemented functions */
-#include "abort.c"
-#include "assert.c"
-#include "exit.c"
-#include "mem.c"
-#include "printf.c"
-#include "putchar.c"
-#include "puts.c"
-#include "sscanf.c"
-#include "strchr.c"
-#include "strcmp.c"
-#include "strlen.c"
-#include "strncmp.c"
-#include "subr_prf.c"
+#endif /* __PL061_GPIO_H__ */
diff --git a/include/drivers/arm/tzc400.h b/include/drivers/arm/tzc400.h
index f8e1664..3085688 100644
--- a/include/drivers/arm/tzc400.h
+++ b/include/drivers/arm/tzc400.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -31,178 +31,179 @@
#ifndef __TZC400_H__
#define __TZC400_H__
+#include <tzc_common.h>
-#define BUILD_CONFIG_OFF 0x000
-#define ACTION_OFF 0x004
-#define GATE_KEEPER_OFF 0x008
-#define SPECULATION_CTRL_OFF 0x00c
-#define INT_STATUS 0x010
-#define INT_CLEAR 0x014
+#define BUILD_CONFIG_OFF 0x000
+#define GATE_KEEPER_OFF 0x008
+#define SPECULATION_CTRL_OFF 0x00c
+#define INT_STATUS 0x010
+#define INT_CLEAR 0x014
-#define FAIL_ADDRESS_LOW_OFF 0x020
-#define FAIL_ADDRESS_HIGH_OFF 0x024
-#define FAIL_CONTROL_OFF 0x028
-#define FAIL_ID 0x02c
+#define FAIL_ADDRESS_LOW_OFF 0x020
+#define FAIL_ADDRESS_HIGH_OFF 0x024
+#define FAIL_CONTROL_OFF 0x028
+#define FAIL_ID 0x02c
-#define REGION_BASE_LOW_OFF 0x100
-#define REGION_BASE_HIGH_OFF 0x104
-#define REGION_TOP_LOW_OFF 0x108
-#define REGION_TOP_HIGH_OFF 0x10c
-#define REGION_ATTRIBUTES_OFF 0x110
-#define REGION_ID_ACCESS_OFF 0x114
-#define REGION_NUM_OFF(region) (0x20 * region)
+/* ID registers not common across different varieties of TZC */
+#define PID5 0xFD4
+#define PID6 0xFD8
+#define PID7 0xFDC
-/* ID Registers */
-#define PID0_OFF 0xfe0
-#define PID1_OFF 0xfe4
-#define PID2_OFF 0xfe8
-#define PID3_OFF 0xfec
-#define PID4_OFF 0xfd0
-#define PID5_OFF 0xfd4
-#define PID6_OFF 0xfd8
-#define PID7_OFF 0xfdc
-#define CID0_OFF 0xff0
-#define CID1_OFF 0xff4
-#define CID2_OFF 0xff8
-#define CID3_OFF 0xffc
-
-#define BUILD_CONFIG_NF_SHIFT 24
-#define BUILD_CONFIG_NF_MASK 0x3
-#define BUILD_CONFIG_AW_SHIFT 8
-#define BUILD_CONFIG_AW_MASK 0x3f
-#define BUILD_CONFIG_NR_SHIFT 0
-#define BUILD_CONFIG_NR_MASK 0x1f
-
-/* Not describing the case where regions 1 to 8 overlap */
-#define ACTION_RV_SHIFT 0
-#define ACTION_RV_MASK 0x3
-#define ACTION_RV_LOWOK 0x0
-#define ACTION_RV_LOWERR 0x1
-#define ACTION_RV_HIGHOK 0x2
-#define ACTION_RV_HIGHERR 0x3
+#define BUILD_CONFIG_NF_SHIFT 24
+#define BUILD_CONFIG_NF_MASK 0x3
+#define BUILD_CONFIG_AW_SHIFT 8
+#define BUILD_CONFIG_AW_MASK 0x3f
+#define BUILD_CONFIG_NR_SHIFT 0
+#define BUILD_CONFIG_NR_MASK 0x1f
/*
* Number of gate keepers is implementation defined. But we know the max for
* this device is 4. Get implementation details from BUILD_CONFIG.
*/
-#define GATE_KEEPER_OS_SHIFT 16
-#define GATE_KEEPER_OS_MASK 0xf
-#define GATE_KEEPER_OR_SHIFT 0
-#define GATE_KEEPER_OR_MASK 0xf
-#define GATE_KEEPER_FILTER_MASK 0x1
+#define GATE_KEEPER_OS_SHIFT 16
+#define GATE_KEEPER_OS_MASK 0xf
+#define GATE_KEEPER_OR_SHIFT 0
+#define GATE_KEEPER_OR_MASK 0xf
+#define GATE_KEEPER_FILTER_MASK 0x1
/* Speculation is enabled by default. */
-#define SPECULATION_CTRL_WRITE_DISABLE (1 << 1)
-#define SPECULATION_CTRL_READ_DISABLE (1 << 0)
+#define SPECULATION_CTRL_WRITE_DISABLE (1 << 1)
+#define SPECULATION_CTRL_READ_DISABLE (1 << 0)
/* Max number of filters allowed is 4. */
-#define INT_STATUS_OVERLAP_SHIFT 16
-#define INT_STATUS_OVERLAP_MASK 0xf
-#define INT_STATUS_OVERRUN_SHIFT 8
-#define INT_STATUS_OVERRUN_MASK 0xf
-#define INT_STATUS_STATUS_SHIFT 0
-#define INT_STATUS_STATUS_MASK 0xf
+#define INT_STATUS_OVERLAP_SHIFT 16
+#define INT_STATUS_OVERLAP_MASK 0xf
+#define INT_STATUS_OVERRUN_SHIFT 8
+#define INT_STATUS_OVERRUN_MASK 0xf
+#define INT_STATUS_STATUS_SHIFT 0
+#define INT_STATUS_STATUS_MASK 0xf
-#define INT_CLEAR_CLEAR_SHIFT 0
-#define INT_CLEAR_CLEAR_MASK 0xf
+#define INT_CLEAR_CLEAR_SHIFT 0
+#define INT_CLEAR_CLEAR_MASK 0xf
-#define FAIL_CONTROL_DIR_SHIFT (1 << 24)
-#define FAIL_CONTROL_DIR_READ 0x0
-#define FAIL_CONTROL_DIR_WRITE 0x1
-#define FAIL_CONTROL_NS_SHIFT (1 << 21)
-#define FAIL_CONTROL_NS_SECURE 0x0
-#define FAIL_CONTROL_NS_NONSECURE 0x1
-#define FAIL_CONTROL_PRIV_SHIFT (1 << 20)
-#define FAIL_CONTROL_PRIV_PRIV 0x0
-#define FAIL_CONTROL_PRIV_UNPRIV 0x1
+#define FAIL_CONTROL_DIR_SHIFT (1 << 24)
+#define FAIL_CONTROL_DIR_READ 0x0
+#define FAIL_CONTROL_DIR_WRITE 0x1
+#define FAIL_CONTROL_NS_SHIFT (1 << 21)
+#define FAIL_CONTROL_NS_SECURE 0x0
+#define FAIL_CONTROL_NS_NONSECURE 0x1
+#define FAIL_CONTROL_PRIV_SHIFT (1 << 20)
+#define FAIL_CONTROL_PRIV_PRIV 0x0
+#define FAIL_CONTROL_PRIV_UNPRIV 0x1
/*
* FAIL_ID_ID_MASK depends on AID_WIDTH which is platform specific.
* Platform should provide the value on initialisation.
*/
-#define FAIL_ID_VNET_SHIFT 24
-#define FAIL_ID_VNET_MASK 0xf
-#define FAIL_ID_ID_SHIFT 0
-
-/* Used along with 'tzc_region_attributes_t' below */
-#define REG_ATTR_SEC_SHIFT 30
-#define REG_ATTR_F_EN_SHIFT 0
-#define REG_ATTR_F_EN_MASK 0xf
-#define REG_ATTR_FILTER_BIT(x) ((1 << x) << REG_ATTR_F_EN_SHIFT)
-#define REG_ATTR_FILTER_BIT_ALL (REG_ATTR_F_EN_MASK << \
- REG_ATTR_F_EN_SHIFT)
+#define FAIL_ID_VNET_SHIFT 24
+#define FAIL_ID_VNET_MASK 0xf
+#define FAIL_ID_ID_SHIFT 0
-#define REGION_ID_ACCESS_NSAID_WR_EN_SHIFT 16
-#define REGION_ID_ACCESS_NSAID_RD_EN_SHIFT 0
-#define REGION_ID_ACCESS_NSAID_ID_MASK 0xf
+#define TZC_400_PERIPHERAL_ID 0x460
+/* Filter enable bits in a TZC */
+#define TZC_400_REGION_ATTR_F_EN_MASK 0xf
+#define TZC_400_REGION_ATTR_FILTER_BIT(x) ((1 << x) \
+ << TZC_REGION_ATTR_F_EN_SHIFT)
+#define TZC_400_REGION_ATTR_FILTER_BIT_ALL \
+ (TZC_400_REGION_ATTR_F_EN_MASK << \
+ TZC_REGION_ATTR_F_EN_SHIFT)
-/* Macros for setting Region ID access permissions based on NSAID */
-#define TZC_REGION_ACCESS_RD(id) \
- ((1 << (id & REGION_ID_ACCESS_NSAID_ID_MASK)) << \
- REGION_ID_ACCESS_NSAID_RD_EN_SHIFT)
-#define TZC_REGION_ACCESS_WR(id) \
- ((1 << (id & REGION_ID_ACCESS_NSAID_ID_MASK)) << \
- REGION_ID_ACCESS_NSAID_WR_EN_SHIFT)
-#define TZC_REGION_ACCESS_RDWR(id) \
- (TZC_REGION_ACCESS_RD(id) | TZC_REGION_ACCESS_WR(id))
-
-/* Consist of part_number_1 and part_number_0 */
-#define TZC400_PERIPHERAL_ID 0x0460
-
+/*
+ * Define some macros for backward compatibility with existing tzc400 clients.
+ */
+#if !ERROR_DEPRECATED
+#define REG_ATTR_FILTER_BIT(x) ((1 << x) \
+ << TZC_REGION_ATTR_F_EN_SHIFT)
+#define REG_ATTR_FILTER_BIT_ALL (TZC_400_REGION_ATTR_F_EN_MASK << \
+ TZC_REGION_ATTR_F_EN_SHIFT)
+#endif /* __ERROR_DEPRECATED__ */
+/*
+ * All TZC region configuration registers are placed one after another. It
+ * depicts size of block of registers for programming each region.
+ */
+#define TZC_400_REGION_SIZE 0x20
+#define TZC_400_ACTION_OFF 0x4
#ifndef __ASSEMBLY__
+#include <cdefs.h>
#include <stdint.h>
/*******************************************************************************
* Function & variable prototypes
******************************************************************************/
+void tzc400_init(uintptr_t base);
+void tzc400_configure_region0(tzc_region_attributes_t sec_attr,
+ unsigned int ns_device_access);
+void tzc400_configure_region(unsigned int filters,
+ int region,
+ uintptr_t region_base,
+ uintptr_t region_top,
+ tzc_region_attributes_t sec_attr,
+ unsigned int ns_device_access);
+void tzc400_set_action(tzc_action_t action);
+void tzc400_enable_filters(void);
+void tzc400_disable_filters(void);
/*
- * What type of action is expected when an access violation occurs.
- * The memory requested is zeroed. But we can also raise and event to
- * let the system know it happened.
- * We can raise an interrupt(INT) and/or cause an exception(ERR).
- * TZC_ACTION_NONE - No interrupt, no Exception
- * TZC_ACTION_ERR - No interrupt, raise exception -> sync external
- * data abort
- * TZC_ACTION_INT - Raise interrupt, no exception
- * TZC_ACTION_ERR_INT - Raise interrupt, raise exception -> sync
- * external data abort
+ * Deprecated APIs
*/
-typedef enum {
- TZC_ACTION_NONE = 0,
- TZC_ACTION_ERR = 1,
- TZC_ACTION_INT = 2,
- TZC_ACTION_ERR_INT = (TZC_ACTION_ERR | TZC_ACTION_INT)
-} tzc_action_t;
-
-/*
- * Controls secure access to a region. If not enabled secure access is not
- * allowed to region.
- */
-typedef enum {
- TZC_REGION_S_NONE = 0,
- TZC_REGION_S_RD = 1,
- TZC_REGION_S_WR = 2,
- TZC_REGION_S_RDWR = (TZC_REGION_S_RD | TZC_REGION_S_WR)
-} tzc_region_attributes_t;
+static inline void tzc_init(uintptr_t base) __deprecated;
+static inline void tzc_configure_region0(
+ tzc_region_attributes_t sec_attr,
+ unsigned int ns_device_access) __deprecated;
+static inline void tzc_configure_region(
+ unsigned int filters,
+ int region,
+ uintptr_t region_base,
+ uintptr_t region_top,
+ tzc_region_attributes_t sec_attr,
+ unsigned int ns_device_access) __deprecated;
+static inline void tzc_set_action(tzc_action_t action) __deprecated;
+static inline void tzc_enable_filters(void) __deprecated;
+static inline void tzc_disable_filters(void) __deprecated;
+static inline void tzc_init(uintptr_t base)
+{
+ tzc400_init(base);
+}
-void tzc_init(uintptr_t base);
-void tzc_configure_region0(tzc_region_attributes_t sec_attr,
- uint32_t ns_device_access);
-void tzc_configure_region(uint32_t filters,
- uint8_t region,
- uint64_t region_base,
- uint64_t region_top,
+static inline void tzc_configure_region0(
tzc_region_attributes_t sec_attr,
- uint32_t ns_device_access);
-void tzc_enable_filters(void);
-void tzc_disable_filters(void);
-void tzc_set_action(tzc_action_t action);
+ unsigned int ns_device_access)
+{
+ tzc400_configure_region0(sec_attr, ns_device_access);
+}
+
+static inline void tzc_configure_region(
+ unsigned int filters,
+ int region,
+ uintptr_t region_base,
+ uintptr_t region_top,
+ tzc_region_attributes_t sec_attr,
+ unsigned int ns_device_access)
+{
+ tzc400_configure_region(filters, region, region_base,
+ region_top, sec_attr, ns_device_access);
+}
+
+static inline void tzc_set_action(tzc_action_t action)
+{
+ tzc400_set_action(action);
+}
+
+
+static inline void tzc_enable_filters(void)
+{
+ tzc400_enable_filters();
+}
+
+static inline void tzc_disable_filters(void)
+{
+ tzc400_disable_filters();
+}
#endif /* __ASSEMBLY__ */
diff --git a/include/drivers/arm/tzc_common.h b/include/drivers/arm/tzc_common.h
new file mode 100644
index 0000000..9b73c3f
--- /dev/null
+++ b/include/drivers/arm/tzc_common.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TZC_COMMON_H__
+#define __TZC_COMMON_H__
+
+/*
+ * Offset of core registers from the start of the base of configuration
+ * registers for each region.
+ */
+
+/* ID Registers */
+#define PID0_OFF 0xfe0
+#define PID1_OFF 0xfe4
+#define PID2_OFF 0xfe8
+#define PID3_OFF 0xfec
+#define PID4_OFF 0xfd0
+#define CID0_OFF 0xff0
+#define CID1_OFF 0xff4
+#define CID2_OFF 0xff8
+#define CID3_OFF 0xffc
+
+/* Bit positions of TZC_ACTION registers */
+#define TZC_ACTION_RV_SHIFT 0
+#define TZC_ACTION_RV_MASK 0x3
+#define TZC_ACTION_RV_LOWOK 0x0
+#define TZC_ACTION_RV_LOWERR 0x1
+#define TZC_ACTION_RV_HIGHOK 0x2
+#define TZC_ACTION_RV_HIGHERR 0x3
+
+/* Used along with 'tzc_region_attributes_t' below */
+#define TZC_REGION_ATTR_S_RD_SHIFT 30
+#define TZC_REGION_ATTR_S_WR_SHIFT 31
+#define TZC_REGION_ATTR_F_EN_SHIFT 0
+#define TZC_REGION_ATTR_SEC_SHIFT 30
+#define TZC_REGION_ATTR_S_RD_MASK 0x1
+#define TZC_REGION_ATTR_S_WR_MASK 0x1
+#define TZC_REGION_ATTR_SEC_MASK 0x3
+
+#define TZC_REGION_ACCESS_WR_EN_SHIFT 16
+#define TZC_REGION_ACCESS_RD_EN_SHIFT 0
+#define TZC_REGION_ACCESS_ID_MASK 0xf
+
+/* Macros for allowing Non-Secure access to a region based on NSAID */
+#define TZC_REGION_ACCESS_RD(nsaid) \
+ ((1 << (nsaid & TZC_REGION_ACCESS_ID_MASK)) << \
+ TZC_REGION_ACCESS_RD_EN_SHIFT)
+#define TZC_REGION_ACCESS_WR(nsaid) \
+ ((1 << (nsaid & TZC_REGION_ACCESS_ID_MASK)) << \
+ TZC_REGION_ACCESS_WR_EN_SHIFT)
+#define TZC_REGION_ACCESS_RDWR(nsaid) \
+ (TZC_REGION_ACCESS_RD(nsaid) | \
+ TZC_REGION_ACCESS_WR(nsaid))
+
+#ifndef __ASSEMBLY__
+
+/* Returns offset of registers to program for a given region no */
+#define TZC_REGION_OFFSET(region_size, region_no) \
+ ((region_size) * (region_no))
+
+/*
+ * What type of action is expected when an access violation occurs.
+ * The memory requested is returned as zero. But we can also raise an event to
+ * let the system know it happened.
+ * We can raise an interrupt(INT) and/or cause an exception(ERR).
+ * TZC_ACTION_NONE - No interrupt, no Exception
+ * TZC_ACTION_ERR - No interrupt, raise exception -> sync external
+ * data abort
+ * TZC_ACTION_INT - Raise interrupt, no exception
+ * TZC_ACTION_ERR_INT - Raise interrupt, raise exception -> sync
+ * external data abort
+ */
+typedef enum {
+ TZC_ACTION_NONE = 0,
+ TZC_ACTION_ERR = 1,
+ TZC_ACTION_INT = 2,
+ TZC_ACTION_ERR_INT = (TZC_ACTION_ERR | TZC_ACTION_INT)
+} tzc_action_t;
+
+/*
+ * Controls secure access to a region. If not enabled secure access is not
+ * allowed to region.
+ */
+typedef enum {
+ TZC_REGION_S_NONE = 0,
+ TZC_REGION_S_RD = 1,
+ TZC_REGION_S_WR = 2,
+ TZC_REGION_S_RDWR = (TZC_REGION_S_RD | TZC_REGION_S_WR)
+} tzc_region_attributes_t;
+
+#endif /* __ASSEMBLY__ */
+#endif /* __TZC_COMMON_H__ */
diff --git a/include/drivers/arm/tzc_dmc500.h b/include/drivers/arm/tzc_dmc500.h
new file mode 100644
index 0000000..70f8ad2
--- /dev/null
+++ b/include/drivers/arm/tzc_dmc500.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TZC_DMC500_H__
+#define __TZC_DMC500_H__
+
+#include <tzc_common.h>
+
+#define SI_STATUS_OFFSET 0x000
+#define SI_STATE_CTRL_OFFSET 0x030
+#define SI_FLUSH_CTRL_OFFSET 0x034
+#define SI_INT_CONTROL_OFFSET 0x048
+
+#define SI_INT_STATUS_OFFSET 0x004
+#define SI_TZ_FAIL_ADDRESS_LOW_OFFSET 0x008
+#define SI_TZ_FAIL_ADDRESS_HIGH_OFFSET 0x00c
+#define SI_FAIL_CONTROL_OFFSET 0x010
+#define SI_FAIL_ID_OFFSET 0x014
+#define SI_INT_CLR_OFFSET 0x04c
+
+/*
+ * DMC-500 has 2 system interfaces each having a similar set of regs
+ * to configure each interface.
+ */
+#define SI0_BASE 0x0000
+#define SI1_BASE 0x0200
+
+/* Bit positions of SIx_SI_STATUS */
+#define SI_EMPTY_SHIFT 0x01
+#define SI_STALL_ACK_SHIFT 0x00
+#define SI_EMPTY_MASK 0x01
+#define SI_STALL_ACK_MASK 0x01
+
+/* Bit positions of SIx_SI_INT_STATUS */
+#define PMU_REQ_INT_OVERFLOW_STATUS_SHIFT 18
+#define FAILED_ACCESS_INT_OVERFLOW_STATUS_SHIFT 16
+#define PMU_REQ_INT_STATUS_SHIFT 2
+#define FAILED_ACCESS_INT_INFO_TZ_OVERLAP_STATUS_SHIFT 1
+#define FAILED_ACCESS_INT_STATUS_SHIFT 0
+#define PMU_REQ_INT_OVERFLOW_STATUS_MASK 0x1
+#define FAILED_ACCESS_INT_OVERFLOW_STATUS_MASK 0x1
+#define PMU_REQ_INT_STATUS_MASK 0x1
+#define FAILED_ACCESS_INT_INFO_TZ_OVERLAP_STATUS_MASK 0x1
+#define FAILED_ACCESS_INT_STATUS_MASK 0x1
+
+/* Bit positions of SIx_TZ_FAIL_CONTROL */
+#define DIRECTION_SHIFT 24
+#define NON_SECURE_SHIFT 21
+#define PRIVILEGED_SHIFT 20
+#define FAILED_ACCESS_INT_INFO_RANK_MASKED_SHIFT 3
+#define FAILED_ACCESS_INT_INFO_UNMAPPED_SHIFT 2
+#define FAILED_ACCESS_INT_TZ_FAIL_SHIFT 0x1
+#define FAILED_ACCESS_INT_INFO_OUTSIDE_DEFAULT_SHIFT 0
+#define DIRECTION_MASK 0x1
+#define NON_SECURE_MASK 0x1
+#define PRIVILEGED_MASK 0x1
+#define FAILED_ACCESS_INT_INFO_RANK_MASKED_MASK 0x1
+#define FAILED_ACCESS_INT_INFO_UNMAPPED_MASK 0x1
+#define FAILED_ACCESS_INT_TZ_FAIL_MASK 1
+#define FAILED_ACCESS_INT_INFO_OUTSIDE_DEFAULT_MASK 0x1
+
+/* Bit positions of SIx_FAIL_STATUS */
+#define FAIL_ID_VNET_SHIFT 24
+#define FAIL_ID_ID_SHIFT 0
+#define FAIL_ID_VNET_MASK 0xf
+#define FAIL_ID_ID_MASK 0xffffff
+
+/* Bit positions of SIx_SI_STATE_CONTRL */
+#define SI_STALL_REQ_GO 0x0
+#define SI_STALL_REQ_STALL 0x1
+
+/* Bit positions of SIx_SI_FLUSH_CONTROL */
+#define SI_FLUSH_REQ_INACTIVE 0x0
+#define SI_FLUSH_REQ_ACTIVE 0x1
+#define SI_FLUSH_REQ_MASK 0x1
+
+/* Bit positions of SIx_SI_INT_CONTROL */
+#define PMU_REQ_INT_EN_SHIFT 2
+#define OVERLAP_DETECT_INT_EN_SHIFT 1
+#define FAILED_ACCESS_INT_EN_SHIFT 0
+#define PMU_REQ_INT_EN_MASK 0x1
+#define OVERLAP_DETECT_INT_EN_MASK 0x1
+#define FAILED_ACCESS_INT_EN_MASK 0x1
+#define PMU_REQ_INT_EN 0x1
+#define OVERLAP_DETECT_INT_EN 0x1
+#define FAILED_ACCESS_INT_EN 0x1
+
+/* Bit positions of SIx_SI_INT_CLR */
+#define PMU_REQ_OFLOW_CLR_SHIFT 18
+#define FAILED_ACCESS_OFLOW_CLR_SHIFT 16
+#define PMU_REQ_INT_CLR_SHIFT 2
+#define FAILED_ACCESS_INT_CLR_SHIFT 0
+#define PMU_REQ_OFLOW_CLR_MASK 0x1
+#define FAILED_ACCESS_OFLOW_CLR_MASK 0x1
+#define PMU_REQ_INT_CLR_MASK 0x1
+#define FAILED_ACCESS_INT_CLR_MASK 0x1
+#define PMU_REQ_OFLOW_CLR 0x1
+#define FAILED_ACCESS_OFLOW_CLR 0x1
+#define PMU_REQ_INT_CLR 0x1
+#define FAILED_ACCESS_INT_CLR 0x1
+
+/* Macro to get the correct base register for a system interface */
+#define IFACE_OFFSET(sys_if) ((sys_if) ? SI1_BASE : SI0_BASE)
+
+#define MAX_SYS_IF_COUNT 2
+#define MAX_REGION_VAL 8
+
+/* DMC-500 supports striping across a max of 4 DMC instances */
+#define MAX_DMC_COUNT 4
+
+/* Consist of part_number_1 and part_number_0 */
+#define DMC500_PERIPHERAL_ID 0x0450
+
+/* Filter enable bits in a TZC */
+#define TZC_DMC500_REGION_ATTR_F_EN_MASK 0x1
+
+/* Length of registers for configuring each region */
+#define TZC_DMC500_REGION_SIZE 0x018
+
+#ifndef __ASSEMBLY__
+
+#include <stdint.h>
+
+/*
+ * Contains the base addresses of all the DMC instances.
+ */
+typedef struct tzc_dmc500_driver_data {
+ uintptr_t dmc_base[MAX_DMC_COUNT];
+ int dmc_count;
+} tzc_dmc500_driver_data_t;
+
+void tzc_dmc500_driver_init(const tzc_dmc500_driver_data_t *plat_driver_data);
+void tzc_dmc500_configure_region0(tzc_region_attributes_t sec_attr,
+ unsigned int nsaid_permissions);
+void tzc_dmc500_configure_region(int region_no,
+ uintptr_t region_base,
+ uintptr_t region_top,
+ tzc_region_attributes_t sec_attr,
+ unsigned int nsaid_permissions);
+void tzc_dmc500_set_action(tzc_action_t action);
+void tzc_dmc500_config_complete(void);
+int tzc_dmc500_verify_complete(void);
+
+
+#endif /* __ASSEMBLY__ */
+#endif /* __TZC_DMC500_H__ */
+
diff --git a/include/drivers/auth/auth_common.h b/include/drivers/auth/auth_common.h
index 52a895e..456f69f 100644
--- a/include/drivers/auth/auth_common.h
+++ b/include/drivers/auth/auth_common.h
@@ -46,6 +46,7 @@
AUTH_PARAM_SIG_ALG, /* The image signature algorithm */
AUTH_PARAM_HASH, /* A hash (including the algorithm) */
AUTH_PARAM_PUB_KEY, /* A public key */
+ AUTH_PARAM_NV_CTR, /* A non-volatile counter */
} auth_param_type_t;
/*
@@ -80,6 +81,7 @@
AUTH_METHOD_NONE = 0,
AUTH_METHOD_HASH, /* Authenticate by hash matching */
AUTH_METHOD_SIG, /* Authenticate by PK operation */
+ AUTH_METHOD_NV_CTR, /* Authenticate by Non-Volatile Counter */
AUTH_METHOD_NUM /* Number of methods */
} auth_method_type_t;
@@ -105,7 +107,8 @@
* Parameters for authentication by NV counter
*/
typedef struct auth_method_param_nv_ctr_s {
- auth_param_type_desc_t *nv_ctr; /* NV counter value */
+ auth_param_type_desc_t *cert_nv_ctr; /* NV counter in certificate */
+ auth_param_type_desc_t *plat_nv_ctr; /* NV counter in platform */
} auth_method_param_nv_ctr_t;
/*
diff --git a/lib/stdlib/std.c b/include/drivers/gpio.h
similarity index 69%
copy from lib/stdlib/std.c
copy to include/drivers/gpio.h
index 5f6ef75..a5cb5c7 100644
--- a/lib/stdlib/std.c
+++ b/include/drivers/gpio.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -28,18 +28,26 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef __GPIO_H__
+#define __GPIO_H__
+
+#define GPIO_DIR_OUT 0
+#define GPIO_DIR_IN 1
+
+#define GPIO_LEVEL_LOW 0
+#define GPIO_LEVEL_HIGH 1
+
+typedef struct gpio_ops {
+ int (*get_direction)(int gpio);
+ void (*set_direction)(int gpio, int direction);
+ int (*get_value)(int gpio);
+ void (*set_value)(int gpio, int value);
+} gpio_ops_t;
+
+int gpio_get_direction(int gpio);
+void gpio_set_direction(int gpio, int direction);
+int gpio_get_value(int gpio);
+void gpio_set_value(int gpio, int value);
+void gpio_init(const gpio_ops_t *ops);
-/* Include the various implemented functions */
-#include "abort.c"
-#include "assert.c"
-#include "exit.c"
-#include "mem.c"
-#include "printf.c"
-#include "putchar.c"
-#include "puts.c"
-#include "sscanf.c"
-#include "strchr.c"
-#include "strcmp.c"
-#include "strlen.c"
-#include "strncmp.c"
-#include "subr_prf.c"
+#endif /* __GPIO_H__ */
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index 49efafc..f9b8ed6 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -186,6 +186,11 @@
#define HCR_IMO_BIT (1 << 4)
#define HCR_FMO_BIT (1 << 3)
+/* ISR definitions */
+#define ISR_A_SHIFT 8
+#define ISR_I_SHIFT 7
+#define ISR_F_SHIFT 6
+
/* CNTHCTL_EL2 definitions */
#define EVNTEN_BIT (1 << 2)
#define EL1PCEN_BIT (1 << 1)
@@ -419,11 +424,11 @@
#define AP_RW (0x0 << 5)
#define NS (0x1 << 3)
-#define ATTR_SO_INDEX 0x2
+#define ATTR_NON_CACHEABLE_INDEX 0x2
#define ATTR_DEVICE_INDEX 0x1
#define ATTR_IWBWA_OWBWA_NTR_INDEX 0x0
#define LOWER_ATTRS(x) (((x) & 0xfff) << 2)
-#define ATTR_SO (0x0)
+#define ATTR_NON_CACHEABLE (0x44)
#define ATTR_DEVICE (0x4)
#define ATTR_IWBWA_OWBWA_NTR (0xff)
#define MAIR_ATTR_SET(attr, index) (attr << (index << 3))
diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h
index 067b830..f9f0715 100644
--- a/include/lib/aarch64/arch_helpers.h
+++ b/include/lib/aarch64/arch_helpers.h
@@ -113,15 +113,6 @@
}
/*******************************************************************************
- * Aarch64 translation tables manipulation helper prototypes
-******************************************************************************/
-uint64_t create_table_desc(uint64_t *next_table_ptr);
-uint64_t create_block_desc(uint64_t desc, uint64_t addr, uint32_t level);
-uint64_t create_device_block(uint64_t output_addr, uint32_t level, uint32_t ns);
-uint64_t create_romem_block(uint64_t output_addr, uint32_t level, uint32_t ns);
-uint64_t create_rwmem_block(uint64_t output_addr, uint32_t level, uint32_t ns);
-
-/*******************************************************************************
* TLB maintenance accessor prototypes
******************************************************************************/
DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1)
@@ -168,15 +159,6 @@
DEFINE_SYSREG_WRITE_CONST_FUNC(daifset)
DEFINE_SYSREG_WRITE_CONST_FUNC(daifclr)
-#define enable_irq() write_daifclr(DAIF_IRQ_BIT)
-#define enable_fiq() write_daifclr(DAIF_FIQ_BIT)
-#define enable_serror() write_daifclr(DAIF_ABT_BIT)
-#define enable_debug_exceptions() write_daifclr(DAIF_DBG_BIT)
-#define disable_irq() write_daifset(DAIF_IRQ_BIT)
-#define disable_fiq() write_daifset(DAIF_FIQ_BIT)
-#define disable_serror() write_daifset(DAIF_ABT_BIT)
-#define disable_debug_exceptions() write_daifset(DAIF_DBG_BIT)
-
DEFINE_SYSREG_READ_FUNC(par_el1)
DEFINE_SYSREG_READ_FUNC(id_pfr1_el1)
DEFINE_SYSREG_READ_FUNC(id_aa64pfr0_el1)
@@ -194,6 +176,8 @@
DEFINE_SYSOP_FUNC(sev)
DEFINE_SYSOP_TYPE_FUNC(dsb, sy)
DEFINE_SYSOP_TYPE_FUNC(dmb, sy)
+DEFINE_SYSOP_TYPE_FUNC(dmb, st)
+DEFINE_SYSOP_TYPE_FUNC(dmb, ld)
DEFINE_SYSOP_TYPE_FUNC(dsb, ish)
DEFINE_SYSOP_TYPE_FUNC(dmb, ish)
DEFINE_SYSOP_FUNC(isb)
diff --git a/include/lib/aarch64/xlat_tables.h b/include/lib/aarch64/xlat_tables.h
index 0b5dbdf..d21100e 100644
--- a/include/lib/aarch64/xlat_tables.h
+++ b/include/lib/aarch64/xlat_tables.h
@@ -52,21 +52,41 @@
#define MAP_REGION(pa, va, sz, attr) {(pa), (va), (sz), (attr)}
/*
- * Flags for building up memory mapping attributes.
- * These are organised so that a clear bit gives a more restrictive mapping
- * that a set bit, that way a bitwise-and two sets of attributes will never give
- * an attribute which has greater access rights that any of the original
- * attributes.
+ * Shifts and masks to access fields of an mmap_attr_t
+ */
+#define MT_TYPE_MASK 0x7
+#define MT_TYPE(_attr) ((_attr) & MT_TYPE_MASK)
+/* Access permissions (RO/RW) */
+#define MT_PERM_SHIFT 3
+/* Security state (SECURE/NS) */
+#define MT_SEC_SHIFT 4
+
+/*
+ * Memory mapping attributes
*/
typedef enum {
- MT_DEVICE = 0 << 0,
- MT_MEMORY = 1 << 0,
+ /*
+ * Memory types supported.
+ * These are organised so that, going down the list, the memory types
+ * are getting weaker; conversely going up the list the memory types are
+ * getting stronger.
+ */
+ MT_DEVICE,
+ MT_NON_CACHEABLE,
+ MT_MEMORY,
+ /* Values up to 7 are reserved to add new memory types in the future */
- MT_RO = 0 << 1,
- MT_RW = 1 << 1,
+ /*
+ * The following values are organised so that a clear bit gives a more
+ * restrictive mapping than a set bit, that way a bitwise-and of two
+ * sets of attributes will never give an attribute which has greater
+ * access rights than any of the original attributes.
+ */
+ MT_RO = 0 << MT_PERM_SHIFT,
+ MT_RW = 1 << MT_PERM_SHIFT,
- MT_SECURE = 0 << 2,
- MT_NS = 1 << 2
+ MT_SECURE = 0 << MT_SEC_SHIFT,
+ MT_NS = 1 << MT_SEC_SHIFT,
} mmap_attr_t;
/*
diff --git a/include/plat/arm/board/common/board_arm_def.h b/include/plat/arm/board/common/board_arm_def.h
index db2a8df..d70fbb4 100644
--- a/include/plat/arm/board/common/board_arm_def.h
+++ b/include/plat/arm/board/common/board_arm_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -60,80 +60,28 @@
#endif
/*
- * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the
- * plat_arm_mmap array defined for each BL stage.
+ * The constants below are not optimised for memory usage. Platforms that wish
+ * to optimise these constants should set `ARM_BOARD_OPTIMISE_MMAP` to 1 and
+ * provide there own values.
*/
-#if IMAGE_BL1
-# if PLAT_fvp
-# if TRUSTED_BOARD_BOOT
-# define PLAT_ARM_MMAP_ENTRIES 8
-# else
-# define PLAT_ARM_MMAP_ENTRIES 7
-# endif /* TRUSTED_BOARD_BOOT */
-# else
-# if TRUSTED_BOARD_BOOT
-# define PLAT_ARM_MMAP_ENTRIES 7
-# else
-# define PLAT_ARM_MMAP_ENTRIES 6
-# endif /* TRUSTED_BOARD_BOOT */
-# endif /* PLAT_ */
-#endif
-#if IMAGE_BL2
-# if PLAT_fvp
-# define PLAT_ARM_MMAP_ENTRIES 9
-# else
-# define PLAT_ARM_MMAP_ENTRIES 8
-# endif
-#endif
-#if IMAGE_BL2U
-# if PLAT_fvp
-# define PLAT_ARM_MMAP_ENTRIES 3
-# else
-# define PLAT_ARM_MMAP_ENTRIES 4
-#endif
-#endif
-#if IMAGE_BL31
-#define PLAT_ARM_MMAP_ENTRIES 5
-#endif
-#if IMAGE_BL32
-#define PLAT_ARM_MMAP_ENTRIES 4
-#endif
-
+#if !ARM_BOARD_OPTIMISE_MMAP
/*
- * Platform specific page table and MMU setup constants
+ * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the
+ * plat_arm_mmap array defined for each BL stage.
+ *
+ * Provide relatively optimised values for the runtime images (BL31 and BL32).
+ * Optimisation is less important for the other, transient boot images so a
+ * common, maximum value is used across these images.
*/
-#if IMAGE_BL1
-# if TRUSTED_BOARD_BOOT
-# define MAX_XLAT_TABLES 4
-# else
-# if PLAT_juno
-# define MAX_XLAT_TABLES 2
-# else
-# define MAX_XLAT_TABLES 3
-# endif /* PLAT_ */
-# endif /* TRUSTED_BOARD_BOOT */
-#elif IMAGE_BL2
-# if PLAT_juno
-# define MAX_XLAT_TABLES 3
-# else
-# define MAX_XLAT_TABLES 4
-# endif /* PLAT_ */
-#elif IMAGE_BL2U
-# if PLAT_juno
-# define MAX_XLAT_TABLES 3
-# else
-# define MAX_XLAT_TABLES 4
-# endif /* PLAT_ */
-#elif IMAGE_BL31
-# define MAX_XLAT_TABLES 2
-#elif IMAGE_BL32
-# if ARM_TSP_RAM_LOCATION_ID == ARM_DRAM_ID
-# define MAX_XLAT_TABLES 3
-# else
-# define MAX_XLAT_TABLES 2
-# endif
+#if IMAGE_BL31 || IMAGE_BL32
+# define PLAT_ARM_MMAP_ENTRIES 6
+# define MAX_XLAT_TABLES 4
+#else
+# define PLAT_ARM_MMAP_ENTRIES 10
+# define MAX_XLAT_TABLES 5
#endif
+#endif /* ARM_BOARD_OPTIMISE_MMAP */
#define MAX_IO_DEVICES 3
#define MAX_IO_HANDLES 4
@@ -143,5 +91,8 @@
#define PLAT_ARM_FIP_BASE V2M_FLASH0_BASE
#define PLAT_ARM_FIP_MAX_SIZE V2M_FLASH0_SIZE
+#define PLAT_ARM_NVM_BASE V2M_FLASH0_BASE
+#define PLAT_ARM_NVM_SIZE V2M_FLASH0_SIZE
+
#endif /* __BOARD_ARM_DEF_H__ */
diff --git a/include/plat/arm/common/aarch64/arm_macros.S b/include/plat/arm/common/aarch64/arm_macros.S
index 384bb51..3b19a7d 100644
--- a/include/plat/arm/common/aarch64/arm_macros.S
+++ b/include/plat/arm/common/aarch64/arm_macros.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -30,7 +30,6 @@
#ifndef __ARM_MACROS_S__
#define __ARM_MACROS_S__
-#include <cci.h>
#include <gic_common.h>
#include <gicv2.h>
#include <gicv3.h>
@@ -117,31 +116,4 @@
exit_print_gic_regs:
.endm
-
-.section .rodata.cci_reg_name, "aS"
-cci_iface_regs:
- .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , ""
-
- /* ------------------------------------------------
- * The below required platform porting macro prints
- * out relevant interconnect registers whenever an
- * unhandled exception is taken in BL31.
- * Clobbers: x0 - x9, sp
- * ------------------------------------------------
- */
- .macro plat_print_interconnect_regs
- adr x6, cci_iface_regs
- /* Store in x7 the base address of the first interface */
- mov_imm x7, (PLAT_ARM_CCI_BASE + SLAVE_IFACE_OFFSET( \
- PLAT_ARM_CCI_CLUSTER0_SL_IFACE_IX))
- ldr w8, [x7, #SNOOP_CTRL_REG]
- /* Store in x7 the base address of the second interface */
- mov_imm x7, (PLAT_ARM_CCI_BASE + SLAVE_IFACE_OFFSET( \
- PLAT_ARM_CCI_CLUSTER1_SL_IFACE_IX))
- ldr w9, [x7, #SNOOP_CTRL_REG]
- /* Store to the crash buf and print to console */
- bl str_in_crash_buf_print
- .endm
-
-
#endif /* __ARM_MACROS_S__ */
diff --git a/include/plat/arm/common/aarch64/cci_macros.S b/include/plat/arm/common/aarch64/cci_macros.S
new file mode 100644
index 0000000..40f9d7e
--- /dev/null
+++ b/include/plat/arm/common/aarch64/cci_macros.S
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __CCI_MACROS_S__
+#define __CCI_MACROS_S__
+
+#include <cci.h>
+#include <platform_def.h>
+
+.section .rodata.cci_reg_name, "aS"
+cci_iface_regs:
+ .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , ""
+
+ /* ------------------------------------------------
+ * The below required platform porting macro prints
+ * out relevant interconnect registers whenever an
+ * unhandled exception is taken in BL31.
+ * Clobbers: x0 - x9, sp
+ * ------------------------------------------------
+ */
+ .macro plat_print_interconnect_regs
+ adr x6, cci_iface_regs
+ /* Store in x7 the base address of the first interface */
+ mov_imm x7, (PLAT_ARM_CCI_BASE + SLAVE_IFACE_OFFSET( \
+ PLAT_ARM_CCI_CLUSTER0_SL_IFACE_IX))
+ ldr w8, [x7, #SNOOP_CTRL_REG]
+ /* Store in x7 the base address of the second interface */
+ mov_imm x7, (PLAT_ARM_CCI_BASE + SLAVE_IFACE_OFFSET( \
+ PLAT_ARM_CCI_CLUSTER1_SL_IFACE_IX))
+ ldr w9, [x7, #SNOOP_CTRL_REG]
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+ .endm
+
+#endif /* __CCI_MACROS_S__ */
diff --git a/include/plat/arm/common/arm_config.h b/include/plat/arm/common/arm_config.h
index 24c1f0a..0380849 100644
--- a/include/plat/arm/common/arm_config.h
+++ b/include/plat/arm/common/arm_config.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -35,8 +35,8 @@
enum arm_config_flags {
/* Whether Base memory map is in use */
ARM_CONFIG_BASE_MMAP = 0x1,
- /* Whether CCI should be enabled */
- ARM_CONFIG_HAS_CCI = 0x2,
+ /* Whether interconnect should be enabled */
+ ARM_CONFIG_HAS_INTERCONNECT = 0x2,
/* Whether TZC should be configured */
ARM_CONFIG_HAS_TZC = 0x4
};
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index b2db616..18fe718 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -44,7 +44,6 @@
/* Special value used to verify platform parameters from BL2 to BL31 */
#define ARM_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL
-#define ARM_CLUSTER_COUNT 2
#define ARM_SYSTEM_COUNT 1
#define ARM_CACHE_WRITEBACK_SHIFT 6
@@ -151,14 +150,10 @@
#define ARM_G0_IRQS ARM_IRQ_SEC_SGI_0, \
ARM_IRQ_SEC_SGI_6
-#define ARM_SHARED_RAM_ATTR ((PLAT_ARM_SHARED_RAM_CACHED ? \
- MT_MEMORY : MT_DEVICE) \
- | MT_RW | MT_SECURE)
-
#define ARM_MAP_SHARED_RAM MAP_REGION_FLAT( \
ARM_SHARED_RAM_BASE, \
ARM_SHARED_RAM_SIZE, \
- ARM_SHARED_RAM_ATTR)
+ MT_DEVICE | MT_RW | MT_SECURE)
#define ARM_MAP_NS_DRAM1 MAP_REGION_FLAT( \
ARM_NS_DRAM1_BASE, \
@@ -170,6 +165,12 @@
TSP_SEC_MEM_SIZE, \
MT_MEMORY | MT_RW | MT_SECURE)
+#if ARM_BL31_IN_DRAM
+#define ARM_MAP_BL31_SEC_DRAM MAP_REGION_FLAT( \
+ BL31_BASE, \
+ PLAT_ARM_MAX_BL31_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+#endif
/*
* The number of regions like RO(code), coherent and data required by
@@ -218,10 +219,6 @@
*/
#define PLAT_MAX_OFF_STATE ARM_LOCAL_STATE_OFF
-
-#define PLATFORM_CORE_COUNT (PLAT_ARM_CLUSTER0_CORE_COUNT + \
- PLAT_ARM_CLUSTER1_CORE_COUNT)
-
/*
* 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
@@ -239,46 +236,51 @@
#define BL1_RO_LIMIT (PLAT_ARM_TRUSTED_ROM_BASE \
+ PLAT_ARM_TRUSTED_ROM_SIZE)
/*
- * Put BL1 RW at the top of the Trusted SRAM. BL1_RW_BASE is calculated using
- * the current BL1 RW debug size plus a little space for growth.
+ * Put BL1 RW at the top of the Trusted SRAM.
*/
-#if TRUSTED_BOARD_BOOT
#define BL1_RW_BASE (ARM_BL_RAM_BASE + \
ARM_BL_RAM_SIZE - \
- 0x9000)
-#else
-#define BL1_RW_BASE (ARM_BL_RAM_BASE + \
- ARM_BL_RAM_SIZE - \
- 0x6000)
-#endif
+ PLAT_ARM_MAX_BL1_RW_SIZE)
#define BL1_RW_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
/*******************************************************************************
* BL2 specific defines.
******************************************************************************/
+#if ARM_BL31_IN_DRAM
/*
- * Put BL2 just below BL31. BL2_BASE is calculated using the current BL2 debug
- * size plus a little space for growth.
+ * BL31 is loaded in the DRAM.
+ * Put BL2 just below BL1.
*/
-#if TRUSTED_BOARD_BOOT
-#define BL2_BASE (BL31_BASE - 0x1D000)
+#define BL2_BASE (BL1_RW_BASE - PLAT_ARM_MAX_BL2_SIZE)
+#define BL2_LIMIT BL1_RW_BASE
#else
-#define BL2_BASE (BL31_BASE - 0xC000)
-#endif
+/*
+ * Put BL2 just below BL31.
+ */
+#define BL2_BASE (BL31_BASE - PLAT_ARM_MAX_BL2_SIZE)
#define BL2_LIMIT BL31_BASE
+#endif
/*******************************************************************************
* BL31 specific defines.
******************************************************************************/
+#if ARM_BL31_IN_DRAM
+/*
+ * Put BL31 at the bottom of TZC secured DRAM
+ */
+#define BL31_BASE ARM_AP_TZC_DRAM1_BASE
+#define BL31_LIMIT (ARM_AP_TZC_DRAM1_BASE + \
+ PLAT_ARM_MAX_BL31_SIZE)
+#else
/*
- * Put BL31 at the top of the Trusted SRAM. BL31_BASE is calculated using the
- * current BL31 debug size plus a little space for growth.
+ * Put BL31 at the top of the Trusted SRAM.
*/
#define BL31_BASE (ARM_BL_RAM_BASE + \
ARM_BL_RAM_SIZE - \
- 0x1D000)
+ PLAT_ARM_MAX_BL31_SIZE)
#define BL31_PROGBITS_LIMIT BL1_RW_BASE
#define BL31_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
+#endif
/*******************************************************************************
* BL32 specific defines.
@@ -288,7 +290,16 @@
* Trusted DRAM (if available) or the DRAM region secured by the TrustZone
* controller.
*/
-#if ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_SRAM_ID
+#if ARM_BL31_IN_DRAM
+# define TSP_SEC_MEM_BASE (ARM_AP_TZC_DRAM1_BASE + \
+ PLAT_ARM_MAX_BL31_SIZE)
+# define TSP_SEC_MEM_SIZE (ARM_AP_TZC_DRAM1_SIZE - \
+ PLAT_ARM_MAX_BL31_SIZE)
+# define BL32_BASE (ARM_AP_TZC_DRAM1_BASE + \
+ PLAT_ARM_MAX_BL31_SIZE)
+# define BL32_LIMIT (ARM_AP_TZC_DRAM1_BASE + \
+ ARM_AP_TZC_DRAM1_SIZE)
+#elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_SRAM_ID
# define TSP_SEC_MEM_BASE ARM_BL_RAM_BASE
# define TSP_SEC_MEM_SIZE ARM_BL_RAM_SIZE
# define TSP_PROGBITS_LIMIT BL2_BASE
@@ -314,9 +325,13 @@
* FWU Images: NS_BL1U, BL2U & NS_BL2U defines.
******************************************************************************/
#define BL2U_BASE BL2_BASE
+#if ARM_BL31_IN_DRAM
+#define BL2U_LIMIT BL1_RW_BASE
+#else
#define BL2U_LIMIT BL31_BASE
+#endif
#define NS_BL2U_BASE ARM_NS_DRAM1_BASE
-#define NS_BL1U_BASE (V2M_FLASH0_BASE + 0x03EB8000)
+#define NS_BL1U_BASE (PLAT_ARM_NVM_BASE + 0x03EB8000)
/*
* ID of the secure physical generic timer interrupt used by the TSP.
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index 3b6a04b..2fe0a69 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -37,11 +37,6 @@
#include <stdint.h>
#include <xlat_tables.h>
-/*
- * Extern declarations common to ARM standard platforms
- */
-extern const mmap_region_t plat_arm_mmap[];
-
#define ARM_CASSERT_MMAP \
CASSERT((ARRAY_SIZE(plat_arm_mmap) + ARM_BL_REGIONS) \
<= MAX_MMAP_REGIONS, \
@@ -131,14 +126,13 @@
#endif /* __ARM_RECOM_STATE_ID_ENC__ */
-/* CCI utility functions */
-void arm_cci_init(void);
-
/* IO storage utility functions */
void arm_io_setup(void);
/* Security utility functions */
-void arm_tzc_setup(void);
+void arm_tzc400_setup(void);
+struct tzc_dmc500_driver_data;
+void arm_tzc_dmc500_setup(struct tzc_dmc500_driver_data *plat_driver_data);
/* Systimer utility function */
void arm_configure_sys_timer(void);
@@ -187,6 +181,7 @@
/*
* Mandatory functions required in ARM standard platforms
*/
+unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr);
void plat_arm_gic_driver_init(void);
void plat_arm_gic_init(void);
void plat_arm_gic_cpuif_enable(void);
@@ -194,6 +189,9 @@
void plat_arm_gic_pcpu_init(void);
void plat_arm_security_setup(void);
void plat_arm_pwrc_setup(void);
+void plat_arm_interconnect_init(void);
+void plat_arm_interconnect_enter_coherency(void);
+void plat_arm_interconnect_exit_coherency(void);
/*
* Optional functions required in ARM standard platforms
@@ -204,6 +202,6 @@
uintptr_t *dev_handle,
uintptr_t *image_spec);
unsigned int plat_arm_calc_core_pos(u_register_t mpidr);
-
+const mmap_region_t *plat_arm_get_mmap(void);
#endif /* __PLAT_ARM_H__ */
diff --git a/include/plat/arm/css/common/css_def.h b/include/plat/arm/css/common/css_def.h
index c900278..636daf2 100644
--- a/include/plat/arm/css/common/css_def.h
+++ b/include/plat/arm/css/common/css_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -37,15 +37,12 @@
/*************************************************************************
* Definitions common to all ARM Compute SubSystems (CSS)
*************************************************************************/
-#define MHU_PAYLOAD_CACHED 0
-
#define NSROM_BASE 0x1f000000
#define NSROM_SIZE 0x00001000
/* Following covers CSS Peripherals excluding NSROM and NSRAM */
#define CSS_DEVICE_BASE 0x20000000
#define CSS_DEVICE_SIZE 0x0e000000
-#define MHU_BASE 0x2b1f0000
#define NSRAM_BASE 0x2e000000
#define NSRAM_SIZE 0x00008000
@@ -78,31 +75,47 @@
* SCP <=> AP boot configuration
*
* The SCP/AP boot configuration is a 32-bit word located at a known offset from
- * the start of the Trusted SRAM. Part of this configuration is which CPU is the
- * primary, according to the shift and mask definitions below.
+ * the start of the Trusted SRAM.
*
* Note that the value stored at this address is only valid at boot time, before
* the SCP_BL2 image is transferred to SCP.
*/
-#define SCP_BOOT_CFG_ADDR (ARM_TRUSTED_SRAM_BASE + 0x80)
-#define PRIMARY_CPU_SHIFT 8
-#define PRIMARY_CPU_BIT_WIDTH 4
-
-/*
- * Base address of the first memory region used for communication between AP
- * and SCP. Used by the BOM and SCPI protocols.
- *
- * 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.
- */
-#define SCP_COM_SHARED_MEM_BASE (ARM_TRUSTED_SRAM_BASE + 0x80)
+#define SCP_BOOT_CFG_ADDR PLAT_CSS_SCP_COM_SHARED_MEM_BASE
#define CSS_MAP_DEVICE MAP_REGION_FLAT( \
CSS_DEVICE_BASE, \
CSS_DEVICE_SIZE, \
MT_DEVICE | MT_RW | MT_SECURE)
+/* Platform ID address */
+#define SSC_VERSION_OFFSET 0x040
+
+#define SSC_VERSION_CONFIG_SHIFT 28
+#define SSC_VERSION_MAJOR_REV_SHIFT 24
+#define SSC_VERSION_MINOR_REV_SHIFT 20
+#define SSC_VERSION_DESIGNER_ID_SHIFT 12
+#define SSC_VERSION_PART_NUM_SHIFT 0x0
+#define SSC_VERSION_CONFIG_MASK 0xf
+#define SSC_VERSION_MAJOR_REV_MASK 0xf
+#define SSC_VERSION_MINOR_REV_MASK 0xf
+#define SSC_VERSION_DESIGNER_ID_MASK 0xff
+#define SSC_VERSION_PART_NUM_MASK 0xfff
+
+#ifndef __ASSEMBLY__
+
+/* SSC_VERSION related accessors */
+
+/* Returns the part number of the platform */
+#define GET_SSC_VERSION_PART_NUM(val) \
+ (((val) >> SSC_VERSION_PART_NUM_SHIFT) & \
+ SSC_VERSION_PART_NUM_MASK)
+
+/* Returns the configuration number of the platform */
+#define GET_SSC_VERSION_CONFIG(val) \
+ (((val) >> SSC_VERSION_CONFIG_SHIFT) & \
+ SSC_VERSION_CONFIG_MASK)
+
+#endif /* __ASSEMBLY__ */
/*************************************************************************
* Required platform porting definitions common to all
@@ -110,6 +123,13 @@
************************************************************************/
/*
+ * The loading of SCP images(SCP_BL2 or SCP_BL2U) is done if there
+ * respective base addresses are defined (i.e SCP_BL2_BASE, SCP_BL2U_BASE).
+ * Hence, `CSS_LOAD_SCP_IMAGES` needs to be set to 1 if BL2 needs to load
+ * an SCP_BL2/SCP_BL2U image.
+ */
+#if CSS_LOAD_SCP_IMAGES
+/*
* Load address of SCP_BL2 in CSS platform ports
* SCP_BL2 is loaded to the same place as BL31. Once SCP_BL2 is transferred to the
* SCP, it is discarded and BL31 is loaded over the top.
@@ -117,18 +137,13 @@
#define SCP_BL2_BASE BL31_BASE
#define SCP_BL2U_BASE BL31_BASE
-
-#define PLAT_ARM_SHARED_RAM_CACHED MHU_PAYLOAD_CACHED
+#endif /* CSS_LOAD_SCP_IMAGES */
/* Load address of Non-Secure Image for CSS platform ports */
#define PLAT_ARM_NS_IMAGE_OFFSET 0xE0000000
/* TZC related constants */
-#define PLAT_ARM_TZC_FILTERS REG_ATTR_FILTER_BIT_ALL
-#define PLAT_ARM_TZC_BASE 0x2a4a0000
-
-/* System timer related constants */
-#define PLAT_ARM_NSTIMER_FRAME_ID 1
+#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
diff --git a/include/plat/arm/soc/common/soc_css_def.h b/include/plat/arm/soc/common/soc_css_def.h
index 428df4d..f1396a6 100644
--- a/include/plat/arm/soc/common/soc_css_def.h
+++ b/include/plat/arm/soc/common/soc_css_def.h
@@ -65,6 +65,13 @@
*/
#define SOC_CSS_NIC400_APB4_BRIDGE 4
+/* Non-volatile counters */
+#define SOC_TRUSTED_NVCTR_BASE 0x7fe70000
+#define TFW_NVCTR_BASE (SOC_TRUSTED_NVCTR_BASE + 0x0000)
+#define TFW_NVCTR_SIZE 4
+#define NTFW_CTR_BASE (SOC_TRUSTED_NVCTR_BASE + 0x0004)
+#define NTFW_CTR_SIZE 4
+
/* Keys */
#define SOC_KEYS_BASE 0x7fe80000
#define TZ_PUB_KEY_HASH_BASE (SOC_KEYS_BASE + 0x0000)
diff --git a/include/plat/common/common_def.h b/include/plat/common/common_def.h
index 916720c..9fac9fa 100644
--- a/include/plat/common/common_def.h
+++ b/include/plat/common/common_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -72,11 +72,12 @@
#define BL2_IMAGE_DESC { \
.image_id = BL2_IMAGE_ID, \
- .image_info.h.version = VERSION_1, \
- .image_info.h.attr = SET_EXEC_STATE(EXECUTABLE),\
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, \
+ VERSION_1, image_info_t, 0), \
.image_info.image_base = BL2_BASE, \
- .ep_info.h.attr = SET_SEC_STATE(SECURE), \
- .ep_info.pc = BL2_BASE \
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, \
+ VERSION_1, entry_point_info_t, SECURE | EXECUTABLE),\
+ .ep_info.pc = BL2_BASE, \
}
#endif /* __COMMON_DEF_H__ */
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index f37a80f..5857501 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -60,7 +60,7 @@
int plat_get_image_source(unsigned int image_id,
uintptr_t *dev_handle,
uintptr_t *image_spec);
-unsigned long plat_get_ns_image_entrypoint(void);
+uintptr_t plat_get_ns_image_entrypoint(void);
unsigned int plat_my_core_pos(void);
int plat_core_pos_by_mpidr(u_register_t mpidr);
@@ -83,6 +83,7 @@
int plat_crash_console_init(void);
int plat_crash_console_putc(int c);
void plat_error_handler(int err) __dead2;
+void plat_panic_handler(void) __dead2;
/*******************************************************************************
* Mandatory BL1 functions
@@ -248,6 +249,8 @@
******************************************************************************/
int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
unsigned int *flags);
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr);
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr);
#if ENABLE_PLAT_COMPAT
/*
diff --git a/lib/aarch64/xlat_helpers.c b/lib/aarch64/xlat_helpers.c
deleted file mode 100644
index d401ffc..0000000
--- a/lib/aarch64/xlat_helpers.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without specific
- * prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <arch.h>
-#include <assert.h>
-
-/*******************************************************************************
- * Helper to create a level 1/2 table descriptor which points to a level 2/3
- * table.
- ******************************************************************************/
-unsigned long create_table_desc(unsigned long *next_table_ptr)
-{
- unsigned long desc = (unsigned long) next_table_ptr;
-
- /* Clear the last 12 bits */
- desc >>= FOUR_KB_SHIFT;
- desc <<= FOUR_KB_SHIFT;
-
- desc |= TABLE_DESC;
-
- return desc;
-}
-
-/*******************************************************************************
- * Helper to create a level 1/2/3 block descriptor which maps the va to addr
- ******************************************************************************/
-unsigned long create_block_desc(unsigned long desc,
- unsigned long addr,
- unsigned int level)
-{
- switch (level) {
- case LEVEL1:
- desc |= (addr << FIRST_LEVEL_DESC_N) | BLOCK_DESC;
- break;
- case LEVEL2:
- desc |= (addr << SECOND_LEVEL_DESC_N) | BLOCK_DESC;
- break;
- case LEVEL3:
- desc |= (addr << THIRD_LEVEL_DESC_N) | TABLE_DESC;
- break;
- default:
- assert(0);
- }
-
- return desc;
-}
-
-/*******************************************************************************
- * Helper to create a level 1/2/3 block descriptor which maps the va to output_
- * addr with Device nGnRE attributes.
- ******************************************************************************/
-unsigned long create_device_block(unsigned long output_addr,
- unsigned int level,
- unsigned int ns)
-{
- unsigned long upper_attrs, lower_attrs, desc;
-
- lower_attrs = LOWER_ATTRS(ACCESS_FLAG | OSH | AP_RW);
- lower_attrs |= LOWER_ATTRS(ns | ATTR_DEVICE_INDEX);
- upper_attrs = UPPER_ATTRS(XN);
- desc = upper_attrs | lower_attrs;
-
- return create_block_desc(desc, output_addr, level);
-}
-
-/*******************************************************************************
- * Helper to create a level 1/2/3 block descriptor which maps the va to output_
- * addr with inner-shareable normal wbwa read-only memory attributes.
- ******************************************************************************/
-unsigned long create_romem_block(unsigned long output_addr,
- unsigned int level,
- unsigned int ns)
-{
- unsigned long upper_attrs, lower_attrs, desc;
-
- lower_attrs = LOWER_ATTRS(ACCESS_FLAG | ISH | AP_RO);
- lower_attrs |= LOWER_ATTRS(ns | ATTR_IWBWA_OWBWA_NTR_INDEX);
- upper_attrs = UPPER_ATTRS(0ull);
- desc = upper_attrs | lower_attrs;
-
- return create_block_desc(desc, output_addr, level);
-}
-
-/*******************************************************************************
- * Helper to create a level 1/2/3 block descriptor which maps the va to output_
- * addr with inner-shareable normal wbwa read-write memory attributes.
- ******************************************************************************/
-unsigned long create_rwmem_block(unsigned long output_addr,
- unsigned int level,
- unsigned int ns)
-{
- unsigned long upper_attrs, lower_attrs, desc;
-
- lower_attrs = LOWER_ATTRS(ACCESS_FLAG | ISH | AP_RW);
- lower_attrs |= LOWER_ATTRS(ns | ATTR_IWBWA_OWBWA_NTR_INDEX);
- upper_attrs = UPPER_ATTRS(XN);
- desc = upper_attrs | lower_attrs;
-
- return create_block_desc(desc, output_addr, level);
-}
diff --git a/lib/aarch64/xlat_tables.c b/lib/aarch64/xlat_tables.c
index 2f2ca81..269743f 100644
--- a/lib/aarch64/xlat_tables.c
+++ b/lib/aarch64/xlat_tables.c
@@ -52,7 +52,17 @@
#define debug_print(...) ((void)0)
#endif
-CASSERT(ADDR_SPACE_SIZE > 0, assert_valid_addr_space_size);
+#define IS_POWER_OF_TWO(x) (((x) & ((x) - 1)) == 0)
+
+/*
+ * The virtual address space size must be a power of two (as set in TCR.T0SZ).
+ * As we start the initial lookup at level 1, it must also be between 2 GB and
+ * 512 GB (with the virtual address size therefore 31 to 39 bits). See section
+ * D4.2.5 in the ARMv8-A Architecture Reference Manual (DDI 0487A.i) for more
+ * information.
+ */
+CASSERT(ADDR_SPACE_SIZE >= (1ull << 31) && ADDR_SPACE_SIZE <= (1ull << 39) &&
+ IS_POWER_OF_TWO(ADDR_SPACE_SIZE), assert_valid_addr_space_size);
#define UNSET_DESC ~0ul
@@ -138,6 +148,7 @@
unsigned level)
{
unsigned long desc = addr_pa;
+ int mem_type;
desc |= level == 3 ? TABLE_DESC : BLOCK_DESC;
@@ -147,16 +158,23 @@
desc |= LOWER_ATTRS(ACCESS_FLAG);
- if (attr & MT_MEMORY) {
+ mem_type = MT_TYPE(attr);
+ if (mem_type == MT_MEMORY) {
desc |= LOWER_ATTRS(ATTR_IWBWA_OWBWA_NTR_INDEX | ISH);
if (attr & MT_RW)
desc |= UPPER_ATTRS(XN);
+ } else if (mem_type == MT_NON_CACHEABLE) {
+ desc |= LOWER_ATTRS(ATTR_NON_CACHEABLE_INDEX | OSH);
+ if (attr & MT_RW)
+ desc |= UPPER_ATTRS(XN);
} else {
+ assert(mem_type == MT_DEVICE);
desc |= LOWER_ATTRS(ATTR_DEVICE_INDEX | OSH);
desc |= UPPER_ATTRS(XN);
}
- debug_print(attr & MT_MEMORY ? "MEM" : "DEV");
+ debug_print((mem_type == MT_MEMORY) ? "MEM" :
+ ((mem_type == MT_NON_CACHEABLE) ? "NC" : "DEV"));
debug_print(attr & MT_RW ? "-RW" : "-RO");
debug_print(attr & MT_NS ? "-NS" : "-S");
@@ -167,6 +185,7 @@
unsigned long size)
{
int attr = mm->attr;
+ int old_mem_type, new_mem_type;
for (;;) {
++mm;
@@ -183,7 +202,20 @@
if ((mm->attr & attr) == attr)
continue; /* Region doesn't override attribs so skip */
+ /*
+ * Update memory mapping attributes in 2 steps:
+ * 1) Update access permissions and security state flags
+ * 2) Update memory type.
+ *
+ * See xlat_tables.h for details about the attributes priority
+ * system and the rules dictating whether attributes should be
+ * updated.
+ */
+ old_mem_type = MT_TYPE(attr);
+ new_mem_type = MT_TYPE(mm->attr);
attr &= mm->attr;
+ if (new_mem_type < old_mem_type)
+ attr = (attr & ~MT_TYPE_MASK) | new_mem_type;
if (mm->base_va > base_va ||
mm->base_va + mm->size < base_va + size)
@@ -207,7 +239,10 @@
do {
unsigned long desc = UNSET_DESC;
- if (mm->base_va + mm->size <= base_va) {
+ if (!mm->size) {
+ /* Done mapping regions; finish zeroing the table */
+ desc = INVALID_DESC;
+ } else if (mm->base_va + mm->size <= base_va) {
/* Area now after the region so skip it */
++mm;
continue;
@@ -245,7 +280,7 @@
*table++ = desc;
base_va += level_size;
- } while (mm->size && (base_va & level_index_mask));
+ } while ((base_va & level_index_mask) && (base_va < ADDR_SPACE_SIZE));
return mm;
}
@@ -309,6 +344,8 @@
mair = MAIR_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX); \
mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, \
ATTR_IWBWA_OWBWA_NTR_INDEX); \
+ mair |= MAIR_ATTR_SET(ATTR_NON_CACHEABLE, \
+ ATTR_NON_CACHEABLE_INDEX); \
write_mair_el##_el(mair); \
\
/* Invalidate TLBs at the current exception level */ \
diff --git a/lib/cpus/aarch64/cortex_a53.S b/lib/cpus/aarch64/cortex_a53.S
index c33ba57..bb56516 100644
--- a/lib/cpus/aarch64/cortex_a53.S
+++ b/lib/cpus/aarch64/cortex_a53.S
@@ -32,6 +32,7 @@
#include <bl_common.h>
#include <cortex_a53.h>
#include <cpu_macros.S>
+#include <debug.h>
#include <plat_macros.S>
/* ---------------------------------------------
@@ -73,7 +74,7 @@
*/
cmp x0, #2
b.ls apply_826319
-#if DEBUG
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
b print_revision_warning
#else
ret
@@ -109,7 +110,7 @@
*/
cmp x0, #3
b.ls disable_hint
-#if DEBUG
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
b print_revision_warning
#else
ret
diff --git a/lib/cpus/aarch64/cortex_a57.S b/lib/cpus/aarch64/cortex_a57.S
index 99db25b..4c0b8ce 100644
--- a/lib/cpus/aarch64/cortex_a57.S
+++ b/lib/cpus/aarch64/cortex_a57.S
@@ -33,6 +33,7 @@
#include <bl_common.h>
#include <cortex_a57.h>
#include <cpu_macros.S>
+#include <debug.h>
#include <plat_macros.S>
/* ---------------------------------------------
@@ -99,7 +100,7 @@
* Compare x0 against revision r0p0
*/
cbz x0, apply_806969
-#if DEBUG
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
b print_revision_warning
#else
ret
@@ -125,7 +126,7 @@
* Compare x0 against revision r0p0
*/
cbz x0, apply_813420
-#if DEBUG
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
b print_revision_warning
#else
ret
@@ -154,7 +155,7 @@
*/
cmp x0, #0x12
b.ls disable_hint
-#if DEBUG
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
b print_revision_warning
#else
ret
diff --git a/lib/cpus/aarch64/cpu_helpers.S b/lib/cpus/aarch64/cpu_helpers.S
index e41d95b..dab933c 100644
--- a/lib/cpus/aarch64/cpu_helpers.S
+++ b/lib/cpus/aarch64/cpu_helpers.S
@@ -35,6 +35,7 @@
#if IMAGE_BL31
#include <cpu_data.h>
#endif
+#include <debug.h>
/* Reset fn is needed in BL at reset vector */
#if IMAGE_BL1 || IMAGE_BL31
@@ -204,10 +205,10 @@
ret
endfunc get_cpu_ops_ptr
-#if DEBUG
-.section .rodata.rev_warn_str, "aS"
-rev_warn_str:
- .asciz "Warning: Skipping CPU specific reset operation for non-matching CPU revision number.\n"
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+.section .rodata.rev_verbose_str, "aS"
+rev_verbose_str:
+ .asciz "VERBOSE: Skipping CPU specific reset operation for non-matching CPU revision number.\n"
/*
* This function prints the above warning message to the crash console.
@@ -224,7 +225,7 @@
/* Check if the console is initialized */
cbz x0, 1f
/* The console is initialized */
- adr x4, rev_warn_str
+ adr x4, rev_verbose_str
bl asm_print_str
1:
ret x5
diff --git a/make_helpers/build_env.mk b/make_helpers/build_env.mk
new file mode 100644
index 0000000..62c7f68
--- /dev/null
+++ b/make_helpers/build_env.mk
@@ -0,0 +1,96 @@
+#
+# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# Neither the name of ARM nor the names of its contributors may be used
+# to endorse or promote products derived from this software without specific
+# prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+# This file contains the logic to identify and include any relevant
+# build environment specific make include files.
+
+ifndef BUILD_ENV_MK
+ BUILD_ENV_MK := $(lastword $(MAKEFILE_LIST))
+
+ # Block possible built-in command definitions that are not fully portable.
+ # This traps occurences that need replacing with our OS portable macros
+ COPY := $$(error "Replace COPY with call to SHELL_COPY or SHELL_COPY_TREE.")
+ CP := $$(error "Replace CP with call to SHELL_COPY or SHELL_COPY_TREE.")
+ DEL := $$(error "Replace DEL with call to SHELL_DELETE.")
+ MD := $$(error "Replace MD with call to MAKE_PREREQ_DIR.")
+ MKDIR := $$(error "Replace MKDIR with call to MAKE_PREREQ_DIR.")
+ RD := $$(error "Replace RD with call to SHELL_REMOVE_DIR.")
+ RM := $$(error "Replace RM with call to SHELL_DELETE.")
+ RMDIR := $$(error "Replace RMDIR with call to SHELL_REMOVE_DIR.")
+
+ ENV_FILE_TO_INCLUDE := unix.mk
+ ifdef OSTYPE
+ ifneq ($(findstring ${OSTYPE}, cygwin),)
+ ENV_FILE_TO_INCLUDE := cygwin.mk
+ else
+ ifneq ($(findstring ${OSTYPE}, MINGW32 mingw msys),)
+ ENV_FILE_TO_INCLUDE := msys.mk
+ endif
+ endif
+ else
+ ifdef MSYSTEM
+ # Although the MINGW MSYS shell sets OSTYPE as msys in its environment,
+ # it does not appear in the GNU make view of environment variables.
+ # We use MSYSTEM as an alternative, as that is seen by make
+ ifneq ($(findstring ${MSYSTEM}, MINGW32 mingw msys),)
+ OSTYPE ?= msys
+ ENV_FILE_TO_INCLUDE := msys.mk
+ endif
+ else
+ ifdef OS
+ ifneq ($(findstring ${OS}, Windows_NT),)
+ ENV_FILE_TO_INCLUDE := windows.mk
+ endif
+ endif
+ endif
+ endif
+ include ${MAKE_HELPERS_DIRECTORY}${ENV_FILE_TO_INCLUDE}
+ ENV_FILE_TO_INCLUDE :=
+
+ ifndef SHELL_COPY
+ $(error "SHELL_COPY not defined for build environment.")
+ endif
+ ifndef SHELL_COPY_TREE
+ $(error "SHELL_COPY_TREE not defined for build environment.")
+ endif
+ ifndef SHELL_DELETE_ALL
+ $(error "SHELL_DELETE_ALL not defined for build environment.")
+ endif
+ ifndef SHELL_DELETE
+ $(error "SHELL_DELETE not defined for build environment.")
+ endif
+ ifndef MAKE_PREREQ_DIR
+ $(error "MAKE_PREREQ_DIR not defined for build environment.")
+ endif
+ ifndef SHELL_REMOVE_DIR
+ $(error "SHELL_REMOVE_DIR not defined for build environment.")
+ endif
+
+endif
diff --git a/make_helpers/build_macros.mk b/make_helpers/build_macros.mk
index d6a4e3a..5171ff0 100644
--- a/make_helpers/build_macros.mk
+++ b/make_helpers/build_macros.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
@@ -28,6 +28,23 @@
# POSSIBILITY OF SUCH DAMAGE.
#
+# Report an error if the eval make function is not available.
+$(eval eval_available := T)
+ifneq (${eval_available},T)
+ $(error This makefile only works with a Make program that supports $$(eval))
+endif
+
+# Some utility macros for manipulating awkward (whitespace) characters.
+blank :=
+space :=${blank} ${blank}
+
+# A user defined function to recursively search for a filename below a directory
+# $1 is the directory root of the recursive search (blank for current directory).
+# $2 is the file name to search for.
+define rwildcard
+$(strip $(foreach d,$(wildcard ${1}*),$(call rwildcard,${d}/,${2}) $(filter $(subst *,%,%${2}),${d})))
+endef
+
# This table is used in converting lower case to upper case.
uppercase_table:=a,A b,B c,C d,D e,E f,F g,G h,H i,I j,J k,K l,L m,M n,N o,O p,P q,Q r,R s,S t,T u,U v,V w,W x,X y,Y z,Z
@@ -193,10 +210,8 @@
@echo " CC $$<"
$$(Q)$$(CC) $$(CFLAGS) -D$(IMAGE) -c $$< -o $$@
-
-$(PREREQUISITES): $(2)
+$(PREREQUISITES): $(2) | bl$(3)_dirs
@echo " DEPS $$@"
- @mkdir -p $(1)
$$(Q)$$(CC) $$(CFLAGS) -M -MT $(OBJ) -MF $$@ $$<
ifdef IS_ANYTHING_TO_BUILD
@@ -220,9 +235,8 @@
@echo " AS $$<"
$$(Q)$$(AS) $$(ASFLAGS) -D$(IMAGE) -c $$< -o $$@
-$(PREREQUISITES): $(2)
+$(PREREQUISITES): $(2) | bl$(3)_dirs
@echo " DEPS $$@"
- @mkdir -p $(1)
$$(Q)$$(AS) $$(ASFLAGS) -M -MT $(OBJ) -MF $$@ $$<
ifdef IS_ANYTHING_TO_BUILD
@@ -243,9 +257,8 @@
@echo " PP $$<"
$$(Q)$$(AS) $$(ASFLAGS) -P -E -D__LINKER__ -o $$@ $$<
-$(PREREQUISITES): $(2)
+$(PREREQUISITES): $(2) | $(dir ${1})
@echo " DEPS $$@"
- @mkdir -p $$(dir $$@)
$$(Q)$$(AS) $$(ASFLAGS) -M -MT $(1) -MF $$@ $$<
ifdef IS_ANYTHING_TO_BUILD
@@ -274,7 +287,7 @@
# NOTE: The line continuation '\' is required in the next define otherwise we
# end up with a line-feed characer at the end of the last c filename.
-# Also bare this issue in mind if extending the list of supported filetypes.
+# Also bear this issue in mind if extending the list of supported filetypes.
define SOURCES_TO_OBJS
$(notdir $(patsubst %.c,%.o,$(filter %.c,$(1)))) \
$(notdir $(patsubst %.S,%.o,$(filter %.S,$(1))))
@@ -290,6 +303,10 @@
$(if $(3),$(eval $(call FIP_ADD_PAYLOAD,$(2),--$(3),bl$(1))))
endef
+# Allow overriding the timestamp, for example for reproducible builds, or to
+# synchronize timestamps across multiple projects.
+# This must be set to a C string (including quotes where applicable).
+BUILD_MESSAGE_TIMESTAMP ?= __TIME__", "__DATE__
# MAKE_BL macro defines the targets and options to build each BL image.
# Arguments:
@@ -306,18 +323,36 @@
$(eval DUMP := $(call IMG_DUMP,$(1)))
$(eval BIN := $(call IMG_BIN,$(1)))
$(eval BL_LINKERFILE := $(BL$(call uppercase,$(1))_LINKERFILE))
+ # We use sort only to get a list of unique object directory names.
+ # ordering is not relevant but sort removes duplicates.
+ $(eval TEMP_OBJ_DIRS := $(sort $(BUILD_DIR)/ $(dir ${OBJS})))
+ # The $(dir ) function leaves a trailing / on the directory names
+ # We append a . then strip /. from each, to remove the trailing / characters
+ # This gives names suitable for use as make rule targets.
+ $(eval OBJ_DIRS := $(subst /.,,$(addsuffix .,$(TEMP_OBJ_DIRS))))
+
+# Create generators for object directory structure
- $(eval $(call MAKE_OBJS,$(BUILD_DIR),$(SOURCES),$(1)))
- $(eval $(call MAKE_LD,$(LINKERFILE),$(BL_LINKERFILE)))
+$(eval $(foreach objd,${OBJ_DIRS},$(call MAKE_PREREQ_DIR,${objd},)))
-$(BUILD_DIR):
- $$(Q)mkdir -p "$$@"
+.PHONY : bl${1}_dirs
-$(ELF): $(OBJS) $(LINKERFILE)
+# We use order-only prerequisites to ensure that directories are created,
+# but do not cause re-builds every time a file is written.
+bl${1}_dirs: | ${OBJ_DIRS}
+
+$(eval $(call MAKE_OBJS,$(BUILD_DIR),$(SOURCES),$(1)))
+$(eval $(call MAKE_LD,$(LINKERFILE),$(BL_LINKERFILE)))
+
+$(ELF): $(OBJS) $(LINKERFILE) | bl$(1)_dirs
@echo " LD $$@"
- @echo 'const char build_message[] = "Built : "__TIME__", "__DATE__; \
+ifdef MAKE_BUILD_STRINGS
+ $(call MAKE_BUILD_STRINGS, $(BUILD_DIR)/build_message.o)
+else
+ @echo 'const char build_message[] = "Built : "$(BUILD_MESSAGE_TIMESTAMP); \
const char version_string[] = "${VERSION_STRING}";' | \
$$(CC) $$(CFLAGS) -xc - -o $(BUILD_DIR)/build_message.o
+endif
$$(Q)$$(LD) -o $$@ $$(LDFLAGS) -Map=$(MAPFILE) --script $(LINKERFILE) \
$(BUILD_DIR)/build_message.o $(OBJS)
@@ -333,7 +368,7 @@
@echo
.PHONY: bl$(1)
-bl$(1): $(BUILD_DIR) $(BIN) $(DUMP)
+bl$(1): $(BIN) $(DUMP)
all: bl$(1)
diff --git a/make_helpers/cygwin.mk b/make_helpers/cygwin.mk
new file mode 100644
index 0000000..e69c0b1
--- /dev/null
+++ b/make_helpers/cygwin.mk
@@ -0,0 +1,43 @@
+#
+# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# Neither the name of ARM nor the names of its contributors may be used
+# to endorse or promote products derived from this software without specific
+# prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+#
+
+# OS specific definitions for builds in a Cygwin environment.
+# Cygwin allows us to use unix style commands on a windows platform.
+
+ifndef CYGWIN_MK
+ CYGWIN_MK := $(lastword $(MAKEFILE_LIST))
+
+ include ${MAKE_HELPERS_DIRECTORY}unix.mk
+
+ # In cygwin executable files have the Windows .exe extension type.
+ BIN_EXT := .exe
+
+endif
diff --git a/make_helpers/msys.mk b/make_helpers/msys.mk
new file mode 100644
index 0000000..188dc6c
--- /dev/null
+++ b/make_helpers/msys.mk
@@ -0,0 +1,44 @@
+#
+# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# Neither the name of ARM nor the names of its contributors may be used
+# to endorse or promote products derived from this software without specific
+# prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+#
+
+# OS specific definitions for builds in a Mingw32 MSYS environment.
+# Mingw32 allows us to use some unix style commands on a windows platform.
+
+ifndef MSYS_MK
+ MSYS_MK := $(lastword $(MAKEFILE_LIST))
+
+ include ${MAKE_HELPERS_DIRECTORY}unix.mk
+
+ # In MSYS executable files have the Windows .exe extension type.
+ BIN_EXT := .exe
+
+endif
+
diff --git a/make_helpers/plat_helpers.mk b/make_helpers/plat_helpers.mk
new file mode 100644
index 0000000..85ba84f
--- /dev/null
+++ b/make_helpers/plat_helpers.mk
@@ -0,0 +1,62 @@
+#
+# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# Neither the name of ARM nor the names of its contributors may be used
+# to endorse or promote products derived from this software without specific
+# prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+################################################################################
+# Helpers for finding and referencing platform directories
+################################################################################
+
+ifndef PLAT_HELPERS_MK
+ PLAT_HELPERS_MK := $(lastword $(MAKEFILE_LIST))
+
+ ifeq (${PLAT},)
+ $(error "Error: Unknown platform. Please use PLAT=<platform name> to specify the platform")
+ endif
+
+ # PLATFORM_ROOT can be overridden for when building tools directly
+ PLATFORM_ROOT ?= plat/
+ PLAT_MAKEFILE := platform.mk
+
+ # Generate the platforms list by recursively searching for all directories
+ # under /plat containing a PLAT_MAKEFILE. Append each platform with a `|`
+ # char and strip out the final '|'.
+ ALL_PLATFORM_MK_FILES := $(call rwildcard,${PLATFORM_ROOT},${PLAT_MAKEFILE})
+ ALL_PLATFORM_DIRS := $(patsubst %/,%,$(dir ${ALL_PLATFORM_MK_FILES}))
+ ALL_PLATFORMS := $(sort $(notdir ${ALL_PLATFORM_DIRS}))
+
+ PLAT_MAKEFILE_FULL := $(filter %/${PLAT}/${PLAT_MAKEFILE},${ALL_PLATFORM_MK_FILES})
+ PLATFORM_LIST := $(subst ${space},|,${ALL_PLATFORMS})
+ ifeq ($(PLAT_MAKEFILE_FULL),)
+ $(error "Error: Invalid platform. The following platforms are available: ${PLATFORM_LIST}")
+ endif
+
+ # Record the directory where the platform make file was found.
+ PLAT_DIR := $(dir ${PLAT_MAKEFILE_FULL})
+
+endif
diff --git a/make_helpers/tbbr/tbbr_tools.mk b/make_helpers/tbbr/tbbr_tools.mk
index e934d72..71d9747 100644
--- a/make_helpers/tbbr/tbbr_tools.mk
+++ b/make_helpers/tbbr/tbbr_tools.mk
@@ -58,6 +58,14 @@
TRUSTED_KEY_CERT := ${BUILD_PLAT}/trusted_key.crt
FWU_CERT := ${BUILD_PLAT}/fwu_cert.crt
+# Default non-volatile counter values (overridable by the platform)
+TFW_NVCTR_VAL ?= 0
+NTFW_NVCTR_VAL ?= 0
+
+# Pass the non-volatile counters to the cert_create tool
+$(eval $(call CERT_ADD_CMD_OPT,${TFW_NVCTR_VAL},--tfw-nvctr))
+$(eval $(call CERT_ADD_CMD_OPT,${NTFW_NVCTR_VAL},--ntfw-nvctr))
+
# Add Trusted Key certificate to the fip_create and cert_create command line options
$(eval $(call FIP_ADD_PAYLOAD,${TRUSTED_KEY_CERT},--trusted-key-cert))
$(eval $(call CERT_ADD_CMD_OPT,${TRUSTED_KEY_CERT},--trusted-key-cert))
diff --git a/make_helpers/unix.mk b/make_helpers/unix.mk
new file mode 100644
index 0000000..ab60435
--- /dev/null
+++ b/make_helpers/unix.mk
@@ -0,0 +1,81 @@
+#
+# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# Neither the name of ARM nor the names of its contributors may be used
+# to endorse or promote products derived from this software without specific
+# prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+#
+
+# Trusted Firmware shell command definitions for a Unix style environment.
+
+ifndef UNIX_MK
+ UNIX_MK := $(lastword $(MAKEFILE_LIST))
+
+ ECHO_BLANK_LINE := echo
+
+ DIR_DELIM := /
+ PATH_SEP := :
+
+ # These defines provide Unix style equivalents of the shell commands
+ # required by the Trusted Firmware build environment.
+
+ # ${1} is the file to be copied.
+ # ${2} is the destination file name.
+ define SHELL_COPY
+ ${Q}cp -f "${1}" "${2}"
+ endef
+
+ # ${1} is the directory to be copied.
+ # ${2} is the destination directory path.
+ define SHELL_COPY_TREE
+ ${Q}cp -rf "${1}" "${2}"
+ endef
+
+ # ${1} is the file to be deleted.
+ define SHELL_DELETE
+ -${Q}rm -f "${1}"
+ endef
+
+ # ${1} is a space delimited list of files to be deleted.
+ # Note that we do not quote ${1}, as multiple parameters may be passed.
+ define SHELL_DELETE_ALL
+ -${Q}rm -rf ${1}
+ endef
+
+ # ${1} is the directory to be generated.
+ # ${2} is optional, and allows a prerequisite to be specified.
+ define MAKE_PREREQ_DIR
+
+${1} : ${2}
+ ${Q}mkdir -p "${1}"
+
+ endef
+
+ define SHELL_REMOVE_DIR
+ -${Q}rm -rf "${1}"
+ endef
+
+endif
diff --git a/make_helpers/windows.mk b/make_helpers/windows.mk
new file mode 100644
index 0000000..8ac8246
--- /dev/null
+++ b/make_helpers/windows.mk
@@ -0,0 +1,109 @@
+#
+# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# Neither the name of ARM nor the names of its contributors may be used
+# to endorse or promote products derived from this software without specific
+# prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+#
+
+# OS specific parts for builds in a Windows_NT environment. The
+# environment variable OS is set to Windows_NT on all modern Windows platforms
+
+# Include generic windows command definitions.
+
+ifndef WINDOWS_MK
+ WINDOWS_MK := $(lastword $(MAKEFILE_LIST))
+
+ ECHO_BLANK_LINE := @cmd /c echo.
+ DIR_DELIM := $(strip \)
+ BIN_EXT := .exe
+ PATH_SEP := ;
+
+ # For some Windows native commands there is a problem with the directory delimiter.
+ # Make uses / (slash) and the commands expect \ (backslash)
+ # We have to provide a means of translating these, so we define local functions.
+
+ # ${1} is the file to be copied.
+ # ${2} is the destination file name.
+ define SHELL_COPY
+ $(eval tmp_from_file:=$(subst /,\,${1}))
+ $(eval tmp_to_file:=$(subst /,\,${2}))
+ copy "${tmp_from_file}" "${tmp_to_file}"
+ endef
+
+ # ${1} is the directory to be copied.
+ # ${2} is the destination directory path.
+ define SHELL_COPY_TREE
+ $(eval tmp_from_dir:=$(subst /,\,${1}))
+ $(eval tmp_to_dir:=$(subst /,\,${2}))
+ xcopy /HIVE "${tmp_from_dir}" "${tmp_to_dir}"
+ endef
+
+ # ${1} is the file to be deleted.
+ define SHELL_DELETE
+ $(eval tmp_del_file:=$(subst /,\,${*}))
+ -@if exist $(tmp_del_file) del /Q $(tmp_del_file)
+ endef
+
+ # ${1} is a space delimited list of files to be deleted.
+ define SHELL_DELETE_ALL
+ $(eval $(foreach filename,$(wildcard ${1}),$(call DELETE_IF_THERE,${filename})))
+ endef
+
+ # ${1} is the directory to be generated.
+ # ${2} is optional, and allows prerequisites to be specified.
+ define MAKE_PREREQ_DIR
+
+${1} : ${2}
+ $(eval tmp_dir:=$(subst /,\,${1}))
+ -@if not exist "$(tmp_dir)" mkdir "${tmp_dir}"
+
+ endef
+
+ # ${1} is the directory to be removed.
+ define SHELL_REMOVE_DIR
+ $(eval tmp_dir:=$(subst /,\,${1}))
+ -@if exist "$(tmp_dir)" rd /Q /S "$(tmp_dir)"
+ endef
+
+endif
+
+# Because git is not available from CMD.EXE, we need to avoid
+# the BUILD_STRING generation which uses git.
+# For now we use "development build".
+# This can be overridden from the command line or environment.
+BUILD_STRING ?= development build
+
+# The DOS echo shell command does not strip ' characters from the command
+# parameters before printing. We therefore use an alternative method invoked
+# by defining the MAKE_BUILD_STRINGS macro.
+BUILT_TIME_DATE_STRING = const char build_message[] = "Built : "${BUILD_MESSAGE_TIMESTAMP};
+VERSION_STRING_MESSAGE = const char version_string[] = "${VERSION_STRING}";
+define MAKE_BUILD_STRINGS
+ @echo $$(BUILT_TIME_DATE_STRING) $$(VERSION_STRING_MESSAGE) | \
+ $$(CC) $$(CFLAGS) -x c - -o $1
+endef
+
diff --git a/plat/arm/board/common/board_arm_trusted_boot.c b/plat/arm/board/common/board_arm_trusted_boot.c
index 103aafb..7ae00cc 100644
--- a/plat/arm/board/common/board_arm_trusted_boot.c
+++ b/plat/arm/board/common/board_arm_trusted_boot.c
@@ -31,11 +31,14 @@
#include <arm_def.h>
#include <assert.h>
#include <platform.h>
+#include <platform_oid.h>
#include <stdint.h>
#include <string.h>
/* Weak definition may be overridden in specific platform */
#pragma weak plat_match_rotpk
+#pragma weak plat_get_nv_ctr
+#pragma weak plat_set_nv_ctr
/* SHA256 algorithm */
#define SHA256_BYTES 32
@@ -148,3 +151,43 @@
return 0;
}
+/*
+ * Return the non-volatile counter value stored in the platform. The cookie
+ * will contain the OID of the counter in the certificate.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
+{
+ const char *oid;
+ uint32_t *nv_ctr_addr;
+
+ assert(cookie != NULL);
+ assert(nv_ctr != NULL);
+
+ oid = (const char *)cookie;
+ if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) {
+ nv_ctr_addr = (uint32_t *)TFW_NVCTR_BASE;
+ } else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) {
+ nv_ctr_addr = (uint32_t *)NTFW_CTR_BASE;
+ } else {
+ return 1;
+ }
+
+ *nv_ctr = (unsigned int)(*nv_ctr_addr);
+
+ return 0;
+}
+
+/*
+ * Store a new non-volatile counter value. On Juno and FVP, the non-volatile
+ * counters are RO and cannot be modified. We expect the values in the
+ * certificates to always match the RO values so that this function is never
+ * called.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+ return 1;
+}
diff --git a/plat/arm/board/common/board_common.mk b/plat/arm/board/common/board_common.mk
index 9e0c848..6ddc0c9 100644
--- a/plat/arm/board/common/board_common.mk
+++ b/plat/arm/board/common/board_common.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
@@ -51,6 +51,18 @@
endif
$(eval $(call add_define,ARM_ROTPK_LOCATION_ID))
+ # Certificate NV-Counters. Use values corresponding to tied off values in
+ # ARM development platforms
+ TFW_NVCTR_VAL ?= 31
+ NTFW_NVCTR_VAL ?= 223
+
BL1_SOURCES += plat/arm/board/common/board_arm_trusted_boot.c
BL2_SOURCES += plat/arm/board/common/board_arm_trusted_boot.c
endif
+
+# This flag controls whether memory usage needs to be optimised
+ARM_BOARD_OPTIMISE_MMAP ?= 0
+
+# Process flags
+$(eval $(call assert_boolean,ARM_BOARD_OPTIMISE_MMAP))
+$(eval $(call add_define,ARM_BOARD_OPTIMISE_MMAP))
diff --git a/plat/arm/board/fvp/aarch64/fvp_common.c b/plat/arm/board/fvp/aarch64/fvp_common.c
index 305505d..1de9999 100644
--- a/plat/arm/board/fvp/aarch64/fvp_common.c
+++ b/plat/arm/board/fvp/aarch64/fvp_common.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -30,7 +30,6 @@
#include <arm_config.h>
#include <arm_def.h>
-#include <cci.h>
#include <debug.h>
#include <gicv2.h>
#include <mmio.h>
@@ -50,9 +49,9 @@
/*******************************************************************************
* arm_config holds the characteristics of the differences between the three FVP
* platforms (Base, A53_A57 & Foundation). It will be populated during cold boot
- * at each boot stage by the primary before enabling the MMU (to allow cci
- * configuration) & used thereafter. Each BL will have its own copy to allow
- * independent operation.
+ * at each boot stage by the primary before enabling the MMU (to allow
+ * interconnect configuration) & used thereafter. Each BL will have its own copy
+ * to allow independent operation.
******************************************************************************/
arm_config_t arm_config;
@@ -98,6 +97,9 @@
MAP_DEVICE2,
ARM_MAP_NS_DRAM1,
ARM_MAP_TSP_SEC_MEM,
+#if ARM_BL31_IN_DRAM
+ ARM_MAP_BL31_SEC_DRAM,
+#endif
{0}
};
#endif
@@ -209,7 +211,7 @@
break;
case HBI_BASE_FVP:
arm_config.flags |= ARM_CONFIG_BASE_MMAP |
- ARM_CONFIG_HAS_CCI | ARM_CONFIG_HAS_TZC;
+ ARM_CONFIG_HAS_INTERCONNECT | ARM_CONFIG_HAS_TZC;
/*
* Check for supported revisions
@@ -230,23 +232,20 @@
}
-void fvp_cci_init(void)
+void fvp_interconnect_init(void)
{
- /*
- * Initialize CCI-400 driver
- */
- if (arm_config.flags & ARM_CONFIG_HAS_CCI)
- arm_cci_init();
+ if (arm_config.flags & ARM_CONFIG_HAS_INTERCONNECT)
+ plat_arm_interconnect_init();
}
-void fvp_cci_enable(void)
+void fvp_interconnect_enable(void)
{
- if (arm_config.flags & ARM_CONFIG_HAS_CCI)
- cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr()));
+ if (arm_config.flags & ARM_CONFIG_HAS_INTERCONNECT)
+ plat_arm_interconnect_enter_coherency();
}
-void fvp_cci_disable(void)
+void fvp_interconnect_disable(void)
{
- if (arm_config.flags & ARM_CONFIG_HAS_CCI)
- cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr()));
+ if (arm_config.flags & ARM_CONFIG_HAS_INTERCONNECT)
+ plat_arm_interconnect_exit_coherency();
}
diff --git a/plat/arm/board/fvp/aarch64/fvp_helpers.S b/plat/arm/board/fvp/aarch64/fvp_helpers.S
index fe7358f..884fee8 100644
--- a/plat/arm/board/fvp/aarch64/fvp_helpers.S
+++ b/plat/arm/board/fvp/aarch64/fvp_helpers.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -111,8 +111,7 @@
*/
dsb sy
wfi
-cb_panic:
- b cb_panic
+ bl plat_panic_handler
#else
mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE
@@ -174,7 +173,7 @@
*/
mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE
ldr x0, [x0]
- cbz x0, _panic
+ cbz x0, _panic_handler
ret
/* ---------------------------------------------------------------------
@@ -182,8 +181,8 @@
* is empty. This should never happen!
* ---------------------------------------------------------------------
*/
-_panic:
- b _panic
+_panic_handler:
+ bl plat_panic_handler
endfunc plat_get_my_entrypoint
/* -----------------------------------------------------
diff --git a/plat/arm/board/fvp/fvp_bl1_setup.c b/plat/arm/board/fvp/fvp_bl1_setup.c
index 91bc9c4..cc7feae 100644
--- a/plat/arm/board/fvp/fvp_bl1_setup.c
+++ b/plat/arm/board/fvp/fvp_bl1_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -44,14 +44,14 @@
fvp_config_setup();
/*
- * Initialize CCI for this cluster during cold boot.
+ * Initialize Interconnect for this cluster during cold boot.
* No need for locks as no other CPU is active.
*/
- fvp_cci_init();
+ fvp_interconnect_init();
/*
- * Enable CCI coherency for the primary CPU's cluster.
+ * Enable coherency in Interconnect for the primary CPU's cluster.
*/
- fvp_cci_enable();
+ fvp_interconnect_enable();
}
/*******************************************************************************
diff --git a/plat/arm/board/fvp/fvp_bl31_setup.c b/plat/arm/board/fvp/fvp_bl31_setup.c
index f29af64..2ee3ba5 100644
--- a/plat/arm/board/fvp/fvp_bl31_setup.c
+++ b/plat/arm/board/fvp/fvp_bl31_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -41,17 +41,17 @@
fvp_config_setup();
/*
- * Initialize CCI for this cluster during cold boot.
- * No need for locks as no other CPU is active.
+ * Initialize the correct interconnect for this cluster during cold
+ * boot. No need for locks as no other CPU is active.
*/
- fvp_cci_init();
+ fvp_interconnect_init();
/*
- * Enable CCI coherency for the primary CPU's cluster.
+ * Enable coherency in interconnect for the primary CPU's cluster.
* Earlier bootloader stages might already do this (e.g. Trusted
* Firmware's BL1 does it) but we can't assume so. There is no harm in
* executing this code twice anyway.
* FVP PSCI code will enable coherency for other clusters.
*/
- fvp_cci_enable();
+ fvp_interconnect_enable();
}
diff --git a/plat/arm/board/fvp/fvp_def.h b/plat/arm/board/fvp/fvp_def.h
index 41b872a..b0f07ef 100644
--- a/plat/arm/board/fvp/fvp_def.h
+++ b/plat/arm/board/fvp/fvp_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -33,7 +33,9 @@
#include <arm_def.h>
-
+#ifndef FVP_CLUSTER_COUNT
+#define FVP_CLUSTER_COUNT 2
+#endif
#define FVP_MAX_CPUS_PER_CLUSTER 4
#define FVP_PRIMARY_CPU 0x0
@@ -67,7 +69,13 @@
#define PCIE_EXP_BASE 0x40000000
#define TZRNG_BASE 0x7fe60000
-#define TZNVCTR_BASE 0x7fe70000
+
+/* Non-volatile counters */
+#define TRUSTED_NVCTR_BASE 0x7fe70000
+#define TFW_NVCTR_BASE (TRUSTED_NVCTR_BASE + 0x0000)
+#define TFW_NVCTR_SIZE 4
+#define NTFW_CTR_BASE (TRUSTED_NVCTR_BASE + 0x0004)
+#define NTFW_CTR_SIZE 4
/* Keys */
#define SOC_KEYS_BASE 0x7fe80000
diff --git a/plat/arm/board/fvp/fvp_pm.c b/plat/arm/board/fvp/fvp_pm.c
index f959fab..3976ef2 100644
--- a/plat/arm/board/fvp/fvp_pm.c
+++ b/plat/arm/board/fvp/fvp_pm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -86,7 +86,7 @@
uint64_t mpidr = read_mpidr_el1();
/* Disable coherency if this cluster is to be turned off */
- fvp_cci_disable();
+ fvp_interconnect_disable();
/* Program the power controller to turn the cluster off */
fvp_pwrc_write_pcoffr(mpidr);
@@ -117,7 +117,7 @@
fvp_pwrc_write_pponr(mpidr);
/* Enable coherency if this cluster was off */
- fvp_cci_enable();
+ fvp_interconnect_enable();
}
/*
diff --git a/plat/arm/board/fvp/fvp_private.h b/plat/arm/board/fvp/fvp_private.h
index e88a45e..bb115e1 100644
--- a/plat/arm/board/fvp/fvp_private.h
+++ b/plat/arm/board/fvp/fvp_private.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -39,9 +39,9 @@
void fvp_config_setup(void);
-void fvp_cci_init(void);
-void fvp_cci_enable(void);
-void fvp_cci_disable(void);
+void fvp_interconnect_init(void);
+void fvp_interconnect_enable(void);
+void fvp_interconnect_disable(void);
#endif /* __FVP_PRIVATE_H__ */
diff --git a/plat/arm/board/fvp/fvp_security.c b/plat/arm/board/fvp/fvp_security.c
index 0cf8450..b1de977 100644
--- a/plat/arm/board/fvp/fvp_security.c
+++ b/plat/arm/board/fvp/fvp_security.c
@@ -46,5 +46,5 @@
*/
if (get_arm_config()->flags & ARM_CONFIG_HAS_TZC)
- arm_tzc_setup();
+ arm_tzc400_setup();
}
diff --git a/plat/arm/board/fvp/fvp_topology.c b/plat/arm/board/fvp/fvp_topology.c
index a212eda..741aad6 100644
--- a/plat/arm/board/fvp/fvp_topology.c
+++ b/plat/arm/board/fvp/fvp_topology.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -29,27 +29,47 @@
*/
#include <arch.h>
+#include <cassert.h>
#include <plat_arm.h>
#include <platform_def.h>
#include "drivers/pwrc/fvp_pwrc.h"
-/*
- * The FVP power domain tree does not have a single system level power domain
- * i.e. a single root node. The first entry in the power domain descriptor
- * specifies the number of power domains at the highest power level. For the FVP
- * this is 2 i.e. the number of cluster power domains.
- */
-#define FVP_PWR_DOMAINS_AT_MAX_PWR_LVL ARM_CLUSTER_COUNT
-
/* The FVP power domain tree descriptor */
-const unsigned char arm_power_domain_tree_desc[] = {
- /* No of root nodes */
- FVP_PWR_DOMAINS_AT_MAX_PWR_LVL,
- /* No of children for the first node */
- PLAT_ARM_CLUSTER0_CORE_COUNT,
- /* No of children for the second node */
- PLAT_ARM_CLUSTER1_CORE_COUNT
-};
+unsigned char fvp_power_domain_tree_desc[FVP_CLUSTER_COUNT + 1];
+
+
+CASSERT(FVP_CLUSTER_COUNT && FVP_CLUSTER_COUNT <= 256, assert_invalid_fvp_cluster_count);
+
+/*******************************************************************************
+ * This function dynamically constructs the topology according to
+ * FVP_CLUSTER_COUNT and returns it.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ int i;
+
+ /*
+ * The FVP power domain tree does not have a single system level power domain
+ * i.e. a single root node. The first entry in the power domain descriptor
+ * specifies the number of power domains at the highest power level. For the FVP
+ * this is the number of cluster power domains.
+ */
+ fvp_power_domain_tree_desc[0] = FVP_CLUSTER_COUNT;
+
+ for (i = 0; i < FVP_CLUSTER_COUNT; i++)
+ fvp_power_domain_tree_desc[i + 1] = FVP_MAX_CPUS_PER_CLUSTER;
+
+ return fvp_power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * 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 FVP_MAX_CPUS_PER_CLUSTER;
+}
/*******************************************************************************
* This function implements a part of the critical interface between the psci
diff --git a/plat/arm/board/fvp/include/plat_macros.S b/plat/arm/board/fvp/include/plat_macros.S
index 2117843..df66a52 100644
--- a/plat/arm/board/fvp/include/plat_macros.S
+++ b/plat/arm/board/fvp/include/plat_macros.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -31,6 +31,7 @@
#define __PLAT_MACROS_S__
#include <arm_macros.S>
+#include <cci_macros.S>
#include <v2m_def.h>
#include "../fvp_def.h"
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index 0d671dc..ca8e35e 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -39,9 +39,10 @@
#include "../fvp_def.h"
/* Required platform porting definitions */
-#define PLAT_NUM_PWR_DOMAINS (ARM_CLUSTER_COUNT + \
+#define PLAT_NUM_PWR_DOMAINS (FVP_CLUSTER_COUNT + \
PLATFORM_CORE_COUNT)
#define PLAT_MAX_PWR_LVL ARM_PWR_LVL1
+#define PLATFORM_CORE_COUNT (FVP_CLUSTER_COUNT * FVP_MAX_CPUS_PER_CLUSTER)
/*
* Other platform porting definitions are provided by included headers
@@ -50,8 +51,7 @@
/*
* Required ARM standard platform porting definitions
*/
-#define PLAT_ARM_CLUSTER0_CORE_COUNT 4
-#define PLAT_ARM_CLUSTER1_CORE_COUNT 4
+#define PLAT_ARM_CLUSTER_COUNT FVP_CLUSTER_COUNT
#define PLAT_ARM_TRUSTED_ROM_BASE 0x00000000
#define PLAT_ARM_TRUSTED_ROM_SIZE 0x04000000 /* 64 MB */
@@ -64,8 +64,6 @@
#define PLAT_ARM_DRAM2_SIZE MAKE_ULL(0x780000000)
-#define PLAT_ARM_SHARED_RAM_CACHED 1
-
/*
* Load address of BL33 for this platform port
*/
@@ -115,7 +113,7 @@
* would normally use the default ID so allow that too.
*/
#define PLAT_ARM_TZC_BASE 0x2a4a0000
-#define PLAT_ARM_TZC_FILTERS REG_ATTR_FILTER_BIT(0)
+#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT(0)
#define PLAT_ARM_TZC_NS_DEV_ACCESS ( \
TZC_REGION_ACCESS_RDWR(FVP_NSAID_DEFAULT) | \
@@ -144,4 +142,26 @@
#define PLAT_ARM_G0_IRQS ARM_G0_IRQS
+/*
+ * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
+ * plus a little space for growth.
+ */
+#define PLAT_ARM_MAX_BL1_RW_SIZE 0xA000
+
+/*
+ * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a
+ * little space for growth.
+ */
+#if TRUSTED_BOARD_BOOT
+# define PLAT_ARM_MAX_BL2_SIZE 0x1D000
+#else
+# define PLAT_ARM_MAX_BL2_SIZE 0xC000
+#endif
+
+/*
+ * PLAT_ARM_MAX_BL31_SIZE is calculated using the current BL31 debug size plus a
+ * little space for growth.
+ */
+#define PLAT_ARM_MAX_BL31_SIZE 0x1D000
+
#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index ed4c898..afd939d 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -34,6 +34,11 @@
# The FVP platform depends on this macro to build with correct GIC driver.
$(eval $(call add_define,FVP_USE_GIC_DRIVER))
+# If FVP_CLUSTER_COUNT has been defined, pass it into the build system.
+ifdef FVP_CLUSTER_COUNT
+$(eval $(call add_define,FVP_CLUSTER_COUNT))
+endif
+
# Choose the GIC sources depending upon the how the FVP will be invoked
ifeq (${FVP_USE_GIC_DRIVER}, FVP_GICV3)
FVP_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \
@@ -57,6 +62,14 @@
$(error "Incorrect GIC driver chosen on FVP port")
endif
+FVP_INTERCONNECT_SOURCES := drivers/arm/cci/cci.c \
+ plat/arm/common/arm_cci.c
+
+FVP_SECURITY_SOURCES := drivers/arm/tzc/tzc400.c \
+ plat/arm/board/fvp/fvp_security.c \
+ plat/arm/common/arm_tzc400.c
+
+
PLAT_INCLUDES := -Iplat/arm/board/fvp/include
@@ -69,13 +82,15 @@
lib/cpus/aarch64/cortex_a72.S
BL1_SOURCES += drivers/io/io_semihosting.c \
- ${FVP_CPU_LIBS} \
lib/semihosting/semihosting.c \
lib/semihosting/aarch64/semihosting_call.S \
plat/arm/board/fvp/aarch64/fvp_helpers.S \
plat/arm/board/fvp/fvp_bl1_setup.c \
plat/arm/board/fvp/fvp_err.c \
- plat/arm/board/fvp/fvp_io_storage.c
+ plat/arm/board/fvp/fvp_io_storage.c \
+ ${FVP_CPU_LIBS} \
+ ${FVP_INTERCONNECT_SOURCES}
+
BL2_SOURCES += drivers/arm/sp804/sp804_delay_timer.c \
drivers/io/io_semihosting.c \
@@ -85,19 +100,20 @@
plat/arm/board/fvp/fvp_bl2_setup.c \
plat/arm/board/fvp/fvp_err.c \
plat/arm/board/fvp/fvp_io_storage.c \
- plat/arm/board/fvp/fvp_security.c
+ ${FVP_SECURITY_SOURCES}
BL2U_SOURCES += plat/arm/board/fvp/fvp_bl2u_setup.c \
- plat/arm/board/fvp/fvp_security.c
+ ${FVP_SECURITY_SOURCES}
-BL31_SOURCES += ${FVP_CPU_LIBS} \
- plat/arm/board/fvp/fvp_bl31_setup.c \
+BL31_SOURCES += plat/arm/board/fvp/fvp_bl31_setup.c \
plat/arm/board/fvp/fvp_pm.c \
- plat/arm/board/fvp/fvp_security.c \
plat/arm/board/fvp/fvp_topology.c \
plat/arm/board/fvp/aarch64/fvp_helpers.S \
plat/arm/board/fvp/drivers/pwrc/fvp_pwrc.c \
- ${FVP_GIC_SOURCES}
+ ${FVP_CPU_LIBS} \
+ ${FVP_GIC_SOURCES} \
+ ${FVP_INTERCONNECT_SOURCES} \
+ ${FVP_SECURITY_SOURCES}
# Disable the PSCI platform compatibility layer
ENABLE_PLAT_COMPAT := 0
diff --git a/plat/arm/board/juno/aarch64/juno_helpers.S b/plat/arm/board/juno/aarch64/juno_helpers.S
index 1931535..377b0cb 100644
--- a/plat/arm/board/juno/aarch64/juno_helpers.S
+++ b/plat/arm/board/juno/aarch64/juno_helpers.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -201,8 +201,7 @@
JUMP_TO_HANDLER_IF_JUNO_R(2)
/* Board revision is not supported */
-not_supported:
- b not_supported
+ bl plat_panic_handler
endfunc plat_reset_handler
diff --git a/plat/arm/board/juno/include/plat_macros.S b/plat/arm/board/juno/include/plat_macros.S
index db0c1d2..d2a88ed 100644
--- a/plat/arm/board/juno/include/plat_macros.S
+++ b/plat/arm/board/juno/include/plat_macros.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -30,6 +30,7 @@
#ifndef __PLAT_MACROS_S__
#define __PLAT_MACROS_S__
+#include <cci_macros.S>
#include <css_macros.S>
/*
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index 924eb0a..a2cf036 100644
--- a/plat/arm/board/juno/include/platform_def.h
+++ b/plat/arm/board/juno/include/platform_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -41,11 +41,15 @@
#include <v2m_def.h>
#include "../juno_def.h"
+/* Required platform porting definitions */
/* Juno supports system power domain */
#define PLAT_MAX_PWR_LVL ARM_PWR_LVL2
#define PLAT_NUM_PWR_DOMAINS (ARM_SYSTEM_COUNT + \
- ARM_CLUSTER_COUNT + \
+ JUNO_CLUSTER_COUNT + \
PLATFORM_CORE_COUNT)
+#define PLATFORM_CORE_COUNT (JUNO_CLUSTER0_CORE_COUNT + \
+ JUNO_CLUSTER1_CORE_COUNT)
+
/*
* Other platform porting definitions are provided by included headers
*/
@@ -53,8 +57,7 @@
/*
* Required ARM standard platform porting definitions
*/
-#define PLAT_ARM_CLUSTER0_CORE_COUNT 2
-#define PLAT_ARM_CLUSTER1_CORE_COUNT 4
+#define PLAT_ARM_CLUSTER_COUNT JUNO_CLUSTER_COUNT
/* Use the bypass address */
#define PLAT_ARM_TRUSTED_ROM_BASE V2M_FLASH0_BASE + BL1_ROM_BYPASS_OFFSET
@@ -70,13 +73,52 @@
#define PLAT_ARM_TRUSTED_ROM_SIZE 0x00010000
#endif /* TRUSTED_BOARD_BOOT */
+/*
+ * If ARM_BOARD_OPTIMISE_MMAP=0 then Juno uses the default, unoptimised values
+ * defined for ARM development platforms.
+ */
+#if ARM_BOARD_OPTIMISE_MMAP
+/*
+ * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the
+ * plat_arm_mmap array defined for each BL stage.
+ */
+#if IMAGE_BL1
+# define PLAT_ARM_MMAP_ENTRIES 7
+# define MAX_XLAT_TABLES 4
+#endif
+
+#if IMAGE_BL2
+# define PLAT_ARM_MMAP_ENTRIES 8
+# define MAX_XLAT_TABLES 3
+#endif
+
+#if IMAGE_BL2U
+# define PLAT_ARM_MMAP_ENTRIES 4
+# define MAX_XLAT_TABLES 3
+#endif
+
+#if IMAGE_BL31
+# define PLAT_ARM_MMAP_ENTRIES 5
+# define MAX_XLAT_TABLES 2
+#endif
+
+#if IMAGE_BL32
+# define PLAT_ARM_MMAP_ENTRIES 4
+# define MAX_XLAT_TABLES 3
+#endif
+
+#endif /* ARM_BOARD_OPTIMISE_MMAP */
/* CCI related constants */
#define PLAT_ARM_CCI_BASE 0x2c090000
#define PLAT_ARM_CCI_CLUSTER0_SL_IFACE_IX 4
#define PLAT_ARM_CCI_CLUSTER1_SL_IFACE_IX 3
+/* System timer related constants */
+#define PLAT_ARM_NSTIMER_FRAME_ID 1
+
/* TZC related constants */
+#define PLAT_ARM_TZC_BASE 0x2a4a0000
#define PLAT_ARM_TZC_NS_DEV_ACCESS ( \
TZC_REGION_ACCESS_RDWR(TZC400_NSAID_CCI400) | \
TZC_REGION_ACCESS_RDWR(TZC400_NSAID_PCIE) | \
@@ -99,6 +141,23 @@
#define PLAT_ARM_GICH_BASE 0x2c04f000
#define PLAT_ARM_GICV_BASE 0x2c06f000
+/* MHU related constants */
+#define PLAT_CSS_MHU_BASE 0x2b1f0000
+
+/*
+ * Base address of the first memory region used for communication between AP
+ * and SCP. Used by the BOM and SCPI protocols.
+ *
+ * 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
+ * 32-bit word on all CSS platforms. On Juno, part of this configuration is
+ * which CPU is the primary, according to the shift and mask definitions below.
+ */
+#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
+
/*
* Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
* terminology. On a GICv2 system or mode, the lists will be merged and treated
@@ -124,5 +183,30 @@
/* CSS SoC NIC-400 Global Programmers View (GPV) */
#define PLAT_SOC_CSS_NIC400_BASE 0x2a000000
+/*
+ * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
+ * plus a little space for growth.
+ */
+#if TRUSTED_BOARD_BOOT
+# define PLAT_ARM_MAX_BL1_RW_SIZE 0x9000
+#else
+# define PLAT_ARM_MAX_BL1_RW_SIZE 0x6000
+#endif
+
+/*
+ * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a
+ * little space for growth.
+ */
+#if TRUSTED_BOARD_BOOT
+# define PLAT_ARM_MAX_BL2_SIZE 0x1D000
+#else
+# define PLAT_ARM_MAX_BL2_SIZE 0xC000
+#endif
+
+/*
+ * PLAT_ARM_MAX_BL31_SIZE is calculated using the current BL31 debug size plus a
+ * little space for growth.
+ */
+#define PLAT_ARM_MAX_BL31_SIZE 0x1D000
#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/arm/board/juno/juno_def.h b/plat/arm/board/juno/juno_def.h
index 1f367f2..f27bbb2 100644
--- a/plat/arm/board/juno/juno_def.h
+++ b/plat/arm/board/juno/juno_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -50,6 +50,14 @@
#define PSRAM_BASE 0x14000000
#define PSRAM_SIZE 0x02000000
+#define JUNO_SSC_VER_PART_NUM 0x030
+
+/*******************************************************************************
+ * Juno topology related constants
+ ******************************************************************************/
+#define JUNO_CLUSTER_COUNT 2
+#define JUNO_CLUSTER0_CORE_COUNT 2
+#define JUNO_CLUSTER1_CORE_COUNT 4
/*******************************************************************************
* TZC-400 related constants
diff --git a/plat/arm/board/juno/juno_security.c b/plat/arm/board/juno/juno_security.c
index f9386ca..202342a 100644
--- a/plat/arm/board/juno/juno_security.c
+++ b/plat/arm/board/juno/juno_security.c
@@ -65,7 +65,7 @@
void plat_arm_security_setup(void)
{
/* Initialize the TrustZone Controller */
- arm_tzc_setup();
+ arm_tzc400_setup();
/* Do ARM CSS internal NIC setup */
css_init_nic400();
/* Do ARM CSS SoC security setup */
diff --git a/plat/arm/board/juno/juno_topology.c b/plat/arm/board/juno/juno_topology.c
new file mode 100644
index 0000000..ee4ec44
--- /dev/null
+++ b/plat/arm/board/juno/juno_topology.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arm_def.h>
+#include <plat_arm.h>
+#include "juno_def.h"
+
+/*
+ * On Juno, the system power level is the highest power level.
+ * The first entry in the power domain descriptor specifies the
+ * number of system power domains i.e. 1.
+ */
+#define JUNO_PWR_DOMAINS_AT_MAX_PWR_LVL ARM_SYSTEM_COUNT
+
+/*
+ * The Juno 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()
+ * i.e. CLUSTER1 CPUs are allocated indices from 0 to 3 and the higher
+ * indices for CLUSTER0 CPUs.
+ */
+const unsigned char juno_power_domain_tree_desc[] = {
+ /* No of root nodes */
+ JUNO_PWR_DOMAINS_AT_MAX_PWR_LVL,
+ /* No of children for the root node */
+ JUNO_CLUSTER_COUNT,
+ /* No of children for the first cluster node */
+ JUNO_CLUSTER1_CORE_COUNT,
+ /* No of children for the second cluster node */
+ JUNO_CLUSTER0_CORE_COUNT
+};
+
+/*******************************************************************************
+ * This function returns the Juno topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return juno_power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * 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 (((mpidr) & 0x100) ? JUNO_CLUSTER1_CORE_COUNT :\
+ JUNO_CLUSTER0_CORE_COUNT);
+}
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index fae30e7..4fda4ca 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
@@ -34,6 +34,14 @@
plat/common/plat_gicv2.c \
plat/arm/common/arm_gicv2.c
+JUNO_INTERCONNECT_SOURCES := drivers/arm/cci/cci.c \
+ plat/arm/common/arm_cci.c
+
+JUNO_SECURITY_SOURCES := drivers/arm/tzc/tzc400.c \
+ plat/arm/board/juno/juno_security.c \
+ plat/arm/common/arm_tzc400.c
+
+
PLAT_INCLUDES := -Iplat/arm/board/juno/include
PLAT_BL_COMMON_SOURCES := plat/arm/board/juno/aarch64/juno_helpers.S
@@ -42,30 +50,36 @@
lib/cpus/aarch64/cortex_a57.S \
lib/cpus/aarch64/cortex_a72.S \
plat/arm/board/juno/juno_bl1_setup.c \
- plat/arm/board/juno/juno_err.c
+ plat/arm/board/juno/juno_err.c \
+ ${JUNO_INTERCONNECT_SOURCES}
-BL2_SOURCES += plat/arm/board/juno/juno_security.c \
- plat/arm/board/juno/juno_err.c
+BL2_SOURCES += plat/arm/board/juno/juno_err.c \
+ ${JUNO_SECURITY_SOURCES}
-BL2U_SOURCES += plat/arm/board/juno/juno_security.c
+BL2U_SOURCES += ${JUNO_SECURITY_SOURCES}
BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \
lib/cpus/aarch64/cortex_a57.S \
lib/cpus/aarch64/cortex_a72.S \
plat/arm/board/juno/juno_pm.c \
- plat/arm/board/juno/juno_security.c \
- ${JUNO_GIC_SOURCES}
+ plat/arm/board/juno/juno_topology.c \
+ ${JUNO_GIC_SOURCES} \
+ ${JUNO_INTERCONNECT_SOURCES} \
+ ${JUNO_SECURITY_SOURCES}
# Enable workarounds for selected Cortex-A57 erratas.
-ERRATA_A57_806969 := 0
-ERRATA_A57_813420 := 1
+ERRATA_A57_806969 := 0
+ERRATA_A57_813420 := 1
# Enable option to skip L1 data cache flush during the Cortex-A57 cluster
# power down sequence
SKIP_A57_L1_FLUSH_PWR_DWN := 1
# Disable the PSCI platform compatibility layer
-ENABLE_PLAT_COMPAT := 0
+ENABLE_PLAT_COMPAT := 0
+
+# Enable memory map related constants optimisation
+ARM_BOARD_OPTIMISE_MMAP := 1
include plat/arm/board/common/board_css.mk
include plat/arm/common/arm_common.mk
diff --git a/plat/arm/board/juno/tsp/tsp-juno.mk b/plat/arm/board/juno/tsp/tsp-juno.mk
index 2ef964e..4e80607 100644
--- a/plat/arm/board/juno/tsp/tsp-juno.mk
+++ b/plat/arm/board/juno/tsp/tsp-juno.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
@@ -28,7 +28,8 @@
# POSSIBILITY OF SUCH DAMAGE.
#
-BL32_SOURCES += plat/arm/css/common/css_topology.c \
+BL32_SOURCES += plat/arm/board/juno/juno_topology.c \
+ plat/arm/css/common/css_topology.c \
${JUNO_GIC_SOURCES}
include plat/arm/common/tsp/arm_tsp.mk
diff --git a/plat/arm/common/aarch64/arm_common.c b/plat/arm/common/aarch64/arm_common.c
index a211f16..19a4931 100644
--- a/plat/arm/common/aarch64/arm_common.c
+++ b/plat/arm/common/aarch64/arm_common.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -29,20 +29,16 @@
*/
#include <arch.h>
#include <arch_helpers.h>
-#include <cci.h>
#include <mmio.h>
#include <plat_arm.h>
#include <platform_def.h>
#include <xlat_tables.h>
-
-static const int cci_map[] = {
- PLAT_ARM_CCI_CLUSTER0_SL_IFACE_IX,
- PLAT_ARM_CCI_CLUSTER1_SL_IFACE_IX
-};
+extern const mmap_region_t plat_arm_mmap[];
/* Weak definitions may be overridden in specific ARM standard platform */
#pragma weak plat_get_ns_image_entrypoint
+#pragma weak plat_arm_get_mmap
/*******************************************************************************
@@ -67,7 +63,7 @@
mmap_add_region(coh_start, coh_start, \
coh_limit - coh_start, \
MT_DEVICE | MT_RW | MT_SECURE); \
- mmap_add(plat_arm_mmap); \
+ mmap_add(plat_arm_get_mmap()); \
init_xlat_tables(); \
\
enable_mmu_el##_el(0); \
@@ -85,7 +81,7 @@
mmap_add_region(ro_start, ro_start, \
ro_limit - ro_start, \
MT_MEMORY | MT_RO | MT_SECURE); \
- mmap_add(plat_arm_mmap); \
+ mmap_add(plat_arm_get_mmap()); \
init_xlat_tables(); \
\
enable_mmu_el##_el(0); \
@@ -97,7 +93,7 @@
DEFINE_CONFIGURE_MMU_EL(3)
-unsigned long plat_get_ns_image_entrypoint(void)
+uintptr_t plat_get_ns_image_entrypoint(void)
{
return PLAT_ARM_NS_IMAGE_OFFSET;
}
@@ -138,12 +134,6 @@
return spsr;
}
-
-void arm_cci_init(void)
-{
- cci_init(PLAT_ARM_CCI_BASE, cci_map, ARRAY_SIZE(cci_map));
-}
-
/*******************************************************************************
* Configures access to the system counter timer module.
******************************************************************************/
@@ -161,3 +151,11 @@
reg_val = (1 << CNTNSAR_NS_SHIFT(PLAT_ARM_NSTIMER_FRAME_ID));
mmio_write_32(ARM_SYS_TIMCTL_BASE + CNTNSAR, reg_val);
}
+
+/*******************************************************************************
+ * Returns ARM platform specific memory map regions.
+ ******************************************************************************/
+const mmap_region_t *plat_arm_get_mmap(void)
+{
+ return plat_arm_mmap;
+}
diff --git a/plat/arm/common/arm_bl1_fwu.c b/plat/arm/common/arm_bl1_fwu.c
index 9a0d93a..2a18d34 100644
--- a/plat/arm/common/arm_bl1_fwu.c
+++ b/plat/arm/common/arm_bl1_fwu.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -33,11 +33,12 @@
#include <debug.h>
#include <errno.h>
#include <plat_arm.h>
+#include <platform_def.h>
#include <tbbr_img_desc.h>
/* Struct to keep track of usable memory */
-typedef struct bl1_mem_info{
+typedef struct bl1_mem_info {
uintptr_t mem_base;
unsigned int mem_size;
} bl1_mem_info_t;
@@ -58,8 +59,8 @@
.mem_size = ARM_NS_DRAM1_SIZE
},
{
- .mem_base = V2M_FLASH0_BASE,
- .mem_size = V2M_FLASH0_SIZE
+ .mem_base = PLAT_ARM_NVM_BASE,
+ .mem_size = PLAT_ARM_NVM_SIZE
},
{
.mem_size = 0
@@ -79,7 +80,7 @@
/*
* Check the given image source and size.
*/
- if (GET_SEC_STATE(flags) == SECURE)
+ if (GET_SECURITY_STATE(flags) == SECURE)
mmap = fwu_addr_map_secure;
else
mmap = fwu_addr_map_non_secure;
diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c
index d0a4c0b..951f48a 100644
--- a/plat/arm/common/arm_bl1_setup.c
+++ b/plat/arm/common/arm_bl1_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -31,7 +31,6 @@
#include <arch.h>
#include <arm_def.h>
#include <bl_common.h>
-#include <cci.h>
#include <console.h>
#include <platform_def.h>
#include <plat_arm.h>
@@ -101,14 +100,14 @@
arm_bl1_early_platform_setup();
/*
- * Initialize CCI for this cluster during cold boot.
+ * Initialize Interconnect for this cluster during cold boot.
* No need for locks as no other CPU is active.
*/
- arm_cci_init();
+ plat_arm_interconnect_init();
/*
- * Enable CCI coherency for the primary CPU's cluster.
+ * Enable Interconnect coherency for the primary CPU's cluster.
*/
- cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr()));
+ plat_arm_interconnect_enter_coherency();
}
/******************************************************************************
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index 97c2bca..a528830 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -96,11 +96,27 @@
#pragma weak bl2_plat_get_bl33_meminfo
#pragma weak bl2_plat_set_bl33_ep_info
+#if ARM_BL31_IN_DRAM
+meminfo_t *bl2_plat_sec_mem_layout(void)
+{
+ static meminfo_t bl2_dram_layout
+ __aligned(CACHE_WRITEBACK_GRANULE) = {
+ .total_base = BL31_BASE,
+ .total_size = (ARM_AP_TZC_DRAM1_BASE +
+ ARM_AP_TZC_DRAM1_SIZE) - BL31_BASE,
+ .free_base = BL31_BASE,
+ .free_size = (ARM_AP_TZC_DRAM1_BASE +
+ ARM_AP_TZC_DRAM1_SIZE) - BL31_BASE
+ };
+ return &bl2_dram_layout;
+}
+#else
meminfo_t *bl2_plat_sec_mem_layout(void)
{
return &bl2_tzram_layout;
}
+#endif
/*******************************************************************************
* This function assigns a pointer to the memory that the platform has kept
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index 6c58ff1..5cc8bfb 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -33,7 +33,6 @@
#include <arm_def.h>
#include <assert.h>
#include <bl_common.h>
-#include <cci.h>
#include <console.h>
#include <debug.h>
#include <mmio.h>
@@ -178,20 +177,20 @@
arm_bl31_early_platform_setup(from_bl2, plat_params_from_bl2);
/*
- * Initialize CCI for this cluster during cold boot.
+ * Initialize Interconnect for this cluster during cold boot.
* No need for locks as no other CPU is active.
*/
- arm_cci_init();
+ plat_arm_interconnect_init();
/*
- * Enable CCI coherency for the primary CPU's cluster.
+ * Enable Interconnect coherency for the primary CPU's cluster.
* Earlier bootloader stages might already do this (e.g. Trusted
* Firmware's BL1 does it) but we can't assume so. There is no harm in
* executing this code twice anyway.
* Platform specific PSCI code will enable coherency for other
* clusters.
*/
- cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr()));
+ plat_arm_interconnect_enter_coherency();
}
/*******************************************************************************
diff --git a/plat/arm/common/arm_cci.c b/plat/arm/common/arm_cci.c
new file mode 100644
index 0000000..41054c2
--- /dev/null
+++ b/plat/arm/common/arm_cci.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <cci.h>
+#include <plat_arm.h>
+#include <platform_def.h>
+
+static const int cci_map[] = {
+ PLAT_ARM_CCI_CLUSTER0_SL_IFACE_IX,
+ PLAT_ARM_CCI_CLUSTER1_SL_IFACE_IX
+};
+
+/******************************************************************************
+ * The following functions are defined as weak to allow a platform to override
+ * the way ARM CCI driver is initialised and used.
+ *****************************************************************************/
+#pragma weak plat_arm_interconnect_init
+#pragma weak plat_arm_interconnect_enter_coherency
+#pragma weak plat_arm_interconnect_exit_coherency
+
+
+/******************************************************************************
+ * Helper function to initialize ARM CCI driver.
+ *****************************************************************************/
+void plat_arm_interconnect_init(void)
+{
+ cci_init(PLAT_ARM_CCI_BASE, cci_map, ARRAY_SIZE(cci_map));
+}
+
+/******************************************************************************
+ * Helper function to place current master into coherency
+ *****************************************************************************/
+void plat_arm_interconnect_enter_coherency(void)
+{
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+}
+
+/******************************************************************************
+ * Helper function to remove current master from coherency
+ *****************************************************************************/
+void plat_arm_interconnect_exit_coherency(void)
+{
+ cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+}
diff --git a/plat/arm/common/arm_ccn.c b/plat/arm/common/arm_ccn.c
new file mode 100644
index 0000000..5cb443a
--- /dev/null
+++ b/plat/arm/common/arm_ccn.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <ccn.h>
+#include <plat_arm.h>
+#include <platform_def.h>
+
+static const unsigned char master_to_rn_id_map[] = {
+ PLAT_ARM_CLUSTER_TO_CCN_ID_MAP
+};
+
+static const ccn_desc_t arm_ccn_desc = {
+ .periphbase = PLAT_ARM_CCN_BASE,
+ .num_masters = ARRAY_SIZE(master_to_rn_id_map),
+ .master_to_rn_id_map = master_to_rn_id_map
+};
+
+/******************************************************************************
+ * The following functions are defined as weak to allow a platform to override
+ * the way ARM CCN driver is initialised and used.
+ *****************************************************************************/
+#pragma weak plat_arm_interconnect_init
+#pragma weak plat_arm_interconnect_enter_coherency
+#pragma weak plat_arm_interconnect_exit_coherency
+
+
+/******************************************************************************
+ * Helper function to initialize ARM CCN driver.
+ *****************************************************************************/
+void plat_arm_interconnect_init(void)
+{
+ ccn_init(&arm_ccn_desc);
+}
+
+/******************************************************************************
+ * Helper function to place current master into coherency
+ *****************************************************************************/
+void plat_arm_interconnect_enter_coherency(void)
+{
+ ccn_enter_snoop_dvm_domain(1 << MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+}
+
+/******************************************************************************
+ * Helper function to remove current master from coherency
+ *****************************************************************************/
+void plat_arm_interconnect_exit_coherency(void)
+{
+ ccn_exit_snoop_dvm_domain(1 << MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+}
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 3202735..973e583 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
@@ -77,6 +77,11 @@
$(eval $(call assert_boolean,ARM_CONFIG_CNTACR))
$(eval $(call add_define,ARM_CONFIG_CNTACR))
+# Process ARM_BL31_IN_DRAM flag
+ARM_BL31_IN_DRAM := 0
+$(eval $(call assert_boolean,ARM_BL31_IN_DRAM))
+$(eval $(call add_define,ARM_BL31_IN_DRAM))
+
PLAT_INCLUDES += -Iinclude/common/tbbr \
-Iinclude/plat/arm/common \
-Iinclude/plat/arm/common/aarch64
@@ -87,9 +92,7 @@
plat/arm/common/aarch64/arm_helpers.S \
plat/common/aarch64/plat_common.c
-BL1_SOURCES += drivers/arm/cci/cci.c \
- drivers/arm/ccn/ccn.c \
- drivers/arm/sp805/sp805.c \
+BL1_SOURCES += drivers/arm/sp805/sp805.c \
drivers/io/io_fip.c \
drivers/io/io_memmap.c \
drivers/io/io_storage.c \
@@ -102,26 +105,18 @@
BL1_SOURCES += plat/arm/common/arm_pm.c
endif
-BL2_SOURCES += drivers/arm/tzc400/tzc400.c \
- drivers/io/io_fip.c \
+BL2_SOURCES += drivers/io/io_fip.c \
drivers/io/io_memmap.c \
drivers/io/io_storage.c \
plat/arm/common/arm_bl2_setup.c \
plat/arm/common/arm_io_storage.c \
- plat/arm/common/arm_security.c \
plat/common/aarch64/platform_up_stack.S
-BL2U_SOURCES += drivers/arm/tzc400/tzc400.c \
- plat/arm/common/arm_bl2u_setup.c \
- plat/arm/common/arm_security.c \
+BL2U_SOURCES += plat/arm/common/arm_bl2u_setup.c \
plat/common/aarch64/platform_up_stack.S
-BL31_SOURCES += drivers/arm/cci/cci.c \
- drivers/arm/ccn/ccn.c \
- drivers/arm/tzc400/tzc400.c \
- plat/arm/common/arm_bl31_setup.c \
+BL31_SOURCES += plat/arm/common/arm_bl31_setup.c \
plat/arm/common/arm_pm.c \
- plat/arm/common/arm_security.c \
plat/arm/common/arm_topology.c \
plat/common/aarch64/platform_mp_stack.S \
plat/common/aarch64/plat_psci_common.c
@@ -139,8 +134,8 @@
PLAT_INCLUDES += -Iinclude/bl1/tbbr
- BL1_SOURCES += ${AUTH_SOURCES} \
- bl1/tbbr/tbbr_img_desc.c \
+ BL1_SOURCES += ${AUTH_SOURCES} \
+ bl1/tbbr/tbbr_img_desc.c \
plat/arm/common/arm_bl1_fwu.c
BL2_SOURCES += ${AUTH_SOURCES}
diff --git a/plat/arm/common/arm_pm.c b/plat/arm/common/arm_pm.c
index 2ddc583..1e756a9 100644
--- a/plat/arm/common/arm_pm.c
+++ b/plat/arm/common/arm_pm.c
@@ -192,11 +192,6 @@
assert((PLAT_ARM_TRUSTED_MAILBOX_BASE >= ARM_SHARED_RAM_BASE) &&
((PLAT_ARM_TRUSTED_MAILBOX_BASE + sizeof(*mailbox)) <= \
(ARM_SHARED_RAM_BASE + ARM_SHARED_RAM_SIZE)));
-
- /* Flush data cache if the mail box shared RAM is cached */
-#if PLAT_ARM_SHARED_RAM_CACHED
- flush_dcache_range((uintptr_t) mailbox, sizeof(*mailbox));
-#endif
}
/*******************************************************************************
diff --git a/plat/arm/common/arm_topology.c b/plat/arm/common/arm_topology.c
index cb0bb9c..4430b13 100644
--- a/plat/arm/common/arm_topology.c
+++ b/plat/arm/common/arm_topology.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -29,26 +29,9 @@
*/
#include <arch.h>
-#include <psci.h>
#include <plat_arm.h>
#include <platform_def.h>
-#define get_arm_cluster_core_count(mpidr)\
- (((mpidr) & 0x100) ? PLAT_ARM_CLUSTER1_CORE_COUNT :\
- PLAT_ARM_CLUSTER0_CORE_COUNT)
-
-/* The power domain tree descriptor which need to be exported by ARM platforms */
-extern const unsigned char arm_power_domain_tree_desc[];
-
-
-/*******************************************************************************
- * This function returns the ARM default topology tree information.
- ******************************************************************************/
-const unsigned char *plat_get_power_domain_tree_desc(void)
-{
- return arm_power_domain_tree_desc;
-}
-
/*******************************************************************************
* This function validates an MPIDR by checking whether it falls within the
* acceptable bounds. An error code (-1) is returned if an incorrect mpidr
@@ -66,12 +49,12 @@
cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
- if (cluster_id >= ARM_CLUSTER_COUNT)
+ if (cluster_id >= PLAT_ARM_CLUSTER_COUNT)
return -1;
/* Validate cpu_id by checking whether it represents a CPU in
one of the two clusters present on the platform. */
- if (cpu_id >= get_arm_cluster_core_count(mpidr))
+ if (cpu_id >= plat_arm_get_cluster_core_count(mpidr))
return -1;
return 0;
diff --git a/plat/arm/common/arm_security.c b/plat/arm/common/arm_tzc400.c
similarity index 88%
rename from plat/arm/common/arm_security.c
rename to plat/arm/common/arm_tzc400.c
index 8b46aae..3962940 100644
--- a/plat/arm/common/arm_security.c
+++ b/plat/arm/common/arm_tzc400.c
@@ -48,53 +48,53 @@
* When booting an EL3 payload, this is simplified: we configure region 0 with
* secure access only and do not enable any other region.
******************************************************************************/
-void arm_tzc_setup(void)
+void arm_tzc400_setup(void)
{
INFO("Configuring TrustZone Controller\n");
- tzc_init(PLAT_ARM_TZC_BASE);
+ tzc400_init(PLAT_ARM_TZC_BASE);
/* Disable filters. */
- tzc_disable_filters();
+ tzc400_disable_filters();
#ifndef EL3_PAYLOAD_BASE
/* Region 0 set to no access by default */
- tzc_configure_region0(TZC_REGION_S_NONE, 0);
+ tzc400_configure_region0(TZC_REGION_S_NONE, 0);
/* Region 1 set to cover Secure part of DRAM */
- tzc_configure_region(PLAT_ARM_TZC_FILTERS, 1,
+ tzc400_configure_region(PLAT_ARM_TZC_FILTERS, 1,
ARM_AP_TZC_DRAM1_BASE, ARM_AP_TZC_DRAM1_END,
TZC_REGION_S_RDWR,
0);
/* Region 2 set to cover Non-Secure access to 1st DRAM address range.
* Apply the same configuration to given filters in the TZC. */
- tzc_configure_region(PLAT_ARM_TZC_FILTERS, 2,
+ tzc400_configure_region(PLAT_ARM_TZC_FILTERS, 2,
ARM_NS_DRAM1_BASE, ARM_NS_DRAM1_END,
TZC_REGION_S_NONE,
PLAT_ARM_TZC_NS_DEV_ACCESS);
/* Region 3 set to cover Non-Secure access to 2nd DRAM address range */
- tzc_configure_region(PLAT_ARM_TZC_FILTERS, 3,
+ tzc400_configure_region(PLAT_ARM_TZC_FILTERS, 3,
ARM_DRAM2_BASE, ARM_DRAM2_END,
TZC_REGION_S_NONE,
PLAT_ARM_TZC_NS_DEV_ACCESS);
#else
/* Allow secure access only to DRAM for EL3 payloads. */
- tzc_configure_region0(TZC_REGION_S_RDWR, 0);
+ tzc400_configure_region0(TZC_REGION_S_RDWR, 0);
#endif /* EL3_PAYLOAD_BASE */
/*
* Raise an exception if a NS device tries to access secure memory
* TODO: Add interrupt handling support.
*/
- tzc_set_action(TZC_ACTION_ERR);
+ tzc400_set_action(TZC_ACTION_ERR);
/* Enable filters. */
- tzc_enable_filters();
+ tzc400_enable_filters();
}
void plat_arm_security_setup(void)
{
- arm_tzc_setup();
+ arm_tzc400_setup();
}
diff --git a/plat/arm/common/arm_security.c b/plat/arm/common/arm_tzc_dmc500.c
similarity index 61%
copy from plat/arm/common/arm_security.c
copy to plat/arm/common/arm_tzc_dmc500.c
index 8b46aae..f0ed9a6 100644
--- a/plat/arm/common/arm_security.c
+++ b/plat/arm/common/arm_tzc_dmc500.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -29,72 +29,72 @@
*/
#include <arm_def.h>
+#include <assert.h>
#include <debug.h>
#include <platform_def.h>
-#include <tzc400.h>
-
-
-/* Weak definitions may be overridden in specific ARM standard platform */
-#pragma weak plat_arm_security_setup
-
+#include <tzc_dmc500.h>
/*******************************************************************************
- * Initialize the TrustZone Controller for ARM standard platforms.
- * Configure:
- * - Region 0 with no access;
- * - Region 1 with secure access only;
- * - the remaining DRAM regions access from the given Non-Secure masters.
+ * Initialize the DMC500-TrustZone Controller for ARM standard platforms.
+ * Configure both the interfaces on Region 0 with no access, Region 1 with
+ * secure access only, and the remaining DRAM regions access from the
+ * given Non-Secure masters.
*
* When booting an EL3 payload, this is simplified: we configure region 0 with
* secure access only and do not enable any other region.
******************************************************************************/
-void arm_tzc_setup(void)
+void arm_tzc_dmc500_setup(tzc_dmc500_driver_data_t *plat_driver_data)
{
- INFO("Configuring TrustZone Controller\n");
+ assert(plat_driver_data);
- tzc_init(PLAT_ARM_TZC_BASE);
+ INFO("Configuring DMC-500 TZ Settings\n");
- /* Disable filters. */
- tzc_disable_filters();
+ tzc_dmc500_driver_init(plat_driver_data);
#ifndef EL3_PAYLOAD_BASE
/* Region 0 set to no access by default */
- tzc_configure_region0(TZC_REGION_S_NONE, 0);
+ tzc_dmc500_configure_region0(TZC_REGION_S_NONE, 0);
/* Region 1 set to cover Secure part of DRAM */
- tzc_configure_region(PLAT_ARM_TZC_FILTERS, 1,
- ARM_AP_TZC_DRAM1_BASE, ARM_AP_TZC_DRAM1_END,
- TZC_REGION_S_RDWR,
- 0);
+ tzc_dmc500_configure_region(1, ARM_AP_TZC_DRAM1_BASE,
+ ARM_AP_TZC_DRAM1_END,
+ TZC_REGION_S_RDWR,
+ 0);
- /* Region 2 set to cover Non-Secure access to 1st DRAM address range.
- * Apply the same configuration to given filters in the TZC. */
- tzc_configure_region(PLAT_ARM_TZC_FILTERS, 2,
- ARM_NS_DRAM1_BASE, ARM_NS_DRAM1_END,
- TZC_REGION_S_NONE,
- PLAT_ARM_TZC_NS_DEV_ACCESS);
+ /* Region 2 set to cover Non-Secure access to 1st DRAM address range.*/
+ tzc_dmc500_configure_region(2,
+ ARM_NS_DRAM1_BASE,
+ ARM_NS_DRAM1_END,
+ TZC_REGION_S_NONE,
+ PLAT_ARM_TZC_NS_DEV_ACCESS);
/* Region 3 set to cover Non-Secure access to 2nd DRAM address range */
- tzc_configure_region(PLAT_ARM_TZC_FILTERS, 3,
- ARM_DRAM2_BASE, ARM_DRAM2_END,
- TZC_REGION_S_NONE,
- PLAT_ARM_TZC_NS_DEV_ACCESS);
+ tzc_dmc500_configure_region(3,
+ ARM_DRAM2_BASE,
+ ARM_DRAM2_END,
+ TZC_REGION_S_NONE,
+ PLAT_ARM_TZC_NS_DEV_ACCESS);
#else
- /* Allow secure access only to DRAM for EL3 payloads. */
- tzc_configure_region0(TZC_REGION_S_RDWR, 0);
-#endif /* EL3_PAYLOAD_BASE */
-
+ /* Allow secure access only to DRAM for EL3 payloads */
+ tzc_dmc500_configure_region0(TZC_REGION_S_RDWR, 0);
+#endif
/*
* Raise an exception if a NS device tries to access secure memory
* TODO: Add interrupt handling support.
*/
- tzc_set_action(TZC_ACTION_ERR);
+ tzc_dmc500_set_action(TZC_ACTION_RV_LOWERR);
- /* Enable filters. */
- tzc_enable_filters();
-}
+ /*
+ * Flush the configuration settings to have an affect. Validate
+ * flush by checking FILTER_EN is set on region 1 attributes
+ * register.
+ */
+ tzc_dmc500_config_complete();
-void plat_arm_security_setup(void)
-{
- arm_tzc_setup();
+ /*
+ * Wait for the flush to complete.
+ * TODO: Have a timeout for this loop
+ */
+ while (tzc_dmc500_verify_complete())
+ ;
}
diff --git a/plat/arm/css/common/aarch64/css_helpers.S b/plat/arm/css/common/aarch64/css_helpers.S
index 2747618..0763a3e 100644
--- a/plat/arm/css/common/aarch64/css_helpers.S
+++ b/plat/arm/css/common/aarch64/css_helpers.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -117,7 +117,8 @@
bl plat_my_core_pos
ldr x1, =SCP_BOOT_CFG_ADDR
ldr x1, [x1]
- ubfx x1, x1, #PRIMARY_CPU_SHIFT, #PRIMARY_CPU_BIT_WIDTH
+ ubfx x1, x1, #PLAT_CSS_PRIMARY_CPU_SHIFT, \
+ #PLAT_CSS_PRIMARY_CPU_BIT_WIDTH
cmp x0, x1
cset w0, eq
ret x9
diff --git a/plat/arm/css/common/css_common.mk b/plat/arm/css/common/css_common.mk
index 6a8773d..65e125e 100644
--- a/plat/arm/css/common/css_common.mk
+++ b/plat/arm/css/common/css_common.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
@@ -28,6 +28,10 @@
# POSSIBILITY OF SUCH DAMAGE.
#
+
+# By default, SCP images are needed by CSS platforms.
+CSS_LOAD_SCP_IMAGES ?= 1
+
PLAT_INCLUDES += -Iinclude/plat/arm/css/common \
-Iinclude/plat/arm/css/common/aarch64
@@ -38,12 +42,10 @@
BL2_SOURCES += plat/arm/css/common/css_bl2_setup.c \
plat/arm/css/common/css_mhu.c \
- plat/arm/css/common/css_scp_bootloader.c \
plat/arm/css/common/css_scpi.c
BL2U_SOURCES += plat/arm/css/common/css_bl2u_setup.c \
plat/arm/css/common/css_mhu.c \
- plat/arm/css/common/css_scp_bootloader.c \
plat/arm/css/common/css_scpi.c
BL31_SOURCES += plat/arm/css/common/css_mhu.c \
@@ -51,17 +53,25 @@
plat/arm/css/common/css_scpi.c \
plat/arm/css/common/css_topology.c
-ifneq (${TRUSTED_BOARD_BOOT},0)
-$(eval $(call FWU_FIP_ADD_IMG,SCP_BL2U,--scp-fwu-cfg))
-endif
ifneq (${RESET_TO_BL31},0)
$(error "Using BL31 as the reset vector is not supported on CSS platforms. \
Please set RESET_TO_BL31 to 0.")
endif
-# Subsystems require a SCP_BL2 image
-$(eval $(call FIP_ADD_IMG,SCP_BL2,--scp-fw))
+# Process CSS_LOAD_SCP_IMAGES flag
+$(eval $(call assert_boolean,CSS_LOAD_SCP_IMAGES))
+$(eval $(call add_define,CSS_LOAD_SCP_IMAGES))
+
+ifeq (${CSS_LOAD_SCP_IMAGES},1)
+ $(eval $(call FIP_ADD_IMG,SCP_BL2,--scp-fw))
+ ifneq (${TRUSTED_BOARD_BOOT},0)
+ $(eval $(call FWU_FIP_ADD_IMG,SCP_BL2U,--scp-fwu-cfg))
+ endif
+
+ BL2U_SOURCES += plat/arm/css/common/css_scp_bootloader.c
+ BL2_SOURCES += plat/arm/css/common/css_scp_bootloader.c
+endif
# Enable option to detect whether the SCP ROM firmware in use predates version
# 1.7.0 and therefore, is incompatible.
diff --git a/plat/arm/css/common/css_mhu.c b/plat/arm/css/common/css_mhu.c
index b1714e2..265d6c2 100644
--- a/plat/arm/css/common/css_mhu.c
+++ b/plat/arm/css/common/css_mhu.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -33,6 +33,7 @@
#include <bakery_lock.h>
#include <css_def.h>
#include <mmio.h>
+#include <platform_def.h>
#include <plat_arm.h>
#include "css_mhu.h"
@@ -66,24 +67,26 @@
arm_lock_get();
/* Make sure any previous command has finished */
- while (mmio_read_32(MHU_BASE + CPU_INTR_S_STAT) & (1 << slot_id))
+ while (mmio_read_32(PLAT_CSS_MHU_BASE + CPU_INTR_S_STAT) &
+ (1 << slot_id))
;
}
void mhu_secure_message_send(unsigned int slot_id)
{
assert(slot_id <= MHU_MAX_SLOT_ID);
- assert(!(mmio_read_32(MHU_BASE + CPU_INTR_S_STAT) & (1 << slot_id)));
+ assert(!(mmio_read_32(PLAT_CSS_MHU_BASE + CPU_INTR_S_STAT) &
+ (1 << slot_id)));
/* Send command to SCP */
- mmio_write_32(MHU_BASE + CPU_INTR_S_SET, 1 << slot_id);
+ mmio_write_32(PLAT_CSS_MHU_BASE + CPU_INTR_S_SET, 1 << slot_id);
}
uint32_t mhu_secure_message_wait(void)
{
/* Wait for response from SCP */
uint32_t response;
- while (!(response = mmio_read_32(MHU_BASE + SCP_INTR_S_STAT)))
+ while (!(response = mmio_read_32(PLAT_CSS_MHU_BASE + SCP_INTR_S_STAT)))
;
return response;
@@ -97,7 +100,7 @@
* Clear any response we got by writing one in the relevant slot bit to
* the CLEAR register
*/
- mmio_write_32(MHU_BASE + SCP_INTR_S_CLEAR, 1 << slot_id);
+ mmio_write_32(PLAT_CSS_MHU_BASE + SCP_INTR_S_CLEAR, 1 << slot_id);
arm_lock_release();
}
@@ -111,7 +114,7 @@
* as a stale or garbage value would make us think it's a message we've
* already sent.
*/
- assert(mmio_read_32(MHU_BASE + CPU_INTR_S_STAT) == 0);
+ assert(mmio_read_32(PLAT_CSS_MHU_BASE + CPU_INTR_S_STAT) == 0);
}
void plat_arm_pwrc_setup(void)
diff --git a/plat/arm/css/common/css_pm.c b/plat/arm/css/common/css_pm.c
index 6d6646e..b6f94ac 100644
--- a/plat/arm/css/common/css_pm.c
+++ b/plat/arm/css/common/css_pm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -31,7 +31,6 @@
#include <arch_helpers.h>
#include <assert.h>
#include <cassert.h>
-#include <cci.h>
#include <css_pm.h>
#include <debug.h>
#include <errno.h>
@@ -108,7 +107,7 @@
* if this cluster was off.
*/
if (CSS_CLUSTER_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF)
- cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+ plat_arm_interconnect_enter_coherency();
}
/*******************************************************************************
@@ -153,7 +152,7 @@
/* Cluster is to be turned off, so disable coherency */
if (CSS_CLUSTER_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) {
- cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr()));
+ plat_arm_interconnect_exit_coherency();
cluster_state = scpi_power_off;
}
diff --git a/plat/arm/css/common/css_scp_bootloader.c b/plat/arm/css/common/css_scp_bootloader.c
index c01f42f..d3f671e 100644
--- a/plat/arm/css/common/css_scp_bootloader.c
+++ b/plat/arm/css/common/css_scp_bootloader.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -60,7 +60,7 @@
* Unlike the SCPI protocol, the boot protocol uses the same memory region
* for both AP -> SCP and SCP -> AP transfers; define the address of this...
*/
-#define BOM_SHARED_MEM SCP_COM_SHARED_MEM_BASE
+#define BOM_SHARED_MEM PLAT_CSS_SCP_COM_SHARED_MEM_BASE
#define BOM_CMD_HEADER ((bom_cmd_t *) BOM_SHARED_MEM)
#define BOM_CMD_PAYLOAD ((void *) (BOM_SHARED_MEM + sizeof(bom_cmd_t)))
@@ -77,10 +77,10 @@
static void scp_boot_message_send(size_t payload_size)
{
- /* Make sure payload can be seen by SCP */
- if (MHU_PAYLOAD_CACHED)
- flush_dcache_range(BOM_SHARED_MEM,
- sizeof(bom_cmd_t) + payload_size);
+ /* Ensure that any write to the BOM payload area is seen by SCP before
+ * we write to the MHU register. If these 2 writes were reordered by
+ * the CPU then SCP would read stale payload data */
+ dmbst();
/* Send command to SCP */
mhu_secure_message_send(BOM_MHU_SLOT_ID);
@@ -99,9 +99,10 @@
panic();
}
- /* Make sure we see the reply from the SCP and not any stale data */
- if (MHU_PAYLOAD_CACHED)
- inv_dcache_range(BOM_SHARED_MEM, size);
+ /* Ensure that any read to the BOM payload area is done after reading
+ * the MHU register. If these 2 reads were reordered then the CPU would
+ * read invalid payload data */
+ dmbld();
return *(uint32_t *) BOM_SHARED_MEM;
}
diff --git a/plat/arm/css/common/css_scpi.c b/plat/arm/css/common/css_scpi.c
index 0a4eafe..02d573c 100644
--- a/plat/arm/css/common/css_scpi.c
+++ b/plat/arm/css/common/css_scpi.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -37,8 +37,9 @@
#include "css_mhu.h"
#include "css_scpi.h"
-#define SCPI_SHARED_MEM_SCP_TO_AP SCP_COM_SHARED_MEM_BASE
-#define SCPI_SHARED_MEM_AP_TO_SCP (SCP_COM_SHARED_MEM_BASE + 0x100)
+#define SCPI_SHARED_MEM_SCP_TO_AP PLAT_CSS_SCP_COM_SHARED_MEM_BASE
+#define SCPI_SHARED_MEM_AP_TO_SCP (PLAT_CSS_SCP_COM_SHARED_MEM_BASE \
+ + 0x100)
#define SCPI_CMD_HEADER_AP_TO_SCP \
((scpi_cmd_t *) SCPI_SHARED_MEM_AP_TO_SCP)
@@ -55,10 +56,10 @@
static void scpi_secure_message_send(size_t payload_size)
{
- /* Make sure payload can be seen by SCP */
- if (MHU_PAYLOAD_CACHED)
- flush_dcache_range(SCPI_SHARED_MEM_AP_TO_SCP,
- sizeof(scpi_cmd_t) + payload_size);
+ /* Ensure that any write to the SCPI payload area is seen by SCP before
+ * we write to the MHU register. If these 2 writes were reordered by
+ * the CPU then SCP would read stale payload data */
+ dmbst();
mhu_secure_message_send(SCPI_MHU_SLOT_ID);
}
@@ -78,9 +79,10 @@
panic();
}
- /* Make sure we don't read stale data */
- if (MHU_PAYLOAD_CACHED)
- inv_dcache_range(SCPI_SHARED_MEM_SCP_TO_AP, sizeof(*cmd));
+ /* Ensure that any read to the SCPI payload area is done after reading
+ * the MHU register. If these 2 reads were reordered then the CPU would
+ * read invalid payload data */
+ dmbld();
memcpy(cmd, (void *) SCPI_SHARED_MEM_SCP_TO_AP, sizeof(*cmd));
}
diff --git a/plat/arm/css/common/css_scpi.h b/plat/arm/css/common/css_scpi.h
index 379a821..4a601f3 100644
--- a/plat/arm/css/common/css_scpi.h
+++ b/plat/arm/css/common/css_scpi.h
@@ -45,7 +45,7 @@
uint32_t set : 1;
/* Sender ID to match a reply. The value is sender specific. */
uint32_t sender : 8;
- /* Size of the payload in bytes (0 – 511) */
+ /* Size of the payload in bytes (0 - 511) */
uint32_t size : 9;
uint32_t reserved : 7;
/*
diff --git a/plat/arm/css/common/css_topology.c b/plat/arm/css/common/css_topology.c
index 03f81e6..d5f0275 100644
--- a/plat/arm/css/common/css_topology.c
+++ b/plat/arm/css/common/css_topology.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -30,33 +30,6 @@
#include <plat_arm.h>
-/*
- * On ARM CSS platforms, by default, the system power level is treated as the
- * highest. The first entry in the power domain descriptor specifies the
- * number of system power domains i.e. 1.
- */
-#define CSS_PWR_DOMAINS_AT_MAX_PWR_LVL ARM_SYSTEM_COUNT
-
-/*
- * The CSS power domain tree descriptor for dual cluster CSS platforms.
- * 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() i.e. CLUSTER1 CPUs are allocated indices
- * from 0 to 3 and the higher indices for CLUSTER0 CPUs.
- */
-const unsigned char arm_power_domain_tree_desc[] = {
- /* No of root nodes */
- CSS_PWR_DOMAINS_AT_MAX_PWR_LVL,
- /* No of children for the root node */
- ARM_CLUSTER_COUNT,
- /* No of children for the first cluster node */
- PLAT_ARM_CLUSTER1_CORE_COUNT,
- /* No of children for the second cluster node */
- PLAT_ARM_CLUSTER0_CORE_COUNT
-};
-
-
/******************************************************************************
* 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
diff --git a/plat/common/aarch64/platform_helpers.S b/plat/common/aarch64/platform_helpers.S
index 29f01ce..0863830 100644
--- a/plat/common/aarch64/platform_helpers.S
+++ b/plat/common/aarch64/platform_helpers.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -39,6 +39,7 @@
.weak plat_disable_acp
.weak bl1_plat_prepare_exit
.weak plat_error_handler
+ .weak plat_panic_handler
#if !ENABLE_PLAT_COMPAT
.globl platform_get_core_pos
@@ -131,3 +132,12 @@
func plat_error_handler
b plat_error_handler
endfunc plat_error_handler
+
+ /* -----------------------------------------------------
+ * void plat_panic_handler(void) __dead2;
+ * Endless loop by default.
+ * -----------------------------------------------------
+ */
+func plat_panic_handler
+ b plat_panic_handler
+endfunc plat_panic_handler
diff --git a/plat/mediatek/mt8173/aarch64/platform_common.c b/plat/mediatek/mt8173/aarch64/platform_common.c
index b537f7b..23116f5 100644
--- a/plat/mediatek/mt8173/aarch64/platform_common.c
+++ b/plat/mediatek/mt8173/aarch64/platform_common.c
@@ -44,7 +44,7 @@
/* Table of regions to map using the MMU. */
const mmap_region_t plat_mmap[] = {
/* for TF text, RO, RW */
- MAP_REGION_FLAT(TZRAM_BASE, TZRAM_SIZE + TZRAM2_SIZE,
+ MAP_REGION_FLAT(TZRAM_BASE, TZRAM_SIZE,
MT_MEMORY | MT_RW | MT_SECURE),
MAP_REGION_FLAT(MTK_DEV_RNG0_BASE, MTK_DEV_RNG0_SIZE,
MT_DEVICE | MT_RW | MT_SECURE),
diff --git a/plat/mediatek/mt8173/bl31_plat_setup.c b/plat/mediatek/mt8173/bl31_plat_setup.c
index ec95143..749009e 100644
--- a/plat/mediatek/mt8173/bl31_plat_setup.c
+++ b/plat/mediatek/mt8173/bl31_plat_setup.c
@@ -50,13 +50,15 @@
unsigned long __COHERENT_RAM_END__;
/*
- * The next 2 constants identify the extents of the code & RO data region.
- * These addresses are used by the MMU setup code and therefore they must be
- * page-aligned. It is the responsibility of the linker script to ensure that
- * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses.
+ * The next 3 constants identify the extents of the code, RO data region and the
+ * limit of the BL31 image. These addresses are used by the MMU setup code and
+ * therefore they must be page-aligned. It is the responsibility of the linker
+ * script to ensure that __RO_START__, __RO_END__ & __BL31_END__ linker symbols
+ * refer to page-aligned addresses.
*/
#define BL31_RO_BASE (unsigned long)(&__RO_START__)
#define BL31_RO_LIMIT (unsigned long)(&__RO_END__)
+#define BL31_END (unsigned long)(&__BL31_END__)
/*
* The next 2 constants identify the extents of the coherent memory region.
@@ -108,6 +110,13 @@
MCU_BUS_DCM_EN);
}
+static void platform_setup_sram(void)
+{
+ /* protect BL31 memory from non-secure read/write access */
+ mmio_write_32(SRAMROM_SEC_ADDR, (uint32_t)(BL31_END + 0x3ff) & 0x3fc00);
+ mmio_write_32(SRAMROM_SEC_CTRL, 0x10000ff9);
+}
+
/*******************************************************************************
* 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
@@ -146,8 +155,6 @@
assert(from_bl2->h.type == PARAM_BL31);
assert(from_bl2->h.version >= VERSION_1);
- assert(((unsigned long)plat_params_from_bl2) == MT_BL31_PLAT_PARAM_VAL);
-
bl32_ep_info = *from_bl2->bl32_ep_info;
bl33_ep_info = *from_bl2->bl33_ep_info;
}
@@ -158,6 +165,7 @@
void bl31_platform_setup(void)
{
platform_setup_cpu();
+ platform_setup_sram();
plat_delay_timer_init();
diff --git a/plat/mediatek/mt8173/drivers/gpio/gpio.c b/plat/mediatek/mt8173/drivers/gpio/gpio.c
deleted file mode 100644
index 20473b9..0000000
--- a/plat/mediatek/mt8173/drivers/gpio/gpio.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without specific
- * prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#include <debug.h>
-#include <gpio.h>
-#include <mmio.h>
-#include <mt8173_def.h>
-#include <pmic_wrap_init.h>
-
-enum {
- MAX_GPIO_REG_BITS = 16,
-};
-
-struct mt_gpio_obj {
- struct gpio_regs *reg;
-};
-
-static struct mt_gpio_obj gpio_dat = {
- .reg = (struct gpio_regs *)(GPIO_BASE),
-};
-
-static struct mt_gpio_obj *gpio_obj = &gpio_dat;
-
-struct mt_gpioext_obj {
- struct gpioext_regs *reg;
-};
-
-static struct mt_gpioext_obj gpioext_dat = {
- .reg = (struct gpioext_regs *)(GPIOEXT_BASE),
-};
-
-static struct mt_gpioext_obj *gpioext_obj = &gpioext_dat;
-
-static inline struct mt_gpio_obj *mt_get_gpio_obj(void)
-{
- return gpio_obj;
-}
-
-static inline struct mt_gpioext_obj *mt_get_gpioext_obj(void)
-{
- return gpioext_obj;
-}
-
-enum {
- GPIO_PRO_DIR = 0,
- GPIO_PRO_DOUT,
- GPIO_PRO_DIN,
- GPIO_PRO_PULLEN,
- GPIO_PRO_PULLSEL,
- GPIO_PRO_MODE,
- GPIO_PRO_MAX,
-};
-
-static inline int32_t gpioext_write(uint16_t *addr, int64_t data)
-{
- return pwrap_write((uint32_t)(uintptr_t)addr, data);
-}
-
-static inline int32_t gpioext_set_bits(uint32_t bit, uint16_t *reg)
-{
- return gpioext_write(reg, bit);
-}
-
-static int32_t mt_set_gpio_chip(uint32_t pin, uint32_t property, uint32_t val)
-{
- uint32_t pos = 0;
- uint32_t bit = 0;
- struct mt_gpio_obj *obj = mt_get_gpio_obj();
- uint16_t *reg;
- uint32_t data = 0;
-
- if (!obj)
- return -ERACCESS;
-
- if (pin >= GPIO_EXTEND_START)
- return -ERINVAL;
-
- if (property >= GPIO_PRO_MAX)
- return -ERINVAL;
-
- pos = pin / MAX_GPIO_REG_BITS;
- bit = pin % MAX_GPIO_REG_BITS;
- data = 1L << bit;
-
- switch (property) {
- case GPIO_PRO_DIR:
- if (val == GPIO_DIR_IN)
- reg = &obj->reg->dir[pos].rst;
- else
- reg = &obj->reg->dir[pos].set;
- break;
- case GPIO_PRO_DOUT:
- if (val == GPIO_OUT_ZERO)
- reg = &obj->reg->dout[pos].rst;
- else
- reg = &obj->reg->dout[pos].set;
- break;
- default:
- return -ERINVAL;
- }
-
- mmio_write_16((uintptr_t)reg, data);
-
- return RSUCCESS;
-}
-
-static int32_t mt_set_gpio_ext(uint32_t pin, uint32_t property, uint32_t val)
-{
- uint32_t pos = 0;
- uint32_t bit = 0;
- struct mt_gpioext_obj *obj = mt_get_gpioext_obj();
- uint16_t *reg;
- uint32_t data = 0;
- int ret = 0;
-
- if (!obj)
- return -ERACCESS;
-
- if (pin >= MAX_GPIO_PIN)
- return -ERINVAL;
-
- if (property >= GPIO_PRO_MAX)
- return -ERINVAL;
-
- pin -= GPIO_EXTEND_START;
- pos = pin / MAX_GPIO_REG_BITS;
- bit = pin % MAX_GPIO_REG_BITS;
-
- switch (property) {
- case GPIO_PRO_DIR:
- if (val == GPIO_DIR_IN)
- reg = &obj->reg->dir[pos].rst;
- else
- reg = &obj->reg->dir[pos].set;
- break;
- case GPIO_PRO_DOUT:
- if (val == GPIO_OUT_ZERO)
- reg = &obj->reg->dout[pos].rst;
- else
- reg = &obj->reg->dout[pos].set;
- break;
- default:
- return -ERINVAL;
- }
- data = (1L << bit);
- ret = gpioext_set_bits(data, reg);
-
- return ret ? -ERWRAPPER : RSUCCESS;
-}
-
-static void mt_gpio_pin_decrypt(uint32_t *cipher)
-{
- if ((*cipher & (0x80000000)) == 0)
- INFO("Pin %u decrypt warning!\n", *cipher);
- *cipher &= ~(0x80000000);
-}
-
-int32_t mt_set_gpio_out(uint32_t pin, uint32_t output)
-{
- uint32_t gp = GPIO_PRO_DOUT;
-
- mt_gpio_pin_decrypt(&pin);
-
- return (pin >= GPIO_EXTEND_START) ?
- mt_set_gpio_ext(pin, gp, output) :
- mt_set_gpio_chip(pin, gp, output);
-}
-
-void gpio_set(uint32_t gpio, int32_t value)
-{
- mt_set_gpio_out(gpio, value);
-}
diff --git a/plat/mediatek/mt8173/drivers/gpio/gpio.h b/plat/mediatek/mt8173/drivers/gpio/gpio.h
deleted file mode 100644
index ccc99e1..0000000
--- a/plat/mediatek/mt8173/drivers/gpio/gpio.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without specific
- * prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef __PLAT_DRIVER_GPIO_H__
-#define __PLAT_DRIVER_GPIO_H__
-
-#include <stdint.h>
-
-enum {
- GPIOEXT_BASE = 0xC000,
-};
-
-/* Error Code No. */
-enum {
- RSUCCESS = 0,
- ERACCESS,
- ERINVAL,
- ERWRAPPER,
-};
-
-enum {
- GPIO_UNSUPPORTED = -1,
-
- GPIO0, GPIO1, GPIO2, GPIO3, GPIO4, GPIO5, GPIO6, GPIO7,
- GPIO8, GPIO9, GPIO10, GPIO11, GPIO12, GPIO13, GPIO14, GPIO15,
- GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22, GPIO23,
- GPIO24, GPIO25, GPIO26, GPIO27, GPIO28, GPIO29, GPIO30, GPIO31,
- GPIO32, GPIO33, GPIO34, GPIO35, GPIO36, GPIO37, GPIO38, GPIO39,
- GPIO40, GPIO41, GPIO42, GPIO43, GPIO44, GPIO45, GPIO46, GPIO47,
- GPIO48, GPIO49, GPIO50, GPIO51, GPIO52, GPIO53, GPIO54, GPIO55,
- GPIO56, GPIO57, GPIO58, GPIO59, GPIO60, GPIO61, GPIO62, GPIO63,
- GPIO64, GPIO65, GPIO66, GPIO67, GPIO68, GPIO69, GPIO70, GPIO71,
- GPIO72, GPIO73, GPIO74, GPIO75, GPIO76, GPIO77, GPIO78, GPIO79,
- GPIO80, GPIO81, GPIO82, GPIO83, GPIO84, GPIO85, GPIO86, GPIO87,
- GPIO88, GPIO89, GPIO90, GPIO91, GPIO92, GPIO93, GPIO94, GPIO95,
- GPIO96, GPIO97, GPIO98, GPIO99, GPIO100, GPIO101, GPIO102, GPIO103,
- GPIO104, GPIO105, GPIO106, GPIO107, GPIO108, GPIO109, GPIO110, GPIO111,
- GPIO112, GPIO113, GPIO114, GPIO115, GPIO116, GPIO117, GPIO118, GPIO119,
- GPIO120, GPIO121, GPIO122, GPIO123, GPIO124, GPIO125, GPIO126, GPIO127,
- GPIO128, GPIO129, GPIO130, GPIO131, GPIO132, GPIO133, GPIO134,
-
- GPIOEXT0, GPIOEXT1, GPIOEXT2, GPIOEXT3, GPIOEXT4, GPIOEXT5,
- GPIOEXT6, GPIOEXT7, GPIOEXT8, GPIOEXT9, GPIOEXT10, GPIOEXT11,
- GPIOEXT12, GPIOEXT13, GPIOEXT14, GPIOEXT15, GPIOEXT16, GPIOEXT17,
- GPIOEXT18, GPIOEXT19, GPIOEXT20, GPIOEXT21, GPIOEXT22, GPIOEXT23,
- GPIOEXT24, GPIOEXT25, GPIOEXT26, GPIOEXT27, GPIOEXT28, GPIOEXT29,
- GPIOEXT30, GPIOEXT31, GPIOEXT32, GPIOEXT33, GPIOEXT34, GPIOEXT35,
- GPIOEXT36, GPIOEXT37, GPIOEXT38, GPIOEXT39, GPIOEXT40,
-
- GPIO_MAX
-};
-
-#define MAX_GPIO_PIN GPIO_MAX
-
-#define GPIO_EXTEND_START GPIOEXT0
-
-/* GPIO DIRECTION */
-enum {
- GPIO_DIR_UNSUPPORTED = -1,
- GPIO_DIR_IN = 0,
- GPIO_DIR_OUT = 1,
- GPIO_DIR_MAX,
- GPIO_DIR_DEFAULT = GPIO_DIR_IN,
-};
-
-/* GPIO OUTPUT */
-enum {
- GPIO_OUT_UNSUPPORTED = -1,
- GPIO_OUT_ZERO = 0,
- GPIO_OUT_ONE = 1,
- GPIO_OUT_MAX,
- GPIO_OUT_DEFAULT = GPIO_OUT_ZERO,
- GPIO_DATA_OUT_DEFAULT = GPIO_OUT_ZERO, /* compatible with DCT */
-};
-
-struct val_regs {
- uint16_t val;
- uint16_t _align1;
- uint16_t set;
- uint16_t _align2;
- uint16_t rst;
- uint16_t _align3[3];
-};
-
-struct gpio_regs {
- struct val_regs dir[9]; /* 0x0000 ~ 0x008F: 144 bytes */
- uint8_t rsv00[112]; /* 0x0090 ~ 0x00FF: 112 bytes */
- struct val_regs pullen[9]; /* 0x0100 ~ 0x018F: 144 bytes */
- uint8_t rsv01[112]; /* 0x0190 ~ 0x01FF: 112 bytes */
- struct val_regs pullsel[9]; /* 0x0200 ~ 0x028F: 144 bytes */
- uint8_t rsv02[112]; /* 0x0290 ~ 0x02FF: 112 bytes */
- uint8_t rsv03[256]; /* 0x0300 ~ 0x03FF: 256 bytes */
- struct val_regs dout[9]; /* 0x0400 ~ 0x048F: 144 bytes */
- uint8_t rsv04[112]; /* 0x0490 ~ 0x04FF: 112 bytes */
- struct val_regs din[9]; /* 0x0500 ~ 0x058F: 114 bytes */
- uint8_t rsv05[112]; /* 0x0590 ~ 0x05FF: 112 bytes */
- struct val_regs mode[27]; /* 0x0600 ~ 0x07AF: 432 bytes */
- uint8_t rsv06[336]; /* 0x07B0 ~ 0x08FF: 336 bytes */
- struct val_regs ies[3]; /* 0x0900 ~ 0x092F: 48 bytes */
- struct val_regs smt[3]; /* 0x0930 ~ 0x095F: 48 bytes */
- uint8_t rsv07[160]; /* 0x0960 ~ 0x09FF: 160 bytes */
- struct val_regs tdsel[8]; /* 0x0A00 ~ 0x0A7F: 128 bytes */
- struct val_regs rdsel[6]; /* 0x0A80 ~ 0x0ADF: 96 bytes */
- uint8_t rsv08[32]; /* 0x0AE0 ~ 0x0AFF: 32 bytes */
- struct val_regs drv_mode[10]; /* 0x0B00 ~ 0x0B9F: 160 bytes */
- uint8_t rsv09[96]; /* 0x0BA0 ~ 0x0BFF: 96 bytes */
- struct val_regs msdc0_ctrl0; /* 0x0C00 ~ 0x0C0F: 16 bytes */
- struct val_regs msdc0_ctrl1; /* 0x0C10 ~ 0x0C1F: 16 bytes */
- struct val_regs msdc0_ctrl2; /* 0x0C20 ~ 0x0C2F: 16 bytes */
- struct val_regs msdc0_ctrl5; /* 0x0C30 ~ 0x0C3F: 16 bytes */
- struct val_regs msdc1_ctrl0; /* 0x0C40 ~ 0x0C4F: 16 bytes */
- struct val_regs msdc1_ctrl1; /* 0x0C50 ~ 0x0C5F: 16 bytes */
- struct val_regs msdc1_ctrl2; /* 0x0C60 ~ 0x0C6F: 16 bytes */
- struct val_regs msdc1_ctrl5; /* 0x0C70 ~ 0x0C7F: 16 bytes */
- struct val_regs msdc2_ctrl0; /* 0x0C80 ~ 0x0C8F: 16 bytes */
- struct val_regs msdc2_ctrl1; /* 0x0C90 ~ 0x0C9F: 16 bytes */
- struct val_regs msdc2_ctrl2; /* 0x0CA0 ~ 0x0CAF: 16 bytes */
- struct val_regs msdc2_ctrl5; /* 0x0CB0 ~ 0x0CBF: 16 bytes */
- struct val_regs msdc3_ctrl0; /* 0x0CC0 ~ 0x0CCF: 16 bytes */
- struct val_regs msdc3_ctrl1; /* 0x0CD0 ~ 0x0CDF: 16 bytes */
- struct val_regs msdc3_ctrl2; /* 0x0CE0 ~ 0x0CEF: 16 bytes */
- struct val_regs msdc3_ctrl5; /* 0x0CF0 ~ 0x0CFF: 16 bytes */
- struct val_regs msdc0_ctrl3; /* 0x0D00 ~ 0x0D0F: 16 bytes */
- struct val_regs msdc0_ctrl4; /* 0x0D10 ~ 0x0D1F: 16 bytes */
- struct val_regs msdc1_ctrl3; /* 0x0D20 ~ 0x0D2F: 16 bytes */
- struct val_regs msdc1_ctrl4; /* 0x0D30 ~ 0x0D3F: 16 bytes */
- struct val_regs msdc2_ctrl3; /* 0x0D40 ~ 0x0D4F: 16 bytes */
- struct val_regs msdc2_ctrl4; /* 0x0D50 ~ 0x0D5F: 16 bytes */
- struct val_regs msdc3_ctrl3; /* 0x0D60 ~ 0x0D6F: 16 bytes */
- struct val_regs msdc3_ctrl4; /* 0x0D70 ~ 0x0D7F: 16 bytes */
- uint8_t rsv10[64]; /* 0x0D80 ~ 0x0DBF: 64 bytes */
- struct val_regs exmd_ctrl[1]; /* 0x0DC0 ~ 0x0DCF: 16 bytes */
- uint8_t rsv11[48]; /* 0x0DD0 ~ 0x0DFF: 48 bytes */
- struct val_regs kpad_ctrl[2]; /* 0x0E00 ~ 0x0E1F: 32 bytes */
- struct val_regs hsic_ctrl[4]; /* 0x0E20 ~ 0x0E5F: 64 bytes */
-};
-
-struct ext_val_regs {
- uint16_t val;
- uint16_t set;
- uint16_t rst;
- uint16_t _align;
-};
-
-struct gpioext_regs {
- struct ext_val_regs dir[4]; /* 0x0000 ~ 0x001F: 32 bytes */
- struct ext_val_regs pullen[4]; /* 0x0020 ~ 0x003F: 32 bytes */
- struct ext_val_regs pullsel[4]; /* 0x0040 ~ 0x005F: 32 bytes */
- struct ext_val_regs dinv[4]; /* 0x0060 ~ 0x007F: 32 bytes */
- struct ext_val_regs dout[4]; /* 0x0080 ~ 0x009F: 32 bytes */
- struct ext_val_regs din[4]; /* 0x00A0 ~ 0x00BF: 32 bytes */
- struct ext_val_regs mode[10]; /* 0x00C0 ~ 0x010F: 80 bytes */
-};
-
-/* GPIO Driver interface */
-void gpio_set(uint32_t gpio, int32_t value);
-
-#endif /* __PLAT_DRIVER_GPIO_H__ */
diff --git a/plat/mediatek/mt8173/drivers/rtc/rtc.c b/plat/mediatek/mt8173/drivers/rtc/rtc.c
index e171863..daaac42 100644
--- a/plat/mediatek/mt8173/drivers/rtc/rtc.c
+++ b/plat/mediatek/mt8173/drivers/rtc/rtc.c
@@ -95,8 +95,8 @@
if (Writeif_unlock()) {
RTC_Write(RTC_BBPU, bbpu);
if (!Write_trigger())
- assert(1);
+ assert(0);
} else {
- assert(1);
+ assert(0);
}
}
diff --git a/plat/mediatek/mt8173/drivers/spm/spm.c b/plat/mediatek/mt8173/drivers/spm/spm.c
index 45defd8..f28b264 100644
--- a/plat/mediatek/mt8173/drivers/spm/spm.c
+++ b/plat/mediatek/mt8173/drivers/spm/spm.c
@@ -384,6 +384,10 @@
void spm_boot_init(void)
{
+ /* set spm transaction to secure mode */
+ mmio_write_32(DEVAPC0_APC_CON, 0x0);
+ mmio_write_32(DEVAPC0_MAS_SEC_0, 0x200);
+
/* Only CPU0 is online during boot, initialize cpu online reserve bit */
mmio_write_32(SPM_PCM_RESERVE, 0xFE);
mmio_clrbits_32(AP_PLL_CON3, 0xFFFFF);
diff --git a/plat/mediatek/mt8173/drivers/spm/spm_suspend.c b/plat/mediatek/mt8173/drivers/spm/spm_suspend.c
index 6bf37f3..843b5f9 100644
--- a/plat/mediatek/mt8173/drivers/spm/spm_suspend.c
+++ b/plat/mediatek/mt8173/drivers/spm/spm_suspend.c
@@ -29,6 +29,9 @@
*/
#include <bakery_lock.h>
#include <debug.h>
+#include <delay_timer.h>
+#include <mmio.h>
+#include <mt8173_def.h>
#include <spm.h>
#include <spm_suspend.h>
@@ -38,8 +41,6 @@
* This driver controls the system power in system suspend flow.
*/
-#define WAIT_UART_ACK_TIMES 80 /* 80 * 10us */
-
#define WAKE_SRC_FOR_SUSPEND \
(WAKE_SRC_KP | WAKE_SRC_EINT | WAKE_SRC_MD32 | \
WAKE_SRC_USB_CD | WAKE_SRC_USB_PDN | WAKE_SRC_THERM | \
@@ -50,6 +51,13 @@
#define spm_is_wakesrc_invalid(wakesrc) \
(!!((unsigned int)(wakesrc) & 0xc0003803))
+#define ARMCA15PLL_CON0 (APMIXED_BASE + 0x200)
+#define ARMCA15PLL_CON1 (APMIXED_BASE + 0x204)
+#define ARMCA15PLL_PWR_CON0 (APMIXED_BASE + 0x20c)
+#define ARMCA15PLL_PWR_ON (1U << 0)
+#define ARMCA15PLL_ISO_EN (1U << 1)
+#define ARMCA15PLL_EN (1U << 0)
+
const unsigned int spm_flags =
SPM_DUALVCORE_PDN_DIS | SPM_PASR_DIS | SPM_DPD_DIS |
SPM_CPU_DVS_DIS | SPM_OPT | SPM_INFRA_PDN_DIS;
@@ -293,8 +301,23 @@
return last_wr;
}
+static void bigcore_pll_on(void)
+{
+ mmio_setbits_32(ARMCA15PLL_PWR_CON0, ARMCA15PLL_PWR_ON);
+ mmio_clrbits_32(ARMCA15PLL_PWR_CON0, ARMCA15PLL_ISO_EN);
+ mmio_setbits_32(ARMCA15PLL_CON0, ARMCA15PLL_EN);
+}
+
+static void bigcore_pll_off(void)
+{
+ mmio_clrbits_32(ARMCA15PLL_CON0, ARMCA15PLL_EN);
+ mmio_setbits_32(ARMCA15PLL_PWR_CON0, ARMCA15PLL_ISO_EN);
+ mmio_clrbits_32(ARMCA15PLL_PWR_CON0, ARMCA15PLL_PWR_ON);
+}
+
void spm_system_suspend(void)
{
+ bigcore_pll_off();
spm_lock_get();
go_to_sleep_before_wfi(spm_flags);
set_suspend_ready();
@@ -308,4 +331,7 @@
INFO("spm_wake_reason=%d\n", spm_wake_reason);
clear_all_ready();
spm_lock_release();
+ bigcore_pll_on();
+ /* Add 20us delay for turning on PLL*/
+ udelay(20);
}
diff --git a/plat/mediatek/mt8173/mt8173_def.h b/plat/mediatek/mt8173/include/mt8173_def.h
similarity index 86%
rename from plat/mediatek/mt8173/mt8173_def.h
rename to plat/mediatek/mt8173/include/mt8173_def.h
index ecf4cc6..0113d60 100644
--- a/plat/mediatek/mt8173/mt8173_def.h
+++ b/plat/mediatek/mt8173/include/mt8173_def.h
@@ -28,22 +28,28 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __PLAT_DEF_H__
-#define __PLAT_DEF_H__
+#ifndef __MT8173_DEF_H__
+#define __MT8173_DEF_H__
-#define MT8173_PRIMARY_CPU 0x0
+#if RESET_TO_BL31
+#error "MT8173 is incompatible with RESET_TO_BL31!"
+#endif
-/* Special value used to verify platform parameters from BL2 to BL3-1 */
-#define MT_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL
+#define MT8173_PRIMARY_CPU 0x0
+/* Register base address */
#define IO_PHYS (0x10000000)
#define INFRACFG_AO_BASE (IO_PHYS + 0x1000)
+#define SRAMROM_SEC_BASE (IO_PHYS + 0x1800)
+#define PERI_CON_BASE (IO_PHYS + 0x3000)
#define GPIO_BASE (IO_PHYS + 0x5000)
#define SPM_BASE (IO_PHYS + 0x6000)
#define RGU_BASE (IO_PHYS + 0x7000)
#define PMIC_WRAP_BASE (IO_PHYS + 0xD000)
+#define DEVAPC0_BASE (IO_PHYS + 0xE000)
#define MCUCFG_BASE (IO_PHYS + 0x200000)
-#define TRNG_base (IO_PHYS + 0x20F000)
+#define APMIXED_BASE (IO_PHYS + 0x209000)
+#define TRNG_BASE (IO_PHYS + 0x20F000)
#define MT_GIC_BASE (IO_PHYS + 0x220000)
#define PLAT_MT_CCI_BASE (IO_PHYS + 0x390000)
@@ -53,6 +59,14 @@
#define MTK_DEV_RNG1_BASE (IO_PHYS + 0x1000000)
#define MTK_DEV_RNG1_SIZE 0x4000000
+/* SRAMROM related registers */
+#define SRAMROM_SEC_CTRL (SRAMROM_SEC_BASE + 0x4)
+#define SRAMROM_SEC_ADDR (SRAMROM_SEC_BASE + 0x8)
+
+/* DEVAPC0 related registers */
+#define DEVAPC0_MAS_SEC_0 (DEVAPC0_BASE + 0x500)
+#define DEVAPC0_APC_CON (DEVAPC0_BASE + 0xF00)
+
/*******************************************************************************
* UART related constants
******************************************************************************/
@@ -112,4 +126,4 @@
#define MT_IRQ_SEC_SGI_6 14
#define MT_IRQ_SEC_SGI_7 15
-#endif /* __PLAT_DEF_H__ */
+#endif /* __MT8173_DEF_H__ */
diff --git a/plat/mediatek/mt8173/plat_private.h b/plat/mediatek/mt8173/include/plat_private.h
similarity index 100%
rename from plat/mediatek/mt8173/plat_private.h
rename to plat/mediatek/mt8173/include/plat_private.h
diff --git a/plat/mediatek/mt8173/include/platform_def.h b/plat/mediatek/mt8173/include/platform_def.h
index 0573bc5..dc5b000 100644
--- a/plat/mediatek/mt8173/include/platform_def.h
+++ b/plat/mediatek/mt8173/include/platform_def.h
@@ -70,7 +70,21 @@
/*******************************************************************************
* Platform memory map related constants
******************************************************************************/
-/* TF txet, ro, rw, internal SRAM, Size: release: 80KB, debug: 92KB */
+/*
+ * MT8173 SRAM memory layout
+ * 0x100000 +-------------------+
+ * | shared mem (4KB) |
+ * 0x101000 +-------------------+
+ * | |
+ * | BL3-1 (124KB) |
+ * | |
+ * 0x120000 +-------------------+
+ * | reserved (64KB) |
+ * 0x130000 +-------------------+
+ */
+/* TF txet, ro, rw, xlat table, coherent memory ... etc.
+ * Size: release: 128KB, debug: 128KB
+ */
#define TZRAM_BASE (0x100000)
#if DEBUG
#define TZRAM_SIZE (0x20000)
@@ -78,7 +92,7 @@
#define TZRAM_SIZE (0x20000)
#endif
-/* xlat_table , coherence ram, 64KB */
+/* Reserved: 64KB */
#define TZRAM2_BASE (TZRAM_BASE + TZRAM_SIZE)
#define TZRAM2_SIZE (0x10000)
diff --git a/plat/mediatek/mt8173/plat_pm.c b/plat/mediatek/mt8173/plat_pm.c
index f28f8ed..6bb8a9b 100644
--- a/plat/mediatek/mt8173/plat_pm.c
+++ b/plat/mediatek/mt8173/plat_pm.c
@@ -36,7 +36,6 @@
#include <console.h>
#include <debug.h>
#include <errno.h>
-#include <gpio.h>
#include <mcucfg.h>
#include <mmio.h>
#include <mt8173_def.h>
@@ -478,7 +477,6 @@
{
INFO("MTK System Off\n");
- gpio_set(GPIO120, GPIO_OUT_ZERO);
rtc_bbpu_power_down();
wfi();
diff --git a/plat/mediatek/mt8173/platform.mk b/plat/mediatek/mt8173/platform.mk
index 30df32f..4169823 100644
--- a/plat/mediatek/mt8173/platform.mk
+++ b/plat/mediatek/mt8173/platform.mk
@@ -32,8 +32,6 @@
MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT}
PLAT_INCLUDES := -I${MTK_PLAT}/common/ \
- -I${MTK_PLAT_SOC}/ \
- -I${MTK_PLAT_SOC}/drivers/gpio/ \
-I${MTK_PLAT_SOC}/drivers/mtcmos/ \
-I${MTK_PLAT_SOC}/drivers/pmic/ \
-I${MTK_PLAT_SOC}/drivers/rtc/ \
@@ -61,7 +59,6 @@
${MTK_PLAT_SOC}/aarch64/plat_helpers.S \
${MTK_PLAT_SOC}/aarch64/platform_common.c \
${MTK_PLAT_SOC}/bl31_plat_setup.c \
- ${MTK_PLAT_SOC}/drivers/gpio/gpio.c \
${MTK_PLAT_SOC}/drivers/mtcmos/mtcmos.c \
${MTK_PLAT_SOC}/drivers/pmic/pmic_wrap_init.c \
${MTK_PLAT_SOC}/drivers/rtc/rtc.c \
diff --git a/plat/rockchip/common/aarch64/plat_helpers.S b/plat/rockchip/common/aarch64/plat_helpers.S
new file mode 100644
index 0000000..a90dcd7
--- /dev/null
+++ b/plat/rockchip/common/aarch64/plat_helpers.S
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <bl_common.h>
+#include <cortex_a53.h>
+#include <cortex_a72.h>
+#include <plat_private.h>
+#include <platform_def.h>
+
+ .globl cpuson_entry_point
+ .globl cpuson_flags
+ .globl platform_cpu_warmboot
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_report_exception
+ .globl platform_is_primary_cpu
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_my_core_pos
+ .globl plat_reset_handler
+
+
+#define RK_REVISION(rev) RK_PLAT_CFG##rev
+#define RK_HANDLER(rev) plat_reset_handler_juno_r##rev
+#define JUMP_TO_HANDLER_IF_RK_R(revision) \
+ jump_to_handler RK_REVISION(revision), RK_HANDLER(revision)
+
+ /*
+ * Helper macro to jump to the given handler if the board revision
+ * matches.
+ * Expects the Juno board revision in x0.
+ *
+ */
+ .macro jump_to_handler _revision, _handler
+ cmp x0, #\_revision
+ b.eq \_handler
+ .endm
+
+ /*
+ * Helper macro that reads the part number of the current CPU and jumps
+ * to the given label if it matches the CPU MIDR provided.
+ */
+ .macro jump_if_cpu_midr _cpu_midr, _label
+ mrs x0, midr_el1
+ ubfx x0, x0, MIDR_PN_SHIFT, #12
+ cmp w0, #((\_cpu_midr >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
+ b.eq \_label
+ .endm
+
+ /*
+ * Platform reset handler for rockchip.
+ * only A53 cores
+ */
+func RK_HANDLER(0)
+ ret
+endfunc RK_HANDLER(0)
+
+ /*
+ * Platform reset handler for rockchip.
+ * - Cortex-A53 processor cluster;
+ * - Cortex-A72 processor cluster.
+ *
+ * This handler does the following:
+ * - Set the L2 Data RAM latency to 2 (i.e. 3 cycles) for Cortex-A72
+ * - Set the L2 Tag RAM latency to 1 (i.e. 2 cycles) for Cortex-A72
+ */
+func RK_HANDLER(1)
+ /*
+ * Nothing to do on Cortex-A53.
+ *
+ */
+ jump_if_cpu_midr CORTEX_A72_MIDR, A72
+ ret
+
+A72:
+ /* Cortex-A72 specific settings */
+ mov x0, #((2 << L2CTLR_DATA_RAM_LATENCY_SHIFT) | \
+ (0x1 << 5))
+ msr L2CTLR_EL1, x0
+ isb
+ ret
+endfunc RK_HANDLER(1)
+
+ /*
+ * void plat_reset_handler(void);
+ *
+ * Determine the SOC type and call the appropriate reset
+ * handler.
+ *
+ */
+func plat_reset_handler
+
+ mov x0, RK_PLAT_AARCH_CFG
+
+ JUMP_TO_HANDLER_IF_RK_R(0)
+ JUMP_TO_HANDLER_IF_RK_R(1)
+
+ /* SOC type is not supported */
+not_supported:
+ b not_supported
+endfunc plat_reset_handler
+
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #6
+ ret
+endfunc plat_my_core_pos
+
+ /* --------------------------------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset e.g
+ * mark the cpu's presence, mechanism to place it in a
+ * holding pen etc.
+ * --------------------------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+ /* rk3368 does not do cold boot for secondary CPU */
+cb_panic:
+ b cb_panic
+endfunc plat_secondary_cold_boot_setup
+
+func platform_is_primary_cpu
+ and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+ cmp x0, #PLAT_RK_PRIMARY_CPU
+ cset x0, eq
+ ret
+endfunc platform_is_primary_cpu
+
+ /* --------------------------------------------------------------------
+ * int plat_crash_console_init(void)
+ * Function to initialize the crash console
+ * without a C Runtime to print crash report.
+ * Clobber list : x0, x1, x2
+ * --------------------------------------------------------------------
+ */
+func plat_crash_console_init
+ mov_imm x0, PLAT_RK_UART_BASE
+ mov_imm x1, PLAT_RK_UART_CLOCK
+ mov_imm x2, PLAT_RK_UART_BAUDRATE
+ b console_core_init
+endfunc plat_crash_console_init
+
+ /* --------------------------------------------------------------------
+ * int plat_crash_console_putc(void)
+ * 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, PLAT_RK_UART_BASE
+ b console_core_putc
+endfunc plat_crash_console_putc
+
+ /* --------------------------------------------------------------------
+ * void platform_cpu_warmboot (void);
+ * cpus online or resume enterpoint
+ * --------------------------------------------------------------------
+ */
+func platform_cpu_warmboot
+ mrs x0, MPIDR_EL1
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ /* --------------------------------------------------------------------
+ * big cluster id is 1
+ * big cores id is from 0-3, little cores id 4-7
+ * --------------------------------------------------------------------
+ */
+ add x0, x1, x0, lsr #6
+ /* --------------------------------------------------------------------
+ * get per cpuup flag
+ * --------------------------------------------------------------------
+ */
+ adr x4, cpuson_flags
+ add x4, x4, x0, lsl #2
+ ldr w1, [x4]
+ /* --------------------------------------------------------------------
+ * get per cpuup boot addr
+ * --------------------------------------------------------------------
+ */
+ adr x5, cpuson_entry_point
+ ldr x2, [x5, x0, lsl #3]
+ /* --------------------------------------------------------------------
+ * check cpuon reason
+ * --------------------------------------------------------------------
+ */
+ ldr w3, =PMU_CPU_AUTO_PWRDN
+ cmp w1, w3
+ b.eq boot_entry
+ ldr w3, =PMU_CPU_HOTPLUG
+ cmp w1, w3
+ b.eq boot_entry
+ /* --------------------------------------------------------------------
+ * If the boot core cpuson_flags or cpuson_entry_point is not
+ * expection. force the core into wfe.
+ * --------------------------------------------------------------------
+ */
+wfe_loop:
+ wfe
+ b wfe_loop
+boot_entry:
+ mov w0, #0
+ str w0, [x4]
+ br x2
+endfunc platform_cpu_warmboot
+
+ /* --------------------------------------------------------------------
+ * Per-CPU Secure entry point - resume or power up
+ * --------------------------------------------------------------------
+ */
+ .section tzfw_coherent_mem, "a"
+ .align 3
+cpuson_entry_point:
+ .rept PLATFORM_CORE_COUNT
+ .quad 0
+ .endr
+cpuson_flags:
+ .rept PLATFORM_CORE_COUNT
+ .quad 0
+ .endr
diff --git a/plat/rockchip/common/aarch64/platform_common.c b/plat/rockchip/common/aarch64/platform_common.c
new file mode 100644
index 0000000..3f912a4
--- /dev/null
+++ b/plat/rockchip/common/aarch64/platform_common.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <arm_gic.h>
+#include <bl_common.h>
+#include <cci.h>
+#include <debug.h>
+#include <string.h>
+#include <xlat_tables.h>
+#include <platform_def.h>
+#include <plat_private.h>
+
+#ifdef PLAT_RK_CCI_BASE
+static const int cci_map[] = {
+ PLAT_RK_CCI_CLUSTER0_SL_IFACE_IX,
+ PLAT_RK_CCI_CLUSTER1_SL_IFACE_IX
+};
+#endif
+
+/******************************************************************************
+ * Macro generating the code for the function setting up the pagetables as per
+ * the platform memory map & initialize the mmu, for the given exception level
+ ******************************************************************************/
+#define DEFINE_CONFIGURE_MMU_EL(_el) \
+ void plat_configure_mmu_el ## _el(unsigned long total_base, \
+ unsigned long total_size, \
+ unsigned long ro_start, \
+ unsigned long ro_limit, \
+ unsigned long coh_start, \
+ unsigned long coh_limit) \
+ { \
+ mmap_add_region(total_base, total_base, \
+ total_size, \
+ MT_MEMORY | MT_RW | MT_SECURE); \
+ mmap_add_region(ro_start, ro_start, \
+ ro_limit - ro_start, \
+ MT_MEMORY | MT_RO | MT_SECURE); \
+ mmap_add_region(coh_start, coh_start, \
+ coh_limit - coh_start, \
+ MT_DEVICE | MT_RW | MT_SECURE); \
+ mmap_add(plat_rk_mmap); \
+ init_xlat_tables(); \
+ \
+ enable_mmu_el ## _el(0); \
+ }
+
+/* Define EL3 variants of the function initialising the MMU */
+DEFINE_CONFIGURE_MMU_EL(3)
+
+uint64_t plat_get_syscnt_freq(void)
+{
+ return SYS_COUNTER_FREQ_IN_TICKS;
+}
+
+void plat_cci_init(void)
+{
+#ifdef PLAT_RK_CCI_BASE
+ /* Initialize CCI driver */
+ cci_init(PLAT_RK_CCI_BASE, cci_map, ARRAY_SIZE(cci_map));
+#endif
+}
+
+void plat_cci_enable(void)
+{
+ /*
+ * Enable CCI coherency for this cluster.
+ * No need for locks as no other cpu is active at the moment.
+ */
+#ifdef PLAT_RK_CCI_BASE
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr()));
+#endif
+}
+
+void plat_cci_disable(void)
+{
+#ifdef PLAT_RK_CCI_BASE
+ cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr()));
+#endif
+}
diff --git a/plat/rockchip/common/bl31_plat_setup.c b/plat/rockchip/common/bl31_plat_setup.c
new file mode 100644
index 0000000..30fb5ac
--- /dev/null
+++ b/plat/rockchip/common/bl31_plat_setup.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arm_gic.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <console.h>
+#include <debug.h>
+#include <mmio.h>
+#include <platform.h>
+#include <plat_private.h>
+#include <platform_def.h>
+
+/*******************************************************************************
+ * Declarations of linker defined symbols which will help us find the layout
+ * of trusted SRAM
+ ******************************************************************************/
+unsigned long __RO_START__;
+unsigned long __RO_END__;
+
+unsigned long __COHERENT_RAM_START__;
+unsigned long __COHERENT_RAM_END__;
+
+/*
+ * The next 2 constants identify the extents of the code & RO data region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned. It is the responsibility of the linker script to ensure that
+ * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses.
+ */
+#define BL31_RO_BASE (unsigned long)(&__RO_START__)
+#define BL31_RO_LIMIT (unsigned long)(&__RO_END__)
+
+/*
+ * The next 2 constants identify the extents of the coherent memory region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned. It is the responsibility of the linker script to ensure that
+ * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols
+ * refer to page-aligned addresses.
+ */
+#define BL31_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
+#define BL31_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
+
+static entry_point_info_t bl32_ep_info;
+static entry_point_info_t bl33_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;
+
+ next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info;
+
+ /* None of the images on this platform can have 0x0 as the entrypoint */
+ if (next_image_info->pc)
+ return next_image_info;
+ else
+ return NULL;
+}
+
+/*******************************************************************************
+ * Perform any BL3-1 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.
+ ******************************************************************************/
+void bl31_early_platform_setup(bl31_params_t *from_bl2,
+ void *plat_params_from_bl2)
+{
+ console_init(PLAT_RK_UART_BASE, PLAT_RK_UART_CLOCK,
+ PLAT_RK_UART_BAUDRATE);
+
+ VERBOSE("bl31_setup\n");
+
+ /* Passing a NULL context is a critical programming error */
+ assert(from_bl2);
+
+ assert(from_bl2->h.type == PARAM_BL31);
+ assert(from_bl2->h.version >= VERSION_1);
+
+ bl32_ep_info = *from_bl2->bl32_ep_info;
+ bl33_ep_info = *from_bl2->bl33_ep_info;
+
+ /*
+ * The code for resuming cpu from suspend must be excuted in pmusram.
+ * Copy the code into pmusram.
+ */
+ plat_rockchip_pmusram_prepare();
+}
+
+/*******************************************************************************
+ * Perform any BL3-1 platform setup code
+ ******************************************************************************/
+void bl31_platform_setup(void)
+{
+ plat_delay_timer_init();
+ plat_rockchip_soc_init();
+
+ /* Initialize the gic cpu and distributor interfaces */
+ plat_rockchip_gic_driver_init();
+ plat_rockchip_gic_init();
+ plat_rockchip_pmu_init();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bl31_plat_arch_setup(void)
+{
+ plat_cci_init();
+ plat_cci_enable();
+ plat_configure_mmu_el3(BL31_RO_BASE,
+ (BL31_COHERENT_RAM_LIMIT - BL31_RO_BASE),
+ BL31_RO_BASE,
+ BL31_RO_LIMIT,
+ BL31_COHERENT_RAM_BASE,
+ BL31_COHERENT_RAM_LIMIT);
+}
diff --git a/plat/rockchip/common/drivers/pmu/pmu_com.h b/plat/rockchip/common/drivers/pmu/pmu_com.h
new file mode 100644
index 0000000..0cab53c
--- /dev/null
+++ b/plat/rockchip/common/drivers/pmu/pmu_com.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PMU_COM_H__
+#define __PMU_COM_H__
+
+DEFINE_BAKERY_LOCK(rockchip_pd_lock);
+
+#define rockchip_pd_lock_get() bakery_lock_get(&rockchip_pd_lock)
+
+#define rockchip_pd_lock_rls() bakery_lock_release(&rockchip_pd_lock)
+
+#define rockchip_pd_lock_init() bakery_lock_init(&rockchip_pd_lock)
+/*****************************************************************************
+ * power domain on or off
+ *****************************************************************************/
+enum pmu_pd_state {
+ pmu_pd_on = 0,
+ pmu_pd_off = 1
+};
+
+#pragma weak plat_ic_get_pending_interrupt_id
+#pragma weak pmu_power_domain_ctr
+#pragma weak check_cpu_wfie
+
+static inline uint32_t pmu_power_domain_st(uint32_t pd)
+{
+ uint32_t pwrdn_st = mmio_read_32(PMU_BASE + PMU_PWRDN_ST) & BIT(pd);
+
+ if (pwrdn_st)
+ return pmu_pd_off;
+ else
+ return pmu_pd_on;
+}
+
+static int pmu_power_domain_ctr(uint32_t pd, uint32_t pd_state)
+{
+ uint32_t val;
+ uint32_t loop = 0;
+ int ret = 0;
+
+ rockchip_pd_lock_get();
+
+ val = mmio_read_32(PMU_BASE + PMU_PWRDN_CON);
+ if (pd_state == pmu_pd_off)
+ val |= BIT(pd);
+ else
+ val &= ~BIT(pd);
+
+ mmio_write_32(PMU_BASE + PMU_PWRDN_CON, val);
+ dsb();
+
+ while ((pmu_power_domain_st(pd) != pd_state) && (loop < PD_CTR_LOOP)) {
+ udelay(1);
+ loop++;
+ }
+
+ if (pmu_power_domain_st(pd) != pd_state) {
+ WARN("%s: %d, %d, error!\n", __func__, pd, pd_state);
+ ret = -EINVAL;
+ }
+
+ rockchip_pd_lock_rls();
+
+ return ret;
+}
+
+static int check_cpu_wfie(uint32_t cpu_id, uint32_t wfie_msk)
+{
+ uint32_t cluster_id, loop = 0;
+
+ if (cpu_id >= PLATFORM_CLUSTER0_CORE_COUNT) {
+ cluster_id = 1;
+ cpu_id -= PLATFORM_CLUSTER0_CORE_COUNT;
+ } else {
+ cluster_id = 0;
+ }
+
+ if (cluster_id)
+ wfie_msk <<= (clstb_cpu_wfe + cpu_id);
+ else
+ wfie_msk <<= (clstl_cpu_wfe + cpu_id);
+
+ while (!(mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST) & wfie_msk) &&
+ (loop < CHK_CPU_LOOP)) {
+ udelay(1);
+ loop++;
+ }
+
+ if ((mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST) & wfie_msk) == 0) {
+ WARN("%s: %d, %d, %d, error!\n", __func__,
+ cluster_id, cpu_id, wfie_msk);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+#endif /* __PMU_COM_H__ */
diff --git a/plat/rockchip/common/include/plat_macros.S b/plat/rockchip/common/include/plat_macros.S
new file mode 100644
index 0000000..ce68cf1
--- /dev/null
+++ b/plat/rockchip/common/include/plat_macros.S
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __ROCKCHIP_PLAT_MACROS_S__
+#define __ROCKCHIP_PLAT_MACROS_S__
+
+#include <cci.h>
+#include <gic_common.h>
+#include <gicv2.h>
+#include <gicv3.h>
+#include <platform_def.h>
+
+.section .rodata.gic_reg_name, "aS"
+/* Applicable only to GICv2 and GICv3 with SRE disabled (legacy mode) */
+gicc_regs:
+ .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+
+/* Applicable only to GICv3 with SRE enabled */
+icc_regs:
+ .asciz "icc_hppir0_el1", "icc_hppir1_el1", "icc_ctlr_el3", ""
+
+/* Registers common to both GICv2 and GICv3 */
+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 utility macro prints out relevant GIC
+ * registers whenever an unhandled exception is
+ * taken in BL31 on ARM standard platforms.
+ * Expects: GICD base in x16, GICC base in x17
+ * Clobbers: x0 - x10, sp
+ * ---------------------------------------------
+ */
+ .macro plat_print_gic_regs
+
+ mov_imm x16, PLAT_RK_GICD_BASE
+ mov_imm x17, PLAT_RK_GICC_BASE
+
+ /* Check for GICv3 system register access */
+ mrs x7, id_aa64pfr0_el1
+ ubfx x7, x7, #ID_AA64PFR0_GIC_SHIFT, #ID_AA64PFR0_GIC_WIDTH
+ cmp x7, #1
+ b.ne print_gicv2
+
+ /* Check for SRE enable */
+ mrs x8, ICC_SRE_EL3
+ tst x8, #ICC_SRE_SRE_BIT
+ b.eq print_gicv2
+
+ /* Load the icc reg list to x6 */
+ adr x6, icc_regs
+ /* Load the icc regs to gp regs used by str_in_crash_buf_print */
+ mrs x8, ICC_HPPIR0_EL1
+ mrs x9, ICC_HPPIR1_EL1
+ mrs x10, ICC_CTLR_EL3
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+ b print_gic_common
+
+print_gicv2:
+ /* Load the gicc reg list to x6 */
+ adr x6, gicc_regs
+ /* Load the gicc regs to gp regs used by str_in_crash_buf_print */
+ ldr w8, [x17, #GICC_HPPIR]
+ ldr w9, [x17, #GICC_AHPPIR]
+ ldr w10, [x17, #GICC_CTLR]
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+
+print_gic_common:
+ /* Print the GICD_ISPENDR regs */
+ 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
+
+.section .rodata.cci_reg_name, "aS"
+cci_iface_regs:
+ .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , ""
+
+ /* ------------------------------------------------
+ * The below macro prints out relevant interconnect
+ * registers whenever an unhandled exception is
+ * taken in BL3-1.
+ * Clobbers: x0 - x9, sp
+ * ------------------------------------------------
+ */
+ .macro plat_print_interconnect_regs
+#if PLATFORM_CLUSTER_COUNT > 1
+ adr x6, cci_iface_regs
+ /* Store in x7 the base address of the first interface */
+ mov_imm x7, (PLAT_RK_CCI_BASE + SLAVE_IFACE_OFFSET( \
+ PLAT_RK_CCI_CLUSTER0_SL_IFACE_IX))
+ ldr w8, [x7, #SNOOP_CTRL_REG]
+ /* Store in x7 the base address of the second interface */
+ mov_imm x7, (PLAT_RK_CCI_BASE + SLAVE_IFACE_OFFSET( \
+ PLAT_RK_CCI_CLUSTER1_SL_IFACE_IX))
+ ldr w9, [x7, #SNOOP_CTRL_REG]
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+#endif
+ .endm
+
+#endif /* __ROCKCHIP_PLAT_MACROS_S__ */
diff --git a/plat/rockchip/common/include/plat_private.h b/plat/rockchip/common/include/plat_private.h
new file mode 100644
index 0000000..67fb827
--- /dev/null
+++ b/plat/rockchip/common/include/plat_private.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PLAT_PRIVATE_H__
+#define __PLAT_PRIVATE_H__
+
+#ifndef __ASSEMBLY__
+#include <mmio.h>
+#include <stdint.h>
+#include <xlat_tables.h>
+
+/******************************************************************************
+ * For rockchip socs pm ops
+ ******************************************************************************/
+struct rockchip_pm_ops_cb {
+ int (*cores_pwr_dm_on)(unsigned long mpidr, uint64_t entrypoint);
+ int (*cores_pwr_dm_off)(void);
+ int (*cores_pwr_dm_on_finish)(void);
+ int (*cores_pwr_dm_suspend)(void);
+ int (*cores_pwr_dm_resume)(void);
+ int (*sys_pwr_dm_suspend)(void);
+ int (*sys_pwr_dm_resume)(void);
+ void (*sys_gbl_soft_reset)(void) __dead2;
+ void (*system_off)(void) __dead2;
+};
+
+/******************************************************************************
+ * The register have write-mask bits, it is mean, if you want to set the bits,
+ * you needs set the write-mask bits at the same time,
+ * The write-mask bits is in high 16-bits.
+ * The fllowing macro definition helps access write-mask bits reg efficient!
+ ******************************************************************************/
+#define REG_MSK_SHIFT 16
+
+#ifndef BIT
+#define BIT(nr) (1 << (nr))
+#endif
+
+#ifndef WMSK_BIT
+#define WMSK_BIT(nr) BIT((nr) + REG_MSK_SHIFT)
+#endif
+
+/* set one bit with write mask */
+#ifndef BIT_WITH_WMSK
+#define BIT_WITH_WMSK(nr) (BIT(nr) | WMSK_BIT(nr))
+#endif
+
+#ifndef BITS_SHIFT
+#define BITS_SHIFT(bits, shift) (bits << (shift))
+#endif
+
+#ifndef BITS_WITH_WMASK
+#define BITS_WITH_WMASK(msk, bits, shift)\
+ (BITS_SHIFT(bits, shift) | BITS_SHIFT(msk, (shift + REG_MSK_SHIFT)))
+#endif
+
+/******************************************************************************
+ * Function and variable prototypes
+ *****************************************************************************/
+void plat_configure_mmu_el3(unsigned long total_base,
+ unsigned long total_size,
+ unsigned long,
+ unsigned long,
+ unsigned long,
+ unsigned long);
+
+void plat_cci_init(void);
+void plat_cci_enable(void);
+void plat_cci_disable(void);
+
+void plat_delay_timer_init(void);
+
+void plat_rockchip_gic_driver_init(void);
+void plat_rockchip_gic_init(void);
+void plat_rockchip_gic_cpuif_enable(void);
+void plat_rockchip_gic_cpuif_disable(void);
+void plat_rockchip_gic_pcpu_init(void);
+
+void plat_rockchip_pmusram_prepare(void);
+void plat_rockchip_pmu_init(void);
+void plat_rockchip_soc_init(void);
+void plat_setup_rockchip_pm_ops(struct rockchip_pm_ops_cb *ops);
+
+extern const unsigned char rockchip_power_domain_tree_desc[];
+
+extern void *pmu_cpuson_entrypoint_start;
+extern void *pmu_cpuson_entrypoint_end;
+extern uint64_t cpuson_entry_point[PLATFORM_CORE_COUNT];
+extern uint32_t cpuson_flags[PLATFORM_CORE_COUNT];
+
+extern const mmap_region_t plat_rk_mmap[];
+#endif /* __ASSEMBLY__ */
+
+/* only Cortex-A53 */
+#define RK_PLAT_CFG0 0
+
+/* include Cortex-A72 */
+#define RK_PLAT_CFG1 1
+
+#endif /* __PLAT_PRIVATE_H__ */
diff --git a/lib/stdlib/std.c b/plat/rockchip/common/plat_delay_timer.c
similarity index 68%
copy from lib/stdlib/std.c
copy to plat/rockchip/common/plat_delay_timer.c
index 5f6ef75..797ce05 100644
--- a/lib/stdlib/std.c
+++ b/plat/rockchip/common/plat_delay_timer.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -28,18 +28,27 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <arch_helpers.h>
+#include <delay_timer.h>
+#include <platform_def.h>
+
+static uint32_t plat_get_timer_value(void)
+{
+ /*
+ * Generic delay timer implementation expects the timer to be a down
+ * counter. We apply bitwise NOT operator to the tick values returned
+ * by read_cntpct_el0() to simulate the down counter.
+ */
+ return (uint32_t)(~read_cntpct_el0());
+}
+
+static const timer_ops_t plat_timer_ops = {
+ .get_timer_value = plat_get_timer_value,
+ .clk_mult = 1,
+ .clk_div = SYS_COUNTER_FREQ_IN_MHZ,
+};
-/* Include the various implemented functions */
-#include "abort.c"
-#include "assert.c"
-#include "exit.c"
-#include "mem.c"
-#include "printf.c"
-#include "putchar.c"
-#include "puts.c"
-#include "sscanf.c"
-#include "strchr.c"
-#include "strcmp.c"
-#include "strlen.c"
-#include "strncmp.c"
-#include "subr_prf.c"
+void plat_delay_timer_init(void)
+{
+ timer_init(&plat_timer_ops);
+}
diff --git a/plat/rockchip/common/plat_pm.c b/plat/rockchip/common/plat_pm.c
new file mode 100644
index 0000000..fcd47a8
--- /dev/null
+++ b/plat/rockchip/common/plat_pm.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <console.h>
+#include <errno.h>
+#include <debug.h>
+#include <psci.h>
+#include <delay_timer.h>
+#include <platform_def.h>
+#include <plat_private.h>
+
+/* Macros to read the rk power domain state */
+#define RK_CORE_PWR_STATE(state) \
+ ((state)->pwr_domain_state[MPIDR_AFFLVL0])
+#define RK_CLUSTER_PWR_STATE(state) \
+ ((state)->pwr_domain_state[MPIDR_AFFLVL1])
+#define RK_SYSTEM_PWR_STATE(state) \
+ ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
+
+static uintptr_t rockchip_sec_entrypoint;
+
+static struct rockchip_pm_ops_cb *rockchip_ops;
+
+static void plat_rockchip_sys_pwr_domain_resume(void)
+{
+ plat_rockchip_gic_init();
+ if (rockchip_ops && rockchip_ops->sys_pwr_dm_resume)
+ rockchip_ops->sys_pwr_dm_resume();
+}
+
+static void plat_rockchip_cores_pwr_domain_resume(void)
+{
+ if (rockchip_ops && rockchip_ops->cores_pwr_dm_resume)
+ rockchip_ops->cores_pwr_dm_resume();
+
+ /* Enable the gic cpu interface */
+ plat_rockchip_gic_pcpu_init();
+ /* Program the gic per-cpu distributor or re-distributor interface */
+ plat_rockchip_gic_cpuif_enable();
+}
+
+/*******************************************************************************
+ * Rockchip standard platform handler called to check the validity of the power
+ * state parameter.
+ ******************************************************************************/
+int rockchip_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ int pstate = psci_get_pstate_type(power_state);
+ int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
+ int i;
+
+ assert(req_state);
+
+ if (pwr_lvl > PLAT_MAX_PWR_LVL)
+ return PSCI_E_INVALID_PARAMS;
+
+ /* Sanity check the requested state */
+ if (pstate == PSTATE_TYPE_STANDBY) {
+ /*
+ * It's probably to enter standby only on power level 0
+ * ignore any other power level.
+ */
+ if (pwr_lvl != MPIDR_AFFLVL0)
+ return PSCI_E_INVALID_PARAMS;
+
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] =
+ PLAT_MAX_RET_STATE;
+ } else {
+ for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++)
+ req_state->pwr_domain_state[i] =
+ PLAT_MAX_OFF_STATE;
+ }
+
+ /* We expect the 'state id' to be zero */
+ if (psci_get_pstate_id(power_state))
+ return PSCI_E_INVALID_PARAMS;
+
+ return PSCI_E_SUCCESS;
+}
+
+void rockchip_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ int i;
+
+ for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
+ req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+}
+
+/*******************************************************************************
+ * RockChip handler called when a CPU is about to enter standby.
+ ******************************************************************************/
+void rockchip_cpu_standby(plat_local_state_t cpu_state)
+{
+ unsigned int scr;
+
+ assert(cpu_state == PLAT_MAX_RET_STATE);
+
+ scr = read_scr_el3();
+ /* Enable PhysicalIRQ bit for NS world to wake the CPU */
+ write_scr_el3(scr | SCR_IRQ_BIT);
+ isb();
+ dsb();
+ wfi();
+
+ /*
+ * Restore SCR to the original value, synchronisation of scr_el3 is
+ * done by eret while el3_exit to save some execution cycles.
+ */
+ write_scr_el3(scr);
+}
+
+/*******************************************************************************
+ * RockChip handler called when a power domain is about to be turned on. The
+ * mpidr determines the CPU to be turned on.
+ ******************************************************************************/
+int rockchip_pwr_domain_on(u_register_t mpidr)
+{
+ if (rockchip_ops && rockchip_ops->cores_pwr_dm_on)
+ rockchip_ops->cores_pwr_dm_on(mpidr, rockchip_sec_entrypoint);
+
+ return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * RockChip handler called when a power domain is about to be turned off. The
+ * target_state encodes the power state that each level should transition to.
+ ******************************************************************************/
+void rockchip_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ assert(RK_CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE);
+
+ plat_rockchip_gic_cpuif_disable();
+
+ if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
+ plat_cci_disable();
+ if (rockchip_ops && rockchip_ops->cores_pwr_dm_off)
+ rockchip_ops->cores_pwr_dm_off();
+}
+
+/*******************************************************************************
+ * RockChip handler called when a power domain is about to be suspended. The
+ * target_state encodes the power state that each level should transition to.
+ ******************************************************************************/
+void rockchip_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+ if (RK_CORE_PWR_STATE(target_state) == PLAT_MAX_RET_STATE)
+ return;
+
+ assert(RK_CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE);
+
+ if (RK_SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
+ if (rockchip_ops && rockchip_ops->sys_pwr_dm_suspend)
+ rockchip_ops->sys_pwr_dm_suspend();
+ } else {
+ if (rockchip_ops && rockchip_ops->cores_pwr_dm_suspend)
+ rockchip_ops->cores_pwr_dm_suspend();
+ }
+
+ /* Prevent interrupts from spuriously waking up this cpu */
+ plat_rockchip_gic_cpuif_disable();
+
+ /* Perform the common cluster specific operations */
+ if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
+ plat_cci_disable();
+}
+
+/*******************************************************************************
+ * RockChip handler called when a power domain has just been powered on after
+ * being turned off earlier. The target_state encodes the low power state that
+ * each level has woken up from.
+ ******************************************************************************/
+void rockchip_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ assert(RK_CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE);
+
+ if (rockchip_ops && rockchip_ops->cores_pwr_dm_on_finish)
+ rockchip_ops->cores_pwr_dm_on_finish();
+
+ /* Perform the common cluster specific operations */
+ if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
+ /* Enable coherency if this cluster was off */
+ plat_cci_enable();
+ }
+
+ /* Enable the gic cpu interface */
+ plat_rockchip_gic_pcpu_init();
+
+ /* Program the gic per-cpu distributor or re-distributor interface */
+ plat_rockchip_gic_cpuif_enable();
+}
+
+/*******************************************************************************
+ * RockChip handler called when a power domain has just been powered on after
+ * having been suspended earlier. The target_state encodes the low power state
+ * that each level has woken up from.
+ * TODO: At the moment we reuse the on finisher and reinitialize the secure
+ * context. Need to implement a separate suspend finisher.
+ ******************************************************************************/
+void rockchip_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+ /* Nothing to be done on waking up from retention from CPU level */
+ if (RK_CORE_PWR_STATE(target_state) == PLAT_MAX_RET_STATE)
+ return;
+
+ /* Perform system domain restore if woken up from system suspend */
+ if (RK_SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
+ plat_rockchip_sys_pwr_domain_resume();
+ else
+ plat_rockchip_cores_pwr_domain_resume();
+
+ /* Perform the common cluster specific operations */
+ if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
+ /* Enable coherency if this cluster was off */
+ plat_cci_enable();
+ }
+}
+
+/*******************************************************************************
+ * RockChip handlers to reboot the system
+ ******************************************************************************/
+static void __dead2 rockchip_system_reset(void)
+{
+ assert(rockchip_ops && rockchip_ops->sys_gbl_soft_reset);
+
+ rockchip_ops->sys_gbl_soft_reset();
+}
+
+/*******************************************************************************
+ * Export the platform handlers via plat_rockchip_psci_pm_ops. The rockchip
+ * standard
+ * platform layer will take care of registering the handlers with PSCI.
+ ******************************************************************************/
+const plat_psci_ops_t plat_rockchip_psci_pm_ops = {
+ .cpu_standby = rockchip_cpu_standby,
+ .pwr_domain_on = rockchip_pwr_domain_on,
+ .pwr_domain_off = rockchip_pwr_domain_off,
+ .pwr_domain_suspend = rockchip_pwr_domain_suspend,
+ .pwr_domain_on_finish = rockchip_pwr_domain_on_finish,
+ .pwr_domain_suspend_finish = rockchip_pwr_domain_suspend_finish,
+ .system_reset = rockchip_system_reset,
+ .validate_power_state = rockchip_validate_power_state,
+ .get_sys_suspend_power_state = rockchip_get_sys_suspend_power_state
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ *psci_ops = &plat_rockchip_psci_pm_ops;
+ rockchip_sec_entrypoint = sec_entrypoint;
+ return 0;
+}
+
+void plat_setup_rockchip_pm_ops(struct rockchip_pm_ops_cb *ops)
+{
+ rockchip_ops = ops;
+}
diff --git a/lib/stdlib/std.c b/plat/rockchip/common/plat_topology.c
similarity index 65%
copy from lib/stdlib/std.c
copy to plat/rockchip/common/plat_topology.c
index 5f6ef75..911978a 100644
--- a/lib/stdlib/std.c
+++ b/plat/rockchip/common/plat_topology.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -28,18 +28,28 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <arch.h>
+#include <platform_def.h>
+#include <plat_private.h>
+#include <psci.h>
+
+/*******************************************************************************
+ * This function returns the RockChip default topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return rockchip_power_domain_tree_desc;
+}
+
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int cluster_id, cpu_id;
+
+ cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+ cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
+
+ if (cluster_id >= PLATFORM_CLUSTER_COUNT)
+ return -1;
-/* Include the various implemented functions */
-#include "abort.c"
-#include "assert.c"
-#include "exit.c"
-#include "mem.c"
-#include "printf.c"
-#include "putchar.c"
-#include "puts.c"
-#include "sscanf.c"
-#include "strchr.c"
-#include "strcmp.c"
-#include "strlen.c"
-#include "strncmp.c"
-#include "subr_prf.c"
+ return ((cluster_id * PLATFORM_CLUSTER0_CORE_COUNT) + cpu_id);
+}
diff --git a/lib/stdlib/std.c b/plat/rockchip/common/pmusram/pmu_sram.c
similarity index 69%
copy from lib/stdlib/std.c
copy to plat/rockchip/common/pmusram/pmu_sram.c
index 5f6ef75..bea4875 100644
--- a/lib/stdlib/std.c
+++ b/plat/rockchip/common/pmusram/pmu_sram.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -11,10 +11,6 @@
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
- * Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without specific
- * prior written permission.
- *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -28,18 +24,15 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <platform.h>
+
+/*****************************************************************************
+ * sram only surpport 32-bits access
+ ******************************************************************************/
+void u32_align_cpy(uint32_t *dst, const uint32_t *src, size_t bytes)
+{
+ uint32_t i;
-/* Include the various implemented functions */
-#include "abort.c"
-#include "assert.c"
-#include "exit.c"
-#include "mem.c"
-#include "printf.c"
-#include "putchar.c"
-#include "puts.c"
-#include "sscanf.c"
-#include "strchr.c"
-#include "strcmp.c"
-#include "strlen.c"
-#include "strncmp.c"
-#include "subr_prf.c"
+ for (i = 0; i < bytes; i++)
+ dst[i] = src[i];
+}
diff --git a/plat/rockchip/common/pmusram/pmu_sram.h b/plat/rockchip/common/pmusram/pmu_sram.h
new file mode 100644
index 0000000..a2ab460
--- /dev/null
+++ b/plat/rockchip/common/pmusram/pmu_sram.h
@@ -0,0 +1,91 @@
+/* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PMU_SRAM_H__
+#define __PMU_SRAM_H__
+
+/*****************************************************************************
+ * cpu up status
+ *****************************************************************************/
+#define PMU_SYS_SLP_MODE 0xa5
+#define PMU_SYS_ON_MODE 0x0
+
+/*****************************************************************************
+ * define data offset in struct psram_data
+ *****************************************************************************/
+#define PSRAM_DT_SP 0x0
+#define PSRAM_DT_DDR_FUNC 0x8
+#define PSRAM_DT_DDR_DATA 0x10
+#define PSRAM_DT_DDRFLAG 0x18
+#define PSRAM_DT_SYS_MODE 0x1c
+#define PSRAM_DT_MPIDR 0x20
+#define PSRAM_DT_END 0x24
+/******************************************************************************
+ * Allocate data region for struct psram_data_t in pmusram
+ ******************************************************************************/
+/* Needed aligned 16 bytes for sp stack top */
+#define PSRAM_DT_SIZE (((PSRAM_DT_END + 16) / 16) * 16)
+#define PSRAM_DT_BASE ((PMUSRAM_BASE + PMUSRAM_RSIZE) - PSRAM_DT_SIZE)
+#define PSRAM_SP_TOP PSRAM_DT_BASE
+
+#ifndef __ASSEMBLY__
+
+/*
+ * The struct is used in pmu_cpus_on.S which
+ * gets the data of the struct by the following index
+ * #define PSRAM_DT_SP 0x0
+ * #define PSRAM_DT_DDR_FUNC 0x8
+ * #define PSRAM_DT_DDR_DATA 0x10
+ * #define PSRAM_DT_DDRFLAG 0x18
+ * #define PSRAM_DT_SYS_MODE 0x1c
+ * #define PSRAM_DT_MPIDR 0x20
+ */
+struct psram_data_t {
+ uint64_t sp;
+ uint64_t ddr_func;
+ uint64_t ddr_data;
+ uint32_t ddr_flag;
+ uint32_t sys_mode;
+ uint32_t boot_mpidr;
+};
+
+CASSERT(sizeof(struct psram_data_t) <= PSRAM_DT_SIZE,
+ assert_psram_dt_size_mismatch);
+CASSERT(__builtin_offsetof(struct psram_data_t, sp) == PSRAM_DT_SP,
+ assert_psram_dt_sp_offset_mistmatch);
+CASSERT(__builtin_offsetof(struct psram_data_t, ddr_func) == PSRAM_DT_DDR_FUNC,
+ assert_psram_dt_ddr_func_offset_mistmatch);
+CASSERT(__builtin_offsetof(struct psram_data_t, ddr_data) == PSRAM_DT_DDR_DATA,
+ assert_psram_dt_ddr_data_offset_mistmatch);
+CASSERT(__builtin_offsetof(struct psram_data_t, ddr_flag) == PSRAM_DT_DDRFLAG,
+ assert_psram_dt_ddr_flag_offset_mistmatch);
+CASSERT(__builtin_offsetof(struct psram_data_t, sys_mode) == PSRAM_DT_SYS_MODE,
+ assert_psram_dt_sys_mode_offset_mistmatch);
+CASSERT(__builtin_offsetof(struct psram_data_t, boot_mpidr) == PSRAM_DT_MPIDR,
+ assert_psram_dt_mpidr_offset_mistmatch);
+void u32_align_cpy(uint32_t *dst, const uint32_t *src, size_t bytes);
+#endif /* __ASSEMBLY__ */
+
+#endif
diff --git a/plat/rockchip/common/pmusram/pmu_sram_cpus_on.S b/plat/rockchip/common/pmusram/pmu_sram_cpus_on.S
new file mode 100644
index 0000000..33a4646
--- /dev/null
+++ b/plat/rockchip/common/pmusram/pmu_sram_cpus_on.S
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+#include <pmu_sram.h>
+
+ .globl pmu_cpuson_entrypoint_start
+ .globl pmu_cpuson_entrypoint_end
+
+func pmu_cpuson_entrypoint
+pmu_cpuson_entrypoint_start:
+ ldr x5, psram_data
+ ldr w0, [x5, #PSRAM_DT_SYS_MODE]
+ cmp w0, #PMU_SYS_SLP_MODE
+ b.eq check_wake_cpus
+ ldr x6, warm_boot_func
+ br x6
+check_wake_cpus:
+ mrs x0, MPIDR_EL1
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ orr x0, x0, x1
+ /* primary_cpu */
+ ldr w1, [x5, #PSRAM_DT_MPIDR]
+ cmp w0, w1
+ b.eq sys_wakeup
+ /*
+ * If the core is not the primary cpu,
+ * force the core into wfe.
+ */
+wfe_loop:
+ wfe
+ b wfe_loop
+sys_wakeup:
+ /* check ddr flag for resume ddr */
+ ldr w2, [x5, #PSRAM_DT_DDRFLAG]
+ cmp w2, #0x0
+ b.eq sys_resume
+ddr_resume:
+ ldr x2, [x5, #PSRAM_DT_SP]
+ mov sp, x2
+ ldr x1, [x5, #PSRAM_DT_DDR_FUNC]
+ ldr x0, [x5, #PSRAM_DT_DDR_DATA]
+ blr x1
+sys_resume:
+ ldr x1, sys_wakeup_entry
+ br x1
+
+ .align 3
+psram_data:
+ .quad PSRAM_DT_BASE
+warm_boot_func:
+ .quad platform_cpu_warmboot
+sys_wakeup_entry:
+ .quad psci_entrypoint
+pmu_cpuson_entrypoint_end:
+ .word 0
+endfunc pmu_cpuson_entrypoint
diff --git a/plat/rockchip/common/rockchip_gicv2.c b/plat/rockchip/common/rockchip_gicv2.c
new file mode 100644
index 0000000..3e1fa91
--- /dev/null
+++ b/plat/rockchip/common/rockchip_gicv2.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <bl_common.h>
+#include <gicv2.h>
+#include <platform_def.h>
+
+/******************************************************************************
+ * The following functions are defined as weak to allow a platform to override
+ * the way the GICv2 driver is initialised and used.
+ *****************************************************************************/
+#pragma weak plat_rockchip_gic_driver_init
+#pragma weak plat_rockchip_gic_init
+#pragma weak plat_rockchip_gic_cpuif_enable
+#pragma weak plat_rockchip_gic_cpuif_disable
+#pragma weak plat_rockchip_gic_pcpu_init
+
+/******************************************************************************
+ * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
+ * interrupts.
+ *****************************************************************************/
+const unsigned int g0_interrupt_array[] = {
+ PLAT_RK_G1S_IRQS,
+};
+
+/*
+ * Ideally `rockchip_gic_data` structure definition should be a `const` but it
+ * is kept as modifiable for overwriting with different GICD and GICC base when
+ * running on FVP with VE memory map.
+ */
+gicv2_driver_data_t rockchip_gic_data = {
+ .gicd_base = PLAT_RK_GICD_BASE,
+ .gicc_base = PLAT_RK_GICC_BASE,
+ .g0_interrupt_num = ARRAY_SIZE(g0_interrupt_array),
+ .g0_interrupt_array = g0_interrupt_array,
+};
+
+/******************************************************************************
+ * RockChip common helper to initialize the GICv2 only driver.
+ *****************************************************************************/
+void plat_rockchip_gic_driver_init(void)
+{
+ gicv2_driver_init(&rockchip_gic_data);
+}
+
+void plat_rockchip_gic_init(void)
+{
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+}
+
+/******************************************************************************
+ * RockChip common helper to enable the GICv2 CPU interface
+ *****************************************************************************/
+void plat_rockchip_gic_cpuif_enable(void)
+{
+ gicv2_cpuif_enable();
+}
+
+/******************************************************************************
+ * RockChip common helper to disable the GICv2 CPU interface
+ *****************************************************************************/
+void plat_rockchip_gic_cpuif_disable(void)
+{
+ gicv2_cpuif_disable();
+}
+
+/******************************************************************************
+ * RockChip common helper to initialize the per cpu distributor interface
+ * in GICv2
+ *****************************************************************************/
+void plat_rockchip_gic_pcpu_init(void)
+{
+ gicv2_pcpu_distif_init();
+}
diff --git a/plat/rockchip/common/rockchip_gicv3.c b/plat/rockchip/common/rockchip_gicv3.c
new file mode 100644
index 0000000..d197aba
--- /dev/null
+++ b/plat/rockchip/common/rockchip_gicv3.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <bl_common.h>
+#include <gicv3.h>
+#include <platform.h>
+#include <platform_def.h>
+
+/******************************************************************************
+ * The following functions are defined as weak to allow a platform to override
+ * the way the GICv3 driver is initialised and used.
+ *****************************************************************************/
+#pragma weak plat_rockchip_gic_driver_init
+#pragma weak plat_rockchip_gic_init
+#pragma weak plat_rockchip_gic_cpuif_enable
+#pragma weak plat_rockchip_gic_cpuif_disable
+#pragma weak plat_rockchip_gic_pcpu_init
+
+/* The GICv3 driver only needs to be initialized in EL3 */
+uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+/* Array of Group1 secure interrupts to be configured by the gic driver */
+const unsigned int g1s_interrupt_array[] = {
+ PLAT_RK_G1S_IRQS
+};
+
+/* Array of Group0 interrupts to be configured by the gic driver */
+const unsigned int g0_interrupt_array[] = {
+ PLAT_RK_G0_IRQS
+};
+
+static unsigned int plat_rockchip_mpidr_to_core_pos(unsigned long mpidr)
+{
+ return (unsigned int)plat_core_pos_by_mpidr(mpidr);
+}
+
+const gicv3_driver_data_t rockchip_gic_data = {
+ .gicd_base = PLAT_RK_GICD_BASE,
+ .gicr_base = PLAT_RK_GICR_BASE,
+ .g0_interrupt_num = ARRAY_SIZE(g0_interrupt_array),
+ .g1s_interrupt_num = ARRAY_SIZE(g1s_interrupt_array),
+ .g0_interrupt_array = g0_interrupt_array,
+ .g1s_interrupt_array = g1s_interrupt_array,
+ .rdistif_num = PLATFORM_CORE_COUNT,
+ .rdistif_base_addrs = rdistif_base_addrs,
+ .mpidr_to_core_pos = plat_rockchip_mpidr_to_core_pos,
+};
+
+void plat_rockchip_gic_driver_init(void)
+{
+ /*
+ * The GICv3 driver is initialized in EL3 and does not need
+ * to be initialized again in SEL1. This is because the S-EL1
+ * can use GIC system registers to manage interrupts and does
+ * not need GIC interface base addresses to be configured.
+ */
+#if IMAGE_BL31
+ gicv3_driver_init(&rockchip_gic_data);
+#endif
+}
+
+/******************************************************************************
+ * RockChip common helper to initialize the GIC. Only invoked
+ * by BL31
+ *****************************************************************************/
+void plat_rockchip_gic_init(void)
+{
+ gicv3_distif_init();
+ gicv3_rdistif_init(plat_my_core_pos());
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * RockChip common helper to enable the GIC CPU interface
+ *****************************************************************************/
+void plat_rockchip_gic_cpuif_enable(void)
+{
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * RockChip common helper to disable the GIC CPU interface
+ *****************************************************************************/
+void plat_rockchip_gic_cpuif_disable(void)
+{
+ gicv3_cpuif_disable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * RockChip common helper to initialize the per-cpu redistributor interface
+ * in GICv3
+ *****************************************************************************/
+void plat_rockchip_gic_pcpu_init(void)
+{
+ gicv3_rdistif_init(plat_my_core_pos());
+}
diff --git a/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.c b/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.c
new file mode 100644
index 0000000..cb89575
--- /dev/null
+++ b/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.c
@@ -0,0 +1,499 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <mmio.h>
+#include <ddr_rk3368.h>
+#include <debug.h>
+#include <stdint.h>
+#include <string.h>
+#include <platform_def.h>
+#include <pmu.h>
+#include <rk3368_def.h>
+#include <soc.h>
+
+/* GRF_SOC_STATUS0 */
+#define DPLL_LOCK (0x1 << 2)
+
+/* GRF_DDRC0_CON0 */
+#define GRF_DDR_16BIT_EN (((0x1 << 3) << 16) | (0x1 << 3))
+#define GRF_DDR_32BIT_EN (((0x1 << 3) << 16) | (0x0 << 3))
+#define GRF_MOBILE_DDR_EN (((0x1 << 4) << 16) | (0x1 << 4))
+#define GRF_MOBILE_DDR_DISB (((0x1 << 4) << 16) | (0x0 << 4))
+#define GRF_DDR3_EN (((0x1 << 2) << 16) | (0x1 << 2))
+#define GRF_LPDDR2_3_EN (((0x1 << 2) << 16) | (0x0 << 2))
+
+/* PMUGRF_SOC_CON0 */
+#define ddrphy_bufferen_io_en(n) ((0x1 << (9 + 16)) | (n << 9))
+#define ddrphy_bufferen_core_en(n) ((0x1 << (8 + 16)) | (n << 8))
+
+struct PCTRL_TIMING_TAG {
+ uint32_t ddrfreq;
+ uint32_t TOGCNT1U;
+ uint32_t TINIT;
+ uint32_t TRSTH;
+ uint32_t TOGCNT100N;
+ uint32_t TREFI;
+ uint32_t TMRD;
+ uint32_t TRFC;
+ uint32_t TRP;
+ uint32_t TRTW;
+ uint32_t TAL;
+ uint32_t TCL;
+ uint32_t TCWL;
+ uint32_t TRAS;
+ uint32_t TRC;
+ uint32_t TRCD;
+ uint32_t TRRD;
+ uint32_t TRTP;
+ uint32_t TWR;
+ uint32_t TWTR;
+ uint32_t TEXSR;
+ uint32_t TXP;
+ uint32_t TXPDLL;
+ uint32_t TZQCS;
+ uint32_t TZQCSI;
+ uint32_t TDQS;
+ uint32_t TCKSRE;
+ uint32_t TCKSRX;
+ uint32_t TCKE;
+ uint32_t TMOD;
+ uint32_t TRSTL;
+ uint32_t TZQCL;
+ uint32_t TMRR;
+ uint32_t TCKESR;
+ uint32_t TDPD;
+ uint32_t TREFI_MEM_DDR3;
+};
+
+struct MSCH_SAVE_REG_TAG {
+ uint32_t ddrconf;
+ uint32_t ddrtiming;
+ uint32_t ddrmode;
+ uint32_t readlatency;
+ uint32_t activate;
+ uint32_t devtodev;
+};
+
+/* ddr suspend need save reg */
+struct PCTL_SAVE_REG_TAG {
+ uint32_t SCFG;
+ uint32_t CMDTSTATEN;
+ uint32_t MCFG1;
+ uint32_t MCFG;
+ uint32_t PPCFG;
+ struct PCTRL_TIMING_TAG pctl_timing;
+ /* DFI Control Registers */
+ uint32_t DFITCTRLDELAY;
+ uint32_t DFIODTCFG;
+ uint32_t DFIODTCFG1;
+ uint32_t DFIODTRANKMAP;
+ /* DFI Write Data Registers */
+ uint32_t DFITPHYWRDATA;
+ uint32_t DFITPHYWRLAT;
+ uint32_t DFITPHYWRDATALAT;
+ /* DFI Read Data Registers */
+ uint32_t DFITRDDATAEN;
+ uint32_t DFITPHYRDLAT;
+ /* DFI Update Registers */
+ uint32_t DFITPHYUPDTYPE0;
+ uint32_t DFITPHYUPDTYPE1;
+ uint32_t DFITPHYUPDTYPE2;
+ uint32_t DFITPHYUPDTYPE3;
+ uint32_t DFITCTRLUPDMIN;
+ uint32_t DFITCTRLUPDMAX;
+ uint32_t DFITCTRLUPDDLY;
+ uint32_t DFIUPDCFG;
+ uint32_t DFITREFMSKI;
+ uint32_t DFITCTRLUPDI;
+ /* DFI Status Registers */
+ uint32_t DFISTCFG0;
+ uint32_t DFISTCFG1;
+ uint32_t DFITDRAMCLKEN;
+ uint32_t DFITDRAMCLKDIS;
+ uint32_t DFISTCFG2;
+ /* DFI Low Power Register */
+ uint32_t DFILPCFG0;
+};
+
+struct DDRPHY_SAVE_REG_TAG {
+ uint32_t PHY_REG0;
+ uint32_t PHY_REG1;
+ uint32_t PHY_REGB;
+ uint32_t PHY_REGC;
+ uint32_t PHY_REG11;
+ uint32_t PHY_REG13;
+ uint32_t PHY_REG14;
+ uint32_t PHY_REG16;
+ uint32_t PHY_REG20;
+ uint32_t PHY_REG21;
+ uint32_t PHY_REG26;
+ uint32_t PHY_REG27;
+ uint32_t PHY_REG28;
+ uint32_t PHY_REG30;
+ uint32_t PHY_REG31;
+ uint32_t PHY_REG36;
+ uint32_t PHY_REG37;
+ uint32_t PHY_REG38;
+ uint32_t PHY_REG40;
+ uint32_t PHY_REG41;
+ uint32_t PHY_REG46;
+ uint32_t PHY_REG47;
+ uint32_t PHY_REG48;
+ uint32_t PHY_REG50;
+ uint32_t PHY_REG51;
+ uint32_t PHY_REG56;
+ uint32_t PHY_REG57;
+ uint32_t PHY_REG58;
+ uint32_t PHY_REGDLL;
+ uint32_t PHY_REGEC;
+ uint32_t PHY_REGED;
+ uint32_t PHY_REGEE;
+ uint32_t PHY_REGEF;
+ uint32_t PHY_REGFB;
+ uint32_t PHY_REGFC;
+ uint32_t PHY_REGFD;
+ uint32_t PHY_REGFE;
+};
+
+struct BACKUP_REG_TAG {
+ uint32_t tag;
+ uint32_t pctladdr;
+ struct PCTL_SAVE_REG_TAG pctl;
+ uint32_t phyaddr;
+ struct DDRPHY_SAVE_REG_TAG phy;
+ uint32_t nocaddr;
+ struct MSCH_SAVE_REG_TAG noc;
+ uint32_t pllselect;
+ uint32_t phypllockaddr;
+ uint32_t phyplllockmask;
+ uint32_t phyplllockval;
+ uint32_t pllpdstat;
+ uint32_t dpllmodeaddr;
+ uint32_t dpllslowmode;
+ uint32_t dpllnormalmode;
+ uint32_t dpllresetaddr;
+ uint32_t dpllreset;
+ uint32_t dplldereset;
+ uint32_t dpllconaddr;
+ uint32_t dpllcon[4];
+ uint32_t dplllockaddr;
+ uint32_t dplllockmask;
+ uint32_t dplllockval;
+ uint32_t ddrpllsrcdivaddr;
+ uint32_t ddrpllsrcdiv;
+ uint32_t retendisaddr;
+ uint32_t retendisval;
+ uint32_t grfregaddr;
+ uint32_t grfddrcreg;
+ uint32_t crupctlphysoftrstaddr;
+ uint32_t cruresetpctlphy;
+ uint32_t cruderesetphy;
+ uint32_t cruderesetpctlphy;
+ uint32_t physoftrstaddr;
+ uint32_t endtag;
+};
+
+static uint32_t ddr_get_phy_pll_freq(void)
+{
+ uint32_t ret = 0;
+ uint32_t fb_div, pre_div;
+
+ fb_div = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGEC);
+ fb_div |= (mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGED) & 0x1) << 8;
+
+ pre_div = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGEE) & 0xff;
+ ret = 2 * 24 * fb_div / (4 * pre_div);
+
+ return ret;
+}
+
+static void ddr_copy(uint32_t *pdest, uint32_t *psrc, uint32_t words)
+{
+ uint32_t i;
+
+ for (i = 0; i < words; i++)
+ pdest[i] = psrc[i];
+}
+
+static void ddr_get_dpll_cfg(uint32_t *p)
+{
+ uint32_t nmhz, NO, NF, NR;
+
+ nmhz = ddr_get_phy_pll_freq();
+ if (nmhz <= 150)
+ NO = 6;
+ else if (nmhz <= 250)
+ NO = 4;
+ else if (nmhz <= 500)
+ NO = 2;
+ else
+ NO = 1;
+
+ NR = 1;
+ NF = 2 * nmhz * NR * NO / 24;
+
+ p[0] = SET_NR(NR) | SET_NO(NO);
+ p[1] = SET_NF(NF);
+ p[2] = SET_NB(NF / 2);
+}
+
+void ddr_reg_save(uint32_t pllpdstat, uint64_t base_addr)
+{
+ struct BACKUP_REG_TAG *p_ddr_reg = (struct BACKUP_REG_TAG *)base_addr;
+ struct PCTL_SAVE_REG_TAG *pctl_tim = &p_ddr_reg->pctl;
+
+ p_ddr_reg->tag = 0x56313031;
+ p_ddr_reg->pctladdr = DDR_PCTL_BASE;
+ p_ddr_reg->phyaddr = DDR_PHY_BASE;
+ p_ddr_reg->nocaddr = SERVICE_BUS_BASE;
+
+ /* PCTLR */
+ ddr_copy((uint32_t *)&pctl_tim->pctl_timing.TOGCNT1U,
+ (uint32_t *)(DDR_PCTL_BASE + DDR_PCTL_TOGCNT1U), 35);
+ pctl_tim->pctl_timing.TREFI |= DDR_UPD_REF_ENABLE;
+ pctl_tim->SCFG = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_SCFG);
+ pctl_tim->CMDTSTATEN = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_CMDTSTATEN);
+ pctl_tim->MCFG1 = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_MCFG1);
+ pctl_tim->MCFG = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_MCFG);
+ pctl_tim->PPCFG = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_PPCFG);
+ pctl_tim->pctl_timing.ddrfreq = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_TOGCNT1U * 2);
+ pctl_tim->DFITCTRLDELAY = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITCTRLDELAY);
+ pctl_tim->DFIODTCFG = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFIODTCFG);
+ pctl_tim->DFIODTCFG1 = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFIODTCFG1);
+ pctl_tim->DFIODTRANKMAP = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFIODTRANKMAP);
+ pctl_tim->DFITPHYWRDATA = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITPHYWRDATA);
+ pctl_tim->DFITPHYWRLAT = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITPHYWRLAT);
+ pctl_tim->DFITPHYWRDATALAT = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITPHYWRDATALAT);
+ pctl_tim->DFITRDDATAEN = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITRDDATAEN);
+ pctl_tim->DFITPHYRDLAT = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITPHYRDLAT);
+ pctl_tim->DFITPHYUPDTYPE0 = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITPHYUPDTYPE0);
+ pctl_tim->DFITPHYUPDTYPE1 = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITPHYUPDTYPE1);
+ pctl_tim->DFITPHYUPDTYPE2 = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITPHYUPDTYPE2);
+ pctl_tim->DFITPHYUPDTYPE3 = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITPHYUPDTYPE3);
+ pctl_tim->DFITCTRLUPDMIN = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITCTRLUPDMIN);
+ pctl_tim->DFITCTRLUPDMAX = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITCTRLUPDMAX);
+ pctl_tim->DFITCTRLUPDDLY = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITCTRLUPDDLY);
+
+ pctl_tim->DFIUPDCFG = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFIUPDCFG);
+ pctl_tim->DFITREFMSKI = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITREFMSKI);
+ pctl_tim->DFITCTRLUPDI = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITCTRLUPDI);
+ pctl_tim->DFISTCFG0 = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFISTCFG0);
+ pctl_tim->DFISTCFG1 = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFISTCFG1);
+ pctl_tim->DFITDRAMCLKEN = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITDRAMCLKEN);
+ pctl_tim->DFITDRAMCLKDIS = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITDRAMCLKDIS);
+ pctl_tim->DFISTCFG2 = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFISTCFG2);
+ pctl_tim->DFILPCFG0 = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFILPCFG0);
+
+ /* PHY */
+ p_ddr_reg->phy.PHY_REG0 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG0);
+ p_ddr_reg->phy.PHY_REG1 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG1);
+ p_ddr_reg->phy.PHY_REGB = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGB);
+ p_ddr_reg->phy.PHY_REGC = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGC);
+ p_ddr_reg->phy.PHY_REG11 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG11);
+ p_ddr_reg->phy.PHY_REG13 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG13);
+ p_ddr_reg->phy.PHY_REG14 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG14);
+ p_ddr_reg->phy.PHY_REG16 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG16);
+ p_ddr_reg->phy.PHY_REG20 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG20);
+ p_ddr_reg->phy.PHY_REG21 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG21);
+ p_ddr_reg->phy.PHY_REG26 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG26);
+ p_ddr_reg->phy.PHY_REG27 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG27);
+ p_ddr_reg->phy.PHY_REG28 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG28);
+ p_ddr_reg->phy.PHY_REG30 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG30);
+ p_ddr_reg->phy.PHY_REG31 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG31);
+ p_ddr_reg->phy.PHY_REG36 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG36);
+ p_ddr_reg->phy.PHY_REG37 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG37);
+ p_ddr_reg->phy.PHY_REG38 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG38);
+ p_ddr_reg->phy.PHY_REG40 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG40);
+ p_ddr_reg->phy.PHY_REG41 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG41);
+ p_ddr_reg->phy.PHY_REG46 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG46);
+ p_ddr_reg->phy.PHY_REG47 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG47);
+ p_ddr_reg->phy.PHY_REG48 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG48);
+ p_ddr_reg->phy.PHY_REG50 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG50);
+ p_ddr_reg->phy.PHY_REG51 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG51);
+ p_ddr_reg->phy.PHY_REG56 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG56);
+ p_ddr_reg->phy.PHY_REG57 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG57);
+ p_ddr_reg->phy.PHY_REG58 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG58);
+ p_ddr_reg->phy.PHY_REGDLL = mmio_read_32(DDR_PHY_BASE +
+ DDR_PHY_REGDLL);
+ p_ddr_reg->phy.PHY_REGEC = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGEC);
+ p_ddr_reg->phy.PHY_REGED = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGED);
+ p_ddr_reg->phy.PHY_REGEE = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGEE);
+ p_ddr_reg->phy.PHY_REGEF = 0;
+
+ if (mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG2) & 0x2) {
+ p_ddr_reg->phy.PHY_REGFB = mmio_read_32(DDR_PHY_BASE +
+ DDR_PHY_REG2C);
+ p_ddr_reg->phy.PHY_REGFC = mmio_read_32(DDR_PHY_BASE +
+ DDR_PHY_REG3C);
+ p_ddr_reg->phy.PHY_REGFD = mmio_read_32(DDR_PHY_BASE +
+ DDR_PHY_REG4C);
+ p_ddr_reg->phy.PHY_REGFE = mmio_read_32(DDR_PHY_BASE +
+ DDR_PHY_REG5C);
+ } else {
+ p_ddr_reg->phy.PHY_REGFB = mmio_read_32(DDR_PHY_BASE +
+ DDR_PHY_REGFB);
+ p_ddr_reg->phy.PHY_REGFC = mmio_read_32(DDR_PHY_BASE +
+ DDR_PHY_REGFC);
+ p_ddr_reg->phy.PHY_REGFD = mmio_read_32(DDR_PHY_BASE +
+ DDR_PHY_REGFD);
+ p_ddr_reg->phy.PHY_REGFE = mmio_read_32(DDR_PHY_BASE +
+ DDR_PHY_REGFE);
+ }
+
+ /* NOC */
+ p_ddr_reg->noc.ddrconf = mmio_read_32(SERVICE_BUS_BASE + MSCH_DDRCONF);
+ p_ddr_reg->noc.ddrtiming = mmio_read_32(SERVICE_BUS_BASE +
+ MSCH_DDRTIMING);
+ p_ddr_reg->noc.ddrmode = mmio_read_32(SERVICE_BUS_BASE + MSCH_DDRMODE);
+ p_ddr_reg->noc.readlatency = mmio_read_32(SERVICE_BUS_BASE +
+ MSCH_READLATENCY);
+ p_ddr_reg->noc.activate = mmio_read_32(SERVICE_BUS_BASE +
+ MSCH_ACTIVATE);
+ p_ddr_reg->noc.devtodev = mmio_read_32(SERVICE_BUS_BASE +
+ MSCH_DEVTODEV);
+
+ p_ddr_reg->pllselect = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGEE) * 0x1;
+ p_ddr_reg->phypllockaddr = GRF_BASE + GRF_SOC_STATUS0;
+ p_ddr_reg->phyplllockmask = GRF_DDRPHY_LOCK;
+ p_ddr_reg->phyplllockval = 0;
+
+ /* PLLPD */
+ p_ddr_reg->pllpdstat = pllpdstat;
+ /* DPLL */
+ p_ddr_reg->dpllmodeaddr = CRU_BASE + PLL_CONS(DPLL_ID, 3);
+ /* slow mode and power on */
+ p_ddr_reg->dpllslowmode = DPLL_WORK_SLOW_MODE | DPLL_POWER_DOWN;
+ p_ddr_reg->dpllnormalmode = DPLL_WORK_NORMAL_MODE;
+ p_ddr_reg->dpllresetaddr = CRU_BASE + PLL_CONS(DPLL_ID, 3);
+ p_ddr_reg->dpllreset = DPLL_RESET_CONTROL_NORMAL;
+ p_ddr_reg->dplldereset = DPLL_RESET_CONTROL_RESET;
+ p_ddr_reg->dpllconaddr = CRU_BASE + PLL_CONS(DPLL_ID, 0);
+
+ if (p_ddr_reg->pllselect == 0) {
+ p_ddr_reg->dpllcon[0] = (mmio_read_32(CRU_BASE +
+ PLL_CONS(DPLL_ID, 0))
+ & 0xffff) |
+ (0xFFFF << 16);
+ p_ddr_reg->dpllcon[1] = (mmio_read_32(CRU_BASE +
+ PLL_CONS(DPLL_ID, 1))
+ & 0xffff);
+ p_ddr_reg->dpllcon[2] = (mmio_read_32(CRU_BASE +
+ PLL_CONS(DPLL_ID, 2))
+ & 0xffff);
+ p_ddr_reg->dpllcon[3] = (mmio_read_32(CRU_BASE +
+ PLL_CONS(DPLL_ID, 3))
+ & 0xffff) |
+ (0xFFFF << 16);
+ } else {
+ ddr_get_dpll_cfg(&p_ddr_reg->dpllcon[0]);
+ }
+
+ p_ddr_reg->pllselect = 0;
+ p_ddr_reg->dplllockaddr = CRU_BASE + PLL_CONS(DPLL_ID, 1);
+ p_ddr_reg->dplllockmask = DPLL_STATUS_LOCK;
+ p_ddr_reg->dplllockval = DPLL_STATUS_LOCK;
+
+ /* SET_DDR_PLL_SRC */
+ p_ddr_reg->ddrpllsrcdivaddr = CRU_BASE + CRU_CLKSELS_CON(13);
+ p_ddr_reg->ddrpllsrcdiv = (mmio_read_32(CRU_BASE + CRU_CLKSELS_CON(13))
+ & DDR_PLL_SRC_MASK)
+ | (DDR_PLL_SRC_MASK << 16);
+ p_ddr_reg->retendisaddr = PMU_BASE + PMU_PWRMD_COM;
+ p_ddr_reg->retendisval = PD_PERI_PWRDN_ENABLE;
+ p_ddr_reg->grfregaddr = GRF_BASE + GRF_DDRC0_CON0;
+ p_ddr_reg->grfddrcreg = (mmio_read_32(GRF_BASE + GRF_DDRC0_CON0) &
+ DDR_PLL_SRC_MASK) |
+ (DDR_PLL_SRC_MASK << 16);
+
+ /* pctl phy soft reset */
+ p_ddr_reg->crupctlphysoftrstaddr = CRU_BASE + CRU_SOFTRSTS_CON(10);
+ p_ddr_reg->cruresetpctlphy = DDRCTRL0_PSRSTN_REQ(1) |
+ DDRCTRL0_SRSTN_REQ(1) |
+ DDRPHY0_PSRSTN_REQ(1) |
+ DDRPHY0_SRSTN_REQ(1);
+ p_ddr_reg->cruderesetphy = DDRCTRL0_PSRSTN_REQ(1) |
+ DDRCTRL0_SRSTN_REQ(1) |
+ DDRPHY0_PSRSTN_REQ(0) |
+ DDRPHY0_SRSTN_REQ(0);
+
+ p_ddr_reg->cruderesetpctlphy = DDRCTRL0_PSRSTN_REQ(0) |
+ DDRCTRL0_SRSTN_REQ(0) |
+ DDRPHY0_PSRSTN_REQ(0) |
+ DDRPHY0_SRSTN_REQ(0);
+
+ p_ddr_reg->physoftrstaddr = DDR_PHY_BASE + DDR_PHY_REG0;
+
+ p_ddr_reg->endtag = 0xFFFFFFFF;
+}
+
+/*
+ * "rk3368_ddr_reg_resume_V1.05.bin" is an executable bin which is generated
+ * by ARM DS5 for resuming ddr controller. If the soc wakes up from system
+ * suspend, ddr needs to be resumed and the resuming code needs to be run in
+ * sram. But there is not a way to pointing the resuming code to the PMUSRAM
+ * when linking .o files of bl31, so we use the
+ * "rk3368_ddr_reg_resume_V1.05.bin" whose code is position-independent and
+ * it can be loaded anywhere and run.
+ */
+static __aligned(4) unsigned int ddr_reg_resume[] = {
+ #include "rk3368_ddr_reg_resume_V1.05.bin"
+};
+
+uint32_t ddr_get_resume_code_size(void)
+{
+ return sizeof(ddr_reg_resume);
+}
+
+uint32_t ddr_get_resume_data_size(void)
+{
+ return sizeof(struct BACKUP_REG_TAG);
+}
+
+uint32_t *ddr_get_resume_code_base(void)
+{
+ return (unsigned int *)ddr_reg_resume;
+}
diff --git a/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.h b/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.h
new file mode 100644
index 0000000..c9d6c25
--- /dev/null
+++ b/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.h
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DDR_RK3368_H__
+#define __DDR_RK3368_H__
+
+#define DDR_PCTL_SCFG 0x0
+#define DDR_PCTL_SCTL 0x4
+#define DDR_PCTL_STAT 0x8
+#define DDR_PCTL_INTRSTAT 0xc
+
+#define DDR_PCTL_MCMD 0x40
+#define DDR_PCTL_POWCTL 0x44
+#define DDR_PCTL_POWSTAT 0x48
+#define DDR_PCTL_CMDTSTAT 0x4c
+#define DDR_PCTL_CMDTSTATEN 0x50
+#define DDR_PCTL_MRRCFG0 0x60
+#define DDR_PCTL_MRRSTAT0 0x64
+#define DDR_PCTL_MRRSTAT1 0x68
+#define DDR_PCTL_MCFG1 0x7c
+#define DDR_PCTL_MCFG 0x80
+#define DDR_PCTL_PPCFG 0x84
+#define DDR_PCTL_MSTAT 0x88
+#define DDR_PCTL_LPDDR2ZQCFG 0x8c
+#define DDR_PCTL_DTUPDES 0x94
+#define DDR_PCTL_DTUNA 0x98
+#define DDR_PCTL_DTUNE 0x9c
+#define DDR_PCTL_DTUPRD0 0xa0
+#define DDR_PCTL_DTUPRD1 0xa4
+#define DDR_PCTL_DTUPRD2 0xa8
+#define DDR_PCTL_DTUPRD3 0xac
+#define DDR_PCTL_DTUAWDT 0xb0
+#define DDR_PCTL_TOGCNT1U 0xc0
+#define DDR_PCTL_TINIT 0xc4
+#define DDR_PCTL_TRSTH 0xc8
+#define DDR_PCTL_TOGCNT100N 0xcc
+#define DDR_PCTL_TREFI 0xd0
+#define DDR_PCTL_TMRD 0xd4
+#define DDR_PCTL_TRFC 0xd8
+#define DDR_PCTL_TRP 0xdc
+#define DDR_PCTL_TRTW 0xe0
+#define DDR_PCTL_TAL 0xe4
+#define DDR_PCTL_TCL 0xe8
+#define DDR_PCTL_TCWL 0xec
+#define DDR_PCTL_TRAS 0xf0
+#define DDR_PCTL_TRC 0xf4
+#define DDR_PCTL_TRCD 0xf8
+#define DDR_PCTL_TRRD 0xfc
+#define DDR_PCTL_TRTP 0x100
+#define DDR_PCTL_TWR 0x104
+#define DDR_PCTL_TWTR 0x108
+#define DDR_PCTL_TEXSR 0x10c
+#define DDR_PCTL_TXP 0x110
+#define DDR_PCTL_TXPDLL 0x114
+#define DDR_PCTL_TZQCS 0x118
+#define DDR_PCTL_TZQCSI 0x11c
+#define DDR_PCTL_TDQS 0x120
+#define DDR_PCTL_TCKSRE 0x124
+#define DDR_PCTL_TCKSRX 0x128
+#define DDR_PCTL_TCKE 0x12c
+#define DDR_PCTL_TMOD 0x130
+#define DDR_PCTL_TRSTL 0x134
+#define DDR_PCTL_TZQCL 0x138
+#define DDR_PCTL_TMRR 0x13c
+#define DDR_PCTL_TCKESR 0x140
+#define DDR_PCTL_TDPD 0x144
+#define DDR_PCTL_TREFI_MEM_DDR3 0x148
+#define DDR_PCTL_ECCCFG 0x180
+#define DDR_PCTL_ECCTST 0x184
+#define DDR_PCTL_ECCCLR 0x188
+#define DDR_PCTL_ECCLOG 0x18c
+#define DDR_PCTL_DTUWACTL 0x200
+#define DDR_PCTL_DTURACTL 0x204
+#define DDR_PCTL_DTUCFG 0x208
+#define DDR_PCTL_DTUECTL 0x20c
+#define DDR_PCTL_DTUWD0 0x210
+#define DDR_PCTL_DTUWD1 0x214
+#define DDR_PCTL_DTUWD2 0x218
+#define DDR_PCTL_DTUWD3 0x21c
+#define DDR_PCTL_DTUWDM 0x220
+#define DDR_PCTL_DTURD0 0x224
+#define DDR_PCTL_DTURD1 0x228
+#define DDR_PCTL_DTURD2 0x22c
+#define DDR_PCTL_DTURD3 0x230
+#define DDR_PCTL_DTULFSRWD 0x234
+#define DDR_PCTL_DTULFSRRD 0x238
+#define DDR_PCTL_DTUEAF 0x23c
+#define DDR_PCTL_DFITCTRLDELAY 0x240
+#define DDR_PCTL_DFIODTCFG 0x244
+#define DDR_PCTL_DFIODTCFG1 0x248
+#define DDR_PCTL_DFIODTRANKMAP 0x24c
+#define DDR_PCTL_DFITPHYWRDATA 0x250
+#define DDR_PCTL_DFITPHYWRLAT 0x254
+#define DDR_PCTL_DFITPHYWRDATALAT 0x258
+#define DDR_PCTL_DFITRDDATAEN 0x260
+#define DDR_PCTL_DFITPHYRDLAT 0x264
+#define DDR_PCTL_DFITPHYUPDTYPE0 0x270
+#define DDR_PCTL_DFITPHYUPDTYPE1 0x274
+#define DDR_PCTL_DFITPHYUPDTYPE2 0x278
+#define DDR_PCTL_DFITPHYUPDTYPE3 0x27c
+#define DDR_PCTL_DFITCTRLUPDMIN 0x280
+#define DDR_PCTL_DFITCTRLUPDMAX 0x284
+#define DDR_PCTL_DFITCTRLUPDDLY 0x288
+#define DDR_PCTL_DFIUPDCFG 0x290
+#define DDR_PCTL_DFITREFMSKI 0x294
+#define DDR_PCTL_DFITCTRLUPDI 0x298
+#define DDR_PCTL_DFITRCFG0 0x2ac
+#define DDR_PCTL_DFITRSTAT0 0x2b0
+#define DDR_PCTL_DFITRWRLVLEN 0x2b4
+#define DDR_PCTL_DFITRRDLVLEN 0x2b8
+#define DDR_PCTL_DFITRRDLVLGATEEN 0x2bc
+#define DDR_PCTL_DFISTSTAT0 0x2c0
+#define DDR_PCTL_DFISTCFG0 0x2c4
+#define DDR_PCTL_DFISTCFG1 0x2c8
+#define DDR_PCTL_DFITDRAMCLKEN 0x2d0
+#define DDR_PCTL_DFITDRAMCLKDIS 0x2d4
+#define DDR_PCTL_DFISTCFG2 0x2d8
+#define DDR_PCTL_DFISTPARCLR 0x2dc
+#define DDR_PCTL_DFISTPARLOG 0x2e0
+#define DDR_PCTL_DFILPCFG0 0x2f0
+#define DDR_PCTL_DFITRWRLVLRESP0 0x300
+#define DDR_PCTL_DFITRWRLVLRESP1 0x304
+#define DDR_PCTL_DFITRWRLVLRESP2 0x308
+#define DDR_PCTL_DFITRRDLVLRESP0 0x30c
+#define DDR_PCTL_DFITRRDLVLRESP1 0x310
+#define DDR_PCTL_DFITRRDLVLRESP2 0x314
+#define DDR_PCTL_DFITRWRLVLDELAY0 0x318
+#define DDR_PCTL_DFITRWRLVLDELAY1 0x31c
+#define DDR_PCTL_DFITRWRLVLDELAY2 0x320
+#define DDR_PCTL_DFITRRDLVLDELAY0 0x324
+#define DDR_PCTL_DFITRRDLVLDELAY1 0x328
+#define DDR_PCTL_DFITRRDLVLDELAY2 0x32c
+#define DDR_PCTL_DFITRRDLVLGATEDELAY0 0x330
+#define DDR_PCTL_DFITRRDLVLGATEDELAY1 0x334
+#define DDR_PCTL_DFITRRDLVLGATEDELAY2 0x338
+#define DDR_PCTL_DFITRCMD 0x33c
+#define DDR_PCTL_IPVR 0x3f8
+#define DDR_PCTL_IPTR 0x3fc
+
+/* DDR PHY REG */
+#define DDR_PHY_REG0 0x0
+#define DDR_PHY_REG1 0x4
+#define DDR_PHY_REG2 0x8
+#define DDR_PHY_REG3 0xc
+#define DDR_PHY_REG4 0x10
+#define DDR_PHY_REG5 0x14
+#define DDR_PHY_REG6 0x18
+#define DDR_PHY_REGB 0x2c
+#define DDR_PHY_REGC 0x30
+#define DDR_PHY_REG11 0x44
+#define DDR_PHY_REG12 0x48
+#define DDR_PHY_REG13 0x4c
+#define DDR_PHY_REG14 0x50
+#define DDR_PHY_REG16 0x58
+#define DDR_PHY_REG20 0x80
+#define DDR_PHY_REG21 0x84
+#define DDR_PHY_REG26 0x98
+#define DDR_PHY_REG27 0x9c
+#define DDR_PHY_REG28 0xa0
+#define DDR_PHY_REG2C 0xb0
+#define DDR_PHY_REG30 0xc0
+#define DDR_PHY_REG31 0xc4
+#define DDR_PHY_REG36 0xd8
+#define DDR_PHY_REG37 0xdc
+#define DDR_PHY_REG38 0xe0
+#define DDR_PHY_REG3C 0xf0
+#define DDR_PHY_REG40 0x100
+#define DDR_PHY_REG41 0x104
+#define DDR_PHY_REG46 0x118
+#define DDR_PHY_REG47 0x11c
+#define DDR_PHY_REG48 0x120
+#define DDR_PHY_REG4C 0x130
+#define DDR_PHY_REG50 0x140
+#define DDR_PHY_REG51 0x144
+#define DDR_PHY_REG56 0x158
+#define DDR_PHY_REG57 0x15c
+#define DDR_PHY_REG58 0x160
+#define DDR_PHY_REG5C 0x170
+#define DDR_PHY_REGDLL 0x290
+#define DDR_PHY_REGEC 0x3b0
+#define DDR_PHY_REGED 0x3b4
+#define DDR_PHY_REGEE 0x3b8
+#define DDR_PHY_REGEF 0x3bc
+#define DDR_PHY_REGF0 0x3c0
+#define DDR_PHY_REGF1 0x3c4
+#define DDR_PHY_REGF2 0x3c8
+#define DDR_PHY_REGFA 0x3e8
+#define DDR_PHY_REGFB 0x3ec
+#define DDR_PHY_REGFC 0x3f0
+#define DDR_PHY_REGFD 0x3f4
+#define DDR_PHY_REGFE 0x3f8
+#define DDR_PHY_REGFF 0x3fc
+
+/* MSCH REG define */
+#define MSCH_COREID 0x0
+#define MSCH_DDRCONF 0x8
+#define MSCH_DDRTIMING 0xc
+#define MSCH_DDRMODE 0x10
+#define MSCH_READLATENCY 0x14
+#define MSCH_ACTIVATE 0x38
+#define MSCH_DEVTODEV 0x3c
+
+#define SET_NR(n) ((0x3f << (8 + 16)) | ((n - 1) << 8))
+#define SET_NO(n) ((0xf << (0 + 16)) | ((n - 1) << 0))
+#define SET_NF(n) ((n - 1) & 0x1fff)
+#define SET_NB(n) ((n - 1) & 0xfff)
+#define PLLMODE(n) ((0x3 << (8 + 16)) | (n << 8))
+
+/* GRF REG define */
+#define GRF_SOC_STATUS0 0x480
+#define GRF_DDRPHY_LOCK (0x1 << 15)
+#define GRF_DDRC0_CON0 0x600
+
+/* CRU softreset ddr pctl, phy */
+#define DDRMSCH0_SRSTN_REQ(n) (((0x1 << 10) << 16) | (n << 10))
+#define DDRCTRL0_PSRSTN_REQ(n) (((0x1 << 3) << 16) | (n << 3))
+#define DDRCTRL0_SRSTN_REQ(n) (((0x1 << 2) << 16) | (n << 2))
+#define DDRPHY0_PSRSTN_REQ(n) (((0x1 << 1) << 16) | (n << 1))
+#define DDRPHY0_SRSTN_REQ(n) (((0x1 << 0) << 16) | (n << 0))
+
+/* CRU_DPLL_CON2 */
+#define DPLL_STATUS_LOCK (1 << 31)
+
+/* CRU_DPLL_CON3 */
+#define DPLL_POWER_DOWN ((0x1 << (1 + 16)) | (0 << 1))
+#define DPLL_WORK_NORMAL_MODE ((0x3 << (8 + 16)) | (0 << 8))
+#define DPLL_WORK_SLOW_MODE ((0x3 << (8 + 16)) | (1 << 8))
+#define DPLL_RESET_CONTROL_NORMAL ((0x1 << (5 + 16)) | (0x0 << 5))
+#define DPLL_RESET_CONTROL_RESET ((0x1 << (5 + 16)) | (0x1 << 5))
+
+/* PMU_PWRDN_CON */
+#define PD_PERI_PWRDN_ENABLE (1 << 13)
+
+#define DDR_PLL_SRC_MASK 0x13
+
+/* DDR_PCTL_TREFI */
+#define DDR_UPD_REF_ENABLE (0X1 << 31)
+
+uint32_t ddr_get_resume_code_size(void);
+uint32_t ddr_get_resume_data_size(void);
+uint32_t *ddr_get_resume_code_base(void);
+void ddr_reg_save(uint32_t pllpdstat, uint64_t base_addr);
+
+#endif
diff --git a/plat/rockchip/rk3368/drivers/ddr/rk3368_ddr_reg_resume_V1.05.bin b/plat/rockchip/rk3368/drivers/ddr/rk3368_ddr_reg_resume_V1.05.bin
new file mode 100644
index 0000000..cecd694
--- /dev/null
+++ b/plat/rockchip/rk3368/drivers/ddr/rk3368_ddr_reg_resume_V1.05.bin
@@ -0,0 +1,461 @@
+ 0x14000088,
+ 0xd10043ff,
+ 0x5283ffe1,
+ 0x52824902,
+ 0x1b020400,
+ 0x530d7c00,
+ 0xb9000fe0,
+ 0xb9400fe0,
+ 0x340000a0,
+ 0xb9400fe0,
+ 0x51000401,
+ 0xb9000fe1,
+ 0x35ffffa0,
+ 0x910043ff,
+ 0xd65f03c0,
+ 0x340000e2,
+ 0xb9400023,
+ 0xb9000003,
+ 0x91001021,
+ 0x91001000,
+ 0x51000442,
+ 0x35ffff62,
+ 0xd65f03c0,
+ 0xd10043ff,
+ 0xb9400801,
+ 0x12000821,
+ 0xb9000fe1,
+ 0xb9400fe1,
+ 0x7100043f,
+ 0x54000320,
+ 0x52800021,
+ 0x52800082,
+ 0xb9400fe3,
+ 0x34000143,
+ 0x71000c7f,
+ 0x54000100,
+ 0x7100147f,
+ 0x54000161,
+ 0xb9000402,
+ 0xb9400803,
+ 0x12000863,
+ 0x71000c7f,
+ 0x54ffffa1,
+ 0xb9000401,
+ 0xb9400803,
+ 0x12000863,
+ 0x7100047f,
+ 0x54ffffa1,
+ 0xb9400803,
+ 0x12000863,
+ 0xb9000fe3,
+ 0xb9400fe3,
+ 0x7100047f,
+ 0x54fffd61,
+ 0x910043ff,
+ 0xd65f03c0,
+ 0xd10043ff,
+ 0xb9400801,
+ 0x12000821,
+ 0xb9000fe1,
+ 0xb9400fe1,
+ 0x7100143f,
+ 0x54000400,
+ 0x52800021,
+ 0x52800042,
+ 0x52800063,
+ 0xb9400fe4,
+ 0x340000c4,
+ 0x7100049f,
+ 0x54000120,
+ 0x71000c9f,
+ 0x54000180,
+ 0x14000010,
+ 0xb9000401,
+ 0xb9400804,
+ 0x12000884,
+ 0x7100049f,
+ 0x54ffffa1,
+ 0xb9000402,
+ 0xb9400804,
+ 0x12000884,
+ 0x71000c9f,
+ 0x54ffffa1,
+ 0xb9000403,
+ 0xb9400804,
+ 0x12000884,
+ 0x7100149f,
+ 0x54ffffa1,
+ 0xb9400804,
+ 0x12000884,
+ 0xb9000fe4,
+ 0xb9400fe4,
+ 0x7100149f,
+ 0x54fffca1,
+ 0x910043ff,
+ 0xd65f03c0,
+ 0xd10043ff,
+ 0xb9400801,
+ 0x12000821,
+ 0xb9000fe1,
+ 0xb9400fe1,
+ 0x71000c3f,
+ 0x54000400,
+ 0x52800021,
+ 0x52800042,
+ 0x52800083,
+ 0xb9400fe4,
+ 0x34000164,
+ 0x7100049f,
+ 0x540001c0,
+ 0x7100149f,
+ 0x54000221,
+ 0xb9000403,
+ 0xb9400804,
+ 0x12000884,
+ 0x71000c9f,
+ 0x54ffffa1,
+ 0x1400000b,
+ 0xb9000401,
+ 0xb9400804,
+ 0x12000884,
+ 0x7100049f,
+ 0x54ffffa1,
+ 0xb9000402,
+ 0xb9400804,
+ 0x12000884,
+ 0x71000c9f,
+ 0x54ffffa1,
+ 0xb9400804,
+ 0x12000884,
+ 0xb9000fe4,
+ 0xb9400fe4,
+ 0x71000c9f,
+ 0x54fffca1,
+ 0x910043ff,
+ 0xd65f03c0,
+ 0xd10103ff,
+ 0xa9037bfd,
+ 0x9100c3fd,
+ 0xa9025ff6,
+ 0xa90157f4,
+ 0xf90007f3,
+ 0xaa0003f3,
+ 0xb9400674,
+ 0xb9411276,
+ 0xb941c660,
+ 0xb941aa75,
+ 0x7100041f,
+ 0x54000261,
+ 0xb9418e60,
+ 0x321f0000,
+ 0xb903b6c0,
+ 0xb9418a60,
+ 0xb903b2c0,
+ 0xb9419260,
+ 0xb903bac0,
+ 0xb9418e60,
+ 0x121e7800,
+ 0xb903b6c0,
+ 0xb941ca60,
+ 0xb941ce61,
+ 0xb941d262,
+ 0xb9400003,
+ 0xa030023,
+ 0x6b22407f,
+ 0x54ffffa0,
+ 0x1400003b,
+ 0xb941d660,
+ 0x7100041f,
+ 0x54000701,
+ 0xb941da60,
+ 0x3100041f,
+ 0x54000080,
+ 0xb941de61,
+ 0x53007c00,
+ 0xb9000001,
+ 0xb941e660,
+ 0x3100041f,
+ 0x54000080,
+ 0xb941ea61,
+ 0x53007c00,
+ 0xb9000001,
+ 0xb941f260,
+ 0x3100041f,
+ 0x54000120,
+ 0xaa1f03e1,
+ 0x53007c00,
+ 0x9107d262,
+ 0xb8616843,
+ 0xb8216803,
+ 0x91001021,
+ 0xf100203f,
+ 0x54ffff81,
+ 0x52800020,
+ 0x97ffff3f,
+ 0xb941e660,
+ 0x3100041f,
+ 0x54000080,
+ 0xb941ee61,
+ 0x53007c00,
+ 0xb9000001,
+ 0x52800020,
+ 0x97ffff37,
+ 0xb9420660,
+ 0x3100041f,
+ 0x54000100,
+ 0xb9420a61,
+ 0xb9420e62,
+ 0x53007c00,
+ 0xb9400003,
+ 0xa030023,
+ 0x6b22407f,
+ 0x54ffffa1,
+ 0xb9421260,
+ 0x3100041f,
+ 0x54000080,
+ 0xb9421661,
+ 0x53007c00,
+ 0xb9000001,
+ 0xb941da60,
+ 0x3100041f,
+ 0x54000080,
+ 0xb941e261,
+ 0x53007c00,
+ 0xb9000001,
+ 0xb9419660,
+ 0xb903bec0,
+ 0xb9422a60,
+ 0x34000400,
+ 0xb9422e61,
+ 0x53007c17,
+ 0xb90002e1,
+ 0x52800140,
+ 0x97ffff18,
+ 0xb9423260,
+ 0xb90002e0,
+ 0x52800140,
+ 0x97ffff14,
+ 0xb9423660,
+ 0xb90002e0,
+ 0x52800140,
+ 0x97ffff10,
+ 0xb9423a60,
+ 0x34000220,
+ 0x53007c17,
+ 0xb94002e0,
+ 0x121c7400,
+ 0xb90002e0,
+ 0x52800020,
+ 0x97ffff08,
+ 0xb94002e0,
+ 0x321e0000,
+ 0xb90002e0,
+ 0x528000a0,
+ 0x97ffff03,
+ 0xb94002e0,
+ 0x321d0000,
+ 0xb90002e0,
+ 0x52800020,
+ 0x97fffefe,
+ 0xb9412a60,
+ 0xb9004ec0,
+ 0xb9412e60,
+ 0xb90052c0,
+ 0xb9413e60,
+ 0xb9009ac0,
+ 0xb9414260,
+ 0xb9009ec0,
+ 0xb9415260,
+ 0xb900dac0,
+ 0xb9415660,
+ 0xb900dec0,
+ 0xb9416660,
+ 0xb9011ac0,
+ 0xb9416a60,
+ 0xb9011ec0,
+ 0xb9417a60,
+ 0xb9015ac0,
+ 0xb9417e60,
+ 0xb9015ec0,
+ 0xb9418660,
+ 0xb90292c0,
+ 0xb9414660,
+ 0xb900a2c0,
+ 0xb9415a60,
+ 0xb900e2c0,
+ 0xb9416e60,
+ 0xb90122c0,
+ 0xb9418260,
+ 0xb90162c0,
+ 0xb9411660,
+ 0xb90002c0,
+ 0xb9411a60,
+ 0xb90006c0,
+ 0xb9411e60,
+ 0xb9002ec0,
+ 0xb9412260,
+ 0xb90032c0,
+ 0xb9412660,
+ 0xb90046c0,
+ 0xb9413260,
+ 0xb9005ac0,
+ 0xb9413660,
+ 0xb90082c0,
+ 0xb9413a60,
+ 0xb90086c0,
+ 0xb9414a60,
+ 0xb900c2c0,
+ 0xb9414e60,
+ 0xb900c6c0,
+ 0xb9415e60,
+ 0xb90102c0,
+ 0xb9416260,
+ 0xb90106c0,
+ 0xb9417260,
+ 0xb90142c0,
+ 0xb9417660,
+ 0xb90146c0,
+ 0x52800040,
+ 0xb9000ac0,
+ 0xb9411261,
+ 0xb9419a60,
+ 0xb900b020,
+ 0xb9419a60,
+ 0xb900b420,
+ 0xb9419e60,
+ 0xb900f020,
+ 0xb9419e60,
+ 0xb900f420,
+ 0xb941a260,
+ 0xb9013020,
+ 0xb941a260,
+ 0xb9013420,
+ 0xb941a660,
+ 0xb9017020,
+ 0xb941a662,
+ 0xaa1f03e0,
+ 0xb9017422,
+ 0x91008261,
+ 0xb8606822,
+ 0x8b000283,
+ 0xb900c062,
+ 0x91001000,
+ 0xf102301f,
+ 0x54ffff61,
+ 0xb9400a60,
+ 0xb9000280,
+ 0xb9400e60,
+ 0xb9005280,
+ 0xb9401260,
+ 0xb9007e80,
+ 0xb9401660,
+ 0xb9008280,
+ 0xb9401a60,
+ 0xb9008680,
+ 0xb940ae60,
+ 0xb9024280,
+ 0xb940b260,
+ 0xb9024680,
+ 0xb940b660,
+ 0xb9024a80,
+ 0xb940ba60,
+ 0xb9024e80,
+ 0xb940be60,
+ 0xb9025280,
+ 0xb940c260,
+ 0xb9025680,
+ 0xb940c660,
+ 0xb9025a80,
+ 0xb940ca60,
+ 0xb9026280,
+ 0xb940ce60,
+ 0xb9026680,
+ 0xb940d260,
+ 0xb9027280,
+ 0xb940d660,
+ 0xb9027680,
+ 0xb940da60,
+ 0xb9027a80,
+ 0xb940de60,
+ 0xb9027e80,
+ 0xb940e260,
+ 0xb9028280,
+ 0xb940e660,
+ 0xb9028680,
+ 0xb940ea60,
+ 0xb9028a80,
+ 0xb940ee60,
+ 0xb9029280,
+ 0xb940f260,
+ 0xb9029680,
+ 0xb940f660,
+ 0xb9029a80,
+ 0xb940fa60,
+ 0xb902c680,
+ 0xb940fe60,
+ 0xb902ca80,
+ 0xb9410260,
+ 0xb902d280,
+ 0xb9410660,
+ 0xb902d680,
+ 0xb9410a60,
+ 0xb902da80,
+ 0xb9410e60,
+ 0xb902f280,
+ 0xb9422260,
+ 0x3100041f,
+ 0x540000c0,
+ 0xb9422661,
+ 0x53007c00,
+ 0xb9000001,
+ 0x52800020,
+ 0x97fffe65,
+ 0x52800020,
+ 0xb9004680,
+ 0xb9404a80,
+ 0x3607ffe0,
+ 0xb941ae60,
+ 0xb9000aa0,
+ 0xb941b260,
+ 0xb9000ea0,
+ 0xb941b660,
+ 0xb90012a0,
+ 0xb941ba60,
+ 0xb90016a0,
+ 0xb941be60,
+ 0xb9003aa0,
+ 0xb941c260,
+ 0xb9003ea0,
+ 0xb9422260,
+ 0x3100041f,
+ 0x54000080,
+ 0x53007c00,
+ 0x320083e1,
+ 0xb9000001,
+ 0xaa1403e0,
+ 0x97fffe84,
+ 0xb9421a60,
+ 0x3100041f,
+ 0x54000100,
+ 0x53007c00,
+ 0xb9421e61,
+ 0xb9400002,
+ 0x2a010041,
+ 0xb9000001,
+ 0x52800020,
+ 0x97fffe43,
+ 0xaa1403e0,
+ 0x97fffea0,
+ 0xb9422260,
+ 0x3100041f,
+ 0x54000080,
+ 0x53007c00,
+ 0x52a00021,
+ 0xb9000001,
+ 0xf94007f3,
+ 0xa94157f4,
+ 0xa9425ff6,
+ 0xa9437bfd,
+ 0x910103ff,
+ 0xd65f03c0,
diff --git a/plat/rockchip/rk3368/drivers/pmu/pmu.c b/plat/rockchip/rk3368/drivers/pmu/pmu.c
new file mode 100644
index 0000000..fc31413
--- /dev/null
+++ b/plat/rockchip/rk3368/drivers/pmu/pmu.c
@@ -0,0 +1,425 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <delay_timer.h>
+#include <errno.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <plat_private.h>
+#include <rk3368_def.h>
+#include <pmu_sram.h>
+#include <soc.h>
+#include <pmu.h>
+#include <ddr_rk3368.h>
+#include <pmu_com.h>
+
+static struct psram_data_t *psram_sleep_cfg =
+ (struct psram_data_t *)PSRAM_DT_BASE;
+
+void rk3368_flash_l2_b(void)
+{
+ uint32_t wait_cnt = 0;
+
+ regs_updata_bit_set(PMU_BASE + PMU_SFT_CON, pmu_sft_l2flsh_clst_b);
+ dsb();
+
+ while (!(mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST)
+ & BIT(clst_b_l2_flsh_done))) {
+ wait_cnt++;
+ if (!(wait_cnt % MAX_WAIT_CONUT))
+ WARN("%s:reg %x,wait\n", __func__,
+ mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST));
+ }
+
+ regs_updata_bit_clr(PMU_BASE + PMU_SFT_CON, pmu_sft_l2flsh_clst_b);
+}
+
+static inline int rk3368_pmu_bus_idle(uint32_t req, uint32_t idle)
+{
+ uint32_t mask = BIT(req);
+ uint32_t idle_mask = 0;
+ uint32_t idle_target = 0;
+ uint32_t val;
+ uint32_t wait_cnt = 0;
+
+ switch (req) {
+ case bus_ide_req_clst_l:
+ idle_mask = BIT(pmu_idle_ack_cluster_l);
+ idle_target = (idle << pmu_idle_ack_cluster_l);
+ break;
+
+ case bus_ide_req_clst_b:
+ idle_mask = BIT(pmu_idle_ack_cluster_b);
+ idle_target = (idle << pmu_idle_ack_cluster_b);
+ break;
+
+ case bus_ide_req_cxcs:
+ idle_mask = BIT(pmu_idle_ack_cxcs);
+ idle_target = ((!idle) << pmu_idle_ack_cxcs);
+ break;
+
+ case bus_ide_req_cci400:
+ idle_mask = BIT(pmu_idle_ack_cci400);
+ idle_target = ((!idle) << pmu_idle_ack_cci400);
+ break;
+
+ case bus_ide_req_gpu:
+ idle_mask = BIT(pmu_idle_ack_gpu) | BIT(pmu_idle_gpu);
+ idle_target = (idle << pmu_idle_ack_gpu) |
+ (idle << pmu_idle_gpu);
+ break;
+
+ case bus_ide_req_core:
+ idle_mask = BIT(pmu_idle_ack_core) | BIT(pmu_idle_core);
+ idle_target = (idle << pmu_idle_ack_core) |
+ (idle << pmu_idle_core);
+ break;
+
+ case bus_ide_req_bus:
+ idle_mask = BIT(pmu_idle_ack_bus) | BIT(pmu_idle_bus);
+ idle_target = (idle << pmu_idle_ack_bus) |
+ (idle << pmu_idle_bus);
+ break;
+ case bus_ide_req_dma:
+ idle_mask = BIT(pmu_idle_ack_dma) | BIT(pmu_idle_dma);
+ idle_target = (idle << pmu_idle_ack_dma) |
+ (idle << pmu_idle_dma);
+ break;
+
+ case bus_ide_req_peri:
+ idle_mask = BIT(pmu_idle_ack_peri) | BIT(pmu_idle_peri);
+ idle_target = (idle << pmu_idle_ack_peri) |
+ (idle << pmu_idle_peri);
+ break;
+
+ case bus_ide_req_video:
+ idle_mask = BIT(pmu_idle_ack_video) | BIT(pmu_idle_video);
+ idle_target = (idle << pmu_idle_ack_video) |
+ (idle << pmu_idle_video);
+ break;
+
+ case bus_ide_req_vio:
+ idle_mask = BIT(pmu_idle_ack_vio) | BIT(pmu_idle_vio);
+ idle_target = (pmu_idle_ack_vio) |
+ (idle << pmu_idle_vio);
+ break;
+
+ case bus_ide_req_alive:
+ idle_mask = BIT(pmu_idle_ack_alive) | BIT(pmu_idle_alive);
+ idle_target = (idle << pmu_idle_ack_alive) |
+ (idle << pmu_idle_alive);
+ break;
+
+ case bus_ide_req_pmu:
+ idle_mask = BIT(pmu_idle_ack_pmu) | BIT(pmu_idle_pmu);
+ idle_target = (idle << pmu_idle_ack_pmu) |
+ (idle << pmu_idle_pmu);
+ break;
+
+ case bus_ide_req_msch:
+ idle_mask = BIT(pmu_idle_ack_msch) | BIT(pmu_idle_msch);
+ idle_target = (idle << pmu_idle_ack_msch) |
+ (idle << pmu_idle_msch);
+ break;
+
+ case bus_ide_req_cci:
+ idle_mask = BIT(pmu_idle_ack_cci) | BIT(pmu_idle_cci);
+ idle_target = (idle << pmu_idle_ack_cci) |
+ (idle << pmu_idle_cci);
+ break;
+
+ default:
+ ERROR("%s: Unsupported the idle request\n", __func__);
+ break;
+ }
+
+ val = mmio_read_32(PMU_BASE + PMU_BUS_IDE_REQ);
+ if (idle)
+ val |= mask;
+ else
+ val &= ~mask;
+
+ mmio_write_32(PMU_BASE + PMU_BUS_IDE_REQ, val);
+
+ while ((mmio_read_32(PMU_BASE +
+ PMU_BUS_IDE_ST) & idle_mask) != idle_target) {
+ wait_cnt++;
+ if (!(wait_cnt % MAX_WAIT_CONUT))
+ WARN("%s:st=%x(%x)\n", __func__,
+ mmio_read_32(PMU_BASE + PMU_BUS_IDE_ST),
+ idle_mask);
+ }
+
+ return 0;
+}
+
+void pmu_scu_b_pwrup(void)
+{
+ regs_updata_bit_clr(PMU_BASE + PMU_SFT_CON, pmu_sft_acinactm_clst_b);
+ rk3368_pmu_bus_idle(bus_ide_req_clst_b, 0);
+}
+
+static void pmu_scu_b_pwrdn(void)
+{
+ uint32_t wait_cnt = 0;
+
+ if ((mmio_read_32(PMU_BASE + PMU_PWRDN_ST) &
+ PM_PWRDM_CPUSB_MSK) != PM_PWRDM_CPUSB_MSK) {
+ ERROR("%s: not all cpus is off\n", __func__);
+ return;
+ }
+
+ rk3368_flash_l2_b();
+
+ regs_updata_bit_set(PMU_BASE + PMU_SFT_CON, pmu_sft_acinactm_clst_b);
+
+ while (!(mmio_read_32(PMU_BASE +
+ PMU_CORE_PWR_ST) & BIT(clst_b_l2_wfi))) {
+ wait_cnt++;
+ if (!(wait_cnt % MAX_WAIT_CONUT))
+ ERROR("%s:wait cluster-b l2(%x)\n", __func__,
+ mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST));
+ }
+ rk3368_pmu_bus_idle(bus_ide_req_clst_b, 1);
+}
+
+static void pmu_sleep_mode_config(void)
+{
+ uint32_t pwrmd_core, pwrmd_com;
+
+ pwrmd_core = BIT(pmu_mdcr_cpu0_pd) |
+ BIT(pmu_mdcr_scu_l_pd) |
+ BIT(pmu_mdcr_l2_flush) |
+ BIT(pmu_mdcr_l2_idle) |
+ BIT(pmu_mdcr_clr_clst_l) |
+ BIT(pmu_mdcr_clr_core) |
+ BIT(pmu_mdcr_clr_cci) |
+ BIT(pmu_mdcr_core_pd);
+
+ pwrmd_com = BIT(pmu_mode_en) |
+ BIT(pmu_mode_sref_enter) |
+ BIT(pmu_mode_pwr_off);
+
+ regs_updata_bit_set(PMU_BASE + PMU_WKUP_CFG2, pmu_cluster_l_wkup_en);
+ regs_updata_bit_set(PMU_BASE + PMU_WKUP_CFG2, pmu_cluster_b_wkup_en);
+ regs_updata_bit_clr(PMU_BASE + PMU_WKUP_CFG2, pmu_gpio_wkup_en);
+
+ mmio_write_32(PMU_BASE + PMU_PLLLOCK_CNT, CYCL_24M_CNT_MS(2));
+ mmio_write_32(PMU_BASE + PMU_PLLRST_CNT, CYCL_24M_CNT_US(100));
+ mmio_write_32(PMU_BASE + PMU_STABLE_CNT, CYCL_24M_CNT_MS(2));
+ mmio_write_32(PMU_BASE + PMU_PWRMD_CORE, pwrmd_core);
+ mmio_write_32(PMU_BASE + PMU_PWRMD_COM, pwrmd_com);
+ dsb();
+}
+
+static void ddr_suspend_save(void)
+{
+ ddr_reg_save(1, psram_sleep_cfg->ddr_data);
+}
+
+static void pmu_set_sleep_mode(void)
+{
+ ddr_suspend_save();
+ pmu_sleep_mode_config();
+ soc_sleep_config();
+ regs_updata_bit_set(PMU_BASE + PMU_PWRMD_CORE, pmu_mdcr_global_int_dis);
+ regs_updata_bit_set(PMU_BASE + PMU_SFT_CON, pmu_sft_glbl_int_dis_b);
+ pmu_scu_b_pwrdn();
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1),
+ (PMUSRAM_BASE >> CPU_BOOT_ADDR_ALIGN) |
+ CPU_BOOT_ADDR_WMASK);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(2),
+ (PMUSRAM_BASE >> CPU_BOOT_ADDR_ALIGN) |
+ CPU_BOOT_ADDR_WMASK);
+}
+
+void plat_rockchip_pmusram_prepare(void)
+{
+ uint32_t *sram_dst, *sram_src;
+ size_t sram_size = 2;
+ uint32_t code_size, data_size;
+
+ /* pmu sram code and data prepare */
+ sram_dst = (uint32_t *)PMUSRAM_BASE;
+ sram_src = (uint32_t *)&pmu_cpuson_entrypoint_start;
+ sram_size = (uint32_t *)&pmu_cpuson_entrypoint_end -
+ (uint32_t *)sram_src;
+ u32_align_cpy(sram_dst, sram_src, sram_size);
+
+ /* ddr code */
+ sram_dst += sram_size;
+ sram_src = ddr_get_resume_code_base();
+ code_size = ddr_get_resume_code_size();
+ u32_align_cpy(sram_dst, sram_src, code_size / 4);
+ psram_sleep_cfg->ddr_func = (uint64_t)sram_dst;
+
+ /* ddr data */
+ sram_dst += (code_size / 4);
+ data_size = ddr_get_resume_data_size();
+ psram_sleep_cfg->ddr_data = (uint64_t)sram_dst;
+
+ assert((uint64_t)(sram_dst + data_size / 4) < PSRAM_SP_BOTTOM);
+ psram_sleep_cfg->sp = PSRAM_SP_TOP;
+}
+
+static int cpus_id_power_domain(uint32_t cluster,
+ uint32_t cpu,
+ uint32_t pd_state,
+ uint32_t wfie_msk)
+{
+ uint32_t pd;
+ uint64_t mpidr;
+
+ if (cluster)
+ pd = PD_CPUB0 + cpu;
+ else
+ pd = PD_CPUL0 + cpu;
+
+ if (pmu_power_domain_st(pd) == pd_state)
+ return 0;
+
+ if (pd_state == pmu_pd_off) {
+ mpidr = (cluster << MPIDR_AFF1_SHIFT) | cpu;
+ if (check_cpu_wfie(mpidr, wfie_msk))
+ return -EINVAL;
+ }
+
+ return pmu_power_domain_ctr(pd, pd_state);
+}
+
+static void nonboot_cpus_off(void)
+{
+ uint32_t boot_cpu, boot_cluster, cpu;
+
+ boot_cpu = MPIDR_AFFLVL0_VAL(read_mpidr_el1());
+ boot_cluster = MPIDR_AFFLVL1_VAL(read_mpidr_el1());
+
+ /* turn off noboot cpus */
+ for (cpu = 0; cpu < PLATFORM_CLUSTER0_CORE_COUNT; cpu++) {
+ if (!boot_cluster && (cpu == boot_cpu))
+ continue;
+ cpus_id_power_domain(0, cpu, pmu_pd_off, CKECK_WFEI_MSK);
+ }
+
+ for (cpu = 0; cpu < PLATFORM_CLUSTER1_CORE_COUNT; cpu++) {
+ if (boot_cluster && (cpu == boot_cpu))
+ continue;
+ cpus_id_power_domain(1, cpu, pmu_pd_off, CKECK_WFEI_MSK);
+ }
+}
+
+static int cores_pwr_domain_on(unsigned long mpidr, uint64_t entrypoint)
+{
+ uint32_t cpu, cluster;
+ uint32_t cpuon_id;
+
+ cpu = MPIDR_AFFLVL0_VAL(mpidr);
+ cluster = MPIDR_AFFLVL1_VAL(mpidr);
+
+ /* Make sure the cpu is off,Before power up the cpu! */
+ cpus_id_power_domain(cluster, cpu, pmu_pd_off, CKECK_WFEI_MSK);
+
+ cpuon_id = (cluster * PLATFORM_CLUSTER0_CORE_COUNT) + cpu;
+ assert(cpuson_flags[cpuon_id] == 0);
+ cpuson_flags[cpuon_id] = PMU_CPU_HOTPLUG;
+ cpuson_entry_point[cpuon_id] = entrypoint;
+
+ /* Switch boot addr to pmusram */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1 + cluster),
+ (PMUSRAM_BASE >> CPU_BOOT_ADDR_ALIGN) |
+ CPU_BOOT_ADDR_WMASK);
+ dsb();
+
+ cpus_id_power_domain(cluster, cpu, pmu_pd_on, CKECK_WFEI_MSK);
+
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1 + cluster),
+ (COLD_BOOT_BASE >> CPU_BOOT_ADDR_ALIGN) |
+ CPU_BOOT_ADDR_WMASK);
+
+ return 0;
+}
+
+static int cores_pwr_domain_on_finish(void)
+{
+ uint32_t cpuon_id;
+
+ cpuon_id = plat_my_core_pos();
+ assert(cpuson_flags[cpuon_id] == 0);
+ cpuson_flags[cpuon_id] = 0x00;
+
+ return 0;
+}
+
+static int sys_pwr_domain_resume(void)
+{
+ psram_sleep_cfg->sys_mode = PMU_SYS_ON_MODE;
+
+ pm_plls_resume();
+ pmu_scu_b_pwrup();
+
+ return 0;
+}
+
+static int sys_pwr_domain_suspend(void)
+{
+ nonboot_cpus_off();
+ pmu_set_sleep_mode();
+
+ psram_sleep_cfg->sys_mode = PMU_SYS_SLP_MODE;
+ psram_sleep_cfg->ddr_flag = 0;
+
+ return 0;
+}
+
+static struct rockchip_pm_ops_cb pm_ops = {
+ .cores_pwr_dm_on = cores_pwr_domain_on,
+ .cores_pwr_dm_on_finish = cores_pwr_domain_on_finish,
+ .sys_pwr_dm_suspend = sys_pwr_domain_suspend,
+ .sys_pwr_dm_resume = sys_pwr_domain_resume,
+ .sys_gbl_soft_reset = soc_sys_global_soft_reset,
+};
+
+void plat_rockchip_pmu_init(void)
+{
+ uint32_t cpu;
+
+ plat_setup_rockchip_pm_ops(&pm_ops);
+
+ for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++)
+ cpuson_flags[cpu] = 0;
+
+ psram_sleep_cfg->sys_mode = PMU_SYS_ON_MODE;
+
+ psram_sleep_cfg->boot_mpidr = read_mpidr_el1() & 0xffff;
+
+ nonboot_cpus_off();
+ INFO("%s(%d): pd status %x\n", __func__, __LINE__,
+ mmio_read_32(PMU_BASE + PMU_PWRDN_ST));
+}
diff --git a/plat/rockchip/rk3368/drivers/pmu/pmu.h b/plat/rockchip/rk3368/drivers/pmu/pmu.h
new file mode 100644
index 0000000..2cf60fd
--- /dev/null
+++ b/plat/rockchip/rk3368/drivers/pmu/pmu.h
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PMU_H__
+#define __PMU_H__
+
+/* Allocate sp reginon in pmusram */
+#define PSRAM_SP_SIZE 0x80
+#define PSRAM_SP_BOTTOM (PSRAM_SP_TOP - PSRAM_SP_SIZE)
+
+/*****************************************************************************
+ * pmu con,reg
+ *****************************************************************************/
+#define PMU_WKUP_CFG0 0x0
+#define PMU_WKUP_CFG1 0x4
+#define PMU_WKUP_CFG2 0x8
+#define PMU_TIMEOUT_CNT 0x7c
+#define PMU_PWRDN_CON 0xc
+#define PMU_PWRDN_ST 0x10
+#define PMU_CORE_PWR_ST 0x38
+
+#define PMU_PWRMD_CORE 0x14
+#define PMU_PWRMD_COM 0x18
+#define PMU_SFT_CON 0x1c
+#define PMU_BUS_IDE_REQ 0x3c
+#define PMU_BUS_IDE_ST 0x40
+#define PMU_OSC_CNT 0x48
+#define PMU_PLLLOCK_CNT 0x4c
+#define PMU_PLLRST_CNT 0x50
+#define PMU_STABLE_CNT 0x54
+#define PMU_DDRIO_PWR_CNT 0x58
+#define PMU_WKUPRST_CNT 0x5c
+
+enum pmu_powermode_core {
+ pmu_mdcr_global_int_dis = 0,
+ pmu_mdcr_core_src_gt,
+ pmu_mdcr_clr_cci,
+ pmu_mdcr_cpu0_pd,
+ pmu_mdcr_clr_clst_l = 4,
+ pmu_mdcr_clr_core,
+ pmu_mdcr_scu_l_pd,
+ pmu_mdcr_core_pd,
+ pmu_mdcr_l2_idle = 8,
+ pmu_mdcr_l2_flush
+};
+
+/*
+ * the shift of bits for cores status
+ */
+enum pmu_core_pwrst_shift {
+ clstl_cpu_wfe = 2,
+ clstl_cpu_wfi = 6,
+ clstb_cpu_wfe = 12,
+ clstb_cpu_wfi = 16
+};
+
+enum pmu_pdid {
+ PD_CPUL0 = 0,
+ PD_CPUL1,
+ PD_CPUL2,
+ PD_CPUL3,
+ PD_SCUL,
+ PD_CPUB0 = 5,
+ PD_CPUB1,
+ PD_CPUB2,
+ PD_CPUB3,
+ PD_SCUB = 9,
+ PD_PERI = 13,
+ PD_VIDEO,
+ PD_VIO,
+ PD_GPU0,
+ PD_GPU1,
+ PD_END
+};
+
+enum pmu_bus_ide {
+ bus_ide_req_clst_l = 0,
+ bus_ide_req_clst_b,
+ bus_ide_req_gpu,
+ bus_ide_req_core,
+ bus_ide_req_bus = 4,
+ bus_ide_req_dma,
+ bus_ide_req_peri,
+ bus_ide_req_video,
+ bus_ide_req_vio = 8,
+ bus_ide_req_res0,
+ bus_ide_req_cxcs,
+ bus_ide_req_alive,
+ bus_ide_req_pmu = 12,
+ bus_ide_req_msch,
+ bus_ide_req_cci,
+ bus_ide_req_cci400 = 15,
+ bus_ide_req_end
+};
+
+enum pmu_powermode_common {
+ pmu_mode_en = 0,
+ pmu_mode_res0,
+ pmu_mode_bus_pd,
+ pmu_mode_wkup_rst,
+ pmu_mode_pll_pd = 4,
+ pmu_mode_pwr_off,
+ pmu_mode_pmu_use_if,
+ pmu_mode_pmu_alive_use_if,
+ pmu_mode_osc_dis = 8,
+ pmu_mode_input_clamp,
+ pmu_mode_sref_enter,
+ pmu_mode_ddrc_gt,
+ pmu_mode_ddrio_ret = 12,
+ pmu_mode_ddrio_ret_deq,
+ pmu_mode_clr_pmu,
+ pmu_mode_clr_alive,
+ pmu_mode_clr_bus = 16,
+ pmu_mode_clr_dma,
+ pmu_mode_clr_msch,
+ pmu_mode_clr_peri,
+ pmu_mode_clr_video = 20,
+ pmu_mode_clr_vio,
+ pmu_mode_clr_gpu,
+ pmu_mode_clr_mcu,
+ pmu_mode_clr_cxcs = 24,
+ pmu_mode_clr_cci400,
+ pmu_mode_res1,
+ pmu_mode_res2,
+ pmu_mode_res3 = 28,
+ pmu_mode_mclst
+};
+
+enum pmu_core_power_st {
+ clst_l_cpu_wfe = 2,
+ clst_l_cpu_wfi = 6,
+ clst_b_l2_flsh_done = 10,
+ clst_b_l2_wfi = 11,
+ clst_b_cpu_wfe = 12,
+ clst_b_cpu_wfi = 16,
+ mcu_sleeping = 20,
+};
+
+enum pmu_sft_con {
+ pmu_sft_acinactm_clst_b = 5,
+ pmu_sft_l2flsh_clst_b,
+ pmu_sft_glbl_int_dis_b = 9,
+ pmu_sft_ddrio_ret_cfg = 11,
+};
+
+enum pmu_wkup_cfg2 {
+ pmu_cluster_l_wkup_en = 0,
+ pmu_cluster_b_wkup_en,
+ pmu_gpio_wkup_en,
+ pmu_sdio_wkup_en,
+ pmu_sdmmc_wkup_en,
+ pmu_sim_wkup_en,
+ pmu_timer_wkup_en,
+ pmu_usbdev_wkup_en,
+ pmu_sft_wkup_en,
+ pmu_wdt_mcu_wkup_en,
+ pmu_timeout_wkup_en,
+};
+
+enum pmu_bus_idle_st {
+ pmu_idle_ack_cluster_l = 0,
+ pmu_idle_ack_cluster_b,
+ pmu_idle_ack_gpu,
+ pmu_idle_ack_core,
+ pmu_idle_ack_bus,
+ pmu_idle_ack_dma,
+ pmu_idle_ack_peri,
+ pmu_idle_ack_video,
+ pmu_idle_ack_vio,
+ pmu_idle_ack_cci = 10,
+ pmu_idle_ack_msch,
+ pmu_idle_ack_alive,
+ pmu_idle_ack_pmu,
+ pmu_idle_ack_cxcs,
+ pmu_idle_ack_cci400,
+ pmu_inactive_cluster_l,
+ pmu_inactive_cluster_b,
+ pmu_idle_gpu,
+ pmu_idle_core,
+ pmu_idle_bus,
+ pmu_idle_dma,
+ pmu_idle_peri,
+ pmu_idle_video,
+ pmu_idle_vio,
+ pmu_idle_cci = 26,
+ pmu_idle_msch,
+ pmu_idle_alive,
+ pmu_idle_pmu,
+ pmu_active_cxcs,
+ pmu_active_cci,
+};
+
+#define PM_PWRDM_CPUSB_MSK (0xf << 5)
+
+#define CKECK_WFE_MSK 0x1
+#define CKECK_WFI_MSK 0x10
+#define CKECK_WFEI_MSK 0x11
+
+#define PD_CTR_LOOP 500
+#define CHK_CPU_LOOP 500
+
+#define MAX_WAIT_CONUT 1000
+
+#endif /* __PMU_H__ */
diff --git a/plat/rockchip/rk3368/drivers/soc/soc.c b/plat/rockchip/rk3368/drivers/soc/soc.c
new file mode 100644
index 0000000..3630828
--- /dev/null
+++ b/plat/rockchip/rk3368/drivers/soc/soc.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <debug.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <plat_private.h>
+#include <rk3368_def.h>
+#include <soc.h>
+
+static uint32_t plls_con[END_PLL_ID][4];
+
+/* Table of regions to map using the MMU. */
+const mmap_region_t plat_rk_mmap[] = {
+ MAP_REGION_FLAT(CCI400_BASE, CCI400_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(GIC400_BASE, GIC400_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(STIME_BASE, STIME_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(SGRF_BASE, SGRF_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(PMUSRAM_BASE, PMUSRAM_SIZE,
+ MT_MEMORY | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(PMU_BASE, PMU_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(UART_DBG_BASE, UART_DBG_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(CRU_BASE, CRU_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(DDR_PCTL_BASE, DDR_PCTL_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(DDR_PHY_BASE, DDR_PHY_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(GRF_BASE, GRF_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(SERVICE_BUS_BASE, SERVICE_BUS_SISE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ { 0 }
+};
+
+/* The RockChip power domain tree descriptor */
+const unsigned char rockchip_power_domain_tree_desc[] = {
+ /* No of root nodes */
+ PLATFORM_SYSTEM_COUNT,
+ /* No of children for the root node */
+ PLATFORM_CLUSTER_COUNT,
+ /* No of children for the first cluster node */
+ PLATFORM_CLUSTER0_CORE_COUNT,
+ /* No of children for the second cluster node */
+ PLATFORM_CLUSTER1_CORE_COUNT
+};
+
+void secure_timer_init(void)
+{
+ mmio_write_32(STIMER1_BASE + TIMER_LOADE_COUNT0, 0xffffffff);
+ mmio_write_32(STIMER1_BASE + TIMER_LOADE_COUNT1, 0xffffffff);
+
+ /* auto reload & enable the timer */
+ mmio_write_32(STIMER1_BASE + TIMER_CONTROL_REG, TIMER_EN);
+}
+
+void sgrf_init(void)
+{
+ /* setting all configurable ip into no-secure */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(5), SGRF_SOC_CON_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6), SGRF_SOC_CON7_BITS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(7), SGRF_SOC_CON_NS);
+
+ /* secure dma to no sesure */
+ mmio_write_32(SGRF_BASE + SGRF_BUSDMAC_CON(0), SGRF_BUSDMAC_CON0_NS);
+ mmio_write_32(SGRF_BASE + SGRF_BUSDMAC_CON(1), SGRF_BUSDMAC_CON1_NS);
+ dsb();
+
+ /* rst dma1 */
+ mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(1),
+ RST_DMA1_MSK | (RST_DMA1_MSK << 16));
+ /* rst dma2 */
+ mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(4),
+ RST_DMA2_MSK | (RST_DMA2_MSK << 16));
+
+ dsb();
+
+ /* release dma1 rst*/
+ mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(1), (RST_DMA1_MSK << 16));
+ /* release dma2 rst*/
+ mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(4), (RST_DMA2_MSK << 16));
+}
+
+void plat_rockchip_soc_init(void)
+{
+ secure_timer_init();
+ sgrf_init();
+}
+
+void regs_updata_bits(uintptr_t addr, uint32_t val,
+ uint32_t mask, uint32_t shift)
+{
+ uint32_t tmp, orig;
+
+ orig = mmio_read_32(addr);
+
+ tmp = orig & ~(mask << shift);
+ tmp |= (val & mask) << shift;
+
+ if (tmp != orig)
+ mmio_write_32(addr, tmp);
+ dsb();
+}
+
+static void plls_suspend(uint32_t pll_id)
+{
+ plls_con[pll_id][0] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 0));
+ plls_con[pll_id][1] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 1));
+ plls_con[pll_id][2] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 2));
+ plls_con[pll_id][3] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 3));
+
+ mmio_write_32(CRU_BASE + PLL_CONS((pll_id), 3), PLL_SLOW_BITS);
+ mmio_write_32(CRU_BASE + PLL_CONS((pll_id), 3), PLL_BYPASS);
+}
+
+static void pm_plls_suspend(void)
+{
+ plls_suspend(NPLL_ID);
+ plls_suspend(CPLL_ID);
+ plls_suspend(GPLL_ID);
+ plls_suspend(ABPLL_ID);
+ plls_suspend(ALPLL_ID);
+}
+
+static inline void plls_resume(void)
+{
+ mmio_write_32(CRU_BASE + PLL_CONS(ABPLL_ID, 3),
+ plls_con[ABPLL_ID][3] | PLL_BYPASS_W_MSK);
+ mmio_write_32(CRU_BASE + PLL_CONS(ALPLL_ID, 3),
+ plls_con[ALPLL_ID][3] | PLL_BYPASS_W_MSK);
+ mmio_write_32(CRU_BASE + PLL_CONS(GPLL_ID, 3),
+ plls_con[GPLL_ID][3] | PLL_BYPASS_W_MSK);
+ mmio_write_32(CRU_BASE + PLL_CONS(CPLL_ID, 3),
+ plls_con[CPLL_ID][3] | PLL_BYPASS_W_MSK);
+ mmio_write_32(CRU_BASE + PLL_CONS(NPLL_ID, 3),
+ plls_con[NPLL_ID][3] | PLL_BYPASS_W_MSK);
+}
+
+void soc_sleep_config(void)
+{
+ int i = 0;
+
+ for (i = 0; i < CRU_CLKGATES_CON_CNT; i++)
+ mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), 0xffff0000);
+ pm_plls_suspend();
+
+ for (i = 0; i < CRU_CLKGATES_CON_CNT; i++)
+ mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), 0xffff0000);
+}
+
+void pm_plls_resume(void)
+{
+ plls_resume();
+
+ mmio_write_32(CRU_BASE + PLL_CONS(ABPLL_ID, 3),
+ plls_con[ABPLL_ID][3] | PLLS_MODE_WMASK);
+ mmio_write_32(CRU_BASE + PLL_CONS(ALPLL_ID, 3),
+ plls_con[ALPLL_ID][3] | PLLS_MODE_WMASK);
+ mmio_write_32(CRU_BASE + PLL_CONS(GPLL_ID, 3),
+ plls_con[GPLL_ID][3] | PLLS_MODE_WMASK);
+ mmio_write_32(CRU_BASE + PLL_CONS(CPLL_ID, 3),
+ plls_con[CPLL_ID][3] | PLLS_MODE_WMASK);
+ mmio_write_32(CRU_BASE + PLL_CONS(NPLL_ID, 3),
+ plls_con[NPLL_ID][3] | PLLS_MODE_WMASK);
+}
+
+void __dead2 soc_sys_global_soft_reset(void)
+{
+ uint32_t temp_val;
+
+ mmio_write_32(CRU_BASE + PLL_CONS((GPLL_ID), 3), PLL_SLOW_BITS);
+ mmio_write_32(CRU_BASE + PLL_CONS((CPLL_ID), 3), PLL_SLOW_BITS);
+ mmio_write_32(CRU_BASE + PLL_CONS((NPLL_ID), 3), PLL_SLOW_BITS);
+ mmio_write_32(CRU_BASE + PLL_CONS((ABPLL_ID), 3), PLL_SLOW_BITS);
+ mmio_write_32(CRU_BASE + PLL_CONS((ALPLL_ID), 3), PLL_SLOW_BITS);
+
+ temp_val = mmio_read_32(CRU_BASE + CRU_GLB_RST_CON) |
+ PMU_RST_BY_SECOND_SFT;
+
+ mmio_write_32(CRU_BASE + CRU_GLB_RST_CON, temp_val);
+ mmio_write_32(CRU_BASE + CRU_GLB_SRST_SND, 0xeca8);
+
+ /*
+ * Maybe the HW needs some times to reset the system,
+ * so we do not hope the core to excute valid codes.
+ */
+ while (1)
+ ;
+}
diff --git a/plat/rockchip/rk3368/drivers/soc/soc.h b/plat/rockchip/rk3368/drivers/soc/soc.h
new file mode 100644
index 0000000..6e2c3fe
--- /dev/null
+++ b/plat/rockchip/rk3368/drivers/soc/soc.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SOC_H__
+#define __SOC_H__
+
+enum plls_id {
+ ABPLL_ID = 0,
+ ALPLL_ID,
+ DPLL_ID,
+ CPLL_ID,
+ GPLL_ID,
+ NPLL_ID,
+ END_PLL_ID,
+};
+
+/*****************************************************************************
+ * secure timer
+ *****************************************************************************/
+#define TIMER_LOADE_COUNT0 0x00
+#define TIMER_LOADE_COUNT1 0x04
+#define TIMER_CURRENT_VALUE0 0x08
+#define TIMER_CURRENT_VALUE1 0x0C
+#define TIMER_CONTROL_REG 0x10
+#define TIMER_INTSTATUS 0x18
+
+#define TIMER_EN 0x1
+
+#define STIMER1_BASE (STIME_BASE + 0x20)
+
+#define CYCL_24M_CNT_US(us) (24 * us)
+#define CYCL_24M_CNT_MS(ms) (ms * CYCL_24M_CNT_US(1000))
+
+/*****************************************************************************
+ * sgrf reg, offset
+ *****************************************************************************/
+#define SGRF_SOC_CON(n) (0x0 + (n) * 4)
+#define SGRF_BUSDMAC_CON(n) (0x100 + (n) * 4)
+
+#define SGRF_SOC_CON_NS 0xffff0000
+
+/*****************************************************************************
+ * con6[2]pmusram is security.
+ * con6[6]stimer is security.
+ *****************************************************************************/
+#define PMUSRAM_S_SHIFT 2
+#define PMUSRAM_S 1
+#define STIMER_S_SHIFT 6
+#define STIMER_S 1
+#define SGRF_SOC_CON7_BITS ((0xffff << 16) | \
+ (PMUSRAM_S << PMUSRAM_S_SHIFT) | \
+ (STIMER_S << STIMER_S_SHIFT))
+
+#define SGRF_BUSDMAC_CON0_NS 0xfffcfff8
+#define SGRF_BUSDMAC_CON1_NS 0xffff0fff
+
+/*
+ * sgrf_soc_con1~2, mask and offset
+ */
+#define CPU_BOOT_ADDR_WMASK 0xffff0000
+#define CPU_BOOT_ADDR_ALIGN 16
+
+/*****************************************************************************
+ * cru reg, offset
+ *****************************************************************************/
+#define CRU_SOFTRST_CON 0x300
+#define CRU_SOFTRSTS_CON(n) (CRU_SOFTRST_CON + ((n) * 4))
+#define CRU_SOFTRSTS_CON_CNT 15
+
+#define SOFTRST_DMA1 0x40004
+#define SOFTRST_DMA2 0x10001
+
+#define RST_DMA1_MSK 0x4
+#define RST_DMA2_MSK 0x0
+
+#define CRU_CLKSEL_CON 0x100
+#define CRU_CLKSELS_CON(i) (CRU_CLKSEL_CON + ((i) * 4))
+#define CRU_CLKSEL_CON_CNT 56
+
+#define CRU_CLKGATE_CON 0x200
+#define CRU_CLKGATES_CON(i) (CRU_CLKGATE_CON + ((i) * 4))
+#define CRU_CLKGATES_CON_CNT 25
+
+#define CRU_GLB_SRST_FST 0x280
+#define CRU_GLB_SRST_SND 0x284
+#define CRU_GLB_RST_CON 0x388
+
+#define CRU_CONS_GATEID(i) (16 * (i))
+#define GATE_ID(reg, bit) ((reg * 16) + bit)
+
+#define PMU_RST_BY_SECOND_SFT (BIT(1) << 2)
+#define PMU_RST_NOT_BY_SFT (BIT(1) << 2)
+
+/***************************************************************************
+ * pll
+ ***************************************************************************/
+#define PLL_PWR_DN_MSK (0x1 << 1)
+#define PLL_PWR_DN REG_WMSK_BITS(1, 1, 0x1)
+#define PLL_PWR_ON REG_WMSK_BITS(0, 1, 0x1)
+#define PLL_RESET REG_WMSK_BITS(1, 5, 0x1)
+#define PLL_RESET_RESUME REG_WMSK_BITS(0, 5, 0x1)
+#define PLL_BYPASS_MSK (0x1 << 0)
+#define PLL_BYPASS_W_MSK (PLL_BYPASS_MSK << 16)
+#define PLL_BYPASS REG_WMSK_BITS(1, 0, 0x1)
+#define PLL_NO_BYPASS REG_WMSK_BITS(0, 0, 0x1)
+#define PLL_MODE_SHIFT 8
+#define PLL_MODE_MSK 0x3
+#define PLLS_MODE_WMASK (PLL_MODE_MSK << (16 + PLL_MODE_SHIFT))
+#define PLL_SLOW 0x0
+#define PLL_NORM 0x1
+#define PLL_DEEP 0x2
+#define PLL_SLOW_BITS REG_WMSK_BITS(PLL_SLOW, 8, 0x3)
+#define PLL_NORM_BITS REG_WMSK_BITS(PLL_NORM, 8, 0x3)
+#define PLL_DEEP_BITS REG_WMSK_BITS(PLL_DEEP, 8, 0x3)
+
+#define PLL_CONS(id, i) ((id) * 0x10 + ((i) * 4))
+
+#define REG_W_MSK(bits_shift, msk) \
+ ((msk) << ((bits_shift) + 16))
+#define REG_VAL_CLRBITS(val, bits_shift, msk) \
+ (val & (~(msk << bits_shift)))
+#define REG_SET_BITS(bits, bits_shift, msk) \
+ (((bits) & (msk)) << (bits_shift))
+#define REG_WMSK_BITS(bits, bits_shift, msk) \
+ (REG_W_MSK(bits_shift, msk) | \
+ REG_SET_BITS(bits, bits_shift, msk))
+
+#define regs_updata_bit_set(addr, shift) \
+ regs_updata_bits((addr), 0x1, 0x1, (shift))
+#define regs_updata_bit_clr(addr, shift) \
+ regs_updata_bits((addr), 0x0, 0x1, (shift))
+
+void __dead2 soc_sys_global_soft_reset(void);
+void regs_updata_bits(uintptr_t addr, uint32_t val,
+ uint32_t mask, uint32_t shift);
+void soc_sleep_config(void);
+void pm_plls_resume(void);
+
+#endif /* __SOC_H__ */
diff --git a/plat/rockchip/rk3368/include/platform_def.h b/plat/rockchip/rk3368/include/platform_def.h
new file mode 100644
index 0000000..876cbfb
--- /dev/null
+++ b/plat/rockchip/rk3368/include/platform_def.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PLATFORM_DEF_H__
+#define __PLATFORM_DEF_H__
+
+#include <arch.h>
+#include <common_def.h>
+#include <rk3368_def.h>
+
+#define DEBUG_XLAT_TABLE 0
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#if DEBUG_XLAT_TABLE
+#define PLATFORM_STACK_SIZE 0x800
+#elif IMAGE_BL1
+#define PLATFORM_STACK_SIZE 0x440
+#elif IMAGE_BL2
+#define PLATFORM_STACK_SIZE 0x400
+#elif IMAGE_BL31
+#define PLATFORM_STACK_SIZE 0x800
+#elif IMAGE_BL32
+#define PLATFORM_STACK_SIZE 0x440
+#endif
+
+#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n"
+
+#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL2
+#define PLATFORM_SYSTEM_COUNT 1
+#define PLATFORM_CLUSTER_COUNT 2
+#define PLATFORM_CLUSTER0_CORE_COUNT 4
+#define PLATFORM_CLUSTER1_CORE_COUNT 4
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \
+ PLATFORM_CLUSTER0_CORE_COUNT)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER 4
+#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \
+ PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2
+
+/*
+ * This macro defines the deepest retention state possible. A higher state
+ * id will represent an invalid or a power down state.
+ */
+#define PLAT_MAX_RET_STATE 1
+
+/*
+ * This macro defines the deepest power down states possible. Any state ID
+ * higher than this is invalid.
+ */
+#define PLAT_MAX_OFF_STATE 2
+
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+/* TF txet, ro, rw, Size: 512KB */
+#define TZRAM_BASE (0x0)
+#define TZRAM_SIZE (0x80000)
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL3-1 at the top of the Trusted RAM
+ */
+#define BL31_BASE (TZRAM_BASE + 0x8000)
+#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE)
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define ADDR_SPACE_SIZE (1ull << 32)
+#define MAX_XLAT_TABLES 8
+#define MAX_MMAP_REGIONS 16
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * 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. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+/*
+ * Define GICD and GICC and GICR base
+ */
+#define PLAT_RK_GICD_BASE RK3368_GICD_BASE
+#define PLAT_RK_GICC_BASE RK3368_GICC_BASE
+
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_RK_G1S_IRQS RK_G1S_IRQS
+
+#define PLAT_RK_UART_BASE RK3368_UART2_BASE
+#define PLAT_RK_UART_CLOCK RK3368_UART_CLOCK
+#define PLAT_RK_UART_BAUDRATE RK3368_BAUDRATE
+
+#define PLAT_RK_CCI_BASE CCI400_BASE
+
+#define PLAT_RK_PRIMARY_CPU 0x0
+
+#define RK_PLAT_AARCH_CFG RK_PLAT_CFG0
+
+#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/rockchip/rk3368/platform.mk b/plat/rockchip/rk3368/platform.mk
new file mode 100644
index 0000000..4fadf21
--- /dev/null
+++ b/plat/rockchip/rk3368/platform.mk
@@ -0,0 +1,74 @@
+#
+# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# Neither the name of ARM nor the names of its contributors may be used
+# to endorse or promote products derived from this software without specific
+# prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+RK_PLAT := plat/rockchip
+RK_PLAT_SOC := ${RK_PLAT}/${PLAT}
+RK_PLAT_COMMON := ${RK_PLAT}/common
+
+PLAT_INCLUDES := -I${RK_PLAT_COMMON}/ \
+ -I${RK_PLAT_COMMON}/include/ \
+ -I${RK_PLAT_COMMON}/pmusram \
+ -I${RK_PLAT_COMMON}/drivers/pmu/ \
+ -I${RK_PLAT_SOC}/ \
+ -I${RK_PLAT_SOC}/drivers/pmu/ \
+ -I${RK_PLAT_SOC}/drivers/soc/ \
+ -I${RK_PLAT_SOC}/drivers/ddr/ \
+ -I${RK_PLAT_SOC}/include/
+
+RK_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 \
+ ${RK_PLAT}/common/rockchip_gicv2.c
+
+PLAT_BL_COMMON_SOURCES := lib/aarch64/xlat_tables.c \
+ plat/common/aarch64/plat_common.c \
+ plat/common/aarch64/plat_psci_common.c
+
+BL31_SOURCES += ${RK_GIC_SOURCES} \
+ drivers/arm/cci/cci.c \
+ drivers/console/console.S \
+ drivers/ti/uart/16550_console.S \
+ drivers/delay_timer/delay_timer.c \
+ lib/cpus/aarch64/cortex_a53.S \
+ plat/common/aarch64/platform_mp_stack.S \
+ ${RK_PLAT_COMMON}/aarch64/plat_helpers.S \
+ ${RK_PLAT_COMMON}/bl31_plat_setup.c \
+ ${RK_PLAT_COMMON}/pmusram/pmu_sram_cpus_on.S \
+ ${RK_PLAT_COMMON}/pmusram/pmu_sram.c \
+ ${RK_PLAT_COMMON}/plat_delay_timer.c \
+ ${RK_PLAT_COMMON}/plat_pm.c \
+ ${RK_PLAT_COMMON}/plat_topology.c \
+ ${RK_PLAT_COMMON}/aarch64/platform_common.c \
+ ${RK_PLAT_SOC}/drivers/pmu/pmu.c \
+ ${RK_PLAT_SOC}/drivers/soc/soc.c \
+ ${RK_PLAT_SOC}/drivers/ddr/ddr_rk3368.c \
+
+ENABLE_PLAT_COMPAT := 0
diff --git a/plat/rockchip/rk3368/rk3368_def.h b/plat/rockchip/rk3368/rk3368_def.h
new file mode 100644
index 0000000..614f270
--- /dev/null
+++ b/plat/rockchip/rk3368/rk3368_def.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PLAT_DEF_H__
+#define __PLAT_DEF_H__
+
+/* Special value used to verify platform parameters from BL2 to BL3-1 */
+#define RK_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL
+
+#define CCI400_BASE 0xffb90000
+#define CCI400_SIZE 0x10000
+
+#define GIC400_BASE 0xffb70000
+#define GIC400_SIZE 0x10000
+
+#define STIME_BASE 0xff830000
+#define STIME_SIZE 0x10000
+
+#define CRU_BASE 0xff760000
+#define CRU_SIZE 0x10000
+
+#define GRF_BASE 0xff770000
+#define GRF_SIZE 0x10000
+
+#define SGRF_BASE 0xff740000
+#define SGRF_SIZE 0x10000
+
+#define PMU_BASE 0xff730000
+#define PMU_GRF_BASE 0xff738000
+#define PMU_SIZE 0x10000
+
+#define RK_INTMEM_BASE 0xff8c0000
+#define RK_INTMEM_SIZE 0x10000
+
+#define UART_DBG_BASE 0xff690000
+#define UART_DBG_SIZE 0x10000
+
+#define CRU_BASE 0xff760000
+
+#define PMUSRAM_BASE 0xff720000
+#define PMUSRAM_SIZE 0x10000
+#define PMUSRAM_RSIZE 0x1000
+
+#define DDR_PCTL_BASE 0xff610000
+#define DDR_PCTL_SIZE 0x10000
+
+#define DDR_PHY_BASE 0xff620000
+#define DDR_PHY_SIZE 0x10000
+
+#define SERVICE_BUS_BASE 0xffac0000
+#define SERVICE_BUS_SISE 0x50000
+
+#define COLD_BOOT_BASE 0xffff0000
+/**************************************************************************
+ * UART related constants
+ **************************************************************************/
+#define RK3368_UART2_BASE UART_DBG_BASE
+#define RK3368_BAUDRATE 115200
+#define RK3368_UART_CLOCK 24000000
+
+/******************************************************************************
+ * System counter frequency related constants
+ ******************************************************************************/
+#define SYS_COUNTER_FREQ_IN_TICKS 24000000
+#define SYS_COUNTER_FREQ_IN_MHZ 24
+
+/******************************************************************************
+ * GIC-400 & interrupt handling related constants
+ ******************************************************************************/
+
+/* Base rk_platform compatible GIC memory map */
+#define RK3368_GICD_BASE (GIC400_BASE + 0x1000)
+#define RK3368_GICC_BASE (GIC400_BASE + 0x2000)
+#define RK3368_GICR_BASE 0 /* no GICR in GIC-400 */
+
+/*****************************************************************************
+ * CCI-400 related constants
+ ******************************************************************************/
+#define PLAT_RK_CCI_CLUSTER0_SL_IFACE_IX 3
+#define PLAT_RK_CCI_CLUSTER1_SL_IFACE_IX 4
+
+/******************************************************************************
+ * cpu up status
+ ******************************************************************************/
+#define PMU_CPU_HOTPLUG 0xdeadbeaf
+#define PMU_CPU_AUTO_PWRDN 0xabcdef12
+
+/******************************************************************************
+ * sgi, ppi
+ ******************************************************************************/
+#define RK_IRQ_SEC_PHY_TIMER 29
+
+#define RK_IRQ_SEC_SGI_0 8
+#define RK_IRQ_SEC_SGI_1 9
+#define RK_IRQ_SEC_SGI_2 10
+#define RK_IRQ_SEC_SGI_3 11
+#define RK_IRQ_SEC_SGI_4 12
+#define RK_IRQ_SEC_SGI_5 13
+#define RK_IRQ_SEC_SGI_6 14
+#define RK_IRQ_SEC_SGI_7 15
+
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define RK_G1S_IRQS (RK_IRQ_SEC_PHY_TIMER)
+
+#endif /* __PLAT_DEF_H__ */
diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu.c b/plat/rockchip/rk3399/drivers/pmu/pmu.c
new file mode 100644
index 0000000..351de7d
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/pmu/pmu.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bakery_lock.h>
+#include <debug.h>
+#include <delay_timer.h>
+#include <errno.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <plat_private.h>
+#include <rk3399_def.h>
+#include <pmu_sram.h>
+#include <soc.h>
+#include <pmu.h>
+#include <pmu_com.h>
+
+static struct psram_data_t *psram_sleep_cfg =
+ (struct psram_data_t *)PSRAM_DT_BASE;
+
+/*
+ * There are two ways to powering on or off on core.
+ * 1) Control it power domain into on or off in PMU_PWRDN_CON reg,
+ * it is core_pwr_pd mode
+ * 2) Enable the core power manage in PMU_CORE_PM_CON reg,
+ * then, if the core enter into wfi, it power domain will be
+ * powered off automatically. it is core_pwr_wfi or core_pwr_wfi_int mode
+ * so we need core_pm_cfg_info to distinguish which method be used now.
+ */
+
+static uint32_t core_pm_cfg_info[PLATFORM_CORE_COUNT]
+#if USE_COHERENT_MEM
+__attribute__ ((section("tzfw_coherent_mem")))
+#endif
+;/* coheront */
+
+void plat_rockchip_pmusram_prepare(void)
+{
+ uint32_t *sram_dst, *sram_src;
+ size_t sram_size = 2;
+
+ /*
+ * pmu sram code and data prepare
+ */
+ sram_dst = (uint32_t *)PMUSRAM_BASE;
+ sram_src = (uint32_t *)&pmu_cpuson_entrypoint_start;
+ sram_size = (uint32_t *)&pmu_cpuson_entrypoint_end -
+ (uint32_t *)sram_src;
+
+ u32_align_cpy(sram_dst, sram_src, sram_size);
+
+ psram_sleep_cfg->sp = PSRAM_DT_BASE;
+}
+
+static inline uint32_t get_cpus_pwr_domain_cfg_info(uint32_t cpu_id)
+{
+ return core_pm_cfg_info[cpu_id];
+}
+
+static inline void set_cpus_pwr_domain_cfg_info(uint32_t cpu_id, uint32_t value)
+{
+ core_pm_cfg_info[cpu_id] = value;
+#if !USE_COHERENT_MEM
+ flush_dcache_range((uintptr_t)&core_pm_cfg_info[cpu_id],
+ sizeof(uint32_t));
+#endif
+}
+
+static int cpus_power_domain_on(uint32_t cpu_id)
+{
+ uint32_t cfg_info;
+ uint32_t cpu_pd = PD_CPUL0 + cpu_id;
+ /*
+ * There are two ways to powering on or off on core.
+ * 1) Control it power domain into on or off in PMU_PWRDN_CON reg
+ * 2) Enable the core power manage in PMU_CORE_PM_CON reg,
+ * then, if the core enter into wfi, it power domain will be
+ * powered off automatically.
+ */
+
+ cfg_info = get_cpus_pwr_domain_cfg_info(cpu_id);
+
+ if (cfg_info == core_pwr_pd) {
+ /* disable core_pm cfg */
+ mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id),
+ CORES_PM_DISABLE);
+ /* if the cores have be on, power off it firstly */
+ if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) {
+ mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), 0);
+ pmu_power_domain_ctr(cpu_pd, pmu_pd_off);
+ }
+
+ pmu_power_domain_ctr(cpu_pd, pmu_pd_on);
+ } else {
+ if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) {
+ WARN("%s: cpu%d is not in off,!\n", __func__, cpu_id);
+ return -EINVAL;
+ }
+
+ mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id),
+ BIT(core_pm_sft_wakeup_en));
+ }
+
+ return 0;
+}
+
+static int cpus_power_domain_off(uint32_t cpu_id, uint32_t pd_cfg)
+{
+ uint32_t cpu_pd;
+ uint32_t core_pm_value;
+
+ cpu_pd = PD_CPUL0 + cpu_id;
+ if (pmu_power_domain_st(cpu_pd) == pmu_pd_off)
+ return 0;
+
+ if (pd_cfg == core_pwr_pd) {
+ if (check_cpu_wfie(cpu_id, CKECK_WFEI_MSK))
+ return -EINVAL;
+
+ /* disable core_pm cfg */
+ mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id),
+ CORES_PM_DISABLE);
+
+ set_cpus_pwr_domain_cfg_info(cpu_id, pd_cfg);
+ pmu_power_domain_ctr(cpu_pd, pmu_pd_off);
+ } else {
+ set_cpus_pwr_domain_cfg_info(cpu_id, pd_cfg);
+
+ core_pm_value = BIT(core_pm_en);
+ if (pd_cfg == core_pwr_wfi_int)
+ core_pm_value |= BIT(core_pm_int_wakeup_en);
+ mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id),
+ core_pm_value);
+ }
+
+ return 0;
+}
+
+static void nonboot_cpus_off(void)
+{
+ uint32_t boot_cpu, cpu;
+
+ boot_cpu = plat_my_core_pos();
+
+ /* turn off noboot cpus */
+ for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) {
+ if (cpu == boot_cpu)
+ continue;
+ cpus_power_domain_off(cpu, core_pwr_pd);
+ }
+}
+
+static int cores_pwr_domain_on(unsigned long mpidr, uint64_t entrypoint)
+{
+ uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr);
+
+ assert(cpuson_flags[cpu_id] == 0);
+ cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG;
+ cpuson_entry_point[cpu_id] = entrypoint;
+ dsb();
+
+ cpus_power_domain_on(cpu_id);
+
+ return 0;
+}
+
+static int cores_pwr_domain_off(void)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+
+ cpus_power_domain_off(cpu_id, core_pwr_wfi);
+
+ return 0;
+}
+
+static int cores_pwr_domain_suspend(void)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+
+ assert(cpuson_flags[cpu_id] == 0);
+ cpuson_flags[cpu_id] = PMU_CPU_AUTO_PWRDN;
+ cpuson_entry_point[cpu_id] = (uintptr_t)psci_entrypoint;
+ dsb();
+
+ cpus_power_domain_off(cpu_id, core_pwr_wfi_int);
+
+ return 0;
+}
+
+static int cores_pwr_domain_on_finish(void)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+
+ cpuson_flags[cpu_id] = 0;
+ cpuson_entry_point[cpu_id] = 0;
+
+ /* Disable core_pm */
+ mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), CORES_PM_DISABLE);
+
+ return 0;
+}
+
+static int cores_pwr_domain_resume(void)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+
+ cpuson_flags[cpu_id] = 0;
+ cpuson_entry_point[cpu_id] = 0;
+
+ /* Disable core_pm */
+ mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), CORES_PM_DISABLE);
+
+ return 0;
+}
+
+static void sys_slp_config(void)
+{
+ uint32_t slp_mode_cfg = 0;
+
+ slp_mode_cfg = PMU_PWR_MODE_EN |
+ PMU_CPU0_PD_EN |
+ PMU_L2_FLUSH_EN |
+ PMU_L2_IDLE_EN |
+ PMU_SCU_PD_EN |
+ PMU_CLK_CORE_SRC_GATE_EN;
+ mmio_setbits_32(PMU_BASE + PMU_WKUP_CFG4, PMU_CLUSTER_L_WKUP_EN);
+ mmio_setbits_32(PMU_BASE + PMU_WKUP_CFG4, PMU_CLUSTER_B_WKUP_EN);
+ mmio_clrbits_32(PMU_BASE + PMU_WKUP_CFG4, PMU_GPIO_WKUP_EN);
+ mmio_write_32(PMU_BASE + PMU_PWRMODE_CON, slp_mode_cfg);
+}
+
+static int sys_pwr_domain_suspend(void)
+{
+ sys_slp_config();
+ plls_suspend();
+ psram_sleep_cfg->sys_mode = PMU_SYS_SLP_MODE;
+ pmu_sgrf_rst_hld();
+ return 0;
+}
+
+static int sys_pwr_domain_resume(void)
+{
+ pmu_sgrf_rst_hld_release();
+ psram_sleep_cfg->sys_mode = PMU_SYS_ON_MODE;
+ plls_resume();
+
+ return 0;
+}
+
+static struct rockchip_pm_ops_cb pm_ops = {
+ .cores_pwr_dm_on = cores_pwr_domain_on,
+ .cores_pwr_dm_off = cores_pwr_domain_off,
+ .cores_pwr_dm_on_finish = cores_pwr_domain_on_finish,
+ .cores_pwr_dm_suspend = cores_pwr_domain_suspend,
+ .cores_pwr_dm_resume = cores_pwr_domain_resume,
+ .sys_pwr_dm_suspend = sys_pwr_domain_suspend,
+ .sys_pwr_dm_resume = sys_pwr_domain_resume,
+ .sys_gbl_soft_reset = soc_global_soft_reset,
+};
+
+void plat_rockchip_pmu_init(void)
+{
+ uint32_t cpu;
+
+ rockchip_pd_lock_init();
+ plat_setup_rockchip_pm_ops(&pm_ops);
+
+ for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++)
+ cpuson_flags[cpu] = 0;
+
+ psram_sleep_cfg->sys_mode = PMU_SYS_ON_MODE;
+
+ psram_sleep_cfg->boot_mpidr = read_mpidr_el1() & 0xffff;
+
+ /* cpu boot from pmusram */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON0_1(1),
+ (PMUSRAM_BASE >> CPU_BOOT_ADDR_ALIGN) |
+ CPU_BOOT_ADDR_WMASK);
+
+ nonboot_cpus_off();
+ INFO("%s(%d): pd status %x\n", __func__, __LINE__,
+ mmio_read_32(PMU_BASE + PMU_PWRDN_ST));
+}
diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu.h b/plat/rockchip/rk3399/drivers/pmu/pmu.h
new file mode 100644
index 0000000..053b6ee
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/pmu/pmu.h
@@ -0,0 +1,709 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PMU_H__
+#define __PMU_H__
+
+/* Allocate sp reginon in pmusram */
+#define PSRAM_SP_SIZE 0x80
+#define PSRAM_SP_BOTTOM (PSRAM_SP_TOP - PSRAM_SP_SIZE)
+
+/*****************************************************************************
+ * Common define for per soc pmu.h
+ *****************************************************************************/
+/* The ways of cores power domain contorlling */
+enum cores_pm_ctr_mode {
+ core_pwr_pd = 0,
+ core_pwr_wfi = 1,
+ core_pwr_wfi_int = 2
+};
+
+/*****************************************************************************
+ * pmu con,reg
+ *****************************************************************************/
+#define PMU_WKUP_CFG(n) ((n) * 4)
+
+#define PMU_CORE_PM_CON(cpu) (0xc0 + (cpu * 4))
+
+/* the shift of bits for cores status */
+enum pmu_core_pwrst_shift {
+ clstl_cpu_wfe = 2,
+ clstl_cpu_wfi = 6,
+ clstb_cpu_wfe = 12,
+ clstb_cpu_wfi = 16
+};
+
+#define CKECK_WFE_MSK 0x1
+#define CKECK_WFI_MSK 0x10
+#define CKECK_WFEI_MSK 0x11
+
+enum pmu_powerdomain_id {
+ PD_CPUL0 = 0,
+ PD_CPUL1,
+ PD_CPUL2,
+ PD_CPUL3,
+ PD_CPUB0,
+ PD_CPUB1,
+ PD_SCUL,
+ PD_SCUB,
+ PD_TCPD0,
+ PD_TCPD1,
+ PD_CCI,
+ PD_PERILP,
+ PD_PERIHP,
+ PD_CENTER,
+ PD_VIO,
+ PD_GPU,
+ PD_VCODEC,
+ PD_VDU,
+ PD_RGA,
+ PD_IEP,
+ PD_VO,
+ PD_ISP0 = 22,
+ PD_ISP1,
+ PD_HDCP,
+ PD_GMAC,
+ PD_EMMC,
+ PD_USB3,
+ PD_EDP,
+ PD_GIC,
+ PD_SD,
+ PD_SDIOAUDIO,
+ PD_END
+};
+
+enum powerdomain_state {
+ PMU_POWER_ON = 0,
+ PMU_POWER_OFF,
+};
+
+enum pmu_bus_id {
+ BUS_ID_GPU = 0,
+ BUS_ID_PERILP,
+ BUS_ID_PERIHP,
+ BUS_ID_VCODEC,
+ BUS_ID_VDU,
+ BUS_ID_RGA,
+ BUS_ID_IEP,
+ BUS_ID_VOPB,
+ BUS_ID_VOPL,
+ BUS_ID_ISP0,
+ BUS_ID_ISP1,
+ BUS_ID_HDCP,
+ BUS_ID_USB3,
+ BUS_ID_PERILPM0,
+ BUS_ID_CENTER,
+ BUS_ID_CCIM0,
+ BUS_ID_CCIM1,
+ BUS_ID_VIO,
+ BUS_ID_MSCH0,
+ BUS_ID_MSCH1,
+ BUS_ID_ALIVE,
+ BUS_ID_PMU,
+ BUS_ID_EDP,
+ BUS_ID_GMAC,
+ BUS_ID_EMMC,
+ BUS_ID_CENTER1,
+ BUS_ID_PMUM0,
+ BUS_ID_GIC,
+ BUS_ID_SD,
+ BUS_ID_SDIOAUDIO,
+};
+
+enum pmu_bus_state {
+ BUS_ACTIVE,
+ BUS_IDLE,
+};
+
+/* pmu_cpuapm bit */
+enum pmu_cores_pm_by_wfi {
+ core_pm_en = 0,
+ core_pm_int_wakeup_en,
+ core_pm_resv,
+ core_pm_sft_wakeup_en
+};
+
+enum pmu_wkup_cfg0 {
+ PMU_GPIO0A_POSE_WKUP_EN = 0,
+ PMU_GPIO0B_POSE_WKUP_EN = 8,
+ PMU_GPIO0C_POSE_WKUP_EN = 16,
+ PMU_GPIO0D_POSE_WKUP_EN = 24,
+};
+
+enum pmu_wkup_cfg1 {
+ PMU_GPIO0A_NEGEDGE_WKUP_EN = 0,
+ PMU_GPIO0B_NEGEDGE_WKUP_EN = 7,
+ PMU_GPIO0C_NEGEDGE_WKUP_EN = 16,
+ PMU_GPIO0D_NEGEDGE_WKUP_EN = 24,
+};
+
+enum pmu_wkup_cfg2 {
+ PMU_GPIO1A_POSE_WKUP_EN = 0,
+ PMU_GPIO1B_POSE_WKUP_EN = 7,
+ PMU_GPIO1C_POSE_WKUP_EN = 16,
+ PMU_GPIO1D_POSE_WKUP_EN = 24,
+};
+
+enum pmu_wkup_cfg3 {
+ PMU_GPIO1A_NEGEDGE_WKUP_EN = 0,
+ PMU_GPIO1B_NEGEDGE_WKUP_EN = 7,
+ PMU_GPIO1C_NEGEDGE_WKUP_EN = 16,
+ PMU_GPIO1D_NEGEDGE_WKUP_EN = 24,
+};
+
+/* pmu_wkup_cfg4 */
+enum pmu_wkup_cfg4 {
+ PMU_CLUSTER_L_WKUP_EN = 0,
+ PMU_CLUSTER_B_WKUP_EN,
+ PMU_GPIO_WKUP_EN,
+ PMU_SDIO_WKUP_EN,
+
+ PMU_SDMMC_WKUP_EN,
+ PMU_TIMER_WKUP_EN = 6,
+ PMU_USBDEV_WKUP_EN,
+
+ PMU_SFT_WKUP_EN,
+ PMU_M0_WDT_WKUP_EN,
+ PMU_TIMEOUT_WKUP_EN,
+ PMU_PWM_WKUP_EN,
+
+ PMU_PCIE_WKUP_EN = 13,
+};
+
+enum pmu_pwrdn_con {
+ PMU_A53_L0_PWRDWN_EN = 0,
+ PMU_A53_L1_PWRDWN_EN,
+ PMU_A53_L2_PWRDWN_EN,
+ PMU_A53_L3_PWRDWN_EN,
+
+ PMU_A72_B0_PWRDWN_EN,
+ PMU_A72_B1_PWRDWN_EN,
+ PMU_SCU_L_PWRDWN_EN,
+ PMU_SCU_B_PWRDWN_EN,
+
+ PMU_TCPD0_PWRDWN_EN,
+ PMU_TCPD1_PWRDWN_EN,
+ PMU_CCI_PWRDWN_EN,
+ PMU_PERILP_PWRDWN_EN,
+
+ PMU_PERIHP_PWRDWN_EN,
+ PMU_CENTER_PWRDWN_EN,
+ PMU_VIO_PWRDWN_EN,
+ PMU_GPU_PWRDWN_EN,
+
+ PMU_VCODEC_PWRDWN_EN,
+ PMU_VDU_PWRDWN_EN,
+ PMU_RGA_PWRDWN_EN,
+ PMU_IEP_PWRDWN_EN,
+
+ PMU_VO_PWRDWN_EN,
+ PMU_ISP0_PWRDWN_EN = 22,
+ PMU_ISP1_PWRDWN_EN,
+
+ PMU_HDCP_PWRDWN_EN,
+ PMU_GMAC_PWRDWN_EN,
+ PMU_EMMC_PWRDWN_EN,
+ PMU_USB3_PWRDWN_EN,
+
+ PMU_EDP_PWRDWN_EN,
+ PMU_GIC_PWRDWN_EN,
+ PMU_SD_PWRDWN_EN,
+ PMU_SDIOAUDIO_PWRDWN_EN,
+};
+
+enum pmu_pwrdn_st {
+ PMU_A53_L0_PWRDWN_ST = 0,
+ PMU_A53_L1_PWRDWN_ST,
+ PMU_A53_L2_PWRDWN_ST,
+ PMU_A53_L3_PWRDWN_ST,
+
+ PMU_A72_B0_PWRDWN_ST,
+ PMU_A72_B1_PWRDWN_ST,
+ PMU_SCU_L_PWRDWN_ST,
+ PMU_SCU_B_PWRDWN_ST,
+
+ PMU_TCPD0_PWRDWN_ST,
+ PMU_TCPD1_PWRDWN_ST,
+ PMU_CCI_PWRDWN_ST,
+ PMU_PERILP_PWRDWN_ST,
+
+ PMU_PERIHP_PWRDWN_ST,
+ PMU_CENTER_PWRDWN_ST,
+ PMU_VIO_PWRDWN_ST,
+ PMU_GPU_PWRDWN_ST,
+
+ PMU_VCODEC_PWRDWN_ST,
+ PMU_VDU_PWRDWN_ST,
+ PMU_RGA_PWRDWN_ST,
+ PMU_IEP_PWRDWN_ST,
+
+ PMU_VO_PWRDWN_ST,
+ PMU_ISP0_PWRDWN_ST = 22,
+ PMU_ISP1_PWRDWN_ST,
+
+ PMU_HDCP_PWRDWN_ST,
+ PMU_GMAC_PWRDWN_ST,
+ PMU_EMMC_PWRDWN_ST,
+ PMU_USB3_PWRDWN_ST,
+
+ PMU_EDP_PWRDWN_ST,
+ PMU_GIC_PWRDWN_ST,
+ PMU_SD_PWRDWN_ST,
+ PMU_SDIOAUDIO_PWRDWN_ST,
+
+};
+
+enum pmu_pll_con {
+ PMU_PLL_PD_CFG = 0,
+ PMU_SFT_PLL_PD = 8,
+};
+
+enum pmu_pwermode_con {
+ PMU_PWR_MODE_EN = 0,
+ PMU_WKUP_RST_EN,
+ PMU_INPUT_CLAMP_EN,
+ PMU_OSC_DIS,
+
+ PMU_ALIVE_USE_LF,
+ PMU_PMU_USE_LF,
+ PMU_POWER_OFF_REQ_CFG,
+ PMU_CHIP_PD_EN,
+
+ PMU_PLL_PD_EN,
+ PMU_CPU0_PD_EN,
+ PMU_L2_FLUSH_EN,
+ PMU_L2_IDLE_EN,
+
+ PMU_SCU_PD_EN,
+ PMU_CCI_PD_EN,
+ PMU_PERILP_PD_EN,
+ PMU_CENTER_PD_EN,
+
+ PMU_SREF0_ENTER_EN,
+ PMU_DDRC0_GATING_EN,
+ PMU_DDRIO0_RET_EN,
+ PMU_DDRIO0_RET_DE_REQ,
+
+ PMU_SREF1_ENTER_EN,
+ PMU_DDRC1_GATING_EN,
+ PMU_DDRIO1_RET_EN,
+ PMU_DDRIO1_RET_DE_REQ,
+
+ PMU_CLK_CENTER_SRC_GATE_EN = 26,
+ PMU_CLK_PERILP_SRC_GATE_EN,
+
+ PMU_CLK_CORE_SRC_GATE_EN,
+ PMU_DDRIO_RET_HW_DE_REQ,
+ PMU_SLP_OUTPUT_CFG,
+ PMU_MAIN_CLUSTER,
+};
+
+enum pmu_sft_con {
+ PMU_WKUP_SFT = 0,
+ PMU_INPUT_CLAMP_CFG,
+ PMU_OSC_DIS_CFG,
+ PMU_PMU_LF_EN_CFG,
+
+ PMU_ALIVE_LF_EN_CFG,
+ PMU_24M_EN_CFG,
+ PMU_DBG_PWRUP_L0_CFG,
+ PMU_WKUP_SFT_M0,
+
+ PMU_DDRCTL0_C_SYSREQ_CFG,
+ PMU_DDR0_IO_RET_CFG,
+
+ PMU_DDRCTL1_C_SYSREQ_CFG = 12,
+ PMU_DDR1_IO_RET_CFG,
+};
+
+enum pmu_int_con {
+ PMU_PMU_INT_EN = 0,
+ PMU_PWRMD_WKUP_INT_EN,
+ PMU_WKUP_GPIO0_NEG_INT_EN,
+ PMU_WKUP_GPIO0_POS_INT_EN,
+ PMU_WKUP_GPIO1_NEG_INT_EN,
+ PMU_WKUP_GPIO1_POS_INT_EN,
+};
+
+enum pmu_int_st {
+ PMU_PWRMD_WKUP_INT_ST = 1,
+ PMU_WKUP_GPIO0_NEG_INT_ST,
+ PMU_WKUP_GPIO0_POS_INT_ST,
+ PMU_WKUP_GPIO1_NEG_INT_ST,
+ PMU_WKUP_GPIO1_POS_INT_ST,
+};
+
+enum pmu_gpio0_pos_int_con {
+ PMU_GPIO0A_POS_INT_EN = 0,
+ PMU_GPIO0B_POS_INT_EN = 8,
+ PMU_GPIO0C_POS_INT_EN = 16,
+ PMU_GPIO0D_POS_INT_EN = 24,
+};
+
+enum pmu_gpio0_neg_int_con {
+ PMU_GPIO0A_NEG_INT_EN = 0,
+ PMU_GPIO0B_NEG_INT_EN = 8,
+ PMU_GPIO0C_NEG_INT_EN = 16,
+ PMU_GPIO0D_NEG_INT_EN = 24,
+};
+
+enum pmu_gpio1_pos_int_con {
+ PMU_GPIO1A_POS_INT_EN = 0,
+ PMU_GPIO1B_POS_INT_EN = 8,
+ PMU_GPIO1C_POS_INT_EN = 16,
+ PMU_GPIO1D_POS_INT_EN = 24,
+};
+
+enum pmu_gpio1_neg_int_con {
+ PMU_GPIO1A_NEG_INT_EN = 0,
+ PMU_GPIO1B_NEG_INT_EN = 8,
+ PMU_GPIO1C_NEG_INT_EN = 16,
+ PMU_GPIO1D_NEG_INT_EN = 24,
+};
+
+enum pmu_gpio0_pos_int_st {
+ PMU_GPIO0A_POS_INT_ST = 0,
+ PMU_GPIO0B_POS_INT_ST = 8,
+ PMU_GPIO0C_POS_INT_ST = 16,
+ PMU_GPIO0D_POS_INT_ST = 24,
+};
+
+enum pmu_gpio0_neg_int_st {
+ PMU_GPIO0A_NEG_INT_ST = 0,
+ PMU_GPIO0B_NEG_INT_ST = 8,
+ PMU_GPIO0C_NEG_INT_ST = 16,
+ PMU_GPIO0D_NEG_INT_ST = 24,
+};
+
+enum pmu_gpio1_pos_int_st {
+ PMU_GPIO1A_POS_INT_ST = 0,
+ PMU_GPIO1B_POS_INT_ST = 8,
+ PMU_GPIO1C_POS_INT_ST = 16,
+ PMU_GPIO1D_POS_INT_ST = 24,
+};
+
+enum pmu_gpio1_neg_int_st {
+ PMU_GPIO1A_NEG_INT_ST = 0,
+ PMU_GPIO1B_NEG_INT_ST = 8,
+ PMU_GPIO1C_NEG_INT_ST = 16,
+ PMU_GPIO1D_NEG_INT_ST = 24,
+};
+
+/* pmu power down configure register 0x0050 */
+enum pmu_pwrdn_inten {
+ PMU_A53_L0_PWR_SWITCH_INT_EN = 0,
+ PMU_A53_L1_PWR_SWITCH_INT_EN,
+ PMU_A53_L2_PWR_SWITCH_INT_EN,
+ PMU_A53_L3_PWR_SWITCH_INT_EN,
+
+ PMU_A72_B0_PWR_SWITCH_INT_EN,
+ PMU_A72_B1_PWR_SWITCH_INT_EN,
+ PMU_SCU_L_PWR_SWITCH_INT_EN,
+ PMU_SCU_B_PWR_SWITCH_INT_EN,
+
+ PMU_TCPD0_PWR_SWITCH_INT_EN,
+ PMU_TCPD1_PWR_SWITCH_INT_EN,
+ PMU_CCI_PWR_SWITCH_INT_EN,
+ PMU_PERILP_PWR_SWITCH_INT_EN,
+
+ PMU_PERIHP_PWR_SWITCH_INT_EN,
+ PMU_CENTER_PWR_SWITCH_INT_EN,
+ PMU_VIO_PWR_SWITCH_INT_EN,
+ PMU_GPU_PWR_SWITCH_INT_EN,
+
+ PMU_VCODEC_PWR_SWITCH_INT_EN,
+ PMU_VDU_PWR_SWITCH_INT_EN,
+ PMU_RGA_PWR_SWITCH_INT_EN,
+ PMU_IEP_PWR_SWITCH_INT_EN,
+
+ PMU_VO_PWR_SWITCH_INT_EN,
+ PMU_ISP0_PWR_SWITCH_INT_EN = 22,
+ PMU_ISP1_PWR_SWITCH_INT_EN,
+
+ PMU_HDCP_PWR_SWITCH_INT_EN,
+ PMU_GMAC_PWR_SWITCH_INT_EN,
+ PMU_EMMC_PWR_SWITCH_INT_EN,
+ PMU_USB3_PWR_SWITCH_INT_EN,
+
+ PMU_EDP_PWR_SWITCH_INT_EN,
+ PMU_GIC_PWR_SWITCH_INT_EN,
+ PMU_SD_PWR_SWITCH_INT_EN,
+ PMU_SDIOAUDIO_PWR_SWITCH_INT_EN,
+};
+
+enum pmu_wkup_status {
+ PMU_WKUP_BY_CLSTER_L_INT = 0,
+ PMU_WKUP_BY_CLSTER_b_INT,
+ PMU_WKUP_BY_GPIO_INT,
+ PMU_WKUP_BY_SDIO_DET,
+
+ PMU_WKUP_BY_SDMMC_DET,
+ PMU_WKUP_BY_TIMER = 6,
+ PMU_WKUP_BY_USBDEV_DET,
+
+ PMU_WKUP_BY_M0_SFT,
+ PMU_WKUP_BY_M0_WDT_INT,
+ PMU_WKUP_BY_TIMEOUT,
+ PMU_WKUP_BY_PWM,
+
+ PMU_WKUP_BY_PCIE = 13,
+};
+
+enum pmu_bus_clr {
+ PMU_CLR_GPU = 0,
+ PMU_CLR_PERILP,
+ PMU_CLR_PERIHP,
+ PMU_CLR_VCODEC,
+
+ PMU_CLR_VDU,
+ PMU_CLR_RGA,
+ PMU_CLR_IEP,
+ PMU_CLR_VOPB,
+
+ PMU_CLR_VOPL,
+ PMU_CLR_ISP0,
+ PMU_CLR_ISP1,
+ PMU_CLR_HDCP,
+
+ PMU_CLR_USB3,
+ PMU_CLR_PERILPM0,
+ PMU_CLR_CENTER,
+ PMU_CLR_CCIM1,
+
+ PMU_CLR_CCIM0,
+ PMU_CLR_VIO,
+ PMU_CLR_MSCH0,
+ PMU_CLR_MSCH1,
+
+ PMU_CLR_ALIVE,
+ PMU_CLR_PMU,
+ PMU_CLR_EDP,
+ PMU_CLR_GMAC,
+
+ PMU_CLR_EMMC,
+ PMU_CLR_CENTER1,
+ PMU_CLR_PMUM0,
+ PMU_CLR_GIC,
+
+ PMU_CLR_SD,
+ PMU_CLR_SDIOAUDIO,
+};
+
+/* PMU bus idle request register */
+enum pmu_bus_idle_req {
+ PMU_IDLE_REQ_GPU = 0,
+ PMU_IDLE_REQ_PERILP,
+ PMU_IDLE_REQ_PERIHP,
+ PMU_IDLE_REQ_VCODEC,
+
+ PMU_IDLE_REQ_VDU,
+ PMU_IDLE_REQ_RGA,
+ PMU_IDLE_REQ_IEP,
+ PMU_IDLE_REQ_VOPB,
+
+ PMU_IDLE_REQ_VOPL,
+ PMU_IDLE_REQ_ISP0,
+ PMU_IDLE_REQ_ISP1,
+ PMU_IDLE_REQ_HDCP,
+
+ PMU_IDLE_REQ_USB3,
+ PMU_IDLE_REQ_PERILPM0,
+ PMU_IDLE_REQ_CENTER,
+ PMU_IDLE_REQ_CCIM0,
+
+ PMU_IDLE_REQ_CCIM1,
+ PMU_IDLE_REQ_VIO,
+ PMU_IDLE_REQ_MSCH0,
+ PMU_IDLE_REQ_MSCH1,
+
+ PMU_IDLE_REQ_ALIVE,
+ PMU_IDLE_REQ_PMU,
+ PMU_IDLE_REQ_EDP,
+ PMU_IDLE_REQ_GMAC,
+
+ PMU_IDLE_REQ_EMMC,
+ PMU_IDLE_REQ_CENTER1,
+ PMU_IDLE_REQ_PMUM0,
+ PMU_IDLE_REQ_GIC,
+
+ PMU_IDLE_REQ_SD,
+ PMU_IDLE_REQ_SDIOAUDIO,
+};
+
+/* pmu bus idle status register */
+enum pmu_bus_idle_st {
+ PMU_IDLE_ST_GPU = 0,
+ PMU_IDLE_ST_PERILP,
+ PMU_IDLE_ST_PERIHP,
+ PMU_IDLE_ST_VCODEC,
+
+ PMU_IDLE_ST_VDU,
+ PMU_IDLE_ST_RGA,
+ PMU_IDLE_ST_IEP,
+ PMU_IDLE_ST_VOPB,
+
+ PMU_IDLE_ST_VOPL,
+ PMU_IDLE_ST_ISP0,
+ PMU_IDLE_ST_ISP1,
+ PMU_IDLE_ST_HDCP,
+
+ PMU_IDLE_ST_USB3,
+ PMU_IDLE_ST_PERILPM0,
+ PMU_IDLE_ST_CENTER,
+ PMU_IDLE_ST_CCIM0,
+
+ PMU_IDLE_ST_CCIM1,
+ PMU_IDLE_ST_VIO,
+ PMU_IDLE_ST_MSCH0,
+ PMU_IDLE_ST_MSCH1,
+
+ PMU_IDLE_ST_ALIVE,
+ PMU_IDLE_ST_PMU,
+ PMU_IDLE_ST_EDP,
+ PMU_IDLE_ST_GMAC,
+
+ PMU_IDLE_ST_EMMC,
+ PMU_IDLE_ST_CENTER1,
+ PMU_IDLE_ST_PMUM0,
+ PMU_IDLE_ST_GIC,
+
+ PMU_IDLE_ST_SD,
+ PMU_IDLE_ST_SDIOAUDIO,
+};
+
+enum pmu_bus_idle_ack {
+ PMU_IDLE_ACK_GPU = 0,
+ PMU_IDLE_ACK_PERILP,
+ PMU_IDLE_ACK_PERIHP,
+ PMU_IDLE_ACK_VCODEC,
+
+ PMU_IDLE_ACK_VDU,
+ PMU_IDLE_ACK_RGA,
+ PMU_IDLE_ACK_IEP,
+ PMU_IDLE_ACK_VOPB,
+
+ PMU_IDLE_ACK_VOPL,
+ PMU_IDLE_ACK_ISP0,
+ PMU_IDLE_ACK_ISP1,
+ PMU_IDLE_ACK_HDCP,
+
+ PMU_IDLE_ACK_USB3,
+ PMU_IDLE_ACK_PERILPM0,
+ PMU_IDLE_ACK_CENTER,
+ PMU_IDLE_ACK_CCIM0,
+
+ PMU_IDLE_ACK_CCIM1,
+ PMU_IDLE_ACK_VIO,
+ PMU_IDLE_ACK_MSCH0,
+ PMU_IDLE_ACK_MSCH1,
+
+ PMU_IDLE_ACK_ALIVE,
+ PMU_IDLE_ACK_PMU,
+ PMU_IDLE_ACK_EDP,
+ PMU_IDLE_ACK_GMAC,
+
+ PMU_IDLE_ACK_EMMC,
+ PMU_IDLE_ACK_CENTER1,
+ PMU_IDLE_ACK_PMUM0,
+ PMU_IDLE_ACK_GIC,
+
+ PMU_IDLE_ACK_SD,
+ PMU_IDLE_ACK_SDIOAUDIO,
+};
+
+enum pmu_pwrdn_con1 {
+ PMU_VD_SCU_L_PWRDN_EN = 0,
+ PMU_VD_SCU_B_PWRDN_EN,
+ PMU_VD_CENTER_PWRDN_EN,
+};
+
+#define PMU_WKUP_CFG0 0x00
+#define PMU_WKUP_CFG1 0x04
+#define PMU_WKUP_CFG2 0x08
+#define PMU_WKUP_CFG3 0x0c
+#define PMU_WKUP_CFG4 0x10
+#define PMU_PWRDN_CON 0x14
+#define PMU_PWRDN_ST 0x18
+#define PMU_PLL_CON 0x1c
+#define PMU_PWRMODE_CON 0x20
+#define PMU_SFT_CON 0x24
+#define PMU_INT_CON 0x28
+#define PMU_INT_ST 0x2c
+#define PMU_GPIO0_POS_INT_CON 0x30
+#define PMU_GPIO0_NEG_INT_CON 0x34
+#define PMU_GPIO1_POS_INT_CON 0x38
+#define PMU_GPIO1_NEG_INT_CON 0x3c
+#define PMU_GPIO0_POS_INT_ST 0x40
+#define PMU_GPIO0_NEG_INT_ST 0x44
+#define PMU_GPIO1_POS_INT_ST 0x48
+#define PMU_GPIO1_NEG_INT_ST 0x4c
+#define PMU_PWRDN_INTEN 0x50
+#define PMU_PWRDN_STATUS 0x54
+#define PMU_WAKEUP_STATUS 0x58
+#define PMU_BUS_CLR 0x5c
+#define PMU_BUS_IDLE_REQ 0x60
+#define PMU_BUS_IDLE_ST 0x64
+#define PMU_BUS_IDLE_ACK 0x68
+#define PMU_CCI500_CON 0x6c
+#define PMU_ADB400_CON 0x70
+#define PMU_ADB400_ST 0x74
+#define PMU_POWER_ST 0x78
+#define PMU_CORE_PWR_ST 0x7c
+#define PMU_OSC_CNT 0x80
+#define PMU_PLLLOCK_CNT 0x84
+#define PMU_PLLRST_CNT 0x88
+#define PMU_STABLE_CNT 0x8c
+#define PMU_DDRIO_PWRON_CNT 0x90
+#define PMU_WAKEUP_RST_CLR_CNT 0x94
+#define PMU_DDR_SREF_ST 0x98
+#define PMU_SCU_L_PWRDN_CNT 0x9c
+#define PMU_SCU_L_PWRUP_CNT 0xa0
+#define PMU_SCU_B_PWRDN_CNT 0xa4
+#define PMU_SCU_B_PWRUP_CNT 0xa8
+#define PMU_GPU_PWRDN_CNT 0xac
+#define PMU_GPU_PWRUP_CNT 0xb0
+#define PMU_CENTER_PWRDN_CNT 0xb4
+#define PMU_CENTER_PWRUP_CNT 0xb8
+#define PMU_TIMEOUT_CNT 0xbc
+#define PMU_CPU0APM_CON 0xc0
+#define PMU_CPU1APM_CON 0xc4
+#define PMU_CPU2APM_CON 0xc8
+#define PMU_CPU3APM_CON 0xcc
+#define PMU_CPU0BPM_CON 0xd0
+#define PMU_CPU1BPM_CON 0xd4
+#define PMU_NOC_AUTO_ENA 0xd8
+#define PMU_PWRDN_CON1 0xdc
+
+#define CORES_PM_DISABLE 0x0
+
+#define PD_CTR_LOOP 500
+#define CHK_CPU_LOOP 500
+
+#endif /* __PMU_H__ */
diff --git a/plat/rockchip/rk3399/drivers/soc/soc.c b/plat/rockchip/rk3399/drivers/soc/soc.c
new file mode 100644
index 0000000..f8d66c2
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/soc/soc.c
@@ -0,0 +1,348 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <debug.h>
+#include <delay_timer.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <plat_private.h>
+#include <rk3399_def.h>
+#include <soc.h>
+
+/* Table of regions to map using the MMU. */
+const mmap_region_t plat_rk_mmap[] = {
+ MAP_REGION_FLAT(GIC500_BASE, GIC500_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(CCI500_BASE, CCI500_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(STIME_BASE, STIME_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(CRUS_BASE, CRUS_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(SGRF_BASE, SGRF_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(PMU_BASE, PMU_SIZE,
+ MT_DEVICE | MT_RW | MT_NS),
+ MAP_REGION_FLAT(PMUSRAM_BASE, PMUSRAM_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(RK3399_UART2_BASE, RK3399_UART2_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ { 0 }
+};
+
+/* The RockChip power domain tree descriptor */
+const unsigned char rockchip_power_domain_tree_desc[] = {
+ /* No of root nodes */
+ PLATFORM_SYSTEM_COUNT,
+ /* No of children for the root node */
+ PLATFORM_CLUSTER_COUNT,
+ /* No of children for the first cluster node */
+ PLATFORM_CLUSTER0_CORE_COUNT,
+ /* No of children for the second cluster node */
+ PLATFORM_CLUSTER1_CORE_COUNT
+};
+
+void secure_timer_init(void)
+{
+ mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_END_COUNT0, 0xffffffff);
+ mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_END_COUNT1, 0xffffffff);
+
+ mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_INIT_COUNT0, 0x0);
+ mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_INIT_COUNT0, 0x0);
+
+ /* auto reload & enable the timer */
+ mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_CONTROL_REG,
+ TIMER_EN | TIMER_FMODE);
+}
+
+void sgrf_init(void)
+{
+ /* security config for master */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON3_7(5),
+ SGRF_SOC_CON_WMSK | SGRF_SOC_ALLMST_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON3_7(6),
+ SGRF_SOC_CON_WMSK | SGRF_SOC_ALLMST_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON3_7(7),
+ SGRF_SOC_CON_WMSK | SGRF_SOC_ALLMST_NS);
+
+ /* security config for slave */
+ mmio_write_32(SGRF_BASE + SGRF_PMU_SLV_CON0_1(0),
+ SGRF_PMU_SLV_S_CFGED |
+ SGRF_PMU_SLV_CRYPTO1_NS);
+ mmio_write_32(SGRF_BASE + SGRF_PMU_SLV_CON0_1(1),
+ SGRF_PMU_SLV_CON1_CFG);
+ mmio_write_32(SGRF_BASE + SGRF_SLV_SECURE_CON0_4(0),
+ SGRF_SLV_S_WMSK | SGRF_SLV_S_ALL_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SLV_SECURE_CON0_4(1),
+ SGRF_SLV_S_WMSK | SGRF_SLV_S_ALL_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SLV_SECURE_CON0_4(2),
+ SGRF_SLV_S_WMSK | SGRF_SLV_S_ALL_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SLV_SECURE_CON0_4(3),
+ SGRF_SLV_S_WMSK | SGRF_SLV_S_ALL_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SLV_SECURE_CON0_4(4),
+ SGRF_SLV_S_WMSK | SGRF_SLV_S_ALL_NS);
+
+ /* security config for ddr memery */
+ mmio_write_32(SGRF_BASE + SGRF_DDRRGN_CON0_16(16),
+ SGRF_DDR_RGN_BYPS);
+}
+
+static void dma_secure_cfg(uint32_t secure)
+{
+ if (secure) {
+ /* rgn0 secure for dmac0 and dmac1 */
+ mmio_write_32(SGRF_BASE + SGRF_DDRRGN_CON20_34(22),
+ SGRF_L_MST_S_DDR_RGN(0) | /* dmac0 */
+ SGRF_H_MST_S_DDR_RGN(0) /* dmac1 */
+ );
+
+ /* set dmac0 boot, under secure state */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(8),
+ SGRF_DMAC_CFG_S);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(9),
+ SGRF_DMAC_CFG_S);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(10),
+ SGRF_DMAC_CFG_S);
+
+ /* dmac0 soft reset */
+ mmio_write_32(CRU_BASE + CRU_SOFTRST_CON(10),
+ CRU_DMAC0_RST);
+ udelay(5);
+ mmio_write_32(CRU_BASE + CRU_SOFTRST_CON(10),
+ CRU_DMAC0_RST_RLS);
+
+ /* set dmac1 boot, under secure state */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(11),
+ SGRF_DMAC_CFG_S);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(12),
+ SGRF_DMAC_CFG_S);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(13),
+ SGRF_DMAC_CFG_S);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(14),
+ SGRF_DMAC_CFG_S);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(15),
+ SGRF_DMAC_CFG_S);
+
+ /* dmac1 soft reset */
+ mmio_write_32(CRU_BASE + CRU_SOFTRST_CON(10),
+ CRU_DMAC1_RST);
+ udelay(5);
+ mmio_write_32(CRU_BASE + CRU_SOFTRST_CON(10),
+ CRU_DMAC1_RST_RLS);
+ } else {
+ /* rgn non-secure for dmac0 and dmac1 */
+ mmio_write_32(SGRF_BASE + SGRF_DDRRGN_CON20_34(22),
+ DMAC1_RGN_NS | DMAC0_RGN_NS);
+
+ /* set dmac0 boot, under non-secure state */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(8),
+ DMAC0_BOOT_CFG_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(9),
+ DMAC0_BOOT_PERIPH_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(10),
+ DMAC0_BOOT_ADDR_NS);
+
+ /* dmac0 soft reset */
+ mmio_write_32(CRU_BASE + CRU_SOFTRST_CON(10),
+ CRU_DMAC0_RST);
+ udelay(5);
+ mmio_write_32(CRU_BASE + CRU_SOFTRST_CON(10),
+ CRU_DMAC0_RST_RLS);
+
+ /* set dmac1 boot, under non-secure state */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(11),
+ DMAC1_BOOT_CFG_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(12),
+ DMAC1_BOOT_PERIPH_L_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(13),
+ DMAC1_BOOT_ADDR_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(14),
+ DMAC1_BOOT_PERIPH_H_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON8_15(15),
+ DMAC1_BOOT_IRQ_NS);
+
+ /* dmac1 soft reset */
+ mmio_write_32(CRU_BASE + CRU_SOFTRST_CON(10),
+ CRU_DMAC1_RST);
+ udelay(5);
+ mmio_write_32(CRU_BASE + CRU_SOFTRST_CON(10),
+ CRU_DMAC1_RST_RLS);
+ }
+}
+
+/* pll suspend */
+struct deepsleep_data_s slp_data;
+
+static void pll_suspend_prepare(uint32_t pll_id)
+{
+ int i;
+
+ if (pll_id == PPLL_ID)
+ for (i = 0; i < PLL_CON_COUNT; i++)
+ slp_data.plls_con[pll_id][i] =
+ mmio_read_32(PMUCRU_BASE + PMUCRU_PPLL_CON(i));
+ else
+ for (i = 0; i < PLL_CON_COUNT; i++)
+ slp_data.plls_con[pll_id][i] =
+ mmio_read_32(CRU_BASE + CRU_PLL_CON(pll_id, i));
+}
+
+static void set_pll_slow_mode(uint32_t pll_id)
+{
+ if (pll_id == PPLL_ID)
+ mmio_write_32(PMUCRU_BASE + PMUCRU_PPLL_CON(3), PLL_SLOW_MODE);
+ else
+ mmio_write_32((CRU_BASE +
+ CRU_PLL_CON(pll_id, 3)), PLL_SLOW_MODE);
+}
+
+static void set_pll_normal_mode(uint32_t pll_id)
+{
+ if (pll_id == PPLL_ID)
+ mmio_write_32(PMUCRU_BASE + PMUCRU_PPLL_CON(3), PLL_NOMAL_MODE);
+ else
+ mmio_write_32(CRU_BASE +
+ CRU_PLL_CON(pll_id, 3), PLL_NOMAL_MODE);
+}
+
+static void set_pll_bypass(uint32_t pll_id)
+{
+ if (pll_id == PPLL_ID)
+ mmio_write_32(PMUCRU_BASE +
+ PMUCRU_PPLL_CON(3), PLL_BYPASS_MODE);
+ else
+ mmio_write_32(CRU_BASE +
+ CRU_PLL_CON(pll_id, 3), PLL_BYPASS_MODE);
+}
+
+static void _pll_suspend(uint32_t pll_id)
+{
+ set_pll_slow_mode(pll_id);
+ set_pll_bypass(pll_id);
+}
+
+void plls_suspend(void)
+{
+ uint32_t i, pll_id;
+
+ for (pll_id = ALPLL_ID; pll_id < END_PLL_ID; pll_id++)
+ pll_suspend_prepare(pll_id);
+
+ for (i = 0; i < CRU_CLKSEL_COUNT; i++)
+ slp_data.cru_clksel_con[i] =
+ mmio_read_32(CRU_BASE +
+ CRU_CLKSEL_OFFSET + i * REG_SIZE);
+
+ for (i = 0; i < PMUCRU_CLKSEL_CONUT; i++)
+ slp_data.pmucru_clksel_con[i] =
+ mmio_read_32(PMUCRU_BASE +
+ PMUCRU_CLKSEL_OFFSET + i * REG_SIZE);
+
+ _pll_suspend(CPLL_ID);
+ _pll_suspend(NPLL_ID);
+ _pll_suspend(VPLL_ID);
+ _pll_suspend(PPLL_ID);
+ _pll_suspend(GPLL_ID);
+ _pll_suspend(ABPLL_ID);
+ _pll_suspend(ALPLL_ID);
+}
+
+static void set_plls_nobypass(uint32_t pll_id)
+{
+ if (pll_id == PPLL_ID)
+ mmio_write_32(PMUCRU_BASE + PMUCRU_PPLL_CON(3),
+ PLL_NO_BYPASS_MODE);
+ else
+ mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 3),
+ PLL_NO_BYPASS_MODE);
+}
+
+static void plls_resume_prepare(void)
+{
+ int i;
+
+ for (i = 0; i < CRU_CLKSEL_COUNT; i++)
+ mmio_write_32((CRU_BASE + CRU_CLKSEL_OFFSET + i * REG_SIZE),
+ REG_SOC_WMSK | slp_data.cru_clksel_con[i]);
+ for (i = 0; i < PMUCRU_CLKSEL_CONUT; i++)
+ mmio_write_32((PMUCRU_BASE +
+ PMUCRU_CLKSEL_OFFSET + i * REG_SIZE),
+ REG_SOC_WMSK | slp_data.pmucru_clksel_con[i]);
+}
+
+void plls_resume(void)
+{
+ int pll_id;
+
+ plls_resume_prepare();
+ for (pll_id = ALPLL_ID; pll_id < END_PLL_ID; pll_id++) {
+ set_plls_nobypass(pll_id);
+ set_pll_normal_mode(pll_id);
+ }
+}
+
+void soc_global_soft_reset_init(void)
+{
+ mmio_write_32(PMUCRU_BASE + CRU_PMU_RSTHOLD_CON(1),
+ CRU_PMU_SGRF_RST_RLS);
+}
+
+void __dead2 soc_global_soft_reset(void)
+{
+ uint32_t temp_val;
+
+ set_pll_slow_mode(VPLL_ID);
+ set_pll_slow_mode(NPLL_ID);
+ set_pll_slow_mode(GPLL_ID);
+ set_pll_slow_mode(CPLL_ID);
+ set_pll_slow_mode(PPLL_ID);
+ set_pll_slow_mode(ABPLL_ID);
+ set_pll_slow_mode(ALPLL_ID);
+ temp_val = mmio_read_32(CRU_BASE + CRU_GLB_RST_CON) |
+ PMU_RST_BY_FIRST_SFT;
+ mmio_write_32(CRU_BASE + CRU_GLB_RST_CON, temp_val);
+ mmio_write_32(CRU_BASE + CRU_GLB_SRST_FST, GLB_SRST_FST_CFG_VAL);
+
+ /*
+ * Maybe the HW needs some times to reset the system,
+ * so we do not hope the core to excute valid codes.
+ */
+ while (1)
+ ;
+}
+
+void plat_rockchip_soc_init(void)
+{
+ secure_timer_init();
+ dma_secure_cfg(0);
+ sgrf_init();
+ soc_global_soft_reset_init();
+}
diff --git a/plat/rockchip/rk3399/drivers/soc/soc.h b/plat/rockchip/rk3399/drivers/soc/soc.h
new file mode 100644
index 0000000..9100d02
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/soc/soc.h
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SOC_H__
+#define __SOC_H__
+
+#define GLB_SRST_FST_CFG_VAL 0xfdb9
+#define GLB_SRST_SND_CFG_VAL 0xeca8
+
+#define PMUCRU_PPLL_CON_OFFSET 0x000
+#define PMUCRU_PPLL_CON_BASE_ADDR (PMUCRU_BASE + PMUCRU_PPLL_CON_OFFSET)
+#define PMUCRU_PPLL_CON_CONUT 0x06
+
+#define PMUCRU_PPLL_CON(num) (PMUCRU_PPLL_CON_BASE_ADDR + num * 4)
+#define CRU_PLL_CON(pll_id, num) (CRU_BASE + pll_id * 0x20 + num * 4)
+#define PLL_MODE_MSK 0x03
+#define PLL_MODE_SHIFT 0x08
+#define PLL_BYPASS_MSK 0x01
+#define PLL_BYPASS_SHIFT 0x01
+#define PLL_PWRDN_MSK 0x01
+#define PLL_PWRDN_SHIFT 0x0
+#define PLL_BYPASS BIT(1)
+#define PLL_PWRDN BIT(0)
+
+#define NO_PLL_BYPASS (0x00)
+#define NO_PLL_PWRDN (0x00)
+
+#define PLL_SLOW_MODE BITS_WITH_WMASK(PLL_MODE_MSK,\
+ SLOW_MODE, PLL_MODE_SHIFT)
+#define PLL_BYPASS_MODE BITS_WITH_WMASK(PLL_BYPASS_MSK,\
+ PLL_BYPASS, PLL_BYPASS_SHIFT)
+#define PLL_NO_BYPASS_MODE BITS_WITH_WMASK(PLL_BYPASS_MSK,\
+ NO_PLL_BYPASS, PLL_BYPASS_SHIFT)
+#define PLL_NOMAL_MODE BITS_WITH_WMASK(PLL_MODE_MSK,\
+ NORMAL_MODE, PLL_MODE_SHIFT)
+
+#define PLL_CON_COUNT 0x06
+#define CRU_CLKSEL_COUNT 0x108
+#define CRU_CLKSEL_OFFSET 0x300
+
+#define PMUCRU_CLKSEL_CONUT 0x06
+#define PMUCRU_CLKSEL_OFFSET 0x080
+#define REG_SIZE 0x04
+#define REG_SOC_WMSK 0xffff0000
+
+enum plls_id {
+ ALPLL_ID = 0,
+ ABPLL_ID,
+ DPLL_ID,
+ CPLL_ID,
+ GPLL_ID,
+ NPLL_ID,
+ VPLL_ID,
+ PPLL_ID,
+ END_PLL_ID,
+};
+
+enum pll_work_mode {
+ SLOW_MODE = 0x00,
+ NORMAL_MODE = 0x01,
+ DEEP_SLOW_MODE = 0x02,
+};
+
+enum glb_sft_reset {
+ PMU_RST_BY_FIRST_SFT,
+ PMU_RST_BY_SECOND_SFT = BIT(2),
+ PMU_RST_NOT_BY_SFT = BIT(3),
+};
+
+struct deepsleep_data_s {
+ uint32_t plls_con[END_PLL_ID][PLL_CON_COUNT];
+ uint32_t pmucru_clksel_con[PMUCRU_CLKSEL_CONUT];
+ uint32_t cru_clksel_con[CRU_CLKSEL_COUNT];
+};
+
+/**************************************************
+ * secure timer
+ **************************************************/
+
+/* chanal0~5 */
+#define STIMER0_CHN_BASE(n) (STIME_BASE + 0x20 * (n))
+/* chanal6~11 */
+#define STIMER1_CHN_BASE(n) (STIME_BASE + 0x8000 + 0x20 * (n))
+
+ /* low 32 bits */
+#define TIMER_END_COUNT0 0x00
+ /* high 32 bits */
+#define TIMER_END_COUNT1 0x04
+
+#define TIMER_CURRENT_VALUE0 0x08
+#define TIMER_CURRENT_VALUE1 0x0C
+
+ /* low 32 bits */
+#define TIMER_INIT_COUNT0 0x10
+ /* high 32 bits */
+#define TIMER_INIT_COUNT1 0x14
+
+#define TIMER_INTSTATUS 0x18
+#define TIMER_CONTROL_REG 0x1c
+
+#define TIMER_EN 0x1
+
+#define TIMER_FMODE (0x0 << 1)
+#define TIMER_RMODE (0x1 << 1)
+
+/**************************************************
+ * cru reg, offset
+ **************************************************/
+#define CRU_SOFTRST_CON(n) (0x400 + (n) * 4)
+
+#define CRU_DMAC0_RST BIT_WITH_WMSK(3)
+ /* reset release*/
+#define CRU_DMAC0_RST_RLS WMSK_BIT(3)
+
+#define CRU_DMAC1_RST BIT_WITH_WMSK(4)
+ /* reset release*/
+#define CRU_DMAC1_RST_RLS WMSK_BIT(4)
+
+#define CRU_GLB_RST_CON 0x0510
+#define CRU_GLB_SRST_FST 0x0500
+#define CRU_GLB_SRST_SND 0x0504
+
+/**************************************************
+ * pmu cru reg, offset
+ **************************************************/
+#define CRU_PMU_RSTHOLD_CON(n) (0x120 + n * 4)
+/* reset hold*/
+#define CRU_PMU_SGRF_RST_HOLD BIT_WITH_WMSK(6)
+/* reset hold release*/
+#define CRU_PMU_SGRF_RST_RLS WMSK_BIT(6)
+/**************************************************
+ * sgrf reg, offset
+ **************************************************/
+#define SGRF_SOC_CON0_1(n) (0xc000 + (n) * 4)
+#define SGRF_SOC_CON3_7(n) (0xe00c + ((n) - 3) * 4)
+#define SGRF_SOC_CON8_15(n) (0x8020 + ((n) - 8) * 4)
+#define SGRF_PMU_SLV_CON0_1(n) (0xc240 + ((n) - 0) * 4)
+#define SGRF_SLV_SECURE_CON0_4(n) (0xe3c0 + ((n) - 0) * 4)
+#define SGRF_DDRRGN_CON0_16(n) ((n) * 4)
+#define SGRF_DDRRGN_CON20_34(n) (0x50 + ((n) - 20) * 4)
+
+/* security config for master */
+#define SGRF_SOC_CON_WMSK 0xffff0000
+/* All of master in ns */
+#define SGRF_SOC_ALLMST_NS 0xffff
+
+/* security config for slave */
+#define SGRF_SLV_S_WMSK 0xffff0000
+#define SGRF_SLV_S_ALL_NS 0x0
+
+/* security config pmu slave ip */
+/* All of slaves is ns */
+#define SGRF_PMU_SLV_S_NS BIT_WITH_WMSK(0)
+/* slaves secure attr is configed */
+#define SGRF_PMU_SLV_S_CFGED WMSK_BIT(0)
+#define SGRF_PMU_SLV_CRYPTO1_NS WMSK_BIT(1)
+
+#define SGRF_PMUSRAM_S BIT(8)
+
+#define SGRF_PMU_SLV_CON1_CFG (SGRF_SLV_S_WMSK | \
+ SGRF_PMUSRAM_S)
+/* ddr region */
+#define SGRF_DDR_RGN_BYPS BIT_WITH_WMSK(9) /* All of ddr rgn is ns */
+
+/* The MST access the ddr rgn n with secure attribution */
+#define SGRF_L_MST_S_DDR_RGN(n) BIT_WITH_WMSK((n))
+/* bits[16:8]*/
+#define SGRF_H_MST_S_DDR_RGN(n) BIT_WITH_WMSK((n) + 8)
+
+/* dmac to periph s or ns*/
+#define SGRF_DMAC_CFG_S 0xffff0000
+
+#define DMAC1_RGN_NS 0xff000000
+#define DMAC0_RGN_NS 0x00ff0000
+
+#define DMAC0_BOOT_CFG_NS 0xfffffff8
+#define DMAC0_BOOT_PERIPH_NS 0xffff0fff
+#define DMAC0_BOOT_ADDR_NS 0xffff0000
+
+#define DMAC1_BOOT_CFG_NS 0xffff0008
+#define DMAC1_BOOT_PERIPH_L_NS 0xffff0fff
+#define DMAC1_BOOT_ADDR_NS 0xffff0000
+#define DMAC1_BOOT_PERIPH_H_NS 0xffffffff
+#define DMAC1_BOOT_IRQ_NS 0xffffffff
+
+#define CPU_BOOT_ADDR_WMASK 0xffff0000
+#define CPU_BOOT_ADDR_ALIGN 16
+
+/*
+ * When system reset in running state, we want the cpus to be reboot
+ * from maskrom (system reboot),
+ * the pmusgrf reset-hold bits needs to be released.
+ * When system wake up from system deep suspend, some soc will be reset
+ * when waked up,
+ * we want the bootcpu to be reboot from pmusram,
+ * the pmusgrf reset-hold bits needs to be held.
+ */
+static inline void pmu_sgrf_rst_hld_release(void)
+{
+ mmio_write_32(PMUCRU_BASE + CRU_PMU_RSTHOLD_CON(1),
+ CRU_PMU_SGRF_RST_RLS);
+}
+
+static inline void pmu_sgrf_rst_hld(void)
+{
+ mmio_write_32(PMUCRU_BASE + CRU_PMU_RSTHOLD_CON(1),
+ CRU_PMU_SGRF_RST_HOLD);
+}
+
+/* funciton*/
+void __dead2 soc_global_soft_reset(void);
+void plls_resume(void);
+void plls_suspend(void);
+
+#endif /* __SOC_H__ */
diff --git a/plat/rockchip/rk3399/include/platform_def.h b/plat/rockchip/rk3399/include/platform_def.h
new file mode 100644
index 0000000..13f3d50
--- /dev/null
+++ b/plat/rockchip/rk3399/include/platform_def.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PLATFORM_DEF_H__
+#define __PLATFORM_DEF_H__
+
+#include <arch.h>
+#include <common_def.h>
+#include <rk3399_def.h>
+
+#define DEBUG_XLAT_TABLE 0
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#if DEBUG_XLAT_TABLE
+#define PLATFORM_STACK_SIZE 0x800
+#elif IMAGE_BL1
+#define PLATFORM_STACK_SIZE 0x440
+#elif IMAGE_BL2
+#define PLATFORM_STACK_SIZE 0x400
+#elif IMAGE_BL31
+#define PLATFORM_STACK_SIZE 0x800
+#elif IMAGE_BL32
+#define PLATFORM_STACK_SIZE 0x440
+#endif
+
+#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n"
+
+#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL2
+#define PLATFORM_SYSTEM_COUNT 1
+#define PLATFORM_CLUSTER_COUNT 2
+#define PLATFORM_CLUSTER0_CORE_COUNT 4
+#define PLATFORM_CLUSTER1_CORE_COUNT 2
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \
+ PLATFORM_CLUSTER0_CORE_COUNT)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER 4
+#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \
+ PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2
+
+/*
+ * This macro defines the deepest retention state possible. A higher state
+ * id will represent an invalid or a power down state.
+ */
+#define PLAT_MAX_RET_STATE 1
+
+/*
+ * This macro defines the deepest power down states possible. Any state ID
+ * higher than this is invalid.
+ */
+#define PLAT_MAX_OFF_STATE 2
+
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+/* TF txet, ro, rw, Size: 512KB */
+#define TZRAM_BASE (0x0)
+#define TZRAM_SIZE (0x80000)
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL3-1 at the top of the Trusted RAM
+ */
+#define BL31_BASE (TZRAM_BASE + 0x8000)
+#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE)
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define ADDR_SPACE_SIZE (1ull << 32)
+#define MAX_XLAT_TABLES 20
+#define MAX_MMAP_REGIONS 16
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * 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. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+/*
+ * Define GICD and GICC and GICR base
+ */
+#define PLAT_RK_GICD_BASE BASE_GICD_BASE
+#define PLAT_RK_GICR_BASE BASE_GICR_BASE
+#define PLAT_RK_GICC_BASE 0
+
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_RK_G1S_IRQS RK3399_G1S_IRQS
+#define PLAT_RK_G0_IRQS RK3399_G0_IRQS
+
+#define PLAT_RK_UART_BASE RK3399_UART2_BASE
+#define PLAT_RK_UART_CLOCK RK3399_UART_CLOCK
+#define PLAT_RK_UART_BAUDRATE RK3399_BAUDRATE
+
+#define PLAT_RK_CCI_BASE CCI500_BASE
+
+#define PLAT_RK_PRIMARY_CPU 0x0
+
+#define RK_PLAT_AARCH_CFG RK_PLAT_CFG1
+
+#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/rockchip/rk3399/platform.mk b/plat/rockchip/rk3399/platform.mk
new file mode 100644
index 0000000..7851726
--- /dev/null
+++ b/plat/rockchip/rk3399/platform.mk
@@ -0,0 +1,73 @@
+#
+# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# Neither the name of ARM nor the names of its contributors may be used
+# to endorse or promote products derived from this software without specific
+# prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+RK_PLAT := plat/rockchip
+RK_PLAT_SOC := ${RK_PLAT}/${PLAT}
+RK_PLAT_COMMON := ${RK_PLAT}/common
+
+PLAT_INCLUDES := -I${RK_PLAT_COMMON}/ \
+ -I${RK_PLAT_COMMON}/include/ \
+ -I${RK_PLAT_COMMON}/pmusram \
+ -I${RK_PLAT_COMMON}/drivers/pmu/ \
+ -I${RK_PLAT_SOC}/ \
+ -I${RK_PLAT_SOC}/drivers/pmu/ \
+ -I${RK_PLAT_SOC}/drivers/soc/ \
+ -I${RK_PLAT_SOC}/include/ \
+
+RK_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 \
+ ${RK_PLAT}/common/rockchip_gicv3.c
+
+PLAT_BL_COMMON_SOURCES := lib/aarch64/xlat_tables.c \
+ plat/common/aarch64/plat_common.c \
+ plat/common/aarch64/plat_psci_common.c
+
+BL31_SOURCES += ${RK_GIC_SOURCES} \
+ drivers/arm/cci/cci.c \
+ drivers/console/console.S \
+ drivers/ti/uart/16550_console.S \
+ drivers/delay_timer/delay_timer.c \
+ lib/cpus/aarch64/cortex_a53.S \
+ lib/cpus/aarch64/cortex_a72.S \
+ plat/common/aarch64/platform_mp_stack.S \
+ ${RK_PLAT_COMMON}/aarch64/plat_helpers.S \
+ ${RK_PLAT_COMMON}/bl31_plat_setup.c \
+ ${RK_PLAT_COMMON}/pmusram/pmu_sram_cpus_on.S \
+ ${RK_PLAT_COMMON}/pmusram/pmu_sram.c \
+ ${RK_PLAT_COMMON}/plat_delay_timer.c \
+ ${RK_PLAT_COMMON}/plat_pm.c \
+ ${RK_PLAT_COMMON}/plat_topology.c \
+ ${RK_PLAT_COMMON}/aarch64/platform_common.c \
+ ${RK_PLAT_SOC}/drivers/pmu/pmu.c \
+ ${RK_PLAT_SOC}/drivers/soc/soc.c
+
+ENABLE_PLAT_COMPAT := 0
diff --git a/plat/rockchip/rk3399/rk3399_def.h b/plat/rockchip/rk3399/rk3399_def.h
new file mode 100644
index 0000000..8562148
--- /dev/null
+++ b/plat/rockchip/rk3399/rk3399_def.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PLAT_DEF_H__
+#define __PLAT_DEF_H__
+
+#define RK3399_PRIMARY_CPU 0x0
+
+/* Special value used to verify platform parameters from BL2 to BL3-1 */
+#define RK_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL
+
+#define SIZE_K(n) ((n) * 1024)
+#define SIZE_M(n) ((n) * 1024 * 1024)
+
+#define CCI500_BASE 0xffb00000
+#define CCI500_SIZE SIZE_M(1)
+
+#define GIC500_BASE 0xfee00000
+#define GIC500_SIZE SIZE_M(2)
+
+#define STIME_BASE 0xff860000
+#define STIME_SIZE SIZE_K(64)
+
+#define CRUS_BASE 0xff750000
+#define CRUS_SIZE SIZE_K(128)
+
+#define SGRF_BASE 0xff330000
+#define SGRF_SIZE SIZE_K(64)
+
+#define PMU_BASE 0xff310000
+#define PMU_SIZE SIZE_K(64)
+
+#define PMUSRAM_BASE 0xff3b0000
+#define PMUSRAM_SIZE SIZE_K(64)
+#define PMUSRAM_RSIZE SIZE_K(8)
+
+/*
+ * include i2c pmu/audio, pwm0-3 rkpwm0-3 uart_dbg,mailbox scr
+ * 0xff650000 -0xff6c0000
+ */
+#define PD_BUS0_BASE 0xff650000
+#define PD_BUS0_SIZE 0x70000
+
+#define PMUCRU_BASE 0xff750000
+#define CRU_BASE 0xff760000
+
+#define COLD_BOOT_BASE 0xffff0000
+
+/**************************************************************************
+ * UART related constants
+ **************************************************************************/
+#define RK3399_UART2_BASE (0xff1a0000)
+#define RK3399_UART2_SIZE SIZE_K(64)
+
+#define RK3399_BAUDRATE (1500000)
+#define RK3399_UART_CLOCK (24000000)
+
+/******************************************************************************
+ * System counter frequency related constants
+ ******************************************************************************/
+#define SYS_COUNTER_FREQ_IN_TICKS 24000000
+#define SYS_COUNTER_FREQ_IN_MHZ 24
+
+/* Base rockchip_platform compatible GIC memory map */
+#define BASE_GICD_BASE (GIC500_BASE)
+#define BASE_GICR_BASE (GIC500_BASE + SIZE_M(1))
+
+/*****************************************************************************
+ * CCI-400 related constants
+ ******************************************************************************/
+#define PLAT_RK_CCI_CLUSTER0_SL_IFACE_IX 0
+#define PLAT_RK_CCI_CLUSTER1_SL_IFACE_IX 1
+
+/******************************************************************************
+ * cpu up status
+ ******************************************************************************/
+#define PMU_CPU_HOTPLUG 0xdeadbeaf
+#define PMU_CPU_AUTO_PWRDN 0xabcdef12
+
+/******************************************************************************
+ * sgi, ppi
+ ******************************************************************************/
+#define ARM_IRQ_SEC_PHY_TIMER 29
+
+#define ARM_IRQ_SEC_SGI_0 8
+#define ARM_IRQ_SEC_SGI_1 9
+#define ARM_IRQ_SEC_SGI_2 10
+#define ARM_IRQ_SEC_SGI_3 11
+#define ARM_IRQ_SEC_SGI_4 12
+#define ARM_IRQ_SEC_SGI_5 13
+#define ARM_IRQ_SEC_SGI_6 14
+#define ARM_IRQ_SEC_SGI_7 15
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define RK3399_G1S_IRQS ARM_IRQ_SEC_PHY_TIMER
+#define RK3399_G0_IRQS ARM_IRQ_SEC_SGI_6
+
+#endif /* __PLAT_DEF_H__ */
diff --git a/tools/cert_create/Makefile b/tools/cert_create/Makefile
index 8d7b8a5..27545ba 100644
--- a/tools/cert_create/Makefile
+++ b/tools/cert_create/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
@@ -32,7 +32,7 @@
PLAT := none
V := 0
DEBUG := 0
-BINARY := ${PROJECT}
+BINARY := ${PROJECT}${BIN_EXT}
OPENSSL_DIR := /usr
OBJECTS := src/cert.o \
@@ -47,15 +47,17 @@
CFLAGS := -Wall -std=c99
-# Check the platform
-ifeq (${PLAT},none)
- $(error "Error: Unknown platform. Please use PLAT=<platform name> to specify the platform")
-endif
-PLAT_MAKEFILE := platform.mk
-PLAT_INCLUDE := $(shell find ../../plat/ -wholename '*/${PLAT}/${PLAT_MAKEFILE}' | \
- sed 's/${PLAT_MAKEFILE}/include/')
+MAKE_HELPERS_DIRECTORY := ../../make_helpers/
+include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
+include ${MAKE_HELPERS_DIRECTORY}build_env.mk
+
+PLATFORM_ROOT := ../../plat/
+include ${MAKE_HELPERS_DIRECTORY}plat_helpers.mk
+
+PLAT_INCLUDE := $(wildcard ${PLAT_DIR}include)
+
ifeq ($(PLAT_INCLUDE),)
- $(error "Error: Invalid platform '${PLAT}'")
+ $(error "Error: Invalid platform '${PLAT}' has no include directory.")
endif
ifeq (${DEBUG},1)
@@ -76,9 +78,8 @@
LIB := -lssl -lcrypto
CC := gcc
-RM := rm -rf
-.PHONY: all clean
+.PHONY: all clean realclean
all: clean ${BINARY}
@@ -94,7 +95,8 @@
${Q}${CC} -c ${CFLAGS} ${INC_DIR} $< -o $@
clean:
- ${Q}${RM} -f src/build_msg.o ${OBJECTS}
+ $(call SHELL_DELETE_ALL, src/build_msg.o ${OBJECTS})
realclean: clean
- ${Q}${RM} -f ${BINARY}
+ $(call SHELL_DELETE, ${BINARY})
+
diff --git a/tools/cert_create/include/ext.h b/tools/cert_create/include/ext.h
index 82a4bcb..95bde6c 100644
--- a/tools/cert_create/include/ext.h
+++ b/tools/cert_create/include/ext.h
@@ -35,12 +35,18 @@
#include <openssl/x509v3.h>
/* Extension types supported */
-enum {
+enum ext_type_e {
EXT_TYPE_NVCOUNTER,
EXT_TYPE_PKEY,
EXT_TYPE_HASH
};
+/* NV-Counter types */
+enum nvctr_type_e {
+ NVCTR_TYPE_TFW,
+ NVCTR_TYPE_NTFW
+};
+
/*
* This structure contains the relevant information to create the extensions
* to be included in the certificates. This extensions will be used to
@@ -50,20 +56,21 @@
const char *oid; /* OID of the extension */
const char *sn; /* Short name */
const char *ln; /* Long description */
+ const char *opt; /* Command line option to specify data */
const char *help_msg; /* Help message */
+ const char *arg; /* Argument passed from command line */
int asn1_type; /* OpenSSL ASN1 type of the extension data.
* Supported types are:
* - V_ASN1_INTEGER
* - V_ASN1_OCTET_STRING
*/
- int type;
- const char *opt; /* Command line option to specify data */
- /* Extension data (depends on extension type) */
+ int type; /* See ext_type_e */
+
+ /* Extension attributes (depends on extension type) */
union {
- const char *fn; /* File with extension data */
- int nvcounter; /* Non volatile counter */
- int key; /* Public key */
- } data;
+ int nvctr_type; /* See nvctr_type_e */
+ int key; /* Index into array of registered public keys */
+ } attr;
int alias; /* In case OpenSSL provides an standard
* extension of the same type, add the new
diff --git a/tools/cert_create/src/main.c b/tools/cert_create/src/main.c
index 3d2b4ba..c87d988 100644
--- a/tools/cert_create/src/main.c
+++ b/tools/cert_create/src/main.c
@@ -196,9 +196,17 @@
for (j = 0; j < cert->num_ext; j++) {
ext = &extensions[cert->ext[j]];
switch (ext->type) {
+ case EXT_TYPE_NVCOUNTER:
+ /* Counter value must be specified */
+ if ((!ext->optional) && (ext->arg == NULL)) {
+ ERROR("Value for '%s' not specified\n",
+ ext->ln);
+ exit(1);
+ }
+ break;
case EXT_TYPE_PKEY:
/* Key filename must be specified */
- key = &keys[ext->data.key];
+ key = &keys[ext->attr.key];
if (!new_keys && key->fn == NULL) {
ERROR("Key '%s' required by '%s' not "
"specified\n", key->desc,
@@ -211,15 +219,15 @@
* Binary image must be specified
* unless it is explicitly made optional.
*/
- if ((!ext->optional) && (ext->data.fn == NULL)) {
+ if ((!ext->optional) && (ext->arg == NULL)) {
ERROR("Image for '%s' not specified\n",
ext->ln);
exit(1);
}
break;
default:
- ERROR("Unknown extension type in '%s'\n",
- ext->ln);
+ ERROR("Unknown extension type '%d' in '%s'\n",
+ ext->type, ext->ln);
exit(1);
break;
}
@@ -259,7 +267,7 @@
key_t *key = NULL;
cert_t *cert = NULL;
FILE *file = NULL;
- int i, j, ext_nid;
+ int i, j, ext_nid, nvctr;
int c, opt_idx = 0;
const struct option *cmd_opt;
const char *cur_opt;
@@ -331,7 +339,7 @@
case CMD_OPT_EXT:
cur_opt = cmd_opt_get_name(opt_idx);
ext = ext_get_by_opt(cur_opt);
- ext->data.fn = strdup(optarg);
+ ext->arg = strdup(optarg);
break;
case CMD_OPT_KEY:
cur_opt = cmd_opt_get_name(opt_idx);
@@ -420,11 +428,12 @@
*/
switch (ext->type) {
case EXT_TYPE_NVCOUNTER:
+ nvctr = atoi(ext->arg);
CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid,
- EXT_CRIT, ext->data.nvcounter));
+ EXT_CRIT, nvctr));
break;
case EXT_TYPE_HASH:
- if (ext->data.fn == NULL) {
+ if (ext->arg == NULL) {
if (ext->optional) {
/* Include a hash filled with zeros */
memset(md, 0x0, SHA256_DIGEST_LENGTH);
@@ -434,9 +443,9 @@
}
} else {
/* Calculate the hash of the file */
- if (!sha_file(ext->data.fn, md)) {
+ if (!sha_file(ext->arg, md)) {
ERROR("Cannot calculate hash of %s\n",
- ext->data.fn);
+ ext->arg);
exit(1);
}
}
@@ -446,11 +455,11 @@
break;
case EXT_TYPE_PKEY:
CHECK_NULL(cert_ext, ext_new_key(ext_nid,
- EXT_CRIT, keys[ext->data.key].key));
+ EXT_CRIT, keys[ext->attr.key].key));
break;
default:
- ERROR("Unknown extension type in %s\n",
- cert->cn);
+ ERROR("Unknown extension type '%d' in %s\n",
+ ext->type, cert->cn);
exit(1);
}
diff --git a/tools/cert_create/src/tbbr/tbb_cert.c b/tools/cert_create/src/tbbr/tbb_cert.c
index 7a50ab3..8f7feb5 100644
--- a/tools/cert_create/src/tbbr/tbb_cert.c
+++ b/tools/cert_create/src/tbbr/tbb_cert.c
@@ -49,9 +49,10 @@
.key = ROT_KEY,
.issuer = TRUSTED_BOOT_FW_CERT,
.ext = {
+ TRUSTED_FW_NVCOUNTER_EXT,
TRUSTED_BOOT_FW_HASH_EXT
},
- .num_ext = 1
+ .num_ext = 2
},
[TRUSTED_KEY_CERT] = {
.id = TRUSTED_KEY_CERT,
@@ -62,10 +63,11 @@
.key = ROT_KEY,
.issuer = TRUSTED_KEY_CERT,
.ext = {
+ TRUSTED_FW_NVCOUNTER_EXT,
TRUSTED_WORLD_PK_EXT,
NON_TRUSTED_WORLD_PK_EXT
},
- .num_ext = 2
+ .num_ext = 3
},
[SCP_FW_KEY_CERT] = {
.id = SCP_FW_KEY_CERT,
@@ -76,9 +78,10 @@
.key = TRUSTED_WORLD_KEY,
.issuer = SCP_FW_KEY_CERT,
.ext = {
+ TRUSTED_FW_NVCOUNTER_EXT,
SCP_FW_CONTENT_CERT_PK_EXT
},
- .num_ext = 1
+ .num_ext = 2
},
[SCP_FW_CONTENT_CERT] = {
.id = SCP_FW_CONTENT_CERT,
@@ -89,9 +92,10 @@
.key = SCP_FW_CONTENT_CERT_KEY,
.issuer = SCP_FW_CONTENT_CERT,
.ext = {
+ TRUSTED_FW_NVCOUNTER_EXT,
SCP_FW_HASH_EXT
},
- .num_ext = 1
+ .num_ext = 2
},
[SOC_FW_KEY_CERT] = {
.id = SOC_FW_KEY_CERT,
@@ -102,9 +106,10 @@
.key = TRUSTED_WORLD_KEY,
.issuer = SOC_FW_KEY_CERT,
.ext = {
+ TRUSTED_FW_NVCOUNTER_EXT,
SOC_FW_CONTENT_CERT_PK_EXT
},
- .num_ext = 1
+ .num_ext = 2
},
[SOC_FW_CONTENT_CERT] = {
.id = SOC_FW_CONTENT_CERT,
@@ -115,9 +120,10 @@
.key = SOC_FW_CONTENT_CERT_KEY,
.issuer = SOC_FW_CONTENT_CERT,
.ext = {
+ TRUSTED_FW_NVCOUNTER_EXT,
SOC_AP_FW_HASH_EXT
},
- .num_ext = 1
+ .num_ext = 2
},
[TRUSTED_OS_FW_KEY_CERT] = {
.id = TRUSTED_OS_FW_KEY_CERT,
@@ -128,9 +134,10 @@
.key = TRUSTED_WORLD_KEY,
.issuer = TRUSTED_OS_FW_KEY_CERT,
.ext = {
+ TRUSTED_FW_NVCOUNTER_EXT,
TRUSTED_OS_FW_CONTENT_CERT_PK_EXT
},
- .num_ext = 1
+ .num_ext = 2
},
[TRUSTED_OS_FW_CONTENT_CERT] = {
.id = TRUSTED_OS_FW_CONTENT_CERT,
@@ -141,9 +148,10 @@
.key = TRUSTED_OS_FW_CONTENT_CERT_KEY,
.issuer = TRUSTED_OS_FW_CONTENT_CERT,
.ext = {
+ TRUSTED_FW_NVCOUNTER_EXT,
TRUSTED_OS_FW_HASH_EXT
},
- .num_ext = 1
+ .num_ext = 2
},
[NON_TRUSTED_FW_KEY_CERT] = {
.id = NON_TRUSTED_FW_KEY_CERT,
@@ -154,9 +162,10 @@
.key = NON_TRUSTED_WORLD_KEY,
.issuer = NON_TRUSTED_FW_KEY_CERT,
.ext = {
+ NON_TRUSTED_FW_NVCOUNTER_EXT,
NON_TRUSTED_FW_CONTENT_CERT_PK_EXT
},
- .num_ext = 1
+ .num_ext = 2
},
[NON_TRUSTED_FW_CONTENT_CERT] = {
.id = NON_TRUSTED_FW_CONTENT_CERT,
@@ -167,9 +176,10 @@
.key = NON_TRUSTED_FW_CONTENT_CERT_KEY,
.issuer = NON_TRUSTED_FW_CONTENT_CERT,
.ext = {
+ NON_TRUSTED_FW_NVCOUNTER_EXT,
NON_TRUSTED_WORLD_BOOTLOADER_HASH_EXT
},
- .num_ext = 1
+ .num_ext = 2
},
[FWU_CERT] = {
.id = FWU_CERT,
diff --git a/tools/cert_create/src/tbbr/tbb_ext.c b/tools/cert_create/src/tbbr/tbb_ext.c
index 8bcb070..5304bd5 100644
--- a/tools/cert_create/src/tbbr/tbb_ext.c
+++ b/tools/cert_create/src/tbbr/tbb_ext.c
@@ -44,19 +44,23 @@
static ext_t tbb_ext[] = {
[TRUSTED_FW_NVCOUNTER_EXT] = {
.oid = TRUSTED_FW_NVCOUNTER_OID,
+ .opt = "tfw-nvctr",
+ .help_msg = "Trusted Firmware Non-Volatile counter value",
.sn = "TrustedWorldNVCounter",
.ln = "Trusted World Non-Volatile counter",
.asn1_type = V_ASN1_INTEGER,
.type = EXT_TYPE_NVCOUNTER,
- .data.nvcounter = TRUSTED_WORLD_NVCTR_VALUE
+ .attr.nvctr_type = NVCTR_TYPE_TFW
},
[NON_TRUSTED_FW_NVCOUNTER_EXT] = {
.oid = NON_TRUSTED_FW_NVCOUNTER_OID,
+ .opt = "ntfw-nvctr",
+ .help_msg = "Non-Trusted Firmware Non-Volatile counter value",
.sn = "NormalWorldNVCounter",
- .ln = "Normal World Non-Volatile counter",
+ .ln = "Non-Trusted Firmware Non-Volatile counter",
.asn1_type = V_ASN1_INTEGER,
.type = EXT_TYPE_NVCOUNTER,
- .data.nvcounter = NORMAL_WORLD_NVCTR_VALUE
+ .attr.nvctr_type = NVCTR_TYPE_NTFW
},
[TRUSTED_BOOT_FW_HASH_EXT] = {
.oid = TRUSTED_BOOT_FW_HASH_OID,
@@ -73,7 +77,7 @@
.ln = "Trusted World Public Key",
.asn1_type = V_ASN1_OCTET_STRING,
.type = EXT_TYPE_PKEY,
- .data.key = TRUSTED_WORLD_KEY
+ .attr.key = TRUSTED_WORLD_KEY
},
[NON_TRUSTED_WORLD_PK_EXT] = {
.oid = NON_TRUSTED_WORLD_PK_OID,
@@ -81,7 +85,7 @@
.ln = "Non-Trusted World Public Key",
.asn1_type = V_ASN1_OCTET_STRING,
.type = EXT_TYPE_PKEY,
- .data.key = NON_TRUSTED_WORLD_KEY
+ .attr.key = NON_TRUSTED_WORLD_KEY
},
[SCP_FW_CONTENT_CERT_PK_EXT] = {
.oid = SCP_FW_CONTENT_CERT_PK_OID,
@@ -89,7 +93,7 @@
.ln = "SCP Firmware content certificate public key",
.asn1_type = V_ASN1_OCTET_STRING,
.type = EXT_TYPE_PKEY,
- .data.key = SCP_FW_CONTENT_CERT_KEY
+ .attr.key = SCP_FW_CONTENT_CERT_KEY
},
[SCP_FW_HASH_EXT] = {
.oid = SCP_FW_HASH_OID,
@@ -106,7 +110,7 @@
.ln = "SoC Firmware content certificate public key",
.asn1_type = V_ASN1_OCTET_STRING,
.type = EXT_TYPE_PKEY,
- .data.key = SOC_FW_CONTENT_CERT_KEY
+ .attr.key = SOC_FW_CONTENT_CERT_KEY
},
[SOC_AP_FW_HASH_EXT] = {
.oid = SOC_AP_FW_HASH_OID,
@@ -123,7 +127,7 @@
.ln = "Trusted OS Firmware content certificate public key",
.asn1_type = V_ASN1_OCTET_STRING,
.type = EXT_TYPE_PKEY,
- .data.key = TRUSTED_OS_FW_CONTENT_CERT_KEY
+ .attr.key = TRUSTED_OS_FW_CONTENT_CERT_KEY
},
[TRUSTED_OS_FW_HASH_EXT] = {
.oid = TRUSTED_OS_FW_HASH_OID,
@@ -140,7 +144,7 @@
.ln = "Non-Trusted Firmware content certificate public key",
.asn1_type = V_ASN1_OCTET_STRING,
.type = EXT_TYPE_PKEY,
- .data.key = NON_TRUSTED_FW_CONTENT_CERT_KEY
+ .attr.key = NON_TRUSTED_FW_CONTENT_CERT_KEY
},
[NON_TRUSTED_WORLD_BOOTLOADER_HASH_EXT] = {
.oid = NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID,
diff --git a/tools/fip_create/Makefile b/tools/fip_create/Makefile
index c72bae5..2e367c2 100644
--- a/tools/fip_create/Makefile
+++ b/tools/fip_create/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
@@ -28,38 +28,56 @@
# POSSIBILITY OF SUCH DAMAGE.
#
-PROJECT = fip_create
-OBJECTS = fip_create.o
+MAKE_HELPERS_DIRECTORY := ../../make_helpers/
+include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
+include ${MAKE_HELPERS_DIRECTORY}build_env.mk
-CFLAGS = -Wall -Werror -pedantic -std=c99
+PROJECT := fip_create${BIN_EXT}
+OBJECTS := fip_create.o
+COPIED_H_FILES := uuid.h firmware_image_package.h
+
+CFLAGS := -Wall -Werror -pedantic -std=c99
ifeq (${DEBUG},1)
CFLAGS += -g -O0 -DDEBUG
else
CFLAGS += -O2
endif
-# Make soft links and include from local directory otherwise wrong headers
-# could get pulled in from firmware tree.
-INCLUDE_PATHS = -I.
+# Only include from local directory (see comment below).
+INCLUDE_PATHS := -I.
CC := gcc
-RM := rm -rf
-.PHONY: all clean
+.PHONY: all clean distclean
all: ${PROJECT}
${PROJECT}: ${OBJECTS} Makefile
@echo " LD $@"
${Q}${CC} ${OBJECTS} -o $@
- @echo
+ @${ECHO_BLANK_LINE}
@echo "Built $@ successfully"
- @echo
+ @${ECHO_BLANK_LINE}
-%.o: %.c %.h Makefile
+%.o: %.c %.h ${COPIED_H_FILES} Makefile
@echo " CC $<"
${Q}${CC} -c ${CFLAGS} ${INCLUDE_PATHS} $< -o $@
+#
+# Copy required library headers to a local directory so they can be included
+# by this project without adding the library directories to the system include
+# path. This avoids conflicts with definitions in the compiler standard
+# include path.
+#
+uuid.h : ../../include/stdlib/sys/uuid.h
+ $(call SHELL_COPY,$<,$@)
+
+firmware_image_package.h : ../../include/common/firmware_image_package.h
+ $(call SHELL_COPY,$<,$@)
+
clean:
- ${Q}${RM} ${PROJECT}
- ${Q}${RM} ${OBJECTS}
+ $(call SHELL_DELETE_ALL, ${PROJECT} ${OBJECTS})
+
+distclean: clean
+ $(call SHELL_DELETE_ALL, ${COPIED_H_FILES})
+
diff --git a/tools/fip_create/firmware_image_package.h b/tools/fip_create/firmware_image_package.h
deleted file mode 120000
index cc61903..0000000
--- a/tools/fip_create/firmware_image_package.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/common/firmware_image_package.h
\ No newline at end of file
diff --git a/tools/fip_create/uuid.h b/tools/fip_create/uuid.h
deleted file mode 120000
index c77762f..0000000
--- a/tools/fip_create/uuid.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/stdlib/sys/uuid.h
\ No newline at end of file