pll.h
Go to the documentation of this file.00001
00038 #ifndef XMEGA_PLL_H_INCLUDED
00039 #define XMEGA_PLL_H_INCLUDED
00040
00041 #include <compiler.h>
00042
00048 #define NR_PLLS 1
00049 #define PLL_MIN_HZ 10000000UL
00050 #define PLL_MAX_HZ 200000000UL
00051 #define PLL_NR_OPTIONS 0
00052
00053 enum pll_source {
00055 PLL_SRC_RC2MHZ = OSC_PLLSRC_RC2M_gc,
00057 PLL_SRC_RC32MHZ = OSC_PLLSRC_RC32M_gc,
00059 PLL_SRC_XOSC = OSC_PLLSRC_XOSC_gc,
00060 };
00061
00062 #define pll_get_default_rate(pll_id) \
00063 pll_get_default_rate_priv(CONFIG_PLL##pll_id##_SOURCE, \
00064 CONFIG_PLL##pll_id##_MUL, \
00065 CONFIG_PLL##pll_id##_DIV)
00066
00081 static inline uint32_t pll_get_default_rate_priv(enum pll_source src,
00082 unsigned int mul, unsigned int div)
00083 {
00084 uint32_t rate;
00085
00086 switch (src) {
00087 case PLL_SRC_RC2MHZ:
00088 rate = 2000000UL;
00089 Assert(div == 1);
00090 break;
00091
00092 case PLL_SRC_RC32MHZ:
00093 rate = 8000000UL;
00094 Assert(div == 4);
00095 break;
00096
00097 case PLL_SRC_XOSC:
00098 rate = osc_get_rate(OSC_ID_XOSC);
00099 Assert(div == 1);
00100 break;
00101
00102 default:
00103 break;
00104 }
00105
00106 Assert(rate >= 440000UL);
00107
00108 rate *= mul;
00109
00110 Assert(rate >= PLL_MIN_HZ);
00111 Assert(rate <= PLL_MAX_HZ);
00112
00113 return rate;
00114 }
00115
00116 struct pll_config {
00117 uint8_t ctrl;
00118 };
00119
00126 static inline void pll_config_init(struct pll_config *cfg, enum pll_source src,
00127 unsigned int div, unsigned int mul)
00128 {
00129 Assert(mul >= 1 && mul <= 31);
00130
00131 if (src == PLL_SRC_RC32MHZ) {
00132 Assert(div == 4);
00133 } else {
00134 Assert(div == 1);
00135 }
00136
00137
00138 cfg->ctrl = src | (mul << OSC_PLLFAC_gp);
00139 }
00140
00141 #define pll_config_defaults(cfg, pll_id) \
00142 pll_config_init(cfg, \
00143 CONFIG_PLL##pll_id##_SOURCE, \
00144 CONFIG_PLL##pll_id##_DIV, \
00145 CONFIG_PLL##pll_id##_MUL)
00146
00147 static inline void pll_config_read(struct pll_config *cfg, unsigned int pll_id)
00148 {
00149 Assert(pll_id < NR_PLLS);
00150
00151 cfg->ctrl = OSC.PLLCTRL;
00152 }
00153
00154 static inline void pll_config_write(const struct pll_config *cfg,
00155 unsigned int pll_id)
00156 {
00157 Assert(pll_id < NR_PLLS);
00158
00159 OSC.PLLCTRL = cfg->ctrl;
00160 }
00161
00167 static inline void pll_enable(const struct pll_config *cfg,
00168 unsigned int pll_id)
00169 {
00170 irqflags_t flags;
00171
00172 Assert(pll_id < NR_PLLS);
00173
00174 flags = cpu_irq_save();
00175 pll_config_write(cfg, pll_id);
00176 OSC.CTRL |= OSC_PLLEN_bm;
00177 cpu_irq_restore(flags);
00178 }
00179
00183 static inline void pll_disable(unsigned int pll_id)
00184 {
00185 irqflags_t flags;
00186
00187 Assert(pll_id < NR_PLLS);
00188
00189 flags = cpu_irq_save();
00190 OSC.CTRL &= ~OSC_PLLEN_bm;
00191 cpu_irq_restore(flags);
00192 }
00193
00194 static inline bool pll_is_locked(unsigned int pll_id)
00195 {
00196 Assert(pll_id < NR_PLLS);
00197
00198 return OSC.STATUS & OSC_PLLRDY_bm;
00199 }
00200
00202
00203 #endif