/** | |
* \file | |
* | |
* \brief Part-specific system clock management | |
* | |
* Copyright (C) 2010 Atmel Corporation. All rights reserved. | |
* | |
* \page License | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions are met: | |
* | |
* 1. Redistributions of source code must retain the above copyright notice, | |
* this list of conditions and the following disclaimer. | |
* | |
* 2. Redistributions in binary form must reproduce the above copyright notice, | |
* this list of conditions and the following disclaimer in the documentation | |
* and/or other materials provided with the distribution. | |
* | |
* 3. The name of Atmel may not be used to endorse or promote products derived | |
* from this software without specific prior written permission. | |
* | |
* 4. This software may only be redistributed and used in connection with an | |
* Atmel AVR product. | |
* | |
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED | |
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE | |
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR | |
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH | |
* DAMAGE. | |
*/ | |
#include "preprocessor.h" | |
#include "compiler.h" | |
#include "board.h" | |
#include "pm_uc3d.h" | |
#include "scif_uc3d.h" | |
#include "ast.h" | |
#include "cycle_counter.h" | |
#include "flashcdw.h" | |
#include "freq_detect.h" | |
/*! | |
* Detects extern OSC frequency and enable USB clock | |
*/ | |
void sysclk_init(void) | |
{ | |
int mul; | |
// Switch to OSC ISP | |
// Set max startup time to make sure any crystal will be supported | |
// We cannot use a TC to measure this OSC frequency | |
// because the master clock must be faster than the clock selected by the TC | |
// Configure OSC0 in crystal mode, external crystal | |
// with a fcrystal Hz frequency. | |
scif_configure_osc_crystalmode(SCIF_OSC0, 12000000); | |
// Enable the OSC0 | |
scif_enable_osc(SCIF_OSC0, AVR32_SCIF_OSCCTRL0_STARTUP_16384_RCOSC, | |
true); | |
flashcdw_set_flash_waitstate_and_readmode(12000000); | |
pm_set_mclk_source(PM_CLK_SRC_OSC0); | |
// Initialize the AST with the internal RC oscillator | |
// AST will count at the frequency of 115KHz/2 | |
if (!ast_init_counter(&AVR32_AST, AST_OSC_RC, 0, 0)) { | |
while (1); | |
} | |
// Enable the AST | |
ast_enable(&AVR32_AST); | |
// Detect the frequency | |
// mul = (((96000000 / freq_detect_start())/2)-1) | |
switch (freq_detect_start()) { | |
case 8000000: | |
mul = 5; | |
break; | |
case 16000000: | |
mul = 2; | |
break; | |
case 12000000: | |
default: | |
mul = 3; | |
break; | |
} | |
scif_pll_opt_t opt; | |
// Set PLL0 VCO @ 96 MHz | |
// Set PLL0 @ 48 MHz | |
opt.osc = SCIF_OSC0; | |
opt.lockcount = 63; | |
opt.div = 0; | |
opt.mul = mul; | |
opt.pll_div2 = 1; | |
opt.pll_wbwdisable = 0; | |
opt.pll_freq = 1; | |
// lockcount in main clock for the PLL wait lock | |
scif_pll_setup(SCIF_PLL0, opt); | |
/* Enable PLL0 */ | |
scif_pll_enable(SCIF_PLL0); | |
/* Wait for PLL0 locked */ | |
scif_wait_for_pll_locked(SCIF_PLL0); | |
// Use 1 flash wait state | |
flashcdw_set_wait_state(1); | |
// Switch the main clock to PLL0 | |
pm_set_mclk_source(PM_CLK_SRC_PLL0); | |
// fPBA: 12 MHz | |
// fPBB: 12 MHz | |
// fHSB: 12 MHz | |
pm_set_clk_domain_div(PM_CLK_DOMAIN_0, PM_CKSEL_DIVRATIO_4); // CPU | |
pm_set_clk_domain_div(PM_CLK_DOMAIN_1, PM_CKSEL_DIVRATIO_4); // HSB | |
pm_set_clk_domain_div(PM_CLK_DOMAIN_3, PM_CKSEL_DIVRATIO_4); // PBB | |
pm_set_clk_domain_div(PM_CLK_DOMAIN_2, PM_CKSEL_DIVRATIO_4); // PBA | |
// Use 0 flash wait state | |
flashcdw_set_wait_state(0); | |
} | |
/*! | |
* Reset the generation of system clocks and switch to RCOsc | |
*/ | |
void sysclk_reset(void) | |
{ | |
flashcdw_set_wait_state(1); | |
pm_set_clk_domain_div(PM_CLK_DOMAIN_0, PM_CKSEL_DIVRATIO_2); // CPU | |
pm_set_clk_domain_div(PM_CLK_DOMAIN_1, PM_CKSEL_DIVRATIO_2); // HSB | |
pm_set_clk_domain_div(PM_CLK_DOMAIN_3, PM_CKSEL_DIVRATIO_2); // PBB | |
pm_set_clk_domain_div(PM_CLK_DOMAIN_2, PM_CKSEL_DIVRATIO_2); // PBA | |
pm_set_mclk_source(PM_CLK_SRC_SLOW); | |
flashcdw_set_wait_state(0); | |
scif_pll_disable(SCIF_PLL0); | |
scif_pll_opt_t opt; | |
opt.osc = 0; | |
opt.lockcount = 0; | |
opt.div = 0; | |
opt.mul = 0; | |
opt.pll_div2 = 0; | |
opt.pll_wbwdisable = 0; | |
opt.pll_freq = 0; | |
scif_pll_setup(SCIF_PLL0, opt); // lockcount in main clock for the PLL wait lock | |
} | |
void sysclk_enable_usb(void) | |
{ | |
// Setup USB GCLK | |
scif_gc_setup(AVR32_SCIF_GCLK_USBC, | |
SCIF_GCCTRL_PLL0, AVR32_SCIF_GC_NO_DIV_CLOCK, 0); | |
// Enable USB GCLK | |
scif_gc_enable(AVR32_SCIF_GCLK_USBC); | |
} | |
void sysclk_disable_usb(void) | |
{ | |
AVR32_SCIF.gcctrl[AVR32_SCIF_GCLK_USBC] = 0; | |
scif_gc_setup(AVR32_SCIF_GCLK_USBC, | |
SCIF_GCCTRL_PLL0, AVR32_SCIF_GC_NO_DIV_CLOCK, 0); | |
} | |
void freq_detect_iface_ref_cnt_reset(void) | |
{ | |
ast_set_counter_value(&AVR32_AST, 0); | |
} | |
int freq_detect_iface_ref_cnt_value(void) | |
{ | |
return ast_get_counter_value(&AVR32_AST) * 2; | |
} | |
void freq_detect_iface_target_cnt_reset(void) | |
{ | |
Set_sys_count(0); | |
} | |
int freq_detetc_iface_target_cnt_value(void) | |
{ | |
return Get_sys_count(); | |
} |