Merge pull request #579 from ashutoshksingh/master

pass r0-r6 as part of smc param
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 6d17cfd..c5ec6d1 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
@@ -110,10 +112,11 @@
 				--ignore GIT_COMMIT_ID
 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))
+# Do not check the coding style on C library files or documentation files
+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 docs %.md, $(wildcard *)))
+CHECK_PATHS		:=	${ROOT_DIRS_TO_CHECK} ${INCLUDE_DIRS_TO_CHECK} ${LIB_DIRS_TO_CHECK}
 
 
 ################################################################################
@@ -122,10 +125,10 @@
 
 # Verbose flag
 ifeq (${V},0)
-        Q=@
+        Q:=@
         CHECKCODE_ARGS	+=	--no-summary --terse
 else
-        Q=
+        Q:=
 endif
 export Q
 
@@ -196,7 +199,6 @@
 				common/aarch64/debug.S			\
 				lib/aarch64/cache_helpers.S		\
 				lib/aarch64/misc_helpers.S		\
-				lib/aarch64/xlat_helpers.c		\
 				lib/stdlib/abort.c			\
 				lib/stdlib/assert.c			\
 				lib/stdlib/exit.c			\
@@ -235,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
@@ -261,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)
@@ -286,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
@@ -317,9 +306,9 @@
 ################################################################################
 
 ifdef EL3_PAYLOAD_BASE
-        ifdef BL33_BASE
-                $(warning "BL33_BASE and EL3_PAYLOAD_BASE are incompatible \
-                build options. EL3_PAYLOAD_BASE has priority.")
+        ifdef PRELOADED_BL33_BASE
+                $(warning "PRELOADED_BL33_BASE and EL3_PAYLOAD_BASE are \
+                incompatible build options. EL3_PAYLOAD_BASE has priority.")
         endif
 endif
 
@@ -328,9 +317,10 @@
                 $(warning "BL33 image is not needed when option \
                 BL33_PAYLOAD_BASE is used and won't be added to the FIP file.")
         endif
-        ifdef BL33_BASE
-                $(warning "BL33 image is not needed when option BL33_BASE is \
-                used and won't be added to the FIP file.")
+        ifdef PRELOADED_BL33_BASE
+                $(warning "BL33 image is not needed when option \
+                PRELOADED_BL33_BASE is used and won't be added to the FIP \
+                file.")
         endif
 endif
 
@@ -353,7 +343,7 @@
                 # in the FIP file.
                 NEED_BL33		:=	no
         else
-                ifdef BL33_BASE
+                ifdef PRELOADED_BL33_BASE
                         # If booting a BL33 preloaded image there is no need of
                         # another one in the FIP file.
                         NEED_BL33		:=	no
@@ -387,11 +377,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}
 
 
 ################################################################################
@@ -425,6 +415,7 @@
 ################################################################################
 
 $(eval $(call add_define,PLAT_${PLAT}))
+$(eval $(call add_define,SPD_${SPD}))
 $(eval $(call add_define,NS_TIMER_SWITCH))
 $(eval $(call add_define,RESET_TO_BL31))
 $(eval $(call add_define,CTX_INCLUDE_FPREGS))
@@ -445,10 +436,10 @@
 ifdef EL3_PAYLOAD_BASE
         $(eval $(call add_define,EL3_PAYLOAD_BASE))
 else
-        # Define the BL33_BASE flag only if it is provided and EL3_PAYLOAD_BASE
-        # is not defined, as it has priority.
-        ifdef BL33_BASE
-                $(eval $(call add_define,BL33_BASE))
+        # Define the PRELOADED_BL33_BASE flag only if it is provided and
+        # EL3_PAYLOAD_BASE is not defined, as it has priority.
+        ifdef PRELOADED_BL33_BASE
+                $(eval $(call add_define,PRELOADED_BL33_BASE))
         endif
 endif
 
@@ -546,14 +537,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
 
@@ -574,24 +565,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}
@@ -622,7 +613,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/acknowledgements.md b/acknowledgements.md
index 3ffefc7..2f6309e 100644
--- a/acknowledgements.md
+++ b/acknowledgements.md
@@ -7,5 +7,7 @@
 
 NVIDIA Corporation
 
+Xilinx, Inc.
+
 Individuals
 -----------
diff --git a/bl1/aarch64/bl1_arch_setup.c b/bl1/aarch64/bl1_arch_setup.c
index 6a3f062..61c01e1 100644
--- a/bl1/aarch64/bl1_arch_setup.c
+++ b/bl1/aarch64/bl1_arch_setup.c
@@ -38,7 +38,7 @@
 void bl1_arch_setup(void)
 {
 	/* Set the next EL to be AArch64 */
-	write_scr_el3(SCR_RES1_BITS | SCR_RW_BIT);
+	write_scr_el3(read_scr_el3() | SCR_RW_BIT);
 }
 
 /*******************************************************************************
diff --git a/bl2/bl2_main.c b/bl2/bl2_main.c
index 73781dd..c8fd683 100644
--- a/bl2/bl2_main.c
+++ b/bl2/bl2_main.c
@@ -169,7 +169,7 @@
 	return e;
 }
 
-#ifndef BL33_BASE
+#ifndef PRELOADED_BL33_BASE
 /*******************************************************************************
  * Load the BL33 image.
  * The bl2_to_bl31_params param will be updated with the relevant BL33
@@ -200,7 +200,7 @@
 
 	return e;
 }
-#endif /* BL33_BASE */
+#endif /* PRELOADED_BL33_BASE */
 
 #endif /* EL3_PAYLOAD_BASE */
 
@@ -277,13 +277,13 @@
 		}
 	}
 
-#ifdef BL33_BASE
+#ifdef PRELOADED_BL33_BASE
 	/*
 	 * In this case, don't load the BL33 image as it's already loaded in
 	 * memory. Update BL33 entrypoint information.
 	 */
 	INFO("BL2: Populating the entrypoint info for the preloaded BL33\n");
-	bl2_to_bl31_params->bl33_ep_info->pc = BL33_BASE;
+	bl2_to_bl31_params->bl33_ep_info->pc = PRELOADED_BL33_BASE;
 	bl2_plat_set_bl33_ep_info(NULL, bl2_to_bl31_params->bl33_ep_info);
 #else
 	e = load_bl33(bl2_to_bl31_params);
@@ -291,7 +291,7 @@
 		ERROR("Failed to load BL33 (%i)\n", e);
 		plat_error_handler(e);
 	}
-#endif /* BL33_BASE */
+#endif /* PRELOADED_BL33_BASE */
 
 #endif /* EL3_PAYLOAD_BASE */
 
