Merge changes I0c1f7d6c,I3bec0b58,If24cf213 into integration

* changes:
  feat(plat/mediatek/apu): add mt8195 APU clock and pll SiP call
  feat(plat/mediatek/apu): add mt8195 APU mcu boot and stop SiP call
  feat(plat/mediatek/apu): add mt8195 APU iommap regions
This commit is contained in:
Manish Pandey 2021-12-01 14:21:50 +01:00 committed by TrustedFirmware Code Review
commit 2141a68543
11 changed files with 1307 additions and 1 deletions

View File

@ -21,6 +21,14 @@ const mmap_region_t plat_mmap[] = {
MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(eDP_SEC_BASE, eDP_SEC_SIZE,
MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(APUSYS_SCTRL_REVISER_BASE, APUSYS_SCTRL_REVISER_SIZE,
MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(APUSYS_APU_S_S_4_BASE, APUSYS_APU_S_S_4_SIZE,
MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(APUSYS_APU_PLL_BASE, APUSYS_APU_PLL_SIZE,
MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(APUSYS_APU_ACC_BASE, APUSYS_APU_ACC_SIZE,
MT_DEVICE | MT_RW | MT_SECURE),
{ 0 }
};

View File

@ -0,0 +1,581 @@
/*
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <errno.h>
#include <arch_helpers.h>
#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <lib/spinlock.h>
#include <apupwr_clkctl.h>
#include <apupwr_clkctl_def.h>
#include <mtk_plat_common.h>
#include <platform_def.h>
uint32_t mixed_con0_addr[APUPLL_MAX] = {
APU_PLL4H_PLL1_CON0,
APU_PLL4H_PLL2_CON0,
APU_PLL4H_PLL3_CON0,
APU_PLL4H_PLL4_CON0,
};
uint32_t mixed_con1_addr[APUPLL_MAX] = {
APU_PLL4H_PLL1_CON1,
APU_PLL4H_PLL2_CON1,
APU_PLL4H_PLL3_CON1,
APU_PLL4H_PLL4_CON1,
};
uint32_t mixed_con3_addr[APUPLL_MAX] = {
APU_PLL4H_PLL1_CON3,
APU_PLL4H_PLL2_CON3,
APU_PLL4H_PLL3_CON3,
APU_PLL4H_PLL4_CON3,
};
uint32_t fhctl_dds_addr[APUPLL_MAX] = {
APU_PLL4H_FHCTL0_DDS,
APU_PLL4H_FHCTL1_DDS,
APU_PLL4H_FHCTL2_DDS,
APU_PLL4H_FHCTL3_DDS,
};
uint32_t fhctl_dvfs_addr[APUPLL_MAX] = {
APU_PLL4H_FHCTL0_DVFS,
APU_PLL4H_FHCTL1_DVFS,
APU_PLL4H_FHCTL2_DVFS,
APU_PLL4H_FHCTL3_DVFS,
};
uint32_t fhctl_mon_addr[APUPLL_MAX] = {
APU_PLL4H_FHCTL0_MON,
APU_PLL4H_FHCTL1_MON,
APU_PLL4H_FHCTL2_MON,
APU_PLL4H_FHCTL3_MON,
};
uint32_t fhctl_cfg_addr[APUPLL_MAX] = {
APU_PLL4H_FHCTL0_CFG,
APU_PLL4H_FHCTL1_CFG,
APU_PLL4H_FHCTL2_CFG,
APU_PLL4H_FHCTL3_CFG,
};
static spinlock_t apupll_lock;
static spinlock_t npupll_lock;
static spinlock_t apupll_1_lock;
static spinlock_t apupll_2_lock;
static uint32_t pll_cnt[APUPLL_MAX];
/**
* vd2pllidx() - voltage domain to pll idx.
* @domain: the voltage domain for getting pll index.
*
* Caller will get correspond pll index by different voltage domain.
* pll_idx[0] --> APUPLL (MDLA0/1)
* pll_idx[1] --> NPUPLL (VPU0/1)
* pll_idx[2] --> APUPLL1(CONN)
* pll_idx[3] --> APUPLL2(IOMMU)
* The longer description may have multiple paragraphs.
*
* Context: Any context.
* Return:
* * 0 ~ 3 - return the corresponding pll index
* * -EEXIST - cannot find pll idex of the specific voltage domain
*
*/
static int32_t vd2pllidx(enum dvfs_voltage_domain domain)
{
int32_t ret;
switch (domain) {
case V_VPU0:
case V_VPU1:
ret = NPUPLL;
break;
case V_MDLA0:
case V_MDLA1:
ret = APUPLL;
break;
case V_TOP_IOMMU:
ret = APUPLL2;
break;
case V_APU_CONN:
ret = APUPLL1;
break;
default:
ERROR("%s wrong voltage domain: %d\n", __func__, domain);
ret = -EEXIST; /* non-exist */
break;
}
return ret;
}
/**
* pllidx2name() - return names of specific pll index.
* @pll_idx: input for specific pll index.
*
* Given pll index, this function will return name of it.
*
* Context: Any context.
* Return: Names of pll_idx, if found, otherwise will return "NULL"
*/
static const char *pllidx2name(int32_t pll_idx)
{
static const char *const names[] = {
[APUPLL] = "PLL4H_PLL1",
[NPUPLL] = "PLL4H_PLL2",
[APUPLL1] = "PLL4H_PLL3",
[APUPLL2] = "PLL4H_PLL4",
[APUPLL_MAX] = "NULL",
};
if (pll_idx >= APUPLL_MAX) {
pll_idx = APUPLL_MAX;
}
return names[pll_idx];
}
/**
* _fhctl_mon_done() - poll whether fhctl HW mode is done.
* @pll_idx: input for specific pll index.
* @tar_dds: target dds for fhctl_mon to be.
*
* Given pll index, this function will continue to poll whether fhctl_mon
* has reached the expected value within 80us.
*
* Context: Any context.
* Return:
* * 0 - OK for fhctl_mon == tar_dds
* * -ETIMEDOUT - fhctl_mon not reach tar_dds
*/
static int32_t _fhctl_mon_done(uint32_t pll_idx, unsigned long tar_dds)
{
unsigned long mon_dds;
uint64_t timeout = timeout_init_us(PLL_READY_TIME_20US);
int32_t ret = 0;
tar_dds &= DDS_MASK;
do {
mon_dds = apupwr_readl(fhctl_mon_addr[pll_idx]) & DDS_MASK;
if (mon_dds == tar_dds) {
break;
}
if (timeout_elapsed(timeout)) {
ERROR("%s monitor DDS 0x%08lx != expect 0x%08lx\n",
pllidx2name(pll_idx), mon_dds, tar_dds);
ret = -ETIMEDOUT;
break;
}
} while (mon_dds != tar_dds);
return ret;
}
/**
* _pll_get_postdiv_reg() - return current post dividor of pll_idx
* @pll_idx: input for specific pll index.
*
* Given pll index, this function will return its current post dividor.
*
* Context: Any context.
* Return: post dividor of current pll_idx.
*
*/
static uint32_t _pll_get_postdiv_reg(uint32_t pll_idx)
{
int32_t pll_postdiv_reg = 0;
uint32_t val;
val = apupwr_readl(mixed_con1_addr[pll_idx]);
pll_postdiv_reg = (val >> POSDIV_SHIFT) & POSDIV_MASK;
return pll_postdiv_reg;
}
/**
* _set_postdiv_reg() - set pll_idx's post dividor.
* @pll_idx: Which PLL to enable/disable
* @post_div: the register value of post dividor to be wrtten.
*
* Below are lists of post dividor register value and its meaning:
* [31] APUPLL_SDM_PCW_CHG
* [26:24] APUPLL_POSDIV
* [21:0] APUPLL_SDM_PCW (8bit integer + 14bit fraction)
* expected freq range ----- divider-------post divider in reg:
* >1500M (1500/ 1) -> 1 -> 0(2 to the zero power)
* > 750M (1500/ 2) -> 2 -> 1(2 to the 1st power)
* > 375M (1500/ 4) -> 4 -> 2(2 to the 2nd power)
* > 187.5M (1500/ 8) -> 8 -> 3(2 to the 3rd power)
* > 93.75M (1500/16) -> 16 -> 4(2 to the 4th power)
*
* Context: Any context.
*/
static void _set_postdiv_reg(uint32_t pll_idx, uint32_t post_div)
{
apupwr_clrbits(POSDIV_MASK << POSDIV_SHIFT, mixed_con1_addr[pll_idx]);
apupwr_setbits((post_div & POSDIV_MASK) << POSDIV_SHIFT,
mixed_con1_addr[pll_idx]);
}
/**
* _cal_pll_data() - input freq, calculate correspond post dividor and dds.
* @pd: address of output post dividor.
* @dds: address of output dds.
* @freq: input frequency.
*
* Given freq, this function will calculate correspond post dividor and dds.
*
* Context: Any context.
* Return:
* * 0 - done for calculating post dividor and dds.
*/
static int32_t _cal_pll_data(uint32_t *pd, uint32_t *dds, uint32_t freq)
{
uint32_t vco, postdiv_val = 1, postdiv_reg = 0;
uint32_t pcw_val;
vco = freq;
postdiv_val = 1;
postdiv_reg = 0;
while (vco <= FREQ_VCO_MIN) {
postdiv_val = postdiv_val << 1;
postdiv_reg = postdiv_reg + 1;
vco = vco << 1;
}
pcw_val = vco * (1 << PCW_FRACTIONAL_SHIFT);
pcw_val = pcw_val / FREQ_FIN;
if (postdiv_reg == 0) { /* Fvco * 2 with post_divider = 2 */
pcw_val = pcw_val * 2;
postdiv_val = postdiv_val << 1;
postdiv_reg = postdiv_reg + 1;
} /* Post divider is 1 is not available */
*pd = postdiv_reg;
*dds = pcw_val | RG_PLL_SDM_PCW_CHG;
return 0;
}
/**
* _pll_en() - enable/disable RG_PLL_EN of CON1 for pll[pll_idx]
* @pll_idx: Which PLL to enable/disable
* @on: 1 -> enable, 0 -> disable.
*
* This funciton will only change RG_PLL_EN of CON1 for pll[pll_idx].
*
* Context: Any context.
*/
static void _pll_en(uint32_t pll_idx, bool on)
{
if (on) {
apupwr_setbits(RG_PLL_EN, mixed_con0_addr[pll_idx]);
} else {
apupwr_clrbits(RG_PLL_EN, mixed_con0_addr[pll_idx]);
}
}
/**
* _pll_pwr() - enable/disable PLL_SDM_PWR_ON of CON3 for pll[pll_idx]
* @pll_idx: Which PLL to enable/disable
* @on: 1 -> enable, 0 -> disable.
*
* This funciton will only change PLL_SDM_PWR_ON of CON3 for pll[pll_idx].
*
* Context: Any context.
*/
static void _pll_pwr(uint32_t pll_idx, bool on)
{
if (on) {
apupwr_setbits(DA_PLL_SDM_PWR_ON, mixed_con3_addr[pll_idx]);
} else {
apupwr_clrbits(DA_PLL_SDM_PWR_ON, mixed_con3_addr[pll_idx]);
}
}
/**
* _pll_iso() - enable/disable PLL_SDM_ISO_EN of CON3 for pll[pll_idx]
* @pll_idx: Which PLL to enable/disable
* @enable: 1 -> turn on isolation, 0 -> turn off isolation.
*
* This funciton will turn on/off pll isolation by
* changing PLL_SDM_PWR_ON of CON3 for pll[pll_idx].
*
* Context: Any context.
*/
static void _pll_iso(uint32_t pll_idx, bool enable)
{
if (enable) {
apupwr_setbits(DA_PLL_SDM_ISO_EN, mixed_con3_addr[pll_idx]);
} else {
apupwr_clrbits(DA_PLL_SDM_ISO_EN, mixed_con3_addr[pll_idx]);
}
}
/**
* _pll_switch() - entry point to turn whole PLL on/off
* @pll_idx: Which PLL to enable/disable
* @on: 1 -> enable, 0 -> disable.
* @fhctl_en: enable or disable fhctl function
*
* This is the entry poing for controlling pll and fhctl funciton on/off.
* Caller can chose only enable pll instead of fhctl function.
*
* Context: Any context.
* Return:
* * 0 - done for enable pll or fhctl as well.
*/
static int32_t _pll_switch(uint32_t pll_idx, bool on, bool fhctl_en)
{
int32_t ret = 0;
if (pll_idx >= APUPLL_MAX) {
ERROR("%s wrong pll_idx: %d\n", __func__, pll_idx);
ret = -EINVAL;
goto err;
}
if (on) {
_pll_pwr(pll_idx, true);
udelay(PLL_CMD_READY_TIME_1US);
_pll_iso(pll_idx, false);
udelay(PLL_CMD_READY_TIME_1US);
_pll_en(pll_idx, true);
udelay(PLL_READY_TIME_20US);
} else {
_pll_en(pll_idx, false);
_pll_iso(pll_idx, true);
_pll_pwr(pll_idx, false);
}
err:
return ret;
}
/**
* apu_pll_enable() - API for smc function to enable/disable pll
* @pll_idx: Which pll to enable/disable.
* @enable: 1 -> enable, 0 -> disable.
* @fhctl_en: enable or disable fhctl function
*
* pll_idx[0] --> APUPLL (MDLA0/1)
* pll_idx[1] --> NPUPLL (VPU0/1)
* pll_idx[2] --> APUPLL1(CONN)
* pll_idx[3] --> APUPLL2(IOMMU)
* The differences between _pll_switch are:
* 1. Atomic update pll reference cnt to protect double enable pll &
* close pll during user is not zero.
*
* Context: Any context.
* Return:
* * 0 - done for enable pll or fhctl as well.
*/
int32_t apu_pll_enable(int32_t pll_idx, bool enable, bool fhctl_en)
{
int32_t ret = 0;
if (pll_idx >= APUPLL_MAX) {
ERROR("%s wrong pll_idx: %d\n", __func__, pll_idx);
ret = -EINVAL;
goto err;
}
if (enable) {
switch (pll_idx) {
case APUPLL:
spin_lock(&apupll_lock);
if (pll_cnt[APUPLL] == 0) {
_pll_switch(pll_idx, enable, fhctl_en);
}
pll_cnt[APUPLL]++;
spin_unlock(&apupll_lock);
break;
case NPUPLL:
spin_lock(&npupll_lock);
if (pll_cnt[NPUPLL] == 0) {
_pll_switch(pll_idx, enable, fhctl_en);
}
pll_cnt[NPUPLL]++;
spin_unlock(&npupll_lock);
break;
case APUPLL1:
spin_lock(&apupll_1_lock);
if (pll_cnt[APUPLL1] == 0) {
_pll_switch(pll_idx, enable, fhctl_en);
}
pll_cnt[APUPLL1]++;
spin_unlock(&apupll_1_lock);
break;
case APUPLL2:
spin_lock(&apupll_2_lock);
if (pll_cnt[APUPLL2] == 0) {
_pll_switch(pll_idx, enable, fhctl_en);
}
pll_cnt[APUPLL2]++;
spin_unlock(&apupll_2_lock);
break;
default:
ERROR("%s invalid pll_idx: %d\n", __func__, pll_idx);
ret = -EINVAL;
break;
}
} else {
switch (pll_idx) {
case APUPLL:
spin_lock(&apupll_lock);
if (pll_cnt[APUPLL]) {
pll_cnt[APUPLL]--;
}
if (pll_cnt[APUPLL] == 0) {
_pll_switch(pll_idx, enable, fhctl_en);
}
spin_unlock(&apupll_lock);
break;
case NPUPLL:
spin_lock(&npupll_lock);
if (pll_cnt[NPUPLL]) {
pll_cnt[NPUPLL]--;
}
if (pll_cnt[NPUPLL] == 0) {
_pll_switch(pll_idx, enable, fhctl_en);
}
spin_unlock(&npupll_lock);
break;
case APUPLL1:
spin_lock(&apupll_1_lock);
if (pll_cnt[APUPLL1]) {
pll_cnt[APUPLL1]--;
}
if (pll_cnt[APUPLL1] == 0) {
_pll_switch(pll_idx, enable, fhctl_en);
}
spin_unlock(&apupll_1_lock);
break;
case APUPLL2:
spin_lock(&apupll_2_lock);
if (pll_cnt[APUPLL2]) {
pll_cnt[APUPLL2]--;
}
if (pll_cnt[APUPLL2] == 0) {
_pll_switch(pll_idx, enable, fhctl_en);
}
spin_unlock(&apupll_2_lock);
break;
default:
ERROR("%s invalid pll_idx: %d\n", __func__, pll_idx);
ret = -EINVAL;
break;
}
}
err:
return ret;
}
/**
* anpu_pll_set_rate() - API for smc function to set rate of voltage domain.
* @domain: Which pll of correspond voltage domain to change rate.
* @mode: which mode to use when set_rate
* @freq: which frequency to set.
*
* For V_VPU0/1, it will only allow 1 of them to modify NPUPLL
* such that there will be no race condition happen.
*
* For V_MDLA0/1, it will only allow 1 of them to modify APUPLL1
* such that there will be no race condition happen.
*
* There are 3 kinds of modes to set pll's rate.
* 1. pure sw mode: (CON0_PCW)
* fhctl function is off and change rate by programming CON1_PCW.
* 2. fhctl sw mode: (FHCTL_SW)
* fhctl function is on and change rate by programming fhctl_dds.
* (post dividor is still need to program CON1_PCW)
* 3. fhctl hw mode: (FHCTL_HW)
* fhctl function is on and change rate by programming fhctl_dvfs.
* (post dividor is still need to program CON1_PCW)
*
* Context: Any context.
* Return:
* * 0 - done for set rate of voltage domain.
*/
int32_t anpu_pll_set_rate(enum dvfs_voltage_domain domain,
enum pll_set_rate_mode mode, int32_t freq)
{
uint32_t pd, old_pd, dds;
int32_t pll_idx, ret = 0;
pll_idx = vd2pllidx(domain);
if (pll_idx < 0) {
ret = pll_idx;
goto err;
}
_cal_pll_data(&pd, &dds, freq / 1000);
INFO("%s %s new post_div=%d, target dds=0x%08x(%dMhz) mode = %d\n",
__func__, pllidx2name(pll_idx), pd, dds, freq / 1000, mode);
/* spin_lock for NPULL, since vpu0/1 share npupll */
if (domain == V_VPU0 || domain == V_VPU1) {
spin_lock(&npupll_lock);
}
/* spin_lock for APUPLL, since mdla0/1 shate apupll */
if (domain == V_MDLA0 || domain == V_MDLA1) {
spin_lock(&apupll_lock);
}
switch (mode) {
case CON0_PCW:
pd = RG_PLL_SDM_PCW_CHG |
(pd & POSDIV_MASK) << POSDIV_SHIFT | dds;
apupwr_writel(pd, mixed_con1_addr[pll_idx]);
udelay(PLL_READY_TIME_20US);
break;
case FHCTL_SW:
/* pll con0 disable */
_pll_en(pll_idx, false);
apupwr_writel(dds, fhctl_dds_addr[pll_idx]);
_set_postdiv_reg(pll_idx, pd);
apupwr_setbits(PLL_TGL_ORG, fhctl_dds_addr[pll_idx]);
udelay(PLL_CMD_READY_TIME_1US);
/* pll con0 enable */
_pll_en(pll_idx, true);
udelay(PLL_READY_TIME_20US);
break;
case FHCTL_HW:
old_pd = _pll_get_postdiv_reg(pll_idx);
if (pd > old_pd) {
_set_postdiv_reg(pll_idx, pd);
apupwr_writel(dds, fhctl_dvfs_addr[pll_idx]);
} else {
apupwr_writel(dds, fhctl_dvfs_addr[pll_idx]);
_set_postdiv_reg(pll_idx, pd);
}
ret = _fhctl_mon_done(pll_idx, dds);
break;
default:
ERROR("%s input wrong mode: %d\n", __func__, mode);
ret = -EINVAL;
break;
}
/* spin_lock for NPULL, since vpu0/1 share npupll */
if (domain == V_VPU0 || domain == V_VPU1) {
spin_unlock(&npupll_lock);
}
/* spin_lock for APUPLL, since mdla0/1 share apupll */
if (domain == V_MDLA0 || domain == V_MDLA1) {
spin_unlock(&apupll_lock);
}
err:
return ret;
}

View File

@ -0,0 +1,341 @@
/*
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <errno.h>
#include <arch_helpers.h>
#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <apupwr_clkctl.h>
#include <apupwr_clkctl_def.h>
#include <mtk_plat_common.h>
#include <platform_def.h>
/* 8195 use PCW mode to change freq directly */
enum pll_set_rate_mode PLL_MODE = CON0_PCW;
char *buck_domain_str[APUSYS_BUCK_DOMAIN_NUM] = {
"V_VPU0",
"V_VPU1",
"V_MDLA0",
"V_MDLA1",
"V_APU_CONN",
"V_TOP_IOMMU",
"V_VCORE",
};
uint32_t aacc_set[APUSYS_BUCK_DOMAIN_NUM] = {
APU_ACC_CONFG_SET1, APU_ACC_CONFG_SET2,
APU_ACC_CONFG_SET4, APU_ACC_CONFG_SET5,
APU_ACC_CONFG_SET0, APU_ACC_CONFG_SET7
};
uint32_t aacc_clr[APUSYS_BUCK_DOMAIN_NUM] = {
APU_ACC_CONFG_CLR1, APU_ACC_CONFG_CLR2,
APU_ACC_CONFG_CLR4, APU_ACC_CONFG_CLR5,
APU_ACC_CONFG_CLR0, APU_ACC_CONFG_CLR7
};
struct reg_seq {
uint32_t address;
uint32_t val;
};
static const struct reg_seq init_acc_cfg[] = {
{ APU_ACC_CONFG_SET0, BIT(BIT_SEL_APU) },
{ APU_ACC_CONFG_CLR0, BIT(BIT_CGEN_SOC) },
{ APU_ACC_CONFG_SET0, BIT(BIT_SEL_APU_DIV2) },
{ APU_ACC_CONFG_SET7, BIT(BIT_SEL_APU) },
{ APU_ACC_CONFG_CLR7, BIT(BIT_CGEN_SOC) },
{ APU_ACC_CONFG_SET7, BIT(BIT_SEL_APU_DIV2) },
{ APU_ACC_CONFG_SET1, BIT(BIT_SEL_APU) },
{ APU_ACC_CONFG_CLR1, BIT(BIT_CGEN_SOC) },
{ APU_ACC_CONFG_SET1, BIT(BIT_SEL_APU_DIV2) },
{ APU_ACC_CONFG_SET2, BIT(BIT_INVEN_OUT) },
{ APU_ACC_CONFG_SET2, BIT(BIT_SEL_APU) },
{ APU_ACC_CONFG_CLR2, BIT(BIT_CGEN_SOC) },
{ APU_ACC_CONFG_SET2, BIT(BIT_SEL_APU_DIV2) },
{ APU_ACC_CONFG_SET4, BIT(BIT_SEL_APU) },
{ APU_ACC_CONFG_CLR4, BIT(BIT_CGEN_SOC) },
{ APU_ACC_CONFG_SET4, BIT(BIT_SEL_APU_DIV2) },
{ APU_ACC_CONFG_SET5, BIT(BIT_INVEN_OUT) },
{ APU_ACC_CONFG_SET5, BIT(BIT_SEL_APU) },
{ APU_ACC_CONFG_CLR5, BIT(BIT_CGEN_SOC) },
{ APU_ACC_CONFG_SET5, BIT(BIT_SEL_APU_DIV2) },
};
int32_t apupwr_smc_acc_init_all(void)
{
int32_t i;
for (i = 0; i < ARRAY_SIZE(init_acc_cfg); i++) {
apupwr_writel(init_acc_cfg[i].val,
init_acc_cfg[i].address);
}
/* Deault ACC will raise APU_DIV_2 */
apupwr_smc_pll_set_rate(BUCK_VCONN_DOMAIN_DEFAULT_FREQ,
true, V_APU_CONN);
apupwr_smc_pll_set_rate(BUCK_VCONN_DOMAIN_DEFAULT_FREQ,
true, V_TOP_IOMMU);
apupwr_smc_pll_set_rate(BUCK_VVPU_DOMAIN_DEFAULT_FREQ,
true, V_VPU0);
apupwr_smc_pll_set_rate(BUCK_VMDLA_DOMAIN_DEFAULT_FREQ,
true, V_MDLA0);
return 0;
}
void apupwr_smc_acc_top(bool enable)
{
if (enable) {
apupwr_writel(BIT(BIT_CGEN_APU), aacc_set[V_APU_CONN]);
apupwr_writel(BIT(BIT_CGEN_APU), aacc_set[V_TOP_IOMMU]);
} else {
apupwr_writel(BIT(BIT_CGEN_APU), aacc_clr[V_APU_CONN]);
apupwr_writel(BIT(BIT_CGEN_APU), aacc_clr[V_TOP_IOMMU]);
}
}
/*
* acc_clk_set_parent:ACC MUX select
* 0. freq parameters here, only ACC clksrc is valid
* 1. Switch between APUPLL <=> Parking (F26M, PARK)
* 2. Turn on/off CG_F26M, CG_PARK, CG_SOC, but no CG_APU
* 3. Clear APU Div2 while Parking
* 4. Only use clksrc of APUPLL while ACC CG_APU is on
*/
int32_t apupwr_smc_acc_set_parent(uint32_t freq, uint32_t domain)
{
uint32_t acc_set = 0;
uint32_t acc_clr = 0;
int32_t ret = 0;
if (freq > DVFS_FREQ_ACC_APUPLL) {
ERROR("%s wrong clksrc: %d\n", __func__, freq);
ret = -EIO;
goto err;
}
switch (domain) {
case V_VPU1:
case V_VPU0:
case V_MDLA1:
case V_MDLA0:
case V_APU_CONN:
case V_TOP_IOMMU:
acc_set = aacc_set[domain];
acc_clr = aacc_clr[domain];
break;
default:
ret = -EIO;
break;
}
/* Select park source */
switch (freq) {
case DVFS_FREQ_ACC_PARKING:
/* Select park source */
apupwr_writel(BIT(BIT_SEL_PARK), acc_set);
apupwr_writel(BIT(BIT_SEL_F26M), acc_clr);
/* Enable park cg */
apupwr_writel(BIT(BIT_CGEN_PARK), acc_set);
apupwr_writel(BIT(BIT_CGEN_F26M) | BIT(BIT_CGEN_SOC), acc_clr);
/* Select park path */
apupwr_writel(BIT(BIT_SEL_APU), acc_clr);
/* clear apu div 2 */
apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_clr);
break;
case DVFS_FREQ_ACC_APUPLL:
/* Select park path */
apupwr_writel(BIT(BIT_SEL_APU), acc_set);
/* Clear park cg */
apupwr_writel(BIT(BIT_CGEN_PARK) | BIT(BIT_CGEN_F26M) |
BIT(BIT_CGEN_SOC), acc_clr);
break;
case DVFS_FREQ_ACC_SOC:
/* Select park source */
apupwr_writel(BIT(BIT_SEL_PARK), acc_clr);
apupwr_writel(BIT(BIT_SEL_F26M), acc_clr);
/* Enable park cg */
apupwr_writel(BIT(BIT_CGEN_SOC), acc_set);
apupwr_writel(BIT(BIT_CGEN_F26M) | BIT(BIT_CGEN_PARK), acc_clr);
/* Select park path */
apupwr_writel(BIT(BIT_SEL_APU), acc_clr);
/* clear apu div 2 */
apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_clr);
break;
case DVFS_FREQ_ACC_26M:
case DVFS_FREQ_NOT_SUPPORT:
default:
/* Select park source */
apupwr_writel(BIT(BIT_SEL_F26M), acc_set);
apupwr_writel(BIT(BIT_SEL_PARK), acc_clr);
/* Enable park cg */
apupwr_writel(BIT(BIT_CGEN_F26M), acc_set);
apupwr_writel(BIT(BIT_CGEN_PARK) | BIT(BIT_CGEN_SOC), acc_clr);
/* Select park path */
apupwr_writel(BIT(BIT_SEL_APU), acc_clr);
/* clear apu div 2 */
apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_clr);
ERROR("[APUPWR] %s wrong ACC clksrc : %d, force assign 26M\n",
__func__, freq);
break;
}
err:
return ret;
}
int32_t apupwr_smc_pll_set_rate(uint32_t freq, bool div2, uint32_t domain)
{
int32_t ret = 0;
uint32_t acc_set0 = 0, acc_set1 = 0;
if (freq > DVFS_FREQ_MAX) {
ERROR("%s wrong freq: %d\n", __func__, freq);
ret = -EIO;
goto err;
}
/*
* Switch to Parking src
* 1. Need to switch out all ACCs sharing the same apupll
*/
switch (domain) {
case V_MDLA0:
case V_MDLA1:
acc_set0 = APU_ACC_CONFG_SET4;
acc_set1 = APU_ACC_CONFG_SET5;
ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING,
V_MDLA0);
ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING,
V_MDLA1);
break;
case V_VPU0:
case V_VPU1:
acc_set0 = APU_ACC_CONFG_SET1;
acc_set1 = APU_ACC_CONFG_SET2;
ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING,
V_VPU0);
ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING,
V_VPU1);
break;
case V_APU_CONN:
acc_set0 = APU_ACC_CONFG_SET0;
ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING,
V_APU_CONN);
break;
case V_TOP_IOMMU:
acc_set0 = APU_ACC_CONFG_SET7;
ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING,
V_TOP_IOMMU);
break;
default:
ERROR("[APUPWR] %s %d invalid domain (%d)\n",
__func__, __LINE__, domain);
ret = -EIO;
goto err;
}
anpu_pll_set_rate(domain, PLL_MODE, (div2) ? (freq * 2) : freq);
if (div2) {
apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_set0);
if (acc_set1) {
apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_set1);
}
}
/*
* Switch back to APUPLL
* Only switch back to APUPLL while CG_APU on
* And clksrc is not APUPLL
*/
switch (domain) {
case V_VPU0:
case V_VPU1:
if ((apupwr_readl(acc_set0) & BIT(BIT_CGEN_APU)) &&
!(apupwr_readl(acc_set0) & BIT(BIT_SEL_APU))) {
ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL,
V_VPU0);
}
if ((apupwr_readl(acc_set1) & BIT(BIT_CGEN_APU)) &&
!(apupwr_readl(acc_set1) & BIT(BIT_SEL_APU))) {
ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL,
V_VPU1);
}
break;
case V_MDLA0:
case V_MDLA1:
if ((apupwr_readl(acc_set0) & BIT(BIT_CGEN_APU)) &&
!(apupwr_readl(acc_set0) & BIT(BIT_SEL_APU))) {
ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL,
V_MDLA0);
}
if ((apupwr_readl(acc_set1) & BIT(BIT_CGEN_APU)) &&
!(apupwr_readl(acc_set1) & BIT(BIT_SEL_APU))) {
ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL,
V_MDLA1);
}
break;
case V_APU_CONN:
case V_TOP_IOMMU:
if ((apupwr_readl(acc_set0) & BIT(BIT_CGEN_APU)) &&
!(apupwr_readl(acc_set0) & BIT(BIT_SEL_APU))) {
ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL,
domain);
}
break;
default:
ERROR("[APUPWR] %s %d invalid domain (%d)\n",
__func__, __LINE__, domain);
ret = -EIO;
break;
}
INFO("[%s][%d] set domain %d to freq %d\n",
__func__, __LINE__, domain, (div2) ? (freq * 2) : freq);
err:
return ret;
}
int32_t apupwr_smc_bulk_pll(bool enable)
{
int32_t ret = 0;
int32_t pll_idx;
if (enable) {
for (pll_idx = APUPLL; pll_idx < APUPLL_MAX; pll_idx++) {
ret = apu_pll_enable(pll_idx, enable, false);
if (ret != 0) {
goto err;
}
}
} else {
for (pll_idx = APUPLL2; pll_idx >= APUPLL; pll_idx--) {
ret = apu_pll_enable(pll_idx, enable, false);
if (ret != 0) {
goto err;
}
}
}
err:
return ret;
}
void apupwr_smc_bus_prot_cg_on(void)
{
apupwr_clrbits(AO_MD32_MNOC_MASK, APU_CSR_DUMMY_0);
}

