mt_spm_rc_dram.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. /*
  2. * Copyright (c) 2023, MediaTek Inc. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <common/debug.h>
  7. #include <drivers/spm/mt_spm_resource_req.h>
  8. #include <lib/pm/mtk_pm.h>
  9. #include <lpm/mt_lp_api.h>
  10. #include <lpm/mt_lp_rm.h>
  11. #include <mt_spm.h>
  12. #include <mt_spm_cond.h>
  13. #include <mt_spm_conservation.h>
  14. #include <mt_spm_constraint.h>
  15. #include <mt_spm_idle.h>
  16. #include <mt_spm_internal.h>
  17. #include <mt_spm_notifier.h>
  18. #include "mt_spm_rc_api.h"
  19. #include "mt_spm_rc_internal.h"
  20. #include <mt_spm_reg.h>
  21. #include <mt_spm_suspend.h>
  22. #define CONSTRAINT_DRAM_ALLOW (MT_RM_CONSTRAINT_ALLOW_DRAM_S0 | \
  23. MT_RM_CONSTRAINT_ALLOW_DRAM_S1 | \
  24. MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF)
  25. #define CONSTRAINT_DRAM_PCM_FLAG (SPM_FLAG_DISABLE_INFRA_PDN | \
  26. SPM_FLAG_DISABLE_VCORE_DVS | \
  27. SPM_FLAG_DISABLE_VCORE_DFS | \
  28. SPM_FLAG_SRAM_SLEEP_CTRL | \
  29. SPM_FLAG_KEEP_CSYSPWRACK_HIGH | \
  30. SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP)
  31. #define CONSTRAINT_DRAM_PCM_FLAG1 (0)
  32. #define CONSTRAINT_DRAM_RESOURCE_REQ (MT_SPM_SYSPLL | MT_SPM_INFRA | MT_SPM_26M)
  33. static struct mt_spm_cond_tables cond_dram = {
  34. .name = "dram",
  35. .table_cg = {
  36. 0xFF5DD002, /* MTCMOS1 */
  37. 0x0000003C, /* MTCMOS2 */
  38. 0x27AF8000, /* INFRA0 */
  39. 0x20010876, /* INFRA1 */
  40. 0x86000640, /* INFRA2 */
  41. 0x00000000, /* INFRA3 */
  42. 0x80000000, /* INFRA4 */
  43. 0x01002A00, /* PERI0 */
  44. 0x00080000, /* VPPSYS0_0 */
  45. 0x38803000, /* VPPSYS0_1 */
  46. 0x00081450, /* VPPSYS1_0 */
  47. 0x00003000, /* VPPSYS1_1 */
  48. 0x00000000, /* VDOSYS0_0 */
  49. 0x00000000, /* VDOSYS0_1 */
  50. 0x000001F8, /* VDOSYS1_0 */
  51. 0x000001E0, /* VDOSYS1_1 */
  52. 0x00FB0007, /* VDOSYS1_2 */
  53. },
  54. .table_pll = 0U,
  55. };
  56. static struct mt_spm_cond_tables cond_dram_res = {
  57. .table_cg = { 0U },
  58. .table_pll = 0U,
  59. };
  60. static struct constraint_status status = {
  61. .id = MT_RM_CONSTRAINT_ID_DRAM,
  62. .is_valid = (MT_SPM_RC_VALID_SW |
  63. MT_SPM_RC_VALID_COND_CHECK |
  64. MT_SPM_RC_VALID_COND_LATCH |
  65. MT_SPM_RC_VALID_XSOC_BBLPM |
  66. MT_SPM_RC_VALID_TRACE_TIME),
  67. .is_cond_block = 0U,
  68. .enter_cnt = 0U,
  69. .cond_res = &cond_dram_res,
  70. .residency = 0ULL,
  71. };
  72. static unsigned short ext_status_dram;
  73. int spm_dram_conduct(int state_id, struct spm_lp_scen *spm_lp, unsigned int *resource_req)
  74. {
  75. unsigned int res_req = CONSTRAINT_DRAM_RESOURCE_REQ;
  76. if ((spm_lp == NULL) || (resource_req == NULL)) {
  77. return -1;
  78. }
  79. spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_DRAM_PCM_FLAG;
  80. spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_DRAM_PCM_FLAG1;
  81. *resource_req |= res_req;
  82. return 0;
  83. }
  84. bool spm_is_valid_rc_dram(unsigned int cpu, int state_id)
  85. {
  86. return (!(status.is_cond_block && (status.is_valid & MT_SPM_RC_VALID_COND_CHECK)) &&
  87. IS_MT_RM_RC_READY(status.is_valid) &&
  88. (IS_PLAT_SUSPEND_ID(state_id) ||
  89. (state_id == MT_PLAT_PWR_STATE_SYSTEM_MEM) ||
  90. (state_id == MT_PLAT_PWR_STATE_SYSTEM_PLL) ||
  91. (state_id == MT_PLAT_PWR_STATE_SYSTEM_BUS)));
  92. }
  93. static int update_rc_condition(int state_id, const void *val)
  94. {
  95. const struct mt_spm_cond_tables *tlb = (const struct mt_spm_cond_tables *)val;
  96. const struct mt_spm_cond_tables *tlb_check = (const struct mt_spm_cond_tables *)&cond_dram;
  97. if (tlb == NULL) {
  98. return MT_RM_STATUS_BAD;
  99. }
  100. status.is_cond_block = mt_spm_cond_check(state_id, tlb, tlb_check,
  101. (status.is_valid & MT_SPM_RC_VALID_COND_LATCH) ?
  102. &cond_dram_res : NULL);
  103. return MT_RM_STATUS_OK;
  104. }
  105. static void update_rc_clkbuf_status(const void *val)
  106. {
  107. unsigned int is_flight = (val) ? !!(*((unsigned int *)val) == FLIGHT_MODE_ON) : 0;
  108. if (is_flight != 0U) {
  109. spm_rc_constraint_valid_set(MT_RM_CONSTRAINT_ID_DRAM,
  110. MT_RM_CONSTRAINT_ID_DRAM,
  111. MT_SPM_RC_VALID_FLIGHTMODE,
  112. (struct constraint_status * const)&status);
  113. } else {
  114. spm_rc_constraint_valid_clr(MT_RM_CONSTRAINT_ID_DRAM,
  115. MT_RM_CONSTRAINT_ID_DRAM,
  116. MT_SPM_RC_VALID_FLIGHTMODE,
  117. (struct constraint_status * const)&status);
  118. }
  119. }
  120. static void update_rc_ufs_status(const void *val)
  121. {
  122. unsigned int is_ufs_h8 = (val) ? !!(*((unsigned int *)val) == UFS_REF_CLK_OFF) : 0;
  123. if (is_ufs_h8 != 0U) {
  124. spm_rc_constraint_valid_set(MT_RM_CONSTRAINT_ID_DRAM,
  125. MT_RM_CONSTRAINT_ID_DRAM,
  126. MT_SPM_RC_VALID_UFS_H8,
  127. (struct constraint_status * const)&status);
  128. } else {
  129. spm_rc_constraint_valid_clr(MT_RM_CONSTRAINT_ID_DRAM,
  130. MT_RM_CONSTRAINT_ID_DRAM,
  131. MT_SPM_RC_VALID_UFS_H8,
  132. (struct constraint_status * const)&status);
  133. }
  134. }
  135. static void update_rc_status(const void *val)
  136. {
  137. const struct rc_common_state *st;
  138. st = (const struct rc_common_state *)val;
  139. if (st == NULL) {
  140. return;
  141. }
  142. if (st->type == CONSTRAINT_UPDATE_COND_CHECK) {
  143. struct mt_spm_cond_tables * const tlb = &cond_dram;
  144. spm_rc_condition_modifier(st->id, st->act, st->value,
  145. MT_RM_CONSTRAINT_ID_DRAM, tlb);
  146. } else if ((st->type == CONSTRAINT_UPDATE_VALID) ||
  147. (st->type == CONSTRAINT_RESIDNECY)) {
  148. spm_rc_constraint_status_set(st->id, st->type, st->act,
  149. MT_RM_CONSTRAINT_ID_DRAM,
  150. (struct constraint_status * const)st->value,
  151. (struct constraint_status * const)&status);
  152. } else {
  153. INFO("[%s:%d] - Unknown type: 0x%x\n", __func__, __LINE__, st->type);
  154. }
  155. }
  156. int spm_update_rc_dram(int state_id, int type, const void *val)
  157. {
  158. int res = MT_RM_STATUS_OK;
  159. switch (type) {
  160. case PLAT_RC_UPDATE_CONDITION:
  161. res = update_rc_condition(state_id, val);
  162. break;
  163. case PLAT_RC_CLKBUF_STATUS:
  164. update_rc_clkbuf_status(val);
  165. break;
  166. case PLAT_RC_UFS_STATUS:
  167. update_rc_ufs_status(val);
  168. break;
  169. case PLAT_RC_STATUS:
  170. update_rc_status(val);
  171. break;
  172. default:
  173. INFO("[%s:%d] - Do nothing for type: %d\n", __func__, __LINE__, type);
  174. break;
  175. }
  176. return res;
  177. }
  178. unsigned int spm_allow_rc_dram(int state_id)
  179. {
  180. return CONSTRAINT_DRAM_ALLOW;
  181. }
  182. int spm_run_rc_dram(unsigned int cpu, int state_id)
  183. {
  184. unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT;
  185. unsigned int allows = CONSTRAINT_DRAM_ALLOW;
  186. ext_status_dram = status.is_valid;
  187. if (IS_MT_SPM_RC_BBLPM_MODE(ext_status_dram)) {
  188. #ifdef MT_SPM_USING_SRCLKEN_RC
  189. ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM;
  190. #else
  191. allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM;
  192. #endif
  193. }
  194. #ifndef MTK_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
  195. mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER, allows | (IS_PLAT_SUSPEND_ID(state_id) ?
  196. (MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND) : (0U)));
  197. #else
  198. (void)allows;
  199. #endif
  200. if (ext_status_dram & MT_SPM_RC_VALID_TRACE_TIME) {
  201. ext_op |= MT_SPM_EX_OP_TRACE_TIMESTAMP_EN;
  202. }
  203. if (IS_PLAT_SUSPEND_ID(state_id)) {
  204. mt_spm_suspend_enter(state_id,
  205. (MT_SPM_EX_OP_CLR_26M_RECORD |
  206. MT_SPM_EX_OP_SET_WDT |
  207. MT_SPM_EX_OP_SET_SUSPEND_MODE |
  208. MT_SPM_EX_OP_HW_S1_DETECT),
  209. CONSTRAINT_DRAM_RESOURCE_REQ);
  210. } else {
  211. mt_spm_idle_generic_enter(state_id, ext_op, spm_dram_conduct);
  212. }
  213. return 0;
  214. }
  215. int spm_reset_rc_dram(unsigned int cpu, int state_id)
  216. {
  217. unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT;
  218. unsigned int allows = CONSTRAINT_DRAM_ALLOW;
  219. if (IS_MT_SPM_RC_BBLPM_MODE(ext_status_dram)) {
  220. #ifdef MT_SPM_USING_SRCLKEN_RC
  221. ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM;
  222. #else
  223. allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM;
  224. #endif
  225. }
  226. #ifndef MTK_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
  227. mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, allows);
  228. #else
  229. (void)allows;
  230. #endif
  231. if (ext_status_dram & MT_SPM_RC_VALID_TRACE_TIME) {
  232. ext_op |= MT_SPM_EX_OP_TRACE_TIMESTAMP_EN;
  233. }
  234. if (IS_PLAT_SUSPEND_ID(state_id)) {
  235. mt_spm_suspend_resume(state_id,
  236. (MT_SPM_EX_OP_SET_WDT | MT_SPM_EX_OP_HW_S1_DETECT),
  237. NULL);
  238. } else {
  239. struct wake_status *waken = NULL;
  240. if (spm_unlikely(status.is_valid & MT_SPM_RC_VALID_TRACE_EVENT)) {
  241. ext_op |= MT_SPM_EX_OP_TRACE_LP;
  242. }
  243. mt_spm_idle_generic_resume(state_id, ext_op, &waken, NULL);
  244. status.enter_cnt++;
  245. if (spm_unlikely(status.is_valid & MT_SPM_RC_VALID_RESIDNECY)) {
  246. status.residency += (waken != NULL) ? waken->tr.comm.timer_out : 0;
  247. }
  248. }
  249. return 0;
  250. }
  251. int spm_get_status_rc_dram(unsigned int type, void *priv)
  252. {
  253. int ret = MT_RM_STATUS_OK;
  254. if (type == PLAT_RC_STATUS) {
  255. int res = 0;
  256. struct rc_common_state *st = (struct rc_common_state *)priv;
  257. if (st == NULL) {
  258. return MT_RM_STATUS_BAD;
  259. }
  260. res = spm_rc_constraint_status_get(st->id, st->type,
  261. st->act, MT_RM_CONSTRAINT_ID_DRAM,
  262. (struct constraint_status * const)&status,
  263. (struct constraint_status * const)st->value);
  264. if ((res == 0) && (st->id != MT_RM_CONSTRAINT_ID_ALL)) {
  265. ret = MT_RM_STATUS_STOP;
  266. }
  267. }
  268. return ret;
  269. }