summaryrefslogtreecommitdiff
path: root/bsp/samd21/sam_d2x_asflib/common/services/clock/dfll.h
blob: ca5bb97adecdbef1f617fe4756a54df0a9723faa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
/**
 * \file
 *
 * \brief DFLL management
 *
 * Copyright (c) 2010-2015 Atmel Corporation. All rights reserved.
 *
 * \asf_license_start
 *
 * \page License
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * 3. The name of Atmel may not be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * 4. This software may only be redistributed and used in connection with an
 *    Atmel microcontroller product.
 *
 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \asf_license_stop
 *
 */
/*
 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
 */
#ifndef CLK_DFLL_H_INCLUDED
#define CLK_DFLL_H_INCLUDED

#include <parts.h>
#include "conf_clock.h"

#if UC3L
# include "uc3l/dfll.h"
#elif SAM4L
# include "sam4l/dfll.h"
#else
# error Unsupported chip type
#endif

/**
 * \ingroup clk_group
 * \defgroup dfll_group DFLL Management
 *
 * A Digital Frequency Locked Loop can be used to generate a highly
 * accurate frequency from a slower-running reference clock, in much the
 * same way as a PLL. DFLLs typically have shorter startup times and
 * less jitter. They can also be used in open-loop mode to generate a
 * less accurate frequency without the use of a reference clock.
 *
 * There may be significant variations between platforms in the support
 * for certain features.
 *
 * \par Example: Setting up DFLL0 with default parameters and dithering enabled
 *
 * The following example shows how to configure and enable DFLL0 in
 * closed-loop mode using the default parameters specified through
 * configuration symbols.
 * \code
	dfll_enable_config_defaults(0); \endcode
 *
 * To configure and enable DFLL0 in closed-loop mode using the default
 * parameters and to enable specific feature like dithering for better accuracy,
 * you can use this initialization process.
 * \code
	struct dfll_config dfllcfg;

	dfll_enable_source(CONFIG_DFLL0_SOURCE);
	dfll_config_defaults(&dfllcfg, 0);
	dfll_config_enable_dithering(&dfllcfg);
	dfll_enable(&dfllcfg, 0);
	dfll_wait_for_accurate_lock(0); \endcode
 *
 * When the last function call returns, DFLL0 is running at a frequency
 * which matches the default configuration as accurately as possible.
 * Any additional alterations to the default configuration can be added
 * at the same place as the call to dfll_config_enable_dithering(), but
 * note that the DFLL will never achieve "accurate" lock if dithering is
 * disabled.
 *
 * @{
 */

//! \name Chip-specific DFLL characteristics
//@{
/**
 * \def NR_DFLLS
 * \brief Number of on-chip DFLLs.
 */
/**
 * \def DFLL_MIN_HZ
 * \brief Minimum frequency that the DFLL can generate.
 */
/**
 * \def DFLL_MAX_HZ
 * \brief Maximum frequency that the DFLL can generate.
 */
//@}

/**
 * \typedef dfll_refclk_t
 * \brief Type used for identifying a reference clock source for the DFLL.
 */

//! \name DFLL Configuration
//@{

/**
 * \struct dfll_config
 * \brief Hardware-specific representation of DFLL configuration.
 *
 * This structure contains one or more device-specific values
 * representing the current DFLL configuration. The contents of this
 * structure is typically different from platform to platform, and the
 * user should not access any fields except through the DFLL
 * configuration API.
 */

/**
 * \fn void dfll_config_init_open_loop_mode(struct dfll_config *cfg)
 * \brief Configure the DFLL configuration \a cfg for open-loop mode.
 *
 * \param cfg The DFLL configuration to be initialized.
 */
/**
 * \fn void dfll_config_init_closed_loop_mode(struct dfll_config *cfg,
 *              dfll_refclk_t refclk, uint16_t div, uint16_t mul)
 * \brief Configure the DFLL configuration \a cfg for closed-loop mode.
 *
 * \param cfg The DFLL configuration to be initialized.
 * \param refclk The reference clock source.
 * \param div Reference clock divider.
 * \param mul Multiplier (integer part only).
 */