diff --git a/bl31/aarch64/bl31_arch_setup.c b/bl31/aarch64/bl31_arch_setup.c
index edf1018..0871b41 100644
--- a/bl31/aarch64/bl31_arch_setup.c
+++ b/bl31/aarch64/bl31_arch_setup.c
@@ -43,9 +43,6 @@
  ******************************************************************************/
 void bl31_arch_setup(void)
 {
-	/* Set the RES1 bits in the SCR_EL3 */
-	write_scr_el3(SCR_RES1_BITS);
-
 	/* Program the counter frequency */
 	write_cntfrq_el0(plat_get_syscnt_freq());
 
diff --git a/bl31/aarch64/crash_reporting.S b/bl31/aarch64/crash_reporting.S
index ff91572..b22ce71 100644
--- a/bl31/aarch64/crash_reporting.S
+++ b/bl31/aarch64/crash_reporting.S
@@ -70,7 +70,8 @@
 		"tpidrro_el0", "dacr32_el2", "ifsr32_el2", "par_el1",\
 		"mpidr_el1", "afsr0_el1", "afsr1_el1", "contextidr_el1",\
 		"vbar_el1", "cntp_ctl_el0", "cntp_cval_el0", "cntv_ctl_el0",\
-		"cntv_cval_el0", "cntkctl_el1", "fpexc32_el2", "sp_el0", ""
+		"cntv_cval_el0", "cntkctl_el1", "fpexc32_el2", "sp_el0",\
+		"isr_el1", ""
 
 panic_msg:
 	.asciz "PANIC in EL3 at x30 = 0x"
@@ -338,6 +339,7 @@
 	mrs	x8, cntkctl_el1
 	mrs	x9, fpexc32_el2
 	mrs	x10, sp_el0
+	mrs	x11, isr_el1
 	bl	str_in_crash_buf_print
 
 	/* Get the cpu specific registers to report */
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/context_mgmt.c b/common/context_mgmt.c
index 68ec894..586d42a 100644
--- a/common/context_mgmt.c
+++ b/common/context_mgmt.c
@@ -111,6 +111,11 @@
 	if (EP_GET_ST(ep->h.attr))
 		scr_el3 |= SCR_ST_BIT;
 
+#ifndef HANDLE_EA_EL3_FIRST
+	/* Explicitly stop to trap aborts from lower exception levels. */
+	scr_el3 &= ~SCR_EA_BIT;
+#endif
+
 #if IMAGE_BL31
 	/*
 	 * IRQ/FIQ bits only need setting if interrupt routing
diff --git a/common/tf_printf.c b/common/tf_printf.c
index c1d4188..ad0b90a 100644
--- a/common/tf_printf.c
+++ b/common/tf_printf.c
@@ -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:
@@ -34,7 +34,22 @@
 /***********************************************************
  * The tf_printf implementation for all BL stages
  ***********************************************************/
-static void unsigned_num_print(unsigned long int unum, unsigned int radix)
+
+#define get_num_va_args(args, lcount) \
+	(((lcount) > 1) ? va_arg(args, long long int) :	\
+	((lcount) ? va_arg(args, long int) : va_arg(args, int)))
+
+#define get_unum_va_args(args, lcount) \
+	(((lcount) > 1) ? va_arg(args, unsigned long long int) :	\
+	((lcount) ? va_arg(args, unsigned long int) : va_arg(args, unsigned int)))
+
+static void string_print(const char *str)
+{
+	while (*str)
+		putchar(*str++);
+}
+
+static void unsigned_num_print(unsigned long long int unum, unsigned int radix)
 {
 	/* Just need enough space to store 64 bit decimal integer */
 	unsigned char num_buf[20];
@@ -52,37 +67,34 @@
 		putchar(num_buf[i]);
 }
 
-static void string_print(const char *str)
-{
-	while (*str)
-		putchar(*str++);
-}
-
 /*******************************************************************
  * Reduced format print for Trusted firmware.
- * The following formats are supported by this print
- * %x - 32 bit hexadecimal format
- * %llx and %lx -64 bit hexadecimal format
+ * The following type specifiers are supported by this print
+ * %x - hexadecimal format
  * %s - string format
- * %d or %i - signed 32 bit decimal format
- * %u - unsigned 32 bit decimal format
- * %ld and %lld - signed 64 bit decimal format
- * %lu and %llu - unsigned 64 bit decimal format
+ * %d or %i - signed decimal format
+ * %u - unsigned decimal format
  * %p - pointer format
- * Exits on all other formats.
+ *
+ * The following length specifiers are supported by this print
+ * %l - long int (64-bit on AArch64)
+ * %ll - long long int (64-bit on AArch64)
+ * %z - size_t sized integer formats (64 bit on AArch64)
+ *
+ * The print exits on all other formats specifiers other than valid
+ * combinations of the above specifiers.
  *******************************************************************/
-
 void tf_printf(const char *fmt, ...)
 {
 	va_list args;
-	int bit64;
-	int64_t num;
-	uint64_t unum;
+	int l_count;
+	long long int num;
+	unsigned long long int unum;
 	char *str;
 
 	va_start(args, fmt);
 	while (*fmt) {
-		bit64 = 0;
+		l_count = 0;
 
 		if (*fmt == '%') {
 			fmt++;
@@ -91,16 +103,12 @@
 			switch (*fmt) {
 			case 'i': /* Fall through to next one */
 			case 'd':
-				if (bit64)
-					num = va_arg(args, int64_t);
-				else
-					num = va_arg(args, int32_t);
-
+				num = get_num_va_args(args, l_count);
 				if (num < 0) {
 					putchar('-');
-					unum = (unsigned long int)-num;
+					unum = (unsigned long long int)-num;
 				} else
-					unum = (unsigned long int)num;
+					unum = (unsigned long long int)num;
 
 				unsigned_num_print(unum, 10);
 				break;
@@ -109,31 +117,28 @@
 				string_print(str);
 				break;
 			case 'p':
-				unum = (uint64_t)va_arg(args, void *);
-
+				unum = (uintptr_t)va_arg(args, void *);
 				if (unum)
 					string_print("0x");
 
 				unsigned_num_print(unum, 16);
 				break;
 			case 'x':
-				if (bit64)
-					unum = va_arg(args, uint64_t);
-				else
-					unum = va_arg(args, uint32_t);
-
+				unum = get_unum_va_args(args, l_count);
 				unsigned_num_print(unum, 16);
 				break;
+			case 'z':
+				if (sizeof(size_t) == 8)
+					l_count = 2;
+
+				fmt++;
+				goto loop;
 			case 'l':
-				bit64 = 1;
+				l_count++;
 				fmt++;
 				goto loop;
 			case 'u':
-				if (bit64)
-					unum = va_arg(args, uint64_t);
-				else
-					unum = va_arg(args, uint32_t);
-
+				unum = get_unum_va_args(args, l_count);
 				unsigned_num_print(unum, 10);
 				break;
 			default:
diff --git a/docs/firmware-design.md b/docs/firmware-design.md
index 54c5068..87bdb88 100644
--- a/docs/firmware-design.md
+++ b/docs/firmware-design.md
@@ -174,8 +174,11 @@
         `SCTLR_EL3.A` and `SCTLR_EL3.SA` bits. Exception endianness is set to
         little-endian by clearing the `SCTLR_EL3.EE` bit.
 
-    -  `SCR_EL3`. The register width of the next lower exception level is set to
-        AArch64 by setting the `SCR.RW` bit.
+    -  `SCR_EL3`. The register width of the next lower exception level is set
+        to AArch64 by setting the `SCR.RW` bit. The `SCR.EA` bit is set to trap
+        both External Aborts and SError Interrupts in EL3. The `SCR.SIF` bit is
+        also set to disable instruction fetches from Non-secure memory when in
+        secure state.
 
     -   `CPTR_EL3`. Accesses to the `CPACR_EL1` register from EL1 or EL2, or the
         `CPTR_EL2` register from EL2 are configured to not trap to EL3 by
diff --git a/docs/plat/xilinx-zynqmp.md b/docs/plat/xilinx-zynqmp.md
new file mode 100644
index 0000000..997d9a9
--- /dev/null
+++ b/docs/plat/xilinx-zynqmp.md
@@ -0,0 +1,49 @@
+ARM Trusted Firmware for Xilinx Zynq UltraScale+ MPSoC
+================================
+
+ARM Trusted Firmware implements the EL3 firmware layer for Xilinx Zynq
+UltraScale + MPSoC.
+The platform only uses the runtime part of ATF as ZynqMP already has a
+BootROM (BL1) and FSBL (BL2).
+
+BL31 is ATF.  
+BL32 is an optional Secure Payload.  
+BL33 is the non-secure world software (U-Boot, Linux etc).  
+
+To build:
+```bash
+make ERROR_DEPRECATED=1 RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=zynqmp bl31
+```
+
+To build bl32 TSP you have to rebuild bl31 too:
+```bash
+make ERROR_DEPRECATED=1 RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=zynqmp SPD=tspd bl31 bl32
+```
+
+# ZynqMP platform specific build options
+*   `ZYNQMP_ATF_LOCATION`: Specifies the location of the bl31 binary. Options:
+    -   `tsram` : bl31 will be located in OCM (default)
+    -   `tdram` : bl31 will be located in DRAM (address: 0x30000000)
+
+*   `ZYNQMP_TSP_RAM_LOCATION`: Specifies the location of the bl32 binary and
+    secure payload dispatcher. Options:
+    -   `tsram` : bl32/spd will be located in OCM (default)
+    -   `tdram` : bl32/spd will be located in DRAM (address: 0x30000000)
+
+# Power Domain Tree
+The following power domain tree represents the power domain model used by the
+ATF for ZynqMP:
+```
+                +-+
+                |0|
+                +-+
+     +-------+---+---+-------+
+     |       |       |       |
+     |       |       |       |
+     v       v       v       v
+    +-+     +-+     +-+     +-+
+    |0|     |1|     |2|     |3|
+    +-+     +-+     +-+     +-+
+```
+The 4 leaf power domains represent the individual A53 cores, while resources
+common to the cluster are grouped in the power domain on the top.
diff --git a/docs/porting-guide.md b/docs/porting-guide.md
index f0adf57..5e14823 100644
--- a/docs/porting-guide.md
+++ b/docs/porting-guide.md
@@ -76,12 +76,12 @@
 A platform port must enable the Memory Management Unit (MMU) as well as the
 instruction and data caches for each BL stage. Setting up the translation
 tables is the responsibility of the platform port because memory maps differ
-across platforms. A memory translation library (see `lib/aarch64/xlat_helpers.c`
-and `lib/aarch64/xlat_tables.c`) is provided to help in this setup. Note that
-although this library supports non-identity mappings, this is intended only for
-re-mapping peripheral physical addresses and allows platforms with high I/O
-addresses to reduce their virtual address space. All other addresses
-corresponding to code and data must currently use an identity mapping.
+across platforms. A memory translation library (see `lib/aarch64/xlat_tables.c`)
+is provided to help in this setup. Note that although this library supports
+non-identity mappings, this is intended only for re-mapping peripheral physical
+addresses and allows platforms with high I/O addresses to reduce their virtual
+address space. All other addresses corresponding to code and data must currently
+use an identity mapping.
 
 In ARM standard platforms, each BL stage configures the MMU in the
 platform-specific architecture setup function, `blX_plat_arch_setup()`, and uses
@@ -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
 ---------------------------------
 
@@ -1242,8 +1271,8 @@
 validate whether the BL33 image can be loaded with in the given
 memory from the given base.
 
-This function isn't needed if either `BL33_BASE` or `EL3_PAYLOAD_BASE` build
-options are used.
+This function isn't needed if either `PRELOADED_BL33_BASE` or `EL3_PAYLOAD_BASE`
+build options are used.
 
 ### Function : bl2_plat_flush_bl31_params() [mandatory]
 
@@ -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
@@ -1267,8 +1296,8 @@
 
 BL2 is responsible for loading the normal world BL33 image (e.g. UEFI).
 
-This function isn't needed if either `BL33_BASE` or `EL3_PAYLOAD_BASE` build
-options are used.
+This function isn't needed if either `PRELOADED_BL33_BASE` or `EL3_PAYLOAD_BASE`
+build options are used.
 
 
 3.3 FWU Boot Loader Stage 2 (BL2U)
@@ -1973,8 +2002,8 @@
     By default, this flag is defined `yes` by the build system and `BL33`
     build option should be supplied as a build option. The platform has the
     option of excluding the BL33 image in the `fip` image by defining this flag
-    to `no`. If any of the options `EL3_PAYLOAD_BASE` or `BL33_BASE` are used,
-    this flag will be set to `no` automatically.
+    to `no`. If any of the options `EL3_PAYLOAD_BASE` or `PRELOADED_BL33_BASE`
+    are used, this flag will be set to `no` automatically.
 
 5.  C Library
 -------------
diff --git a/docs/user-guide.md b/docs/user-guide.md
index ea10a81..e5e28a3 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
 ---------
 
@@ -408,11 +411,11 @@
     payload. Please refer to the "Booting an EL3 payload" section for more
     details.
 
-*   `BL33_BASE`: This option enables booting a preloaded BL33 image instead of
-    the normal boot flow. When defined, it must specify the entry point address
-    for the preloaded BL33 image. This option is incompatible with
+*   `PRELOADED_BL33_BASE`: This option enables booting a preloaded BL33 image
+    instead of the normal boot flow. When defined, it must specify the entry
+    point address for the preloaded BL33 image. This option is incompatible with
     `EL3_PAYLOAD_BASE`. If both are defined, `EL3_PAYLOAD_BASE` has priority
-    over `BL33_BASE`.
+    over `PRELOADED_BL33_BASE`.
 
 *   `PL011_GENERIC_UART`: Boolean option to indicate the PL011 driver that
     the underlying hardware is not a full PL011 UART but a minimally compliant
@@ -439,6 +442,9 @@
     where applicable). Defaults to a string that contains the time and date of
     the compilation.
 
+*   `HANDLE_EA_EL3_FIRST`: When defined External Aborts and SError Interrupts
+    will be always trapped in EL3 i.e. in BL31 at runtime.
+
 #### ARM development platform specific build options
 
 *   `ARM_TSP_RAM_LOCATION`: location of the TSP binary. Options:
@@ -495,6 +501,12 @@
     that wish to optimise memory usage for page tables need to set this flag to 1
     and must override the related macros.
 
+*   'ARM_BL31_IN_DRAM': Boolean option to select loading of BL31 in TZC secured
+    DRAM. By default, BL31 is in the secure SRAM. Set this flag to 1 to load
+    BL31 in TZC secured DRAM. If TSP is present, then setting this option also
+    sets the TSP location to DRAM and ignores the `ARM_TSP_RAM_LOCATION` build
+    flag.
+
 #### ARM CSS platform specific build options
 
 *   `CSS_DETECT_PRE_1_7_0_SCP`: Boolean flag to detect SCP version
@@ -989,13 +1001,13 @@
 cold boot is complete, Trusted Firmware simply jumps to a BL33 base address
 provided at build time.
 
-For this option to be used, the `BL33_BASE` build option has to be used when
-compiling the Trusted Firmware. For example, the following command will create
-a FIP without a BL33 and prepare to jump to a BL33 image loaded at address
-0x80000000:
+For this option to be used, the `PRELOADED_BL33_BASE` build option has to be
+used when compiling the Trusted Firmware. For example, the following command
+will create a FIP without a BL33 and prepare to jump to a BL33 image loaded at
+address 0x80000000:
 
     CROSS_COMPILE=<path-to>/bin/aarch64-linux-gnu- \
-    make BL33_BASE=0x80000000 PLAT=fvp all fip
+    make PRELOADED_BL33_BASE=0x80000000 PLAT=fvp all fip
 
 #### Boot of a preloaded bootwrapped kernel image on Base FVP
 
@@ -1017,8 +1029,8 @@
 The `-a cluster0.cpu0=<bootwrapped-kernel.elf>` option loads the ELF file. It
 also sets the PC register to the ELF entry point address, which is not the
 desired behaviour, so the `--start cluster0.cpu0=0x0` option forces the PC back
-to 0x0 (the BL1 entry point address) on CPU #0. The `BL33_BASE` define used when
-compiling the FIP must match the ELF entry point.
+to 0x0 (the BL1 entry point address) on CPU #0. The `PRELOADED_BL33_BASE` define
+used when compiling the FIP must match the ELF entry point.
 
 #### Boot of a preloaded bootwrapped kernel image on Juno
 
diff --git a/drivers/arm/tzc/tzc400.c b/drivers/arm/tzc/tzc400.c
new file mode 100644
index 0000000..ee6bf8d
--- /dev/null
+++ b/drivers/arm/tzc/tzc400.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <mmio.h>
+#include <stddef.h>
+#include <tzc400.h>
+#include "tzc_common_private.c"
+
+/*
+ * Macros which will be used by common core functions.
+ */
+#define TZC_400_REGION_BASE_LOW_0_OFFSET	0x100
+#define TZC_400_REGION_BASE_HIGH_0_OFFSET	0x104
+#define TZC_400_REGION_TOP_LOW_0_OFFSET		0x108
+#define TZC_400_REGION_TOP_HIGH_0_OFFSET	0x10c
+#define TZC_400_REGION_ATTR_0_OFFSET		0x110
+#define TZC_400_REGION_ID_ACCESS_0_OFFSET	0x114
+
+/*
+ * Implementation defined values used to validate inputs later.
+ * Filters : max of 4 ; 0 to 3
+ * Regions : max of 9 ; 0 to 8
+ * Address width : Values between 32 to 64
+ */
+typedef struct tzc400_instance {
+	uintptr_t base;
+	uint8_t addr_width;
+	uint8_t num_filters;
+	uint8_t num_regions;
+} tzc400_instance_t;
+
+tzc400_instance_t tzc400;
+
+static inline unsigned int _tzc400_read_build_config(uintptr_t base)
+{
+	return mmio_read_32(base + BUILD_CONFIG_OFF);
+}
+
+static inline unsigned int _tzc400_read_gate_keeper(uintptr_t base)
+{
+	return mmio_read_32(base + GATE_KEEPER_OFF);
+}
+
+static inline void _tzc400_write_gate_keeper(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GATE_KEEPER_OFF, val);
+}
+
+/*
+ * Get the open status information for all filter units.
+ */
+#define get_gate_keeper_os(base)	((_tzc400_read_gate_keeper(base) >>	\
+					GATE_KEEPER_OS_SHIFT) &		\
+					GATE_KEEPER_OS_MASK)
+
+
+/* Define common core functions used across different TZC peripherals. */
+DEFINE_TZC_COMMON_WRITE_ACTION(400, 400)
+DEFINE_TZC_COMMON_WRITE_REGION_BASE(400, 400)
+DEFINE_TZC_COMMON_WRITE_REGION_TOP(400, 400)
+DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(400, 400)
+DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(400, 400)
+DEFINE_TZC_COMMON_CONFIGURE_REGION0(400)
+DEFINE_TZC_COMMON_CONFIGURE_REGION(400)
+
+static unsigned int _tzc400_get_gate_keeper(uintptr_t base,
+				unsigned int filter)
+{
+	unsigned int open_status;
+
+	open_status = get_gate_keeper_os(base);
+
+	return (open_status >> filter) & GATE_KEEPER_FILTER_MASK;
+}
+
+/* This function is not MP safe. */
+static void _tzc400_set_gate_keeper(uintptr_t base,
+				unsigned int filter,
+				int val)
+{
+	unsigned int open_status;
+
+	/* Upper half is current state. Lower half is requested state. */
+	open_status = get_gate_keeper_os(base);
+
+	if (val)
+		open_status |=  (1 << filter);
+	else
+		open_status &= ~(1 << filter);
+
+	_tzc400_write_gate_keeper(base, (open_status & GATE_KEEPER_OR_MASK) <<
+			      GATE_KEEPER_OR_SHIFT);
+
+	/* Wait here until we see the change reflected in the TZC status. */
+	while ((get_gate_keeper_os(base)) != open_status)
+		;
+}
+
+void tzc400_set_action(tzc_action_t action)
+{
+	assert(tzc400.base);
+	assert(action <= TZC_ACTION_ERR_INT);
+
+	/*
+	 * - Currently no handler is provided to trap an error via interrupt
+	 *   or exception.
+	 * - The interrupt action has not been tested.
+	 */
+	_tzc400_write_action(tzc400.base, action);
+}
+
+void tzc400_init(uintptr_t base)
+{
+#if DEBUG
+	unsigned int tzc400_id;
+#endif
+	unsigned int tzc400_build;
+
+	assert(base);
+	tzc400.base = base;
+
+#if DEBUG
+	tzc400_id = _tzc_read_peripheral_id(base);
+	if (tzc400_id != TZC_400_PERIPHERAL_ID) {
+		ERROR("TZC-400 : Wrong device ID (0x%x).\n", tzc400_id);
+		panic();
+	}
+#endif
+
+	/* Save values we will use later. */
+	tzc400_build = _tzc400_read_build_config(tzc400.base);
+	tzc400.num_filters = ((tzc400_build >> BUILD_CONFIG_NF_SHIFT) &
+			   BUILD_CONFIG_NF_MASK) + 1;
+	tzc400.addr_width  = ((tzc400_build >> BUILD_CONFIG_AW_SHIFT) &
+			   BUILD_CONFIG_AW_MASK) + 1;
+	tzc400.num_regions = ((tzc400_build >> BUILD_CONFIG_NR_SHIFT) &
+			   BUILD_CONFIG_NR_MASK) + 1;
+}
+
+/*
+ * `tzc400_configure_region0` is used to program region 0 into the TrustZone
+ * controller. Region 0 covers the whole address space that is not mapped
+ * to any other region, and is enabled on all filters; this cannot be
+ * changed. This function only changes the access permissions.
+ */
+void tzc400_configure_region0(tzc_region_attributes_t sec_attr,
+			   unsigned int ns_device_access)
+{
+	assert(tzc400.base);
+	assert(sec_attr <= TZC_REGION_S_RDWR);
+
+	_tzc400_configure_region0(tzc400.base, sec_attr, ns_device_access);
+}
+
+/*
+ * `tzc400_configure_region` is used to program regions into the TrustZone
+ * controller. A region can be associated with more than one filter. The
+ * associated filters are passed in as a bitmap (bit0 = filter0).
+ * NOTE:
+ * Region 0 is special; it is preferable to use tzc400_configure_region0
+ * for this region (see comment for that function).
+ */
+void tzc400_configure_region(unsigned int filters,
+			  int region,
+			  uintptr_t region_base,
+			  uintptr_t region_top,
+			  tzc_region_attributes_t sec_attr,
+			  unsigned int nsaid_permissions)
+{
+	assert(tzc400.base);
+
+	/* Do range checks on filters and regions. */
+	assert(((filters >> tzc400.num_filters) == 0) &&
+	       (region >= 0) && (region < tzc400.num_regions));
+
+	/*
+	 * Do address range check based on TZC configuration. A 64bit address is
+	 * the max and expected case.
+	 */
+	assert(((region_top <= (UINT64_MAX >> (64 - tzc400.addr_width))) &&
+		(region_base < region_top)));
+
+	/* region_base and (region_top + 1) must be 4KB aligned */
+	assert(((region_base | (region_top + 1)) & (4096 - 1)) == 0);
+
+	assert(sec_attr <= TZC_REGION_S_RDWR);
+
+	_tzc400_configure_region(tzc400.base, filters, region, region_base,
+						region_top,
+						sec_attr, nsaid_permissions);
+}
+
+void tzc400_enable_filters(void)
+{
+	unsigned int state;
+	unsigned int filter;
+
+	assert(tzc400.base);
+
+	for (filter = 0; filter < tzc400.num_filters; filter++) {
+		state = _tzc400_get_gate_keeper(tzc400.base, filter);
+		if (state) {
+			/* The TZC filter is already configured. Changing the
+			 * programmer's view in an active system can cause
+			 * unpredictable behavior therefore panic for now rather
+			 * than try to determine whether this is safe in this
+			 * instance. See:
+			 * http://infocenter.arm.com/help/index.jsp?\
+			 * topic=/com.arm.doc.ddi0504c/CJHHECBF.html */
+			ERROR("TZC-400 : Filter %d Gatekeeper already"
+				" enabled.\n", filter);
+			panic();
+		}
+		_tzc400_set_gate_keeper(tzc400.base, filter, 1);
+	}
+}
+
+void tzc400_disable_filters(void)
+{
+	unsigned int filter;
+
+	assert(tzc400.base);
+
+	/*
+	 * We don't do the same state check as above as the Gatekeepers are
+	 * disabled after reset.
+	 */
+	for (filter = 0; filter < tzc400.num_filters; filter++)
+		_tzc400_set_gate_keeper(tzc400.base, filter, 0);
+}
diff --git a/drivers/arm/tzc/tzc_common_private.c b/drivers/arm/tzc/tzc_common_private.c
new file mode 100644
index 0000000..f570daf
--- /dev/null
+++ b/drivers/arm/tzc/tzc_common_private.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <mmio.h>
+#include <tzc_common.h>
+
+#define DEFINE_TZC_COMMON_WRITE_ACTION(fn_name, macro_name)		\
+	static inline void _tzc##fn_name##_write_action(		\
+					uintptr_t base,			\
+					tzc_action_t action)		\
+	{								\
+		mmio_write_32(base + TZC_##macro_name##_ACTION_OFF,	\
+			action);					\
+	}
+
+#define DEFINE_TZC_COMMON_WRITE_REGION_BASE(fn_name, macro_name)	\
+	static inline void _tzc##fn_name##_write_region_base(		\
+						uintptr_t base,		\
+						int region_no,		\
+						uintptr_t region_base)	\
+	{								\
+		mmio_write_32(base +					\
+			TZC_REGION_OFFSET(				\
+				TZC_##macro_name##_REGION_SIZE,		\
+				region_no) +				\
+				TZC_##macro_name##_REGION_BASE_LOW_0_OFFSET,	\
+			(unsigned int)region_base);			\
+		mmio_write_32(base +					\
+			TZC_REGION_OFFSET(				\
+				TZC_##macro_name##_REGION_SIZE,		\
+				region_no) +				\
+			TZC_##macro_name##_REGION_BASE_HIGH_0_OFFSET,	\
+			(unsigned int)(region_base >> 32));		\
+	}
+
+#define DEFINE_TZC_COMMON_WRITE_REGION_TOP(fn_name, macro_name)		\
+	static inline void _tzc##fn_name##_write_region_top(		\
+						uintptr_t base,		\
+						int region_no,		\
+						uintptr_t region_top)	\
+	{								\
+		mmio_write_32(base +					\
+			TZC_REGION_OFFSET				\
+				(TZC_##macro_name##_REGION_SIZE,	\
+				region_no) +				\
+			TZC_##macro_name##_REGION_TOP_LOW_0_OFFSET,	\
+			(unsigned int)region_top);			\
+		mmio_write_32(base +					\
+			TZC_REGION_OFFSET(				\
+				TZC_##macro_name##_REGION_SIZE,		\
+				region_no) +				\
+			TZC_##macro_name##_REGION_TOP_HIGH_0_OFFSET,	\
+			(unsigned int)(region_top >> 32));		\
+	}
+
+#define DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(fn_name, macro_name)	\
+	static inline void _tzc##fn_name##_write_region_attributes(	\
+						uintptr_t base,		\
+						int region_no,		\
+						unsigned int attr)	\
+	{								\
+		mmio_write_32(base +					\
+			TZC_REGION_OFFSET(				\
+				TZC_##macro_name##_REGION_SIZE,		\
+				region_no) +				\
+			TZC_##macro_name##_REGION_ATTR_0_OFFSET,	\
+			attr);						\
+	}
+
+#define DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(fn_name, macro_name)	\
+	static inline void _tzc##fn_name##_write_region_id_access(	\
+						uintptr_t base,		\
+						int region_no,		\
+						unsigned int val)	\
+	{								\
+		mmio_write_32(base +					\
+			TZC_REGION_OFFSET(				\
+				TZC_##macro_name##_REGION_SIZE,		\
+				region_no) +				\
+			TZC_##macro_name##_REGION_ID_ACCESS_0_OFFSET,	\
+			val);						\
+	}
+
+/*
+ * It is used to program region 0 ATTRIBUTES and ACCESS register.
+ */
+#define DEFINE_TZC_COMMON_CONFIGURE_REGION0(fn_name)			\
+	void _tzc##fn_name##_configure_region0(uintptr_t base,		\
+			   tzc_region_attributes_t sec_attr,		\
+			   unsigned int ns_device_access)		\
+	{								\
+		assert(base);						\
+		VERBOSE("TrustZone : Configuring region 0 "		\
+			"(TZC Interface Base=%p sec_attr=0x%x,"		\
+			" ns_devs=0x%x)\n", (void *)base,		\
+			sec_attr, ns_device_access);			\
+									\
+		/* Set secure attributes on region 0 */			\
+		_tzc##fn_name##_write_region_attributes(base, 0,	\
+			sec_attr << TZC_REGION_ATTR_SEC_SHIFT);		\
+									\
+		/***************************************************/	\
+		/* Specify which non-secure devices have permission*/	\
+		/* to access region 0.				   */	\
+		/***************************************************/	\
+		_tzc##fn_name##_write_region_id_access(base,		\
+						0,			\
+						ns_device_access);	\
+	}
+
+/*
+ * It is used to program a region from 1 to 8 in the TrustZone controller.
+ * NOTE:
+ * Region 0 is special; it is preferable to use
+ * ##fn_name##_configure_region0 for this region (see comment for
+ * that function).
+ */
+#define DEFINE_TZC_COMMON_CONFIGURE_REGION(fn_name)			\
+	void _tzc##fn_name##_configure_region(uintptr_t base,		\
+				unsigned int filters,			\
+				int region_no,				\
+				uintptr_t region_base,			\
+				uintptr_t region_top,			\
+				tzc_region_attributes_t sec_attr,	\
+				unsigned int nsaid_permissions)	\
+	{								\
+		assert(base);						\
+		VERBOSE("TrustZone : Configuring region "		\
+			"(TZC Interface Base: %p, region_no = %d)"	\
+			"...\n", (void *)base, region_no);		\
+		VERBOSE("TrustZone : ... base = %p, top = %p,"		\
+			"\n", (void *)region_base, (void *)region_top);\
+		VERBOSE("TrustZone : ... sec_attr = 0x%x,"		\
+			" ns_devs = 0x%x)\n",				\
+			sec_attr, nsaid_permissions);			\
+									\
+		/***************************************************/	\
+		/* Inputs look ok, start programming registers.    */	\
+		/* All the address registers are 32 bits wide and  */	\
+		/* have a LOW and HIGH				   */	\
+		/* component used to construct an address up to a  */	\
+		/* 64bit.					   */	\
+		/***************************************************/	\
+		_tzc##fn_name##_write_region_base(base,			\
+					region_no, region_base);	\
+		_tzc##fn_name##_write_region_top(base,			\
+					region_no, region_top);		\
+									\
+		/* Enable filter to the region and set secure attributes */\
+		_tzc##fn_name##_write_region_attributes(base,		\
+				region_no,				\
+				(sec_attr << TZC_REGION_ATTR_SEC_SHIFT) |\
+				(filters << TZC_REGION_ATTR_F_EN_SHIFT));\
+									\
+		/***************************************************/	\
+		/* Specify which non-secure devices have permission*/	\
+		/* to access this region.			   */	\
+		/***************************************************/	\
+		_tzc##fn_name##_write_region_id_access(base,		\
+						region_no,		\
+						nsaid_permissions);	\
+	}
+
+#if DEBUG
+static unsigned int _tzc_read_peripheral_id(uintptr_t base)
+{
+	unsigned int id;
+
+	id = mmio_read_32(base + PID0_OFF);
+	/* Masks DESC part in PID1 */
+	id |= ((mmio_read_32(base + PID1_OFF) & 0xF) << 8);
+
+	return id;
+}
+#endif
diff --git a/drivers/arm/tzc/tzc_dmc500.c b/drivers/arm/tzc/tzc_dmc500.c
new file mode 100644
index 0000000..16a53a4
--- /dev/null
+++ b/drivers/arm/tzc/tzc_dmc500.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <mmio.h>
+#include <tzc_dmc500.h>
+#include "tzc_common.h"
+#include "tzc_common_private.c"
+
+/*
+ * Macros which will be used by common core functions.
+ */
+#define TZC_DMC500_REGION_BASE_LOW_0_OFFSET		0x054
+#define TZC_DMC500_REGION_BASE_HIGH_0_OFFSET		0x058
+#define TZC_DMC500_REGION_TOP_LOW_0_OFFSET		0x05C
+#define TZC_DMC500_REGION_TOP_HIGH_0_OFFSET		0x060
+#define TZC_DMC500_REGION_ATTR_0_OFFSET			0x064
+#define TZC_DMC500_REGION_ID_ACCESS_0_OFFSET		0x068
+
+#define TZC_DMC500_ACTION_OFF				0x50
+
+/* Pointer to the tzc_dmc500_driver_data structure populated by the platform */
+static const tzc_dmc500_driver_data_t *g_driver_data;
+
+#define verify_region_attr(region, attr)	\
+		((g_conf_regions[(region)].sec_attr ==			\
+			((attr) >> TZC_REGION_ATTR_SEC_SHIFT))		\
+		&& ((attr) & (0x1 << TZC_REGION_ATTR_F_EN_SHIFT)))
+
+/*
+ * Structure for configured regions attributes in DMC500.
+ */
+typedef struct tzc_dmc500_regions {
+	tzc_region_attributes_t sec_attr;
+	int is_enabled;
+} tzc_dmc500_regions_t;
+
+/*
+ * Array storing the attributes of the configured regions. This array
+ * will be used by the `tzc_dmc500_verify_complete` to verify the flush
+ * completion.
+ */
+static tzc_dmc500_regions_t g_conf_regions[MAX_REGION_VAL + 1];
+
+/* Helper Macros for making the code readable */
+#define DMC_INST_BASE_ADDR(instance) (g_driver_data->dmc_base[instance])
+#define DMC_INST_SI_BASE(instance, interface) \
+		(DMC_INST_BASE_ADDR(instance) + IFACE_OFFSET(interface))
+
+DEFINE_TZC_COMMON_WRITE_ACTION(_dmc500, DMC500)
+DEFINE_TZC_COMMON_WRITE_REGION_BASE(_dmc500, DMC500)
+DEFINE_TZC_COMMON_WRITE_REGION_TOP(_dmc500, DMC500)
+DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(_dmc500, DMC500)
+DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(_dmc500, DMC500)
+
+DEFINE_TZC_COMMON_CONFIGURE_REGION0(_dmc500)
+DEFINE_TZC_COMMON_CONFIGURE_REGION(_dmc500)
+
+static inline unsigned int _tzc_dmc500_read_region_attr_0(
+					uintptr_t dmc_si_base,
+					int region_no)
+{
+	return mmio_read_32(dmc_si_base +
+			TZC_REGION_OFFSET(TZC_DMC500_REGION_SIZE, region_no) +
+			TZC_DMC500_REGION_ATTR_0_OFFSET);
+}
+
+static inline void _tzc_dmc500_write_flush_control(uintptr_t dmc_si_base)
+{
+	mmio_write_32(dmc_si_base + SI_FLUSH_CTRL_OFFSET, 1);
+}
+
+/*
+ * Sets the Flush controls for all the DMC Instances and System Interfaces.
+ * This initiates the flush of configuration settings from the shadow
+ * registers to the actual configuration register. The caller should poll
+ * changed register to confirm update.
+ */
+void tzc_dmc500_config_complete(void)
+{
+	int dmc_inst, sys_if;
+
+	assert(g_driver_data);
+
+	for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) {
+		assert(DMC_INST_BASE_ADDR(dmc_inst));
+		for (sys_if = 0; sys_if < MAX_SYS_IF_COUNT; sys_if++)
+			_tzc_dmc500_write_flush_control(
+					DMC_INST_SI_BASE(dmc_inst, sys_if));
+	}
+}
+
+/*
+ * This function reads back the secure attributes from the configuration
+ * register for each DMC Instance and System Interface and compares it with
+ * the configured value. The successful verification of the region attributes
+ * confirms that the flush operation has completed.
+ * If the verification fails, the caller is expected to invoke this API again
+ * till it succeeds.
+ * Returns 0 on success and 1 on failure.
+ */
+int tzc_dmc500_verify_complete(void)
+{
+	int dmc_inst, sys_if, region_no;
+	unsigned int attr;
+
+	assert(g_driver_data);
+	/* Region 0 must be configured */
+	assert(g_conf_regions[0].is_enabled);
+
+	/* Iterate over all configured regions */
+	for (region_no = 0; region_no <= MAX_REGION_VAL; region_no++) {
+		if (!g_conf_regions[region_no].is_enabled)
+			continue;
+		for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count;
+								dmc_inst++) {
+			assert(DMC_INST_BASE_ADDR(dmc_inst));
+			for (sys_if = 0; sys_if < MAX_SYS_IF_COUNT;
+							sys_if++) {
+				attr = _tzc_dmc500_read_region_attr_0(
+					DMC_INST_SI_BASE(dmc_inst, sys_if),
+					region_no);
+				VERBOSE("Verifying DMC500 region:%d"
+					" dmc_inst:%d sys_if:%d attr:%x\n",
+					region_no, dmc_inst, sys_if, attr);
+				if (!verify_region_attr(region_no, attr))
+					return 1;
+			}
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * `tzc_dmc500_configure_region0` is used to program region 0 in both the
+ * system interfaces of all the DMC-500 instances. Region 0 covers the whole
+ * address space that is not mapped to any other region for a system interface,
+ * and is always enabled; this cannot be changed. This function only changes
+ * the access permissions.
+ */
+void tzc_dmc500_configure_region0(tzc_region_attributes_t sec_attr,
+					unsigned int nsaid_permissions)
+{
+	int dmc_inst, sys_if;
+
+	/* Assert if DMC-500 is not initialized */
+	assert(g_driver_data);
+
+	/* Configure region_0 in all DMC instances */
+	for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) {
+		assert(DMC_INST_BASE_ADDR(dmc_inst));
+		for (sys_if = 0; sys_if < MAX_SYS_IF_COUNT; sys_if++)
+			_tzc_dmc500_configure_region0(
+					DMC_INST_SI_BASE(dmc_inst, sys_if),
+					sec_attr, nsaid_permissions);
+	}
+
+	g_conf_regions[0].sec_attr = sec_attr;
+	g_conf_regions[0].is_enabled = 1;
+}
+
+/*
+ * `tzc_dmc500_configure_region` is used to program a region into all system
+ * interfaces of all the DMC instances.
+ * NOTE:
+ * Region 0 is special; it is preferable to use tzc_dmc500_configure_region0
+ * for this region (see comment for that function).
+ */
+void tzc_dmc500_configure_region(int region_no,
+			uintptr_t region_base,
+			uintptr_t region_top,
+			tzc_region_attributes_t sec_attr,
+			unsigned int nsaid_permissions)
+{
+	int dmc_inst, sys_if;
+
+	assert(g_driver_data);
+	/* Do range checks on regions. */
+	assert(region_no >= 0 && region_no <= MAX_REGION_VAL);
+
+	/*
+	 * Do address range check based on DMC-TZ configuration. A 43bit address
+	 * is the max and expected case.
+	 */
+	assert(((region_top <= (UINT64_MAX >> (64 - 43))) &&
+		(region_base < region_top)));
+
+	/* region_base and (region_top + 1) must be 4KB aligned */
+	assert(((region_base | (region_top + 1)) & (4096 - 1)) == 0);
+
+	for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) {
+		assert(DMC_INST_BASE_ADDR(dmc_inst));
+		for (sys_if = 0; sys_if < MAX_SYS_IF_COUNT; sys_if++)
+			_tzc_dmc500_configure_region(
+					DMC_INST_SI_BASE(dmc_inst, sys_if),
+					TZC_DMC500_REGION_ATTR_F_EN_MASK,
+					region_no, region_base, region_top,
+					sec_attr, nsaid_permissions);
+	}
+
+	g_conf_regions[region_no].sec_attr = sec_attr;
+	g_conf_regions[region_no].is_enabled = 1;
+}
+
+/* Sets the action value for all the DMC instances */
+void tzc_dmc500_set_action(tzc_action_t action)
+{
+	int dmc_inst;
+
+	assert(g_driver_data);
+
+	for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) {
+		assert(DMC_INST_BASE_ADDR(dmc_inst));
+		/*
+		 * - Currently no handler is provided to trap an error via
+		 *   interrupt or exception.
+		 * - The interrupt action has not been tested.
+		 */
+		_tzc_dmc500_write_action(DMC_INST_BASE_ADDR(dmc_inst), action);
+	}
+}
+
+/*
+ * A DMC-500 instance must be present at each base address provided by the
+ * platform. It also expects platform to pass at least one instance of
+ * DMC-500.
+ */
+static void validate_plat_driver_data(
+			const tzc_dmc500_driver_data_t *plat_driver_data)
+{
+#if DEBUG
+	int i;
+	unsigned int dmc_id;
+	uintptr_t dmc_base;
+
+	assert(plat_driver_data);
+	assert(plat_driver_data->dmc_count > 0 &&
+		(plat_driver_data->dmc_count <= MAX_DMC_COUNT));
+
+	for (i = 0; i < plat_driver_data->dmc_count; i++) {
+		dmc_base = plat_driver_data->dmc_base[i];
+		assert(dmc_base);
+
+		dmc_id = _tzc_read_peripheral_id(dmc_base);
+		assert(dmc_id == DMC500_PERIPHERAL_ID);
+	}
+#endif /* DEBUG */
+}
+
+
+/*
+ * Initializes the base address and count of DMC instances.
+ *
+ * Note : Only pointer to plat_driver_data is saved, so it is caller's
+ * responsibility to keep it valid until the driver is used.
+ */
+void tzc_dmc500_driver_init(const tzc_dmc500_driver_data_t *plat_driver_data)
+{
+	/* Check valid pointer is passed */
+	assert(plat_driver_data);
+
+	/*
+	 * NOTE: This driver expects the DMC-500 controller is already in
+	 * READY state. Hence, it uses the reconfiguration method for
+	 * programming TrustZone regions
+	 */
+	/* Validates the information passed by platform */
+	validate_plat_driver_data(plat_driver_data);
+	g_driver_data = plat_driver_data;
+}
diff --git a/drivers/arm/tzc400/tzc400.c b/drivers/arm/tzc400/tzc400.c
index 7194443..97adf81 100644
--- a/drivers/arm/tzc400/tzc400.c
+++ b/drivers/arm/tzc400/tzc400.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -28,313 +28,8 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <assert.h>
-#include <debug.h>
-#include <mmio.h>
-#include <stddef.h>
-#include <tzc400.h>
-
-/*
- * Implementation defined values used to validate inputs later.
- * Filters : max of 4 ; 0 to 3
- * Regions : max of 9 ; 0 to 8
- * Address width : Values between 32 to 64
- */
-typedef struct tzc_instance {
-	uintptr_t base;
-	uint8_t addr_width;
-	uint8_t num_filters;
-	uint8_t num_regions;
-} tzc_instance_t;
-
-tzc_instance_t tzc;
-
-
-static inline uint32_t tzc_read_build_config(uintptr_t base)
-{
-	return mmio_read_32(base + BUILD_CONFIG_OFF);
-}
-
-static inline uint32_t tzc_read_gate_keeper(uintptr_t base)
-{
-	return mmio_read_32(base + GATE_KEEPER_OFF);
-}
-
-static inline void tzc_write_gate_keeper(uintptr_t base, uint32_t val)
-{
-	mmio_write_32(base + GATE_KEEPER_OFF, val);
-}
-
-static inline void tzc_write_action(uintptr_t base, tzc_action_t action)
-{
-	mmio_write_32(base + ACTION_OFF, action);
-}
-
-static inline void tzc_write_region_base_low(uintptr_t base,
-					uint32_t region,
-					uint32_t val)
-{
-	mmio_write_32(base + REGION_BASE_LOW_OFF +
-		REGION_NUM_OFF(region), val);
-}
-
-static inline void tzc_write_region_base_high(uintptr_t base,
-					uint32_t region,
-					uint32_t val)
-{
-	mmio_write_32(base + REGION_BASE_HIGH_OFF +
-		REGION_NUM_OFF(region), val);
-}
-
-static inline void tzc_write_region_top_low(uintptr_t base,
-					uint32_t region,
-					uint32_t val)
-{
-	mmio_write_32(base + REGION_TOP_LOW_OFF +
-		REGION_NUM_OFF(region), val);
-}
-
-static inline void tzc_write_region_top_high(uintptr_t base,
-					uint32_t region,
-					uint32_t val)
-{
-	mmio_write_32(base + REGION_TOP_HIGH_OFF +
-		REGION_NUM_OFF(region), val);
-}
-
-static inline void tzc_write_region_attributes(uintptr_t base,
-					uint32_t region,
-					uint32_t val)
-{
-	mmio_write_32(base + REGION_ATTRIBUTES_OFF +
-		REGION_NUM_OFF(region), val);
-}
-
-static inline void tzc_write_region_id_access(uintptr_t base,
-					uint32_t region,
-					uint32_t val)
-{
-	mmio_write_32(base + REGION_ID_ACCESS_OFF +
-		REGION_NUM_OFF(region), val);
-}
-
-static unsigned int tzc_read_peripheral_id(uintptr_t base)
-{
-	unsigned int id;
-
-	id = mmio_read_8(base + PID0_OFF);
-	/* Masks jep106_id_3_0 part in PID1 */
-	id |= ((mmio_read_8(base + PID1_OFF) & 0xF) << 8);
-
-	return id;
-}
-
-static uint32_t tzc_get_gate_keeper(uintptr_t base, uint8_t filter)
-{
-	uint32_t tmp;
-
-	tmp = (tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
-		GATE_KEEPER_OS_MASK;
-
-	return (tmp >> filter) & GATE_KEEPER_FILTER_MASK;
-}
-
-/* This function is not MP safe. */
-static void tzc_set_gate_keeper(uintptr_t base, uint8_t filter, uint32_t val)
-{
-	uint32_t tmp;
-
-	/* Upper half is current state. Lower half is requested state. */
-	tmp = (tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
-		GATE_KEEPER_OS_MASK;
-
-	if (val)
-		tmp |=  (1 << filter);
-	else
-		tmp &= ~(1 << filter);
-
-	tzc_write_gate_keeper(base, (tmp & GATE_KEEPER_OR_MASK) <<
-			      GATE_KEEPER_OR_SHIFT);
-
-	/* Wait here until we see the change reflected in the TZC status. */
-	while (((tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
-		GATE_KEEPER_OS_MASK) != tmp)
-	  ;
-}
-
-
-void tzc_init(uintptr_t base)
-{
-	unsigned int tzc_id;
-	unsigned int tzc_build;
-
-	assert(base);
-
-	tzc.base = base;
-
-	/*
-	 * We expect to see a tzc400. Check peripheral ID.
-	 */
-	tzc_id = tzc_read_peripheral_id(tzc.base);
-	if (tzc_id != TZC400_PERIPHERAL_ID) {
-		ERROR("TZC : Wrong device ID (0x%x).\n", tzc_id);
-		panic();
-	}
-
-	/* Save values we will use later. */
-	tzc_build = tzc_read_build_config(tzc.base);
-	tzc.num_filters = ((tzc_build >> BUILD_CONFIG_NF_SHIFT) &
-			   BUILD_CONFIG_NF_MASK) + 1;
-	tzc.addr_width  = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) &
-			   BUILD_CONFIG_AW_MASK) + 1;
-	tzc.num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) &
-			   BUILD_CONFIG_NR_MASK) + 1;
-}
-
-/*
- * `tzc_configure_region0` is used to program region 0 into the TrustZone
- * controller. Region 0 covers the whole address space that is not mapped
- * to any other region, and is enabled on all filters; this cannot be
- * changed. This function only changes the access permissions.
- */
-void tzc_configure_region0(tzc_region_attributes_t sec_attr,
-			   uint32_t ns_device_access)
-{
-	assert(tzc.base);
-
-	VERBOSE("TZC : Configuring region 0 (sec_attr=0x%x, ns_devs=0x%x)\n",
-		sec_attr, ns_device_access);
-
-	assert(sec_attr <= TZC_REGION_S_RDWR);
-
-	/* Set secure attributes on region 0 */
-	tzc_write_region_attributes(tzc.base, 0,
-		sec_attr << REG_ATTR_SEC_SHIFT);
-
-	/*
-	 * Specify which non-secure devices have permission to access
-	 * region 0.
-	 */
-	tzc_write_region_id_access(tzc.base, 0, ns_device_access);
-}
-
-
-/*
- * `tzc_configure_region` is used to program regions into the TrustZone
- * controller. A region can be associated with more than one filter. The
- * associated filters are passed in as a bitmap (bit0 = filter0).
- * NOTE:
- * Region 0 is special; it is preferable to use tzc_configure_region0
- * for this region (see comment for that function).
- */
-void tzc_configure_region(uint32_t filters,
-			  uint8_t  region,
-			  uint64_t region_base,
-			  uint64_t region_top,
-			  tzc_region_attributes_t sec_attr,
-			  uint32_t ns_device_access)
-{
-	assert(tzc.base);
-
-	VERBOSE("TZC : Configuring region (filters=0x%x, region=%d, ...\n",
-		filters, region);
-	VERBOSE("TZC : ... base=0x%lx, top=0x%lx, ...\n",
-		region_base, region_top);
-	VERBOSE("TZC : ... sec_attr=0x%x, ns_devs=0x%x)\n",
-		sec_attr, ns_device_access);
-
-	/* Do range checks on filters and regions. */
-	assert(((filters >> tzc.num_filters) == 0) &&
-	       (region < tzc.num_regions));
-
-	/*
-	 * Do address range check based on TZC configuration. A 64bit address is
-	 * the max and expected case.
-	 */
-	assert(((region_top <= (UINT64_MAX >> (64 - tzc.addr_width))) &&
-		(region_base < region_top)));
-
-	/* region_base and (region_top + 1) must be 4KB aligned */
-	assert(((region_base | (region_top + 1)) & (4096 - 1)) == 0);
-
-	assert(sec_attr <= TZC_REGION_S_RDWR);
-
-	/*
-	 * Inputs look ok, start programming registers.
-	 * All the address registers are 32 bits wide and have a LOW and HIGH
-	 * component used to construct a up to a 64bit address.
-	 */
-	tzc_write_region_base_low(tzc.base, region,
-				(uint32_t)(region_base));
-	tzc_write_region_base_high(tzc.base, region,
-				(uint32_t)(region_base >> 32));
-
-	tzc_write_region_top_low(tzc.base, region,
-				(uint32_t)(region_top));
-	tzc_write_region_top_high(tzc.base, region,
-				(uint32_t)(region_top >> 32));
-
-	/* Assign the region to a filter and set secure attributes */
-	tzc_write_region_attributes(tzc.base, region,
-		(sec_attr << REG_ATTR_SEC_SHIFT) | filters);
-
-	/*
-	 * Specify which non-secure devices have permission to access this
-	 * region.
-	 */
-	tzc_write_region_id_access(tzc.base, region, ns_device_access);
-}
-
-
-void tzc_set_action(tzc_action_t action)
-{
-	assert(tzc.base);
-
-	/*
-	 * - Currently no handler is provided to trap an error via interrupt
-	 *   or exception.
-	 * - The interrupt action has not been tested.
-	 */
-	tzc_write_action(tzc.base, action);
-}
-
-
-void tzc_enable_filters(void)
-{
-	uint32_t state;
-	uint32_t filter;
-
-	assert(tzc.base);
-
-	for (filter = 0; filter < tzc.num_filters; filter++) {
-		state = tzc_get_gate_keeper(tzc.base, filter);
-		if (state) {
-			/* The TZC filter is already configured. Changing the
-			 * programmer's view in an active system can cause
-			 * unpredictable behavior therefore panic for now rather
-			 * than try to determine whether this is safe in this
-			 * instance. See:
-			 * http://infocenter.arm.com/help/index.jsp?\
-			 * topic=/com.arm.doc.ddi0504c/CJHHECBF.html */
-			ERROR("TZC : Filter %d Gatekeeper already enabled.\n",
-				filter);
-			panic();
-		}
-		tzc_set_gate_keeper(tzc.base, filter, 1);
-	}
-}
-
-
-void tzc_disable_filters(void)
-{
-	uint32_t filter;
-
-	assert(tzc.base);
-
-	/*
-	 * We don't do the same state check as above as the Gatekeepers are
-	 * disabled after reset.
-	 */
-	for (filter = 0; filter < tzc.num_filters; filter++)
-		tzc_set_gate_keeper(tzc.base, filter, 0);
-}
+#if ERROR_DEPRECATED
+#error "Using deprecated TZC-400 source file"
+#else
+#include "../tzc/tzc400.c"
+#endif /* ERROR_DEPRECATED */
diff --git a/drivers/auth/auth_mod.c b/drivers/auth/auth_mod.c
index bdd3c5a..4184556 100644
--- a/drivers/auth/auth_mod.c
+++ b/drivers/auth/auth_mod.c
@@ -40,6 +40,9 @@
 #include <stdint.h>
 #include <string.h>
 
