Merge changes I41001484,Ic734696a,I84741535,I85aaaf3a,Ibd5423b7, ... into integration

* changes:
  feat(plat/mediatek/mt8186): add reboot function for PSCI
  feat(plat/mdeiatek/mt8186): add power-off function for PSCI
  feat(plat/mediatek/mt8186): apply erratas for MT8186
  feat(plat/mediatek/mt8186): add MCDI drivers
  feat(plat/mediatek/mt8186): add CPU hotplug
  feat(plat/mediatek/mt8186): add RTC drivers
  fix(plat/mediatek/mt8186): extend MMU region size
  feat(plat/mediatek/mt8186): add DCM driver
  feat(plat/mediatek/mt8186): add pinctrl support
  feat(plat/mediatek/mt8186): add sys_cirq support
  feat(plat/mediatek/mt8186): initialize GIC
  feat(plat/mediatek/mt8186): add SiP service
  feat(plat/mediatek/mt8186): add pwrap and pmic driver
  feat(plat/mediatek/mt8186): initialize delay_timer
  feat(plat/mediatek/mt8186): initialize systimer
  feat(plat/mediatek/mt8186): add EMI MPU basic driver
This commit is contained in:
Madhukar Pappireddy 2021-12-22 19:16:55 +01:00 committed by TrustedFirmware Code Review
commit ed780b0b40
36 changed files with 3724 additions and 5 deletions

View File

@ -13,8 +13,6 @@ 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),
{ 0 }

View File

@ -11,10 +11,16 @@
#include <common/bl_common.h>
#include <common/debug.h>
#include <common/desc_image_load.h>
#include <drivers/generic_delay_timer.h>
#include <drivers/ti/uart/uart_16550.h>
#include <lib/coreboot.h>
/* Platform Includes */
#include <emi_mpu.h>
#include <mt_gic_v3.h>
#include <mt_timer.h>
#include <mtgpio.h>
#include <mtk_dcm.h>
#include <plat_params.h>
#include <plat_private.h>
@ -79,6 +85,17 @@ void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
******************************************************************************/
void bl31_platform_setup(void)
{
dcm_set_default();
/* Initialize the GIC driver, CPU and distributor interfaces */
mt_gic_driver_init();
mt_gic_init();
mt_gpio_init();
mt_systimer_init();
generic_delay_timer_init();
emi_mpu_init();
}
/*******************************************************************************

View File

@ -0,0 +1,66 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common/debug.h>
#include <mtk_dcm.h>
#include <mtk_dcm_utils.h>
static void dcm_armcore(bool mode)
{
dcm_mp_cpusys_top_bus_pll_div_dcm(mode);
dcm_mp_cpusys_top_cpu_pll_div_0_dcm(mode);
dcm_mp_cpusys_top_cpu_pll_div_1_dcm(mode);
}
static void dcm_mcusys(bool on)
{
dcm_mp_cpusys_top_adb_dcm(on);
dcm_mp_cpusys_top_apb_dcm(on);
dcm_mp_cpusys_top_cpubiu_dcm(on);
dcm_mp_cpusys_top_cpubiu_dbg_cg(on);
dcm_mp_cpusys_top_misc_dcm(on);
dcm_mp_cpusys_top_mp0_qdcm(on);
dcm_cpccfg_reg_emi_wfifo(on);
dcm_mp_cpusys_top_last_cor_idle_dcm(on);
}
static void dcm_stall(bool on)
{
dcm_mp_cpusys_top_core_stall_dcm(on);
dcm_mp_cpusys_top_fcm_stall_dcm(on);
}
static bool check_dcm_state(void)
{
bool ret = true;
ret &= dcm_mp_cpusys_top_bus_pll_div_dcm_is_on();
ret &= dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on();
ret &= dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on();
ret &= dcm_mp_cpusys_top_adb_dcm_is_on();
ret &= dcm_mp_cpusys_top_apb_dcm_is_on();
ret &= dcm_mp_cpusys_top_cpubiu_dcm_is_on();
ret &= dcm_mp_cpusys_top_cpubiu_dbg_cg_is_on();
ret &= dcm_mp_cpusys_top_misc_dcm_is_on();
ret &= dcm_mp_cpusys_top_mp0_qdcm_is_on();
ret &= dcm_cpccfg_reg_emi_wfifo_is_on();
ret &= dcm_mp_cpusys_top_last_cor_idle_dcm_is_on();
ret &= dcm_mp_cpusys_top_core_stall_dcm_is_on();
ret &= dcm_mp_cpusys_top_fcm_stall_dcm_is_on();
return ret;
}
void dcm_set_default(void)
{
dcm_armcore(true);
dcm_mcusys(true);
dcm_stall(true);
INFO("%s: %d", __func__, check_dcm_state());
}

View File

@ -0,0 +1,14 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MTK_DCM_H
#define MTK_DCM_H
#include <stdbool.h>
void dcm_set_default(void);
#endif /* #ifndef MTK_DCM_H */

View File

@ -0,0 +1,490 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <lib/mmio.h>
#include <lib/utils_def.h>
#include <mtk_dcm_utils.h>
#define MP_CPUSYS_TOP_ADB_DCM_REG0_MASK (BIT(16) | \
BIT(17) | \
BIT(18) | \
BIT(21))
#define MP_CPUSYS_TOP_ADB_DCM_REG1_MASK (BIT(16) | \
BIT(17) | \
BIT(18))
#define MP_CPUSYS_TOP_ADB_DCM_REG0_ON (BIT(16) | \
BIT(17) | \
BIT(18) | \
BIT(21))
#define MP_CPUSYS_TOP_ADB_DCM_REG1_ON (BIT(16) | \
BIT(17) | \
BIT(18))
#define MP_CPUSYS_TOP_ADB_DCM_REG0_OFF ((0x0 << 16) | \
(0x0 << 17) | \
(0x0 << 18) | \
(0x0 << 21))
#define MP_CPUSYS_TOP_ADB_DCM_REG1_OFF ((0x0 << 16) | \
(0x0 << 17) | \
(0x0 << 18))
bool dcm_mp_cpusys_top_adb_dcm_is_on(void)
{
bool ret = true;
ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG4) &
MP_CPUSYS_TOP_ADB_DCM_REG0_MASK) ==
(unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG0_ON);
ret &= ((mmio_read_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0) &
MP_CPUSYS_TOP_ADB_DCM_REG1_MASK) ==
(unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG1_ON);
return ret;
}
void dcm_mp_cpusys_top_adb_dcm(bool on)
{
if (on) {
/* TINFO = "Turn ON DCM 'mp_cpusys_top_adb_dcm'" */
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG4,
MP_CPUSYS_TOP_ADB_DCM_REG0_MASK,
MP_CPUSYS_TOP_ADB_DCM_REG0_ON);
mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
MP_CPUSYS_TOP_ADB_DCM_REG1_MASK,
MP_CPUSYS_TOP_ADB_DCM_REG1_ON);
} else {
/* TINFO = "Turn OFF DCM 'mp_cpusys_top_adb_dcm'" */
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG4,
MP_CPUSYS_TOP_ADB_DCM_REG0_MASK,
MP_CPUSYS_TOP_ADB_DCM_REG0_OFF);
mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
MP_CPUSYS_TOP_ADB_DCM_REG1_MASK,
MP_CPUSYS_TOP_ADB_DCM_REG1_OFF);
}
}
#define MP_CPUSYS_TOP_APB_DCM_REG0_MASK (BIT(5))
#define MP_CPUSYS_TOP_APB_DCM_REG1_MASK (BIT(8))
#define MP_CPUSYS_TOP_APB_DCM_REG2_MASK (BIT(16))
#define MP_CPUSYS_TOP_APB_DCM_REG0_ON (BIT(5))
#define MP_CPUSYS_TOP_APB_DCM_REG1_ON (BIT(8))
#define MP_CPUSYS_TOP_APB_DCM_REG2_ON (BIT(16))
#define MP_CPUSYS_TOP_APB_DCM_REG0_OFF ((0x0 << 5))
#define MP_CPUSYS_TOP_APB_DCM_REG1_OFF ((0x0 << 8))
#define MP_CPUSYS_TOP_APB_DCM_REG2_OFF ((0x0 << 16))
bool dcm_mp_cpusys_top_apb_dcm_is_on(void)
{
bool ret = true;
ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0) &
MP_CPUSYS_TOP_APB_DCM_REG0_MASK) ==
(unsigned int) MP_CPUSYS_TOP_APB_DCM_REG0_ON);
ret &= ((mmio_read_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0) &
MP_CPUSYS_TOP_APB_DCM_REG1_MASK) ==
(unsigned int) MP_CPUSYS_TOP_APB_DCM_REG1_ON);
ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP0_DCM_CFG0) &
MP_CPUSYS_TOP_APB_DCM_REG2_MASK) ==
(unsigned int) MP_CPUSYS_TOP_APB_DCM_REG2_ON);
return ret;
}
void dcm_mp_cpusys_top_apb_dcm(bool on)
{
if (on) {
/* TINFO = "Turn ON DCM 'mp_cpusys_top_apb_dcm'" */
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
MP_CPUSYS_TOP_APB_DCM_REG0_MASK,
MP_CPUSYS_TOP_APB_DCM_REG0_ON);
mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
MP_CPUSYS_TOP_APB_DCM_REG1_MASK,
MP_CPUSYS_TOP_APB_DCM_REG1_ON);
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0,
MP_CPUSYS_TOP_APB_DCM_REG2_MASK,
MP_CPUSYS_TOP_APB_DCM_REG2_ON);
} else {
/* TINFO = "Turn OFF DCM 'mp_cpusys_top_apb_dcm'" */
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
MP_CPUSYS_TOP_APB_DCM_REG0_MASK,
MP_CPUSYS_TOP_APB_DCM_REG0_OFF);
mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
MP_CPUSYS_TOP_APB_DCM_REG1_MASK,
MP_CPUSYS_TOP_APB_DCM_REG1_OFF);
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0,
MP_CPUSYS_TOP_APB_DCM_REG2_MASK,
MP_CPUSYS_TOP_APB_DCM_REG2_OFF);
}
}
#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK (BIT(11) | \
BIT(24) | \
BIT(25))
#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON (BIT(11) | \
BIT(24) | \
BIT(25))
#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_OFF ((0x0 << 11) | \
(0x0 << 24) | \
(0x0 << 25))
bool dcm_mp_cpusys_top_bus_pll_div_dcm_is_on(void)
{
bool ret = true;
ret &= ((mmio_read_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG) &
MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK) ==
(unsigned int) MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON);
return ret;
}
void dcm_mp_cpusys_top_bus_pll_div_dcm(bool on)
{
if (on) {
/* TINFO = "Turn ON DCM 'mp_cpusys_top_bus_pll_div_dcm'" */
mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG,
MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK,
MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON);
} else {
/* TINFO = "Turn OFF DCM 'mp_cpusys_top_bus_pll_div_dcm'" */
mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG,
MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK,
MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_OFF);
}
}
#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK (BIT(0))
#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON (BIT(0))
#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_OFF ((0x0 << 0))
bool dcm_mp_cpusys_top_core_stall_dcm_is_on(void)
{
bool ret = true;
ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP0_DCM_CFG7) &
MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK) ==
(unsigned int) MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON);
return ret;
}
void dcm_mp_cpusys_top_core_stall_dcm(bool on)
{
if (on) {
/* TINFO = "Turn ON DCM 'mp_cpusys_top_core_stall_dcm'" */
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7,
MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK,
MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON);
} else {
/* TINFO = "Turn OFF DCM 'mp_cpusys_top_core_stall_dcm'" */
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7,
MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK,
MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_OFF);
}
}
#define MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_MASK (BIT(0))
#define MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_ON ((0x0 << 0))
#define MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_OFF (BIT(0))
bool dcm_mp_cpusys_top_cpubiu_dbg_cg_is_on(void)
{
bool ret = true;
ret &= ((mmio_read_32(MP_CPUSYS_TOP_MCSI_CFG2) &
MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_MASK) ==
(unsigned int) MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_ON);
return ret;
}
void dcm_mp_cpusys_top_cpubiu_dbg_cg(bool on)
{
if (on) {
/* TINFO = "Turn ON DCM 'mp_cpusys_top_cpubiu_dbg_cg'" */
mmio_clrsetbits_32(MP_CPUSYS_TOP_MCSI_CFG2,
MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_MASK,
MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_ON);
} else {
/* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpubiu_dbg_cg'" */
mmio_clrsetbits_32(MP_CPUSYS_TOP_MCSI_CFG2,
MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_MASK,
MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_OFF);
}
}
#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK ((0xffff << 0))
#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON ((0xffff << 0))
#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_OFF ((0x0 << 0))
bool dcm_mp_cpusys_top_cpubiu_dcm_is_on(void)
{
bool ret = true;
ret &= ((mmio_read_32(MP_CPUSYS_TOP_MCSIC_DCM0) &
MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK) ==
(unsigned int) MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON);
return ret;
}
void dcm_mp_cpusys_top_cpubiu_dcm(bool on)
{
if (on) {
/* TINFO = "Turn ON DCM 'mp_cpusys_top_cpubiu_dcm'" */
mmio_clrsetbits_32(MP_CPUSYS_TOP_MCSIC_DCM0,
MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK,
MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON);
} else {
/* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpubiu_dcm'" */
mmio_clrsetbits_32(MP_CPUSYS_TOP_MCSIC_DCM0,
MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK,
MP_CPUSYS_TOP_CPUBIU_DCM_REG0_OFF);
}
}
#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK (BIT(11) | \
BIT(24) | \
BIT(25))
#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON (BIT(11) | \
BIT(24) | \
BIT(25))
#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_OFF ((0x0 << 11) | \
(0x0 << 24) | \
(0x0 << 25))
bool dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on(void)
{
bool ret = true;
ret &= ((mmio_read_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG0) &
MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK) ==
(unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON);
return ret;
}
void dcm_mp_cpusys_top_cpu_pll_div_0_dcm(bool on)
{
if (on) {
/* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_0_dcm'" */
mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG0,
MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK,
MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON);
} else {
/* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_0_dcm'" */
mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG0,
MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK,
MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_OFF);
}
}
#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK (BIT(11) | \
BIT(24) | \
BIT(25))
#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON (BIT(11) | \
BIT(24) | \
BIT(25))
#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_OFF ((0x0 << 11) | \
(0x0 << 24) | \
(0x0 << 25))
bool dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on(void)
{
bool ret = true;
ret &= ((mmio_read_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG1) &
MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK) ==
(unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON);
return ret;
}
void dcm_mp_cpusys_top_cpu_pll_div_1_dcm(bool on)
{
if (on) {
/* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_1_dcm'" */
mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG1,
MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK,
MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON);
} else {
/* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_1_dcm'" */
mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG1,
MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK,
MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_OFF);
}
}
#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK (BIT(4))
#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON (BIT(4))
#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_OFF ((0x0 << 4))
bool dcm_mp_cpusys_top_fcm_stall_dcm_is_on(void)
{
bool ret = true;
ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP0_DCM_CFG7) &
MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK) ==
(unsigned int) MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON);
return ret;
}
void dcm_mp_cpusys_top_fcm_stall_dcm(bool on)
{
if (on) {
/* TINFO = "Turn ON DCM 'mp_cpusys_top_fcm_stall_dcm'" */
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7,
MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK,
MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON);
} else {
/* TINFO = "Turn OFF DCM 'mp_cpusys_top_fcm_stall_dcm'" */
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7,
MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK,
MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_OFF);
}
}
#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK (BIT(31))
#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON (BIT(31))
#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_OFF ((0x0 << 31))
bool dcm_mp_cpusys_top_last_cor_idle_dcm_is_on(void)
{
bool ret = true;
ret &= ((mmio_read_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG) &
MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK) ==
(unsigned int) MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON);
return ret;
}
void dcm_mp_cpusys_top_last_cor_idle_dcm(bool on)
{
if (on) {
/* TINFO = "Turn ON DCM 'mp_cpusys_top_last_cor_idle_dcm'" */
mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG,
MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK,
MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON);
} else {
/* TINFO = "Turn OFF DCM 'mp_cpusys_top_last_cor_idle_dcm'" */
mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG,
MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK,
MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_OFF);
}
}
#define MP_CPUSYS_TOP_MISC_DCM_REG0_MASK (BIT(0) | \
BIT(1) | \
BIT(2) | \
BIT(3) | \
BIT(4))
#define MP_CPUSYS_TOP_MISC_DCM_REG0_ON (BIT(0) | \
BIT(1) | \
BIT(2) | \
BIT(3) | \
BIT(4))
#define MP_CPUSYS_TOP_MISC_DCM_REG0_OFF ((0x0 << 0) | \
(0x0 << 1) | \
(0x0 << 2) | \
(0x0 << 3) | \
(0x0 << 4))
bool dcm_mp_cpusys_top_misc_dcm_is_on(void)
{
bool ret = true;
ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0) &
MP_CPUSYS_TOP_MISC_DCM_REG0_MASK) ==
(unsigned int) MP_CPUSYS_TOP_MISC_DCM_REG0_ON);
return ret;
}
void dcm_mp_cpusys_top_misc_dcm(bool on)
{
if (on) {
/* TINFO = "Turn ON DCM 'mp_cpusys_top_misc_dcm'" */
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
MP_CPUSYS_TOP_MISC_DCM_REG0_MASK,
MP_CPUSYS_TOP_MISC_DCM_REG0_ON);
} else {
/* TINFO = "Turn OFF DCM 'mp_cpusys_top_misc_dcm'" */
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
MP_CPUSYS_TOP_MISC_DCM_REG0_MASK,
MP_CPUSYS_TOP_MISC_DCM_REG0_OFF);
}
}
#define MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK (BIT(0) | \
BIT(1) | \
BIT(2) | \
BIT(3))
#define MP_CPUSYS_TOP_MP0_QDCM_REG0_ON (BIT(0) | \
BIT(1) | \
BIT(2) | \
BIT(3))
#define MP_CPUSYS_TOP_MP0_QDCM_REG0_OFF ((0x0 << 0) | \
(0x0 << 1) | \
(0x0 << 2) | \
(0x0 << 3))
bool dcm_mp_cpusys_top_mp0_qdcm_is_on(void)
{
bool ret = true;
ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP0_DCM_CFG0) &
MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK) ==
(unsigned int) MP_CPUSYS_TOP_MP0_QDCM_REG0_ON);
return ret;
}
void dcm_mp_cpusys_top_mp0_qdcm(bool on)
{
if (on) {
/* TINFO = "Turn ON DCM 'mp_cpusys_top_mp0_qdcm'" */
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0,
MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK,
MP_CPUSYS_TOP_MP0_QDCM_REG0_ON);
} else {
/* TINFO = "Turn OFF DCM 'mp_cpusys_top_mp0_qdcm'" */
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0,
MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK,
MP_CPUSYS_TOP_MP0_QDCM_REG0_OFF);
}
}
#define CPCCFG_REG_EMI_WFIFO_REG0_MASK (BIT(0) | BIT(2))
#define CPCCFG_REG_EMI_WFIFO_REG0_ON (BIT(0) | BIT(2))
#define CPCCFG_REG_EMI_WFIFO_REG0_OFF ((0x0 << 0) | (0x0 << 2))
bool dcm_cpccfg_reg_emi_wfifo_is_on(void)
{
bool ret = true;
ret &= ((mmio_read_32(CPCCFG_REG_EMI_WFIFO) &
CPCCFG_REG_EMI_WFIFO_REG0_MASK) ==
(unsigned int) CPCCFG_REG_EMI_WFIFO_REG0_ON);
return ret;
}
void dcm_cpccfg_reg_emi_wfifo(bool on)
{
if (on) {
/* TINFO = "Turn ON DCM 'cpccfg_reg_emi_wfifo'" */
mmio_clrsetbits_32(CPCCFG_REG_EMI_WFIFO,
CPCCFG_REG_EMI_WFIFO_REG0_MASK,
CPCCFG_REG_EMI_WFIFO_REG0_ON);
} else {
/* TINFO = "Turn OFF DCM 'cpccfg_reg_emi_wfifo'" */
mmio_clrsetbits_32(CPCCFG_REG_EMI_WFIFO,
CPCCFG_REG_EMI_WFIFO_REG0_MASK,
CPCCFG_REG_EMI_WFIFO_REG0_OFF);
}
}

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MTK_DCM_UTILS_H
#define MTK_DCM_UTILS_H
#include <stdbool.h>
#include <mtk_dcm.h>
#include <platform_def.h>
/* Base */
#define MP_CPUSYS_TOP_BASE 0xc538000
#define CPCCFG_REG_BASE 0xc53a800
/* Register Definition */
#define CPCCFG_REG_EMI_WFIFO (CPCCFG_REG_BASE + 0x100)
#define MP_CPUSYS_TOP_BUS_PLLDIV_CFG (MP_CPUSYS_TOP_BASE + 0x22e0)
#define MP_CPUSYS_TOP_CPU_PLLDIV_CFG0 (MP_CPUSYS_TOP_BASE + 0x22a0)
#define MP_CPUSYS_TOP_CPU_PLLDIV_CFG1 (MP_CPUSYS_TOP_BASE + 0x22a4)
#define MP_CPUSYS_TOP_MCSIC_DCM0 (MP_CPUSYS_TOP_BASE + 0x2440)
#define MP_CPUSYS_TOP_MCSI_CFG2 (MP_CPUSYS_TOP_BASE + 0x2418)
#define MP_CPUSYS_TOP_MCUSYS_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x25c0)
#define MP_CPUSYS_TOP_MP0_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x4880)
#define MP_CPUSYS_TOP_MP0_DCM_CFG7 (MP_CPUSYS_TOP_BASE + 0x489c)
#define MP_CPUSYS_TOP_MP_ADB_DCM_CFG4 (MP_CPUSYS_TOP_BASE + 0x2510)
#define MP_CPUSYS_TOP_MP_MISC_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x2518)
bool dcm_mp_cpusys_top_adb_dcm_is_on(void);
void dcm_mp_cpusys_top_adb_dcm(bool on);
bool dcm_mp_cpusys_top_apb_dcm_is_on(void);
void dcm_mp_cpusys_top_apb_dcm(bool on);
bool dcm_mp_cpusys_top_bus_pll_div_dcm_is_on(void);
void dcm_mp_cpusys_top_bus_pll_div_dcm(bool on);
bool dcm_mp_cpusys_top_core_stall_dcm_is_on(void);
void dcm_mp_cpusys_top_core_stall_dcm(bool on);
bool dcm_mp_cpusys_top_cpubiu_dbg_cg_is_on(void);
void dcm_mp_cpusys_top_cpubiu_dbg_cg(bool on);
bool dcm_mp_cpusys_top_cpubiu_dcm_is_on(void);
void dcm_mp_cpusys_top_cpubiu_dcm(bool on);
bool dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on(void);
void dcm_mp_cpusys_top_cpu_pll_div_0_dcm(bool on);
bool dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on(void);
void dcm_mp_cpusys_top_cpu_pll_div_1_dcm(bool on);
bool dcm_mp_cpusys_top_fcm_stall_dcm_is_on(void);
void dcm_mp_cpusys_top_fcm_stall_dcm(bool on);
bool dcm_mp_cpusys_top_last_cor_idle_dcm_is_on(void);
void dcm_mp_cpusys_top_last_cor_idle_dcm(bool on);
bool dcm_mp_cpusys_top_misc_dcm_is_on(void);
void dcm_mp_cpusys_top_misc_dcm(bool on);
bool dcm_mp_cpusys_top_mp0_qdcm_is_on(void);
void dcm_mp_cpusys_top_mp0_qdcm(bool on);
bool dcm_cpccfg_reg_emi_wfifo_is_on(void);
void dcm_cpccfg_reg_emi_wfifo(bool on);
#endif

