Support for Rockchip's family SoCs

This patch adds to support the RK3368 and RK3399 SoCs.

RK3368/RK3399 is one of the Rockchip family SoCs, which is an
multi-cores ARM SoCs.

This patch adds support to boot the Trusted Firmware on RK3368/RK3399
SoCs, and adds support to boot secondary CPUs, enter/exit core
power states for all CPUs in the slow/fast clusters.

This is the initial version for rockchip SoCs.(RK3368/RK3399 and next SoCs)
* Support arm gicv2 & gicv3.
* Boot up multi-cores CPU.
* Add generic CPU helper functions.
* Support suspend/resume.
* Add system_off & system_reset implementation.
* Add delay timer platform implementation.
* Support the new porting interface for the PSCI implementation.

Change-Id: I704bb3532d65e8c70dbd99b512c5e6e440ea6f43
Signed-off-by: Tony Xie <tony.xie@rock-chips.com>
Signed-off-by: Caesar Wang <wxt@rock-chips.com>
Signed-off-by: Shengfei xu <xsf@rock-chips.com>
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__ */