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 <benpicco@googlemail.com>
This commit is contained in:
Benjamin Valentin 2019-03-15 23:39:57 +01:00 committed by Anas Nashif
parent 41713244b3
commit cd0873015a
2 changed files with 124 additions and 4 deletions

View file

@ -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);

View file

@ -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