View File

@ -0,0 +1,100 @@
/*
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <string.h>
#include <common/debug.h>
#include <lib/mmio.h>
#include <emi_mpu.h>
#if ENABLE_EMI_MPU_SW_LOCK
static unsigned char region_lock_state[EMI_MPU_REGION_NUM];
#endif
#define EMI_MPU_START_MASK (0x00FFFFFF)
#define EMI_MPU_END_MASK (0x00FFFFFF)
#define EMI_MPU_APC_SW_LOCK_MASK (0x00FFFFFF)
#define EMI_MPU_APC_HW_LOCK_MASK (0x80FFFFFF)
static int _emi_mpu_set_protection(unsigned int start, unsigned int end,
unsigned int apc)
{
unsigned int dgroup;
unsigned int region;
region = (start >> 24) & 0xFF;
start &= EMI_MPU_START_MASK;
dgroup = (end >> 24) & 0xFF;
end &= EMI_MPU_END_MASK;
if ((region >= EMI_MPU_REGION_NUM) || (dgroup > EMI_MPU_DGROUP_NUM)) {
WARN("invalid region, domain\n");
return -1;
}
#if ENABLE_EMI_MPU_SW_LOCK
if (region_lock_state[region] == 1) {
WARN("invalid region\n");
return -1;
}
if ((dgroup == 0U) && ((apc >> 31) & 0x1)) {
region_lock_state[region] = 1;
}
apc &= EMI_MPU_APC_SW_LOCK_MASK;
#else
apc &= EMI_MPU_APC_HW_LOCK_MASK;
#endif
if ((start >= DRAM_OFFSET) && (end >= start)) {
start -= DRAM_OFFSET;
end -= DRAM_OFFSET;
} else {
WARN("invalid range\n");
return -1;
}
mmio_write_32(EMI_MPU_SA(region), start);
mmio_write_32(EMI_MPU_EA(region), end);
mmio_write_32(EMI_MPU_APC(region, dgroup), apc);
#if defined(SUB_EMI_MPU_BASE)
mmio_write_32(SUB_EMI_MPU_SA(region), start);
mmio_write_32(SUB_EMI_MPU_EA(region), end);
mmio_write_32(SUB_EMI_MPU_APC(region, dgroup), apc);
#endif
return 0;
}
int emi_mpu_set_protection(struct emi_region_info_t *region_info)
{
unsigned int start, end;
int i;
if (region_info->region >= EMI_MPU_REGION_NUM) {
WARN("invalid region\n");
return -1;
}
start = (unsigned int)(region_info->start >> EMI_MPU_ALIGN_BITS) |
(region_info->region << 24);
for (i = EMI_MPU_DGROUP_NUM - 1; i >= 0; i--) {
end = (unsigned int)(region_info->end >> EMI_MPU_ALIGN_BITS) | (i << 24);
if (_emi_mpu_set_protection(start, end, region_info->apc[i]) < 0) {
WARN("failed to set emi mpu protection(%d, %d, %d)\n",
start, end, region_info->apc[i]);
}
}
return 0;
}
void emi_mpu_init(void)
{
/* TODO: more setting for EMI MPU. */
}

View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef EMI_MPU_H
#define EMI_MPU_H
#include <platform_def.h>
#define ENABLE_EMI_MPU_SW_LOCK 1
#define EMI_MPU_CTRL (EMI_MPU_BASE + 0x000)
#define EMI_MPU_DBG (EMI_MPU_BASE + 0x004)
#define EMI_MPU_SA0 (EMI_MPU_BASE + 0x100)
#define EMI_MPU_EA0 (EMI_MPU_BASE + 0x200)
#define EMI_MPU_SA(region) (EMI_MPU_SA0 + (region * 4))
#define EMI_MPU_EA(region) (EMI_MPU_EA0 + (region * 4))
#define EMI_MPU_APC0 (EMI_MPU_BASE + 0x300)
#define EMI_MPU_APC(region, dgroup) (EMI_MPU_APC0 + (region * 4) + (dgroup * 0x100))
#define EMI_MPU_CTRL_D0 (EMI_MPU_BASE + 0x800)
#define EMI_MPU_CTRL_D(domain) (EMI_MPU_CTRL_D0 + (domain * 4))
#define EMI_RG_MASK_D0 (EMI_MPU_BASE + 0x900)
#define EMI_RG_MASK_D(domain) (EMI_RG_MASK_D0 + (domain * 4))
#define EMI_MPU_START (0x000)
#define EMI_MPU_END (0x93C)
#define SUB_EMI_MPU_CTRL (SUB_EMI_MPU_BASE + 0x000)
#define SUB_EMI_MPU_DBG (SUB_EMI_MPU_BASE + 0x004)
#define SUB_EMI_MPU_SA0 (SUB_EMI_MPU_BASE + 0x100)
#define SUB_EMI_MPU_EA0 (SUB_EMI_MPU_BASE + 0x200)
#define SUB_EMI_MPU_SA(region) (SUB_EMI_MPU_SA0 + (region * 4))
#define SUB_EMI_MPU_EA(region) (SUB_EMI_MPU_EA0 + (region * 4))
#define SUB_EMI_MPU_APC0 (SUB_EMI_MPU_BASE + 0x300)
#define SUB_EMI_MPU_APC(region, dgroup) (SUB_EMI_MPU_APC0 + (region * 4) + (dgroup * 0x100))
#define SUB_EMI_MPU_CTRL_D0 (SUB_EMI_MPU_BASE + 0x800)
#define SUB_EMI_MPU_CTRL_D(domain) (SUB_EMI_MPU_CTRL_D0 + (domain * 4))
#define SUB_EMI_RG_MASK_D0 (SUB_EMI_MPU_BASE + 0x900)
#define SUB_EMI_RG_MASK_D(domain) (SUB_EMI_RG_MASK_D0 + (domain * 4))
#define EMI_MPU_DOMAIN_NUM (16)
#define EMI_MPU_REGION_NUM (32)
#define EMI_MPU_ALIGN_BITS (16)
#define DRAM_OFFSET (0x40000000 >> EMI_MPU_ALIGN_BITS)
#define NO_PROTECTION 0
#define SEC_RW 1
#define SEC_RW_NSEC_R 2
#define SEC_RW_NSEC_W 3
#define SEC_R_NSEC_R 4
#define FORBIDDEN 5
#define SEC_R_NSEC_RW 6
#define LOCK 1
#define UNLOCK 0
#define EMI_MPU_DGROUP_NUM (EMI_MPU_DOMAIN_NUM / 8)
#if (EMI_MPU_DGROUP_NUM == 1)
#define SET_ACCESS_PERMISSION(apc_ary, lock, d7, d6, d5, d4, d3, d2, d1, d0) \
do { \
apc_ary[1] = 0; \
apc_ary[0] = \
(((unsigned int) d7) << 21) | (((unsigned int) d6) << 18) | \
(((unsigned int) d5) << 15) | (((unsigned int) d4) << 12) | \
(((unsigned int) d3) << 9) | (((unsigned int) d2) << 6) | \
(((unsigned int) d1) << 3) | ((unsigned int) d0) | \
((unsigned int) lock << 31); \
} while (0)
#elif (EMI_MPU_DGROUP_NUM == 2)
#define SET_ACCESS_PERMISSION(apc_ary, lock, d15, d14, d13, d12, d11, d10, \
d9, d8, d7, d6, d5, d4, d3, d2, d1, d0) \
do { \
apc_ary[1] = \
(((unsigned int) d15) << 21) | (((unsigned int) d14) << 18) | \
(((unsigned int) d13) << 15) | (((unsigned int) d12) << 12) | \
(((unsigned int) d11) << 9) | (((unsigned int) d10) << 6) | \
(((unsigned int) d9) << 3) | ((unsigned int) d8); \
apc_ary[0] = \
(((unsigned int) d7) << 21) | (((unsigned int) d6) << 18) | \
(((unsigned int) d5) << 15) | (((unsigned int) d4) << 12) | \
(((unsigned int) d3) << 9) | (((unsigned int) d2) << 6) | \
(((unsigned int) d1) << 3) | ((unsigned int) d0) | \
((unsigned int) lock << 31); \
} while (0)
#endif
struct emi_region_info_t {
unsigned long long start;
unsigned long long end;
unsigned int region;
unsigned int apc[EMI_MPU_DGROUP_NUM];
};
void emi_mpu_init(void);
#endif

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <mtgpio.h>
#include <platform_def.h>
uintptr_t mt_gpio_find_reg_addr(uint32_t pin)
{
uintptr_t reg_addr = 0U;
struct mt_pin_info gpio_info;
assert(pin < MAX_GPIO_PIN);
gpio_info = mt_pin_infos[pin];
switch (gpio_info.base & 0x0f) {
case 0:
reg_addr = IOCFG_LT_BASE;
break;
case 1:
reg_addr = IOCFG_LM_BASE;
break;
case 2:
reg_addr = IOCFG_LB_BASE;
break;
case 3:
reg_addr = IOCFG_BL_BASE;
break;
case 4:
reg_addr = IOCFG_RB_BASE;
break;
case 5:
reg_addr = IOCFG_RT_BASE;
break;
default:
break;
}
return reg_addr;
}

View File

