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