+/* ASN.1 tags */
+#define ASN1_INTEGER                 0x02
+
 #define return_if_error(rc) \
 	do { \
 		if (rc != 0) { \
@@ -227,6 +230,83 @@
 }
 
 /*
+ * Authenticate by Non-Volatile counter
+ *
+ * To protect the system against rollback, the platform includes a non-volatile
+ * counter whose value can only be increased. All certificates include a counter
+ * value that should not be lower than the value stored in the platform. If the
+ * value is larger, the counter in the platform must be updated to the new
+ * value.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+static int auth_nvctr(const auth_method_param_nv_ctr_t *param,
+		      const auth_img_desc_t *img_desc,
+		      void *img, unsigned int img_len)
+{
+	char *p;
+	void *data_ptr = NULL;
+	unsigned int data_len, len, i;
+	unsigned int cert_nv_ctr, plat_nv_ctr;
+	int rc = 0;
+
+	/* Get the counter value from current image. The AM expects the IPM
+	 * to return the counter value as a DER encoded integer */
+	rc = img_parser_get_auth_param(img_desc->img_type, param->cert_nv_ctr,
+				       img, img_len, &data_ptr, &data_len);
+	return_if_error(rc);
+
+	/* Parse the DER encoded integer */
+	assert(data_ptr);
+	p = (char *)data_ptr;
+	if (*p != ASN1_INTEGER) {
+		/* Invalid ASN.1 integer */
+		return 1;
+	}
+	p++;
+
+	/* NV-counters are unsigned integers up to 32-bit */
+	len = (unsigned int)(*p & 0x7f);
+	if ((*p & 0x80) || (len > 4)) {
+		return 1;
+	}
+	p++;
+
+	/* Check the number is not negative */
+	if (*p & 0x80) {
+		return 1;
+	}
+
+	/* Convert to unsigned int. This code is for a little-endian CPU */
+	cert_nv_ctr = 0;
+	for (i = 0; i < len; i++) {
+		cert_nv_ctr = (cert_nv_ctr << 8) | *p++;
+	}
+
+	/* Get the counter from the platform */
+	rc = plat_get_nv_ctr(param->plat_nv_ctr->cookie, &plat_nv_ctr);
+	return_if_error(rc);
+
+	if (cert_nv_ctr < plat_nv_ctr) {
+		/* Invalid NV-counter */
+		return 1;
+	} else if (cert_nv_ctr > plat_nv_ctr) {
+		if (img_desc->parent == NULL) {
+			/* This certificate has been signed with the ROT key.
+			 * Update the platform counter value */
+			rc = plat_set_nv_ctr(param->plat_nv_ctr->cookie,
+					     cert_nv_ctr);
+			return_if_error(rc);
+		} else {
+			/* Secondary certificates cannot modify the counter */
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+/*
  * Return the parent id in the output parameter '*parent_id'
  *
  * Return value:
@@ -310,6 +390,10 @@
 			rc = auth_signature(&auth_method->param.sig,
 					img_desc, img_ptr, img_len);
 			break;
+		case AUTH_METHOD_NV_CTR:
+			rc = auth_nvctr(&auth_method->param.nv_ctr,
+					img_desc, img_ptr, img_len);
+			break;
 		default:
 			/* Unknown authentication method */
 			rc = 1;
diff --git a/drivers/auth/mbedtls/mbedtls_x509_parser.c b/drivers/auth/mbedtls/mbedtls_x509_parser.c
index 52e6971..1a6a9a7 100644
--- a/drivers/auth/mbedtls/mbedtls_x509_parser.c
+++ b/drivers/auth/mbedtls/mbedtls_x509_parser.c
@@ -405,6 +405,13 @@
 
 /*
  * Extract an authentication parameter from an X509v3 certificate
+ *
+ * This function returns a pointer to the extracted data and its length.
+ * Depending on the type of parameter, a pointer to the data stored in the
+ * certificate may be returned (i.e. an octet string containing a hash). Other
+ * data may need to be copied and formatted (i.e. integers). In the later case,
+ * a buffer of the correct type needs to be statically allocated, filled and
+ * returned.
  */
 static int get_auth_param(const auth_param_type_desc_t *type_desc,
 		void *img, unsigned int img_len,
@@ -422,6 +429,7 @@
 		*param_len = (unsigned int)tbs.len;
 		break;
 	case AUTH_PARAM_HASH:
+	case AUTH_PARAM_NV_CTR:
 		/* All these parameters are included as X509v3 extensions */
 		rc = get_ext(type_desc->cookie, param, param_len);
 		break;
diff --git a/drivers/auth/tbbr/tbbr_cot.c b/drivers/auth/tbbr/tbbr_cot.c
index 6023c78..dae35d1 100644
--- a/drivers/auth/tbbr/tbbr_cot.c
+++ b/drivers/auth/tbbr/tbbr_cot.c
@@ -56,6 +56,11 @@
 /*
  * Parameter type descriptors
  */
+static auth_param_type_desc_t trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_NV_CTR, TRUSTED_FW_NVCOUNTER_OID);
+static auth_param_type_desc_t non_trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_NV_CTR, NON_TRUSTED_FW_NVCOUNTER_OID);
+
 static auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC(
 		AUTH_PARAM_PUB_KEY, 0);
 static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC(
@@ -116,6 +121,13 @@
 					.alg = &sig_alg,
 					.data = &raw_data,
 				}
+			},
+			[1] = {
+				.type = AUTH_METHOD_NV_CTR,
+				.param.nv_ctr = {
+					.cert_nv_ctr = &trusted_nv_ctr,
+					.plat_nv_ctr = &trusted_nv_ctr
+				}
 			}
 		},
 		.authenticated_data = {
@@ -158,6 +170,13 @@
 					.alg = &sig_alg,
 					.data = &raw_data,
 				}
+			},
+			[1] = {
+				.type = AUTH_METHOD_NV_CTR,
+				.param.nv_ctr = {
+					.cert_nv_ctr = &trusted_nv_ctr,
+					.plat_nv_ctr = &trusted_nv_ctr
+				}
 			}
 		},
 		.authenticated_data = {
@@ -193,6 +212,13 @@
 					.alg = &sig_alg,
 					.data = &raw_data,
 				}
+			},
+			[1] = {
+				.type = AUTH_METHOD_NV_CTR,
+				.param.nv_ctr = {
+					.cert_nv_ctr = &trusted_nv_ctr,
+					.plat_nv_ctr = &trusted_nv_ctr
+				}
 			}
 		},
 		.authenticated_data = {
@@ -218,6 +244,13 @@
 					.alg = &sig_alg,
 					.data = &raw_data,
 				}
+			},
+			[1] = {
+				.type = AUTH_METHOD_NV_CTR,
+				.param.nv_ctr = {
+					.cert_nv_ctr = &trusted_nv_ctr,
+					.plat_nv_ctr = &trusted_nv_ctr
+				}
 			}
 		},
 		.authenticated_data = {
@@ -260,6 +293,13 @@
 					.alg = &sig_alg,
 					.data = &raw_data,
 				}
+			},
+			[1] = {
+				.type = AUTH_METHOD_NV_CTR,
+				.param.nv_ctr = {
+					.cert_nv_ctr = &trusted_nv_ctr,
+					.plat_nv_ctr = &trusted_nv_ctr
+				}
 			}
 		},
 		.authenticated_data = {
@@ -285,6 +325,13 @@
 					.alg = &sig_alg,
 					.data = &raw_data,
 				}
+			},
+			[1] = {
+				.type = AUTH_METHOD_NV_CTR,
+				.param.nv_ctr = {
+					.cert_nv_ctr = &trusted_nv_ctr,
+					.plat_nv_ctr = &trusted_nv_ctr
+				}
 			}
 		},
 		.authenticated_data = {
@@ -327,6 +374,13 @@
 					.alg = &sig_alg,
 					.data = &raw_data,
 				}
+			},
+			[1] = {
+				.type = AUTH_METHOD_NV_CTR,
+				.param.nv_ctr = {
+					.cert_nv_ctr = &trusted_nv_ctr,
+					.plat_nv_ctr = &trusted_nv_ctr
+				}
 			}
 		},
 		.authenticated_data = {
@@ -352,6 +406,13 @@
 					.alg = &sig_alg,
 					.data = &raw_data,
 				}
+			},
+			[1] = {
+				.type = AUTH_METHOD_NV_CTR,
+				.param.nv_ctr = {
+					.cert_nv_ctr = &trusted_nv_ctr,
+					.plat_nv_ctr = &trusted_nv_ctr
+				}
 			}
 		},
 		.authenticated_data = {
@@ -394,6 +455,13 @@
 					.alg = &sig_alg,
 					.data = &raw_data,
 				}
+			},
+			[1] = {
+				.type = AUTH_METHOD_NV_CTR,
+				.param.nv_ctr = {
+					.cert_nv_ctr = &non_trusted_nv_ctr,
+					.plat_nv_ctr = &non_trusted_nv_ctr
+				}
 			}
 		},
 		.authenticated_data = {
@@ -419,6 +487,13 @@
 					.alg = &sig_alg,
 					.data = &raw_data,
 				}
+			},
+			[1] = {
+				.type = AUTH_METHOD_NV_CTR,
+				.param.nv_ctr = {
+					.cert_nv_ctr = &non_trusted_nv_ctr,
+					.plat_nv_ctr = &non_trusted_nv_ctr
+				}
 			}
 		},
 		.authenticated_data = {
diff --git a/drivers/cadence/uart/cdns_console.S b/drivers/cadence/uart/cdns_console.S
new file mode 100644
index 0000000..2c7960d
--- /dev/null
+++ b/drivers/cadence/uart/cdns_console.S
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <arch.h>
+#include <asm_macros.S>
+#include <cadence/cdns_uart.h>
+
+        .globl  console_core_init
+        .globl  console_core_putc
+        .globl  console_core_getc
+
+	/* -----------------------------------------------
+	 * int console_core_init(unsigned long base_addr,
+	 * unsigned int uart_clk, unsigned int baud_rate)
+	 * Function to initialize the console without a
+	 * C Runtime to print debug information. This
+	 * function will be accessed by console_init and
+	 * crash reporting.
+	 * We assume that the bootloader already set up
+	 * the HW (baud, ...) and only enable the trans-
+	 * mitter and receiver here.
+	 * In: x0 - console base address
+	 *     w1 - Uart clock in Hz
+	 *     w2 - Baud rate
+	 * Out: return 1 on success else 0 on error
+	 * Clobber list : x1, x2, x3
+	 * -----------------------------------------------
+	 */
+func console_core_init
+	/* Check the input base address */
+	cbz	x0, core_init_fail
+	/* Check baud rate and uart clock for sanity */
+	cbz	w1, core_init_fail
+	cbz	w2, core_init_fail
+
+	/* RX/TX enabled & reset */
+	mov	w3, #(R_UART_CR_TX_EN | R_UART_CR_RX_EN | R_UART_CR_TXRST | R_UART_CR_RXRST)
+	str	w3, [x0, #R_UART_CR]
+
+	mov	w0, #1
+	ret
+core_init_fail:
+	mov	w0, wzr
+	ret
+endfunc console_core_init
+
+	/* --------------------------------------------------------
+	 * int console_core_putc(int c, unsigned long base_addr)
+	 * Function to output a character over the console. It
+	 * returns the character printed on success or -1 on error.
+	 * In : w0 - character to be printed
+	 *      x1 - console base address
+	 * Out : return -1 on error else return character.
+	 * Clobber list : x2
+	 * --------------------------------------------------------
+	 */
+func console_core_putc
+	/* Check the input parameter */
+	cbz	x1, putc_error
+	/* Prepend '\r' to '\n' */
+	cmp	w0, #0xA
+	b.ne	2f
+1:
+	/* Check if the transmit FIFO is full */
+	ldr	w2, [x1, #R_UART_SR]
+	tbnz	w2, #UART_SR_INTR_TFUL_BIT, 1b
+	mov	w2, #0xD
+	str	w2, [x1, #R_UART_TX]
+2:
+	/* Check if the transmit FIFO is full */
+	ldr	w2, [x1, #R_UART_SR]
+	tbnz	w2, #UART_SR_INTR_TFUL_BIT, 2b
+	str	w0, [x1, #R_UART_TX]
+	ret
+putc_error:
+	mov	w0, #-1
+	ret
+endfunc console_core_putc
+
+	/* ---------------------------------------------
+	 * int console_core_getc(unsigned long base_addr)
+	 * Function to get a character from the console.
+	 * It returns the character grabbed on success
+	 * or -1 on error.
+	 * In : x0 - console base address
+	 * Clobber list : x0, x1
+	 * ---------------------------------------------
+	 */
+func console_core_getc
+	cbz	x0, getc_error
+1:
+	/* Check if the receive FIFO is empty */
+	ldr	w1, [x0, #R_UART_SR]
+	tbnz	w1, #UART_SR_INTR_REMPTY_BIT, 1b
+	ldr	w1, [x0, #R_UART_RX]
+	mov	w0, w1
+	ret
+getc_error:
+	mov	w0, #-1
+	ret
+endfunc console_core_getc
diff --git a/include/common/el3_common_macros.S b/include/common/el3_common_macros.S
index 0cd85c3..9b22a73 100644
--- a/include/common/el3_common_macros.S
+++ b/include/common/el3_common_macros.S
@@ -70,8 +70,16 @@
 	isb
 
 	/* ---------------------------------------------------------------------
-	 * Enable the SError interrupt now that the exception vectors have been
-	 * setup.
+	 * Early set RES1 bits in SCR_EL3. Set EA bit to catch both
+	 * External Aborts and SError Interrupts in EL3 and also the SIF bit
+	 * to disable instruction fetches from Non-secure memory.
+	 * ---------------------------------------------------------------------
+	 */
+	mov	x0, #(SCR_RES1_BITS | SCR_EA_BIT | SCR_SIF_BIT)
+	msr	scr_el3, x0
+	/* ---------------------------------------------------------------------
+	 * Enable External Aborts and SError Interrupts now that the exception
+	 * vectors have been setup.
 	 * ---------------------------------------------------------------------
 	 */
 	msr	daifclr, #DAIF_ABT_BIT
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/drivers/cadence/cdns_uart.h b/include/drivers/cadence/cdns_uart.h
new file mode 100644
index 0000000..bc1cc90
--- /dev/null
+++ b/include/drivers/cadence/cdns_uart.h
@@ -0,0 +1,50 @@
+/*
+ * 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 __CADENCE_UART_H__
+#define __CADENCE_UART_H__
+
+/* This is very minimalistic and will only work in QEMU.  */
+
+/* CADENCE Registers */
+#define R_UART_CR	0
+#define R_UART_CR_RXRST	(1 << 0) /* RX logic reset */
+#define R_UART_CR_TXRST	(1 << 1) /* TX logic reset */
+#define R_UART_CR_RX_EN	(1 << 2) /* RX enabled */
+#define R_UART_CR_TX_EN	(1 << 4) /* TX enabled */
+
+#define R_UART_SR		0x2C
+#define UART_SR_INTR_REMPTY_BIT	1
+#define UART_SR_INTR_TFUL_BIT	4
+
+#define R_UART_TX	0x30
+#define R_UART_RX	0x30
+
+#endif
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index a9b2dbb..f9b8ed6 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -186,6 +186,11 @@
 #define HCR_IMO_BIT		(1 << 4)
 #define HCR_FMO_BIT		(1 << 3)
 
+/* ISR definitions */
+#define ISR_A_SHIFT		8
+#define ISR_I_SHIFT		7
+#define ISR_F_SHIFT		6
+
 /* CNTHCTL_EL2 definitions */
 #define EVNTEN_BIT		(1 << 2)
 #define EL1PCEN_BIT		(1 << 1)
diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h
index d1ad31d..f9f0715 100644
--- a/include/lib/aarch64/arch_helpers.h
+++ b/include/lib/aarch64/arch_helpers.h
@@ -113,15 +113,6 @@
 }
 
 /*******************************************************************************
- * Aarch64 translation tables manipulation helper prototypes
-******************************************************************************/
-uint64_t create_table_desc(uint64_t *next_table_ptr);
-uint64_t create_block_desc(uint64_t desc, uint64_t addr, uint32_t level);
-uint64_t create_device_block(uint64_t output_addr, uint32_t level, uint32_t ns);
-uint64_t create_romem_block(uint64_t output_addr, uint32_t level, uint32_t ns);
-uint64_t create_rwmem_block(uint64_t output_addr, uint32_t level, uint32_t ns);
-
-/*******************************************************************************
  * TLB maintenance accessor prototypes
  ******************************************************************************/
 DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1)
@@ -168,15 +159,6 @@
 DEFINE_SYSREG_WRITE_CONST_FUNC(daifset)
 DEFINE_SYSREG_WRITE_CONST_FUNC(daifclr)
 
-#define enable_irq()			write_daifclr(DAIF_IRQ_BIT)
-#define enable_fiq()			write_daifclr(DAIF_FIQ_BIT)
-#define enable_serror()			write_daifclr(DAIF_ABT_BIT)
-#define enable_debug_exceptions()	write_daifclr(DAIF_DBG_BIT)
-#define disable_irq()			write_daifset(DAIF_IRQ_BIT)
-#define disable_fiq()			write_daifset(DAIF_FIQ_BIT)
-#define disable_serror()		write_daifset(DAIF_ABT_BIT)
-#define disable_debug_exceptions()	write_daifset(DAIF_DBG_BIT)
-
 DEFINE_SYSREG_READ_FUNC(par_el1)
 DEFINE_SYSREG_READ_FUNC(id_pfr1_el1)
 DEFINE_SYSREG_READ_FUNC(id_aa64pfr0_el1)
diff --git a/include/plat/arm/board/common/board_arm_def.h b/include/plat/arm/board/common/board_arm_def.h
index b065537..d70fbb4 100644
--- a/include/plat/arm/board/common/board_arm_def.h
+++ b/include/plat/arm/board/common/board_arm_def.h
@@ -75,10 +75,10 @@
  */
 #if IMAGE_BL31 || IMAGE_BL32
 # define PLAT_ARM_MMAP_ENTRIES		6
-# define MAX_XLAT_TABLES		3
-#else
-# define PLAT_ARM_MMAP_ENTRIES		9
 # define MAX_XLAT_TABLES		4
+#else
+# define PLAT_ARM_MMAP_ENTRIES		10
+# define MAX_XLAT_TABLES		5
 #endif
 
 #endif /* ARM_BOARD_OPTIMISE_MMAP */
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index d04f9d6..0b3e66b 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -165,6 +165,12 @@
 						TSP_SEC_MEM_SIZE,	\
 						MT_MEMORY | MT_RW | MT_SECURE)
 
+#if ARM_BL31_IN_DRAM
+#define ARM_MAP_BL31_SEC_DRAM		MAP_REGION_FLAT(		\
+						BL31_BASE,		\
+						PLAT_ARM_MAX_BL31_SIZE,	\
+						MT_MEMORY | MT_RW | MT_SECURE)
+#endif
 
 /*
  * The number of regions like RO(code), coherent and data required by
@@ -240,15 +246,32 @@
 /*******************************************************************************
  * BL2 specific defines.
  ******************************************************************************/
+#if ARM_BL31_IN_DRAM
+/*
+ * BL31 is loaded in the DRAM.
+ * Put BL2 just below BL1.
+ */
+#define BL2_BASE			(BL1_RW_BASE - PLAT_ARM_MAX_BL2_SIZE)
+#define BL2_LIMIT			BL1_RW_BASE
+#else
 /*
  * Put BL2 just below BL31.
  */
 #define BL2_BASE			(BL31_BASE - PLAT_ARM_MAX_BL2_SIZE)
 #define BL2_LIMIT			BL31_BASE
+#endif
 
 /*******************************************************************************
  * BL31 specific defines.
  ******************************************************************************/
+#if ARM_BL31_IN_DRAM
+/*
+ * Put BL31 at the bottom of TZC secured DRAM
+ */
+#define BL31_BASE			ARM_AP_TZC_DRAM1_BASE
+#define BL31_LIMIT			(ARM_AP_TZC_DRAM1_BASE +	\
+						PLAT_ARM_MAX_BL31_SIZE)
+#else
 /*
  * Put BL31 at the top of the Trusted SRAM.
  */
@@ -257,6 +280,7 @@
 						PLAT_ARM_MAX_BL31_SIZE)
 #define BL31_PROGBITS_LIMIT		BL1_RW_BASE
 #define BL31_LIMIT			(ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
+#endif
 
 /*******************************************************************************
  * BL32 specific defines.
@@ -266,7 +290,16 @@
  * Trusted DRAM (if available) or the DRAM region secured by the TrustZone
  * controller.
  */
-#if ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_SRAM_ID
+#if ARM_BL31_IN_DRAM
+# define TSP_SEC_MEM_BASE		(ARM_AP_TZC_DRAM1_BASE +	\
+						PLAT_ARM_MAX_BL31_SIZE)
+# define TSP_SEC_MEM_SIZE		(ARM_AP_TZC_DRAM1_SIZE -	\
+						PLAT_ARM_MAX_BL31_SIZE)
+# define BL32_BASE			(ARM_AP_TZC_DRAM1_BASE +	\
+						PLAT_ARM_MAX_BL31_SIZE)
+# define BL32_LIMIT			(ARM_AP_TZC_DRAM1_BASE +	\
+						ARM_AP_TZC_DRAM1_SIZE)
+#elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_SRAM_ID
 # define TSP_SEC_MEM_BASE		ARM_BL_RAM_BASE
 # define TSP_SEC_MEM_SIZE		ARM_BL_RAM_SIZE
 # define TSP_PROGBITS_LIMIT		BL2_BASE
