1 /* 2 * Copyright (c) 2025, 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_ppu.h" 18 #include "mt_smp.h" 19 20 #define is_core_power_status_on(_pwr_ctrl)\ 21 (!!((mmio_read_32(_pwr_ctrl->pwr.ppu_pwsr)) & (PPU_PWSR_STATE_ON))) 22 23 #ifndef CPU_PM_CORE_ARCH64_ONLY 24 void mt_smp_core_init_arch(int cluster, 25 int cpu, 26 int arm64, 27 struct cpu_pwr_ctrl *pwr_ctrl) 28 { 29 CPU_PM_ASSERT(cluster == 0); 30 CPU_PM_ASSERT(pwr_ctrl); 31 32 /* aa64naa32 in bits[16:23] */ 33 if (arm64) 34 mmio_setbits_32(pwr_ctrl->arch_addr, 35 BIT(AA64NAA32_FLAG_START_BIT + cpu)); 36 else 37 mmio_clrbits_32(pwr_ctrl->arch_addr, 38 BIT(AA64NAA32_FLAG_START_BIT + cpu)); 39 } 40 #endif /* CPU_PM_CORE_ARCH64_ONLY */ 41 42 void mt_smp_core_bootup_address_set(int cluster, 43 int cpu, 44 struct cpu_pwr_ctrl *pwr_ctrl, 45 uintptr_t entry) 46 { 47 CPU_PM_ASSERT(pwr_ctrl); 48 49 /* Set bootup address */ 50 mmio_write_32(pwr_ctrl->rvbaraddr_l, entry); 51 mmio_write_32(pwr_ctrl->rvbaraddr_h, 0); 52 } 53 54 int mt_smp_power_core_on(unsigned int cpu_id, struct cpu_pwr_ctrl *pwr_ctrl) 55 { 56 unsigned int val = 0; 57 58 CPU_PM_ASSERT(pwr_ctrl); 59 60 mt_smp_ppu_pwr_set(&pwr_ctrl->pwr, PPU_PWPR_DYNAMIC_MODE, PPU_PWPR_OFF); 61 val = is_core_power_status_on(pwr_ctrl); 62 if (!val) { 63 mmio_clrbits_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG, 64 GIC_WAKEUP_IGNORE(cpu_id)); 65 mmio_setbits_32(SPM_EXT_INT_WAKEUP_REQ_SET, BIT(cpu_id)); 66 67 mmio_clrbits_32(SPMC_CONTROL_CONFIG, 68 SPMC_CPU_RESET_PWRON_CONFIG << (cpu_id)); 69 dsbsy(); 70 isb(); 71 72 while (!is_core_power_status_on(pwr_ctrl)) 73 DO_SMP_CORE_ON_WAIT_TIMEOUT(cpu_id, val); 74 mmio_setbits_32(SPM_EXT_INT_WAKEUP_REQ_CLR, BIT(cpu_id)); 75 } else { 76 mmio_clrbits_32(SPMC_CONTROL_CONFIG, 77 SPMC_CPU_RESET_PWRON_CONFIG << (cpu_id)); 78 INFO("[%s:%d] - core_%u have been power on\n", 79 __func__, __LINE__, cpu_id); 80 } 81 82 return MTK_CPUPM_E_OK; 83 } 84 85 int mt_smp_power_core_off(unsigned int cpu_id, struct cpu_pwr_ctrl *pwr_ctrl) 86 { 87 mmio_setbits_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG, 88 GIC_WAKEUP_IGNORE(cpu_id)); 89 return MTK_CPUPM_E_OK; 90 } 91 92 void mt_smp_init(void) 93 { 94 mmio_write_32(SPM_POWERON_CONFIG_EN, PROJECT_CODE | BCLK_CG_EN); 95 96 /* INFO=SPMC_INIT: clear resetpwron of mcusys/cluster/core0 */ 97 mmio_clrbits_32(SPMC_CONTROL_CONFIG, SPMC_MCUSYS_RESET_PWRON_CONFIG); 98 mmio_clrbits_32(SPMC_CONTROL_CONFIG, SPMC_CPUTOP_RESET_PWRON_CONFIG); 99 100 /* Switch DSU ISO/CKDIS control from PCSM to PPU */ 101 mmio_setbits_32(CPC_FCM_SPMC_SW_CFG2, 102 (CPUSYS_PPU_CLK_EN_CTRL | CPUSYS_PPU_ISO_CTRL)); 103 104 #ifdef SPM_CPU_BUCK_ISO_CON 105 /* Make sure that buck iso have been released before power on */ 106 mmio_write_32(SPM_CPU_BUCK_ISO_CON, SPM_CPU_BUCK_ISO_DEFAUT); 107 #endif /* SPM_CPU_BUCK_ISO_CON */ 108 } 109