4 * \brief DFLL management
\r
6 * Copyright (c) 2010-2012 Atmel Corporation. All rights reserved.
\r
12 * Redistribution and use in source and binary forms, with or without
\r
13 * modification, are permitted provided that the following conditions are met:
\r
15 * 1. Redistributions of source code must retain the above copyright notice,
\r
16 * this list of conditions and the following disclaimer.
\r
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
\r
19 * this list of conditions and the following disclaimer in the documentation
\r
20 * and/or other materials provided with the distribution.
\r
22 * 3. The name of Atmel may not be used to endorse or promote products derived
\r
23 * from this software without specific prior written permission.
\r
25 * 4. This software may only be redistributed and used in connection with an
\r
26 * Atmel microcontroller product.
\r
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
\r
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
\r
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
\r
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
\r
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
\r
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
\r
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
\r
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
\r
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
\r
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
\r
38 * POSSIBILITY OF SUCH DAMAGE.
\r
43 #ifndef CLK_DFLL_H_INCLUDED
\r
44 #define CLK_DFLL_H_INCLUDED
\r
47 #include "conf_clock.h"
\r
50 # include "uc3l/dfll.h"
\r
52 # include "sam4l/dfll.h"
\r
54 # error Unsupported chip type
\r
58 * \ingroup clk_group
\r
59 * \defgroup dfll_group DFLL Management
\r
61 * A Digital Frequency Locked Loop can be used to generate a highly
\r
62 * accurate frequency from a slower-running reference clock, in much the
\r
63 * same way as a PLL. DFLLs typically have shorter startup times and
\r
64 * less jitter. They can also be used in open-loop mode to generate a
\r
65 * less accurate frequency without the use of a reference clock.
\r
67 * There may be significant variations between platforms in the support
\r
68 * for certain features.
\r
70 * \par Example: Setting up DFLL0 with default parameters and dithering enabled
\r
72 * The following example shows how to configure and enable DFLL0 in
\r
73 * closed-loop mode using the default parameters specified through
\r
74 * configuration symbols.
\r
76 dfll_enable_config_defaults(0); \endcode
\r
78 * To configure and enable DFLL0 in closed-loop mode using the default
\r
79 * parameters and to enable specific feature like dithering for better accuracy,
\r
80 * you can use this initialization process.
\r
82 struct dfll_config dfllcfg;
\r
84 dfll_enable_source(CONFIG_DFLL0_SOURCE);
\r
85 dfll_config_defaults(&dfllcfg, 0);
\r
86 dfll_config_enable_dithering(&dfllcfg);
\r
87 dfll_enable(&dfllcfg, 0);
\r
88 dfll_wait_for_accurate_lock(0); \endcode
\r
90 * When the last function call returns, DFLL0 is running at a frequency
\r
91 * which matches the default configuration as accurately as possible.
\r
92 * Any additional alterations to the default configuration can be added
\r
93 * at the same place as the call to dfll_config_enable_dithering(), but
\r
94 * note that the DFLL will never achieve "accurate" lock if dithering is
\r
100 //! \name Chip-specific DFLL characteristics
\r
104 * \brief Number of on-chip DFLLs.
\r
108 * \brief Minimum frequency that the DFLL can generate.
\r
112 * \brief Maximum frequency that the DFLL can generate.
\r
117 * \typedef dfll_refclk_t
\r
118 * \brief Type used for identifying a reference clock source for the DFLL.
\r
121 //! \name DFLL Configuration
\r
125 * \struct dfll_config
\r
126 * \brief Hardware-specific representation of DFLL configuration.
\r
128 * This structure contains one or more device-specific values
\r
129 * representing the current DFLL configuration. The contents of this
\r
130 * structure is typically different from platform to platform, and the
\r
131 * user should not access any fields except through the DFLL
\r
132 * configuration API.
\r
136 * \fn void dfll_config_init_open_loop_mode(struct dfll_config *cfg)
\r
137 * \brief Configure the DFLL configuration \a cfg for open-loop mode.
\r
139 * \param cfg The DFLL configuration to be initialized.
\r
142 * \fn void dfll_config_init_closed_loop_mode(struct dfll_config *cfg,
\r
143 * dfll_refclk_t refclk, uint16_t div, uint16_t mul)
\r
144 * \brief Configure the DFLL configuration \a cfg for closed-loop mode.
\r
146 * \param cfg The DFLL configuration to be initialized.
\r
147 * \param refclk The reference clock source.
\r
148 * \param div Reference clock divider.
\r
149 * \param mul Multiplier (integer part only).
\r
152 * \def dfll_config_defaults(cfg, dfll_id)
\r
153 * \brief Initialize DFLL configuration using default parameters.
\r
155 * After this function returns, \a cfg will contain a configuration
\r
156 * which will make the DFLL run at (CONFIG_DFLLx_MUL / CONFIG_DFLLx_DIV)
\r
157 * times the frequency of CONFIG_DFLLx_SOURCE. The default configuration
\r
158 * will always use closed-loop mode with no fractional multiplier.
\r
160 * \param cfg The DFLL configuration to be initialized.
\r
161 * \param dfll_id Use defaults for this DFLL.
\r
164 * \def dfll_get_default_rate(dfll_id)
\r
165 * \brief Return the default rate in Hz of \a dfll_id.
\r
169 * \fn void dfll_config_set_fractional_multiplier(struct dfll_config *cfg,
\r
170 * uint16_t mul_i, uint16_t mul_f)
\r
171 * \brief Set a fractional multiplier.
\r
173 * This function has no effect in open-loop mode, and is only available
\r
174 * on devices which support fractional multipliers.
\r
176 * The fractional part of the multiplier is assumed to be 16 bits. The
\r
177 * low-level driver will make sure to shift this value to match the
\r
178 * hardware if necessary.
\r
180 * \param cfg The DFLL configuration to be modified.
\r
181 * \param mul_i Integer part of multiplier.
\r
182 * \param mul_f Fractional part of multiplier.
\r
185 * \fn void dfll_config_enable_dithering(struct dfll_config *cfg)
\r
186 * \brief Enable dithering for more accurate frequency generation.
\r
188 * The fine LSB input to the VCO is dithered to achieve fractional
\r
189 * approximation to the correct multiplication ratio.
\r
191 * \param cfg The DFLL configuration to be modified.
\r
194 * \fn void dfll_config_disable_dithering(struct dfll_config *cfg)
\r
195 * \brief Disable dithering.
\r
197 * \see dfll_config_enable_dithering()
\r
199 * \param cfg The DFLL configuration to be modified.
\r
202 * \fn void dfll_config_set_initial_tuning(struct dfll_config *cfg,
\r
203 * uint16_t coarse, uint16_t fine)
\r
204 * \brief Set initial VCO tuning.
\r
206 * In open loop mode, this will determine the frequency of the output.
\r
208 * In closed loop mode, this will provide an initial estimate of the VCO
\r
209 * tuning. While the DFLL will automatically adjust these values to
\r
210 * match the desired output frequency, careful selection of initial
\r
211 * values might reduce the time to achieve coarse and fine lock.
\r
213 * \param cfg The DFLL configuration to be modified.
\r
214 * \param coarse Coarse tuning of the frequency generator.
\r
215 * \param fine Fine tuning of the frequency generator.
\r
218 * \fn void dfll_config_set_max_step(struct dfll_config *cfg,
\r
219 * uint16_t coarse, uint16_t fine)
\r
220 * \brief Set the maximum VCO tuning step size.
\r
222 * This function has no effect in open-loop mode.
\r
224 * By default, both of these values are set to 50% of their respective
\r
225 * maximums. It is not recommended to set the values any higher than
\r
226 * this, but setting them lower might reduce the frequency overshoot at
\r
227 * the expense of longer time to achieve coarse and/or fine lock.
\r
229 * \param cfg The DFLL configuration to be modified
\r
230 * \param coarse The maximum step size of the coarse VCO tuning.
\r
231 * \param fine The maximum step size of the fine VCO tuning.
\r
234 * \fn void dfll_config_enable_ssg(struct dfll_config *cfg,
\r
235 * uint16_t amplitude, uint16_t step_size)
\r
236 * \brief Enable Spread Spectrum Generator.
\r
238 * \param cfg The DFLL configuration to be modified.
\r
239 * \param amplitude The amplitude of the spread spectrum.
\r
240 * \param step_size The step size of the spread spectrum.
\r
243 * \fn void dfll_config_disable_ssg(struct dfll_config *cfg)
\r
244 * \brief Disable Spread Spectrum Generator.
\r
246 * \param cfg The DFLL configuration to be modified.
\r
250 //! \name Interaction with the DFLL hardware
\r
253 * \fn void dfll_enable_open_loop(const struct dfll_config *cfg,
\r
254 * unsigned int dfll_id)
\r
255 * \brief Activate the configuration \a cfg and enable DFLL \a dfll_id
\r
256 * in open-loop mode.
\r
258 * \pre The configuration in \a cfg must represent an open-loop
\r
261 * \param cfg The configuration to be activated.
\r
262 * \param dfll_id The ID of the DFLL to be enabled.
\r
265 * \fn void dfll_enable_closed_loop(const struct dfll_config *cfg,
\r
266 * unsigned int dfll_id)
\r
267 * \brief Activate the configuration \a cfg and enable DFLL \a dfll_id
\r
268 * in closed-loop mode.
\r
270 * \pre The configuration in \a cfg must represent a closed-loop
\r
273 * \param cfg The configuration to be activated.
\r
274 * \param dfll_id The ID of the DFLL to be enabled.
\r
277 * \fn void dfll_disable_open_loop(unsigned int dfll_id)
\r
278 * \brief Disable the DFLL identified by \a dfll_id.
\r
280 * \pre The DFLL must have been enabled in open loop mode.
\r
282 * \param dfll_id The ID of the DFLL to be disabled.
\r
285 * \fn void dfll_disable_closed_loop(unsigned int dfll_id)
\r
286 * \brief Disable the DFLL identified by \a dfll_id.
\r
288 * \pre The DFLL must have been enabled in closed loop mode.
\r
290 * \param dfll_id The ID of the DFLL to be disabled.
\r
293 * \fn bool dfll_is_coarse_locked(unsigned int dfll_id)
\r
294 * \brief Determine whether or not a DFLL has achieved coarse lock.
\r
296 * \param dfll_id The ID of the DFLL to check.
\r
298 * \retval true The DFLL has determined the final value of the coarse
\r
299 * VCO tuning value.
\r
300 * \retval false The DFLL has not yet determined the coarse VCO tuning
\r
301 * value, or has not been enabled.
\r
304 * \fn bool dfll_is_fine_locked(unsigned int dfll_id)
\r
305 * \brief Determine whether or not a DFLL has achieved fine lock.
\r
307 * \param dfll_id The ID of the DFLL to check.
\r
309 * \retval true The DFLL has determined the final value of the fine VCO
\r
311 * \retval false The DFLL has not yet determined the fine VCO tuning
\r
312 * value, or has not been enabled.
\r
315 * \fn bool dfll_is_accurate_locked(unsigned int dfll_id)
\r
316 * \brief Determine whether or not a DFLL has achieved accurate lock.
\r
318 * \param dfll_id The ID of the DFLL to check.
\r
320 * \retval true The DFLL has determined the final dithering duty cycle.
\r
321 * \retval false The DFLL has not yet determined the dithering duty
\r
322 * cycle, or has not been enabled with dithering enabled.
\r
325 * \fn void dfll_enable_source(enum dfll_refclk_t src)
\r
326 * \brief Enable the source of the dfll.
\r
327 * The source is enabled, if the source is not already running.
\r
329 * \param dfll_source src The ID of the DFLL source to enable.
\r
332 * \fn void dfll_enable_config_defaults(unsigned int dfll_id)
\r
333 * \brief Enable the dfll with the default configuration.
\r
334 * DFLL is enabled, if the DFLL is not already locked.
\r
336 * \param dfll_id The ID of the DFLL to enable.
\r
340 * \brief Wait for the DFLL identified by \a dfll_id to achieve coarse
\r
343 * \param dfll_id The ID of the DFLL to wait for.
\r
345 * \retval STATUS_OK The DFLL has achieved coarse lock.
\r
346 * \retval ERR_TIMEOUT Timed out waiting for lock.
\r
348 static inline int dfll_wait_for_coarse_lock(unsigned int dfll_id)
\r
350 /* TODO: Add timeout mechanism */
\r
351 while (!dfll_is_coarse_locked(dfll_id)) {
\r
359 * \brief Wait for the DFLL identified by \a dfll_id to achieve fine
\r
362 * \param dfll_id The ID of the DFLL to wait for.
\r
364 * \retval STATUS_OK The DFLL has achieved fine lock.
\r
365 * \retval ERR_TIMEOUT Timed out waiting for lock.
\r
367 static inline int dfll_wait_for_fine_lock(unsigned int dfll_id)
\r
369 /* TODO: Add timeout mechanism */
\r
370 while (!dfll_is_fine_locked(dfll_id)) {
\r
378 * \brief Wait for the DFLL identified by \a dfll_id to achieve accurate
\r
381 * \param dfll_id The ID of the DFLL to wait for.
\r
383 * \retval STATUS_OK The DFLL has achieved accurate lock.
\r
384 * \retval ERR_TIMEOUT Timed out waiting for lock.
\r
386 static inline int dfll_wait_for_accurate_lock(unsigned int dfll_id)
\r
388 /* TODO: Add timeout mechanism */
\r
389 while (!dfll_is_accurate_locked(dfll_id)) {
\r
399 #endif /* CLK_DFLL_H_INCLUDED */
\r