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