1 /* 2 * Copyright (c) 2025, MediaTek Inc. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <stdint.h> 9 10 #include <lib/spinlock.h> 11 #include <platform_def.h> 12 13 #include "../inc/pwr_topology.h" 14 #include <lib/pm/mtk_pm.h> 15 #include <lpm/mt_lp_rm.h> 16 17 #ifdef MT_CPU_PM_USING_BAKERY_LOCK 18 DEFINE_BAKERY_LOCK(mt_pwr_lock); 19 20 #define plat_pwr_lock_init() bakery_lock_init(&mt_pwr_lock) 21 22 #define plat_pwr_lock() bakery_lock_get(&mt_pwr_lock) 23 24 #define plat_pwr_unlock() bakery_lock_release(&mt_pwr_lock) 25 #else 26 spinlock_t mt_pwr_lock; 27 28 #define plat_pwr_lock_init() 29 #define plat_pwr_lock() spin_lock(&mt_pwr_lock) 30 31 #define plat_pwr_unlock() spin_unlock(&mt_pwr_lock) 32 #endif 33 34 enum mt_pwr_domain_node { 35 MT_PWR_NONMCUSYS = 0, 36 MT_PWR_MCUSYS_PDN, 37 MT_PWR_MAX 38 }; 39 40 #if CONFIG_MTK_PM_SUPPORT && CONFIG_MTK_CPU_SUSPEND_EN && \ 41 !CPU_PM_DOMAIN_CORE_ONLY 42 static int mt_pwr_domain_st[MT_PWR_MAX]; 43 #endif 44 45 #define ALL_IN_ONE_GROUP 0xFF 46 unsigned int pwr_domain_coordination(enum pwr_domain_status pwr, 47 const mtk_pstate_type psci_state, 48 const struct mtk_cpupm_pwrstate *state, 49 afflv_prepare fn) 50 { 51 unsigned int pstate = 0; 52 53 #if CONFIG_MTK_PM_SUPPORT && CONFIG_MTK_CPU_SUSPEND_EN && \ 54 !CPU_PM_DOMAIN_CORE_ONLY 55 unsigned int is_flush = 0; 56 struct pwr_toplogy tp = { 57 .cur_group_bit = ALL_IN_ONE_GROUP, 58 .group = ALL_IN_ONE_GROUP, 59 }; 60 61 /* Skip to process smp */ 62 if (pwr > PWR_DOMAIN_OFF) 63 return pstate; 64 65 if (!IS_MT_PLAT_PWR_STATE_MCUSYS(state->pwr.state_id)) { 66 plat_pwr_lock(); 67 if (pwr == PWR_DOMAIN_OFF) 68 mt_pwr_domain_st[MT_PWR_NONMCUSYS] += 1; 69 else 70 mt_pwr_domain_st[MT_PWR_NONMCUSYS] -= 1; 71 flush_dcache_range( 72 (uintptr_t)&mt_pwr_domain_st[MT_PWR_NONMCUSYS], 73 sizeof(mt_pwr_domain_st[MT_PWR_NONMCUSYS])); 74 plat_pwr_unlock(); 75 } 76 77 plat_pwr_lock(); 78 if (state->pwr.afflv >= PLAT_MT_CPU_SUSPEND_CLUSTER) 79 pstate |= MT_CPUPM_PWR_DOMAIN_CLUSTER; 80 81 if (psci_get_pstate_pwrlvl(psci_state) >= PLAT_MT_CPU_SUSPEND_CLUSTER) 82 pstate |= MT_CPUPM_PWR_DOMAIN_PERCORE_DSU; 83 84 if (pwr == PWR_DOMAIN_OFF) { 85 if (IS_PLAT_MCUSYSOFF_AFFLV(state->pwr.afflv) && 86 (mt_pwr_domain_st[MT_PWR_NONMCUSYS] == 0)) { 87 int ret = MTK_CPUPM_E_OK; 88 89 tp.group = ALL_IN_ONE_GROUP; 90 if (fn) 91 ret = fn(1, state, &tp); 92 93 if (ret == MTK_CPUPM_E_OK) { 94 pstate |= MT_CPUPM_PWR_DOMAIN_MCUSYS; 95 mt_pwr_domain_st[MT_PWR_MCUSYS_PDN] += 1; 96 is_flush = 1; 97 } 98 } 99 } else { 100 if (mt_pwr_domain_st[MT_PWR_MCUSYS_PDN]) { 101 tp.group = 0x0; 102 if (fn) 103 fn(1, state, &tp); 104 pstate |= MT_CPUPM_PWR_DOMAIN_MCUSYS; 105 mt_pwr_domain_st[MT_PWR_MCUSYS_PDN] -= 1; 106 is_flush = 1; 107 } 108 if (mt_pwr_domain_st[MT_PWR_NONMCUSYS] < 0) 109 assert(0); 110 } 111 112 if (is_flush) 113 flush_dcache_range( 114 (uintptr_t)&mt_pwr_domain_st[MT_PWR_MCUSYS_PDN], 115 sizeof(mt_pwr_domain_st[MT_PWR_MCUSYS_PDN])); 116 117 plat_pwr_unlock(); 118 #endif 119 return pstate; 120 } 121 122 void pwr_topology_init(void) 123 { 124 plat_pwr_lock_init(); 125 } 126