xref: /rk3399_ARM-atf/plat/mediatek/drivers/spm/mt8188/mt_spm_conservation.c (revision f90fe02f061b8a203391e566682221396b656c6f)
1 /*
2  * Copyright (c) 2023, MediaTek Inc. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 #include <stddef.h>
9 #include <stdio.h>
10 #include <string.h>
11 
12 #include <common/debug.h>
13 #include <lib/mmio.h>
14 #include <plat/common/platform.h>
15 #include <lib/pm/mtk_pm.h>
16 #include <lpm/mt_lp_rqm.h>
17 #include "mt_spm.h"
18 #include "mt_spm_conservation.h"
19 #include "mt_spm_reg.h"
20 #include <platform_def.h>
21 
22 #define INFRA_EMI_DCM_CFG0	U(0x10002028)
23 
24 static struct wake_status spm_wakesta; /* record last wakesta */
25 static wake_reason_t spm_wake_reason = WR_NONE;
26 static unsigned int emi_bak;
27 
28 static int go_to_spm_before_wfi(int state_id, unsigned int ext_opand,
29 				struct spm_lp_scen *spm_lp,
30 				unsigned int resource_req)
31 {
32 	int ret = 0;
33 	struct pwr_ctrl *pwrctrl;
34 	unsigned int cpu = plat_my_core_pos();
35 
36 	pwrctrl = spm_lp->pwrctrl;
37 
38 	/* EMI workaround */
39 	emi_bak = mmio_read_32(INFRA_EMI_DCM_CFG0) & BIT(22);
40 	mmio_setbits_32(INFRA_EMI_DCM_CFG0, BIT(22));
41 
42 	__spm_set_cpu_status(cpu);
43 	__spm_set_power_control(pwrctrl);
44 	__spm_set_wakeup_event(pwrctrl);
45 
46 	__spm_set_pcm_flags(pwrctrl);
47 
48 	__spm_src_req_update(pwrctrl, resource_req);
49 
50 	if ((ext_opand & MT_SPM_EX_OP_CLR_26M_RECORD) != 0U) {
51 		__spm_clean_before_wfi();
52 	}
53 
54 	if ((ext_opand & MT_SPM_EX_OP_SET_WDT) != 0U) {
55 		__spm_set_pcm_wdt(1);
56 	}
57 
58 	if ((ext_opand & MT_SPM_EX_OP_HW_S1_DETECT) != 0U) {
59 		spm_hw_s1_state_monitor_resume();
60 	}
61 
62 	__spm_send_cpu_wakeup_event();
63 
64 	return ret;
65 }
66 
67 static void go_to_spm_after_wfi(int state_id, unsigned int ext_opand,
68 				struct spm_lp_scen *spm_lp,
69 				struct wake_status **status)
70 {
71 	unsigned int ext_status = 0U;
72 
73 	if ((ext_opand & MT_SPM_EX_OP_SET_WDT) != 0U) {
74 		__spm_set_pcm_wdt(0);
75 	}
76 
77 	if ((ext_opand & MT_SPM_EX_OP_HW_S1_DETECT) != 0U) {
78 		spm_hw_s1_state_monitor_pause(&ext_status);
79 	}
80 
81 	__spm_ext_int_wakeup_req_clr();
82 
83 	__spm_get_wakeup_status(&spm_wakesta, ext_status);
84 
85 	if (status != NULL) {
86 		*status = &spm_wakesta;
87 	}
88 
89 	__spm_clean_after_wakeup();
90 	spm_wake_reason = __spm_output_wake_reason(&spm_wakesta);
91 
92 	/* EMI workaround */
93 	if (emi_bak == 0U) {
94 		mmio_clrbits_32(INFRA_EMI_DCM_CFG0, BIT(22));
95 	}
96 }
97 
98 int spm_conservation(int state_id, unsigned int ext_opand,
99 		     struct spm_lp_scen *spm_lp,
100 		     unsigned int resource_req)
101 {
102 	unsigned int rc_state = resource_req;
103 
104 	if (spm_lp == NULL) {
105 		return -1;
106 	}
107 
108 	spin_lock(&spm_lock);
109 	go_to_spm_before_wfi(state_id, ext_opand, spm_lp, rc_state);
110 	spin_unlock(&spm_lock);
111 
112 	return 0;
113 }
114 
115 void spm_conservation_finish(int state_id, unsigned int ext_opand, struct spm_lp_scen *spm_lp,
116 			     struct wake_status **status)
117 {
118 	spin_lock(&spm_lock);
119 	go_to_spm_after_wfi(state_id, ext_opand, spm_lp, status);
120 	spin_unlock(&spm_lock);
121 }
122 
123 int spm_conservation_get_result(struct wake_status **res)
124 {
125 	if (res == NULL) {
126 		return -1;
127 	}
128 	*res = &spm_wakesta;
129 	return 0;
130 }
131