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> 378867299fSCaesar Wang #include <gpio.h> 386fba6e04STony Xie #include <mmio.h> 396fba6e04STony Xie #include <platform.h> 406fba6e04STony Xie #include <platform_def.h> 418867299fSCaesar Wang #include <plat_params.h> 426fba6e04STony Xie #include <plat_private.h> 436fba6e04STony Xie #include <rk3399_def.h> 446fba6e04STony Xie #include <pmu_sram.h> 456fba6e04STony Xie #include <soc.h> 466fba6e04STony Xie #include <pmu.h> 476fba6e04STony Xie #include <pmu_com.h> 486fba6e04STony Xie 496fba6e04STony Xie static struct psram_data_t *psram_sleep_cfg = 506fba6e04STony Xie (struct psram_data_t *)PSRAM_DT_BASE; 516fba6e04STony Xie 52f47a25ddSCaesar Wang static uint32_t cpu_warm_boot_addr; 53f47a25ddSCaesar Wang 546fba6e04STony Xie /* 556fba6e04STony Xie * There are two ways to powering on or off on core. 566fba6e04STony Xie * 1) Control it power domain into on or off in PMU_PWRDN_CON reg, 576fba6e04STony Xie * it is core_pwr_pd mode 586fba6e04STony Xie * 2) Enable the core power manage in PMU_CORE_PM_CON reg, 596fba6e04STony Xie * then, if the core enter into wfi, it power domain will be 606fba6e04STony Xie * powered off automatically. it is core_pwr_wfi or core_pwr_wfi_int mode 616fba6e04STony Xie * so we need core_pm_cfg_info to distinguish which method be used now. 626fba6e04STony Xie */ 636fba6e04STony Xie 646fba6e04STony Xie static uint32_t core_pm_cfg_info[PLATFORM_CORE_COUNT] 656fba6e04STony Xie #if USE_COHERENT_MEM 666fba6e04STony Xie __attribute__ ((section("tzfw_coherent_mem"))) 676fba6e04STony Xie #endif 686fba6e04STony Xie ;/* coheront */ 696fba6e04STony Xie 70f47a25ddSCaesar Wang void rk3399_flash_l2_b(void) 71f47a25ddSCaesar Wang { 72f47a25ddSCaesar Wang uint32_t wait_cnt = 0; 73f47a25ddSCaesar Wang 74f47a25ddSCaesar Wang mmio_setbits_32(PMU_BASE + PMU_SFT_CON, BIT(L2_FLUSH_REQ_CLUSTER_B)); 75f47a25ddSCaesar Wang dsb(); 76f47a25ddSCaesar Wang 77f47a25ddSCaesar Wang while (!(mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST) & 78f47a25ddSCaesar Wang BIT(L2_FLUSHDONE_CLUSTER_B))) { 79f47a25ddSCaesar Wang wait_cnt++; 80f47a25ddSCaesar Wang if (!(wait_cnt % MAX_WAIT_CONUT)) 81f47a25ddSCaesar Wang WARN("%s:reg %x,wait\n", __func__, 82f47a25ddSCaesar Wang mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST)); 83f47a25ddSCaesar Wang } 84f47a25ddSCaesar Wang 85f47a25ddSCaesar Wang mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, BIT(L2_FLUSH_REQ_CLUSTER_B)); 86f47a25ddSCaesar Wang } 87f47a25ddSCaesar Wang 88f47a25ddSCaesar Wang static void pmu_scu_b_pwrdn(void) 89f47a25ddSCaesar Wang { 90f47a25ddSCaesar Wang uint32_t wait_cnt = 0; 91f47a25ddSCaesar Wang 92f47a25ddSCaesar Wang if ((mmio_read_32(PMU_BASE + PMU_PWRDN_ST) & 93f47a25ddSCaesar Wang (BIT(PMU_A72_B0_PWRDWN_ST) | BIT(PMU_A72_B1_PWRDWN_ST))) != 94f47a25ddSCaesar Wang (BIT(PMU_A72_B0_PWRDWN_ST) | BIT(PMU_A72_B1_PWRDWN_ST))) { 95f47a25ddSCaesar Wang ERROR("%s: not all cpus is off\n", __func__); 96f47a25ddSCaesar Wang return; 97f47a25ddSCaesar Wang } 98f47a25ddSCaesar Wang 99f47a25ddSCaesar Wang rk3399_flash_l2_b(); 100f47a25ddSCaesar Wang 101f47a25ddSCaesar Wang mmio_setbits_32(PMU_BASE + PMU_SFT_CON, BIT(ACINACTM_CLUSTER_B_CFG)); 102f47a25ddSCaesar Wang 103f47a25ddSCaesar Wang while (!(mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST) & 104f47a25ddSCaesar Wang BIT(STANDBY_BY_WFIL2_CLUSTER_B))) { 105f47a25ddSCaesar Wang wait_cnt++; 106f47a25ddSCaesar Wang if (!(wait_cnt % MAX_WAIT_CONUT)) 107f47a25ddSCaesar Wang ERROR("%s:wait cluster-b l2(%x)\n", __func__, 108f47a25ddSCaesar Wang mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST)); 109f47a25ddSCaesar Wang } 110f47a25ddSCaesar Wang } 111f47a25ddSCaesar Wang 112f47a25ddSCaesar Wang static void pmu_scu_b_pwrup(void) 113f47a25ddSCaesar Wang { 114f47a25ddSCaesar Wang mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, BIT(ACINACTM_CLUSTER_B_CFG)); 115f47a25ddSCaesar Wang } 116f47a25ddSCaesar Wang 1176fba6e04STony Xie void plat_rockchip_pmusram_prepare(void) 1186fba6e04STony Xie { 1196fba6e04STony Xie uint32_t *sram_dst, *sram_src; 1206fba6e04STony Xie size_t sram_size = 2; 1216fba6e04STony Xie 1226fba6e04STony Xie /* 1236fba6e04STony Xie * pmu sram code and data prepare 1246fba6e04STony Xie */ 1256fba6e04STony Xie sram_dst = (uint32_t *)PMUSRAM_BASE; 1266fba6e04STony Xie sram_src = (uint32_t *)&pmu_cpuson_entrypoint_start; 1276fba6e04STony Xie sram_size = (uint32_t *)&pmu_cpuson_entrypoint_end - 1286fba6e04STony Xie (uint32_t *)sram_src; 1296fba6e04STony Xie 1306fba6e04STony Xie u32_align_cpy(sram_dst, sram_src, sram_size); 1316fba6e04STony Xie 1326fba6e04STony Xie psram_sleep_cfg->sp = PSRAM_DT_BASE; 1336fba6e04STony Xie } 1346fba6e04STony Xie 1356fba6e04STony Xie static inline uint32_t get_cpus_pwr_domain_cfg_info(uint32_t cpu_id) 1366fba6e04STony Xie { 13780fb66b3SSandrine Bailleux assert(cpu_id < PLATFORM_CORE_COUNT); 1386fba6e04STony Xie return core_pm_cfg_info[cpu_id]; 1396fba6e04STony Xie } 1406fba6e04STony Xie 1416fba6e04STony Xie static inline void set_cpus_pwr_domain_cfg_info(uint32_t cpu_id, uint32_t value) 1426fba6e04STony Xie { 14380fb66b3SSandrine Bailleux assert(cpu_id < PLATFORM_CORE_COUNT); 1446fba6e04STony Xie core_pm_cfg_info[cpu_id] = value; 1456fba6e04STony Xie #if !USE_COHERENT_MEM 1466fba6e04STony Xie flush_dcache_range((uintptr_t)&core_pm_cfg_info[cpu_id], 1476fba6e04STony Xie sizeof(uint32_t)); 1486fba6e04STony Xie #endif 1496fba6e04STony Xie } 1506fba6e04STony Xie 1516fba6e04STony Xie static int cpus_power_domain_on(uint32_t cpu_id) 1526fba6e04STony Xie { 1536fba6e04STony Xie uint32_t cfg_info; 1546fba6e04STony Xie uint32_t cpu_pd = PD_CPUL0 + cpu_id; 1556fba6e04STony Xie /* 1566fba6e04STony Xie * There are two ways to powering on or off on core. 1576fba6e04STony Xie * 1) Control it power domain into on or off in PMU_PWRDN_CON reg 1586fba6e04STony Xie * 2) Enable the core power manage in PMU_CORE_PM_CON reg, 1596fba6e04STony Xie * then, if the core enter into wfi, it power domain will be 1606fba6e04STony Xie * powered off automatically. 1616fba6e04STony Xie */ 1626fba6e04STony Xie 1636fba6e04STony Xie cfg_info = get_cpus_pwr_domain_cfg_info(cpu_id); 1646fba6e04STony Xie 1656fba6e04STony Xie if (cfg_info == core_pwr_pd) { 1666fba6e04STony Xie /* disable core_pm cfg */ 1676fba6e04STony Xie mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), 1686fba6e04STony Xie CORES_PM_DISABLE); 1696fba6e04STony Xie /* if the cores have be on, power off it firstly */ 1706fba6e04STony Xie if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) { 1716fba6e04STony Xie mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), 0); 1726fba6e04STony Xie pmu_power_domain_ctr(cpu_pd, pmu_pd_off); 1736fba6e04STony Xie } 1746fba6e04STony Xie 1756fba6e04STony Xie pmu_power_domain_ctr(cpu_pd, pmu_pd_on); 1766fba6e04STony Xie } else { 1776fba6e04STony Xie if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) { 1786fba6e04STony Xie WARN("%s: cpu%d is not in off,!\n", __func__, cpu_id); 1796fba6e04STony Xie return -EINVAL; 1806fba6e04STony Xie } 1816fba6e04STony Xie 1826fba6e04STony Xie mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), 1836fba6e04STony Xie BIT(core_pm_sft_wakeup_en)); 184f47a25ddSCaesar Wang dsb(); 1856fba6e04STony Xie } 1866fba6e04STony Xie 1876fba6e04STony Xie return 0; 1886fba6e04STony Xie } 1896fba6e04STony Xie 1906fba6e04STony Xie static int cpus_power_domain_off(uint32_t cpu_id, uint32_t pd_cfg) 1916fba6e04STony Xie { 1926fba6e04STony Xie uint32_t cpu_pd; 1936fba6e04STony Xie uint32_t core_pm_value; 1946fba6e04STony Xie 1956fba6e04STony Xie cpu_pd = PD_CPUL0 + cpu_id; 1966fba6e04STony Xie if (pmu_power_domain_st(cpu_pd) == pmu_pd_off) 1976fba6e04STony Xie return 0; 1986fba6e04STony Xie 1996fba6e04STony Xie if (pd_cfg == core_pwr_pd) { 2006fba6e04STony Xie if (check_cpu_wfie(cpu_id, CKECK_WFEI_MSK)) 2016fba6e04STony Xie return -EINVAL; 2026fba6e04STony Xie 2036fba6e04STony Xie /* disable core_pm cfg */ 2046fba6e04STony Xie mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), 2056fba6e04STony Xie CORES_PM_DISABLE); 2066fba6e04STony Xie 2076fba6e04STony Xie set_cpus_pwr_domain_cfg_info(cpu_id, pd_cfg); 2086fba6e04STony Xie pmu_power_domain_ctr(cpu_pd, pmu_pd_off); 2096fba6e04STony Xie } else { 2106fba6e04STony Xie set_cpus_pwr_domain_cfg_info(cpu_id, pd_cfg); 2116fba6e04STony Xie 2126fba6e04STony Xie core_pm_value = BIT(core_pm_en); 2136fba6e04STony Xie if (pd_cfg == core_pwr_wfi_int) 2146fba6e04STony Xie core_pm_value |= BIT(core_pm_int_wakeup_en); 2156fba6e04STony Xie mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), 2166fba6e04STony Xie core_pm_value); 217f47a25ddSCaesar Wang dsb(); 2186fba6e04STony Xie } 2196fba6e04STony Xie 2206fba6e04STony Xie return 0; 2216fba6e04STony Xie } 2226fba6e04STony Xie 2236fba6e04STony Xie static void nonboot_cpus_off(void) 2246fba6e04STony Xie { 2256fba6e04STony Xie uint32_t boot_cpu, cpu; 2266fba6e04STony Xie 2276fba6e04STony Xie boot_cpu = plat_my_core_pos(); 2286fba6e04STony Xie 2296fba6e04STony Xie /* turn off noboot cpus */ 2306fba6e04STony Xie for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) { 2316fba6e04STony Xie if (cpu == boot_cpu) 2326fba6e04STony Xie continue; 2336fba6e04STony Xie cpus_power_domain_off(cpu, core_pwr_pd); 2346fba6e04STony Xie } 2356fba6e04STony Xie } 2366fba6e04STony Xie 2376fba6e04STony Xie static int cores_pwr_domain_on(unsigned long mpidr, uint64_t entrypoint) 2386fba6e04STony Xie { 2396fba6e04STony Xie uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr); 2406fba6e04STony Xie 24180fb66b3SSandrine Bailleux assert(cpu_id < PLATFORM_CORE_COUNT); 2426fba6e04STony Xie assert(cpuson_flags[cpu_id] == 0); 2436fba6e04STony Xie cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG; 2446fba6e04STony Xie cpuson_entry_point[cpu_id] = entrypoint; 2456fba6e04STony Xie dsb(); 2466fba6e04STony Xie 2476fba6e04STony Xie cpus_power_domain_on(cpu_id); 2486fba6e04STony Xie 2496fba6e04STony Xie return 0; 2506fba6e04STony Xie } 2516fba6e04STony Xie 2526fba6e04STony Xie static int cores_pwr_domain_off(void) 2536fba6e04STony Xie { 2546fba6e04STony Xie uint32_t cpu_id = plat_my_core_pos(); 2556fba6e04STony Xie 2566fba6e04STony Xie cpus_power_domain_off(cpu_id, core_pwr_wfi); 2576fba6e04STony Xie 2586fba6e04STony Xie return 0; 2596fba6e04STony Xie } 2606fba6e04STony Xie 2616fba6e04STony Xie static int cores_pwr_domain_suspend(void) 2626fba6e04STony Xie { 2636fba6e04STony Xie uint32_t cpu_id = plat_my_core_pos(); 2646fba6e04STony Xie 26580fb66b3SSandrine Bailleux assert(cpu_id < PLATFORM_CORE_COUNT); 2666fba6e04STony Xie assert(cpuson_flags[cpu_id] == 0); 2676fba6e04STony Xie cpuson_flags[cpu_id] = PMU_CPU_AUTO_PWRDN; 2686fba6e04STony Xie cpuson_entry_point[cpu_id] = (uintptr_t)psci_entrypoint; 2696fba6e04STony Xie dsb(); 2706fba6e04STony Xie 2716fba6e04STony Xie cpus_power_domain_off(cpu_id, core_pwr_wfi_int); 2726fba6e04STony Xie 2736fba6e04STony Xie return 0; 2746fba6e04STony Xie } 2756fba6e04STony Xie 2766fba6e04STony Xie static int cores_pwr_domain_on_finish(void) 2776fba6e04STony Xie { 2786fba6e04STony Xie uint32_t cpu_id = plat_my_core_pos(); 2796fba6e04STony Xie 2806fba6e04STony Xie /* Disable core_pm */ 2816fba6e04STony Xie mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), CORES_PM_DISABLE); 2826fba6e04STony Xie 2836fba6e04STony Xie return 0; 2846fba6e04STony Xie } 2856fba6e04STony Xie 2866fba6e04STony Xie static int cores_pwr_domain_resume(void) 2876fba6e04STony Xie { 2886fba6e04STony Xie uint32_t cpu_id = plat_my_core_pos(); 2896fba6e04STony Xie 2906fba6e04STony Xie /* Disable core_pm */ 2916fba6e04STony Xie mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), CORES_PM_DISABLE); 2926fba6e04STony Xie 2936fba6e04STony Xie return 0; 2946fba6e04STony Xie } 2956fba6e04STony Xie 2966fba6e04STony Xie static void sys_slp_config(void) 2976fba6e04STony Xie { 2986fba6e04STony Xie uint32_t slp_mode_cfg = 0; 2996fba6e04STony Xie 300f47a25ddSCaesar Wang mmio_write_32(PMU_BASE + PMU_CCI500_CON, 301f47a25ddSCaesar Wang BIT_WITH_WMSK(PMU_CLR_PREQ_CCI500_HW) | 302f47a25ddSCaesar Wang BIT_WITH_WMSK(PMU_CLR_QREQ_CCI500_HW) | 303f47a25ddSCaesar Wang BIT_WITH_WMSK(PMU_QGATING_CCI500_CFG)); 304f47a25ddSCaesar Wang 305f47a25ddSCaesar Wang mmio_write_32(PMU_BASE + PMU_ADB400_CON, 306f47a25ddSCaesar Wang BIT_WITH_WMSK(PMU_CLR_CORE_L_HW) | 307f47a25ddSCaesar Wang BIT_WITH_WMSK(PMU_CLR_CORE_L_2GIC_HW) | 308f47a25ddSCaesar Wang BIT_WITH_WMSK(PMU_CLR_GIC2_CORE_L_HW)); 309f47a25ddSCaesar Wang 310f47a25ddSCaesar Wang mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO1A_IOMUX, 311f47a25ddSCaesar Wang BIT_WITH_WMSK(AP_PWROFF)); 312f47a25ddSCaesar Wang 313f47a25ddSCaesar Wang slp_mode_cfg = BIT(PMU_PWR_MODE_EN) | 314f47a25ddSCaesar Wang BIT(PMU_POWER_OFF_REQ_CFG) | 315f47a25ddSCaesar Wang BIT(PMU_CPU0_PD_EN) | 316f47a25ddSCaesar Wang BIT(PMU_L2_FLUSH_EN) | 317f47a25ddSCaesar Wang BIT(PMU_L2_IDLE_EN) | 318f47a25ddSCaesar Wang BIT(PMU_SCU_PD_EN); 319f47a25ddSCaesar Wang 3206fba6e04STony Xie mmio_setbits_32(PMU_BASE + PMU_WKUP_CFG4, PMU_CLUSTER_L_WKUP_EN); 3216fba6e04STony Xie mmio_setbits_32(PMU_BASE + PMU_WKUP_CFG4, PMU_CLUSTER_B_WKUP_EN); 3226fba6e04STony Xie mmio_clrbits_32(PMU_BASE + PMU_WKUP_CFG4, PMU_GPIO_WKUP_EN); 323f47a25ddSCaesar Wang 3246fba6e04STony Xie mmio_write_32(PMU_BASE + PMU_PWRMODE_CON, slp_mode_cfg); 325f47a25ddSCaesar Wang 326f47a25ddSCaesar Wang mmio_write_32(PMU_BASE + PMU_STABLE_CNT, CYCL_24M_CNT_MS(5)); 327f47a25ddSCaesar Wang mmio_write_32(PMU_BASE + PMU_SCU_L_PWRDN_CNT, CYCL_24M_CNT_MS(2)); 328f47a25ddSCaesar Wang mmio_write_32(PMU_BASE + PMU_SCU_L_PWRUP_CNT, CYCL_24M_CNT_MS(2)); 329f47a25ddSCaesar Wang mmio_write_32(PMU_BASE + PMU_SCU_B_PWRDN_CNT, CYCL_24M_CNT_MS(2)); 330f47a25ddSCaesar Wang mmio_write_32(PMU_BASE + PMU_SCU_B_PWRUP_CNT, CYCL_24M_CNT_MS(2)); 3316fba6e04STony Xie } 3326fba6e04STony Xie 3336fba6e04STony Xie static int sys_pwr_domain_suspend(void) 3346fba6e04STony Xie { 3356fba6e04STony Xie sys_slp_config(); 3366fba6e04STony Xie plls_suspend(); 3376fba6e04STony Xie pmu_sgrf_rst_hld(); 338f47a25ddSCaesar Wang 339f47a25ddSCaesar Wang mmio_write_32(SGRF_BASE + SGRF_SOC_CON0_1(1), 340f47a25ddSCaesar Wang (PMUSRAM_BASE >> CPU_BOOT_ADDR_ALIGN) | 341f47a25ddSCaesar Wang CPU_BOOT_ADDR_WMASK); 342f47a25ddSCaesar Wang 343f47a25ddSCaesar Wang pmu_scu_b_pwrdn(); 344f47a25ddSCaesar Wang 345f47a25ddSCaesar Wang mmio_write_32(PMU_BASE + PMU_ADB400_CON, 346f47a25ddSCaesar Wang BIT_WITH_WMSK(PMU_PWRDWN_REQ_CORE_B_2GIC_SW) | 347f47a25ddSCaesar Wang BIT_WITH_WMSK(PMU_PWRDWN_REQ_CORE_B_SW) | 348f47a25ddSCaesar Wang BIT_WITH_WMSK(PMU_PWRDWN_REQ_GIC2_CORE_B_SW)); 349f47a25ddSCaesar Wang dsb(); 350f47a25ddSCaesar Wang mmio_setbits_32(PMU_BASE + PMU_PWRDN_CON, BIT(PMU_SCU_B_PWRDWN_EN)); 351f47a25ddSCaesar Wang 3526fba6e04STony Xie return 0; 3536fba6e04STony Xie } 3546fba6e04STony Xie 3556fba6e04STony Xie static int sys_pwr_domain_resume(void) 3566fba6e04STony Xie { 357f47a25ddSCaesar Wang pmu_sgrf_rst_hld(); 358f47a25ddSCaesar Wang 359f47a25ddSCaesar Wang mmio_write_32(SGRF_BASE + SGRF_SOC_CON0_1(1), 360f47a25ddSCaesar Wang (cpu_warm_boot_addr >> CPU_BOOT_ADDR_ALIGN) | 361f47a25ddSCaesar Wang CPU_BOOT_ADDR_WMASK); 362f47a25ddSCaesar Wang 3636fba6e04STony Xie plls_resume(); 3646fba6e04STony Xie 365f47a25ddSCaesar Wang mmio_write_32(PMU_BASE + PMU_CCI500_CON, 366f47a25ddSCaesar Wang WMSK_BIT(PMU_CLR_PREQ_CCI500_HW) | 367f47a25ddSCaesar Wang WMSK_BIT(PMU_CLR_QREQ_CCI500_HW) | 368f47a25ddSCaesar Wang WMSK_BIT(PMU_QGATING_CCI500_CFG)); 369f47a25ddSCaesar Wang 370f47a25ddSCaesar Wang mmio_write_32(PMU_BASE + PMU_ADB400_CON, 371f47a25ddSCaesar Wang WMSK_BIT(PMU_CLR_CORE_L_HW) | 372f47a25ddSCaesar Wang WMSK_BIT(PMU_CLR_CORE_L_2GIC_HW) | 373f47a25ddSCaesar Wang WMSK_BIT(PMU_CLR_GIC2_CORE_L_HW)); 374f47a25ddSCaesar Wang 375f47a25ddSCaesar Wang mmio_clrbits_32(PMU_BASE + PMU_PWRDN_CON, 376f47a25ddSCaesar Wang BIT(PMU_SCU_B_PWRDWN_EN)); 377f47a25ddSCaesar Wang 378f47a25ddSCaesar Wang mmio_write_32(PMU_BASE + PMU_ADB400_CON, 379f47a25ddSCaesar Wang WMSK_BIT(PMU_PWRDWN_REQ_CORE_B_2GIC_SW) | 380f47a25ddSCaesar Wang WMSK_BIT(PMU_PWRDWN_REQ_CORE_B_SW) | 381f47a25ddSCaesar Wang WMSK_BIT(PMU_PWRDWN_REQ_GIC2_CORE_B_SW)); 382f47a25ddSCaesar Wang 383f47a25ddSCaesar Wang pmu_scu_b_pwrup(); 384f47a25ddSCaesar Wang 385f47a25ddSCaesar Wang plat_rockchip_gic_cpuif_enable(); 3866fba6e04STony Xie return 0; 3876fba6e04STony Xie } 3886fba6e04STony Xie 3898867299fSCaesar Wang void __dead2 soc_soft_reset(void) 3908867299fSCaesar Wang { 3918867299fSCaesar Wang struct gpio_info *rst_gpio; 3928867299fSCaesar Wang 3938867299fSCaesar Wang rst_gpio = (struct gpio_info *)plat_get_rockchip_gpio_reset(); 3948867299fSCaesar Wang 3958867299fSCaesar Wang if (rst_gpio) { 3968867299fSCaesar Wang gpio_set_direction(rst_gpio->index, GPIO_DIR_OUT); 3978867299fSCaesar Wang gpio_set_value(rst_gpio->index, rst_gpio->polarity); 3988867299fSCaesar Wang } else { 3998867299fSCaesar Wang soc_global_soft_reset(); 4008867299fSCaesar Wang } 4018867299fSCaesar Wang 4028867299fSCaesar Wang while (1) 4038867299fSCaesar Wang ; 4048867299fSCaesar Wang } 4058867299fSCaesar Wang 406*86c253e4SCaesar Wang void __dead2 soc_system_off(void) 407*86c253e4SCaesar Wang { 408*86c253e4SCaesar Wang struct gpio_info *poweroff_gpio; 409*86c253e4SCaesar Wang 410*86c253e4SCaesar Wang poweroff_gpio = (struct gpio_info *)plat_get_rockchip_gpio_poweroff(); 411*86c253e4SCaesar Wang 412*86c253e4SCaesar Wang if (poweroff_gpio) { 413*86c253e4SCaesar Wang /* 414*86c253e4SCaesar Wang * if use tsadc over temp pin(GPIO1A6) as shutdown gpio, 415*86c253e4SCaesar Wang * need to set this pin iomux back to gpio function 416*86c253e4SCaesar Wang */ 417*86c253e4SCaesar Wang if (poweroff_gpio->index == TSADC_INT_PIN) { 418*86c253e4SCaesar Wang mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO1A_IOMUX, 419*86c253e4SCaesar Wang GPIO1A6_IOMUX); 420*86c253e4SCaesar Wang } 421*86c253e4SCaesar Wang gpio_set_direction(poweroff_gpio->index, GPIO_DIR_OUT); 422*86c253e4SCaesar Wang gpio_set_value(poweroff_gpio->index, poweroff_gpio->polarity); 423*86c253e4SCaesar Wang } else { 424*86c253e4SCaesar Wang WARN("Do nothing when system off\n"); 425*86c253e4SCaesar Wang } 426*86c253e4SCaesar Wang 427*86c253e4SCaesar Wang while (1) 428*86c253e4SCaesar Wang ; 429*86c253e4SCaesar Wang } 430*86c253e4SCaesar Wang 4316fba6e04STony Xie static struct rockchip_pm_ops_cb pm_ops = { 4326fba6e04STony Xie .cores_pwr_dm_on = cores_pwr_domain_on, 4336fba6e04STony Xie .cores_pwr_dm_off = cores_pwr_domain_off, 4346fba6e04STony Xie .cores_pwr_dm_on_finish = cores_pwr_domain_on_finish, 4356fba6e04STony Xie .cores_pwr_dm_suspend = cores_pwr_domain_suspend, 4366fba6e04STony Xie .cores_pwr_dm_resume = cores_pwr_domain_resume, 4376fba6e04STony Xie .sys_pwr_dm_suspend = sys_pwr_domain_suspend, 4386fba6e04STony Xie .sys_pwr_dm_resume = sys_pwr_domain_resume, 4398867299fSCaesar Wang .sys_gbl_soft_reset = soc_soft_reset, 440*86c253e4SCaesar Wang .system_off = soc_system_off, 4416fba6e04STony Xie }; 4426fba6e04STony Xie 4436fba6e04STony Xie void plat_rockchip_pmu_init(void) 4446fba6e04STony Xie { 4456fba6e04STony Xie uint32_t cpu; 4466fba6e04STony Xie 4476fba6e04STony Xie rockchip_pd_lock_init(); 4486fba6e04STony Xie plat_setup_rockchip_pm_ops(&pm_ops); 4496fba6e04STony Xie 450f47a25ddSCaesar Wang /* register requires 32bits mode, switch it to 32 bits */ 451f47a25ddSCaesar Wang cpu_warm_boot_addr = (uint64_t)platform_cpu_warmboot; 452f47a25ddSCaesar Wang 4536fba6e04STony Xie for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) 4546fba6e04STony Xie cpuson_flags[cpu] = 0; 4556fba6e04STony Xie 456f47a25ddSCaesar Wang psram_sleep_cfg->ddr_func = 0x00; 457f47a25ddSCaesar Wang psram_sleep_cfg->ddr_data = 0x00; 458f47a25ddSCaesar Wang psram_sleep_cfg->ddr_flag = 0x00; 4596fba6e04STony Xie psram_sleep_cfg->boot_mpidr = read_mpidr_el1() & 0xffff; 4606fba6e04STony Xie 4616fba6e04STony Xie /* cpu boot from pmusram */ 4626fba6e04STony Xie mmio_write_32(SGRF_BASE + SGRF_SOC_CON0_1(1), 463f47a25ddSCaesar Wang (cpu_warm_boot_addr >> CPU_BOOT_ADDR_ALIGN) | 4646fba6e04STony Xie CPU_BOOT_ADDR_WMASK); 4656fba6e04STony Xie 4666fba6e04STony Xie nonboot_cpus_off(); 467f47a25ddSCaesar Wang 4686fba6e04STony Xie INFO("%s(%d): pd status %x\n", __func__, __LINE__, 4696fba6e04STony Xie mmio_read_32(PMU_BASE + PMU_PWRDN_ST)); 4706fba6e04STony Xie } 471