xref: /rk3399_ARM-atf/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_smp.c (revision 3fb300a9648c4aafc13eb48d545d2d14908cbad3)
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 
is_core_power_status_on(unsigned int cpuid)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 
mt_smp_core_init_arch(unsigned int cluster,unsigned int cpu,int arm64,struct cpu_pwr_ctrl * pwr_ctrl)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 
mt_smp_core_bootup_address_set(struct cpu_pwr_ctrl * pwr_ctrl,uintptr_t entry)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 
mt_smp_power_core_on(unsigned int cpu_id,struct cpu_pwr_ctrl * pwr_ctrl)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 
mt_smp_power_core_off(struct cpu_pwr_ctrl * pwr_ctrl)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 
mt_smp_init(void)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