16fba6e04STony Xie /* 26fba6e04STony Xie * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. 36fba6e04STony Xie * 46fba6e04STony Xie * Redistribution and use in source and binary forms, with or without 56fba6e04STony Xie * modification, are permitted provided that the following conditions are met: 66fba6e04STony Xie * 76fba6e04STony Xie * Redistributions of source code must retain the above copyright notice, this 86fba6e04STony Xie * list of conditions and the following disclaimer. 96fba6e04STony Xie * 106fba6e04STony Xie * Redistributions in binary form must reproduce the above copyright notice, 116fba6e04STony Xie * this list of conditions and the following disclaimer in the documentation 126fba6e04STony Xie * and/or other materials provided with the distribution. 136fba6e04STony Xie * 146fba6e04STony Xie * Neither the name of ARM nor the names of its contributors may be used 156fba6e04STony Xie * to endorse or promote products derived from this software without specific 166fba6e04STony Xie * prior written permission. 176fba6e04STony Xie * 186fba6e04STony Xie * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 196fba6e04STony Xie * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 206fba6e04STony Xie * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 216fba6e04STony Xie * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 226fba6e04STony Xie * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 236fba6e04STony Xie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 246fba6e04STony Xie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 256fba6e04STony Xie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 266fba6e04STony Xie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 276fba6e04STony Xie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 286fba6e04STony Xie * POSSIBILITY OF SUCH DAMAGE. 296fba6e04STony Xie */ 306fba6e04STony Xie 316fba6e04STony Xie #include <arch_helpers.h> 326fba6e04STony Xie #include <assert.h> 336fba6e04STony Xie #include <bakery_lock.h> 346fba6e04STony Xie #include <debug.h> 356fba6e04STony Xie #include <delay_timer.h> 366fba6e04STony Xie #include <errno.h> 376fba6e04STony Xie #include <mmio.h> 386fba6e04STony Xie #include <platform.h> 396fba6e04STony Xie #include <platform_def.h> 406fba6e04STony Xie #include <plat_private.h> 416fba6e04STony Xie #include <rk3399_def.h> 426fba6e04STony Xie #include <pmu_sram.h> 436fba6e04STony Xie #include <soc.h> 446fba6e04STony Xie #include <pmu.h> 456fba6e04STony Xie #include <pmu_com.h> 466fba6e04STony Xie 476fba6e04STony Xie static struct psram_data_t *psram_sleep_cfg = 486fba6e04STony Xie (struct psram_data_t *)PSRAM_DT_BASE; 496fba6e04STony Xie 50f47a25ddSCaesar Wang static uint32_t cpu_warm_boot_addr; 51f47a25ddSCaesar Wang 526fba6e04STony Xie /* 536fba6e04STony Xie * There are two ways to powering on or off on core. 546fba6e04STony Xie * 1) Control it power domain into on or off in PMU_PWRDN_CON reg, 556fba6e04STony Xie * it is core_pwr_pd mode 566fba6e04STony Xie * 2) Enable the core power manage in PMU_CORE_PM_CON reg, 576fba6e04STony Xie * then, if the core enter into wfi, it power domain will be 586fba6e04STony Xie * powered off automatically. it is core_pwr_wfi or core_pwr_wfi_int mode 596fba6e04STony Xie * so we need core_pm_cfg_info to distinguish which method be used now. 606fba6e04STony Xie */ 616fba6e04STony Xie 626fba6e04STony Xie static uint32_t core_pm_cfg_info[PLATFORM_CORE_COUNT] 636fba6e04STony Xie #if USE_COHERENT_MEM 646fba6e04STony Xie __attribute__ ((section("tzfw_coherent_mem"))) 656fba6e04STony Xie #endif 666fba6e04STony Xie ;/* coheront */ 676fba6e04STony Xie 68f47a25ddSCaesar Wang void rk3399_flash_l2_b(void) 69f47a25ddSCaesar Wang { 70f47a25ddSCaesar Wang uint32_t wait_cnt = 0; 71f47a25ddSCaesar Wang 72f47a25ddSCaesar Wang mmio_setbits_32(PMU_BASE + PMU_SFT_CON, BIT(L2_FLUSH_REQ_CLUSTER_B)); 73f47a25ddSCaesar Wang dsb(); 74f47a25ddSCaesar Wang 75f47a25ddSCaesar Wang while (!(mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST) & 76f47a25ddSCaesar Wang BIT(L2_FLUSHDONE_CLUSTER_B))) { 77f47a25ddSCaesar Wang wait_cnt++; 78f47a25ddSCaesar Wang if (!(wait_cnt % MAX_WAIT_CONUT)) 79f47a25ddSCaesar Wang WARN("%s:reg %x,wait\n", __func__, 80f47a25ddSCaesar Wang mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST)); 81f47a25ddSCaesar Wang } 82f47a25ddSCaesar Wang 83f47a25ddSCaesar Wang mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, BIT(L2_FLUSH_REQ_CLUSTER_B)); 84f47a25ddSCaesar Wang } 85f47a25ddSCaesar Wang 86f47a25ddSCaesar Wang static void pmu_scu_b_pwrdn(void) 87f47a25ddSCaesar Wang { 88f47a25ddSCaesar Wang uint32_t wait_cnt = 0; 89f47a25ddSCaesar Wang 90f47a25ddSCaesar Wang if ((mmio_read_32(PMU_BASE + PMU_PWRDN_ST) & 91f47a25ddSCaesar Wang (BIT(PMU_A72_B0_PWRDWN_ST) | BIT(PMU_A72_B1_PWRDWN_ST))) != 92f47a25ddSCaesar Wang (BIT(PMU_A72_B0_PWRDWN_ST) | BIT(PMU_A72_B1_PWRDWN_ST))) { 93f47a25ddSCaesar Wang ERROR("%s: not all cpus is off\n", __func__); 94f47a25ddSCaesar Wang return; 95f47a25ddSCaesar Wang } 96f47a25ddSCaesar Wang 97f47a25ddSCaesar Wang rk3399_flash_l2_b(); 98f47a25ddSCaesar Wang 99f47a25ddSCaesar Wang mmio_setbits_32(PMU_BASE + PMU_SFT_CON, BIT(ACINACTM_CLUSTER_B_CFG)); 100f47a25ddSCaesar Wang 101f47a25ddSCaesar Wang while (!(mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST) & 102f47a25ddSCaesar Wang BIT(STANDBY_BY_WFIL2_CLUSTER_B))) { 103f47a25ddSCaesar Wang wait_cnt++; 104f47a25ddSCaesar Wang if (!(wait_cnt % MAX_WAIT_CONUT)) 105f47a25ddSCaesar Wang ERROR("%s:wait cluster-b l2(%x)\n", __func__, 106f47a25ddSCaesar Wang mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST)); 107f47a25ddSCaesar Wang } 108f47a25ddSCaesar Wang } 109f47a25ddSCaesar Wang 110f47a25ddSCaesar Wang static void pmu_scu_b_pwrup(void) 111f47a25ddSCaesar Wang { 112f47a25ddSCaesar Wang mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, BIT(ACINACTM_CLUSTER_B_CFG)); 113f47a25ddSCaesar Wang } 114f47a25ddSCaesar Wang 1156fba6e04STony Xie void plat_rockchip_pmusram_prepare(void) 1166fba6e04STony Xie { 1176fba6e04STony Xie uint32_t *sram_dst, *sram_src; 1186fba6e04STony Xie size_t sram_size = 2; 1196fba6e04STony Xie 1206fba6e04STony Xie /* 1216fba6e04STony Xie * pmu sram code and data prepare 1226fba6e04STony Xie */ 1236fba6e04STony Xie sram_dst = (uint32_t *)PMUSRAM_BASE; 1246fba6e04STony Xie sram_src = (uint32_t *)&pmu_cpuson_entrypoint_start; 1256fba6e04STony Xie sram_size = (uint32_t *)&pmu_cpuson_entrypoint_end - 1266fba6e04STony Xie (uint32_t *)sram_src; 1276fba6e04STony Xie 1286fba6e04STony Xie u32_align_cpy(sram_dst, sram_src, sram_size); 1296fba6e04STony Xie 1306fba6e04STony Xie psram_sleep_cfg->sp = PSRAM_DT_BASE; 1316fba6e04STony Xie } 1326fba6e04STony Xie 1336fba6e04STony Xie static inline uint32_t get_cpus_pwr_domain_cfg_info(uint32_t cpu_id) 1346fba6e04STony Xie { 135*80fb66b3SSandrine Bailleux assert(cpu_id < PLATFORM_CORE_COUNT); 1366fba6e04STony Xie return core_pm_cfg_info[cpu_id]; 1376fba6e04STony Xie } 1386fba6e04STony Xie 1396fba6e04STony Xie static inline void set_cpus_pwr_domain_cfg_info(uint32_t cpu_id, uint32_t value) 1406fba6e04STony Xie { 141*80fb66b3SSandrine Bailleux assert(cpu_id < PLATFORM_CORE_COUNT); 1426fba6e04STony Xie core_pm_cfg_info[cpu_id] = value; 1436fba6e04STony Xie #if !USE_COHERENT_MEM 1446fba6e04STony Xie flush_dcache_range((uintptr_t)&core_pm_cfg_info[cpu_id], 1456fba6e04STony Xie sizeof(uint32_t)); 1466fba6e04STony Xie #endif 1476fba6e04STony Xie } 1486fba6e04STony Xie 1496fba6e04STony Xie static int cpus_power_domain_on(uint32_t cpu_id) 1506fba6e04STony Xie { 1516fba6e04STony Xie uint32_t cfg_info; 1526fba6e04STony Xie uint32_t cpu_pd = PD_CPUL0 + cpu_id; 1536fba6e04STony Xie /* 1546fba6e04STony Xie * There are two ways to powering on or off on core. 1556fba6e04STony Xie * 1) Control it power domain into on or off in PMU_PWRDN_CON reg 1566fba6e04STony Xie * 2) Enable the core power manage in PMU_CORE_PM_CON reg, 1576fba6e04STony Xie * then, if the core enter into wfi, it power domain will be 1586fba6e04STony Xie * powered off automatically. 1596fba6e04STony Xie */ 1606fba6e04STony Xie 1616fba6e04STony Xie cfg_info = get_cpus_pwr_domain_cfg_info(cpu_id); 1626fba6e04STony Xie 1636fba6e04STony Xie if (cfg_info == core_pwr_pd) { 1646fba6e04STony Xie /* disable core_pm cfg */ 1656fba6e04STony Xie mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), 1666fba6e04STony Xie CORES_PM_DISABLE); 1676fba6e04STony Xie /* if the cores have be on, power off it firstly */ 1686fba6e04STony Xie if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) { 1696fba6e04STony Xie mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), 0); 1706fba6e04STony Xie pmu_power_domain_ctr(cpu_pd, pmu_pd_off); 1716fba6e04STony Xie } 1726fba6e04STony Xie 1736fba6e04STony Xie pmu_power_domain_ctr(cpu_pd, pmu_pd_on); 1746fba6e04STony Xie } else { 1756fba6e04STony Xie if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) { 1766fba6e04STony Xie WARN("%s: cpu%d is not in off,!\n", __func__, cpu_id); 1776fba6e04STony Xie return -EINVAL; 1786fba6e04STony Xie } 1796fba6e04STony Xie 1806fba6e04STony Xie mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), 1816fba6e04STony Xie BIT(core_pm_sft_wakeup_en)); 182f47a25ddSCaesar Wang dsb(); 1836fba6e04STony Xie } 1846fba6e04STony Xie 1856fba6e04STony Xie return 0; 1866fba6e04STony Xie } 1876fba6e04STony Xie 1886fba6e04STony Xie static int cpus_power_domain_off(uint32_t cpu_id, uint32_t pd_cfg) 1896fba6e04STony Xie { 1906fba6e04STony Xie uint32_t cpu_pd; 1916fba6e04STony Xie uint32_t core_pm_value; 1926fba6e04STony Xie 1936fba6e04STony Xie cpu_pd = PD_CPUL0 + cpu_id; 1946fba6e04STony Xie if (pmu_power_domain_st(cpu_pd) == pmu_pd_off) 1956fba6e04STony Xie return 0; 1966fba6e04STony Xie 1976fba6e04STony Xie if (pd_cfg == core_pwr_pd) { 1986fba6e04STony Xie if (check_cpu_wfie(cpu_id, CKECK_WFEI_MSK)) 1996fba6e04STony Xie return -EINVAL; 2006fba6e04STony Xie 2016fba6e04STony Xie /* disable core_pm cfg */ 2026fba6e04STony Xie mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), 2036fba6e04STony Xie CORES_PM_DISABLE); 2046fba6e04STony Xie 2056fba6e04STony Xie set_cpus_pwr_domain_cfg_info(cpu_id, pd_cfg); 2066fba6e04STony Xie pmu_power_domain_ctr(cpu_pd, pmu_pd_off); 2076fba6e04STony Xie } else { 2086fba6e04STony Xie set_cpus_pwr_domain_cfg_info(cpu_id, pd_cfg); 2096fba6e04STony Xie 2106fba6e04STony Xie core_pm_value = BIT(core_pm_en); 2116fba6e04STony Xie if (pd_cfg == core_pwr_wfi_int) 2126fba6e04STony Xie core_pm_value |= BIT(core_pm_int_wakeup_en); 2136fba6e04STony Xie mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), 2146fba6e04STony Xie core_pm_value); 215f47a25ddSCaesar Wang dsb(); 2166fba6e04STony Xie } 2176fba6e04STony Xie 2186fba6e04STony Xie return 0; 2196fba6e04STony Xie } 2206fba6e04STony Xie 2216fba6e04STony Xie static void nonboot_cpus_off(void) 2226fba6e04STony Xie { 2236fba6e04STony Xie uint32_t boot_cpu, cpu; 2246fba6e04STony Xie 2256fba6e04STony Xie boot_cpu = plat_my_core_pos(); 2266fba6e04STony Xie 2276fba6e04STony Xie /* turn off noboot cpus */ 2286fba6e04STony Xie for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) { 2296fba6e04STony Xie if (cpu == boot_cpu) 2306fba6e04STony Xie continue; 2316fba6e04STony Xie cpus_power_domain_off(cpu, core_pwr_pd); 2326fba6e04STony Xie } 2336fba6e04STony Xie } 2346fba6e04STony Xie 2356fba6e04STony Xie static int cores_pwr_domain_on(unsigned long mpidr, uint64_t entrypoint) 2366fba6e04STony Xie { 2376fba6e04STony Xie uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr); 2386fba6e04STony Xie 239*80fb66b3SSandrine Bailleux assert(cpu_id < PLATFORM_CORE_COUNT); 2406fba6e04STony Xie assert(cpuson_flags[cpu_id] == 0); 2416fba6e04STony Xie cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG; 2426fba6e04STony Xie cpuson_entry_point[cpu_id] = entrypoint; 2436fba6e04STony Xie dsb(); 2446fba6e04STony Xie 2456fba6e04STony Xie cpus_power_domain_on(cpu_id); 2466fba6e04STony Xie 2476fba6e04STony Xie return 0; 2486fba6e04STony Xie } 2496fba6e04STony Xie 2506fba6e04STony Xie static int cores_pwr_domain_off(void) 2516fba6e04STony Xie { 2526fba6e04STony Xie uint32_t cpu_id = plat_my_core_pos(); 2536fba6e04STony Xie 2546fba6e04STony Xie cpus_power_domain_off(cpu_id, core_pwr_wfi); 2556fba6e04STony Xie 2566fba6e04STony Xie return 0; 2576fba6e04STony Xie } 2586fba6e04STony Xie 2596fba6e04STony Xie static int cores_pwr_domain_suspend(void) 2606fba6e04STony Xie { 2616fba6e04STony Xie uint32_t cpu_id = plat_my_core_pos(); 2626fba6e04STony Xie 263*80fb66b3SSandrine Bailleux assert(cpu_id < PLATFORM_CORE_COUNT); 2646fba6e04STony Xie assert(cpuson_flags[cpu_id] == 0); 2656fba6e04STony Xie cpuson_flags[cpu_id] = PMU_CPU_AUTO_PWRDN; 2666fba6e04STony Xie cpuson_entry_point[cpu_id] = (uintptr_t)psci_entrypoint; 2676fba6e04STony Xie dsb(); 2686fba6e04STony Xie 2696fba6e04STony Xie cpus_power_domain_off(cpu_id, core_pwr_wfi_int); 2706fba6e04STony Xie 2716fba6e04STony Xie return 0; 2726fba6e04STony Xie } 2736fba6e04STony Xie 2746fba6e04STony Xie static int cores_pwr_domain_on_finish(void) 2756fba6e04STony Xie { 2766fba6e04STony Xie uint32_t cpu_id = plat_my_core_pos(); 2776fba6e04STony Xie 2786fba6e04STony Xie /* Disable core_pm */ 2796fba6e04STony Xie mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), CORES_PM_DISABLE); 2806fba6e04STony Xie 2816fba6e04STony Xie return 0; 2826fba6e04STony Xie } 2836fba6e04STony Xie 2846fba6e04STony Xie static int cores_pwr_domain_resume(void) 2856fba6e04STony Xie { 2866fba6e04STony Xie uint32_t cpu_id = plat_my_core_pos(); 2876fba6e04STony Xie 2886fba6e04STony Xie /* Disable core_pm */ 2896fba6e04STony Xie mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), CORES_PM_DISABLE); 2906fba6e04STony Xie 2916fba6e04STony Xie return 0; 2926fba6e04STony Xie } 2936fba6e04STony Xie 2946fba6e04STony Xie static void sys_slp_config(void) 2956fba6e04STony Xie { 2966fba6e04STony Xie uint32_t slp_mode_cfg = 0; 2976fba6e04STony Xie 298f47a25ddSCaesar Wang mmio_write_32(PMU_BASE + PMU_CCI500_CON, 299f47a25ddSCaesar Wang BIT_WITH_WMSK(PMU_CLR_PREQ_CCI500_HW) | 300f47a25ddSCaesar Wang BIT_WITH_WMSK(PMU_CLR_QREQ_CCI500_HW) | 301f47a25ddSCaesar Wang BIT_WITH_WMSK(PMU_QGATING_CCI500_CFG)); 302f47a25ddSCaesar Wang 303f47a25ddSCaesar Wang mmio_write_32(PMU_BASE + PMU_ADB400_CON, 304f47a25ddSCaesar Wang BIT_WITH_WMSK(PMU_CLR_CORE_L_HW) | 305f47a25ddSCaesar Wang BIT_WITH_WMSK(PMU_CLR_CORE_L_2GIC_HW) | 306f47a25ddSCaesar Wang BIT_WITH_WMSK(PMU_CLR_GIC2_CORE_L_HW)); 307f47a25ddSCaesar Wang 308f47a25ddSCaesar Wang mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO1A_IOMUX, 309f47a25ddSCaesar Wang BIT_WITH_WMSK(AP_PWROFF)); 310f47a25ddSCaesar Wang 311f47a25ddSCaesar Wang slp_mode_cfg = BIT(PMU_PWR_MODE_EN) | 312f47a25ddSCaesar Wang BIT(PMU_POWER_OFF_REQ_CFG) | 313f47a25ddSCaesar Wang BIT(PMU_CPU0_PD_EN) | 314f47a25ddSCaesar Wang BIT(PMU_L2_FLUSH_EN) | 315f47a25ddSCaesar Wang BIT(PMU_L2_IDLE_EN) | 316f47a25ddSCaesar Wang BIT(PMU_SCU_PD_EN); 317f47a25ddSCaesar Wang 3186fba6e04STony Xie mmio_setbits_32(PMU_BASE + PMU_WKUP_CFG4, PMU_CLUSTER_L_WKUP_EN); 3196fba6e04STony Xie mmio_setbits_32(PMU_BASE + PMU_WKUP_CFG4, PMU_CLUSTER_B_WKUP_EN); 3206fba6e04STony Xie mmio_clrbits_32(PMU_BASE + PMU_WKUP_CFG4, PMU_GPIO_WKUP_EN); 321f47a25ddSCaesar Wang 3226fba6e04STony Xie mmio_write_32(PMU_BASE + PMU_PWRMODE_CON, slp_mode_cfg); 323f47a25ddSCaesar Wang 324f47a25ddSCaesar Wang mmio_write_32(PMU_BASE + PMU_STABLE_CNT, CYCL_24M_CNT_MS(5)); 325f47a25ddSCaesar Wang mmio_write_32(PMU_BASE + PMU_SCU_L_PWRDN_CNT, CYCL_24M_CNT_MS(2)); 326f47a25ddSCaesar Wang mmio_write_32(PMU_BASE + PMU_SCU_L_PWRUP_CNT, CYCL_24M_CNT_MS(2)); 327f47a25ddSCaesar Wang mmio_write_32(PMU_BASE + PMU_SCU_B_PWRDN_CNT, CYCL_24M_CNT_MS(2)); 328f47a25ddSCaesar Wang mmio_write_32(PMU_BASE + PMU_SCU_B_PWRUP_CNT, CYCL_24M_CNT_MS(2)); 3296fba6e04STony Xie } 3306fba6e04STony Xie 3316fba6e04STony Xie static int sys_pwr_domain_suspend(void) 3326fba6e04STony Xie { 3336fba6e04STony Xie sys_slp_config(); 3346fba6e04STony Xie plls_suspend(); 3356fba6e04STony Xie pmu_sgrf_rst_hld(); 336f47a25ddSCaesar Wang 337f47a25ddSCaesar Wang mmio_write_32(SGRF_BASE + SGRF_SOC_CON0_1(1), 338f47a25ddSCaesar Wang (PMUSRAM_BASE >> CPU_BOOT_ADDR_ALIGN) | 339f47a25ddSCaesar Wang CPU_BOOT_ADDR_WMASK); 340f47a25ddSCaesar Wang 341f47a25ddSCaesar Wang pmu_scu_b_pwrdn(); 342f47a25ddSCaesar Wang 343f47a25ddSCaesar Wang mmio_write_32(PMU_BASE + PMU_ADB400_CON, 344f47a25ddSCaesar Wang BIT_WITH_WMSK(PMU_PWRDWN_REQ_CORE_B_2GIC_SW) | 345f47a25ddSCaesar Wang BIT_WITH_WMSK(PMU_PWRDWN_REQ_CORE_B_SW) | 346f47a25ddSCaesar Wang BIT_WITH_WMSK(PMU_PWRDWN_REQ_GIC2_CORE_B_SW)); 347f47a25ddSCaesar Wang dsb(); 348f47a25ddSCaesar Wang mmio_setbits_32(PMU_BASE + PMU_PWRDN_CON, BIT(PMU_SCU_B_PWRDWN_EN)); 349f47a25ddSCaesar Wang 3506fba6e04STony Xie return 0; 3516fba6e04STony Xie } 3526fba6e04STony Xie 3536fba6e04STony Xie static int sys_pwr_domain_resume(void) 3546fba6e04STony Xie { 355f47a25ddSCaesar Wang pmu_sgrf_rst_hld(); 356f47a25ddSCaesar Wang 357f47a25ddSCaesar Wang mmio_write_32(SGRF_BASE + SGRF_SOC_CON0_1(1), 358f47a25ddSCaesar Wang (cpu_warm_boot_addr >> CPU_BOOT_ADDR_ALIGN) | 359f47a25ddSCaesar Wang CPU_BOOT_ADDR_WMASK); 360f47a25ddSCaesar Wang 3616fba6e04STony Xie plls_resume(); 3626fba6e04STony Xie 363f47a25ddSCaesar Wang mmio_write_32(PMU_BASE + PMU_CCI500_CON, 364f47a25ddSCaesar Wang WMSK_BIT(PMU_CLR_PREQ_CCI500_HW) | 365f47a25ddSCaesar Wang WMSK_BIT(PMU_CLR_QREQ_CCI500_HW) | 366f47a25ddSCaesar Wang WMSK_BIT(PMU_QGATING_CCI500_CFG)); 367f47a25ddSCaesar Wang 368f47a25ddSCaesar Wang mmio_write_32(PMU_BASE + PMU_ADB400_CON, 369f47a25ddSCaesar Wang WMSK_BIT(PMU_CLR_CORE_L_HW) | 370f47a25ddSCaesar Wang WMSK_BIT(PMU_CLR_CORE_L_2GIC_HW) | 371f47a25ddSCaesar Wang WMSK_BIT(PMU_CLR_GIC2_CORE_L_HW)); 372f47a25ddSCaesar Wang 373f47a25ddSCaesar Wang mmio_clrbits_32(PMU_BASE + PMU_PWRDN_CON, 374f47a25ddSCaesar Wang BIT(PMU_SCU_B_PWRDWN_EN)); 375f47a25ddSCaesar Wang 376f47a25ddSCaesar Wang mmio_write_32(PMU_BASE + PMU_ADB400_CON, 377f47a25ddSCaesar Wang WMSK_BIT(PMU_PWRDWN_REQ_CORE_B_2GIC_SW) | 378f47a25ddSCaesar Wang WMSK_BIT(PMU_PWRDWN_REQ_CORE_B_SW) | 379f47a25ddSCaesar Wang WMSK_BIT(PMU_PWRDWN_REQ_GIC2_CORE_B_SW)); 380f47a25ddSCaesar Wang 381f47a25ddSCaesar Wang pmu_scu_b_pwrup(); 382f47a25ddSCaesar Wang 383f47a25ddSCaesar Wang plat_rockchip_gic_cpuif_enable(); 3846fba6e04STony Xie return 0; 3856fba6e04STony Xie } 3866fba6e04STony Xie 3876fba6e04STony Xie static struct rockchip_pm_ops_cb pm_ops = { 3886fba6e04STony Xie .cores_pwr_dm_on = cores_pwr_domain_on, 3896fba6e04STony Xie .cores_pwr_dm_off = cores_pwr_domain_off, 3906fba6e04STony Xie .cores_pwr_dm_on_finish = cores_pwr_domain_on_finish, 3916fba6e04STony Xie .cores_pwr_dm_suspend = cores_pwr_domain_suspend, 3926fba6e04STony Xie .cores_pwr_dm_resume = cores_pwr_domain_resume, 3936fba6e04STony Xie .sys_pwr_dm_suspend = sys_pwr_domain_suspend, 3946fba6e04STony Xie .sys_pwr_dm_resume = sys_pwr_domain_resume, 3956fba6e04STony Xie .sys_gbl_soft_reset = soc_global_soft_reset, 3966fba6e04STony Xie }; 3976fba6e04STony Xie 3986fba6e04STony Xie void plat_rockchip_pmu_init(void) 3996fba6e04STony Xie { 4006fba6e04STony Xie uint32_t cpu; 4016fba6e04STony Xie 4026fba6e04STony Xie rockchip_pd_lock_init(); 4036fba6e04STony Xie plat_setup_rockchip_pm_ops(&pm_ops); 4046fba6e04STony Xie 405f47a25ddSCaesar Wang /* register requires 32bits mode, switch it to 32 bits */ 406f47a25ddSCaesar Wang cpu_warm_boot_addr = (uint64_t)platform_cpu_warmboot; 407f47a25ddSCaesar Wang 4086fba6e04STony Xie for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) 4096fba6e04STony Xie cpuson_flags[cpu] = 0; 4106fba6e04STony Xie 411f47a25ddSCaesar Wang psram_sleep_cfg->ddr_func = 0x00; 412f47a25ddSCaesar Wang psram_sleep_cfg->ddr_data = 0x00; 413f47a25ddSCaesar Wang psram_sleep_cfg->ddr_flag = 0x00; 4146fba6e04STony Xie psram_sleep_cfg->boot_mpidr = read_mpidr_el1() & 0xffff; 4156fba6e04STony Xie 4166fba6e04STony Xie /* cpu boot from pmusram */ 4176fba6e04STony Xie mmio_write_32(SGRF_BASE + SGRF_SOC_CON0_1(1), 418f47a25ddSCaesar Wang (cpu_warm_boot_addr >> CPU_BOOT_ADDR_ALIGN) | 4196fba6e04STony Xie CPU_BOOT_ADDR_WMASK); 4206fba6e04STony Xie 4216fba6e04STony Xie nonboot_cpus_off(); 422f47a25ddSCaesar Wang 4236fba6e04STony Xie INFO("%s(%d): pd status %x\n", __func__, __LINE__, 4246fba6e04STony Xie mmio_read_32(PMU_BASE + PMU_PWRDN_ST)); 4256fba6e04STony Xie } 426