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 	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  */
clock_control_off(const struct device * dev,clock_control_subsys_t sys)144 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  */
clock_control_async_on(const struct device * dev,clock_control_subsys_t sys,clock_control_cb_t cb,void * user_data)170 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  */
clock_control_get_status(const struct device * dev,clock_control_subsys_t sys)193 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  */
clock_control_get_rate(const struct device * dev,clock_control_subsys_t sys,uint32_t * rate)218 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  */
clock_control_set_rate(const struct device * dev,clock_control_subsys_t sys,clock_control_subsys_rate_t rate)248 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  */
clock_control_configure(const struct device * dev,clock_control_subsys_t sys,void * data)284 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_ */
307