145d50759SJames Liao /*
245d50759SJames Liao * Copyright (c) 2023, MediaTek Inc. All rights reserved.
345d50759SJames Liao *
445d50759SJames Liao * SPDX-License-Identifier: BSD-3-Clause
545d50759SJames Liao */
645d50759SJames Liao
745d50759SJames Liao #include <assert.h>
845d50759SJames Liao #include <stddef.h>
945d50759SJames Liao #include <stdio.h>
1045d50759SJames Liao #include <string.h>
1145d50759SJames Liao
1245d50759SJames Liao #include <common/debug.h>
1345d50759SJames Liao #include <drivers/delay_timer.h>
1445d50759SJames Liao #include <lib/mmio.h>
1545d50759SJames Liao
1645d50759SJames Liao #include <drivers/spm/mt_spm_resource_req.h>
1745d50759SJames Liao #include "mt_spm.h"
1845d50759SJames Liao #include "mt_spm_internal.h"
1945d50759SJames Liao #include "mt_spm_pmic_wrap.h"
2045d50759SJames Liao #include "mt_spm_reg.h"
2145d50759SJames Liao #include <platform_def.h>
2245d50759SJames Liao
2345d50759SJames Liao #define SPM_INIT_DONE_US (20) /* Simulation result */
2445d50759SJames Liao
__spm_output_wake_reason(const struct wake_status * wakesta)2545d50759SJames Liao wake_reason_t __spm_output_wake_reason(const struct wake_status *wakesta)
2645d50759SJames Liao {
27*f85b34b1SJason Chen uint32_t bk_vtcxo_dur, spm_26m_off_pct;
2845d50759SJames Liao wake_reason_t wr = WR_UNKNOWN;
2945d50759SJames Liao
3045d50759SJames Liao if (wakesta == NULL) {
3145d50759SJames Liao return wr;
3245d50759SJames Liao }
3345d50759SJames Liao
3445d50759SJames Liao if (wakesta->is_abort != 0U) {
3545d50759SJames Liao VERBOSE("SPM EARLY WAKE r12 = 0x%x, debug_flag = 0x%x 0x%x\n",
3645d50759SJames Liao wakesta->tr.comm.r12,
3745d50759SJames Liao wakesta->tr.comm.debug_flag, wakesta->tr.comm.debug_flag1);
3845d50759SJames Liao VERBOSE("SPM EARLY WAKE sw_flag = 0x%x 0x%x b_sw_flag = 0x%x 0x%x\n",
3945d50759SJames Liao wakesta->sw_flag0, wakesta->sw_flag1,
4045d50759SJames Liao wakesta->tr.comm.b_sw_flag0, wakesta->tr.comm.b_sw_flag1);
4145d50759SJames Liao }
4245d50759SJames Liao
4345d50759SJames Liao if ((wakesta->tr.comm.r12 & R12_PCM_TIMER) != 0U) {
4445d50759SJames Liao
4545d50759SJames Liao if ((wakesta->wake_misc & WAKE_MISC_PCM_TIMER_EVENT) != 0U) {
4645d50759SJames Liao wr = WR_PCM_TIMER;
4745d50759SJames Liao }
4845d50759SJames Liao }
4945d50759SJames Liao
50*f85b34b1SJason Chen INFO("r12 = 0x%x, r12_ext = 0x%x, r13 = 0x%x, debug_flag = 0x%x 0x%x\n",
51*f85b34b1SJason Chen wakesta->tr.comm.r12, wakesta->r12_ext, wakesta->tr.comm.r13, wakesta->tr.comm.debug_flag,
52*f85b34b1SJason Chen wakesta->tr.comm.debug_flag1);
53*f85b34b1SJason Chen INFO("raw_sta = 0x%x 0x%x 0x%x, idle_sta = 0x%x, cg_check_sta = 0x%x\n",
54*f85b34b1SJason Chen wakesta->tr.comm.raw_sta, wakesta->md32pcm_wakeup_sta,
55*f85b34b1SJason Chen wakesta->md32pcm_event_sta, wakesta->idle_sta,
56*f85b34b1SJason Chen wakesta->cg_check_sta);
57*f85b34b1SJason Chen INFO("req_sta = 0x%x 0x%x 0x%x 0x%x 0x%x, isr = 0x%x\n",
58*f85b34b1SJason Chen wakesta->tr.comm.req_sta0, wakesta->tr.comm.req_sta1, wakesta->tr.comm.req_sta2,
59*f85b34b1SJason Chen wakesta->tr.comm.req_sta3, wakesta->tr.comm.req_sta4, wakesta->isr);
60*f85b34b1SJason Chen INFO("rt_req_sta0 = 0x%x, rt_req_sta1 = 0x%x, rt_req_sta2 = 0x%x\n",
61*f85b34b1SJason Chen wakesta->rt_req_sta0, wakesta->rt_req_sta1, wakesta->rt_req_sta2);
62*f85b34b1SJason Chen INFO("rt_req_sta3 = 0x%x, dram_sw_con_3 = 0x%x, raw_ext_sta = 0x%x\n",
63*f85b34b1SJason Chen wakesta->rt_req_sta3, wakesta->rt_req_sta4, wakesta->raw_ext_sta);
64*f85b34b1SJason Chen INFO("wake_misc = 0x%x, pcm_flag = 0x%x 0x%x 0x%x 0x%x, req = 0x%x\n",
65*f85b34b1SJason Chen wakesta->wake_misc, wakesta->sw_flag0, wakesta->sw_flag1,
66*f85b34b1SJason Chen wakesta->tr.comm.b_sw_flag0, wakesta->tr.comm.b_sw_flag1, wakesta->src_req);
67*f85b34b1SJason Chen INFO("clk_settle = 0x%x, wlk_cntcv_l = 0x%x, wlk_cntcv_h = 0x%x\n",
68*f85b34b1SJason Chen wakesta->clk_settle, mmio_read_32(SYS_TIMER_VALUE_L),
69*f85b34b1SJason Chen mmio_read_32(SYS_TIMER_VALUE_H));
70*f85b34b1SJason Chen
71*f85b34b1SJason Chen if (wakesta->tr.comm.timer_out != 0U) {
72*f85b34b1SJason Chen bk_vtcxo_dur = mmio_read_32(SPM_BK_VTCXO_DUR);
73*f85b34b1SJason Chen spm_26m_off_pct = (100 * bk_vtcxo_dur) / wakesta->tr.comm.timer_out;
74*f85b34b1SJason Chen INFO("spm_26m_off_pct = %u\n", spm_26m_off_pct);
75*f85b34b1SJason Chen }
76*f85b34b1SJason Chen
7745d50759SJames Liao return wr;
7845d50759SJames Liao }
7945d50759SJames Liao
__spm_set_cpu_status(unsigned int cpu)8045d50759SJames Liao void __spm_set_cpu_status(unsigned int cpu)
8145d50759SJames Liao {
8245d50759SJames Liao if (cpu >= 8) {
8345d50759SJames Liao ERROR("%s: error cpu number %d\n", __func__, cpu);
8445d50759SJames Liao return;
8545d50759SJames Liao }
8645d50759SJames Liao mmio_write_32(ROOT_CPUTOP_ADDR, BIT(cpu));
8745d50759SJames Liao mmio_write_32(ROOT_CORE_ADDR, SPM_CPU0_PWR_CON + (cpu * 0x4) + 0x20000000);
8845d50759SJames Liao /* Notify MCUPM to wake the target CPU up */
8945d50759SJames Liao mmio_write_32(MCUPM_MBOX_WAKEUP_CPU, cpu);
9045d50759SJames Liao }
9145d50759SJames Liao
__spm_src_req_update(const struct pwr_ctrl * pwrctrl,unsigned int resource_usage)9245d50759SJames Liao void __spm_src_req_update(const struct pwr_ctrl *pwrctrl, unsigned int resource_usage)
9345d50759SJames Liao {
9445d50759SJames Liao
9545d50759SJames Liao uint8_t reg_spm_apsrc_req = (resource_usage & MT_SPM_DRAM_S0) ?
9645d50759SJames Liao 1 : pwrctrl->reg_spm_apsrc_req;
9745d50759SJames Liao uint8_t reg_spm_ddr_en_req = (resource_usage & MT_SPM_DRAM_S1) ?
9845d50759SJames Liao 1 : pwrctrl->reg_spm_ddr_en_req;
9945d50759SJames Liao uint8_t reg_spm_vrf18_req = (resource_usage & MT_SPM_SYSPLL) ?
10045d50759SJames Liao 1 : pwrctrl->reg_spm_vrf18_req;
10145d50759SJames Liao uint8_t reg_spm_infra_req = (resource_usage & MT_SPM_INFRA) ?
10245d50759SJames Liao 1 : pwrctrl->reg_spm_infra_req;
10345d50759SJames Liao uint8_t reg_spm_f26m_req = (resource_usage & (MT_SPM_26M | MT_SPM_XO_FPM)) ?
10445d50759SJames Liao 1 : pwrctrl->reg_spm_f26m_req;
10545d50759SJames Liao
10645d50759SJames Liao /* SPM_SRC_REQ */
10745d50759SJames Liao mmio_write_32(SPM_SRC_REQ,
10845d50759SJames Liao ((reg_spm_apsrc_req & 0x1) << 0) |
10945d50759SJames Liao ((reg_spm_f26m_req & 0x1) << 1) |
11045d50759SJames Liao ((reg_spm_infra_req & 0x1) << 3) |
11145d50759SJames Liao ((reg_spm_vrf18_req & 0x1) << 4) |
11245d50759SJames Liao ((reg_spm_ddr_en_req & 0x1) << 7) |
11345d50759SJames Liao ((pwrctrl->reg_spm_dvfs_req & 0x1) << 8) |
11445d50759SJames Liao ((pwrctrl->reg_spm_sw_mailbox_req & 0x1) << 9) |
11545d50759SJames Liao ((pwrctrl->reg_spm_sspm_mailbox_req & 0x1) << 10) |
11645d50759SJames Liao ((pwrctrl->reg_spm_adsp_mailbox_req & 0x1) << 11) |
11745d50759SJames Liao ((pwrctrl->reg_spm_scp_mailbox_req & 0x1) << 12));
11845d50759SJames Liao }
11945d50759SJames Liao
__spm_set_power_control(const struct pwr_ctrl * pwrctrl)12045d50759SJames Liao void __spm_set_power_control(const struct pwr_ctrl *pwrctrl)
12145d50759SJames Liao {
12245d50759SJames Liao /* SPM_AP_STANDBY_CON */
12345d50759SJames Liao mmio_write_32(SPM_AP_STANDBY_CON,
12445d50759SJames Liao ((pwrctrl->reg_wfi_op & 0x1) << 0) |
12545d50759SJames Liao ((pwrctrl->reg_wfi_type & 0x1) << 1) |
12645d50759SJames Liao ((pwrctrl->reg_mp0_cputop_idle_mask & 0x1) << 2) |
12745d50759SJames Liao ((pwrctrl->reg_mp1_cputop_idle_mask & 0x1) << 3) |
12845d50759SJames Liao ((pwrctrl->reg_mcusys_idle_mask & 0x1) << 4) |
12945d50759SJames Liao ((pwrctrl->reg_md_apsrc_1_sel & 0x1) << 25) |
13045d50759SJames Liao ((pwrctrl->reg_md_apsrc_0_sel & 0x1) << 26) |
13145d50759SJames Liao ((pwrctrl->reg_conn_apsrc_sel & 0x1) << 29));
13245d50759SJames Liao
13345d50759SJames Liao /* SPM_SRC_REQ */
13445d50759SJames Liao mmio_write_32(SPM_SRC_REQ,
13545d50759SJames Liao ((pwrctrl->reg_spm_apsrc_req & 0x1) << 0) |
13645d50759SJames Liao ((pwrctrl->reg_spm_f26m_req & 0x1) << 1) |
13745d50759SJames Liao ((pwrctrl->reg_spm_infra_req & 0x1) << 3) |
13845d50759SJames Liao ((pwrctrl->reg_spm_vrf18_req & 0x1) << 4) |
13945d50759SJames Liao ((pwrctrl->reg_spm_ddr_en_req & 0x1) << 7) |
14045d50759SJames Liao ((pwrctrl->reg_spm_dvfs_req & 0x1) << 8) |
14145d50759SJames Liao ((pwrctrl->reg_spm_sw_mailbox_req & 0x1) << 9) |
14245d50759SJames Liao ((pwrctrl->reg_spm_sspm_mailbox_req & 0x1) << 10) |
14345d50759SJames Liao ((pwrctrl->reg_spm_adsp_mailbox_req & 0x1) << 11) |
14445d50759SJames Liao ((pwrctrl->reg_spm_scp_mailbox_req & 0x1) << 12));
14545d50759SJames Liao
14645d50759SJames Liao /* SPM_SRC_MASK */
14745d50759SJames Liao mmio_write_32(SPM_SRC_MASK,
14845d50759SJames Liao ((pwrctrl->reg_sspm_srcclkena_0_mask_b & 0x1) << 0) |
14945d50759SJames Liao ((pwrctrl->reg_sspm_infra_req_0_mask_b & 0x1) << 1) |
15045d50759SJames Liao ((pwrctrl->reg_sspm_apsrc_req_0_mask_b & 0x1) << 2) |
15145d50759SJames Liao ((pwrctrl->reg_sspm_vrf18_req_0_mask_b & 0x1) << 3) |
15245d50759SJames Liao ((pwrctrl->reg_sspm_ddr_en_0_mask_b & 0x1) << 4) |
15345d50759SJames Liao ((pwrctrl->reg_scp_srcclkena_mask_b & 0x1) << 5) |
15445d50759SJames Liao ((pwrctrl->reg_scp_infra_req_mask_b & 0x1) << 6) |
15545d50759SJames Liao ((pwrctrl->reg_scp_apsrc_req_mask_b & 0x1) << 7) |
15645d50759SJames Liao ((pwrctrl->reg_scp_vrf18_req_mask_b & 0x1) << 8) |
15745d50759SJames Liao ((pwrctrl->reg_scp_ddr_en_mask_b & 0x1) << 9) |
15845d50759SJames Liao ((pwrctrl->reg_audio_dsp_srcclkena_mask_b & 0x1) << 10) |
15945d50759SJames Liao ((pwrctrl->reg_audio_dsp_infra_req_mask_b & 0x1) << 11) |
16045d50759SJames Liao ((pwrctrl->reg_audio_dsp_apsrc_req_mask_b & 0x1) << 12) |
16145d50759SJames Liao ((pwrctrl->reg_audio_dsp_vrf18_req_mask_b & 0x1) << 13) |
16245d50759SJames Liao ((pwrctrl->reg_audio_dsp_ddr_en_mask_b & 0x1) << 14) |
16345d50759SJames Liao ((pwrctrl->reg_apu_srcclkena_mask_b & 0x1) << 15) |
16445d50759SJames Liao ((pwrctrl->reg_apu_infra_req_mask_b & 0x1) << 16) |
16545d50759SJames Liao ((pwrctrl->reg_apu_apsrc_req_mask_b & 0x1) << 17) |
16645d50759SJames Liao ((pwrctrl->reg_apu_vrf18_req_mask_b & 0x1) << 18) |
16745d50759SJames Liao ((pwrctrl->reg_apu_ddr_en_mask_b & 0x1) << 19) |
16845d50759SJames Liao ((pwrctrl->reg_cpueb_srcclkena_mask_b & 0x1) << 20) |
16945d50759SJames Liao ((pwrctrl->reg_cpueb_infra_req_mask_b & 0x1) << 21) |
17045d50759SJames Liao ((pwrctrl->reg_cpueb_apsrc_req_mask_b & 0x1) << 22) |
17145d50759SJames Liao ((pwrctrl->reg_cpueb_vrf18_req_mask_b & 0x1) << 23) |
17245d50759SJames Liao ((pwrctrl->reg_cpueb_ddr_en_mask_b & 0x1) << 24) |
17345d50759SJames Liao ((pwrctrl->reg_bak_psri_srcclkena_mask_b & 0x1) << 25) |
17445d50759SJames Liao ((pwrctrl->reg_bak_psri_infra_req_mask_b & 0x1) << 26) |
17545d50759SJames Liao ((pwrctrl->reg_bak_psri_apsrc_req_mask_b & 0x1) << 27) |
17645d50759SJames Liao ((pwrctrl->reg_bak_psri_vrf18_req_mask_b & 0x1) << 28) |
17745d50759SJames Liao ((pwrctrl->reg_bak_psri_ddr_en_mask_b & 0x1) << 29) |
17845d50759SJames Liao ((pwrctrl->reg_cam_ddren_req_mask_b & 0x1) << 30) |
17945d50759SJames Liao ((pwrctrl->reg_img_ddren_req_mask_b & 0x1) << 31));
18045d50759SJames Liao
18145d50759SJames Liao /* SPM_SRC2_MASK */
18245d50759SJames Liao mmio_write_32(SPM_SRC2_MASK,
18345d50759SJames Liao ((pwrctrl->reg_msdc0_srcclkena_mask_b & 0x1) << 0) |
18445d50759SJames Liao ((pwrctrl->reg_msdc0_infra_req_mask_b & 0x1) << 1) |
18545d50759SJames Liao ((pwrctrl->reg_msdc0_apsrc_req_mask_b & 0x1) << 2) |
18645d50759SJames Liao ((pwrctrl->reg_msdc0_vrf18_req_mask_b & 0x1) << 3) |
18745d50759SJames Liao ((pwrctrl->reg_msdc0_ddr_en_mask_b & 0x1) << 4) |
18845d50759SJames Liao ((pwrctrl->reg_msdc1_srcclkena_mask_b & 0x1) << 5) |
18945d50759SJames Liao ((pwrctrl->reg_msdc1_infra_req_mask_b & 0x1) << 6) |
19045d50759SJames Liao ((pwrctrl->reg_msdc1_apsrc_req_mask_b & 0x1) << 7) |
19145d50759SJames Liao ((pwrctrl->reg_msdc1_vrf18_req_mask_b & 0x1) << 8) |
19245d50759SJames Liao ((pwrctrl->reg_msdc1_ddr_en_mask_b & 0x1) << 9) |
19345d50759SJames Liao ((pwrctrl->reg_msdc2_srcclkena_mask_b & 0x1) << 10) |
19445d50759SJames Liao ((pwrctrl->reg_msdc2_infra_req_mask_b & 0x1) << 11) |
19545d50759SJames Liao ((pwrctrl->reg_msdc2_apsrc_req_mask_b & 0x1) << 12) |
19645d50759SJames Liao ((pwrctrl->reg_msdc2_vrf18_req_mask_b & 0x1) << 13) |
19745d50759SJames Liao ((pwrctrl->reg_msdc2_ddr_en_mask_b & 0x1) << 14) |
19845d50759SJames Liao ((pwrctrl->reg_ufs_srcclkena_mask_b & 0x1) << 15) |
19945d50759SJames Liao ((pwrctrl->reg_ufs_infra_req_mask_b & 0x1) << 16) |
20045d50759SJames Liao ((pwrctrl->reg_ufs_apsrc_req_mask_b & 0x1) << 17) |
20145d50759SJames Liao ((pwrctrl->reg_ufs_vrf18_req_mask_b & 0x1) << 18) |
20245d50759SJames Liao ((pwrctrl->reg_ufs_ddr_en_mask_b & 0x1) << 19) |
20345d50759SJames Liao ((pwrctrl->reg_usb_srcclkena_mask_b & 0x1) << 20) |
20445d50759SJames Liao ((pwrctrl->reg_usb_infra_req_mask_b & 0x1) << 21) |
20545d50759SJames Liao ((pwrctrl->reg_usb_apsrc_req_mask_b & 0x1) << 22) |
20645d50759SJames Liao ((pwrctrl->reg_usb_vrf18_req_mask_b & 0x1) << 23) |
20745d50759SJames Liao ((pwrctrl->reg_usb_ddr_en_mask_b & 0x1) << 24) |
20845d50759SJames Liao ((pwrctrl->reg_pextp_p0_srcclkena_mask_b & 0x1) << 25) |
20945d50759SJames Liao ((pwrctrl->reg_pextp_p0_infra_req_mask_b & 0x1) << 26) |
21045d50759SJames Liao ((pwrctrl->reg_pextp_p0_apsrc_req_mask_b & 0x1) << 27) |
21145d50759SJames Liao ((pwrctrl->reg_pextp_p0_vrf18_req_mask_b & 0x1) << 28) |
21245d50759SJames Liao ((pwrctrl->reg_pextp_p0_ddr_en_mask_b & 0x1) << 29));
21345d50759SJames Liao
21445d50759SJames Liao /* SPM_SRC3_MASK */
21545d50759SJames Liao mmio_write_32(SPM_SRC3_MASK,
21645d50759SJames Liao ((pwrctrl->reg_pextp_p1_srcclkena_mask_b & 0x1) << 0) |
21745d50759SJames Liao ((pwrctrl->reg_pextp_p1_infra_req_mask_b & 0x1) << 1) |
21845d50759SJames Liao ((pwrctrl->reg_pextp_p1_apsrc_req_mask_b & 0x1) << 2) |
21945d50759SJames Liao ((pwrctrl->reg_pextp_p1_vrf18_req_mask_b & 0x1) << 3) |
22045d50759SJames Liao ((pwrctrl->reg_pextp_p1_ddr_en_mask_b & 0x1) << 4) |
22145d50759SJames Liao ((pwrctrl->reg_gce0_infra_req_mask_b & 0x1) << 5) |
22245d50759SJames Liao ((pwrctrl->reg_gce0_apsrc_req_mask_b & 0x1) << 6) |
22345d50759SJames Liao ((pwrctrl->reg_gce0_vrf18_req_mask_b & 0x1) << 7) |
22445d50759SJames Liao ((pwrctrl->reg_gce0_ddr_en_mask_b & 0x1) << 8) |
22545d50759SJames Liao ((pwrctrl->reg_gce1_infra_req_mask_b & 0x1) << 9) |
22645d50759SJames Liao ((pwrctrl->reg_gce1_apsrc_req_mask_b & 0x1) << 10) |
22745d50759SJames Liao ((pwrctrl->reg_gce1_vrf18_req_mask_b & 0x1) << 11) |
22845d50759SJames Liao ((pwrctrl->reg_gce1_ddr_en_mask_b & 0x1) << 12) |
22945d50759SJames Liao ((pwrctrl->reg_spm_srcclkena_reserved_mask_b & 0x1) << 13) |
23045d50759SJames Liao ((pwrctrl->reg_spm_infra_req_reserved_mask_b & 0x1) << 14) |
23145d50759SJames Liao ((pwrctrl->reg_spm_apsrc_req_reserved_mask_b & 0x1) << 15) |
23245d50759SJames Liao ((pwrctrl->reg_spm_vrf18_req_reserved_mask_b & 0x1) << 16) |
23345d50759SJames Liao ((pwrctrl->reg_spm_ddr_en_reserved_mask_b & 0x1) << 17) |
23445d50759SJames Liao ((pwrctrl->reg_disp0_ddr_en_mask_b & 0x1) << 18) |
23545d50759SJames Liao ((pwrctrl->reg_disp0_ddr_en_mask_b & 0x1) << 19) |
23645d50759SJames Liao ((pwrctrl->reg_disp1_apsrc_req_mask_b & 0x1) << 20) |
23745d50759SJames Liao ((pwrctrl->reg_disp1_ddr_en_mask_b & 0x1) << 21) |
23845d50759SJames Liao ((pwrctrl->reg_disp2_apsrc_req_mask_b & 0x1) << 22) |
23945d50759SJames Liao ((pwrctrl->reg_disp2_ddr_en_mask_b & 0x1) << 23) |
24045d50759SJames Liao ((pwrctrl->reg_disp3_apsrc_req_mask_b & 0x1) << 24) |
24145d50759SJames Liao ((pwrctrl->reg_disp3_ddr_en_mask_b & 0x1) << 25) |
24245d50759SJames Liao ((pwrctrl->reg_infrasys_apsrc_req_mask_b & 0x1) << 26) |
24345d50759SJames Liao ((pwrctrl->reg_infrasys_ddr_en_mask_b & 0x1) << 27));
24445d50759SJames Liao
24545d50759SJames Liao /* SPM_SRC4_MASK */
24645d50759SJames Liao mmio_write_32(SPM_SRC4_MASK,
24745d50759SJames Liao ((pwrctrl->reg_mcusys_merge_apsrc_req_mask_b & 0x1ff) << 0) |
24845d50759SJames Liao ((pwrctrl->reg_mcusys_merge_ddr_en_mask_b & 0x1ff) << 9) |
24945d50759SJames Liao ((pwrctrl->reg_dramc_md32_infra_req_mask_b & 0x3) << 18) |
25045d50759SJames Liao ((pwrctrl->reg_dramc_md32_vrf18_req_mask_b & 0x3) << 20) |
25145d50759SJames Liao ((pwrctrl->reg_dramc_md32_ddr_en_mask_b & 0x3) << 22) |
25245d50759SJames Liao ((pwrctrl->reg_dvfsrc_event_trigger_mask_b & 0x1) << 24));
25345d50759SJames Liao
25445d50759SJames Liao /* SPM_WAKEUP_EVENT_MASK */
25545d50759SJames Liao mmio_write_32(SPM_WAKEUP_EVENT_MASK,
25645d50759SJames Liao ((pwrctrl->reg_wakeup_event_mask & 0xffffffff) << 0));
25745d50759SJames Liao
25845d50759SJames Liao /* SPM_WAKEUP_EVENT_EXT_MASK */
25945d50759SJames Liao mmio_write_32(SPM_WAKEUP_EVENT_EXT_MASK,
26045d50759SJames Liao ((pwrctrl->reg_ext_wakeup_event_mask & 0xffffffff) << 0));
26145d50759SJames Liao }
26245d50759SJames Liao
__spm_set_wakeup_event(const struct pwr_ctrl * pwrctrl)26345d50759SJames Liao void __spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl)
26445d50759SJames Liao {
26545d50759SJames Liao unsigned int val, mask;
26645d50759SJames Liao
26745d50759SJames Liao /* toggle event counter clear */
26845d50759SJames Liao mmio_setbits_32(PCM_CON1, SPM_REGWR_CFG_KEY | SPM_EVENT_COUNTER_CLR_LSB);
26945d50759SJames Liao /* toggle for reset SYS TIMER start point */
27045d50759SJames Liao mmio_setbits_32(SYS_TIMER_CON, SYS_TIMER_START_EN_LSB);
27145d50759SJames Liao
27245d50759SJames Liao if (pwrctrl->timer_val_cust == 0U) {
27345d50759SJames Liao val = (pwrctrl->timer_val != 0U) ? pwrctrl->timer_val : PCM_TIMER_MAX;
27445d50759SJames Liao } else {
27545d50759SJames Liao val = pwrctrl->timer_val_cust;
27645d50759SJames Liao }
27745d50759SJames Liao
27845d50759SJames Liao mmio_write_32(PCM_TIMER_VAL, val);
27945d50759SJames Liao mmio_setbits_32(PCM_CON1, SPM_REGWR_CFG_KEY | RG_PCM_TIMER_EN_LSB);
28045d50759SJames Liao
28145d50759SJames Liao /* unmask AP wakeup source */
28245d50759SJames Liao if (pwrctrl->wake_src_cust == 0U) {
28345d50759SJames Liao mask = pwrctrl->wake_src;
28445d50759SJames Liao } else {
28545d50759SJames Liao mask = pwrctrl->wake_src_cust;
28645d50759SJames Liao }
28745d50759SJames Liao
28845d50759SJames Liao mmio_write_32(SPM_WAKEUP_EVENT_MASK, ~mask);
28945d50759SJames Liao
29045d50759SJames Liao /* unmask SPM ISR (keep TWAM setting) */
29145d50759SJames Liao mmio_setbits_32(SPM_IRQ_MASK, ISRM_RET_IRQ_AUX);
29245d50759SJames Liao
29345d50759SJames Liao /* toggle event counter clear */
29445d50759SJames Liao mmio_clrsetbits_32(PCM_CON1, SPM_EVENT_COUNTER_CLR_LSB, SPM_REGWR_CFG_KEY);
29545d50759SJames Liao /* toggle for reset SYS TIMER start point */
29645d50759SJames Liao mmio_clrbits_32(SYS_TIMER_CON, SYS_TIMER_START_EN_LSB);
29745d50759SJames Liao }
29845d50759SJames Liao
__spm_set_pcm_flags(struct pwr_ctrl * pwrctrl)29945d50759SJames Liao void __spm_set_pcm_flags(struct pwr_ctrl *pwrctrl)
30045d50759SJames Liao {
30145d50759SJames Liao /* set PCM flags and data */
30245d50759SJames Liao if (pwrctrl->pcm_flags_cust_clr != 0U) {
30345d50759SJames Liao pwrctrl->pcm_flags &= ~pwrctrl->pcm_flags_cust_clr;
30445d50759SJames Liao }
30545d50759SJames Liao if (pwrctrl->pcm_flags_cust_set != 0U) {
30645d50759SJames Liao pwrctrl->pcm_flags |= pwrctrl->pcm_flags_cust_set;
30745d50759SJames Liao }
30845d50759SJames Liao if (pwrctrl->pcm_flags1_cust_clr != 0U) {
30945d50759SJames Liao pwrctrl->pcm_flags1 &= ~pwrctrl->pcm_flags1_cust_clr;
31045d50759SJames Liao }
31145d50759SJames Liao if (pwrctrl->pcm_flags1_cust_set != 0U) {
31245d50759SJames Liao pwrctrl->pcm_flags1 |= pwrctrl->pcm_flags1_cust_set;
31345d50759SJames Liao }
31445d50759SJames Liao
31545d50759SJames Liao mmio_write_32(SPM_SW_FLAG_0, pwrctrl->pcm_flags);
31645d50759SJames Liao
31745d50759SJames Liao mmio_write_32(SPM_SW_FLAG_1, pwrctrl->pcm_flags1);
31845d50759SJames Liao
31945d50759SJames Liao mmio_write_32(SPM_SW_RSV_7, pwrctrl->pcm_flags);
32045d50759SJames Liao
32145d50759SJames Liao mmio_write_32(SPM_SW_RSV_8, pwrctrl->pcm_flags1);
32245d50759SJames Liao }
32345d50759SJames Liao
__spm_get_wakeup_status(struct wake_status * wakesta,unsigned int ext_status)32445d50759SJames Liao void __spm_get_wakeup_status(struct wake_status *wakesta, unsigned int ext_status)
32545d50759SJames Liao {
32645d50759SJames Liao /* get wakeup event */
32745d50759SJames Liao wakesta->tr.comm.r12 = mmio_read_32(SPM_BK_WAKE_EVENT); /* backup of PCM_REG12_DATA */
32845d50759SJames Liao wakesta->r12_ext = mmio_read_32(SPM_WAKEUP_EXT_STA);
32945d50759SJames Liao wakesta->tr.comm.raw_sta = mmio_read_32(SPM_WAKEUP_STA);
33045d50759SJames Liao wakesta->raw_ext_sta = mmio_read_32(SPM_WAKEUP_EXT_STA);
33145d50759SJames Liao wakesta->md32pcm_wakeup_sta = mmio_read_32(MD32PCM_WAKEUP_STA);
33245d50759SJames Liao wakesta->md32pcm_event_sta = mmio_read_32(MD32PCM_EVENT_STA);
33345d50759SJames Liao wakesta->wake_misc = mmio_read_32(SPM_BK_WAKE_MISC); /* backup of SPM_WAKEUP_MISC */
33445d50759SJames Liao
33545d50759SJames Liao /* get sleep time */
33645d50759SJames Liao wakesta->tr.comm.timer_out =
33745d50759SJames Liao mmio_read_32(SPM_BK_PCM_TIMER); /* backup of PCM_TIMER_OUT */
33845d50759SJames Liao
33945d50759SJames Liao /* get other SYS and co-clock status */
34045d50759SJames Liao wakesta->tr.comm.r13 = mmio_read_32(PCM_REG13_DATA);
34145d50759SJames Liao wakesta->idle_sta = mmio_read_32(SUBSYS_IDLE_STA);
34245d50759SJames Liao wakesta->tr.comm.req_sta0 = mmio_read_32(SRC_REQ_STA_0);
34345d50759SJames Liao wakesta->tr.comm.req_sta1 = mmio_read_32(SRC_REQ_STA_1);
34445d50759SJames Liao wakesta->tr.comm.req_sta2 = mmio_read_32(SRC_REQ_STA_2);
34545d50759SJames Liao wakesta->tr.comm.req_sta3 = mmio_read_32(SRC_REQ_STA_3);
34645d50759SJames Liao wakesta->tr.comm.req_sta4 = mmio_read_32(SRC_REQ_STA_4);
34745d50759SJames Liao
34845d50759SJames Liao /* get debug flag for PCM execution check */
34945d50759SJames Liao wakesta->tr.comm.debug_flag = mmio_read_32(PCM_WDT_LATCH_SPARE_0);
35045d50759SJames Liao wakesta->tr.comm.debug_flag1 = mmio_read_32(PCM_WDT_LATCH_SPARE_1);
35145d50759SJames Liao
35245d50759SJames Liao if ((ext_status & SPM_INTERNAL_STATUS_HW_S1) != 0U) {
35345d50759SJames Liao wakesta->tr.comm.debug_flag |= (SPM_DBG_DEBUG_IDX_DDREN_WAKE |
35445d50759SJames Liao SPM_DBG_DEBUG_IDX_DDREN_SLEEP);
35545d50759SJames Liao mmio_write_32(PCM_WDT_LATCH_SPARE_0, wakesta->tr.comm.debug_flag);
35645d50759SJames Liao }
35745d50759SJames Liao
35845d50759SJames Liao /* get backup SW flag status */
35945d50759SJames Liao wakesta->tr.comm.b_sw_flag0 = mmio_read_32(SPM_SW_RSV_7); /* SPM_SW_RSV_7 */
36045d50759SJames Liao wakesta->tr.comm.b_sw_flag1 = mmio_read_32(SPM_SW_RSV_8); /* SPM_SW_RSV_8 */
36145d50759SJames Liao
362*f85b34b1SJason Chen /* record below spm info for debug */
363*f85b34b1SJason Chen wakesta->src_req = mmio_read_32(SPM_SRC_REQ);
364*f85b34b1SJason Chen
365*f85b34b1SJason Chen /* get HW CG check status */
366*f85b34b1SJason Chen wakesta->cg_check_sta = mmio_read_32(SPM_CG_CHECK_STA);
367*f85b34b1SJason Chen
368*f85b34b1SJason Chen wakesta->rt_req_sta0 = mmio_read_32(SPM_SW_RSV_2);
369*f85b34b1SJason Chen wakesta->rt_req_sta1 = mmio_read_32(SPM_SW_RSV_3);
370*f85b34b1SJason Chen wakesta->rt_req_sta2 = mmio_read_32(SPM_SW_RSV_4);
371*f85b34b1SJason Chen wakesta->rt_req_sta3 = mmio_read_32(SPM_SW_RSV_5);
372*f85b34b1SJason Chen wakesta->rt_req_sta4 = mmio_read_32(SPM_SW_RSV_6);
373*f85b34b1SJason Chen
37445d50759SJames Liao /* get ISR status */
37545d50759SJames Liao wakesta->isr = mmio_read_32(SPM_IRQ_STA);
37645d50759SJames Liao
37745d50759SJames Liao /* get SW flag status */
37845d50759SJames Liao wakesta->sw_flag0 = mmio_read_32(SPM_SW_FLAG_0);
37945d50759SJames Liao wakesta->sw_flag1 = mmio_read_32(SPM_SW_FLAG_1);
38045d50759SJames Liao
381*f85b34b1SJason Chen /* get CLK SETTLE */
382*f85b34b1SJason Chen wakesta->clk_settle = mmio_read_32(SPM_CLK_SETTLE);
383*f85b34b1SJason Chen
38445d50759SJames Liao /* check abort */
38545d50759SJames Liao wakesta->is_abort = wakesta->tr.comm.debug_flag & DEBUG_ABORT_MASK;
38645d50759SJames Liao wakesta->is_abort |= wakesta->tr.comm.debug_flag1 & DEBUG_ABORT_MASK_1;
38745d50759SJames Liao }
38845d50759SJames Liao
__spm_clean_after_wakeup(void)38945d50759SJames Liao void __spm_clean_after_wakeup(void)
39045d50759SJames Liao {
39145d50759SJames Liao /*
39245d50759SJames Liao * Copy SPM_WAKEUP_STA to SPM_BK_WAKE_EVENT before clear SPM_WAKEUP_STA
39345d50759SJames Liao *
39445d50759SJames Liao * CPU dormant driver @kernel will copy edge-trig IRQ pending
39545d50759SJames Liao * (recorded @SPM_BK_WAKE_EVENT) to GIC
39645d50759SJames Liao */
39745d50759SJames Liao mmio_write_32(SPM_BK_WAKE_EVENT, mmio_read_32(SPM_WAKEUP_STA) |
39845d50759SJames Liao mmio_read_32(SPM_BK_WAKE_EVENT));
39945d50759SJames Liao
40045d50759SJames Liao /* clean CPU wakeup event */
40145d50759SJames Liao mmio_write_32(SPM_CPU_WAKEUP_EVENT, 0U);
40245d50759SJames Liao
40345d50759SJames Liao /* clean wakeup event raw status (for edge trigger event) */
40445d50759SJames Liao mmio_write_32(SPM_WAKEUP_EVENT_MASK, 0xefffffff); /* bit[28] for cpu wake up event */
40545d50759SJames Liao
40645d50759SJames Liao /* clean ISR status (except TWAM) */
40745d50759SJames Liao mmio_setbits_32(SPM_IRQ_MASK, ISRM_ALL_EXC_TWAM);
40845d50759SJames Liao mmio_write_32(SPM_IRQ_STA, ISRC_ALL_EXC_TWAM);
40945d50759SJames Liao mmio_write_32(SPM_SWINT_CLR, PCM_SW_INT_ALL);
41045d50759SJames Liao }
41145d50759SJames Liao
__spm_set_pcm_wdt(int en)41245d50759SJames Liao void __spm_set_pcm_wdt(int en)
41345d50759SJames Liao {
41445d50759SJames Liao /* enable PCM WDT (normal mode) to start count if needed */
41545d50759SJames Liao if (en != 0) {
41645d50759SJames Liao mmio_clrsetbits_32(PCM_CON1, RG_PCM_WDT_WAKE_LSB, SPM_REGWR_CFG_KEY);
41745d50759SJames Liao
41845d50759SJames Liao if (mmio_read_32(PCM_TIMER_VAL) > PCM_TIMER_MAX) {
41945d50759SJames Liao mmio_write_32(PCM_TIMER_VAL, PCM_TIMER_MAX);
42045d50759SJames Liao }
42145d50759SJames Liao mmio_write_32(PCM_WDT_VAL, mmio_read_32(PCM_TIMER_VAL) + PCM_WDT_TIMEOUT);
42245d50759SJames Liao mmio_setbits_32(PCM_CON1, SPM_REGWR_CFG_KEY | RG_PCM_WDT_EN_LSB);
42345d50759SJames Liao } else {
42445d50759SJames Liao mmio_clrsetbits_32(PCM_CON1, RG_PCM_WDT_EN_LSB, SPM_REGWR_CFG_KEY);
42545d50759SJames Liao }
42645d50759SJames Liao }
42745d50759SJames Liao
__spm_send_cpu_wakeup_event(void)42845d50759SJames Liao void __spm_send_cpu_wakeup_event(void)
42945d50759SJames Liao {
43045d50759SJames Liao mmio_write_32(SPM_CPU_WAKEUP_EVENT, 1);
43145d50759SJames Liao /* SPM will clear SPM_CPU_WAKEUP_EVENT */
43245d50759SJames Liao }
43345d50759SJames Liao
__spm_ext_int_wakeup_req_clr(void)43445d50759SJames Liao void __spm_ext_int_wakeup_req_clr(void)
43545d50759SJames Liao {
43645d50759SJames Liao mmio_write_32(EXT_INT_WAKEUP_REQ_CLR, mmio_read_32(ROOT_CPUTOP_ADDR));
43745d50759SJames Liao
43845d50759SJames Liao /* clear spm2mcupm wakeup interrupt status */
43945d50759SJames Liao mmio_write_32(SPM2CPUEB_CON, 0);
44045d50759SJames Liao }
44145d50759SJames Liao
__spm_clean_before_wfi(void)44245d50759SJames Liao void __spm_clean_before_wfi(void)
44345d50759SJames Liao {
44445d50759SJames Liao }
44545d50759SJames Liao
__spm_hw_s1_state_monitor(int en,unsigned int * status)44645d50759SJames Liao void __spm_hw_s1_state_monitor(int en, unsigned int *status)
44745d50759SJames Liao {
44845d50759SJames Liao unsigned int reg;
44945d50759SJames Liao
45045d50759SJames Liao if (en != 0) {
45145d50759SJames Liao mmio_clrsetbits_32(SPM_ACK_CHK_CON_3, SPM_ACK_CHK_3_CON_CLR_ALL,
45245d50759SJames Liao SPM_ACK_CHK_3_CON_EN);
45345d50759SJames Liao } else {
45445d50759SJames Liao reg = mmio_read_32(SPM_ACK_CHK_CON_3);
45545d50759SJames Liao
45645d50759SJames Liao if ((reg & SPM_ACK_CHK_3_CON_RESULT) != 0U) {
45745d50759SJames Liao if (status != NULL) {
45845d50759SJames Liao *status |= SPM_INTERNAL_STATUS_HW_S1;
45945d50759SJames Liao }
46045d50759SJames Liao }
46145d50759SJames Liao
46245d50759SJames Liao mmio_clrsetbits_32(SPM_ACK_CHK_CON_3, SPM_ACK_CHK_3_CON_EN,
46345d50759SJames Liao (SPM_ACK_CHK_3_CON_HW_MODE_TRIG | SPM_ACK_CHK_3_CON_CLR_ALL));
46445d50759SJames Liao }
46545d50759SJames Liao }
466