diff options
author | Hsin-Hsiung Wang <hsin-hsiung.wang@mediatek.com> | 2020-12-30 12:15:54 +0800 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2021-01-22 14:26:08 +0000 |
commit | d194081ba60a2541062b9cc6d131a0eddd3335d1 (patch) | |
tree | f625ebfe1e1252f82adbaa376d8f024d898f84cc /src/soc/mediatek | |
parent | d6375cf556fb7a4612a441c4d32f93fa57556f3a (diff) |
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>
Diffstat (limited to 'src/soc/mediatek')
-rw-r--r-- | src/soc/mediatek/mt8192/include/soc/mt6359p.h | 21 | ||||
-rw-r--r-- | src/soc/mediatek/mt8192/mt6359p.c | 91 |
2 files changed, 112 insertions, 0 deletions
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 <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(); } |