mt_spm_sleep.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/kernel.h>
  4. #include <linux/spinlock.h>
  5. #include <linux/delay.h>
  6. #include <linux/string.h>
  7. #include <linux/of_fdt.h>
  8. #include <asm/setup.h>
  9. #ifndef CONFIG_ARM64
  10. #include <mach/irqs.h>
  11. #else
  12. #include <linux/irqchip/mt-gic.h>
  13. #endif
  14. #if defined(CONFIG_MTK_SYS_CIRQ)
  15. #include <mt-plat/mt_cirq.h>
  16. #endif
  17. #include <mach/mt_clkmgr.h>
  18. #include "mt_cpuidle.h"
  19. #ifdef CONFIG_MTK_WD_KICKER
  20. #include <mach/wd_api.h>
  21. #endif
  22. #include "mt_cpufreq.h"
  23. #include <mt-plat/upmu_common.h>
  24. #include "mt_spm_misc.h"
  25. #if 1
  26. #include <mt_dramc.h>
  27. #endif
  28. #include "mt_spm_internal.h"
  29. #include "mt_spm_pmic_wrap.h"
  30. #include <mt-plat/mt_ccci_common.h>
  31. /**************************************
  32. * only for internal debug
  33. **************************************/
  34. #ifdef CONFIG_MTK_LDVT
  35. #define SPM_PWAKE_EN 0
  36. #define SPM_PCMWDT_EN 0
  37. #define SPM_BYPASS_SYSPWREQ 1
  38. #else
  39. #define SPM_PWAKE_EN 1
  40. #define SPM_PCMWDT_EN 1
  41. #define SPM_BYPASS_SYSPWREQ 0
  42. #endif
  43. #ifdef CONFIG_OF
  44. #define MCUCFG_BASE spm_mcucfg
  45. #else
  46. #define MCUCFG_BASE (0xF0200000) /* 0x1020_0000 */
  47. #endif
  48. #define MP0_AXI_CONFIG (MCUCFG_BASE + 0x2C)
  49. #define MP1_AXI_CONFIG (MCUCFG_BASE + 0x22C)
  50. #define ACINACTM (1<<4)
  51. int spm_dormant_sta = MT_CPU_DORMANT_RESET;
  52. int spm_ap_mdsrc_req_cnt = 0;
  53. struct wake_status suspend_info[20];
  54. u32 log_wakesta_cnt = 0;
  55. u32 log_wakesta_index = 0;
  56. u8 spm_snapshot_golden_setting = 0;
  57. struct wake_status spm_wakesta; /* record last wakesta */
  58. /**************************************
  59. * SW code for suspend
  60. **************************************/
  61. #define SPM_SYSCLK_SETTLE 99 /* 3ms */
  62. #define WAIT_UART_ACK_TIMES 10 /* 10 * 10us */
  63. #define SPM_WAKE_PERIOD 600 /* sec */
  64. #define WAKE_SRC_FOR_SUSPEND \
  65. (WAKE_SRC_R12_MD32_WDT_EVENT_B | \
  66. WAKE_SRC_R12_KP_IRQ_B | \
  67. WAKE_SRC_R12_CONN2AP_SPM_WAKEUP_B | \
  68. WAKE_SRC_R12_EINT_EVENT_B | \
  69. WAKE_SRC_R12_CONN_WDT_IRQ_B | \
  70. WAKE_SRC_R12_CCIF0_EVENT_B | \
  71. WAKE_SRC_R12_CCIF1_EVENT_B | \
  72. WAKE_SRC_R12_MD32_SPM_IRQ_B | \
  73. WAKE_SRC_R12_USB_CDSC_B | \
  74. WAKE_SRC_R12_USB_POWERDWN_B | \
  75. WAKE_SRC_R12_EINT_EVENT_SECURE_B | \
  76. WAKE_SRC_R12_MD1_WDT_B | \
  77. WAKE_SRC_R12_MD2_WDT_B | \
  78. WAKE_SRC_R12_CLDMA_EVENT_B | \
  79. WAKE_SRC_R12_SEJ_WDT_GPT_B | \
  80. WAKE_SRC_R12_ALL_MD32_WAKEUP_B)
  81. #define WAKE_SRC_FOR_MD32 0 \
  82. /* (WAKE_SRC_AUD_MD32) */
  83. #define spm_is_wakesrc_invalid(wakesrc) (!!((u32)(wakesrc) & 0xc0003803))
  84. /* FIXME: check mt_cpu_dormant */
  85. int __attribute__ ((weak)) mt_cpu_dormant(unsigned long flags)
  86. {
  87. return 0;
  88. }
  89. /* FIXME: check charger for get_dynamic_period */
  90. int __attribute__ ((weak)) get_dynamic_period(int first_use, int first_wakeup_time,
  91. int battery_capacity_level)
  92. {
  93. return 60;
  94. }
  95. #if SPM_AEE_RR_REC
  96. enum spm_suspend_step {
  97. SPM_SUSPEND_ENTER = 0,
  98. SPM_SUSPEND_ENTER_WFI = 0xff,
  99. SPM_SUSPEND_LEAVE_WFI = 0x1ff,
  100. SPM_SUSPEND_LEAVE
  101. };
  102. #endif
  103. static struct pwr_ctrl suspend_ctrl = {
  104. .wake_src = WAKE_SRC_FOR_SUSPEND,
  105. .wake_src_md32 = WAKE_SRC_FOR_MD32,
  106. .r0_ctrl_en = 1,
  107. .r7_ctrl_en = 1,
  108. .infra_dcm_lock = 1,
  109. .wfi_op = WFI_OP_AND,
  110. .mp0top_idle_mask = 0,
  111. .mp1top_idle_mask = 0,
  112. .mcusys_idle_mask = 0,
  113. .md_ddr_dbc_en = 0,
  114. .md1_req_mask_b = 1,
  115. .md2_req_mask_b = 0,
  116. .scp_req_mask_b = 0,
  117. .lte_mask_b = 0,
  118. .md_apsrc1_sel = 0,
  119. .md_apsrc0_sel = 0,
  120. .conn_mask_b = 1,
  121. .conn_apsrc_sel = 0,
  122. .ccif0_to_ap_mask_b = 1,
  123. .ccif0_to_md_mask_b = 1,
  124. .ccif1_to_ap_mask_b = 1,
  125. .ccif1_to_md_mask_b = 1,
  126. .ccifmd_md1_event_mask_b = 1,
  127. .ccifmd_md2_event_mask_b = 1,
  128. .vsync_mask_b = 0, /* 5bit */
  129. .md_srcclkena_0_infra_mask_b = 0,
  130. .md_srcclkena_1_infra_mask_b = 0,
  131. .conn_srcclkena_infra_mask_b = 0,
  132. .md32_srcclkena_infra_mask_b = 0,
  133. #if defined(CONFIG_ARCH_MT6755)
  134. .srcclkeni_infra_mask_b = 1,
  135. #else
  136. .srcclkeni_infra_mask_b = 0,
  137. #endif
  138. .md_apsrcreq_0_infra_mask_b = 1,
  139. .md_apsrcreq_1_infra_mask_b = 0,
  140. .conn_apsrcreq_infra_mask_b = 1,
  141. .md32_apsrcreq_infra_mask_b = 0,
  142. .md_ddr_en_0_mask_b = 1,
  143. .md_ddr_en_1_mask_b = 0,
  144. .md_vrf18_req_0_mask_b = 1,
  145. .md_vrf18_req_1_mask_b = 0,
  146. .emi_bw_dvfs_req_mask = 1,
  147. .md_srcclkena_0_dvfs_req_mask_b = 0,
  148. .md_srcclkena_1_dvfs_req_mask_b = 0,
  149. .conn_srcclkena_dvfs_req_mask_b = 0,
  150. .dvfs_halt_mask_b = 0x1f, /* 5bit */
  151. .vdec_req_mask_b = 0,
  152. .gce_req_mask_b = 0,
  153. .cpu_md_dvfs_erq_merge_mask_b = 0,
  154. .md1_ddr_en_dvfs_halt_mask_b = 0,
  155. .md2_ddr_en_dvfs_halt_mask_b = 0,
  156. .vsync_dvfs_halt_mask_b = 0, /* 5bit */
  157. .conn_ddr_en_mask_b = 1,
  158. .disp_req_mask_b = 0,
  159. .disp1_req_mask_b = 0,
  160. .mfg_req_mask_b = 0,
  161. .c2k_ps_rccif_wake_mask_b = 1,
  162. .c2k_l1_rccif_wake_mask_b = 1,
  163. .ps_c2k_rccif_wake_mask_b = 1,
  164. .l1_c2k_rccif_wake_mask_b = 1,
  165. .sdio_on_dvfs_req_mask_b = 0,
  166. .emi_boost_dvfs_req_mask_b = 0,
  167. .cpu_md_emi_dvfs_req_prot_dis = 0,
  168. .spm_apsrc_req = 0,
  169. .spm_f26m_req = 0,
  170. .spm_lte_req = 0,
  171. .spm_infra_req = 0,
  172. .spm_vrf18_req = 0,
  173. .spm_dvfs_req = 0,
  174. .spm_dvfs_force_down = 1,
  175. .spm_ddren_req = 0,
  176. .cpu_md_dvfs_sop_force_on = 0,
  177. /* SPM_CLK_CON */
  178. .srclkenai_mask = 1,
  179. .mp0_cpu0_wfi_en = 1,
  180. .mp0_cpu1_wfi_en = 1,
  181. .mp0_cpu2_wfi_en = 1,
  182. .mp0_cpu3_wfi_en = 1,
  183. .mp1_cpu0_wfi_en = 1,
  184. .mp1_cpu1_wfi_en = 1,
  185. .mp1_cpu2_wfi_en = 1,
  186. .mp1_cpu3_wfi_en = 1,
  187. #if SPM_BYPASS_SYSPWREQ
  188. .syspwreq_mask = 1,
  189. #endif
  190. };
  191. /* please put firmware to vendor/mediatek/proprietary/hardware/spm/mtxxxx/ */
  192. struct spm_lp_scen __spm_suspend = {
  193. .pwrctrl = &suspend_ctrl,
  194. .wakestatus = &suspend_info[0],
  195. };
  196. static void spm_suspend_pre_process(struct pwr_ctrl *pwrctrl)
  197. {
  198. #if defined(CONFIG_ARCH_MT6755)
  199. unsigned int temp;
  200. __spm_pmic_pg_force_on();
  201. spm_pmic_power_mode(PMIC_PWR_SUSPEND, 0, 0);
  202. /* set PMIC WRAP table for suspend power control */
  203. pmic_read_interface_nolock(MT6351_PMIC_RG_VSRAM_PROC_EN_ADDR, &temp, 0xFFFF, 0);
  204. mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_SUSPEND,
  205. IDX_SP_VSRAM_PWR_ON,
  206. temp | (1 << MT6351_PMIC_RG_VSRAM_PROC_EN_SHIFT));
  207. mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_SUSPEND,
  208. IDX_SP_VSRAM_SHUTDOWN,
  209. temp & ~(1 << MT6351_PMIC_RG_VSRAM_PROC_EN_SHIFT));
  210. mt_spm_pmic_wrap_set_phase(PMIC_WRAP_PHASE_SUSPEND);
  211. /* fpr dpd */
  212. if (!(pwrctrl->pcm_flags & SPM_FLAG_DIS_DPD))
  213. spm_dpd_init();
  214. /* Do more low power setting when MD1/C2K/CONN off */
  215. if (is_md_c2k_conn_power_off()) {
  216. __spm_bsi_top_init_setting();
  217. __spm_backup_pmic_ck_pdn();
  218. }
  219. #endif
  220. }
  221. static void spm_suspend_post_process(struct pwr_ctrl *pwrctrl)
  222. {
  223. #if defined(CONFIG_ARCH_MT6755)
  224. /* Do more low power setting when MD1/C2K/CONN off */
  225. if (is_md_c2k_conn_power_off())
  226. __spm_restore_pmic_ck_pdn();
  227. /* fpr dpd */
  228. if (!(pwrctrl->pcm_flags & SPM_FLAG_DIS_DPD))
  229. spm_dpd_dram_init();
  230. /* set PMIC WRAP table for normal power control */
  231. mt_spm_pmic_wrap_set_phase(PMIC_WRAP_PHASE_NORMAL);
  232. __spm_pmic_pg_force_off();
  233. #endif
  234. }
  235. static void spm_set_sysclk_settle(void)
  236. {
  237. u32 md_settle, settle;
  238. /* get MD SYSCLK settle */
  239. spm_write(SPM_CLK_CON, spm_read(SPM_CLK_CON) | SYS_SETTLE_SEL_LSB);
  240. spm_write(SPM_CLK_SETTLE, 0);
  241. md_settle = spm_read(SPM_CLK_SETTLE);
  242. /* SYSCLK settle = MD SYSCLK settle but set it again for MD PDN */
  243. spm_write(SPM_CLK_SETTLE, SPM_SYSCLK_SETTLE - md_settle);
  244. settle = spm_read(SPM_CLK_SETTLE);
  245. spm_crit2("md_settle = %u, settle = %u\n", md_settle, settle);
  246. }
  247. static void spm_kick_pcm_to_run(struct pwr_ctrl *pwrctrl)
  248. {
  249. /* enable PCM WDT (normal mode) to start count if needed */
  250. #if SPM_PCMWDT_EN
  251. if (!pwrctrl->wdt_disable) {
  252. u32 con1;
  253. con1 = spm_read(PCM_CON1) & ~(PCM_WDT_WAKE_MODE_LSB | PCM_WDT_EN_LSB);
  254. spm_write(PCM_CON1, SPM_REGWR_CFG_KEY | con1);
  255. if (spm_read(PCM_TIMER_VAL) > PCM_TIMER_MAX)
  256. spm_write(PCM_TIMER_VAL, PCM_TIMER_MAX);
  257. spm_write(PCM_WDT_VAL, spm_read(PCM_TIMER_VAL) + PCM_WDT_TIMEOUT);
  258. spm_write(PCM_CON1, con1 | SPM_REGWR_CFG_KEY | PCM_WDT_EN_LSB);
  259. }
  260. #endif
  261. #if 0
  262. /* make MD32 work in suspend: fscp_ck = CLK26M */
  263. clkmux_sel(MT_MUX_SCP, 0, "SPM-Sleep");
  264. #endif
  265. __spm_kick_pcm_to_run(pwrctrl);
  266. }
  267. static void spm_trigger_wfi_for_sleep(struct pwr_ctrl *pwrctrl)
  268. {
  269. #if 0
  270. sync_hw_gating_value(); /* for Vcore DVFS */
  271. #endif
  272. if (is_cpu_pdn(pwrctrl->pcm_flags)) {
  273. spm_dormant_sta = mt_cpu_dormant(CPU_SHUTDOWN_MODE /* | DORMANT_SKIP_WFI */);
  274. switch (spm_dormant_sta) {
  275. case MT_CPU_DORMANT_RESET:
  276. break;
  277. case MT_CPU_DORMANT_ABORT:
  278. break;
  279. case MT_CPU_DORMANT_BREAK:
  280. break;
  281. case MT_CPU_DORMANT_BYPASS:
  282. break;
  283. }
  284. } else {
  285. spm_dormant_sta = -1;
  286. spm_write(MP0_AXI_CONFIG, spm_read(MP0_AXI_CONFIG) | ACINACTM);
  287. spm_write(MP1_AXI_CONFIG, spm_read(MP1_AXI_CONFIG) | ACINACTM);
  288. wfi_with_sync();
  289. spm_write(MP0_AXI_CONFIG, spm_read(MP0_AXI_CONFIG) & ~ACINACTM);
  290. spm_write(MP1_AXI_CONFIG, spm_read(MP1_AXI_CONFIG) & ~ACINACTM);
  291. }
  292. if (is_infra_pdn(pwrctrl->pcm_flags))
  293. mtk_uart_restore();
  294. }
  295. static void spm_clean_after_wakeup(void)
  296. {
  297. /* disable PCM WDT to stop count if needed */
  298. #if SPM_PCMWDT_EN
  299. spm_write(PCM_CON1, SPM_REGWR_CFG_KEY | (spm_read(PCM_CON1) & ~PCM_WDT_EN_LSB));
  300. #endif
  301. __spm_clean_after_wakeup();
  302. #if 0
  303. /* restore clock mux: fscp_ck = SYSPLL1_D2 */
  304. clkmux_sel(MT_MUX_SCP, 1, "SPM-Sleep");
  305. #endif
  306. }
  307. static wake_reason_t spm_output_wake_reason(struct wake_status *wakesta, struct pcm_desc *pcmdesc)
  308. {
  309. wake_reason_t wr;
  310. u32 md32_flag = 0;
  311. u32 md32_flag2 = 0;
  312. wr = __spm_output_wake_reason(wakesta, pcmdesc, true);
  313. #if 1
  314. memcpy(&suspend_info[log_wakesta_cnt], wakesta, sizeof(struct wake_status));
  315. suspend_info[log_wakesta_cnt].log_index = log_wakesta_index;
  316. if (10 <= log_wakesta_cnt) {
  317. log_wakesta_cnt = 0;
  318. spm_snapshot_golden_setting = 0;
  319. } else {
  320. log_wakesta_cnt++;
  321. log_wakesta_index++;
  322. }
  323. if (0xFFFFFFF0 <= log_wakesta_index)
  324. log_wakesta_index = 0;
  325. #endif
  326. spm_crit2("suspend dormant state = %d, md32_flag = 0x%x, md32_flag2 = %d\n",
  327. spm_dormant_sta, md32_flag, md32_flag2);
  328. if (0 != spm_ap_mdsrc_req_cnt)
  329. spm_crit2("warning: spm_ap_mdsrc_req_cnt = %d, r7[ap_mdsrc_req] = 0x%x\n",
  330. spm_ap_mdsrc_req_cnt, spm_read(SPM_POWER_ON_VAL1) & (1 << 17));
  331. if (wakesta->r12 & WAKE_SRC_R12_EINT_EVENT_B)
  332. mt_eint_print_status();
  333. #if 0
  334. if (wakesta->debug_flag & (1 << 18)) {
  335. spm_crit2("MD32 suspned pmic wrapper error");
  336. BUG();
  337. }
  338. if (wakesta->debug_flag & (1 << 19)) {
  339. spm_crit2("MD32 resume pmic wrapper error");
  340. BUG();
  341. }
  342. #endif
  343. #ifdef CONFIG_MTK_CCCI_DEVICES
  344. /* if (wakesta->r13 & 0x18) { */
  345. spm_crit2("dump ID_DUMP_MD_SLEEP_MODE");
  346. exec_ccci_kern_func_by_md_id(0, ID_DUMP_MD_SLEEP_MODE, NULL, 0);
  347. /* } */
  348. #endif
  349. #ifndef CONFIG_MTK_FPGA
  350. #ifdef CONFIG_MTK_ECCCI_DRIVER
  351. if (wakesta->r12 & WAKE_SRC_R12_CLDMA_EVENT_B)
  352. exec_ccci_kern_func_by_md_id(0, ID_GET_MD_WAKEUP_SRC, NULL, 0);
  353. if (wakesta->r12 & WAKE_SRC_R12_CCIF1_EVENT_B)
  354. exec_ccci_kern_func_by_md_id(2, ID_GET_MD_WAKEUP_SRC, NULL, 0);
  355. #endif
  356. #endif
  357. return wr;
  358. }
  359. #if SPM_PWAKE_EN
  360. static u32 spm_get_wake_period(int pwake_time, wake_reason_t last_wr)
  361. {
  362. int period = SPM_WAKE_PERIOD;
  363. if (pwake_time < 0) {
  364. /* use FG to get the period of 1% battery decrease */
  365. period = get_dynamic_period(last_wr != WR_PCM_TIMER ? 1 : 0, SPM_WAKE_PERIOD, 1);
  366. if (period <= 0) {
  367. spm_warn("CANNOT GET PERIOD FROM FUEL GAUGE\n");
  368. period = SPM_WAKE_PERIOD;
  369. }
  370. } else {
  371. period = pwake_time;
  372. spm_crit2("pwake = %d\n", pwake_time);
  373. }
  374. if (period > 36 * 3600) /* max period is 36.4 hours */
  375. period = 36 * 3600;
  376. return period;
  377. }
  378. #endif
  379. /*
  380. * wakesrc: WAKE_SRC_XXX
  381. * enable : enable or disable @wakesrc
  382. * replace: if true, will replace the default setting
  383. */
  384. int spm_set_sleep_wakesrc(u32 wakesrc, bool enable, bool replace)
  385. {
  386. unsigned long flags;
  387. if (spm_is_wakesrc_invalid(wakesrc))
  388. return -EINVAL;
  389. spin_lock_irqsave(&__spm_lock, flags);
  390. if (enable) {
  391. if (replace)
  392. __spm_suspend.pwrctrl->wake_src = wakesrc;
  393. else
  394. __spm_suspend.pwrctrl->wake_src |= wakesrc;
  395. } else {
  396. if (replace)
  397. __spm_suspend.pwrctrl->wake_src = 0;
  398. else
  399. __spm_suspend.pwrctrl->wake_src &= ~wakesrc;
  400. }
  401. spin_unlock_irqrestore(&__spm_lock, flags);
  402. return 0;
  403. }
  404. /*
  405. * wakesrc: WAKE_SRC_XXX
  406. */
  407. u32 spm_get_sleep_wakesrc(void)
  408. {
  409. return __spm_suspend.pwrctrl->wake_src;
  410. }
  411. #if SPM_AEE_RR_REC
  412. void spm_suspend_aee_init(void)
  413. {
  414. aee_rr_rec_spm_suspend_val(0);
  415. }
  416. #endif
  417. #ifndef CONFIG_MTK_FPGA
  418. #ifdef CONFIG_MTK_PMIC
  419. /* #include <cust_pmic.h> */
  420. #ifndef DISABLE_DLPT_FEATURE
  421. /* extern int get_dlpt_imix_spm(void); */
  422. int __attribute__((weak)) get_dlpt_imix_spm(void)
  423. {
  424. return 0;
  425. }
  426. #endif
  427. #endif
  428. #endif
  429. wake_reason_t spm_go_to_sleep(u32 spm_flags, u32 spm_data)
  430. {
  431. u32 sec = 2;
  432. /* struct wake_status wakesta; */
  433. unsigned long flags;
  434. struct mtk_irq_mask mask;
  435. #ifndef CONFIG_MTK_FPGA
  436. #ifdef CONFIG_MTK_WD_KICKER
  437. struct wd_api *wd_api;
  438. int wd_ret;
  439. #endif
  440. #endif
  441. static wake_reason_t last_wr = WR_NONE;
  442. struct pcm_desc *pcmdesc = NULL;
  443. struct pwr_ctrl *pwrctrl;
  444. u32 cpu = smp_processor_id();
  445. #ifndef CONFIG_MTK_FPGA
  446. #ifdef CONFIG_MTK_PMIC
  447. #ifndef DISABLE_DLPT_FEATURE
  448. get_dlpt_imix_spm();
  449. #endif
  450. #endif
  451. #endif
  452. #if SPM_AEE_RR_REC
  453. spm_suspend_aee_init();
  454. aee_rr_rec_spm_suspend_val(SPM_SUSPEND_ENTER);
  455. #endif
  456. if (dyna_load_pcm[DYNA_LOAD_PCM_SUSPEND + cpu / 4].ready)
  457. pcmdesc = &(dyna_load_pcm[DYNA_LOAD_PCM_SUSPEND + cpu / 4].desc);
  458. else
  459. BUG();
  460. spm_crit2("Online CPU is %d, suspend FW ver. is %s\n", cpu, pcmdesc->version);
  461. pwrctrl = __spm_suspend.pwrctrl;
  462. update_pwrctrl_pcm_flags(&spm_flags);
  463. set_pwrctrl_pcm_flags(pwrctrl, spm_flags);
  464. set_pwrctrl_pcm_data(pwrctrl, spm_data);
  465. #if SPM_PWAKE_EN
  466. sec = spm_get_wake_period(-1 /* FIXME */, last_wr);
  467. #endif
  468. pwrctrl->timer_val = sec * 32768;
  469. #ifdef CONFIG_MTK_WD_KICKER
  470. wd_ret = get_wd_api(&wd_api);
  471. if (!wd_ret) {
  472. wd_api->wd_spmwdt_mode_config(WD_REQ_EN, WD_REQ_RST_MODE);
  473. wd_api->wd_suspend_notify();
  474. } else
  475. spm_crit2("FAILED TO GET WD API\n");
  476. #endif
  477. spm_suspend_pre_process(pwrctrl);
  478. #if 0
  479. /* snapshot golden setting */
  480. {
  481. if (!is_already_snap_shot)
  482. snapshot_golden_setting(__func__, 0);
  483. }
  484. #endif
  485. spin_lock_irqsave(&__spm_lock, flags);
  486. mt_irq_mask_all(&mask);
  487. mt_irq_unmask_for_sleep(SPM_IRQ0_ID);
  488. #if defined(CONFIG_MTK_SYS_CIRQ)
  489. mt_cirq_clone_gic();
  490. mt_cirq_enable();
  491. #endif
  492. spm_set_sysclk_settle();
  493. spm_crit2("sec = %u, wakesrc = 0x%x (%u)(%u)\n",
  494. sec, pwrctrl->wake_src, is_cpu_pdn(pwrctrl->pcm_flags),
  495. is_infra_pdn(pwrctrl->pcm_flags));
  496. if (request_uart_to_sleep()) {
  497. last_wr = WR_UART_BUSY;
  498. goto RESTORE_IRQ;
  499. }
  500. __spm_reset_and_init_pcm(pcmdesc);
  501. __spm_kick_im_to_fetch(pcmdesc);
  502. __spm_init_pcm_register();
  503. __spm_init_event_vector(pcmdesc);
  504. __spm_check_md_pdn_power_control(pwrctrl);
  505. /* __spm_sync_vcore_dvfs_power_control(pwrctrl, __spm_vcore_dvfs.pwrctrl); */
  506. __spm_set_power_control(pwrctrl);
  507. __spm_set_wakeup_event(pwrctrl);
  508. spm_kick_pcm_to_run(pwrctrl);
  509. #if SPM_AEE_RR_REC
  510. aee_rr_rec_spm_suspend_val(SPM_SUSPEND_ENTER_WFI);
  511. #endif
  512. spm_trigger_wfi_for_sleep(pwrctrl);
  513. #if SPM_AEE_RR_REC
  514. aee_rr_rec_spm_suspend_val(SPM_SUSPEND_LEAVE_WFI);
  515. #endif
  516. /* record last wakesta */
  517. /* __spm_get_wakeup_status(&wakesta); */
  518. __spm_get_wakeup_status(&spm_wakesta);
  519. spm_clean_after_wakeup();
  520. request_uart_to_wakeup();
  521. /* record last wakesta */
  522. /* last_wr = spm_output_wake_reason(&wakesta, pcmdesc); */
  523. last_wr = spm_output_wake_reason(&spm_wakesta, pcmdesc);
  524. RESTORE_IRQ:
  525. #if defined(CONFIG_MTK_SYS_CIRQ)
  526. mt_cirq_flush();
  527. mt_cirq_disable();
  528. #endif
  529. mt_irq_mask_restore(&mask);
  530. spin_unlock_irqrestore(&__spm_lock, flags);
  531. spm_suspend_post_process(pwrctrl);
  532. #ifdef CONFIG_MTK_WD_KICKER
  533. if (!wd_ret) {
  534. if (!pwrctrl->wdt_disable)
  535. wd_api->wd_resume_notify();
  536. else
  537. spm_crit2("pwrctrl->wdt_disable %d\n", pwrctrl->wdt_disable);
  538. wd_api->wd_spmwdt_mode_config(WD_REQ_DIS, WD_REQ_RST_MODE);
  539. }
  540. #endif
  541. #if SPM_AEE_RR_REC
  542. aee_rr_rec_spm_suspend_val(0);
  543. #endif
  544. return last_wr;
  545. }
  546. bool spm_is_md_sleep(void)
  547. {
  548. return !((spm_read(PCM_REG13_DATA) & R13_MD1_SRCCLKENA) |
  549. (spm_read(PCM_REG13_DATA) & R13_MD2_SRCCLKENA));
  550. }
  551. bool spm_is_md1_sleep(void)
  552. {
  553. return !(spm_read(PCM_REG13_DATA) & R13_MD1_SRCCLKENA);
  554. }
  555. bool spm_is_md2_sleep(void)
  556. {
  557. return !(spm_read(PCM_REG13_DATA) & R13_MD2_SRCCLKENA);
  558. }
  559. bool spm_is_conn_sleep(void)
  560. {
  561. return !(spm_read(PCM_REG13_DATA) & R13_CONN_SRCCLKENA);
  562. }
  563. void spm_set_wakeup_src_check(void)
  564. {
  565. /* clean wakeup event raw status */
  566. spm_write(SPM_WAKEUP_EVENT_MASK, 0xFFFFFFFF);
  567. /* set wakeup event */
  568. spm_write(SPM_WAKEUP_EVENT_MASK, ~WAKE_SRC_FOR_SUSPEND);
  569. }
  570. bool spm_check_wakeup_src(void)
  571. {
  572. u32 wakeup_src;
  573. /* check wanek event raw status */
  574. wakeup_src = spm_read(SPM_WAKEUP_STA);
  575. if (wakeup_src) {
  576. spm_crit2("WARNING: spm_check_wakeup_src = 0x%x", wakeup_src);
  577. return 1;
  578. } else
  579. return 0;
  580. }
  581. void spm_poweron_config_set(void)
  582. {
  583. unsigned long flags;
  584. spin_lock_irqsave(&__spm_lock, flags);
  585. /* enable register control */
  586. spm_write(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | BCLK_CG_EN_LSB);
  587. spin_unlock_irqrestore(&__spm_lock, flags);
  588. }
  589. void spm_md32_sram_con(u32 value)
  590. {
  591. unsigned long flags;
  592. spin_lock_irqsave(&__spm_lock, flags);
  593. /* enable register control */
  594. spm_write(SCP_SRAM_CON, value);
  595. spin_unlock_irqrestore(&__spm_lock, flags);
  596. }
  597. #if 0
  598. #define hw_spin_lock_for_ddrdfs() \
  599. do { \
  600. spm_write(0xF0050090, 0x8000); \
  601. } while (!(spm_read(0xF0050090) & 0x8000))
  602. #define hw_spin_unlock_for_ddrdfs() \
  603. spm_write(0xF0050090, 0x8000)
  604. #else
  605. #define hw_spin_lock_for_ddrdfs()
  606. #define hw_spin_unlock_for_ddrdfs()
  607. #endif
  608. void spm_ap_mdsrc_req(u8 set)
  609. {
  610. unsigned long flags;
  611. u32 i = 0;
  612. u32 md_sleep = 0;
  613. if (set) {
  614. spin_lock_irqsave(&__spm_lock, flags);
  615. if (spm_ap_mdsrc_req_cnt < 0) {
  616. spm_crit2("warning: set = %d, spm_ap_mdsrc_req_cnt = %d\n", set,
  617. spm_ap_mdsrc_req_cnt);
  618. /* goto AP_MDSRC_REC_CNT_ERR; */
  619. spin_unlock_irqrestore(&__spm_lock, flags);
  620. } else {
  621. spm_ap_mdsrc_req_cnt++;
  622. hw_spin_lock_for_ddrdfs();
  623. spm_write(AP_MDSRC_REQ, spm_read(AP_MDSRC_REQ) | AP_MD1SRC_REQ_LSB);
  624. hw_spin_unlock_for_ddrdfs();
  625. spin_unlock_irqrestore(&__spm_lock, flags);
  626. /* if md_apsrc_req = 1'b0, wait 26M settling time (3ms) */
  627. if (0 == (spm_read(PCM_REG13_DATA) & R13_MD1_APSRC_REQ)) {
  628. md_sleep = 1;
  629. mdelay(3);
  630. }
  631. /* Check ap_mdsrc_ack = 1'b1 */
  632. while (0 == (spm_read(AP_MDSRC_REQ) & AP_MD1SRC_ACK_LSB)) {
  633. if (10 > i++) {
  634. mdelay(1);
  635. } else {
  636. spm_crit2
  637. ("WARNING: MD SLEEP = %d, spm_ap_mdsrc_req CAN NOT polling AP_MD1SRC_ACK\n",
  638. md_sleep);
  639. /* goto AP_MDSRC_REC_CNT_ERR; */
  640. break;
  641. }
  642. }
  643. }
  644. } else {
  645. spin_lock_irqsave(&__spm_lock, flags);
  646. spm_ap_mdsrc_req_cnt--;
  647. if (spm_ap_mdsrc_req_cnt < 0) {
  648. spm_crit2("warning: set = %d, spm_ap_mdsrc_req_cnt = %d\n", set,
  649. spm_ap_mdsrc_req_cnt);
  650. /* goto AP_MDSRC_REC_CNT_ERR; */
  651. } else {
  652. if (0 == spm_ap_mdsrc_req_cnt) {
  653. hw_spin_lock_for_ddrdfs();
  654. spm_write(AP_MDSRC_REQ, spm_read(AP_MDSRC_REQ) & ~AP_MD1SRC_REQ_LSB);
  655. hw_spin_unlock_for_ddrdfs();
  656. }
  657. }
  658. spin_unlock_irqrestore(&__spm_lock, flags);
  659. }
  660. /* AP_MDSRC_REC_CNT_ERR: */
  661. /* spin_unlock_irqrestore(&__spm_lock, flags); */
  662. }
  663. bool spm_set_suspned_pcm_init_flag(u32 *suspend_flags)
  664. {
  665. return true;
  666. }
  667. void spm_output_sleep_option(void)
  668. {
  669. spm_notice("PWAKE_EN:%d, PCMWDT_EN:%d, BYPASS_SYSPWREQ:%d\n",
  670. SPM_PWAKE_EN, SPM_PCMWDT_EN, SPM_BYPASS_SYSPWREQ);
  671. }
  672. uint32_t get_suspend_debug_regs(uint32_t index)
  673. {
  674. uint32_t value = 0;
  675. switch (index) {
  676. case 0:
  677. #ifndef CONFIG_MTK_FPGA
  678. value = 5;
  679. #else
  680. value = 0;
  681. #endif
  682. spm_crit("SPM Suspend debug regs count = 0x%.8x\n", value);
  683. break;
  684. case 1:
  685. value = spm_read(PCM_WDT_LATCH_0);
  686. spm_crit("SPM Suspend debug regs(0x%x) = 0x%.8x\n", index, value);
  687. break;
  688. case 2:
  689. value = spm_read(PCM_WDT_LATCH_1);
  690. spm_crit("SPM Suspend debug regs(0x%x) = 0x%.8x\n", index, value);
  691. break;
  692. case 3:
  693. value = spm_read(PCM_WDT_LATCH_2);
  694. spm_crit("SPM Suspend debug regs(0x%x) = 0x%.8x\n", index, value);
  695. break;
  696. case 4:
  697. value = spm_read(PCM_WDT_LATCH_3);
  698. spm_crit("SPM Suspend debug regs(0x%x) = 0x%.8x\n", index, value);
  699. break;
  700. case 5:
  701. value = spm_read(DRAMC_DBG_LATCH);
  702. spm_crit("SPM Suspend debug regs(0x%x) = 0x%.8x\n", index, value);
  703. break;
  704. }
  705. return value;
  706. }
  707. EXPORT_SYMBOL(get_suspend_debug_regs);
  708. /* record last wakesta */
  709. u32 spm_get_last_wakeup_src(void)
  710. {
  711. return spm_wakesta.r12;
  712. }
  713. u32 spm_get_last_wakeup_misc(void)
  714. {
  715. return spm_wakesta.wake_misc;
  716. }
  717. MODULE_DESCRIPTION("SPM-Sleep Driver v0.1");