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