123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- /* Copyright (C) 2018 RDA Technologies Limited and/or its affiliates("RDA").
- * All rights reserved.
- *
- * This software is supplied "AS IS" without any warranties.
- * RDA assumes no responsibility or liability for the use of the software,
- * conveys no license or title under any patent, copyright, or mask work
- * right to the product. RDA reserves the right to make changes in the
- * software without notification. RDA also make no representation or
- * warranty that such application will be suitable for the specified use
- * without further testing or modification.
- */
- #ifndef _OSI_CLOCK_H_
- #define _OSI_CLOCK_H_
- #include <stdint.h>
- #include <stdbool.h>
- #include <stddef.h>
- #ifdef __cplusplus
- extern "C" {
- #endif
- /**
- * \brief callback function for clk_sys change
- *
- * The callback is platform dependent. Typical usage is for hardware module,
- * whose clock is divided from clk_sys. So, when clk_sys is changed, it is
- * needed to update the divider from clk_sys.
- *
- * It is recommended to add callback only in hardware driver, and divider
- * change is needed.
- *
- * To ensure atomic, the callback will be called with interrupt disabled.
- * So, the callback should be as fast as possible, even trace inside
- * callback is discouraged.
- *
- * \param [in] sysClkFreq new clk_sys to be changed
- * \return hardware module working frequency
- */
- typedef uint32_t (*osiSysClkChangeCallback_t)(uint32_t sysClkFreq);
- /**
- * \brief clk_sys change callback registry
- */
- typedef struct
- {
- uint32_t tag; ///< name tag
- //! @cond Doxygen_Suppress
- uint32_t dummy0;
- uint32_t dummy1;
- uint32_t dummy2;
- //! @endcond
- } osiSysClkCallbackRegistry_t;
- /**
- * \brief clk_sys constraint registry
- */
- typedef struct
- {
- uint32_t tag; ///< name tag
- //! @cond Doxygen_Suppress
- uint32_t dummy0;
- uint32_t dummy1;
- uint32_t dummy2;
- uint32_t dummy3;
- uint32_t dummy4;
- //! @endcond
- } osiClockConstrainRegistry_t;
- /**
- * \brief clock management module initialization
- */
- void osiClockManInit(void);
- /**
- * \brief clock management start
- *
- * At initialization, clock management will just record clock constrains. Only
- * after this is called, clock management will start to change system clock
- * based on clock constrains.
- */
- void osiClockManStart(void);
- /**
- * \brief register clk_sys change callback
- *
- * When \p cb is NULL, it is the same as \p osiUnregisterSysClkChangeCallback(r).
- *
- * \param [in] r callback registry, must be valid
- * \param [in] cb callback function
- */
- void osiRegisterSysClkChangeCallback(osiSysClkCallbackRegistry_t *r, osiSysClkChangeCallback_t cb);
- /**
- * \brief unregister clk_sys change callback
- *
- * \param [in] r callback registry, must be valid
- */
- void osiUnregisterSysClkChangeCallback(osiSysClkCallbackRegistry_t *r);
- /**
- * \brief initialize clock constrain
- *
- * \param [in] r clock constrain registry, must be valid
- * \param [in] tag tag name of the clock constrain
- */
- void osiClockConstrainInit(osiClockConstrainRegistry_t *r, uint32_t tag);
- /**
- * \brief set hardware minimal clock constrain
- *
- * It is not needed to specify \p freq to be supported by hardware divider.
- * The **closest** supported hardware divider will be chosen.
- *
- * When \p freq is too high to be supported by hardware, the highest
- * supported frequency will be chosen.
- *
- * After this call, the actual clk_sys may be different with \p freq:
- * - When there are higher frequency requests, the actual clk_sys frequency
- * may be higher than \p freq.
- * - When the closest supported frequency is lower, the actual clk_sys
- * frequency may be lower than \p freq.
- * - When \p freq is too high, clk_sys will be set to be the highest
- * supported frequency.
- *
- * \param [in] r clock constrain registry, must be valid
- * \param [in] freq minimum clk_sys frequency
- */
- void osiRequestSysClk(osiClockConstrainRegistry_t *r, uint32_t freq);
- /**
- * \brief set hardware maximum clock constrain
- *
- * This is for special purpose. In some cases, some hardware can only work
- * when sys_clk doesn't exceed a certain frequency. This can be called to
- * set the limit.
- *
- * This will have higher priority than \p osiRequestSysClk. For example,
- * module A call \p osiRequestSysClk to request minimal frequency 200MHz,
- * and module B call \p osiRequestMaxSysClk to limit the maximum frequency
- * 100MHz, sys_clk will be changed to 100MHz though it doesn't satisfy
- * the requirement of module A.
- *
- * \param [in] r clock constrain registry, must be valid
- * \param [in] freq maximum clk_sys frequency
- */
- void osiRequestMaxSysClk(osiClockConstrainRegistry_t *r, uint32_t freq);
- /**
- * \brief set hardware minimal clock constrain, without specified frequency
- *
- * Besides it will prevent system sleep, it will prevent clk_sys related
- * power consumption optimization.
- *
- * \param [in] r clock constrain registry, must be valid
- */
- void osiRequestSysClkActive(osiClockConstrainRegistry_t *r);
- /**
- * \brief set software minimal clock constrain
- *
- * It is similar to \p osiRequestSysClk. However, it won't prevent system
- * sleep or clk_sys related power consumption optimization.
- *
- * \param [in] r clock constrain registry, must be valid
- * \param [in] freq minimum clk_sys frequency
- */
- void osiRequestPerfClk(osiClockConstrainRegistry_t *r, uint32_t freq);
- /**
- * \brief unset software or hardware minimal clock constrain
- *
- * \param [in] r clock constrain registry, must be valid
- */
- void osiReleaseClk(osiClockConstrainRegistry_t *r);
- /**
- * \brief whether slow down sys clock is allowed
- *
- * \return
- * - true if allowed
- * - false if not allowed
- */
- bool osiIsSlowSysClkAllowed(void);
- /**
- * \brief reapply clk_sys constrains
- *
- * It is possible that some constrains aren't satisfied immediately,
- * especially to decrease clk_sys. So, it may be needed to reapply
- * constrains. Usually, it is called in idle thread.
- *
- * It should be called by system only.
- */
- void osiReapplySysClk(void);
- /**
- * \brief dump clock constrain information to memory
- *
- * It is for debug only. The data format of timer information dump is
- * not stable, and may change. When \p mem is NULL, it will return the
- * estimated dump size.
- *
- * \param mem memory for clock constrain information dump
- * \param size provided memory size
- * \return
- * - dump memory size
- * - -1 if memory size of not enough
- */
- int osiClockConstrainDump(void *mem, unsigned size);
- #ifdef __cplusplus
- }
- #endif
- #endif
|