16fba6e04STony Xie /* 26fba6e04STony Xie * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. 36fba6e04STony Xie * 482cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause 56fba6e04STony Xie */ 66fba6e04STony Xie 7c3cf06f1SAntonio Nino Diaz #ifndef PMU_COM_H 8c3cf06f1SAntonio Nino Diaz #define PMU_COM_H 96fba6e04STony Xie 100d5ec955Stony.xie #ifndef CHECK_CPU_WFIE_BASE 110d5ec955Stony.xie #define CHECK_CPU_WFIE_BASE (PMU_BASE + PMU_CORE_PWR_ST) 120d5ec955Stony.xie #endif 13f47a25ddSCaesar Wang /* 14f47a25ddSCaesar Wang * Use this macro to instantiate lock before it is used in below 15f47a25ddSCaesar Wang * rockchip_pd_lock_xxx() macros 16f47a25ddSCaesar Wang */ 179ec78bdfSTony Xie DECLARE_BAKERY_LOCK(rockchip_pd_lock); 186fba6e04STony Xie 19f47a25ddSCaesar Wang /* 20f47a25ddSCaesar Wang * These are wrapper macros to the powe domain Bakery Lock API. 21f47a25ddSCaesar Wang */ 22f47a25ddSCaesar Wang #define rockchip_pd_lock_init() bakery_lock_init(&rockchip_pd_lock) 236fba6e04STony Xie #define rockchip_pd_lock_get() bakery_lock_get(&rockchip_pd_lock) 246fba6e04STony Xie #define rockchip_pd_lock_rls() bakery_lock_release(&rockchip_pd_lock) 256fba6e04STony Xie 266fba6e04STony Xie /***************************************************************************** 276fba6e04STony Xie * power domain on or off 286fba6e04STony Xie *****************************************************************************/ 296fba6e04STony Xie enum pmu_pd_state { 306fba6e04STony Xie pmu_pd_on = 0, 316fba6e04STony Xie pmu_pd_off = 1 326fba6e04STony Xie }; 336fba6e04STony Xie 346fba6e04STony Xie #pragma weak plat_ic_get_pending_interrupt_id 356fba6e04STony Xie #pragma weak pmu_power_domain_ctr 366fba6e04STony Xie #pragma weak check_cpu_wfie 376fba6e04STony Xie 386fba6e04STony Xie static inline uint32_t pmu_power_domain_st(uint32_t pd) 396fba6e04STony Xie { 406fba6e04STony Xie uint32_t pwrdn_st = mmio_read_32(PMU_BASE + PMU_PWRDN_ST) & BIT(pd); 416fba6e04STony Xie 426fba6e04STony Xie if (pwrdn_st) 436fba6e04STony Xie return pmu_pd_off; 446fba6e04STony Xie else 456fba6e04STony Xie return pmu_pd_on; 466fba6e04STony Xie } 476fba6e04STony Xie 486fba6e04STony Xie static int pmu_power_domain_ctr(uint32_t pd, uint32_t pd_state) 496fba6e04STony Xie { 506fba6e04STony Xie uint32_t val; 516fba6e04STony Xie uint32_t loop = 0; 526fba6e04STony Xie int ret = 0; 536fba6e04STony Xie 546fba6e04STony Xie rockchip_pd_lock_get(); 556fba6e04STony Xie 566fba6e04STony Xie val = mmio_read_32(PMU_BASE + PMU_PWRDN_CON); 576fba6e04STony Xie if (pd_state == pmu_pd_off) 586fba6e04STony Xie val |= BIT(pd); 596fba6e04STony Xie else 606fba6e04STony Xie val &= ~BIT(pd); 616fba6e04STony Xie 626fba6e04STony Xie mmio_write_32(PMU_BASE + PMU_PWRDN_CON, val); 636fba6e04STony Xie dsb(); 646fba6e04STony Xie 656fba6e04STony Xie while ((pmu_power_domain_st(pd) != pd_state) && (loop < PD_CTR_LOOP)) { 666fba6e04STony Xie udelay(1); 676fba6e04STony Xie loop++; 686fba6e04STony Xie } 696fba6e04STony Xie 706fba6e04STony Xie if (pmu_power_domain_st(pd) != pd_state) { 716fba6e04STony Xie WARN("%s: %d, %d, error!\n", __func__, pd, pd_state); 726fba6e04STony Xie ret = -EINVAL; 736fba6e04STony Xie } 746fba6e04STony Xie 756fba6e04STony Xie rockchip_pd_lock_rls(); 766fba6e04STony Xie 776fba6e04STony Xie return ret; 786fba6e04STony Xie } 796fba6e04STony Xie 806fba6e04STony Xie static int check_cpu_wfie(uint32_t cpu_id, uint32_t wfie_msk) 816fba6e04STony Xie { 826fba6e04STony Xie uint32_t cluster_id, loop = 0; 836fba6e04STony Xie 846fba6e04STony Xie if (cpu_id >= PLATFORM_CLUSTER0_CORE_COUNT) { 856fba6e04STony Xie cluster_id = 1; 866fba6e04STony Xie cpu_id -= PLATFORM_CLUSTER0_CORE_COUNT; 876fba6e04STony Xie } else { 886fba6e04STony Xie cluster_id = 0; 896fba6e04STony Xie } 906fba6e04STony Xie 913b5b888dSHeiko Stuebner /* 923b5b888dSHeiko Stuebner * wfe/wfi tracking not possible, hopefully the host 93*1b491eeaSElyes Haouas * was successful in enabling wfe/wfi. 943b5b888dSHeiko Stuebner * We'll give a bit of additional time, like the kernel does. 953b5b888dSHeiko Stuebner */ 963b5b888dSHeiko Stuebner if ((cluster_id && clstb_cpu_wfe < 0) || 973b5b888dSHeiko Stuebner (!cluster_id && clstl_cpu_wfe < 0)) { 983b5b888dSHeiko Stuebner mdelay(1); 993b5b888dSHeiko Stuebner return 0; 1003b5b888dSHeiko Stuebner } 1013b5b888dSHeiko Stuebner 1026fba6e04STony Xie if (cluster_id) 1036fba6e04STony Xie wfie_msk <<= (clstb_cpu_wfe + cpu_id); 1046fba6e04STony Xie else 1056fba6e04STony Xie wfie_msk <<= (clstl_cpu_wfe + cpu_id); 1066fba6e04STony Xie 1070d5ec955Stony.xie while (!(mmio_read_32(CHECK_CPU_WFIE_BASE) & wfie_msk) && 1086fba6e04STony Xie (loop < CHK_CPU_LOOP)) { 1096fba6e04STony Xie udelay(1); 1106fba6e04STony Xie loop++; 1116fba6e04STony Xie } 1126fba6e04STony Xie 1130d5ec955Stony.xie if ((mmio_read_32(CHECK_CPU_WFIE_BASE) & wfie_msk) == 0) { 1146fba6e04STony Xie WARN("%s: %d, %d, %d, error!\n", __func__, 1156fba6e04STony Xie cluster_id, cpu_id, wfie_msk); 1166fba6e04STony Xie return -EINVAL; 1176fba6e04STony Xie } 1186fba6e04STony Xie 1196fba6e04STony Xie return 0; 1206fba6e04STony Xie } 1216fba6e04STony Xie 122c3cf06f1SAntonio Nino Diaz #endif /* PMU_COM_H */ 123