powerdomain33xx.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. * AM33XX Powerdomain control
  3. *
  4. * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
  5. *
  6. * Derived from mach-omap2/powerdomain44xx.c written by Rajendra Nayak
  7. * <rnayak@ti.com>
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License as
  11. * published by the Free Software Foundation version 2.
  12. *
  13. * This program is distributed "as is" WITHOUT ANY WARRANTY of any
  14. * kind, whether express or implied; without even the implied warranty
  15. * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. */
  18. #include <linux/io.h>
  19. #include <linux/errno.h>
  20. #include <linux/delay.h>
  21. #include <plat/prcm.h>
  22. #include "powerdomain.h"
  23. #include "prm33xx.h"
  24. #include "prm-regbits-33xx.h"
  25. static int am33xx_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
  26. {
  27. am33xx_prm_rmw_reg_bits(OMAP_POWERSTATE_MASK,
  28. (pwrst << OMAP_POWERSTATE_SHIFT),
  29. pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
  30. return 0;
  31. }
  32. static int am33xx_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
  33. {
  34. u32 v;
  35. v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
  36. v &= OMAP_POWERSTATE_MASK;
  37. v >>= OMAP_POWERSTATE_SHIFT;
  38. return v;
  39. }
  40. static int am33xx_pwrdm_read_pwrst(struct powerdomain *pwrdm)
  41. {
  42. u32 v;
  43. v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
  44. v &= OMAP_POWERSTATEST_MASK;
  45. v >>= OMAP_POWERSTATEST_SHIFT;
  46. return v;
  47. }
  48. static int am33xx_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
  49. {
  50. u32 v;
  51. v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
  52. v &= AM33XX_LASTPOWERSTATEENTERED_MASK;
  53. v >>= AM33XX_LASTPOWERSTATEENTERED_SHIFT;
  54. return v;
  55. }
  56. static int am33xx_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
  57. {
  58. am33xx_prm_rmw_reg_bits(AM33XX_LOWPOWERSTATECHANGE_MASK,
  59. (1 << AM33XX_LOWPOWERSTATECHANGE_SHIFT),
  60. pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
  61. return 0;
  62. }
  63. static int am33xx_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
  64. {
  65. am33xx_prm_rmw_reg_bits(AM33XX_LASTPOWERSTATEENTERED_MASK,
  66. AM33XX_LASTPOWERSTATEENTERED_MASK,
  67. pwrdm->prcm_offs, pwrdm->pwrstst_offs);
  68. return 0;
  69. }
  70. static int am33xx_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
  71. {
  72. u32 m;
  73. m = pwrdm->logicretstate_mask;
  74. if (!m)
  75. return -EINVAL;
  76. am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
  77. pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
  78. return 0;
  79. }
  80. static int am33xx_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
  81. {
  82. u32 v;
  83. v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
  84. v &= AM33XX_LOGICSTATEST_MASK;
  85. v >>= AM33XX_LOGICSTATEST_SHIFT;
  86. return v;
  87. }
  88. static int am33xx_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
  89. {
  90. u32 v, m;
  91. m = pwrdm->logicretstate_mask;
  92. if (!m)
  93. return -EINVAL;
  94. v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
  95. v &= m;
  96. v >>= __ffs(m);
  97. return v;
  98. }
  99. static int am33xx_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
  100. u8 pwrst)
  101. {
  102. u32 m;
  103. m = pwrdm->mem_on_mask[bank];
  104. if (!m)
  105. return -EINVAL;
  106. am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
  107. pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
  108. return 0;
  109. }
  110. static int am33xx_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
  111. u8 pwrst)
  112. {
  113. u32 m;
  114. m = pwrdm->mem_ret_mask[bank];
  115. if (!m)
  116. return -EINVAL;
  117. am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
  118. pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
  119. return 0;
  120. }
  121. static int am33xx_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
  122. {
  123. u32 m, v;
  124. m = pwrdm->mem_pwrst_mask[bank];
  125. if (!m)
  126. return -EINVAL;
  127. v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
  128. v &= m;
  129. v >>= __ffs(m);
  130. return v;
  131. }
  132. static int am33xx_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
  133. {
  134. u32 m, v;
  135. m = pwrdm->mem_retst_mask[bank];
  136. if (!m)
  137. return -EINVAL;
  138. v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
  139. v &= m;
  140. v >>= __ffs(m);
  141. return v;
  142. }
  143. static int am33xx_pwrdm_wait_transition(struct powerdomain *pwrdm)
  144. {
  145. u32 c = 0;
  146. /*
  147. * REVISIT: pwrdm_wait_transition() may be better implemented
  148. * via a callback and a periodic timer check -- how long do we expect
  149. * powerdomain transitions to take?
  150. */
  151. /* XXX Is this udelay() value meaningful? */
  152. while ((am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs)
  153. & OMAP_INTRANSITION_MASK) &&
  154. (c++ < PWRDM_TRANSITION_BAILOUT))
  155. udelay(1);
  156. if (c > PWRDM_TRANSITION_BAILOUT) {
  157. pr_err("powerdomain: %s: waited too long to complete transition\n",
  158. pwrdm->name);
  159. return -EAGAIN;
  160. }
  161. pr_debug("powerdomain: completed transition in %d loops\n", c);
  162. return 0;
  163. }
  164. struct pwrdm_ops am33xx_pwrdm_operations = {
  165. .pwrdm_set_next_pwrst = am33xx_pwrdm_set_next_pwrst,
  166. .pwrdm_read_next_pwrst = am33xx_pwrdm_read_next_pwrst,
  167. .pwrdm_read_pwrst = am33xx_pwrdm_read_pwrst,
  168. .pwrdm_read_prev_pwrst = am33xx_pwrdm_read_prev_pwrst,
  169. .pwrdm_set_logic_retst = am33xx_pwrdm_set_logic_retst,
  170. .pwrdm_read_logic_pwrst = am33xx_pwrdm_read_logic_pwrst,
  171. .pwrdm_read_logic_retst = am33xx_pwrdm_read_logic_retst,
  172. .pwrdm_clear_all_prev_pwrst = am33xx_pwrdm_clear_all_prev_pwrst,
  173. .pwrdm_set_lowpwrstchange = am33xx_pwrdm_set_lowpwrstchange,
  174. .pwrdm_read_mem_pwrst = am33xx_pwrdm_read_mem_pwrst,
  175. .pwrdm_read_mem_retst = am33xx_pwrdm_read_mem_retst,
  176. .pwrdm_set_mem_onst = am33xx_pwrdm_set_mem_onst,
  177. .pwrdm_set_mem_retst = am33xx_pwrdm_set_mem_retst,
  178. .pwrdm_wait_transition = am33xx_pwrdm_wait_transition,
  179. };