soc/mediatek/mt8192: pmic: Set efuses manually

Some efuse settings would not be applied automatically, so we need
set the settings manually. The low power consumption would not be
optimal without correct efuse settings.

BUG=b:172636735
BRANCH=none
TEST=see 'pmic_efuse_setting: Set efuses in 11 msecs'

Signed-off-by: Hsin-Hsiung Wang <hsin-hsiung.wang@mediatek.com>
Change-Id: Ideb862c3cb0f1fee183804aed74fcf141bf1f5df
Reviewed-on: https://review.coreboot.org/c/coreboot/+/49006
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Yu-Ping Wu <yupingso@google.com>
This commit is contained in:
Hsin-Hsiung Wang 2020-12-30 12:15:54 +08:00 committed by Patrick Georgi
parent d6375cf556
commit d194081ba6
2 changed files with 112 additions and 0 deletions

View File

@ -8,14 +8,23 @@
enum {
PMIC_HWCID = 0x0008,
PMIC_SWCID = 0x000a,
PMIC_TOP_CKPDN_CON0 = 0x010c,
PMIC_TOP_CKHWEN_CON0 = 0x012a,
PMIC_TOP_RST_MISC_SET = 0x014c,
PMIC_TOP_RST_MISC_CLR = 0x014e,
PMIC_OTP_CON0 = 0x038a,
PMIC_OTP_CON8 = 0x039a,
PMIC_OTP_CON11 = 0x03a0,
PMIC_OTP_CON12 = 0x03a2,
PMIC_OTP_CON13 = 0x03a4,
PMIC_PWRHOLD = 0x0a08,
PMIC_VGPU11_DBG0 = 0x15a6,
PMIC_VGPU11_ELR0 = 0x15b4,
PMIC_VS2_VOTER = 0x18aa,
PMIC_VS2_VOTER_CFG = 0x18b0,
PMIC_VS2_ELR0 = 0x18b4,
PMIC_BUCK_VPA_DLC_CON0 = 0x1918,
PMIC_BUCK_VPA_DLC_CON1 = 0x191a,
PMIC_VSRAM_PROC1_ELR = 0x1b44,
PMIC_VSRAM_PROC2_ELR = 0x1b46,
PMIC_VSRAM_PROC1_VOSEL1 = 0x1e90,
@ -30,6 +39,13 @@ struct pmic_setting {
unsigned char shift;
};
struct pmic_efuse {
unsigned short efuse_bit;
unsigned short addr;
unsigned short mask;
unsigned char shift;
};
enum {
MT6359P_GPU11 = 0,
MT6359P_SRAM_PROC1,
@ -40,6 +56,11 @@ enum {
#define VM18_VOL_REG_SHIFT 8
#define VM18_VOL_OFFSET 600
#define EFUSE_WAIT_US 5000
#define EFUSE_BUSY 1
#define EFUSE_RG_VPA_OC_FT 78
void mt6359p_init(void);
void mt6359p_romstage_init(void);
void mt6359p_buck_set_voltage(u32 buck_id, u32 buck_uv);

View File

@ -5,6 +5,7 @@
#include <delay.h>
#include <soc/pmif.h>
#include <soc/mt6359p.h>
#include <timer.h>
static const struct pmic_setting key_protect_setting[] = {
{0x3A8, 0x9CA6, 0xFFFF, 0},
@ -298,6 +299,32 @@ static const struct pmic_setting lp_setting[] = {
{0x1d14, 0x1, 0x1, 0x2},
};
static const struct pmic_efuse efuse_setting[] = {
{79, 0xa0e, 0x1, 0xf},
{886, 0x198c, 0xf, 0x8},
{890, 0x198e, 0xf, 0x0},
{902, 0x1998, 0xf, 0x8},
{906, 0x1998, 0xf, 0xc},
{918, 0x19a2, 0xf, 0x8},
{922, 0x19a2, 0xf, 0xc},
{1014, 0x19ae, 0xf, 0x7},
{1018, 0x19ae, 0xf, 0xb},
{1158, 0x1a0a, 0xf, 0x7},
{1162, 0x1a0a, 0xf, 0xb},
{1206, 0x1a16, 0xf, 0x7},
{1210, 0x1a16, 0xf, 0xb},
{1254, 0x1a22, 0xf, 0x7},
{1258, 0x1a22, 0xf, 0xb},
{1304, 0x1a2c, 0x7, 0x4},
{1307, 0x1a32, 0x7, 0x8},
{1336, 0x1a34, 0x7, 0x4},
{1339, 0x1a3a, 0x7, 0x8},
{1683, 0x79c, 0xf, 0x4},
{1688, 0xc8a, 0x1, 0x3},
{1689, 0xc88, 0x1, 0x3},
{1690, 0xc88, 0x7, 0x0},
};
static struct pmif *pmif_arb = NULL;
static void mt6359p_write(u32 reg, u32 data)
{
@ -336,6 +363,45 @@ static void pmic_protect_key_setting(bool lock)
lock ? 0 : key_protect_setting[i].val);
}
static int check_idle(u32 timeout, u32 addr, u32 mask)
{
if (!wait_us(timeout, !mt6359p_read_field(addr, mask, 0)))
return -1;
return 0;
}
static u32 pmic_read_efuse(u32 efuse_bit, u32 mask)
{
u32 efuse_data;
int index, shift;
index = efuse_bit / 16;
shift = efuse_bit % 16;
mt6359p_write_field(PMIC_TOP_CKHWEN_CON0, 0, 0x1, 2);
mt6359p_write_field(PMIC_TOP_CKPDN_CON0, 0, 0x1, 4);
mt6359p_write_field(PMIC_OTP_CON11, 1, 0x1, 0);
mt6359p_write_field(PMIC_OTP_CON0, index * 2, 0xFF, 0);
if (mt6359p_read_field(PMIC_OTP_CON8, 1, 0))
mt6359p_write_field(PMIC_OTP_CON8, 0, 1, 0);
else
mt6359p_write_field(PMIC_OTP_CON8, 1, 1, 0);
udelay(300);
if (check_idle(EFUSE_WAIT_US, PMIC_OTP_CON13, EFUSE_BUSY))
die("[%s] timeout after %d usecs\n", __func__, EFUSE_WAIT_US);
udelay(100);
efuse_data = mt6359p_read_field(PMIC_OTP_CON12, 0xFFFF, 0);
efuse_data = (efuse_data >> shift) & mask;
mt6359p_write_field(PMIC_TOP_CKHWEN_CON0, 1, 0x1, 2);
mt6359p_write_field(PMIC_TOP_CKPDN_CON0, 1, 0x1, 4);
return efuse_data;
}
static void pmic_init_setting(void)
{
for (int i = 0; i < ARRAY_SIZE(init_setting); i++)
@ -350,6 +416,30 @@ static void pmic_lp_setting(void)
lp_setting[i].mask, lp_setting[i].shift);
}
static void pmic_efuse_setting(void)
{
u32 efuse_data;
struct stopwatch sw;
stopwatch_init(&sw);
for (int i = 0; i < ARRAY_SIZE(efuse_setting); i++) {
efuse_data = pmic_read_efuse(efuse_setting[i].efuse_bit, efuse_setting[i].mask);
mt6359p_write_field(efuse_setting[i].addr, efuse_data,
efuse_setting[i].mask, efuse_setting[i].shift);
}
efuse_data = pmic_read_efuse(EFUSE_RG_VPA_OC_FT, 0x1);
if (efuse_data) {
/* restore VPA_DLC initial setting */
mt6359p_write(PMIC_BUCK_VPA_DLC_CON0, 0x2810);
mt6359p_write(PMIC_BUCK_VPA_DLC_CON1, 0x800);
}
printk(BIOS_DEBUG, "%s: Set efuses in %ld msecs\n",
__func__, stopwatch_duration_msecs(&sw));
}
static void pmic_wk_vs2_voter_setting(void)
{
/*
@ -470,6 +560,7 @@ void mt6359p_init(void)
pmic_protect_key_setting(false);
pmic_init_setting();
pmic_lp_setting();
pmic_efuse_setting();
pmic_protect_key_setting(true);
pmic_wk_vs2_voter_setting();
}