soc: atmel: sam0: Configure GCLK[4] to RTC
Configure the Generic Clock Generator to be used as source to RTC. The index 4 is now reserved to RTC. Signed-off-by: Gerson Fernando Budke <nandojve@gmail.com>
This commit is contained in:
parent
fb6079999d
commit
d4fe29c542
6 changed files with 150 additions and 73 deletions
|
@ -1,3 +1,4 @@
|
|||
# Copyright (c) 2024-2025 Gerson Fernando Budke <nandojve@gmail.com>
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
if SOC_SERIES_SAMD20 || SOC_SERIES_SAMD21 || SOC_SERIES_SAMR21
|
||||
|
@ -35,6 +36,21 @@ config SOC_ATMEL_SAMD_XOSC32K_CRYSTAL
|
|||
Enable the crystal oscillator (if disabled, expect a clock signal on
|
||||
XIN32).
|
||||
|
||||
DT_ATMEL_RTC := $(dt_nodelabel_path,rtc)
|
||||
DT_ATMEL_RTC_COUNTER_CLOCK_MODE := $(dt_node_str_prop_equals,$(DT_ATMEL_RTC),counter-mode,clock)
|
||||
|
||||
config SOC_ATMEL_SAMD_XOSC32K_PRESCALER
|
||||
int "XOSC32 Generic Clock Prescaler"
|
||||
range 1 512
|
||||
default 32 if "$(DT_ATMEL_RTC_COUNTER_CLOCK_MODE)"
|
||||
default 1
|
||||
depends on SOC_ATMEL_SAMD_XOSC32K
|
||||
help
|
||||
Configure the prescaler for the generic clock output
|
||||
connected on the xosc32. When using RTC in calendar mode
|
||||
the GCLK should be divided by 32 to RTC receive the
|
||||
1024 Hz reference clock.
|
||||
|
||||
config SOC_ATMEL_SAMD_XOSC
|
||||
bool "External 0.4..32 MHz clock source"
|
||||
help
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# Copyright (c) 2019 ML!PA Consulting GmbH
|
||||
# Copyright (c) 2024-2025 Gerson Fernando Budke <nandojve@gmail.com>
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
if SOC_SERIES_SAMD51 || SOC_SERIES_SAME51 || SOC_SERIES_SAME53 || SOC_SERIES_SAME54
|
||||
|
@ -18,6 +19,34 @@ config SOC_ATMEL_SAMD5X_XOSC32K_STARTUP
|
|||
help
|
||||
Selects the startup time for the external 32 kHz crystal oscillator.
|
||||
|
||||
config SOC_ATMEL_SAMD5X_XOSC32K_CRYSTAL
|
||||
bool "External 32.768 kHz clock is a crystal oscillator"
|
||||
depends on SOC_ATMEL_SAMD5X_XOSC32K
|
||||
default y
|
||||
help
|
||||
Enable the crystal oscillator (if disabled, expect a clock
|
||||
signal on XIN32).
|
||||
|
||||
config SOC_ATMEL_SAMD5X_XOSC32K_GAIN_HS
|
||||
bool "XOSC32 High Speed gain"
|
||||
depends on SOC_ATMEL_SAMD5X_XOSC32K
|
||||
help
|
||||
When this option is selected the gain is set High Speed
|
||||
instead standard.
|
||||
|
||||
DT_ATMEL_RTC := $(dt_nodelabel_path,rtc)
|
||||
DT_ATMEL_RTC_COUNTER_CLOCK_MODE := $(dt_node_str_prop_equals,$(DT_ATMEL_RTC),counter-mode,clock)
|
||||
|
||||
config SOC_ATMEL_SAMD5X_OSC32K_PRESCALER
|
||||
int "XOSC32 Generic Clock Prescaler"
|
||||
range 1 512
|
||||
default 32 if "$(DT_ATMEL_RTC_COUNTER_CLOCK_MODE)"
|
||||
default 1
|
||||
help
|
||||
Configure the prescaler for the generic clock output connected on the
|
||||
xosc32 or osculp32k. When using RTC in calendar mode the GCLK should
|
||||
be divided by 32 to RTC receive the 1024 Hz reference clock.
|
||||
|
||||
choice
|
||||
prompt "Main clock source"
|
||||
default SOC_ATMEL_SAMD5X_DEFAULT_AS_MAIN
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Kamil Serwus
|
||||
* Copyright (c) 2023 Gerson Fernando Budke <nandojve@gmail.com>
|
||||
* Copyright (c) 2023-2025 Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -10,11 +10,19 @@
|
|||
* @brief Atmel SAMC MCU series initialization code
|
||||
*/
|
||||
|
||||
/* GCLK Gen 0 -> GCLK_MAIN @ OSC48M
|
||||
* GCLK Gen 2 -> WDT @ reserved
|
||||
* GCLK Gen 0 -> ADC @ OSC48M
|
||||
* GCLK Gen 4 -> RTC @ reserved
|
||||
*/
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/init.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <soc.h>
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
static void flash_waitstates_init(void)
|
||||
{
|
||||
/* Two wait state at 48 MHz. */
|
||||
|
@ -50,3 +58,5 @@ void soc_reset_hook(void)
|
|||
mclk_init();
|
||||
gclks_init();
|
||||
}
|
||||
|
||||
/* clang-format on */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Google LLC.
|
||||
* Copyright (c) 2023 Ionut Catalin Pavel <iocapa@iocapa.com>
|
||||
* Copyright (c) 2023 Gerson Fernando Budke <nandojve@gmail.com>
|
||||
* Copyright (c) 2023-2025 Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -20,6 +20,7 @@
|
|||
* GCLK Gen 1 -> DFLL48M (variable)
|
||||
* GCLK Gen 2 -> WDT @ 32768 Hz
|
||||
* GCLK Gen 3 -> ADC @ 8 MHz
|
||||
* GCLK Gen 4 -> RTC @ xtal 32768 Hz
|
||||
*/
|
||||
|
||||
#include <zephyr/device.h>
|
||||
|
@ -29,6 +30,8 @@
|
|||
#include <soc.h>
|
||||
#include <cmsis_core.h>
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
/**
|
||||
* Fix different naming conventions for SAMD20
|
||||
*/
|
||||
|
@ -38,6 +41,23 @@
|
|||
#define FUSES_OSC32K_CAL_Msk FUSES_OSC32KCAL_Msk
|
||||
#endif
|
||||
|
||||
static void gclk_connect(uint8_t gclk, uint32_t src, uint32_t div, uint32_t flags)
|
||||
{
|
||||
GCLK->GENDIV.reg = GCLK_GENDIV_ID(gclk)
|
||||
| GCLK_GENDIV_DIV(div);
|
||||
|
||||
while (GCLK->STATUS.bit.SYNCBUSY) {
|
||||
}
|
||||
|
||||
GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(gclk)
|
||||
| GCLK_GENCTRL_GENEN
|
||||
| src
|
||||
| flags;
|
||||
|
||||
while (GCLK->STATUS.bit.SYNCBUSY) {
|
||||
}
|
||||
}
|
||||
|
||||
static inline void osc8m_init(void)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
@ -57,19 +77,7 @@ static inline void osc8m_init(void)
|
|||
/* Use 8Mhz clock as gclk_main to allow switching between clocks
|
||||
* when using bootloaders
|
||||
*/
|
||||
GCLK->GENDIV.reg = GCLK_GENDIV_ID(0)
|
||||
| GCLK_GENDIV_DIV(0);
|
||||
|
||||
while (GCLK->STATUS.bit.SYNCBUSY) {
|
||||
}
|
||||
|
||||
GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(0)
|
||||
| GCLK_GENCTRL_SRC_OSC8M
|
||||
| GCLK_GENCTRL_IDC
|
||||
| GCLK_GENCTRL_GENEN;
|
||||
|
||||
while (GCLK->STATUS.bit.SYNCBUSY) {
|
||||
}
|
||||
gclk_connect(0, GCLK_GENCTRL_SRC_OSC8M, 0, 0);
|
||||
}
|
||||
|
||||
#if !CONFIG_SOC_ATMEL_SAMD_OSC32K || CONFIG_SOC_ATMEL_SAMD_DEFAULT_AS_MAIN
|
||||
|
@ -149,28 +157,17 @@ static inline void dfll48m_init(void)
|
|||
{
|
||||
uint32_t fcal, ccal;
|
||||
|
||||
GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(1)
|
||||
gclk_connect(1,
|
||||
#if CONFIG_SOC_ATMEL_SAMD_OSC32K_AS_MAIN
|
||||
| GCLK_GENCTRL_SRC_OSC32K
|
||||
GCLK_GENCTRL_SRC_OSC32K,
|
||||
#elif CONFIG_SOC_ATMEL_SAMD_XOSC32K_AS_MAIN
|
||||
| GCLK_GENCTRL_SRC_XOSC32K
|
||||
GCLK_GENCTRL_SRC_XOSC32K,
|
||||
#elif CONFIG_SOC_ATMEL_SAMD_OSC8M_AS_MAIN
|
||||
| GCLK_GENCTRL_SRC_OSC8M
|
||||
GCLK_GENCTRL_SRC_OSC8M,
|
||||
#elif CONFIG_SOC_ATMEL_SAMD_XOSC_AS_MAIN
|
||||
| GCLK_GENCTRL_SRC_XOSC
|
||||
GCLK_GENCTRL_SRC_XOSC,
|
||||
#endif
|
||||
| GCLK_GENCTRL_IDC
|
||||
| GCLK_GENCTRL_RUNSTDBY
|
||||
| GCLK_GENCTRL_GENEN;
|
||||
|
||||
while (GCLK->STATUS.bit.SYNCBUSY) {
|
||||
}
|
||||
|
||||
GCLK->GENDIV.reg = GCLK_GENDIV_ID(1)
|
||||
| GCLK_GENDIV_DIV(SOC_ATMEL_SAM0_GCLK1_DIV);
|
||||
|
||||
while (GCLK->STATUS.bit.SYNCBUSY) {
|
||||
}
|
||||
SOC_ATMEL_SAM0_GCLK1_DIV, GCLK_GENCTRL_RUNSTDBY);
|
||||
|
||||
/* Route multiplexer 0 to DFLL48M */
|
||||
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(0)
|
||||
|
@ -222,19 +219,7 @@ static inline void flash_waitstates_init(void)
|
|||
#else
|
||||
static inline void gclk_main_configure(void)
|
||||
{
|
||||
GCLK->GENDIV.reg = GCLK_GENDIV_ID(0)
|
||||
| GCLK_GENDIV_DIV(SOC_ATMEL_SAM0_GCLK0_DIV);
|
||||
|
||||
while (GCLK->STATUS.bit.SYNCBUSY) {
|
||||
}
|
||||
|
||||
GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(0)
|
||||
| GCLK_GENCTRL_SRC_DFLL48M
|
||||
| GCLK_GENCTRL_IDC
|
||||
| GCLK_GENCTRL_GENEN;
|
||||
|
||||
while (GCLK->STATUS.bit.SYNCBUSY) {
|
||||
}
|
||||
gclk_connect(0, GCLK_GENCTRL_SRC_DFLL48M, SOC_ATMEL_SAM0_GCLK0_DIV, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -243,19 +228,16 @@ static inline void gclk_main_configure(void)
|
|||
#else
|
||||
static inline void gclk_adc_configure(void)
|
||||
{
|
||||
GCLK->GENDIV.reg = GCLK_GENDIV_ID(3)
|
||||
| GCLK_GENDIV_DIV(SOC_ATMEL_SAM0_GCLK3_DIV);
|
||||
gclk_connect(3, GCLK_GENCTRL_SRC_DFLL48M, SOC_ATMEL_SAM0_GCLK3_DIV, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
while (GCLK->STATUS.bit.SYNCBUSY) {
|
||||
}
|
||||
|
||||
GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(3)
|
||||
| GCLK_GENCTRL_SRC_DFLL48M
|
||||
| GCLK_GENCTRL_IDC
|
||||
| GCLK_GENCTRL_GENEN;
|
||||
|
||||
while (GCLK->STATUS.bit.SYNCBUSY) {
|
||||
}
|
||||
#if !CONFIG_RTC_ATMEL_SAM0 || CONFIG_SOC_ATMEL_SAMD_DEFAULT_AS_MAIN
|
||||
#define gclk_rtc_configure()
|
||||
#else
|
||||
static inline void gclk_rtc_configure(void)
|
||||
{
|
||||
gclk_connect(4, GCLK_GENCTRL_SRC_XOSC32K, CONFIG_SOC_ATMEL_SAMD_XOSC32K_PRESCALER, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -264,16 +246,7 @@ static inline void gclk_adc_configure(void)
|
|||
#else
|
||||
static inline void gclk_wdt_configure(void)
|
||||
{
|
||||
GCLK->GENDIV.reg = GCLK_GENDIV_ID(2)
|
||||
| GCLK_GENDIV_DIV(4);
|
||||
|
||||
GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(2)
|
||||
| GCLK_GENCTRL_GENEN
|
||||
| GCLK_GENCTRL_SRC_OSCULP32K
|
||||
| GCLK_GENCTRL_DIVSEL;
|
||||
|
||||
while (GCLK->STATUS.bit.SYNCBUSY) {
|
||||
}
|
||||
gclk_connect(2, GCLK_GENCTRL_SRC_OSCULP32K, 4, GCLK_GENCTRL_DIVSEL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -296,6 +269,9 @@ void soc_reset_hook(void)
|
|||
flash_waitstates_init();
|
||||
gclk_main_configure();
|
||||
gclk_adc_configure();
|
||||
gclk_rtc_configure();
|
||||
gclk_wdt_configure();
|
||||
osc8m_disable();
|
||||
}
|
||||
|
||||
/* clang-format on */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2019 ML!PA Consulting GmbH
|
||||
* Copyright (c) 2023 Gerson Fernando Budke <nandojve@gmail.com>
|
||||
* Copyright (c) 2023-2025 Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -10,30 +10,57 @@
|
|||
* @brief Atmel SAMD MCU series initialization code
|
||||
*/
|
||||
|
||||
/* The CPU clock will be configured to the DT requested value,
|
||||
* and run via DFLL48M.
|
||||
*
|
||||
* Reference -> GCLK Gen 1 -> DFLL48M -> GCLK Gen 0 -> GCLK_MAIN
|
||||
*
|
||||
* GCLK Gen 0 -> GCLK_MAIN @ DPLL0
|
||||
* GCLK Gen 1 -> DFLL48M @ 32768 Hz
|
||||
* GCLK Gen 2 -> USB @ DFLL48M
|
||||
* GCLK Gen 3 -> ADC @ reserved
|
||||
* GCLK Gen 4 -> RTC @ xtal 32768 Hz
|
||||
*/
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/init.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <soc.h>
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
#define SAM0_DFLL_FREQ_HZ (48000000U)
|
||||
#define SAM0_DPLL_FREQ_MIN_HZ (96000000U)
|
||||
#define SAM0_DPLL_FREQ_MAX_HZ (200000000U)
|
||||
#define SAM0_XOSC32K_STARTUP_TIME CONFIG_SOC_ATMEL_SAMD5X_XOSC32K_STARTUP
|
||||
|
||||
#if CONFIG_SOC_ATMEL_SAMD5X_XOSC32K_AS_MAIN
|
||||
static void osc32k_init(void)
|
||||
#if !CONFIG_SOC_ATMEL_SAMD5X_XOSC32K
|
||||
#define xosc32k_init()
|
||||
#else
|
||||
static inline void xosc32k_init(void)
|
||||
{
|
||||
OSC32KCTRL->XOSC32K.reg = OSC32KCTRL_XOSC32K_ENABLE
|
||||
#if CONFIG_SOC_ATMEL_SAMD5X_XOSC32K_CRYSTAL
|
||||
| OSC32KCTRL_XOSC32K_XTALEN
|
||||
#endif
|
||||
#if CONFIG_SOC_ATMEL_SAMD5X_XOSC32K_GAIN_HS
|
||||
| OSC32KCTRL_XOSC32K_CGM_HS
|
||||
#else
|
||||
| OSC32KCTRL_XOSC32K_CGM_XT
|
||||
#endif
|
||||
| OSC32KCTRL_XOSC32K_EN32K
|
||||
| OSC32KCTRL_XOSC32K_EN1K
|
||||
| OSC32KCTRL_XOSC32K_RUNSTDBY
|
||||
| OSC32KCTRL_XOSC32K_STARTUP(SAM0_XOSC32K_STARTUP_TIME)
|
||||
;
|
||||
| OSC32KCTRL_XOSC32K_STARTUP(SAM0_XOSC32K_STARTUP_TIME);
|
||||
|
||||
while (!OSC32KCTRL->STATUS.bit.XOSC32KRDY) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_SOC_ATMEL_SAMD5X_XOSC32K_AS_MAIN
|
||||
static void osc32k_init(void)
|
||||
{
|
||||
GCLK->GENCTRL[1].reg = GCLK_GENCTRL_SRC(GCLK_SOURCE_XOSC32K)
|
||||
| GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN;
|
||||
|
||||
|
@ -132,6 +159,7 @@ void soc_reset_hook(void)
|
|||
CMCC->CTRL.bit.CEN = 0;
|
||||
|
||||
gclk_reset();
|
||||
xosc32k_init();
|
||||
osc32k_init();
|
||||
dfll_init();
|
||||
dpll_init(0, dfll_div * CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC);
|
||||
|
@ -141,4 +169,15 @@ void soc_reset_hook(void)
|
|||
|
||||
/* connect GCLK2 to 48 MHz DFLL for USB */
|
||||
gclk_connect(2, GCLK_SOURCE_DFLL48M, 0);
|
||||
|
||||
/* connect GCLK4 to xosc32k for RTC. The output is 1024 Hz*/
|
||||
gclk_connect(4,
|
||||
#if CONFIG_SOC_ATMEL_SAMD5X_XOSC32K
|
||||
GCLK_SOURCE_XOSC32K,
|
||||
#else
|
||||
GCLK_SOURCE_OSCULP32K,
|
||||
#endif
|
||||
CONFIG_SOC_ATMEL_SAMD5X_OSC32K_PRESCALER);
|
||||
}
|
||||
|
||||
/* clang-format on */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Argentum Systems Ltd.
|
||||
* Copyright (c) 2023 Gerson Fernando Budke <nandojve@gmail.com>
|
||||
* Copyright (c) 2023-2025 Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -16,6 +16,8 @@
|
|||
#include <soc.h>
|
||||
#include <cmsis_core.h>
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
/* the SAML21 currently operates only in Performance Level 2... sleep
|
||||
* and low-power operation are not currently supported by the BSP
|
||||
*
|
||||
|
@ -27,6 +29,7 @@
|
|||
* GCLK Gen 1 -> DFLL48M (variable)
|
||||
* GCLK Gen 2 -> USB @ 48 MHz
|
||||
* GCLK Gen 3 -> ADC @ 24 MHz (further /2 in the ADC peripheral)
|
||||
* GCLK Gen 4 -> RTC @ reserved
|
||||
*/
|
||||
|
||||
static inline void gclk_reset(void)
|
||||
|
@ -57,6 +60,7 @@ static inline void osc32k_init(void)
|
|||
| !OSC32KCTRL_OSC32K_ONDEMAND
|
||||
| OSC32KCTRL_OSC32K_RUNSTDBY
|
||||
| OSC32KCTRL_OSC32K_EN32K
|
||||
| OSC32KCTRL_OSC32K_EN1K
|
||||
| OSC32KCTRL_OSC32K_ENABLE;
|
||||
|
||||
/* wait for ready */
|
||||
|
@ -75,6 +79,7 @@ static inline void xosc32k_init(void)
|
|||
| !OSC32KCTRL_XOSC32K_ONDEMAND
|
||||
| OSC32KCTRL_XOSC32K_RUNSTDBY
|
||||
| OSC32KCTRL_XOSC32K_EN32K
|
||||
| OSC32KCTRL_XOSC32K_EN1K
|
||||
#if CONFIG_SOC_ATMEL_SAML_XOSC32K_CRYSTAL
|
||||
| OSC32KCTRL_XOSC32K_XTALEN
|
||||
#endif
|
||||
|
@ -266,3 +271,5 @@ void soc_reset_hook(void)
|
|||
gclk_usb_configure();
|
||||
gclk_adc_configure();
|
||||
}
|
||||
|
||||
/* clang-format on */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue