From e0943cfaab29100c5212f74aa9f3eb1a4aa58f0b Mon Sep 17 00:00:00 2001 From: Krzysztof Chruscinski Date: Fri, 7 Jun 2019 11:14:52 +0200 Subject: [PATCH] drivers: clock_control: API extension proposal Proposal which extends api to allow asynchronous clock enabling. Signed-off-by: Krzysztof Chruscinski --- include/clock_control.h | 121 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 118 insertions(+), 3 deletions(-) diff --git a/include/clock_control.h b/include/clock_control.h index eb4f59c7e49..49354aaed4b 100644 --- a/include/clock_control.h +++ b/include/clock_control.h @@ -13,6 +13,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -23,6 +24,54 @@ extern "C" { /* Used to select all subsystem of a clock controller */ #define CLOCK_CONTROL_SUBSYS_ALL NULL +/** + * @brief Current clock status. + */ +enum clock_control_status { + CLOCK_CONTROL_STATUS_STARTING, + CLOCK_CONTROL_STATUS_OFF, + CLOCK_CONTROL_STATUS_ON, + CLOCK_CONTROL_STATUS_UNKNOWN +}; + +typedef void (*clock_control_cb_t)(struct device *dev, void *user_data); + +/** + * @cond INTERNAL_HIDDEN + */ +#define Z_CLOCK_CONTROL_ASYNC_DATA_INITIALIZER(_cb, _user_data) \ + { \ + .cb = cb, \ + .user_data = _user_data \ + } +/** + * INTERNAL_HIDDEN @endcond + */ + +/** + * Define and initialize clock_control async data. + * + * @param name Name of the data. + * @param cb Callback. + * @param user_data User data + */ +#define CLOCK_CONTROL_ASYNC_DATA_DEFINE(name, cb, user_data) \ + struct clock_control_async_data name = \ + Z_CLOCK_CONTROL_ASYNC_DATA_INITIALIZER(cb, user_data) + +/** + * @brief Clock control data used for asynchronous clock enabling. + * + * @param node Used internally for linking asynchronous requests. + * @param cb Callback called when clock is started. + * @param user_data User data passed as an argument in the callback. + */ +struct clock_control_async_data { + sys_snode_t node; + clock_control_cb_t cb; + void *user_data; +}; + /** * clock_control_subsys_t is a type to identify a clock controller sub-system. * Such data pointed is opaque and relevant only to the clock controller @@ -36,10 +85,20 @@ typedef int (*clock_control_get)(struct device *dev, clock_control_subsys_t sys, u32_t *rate); +typedef int (*clock_control_async_on_fn)(struct device *dev, + clock_control_subsys_t sys, + struct clock_control_async_data *data); + +typedef enum clock_control_status (*clock_control_get_status_fn)( + struct device *dev, + clock_control_subsys_t sys); + struct clock_control_driver_api { - clock_control on; - clock_control off; - clock_control_get get_rate; + clock_control on; + clock_control off; + clock_control_async_on_fn async_on; + clock_control_get get_rate; + clock_control_get_status_fn get_status; }; /** @@ -72,6 +131,62 @@ static inline int clock_control_off(struct device *dev, return api->off(dev, sys); } +/** + * @brief Request clock to start with notification when clock has been started. + * + * User can request delayed start by providing exact information when clock + * should be ready. Driver ensures that clock is ready before requested time. + * It is the driver responsibility to take into account clock startup time. + * When clock is already running user callback will be called from the context + * of the function call else it is called from other context (e.g. clock + * interrupt). + * + * @param dev Device. + * @param sys A pointer to an opaque data representing the sub-system. + * @param data Data structure containing a callback that is called when + * action is performed. Structure content must be valid until + * clock is started and user callback is called. Can be NULL. + * + * @retval 0 if clock is started or already running. + * @retval -EBUSY if same request already scheduled and not yet completed. + * @retval -ENOTSUP if not supported. + */ +static inline int clock_control_async_on(struct device *dev, + clock_control_subsys_t sys, + struct clock_control_async_data *data) +{ + const struct clock_control_driver_api *api = + (const struct clock_control_driver_api *)dev->driver_api; + + if (!api->async_on) { + return -ENOTSUP; + } + + return api->async_on(dev, sys, data); +} + +/** + * @brief Get clock status. + * + * @param dev Device. + * @param sys A pointer to an opaque data representing the sub-system. + * + * @return Status. + */ +static inline enum clock_control_status clock_control_get_status( + struct device *dev, + clock_control_subsys_t sys) +{ + const struct clock_control_driver_api *api = + (const struct clock_control_driver_api *)dev->driver_api; + + if (!api->get_status) { + return CLOCK_CONTROL_STATUS_UNKNOWN; + } + + return api->get_status(dev, sys); +} + /** * @brief Obtain the clock rate of given sub-system * @param dev Pointer to the device structure for the clock controller driver