@ -0,0 +1,230 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MT_GPIO_H
#define MT_GPIO_H
#include <mtgpio_common.h>
/* Enumeration for GPIO pin */
typedef enum GPIO_PIN {
GPIO_UNSUPPORTED = -1,
GPIO0, GPIO1, GPIO2, GPIO3, GPIO4, GPIO5, GPIO6,
GPIO7, GPIO8, GPIO9, GPIO10, GPIO11, GPIO12, GPIO13, GPIO14,
GPIO15, GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22,
GPIO23, GPIO24, GPIO25, GPIO26, GPIO27, GPIO28, GPIO29, GPIO30,
GPIO31, GPIO32, GPIO33, GPIO34, GPIO35, GPIO36, GPIO37, GPIO38,
GPIO39, GPIO40, GPIO41, GPIO42, GPIO43, GPIO44, GPIO45, GPIO46,
GPIO47, GPIO48, GPIO49, GPIO50, GPIO51, GPIO52, GPIO53, GPIO54,
GPIO55, GPIO56, GPIO57, GPIO58, GPIO59, GPIO60, GPIO61, GPIO62,
GPIO63, GPIO64, GPIO65, GPIO66, GPIO67, GPIO68, GPIO69, GPIO70,
GPIO71, GPIO72, GPIO73, GPIO74, GPIO75, GPIO76, GPIO77, GPIO78,
GPIO79, GPIO80, GPIO81, GPIO82, GPIO83, GPIO84, GPIO85, GPIO86,
GPIO87, GPIO88, GPIO89, GPIO90, GPIO91, GPIO92, GPIO93, GPIO94,
GPIO95, GPIO96, GPIO97, GPIO98, GPIO99, GPIO100, GPIO101, GPIO102,
GPIO103, GPIO104, GPIO105, GPIO106, GPIO107, GPIO108, GPIO109, GPIO110,
GPIO111, GPIO112, GPIO113, GPIO114, GPIO115, GPIO116, GPIO117, GPIO118,
GPIO119, GPIO120, GPIO121, GPIO122, GPIO123, GPIO124, GPIO125, GPIO126,
GPIO127, GPIO128, GPIO129, GPIO130, GPIO131, GPIO132, GPIO133, GPIO134,
GPIO135, GPIO136, GPIO137, GPIO138, GPIO139, GPIO140, GPIO141, GPIO142,
GPIO143, GPIO144, GPIO145, GPIO146, GPIO147, GPIO148, GPIO149, GPIO150,
GPIO151, GPIO152, GPIO153, GPIO154, GPIO155, GPIO156, GPIO157, GPIO158,
GPIO159, GPIO160, GPIO161, GPIO162, GPIO163, GPIO164, GPIO165, GPIO166,
GPIO167, GPIO168, GPIO169, GPIO170, GPIO171, GPIO172, GPIO173, GPIO174,
GPIO175, GPIO176, GPIO177, GPIO178, GPIO179, GPIO180, GPIO181, GPIO182,
GPIO183, GPIO184,
MT_GPIO_BASE_MAX
} GPIO_PIN;
static const struct mt_pin_info mt_pin_infos[] = {
PIN(0, 0, 13, 0x16, 0x40),
PIN(1, 0, 14, 0x16, 0x40),
PIN(2, 0, 17, 0x16, 0x40),
PIN(3, 0, 18, 0x16, 0x40),
PIN(4, 0, 19, 0x16, 0x40),
PIN(5, 0, 20, 0x16, 0x40),
PIN(6, 0, 19, 0x24, 0x40),
PIN(7, 0, 20, 0x24, 0x40),
PIN(8, 0, 21, 0x24, 0x40),
PIN(9, 0, 22, 0x24, 0x40),
PIN(10, 0, 16, 0x24, 0x40),
PIN(11, 0, 17, 0x24, 0x40),
PIN(12, 0, 18, 0x24, 0x40),
PIN(13, 0, 0, 0x23, 0x60),
PIN(14, 0, 1, 0x23, 0x60),
PIN(15, 0, 15, 0x16, 0x40),
PIN(16, 0, 16, 0x16, 0x40),
PIN(17, 0, 9, 0x25, 0x70),
PIN(18, 0, 10, 0x25, 0x70),
PIN(19, 0, 3, 0x25, 0x70),
PIN(20, 0, 6, 0x25, 0x70),
PIN(21, 0, 4, 0x25, 0x70),
PIN(22, 0, 7, 0x25, 0x70),
PIN(23, 0, 5, 0x25, 0x70),
PIN(24, 0, 8, 0x25, 0x70),
PIN(25, 0, 18, 0x25, 0x70),
PIN(26, 0, 15, 0x25, 0x70),
PIN(27, 0, 17, 0x25, 0x70),
PIN(28, 0, 16, 0x25, 0x70),
PIN(29, 0, 0, 0x16, 0x40),
PIN(30, 0, 1, 0x16, 0x40),
PIN(31, 0, 2, 0x16, 0x40),
PIN(32, 0, 25, 0x12, 0x50),
PIN(33, 0, 27, 0x12, 0x50),
PIN(34, 0, 26, 0x12, 0x50),
PIN(35, 0, 28, 0x12, 0x50),
PIN(36, 0, 9, 0x12, 0x50),
PIN(37, 0, 10, 0x12, 0x50),
PIN(38, 0, 12, 0x12, 0x50),
PIN(39, 0, 11, 0x12, 0x50),
PIN(40, 0, 13, 0x12, 0x50),
PIN(41, 0, 14, 0x12, 0x50),
PIN(42, 0, 16, 0x12, 0x50),
PIN(43, 0, 15, 0x12, 0x50),
PIN(44, 0, 28, 0x25, 0x70),
PIN(45, 0, 29, 0x25, 0x70),
PIN(46, 0, 31, 0x25, 0x70),
PIN(47, 0, 30, 0x25, 0x70),
PIN(48, 0, 17, 0x12, 0x50),
PIN(49, 0, 18, 0x12, 0x50),
PIN(50, 0, 20, 0x12, 0x50),
PIN(51, 0, 19, 0x12, 0x50),
PIN(52, 0, 12, 0x23, 0x60),
PIN(53, 0, 13, 0x23, 0x60),
PIN(54, 0, 15, 0x23, 0x60),
PIN(55, 0, 14, 0x23, 0x60),
PIN(56, 0, 12, 0x25, 0x70),
PIN(57, 0, 11, 0x25, 0x70),
PIN(58, 0, 13, 0x25, 0x70),
PIN(59, 0, 14, 0x25, 0x70),
PIN(60, 0, 21, 0x23, 0x60),
PIN(61, 0, 16, 0x23, 0x60),
PIN(62, 0, 22, 0x23, 0x60),
PIN(63, 0, 17, 0x23, 0x60),
PIN(64, 0, 18, 0x23, 0x60),
PIN(65, 0, 19, 0x23, 0x60),
PIN(66, 0, 20, 0x23, 0x60),
PIN(67, 1, 10, 0x21, 0x70),
PIN(68, 1, 0, 0x21, 0x70),
PIN(69, 1, 1, 0x21, 0x70),
PIN(70, 1, 11, 0x21, 0x70),
PIN(71, 1, 2, 0x21, 0x70),
PIN(72, 1, 3, 0x21, 0x70),
PIN(73, 1, 4, 0x21, 0x70),
PIN(74, 1, 5, 0x21, 0x70),
PIN(75, 1, 6, 0x21, 0x70),
PIN(76, 1, 7, 0x21, 0x70),
PIN(77, 1, 8, 0x21, 0x70),
PIN(78, 1, 9, 0x21, 0x70),
PIN(79, 1, 0, 0x25, 0x80),
PIN(80, 1, 1, 0x25, 0x80),
PIN(81, 1, 2, 0x25, 0x80),
PIN(82, 1, 3, 0x25, 0x80),
PIN(83, 0, 3, 0x16, 0x40),
PIN(84, 1, 0, 0x23, 0x70),
PIN(85, 1, 1, 0x23, 0x70),
PIN(86, 1, 2, 0x23, 0x70),
PIN(87, 1, 3, 0x23, 0x70),
PIN(88, 1, 4, 0x23, 0x70),
PIN(89, 1, 5, 0x23, 0x70),
PIN(90, 0, 2, 0x23, 0x60),
PIN(91, 0, 23, 0x23, 0x60),
PIN(92, 0, 25, 0x23, 0x60),
PIN(93, 0, 3, 0x23, 0x60),
PIN(94, 0, 24, 0x23, 0x60),
PIN(95, 0, 26, 0x23, 0x60),
PIN(96, 0, 1, 0x12, 0x50),
PIN(97, 0, 0, 0x12, 0x50),
PIN(98, 0, 2, 0x12, 0x50),
PIN(99, 0, 14, 0x24, 0x40),
PIN(100, 0, 15, 0x24, 0x40),
PIN(101, 0, 13, 0x24, 0x40),
PIN(102, 0, 12, 0x24, 0x40),
PIN(103, 0, 0, 0x24, 0x40),
PIN(104, 0, 1, 0x24, 0x40),
PIN(105, 0, 4, 0x24, 0x40),
PIN(106, 0, 5, 0x24, 0x40),
PIN(107, 0, 6, 0x24, 0x40),
PIN(108, 0, 7, 0x24, 0x40),
PIN(109, 0, 8, 0x24, 0x40),
PIN(110, 0, 9, 0x24, 0x40),
PIN(111, 0, 10, 0x24, 0x40),
PIN(112, 0, 11, 0x24, 0x40),
PIN(113, 0, 2, 0x24, 0x40),
PIN(114, 0, 3, 0x24, 0x40),
PIN(115, 0, 4, 0x23, 0x60),
PIN(116, 0, 7, 0x23, 0x60),
PIN(117, 0, 5, 0x23, 0x60),
PIN(118, 0, 6, 0x23, 0x60),
PIN(119, 0, 22, 0x25, 0x70),
PIN(120, 0, 19, 0x25, 0x70),
PIN(121, 0, 20, 0x25, 0x70),
PIN(122, 0, 21, 0x25, 0x70),
PIN(123, 0, 23, 0x25, 0x70),
PIN(124, 0, 0, 0x25, 0x70),
PIN(125, 0, 1, 0x25, 0x70),
PIN(126, 0, 2, 0x25, 0x70),
PIN(127, 0, 8, 0x23, 0x60),
PIN(128, 0, 10, 0x23, 0x60),
PIN(129, 0, 24, 0x25, 0x70),
PIN(130, 0, 26, 0x25, 0x70),
PIN(131, 0, 25, 0x25, 0x70),
PIN(132, 0, 27, 0x25, 0x70),
PIN(133, 0, 9, 0x21, 0x60),
PIN(134, 0, 12, 0x21, 0x60),
PIN(135, 0, 21, 0x16, 0x40),
PIN(136, 0, 24, 0x16, 0x40),
PIN(137, 0, 10, 0x21, 0x60),
PIN(138, 0, 13, 0x21, 0x60),
PIN(139, 0, 7, 0x12, 0x50),
PIN(140, 0, 8, 0x12, 0x50),
PIN(141, 0, 9, 0x23, 0x60),
PIN(142, 0, 11, 0x23, 0x60),
PIN(143, 0, 22, 0x16, 0x40),
PIN(144, 0, 25, 0x16, 0x40),
PIN(145, 0, 23, 0x16, 0x40),
PIN(146, 0, 26, 0x16, 0x40),
PIN(147, 0, 23, 0x24, 0x40),
PIN(148, 0, 24, 0x24, 0x40),
PIN(149, 0, 25, 0x24, 0x40),
PIN(150, 0, 26, 0x24, 0x40),
PIN(151, 0, 27, 0x24, 0x40),
PIN(152, 0, 28, 0x24, 0x40),
PIN(153, 0, 29, 0x24, 0x40),
PIN(154, 0, 30, 0x24, 0x40),
PIN(155, 0, 31, 0x24, 0x40),
PIN(156, 0, 0, 0x24, 0x50),
PIN(157, 0, 4, 0x12, 0x50),
PIN(158, 0, 3, 0x12, 0x50),
PIN(159, 0, 6, 0x12, 0x50),
PIN(160, 0, 5, 0x12, 0x50),
PIN(161, 0, 23, 0x12, 0x50),
PIN(162, 0, 24, 0x12, 0x50),
PIN(163, 0, 11, 0x21, 0x60),
PIN(164, 0, 8, 0x21, 0x60),
PIN(165, 0, 16, 0x21, 0x60),
PIN(166, 0, 1, 0x21, 0x60),
PIN(167, 0, 7, 0x21, 0x60),
PIN(168, 0, 4, 0x21, 0x60),
PIN(169, 0, 5, 0x21, 0x60),
PIN(170, 0, 0, 0x21, 0x60),
PIN(171, 0, 6, 0x21, 0x60),
PIN(172, 0, 2, 0x21, 0x60),
PIN(173, 0, 3, 0x21, 0x60),
PIN(174, 0, 7, 0x16, 0x40),
PIN(175, 0, 8, 0x16, 0x40),
PIN(176, 0, 4, 0x16, 0x40),
PIN(177, 0, 5, 0x16, 0x40),
PIN(178, 0, 6, 0x16, 0x40),
PIN(179, 0, 9, 0x16, 0x40),
PIN(180, 0, 10, 0x16, 0x40),
PIN(181, 0, 11, 0x16, 0x40),
PIN(182, 0, 12, 0x16, 0x40),
PIN(183, 0, 21, 0x12, 0x50),
PIN(184, 0, 22, 0x12, 0x50),
};
#endif /* MT_GPIO_H */

View File

@ -0,0 +1,31 @@
#
# Copyright (c) 2021, MediaTek Inc. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
MCDI_TINYSYS_TYPE = sspm
MCDI_TINYSYS_MBOX_TYPE = share_sram
CUR_MCDI_FOLDER = ${MTK_PLAT_SOC}/drivers/mcdi
BL31_MT_LPM_PLAT_CFLAGS += -I${CUR_MCDI_FOLDER}/
BL31_MT_LPM_PLAT_SOURCE += \
${CUR_MCDI_FOLDER}/mt_cpu_pm.c \
${CUR_MCDI_FOLDER}/mt_cpu_pm_cpc.c \
${CUR_MCDI_FOLDER}/mt_mcdi.c \
${CUR_MCDI_FOLDER}/mt_lp_irqremain.c
ifeq ($(MCDI_TINYSYS_TYPE), sspm)
BL31_MT_LPM_PLAT_CFLAGS += -DMCDI_TINYSYS_SSPM
BL31_MT_LPM_PLAT_SOURCE += ${CUR_MCDI_FOLDER}/mt_cpu_pm_mbox_sspm.c
else
BL31_MT_LPM_PLAT_CFLAGS += -DMCDI_TINYSYS_MCUPM
BL31_MT_LPM_PLAT_SOURCE += ${CUR_MCDI_FOLDER}/mt_cpu_pm_mbox.c
endif
ifeq ($(MCDI_TINYSYS_MBOX_TYPE), share_sram)
BL31_MT_LPM_PLAT_CFLAGS += -DMCDI_TINYSYS_MBOX_SHARE_SRAM
endif

View File

@ -0,0 +1,123 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <stdint.h>
#include <arch_helpers.h>
#include <lib/psci/psci.h>
#include <lib/spinlock.h>
#include <mt_cpu_pm_cpc.h>
#include <mt_mcdi.h>
#include <plat_mtk_lpm.h>
#include <plat_pm.h>
DEFINE_SYSREG_RW_FUNCS(dbgprcr_el1);
static int plat_mt_lp_cpu_rc;
static int pwr_state_prompt(unsigned int cpu, const psci_power_state_t *state)
{
return 0;
}
static int pwr_state_reflect(unsigned int cpu, const psci_power_state_t *state)
{
mtk_cpc_core_on_hint_clr(cpu);
if (IS_SYSTEM_SUSPEND_STATE(state)) {
mtk_cpc_time_sync();
}
return 0;
}
static int pwr_cpu_pwron(unsigned int cpu, const psci_power_state_t *state)
{
return 0;
}
static int pwr_cpu_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
{
/* clear DBGPRCR.CORENPDRQ to allow CPU power down */
write_dbgprcr_el1(0ULL);
return 0;
}
static int pwr_cluster_pwron(unsigned int cpu, const psci_power_state_t *state)
{
return 0;
}
static int pwr_cluster_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
{
return 0;
}
static int pwr_mcusys_pwron(unsigned int cpu, const psci_power_state_t *state)
{
if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) {
return -1;
}
mtk_cpc_mcusys_off_reflect();
return 0;
}
static int pwr_mcusys_pwron_finished(unsigned int cpu,
const psci_power_state_t *state)
{
if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) {
return -1;
}
return 0;
}
static int pwr_mcusys_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
{
if (!IS_MCUSYS_OFF_STATE(state)) {
goto mt_pwr_mcusysoff_break;
}
if (mcdi_try_init() != 0) { /* not ready to process mcusys-off */
goto mt_pwr_mcusysoff_break;
}
return 0;
mt_pwr_mcusysoff_break:
plat_mt_lp_cpu_rc = -1;
return -1;
}
static const struct mt_lpm_tz plat_pm = {
.pwr_prompt = pwr_state_prompt,
.pwr_reflect = pwr_state_reflect,
.pwr_cpu_on = pwr_cpu_pwron,
.pwr_cpu_dwn = pwr_cpu_pwrdwn,
.pwr_cluster_on = pwr_cluster_pwron,
.pwr_cluster_dwn = pwr_cluster_pwrdwn,
.pwr_mcusys_dwn = pwr_mcusys_pwrdwn,
.pwr_mcusys_on = pwr_mcusys_pwron,
.pwr_mcusys_on_finished = pwr_mcusys_pwron_finished
};
const struct mt_lpm_tz *mt_plat_cpu_pm_init(void)
{
mtk_cpc_init();
if (mcdi_try_init() == 0) {
INFO("MCDI init done.\n");
}
return &plat_pm;
}

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __MT_CPU_PM_H__
#define __MT_CPU_PM_H__
#define MCUSYS_STATUS_PDN (1 << 0UL)
#define MCUSYS_STATUS_CPUSYS_PROTECT (1 << 8UL)
#define MCUSYS_STATUS_MCUSYS_PROTECT (1 << 9UL)
/* cpu_pm function ID*/
enum mt_cpu_pm_user_id {
MCUSYS_STATUS,
CPC_COMMAND,
IRQ_REMAIN_LIST_ALLOC,
IRQ_REMAIN_IRQ_ADD,
IRQ_REMAIN_IRQ_SUBMIT,
MBOX_INFO,
};
/* cpu_pm lp function ID */
enum mt_cpu_pm_lp_smc_id {
LP_CPC_COMMAND,
IRQS_REMAIN_ALLOC,
IRQS_REMAIN_CTRL,
IRQS_REMAIN_IRQ,
IRQS_REMAIN_WAKEUP_CAT,
IRQS_REMAIN_WAKEUP_SRC,
};
#endif

View File

