1 /* 2 * Copyright (c) 2020, 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 19 DEFINE_SYSREG_RW_FUNCS(dbgprcr_el1); 20 21 static int plat_mt_lp_cpu_rc; 22 23 static int pwr_state_prompt(unsigned int cpu, const psci_power_state_t *state) 24 { 25 return 0; 26 } 27 28 static 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 39 static int pwr_cpu_pwron(unsigned int cpu, const psci_power_state_t *state) 40 { 41 return 0; 42 } 43 44 static 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 52 static int pwr_cluster_pwron(unsigned int cpu, const psci_power_state_t *state) 53 { 54 return 0; 55 } 56 57 static int pwr_cluster_pwrdwn(unsigned int cpu, const psci_power_state_t *state) 58 { 59 return 0; 60 } 61 62 static 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 73 static 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 83 static 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 95 mt_pwr_mcusysoff_break: 96 97 plat_mt_lp_cpu_rc = -1; 98 99 return -1; 100 } 101 102 static 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 114 const 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 } 124