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