mt_spm_conservation.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /*
  2. * Copyright (c) 2023, MediaTek Inc. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <assert.h>
  7. #include <stddef.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <common/debug.h>
  11. #include <lib/mmio.h>
  12. #include <plat/common/platform.h>
  13. #include <lib/pm/mtk_pm.h>
  14. #include <lpm/mt_lp_rqm.h>
  15. #include "mt_spm.h"
  16. #include "mt_spm_conservation.h"
  17. #include "mt_spm_reg.h"
  18. #include <platform_def.h>
  19. #define INFRA_EMI_DCM_CFG0 U(0x10002028)
  20. static struct wake_status spm_wakesta; /* record last wakesta */
  21. static wake_reason_t spm_wake_reason = WR_NONE;
  22. static unsigned int emi_bak;
  23. static int go_to_spm_before_wfi(int state_id, unsigned int ext_opand,
  24. struct spm_lp_scen *spm_lp,
  25. unsigned int resource_req)
  26. {
  27. int ret = 0;
  28. struct pwr_ctrl *pwrctrl;
  29. unsigned int cpu = plat_my_core_pos();
  30. pwrctrl = spm_lp->pwrctrl;
  31. /* EMI workaround */
  32. emi_bak = mmio_read_32(INFRA_EMI_DCM_CFG0) & BIT(22);
  33. mmio_setbits_32(INFRA_EMI_DCM_CFG0, BIT(22));
  34. __spm_set_cpu_status(cpu);
  35. __spm_set_power_control(pwrctrl);
  36. __spm_set_wakeup_event(pwrctrl);
  37. __spm_set_pcm_flags(pwrctrl);
  38. __spm_src_req_update(pwrctrl, resource_req);
  39. if ((ext_opand & MT_SPM_EX_OP_CLR_26M_RECORD) != 0U) {
  40. __spm_clean_before_wfi();
  41. }
  42. if ((ext_opand & MT_SPM_EX_OP_SET_WDT) != 0U) {
  43. __spm_set_pcm_wdt(1);
  44. }
  45. if ((ext_opand & MT_SPM_EX_OP_HW_S1_DETECT) != 0U) {
  46. spm_hw_s1_state_monitor_resume();
  47. }
  48. __spm_send_cpu_wakeup_event();
  49. INFO("cpu%d: wakesrc = 0x%x, settle = 0x%x, sec = %u\n",
  50. cpu, pwrctrl->wake_src, mmio_read_32(SPM_CLK_SETTLE),
  51. (mmio_read_32(PCM_TIMER_VAL) / 32768));
  52. INFO("sw_flag = 0x%x 0x%x, req = 0x%x, pwr = 0x%x 0x%x\n",
  53. pwrctrl->pcm_flags, pwrctrl->pcm_flags1,
  54. mmio_read_32(SPM_SRC_REQ), mmio_read_32(PWR_STATUS),
  55. mmio_read_32(PWR_STATUS_2ND));
  56. return ret;
  57. }
  58. static void go_to_spm_after_wfi(int state_id, unsigned int ext_opand,
  59. struct spm_lp_scen *spm_lp,
  60. struct wake_status **status)
  61. {
  62. unsigned int ext_status = 0U;
  63. if ((ext_opand & MT_SPM_EX_OP_SET_WDT) != 0U) {
  64. __spm_set_pcm_wdt(0);
  65. }
  66. if ((ext_opand & MT_SPM_EX_OP_HW_S1_DETECT) != 0U) {
  67. spm_hw_s1_state_monitor_pause(&ext_status);
  68. }
  69. __spm_ext_int_wakeup_req_clr();
  70. __spm_get_wakeup_status(&spm_wakesta, ext_status);
  71. if (status != NULL) {
  72. *status = &spm_wakesta;
  73. }
  74. __spm_clean_after_wakeup();
  75. spm_wake_reason = __spm_output_wake_reason(&spm_wakesta);
  76. /* EMI workaround */
  77. if (emi_bak == 0U) {
  78. mmio_clrbits_32(INFRA_EMI_DCM_CFG0, BIT(22));
  79. }
  80. }
  81. int spm_conservation(int state_id, unsigned int ext_opand,
  82. struct spm_lp_scen *spm_lp,
  83. unsigned int resource_req)
  84. {
  85. unsigned int rc_state = resource_req;
  86. if (spm_lp == NULL) {
  87. return -1;
  88. }
  89. spin_lock(&spm_lock);
  90. go_to_spm_before_wfi(state_id, ext_opand, spm_lp, rc_state);
  91. spin_unlock(&spm_lock);
  92. return 0;
  93. }
  94. void spm_conservation_finish(int state_id, unsigned int ext_opand, struct spm_lp_scen *spm_lp,
  95. struct wake_status **status)
  96. {
  97. spin_lock(&spm_lock);
  98. go_to_spm_after_wfi(state_id, ext_opand, spm_lp, status);
  99. spin_unlock(&spm_lock);
  100. }
  101. int spm_conservation_get_result(struct wake_status **res)
  102. {
  103. if (res == NULL) {
  104. return -1;
  105. }
  106. *res = &spm_wakesta;
  107. return 0;
  108. }