@ -0,0 +1,269 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <string.h>
#include <drivers/delay_timer.h>
#include <mt_cpu_pm_cpc.h>
#include <mt_timer.h>
struct mtk_cpc_dev {
int auto_off;
unsigned int auto_thres_tick;
};
static struct mtk_cpc_dev cpc;
static int mtk_cpc_last_core_prot(uint32_t prot_req,
uint32_t resp_reg, uint32_t resp_ofs)
{
uint32_t sta, retry;
retry = 0U;
while (retry++ < RETRY_CNT_MAX) {
mmio_write_32(CPC_MCUSYS_LAST_CORE_REQ, prot_req);
udelay(1U);
sta = (mmio_read_32(resp_reg) >> resp_ofs) & CPC_PROT_RESP_MASK;
if (sta == PROT_SUCCESS) {
return CPC_SUCCESS;
} else if (sta == PROT_GIVEUP) {
return CPC_ERR_FAIL;
}
}
return CPC_ERR_TIMEOUT;
}
int mtk_cpu_pm_mcusys_prot_aquire(void)
{
return mtk_cpc_last_core_prot(
MCUSYS_PROT_SET,
CPC_MCUSYS_LAST_CORE_RESP,
MCUSYS_RESP_OFS);
}
void mtk_cpu_pm_mcusys_prot_release(void)
{
mmio_write_32(CPC_MCUSYS_PWR_ON_MASK, MCUSYS_PROT_CLR);
}
int mtk_cpu_pm_cluster_prot_aquire(unsigned int cluster)
{
return mtk_cpc_last_core_prot(
CPUSYS_PROT_SET,
CPC_MCUSYS_MP_LAST_CORE_RESP,
CPUSYS_RESP_OFS);
}
void mtk_cpu_pm_cluster_prot_release(unsigned int cluster)
{
mmio_write_32(CPC_MCUSYS_PWR_ON_MASK, CPUSYS_PROT_CLR);
}
static void mtk_cpc_cluster_cnt_backup(void)
{
uint32_t backup_cnt;
uint32_t curr_cnt;
uint32_t cnt_mask = GENMASK(14, 0);
uint32_t clr_mask = GENMASK(1, 0);
/* Single Cluster */
backup_cnt = mmio_read_32(CPC_CLUSTER_CNT_BACKUP);
curr_cnt = mmio_read_32(CPC_MCUSYS_CLUSTER_COUNTER);
/* Get off count if dormant count is 0 */
if ((curr_cnt & cnt_mask) == 0U) {
curr_cnt = (curr_cnt >> 16) & cnt_mask;
} else {
curr_cnt = curr_cnt & cnt_mask;
}
mmio_write_32(CPC_CLUSTER_CNT_BACKUP, backup_cnt + curr_cnt);
mmio_write_32(CPC_MCUSYS_CLUSTER_COUNTER_CLR, clr_mask);
}
static inline void mtk_cpc_mcusys_off_en(void)
{
mmio_write_32(CPC_MCUSYS_PWR_CTRL, 1U);
}
static inline void mtk_cpc_mcusys_off_dis(void)
{
mmio_write_32(CPC_MCUSYS_PWR_CTRL, 0U);
}
void mtk_cpc_mcusys_off_reflect(void)
{
mtk_cpc_mcusys_off_dis();
mtk_cpu_pm_mcusys_prot_release();
}
int mtk_cpc_mcusys_off_prepare(void)
{
if (mtk_cpu_pm_mcusys_prot_aquire() != CPC_SUCCESS) {
return CPC_ERR_FAIL;
}
mtk_cpc_cluster_cnt_backup();
mtk_cpc_mcusys_off_en();
return CPC_SUCCESS;
}
void mtk_cpc_core_on_hint_set(unsigned int cpu)
{
mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_SET, BIT(cpu));
}
void mtk_cpc_core_on_hint_clr(unsigned int cpu)
{
mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu));
}
static void mtk_cpc_dump_timestamp(void)
{
uint32_t id;
for (id = 0U; id < CPC_TRACE_ID_NUM; id++) {
mmio_write_32(CPC_MCUSYS_TRACE_SEL, id);
memcpy((void *)(uintptr_t)CPC_TRACE_SRAM(id),
(const void *)(uintptr_t)CPC_MCUSYS_TRACE_DATA,
CPC_TRACE_SIZE);
}
}
void mtk_cpc_time_sync(void)
{
uint64_t kt;
uint32_t systime_l, systime_h;
kt = sched_clock();
systime_l = mmio_read_32(CNTSYS_L_REG);
systime_h = mmio_read_32(CNTSYS_H_REG);
/* sync kernel timer to cpc */
mmio_write_32(CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE, (uint32_t)kt);
mmio_write_32(CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE, (uint32_t)(kt >> 32));
/* sync system timer to cpc */
mmio_write_32(CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE, systime_l);
mmio_write_32(CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE, systime_h);
}
static void mtk_cpc_config(uint32_t cfg, uint32_t data)
{
uint32_t val;
uint32_t reg = 0U;
switch (cfg) {
case CPC_SMC_CONFIG_PROF:
reg = CPC_MCUSYS_CPC_DBG_SETTING;
val = mmio_read_32(reg);
val = (data != 0U) ? (val | CPC_PROF_EN) : (val & ~CPC_PROF_EN);
break;
case CPC_SMC_CONFIG_AUTO_OFF:
reg = CPC_MCUSYS_CPC_FLOW_CTRL_CFG;
val = mmio_read_32(reg);
if (data != 0U) {
val |= CPC_AUTO_OFF_EN;
cpc.auto_off = 1;
} else {
val &= ~CPC_AUTO_OFF_EN;
cpc.auto_off = 0;
}
break;
case CPC_SMC_CONFIG_AUTO_OFF_THRES:
reg = CPC_MCUSYS_CPC_OFF_THRES;
cpc.auto_thres_tick = us_to_ticks(data);
val = cpc.auto_thres_tick;
break;
case CPC_SMC_CONFIG_CNT_CLR:
reg = CPC_MCUSYS_CLUSTER_COUNTER_CLR;
val = GENMASK(1, 0); /* clr_mask */
break;
case CPC_SMC_CONFIG_TIME_SYNC:
mtk_cpc_time_sync();
break;
default:
break;
}
if (reg != 0U) {
mmio_write_32(reg, val);
}
}
static uint32_t mtk_cpc_read_config(uint32_t cfg)
{
uint32_t res = 0U;
switch (cfg) {
case CPC_SMC_CONFIG_PROF:
res = (mmio_read_32(CPC_MCUSYS_CPC_DBG_SETTING) & CPC_PROF_EN) ?
1U : 0U;
break;
case CPC_SMC_CONFIG_AUTO_OFF:
res = cpc.auto_off;
break;
case CPC_SMC_CONFIG_AUTO_OFF_THRES:
res = ticks_to_us(cpc.auto_thres_tick);
break;
case CPC_SMC_CONFIG_CNT_CLR:
break;
default:
break;
}
return res;
}
uint64_t mtk_cpc_handler(uint64_t act, uint64_t arg1, uint64_t arg2)
{
uint64_t res = 0ULL;
switch (act) {
case CPC_SMC_EVENT_DUMP_TRACE_DATA:
mtk_cpc_dump_timestamp();
break;
case CPC_SMC_EVENT_GIC_DPG_SET:
/* isolated_status = x2; */
break;
case CPC_SMC_EVENT_CPC_CONFIG:
mtk_cpc_config((uint32_t)arg1, (uint32_t)arg2);
break;
case CPC_SMC_EVENT_READ_CONFIG:
res = mtk_cpc_read_config((uint32_t)arg1);
break;
default:
break;
}
return res;
}
void mtk_cpc_init(void)
{
mmio_write_32(CPC_MCUSYS_CPC_DBG_SETTING,
mmio_read_32(CPC_MCUSYS_CPC_DBG_SETTING)
| CPC_DBG_EN
| CPC_CALC_EN);
cpc.auto_off = 1;
cpc.auto_thres_tick = us_to_ticks(8000);
mmio_write_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG,
mmio_read_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG)
| CPC_OFF_PRE_EN
| (cpc.auto_off ? CPC_AUTO_OFF_EN : 0U));
mmio_write_32(CPC_MCUSYS_CPC_OFF_THRES, cpc.auto_thres_tick);
}

View File

@ -0,0 +1,102 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MT_CPU_PM_CPC_H
#define MT_CPU_PM_CPC_H
#include <lib/mmio.h>
#include <lib/utils_def.h>
#include <mcucfg.h>
#include <platform_def.h>
#define NEED_CPUSYS_PROT_WORKAROUND 1
/* system sram registers */
#define CPUIDLE_SRAM_REG(r) (0x11B000 + (r))
/* db dump */
#define CPC_TRACE_SIZE U(0x20)
#define CPC_TRACE_ID_NUM U(10)
#define CPC_TRACE_SRAM(id) (CPUIDLE_SRAM_REG(0x10) + (id) * CPC_TRACE_SIZE)
/* buckup off count */
#define CPC_CLUSTER_CNT_BACKUP CPUIDLE_SRAM_REG(0x1F0)
#define CPC_MCUSYS_CNT CPUIDLE_SRAM_REG(0x1F4)
/* CPC_MCUSYS_CPC_FLOW_CTRL_CFG(0xA814): debug setting */
#define CPC_PWR_ON_SEQ_DIS BIT(1)
#define CPC_PWR_ON_PRIORITY BIT(2)
#define CPC_AUTO_OFF_EN BIT(5)
#define CPC_DORMANT_WAIT_EN BIT(14)
#define CPC_CTRL_EN BIT(16)
#define CPC_OFF_PRE_EN BIT(29)
/* CPC_MCUSYS_LAST_CORE_REQ(0xA818) : last core protection */
#define CPUSYS_PROT_SET BIT(0)
#define MCUSYS_PROT_SET BIT(8)
#define CPUSYS_PROT_CLR BIT(8)
#define MCUSYS_PROT_CLR BIT(9)
#define CPC_PROT_RESP_MASK U(0x3)
#define CPUSYS_RESP_OFS U(16)
#define MCUSYS_RESP_OFS U(30)
#define cpusys_resp(r) (((r) >> CPUSYS_RESP_OFS) & CPC_PROT_RESP_MASK)
#define mcusys_resp(r) (((r) >> MCUSYS_RESP_OFS) & CPC_PROT_RESP_MASK)
#define RETRY_CNT_MAX U(1000)
#define PROT_RETRY U(0)
#define PROT_SUCCESS U(1)
#define PROT_GIVEUP U(2)
/* CPC_MCUSYS_CPC_DBG_SETTING(0xAB00): debug setting */
#define CPC_PROF_EN BIT(0)
#define CPC_DBG_EN BIT(1)
#define CPC_FREEZE BIT(2)
#define CPC_CALC_EN BIT(3)
enum {
CPC_SUCCESS = 0U,
CPC_ERR_FAIL = 1U,
CPC_ERR_TIMEOUT = 2U,
NF_CPC_ERR = 3U,
};
enum {
CPC_SMC_EVENT_DUMP_TRACE_DATA = 0U,
CPC_SMC_EVENT_GIC_DPG_SET = 1U,
CPC_SMC_EVENT_CPC_CONFIG = 2U,
CPC_SMC_EVENT_READ_CONFIG = 3U,
NF_CPC_SMC_EVENT = 4U,
};
enum {
CPC_SMC_CONFIG_PROF = 0U,
CPC_SMC_CONFIG_AUTO_OFF = 1U,
CPC_SMC_CONFIG_AUTO_OFF_THRES = 2U,
CPC_SMC_CONFIG_CNT_CLR = 3U,
CPC_SMC_CONFIG_TIME_SYNC = 4U,
NF_CPC_SMC_CONFIG = 5U,
};
#define us_to_ticks(us) ((us) * 13)
#define ticks_to_us(tick) ((tick) / 13)
int mtk_cpu_pm_cluster_prot_aquire(unsigned int cluster);
void mtk_cpu_pm_cluster_prot_release(unsigned int cluster);
void mtk_cpc_mcusys_off_reflect(void);
int mtk_cpc_mcusys_off_prepare(void);
void mtk_cpc_core_on_hint_set(unsigned int cpu);
void mtk_cpc_core_on_hint_clr(unsigned int cpu);
void mtk_cpc_time_sync(void);
uint64_t mtk_cpc_handler(uint64_t act, uint64_t arg1, uint64_t arg2);
void mtk_cpc_init(void);
#endif /* MT_CPU_PM_CPC_H */

View File

@ -0,0 +1,79 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <mmio.h>
#include <mt_cpu_pm_mbox.h>
#include <platform_def.h>
#include <sspm_reg.h>
#define MCUPM_MBOX_3_BASE (MTK_MCUPM_SRAM_BASE + 0xFCE0)
#define _sspm_mbox_write(id, val) \
mmio_write_32(SSPM_MBOX_3_BASE + 4 * (id), val)
#define _sspm_mbox_read(id) \
mmio_read_32(SSPM_MBOX_3_BASE + 4 * (id))
#define _mcupm_mbox_write(id, val) \
mmio_write_32(MCUPM_MBOX_3_BASE + 4 * (id), val)
#define _mcupm_mbox_read(id) \
mmio_read_32(MCUPM_MBOX_3_BASE + 4 * (id))
#define MCUPM_MBOX_OFFSET_PDN (0x0C55FDA8)
#define MCUPM_POWER_DOWN (0x4D50444E)
void mtk_set_sspm_lp_cmd(void *buf, unsigned int size)
{
unsigned int *p = (unsigned int *)buf;
int i;
for (i = 0; i < size; i++) {
_sspm_mbox_write(SSPM_MBOX_SPM_CMD + i, p[i]);
}
}
void mtk_clr_sspm_lp_cmd(unsigned int size)
{
int i;
for (i = 0; i < size; i++) {
_sspm_mbox_write(SSPM_MBOX_SPM_CMD + i, 0);
}
}
void mtk_set_cpu_pm_pll_mode(unsigned int mode)
{
if (mode < NF_MCUPM_ARMPLL_MODE) {
_mcupm_mbox_write(MCUPM_MBOX_ARMPLL_MODE, mode);
}
}
int mtk_get_cpu_pm_pll_mode(void)
{
return _mcupm_mbox_read(MCUPM_MBOX_ARMPLL_MODE);
}
void mtk_set_cpu_pm_buck_mode(unsigned int mode)
{
if (mode < NF_MCUPM_BUCK_MODE) {
_mcupm_mbox_write(MCUPM_MBOX_BUCK_MODE, mode);
}
}
int mtk_get_cpu_pm_buck_mode(void)
{
return _mcupm_mbox_read(MCUPM_MBOX_BUCK_MODE);
}
void mtk_set_cpu_pm_preffered_cpu(unsigned int cpuid)
{
return _mcupm_mbox_read(MCUPM_MBOX_WAKEUP_CPU);
}
int mtk_set_cpu_pm_mbox_addr(uint64_t phy_addr)
{
return 0;
}

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __MT_CPU_PM_MBOX_H__
#define __MT_CPU_PM_MBOX_H__
/* SSPM Mbox */
/* AP Write */
#define SSPM_MBOX_SPM_CMD (0U)
#define SSPM_MBOX_SPM_ARGS1 (1U)
#define SSPM_MBOX_SPM_ARGS2 (2U)
#define SSPM_MBOX_SPM_ARGS3 (3U)
#define SSPM_MBOX_SPM_ARGS4 (4U)
#define SSPM_MBOX_SPM_ARGS5 (5U)
#define SSPM_MBOX_SPM_ARGS6 (6U)
#define SSPM_MBOX_SPM_ARGS7 (7U)
#define SSPM_MBOX_AP_READY (17U)
#define SSPM_MBOX_SPM_CMD_SIZE (8U)
void mtk_set_sspm_lp_cmd(void *buf, unsigned int size);
void mtk_clr_sspm_lp_cmd(unsigned int size);
/* MCUPM Mbox */
/* AP Write */
#define MCUPM_MBOX_AP_READY (0U)
#define MCUPM_MBOX_RESERVED_1 (1U)
#define MCUPM_MBOX_RESERVED_2 (2U)
#define MCUPM_MBOX_RESERVED_3 (3U)
#define MCUPM_MBOX_PWR_CTRL_EN (4U)
#define MCUPM_MBOX_L3_CACHE_MODE (5U)
#define MCUPM_MBOX_BUCK_MODE (6U)
#define MCUPM_MBOX_ARMPLL_MODE (7U)
/* AP Read */
#define MCUPM_MBOX_TASK_STA (8U)
#define MCUPM_MBOX_RESERVED_9 (9U)
#define MCUPM_MBOX_RESERVED_10 (10U)
#define MCUPM_MBOX_RESERVED_11 (11U)
/* CPC mode - Read/Write */
#define MCUPM_MBOX_WAKEUP_CPU (12U)
/* Mbox Slot: APMCU_MCUPM_MBOX_PWR_CTRL_EN (4) */
#define MCUPM_MCUSYS_CTRL (1U << 0)
#define MCUPM_BUCK_CTRL (1U << 1)
#define MCUPM_ARMPLL_CTRL (1U << 2)
#define MCUPM_PWR_CTRL_MASK ((1U << 3) - 1U)
/* Mbox Slot: APMCU_MCUPM_MBOX_L3_CACHE_MODE (5) */
#define MCUPM_L3_OFF_MODE (0U) /* default */
#define MCUPM_L3_DORMANT_MODE (1U)
#define NF_MCUPM_L3_MODE (2U)
/* Mbox Slot: APMCU_MCUPM_MBOX_BUCK_MODE (6) */
#define MCUPM_BUCK_NORMAL_MODE (0U) /* default */
#define MCUPM_BUCK_LP_MODE (1U)
#define MCUPM_BUCK_OFF_MODE (2U)
#define NF_MCUPM_BUCK_MODE (3U)
/* Mbox Slot: APMCU_MCUPM_MBOX_ARMPLL_MODE (7) */
#define MCUPM_ARMPLL_ON (0U) /* default */
#define MCUPM_ARMPLL_GATING (1U)
#define MCUPM_ARMPLL_OFF (2U)
#define NF_MCUPM_ARMPLL_MODE (3U)
/* Mbox Slot: APMCU_MCUPM_MBOX_TASK_STA (9) */
#define MCUPM_TASK_UNINIT (0U)
#define MCUPM_TASK_INIT (1U)
#define MCUPM_TASK_INIT_FINISH (2U)
#define MCUPM_TASK_WAIT (3U)
#define MCUPM_TASK_RUN (4U)
#define MCUPM_TASK_PAUSE (5U)
void mtk_set_cpu_pm_pll_mode(unsigned int mode);
int mtk_get_cpu_pm_pll_mode(void);
void mtk_set_cpu_pm_buck_mode(unsigned int mode);
int mtk_get_cpu_pm_buck_mode(void);
void mtk_set_cpu_pm_preffered_cpu(unsigned int cpuid);
int mtk_set_cpu_pm_mbox_addr(uint64_t phy_addr);
#endif

