xref: /rk3399_ARM-atf/plat/mediatek/drivers/spm/mt8196/mt_spm_conservation.c (revision b47dddd061e92054c3b2096fc8aa9688bfef68d6)
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 <inttypes.h>
9 #include <stddef.h>
10 #include <stdint.h>
11 #include <stdio.h>
12 #include <string.h>
13 
14 #include <common/debug.h>
15 #include <lib/mmio.h>
16 #include <plat/common/platform.h>
17 #include <platform_def.h>
18 
19 #include <lib/pm/mtk_pm.h>
20 #include <lpm_v2/mt_lp_rqm.h>
21 #include <mt_spm.h>
22 #include <mt_spm_common.h>
23 #include <mt_spm_conservation.h>
24 #include <mt_spm_reg.h>
25 #include <mt_spm_vcorefs.h>
26 
27 #define MT_RESUMETIME_THRESHOLD_MAX	5
28 #define IS_RESUME_OVERTIME(delta) \
29 	(delta > MT_RESUMETIME_THRESHOLD_MAX)
30 
31 static struct wake_status spm_wakesta; /* Record last wakesta */
32 static wake_reason_t spm_wake_reason = WR_NONE;
33 static struct resource_req_status generic_spm_resource_req = {
34 	.id = MT_LP_RQ_ID_ALL_USAGE,
35 	.val = 0,
36 };
37 
38 #define do_spm_init(pwrctrl)	({ int local_ret = 0; local_ret; })
39 #define do_spm_run(pwrctrl)	__spm_send_cpu_wakeup_event()
40 
41 static int go_to_spm_before_wfi(int state_id, uint32_t ext_opand,
42 				struct spm_lp_scen *spm_lp,
43 				uint32_t resource_req)
44 {
45 	int ret = 0;
46 	struct pwr_ctrl *pwrctrl;
47 
48 	pwrctrl = spm_lp->pwrctrl;
49 
50 #if SPM_FW_NO_RESUME == 0
51 	ret = do_spm_init(pwrctrl);
52 
53 	if (ret)
54 		return ret;
55 #endif
56 	__spm_set_power_control(pwrctrl, resource_req);
57 	__spm_set_wakeup_event(pwrctrl);
58 #if defined(CONFIG_MTK_VCOREDVFS_SUPPORT)
59 	__spm_sync_vcore_dvfs_power_control(pwrctrl, __spm_vcorefs.pwrctrl);
60 #endif
61 
62 #ifdef MTK_SPM_IVI_SUPPORT
63 	pwrctrl->pcm_flags |= SPM_FLAG_ENABLE_MT8196_IVI;
64 #endif
65 	__spm_set_pcm_flags(pwrctrl);
66 
67 #ifdef HW_S1_DETECT
68 	if (ext_opand & MT_SPM_EX_OP_HW_S1_DETECT)
69 		spm_hw_s1_state_monitor_resume();
70 #endif
71 	do_spm_run(pwrctrl);
72 	return ret;
73 }
74 
75 static void go_to_spm_after_wfi(int state_id, uint32_t ext_opand,
76 				struct spm_lp_scen *spm_lp,
77 				struct wake_status **status)
78 {
79 	uint32_t ext_status = 0;
80 
81 	spm_wakesta.tr.comm.resumetime = 0;
82 	spm_wakesta.tr.comm.times_h = spm_wakesta.tr.comm.times_l = 0;
83 
84 	if (ext_opand & MT_SPM_EX_OP_HW_S1_DETECT)
85 		spm_hw_s1_state_monitor_pause(&ext_status);
86 
87 	__spm_ext_int_wakeup_req_clr();
88 
89 	__spm_get_wakeup_status(&spm_wakesta, ext_status);
90 
91 	if (status)
92 		*status = &spm_wakesta;
93 
94 #ifndef MT_SPM_COMMON_SODI_SUPPORT
95 	__spm_clean_after_wakeup();
96 #endif
97 	spm_wake_reason = __spm_output_wake_reason(&spm_wakesta);
98 }
99 
100 int spm_conservation(int state_id, uint32_t ext_opand,
101 		     struct spm_lp_scen *spm_lp, uint32_t resource_req)
102 {
103 	uint32_t rc_state = resource_req;
104 
105 	if (!spm_lp)
106 		return -1;
107 
108 	spm_lock_get();
109 
110 	/* Uart bk/rs is needed if infra off for legacy project
111 	 * leave code here for reference.
112 	 */
113 	if (ext_opand & MT_SPM_EX_OP_NOTIFY_INFRA_OFF) {
114 #ifndef MTK_PLAT_SPM_UART_UNSUPPORT
115 		/* Notify UART to sleep */
116 		mt_uart_save();
117 #endif
118 	}
119 
120 	if (!(ext_opand & MT_SPM_EX_OP_NON_GENERIC_RESOURCE_REQ)) {
121 		/* Resource request */
122 		mt_lp_rq_get_status(PLAT_RQ_REQ_USAGE,
123 				    &generic_spm_resource_req);
124 		rc_state |= generic_spm_resource_req.val;
125 	}
126 	go_to_spm_before_wfi(state_id, ext_opand, spm_lp, rc_state);
127 
128 	spm_lock_release();
129 
130 	return 0;
131 }
132 
133 void spm_conservation_finish(int state_id, uint32_t ext_opand,
134 			     struct spm_lp_scen *spm_lp,
135 			     struct wake_status **status)
136 {
137 	/* Uart bk/rs is needed if infra off for legacy project
138 	 * leave code here for reference.
139 	 */
140 	if (ext_opand & MT_SPM_EX_OP_NOTIFY_INFRA_OFF) {
141 #ifndef MTK_PLAT_SPM_UART_UNSUPPORT
142 		/* Notify UART to wakeup */
143 		mt_uart_restore();
144 #endif
145 	}
146 
147 	spm_lock_get();
148 	go_to_spm_after_wfi(state_id, ext_opand, spm_lp, status);
149 #ifdef MT_SPM_COMMON_SODI_SUPPORT
150 	/* Restore common sodi mask and resource req setting */
151 	mt_spm_set_common_sodi_pwrctr();
152 	mt_spm_set_common_sodi_pcm_flags();
153 #endif
154 	spm_lock_release();
155 }
156 
157 int spm_conservation_get_result(struct wake_status **res)
158 {
159 	if (!res)
160 		return -1;
161 	*res = &spm_wakesta;
162 	return 0;
163 }
164