Intel® Quark™ Microcontroller Software Interface  1.4.0
Intel® Quark™ Microcontroller BSP
qm_rtc.c
1 /*
2  * {% copyright %}
3  */
4 
5 #include "qm_rtc.h"
6 #include "clk.h"
7 #if (HAS_SOC_CONTEXT_RETENTION)
8 #include "power_states.h"
9 #endif /* HAS_SOC_CONTEXT_RETENTION */
10 
11 static void (*callback[QM_RTC_NUM])(void *data);
12 static void *callback_data[QM_RTC_NUM];
13 
14 #ifndef UNIT_TEST
15 qm_rtc_reg_t *qm_rtc[QM_RTC_NUM] = {(qm_rtc_reg_t *)(QM_RTC_BASE)};
16 #endif /* UNIT_TEST */
17 
18 QM_ISR_DECLARE(qm_rtc_0_isr)
19 {
20  /* Disable RTC interrupt */
21  QM_RTC[QM_RTC_0]->rtc_ccr &= ~QM_RTC_CCR_INTERRUPT_ENABLE;
22 
23 #if (HAS_SOC_CONTEXT_RETENTION)
24  if (QM_SCSS_GP->gps0 & QM_GPS0_POWER_STATES_MASK) {
26  }
27 #endif /* HAS_SOC_CONTEXT_RETENTION */
28  if (callback[QM_RTC_0]) {
29  (callback[QM_RTC_0])(callback_data[QM_RTC_0]);
30  }
31 
32  /* Clear interrupt. */
33  QM_RTC[QM_RTC_0]->rtc_eoi;
34  QM_ISR_EOI(QM_IRQ_RTC_0_INT_VECTOR);
35 }
36 
37 int qm_rtc_set_config(const qm_rtc_t rtc, const qm_rtc_config_t *const cfg)
38 {
39  QM_CHECK(rtc < QM_RTC_NUM, -EINVAL);
40  QM_CHECK(rtc >= QM_RTC_0, -EINVAL);
41  QM_CHECK(NULL != cfg, -EINVAL);
42 
43  /* Disable the RTC before re-configuration. */
44  QM_RTC[rtc]->rtc_ccr &= ~QM_RTC_CCR_ENABLE;
45 
46  QM_RTC[rtc]->rtc_clr = cfg->init_val;
47 
48  /* Clear any pending interrupts. */
49  QM_RTC[rtc]->rtc_eoi;
50 
51 /* Perform if the IP used has the prescaler feature. */
52 #if (HAS_RTC_PRESCALER)
53  /* With the RTC prescaler, the minimum value that can be set is 2. */
54  if (QM_RTC_MIN_PRESCALER <= cfg->prescaler) {
55  /* Enable RTC prescaler in CCR. */
56  QM_RTC[rtc]->rtc_ccr |= QM_RTC_PRESCLR_ENABLE;
57  QM_RTC[rtc]->rtc_cpsr = BIT(cfg->prescaler);
58  } else {
59  /* Disable RTC prescaler in CCR. */
60  QM_RTC[rtc]->rtc_ccr &= ~QM_RTC_PRESCLR_ENABLE;
61  }
62 #else /* HAS_RTC_PRESCALER */
63  clk_rtc_set_div(cfg->prescaler); /* Set RTC divider. */
64 #endif /* HAS_RTC_PRESCALER */
65 
66  if (cfg->alarm_en) {
67  callback[rtc] = cfg->callback;
68  callback_data[rtc] = cfg->callback_data;
69  qm_rtc_set_alarm(rtc, cfg->alarm_val);
70  } else {
71  callback[rtc] = NULL;
72  callback_data[rtc] = NULL;
73  /* Disable RTC interrupt. */
74  QM_RTC[rtc]->rtc_ccr &= ~QM_RTC_CCR_INTERRUPT_ENABLE;
75  /* Internally mask the RTC interrupt. */
76  QM_RTC[rtc]->rtc_ccr |= QM_RTC_CCR_INTERRUPT_MASK;
77  }
78 
79  /* Enable the RTC upon completion. */
80  QM_RTC[rtc]->rtc_ccr |= QM_RTC_CCR_ENABLE;
81 
82  return 0;
83 }
84 
85 int qm_rtc_set_alarm(const qm_rtc_t rtc, const uint32_t alarm_val)
86 {
87  QM_CHECK(rtc < QM_RTC_NUM, -EINVAL);
88  QM_CHECK(rtc >= QM_RTC_0, -EINVAL);
89 
90  /* Enable RTC interrupt. */
91  QM_RTC[rtc]->rtc_ccr |= QM_RTC_CCR_INTERRUPT_ENABLE;
92  /* Internally unmask the RTC interrupt. */
93  QM_RTC[rtc]->rtc_ccr &= ~QM_RTC_CCR_INTERRUPT_MASK;
94 
95  /* Set alarm value. */
96  QM_RTC[rtc]->rtc_cmr = alarm_val;
97 
98  return 0;
99 }
100 
101 int qm_rtc_read(const qm_rtc_t rtc, uint32_t *const value)
102 {
103  QM_CHECK(rtc < QM_RTC_NUM, -EINVAL);
104  QM_CHECK(rtc >= QM_RTC_0, -EINVAL);
105  QM_CHECK(NULL != value, -EINVAL);
106 
107  *value = QM_RTC[rtc]->rtc_ccvr;
108 
109  return 0;
110 }
111 
112 #if (ENABLE_RESTORE_CONTEXT)
113 int qm_rtc_save_context(const qm_rtc_t rtc, qm_rtc_context_t *const ctx)
114 {
115  QM_CHECK(rtc < QM_RTC_NUM, -EINVAL);
116  QM_CHECK(ctx != NULL, -EINVAL);
117 
118  (void)rtc;
119  (void)ctx;
120 
121  return 0;
122 }
123 
125  const qm_rtc_context_t *const ctx)
126 {
127  uint32_t int_rtc_mask;
128  QM_CHECK(rtc < QM_RTC_NUM, -EINVAL);
129  QM_CHECK(ctx != NULL, -EINVAL);
130 
131  (void)rtc;
132  (void)ctx;
133 
134  /* The interrupt router registers are sticky and retain their
135  * values across warm resets, so we don't need to save them.
136  * But for wake capable peripherals, if their interrupts are
137  * configured to be edge sensitive, the wake event will be lost
138  * by the time the interrupt controller is reconfigured, while
139  * the interrupt is still pending. By masking and unmasking again
140  * the corresponding routing register, the interrupt is forwarded
141  * to the core and the ISR will be serviced as expected.
142  */
143  int_rtc_mask = QM_INTERRUPT_ROUTER->rtc_0_int_mask;
144  QM_INTERRUPT_ROUTER->rtc_0_int_mask = 0xFFFFFFFF;
145  QM_INTERRUPT_ROUTER->rtc_0_int_mask = int_rtc_mask;
146 
147  return 0;
148 }
149 #else
150 int qm_rtc_save_context(const qm_rtc_t rtc, qm_rtc_context_t *const ctx)
151 {
152  (void)rtc;
153  (void)ctx;
154 
155  return 0;
156 }
157 
159  const qm_rtc_context_t *const ctx)
160 {
161  (void)rtc;
162  (void)ctx;
163 
164  return 0;
165 }
166 #endif /* ENABLE_RESTORE_CONTEXT */
void qm_power_soc_restore(void)
Restore system state after sleep or deep sleep.
Definition: power_states.c:402
int qm_rtc_read(const qm_rtc_t rtc, uint32_t *const value)
Read the RTC register value.
Definition: qm_rtc.c:101
int clk_rtc_set_div(const clk_rtc_div_t div)
Change divider value of RTC.
Definition: clk.c:306
QM_ISR_DECLARE(qm_rtc_0_isr)
ISR for RTC 0 interrupt.
Definition: qm_rtc.c:18
void * callback_data
Callback user data.
Definition: qm_rtc.h:58
uint32_t alarm_val
Alarm value in RTC clocks.
Definition: qm_rtc.h:42
int qm_rtc_set_alarm(const qm_rtc_t rtc, const uint32_t alarm_val)
Set Alarm value.
Definition: qm_rtc.c:85
int qm_rtc_restore_context(const qm_rtc_t rtc, const qm_rtc_context_t *const ctx)
Restore RTC context.
Definition: qm_rtc.c:124
clk_rtc_div_t prescaler
RTC Clock prescaler.
Definition: qm_rtc.h:50
uint32_t init_val
Initial value in RTC clocks.
Definition: qm_rtc.h:40
RTC register map.
Definition: qm_soc_regs.h:821
qm_rtc_t
Number of RTC controllers.
Definition: qm_soc_regs.h:818
int qm_rtc_set_config(const qm_rtc_t rtc, const qm_rtc_config_t *const cfg)
Set RTC configuration.
Definition: qm_rtc.c:37
bool alarm_en
Alarm enable.
Definition: qm_rtc.h:41
int qm_rtc_save_context(const qm_rtc_t rtc, qm_rtc_context_t *const ctx)
Save RTC context.
Definition: qm_rtc.c:113
void(* callback)(void *data)
User callback.
Definition: qm_rtc.h:57
QM RTC configuration type.
Definition: qm_rtc.h:39