mt_cpu_pm.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /*
  2. * Copyright (c) 2021, MediaTek Inc. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <assert.h>
  7. #include <stdint.h>
  8. #include <arch_helpers.h>
  9. #include <lib/psci/psci.h>
  10. #include <lib/spinlock.h>
  11. #include <mt_cpu_pm_cpc.h>
  12. #include <mt_lp_irqremain.h>
  13. #include <mt_lp_rm.h>
  14. #include <mt_mcdi.h>
  15. #include <plat_mtk_lpm.h>
  16. #include <plat_pm.h>
  17. DEFINE_SYSREG_RW_FUNCS(dbgprcr_el1);
  18. static int plat_mt_lp_cpu_rc;
  19. static int pwr_state_prompt(unsigned int cpu, const psci_power_state_t *state)
  20. {
  21. return 0;
  22. }
  23. static int pwr_state_reflect(unsigned int cpu, const psci_power_state_t *state)
  24. {
  25. mtk_cpc_core_on_hint_clr(cpu);
  26. if (IS_SYSTEM_SUSPEND_STATE(state)) {
  27. mtk_cpc_time_sync();
  28. }
  29. return 0;
  30. }
  31. static int pwr_cpu_pwron(unsigned int cpu, const psci_power_state_t *state)
  32. {
  33. return 0;
  34. }
  35. static int pwr_cpu_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
  36. {
  37. /* clear DBGPRCR.CORENPDRQ to allow CPU power down */
  38. write_dbgprcr_el1(0ULL);
  39. return 0;
  40. }
  41. static int pwr_cluster_pwron(unsigned int cpu, const psci_power_state_t *state)
  42. {
  43. return 0;
  44. }
  45. static int pwr_cluster_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
  46. {
  47. return 0;
  48. }
  49. static int pwr_mcusys_pwron(unsigned int cpu, const psci_power_state_t *state)
  50. {
  51. if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) {
  52. return -1;
  53. }
  54. mtk_cpc_mcusys_off_reflect();
  55. return 0;
  56. }
  57. static int pwr_mcusys_pwron_finished(unsigned int cpu,
  58. const psci_power_state_t *state)
  59. {
  60. int state_id = state->pwr_domain_state[MTK_AFFLVL_MCUSYS];
  61. if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) {
  62. return -1;
  63. }
  64. mt_lp_rm_reset_constraint(plat_mt_lp_cpu_rc, cpu, state_id);
  65. mt_lp_irqremain_release();
  66. return 0;
  67. }
  68. static int pwr_mcusys_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
  69. {
  70. int state_id = state->pwr_domain_state[MTK_AFFLVL_MCUSYS];
  71. if (!IS_MCUSYS_OFF_STATE(state)) {
  72. goto mt_pwr_mcusysoff_break;
  73. }
  74. if (mcdi_try_init() != 0) { /* not ready to process mcusys-off */
  75. goto mt_pwr_mcusysoff_break;
  76. }
  77. if (mtk_cpc_mcusys_off_prepare() != CPC_SUCCESS) {
  78. goto mt_pwr_mcusysoff_break;
  79. }
  80. plat_mt_lp_cpu_rc =
  81. mt_lp_rm_find_and_run_constraint(0, cpu, state_id, NULL);
  82. if (plat_mt_lp_cpu_rc < 0) {
  83. goto mt_pwr_mcusysoff_reflect;
  84. }
  85. mt_lp_irqremain_aquire();
  86. return 0;
  87. mt_pwr_mcusysoff_reflect:
  88. mtk_cpc_mcusys_off_reflect();
  89. mt_pwr_mcusysoff_break:
  90. plat_mt_lp_cpu_rc = -1;
  91. return -1;
  92. }
  93. static const struct mt_lpm_tz plat_pm = {
  94. .pwr_prompt = pwr_state_prompt,
  95. .pwr_reflect = pwr_state_reflect,
  96. .pwr_cpu_on = pwr_cpu_pwron,
  97. .pwr_cpu_dwn = pwr_cpu_pwrdwn,
  98. .pwr_cluster_on = pwr_cluster_pwron,
  99. .pwr_cluster_dwn = pwr_cluster_pwrdwn,
  100. .pwr_mcusys_dwn = pwr_mcusys_pwrdwn,
  101. .pwr_mcusys_on = pwr_mcusys_pwron,
  102. .pwr_mcusys_on_finished = pwr_mcusys_pwron_finished
  103. };
  104. const struct mt_lpm_tz *mt_plat_cpu_pm_init(void)
  105. {
  106. mtk_cpc_init();
  107. if (mcdi_try_init() == 0) {
  108. INFO("MCDI init done.\n");
  109. }
  110. mt_lp_irqremain_init();
  111. return &plat_pm;
  112. }