Merge pull request #1071 from jeenu-arm/syntax-fix

plat/arm: Fix ARM_INSTANTIATE_LOCK syntax anomaly
diff --git a/docs/diagrams/Makefile b/docs/diagrams/Makefile
new file mode 100644
index 0000000..de7d8f3
--- /dev/null
+++ b/docs/diagrams/Makefile
@@ -0,0 +1,74 @@
+#
+# Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#
+# This Makefile generates the image files used in the ARM Trusted Firmware
+# document from the dia file.
+#
+# The PNG files in the present directory have been generated using Dia version
+# 0.97.2, which can be obtained from https://wiki.gnome.org/Apps/Dia/Download
+#
+
+# generate_image use the tool dia generate png from dia file
+#    $(1) = layers
+#    $(2) = image file name
+#    $(3) = image file format
+#    $(4) = addition opts
+#    $(5) = dia source file
+define generate_image
+	dia --show-layers=$(1) --filter=$(3) --export=$(2) $(4) $(5)
+endef
+
+RESET_DIA							= reset_code_flow.dia
+RESET_PNGS							=		\
+		default_reset_code.png 				\
+		reset_code_no_cpu_check.png			\
+		reset_code_no_boot_type_check.png 	\
+		reset_code_no_checks.png			\
+
+# The $(RESET_DIA) file is organized in several layers.
+# Each image is generated by combining and exporting the appropriate set of
+# layers.
+default_reset_code_layers			= "Frontground,Background,cpu_type_check,boot_type_check"
+reset_code_no_cpu_check_layers		= "Frontground,Background,no_cpu_type_check,boot_type_check"
+reset_code_no_boot_type_check_layers= "Frontground,Background,cpu_type_check,no_boot_type_check"
+reset_code_no_checks_layers			= "Frontground,Background,no_cpu_type_check,no_boot_type_check"
+
+default_reset_code_opts          	=
+reset_code_no_cpu_check_opts     	=
+reset_code_no_boot_type_check_opts	=
+reset_code_no_checks_opts			=
+
+INT_DIA								= int_handling.dia
+INT_PNGS							=		\
+		sec-int-handling.png				\
+		non-sec-int-handling.png
+
+# The $(INT_DIA) file is organized in several layers.
+# Each image is generated by combining and exporting the appropriate set of
+# layers.
+non-sec-int-handling_layers			= "non_sec_int_bg,legend,non_sec_int_note,non_sec_int_handling"
+sec-int-handling_layers				= "sec_int_bg,legend,sec_int_note,sec_int_handling"
+
+non-sec-int-handling_opts			= --size=1692x
+sec-int-handling_opts				= --size=1570x
+
+XLAT_DIA 							= xlat_align.dia
+XLAT_PNG 							= xlat_align.png
+
+xlat_align_layers					= "bg,translations"
+xlat_align_opts						=
+
+all:$(RESET_PNGS) $(INT_PNGS) $(XLAT_PNG)
+
+$(RESET_PNGS):$(RESET_DIA)
+	$(call generate_image,$($(patsubst %.png,%_layers,$@)),$@,png,$($(patsubst %.png,%_opts,$@)),$<)
+
+$(INT_PNGS):$(INT_DIA)
+	$(call generate_image,$($(patsubst %.png,%_layers,$@)),$@,png,$($(patsubst %.png,%_opts,$@)),$<)
+
+$(XLAT_PNG):$(XLAT_DIA)
+	$(call generate_image,$($(patsubst %.png,%_layers,$@)),$(patsubst %.png,%.svg,$@),svg,$($(patsubst %.png,%_opts,$@)),$<)
+	inkscape -z $(patsubst %.png,%.svg,$@) -e $@ -d 45
diff --git a/docs/diagrams/generate_reset_images.sh b/docs/diagrams/generate_reset_images.sh
deleted file mode 100755
index eef5648..0000000
--- a/docs/diagrams/generate_reset_images.sh
+++ /dev/null
@@ -1,41 +0,0 @@
-#! /bin/bash
-
-#
-# This script generates the image files used in the ARM Trusted Firmware Reset
-# Design document from the 'reset_code_flow.dia' file.
-#
-# The PNG files in the present directory have been generated using Dia version
-# 0.97.2, which can be obtained from https://wiki.gnome.org/Apps/Dia/Download
-#
-
-set -e
-
-# Usage: generate_image <layers> <image_filename>
-function generate_image
-{
-	dia				\
-		--show-layers=$1	\
-		--filter=png		\
-		--export=$2		\
-		reset_code_flow.dia
-
-}
-
-# The 'reset_code_flow.dia' file is organized in several layers.
-# Each image is generated by combining and exporting the appropriate set of
-# layers.
-generate_image								\
-	Frontground,Background,cpu_type_check,boot_type_check		\
-	default_reset_code.png
-
-generate_image								\
-	Frontground,Background,no_cpu_type_check,boot_type_check	\
-	reset_code_no_cpu_check.png
-
-generate_image								\
-	Frontground,Background,cpu_type_check,no_boot_type_check	\
-	reset_code_no_boot_type_check.png
-
-generate_image								\
-	Frontground,Background,no_cpu_type_check,no_boot_type_check	\
-	reset_code_no_checks.png
diff --git a/docs/diagrams/generate_xlat_images.sh b/docs/diagrams/generate_xlat_images.sh
deleted file mode 100755
index 9daef5f..0000000
--- a/docs/diagrams/generate_xlat_images.sh
+++ /dev/null
@@ -1,26 +0,0 @@
-#! /bin/bash
-
-#
-# This script generates the image file used in the ARM Trusted Firmware
-# Translation Tables Library V2 Design document from the 'xlat_align.dia' file.
-#
-
-set -e
-
-# Usage: generate_image <dia_filename> <layers> <image_filename>
-function generate_image
-{
-	dia				\
-		--show-layers=$2	\
-		--filter=svg		\
-		--export=$3		\
-		$1
-
-}
-
-generate_image			\
-	xlat_align.dia		\
-	bg,translations		\
-	xlat_align.svg
-
-inkscape -z xlat_align.svg -e xlat_align.png -d 45
diff --git a/docs/diagrams/int_handling.dia b/docs/diagrams/int_handling.dia
new file mode 100644
index 0000000..12aa186
--- /dev/null
+++ b/docs/diagrams/int_handling.dia
Binary files differ
diff --git a/docs/diagrams/non-sec-int-handling.png b/docs/diagrams/non-sec-int-handling.png
index 1a5f629..64082c9 100644
--- a/docs/diagrams/non-sec-int-handling.png
+++ b/docs/diagrams/non-sec-int-handling.png
Binary files differ
diff --git a/docs/diagrams/sec-int-handling.png b/docs/diagrams/sec-int-handling.png
index 2ebbca4..fa5c340 100644
--- a/docs/diagrams/sec-int-handling.png
+++ b/docs/diagrams/sec-int-handling.png
Binary files differ
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index 55747bf..106cd74 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -97,16 +97,18 @@
 
 #ifdef SPD_opteed
 /*
- * BL2 needs to map 3.5MB from 512KB offset in TZC_DRAM1 in order to
- * load/authenticate the trusted os extra image. The first 512KB of TZC_DRAM1
- * are reserved for trusted os (OPTEE). The extra image loading for OPTEE is
- * paged image which only include the paging part using virtual memory but
- * without "init" data. OPTEE will copy the "init" data (from pager image) to
- * the first 512KB of TZC_DRAM, and then copy the extra image behind the "init"
- * data.
+ * BL2 needs to map 4MB at the end of TZC_DRAM1 in order to
+ * load/authenticate the trusted os extra image. The first 512KB of
+ * TZC_DRAM1 are reserved for trusted os (OPTEE). The extra image loading
+ * for OPTEE is paged image which only include the paging part using
+ * virtual memory but without "init" data. OPTEE will copy the "init" data
+ * (from pager image) to the first 512KB of TZC_DRAM, and then copy the
+ * extra image behind the "init" data.
  */
