pm-imx6q.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /*
  2. * Copyright 2011-2013 Freescale Semiconductor, Inc.
  3. * Copyright 2011 Linaro Ltd.
  4. *
  5. * The code contained herein is licensed under the GNU General Public
  6. * License. You may obtain a copy of the GNU General Public License
  7. * Version 2 or later at the following locations:
  8. *
  9. * http://www.opensource.org/licenses/gpl-license.html
  10. * http://www.gnu.org/copyleft/gpl.html
  11. */
  12. #include <linux/delay.h>
  13. #include <linux/init.h>
  14. #include <linux/io.h>
  15. #include <linux/of.h>
  16. #include <linux/of_address.h>
  17. #include <linux/suspend.h>
  18. #include <asm/cacheflush.h>
  19. #include <asm/proc-fns.h>
  20. #include <asm/suspend.h>
  21. #include <asm/hardware/cache-l2x0.h>
  22. #include "common.h"
  23. #include "hardware.h"
  24. #define CCR 0x0
  25. #define BM_CCR_WB_COUNT (0x7 << 16)
  26. #define BM_CCR_RBC_BYPASS_COUNT (0x3f << 21)
  27. #define BM_CCR_RBC_EN (0x1 << 27)
  28. #define CLPCR 0x54
  29. #define BP_CLPCR_LPM 0
  30. #define BM_CLPCR_LPM (0x3 << 0)
  31. #define BM_CLPCR_BYPASS_PMIC_READY (0x1 << 2)
  32. #define BM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5)
  33. #define BM_CLPCR_SBYOS (0x1 << 6)
  34. #define BM_CLPCR_DIS_REF_OSC (0x1 << 7)
  35. #define BM_CLPCR_VSTBY (0x1 << 8)
  36. #define BP_CLPCR_STBY_COUNT 9
  37. #define BM_CLPCR_STBY_COUNT (0x3 << 9)
  38. #define BM_CLPCR_COSC_PWRDOWN (0x1 << 11)
  39. #define BM_CLPCR_WB_PER_AT_LPM (0x1 << 16)
  40. #define BM_CLPCR_WB_CORE_AT_LPM (0x1 << 17)
  41. #define BM_CLPCR_BYP_MMDC_CH0_LPM_HS (0x1 << 19)
  42. #define BM_CLPCR_BYP_MMDC_CH1_LPM_HS (0x1 << 21)
  43. #define BM_CLPCR_MASK_CORE0_WFI (0x1 << 22)
  44. #define BM_CLPCR_MASK_CORE1_WFI (0x1 << 23)
  45. #define BM_CLPCR_MASK_CORE2_WFI (0x1 << 24)
  46. #define BM_CLPCR_MASK_CORE3_WFI (0x1 << 25)
  47. #define BM_CLPCR_MASK_SCU_IDLE (0x1 << 26)
  48. #define BM_CLPCR_MASK_L2CC_IDLE (0x1 << 27)
  49. #define CGPR 0x64
  50. #define BM_CGPR_CHICKEN_BIT (0x1 << 17)
  51. static void __iomem *ccm_base;
  52. void imx6q_set_chicken_bit(void)
  53. {
  54. u32 val = readl_relaxed(ccm_base + CGPR);
  55. val |= BM_CGPR_CHICKEN_BIT;
  56. writel_relaxed(val, ccm_base + CGPR);
  57. }
  58. static void imx6q_enable_rbc(bool enable)
  59. {
  60. u32 val;
  61. /*
  62. * need to mask all interrupts in GPC before
  63. * operating RBC configurations
  64. */
  65. imx_gpc_mask_all();
  66. /* configure RBC enable bit */
  67. val = readl_relaxed(ccm_base + CCR);
  68. val &= ~BM_CCR_RBC_EN;
  69. val |= enable ? BM_CCR_RBC_EN : 0;
  70. writel_relaxed(val, ccm_base + CCR);
  71. /* configure RBC count */
  72. val = readl_relaxed(ccm_base + CCR);
  73. val &= ~BM_CCR_RBC_BYPASS_COUNT;
  74. val |= enable ? BM_CCR_RBC_BYPASS_COUNT : 0;
  75. writel(val, ccm_base + CCR);
  76. /*
  77. * need to delay at least 2 cycles of CKIL(32K)
  78. * due to hardware design requirement, which is
  79. * ~61us, here we use 65us for safe
  80. */
  81. udelay(65);
  82. /* restore GPC interrupt mask settings */
  83. imx_gpc_restore_all();
  84. }
  85. static void imx6q_enable_wb(bool enable)
  86. {
  87. u32 val;
  88. /* configure well bias enable bit */
  89. val = readl_relaxed(ccm_base + CLPCR);
  90. val &= ~BM_CLPCR_WB_PER_AT_LPM;
  91. val |= enable ? BM_CLPCR_WB_PER_AT_LPM : 0;
  92. writel_relaxed(val, ccm_base + CLPCR);
  93. /* configure well bias count */
  94. val = readl_relaxed(ccm_base + CCR);
  95. val &= ~BM_CCR_WB_COUNT;
  96. val |= enable ? BM_CCR_WB_COUNT : 0;
  97. writel_relaxed(val, ccm_base + CCR);
  98. }
  99. int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
  100. {
  101. u32 val = readl_relaxed(ccm_base + CLPCR);
  102. val &= ~BM_CLPCR_LPM;
  103. switch (mode) {
  104. case WAIT_CLOCKED:
  105. break;
  106. case WAIT_UNCLOCKED:
  107. val |= 0x1 << BP_CLPCR_LPM;
  108. val |= BM_CLPCR_ARM_CLK_DIS_ON_LPM;
  109. break;
  110. case STOP_POWER_ON:
  111. val |= 0x2 << BP_CLPCR_LPM;
  112. break;
  113. case WAIT_UNCLOCKED_POWER_OFF:
  114. val |= 0x1 << BP_CLPCR_LPM;
  115. val &= ~BM_CLPCR_VSTBY;
  116. val &= ~BM_CLPCR_SBYOS;
  117. break;
  118. case STOP_POWER_OFF:
  119. val |= 0x2 << BP_CLPCR_LPM;
  120. val |= 0x3 << BP_CLPCR_STBY_COUNT;
  121. val |= BM_CLPCR_VSTBY;
  122. val |= BM_CLPCR_SBYOS;
  123. break;
  124. default:
  125. return -EINVAL;
  126. }
  127. writel_relaxed(val, ccm_base + CLPCR);
  128. return 0;
  129. }
  130. static int imx6q_suspend_finish(unsigned long val)
  131. {
  132. cpu_do_idle();
  133. return 0;
  134. }
  135. static int imx6q_pm_enter(suspend_state_t state)
  136. {
  137. switch (state) {
  138. case PM_SUSPEND_MEM:
  139. imx6q_set_lpm(STOP_POWER_OFF);
  140. imx6q_enable_wb(true);
  141. imx6q_enable_rbc(true);
  142. imx_gpc_pre_suspend();
  143. imx_anatop_pre_suspend();
  144. imx_set_cpu_jump(0, v7_cpu_resume);
  145. /* Zzz ... */
  146. cpu_suspend(0, imx6q_suspend_finish);
  147. imx_smp_prepare();
  148. imx_anatop_post_resume();
  149. imx_gpc_post_resume();
  150. imx6q_enable_rbc(false);
  151. imx6q_enable_wb(false);
  152. imx6q_set_lpm(WAIT_CLOCKED);
  153. break;
  154. default:
  155. return -EINVAL;
  156. }
  157. return 0;
  158. }
  159. static const struct platform_suspend_ops imx6q_pm_ops = {
  160. .enter = imx6q_pm_enter,
  161. .valid = suspend_valid_only_mem,
  162. };
  163. void __init imx6q_pm_set_ccm_base(void __iomem *base)
  164. {
  165. ccm_base = base;
  166. }
  167. void __init imx6q_pm_init(void)
  168. {
  169. WARN_ON(!ccm_base);
  170. /* Set initial power mode */
  171. imx6q_set_lpm(WAIT_CLOCKED);
  172. suspend_set_ops(&imx6q_pm_ops);
  173. }