hal_pd.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /* SPDX-License-Identifier: BSD-3-Clause */
  2. /*
  3. * Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd.
  4. */
  5. #include "hal_base.h"
  6. #ifdef HAL_PMU_MODULE_ENABLED
  7. /** @addtogroup RK_HAL_Driver
  8. * @{
  9. */
  10. /** @addtogroup PD
  11. * @{
  12. */
  13. /** @defgroup PD_How_To_Use How To Use
  14. * @{
  15. The PD driver can be used as follows:
  16. - Invoke HAL_PD_Setting in each device power on/off its own Pd.
  17. - The order of setting power domain.
  18. power on:
  19. set power domain on
  20. leave idle
  21. power off:
  22. request ilde
  23. set power domain off
  24. - The PD ID is include shift information:
  25. [3:0]: power on shift
  26. [7:4]: power on status shift
  27. [11:8]: idle request shift
  28. [15:12]: idle status shift
  29. [19:16]: ack status shift
  30. - PD driver is just responsible for passing simple command data, And
  31. the usecount is the user's responsibility. Protection the usecount at the driver layer.
  32. - More details refer to APIs' descriptions as below.
  33. @} */
  34. /** @defgroup PD_Private_Definition Private Definition
  35. * @{
  36. */
  37. /********************* Private MACRO Definition ******************************/
  38. #define PD_PWR_SHIFT 0U
  39. #define PD_PWR_MASK 0x0000000FU
  40. #define PD_ST_SHIFT 4U
  41. #define PD_ST_MASK 0x000000F0U
  42. #define PD_REQ_SHIFT 8U
  43. #define PD_REQ_MASK 0x00000F00U
  44. #define PD_IDLE_SHIFT 12U
  45. #define PD_IDLE_MASK 0x0000F000U
  46. #define PD_ACK_SHIFT 16U
  47. #define PD_ACK_MASK 0x000F0000U
  48. #define PD_VALID_SHIFT 31U
  49. #define PD_VALID_MASK 0x80000000U
  50. #define PD_GET_PWR_SHIFT(x) (((uint32_t)(x)&PD_PWR_MASK) >> PD_PWR_SHIFT)
  51. #define PD_GET_ST_SHIFT(x) (((uint32_t)(x)&PD_ST_MASK) >> PD_ST_SHIFT)
  52. #define PD_GET_REQ_SHIFT(x) (((uint32_t)(x)&PD_REQ_MASK) >> PD_REQ_SHIFT)
  53. #if defined(SOC_RK1808)
  54. #define PD_GET_IDLE_SHIFT(x) ((((uint32_t)(x)&PD_IDLE_MASK) >> PD_IDLE_SHIFT) + 16)
  55. #else
  56. #define PD_GET_IDLE_SHIFT(x) (((uint32_t)(x)&PD_IDLE_MASK) >> PD_IDLE_SHIFT)
  57. #endif
  58. #define PD_GET_ACK_SHIFT(x) (((uint32_t)(x)&PD_ACK_MASK) >> PD_ACK_SHIFT)
  59. #define PD_IS_INVALID(x) (!(((uint32_t)(x)&PD_VALID_MASK) >> PD_VALID_SHIFT))
  60. /********************* Private Structure Definition **************************/
  61. /********************* Private Variable Definition ***************************/
  62. /********************* Private Function Definition ***************************/
  63. static HAL_Check PD_IsIdle(ePD_Id pd)
  64. {
  65. uint32_t idleShift = PD_GET_IDLE_SHIFT(pd);
  66. return (HAL_Check)((PMU->BUS_IDLE_ST & (1 << idleShift)) >> idleShift);
  67. }
  68. #if defined(SOC_RK1808)
  69. static HAL_Check PD_ReadAck(ePD_Id pd)
  70. {
  71. uint32_t ackShift = PD_GET_ACK_SHIFT(pd);
  72. return (HAL_Check)((PMU->BUS_IDLE_ST & (1 << ackShift)) >> ackShift);
  73. }
  74. #else
  75. static HAL_Check PD_ReadAck(ePD_Id pd)
  76. {
  77. uint32_t ackShift = PD_GET_ACK_SHIFT(pd);
  78. return (HAL_Check)((PMU->BUS_IDLE_ACK & (1 << ackShift)) >> ackShift);
  79. }
  80. #endif
  81. static HAL_Check PD_IsOn(ePD_Id pd)
  82. {
  83. uint32_t stShift = PD_GET_ST_SHIFT(pd);
  84. /* check idle status for idle-only domains */
  85. if (stShift > 16) {
  86. return PD_IsIdle(pd) ? HAL_FALSE : HAL_TRUE;
  87. }
  88. return (HAL_Check)(!((PMU->PWRDN_ST & (1 << stShift)) >> stShift));
  89. }
  90. static HAL_Status PD_IdleRequest(ePD_Id pd, HAL_Check idle)
  91. {
  92. uint32_t reqShift = PD_GET_REQ_SHIFT(pd);
  93. uint32_t start, timeoutMs = 1000;
  94. if (reqShift > 16) {
  95. return HAL_INVAL;
  96. }
  97. PMU->BUS_IDLE_REQ = VAL_MASK_WE(1U << reqShift, (idle ? 1U : 0U) << reqShift);
  98. /* Wait util idle_ack = 1 */
  99. start = HAL_GetTick();
  100. while (PD_ReadAck(pd) != idle) {
  101. if ((HAL_GetTick() - start) > timeoutMs) {
  102. return HAL_TIMEOUT;
  103. }
  104. }
  105. start = HAL_GetTick();
  106. while (PD_IsIdle(pd) != idle) {
  107. if ((HAL_GetTick() - start) > timeoutMs) {
  108. return HAL_TIMEOUT;
  109. }
  110. }
  111. return HAL_OK;
  112. }
  113. static HAL_Status PD_PowerOn(ePD_Id pd, HAL_Check on)
  114. {
  115. uint32_t pwrShift = PD_GET_PWR_SHIFT(pd);
  116. uint32_t start, timeoutMs = 1000;
  117. if (pwrShift > 16) {
  118. return HAL_INVAL;
  119. }
  120. PMU->PWRDN_CON = VAL_MASK_WE(1U << pwrShift, (on ? 0U : 1U) << pwrShift);
  121. start = HAL_GetTick();
  122. while (PD_IsOn(pd) != on) {
  123. if ((HAL_GetTick() - start) > timeoutMs) {
  124. return HAL_TIMEOUT;
  125. }
  126. }
  127. return HAL_OK;
  128. }
  129. /** @} */
  130. /********************* Public Function Definition ****************************/
  131. /** @defgroup PD_Exported_Functions_Group5 Other Functions
  132. * @attention these APIs allow direct use in the HAL layer.
  133. * @{
  134. */
  135. /**
  136. * @brief Pd setting on
  137. * @param pd: pd id
  138. * @return HAL_Status
  139. */
  140. HAL_Status HAL_PD_On(ePD_Id pd)
  141. {
  142. HAL_Status error;
  143. if (PD_IS_INVALID(pd)) {
  144. return HAL_INVAL;
  145. }
  146. if (PD_IsOn(pd)) {
  147. return HAL_OK;
  148. }
  149. error = PD_PowerOn(pd, HAL_TRUE);
  150. if (error) {
  151. return error;
  152. }
  153. /* if powering up, leave idle mode */
  154. error = PD_IdleRequest(pd, HAL_FALSE);
  155. return error;
  156. }
  157. /**
  158. * @brief Pd setting off
  159. * @param pd: pd id
  160. * @return HAL_Status
  161. */
  162. HAL_Status HAL_PD_Off(ePD_Id pd)
  163. {
  164. HAL_Status error;
  165. if (PD_IS_INVALID(pd)) {
  166. return HAL_INVAL;
  167. }
  168. if (!PD_IsOn(pd)) {
  169. return HAL_OK;
  170. }
  171. /* if powering down, idle request to NIU first */
  172. error = PD_IdleRequest(pd, HAL_TRUE);
  173. if (error) {
  174. return error;
  175. }
  176. error = PD_PowerOn(pd, HAL_FALSE);
  177. return error;
  178. }
  179. /** @} */
  180. /** @} */
  181. /** @} */
  182. #endif /* HAL_PMU_MODULE_ENABLED */