aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2021-06-04 17:03:46 -0400
committerKevin O'Connor <kevin@koconnor.net>2021-06-04 17:48:21 -0400
commitbd65c37ed5caac04857493518b07eda083659977 (patch)
tree0346d0743622f9964190442f5d8a4532926fc0d9
parent6266e7c259f6974254b7253d6bf028063fb9d03c (diff)
downloadkutter-bd65c37ed5caac04857493518b07eda083659977.tar.gz
kutter-bd65c37ed5caac04857493518b07eda083659977.tar.xz
kutter-bd65c37ed5caac04857493518b07eda083659977.zip
atsamd: Add support for 25Mhz crystals
Needed for the Duet3 Mini 5+ board. Reported by @lukeslaboratory. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
-rw-r--r--src/atsamd/Kconfig2
-rw-r--r--src/atsamd/samd51_clock.c31
2 files changed, 33 insertions, 0 deletions
diff --git a/src/atsamd/Kconfig b/src/atsamd/Kconfig
index 44ded6ca..5684ff6f 100644
--- a/src/atsamd/Kconfig
+++ b/src/atsamd/Kconfig
@@ -89,6 +89,8 @@ choice
prompt "Clock Reference"
config CLOCK_REF_X32K
bool "32.768Khz crystal"
+ config CLOCK_REF_X25M
+ bool "25Mhz crystal" if MACH_SAMD51
config CLOCK_REF_INTERNAL
bool "Internal clock"
endchoice
diff --git a/src/atsamd/samd51_clock.c b/src/atsamd/samd51_clock.c
index 046f5744..cf7402e5 100644
--- a/src/atsamd/samd51_clock.c
+++ b/src/atsamd/samd51_clock.c
@@ -97,6 +97,8 @@ config_dfll(uint32_t dfllmul, uint32_t ctrlb)
#if CONFIG_CLOCK_REF_X32K
DECL_CONSTANT_STR("RESERVE_PINS_crystal", "PA0,PA1");
+#elif CONFIG_CLOCK_REF_X25M
+DECL_CONSTANT_STR("RESERVE_PINS_crystal", "PB22,PB23");
#endif
// Initialize the clocks using an external 32K crystal
@@ -123,6 +125,33 @@ clock_init_32k(void)
gen_clock(CLKGEN_48M, GCLK_GENCTRL_SRC_DPLL1);
}
+// Initialize the clocks using an external 25M crystal
+static void
+clock_init_25m(void)
+{
+ // Enable XOSC1
+ uint32_t freq_xosc = 25000000;
+ uint32_t val = (OSCCTRL_XOSCCTRL_ENABLE | OSCCTRL_XOSCCTRL_XTALEN
+ | OSCCTRL_XOSCCTRL_IPTAT(3) | OSCCTRL_XOSCCTRL_IMULT(6));
+ OSCCTRL->XOSCCTRL[1].reg = val;
+ while (!(OSCCTRL->STATUS.reg & OSCCTRL_STATUS_XOSCRDY1))
+ ;
+
+ // Generate 120Mhz clock on PLL0 (with XOSC1 as reference)
+ uint32_t p0div = 10, p0mul = DIV_ROUND_CLOSEST(FREQ_MAIN, freq_xosc/p0div);
+ uint32_t p0ctrlb = OSCCTRL_DPLLCTRLB_DIV(p0div / 2 - 1);
+ config_dpll(0, p0mul, p0ctrlb | OSCCTRL_DPLLCTRLB_REFCLK_XOSC1);
+
+ // Switch main clock to 120Mhz PLL0
+ gen_clock(CLKGEN_MAIN, GCLK_GENCTRL_SRC_DPLL0);
+
+ // Generate 48Mhz clock on PLL1 (with XOSC1 as reference)
+ uint32_t p1div = 50, p1mul = DIV_ROUND_CLOSEST(FREQ_48M, freq_xosc/p1div);
+ uint32_t p1ctrlb = OSCCTRL_DPLLCTRLB_DIV(p1div / 2 - 1);
+ config_dpll(1, p1mul, p1ctrlb | OSCCTRL_DPLLCTRLB_REFCLK_XOSC1);
+ gen_clock(CLKGEN_48M, GCLK_GENCTRL_SRC_DPLL1);
+}
+
// Initialize clocks from factory calibrated internal clock
static void
clock_init_internal(void)
@@ -167,6 +196,8 @@ SystemInit(void)
// Init clocks
if (CONFIG_CLOCK_REF_X32K)
clock_init_32k();
+ else if (CONFIG_CLOCK_REF_X25M)
+ clock_init_25m();
else
clock_init_internal();