-#define ARM_OPTEE_PAGEABLE_LOAD_BASE	(ARM_AP_TZC_DRAM1_BASE + 0x80000)
-#define ARM_OPTEE_PAGEABLE_LOAD_SIZE	0x380000
+#define ARM_OPTEE_PAGEABLE_LOAD_BASE	(ARM_AP_TZC_DRAM1_BASE + \
+					 ARM_AP_TZC_DRAM1_SIZE - \
+					 ARM_OPTEE_PAGEABLE_LOAD_SIZE)
+#define ARM_OPTEE_PAGEABLE_LOAD_SIZE	0x400000
 #define ARM_OPTEE_PAGEABLE_LOAD_MEM	MAP_REGION_FLAT(		\
 					ARM_OPTEE_PAGEABLE_LOAD_BASE,	\
 					ARM_OPTEE_PAGEABLE_LOAD_SIZE,	\
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
index d6b9820..d97a049 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -87,6 +87,9 @@
 #if ARM_BL31_IN_DRAM
 	ARM_MAP_BL31_SEC_DRAM,
 #endif
+#ifdef SPD_opteed
+	ARM_OPTEE_PAGEABLE_LOAD_MEM,
+#endif
 	{0}
 };
 #endif
diff --git a/plat/rockchip/common/include/plat_private.h b/plat/rockchip/common/include/plat_private.h
index 290811a..5456773 100644
--- a/plat/rockchip/common/include/plat_private.h
+++ b/plat/rockchip/common/include/plat_private.h
@@ -90,6 +90,8 @@
 struct gpio_info *plat_get_rockchip_suspend_gpio(uint32_t *count);
 struct apio_info *plat_get_rockchip_suspend_apio(void);
 void plat_rockchip_gpio_init(void);
+void plat_rockchip_save_gpio(void);
+void plat_rockchip_restore_gpio(void);
 
 int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint);
 int rockchip_soc_hlvl_pwr_dm_off(uint32_t lvl,
diff --git a/plat/rockchip/common/pmusram/pmu_sram_cpus_on.S b/plat/rockchip/common/pmusram/pmu_sram_cpus_on.S
index 22bdffc..5a1854b 100644
--- a/plat/rockchip/common/pmusram/pmu_sram_cpus_on.S
+++ b/plat/rockchip/common/pmusram/pmu_sram_cpus_on.S
@@ -45,7 +45,7 @@
 ddr_resume:
 	ldr	x2, =__bl31_sram_stack_end
 	mov     sp, x2
-	bl	dmc_restore
+	bl	dmc_resume
 #endif
 	bl	sram_restore
 sys_resume:
diff --git a/plat/rockchip/rk3399/drivers/dram/dram.h b/plat/rockchip/rk3399/drivers/dram/dram.h
index fede7ee..0780fc3 100644
--- a/plat/rockchip/rk3399/drivers/dram/dram.h
+++ b/plat/rockchip/rk3399/drivers/dram/dram.h
@@ -25,10 +25,10 @@
 
 struct rk3399_ddr_publ_regs {
 	/*
-	 * PHY registers from 0 to 511.
-	 * Only registers 0-90 of each 128 register range are used.
+	 * PHY registers from 0 to 90 for slice1.
+	 * These are used to restore slice1-4 on resume.
 	 */
-	uint32_t phy0[4][91];
+	uint32_t phy0[91];
 	/*
 	 * PHY registers from 512 to 895.
 	 * Only registers 0-37 of each 128 register range are used.
diff --git a/plat/rockchip/rk3399/drivers/dram/suspend.c b/plat/rockchip/rk3399/drivers/dram/suspend.c
index 6867744..f66150a 100644
--- a/plat/rockchip/rk3399/drivers/dram/suspend.c
+++ b/plat/rockchip/rk3399/drivers/dram/suspend.c
@@ -43,6 +43,9 @@
 
 #define SYS_COUNTER_FREQ_IN_MHZ		(SYS_COUNTER_FREQ_IN_TICKS / 1000000)
 
+__pmusramdata uint32_t dpll_data[PLL_CON_COUNT];
+__pmusramdata uint32_t cru_clksel_con6;
+
 /*
  * Copy @num registers from @src to @dst
  */
@@ -528,7 +531,7 @@
 
 	for (i = 0; i < 4; i++)
 		sram_regcpy(PHY_REG(ch, 128 * i),
-			    (uintptr_t)&phy_regs->phy0[i][0], 91);
+			    (uintptr_t)&phy_regs->phy0[0], 91);
 
 	for (i = 0; i < 3; i++)
 		sram_regcpy(PHY_REG(ch, 512 + 128 * i),
@@ -636,24 +639,45 @@
 	return 0;
 }
 
+__pmusramfunc static void pmusram_restore_pll(int pll_id, uint32_t *src)
+{
+	mmio_write_32((CRU_BASE + CRU_PLL_CON(pll_id, 3)), PLL_SLOW_MODE);
+
+	mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 0), src[0] | REG_SOC_WMSK);
+	mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 1), src[1] | REG_SOC_WMSK);
+	mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 2), src[2]);
+	mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 4), src[4] | REG_SOC_WMSK);
+	mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 5), src[5] | REG_SOC_WMSK);
+
+	mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 3), src[3] | REG_SOC_WMSK);
+
+	while ((mmio_read_32(CRU_BASE + CRU_PLL_CON(pll_id, 2)) &
+		(1 << 31)) == 0x0)
+		;
+}
+
-void dmc_save(void)
+void dmc_suspend(void)
 {
 	struct rk3399_sdram_params *sdram_params = &sdram_config;
 	struct rk3399_ddr_publ_regs *phy_regs;
 	uint32_t *params_ctl;
 	uint32_t *params_pi;
 	uint32_t refdiv, postdiv2, postdiv1, fbdiv;
-	uint32_t tmp, ch, byte, i;
+	uint32_t ch, byte, i;
 
 	phy_regs = &sdram_params->phy_regs;
 	params_ctl = sdram_params->pctl_regs.denali_ctl;
 	params_pi = sdram_params->pi_regs.denali_pi;
 
+	/* save dpll register and ddr clock register value to pmusram */
+	cru_clksel_con6 = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON6);
+	for (i = 0; i < PLL_CON_COUNT; i++)
+		dpll_data[i] = mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, i));
+
-	fbdiv = mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, 0)) & 0xfff;
-	tmp = mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, 1));
-	postdiv2 = POSTDIV2_DEC(tmp);
-	postdiv1 = POSTDIV1_DEC(tmp);
-	refdiv = REFDIV_DEC(tmp);
+	fbdiv = dpll_data[0] & 0xfff;
+	postdiv2 = POSTDIV2_DEC(dpll_data[1]);
+	postdiv1 = POSTDIV1_DEC(dpll_data[1]);
+	refdiv = REFDIV_DEC(dpll_data[1]);
 
 	sdram_params->ddr_freq = ((fbdiv * 24) /
 				(refdiv * postdiv1 * postdiv2)) * MHz;
