1 /*******************************************************************************
2 * File Name: cyhal_clock.h
3 *
4 * Description:
5 * Provides a high level interface for interacting with the Clocks on the device.
6 *
7 ********************************************************************************
8 * \copyright
9 * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or
10 * an affiliate of Cypress Semiconductor Corporation
11 *
12 * SPDX-License-Identifier: Apache-2.0
13 *
14 * Licensed under the Apache License, Version 2.0 (the "License");
15 * you may not use this file except in compliance with the License.
16 * You may obtain a copy of the License at
17 *
18 *     http://www.apache.org/licenses/LICENSE-2.0
19 *
20 * Unless required by applicable law or agreed to in writing, software
21 * distributed under the License is distributed on an "AS IS" BASIS,
22 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 * See the License for the specific language governing permissions and
24 * limitations under the License.
25 *******************************************************************************/
26 
27 /**
28 * \addtogroup group_hal_clock Clock
29 * \ingroup group_hal
30 * \{
31 * Interface for getting and changing clock configuration.
32 *
33 * The clock driver is a single API designed to allow reading and configuring
34 * any clock in the system. The driver works the same to configure System clocks
35 * as it does for Peripheral clocks. It supports both a readonly mode where any
36 * number of items can get information about the clock. Alternatively, each
37 * clock can have a single owner that is able to adjust the configuration of the
38 * clock.
39 *
40 * This driver supports source clocks, clock dividers, and clock signal muxes.
41 * All clock objects support the get() functions. Only some clocks support
42 * setting specific attributes. Use the \ref cyhal_clock_get_features() function
43 * to determine which features are settable for a specific clock. Calling a set()
44 * function on a clock that does not support it will return an error.
45 *
46 * This driver makes no assumptions about how the device is currently configured.
47 * It can be used from a completely unconfigured system (eg: device just booted)
48 * to a fully pre-configured (eg: setup by the Device Configurator). The drivers
49 * query and modify the actual state of the hardware, there is no caching or
50 * remembering of state. To maximize portability of code, it is often convenient
51 * to place all system clock configuration into a Board Support Package (BSP) so
52 * the main application code is flexible and can port between devices.
53 *
54 * All System Clock instances are available as constant variables in the
55 * implementation specific header. These clocks can be used directly to call
56 * any get() function. Similarly, \ref cyhal_clock_get allows for getting
57 * access to a specific clock object given a resource instance. Like the
58 * constant variables, this clock reference can be used to call any of the
59 * get() functions at any time. If a clock needs to be modified, either
60 * \ref cyhal_clock_allocate or \ref cyhal_clock_reserve must be called to
61 * obtain a lock on the clock object and to ensure that nothing else in the
62 * application is currently using it or assuming its configuration is stable.
63 * If exclusive control of a clock is no longer needed \ref cyhal_clock_free
64 * can be called to release it. This will remove the lock allowing something
65 * else in the system to potentially modify its state.
66 *
67 * \ref cyhal_clock_reserve and \ref cyhal_clock_allocate are very similar. They
68 * both reserve a clock object that can then be modified. The difference between
69 * them is the argument that is passed in. \ref cyhal_clock_reserve takes a
70 * specific instance that it will attempt to reserve. \ref cyhal_clock_allocate
71 * takes in a type of clock that it will attempt to find a free instance for and
72 * reserve that.
73 *
74 * \note After calling \ref cyhal_clock_free the clock object can still be used
75 * to call any of the get() functions just as is possible from the instance
76 * returned by \ref cyhal_clock_get or using any of the constant clock variables.
77 *
78 * \note A clock only needs to be allocated ( \ref cyhal_clock_allocate ) or
79 * reserved ( \ref cyhal_clock_reserve ) if its configuration needs to be changed
80 * by calling one of the set() functions.
81 *
82 * \note While the API is generic, the specific clock resource instances
83 * (\ref cyhal_resource_inst_t) are device specific. See the implementation
84 * specific sections for more details on what clocks and hardware resources are
85 * available.
86 *
87 * \section section_clock_features Features
88 * * Queryable clock features
89 * * Configurable clock enablement
90 * * Configurable clock frequency/divider
91 * * Configurable clock sources
92 * * Reserve or share clock objects
93 *
94 * \section section_clock_quickstart Quick Start
95 *
96 * See \ref subsection_clock_snippet_1 for a code snippet that shows how to reserve
97 * and configure a clock object.
98 *
99 * \section section_clock_snippets Code snippets
100 * \note Error handling code has been intentionally left out of snippets to highlight API usage.
101 *
102 * \subsection subsection_clock_snippet_1 Snippet 1: Simple clock read only access
103 * The following snippet shows how get details about a clock if there is no need to adjust any of its
104 * settings (e.g. read only access). This does not require initializing a clock object.
105 * \snippet hal_clock.c snippet_cyhal_clock_simple_access
106 *
107 * \subsection subsection_clock_snippet_2 Snippet 2: Simple clock reservation and configuration
108 * The following snippet initializes a clock object, updates its frequency then enables it.
109 * \snippet hal_clock.c snippet_cyhal_clock_simple_init
110 *
111 * \subsection subsection_clock_snippet_3 Snippet 3: Clock allocation and reuse
112 * The following snippet shows how a clock can be allocated and reused for multiple peripheral instances.
113 * \snippet hal_clock.c snippet_cyhal_clock_simple_allocate
114 *
115 * \subsection subsection_clock_snippet_4 Snippet 4: Change clock source
116 * The following snippet shows how a to change the source of a clock.
117 * \snippet hal_clock.c snippet_cyhal_clock_change_source
118 *
119 * \subsection subsection_clock_snippet_5 Snippet 5: System initialization
120 * \note This example is device specific. See \ref subsection_clock_snippet_5_impl for specific implementation.
121 *
122 */
123 
124 #pragma once
125 
126 #include <stdint.h>
127 #include <stdbool.h>
128 #include "cy_result.h"
129 #include "cyhal_hw_types.h"
130 
131 #if defined(__cplusplus)
132 extern "C"
133 {
134 #endif
135 
136 /** \addtogroup group_hal_results_clock Clock HAL Results
137  *  Clock specific return codes
138  *  \ingroup group_hal_results
139  *  \{ *//**
140  */
141 
142 
143 /** Error configuring clock frequency, divider, or multiplier. */
144 #define CYHAL_CLOCK_RSLT_ERR_FREQ               \
145     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_CLOCK, 0))
146 /** Invalid source clock. */
147 #define CYHAL_CLOCK_RSLT_ERR_SOURCE             \
148     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_CLOCK, 1))
149 /** Specified operation is not supported by the current clock. */
150 #define CYHAL_CLOCK_RSLT_ERR_NOT_SUPPORTED      \
151     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_CLOCK, 2))
152 /** The specified resource is not valid. */
153 #define CYHAL_CLOCK_RSLT_ERR_RESOURCE           \
154     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_CLOCK, 3))
155 /** The clock did not lock after being enabled. */
156 #define CYHAL_CLOCK_RSLT_ERR_LOCK               \
157     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_CLOCK, 4))
158 /** Source clock for the clock being configured is turned off. */
159 #define CYHAL_CLOCK_RSLT_ERR_SOURCE_DISABLED    \
160     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_CLOCK, 5))
161 
162 /**
163  * \}
164  */
165 
166 /** \addtogroup group_hal_tolerance
167  *  \{ *//**
168  *  \{ @name Clock Tolerance
169  */
170 
171 /** Clock tolerance 0 percent */
172 extern const cyhal_clock_tolerance_t CYHAL_CLOCK_TOLERANCE_0_P;
173 /** Clock tolerance 1 percent */
174 extern const cyhal_clock_tolerance_t CYHAL_CLOCK_TOLERANCE_1_P;
175 /** Clock tolerance 5 percent */
176 extern const cyhal_clock_tolerance_t CYHAL_CLOCK_TOLERANCE_5_P;
177 
178 /**
179  * \} \}
180  */
181 
182 /** Enum defining the different features each clock can support of clocks. These are bit masks.
183  * These can be used to determine which set() APIs are legal for a particular clock. */
184 typedef enum
185 {
186     CYHAL_CLOCK_FEATURE_NONE =       (0),       //!< No features of the clock are configurable.
187     CYHAL_CLOCK_FEATURE_ENABLE =     (1 << 0),  //!< The clock can be enabled & disabled \ref cyhal_clock_set_enabled.
188     CYHAL_CLOCK_FEATURE_FREQUENCY =  (1 << 1),  //!< The clock frequency can be adjusted \ref cyhal_clock_set_frequency.
189     CYHAL_CLOCK_FEATURE_DIVIDER =    (1 << 2),  //!< The clock divider can be adjusted \ref cyhal_clock_set_divider.
190     // Not available on any supported device yet.
191 //  CYHAL_CLOCK_FEATURE_MULTIPLIER = (1 << 3),  //!< The clock multiplier can be adjusted \ref  cyhal_clock_set_multiplier.
192     CYHAL_CLOCK_FEATURE_SOURCE =     (1 << 4),  //!< The clock source can be adjusted \ref cyhal_clock_set_source.
193 } cyhal_clock_feature_t;
194 
195 
196 /** Get a Clock instance for readonly use. This clock object can be used to call
197  * any of the get() functions. To call any of the set() functions, \ref
198  * cyhal_clock_reserve must be called to get exclusive access to the clock object
199  * to allow it to be modified.
200  *
201  * @param[out] clock    The clock object to store the initialized data into. The
202  * caller must allocate the memory for this object but the init function will
203  * initialize its contents.
204  * @param[in]  resource The clock resource instance to initialize.
205  * @return The status of the get request. This will only return an error if the provided
206  * resource instance is not a valid clock object.
207  */
208 cy_rslt_t cyhal_clock_get(cyhal_clock_t *clock, const cyhal_resource_inst_t *resource);
209 
210 /** Reserves the specified Clock instance.
211  * Once the clock has been reserved the get() and set() functions can be used. If
212  * at any time the clock is no longer needed, it can be released by calling
213  * \ref cyhal_clock_free.
214  * \note This does not change the clock configuration or connections.
215  *
216  * @param[out] clock        The clock object to initialize. The caller must allocate
217  * the memory for this object but the init function will initialize its contents.
218  * @param[in]  clock_       The constant clock object to reserve
219  * @return The status of the reserve request.
220  */
221 cy_rslt_t cyhal_clock_reserve(cyhal_clock_t *clock, const cyhal_clock_t *clock_);
222 
223 /** Allocates and Reserves a Clock instance, of the provided block type, for use.
224  * This should be used when needing a specific type of clock but the exact instance
225  * does not matter. This does everything that is done by \ref cyhal_clock_reserve.
226  * Once the clock has been allocated the get() and set() functions can be used. If
227  * at any time the clock is no longer needed, it can be released by calling
228  * \ref cyhal_clock_free.
229  * \note This does not change the clock configuration or connections.
230  * \note This is generally only supported for clock blocks that have multiple instances
231  *
232  * @param[out] clock        The clock object to initialize. The caller must allocate
233  * the memory for this object but the init function will initialize its contents.
234  * @param[in]  block        The specific type of clock to allocate
235  * @return The status of the allocate request.
236  */
237 cy_rslt_t cyhal_clock_allocate(cyhal_clock_t *clock, cyhal_clock_block_t block);
238 
239 /** Gets the features supported by the specified clock. This can be used to determine which
240  * set() APIs are legal to be called for this clock.
241  *
242  * @param[in] clock The clock object to get features for.
243  * @return The feature set that can be configured by this clock. Features are bit mask values.
244  */
245 cyhal_clock_feature_t cyhal_clock_get_features(const cyhal_clock_t *clock);
246 
247 /** Gets whether the specified clock is currently enabled and locked, if appropriate. While
248  * most clocks simply have an enabled state, Crystals, PLL, and a few others may also check
249  * to make sure the clock has locked and is stable before returning true.
250  *
251  * \note External clocks which cannot be enabled/disabled directly will return true
252  * if a frequency has been set for them, and false otherwise
253  *
254  * @param[in] clock The clock object to check if it is enabled.
255  * @return Whether the specified clock is enabled or not.
256  */
257 bool cyhal_clock_is_enabled(const cyhal_clock_t *clock);
258 
259 /** Attempts to update the enablement of the specified clock. This is only legal to call
260  * if the \ref cyhal_clock_get_features API indicates support for \ref CYHAL_CLOCK_FEATURE_ENABLE.
261  *
262  * \note \ref cyhal_clock_allocate or \ref cyhal_clock_reserve must be called on the <b>clock</b>
263  * instance before using this function.
264  *
265  * \note If disabled, any clocks or peripherals that are using this will stop working. Make sure
266  * to switch the clock source (\ref cyhal_clock_set_source) of any downstream clocks if necessary
267  * to keep them running prior to disabling their source.
268  *
269  * @param[in] clock         The clock object to update the enablement of.
270  * @param[in] enabled       Whether the clock should be enabled (true) or disabled (false).
271  * @param[in] wait_for_lock Whether to wait for the clock to enable & lock (true), or just send
272  *                          the request and return (false). Most clocks behave the same either
273  *                          way, however Crystals, PLLs, and similar require time to lock. If
274  *                          false, \ref cyhal_clock_is_enabled needs to be used to check that
275  *                          it is running before using the clock.
276  * @return The status of the requested to change the clocks enablement.
277  */
278 cy_rslt_t cyhal_clock_set_enabled(cyhal_clock_t *clock, bool enabled, bool wait_for_lock);
279 
280 /** Gets the frequency (in Hz) the clock is currently operating at.
281  *
282  * @param[in] clock    The clock object to get the frequency of.
283  * @return The frequency the clock is currently running at. 0 if the clock is disabled.
284  */
285 uint32_t cyhal_clock_get_frequency(const cyhal_clock_t *clock);
286 
287 /** Attempts to update the operating frequency of the clock. This is only legal to call
288  * if the \ref cyhal_clock_get_features API indicates support for \ref CYHAL_CLOCK_FEATURE_FREQUENCY.
289  *
290  * \note \ref cyhal_clock_allocate or \ref cyhal_clock_reserve must be called on the <b>clock</b>
291  * instance before using this function.
292  *
293  * \note Some clocks (eg: FLLs & PLLs) may need to be stopped before their frequency can
294  * be changed. This function will take care of disabling & re-enabling as necessary, however,
295  * this can cause a temporary glitch on anything that is running off of the clock at the time.
296  * If glitch free operation is required, change the source of any downstream clocks the
297  * application before changing the clock frequency.
298  *
299  * @param[in] clock     The clock object to set the frequency for.
300  * @param[in] hz        The frequency, in hertz, to set the clock to.
301  * @param[in] tolerance The allowed tolerance from the desired hz that is acceptable, use NULL if no
302  *                      tolerance check is required.
303  * @return The status of the request to set the clock frequency.
304  */
305 cy_rslt_t cyhal_clock_set_frequency(cyhal_clock_t *clock, uint32_t hz, const cyhal_clock_tolerance_t *tolerance);
306 
307 /** Attempts to update the divider, and by extension the operating frequency, of the clock. This is only
308  * legal to call if the \ref cyhal_clock_get_features API indicates support for
309  * \ref CYHAL_CLOCK_FEATURE_DIVIDER.
310  *
311  * \note \ref cyhal_clock_allocate or \ref cyhal_clock_reserve must be called on the <b>clock</b>
312  * instance before using this function.
313  *
314  * @param[in] clock     The clock object to set the divider for.
315  * @param[in] divider   The divider value to use.
316  * @return The status of the request to set the clock divider.
317  */
318 cy_rslt_t cyhal_clock_set_divider(cyhal_clock_t *clock, uint32_t divider);
319 
320 /** Gets the clocks that can serve as inputs to the current clock.
321  *
322  * @param[in]  clock    The clock object to get legal sources for.
323  * @param[out] sources  The sources that are legal for the current clock.
324  *                      \note the array does not need to be allocated before calling this
325  *                      the pointer will be updated to point to an existing const array.
326  * @param[out] count    The number of clock sources contained in the <b>sources</b> variable.
327  * @return The status of the request to get clock sources.
328  */
329 cy_rslt_t cyhal_clock_get_sources(const cyhal_clock_t *clock, const cyhal_resource_inst_t **sources[], uint32_t *count);
330 
331 /** Attempts to update the source for the specified clock. This is only legal to call if the
332  * \ref cyhal_clock_get_features API indicates support for \ref CYHAL_CLOCK_FEATURE_SOURCE.
333  *
334  * \note \ref cyhal_clock_allocate or \ref cyhal_clock_reserve must be called on the <b>clock</b>
335  * instance before using this function.
336  *
337  * \note Some clocks (eg: FLLs & PLLs) may need to be stopped before their source can be changed.
338  * This function will take care of disabling & re-enabling as necessary, however, this can cause
339  * a temporary glitch on anything that is running off of the clock at the time. If glitch free
340  * operation is required, change the source for any downstream clocks in the application before
341  * changing the source clock.
342  *
343  * \note No checking is done to verify that the source clock is running. This needs to be done
344  * by the caller.
345  *
346  * @param[in] clock     The clock object to set a new source for.
347  * @param[in] source    The source clock to update to.
348  * @return The status of the request to set the source of the clock
349  */
350 cy_rslt_t cyhal_clock_set_source(cyhal_clock_t *clock, const cyhal_clock_t *source);
351 
352 /** Releases the exclusive lock the clock. This instance can no longer be used to with any set()
353  * functions. It can still be used for readonly access to Clock APIs just like is possible after
354  * calling \ref cyhal_clock_get.
355  *
356  * \note This does not change the behavior (e.g.: enablement) of the clock.
357  *
358  * @param[in,out] clock The clock object to free
359  */
360 void cyhal_clock_free(cyhal_clock_t *clock);
361 
362 #if defined(__cplusplus)
363 }
364 #endif
365 
366 #ifdef CYHAL_CLOCK_IMPL_HEADER
367 #include CYHAL_CLOCK_IMPL_HEADER
368 #endif /* CYHAL_CLOCK_IMPL_HEADER */
369 
370 /** \} group_hal_clock */
371