@@ -288,11 +321,19 @@
 # error "Unsupported ARM_TSP_RAM_LOCATION_ID value"
 #endif
 
+#ifdef SPD_none
+#undef BL32_BASE
+#endif /* SPD_none */
+
 /*******************************************************************************
  * FWU Images: NS_BL1U, BL2U & NS_BL2U defines.
  ******************************************************************************/
 #define BL2U_BASE			BL2_BASE
+#if ARM_BL31_IN_DRAM
+#define BL2U_LIMIT			BL1_RW_BASE
+#else
 #define BL2U_LIMIT			BL31_BASE
+#endif
 #define NS_BL2U_BASE			ARM_NS_DRAM1_BASE
 #define NS_BL1U_BASE			(PLAT_ARM_NVM_BASE + 0x03EB8000)
 
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/lib/aarch64/xlat_helpers.c b/lib/aarch64/xlat_helpers.c
deleted file mode 100644
index d401ffc..0000000
--- a/lib/aarch64/xlat_helpers.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without specific
- * prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <arch.h>
-#include <assert.h>
-
-/*******************************************************************************
- * Helper to create a level 1/2 table descriptor which points to a level 2/3
- * table.
- ******************************************************************************/
-unsigned long create_table_desc(unsigned long *next_table_ptr)
-{
-	unsigned long desc = (unsigned long) next_table_ptr;
-
-	/* Clear the last 12 bits */
-	desc >>= FOUR_KB_SHIFT;
-	desc <<= FOUR_KB_SHIFT;
-
-	desc |= TABLE_DESC;
-
-	return desc;
-}
-
-/*******************************************************************************
- * Helper to create a level 1/2/3 block descriptor which maps the va to addr
- ******************************************************************************/
-unsigned long create_block_desc(unsigned long desc,
-				unsigned long addr,
-				unsigned int level)
-{
-	switch (level) {
-	case LEVEL1:
-		desc |= (addr << FIRST_LEVEL_DESC_N) | BLOCK_DESC;
-		break;
-	case LEVEL2:
-		desc |= (addr << SECOND_LEVEL_DESC_N) | BLOCK_DESC;
-		break;
-	case LEVEL3:
-		desc |= (addr << THIRD_LEVEL_DESC_N) | TABLE_DESC;
-		break;
-	default:
-		assert(0);
-	}
-
-	return desc;
-}
-
-/*******************************************************************************
- * Helper to create a level 1/2/3 block descriptor which maps the va to output_
- * addr with Device nGnRE attributes.
- ******************************************************************************/
-unsigned long create_device_block(unsigned long output_addr,
-				  unsigned int level,
-				  unsigned int ns)
-{
-	unsigned long upper_attrs, lower_attrs, desc;
-
-	lower_attrs = LOWER_ATTRS(ACCESS_FLAG | OSH | AP_RW);
-	lower_attrs |= LOWER_ATTRS(ns | ATTR_DEVICE_INDEX);
-	upper_attrs = UPPER_ATTRS(XN);
-	desc = upper_attrs | lower_attrs;
-
-	return create_block_desc(desc, output_addr, level);
-}
-
-/*******************************************************************************
- * Helper to create a level 1/2/3 block descriptor which maps the va to output_
- * addr with inner-shareable normal wbwa read-only memory attributes.
- ******************************************************************************/
-unsigned long create_romem_block(unsigned long output_addr,
-				 unsigned int level,
-				 unsigned int ns)
-{
-	unsigned long upper_attrs, lower_attrs, desc;
-
-	lower_attrs = LOWER_ATTRS(ACCESS_FLAG | ISH | AP_RO);
-	lower_attrs |= LOWER_ATTRS(ns | ATTR_IWBWA_OWBWA_NTR_INDEX);
-	upper_attrs = UPPER_ATTRS(0ull);
-	desc = upper_attrs | lower_attrs;
-
-	return create_block_desc(desc, output_addr, level);
-}
-
-/*******************************************************************************
- * Helper to create a level 1/2/3 block descriptor which maps the va to output_
- * addr with inner-shareable normal wbwa read-write memory attributes.
- ******************************************************************************/
-unsigned long create_rwmem_block(unsigned long output_addr,
-				 unsigned int level,
-				 unsigned int ns)
-{
-	unsigned long upper_attrs, lower_attrs, desc;
-
-	lower_attrs = LOWER_ATTRS(ACCESS_FLAG | ISH | AP_RW);
-	lower_attrs |= LOWER_ATTRS(ns | ATTR_IWBWA_OWBWA_NTR_INDEX);
-	upper_attrs = UPPER_ATTRS(XN);
-	desc = upper_attrs | lower_attrs;
-
-	return create_block_desc(desc, output_addr, level);
-}
diff --git a/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/aarch64/fvp_common.c b/plat/arm/board/fvp/aarch64/fvp_common.c
index f684d97..1de9999 100644
--- a/plat/arm/board/fvp/aarch64/fvp_common.c
+++ b/plat/arm/board/fvp/aarch64/fvp_common.c
@@ -97,6 +97,9 @@
 	MAP_DEVICE2,
 	ARM_MAP_NS_DRAM1,
 	ARM_MAP_TSP_SEC_MEM,
+#if ARM_BL31_IN_DRAM
+	ARM_MAP_BL31_SEC_DRAM,
+#endif
 	{0}
 };
 #endif
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 a8267de..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)	|	\
@@ -146,11 +146,7 @@
  * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
  * plus a little space for growth.
  */
-#if TRUSTED_BOARD_BOOT
-# define PLAT_ARM_MAX_BL1_RW_SIZE	0x9000
-#else
-# define PLAT_ARM_MAX_BL1_RW_SIZE	0x6000
-#endif
+#define PLAT_ARM_MAX_BL1_RW_SIZE	0xA000
 
 /*
  * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a
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..78b75b4 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;
 }
@@ -137,6 +137,7 @@
 /*******************************************************************************
  * Configures access to the system counter timer module.
  ******************************************************************************/
+#ifdef ARM_SYS_TIMCTL_BASE
 void arm_configure_sys_timer(void)
 {
 	unsigned int reg_val;
@@ -151,6 +152,7 @@
 	reg_val = (1 << CNTNSAR_NS_SHIFT(PLAT_ARM_NSTIMER_FRAME_ID));
 	mmio_write_32(ARM_SYS_TIMCTL_BASE + CNTNSAR, reg_val);
 }
+#endif /* ARM_SYS_TIMCTL_BASE */
 
 /*******************************************************************************
  * Returns ARM platform specific memory map regions.
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index 97c2bca..681dc8a 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -96,11 +96,27 @@
 #pragma weak bl2_plat_get_bl33_meminfo
 #pragma weak bl2_plat_set_bl33_ep_info
 
+#if ARM_BL31_IN_DRAM
+meminfo_t *bl2_plat_sec_mem_layout(void)
+{
+	static meminfo_t bl2_dram_layout
+		__aligned(CACHE_WRITEBACK_GRANULE) = {
+		.total_base = BL31_BASE,
+		.total_size = (ARM_AP_TZC_DRAM1_BASE +
+				ARM_AP_TZC_DRAM1_SIZE) - BL31_BASE,
+		.free_base = BL31_BASE,
+		.free_size = (ARM_AP_TZC_DRAM1_BASE +
+				ARM_AP_TZC_DRAM1_SIZE) - BL31_BASE
+	};
 
+	return &bl2_dram_layout;
+}
+#else
 meminfo_t *bl2_plat_sec_mem_layout(void)
 {
 	return &bl2_tzram_layout;
 }
+#endif
 
 /*******************************************************************************
  * This function assigns a pointer to the memory that the platform has kept
@@ -131,14 +147,14 @@
 		VERSION_1, 0);
 
 	/* Fill BL32 related information if it exists */
-#if BL32_BASE
+#ifdef BL32_BASE
 	bl2_to_bl31_params->bl32_ep_info = &bl31_params_mem.bl32_ep_info;
 	SET_PARAM_HEAD(bl2_to_bl31_params->bl32_ep_info, PARAM_EP,
 		VERSION_1, 0);
 	bl2_to_bl31_params->bl32_image_info = &bl31_params_mem.bl32_image_info;
 	SET_PARAM_HEAD(bl2_to_bl31_params->bl32_image_info, PARAM_IMAGE_BINARY,
 		VERSION_1, 0);
-#endif
+#endif /* BL32_BASE */
 
 	/* Fill BL33 related information */
 	bl2_to_bl31_params->bl33_ep_info = &bl31_params_mem.bl33_ep_info;
@@ -264,6 +280,7 @@
  * the entrypoint of BL32 and set SPSR and security state.
  * On ARM standard platforms we only set the security state of the entrypoint
  ******************************************************************************/
+#ifdef BL32_BASE
 void bl2_plat_set_bl32_ep_info(image_info_t *bl32_image_info,
 					entry_point_info_t *bl32_ep_info)
 {
@@ -272,20 +289,6 @@
 }
 
 /*******************************************************************************
- * Before calling this function BL33 is loaded in memory and its entrypoint
- * is set by load_image. This is a placeholder for the platform to change
- * the entrypoint of BL33 and set SPSR and security state.
- * On ARM standard platforms we only set the security state of the entrypoint
- ******************************************************************************/
-void bl2_plat_set_bl33_ep_info(image_info_t *image,
-					entry_point_info_t *bl33_ep_info)
-{
-
-	SET_SECURITY_STATE(bl33_ep_info->h.attr, NON_SECURE);
-	bl33_ep_info->spsr = arm_get_spsr_for_bl33_entry();
-}
-
-/*******************************************************************************
  * Populate the extents of memory available for loading BL32
  ******************************************************************************/
 void bl2_plat_get_bl32_meminfo(meminfo_t *bl32_meminfo)
@@ -300,7 +303,20 @@
 	bl32_meminfo->free_size =
 			(TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE;
 }
+#endif /* BL32_BASE */
 
+/*******************************************************************************
+ * Before calling this function BL33 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL33 and set SPSR and security state.
+ * On ARM standard platforms we only set the security state of the entrypoint
+ ******************************************************************************/
+void bl2_plat_set_bl33_ep_info(image_info_t *image,
+					entry_point_info_t *bl33_ep_info)
+{
+	SET_SECURITY_STATE(bl33_ep_info->h.attr, NON_SECURE);
+	bl33_ep_info->spsr = arm_get_spsr_for_bl33_entry();
+}
 
 /*******************************************************************************
  * Populate the extents of memory available for loading BL33
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index 5cc8bfb..8fcfa77 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -142,7 +142,11 @@
 	 * Tell BL31 where the non-trusted software image
 	 * is located and the entry state information
 	 */
+#ifdef PRELOADED_BL33_BASE
+	bl33_image_ep_info.pc = PRELOADED_BL33_BASE;
+#else
 	bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
+#endif /* PRELOADED_BL33_BASE */
 	bl33_image_ep_info.spsr = arm_get_spsr_for_bl33_entry();
 	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
 
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 425e0d3..973e583 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -77,6 +77,11 @@
 $(eval $(call assert_boolean,ARM_CONFIG_CNTACR))
 $(eval $(call add_define,ARM_CONFIG_CNTACR))
 
+# Process ARM_BL31_IN_DRAM flag
+ARM_BL31_IN_DRAM		:=	0
+$(eval $(call assert_boolean,ARM_BL31_IN_DRAM))
+$(eval $(call add_define,ARM_BL31_IN_DRAM))
+
 PLAT_INCLUDES		+=	-Iinclude/common/tbbr				\
 				-Iinclude/plat/arm/common			\
 				-Iinclude/plat/arm/common/aarch64
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/mediatek/mt8173/bl31_plat_setup.c b/plat/mediatek/mt8173/bl31_plat_setup.c
index 8783775..749009e 100644
--- a/plat/mediatek/mt8173/bl31_plat_setup.c
+++ b/plat/mediatek/mt8173/bl31_plat_setup.c
@@ -50,13 +50,15 @@
 unsigned long __COHERENT_RAM_END__;
 
 /*
- * The next 2 constants identify the extents of the code & RO data region.
- * These addresses are used by the MMU setup code and therefore they must be
- * page-aligned.  It is the responsibility of the linker script to ensure that
- * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses.
+ * The next 3 constants identify the extents of the code, RO data region and the
+ * limit of the BL31 image.  These addresses are used by the MMU setup code and
+ * therefore they must be page-aligned.  It is the responsibility of the linker
+ * script to ensure that __RO_START__, __RO_END__ & __BL31_END__ linker symbols
+ * refer to page-aligned addresses.
  */
 #define BL31_RO_BASE (unsigned long)(&__RO_START__)
 #define BL31_RO_LIMIT (unsigned long)(&__RO_END__)
+#define BL31_END (unsigned long)(&__BL31_END__)
 
 /*
  * The next 2 constants identify the extents of the coherent memory region.
@@ -108,6 +110,13 @@
 		MCU_BUS_DCM_EN);
 }
 
+static void platform_setup_sram(void)
+{
+	/* protect BL31 memory from non-secure read/write access */
+	mmio_write_32(SRAMROM_SEC_ADDR, (uint32_t)(BL31_END + 0x3ff) & 0x3fc00);
+	mmio_write_32(SRAMROM_SEC_CTRL, 0x10000ff9);
+}
+
 /*******************************************************************************
  * Return a pointer to the 'entry_point_info' structure of the next image for
  * the security state specified. BL33 corresponds to the non-secure image type
@@ -156,6 +165,7 @@
 void bl31_platform_setup(void)
 {
 	platform_setup_cpu();
+	platform_setup_sram();
 
 	plat_delay_timer_init();
 
diff --git a/plat/mediatek/mt8173/drivers/spm/spm.c b/plat/mediatek/mt8173/drivers/spm/spm.c
index 45defd8..75eb61a 100644
--- a/plat/mediatek/mt8173/drivers/spm/spm.c
+++ b/plat/mediatek/mt8173/drivers/spm/spm.c
@@ -49,10 +49,6 @@
 
 #define SPM_SYSCLK_SETTLE       128	/* 3.9ms */
 
-#if DEBUG
-static int spm_dormant_sta = CPU_DORMANT_RESET;
-#endif
-
 DEFINE_BAKERY_LOCK(spm_lock);
 
 static int spm_hotplug_ready __section("tzfw_coherent_mem");
@@ -378,12 +374,15 @@
 	     wakesta->raw_sta, wakesta->idle_sta, wakesta->event_reg,
 	     wakesta->isr);
 
