pm-pxa910.c 6.9 KB

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