summaryrefslogtreecommitdiffstats
path: root/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_smp.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_smp.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_smp.c b/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_smp.c
new file mode 100644
index 0000000..a1d9c31
--- /dev/null
+++ b/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_smp.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <plat/common/platform.h>
+
+#include <lib/pm/mtk_pm.h>
+#include <mcucfg.h>
+#include "mt_cpu_pm.h"
+#include "mt_smp.h"
+
+static inline int is_core_power_status_on(unsigned int cpuid)
+{
+ return !!(mmio_read_32(CPU_PWR_STATUS) & BIT(cpuid));
+}
+
+void mt_smp_core_init_arch(unsigned int cluster, unsigned int cpu, int arm64,
+ struct cpu_pwr_ctrl *pwr_ctrl)
+{
+ CPU_PM_ASSERT(cluster == 0);
+ CPU_PM_ASSERT(pwr_ctrl != NULL);
+
+ /* aa64naa32 in bits[16:23] */
+ if (arm64 != 0) {
+ mmio_setbits_32(pwr_ctrl->arch_addr, 1 << (16 + cpu));
+ } else {
+ mmio_clrbits_32(pwr_ctrl->arch_addr, 1 << (16 + cpu));
+ }
+}
+
+void mt_smp_core_bootup_address_set(struct cpu_pwr_ctrl *pwr_ctrl, uintptr_t entry)
+{
+ CPU_PM_ASSERT(pwr_ctrl != NULL);
+
+ /* Set bootup address */
+ mmio_write_32(pwr_ctrl->rvbaraddr_l, entry);
+}
+
+int mt_smp_power_core_on(unsigned int cpu_id, struct cpu_pwr_ctrl *pwr_ctrl)
+{
+ unsigned int val = is_core_power_status_on(cpu_id);
+
+ CPU_PM_ASSERT(pwr_ctrl);
+
+ mmio_clrbits_32(pwr_ctrl->pwpr, RESETPWRON_CONFIG);
+ if (val == 0) {
+ /*
+ * Set to 0 after BIG VPROC bulk powered on (configure in MCUPM) and
+ * before big core power-on sequence.
+ */
+ if (cpu_id >= PLAT_CPU_PM_B_BUCK_ISO_ID) {
+ mmio_write_32(DREQ20_BIG_VPROC_ISO, 0);
+ }
+
+ mmio_setbits_32(pwr_ctrl->pwpr, PWR_RST_B);
+ dsbsy();
+
+ /* set mp0_spmc_pwr_on_cpuX = 1 */
+ mmio_setbits_32(pwr_ctrl->pwpr, PWR_ON);
+
+ val = 0;
+ while (is_core_power_status_on(cpu_id) == 0) {
+ DO_SMP_CORE_ON_WAIT_TIMEOUT(val);
+ mmio_clrbits_32(pwr_ctrl->pwpr, PWR_ON);
+ mmio_setbits_32(pwr_ctrl->pwpr, PWR_ON);
+ }
+ } else {
+ INFO("[%s:%d] - core_%u haven been power on\n", __func__, __LINE__, cpu_id);
+ }
+
+ return MTK_CPUPM_E_OK;
+}
+
+int mt_smp_power_core_off(struct cpu_pwr_ctrl *pwr_ctrl)
+{
+ /* set mp0_spmc_pwr_on_cpuX = 1 */
+ mmio_clrbits_32(pwr_ctrl->pwpr, PWR_ON);
+ return MTK_CPUPM_E_OK;
+}
+
+void mt_smp_init(void)
+{
+ /* clear RESETPWRON_CONFIG of mcusys/cluster/core0 */
+ mmio_clrbits_32(SPM_MCUSYS_PWR_CON, RESETPWRON_CONFIG);
+ mmio_clrbits_32(SPM_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG);
+}