Skip to content

Commit e0943cf

Browse files
nordic-krchcarlescufi
authored andcommitted
drivers: clock_control: API extension proposal
Proposal which extends api to allow asynchronous clock enabling. Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
1 parent 95f28eb commit e0943cf

File tree

1 file changed

+118
-3
lines changed

1 file changed

+118
-3
lines changed

include/clock_control.h

Lines changed: 118 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <stddef.h>
1414
#include <device.h>
1515
#include <misc/__assert.h>
16+
#include <misc/slist.h>
1617

1718
#ifdef __cplusplus
1819
extern "C" {
@@ -23,6 +24,54 @@ extern "C" {
2324
/* Used to select all subsystem of a clock controller */
2425
#define CLOCK_CONTROL_SUBSYS_ALL NULL
2526

27+
/**
28+
* @brief Current clock status.
29+
*/
30+
enum clock_control_status {
31+
CLOCK_CONTROL_STATUS_STARTING,
32+
CLOCK_CONTROL_STATUS_OFF,
33+
CLOCK_CONTROL_STATUS_ON,
34+
CLOCK_CONTROL_STATUS_UNKNOWN
35+
};
36+
37+
typedef void (*clock_control_cb_t)(struct device *dev, void *user_data);
38+
39+
/**
40+
* @cond INTERNAL_HIDDEN
41+
*/
42+
#define Z_CLOCK_CONTROL_ASYNC_DATA_INITIALIZER(_cb, _user_data) \
43+
{ \
44+
.cb = cb, \
45+
.user_data = _user_data \
46+
}
47+
/**
48+
* INTERNAL_HIDDEN @endcond
49+
*/
50+
51+
/**
52+
* Define and initialize clock_control async data.
53+
*
54+
* @param name Name of the data.
55+
* @param cb Callback.
56+
* @param user_data User data
57+
*/
58+
#define CLOCK_CONTROL_ASYNC_DATA_DEFINE(name, cb, user_data) \
59+
struct clock_control_async_data name = \
60+
Z_CLOCK_CONTROL_ASYNC_DATA_INITIALIZER(cb, user_data)
61+
62+
/**
63+
* @brief Clock control data used for asynchronous clock enabling.
64+
*
65+
* @param node Used internally for linking asynchronous requests.
66+
* @param cb Callback called when clock is started.
67+
* @param user_data User data passed as an argument in the callback.
68+
*/
69+
struct clock_control_async_data {
70+
sys_snode_t node;
71+
clock_control_cb_t cb;
72+
void *user_data;
73+
};
74+
2675
/**
2776
* clock_control_subsys_t is a type to identify a clock controller sub-system.
2877
* Such data pointed is opaque and relevant only to the clock controller
@@ -36,10 +85,20 @@ typedef int (*clock_control_get)(struct device *dev,
3685
clock_control_subsys_t sys,
3786
u32_t *rate);
3887

88+
typedef int (*clock_control_async_on_fn)(struct device *dev,
89+
clock_control_subsys_t sys,
90+
struct clock_control_async_data *data);
91+
92+
typedef enum clock_control_status (*clock_control_get_status_fn)(
93+
struct device *dev,
94+
clock_control_subsys_t sys);
95+
3996
struct clock_control_driver_api {
40-
clock_control on;
41-
clock_control off;
42-
clock_control_get get_rate;
97+
clock_control on;
98+
clock_control off;
99+
clock_control_async_on_fn async_on;
100+
clock_control_get get_rate;
101+
clock_control_get_status_fn get_status;
43102
};
44103

45104
/**
@@ -72,6 +131,62 @@ static inline int clock_control_off(struct device *dev,
72131
return api->off(dev, sys);
73132
}
74133

134+
/**
135+
* @brief Request clock to start with notification when clock has been started.
136+
*
137+
* User can request delayed start by providing exact information when clock
138+
* should be ready. Driver ensures that clock is ready before requested time.
139+
* It is the driver responsibility to take into account clock startup time.
140+
* When clock is already running user callback will be called from the context
141+
* of the function call else it is called from other context (e.g. clock
142+
* interrupt).
143+
*
144+
* @param dev Device.
145+
* @param sys A pointer to an opaque data representing the sub-system.
146+
* @param data Data structure containing a callback that is called when
147+
* action is performed. Structure content must be valid until
148+
* clock is started and user callback is called. Can be NULL.
149+
*
150+
* @retval 0 if clock is started or already running.
151+
* @retval -EBUSY if same request already scheduled and not yet completed.
152+
* @retval -ENOTSUP if not supported.
153+
*/
154+
static inline int clock_control_async_on(struct device *dev,
155+
clock_control_subsys_t sys,
156+
struct clock_control_async_data *data)
157+
{
158+
const struct clock_control_driver_api *api =
159+
(const struct clock_control_driver_api *)dev->driver_api;
160+
161+
if (!api->async_on) {
162+
return -ENOTSUP;
163+
}
164+
165+
return api->async_on(dev, sys, data);
166+
}
167+
168+
/**
169+
* @brief Get clock status.
170+
*
171+
* @param dev Device.
172+
* @param sys A pointer to an opaque data representing the sub-system.
173+
*
174+
* @return Status.
175+
*/
176+
static inline enum clock_control_status clock_control_get_status(
177+
struct device *dev,
178+
clock_control_subsys_t sys)
179+
{
180+
const struct clock_control_driver_api *api =
181+
(const struct clock_control_driver_api *)dev->driver_api;
182+
183+
if (!api->get_status) {
184+
return CLOCK_CONTROL_STATUS_UNKNOWN;
185+
}
186+
187+
return api->get_status(dev, sys);
188+
}
189+
75190
/**
76191
* @brief Obtain the clock rate of given sub-system
77192
* @param dev Pointer to the device structure for the clock controller driver

0 commit comments

Comments
 (0)