blob: 83c8d4cdca3fca1ee2014c062ccb6f7c6c29ab03 [file] [log] [blame]
developer1033ea12019-04-10 21:09:26 +08001/*
developera21d47e2019-05-02 19:29:25 +08002 * Copyright (c) 2019, MediaTek Inc. All rights reserved.
developer1033ea12019-04-10 21:09:26 +08003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7/* common headers */
8#include <arch_helpers.h>
9#include <assert.h>
10#include <common/debug.h>
11#include <lib/mmio.h>
12#include <lib/psci/psci.h>
13#include <errno.h>
14
15/* mediatek platform specific headers */
16#include <platform_def.h>
17#include <scu.h>
developera21d47e2019-05-02 19:29:25 +080018#include <mt_gic_v3.h>
developer1033ea12019-04-10 21:09:26 +080019#include <mtk_plat_common.h>
developer043c9332019-05-03 17:02:46 +080020#include <mtgpio.h>
developera21d47e2019-05-02 19:29:25 +080021#include <mtspmc.h>
developera21d47e2019-05-02 19:29:25 +080022#include <plat_dcm.h>
23#include <plat_debug.h>
developer043c9332019-05-03 17:02:46 +080024#include <plat_params.h>
developer1033ea12019-04-10 21:09:26 +080025#include <plat_private.h>
developer043c9332019-05-03 17:02:46 +080026#include <power_tracer.h>
developer6f37fd22019-05-02 20:02:05 +080027#include <pmic.h>
28#include <rtc.h>
developer1033ea12019-04-10 21:09:26 +080029
developera21d47e2019-05-02 19:29:25 +080030#define MTK_LOCAL_STATE_OFF 2
31
32static uintptr_t secure_entrypoint;
33
34static void mp1_L2_desel_config(void)
35{
36 mmio_write_64(MCUCFG_BASE + 0x2200, 0x2092c820);
37
38 dsb();
39}
40
41static int plat_mtk_power_domain_on(unsigned long mpidr)
42{
43 int cpu = MPIDR_AFFLVL0_VAL(mpidr);
44 int cluster = MPIDR_AFFLVL1_VAL(mpidr);
45
46 INFO("%s():%d: mpidr: %lx, c.c: %d.%d\n",
47 __func__, __LINE__, mpidr, cluster, cpu);
48
49 /* power on cluster */
50 if (!spm_get_cluster_powerstate(cluster)) {
51 spm_poweron_cluster(cluster);
52 if (cluster == 1) {
53 l2c_parity_check_setup();
54 circular_buffer_setup();
55 mp1_L2_desel_config();
56 mt_gic_sync_dcm_disable();
57 }
58 }
59
60 /* init cpu reset arch as AARCH64 */
61 mcucfg_init_archstate(cluster, cpu, 1);
62 mcucfg_set_bootaddr(cluster, cpu, secure_entrypoint);
63
64 spm_poweron_cpu(cluster, cpu);
65
66 return PSCI_E_SUCCESS;
67}
68
69static void plat_mtk_power_domain_off(const psci_power_state_t *state)
70{
71 uint64_t mpidr = read_mpidr();
72 int cpu = MPIDR_AFFLVL0_VAL(mpidr);
73 int cluster = MPIDR_AFFLVL1_VAL(mpidr);
74
75 INFO("%s():%d: c.c: %d.%d\n", __func__, __LINE__, cluster, cpu);
76
77 /* Prevent interrupts from spuriously waking up this cpu */
78 mt_gic_cpuif_disable();
79
80 spm_enable_cpu_auto_off(cluster, cpu);
81
82 if (state->pwr_domain_state[MPIDR_AFFLVL1] == MTK_LOCAL_STATE_OFF) {
83 if (cluster == 1)
84 mt_gic_sync_dcm_enable();
85
86 plat_mtk_cci_disable();
87 spm_enable_cluster_auto_off(cluster);
88 }
89
90 spm_set_cpu_power_off(cluster, cpu);
91}
92
93static void plat_mtk_power_domain_on_finish(const psci_power_state_t *state)
94{
95 uint64_t mpidr = read_mpidr();
96 int cpu = MPIDR_AFFLVL0_VAL(mpidr);
97 int cluster = MPIDR_AFFLVL1_VAL(mpidr);
98
99 INFO("%s():%d: c.c: %d.%d\n", __func__, __LINE__, cluster, cpu);
100
101 assert(state->pwr_domain_state[MPIDR_AFFLVL0] == MTK_LOCAL_STATE_OFF);
102
103 if (state->pwr_domain_state[MPIDR_AFFLVL1] == MTK_LOCAL_STATE_OFF) {
104 enable_scu(mpidr);
105
106 /* Enable coherency if this cluster was off */
107 plat_mtk_cci_enable();
108 /* Enable big core dcm if this cluster was on */
109 plat_dcm_restore_cluster_on(mpidr);
110 /* Enable rgu dcm if this cluster was off */
111 plat_dcm_rgu_enable();
112 }
113
114 spm_disable_cpu_auto_off(cluster, cpu);
115
116 /* Enable the gic cpu interface */
117 mt_gic_pcpu_init();
118 mt_gic_cpuif_enable();
119}
120
developer1033ea12019-04-10 21:09:26 +0800121/*******************************************************************************
developer6f37fd22019-05-02 20:02:05 +0800122 * MTK handlers to shutdown/reboot the system
123 ******************************************************************************/
124static void __dead2 plat_mtk_system_off(void)
125{
126 INFO("MTK System Off\n");
127
128 rtc_power_off_sequence();
129 wk_pmic_enable_sdn_delay();
130 pmic_power_off();
131
132 wfi();
133 ERROR("MTK System Off: operation not handled.\n");
134 panic();
135}
136
developer043c9332019-05-03 17:02:46 +0800137static void __dead2 plat_mtk_system_reset(void)
138{
139 struct bl_aux_gpio_info *gpio_reset = plat_get_mtk_gpio_reset();
140
141 INFO("MTK System Reset\n");
142
143 mt_set_gpio_out(gpio_reset->index, gpio_reset->polarity);
144
145 wfi();
146 ERROR("MTK System Reset: operation not handled.\n");
147 panic();
148}
149
developer6f37fd22019-05-02 20:02:05 +0800150/*******************************************************************************
developer1033ea12019-04-10 21:09:26 +0800151 * MTK_platform handler called when an affinity instance is about to be turned
152 * on. The level and mpidr determine the affinity instance.
153 ******************************************************************************/
developer1033ea12019-04-10 21:09:26 +0800154static const plat_psci_ops_t plat_plat_pm_ops = {
155 .cpu_standby = NULL,
developera21d47e2019-05-02 19:29:25 +0800156 .pwr_domain_on = plat_mtk_power_domain_on,
157 .pwr_domain_on_finish = plat_mtk_power_domain_on_finish,
158 .pwr_domain_off = plat_mtk_power_domain_off,
developer1033ea12019-04-10 21:09:26 +0800159 .pwr_domain_suspend = NULL,
160 .pwr_domain_suspend_finish = NULL,
developer6f37fd22019-05-02 20:02:05 +0800161 .system_off = plat_mtk_system_off,
developer043c9332019-05-03 17:02:46 +0800162 .system_reset = plat_mtk_system_reset,
developer1033ea12019-04-10 21:09:26 +0800163 .validate_power_state = NULL,
164 .get_sys_suspend_power_state = NULL,
165};
166
167int plat_setup_psci_ops(uintptr_t sec_entrypoint,
168 const plat_psci_ops_t **psci_ops)
169{
170 *psci_ops = &plat_plat_pm_ops;
171 secure_entrypoint = sec_entrypoint;
172 return 0;
173}