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
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
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
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
00197
00199
00200 #endif