diff options
author | danh-arm <dan.handley@arm.com> | 2017-08-29 11:52:04 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-08-29 11:52:04 +0100 |
commit | 6328f76b0cc0ef809cd3b754ac37046ade8e04f4 (patch) | |
tree | d93fb553bb0a6a967845564035531d2b73a89c5a | |
parent | 48f4bcd2ec9eeec58ff06e8b96094e0b0544ef5e (diff) | |
parent | dbc0f2dcc0cf4960e2a6064ddf50df9ce1513ec0 (diff) | |
download | platform_external_arm-trusted-firmware-6328f76b0cc0ef809cd3b754ac37046ade8e04f4.tar.gz platform_external_arm-trusted-firmware-6328f76b0cc0ef809cd3b754ac37046ade8e04f4.tar.bz2 platform_external_arm-trusted-firmware-6328f76b0cc0ef809cd3b754ac37046ade8e04f4.zip |
Merge pull request #1070 from rockchip-linux/rk3399-fixes-logic
rockchip/rk3399: Support Turning off VD_LOGIC during suspend-to-ram
-rw-r--r-- | plat/rockchip/common/include/plat_private.h | 2 | ||||
-rw-r--r-- | plat/rockchip/common/pmusram/pmu_sram_cpus_on.S | 2 | ||||
-rw-r--r-- | plat/rockchip/rk3399/drivers/dram/dram.h | 6 | ||||
-rw-r--r-- | plat/rockchip/rk3399/drivers/dram/suspend.c | 57 | ||||
-rw-r--r-- | plat/rockchip/rk3399/drivers/dram/suspend.h | 4 | ||||
-rw-r--r-- | plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c | 114 | ||||
-rw-r--r-- | plat/rockchip/rk3399/drivers/pmu/pmu.c | 269 | ||||
-rw-r--r-- | plat/rockchip/rk3399/drivers/secure/secure.c | 13 | ||||
-rw-r--r-- | plat/rockchip/rk3399/drivers/secure/secure.h | 1 | ||||
-rw-r--r-- | plat/rockchip/rk3399/drivers/soc/soc.c | 46 | ||||
-rw-r--r-- | plat/rockchip/rk3399/drivers/soc/soc.h | 65 | ||||
-rw-r--r-- | plat/rockchip/rk3399/include/shared/addressmap_shared.h | 3 |
12 files changed, 550 insertions, 32 deletions
diff --git a/plat/rockchip/common/include/plat_private.h b/plat/rockchip/common/include/plat_private.h index 290811a26..545677352 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/common/pmusram/pmu_sram_cpus_on.S b/plat/rockchip/common/pmusram/pmu_sram_cpus_on.S index 22bdffcae..5a1854b42 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 @@ sys_wakeup: 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 fede7eef8..0780fc3a2 100644 --- a/plat/rockchip/rk3399/drivers/dram/dram.h +++ b/plat/rockchip/rk3399/drivers/dram/dram.h @@ -25,10 +25,10 @@ struct rk3399_ddr_pctl_regs { 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 686774498..f66150ae8 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 @@ static __pmusramfunc void pctl_cfg(uint32_t ch, 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 @@ static __pmusramfunc int pctl_start(uint32_t channel_mask, return 0; } -void dmc_save(void) +__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_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; - 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); + /* 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 = 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 @@ void dmc_save(void) /* 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 @@ void dmc_save(void) 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 77f9c317b..a8a864108 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 d5a266093..e74c4d91a 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 6b420c24c..c666c3c20 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. @@ -323,6 +336,11 @@ static void pmu_power_domains_suspend(void) 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 @@ static void pmu_power_domains_resume(void) 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 @@ static void sys_slp_config(void) 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 @@ static void sys_slp_config(void) 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 @@ void sram_restore(void) 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 @@ int rockchip_soc_sys_pwr_dm_suspend(void) 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 @@ 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; } @@ -1149,6 +1399,11 @@ 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(); enable_nodvfs_plls(); @@ -1158,6 +1413,8 @@ int rockchip_soc_sys_pwr_dm_resume(void) 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 @@ int rockchip_soc_sys_pwr_dm_resume(void) 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 @@ 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/secure/secure.c b/plat/rockchip/rk3399/drivers/secure/secure.c index 6b4f3b894..589d833c8 100644 --- a/plat/rockchip/rk3399/drivers/secure/secure.c +++ b/plat/rockchip/rk3399/drivers/secure/secure.c @@ -101,6 +101,19 @@ void secure_watchdog_enable(void) 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 7784ae761..334805d0d 100644 --- a/plat/rockchip/rk3399/drivers/secure/secure.h +++ b/plat/rockchip/rk3399/drivers/secure/secure.h @@ -100,5 +100,6 @@ void secure_watchdog_enable(void); 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 993b80ad4..7dd0b72e2 100644 --- a/plat/rockchip/rk3399/drivers/soc/soc.c +++ b/plat/rockchip/rk3399/drivers/soc/soc.c @@ -171,11 +171,6 @@ void restore_abpll(void) 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 @@ static void _pll_resume(uint32_t pll_id) 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 8d1fd13ff..6100d9558 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 @@ struct deepsleep_data_s { 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 @@ 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 @@ -231,9 +292,9 @@ void enable_dvfs_plls(void); 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 fe23e5690..dc5c8d568 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) |