View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <mmio.h>
#include <mt_cpu_pm.h>
#include <mt_cpu_pm_mbox.h>
#include <platform_def.h>
#include <sspm_reg.h>
#ifdef MCDI_TINYSYS_MBOX_SHARE_SRAM
struct cpu_pm_mbox {
unsigned int ap_ready;
unsigned int reserved1;
unsigned int reserved2;
unsigned int reserved3;
unsigned int pwr_ctrl_en;
unsigned int l3_cache_mode;
unsigned int buck_mode;
unsigned int armpll_mode;
unsigned int task_sta;
unsigned int reserved9;
unsigned int reserved10;
unsigned int reserved11;
unsigned int wakeup_cpu;
};
struct cpu_pm_mbox *_cpu_pm_box = (struct cpu_pm_mbox *)SSPM_MBOX_3_BASE;
#endif
void mtk_set_cpu_pm_pll_mode(unsigned int mode)
{
#ifdef MCDI_TINYSYS_MBOX_SHARE_SRAM
if (_cpu_pm_box) {
_cpu_pm_box->armpll_mode = mode;
}
#endif
}
int mtk_get_cpu_pm_pll_mode(void)
{
#ifdef MCDI_TINYSYS_MBOX_SHARE_SRAM
if (!_cpu_pm_box) {
return 0;
}
return _cpu_pm_box->armpll_mode;
#endif
}
void mtk_set_cpu_pm_buck_mode(unsigned int mode)
{
#ifdef MCDI_TINYSYS_MBOX_SHARE_SRAM
if (_cpu_pm_box) {
_cpu_pm_box->buck_mode = mode;
}
#endif
}
int mtk_get_cpu_pm_buck_mode(void)
{
#ifdef MCDI_TINYSYS_MBOX_SHARE_SRAM
if (!_cpu_pm_box) {
return 0;
}
return _cpu_pm_box->buck_mode;
#endif
}
void mtk_set_cpu_pm_preffered_cpu(unsigned int cpuid)
{
#ifdef MCDI_TINYSYS_MBOX_SHARE_SRAM
if (_cpu_pm_box) {
_cpu_pm_box->wakeup_cpu = cpuid;
}
#endif
}
int mtk_set_cpu_pm_mbox_addr(uint64_t phy_addr)
{
#ifdef MCDI_TINYSYS_MBOX_SHARE_SRAM
if (_cpu_pm_box || (phy_addr == 0)) {
return -1;
}
_cpu_pm_box = (struct cpu_pm_mbox *)(MTK_SSPM_BASE + phy_addr);
#endif
return 0;
}

View File

@ -0,0 +1,150 @@
/*
* 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>
#include <mt_mcdi.h>
/* Read/Write */
#define APMCU_MCUPM_MBOX_AP_READY U(0)
#define APMCU_MCUPM_MBOX_RESERVED_1 U(1)
#define APMCU_MCUPM_MBOX_RESERVED_2 U(2)
#define APMCU_MCUPM_MBOX_RESERVED_3 U(3)
#define APMCU_MCUPM_MBOX_PWR_CTRL_EN U(4)
#define APMCU_MCUPM_MBOX_L3_CACHE_MODE U(5)
#define APMCU_MCUPM_MBOX_BUCK_MODE U(6)
#define APMCU_MCUPM_MBOX_ARMPLL_MODE U(7)
/* Read only */
#define APMCU_MCUPM_MBOX_TASK_STA U(8)
#define APMCU_MCUPM_MBOX_RESERVED_9 U(9)
#define APMCU_MCUPM_MBOX_RESERVED_10 U(10)
#define APMCU_MCUPM_MBOX_RESERVED_11 U(11)
/* CPC mode - Read/Write */
#define APMCU_MCUPM_MBOX_WAKEUP_CPU U(12)
/* Mbox Slot: APMCU_MCUPM_MBOX_PWR_CTRL_EN */
#define MCUPM_MCUSYS_CTRL BIT(0)
#define MCUPM_BUCK_CTRL BIT(1)
#define MCUPM_ARMPLL_CTRL BIT(2)
#define MCUPM_CM_CTRL BIT(3)
#define MCUPM_PWR_CTRL_MASK GENMASK(3, 0)
/* Mbox Slot: APMCU_MCUPM_MBOX_BUCK_MODE */
#define MCUPM_BUCK_NORMAL_MODE U(0) /* default */
#define MCUPM_BUCK_LP_MODE U(1)
#define MCUPM_BUCK_OFF_MODE U(2)
#define NF_MCUPM_BUCK_MODE U(3)
/* Mbox Slot: APMCU_MCUPM_MBOX_ARMPLL_MODE */
#define MCUPM_ARMPLL_ON U(0) /* default */
#define MCUPM_ARMPLL_GATING U(1)
#define MCUPM_ARMPLL_OFF U(2)
#define NF_MCUPM_ARMPLL_MODE U(3)
/* Mbox Slot: APMCU_MCUPM_MBOX_TASK_STA */
#define MCUPM_TASK_UNINIT U(0)
#define MCUPM_TASK_INIT U(1)
#define MCUPM_TASK_INIT_FINISH U(2)
#define MCUPM_TASK_WAIT U(3)
#define MCUPM_TASK_RUN U(4)
#define MCUPM_TASK_PAUSE U(5)
#define SSPM_MBOX_3_BASE U(0x10420000)
#define MCDI_NOT_INIT U(0)
#define MCDI_INIT_1 U(1)
#define MCDI_INIT_2 U(2)
#define MCDI_INIT_DONE U(3)
static int mcdi_init_status __section("tzfw_coherent_mem");
static inline uint32_t mcdi_mbox_read(uint32_t id)
{
return mmio_read_32(SSPM_MBOX_3_BASE + (id << 2));
}
static inline void mcdi_mbox_write(uint32_t id, uint32_t val)
{
mmio_write_32(SSPM_MBOX_3_BASE + (id << 2), val);
}
static void mtk_mcupm_pwr_ctrl_setting(uint32_t dev)
{
mcdi_mbox_write(APMCU_MCUPM_MBOX_PWR_CTRL_EN, dev);
}
static void mtk_set_mcupm_pll_mode(uint32_t mode)
{
if (mode < NF_MCUPM_ARMPLL_MODE) {
mcdi_mbox_write(APMCU_MCUPM_MBOX_ARMPLL_MODE, mode);
}
}
static void mtk_set_mcupm_buck_mode(uint32_t mode)
{
if (mode < NF_MCUPM_BUCK_MODE) {
mcdi_mbox_write(APMCU_MCUPM_MBOX_BUCK_MODE, mode);
}
}
static int mtk_mcupm_is_ready(void)
{
unsigned int sta = mcdi_mbox_read(APMCU_MCUPM_MBOX_TASK_STA);
return ((sta == MCUPM_TASK_WAIT) || (sta == MCUPM_TASK_INIT_FINISH));
}
static int mcdi_init_1(void)
{
unsigned int sta = mcdi_mbox_read(APMCU_MCUPM_MBOX_TASK_STA);
if (sta != MCUPM_TASK_INIT) {
return -1;
}
mtk_set_mcupm_pll_mode(MCUPM_ARMPLL_OFF);
mtk_set_mcupm_buck_mode(MCUPM_BUCK_OFF_MODE);
mtk_mcupm_pwr_ctrl_setting(
MCUPM_MCUSYS_CTRL |
MCUPM_BUCK_CTRL |
MCUPM_ARMPLL_CTRL);
mcdi_mbox_write(APMCU_MCUPM_MBOX_AP_READY, 1);
return 0;
}
static int mcdi_init_2(void)
{
return mtk_mcupm_is_ready() ? 0 : -1;
}
int mcdi_try_init(void)
{
if (mcdi_init_status == MCDI_INIT_DONE) {
return 0;
}
if (mcdi_init_status == MCDI_NOT_INIT) {
mcdi_init_status = MCDI_INIT_1;
}
if (mcdi_init_status == MCDI_INIT_1 && mcdi_init_1() == 0) {
mcdi_init_status = MCDI_INIT_2;
}
if (mcdi_init_status == MCDI_INIT_2 && mcdi_init_2() == 0) {
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;
}

View File

@ -0,0 +1,12 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MT_MCDI_H
#define MT_MCDI_H
int mcdi_try_init(void);
#endif /* MT_MCDI_H */

View File

@ -0,0 +1,23 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common/debug.h>
#include <pmic.h>
#include <pmic_wrap_init.h>
uint32_t pmic_get_hwcid(void)
{
uint32_t val = 0;
pwrap_read(PMIC_RG_HWCID_ADDR, &val);
return val;
}
void pmic_power_off(void)
{
pwrap_write(PMIC_PWRHOLD, 0x0);
}

View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PMIC_H
#define PMIC_H
#include <stdint.h>
#define PMIC_RG_HWCID_ADDR 0x8
#define PMIC_PWRHOLD 0xa08
/* external API */
uint32_t pmic_get_hwcid(void);
void pmic_power_off(void);
#endif /* PMIC_H */

View File

@ -0,0 +1,94 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PMIC_WRAP_INIT_H
#define PMIC_WRAP_INIT_H
#include <stdint.h>
#include "platform_def.h"
/* external API */
int32_t pwrap_read(uint32_t adr, uint32_t *rdata);
int32_t pwrap_write(uint32_t adr, uint32_t wdata);
static struct mt8186_pmic_wrap_regs *const mtk_pwrap = (void *)PMIC_WRAP_BASE;
/* timeout setting */
enum {
TIMEOUT_RESET = 50, /* us */
TIMEOUT_READ = 50, /* us */
TIMEOUT_WAIT_IDLE = 50 /* us */
};
/* PMIC_WRAP registers */
struct mt8186_pmic_wrap_regs {
uint32_t unused[776];
uint32_t wacs2_cmd;
uint32_t wacs2_rdata;
uint32_t wacs2_vldclr;
};
enum {
RDATA_WACS_RDATA_SHIFT = 0,
RDATA_WACS_FSM_SHIFT = 16,
RDATA_WACS_REQ_SHIFT = 19,
RDATA_SYNC_IDLE_SHIFT = 20,
RDATA_INIT_DONE_SHIFT = 22,
RDATA_SYS_IDLE_SHIFT = 23,
};
enum {
RDATA_WACS_RDATA_MASK = 0xffff,
RDATA_WACS_FSM_MASK = 0x7,
RDATA_WACS_REQ_MASK = 0x1,
RDATA_SYNC_IDLE_MASK = 0x1,
RDATA_INIT_DONE_MASK = 0x1,
RDATA_SYS_IDLE_MASK = 0x1,
};
/* WACS_FSM */
enum {
WACS_FSM_IDLE = 0x00,
WACS_FSM_REQ = 0x02,
WACS_FSM_WFDLE = 0x04,
WACS_FSM_WFVLDCLR = 0x06,
WACS_INIT_DONE = 0x01,
WACS_SYNC_IDLE = 0x01,
WACS_SYNC_BUSY = 0x00
};
/* error information flag */
enum {
E_PWR_INVALID_ARG = 1,
E_PWR_INVALID_RW = 2,
E_PWR_INVALID_ADDR = 3,
E_PWR_INVALID_WDAT = 4,
E_PWR_INVALID_OP_MANUAL = 5,
E_PWR_NOT_IDLE_STATE = 6,
E_PWR_NOT_INIT_DONE = 7,
E_PWR_NOT_INIT_DONE_READ = 8,
E_PWR_WAIT_IDLE_TIMEOUT = 9,
E_PWR_WAIT_IDLE_TIMEOUT_READ = 10,
E_PWR_INIT_SIDLY_FAIL = 11,
E_PWR_RESET_TIMEOUT = 12,
E_PWR_TIMEOUT = 13,
E_PWR_INIT_RESET_SPI = 20,
E_PWR_INIT_SIDLY = 21,
E_PWR_INIT_REG_CLOCK = 22,
E_PWR_INIT_ENABLE_PMIC = 23,
E_PWR_INIT_DIO = 24,
E_PWR_INIT_CIPHER = 25,
E_PWR_INIT_WRITE_TEST = 26,
E_PWR_INIT_ENABLE_CRC = 27,
E_PWR_INIT_ENABLE_DEWRAP = 28,
E_PWR_INIT_ENABLE_EVENT = 29,
E_PWR_READ_TEST_FAIL = 30,
E_PWR_WRITE_TEST_FAIL = 31,
E_PWR_SWITCH_DIO = 32
};
#endif /* PMIC_WRAP_INIT_H */

View File

@ -0,0 +1,133 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <rtc.h>
static void RTC_Config_Interface(uint32_t addr, uint16_t data,
uint16_t MASK, uint16_t SHIFT)
{
uint16_t pmic_reg = 0;
pmic_reg = RTC_Read(addr);
pmic_reg &= ~(MASK << SHIFT);
pmic_reg |= (data << SHIFT);
RTC_Write(addr, pmic_reg);
}
static void rtc_disable_2sec_reboot(void)
{
uint16_t reboot;
reboot = (RTC_Read(RTC_AL_SEC) & ~RTC_BBPU_2SEC_EN) &
~RTC_BBPU_AUTO_PDN_SEL;
RTC_Write(RTC_AL_SEC, reboot);
RTC_Write_Trigger();
}
static void rtc_xosc_write(uint16_t val, bool reload)
{
uint16_t bbpu;
RTC_Write(RTC_OSC32CON, RTC_OSC32CON_UNLOCK1);
rtc_busy_wait();
RTC_Write(RTC_OSC32CON, RTC_OSC32CON_UNLOCK2);
rtc_busy_wait();
RTC_Write(RTC_OSC32CON, val);
rtc_busy_wait();
if (reload) {
bbpu = RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD;
RTC_Write(RTC_BBPU, bbpu);
RTC_Write_Trigger();
}
}
static void rtc_enable_k_eosc(void)
{
uint16_t osc32;
uint16_t rtc_eosc_cali_td = 8; /* eosc cali period time */
/* Truning on eosc cali mode clock */
RTC_Config_Interface(PMIC_RG_TOP_CON, 1,
PMIC_RG_SRCLKEN_IN0_HW_MODE_MASK,
PMIC_RG_SRCLKEN_IN0_HW_MODE_SHIFT);
RTC_Config_Interface(PMIC_RG_TOP_CON, 1,
PMIC_RG_SRCLKEN_IN1_HW_MODE_MASK,
PMIC_RG_SRCLKEN_IN1_HW_MODE_SHIFT);
RTC_Config_Interface(PMIC_RG_SCK_TOP_CKPDN_CON0, 0,
PMIC_RG_RTC_EOSC32_CK_PDN_MASK,
PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT);
switch (rtc_eosc_cali_td) {
case 1:
RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x3,
PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
break;
case 2:
RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x4,
PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
break;
case 4:
RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x5,
PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
break;
case 16:
RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x7,
PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
break;
default:
RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x6,
PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
break;
}
/* Switch the DCXO from 32k-less mode to RTC mode,
* otherwise, EOSC cali will fail
*/
/* RTC mode will have only OFF mode and FPM */
RTC_Config_Interface(PMIC_RG_DCXO_CW02, 0, PMIC_RG_XO_EN32K_MAN_MASK,
PMIC_RG_XO_EN32K_MAN_SHIFT);
RTC_Write(RTC_BBPU,
RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD);
RTC_Write_Trigger();
/* Enable K EOSC mode for normal power off and then plug out battery */
RTC_Write(RTC_AL_YEA, ((RTC_Read(RTC_AL_YEA) | RTC_K_EOSC_RSV_0)
& (~RTC_K_EOSC_RSV_1)) | RTC_K_EOSC_RSV_2);
RTC_Write_Trigger();
osc32 = RTC_Read(RTC_OSC32CON);
rtc_xosc_write(osc32 | RTC_EMBCK_SRC_SEL, true);
INFO("[RTC] RTC_enable_k_eosc\n");
}
void rtc_power_off_sequence(void)
{
uint16_t bbpu;
rtc_disable_2sec_reboot();
rtc_enable_k_eosc();
/* clear alarm */
bbpu = RTC_BBPU_KEY | RTC_BBPU_CLR | RTC_BBPU_PWREN;
if (Writeif_unlock()) {
RTC_Write(RTC_BBPU, bbpu);
RTC_Write(RTC_AL_MASK, RTC_AL_MASK_DOW);
RTC_Write_Trigger();
mdelay(1);
bbpu = RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD;
RTC_Write(RTC_BBPU, bbpu);
RTC_Write_Trigger();
INFO("[RTC] BBPU=0x%x, IRQ_EN=0x%x, AL_MSK=0x%x, AL_SEC=0x%x\n",
RTC_Read(RTC_BBPU), RTC_Read(RTC_IRQ_EN),
RTC_Read(RTC_AL_MASK), RTC_Read(RTC_AL_SEC));
}
}

View File

@ -0,0 +1,145 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef RTC_H
#define RTC_H
#define PMIC_RG_SRCLKEN_IN0_HW_MODE_MASK (1U)
#define PMIC_RG_SRCLKEN_IN0_HW_MODE_SHIFT (1U)
#define PMIC_RG_SRCLKEN_IN1_HW_MODE_MASK (1U)
#define PMIC_RG_SRCLKEN_IN1_HW_MODE_SHIFT (3U)
#define PMIC_RG_RTC_EOSC32_CK_PDN_MASK (1U)
#define PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT (2U)
#define PMIC_RG_EOSC_CALI_TD_MASK (7U)
#define PMIC_RG_EOSC_CALI_TD_SHIFT (5U)
#define PMIC_RG_XO_EN32K_MAN_MASK (1U)
#define PMIC_RG_XO_EN32K_MAN_SHIFT (0U)
/* RTC registers */
enum {
RTC_BBPU = 0x0588,
RTC_IRQ_STA = 0x058A,
RTC_IRQ_EN = 0x058C,
RTC_CII_EN = 0x058E
};
enum {
RTC_AL_SEC = 0x05A0,
RTC_AL_MIN = 0x05A2,
RTC_AL_HOU = 0x05A4,
RTC_AL_DOM = 0x05A6,
RTC_AL_DOW = 0x05A8,
RTC_AL_MTH = 0x05AA,
RTC_AL_YEA = 0x05AC,
RTC_AL_MASK = 0x0590
};
enum {
RTC_OSC32CON = 0x05AE,
RTC_CON = 0x05C4,
RTC_WRTGR = 0x05C2
};
enum {
RTC_PDN1 = 0x05B4,
RTC_PDN2 = 0x05B6,
RTC_SPAR0 = 0x05B8,
RTC_SPAR1 = 0x05BA,
RTC_PROT = 0x05BC,
RTC_DIFF = 0x05BE,
RTC_CALI = 0x05C0
};
enum {
RTC_OSC32CON_UNLOCK1 = 0x1A57,
RTC_OSC32CON_UNLOCK2 = 0x2B68
};
enum {
RTC_PROT_UNLOCK1 = 0x586A,
RTC_PROT_UNLOCK2 = 0x9136
};
enum {
RTC_BBPU_PWREN = 1U << 0,
RTC_BBPU_CLR = 1U << 1,
RTC_BBPU_INIT = 1U << 2,
RTC_BBPU_AUTO = 1U << 3,
RTC_BBPU_CLRPKY = 1U << 4,
RTC_BBPU_RELOAD = 1U << 5,
RTC_BBPU_CBUSY = 1U << 6
};
enum {
RTC_AL_MASK_SEC = 1U << 0,
RTC_AL_MASK_MIN = 1U << 1,
RTC_AL_MASK_HOU = 1U << 2,
RTC_AL_MASK_DOM = 1U << 3,
RTC_AL_MASK_DOW = 1U << 4,
RTC_AL_MASK_MTH = 1U << 5,
RTC_AL_MASK_YEA = 1U << 6
};
enum {
RTC_BBPU_AUTO_PDN_SEL = 1U << 6,
RTC_BBPU_2SEC_CK_SEL = 1U << 7,
RTC_BBPU_2SEC_EN = 1U << 8,
RTC_BBPU_2SEC_MODE = 0x3 << 9,
RTC_BBPU_2SEC_STAT_CLEAR = 1U << 11,
RTC_BBPU_2SEC_STAT_STA = 1U << 12
};
enum {
RTC_BBPU_KEY = 0x43 << 8
};
enum {
RTC_EMBCK_SRC_SEL = 1 << 8,
RTC_EMBCK_SEL_MODE = 3 << 6,
RTC_XOSC32_ENB = 1 << 5,
RTC_REG_XOSC32_ENB = 1 << 15
};
enum {
RTC_K_EOSC_RSV_0 = 1 << 8,
RTC_K_EOSC_RSV_1 = 1 << 9,
RTC_K_EOSC_RSV_2 = 1 << 10
};
/* PMIC TOP Register Definition */
enum {
PMIC_RG_TOP_CON = 0x001E,
PMIC_RG_TOP_CKPDN_CON1 = 0x0112,
PMIC_RG_TOP_CKPDN_CON1_SET = 0x0114,
PMIC_RG_TOP_CKPDN_CON1_CLR = 0x0116,
PMIC_RG_TOP_CKSEL_CON0 = 0x0118,
PMIC_RG_TOP_CKSEL_CON0_SET = 0x011A,
PMIC_RG_TOP_CKSEL_CON0_CLR = 0x011C
};
/* PMIC SCK Register Definition */
enum {
PMIC_RG_SCK_TOP_CKPDN_CON0 = 0x051A,
PMIC_RG_SCK_TOP_CKPDN_CON0_SET = 0x051C,
PMIC_RG_SCK_TOP_CKPDN_CON0_CLR = 0x051E,
PMIC_RG_EOSC_CALI_CON0 = 0x540
};
/* PMIC DCXO Register Definition */
enum {
PMIC_RG_DCXO_CW00 = 0x0788,
PMIC_RG_DCXO_CW02 = 0x0790
};
/* external API */
uint16_t RTC_Read(uint32_t addr);
void RTC_Write(uint32_t addr, uint16_t data);
int32_t rtc_busy_wait(void);
int32_t RTC_Write_Trigger(void);
int32_t Writeif_unlock(void);
void rtc_power_off_sequence(void);
#endif /* RTC_H */

View File

@ -0,0 +1,172 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <lib/mmio.h>
#include <mcucfg.h>
#include <mtspmc.h>
#include <mtspmc_private.h>
#include <plat/common/platform.h>
void mcucfg_disable_gic_wakeup(unsigned int cluster, unsigned int cpu)
{
mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu));
}
void mcucfg_enable_gic_wakeup(unsigned int cluster, unsigned int cpu)
{
mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu));
/* Clear cpu's cpc sw hint */
mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu));
}
void mcucfg_set_bootaddr(unsigned int cluster, unsigned int cpu, uintptr_t bootaddr)
{
assert(cluster == 0U);
mmio_write_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR), bootaddr);
}
uintptr_t mcucfg_get_bootaddr(unsigned int cluster, unsigned int cpu)
{
assert(cluster == 0U);
return (uintptr_t)mmio_read_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR));
}
void mcucfg_init_archstate(unsigned int cluster, unsigned int cpu, bool arm64)
{
uint32_t reg;
assert(cluster == 0U);
reg = per_cluster(cluster, MCUCFG_INITARCH);
if (arm64) {
mmio_setbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu));
} else {
mmio_clrbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu));
}
}
/*
* Return subsystem's power state.
*
* @mask: mask to SPM_CPU_PWR_STATUS to query the power state
* of one subsystem.
* RETURNS:
* 0 (the subsys was powered off)
* 1 (the subsys was powered on)
*/
bool spm_get_powerstate(uint32_t mask)
{
return (mmio_read_32(SPM_CPU_PWR_STATUS) & mask);
}
bool spm_get_cluster_powerstate(unsigned int cluster)
{
assert(cluster == 0U);
return spm_get_powerstate(MP0_CPUTOP);
}
bool spm_get_cpu_powerstate(unsigned int cluster, unsigned int cpu)
{
uint32_t mask = BIT(cpu);
assert(cluster == 0U);
return spm_get_powerstate(mask);
}
int spmc_init(void)
{
unsigned int cpu = plat_my_core_pos();
INFO("SPM: enable CPC mode\n");
mmio_write_32(SPM_POWERON_CONFIG_EN, PROJECT_CODE | BCLK_CG_EN);
mmio_setbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWR_RST_B);
mmio_setbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWR_RST_B);
mmio_setbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWR_RST_B);
mmio_setbits_32(per_cpu(0, 4, SPM_CPU_PWR), PWR_RST_B);
mmio_setbits_32(per_cpu(0, 5, SPM_CPU_PWR), PWR_RST_B);
mmio_setbits_32(per_cpu(0, 6, SPM_CPU_PWR), PWR_RST_B);
mmio_setbits_32(per_cpu(0, 7, SPM_CPU_PWR), PWR_RST_B);
mmio_clrbits_32(SPM_MCUSYS_PWR_CON, RESETPWRON_CONFIG);
mmio_clrbits_32(SPM_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG);
mmio_clrbits_32(per_cpu(0, 0, SPM_CPU_PWR), RESETPWRON_CONFIG);
mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, CPC_CTRL_ENABLE);
/* Clear bootup cpu's cpc sw hint */
mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu));
return 0;
}
/*
* Power on a core with specified cluster and core index
*
* @cluster: the cluster ID of the CPU which to be powered on
* @cpu: the CPU ID of the CPU which to be powered on
*/
void spm_poweron_cpu(unsigned int cluster, unsigned int cpu)
{
/* info CPC that CPU hotplug on */
mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_ALL_PWR_CTRL_EN);
/* Set mp0_spmc_pwr_on_cpuX = 1 */
mmio_setbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON);
/* wait for power on ack */
while (!spm_get_cpu_powerstate(cluster, cpu))
;
/* info CPC that CPU hotplug off */
mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_ALL_PWR_CTRL_EN);
}
/*
* Power off a core with specified cluster and core index
*
* @cluster: the cluster ID of the CPU which to be powered off
* @cpu: the CPU ID of the CPU which to be powered off
*/
void spm_poweroff_cpu(unsigned int cluster, unsigned int cpu)
{
/* Set mp0_spmc_pwr_on_cpuX = 0 */
mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON);
}
/*
* Power off a cluster with specified index
*
* @cluster: the cluster index which to be powered off
*/
void spm_poweroff_cluster(unsigned int cluster)
{
/* No need to power on/off cluster on single cluster platform */
assert(false);
}
/*
* Power on a cluster with specified index
*
* @cluster: the cluster index which to be powered on
*/
void spm_poweron_cluster(unsigned int cluster)
{
/* No need to power on/off cluster on single cluster platform */
assert(false);
}

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MTSPMC_H
#define MTSPMC_H
#include <stdint.h>
int spmc_init(void);
void spm_poweron_cpu(unsigned int cluster, unsigned int cpu);
void spm_poweroff_cpu(unsigned int cluster, unsigned int cpu);
void spm_poweroff_cluster(unsigned int cluster);
void spm_poweron_cluster(unsigned int cluster);
bool spm_get_cpu_powerstate(unsigned int cluster, unsigned int cpu);
bool spm_get_cluster_powerstate(unsigned int cluster);
bool spm_get_powerstate(uint32_t mask);
void mcucfg_init_archstate(unsigned int cluster, unsigned int cpu, bool arm64);
void mcucfg_set_bootaddr(unsigned int cluster, unsigned int cpu, uintptr_t bootaddr);
uintptr_t mcucfg_get_bootaddr(unsigned int cluster, unsigned int cpu);
void mcucfg_disable_gic_wakeup(unsigned int cluster, unsigned int cpu);
void mcucfg_enable_gic_wakeup(unsigned int cluster, unsigned int cpu);
#endif /* MTSPMC_H */

