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