aboutsummaryrefslogtreecommitdiff
path: root/src/soc
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc')
-rw-r--r--src/soc/mediatek/mt8192/include/soc/mt6359p.h21
-rw-r--r--src/soc/mediatek/mt8192/mt6359p.c91
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();
}