View File

@ -0,0 +1,176 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MTSPMC_PRIVATE_H
#define MTSPMC_PRIVATE_H
#include <lib/utils_def.h>
#include <platform_def.h>
unsigned long read_cpuectlr(void);
void write_cpuectlr(unsigned long cpuectlr);
unsigned long read_cpupwrctlr_el1(void);
void write_cpupwrctlr_el1(unsigned long cpuectlr);
/* per_cpu/cluster helper */
struct per_cpu_reg {
unsigned int cluster_addr;
unsigned int cpu_stride;
};
#define per_cpu(cluster, cpu, reg) \
(reg[cluster].cluster_addr + (cpu << reg[cluster].cpu_stride))
#define per_cluster(cluster, reg) (reg[cluster].cluster_addr)
#define SPM_REG(ofs) (uint32_t)(SPM_BASE + (ofs))
#define MCUCFG_REG(ofs) (uint32_t)(MCUCFG_BASE + (ofs))
#define INFRACFG_AO_REG(ofs) (uint32_t)(INFRACFG_AO_BASE + (ofs))
/* SPMC related registers */
#define SPM_POWERON_CONFIG_EN SPM_REG(0x000)
/* bit-fields of SPM_POWERON_CONFIG_EN */
#define PROJECT_CODE (U(0xb16) << 16)
#define BCLK_CG_EN BIT(0)
#define SPM_PWR_STATUS SPM_REG(0x16c)
#define SPM_PWR_STATUS_2ND SPM_REG(0x170)
#define SPM_CPU_PWR_STATUS SPM_REG(0x174)
/* bit-fields of SPM_PWR_STATUS */
#define MD BIT(0)
#define CONN BIT(1)
#define DDRPHY BIT(2)
#define DISP BIT(3)
#define MFG BIT(4)
#define ISP BIT(5)
#define INFRA BIT(6)
#define VDEC BIT(7)
#define MP0_CPUTOP BIT(8)
#define MP0_CPU0 BIT(9)
#define MP0_CPU1 BIT(10)
#define MP0_CPU2 BIT(11)
#define MP0_CPU3 BIT(12)
#define MCUSYS BIT(14)
#define MP0_CPU4 BIT(15)
#define MP0_CPU5 BIT(16)
#define MP0_CPU6 BIT(17)
#define MP0_CPU7 BIT(18)
#define VEN BIT(21)
/* SPMC related registers */
#define SPM_MCUSYS_PWR_CON SPM_REG(0x200)
#define SPM_MP0_CPUTOP_PWR_CON SPM_REG(0x204)
#define SPM_MP0_CPU0_PWR_CON SPM_REG(0x208)
#define SPM_MP0_CPU1_PWR_CON SPM_REG(0x20c)
#define SPM_MP0_CPU2_PWR_CON SPM_REG(0x210)
#define SPM_MP0_CPU3_PWR_CON SPM_REG(0x214)
#define SPM_MP0_CPU4_PWR_CON SPM_REG(0x218)
#define SPM_MP0_CPU5_PWR_CON SPM_REG(0x21c)
#define SPM_MP0_CPU6_PWR_CON SPM_REG(0x220)
#define SPM_MP0_CPU7_PWR_CON SPM_REG(0x224)
/* bit-fields of SPM_*_PWR_CON */
#define PWR_ON_ACK BIT(31)
#define VPROC_EXT_OFF BIT(7)
#define DORMANT_EN BIT(6)
#define RESETPWRON_CONFIG BIT(5)
#define PWR_CLK_DIS BIT(4)
#define PWR_ON BIT(2)
#define PWR_RST_B BIT(0)
/* per_cpu registers for SPM_MP0_CPU_PWR_CON */
static const struct per_cpu_reg SPM_CPU_PWR[] = {
{ .cluster_addr = SPM_MP0_CPU0_PWR_CON, .cpu_stride = 2U }
};
/* per_cluster registers for SPM_MP0_CPUTOP_PWR_CON */
static const struct per_cpu_reg SPM_CLUSTER_PWR[] = {
{ .cluster_addr = SPM_MP0_CPUTOP_PWR_CON, .cpu_stride = 0U }
};
/* MCUCFG related registers */
#define MCUCFG_MP0_CLUSTER_CFG5 MCUCFG_REG(0xc8e4)
/* reset vectors */
#define MCUCFG_MP0_CLUSTER_CFG8 MCUCFG_REG(0xc900)
#define MCUCFG_MP0_CLUSTER_CFG10 MCUCFG_REG(0xc908)
#define MCUCFG_MP0_CLUSTER_CFG12 MCUCFG_REG(0xc910)
#define MCUCFG_MP0_CLUSTER_CFG14 MCUCFG_REG(0xc918)
#define MCUCFG_MP0_CLUSTER_CFG16 MCUCFG_REG(0xc920)
#define MCUCFG_MP0_CLUSTER_CFG18 MCUCFG_REG(0xc928)
#define MCUCFG_MP0_CLUSTER_CFG20 MCUCFG_REG(0xc930)
#define MCUCFG_MP0_CLUSTER_CFG22 MCUCFG_REG(0xc938)
/* per_cpu registers for MCUCFG_MP0_CLUSTER_CFG */
static const struct per_cpu_reg MCUCFG_BOOTADDR[] = {
{ .cluster_addr = MCUCFG_MP0_CLUSTER_CFG8, .cpu_stride = 3U }
};
/* per_cpu registers for MCUCFG_MP0_CLUSTER_CFG5 */
static const struct per_cpu_reg MCUCFG_INITARCH[] = {
{ .cluster_addr = MCUCFG_MP0_CLUSTER_CFG5, .cpu_stride = 0U }
};
#define MCUCFG_INITARCH_CPU_BIT(cpu) BIT(16U + cpu)
/* CPC control */
#define MCUCFG_CPC_FLOW_CTRL_CFG MCUCFG_REG(0xa814)
#define MCUCFG_CPC_SPMC_PWR_STATUS MCUCFG_REG(0xa840)
/* bit-fields of CPC_FLOW_CTRL_CFG */
#define CPC_CTRL_ENABLE BIT(16)
#define SSPM_ALL_PWR_CTRL_EN BIT(13) /* for cpu-hotplug */
#define GIC_WAKEUP_IGNORE(cpu) BIT(21 + cpu)
/* bit-fields of CPC_SPMC_PWR_STATUS */
#define CORE_SPMC_PWR_ON_ACK GENMASK(11, 0)
/* APB module infracfg_ao */
#define INFRA_TOPAXI_PROTECTEN INFRACFG_AO_REG(0x0220)
#define INFRA_TOPAXI_PROTECTEN_STA0 INFRACFG_AO_REG(0x0224)
#define INFRA_TOPAXI_PROTECTEN_STA1 INFRACFG_AO_REG(0x0228)
#define INFRA_TOPAXI_PROTECTEN_SET INFRACFG_AO_REG(0x02a0)
#define INFRA_TOPAXI_PROTECTEN_CLR INFRACFG_AO_REG(0x02a4)
#define INFRA_TOPAXI_PROTECTEN_1 INFRACFG_AO_REG(0x0250)
#define INFRA_TOPAXI_PROTECTEN_STA0_1 INFRACFG_AO_REG(0x0254)
#define INFRA_TOPAXI_PROTECTEN_STA1_1 INFRACFG_AO_REG(0x0258)
#define INFRA_TOPAXI_PROTECTEN_1_SET INFRACFG_AO_REG(0x02a8)
#define INFRA_TOPAXI_PROTECTEN_1_CLR INFRACFG_AO_REG(0x02ac)
/* bit-fields of INFRA_TOPAXI_PROTECTEN */
#define MP0_SPMC_PROT_STEP1_0_MASK BIT(12)
#define MP0_SPMC_PROT_STEP1_1_MASK (BIT(26) | BIT(12))
/* SPARK */
#define VOLTAGE_04 U(0x40)
#define VOLTAGE_05 U(0x60)
#define PTP3_CPU0_SPMC_SW_CFG MCUCFG_REG(0x200)
#define CPU0_ILDO_CONTROL5 MCUCFG_REG(0x334)
#define CPU0_ILDO_CONTROL8 MCUCFG_REG(0x340)
/* bit-fields of CPU0_ILDO_CONTROL5 */
#define ILDO_RET_VOSEL GENMASK(7, 0)
/* bit-fields of PTP3_CPU_SPMC_SW_CFG */
#define SW_SPARK_EN BIT(0)
/* bit-fields of CPU0_ILDO_CONTROL8 */
#define ILDO_BYPASS_B BIT(0)
static const struct per_cpu_reg MCUCFG_SPARK[] = {
{ .cluster_addr = PTP3_CPU0_SPMC_SW_CFG, .cpu_stride = 11U }
};
static const struct per_cpu_reg ILDO_CONTROL5[] = {
{ .cluster_addr = CPU0_ILDO_CONTROL5, .cpu_stride = 11U }
};
static const struct per_cpu_reg ILDO_CONTROL8[] = {
{ .cluster_addr = CPU0_ILDO_CONTROL8, .cpu_stride = 11U }
};
#endif /* MTSPMC_PRIVATE_H */

