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