Merge pull request #583 from mtk09422/fix-build-error
mt8173: fix spm driver build errors
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 d7a7a36..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
@@ -234,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
@@ -260,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)
@@ -285,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
@@ -386,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}
################################################################################
@@ -545,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
@@ -573,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}
@@ -621,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/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/tf_printf.c b/common/tf_printf.c
index c1d4188..9a7667a 100644
--- a/common/tf_printf.c
+++ b/common/tf_printf.c
@@ -69,6 +69,7 @@
* %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.
*******************************************************************/
@@ -124,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/porting-guide.md b/docs/porting-guide.md
index 944c798..3b6e242 100644
--- a/docs/porting-guide.md
+++ b/docs/porting-guide.md
@@ -633,6 +633,35 @@
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
---------------------------------
@@ -1259,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
diff --git a/docs/user-guide.md b/docs/user-guide.md
index 37e2034..8d7376d 100644
--- a/docs/user-guide.md
+++ b/docs/user-guide.md
@@ -42,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
---------
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/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/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index e9eebaa..2fe0a69 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -130,7 +130,9 @@
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);
diff --git a/include/plat/arm/css/common/css_def.h b/include/plat/arm/css/common/css_def.h
index f92126b..636daf2 100644
--- a/include/plat/arm/css/common/css_def.h
+++ b/include/plat/arm/css/common/css_def.h
@@ -143,7 +143,7 @@
#define PLAT_ARM_NS_IMAGE_OFFSET 0xE0000000
/* TZC related constants */
-#define PLAT_ARM_TZC_FILTERS REG_ATTR_FILTER_BIT_ALL
+#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/platform.h b/include/plat/common/platform.h
index 5c61f38..5857501 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -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);
@@ -249,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/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 b22eaf9..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))))
@@ -310,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 $$@"
+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)
@@ -337,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 da6beec..6ddc0c9 100644
--- a/plat/arm/board/common/board_common.mk
+++ b/plat/arm/board/common/board_common.mk
@@ -51,6 +51,11 @@
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
diff --git a/plat/arm/board/fvp/fvp_def.h b/plat/arm/board/fvp/fvp_def.h
index dbca280..b0f07ef 100644
--- a/plat/arm/board/fvp/fvp_def.h
+++ b/plat/arm/board/fvp/fvp_def.h
@@ -69,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_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/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index 3428cb5..ca8e35e 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -113,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) | \
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index aad2e2e..afd939d 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -65,7 +65,7 @@
FVP_INTERCONNECT_SOURCES := drivers/arm/cci/cci.c \
plat/arm/common/arm_cci.c
-FVP_SECURITY_SOURCES := drivers/arm/tzc400/tzc400.c \
+FVP_SECURITY_SOURCES := drivers/arm/tzc/tzc400.c \
plat/arm/board/fvp/fvp_security.c \
plat/arm/common/arm_tzc400.c
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/platform.mk b/plat/arm/board/juno/platform.mk
index 0a2244d..4fda4ca 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -37,7 +37,7 @@
JUNO_INTERCONNECT_SOURCES := drivers/arm/cci/cci.c \
plat/arm/common/arm_cci.c
-JUNO_SECURITY_SOURCES := drivers/arm/tzc400/tzc400.c \
+JUNO_SECURITY_SOURCES := drivers/arm/tzc/tzc400.c \
plat/arm/board/juno/juno_security.c \
plat/arm/common/arm_tzc400.c
diff --git a/plat/arm/common/aarch64/arm_common.c b/plat/arm/common/aarch64/arm_common.c
index c84a65b..19a4931 100644
--- a/plat/arm/common/aarch64/arm_common.c
+++ b/plat/arm/common/aarch64/arm_common.c
@@ -93,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;
}
diff --git a/plat/arm/common/arm_tzc400.c b/plat/arm/common/arm_tzc400.c
index 8b46aae..3962940 100644
--- a/plat/arm/common/arm_tzc400.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_tzc_dmc500.c b/plat/arm/common/arm_tzc_dmc500.c
new file mode 100644
index 0000000..f0ed9a6
--- /dev/null
+++ b/plat/arm/common/arm_tzc_dmc500.c
@@ -0,0 +1,100 @@
+/*
+ * 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 <assert.h>
+#include <debug.h>
+#include <platform_def.h>
+#include <tzc_dmc500.h>
+
+/*******************************************************************************
+ * 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_dmc500_setup(tzc_dmc500_driver_data_t *plat_driver_data)
+{
+ assert(plat_driver_data);
+
+ INFO("Configuring DMC-500 TZ Settings\n");
+
+ tzc_dmc500_driver_init(plat_driver_data);
+
+#ifndef EL3_PAYLOAD_BASE
+ /* Region 0 set to no access by default */
+ tzc_dmc500_configure_region0(TZC_REGION_S_NONE, 0);
+
+ /* Region 1 set to cover Secure part of DRAM */
+ 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.*/
+ 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_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_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_dmc500_set_action(TZC_ACTION_RV_LOWERR);
+
+ /*
+ * 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();
+
+ /*
+ * Wait for the flush to complete.
+ * TODO: Have a timeout for this loop
+ */
+ while (tzc_dmc500_verify_complete())
+ ;
+}
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/plat/rockchip/common/plat_delay_timer.c b/plat/rockchip/common/plat_delay_timer.c
new file mode 100644
index 0000000..797ce05
--- /dev/null
+++ b/plat/rockchip/common/plat_delay_timer.c
@@ -0,0 +1,54 @@
+/*
+ * 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 <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,
+};
+
+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/plat/rockchip/common/plat_topology.c b/plat/rockchip/common/plat_topology.c
new file mode 100644
index 0000000..911978a
--- /dev/null
+++ b/plat/rockchip/common/plat_topology.c
@@ -0,0 +1,55 @@
+/*
+ * 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 <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;
+
+ return ((cluster_id * PLATFORM_CLUSTER0_CORE_COUNT) + cpu_id);
+}
diff --git a/plat/rockchip/common/pmusram/pmu_sram.c b/plat/rockchip/common/pmusram/pmu_sram.c
new file mode 100644
index 0000000..bea4875
--- /dev/null
+++ b/plat/rockchip/common/pmusram/pmu_sram.c
@@ -0,0 +1,38 @@
+/*
+ * 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 <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;
+
+ 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/fip_create.c b/tools/fip_create/fip_create.c
index 19afc74..7bce348 100644
--- a/tools/fip_create/fip_create.c
+++ b/tools/fip_create/fip_create.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:
@@ -40,12 +40,19 @@
/* Values returned by getopt() as part of the command line parsing */
#define OPT_TOC_ENTRY 0
-#define OPT_DUMP 1
-#define OPT_HELP 2
+#define OPT_DUMP 'd'
+#define OPT_HELP 'h'
+#define OPT_UNPACK 'u'
+#define OPT_FORCE 'f'
+#define OPT_STR "dfhu"
-file_info_t files[MAX_FILES];
-unsigned file_info_count = 0;
-uuid_t uuid_null = {0};
+static file_info_t files[MAX_FILES];
+static unsigned file_info_count;
+static uuid_t uuid_null = {0};
+static int do_dump;
+static int do_pack;
+static int do_unpack;
+static int do_force;
/*
* TODO: Add ability to specify and flag different file types.
@@ -118,12 +125,15 @@
{
entry_lookup_list_t *entry = toc_entry_lookup_list;
- printf("Usage: fip_create [options] FIP_FILENAME\n\n");
- printf("\tThis tool is used to create a Firmware Image Package.\n\n");
+ printf("\nThis tool is used to create a Firmware Image Package.\n\n");
+ printf("Usage:\n");
+ printf("\tfip_create [options] FIP_FILENAME\n\n");
printf("Options:\n");
- printf("\t--help: Print this help message and exit\n");
- printf("\t--dump: Print contents of FIP\n\n");
- printf("\tComponents that can be added/updated:\n");
+ printf("\t-h,--help: Print this help message and exit\n");
+ printf("\t-d,--dump: Print contents of FIP after update\n");
+ printf("\t-u,--unpack: Unpack images from an existing FIP\n");
+ printf("\t-f,--force: Overwrite existing files when unpacking images\n\n");
+ printf("Components that can be added/updated:\n");
for (; entry->command_line_name != NULL; entry++) {
printf("\t--%s%s\t\t%s",
entry->command_line_name,
@@ -131,6 +141,7 @@
entry->name);
printf("\n");
}
+ printf("\n");
}
@@ -371,6 +382,109 @@
}
+/*
+ * Unpack all images from an existing FIP
+ *
+ * Images will be unpacked into the working directory using filenames as
+ * specified by the corresponding command line option plus the 'bin' extension.
+ * For example, the image specified by the --soc-fw option will be unpacked as
+ * 'soc-fw.bin'
+ */
+static int unpack_images(void)
+{
+ FILE *stream;
+ size_t bytes_written;
+ file_info_t *file_info;
+ char *filename[MAX_FILES];
+ int status, ret = 0;
+ unsigned int i, idx, num_img;
+ struct stat st;
+ size_t len;
+
+ /* Make the output filenames */
+ for (idx = 0; idx < file_info_count; idx++) {
+ filename[idx] = NULL;
+ file_info = &files[idx];
+ if (file_info->image_buffer == NULL) {
+ continue;
+ }
+ len = strlen(file_info->entry->command_line_name);
+ filename[idx] = malloc(len + 5); /* ".bin" + '\0' */
+ if (filename[idx] == NULL) {
+ printf("ERROR: out of memory\n");
+ for (i = 0; i < idx; i++) {
+ free(filename[i]);
+ }
+ return ENOMEM;
+ }
+ strcpy(filename[idx], file_info->entry->command_line_name);
+ strcat(filename[idx], ".bin");
+ }
+
+
+ /* Check if output files already exist in the filesystem. We perform
+ * this check before any other action, so if any of the files
+ * exists, nothing is unpacked. If force overwrite is enabled, we skip
+ * this check */
+ if (!do_force) {
+ for (idx = 0; idx < file_info_count; idx++) {
+ file_info = &files[idx];
+ if (file_info->image_buffer == NULL) {
+ continue;
+ }
+ status = stat(filename[idx], &st);
+ if (!status) {
+ printf("File '%s' exists. Use --force to overwrite.\n",
+ filename[idx]);
+ printf("Process aborted.\n");
+ ret = EEXIST;
+ goto unpack_images_free;
+ }
+ }
+ }
+
+ printf("Unpacking images...\n");
+
+ /* Write the images to files */
+ num_img = 0;
+ for (idx = 0; idx < file_info_count; idx++) {
+ file_info = &files[idx];
+ if (file_info->image_buffer == NULL) {
+ continue;
+ }
+ /* Unpack the image to a file */
+ stream = fopen(filename[idx], "w");
+ if (!stream) {
+ printf("ERROR: cannot open '%s' for writing\n",
+ filename[idx]);
+ ret = EIO;
+ goto unpack_images_free;
+ }
+ bytes_written = fwrite(file_info->image_buffer, sizeof(uint8_t),
+ file_info->size, stream);
+ fclose(stream);
+
+ if (bytes_written != file_info->size) {
+ printf("ERROR: Incorrect write for file \"%s\": Size=%u,"
+ "Written=%lu bytes.\n", filename[idx], file_info->size,
+ bytes_written);
+ ret = EIO;
+ goto unpack_images_free;
+ }
+ num_img++;
+ }
+
+ printf("Done. %u images unpacked\n", num_img);
+
+unpack_images_free:
+ for (idx = 0; idx < file_info_count; idx++) {
+ free(filename[idx]);
+ }
+
+ return ret;
+}
+
+
static void dump_toc(void)
{
unsigned int index = 0;
@@ -528,7 +642,7 @@
*/
optind = 1;
while (1) {
- c = getopt_long(argc, argv, "", options, NULL);
+ c = getopt_long(argc, argv, OPT_STR, options, NULL);
if (c == -1)
break;
@@ -549,19 +663,17 @@
/* Work through command-line options */
-static int parse_cmdline(int argc, char **argv, struct option *options,
- int *do_pack)
+static int parse_cmdline(int argc, char **argv, struct option *options)
{
int c;
int status = 0;
int option_index = 0;
entry_lookup_list_t *lookup_entry;
- int do_dump = 0;
/* restart parse to process all options. starts at 1. */
optind = 1;
while (1) {
- c = getopt_long(argc, argv, "", options, &option_index);
+ c = getopt_long(argc, argv, OPT_STR, options, &option_index);
if (c == -1)
break;
@@ -578,7 +690,7 @@
return status;
} else {
/* Update package */
- *do_pack = 1;
+ do_pack = 1;
}
}
}
@@ -586,24 +698,26 @@
case OPT_DUMP:
do_dump = 1;
- continue;
+ break;
case OPT_HELP:
print_usage();
exit(0);
+ case OPT_UNPACK:
+ do_unpack = 1;
+ break;
+
+ case OPT_FORCE:
+ do_force = 1;
+ break;
+
default:
/* Unrecognised options are caught in get_filename() */
break;
}
}
-
- /* Do not dump toc if we have an error as it could hide the error */
- if ((status == 0) && (do_dump)) {
- dump_toc();
- }
-
return status;
}
@@ -613,17 +727,17 @@
int i;
int status;
char *fip_filename;
- int do_pack = 0;
+ struct stat st;
/* Clear file list table. */
memset(files, 0, sizeof(files));
/* Initialise for getopt_long().
* Use image table as defined at top of file to get options.
- * Add 'dump' option, 'help' option and end marker.
+ * Add common options and end marker.
*/
static struct option long_options[(sizeof(toc_entry_lookup_list)/
- sizeof(entry_lookup_list_t)) + 2];
+ sizeof(entry_lookup_list_t)) + 4];
for (i = 0;
/* -1 because we dont want to process end marker in toc table */
@@ -648,6 +762,18 @@
long_options[i].flag = 0;
long_options[i].val = OPT_HELP;
+ /* Add '--unpack' option */
+ long_options[++i].name = "unpack";
+ long_options[i].has_arg = 0;
+ long_options[i].flag = 0;
+ long_options[i].val = OPT_UNPACK;
+
+ /* Add '--force' option */
+ long_options[++i].name = "force";
+ long_options[i].has_arg = 0;
+ long_options[i].flag = 0;
+ long_options[i].val = OPT_FORCE;
+
/* Zero the last entry (required) */
long_options[++i].name = 0;
long_options[i].has_arg = 0;
@@ -677,7 +803,7 @@
}
/* Work through provided program arguments and perform actions */
- status = parse_cmdline(argc, argv, long_options, &do_pack);
+ status = parse_cmdline(argc, argv, long_options);
if (status != 0) {
return status;
};
@@ -688,10 +814,28 @@
return 0;
}
- /* Processed all command line options. Create/update the package if
- * required.
- */
- if (do_pack) {
+ /* Unpack images from FIP always takes precedence over packaging. In
+ * the future, there will be different commands for each action and
+ * only one will be specified in the command line */
+ if (do_unpack) {
+ status = stat(fip_filename, &st);
+ if (status != 0) {
+ printf("ERROR: cannot open %s\n", fip_filename);
+ return status;
+ }
+ /* Warning if user has specified images */
+ if (do_pack) {
+ printf("WARNING: Unpack option specified. Input images "
+ "will be ignored.\n");
+ }
+ status = unpack_images();
+ if (status != 0) {
+ printf("ERROR: failed to unpack package (status = %d).\n",
+ status);
+ return status;
+ }
+ } else if (do_pack) {
+ /* Create/update FIP */
status = pack_images(fip_filename);
if (status != 0) {
printf("Failed to create package (status = %d).\n",
@@ -699,5 +843,10 @@
}
}
+ /* Do not dump toc if we have an error as it could hide the error */
+ if ((status == 0) && (do_dump)) {
+ dump_toc();
+ }
+
return status;
}
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