View File

@ -0,0 +1,255 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MCUCFG_H
#define MCUCFG_H
#ifndef __ASSEMBLER__
#include <stdint.h>
#endif /* __ASSEMBLER__ */
#include <platform_def.h>
#define MCUCFG_REG(ofs) (uint32_t)(MCUCFG_BASE + (ofs))
#define MP2_MISC_CONFIG_BOOT_ADDR_L(cpu) (MCUCFG_REG(0x2290) + ((cpu) * 8))
#define MP2_MISC_CONFIG_BOOT_ADDR_H(cpu) (MCUCFG_REG(0x2294) + ((cpu) * 8))
#define MP2_CPUCFG MCUCFG_REG(0x2208)
#define MP2_CPU0_STANDBYWFE BIT(4)
#define MP2_CPU1_STANDBYWFE BIT(5)
#define MP0_CPUTOP_SPMC_CTL MCUCFG_REG(0x788)
#define MP1_CPUTOP_SPMC_CTL MCUCFG_REG(0x78C)
#define MP1_CPUTOP_SPMC_SRAM_CTL MCUCFG_REG(0x790)
#define sw_spark_en BIT(0)
#define sw_no_wait_for_q_channel BIT(1)
#define sw_fsm_override BIT(2)
#define sw_logic_pre1_pdb BIT(3)
#define sw_logic_pre2_pdb BIT(4)
#define sw_logic_pdb BIT(5)
#define sw_iso BIT(6)
#define sw_sram_sleepb (U(0x3F) << 7)
#define sw_sram_isointb BIT(13)
#define sw_clk_dis BIT(14)
#define sw_ckiso BIT(15)
#define sw_pd (U(0x3F) << 16)
#define sw_hot_plug_reset BIT(22)
#define sw_pwr_on_override_en BIT(23)
#define sw_pwr_on BIT(24)
#define sw_coq_dis BIT(25)
#define logic_pdbo_all_off_ack BIT(26)
#define logic_pdbo_all_on_ack BIT(27)
#define logic_pre2_pdbo_all_on_ack BIT(28)
#define logic_pre1_pdbo_all_on_ack BIT(29)
#define CPUSYSx_CPUx_SPMC_CTL(cluster, cpu) \
(MCUCFG_REG(0x1c30) + cluster * 0x2000 + cpu * 4)
#define CPUSYS0_CPU0_SPMC_CTL MCUCFG_REG(0x1c30)
#define CPUSYS0_CPU1_SPMC_CTL MCUCFG_REG(0x1c34)
#define CPUSYS0_CPU2_SPMC_CTL MCUCFG_REG(0x1c38)
#define CPUSYS0_CPU3_SPMC_CTL MCUCFG_REG(0x1c3C)
#define CPUSYS1_CPU0_SPMC_CTL MCUCFG_REG(0x3c30)
#define CPUSYS1_CPU1_SPMC_CTL MCUCFG_REG(0x3c34)
#define CPUSYS1_CPU2_SPMC_CTL MCUCFG_REG(0x3c38)
#define CPUSYS1_CPU3_SPMC_CTL MCUCFG_REG(0x3c3C)
#define cpu_sw_spark_en BIT(0)
#define cpu_sw_no_wait_for_q_channel BIT(1)
#define cpu_sw_fsm_override BIT(2)
#define cpu_sw_logic_pre1_pdb BIT(3)
#define cpu_sw_logic_pre2_pdb BIT(4)
#define cpu_sw_logic_pdb BIT(5)
#define cpu_sw_iso BIT(6)
#define cpu_sw_sram_sleepb BIT(7)
#define cpu_sw_sram_isointb BIT(8)
#define cpu_sw_clk_dis BIT(9)
#define cpu_sw_ckiso BIT(10)
#define cpu_sw_pd (U(0x1F) << 11)
#define cpu_sw_hot_plug_reset BIT(16)
#define cpu_sw_powr_on_override_en BIT(17)
#define cpu_sw_pwr_on BIT(18)
#define cpu_spark2ldo_allswoff BIT(19)
#define cpu_pdbo_all_on_ack BIT(20)
#define cpu_pre2_pdbo_allon_ack BIT(21)
#define cpu_pre1_pdbo_allon_ack BIT(22)
/* CPC related registers */
#define CPC_MCUSYS_CPC_OFF_THRES MCUCFG_REG(0xa714)
#define CPC_MCUSYS_PWR_CTRL MCUCFG_REG(0xa804)
#define CPC_MCUSYS_CPC_FLOW_CTRL_CFG MCUCFG_REG(0xa814)
#define CPC_MCUSYS_LAST_CORE_REQ MCUCFG_REG(0xa818)
#define CPC_MCUSYS_MP_LAST_CORE_RESP MCUCFG_REG(0xa81c)
#define CPC_MCUSYS_LAST_CORE_RESP MCUCFG_REG(0xa824)
#define CPC_MCUSYS_PWR_ON_MASK MCUCFG_REG(0xa828)
#define CPC_MCUSYS_CPU_ON_SW_HINT_SET MCUCFG_REG(0xa8a8)
#define CPC_MCUSYS_CPU_ON_SW_HINT_CLR MCUCFG_REG(0xa8ac)
#define CPC_MCUSYS_CPC_DBG_SETTING MCUCFG_REG(0xab00)
#define CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE MCUCFG_REG(0xab04)
#define CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE MCUCFG_REG(0xab08)
#define CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE MCUCFG_REG(0xab0c)
#define CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE MCUCFG_REG(0xab10)
#define CPC_MCUSYS_TRACE_SEL MCUCFG_REG(0xab14)
#define CPC_MCUSYS_TRACE_DATA MCUCFG_REG(0xab20)
#define CPC_MCUSYS_CLUSTER_COUNTER MCUCFG_REG(0xab70)
#define CPC_MCUSYS_CLUSTER_COUNTER_CLR MCUCFG_REG(0xab74)
#define SPARK2LDO MCUCFG_REG(0x2700)
/* APB module mcucfg */
#define MP0_CA7_CACHE_CONFIG MCUCFG_REG(0x000)
#define MP0_AXI_CONFIG MCUCFG_REG(0x02C)
#define MP0_MISC_CONFIG0 MCUCFG_REG(0x030)
#define MP0_MISC_CONFIG1 MCUCFG_REG(0x034)
#define MP0_MISC_CONFIG2 MCUCFG_REG(0x038)
#define MP0_MISC_CONFIG_BOOT_ADDR(cpu) (MP0_MISC_CONFIG2 + ((cpu) * 8))
#define MP0_MISC_CONFIG3 MCUCFG_REG(0x03C)
#define MP0_MISC_CONFIG9 MCUCFG_REG(0x054)
#define MP0_CA7_MISC_CONFIG MCUCFG_REG(0x064)
#define MP0_RW_RSVD0 MCUCFG_REG(0x06C)
#define MP1_CA7_CACHE_CONFIG MCUCFG_REG(0x200)
#define MP1_AXI_CONFIG MCUCFG_REG(0x22C)
#define MP1_MISC_CONFIG0 MCUCFG_REG(0x230)
#define MP1_MISC_CONFIG1 MCUCFG_REG(0x234)
#define MP1_MISC_CONFIG2 MCUCFG_REG(0x238)
#define MP1_MISC_CONFIG_BOOT_ADDR(cpu) (MP1_MISC_CONFIG2 + ((cpu) * 8))
#define MP1_MISC_CONFIG3 MCUCFG_REG(0x23C)
#define MP1_MISC_CONFIG9 MCUCFG_REG(0x254)
#define MP1_CA7_MISC_CONFIG MCUCFG_REG(0x264)
#define CCI_ADB400_DCM_CONFIG MCUCFG_REG(0x740)
#define SYNC_DCM_CONFIG MCUCFG_REG(0x744)
#define MP0_CLUSTER_CFG0 MCUCFG_REG(0xC8D0)
#define MP0_SPMC MCUCFG_REG(0x788)
#define MP1_SPMC MCUCFG_REG(0x78C)
#define MP2_AXI_CONFIG MCUCFG_REG(0x220C)
#define MP2_AXI_CONFIG_ACINACTM BIT(0)
#define MP2_AXI_CONFIG_AINACTS BIT(4)
#define MPx_AXI_CONFIG_ACINACTM BIT(4)
#define MPx_AXI_CONFIG_AINACTS BIT(5)
#define MPx_CA7_MISC_CONFIG_standbywfil2 BIT(28)
#define MP0_CPU0_STANDBYWFE BIT(20)
#define MP0_CPU1_STANDBYWFE BIT(21)
#define MP0_CPU2_STANDBYWFE BIT(22)
#define MP0_CPU3_STANDBYWFE BIT(23)
#define MP1_CPU0_STANDBYWFE BIT(20)
#define MP1_CPU1_STANDBYWFE BIT(21)
#define MP1_CPU2_STANDBYWFE BIT(22)
#define MP1_CPU3_STANDBYWFE BIT(23)
#define CPUSYS0_SPARKVRETCNTRL MCUCFG_REG(0x1c00)
#define CPUSYS0_SPARKEN MCUCFG_REG(0x1c04)
#define CPUSYS0_AMUXSEL MCUCFG_REG(0x1c08)
#define CPUSYS1_SPARKVRETCNTRL MCUCFG_REG(0x3c00)
#define CPUSYS1_SPARKEN MCUCFG_REG(0x3c04)
#define CPUSYS1_AMUXSEL MCUCFG_REG(0x3c08)
#define MP2_PWR_RST_CTL MCUCFG_REG(0x2008)
#define MP2_PTP3_CPUTOP_SPMC0 MCUCFG_REG(0x22A0)
#define MP2_PTP3_CPUTOP_SPMC1 MCUCFG_REG(0x22A4)
#define MP2_COQ MCUCFG_REG(0x22BC)
#define MP2_COQ_SW_DIS BIT(0)
#define MP2_CA15M_MON_SEL MCUCFG_REG(0x2400)
#define MP2_CA15M_MON_L MCUCFG_REG(0x2404)
#define CPUSYS2_CPU0_SPMC_CTL MCUCFG_REG(0x2430)
#define CPUSYS2_CPU1_SPMC_CTL MCUCFG_REG(0x2438)
#define CPUSYS2_CPU0_SPMC_STA MCUCFG_REG(0x2434)
#define CPUSYS2_CPU1_SPMC_STA MCUCFG_REG(0x243C)
#define MP0_CA7L_DBG_PWR_CTRL MCUCFG_REG(0x068)
#define MP1_CA7L_DBG_PWR_CTRL MCUCFG_REG(0x268)
#define BIG_DBG_PWR_CTRL MCUCFG_REG(0x75C)
#define MP2_SW_RST_B BIT(0)
#define MP2_TOPAON_APB_MASK BIT(1)
#define B_SW_HOT_PLUG_RESET BIT(30)
#define B_SW_PD_OFFSET (18U)
#define B_SW_PD (U(0x3f) << B_SW_PD_OFFSET)
#define B_SW_SRAM_SLEEPB_OFFSET (12U)
#define B_SW_SRAM_SLEEPB (U(0x3f) << B_SW_SRAM_SLEEPB_OFFSET)
#define B_SW_SRAM_ISOINTB BIT(9)
#define B_SW_ISO BIT(8)
#define B_SW_LOGIC_PDB BIT(7)
#define B_SW_LOGIC_PRE2_PDB BIT(6)
#define B_SW_LOGIC_PRE1_PDB BIT(5)
#define B_SW_FSM_OVERRIDE BIT(4)
#define B_SW_PWR_ON BIT(3)
#define B_SW_PWR_ON_OVERRIDE_EN BIT(2)
#define B_FSM_STATE_OUT_OFFSET (6U)
#define B_FSM_STATE_OUT_MASK (U(0x1f) << B_FSM_STATE_OUT_OFFSET)
#define B_SW_LOGIC_PDBO_ALL_OFF_ACK BIT(5)
#define B_SW_LOGIC_PDBO_ALL_ON_ACK BIT(4)
#define B_SW_LOGIC_PRE2_PDBO_ALL_ON_ACK BIT(3)
#define B_SW_LOGIC_PRE1_PDBO_ALL_ON_ACK BIT(2)
#define B_FSM_OFF (0U << B_FSM_STATE_OUT_OFFSET)
#define B_FSM_ON (1U << B_FSM_STATE_OUT_OFFSET)
#define B_FSM_RET (2U << B_FSM_STATE_OUT_OFFSET)
#ifndef __ASSEMBLER__
/* cpu boot mode */
enum {
MP0_CPUCFG_64BIT_SHIFT = 12U,
MP1_CPUCFG_64BIT_SHIFT = 28U,
MP0_CPUCFG_64BIT = U(0xf) << MP0_CPUCFG_64BIT_SHIFT,
MP1_CPUCFG_64BIT = U(0xf) << MP1_CPUCFG_64BIT_SHIFT
};
enum {
MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT = 0U,
MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT = 4U,
MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT = 8U,
MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT = 12U,
MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT = 16U,
MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK =
U(0xf) << MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT,
MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK =
U(0xf) << MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT,
MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK =
U(0xf) << MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT,
MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK =
U(0xf) << MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT,
MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK =
U(0xf) << MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT
};
enum {
MP1_AINACTS_SHIFT = 4U,
MP1_AINACTS = 1U << MP1_AINACTS_SHIFT
};
enum {
MP1_SW_CG_GEN_SHIFT = 12U,
MP1_SW_CG_GEN = 1U << MP1_SW_CG_GEN_SHIFT
};
enum {
MP1_L2RSTDISABLE_SHIFT = 14U,
MP1_L2RSTDISABLE = 1U << MP1_L2RSTDISABLE_SHIFT
};
#endif /* __ASSEMBLER__ */
#endif /* MCUCFG_H */

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PLAT_MTK_LPM_H
#define PLAT_MTK_LPM_H
#include <lib/psci/psci.h>
#include <lib/utils_def.h>
#define MT_IRQ_REMAIN_MAX U(32)
#define MT_IRQ_REMAIN_CAT_LOG BIT(31)
struct mt_irqremain {
unsigned int count;
unsigned int irqs[MT_IRQ_REMAIN_MAX];
unsigned int wakeupsrc_cat[MT_IRQ_REMAIN_MAX];
unsigned int wakeupsrc[MT_IRQ_REMAIN_MAX];
};
#define PLAT_RC_STATUS_READY BIT(0)
#define PLAT_RC_STATUS_FEATURE_EN BIT(1)
#define PLAT_RC_STATUS_UART_NONSLEEP BIT(31)
struct mt_lpm_tz {
int (*pwr_prompt)(unsigned int cpu, const psci_power_state_t *state);
int (*pwr_reflect)(unsigned int cpu, const psci_power_state_t *state);
int (*pwr_cpu_on)(unsigned int cpu, const psci_power_state_t *state);
int (*pwr_cpu_dwn)(unsigned int cpu, const psci_power_state_t *state);
int (*pwr_cluster_on)(unsigned int cpu,
const psci_power_state_t *state);
int (*pwr_cluster_dwn)(unsigned int cpu,
const psci_power_state_t *state);
int (*pwr_mcusys_on)(unsigned int cpu, const psci_power_state_t *state);
int (*pwr_mcusys_on_finished)(unsigned int cpu,
const psci_power_state_t *state);
int (*pwr_mcusys_dwn)(unsigned int cpu,
const psci_power_state_t *state);
};
const struct mt_lpm_tz *mt_plat_cpu_pm_init(void);
#endif /* PLAT_MTK_LPM_H */

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PLAT_PM_H
#define PLAT_PM_H
#include <lib/utils_def.h>
#define MT_PLAT_PWR_STATE_CPU U(1)
#define MT_PLAT_PWR_STATE_CLUSTER U(2)
#define MT_PLAT_PWR_STATE_MCUSYS U(3)
#define MT_PLAT_PWR_STATE_SUSPEND2IDLE U(8)
#define MT_PLAT_PWR_STATE_SYSTEM_SUSPEND U(9)
#define MTK_LOCAL_STATE_RUN U(0)
#define MTK_LOCAL_STATE_RET U(1)
#define MTK_LOCAL_STATE_OFF U(2)
#define MTK_AFFLVL_CPU U(0)
#define MTK_AFFLVL_CLUSTER U(1)
#define MTK_AFFLVL_MCUSYS U(2)
#define MTK_AFFLVL_SYSTEM U(3)
#define IS_CLUSTER_OFF_STATE(s) \
is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_CLUSTER])
#define IS_MCUSYS_OFF_STATE(s) \
is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_MCUSYS])
#define IS_SYSTEM_SUSPEND_STATE(s) \
is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_SYSTEM])
#define IS_PLAT_SUSPEND_ID(stateid) \
((stateid == MT_PLAT_PWR_STATE_SUSPEND2IDLE) \
|| (stateid == MT_PLAT_PWR_STATE_SYSTEM_SUSPEND))
#endif /* PLAT_PM_H */

View File

@ -0,0 +1,15 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PLAT_SIP_CALLS_H
#define PLAT_SIP_CALLS_H
/*******************************************************************************
* Plat SiP function constants
******************************************************************************/
#define MTK_PLAT_SIP_NUM_CALLS 0
#endif /* PLAT_SIP_CALLS_H */

View File

