1 /* 2 * Copyright (c) 2022, MediaTek Inc. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <string.h> 8 #include <common/debug.h> 9 #include <lib/mmio.h> 10 #include <mt_spm.h> 11 #include <mt_spm_internal.h> 12 #include <mt_spm_pmic_wrap.h> 13 #include <mt_spm_reg.h> 14 #include <plat_pm.h> 15 #include <platform_def.h> 16 #include <pmic.h> 17 18 /* PMIC_WRAP MT6359 */ 19 #define NR_PMIC_WRAP_CMD (NR_IDX_ALL) 20 #define SPM_DATA_SHIFT (16U) 21 22 struct pmic_wrap_cmd { 23 unsigned long cmd_addr; 24 unsigned long cmd_wdata; 25 }; 26 27 struct pmic_wrap_setting { 28 enum pmic_wrap_phase_id phase; 29 struct pmic_wrap_cmd addr[NR_PMIC_WRAP_CMD]; 30 struct { 31 struct { 32 unsigned long cmd_addr; 33 unsigned long cmd_wdata; 34 } _[NR_PMIC_WRAP_CMD]; 35 const int nr_idx; 36 } set[NR_PMIC_WRAP_PHASE]; 37 }; 38 39 struct set_vsram { 40 unsigned long cmd_addr; 41 unsigned long cmd_wdata; 42 }; 43 44 /* MT6366 */ 45 #define VOLT_TO_PMIC_VAL_66(volt) (((volt) - 50000 + 625 - 1) / 625) 46 #define BUCK_VCORE_ELR0_66 (0x14AA) 47 #define TOP_SPI_CON0_66 (0x44C) 48 49 static struct pmic_wrap_setting pw66 = { 50 .phase = NR_PMIC_WRAP_PHASE, /* invalid setting for init */ 51 .addr = { {0UL, 0UL} }, 52 .set[PMIC_WRAP_PHASE_ALLINONE] = { 53 ._[CMD_0] = { BUCK_VCORE_ELR0_66, VOLT_TO_PMIC_VAL_66(80000), }, 54 ._[CMD_1] = { BUCK_VCORE_ELR0_66, VOLT_TO_PMIC_VAL_66(80000), }, 55 ._[CMD_2] = { BUCK_VCORE_ELR0_66, VOLT_TO_PMIC_VAL_66(80000), }, 56 ._[CMD_3] = { BUCK_VCORE_ELR0_66, VOLT_TO_PMIC_VAL_66(80000), }, 57 ._[CMD_4] = { BUCK_VCORE_ELR0_66, VOLT_TO_PMIC_VAL_66(80000), }, 58 ._[CMD_5] = { TOP_SPI_CON0_66, 0x1, }, 59 ._[CMD_6] = { TOP_SPI_CON0_66, 0x0, }, 60 .nr_idx = NR_IDX_ALL, 61 }, 62 }; 63 64 /* MT6357 */ 65 #define VOLT_TO_PMIC_VAL_57(volt) (((volt) - 51875 + 625 - 1) / 625) 66 #define BUCK_VCORE_ELR0_57 (0x152A) 67 #define TOP_SPI_CON0_57 (0x448) 68 69 static struct pmic_wrap_setting pw57 = { 70 .phase = NR_PMIC_WRAP_PHASE, /* invalid setting for init */ 71 .addr = { {0UL, 0UL} }, 72 .set[PMIC_WRAP_PHASE_ALLINONE] = { 73 ._[CMD_0] = { BUCK_VCORE_ELR0_57, VOLT_TO_PMIC_VAL_57(80000), }, 74 ._[CMD_1] = { BUCK_VCORE_ELR0_57, VOLT_TO_PMIC_VAL_57(75000), }, 75 ._[CMD_2] = { BUCK_VCORE_ELR0_57, VOLT_TO_PMIC_VAL_57(70000), }, 76 ._[CMD_3] = { BUCK_VCORE_ELR0_57, VOLT_TO_PMIC_VAL_57(65000), }, 77 ._[CMD_4] = { BUCK_VCORE_ELR0_57, VOLT_TO_PMIC_VAL_57(62500), }, 78 ._[CMD_5] = { TOP_SPI_CON0_57, 0x1, }, 79 ._[CMD_6] = { TOP_SPI_CON0_57, 0x0, }, 80 .nr_idx = NR_IDX_ALL, 81 }, 82 }; 83 84 static struct pmic_wrap_setting *pw; 85 86 #define IS_PMIC_57() ((pmic_get_hwcid() >> 8) == 0x57) 87 88 void _mt_spm_pmic_table_init(void) 89 { 90 struct pmic_wrap_cmd pwrap_cmd_default[NR_PMIC_WRAP_CMD] = { 91 { (uint32_t)SPM_DVFS_CMD0, (uint32_t)SPM_DVFS_CMD0, }, 92 { (uint32_t)SPM_DVFS_CMD1, (uint32_t)SPM_DVFS_CMD1, }, 93 { (uint32_t)SPM_DVFS_CMD2, (uint32_t)SPM_DVFS_CMD2, }, 94 { (uint32_t)SPM_DVFS_CMD3, (uint32_t)SPM_DVFS_CMD3, }, 95 { (uint32_t)SPM_DVFS_CMD4, (uint32_t)SPM_DVFS_CMD4, }, 96 { (uint32_t)SPM_DVFS_CMD5, (uint32_t)SPM_DVFS_CMD5, }, 97 { (uint32_t)SPM_DVFS_CMD6, (uint32_t)SPM_DVFS_CMD6, }, 98 { (uint32_t)SPM_DVFS_CMD7, (uint32_t)SPM_DVFS_CMD7, }, 99 { (uint32_t)SPM_DVFS_CMD8, (uint32_t)SPM_DVFS_CMD8, }, 100 }; 101 102 if (IS_PMIC_57()) { 103 pw = &pw57; 104 } else { 105 pw = &pw66; 106 } 107 108 memcpy(pw->addr, pwrap_cmd_default, sizeof(pwrap_cmd_default)); 109 } 110 111 void mt_spm_pmic_wrap_set_phase(enum pmic_wrap_phase_id phase) 112 { 113 uint32_t idx, addr, data; 114 115 if (phase < NR_PMIC_WRAP_PHASE) { 116 if (pw == NULL || pw->addr[0].cmd_addr == 0) { 117 _mt_spm_pmic_table_init(); 118 } 119 120 if (pw->phase != phase) { 121 pw->phase = phase; 122 123 mmio_write_32(POWERON_CONFIG_EN, SPM_REGWR_CFG_KEY | BCLK_CG_EN_LSB); 124 125 for (idx = 0; idx < pw->set[phase].nr_idx; idx++) { 126 addr = pw->set[phase]._[idx].cmd_addr << SPM_DATA_SHIFT; 127 data = pw->set[phase]._[idx].cmd_wdata; 128 mmio_write_32(pw->addr[idx].cmd_addr, addr | data); 129 } 130 } 131 } 132 } 133 134 void mt_spm_pmic_wrap_set_cmd(enum pmic_wrap_phase_id phase, uint32_t idx, 135 uint32_t cmd_wdata) 136 { 137 uint32_t addr; 138 139 if (phase >= NR_PMIC_WRAP_PHASE) { 140 return; 141 } 142 143 if (pw == NULL || idx >= pw->set[phase].nr_idx) { 144 return; 145 } 146 147 pw->set[phase]._[idx].cmd_wdata = cmd_wdata; 148 149 mmio_write_32(POWERON_CONFIG_EN, SPM_REGWR_CFG_KEY | BCLK_CG_EN_LSB); 150 if (pw->phase == phase) { 151 addr = pw->set[phase]._[idx].cmd_addr << SPM_DATA_SHIFT; 152 mmio_write_32(pw->addr[idx].cmd_addr, addr | cmd_wdata); 153 } 154 } 155 156 uint64_t mt_spm_pmic_wrap_get_cmd(enum pmic_wrap_phase_id phase, uint32_t idx) 157 { 158 uint64_t ret = 0UL; 159 160 if ((phase < NR_PMIC_WRAP_PHASE) && 161 (pw != NULL && idx < pw->set[phase].nr_idx)) { 162 ret = pw->set[phase]._[idx].cmd_wdata; 163 } 164 165 return ret; 166 } 167