17ac6a76cSjason-ch chen /*
27ac6a76cSjason-ch chen * Copyright (c) 2022, MediaTek Inc. All rights reserved.
37ac6a76cSjason-ch chen *
47ac6a76cSjason-ch chen * SPDX-License-Identifier: BSD-3-Clause
57ac6a76cSjason-ch chen */
67ac6a76cSjason-ch chen
77ac6a76cSjason-ch chen #include <string.h>
87ac6a76cSjason-ch chen #include <common/debug.h>
97ac6a76cSjason-ch chen #include <lib/mmio.h>
107ac6a76cSjason-ch chen #include <mt_spm.h>
117ac6a76cSjason-ch chen #include <mt_spm_internal.h>
127ac6a76cSjason-ch chen #include <mt_spm_pmic_wrap.h>
137ac6a76cSjason-ch chen #include <mt_spm_reg.h>
147ac6a76cSjason-ch chen #include <plat_pm.h>
157ac6a76cSjason-ch chen #include <platform_def.h>
167ac6a76cSjason-ch chen #include <pmic.h>
177ac6a76cSjason-ch chen
187ac6a76cSjason-ch chen /* PMIC_WRAP MT6359 */
197ac6a76cSjason-ch chen #define NR_PMIC_WRAP_CMD (NR_IDX_ALL)
207ac6a76cSjason-ch chen #define SPM_DATA_SHIFT (16U)
217ac6a76cSjason-ch chen
227ac6a76cSjason-ch chen struct pmic_wrap_cmd {
237ac6a76cSjason-ch chen unsigned long cmd_addr;
247ac6a76cSjason-ch chen unsigned long cmd_wdata;
257ac6a76cSjason-ch chen };
267ac6a76cSjason-ch chen
277ac6a76cSjason-ch chen struct pmic_wrap_setting {
287ac6a76cSjason-ch chen enum pmic_wrap_phase_id phase;
297ac6a76cSjason-ch chen struct pmic_wrap_cmd addr[NR_PMIC_WRAP_CMD];
307ac6a76cSjason-ch chen struct {
317ac6a76cSjason-ch chen struct {
327ac6a76cSjason-ch chen unsigned long cmd_addr;
337ac6a76cSjason-ch chen unsigned long cmd_wdata;
347ac6a76cSjason-ch chen } _[NR_PMIC_WRAP_CMD];
357ac6a76cSjason-ch chen const int nr_idx;
367ac6a76cSjason-ch chen } set[NR_PMIC_WRAP_PHASE];
377ac6a76cSjason-ch chen };
387ac6a76cSjason-ch chen
397ac6a76cSjason-ch chen struct set_vsram {
407ac6a76cSjason-ch chen unsigned long cmd_addr;
417ac6a76cSjason-ch chen unsigned long cmd_wdata;
427ac6a76cSjason-ch chen };
437ac6a76cSjason-ch chen
447ac6a76cSjason-ch chen /* MT6366 */
457ac6a76cSjason-ch chen #define VOLT_TO_PMIC_VAL_66(volt) (((volt) - 50000 + 625 - 1) / 625)
467ac6a76cSjason-ch chen #define BUCK_VCORE_ELR0_66 (0x14AA)
477ac6a76cSjason-ch chen #define TOP_SPI_CON0_66 (0x44C)
487ac6a76cSjason-ch chen
497ac6a76cSjason-ch chen static struct pmic_wrap_setting pw66 = {
507ac6a76cSjason-ch chen .phase = NR_PMIC_WRAP_PHASE, /* invalid setting for init */
517ac6a76cSjason-ch chen .addr = { {0UL, 0UL} },
527ac6a76cSjason-ch chen .set[PMIC_WRAP_PHASE_ALLINONE] = {
537ac6a76cSjason-ch chen ._[CMD_0] = { BUCK_VCORE_ELR0_66, VOLT_TO_PMIC_VAL_66(80000), },
54*600f1681SAllen-KH Cheng ._[CMD_1] = { BUCK_VCORE_ELR0_66, VOLT_TO_PMIC_VAL_66(80000), },
55*600f1681SAllen-KH Cheng ._[CMD_2] = { BUCK_VCORE_ELR0_66, VOLT_TO_PMIC_VAL_66(80000), },
56*600f1681SAllen-KH Cheng ._[CMD_3] = { BUCK_VCORE_ELR0_66, VOLT_TO_PMIC_VAL_66(80000), },
57*600f1681SAllen-KH Cheng ._[CMD_4] = { BUCK_VCORE_ELR0_66, VOLT_TO_PMIC_VAL_66(80000), },
587ac6a76cSjason-ch chen ._[CMD_5] = { TOP_SPI_CON0_66, 0x1, },
597ac6a76cSjason-ch chen ._[CMD_6] = { TOP_SPI_CON0_66, 0x0, },
607ac6a76cSjason-ch chen .nr_idx = NR_IDX_ALL,
617ac6a76cSjason-ch chen },
627ac6a76cSjason-ch chen };
637ac6a76cSjason-ch chen
647ac6a76cSjason-ch chen /* MT6357 */
657ac6a76cSjason-ch chen #define VOLT_TO_PMIC_VAL_57(volt) (((volt) - 51875 + 625 - 1) / 625)
667ac6a76cSjason-ch chen #define BUCK_VCORE_ELR0_57 (0x152A)
677ac6a76cSjason-ch chen #define TOP_SPI_CON0_57 (0x448)
687ac6a76cSjason-ch chen
697ac6a76cSjason-ch chen static struct pmic_wrap_setting pw57 = {
707ac6a76cSjason-ch chen .phase = NR_PMIC_WRAP_PHASE, /* invalid setting for init */
717ac6a76cSjason-ch chen .addr = { {0UL, 0UL} },
727ac6a76cSjason-ch chen .set[PMIC_WRAP_PHASE_ALLINONE] = {
737ac6a76cSjason-ch chen ._[CMD_0] = { BUCK_VCORE_ELR0_57, VOLT_TO_PMIC_VAL_57(80000), },
747ac6a76cSjason-ch chen ._[CMD_1] = { BUCK_VCORE_ELR0_57, VOLT_TO_PMIC_VAL_57(75000), },
757ac6a76cSjason-ch chen ._[CMD_2] = { BUCK_VCORE_ELR0_57, VOLT_TO_PMIC_VAL_57(70000), },
767ac6a76cSjason-ch chen ._[CMD_3] = { BUCK_VCORE_ELR0_57, VOLT_TO_PMIC_VAL_57(65000), },
777ac6a76cSjason-ch chen ._[CMD_4] = { BUCK_VCORE_ELR0_57, VOLT_TO_PMIC_VAL_57(62500), },
787ac6a76cSjason-ch chen ._[CMD_5] = { TOP_SPI_CON0_57, 0x1, },
797ac6a76cSjason-ch chen ._[CMD_6] = { TOP_SPI_CON0_57, 0x0, },
807ac6a76cSjason-ch chen .nr_idx = NR_IDX_ALL,
817ac6a76cSjason-ch chen },
827ac6a76cSjason-ch chen };
837ac6a76cSjason-ch chen
847ac6a76cSjason-ch chen static struct pmic_wrap_setting *pw;
857ac6a76cSjason-ch chen
867ac6a76cSjason-ch chen #define IS_PMIC_57() ((pmic_get_hwcid() >> 8) == 0x57)
877ac6a76cSjason-ch chen
_mt_spm_pmic_table_init(void)887ac6a76cSjason-ch chen void _mt_spm_pmic_table_init(void)
897ac6a76cSjason-ch chen {
907ac6a76cSjason-ch chen struct pmic_wrap_cmd pwrap_cmd_default[NR_PMIC_WRAP_CMD] = {
917ac6a76cSjason-ch chen { (uint32_t)SPM_DVFS_CMD0, (uint32_t)SPM_DVFS_CMD0, },
927ac6a76cSjason-ch chen { (uint32_t)SPM_DVFS_CMD1, (uint32_t)SPM_DVFS_CMD1, },
937ac6a76cSjason-ch chen { (uint32_t)SPM_DVFS_CMD2, (uint32_t)SPM_DVFS_CMD2, },
947ac6a76cSjason-ch chen { (uint32_t)SPM_DVFS_CMD3, (uint32_t)SPM_DVFS_CMD3, },
957ac6a76cSjason-ch chen { (uint32_t)SPM_DVFS_CMD4, (uint32_t)SPM_DVFS_CMD4, },
967ac6a76cSjason-ch chen { (uint32_t)SPM_DVFS_CMD5, (uint32_t)SPM_DVFS_CMD5, },
977ac6a76cSjason-ch chen { (uint32_t)SPM_DVFS_CMD6, (uint32_t)SPM_DVFS_CMD6, },
987ac6a76cSjason-ch chen { (uint32_t)SPM_DVFS_CMD7, (uint32_t)SPM_DVFS_CMD7, },
997ac6a76cSjason-ch chen { (uint32_t)SPM_DVFS_CMD8, (uint32_t)SPM_DVFS_CMD8, },
1007ac6a76cSjason-ch chen };
1017ac6a76cSjason-ch chen
1027ac6a76cSjason-ch chen if (IS_PMIC_57()) {
1037ac6a76cSjason-ch chen pw = &pw57;
1047ac6a76cSjason-ch chen } else {
1057ac6a76cSjason-ch chen pw = &pw66;
1067ac6a76cSjason-ch chen }
1077ac6a76cSjason-ch chen
1087ac6a76cSjason-ch chen memcpy(pw->addr, pwrap_cmd_default, sizeof(pwrap_cmd_default));
1097ac6a76cSjason-ch chen }
1107ac6a76cSjason-ch chen
mt_spm_pmic_wrap_set_phase(enum pmic_wrap_phase_id phase)1117ac6a76cSjason-ch chen void mt_spm_pmic_wrap_set_phase(enum pmic_wrap_phase_id phase)
1127ac6a76cSjason-ch chen {
1137ac6a76cSjason-ch chen uint32_t idx, addr, data;
1147ac6a76cSjason-ch chen
1157ac6a76cSjason-ch chen if (phase < NR_PMIC_WRAP_PHASE) {
1167ac6a76cSjason-ch chen if (pw == NULL || pw->addr[0].cmd_addr == 0) {
1177ac6a76cSjason-ch chen _mt_spm_pmic_table_init();
1187ac6a76cSjason-ch chen }
1197ac6a76cSjason-ch chen
1207ac6a76cSjason-ch chen if (pw->phase != phase) {
1217ac6a76cSjason-ch chen pw->phase = phase;
1227ac6a76cSjason-ch chen
1237ac6a76cSjason-ch chen mmio_write_32(POWERON_CONFIG_EN, SPM_REGWR_CFG_KEY | BCLK_CG_EN_LSB);
1247ac6a76cSjason-ch chen
1257ac6a76cSjason-ch chen for (idx = 0; idx < pw->set[phase].nr_idx; idx++) {
1267ac6a76cSjason-ch chen addr = pw->set[phase]._[idx].cmd_addr << SPM_DATA_SHIFT;
1277ac6a76cSjason-ch chen data = pw->set[phase]._[idx].cmd_wdata;
1287ac6a76cSjason-ch chen mmio_write_32(pw->addr[idx].cmd_addr, addr | data);
1297ac6a76cSjason-ch chen }
1307ac6a76cSjason-ch chen }
1317ac6a76cSjason-ch chen }
1327ac6a76cSjason-ch chen }
1337ac6a76cSjason-ch chen
mt_spm_pmic_wrap_set_cmd(enum pmic_wrap_phase_id phase,uint32_t idx,uint32_t cmd_wdata)1347ac6a76cSjason-ch chen void mt_spm_pmic_wrap_set_cmd(enum pmic_wrap_phase_id phase, uint32_t idx,
1357ac6a76cSjason-ch chen uint32_t cmd_wdata)
1367ac6a76cSjason-ch chen {
1377ac6a76cSjason-ch chen uint32_t addr;
1387ac6a76cSjason-ch chen
1397ac6a76cSjason-ch chen if (phase >= NR_PMIC_WRAP_PHASE) {
1407ac6a76cSjason-ch chen return;
1417ac6a76cSjason-ch chen }
1427ac6a76cSjason-ch chen
1437ac6a76cSjason-ch chen if (pw == NULL || idx >= pw->set[phase].nr_idx) {
1447ac6a76cSjason-ch chen return;
1457ac6a76cSjason-ch chen }
1467ac6a76cSjason-ch chen
1477ac6a76cSjason-ch chen pw->set[phase]._[idx].cmd_wdata = cmd_wdata;
1487ac6a76cSjason-ch chen
1497ac6a76cSjason-ch chen mmio_write_32(POWERON_CONFIG_EN, SPM_REGWR_CFG_KEY | BCLK_CG_EN_LSB);
1507ac6a76cSjason-ch chen if (pw->phase == phase) {
1517ac6a76cSjason-ch chen addr = pw->set[phase]._[idx].cmd_addr << SPM_DATA_SHIFT;
1527ac6a76cSjason-ch chen mmio_write_32(pw->addr[idx].cmd_addr, addr | cmd_wdata);
1537ac6a76cSjason-ch chen }
1547ac6a76cSjason-ch chen }
1557ac6a76cSjason-ch chen
mt_spm_pmic_wrap_get_cmd(enum pmic_wrap_phase_id phase,uint32_t idx)1567ac6a76cSjason-ch chen uint64_t mt_spm_pmic_wrap_get_cmd(enum pmic_wrap_phase_id phase, uint32_t idx)
1577ac6a76cSjason-ch chen {
1587ac6a76cSjason-ch chen uint64_t ret = 0UL;
1597ac6a76cSjason-ch chen
1607ac6a76cSjason-ch chen if ((phase < NR_PMIC_WRAP_PHASE) &&
1617ac6a76cSjason-ch chen (pw != NULL && idx < pw->set[phase].nr_idx)) {
1627ac6a76cSjason-ch chen ret = pw->set[phase]._[idx].cmd_wdata;
1637ac6a76cSjason-ch chen }
1647ac6a76cSjason-ch chen
1657ac6a76cSjason-ch chen return ret;
1667ac6a76cSjason-ch chen }
167