mt_spm_pmic_wrap.c 4.4 KB

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