atsamd: Do not generate 200M/100M interal clocks

Now that the internal DWT timer is used for software timers, there is
no need to clock the peripherals at a higher clock speed.  Clock all
peripherals at 48Mhz and simplify the clock generation code.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2019-02-14 13:05:06 -05:00
parent a00657d2ae
commit b33ad59e25
1 changed files with 2 additions and 51 deletions

View File

@ -9,18 +9,14 @@
// The "generic clock generators" that are configured // The "generic clock generators" that are configured
#define CLKGEN_MAIN 0 #define CLKGEN_MAIN 0
#define CLKGEN_200M 1
#define CLKGEN_32K 2 #define CLKGEN_32K 2
#define CLKGEN_48M 3 #define CLKGEN_48M 3
#define CLKGEN_2M 4 #define CLKGEN_2M 4
#define CLKGEN_100M 5
#define FREQ_MAIN 120000000 #define FREQ_MAIN 120000000
#define FREQ_200M 200000000
#define FREQ_32K 32768 #define FREQ_32K 32768
#define FREQ_48M 48000000 #define FREQ_48M 48000000
#define FREQ_2M 2000000 #define FREQ_2M 2000000
#define FREQ_100M 100000000
// Configure a clock generator using a given source as input // Configure a clock generator using a given source as input
static inline void static inline void
@ -45,12 +41,7 @@ route_pclock(uint32_t pclk_id, uint32_t clkgen_id)
void void
enable_pclock(uint32_t pclk_id, uint32_t pm_id) enable_pclock(uint32_t pclk_id, uint32_t pm_id)
{ {
uint32_t clkgen_id = CLKGEN_100M; route_pclock(pclk_id, CLKGEN_48M);
if (pclk_id == TC0_GCLK_ID || pclk_id == TC1_GCLK_ID)
clkgen_id = CLKGEN_200M;
else if (pclk_id == USB_GCLK_ID)
clkgen_id = CLKGEN_48M;
route_pclock(pclk_id, clkgen_id);
uint32_t pm_port = pm_id / 32, pm_bit = 1 << (pm_id % 32); uint32_t pm_port = pm_id / 32, pm_bit = 1 << (pm_id % 32);
(&MCLK->APBAMASK.reg)[pm_port] |= pm_bit; (&MCLK->APBAMASK.reg)[pm_port] |= pm_bit;
} }
@ -59,11 +50,7 @@ enable_pclock(uint32_t pclk_id, uint32_t pm_id)
uint32_t uint32_t
get_pclock_frequency(uint32_t pclk_id) get_pclock_frequency(uint32_t pclk_id)
{ {
if (pclk_id == TC0_GCLK_ID || pclk_id == TC1_GCLK_ID)
return FREQ_200M;
else if (pclk_id == USB_GCLK_ID)
return FREQ_48M; return FREQ_48M;
return FREQ_100M;
} }
// Initialize the clocks using an external 32K crystal // Initialize the clocks using an external 32K crystal
@ -94,24 +81,6 @@ clock_init_32k(void)
// Switch main clock to 120Mhz PLL0 // Switch main clock to 120Mhz PLL0
gen_clock(CLKGEN_MAIN, GCLK_GENCTRL_SRC_DPLL0); gen_clock(CLKGEN_MAIN, GCLK_GENCTRL_SRC_DPLL0);
// Generate 200Mhz clock on PLL1 (with CLKGEN_32K as reference)
route_pclock(OSCCTRL_GCLK_ID_FDPLL1, CLKGEN_32K);
mul = DIV_ROUND_CLOSEST(FREQ_200M, FREQ_32K);
OSCCTRL->Dpll[1].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDR(mul - 1);
while (OSCCTRL->Dpll[1].DPLLSYNCBUSY.reg & OSCCTRL_DPLLSYNCBUSY_DPLLRATIO)
;
OSCCTRL->Dpll[1].DPLLCTRLB.reg = (OSCCTRL_DPLLCTRLB_REFCLK_GCLK
| OSCCTRL_DPLLCTRLB_LBYPASS);
OSCCTRL->Dpll[1].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_ENABLE;
mask = OSCCTRL_DPLLSTATUS_CLKRDY | OSCCTRL_DPLLSTATUS_LOCK;
while ((OSCCTRL->Dpll[1].DPLLSTATUS.reg & mask) != mask)
;
// Produce 100Mhz and 200Mhz clocks from PLL1
gen_clock(CLKGEN_200M, GCLK_GENCTRL_SRC_DPLL1);
uint32_t div = DIV_ROUND_CLOSEST(FREQ_200M, FREQ_100M);
gen_clock(CLKGEN_100M, GCLK_GENCTRL_SRC_DPLL1 | GCLK_GENCTRL_DIV(div));
// Configure DFLL48M clock (with CLKGEN_32K as reference) // Configure DFLL48M clock (with CLKGEN_32K as reference)
OSCCTRL->DFLLCTRLA.reg = 0; OSCCTRL->DFLLCTRLA.reg = 0;
route_pclock(OSCCTRL_GCLK_ID_DFLL48, CLKGEN_32K); route_pclock(OSCCTRL_GCLK_ID_DFLL48, CLKGEN_32K);
@ -157,24 +126,6 @@ clock_init_internal(void)
// Switch main clock to 120Mhz PLL0 // Switch main clock to 120Mhz PLL0
gen_clock(CLKGEN_MAIN, GCLK_GENCTRL_SRC_DPLL0); gen_clock(CLKGEN_MAIN, GCLK_GENCTRL_SRC_DPLL0);
// Generate 200Mhz clock on PLL1 (with CLKGEN_2M as reference)
route_pclock(OSCCTRL_GCLK_ID_FDPLL1, CLKGEN_2M);
mul = DIV_ROUND_CLOSEST(FREQ_200M, FREQ_2M);
OSCCTRL->Dpll[1].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDR(mul - 1);
while (OSCCTRL->Dpll[1].DPLLSYNCBUSY.reg & OSCCTRL_DPLLSYNCBUSY_DPLLRATIO)
;
OSCCTRL->Dpll[1].DPLLCTRLB.reg = (OSCCTRL_DPLLCTRLB_REFCLK_GCLK
| OSCCTRL_DPLLCTRLB_LBYPASS);
OSCCTRL->Dpll[1].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_ENABLE;
mask = OSCCTRL_DPLLSTATUS_CLKRDY | OSCCTRL_DPLLSTATUS_LOCK;
while ((OSCCTRL->Dpll[1].DPLLSTATUS.reg & mask) != mask)
;
// Produce 100Mhz and 200Mhz clocks from PLL1
gen_clock(CLKGEN_200M, GCLK_GENCTRL_SRC_DPLL1);
div = DIV_ROUND_CLOSEST(FREQ_200M, FREQ_100M);
gen_clock(CLKGEN_100M, GCLK_GENCTRL_SRC_DPLL1 | GCLK_GENCTRL_DIV(div));
} }
void void