@@ -674,9 +698,8 @@
 	/* mask DENALI_PI_00_DATA.START, only copy here, will trigger later*/
 	params_pi[0] &= ~(0x1 << 0);
 
-	for (i = 0; i < 4; i++)
-		dram_regcpy((uintptr_t)&phy_regs->phy0[i][0],
-			    PHY_REG(0, 128 * i), 91);
+	dram_regcpy((uintptr_t)&phy_regs->phy0[0],
+			    PHY_REG(0, 0), 91);
 
 	for (i = 0; i < 3; i++)
 		dram_regcpy((uintptr_t)&phy_regs->phy512[i][0],
@@ -697,12 +720,22 @@
 	phy_regs->phy896[0] &= ~(0x3 << 8);
 }
 
-__pmusramfunc void dmc_restore(void)
+__pmusramfunc void dmc_resume(void)
 {
 	struct rk3399_sdram_params *sdram_params = &sdram_config;
 	uint32_t channel_mask = 0;
 	uint32_t channel;
 
+	sram_secure_timer_init();
+
+	/*
+	 * we switch ddr clock to abpll when suspend,
+	 * we set back to dpll here
+	 */
+	mmio_write_32(CRU_BASE + CRU_CLKSEL_CON6,
+			cru_clksel_con6 | REG_SOC_WMSK);
+	pmusram_restore_pll(DPLL_ID, dpll_data);
+
 	configure_sgrf();
 
 retry:
diff --git a/plat/rockchip/rk3399/drivers/dram/suspend.h b/plat/rockchip/rk3399/drivers/dram/suspend.h
index 77f9c31..a8a8641 100644
--- a/plat/rockchip/rk3399/drivers/dram/suspend.h
+++ b/plat/rockchip/rk3399/drivers/dram/suspend.h
@@ -19,7 +19,7 @@
 #define PI_WDQ_LEVELING		(1 << 4)
 #define PI_FULL_TRAINING	(0xff)
 
-void dmc_save(void);
-__pmusramfunc void dmc_restore(void);
+void dmc_suspend(void);
+__pmusramfunc void dmc_resume(void);
 
 #endif /* __DRAM_H__ */
diff --git a/plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c b/plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c
index d5a2660..e74c4d9 100644
--- a/plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c
+++ b/plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c
@@ -22,10 +22,29 @@
 	GPIO4_BASE,
 };
 
+struct {
+	uint32_t swporta_dr;
+	uint32_t swporta_ddr;
+	uint32_t inten;
+	uint32_t intmask;
+	uint32_t inttype_level;
+	uint32_t int_polarity;
+	uint32_t debounce;
+	uint32_t ls_sync;
+} store_gpio[3];
+
+static uint32_t store_grf_gpio[(GRF_GPIO2D_HE - GRF_GPIO2A_IOMUX) / 4 + 1];
+
 #define SWPORTA_DR	0x00
 #define SWPORTA_DDR	0x04
-#define EXT_PORTA	0x50
+#define INTEN		0x30
+#define INTMASK		0x34
+#define INTTYPE_LEVEL	0x38
+#define INT_POLARITY	0x3c
+#define DEBOUNCE	0x48
+#define LS_SYNC		0x60
 
+#define EXT_PORTA	0x50
 #define PMU_GPIO_PORT0	0
 #define PMU_GPIO_PORT1	1
 #define GPIO_PORT2	2
@@ -290,6 +309,99 @@
 	gpio_put_clock(gpio, clock_state);
 }
 
