rockchip/rk3399: save and restore pd_alive register

pd_alive control cru, grf, timer, gpio and wdt, when
turn off logic power rail, these register value will
back to reset value, we need to save them value in suspend
and restore them when resuem, since timer will reinitial
in kernel, so it not need to save/restore.

Change-Id: I0fc2a011d3cdc04b66ffbf728e769eb28b51ee38
Signed-off-by: Lin Huang <hl@rock-chips.com>
diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu.c b/plat/rockchip/rk3399/drivers/pmu/pmu.c
index d97b046..7f246c2 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.
@@ -1132,6 +1145,161 @@
 	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;
@@ -1141,6 +1309,9 @@
 	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) |
@@ -1196,8 +1367,12 @@
 	suspend_apio();
 	suspend_gpio();
 	suspend_uart();
-
+	grf_register_save();
+	cru_register_save();
+	wdt_register_save();
 	sram_save();
+	plat_rockchip_save_gpio();
+
 	return 0;
 }
 
@@ -1206,6 +1381,10 @@
 	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();
@@ -1285,6 +1464,8 @@
 	plat_rockchip_gic_cpuif_enable();
 	m0_stop();
 
+	restore_usbphy();
+
 	ddr_prepare_for_sys_resume();
 
 	return 0;