osi_clock.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /* Copyright (C) 2018 RDA Technologies Limited and/or its affiliates("RDA").
  2. * All rights reserved.
  3. *
  4. * This software is supplied "AS IS" without any warranties.
  5. * RDA assumes no responsibility or liability for the use of the software,
  6. * conveys no license or title under any patent, copyright, or mask work
  7. * right to the product. RDA reserves the right to make changes in the
  8. * software without notification. RDA also make no representation or
  9. * warranty that such application will be suitable for the specified use
  10. * without further testing or modification.
  11. */
  12. #ifndef _OSI_CLOCK_H_
  13. #define _OSI_CLOCK_H_
  14. #include <stdint.h>
  15. #include <stdbool.h>
  16. #include <stddef.h>
  17. #ifdef __cplusplus
  18. extern "C" {
  19. #endif
  20. /**
  21. * \brief callback function for clk_sys change
  22. *
  23. * The callback is platform dependent. Typical usage is for hardware module,
  24. * whose clock is divided from clk_sys. So, when clk_sys is changed, it is
  25. * needed to update the divider from clk_sys.
  26. *
  27. * It is recommended to add callback only in hardware driver, and divider
  28. * change is needed.
  29. *
  30. * To ensure atomic, the callback will be called with interrupt disabled.
  31. * So, the callback should be as fast as possible, even trace inside
  32. * callback is discouraged.
  33. *
  34. * \param [in] sysClkFreq new clk_sys to be changed
  35. * \return hardware module working frequency
  36. */
  37. typedef uint32_t (*osiSysClkChangeCallback_t)(uint32_t sysClkFreq);
  38. /**
  39. * \brief clk_sys change callback registry
  40. */
  41. typedef struct
  42. {
  43. uint32_t tag; ///< name tag
  44. //! @cond Doxygen_Suppress
  45. uint32_t dummy0;
  46. uint32_t dummy1;
  47. uint32_t dummy2;
  48. //! @endcond
  49. } osiSysClkCallbackRegistry_t;
  50. /**
  51. * \brief clk_sys constraint registry
  52. */
  53. typedef struct
  54. {
  55. uint32_t tag; ///< name tag
  56. //! @cond Doxygen_Suppress
  57. uint32_t dummy0;
  58. uint32_t dummy1;
  59. uint32_t dummy2;
  60. uint32_t dummy3;
  61. uint32_t dummy4;
  62. //! @endcond
  63. } osiClockConstrainRegistry_t;
  64. /**
  65. * \brief clock management module initialization
  66. */
  67. void osiClockManInit(void);
  68. /**
  69. * \brief clock management start
  70. *
  71. * At initialization, clock management will just record clock constrains. Only
  72. * after this is called, clock management will start to change system clock
  73. * based on clock constrains.
  74. */
  75. void osiClockManStart(void);
  76. /**
  77. * \brief register clk_sys change callback
  78. *
  79. * When \p cb is NULL, it is the same as \p osiUnregisterSysClkChangeCallback(r).
  80. *
  81. * \param [in] r callback registry, must be valid
  82. * \param [in] cb callback function
  83. */
  84. void osiRegisterSysClkChangeCallback(osiSysClkCallbackRegistry_t *r, osiSysClkChangeCallback_t cb);
  85. /**
  86. * \brief unregister clk_sys change callback
  87. *
  88. * \param [in] r callback registry, must be valid
  89. */
  90. void osiUnregisterSysClkChangeCallback(osiSysClkCallbackRegistry_t *r);
  91. /**
  92. * \brief initialize clock constrain
  93. *
  94. * \param [in] r clock constrain registry, must be valid
  95. * \param [in] tag tag name of the clock constrain
  96. */
  97. void osiClockConstrainInit(osiClockConstrainRegistry_t *r, uint32_t tag);
  98. /**
  99. * \brief set hardware minimal clock constrain
  100. *
  101. * It is not needed to specify \p freq to be supported by hardware divider.
  102. * The **closest** supported hardware divider will be chosen.
  103. *
  104. * When \p freq is too high to be supported by hardware, the highest
  105. * supported frequency will be chosen.
  106. *
  107. * After this call, the actual clk_sys may be different with \p freq:
  108. * - When there are higher frequency requests, the actual clk_sys frequency
  109. * may be higher than \p freq.
  110. * - When the closest supported frequency is lower, the actual clk_sys
  111. * frequency may be lower than \p freq.
  112. * - When \p freq is too high, clk_sys will be set to be the highest
  113. * supported frequency.
  114. *
  115. * \param [in] r clock constrain registry, must be valid
  116. * \param [in] freq minimum clk_sys frequency
  117. */
  118. void osiRequestSysClk(osiClockConstrainRegistry_t *r, uint32_t freq);
  119. /**
  120. * \brief set hardware maximum clock constrain
  121. *
  122. * This is for special purpose. In some cases, some hardware can only work
  123. * when sys_clk doesn't exceed a certain frequency. This can be called to
  124. * set the limit.
  125. *
  126. * This will have higher priority than \p osiRequestSysClk. For example,
  127. * module A call \p osiRequestSysClk to request minimal frequency 200MHz,
  128. * and module B call \p osiRequestMaxSysClk to limit the maximum frequency
  129. * 100MHz, sys_clk will be changed to 100MHz though it doesn't satisfy
  130. * the requirement of module A.
  131. *
  132. * \param [in] r clock constrain registry, must be valid
  133. * \param [in] freq maximum clk_sys frequency
  134. */
  135. void osiRequestMaxSysClk(osiClockConstrainRegistry_t *r, uint32_t freq);
  136. /**
  137. * \brief set hardware minimal clock constrain, without specified frequency
  138. *
  139. * Besides it will prevent system sleep, it will prevent clk_sys related
  140. * power consumption optimization.
  141. *
  142. * \param [in] r clock constrain registry, must be valid
  143. */
  144. void osiRequestSysClkActive(osiClockConstrainRegistry_t *r);
  145. /**
  146. * \brief set software minimal clock constrain
  147. *
  148. * It is similar to \p osiRequestSysClk. However, it won't prevent system
  149. * sleep or clk_sys related power consumption optimization.
  150. *
  151. * \param [in] r clock constrain registry, must be valid
  152. * \param [in] freq minimum clk_sys frequency
  153. */
  154. void osiRequestPerfClk(osiClockConstrainRegistry_t *r, uint32_t freq);
  155. /**
  156. * \brief unset software or hardware minimal clock constrain
  157. *
  158. * \param [in] r clock constrain registry, must be valid
  159. */
  160. void osiReleaseClk(osiClockConstrainRegistry_t *r);
  161. /**
  162. * \brief whether slow down sys clock is allowed
  163. *
  164. * \return
  165. * - true if allowed
  166. * - false if not allowed
  167. */
  168. bool osiIsSlowSysClkAllowed(void);
  169. /**
  170. * \brief reapply clk_sys constrains
  171. *
  172. * It is possible that some constrains aren't satisfied immediately,
  173. * especially to decrease clk_sys. So, it may be needed to reapply
  174. * constrains. Usually, it is called in idle thread.
  175. *
  176. * It should be called by system only.
  177. */
  178. void osiReapplySysClk(void);
  179. /**
  180. * \brief dump clock constrain information to memory
  181. *
  182. * It is for debug only. The data format of timer information dump is
  183. * not stable, and may change. When \p mem is NULL, it will return the
  184. * estimated dump size.
  185. *
  186. * \param mem memory for clock constrain information dump
  187. * \param size provided memory size
  188. * \return
  189. * - dump memory size
  190. * - -1 if memory size of not enough
  191. */
  192. int osiClockConstrainDump(void *mem, unsigned size);
  193. #ifdef __cplusplus
  194. }
  195. #endif
  196. #endif