xref: /rk3399_ARM-atf/plat/mediatek/drivers/cpu_pm/topology/default/pwr.c (revision cf2df874cd09305ac7282fadb0fef6be597dfffb)
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
pwr_domain_coordination(enum pwr_domain_status pwr,const mtk_pstate_type psci_state,const struct mtk_cpupm_pwrstate * state,afflv_prepare fn)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 
pwr_topology_init(void)122 void pwr_topology_init(void)
123 {
124 	plat_pwr_lock_init();
125 }
126