sysclk.c
Go to the documentation of this file.00001
00039 #include <compiler.h>
00040
00041 #include <sysclk.h>
00042 #include <osc.h>
00043 #include <pll.h>
00044 #if (CONFIG_OSC_RC32_CAL==48000000UL)
00045 #include <nvm.h>
00046 #endif
00047
00048 #ifdef CONFIG_PLL0_SOURCE
00049 static void sysclk_init_pll(void)
00050 {
00051 struct pll_config pllcfg;
00052
00053 switch (CONFIG_PLL0_SOURCE) {
00054 case PLL_SRC_RC2MHZ:
00055 break;
00056
00057 case PLL_SRC_RC32MHZ:
00058 osc_enable(OSC_ID_RC32MHZ);
00059 osc_wait_ready(OSC_ID_RC32MHZ);
00060 break;
00061
00062 case PLL_SRC_XOSC:
00063 osc_enable(OSC_ID_XOSC);
00064 osc_wait_ready(OSC_ID_XOSC);
00065 break;
00066
00067 default:
00068
00069 break;
00070 }
00071
00072 pll_config_defaults(&pllcfg, 0);
00073 pll_enable(&pllcfg, 0);
00074 pll_wait_for_lock(0);
00075 }
00076 #endif
00077
00078 void sysclk_init(void)
00079 {
00080 uint8_t *reg = (uint8_t *)&PR.PRGEN;
00081 uint8_t i;
00082 #ifdef CONFIG_OSC_RC32_CAL
00083 uint16_t cal;
00084 #endif
00085
00086
00087 for (i = 0; i <= SYSCLK_PORT_F; i++) {
00088 *(reg++) = 0xff;
00089 }
00090
00091
00092 if ((CONFIG_SYSCLK_PSADIV != SYSCLK_PSADIV_1)
00093 || (CONFIG_SYSCLK_PSBCDIV != SYSCLK_PSBCDIV_1_1)) {
00094 sysclk_set_prescalers(CONFIG_SYSCLK_PSADIV,
00095 CONFIG_SYSCLK_PSBCDIV);
00096 }
00097
00098
00099
00100
00101
00102 if (CONFIG_SYSCLK_SOURCE != SYSCLK_SRC_RC2MHZ) {
00103 bool need_rc2mhz = false;
00104
00105 switch (CONFIG_SYSCLK_SOURCE) {
00106 case SYSCLK_SRC_RC32MHZ:
00107 #if (CONFIG_OSC_RC32_CAL==48000000UL)
00108 MSB(cal) = nvm_read_production_signature_row(nvm_get_production_signature_row_offset(USBRCOSCB));
00109 LSB(cal) = nvm_read_production_signature_row(nvm_get_production_signature_row_offset(USBRCOSCA));
00110 osc_user_calibration(OSC_ID_RC32MHZ,cal);
00111 #endif
00112 osc_enable(OSC_ID_RC32MHZ);
00113 osc_wait_ready(OSC_ID_RC32MHZ);
00114 break;
00115
00116 case SYSCLK_SRC_RC32KHZ:
00117 osc_enable(OSC_ID_RC32KHZ);
00118 osc_wait_ready(OSC_ID_RC32KHZ);
00119 break;
00120
00121 case SYSCLK_SRC_XOSC:
00122 osc_enable(OSC_ID_XOSC);
00123 osc_wait_ready(OSC_ID_XOSC);
00124 break;
00125
00126 #ifdef CONFIG_PLL0_SOURCE
00127 case SYSCLK_SRC_PLL:
00128 if (CONFIG_PLL0_SOURCE == PLL_SRC_RC2MHZ) {
00129 need_rc2mhz = true;
00130 }
00131 sysclk_init_pll();
00132 break;
00133 #endif
00134
00135 default:
00136
00137 return;
00138 }
00139
00140 ccp_write_io((uint8_t *)&CLK.CTRL, CONFIG_SYSCLK_SOURCE);
00141 Assert(CLK.CTRL == CONFIG_SYSCLK_SOURCE);
00142
00143 #ifdef CONFIG_OSC_AUTOCAL
00144 osc_enable_autocalibration(CONFIG_OSC_AUTOCAL,CONFIG_OSC_AUTOCAL_REF_OSC);
00145 if (CONFIG_OSC_AUTOCAL == OSC_ID_RC2MHZ\
00146 || CONFIG_OSC_AUTOCAL_REF_OSC == OSC_ID_RC2MHZ) {
00147 need_rc2mhz = true;
00148 }
00149 #endif
00150
00151 if (!need_rc2mhz) {
00152 osc_disable(OSC_ID_RC2MHZ);
00153 }
00154 }
00155 }
00156
00157 void sysclk_enable_module(enum sysclk_port_id port, uint8_t id)
00158 {
00159 irqflags_t flags = cpu_irq_save();
00160
00161 *((uint8_t *)&PR.PRGEN + port) &= ~id;
00162
00163 cpu_irq_restore(flags);
00164 }
00165
00166 void sysclk_disable_module(enum sysclk_port_id port, uint8_t id)
00167 {
00168 irqflags_t flags = cpu_irq_save();
00169
00170 *((uint8_t *)&PR.PRGEN + port) |= id;
00171
00172 cpu_irq_restore(flags);
00173 }
00174
00175 #if XMEGA_USB
00176 # if defined(CONFIG_USBCLK_SOURCE) || defined(__DOXYGEN__)
00177
00186 void sysclk_enable_usb(uint8_t freq)
00187 {
00188 uint8_t prescaler;
00189
00190
00191 if (freq == 6) {
00192 prescaler = CLK_USBPSDIV_8_gc;
00193 } else {
00194
00195 Assert(freq == 48);
00196 prescaler = 0;
00197 }
00198 ccp_write_io((uint8_t *)&CLK.USBCTRL, (prescaler)
00199 | (CONFIG_USBCLK_SOURCE)
00200 | CLK_USBEN_bm);
00201
00202 sysclk_enable_module(SYSCLK_PORT_GEN, SYSCLK_USB);
00203 }
00204
00208 void sysclk_disable_usb(void)
00209 {
00210 sysclk_disable_module(SYSCLK_PORT_GEN, SYSCLK_USB);
00211 ccp_write_io((uint8_t *)&CLK.USBCTRL, 0);
00212 }
00213 # endif // CONFIG_USBCLK_SOURCE
00214 #endif // XMEGA_USB