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