From cd0873015a1c8d54d83795dc4673b2df5c8cbfec Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Fri, 15 Mar 2019 23:39:57 +0100 Subject: [PATCH] timer: sam0_rtc_timer: Add support for SAME54 The RTC peripheral found in the SAMD5x/SAME5x MCUs is very simmilar to the one found in existing sam0 devices with only a few changes to register names and the clock source selection. Signed-off-by: Benjamin Valentin --- drivers/timer/sam0_rtc_timer.c | 55 ++++++++++++++-- soc/arm/atmel_sam0/common/tc_fixup_samd5x.h | 73 +++++++++++++++++++++ 2 files changed, 124 insertions(+), 4 deletions(-) create mode 100644 soc/arm/atmel_sam0/common/tc_fixup_samd5x.h diff --git a/drivers/timer/sam0_rtc_timer.c b/drivers/timer/sam0_rtc_timer.c index c7fc68b7543..2a0b5f93f7c 100644 --- a/drivers/timer/sam0_rtc_timer.c +++ b/drivers/timer/sam0_rtc_timer.c @@ -22,8 +22,14 @@ /* RTC registers. */ #define RTC0 ((RtcMode0 *) DT_INST_0_ATMEL_SAM0_RTC_BASE_ADDRESS) +#ifdef MCLK +#define RTC_CLOCK_HW_CYCLES_PER_SEC SOC_ATMEL_SAM0_OSC32K_FREQ_HZ +#else +#define RTC_CLOCK_HW_CYCLES_PER_SEC SOC_ATMEL_SAM0_GCLK0_FREQ_HZ +#endif + /* Number of sys timer cycles per on tick. */ -#define CYCLES_PER_TICK (SOC_ATMEL_SAM0_GCLK0_FREQ_HZ \ +#define CYCLES_PER_TICK (RTC_CLOCK_HW_CYCLES_PER_SEC \ / CONFIG_SYS_CLOCK_TICKS_PER_SEC) /* Maximum number of ticks. */ @@ -76,9 +82,14 @@ static volatile u32_t rtc_timeout; */ static inline void rtc_sync(void) { + /* Wait for bus synchronization... */ +#ifdef RTC_STATUS_SYNCBUSY while (RTC0->STATUS.reg & RTC_STATUS_SYNCBUSY) { - /* Wait for bus synchronization... */ } +#else + while (RTC0->SYNCBUSY.reg) { + } +#endif } /* @@ -88,7 +99,9 @@ static inline void rtc_sync(void) */ static u32_t rtc_count(void) { +#ifdef RTC_READREQ_RREQ RTC0->READREQ.reg = RTC_READREQ_RREQ; +#endif rtc_sync(); return RTC0->COUNT.reg; } @@ -103,12 +116,24 @@ static void rtc_reset(void) RTC0->INTFLAG.reg = RTC_MODE0_INTFLAG_MASK; /* Disable RTC module. */ +#ifdef RTC_MODE0_CTRL_ENABLE RTC0->CTRL.reg &= ~RTC_MODE0_CTRL_ENABLE; +#else + RTC0->CTRLA.reg &= ~RTC_MODE0_CTRLA_ENABLE; +#endif rtc_sync(); /* Initiate software reset. */ - RTC0->CTRL.reg |= RTC_MODE0_CTRL_SWRST; +#ifdef RTC_MODE0_CTRL_SWRST + RTC0->CTRL.bit.SWRST = 1; + while (RTC0->CTRL.bit.SWRST) { + } +#else + RTC0->CTRLA.bit.SWRST = 1; + while (RTC0->CTRLA.bit.SWRST) { + } +#endif } static void rtc_isr(void *arg) @@ -152,14 +177,19 @@ int z_clock_driver_init(struct device *device) { ARG_UNUSED(device); +#ifdef MCLK + MCLK->APBAMASK.reg |= MCLK_APBAMASK_RTC; + OSC32KCTRL->RTCCTRL.reg = OSC32KCTRL_RTCCTRL_RTCSEL_ULP32K; +#else /* Set up bus clock and GCLK generator. */ PM->APBAMASK.reg |= PM_APBAMASK_RTC; GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(RTC_GCLK_ID) | GCLK_CLKCTRL_CLKEN | GCLK_GEN(DT_INST_0_ATMEL_SAM0_RTC_CLOCK_GENERATOR); + /* Synchronize GCLK. */ while (GCLK->STATUS.bit.SYNCBUSY) { - /* Synchronize GCLK. */ } +#endif /* Reset module to hardware defaults. */ rtc_reset(); @@ -167,12 +197,25 @@ int z_clock_driver_init(struct device *device) rtc_last = 0U; /* Configure RTC with 32-bit mode, configured prescaler and MATCHCLR. */ +#ifdef RTC_MODE0_CTRL_MODE u16_t ctrl = RTC_MODE0_CTRL_MODE(0) | RTC_MODE0_CTRL_PRESCALER(0); +#else + u16_t ctrl = RTC_MODE0_CTRLA_MODE(0) | RTC_MODE0_CTRLA_PRESCALER(0); +#endif + #ifndef CONFIG_TICKLESS_KERNEL +#ifdef RTC_MODE0_CTRL_MATCHCLR ctrl |= RTC_MODE0_CTRL_MATCHCLR; +#else + ctrl |= RTC_MODE0_CTRLA_MATCHCLR; +#endif #endif rtc_sync(); +#ifdef RTC_MODE0_CTRL_MODE RTC0->CTRL.reg = ctrl; +#else + RTC0->CTRLA.reg = ctrl; +#endif #ifdef CONFIG_TICKLESS_KERNEL /* Tickless kernel lets RTC count continually and ignores overflows. */ @@ -188,7 +231,11 @@ int z_clock_driver_init(struct device *device) /* Enable RTC module. */ rtc_sync(); +#ifdef RTC_MODE0_CTRL_ENABLE RTC0->CTRL.reg |= RTC_MODE0_CTRL_ENABLE; +#else + RTC0->CTRLA.reg |= RTC_MODE0_CTRLA_ENABLE; +#endif /* Enable RTC interrupt. */ NVIC_ClearPendingIRQ(DT_INST_0_ATMEL_SAM0_RTC_IRQ_0); diff --git a/soc/arm/atmel_sam0/common/tc_fixup_samd5x.h b/soc/arm/atmel_sam0/common/tc_fixup_samd5x.h new file mode 100644 index 00000000000..e45c048b7f4 --- /dev/null +++ b/soc/arm/atmel_sam0/common/tc_fixup_samd5x.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2019 ML!PA Consulting GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifdef MCLK_APBAMASK_TC0 +#define MCLK_TC0 (&MCLK->APBAMASK.reg) +#define MCLK_TC0_MASK ((1 << MCLK_APBAMASK_TC0_Pos) | (1 << MCLK_APBAMASK_TC1_Pos)) +#endif +#ifdef MCLK_APBBMASK_TC0 +#define MCLK_TC0 (&MCLK->APBBMASK.reg) +#define MCLK_TC0_MASK ((1 << MCLK_APBBMASK_TC0_Pos) | (1 << MCLK_APBBMASK_TC1_Pos)) +#endif +#ifdef MCLK_APBCMASK_TC0 +#define MCLK_TC0 (&MCLK->APBCMASK.reg) +#define MCLK_TC0_MASK ((1 << MCLK_APBCMASK_TC0_Pos) | (1 << MCLK_APBCMASK_TC1_Pos)) +#endif +#ifdef MCLK_APBDMASK_TC0 +#define MCLK_TC0 (&MCLK->APBDMASK.reg) +#define MCLK_TC0_MASK ((1 << MCLK_APBDMASK_TC0_Pos) | (1 << MCLK_APBDMASK_TC1_Pos)) +#endif + +#ifdef MCLK_APBAMASK_TC2 +#define MCLK_TC2 (&MCLK->APBAMASK.reg) +#define MCLK_TC2_MASK ((1 << MCLK_APBAMASK_TC2_Pos) | (1 << MCLK_APBAMASK_TC3_Pos)) +#endif +#ifdef MCLK_APBBMASK_TC2 +#define MCLK_TC2 (&MCLK->APBBMASK.reg) +#define MCLK_TC2_MASK ((1 << MCLK_APBBMASK_TC2_Pos) | (1 << MCLK_APBBMASK_TC3_Pos)) +#endif +#ifdef MCLK_APBCMASK_TC2 +#define MCLK_TC2 (&MCLK->APBCMASK.reg) +#define MCLK_TC2_MASK ((1 << MCLK_APBCMASK_TC2_Pos) | (1 << MCLK_APBCMASK_TC3_Pos)) +#endif +#ifdef MCLK_APBDMASK_TC2 +#define MCLK_TC2 (&MCLK->APBDMASK.reg) +#define MCLK_TC2_MASK ((1 << MCLK_APBDMASK_TC2_Pos) | (1 << MCLK_APBDMASK_TC3_Pos)) +#endif + +#ifdef MCLK_APBAMASK_TC4 +#define MCLK_TC4 (&MCLK->APBAMASK.reg) +#define MCLK_TC4_MASK ((1 << MCLK_APBAMASK_TC4_Pos) | (1 << MCLK_APBAMASK_TC5_Pos)) +#endif +#ifdef MCLK_APBBMASK_TC4 +#define MCLK_TC4 (&MCLK->APBBMASK.reg) +#define MCLK_TC4_MASK ((1 << MCLK_APBBMASK_TC4_Pos) | (1 << MCLK_APBBMASK_TC5_Pos)) +#endif +#ifdef MCLK_APBCMASK_TC4 +#define MCLK_TC4 (&MCLK->APBCMASK.reg) +#define MCLK_TC4_MASK ((1 << MCLK_APBCMASK_TC4_Pos) | (1 << MCLK_APBCMASK_TC5_Pos)) +#endif +#ifdef MCLK_APBDMASK_TC4 +#define MCLK_TC4 (&MCLK->APBDMASK.reg) +#define MCLK_TC4_MASK ((1 << MCLK_APBDMASK_TC4_Pos) | (1 << MCLK_APBDMASK_TC5_Pos)) +#endif + +#ifdef MCLK_APBAMASK_TC6 +#define MCLK_TC6 (&MCLK->APBAMASK.reg) +#define MCLK_TC6_MASK ((1 << MCLK_APBAMASK_TC6_Pos) | (1 << MCLK_APBAMASK_TC7_Pos)) +#endif +#ifdef MCLK_APBBMASK_TC6 +#define MCLK_TC6 (&MCLK->APBBMASK.reg) +#define MCLK_TC6_MASK ((1 << MCLK_APBBMASK_TC6_Pos) | (1 << MCLK_APBBMASK_TC7_Pos)) +#endif +#ifdef MCLK_APBCMASK_TC6 +#define MCLK_TC6 (&MCLK->APBCMASK.reg) +#define MCLK_TC6_MASK ((1 << MCLK_APBCMASK_TC6_Pos) | (1 << MCLK_APBCMASK_TC7_Pos)) +#endif +#ifdef MCLK_APBDMASK_TC6 +#define MCLK_TC6 (&MCLK->APBDMASK.reg) +#define MCLK_TC6_MASK ((1 << MCLK_APBDMASK_TC6_Pos) | (1 << MCLK_APBDMASK_TC7_Pos)) +#endif