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