pm-pxa910.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. /*
  2. * PXA910 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 2009 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/interrupt.h>
  17. #include <linux/io.h>
  18. #include <linux/irq.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-pxa910.h>
  24. #include <mach/regs-icu.h>
  25. #include <mach/irqs.h>
  26. int pxa910_set_wake(struct irq_data *data, unsigned int on)
  27. {
  28. int irq = data->irq;
  29. struct irq_desc *desc = irq_to_desc(data->irq);
  30. uint32_t awucrm = 0, apcr = 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. /* setting wakeup sources */
  43. switch (irq) {
  44. /* wakeup line 2 */
  45. case IRQ_PXA910_AP_GPIO:
  46. awucrm = MPMU_AWUCRM_WAKEUP(2);
  47. apcr |= MPMU_APCR_SLPWP2;
  48. break;
  49. /* wakeup line 3 */
  50. case IRQ_PXA910_KEYPAD:
  51. awucrm = MPMU_AWUCRM_WAKEUP(3) | MPMU_AWUCRM_KEYPRESS;
  52. apcr |= MPMU_APCR_SLPWP3;
  53. break;
  54. case IRQ_PXA910_ROTARY:
  55. awucrm = MPMU_AWUCRM_WAKEUP(3) | MPMU_AWUCRM_NEWROTARY;
  56. apcr |= MPMU_APCR_SLPWP3;
  57. break;
  58. case IRQ_PXA910_TRACKBALL:
  59. awucrm = MPMU_AWUCRM_WAKEUP(3) | MPMU_AWUCRM_TRACKBALL;
  60. apcr |= MPMU_APCR_SLPWP3;
  61. break;
  62. /* wakeup line 4 */
  63. case IRQ_PXA910_AP1_TIMER1:
  64. awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP1_TIMER_1;
  65. apcr |= MPMU_APCR_SLPWP4;
  66. break;
  67. case IRQ_PXA910_AP1_TIMER2:
  68. awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP1_TIMER_2;
  69. apcr |= MPMU_APCR_SLPWP4;
  70. break;
  71. case IRQ_PXA910_AP1_TIMER3:
  72. awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP1_TIMER_3;
  73. apcr |= MPMU_APCR_SLPWP4;
  74. break;
  75. case IRQ_PXA910_AP2_TIMER1:
  76. awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP2_TIMER_1;
  77. apcr |= MPMU_APCR_SLPWP4;
  78. break;
  79. case IRQ_PXA910_AP2_TIMER2:
  80. awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP2_TIMER_2;
  81. apcr |= MPMU_APCR_SLPWP4;
  82. break;
  83. case IRQ_PXA910_AP2_TIMER3:
  84. awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_AP2_TIMER_3;
  85. apcr |= MPMU_APCR_SLPWP4;
  86. break;
  87. case IRQ_PXA910_RTC_ALARM:
  88. awucrm = MPMU_AWUCRM_WAKEUP(4) | MPMU_AWUCRM_RTC_ALARM;
  89. apcr |= MPMU_APCR_SLPWP4;
  90. break;
  91. /* wakeup line 5 */
  92. case IRQ_PXA910_USB1:
  93. case IRQ_PXA910_USB2:
  94. awucrm = MPMU_AWUCRM_WAKEUP(5);
  95. apcr |= MPMU_APCR_SLPWP5;
  96. break;
  97. /* wakeup line 6 */
  98. case IRQ_PXA910_MMC:
  99. awucrm = MPMU_AWUCRM_WAKEUP(6)
  100. | MPMU_AWUCRM_SDH1
  101. | MPMU_AWUCRM_SDH2;
  102. apcr |= MPMU_APCR_SLPWP6;
  103. break;
  104. /* wakeup line 7 */
  105. case IRQ_PXA910_PMIC_INT:
  106. awucrm = MPMU_AWUCRM_WAKEUP(7);
  107. apcr |= MPMU_APCR_SLPWP7;
  108. break;
  109. default:
  110. if (irq >= IRQ_GPIO_START && irq < IRQ_BOARD_START) {
  111. awucrm = MPMU_AWUCRM_WAKEUP(2);
  112. apcr |= MPMU_APCR_SLPWP2;
  113. } else
  114. printk(KERN_ERR "Error: no defined wake up source irq: %d\n",
  115. irq);
  116. }
  117. if (on) {
  118. if (awucrm) {
  119. awucrm |= __raw_readl(MPMU_AWUCRM);
  120. __raw_writel(awucrm, MPMU_AWUCRM);
  121. }
  122. if (apcr) {
  123. apcr = ~apcr & __raw_readl(MPMU_APCR);
  124. __raw_writel(apcr, MPMU_APCR);
  125. }
  126. } else {
  127. if (awucrm) {
  128. awucrm = ~awucrm & __raw_readl(MPMU_AWUCRM);
  129. __raw_writel(awucrm, MPMU_AWUCRM);
  130. }
  131. if (apcr) {
  132. apcr |= __raw_readl(MPMU_APCR);
  133. __raw_writel(apcr, MPMU_APCR);
  134. }
  135. }
  136. return 0;
  137. }
  138. void pxa910_pm_enter_lowpower_mode(int state)
  139. {
  140. uint32_t idle_cfg, apcr;
  141. idle_cfg = __raw_readl(APMU_MOH_IDLE_CFG);
  142. apcr = __raw_readl(MPMU_APCR);
  143. apcr &= ~(MPMU_APCR_DDRCORSD | MPMU_APCR_APBSD | MPMU_APCR_AXISD
  144. | MPMU_APCR_VCTCXOSD | MPMU_APCR_STBYEN);
  145. idle_cfg &= ~(APMU_MOH_IDLE_CFG_MOH_IDLE
  146. | APMU_MOH_IDLE_CFG_MOH_PWRDWN);
  147. switch (state) {
  148. case POWER_MODE_UDR:
  149. /* only shutdown APB in UDR */
  150. apcr |= MPMU_APCR_STBYEN | MPMU_APCR_APBSD;
  151. /* fall through */
  152. case POWER_MODE_SYS_SLEEP:
  153. apcr |= MPMU_APCR_SLPEN; /* set the SLPEN bit */
  154. apcr |= MPMU_APCR_VCTCXOSD; /* set VCTCXOSD */
  155. /* fall through */
  156. case POWER_MODE_APPS_SLEEP:
  157. apcr |= MPMU_APCR_DDRCORSD; /* set DDRCORSD */
  158. /* fall through */
  159. case POWER_MODE_APPS_IDLE:
  160. apcr |= MPMU_APCR_AXISD; /* set AXISDD bit */
  161. /* fall through */
  162. case POWER_MODE_CORE_EXTIDLE:
  163. idle_cfg |= APMU_MOH_IDLE_CFG_MOH_IDLE;
  164. idle_cfg |= APMU_MOH_IDLE_CFG_MOH_PWRDWN;
  165. idle_cfg |= APMU_MOH_IDLE_CFG_MOH_PWR_SW(3)
  166. | APMU_MOH_IDLE_CFG_MOH_L2_PWR_SW(3);
  167. /* fall through */
  168. case POWER_MODE_CORE_INTIDLE:
  169. break;
  170. }
  171. /* program the memory controller hardware sleep type and auto wakeup */
  172. idle_cfg |= APMU_MOH_IDLE_CFG_MOH_DIS_MC_SW_REQ;
  173. idle_cfg |= APMU_MOH_IDLE_CFG_MOH_MC_WAKE_EN;
  174. __raw_writel(0x0, APMU_MC_HW_SLP_TYPE); /* auto refresh */
  175. /* set DSPSD, DTCMSD, BBSD, MSASLPEN */
  176. apcr |= MPMU_APCR_DSPSD | MPMU_APCR_DTCMSD | MPMU_APCR_BBSD
  177. | MPMU_APCR_MSASLPEN;
  178. /*always set SLEPEN bit mainly for MSA*/
  179. apcr |= MPMU_APCR_SLPEN;
  180. /* finally write the registers back */
  181. __raw_writel(idle_cfg, APMU_MOH_IDLE_CFG);
  182. __raw_writel(apcr, MPMU_APCR);
  183. }
  184. static int pxa910_pm_enter(suspend_state_t state)
  185. {
  186. unsigned int idle_cfg, reg = 0;
  187. /*pmic thread not completed,exit;otherwise system can't be waked up*/
  188. reg = __raw_readl(ICU_INT_CONF(IRQ_PXA910_PMIC_INT));
  189. if ((reg & 0x3) == 0)
  190. return -EAGAIN;
  191. idle_cfg = __raw_readl(APMU_MOH_IDLE_CFG);
  192. idle_cfg |= APMU_MOH_IDLE_CFG_MOH_PWRDWN
  193. | APMU_MOH_IDLE_CFG_MOH_SRAM_PWRDWN;
  194. __raw_writel(idle_cfg, APMU_MOH_IDLE_CFG);
  195. /* disable L2 */
  196. outer_disable();
  197. /* wait for l2 idle */
  198. while (!(readl(CIU_REG(0x8)) & (1 << 16)))
  199. udelay(1);
  200. cpu_do_idle();
  201. /* enable L2 */
  202. outer_resume();
  203. /* wait for l2 idle */
  204. while (!(readl(CIU_REG(0x8)) & (1 << 16)))
  205. udelay(1);
  206. idle_cfg = __raw_readl(APMU_MOH_IDLE_CFG);
  207. idle_cfg &= ~(APMU_MOH_IDLE_CFG_MOH_PWRDWN
  208. | APMU_MOH_IDLE_CFG_MOH_SRAM_PWRDWN);
  209. __raw_writel(idle_cfg, APMU_MOH_IDLE_CFG);
  210. return 0;
  211. }
  212. /*
  213. * Called after processes are frozen, but before we shut down devices.
  214. */
  215. static int pxa910_pm_prepare(void)
  216. {
  217. pxa910_pm_enter_lowpower_mode(POWER_MODE_UDR);
  218. return 0;
  219. }
  220. /*
  221. * Called after devices are re-setup, but before processes are thawed.
  222. */
  223. static void pxa910_pm_finish(void)
  224. {
  225. pxa910_pm_enter_lowpower_mode(POWER_MODE_CORE_INTIDLE);
  226. }
  227. static int pxa910_pm_valid(suspend_state_t state)
  228. {
  229. return ((state == PM_SUSPEND_STANDBY) || (state == PM_SUSPEND_MEM));
  230. }
  231. static const struct platform_suspend_ops pxa910_pm_ops = {
  232. .valid = pxa910_pm_valid,
  233. .prepare = pxa910_pm_prepare,
  234. .enter = pxa910_pm_enter,
  235. .finish = pxa910_pm_finish,
  236. };
  237. static int __init pxa910_pm_init(void)
  238. {
  239. uint32_t awucrm = 0;
  240. if (!cpu_is_pxa910())
  241. return -EIO;
  242. suspend_set_ops(&pxa910_pm_ops);
  243. /* Set the following bits for MMP3 playback with VCTXO on */
  244. __raw_writel(__raw_readl(APMU_SQU_CLK_GATE_CTRL) | (1 << 30),
  245. APMU_SQU_CLK_GATE_CTRL);
  246. __raw_writel(__raw_readl(MPMU_FCCR) | (1 << 28), MPMU_FCCR);
  247. awucrm |= MPMU_AWUCRM_AP_ASYNC_INT | MPMU_AWUCRM_AP_FULL_IDLE;
  248. __raw_writel(awucrm, MPMU_AWUCRM);
  249. return 0;
  250. }
  251. late_initcall(pxa910_pm_init);