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 : if (api->on == NULL) {
132 : return -ENOSYS;
133 : }
134 :
135 : return api->on(dev, sys);
136 : }
137 :
138 : /**
139 : * @brief Disable a clock controlled by the device
140 : *
141 : * This function is non-blocking and can be called from any context.
142 : * On success, the clock is disabled when this function returns.
143 : *
144 : * @param dev Device structure whose driver controls the clock
145 : * @param sys Opaque data representing the clock
146 : * @return 0 on success, negative errno on failure.
147 : */
148 1 : static inline int clock_control_off(const struct device *dev,
149 : clock_control_subsys_t sys)
150 : {
151 : const struct clock_control_driver_api *api =
152 : (const struct clock_control_driver_api *)dev->api;
153 :
154 : if (api->off == NULL) {
155 : return -ENOSYS;
156 : }
157 :
158 : return api->off(dev, sys);
159 : }
160 :
161 : /**
162 : * @brief Request clock to start with notification when clock has been started.
163 : *
164 : * Function is non-blocking and can be called from any context. User callback is
165 : * called when clock is started.
166 : *
167 : * @param dev Device.
168 : * @param sys A pointer to an opaque data representing the sub-system.
169 : * @param cb Callback.
170 : * @param user_data User context passed to the callback.
171 : *
172 : * @retval 0 if start is successfully initiated.
173 : * @retval -EALREADY if clock was already started and is starting or running.
174 : * @retval -ENOTSUP If the requested mode of operation is not supported.
175 : * @retval -ENOSYS if the interface is not implemented.
176 : * @retval other negative errno on vendor specific error.
177 : */
178 1 : static inline int clock_control_async_on(const struct device *dev,
179 : clock_control_subsys_t sys,
180 : clock_control_cb_t cb,
181 : void *user_data)
182 : {
183 : const struct clock_control_driver_api *api =
184 : (const struct clock_control_driver_api *)dev->api;
185 :
186 : if (api->async_on == NULL) {
187 : return -ENOSYS;
188 : }
189 :
190 : return api->async_on(dev, sys, cb, user_data);
191 : }
192 :
193 : /**
194 : * @brief Get clock status.
195 : *
196 : * @param dev Device.
197 : * @param sys A pointer to an opaque data representing the sub-system.
198 : *
199 : * @return Status.
200 : */
201 1 : static inline enum clock_control_status clock_control_get_status(const struct device *dev,
202 : clock_control_subsys_t sys)
203 : {
204 : const struct clock_control_driver_api *api =
205 : (const struct clock_control_driver_api *)dev->api;
206 :
207 : if (!api->get_status) {
208 : return CLOCK_CONTROL_STATUS_UNKNOWN;
209 : }
210 :
211 : return api->get_status(dev, sys);
212 : }
213 :
214 : /**
215 : * @brief Obtain the clock rate of given sub-system
216 : * @param dev Pointer to the device structure for the clock controller driver
217 : * instance
218 : * @param sys A pointer to an opaque data representing the sub-system
219 : * @param[out] rate Subsystem clock rate
220 : * @retval 0 on successful rate reading.
221 : * @retval -EAGAIN if rate cannot be read. Some drivers do not support returning the rate when the
222 : * clock is off.
223 : * @retval -ENOTSUP if reading the clock rate is not supported for the given sub-system.
224 : * @retval -ENOSYS if the interface is not implemented.
225 : */
226 1 : static inline int clock_control_get_rate(const struct device *dev,
227 : clock_control_subsys_t sys,
228 : uint32_t *rate)
229 : {
230 : const struct clock_control_driver_api *api =
231 : (const struct clock_control_driver_api *)dev->api;
232 :
233 : if (api->get_rate == NULL) {
234 : return -ENOSYS;
235 : }
236 :
237 : return api->get_rate(dev, sys, rate);
238 : }
239 :
240 : /**
241 : * @brief Set the rate of the clock controlled by the device.
242 : *
243 : * On success, the new clock rate is set and ready when this function
244 : * returns. This function may sleep, and thus can only be called from
245 : * thread context.
246 : *
247 : * @param dev Device structure whose driver controls the clock.
248 : * @param sys Opaque data representing the clock.
249 : * @param rate Opaque data representing the clock rate to be used.
250 : *
251 : * @retval -EALREADY if clock was already in the given rate.
252 : * @retval -ENOTSUP If the requested mode of operation is not supported.
253 : * @retval -ENOSYS if the interface is not implemented.
254 : * @retval other negative errno on vendor specific error.
255 : */
256 1 : static inline int clock_control_set_rate(const struct device *dev,
257 : clock_control_subsys_t sys,
258 : clock_control_subsys_rate_t rate)
259 : {
260 : const struct clock_control_driver_api *api =
261 : (const struct clock_control_driver_api *)dev->api;
262 :
263 : if (api->set_rate == NULL) {
264 : return -ENOSYS;
265 : }
266 :
267 : return api->set_rate(dev, sys, rate);
268 : }
269 :
270 : /**
271 : * @brief Configure a source clock
272 : *
273 : * This function is non-blocking and can be called from any context.
274 : * On success, the selected clock is configured as per caller's request.
275 : *
276 : * It is caller's responsibility to ensure that subsequent calls to the API
277 : * provide the right information to allows clock_control driver to perform
278 : * the right action (such as using the right clock source on clock_control_get_rate
279 : * call).
280 : *
281 : * @p data is implementation specific and could be used to convey
282 : * supplementary information required for expected clock configuration.
283 : *
284 : * @param dev Device structure whose driver controls the clock
285 : * @param sys Opaque data representing the clock
286 : * @param data Opaque data providing additional input for clock configuration
287 : *
288 : * @retval 0 On success
289 : * @retval -ENOSYS If the device driver does not implement this call
290 : * @retval -errno Other negative errno on failure.
291 : */
292 1 : static inline int clock_control_configure(const struct device *dev,
293 : clock_control_subsys_t sys,
294 : void *data)
295 : {
296 : const struct clock_control_driver_api *api =
297 : (const struct clock_control_driver_api *)dev->api;
298 :
299 : if (api->configure == NULL) {
300 : return -ENOSYS;
301 : }
302 :
303 : return api->configure(dev, sys, data);
304 : }
305 :
306 : #ifdef __cplusplus
307 : }
308 : #endif
309 :
310 : /**
311 : * @}
312 : */
313 :
314 : #endif /* ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_H_ */
|