/**
 * \def dfll_config_defaults(cfg, dfll_id)
 * \brief Initialize DFLL configuration using default parameters.
 *
 * After this function returns, \a cfg will contain a configuration
 * which will make the DFLL run at (CONFIG_DFLLx_MUL / CONFIG_DFLLx_DIV)
 * times the frequency of CONFIG_DFLLx_SOURCE. The default configuration
 * will always use closed-loop mode with no fractional multiplier.
 *
 * \param cfg The DFLL configuration to be initialized.
 * \param dfll_id Use defaults for this DFLL.
 */
/**
 * \def dfll_get_default_rate(dfll_id)
 * \brief Return the default rate in Hz of \a dfll_id.
 */

/**
 * \fn void dfll_config_set_fractional_multiplier(struct dfll_config *cfg,
 *              uint16_t mul_i, uint16_t mul_f)
 * \brief Set a fractional multiplier.
 *
 * This function has no effect in open-loop mode, and is only available
 * on devices which support fractional multipliers.
 *
 * The fractional part of the multiplier is assumed to be 16 bits. The
 * low-level driver will make sure to shift this value to match the
 * hardware if necessary.
 *
 * \param cfg The DFLL configuration to be modified.
 * \param mul_i Integer part of multiplier.
 * \param mul_f Fractional part of multiplier.
 */
/**
 * \fn void dfll_config_enable_dithering(struct dfll_config *cfg)
 * \brief Enable dithering for more accurate frequency generation.
 *
 * The fine LSB input to the VCO is dithered to achieve fractional
 * approximation to the correct multiplication ratio.
 *
 * \param cfg The DFLL configuration to be modified.
 */
/**
 * \fn void dfll_config_disable_dithering(struct dfll_config *cfg)
 * \brief Disable dithering.
 *
 * \see dfll_config_enable_dithering()
 *
 * \param cfg The DFLL configuration to be modified.
 */
/**
 * \fn void dfll_config_set_initial_tuning(struct dfll_config *cfg,
 *              uint16_t coarse, uint16_t fine)
 * \brief Set initial VCO tuning.
 *
 * In open loop mode, this will determine the frequency of the output.
 *
 * In closed loop mode, this will provide an initial estimate of the VCO
 * tuning. While the DFLL will automatically adjust these values to
 * match the desired output frequency, careful selection of initial
 * values might reduce the time to achieve coarse and fine lock.
 *
 * \param cfg The DFLL configuration to be modified.
 * \param coarse Coarse tuning of the frequency generator.
 * \param fine Fine tuning of the frequency generator.
 */
/**
 * \fn void dfll_config_set_max_step(struct dfll_config *cfg,
 *              uint16_t coarse, uint16_t fine)
 * \brief Set the maximum VCO tuning step size.
 *
 * This function has no effect in open-loop mode.
 *
 * By default, both of these values are set to 50% of their respective
 * maximums.  It is not recommended to set the values any higher than
 * this, but setting them lower might reduce the frequency overshoot at
 * the expense of longer time to achieve coarse and/or fine lock.
 *
 * \param cfg The DFLL configuration to be modified
 * \param coarse The maximum step size of the coarse VCO tuning.
 * \param fine The maximum step size of the fine VCO tuning.
 */
/**
 * \fn void dfll_config_enable_ssg(struct dfll_config *cfg,
 *              uint16_t amplitude, uint16_t step_size)
 * \brief Enable Spread Spectrum Generator.
 *
 * \param cfg The DFLL configuration to be modified.
 * \param amplitude The amplitude of the spread spectrum.
 * \param step_size The step size of the spread spectrum.
 */
/**
 * \fn void dfll_config_disable_ssg(struct dfll_config *cfg)
 * \brief Disable Spread Spectrum Generator.
 *
 * \param cfg The DFLL configuration to be modified.
 */
//@}

//! \name Interaction with the DFLL hardware
//@{
/**
 * \fn void dfll_enable_open_loop(const struct dfll_config *cfg,
 *              unsigned int dfll_id)
 * \brief Activate the configuration \a cfg and enable DFLL \a dfll_id
 * in open-loop mode.
 *
 * \pre The configuration in \a cfg must represent an open-loop
 * configuration.
 *
 * \param cfg The configuration to be activated.
 * \param dfll_id The ID of the DFLL to be enabled.
 */
/**
 * \fn void dfll_enable_closed_loop(const struct dfll_config *cfg,
 *              unsigned int dfll_id)
 * \brief Activate the configuration \a cfg and enable DFLL \a dfll_id
 * in closed-loop mode.
 *
 * \pre The configuration in \a cfg must represent a closed-loop
 * configuration.
 *
 * \param cfg The configuration to be activated.
 * \param dfll_id The ID of the DFLL to be enabled.
 */
