Xmega Application Note


pll.h

Go to the documentation of this file.
00001 
00038 #ifndef CHIP_PLL_H_INCLUDED
00039 #define CHIP_PLL_H_INCLUDED
00040 
00046 #define PLL_MAX_STARTUP_CYCLES    ((1 << AVR32_PM_PLL0_PLLCOUNT_SIZE) - 1)
00047 #define NR_PLLS                   2
00048 
00052 #define PLL_TIMEOUT_MS    \
00053         div_ceil(1000 * (PLL_MAX_STARTUP_CYCLES * 2), OSC_SLOW_MIN_HZ)
00054 
00059 #define PLL_MIN_HZ                40000000
00060 #define PLL_MAX_HZ                240000000
00061 
00063 
00064 
00065 #define PLL_OPT_VCO_RANGE_LOW     0
00066 
00067 #define PLL_OPT_OUTPUT_DIV        1
00068 
00069 #define PLL_OPT_WBM_DISABLE       2
00070 
00071 #define PLL_NR_OPTIONS            AVR32_PM_PLL0_PLLOPT_SIZE
00072 
00073 #define PLL_VCO_LOW_THRESHOLD     AVR32_PM_PLL_VCO_RANGE0_MIN_FREQ
00074 
00075 
00076 #ifndef __ASSEMBLY__
00077 
00078 #include <avr32/io.h>
00079 #include <osc.h>
00080 #include <stdbool.h>
00081 #include <stdint.h>
00082 
00083 enum pll_source {
00084         PLL_SRC_OSC0            = 0,    
00085         PLL_SRC_OSC1            = 1,    
00086         PLL_NR_SOURCES,                 
00087 };
00088 
00089 struct pll_config {
00090         uint32_t ctrl;
00091 };
00092 
00093 #define pll_get_default_rate(pll_id)                                           \
00094         ((osc_get_rate(CONFIG_PLL##pll_id##_SOURCE)                            \
00095                         * CONFIG_PLL##pll_id##_MUL)                            \
00096                         / CONFIG_PLL##pll_id##_DIV)
00097 
00098 static inline void pll_config_set_option(struct pll_config *cfg,
00099                 unsigned int option)
00100 {
00101         Assert(option < PLL_NR_OPTIONS);
00102 
00103         cfg->ctrl |= 1U << (AVR32_PM_PLL0_PLLOPT + option);
00104 }
00105 
00106 static inline void pll_config_clear_option(struct pll_config *cfg,
00107                 unsigned int option)
00108 {
00109         Assert(option < PLL_NR_OPTIONS);
00110 
00111         cfg->ctrl &= ~(1U << (AVR32_PM_PLL0_PLLOPT + option));
00112 }
00113 
00118 static inline void pll_config_init(struct pll_config *cfg,
00119                 enum pll_source src, unsigned int div, unsigned int mul)
00120 {
00121         uint32_t vco_hz;
00122 
00123         Assert(src < PLL_NR_SOURCES);
00124 
00125         /* Calculate internal VCO frequency */
00126         vco_hz = osc_get_rate(src) * mul;
00127         vco_hz /= div;
00128         Assert(vco_hz >= PLL_MIN_HZ);
00129         Assert(vco_hz <= PLL_MAX_HZ);
00130 
00131         cfg->ctrl = 0;
00132 
00133         /* Bring the internal VCO frequency up to the minimum value */
00134         if ((vco_hz < PLL_MIN_HZ * 2) && (mul <= 8)) {
00135                 mul *= 2;
00136                 vco_hz *= 2;
00137                 pll_config_set_option(cfg, PLL_OPT_OUTPUT_DIV);
00138         }
00139 
00140         /* Set VCO frequency range according to calculated value */
00141         if (vco_hz < PLL_VCO_LOW_THRESHOLD)
00142                 pll_config_set_option(cfg, PLL_OPT_VCO_RANGE_LOW);
00143 
00144         Assert((mul > 2) && (mul <= 16));
00145         Assert((div > 0) && (div <= 15));
00146 
00147         cfg->ctrl |= ((mul - 1) << AVR32_PM_PLL0_PLLMUL)
00148                         | (div << AVR32_PM_PLL0_PLLDIV)
00149                         | (PLL_MAX_STARTUP_CYCLES << AVR32_PM_PLL0_PLLCOUNT)
00150                         | (src << AVR32_PM_PLL0_PLLOSC);
00151 }
00152 
00153 #define pll_config_defaults(cfg, pll_id)                                       \
00154         pll_config_init(cfg,                                                   \
00155                         CONFIG_PLL##pll_id##_SOURCE,                           \
00156                         CONFIG_PLL##pll_id##_DIV,                              \
00157                         CONFIG_PLL##pll_id##_MUL)
00158 
00159 static inline void pll_config_read(struct pll_config *cfg, unsigned int pll_id)
00160 {
00161         Assert(pll_id < NR_PLLS);
00162 
00163         cfg->ctrl = AVR32_PM.pll[pll_id];
00164 }
00165 
00166 static inline void pll_config_write(const struct pll_config *cfg,
00167                 unsigned int pll_id)
00168 {
00169         Assert(pll_id < NR_PLLS);
00170 
00171         AVR32_PM.pll[pll_id] = cfg->ctrl;
00172 }
00173 
00174 static inline void pll_enable(const struct pll_config *cfg,
00175                 unsigned int pll_id)
00176 {
00177         Assert(pll_id < NR_PLLS);
00178 
00179         AVR32_PM.pll[pll_id] = cfg->ctrl | (1U << AVR32_PM_PLL0_PLLEN);
00180 }
00181 
00182 static inline void pll_disable(unsigned int pll_id)
00183 {
00184         Assert(pll_id < NR_PLLS);
00185 
00186         AVR32_PM.pll[pll_id] = 0;
00187 }
00188 
00189 static inline bool pll_is_locked(unsigned int pll_id)
00190 {
00191         Assert(pll_id < NR_PLLS);
00192 
00193         return !!(AVR32_PM.poscsr & (1U << (AVR32_PM_POSCSR_LOCK0 + pll_id)));
00194 }
00195 
00196 #endif /* __ASSEMBLY__ */
00197 
00199 
00200 #endif /* CHIP_PLL_H_INCLUDED */
@DOC_TITLE@
Generated on Fri Oct 22 12:15:25 2010 for AVR1300 Using the Xmega ADC by doxygen 1.6.3