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