14fe7e6a8SEdward-JW Yang /*
24fe7e6a8SEdward-JW Yang * Copyright (c) 2022, MediaTek Inc. All rights reserved.
34fe7e6a8SEdward-JW Yang *
44fe7e6a8SEdward-JW Yang * SPDX-License-Identifier: BSD-3-Clause
54fe7e6a8SEdward-JW Yang */
64fe7e6a8SEdward-JW Yang
74fe7e6a8SEdward-JW Yang #include <assert.h>
84fe7e6a8SEdward-JW Yang
94fe7e6a8SEdward-JW Yang #include <arch_helpers.h>
104fe7e6a8SEdward-JW Yang #include <common/debug.h>
114fe7e6a8SEdward-JW Yang #include <drivers/delay_timer.h>
124fe7e6a8SEdward-JW Yang #include <plat/common/platform.h>
134fe7e6a8SEdward-JW Yang
144fe7e6a8SEdward-JW Yang #include <lib/pm/mtk_pm.h>
154fe7e6a8SEdward-JW Yang #include <mcucfg.h>
164fe7e6a8SEdward-JW Yang #include "mt_cpu_pm.h"
174fe7e6a8SEdward-JW Yang #include "mt_smp.h"
184fe7e6a8SEdward-JW Yang
is_core_power_status_on(unsigned int cpuid)194fe7e6a8SEdward-JW Yang static inline int is_core_power_status_on(unsigned int cpuid)
204fe7e6a8SEdward-JW Yang {
214fe7e6a8SEdward-JW Yang return !!(mmio_read_32(CPU_PWR_STATUS) & BIT(cpuid));
224fe7e6a8SEdward-JW Yang }
234fe7e6a8SEdward-JW Yang
mt_smp_core_init_arch(unsigned int cluster,unsigned int cpu,int arm64,struct cpu_pwr_ctrl * pwr_ctrl)244fe7e6a8SEdward-JW Yang void mt_smp_core_init_arch(unsigned int cluster, unsigned int cpu, int arm64,
254fe7e6a8SEdward-JW Yang struct cpu_pwr_ctrl *pwr_ctrl)
264fe7e6a8SEdward-JW Yang {
274fe7e6a8SEdward-JW Yang CPU_PM_ASSERT(cluster == 0);
284fe7e6a8SEdward-JW Yang CPU_PM_ASSERT(pwr_ctrl != NULL);
294fe7e6a8SEdward-JW Yang
304fe7e6a8SEdward-JW Yang /* aa64naa32 in bits[16:23] */
314fe7e6a8SEdward-JW Yang if (arm64 != 0) {
324fe7e6a8SEdward-JW Yang mmio_setbits_32(pwr_ctrl->arch_addr, 1 << (16 + cpu));
334fe7e6a8SEdward-JW Yang } else {
344fe7e6a8SEdward-JW Yang mmio_clrbits_32(pwr_ctrl->arch_addr, 1 << (16 + cpu));
354fe7e6a8SEdward-JW Yang }
364fe7e6a8SEdward-JW Yang }
374fe7e6a8SEdward-JW Yang
mt_smp_core_bootup_address_set(struct cpu_pwr_ctrl * pwr_ctrl,uintptr_t entry)384fe7e6a8SEdward-JW Yang void mt_smp_core_bootup_address_set(struct cpu_pwr_ctrl *pwr_ctrl, uintptr_t entry)
394fe7e6a8SEdward-JW Yang {
404fe7e6a8SEdward-JW Yang CPU_PM_ASSERT(pwr_ctrl != NULL);
414fe7e6a8SEdward-JW Yang
424fe7e6a8SEdward-JW Yang /* Set bootup address */
434fe7e6a8SEdward-JW Yang mmio_write_32(pwr_ctrl->rvbaraddr_l, entry);
444fe7e6a8SEdward-JW Yang }
454fe7e6a8SEdward-JW Yang
mt_smp_power_core_on(unsigned int cpu_id,struct cpu_pwr_ctrl * pwr_ctrl)464fe7e6a8SEdward-JW Yang int mt_smp_power_core_on(unsigned int cpu_id, struct cpu_pwr_ctrl *pwr_ctrl)
474fe7e6a8SEdward-JW Yang {
48*b8d63a7aSKai Liang uint32_t pwpr_reg;
494fe7e6a8SEdward-JW Yang unsigned int val = is_core_power_status_on(cpu_id);
504fe7e6a8SEdward-JW Yang
514fe7e6a8SEdward-JW Yang CPU_PM_ASSERT(pwr_ctrl);
524fe7e6a8SEdward-JW Yang
53*b8d63a7aSKai Liang #ifdef CPU_PM_SPM_CORE_POWERON
54*b8d63a7aSKai Liang pwpr_reg = pwr_ctrl->pwpr_intermediate;
55*b8d63a7aSKai Liang #else
56*b8d63a7aSKai Liang pwpr_reg = pwr_ctrl->pwpr;
57*b8d63a7aSKai Liang #endif
58*b8d63a7aSKai Liang
59*b8d63a7aSKai Liang mmio_clrbits_32(pwpr_reg, RESETPWRON_CONFIG);
60*b8d63a7aSKai Liang
614fe7e6a8SEdward-JW Yang if (val == 0) {
624fe7e6a8SEdward-JW Yang /*
634fe7e6a8SEdward-JW Yang * Set to 0 after BIG VPROC bulk powered on (configure in MCUPM) and
644fe7e6a8SEdward-JW Yang * before big core power-on sequence.
654fe7e6a8SEdward-JW Yang */
664fe7e6a8SEdward-JW Yang if (cpu_id >= PLAT_CPU_PM_B_BUCK_ISO_ID) {
674fe7e6a8SEdward-JW Yang mmio_write_32(DREQ20_BIG_VPROC_ISO, 0);
684fe7e6a8SEdward-JW Yang }
694fe7e6a8SEdward-JW Yang
70*b8d63a7aSKai Liang #ifdef CPU_PM_SPM_CORE_POWERON
71*b8d63a7aSKai Liang mmio_setbits_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG,
72*b8d63a7aSKai Liang SSPM_ALL_PWR_CTRL_EN);
73*b8d63a7aSKai Liang #endif
74*b8d63a7aSKai Liang
754fe7e6a8SEdward-JW Yang mmio_setbits_32(pwr_ctrl->pwpr, PWR_RST_B);
764fe7e6a8SEdward-JW Yang dsbsy();
774fe7e6a8SEdward-JW Yang
78*b8d63a7aSKai Liang /* Set mp0_spmc_pwr_on_cpuX = 1 */
79*b8d63a7aSKai Liang mmio_setbits_32(pwpr_reg, PWR_ON);
804fe7e6a8SEdward-JW Yang
814fe7e6a8SEdward-JW Yang val = 0;
824fe7e6a8SEdward-JW Yang while (is_core_power_status_on(cpu_id) == 0) {
834fe7e6a8SEdward-JW Yang DO_SMP_CORE_ON_WAIT_TIMEOUT(val);
84*b8d63a7aSKai Liang mmio_clrbits_32(pwpr_reg, PWR_ON);
85*b8d63a7aSKai Liang mmio_setbits_32(pwpr_reg, PWR_ON);
864fe7e6a8SEdward-JW Yang }
874fe7e6a8SEdward-JW Yang } else {
884fe7e6a8SEdward-JW Yang INFO("[%s:%d] - core_%u haven been power on\n", __func__, __LINE__, cpu_id);
894fe7e6a8SEdward-JW Yang }
904fe7e6a8SEdward-JW Yang
914fe7e6a8SEdward-JW Yang return MTK_CPUPM_E_OK;
924fe7e6a8SEdward-JW Yang }
934fe7e6a8SEdward-JW Yang
mt_smp_power_core_off(struct cpu_pwr_ctrl * pwr_ctrl)944fe7e6a8SEdward-JW Yang int mt_smp_power_core_off(struct cpu_pwr_ctrl *pwr_ctrl)
954fe7e6a8SEdward-JW Yang {
96*b8d63a7aSKai Liang /* Set mp0_spmc_pwr_on_cpuX = 1 */
97*b8d63a7aSKai Liang #ifdef CPU_PM_SPM_CORE_POWERON
98*b8d63a7aSKai Liang mmio_clrbits_32(pwr_ctrl->pwpr_intermediate, PWR_ON);
99*b8d63a7aSKai Liang #else
1004fe7e6a8SEdward-JW Yang mmio_clrbits_32(pwr_ctrl->pwpr, PWR_ON);
101*b8d63a7aSKai Liang #endif
1024fe7e6a8SEdward-JW Yang return MTK_CPUPM_E_OK;
1034fe7e6a8SEdward-JW Yang }
1044fe7e6a8SEdward-JW Yang
mt_smp_init(void)1054fe7e6a8SEdward-JW Yang void mt_smp_init(void)
1064fe7e6a8SEdward-JW Yang {
107*b8d63a7aSKai Liang /* INFO=SPMC_INIT: clear resetpwron of mcusys/cluster/core0 */
108*b8d63a7aSKai Liang #ifdef CPU_PM_SPM_CORE_POWERON
109*b8d63a7aSKai Liang mmio_write_32(SPM_POWERON_CONFIG_EN, PROJECT_CODE | BCLK_CG_EN);
110*b8d63a7aSKai Liang mmio_clrbits_32(SPM_VLP_MCUSYS_PWR_CON, RESETPWRON_CONFIG);
111*b8d63a7aSKai Liang mmio_clrbits_32(SPM_VLP_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG);
112*b8d63a7aSKai Liang #else
1134fe7e6a8SEdward-JW Yang mmio_clrbits_32(SPM_MCUSYS_PWR_CON, RESETPWRON_CONFIG);
1144fe7e6a8SEdward-JW Yang mmio_clrbits_32(SPM_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG);
115*b8d63a7aSKai Liang #endif
1164fe7e6a8SEdward-JW Yang }
117