pm-mmp2.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * MMP2 Power Management Routines
  4. *
  5. * (C) Copyright 2012 Marvell International Ltd.
  6. * All Rights Reserved
  7. */
  8. #include <linux/kernel.h>
  9. #include <linux/errno.h>
  10. #include <linux/err.h>
  11. #include <linux/time.h>
  12. #include <linux/delay.h>
  13. #include <linux/suspend.h>
  14. #include <linux/irq.h>
  15. #include <linux/io.h>
  16. #include <linux/interrupt.h>
  17. #include <asm/mach-types.h>
  18. #include <linux/soc/mmp/cputype.h>
  19. #include "addr-map.h"
  20. #include "pm-mmp2.h"
  21. #include "regs-icu.h"
  22. #include "irqs.h"
  23. int mmp2_set_wake(struct irq_data *d, unsigned int on)
  24. {
  25. unsigned long data = 0;
  26. int irq = d->irq;
  27. /* enable wakeup sources */
  28. switch (irq) {
  29. case IRQ_MMP2_RTC:
  30. case IRQ_MMP2_RTC_ALARM:
  31. data = MPMU_WUCRM_PJ_WAKEUP(4) | MPMU_WUCRM_PJ_RTC_ALARM;
  32. break;
  33. case IRQ_MMP2_PMIC:
  34. data = MPMU_WUCRM_PJ_WAKEUP(7);
  35. break;
  36. case IRQ_MMP2_MMC2:
  37. /* mmc use WAKEUP2, same as GPIO wakeup source */
  38. data = MPMU_WUCRM_PJ_WAKEUP(2);
  39. break;
  40. }
  41. if (on) {
  42. if (data) {
  43. data |= __raw_readl(MPMU_WUCRM_PJ);
  44. __raw_writel(data, MPMU_WUCRM_PJ);
  45. }
  46. } else {
  47. if (data) {
  48. data = ~data & __raw_readl(MPMU_WUCRM_PJ);
  49. __raw_writel(data, MPMU_WUCRM_PJ);
  50. }
  51. }
  52. return 0;
  53. }
  54. static void pm_scu_clk_disable(void)
  55. {
  56. unsigned int val;
  57. /* close AXI fabric clock gate */
  58. __raw_writel(0x0, CIU_REG(0x64));
  59. __raw_writel(0x0, CIU_REG(0x68));
  60. /* close MCB master clock gate */
  61. val = __raw_readl(CIU_REG(0x1c));
  62. val |= 0xf0;
  63. __raw_writel(val, CIU_REG(0x1c));
  64. return ;
  65. }
  66. static void pm_scu_clk_enable(void)
  67. {
  68. unsigned int val;
  69. /* open AXI fabric clock gate */
  70. __raw_writel(0x03003003, CIU_REG(0x64));
  71. __raw_writel(0x00303030, CIU_REG(0x68));
  72. /* open MCB master clock gate */
  73. val = __raw_readl(CIU_REG(0x1c));
  74. val &= ~(0xf0);
  75. __raw_writel(val, CIU_REG(0x1c));
  76. return ;
  77. }
  78. static void pm_mpmu_clk_disable(void)
  79. {
  80. /*
  81. * disable clocks in MPMU_CGR_PJ register
  82. * except clock for APMU_PLL1, APMU_PLL1_2 and AP_26M
  83. */
  84. __raw_writel(0x0000a010, MPMU_CGR_PJ);
  85. }
  86. static void pm_mpmu_clk_enable(void)
  87. {
  88. unsigned int val;
  89. __raw_writel(0xdffefffe, MPMU_CGR_PJ);
  90. val = __raw_readl(MPMU_PLL2_CTRL1);
  91. val |= (1 << 29);
  92. __raw_writel(val, MPMU_PLL2_CTRL1);
  93. return ;
  94. }
  95. void mmp2_pm_enter_lowpower_mode(int state)
  96. {
  97. uint32_t idle_cfg, apcr;
  98. idle_cfg = __raw_readl(APMU_PJ_IDLE_CFG);
  99. apcr = __raw_readl(MPMU_PCR_PJ);
  100. apcr &= ~(MPMU_PCR_PJ_SLPEN | MPMU_PCR_PJ_DDRCORSD | MPMU_PCR_PJ_APBSD
  101. | MPMU_PCR_PJ_AXISD | MPMU_PCR_PJ_VCTCXOSD | (1 << 13));
  102. idle_cfg &= ~APMU_PJ_IDLE_CFG_PJ_IDLE;
  103. switch (state) {
  104. case POWER_MODE_SYS_SLEEP:
  105. apcr |= MPMU_PCR_PJ_SLPEN; /* set the SLPEN bit */
  106. apcr |= MPMU_PCR_PJ_VCTCXOSD; /* set VCTCXOSD */
  107. fallthrough;
  108. case POWER_MODE_CHIP_SLEEP:
  109. apcr |= MPMU_PCR_PJ_SLPEN;
  110. fallthrough;
  111. case POWER_MODE_APPS_SLEEP:
  112. apcr |= MPMU_PCR_PJ_APBSD; /* set APBSD */
  113. fallthrough;
  114. case POWER_MODE_APPS_IDLE:
  115. apcr |= MPMU_PCR_PJ_AXISD; /* set AXISDD bit */
  116. apcr |= MPMU_PCR_PJ_DDRCORSD; /* set DDRCORSD bit */
  117. idle_cfg |= APMU_PJ_IDLE_CFG_PJ_PWRDWN; /* PJ power down */
  118. apcr |= MPMU_PCR_PJ_SPSD;
  119. fallthrough;
  120. case POWER_MODE_CORE_EXTIDLE:
  121. idle_cfg |= APMU_PJ_IDLE_CFG_PJ_IDLE; /* set the IDLE bit */
  122. idle_cfg &= ~APMU_PJ_IDLE_CFG_ISO_MODE_CNTRL_MASK;
  123. idle_cfg |= APMU_PJ_IDLE_CFG_PWR_SW(3)
  124. | APMU_PJ_IDLE_CFG_L2_PWR_SW;
  125. break;
  126. case POWER_MODE_CORE_INTIDLE:
  127. apcr &= ~MPMU_PCR_PJ_SPSD;
  128. break;
  129. }
  130. /* set reserve bits */
  131. apcr |= (1 << 30) | (1 << 25);
  132. /* finally write the registers back */
  133. __raw_writel(idle_cfg, APMU_PJ_IDLE_CFG);
  134. __raw_writel(apcr, MPMU_PCR_PJ); /* 0xfe086000 */
  135. }
  136. static int mmp2_pm_enter(suspend_state_t state)
  137. {
  138. int temp;
  139. temp = __raw_readl(MMP2_ICU_INT4_MASK);
  140. if (temp & (1 << 1)) {
  141. printk(KERN_ERR "%s: PMIC interrupt is handling\n", __func__);
  142. return -EAGAIN;
  143. }
  144. temp = __raw_readl(APMU_SRAM_PWR_DWN);
  145. temp |= ((1 << 19) | (1 << 18));
  146. __raw_writel(temp, APMU_SRAM_PWR_DWN);
  147. pm_mpmu_clk_disable();
  148. pm_scu_clk_disable();
  149. printk(KERN_INFO "%s: before suspend\n", __func__);
  150. cpu_do_idle();
  151. printk(KERN_INFO "%s: after suspend\n", __func__);
  152. pm_mpmu_clk_enable(); /* enable clocks in MPMU */
  153. pm_scu_clk_enable(); /* enable clocks in SCU */
  154. return 0;
  155. }
  156. /*
  157. * Called after processes are frozen, but before we shut down devices.
  158. */
  159. static int mmp2_pm_prepare(void)
  160. {
  161. mmp2_pm_enter_lowpower_mode(POWER_MODE_SYS_SLEEP);
  162. return 0;
  163. }
  164. /*
  165. * Called after devices are re-setup, but before processes are thawed.
  166. */
  167. static void mmp2_pm_finish(void)
  168. {
  169. mmp2_pm_enter_lowpower_mode(POWER_MODE_CORE_INTIDLE);
  170. }
  171. static int mmp2_pm_valid(suspend_state_t state)
  172. {
  173. return ((state == PM_SUSPEND_STANDBY) || (state == PM_SUSPEND_MEM));
  174. }
  175. /*
  176. * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
  177. */
  178. static const struct platform_suspend_ops mmp2_pm_ops = {
  179. .valid = mmp2_pm_valid,
  180. .prepare = mmp2_pm_prepare,
  181. .enter = mmp2_pm_enter,
  182. .finish = mmp2_pm_finish,
  183. };
  184. static int __init mmp2_pm_init(void)
  185. {
  186. uint32_t apcr;
  187. if (!cpu_is_mmp2())
  188. return -EIO;
  189. suspend_set_ops(&mmp2_pm_ops);
  190. /*
  191. * Set bit 0, Slow clock Select 32K clock input instead of VCXO
  192. * VCXO is chosen by default, which would be disabled in suspend
  193. */
  194. __raw_writel(0x5, MPMU_SCCR);
  195. /*
  196. * Clear bit 23 of CIU_CPU_CONF
  197. * direct PJ4 to DDR access through Memory Controller slow queue
  198. * fast queue has issue and cause lcd will flick
  199. */
  200. __raw_writel(__raw_readl(CIU_REG(0x8)) & ~(0x1 << 23), CIU_REG(0x8));
  201. /* Clear default low power control bit */
  202. apcr = __raw_readl(MPMU_PCR_PJ);
  203. apcr &= ~(MPMU_PCR_PJ_SLPEN | MPMU_PCR_PJ_DDRCORSD
  204. | MPMU_PCR_PJ_APBSD | MPMU_PCR_PJ_AXISD | 1 << 13);
  205. __raw_writel(apcr, MPMU_PCR_PJ);
  206. return 0;
  207. }
  208. late_initcall(mmp2_pm_init);