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