@@ -66,11 +66,28 @@ static rtc_state_t alarm_cb;
6666static rtc_state_t overflow_cb ;
6767
6868#if IS_ACTIVE (MODULE_PM_LAYERED ) && defined(SAM0_RTCRTT_PM_BLOCK )
69- /* This flag keeps track of the RTC/RTT being activated by this driver.
70- * The peripheral is clocked by default! We can't take this enable bit
71- * as an indicator whether pm_block() has been called in the past.
72- */
73- static bool rtx_is_active = false;
69+ static bool _pm_alarm = false;
70+ static bool _pm_overflow = false;
71+
72+ static inline void _pm_block (bool * flag )
73+ {
74+ if (!* flag ) {
75+ pm_block (SAM0_RTCRTT_PM_BLOCK );
76+ * flag = true;
77+ }
78+ }
79+
80+ static inline void _pm_unblock (bool * flag )
81+ {
82+ if (* flag ) {
83+ pm_unblock (SAM0_RTCRTT_PM_BLOCK );
84+ * flag = false;
85+ }
86+ }
87+ #else
88+ /* Use empty stubs if pm is disabled */
89+ #define _pm_block (x )
90+ #define _pm_unblock (x )
7491#endif
7592
7693/* At 1Hz, RTC goes till 63 years (2^5, see 17.8.22 in datasheet)
@@ -108,13 +125,6 @@ static void _read_req(void)
108125
109126static void _poweron (void )
110127{
111- #if IS_ACTIVE (MODULE_PM_LAYERED ) && defined(SAM0_RTCRTT_PM_BLOCK )
112- if (!rtx_is_active ) {
113- pm_block (SAM0_RTCRTT_PM_BLOCK );
114- rtx_is_active = true;
115- }
116- #endif
117-
118128#ifdef MCLK
119129 MCLK -> APBAMASK .reg |= MCLK_APBAMASK_RTC ;
120130#else
@@ -140,13 +150,6 @@ static void _poweroff(void)
140150#else
141151 PM -> APBAMASK .reg &= ~PM_APBAMASK_RTC ;
142152#endif
143-
144- #if IS_ACTIVE (MODULE_PM_LAYERED ) && defined(SAM0_RTCRTT_PM_BLOCK )
145- if (rtx_is_active ) {
146- pm_unblock (SAM0_RTCRTT_PM_BLOCK );
147- rtx_is_active = false;
148- }
149- #endif
150153}
151154
152155static inline void _rtc_set_enabled (bool on )
@@ -334,6 +337,9 @@ static void _rtc_init(void)
334337
335338void rtc_init (void )
336339{
340+ /* clear previously set pm mode blockers */
341+ _pm_unblock (& _pm_alarm );
342+
337343 _poweroff ();
338344 _rtc_clock_setup ();
339345 _poweron ();
@@ -345,6 +351,7 @@ void rtc_init(void)
345351
346352 /* enable overflow interrupt */
347353 RTC -> MODE2 .INTENSET .reg = RTC_MODE2_INTENSET_OVF ;
354+ _pm_block (& _pm_overflow );
348355
349356 /* Clear interrupt flags */
350357 RTC -> MODE2 .INTFLAG .reg = RTC_MODE2_INTFLAG_OVF
@@ -359,6 +366,9 @@ void rtc_init(void)
359366#ifdef MODULE_PERIPH_RTT
360367void rtt_init (void )
361368{
369+ /* clear previously set pm mode blockers */
370+ _pm_unblock (& _pm_alarm );
371+ _pm_unblock (& _pm_overflow );
362372
363373 _rtt_clock_setup ();
364374 _poweron ();
@@ -606,6 +616,11 @@ int rtc_set_alarm(struct tm *time, rtc_alarm_cb_t cb, void *arg)
606616 RTC -> MODE2 .INTFLAG .reg = RTC_MODE2_INTFLAG_ALARM0 ;
607617 RTC -> MODE2 .INTENSET .reg = RTC_MODE2_INTENSET_ALARM0 ;
608618
619+ /* block power mode if callback function is present */
620+ if (alarm_cb .cb ) {
621+ _pm_block (& _pm_alarm );
622+ }
623+
609624 return 0 ;
610625}
611626
@@ -635,6 +650,8 @@ void rtc_clear_alarm(void)
635650{
636651 /* disable alarm interrupt */
637652 RTC -> MODE2 .INTENCLR .reg = RTC_MODE2_INTENCLR_ALARM0 ;
653+
654+ _pm_unblock (& _pm_alarm );
638655}
639656
640657void rtc_poweron (void )
@@ -660,11 +677,18 @@ void rtt_set_overflow_cb(rtt_cb_t cb, void *arg)
660677
661678 /* enable overflow interrupt */
662679 RTC -> MODE0 .INTENSET .reg = RTC_MODE0_INTENSET_OVF ;
680+
681+ /* block power mode if callback function is present */
682+ if (overflow_cb .cb ) {
683+ _pm_block (& _pm_overflow );
684+ }
663685}
664686void rtt_clear_overflow_cb (void )
665687{
666688 /* disable overflow interrupt */
667689 RTC -> MODE0 .INTENCLR .reg = RTC_MODE0_INTENCLR_OVF ;
690+
691+ _pm_unblock (& _pm_overflow );
668692}
669693
670694uint32_t rtt_get_counter (void )
@@ -701,12 +725,19 @@ void rtt_set_alarm(uint32_t alarm, rtt_cb_t cb, void *arg)
701725 /* enable compare interrupt and clear flag */
702726 RTC -> MODE0 .INTFLAG .reg = RTC_MODE0_INTFLAG_CMP0 ;
703727 RTC -> MODE0 .INTENSET .reg = RTC_MODE0_INTENSET_CMP0 ;
728+
729+ /* block power mode if callback function is present */
730+ if (alarm_cb .cb ) {
731+ _pm_block (& _pm_alarm );
732+ }
704733}
705734
706735void rtt_clear_alarm (void )
707736{
708737 /* disable compare interrupt */
709738 RTC -> MODE0 .INTENCLR .reg = RTC_MODE0_INTENCLR_CMP0 ;
739+
740+ _pm_unblock (& _pm_alarm );
710741}
711742
712743void rtt_poweron (void )
@@ -761,6 +792,7 @@ static void _isr_rtt(void)
761792 /* disable interrupt */
762793 RTC -> MODE0 .INTENCLR .reg = RTC_MODE0_INTENCLR_CMP0 ;
763794 if (alarm_cb .cb ) {
795+ _pm_unblock (& _pm_alarm );
764796 alarm_cb .cb (alarm_cb .arg );
765797 }
766798 }
0 commit comments