1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #ifndef PMU_COM_H 8*91f16700Schasinglulu #define PMU_COM_H 9*91f16700Schasinglulu 10*91f16700Schasinglulu #ifndef CHECK_CPU_WFIE_BASE 11*91f16700Schasinglulu #define CHECK_CPU_WFIE_BASE (PMU_BASE + PMU_CORE_PWR_ST) 12*91f16700Schasinglulu #endif 13*91f16700Schasinglulu /* 14*91f16700Schasinglulu * Use this macro to instantiate lock before it is used in below 15*91f16700Schasinglulu * rockchip_pd_lock_xxx() macros 16*91f16700Schasinglulu */ 17*91f16700Schasinglulu DECLARE_BAKERY_LOCK(rockchip_pd_lock); 18*91f16700Schasinglulu 19*91f16700Schasinglulu /* 20*91f16700Schasinglulu * These are wrapper macros to the powe domain Bakery Lock API. 21*91f16700Schasinglulu */ 22*91f16700Schasinglulu #define rockchip_pd_lock_init() bakery_lock_init(&rockchip_pd_lock) 23*91f16700Schasinglulu #define rockchip_pd_lock_get() bakery_lock_get(&rockchip_pd_lock) 24*91f16700Schasinglulu #define rockchip_pd_lock_rls() bakery_lock_release(&rockchip_pd_lock) 25*91f16700Schasinglulu 26*91f16700Schasinglulu /***************************************************************************** 27*91f16700Schasinglulu * power domain on or off 28*91f16700Schasinglulu *****************************************************************************/ 29*91f16700Schasinglulu enum pmu_pd_state { 30*91f16700Schasinglulu pmu_pd_on = 0, 31*91f16700Schasinglulu pmu_pd_off = 1 32*91f16700Schasinglulu }; 33*91f16700Schasinglulu 34*91f16700Schasinglulu #pragma weak plat_ic_get_pending_interrupt_id 35*91f16700Schasinglulu #pragma weak pmu_power_domain_ctr 36*91f16700Schasinglulu #pragma weak check_cpu_wfie 37*91f16700Schasinglulu 38*91f16700Schasinglulu static inline uint32_t pmu_power_domain_st(uint32_t pd) 39*91f16700Schasinglulu { 40*91f16700Schasinglulu uint32_t pwrdn_st = mmio_read_32(PMU_BASE + PMU_PWRDN_ST) & BIT(pd); 41*91f16700Schasinglulu 42*91f16700Schasinglulu if (pwrdn_st) 43*91f16700Schasinglulu return pmu_pd_off; 44*91f16700Schasinglulu else 45*91f16700Schasinglulu return pmu_pd_on; 46*91f16700Schasinglulu } 47*91f16700Schasinglulu 48*91f16700Schasinglulu static int pmu_power_domain_ctr(uint32_t pd, uint32_t pd_state) 49*91f16700Schasinglulu { 50*91f16700Schasinglulu uint32_t val; 51*91f16700Schasinglulu uint32_t loop = 0; 52*91f16700Schasinglulu int ret = 0; 53*91f16700Schasinglulu 54*91f16700Schasinglulu rockchip_pd_lock_get(); 55*91f16700Schasinglulu 56*91f16700Schasinglulu val = mmio_read_32(PMU_BASE + PMU_PWRDN_CON); 57*91f16700Schasinglulu if (pd_state == pmu_pd_off) 58*91f16700Schasinglulu val |= BIT(pd); 59*91f16700Schasinglulu else 60*91f16700Schasinglulu val &= ~BIT(pd); 61*91f16700Schasinglulu 62*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_PWRDN_CON, val); 63*91f16700Schasinglulu dsb(); 64*91f16700Schasinglulu 65*91f16700Schasinglulu while ((pmu_power_domain_st(pd) != pd_state) && (loop < PD_CTR_LOOP)) { 66*91f16700Schasinglulu udelay(1); 67*91f16700Schasinglulu loop++; 68*91f16700Schasinglulu } 69*91f16700Schasinglulu 70*91f16700Schasinglulu if (pmu_power_domain_st(pd) != pd_state) { 71*91f16700Schasinglulu WARN("%s: %d, %d, error!\n", __func__, pd, pd_state); 72*91f16700Schasinglulu ret = -EINVAL; 73*91f16700Schasinglulu } 74*91f16700Schasinglulu 75*91f16700Schasinglulu rockchip_pd_lock_rls(); 76*91f16700Schasinglulu 77*91f16700Schasinglulu return ret; 78*91f16700Schasinglulu } 79*91f16700Schasinglulu 80*91f16700Schasinglulu static int check_cpu_wfie(uint32_t cpu_id, uint32_t wfie_msk) 81*91f16700Schasinglulu { 82*91f16700Schasinglulu uint32_t cluster_id, loop = 0; 83*91f16700Schasinglulu 84*91f16700Schasinglulu if (cpu_id >= PLATFORM_CLUSTER0_CORE_COUNT) { 85*91f16700Schasinglulu cluster_id = 1; 86*91f16700Schasinglulu cpu_id -= PLATFORM_CLUSTER0_CORE_COUNT; 87*91f16700Schasinglulu } else { 88*91f16700Schasinglulu cluster_id = 0; 89*91f16700Schasinglulu } 90*91f16700Schasinglulu 91*91f16700Schasinglulu /* 92*91f16700Schasinglulu * wfe/wfi tracking not possible, hopefully the host 93*91f16700Schasinglulu * was successful in enabling wfe/wfi. 94*91f16700Schasinglulu * We'll give a bit of additional time, like the kernel does. 95*91f16700Schasinglulu */ 96*91f16700Schasinglulu if ((cluster_id && clstb_cpu_wfe < 0) || 97*91f16700Schasinglulu (!cluster_id && clstl_cpu_wfe < 0)) { 98*91f16700Schasinglulu mdelay(1); 99*91f16700Schasinglulu return 0; 100*91f16700Schasinglulu } 101*91f16700Schasinglulu 102*91f16700Schasinglulu if (cluster_id) 103*91f16700Schasinglulu wfie_msk <<= (clstb_cpu_wfe + cpu_id); 104*91f16700Schasinglulu else 105*91f16700Schasinglulu wfie_msk <<= (clstl_cpu_wfe + cpu_id); 106*91f16700Schasinglulu 107*91f16700Schasinglulu while (!(mmio_read_32(CHECK_CPU_WFIE_BASE) & wfie_msk) && 108*91f16700Schasinglulu (loop < CHK_CPU_LOOP)) { 109*91f16700Schasinglulu udelay(1); 110*91f16700Schasinglulu loop++; 111*91f16700Schasinglulu } 112*91f16700Schasinglulu 113*91f16700Schasinglulu if ((mmio_read_32(CHECK_CPU_WFIE_BASE) & wfie_msk) == 0) { 114*91f16700Schasinglulu WARN("%s: %d, %d, %d, error!\n", __func__, 115*91f16700Schasinglulu cluster_id, cpu_id, wfie_msk); 116*91f16700Schasinglulu return -EINVAL; 117*91f16700Schasinglulu } 118*91f16700Schasinglulu 119*91f16700Schasinglulu return 0; 120*91f16700Schasinglulu } 121*91f16700Schasinglulu 122*91f16700Schasinglulu #endif /* PMU_COM_H */ 123