-	INFO("dormant state = %d\n", spm_dormant_sta);
 	return wr;
 }
 
 void spm_boot_init(void)
 {
+	/* set spm transaction to secure mode */
+	mmio_write_32(DEVAPC0_APC_CON, 0x0);
+	mmio_write_32(DEVAPC0_MAS_SEC_0, 0x200);
+
 	/* Only CPU0 is online during boot, initialize cpu online reserve bit */
 	mmio_write_32(SPM_PCM_RESERVE, 0xFE);
 	mmio_clrbits_32(AP_PLL_CON3, 0xFFFFF);
diff --git a/plat/mediatek/mt8173/include/mt8173_def.h b/plat/mediatek/mt8173/include/mt8173_def.h
index 39bab14..0113d60 100644
--- a/plat/mediatek/mt8173/include/mt8173_def.h
+++ b/plat/mediatek/mt8173/include/mt8173_def.h
@@ -40,11 +40,13 @@
 /* Register base address */
 #define IO_PHYS			(0x10000000)
 #define INFRACFG_AO_BASE	(IO_PHYS + 0x1000)
+#define SRAMROM_SEC_BASE	(IO_PHYS + 0x1800)
 #define PERI_CON_BASE		(IO_PHYS + 0x3000)
 #define GPIO_BASE		(IO_PHYS + 0x5000)
 #define SPM_BASE		(IO_PHYS + 0x6000)
 #define RGU_BASE		(IO_PHYS + 0x7000)
 #define PMIC_WRAP_BASE		(IO_PHYS + 0xD000)
+#define DEVAPC0_BASE		(IO_PHYS + 0xE000)
 #define MCUCFG_BASE		(IO_PHYS + 0x200000)
 #define APMIXED_BASE		(IO_PHYS + 0x209000)
 #define TRNG_BASE		(IO_PHYS + 0x20F000)
@@ -57,6 +59,14 @@
 #define MTK_DEV_RNG1_BASE	(IO_PHYS + 0x1000000)
 #define MTK_DEV_RNG1_SIZE	0x4000000
 
+/* SRAMROM related registers */
+#define SRAMROM_SEC_CTRL	(SRAMROM_SEC_BASE + 0x4)
+#define SRAMROM_SEC_ADDR	(SRAMROM_SEC_BASE + 0x8)
+
+/* DEVAPC0 related registers */
+#define DEVAPC0_MAS_SEC_0	(DEVAPC0_BASE + 0x500)
+#define DEVAPC0_APC_CON		(DEVAPC0_BASE + 0xF00)
+
 /*******************************************************************************
  * UART related constants
  ******************************************************************************/
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/plat/xilinx/zynqmp/aarch64/zynqmp_common.c b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c
new file mode 100644
index 0000000..0a878c3
--- /dev/null
+++ b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c
@@ -0,0 +1,308 @@
+/*
+ * 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 <cci.h>
+#include <debug.h>
+#include <gicv2.h>
+#include <mmio.h>
+#include <plat_arm.h>
+#include <platform.h>
+#include <xlat_tables.h>
+#include "../zynqmp_private.h"
+
+/*
+ * Table of regions to map using the MMU.
+ * This doesn't include TZRAM as the 'mem_layout' argument passed to
+ * configure_mmu_elx() will give the available subset of that,
+ */
+const mmap_region_t plat_arm_mmap[] = {
+	{ DEVICE0_BASE, DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE },
+	{ DEVICE1_BASE, DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE },
+	{ CRF_APB_BASE, CRF_APB_BASE, CRF_APB_SIZE, MT_DEVICE | MT_RW | MT_SECURE },
+	{0}
+};
+
+static unsigned int zynqmp_get_silicon_ver(void)
+{
+	unsigned int ver;
+
+	ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET);
+	ver &= ZYNQMP_SILICON_VER_MASK;
+	ver >>= ZYNQMP_SILICON_VER_SHIFT;
+
+	return ver;
+}
+
+unsigned int zynqmp_get_uart_clk(void)
+{
+	unsigned int ver = zynqmp_get_silicon_ver();
+
+	switch (ver) {
+	case ZYNQMP_CSU_VERSION_VELOCE:
+		return 48000;
+	case ZYNQMP_CSU_VERSION_EP108:
+		return 25000000;
+	case ZYNQMP_CSU_VERSION_QEMU:
+		return 133000000;
+	}
+
+	return 100000000;
+}
+
+static unsigned int zynqmp_get_system_timer_freq(void)
+{
+	unsigned int ver = zynqmp_get_silicon_ver();
+
+	switch (ver) {
+	case ZYNQMP_CSU_VERSION_VELOCE:
+		return 10000;
+	case ZYNQMP_CSU_VERSION_EP108:
+		return 4000000;
+	case ZYNQMP_CSU_VERSION_QEMU:
+		return 50000000;
+	}
+
+	return 100000000;
+}
+
+#if LOG_LEVEL >= LOG_LEVEL_NOTICE
+static const struct {
+	unsigned int id;
+	char *name;
+} zynqmp_devices[] = {
+	{
+		.id = 0x10,
+		.name = "3EG",
+	},
+	{
+		.id = 0x11,
+		.name = "2EG",
+	},
+	{
+		.id = 0x20,
+		.name = "5EV",
+	},
+	{
+		.id = 0x21,
+		.name = "4EV",
+	},
+	{
+		.id = 0x30,
+		.name = "7EV",
+	},
+	{
+		.id = 0x38,
+		.name = "9EG",
+	},
+	{
+		.id = 0x39,
+		.name = "6EG",
+	},
+	{
+		.id = 0x40,
+		.name = "11EG",
+	},
+	{
+		.id = 0x50,
+		.name = "15EG",
+	},
+	{
+		.id = 0x58,
+		.name = "19EG",
+	},
+	{
+		.id = 0x59,
+		.name = "17EG",
+	},
+};
+
+static unsigned int zynqmp_get_silicon_id(void)
+{
+	uint32_t id;
+
+	id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
+
+	id &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | ZYNQMP_CSU_IDCODE_SVD_MASK;
+	id >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
+
+	return id;
+}
+
+static char *zynqmp_get_silicon_idcode_name(void)
+{
+	unsigned int id;
+
+	id = zynqmp_get_silicon_id();
+	for (size_t i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
+		if (zynqmp_devices[i].id == id)
+			return zynqmp_devices[i].name;
+	}
+	return "UNKN";
+}
+
+static unsigned int zynqmp_get_rtl_ver(void)
+{
+	uint32_t ver;
+
+	ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET);
+	ver &= ZYNQMP_RTL_VER_MASK;
+	ver >>= ZYNQMP_RTL_VER_SHIFT;
+
+	return ver;
+}
+
+static char *zynqmp_print_silicon_idcode(void)
+{
+	uint32_t id, maskid, tmp;
+
+	id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
+
+	tmp = id;
+	tmp &= ZYNQMP_CSU_IDCODE_XILINX_ID_MASK |
+	       ZYNQMP_CSU_IDCODE_FAMILY_MASK |
+	       ZYNQMP_CSU_IDCODE_REVISION_MASK;
+	maskid = ZYNQMP_CSU_IDCODE_XILINX_ID << ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT |
+		 ZYNQMP_CSU_IDCODE_FAMILY << ZYNQMP_CSU_IDCODE_FAMILY_SHIFT |
+		 ZYNQMP_CSU_IDCODE_REVISION << ZYNQMP_CSU_IDCODE_REVISION_SHIFT;
+	if (tmp != maskid) {
+		ERROR("Incorrect XILINX IDCODE 0x%x, maskid 0x%x\n", id, maskid);
+		return "UNKN";
+	}
+	VERBOSE("Xilinx IDCODE 0x%x\n", id);
+	return zynqmp_get_silicon_idcode_name();
+}
+
+static unsigned int zynqmp_get_ps_ver(void)
+{
+	uint32_t ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET);
+
+	ver &= ZYNQMP_PS_VER_MASK;
+	ver >>= ZYNQMP_PS_VER_SHIFT;
+
+	return ver + 1;
+}
+
+static void zynqmp_print_platform_name(void)
+{
+	unsigned int ver = zynqmp_get_silicon_ver();
+	unsigned int rtl = zynqmp_get_rtl_ver();
+	char *label = "Unknown";
+
+	switch (ver) {
+	case ZYNQMP_CSU_VERSION_VELOCE:
+		label = "VELOCE";
+		break;
+	case ZYNQMP_CSU_VERSION_EP108:
+		label = "EP108";
+		break;
+	case ZYNQMP_CSU_VERSION_QEMU:
+		label = "QEMU";
+		break;
+	case ZYNQMP_CSU_VERSION_SILICON:
+		label = "silicon";
+		break;
+	}
+
+	NOTICE("ATF running on XCZU%s/%s v%d/RTL%d.%d at 0x%x%s\n",
+	       zynqmp_print_silicon_idcode(), label, zynqmp_get_ps_ver(),
+	       (rtl & 0xf0) >> 4, rtl & 0xf, BL31_BASE,
+	       zynqmp_is_pmu_up() ? ", with PMU firmware" : "");
+}
+#else
+static inline void zynqmp_print_platform_name(void) { }
+#endif
+
+/*
+ * Indicator for PMUFW discovery:
+ *   0 = No FW found
+ *   non-zero = FW is present
+ */
+static int zynqmp_pmufw_present;
+
+/*
+ * zynqmp_discover_pmufw - Discover presence of PMUFW
+ *
+ * Discover the presence of PMUFW and store it for later run-time queries
+ * through zynqmp_is_pmu_up.
+ * NOTE: This discovery method is fragile and will break if:
+ *  - setting FW_PRESENT is done by PMUFW itself and could be left out in PMUFW
+ *    (be it by error or intentionally)
+ *  - XPPU/XMPU may restrict ATF's access to the PMU address space
+ */
+static int zynqmp_discover_pmufw(void)
+{
+	zynqmp_pmufw_present = mmio_read_32(PMU_GLOBAL_CNTRL);
+	zynqmp_pmufw_present &= PMU_GLOBAL_CNTRL_FW_IS_PRESENT;
+
+	return !!zynqmp_pmufw_present;
+}
+
+/*
+ * zynqmp_is_pmu_up - Find if PMU firmware is up and running
+ *
+ * Return 0 if firmware is not available, non 0 otherwise
+ */
+int zynqmp_is_pmu_up(void)
+{
+	return zynqmp_pmufw_present;
+}
+
+/*
+ * A single boot loader stack is expected to work on both the Foundation ZYNQMP
+ * models and the two flavours of the Base ZYNQMP models (AEMv8 & Cortex). The
+ * SYS_ID register provides a mechanism for detecting the differences between
+ * these platforms. This information is stored in a per-BL array to allow the
+ * code to take the correct path.Per BL platform configuration.
+ */
+void zynqmp_config_setup(void)
+{
+	zynqmp_discover_pmufw();
+	zynqmp_print_platform_name();
+
+	/* Global timer init - Program time stamp reference clk */
+	uint32_t val = mmio_read_32(CRL_APB_TIMESTAMP_REF_CTRL);
+	val |= CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT;
+	mmio_write_32(CRL_APB_TIMESTAMP_REF_CTRL, val);
+
+	/* Program freq register in System counter and enable system counter. */
+	mmio_write_32(IOU_SCNTRS_BASEFREQ, zynqmp_get_system_timer_freq());
+	mmio_write_32(IOU_SCNTRS_CONTROL, IOU_SCNTRS_CONTROL_EN);
+}
+
+uint64_t plat_get_syscnt_freq(void)
+{
+	uint64_t counter_base_frequency;
+
+	/* FIXME: Read the frequency from Frequency modes table */
+	counter_base_frequency = zynqmp_get_system_timer_freq();
+
+	return counter_base_frequency;
+}
diff --git a/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S b/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S
new file mode 100644
index 0000000..0afed47
--- /dev/null
+++ b/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S
@@ -0,0 +1,73 @@
+/*
+ * 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 <asm_macros.S>
+#include <gicv2.h>
+#include <platform_def.h>
+
+	.globl	plat_secondary_cold_boot_setup
+	.globl	plat_is_my_cpu_primary
+
+	/* -----------------------------------------------------
+	 * 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.
+	 * TODO: Should we read the PSYS register to make sure
+	 * that the request has gone through.
+	 * -----------------------------------------------------
+	 */
+func plat_secondary_cold_boot_setup
+	mrs	x0, mpidr_el1
+
+	/* Deactivate the gic cpu interface */
+	ldr	x1, =BASE_GICC_BASE
+	mov	w0, #(IRQ_BYP_DIS_GRP1 | FIQ_BYP_DIS_GRP1)
+	orr	w0, w0, #(IRQ_BYP_DIS_GRP0 | FIQ_BYP_DIS_GRP0)
+	str	w0, [x1, #GICC_CTLR]
+
+	/*
+	 * There is no sane reason to come out of this wfi. This
+	 * cpu will be powered on and reset by the cpu_on pm api
+	 */
+	dsb	sy
+1:
+	bl	plat_panic_handler
+endfunc plat_secondary_cold_boot_setup
+
+func plat_is_my_cpu_primary
+	mov	x9, x30
+	bl	plat_my_core_pos
+	cmp	x0, #ZYNQMP_PRIMARY_CPU
+	cset	x0, eq
+	ret	x9
+endfunc plat_is_my_cpu_primary
diff --git a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
new file mode 100644
index 0000000..9c9d18d
--- /dev/null
+++ b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
@@ -0,0 +1,164 @@
+/*
+ * 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 <assert.h>
+#include <bl_common.h>
+#include <bl31.h>
+#include <console.h>
+#include <debug.h>
+#include <errno.h>
+#include <plat_arm.h>
+#include <platform.h>
+#include "zynqmp_private.h"
+
+/*
+ * Declarations of linker defined symbols which will help us find the layout
+ * of trusted SRAM
+ */
+extern unsigned long __RO_START__;
+extern unsigned long __RO_END__;
+
+extern unsigned long __COHERENT_RAM_START__;
+extern 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_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+/*
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ */
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+	assert(sec_state_is_valid(type));
+
+	if (type == NON_SECURE)
+		return &bl33_image_ep_info;
+
+	return &bl32_image_ep_info;
+}
+
+/*
+ * Perform any BL31 specific platform actions. 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.
+ */
+void bl31_early_platform_setup(bl31_params_t *from_bl2,
+			       void *plat_params_from_bl2)
+{
+	/* Initialize the console to provide early debug support */
+	console_init(ZYNQMP_UART0_BASE, zynqmp_get_uart_clk(),
+		     ZYNQMP_UART_BAUDRATE);
+
+	/* Initialize the platform config for future decision making */
+	zynqmp_config_setup();
+
+	/* There are no parameters from BL2 if BL31 is a reset vector */
+	assert(from_bl2 == NULL);
+	assert(plat_params_from_bl2 == NULL);
+
+	/*
+	 * Do initial security configuration to allow DRAM/device access. On
+	 * Base ZYNQMP only DRAM security is programmable (via TrustZone), but
+	 * other platforms might have more programmable security devices
+	 * present.
+	 */
+
+	/* Populate entry point information for BL32 and BL33 */
+	SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0);
+	SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+	bl32_image_ep_info.pc = BL32_BASE;
+	bl32_image_ep_info.spsr = arm_get_spsr_for_bl32_entry();
+
+	NOTICE("BL31: Secure code at 0x%lx\n", bl32_image_ep_info.pc);
+
+	SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0);
+
+	/*
+	 * Tell BL31 where the non-trusted software image
+	 * is located and the entry state information
+	 */
+	bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
+	bl33_image_ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
+					  DISABLE_ALL_EXCEPTIONS);
+	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+	NOTICE("BL31: Non secure code at 0x%lx\n", bl33_image_ep_info.pc);
+}
+
+void bl31_platform_setup(void)
+{
+	/* Initialize the gic cpu and distributor interfaces */
+	plat_arm_gic_driver_init();
+	plat_arm_gic_init();
+}
+
+void bl31_plat_runtime_setup(void)
+{
+}
+
+/*
+ * 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_arm_interconnect_init();
+	plat_arm_interconnect_enter_coherency();
+
+	arm_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/xilinx/zynqmp/include/plat_macros.S b/plat/xilinx/zynqmp/include/plat_macros.S
new file mode 100644
index 0000000..e6c39bb
--- /dev/null
+++ b/plat/xilinx/zynqmp/include/plat_macros.S
@@ -0,0 +1,51 @@
+/*
+ * 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_MACROS_S__
+#define __PLAT_MACROS_S__
+
+#include <arm_macros.S>
+#include <cci_macros.S>
+#include "../zynqmp_def.h"
+
+	/* ---------------------------------------------
+	 * The below required platform porting macro
+	 * prints out relevant GIC registers whenever an
+	 * unhandled exception is taken in BL31.
+	 * Clobbers: x0 - x10, x16, sp
+	 * ---------------------------------------------
+	 */
+	.macro plat_print_gic_regs
+	mov_imm	x17, BASE_GICC_BASE
+	mov_imm	x16, BASE_GICD_BASE
+	arm_print_gic_regs
+	mov x0, x1
+	.endm
+
+#endif /* __PLAT_MACROS_S__ */
diff --git a/plat/xilinx/zynqmp/include/platform_def.h b/plat/xilinx/zynqmp/include/platform_def.h
new file mode 100644
index 0000000..947a0f3
--- /dev/null
+++ b/plat/xilinx/zynqmp/include/platform_def.h
@@ -0,0 +1,135 @@
+/*
+ * 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 "../zynqmp_def.h"
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#define PLATFORM_STACK_SIZE 0x440
+
+#define PLATFORM_CORE_COUNT		4
+#define PLAT_NUM_POWER_DOMAINS		5
+#define PLAT_MAX_PWR_LVL		1
+#define PLAT_MAX_RET_STATE		1
+#define PLAT_MAX_OFF_STATE		2
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+
+#define ZYNQMP_BL31_SIZE	0x1b000
+/*
+ * Put BL31 at the top of the Trusted SRAM (just below the shared memory, if
+ * present). BL31_BASE is calculated using the current BL31 debug size plus a
+ * little space for growth.
+ */
+#if ZYNQMP_ATF_LOCATION_ID == ZYNQMP_IN_TRUSTED_SRAM
+# define BL31_BASE			(ZYNQMP_TRUSTED_SRAM_LIMIT - \
+					 ZYNQMP_BL31_SIZE)
+# define BL31_PROGBITS_LIMIT		(ZYNQMP_TRUSTED_SRAM_LIMIT - 0x6000)
+# define BL31_LIMIT			ZYNQMP_TRUSTED_SRAM_LIMIT
+#elif ZYNQMP_ATF_LOCATION_ID == ZYNQMP_IN_TRUSTED_DRAM
+# define BL31_BASE			(ZYNQMP_TRUSTED_DRAM_LIMIT - \
+					 ZYNQMP_BL31_SIZE)
+# define BL31_PROGBITS_LIMIT		(ZYNQMP_TRUSTED_DRAM_LIMIT - 0x6000)
+# define BL31_LIMIT			(ZYNQMP_TRUSTED_DRAM_BASE + \
+					ZYNQMP_TRUSTED_DRAM_SIZE)
+#else
+# error "Unsupported ZYNQMP_ATF_LOCATION_ID value"
+#endif
+
+/*******************************************************************************
+ * BL32 specific defines.
+ ******************************************************************************/
+/*
+ * On ZYNQMP, the TSP can execute either from Trusted SRAM or Trusted DRAM.
+ */
+#if ZYNQMP_TSP_RAM_LOCATION_ID == ZYNQMP_IN_TRUSTED_SRAM
+# define TSP_SEC_MEM_BASE		ZYNQMP_TRUSTED_SRAM_BASE
+# define TSP_SEC_MEM_SIZE		ZYNQMP_TRUSTED_SRAM_SIZE
+# define TSP_PROGBITS_LIMIT		(ZYNQMP_TRUSTED_SRAM_LIMIT - \
+					 ZYNQMP_BL31_SIZE)
+# define BL32_BASE			ZYNQMP_TRUSTED_SRAM_BASE
+# define BL32_LIMIT			(ZYNQMP_TRUSTED_SRAM_LIMIT - \
+					 ZYNQMP_BL31_SIZE)
+#elif ZYNQMP_TSP_RAM_LOCATION_ID == ZYNQMP_IN_TRUSTED_DRAM
+# define TSP_SEC_MEM_BASE		ZYNQMP_TRUSTED_DRAM_BASE
+# define TSP_SEC_MEM_SIZE		(ZYNQMP_TRUSTED_DRAM_LIMIT - \
+					 ZYNQMP_BL31_SIZE)
+# define BL32_BASE			ZYNQMP_TRUSTED_DRAM_BASE
+# define BL32_LIMIT			(ZYNQMP_TRUSTED_DRAM_LIMIT - \
+					 ZYNQMP_BL31_SIZE)
+#else
+# error "Unsupported ZYNQMP_TSP_RAM_LOCATION_ID value"
+#endif
+
+/*
+ * ID of the secure physical generic timer interrupt used by the TSP.
+ */
+#define TSP_IRQ_SEC_PHY_TIMER		ARM_IRQ_SEC_PHY_TIMER
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define ADDR_SPACE_SIZE			(1ull << 32)
+#define MAX_XLAT_TABLES			5
+#define MAX_MMAP_REGIONS		7
+
+#define CACHE_WRITEBACK_SHIFT   6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+#define PLAT_ARM_GICD_BASE	BASE_GICD_BASE
+#define PLAT_ARM_GICC_BASE	BASE_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_ARM_G1S_IRQS	ARM_IRQ_SEC_PHY_TIMER,	\
+				IRQ_SEC_IPI_APU,	\
+				ARM_IRQ_SEC_SGI_0,	\
+				ARM_IRQ_SEC_SGI_1,	\
+				ARM_IRQ_SEC_SGI_2,	\
+				ARM_IRQ_SEC_SGI_3,	\
+				ARM_IRQ_SEC_SGI_4,	\
+				ARM_IRQ_SEC_SGI_5,	\
+				ARM_IRQ_SEC_SGI_6,	\
+				ARM_IRQ_SEC_SGI_7
+
+#define PLAT_ARM_G0_IRQS
+
+#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/xilinx/zynqmp/plat_psci.c b/plat/xilinx/zynqmp/plat_psci.c
new file mode 100644
index 0000000..d693a2d
--- /dev/null
+++ b/plat/xilinx/zynqmp/plat_psci.c
@@ -0,0 +1,374 @@
+/*
+ * 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 <errno.h>
+#include <assert.h>
+#include <debug.h>
+#include <gicv2.h>
+#include <mmio.h>
+#include <plat_arm.h>
+#include <platform.h>
+#include <psci.h>
+#include "pm_api_sys.h"
+#include "pm_client.h"
+#include "zynqmp_private.h"
+
+uintptr_t zynqmp_sec_entry;
+
+void zynqmp_cpu_standby(plat_local_state_t cpu_state)
+{
+	VERBOSE("%s: cpu_state: 0x%x\n", __func__, cpu_state);
+
+	dsb();
+	wfi();
+}
+
+static int zynqmp_nopmu_pwr_domain_on(u_register_t mpidr)
+{
+	uint32_t r;
+	unsigned int cpu_id = plat_core_pos_by_mpidr(mpidr);
+
+	VERBOSE("%s: mpidr: 0x%lx\n", __func__, mpidr);
+
+	if (cpu_id == -1)
+		return PSCI_E_INTERN_FAIL;
+
+	/* program RVBAR */
+	mmio_write_32(APU_RVBAR_L_0 + (cpu_id << 3), zynqmp_sec_entry);
+	mmio_write_32(APU_RVBAR_H_0 + (cpu_id << 3), zynqmp_sec_entry >> 32);
+
+	/* clear VINITHI */
+	r = mmio_read_32(APU_CONFIG_0);
+	r &= ~(1 << APU_CONFIG_0_VINITHI_SHIFT << cpu_id);
+	mmio_write_32(APU_CONFIG_0, r);
+
+	/* clear power down request */
+	r = mmio_read_32(APU_PWRCTL);
+	r &= ~(1 << cpu_id);
+	mmio_write_32(APU_PWRCTL, r);
+
+	/* power up island */
+	mmio_write_32(PMU_GLOBAL_REQ_PWRUP_EN, 1 << cpu_id);
+	mmio_write_32(PMU_GLOBAL_REQ_PWRUP_TRIG, 1 << cpu_id);
+	/* FIXME: we should have a way to break out */
+	while (mmio_read_32(PMU_GLOBAL_REQ_PWRUP_STATUS) & (1 << cpu_id))
+		;
+
+	/* release core reset */
+	r = mmio_read_32(CRF_APB_RST_FPD_APU);
+	r &= ~((CRF_APB_RST_FPD_APU_ACPU_PWRON_RESET |
+			CRF_APB_RST_FPD_APU_ACPU_RESET) << cpu_id);
+	mmio_write_32(CRF_APB_RST_FPD_APU, r);
+
+	return PSCI_E_SUCCESS;
+}
+
+static int zynqmp_pwr_domain_on(u_register_t mpidr)
+{
+	unsigned int cpu_id = plat_core_pos_by_mpidr(mpidr);
+	const struct pm_proc *proc;
+
+	VERBOSE("%s: mpidr: 0x%lx\n", __func__, mpidr);
+
+	if (cpu_id == -1)
+		return PSCI_E_INTERN_FAIL;
+
+	proc = pm_get_proc(cpu_id);
+
+	/* Send request to PMU to wake up selected APU CPU core */
+	pm_req_wakeup(proc->node_id, 1, zynqmp_sec_entry, REQ_ACK_NO);
+
+	return PSCI_E_SUCCESS;
+}
+
+static void zynqmp_nopmu_pwr_domain_off(const psci_power_state_t *target_state)
+{
+	uint32_t r;
+	unsigned int cpu_id = plat_my_core_pos();
+
+	for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
+		VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
+			__func__, i, target_state->pwr_domain_state[i]);
+
+	/* Prevent interrupts from spuriously waking up this cpu */
+	gicv2_cpuif_disable();
+
+	/* set power down request */
+	r = mmio_read_32(APU_PWRCTL);
+	r |= (1 << cpu_id);
+	mmio_write_32(APU_PWRCTL, r);
+}
+
+static void zynqmp_pwr_domain_off(const psci_power_state_t *target_state)
+{
+	unsigned int cpu_id = plat_my_core_pos();
+	const struct pm_proc *proc = pm_get_proc(cpu_id);
+
+	for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
+		VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
+			__func__, i, target_state->pwr_domain_state[i]);
+
+	/* Prevent interrupts from spuriously waking up this cpu */
+	gicv2_cpuif_disable();
+
+	/*
+	 * Send request to PMU to power down the appropriate APU CPU
+	 * core.
+	 * According to PSCI specification, CPU_off function does not
+	 * have resume address and CPU core can only be woken up
+	 * invoking CPU_on function, during which resume address will
+	 * be set.
+	 */
+	pm_self_suspend(proc->node_id, MAX_LATENCY, 0, 0);
+}
+
+static void zynqmp_nopmu_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+	uint32_t r;
+	unsigned int cpu_id = plat_my_core_pos();
+
+	for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
+		VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
+			__func__, i, target_state->pwr_domain_state[i]);
+
+	/* set power down request */
+	r = mmio_read_32(APU_PWRCTL);
+	r |= (1 << cpu_id);
+	mmio_write_32(APU_PWRCTL, r);
+
+	/* program RVBAR */
+	mmio_write_32(APU_RVBAR_L_0 + (cpu_id << 3), zynqmp_sec_entry);
+	mmio_write_32(APU_RVBAR_H_0 + (cpu_id << 3), zynqmp_sec_entry >> 32);
+
+	/* clear VINITHI */
+	r = mmio_read_32(APU_CONFIG_0);
+	r &= ~(1 << APU_CONFIG_0_VINITHI_SHIFT << cpu_id);
+	mmio_write_32(APU_CONFIG_0, r);
+
+	/* enable power up on IRQ */
+	mmio_write_32(PMU_GLOBAL_REQ_PWRUP_EN, 1 << cpu_id);
+}
+
+static void zynqmp_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+	unsigned int cpu_id = plat_my_core_pos();
+	const struct pm_proc *proc = pm_get_proc(cpu_id);
+
+	for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
+		VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
+			__func__, i, target_state->pwr_domain_state[i]);
+
+	/* Send request to PMU to suspend this core */
+	pm_self_suspend(proc->node_id, MAX_LATENCY, 0, zynqmp_sec_entry);
+
+	/* APU is to be turned off */
+	if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) {
+		/* Power down L2 cache */
+		pm_set_requirement(NODE_L2, 0, 0, REQ_ACK_NO);
+		/* Send request for OCM retention state */
+		set_ocm_retention();
+		/* disable coherency */
+		plat_arm_interconnect_exit_coherency();
+	}
+}
+
+static void zynqmp_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+	for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
+		VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
+			__func__, i, target_state->pwr_domain_state[i]);
+
+	gicv2_cpuif_enable();
+	gicv2_pcpu_distif_init();
+}
+
+static void zynqmp_nopmu_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+	uint32_t r;
+	unsigned int cpu_id = plat_my_core_pos();
+
+	for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
+		VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
+			__func__, i, target_state->pwr_domain_state[i]);
+
+	/* disable power up on IRQ */
+	mmio_write_32(PMU_GLOBAL_REQ_PWRUP_DIS, 1 << cpu_id);
+
+	/* clear powerdown bit */
+	r = mmio_read_32(APU_PWRCTL);
+	r &= ~(1 << cpu_id);
+	mmio_write_32(APU_PWRCTL, r);
+}
+
+static void zynqmp_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+	unsigned int cpu_id = plat_my_core_pos();
+	const struct pm_proc *proc = pm_get_proc(cpu_id);
+
+	for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
+		VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
+			__func__, i, target_state->pwr_domain_state[i]);
+
+	/* Clear the APU power control register for this cpu */
+	pm_client_wakeup(proc);
+
+	/* enable coherency */
+	plat_arm_interconnect_enter_coherency();
+}
+
+/*******************************************************************************
+ * ZynqMP handlers to shutdown/reboot the system
+ ******************************************************************************/
+static void __dead2 zynqmp_nopmu_system_off(void)
+{
+	ERROR("ZynqMP System Off: operation not handled.\n");
+
+	/* disable coherency */
+	plat_arm_interconnect_exit_coherency();
+
+	panic();
+}
+
+static void __dead2 zynqmp_system_off(void)
+{
+	/* disable coherency */
+	plat_arm_interconnect_exit_coherency();
+
+	/* Send the power down request to the PMU */
+	pm_system_shutdown(0);
+
+	while (1)
+		wfi();
+}
+
+static void __dead2 zynqmp_nopmu_system_reset(void)
+{
+	/*
+	 * This currently triggers a system reset. I.e. the whole
+	 * system will be reset! Including RPUs, PMU, PL, etc.
+	 */
+
+	/* disable coherency */
+	plat_arm_interconnect_exit_coherency();
+
+	/* bypass RPLL (needed on 1.0 silicon) */
+	uint32_t reg = mmio_read_32(CRL_APB_RPLL_CTRL);
+	reg |= CRL_APB_RPLL_CTRL_BYPASS;
+	mmio_write_32(CRL_APB_RPLL_CTRL, reg);
+
+	/* trigger system reset */
+	mmio_write_32(CRL_APB_RESET_CTRL, CRL_APB_RESET_CTRL_SOFT_RESET);
+
+	while (1)
+		wfi();
+}
+
+static void __dead2 zynqmp_system_reset(void)
+{
+	/* disable coherency */
+	plat_arm_interconnect_exit_coherency();
+
+	/* Send the system reset request to the PMU */
+	pm_system_shutdown(1);
+
+	while (1)
+		wfi();
+}
+
+int zynqmp_validate_power_state(unsigned int power_state,
+				psci_power_state_t *req_state)
+{
+	VERBOSE("%s: power_state: 0x%x\n", __func__, power_state);
+
+	/* FIXME: populate req_state */
+	return PSCI_E_SUCCESS;
+}
+
+int zynqmp_validate_ns_entrypoint(unsigned long ns_entrypoint)
+{
+	VERBOSE("%s: ns_entrypoint: 0x%lx\n", __func__, ns_entrypoint);
+
+	/* FIXME: Actually validate */
+	return PSCI_E_SUCCESS;
+}
+
+void zynqmp_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+	req_state->pwr_domain_state[PSCI_CPU_PWR_LVL] = PLAT_MAX_OFF_STATE;
+	req_state->pwr_domain_state[1] = PLAT_MAX_OFF_STATE;
+}
+
+/*******************************************************************************
+ * Export the platform handlers to enable psci to invoke them
+ ******************************************************************************/
+static const struct plat_psci_ops zynqmp_psci_ops = {
+	.cpu_standby			= zynqmp_cpu_standby,
+	.pwr_domain_on			= zynqmp_pwr_domain_on,
+	.pwr_domain_off			= zynqmp_pwr_domain_off,
+	.pwr_domain_suspend		= zynqmp_pwr_domain_suspend,
+	.pwr_domain_on_finish		= zynqmp_pwr_domain_on_finish,
+	.pwr_domain_suspend_finish	= zynqmp_pwr_domain_suspend_finish,
+	.system_off			= zynqmp_system_off,
+	.system_reset			= zynqmp_system_reset,
+	.validate_power_state		= zynqmp_validate_power_state,
+	.validate_ns_entrypoint		= zynqmp_validate_ns_entrypoint,
+	.get_sys_suspend_power_state	= zynqmp_get_sys_suspend_power_state,
+};
+
+static const struct plat_psci_ops zynqmp_nopmu_psci_ops = {
+	.cpu_standby			= zynqmp_cpu_standby,
+	.pwr_domain_on			= zynqmp_nopmu_pwr_domain_on,
+	.pwr_domain_off			= zynqmp_nopmu_pwr_domain_off,
+	.pwr_domain_suspend		= zynqmp_nopmu_pwr_domain_suspend,
+	.pwr_domain_on_finish		= zynqmp_pwr_domain_on_finish,
+	.pwr_domain_suspend_finish	= zynqmp_nopmu_pwr_domain_suspend_finish,
+	.system_off			= zynqmp_nopmu_system_off,
+	.system_reset			= zynqmp_nopmu_system_reset,
+	.validate_power_state		= zynqmp_validate_power_state,
+	.validate_ns_entrypoint		= zynqmp_validate_ns_entrypoint,
+	.get_sys_suspend_power_state	= zynqmp_get_sys_suspend_power_state,
+};
+
+/*******************************************************************************
+ * Export the platform specific power ops.
+ ******************************************************************************/
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+			const struct plat_psci_ops **psci_ops)
+{
+	zynqmp_sec_entry = sec_entrypoint;
+
+	if (zynqmp_is_pmu_up())
+		*psci_ops = &zynqmp_psci_ops;
+	else
+		*psci_ops = &zynqmp_nopmu_psci_ops;
+
+	return 0;
+}
diff --git a/plat/xilinx/zynqmp/plat_topology.c b/plat/xilinx/zynqmp/plat_topology.c
new file mode 100644
index 0000000..34e7b53
--- /dev/null
+++ b/plat/xilinx/zynqmp/plat_topology.c
@@ -0,0 +1,39 @@
+/*
+ * 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 <platform_def.h>
+#include <psci.h>
+
+static const unsigned char plat_power_domain_tree_desc[] = {1, 4};
+
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+	return plat_power_domain_tree_desc;
+}
diff --git a/plat/xilinx/zynqmp/plat_zynqmp.c b/plat/xilinx/zynqmp/plat_zynqmp.c
new file mode 100644
index 0000000..38fa20f
--- /dev/null
+++ b/plat/xilinx/zynqmp/plat_zynqmp.c
@@ -0,0 +1,42 @@
+/*
+ * 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:
+ *
+ * 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 <plat_arm.h>
+
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+	if (mpidr & MPIDR_CLUSTER_MASK)
+		return -1;
+
+	if ((mpidr & MPIDR_CPU_MASK) >= PLATFORM_CORE_COUNT)
+		return -1;
+
+	return plat_arm_calc_core_pos(mpidr);
+}
diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk
new file mode 100644
index 0000000..0ffc0a9
--- /dev/null
+++ b/plat/xilinx/zynqmp/platform.mk
@@ -0,0 +1,95 @@
+# 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.
+
+ENABLE_PLAT_COMPAT := 0
+PROGRAMMABLE_RESET_ADDRESS := 1
+PSCI_EXTENDED_STATE_ID := 1
+A53_DISABLE_NON_TEMPORAL_HINT := 0
+
+ZYNQMP_ATF_LOCATION	?=	tsram
+ifeq (${ZYNQMP_ATF_LOCATION}, tsram)
+  ZYNQMP_ATF_LOCATION_ID := ZYNQMP_IN_TRUSTED_SRAM
+else ifeq (${ZYNQMP_ATF_LOCATION}, tdram)
+  ZYNQMP_ATF_LOCATION_ID := ZYNQMP_IN_TRUSTED_DRAM
+else
+  $(error "Unsupported ZYNQMP_ATF_LOCATION value")
+endif
+
+# On ZYNQMP, the TSP can execute either from Trusted SRAM or Trusted DRAM.
+# Trusted SRAM is the default.
+ZYNQMP_TSP_RAM_LOCATION	?=	tsram
+ifeq (${ZYNQMP_TSP_RAM_LOCATION}, tsram)
+  ZYNQMP_TSP_RAM_LOCATION_ID := ZYNQMP_IN_TRUSTED_SRAM
+else ifeq (${ZYNQMP_TSP_RAM_LOCATION}, tdram)
+  ZYNQMP_TSP_RAM_LOCATION_ID := ZYNQMP_IN_TRUSTED_DRAM
+else
+  $(error "Unsupported ZYNQMP_TSP_RAM_LOCATION value")
+endif
+
+# Process flags
+$(eval $(call add_define,ZYNQMP_ATF_LOCATION_ID))
+$(eval $(call add_define,ZYNQMP_TSP_RAM_LOCATION_ID))
+
+PLAT_INCLUDES		:=	-Iinclude/plat/arm/common/			\
+				-Iinclude/plat/arm/common/aarch64/		\
+				-Iplat/xilinx/zynqmp/include/			\
+				-Iplat/xilinx/zynqmp/pm_service/
+
+PLAT_BL_COMMON_SOURCES	:=	lib/aarch64/xlat_tables.c			\
+				drivers/arm/gic/common/gic_common.c		\
+				drivers/arm/gic/v2/gicv2_main.c			\
+				drivers/arm/gic/v2/gicv2_helpers.c		\
+				drivers/cadence/uart/cdns_console.S		\
+				drivers/console/console.S			\
+				plat/arm/common/aarch64/arm_common.c		\
+				plat/arm/common/aarch64/arm_helpers.S		\
+				plat/arm/common/arm_cci.c			\
+				plat/arm/common/arm_gicv2.c			\
+				plat/common/plat_gicv2.c			\
+				plat/common/aarch64/plat_common.c		\
+				plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S	\
+				plat/xilinx/zynqmp/aarch64/zynqmp_common.c
+
+BL31_SOURCES		+=	drivers/arm/cci/cci.c				\
+				lib/cpus/aarch64/aem_generic.S			\
+				lib/cpus/aarch64/cortex_a53.S			\
+				plat/common/aarch64/plat_psci_common.c		\
+				plat/common/aarch64/platform_mp_stack.S		\
+				plat/xilinx/zynqmp/bl31_zynqmp_setup.c		\
+				plat/xilinx/zynqmp/plat_psci.c			\
+				plat/xilinx/zynqmp/plat_zynqmp.c		\
+				plat/xilinx/zynqmp/plat_topology.c		\
+				plat/xilinx/zynqmp/sip_svc_setup.c		\
+				plat/xilinx/zynqmp/pm_service/pm_svc_main.c	\
+				plat/xilinx/zynqmp/pm_service/pm_api_sys.c	\
+				plat/xilinx/zynqmp/pm_service/pm_ipi.c		\
+				plat/xilinx/zynqmp/pm_service/pm_client.c
+
+ifneq (${RESET_TO_BL31},1)
+  $(error "Using BL31 as the reset vector is only one option supported on ZynqMP. Please set RESET_TO_BL31 to 1.")
+endif
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
new file mode 100644
index 0000000..2f2e2ed
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
@@ -0,0 +1,485 @@
+/*
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * ZynqMP system level PM-API functions and communication with PMU via
+ * IPI interrupts
+ */
+
+#include <arch_helpers.h>
+#include <platform.h>
+#include "pm_client.h"
+#include "pm_common.h"
+#include "pm_api_sys.h"
+
+/**
+ * Assigning of argument values into array elements.
+ */
+#define PM_PACK_PAYLOAD1(pl, arg0) {	\
+	pl[0] = (uint32_t)(arg0);	\
+}
+
+#define PM_PACK_PAYLOAD2(pl, arg0, arg1) {	\
+	pl[1] = (uint32_t)(arg1);		\
+	PM_PACK_PAYLOAD1(pl, arg0);		\
+}
+
+#define PM_PACK_PAYLOAD3(pl, arg0, arg1, arg2) {	\
+	pl[2] = (uint32_t)(arg2);			\
+	PM_PACK_PAYLOAD2(pl, arg0, arg1);		\
+}
+
+#define PM_PACK_PAYLOAD4(pl, arg0, arg1, arg2, arg3) {	\
+	pl[3] = (uint32_t)(arg3);			\
+	PM_PACK_PAYLOAD3(pl, arg0, arg1, arg2);		\
+}
+
+#define PM_PACK_PAYLOAD5(pl, arg0, arg1, arg2, arg3, arg4) {	\
+	pl[4] = (uint32_t)(arg4);				\
+	PM_PACK_PAYLOAD4(pl, arg0, arg1, arg2, arg3);		\
+}
+
+#define PM_PACK_PAYLOAD6(pl, arg0, arg1, arg2, arg3, arg4, arg5) {	\
+	pl[5] = (uint32_t)(arg5);					\
+	PM_PACK_PAYLOAD5(pl, arg0, arg1, arg2, arg3, arg4);		\
+}
+
+/**
+ * pm_self_suspend() - PM call for processor to suspend itself
+ * @nid		Node id of the processor or subsystem
+ * @latency	Requested maximum wakeup latency (not supported)
+ * @state	Requested state (not supported)
+ * @address	Resume address
+ *
+ * This is a blocking call, it will return only once PMU has responded.
+ * On a wakeup, resume address will be automatically set by PMU.
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_self_suspend(enum pm_node_id nid,
+				   unsigned int latency,
+				   unsigned int state,
+				   uintptr_t address)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+	unsigned int cpuid = plat_my_core_pos();
+	const struct pm_proc *proc = pm_get_proc(cpuid);
+
+	/*
+	 * Do client specific suspend operations
+	 * (e.g. set powerdown request bit)
+	 */
+	pm_client_suspend(proc);
+	/* Send request to the PMU */
+	PM_PACK_PAYLOAD6(payload, PM_SELF_SUSPEND, proc->node_id, latency,
+			 state, address, (address >> 32));
+	return pm_ipi_send_sync(proc, payload, NULL);
+}
+
+/**
+ * pm_req_suspend() - PM call to request for another PU or subsystem to
+ *		      be suspended gracefully.
+ * @target	Node id of the targeted PU or subsystem
+ * @ack		Flag to specify whether acknowledge is requested
+ * @latency	Requested wakeup latency (not supported)
+ * @state	Requested state (not supported)
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_req_suspend(enum pm_node_id target,
+				  enum pm_request_ack ack,
+				  unsigned int latency, unsigned int state)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMU */
+	PM_PACK_PAYLOAD5(payload, PM_REQ_SUSPEND, target, ack, latency, state);
+	if (ack == REQ_ACK_BLOCKING)
+		return pm_ipi_send_sync(primary_proc, payload, NULL);
+	else
+		return pm_ipi_send(primary_proc, payload);
+}
+
+/**
+ * pm_req_wakeup() - PM call for processor to wake up selected processor
+ *		     or subsystem
+ * @target	Node id of the processor or subsystem to wake up
+ * @ack		Flag to specify whether acknowledge requested
+ * @set_address	Resume address presence indicator
+ *				1 resume address specified, 0 otherwise
+ * @address	Resume address
+ *
+ * This API function is either used to power up another APU core for SMP
+ * (by PSCI) or to power up an entirely different PU or subsystem, such
+ * as RPU0, RPU, or PL_CORE_xx. Resume address for the target PU will be
+ * automatically set by PMU.
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_req_wakeup(enum pm_node_id target,
+				 unsigned int set_address,
+				 uintptr_t address,
+				 enum pm_request_ack ack)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+	uint64_t encoded_address;
+	const struct pm_proc *proc = pm_get_proc_by_node(target);
+
+	/* invoke APU-specific code for waking up another APU core */
+	pm_client_wakeup(proc);
+
+	/* encode set Address into 1st bit of address */
+	encoded_address = address;
+	encoded_address |= !!set_address;
+
+	/* Send request to the PMU to perform the wake of the PU */
+	PM_PACK_PAYLOAD5(payload, PM_REQ_WAKEUP, target, encoded_address,
+			 encoded_address >> 32, ack);
+
+	if (ack == REQ_ACK_BLOCKING)
+		return pm_ipi_send_sync(primary_proc, payload, NULL);
+	else
+		return pm_ipi_send(primary_proc, payload);
+}
+
+/**
+ * pm_force_powerdown() - PM call to request for another PU or subsystem to
+ *			  be powered down forcefully
+ * @target	Node id of the targeted PU or subsystem
+ * @ack		Flag to specify whether acknowledge is requested
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_force_powerdown(enum pm_node_id target,
+				      enum pm_request_ack ack)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMU */
+	PM_PACK_PAYLOAD3(payload, PM_FORCE_POWERDOWN, target, ack);
+
+	if (ack == REQ_ACK_BLOCKING)
+		return pm_ipi_send_sync(primary_proc, payload, NULL);
+	else
+		return pm_ipi_send(primary_proc, payload);
+}
+
+/**
+ * pm_abort_suspend() - PM call to announce that a prior suspend request
+ *			is to be aborted.
+ * @reason	Reason for the abort
+ *
+ * Calling PU expects the PMU to abort the initiated suspend procedure.
+ * This is a non-blocking call without any acknowledge.
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/*
+	 * Do client specific abort suspend operations
+	 * (e.g. enable interrupts and clear powerdown request bit)
+	 */
+	pm_client_abort_suspend();
+	/* Send request to the PMU */
+	/* TODO: allow passing the node ID of the affected CPU */
+	PM_PACK_PAYLOAD3(payload, PM_ABORT_SUSPEND, reason,
+			 primary_proc->node_id);
+	return pm_ipi_send(primary_proc, payload);
+}
+
+/**
+ * pm_set_wakeup_source() - PM call to specify the wakeup source while suspended
+ * @target	Node id of the targeted PU or subsystem
+ * @wkup_node	Node id of the wakeup peripheral
+ * @enable	Enable or disable the specified peripheral as wake source
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_set_wakeup_source(enum pm_node_id target,
+					enum pm_node_id wkup_node,
+					unsigned int enable)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	PM_PACK_PAYLOAD4(payload, PM_SET_WAKEUP_SOURCE, target, wkup_node,
+			 enable);
+	return pm_ipi_send(primary_proc, payload);
+}
+
+/**
+ * pm_system_shutdown() - PM call to request a system shutdown or restart
+ * @restart	Shutdown or restart? 0 for shutdown, 1 for restart
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_system_shutdown(unsigned int restart)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	PM_PACK_PAYLOAD2(payload, PM_SYSTEM_SHUTDOWN, restart);
+	return pm_ipi_send(primary_proc, payload);
+}
+
+/* APIs for managing PM slaves: */
+
+/**
+ * pm_req_node() - PM call to request a node with specific capabilities
+ * @nid		Node id of the slave
+ * @capabilities Requested capabilities of the slave
+ * @qos		Quality of service (not supported)
+ * @ack		Flag to specify whether acknowledge is requested
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_req_node(enum pm_node_id nid,
+			       unsigned int capabilities,
+			       unsigned int qos,
+			       enum pm_request_ack ack)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	PM_PACK_PAYLOAD5(payload, PM_REQ_NODE, nid, capabilities, qos, ack);
+
+	if (ack == REQ_ACK_BLOCKING)
+		return pm_ipi_send_sync(primary_proc, payload, NULL);
+	else
+		return pm_ipi_send(primary_proc, payload);
+}
+
+/**
+ * pm_set_requirement() - PM call to set requirement for PM slaves
+ * @nid		Node id of the slave
+ * @capabilities Requested capabilities of the slave
+ * @qos		Quality of service (not supported)
+ * @ack		Flag to specify whether acknowledge is requested
+ *
+ * This API function is to be used for slaves a PU already has requested
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_set_requirement(enum pm_node_id nid,
+				      unsigned int capabilities,
+				      unsigned int qos,
+				      enum pm_request_ack ack)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	PM_PACK_PAYLOAD5(payload, PM_SET_REQUIREMENT, nid, capabilities, qos,
+			 ack);
+
+	if (ack == REQ_ACK_BLOCKING)
+		return pm_ipi_send_sync(primary_proc, payload, NULL);
+	else
+		return pm_ipi_send(primary_proc, payload);
+}
+
+/**
+ * pm_release_node() - PM call to release a node
+ * @nid		Node id of the slave
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_release_node(enum pm_node_id nid)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	PM_PACK_PAYLOAD2(payload, PM_RELEASE_NODE, nid);
+	return pm_ipi_send(primary_proc, payload);
+}
+
+/**
+ * pm_set_max_latency() - PM call to set wakeup latency requirements
+ * @nid		Node id of the slave
+ * @latency	Requested maximum wakeup latency
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_set_max_latency(enum pm_node_id nid,
+				      unsigned int latency)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	PM_PACK_PAYLOAD3(payload, PM_SET_MAX_LATENCY, nid, latency);
+	return pm_ipi_send(primary_proc, payload);
+}
+
+/* Miscellaneous API functions */
+
+/**
+ * pm_get_api_version() - Get version number of PMU PM firmware
+ * @version	Returns 32-bit version number of PMU Power Management Firmware
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_get_api_version(unsigned int *version)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMU */
+	PM_PACK_PAYLOAD1(payload, PM_GET_API_VERSION);
+	return pm_ipi_send_sync(primary_proc, payload, version);
+}
+
+/**
+ * pm_set_configuration() - PM call to set system configuration
+ * @phys_addr	Physical 32-bit address of data structure in memory
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_set_configuration(unsigned int phys_addr)
+{
+	return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/**
+ * pm_get_node_status() - PM call to request a node's current power state
+ * @nid		Node id of the slave
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_get_node_status(enum pm_node_id nid)
+{
+	/* TODO: Add power state argument!! */
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	PM_PACK_PAYLOAD2(payload, PM_GET_NODE_STATUS, nid);
+	return pm_ipi_send(primary_proc, payload);
+}
+
+/**
+ * pm_register_notifier() - Register the PU to be notified of PM events
+ * @nid		Node id of the slave
+ * @event	The event to be notified about
+ * @wake	Wake up on event
+ * @enable	Enable or disable the notifier
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_register_notifier(enum pm_node_id nid,
+					unsigned int event,
+					unsigned int wake,
+					unsigned int enable)
+{
+	return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/**
+ * pm_get_op_characteristic() - PM call to get a particular operating
+ *				characteristic of a node
+ * @nid	Node ID
+ * @type	Operating characterstic type to be returned
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_get_op_characteristic(enum pm_node_id nid,
+					    enum pm_opchar_type type)
+{
+	return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/* Direct-Control API functions */
+
+/**
+ * pm_reset_assert() - Assert reset
+ * @reset	Reset ID
+ * @assert	Assert (1) or de-assert (0)
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_reset_assert(unsigned int reset,
+				   unsigned int assert)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMU */
+	PM_PACK_PAYLOAD3(payload, PM_RESET_ASSERT, reset, assert);
+	return pm_ipi_send(primary_proc, payload);
+}
+
+/**
+ * pm_reset_get_status() - Get current status of a reset line
+ * @reset	Reset ID
+ * @reset_status Returns current status of selected reset line
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_reset_get_status(unsigned int reset,
+				       unsigned int *reset_status)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMU */
+	PM_PACK_PAYLOAD2(payload, PM_RESET_GET_STATUS, reset);
+	return pm_ipi_send_sync(primary_proc, payload, reset_status);
+}
+
+/**
+ * pm_mmio_write() - Perform write to protected mmio
+ * @address	Address to write to
+ * @mask	Mask to apply
+ * @value	Value to write
+ *
+ * This function provides access to PM-related control registers
+ * that may not be directly accessible by a particular PU.
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_mmio_write(uintptr_t address,
+				 unsigned int mask,
+				 unsigned int value)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMU */
+	PM_PACK_PAYLOAD4(payload, PM_MMIO_WRITE, address, mask, value);
+	return pm_ipi_send(primary_proc, payload);
+}
+
+/**
+ * pm_mmio_read() - Read value from protected mmio
+ * @address	Address to write to
+ * @value	Value to write
+ *
+ * This function provides access to PM-related control registers
+ * that may not be directly accessible by a particular PU.
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_mmio_read(uintptr_t address, unsigned int *value)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMU */
+	PM_PACK_PAYLOAD2(payload, PM_MMIO_READ, address);
+	return pm_ipi_send_sync(primary_proc, payload, value);
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
new file mode 100644
index 0000000..f0365cd
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _PM_API_SYS_H_
+#define _PM_API_SYS_H_
+
+#include <stdint.h>
+#include "pm_defs.h"
+
+/**********************************************************
+ * System-level API function declarations
+ **********************************************************/
+enum pm_ret_status pm_req_suspend(enum pm_node_id nid,
+				  enum pm_request_ack ack,
+				  unsigned int latency,
+				  unsigned int state);
+
+enum pm_ret_status pm_self_suspend(enum pm_node_id nid,
+				   unsigned int latency,
+				   unsigned int state,
+				   uintptr_t address);
+
+enum pm_ret_status pm_force_powerdown(enum pm_node_id nid,
+				      enum pm_request_ack ack);
+
+enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason);
+
+enum pm_ret_status pm_req_wakeup(enum pm_node_id nid,
+				 unsigned int set_address,
+				 uintptr_t address,
+				 enum pm_request_ack ack);
+
+enum pm_ret_status pm_set_wakeup_source(enum pm_node_id target,
+					enum pm_node_id wkup_node,
+					unsigned int enable);
+
+enum pm_ret_status pm_system_shutdown(unsigned int restart);
+
+enum pm_ret_status pm_init_suspend_cb(enum pm_suspend_reason reason,
+				      unsigned int latency,
+				      unsigned int state,
+				      unsigned int timeout);
+
+/* API functions for managing PM Slaves */
+enum pm_ret_status pm_req_node(enum pm_node_id nid,
+			       unsigned int capabilities,
+			       unsigned int qos,
+			       enum pm_request_ack ack);
+enum pm_ret_status pm_release_node(enum pm_node_id nid);
+
+enum pm_ret_status pm_set_requirement(enum pm_node_id nid,
+				      unsigned int capabilities,
+				      unsigned int qos,
+				      enum pm_request_ack ack);
+enum pm_ret_status pm_set_max_latency(enum pm_node_id nid,
+				      unsigned int latency);
+
+/* Miscellaneous API functions */
+enum pm_ret_status pm_get_api_version(unsigned int *version);
+enum pm_ret_status pm_set_configuration(unsigned int phys_addr);
+enum pm_ret_status pm_get_node_status(enum pm_node_id node);
+enum pm_ret_status pm_register_notifier(enum pm_node_id nid,
+					unsigned int event,
+					unsigned int wake,
+					unsigned int enable);
+enum pm_ret_status pm_get_op_characteristic(enum pm_node_id nid,
+					    enum pm_opchar_type type);
+enum pm_ret_status pm_acknowledge_cb(enum pm_node_id nid,
+				     enum pm_ret_status status,
+				     unsigned int oppoint);
+enum pm_ret_status pm_notify_cb(enum pm_node_id nid,
+				unsigned int event,
+				unsigned int oppoint);
+
+/* Direct-Control API functions */
+enum pm_ret_status pm_reset_assert(unsigned int reset_id,
+				   unsigned int assert);
+enum pm_ret_status pm_reset_get_status(unsigned int reset_id,
+				       unsigned int *reset_status);
+enum pm_ret_status pm_mmio_write(uintptr_t address,
+				 unsigned int mask,
+				 unsigned int value);
+enum pm_ret_status pm_mmio_read(uintptr_t address, unsigned int *value);
+#endif /* _PM_API_SYS_H_ */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_client.c b/plat/xilinx/zynqmp/pm_service/pm_client.c
new file mode 100644
index 0000000..eb986bc
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_client.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * APU specific definition of processors in the subsystem as well as functions
+ * for getting information about and changing state of the APU.
+ */
+
+#include <gicv2.h>
+#include <bl_common.h>
+#include <mmio.h>
+#include "pm_api_sys.h"
+#include "pm_client.h"
+#include "pm_ipi.h"
+#include "../zynqmp_def.h"
+
+#define OCM_BANK_0	0xFFFC0000
+#define OCM_BANK_1	(OCM_BANK_0 + 0x10000)
+#define OCM_BANK_2	(OCM_BANK_1 + 0x10000)
+#define OCM_BANK_3	(OCM_BANK_2 + 0x10000)
+
+#define UNDEFINED_CPUID		(~0)
+
+/* Declaration of linker defined symbol */
+extern unsigned long __BL31_END__;
+extern const struct pm_ipi apu_ipi;
+
+/* Order in pm_procs_all array must match cpu ids */
+static const struct pm_proc const pm_procs_all[] = {
+	{
+		.node_id = NODE_APU_0,
+		.pwrdn_mask = APU_0_PWRCTL_CPUPWRDWNREQ_MASK,
+		.ipi = &apu_ipi,
+	},
+	{
+		.node_id = NODE_APU_1,
+		.pwrdn_mask = APU_1_PWRCTL_CPUPWRDWNREQ_MASK,
+		.ipi = &apu_ipi,
+	},
+	{
+		.node_id = NODE_APU_2,
+		.pwrdn_mask = APU_2_PWRCTL_CPUPWRDWNREQ_MASK,
+		.ipi = &apu_ipi,
+	},
+	{
+		.node_id = NODE_APU_3,
+		.pwrdn_mask = APU_3_PWRCTL_CPUPWRDWNREQ_MASK,
+		.ipi = &apu_ipi,
+	},
+};
+
+/**
+ * set_ocm_retention() - Configure OCM memory banks for retention
+ *
+ * APU specific requirements for suspend action:
+ * OCM has to enter retention state in order to preserve saved
+ * context after suspend request. OCM banks are determined by
+ * __BL31_END__ linker symbol.
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+enum pm_ret_status set_ocm_retention(void)
+{
+	enum pm_ret_status ret;
+
+	/* OCM_BANK_0 will always be occupied */
+	ret = pm_set_requirement(NODE_OCM_BANK_0, PM_CAP_CONTEXT, 0,
+				 REQ_ACK_NO);
+
+	/* Check for other OCM banks  */
+	if ((unsigned long)&__BL31_END__ >= OCM_BANK_1)
+		ret = pm_set_requirement(NODE_OCM_BANK_1, PM_CAP_CONTEXT, 0,
+					 REQ_ACK_NO);
+	if ((unsigned long)&__BL31_END__ >= OCM_BANK_2)
+		ret = pm_set_requirement(NODE_OCM_BANK_2, PM_CAP_CONTEXT, 0,
+					 REQ_ACK_NO);
+	if ((unsigned long)&__BL31_END__ >= OCM_BANK_3)
+		ret = pm_set_requirement(NODE_OCM_BANK_3, PM_CAP_CONTEXT, 0,
+					 REQ_ACK_NO);
+
+	return ret;
+}
+
+/**
+ * pm_get_proc() - returns pointer to the proc structure
+ * @cpuid:	id of the cpu whose proc struct pointer should be returned
+ *
+ * Return: pointer to a proc structure if proc is found, otherwise NULL
+ */
+const struct pm_proc *pm_get_proc(unsigned int cpuid)
+{
+	if (cpuid < ARRAY_SIZE(pm_procs_all))
+		return &pm_procs_all[cpuid];
+
+	return NULL;
+}
+
+/**
+ * pm_get_proc_by_node() - returns pointer to the proc structure
+ * @nid:	node id of the processor
+ *
+ * Return: pointer to a proc structure if proc is found, otherwise NULL
+ */
+const struct pm_proc *pm_get_proc_by_node(enum pm_node_id nid)
+{
+	for (size_t i = 0; i < ARRAY_SIZE(pm_procs_all); i++) {
+		if (nid == pm_procs_all[i].node_id)
+			return &pm_procs_all[i];
+	}
+	return NULL;
+}
+
+/**
+ * pm_get_cpuid() - get the local cpu ID for a global node ID
+ * @nid:	node id of the processor
+ *
+ * Return: the cpu ID (starting from 0) for the subsystem
+ */
+static unsigned int pm_get_cpuid(enum pm_node_id nid)
+{
+	for (size_t i = 0; i < ARRAY_SIZE(pm_procs_all); i++) {
+		if (pm_procs_all[i].node_id == nid)
+			return i;
+	}
+	return UNDEFINED_CPUID;
+}
+
+const struct pm_proc *primary_proc = &pm_procs_all[0];
+
+/**
+ * pm_client_suspend() - Client-specific suspend actions
+ *
+ * This function should contain any PU-specific actions
+ * required prior to sending suspend request to PMU
+ */
+void pm_client_suspend(const struct pm_proc *proc)
+{
+	/* Set powerdown request */
+	mmio_write_32(APU_PWRCTL, mmio_read_32(APU_PWRCTL) | proc->pwrdn_mask);
+}
+
+
+/**
+ * pm_client_abort_suspend() - Client-specific abort-suspend actions
+ *
+ * This function should contain any PU-specific actions
+ * required for aborting a prior suspend request
+ */
+void pm_client_abort_suspend(void)
+{
+	/* Enable interrupts at processor level (for current cpu) */
+	gicv2_cpuif_enable();
+	/* Clear powerdown request */
+	mmio_write_32(APU_PWRCTL,
+		 mmio_read_32(APU_PWRCTL) & ~primary_proc->pwrdn_mask);
+}
+
+/**
+ * pm_client_wakeup() - Client-specific wakeup actions
+ *
+ * This function should contain any PU-specific actions
+ * required for waking up another APU core
+ */
+void pm_client_wakeup(const struct pm_proc *proc)
+{
+	unsigned int cpuid = pm_get_cpuid(proc->node_id);
+
+	if (cpuid == UNDEFINED_CPUID)
+		return;
+
+	/* clear powerdown bit for affected cpu */
+	uint32_t val = mmio_read_32(APU_PWRCTL);
+	val &= ~(proc->pwrdn_mask);
+	mmio_write_32(APU_PWRCTL, val);
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_client.h b/plat/xilinx/zynqmp/pm_service/pm_client.h
new file mode 100644
index 0000000..b9f196d
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_client.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Contains APU specific macros and macros to be defined depending on
+ * the execution environment.
+ */
+
+#ifndef _PM_CLIENT_H_
+#define _PM_CLIENT_H_
+
+#include "pm_defs.h"
+#include "pm_common.h"
+
+/* Functions to be implemented by each PU */
+enum pm_ret_status pm_ipi_send(const struct pm_proc *proc,
+			       uint32_t payload[PAYLOAD_ARG_CNT]);
+enum pm_ret_status pm_ipi_send_sync(const struct pm_proc *proc,
+				    uint32_t payload[PAYLOAD_ARG_CNT],
+				    uint32_t *val);
+void pm_client_suspend(const struct pm_proc *proc);
+void pm_client_abort_suspend(void);
+void pm_client_wakeup(const struct pm_proc *proc);
+enum pm_ret_status set_ocm_retention(void);
+
+/* Global variables to be set in pm_client.c */
+extern const struct pm_proc *primary_proc;
+
+#endif /* _PM_CLIENT_H_ */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_common.h b/plat/xilinx/zynqmp/pm_service/pm_common.h
new file mode 100644
index 0000000..b432a83
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_common.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Contains definitions of commonly used macros and data types needed
+ * for PU Power Management. This file should be common for all PU's.
+ */
+
+#ifndef _PM_COMMON_H_
+#define _PM_COMMON_H_
+
+#include <debug.h>
+#include <stdint.h>
+#include "pm_defs.h"
+
+#define PAYLOAD_ARG_CNT		6U
+#define PAYLOAD_ARG_SIZE	4U	/* size in bytes */
+
+/**
+ * pm_ipi - struct for capturing IPI-channel specific info
+ * @mask	mask for enabling/disabling and triggering the IPI
+ * @base	base address for IPI
+ * @buffer_base	base address for payload buffer
+ */
+struct pm_ipi {
+	const unsigned int mask;
+	const uintptr_t base;
+	const uintptr_t buffer_base;
+};
+
+/**
+ * pm_proc - struct for capturing processor related info
+ * @node_id	node-ID of the processor
+ * @pwrdn_mask	cpu-specific mask to be used for power control register
+ * @ipi		pointer to IPI channel structure
+ *		(in APU all processors share one IPI channel)
+ */
+struct pm_proc {
+	const enum pm_node_id node_id;
+	const unsigned int pwrdn_mask;
+	const struct pm_ipi *ipi;
+};
+
+const struct pm_proc *pm_get_proc(unsigned int cpuid);
+const struct pm_proc *pm_get_proc_by_node(enum pm_node_id nid);
+
+#endif /* _PM_COMMON_H_ */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h
new file mode 100644
index 0000000..08f4aab
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* ZynqMP power management enums and defines */
+
+#ifndef _PM_DEFS_H_
+#define _PM_DEFS_H_
+
+/*********************************************************************
+ * Macro definitions
+ ********************************************************************/
+
+/*
+ * Version number is a 32bit value, like:
+ * (PM_VERSION_MAJOR << 16) | PM_VERSION_MINOR
+ */
+#define PM_VERSION_MAJOR	0
+#define PM_VERSION_MINOR	2
+
+#define PM_VERSION	((PM_VERSION_MAJOR << 16) | PM_VERSION_MINOR)
+
+/* Capabilities for RAM */
+#define PM_CAP_ACCESS	0x1U
+#define PM_CAP_CONTEXT	0x2U
+
+#define MAX_LATENCY	(~0U)
+#define MAX_QOS		100U
+
+/*********************************************************************
+ * Enum definitions
+ ********************************************************************/
+
+enum pm_api_id {
+	/* Miscellaneous API functions: */
+	PM_GET_API_VERSION = 1, /* Do not change or move */
+	PM_SET_CONFIGURATION,
+	PM_GET_NODE_STATUS,
+	PM_GET_OP_CHARACTERISTIC,
+	PM_REGISTER_NOTIFIER,
+	/* API for suspending of PUs: */
+	PM_REQ_SUSPEND,
+	PM_SELF_SUSPEND,
+	PM_FORCE_POWERDOWN,
+	PM_ABORT_SUSPEND,
+	PM_REQ_WAKEUP,
+	PM_SET_WAKEUP_SOURCE,
+	PM_SYSTEM_SHUTDOWN,
+	/* API for managing PM slaves: */
+	PM_REQ_NODE,
+	PM_RELEASE_NODE,
+	PM_SET_REQUIREMENT,
+	PM_SET_MAX_LATENCY,
+	/* Direct control API functions: */
+	PM_RESET_ASSERT,
+	PM_RESET_GET_STATUS,
+	PM_MMIO_WRITE,
+	PM_MMIO_READ,
+	PM_API_MAX
+};
+
+enum pm_node_id {
+	NODE_UNKNOWN = 0,
+	NODE_APU,
+	NODE_APU_0,
+	NODE_APU_1,
+	NODE_APU_2,
+	NODE_APU_3,
+	NODE_RPU,
+	NODE_RPU_0,
+	NODE_RPU_1,
+	NODE_PL,
+	NODE_FPD,
+	NODE_OCM_BANK_0,
+	NODE_OCM_BANK_1,
+	NODE_OCM_BANK_2,
+	NODE_OCM_BANK_3,
+	NODE_TCM_0_A,
+	NODE_TCM_0_B,
+	NODE_TCM_1_A,
+	NODE_TCM_1_B,
+	NODE_L2,
+	NODE_GPU_PP_0,
+	NODE_GPU_PP_1,
+	NODE_USB_0,
+	NODE_USB_1,
+	NODE_TTC_0,
+	NODE_TTC_1,
+	NODE_TTC_2,
+	NODE_TTC_3,
+	NODE_SATA,
+	NODE_ETH_0,
+	NODE_ETH_1,
+	NODE_ETH_2,
+	NODE_ETH_3,
+	NODE_UART_0,
+	NODE_UART_1,
+	NODE_SPI_0,
+	NODE_SPI_1,
+	NODE_I2C_0,
+	NODE_I2C_1,
+	NODE_SD_0,
+	NODE_SD_1,
+	NODE_DP,
+	NODE_GDMA,
+	NODE_ADMA,
+	NODE_NAND,
+	NODE_QSPI,
+	NODE_GPIO,
+	NODE_CAN_0,
+	NODE_CAN_1,
+	NODE_AFI,
+	NODE_APLL,
+	NODE_VPLL,
+	NODE_DPLL,
+	NODE_RPLL,
+	NODE_IOPLL,
+	NODE_DDR,
+};
+
+enum pm_request_ack {
+	REQ_ACK_NO = 1,
+	REQ_ACK_BLOCKING,
+	REQ_ACK_NON_BLOCKING,
+};
+
+enum pm_abort_reason {
+	ABORT_REASON_WKUP_EVENT = 100,
+	ABORT_REASON_PU_BUSY,
+	ABORT_REASON_NO_PWRDN,
+	ABORT_REASON_UNKNOWN,
+};
+
+enum pm_suspend_reason {
+	SUSPEND_REASON_PU_REQ = 201,
+	SUSPEND_REASON_ALERT,
+	SUSPEND_REASON_SYS_SHUTDOWN,
+};
+
+enum pm_ram_state {
+	PM_RAM_STATE_OFF = 1,
+	PM_RAM_STATE_RETENTION,
+	PM_RAM_STATE_ON,
+};
+
+enum pm_opchar_type {
+	PM_OPCHAR_TYPE_POWER = 1,
+	PM_OPCHAR_TYPE_ENERGY,
+	PM_OPCHAR_TYPE_TEMP,
+};
+
+/**
+ * @PM_RET_SUCCESS:		success
+ * @PM_RET_ERROR_ARGS:		illegal arguments provided
+ * @PM_RET_ERROR_ACCESS:	access rights violation
+ * @PM_RET_ERROR_TIMEOUT:	timeout in communication with PMU
+ * @PM_RET_ERROR_NOTSUPPORTED:	feature not supported
+ * @PM_RET_ERROR_PROC:		node is not a processor node
+ * @PM_RET_ERROR_API_ID:	illegal API ID
+ * @PM_RET_ERROR_OTHER:		other error
+ */
+enum pm_ret_status {
+	PM_RET_SUCCESS,
+	PM_RET_ERROR_ARGS,
+	PM_RET_ERROR_ACCESS,
+	PM_RET_ERROR_TIMEOUT,
+	PM_RET_ERROR_NOTSUPPORTED,
+	PM_RET_ERROR_PROC,
+	PM_RET_ERROR_API_ID,
+	PM_RET_ERROR_FAILURE,
+	PM_RET_ERROR_COMMUNIC,
+	PM_RET_ERROR_DOUBLEREQ,
+	PM_RET_ERROR_OTHER,
+};
+
+/**
+ * @PM_INITIAL_BOOT:	boot is a fresh system startup
+ * @PM_RESUME:		boot is a resume
+ * @PM_BOOT_ERROR:	error, boot cause cannot be identified
+ */
+enum pm_boot_status {
+	PM_INITIAL_BOOT,
+	PM_RESUME,
+	PM_BOOT_ERROR,
+};
+
+#endif /* _PM_DEFS_H_ */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_ipi.c b/plat/xilinx/zynqmp/pm_service/pm_ipi.c
new file mode 100644
index 0000000..ef2b4fe
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_ipi.c
@@ -0,0 +1,247 @@
+/*
+ * 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 <bakery_lock.h>
+#include <mmio.h>
+#include <platform.h>
+#include <arch_helpers.h>
+#include "pm_ipi.h"
+#include "../zynqmp_private.h"
+
+/* IPI message buffers */
+#define IPI_BUFFER_BASEADDR	0xFF990000U
+
+#define IPI_BUFFER_RPU_0_BASE	(IPI_BUFFER_BASEADDR + 0x0U)
+#define IPI_BUFFER_RPU_1_BASE	(IPI_BUFFER_BASEADDR + 0x200U)
+#define IPI_BUFFER_APU_BASE	(IPI_BUFFER_BASEADDR + 0x400U)
+#define IPI_BUFFER_PL_0_BASE	(IPI_BUFFER_BASEADDR + 0x600U)
+#define IPI_BUFFER_PL_1_BASE	(IPI_BUFFER_BASEADDR + 0x800U)
+#define IPI_BUFFER_PL_2_BASE	(IPI_BUFFER_BASEADDR + 0xA00U)
+#define IPI_BUFFER_PL_3_BASE	(IPI_BUFFER_BASEADDR + 0xC00U)
+#define IPI_BUFFER_PMU_BASE	(IPI_BUFFER_BASEADDR + 0xE00U)
+
+#define IPI_BUFFER_TARGET_RPU_0_OFFSET	0x0U
+#define IPI_BUFFER_TARGET_RPU_1_OFFSET	0x40U
+#define IPI_BUFFER_TARGET_APU_OFFSET	0x80U
+#define IPI_BUFFER_TARGET_PL_0_OFFSET	0xC0U
+#define IPI_BUFFER_TARGET_PL_1_OFFSET	0x100U
+#define IPI_BUFFER_TARGET_PL_2_OFFSET	0x140U
+#define IPI_BUFFER_TARGET_PL_3_OFFSET	0x180U
+#define IPI_BUFFER_TARGET_PMU_OFFSET	0x1C0U
+
+#define IPI_BUFFER_REQ_OFFSET	0x0U
+#define IPI_BUFFER_RESP_OFFSET	0x20U
+
+/* IPI Base Address */
+#define IPI_BASEADDR		0XFF300000
+
+/* APU's IPI registers */
+#define IPI_APU_ISR		(IPI_BASEADDR + 0X00000010)
+#define IPI_APU_IER		(IPI_BASEADDR + 0X00000018)
+#define IPI_APU_IDR		(IPI_BASEADDR + 0X0000001C)
+#define IPI_APU_ISR_PMU_0_MASK		0X00010000
+#define IPI_APU_IER_PMU_0_MASK		0X00010000
+
+#define IPI_TRIG_OFFSET		0
+#define IPI_OBS_OFFSET		4
+
+/* Power Management IPI interrupt number */
+#define PM_INT_NUM		0
+#define IPI_PMU_PM_INT_BASE	(IPI_PMU_0_TRIG + (PM_INT_NUM * 0x1000))
+#define IPI_PMU_PM_INT_MASK	(IPI_APU_ISR_PMU_0_MASK << PM_INT_NUM)
+#if (PM_INT_NUM < 0 || PM_INT_NUM > 3)
+	#error PM_INT_NUM value out of range
+#endif
+
+#define IPI_APU_MASK		1U
+
+static bakery_lock_t pm_secure_lock;
+
+const struct pm_ipi apu_ipi = {
+	.mask = IPI_APU_MASK,
+	.base = IPI_BASEADDR,
+	.buffer_base = IPI_BUFFER_APU_BASE,
+};
+
+/**
+ * pm_ipi_init() - Initialize IPI peripheral for communication with PMU
+ *
+ * @return	On success, the initialization function must return 0.
+ *		Any other return value will cause the framework to ignore
+ *		the service
+ *
+ * Enable interrupts at registered entrance in IPI peripheral
+ * Called from pm_setup initialization function
+ */
+int pm_ipi_init(void)
+{
+	bakery_lock_init(&pm_secure_lock);
+
+	/* IPI Interrupts Clear & Disable */
+	mmio_write_32(IPI_APU_ISR, 0xffffffff);
+	mmio_write_32(IPI_APU_IDR, 0xffffffff);
+
+	return 0;
+}
+
+/**
+ * pm_ipi_wait() - wait for pmu to handle request
+ * @proc	proc which is waiting for PMU to handle request
+ */
+static enum pm_ret_status pm_ipi_wait(const struct pm_proc *proc)
+{
+	int status;
+
+	/* Wait until previous interrupt is handled by PMU */
+	do {
+		status = mmio_read_32(proc->ipi->base + IPI_OBS_OFFSET) &
+					IPI_PMU_PM_INT_MASK;
+		/* TODO: 1) Use timer to add delay between read attempts */
+		/* TODO: 2) Return PM_RET_ERR_TIMEOUT if this times out */
+	} while (status);
+
+	return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_ipi_send_common() - Sends IPI request to the PMU
+ * @proc	Pointer to the processor who is initiating request
+ * @payload	API id and call arguments to be written in IPI buffer
+ *
+ * Send an IPI request to the power controller. Caller needs to hold
+ * the 'pm_secure_lock' lock.
+ *
+ * @return	Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ipi_send_common(const struct pm_proc *proc,
+					     uint32_t payload[PAYLOAD_ARG_CNT])
+{
+	unsigned int offset = 0;
+	uintptr_t buffer_base = proc->ipi->buffer_base +
+					IPI_BUFFER_TARGET_PMU_OFFSET +
+					IPI_BUFFER_REQ_OFFSET;
+
+	/* Wait until previous interrupt is handled by PMU */
+	pm_ipi_wait(proc);
+
+	/* Write payload into IPI buffer */
+	for (size_t i = 0; i < PAYLOAD_ARG_CNT; i++) {
+		mmio_write_32(buffer_base + offset, payload[i]);
+		offset += PAYLOAD_ARG_SIZE;
+	}
+	/* Generate IPI to PMU */
+	mmio_write_32(proc->ipi->base + IPI_TRIG_OFFSET, IPI_PMU_PM_INT_MASK);
+
+	return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_ipi_send() - Sends IPI request to the PMU
+ * @proc	Pointer to the processor who is initiating request
+ * @payload	API id and call arguments to be written in IPI buffer
+ *
+ * Send an IPI request to the power controller.
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_ipi_send(const struct pm_proc *proc,
+			       uint32_t payload[PAYLOAD_ARG_CNT])
+{
+	enum pm_ret_status ret;
+
+	bakery_lock_get(&pm_secure_lock);
+
+	ret = pm_ipi_send_common(proc, payload);
+
+	bakery_lock_release(&pm_secure_lock);
+
+	return ret;
+}
+
+
+/**
+ * pm_ipi_buff_read() - Reads IPI response after PMU has handled interrupt
+ * @proc	Pointer to the processor who is waiting and reading response
+ * @value	Used to return value from 2nd IPI buffer element (optional)
+ *
+ * @return	Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ipi_buff_read(const struct pm_proc *proc,
+					   unsigned int *value)
+{
+	uintptr_t buffer_base = proc->ipi->buffer_base +
+				IPI_BUFFER_TARGET_PMU_OFFSET +
+				IPI_BUFFER_RESP_OFFSET;
+
+	pm_ipi_wait(proc);
+
+	/*
+	 * Read response from IPI buffer
+	 * buf-0: success or error+reason
+	 * buf-1: value
+	 * buf-2: unused
+	 * buf-3: unused
+	 */
+	if (value != NULL)
+		*value = mmio_read_32(buffer_base + PAYLOAD_ARG_SIZE);
+
+	return mmio_read_32(buffer_base);
+}
+
+/**
+ * pm_ipi_send_sync() - Sends IPI request to the PMU
+ * @proc	Pointer to the processor who is initiating request
+ * @payload	API id and call arguments to be written in IPI buffer
+ * @value	Used to return value from 2nd IPI buffer element (optional)
+ *
+ * Send an IPI request to the power controller and wait for it to be handled.
+ *
+ * @return	Returns status, either success or error+reason and, optionally,
+ *		@value
+ */
+enum pm_ret_status pm_ipi_send_sync(const struct pm_proc *proc,
+				    uint32_t payload[PAYLOAD_ARG_CNT],
+				    unsigned int *value)
+{
+	enum pm_ret_status ret;
+
+	bakery_lock_get(&pm_secure_lock);
+
+	ret = pm_ipi_send_common(proc, payload);
+	if (ret != PM_RET_SUCCESS)
+		goto unlock;
+
+	ret = pm_ipi_buff_read(proc, value);
+
+unlock:
+	bakery_lock_release(&pm_secure_lock);
+
+	return ret;
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_ipi.h b/plat/xilinx/zynqmp/pm_service/pm_ipi.h
new file mode 100644
index 0000000..d92e648
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_ipi.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _PM_IPI_H_
+#define _PM_IPI_H_
+
+#include "pm_common.h"
+
+int pm_ipi_init(void);
+
+enum pm_ret_status pm_ipi_send(const struct pm_proc *proc,
+			       uint32_t payload[PAYLOAD_ARG_CNT]);
+enum pm_ret_status pm_ipi_send_sync(const struct pm_proc *proc,
+				    uint32_t payload[PAYLOAD_ARG_CNT],
+				    unsigned int *value);
+
+#endif /* _PM_IPI_H_ */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
new file mode 100644
index 0000000..6744065
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Top-level SMC handler for ZynqMP power management calls and
+ * IPI setup functions for communication with PMU.
+ */
+
+#include <errno.h>
+#include <gic_common.h>
+#include <runtime_svc.h>
+#include <string.h>
+#include "pm_api_sys.h"
+#include "pm_client.h"
+#include "pm_ipi.h"
+#include "../zynqmp_private.h"
+
+/* 0 - UP, !0 - DOWN */
+static int32_t pm_down = !0;
+
+/**
+ * pm_context - Structure which contains data for power management
+ * @api_version		version of PM API, must match with one on PMU side
+ * @payload		payload array used to store received
+ *			data from ipi buffer registers
+ */
+static struct {
+	uint32_t api_version;
+	uint32_t payload[PAYLOAD_ARG_CNT];
+} pm_ctx;
+
+/**
+ * pm_setup() - PM service setup
+ *
+ * @return	On success, the initialization function must return 0.
+ *		Any other return value will cause the framework to ignore
+ *		the service
+ *
+ * Initialization functions for ZynqMP power management for
+ * communicaton with PMU.
+ *
+ * Called from sip_svc_setup initialization function with the
+ * rt_svc_init signature.
+ *
+ */
+int pm_setup(void)
+{
+	int status;
+
+	if (!zynqmp_is_pmu_up())
+		return -ENODEV;
+
+	status = pm_ipi_init();
+
+	if (status == 0)
+		INFO("BL31: PM Service Init Complete: API v%d.%d\n",
+		     PM_VERSION_MAJOR, PM_VERSION_MINOR);
+	else
+		INFO("BL31: PM Service Init Failed, Error Code %d!\n", status);
+
+	pm_down = status;
+
+	return status;
+}
+
+/**
+ * pm_smc_handler() - SMC handler for PM-API calls coming from EL1/EL2.
+ * @smc_fid - Function Identifier
+ * @x1 - x4 - Arguments
+ * @cookie  - Unused
+ * @handler - Pointer to caller's context structure
+ *
+ * @return  - Unused
+ *
+ * Determines that smc_fid is valid and supported PM SMC Function ID from the
+ * list of pm_api_ids, otherwise completes the request with
+ * the unknown SMC Function ID
+ *
+ * The SMC calls for PM service are forwarded from SIP Service SMC handler
+ * function with rt_svc_handle signature
+ */
+uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
+			uint64_t x4, void *cookie, void *handle, uint64_t flags)
+{
+	enum pm_ret_status ret;
+
+	uint32_t pm_arg[4];
+
+	/* Handle case where PM wasn't initialized properly */
+	if (pm_down)
+		SMC_RET1(handle, SMC_UNK);
+
+	pm_arg[0] = (uint32_t)x1;
+	pm_arg[1] = (uint32_t)(x1 >> 32);
+	pm_arg[2] = (uint32_t)x2;
+	pm_arg[3] = (uint32_t)(x2 >> 32);
+
+	switch (smc_fid & FUNCID_NUM_MASK) {
+	/* PM API Functions */
+	case PM_SELF_SUSPEND:
+		ret = pm_self_suspend(pm_arg[0], pm_arg[1], pm_arg[2],
+				      pm_arg[3]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_REQ_SUSPEND:
+		ret = pm_req_suspend(pm_arg[0], pm_arg[1], pm_arg[2],
+				     pm_arg[3]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_REQ_WAKEUP:
+		ret = pm_req_wakeup(pm_arg[0], pm_arg[1], pm_arg[2],
+				    pm_arg[3]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_FORCE_POWERDOWN:
+		ret = pm_force_powerdown(pm_arg[0], pm_arg[1]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_ABORT_SUSPEND:
+		ret = pm_abort_suspend(pm_arg[0]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_SET_WAKEUP_SOURCE:
+		ret = pm_set_wakeup_source(pm_arg[0], pm_arg[1], pm_arg[2]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_SYSTEM_SHUTDOWN:
+		ret = pm_system_shutdown(pm_arg[0]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_REQ_NODE:
+		ret = pm_req_node(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_RELEASE_NODE:
+		ret = pm_release_node(pm_arg[0]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_SET_REQUIREMENT:
+		ret = pm_set_requirement(pm_arg[0], pm_arg[1], pm_arg[2],
+					 pm_arg[3]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_SET_MAX_LATENCY:
+		ret = pm_set_max_latency(pm_arg[0], pm_arg[1]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_GET_API_VERSION:
+		/* Check is PM API version already verified */
+		if (pm_ctx.api_version == PM_VERSION)
+			SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS |
+				 ((uint64_t)PM_VERSION << 32));
+
+		ret = pm_get_api_version(&pm_ctx.api_version);
+		SMC_RET1(handle, (uint64_t)ret |
+			 ((uint64_t)pm_ctx.api_version << 32));
+
+	case PM_SET_CONFIGURATION:
+		ret = pm_set_configuration(pm_arg[0]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_GET_NODE_STATUS:
+		ret = pm_get_node_status(pm_arg[0]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_GET_OP_CHARACTERISTIC:
+		ret = pm_get_op_characteristic(pm_arg[0], pm_arg[1]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_REGISTER_NOTIFIER:
+		ret = pm_register_notifier(pm_arg[0], pm_arg[1], pm_arg[2],
+					   pm_arg[3]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_RESET_ASSERT:
+		ret = pm_reset_assert(pm_arg[0], pm_arg[1]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_RESET_GET_STATUS:
+	{
+		uint32_t reset_status;
+
+		ret = pm_reset_get_status(pm_arg[0], &reset_status);
+		SMC_RET1(handle, (uint64_t)ret |
+			 ((uint64_t)reset_status << 32));
+	}
+
+	/* PM memory access functions */
+	case PM_MMIO_WRITE:
+		ret = pm_mmio_write(pm_arg[0], pm_arg[1], pm_arg[2]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_MMIO_READ:
+	{
+		uint32_t value;
+
+		ret = pm_mmio_read(pm_arg[0], &value);
+		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+	}
+	default:
+		WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid);
+		SMC_RET1(handle, SMC_UNK);
+	}
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.h b/plat/xilinx/zynqmp/pm_service/pm_svc_main.h
new file mode 100644
index 0000000..26985a2
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _PM_SVC_MAIN_H_
+#define _PM_SVC_MAIN_H_
+
+#include "pm_common.h"
+
+int pm_setup(void);
+uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
+			uint64_t x4, void *cookie, void *handle,
+			uint64_t flags);
+
+#endif /*  _PM_SVC_MAIN_H_ */
diff --git a/plat/xilinx/zynqmp/sip_svc_setup.c b/plat/xilinx/zynqmp/sip_svc_setup.c
new file mode 100644
index 0000000..8bcfa6e
--- /dev/null
+++ b/plat/xilinx/zynqmp/sip_svc_setup.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Top level SMC handler for SiP calls. Dispatch PM calls to PM SMC handler. */
+
+#include <runtime_svc.h>
+#include <uuid.h>
+#include "pm_svc_main.h"
+
+/* SMC function IDs for SiP Service queries */
+#define ZYNQMP_SIP_SVC_CALL_COUNT	0x8200ff00
+#define ZYNQMP_SIP_SVC_UID		0x8200ff01
+#define ZYNQMP_SIP_SVC_VERSION		0x8200ff03
+
+/* SiP Service Calls version numbers */
+#define SIP_SVC_VERSION_MAJOR	0
+#define SIP_SVC_VERSION_MINOR	1
+
+/* These macros are used to identify PM calls from the SMC function ID */
+#define PM_FID_MASK	0xf000u
+#define PM_FID_VALUE	0u
+#define is_pm_fid(_fid) (((_fid) & PM_FID_MASK) == PM_FID_VALUE)
+
+/* SiP Service UUID */
+DEFINE_SVC_UUID(zynqmp_sip_uuid,
+		0x2a1d9b5c, 0x8605, 0x4023, 0xa6, 0x1b,
+		0xb9, 0x25, 0x82, 0x2d, 0xe3, 0xa5);
+
+/**
+ * sip_svc_setup() - Setup SiP Service
+ *
+ * Invokes PM setup
+ */
+static int32_t sip_svc_setup(void)
+{
+	/* PM implementation as SiP Service */
+	pm_setup();
+
+	return 0;
+}
+
+/**
+ * sip_svc_smc_handler() - Top-level SiP Service SMC handler
+ *
+ * Handler for all SiP SMC calls. Handles standard SIP requests
+ * and calls PM SMC handler if the call is for a PM-API function.
+ */
+uint64_t sip_svc_smc_handler(uint32_t smc_fid,
+			     uint64_t x1,
+			     uint64_t x2,
+			     uint64_t x3,
+			     uint64_t x4,
+			     void *cookie,
+			     void *handle,
+			     uint64_t flags)
+{
+	/* Let PM SMC handler deal with PM-related requests */
+	if (is_pm_fid(smc_fid)) {
+		return pm_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle,
+				      flags);
+	}
+
+	switch (smc_fid) {
+	case ZYNQMP_SIP_SVC_CALL_COUNT:
+		/* PM functions + default functions */
+		SMC_RET1(handle, PM_API_MAX + 2);
+
+	case ZYNQMP_SIP_SVC_UID:
+		SMC_UUID_RET(handle, zynqmp_sip_uuid);
+
+	case ZYNQMP_SIP_SVC_VERSION:
+		SMC_RET2(handle, SIP_SVC_VERSION_MAJOR, SIP_SVC_VERSION_MINOR);
+
+	default:
+		WARN("Unimplemented SiP Service Call: 0x%x\n", smc_fid);
+		SMC_RET1(handle, SMC_UNK);
+	}
+}
+
+/* Register PM Service Calls as runtime service */
+DECLARE_RT_SVC(
+		sip_svc,
+		OEN_SIP_START,
+		OEN_SIP_END,
+		SMC_TYPE_FAST,
+		sip_svc_setup,
+		sip_svc_smc_handler);
diff --git a/plat/xilinx/zynqmp/tsp/tsp-zynqmp.mk b/plat/xilinx/zynqmp/tsp/tsp-zynqmp.mk
new file mode 100644
index 0000000..a9ebe60
--- /dev/null
+++ b/plat/xilinx/zynqmp/tsp/tsp-zynqmp.mk
@@ -0,0 +1,31 @@
+# Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# Neither the name of ARM nor the names of its contributors may be used
+# to endorse or promote products derived from this software without specific
+# prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+# TSP source files specific to ZynqMP platform
+BL32_SOURCES		+=	plat/common/aarch64/platform_mp_stack.S		\
+				plat/xilinx/zynqmp/tsp/tsp_plat_setup.c
diff --git a/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c b/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c
new file mode 100644
index 0000000..291ccba
--- /dev/null
+++ b/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <bl_common.h>
+#include <console.h>
+#include <debug.h>
+#include <platform_tsp.h>
+#include <xlat_tables.h>
+#include <plat_arm.h>
+#include "../zynqmp_def.h"
+#include "../zynqmp_private.h"
+
+/*
+ * The next 3 constants identify the extents of the code & RO data region and
+ * the limit of the BL32 image. These addresses are used by the MMU setup code
+ * and therefore they must be page-aligned.  It is the responsibility of the
+ * linker script to ensure that __RO_START__, __RO_END__ & & __BL32_END__
+ * linker symbols refer to page-aligned addresses.
+ */
+#define BL32_RO_BASE (unsigned long)(&__RO_START__)
+#define BL32_RO_LIMIT (unsigned long)(&__RO_END__)
+#define BL32_END (unsigned long)(&__BL32_END__)
+
+
+#if USE_COHERENT_MEM
+/*
+ * 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 BL32_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
+#define BL32_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
+#endif
+
+/*******************************************************************************
+ * Initialize the UART
+ ******************************************************************************/
+void tsp_early_platform_setup(void)
+{
+	/*
+	 * Initialize a different console than already in use to display
+	 * messages from TSP
+	 */
+	console_init(ZYNQMP_UART0_BASE, zynqmp_get_uart_clk(),
+		     ZYNQMP_UART_BAUDRATE);
+
+	/* Initialize the platform config for future decision making */
+	zynqmp_config_setup();
+}
+
+/*******************************************************************************
+ * Perform platform specific setup placeholder
+ ******************************************************************************/
+void tsp_platform_setup(void)
+{
+	plat_arm_gic_driver_init();
+	plat_arm_gic_init();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the MMU
+ ******************************************************************************/
+void tsp_plat_arch_setup(void)
+{
+	arm_configure_mmu_el1(BL32_RO_BASE,
+			      (BL32_END - BL32_RO_BASE),
+			      BL32_RO_BASE,
+			      BL32_RO_LIMIT
+#if USE_COHERENT_MEM
+			      , BL32_COHERENT_RAM_BASE,
+			      BL32_COHERENT_RAM_LIMIT
+#endif
+			      );
+}
diff --git a/plat/xilinx/zynqmp/zynqmp_def.h b/plat/xilinx/zynqmp/zynqmp_def.h
new file mode 100644
index 0000000..32190e4
--- /dev/null
+++ b/plat/xilinx/zynqmp/zynqmp_def.h
@@ -0,0 +1,207 @@
+/*
+ * 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 __ZYNQMP_DEF_H__
+#define __ZYNQMP_DEF_H__
+
+#include <common_def.h>
+
+/* Firmware Image Package */
+#define ZYNQMP_PRIMARY_CPU		0
+
+/* Memory location options for Shared data and TSP in ZYNQMP */
+#define ZYNQMP_IN_TRUSTED_SRAM		0
+#define ZYNQMP_IN_TRUSTED_DRAM		1
+
+/*******************************************************************************
+ * ZYNQMP memory map related constants
+ ******************************************************************************/
+
+#define ZYNQMP_TRUSTED_SRAM_BASE	0xFFFC0000
+#define ZYNQMP_TRUSTED_SRAM_SIZE	0x00040000
+#define ZYNQMP_TRUSTED_SRAM_LIMIT	(ZYNQMP_TRUSTED_SRAM_BASE + \
+					 ZYNQMP_TRUSTED_SRAM_SIZE)
+
+
+/* Location of trusted dram on the base zynqmp */
+#define ZYNQMP_TRUSTED_DRAM_BASE	0x30000000 /* Can't overlap TZROM area */
+#define ZYNQMP_TRUSTED_DRAM_SIZE	0x10000000
+#define ZYNQMP_TRUSTED_DRAM_LIMIT	(ZYNQMP_TRUSTED_DRAM_BASE + \
+					 ZYNQMP_TRUSTED_DRAM_SIZE)
+
+/* Aggregate of all devices in the first GB */
+#define DEVICE0_BASE		0xFF000000
+#define DEVICE0_SIZE		0x00E00000
+#define DEVICE1_BASE		0xF9000000
+#define DEVICE1_SIZE		0x01000000
+
+/* For cpu reset APU space here too 0xFE5F1000 CRF_APB*/
+#define CRF_APB_BASE		0xFD1A0000
+#define CRF_APB_SIZE		0x00600000
+
+/* CRF registers and bitfields */
+#define CRF_APB_RST_FPD_APU	(CRF_APB_BASE + 0X00000104)
+
+#define CRF_APB_RST_FPD_APU_ACPU_RESET		(1 << 0)
+#define CRF_APB_RST_FPD_APU_ACPU_PWRON_RESET	(1 << 10)
+
+/* CRL registers and bitfields */
+#define CRL_APB_BASE			0xFF5E0000
+#define CRL_APB_RPLL_CTRL		(CRL_APB_BASE + 0x30)
+#define CRL_APB_TIMESTAMP_REF_CTRL	(CRL_APB_BASE + 0x128)
+#define CRL_APB_RESET_CTRL		(CRL_APB_BASE + 0x218)
+
+#define CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT	(1 << 24)
+
+#define CRL_APB_RPLL_CTRL_BYPASS	(1 << 3)
+
+#define CRL_APB_RESET_CTRL_SOFT_RESET	(1 << 4)
+
+/* system counter registers and bitfields */
+#define IOU_SCNTRS_BASE			0xFF260000
+#define IOU_SCNTRS_CONTROL		(IOU_SCNTRS_BASE + 0)
+#define IOU_SCNTRS_BASEFREQ		(IOU_SCNTRS_BASE + 0x20)
+
+#define IOU_SCNTRS_CONTROL_EN		(1 << 0)
+
+/* APU registers and bitfields */
+#define APU_BASE		0xFD5C0000
+#define APU_CONFIG_0		(APU_BASE + 0x20)
+#define APU_RVBAR_L_0		(APU_BASE + 0x40)
+#define APU_RVBAR_H_0		(APU_BASE + 0x44)
+#define APU_PWRCTL		(APU_BASE + 0x90)
+
+#define APU_CONFIG_0_VINITHI_SHIFT	8
+#define APU_0_PWRCTL_CPUPWRDWNREQ_MASK		1
+#define APU_1_PWRCTL_CPUPWRDWNREQ_MASK		2
+#define APU_2_PWRCTL_CPUPWRDWNREQ_MASK		4
+#define APU_3_PWRCTL_CPUPWRDWNREQ_MASK		8
+
+/* PMU registers and bitfields */
+#define PMU_GLOBAL_BASE			0xFFD80000
+#define PMU_GLOBAL_CNTRL		(PMU_GLOBAL_BASE + 0)
+#define PMU_GLOBAL_REQ_PWRUP_STATUS	(PMU_GLOBAL_BASE + 0x110)
+#define PMU_GLOBAL_REQ_PWRUP_EN		(PMU_GLOBAL_BASE + 0x118)
+#define PMU_GLOBAL_REQ_PWRUP_DIS	(PMU_GLOBAL_BASE + 0x11c)
+#define PMU_GLOBAL_REQ_PWRUP_TRIG	(PMU_GLOBAL_BASE + 0x120)
+
+#define PMU_GLOBAL_CNTRL_FW_IS_PRESENT	(1 << 4)
+
+#define DRAM1_BASE		0x00000000ull
+#define DRAM1_SIZE		0x10000000ull
+#define DRAM1_END		(DRAM1_BASE + DRAM1_SIZE - 1)
+
+#define DRAM_BASE		DRAM1_BASE
+#define DRAM_SIZE		DRAM1_SIZE
+
+/* Load address of BL33 in the ZYNQMP port */
+#define PLAT_ARM_NS_IMAGE_OFFSET	(DRAM1_BASE + 0x8000000) /* DRAM + 128MB */
+
+/*******************************************************************************
+ * CCI-400 related constants
+ ******************************************************************************/
+#define PLAT_ARM_CCI_BASE		0xFD6E0000
+#define PLAT_ARM_CCI_CLUSTER0_SL_IFACE_IX	3
+#define PLAT_ARM_CCI_CLUSTER1_SL_IFACE_IX	4
+
+/*******************************************************************************
+ * GIC-400 & interrupt handling related constants
+ ******************************************************************************/
+#define BASE_GICD_BASE		0xF9010000
+#define BASE_GICC_BASE		0xF9020000
+#define BASE_GICH_BASE		0xF9040000
+#define BASE_GICV_BASE		0xF9060000
+
+#define IRQ_SEC_IPI_APU			67
+#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 MAX_INTR_EL3			128
+
+/*******************************************************************************
+ * UART related constants
+ ******************************************************************************/
+#define ZYNQMP_UART0_BASE		0xFF000000
+#define ZYNQMP_UART1_BASE		0xFF001000
+
+#define PLAT_ARM_CRASH_UART_BASE	ZYNQMP_UART0_BASE
+/* impossible to call C routine how it is done now - hardcode any value */
+#define	PLAT_ARM_CRASH_UART_CLK_IN_HZ	100000000 /* FIXME */
+
+/* Must be non zero */
+#define ZYNQMP_UART_BAUDRATE	115200
+#define ARM_CONSOLE_BAUDRATE	ZYNQMP_UART_BAUDRATE
+
+/* Silicon version detection */
+#define ZYNQMP_SILICON_VER_MASK		0xF000
+#define ZYNQMP_SILICON_VER_SHIFT	12
+#define ZYNQMP_CSU_VERSION_SILICON	0
+#define ZYNQMP_CSU_VERSION_EP108	1
+#define ZYNQMP_CSU_VERSION_VELOCE	2
+#define ZYNQMP_CSU_VERSION_QEMU		3
+
+#define ZYNQMP_RTL_VER_MASK		0xFF0
+#define ZYNQMP_RTL_VER_SHIFT		4
+
+#define ZYNQMP_PS_VER_MASK		0xF
+#define ZYNQMP_PS_VER_SHIFT		0
+
+#define ZYNQMP_CSU_BASEADDR		0xFFCA0000
+#define ZYNQMP_CSU_IDCODE_OFFSET	0x40
+
+#define ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT	0
+#define ZYNQMP_CSU_IDCODE_XILINX_ID_MASK	(0xFFF << ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT)
+#define ZYNQMP_CSU_IDCODE_XILINX_ID		0x093
+
+#define ZYNQMP_CSU_IDCODE_SVD_SHIFT		12
+#define ZYNQMP_CSU_IDCODE_SVD_MASK		(0xE << ZYNQMP_CSU_IDCODE_SVD_SHIFT)
+#define ZYNQMP_CSU_IDCODE_DEVICE_CODE_SHIFT	15
+#define ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK	(0xF << ZYNQMP_CSU_IDCODE_DEVICE_CODE_SHIFT)
+#define ZYNQMP_CSU_IDCODE_SUB_FAMILY_SHIFT	19
+#define ZYNQMP_CSU_IDCODE_SUB_FAMILY_MASK	(0x3 << ZYNQMP_CSU_IDCODE_SUB_FAMILY_SHIFT)
+#define ZYNQMP_CSU_IDCODE_FAMILY_SHIFT		21
+#define ZYNQMP_CSU_IDCODE_FAMILY_MASK		(0x7F << ZYNQMP_CSU_IDCODE_FAMILY_SHIFT)
+#define ZYNQMP_CSU_IDCODE_FAMILY		0x23
+
+#define ZYNQMP_CSU_IDCODE_REVISION_SHIFT	28
+#define ZYNQMP_CSU_IDCODE_REVISION_MASK		(0xF << ZYNQMP_CSU_IDCODE_REVISION_SHIFT)
+#define ZYNQMP_CSU_IDCODE_REVISION		0
+
+#define ZYNQMP_CSU_VERSION_OFFSET	0x44
+
+#endif /* __ZYNQMP_DEF_H__ */
diff --git a/plat/xilinx/zynqmp/zynqmp_private.h b/plat/xilinx/zynqmp/zynqmp_private.h
new file mode 100644
index 0000000..1f5be39
--- /dev/null
+++ b/plat/xilinx/zynqmp/zynqmp_private.h
@@ -0,0 +1,42 @@
+/*
+ * 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 __ZYNQMP_PRIVATE_H__
+#define __ZYNQMP_PRIVATE_H__
+
+#include <interrupt_mgmt.h>
+
+void zynqmp_config_setup(void);
+
+/* ZynqMP specific functions */
+unsigned int zynqmp_get_uart_clk(void);
+int zynqmp_is_pmu_up(void);
+
+#endif /* __ZYNQMP_PRIVATE_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