From d194081ba60a2541062b9cc6d131a0eddd3335d1 Mon Sep 17 00:00:00 2001 From: Hsin-Hsiung Wang Date: Wed, 30 Dec 2020 12:15:54 +0800 Subject: [PATCH] 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 Change-Id: Ideb862c3cb0f1fee183804aed74fcf141bf1f5df Reviewed-on: https://review.coreboot.org/c/coreboot/+/49006 Tested-by: build bot (Jenkins) Reviewed-by: Yu-Ping Wu --- src/soc/mediatek/mt8192/include/soc/mt6359p.h | 21 +++++ src/soc/mediatek/mt8192/mt6359p.c | 91 +++++++++++++++++++ 2 files changed, 112 insertions(+) diff --git a/src/soc/mediatek/mt8192/include/soc/mt6359p.h b/src/soc/mediatek/mt8192/include/soc/mt6359p.h index b90e0f55ed..5519cc2383 100644 --- a/src/soc/mediatek/mt8192/include/soc/mt6359p.h +++ b/src/soc/mediatek/mt8192/include/soc/mt6359p.h @@ -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); diff --git a/src/soc/mediatek/mt8192/mt6359p.c b/src/soc/mediatek/mt8192/mt6359p.c index c93b66a426..e9dadc0d74 100644 --- a/src/soc/mediatek/mt8192/mt6359p.c +++ b/src/soc/mediatek/mt8192/mt6359p.c @@ -5,6 +5,7 @@ #include #include #include +#include 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(); }