/* SPDX-License-Identifier: GPL-2.0-only */ #include #include #include #include #include #include #define MT6363_SET_DELAY_US 200 static const struct pmic_setting key_protect_setting[] = { {0x39E, 0x9C, 0xFF}, {0x39F, 0x9C, 0xFF}, {0xFAB, 0x63, 0xFF}, {0xFAC, 0x63, 0xFF}, {0x142A, 0x43, 0xFF}, {0x142B, 0x55, 0xFF}, {0x3A7, 0x9C, 0xFF}, {0x3A8, 0x9C, 0xFF}, {0xA33, 0x29, 0xFF}, {0xA34, 0x47, 0xFF}, {0xC42, 0x06, 0xFF}, {0xC43, 0x17, 0xFF}, }; static struct pmif *pmif_arb; u16 mt6363_read16(u32 reg) { u16 rdata = 0; assert(pmif_arb); pmif_arb->read16(pmif_arb, SPMI_SLAVE_4, reg, &rdata); return rdata; } u8 mt6363_read8(u32 reg) { u32 rdata = 0; assert(pmif_arb); pmif_arb->read(pmif_arb, SPMI_SLAVE_4, reg, &rdata); return (u8)rdata; } void mt6363_write8(u32 reg, u8 data) { assert(pmif_arb); pmif_arb->write(pmif_arb, SPMI_SLAVE_4, reg, data); } static u32 mt6363_read_field(u32 reg, u32 mask, u32 shift) { assert(pmif_arb); return pmif_arb->read_field(pmif_arb, SPMI_SLAVE_4, reg, mask, shift); } void mt6363_write_field(u32 reg, u32 val, u32 mask, u32 shift) { assert(pmif_arb); pmif_arb->write_field(pmif_arb, SPMI_SLAVE_4, reg, val, mask, shift); } static void pmic_set_power_hold(void) { printk(BIOS_INFO, "[%s]before POWER_HOLD = 0x%x\n", __func__, mt6363_read_field(PMIC_PWRHOLD, 0x1, 0)); mt6363_write_field(PMIC_PWRHOLD, 0x1, 0x1, 0); printk(BIOS_INFO, "[%s]POWER_HOLD = 0x%x\n", __func__, mt6363_read_field(PMIC_PWRHOLD, 0x1, 0)); } static void pmic_wdt_set(void) { /* [5]=1, RG_WDTRSTB_DEB */ mt6363_write_field(PMIC_TOP_RST_MISC1_SET, 0x20, 0xFFFF, 0); /* [1]=0, RG_WDTRSTB_MODE */ mt6363_write_field(PMIC_TOP_RST_MISC1_CLR, 0x02, 0xFFFF, 0); /* [0]=1, RG_WDTRSTB_EN */ mt6363_write_field(PMIC_TOP_RST_MISC1_SET, 0x01, 0xFFFF, 0); /* Enable BUCK/LDO WDT VOSEL Debug */ mt6363_write_field(PMIC_TOP_VRCTL_DBG_CON0, 0x1, 0x1, 0); /* Clear WDT status */ mt6363_write_field(PMIC_TOP_RST_MISC1_SET, 0x1, 0x1, 3); udelay(50); mt6363_write_field(PMIC_TOP_RST_MISC1_CLR, 0x1, 0x1, 3); printk(BIOS_INFO, "[%s]WDTRSTB[0x%x]=0x%x\n", __func__, PMIC_TOP_RST_MISC1, mt6363_read_field(PMIC_TOP_RST_MISC1, 0xFF, 0)); } static void pmic_protect_key_setting(bool lock) { const struct pmic_setting *entry; for (int i = 0; i < ARRAY_SIZE(key_protect_setting); i++) { entry = &key_protect_setting[i]; mt6363_write8(entry->addr, lock ? 0 : entry->val); } printk(BIOS_INFO, "%s done\n", __func__); } void mt6363_buck_set_voltage(u32 buck_id, u32 buck_uv) { u32 vol_offset, vol_reg, vol, vol_step; switch (buck_id) { case MT6363_VBUCK2: vol_offset = 0; vol_reg = PMIC_VRCTL_VOSEL_VBUCK2; vol_step = 6250; break; default: printk(BIOS_WARNING, "[%s] Unknown buck_id %u", __func__, buck_id); return; }; vol = (buck_uv - vol_offset) / vol_step; mt6363_write_field(vol_reg, vol, 0xFF, 0); udelay(MT6363_SET_DELAY_US); printk(BIOS_INFO, "%s: %d, %d\n", __func__, buck_id, vol); } u32 mt6363_buck_get_voltage(u32 buck_id) { u32 vol_shift, vol_offset, vol_reg, vol, vol_step; switch (buck_id) { case MT6363_VBUCK2: vol_shift = 0; vol_offset = 0; vol_reg = PMIC_VBUCK2_DBG0; vol_step = 6250; break; case MT6363_VBUCK4: vol_shift = 0; vol_offset = 0; vol_reg = PMIC_VBUCK4_DBG0; vol_step = 6250; break; default: printk(BIOS_WARNING, "[%s] Unknown buck_id %u", __func__, buck_id); return 0; }; vol = mt6363_read_field(vol_reg, 0xFF, vol_shift); printk(BIOS_INFO, "%s: %d, %d\n", __func__, buck_id, vol); return vol_offset + vol * vol_step; } void mt6363_set_vm18_voltage(u32 vm18_uv) { u8 reg_vol; assert(pmif_arb); assert(vm18_uv >= 1700000); assert(vm18_uv < 2000000); reg_vol = ((vm18_uv - 1700000) / 50000) + 12; mt6363_write8(PMIC_VM18_ANA_CON1, reg_vol); mt6363_write8(PMIC_VM18_ANA_CON0, 0x0); udelay(MT6363_SET_DELAY_US); printk(BIOS_INFO, "%s: 0x%x, %d\n", __func__, reg_vol, vm18_uv); } u32 mt6363_get_vm18_voltage(void) { u32 reg_vol, reg_cali, voltage; assert(pmif_arb); reg_cali = mt6363_read_field(PMIC_VM18_ANA_CON0, 0xF, 0); reg_vol = mt6363_read_field(PMIC_VM18_ANA_CON1, 0xF, 0); voltage = (reg_vol - 12) * 50000 + reg_cali * 5000 + 1700000; printk(BIOS_INFO, "%s: reg_vol 0x%x, reg_cali 0x%x, %d\n", __func__, reg_vol, reg_cali, voltage); return voltage; } void mt6363_set_vtref18_voltage(u32 vtref18_uv) { u8 reg_vol, reg_cali; assert(pmif_arb); assert(vtref18_uv >= 1800000); assert(vtref18_uv <= 3400000); reg_cali = ((vtref18_uv - 1800000) % 100000) / 10000; reg_vol = (vtref18_uv - 1800000) / 100000; mt6363_write8(PMIC_VTREF18_ANA_CON0, reg_cali); mt6363_write8(PMIC_VTREF18_ANA_CON1, reg_vol); udelay(MT6363_SET_DELAY_US); printk(BIOS_INFO, "%s: reg_vol 0x%x, reg_cali 0x%x, %d\n", __func__, reg_vol, reg_cali, vtref18_uv); } u32 mt6363_get_vtref18_voltage(void) { u32 reg_vol, reg_cali, vtref18_uv; assert(pmif_arb); reg_cali = mt6363_read_field(PMIC_VTREF18_ANA_CON0, 0xF, 0); reg_vol = mt6363_read_field(PMIC_VTREF18_ANA_CON1, 0xF, 0); vtref18_uv = reg_cali * 10000 + reg_vol * 100000 + 1800000; printk(BIOS_INFO, "%s: reg_vol 0x%x, reg_cali 0x%x, %d\n", __func__, reg_vol, reg_cali, vtref18_uv); return vtref18_uv; } void mt6363_enable_vtref18(bool enable) { mt6363_write_field(PMIC_LDO_VTREF18_CON0, enable, 0x1, 0); } void mt6363_enable_buck5(bool enable) { mt6363_write_field(PMIC_VBUCK5_OP_EN_2, enable, 0x1, 7); } void mt6363_enable_vcn15(bool enable) { mt6363_write_field(PMIC_LDO_VCN15_CON0, enable, 0x1, 0); } void mt6363_enable_vrf09(bool enable) { mt6363_write_field(PMIC_LDO_VRF09_CON0, enable, 0x1, 0); } void mt6363_enable_vrf12(bool enable) { mt6363_write_field(PMIC_LDO_VRF12_CON0, enable, 0x1, 0); } void mt6363_enable_vrf13(bool enable) { mt6363_write_field(PMIC_LDO_VRF13_CON0, enable, 0x1, 0); } void mt6363_enable_vrf18(bool enable) { mt6363_write_field(PMIC_LDO_VRF18_CON0, enable, 0x1, 0); } void mt6363_enable_vram_digrf(bool enable) { mt6363_write_field(PMIC_LDO_VSRAM_DIGRF_CON0, enable, 0x1, 0); } void mt6363_enable_vram_mdfe(bool enable) { mt6363_write_field(PMIC_LDO_VSRAM_MDFE_CON0, enable, 0x1, 0); } void mt6363_init_pmif_arb(void) { if (pmif_arb) return; pmif_arb = get_pmif_controller(PMIF_SPMI, SPMI_MASTER_1); assert(pmif_arb); if (pmif_arb->check_init_done(pmif_arb)) die("ERROR - Failed to initialize pmif spi"); printk(BIOS_INFO, "[%s][MT6363]CHIP ID = 0x%x\n", __func__, mt6363_read_field(PMIC_SWCID1, 0xFF, 0)); } void mt6363_init(void) { mt6363_init_pmif_arb(); pmic_set_power_hold(); pmic_wdt_set(); pmic_protect_key_setting(false); mt6363_init_setting(); pmic_protect_key_setting(true); }