+void plat_rockchip_save_gpio(void)
+{
+	int i;
+	uint32_t cru_gate_save;
+
+	cru_gate_save = mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(31));
+
+	/*
+	 * when shutdown logic, we need to save gpio2 ~ gpio4 register,
+	 * we need to enable gpio2 ~ gpio4 clock here, since it may be gating,
+	 * and we do not care gpio0 and gpio1 clock gate, since we never
+	 * gating them
+	 */
+	mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
+		      BITS_WITH_WMASK(0, 0x07, PCLK_GPIO2_GATE_SHIFT));
+
+	/*
+	 * since gpio0, gpio1 are pmugpio, they will keep ther value
+	 * when shutdown logic power rail, so only need to save gpio2 ~ gpio4
+	 * register value
+	 */
+	for (i = 2; i < 5; i++) {
+		store_gpio[i - 2].swporta_dr =
+			mmio_read_32(gpio_port[i] + SWPORTA_DR);
+		store_gpio[i - 2].swporta_ddr =
+			mmio_read_32(gpio_port[i] + SWPORTA_DDR);
+		store_gpio[i - 2].inten =
+			mmio_read_32(gpio_port[i] + INTEN);
+		store_gpio[i - 2].intmask =
+			mmio_read_32(gpio_port[i] + INTMASK);
+		store_gpio[i - 2].inttype_level =
+			mmio_read_32(gpio_port[i] + INTTYPE_LEVEL);
+		store_gpio[i - 2].int_polarity =
+			mmio_read_32(gpio_port[i] + INT_POLARITY);
+		store_gpio[i - 2].debounce =
+			mmio_read_32(gpio_port[i] + DEBOUNCE);
+		store_gpio[i - 2].ls_sync =
+			mmio_read_32(gpio_port[i] + LS_SYNC);
+	}
+	mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
+			cru_gate_save | REG_SOC_WMSK);
+
+	/*
+	 * gpio0, gpio1 in pmuiomux, they will keep ther value
+	 * when shutdown logic power rail, so only need to save gpio2 ~ gpio4
+	 * iomux register value
+	 */
+	for (i = 0; i < ARRAY_SIZE(store_grf_gpio); i++)
+		store_grf_gpio[i] =
+			mmio_read_32(GRF_BASE + GRF_GPIO2A_IOMUX + i * 4);
+}
+
+void plat_rockchip_restore_gpio(void)
+{
+	int i;
+	uint32_t cru_gate_save;
+
+	for (i = 0; i < ARRAY_SIZE(store_grf_gpio); i++)
+		mmio_write_32(GRF_BASE + GRF_GPIO2A_IOMUX + i * 4,
+		      REG_SOC_WMSK | store_grf_gpio[i]);
+
+	cru_gate_save = mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(31));
+
+	/*
+	 * when shutdown logic, we need to save gpio2 ~ gpio4 register,
+	 * we need to enable gpio2 ~ gpio4 clock here, since it may be gating,
+	 * and we do not care gpio0 and gpio1 clock gate, since we never
+	 * gating them
+	 */
+	mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
+		      BITS_WITH_WMASK(0, 0x07, PCLK_GPIO2_GATE_SHIFT));
+
+	for (i = 2; i < 5; i++) {
+		mmio_write_32(gpio_port[i] + SWPORTA_DR,
+				store_gpio[i - 2].swporta_dr);
+		mmio_write_32(gpio_port[i] + SWPORTA_DDR,
+				store_gpio[i - 2].swporta_ddr);
+		mmio_write_32(gpio_port[i] + INTEN, store_gpio[i - 2].inten);
+		mmio_write_32(gpio_port[i] + INTMASK,
+				store_gpio[i - 2].intmask);
+		mmio_write_32(gpio_port[i] + INTTYPE_LEVEL,
+				store_gpio[i - 2].inttype_level);
+		mmio_write_32(gpio_port[i] + INT_POLARITY,
+				store_gpio[i - 2].int_polarity);
+		mmio_write_32(gpio_port[i] + DEBOUNCE,
+				store_gpio[i - 2].debounce);
+		mmio_write_32(gpio_port[i] + LS_SYNC,
+				store_gpio[i - 2].ls_sync);
+	}
+	mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
+			cru_gate_save | REG_SOC_WMSK);
+}
+
 const gpio_ops_t rk3399_gpio_ops = {
 	.get_direction = get_direction,
 	.set_direction = set_direction,
diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu.c b/plat/rockchip/rk3399/drivers/pmu/pmu.c
index 6b420c2..c666c3c 100644
--- a/plat/rockchip/rk3399/drivers/pmu/pmu.c
+++ b/plat/rockchip/rk3399/drivers/pmu/pmu.c
@@ -32,6 +32,19 @@
 
 static uint32_t cpu_warm_boot_addr;
 static char store_sram[SRAM_BIN_LIMIT + SRAM_TEXT_LIMIT + SRAM_DATA_LIMIT];
+static uint32_t store_cru[CRU_SDIO0_CON1 / 4];
+static uint32_t store_usbphy0[7];
+static uint32_t store_usbphy1[7];
+static uint32_t store_grf_io_vsel;
+static uint32_t store_grf_soc_con0;
+static uint32_t store_grf_soc_con1;
+static uint32_t store_grf_soc_con2;
+static uint32_t store_grf_soc_con3;
+static uint32_t store_grf_soc_con4;
+static uint32_t store_grf_soc_con7;
+static uint32_t store_grf_ddrc_con[4];
+static uint32_t store_wdt0[2];
+static uint32_t store_wdt1[2];
 
 /*
  * There are two ways to powering on or off on core.
@@ -323,6 +336,11 @@
 	pmu_set_power_domain(PD_RGA, pmu_pd_off);
 	pmu_set_power_domain(PD_VCODEC, pmu_pd_off);
 	pmu_set_power_domain(PD_VDU, pmu_pd_off);
+	pmu_set_power_domain(PD_USB3, pmu_pd_off);
+	pmu_set_power_domain(PD_EMMC, pmu_pd_off);
+	pmu_set_power_domain(PD_VIO, pmu_pd_off);
+	pmu_set_power_domain(PD_SD, pmu_pd_off);
+	pmu_set_power_domain(PD_PERIHP, pmu_pd_off);
 	clk_gate_con_restore();
 }
 
@@ -358,6 +376,16 @@
 		pmu_set_power_domain(PD_TCPD0, pmu_pd_on);
 	if (!(pmu_powerdomain_state & BIT(PD_GPU)))
 		pmu_set_power_domain(PD_GPU, pmu_pd_on);
+	if (!(pmu_powerdomain_state & BIT(PD_USB3)))
+		pmu_set_power_domain(PD_USB3, pmu_pd_on);
+	if (!(pmu_powerdomain_state & BIT(PD_EMMC)))
+		pmu_set_power_domain(PD_EMMC, pmu_pd_on);
+	if (!(pmu_powerdomain_state & BIT(PD_VIO)))
+		pmu_set_power_domain(PD_VIO, pmu_pd_on);
+	if (!(pmu_powerdomain_state & BIT(PD_SD)))
+		pmu_set_power_domain(PD_SD, pmu_pd_on);
+	if (!(pmu_powerdomain_state & BIT(PD_PERIHP)))
+		pmu_set_power_domain(PD_PERIHP, pmu_pd_on);
 	qos_restore();
 	clk_gate_con_restore();
 }
@@ -815,6 +843,7 @@
 		      BIT_WITH_WMSK(PMU_CLR_GIC2_CORE_L_HW));
 
 	slp_mode_cfg = BIT(PMU_PWR_MODE_EN) |
+		       BIT(PMU_INPUT_CLAMP_EN) |
 		       BIT(PMU_POWER_OFF_REQ_CFG) |
 		       BIT(PMU_CPU0_PD_EN) |
 		       BIT(PMU_L2_FLUSH_EN) |
@@ -828,7 +857,9 @@
 		       BIT(PMU_DDRC0_GATING_EN) |
 		       BIT(PMU_DDRC1_GATING_EN) |
 		       BIT(PMU_DDRIO0_RET_EN) |
+		       BIT(PMU_DDRIO0_RET_DE_REQ) |
 		       BIT(PMU_DDRIO1_RET_EN) |
+		       BIT(PMU_DDRIO1_RET_DE_REQ) |
 		       BIT(PMU_DDRIO_RET_HW_DE_REQ) |
 		       BIT(PMU_CENTER_PD_EN) |
 		       BIT(PMU_PERILP_PD_EN) |
@@ -1076,15 +1107,229 @@
 	       incbin_size);
 }
 
+struct uart_debug {
+	uint32_t uart_dll;
+	uint32_t uart_dlh;
+	uint32_t uart_ier;
+	uint32_t uart_fcr;
+	uint32_t uart_mcr;
+	uint32_t uart_lcr;
+};
+
+#define UART_DLL	0x00
+#define UART_DLH	0x04
+#define UART_IER	0x04
+#define UART_FCR	0x08
+#define UART_LCR	0x0c
+#define UART_MCR	0x10
+#define UARTSRR		0x88
+
+#define UART_RESET	BIT(0)
+#define UARTFCR_FIFOEN	BIT(0)
+#define RCVR_FIFO_RESET	BIT(1)
+#define XMIT_FIFO_RESET	BIT(2)
+#define DIAGNOSTIC_MODE	BIT(4)
+#define UARTLCR_DLAB	BIT(7)
+
+static struct uart_debug uart_save;
+
+void suspend_uart(void)
+{
+	uart_save.uart_lcr = mmio_read_32(PLAT_RK_UART_BASE + UART_LCR);
+	uart_save.uart_ier = mmio_read_32(PLAT_RK_UART_BASE + UART_IER);
+	uart_save.uart_mcr = mmio_read_32(PLAT_RK_UART_BASE + UART_MCR);
+	mmio_write_32(PLAT_RK_UART_BASE + UART_LCR,
+		      uart_save.uart_lcr | UARTLCR_DLAB);
+	uart_save.uart_dll = mmio_read_32(PLAT_RK_UART_BASE + UART_DLL);
+	uart_save.uart_dlh = mmio_read_32(PLAT_RK_UART_BASE + UART_DLH);
+	mmio_write_32(PLAT_RK_UART_BASE + UART_LCR, uart_save.uart_lcr);
+}
+
+void resume_uart(void)
+{
+	uint32_t uart_lcr;
+
+	mmio_write_32(PLAT_RK_UART_BASE + UARTSRR,
+		      XMIT_FIFO_RESET | RCVR_FIFO_RESET | UART_RESET);
+
+	uart_lcr = mmio_read_32(PLAT_RK_UART_BASE + UART_LCR);
+	mmio_write_32(PLAT_RK_UART_BASE + UART_MCR, DIAGNOSTIC_MODE);
+	mmio_write_32(PLAT_RK_UART_BASE + UART_LCR, uart_lcr | UARTLCR_DLAB);
+	mmio_write_32(PLAT_RK_UART_BASE + UART_DLL, uart_save.uart_dll);
+	mmio_write_32(PLAT_RK_UART_BASE + UART_DLH, uart_save.uart_dlh);
+	mmio_write_32(PLAT_RK_UART_BASE + UART_LCR, uart_save.uart_lcr);
+	mmio_write_32(PLAT_RK_UART_BASE + UART_IER, uart_save.uart_ier);
+	mmio_write_32(PLAT_RK_UART_BASE + UART_FCR, UARTFCR_FIFOEN);
+	mmio_write_32(PLAT_RK_UART_BASE + UART_MCR, uart_save.uart_mcr);
+}
+
+void save_usbphy(void)
+{
+	store_usbphy0[0] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL0);
+	store_usbphy0[1] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL2);
+	store_usbphy0[2] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL3);
+	store_usbphy0[3] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL12);
+	store_usbphy0[4] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL13);
+	store_usbphy0[5] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL15);
+	store_usbphy0[6] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL16);
+
+	store_usbphy1[0] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL0);
+	store_usbphy1[1] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL2);
+	store_usbphy1[2] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL3);
+	store_usbphy1[3] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL12);
+	store_usbphy1[4] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL13);
+	store_usbphy1[5] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL15);
+	store_usbphy1[6] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL16);
+}
+
+void restore_usbphy(void)
+{
+	mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL0,
+		      REG_SOC_WMSK | store_usbphy0[0]);
+	mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL2,
+		      REG_SOC_WMSK | store_usbphy0[1]);
+	mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL3,
+		      REG_SOC_WMSK | store_usbphy0[2]);
+	mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL12,
+		      REG_SOC_WMSK | store_usbphy0[3]);
+	mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL13,
+		      REG_SOC_WMSK | store_usbphy0[4]);
+	mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL15,
+		      REG_SOC_WMSK | store_usbphy0[5]);
+	mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL16,
+		      REG_SOC_WMSK | store_usbphy0[6]);
+
+	mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL0,
+		      REG_SOC_WMSK | store_usbphy1[0]);
+	mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL2,
+		      REG_SOC_WMSK | store_usbphy1[1]);
+	mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL3,
+		      REG_SOC_WMSK | store_usbphy1[2]);
+	mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL12,
+		      REG_SOC_WMSK | store_usbphy1[3]);
+	mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL13,
+		      REG_SOC_WMSK | store_usbphy1[4]);
+	mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL15,
+		      REG_SOC_WMSK | store_usbphy1[5]);
+	mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL16,
+		      REG_SOC_WMSK | store_usbphy1[6]);
+}
+
+void grf_register_save(void)
+{
+	int i;
+
+	store_grf_soc_con0 = mmio_read_32(GRF_BASE + GRF_SOC_CON(0));
+	store_grf_soc_con1 = mmio_read_32(GRF_BASE + GRF_SOC_CON(1));
+	store_grf_soc_con2 = mmio_read_32(GRF_BASE + GRF_SOC_CON(2));
+	store_grf_soc_con3 = mmio_read_32(GRF_BASE + GRF_SOC_CON(3));
+	store_grf_soc_con4 = mmio_read_32(GRF_BASE + GRF_SOC_CON(4));
+	store_grf_soc_con7 = mmio_read_32(GRF_BASE + GRF_SOC_CON(7));
+
+	for (i = 0; i < 4; i++)
+		store_grf_ddrc_con[i] =
+			mmio_read_32(GRF_BASE + GRF_DDRC0_CON0 + i * 4);
+
+	store_grf_io_vsel = mmio_read_32(GRF_BASE + GRF_IO_VSEL);
+}
+
+void grf_register_restore(void)
+{
+	int i;
+
+	mmio_write_32(GRF_BASE + GRF_SOC_CON(0),
+		      REG_SOC_WMSK | store_grf_soc_con0);
+	mmio_write_32(GRF_BASE + GRF_SOC_CON(1),
+		      REG_SOC_WMSK | store_grf_soc_con1);
+	mmio_write_32(GRF_BASE + GRF_SOC_CON(2),
+		      REG_SOC_WMSK | store_grf_soc_con2);
+	mmio_write_32(GRF_BASE + GRF_SOC_CON(3),
+		      REG_SOC_WMSK | store_grf_soc_con3);
+	mmio_write_32(GRF_BASE + GRF_SOC_CON(4),
+		      REG_SOC_WMSK | store_grf_soc_con4);
+	mmio_write_32(GRF_BASE + GRF_SOC_CON(7),
+		      REG_SOC_WMSK | store_grf_soc_con7);
+
+	for (i = 0; i < 4; i++)
+		mmio_write_32(GRF_BASE + GRF_DDRC0_CON0 + i * 4,
+			      REG_SOC_WMSK | store_grf_ddrc_con[i]);
+
+	mmio_write_32(GRF_BASE + GRF_IO_VSEL, REG_SOC_WMSK | store_grf_io_vsel);
+}
+
+void cru_register_save(void)
+{
+	int i;
+
+	for (i = 0; i <= CRU_SDIO0_CON1; i = i + 4)
+		store_cru[i / 4] = mmio_read_32(CRU_BASE + i);
+}
+
+void cru_register_restore(void)
+{
+	int i;
+
+	for (i = 0; i <= CRU_SDIO0_CON1; i = i + 4) {
+
+		/*
+		 * since DPLL, CRU_CLKSEL_CON6 have been restore in
+		 * dmc_resume, ABPLL will resote later, so skip them
+		 */
+		if ((i == CRU_CLKSEL_CON6) ||
+		    (i >= CRU_PLL_CON(ABPLL_ID, 0) &&
+		     i <= CRU_PLL_CON(DPLL_ID, 5)))
+			continue;
+
+		if ((i == CRU_PLL_CON(ALPLL_ID, 2)) ||
+		    (i == CRU_PLL_CON(CPLL_ID, 2)) ||
+		    (i == CRU_PLL_CON(GPLL_ID, 2)) ||
+		    (i == CRU_PLL_CON(NPLL_ID, 2)) ||
+		    (i == CRU_PLL_CON(VPLL_ID, 2)))
+			mmio_write_32(CRU_BASE + i, store_cru[i / 4]);
+		/*
+		 * CRU_GLB_CNT_TH and CRU_CLKSEL_CON97~CRU_CLKSEL_CON107
+		 * not need do high 16bit mask
+		 */
+		else if ((i > 0x27c && i < 0x2b0) || (i == 0x508))
+			mmio_write_32(CRU_BASE + i, store_cru[i / 4]);
+		else
+			mmio_write_32(CRU_BASE + i,
+				      REG_SOC_WMSK | store_cru[i / 4]);
+	}
+}
+
+void wdt_register_save(void)
+{
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		store_wdt0[i] = mmio_read_32(WDT0_BASE + i * 4);
+		store_wdt1[i] = mmio_read_32(WDT1_BASE + i * 4);
+	}
+}
+
+void wdt_register_restore(void)
+{
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		mmio_write_32(WDT0_BASE + i * 4, store_wdt0[i]);
+		mmio_write_32(WDT1_BASE + i * 4, store_wdt1[i]);
+	}
+}
+
 int rockchip_soc_sys_pwr_dm_suspend(void)
 {
 	uint32_t wait_cnt = 0;
 	uint32_t status = 0;
 
 	ddr_prepare_for_sys_suspend();
-	dmc_save();
+	dmc_suspend();
 	pmu_scu_b_pwrdn();
 
+	/* need to save usbphy before shutdown PERIHP PD */
+	save_usbphy();
+
 	pmu_power_domains_suspend();
 	set_hw_idle(BIT(PMU_CLR_CENTER1) |
 		    BIT(PMU_CLR_ALIVE) |
@@ -1096,7 +1341,7 @@
 		    BIT(PMU_CLR_PERILP) |
 		    BIT(PMU_CLR_PERILPM0) |
 		    BIT(PMU_CLR_GIC));
-
+	set_pmu_rsthold();
 	sys_slp_config();
 
 	m0_configure_suspend();
@@ -1139,8 +1384,13 @@
 
 	suspend_apio();
 	suspend_gpio();
-
+	suspend_uart();
+	grf_register_save();
+	cru_register_save();
+	wdt_register_save();
 	sram_save();
+	plat_rockchip_save_gpio();
+
 	return 0;
 }
 
