prm2xxx.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. /*
  2. * OMAP2xxx PRM module functions
  3. *
  4. * Copyright (C) 2010-2012 Texas Instruments, Inc.
  5. * Copyright (C) 2010 Nokia Corporation
  6. * Benoît Cousson
  7. * Paul Walmsley
  8. * Rajendra Nayak <rnayak@ti.com>
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License version 2 as
  12. * published by the Free Software Foundation.
  13. */
  14. #include <linux/kernel.h>
  15. #include <linux/errno.h>
  16. #include <linux/err.h>
  17. #include <linux/io.h>
  18. #include <linux/irq.h>
  19. #include "soc.h"
  20. #include "common.h"
  21. #include "vp.h"
  22. #include "powerdomain.h"
  23. #include "clockdomain.h"
  24. #include "prm2xxx.h"
  25. #include "cm2xxx_3xxx.h"
  26. #include "prm-regbits-24xx.h"
  27. /*
  28. * OMAP24xx PM_PWSTCTRL_*.POWERSTATE and PM_PWSTST_*.LASTSTATEENTERED bits -
  29. * these are reversed from the bits used on OMAP3+
  30. */
  31. #define OMAP24XX_PWRDM_POWER_ON 0x0
  32. #define OMAP24XX_PWRDM_POWER_RET 0x1
  33. #define OMAP24XX_PWRDM_POWER_OFF 0x3
  34. /*
  35. * omap2xxx_prm_reset_src_map - map from bits in the PRM_RSTST_WKUP
  36. * hardware register (which are specific to the OMAP2xxx SoCs) to
  37. * reset source ID bit shifts (which is an OMAP SoC-independent
  38. * enumeration)
  39. */
  40. static struct prm_reset_src_map omap2xxx_prm_reset_src_map[] = {
  41. { OMAP_GLOBALCOLD_RST_SHIFT, OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT },
  42. { OMAP_GLOBALWARM_RST_SHIFT, OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT },
  43. { OMAP24XX_SECU_VIOL_RST_SHIFT, OMAP_SECU_VIOL_RST_SRC_ID_SHIFT },
  44. { OMAP24XX_MPU_WD_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT },
  45. { OMAP24XX_SECU_WD_RST_SHIFT, OMAP_SECU_WD_RST_SRC_ID_SHIFT },
  46. { OMAP24XX_EXTWMPU_RST_SHIFT, OMAP_EXTWARM_RST_SRC_ID_SHIFT },
  47. { -1, -1 },
  48. };
  49. /**
  50. * omap2xxx_prm_read_reset_sources - return the last SoC reset source
  51. *
  52. * Return a u32 representing the last reset sources of the SoC. The
  53. * returned reset source bits are standardized across OMAP SoCs.
  54. */
  55. static u32 omap2xxx_prm_read_reset_sources(void)
  56. {
  57. struct prm_reset_src_map *p;
  58. u32 r = 0;
  59. u32 v;
  60. v = omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTST);
  61. p = omap2xxx_prm_reset_src_map;
  62. while (p->reg_shift >= 0 && p->std_shift >= 0) {
  63. if (v & (1 << p->reg_shift))
  64. r |= 1 << p->std_shift;
  65. p++;
  66. }
  67. return r;
  68. }
  69. /**
  70. * omap2xxx_pwrst_to_common_pwrst - convert OMAP2xxx pwrst to common pwrst
  71. * @omap2xxx_pwrst: OMAP2xxx hardware power state to convert
  72. *
  73. * Return the common power state bits corresponding to the OMAP2xxx
  74. * hardware power state bits @omap2xxx_pwrst, or -EINVAL upon error.
  75. */
  76. static int omap2xxx_pwrst_to_common_pwrst(u8 omap2xxx_pwrst)
  77. {
  78. u8 pwrst;
  79. switch (omap2xxx_pwrst) {
  80. case OMAP24XX_PWRDM_POWER_OFF:
  81. pwrst = PWRDM_POWER_OFF;
  82. break;
  83. case OMAP24XX_PWRDM_POWER_RET:
  84. pwrst = PWRDM_POWER_RET;
  85. break;
  86. case OMAP24XX_PWRDM_POWER_ON:
  87. pwrst = PWRDM_POWER_ON;
  88. break;
  89. default:
  90. return -EINVAL;
  91. }
  92. return pwrst;
  93. }
  94. /**
  95. * omap2xxx_prm_dpll_reset - use DPLL reset to reboot the OMAP SoC
  96. *
  97. * Set the DPLL reset bit, which should reboot the SoC. This is the
  98. * recommended way to restart the SoC. No return value.
  99. */
  100. void omap2xxx_prm_dpll_reset(void)
  101. {
  102. omap2_prm_set_mod_reg_bits(OMAP_RST_DPLL3_MASK, WKUP_MOD,
  103. OMAP2_RM_RSTCTRL);
  104. /* OCP barrier */
  105. omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTCTRL);
  106. }
  107. int omap2xxx_clkdm_sleep(struct clockdomain *clkdm)
  108. {
  109. omap2_prm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
  110. clkdm->pwrdm.ptr->prcm_offs,
  111. OMAP2_PM_PWSTCTRL);
  112. return 0;
  113. }
  114. int omap2xxx_clkdm_wakeup(struct clockdomain *clkdm)
  115. {
  116. omap2_prm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
  117. clkdm->pwrdm.ptr->prcm_offs,
  118. OMAP2_PM_PWSTCTRL);
  119. return 0;
  120. }
  121. static int omap2xxx_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
  122. {
  123. u8 omap24xx_pwrst;
  124. switch (pwrst) {
  125. case PWRDM_POWER_OFF:
  126. omap24xx_pwrst = OMAP24XX_PWRDM_POWER_OFF;
  127. break;
  128. case PWRDM_POWER_RET:
  129. omap24xx_pwrst = OMAP24XX_PWRDM_POWER_RET;
  130. break;
  131. case PWRDM_POWER_ON:
  132. omap24xx_pwrst = OMAP24XX_PWRDM_POWER_ON;
  133. break;
  134. default:
  135. return -EINVAL;
  136. }
  137. omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
  138. (omap24xx_pwrst << OMAP_POWERSTATE_SHIFT),
  139. pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
  140. return 0;
  141. }
  142. static int omap2xxx_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
  143. {
  144. u8 omap2xxx_pwrst;
  145. omap2xxx_pwrst = omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
  146. OMAP2_PM_PWSTCTRL,
  147. OMAP_POWERSTATE_MASK);
  148. return omap2xxx_pwrst_to_common_pwrst(omap2xxx_pwrst);
  149. }
  150. static int omap2xxx_pwrdm_read_pwrst(struct powerdomain *pwrdm)
  151. {
  152. u8 omap2xxx_pwrst;
  153. omap2xxx_pwrst = omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
  154. OMAP2_PM_PWSTST,
  155. OMAP_POWERSTATEST_MASK);
  156. return omap2xxx_pwrst_to_common_pwrst(omap2xxx_pwrst);
  157. }
  158. struct pwrdm_ops omap2_pwrdm_operations = {
  159. .pwrdm_set_next_pwrst = omap2xxx_pwrdm_set_next_pwrst,
  160. .pwrdm_read_next_pwrst = omap2xxx_pwrdm_read_next_pwrst,
  161. .pwrdm_read_pwrst = omap2xxx_pwrdm_read_pwrst,
  162. .pwrdm_set_logic_retst = omap2_pwrdm_set_logic_retst,
  163. .pwrdm_set_mem_onst = omap2_pwrdm_set_mem_onst,
  164. .pwrdm_set_mem_retst = omap2_pwrdm_set_mem_retst,
  165. .pwrdm_read_mem_pwrst = omap2_pwrdm_read_mem_pwrst,
  166. .pwrdm_read_mem_retst = omap2_pwrdm_read_mem_retst,
  167. .pwrdm_wait_transition = omap2_pwrdm_wait_transition,
  168. };
  169. /*
  170. *
  171. */
  172. static struct prm_ll_data omap2xxx_prm_ll_data = {
  173. .read_reset_sources = &omap2xxx_prm_read_reset_sources,
  174. };
  175. int __init omap2xxx_prm_init(void)
  176. {
  177. if (!cpu_is_omap24xx())
  178. return 0;
  179. return prm_register(&omap2xxx_prm_ll_data);
  180. }
  181. static void __exit omap2xxx_prm_exit(void)
  182. {
  183. if (!cpu_is_omap24xx())
  184. return;
  185. /* Should never happen */
  186. WARN(prm_unregister(&omap2xxx_prm_ll_data),
  187. "%s: prm_ll_data function pointer mismatch\n", __func__);
  188. }
  189. __exitcall(omap2xxx_prm_exit);