View File

@ -0,0 +1,23 @@
/*
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef APUPWR_CLKCTL_H
#define APUPWR_CLKCTL_H
#include <arch_helpers.h>
#include <apupwr_clkctl_def.h>
int32_t apupwr_smc_acc_init_all(void);
void apupwr_smc_acc_top(bool enable);
int32_t apupwr_smc_acc_set_parent(uint32_t freq, uint32_t domain);
int32_t apupwr_smc_pll_set_rate(uint32_t pll, bool div2, uint32_t domain);
int32_t apupwr_smc_bulk_pll(bool enable);
void apupwr_smc_bus_prot_cg_on(void);
int32_t apu_pll_enable(int32_t pll_idx, bool enable, bool fhctl_en);
int32_t anpu_pll_set_rate(enum dvfs_voltage_domain domain,
enum pll_set_rate_mode mode, int32_t freq);
#endif /* APUPWR_CLKCTL_H */

View File

@ -0,0 +1,195 @@
/*
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef APUPWR_CLKCTL_DEF_H
#define APUPWR_CLKCTL_DEF_H
#include <lib/mmio.h>
enum dvfs_voltage_domain {
V_VPU0 = 0,
V_VPU1 = 1,
V_MDLA0 = 2,
V_MDLA1 = 3,
V_APU_CONN = 4,
V_TOP_IOMMU = 5,
V_VCORE = 6,
APUSYS_BUCK_DOMAIN_NUM = 7,
};
enum dvfs_freq {
DVFS_FREQ_NOT_SUPPORT = 0,
DVFS_FREQ_ACC_26M = 1,
DVFS_FREQ_ACC_PARKING = 2,
DVFS_FREQ_ACC_SOC = 3,
DVFS_FREQ_ACC_APUPLL = 4,
DVFS_FREQ_00_026000_F = 26000,
DVFS_FREQ_00_208000_F = 208000,
DVFS_FREQ_00_238000_F = 238000,
DVFS_FREQ_00_273000_F = 273000,
DVFS_FREQ_00_312000_F = 312000,
DVFS_FREQ_00_358000_F = 358000,
DVFS_FREQ_00_385000_F = 385000,
DVFS_FREQ_00_499200_F = 499200,
DVFS_FREQ_00_500000_F = 500000,
DVFS_FREQ_00_525000_F = 525000,
DVFS_FREQ_00_546000_F = 546000,
DVFS_FREQ_00_594000_F = 594000,
DVFS_FREQ_00_624000_F = 624000,
DVFS_FREQ_00_688000_F = 688000,
DVFS_FREQ_00_687500_F = 687500,
DVFS_FREQ_00_728000_F = 728000,
DVFS_FREQ_00_800000_F = 800000,
DVFS_FREQ_00_832000_F = 832000,
DVFS_FREQ_00_960000_F = 960000,
DVFS_FREQ_00_1100000_F = 1100000,
};
#define DVFS_FREQ_MAX (DVFS_FREQ_00_1100000_F)
enum pll_set_rate_mode {
CON0_PCW = 0,
FHCTL_SW = 1,
FHCTL_HW = 2,
PLL_SET_RATE_MODE_MAX = 3,
};
enum apupll {
APUPLL = 0,
NPUPLL = 1,
APUPLL1 = 2,
APUPLL2 = 3,
APUPLL_MAX = 4,
};
#define BUCK_VVPU_DOMAIN_DEFAULT_FREQ (DVFS_FREQ_00_273000_F)
#define BUCK_VMDLA_DOMAIN_DEFAULT_FREQ (DVFS_FREQ_00_312000_F)
#define BUCK_VCONN_DOMAIN_DEFAULT_FREQ (DVFS_FREQ_00_208000_F)
#define apupwr_writel(VAL, REG) mmio_write_32((uintptr_t)REG, VAL)
#define apupwr_writel_relax(VAL, REG) mmio_write_32_relax((uintptr_t)REG, VAL)
#define apupwr_readl(REG) mmio_read_32((uintptr_t)REG)
#define apupwr_clrbits(VAL, REG) mmio_clrbits_32((uintptr_t)REG, VAL)
#define apupwr_setbits(VAL, REG) mmio_setbits_32((uintptr_t)REG, VAL)
#define apupwr_clrsetbits(CLR_VAL, SET_VAL, REG) \
mmio_clrsetbits_32((uintptr_t)REG, CLR_VAL, SET_VAL)
/* PLL and related register */
#define APU_PLL_BASE (APUSYS_APU_PLL_BASE)
#define APU_PLL4H_PLL1_CON0 (APU_PLL_BASE + 0x008)
#define APU_PLL4H_PLL1_CON1 (APU_PLL_BASE + 0x00C)
#define APU_PLL4H_PLL1_CON3 (APU_PLL_BASE + 0x014)
#define APU_PLL4H_PLL2_CON0 (APU_PLL_BASE + 0x018)
#define APU_PLL4H_PLL2_CON1 (APU_PLL_BASE + 0x01C)
#define APU_PLL4H_PLL2_CON3 (APU_PLL_BASE + 0x024)
#define APU_PLL4H_PLL3_CON0 (APU_PLL_BASE + 0x028)
#define APU_PLL4H_PLL3_CON1 (APU_PLL_BASE + 0x02C)
#define APU_PLL4H_PLL3_CON3 (APU_PLL_BASE + 0x034)
#define APU_PLL4H_PLL4_CON0 (APU_PLL_BASE + 0x038)
#define APU_PLL4H_PLL4_CON1 (APU_PLL_BASE + 0x03C)
#define APU_PLL4H_PLL4_CON3 (APU_PLL_BASE + 0x044)
#define APU_PLL4H_FHCTL_HP_EN (APU_PLL_BASE + 0x0E00)
#define APU_PLL4H_FHCTL_UNITSLOPE_EN (APU_PLL_BASE + 0x0E04)
#define APU_PLL4H_FHCTL_CLK_CON (APU_PLL_BASE + 0x0E08)
#define APU_PLL4H_FHCTL_RST_CON (APU_PLL_BASE + 0x0E0C)
#define APU_PLL4H_FHCTL_SLOPE0 (APU_PLL_BASE + 0x0E10)
#define APU_PLL4H_FHCTL_SLOPE1 (APU_PLL_BASE + 0x0E14)
#define APU_PLL4H_FHCTL_DSSC_CFG (APU_PLL_BASE + 0x0E18)
#define APU_PLL4H_FHCTL_DSSC0_CON (APU_PLL_BASE + 0x0E1C)
#define APU_PLL4H_FHCTL_DSSC1_CON (APU_PLL_BASE + 0x0E20)
#define APU_PLL4H_FHCTL_DSSC2_CON (APU_PLL_BASE + 0x0E24)
#define APU_PLL4H_FHCTL_DSSC3_CON (APU_PLL_BASE + 0x0E28)
#define APU_PLL4H_FHCTL_DSSC4_CON (APU_PLL_BASE + 0x0E2C)
#define APU_PLL4H_FHCTL_DSSC5_CON (APU_PLL_BASE + 0x0E30)
#define APU_PLL4H_FHCTL_DSSC6_CON (APU_PLL_BASE + 0x0E34)
#define APU_PLL4H_FHCTL_DSSC7_CON (APU_PLL_BASE + 0x0E38)
#define APU_PLL4H_FHCTL0_CFG (APU_PLL_BASE + 0x0E3C)
#define APU_PLL4H_FHCTL0_UPDNLMT (APU_PLL_BASE + 0x0E40)
#define APU_PLL4H_FHCTL0_DDS (APU_PLL_BASE + 0x0E44)
#define APU_PLL4H_FHCTL0_DVFS (APU_PLL_BASE + 0x0E48)
#define APU_PLL4H_FHCTL0_MON (APU_PLL_BASE + 0x0E4C)
#define APU_PLL4H_FHCTL1_CFG (APU_PLL_BASE + 0x0E50)
#define APU_PLL4H_FHCTL1_UPDNLMT (APU_PLL_BASE + 0x0E54)
#define APU_PLL4H_FHCTL1_DDS (APU_PLL_BASE + 0x0E58)
#define APU_PLL4H_FHCTL1_DVFS (APU_PLL_BASE + 0x0E5C)
#define APU_PLL4H_FHCTL1_MON (APU_PLL_BASE + 0x0E60)
#define APU_PLL4H_FHCTL2_CFG (APU_PLL_BASE + 0x0E64)
#define APU_PLL4H_FHCTL2_UPDNLMT (APU_PLL_BASE + 0x0E68)
#define APU_PLL4H_FHCTL2_DDS (APU_PLL_BASE + 0x0E6C)
#define APU_PLL4H_FHCTL2_DVFS (APU_PLL_BASE + 0x0E70)
#define APU_PLL4H_FHCTL2_MON (APU_PLL_BASE + 0x0E74)
#define APU_PLL4H_FHCTL3_CFG (APU_PLL_BASE + 0x0E78)
#define APU_PLL4H_FHCTL3_UPDNLMT (APU_PLL_BASE + 0x0E7C)
#define APU_PLL4H_FHCTL3_DDS (APU_PLL_BASE + 0x0E80)
#define APU_PLL4H_FHCTL3_DVFS (APU_PLL_BASE + 0x0E84)
#define APU_PLL4H_FHCTL3_MON (APU_PLL_BASE + 0x0E88)
/* PLL4H_PLLx_CON0 */
#define RG_PLL_EN BIT(0)
/* PLL4H_PLLx_CON1 */
#define RG_PLL_SDM_PCW_CHG BIT(31)
#define POSDIV_SHIFT (24U)
#define POSDIV_MASK (0x7)
/* PLL4H_PLLx_CON3 */
#define DA_PLL_SDM_PWR_ON BIT(0)
#define DA_PLL_SDM_ISO_EN BIT(1)
/* FHCTLx_DDS */
#define DDS_MASK GENMASK_32(21, 0)
#define PCW_FRACTIONAL_SHIFT 14U
#define PLL_TGL_ORG BIT(31)
#define PLL_READY_TIME_20US (20U)
#define PLL_CMD_READY_TIME_1US (1U)
#define FREQ_VCO_MIN (1500U) /* 1500MHz*/
#define FREQ_FIN (26U) /* 26M*/
/* ACC and related register */
#define APU_ACC_BASE (APUSYS_APU_ACC_BASE)
#define APU_ACC_CONFG_SET0 (APU_ACC_BASE + 0x000)
#define APU_ACC_CONFG_SET1 (APU_ACC_BASE + 0x004)
#define APU_ACC_CONFG_SET2 (APU_ACC_BASE + 0x008)
#define APU_ACC_CONFG_SET4 (APU_ACC_BASE + 0x010)
#define APU_ACC_CONFG_SET5 (APU_ACC_BASE + 0x014)
#define APU_ACC_CONFG_SET7 (APU_ACC_BASE + 0x01C)
#define APU_ACC_CONFG_CLR0 (APU_ACC_BASE + 0x040)
#define APU_ACC_CONFG_CLR1 (APU_ACC_BASE + 0x044)
#define APU_ACC_CONFG_CLR2 (APU_ACC_BASE + 0x048)
#define APU_ACC_CONFG_CLR4 (APU_ACC_BASE + 0x050)
#define APU_ACC_CONFG_CLR5 (APU_ACC_BASE + 0x054)
#define APU_ACC_CONFG_CLR7 (APU_ACC_BASE + 0x05C)
#define APU_ACC_FM_CONFG_SET (APU_ACC_BASE + 0x0C0)
#define APU_ACC_FM_CONFG_CLR (APU_ACC_BASE + 0x0C4)
#define APU_ACC_FM_SEL (APU_ACC_BASE + 0x0C8)
#define APU_ACC_FM_CNT (APU_ACC_BASE + 0x0CC)
/* APU AO control */
#define APU_AO_CTRL_BASE (APUSYS_APU_S_S_4_BASE)
#define APU_CSR_DUMMY_0 (APU_AO_CTRL_BASE + 0x24)
#define AO_MD32_MNOC_MASK (BIT(1) | BIT(0))
#define BIT_CGEN_F26M (0)
#define BIT_CGEN_PARK (1)
#define BIT_CGEN_SOC (2)
#define BIT_CGEN_APU (3)
#define BIT_CGEN_OUT (4)
#define BIT_SEL_PARK (8)
#define BIT_SEL_F26M (9)
#define BIT_SEL_APU_DIV2 (10)
#define BIT_SEL_APU (11)
#define BIT_SEL_PARK_SRC_OUT (12)
#define BIT_INVEN_OUT (15)
#endif /* APUPWR_CLKCTL_DEF_H*/

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common/debug.h>
#include <drivers/console.h>
#include <lib/mmio.h>
#include <apupwr_clkctl.h>
#include <mtk_apusys.h>
#include <plat/common/platform.h>
int32_t apusys_kernel_ctrl(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4,
uint32_t *ret1)
{
int32_t ret = 0L;
uint32_t request_ops;
request_ops = (uint32_t)x1;
switch (request_ops) {
case MTK_SIP_APU_START_MCU:
/* setup addr[33:32] in reviser */
mmio_write_32(REVISER_SECUREFW_CTXT, 0U);
mmio_write_32(REVISER_USDRFW_CTXT, 0U);
/* setup secure sideband */
mmio_write_32(AO_SEC_FW,
(SEC_FW_NON_SECURE << SEC_FW_SHIFT_NS) |
(0U << SEC_FW_DOMAIN_SHIFT));
/* setup boot address */
mmio_write_32(AO_MD32_BOOT_CTRL, 0U);
/* setup pre-define region */
mmio_write_32(AO_MD32_PRE_DEFINE,
(PRE_DEFINE_CACHE_TCM << PRE_DEFINE_SHIFT_0G) |
(PRE_DEFINE_CACHE << PRE_DEFINE_SHIFT_1G) |
(PRE_DEFINE_CACHE << PRE_DEFINE_SHIFT_2G) |
(PRE_DEFINE_CACHE << PRE_DEFINE_SHIFT_3G));
/* release runstall */
mmio_write_32(AO_MD32_SYS_CTRL, SYS_CTRL_RUN);
INFO("[APUSYS] rev(0x%08x,0x%08x)\n",
mmio_read_32(REVISER_SECUREFW_CTXT),
mmio_read_32(REVISER_USDRFW_CTXT));
INFO("[APUSYS] ao(0x%08x,0x%08x,0x%08x,0x%08x,0x%08x)\n",
mmio_read_32(AO_SEC_FW),
mmio_read_32(AO_SEC_USR_FW),
mmio_read_32(AO_MD32_BOOT_CTRL),
mmio_read_32(AO_MD32_PRE_DEFINE),
mmio_read_32(AO_MD32_SYS_CTRL));
break;
case MTK_SIP_APU_STOP_MCU:
/* hold runstall */
mmio_write_32(AO_MD32_SYS_CTRL, SYS_CTRL_STALL);
INFO("[APUSYS] md32_boot_ctrl=0x%08x,runstall=0x%08x\n",
mmio_read_32(AO_MD32_BOOT_CTRL),
mmio_read_32(AO_MD32_SYS_CTRL));
break;
case MTK_SIP_APUPWR_BUS_PROT_CG_ON:
apupwr_smc_bus_prot_cg_on();
break;
case MTK_SIP_APUPWR_BULK_PLL:
ret = apupwr_smc_bulk_pll((bool)x2);
break;
case MTK_SIP_APUPWR_ACC_INIT_ALL:
ret = apupwr_smc_acc_init_all();
break;
case MTK_SIP_APUPWR_ACC_TOP:
apupwr_smc_acc_top((bool)x2);
break;
default:
ERROR("%s, unknown request_ops=0x%x\n", __func__, request_ops);
break;
}
return ret;
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2021, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MTK_APUSYS_H
#define MTK_APUSYS_H
#include <stdint.h>
/* setup the SMC command ops */
#define MTK_SIP_APU_START_MCU (0x00U)
#define MTK_SIP_APU_STOP_MCU (0x01U)
#define MTK_SIP_APUPWR_BUS_PROT_CG_ON (0x02U)
#define MTK_SIP_APUPWR_BULK_PLL (0x03U)
#define MTK_SIP_APUPWR_ACC_INIT_ALL (0x04U)
#define MTK_SIP_APUPWR_ACC_TOP (0x05U)
/* AO Register */
#define AO_MD32_PRE_DEFINE (APUSYS_APU_S_S_4_BASE + 0x00)
#define AO_MD32_BOOT_CTRL (APUSYS_APU_S_S_4_BASE + 0x04)
#define AO_MD32_SYS_CTRL (APUSYS_APU_S_S_4_BASE + 0x08)
#define AO_SEC_FW (APUSYS_APU_S_S_4_BASE + 0x10)
#define AO_SEC_USR_FW (APUSYS_APU_S_S_4_BASE + 0x14)
#define PRE_DEFINE_CACHE_TCM (0x3U)
#define PRE_DEFINE_CACHE (0x2U)
#define PRE_DEFINE_SHIFT_0G (0U)
#define PRE_DEFINE_SHIFT_1G (2U)
#define PRE_DEFINE_SHIFT_2G (4U)
#define PRE_DEFINE_SHIFT_3G (6U)
#define SEC_FW_NON_SECURE (1U)
#define SEC_FW_SHIFT_NS (4U)
#define SEC_FW_DOMAIN_SHIFT (0U)
#define SEC_USR_FW_NON_SECURE (1U)
#define SEC_USR_FW_SHIFT_NS (4U)
#define SEC_USR_FW_DOMAIN_SHIFT (0U)
#define SYS_CTRL_RUN (0U)
#define SYS_CTRL_STALL (1U)
/* Reviser Register */
#define REVISER_SECUREFW_CTXT (APUSYS_SCTRL_REVISER_BASE + 0x100)
#define REVISER_USDRFW_CTXT (APUSYS_SCTRL_REVISER_BASE + 0x104)
int32_t apusys_kernel_ctrl(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4,
uint32_t *ret1);
#endif /* MTK_APUSYS_H */

View File

@ -10,7 +10,7 @@
/*******************************************************************************
* Plat SiP function constants
******************************************************************************/
#define MTK_PLAT_SIP_NUM_CALLS 4
#define MTK_PLAT_SIP_NUM_CALLS 6
/* DFD */
#define MTK_SIP_KERNEL_DFD_AARCH32 0x82000205
@ -20,4 +20,8 @@
#define MTK_SIP_DP_CONTROL_AARCH32 0x82000523
#define MTK_SIP_DP_CONTROL_AARCH64 0xC2000523
/* APUSYS SMC call */
#define MTK_SIP_APUSYS_CONTROL_AARCH32 0x8200051E
#define MTK_SIP_APUSYS_CONTROL_AARCH64 0xC200051E
#endif /* PLAT_SIP_CALLS_H */

View File

@ -21,6 +21,16 @@
#define MTK_MCDI_SRAM_BASE 0x11B000
#define MTK_MCDI_SRAM_MAP_SIZE 0x1000
#define APUSYS_BASE 0x19000000
#define APUSYS_SCTRL_REVISER_BASE 0x19021000
#define APUSYS_SCTRL_REVISER_SIZE 0x1000
#define APUSYS_APU_S_S_4_BASE 0x190F2000
#define APUSYS_APU_S_S_4_SIZE 0x1000
#define APUSYS_APU_PLL_BASE 0x190F3000
#define APUSYS_APU_PLL_SIZE 0x1000
#define APUSYS_APU_ACC_BASE 0x190F4000
#define APUSYS_APU_ACC_SIZE 0x1000
#define TOPCKGEN_BASE (IO_PHYS + 0x00000000)
#define INFRACFG_AO_BASE (IO_PHYS + 0x00001000)
#define SPM_BASE (IO_PHYS + 0x00006000)

View File

@ -9,6 +9,7 @@
#include <mt_dp.h>
#include <mt_spm.h>
#include <mt_spm_vcorefs.h>
#include <mtk_apusys.h>
#include <mtk_sip_svc.h>
#include <plat_dfd.h>
#include "plat_sip_calls.h"
@ -41,6 +42,11 @@ uintptr_t mediatek_plat_sip_handler(uint32_t smc_fid,
ret = dfd_smc_dispatcher(x1, x2, x3, x4);
SMC_RET1(handle, ret);
break;
case MTK_SIP_APUSYS_CONTROL_AARCH32:
case MTK_SIP_APUSYS_CONTROL_AARCH64:
ret = apusys_kernel_ctrl(x1, x2, x3, x4, &ret_val);
SMC_RET2(handle, ret, ret_val);
break;
default:
ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
break;

View File

@ -14,6 +14,7 @@ PLAT_INCLUDES := -I${MTK_PLAT}/common/ \
-I${MTK_PLAT}/common/drivers/timer/ \
-I${MTK_PLAT}/common/drivers/uart/ \
-I${MTK_PLAT}/common/lpm/ \
-I${MTK_PLAT_SOC}/drivers/apusys/ \
-I${MTK_PLAT_SOC}/drivers/dcm \
-I${MTK_PLAT_SOC}/drivers/dfd \
-I${MTK_PLAT_SOC}/drivers/dp/ \
@ -59,6 +60,9 @@ BL31_SOURCES += common/desc_image_load.c \
${MTK_PLAT_SOC}/aarch64/platform_common.c \
${MTK_PLAT_SOC}/aarch64/plat_helpers.S \
${MTK_PLAT_SOC}/bl31_plat_setup.c \
${MTK_PLAT_SOC}/drivers/apusys/apupll.c \
${MTK_PLAT_SOC}/drivers/apusys/apupwr_clkctl.c \
${MTK_PLAT_SOC}/drivers/apusys/mtk_apusys.c \
${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm.c \
${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm_utils.c \
${MTK_PLAT_SOC}/drivers/dfd/plat_dfd.c \