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 * @ingroup io_interfaces
21 * @{
22 */
23
24 #include <zephyr/types.h>
25 #include <stddef.h>
26 #include <device.h>
27 #include <sys/__assert.h>
28 #include <sys/slist.h>
29
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33
34 /* Clock control API */
35
36 /* Used to select all subsystem of a clock controller */
37 #define CLOCK_CONTROL_SUBSYS_ALL NULL
38
39 /**
40 * @brief Current clock status.
41 */
42 enum clock_control_status {
43 CLOCK_CONTROL_STATUS_STARTING,
44 CLOCK_CONTROL_STATUS_OFF,
45 CLOCK_CONTROL_STATUS_ON,
46 CLOCK_CONTROL_STATUS_UNAVAILABLE,
47 CLOCK_CONTROL_STATUS_UNKNOWN
48 };
49
50 /**
51 * clock_control_subsys_t is a type to identify a clock controller sub-system.
52 * Such data pointed is opaque and relevant only to the clock controller
53 * driver instance being used.
54 */
55 typedef void *clock_control_subsys_t;
56
57 /** @brief Callback called on clock started.
58 *
59 * @param dev Device structure whose driver controls the clock.
60 * @param subsys Opaque data representing the clock.
61 * @param user_data User data.
62 */
63 typedef void (*clock_control_cb_t)(const struct device *dev,
64 clock_control_subsys_t subsys,
65 void *user_data);
66
67 typedef int (*clock_control)(const struct device *dev,
68 clock_control_subsys_t sys);
69
70 typedef int (*clock_control_get)(const struct device *dev,
71 clock_control_subsys_t sys,
72 uint32_t *rate);
73
74 typedef int (*clock_control_async_on_fn)(const struct device *dev,
75 clock_control_subsys_t sys,
76 clock_control_cb_t cb,
77 void *user_data);
78
79 typedef enum clock_control_status (*clock_control_get_status_fn)(
80 const struct device *dev,
81 clock_control_subsys_t sys);
82
83 struct clock_control_driver_api {
84 clock_control on;
85 clock_control off;
86 clock_control_async_on_fn async_on;
87 clock_control_get get_rate;
88 clock_control_get_status_fn get_status;
89 };
90
91 /**
92 * @brief Enable a clock controlled by the device
93 *
94 * On success, the clock is enabled and ready when this function
95 * returns. This function may sleep, and thus can only be called from
96 * thread context.
97 *
98 * Use @ref clock_control_async_on() for non-blocking operation.
99 *
100 * @param dev Device structure whose driver controls the clock.
101 * @param sys Opaque data representing the clock.
102 * @return 0 on success, negative errno on failure.
103 */
clock_control_on(const struct device * dev,clock_control_subsys_t sys)104 static inline int clock_control_on(const struct device *dev,
105 clock_control_subsys_t sys)
106 {
107 int ret = device_usable_check(dev);
108
109 if (ret != 0) {
110 return ret;
111 }
112
113 const struct clock_control_driver_api *api =
114 (const struct clock_control_driver_api *)dev->api;
115
116 return api->on(dev, sys);
117 }
118
119 /**
120 * @brief Disable a clock controlled by the device
121 *
122 * This function is non-blocking and can be called from any context.
123 * On success, the clock is disabled when this function returns.
124 *
125 * @param dev Device structure whose driver controls the clock
126 * @param sys Opaque data representing the clock
127 * @return 0 on success, negative errno on failure.
128 */
clock_control_off(const struct device * dev,clock_control_subsys_t sys)129 static inline int clock_control_off(const struct device *dev,
130 clock_control_subsys_t sys)
131 {
132 int ret = device_usable_check(dev);
133
134 if (ret != 0) {
135 return ret;
136 }
137
138 const struct clock_control_driver_api *api =
139 (const struct clock_control_driver_api *)dev->api;
140
141 return api->off(dev, sys);
142 }
143
144 /**
145 * @brief Request clock to start with notification when clock has been started.
146 *
147 * Function is non-blocking and can be called from any context. User callback is
148 * called when clock is started.
149 *
150 * @param dev Device.
151 * @param sys A pointer to an opaque data representing the sub-system.
152 * @param cb Callback.
153 * @param user_data User context passed to the callback.
154 *
155 * @retval 0 if start is successfully initiated.
156 * @retval -EALREADY if clock was already started and is starting or running.
157 * @retval -ENOTSUP If the requested mode of operation is not supported.
158 * @retval -ENOSYS if the interface is not implemented.
159 * @retval other negative errno on vendor specific error.
160 */
clock_control_async_on(const struct device * dev,clock_control_subsys_t sys,clock_control_cb_t cb,void * user_data)161 static inline int clock_control_async_on(const struct device *dev,
162 clock_control_subsys_t sys,
163 clock_control_cb_t cb,
164 void *user_data)
165 {
166 const struct clock_control_driver_api *api =
167 (const struct clock_control_driver_api *)dev->api;
168
169 if (api->async_on == NULL) {
170 return -ENOSYS;
171 }
172
173 int ret = device_usable_check(dev);
174
175 if (ret != 0) {
176 return ret;
177 }
178
179 return api->async_on(dev, sys, cb, user_data);
180 }
181
182 /**
183 * @brief Get clock status.
184 *
185 * @param dev Device.
186 * @param sys A pointer to an opaque data representing the sub-system.
187 *
188 * @return Status.
189 */
clock_control_get_status(const struct device * dev,clock_control_subsys_t sys)190 static inline enum clock_control_status clock_control_get_status(const struct device *dev,
191 clock_control_subsys_t sys)
192 {
193 const struct clock_control_driver_api *api =
194 (const struct clock_control_driver_api *)dev->api;
195
196 if (!api->get_status) {
197 return CLOCK_CONTROL_STATUS_UNKNOWN;
198 }
199
200 if (!device_is_ready(dev)) {
201 return CLOCK_CONTROL_STATUS_UNAVAILABLE;
202 }
203
204 return api->get_status(dev, sys);
205 }
206
207 /**
208 * @brief Obtain the clock rate of given sub-system
209 * @param dev Pointer to the device structure for the clock controller driver
210 * instance
211 * @param sys A pointer to an opaque data representing the sub-system
212 * @param[out] rate Subsystem clock rate
213 */
clock_control_get_rate(const struct device * dev,clock_control_subsys_t sys,uint32_t * rate)214 static inline int clock_control_get_rate(const struct device *dev,
215 clock_control_subsys_t sys,
216 uint32_t *rate)
217 {
218 int ret = device_usable_check(dev);
219
220 if (ret != 0) {
221 return ret;
222 }
223
224 const struct clock_control_driver_api *api =
225 (const struct clock_control_driver_api *)dev->api;
226
227 if (api->get_rate == NULL) {
228 return -ENOSYS;
229 }
230
231 return api->get_rate(dev, sys, rate);
232 }
233
234 #ifdef __cplusplus
235 }
236 #endif
237
238 /**
239 * @}
240 */
241
242 #endif /* ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_H_ */
243