Merge changes I93ecff4d,I30dd9a95,I8207eea9,Id4197b07,Ib810125b, ... into integration
* changes: mediatek: mt8183: add MTK MCDI driver mediatek: mt8183: add MTK SSPM driver mediatek: mt8183: add MTK SPM driver mediatek: mt8183: add MTK uart driver for controlling clock gate mediatek: mt8183: configure MCUSYS DCM mediatek: mt8173: refactor RTC and PMIC drivers
This commit is contained in:
commit
3ea2cc00fc
|
@ -1,165 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <mt8173_def.h>
|
||||
#include <pmic_wrap_init.h>
|
||||
|
||||
/* pmic wrap module wait_idle and read polling interval (in microseconds) */
|
||||
enum {
|
||||
WAIT_IDLE_POLLING_DELAY_US = 1,
|
||||
READ_POLLING_DELAY_US = 2
|
||||
};
|
||||
|
||||
static inline uint32_t wait_for_state_idle(uint32_t timeout_us,
|
||||
void *wacs_register,
|
||||
void *wacs_vldclr_register,
|
||||
uint32_t *read_reg)
|
||||
{
|
||||
uint32_t reg_rdata;
|
||||
uint32_t retry;
|
||||
|
||||
retry = (timeout_us + WAIT_IDLE_POLLING_DELAY_US) /
|
||||
WAIT_IDLE_POLLING_DELAY_US;
|
||||
|
||||
do {
|
||||
udelay(WAIT_IDLE_POLLING_DELAY_US);
|
||||
reg_rdata = mmio_read_32((uintptr_t)wacs_register);
|
||||
/* if last read command timeout,clear vldclr bit
|
||||
read command state machine:FSM_REQ-->wfdle-->WFVLDCLR;
|
||||
write:FSM_REQ-->idle */
|
||||
switch (((reg_rdata >> RDATA_WACS_FSM_SHIFT) &
|
||||
RDATA_WACS_FSM_MASK)) {
|
||||
case WACS_FSM_WFVLDCLR:
|
||||
mmio_write_32((uintptr_t)wacs_vldclr_register, 1);
|
||||
ERROR("WACS_FSM = PMIC_WRAP_WACS_VLDCLR\n");
|
||||
break;
|
||||
case WACS_FSM_WFDLE:
|
||||
ERROR("WACS_FSM = WACS_FSM_WFDLE\n");
|
||||
break;
|
||||
case WACS_FSM_REQ:
|
||||
ERROR("WACS_FSM = WACS_FSM_REQ\n");
|
||||
break;
|
||||
case WACS_FSM_IDLE:
|
||||
goto done;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
retry--;
|
||||
} while (retry);
|
||||
|
||||
done:
|
||||
if (!retry) /* timeout */
|
||||
return E_PWR_WAIT_IDLE_TIMEOUT;
|
||||
|
||||
if (read_reg)
|
||||
*read_reg = reg_rdata;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline uint32_t wait_for_state_ready(uint32_t timeout_us,
|
||||
void *wacs_register,
|
||||
uint32_t *read_reg)
|
||||
{
|
||||
uint32_t reg_rdata;
|
||||
uint32_t retry;
|
||||
|
||||
retry = (timeout_us + READ_POLLING_DELAY_US) / READ_POLLING_DELAY_US;
|
||||
|
||||
do {
|
||||
udelay(READ_POLLING_DELAY_US);
|
||||
reg_rdata = mmio_read_32((uintptr_t)wacs_register);
|
||||
|
||||
if (((reg_rdata >> RDATA_WACS_FSM_SHIFT) & RDATA_WACS_FSM_MASK)
|
||||
== WACS_FSM_WFVLDCLR)
|
||||
break;
|
||||
|
||||
retry--;
|
||||
} while (retry);
|
||||
|
||||
if (!retry) { /* timeout */
|
||||
ERROR("timeout when waiting for idle\n");
|
||||
return E_PWR_WAIT_IDLE_TIMEOUT_READ;
|
||||
}
|
||||
|
||||
if (read_reg)
|
||||
*read_reg = reg_rdata;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t pwrap_wacs2(uint32_t write,
|
||||
uint32_t adr,
|
||||
uint32_t wdata,
|
||||
uint32_t *rdata,
|
||||
uint32_t init_check)
|
||||
{
|
||||
uint32_t reg_rdata = 0;
|
||||
uint32_t wacs_write = 0;
|
||||
uint32_t wacs_adr = 0;
|
||||
uint32_t wacs_cmd = 0;
|
||||
uint32_t return_value = 0;
|
||||
|
||||
if (init_check) {
|
||||
reg_rdata = mmio_read_32((uintptr_t)&mt8173_pwrap->wacs2_rdata);
|
||||
/* Prevent someone to used pwrap before pwrap init */
|
||||
if (((reg_rdata >> RDATA_INIT_DONE_SHIFT) &
|
||||
RDATA_INIT_DONE_MASK) != WACS_INIT_DONE) {
|
||||
ERROR("initialization isn't finished\n");
|
||||
return E_PWR_NOT_INIT_DONE;
|
||||
}
|
||||
}
|
||||
reg_rdata = 0;
|
||||
/* Check IDLE in advance */
|
||||
return_value = wait_for_state_idle(TIMEOUT_WAIT_IDLE,
|
||||
&mt8173_pwrap->wacs2_rdata,
|
||||
&mt8173_pwrap->wacs2_vldclr,
|
||||
0);
|
||||
if (return_value != 0) {
|
||||
ERROR("wait_for_fsm_idle fail,return_value=%d\n", return_value);
|
||||
goto FAIL;
|
||||
}
|
||||
wacs_write = write << 31;
|
||||
wacs_adr = (adr >> 1) << 16;
|
||||
wacs_cmd = wacs_write | wacs_adr | wdata;
|
||||
|
||||
mmio_write_32((uintptr_t)&mt8173_pwrap->wacs2_cmd, wacs_cmd);
|
||||
if (write == 0) {
|
||||
if (NULL == rdata) {
|
||||
ERROR("rdata is a NULL pointer\n");
|
||||
return_value = E_PWR_INVALID_ARG;
|
||||
goto FAIL;
|
||||
}
|
||||
return_value = wait_for_state_ready(TIMEOUT_READ,
|
||||
&mt8173_pwrap->wacs2_rdata,
|
||||
®_rdata);
|
||||
if (return_value != 0) {
|
||||
ERROR("wait_for_fsm_vldclr fail,return_value=%d\n",
|
||||
return_value);
|
||||
goto FAIL;
|
||||
}
|
||||
*rdata = ((reg_rdata >> RDATA_WACS_RDATA_SHIFT)
|
||||
& RDATA_WACS_RDATA_MASK);
|
||||
mmio_write_32((uintptr_t)&mt8173_pwrap->wacs2_vldclr, 1);
|
||||
}
|
||||
FAIL:
|
||||
return return_value;
|
||||
}
|
||||
|
||||
/* external API for pmic_wrap user */
|
||||
|
||||
int32_t pwrap_read(uint32_t adr, uint32_t *rdata)
|
||||
{
|
||||
return pwrap_wacs2(0, adr, 0, rdata, 1);
|
||||
}
|
||||
|
||||
int32_t pwrap_write(uint32_t adr, uint32_t wdata)
|
||||
{
|
||||
return pwrap_wacs2(1, adr, wdata, 0, 1);
|
||||
}
|
|
@ -7,11 +7,13 @@
|
|||
#ifndef PMIC_WRAP_INIT_H
|
||||
#define PMIC_WRAP_INIT_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 mt8173_pmic_wrap_regs *const mt8173_pwrap =
|
||||
static struct mt8173_pmic_wrap_regs *const mtk_pwrap =
|
||||
(void *)PMIC_WRAP_BASE;
|
||||
|
||||
/* timeout setting */
|
||||
|
|
|
@ -5,66 +5,11 @@
|
|||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
|
||||
#include <mt8173_def.h>
|
||||
#include <pmic_wrap_init.h>
|
||||
#include <rtc.h>
|
||||
|
||||
/* RTC busy status polling interval and retry count */
|
||||
enum {
|
||||
RTC_WRTGR_POLLING_DELAY_MS = 10,
|
||||
RTC_WRTGR_POLLING_CNT = 100
|
||||
};
|
||||
|
||||
static uint16_t RTC_Read(uint32_t addr)
|
||||
{
|
||||
uint32_t rdata = 0;
|
||||
|
||||
pwrap_read((uint32_t)addr, &rdata);
|
||||
return (uint16_t)rdata;
|
||||
}
|
||||
|
||||
static void RTC_Write(uint32_t addr, uint16_t data)
|
||||
{
|
||||
pwrap_write((uint32_t)addr, (uint32_t)data);
|
||||
}
|
||||
|
||||
static inline int32_t rtc_busy_wait(void)
|
||||
{
|
||||
uint64_t retry = RTC_WRTGR_POLLING_CNT;
|
||||
|
||||
do {
|
||||
mdelay(RTC_WRTGR_POLLING_DELAY_MS);
|
||||
if (!(RTC_Read(RTC_BBPU) & RTC_BBPU_CBUSY))
|
||||
return 1;
|
||||
retry--;
|
||||
} while (retry);
|
||||
|
||||
ERROR("[RTC] rtc cbusy time out!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t Write_trigger(void)
|
||||
{
|
||||
RTC_Write(RTC_WRTGR, 1);
|
||||
return rtc_busy_wait();
|
||||
}
|
||||
|
||||
static int32_t Writeif_unlock(void)
|
||||
{
|
||||
RTC_Write(RTC_PROT, RTC_PROT_UNLOCK1);
|
||||
if (!Write_trigger())
|
||||
return 0;
|
||||
RTC_Write(RTC_PROT, RTC_PROT_UNLOCK2);
|
||||
if (!Write_trigger())
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void rtc_bbpu_power_down(void)
|
||||
{
|
||||
uint16_t bbpu;
|
||||
|
@ -73,7 +18,7 @@ void rtc_bbpu_power_down(void)
|
|||
bbpu = RTC_BBPU_KEY | RTC_BBPU_AUTO | RTC_BBPU_PWREN;
|
||||
if (Writeif_unlock()) {
|
||||
RTC_Write(RTC_BBPU, bbpu);
|
||||
if (!Write_trigger())
|
||||
if (!RTC_Write_Trigger())
|
||||
assert(0);
|
||||
} else {
|
||||
assert(0);
|
||||
|
|
|
@ -49,6 +49,12 @@ enum {
|
|||
RTC_BBPU_KEY = 0x43 << 8
|
||||
};
|
||||
|
||||
/* 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_bbpu_power_down(void);
|
||||
|
||||
#endif /* RTC_H */
|
||||
|
|
|
@ -35,6 +35,8 @@ BL31_SOURCES += common/desc_image_load.c \
|
|||
lib/cpus/aarch64/cortex_a53.S \
|
||||
lib/cpus/aarch64/cortex_a57.S \
|
||||
lib/cpus/aarch64/cortex_a72.S \
|
||||
${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_SOC}/aarch64/plat_helpers.S \
|
||||
|
@ -42,7 +44,6 @@ BL31_SOURCES += common/desc_image_load.c \
|
|||
${MTK_PLAT_SOC}/bl31_plat_setup.c \
|
||||
${MTK_PLAT_SOC}/drivers/crypt/crypt.c \
|
||||
${MTK_PLAT_SOC}/drivers/mtcmos/mtcmos.c \
|
||||
${MTK_PLAT_SOC}/drivers/pmic/pmic_wrap_init.c \
|
||||
${MTK_PLAT_SOC}/drivers/rtc/rtc.c \
|
||||
${MTK_PLAT_SOC}/drivers/spm/spm.c \
|
||||
${MTK_PLAT_SOC}/drivers/spm/spm_hotplug.c \
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <mt_gic_v3.h>
|
||||
#include <lib/coreboot.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <mtk_mcdi.h>
|
||||
#include <mtk_plat_common.h>
|
||||
#include <mtspmc.h>
|
||||
#include <plat_debug.h>
|
||||
|
@ -23,6 +24,7 @@
|
|||
#include <plat_private.h>
|
||||
#include <platform_def.h>
|
||||
#include <scu.h>
|
||||
#include <spm.h>
|
||||
#include <drivers/ti/uart/uart_16550.h>
|
||||
|
||||
static entry_point_info_t bl32_ep_info;
|
||||
|
@ -32,15 +34,49 @@ static void platform_setup_cpu(void)
|
|||
{
|
||||
mmio_write_32((uintptr_t)&mt8183_mcucfg->mp0_rw_rsvd0, 0x00000001);
|
||||
|
||||
VERBOSE("addr of cci_adb400_dcm_config: 0x%x\n",
|
||||
mmio_read_32((uintptr_t)&mt8183_mcucfg->cci_adb400_dcm_config));
|
||||
VERBOSE("addr of sync_dcm_config: 0x%x\n",
|
||||
mmio_read_32((uintptr_t)&mt8183_mcucfg->sync_dcm_config));
|
||||
|
||||
VERBOSE("mp0_spmc: 0x%x\n",
|
||||
mmio_read_32((uintptr_t)&mt8183_mcucfg->mp0_cputop_spmc_ctl));
|
||||
VERBOSE("mp1_spmc: 0x%x\n",
|
||||
mmio_read_32((uintptr_t)&mt8183_mcucfg->mp1_cputop_spmc_ctl));
|
||||
/* Mcusys dcm control */
|
||||
/* Enable pll plldiv dcm */
|
||||
mmio_setbits_32((uintptr_t)&mt8183_mcucfg->bus_pll_divider_cfg,
|
||||
BUS_PLLDIV_DCM);
|
||||
mmio_setbits_32((uintptr_t)&mt8183_mcucfg->mp0_pll_divider_cfg,
|
||||
MP0_PLLDIV_DCM);
|
||||
mmio_setbits_32((uintptr_t)&mt8183_mcucfg->mp2_pll_divider_cfg,
|
||||
MP2_PLLDIV_DCM);
|
||||
/* Enable mscib dcm */
|
||||
mmio_clrsetbits_32((uintptr_t)&mt8183_mcucfg->mscib_dcm_en,
|
||||
MCSIB_CACTIVE_SEL_MASK, MCSIB_CACTIVE_SEL);
|
||||
mmio_clrsetbits_32((uintptr_t)&mt8183_mcucfg->mscib_dcm_en,
|
||||
MCSIB_DCM_MASK, MCSIB_DCM);
|
||||
/* Enable adb400 dcm */
|
||||
mmio_clrsetbits_32((uintptr_t)&mt8183_mcucfg->cci_adb400_dcm_config,
|
||||
CCI_ADB400_DCM_MASK, CCI_ADB400_DCM);
|
||||
/* Enable bus clock dcm */
|
||||
mmio_setbits_32((uintptr_t)&mt8183_mcucfg->cci_clk_ctrl,
|
||||
MCU_BUS_DCM);
|
||||
/* Enable bus fabric dcm */
|
||||
mmio_clrsetbits_32(
|
||||
(uintptr_t)&mt8183_mcucfg->mcusys_bus_fabric_dcm_ctrl,
|
||||
MCUSYS_BUS_FABRIC_DCM_MASK,
|
||||
MCUSYS_BUS_FABRIC_DCM);
|
||||
/* Enable l2c sram dcm */
|
||||
mmio_setbits_32((uintptr_t)&mt8183_mcucfg->l2c_sram_ctrl,
|
||||
L2C_SRAM_DCM);
|
||||
/* Enable busmp0 sync dcm */
|
||||
mmio_clrsetbits_32((uintptr_t)&mt8183_mcucfg->sync_dcm_config,
|
||||
SYNC_DCM_MASK, SYNC_DCM);
|
||||
/* Enable cntvalue dcm */
|
||||
mmio_setbits_32((uintptr_t)&mt8183_mcucfg->mcu_misc_dcm_ctrl,
|
||||
CNTVALUEB_DCM);
|
||||
/* Enable dcm cluster stall */
|
||||
mmio_clrsetbits_32(
|
||||
(uintptr_t)&mt8183_mcucfg->sync_dcm_cluster_config,
|
||||
MCUSYS_MAX_ACCESS_LATENCY_MASK,
|
||||
MCUSYS_MAX_ACCESS_LATENCY);
|
||||
mmio_setbits_32((uintptr_t)&mt8183_mcucfg->sync_dcm_cluster_config,
|
||||
MCU0_SYNC_DCM_STALL_WR_EN);
|
||||
/* Enable rgu dcm */
|
||||
mmio_setbits_32((uintptr_t)&mt8183_mcucfg->mp0_rgu_dcm_config,
|
||||
CPUSYS_RGU_DCM_CINFIG);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -112,6 +148,8 @@ void bl31_platform_setup(void)
|
|||
#if SPMC_MODE == 1
|
||||
spmc_init();
|
||||
#endif
|
||||
spm_boot_init();
|
||||
mcdi_init();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
|
@ -0,0 +1,259 @@
|
|||
/*
|
||||
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <sspm_reg.h>
|
||||
#include <mtk_mcdi.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void sspm_set_bootaddr(uint32_t bootaddr)
|
||||
{
|
||||
mcdi_mbox_write(MCDI_MBOX_BOOTADDR, bootaddr);
|
||||
}
|
||||
|
||||
void sspm_cluster_pwr_off_notify(uint32_t cluster)
|
||||
{
|
||||
mcdi_mbox_write(MCDI_MBOX_CLUSTER_0_ATF_ACTION_DONE + cluster, 1);
|
||||
}
|
||||
|
||||
void sspm_cluster_pwr_on_notify(uint32_t cluster)
|
||||
{
|
||||
mcdi_mbox_write(MCDI_MBOX_CLUSTER_0_ATF_ACTION_DONE + cluster, 0);
|
||||
}
|
||||
|
||||
void sspm_standbywfi_irq_enable(uint32_t cpu_idx)
|
||||
{
|
||||
mmio_write_32(SSPM_CFGREG_ACAO_INT_SET, STANDBYWFI_EN(cpu_idx));
|
||||
}
|
||||
|
||||
uint32_t mcdi_avail_cpu_mask_read(void)
|
||||
{
|
||||
return mcdi_mbox_read(MCDI_MBOX_AVAIL_CPU_MASK);
|
||||
}
|
||||
|
||||
uint32_t mcdi_avail_cpu_mask_write(uint32_t mask)
|
||||
{
|
||||
mcdi_mbox_write(MCDI_MBOX_AVAIL_CPU_MASK, mask);
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
uint32_t mcdi_avail_cpu_mask_set(uint32_t mask)
|
||||
{
|
||||
uint32_t m;
|
||||
|
||||
m = mcdi_mbox_read(MCDI_MBOX_AVAIL_CPU_MASK);
|
||||
m |= mask;
|
||||
mcdi_mbox_write(MCDI_MBOX_AVAIL_CPU_MASK, m);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
uint32_t mcdi_avail_cpu_mask_clr(uint32_t mask)
|
||||
{
|
||||
uint32_t m;
|
||||
|
||||
m = mcdi_mbox_read(MCDI_MBOX_AVAIL_CPU_MASK);
|
||||
m &= ~mask;
|
||||
mcdi_mbox_write(MCDI_MBOX_AVAIL_CPU_MASK, m);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
uint32_t mcdi_cpu_cluster_pwr_stat_read(void)
|
||||
{
|
||||
return mcdi_mbox_read(MCDI_MBOX_CPU_CLUSTER_PWR_STAT);
|
||||
}
|
||||
|
||||
#define PAUSE_BIT 1
|
||||
#define CLUSTER_OFF_OFS 20
|
||||
#define CPU_OFF_OFS 24
|
||||
#define CLUSTER_ON_OFS 4
|
||||
#define CPU_ON_OFS 8
|
||||
|
||||
static uint32_t target_mask(int cluster, int cpu_idx, bool on)
|
||||
{
|
||||
uint32_t t = 0;
|
||||
|
||||
if (on) {
|
||||
if (cluster >= 0)
|
||||
t |= BIT(cluster + CLUSTER_ON_OFS);
|
||||
|
||||
if (cpu_idx >= 0)
|
||||
t |= BIT(cpu_idx + CPU_ON_OFS);
|
||||
} else {
|
||||
if (cluster >= 0)
|
||||
t |= BIT(cluster + CLUSTER_OFF_OFS);
|
||||
|
||||
if (cpu_idx >= 0)
|
||||
t |= BIT(cpu_idx + CPU_OFF_OFS);
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
void mcdi_pause_clr(int cluster, int cpu_idx, bool on)
|
||||
{
|
||||
uint32_t tgt = target_mask(cluster, cpu_idx, on);
|
||||
uint32_t m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION);
|
||||
|
||||
m &= ~tgt;
|
||||
mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m);
|
||||
}
|
||||
|
||||
void mcdi_pause_set(int cluster, int cpu_idx, bool on)
|
||||
{
|
||||
uint32_t tgt = target_mask(cluster, cpu_idx, on);
|
||||
uint32_t m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION);
|
||||
uint32_t tgtn = target_mask(-1, cpu_idx, !on);
|
||||
|
||||
/* request on and off at the same time to ensure it can be paused */
|
||||
m |= tgt | tgtn;
|
||||
mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m);
|
||||
|
||||
/* wait pause_ack */
|
||||
while (!mcdi_mbox_read(MCDI_MBOX_PAUSE_ACK))
|
||||
;
|
||||
|
||||
/* clear non-requested operation */
|
||||
m &= ~tgtn;
|
||||
mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m);
|
||||
}
|
||||
|
||||
void mcdi_pause(void)
|
||||
{
|
||||
uint32_t m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION) | BIT(PAUSE_BIT);
|
||||
|
||||
mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m);
|
||||
|
||||
/* wait pause_ack */
|
||||
while (!mcdi_mbox_read(MCDI_MBOX_PAUSE_ACK))
|
||||
;
|
||||
}
|
||||
|
||||
void mcdi_unpause(void)
|
||||
{
|
||||
uint32_t m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION) & ~BIT(PAUSE_BIT);
|
||||
|
||||
mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m);
|
||||
}
|
||||
|
||||
void mcdi_hotplug_wait_ack(int cluster, int cpu_idx, bool on)
|
||||
{
|
||||
uint32_t tgt = target_mask(cluster, cpu_idx, on);
|
||||
uint32_t ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK);
|
||||
|
||||
/* wait until ack */
|
||||
while (!(ack & tgt))
|
||||
ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK);
|
||||
}
|
||||
|
||||
void mcdi_hotplug_clr(int cluster, int cpu_idx, bool on)
|
||||
{
|
||||
uint32_t tgt = target_mask(cluster, cpu_idx, on);
|
||||
uint32_t tgt_cpu = target_mask(-1, cpu_idx, on);
|
||||
uint32_t cmd = mcdi_mbox_read(MCDI_MBOX_HP_CMD);
|
||||
uint32_t ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK);
|
||||
|
||||
if (!(cmd & tgt))
|
||||
return;
|
||||
|
||||
/* wait until ack */
|
||||
while (!(ack & tgt_cpu))
|
||||
ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK);
|
||||
|
||||
cmd &= ~tgt;
|
||||
mcdi_mbox_write(MCDI_MBOX_HP_CMD, cmd);
|
||||
}
|
||||
|
||||
void mcdi_hotplug_set(int cluster, int cpu_idx, bool on)
|
||||
{
|
||||
uint32_t tgt = target_mask(cluster, cpu_idx, on);
|
||||
uint32_t tgt_cpu = target_mask(-1, cpu_idx, on);
|
||||
uint32_t cmd = mcdi_mbox_read(MCDI_MBOX_HP_CMD);
|
||||
uint32_t ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK);
|
||||
|
||||
if ((cmd & tgt) == tgt)
|
||||
return;
|
||||
|
||||
/* wait until ack clear */
|
||||
while (ack & tgt_cpu)
|
||||
ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK);
|
||||
|
||||
cmd |= tgt;
|
||||
mcdi_mbox_write(MCDI_MBOX_HP_CMD, cmd);
|
||||
}
|
||||
|
||||
bool check_mcdi_ctl_stat(void)
|
||||
{
|
||||
uint32_t clk_regs[] = {0x100010ac, 0x100010c8};
|
||||
uint32_t clk_mask[] = {0x00028000, 0x00000018};
|
||||
uint32_t tgt = target_mask(0, 0, true);
|
||||
uint32_t m;
|
||||
int i;
|
||||
|
||||
/* check clk status */
|
||||
for (i = 0; i < ARRAY_SIZE(clk_regs); i++) {
|
||||
if (mmio_read_32(clk_regs[i]) & clk_mask[i]) {
|
||||
WARN("mcdi: clk check fail.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* check mcdi cmd handling */
|
||||
m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION) | BIT(PAUSE_BIT);
|
||||
mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m);
|
||||
|
||||
i = 500;
|
||||
while (!mcdi_mbox_read(MCDI_MBOX_PAUSE_ACK) && --i > 0)
|
||||
udelay(10);
|
||||
|
||||
m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION) & ~BIT(PAUSE_BIT);
|
||||
mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m);
|
||||
|
||||
if (i == 0) {
|
||||
WARN("mcdi: pause_action fail.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* check mcdi cmd handling */
|
||||
if (mcdi_mbox_read(MCDI_MBOX_HP_CMD) ||
|
||||
mcdi_mbox_read(MCDI_MBOX_HP_ACK)) {
|
||||
WARN("mcdi: hp_cmd fail.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
mcdi_mbox_write(MCDI_MBOX_HP_CMD, tgt);
|
||||
|
||||
i = 500;
|
||||
while ((mcdi_mbox_read(MCDI_MBOX_HP_ACK) & tgt) != tgt && --i > 0)
|
||||
udelay(10);
|
||||
|
||||
mcdi_mbox_write(MCDI_MBOX_HP_CMD, 0);
|
||||
|
||||
if (i == 0) {
|
||||
WARN("mcdi: hp_ack fail.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void mcdi_init(void)
|
||||
{
|
||||
mcdi_avail_cpu_mask_write(0x01); /* cpu0 default on */
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef __MTK_MCDI_H__
|
||||
#define __MTK_MCDI_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
void sspm_set_bootaddr(uint32_t bootaddr);
|
||||
void sspm_standbywfi_irq_enable(uint32_t cpu_idx);
|
||||
void sspm_cluster_pwr_off_notify(uint32_t cluster);
|
||||
void sspm_cluster_pwr_on_notify(uint32_t cluster);
|
||||
|
||||
uint32_t mcdi_avail_cpu_mask_read(void);
|
||||
uint32_t mcdi_avail_cpu_mask_write(uint32_t mask);
|
||||
uint32_t mcdi_avail_cpu_mask_set(uint32_t mask);
|
||||
uint32_t mcdi_avail_cpu_mask_clr(uint32_t mask);
|
||||
uint32_t mcdi_cpu_cluster_pwr_stat_read(void);
|
||||
|
||||
void mcdi_pause(void);
|
||||
void mcdi_unpause(void);
|
||||
void mcdi_pause_set(int cluster, int cpu_idx, bool on);
|
||||
void mcdi_pause_clr(int cluster, int cpu_idx, bool on);
|
||||
void mcdi_hotplug_set(int cluster, int cpu_idx, bool on);
|
||||
void mcdi_hotplug_clr(int cluster, int cpu_idx, bool on);
|
||||
void mcdi_hotplug_wait_ack(int cluster, int cpu_idx, bool on);
|
||||
|
||||
bool check_mcdi_ctl_stat(void);
|
||||
void mcdi_init(void);
|
||||
|
||||
#endif /* __MTK_MCDI_H__ */
|
|
@ -7,6 +7,24 @@
|
|||
#include <pmic_wrap_init.h>
|
||||
#include <pmic.h>
|
||||
|
||||
void bcpu_enable(uint32_t en)
|
||||
{
|
||||
pwrap_write(PMIC_VPROC11_OP_EN, 0x1);
|
||||
if (en)
|
||||
pwrap_write(PMIC_VPROC11_CON0, 1);
|
||||
else
|
||||
pwrap_write(PMIC_VPROC11_CON0, 0);
|
||||
}
|
||||
|
||||
void bcpu_sram_enable(uint32_t en)
|
||||
{
|
||||
pwrap_write(PMIC_VSRAM_PROC11_OP_EN, 0x1);
|
||||
if (en)
|
||||
pwrap_write(PMIC_VSRAM_PROC11_CON0, 1);
|
||||
else
|
||||
pwrap_write(PMIC_VSRAM_PROC11_CON0, 0);
|
||||
}
|
||||
|
||||
void wk_pmic_enable_sdn_delay(void)
|
||||
{
|
||||
uint32_t con;
|
||||
|
|
|
@ -10,7 +10,11 @@
|
|||
enum {
|
||||
PMIC_TMA_KEY = 0x03a8,
|
||||
PMIC_PWRHOLD = 0x0a08,
|
||||
PMIC_PSEQ_ELR11 = 0x0a62
|
||||
PMIC_PSEQ_ELR11 = 0x0a62,
|
||||
PMIC_VPROC11_CON0 = 0x1388,
|
||||
PMIC_VPROC11_OP_EN = 0x1390,
|
||||
PMIC_VSRAM_PROC11_CON0 = 0x1b46,
|
||||
PMIC_VSRAM_PROC11_OP_EN = 0x1b4e
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -18,6 +22,8 @@ enum {
|
|||
};
|
||||
|
||||
/* external API */
|
||||
void bcpu_enable(uint32_t en);
|
||||
void bcpu_sram_enable(uint32_t en);
|
||||
void wk_pmic_enable_sdn_delay(void);
|
||||
void pmic_power_off(void);
|
||||
|
||||
|
|
|
@ -0,0 +1,328 @@
|
|||
/*
|
||||
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include <lib/bakery_lock.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <spm.h>
|
||||
#include <spm_pmic_wrap.h>
|
||||
|
||||
DEFINE_BAKERY_LOCK(spm_lock);
|
||||
|
||||
const char *wakeup_src_str[32] = {
|
||||
[0] = "R12_PCM_TIMER",
|
||||
[1] = "R12_SSPM_WDT_EVENT_B",
|
||||
[2] = "R12_KP_IRQ_B",
|
||||
[3] = "R12_APWDT_EVENT_B",
|
||||
[4] = "R12_APXGPT1_EVENT_B",
|
||||
[5] = "R12_CONN2AP_SPM_WAKEUP_B",
|
||||
[6] = "R12_EINT_EVENT_B",
|
||||
[7] = "R12_CONN_WDT_IRQ_B",
|
||||
[8] = "R12_CCIF0_EVENT_B",
|
||||
[9] = "R12_LOWBATTERY_IRQ_B",
|
||||
[10] = "R12_SSPM_SPM_IRQ_B",
|
||||
[11] = "R12_SCP_SPM_IRQ_B",
|
||||
[12] = "R12_SCP_WDT_EVENT_B",
|
||||
[13] = "R12_PCM_WDT_WAKEUP_B",
|
||||
[14] = "R12_USB_CDSC_B ",
|
||||
[15] = "R12_USB_POWERDWN_B",
|
||||
[16] = "R12_SYS_TIMER_EVENT_B",
|
||||
[17] = "R12_EINT_EVENT_SECURE_B",
|
||||
[18] = "R12_CCIF1_EVENT_B",
|
||||
[19] = "R12_UART0_IRQ_B",
|
||||
[20] = "R12_AFE_IRQ_MCU_B",
|
||||
[21] = "R12_THERM_CTRL_EVENT_B",
|
||||
[22] = "R12_SYS_CIRQ_IRQ_B",
|
||||
[23] = "R12_MD2AP_PEER_EVENT_B",
|
||||
[24] = "R12_CSYSPWREQ_B",
|
||||
[25] = "R12_MD1_WDT_B ",
|
||||
[26] = "R12_CLDMA_EVENT_B",
|
||||
[27] = "R12_SEJ_WDT_GPT_B",
|
||||
[28] = "R12_ALL_SSPM_WAKEUP_B",
|
||||
[29] = "R12_CPU_IRQ_B",
|
||||
[30] = "R12_CPU_WFI_AND_B"
|
||||
};
|
||||
|
||||
const char *spm_get_firmware_version(void)
|
||||
{
|
||||
return "DYNAMIC_SPM_FW_VERSION";
|
||||
}
|
||||
|
||||
void spm_lock_init(void)
|
||||
{
|
||||
bakery_lock_init(&spm_lock);
|
||||
}
|
||||
|
||||
void spm_lock_get(void)
|
||||
{
|
||||
bakery_lock_get(&spm_lock);
|
||||
}
|
||||
|
||||
void spm_lock_release(void)
|
||||
{
|
||||
bakery_lock_release(&spm_lock);
|
||||
}
|
||||
|
||||
void spm_set_bootaddr(unsigned long bootaddr)
|
||||
{
|
||||
/* initialize core4~7 boot entry address */
|
||||
mmio_write_32(SW2SPM_MAILBOX_3, bootaddr);
|
||||
}
|
||||
|
||||
void spm_set_cpu_status(int cpu)
|
||||
{
|
||||
if (cpu >= 0 && cpu < 4) {
|
||||
mmio_write_32(ROOT_CPUTOP_ADDR, 0x10006204);
|
||||
mmio_write_32(ROOT_CORE_ADDR, 0x10006208 + (cpu * 0x4));
|
||||
} else if (cpu >= 4 && cpu < 8) {
|
||||
mmio_write_32(ROOT_CPUTOP_ADDR, 0x10006218);
|
||||
mmio_write_32(ROOT_CORE_ADDR, 0x1000621c + ((cpu - 4) * 0x4));
|
||||
} else {
|
||||
ERROR("%s: error cpu number %d\n", __func__, cpu);
|
||||
}
|
||||
}
|
||||
|
||||
void spm_set_power_control(const struct pwr_ctrl *pwrctrl)
|
||||
{
|
||||
mmio_write_32(SPM_AP_STANDBY_CON,
|
||||
((pwrctrl->wfi_op & 0x1) << 0) |
|
||||
((pwrctrl->mp0_cputop_idle_mask & 0x1) << 1) |
|
||||
((pwrctrl->mp1_cputop_idle_mask & 0x1) << 2) |
|
||||
((pwrctrl->mcusys_idle_mask & 0x1) << 4) |
|
||||
((pwrctrl->mm_mask_b & 0x3) << 16) |
|
||||
((pwrctrl->md_ddr_en_0_dbc_en & 0x1) << 18) |
|
||||
((pwrctrl->md_ddr_en_1_dbc_en & 0x1) << 19) |
|
||||
((pwrctrl->md_mask_b & 0x3) << 20) |
|
||||
((pwrctrl->sspm_mask_b & 0x1) << 22) |
|
||||
((pwrctrl->scp_mask_b & 0x1) << 23) |
|
||||
((pwrctrl->srcclkeni_mask_b & 0x1) << 24) |
|
||||
((pwrctrl->md_apsrc_1_sel & 0x1) << 25) |
|
||||
((pwrctrl->md_apsrc_0_sel & 0x1) << 26) |
|
||||
((pwrctrl->conn_ddr_en_dbc_en & 0x1) << 27) |
|
||||
((pwrctrl->conn_mask_b & 0x1) << 28) |
|
||||
((pwrctrl->conn_apsrc_sel & 0x1) << 29));
|
||||
|
||||
mmio_write_32(SPM_SRC_REQ,
|
||||
((pwrctrl->spm_apsrc_req & 0x1) << 0) |
|
||||
((pwrctrl->spm_f26m_req & 0x1) << 1) |
|
||||
((pwrctrl->spm_infra_req & 0x1) << 3) |
|
||||
((pwrctrl->spm_vrf18_req & 0x1) << 4) |
|
||||
((pwrctrl->spm_ddren_req & 0x1) << 7) |
|
||||
((pwrctrl->spm_rsv_src_req & 0x7) << 8) |
|
||||
((pwrctrl->spm_ddren_2_req & 0x1) << 11) |
|
||||
((pwrctrl->cpu_md_dvfs_sop_force_on & 0x1) << 16));
|
||||
|
||||
mmio_write_32(SPM_SRC_MASK,
|
||||
((pwrctrl->csyspwreq_mask & 0x1) << 0) |
|
||||
((pwrctrl->ccif0_md_event_mask_b & 0x1) << 1) |
|
||||
((pwrctrl->ccif0_ap_event_mask_b & 0x1) << 2) |
|
||||
((pwrctrl->ccif1_md_event_mask_b & 0x1) << 3) |
|
||||
((pwrctrl->ccif1_ap_event_mask_b & 0x1) << 4) |
|
||||
((pwrctrl->ccif2_md_event_mask_b & 0x1) << 5) |
|
||||
((pwrctrl->ccif2_ap_event_mask_b & 0x1) << 6) |
|
||||
((pwrctrl->ccif3_md_event_mask_b & 0x1) << 7) |
|
||||
((pwrctrl->ccif3_ap_event_mask_b & 0x1) << 8) |
|
||||
((pwrctrl->md_srcclkena_0_infra_mask_b & 0x1) << 9) |
|
||||
((pwrctrl->md_srcclkena_1_infra_mask_b & 0x1) << 10) |
|
||||
((pwrctrl->conn_srcclkena_infra_mask_b & 0x1) << 11) |
|
||||
((pwrctrl->ufs_infra_req_mask_b & 0x1) << 12) |
|
||||
((pwrctrl->srcclkeni_infra_mask_b & 0x1) << 13) |
|
||||
((pwrctrl->md_apsrc_req_0_infra_mask_b & 0x1) << 14) |
|
||||
((pwrctrl->md_apsrc_req_1_infra_mask_b & 0x1) << 15) |
|
||||
((pwrctrl->conn_apsrcreq_infra_mask_b & 0x1) << 16) |
|
||||
((pwrctrl->ufs_srcclkena_mask_b & 0x1) << 17) |
|
||||
((pwrctrl->md_vrf18_req_0_mask_b & 0x1) << 18) |
|
||||
((pwrctrl->md_vrf18_req_1_mask_b & 0x1) << 19) |
|
||||
((pwrctrl->ufs_vrf18_req_mask_b & 0x1) << 20) |
|
||||
((pwrctrl->gce_vrf18_req_mask_b & 0x1) << 21) |
|
||||
((pwrctrl->conn_infra_req_mask_b & 0x1) << 22) |
|
||||
((pwrctrl->gce_apsrc_req_mask_b & 0x1) << 23) |
|
||||
((pwrctrl->disp0_apsrc_req_mask_b & 0x1) << 24) |
|
||||
((pwrctrl->disp1_apsrc_req_mask_b & 0x1) << 25) |
|
||||
((pwrctrl->mfg_req_mask_b & 0x1) << 26) |
|
||||
((pwrctrl->vdec_req_mask_b & 0x1) << 27));
|
||||
|
||||
mmio_write_32(SPM_SRC2_MASK,
|
||||
((pwrctrl->md_ddr_en_0_mask_b & 0x1) << 0) |
|
||||
((pwrctrl->md_ddr_en_1_mask_b & 0x1) << 1) |
|
||||
((pwrctrl->conn_ddr_en_mask_b & 0x1) << 2) |
|
||||
((pwrctrl->ddren_sspm_apsrc_req_mask_b & 0x1) << 3) |
|
||||
((pwrctrl->ddren_scp_apsrc_req_mask_b & 0x1) << 4) |
|
||||
((pwrctrl->disp0_ddren_mask_b & 0x1) << 5) |
|
||||
((pwrctrl->disp1_ddren_mask_b & 0x1) << 6) |
|
||||
((pwrctrl->gce_ddren_mask_b & 0x1) << 7) |
|
||||
((pwrctrl->ddren_emi_self_refresh_ch0_mask_b & 0x1)
|
||||
<< 8) |
|
||||
((pwrctrl->ddren_emi_self_refresh_ch1_mask_b & 0x1)
|
||||
<< 9));
|
||||
|
||||
mmio_write_32(SPM_WAKEUP_EVENT_MASK,
|
||||
((pwrctrl->spm_wakeup_event_mask & 0xffffffff) << 0));
|
||||
|
||||
mmio_write_32(SPM_WAKEUP_EVENT_EXT_MASK,
|
||||
((pwrctrl->spm_wakeup_event_ext_mask & 0xffffffff)
|
||||
<< 0));
|
||||
|
||||
mmio_write_32(SPM_SRC3_MASK,
|
||||
((pwrctrl->md_ddr_en_2_0_mask_b & 0x1) << 0) |
|
||||
((pwrctrl->md_ddr_en_2_1_mask_b & 0x1) << 1) |
|
||||
((pwrctrl->conn_ddr_en_2_mask_b & 0x1) << 2) |
|
||||
((pwrctrl->ddren2_sspm_apsrc_req_mask_b & 0x1) << 3) |
|
||||
((pwrctrl->ddren2_scp_apsrc_req_mask_b & 0x1) << 4) |
|
||||
((pwrctrl->disp0_ddren2_mask_b & 0x1) << 5) |
|
||||
((pwrctrl->disp1_ddren2_mask_b & 0x1) << 6) |
|
||||
((pwrctrl->gce_ddren2_mask_b & 0x1) << 7) |
|
||||
((pwrctrl->ddren2_emi_self_refresh_ch0_mask_b & 0x1)
|
||||
<< 8) |
|
||||
((pwrctrl->ddren2_emi_self_refresh_ch1_mask_b & 0x1)
|
||||
<< 9));
|
||||
|
||||
mmio_write_32(MP0_CPU0_WFI_EN,
|
||||
((pwrctrl->mp0_cpu0_wfi_en & 0x1) << 0));
|
||||
mmio_write_32(MP0_CPU1_WFI_EN,
|
||||
((pwrctrl->mp0_cpu1_wfi_en & 0x1) << 0));
|
||||
mmio_write_32(MP0_CPU2_WFI_EN,
|
||||
((pwrctrl->mp0_cpu2_wfi_en & 0x1) << 0));
|
||||
mmio_write_32(MP0_CPU3_WFI_EN,
|
||||
((pwrctrl->mp0_cpu3_wfi_en & 0x1) << 0));
|
||||
|
||||
mmio_write_32(MP1_CPU0_WFI_EN,
|
||||
((pwrctrl->mp1_cpu0_wfi_en & 0x1) << 0));
|
||||
mmio_write_32(MP1_CPU1_WFI_EN,
|
||||
((pwrctrl->mp1_cpu1_wfi_en & 0x1) << 0));
|
||||
mmio_write_32(MP1_CPU2_WFI_EN,
|
||||
((pwrctrl->mp1_cpu2_wfi_en & 0x1) << 0));
|
||||
mmio_write_32(MP1_CPU3_WFI_EN,
|
||||
((pwrctrl->mp1_cpu3_wfi_en & 0x1) << 0));
|
||||
}
|
||||
|
||||
void spm_disable_pcm_timer(void)
|
||||
{
|
||||
mmio_clrsetbits_32(PCM_CON1, PCM_TIMER_EN_LSB, SPM_REGWR_CFG_KEY);
|
||||
}
|
||||
|
||||
void spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl)
|
||||
{
|
||||
uint32_t val, mask, isr;
|
||||
|
||||
val = pwrctrl->timer_val ? pwrctrl->timer_val : PCM_TIMER_MAX;
|
||||
mmio_write_32(PCM_TIMER_VAL, val);
|
||||
mmio_setbits_32(PCM_CON1, SPM_REGWR_CFG_KEY | PCM_TIMER_EN_LSB);
|
||||
|
||||
mask = pwrctrl->wake_src;
|
||||
|
||||
if (pwrctrl->csyspwreq_mask)
|
||||
mask &= ~WAKE_SRC_R12_CSYSPWREQ_B;
|
||||
|
||||
mmio_write_32(SPM_WAKEUP_EVENT_MASK, ~mask);
|
||||
|
||||
isr = mmio_read_32(SPM_IRQ_MASK) & SPM_TWAM_IRQ_MASK_LSB;
|
||||
mmio_write_32(SPM_IRQ_MASK, isr | ISRM_RET_IRQ_AUX);
|
||||
}
|
||||
|
||||
void spm_set_pcm_flags(const struct pwr_ctrl *pwrctrl)
|
||||
{
|
||||
mmio_write_32(SPM_SW_FLAG, pwrctrl->pcm_flags);
|
||||
mmio_write_32(SPM_SW_RSV_2, pwrctrl->pcm_flags1);
|
||||
}
|
||||
|
||||
void spm_set_pcm_wdt(int en)
|
||||
{
|
||||
if (en) {
|
||||
mmio_clrsetbits_32(PCM_CON1, PCM_WDT_WAKE_MODE_LSB,
|
||||
SPM_REGWR_CFG_KEY);
|
||||
|
||||
if (mmio_read_32(PCM_TIMER_VAL) > PCM_TIMER_MAX)
|
||||
mmio_write_32(PCM_TIMER_VAL, PCM_TIMER_MAX);
|
||||
mmio_write_32(PCM_WDT_VAL,
|
||||
mmio_read_32(PCM_TIMER_VAL) + PCM_WDT_TIMEOUT);
|
||||
mmio_setbits_32(PCM_CON1, SPM_REGWR_CFG_KEY | PCM_WDT_EN_LSB);
|
||||
} else {
|
||||
mmio_clrsetbits_32(PCM_CON1, PCM_WDT_EN_LSB,
|
||||
SPM_REGWR_CFG_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
void spm_send_cpu_wakeup_event(void)
|
||||
{
|
||||
mmio_write_32(PCM_REG_DATA_INI, 0);
|
||||
mmio_write_32(SPM_CPU_WAKEUP_EVENT, 1);
|
||||
}
|
||||
|
||||
void spm_get_wakeup_status(struct wake_status *wakesta)
|
||||
{
|
||||
wakesta->assert_pc = mmio_read_32(PCM_REG_DATA_INI);
|
||||
wakesta->r12 = mmio_read_32(SPM_SW_RSV_0);
|
||||
wakesta->r12_ext = mmio_read_32(PCM_REG12_EXT_DATA);
|
||||
wakesta->raw_sta = mmio_read_32(SPM_WAKEUP_STA);
|
||||
wakesta->raw_ext_sta = mmio_read_32(SPM_WAKEUP_EXT_STA);
|
||||
wakesta->wake_misc = mmio_read_32(SPM_BSI_D0_SR);
|
||||
wakesta->timer_out = mmio_read_32(SPM_BSI_D1_SR);
|
||||
wakesta->r13 = mmio_read_32(PCM_REG13_DATA);
|
||||
wakesta->idle_sta = mmio_read_32(SUBSYS_IDLE_STA);
|
||||
wakesta->req_sta = mmio_read_32(SRC_REQ_STA);
|
||||
wakesta->sw_flag = mmio_read_32(SPM_SW_FLAG);
|
||||
wakesta->sw_flag1 = mmio_read_32(SPM_SW_RSV_2);
|
||||
wakesta->r15 = mmio_read_32(PCM_REG15_DATA);
|
||||
wakesta->debug_flag = mmio_read_32(SPM_SW_DEBUG);
|
||||
wakesta->debug_flag1 = mmio_read_32(WDT_LATCH_SPARE0_FIX);
|
||||
wakesta->event_reg = mmio_read_32(SPM_BSI_D2_SR);
|
||||
wakesta->isr = mmio_read_32(SPM_IRQ_STA);
|
||||
}
|
||||
|
||||
void spm_clean_after_wakeup(void)
|
||||
{
|
||||
mmio_write_32(SPM_SW_RSV_0,
|
||||
mmio_read_32(SPM_WAKEUP_STA) |
|
||||
mmio_read_32(SPM_SW_RSV_0));
|
||||
mmio_write_32(SPM_CPU_WAKEUP_EVENT, 0);
|
||||
mmio_write_32(SPM_WAKEUP_EVENT_MASK, ~0);
|
||||
mmio_setbits_32(SPM_IRQ_MASK, ISRM_ALL_EXC_TWAM);
|
||||
mmio_write_32(SPM_IRQ_STA, ISRC_ALL_EXC_TWAM);
|
||||
mmio_write_32(SPM_SWINT_CLR, PCM_SW_INT_ALL);
|
||||
}
|
||||
|
||||
void spm_output_wake_reason(struct wake_status *wakesta, const char *scenario)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
if (wakesta->assert_pc != 0) {
|
||||
INFO("%s: PCM ASSERT AT %u, ULPOSC_CON = 0x%x\n",
|
||||
scenario, wakesta->assert_pc, mmio_read_32(ULPOSC_CON));
|
||||
goto spm_debug_flags;
|
||||
}
|
||||
|
||||
for (i = 0; i <= 31; i++) {
|
||||
if (wakesta->r12 & (1U << i)) {
|
||||
INFO("%s: wake up by %s, timer_out = %u\n",
|
||||
scenario, wakeup_src_str[i], wakesta->timer_out);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
spm_debug_flags:
|
||||
INFO("r15 = 0x%x, r13 = 0x%x, debug_flag = 0x%x 0x%x\n",
|
||||
wakesta->r15, wakesta->r13, wakesta->debug_flag,
|
||||
wakesta->debug_flag1);
|
||||
INFO("sw_flag = 0x%x 0x%x, r12 = 0x%x, r12_ext = 0x%x\n",
|
||||
wakesta->sw_flag, wakesta->sw_flag1, wakesta->r12,
|
||||
wakesta->r12_ext);
|
||||
INFO("idle_sta = 0x%x, req_sta = 0x%x, event_reg = 0x%x\n",
|
||||
wakesta->idle_sta, wakesta->req_sta, wakesta->event_reg);
|
||||
INFO("isr = 0x%x, raw_sta = 0x%x, raw_ext_sta = 0x%x\n",
|
||||
wakesta->isr, wakesta->raw_sta, wakesta->raw_ext_sta);
|
||||
INFO("wake_misc = 0x%x\n", wakesta->wake_misc);
|
||||
}
|
||||
|
||||
void spm_boot_init(void)
|
||||
{
|
||||
NOTICE("%s() start\n", __func__);
|
||||
|
||||
spm_lock_init();
|
||||
mt_spm_pmic_wrap_set_phase(PMIC_WRAP_PHASE_ALLINONE);
|
||||
|
||||
NOTICE("%s() end\n", __func__);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <platform_def.h>
|
||||
#include <spm.h>
|
||||
#include <spm_pmic_wrap.h>
|
||||
#include <lib/libc/string.h>
|
||||
|
||||
#define SLEEP_REG_MD_SPM_DVFS_CMD20 (SLEEP_REG_MD_BASE + 0x010)
|
||||
#define SLEEP_REG_MD_SPM_DVFS_CMD21 (SLEEP_REG_MD_BASE + 0x014)
|
||||
#define SLEEP_REG_MD_SPM_DVFS_CMD22 (SLEEP_REG_MD_BASE + 0x018)
|
||||
#define SLEEP_REG_MD_SPM_DVFS_CMD23 (SLEEP_REG_MD_BASE + 0x01C)
|
||||
|
||||
/* PMIC_WRAP -> PMIC MT6358 */
|
||||
#define VCORE_BASE_UV 50000
|
||||
#define VOLT_TO_PMIC_VAL(volt) (((volt) - VCORE_BASE_UV + 625 - 1) / 625)
|
||||
#define PMIC_VAL_TO_VOLT(pmic) (((pmic) * 625) + VCORE_BASE_UV)
|
||||
|
||||
#define DEFAULT_VOLT_VSRAM (100000)
|
||||
#define DEFAULT_VOLT_VCORE (100000)
|
||||
#define NR_PMIC_WRAP_CMD (NR_IDX_ALL)
|
||||
#define MAX_RETRY_COUNT (100)
|
||||
#define SPM_DATA_SHIFT (16)
|
||||
|
||||
#define BUCK_VCORE_ELR0 0x14AA
|
||||
#define BUCK_VPROC12_CON0 0x1408
|
||||
#define BUCK_VPROC11_CON0 0x1388
|
||||
#define TOP_SPI_CON0 0x044C
|
||||
#define LDO_VSRAM_PROC12_CON0 0x1B88
|
||||
#define LDO_VSRAM_PROC11_CON0 0x1B46
|
||||
#define BUCK_VMODEM_ELR0 0x15A6
|
||||
|
||||
struct pmic_wrap_cmd {
|
||||
unsigned long cmd_addr;
|
||||
unsigned long cmd_wdata;
|
||||
};
|
||||
|
||||
struct pmic_wrap_setting {
|
||||
enum pmic_wrap_phase_id phase;
|
||||
struct pmic_wrap_cmd addr[NR_PMIC_WRAP_CMD];
|
||||
struct {
|
||||
struct {
|
||||
unsigned long cmd_addr;
|
||||
unsigned long cmd_wdata;
|
||||
} _[NR_PMIC_WRAP_CMD];
|
||||
const int nr_idx;
|
||||
} set[NR_PMIC_WRAP_PHASE];
|
||||
};
|
||||
|
||||
static struct pmic_wrap_setting pw = {
|
||||
.phase = NR_PMIC_WRAP_PHASE,
|
||||
.addr = {{0, 0} },
|
||||
.set[PMIC_WRAP_PHASE_ALLINONE] = {
|
||||
._[CMD_0] = {BUCK_VCORE_ELR0, VOLT_TO_PMIC_VAL(70000),},
|
||||
._[CMD_1] = {BUCK_VCORE_ELR0, VOLT_TO_PMIC_VAL(80000),},
|
||||
._[CMD_2] = {BUCK_VPROC12_CON0, 0x3,},
|
||||
._[CMD_3] = {BUCK_VPROC12_CON0, 0x1,},
|
||||
._[CMD_4] = {BUCK_VPROC11_CON0, 0x3,},
|
||||
._[CMD_5] = {BUCK_VPROC11_CON0, 0x1,},
|
||||
._[CMD_6] = {TOP_SPI_CON0, 0x1,},
|
||||
._[CMD_7] = {TOP_SPI_CON0, 0x0,},
|
||||
._[CMD_8] = {BUCK_VPROC12_CON0, 0x0,},
|
||||
._[CMD_9] = {BUCK_VPROC12_CON0, 0x1,},
|
||||
._[CMD_10] = {BUCK_VPROC11_CON0, 0x0,},
|
||||
._[CMD_11] = {BUCK_VPROC11_CON0, 0x1,},
|
||||
._[CMD_12] = {LDO_VSRAM_PROC12_CON0, 0x0,},
|
||||
._[CMD_13] = {LDO_VSRAM_PROC12_CON0, 0x1,},
|
||||
._[CMD_14] = {LDO_VSRAM_PROC11_CON0, 0x0,},
|
||||
._[CMD_15] = {LDO_VSRAM_PROC11_CON0, 0x1,},
|
||||
._[CMD_20] = {BUCK_VMODEM_ELR0, VOLT_TO_PMIC_VAL(55000),},
|
||||
._[CMD_21] = {BUCK_VCORE_ELR0, VOLT_TO_PMIC_VAL(60000),},
|
||||
._[CMD_22] = {LDO_VSRAM_PROC11_CON0, 0x3,},
|
||||
._[CMD_23] = {LDO_VSRAM_PROC11_CON0, 0x1,},
|
||||
.nr_idx = NR_IDX_ALL
|
||||
}
|
||||
};
|
||||
|
||||
void _mt_spm_pmic_table_init(void)
|
||||
{
|
||||
struct pmic_wrap_cmd pwrap_cmd_default[NR_PMIC_WRAP_CMD] = {
|
||||
{(uint32_t)SPM_DVFS_CMD0, (uint32_t)SPM_DVFS_CMD0,},
|
||||
{(uint32_t)SPM_DVFS_CMD1, (uint32_t)SPM_DVFS_CMD1,},
|
||||
{(uint32_t)SPM_DVFS_CMD2, (uint32_t)SPM_DVFS_CMD2,},
|
||||
{(uint32_t)SPM_DVFS_CMD3, (uint32_t)SPM_DVFS_CMD3,},
|
||||
{(uint32_t)SPM_DVFS_CMD4, (uint32_t)SPM_DVFS_CMD4,},
|
||||
{(uint32_t)SPM_DVFS_CMD5, (uint32_t)SPM_DVFS_CMD5,},
|
||||
{(uint32_t)SPM_DVFS_CMD6, (uint32_t)SPM_DVFS_CMD6,},
|
||||
{(uint32_t)SPM_DVFS_CMD7, (uint32_t)SPM_DVFS_CMD7,},
|
||||
{(uint32_t)SPM_DVFS_CMD8, (uint32_t)SPM_DVFS_CMD8,},
|
||||
{(uint32_t)SPM_DVFS_CMD9, (uint32_t)SPM_DVFS_CMD9,},
|
||||
{(uint32_t)SPM_DVFS_CMD10, (uint32_t)SPM_DVFS_CMD10,},
|
||||
{(uint32_t)SPM_DVFS_CMD11, (uint32_t)SPM_DVFS_CMD11,},
|
||||
{(uint32_t)SPM_DVFS_CMD12, (uint32_t)SPM_DVFS_CMD12,},
|
||||
{(uint32_t)SPM_DVFS_CMD13, (uint32_t)SPM_DVFS_CMD13,},
|
||||
{(uint32_t)SPM_DVFS_CMD14, (uint32_t)SPM_DVFS_CMD14,},
|
||||
{(uint32_t)SPM_DVFS_CMD15, (uint32_t)SPM_DVFS_CMD15,},
|
||||
{(uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD20,
|
||||
(uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD20,},
|
||||
{(uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD21,
|
||||
(uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD21,},
|
||||
{(uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD22,
|
||||
(uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD22,},
|
||||
{(uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD23,
|
||||
(uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD23,}
|
||||
};
|
||||
|
||||
memcpy(pw.addr, pwrap_cmd_default, sizeof(pwrap_cmd_default));
|
||||
}
|
||||
|
||||
void mt_spm_pmic_wrap_set_phase(enum pmic_wrap_phase_id phase)
|
||||
{
|
||||
uint32_t idx, addr, data;
|
||||
|
||||
if (phase >= NR_PMIC_WRAP_PHASE)
|
||||
return;
|
||||
|
||||
if (pw.phase == phase)
|
||||
return;
|
||||
|
||||
if (pw.addr[0].cmd_addr == 0)
|
||||
_mt_spm_pmic_table_init();
|
||||
|
||||
pw.phase = phase;
|
||||
|
||||
mmio_write_32(POWERON_CONFIG_EN, SPM_REGWR_CFG_KEY |
|
||||
BCLK_CG_EN_LSB | MD_BCLK_CG_EN_LSB);
|
||||
for (idx = 0; idx < pw.set[phase].nr_idx; idx++) {
|
||||
addr = pw.set[phase]._[idx].cmd_addr << SPM_DATA_SHIFT;
|
||||
data = pw.set[phase]._[idx].cmd_wdata;
|
||||
mmio_write_32(pw.addr[idx].cmd_addr, addr | data);
|
||||
}
|
||||
}
|
||||
|
||||
void mt_spm_pmic_wrap_set_cmd(enum pmic_wrap_phase_id phase, uint32_t idx,
|
||||
uint32_t cmd_wdata)
|
||||
{
|
||||
uint32_t addr;
|
||||
|
||||
if (phase >= NR_PMIC_WRAP_PHASE)
|
||||
return;
|
||||
|
||||
if (idx >= pw.set[phase].nr_idx)
|
||||
return;
|
||||
|
||||
pw.set[phase]._[idx].cmd_wdata = cmd_wdata;
|
||||
|
||||
mmio_write_32(POWERON_CONFIG_EN, SPM_REGWR_CFG_KEY |
|
||||
BCLK_CG_EN_LSB | MD_BCLK_CG_EN_LSB);
|
||||
if (pw.phase == phase) {
|
||||
addr = pw.set[phase]._[idx].cmd_addr << SPM_DATA_SHIFT;
|
||||
mmio_write_32(pw.addr[idx].cmd_addr, addr | cmd_wdata);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t mt_spm_pmic_wrap_get_cmd(enum pmic_wrap_phase_id phase, uint32_t idx)
|
||||
{
|
||||
if (phase >= NR_PMIC_WRAP_PHASE)
|
||||
return 0;
|
||||
|
||||
if (idx >= pw.set[phase].nr_idx)
|
||||
return 0;
|
||||
|
||||
return pw.set[phase]._[idx].cmd_wdata;
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/****************************************************************
|
||||
* Auto generated by DE, please DO NOT modify this file directly.
|
||||
*****************************************************************/
|
||||
|
||||
#ifndef SPM_PMIC_WRAP__H
|
||||
#define SPM_PMIC_WRAP__H
|
||||
|
||||
enum pmic_wrap_phase_id {
|
||||
PMIC_WRAP_PHASE_ALLINONE,
|
||||
NR_PMIC_WRAP_PHASE
|
||||
};
|
||||
|
||||
/* IDX mapping */
|
||||
enum {
|
||||
CMD_0, /* 0x0 *//* PMIC_WRAP_PHASE_ALLINONE */
|
||||
CMD_1, /* 0x1 */
|
||||
CMD_2, /* 0x2 */
|
||||
CMD_3, /* 0x3 */
|
||||
CMD_4, /* 0x4 */
|
||||
CMD_5, /* 0x5 */
|
||||
CMD_6, /* 0x6 */
|
||||
CMD_7, /* 0x7 */
|
||||
CMD_8, /* 0x8 */
|
||||
CMD_9, /* 0x9 */
|
||||
CMD_10, /* 0xA */
|
||||
CMD_11, /* 0xB */
|
||||
CMD_12, /* 0xC */
|
||||
CMD_13, /* 0xD */
|
||||
CMD_14, /* 0xE */
|
||||
CMD_15, /* 0xF */
|
||||
CMD_20, /* 0x14 */
|
||||
CMD_21, /* 0x15 */
|
||||
CMD_22, /* 0x16 */
|
||||
CMD_23, /* 0x17 */
|
||||
NR_IDX_ALL
|
||||
};
|
||||
|
||||
/* APIs */
|
||||
void mt_spm_pmic_wrap_set_phase(enum pmic_wrap_phase_id phase);
|
||||
void mt_spm_pmic_wrap_set_cmd(enum pmic_wrap_phase_id phase,
|
||||
uint32_t idx, uint32_t cmd_wdata);
|
||||
uint64_t mt_spm_pmic_wrap_get_cmd(enum pmic_wrap_phase_id phase, uint32_t idx);
|
||||
#endif /* SPM_PMIC_WRAP__H */
|
||||
|
|
@ -0,0 +1,255 @@
|
|||
/*
|
||||
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <mt_gic_v3.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <platform_def.h>
|
||||
#include <pmic.h>
|
||||
#include <spm.h>
|
||||
#include <uart.h>
|
||||
|
||||
#define SPM_SYSCLK_SETTLE 99
|
||||
|
||||
#define WAKE_SRC_FOR_SUSPEND \
|
||||
(WAKE_SRC_R12_PCM_TIMER | \
|
||||
WAKE_SRC_R12_SSPM_WDT_EVENT_B | \
|
||||
WAKE_SRC_R12_KP_IRQ_B | \
|
||||
WAKE_SRC_R12_CONN2AP_SPM_WAKEUP_B | \
|
||||
WAKE_SRC_R12_EINT_EVENT_B | \
|
||||
WAKE_SRC_R12_CONN_WDT_IRQ_B | \
|
||||
WAKE_SRC_R12_CCIF0_EVENT_B | \
|
||||
WAKE_SRC_R12_SSPM_SPM_IRQ_B | \
|
||||
WAKE_SRC_R12_SCP_SPM_IRQ_B | \
|
||||
WAKE_SRC_R12_SCP_WDT_EVENT_B | \
|
||||
WAKE_SRC_R12_USB_CDSC_B | \
|
||||
WAKE_SRC_R12_USB_POWERDWN_B | \
|
||||
WAKE_SRC_R12_SYS_TIMER_EVENT_B | \
|
||||
WAKE_SRC_R12_EINT_EVENT_SECURE_B | \
|
||||
WAKE_SRC_R12_CCIF1_EVENT_B | \
|
||||
WAKE_SRC_R12_MD2AP_PEER_EVENT_B | \
|
||||
WAKE_SRC_R12_MD1_WDT_B | \
|
||||
WAKE_SRC_R12_CLDMA_EVENT_B | \
|
||||
WAKE_SRC_R12_SEJ_WDT_GPT_B)
|
||||
|
||||
#define SLP_PCM_FLAGS \
|
||||
(SPM_FLAG_DIS_VCORE_DVS | SPM_FLAG_DIS_VCORE_DFS | \
|
||||
SPM_FLAG_DIS_ATF_ABORT | SPM_FLAG_DISABLE_MMSYS_DVFS | \
|
||||
SPM_FLAG_DIS_INFRA_PDN | SPM_FLAG_SUSPEND_OPTION)
|
||||
|
||||
#define SLP_PCM_FLAGS1 \
|
||||
(SPM_FLAG1_DISABLE_MCDSR)
|
||||
|
||||
static const struct pwr_ctrl suspend_ctrl = {
|
||||
.wake_src = WAKE_SRC_FOR_SUSPEND,
|
||||
.pcm_flags = SLP_PCM_FLAGS,
|
||||
.pcm_flags1 = SLP_PCM_FLAGS1,
|
||||
|
||||
/* SPM_AP_STANDBY_CON */
|
||||
.wfi_op = 0x1,
|
||||
.mp0_cputop_idle_mask = 0,
|
||||
.mp1_cputop_idle_mask = 0,
|
||||
.mcusys_idle_mask = 0,
|
||||
.mm_mask_b = 0,
|
||||
.md_ddr_en_0_dbc_en = 0x1,
|
||||
.md_ddr_en_1_dbc_en = 0,
|
||||
.md_mask_b = 0x1,
|
||||
.sspm_mask_b = 0x1,
|
||||
.scp_mask_b = 0x1,
|
||||
.srcclkeni_mask_b = 0x1,
|
||||
.md_apsrc_1_sel = 0,
|
||||
.md_apsrc_0_sel = 0,
|
||||
.conn_ddr_en_dbc_en = 0x1,
|
||||
.conn_mask_b = 0x1,
|
||||
.conn_apsrc_sel = 0,
|
||||
|
||||
/* SPM_SRC_REQ */
|
||||
.spm_apsrc_req = 0,
|
||||
.spm_f26m_req = 0,
|
||||
.spm_infra_req = 0,
|
||||
.spm_vrf18_req = 0,
|
||||
.spm_ddren_req = 0,
|
||||
.spm_rsv_src_req = 0,
|
||||
.spm_ddren_2_req = 0,
|
||||
.cpu_md_dvfs_sop_force_on = 0,
|
||||
|
||||
/* SPM_SRC_MASK */
|
||||
.csyspwreq_mask = 0x1,
|
||||
.ccif0_md_event_mask_b = 0x1,
|
||||
.ccif0_ap_event_mask_b = 0x1,
|
||||
.ccif1_md_event_mask_b = 0x1,
|
||||
.ccif1_ap_event_mask_b = 0x1,
|
||||
.ccif2_md_event_mask_b = 0x1,
|
||||
.ccif2_ap_event_mask_b = 0x1,
|
||||
.ccif3_md_event_mask_b = 0x1,
|
||||
.ccif3_ap_event_mask_b = 0x1,
|
||||
.md_srcclkena_0_infra_mask_b = 0x1,
|
||||
.md_srcclkena_1_infra_mask_b = 0,
|
||||
.conn_srcclkena_infra_mask_b = 0,
|
||||
.ufs_infra_req_mask_b = 0,
|
||||
.srcclkeni_infra_mask_b = 0,
|
||||
.md_apsrc_req_0_infra_mask_b = 0x1,
|
||||
.md_apsrc_req_1_infra_mask_b = 0x1,
|
||||
.conn_apsrcreq_infra_mask_b = 0x1,
|
||||
.ufs_srcclkena_mask_b = 0,
|
||||
.md_vrf18_req_0_mask_b = 0,
|
||||
.md_vrf18_req_1_mask_b = 0,
|
||||
.ufs_vrf18_req_mask_b = 0,
|
||||
.gce_vrf18_req_mask_b = 0,
|
||||
.conn_infra_req_mask_b = 0x1,
|
||||
.gce_apsrc_req_mask_b = 0,
|
||||
.disp0_apsrc_req_mask_b = 0,
|
||||
.disp1_apsrc_req_mask_b = 0,
|
||||
.mfg_req_mask_b = 0,
|
||||
.vdec_req_mask_b = 0,
|
||||
|
||||
/* SPM_SRC2_MASK */
|
||||
.md_ddr_en_0_mask_b = 0x1,
|
||||
.md_ddr_en_1_mask_b = 0,
|
||||
.conn_ddr_en_mask_b = 0x1,
|
||||
.ddren_sspm_apsrc_req_mask_b = 0x1,
|
||||
.ddren_scp_apsrc_req_mask_b = 0x1,
|
||||
.disp0_ddren_mask_b = 0x1,
|
||||
.disp1_ddren_mask_b = 0x1,
|
||||
.gce_ddren_mask_b = 0x1,
|
||||
.ddren_emi_self_refresh_ch0_mask_b = 0,
|
||||
.ddren_emi_self_refresh_ch1_mask_b = 0,
|
||||
|
||||
/* SPM_WAKEUP_EVENT_MASK */
|
||||
.spm_wakeup_event_mask = 0xF1782218,
|
||||
|
||||
/* SPM_WAKEUP_EVENT_EXT_MASK */
|
||||
.spm_wakeup_event_ext_mask = 0xFFFFFFFF,
|
||||
|
||||
/* SPM_SRC3_MASK */
|
||||
.md_ddr_en_2_0_mask_b = 0x1,
|
||||
.md_ddr_en_2_1_mask_b = 0,
|
||||
.conn_ddr_en_2_mask_b = 0x1,
|
||||
.ddren2_sspm_apsrc_req_mask_b = 0x1,
|
||||
.ddren2_scp_apsrc_req_mask_b = 0x1,
|
||||
.disp0_ddren2_mask_b = 0,
|
||||
.disp1_ddren2_mask_b = 0,
|
||||
.gce_ddren2_mask_b = 0,
|
||||
.ddren2_emi_self_refresh_ch0_mask_b = 0,
|
||||
.ddren2_emi_self_refresh_ch1_mask_b = 0,
|
||||
|
||||
.mp0_cpu0_wfi_en = 0x1,
|
||||
.mp0_cpu1_wfi_en = 0x1,
|
||||
.mp0_cpu2_wfi_en = 0x1,
|
||||
.mp0_cpu3_wfi_en = 0x1,
|
||||
|
||||
.mp1_cpu0_wfi_en = 0x1,
|
||||
.mp1_cpu1_wfi_en = 0x1,
|
||||
.mp1_cpu2_wfi_en = 0x1,
|
||||
.mp1_cpu3_wfi_en = 0x1
|
||||
};
|
||||
|
||||
static uint32_t spm_set_sysclk_settle(void)
|
||||
{
|
||||
mmio_write_32(SPM_CLK_SETTLE, SPM_SYSCLK_SETTLE);
|
||||
return mmio_read_32(SPM_CLK_SETTLE);
|
||||
}
|
||||
|
||||
void go_to_sleep_before_wfi(void)
|
||||
{
|
||||
int cpu = MPIDR_AFFLVL0_VAL(read_mpidr());
|
||||
uint32_t settle;
|
||||
|
||||
settle = spm_set_sysclk_settle();
|
||||
spm_set_cpu_status(cpu);
|
||||
spm_set_power_control(&suspend_ctrl);
|
||||
spm_set_wakeup_event(&suspend_ctrl);
|
||||
spm_set_pcm_flags(&suspend_ctrl);
|
||||
spm_send_cpu_wakeup_event();
|
||||
spm_set_pcm_wdt(0);
|
||||
spm_disable_pcm_timer();
|
||||
|
||||
if (is_infra_pdn(suspend_ctrl.pcm_flags))
|
||||
mt_uart_save();
|
||||
|
||||
if (!mt_console_uart_cg_status())
|
||||
console_switch_state(CONSOLE_FLAG_BOOT);
|
||||
|
||||
INFO("cpu%d: \"%s\", wakesrc = 0x%x, pcm_con1 = 0x%x\n",
|
||||
cpu, spm_get_firmware_version(), suspend_ctrl.wake_src,
|
||||
mmio_read_32(PCM_CON1));
|
||||
INFO("settle = %u, sec = %u, sw_flag = 0x%x 0x%x, src_req = 0x%x\n",
|
||||
settle, mmio_read_32(PCM_TIMER_VAL) / 32768,
|
||||
suspend_ctrl.pcm_flags, suspend_ctrl.pcm_flags1,
|
||||
mmio_read_32(SPM_SRC_REQ));
|
||||
|
||||
if (!mt_console_uart_cg_status())
|
||||
console_switch_state(CONSOLE_FLAG_RUNTIME);
|
||||
}
|
||||
|
||||
static void go_to_sleep_after_wfi(void)
|
||||
{
|
||||
struct wake_status spm_wakesta;
|
||||
|
||||
if (is_infra_pdn(suspend_ctrl.pcm_flags))
|
||||
mt_uart_restore();
|
||||
|
||||
spm_set_pcm_wdt(0);
|
||||
spm_get_wakeup_status(&spm_wakesta);
|
||||
spm_clean_after_wakeup();
|
||||
|
||||
if (!mt_console_uart_cg_status())
|
||||
console_switch_state(CONSOLE_FLAG_BOOT);
|
||||
|
||||
spm_output_wake_reason(&spm_wakesta, "suspend");
|
||||
|
||||
if (!mt_console_uart_cg_status())
|
||||
console_switch_state(CONSOLE_FLAG_RUNTIME);
|
||||
}
|
||||
|
||||
static void spm_enable_armpll_l(void)
|
||||
{
|
||||
/* power on */
|
||||
mmio_setbits_32(ARMPLL_L_PWR_CON0, 0x1);
|
||||
|
||||
/* clear isolation */
|
||||
mmio_clrbits_32(ARMPLL_L_PWR_CON0, 0x2);
|
||||
|
||||
/* enable pll */
|
||||
mmio_setbits_32(ARMPLL_L_CON0, 0x1);
|
||||
|
||||
/* Add 20us delay for turning on PLL */
|
||||
udelay(20);
|
||||
}
|
||||
|
||||
static void spm_disable_armpll_l(void)
|
||||
{
|
||||
/* disable pll */
|
||||
mmio_clrbits_32(ARMPLL_L_CON0, 0x1);
|
||||
|
||||
/* isolation */
|
||||
mmio_setbits_32(ARMPLL_L_PWR_CON0, 0x2);
|
||||
|
||||
/* power off */
|
||||
mmio_clrbits_32(ARMPLL_L_PWR_CON0, 0x1);
|
||||
}
|
||||
|
||||
void spm_system_suspend(void)
|
||||
{
|
||||
spm_disable_armpll_l();
|
||||
bcpu_enable(0);
|
||||
bcpu_sram_enable(0);
|
||||
spm_lock_get();
|
||||
go_to_sleep_before_wfi();
|
||||
spm_lock_release();
|
||||
}
|
||||
|
||||
void spm_system_suspend_finish(void)
|
||||
{
|
||||
spm_lock_get();
|
||||
go_to_sleep_after_wfi();
|
||||
spm_lock_release();
|
||||
spm_enable_armpll_l();
|
||||
bcpu_sram_enable(1);
|
||||
bcpu_enable(1);
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef __SPM_SUSPEND_H__
|
||||
#define __SPM_SUSPEND_H__
|
||||
|
||||
void spm_system_suspend(void);
|
||||
void spm_system_suspend_finish(void);
|
||||
|
||||
#endif /* __SPM_SUSPEND_H__*/
|
|
@ -136,8 +136,7 @@ static const struct per_cpu_reg SPM_CLUSTER_PWR[] = {
|
|||
/*
|
||||
* MCU configuration registers
|
||||
*/
|
||||
#define MCUCFG_MP0_AXI_CONFIG ((uintptr_t)&mt8183_mcucfg->mp0_axi_config)
|
||||
#define MCUCFG_MP1_AXI_CONFIG ((uintptr_t)&mt8183_mcucfg->mp1_axi_config)
|
||||
|
||||
/* bit-fields of MCUCFG_MP?_AXI_CONFIG */
|
||||
#define MCUCFG_AXI_CONFIG_BROADCASTINNER (1 << 0)
|
||||
#define MCUCFG_AXI_CONFIG_BROADCASTOUTER (1 << 1)
|
||||
|
@ -146,11 +145,6 @@ static const struct per_cpu_reg SPM_CLUSTER_PWR[] = {
|
|||
#define MCUCFG_AXI_CONFIG_ACINACTM (1 << 4)
|
||||
#define MCUCFG_AXI_CONFIG_AINACTS (1 << 5)
|
||||
|
||||
/* per_cpu registers for MCUCFG_MP?_AXI_CONFIG */
|
||||
static const struct per_cpu_reg MCUCFG_SCUCTRL[] = {
|
||||
[0] = { .cluster_addr = MCUCFG_MP0_AXI_CONFIG },
|
||||
[1] = { .cluster_addr = MCUCFG_MP1_AXI_CONFIG },
|
||||
};
|
||||
|
||||
#define MCUCFG_MP0_MISC_CONFIG2 ((uintptr_t)&mt8183_mcucfg->mp0_misc_config[2])
|
||||
#define MCUCFG_MP0_MISC_CONFIG3 ((uintptr_t)&mt8183_mcucfg->mp0_misc_config[3])
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <errno.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <sspm.h>
|
||||
|
||||
static void memcpy_to_sspm(uint32_t dst, uint32_t *src, uint32_t len)
|
||||
{
|
||||
while (len--) {
|
||||
mmio_write_32(dst, *src);
|
||||
dst += sizeof(uint32_t);
|
||||
src++;
|
||||
}
|
||||
}
|
||||
|
||||
static void memcpy_from_sspm(uint32_t *dst, uint32_t src, uint32_t len)
|
||||
{
|
||||
while (len--) {
|
||||
*dst = mmio_read_32(src);
|
||||
dst++;
|
||||
src += sizeof(uint32_t);
|
||||
}
|
||||
}
|
||||
|
||||
int sspm_mbox_read(uint32_t slot, uint32_t *data, uint32_t len)
|
||||
{
|
||||
if (slot >= 32) {
|
||||
ERROR("%s:slot = %d\n", __func__, slot);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (data)
|
||||
memcpy_from_sspm(data,
|
||||
MBOX3_BASE + slot * 4,
|
||||
len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sspm_mbox_write(uint32_t slot, uint32_t *data, uint32_t len)
|
||||
{
|
||||
if (slot >= 32) {
|
||||
ERROR("%s:slot = %d\n", __func__, slot);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (data)
|
||||
memcpy_to_sspm(MBOX3_BASE + slot * 4,
|
||||
data,
|
||||
len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sspm_ipi_check_ack(uint32_t id)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (id == IPI_ID_PLATFORM) {
|
||||
if ((mmio_read_32(MBOX0_BASE + MBOX_IN_IRQ_OFS) & 0x1) == 0x1)
|
||||
ret = -EINPROGRESS;
|
||||
} else if (id == IPI_ID_SUSPEND) {
|
||||
if ((mmio_read_32(MBOX1_BASE + MBOX_IN_IRQ_OFS) & 0x2) == 0x2)
|
||||
ret = -EINPROGRESS;
|
||||
} else {
|
||||
ERROR("%s: id = %d\n", __func__, id);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sspm_ipi_send_non_blocking(uint32_t id, uint32_t *data)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = sspm_ipi_check_ack(id);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (id == IPI_ID_PLATFORM) {
|
||||
memcpy_to_sspm(MBOX0_BASE + PINR_OFFSET_PLATFORM * 4,
|
||||
data,
|
||||
PINR_SIZE_PLATFORM);
|
||||
dsb();
|
||||
mmio_write_32(MBOX0_BASE + MBOX_OUT_IRQ_OFS, 0x1);
|
||||
} else if (id == IPI_ID_SUSPEND) {
|
||||
memcpy_to_sspm(MBOX1_BASE + PINR_OFFSET_SUSPEND * 4,
|
||||
data,
|
||||
PINR_SIZE_SUSPEND);
|
||||
dsb();
|
||||
mmio_write_32(MBOX1_BASE + MBOX_OUT_IRQ_OFS,
|
||||
0x2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sspm_ipi_recv_non_blocking(uint32_t id, uint32_t *data, uint32_t len)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = sspm_ipi_check_ack(id);
|
||||
if (ret == -EINPROGRESS) {
|
||||
if (id == IPI_ID_PLATFORM) {
|
||||
memcpy_from_sspm(data,
|
||||
MBOX0_BASE + PINR_OFFSET_PLATFORM * 4,
|
||||
len);
|
||||
dsb();
|
||||
/* clear interrupt bit*/
|
||||
mmio_write_32(MBOX0_BASE + MBOX_IN_IRQ_OFS,
|
||||
0x1);
|
||||
ret = 0;
|
||||
} else if (id == IPI_ID_SUSPEND) {
|
||||
memcpy_from_sspm(data,
|
||||
MBOX1_BASE + PINR_OFFSET_SUSPEND * 4,
|
||||
len);
|
||||
dsb();
|
||||
/* clear interrupt bit*/
|
||||
mmio_write_32(MBOX1_BASE + MBOX_IN_IRQ_OFS,
|
||||
0x2);
|
||||
ret = 0;
|
||||
}
|
||||
} else if (ret == 0) {
|
||||
ret = -EBUSY;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sspm_alive_show(void)
|
||||
{
|
||||
uint32_t ipi_data, count;
|
||||
int ret = 0;
|
||||
|
||||
count = 5;
|
||||
ipi_data = 0xdead;
|
||||
|
||||
if (sspm_ipi_send_non_blocking(IPI_ID_PLATFORM, &ipi_data) != 0) {
|
||||
ERROR("sspm init send fail! ret=%d\n", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (sspm_ipi_recv_non_blocking(IPI_ID_PLATFORM,
|
||||
&ipi_data,
|
||||
sizeof(ipi_data))
|
||||
&& count) {
|
||||
mdelay(100);
|
||||
count--;
|
||||
}
|
||||
|
||||
return (ipi_data == 1) ? 0 : -1;
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef __SSPM_H__
|
||||
#define __SSPM_H__
|
||||
/* These should sync with sspm.bin */
|
||||
#define IPI_ID_PLATFORM 0
|
||||
#define IPI_ID_SUSPEND 6
|
||||
#define PINR_OFFSET_PLATFORM 0
|
||||
#define PINR_SIZE_PLATFORM 3
|
||||
#define PINR_OFFSET_SUSPEND 2
|
||||
#define PINR_SIZE_SUSPEND 8
|
||||
|
||||
#define MBOX0_BASE 0x10450000
|
||||
#define MBOX1_BASE 0x10460000
|
||||
#define MBOX3_BASE 0x10480000
|
||||
#define MBOX_OUT_IRQ_OFS 0x1000
|
||||
#define MBOX_IN_IRQ_OFS 0x1004
|
||||
|
||||
#define SHAREMBOX_OFFSET_MCDI 0
|
||||
#define SHAREMBOX_SIZE_MCDI 20
|
||||
#define SHAREMBOX_OFFSET_SUSPEND 26
|
||||
#define SHAREMBOX_SIZE_SUSPEND 6
|
||||
|
||||
int sspm_mbox_read(uint32_t slot, uint32_t *data, uint32_t len);
|
||||
int sspm_mbox_write(uint32_t slot, uint32_t *data, uint32_t len);
|
||||
int sspm_ipi_send_non_blocking(uint32_t id, uint32_t *data);
|
||||
int sspm_ipi_recv_non_blocking(uint32_t slot, uint32_t *data, uint32_t len);
|
||||
int sspm_alive_show(void);
|
||||
#endif /* __SSPM_H__ */
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <lib/mmio.h>
|
||||
#include <uart.h>
|
||||
|
||||
static struct mt_uart uart_save_addr[DRV_SUPPORT_UART_PORTS];
|
||||
|
||||
static const unsigned int uart_base_addr[DRV_SUPPORT_UART_PORTS] = {
|
||||
UART0_BASE,
|
||||
UART1_BASE
|
||||
};
|
||||
|
||||
void mt_uart_restore(void)
|
||||
{
|
||||
int uart_idx = UART_PORT0;
|
||||
struct mt_uart *uart;
|
||||
unsigned long base;
|
||||
|
||||
/* Must NOT print any debug log before UART restore */
|
||||
for (uart_idx = UART_PORT0; uart_idx < HW_SUPPORT_UART_PORTS;
|
||||
uart_idx++) {
|
||||
|
||||
uart = &uart_save_addr[uart_idx];
|
||||
base = uart->base;
|
||||
|
||||
mmio_write_32(UART_LCR(base), UART_LCR_MODE_B);
|
||||
mmio_write_32(UART_EFR(base), uart->registers.efr);
|
||||
mmio_write_32(UART_LCR(base), uart->registers.lcr);
|
||||
mmio_write_32(UART_FCR(base), uart->registers.fcr);
|
||||
|
||||
/* baudrate */
|
||||
mmio_write_32(UART_HIGHSPEED(base), uart->registers.highspeed);
|
||||
mmio_write_32(UART_FRACDIV_L(base), uart->registers.fracdiv_l);
|
||||
mmio_write_32(UART_FRACDIV_M(base), uart->registers.fracdiv_m);
|
||||
mmio_write_32(UART_LCR(base),
|
||||
uart->registers.lcr | UART_LCR_DLAB);
|
||||
mmio_write_32(UART_DLL(base), uart->registers.dll);
|
||||
mmio_write_32(UART_DLH(base), uart->registers.dlh);
|
||||
mmio_write_32(UART_LCR(base), uart->registers.lcr);
|
||||
mmio_write_32(UART_SAMPLE_COUNT(base),
|
||||
uart->registers.sample_count);
|
||||
mmio_write_32(UART_SAMPLE_POINT(base),
|
||||
uart->registers.sample_point);
|
||||
mmio_write_32(UART_GUARD(base), uart->registers.guard);
|
||||
|
||||
/* flow control */
|
||||
mmio_write_32(UART_ESCAPE_EN(base), uart->registers.escape_en);
|
||||
mmio_write_32(UART_MCR(base), uart->registers.mcr);
|
||||
mmio_write_32(UART_IER(base), uart->registers.ier);
|
||||
mmio_write_32(UART_SCR(base), uart->registers.scr);
|
||||
}
|
||||
}
|
||||
|
||||
void mt_uart_save(void)
|
||||
{
|
||||
int uart_idx = UART_PORT0;
|
||||
struct mt_uart *uart;
|
||||
unsigned long base;
|
||||
|
||||
for (uart_idx = UART_PORT0; uart_idx < HW_SUPPORT_UART_PORTS;
|
||||
uart_idx++) {
|
||||
|
||||
uart_save_addr[uart_idx].base = uart_base_addr[uart_idx];
|
||||
base = uart_base_addr[uart_idx];
|
||||
uart = &uart_save_addr[uart_idx];
|
||||
uart->registers.lcr = mmio_read_32(UART_LCR(base));
|
||||
|
||||
mmio_write_32(UART_LCR(base), UART_LCR_MODE_B);
|
||||
uart->registers.efr = mmio_read_32(UART_EFR(base));
|
||||
mmio_write_32(UART_LCR(base), uart->registers.lcr);
|
||||
uart->registers.fcr = mmio_read_32(UART_FCR_RD(base));
|
||||
|
||||
/* baudrate */
|
||||
uart->registers.highspeed = mmio_read_32(UART_HIGHSPEED(base));
|
||||
uart->registers.fracdiv_l = mmio_read_32(UART_FRACDIV_L(base));
|
||||
uart->registers.fracdiv_m = mmio_read_32(UART_FRACDIV_M(base));
|
||||
mmio_write_32(UART_LCR(base),
|
||||
uart->registers.lcr | UART_LCR_DLAB);
|
||||
uart->registers.dll = mmio_read_32(UART_DLL(base));
|
||||
uart->registers.dlh = mmio_read_32(UART_DLH(base));
|
||||
mmio_write_32(UART_LCR(base), uart->registers.lcr);
|
||||
uart->registers.sample_count = mmio_read_32(
|
||||
UART_SAMPLE_COUNT(base));
|
||||
uart->registers.sample_point = mmio_read_32(
|
||||
UART_SAMPLE_POINT(base));
|
||||
uart->registers.guard = mmio_read_32(UART_GUARD(base));
|
||||
|
||||
/* flow control */
|
||||
uart->registers.escape_en = mmio_read_32(UART_ESCAPE_EN(base));
|
||||
uart->registers.mcr = mmio_read_32(UART_MCR(base));
|
||||
uart->registers.ier = mmio_read_32(UART_IER(base));
|
||||
uart->registers.scr = mmio_read_32(UART_SCR(base));
|
||||
}
|
||||
}
|
||||
|
||||
void mt_console_uart_cg(int on)
|
||||
{
|
||||
if (on)
|
||||
mmio_write_32(UART_CLOCK_GATE_CLR, UART0_CLOCK_GATE_BIT);
|
||||
else
|
||||
mmio_write_32(UART_CLOCK_GATE_SET, UART0_CLOCK_GATE_BIT);
|
||||
}
|
||||
|
||||
int mt_console_uart_cg_status(void)
|
||||
{
|
||||
return mmio_read_32(UART_CLOCK_GATE_STA) & UART0_CLOCK_GATE_BIT;
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef __UART_H__
|
||||
#define __UART_H__
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
/* UART HW information */
|
||||
#define HW_SUPPORT_UART_PORTS 2
|
||||
#define DRV_SUPPORT_UART_PORTS 2
|
||||
|
||||
/* console UART clock cg */
|
||||
#define UART_CLOCK_GATE_SET (INFRACFG_AO_BASE + 0x80)
|
||||
#define UART_CLOCK_GATE_CLR (INFRACFG_AO_BASE + 0x84)
|
||||
#define UART_CLOCK_GATE_STA (INFRACFG_AO_BASE + 0x90)
|
||||
#define UART0_CLOCK_GATE_BIT (1U<<22)
|
||||
#define UART1_CLOCK_GATE_BIT (1U<<23)
|
||||
|
||||
/* UART registers */
|
||||
#define UART_RBR(_baseaddr) (_baseaddr + 0x0)
|
||||
#define UART_THR(_baseaddr) (_baseaddr + 0x0)
|
||||
#define UART_IER(_baseaddr) (_baseaddr + 0x4)
|
||||
#define UART_IIR(_baseaddr) (_baseaddr + 0x8)
|
||||
#define UART_FCR(_baseaddr) (_baseaddr + 0x8)
|
||||
#define UART_LCR(_baseaddr) (_baseaddr + 0xc)
|
||||
#define UART_MCR(_baseaddr) (_baseaddr + 0x10)
|
||||
#define UART_LSR(_baseaddr) (_baseaddr + 0x14)
|
||||
#define UART_MSR(_baseaddr) (_baseaddr + 0x18)
|
||||
#define UART_SCR(_baseaddr) (_baseaddr + 0x1c)
|
||||
#define UART_DLL(_baseaddr) (_baseaddr + 0x0)
|
||||
#define UART_DLH(_baseaddr) (_baseaddr + 0x4)
|
||||
#define UART_EFR(_baseaddr) (_baseaddr + 0x8)
|
||||
#define UART_XON1(_baseaddr) (_baseaddr + 0x10)
|
||||
#define UART_XON2(_baseaddr) (_baseaddr + 0x14)
|
||||
#define UART_XOFF1(_baseaddr) (_baseaddr + 0x18)
|
||||
#define UART_XOFF2(_baseaddr) (_baseaddr + 0x1c)
|
||||
#define UART_AUTOBAUD(_baseaddr) (_baseaddr + 0x20)
|
||||
#define UART_HIGHSPEED(_baseaddr) (_baseaddr + 0x24)
|
||||
#define UART_SAMPLE_COUNT(_baseaddr) (_baseaddr + 0x28)
|
||||
#define UART_SAMPLE_POINT(_baseaddr) (_baseaddr + 0x2c)
|
||||
#define UART_AUTOBAUD_REG(_baseaddr) (_baseaddr + 0x30)
|
||||
#define UART_RATE_FIX_REG(_baseaddr) (_baseaddr + 0x34)
|
||||
#define UART_AUTO_BAUDSAMPLE(_baseaddr) (_baseaddr + 0x38)
|
||||
#define UART_GUARD(_baseaddr) (_baseaddr + 0x3c)
|
||||
#define UART_ESCAPE_DAT(_baseaddr) (_baseaddr + 0x40)
|
||||
#define UART_ESCAPE_EN(_baseaddr) (_baseaddr + 0x44)
|
||||
#define UART_SLEEP_EN(_baseaddr) (_baseaddr + 0x48)
|
||||
#define UART_DMA_EN(_baseaddr) (_baseaddr + 0x4c)
|
||||
#define UART_RXTRI_AD(_baseaddr) (_baseaddr + 0x50)
|
||||
#define UART_FRACDIV_L(_baseaddr) (_baseaddr + 0x54)
|
||||
#define UART_FRACDIV_M(_baseaddr) (_baseaddr + 0x58)
|
||||
#define UART_FCR_RD(_baseaddr) (_baseaddr + 0x5C)
|
||||
#define UART_USB_RX_SEL(_baseaddr) (_baseaddr + 0xB0)
|
||||
#define UART_SLEEP_REQ(_baseaddr) (_baseaddr + 0xB4)
|
||||
#define UART_SLEEP_ACK(_baseaddr) (_baseaddr + 0xB8)
|
||||
#define UART_SPM_SEL(_baseaddr) (_baseaddr + 0xBC)
|
||||
#define UART_LCR_DLAB 0x0080
|
||||
#define UART_LCR_MODE_B 0x00bf
|
||||
|
||||
enum uart_port_ID {
|
||||
UART_PORT0 = 0,
|
||||
UART_PORT1
|
||||
};
|
||||
|
||||
struct mt_uart_register {
|
||||
unsigned int dll;
|
||||
unsigned int dlh;
|
||||
unsigned int ier;
|
||||
unsigned int lcr;
|
||||
unsigned int mcr;
|
||||
unsigned int fcr;
|
||||
unsigned int lsr;
|
||||
unsigned int scr;
|
||||
unsigned int efr;
|
||||
unsigned int highspeed;
|
||||
unsigned int sample_count;
|
||||
unsigned int sample_point;
|
||||
unsigned int fracdiv_l;
|
||||
unsigned int fracdiv_m;
|
||||
unsigned int escape_en;
|
||||
unsigned int guard;
|
||||
unsigned int rx_sel;
|
||||
};
|
||||
|
||||
struct mt_uart {
|
||||
unsigned long base;
|
||||
struct mt_uart_register registers;
|
||||
};
|
||||
|
||||
/* external API */
|
||||
void mt_uart_save(void);
|
||||
void mt_uart_restore(void);
|
||||
void mt_console_uart_cg(int on);
|
||||
int mt_console_uart_cg_status(void);
|
||||
|
||||
#endif /* __UART_H__ */
|
|
@ -28,51 +28,141 @@ struct mt8183_mcucfg_regs {
|
|||
uint32_t mp0_rw_rsvd0; /* 0x6C */
|
||||
uint32_t mp0_rw_rsvd1; /* 0x70 */
|
||||
uint32_t mp0_ro_rsvd; /* 0x74 */
|
||||
uint32_t reserved0_0[98]; /* 0x78 */
|
||||
uint32_t mp1_ca7l_cache_config; /* 0x200 */
|
||||
uint32_t mp1_miscdbg; /* 0x204 */
|
||||
uint32_t reserved0_1[9]; /* 0x208 */
|
||||
uint32_t mp1_axi_config; /* 0x22C */
|
||||
uint32_t mp1_misc_config[10]; /* 0x230 */
|
||||
uint32_t reserved0_2[3]; /* 0x258 */
|
||||
uint32_t mp1_ca7l_misc_config; /* 0x264 */
|
||||
uint32_t reserved0_3[310]; /* 0x268 */
|
||||
uint32_t reserved0_0; /* 0x78 */
|
||||
uint32_t mp0_l2_cache_parity1_rdata; /* 0x7C */
|
||||
uint32_t mp0_l2_cache_parity2_rdata; /* 0x80 */
|
||||
uint32_t reserved0_1; /* 0x84 */
|
||||
uint32_t mp0_rgu_dcm_config; /* 0x88 */
|
||||
uint32_t mp0_ca53_specific_ctrl; /* 0x8C */
|
||||
uint32_t mp0_esr_case; /* 0x90 */
|
||||
uint32_t mp0_esr_mask; /* 0x94 */
|
||||
uint32_t mp0_esr_trig_en; /* 0x98 */
|
||||
uint32_t reserved_0_2; /* 0x9C */
|
||||
uint32_t mp0_ses_cg_en; /* 0xA0 */
|
||||
uint32_t reserved0_3[216]; /* 0xA4 */
|
||||
uint32_t mp_dbg_ctrl; /* 0x404 */
|
||||
uint32_t reserved0_4[34]; /* 0x408 */
|
||||
uint32_t mp_dfd_ctrl; /* 0x490 */
|
||||
uint32_t dfd_cnt_l; /* 0x494 */
|
||||
uint32_t dfd_cnt_h; /* 0x498 */
|
||||
uint32_t misccfg_ro_rsvd; /* 0x49C */
|
||||
uint32_t reserved0_5[24]; /* 0x4A0 */
|
||||
uint32_t mp1_rst_status; /* 0x500 */
|
||||
uint32_t mp1_dbg_ctrl; /* 0x504 */
|
||||
uint32_t mp1_dbg_flag; /* 0x508 */
|
||||
uint32_t mp1_ca7l_ir_mon; /* 0x50C */
|
||||
uint32_t reserved0_6[32]; /* 0x510 */
|
||||
uint32_t mcusys_dbg_mon_sel_a; /* 0x590 */
|
||||
uint32_t mcucys_dbg_mon; /* 0x594 */
|
||||
uint32_t misccfg_sec_voi_status0; /* 0x598 */
|
||||
uint32_t misccfg_sec_vio_status1; /* 0x59C */
|
||||
uint32_t reserved0_7[18]; /* 0x5A0 */
|
||||
uint32_t gic500_int_mask; /* 0x5E8 */
|
||||
uint32_t core_rst_en_latch; /* 0x5EC */
|
||||
uint32_t reserved0_8[3]; /* 0x5F0 */
|
||||
uint32_t dbg_core_ret; /* 0x5FC */
|
||||
uint32_t mcusys_config_a; /* 0x600 */
|
||||
uint32_t mcusys_config1_a; /* 0x604 */
|
||||
uint32_t mcusys_gic_prebase_a; /* 0x608 */
|
||||
uint32_t mcusys_pinmux; /* 0x60C */
|
||||
uint32_t sec_range0_start; /* 0x610 */
|
||||
uint32_t sec_range0_end; /* 0x614 */
|
||||
uint32_t sec_range_enable; /* 0x618 */
|
||||
uint32_t l2c_mm_base; /* 0x61C */
|
||||
uint32_t reserved0_9[8]; /* 0x620 */
|
||||
uint32_t aclken_div; /* 0x640 */
|
||||
uint32_t pclken_div; /* 0x644 */
|
||||
uint32_t l2c_sram_ctrl; /* 0x648 */
|
||||
uint32_t armpll_jit_ctrl; /* 0x64C */
|
||||
uint32_t cci_addrmap; /* 0x650 */
|
||||
uint32_t cci_config; /* 0x654 */
|
||||
uint32_t cci_periphbase; /* 0x658 */
|
||||
uint32_t cci_nevntcntovfl; /* 0x65C */
|
||||
uint32_t cci_clk_ctrl; /* 0x660 */
|
||||
uint32_t cci_acel_s1_ctrl; /* 0x664 */
|
||||
uint32_t mcusys_bus_fabric_dcm_ctrl; /* 0x668 */
|
||||
uint32_t mcu_misc_dcm_ctrl; /* 0x66C */
|
||||
uint32_t xgpt_ctl; /* 0x670 */
|
||||
uint32_t xgpt_idx; /* 0x674 */
|
||||
uint32_t reserved0_10[3]; /* 0x678 */
|
||||
uint32_t mcusys_rw_rsvd0; /* 0x684 */
|
||||
uint32_t mcusys_rw_rsvd1; /* 0x688 */
|
||||
uint32_t reserved0_11[13]; /* 0x68C */
|
||||
uint32_t gic_500_delsel_ctl; /* 0x6C0 */
|
||||
uint32_t etb_delsel_ctl; /* 0x6C4 */
|
||||
uint32_t etb_rst_ctl; /* 0x6C8 */
|
||||
uint32_t reserved0_12[29]; /* 0x6CC */
|
||||
uint32_t cci_adb400_dcm_config; /* 0x740 */
|
||||
uint32_t sync_dcm_config; /* 0x744 */
|
||||
uint32_t reserved0_4[16]; /* 0x748 */
|
||||
uint32_t mp0_cputop_spmc_ctl; /* 0x788 */
|
||||
uint32_t mp1_cputop_spmc_ctl; /* 0x78C */
|
||||
uint32_t mp1_cputop_spmc_sram_ctl; /* 0x790 */
|
||||
uint32_t reserved0_5[23]; /* 0x794 */
|
||||
uint32_t reserved0_13; /* 0x748 */
|
||||
uint32_t sync_dcm_cluster_config; /* 0x74C */
|
||||
uint32_t sw_udi; /* 0x750 */
|
||||
uint32_t reserved0_14; /* 0x754 */
|
||||
uint32_t gic_sync_dcm; /* 0x758 */
|
||||
uint32_t big_dbg_pwr_ctrl; /* 0x75C */
|
||||
uint32_t gic_cpu_periphbase; /* 0x760 */
|
||||
uint32_t axi_cpu_config; /* 0x764 */
|
||||
uint32_t reserved0_15[2]; /* 0x768 */
|
||||
uint32_t mcsib_sys_ctrl1; /* 0x770 */
|
||||
uint32_t mcsib_sys_ctrl2; /* 0x774 */
|
||||
uint32_t mcsib_sys_ctrl3; /* 0x778 */
|
||||
uint32_t mcsib_sys_ctrl4; /* 0x77C */
|
||||
uint32_t mcsib_dbg_ctrl1; /* 0x780 */
|
||||
uint32_t pwrmcu_apb2to1; /* 0x784 */
|
||||
uint32_t mp0_spmc; /* 0x788 */
|
||||
uint32_t reserved0_16; /* 0x78C */
|
||||
uint32_t mp0_spmc_sram_ctl; /* 0x790 */
|
||||
uint32_t reserved0_17; /* 0x794 */
|
||||
uint32_t mp0_sw_rst_wait_cycle; /* 0x798 */
|
||||
uint32_t reserved0_18; /* 0x79C */
|
||||
uint32_t mp0_pll_divider_cfg; /* 0x7A0 */
|
||||
uint32_t reserved0_19; /* 0x7A4 */
|
||||
uint32_t mp2_pll_divider_cfg; /* 0x7A8 */
|
||||
uint32_t reserved0_20[5]; /* 0x7AC */
|
||||
uint32_t bus_pll_divider_cfg; /* 0x7C0 */
|
||||
uint32_t reserved0_21[7]; /* 0x7C4 */
|
||||
uint32_t clusterid_aff1; /* 0x7E0 */
|
||||
uint32_t clusterid_aff2; /* 0x7E4 */
|
||||
uint32_t reserved0_22[2]; /* 0x7E8 */
|
||||
uint32_t l2_cfg_mp0; /* 0x7F0 */
|
||||
uint32_t l2_cfg_mp1; /* 0x7F4 */
|
||||
uint32_t reserved0_6[1282]; /* 0x7F8 */
|
||||
uint32_t reserved0_23[218]; /* 0x7F8 */
|
||||
uint32_t mscib_dcm_en; /* 0xB60 */
|
||||
uint32_t reserved0_24[1063]; /* 0xB64 */
|
||||
uint32_t cpusys0_sparkvretcntrl; /* 0x1C00 */
|
||||
uint32_t cpusys0_sparken; /* 0x1C04 */
|
||||
uint32_t cpusys0_amuxsel; /* 0x1C08 */
|
||||
uint32_t reserved0_7[9]; /* 0x1C0C */
|
||||
uint32_t reserved0_25[9]; /* 0x1C0C */
|
||||
uint32_t cpusys0_cpu0_spmc_ctl; /* 0x1C30 */
|
||||
uint32_t cpusys0_cpu1_spmc_ctl; /* 0x1C34 */
|
||||
uint32_t cpusys0_cpu2_spmc_ctl; /* 0x1C38 */
|
||||
uint32_t cpusys0_cpu3_spmc_ctl; /* 0x1C3C */
|
||||
uint32_t reserved0_8[370]; /* 0x1C40 */
|
||||
uint32_t reserved0_26[8]; /* 0x1C40 */
|
||||
uint32_t mp0_sync_dcm_cgavg_ctrl; /* 0x1C60 */
|
||||
uint32_t mp0_sync_dcm_cgavg_fact; /* 0x1C64 */
|
||||
uint32_t mp0_sync_dcm_cgavg_rfact; /* 0x1C68 */
|
||||
uint32_t mp0_sync_dcm_cgavg; /* 0x1C6C */
|
||||
uint32_t mp0_l2_parity_clr; /* 0x1C70 */
|
||||
uint32_t reserved0_27[357]; /* 0x1C74 */
|
||||
uint32_t mp2_cpucfg; /* 0x2208 */
|
||||
uint32_t mp2_axi_config; /* 0x220C */
|
||||
uint32_t reserved0_9[36]; /* 0x2210 */
|
||||
uint32_t mp2_cputop_spm_ctl; /* 0x22A0 */
|
||||
uint32_t mp2_cputop_spm_sta; /* 0x22A4 */
|
||||
uint32_t reserved0_10[98]; /* 0x22A8 */
|
||||
uint32_t cpusys2_cpu0_spmc_ctl; /* 0x2430 */
|
||||
uint32_t cpusys2_cpu0_spmc_sta; /* 0x2434 */
|
||||
uint32_t cpusys2_cpu1_spmc_ctl; /* 0x2438 */
|
||||
uint32_t cpusys2_cpu1_spmc_sta; /* 0x243C */
|
||||
uint32_t reserved0_11[176]; /* 0x2440 */
|
||||
uint32_t reserved0_28[25]; /* 0x2210 */
|
||||
uint32_t mp2_sync_dcm; /* 0x2274 */
|
||||
uint32_t reserved0_29[10]; /* 0x2278 */
|
||||
uint32_t ptp3_cputop_spmc0; /* 0x22A0 */
|
||||
uint32_t ptp3_cputop_spmc1; /* 0x22A4 */
|
||||
uint32_t reserved0_30[98]; /* 0x22A8 */
|
||||
uint32_t ptp3_cpu0_spmc0; /* 0x2430 */
|
||||
uint32_t ptp3_cpu0_spmc1; /* 0x2434 */
|
||||
uint32_t ptp3_cpu1_spmc0; /* 0x2438 */
|
||||
uint32_t ptp3_cpu1_spmc1; /* 0x243C */
|
||||
uint32_t ptp3_cpu2_spmc0; /* 0x2440 */
|
||||
uint32_t ptp3_cpu2_spmc1; /* 0x2444 */
|
||||
uint32_t ptp3_cpu3_spmc0; /* 0x2448 */
|
||||
uint32_t ptp3_cpu3_spmc1; /* 0x244C */
|
||||
uint32_t ptp3_cpux_spmc; /* 0x2450 */
|
||||
uint32_t reserved0_31[171]; /* 0x2454 */
|
||||
uint32_t spark2ld0; /* 0x2700 */
|
||||
uint32_t reserved0_12[1355]; /* 0x2704 */
|
||||
uint32_t cpusys1_cpu0_spmc_ctl; /* 0x3C30 */
|
||||
uint32_t cpusys1_cpu1_spmc_ctl; /* 0x3C34 */
|
||||
uint32_t cpusys1_cpu2_spmc_ctl; /* 0x3C38 */
|
||||
uint32_t cpusys1_cpu3_spmc_ctl; /* 0x3C3C */
|
||||
};
|
||||
|
||||
static struct mt8183_mcucfg_regs *const mt8183_mcucfg = (void *)MCUCFG_BASE;
|
||||
|
@ -244,4 +334,235 @@ enum {
|
|||
MP1_L2RSTDISABLE = 1 << MP1_L2RSTDISABLE_SHIFT
|
||||
};
|
||||
|
||||
/* bus pll divider dcm related */
|
||||
enum {
|
||||
BUS_PLLDIVIDER_DCM_DBC_CNT_0_SHIFT = 11,
|
||||
BUS_PLLDIV_ARMWFI_DCM_EN_SHIFT = 24,
|
||||
BUS_PLLDIV_ARMWFE_DCM_EN_SHIFT = 25,
|
||||
|
||||
BUS_PLLDIV_DCM = (1 << BUS_PLLDIVIDER_DCM_DBC_CNT_0_SHIFT) |
|
||||
(1 << BUS_PLLDIV_ARMWFI_DCM_EN_SHIFT) |
|
||||
(1 << BUS_PLLDIV_ARMWFE_DCM_EN_SHIFT)
|
||||
};
|
||||
|
||||
/* mp0 pll divider dcm related */
|
||||
enum {
|
||||
MP0_PLLDIV_DCM_DBC_CNT_0_SHIFT = 11,
|
||||
MP0_PLLDIV_ARMWFI_DCM_EN_SHIFT = 24,
|
||||
MP0_PLLDIV_ARMWFE_DCM_EN_SHIFT = 25,
|
||||
MP0_PLLDIV_LASTCORE_IDLE_EN_SHIFT = 31,
|
||||
MP0_PLLDIV_DCM = (1 << MP0_PLLDIV_DCM_DBC_CNT_0_SHIFT) |
|
||||
(1 << MP0_PLLDIV_ARMWFI_DCM_EN_SHIFT) |
|
||||
(1 << MP0_PLLDIV_ARMWFE_DCM_EN_SHIFT) |
|
||||
(1u << MP0_PLLDIV_LASTCORE_IDLE_EN_SHIFT)
|
||||
};
|
||||
|
||||
/* mp2 pll divider dcm related */
|
||||
enum {
|
||||
MP2_PLLDIV_DCM_DBC_CNT_0_SHIFT = 11,
|
||||
MP2_PLLDIV_ARMWFI_DCM_EN_SHIFT = 24,
|
||||
MP2_PLLDIV_ARMWFE_DCM_EN_SHIFT = 25,
|
||||
MP2_PLLDIV_LASTCORE_IDLE_EN_SHIFT = 31,
|
||||
MP2_PLLDIV_DCM = (1 << MP2_PLLDIV_DCM_DBC_CNT_0_SHIFT) |
|
||||
(1 << MP2_PLLDIV_ARMWFI_DCM_EN_SHIFT) |
|
||||
(1 << MP2_PLLDIV_ARMWFE_DCM_EN_SHIFT) |
|
||||
(1u << MP2_PLLDIV_LASTCORE_IDLE_EN_SHIFT)
|
||||
};
|
||||
|
||||
/* mcsib dcm related */
|
||||
enum {
|
||||
MCSIB_CACTIVE_SEL_SHIFT = 0,
|
||||
MCSIB_DCM_EN_SHIFT = 16,
|
||||
|
||||
MCSIB_CACTIVE_SEL_MASK = 0xffff << MCSIB_CACTIVE_SEL_SHIFT,
|
||||
MCSIB_CACTIVE_SEL = 0xffff << MCSIB_CACTIVE_SEL_SHIFT,
|
||||
|
||||
MCSIB_DCM_MASK = 0xffffu << MCSIB_DCM_EN_SHIFT,
|
||||
MCSIB_DCM = 0xffffu << MCSIB_DCM_EN_SHIFT,
|
||||
};
|
||||
|
||||
/* cci adb400 dcm related */
|
||||
enum {
|
||||
CCI_M0_ADB400_DCM_EN_SHIFT = 0,
|
||||
CCI_M1_ADB400_DCM_EN_SHIFT = 1,
|
||||
CCI_M2_ADB400_DCM_EN_SHIFT = 2,
|
||||
CCI_S2_ADB400_DCM_EN_SHIFT = 3,
|
||||
CCI_S3_ADB400_DCM_EN_SHIFT = 4,
|
||||
CCI_S4_ADB400_DCM_EN_SHIFT = 5,
|
||||
CCI_S5_ADB400_DCM_EN_SHIFT = 6,
|
||||
ACP_S3_ADB400_DCM_EN_SHIFT = 11,
|
||||
|
||||
CCI_ADB400_DCM_MASK = (1 << CCI_M0_ADB400_DCM_EN_SHIFT) |
|
||||
(1 << CCI_M1_ADB400_DCM_EN_SHIFT) |
|
||||
(1 << CCI_M2_ADB400_DCM_EN_SHIFT) |
|
||||
(1 << CCI_S2_ADB400_DCM_EN_SHIFT) |
|
||||
(1 << CCI_S4_ADB400_DCM_EN_SHIFT) |
|
||||
(1 << CCI_S4_ADB400_DCM_EN_SHIFT) |
|
||||
(1 << CCI_S5_ADB400_DCM_EN_SHIFT) |
|
||||
(1 << ACP_S3_ADB400_DCM_EN_SHIFT),
|
||||
CCI_ADB400_DCM = (1 << CCI_M0_ADB400_DCM_EN_SHIFT) |
|
||||
(1 << CCI_M1_ADB400_DCM_EN_SHIFT) |
|
||||
(1 << CCI_M2_ADB400_DCM_EN_SHIFT) |
|
||||
(0 << CCI_S2_ADB400_DCM_EN_SHIFT) |
|
||||
(0 << CCI_S4_ADB400_DCM_EN_SHIFT) |
|
||||
(0 << CCI_S4_ADB400_DCM_EN_SHIFT) |
|
||||
(0 << CCI_S5_ADB400_DCM_EN_SHIFT) |
|
||||
(1 << ACP_S3_ADB400_DCM_EN_SHIFT)
|
||||
};
|
||||
|
||||
/* sync dcm related */
|
||||
enum {
|
||||
CCI_SYNC_DCM_DIV_EN_SHIFT = 0,
|
||||
CCI_SYNC_DCM_UPDATE_TOG_SHIFT = 1,
|
||||
CCI_SYNC_DCM_DIV_SEL_SHIFT = 2,
|
||||
MP0_SYNC_DCM_DIV_EN_SHIFT = 10,
|
||||
MP0_SYNC_DCM_UPDATE_TOG_SHIFT = 11,
|
||||
MP0_SYNC_DCM_DIV_SEL_SHIFT = 12,
|
||||
|
||||
SYNC_DCM_MASK = (1 << CCI_SYNC_DCM_DIV_EN_SHIFT) |
|
||||
(1 << CCI_SYNC_DCM_UPDATE_TOG_SHIFT) |
|
||||
(0x7f << CCI_SYNC_DCM_DIV_SEL_SHIFT) |
|
||||
(1 << MP0_SYNC_DCM_DIV_EN_SHIFT) |
|
||||
(1 << MP0_SYNC_DCM_UPDATE_TOG_SHIFT) |
|
||||
(0x7f << MP0_SYNC_DCM_DIV_SEL_SHIFT),
|
||||
SYNC_DCM = (1 << CCI_SYNC_DCM_DIV_EN_SHIFT) |
|
||||
(1 << CCI_SYNC_DCM_UPDATE_TOG_SHIFT) |
|
||||
(0 << CCI_SYNC_DCM_DIV_SEL_SHIFT) |
|
||||
(1 << MP0_SYNC_DCM_DIV_EN_SHIFT) |
|
||||
(1 << MP0_SYNC_DCM_UPDATE_TOG_SHIFT) |
|
||||
(0 << MP0_SYNC_DCM_DIV_SEL_SHIFT)
|
||||
};
|
||||
|
||||
/* mcu bus dcm related */
|
||||
enum {
|
||||
MCU_BUS_DCM_EN_SHIFT = 8,
|
||||
MCU_BUS_DCM = 1 << MCU_BUS_DCM_EN_SHIFT
|
||||
};
|
||||
|
||||
/* mcusys bus fabric dcm related */
|
||||
enum {
|
||||
ACLK_INFRA_DYNAMIC_CG_EN_SHIFT = 0,
|
||||
EMI2_ADB400_S_DCM_CTRL_SHIFT = 1,
|
||||
ACLK_GPU_DYNAMIC_CG_EN_SHIFT = 2,
|
||||
ACLK_PSYS_DYNAMIC_CG_EN_SHIFT = 3,
|
||||
MP0_ADB400_S_DCM_CTRL_SHIFT = 4,
|
||||
MP0_ADB400_M_DCM_CTRL_SHIFT = 5,
|
||||
MP1_ADB400_S_DCM_CTRL_SHIFT = 6,
|
||||
MP1_ADB400_M_DCM_CTRL_SHIFT = 7,
|
||||
EMICLK_EMI_DYNAMIC_CG_EN_SHIFT = 8,
|
||||
INFRACLK_INFRA_DYNAMIC_CG_EN_SHIFT = 9,
|
||||
EMICLK_GPU_DYNAMIC_CG_EN_SHIFT = 10,
|
||||
INFRACLK_PSYS_DYNAMIC_CG_EN_SHIFT = 11,
|
||||
EMICLK_EMI1_DYNAMIC_CG_EN_SHIFT = 12,
|
||||
EMI1_ADB400_S_DCM_CTRL_SHIFT = 16,
|
||||
MP2_ADB400_M_DCM_CTRL_SHIFT = 17,
|
||||
MP0_ICC_AXI_STREAM_ARCH_CG_SHIFT = 18,
|
||||
MP1_ICC_AXI_STREAM_ARCH_CG_SHIFT = 19,
|
||||
MP2_ICC_AXI_STREAM_ARCH_CG_SHIFT = 20,
|
||||
L2_SHARE_ADB400_DCM_CTRL_SHIFT = 21,
|
||||
MP1_AGGRESS_DCM_CTRL_SHIFT = 22,
|
||||
MP0_AGGRESS_DCM_CTRL_SHIFT = 23,
|
||||
MP0_ADB400_ACP_S_DCM_CTRL_SHIFT = 24,
|
||||
MP0_ADB400_ACP_M_DCM_CTRL_SHIFT = 25,
|
||||
MP1_ADB400_ACP_S_DCM_CTRL_SHIFT = 26,
|
||||
MP1_ADB400_ACP_M_DCM_CTRL_SHIFT = 27,
|
||||
MP3_ADB400_M_DCM_CTRL_SHIFT = 28,
|
||||
MP3_ICC_AXI_STREAM_ARCH_CG_SHIFT = 29,
|
||||
|
||||
MCUSYS_BUS_FABRIC_DCM_MASK = (1 << ACLK_INFRA_DYNAMIC_CG_EN_SHIFT) |
|
||||
(1 << EMI2_ADB400_S_DCM_CTRL_SHIFT) |
|
||||
(1 << ACLK_GPU_DYNAMIC_CG_EN_SHIFT) |
|
||||
(1 << ACLK_PSYS_DYNAMIC_CG_EN_SHIFT) |
|
||||
(1 << MP0_ADB400_S_DCM_CTRL_SHIFT) |
|
||||
(1 << MP0_ADB400_M_DCM_CTRL_SHIFT) |
|
||||
(1 << MP1_ADB400_S_DCM_CTRL_SHIFT) |
|
||||
(1 << MP1_ADB400_M_DCM_CTRL_SHIFT) |
|
||||
(1 << EMICLK_EMI_DYNAMIC_CG_EN_SHIFT) |
|
||||
(1 << INFRACLK_INFRA_DYNAMIC_CG_EN_SHIFT) |
|
||||
(1 << EMICLK_GPU_DYNAMIC_CG_EN_SHIFT) |
|
||||
(1 << INFRACLK_PSYS_DYNAMIC_CG_EN_SHIFT) |
|
||||
(1 << EMICLK_EMI1_DYNAMIC_CG_EN_SHIFT) |
|
||||
(1 << EMI1_ADB400_S_DCM_CTRL_SHIFT) |
|
||||
(1 << MP2_ADB400_M_DCM_CTRL_SHIFT) |
|
||||
(1 << MP0_ICC_AXI_STREAM_ARCH_CG_SHIFT) |
|
||||
(1 << MP1_ICC_AXI_STREAM_ARCH_CG_SHIFT) |
|
||||
(1 << MP2_ICC_AXI_STREAM_ARCH_CG_SHIFT) |
|
||||
(1 << L2_SHARE_ADB400_DCM_CTRL_SHIFT) |
|
||||
(1 << MP1_AGGRESS_DCM_CTRL_SHIFT) |
|
||||
(1 << MP0_AGGRESS_DCM_CTRL_SHIFT) |
|
||||
(1 << MP0_ADB400_ACP_S_DCM_CTRL_SHIFT) |
|
||||
(1 << MP0_ADB400_ACP_M_DCM_CTRL_SHIFT) |
|
||||
(1 << MP1_ADB400_ACP_S_DCM_CTRL_SHIFT) |
|
||||
(1 << MP1_ADB400_ACP_M_DCM_CTRL_SHIFT) |
|
||||
(1 << MP3_ADB400_M_DCM_CTRL_SHIFT) |
|
||||
(1 << MP3_ICC_AXI_STREAM_ARCH_CG_SHIFT),
|
||||
|
||||
MCUSYS_BUS_FABRIC_DCM = (1 << ACLK_INFRA_DYNAMIC_CG_EN_SHIFT) |
|
||||
(1 << EMI2_ADB400_S_DCM_CTRL_SHIFT) |
|
||||
(1 << ACLK_GPU_DYNAMIC_CG_EN_SHIFT) |
|
||||
(1 << ACLK_PSYS_DYNAMIC_CG_EN_SHIFT) |
|
||||
(0 << MP0_ADB400_S_DCM_CTRL_SHIFT) |
|
||||
(0 << MP0_ADB400_M_DCM_CTRL_SHIFT) |
|
||||
(1 << MP1_ADB400_S_DCM_CTRL_SHIFT) |
|
||||
(1 << MP1_ADB400_M_DCM_CTRL_SHIFT) |
|
||||
(1 << EMICLK_EMI_DYNAMIC_CG_EN_SHIFT) |
|
||||
(1 << INFRACLK_INFRA_DYNAMIC_CG_EN_SHIFT) |
|
||||
(1 << EMICLK_GPU_DYNAMIC_CG_EN_SHIFT) |
|
||||
(1 << INFRACLK_PSYS_DYNAMIC_CG_EN_SHIFT) |
|
||||
(1 << EMICLK_EMI1_DYNAMIC_CG_EN_SHIFT) |
|
||||
(1 << EMI1_ADB400_S_DCM_CTRL_SHIFT) |
|
||||
(0 << MP2_ADB400_M_DCM_CTRL_SHIFT) |
|
||||
(1 << MP0_ICC_AXI_STREAM_ARCH_CG_SHIFT) |
|
||||
(1 << MP1_ICC_AXI_STREAM_ARCH_CG_SHIFT) |
|
||||
(1 << MP2_ICC_AXI_STREAM_ARCH_CG_SHIFT) |
|
||||
(1 << L2_SHARE_ADB400_DCM_CTRL_SHIFT) |
|
||||
(1 << MP1_AGGRESS_DCM_CTRL_SHIFT) |
|
||||
(1 << MP0_AGGRESS_DCM_CTRL_SHIFT) |
|
||||
(1 << MP0_ADB400_ACP_S_DCM_CTRL_SHIFT) |
|
||||
(1 << MP0_ADB400_ACP_M_DCM_CTRL_SHIFT) |
|
||||
(1 << MP1_ADB400_ACP_S_DCM_CTRL_SHIFT) |
|
||||
(1 << MP1_ADB400_ACP_M_DCM_CTRL_SHIFT) |
|
||||
(1 << MP3_ADB400_M_DCM_CTRL_SHIFT) |
|
||||
(1 << MP3_ICC_AXI_STREAM_ARCH_CG_SHIFT)
|
||||
};
|
||||
|
||||
/* l2c_sram dcm related */
|
||||
enum {
|
||||
L2C_SRAM_DCM_EN_SHIFT = 0,
|
||||
L2C_SRAM_DCM = 1 << L2C_SRAM_DCM_EN_SHIFT
|
||||
};
|
||||
|
||||
/* mcu misc dcm related */
|
||||
enum {
|
||||
MP0_CNTVALUEB_DCM_EN_SHIFT = 0,
|
||||
MP_CNTVALUEB_DCM_EN = 8,
|
||||
|
||||
CNTVALUEB_DCM = (1 << MP0_CNTVALUEB_DCM_EN_SHIFT) |
|
||||
(1 << MP_CNTVALUEB_DCM_EN)
|
||||
};
|
||||
|
||||
/* sync dcm cluster config related */
|
||||
enum {
|
||||
MP0_SYNC_DCM_STALL_WR_EN_SHIFT = 7,
|
||||
MCUSYS_MAX_ACCESS_LATENCY_SHIFT = 24,
|
||||
|
||||
MCU0_SYNC_DCM_STALL_WR_EN = 1 << MP0_SYNC_DCM_STALL_WR_EN_SHIFT,
|
||||
|
||||
MCUSYS_MAX_ACCESS_LATENCY_MASK = 0xf << MCUSYS_MAX_ACCESS_LATENCY_SHIFT,
|
||||
MCUSYS_MAX_ACCESS_LATENCY = 0x5 << MCUSYS_MAX_ACCESS_LATENCY_SHIFT
|
||||
};
|
||||
|
||||
/* cpusys rgu dcm related */
|
||||
enum {
|
||||
CPUSYS_RGU_DCM_CONFIG_SHIFT = 0,
|
||||
|
||||
CPUSYS_RGU_DCM_CINFIG = 1 << CPUSYS_RGU_DCM_CONFIG_SHIFT
|
||||
};
|
||||
|
||||
/* mp2 sync dcm related */
|
||||
enum {
|
||||
MP2_DCM_EN_SHIFT = 0,
|
||||
|
||||
MP2_DCM_EN = 1 << MP2_DCM_EN_SHIFT
|
||||
};
|
||||
#endif /* MT8183_MCUCFG_H */
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
#define BIT_CA15M_L2PARITY_EN (1 << 1)
|
||||
#define BIT_CA15M_LASTPC_DIS (1 << 8)
|
||||
|
||||
#define MP1_CPUTOP_PWR_CON 0x10006218
|
||||
|
||||
#define MCU_ALL_PWR_ON_CTRL 0x0c530b58
|
||||
#define PLAT_MTK_CIRCULAR_BUFFER_UNLOCK 0xefab4133
|
||||
#define PLAT_MTK_CIRCULAR_BUFFER_LOCK 0xefab4134
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#define APMIXEDSYS (IO_PHYS + 0xC000)
|
||||
#define ARMPLL_LL_CON0 (APMIXEDSYS + 0x200)
|
||||
#define ARMPLL_L_CON0 (APMIXEDSYS + 0x210)
|
||||
#define ARMPLL_L_PWR_CON0 (APMIXEDSYS + 0x21c)
|
||||
#define MAINPLL_CON0 (APMIXEDSYS + 0x220)
|
||||
#define CCIPLL_CON0 (APMIXEDSYS + 0x290)
|
||||
|
||||
|
@ -74,6 +75,7 @@
|
|||
#define MT_L2_WRITE_ACCESS_RATE (MCUCFG_BASE + 0x604)
|
||||
#define MP0_CA7L_CACHE_CONFIG (MCUCFG_BASE + 0x7f0)
|
||||
#define MP1_CA7L_CACHE_CONFIG (MCUCFG_BASE + 0x7f4)
|
||||
#define EMI_WFIFO (MCUCFG_BASE + 0x0b5c)
|
||||
|
||||
/*******************************************************************************
|
||||
* GIC related constants
|
||||
|
@ -87,6 +89,7 @@
|
|||
* UART related constants
|
||||
******************************************************************************/
|
||||
#define UART0_BASE (IO_PHYS + 0x01002000)
|
||||
#define UART1_BASE (IO_PHYS + 0x01003000)
|
||||
|
||||
#define UART_BAUDRATE 115200
|
||||
#define UART_CLOCK 26000000
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef __SSPM_REG_H__
|
||||
#define __SSPM_REG_H__
|
||||
|
||||
#include "platform_def.h"
|
||||
|
||||
#define SSPM_CFGREG_RSV_RW_REG0 (SSPM_CFGREG_BASE + 0x0100)
|
||||
#define SSPM_CFGREG_ACAO_INT_SET (SSPM_CFGREG_BASE + 0x00D8)
|
||||
#define SSPM_CFGREG_ACAO_INT_CLR (SSPM_CFGREG_BASE + 0x00DC)
|
||||
#define SSPM_CFGREG_ACAO_WAKEUP_EN (SSPM_CFGREG_BASE + 0x0204)
|
||||
|
||||
#define STANDBYWFI_EN(n) (1 << (n + 8))
|
||||
#define GIC_IRQOUT_EN(n) (1 << (n + 0))
|
||||
|
||||
#define NF_MCDI_MBOX 19
|
||||
#define MCDI_MBOX_CLUSTER_0_CAN_POWER_OFF 0
|
||||
#define MCDI_MBOX_CLUSTER_1_CAN_POWER_OFF 1
|
||||
#define MCDI_MBOX_BUCK_POWER_OFF_MASK 2
|
||||
#define MCDI_MBOX_CLUSTER_0_ATF_ACTION_DONE 3
|
||||
#define MCDI_MBOX_CLUSTER_1_ATF_ACTION_DONE 4
|
||||
#define MCDI_MBOX_BOOTADDR 5
|
||||
#define MCDI_MBOX_PAUSE_ACTION 6
|
||||
#define MCDI_MBOX_AVAIL_CPU_MASK 7
|
||||
#define MCDI_MBOX_CPU_CLUSTER_PWR_STAT 8
|
||||
#define MCDI_MBOX_ACTION_STAT 9
|
||||
#define MCDI_MBOX_CLUSTER_0_CNT 10
|
||||
#define MCDI_MBOX_CLUSTER_1_CNT 11
|
||||
#define MCDI_MBOX_CPU_ISOLATION_MASK 12
|
||||
#define MCDI_MBOX_PAUSE_ACK 13
|
||||
#define MCDI_MBOX_PENDING_ON_EVENT 14
|
||||
#define MCDI_MBOX_PROF_CMD 15
|
||||
#define MCDI_MBOX_DRCC_CALI_DONE 16
|
||||
#define MCDI_MBOX_HP_CMD 17
|
||||
#define MCDI_MBOX_HP_ACK 18
|
||||
|
||||
#endif /* __SSPM_REG_H__ */
|
|
@ -9,6 +9,7 @@
|
|||
#include <lib/mmio.h>
|
||||
#include <plat_debug.h>
|
||||
#include <platform_def.h>
|
||||
#include <spm.h>
|
||||
|
||||
void circular_buffer_setup(void)
|
||||
{
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <platform_def.h>
|
||||
#include <scu.h>
|
||||
#include <mt_gic_v3.h>
|
||||
#include <mtk_mcdi.h>
|
||||
#include <mtk_plat_common.h>
|
||||
#include <mtgpio.h>
|
||||
#include <mtspmc.h>
|
||||
|
@ -25,9 +26,103 @@
|
|||
#include <plat_private.h>
|
||||
#include <power_tracer.h>
|
||||
#include <pmic.h>
|
||||
#include <spm.h>
|
||||
#include <spm_suspend.h>
|
||||
#include <sspm.h>
|
||||
#include <rtc.h>
|
||||
|
||||
#define MTK_LOCAL_STATE_OFF 2
|
||||
/* Local power state for power domains in Run state. */
|
||||
#define MTK_LOCAL_STATE_RUN 0
|
||||
/* Local power state for retention. */
|
||||
#define MTK_LOCAL_STATE_RET 1
|
||||
/* Local power state for OFF/power-down. */
|
||||
#define MTK_LOCAL_STATE_OFF 2
|
||||
|
||||
#if PSCI_EXTENDED_STATE_ID
|
||||
/*
|
||||
* Macros used to parse state information from State-ID if it is using the
|
||||
* recommended encoding for State-ID.
|
||||
*/
|
||||
#define MTK_LOCAL_PSTATE_WIDTH 4
|
||||
#define MTK_LOCAL_PSTATE_MASK ((1 << MTK_LOCAL_PSTATE_WIDTH) - 1)
|
||||
|
||||
/* Macros to construct the composite power state */
|
||||
|
||||
/* Make composite power state parameter till power level 0 */
|
||||
|
||||
#define mtk_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \
|
||||
(((lvl0_state) << PSTATE_ID_SHIFT) | ((type) << PSTATE_TYPE_SHIFT))
|
||||
|
||||
#else /* !PSCI_EXTENDED_STATE_ID */
|
||||
|
||||
#define mtk_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \
|
||||
(((lvl0_state) << PSTATE_ID_SHIFT) | \
|
||||
((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \
|
||||
((type) << PSTATE_TYPE_SHIFT))
|
||||
|
||||
#endif /* PSCI_EXTENDED_STATE_ID */
|
||||
|
||||
/* Make composite power state parameter till power level 1 */
|
||||
#define mtk_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \
|
||||
(((lvl1_state) << MTK_LOCAL_PSTATE_WIDTH) | \
|
||||
mtk_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type))
|
||||
|
||||
/* Make composite power state parameter till power level 2 */
|
||||
#define mtk_make_pwrstate_lvl2( \
|
||||
lvl2_state, lvl1_state, lvl0_state, pwr_lvl, type) \
|
||||
(((lvl2_state) << (MTK_LOCAL_PSTATE_WIDTH * 2)) | \
|
||||
mtk_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type))
|
||||
|
||||
#define MTK_PWR_LVL0 0
|
||||
#define MTK_PWR_LVL1 1
|
||||
#define MTK_PWR_LVL2 2
|
||||
|
||||
/* Macros to read the MTK power domain state */
|
||||
#define MTK_CORE_PWR_STATE(state) (state)->pwr_domain_state[MTK_PWR_LVL0]
|
||||
#define MTK_CLUSTER_PWR_STATE(state) (state)->pwr_domain_state[MTK_PWR_LVL1]
|
||||
#define MTK_SYSTEM_PWR_STATE(state) ((PLAT_MAX_PWR_LVL > MTK_PWR_LVL1) ? \
|
||||
(state)->pwr_domain_state[MTK_PWR_LVL2] : 0)
|
||||
|
||||
#if PSCI_EXTENDED_STATE_ID
|
||||
/*
|
||||
* The table storing the valid idle power states. Ensure that the
|
||||
* array entries are populated in ascending order of state-id to
|
||||
* enable us to use binary search during power state validation.
|
||||
* The table must be terminated by a NULL entry.
|
||||
*/
|
||||
const unsigned int mtk_pm_idle_states[] = {
|
||||
/* State-id - 0x001 */
|
||||
mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_RUN, MTK_LOCAL_STATE_RUN,
|
||||
MTK_LOCAL_STATE_RET, MTK_PWR_LVL0, PSTATE_TYPE_STANDBY),
|
||||
/* State-id - 0x002 */
|
||||
mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_RUN, MTK_LOCAL_STATE_RUN,
|
||||
MTK_LOCAL_STATE_OFF, MTK_PWR_LVL0, PSTATE_TYPE_POWERDOWN),
|
||||
/* State-id - 0x022 */
|
||||
mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_RUN, MTK_LOCAL_STATE_OFF,
|
||||
MTK_LOCAL_STATE_OFF, MTK_PWR_LVL1, PSTATE_TYPE_POWERDOWN),
|
||||
#if PLAT_MAX_PWR_LVL > MTK_PWR_LVL1
|
||||
/* State-id - 0x222 */
|
||||
mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_OFF, MTK_LOCAL_STATE_OFF,
|
||||
MTK_LOCAL_STATE_OFF, MTK_PWR_LVL2, PSTATE_TYPE_POWERDOWN),
|
||||
#endif
|
||||
0,
|
||||
};
|
||||
#endif
|
||||
|
||||
#define CPU_IDX(cluster, cpu) ((cluster << 2) + cpu)
|
||||
#define ON true
|
||||
#define OFF false
|
||||
|
||||
/* Pause MCDI when CPU hotplug */
|
||||
static bool HP_SSPM_PAUSE;
|
||||
/* CPU Hotplug by SSPM */
|
||||
static bool HP_SSPM_CTRL = true;
|
||||
/* Turn off cluster when CPU hotplug off */
|
||||
static bool HP_CLUSTER_OFF = true;
|
||||
/* Turn off cluster when CPU MCDI off */
|
||||
static bool MCDI_C2 = true;
|
||||
/* Enable MCDI */
|
||||
static bool MCDI_SSPM = true;
|
||||
|
||||
static uintptr_t secure_entrypoint;
|
||||
|
||||
|
@ -38,30 +133,171 @@ static void mp1_L2_desel_config(void)
|
|||
dsb();
|
||||
}
|
||||
|
||||
static bool clst_single_pwr(int cluster, int cpu)
|
||||
{
|
||||
uint32_t cpu_mask[2] = {0x00001e00, 0x000f0000};
|
||||
uint32_t cpu_pwr_bit[] = {9, 10, 11, 12, 16, 17, 18, 19};
|
||||
int my_idx = (cluster << 2) + cpu;
|
||||
uint32_t pwr_stat = mmio_read_32(0x10006180);
|
||||
|
||||
return !(pwr_stat & (cpu_mask[cluster] & ~BIT(cpu_pwr_bit[my_idx])));
|
||||
}
|
||||
|
||||
static bool clst_single_on(int cluster, int cpu)
|
||||
{
|
||||
uint32_t cpu_mask[2] = {0x0f, 0xf0};
|
||||
int my_idx = (cluster << 2) + cpu;
|
||||
uint32_t on_stat = mcdi_avail_cpu_mask_read();
|
||||
|
||||
return !(on_stat & (cpu_mask[cluster] & ~BIT(my_idx)));
|
||||
}
|
||||
|
||||
static void plat_cluster_pwrdwn_common(uint64_t mpidr, int cluster)
|
||||
{
|
||||
if (cluster > 0)
|
||||
mt_gic_sync_dcm_enable();
|
||||
|
||||
/* Disable coherency */
|
||||
plat_mtk_cci_disable();
|
||||
disable_scu(mpidr);
|
||||
}
|
||||
|
||||
static void plat_cluster_pwron_common(uint64_t mpidr, int cluster)
|
||||
{
|
||||
if (cluster > 0) {
|
||||
l2c_parity_check_setup();
|
||||
circular_buffer_setup();
|
||||
mp1_L2_desel_config();
|
||||
mt_gic_sync_dcm_disable();
|
||||
}
|
||||
|
||||
/* Enable coherency */
|
||||
enable_scu(mpidr);
|
||||
plat_mtk_cci_enable();
|
||||
/* Enable big core dcm */
|
||||
plat_dcm_restore_cluster_on(mpidr);
|
||||
/* Enable rgu dcm */
|
||||
plat_dcm_rgu_enable();
|
||||
}
|
||||
|
||||
static void plat_cpu_standby(plat_local_state_t cpu_state)
|
||||
{
|
||||
unsigned int scr;
|
||||
|
||||
scr = read_scr_el3();
|
||||
write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
|
||||
|
||||
isb();
|
||||
dsb();
|
||||
wfi();
|
||||
|
||||
write_scr_el3(scr);
|
||||
}
|
||||
|
||||
static void mcdi_ctrl_before_hotplug_on(int cluster, int cpu)
|
||||
{
|
||||
if (!HP_SSPM_CTRL && HP_SSPM_PAUSE && MCDI_SSPM) {
|
||||
mcdi_pause_clr(cluster, CPU_IDX(cluster, cpu), OFF);
|
||||
mcdi_pause_set(cluster, CPU_IDX(cluster, cpu), ON);
|
||||
}
|
||||
}
|
||||
|
||||
static void mcdi_ctrl_before_hotplug_off(int cluster, int cpu, bool cluster_off)
|
||||
{
|
||||
if (!HP_SSPM_CTRL && HP_SSPM_PAUSE && MCDI_SSPM)
|
||||
mcdi_pause_set(cluster_off ? cluster : -1,
|
||||
CPU_IDX(cluster, cpu), OFF);
|
||||
}
|
||||
|
||||
static void mcdi_ctrl_cluster_cpu_off(int cluster, int cpu, bool cluster_off)
|
||||
{
|
||||
if (MCDI_SSPM) {
|
||||
sspm_set_bootaddr(secure_entrypoint);
|
||||
|
||||
sspm_standbywfi_irq_enable(CPU_IDX(cluster, cpu));
|
||||
|
||||
if (cluster_off)
|
||||
sspm_cluster_pwr_off_notify(cluster);
|
||||
else
|
||||
sspm_cluster_pwr_on_notify(cluster);
|
||||
}
|
||||
}
|
||||
|
||||
static void mcdi_ctrl_suspend(void)
|
||||
{
|
||||
if (MCDI_SSPM)
|
||||
mcdi_pause();
|
||||
}
|
||||
|
||||
static void mcdi_ctrl_resume(void)
|
||||
{
|
||||
if (MCDI_SSPM)
|
||||
mcdi_unpause();
|
||||
}
|
||||
|
||||
static void hotplug_ctrl_cluster_on(int cluster, int cpu)
|
||||
{
|
||||
if (HP_SSPM_CTRL && MCDI_SSPM) {
|
||||
mcdi_hotplug_clr(cluster, CPU_IDX(cluster, cpu), OFF);
|
||||
mcdi_hotplug_set(cluster, -1, ON);
|
||||
mcdi_hotplug_wait_ack(cluster, -1, ON);
|
||||
} else {
|
||||
/* power on cluster */
|
||||
if (!spm_get_cluster_powerstate(cluster))
|
||||
spm_poweron_cluster(cluster);
|
||||
}
|
||||
}
|
||||
|
||||
static void hotplug_ctrl_cpu_on(int cluster, int cpu)
|
||||
{
|
||||
if (HP_SSPM_CTRL && MCDI_SSPM)
|
||||
mcdi_hotplug_set(cluster, CPU_IDX(cluster, cpu), ON);
|
||||
else
|
||||
spm_poweron_cpu(cluster, cpu);
|
||||
}
|
||||
|
||||
static void hotplug_ctrl_cpu_on_finish(int cluster, int cpu)
|
||||
{
|
||||
spm_disable_cpu_auto_off(cluster, cpu);
|
||||
|
||||
if (HP_SSPM_CTRL && MCDI_SSPM)
|
||||
mcdi_hotplug_clr(cluster, CPU_IDX(cluster, cpu), ON);
|
||||
else if (HP_SSPM_PAUSE && MCDI_SSPM)
|
||||
mcdi_pause_clr(cluster, CPU_IDX(cluster, cpu), ON);
|
||||
|
||||
mcdi_avail_cpu_mask_set(BIT(CPU_IDX(cluster, cpu)));
|
||||
}
|
||||
|
||||
static void hotplug_ctrl_cluster_cpu_off(int cluster, int cpu, bool cluster_off)
|
||||
{
|
||||
mcdi_avail_cpu_mask_clr(BIT(CPU_IDX(cluster, cpu)));
|
||||
|
||||
if (HP_SSPM_CTRL && MCDI_SSPM) {
|
||||
mcdi_hotplug_set(cluster_off ? cluster : -1,
|
||||
CPU_IDX(cluster, cpu), OFF);
|
||||
} else {
|
||||
spm_enable_cpu_auto_off(cluster, cpu);
|
||||
|
||||
if (cluster_off)
|
||||
spm_enable_cluster_auto_off(cluster);
|
||||
|
||||
spm_set_cpu_power_off(cluster, cpu);
|
||||
}
|
||||
}
|
||||
|
||||
static int plat_mtk_power_domain_on(unsigned long mpidr)
|
||||
{
|
||||
int cpu = MPIDR_AFFLVL0_VAL(mpidr);
|
||||
int cluster = MPIDR_AFFLVL1_VAL(mpidr);
|
||||
|
||||
INFO("%s():%d: mpidr: %lx, c.c: %d.%d\n",
|
||||
__func__, __LINE__, mpidr, cluster, cpu);
|
||||
|
||||
/* power on cluster */
|
||||
if (!spm_get_cluster_powerstate(cluster)) {
|
||||
spm_poweron_cluster(cluster);
|
||||
if (cluster == 1) {
|
||||
l2c_parity_check_setup();
|
||||
circular_buffer_setup();
|
||||
mp1_L2_desel_config();
|
||||
mt_gic_sync_dcm_disable();
|
||||
}
|
||||
}
|
||||
mcdi_ctrl_before_hotplug_on(cluster, cpu);
|
||||
hotplug_ctrl_cluster_on(cluster, cpu);
|
||||
|
||||
/* init cpu reset arch as AARCH64 */
|
||||
mcucfg_init_archstate(cluster, cpu, 1);
|
||||
mcucfg_set_bootaddr(cluster, cpu, secure_entrypoint);
|
||||
|
||||
spm_poweron_cpu(cluster, cpu);
|
||||
hotplug_ctrl_cpu_on(cluster, cpu);
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
@ -71,23 +307,18 @@ static void plat_mtk_power_domain_off(const psci_power_state_t *state)
|
|||
uint64_t mpidr = read_mpidr();
|
||||
int cpu = MPIDR_AFFLVL0_VAL(mpidr);
|
||||
int cluster = MPIDR_AFFLVL1_VAL(mpidr);
|
||||
const plat_local_state_t *pds = state->pwr_domain_state;
|
||||
bool afflvl1 = (pds[MPIDR_AFFLVL1] == MTK_LOCAL_STATE_OFF);
|
||||
bool cluster_off = (HP_CLUSTER_OFF && afflvl1 &&
|
||||
clst_single_on(cluster, cpu));
|
||||
|
||||
INFO("%s():%d: c.c: %d.%d\n", __func__, __LINE__, cluster, cpu);
|
||||
|
||||
/* Prevent interrupts from spuriously waking up this cpu */
|
||||
mt_gic_cpuif_disable();
|
||||
|
||||
spm_enable_cpu_auto_off(cluster, cpu);
|
||||
if (cluster_off)
|
||||
plat_cluster_pwrdwn_common(mpidr, cluster);
|
||||
|
||||
if (state->pwr_domain_state[MPIDR_AFFLVL1] == MTK_LOCAL_STATE_OFF) {
|
||||
if (cluster == 1)
|
||||
mt_gic_sync_dcm_enable();
|
||||
|
||||
plat_mtk_cci_disable();
|
||||
spm_enable_cluster_auto_off(cluster);
|
||||
}
|
||||
|
||||
spm_set_cpu_power_off(cluster, cpu);
|
||||
mcdi_ctrl_before_hotplug_off(cluster, cpu, cluster_off);
|
||||
hotplug_ctrl_cluster_cpu_off(cluster, cpu, cluster_off);
|
||||
}
|
||||
|
||||
static void plat_mtk_power_domain_on_finish(const psci_power_state_t *state)
|
||||
|
@ -95,29 +326,170 @@ static void plat_mtk_power_domain_on_finish(const psci_power_state_t *state)
|
|||
uint64_t mpidr = read_mpidr();
|
||||
int cpu = MPIDR_AFFLVL0_VAL(mpidr);
|
||||
int cluster = MPIDR_AFFLVL1_VAL(mpidr);
|
||||
const plat_local_state_t *pds = state->pwr_domain_state;
|
||||
bool afflvl1 = (pds[MPIDR_AFFLVL1] == MTK_LOCAL_STATE_OFF);
|
||||
|
||||
INFO("%s():%d: c.c: %d.%d\n", __func__, __LINE__, cluster, cpu);
|
||||
if (afflvl1)
|
||||
plat_cluster_pwron_common(mpidr, cluster);
|
||||
|
||||
assert(state->pwr_domain_state[MPIDR_AFFLVL0] == MTK_LOCAL_STATE_OFF);
|
||||
|
||||
if (state->pwr_domain_state[MPIDR_AFFLVL1] == MTK_LOCAL_STATE_OFF) {
|
||||
enable_scu(mpidr);
|
||||
|
||||
/* Enable coherency if this cluster was off */
|
||||
plat_mtk_cci_enable();
|
||||
/* Enable big core dcm if this cluster was on */
|
||||
plat_dcm_restore_cluster_on(mpidr);
|
||||
/* Enable rgu dcm if this cluster was off */
|
||||
plat_dcm_rgu_enable();
|
||||
}
|
||||
|
||||
spm_disable_cpu_auto_off(cluster, cpu);
|
||||
|
||||
/* Enable the gic cpu interface */
|
||||
mt_gic_pcpu_init();
|
||||
mt_gic_cpuif_enable();
|
||||
|
||||
hotplug_ctrl_cpu_on_finish(cluster, cpu);
|
||||
}
|
||||
|
||||
static void plat_mtk_power_domain_suspend(const psci_power_state_t *state)
|
||||
{
|
||||
uint64_t mpidr = read_mpidr();
|
||||
int cpu = MPIDR_AFFLVL0_VAL(mpidr);
|
||||
int cluster = MPIDR_AFFLVL1_VAL(mpidr);
|
||||
const plat_local_state_t *pds = state->pwr_domain_state;
|
||||
bool afflvl1 = (pds[MPIDR_AFFLVL1] == MTK_LOCAL_STATE_OFF);
|
||||
bool afflvl2 = (pds[MPIDR_AFFLVL2] == MTK_LOCAL_STATE_OFF);
|
||||
bool cluster_off = MCDI_C2 && afflvl1 && clst_single_pwr(cluster, cpu);
|
||||
|
||||
/* init cpu reset arch as AARCH64 */
|
||||
mcucfg_init_archstate(cluster, cpu, 1);
|
||||
mcucfg_set_bootaddr(cluster, cpu, secure_entrypoint);
|
||||
|
||||
mt_gic_cpuif_disable();
|
||||
mt_gic_irq_save();
|
||||
plat_dcm_mcsi_a_backup();
|
||||
|
||||
if (cluster_off || afflvl2)
|
||||
plat_cluster_pwrdwn_common(mpidr, cluster);
|
||||
|
||||
if (afflvl2) {
|
||||
spm_data_t spm_d = { .cmd = SPM_SUSPEND };
|
||||
uint32_t *d = (uint32_t *)&spm_d;
|
||||
uint32_t l = sizeof(spm_d) / sizeof(uint32_t);
|
||||
|
||||
mcdi_ctrl_suspend();
|
||||
|
||||
spm_set_bootaddr(secure_entrypoint);
|
||||
|
||||
if (MCDI_SSPM)
|
||||
sspm_ipi_send_non_blocking(IPI_ID_SUSPEND, d);
|
||||
|
||||
spm_system_suspend();
|
||||
|
||||
if (MCDI_SSPM)
|
||||
while (sspm_ipi_recv_non_blocking(IPI_ID_SUSPEND, d, l))
|
||||
;
|
||||
} else {
|
||||
mcdi_ctrl_cluster_cpu_off(cluster, cpu, cluster_off);
|
||||
}
|
||||
}
|
||||
|
||||
static void plat_mtk_power_domain_suspend_finish(const psci_power_state_t *state)
|
||||
{
|
||||
uint64_t mpidr = read_mpidr();
|
||||
int cluster = MPIDR_AFFLVL1_VAL(mpidr);
|
||||
const plat_local_state_t *pds = state->pwr_domain_state;
|
||||
bool afflvl2 = (pds[MPIDR_AFFLVL2] == MTK_LOCAL_STATE_OFF);
|
||||
|
||||
if (afflvl2) {
|
||||
spm_data_t spm_d = { .cmd = SPM_RESUME };
|
||||
uint32_t *d = (uint32_t *)&spm_d;
|
||||
uint32_t l = sizeof(spm_d) / sizeof(uint32_t);
|
||||
|
||||
mt_gic_init();
|
||||
mt_gic_irq_restore();
|
||||
mmio_write_32(EMI_WFIFO, 0xf);
|
||||
|
||||
if (MCDI_SSPM)
|
||||
sspm_ipi_send_non_blocking(IPI_ID_SUSPEND, d);
|
||||
|
||||
spm_system_suspend_finish();
|
||||
|
||||
if (MCDI_SSPM)
|
||||
while (sspm_ipi_recv_non_blocking(IPI_ID_SUSPEND, d, l))
|
||||
;
|
||||
|
||||
mcdi_ctrl_resume();
|
||||
}
|
||||
|
||||
plat_cluster_pwron_common(mpidr, cluster);
|
||||
|
||||
plat_dcm_mcsi_a_restore();
|
||||
}
|
||||
|
||||
#if PSCI_EXTENDED_STATE_ID
|
||||
|
||||
static int plat_mtk_validate_power_state(unsigned int power_state,
|
||||
psci_power_state_t *req_state)
|
||||
{
|
||||
unsigned int state_id;
|
||||
int i;
|
||||
|
||||
assert(req_state);
|
||||
|
||||
if (!MCDI_SSPM)
|
||||
return PSCI_E_INVALID_PARAMS;
|
||||
|
||||
/*
|
||||
* Currently we are using a linear search for finding the matching
|
||||
* entry in the idle power state array. This can be made a binary
|
||||
* search if the number of entries justify the additional complexity.
|
||||
*/
|
||||
for (i = 0; !!mtk_pm_idle_states[i]; i++) {
|
||||
if (power_state == mtk_pm_idle_states[i])
|
||||
break;
|
||||
}
|
||||
|
||||
/* Return error if entry not found in the idle state array */
|
||||
if (!mtk_pm_idle_states[i])
|
||||
return PSCI_E_INVALID_PARAMS;
|
||||
|
||||
i = 0;
|
||||
state_id = psci_get_pstate_id(power_state);
|
||||
|
||||
/* Parse the State ID and populate the state info parameter */
|
||||
while (state_id) {
|
||||
req_state->pwr_domain_state[i++] = state_id &
|
||||
MTK_LOCAL_PSTATE_MASK;
|
||||
state_id >>= MTK_LOCAL_PSTATE_WIDTH;
|
||||
}
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
#else /* if !PSCI_EXTENDED_STATE_ID */
|
||||
|
||||
static int plat_mtk_validate_power_state(unsigned int power_state,
|
||||
psci_power_state_t *req_state)
|
||||
{
|
||||
int pstate = psci_get_pstate_type(power_state);
|
||||
int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
|
||||
int i;
|
||||
|
||||
assert(req_state);
|
||||
|
||||
if (pwr_lvl > PLAT_MAX_PWR_LVL)
|
||||
return PSCI_E_INVALID_PARAMS;
|
||||
|
||||
/* Sanity check the requested state */
|
||||
if (pstate == PSTATE_TYPE_STANDBY) {
|
||||
/*
|
||||
* It's possible to enter standby only on power level 0
|
||||
* Ignore any other power level.
|
||||
*/
|
||||
if (pwr_lvl != 0)
|
||||
return PSCI_E_INVALID_PARAMS;
|
||||
|
||||
req_state->pwr_domain_state[MTK_PWR_LVL0] = MTK_LOCAL_STATE_RET;
|
||||
} else if (!MCDI_SSPM) {
|
||||
return PSCI_E_INVALID_PARAMS;
|
||||
} else {
|
||||
for (i = 0; i <= pwr_lvl; i++)
|
||||
req_state->pwr_domain_state[i] = MTK_LOCAL_STATE_OFF;
|
||||
}
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
#endif /* PSCI_EXTENDED_STATE_ID */
|
||||
|
||||
/*******************************************************************************
|
||||
* MTK handlers to shutdown/reboot the system
|
||||
******************************************************************************/
|
||||
|
@ -147,21 +519,29 @@ static void __dead2 plat_mtk_system_reset(void)
|
|||
panic();
|
||||
}
|
||||
|
||||
static void plat_mtk_get_sys_suspend_power_state(psci_power_state_t *req_state)
|
||||
{
|
||||
assert(PLAT_MAX_PWR_LVL >= 2);
|
||||
|
||||
for (int i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
|
||||
req_state->pwr_domain_state[i] = MTK_LOCAL_STATE_OFF;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* MTK_platform handler called when an affinity instance is about to be turned
|
||||
* on. The level and mpidr determine the affinity instance.
|
||||
******************************************************************************/
|
||||
static const plat_psci_ops_t plat_plat_pm_ops = {
|
||||
.cpu_standby = NULL,
|
||||
.cpu_standby = plat_cpu_standby,
|
||||
.pwr_domain_on = plat_mtk_power_domain_on,
|
||||
.pwr_domain_on_finish = plat_mtk_power_domain_on_finish,
|
||||
.pwr_domain_off = plat_mtk_power_domain_off,
|
||||
.pwr_domain_suspend = NULL,
|
||||
.pwr_domain_suspend_finish = NULL,
|
||||
.pwr_domain_suspend = plat_mtk_power_domain_suspend,
|
||||
.pwr_domain_suspend_finish = plat_mtk_power_domain_suspend_finish,
|
||||
.system_off = plat_mtk_system_off,
|
||||
.system_reset = plat_mtk_system_reset,
|
||||
.validate_power_state = NULL,
|
||||
.get_sys_suspend_power_state = NULL,
|
||||
.validate_power_state = plat_mtk_validate_power_state,
|
||||
.get_sys_suspend_power_state = plat_mtk_get_sys_suspend_power_state,
|
||||
};
|
||||
|
||||
int plat_setup_psci_ops(uintptr_t sec_entrypoint,
|
||||
|
@ -169,5 +549,11 @@ int plat_setup_psci_ops(uintptr_t sec_entrypoint,
|
|||
{
|
||||
*psci_ops = &plat_plat_pm_ops;
|
||||
secure_entrypoint = sec_entrypoint;
|
||||
|
||||
if (!check_mcdi_ctl_stat()) {
|
||||
HP_SSPM_CTRL = false;
|
||||
MCDI_SSPM = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -9,10 +9,14 @@ MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT}
|
|||
|
||||
PLAT_INCLUDES := -I${MTK_PLAT}/common/ \
|
||||
-I${MTK_PLAT_SOC}/drivers/ \
|
||||
-I${MTK_PLAT_SOC}/drivers/mcdi/ \
|
||||
-I${MTK_PLAT_SOC}/drivers/spmc/ \
|
||||
-I${MTK_PLAT_SOC}/drivers/gpio/ \
|
||||
-I${MTK_PLAT_SOC}/drivers/pmic/ \
|
||||
-I${MTK_PLAT_SOC}/drivers/spm/ \
|
||||
-I${MTK_PLAT_SOC}/drivers/sspm/ \
|
||||
-I${MTK_PLAT_SOC}/drivers/rtc/ \
|
||||
-I${MTK_PLAT_SOC}/drivers/uart/ \
|
||||
-I${MTK_PLAT_SOC}/include/
|
||||
|
||||
PLAT_BL_COMMON_SOURCES := lib/xlat_tables/aarch64/xlat_tables.c \
|
||||
|
@ -45,15 +49,21 @@ BL31_SOURCES += common/desc_image_load.c \
|
|||
${MTK_PLAT_SOC}/drivers/mcsi/mcsi.c \
|
||||
${MTK_PLAT_SOC}/drivers/pmic/pmic.c \
|
||||
${MTK_PLAT_SOC}/drivers/rtc/rtc.c \
|
||||
${MTK_PLAT_SOC}/drivers/mcdi/mtk_mcdi.c \
|
||||
${MTK_PLAT_SOC}/drivers/spmc/mtspmc.c \
|
||||
${MTK_PLAT_SOC}/drivers/spm/spm.c \
|
||||
${MTK_PLAT_SOC}/drivers/spm/spm_pmic_wrap.c \
|
||||
${MTK_PLAT_SOC}/drivers/spm/spm_suspend.c \
|
||||
${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c \
|
||||
${MTK_PLAT_SOC}/drivers/uart/uart.c \
|
||||
${MTK_PLAT_SOC}/plat_pm.c \
|
||||
${MTK_PLAT_SOC}/plat_topology.c \
|
||||
${MTK_PLAT_SOC}/plat_mt_gic.c \
|
||||
${MTK_PLAT_SOC}/plat_dcm.c \
|
||||
${MTK_PLAT_SOC}/bl31_plat_setup.c \
|
||||
${MTK_PLAT_SOC}/plat_debug.c \
|
||||
${MTK_PLAT_SOC}/scu.c
|
||||
${MTK_PLAT_SOC}/scu.c \
|
||||
${MTK_PLAT_SOC}/drivers/sspm/sspm.c
|
||||
|
||||
# Enable workarounds for selected Cortex-A53 erratas.
|
||||
ERRATA_A53_826319 := 0
|
||||
|
|
Loading…
Reference in New Issue