Commit 7fa35d06 authored by Manish Pandey's avatar Manish Pandey Committed by TrustedFirmware Code Review
Browse files

Merge changes Ib8502f9b,I388fd231,I7bd37912,I3a186ed7 into integration

* changes:
  feat(plat/mediatek/mt8195): add SPM suspend driver
  feat(plat/mediatek/mt8195): support MCUSYS off when system suspend
  feat(plat/mediatek/mt8195): add support for PTP3
  fix(plat/mediatek/mt8195): extend MMU region size
parents 05f47b77 859e346b
......@@ -13,10 +13,10 @@ const mmap_region_t plat_mmap[] = {
/* for TF text, RO, RW */
MAP_REGION_FLAT(MTK_DEV_RNG0_BASE, MTK_DEV_RNG0_SIZE,
MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(MTK_DEV_RNG1_BASE, MTK_DEV_RNG1_SIZE,
MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(MTK_DEV_RNG2_BASE, MTK_DEV_RNG2_SIZE,
MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(MTK_MCDI_SRAM_BASE, MTK_MCDI_SRAM_MAP_SIZE,
MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(DP_SEC_BASE, DP_SEC_SIZE,
MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(eDP_SEC_BASE, eDP_SEC_SIZE,
......
......@@ -17,6 +17,7 @@
/* Platform Includes */
#include <mt_gic_v3.h>
#include <mt_spm.h>
#include <mt_timer.h>
#include <mtgpio.h>
#include <plat_params.h>
......@@ -90,6 +91,7 @@ void bl31_platform_setup(void)
mt_gpio_init();
mt_systimer_init();
generic_delay_timer_init();
spm_boot_init();
}
/*******************************************************************************
......
/*
* Copyright (c) 2020, MediaTek Inc. All rights reserved.
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
......@@ -12,6 +12,8 @@
#include <lib/spinlock.h>
#include <mt_cpu_pm_cpc.h>
#include <mt_lp_irqremain.h>
#include <mt_lp_rm.h>
#include <mt_mcdi.h>
#include <plat_mtk_lpm.h>
#include <plat_pm.h>
......@@ -73,25 +75,48 @@ static int pwr_mcusys_pwron(unsigned int cpu, const psci_power_state_t *state)
static int pwr_mcusys_pwron_finished(unsigned int cpu,
const psci_power_state_t *state)
{
int state_id = state->pwr_domain_state[MTK_AFFLVL_MCUSYS];
if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) {
return -1;
}
mt_lp_rm_reset_constraint(plat_mt_lp_cpu_rc, cpu, state_id);
mt_lp_irqremain_release();
return 0;
}
static int pwr_mcusys_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
{
int state_id = state->pwr_domain_state[MTK_AFFLVL_MCUSYS];
if (!IS_MCUSYS_OFF_STATE(state)) {
goto mt_pwr_mcusysoff_break;
}
if (mcdi_try_init() != 0) { /* not ready to process mcusys-off */
if (mcdi_try_init() != 0) {
goto mt_pwr_mcusysoff_break;
}
if (mtk_cpc_mcusys_off_prepare() != CPC_SUCCESS) {
goto mt_pwr_mcusysoff_break;
}
plat_mt_lp_cpu_rc =
mt_lp_rm_find_and_run_constraint(0, cpu, state_id, NULL);
if (plat_mt_lp_cpu_rc < 0) {
goto mt_pwr_mcusysoff_reflect;
}
mt_lp_irqremain_aquire();
return 0;
mt_pwr_mcusysoff_reflect:
mtk_cpc_mcusys_off_reflect();
mt_pwr_mcusysoff_break:
plat_mt_lp_cpu_rc = -1;
......@@ -119,5 +144,7 @@ const struct mt_lpm_tz *mt_plat_cpu_pm_init(void)
INFO("MCDI init done.\n");
}
mt_lp_irqremain_init();
return &plat_pm;
}
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <mt_lp_rm.h>
#include <mt_lp_irqremain.h>
#include <mtk_cirq.h>
#include <plat_mtk_lpm.h>
#define KEYPAD_IRQ_ID U(138)
#define KEYPAD_WAKESRC 0x4
static struct mt_irqremain remain_irqs;
int mt_lp_irqremain_submit(void)
{
if (remain_irqs.count == 0) {
return -1;
}
set_wakeup_sources(remain_irqs.irqs, remain_irqs.count);
mt_lp_rm_do_update(-1, PLAT_RC_UPDATE_REMAIN_IRQS, &remain_irqs);
return 0;
}
int mt_lp_irqremain_aquire(void)
{
if (remain_irqs.count == 0) {
return -1;
}
mt_cirq_sw_reset();
mt_cirq_clone_gic();
mt_cirq_enable();
return 0;
}
int mt_lp_irqremain_release(void)
{
if (remain_irqs.count == 0) {
return -1;
}
mt_cirq_flush();
mt_cirq_disable();
return 0;
}
void mt_lp_irqremain_init(void)
{
uint32_t idx;
remain_irqs.count = 0;
/*edge keypad*/
idx = remain_irqs.count;
remain_irqs.irqs[idx] = KEYPAD_IRQ_ID;
remain_irqs.wakeupsrc_cat[idx] = 0;
remain_irqs.wakeupsrc[idx] = KEYPAD_WAKESRC;
remain_irqs.count++;
mt_lp_irqremain_submit();
}
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MT_LP_IRQREMAIN_H
#define MT_LP_IRQREMAIN_H
extern int mt_lp_irqremain_submit(void);
extern int mt_lp_irqremain_aquire(void);
extern int mt_lp_irqremain_release(void);
extern void mt_lp_irqremain_init(void);
#endif /* MT_LP_IRQREMAIN_H */
/*
* Copyright (c) 2020, MediaTek Inc. All rights reserved.
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <cdefs.h>
#include <common/debug.h>
#include <lib/mmio.h>
#include <lib/utils_def.h>
......@@ -144,5 +145,7 @@ int mcdi_try_init(void)
mcdi_init_status = MCDI_INIT_DONE;
}
INFO("mcdi ready for mcusys-off-idle and system suspend\n");
return (mcdi_init_status == MCDI_INIT_DONE) ? 0 : mcdi_init_status;
}
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MTK_PTP3_COMMON_H
#define MTK_PTP3_COMMON_H
#include <lib/mmio.h>
#include <lib/utils_def.h>
/************************************************
* CPU info
************************************************/
#define NR_PTP3_CFG_CPU U(8)
#define PTP3_CFG_CPU_START_ID_L U(0)
#define PTP3_CFG_CPU_START_ID_B U(4)
#define PTP3_CFG_CPU_END_ID U(7)
#define NR_PTP3_CFG1_DATA U(2)
#define PTP3_CFG1_MASK 0x3000
#define NR_PTP3_CFG2_DATA U(5)
#define PTP3_CFG3_MASK1 0x1180
#define PTP3_CFG3_MASK2 0x35C0
#define PTP3_CFG3_MASK3 0x3DC0
/************************************************
* register read/write
************************************************/
#define ptp3_write(addr, val) mmio_write_32((uintptr_t)addr, val)
#define ptp3_clrsetbits(addr, clear, set) \
mmio_clrsetbits_32((uintptr_t)addr, clear, set)
/************************************************
* config enum
************************************************/
enum PTP3_CFG {
PTP3_CFG_ADDR,
PTP3_CFG_VALUE,
NR_PTP3_CFG,
};
/************************************
* prototype
************************************/
extern void ptp3_core_init(unsigned int core);
extern void ptp3_core_unInit(unsigned int core);
#endif /* MTK_PTP3_COMMON_H */
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved. \
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <mtk_ptp3_common.h>
#define PTP3_CORE_OFT(core) (0x800 * (core))
/************************************************
* Central control
************************************************/
static unsigned int ptp3_cfg1[NR_PTP3_CFG1_DATA][NR_PTP3_CFG] = {
{0x0C53A2A0, 0x1000},
{0x0C53A2A4, 0x1000}
};
static unsigned int ptp3_cfg2[NR_PTP3_CFG2_DATA][NR_PTP3_CFG] = {
{0x0C530404, 0x3A1000},
{0x0C530428, 0x13E0408},
{0x0C530434, 0xB22800},
{0x0C53043C, 0x750},
{0x0C530440, 0x0222c4cc}
};
static unsigned int ptp3_cfg3[NR_PTP3_CFG] = {0x0C530400, 0x2D80};
static unsigned int ptp3_cfg3_ext[NR_PTP3_CFG] = {0x0C530400, 0xC00};
static void ptp3_init(unsigned int core)
{
unsigned int i, addr, value;
if (core < PTP3_CFG_CPU_START_ID_B) {
ptp3_clrsetbits(ptp3_cfg1[0][PTP3_CFG_ADDR], PTP3_CFG1_MASK,
ptp3_cfg1[0][PTP3_CFG_VALUE]);
} else {
ptp3_clrsetbits(ptp3_cfg1[1][PTP3_CFG_ADDR], PTP3_CFG1_MASK,
ptp3_cfg1[1][PTP3_CFG_VALUE]);
}
if (core < PTP3_CFG_CPU_START_ID_B) {
for (i = 0; i < NR_PTP3_CFG2_DATA; i++) {
addr = ptp3_cfg2[i][PTP3_CFG_ADDR] +
PTP3_CORE_OFT(core);
value = ptp3_cfg2[i][PTP3_CFG_VALUE];
ptp3_write(addr, value);
}
} else {
for (i = 0; i < NR_PTP3_CFG2_DATA; i++) {
addr = ptp3_cfg2[i][PTP3_CFG_ADDR] +
PTP3_CORE_OFT(core);
if (i == 2) {
value = ptp3_cfg2[i][PTP3_CFG_VALUE] + 0x5E0;
} else {
value = ptp3_cfg2[i][PTP3_CFG_VALUE];
}
ptp3_write(addr, value);
}
}
if (core < PTP3_CFG_CPU_START_ID_B) {
addr = ptp3_cfg3[PTP3_CFG_ADDR] + PTP3_CORE_OFT(core);
value = ptp3_cfg3[PTP3_CFG_VALUE];
ptp3_write(addr, value & PTP3_CFG3_MASK1);
ptp3_write(addr, value & PTP3_CFG3_MASK2);
ptp3_write(addr, value & PTP3_CFG3_MASK3);
} else {
addr = ptp3_cfg3_ext[PTP3_CFG_ADDR] + PTP3_CORE_OFT(core);
value = ptp3_cfg3_ext[PTP3_CFG_VALUE];
ptp3_write(addr, value & PTP3_CFG3_MASK1);
ptp3_write(addr, value & PTP3_CFG3_MASK2);
ptp3_write(addr, value & PTP3_CFG3_MASK3);
}
}
void pdp_proc_ARM_write(unsigned int pdp_n)
{
unsigned long v = 0;
dsb();
__asm__ volatile ("mrs %0, S3_6_C15_C2_0" : "=r" (v));
v |= (UL(0x0) << 52);
v |= (UL(0x1) << 53);
v |= (UL(0x0) << 54);
v |= (UL(0x0) << 48);
v |= (UL(0x1) << 49);
__asm__ volatile ("msr S3_6_C15_C2_0, %0" : : "r" (v));
dsb();
}
void pdp_init(unsigned int pdp_cpu, unsigned int en)
{
if ((pdp_cpu >= PTP3_CFG_CPU_START_ID_B) &&
(pdp_cpu < NR_PTP3_CFG_CPU)) {
pdp_proc_ARM_write(pdp_cpu);
}
}
static void dt_proc_ARM_write(unsigned int dt_n)
{
unsigned long v = 0;
dsb();
__asm__ volatile ("mrs %0, S3_6_C15_C2_0" : "=r" (v));
v |= (UL(0x0) << 33);
v |= (UL(0x0) << 32);
__asm__ volatile ("msr S3_6_C15_C2_0, %0" : : "r" (v));
dsb();
}
void dt_init(unsigned int dt_cpu, unsigned int en)
{
if ((dt_cpu >= PTP3_CFG_CPU_START_ID_B) &&
(dt_cpu < NR_PTP3_CFG_CPU)) {
dt_proc_ARM_write(dt_cpu);
}
}
void ptp3_core_init(unsigned int core)
{
/* init for ptp3 */
ptp3_init(core);
/* init for pdp */
pdp_init(core, 1);
/* init for dt */
dt_init(core, 1);
}
void ptp3_core_unInit(unsigned int core)
{
/* TBD */
}
#
# Copyright (c) 2021, MediaTek Inc. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
# Enable or disable spm feature
MT_SPM_FEATURE_SUPPORT = yes
# Enable or disable cirq restore
MT_SPM_CIRQ_FEATURE_SUPPORT = yes
# sspm notifier support
MT_SPM_SSPM_NOTIFIER_SUPPORT = yes
CUR_SPM_FOLDER = ${MTK_PLAT_SOC}/drivers/spm
# spm common files
PLAT_SPM_SOURCE_FILES_COMMON += \
${CUR_SPM_FOLDER}/mt_spm.c \
${CUR_SPM_FOLDER}/mt_spm_conservation.c \
${CUR_SPM_FOLDER}/mt_spm_internal.c \
${CUR_SPM_FOLDER}/mt_spm_pmic_wrap.c
# spm platform dependcy files
PLAT_SPM_SOURCE_FILES += \
${CUR_SPM_FOLDER}/constraints/mt_spm_rc_bus26m.c \
${CUR_SPM_FOLDER}/constraints/mt_spm_rc_cpu_buck_ldo.c \
${CUR_SPM_FOLDER}/constraints/mt_spm_rc_dram.c \
${CUR_SPM_FOLDER}/constraints/mt_spm_rc_syspll.c \
${CUR_SPM_FOLDER}/mt_spm_cond.c \
${CUR_SPM_FOLDER}/mt_spm_suspend.c \
${CUR_SPM_FOLDER}/mt_spm_idle.c
ifeq (${MT_SPM_FEATURE_SUPPORT}, no)
PLAT_SPM_DEBUG_CFLAGS += -DATF_PLAT_SPM_UNSUPPORT
BL31_MT_LPM_PLAT_SPM_SOURCE_FILES += ${PLAT_SPM_SOURCE_FILES_COMMON}
else
BL31_MT_LPM_PLAT_SPM_SOURCE_FILES += \
${PLAT_SPM_SOURCE_FILES_COMMON} \
${PLAT_SPM_SOURCE_FILES}
endif
ifeq (${MT_SPM_CIRQ_FEATURE_SUPPORT}, no)
PLAT_SPM_DEBUG_CFLAGS += -DATF_PLAT_CIRQ_UNSUPPORT
endif
ifeq (${MT_SPM_SSPM_NOTIFIER_SUPPORT}, no)
PLAT_SPM_DEBUG_CFLAGS += -DATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
else
BL31_MT_LPM_PLAT_SPM_SOURCE_FILES += \
${CUR_SPM_FOLDER}/notifier/mt_spm_sspm_notifier.c
endif
$(info --------------------------------------)
$(info SPM build flags: ${PLAT_SPM_DEBUG_CFLAGS})
$(info SPM build files: ${BL31_MT_LPM_PLAT_SPM_SOURCE_FILES})
$(info --------------------------------------)
# Common makefile for platform.mk
PLAT_INCLUDES += \
${PLAT_SPM_DEBUG_CFLAGS} \
-I${CUR_SPM_FOLDER}/ \
-I${CUR_SPM_FOLDER}/constraints/ \
-I${CUR_SPM_FOLDER}/notifier/
PLAT_BL_COMMON_SOURCES += ${BL31_MT_LPM_PLAT_SPM_SOURCE_FILES}
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <common/debug.h>
#include <mt_lp_rm.h>
#include <mt_spm.h>
#include <mt_spm_cond.h>
#include <mt_spm_constraint.h>
#include <mt_spm_conservation.h>
#include <mt_spm_idle.h>
#include <mt_spm_internal.h>
#include <mt_spm_notifier.h>
#include <mt_spm_rc_internal.h>
#include <mt_spm_resource_req.h>
#include <mt_spm_reg.h>
#include <mt_spm_suspend.h>
#include <plat_pm.h>
#include <plat_mtk_lpm.h>
#ifndef ATF_PLAT_CIRQ_UNSUPPORT
#include <mt_gic_v3.h>
#include <mtk_cirq.h>
#endif
#define CONSTRAINT_BUS26M_ALLOW \
(MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF | \
MT_RM_CONSTRAINT_ALLOW_DRAM_S0 | \
MT_RM_CONSTRAINT_ALLOW_DRAM_S1 | \
MT_RM_CONSTRAINT_ALLOW_VCORE_LP | \
MT_RM_CONSTRAINT_ALLOW_LVTS_STATE | \
MT_RM_CONSTRAINT_ALLOW_BUS26M_OFF)
#define CONSTRAINT_BUS26M_PCM_FLAG \
(SPM_FLAG_DISABLE_INFRA_PDN | \
SPM_FLAG_DISABLE_VCORE_DVS | \
SPM_FLAG_DISABLE_VCORE_DFS | \
SPM_FLAG_SRAM_SLEEP_CTRL | \
SPM_FLAG_ENABLE_TIA_WORKAROUND | \
SPM_FLAG_ENABLE_LVTS_WORKAROUND | \
SPM_FLAG_KEEP_CSYSPWRACK_HIGH | \
SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP)
#define CONSTRAINT_BUS26M_PCM_FLAG1 0U
#define CONSTRAINT_BUS26M_RESOURCE_REQ 0U
static unsigned int bus26m_ext_opand;
static struct mt_irqremain *refer2remain_irq;
static struct mt_spm_cond_tables cond_bus26m = {
.name = "bus26m",
.table_cg = {
0xFFFFD408, /* MTCMOS1 */
0x2284C802, /* INFRA0 */
0x27AF8000, /* INFRA1 */
0x86040650, /* INFRA2 */
0x30038020, /* INFRA3 */
0x80000000, /* INFRA4 */
0x00080ABB, /* PERI0 */
0x00004000, /* VPPSYS0_0 */
0x08803000, /* VPPSYS0_1 */
0x00000000, /* VPPSYS0_2 */
0x80005555, /* VPPSYS1_0 */
0x00009008, /* VPPSYS1_1 */
0x60060000, /* VDOSYS0_0 */
0x00000000, /* VDOSYS0_1 */
0x201E01F8, /* VDOSYS1_0 */
0x00800000, /* VDOSYS1_1 */
0x00000000, /* VDOSYS1_2 */
0x00000080, /* I2C */
},
.table_pll = (PLL_BIT_UNIVPLL |
PLL_BIT_MFGPLL |
PLL_BIT_MSDCPLL |
PLL_BIT_TVDPLL |
PLL_BIT_MMPLL),
};
static struct mt_spm_cond_tables cond_bus26m_res = {
.table_cg = { 0U },
.table_pll = 0U,
};
static struct constraint_status status = {
.id = MT_RM_CONSTRAINT_ID_BUS26M,
.valid = (MT_SPM_RC_VALID_SW |
MT_SPM_RC_VALID_COND_LATCH),
.cond_block = 0U,
.enter_cnt = 0U,
.cond_res = &cond_bus26m_res,
};
/*
* Cirq will take the place of gic when gic is off.
* However, cirq cannot work if 26m clk is turned off when system idle/suspend.
* Therefore, we need to set irq pending for specific wakeup source.
*/
#ifdef ATF_PLAT_CIRQ_UNSUPPORT
#define do_irqs_delivery()
#else
static void mt_spm_irq_remain_dump(struct mt_irqremain *irqs,
unsigned int irq_index,
struct wake_status *wakeup)
{
INFO("[SPM] r12 = 0x%08x(0x%08x), flag = 0x%08x 0x%08x 0x%08x\n",
wakeup->tr.comm.r12, wakeup->md32pcm_wakeup_sta,
wakeup->tr.comm.debug_flag, wakeup->tr.comm.b_sw_flag0,
wakeup->tr.comm.b_sw_flag1);
INFO("irq:%u(0x%08x) set pending\n",
irqs->wakeupsrc[irq_index], irqs->irqs[irq_index]);
}
static void do_irqs_delivery(void)
{
unsigned int idx;
int res = 0;
struct wake_status *wakeup = NULL;
struct mt_irqremain *irqs = refer2remain_irq;
res = spm_conservation_get_result(&wakeup);
if ((res != 0) && (irqs == NULL)) {
return;
}
for (idx = 0U; idx < irqs->count; ++idx) {
if (((wakeup->tr.comm.r12 & irqs->wakeupsrc[idx]) != 0U) ||
((wakeup->raw_sta & irqs->wakeupsrc[idx]) != 0U)) {
if ((irqs->wakeupsrc_cat[idx] &
MT_IRQ_REMAIN_CAT_LOG) != 0U) {
mt_spm_irq_remain_dump(irqs, idx, wakeup);
}
mt_irq_set_pending(irqs->irqs[idx]);
}
}
}
#endif
static void spm_bus26m_conduct(struct spm_lp_scen *spm_lp,
unsigned int *resource_req)
{
spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_BUS26M_PCM_FLAG;
spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_BUS26M_PCM_FLAG1;
*resource_req |= CONSTRAINT_BUS26M_RESOURCE_REQ;
}
bool spm_is_valid_rc_bus26m(unsigned int cpu, int state_id)
{
(void)cpu;
(void)state_id;
return (status.cond_block == 0U) && IS_MT_RM_RC_READY(status.valid);
}
int spm_update_rc_bus26m(int state_id, int type, const void *val)
{
const struct mt_spm_cond_tables *tlb;
const struct mt_spm_cond_tables *tlb_check;
int res = MT_RM_STATUS_OK;
if (val == NULL) {
return MT_RM_STATUS_BAD;
}
if (type == PLAT_RC_UPDATE_CONDITION) {
tlb = (const struct mt_spm_cond_tables *)val;
tlb_check = (const struct mt_spm_cond_tables *)&cond_bus26m;
status.cond_block =
mt_spm_cond_check(state_id, tlb, tlb_check,
((status.valid &
MT_SPM_RC_VALID_COND_LATCH) != 0U) ?
&cond_bus26m_res : NULL);
} else if (type == PLAT_RC_UPDATE_REMAIN_IRQS) {
refer2remain_irq = (struct mt_irqremain *)val;
} else {
res = MT_RM_STATUS_BAD;
}
return res;
}
unsigned int spm_allow_rc_bus26m(int state_id)
{
(void)state_id;
return CONSTRAINT_BUS26M_ALLOW;
}
int spm_run_rc_bus26m(unsigned int cpu, int state_id)
{
(void)cpu;
#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER, CONSTRAINT_BUS26M_ALLOW |
(IS_PLAT_SUSPEND_ID(state_id) ?
MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND : 0U));
#endif
if (IS_PLAT_SUSPEND_ID(state_id)) {
mt_spm_suspend_enter(state_id,
(MT_SPM_EX_OP_SET_WDT |
MT_SPM_EX_OP_HW_S1_DETECT |
MT_SPM_EX_OP_SET_SUSPEND_MODE |
bus26m_ext_opand),
CONSTRAINT_BUS26M_RESOURCE_REQ);
} else {
mt_spm_idle_generic_enter(state_id, MT_SPM_EX_OP_HW_S1_DETECT,
spm_bus26m_conduct);
}
return 0;
}
int spm_reset_rc_bus26m(unsigned int cpu, int state_id)
{
unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT;
(void)cpu;
#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, 0U);
#endif
if (IS_PLAT_SUSPEND_ID(state_id)) {
ext_op |= (bus26m_ext_opand | MT_SPM_EX_OP_SET_WDT);
mt_spm_suspend_resume(state_id, ext_op, NULL);
bus26m_ext_opand = 0U;
} else {
mt_spm_idle_generic_resume(state_id, ext_op, NULL);
status.enter_cnt++;
}
do_irqs_delivery();
return 0;
}
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <common/debug.h>
#include <mt_spm.h>
#include <mt_spm_cond.h>
#include <mt_spm_constraint.h>
#include <mt_spm_conservation.h>
#include <mt_spm_idle.h>
#include <mt_spm_internal.h>
#include <mt_spm_notifier.h>
#include <mt_spm_rc_internal.h>
#include <mt_spm_resource_req.h>
#include <mt_spm_reg.h>
#include <mt_spm_suspend.h>
#include <plat_pm.h>
#define CONSTRAINT_CPU_BUCK_PCM_FLAG \
(SPM_FLAG_DISABLE_INFRA_PDN | \
SPM_FLAG_DISABLE_VCORE_DVS | \
SPM_FLAG_DISABLE_VCORE_DFS | \
SPM_FLAG_SRAM_SLEEP_CTRL | \
SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP |\
SPM_FLAG_KEEP_CSYSPWRACK_HIGH)
#define CONSTRAINT_CPU_BUCK_PCM_FLAG1 0U
#define CONSTRAINT_CPU_BUCK_RESOURCE_REQ \
(MT_SPM_DRAM_S1 | \
MT_SPM_DRAM_S0 | \
MT_SPM_SYSPLL | \
MT_SPM_INFRA | \
MT_SPM_26M | \
MT_SPM_XO_FPM)
static unsigned int cpubuckldo_status = MT_SPM_RC_VALID_SW;
static unsigned int cpubuckldo_enter_cnt;
static void spm_cpu_bcuk_ldo_conduct(struct spm_lp_scen *spm_lp,
unsigned int *resource_req)
{
spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_CPU_BUCK_PCM_FLAG;
spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_CPU_BUCK_PCM_FLAG1;
*resource_req |= CONSTRAINT_CPU_BUCK_RESOURCE_REQ;
}
bool spm_is_valid_rc_cpu_buck_ldo(unsigned int cpu, int state_id)
{
(void)cpu;
(void)state_id;
return IS_MT_RM_RC_READY(cpubuckldo_status);
}
unsigned int spm_allow_rc_cpu_buck_ldo(int state_id)
{
(void)state_id;
return MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF;
}
int spm_run_rc_cpu_buck_ldo(unsigned int cpu, int state_id)
{
(void)cpu;
#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER,
(IS_PLAT_SUSPEND_ID(state_id) ?
MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND : 0U));
#endif
if (IS_PLAT_SUSPEND_ID(state_id)) {
mt_spm_suspend_enter(state_id,
MT_SPM_EX_OP_SET_SUSPEND_MODE |
MT_SPM_EX_OP_SET_WDT,
CONSTRAINT_CPU_BUCK_RESOURCE_REQ);
} else {
mt_spm_idle_generic_enter(state_id, 0U,
spm_cpu_bcuk_ldo_conduct);
}
cpubuckldo_enter_cnt++;
return 0;
}
int spm_reset_rc_cpu_buck_ldo(unsigned int cpu, int state_id)
{
(void)cpu;
#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, 0U);
#endif
if (IS_PLAT_SUSPEND_ID(state_id)) {
mt_spm_suspend_resume(state_id, MT_SPM_EX_OP_SET_WDT, NULL);
} else {
mt_spm_idle_generic_resume(state_id, 0U, NULL);
}
return 0;
}
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <common/debug.h>
#include <mt_lp_rm.h>
#include <mt_spm.h>
#include <mt_spm_cond.h>
#include <mt_spm_constraint.h>
#include <mt_spm_conservation.h>
#include <mt_spm_idle.h>
#include <mt_spm_internal.h>
#include <mt_spm_notifier.h>
#include <mt_spm_resource_req.h>
#include <mt_spm_reg.h>
#include <mt_spm_rc_internal.h>
#include <mt_spm_suspend.h>
#include <plat_pm.h>
#include <plat_mtk_lpm.h>
#define CONSTRAINT_DRAM_ALLOW \
(MT_RM_CONSTRAINT_ALLOW_DRAM_S0 | \
MT_RM_CONSTRAINT_ALLOW_DRAM_S1 | \
MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF)
#define CONSTRAINT_DRAM_PCM_FLAG \
(SPM_FLAG_DISABLE_INFRA_PDN | \
SPM_FLAG_DISABLE_VCORE_DVS | \
SPM_FLAG_DISABLE_VCORE_DFS | \
SPM_FLAG_SRAM_SLEEP_CTRL | \
SPM_FLAG_KEEP_CSYSPWRACK_HIGH | \
SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP)
#define CONSTRAINT_DRAM_PCM_FLAG1 0U
#define CONSTRAINT_DRAM_RESOURCE_REQ \
(MT_SPM_SYSPLL | \
MT_SPM_INFRA | \
MT_SPM_26M)
static struct mt_spm_cond_tables cond_dram = {
.name = "dram",
.table_cg = {
0xFFFDD008, /* MTCMOS1 */
0x20040802, /* INFRA0 */
0x27AF8000, /* INFRA1 */
0x86040640, /* INFRA2 */
0x00000000, /* INFRA3 */
0x80000000, /* INFRA4 */
0x00000000, /* PERI0 */
0x00004000, /* VPPSYS0_0 */
0x08803000, /* VPPSYS0_1 */
0x00000000, /* VPPSYS0_2 */
0x80005555, /* VPPSYS1_0 */
0x00009008, /* VPPSYS1_1 */
0x60060000, /* VDOSYS0_0 */
0x00000000, /* VDOSYS0_1 */
0x201E01F8, /* VDOSYS1_0 */
0x00800000, /* VDOSYS1_1 */
0x00000000, /* VDOSYS1_2 */
0x00000080, /* I2C */
},
.table_pll = 0U,
};
static struct mt_spm_cond_tables cond_dram_res = {
.table_cg = { 0U },
.table_pll = 0U,
};
static struct constraint_status status = {
.id = MT_RM_CONSTRAINT_ID_DRAM,
.valid = (MT_SPM_RC_VALID_SW |
MT_SPM_RC_VALID_COND_LATCH |
MT_SPM_RC_VALID_XSOC_BBLPM),
.cond_block = 0U,
.enter_cnt = 0U,
.cond_res = &cond_dram_res,
};
static void spm_dram_conduct(struct spm_lp_scen *spm_lp,
unsigned int *resource_req)
{
spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_DRAM_PCM_FLAG;
spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_DRAM_PCM_FLAG1;
*resource_req |= CONSTRAINT_DRAM_RESOURCE_REQ;
}
bool spm_is_valid_rc_dram(unsigned int cpu, int state_id)
{
(void)cpu;
(void)state_id;
return (status.cond_block == 0U) && IS_MT_RM_RC_READY(status.valid);
}
int spm_update_rc_dram(int state_id, int type, const void *val)
{
const struct mt_spm_cond_tables *tlb;
const struct mt_spm_cond_tables *tlb_check;
int res = MT_RM_STATUS_OK;
if (val == NULL) {
return MT_RM_STATUS_BAD;
}
if (type == PLAT_RC_UPDATE_CONDITION) {
tlb = (const struct mt_spm_cond_tables *)val;
tlb_check = (const struct mt_spm_cond_tables *)&cond_dram;
status.cond_block =
mt_spm_cond_check(state_id, tlb, tlb_check,
((status.valid &
MT_SPM_RC_VALID_COND_LATCH) != 0U) ?
&cond_dram_res : NULL);
} else {
res = MT_RM_STATUS_BAD;
}
return res;
}
unsigned int spm_allow_rc_dram(int state_id)
{
(void)state_id;
return CONSTRAINT_DRAM_ALLOW;
}
int spm_run_rc_dram(unsigned int cpu, int state_id)
{
unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT;
unsigned int allows = CONSTRAINT_DRAM_ALLOW;
(void)cpu;
if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) {
#ifdef MT_SPM_USING_SRCLKEN_RC
ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM;
#else
allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM;
#endif
}
#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER, allows |
(IS_PLAT_SUSPEND_ID(state_id) ?
MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND : 0U));
#else
(void)allows;
#endif
if (IS_PLAT_SUSPEND_ID(state_id)) {
mt_spm_suspend_enter(state_id,
(MT_SPM_EX_OP_SET_WDT |
MT_SPM_EX_OP_SET_SUSPEND_MODE |
MT_SPM_EX_OP_HW_S1_DETECT),
CONSTRAINT_DRAM_RESOURCE_REQ);
} else {
mt_spm_idle_generic_enter(state_id, ext_op, spm_dram_conduct);
}
return 0;
}
int spm_reset_rc_dram(unsigned int cpu, int state_id)
{
unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT;
unsigned int allows = CONSTRAINT_DRAM_ALLOW;
(void)cpu;
if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) {
#ifdef MT_SPM_USING_SRCLKEN_RC
ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM;
#else
allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM;
#endif
}
#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, allows);
#else
(void)allows;
#endif
if (IS_PLAT_SUSPEND_ID(state_id)) {
mt_spm_suspend_resume(state_id,
(MT_SPM_EX_OP_SET_WDT |
MT_SPM_EX_OP_HW_S1_DETECT),
NULL);
} else {
mt_spm_idle_generic_resume(state_id, ext_op, NULL);
status.enter_cnt++;
}
return 0;
}
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MT_SPM_RC_INTERNAL_H
#define MT_SPM_RC_INTERNAL_H
#include <stdbool.h>
#define SPM_FLAG_SRAM_SLEEP_CTRL \
(SPM_FLAG_DISABLE_SSPM_SRAM_SLEEP | \
SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP | \
SPM_FLAG_DISABLE_SYSRAM_SLEEP)
/* cpu buck/ldo constraint function */
bool spm_is_valid_rc_cpu_buck_ldo(unsigned int cpu, int state_id);
unsigned int spm_allow_rc_cpu_buck_ldo(int state_id);
int spm_run_rc_cpu_buck_ldo(unsigned int cpu, int state_id);
int spm_reset_rc_cpu_buck_ldo(unsigned int cpu, int state_id);
/* spm resource dram constraint function */
bool spm_is_valid_rc_dram(unsigned int cpu, int state_id);
int spm_update_rc_dram(int state_id, int type, const void *val);
unsigned int spm_allow_rc_dram(int state_id);
int spm_run_rc_dram(unsigned int cpu, int state_id);
int spm_reset_rc_dram(unsigned int cpu, int state_id);
/* spm resource syspll constraint function */
bool spm_is_valid_rc_syspll(unsigned int cpu, int state_id);
int spm_update_rc_syspll(int state_id, int type, const void *val);
unsigned int spm_allow_rc_syspll(int state_id);
int spm_run_rc_syspll(unsigned int cpu, int state_id);
int spm_reset_rc_syspll(unsigned int cpu, int state_id);
/* spm resource bus26m constraint function */
bool spm_is_valid_rc_bus26m(unsigned int cpu, int state_id);
int spm_update_rc_bus26m(int state_id, int type, const void *val);
unsigned int spm_allow_rc_bus26m(int state_id);
int spm_run_rc_bus26m(unsigned int cpu, int state_id);
int spm_reset_rc_bus26m(unsigned int cpu, int state_id);
#endif /* MT_SPM_RC_INTERNAL_H */
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common/debug.h>
#include <mt_lp_rm.h>
#include <mt_spm.h>
#include <mt_spm_cond.h>
#include <mt_spm_constraint.h>
#include <mt_spm_conservation.h>
#include <mt_spm_idle.h>
#include <mt_spm_internal.h>
#include <mt_spm_notifier.h>
#include <mt_spm_rc_internal.h>
#include <mt_spm_reg.h>
#include <mt_spm_resource_req.h>
#include <mt_spm_suspend.h>
#include <plat_pm.h>
#include <plat_mtk_lpm.h>
#define CONSTRAINT_SYSPLL_ALLOW \
(MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF | \
MT_RM_CONSTRAINT_ALLOW_DRAM_S0 | \
MT_RM_CONSTRAINT_ALLOW_DRAM_S1 | \
MT_RM_CONSTRAINT_ALLOW_VCORE_LP)
#define CONSTRAINT_SYSPLL_PCM_FLAG \
(SPM_FLAG_DISABLE_INFRA_PDN | \
SPM_FLAG_DISABLE_VCORE_DVS | \
SPM_FLAG_DISABLE_VCORE_DFS | \
SPM_FLAG_SRAM_SLEEP_CTRL | \
SPM_FLAG_KEEP_CSYSPWRACK_HIGH | \
SPM_FLAG_ENABLE_6315_CTRL | \
SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP |\
SPM_FLAG_USE_SRCCLKENO2)
#define CONSTRAINT_SYSPLL_PCM_FLAG1 0U
#define CONSTRAINT_SYSPLL_RESOURCE_REQ (MT_SPM_26M)
static struct mt_spm_cond_tables cond_syspll = {
.name = "syspll",
.table_cg = {
0xFFFFD008, /* MTCMOS1 */
0x20844802, /* INFRA0 */
0x27AF8000, /* INFRA1 */
0x86040640, /* INFRA2 */
0x30038020, /* INFRA3 */
0x80000000, /* INFRA4 */
0x00080A8B, /* PERI0 */
0x00004000, /* VPPSYS0_0 */
0x08803000, /* VPPSYS0_1 */
0x00000000, /* VPPSYS0_2 */
0x80005555, /* VPPSYS1_0 */
0x00009008, /* VPPSYS1_1 */
0x60060000, /* VDOSYS0_0 */
0x00000000, /* VDOSYS0_1 */
0x201E01F8, /* VDOSYS1_0 */
0x00800000, /* VDOSYS1_1 */
0x00000000, /* VDOSYS1_2 */
0x00000080, /* I2C */
},
.table_pll = 0U,
};
static struct mt_spm_cond_tables cond_syspll_res = {
.table_cg = { 0U },
.table_pll = 0U,
};
static struct constraint_status status = {
.id = MT_RM_CONSTRAINT_ID_SYSPLL,
.valid = (MT_SPM_RC_VALID_SW |
MT_SPM_RC_VALID_COND_LATCH |
MT_SPM_RC_VALID_XSOC_BBLPM),
.cond_block = 0U,
.enter_cnt = 0U,
.cond_res = &cond_syspll_res,
};
static void spm_syspll_conduct(struct spm_lp_scen *spm_lp,
unsigned int *resource_req)
{
spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_SYSPLL_PCM_FLAG;
spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_SYSPLL_PCM_FLAG1;
*resource_req |= CONSTRAINT_SYSPLL_RESOURCE_REQ;
}
bool spm_is_valid_rc_syspll(unsigned int cpu, int state_id)
{
(void)cpu;
(void)state_id;
return (status.cond_block == 0U) && IS_MT_RM_RC_READY(status.valid);
}
int spm_update_rc_syspll(int state_id, int type, const void *val)
{
const struct mt_spm_cond_tables *tlb;
const struct mt_spm_cond_tables *tlb_check;
int res = MT_RM_STATUS_OK;
if (val == NULL) {
return MT_RM_STATUS_BAD;
}
if (type == PLAT_RC_UPDATE_CONDITION) {
tlb = (const struct mt_spm_cond_tables *)val;
tlb_check = (const struct mt_spm_cond_tables *)&cond_syspll;
status.cond_block =
mt_spm_cond_check(state_id, tlb, tlb_check,
((status.valid &
MT_SPM_RC_VALID_COND_LATCH) != 0U) ?
&cond_syspll_res : NULL);
} else {
res = MT_RM_STATUS_BAD;
}
return res;
}
unsigned int spm_allow_rc_syspll(int state_id)
{
(void)state_id;
return CONSTRAINT_SYSPLL_ALLOW;
}
int spm_run_rc_syspll(unsigned int cpu, int state_id)
{
unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT;
unsigned int allows = CONSTRAINT_SYSPLL_ALLOW;
(void)cpu;
if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) {
#ifdef MT_SPM_USING_SRCLKEN_RC
ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM;
#else
allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM;
#endif
}
#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER, allows |
(IS_PLAT_SUSPEND_ID(state_id) ?
MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND : 0U));
#else
(void)allows;
#endif
if (IS_PLAT_SUSPEND_ID(state_id)) {
mt_spm_suspend_enter(state_id,
(MT_SPM_EX_OP_SET_WDT |
MT_SPM_EX_OP_HW_S1_DETECT |
MT_SPM_EX_OP_SET_SUSPEND_MODE),
CONSTRAINT_SYSPLL_RESOURCE_REQ);
} else {
mt_spm_idle_generic_enter(state_id, ext_op, spm_syspll_conduct);
}
return 0;
}
int spm_reset_rc_syspll(unsigned int cpu, int state_id)
{
unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT;
unsigned int allows = CONSTRAINT_SYSPLL_ALLOW;
(void)cpu;
if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) {
#ifdef MT_SPM_USING_SRCLKEN_RC
ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM;
#else
allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM;
#endif
}
#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, allows);
#else
(void)allows;
#endif
if (IS_PLAT_SUSPEND_ID(state_id)) {
mt_spm_suspend_resume(state_id,
(MT_SPM_EX_OP_SET_SUSPEND_MODE |
MT_SPM_EX_OP_SET_WDT |
MT_SPM_EX_OP_HW_S1_DETECT),
NULL);
} else {
mt_spm_idle_generic_resume(state_id, ext_op, NULL);
status.enter_cnt++;
}
return 0;
}
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stddef.h>
#include <string.h>
#include <common/debug.h>
#include <lib/bakery_lock.h>
#include <lib/mmio.h>
#include <mt_lp_rm.h>
#include <mt_spm.h>
#include <mt_spm_cond.h>
#include <mt_spm_conservation.h>
#include <mt_spm_constraint.h>
#include <mt_spm_idle.h>
#include <mt_spm_internal.h>
#include <mt_spm_pmic_wrap.h>
#include <mt_spm_rc_internal.h>
#include <mt_spm_reg.h>
#include <mt_spm_resource_req.h>
#include <mt_spm_suspend.h>
#include <mtk_plat_common.h>
#include <plat_mtk_lpm.h>
#include <plat_pm.h>
#include <platform_def.h>
#include <sleep_def.h>
#ifdef MT_SPM_USING_BAKERY_LOCK
DEFINE_BAKERY_LOCK(spm_lock);
#define plat_spm_lock_init() bakery_lock_init(&spm_lock)
#else
spinlock_t spm_lock;
#define plat_spm_lock_init()
#endif
/* CLK_SCP_CFG_0 */
#define CLK_SCP_CFG_0 (TOPCKGEN_BASE + 0x264)
#define SPM_CK_CONTROL_EN 0x7FF
struct mt_resource_constraint plat_constraint_bus26m = {
.is_valid = spm_is_valid_rc_bus26m,
.update = spm_update_rc_bus26m,
.allow = spm_allow_rc_bus26m,
.run = spm_run_rc_bus26m,
.reset = spm_reset_rc_bus26m,
};
struct mt_resource_constraint plat_constraint_syspll = {
.is_valid = spm_is_valid_rc_syspll,
.update = spm_update_rc_syspll,
.allow = spm_allow_rc_syspll,
.run = spm_run_rc_syspll,
.reset = spm_reset_rc_syspll,
};
struct mt_resource_constraint plat_constraint_dram = {
.is_valid = spm_is_valid_rc_dram,
.update = spm_update_rc_dram,
.allow = spm_allow_rc_dram,
.run = spm_run_rc_dram,
.reset = spm_reset_rc_dram,
};
struct mt_resource_constraint plat_constraint_cpu = {
.is_valid = spm_is_valid_rc_cpu_buck_ldo,
.update = NULL,
.allow = spm_allow_rc_cpu_buck_ldo,
.run = spm_run_rc_cpu_buck_ldo,
.reset = spm_reset_rc_cpu_buck_ldo,
};
struct mt_resource_constraint *plat_constraints[] = {
&plat_constraint_bus26m,
&plat_constraint_syspll,
&plat_constraint_dram,
&plat_constraint_cpu,
NULL,
};
struct mt_resource_manager plat_mt8195_rm = {
.update = mt_spm_cond_update,
.consts = plat_constraints,
};
void spm_boot_init(void)
{
NOTICE("MT8195 %s\n", __func__);
/* switch ck_off/axi_26m control to SPM */
mmio_setbits_32(CLK_SCP_CFG_0, SPM_CK_CONTROL_EN);
plat_spm_lock_init();
mt_spm_pmic_wrap_set_phase(PMIC_WRAP_PHASE_ALLINONE);
mt_lp_rm_register(&plat_mt8195_rm);
mt_spm_idle_generic_init();
mt_spm_suspend_init();
}
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MT_SPM_H
#define MT_SPM_H
#include <lib/bakery_lock.h>
#include <lib/spinlock.h>
#include <plat_mtk_lpm.h>
/*
* ARM v8.2, the cache will turn off automatically when cpu
* power down. So, there is no doubt to use the spin_lock here
*/
#if !HW_ASSISTED_COHERENCY
#define MT_SPM_USING_BAKERY_LOCK
#endif
#ifdef MT_SPM_USING_BAKERY_LOCK
DECLARE_BAKERY_LOCK(spm_lock);
#define plat_spm_lock() bakery_lock_get(&spm_lock)
#define plat_spm_unlock() bakery_lock_release(&spm_lock)
#else
extern spinlock_t spm_lock;
#define plat_spm_lock() spin_lock(&spm_lock)
#define plat_spm_unlock() spin_unlock(&spm_lock)
#endif
#define MT_SPM_USING_SRCLKEN_RC
/* spm extern operand definition */
#define MT_SPM_EX_OP_CLR_26M_RECORD (1U << 0)
#define MT_SPM_EX_OP_SET_WDT (1U << 1)
#define MT_SPM_EX_OP_NON_GENERIC_RESOURCE_REQ (1U << 2)
#define MT_SPM_EX_OP_SET_SUSPEND_MODE (1U << 3)
#define MT_SPM_EX_OP_SET_IS_ADSP (1U << 4)
#define MT_SPM_EX_OP_SRCLKEN_RC_BBLPM (1U << 5)
#define MT_SPM_EX_OP_HW_S1_DETECT (1U << 6)
typedef enum {
WR_NONE = 0,
WR_UART_BUSY = 1,
WR_ABORT = 2,
WR_PCM_TIMER = 3,
WR_WAKE_SRC = 4,
WR_DVFSRC = 5,
WR_TWAM = 6,
WR_PMSR = 7,
WR_SPM_ACK_CHK = 8,
WR_UNKNOWN = 9,
} wake_reason_t;
static inline void spm_lock_get(void)
{
plat_spm_lock();
}
static inline void spm_lock_release(void)
{
plat_spm_unlock();
}
extern void spm_boot_init(void);
#endif /* MT_SPM_H */
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdbool.h>
#include <common/debug.h>
#include <lib/mmio.h>
#include <mt_spm_cond.h>
#include <mt_spm_conservation.h>
#include <mt_spm_constraint.h>
#include <plat_mtk_lpm.h>
#include <plat_pm.h>
#include <platform_def.h>
#define MT_LP_TZ_INFRA_REG(ofs) (INFRACFG_AO_BASE + ofs)
#define MT_LP_TZ_SPM_REG(ofs) (SPM_BASE + ofs)
#define MT_LP_TZ_TOPCK_REG(ofs) (TOPCKGEN_BASE + ofs)
#define MT_LP_TZ_APMIXEDSYS(ofs) (APMIXEDSYS + ofs)
#define MT_LP_TZ_VPPSYS0_REG(ofs) (VPPSYS0_BASE + ofs)
#define MT_LP_TZ_VPPSYS1_REG(ofs) (VPPSYS1_BASE + ofs)
#define MT_LP_TZ_VDOSYS0_REG(ofs) (VDOSYS0_BASE + ofs)
#define MT_LP_TZ_VDOSYS1_REG(ofs) (VDOSYS1_BASE + ofs)
#define MT_LP_TZ_PERI_AO_REG(ofs) (PERICFG_AO_BASE + ofs)
#define SPM_PWR_STATUS MT_LP_TZ_SPM_REG(0x016C)
#define SPM_PWR_STATUS_2ND MT_LP_TZ_SPM_REG(0x0170)
#define INFRA_SW_CG0 MT_LP_TZ_INFRA_REG(0x0094)
#define INFRA_SW_CG1 MT_LP_TZ_INFRA_REG(0x0090)
#define INFRA_SW_CG2 MT_LP_TZ_INFRA_REG(0x00AC)
#define INFRA_SW_CG3 MT_LP_TZ_INFRA_REG(0x00C8)
#define INFRA_SW_CG4 MT_LP_TZ_INFRA_REG(0x00E8)
#define TOP_SW_I2C_CG MT_LP_TZ_TOPCK_REG(0x00BC)
#define PERI_SW_CG0 MT_LP_TZ_PERI_AO_REG(0x0018)
#define VPPSYS0_SW_CG0 MT_LP_TZ_VPPSYS0_REG(0x0020)
#define VPPSYS0_SW_CG1 MT_LP_TZ_VPPSYS0_REG(0x002C)
#define VPPSYS0_SW_CG2 MT_LP_TZ_VPPSYS0_REG(0x0038)
#define VPPSYS1_SW_CG0 MT_LP_TZ_VPPSYS1_REG(0x0100)
#define VPPSYS1_SW_CG1 MT_LP_TZ_VPPSYS1_REG(0x0110)
#define VDOSYS0_SW_CG0 MT_LP_TZ_VDOSYS0_REG(0x0100)
#define VDOSYS0_SW_CG1 MT_LP_TZ_VDOSYS0_REG(0x0110)
#define VDOSYS1_SW_CG0 MT_LP_TZ_VDOSYS1_REG(0x0100)
#define VDOSYS1_SW_CG1 MT_LP_TZ_VDOSYS1_REG(0x0120)
#define VDOSYS1_SW_CG2 MT_LP_TZ_VDOSYS1_REG(0x0130)
/***********************************************************
* Check clkmux registers
***********************************************************/
#define CLK_CFG(id) MT_LP_TZ_TOPCK_REG(0x98 + id * 0x10)
#define PDN_CHECK BIT(7)
#define CLK_CHECK BIT(31)
enum {
CLKMUX_DISP = 0,
NF_CLKMUX,
};
static bool is_clkmux_pdn(unsigned int clkmux_id)
{
unsigned int reg, val, idx;
if ((clkmux_id & CLK_CHECK) != 0U) {
clkmux_id = (clkmux_id & ~CLK_CHECK);
reg = clkmux_id / 4U;
val = mmio_read_32(CLK_CFG(reg));
idx = clkmux_id % 4U;
val = (val >> (idx * 8U)) & PDN_CHECK;
return (val != 0U);
}
return false;
}
static struct mt_spm_cond_tables spm_cond_t;
struct idle_cond_info {
unsigned int subsys_mask;
uintptr_t addr;
bool bBitflip;
unsigned int clkmux_id;
};
#define IDLE_CG(mask, addr, bitflip, clkmux) \
{mask, (uintptr_t)addr, bitflip, clkmux}
static struct idle_cond_info idle_cg_info[PLAT_SPM_COND_MAX] = {
IDLE_CG(0xffffffff, SPM_PWR_STATUS, false, 0U),
IDLE_CG(0xffffffff, INFRA_SW_CG0, true, 0U),
IDLE_CG(0xffffffff, INFRA_SW_CG1, true, 0U),
IDLE_CG(0xffffffff, INFRA_SW_CG2, true, 0U),
IDLE_CG(0xffffffff, INFRA_SW_CG3, true, 0U),
IDLE_CG(0xffffffff, INFRA_SW_CG4, true, 0U),
IDLE_CG(0xffffffff, PERI_SW_CG0, true, 0U),
IDLE_CG(0x00000800, VPPSYS0_SW_CG0, true, (CLK_CHECK|CLKMUX_DISP)),
IDLE_CG(0x00000800, VPPSYS0_SW_CG1, true, (CLK_CHECK|CLKMUX_DISP)),
IDLE_CG(0x00000800, VPPSYS0_SW_CG2, true, (CLK_CHECK|CLKMUX_DISP)),
IDLE_CG(0x00001000, VPPSYS1_SW_CG0, true, (CLK_CHECK|CLKMUX_DISP)),
IDLE_CG(0x00001000, VPPSYS1_SW_CG1, true, (CLK_CHECK|CLKMUX_DISP)),
IDLE_CG(0x00002000, VDOSYS0_SW_CG0, true, (CLK_CHECK|CLKMUX_DISP)),
IDLE_CG(0x00002000, VDOSYS0_SW_CG1, true, (CLK_CHECK|CLKMUX_DISP)),
IDLE_CG(0x00004000, VDOSYS1_SW_CG0, true, (CLK_CHECK|CLKMUX_DISP)),
IDLE_CG(0x00004000, VDOSYS1_SW_CG1, true, (CLK_CHECK|CLKMUX_DISP)),
IDLE_CG(0x00004000, VDOSYS1_SW_CG2, true, (CLK_CHECK|CLKMUX_DISP)),
IDLE_CG(0x00000080, TOP_SW_I2C_CG, true, (CLK_CHECK|CLKMUX_DISP)),
};
/***********************************************************
* Check pll idle condition
***********************************************************/
#define PLL_MFGPLL MT_LP_TZ_APMIXEDSYS(0x340)
#define PLL_MMPLL MT_LP_TZ_APMIXEDSYS(0x0E0)
#define PLL_UNIVPLL MT_LP_TZ_APMIXEDSYS(0x1F0)
#define PLL_MSDCPLL MT_LP_TZ_APMIXEDSYS(0x710)
#define PLL_TVDPLL MT_LP_TZ_APMIXEDSYS(0x380)
unsigned int mt_spm_cond_check(int state_id,
const struct mt_spm_cond_tables *src,
const struct mt_spm_cond_tables *dest,
struct mt_spm_cond_tables *res)
{
unsigned int blocked = 0U, i;
bool is_system_suspend = IS_PLAT_SUSPEND_ID(state_id);
if ((src == NULL) || (dest == NULL)) {
return SPM_COND_CHECK_FAIL;
}
for (i = 0U; i < PLAT_SPM_COND_MAX; i++) {
if (res != NULL) {
res->table_cg[i] =
(src->table_cg[i] & dest->table_cg[i]);
if (is_system_suspend && (res->table_cg[i] != 0U)) {
INFO("suspend: %s block[%u](0x%lx) = 0x%08x\n",
dest->name, i, idle_cg_info[i].addr,
res->table_cg[i]);
}
if (res->table_cg[i] != 0U) {
blocked |= (1U << i);
}
} else if ((src->table_cg[i] & dest->table_cg[i]) != 0U) {
blocked |= (1U << i);
break;
}
}
if (res != NULL) {
res->table_pll = (src->table_pll & dest->table_pll);
if (res->table_pll != 0U) {
blocked |=
(res->table_pll << SPM_COND_BLOCKED_PLL_IDX) |
SPM_COND_CHECK_BLOCKED_PLL;
}
} else if ((src->table_pll & dest->table_pll) != 0U) {
blocked |= SPM_COND_CHECK_BLOCKED_PLL;
}
if (is_system_suspend && (blocked != 0U)) {
INFO("suspend: %s blocked=0x%08x\n", dest->name, blocked);
}
return blocked;
}
#define IS_MT_SPM_PWR_OFF(mask) \
(((mmio_read_32(SPM_PWR_STATUS) & mask) == 0U) && \
((mmio_read_32(SPM_PWR_STATUS_2ND) & mask) == 0U))
int mt_spm_cond_update(struct mt_resource_constraint **con,
int stateid, void *priv)
{
int res;
uint32_t i;
struct mt_resource_constraint *const *rc;
/* read all cg state */
for (i = 0U; i < PLAT_SPM_COND_MAX; i++) {
spm_cond_t.table_cg[i] = 0U;
/* check mtcmos, if off set idle_value and clk to 0 disable */
if (IS_MT_SPM_PWR_OFF(idle_cg_info[i].subsys_mask)) {
continue;
}
/* check clkmux */
if (is_clkmux_pdn(idle_cg_info[i].clkmux_id)) {
continue;
}
spm_cond_t.table_cg[i] = idle_cg_info[i].bBitflip ?
~mmio_read_32(idle_cg_info[i].addr) :
mmio_read_32(idle_cg_info[i].addr);
}
spm_cond_t.table_pll = 0U;
if ((mmio_read_32(PLL_MFGPLL) & 0x200) != 0U) {
spm_cond_t.table_pll |= PLL_BIT_MFGPLL;
}
if ((mmio_read_32(PLL_MMPLL) & 0x200) != 0U) {
spm_cond_t.table_pll |= PLL_BIT_MMPLL;
}
if ((mmio_read_32(PLL_UNIVPLL) & 0x200) != 0U) {
spm_cond_t.table_pll |= PLL_BIT_UNIVPLL;
}
if ((mmio_read_32(PLL_MSDCPLL) & 0x200) != 0U) {
spm_cond_t.table_pll |= PLL_BIT_MSDCPLL;
}
if ((mmio_read_32(PLL_TVDPLL) & 0x200) != 0U) {
spm_cond_t.table_pll |= PLL_BIT_TVDPLL;
}
spm_cond_t.priv = priv;
for (rc = con; *rc != NULL; rc++) {
if (((*rc)->update) == NULL) {
continue;
}
res = (*rc)->update(stateid, PLAT_RC_UPDATE_CONDITION,
(void const *)&spm_cond_t);
if (res != MT_RM_STATUS_OK) {
break;
}
}
return 0;
}
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MT_SPM_CONDIT_H
#define MT_SPM_CONDIT_H
#include <mt_lp_rm.h>
enum PLAT_SPM_COND {
PLAT_SPM_COND_MTCMOS1 = 0,
PLAT_SPM_COND_CG_INFRA_0,
PLAT_SPM_COND_CG_INFRA_1,
PLAT_SPM_COND_CG_INFRA_2,
PLAT_SPM_COND_CG_INFRA_3,
PLAT_SPM_COND_CG_INFRA_4,
PLAT_SPM_COND_CG_PERI_SW_0,
PLAT_SPM_COND_CG_VPPSYS0_SW_CG_0,
PLAT_SPM_COND_CG_VPPSYS0_SW_CG_1,
PLAT_SPM_COND_CG_VPPSYS0_SW_CG_2,
PLAT_SPM_COND_CG_VPPSYS1_SW_CG_0,
PLAT_SPM_COND_CG_VPPSYS1_SW_CG_1,
PLAT_SPM_COND_CG_VDOSYS0_SW_CG_0,
PLAT_SPM_COND_CG_VDOSYS0_SW_CG_1,
PLAT_SPM_COND_CG_VDOSYS1_SW_CG_0,
PLAT_SPM_COND_CG_VDOSYS1_SW_CG_1,
PLAT_SPM_COND_CG_VDOSYS1_SW_CG_2,
PLAT_SPM_COND_CG_I2C_SW_CG,
PLAT_SPM_COND_MAX,
};
enum PLAT_SPM_COND_PLL {
PLAT_SPM_COND_PLL_UNIVPLL = 0,
PLAT_SPM_COND_PLL_MFGPLL,
PLAT_SPM_COND_PLL_MSDCPLL,
PLAT_SPM_COND_PLL_TVDPLL,
PLAT_SPM_COND_PLL_MMPLL,
PLAT_SPM_COND_PLL_MAX,
};
#define PLL_BIT_MFGPLL BIT(PLAT_SPM_COND_PLL_MFGPLL)
#define PLL_BIT_MMPLL BIT(PLAT_SPM_COND_PLL_MMPLL)
#define PLL_BIT_UNIVPLL BIT(PLAT_SPM_COND_PLL_UNIVPLL)
#define PLL_BIT_MSDCPLL BIT(PLAT_SPM_COND_PLL_MSDCPLL)
#define PLL_BIT_TVDPLL BIT(PLAT_SPM_COND_PLL_TVDPLL)
/* Definition about SPM_COND_CHECK_BLOCKED
* bit [00 ~ 17]: cg blocking index
* bit [18 ~ 29]: pll blocking index
* bit [30] : pll blocking information
* bit [31] : idle condition check fail
*/
#define SPM_COND_BLOCKED_CG_IDX U(0)
#define SPM_COND_BLOCKED_PLL_IDX U(18)
#define SPM_COND_CHECK_BLOCKED_PLL BIT(30)
#define SPM_COND_CHECK_FAIL BIT(31)
struct mt_spm_cond_tables {
char *name;
unsigned int table_cg[PLAT_SPM_COND_MAX];
unsigned int table_pll;
void *priv;
};
extern unsigned int mt_spm_cond_check(int state_id,
const struct mt_spm_cond_tables *src,
const struct mt_spm_cond_tables *dest,
struct mt_spm_cond_tables *res);
extern int mt_spm_cond_update(struct mt_resource_constraint **con,
int stateid, void *priv);
#endif /* MT_SPM_CONDIT_H */
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common/debug.h>
#include <lib/mmio.h>
#include <mt_spm.h>
#include <mt_spm_conservation.h>
#include <mt_spm_internal.h>
#include <mt_spm_reg.h>
#include <plat_mtk_lpm.h>
#include <plat_pm.h>
#include <plat/common/platform.h>
#include <platform_def.h>
struct wake_status spm_wakesta; /* record last wakesta */
static int go_to_spm_before_wfi(int state_id, unsigned int ext_opand,
struct spm_lp_scen *spm_lp,
unsigned int resource_req)
{
int ret = 0;
struct pwr_ctrl *pwrctrl;
uint32_t cpu = plat_my_core_pos();
pwrctrl = spm_lp->pwrctrl;
__spm_set_cpu_status(cpu);
__spm_set_power_control(pwrctrl);
__spm_set_wakeup_event(pwrctrl);
__spm_set_pcm_flags(pwrctrl);
__spm_src_req_update(pwrctrl, resource_req);
if ((ext_opand & MT_SPM_EX_OP_SET_WDT) != 0U) {
__spm_set_pcm_wdt(1);
}
if ((ext_opand & MT_SPM_EX_OP_SRCLKEN_RC_BBLPM) != 0U) {
__spm_xo_soc_bblpm(1);
}
if ((ext_opand & MT_SPM_EX_OP_HW_S1_DETECT) != 0U) {
spm_hw_s1_state_monitor_resume();
}
/* Disable auto resume by PCM in system suspend stage */
if (IS_PLAT_SUSPEND_ID(state_id)) {
__spm_disable_pcm_timer();
__spm_set_pcm_wdt(0);
}
__spm_send_cpu_wakeup_event();
INFO("cpu%d: wakesrc = 0x%x, settle = 0x%x, sec = %u\n",
cpu, pwrctrl->wake_src, mmio_read_32(SPM_CLK_SETTLE),
mmio_read_32(PCM_TIMER_VAL) / 32768);
INFO("sw_flag = 0x%x 0x%x, req = 0x%x, pwr = 0x%x 0x%x\n",
pwrctrl->pcm_flags, pwrctrl->pcm_flags1,
mmio_read_32(SPM_SRC_REQ), mmio_read_32(PWR_STATUS),
mmio_read_32(PWR_STATUS_2ND));
INFO("cpu_pwr = 0x%x 0x%x\n", mmio_read_32(CPU_PWR_STATUS),
mmio_read_32(CPU_PWR_STATUS_2ND));
return ret;
}
static void go_to_spm_after_wfi(int state_id, unsigned int ext_opand,
struct spm_lp_scen *spm_lp,
struct wake_status **status)
{
unsigned int ext_status = 0U;
/* system watchdog will be resumed at kernel stage */
if ((ext_opand & MT_SPM_EX_OP_SET_WDT) != 0U) {
__spm_set_pcm_wdt(0);
}
if ((ext_opand & MT_SPM_EX_OP_SRCLKEN_RC_BBLPM) != 0U) {
__spm_xo_soc_bblpm(0);
}
if ((ext_opand & MT_SPM_EX_OP_HW_S1_DETECT) != 0U) {
spm_hw_s1_state_monitor_pause(&ext_status);
}
__spm_ext_int_wakeup_req_clr();
__spm_get_wakeup_status(&spm_wakesta, ext_status);
if (status != NULL) {
*status = &spm_wakesta;
}
__spm_clean_after_wakeup();
if (IS_PLAT_SUSPEND_ID(state_id)) {
__spm_output_wake_reason(state_id, &spm_wakesta);
}
}
int spm_conservation(int state_id, unsigned int ext_opand,
struct spm_lp_scen *spm_lp, unsigned int resource_req)
{
if (spm_lp == NULL) {
return -1;
}
spm_lock_get();
go_to_spm_before_wfi(state_id, ext_opand, spm_lp, resource_req);
spm_lock_release();
return 0;
}
void spm_conservation_finish(int state_id, unsigned int ext_opand,
struct spm_lp_scen *spm_lp,
struct wake_status **status)
{
spm_lock_get();
go_to_spm_after_wfi(state_id, ext_opand, spm_lp, status);
spm_lock_release();
}
int spm_conservation_get_result(struct wake_status **res)
{
if (res == NULL) {
return -1;
}
*res = &spm_wakesta;
return 0;
}
#define GPIO_BANK (GPIO_BASE + 0x6F0)
#define TRAP_UFS_FIRST BIT(11) /* bit 11, 0: UFS, 1: eMMC */
void spm_conservation_pwrctrl_init(struct pwr_ctrl *pwrctrl)
{
if (pwrctrl == NULL) {
return;
}
/* For ufs, emmc storage type */
if ((mmio_read_32(GPIO_BANK) & TRAP_UFS_FIRST) != 0U) {
/* If eMMC is used, mask UFS req */
pwrctrl->reg_ufs_srcclkena_mask_b = 0;
pwrctrl->reg_ufs_infra_req_mask_b = 0;
pwrctrl->reg_ufs_apsrc_req_mask_b = 0;
pwrctrl->reg_ufs_vrf18_req_mask_b = 0;
pwrctrl->reg_ufs_ddr_en_mask_b = 0;
}
}
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MT_SPM_CONSERVATION_H
#define MT_SPM_CONSERVATION_H
#include <mt_spm_internal.h>
extern int spm_conservation(int state_id, unsigned int ext_opand,
struct spm_lp_scen *spm_lp,
unsigned int resource_req);
extern void spm_conservation_finish(int state_id, unsigned int ext_opand,
struct spm_lp_scen *spm_lp,
struct wake_status **status);
extern int spm_conservation_get_result(struct wake_status **res);
extern void spm_conservation_pwrctrl_init(struct pwr_ctrl *pwrctrl);
#endif /* MT_SPM_CONSERVATION_H */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment