1 /**
2 * \file
3 *
4 * \brief DFLL management
5 *
6 * Copyright (c) 2010-2015 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43 /*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46 #ifndef CLK_DFLL_H_INCLUDED
47 #define CLK_DFLL_H_INCLUDED
48
49 #include <parts.h>
50 #include "conf_clock.h"
51
52 #if UC3L
53 # include "uc3l/dfll.h"
54 #elif SAM4L
55 # include "sam4l/dfll.h"
56 #else
57 # error Unsupported chip type
58 #endif
59
60 /**
61 * \ingroup clk_group
62 * \defgroup dfll_group DFLL Management
63 *
64 * A Digital Frequency Locked Loop can be used to generate a highly
65 * accurate frequency from a slower-running reference clock, in much the
66 * same way as a PLL. DFLLs typically have shorter startup times and
67 * less jitter. They can also be used in open-loop mode to generate a
68 * less accurate frequency without the use of a reference clock.
69 *
70 * There may be significant variations between platforms in the support
71 * for certain features.
72 *
73 * \par Example: Setting up DFLL0 with default parameters and dithering enabled
74 *
75 * The following example shows how to configure and enable DFLL0 in
76 * closed-loop mode using the default parameters specified through
77 * configuration symbols.
78 * \code
79 dfll_enable_config_defaults(0); \endcode
80 *
81 * To configure and enable DFLL0 in closed-loop mode using the default
82 * parameters and to enable specific feature like dithering for better accuracy,
83 * you can use this initialization process.
84 * \code
85 struct dfll_config dfllcfg;
86
87 dfll_enable_source(CONFIG_DFLL0_SOURCE);
88 dfll_config_defaults(&dfllcfg, 0);
89 dfll_config_enable_dithering(&dfllcfg);
90 dfll_enable(&dfllcfg, 0);
91 dfll_wait_for_accurate_lock(0); \endcode
92 *
93 * When the last function call returns, DFLL0 is running at a frequency
94 * which matches the default configuration as accurately as possible.
95 * Any additional alterations to the default configuration can be added
96 * at the same place as the call to dfll_config_enable_dithering(), but
97 * note that the DFLL will never achieve "accurate" lock if dithering is
98 * disabled.
99 *
100 * @{
101 */
102
103 //! \name Chip-specific DFLL characteristics
104 //@{
105 /**
106 * \def NR_DFLLS
107 * \brief Number of on-chip DFLLs.
108 */
109 /**
110 * \def DFLL_MIN_HZ
111 * \brief Minimum frequency that the DFLL can generate.
112 */
113 /**
114 * \def DFLL_MAX_HZ
115 * \brief Maximum frequency that the DFLL can generate.
116 */
117 //@}
118
119 /**
120 * \typedef dfll_refclk_t
121 * \brief Type used for identifying a reference clock source for the DFLL.
122 */
123
124 //! \name DFLL Configuration
125 //@{
126
127 /**
128 * \struct dfll_config
129 * \brief Hardware-specific representation of DFLL configuration.
130 *
131 * This structure contains one or more device-specific values
132 * representing the current DFLL configuration. The contents of this
133 * structure is typically different from platform to platform, and the
134 * user should not access any fields except through the DFLL
135 * configuration API.
136 */
137
138 /**
139 * \fn void dfll_config_init_open_loop_mode(struct dfll_config *cfg)
140 * \brief Configure the DFLL configuration \a cfg for open-loop mode.
141 *
142 * \param cfg The DFLL configuration to be initialized.
143 */
144 /**
145 * \fn void dfll_config_init_closed_loop_mode(struct dfll_config *cfg,
146 * dfll_refclk_t refclk, uint16_t div, uint16_t mul)
147 * \brief Configure the DFLL configuration \a cfg for closed-loop mode.
148 *
149 * \param cfg The DFLL configuration to be initialized.
150 * \param refclk The reference clock source.
151 * \param div Reference clock divider.
152 * \param mul Multiplier (integer part only).
153 */
154 /**
155 * \def dfll_config_defaults(cfg, dfll_id)
156 * \brief Initialize DFLL configuration using default parameters.
157 *
158 * After this function returns, \a cfg will contain a configuration
159 * which will make the DFLL run at (CONFIG_DFLLx_MUL / CONFIG_DFLLx_DIV)
160 * times the frequency of CONFIG_DFLLx_SOURCE. The default configuration
161 * will always use closed-loop mode with no fractional multiplier.
162 *
163 * \param cfg The DFLL configuration to be initialized.
164 * \param dfll_id Use defaults for this DFLL.
165 */
166 /**
167 * \def dfll_get_default_rate(dfll_id)
168 * \brief Return the default rate in Hz of \a dfll_id.
169 */
170
171 /**
172 * \fn void dfll_config_set_fractional_multiplier(struct dfll_config *cfg,
173 * uint16_t mul_i, uint16_t mul_f)
174 * \brief Set a fractional multiplier.
175 *
176 * This function has no effect in open-loop mode, and is only available
177 * on devices which support fractional multipliers.
178 *
179 * The fractional part of the multiplier is assumed to be 16 bits. The
180 * low-level driver will make sure to shift this value to match the
181 * hardware if necessary.
182 *
183 * \param cfg The DFLL configuration to be modified.
184 * \param mul_i Integer part of multiplier.
185 * \param mul_f Fractional part of multiplier.
186 */
187 /**
188 * \fn void dfll_config_enable_dithering(struct dfll_config *cfg)
189 * \brief Enable dithering for more accurate frequency generation.
190 *
191 * The fine LSB input to the VCO is dithered to achieve fractional
192 * approximation to the correct multiplication ratio.
193 *
194 * \param cfg The DFLL configuration to be modified.
195 */
196 /**
197 * \fn void dfll_config_disable_dithering(struct dfll_config *cfg)
198 * \brief Disable dithering.
199 *
200 * \see dfll_config_enable_dithering()
201 *
202 * \param cfg The DFLL configuration to be modified.
203 */
204 /**
205 * \fn void dfll_config_set_initial_tuning(struct dfll_config *cfg,
206 * uint16_t coarse, uint16_t fine)
207 * \brief Set initial VCO tuning.
208 *
209 * In open loop mode, this will determine the frequency of the output.
210 *
211 * In closed loop mode, this will provide an initial estimate of the VCO
212 * tuning. While the DFLL will automatically adjust these values to
213 * match the desired output frequency, careful selection of initial
214 * values might reduce the time to achieve coarse and fine lock.
215 *
216 * \param cfg The DFLL configuration to be modified.
217 * \param coarse Coarse tuning of the frequency generator.
218 * \param fine Fine tuning of the frequency generator.
219 */
220 /**
221 * \fn void dfll_config_set_max_step(struct dfll_config *cfg,
222 * uint16_t coarse, uint16_t fine)
223 * \brief Set the maximum VCO tuning step size.
224 *
225 * This function has no effect in open-loop mode.
226 *
227 * By default, both of these values are set to 50% of their respective
228 * maximums. It is not recommended to set the values any higher than
229 * this, but setting them lower might reduce the frequency overshoot at
230 * the expense of longer time to achieve coarse and/or fine lock.
231 *
232 * \param cfg The DFLL configuration to be modified
233 * \param coarse The maximum step size of the coarse VCO tuning.
234 * \param fine The maximum step size of the fine VCO tuning.
235 */
236 /**
237 * \fn void dfll_config_enable_ssg(struct dfll_config *cfg,
238 * uint16_t amplitude, uint16_t step_size)
239 * \brief Enable Spread Spectrum Generator.
240 *
241 * \param cfg The DFLL configuration to be modified.
242 * \param amplitude The amplitude of the spread spectrum.
243 * \param step_size The step size of the spread spectrum.
244 */
245 /**
246 * \fn void dfll_config_disable_ssg(struct dfll_config *cfg)
247 * \brief Disable Spread Spectrum Generator.
248 *
249 * \param cfg The DFLL configuration to be modified.
250 */
251 //@}
252
253 //! \name Interaction with the DFLL hardware
254 //@{
255 /**
256 * \fn void dfll_enable_open_loop(const struct dfll_config *cfg,
257 * unsigned int dfll_id)
258 * \brief Activate the configuration \a cfg and enable DFLL \a dfll_id
259 * in open-loop mode.
260 *
261 * \pre The configuration in \a cfg must represent an open-loop
262 * configuration.
263 *
264 * \param cfg The configuration to be activated.
265 * \param dfll_id The ID of the DFLL to be enabled.
266 */
267 /**
268 * \fn void dfll_enable_closed_loop(const struct dfll_config *cfg,
269 * unsigned int dfll_id)
270 * \brief Activate the configuration \a cfg and enable DFLL \a dfll_id
271 * in closed-loop mode.
272 *
273 * \pre The configuration in \a cfg must represent a closed-loop
274 * configuration.
275 *
276 * \param cfg The configuration to be activated.
277 * \param dfll_id The ID of the DFLL to be enabled.
278 */
279 /**
280 * \fn void dfll_disable_open_loop(unsigned int dfll_id)
281 * \brief Disable the DFLL identified by \a dfll_id.
282 *
283 * \pre The DFLL must have been enabled in open loop mode.
284 *
285 * \param dfll_id The ID of the DFLL to be disabled.
286 */
287 /**
288 * \fn void dfll_disable_closed_loop(unsigned int dfll_id)
289 * \brief Disable the DFLL identified by \a dfll_id.
290 *
291 * \pre The DFLL must have been enabled in closed loop mode.
292 *
293 * \param dfll_id The ID of the DFLL to be disabled.
294 */
295 /**
296 * \fn bool dfll_is_coarse_locked(unsigned int dfll_id)
297 * \brief Determine whether or not a DFLL has achieved coarse lock.
298 *
299 * \param dfll_id The ID of the DFLL to check.
300 *
301 * \retval true The DFLL has determined the final value of the coarse
302 * VCO tuning value.
303 * \retval false The DFLL has not yet determined the coarse VCO tuning
304 * value, or has not been enabled.
305 */
306 /**
307 * \fn bool dfll_is_fine_locked(unsigned int dfll_id)
308 * \brief Determine whether or not a DFLL has achieved fine lock.
309 *
310 * \param dfll_id The ID of the DFLL to check.
311 *
312 * \retval true The DFLL has determined the final value of the fine VCO
313 * tuning value.
314 * \retval false The DFLL has not yet determined the fine VCO tuning
315 * value, or has not been enabled.
316 */
317 /**
318 * \fn bool dfll_is_accurate_locked(unsigned int dfll_id)
319 * \brief Determine whether or not a DFLL has achieved accurate lock.
320 *
321 * \param dfll_id The ID of the DFLL to check.
322 *
323 * \retval true The DFLL has determined the final dithering duty cycle.
324 * \retval false The DFLL has not yet determined the dithering duty
325 * cycle, or has not been enabled with dithering enabled.
326 */
327 /**
328 * \fn void dfll_enable_source(enum dfll_refclk_t src)
329 * \brief Enable the source of the dfll.
330 * The source is enabled, if the source is not already running.
331 *
332 * \param dfll_source src The ID of the DFLL source to enable.
333 */
334 /**
335 * \fn void dfll_enable_config_defaults(unsigned int dfll_id)
336 * \brief Enable the dfll with the default configuration.
337 * DFLL is enabled, if the DFLL is not already locked.
338 *
339 * \param dfll_id The ID of the DFLL to enable.
340 */
341
342 /**
343 * \brief Wait for the DFLL identified by \a dfll_id to achieve coarse
344 * lock.
345 *
346 * \param dfll_id The ID of the DFLL to wait for.
347 *
348 * \retval STATUS_OK The DFLL has achieved coarse lock.
349 * \retval ERR_TIMEOUT Timed out waiting for lock.
350 */
dfll_wait_for_coarse_lock(unsigned int dfll_id)351 static inline int dfll_wait_for_coarse_lock(unsigned int dfll_id)
352 {
353 /* TODO: Add timeout mechanism */
354 while (!dfll_is_coarse_locked(dfll_id)) {
355 /* Do nothing */
356 }
357
358 return 0;
359 }
360
361 /**
362 * \brief Wait for the DFLL identified by \a dfll_id to achieve fine
363 * lock.
364 *
365 * \param dfll_id The ID of the DFLL to wait for.
366 *
367 * \retval STATUS_OK The DFLL has achieved fine lock.
368 * \retval ERR_TIMEOUT Timed out waiting for lock.
369 */
dfll_wait_for_fine_lock(unsigned int dfll_id)370 static inline int dfll_wait_for_fine_lock(unsigned int dfll_id)
371 {
372 /* TODO: Add timeout mechanism */
373 while (!dfll_is_fine_locked(dfll_id)) {
374 /* Do nothing */
375 }
376
377 return 0;
378 }
379
380 /**
381 * \brief Wait for the DFLL identified by \a dfll_id to achieve accurate
382 * lock.
383 *
384 * \param dfll_id The ID of the DFLL to wait for.
385 *
386 * \retval STATUS_OK The DFLL has achieved accurate lock.
387 * \retval ERR_TIMEOUT Timed out waiting for lock.
388 */
dfll_wait_for_accurate_lock(unsigned int dfll_id)389 static inline int dfll_wait_for_accurate_lock(unsigned int dfll_id)
390 {
391 /* TODO: Add timeout mechanism */
392 while (!dfll_is_accurate_locked(dfll_id)) {
393 /* Do nothing */
394 }
395
396 return 0;
397 }
398
399 //@}
400 //! @}
401
402 #endif /* CLK_DFLL_H_INCLUDED */
403