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(); }