/**
 * \fn void dfll_disable_open_loop(unsigned int dfll_id)
 * \brief Disable the DFLL identified by \a dfll_id.
 *
 * \pre The DFLL must have been enabled in open loop mode.
 *
 * \param dfll_id The ID of the DFLL to be disabled.
 */
/**
 * \fn void dfll_disable_closed_loop(unsigned int dfll_id)
 * \brief Disable the DFLL identified by \a dfll_id.
 *
 * \pre The DFLL must have been enabled in closed loop mode.
 *
 * \param dfll_id The ID of the DFLL to be disabled.
 */
/**
 * \fn bool dfll_is_coarse_locked(unsigned int dfll_id)
 * \brief Determine whether or not a DFLL has achieved coarse lock.
 *
 * \param dfll_id The ID of the DFLL to check.
 *
 * \retval true The DFLL has determined the final value of the coarse
 * VCO tuning value.
 * \retval false The DFLL has not yet determined the coarse VCO tuning
 * value, or has not been enabled.
 */
/**
 * \fn bool dfll_is_fine_locked(unsigned int dfll_id)
 * \brief Determine whether or not a DFLL has achieved fine lock.
 *
 * \param dfll_id The ID of the DFLL to check.
 *
 * \retval true The DFLL has determined the final value of the fine VCO
 * tuning value.
 * \retval false The DFLL has not yet determined the fine VCO tuning
 * value, or has not been enabled.
 */
/**
 * \fn bool dfll_is_accurate_locked(unsigned int dfll_id)
 * \brief Determine whether or not a DFLL has achieved accurate lock.
 *
 * \param dfll_id The ID of the DFLL to check.
 *
 * \retval true The DFLL has determined the final dithering duty cycle.
 * \retval false The DFLL has not yet determined the dithering duty
 * cycle, or has not been enabled with dithering enabled.
 */
/**
 * \fn void dfll_enable_source(enum dfll_refclk_t src)
 * \brief Enable the source of the dfll.
 * The source is enabled, if the source is not already running.
 *
 * \param dfll_source src The ID of the DFLL source to enable.
 */
/**
 * \fn void dfll_enable_config_defaults(unsigned int dfll_id)
 * \brief Enable the dfll with the default configuration.
 * DFLL is enabled, if the DFLL is not already locked.
 *
 * \param dfll_id The ID of the DFLL to enable.
 */

/**
 * \brief Wait for the DFLL identified by \a dfll_id to achieve coarse
 * lock.
 *
 * \param dfll_id The ID of the DFLL to wait for.
 *
 * \retval STATUS_OK The DFLL has achieved coarse lock.
 * \retval ERR_TIMEOUT Timed out waiting for lock.
 */
static inline int dfll_wait_for_coarse_lock(unsigned int dfll_id)
{
	/* TODO: Add timeout mechanism */
	while (!dfll_is_coarse_locked(dfll_id)) {
		/* Do nothing */
	}

	return 0;
}

/**
 * \brief Wait for the DFLL identified by \a dfll_id to achieve fine
 * lock.
 *
 * \param dfll_id The ID of the DFLL to wait for.
 *
 * \retval STATUS_OK The DFLL has achieved fine lock.
 * \retval ERR_TIMEOUT Timed out waiting for lock.
 */
static inline int dfll_wait_for_fine_lock(unsigned int dfll_id)
{
	/* TODO: Add timeout mechanism */
	while (!dfll_is_fine_locked(dfll_id)) {
		/* Do nothing */
	}

	return 0;
}

/**
 * \brief Wait for the DFLL identified by \a dfll_id to achieve accurate
 * lock.
 *
 * \param dfll_id The ID of the DFLL to wait for.
 *
 * \retval STATUS_OK The DFLL has achieved accurate lock.
 * \retval ERR_TIMEOUT Timed out waiting for lock.
 */
static inline int dfll_wait_for_accurate_lock(unsigned int dfll_id)
{
	/* TODO: Add timeout mechanism */
	while (!dfll_is_accurate_locked(dfll_id)) {
		/* Do nothing */
	}

	return 0;
}

//@}
//! @}

#endif /* CLK_DFLL_H_INCLUDED */