pm-mmp2.c 6.1 KB

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