xref: /arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_conservation.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2022, MediaTek Inc. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <common/debug.h>
8*91f16700Schasinglulu #include <lib/mmio.h>
9*91f16700Schasinglulu #include <plat/common/platform.h>
10*91f16700Schasinglulu #include <mt_spm.h>
11*91f16700Schasinglulu #include <mt_spm_conservation.h>
12*91f16700Schasinglulu #include <mt_spm_internal.h>
13*91f16700Schasinglulu #include <mt_spm_reg.h>
14*91f16700Schasinglulu #include <mt_spm_resource_req.h>
15*91f16700Schasinglulu #include <mt_spm_vcorefs.h>
16*91f16700Schasinglulu #include <plat_mtk_lpm.h>
17*91f16700Schasinglulu #include <plat_pm.h>
18*91f16700Schasinglulu #include <platform_def.h>
19*91f16700Schasinglulu 
20*91f16700Schasinglulu #define MT_RESUMETIME_THRESHOLD_MAX	(5U) /*ms*/
21*91f16700Schasinglulu #define IS_RESUME_OVERTIME(delta)	(delta > MT_RESUMETIME_THRESHOLD_MAX)
22*91f16700Schasinglulu 
23*91f16700Schasinglulu static struct wake_status spm_wakesta; /* record last wakesta */
24*91f16700Schasinglulu 
25*91f16700Schasinglulu static int go_to_spm_before_wfi(int state_id, unsigned int ext_opand,
26*91f16700Schasinglulu 				struct spm_lp_scen *spm_lp,
27*91f16700Schasinglulu 				unsigned int resource_req)
28*91f16700Schasinglulu {
29*91f16700Schasinglulu 	int ret = 0;
30*91f16700Schasinglulu 	struct pwr_ctrl *pwrctrl;
31*91f16700Schasinglulu 	uint32_t cpu = plat_my_core_pos();
32*91f16700Schasinglulu 
33*91f16700Schasinglulu 	pwrctrl = spm_lp->pwrctrl;
34*91f16700Schasinglulu 
35*91f16700Schasinglulu 	__spm_set_cpu_status(cpu);
36*91f16700Schasinglulu 	__spm_set_power_control(pwrctrl);
37*91f16700Schasinglulu 	__spm_set_wakeup_event(pwrctrl);
38*91f16700Schasinglulu 	__spm_sync_vcore_dvfs_power_control(pwrctrl, __spm_vcorefs.pwrctrl);
39*91f16700Schasinglulu 	__spm_set_pcm_flags(pwrctrl);
40*91f16700Schasinglulu 
41*91f16700Schasinglulu 	__spm_src_req_update(pwrctrl, resource_req);
42*91f16700Schasinglulu 
43*91f16700Schasinglulu 	if ((ext_opand & MT_SPM_EX_OP_SET_WDT) != 0U) {
44*91f16700Schasinglulu 		__spm_set_pcm_wdt(1);
45*91f16700Schasinglulu 	}
46*91f16700Schasinglulu 
47*91f16700Schasinglulu 	if ((ext_opand & MT_SPM_EX_OP_SRCLKEN_RC_BBLPM) != 0U) {
48*91f16700Schasinglulu 		__spm_xo_soc_bblpm(1);
49*91f16700Schasinglulu 	}
50*91f16700Schasinglulu 
51*91f16700Schasinglulu 	if ((ext_opand & MT_SPM_EX_OP_HW_S1_DETECT) != 0U) {
52*91f16700Schasinglulu 		spm_hw_s1_state_monitor_resume();
53*91f16700Schasinglulu 	}
54*91f16700Schasinglulu 
55*91f16700Schasinglulu 	/* Disable auto resume by PCM in system suspend stage */
56*91f16700Schasinglulu 	if (IS_PLAT_SUSPEND_ID(state_id)) {
57*91f16700Schasinglulu 		__spm_disable_pcm_timer();
58*91f16700Schasinglulu 		__spm_set_pcm_wdt(0);
59*91f16700Schasinglulu 	}
60*91f16700Schasinglulu 
61*91f16700Schasinglulu 	__spm_send_cpu_wakeup_event();
62*91f16700Schasinglulu 
63*91f16700Schasinglulu 	INFO("cpu%d: wakesrc = 0x%x, settle = 0x%x, sec = %u\n",
64*91f16700Schasinglulu 	     cpu, pwrctrl->wake_src, mmio_read_32(SPM_CLK_SETTLE),
65*91f16700Schasinglulu 	     (mmio_read_32(PCM_TIMER_VAL) / 32768));
66*91f16700Schasinglulu 	INFO("sw_flag = 0x%x 0x%x, req = 0x%x, pwr = 0x%x 0x%x\n",
67*91f16700Schasinglulu 	     pwrctrl->pcm_flags, pwrctrl->pcm_flags1,
68*91f16700Schasinglulu 	     mmio_read_32(SPM_SRC_REQ), mmio_read_32(PWR_STATUS),
69*91f16700Schasinglulu 	     mmio_read_32(PWR_STATUS_2ND));
70*91f16700Schasinglulu 
71*91f16700Schasinglulu 	return ret;
72*91f16700Schasinglulu }
73*91f16700Schasinglulu 
74*91f16700Schasinglulu static void go_to_spm_after_wfi(int state_id, unsigned int ext_opand,
75*91f16700Schasinglulu 				struct spm_lp_scen *spm_lp,
76*91f16700Schasinglulu 				struct wake_status **status)
77*91f16700Schasinglulu {
78*91f16700Schasinglulu 	unsigned int ext_status = 0U;
79*91f16700Schasinglulu 
80*91f16700Schasinglulu 	spm_wakesta.tr.comm.resumetime = 0;
81*91f16700Schasinglulu 	spm_wakesta.tr.comm.times_h = spm_wakesta.tr.comm.times_l = 0;
82*91f16700Schasinglulu 
83*91f16700Schasinglulu 	/* system watchdog will be resumed at kernel stage */
84*91f16700Schasinglulu 	if ((ext_opand & MT_SPM_EX_OP_SET_WDT) != 0U) {
85*91f16700Schasinglulu 		__spm_set_pcm_wdt(0);
86*91f16700Schasinglulu 	}
87*91f16700Schasinglulu 
88*91f16700Schasinglulu 	if ((ext_opand & MT_SPM_EX_OP_SRCLKEN_RC_BBLPM) != 0U) {
89*91f16700Schasinglulu 		__spm_xo_soc_bblpm(0);
90*91f16700Schasinglulu 	}
91*91f16700Schasinglulu 
92*91f16700Schasinglulu 	if ((ext_opand & MT_SPM_EX_OP_HW_S1_DETECT) != 0U) {
93*91f16700Schasinglulu 		spm_hw_s1_state_monitor_pause(&ext_status);
94*91f16700Schasinglulu 	}
95*91f16700Schasinglulu 
96*91f16700Schasinglulu 	__spm_ext_int_wakeup_req_clr();
97*91f16700Schasinglulu 
98*91f16700Schasinglulu 	__spm_get_wakeup_status(&spm_wakesta, ext_status);
99*91f16700Schasinglulu 
100*91f16700Schasinglulu 	if (status != NULL) {
101*91f16700Schasinglulu 		*status = &spm_wakesta;
102*91f16700Schasinglulu 	}
103*91f16700Schasinglulu 
104*91f16700Schasinglulu 	__spm_clean_after_wakeup();
105*91f16700Schasinglulu 
106*91f16700Schasinglulu 	if (IS_PLAT_SUSPEND_ID(state_id)) {
107*91f16700Schasinglulu 		__spm_output_wake_reason(state_id, &spm_wakesta);
108*91f16700Schasinglulu 	}
109*91f16700Schasinglulu 
110*91f16700Schasinglulu }
111*91f16700Schasinglulu 
112*91f16700Schasinglulu int spm_conservation(int state_id, unsigned int ext_opand,
113*91f16700Schasinglulu 		     struct spm_lp_scen *spm_lp, unsigned int resource_req)
114*91f16700Schasinglulu {
115*91f16700Schasinglulu 	int ret = 0;
116*91f16700Schasinglulu 
117*91f16700Schasinglulu 	if (spm_lp == NULL) {
118*91f16700Schasinglulu 		ret = -1;
119*91f16700Schasinglulu 	} else {
120*91f16700Schasinglulu 		spm_lock_get();
121*91f16700Schasinglulu 		go_to_spm_before_wfi(state_id, ext_opand, spm_lp, resource_req);
122*91f16700Schasinglulu 		spm_lock_release();
123*91f16700Schasinglulu 	}
124*91f16700Schasinglulu 
125*91f16700Schasinglulu 	return ret;
126*91f16700Schasinglulu }
127*91f16700Schasinglulu 
128*91f16700Schasinglulu void spm_conservation_finish(int state_id, unsigned int ext_opand,
129*91f16700Schasinglulu 			     struct spm_lp_scen *spm_lp,
130*91f16700Schasinglulu 			     struct wake_status **status)
131*91f16700Schasinglulu {
132*91f16700Schasinglulu 	spm_lock_get();
133*91f16700Schasinglulu 	go_to_spm_after_wfi(state_id, ext_opand, spm_lp, status);
134*91f16700Schasinglulu 	spm_lock_release();
135*91f16700Schasinglulu }
136*91f16700Schasinglulu 
137*91f16700Schasinglulu int spm_conservation_get_result(struct wake_status **res)
138*91f16700Schasinglulu {
139*91f16700Schasinglulu 	int ret = 0;
140*91f16700Schasinglulu 
141*91f16700Schasinglulu 	if (res == NULL) {
142*91f16700Schasinglulu 		ret = -1;
143*91f16700Schasinglulu 	} else {
144*91f16700Schasinglulu 		*res = &spm_wakesta;
145*91f16700Schasinglulu 	}
146*91f16700Schasinglulu 	return ret;
147*91f16700Schasinglulu }
148*91f16700Schasinglulu 
149*91f16700Schasinglulu #define GPIO_BANK	(GPIO_BASE + 0x6F0)
150*91f16700Schasinglulu #define TRAP_UFS_FIRST	BIT(11) /* bit 11, 0: UFS, 1: eMMC */
151*91f16700Schasinglulu 
152*91f16700Schasinglulu void spm_conservation_pwrctrl_init(struct pwr_ctrl *pwrctrl)
153*91f16700Schasinglulu {
154*91f16700Schasinglulu 	if (pwrctrl != NULL) {
155*91f16700Schasinglulu 		/* For ufs, emmc storage type */
156*91f16700Schasinglulu 		if ((mmio_read_32(GPIO_BANK) & TRAP_UFS_FIRST) != 0U) {
157*91f16700Schasinglulu 			/* If eMMC is used, mask UFS req */
158*91f16700Schasinglulu 			pwrctrl->reg_ufs_srcclkena_mask_b = 0;
159*91f16700Schasinglulu 			pwrctrl->reg_ufs_infra_req_mask_b = 0;
160*91f16700Schasinglulu 			pwrctrl->reg_ufs_apsrc_req_mask_b = 0;
161*91f16700Schasinglulu 			pwrctrl->reg_ufs_vrf18_req_mask_b = 0;
162*91f16700Schasinglulu 			pwrctrl->reg_ufs_ddren_req_mask_b = 0;
163*91f16700Schasinglulu 		}
164*91f16700Schasinglulu 	}
165*91f16700Schasinglulu }
166