Line data Source code
1 1 : /* clock_control.h - public clock controller driver API */
2 :
3 : /*
4 : * Copyright (c) 2015 Intel Corporation
5 : *
6 : * SPDX-License-Identifier: Apache-2.0
7 : */
8 :
9 : /**
10 : * @file
11 : * @brief Public Clock Control APIs
12 : */
13 :
14 : #ifndef ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_H_
15 : #define ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_H_
16 :
17 : /**
18 : * @brief Clock Control Interface
19 : * @defgroup clock_control_interface Clock Control Interface
20 : * @since 1.0
21 : * @version 1.0.0
22 : * @ingroup io_interfaces
23 : * @{
24 : */
25 :
26 : #include <errno.h>
27 : #include <stddef.h>
28 :
29 : #include <zephyr/types.h>
30 : #include <zephyr/device.h>
31 : #include <zephyr/sys/__assert.h>
32 : #include <zephyr/sys/slist.h>
33 :
34 : #ifdef __cplusplus
35 : extern "C" {
36 : #endif
37 :
38 : /* Clock control API */
39 :
40 : /* Used to select all subsystem of a clock controller */
41 0 : #define CLOCK_CONTROL_SUBSYS_ALL NULL
42 :
43 : /**
44 : * @brief Current clock status.
45 : */
46 0 : enum clock_control_status {
47 : CLOCK_CONTROL_STATUS_STARTING,
48 : CLOCK_CONTROL_STATUS_OFF,
49 : CLOCK_CONTROL_STATUS_ON,
50 : CLOCK_CONTROL_STATUS_UNKNOWN
51 : };
52 :
53 : /**
54 : * clock_control_subsys_t is a type to identify a clock controller sub-system.
55 : * Such data pointed is opaque and relevant only to the clock controller
56 : * driver instance being used.
57 : */
58 1 : typedef void *clock_control_subsys_t;
59 :
60 : /**
61 : * clock_control_subsys_rate_t is a type to identify a clock
62 : * controller sub-system rate. Such data pointed is opaque and
63 : * relevant only to set the clock controller rate of the driver
64 : * instance being used.
65 : */
66 1 : typedef void *clock_control_subsys_rate_t;
67 :
68 : /** @brief Callback called on clock started.
69 : *
70 : * @param dev Device structure whose driver controls the clock.
71 : * @param subsys Opaque data representing the clock.
72 : * @param user_data User data.
73 : */
74 1 : typedef void (*clock_control_cb_t)(const struct device *dev,
75 : clock_control_subsys_t subsys,
76 : void *user_data);
77 :
78 0 : typedef int (*clock_control)(const struct device *dev,
79 : clock_control_subsys_t sys);
80 :
81 0 : typedef int (*clock_control_get)(const struct device *dev,
82 : clock_control_subsys_t sys,
83 : uint32_t *rate);
84 :
85 0 : typedef int (*clock_control_async_on_fn)(const struct device *dev,
86 : clock_control_subsys_t sys,
87 : clock_control_cb_t cb,
88 : void *user_data);
89 :
90 : typedef enum clock_control_status (*clock_control_get_status_fn)(
91 : const struct device *dev,
92 : clock_control_subsys_t sys);
93 :
94 0 : typedef int (*clock_control_set)(const struct device *dev,
95 : clock_control_subsys_t sys,
96 : clock_control_subsys_rate_t rate);
97 :
98 0 : typedef int (*clock_control_configure_fn)(const struct device *dev,
99 : clock_control_subsys_t sys,
100 : void *data);
101 :
102 0 : __subsystem struct clock_control_driver_api {
103 0 : clock_control on;
104 0 : clock_control off;
105 0 : clock_control_async_on_fn async_on;
106 0 : clock_control_get get_rate;
107 0 : clock_control_get_status_fn get_status;
108 0 : clock_control_set set_rate;
109 0 : clock_control_configure_fn configure;
110 : };
111 :
112 : /**
113 : * @brief Enable a clock controlled by the device
114 : *
115 : * On success, the clock is enabled and ready when this function
116 : * returns. This function may sleep, and thus can only be called from
117 : * thread context.
118 : *
119 : * Use @ref clock_control_async_on() for non-blocking operation.
120 : *
121 : * @param dev Device structure whose driver controls the clock.
122 : * @param sys Opaque data representing the clock.
123 : * @return 0 on success, negative errno on failure.
124 : */
125 1 : static inline int clock_control_on(const struct device *dev,
126 : clock_control_subsys_t sys)
127 : {
128 : const struct clock_control_driver_api *api =
129 : (const struct clock_control_driver_api *)dev->api;
130 :
131 : return api->on(dev, sys);
132 : }
133 :
134 : /**
135 : * @brief Disable a clock controlled by the device
136 : *
137 : * This function is non-blocking and can be called from any context.
138 : * On success, the clock is disabled when this function returns.
139 : *
140 : * @param dev Device structure whose driver controls the clock
141 : * @param sys Opaque data representing the clock
142 : * @return 0 on success, negative errno on failure.
143 : */
144 1 : static inline int clock_control_off(const struct device *dev,
145 : clock_control_subsys_t sys)
146 : {
147 : const struct clock_control_driver_api *api =
148 : (const struct clock_control_driver_api *)dev->api;
149 :
150 : return api->off(dev, sys);
151 : }
152 :
153 : /**
154 : * @brief Request clock to start with notification when clock has been started.
155 : *
156 : * Function is non-blocking and can be called from any context. User callback is
157 : * called when clock is started.
158 : *
159 : * @param dev Device.
160 : * @param sys A pointer to an opaque data representing the sub-system.
161 : * @param cb Callback.
162 : * @param user_data User context passed to the callback.
163 : *
164 : * @retval 0 if start is successfully initiated.
165 : * @retval -EALREADY if clock was already started and is starting or running.
166 : * @retval -ENOTSUP If the requested mode of operation is not supported.
167 : * @retval -ENOSYS if the interface is not implemented.
168 : * @retval other negative errno on vendor specific error.
169 : */
170 1 : static inline int clock_control_async_on(const struct device *dev,
171 : clock_control_subsys_t sys,
172 : clock_control_cb_t cb,
173 : void *user_data)
174 : {
175 : const struct clock_control_driver_api *api =
176 : (const struct clock_control_driver_api *)dev->api;
177 :
178 : if (api->async_on == NULL) {
179 : return -ENOSYS;
180 : }
181 :
182 : return api->async_on(dev, sys, cb, user_data);
183 : }
184 :
185 : /**
186 : * @brief Get clock status.
187 : *
188 : * @param dev Device.
189 : * @param sys A pointer to an opaque data representing the sub-system.
190 : *
191 : * @return Status.
192 : */
193 1 : static inline enum clock_control_status clock_control_get_status(const struct device *dev,
194 : clock_control_subsys_t sys)
195 : {
196 : const struct clock_control_driver_api *api =
197 : (const struct clock_control_driver_api *)dev->api;
198 :
199 : if (!api->get_status) {
200 : return CLOCK_CONTROL_STATUS_UNKNOWN;
201 : }
202 :
203 : return api->get_status(dev, sys);
204 : }
205 :
206 : /**
207 : * @brief Obtain the clock rate of given sub-system
208 : * @param dev Pointer to the device structure for the clock controller driver
209 : * instance
210 : * @param sys A pointer to an opaque data representing the sub-system
211 : * @param[out] rate Subsystem clock rate
212 : * @retval 0 on successful rate reading.
213 : * @retval -EAGAIN if rate cannot be read. Some drivers do not support returning the rate when the
214 : * clock is off.
215 : * @retval -ENOTSUP if reading the clock rate is not supported for the given sub-system.
216 : * @retval -ENOSYS if the interface is not implemented.
217 : */
218 1 : static inline int clock_control_get_rate(const struct device *dev,
219 : clock_control_subsys_t sys,
220 : uint32_t *rate)
221 : {
222 : const struct clock_control_driver_api *api =
223 : (const struct clock_control_driver_api *)dev->api;
224 :
225 : if (api->get_rate == NULL) {
226 : return -ENOSYS;
227 : }
228 :
229 : return api->get_rate(dev, sys, rate);
230 : }
231 :
232 : /**
233 : * @brief Set the rate of the clock controlled by the device.
234 : *
235 : * On success, the new clock rate is set and ready when this function
236 : * returns. This function may sleep, and thus can only be called from
237 : * thread context.
238 : *
239 : * @param dev Device structure whose driver controls the clock.
240 : * @param sys Opaque data representing the clock.
241 : * @param rate Opaque data representing the clock rate to be used.
242 : *
243 : * @retval -EALREADY if clock was already in the given rate.
244 : * @retval -ENOTSUP If the requested mode of operation is not supported.
245 : * @retval -ENOSYS if the interface is not implemented.
246 : * @retval other negative errno on vendor specific error.
247 : */
248 1 : static inline int clock_control_set_rate(const struct device *dev,
249 : clock_control_subsys_t sys,
250 : clock_control_subsys_rate_t rate)
251 : {
252 : const struct clock_control_driver_api *api =
253 : (const struct clock_control_driver_api *)dev->api;
254 :
255 : if (api->set_rate == NULL) {
256 : return -ENOSYS;
257 : }
258 :
259 : return api->set_rate(dev, sys, rate);
260 : }
261 :
262 : /**
263 : * @brief Configure a source clock
264 : *
265 : * This function is non-blocking and can be called from any context.
266 : * On success, the selected clock is configured as per caller's request.
267 : *
268 : * It is caller's responsibility to ensure that subsequent calls to the API
269 : * provide the right information to allows clock_control driver to perform
270 : * the right action (such as using the right clock source on clock_control_get_rate
271 : * call).
272 : *
273 : * @p data is implementation specific and could be used to convey
274 : * supplementary information required for expected clock configuration.
275 : *
276 : * @param dev Device structure whose driver controls the clock
277 : * @param sys Opaque data representing the clock
278 : * @param data Opaque data providing additional input for clock configuration
279 : *
280 : * @retval 0 On success
281 : * @retval -ENOSYS If the device driver does not implement this call
282 : * @retval -errno Other negative errno on failure.
283 : */
284 1 : static inline int clock_control_configure(const struct device *dev,
285 : clock_control_subsys_t sys,
286 : void *data)
287 : {
288 : const struct clock_control_driver_api *api =
289 : (const struct clock_control_driver_api *)dev->api;
290 :
291 : if (api->configure == NULL) {
292 : return -ENOSYS;
293 : }
294 :
295 : return api->configure(dev, sys, data);
296 : }
297 :
298 : #ifdef __cplusplus
299 : }
300 : #endif
301 :
302 : /**
303 : * @}
304 : */
305 :
306 : #endif /* ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_H_ */
|