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