Line data Source code
1 0 : /*
2 : * Copyright (c) 2016 Nordic Semiconductor ASA
3 : *
4 : * SPDX-License-Identifier: Apache-2.0
5 : */
6 :
7 : #ifndef ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_NRF_CLOCK_CONTROL_H_
8 : #define ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_NRF_CLOCK_CONTROL_H_
9 :
10 : #include <zephyr/device.h>
11 : #include <zephyr/sys/onoff.h>
12 : #include <zephyr/drivers/clock_control.h>
13 :
14 : #ifdef __cplusplus
15 : extern "C" {
16 : #endif
17 :
18 : #if defined(CONFIG_CLOCK_CONTROL_NRF)
19 :
20 : #include <hal/nrf_clock.h>
21 :
22 : /** @brief Clocks handled by the CLOCK peripheral.
23 : *
24 : * Enum shall be used as a sys argument in clock_control API.
25 : */
26 : enum clock_control_nrf_type {
27 : CLOCK_CONTROL_NRF_TYPE_HFCLK,
28 : CLOCK_CONTROL_NRF_TYPE_LFCLK,
29 : #if NRF_CLOCK_HAS_HFCLK24M
30 : CLOCK_CONTROL_NRF_TYPE_HFCLK24M,
31 : #endif
32 : #if NRF_CLOCK_HAS_HFCLK192M
33 : CLOCK_CONTROL_NRF_TYPE_HFCLK192M,
34 : #endif
35 : #if NRF_CLOCK_HAS_HFCLKAUDIO
36 : CLOCK_CONTROL_NRF_TYPE_HFCLKAUDIO,
37 : #endif
38 : CLOCK_CONTROL_NRF_TYPE_COUNT
39 : };
40 :
41 : /* Define can be used with clock control API instead of enum directly to
42 : * increase code readability.
43 : */
44 : #define CLOCK_CONTROL_NRF_SUBSYS_HF \
45 : ((clock_control_subsys_t)CLOCK_CONTROL_NRF_TYPE_HFCLK)
46 : #define CLOCK_CONTROL_NRF_SUBSYS_LF \
47 : ((clock_control_subsys_t)CLOCK_CONTROL_NRF_TYPE_LFCLK)
48 : #define CLOCK_CONTROL_NRF_SUBSYS_HF24M \
49 : ((clock_control_subsys_t)CLOCK_CONTROL_NRF_TYPE_HFCLK24M)
50 : #define CLOCK_CONTROL_NRF_SUBSYS_HF192M \
51 : ((clock_control_subsys_t)CLOCK_CONTROL_NRF_TYPE_HFCLK192M)
52 : #define CLOCK_CONTROL_NRF_SUBSYS_HFAUDIO \
53 : ((clock_control_subsys_t)CLOCK_CONTROL_NRF_TYPE_HFCLKAUDIO)
54 :
55 : /** @brief LF clock start modes. */
56 : enum nrf_lfclk_start_mode {
57 : CLOCK_CONTROL_NRF_LF_START_NOWAIT,
58 : CLOCK_CONTROL_NRF_LF_START_AVAILABLE,
59 : CLOCK_CONTROL_NRF_LF_START_STABLE,
60 : };
61 :
62 : /* Define 32KHz clock source */
63 : #ifdef CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC
64 : #define CLOCK_CONTROL_NRF_K32SRC NRF_CLOCK_LFCLK_RC
65 : #endif
66 : #ifdef CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL
67 : #define CLOCK_CONTROL_NRF_K32SRC NRF_CLOCK_LFCLK_XTAL
68 : #endif
69 : #ifdef CONFIG_CLOCK_CONTROL_NRF_K32SRC_SYNTH
70 : #define CLOCK_CONTROL_NRF_K32SRC NRF_CLOCK_LFCLK_SYNTH
71 : #endif
72 : #ifdef CONFIG_CLOCK_CONTROL_NRF_K32SRC_EXT_LOW_SWING
73 : #define CLOCK_CONTROL_NRF_K32SRC NRF_CLOCK_LFCLK_XTAL_LOW_SWING
74 : #endif
75 : #ifdef CONFIG_CLOCK_CONTROL_NRF_K32SRC_EXT_FULL_SWING
76 : #define CLOCK_CONTROL_NRF_K32SRC NRF_CLOCK_LFCLK_XTAL_FULL_SWING
77 : #endif
78 :
79 : /* Define 32KHz clock accuracy */
80 : #ifdef CONFIG_CLOCK_CONTROL_NRF_K32SRC_500PPM
81 : #define CLOCK_CONTROL_NRF_K32SRC_ACCURACY 0
82 : #endif
83 : #ifdef CONFIG_CLOCK_CONTROL_NRF_K32SRC_250PPM
84 : #define CLOCK_CONTROL_NRF_K32SRC_ACCURACY 1
85 : #endif
86 : #ifdef CONFIG_CLOCK_CONTROL_NRF_K32SRC_150PPM
87 : #define CLOCK_CONTROL_NRF_K32SRC_ACCURACY 2
88 : #endif
89 : #ifdef CONFIG_CLOCK_CONTROL_NRF_K32SRC_100PPM
90 : #define CLOCK_CONTROL_NRF_K32SRC_ACCURACY 3
91 : #endif
92 : #ifdef CONFIG_CLOCK_CONTROL_NRF_K32SRC_75PPM
93 : #define CLOCK_CONTROL_NRF_K32SRC_ACCURACY 4
94 : #endif
95 : #ifdef CONFIG_CLOCK_CONTROL_NRF_K32SRC_50PPM
96 : #define CLOCK_CONTROL_NRF_K32SRC_ACCURACY 5
97 : #endif
98 : #ifdef CONFIG_CLOCK_CONTROL_NRF_K32SRC_30PPM
99 : #define CLOCK_CONTROL_NRF_K32SRC_ACCURACY 6
100 : #endif
101 : #ifdef CONFIG_CLOCK_CONTROL_NRF_K32SRC_20PPM
102 : #define CLOCK_CONTROL_NRF_K32SRC_ACCURACY 7
103 : #endif
104 :
105 : /** @brief Force LF clock calibration. */
106 : void z_nrf_clock_calibration_force_start(void);
107 :
108 : /** @brief Return number of calibrations performed.
109 : *
110 : * Valid when @kconfig{CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_DEBUG} is set.
111 : *
112 : * @return Number of calibrations or -1 if feature is disabled.
113 : */
114 : int z_nrf_clock_calibration_count(void);
115 :
116 : /** @brief Return number of attempts when calibration was skipped.
117 : *
118 : * Valid when @kconfig{CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_DEBUG} is set.
119 : *
120 : * @return Number of calibrations or -1 if feature is disabled.
121 : */
122 : int z_nrf_clock_calibration_skips_count(void);
123 :
124 :
125 : /** @brief Returns information if LF clock calibration is in progress.
126 : *
127 : * @return True if calibration is in progress, false otherwise.
128 : */
129 : bool z_nrf_clock_calibration_is_in_progress(void);
130 :
131 : /** @brief Get onoff service for given clock subsystem.
132 : *
133 : * @param sys Subsystem.
134 : *
135 : * @return Service handler or NULL.
136 : */
137 : struct onoff_manager *z_nrf_clock_control_get_onoff(clock_control_subsys_t sys);
138 :
139 : /** @brief Permanently enable low frequency clock.
140 : *
141 : * Low frequency clock is usually enabled during application lifetime because
142 : * of long startup time and low power consumption. Multiple modules can request
143 : * it but never release.
144 : *
145 : * @param start_mode Specify if function should block until clock is available.
146 : */
147 : void z_nrf_clock_control_lf_on(enum nrf_lfclk_start_mode start_mode);
148 :
149 : /** @brief Request high frequency clock from Bluetooth Controller.
150 : *
151 : * Function is optimized for Bluetooth Controller which turns HF clock before
152 : * each radio activity and has hard timing requirements but does not require
153 : * any confirmation when clock is ready because it assumes that request is
154 : * performed long enough before radio activity. Clock is released immediately
155 : * after radio activity.
156 : *
157 : * Function does not perform any validation. It is the caller responsibility to
158 : * ensure that every z_nrf_clock_bt_ctlr_hf_request matches
159 : * z_nrf_clock_bt_ctlr_hf_release call.
160 : */
161 : void z_nrf_clock_bt_ctlr_hf_request(void);
162 :
163 : /** @brief Release high frequency clock from Bluetooth Controller.
164 : *
165 : * See z_nrf_clock_bt_ctlr_hf_request for details.
166 : */
167 : void z_nrf_clock_bt_ctlr_hf_release(void);
168 :
169 : /**
170 : * @brief Get clock startup time
171 : *
172 : * @retval HFCLK startup time in microseconds
173 : */
174 : uint32_t z_nrf_clock_bt_ctlr_hf_get_startup_time_us(void);
175 :
176 : #endif /* defined(CONFIG_CLOCK_CONTROL_NRF) */
177 :
178 : /* Specifies to use the maximum available frequency for a given clock. */
179 0 : #define NRF_CLOCK_CONTROL_FREQUENCY_MAX UINT32_MAX
180 :
181 : /* Specifies to use the maximum available accuracy for a given clock. */
182 0 : #define NRF_CLOCK_CONTROL_ACCURACY_MAX 1
183 : /* Specifies the required clock accuracy in parts-per-million. */
184 0 : #define NRF_CLOCK_CONTROL_ACCURACY_PPM(ppm) (ppm)
185 :
186 : /* Specifies that high precision of the clock is required. */
187 0 : #define NRF_CLOCK_CONTROL_PRECISION_HIGH 1
188 : /* Specifies that default precision of the clock is sufficient. */
189 0 : #define NRF_CLOCK_CONTROL_PRECISION_DEFAULT 0
190 :
191 0 : struct nrf_clock_spec {
192 0 : uint32_t frequency;
193 0 : uint16_t accuracy : 15;
194 0 : uint16_t precision : 1;
195 : };
196 :
197 0 : __subsystem struct nrf_clock_control_driver_api {
198 0 : struct clock_control_driver_api std_api;
199 :
200 0 : int (*request)(const struct device *dev,
201 : const struct nrf_clock_spec *spec,
202 : struct onoff_client *cli);
203 0 : int (*release)(const struct device *dev,
204 : const struct nrf_clock_spec *spec);
205 0 : int (*cancel_or_release)(const struct device *dev,
206 : const struct nrf_clock_spec *spec,
207 : struct onoff_client *cli);
208 0 : int (*resolve)(const struct device *dev,
209 : const struct nrf_clock_spec *req_spec,
210 : struct nrf_clock_spec *res_spec);
211 0 : int (*get_startup_time)(const struct device *dev,
212 : const struct nrf_clock_spec *spec,
213 : uint32_t *startup_time_us);
214 : };
215 :
216 : /**
217 : * @brief Request a reservation to use a given clock with specified attributes.
218 : *
219 : * The return value indicates the success or failure of an attempt to initiate
220 : * an operation to request the clock be made available. If initiation of the
221 : * operation succeeds, the result of the request operation is provided through
222 : * the configured client notification method, possibly before this call returns.
223 : *
224 : * Note that the call to this function may succeed in a case where the actual
225 : * request fails. Always check the operation completion result.
226 : *
227 : * @param dev pointer to the clock device structure.
228 : * @param spec specification of minimal acceptable attributes, like frequency,
229 : * accuracy, and precision, required for the clock.
230 : * Value of 0 has the meaning of "default" and can be passed
231 : * instead of a given attribute if there is no strict requirement
232 : * in this regard. If there is no specific requirement for any of
233 : * the attributes, this parameter can be NULL.
234 : * @param cli pointer to client state providing instructions on synchronous
235 : * expectations and how to notify the client when the request
236 : * completes. Behavior is undefined if client passes a pointer
237 : * object associated with an incomplete service operation.
238 : *
239 : * @retval non-negative the observed state of the on-off service associated
240 : * with the clock machine at the time the request was
241 : * processed (see onoff_request()), if successful.
242 : * @retval -EIO if service has recorded an error.
243 : * @retval -EINVAL if the function parameters are invalid or the clock
244 : * attributes cannot be provided (e.g. the requested accuracy
245 : * is unavailable).
246 : * @retval -EAGAIN if the reference count would overflow.
247 : */
248 : static inline
249 1 : int nrf_clock_control_request(const struct device *dev,
250 : const struct nrf_clock_spec *spec,
251 : struct onoff_client *cli)
252 : {
253 : const struct nrf_clock_control_driver_api *api =
254 : (const struct nrf_clock_control_driver_api *)dev->api;
255 :
256 : return api->request(dev, spec, cli);
257 : }
258 :
259 : /**
260 : * @brief Synchronously request a reservation to use a given clock with specified attributes.
261 : *
262 : * Function can only be called from thread context as it blocks until request is completed.
263 : * @see nrf_clock_control_request().
264 : *
265 : * @param dev pointer to the clock device structure.
266 : * @param spec See nrf_clock_control_request().
267 : * @param timeout Request timeout.
268 : *
269 : * @retval 0 if request is fulfilled.
270 : * @retval -EWOULDBLOCK if request is called from the interrupt context.
271 : * @retval negative See error codes returned by nrf_clock_control_request().
272 : */
273 1 : int nrf_clock_control_request_sync(const struct device *dev,
274 : const struct nrf_clock_spec *spec,
275 : k_timeout_t timeout);
276 :
277 : /**
278 : * @brief Release a reserved use of a clock.
279 : *
280 : * @param dev pointer to the clock device structure.
281 : * @param spec the same specification of the clock attributes that was used
282 : * in the reservation request (so that the clock control module
283 : * can keep track of what attributes are still requested).
284 : *
285 : * @retval non-negative the observed state of the on-off service associated
286 : * with the clock machine at the time the request was
287 : * processed (see onoff_release()), if successful.
288 : * @retval -EIO if service has recorded an error.
289 : * @retval -ENOTSUP if the service is not in a state that permits release.
290 : */
291 : static inline
292 1 : int nrf_clock_control_release(const struct device *dev,
293 : const struct nrf_clock_spec *spec)
294 : {
295 : const struct nrf_clock_control_driver_api *api =
296 : (const struct nrf_clock_control_driver_api *)dev->api;
297 :
298 : return api->release(dev, spec);
299 : }
300 :
301 : /**
302 : * @brief Safely cancel a reservation request.
303 : *
304 : * It may be that a client has issued a reservation request but needs to
305 : * shut down before the request has completed. This function attempts to
306 : * cancel the request and issues a release if cancellation fails because
307 : * the request was completed. This synchronously ensures that ownership
308 : * data reverts to the client so is available for a future request.
309 : *
310 : * @param dev pointer to the clock device structure.
311 : * @param spec the same specification of the clock attributes that was used
312 : * in the reservation request.
313 : * @param cli a pointer to the same client state that was provided
314 : * when the operation to be cancelled was issued.
315 : *
316 : * @retval ONOFF_STATE_TO_ON if the cancellation occurred before the transition
317 : * completed.
318 : * @retval ONOFF_STATE_ON if the cancellation occurred after the transition
319 : * completed.
320 : * @retval -EINVAL if the parameters are invalid.
321 : * @retval negative other errors produced by onoff_release().
322 : */
323 : static inline
324 1 : int nrf_clock_control_cancel_or_release(const struct device *dev,
325 : const struct nrf_clock_spec *spec,
326 : struct onoff_client *cli)
327 : {
328 : const struct nrf_clock_control_driver_api *api =
329 : (const struct nrf_clock_control_driver_api *)dev->api;
330 :
331 : return api->cancel_or_release(dev, spec, cli);
332 : }
333 :
334 : /**
335 : * @brief Resolve a requested clock spec to resulting spec.
336 : *
337 : * @param dev Device structure.
338 : * @param req_spec The requested clock specification.
339 : * @param res_spec Destination for the resulting clock specification.
340 : *
341 : * @retval Successful if successful.
342 : * @retval -errno code if failure
343 : */
344 1 : static inline int nrf_clock_control_resolve(const struct device *dev,
345 : const struct nrf_clock_spec *req_spec,
346 : struct nrf_clock_spec *res_spec)
347 : {
348 : const struct nrf_clock_control_driver_api *api =
349 : (const struct nrf_clock_control_driver_api *)dev->api;
350 :
351 : if (api->resolve == NULL) {
352 : return -ENOSYS;
353 : }
354 :
355 : return api->resolve(dev, req_spec, res_spec);
356 : }
357 :
358 : /**
359 : * @brief Get the startup time of a clock.
360 : *
361 : * @param dev Device structure.
362 : * @param spec Clock specification to get startup time for.
363 : * @param startup_time_us Destination for startup time in microseconds.
364 : *
365 : * @retval Successful if successful.
366 : * @retval -errno code if failure.
367 : */
368 1 : static inline int nrf_clock_control_get_startup_time(const struct device *dev,
369 : const struct nrf_clock_spec *spec,
370 : uint32_t *startup_time_us)
371 : {
372 : const struct nrf_clock_control_driver_api *api =
373 : (const struct nrf_clock_control_driver_api *)dev->api;
374 :
375 : if (api->get_startup_time == NULL) {
376 : return -ENOSYS;
377 : }
378 :
379 : return api->get_startup_time(dev, spec, startup_time_us);
380 : }
381 :
382 : /** @brief Request the HFXO from Zero Latency Interrupt context.
383 : *
384 : * Function is optimized for use in Zero Latency Interrupt context.
385 : * It does not give notification when the HFXO is ready, so each
386 : * user must put the request early enough to make sure the HFXO
387 : * ramp-up has finished on time.
388 : *
389 : * This function uses reference counting so the caller must ensure
390 : * that every nrf_clock_control_hfxo_request() call has a matching
391 : * nrf_clock_control_hfxo_release() call.
392 : */
393 1 : void nrf_clock_control_hfxo_request(void);
394 :
395 : /** @brief Release the HFXO from Zero Latency Interrupt context.
396 : *
397 : * Function is optimized for use in Zero Latency Interrupt context.
398 : *
399 : * Calls to this function must be coupled with prior calls
400 : * to nrf_clock_control_hfxo_request(), because it uses basic
401 : * reference counting to make sure the HFXO is released when
402 : * there are no more pending requests.
403 : */
404 1 : void nrf_clock_control_hfxo_release(void);
405 :
406 : #ifdef __cplusplus
407 : }
408 : #endif
409 :
410 : #endif /* ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_NRF_CLOCK_CONTROL_H_ */
|