@@ -1149,6 +1399,11 @@
 	uint32_t wait_cnt = 0;
 	uint32_t status = 0;
 
+	plat_rockchip_restore_gpio();
+	wdt_register_restore();
+	cru_register_restore();
+	grf_register_restore();
+	resume_uart();
 	resume_apio();
 	resume_gpio();
 	enable_nodvfs_plls();
@@ -1158,6 +1413,8 @@
 	enable_dvfs_plls();
 
 	secure_watchdog_enable();
+	secure_sgrf_init();
+	secure_sgrf_ddr_rgn_init();
 
 	/* restore clk_ddrc_bpll_src_en gate */
 	mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(3),
@@ -1211,10 +1468,8 @@
 	pmu_scu_b_pwrup();
 	pmu_power_domains_resume();
 
-	restore_dpll();
-	sram_func_set_ddrctl_pll(DPLL_ID);
 	restore_abpll();
-
+	restore_pmu_rsthold();
 	clr_hw_idle(BIT(PMU_CLR_CENTER1) |
 				BIT(PMU_CLR_ALIVE) |
 				BIT(PMU_CLR_MSCH0) |
@@ -1229,6 +1484,8 @@
 	plat_rockchip_gic_cpuif_enable();
 	m0_stop();
 
+	restore_usbphy();
+
 	ddr_prepare_for_sys_resume();
 
 	return 0;
diff --git a/plat/rockchip/rk3399/drivers/secure/secure.c b/plat/rockchip/rk3399/drivers/secure/secure.c
index 6b4f3b8..589d833 100644
--- a/plat/rockchip/rk3399/drivers/secure/secure.c
+++ b/plat/rockchip/rk3399/drivers/secure/secure.c
@@ -101,6 +101,19 @@
 		      WMSK_BIT(PCLK_WDT_CM0_GATE_SHIFT));
 }
 