@ -15,12 +15,22 @@
/* Aggregate of all devices for MMU mapping */
#define MTK_DEV_RNG0_BASE IO_PHYS
#define MTK_DEV_RNG0_SIZE 0x400000
#define MTK_DEV_RNG1_BASE (IO_PHYS + 0x1000000)
#define MTK_DEV_RNG1_SIZE 0xa110000
#define MTK_DEV_RNG0_SIZE 0x10000000
#define MTK_DEV_RNG2_BASE MT_GIC_BASE
#define MTK_DEV_RNG2_SIZE 0x600000
#define SPM_BASE (IO_PHYS + 0x00006000)
/*******************************************************************************
* GPIO related constants
******************************************************************************/
#define GPIO_BASE (IO_PHYS + 0x00005000)
#define IOCFG_LT_BASE (IO_PHYS + 0x00002000)
#define IOCFG_LM_BASE (IO_PHYS + 0x00002200)
#define IOCFG_LB_BASE (IO_PHYS + 0x00002400)
#define IOCFG_BL_BASE (IO_PHYS + 0x00002600)
#define IOCFG_RB_BASE (IO_PHYS + 0x00002A00)
#define IOCFG_RT_BASE (IO_PHYS + 0x00002C00)
/*******************************************************************************
* UART related constants
@ -29,6 +39,28 @@
#define UART_BAUDRATE 115200
/*******************************************************************************
* PWRAP related constants
******************************************************************************/
#define PMIC_WRAP_BASE (IO_PHYS + 0x0000D000)
/*******************************************************************************
* EMI MPU related constants
******************************************************************************/
#define EMI_MPU_BASE (IO_PHYS + 0x0021B000)
/*******************************************************************************
* GIC-600 & interrupt handling related constants
******************************************************************************/
/* Base MTK_platform compatible GIC memory map */
#define BASE_GICD_BASE MT_GIC_BASE
#define MT_GIC_RDIST_BASE (MT_GIC_BASE + 0x40000)
#define SYS_CIRQ_BASE (IO_PHYS + 0x204000)
#define CIRQ_REG_NUM 11
#define CIRQ_IRQ_NUM 326
#define CIRQ_SPI_START 64
#define MD_WDT_IRQ_BIT_ID 107
/*******************************************************************************
* System counter frequency related constants
******************************************************************************/

View File

@ -4,15 +4,397 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
/* common headers */
#include <assert.h>
#include <arch_helpers.h>
#include <common/debug.h>
#include <drivers/gpio.h>
#include <lib/psci/psci.h>
/* platform specific headers */
#include <mt_gic_v3.h>
#include <mtspmc.h>
#include <plat/common/platform.h>
#include <plat_mtk_lpm.h>
#include <plat_params.h>
#include <plat_pm.h>
#include <pmic.h>
#include <rtc.h>
/*
* Cluster state request:
* [0] : The CPU requires cluster power down
* [1] : The CPU requires cluster power on
*/
#define coordinate_cluster(onoff) write_clusterpwrdn_el1(onoff)
#define coordinate_cluster_pwron() coordinate_cluster(1)
#define coordinate_cluster_pwroff() coordinate_cluster(0)
/* platform secure entry point */
static uintptr_t secure_entrypoint;
/* per-CPU power state */
static unsigned int plat_power_state[PLATFORM_CORE_COUNT];
/* platform CPU power domain - ops */
static const struct mt_lpm_tz *plat_mt_pm;
static inline int plat_mt_pm_invoke(int (*func)(unsigned int cpu,
const psci_power_state_t *state),
int cpu, const psci_power_state_t *state)
{
int ret = -1;
if (func != NULL) {
ret = func(cpu, state);
}
return ret;
}
/*
* Common MTK_platform operations to power on/off a
* CPU in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
*/
static void plat_cpu_pwrdwn_common(unsigned int cpu,
const psci_power_state_t *state, unsigned int req_pstate)
{
assert(cpu == plat_my_core_pos());
assert(plat_mt_pm != NULL);
(void)plat_mt_pm_invoke(plat_mt_pm->pwr_cpu_dwn, cpu, state);
if ((psci_get_pstate_pwrlvl(req_pstate) >= MTK_AFFLVL_CLUSTER) ||
(req_pstate == 0U)) { /* hotplug off */
coordinate_cluster_pwroff();
}
/* Prevent interrupts from spuriously waking up this CPU */
mt_gic_rdistif_save();
gicv3_cpuif_disable(cpu);
gicv3_rdistif_off(cpu);
}
static void plat_cpu_pwron_common(unsigned int cpu,
const psci_power_state_t *state, unsigned int req_pstate)
{
assert(cpu == plat_my_core_pos());
assert(plat_mt_pm != NULL);
(void)plat_mt_pm_invoke(plat_mt_pm->pwr_cpu_on, cpu, state);
coordinate_cluster_pwron();
/*
* If mcusys does power down before then restore
* all CPUs' GIC Redistributors
*/
if (IS_MCUSYS_OFF_STATE(state)) {
mt_gic_rdistif_restore_all();
} else {
gicv3_rdistif_on(cpu);
gicv3_cpuif_enable(cpu);
mt_gic_rdistif_init();
mt_gic_rdistif_restore();
}
}
/*
* Common MTK_platform operations to power on/off a
* cluster in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
*/
static void plat_cluster_pwrdwn_common(unsigned int cpu,
const psci_power_state_t *state, unsigned int req_pstate)
{
assert(cpu == plat_my_core_pos());
assert(plat_mt_pm != NULL);
if (plat_mt_pm_invoke(plat_mt_pm->pwr_cluster_dwn, cpu, state) != 0) {
coordinate_cluster_pwron();
/*
* TODO:
* Return on fail and add a 'return' here before
* adding any code following the if-block.
*/
}
}
static void plat_cluster_pwron_common(unsigned int cpu,
const psci_power_state_t *state, unsigned int req_pstate)
{
assert(cpu == plat_my_core_pos());
assert(plat_mt_pm != NULL);
if (plat_mt_pm_invoke(plat_mt_pm->pwr_cluster_on, cpu, state) != 0) {
/*
* TODO:
* return on fail and add a 'return' here before
* adding any code following the if-block.
*/
}
}
/*
* Common MTK_platform operations to power on/off a
* mcusys in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
*/
static void plat_mcusys_pwrdwn_common(unsigned int cpu,
const psci_power_state_t *state, unsigned int req_pstate)
{
assert(cpu == plat_my_core_pos());
assert(plat_mt_pm != NULL);
if (plat_mt_pm_invoke(plat_mt_pm->pwr_mcusys_dwn, cpu, state) != 0) {
return; /* return on fail */
}
mt_gic_distif_save();
gic_sgi_save_all();
}
static void plat_mcusys_pwron_common(unsigned int cpu,
const psci_power_state_t *state, unsigned int req_pstate)
{
assert(cpu == plat_my_core_pos());
assert(plat_mt_pm != NULL);
if (plat_mt_pm_invoke(plat_mt_pm->pwr_mcusys_on, cpu, state) != 0) {
/* return on fail */
return;
}
mt_gic_init();
mt_gic_distif_restore();
gic_sgi_restore_all();
(void)plat_mt_pm_invoke(plat_mt_pm->pwr_mcusys_on_finished, cpu, state);
}
/* plat_psci_ops implementation */
static void plat_cpu_standby(plat_local_state_t cpu_state)
{
uint64_t scr;
scr = read_scr_el3();
write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
isb();
dsb();
wfi();
write_scr_el3(scr);
}
static int plat_power_domain_on(u_register_t mpidr)
{
unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
unsigned int cluster = 0U;
if (cpu >= PLATFORM_CORE_COUNT) {
return PSCI_E_INVALID_PARAMS;
}
if (!spm_get_cluster_powerstate(cluster)) {
spm_poweron_cluster(cluster);
}
/* init CPU reset arch as AARCH64 */
mcucfg_init_archstate(cluster, cpu, true);
mcucfg_set_bootaddr(cluster, cpu, secure_entrypoint);
spm_poweron_cpu(cluster, cpu);
return PSCI_E_SUCCESS;
}
static void plat_power_domain_on_finish(const psci_power_state_t *state)
{
unsigned long mpidr = read_mpidr_el1();
unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
assert(cpu < PLATFORM_CORE_COUNT);
/* Allow IRQs to wakeup this core in IDLE flow */
mcucfg_enable_gic_wakeup(0U, cpu);
if (IS_CLUSTER_OFF_STATE(state)) {
plat_cluster_pwron_common(cpu, state, 0U);
}
plat_cpu_pwron_common(cpu, state, 0U);
}
static void plat_power_domain_off(const psci_power_state_t *state)
{
unsigned long mpidr = read_mpidr_el1();
unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
assert(cpu < PLATFORM_CORE_COUNT);
plat_cpu_pwrdwn_common(cpu, state, 0U);
spm_poweroff_cpu(0U, cpu);
/* prevent unintended IRQs from waking up the hot-unplugged core */
mcucfg_disable_gic_wakeup(0U, cpu);
if (IS_CLUSTER_OFF_STATE(state)) {
plat_cluster_pwrdwn_common(cpu, state, 0U);
}
}
static void plat_power_domain_suspend(const psci_power_state_t *state)
{
unsigned int cpu = plat_my_core_pos();
assert(cpu < PLATFORM_CORE_COUNT);
assert(plat_mt_pm != NULL);
(void)plat_mt_pm_invoke(plat_mt_pm->pwr_prompt, cpu, state);
/* Perform the common CPU specific operations */
plat_cpu_pwrdwn_common(cpu, state, plat_power_state[cpu]);
if (IS_CLUSTER_OFF_STATE(state)) {
/* Perform the common cluster specific operations */
plat_cluster_pwrdwn_common(cpu, state, plat_power_state[cpu]);
}
if (IS_MCUSYS_OFF_STATE(state)) {
/* Perform the common mcusys specific operations */
plat_mcusys_pwrdwn_common(cpu, state, plat_power_state[cpu]);
}
}
static void plat_power_domain_suspend_finish(const psci_power_state_t *state)
{
unsigned int cpu = plat_my_core_pos();
assert(cpu < PLATFORM_CORE_COUNT);
assert(plat_mt_pm != NULL);
if (IS_MCUSYS_OFF_STATE(state)) {
/* Perform the common mcusys specific operations */
plat_mcusys_pwron_common(cpu, state, plat_power_state[cpu]);
}
if (IS_CLUSTER_OFF_STATE(state)) {
/* Perform the common cluster specific operations */
plat_cluster_pwron_common(cpu, state, plat_power_state[cpu]);
}
/* Perform the common CPU specific operations */
plat_cpu_pwron_common(cpu, state, plat_power_state[cpu]);
(void)plat_mt_pm_invoke(plat_mt_pm->pwr_reflect, cpu, state);
}
static int plat_validate_power_state(unsigned int power_state,
psci_power_state_t *req_state)
{
unsigned int pstate = psci_get_pstate_type(power_state);
unsigned int aff_lvl = psci_get_pstate_pwrlvl(power_state);
unsigned int cpu = plat_my_core_pos();
if (aff_lvl > PLAT_MAX_PWR_LVL) {
return PSCI_E_INVALID_PARAMS;
}
if (pstate == PSTATE_TYPE_STANDBY) {
req_state->pwr_domain_state[0] = PLAT_MAX_RET_STATE;
} else {
unsigned int i;
unsigned int pstate_id = psci_get_pstate_id(power_state);
plat_local_state_t s = MTK_LOCAL_STATE_OFF;
/* Use pstate_id to be power domain state */
if (pstate_id > s) {
s = (plat_local_state_t)pstate_id;
}
for (i = 0U; i <= aff_lvl; i++) {
req_state->pwr_domain_state[i] = s;
}
}
plat_power_state[cpu] = power_state;
return PSCI_E_SUCCESS;
}
static void plat_get_sys_suspend_power_state(psci_power_state_t *req_state)
{
unsigned int lv;
unsigned int cpu = plat_my_core_pos();
for (lv = PSCI_CPU_PWR_LVL; lv <= PLAT_MAX_PWR_LVL; lv++) {
req_state->pwr_domain_state[lv] = PLAT_MAX_OFF_STATE;
}
plat_power_state[cpu] =
psci_make_powerstate(
MT_PLAT_PWR_STATE_SYSTEM_SUSPEND,
PSTATE_TYPE_POWERDOWN, PLAT_MAX_PWR_LVL);
flush_dcache_range((uintptr_t)
&plat_power_state[cpu],
sizeof(plat_power_state[cpu]));
}
/*******************************************************************************
* MTK handlers to shutdown/reboot the system
******************************************************************************/
static void __dead2 plat_mtk_system_reset(void)
{
struct bl_aux_gpio_info *gpio_reset = plat_get_mtk_gpio_reset();
INFO("MTK System Reset\n");
gpio_set_value(gpio_reset->index, gpio_reset->polarity);
wfi();
ERROR("MTK System Reset: operation not handled.\n");
panic();
}
static void __dead2 plat_mtk_system_off(void)
{
INFO("MTK System Off\n");
rtc_power_off_sequence();
pmic_power_off();
wfi();
ERROR("MTK System Off: operation not handled.\n");
panic();
}
static const plat_psci_ops_t plat_psci_ops = {
.cpu_standby = plat_cpu_standby,
.pwr_domain_on = plat_power_domain_on,
.pwr_domain_on_finish = plat_power_domain_on_finish,
.pwr_domain_off = plat_power_domain_off,
.pwr_domain_suspend = plat_power_domain_suspend,
.pwr_domain_suspend_finish = plat_power_domain_suspend_finish,
.validate_power_state = plat_validate_power_state,
.get_sys_suspend_power_state = plat_get_sys_suspend_power_state,
.system_off = plat_mtk_system_off,
.system_reset = plat_mtk_system_reset,
};
int plat_setup_psci_ops(uintptr_t sec_entrypoint,
const plat_psci_ops_t **psci_ops)
{
*psci_ops = &plat_psci_ops;
secure_entrypoint = sec_entrypoint;
/*
* init the warm reset config for boot CPU
* reset arch as AARCH64
* reset addr as function bl31_warm_entrypoint()
*/
mcucfg_init_archstate(0U, 0U, true);
mcucfg_set_bootaddr(0U, 0U, secure_entrypoint);
spmc_init();
plat_mt_pm = mt_plat_cpu_pm_init();
return 0;
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common/debug.h>
#include <common/runtime_svc.h>
uintptr_t mediatek_plat_sip_handler(uint32_t smc_fid,
u_register_t x1,
u_register_t x2,
u_register_t x3,
u_register_t x4,
void *cookie,
void *handle,
u_register_t flags)
{
switch (smc_fid) {
default:
ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
break;
}
SMC_RET1(handle, SMC_UNK);
}

View File

@ -8,8 +8,19 @@ MTK_PLAT := plat/mediatek
MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT}
PLAT_INCLUDES := -I${MTK_PLAT}/common/ \
-I${MTK_PLAT}/common/drivers/gic600/ \
-I${MTK_PLAT}/common/drivers/gpio/ \
-I${MTK_PLAT}/common/drivers/timer/ \
-I${MTK_PLAT_SOC}/drivers/dcm/ \
-I${MTK_PLAT_SOC}/drivers/emi_mpu/ \
-I${MTK_PLAT_SOC}/drivers/gpio/ \
-I${MTK_PLAT_SOC}/drivers/mcdi/ \
-I${MTK_PLAT_SOC}/drivers/pmic/ \
-I${MTK_PLAT_SOC}/drivers/rtc/ \
-I${MTK_PLAT_SOC}/drivers/spmc/ \
-I${MTK_PLAT_SOC}/include/
GICV3_SUPPORT_GIC600 := 1
include drivers/arm/gic/v3/gicv3.mk
include lib/xlat_tables_v2/xlat_tables.mk
@ -20,17 +31,38 @@ PLAT_BL_COMMON_SOURCES := ${GICV3_SOURCES} \
BL31_SOURCES += common/desc_image_load.c \
drivers/delay_timer/delay_timer.c \
drivers/gpio/gpio.c \
drivers/delay_timer/generic_delay_timer.c \
drivers/ti/uart/aarch64/16550_console.S \
lib/bl_aux_params/bl_aux_params.c \
lib/cpus/aarch64/cortex_a55.S \
lib/cpus/aarch64/cortex_a76.S \
plat/common/plat_gicv3.c \
${MTK_PLAT}/common/drivers/gic600/mt_gic_v3.c \
${MTK_PLAT}/common/drivers/gpio/mtgpio_common.c \
${MTK_PLAT}/common/drivers/pmic_wrap/pmic_wrap_init.c \
${MTK_PLAT}/common/drivers/rtc/rtc_common.c \
${MTK_PLAT}/common/mtk_plat_common.c \
${MTK_PLAT}/common/mtk_sip_svc.c \
${MTK_PLAT}/common/params_setup.c \
${MTK_PLAT}/common/drivers/timer/mt_timer.c \
${MTK_PLAT}/common/mtk_cirq.c \
${MTK_PLAT_SOC}/aarch64/platform_common.c \
${MTK_PLAT_SOC}/aarch64/plat_helpers.S \
${MTK_PLAT_SOC}/bl31_plat_setup.c \
${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm.c \
${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm_utils.c \
${MTK_PLAT_SOC}/drivers/emi_mpu/emi_mpu.c \
${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c \
${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm.c \
${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm_cpc.c \
${MTK_PLAT_SOC}/drivers/mcdi/mt_mcdi.c \
${MTK_PLAT_SOC}/drivers/pmic/pmic.c \
${MTK_PLAT_SOC}/drivers/rtc/rtc.c \
${MTK_PLAT_SOC}/drivers/spmc/mtspmc.c \
${MTK_PLAT_SOC}/plat_pm.c \
${MTK_PLAT_SOC}/plat_sip_calls.c \
${MTK_PLAT_SOC}/plat_topology.c
# Configs for A76 and A55
@ -40,6 +72,16 @@ CTX_INCLUDE_AARCH32_REGS := 0
ERRATA_A55_1530923 := 1
ERRATA_A55_1221012 := 1
ERRATA_A76_1257314 := 1
ERRATA_A76_1262606 := 1
ERRATA_A76_1262888 := 1
ERRATA_A76_1275112 := 1
ERRATA_A76_1286807 := 1
ERRATA_A76_1791580 := 1
ERRATA_A76_1165522 := 1
ERRATA_A76_1868343 := 1
ERRATA_A76_1946160 := 1
# indicate the reset vector address can be programmed
PROGRAMMABLE_RESET_ADDRESS := 1