mt_sleep.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/kernel.h>
  4. #include <linux/spinlock.h>
  5. #include <linux/suspend.h>
  6. #include <linux/console.h>
  7. /* #include <linux/aee.h> */
  8. #include <linux/proc_fs.h>
  9. #include <linux/fs.h>
  10. #include <linux/vmalloc.h>
  11. #include <linux/uaccess.h>
  12. #include <mt-plat/sync_write.h>
  13. #include "mt_sleep.h"
  14. #include "mt_spm.h"
  15. #include "mt_spm_sleep.h"
  16. #include "mt_spm_idle.h"
  17. #include "mt_spm_mtcmos.h"
  18. #include "mt_clkmgr.h"
  19. #include "mt_spm_misc.h"
  20. #ifdef CONFIG_MT_SND_SOC_6755
  21. #include <mt_soc_afe_control.h>
  22. #endif
  23. /**************************************
  24. * only for internal debug
  25. **************************************/
  26. #ifdef CONFIG_MTK_LDVT
  27. #define SLP_SLEEP_DPIDLE_EN 1
  28. #define SLP_REPLACE_DEF_WAKESRC 1
  29. #define SLP_SUSPEND_LOG_EN 1
  30. #else
  31. #define SLP_SLEEP_DPIDLE_EN 1
  32. #define SLP_REPLACE_DEF_WAKESRC 0
  33. #define SLP_SUSPEND_LOG_EN 1
  34. #endif
  35. /**************************************
  36. * SW code for suspend
  37. **************************************/
  38. #define slp_read(addr) __raw_readl((void __force __iomem *)(addr))
  39. #define slp_write(addr, val) mt65xx_reg_sync_writel(val, addr)
  40. /*
  41. #define slp_emerg(fmt, args...) pr_debug(KERN_EMERG "[SLP] " fmt, ##args)
  42. #define slp_alert(fmt, args...) pr_debug(KERN_ALERT "[SLP] " fmt, ##args)
  43. #define slp_crit(fmt, args...) pr_debug(KERN_CRIT "[SLP] " fmt, ##args)
  44. #define slp_crit2(fmt, args...) pr_debug(KERN_CRIT "[SLP] " fmt, ##args)
  45. #define slp_error(fmt, args...) pr_err(KERN_ERR "[SLP] " fmt, ##args)
  46. #define slp_warning(fmt, args...) pr_debug(KERN_WARNING "[SLP] " fmt, ##args)
  47. #define slp_notice(fmt, args...) pr_debug(KERN_NOTICE "[SLP] " fmt, ##args)
  48. #define slp_info(fmt, args...) pr_debug(KERN_INFO "[SLP] " fmt, ##args)
  49. #define slp_debug(fmt, args...) pr_debug(KERN_DEBUG "[SLP] " fmt, ##args)
  50. */
  51. #define slp_emerg(fmt, args...) pr_debug("[SLP] " fmt, ##args)
  52. #define slp_alert(fmt, args...) pr_debug("[SLP] " fmt, ##args)
  53. #define slp_crit(fmt, args...) pr_debug("[SLP] " fmt, ##args)
  54. #define slp_crit2(fmt, args...) pr_debug("[SLP] " fmt, ##args)
  55. #define slp_error(fmt, args...) pr_err("[SLP] " fmt, ##args)
  56. #define slp_warning(fmt, args...) pr_debug("[SLP] " fmt, ##args)
  57. #define slp_notice(fmt, args...) pr_debug("[SLP] " fmt, ##args)
  58. #define slp_info(fmt, args...) pr_debug("[SLP] " fmt, ##args)
  59. #define slp_debug(fmt, args...) pr_debug("[SLP] " fmt, ##args)
  60. static DEFINE_SPINLOCK(slp_lock);
  61. static wake_reason_t slp_wake_reason = WR_NONE;
  62. static bool slp_ck26m_on;
  63. static bool slp_chk_golden = 1;
  64. bool slp_dump_gpio = 0;
  65. static bool slp_dump_regs = 1;
  66. static bool slp_check_mtcmos_pll = 1;
  67. static u32 slp_spm_flags = {
  68. #if 0
  69. SPM_FLAG_DIS_CPU_PDN |
  70. SPM_FLAG_DIS_INFRA_PDN |
  71. SPM_FLAG_DIS_DDRPHY_PDN |
  72. SPM_FLAG_DIS_DPD |
  73. SPM_FLAG_DIS_BUS_CLOCK_OFF |
  74. SPM_FLAG_DIS_VPROC_VSRAM_DVS
  75. #else
  76. #ifdef CONFIG_MTK_ICUSB_SUPPORT
  77. SPM_FLAG_DIS_INFRA_PDN |
  78. #endif
  79. SPM_FLAG_DIS_DPD
  80. #endif
  81. };
  82. #if defined(CONFIG_ARCH_MT6755)
  83. #if SLP_SLEEP_DPIDLE_EN
  84. /* sync with mt_idle.c spm_deepidle_flags setting */
  85. static u32 slp_spm_deepidle_flags = {
  86. 0
  87. };
  88. #endif
  89. #endif
  90. /* static u32 slp_spm_data = 0; */
  91. u32 slp_spm_data = 0;
  92. #if 1
  93. static int slp_suspend_ops_valid(suspend_state_t state)
  94. {
  95. return state == PM_SUSPEND_MEM;
  96. }
  97. static int slp_suspend_ops_begin(suspend_state_t state)
  98. {
  99. /* legacy log */
  100. slp_notice("@@@@@@@@@@@@@@@@@@@@\n");
  101. slp_notice("Chip_pm_begin(%u)(%u)\n", is_cpu_pdn(slp_spm_flags),
  102. is_infra_pdn(slp_spm_flags));
  103. slp_notice("@@@@@@@@@@@@@@@@@@@@\n");
  104. slp_wake_reason = WR_NONE;
  105. return 0;
  106. }
  107. void __attribute__((weak)) mt_power_gs_dump_suspend(void)
  108. {
  109. }
  110. static int slp_suspend_ops_prepare(void)
  111. {
  112. /* legacy log */
  113. slp_notice("@@@@@@@@@@@@@@@@@@@@\n");
  114. slp_crit2("Chip_pm_prepare\n");
  115. slp_notice("@@@@@@@@@@@@@@@@@@@@\n");
  116. #ifndef CONFIG_MTK_FPGA
  117. if (slp_chk_golden)
  118. mt_power_gs_dump_suspend();
  119. #endif
  120. return 0;
  121. }
  122. #ifdef CONFIG_MTKPASR
  123. /* PASR/DPD Preliminary operations */
  124. static int slp_suspend_ops_prepare_late(void)
  125. {
  126. slp_notice("[%s]\n", __func__);
  127. mtkpasr_phaseone_ops();
  128. return 0;
  129. }
  130. static void slp_suspend_ops_wake(void)
  131. {
  132. slp_notice("[%s]\n", __func__);
  133. }
  134. /* PASR/DPD SW operations */
  135. static int enter_pasrdpd(void)
  136. {
  137. int error = 0;
  138. u32 sr = 0, dpd = 0;
  139. slp_notice("@@@@@@@@@@@@@@@@@@@@\n");
  140. slp_crit2("[%s]\n", __func__);
  141. slp_notice("@@@@@@@@@@@@@@@@@@@@\n");
  142. /* Setup SPM wakeup event firstly */
  143. spm_set_wakeup_src_check();
  144. /* Start PASR/DPD SW operations */
  145. error = pasr_enter(&sr, &dpd);
  146. if (error) {
  147. slp_crit2("[PM_WAKEUP] Failed to enter PASR!\n");
  148. } else {
  149. /* Call SPM/DPD control API */
  150. slp_crit2("MR17[0x%x] DPD[0x%x]\n", sr, dpd);
  151. /* Should configure SR */
  152. if (mtkpasr_enable_sr == 0) {
  153. sr = 0x0;
  154. slp_crit2("[%s][%d] No configuration on SR\n", __func__, __LINE__);
  155. }
  156. /* Configure PASR */
  157. enter_pasr_dpd_config((sr & 0xFF), (sr >> 0x8));
  158. /* if (mrw_error) { */
  159. /* pr_debug(KERN_ERR "[%s][%d] PM: Failed to configure MRW PASR [%d]!\n",
  160. *__FUNCTION__,__LINE__,mrw_error); */
  161. /* } */
  162. }
  163. slp_crit2("Bye [%s]\n", __func__);
  164. return error;
  165. }
  166. static void leave_pasrdpd(void)
  167. {
  168. slp_notice("@@@@@@@@@@@@@@@@@@@@\n");
  169. slp_crit2("[%s]\n", __func__);
  170. slp_notice("@@@@@@@@@@@@@@@@@@@@\n");
  171. /* Disable PASR */
  172. exit_pasr_dpd_config();
  173. slp_crit2("[%d]\n", __LINE__);
  174. /* End PASR/DPD SW operations */
  175. pasr_exit();
  176. slp_crit2("Bye [%s]\n", __func__);
  177. }
  178. #endif
  179. bool __attribute__ ((weak)) ConditionEnterSuspend(void)
  180. {
  181. return true;
  182. }
  183. #ifdef CONFIG_MTK_SYSTRACKER
  184. void __attribute__ ((weak)) systracker_enable(void)
  185. {
  186. }
  187. #endif
  188. static int slp_suspend_ops_enter(suspend_state_t state)
  189. {
  190. int ret = 0;
  191. #if SLP_SLEEP_DPIDLE_EN
  192. #ifdef CONFIG_MT_SND_SOC_6755
  193. int fm_radio_is_playing = 0;
  194. if (ConditionEnterSuspend() == true)
  195. fm_radio_is_playing = 0;
  196. else
  197. fm_radio_is_playing = 1;
  198. #endif /* CONFIG_MT_SND_SOC_6755 */
  199. #endif
  200. #ifdef CONFIG_MTKPASR
  201. /* PASR SW operations */
  202. enter_pasrdpd();
  203. #endif
  204. /* legacy log */
  205. slp_notice("@@@@@@@@@@@@@@@@@@@@\n");
  206. slp_crit2("Chip_pm_enter\n");
  207. slp_notice("@@@@@@@@@@@@@@@@@@@@\n");
  208. if (slp_dump_gpio)
  209. gpio_dump_regs();
  210. #if 0
  211. if (slp_dump_regs)
  212. slp_dump_pm_regs();
  213. #endif
  214. #if 0
  215. #ifndef CONFIG_MTK_FPGA
  216. if (slp_check_mtcmos_pll)
  217. slp_check_pm_mtcmos_pll();
  218. if (!(spm_cpusys0_can_power_down() || spm_cpusys1_can_power_down())) {
  219. slp_error("CANNOT SLEEP DUE TO CPUx PON, PWR_STATUS = 0x%x, PWR_STATUS_2ND = 0x%x\n",
  220. slp_read(PWR_STATUS), slp_read(PWR_STATUS_2ND));
  221. /* return -EPERM; */
  222. ret = -EPERM;
  223. goto LEAVE_SLEEP;
  224. }
  225. #endif
  226. #endif
  227. if (is_infra_pdn(slp_spm_flags) && !is_cpu_pdn(slp_spm_flags)) {
  228. slp_error("CANNOT SLEEP DUE TO INFRA PDN BUT CPU PON\n");
  229. ret = -EPERM;
  230. goto LEAVE_SLEEP;
  231. }
  232. if (!spm_load_firmware_status()) {
  233. slp_error("SPM FIRMWARE IS NOT READY\n");
  234. ret = -EPERM;
  235. goto LEAVE_SLEEP;
  236. }
  237. #if defined(CONFIG_ARCH_MT6755)
  238. #if SLP_SLEEP_DPIDLE_EN
  239. #ifdef CONFIG_MT_SND_SOC_6755
  240. if (slp_ck26m_on | fm_radio_is_playing)
  241. #else
  242. if (slp_ck26m_on)
  243. #endif
  244. slp_wake_reason = spm_go_to_sleep_dpidle(slp_spm_deepidle_flags, slp_spm_data);
  245. else
  246. #endif
  247. slp_wake_reason = spm_go_to_sleep(slp_spm_flags, slp_spm_data);
  248. #endif
  249. LEAVE_SLEEP:
  250. #ifdef CONFIG_MTKPASR
  251. /* PASR SW operations */
  252. leave_pasrdpd();
  253. #endif
  254. #ifndef CONFIG_MTK_FPGA
  255. #ifdef CONFIG_MTK_SYSTRACKER
  256. systracker_enable();
  257. #endif
  258. #endif
  259. return ret;
  260. }
  261. static void slp_suspend_ops_finish(void)
  262. {
  263. /* legacy log */
  264. slp_notice("@@@@@@@@@@@@@@@@@@@@\n");
  265. slp_crit2("Chip_pm_finish\n");
  266. slp_notice("@@@@@@@@@@@@@@@@@@@@\n");
  267. }
  268. static void slp_suspend_ops_end(void)
  269. {
  270. /* legacy log */
  271. slp_notice("@@@@@@@@@@@@@@@@@@@@\n");
  272. slp_notice("Chip_pm_end\n");
  273. slp_notice("@@@@@@@@@@@@@@@@@@@@\n");
  274. }
  275. static const struct platform_suspend_ops slp_suspend_ops = {
  276. .valid = slp_suspend_ops_valid,
  277. .begin = slp_suspend_ops_begin,
  278. .prepare = slp_suspend_ops_prepare,
  279. .enter = slp_suspend_ops_enter,
  280. .finish = slp_suspend_ops_finish,
  281. .end = slp_suspend_ops_end,
  282. #ifdef CONFIG_MTKPASR
  283. .prepare_late = slp_suspend_ops_prepare_late,
  284. .wake = slp_suspend_ops_wake,
  285. #endif
  286. };
  287. #endif
  288. __attribute__ ((weak))
  289. int spm_set_dpidle_wakesrc(u32 wakesrc, bool enable, bool replace)
  290. {
  291. return 0;
  292. }
  293. /*
  294. * wakesrc : WAKE_SRC_XXX
  295. * enable : enable or disable @wakesrc
  296. * ck26m_on: if true, mean @wakesrc needs 26M to work
  297. */
  298. int slp_set_wakesrc(u32 wakesrc, bool enable, bool ck26m_on)
  299. {
  300. int r;
  301. unsigned long flags;
  302. slp_notice("wakesrc = 0x%x, enable = %u, ck26m_on = %u\n", wakesrc, enable, ck26m_on);
  303. #if SLP_REPLACE_DEF_WAKESRC
  304. if (wakesrc & WAKE_SRC_CFG_KEY)
  305. #else
  306. if (!(wakesrc & WAKE_SRC_CFG_KEY))
  307. #endif
  308. return -EPERM;
  309. spin_lock_irqsave(&slp_lock, flags);
  310. #if SLP_REPLACE_DEF_WAKESRC
  311. if (ck26m_on)
  312. r = spm_set_dpidle_wakesrc(wakesrc, enable, true);
  313. else
  314. r = spm_set_sleep_wakesrc(wakesrc, enable, true);
  315. #else
  316. if (ck26m_on)
  317. r = spm_set_dpidle_wakesrc(wakesrc & ~WAKE_SRC_CFG_KEY, enable, false);
  318. else
  319. r = spm_set_sleep_wakesrc(wakesrc & ~WAKE_SRC_CFG_KEY, enable, false);
  320. #endif
  321. if (!r)
  322. slp_ck26m_on = ck26m_on;
  323. spin_unlock_irqrestore(&slp_lock, flags);
  324. return r;
  325. }
  326. wake_reason_t slp_get_wake_reason(void)
  327. {
  328. return slp_wake_reason;
  329. }
  330. bool slp_will_infra_pdn(void)
  331. {
  332. return is_infra_pdn(slp_spm_flags);
  333. }
  334. void slp_module_init(void)
  335. {
  336. spm_output_sleep_option();
  337. slp_notice("SLEEP_DPIDLE_EN:%d, REPLACE_DEF_WAKESRC:%d, SUSPEND_LOG_EN:%d\n",
  338. SLP_SLEEP_DPIDLE_EN, SLP_REPLACE_DEF_WAKESRC, SLP_SUSPEND_LOG_EN);
  339. suspend_set_ops(&slp_suspend_ops);
  340. #if SLP_SUSPEND_LOG_EN
  341. console_suspend_enabled = 0;
  342. #endif
  343. #ifndef CONFIG_MTK_FPGA
  344. spm_set_suspned_pcm_init_flag(&slp_spm_flags);
  345. #endif
  346. }
  347. /*
  348. #ifdef CONFIG_MTK_FPGA
  349. static int __init spm_fpga_module_init(void)
  350. {
  351. spm_module_init();
  352. slp_module_init();
  353. return 0;
  354. }
  355. arch_initcall(spm_fpga_module_init);
  356. #else
  357. #endif
  358. */
  359. module_param(slp_ck26m_on, bool, 0644);
  360. module_param(slp_spm_flags, uint, 0644);
  361. module_param(slp_chk_golden, bool, 0644);
  362. module_param(slp_dump_gpio, bool, 0644);
  363. module_param(slp_dump_regs, bool, 0644);
  364. module_param(slp_check_mtcmos_pll, bool, 0644);
  365. MODULE_DESCRIPTION("Sleep Driver v0.1");