00001
00038 #ifndef CHIP_PLL_H_INCLUDED
00039 #define CHIP_PLL_H_INCLUDED
00040
00041 #include <assert.h>
00042 #include <clk/osc.h>
00043 #include <regs/xmega_osc.h>
00044 #include <status_codes.h>
00045 #include <stdint.h>
00046
00052 #define NR_PLLS 1
00053
00054 #define PLL_MIN_HZ 10000000UL
00055 #define PLL_MAX_HZ 200000000UL
00056
00057 enum pll_source {
00058 PLL_SRC_RC2MHZ = 0,
00059 PLL_SRC_RC32MHZ = 2,
00060 PLL_SRC_XOSC = 3,
00061 PLL_NR_SOURCES,
00062 };
00063
00064 #define pll_get_default_rate(pll_id) \
00065 ((osc_get_rate(CONFIG_PLL##pll_id##_SOURCE) \
00066 * CONFIG_PLL##pll_id##_MUL) \
00067 / CONFIG_PLL##pll_id##_DIV)
00068
00069 struct pll_config {
00070 uint8_t ctrl;
00071 };
00072
00079 static inline void pll_config_init(struct pll_config *cfg,
00080 enum pll_source src, unsigned int div, unsigned int mul)
00081 {
00082
00083 assert(src < PLL_NR_SOURCES && src != 1);
00084 assert(mul >= 1 && mul <= 31);
00085 assert(osc_get_rate(src) >= 400000);
00086 assert(osc_get_rate(src) * mul <= PLL_MAX_HZ);
00087
00088 if (src == PLL_SRC_RC32MHZ)
00089 assert(div == 4);
00090 else
00091 assert(div == 1);
00092
00093
00094 cfg->ctrl = OSC_BF(PLLSRC, src) | OSC_BF(PLLFAC, mul);
00095 }
00096
00097 #define pll_config_defaults(cfg, pll_id) \
00098 pll_config_init(cfg, \
00099 CONFIG_PLL##pll_id##_SOURCE, \
00100 CONFIG_PLL##pll_id##_DIV, \
00101 CONFIG_PLL##pll_id##_MUL)
00102
00103 static inline void pll_config_read(struct pll_config *cfg, unsigned int pll_id)
00104 {
00105 assert(pll_id < NR_PLLS);
00106
00107 cfg->ctrl = osc_read_reg(PLLCTRL);
00108 }
00109
00110 static inline void pll_config_write(const struct pll_config *cfg,
00111 unsigned int pll_id)
00112 {
00113 assert(pll_id < NR_PLLS);
00114
00115 osc_write_reg(PLLCTRL, cfg->ctrl);
00116 }
00117
00118 static inline void pll_enable(const struct pll_config *cfg,
00119 unsigned int pll_id)
00120 {
00121 uint8_t osc_ctrl;
00122
00123 pll_config_write(cfg, pll_id);
00124 osc_ctrl = osc_read_reg(CTRL);
00125 osc_ctrl |= OSC_BIT(PLLEN);
00126 osc_write_reg(CTRL, osc_ctrl);
00127 }
00128
00129 static inline void pll_disable(unsigned int pll_id)
00130 {
00131 uint8_t osc_ctrl;
00132
00133 assert(pll_id < NR_PLLS);
00134
00135 osc_ctrl = osc_read_reg(CTRL);
00136 osc_ctrl &= ~OSC_BIT(PLLEN);
00137 osc_write_reg(CTRL, osc_ctrl);
00138 }
00139
00140 static inline status_t pll_wait_for_lock(unsigned int pll_id)
00141 {
00142 assert(pll_id < NR_PLLS);
00143
00144 while (!(osc_read_reg(STATUS) & OSC_BIT(PLLRDY))) {
00145
00146 }
00147
00148 return STATUS_OK;
00149 }
00150
00152
00153 #endif