+__pmusramfunc void sram_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 secure_timer_init(void)
 {
 	mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_END_COUNT0, 0xffffffff);
diff --git a/plat/rockchip/rk3399/drivers/secure/secure.h b/plat/rockchip/rk3399/drivers/secure/secure.h
index 7784ae7..334805d 100644
--- a/plat/rockchip/rk3399/drivers/secure/secure.h
+++ b/plat/rockchip/rk3399/drivers/secure/secure.h
@@ -100,5 +100,6 @@
 void secure_timer_init(void);
 void secure_sgrf_init(void);
 void secure_sgrf_ddr_rgn_init(void);
+__pmusramfunc void sram_secure_timer_init(void);
 
 #endif /* __PLAT_ROCKCHIP_RK3399_DRIVER_SECURE_H__ */
diff --git a/plat/rockchip/rk3399/drivers/soc/soc.c b/plat/rockchip/rk3399/drivers/soc/soc.c
index 993b80a..7dd0b72 100644
--- a/plat/rockchip/rk3399/drivers/soc/soc.c
+++ b/plat/rockchip/rk3399/drivers/soc/soc.c
@@ -171,11 +171,6 @@
 	restore_pll(ABPLL_ID, slp_data.plls_con[ABPLL_ID]);
 }
 
-void restore_dpll(void)
-{
-	restore_pll(DPLL_ID, slp_data.plls_con[DPLL_ID]);
-}
-
 void clk_gate_con_save(void)
 {
 	uint32_t i = 0;
@@ -229,6 +224,47 @@
 	set_pll_normal_mode(pll_id);
 }
 
