diff --git a/plat/rockchip/common/plat_pm.c b/plat/rockchip/common/plat_pm.c index d28100d9c..e926345be 100644 --- a/plat/rockchip/common/plat_pm.c +++ b/plat/rockchip/common/plat_pm.c @@ -317,18 +317,6 @@ static void __dead2 rockchip_system_poweroff(void) rockchip_ops->system_off(); } -static void -__dead2 rockchip_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state) -{ - if ((RK_CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) && - (rockchip_ops)) { - if (RK_SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE && - rockchip_ops->sys_pwr_down_wfi) - rockchip_ops->sys_pwr_down_wfi(target_state); - } - psci_power_down_wfi(); -} - /******************************************************************************* * Export the platform handlers via plat_rockchip_psci_pm_ops. The rockchip * standard @@ -341,7 +329,6 @@ const plat_psci_ops_t plat_rockchip_psci_pm_ops = { .pwr_domain_suspend = rockchip_pwr_domain_suspend, .pwr_domain_on_finish = rockchip_pwr_domain_on_finish, .pwr_domain_suspend_finish = rockchip_pwr_domain_suspend_finish, - .pwr_domain_pwr_down_wfi = rockchip_pwr_domain_pwr_down_wfi, .system_reset = rockchip_system_reset, .system_off = rockchip_system_poweroff, .validate_power_state = rockchip_validate_power_state, diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu.c b/plat/rockchip/rk3399/drivers/pmu/pmu.c index 4ae766cea..8d3f482f4 100644 --- a/plat/rockchip/rk3399/drivers/pmu/pmu.c +++ b/plat/rockchip/rk3399/drivers/pmu/pmu.c @@ -48,6 +48,7 @@ #include #include #include +#include DEFINE_BAKERY_LOCK(rockchip_pd_lock); @@ -840,8 +841,6 @@ static void sys_slp_config(void) BIT(PMU_SCU_PD_EN) | BIT(PMU_CCI_PD_EN) | BIT(PMU_CLK_CORE_SRC_GATE_EN) | - BIT(PMU_PERILP_PD_EN) | - BIT(PMU_CLK_PERILP_SRC_GATE_EN) | BIT(PMU_ALIVE_USE_LF) | BIT(PMU_SREF0_ENTER_EN) | BIT(PMU_SREF1_ENTER_EN) | @@ -1058,6 +1057,38 @@ static void resume_gpio(void) } } +static void m0_clock_init(void) +{ + /* enable clocks for M0 */ + mmio_write_32(PMUCRU_BASE + PMUCRU_CLKGATE_CON2, + BITS_WITH_WMASK(0x0, 0x2f, 0)); + + /* switch the parent to xin24M and div == 1 */ + mmio_write_32(PMUCRU_BASE + PMUCRU_CLKSEL_CON0, + BIT_WITH_WMSK(15) | BITS_WITH_WMASK(0x0, 0x1f, 8)); + + /* start M0 */ + mmio_write_32(PMUCRU_BASE + PMUCRU_SOFTRST_CON0, + BITS_WITH_WMASK(0x0, 0x24, 0)); + + /* gating disable for M0 */ + mmio_write_32(PMUCRU_BASE + PMUCRU_GATEDIS_CON0, BIT_WITH_WMSK(1)); +} + +static void m0_reset(void) +{ + /* stop M0 */ + mmio_write_32(PMUCRU_BASE + PMUCRU_SOFTRST_CON0, + BITS_WITH_WMASK(0x24, 0x24, 0)); + + /* recover gating bit for M0 */ + mmio_write_32(PMUCRU_BASE + PMUCRU_GATEDIS_CON0, WMSK_BIT(1)); + + /* disable clocks for M0 */ + mmio_write_32(PMUCRU_BASE + PMUCRU_CLKGATE_CON2, + BITS_WITH_WMASK(0x2f, 0x2f, 0)); +} + static int sys_pwr_domain_suspend(void) { uint32_t wait_cnt = 0; @@ -1071,12 +1102,12 @@ static int sys_pwr_domain_suspend(void) BIT(PMU_CLR_CCIM0) | BIT(PMU_CLR_CCIM1) | BIT(PMU_CLR_CENTER) | - BIT(PMU_CLR_PERILP) | - BIT(PMU_CLR_PMU) | - BIT(PMU_CLR_PERILPM0) | BIT(PMU_CLR_GIC)); sys_slp_config(); + + m0_clock_init(); + pmu_sgrf_rst_hld(); mmio_write_32(SGRF_BASE + SGRF_SOC_CON0_1(1), @@ -1111,6 +1142,7 @@ static int sys_pwr_domain_suspend(void) disable_dvfs_plls(); disable_pwms(); disable_nodvfs_plls(); + suspend_apio(); suspend_gpio(); @@ -1186,12 +1218,12 @@ static int sys_pwr_domain_resume(void) BIT(PMU_CLR_CCIM0) | BIT(PMU_CLR_CCIM1) | BIT(PMU_CLR_CENTER) | - BIT(PMU_CLR_PERILP) | - BIT(PMU_CLR_PMU) | BIT(PMU_CLR_GIC)); plat_rockchip_gic_cpuif_enable(); + m0_reset(); + return 0; } @@ -1236,42 +1268,6 @@ void __dead2 soc_system_off(void) while (1) ; } -static void __dead2 sys_pwr_down_wfi(const psci_power_state_t *target_state) -{ - uint32_t wakeup_status; - - /* - * Check wakeup status and abort suspend early if we see a wakeup - * event. - * - * NOTE: technically I we're supposed to just execute a wfi here and - * we'll either execute a normal suspend/resume or the wfi will be - * treated as a no-op if a wake event was present and caused an abort - * of the suspend/resume. For some reason that's not happening and if - * we execute the wfi while a wake event is pending then the whole - * system wedges. - * - * Until the above is solved this extra check prevents system wedges in - * most cases but there is still a small race condition between checking - * PMU_WAKEUP_STATUS and executing wfi. If a wake event happens in - * there then we will die. - */ - wakeup_status = mmio_read_32(PMU_BASE + PMU_WAKEUP_STATUS); - if (wakeup_status) { - WARN("early wake, will not enter power mode.\n"); - - mmio_write_32(PMU_BASE + PMU_PWRMODE_CON, 0); - - disable_mmu_icache_el3(); - bl31_warm_entrypoint(); - - while (1) - ; - } else { - /* Enter WFI */ - psci_power_down_wfi(); - } -} static struct rockchip_pm_ops_cb pm_ops = { .cores_pwr_dm_on = cores_pwr_domain_on, @@ -1287,7 +1283,6 @@ static struct rockchip_pm_ops_cb pm_ops = { .sys_pwr_dm_resume = sys_pwr_domain_resume, .sys_gbl_soft_reset = soc_soft_reset, .system_off = soc_system_off, - .sys_pwr_down_wfi = sys_pwr_down_wfi, }; void plat_rockchip_pmu_init(void) diff --git a/plat/rockchip/rk3399/drivers/soc/soc.c b/plat/rockchip/rk3399/drivers/soc/soc.c index 29bf6dda3..2dc70ec2e 100644 --- a/plat/rockchip/rk3399/drivers/soc/soc.c +++ b/plat/rockchip/rk3399/drivers/soc/soc.c @@ -35,6 +35,7 @@ #include #include #include +#include #include /* Table of regions to map using the MMU. */ @@ -380,6 +381,20 @@ void __dead2 soc_global_soft_reset(void) ; } +static void soc_m0_init(void) +{ + /* secure config for pmu M0 */ + mmio_write_32(SGRF_BASE + SGRF_PMU_CON(0), WMSK_BIT(7)); + + /* set the execute address for M0 */ + mmio_write_32(SGRF_BASE + SGRF_PMU_CON(3), + BITS_WITH_WMASK((M0_BINCODE_BASE >> 12) & 0xffff, + 0xffff, 0)); + mmio_write_32(SGRF_BASE + SGRF_PMU_CON(7), + BITS_WITH_WMASK((M0_BINCODE_BASE >> 28) & 0xf, + 0xf, 0)); +} + void plat_rockchip_soc_init(void) { secure_timer_init(); @@ -387,4 +402,5 @@ void plat_rockchip_soc_init(void) sgrf_init(); soc_global_soft_reset_init(); plat_rockchip_gpio_init(); + soc_m0_init(); } diff --git a/plat/rockchip/rk3399/drivers/soc/soc.h b/plat/rockchip/rk3399/drivers/soc/soc.h index 906452a38..da4cb54e7 100644 --- a/plat/rockchip/rk3399/drivers/soc/soc.h +++ b/plat/rockchip/rk3399/drivers/soc/soc.h @@ -293,6 +293,18 @@ struct deepsleep_data_s { #define GRF_DDRC1_CON0 0xe388 #define GRF_DDRC1_CON1 0xe38c +#define PMUCRU_CLKSEL_CON0 0x0080 +#define PMUCRU_CLKGATE_CON2 0x0108 +#define PMUCRU_SOFTRST_CON0 0x0110 +#define PMUCRU_GATEDIS_CON0 0x0130 + +#define SGRF_SOC_CON6 0x0e018 +#define SGRF_PERILP_CON0 0x08100 +#define SGRF_PERILP_CON(n) (SGRF_PERILP_CON0 + (n) * 4) +#define SGRF_PMU_CON0 0x0c100 +#define SGRF_PMU_CON(n) (SGRF_PMU_CON0 + (n) * 4) +#define PMUCRU_SOFTRST_CON(n) (PMUCRU_SOFTRST_CON0 + (n) * 4) + /* * When system reset in running state, we want the cpus to be reboot * from maskrom (system reboot),