summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plat/rockchip/common/include/plat_private.h2
-rw-r--r--plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c114
-rw-r--r--plat/rockchip/rk3399/drivers/pmu/pmu.c183
-rw-r--r--plat/rockchip/rk3399/drivers/soc/soc.h21
-rw-r--r--plat/rockchip/rk3399/include/shared/addressmap_shared.h3
5 files changed, 321 insertions, 2 deletions
diff --git a/plat/rockchip/common/include/plat_private.h b/plat/rockchip/common/include/plat_private.h
index 290811a2..54567735 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_gpio_poweroff(void);
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/rk3399/drivers/gpio/rk3399_gpio.c b/plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c
index d5a26609..e74c4d91 100644
--- a/plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c
+++ b/plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c
@@ -22,10 +22,29 @@ uint32_t gpio_port[] = {
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 @@ static void set_value(int gpio, int value)
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 d97b0463..7f246c2f 100644
--- a/plat/rockchip/rk3399/drivers/pmu/pmu.c
+++ b/plat/rockchip/rk3399/drivers/pmu/pmu.c
@@ -32,6 +32,19 @@ DEFINE_BAKERY_LOCK(rockchip_pd_lock);
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 @@ void resume_uart(void)
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 @@ int rockchip_soc_sys_pwr_dm_suspend(void)
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 @@ int rockchip_soc_sys_pwr_dm_suspend(void)
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 @@ int rockchip_soc_sys_pwr_dm_resume(void)
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 @@ int rockchip_soc_sys_pwr_dm_resume(void)
plat_rockchip_gic_cpuif_enable();
m0_stop();
+ restore_usbphy();
+
ddr_prepare_for_sys_resume();
return 0;
diff --git a/plat/rockchip/rk3399/drivers/soc/soc.h b/plat/rockchip/rk3399/drivers/soc/soc.h
index 9680beab..c4183373 100644
--- a/plat/rockchip/rk3399/drivers/soc/soc.h
+++ b/plat/rockchip/rk3399/drivers/soc/soc.h
@@ -189,14 +189,35 @@ struct deepsleep_data_s {
#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
diff --git a/plat/rockchip/rk3399/include/shared/addressmap_shared.h b/plat/rockchip/rk3399/include/shared/addressmap_shared.h
index fe23e569..dc5c8d56 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)