1 /* 2 * Copyright (c) 2022, MediaTek Inc. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 9 #include <arch_helpers.h> 10 #include <common/debug.h> 11 #include <drivers/delay_timer.h> 12 #include <plat/common/platform.h> 13 14 #include <lib/pm/mtk_pm.h> 15 #include <mcucfg.h> 16 #include "mt_cpu_pm.h" 17 #include "mt_smp.h" 18 19 static inline int is_core_power_status_on(unsigned int cpuid) 20 { 21 return !!(mmio_read_32(CPU_PWR_STATUS) & BIT(cpuid)); 22 } 23 24 void mt_smp_core_init_arch(unsigned int cluster, unsigned int cpu, int arm64, 25 struct cpu_pwr_ctrl *pwr_ctrl) 26 { 27 CPU_PM_ASSERT(cluster == 0); 28 CPU_PM_ASSERT(pwr_ctrl != NULL); 29 30 /* aa64naa32 in bits[16:23] */ 31 if (arm64 != 0) { 32 mmio_setbits_32(pwr_ctrl->arch_addr, 1 << (16 + cpu)); 33 } else { 34 mmio_clrbits_32(pwr_ctrl->arch_addr, 1 << (16 + cpu)); 35 } 36 } 37 38 void mt_smp_core_bootup_address_set(struct cpu_pwr_ctrl *pwr_ctrl, uintptr_t entry) 39 { 40 CPU_PM_ASSERT(pwr_ctrl != NULL); 41 42 /* Set bootup address */ 43 mmio_write_32(pwr_ctrl->rvbaraddr_l, entry); 44 } 45 46 int mt_smp_power_core_on(unsigned int cpu_id, struct cpu_pwr_ctrl *pwr_ctrl) 47 { 48 uint32_t pwpr_reg; 49 unsigned int val = is_core_power_status_on(cpu_id); 50 51 CPU_PM_ASSERT(pwr_ctrl); 52 53 #ifdef CPU_PM_SPM_CORE_POWERON 54 pwpr_reg = pwr_ctrl->pwpr_intermediate; 55 #else 56 pwpr_reg = pwr_ctrl->pwpr; 57 #endif 58 59 mmio_clrbits_32(pwpr_reg, RESETPWRON_CONFIG); 60 61 if (val == 0) { 62 /* 63 * Set to 0 after BIG VPROC bulk powered on (configure in MCUPM) and 64 * before big core power-on sequence. 65 */ 66 if (cpu_id >= PLAT_CPU_PM_B_BUCK_ISO_ID) { 67 mmio_write_32(DREQ20_BIG_VPROC_ISO, 0); 68 } 69 70 #ifdef CPU_PM_SPM_CORE_POWERON 71 mmio_setbits_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG, 72 SSPM_ALL_PWR_CTRL_EN); 73 #endif 74 75 mmio_setbits_32(pwr_ctrl->pwpr, PWR_RST_B); 76 dsbsy(); 77 78 /* Set mp0_spmc_pwr_on_cpuX = 1 */ 79 mmio_setbits_32(pwpr_reg, PWR_ON); 80 81 val = 0; 82 while (is_core_power_status_on(cpu_id) == 0) { 83 DO_SMP_CORE_ON_WAIT_TIMEOUT(val); 84 mmio_clrbits_32(pwpr_reg, PWR_ON); 85 mmio_setbits_32(pwpr_reg, PWR_ON); 86 } 87 } else { 88 INFO("[%s:%d] - core_%u haven been power on\n", __func__, __LINE__, cpu_id); 89 } 90 91 return MTK_CPUPM_E_OK; 92 } 93 94 int mt_smp_power_core_off(struct cpu_pwr_ctrl *pwr_ctrl) 95 { 96 /* Set mp0_spmc_pwr_on_cpuX = 1 */ 97 #ifdef CPU_PM_SPM_CORE_POWERON 98 mmio_clrbits_32(pwr_ctrl->pwpr_intermediate, PWR_ON); 99 #else 100 mmio_clrbits_32(pwr_ctrl->pwpr, PWR_ON); 101 #endif 102 return MTK_CPUPM_E_OK; 103 } 104 105 void mt_smp_init(void) 106 { 107 /* INFO=SPMC_INIT: clear resetpwron of mcusys/cluster/core0 */ 108 #ifdef CPU_PM_SPM_CORE_POWERON 109 mmio_write_32(SPM_POWERON_CONFIG_EN, PROJECT_CODE | BCLK_CG_EN); 110 mmio_clrbits_32(SPM_VLP_MCUSYS_PWR_CON, RESETPWRON_CONFIG); 111 mmio_clrbits_32(SPM_VLP_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG); 112 #else 113 mmio_clrbits_32(SPM_MCUSYS_PWR_CON, RESETPWRON_CONFIG); 114 mmio_clrbits_32(SPM_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG); 115 #endif 116 } 117