+void set_pmu_rsthold(void)
+{
+	uint32_t rstnhold_cofig0;
+	uint32_t rstnhold_cofig1;
+
+	slp_data.pmucru_rstnhold_con0 = mmio_read_32(PMUCRU_BASE +
+					    PMUCRU_RSTNHOLD_CON0);
+	slp_data.pmucru_rstnhold_con1 = mmio_read_32(PMUCRU_BASE +
+					    PMUCRU_RSTNHOLD_CON1);
+	rstnhold_cofig0 = BIT_WITH_WMSK(PRESETN_NOC_PMU_HOLD) |
+			  BIT_WITH_WMSK(PRESETN_INTMEM_PMU_HOLD) |
+			  BIT_WITH_WMSK(HRESETN_CM0S_PMU_HOLD) |
+			  BIT_WITH_WMSK(HRESETN_CM0S_NOC_PMU_HOLD) |
+			  BIT_WITH_WMSK(DRESETN_CM0S_PMU_HOLD) |
+			  BIT_WITH_WMSK(POESETN_CM0S_PMU_HOLD) |
+			  BIT_WITH_WMSK(PRESETN_TIMER_PMU_0_1_HOLD) |
+			  BIT_WITH_WMSK(RESETN_TIMER_PMU_0_HOLD) |
+			  BIT_WITH_WMSK(RESETN_TIMER_PMU_1_HOLD) |
+			  BIT_WITH_WMSK(PRESETN_UART_M0_PMU_HOLD) |
+			  BIT_WITH_WMSK(RESETN_UART_M0_PMU_HOLD) |
+			  BIT_WITH_WMSK(PRESETN_WDT_PMU_HOLD);
+	rstnhold_cofig1 = BIT_WITH_WMSK(PRESETN_RKPWM_PMU_HOLD) |
+			  BIT_WITH_WMSK(PRESETN_PMUGRF_HOLD) |
+			  BIT_WITH_WMSK(PRESETN_SGRF_HOLD) |
+			  BIT_WITH_WMSK(PRESETN_GPIO0_HOLD) |
+			  BIT_WITH_WMSK(PRESETN_GPIO1_HOLD) |
+			  BIT_WITH_WMSK(PRESETN_CRU_PMU_HOLD) |
+			  BIT_WITH_WMSK(PRESETN_PVTM_PMU_HOLD);
+
+	mmio_write_32(PMUCRU_BASE + PMUCRU_RSTNHOLD_CON0, rstnhold_cofig0);
+	mmio_write_32(PMUCRU_BASE + PMUCRU_RSTNHOLD_CON1, rstnhold_cofig1);
+}
+
+void restore_pmu_rsthold(void)
+{
+	mmio_write_32(PMUCRU_BASE + PMUCRU_RSTNHOLD_CON0,
+		      slp_data.pmucru_rstnhold_con0 | REG_SOC_WMSK);
+	mmio_write_32(PMUCRU_BASE + PMUCRU_RSTNHOLD_CON1,
+		      slp_data.pmucru_rstnhold_con1 | REG_SOC_WMSK);
+}
+
 /**
  * enable_dvfs_plls - To resume the specific PLLs
  *
diff --git a/plat/rockchip/rk3399/drivers/soc/soc.h b/plat/rockchip/rk3399/drivers/soc/soc.h
index 8d1fd13..6100d95 100644
--- a/plat/rockchip/rk3399/drivers/soc/soc.h
+++ b/plat/rockchip/rk3399/drivers/soc/soc.h
@@ -56,6 +56,43 @@
 #define PMUCRU_GATE_CON(n)	(0x100 + (n) * 4)
 #define CRU_GATE_CON(n)	(0x300 + (n) * 4)
 
+#define PMUCRU_RSTNHOLD_CON0	0x120
+enum {
+	PRESETN_NOC_PMU_HOLD = 1,
+	PRESETN_INTMEM_PMU_HOLD,
+	HRESETN_CM0S_PMU_HOLD,
+	HRESETN_CM0S_NOC_PMU_HOLD,
+	DRESETN_CM0S_PMU_HOLD,
+	POESETN_CM0S_PMU_HOLD,
+	PRESETN_SPI3_HOLD,
+	RESETN_SPI3_HOLD,
+	PRESETN_TIMER_PMU_0_1_HOLD,
+	RESETN_TIMER_PMU_0_HOLD,
+	RESETN_TIMER_PMU_1_HOLD,
+	PRESETN_UART_M0_PMU_HOLD,
+	RESETN_UART_M0_PMU_HOLD,
+	PRESETN_WDT_PMU_HOLD
+};
+
+#define PMUCRU_RSTNHOLD_CON1	0x124
+enum {
+	PRESETN_I2C0_HOLD,
+	PRESETN_I2C4_HOLD,
+	PRESETN_I2C8_HOLD,
+	PRESETN_MAILBOX_PMU_HOLD,
+	PRESETN_RKPWM_PMU_HOLD,
+	PRESETN_PMUGRF_HOLD,
+	PRESETN_SGRF_HOLD,
+	PRESETN_GPIO0_HOLD,
+	PRESETN_GPIO1_HOLD,
+	PRESETN_CRU_PMU_HOLD,
+	PRESETN_INTR_ARB_HOLD,
+	PRESETN_PVTM_PMU_HOLD,
+	RESETN_I2C0_HOLD,
+	RESETN_I2C4_HOLD,
+	RESETN_I2C8_HOLD
+};
+
 enum plls_id {
 	ALPLL_ID = 0,
 	ABPLL_ID,
@@ -97,6 +134,8 @@
 	uint32_t plls_con[END_PLL_ID][PLL_CON_COUNT];
 	uint32_t cru_gate_con[CRU_GATE_COUNT];
 	uint32_t pmucru_gate_con[PMUCRU_GATE_COUNT];
+	uint32_t pmucru_rstnhold_con0;
+	uint32_t pmucru_rstnhold_con1;
 };
 
 /**************************************************
@@ -189,13 +228,35 @@
 #define PWM_ENABLE			(1 << 0)
 
 /* grf reg offset */
