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 #define CLOCK_CONTROL_SUBSYS_ALL NULL
42
43 /**
44 * @brief Current clock status.
45 */
46 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 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 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 typedef void (*clock_control_cb_t)(const struct device *dev,
75 clock_control_subsys_t subsys,
76 void *user_data);
77
78 typedef int (*clock_control)(const struct device *dev,
79 clock_control_subsys_t sys);
80
81 typedef int (*clock_control_get)(const struct device *dev,
82 clock_control_subsys_t sys,
83 uint32_t *rate);
84
85 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 typedef int (*clock_control_set)(const struct device *dev,
95 clock_control_subsys_t sys,
96 clock_control_subsys_rate_t rate);
97
98 typedef int (*clock_control_configure_fn)(const struct device *dev,
99 clock_control_subsys_t sys,
100 void *data);
101
102 __subsystem struct clock_control_driver_api {
103 clock_control on;
104 clock_control off;
105 clock_control_async_on_fn async_on;
106 clock_control_get get_rate;
107 clock_control_get_status_fn get_status;
108 clock_control_set set_rate;
109 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 */
clock_control_on(const struct device * dev,clock_control_subsys_t sys)125 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 */
clock_control_off(const struct device * dev,clock_control_subsys_t sys)148 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 */
clock_control_async_on(const struct device * dev,clock_control_subsys_t sys,clock_control_cb_t cb,void * user_data)178 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 */
clock_control_get_status(const struct device * dev,clock_control_subsys_t sys)201 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 */
clock_control_get_rate(const struct device * dev,clock_control_subsys_t sys,uint32_t * rate)226 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 */
clock_control_set_rate(const struct device * dev,clock_control_subsys_t sys,clock_control_subsys_rate_t rate)256 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 */
clock_control_configure(const struct device * dev,clock_control_subsys_t sys,void * data)292 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_ */
315