pm-pxa910.c 6.7 KB

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