+#define GRF_USBPHY0_CTRL0	0x4480
+#define GRF_USBPHY0_CTRL2	0x4488
+#define GRF_USBPHY0_CTRL3	0x448c
+#define GRF_USBPHY0_CTRL12	0x44b0
+#define GRF_USBPHY0_CTRL13	0x44b4
+#define GRF_USBPHY0_CTRL15	0x44bc
+#define GRF_USBPHY0_CTRL16	0x44c0
+
+#define GRF_USBPHY1_CTRL0	0x4500
+#define GRF_USBPHY1_CTRL2	0x4508
+#define GRF_USBPHY1_CTRL3	0x450c
+#define GRF_USBPHY1_CTRL12	0x4530
+#define GRF_USBPHY1_CTRL13	0x4534
+#define GRF_USBPHY1_CTRL15	0x453c
+#define GRF_USBPHY1_CTRL16	0x4540
+
+#define GRF_GPIO2A_IOMUX	0xe000
+#define GRF_GPIO2D_HE		0xe18c
 #define GRF_DDRC0_CON0		0xe380
 #define GRF_DDRC0_CON1		0xe384
 #define GRF_DDRC1_CON0		0xe388
 #define GRF_DDRC1_CON1		0xe38c
 #define GRF_SOC_CON_BASE	0xe200
 #define GRF_SOC_CON(n)		(GRF_SOC_CON_BASE + (n) * 4)
+#define GRF_IO_VSEL		0xe640
 
+#define CRU_CLKSEL_CON0		0x0100
+#define CRU_CLKSEL_CON6		0x0118
+#define CRU_SDIO0_CON1		0x058c
 #define PMUCRU_CLKSEL_CON0	0x0080
 #define PMUCRU_CLKGATE_CON2	0x0108
 #define PMUCRU_SOFTRST_CON0	0x0110
@@ -231,9 +292,9 @@
 void enable_nodvfs_plls(void);
 void prepare_abpll_for_ddrctrl(void);
 void restore_abpll(void);
-void restore_dpll(void);
 void clk_gate_con_save(void);
 void clk_gate_con_disable(void);
 void clk_gate_con_restore(void);
-
+void set_pmu_rsthold(void);
+void restore_pmu_rsthold(void);
 #endif /* __SOC_H__ */
diff --git a/plat/rockchip/rk3399/include/shared/addressmap_shared.h b/plat/rockchip/rk3399/include/shared/addressmap_shared.h
index fe23e56..dc5c8d5 100644
--- a/plat/rockchip/rk3399/include/shared/addressmap_shared.h
+++ b/plat/rockchip/rk3399/include/shared/addressmap_shared.h
@@ -40,6 +40,9 @@
 #define GPIO2_BASE		(MMIO_BASE + 0x07780000)
 #define GPIO3_BASE		(MMIO_BASE + 0x07788000)
 #define GPIO4_BASE		(MMIO_BASE + 0x07790000)
+#define WDT1_BASE		(MMIO_BASE + 0x07840000)
+#define WDT0_BASE		(MMIO_BASE + 0x07848000)
+#define TIMER_BASE		(MMIO_BASE + 0x07850000)
 #define STIME_BASE		(MMIO_BASE + 0x07860000)
 #define SRAM_BASE		(MMIO_BASE + 0x078C0000)
 #define SERVICE_NOC_0_BASE	(MMIO_BASE + 0x07A50000)