blob: c6c2e382599c5ec2e6df7225cbe726536e1effe1 [file] [log] [blame]
developerba7b7d22021-11-14 10:14:45 +08001/*
2 * Copyright (c) 2021, MediaTek Inc. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
8#include <stdint.h>
9
10#include <arch_helpers.h>
11#include <lib/psci/psci.h>
12#include <lib/spinlock.h>
13
14#include <mt_cpu_pm_cpc.h>
15#include <mt_mcdi.h>
16#include <plat_mtk_lpm.h>
17#include <plat_pm.h>
18
19DEFINE_SYSREG_RW_FUNCS(dbgprcr_el1);
20
21static int plat_mt_lp_cpu_rc;
22
23static int pwr_state_prompt(unsigned int cpu, const psci_power_state_t *state)
24{
25 return 0;
26}
27
28static int pwr_state_reflect(unsigned int cpu, const psci_power_state_t *state)
29{
30 mtk_cpc_core_on_hint_clr(cpu);
31
32 if (IS_SYSTEM_SUSPEND_STATE(state)) {
33 mtk_cpc_time_sync();
34 }
35
36 return 0;
37}
38
39static int pwr_cpu_pwron(unsigned int cpu, const psci_power_state_t *state)
40{
41 return 0;
42}
43
44static int pwr_cpu_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
45{
46 /* clear DBGPRCR.CORENPDRQ to allow CPU power down */
47 write_dbgprcr_el1(0ULL);
48
49 return 0;
50}
51
52static int pwr_cluster_pwron(unsigned int cpu, const psci_power_state_t *state)
53{
54 return 0;
55}
56
57static int pwr_cluster_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
58{
59 return 0;
60}
61
62static int pwr_mcusys_pwron(unsigned int cpu, const psci_power_state_t *state)
63{
64 if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) {
65 return -1;
66 }
67
68 mtk_cpc_mcusys_off_reflect();
69
70 return 0;
71}
72
73static int pwr_mcusys_pwron_finished(unsigned int cpu,
74 const psci_power_state_t *state)
75{
76 if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) {
77 return -1;
78 }
79
80 return 0;
81}
82
83static int pwr_mcusys_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
84{
85 if (!IS_MCUSYS_OFF_STATE(state)) {
86 goto mt_pwr_mcusysoff_break;
87 }
88
89 if (mcdi_try_init() != 0) { /* not ready to process mcusys-off */
90 goto mt_pwr_mcusysoff_break;
91 }
92
93 return 0;
94
95mt_pwr_mcusysoff_break:
96
97 plat_mt_lp_cpu_rc = -1;
98
99 return -1;
100}
101
102static const struct mt_lpm_tz plat_pm = {
103 .pwr_prompt = pwr_state_prompt,
104 .pwr_reflect = pwr_state_reflect,
105 .pwr_cpu_on = pwr_cpu_pwron,
106 .pwr_cpu_dwn = pwr_cpu_pwrdwn,
107 .pwr_cluster_on = pwr_cluster_pwron,
108 .pwr_cluster_dwn = pwr_cluster_pwrdwn,
109 .pwr_mcusys_dwn = pwr_mcusys_pwrdwn,
110 .pwr_mcusys_on = pwr_mcusys_pwron,
111 .pwr_mcusys_on_finished = pwr_mcusys_pwron_finished
112};
113
114const struct mt_lpm_tz *mt_plat_cpu_pm_init(void)
115{
116 mtk_cpc_init();
117
118 if (mcdi_try_init() == 0) {
119 INFO("MCDI init done.\n");
120 }
121
122 return &plat_pm;
123}