blob: 1a3cc8829fb9ef107e3a0db905078064d5bd5c25 [file] [log] [blame]
Harald Welted1bd5c42019-05-17 16:38:30 +02001
2/**
3 * \file
4 *
5 * \brief RTC Driver
6 *
7 * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
8 *
9 * \asf_license_start
10 *
11 * \page License
12 *
13 * Subject to your compliance with these terms, you may use Microchip
14 * software and any derivatives exclusively with Microchip products.
15 * It is your responsibility to comply with third party license terms applicable
16 * to your use of third party software (including open source software) that
17 * may accompany Microchip software.
18 *
19 * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
20 * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
21 * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
22 * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
23 * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
24 * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
25 * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
26 * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
27 * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
28 * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
29 * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
30 *
31 * \asf_license_stop
32 *
33 */
34
35#include <hpl_calendar.h>
36#include <utils_assert.h>
37#include <hpl_rtc_config.h>
38
39/*!< Pointer to hpl device */
40static struct calendar_dev *_rtc_dev = NULL;
41
42/**
43 * \brief Initializes the RTC module with given configurations.
44 */
45int32_t _calendar_init(struct calendar_dev *const dev)
46{
47 ASSERT(dev && dev->hw);
48
49 _rtc_dev = dev;
50
51 hri_rtcmode0_wait_for_sync(dev->hw, RTC_MODE0_SYNCBUSY_SWRST);
52 if (hri_rtcmode0_get_CTRLA_ENABLE_bit(dev->hw)) {
53#if !CONF_RTC_INIT_RESET
54 return ERR_DENIED;
55#else
56 hri_rtcmode0_clear_CTRLA_ENABLE_bit(dev->hw);
57 hri_rtcmode0_wait_for_sync(dev->hw, RTC_MODE0_SYNCBUSY_ENABLE);
58#endif
59 }
60 hri_rtcmode0_set_CTRLA_SWRST_bit(dev->hw);
61 hri_rtcmode0_wait_for_sync(dev->hw, RTC_MODE0_SYNCBUSY_SWRST);
62
63#if CONF_RTC_EVENT_CONTROL_ENABLE == 1
64 hri_rtcmode0_write_EVCTRL_reg(
65 dev->hw,
66 (CONF_RTC_PEREO0 << RTC_MODE0_EVCTRL_PEREO0_Pos) | (CONF_RTC_PEREO1 << RTC_MODE0_EVCTRL_PEREO1_Pos)
67 | (CONF_RTC_PEREO2 << RTC_MODE0_EVCTRL_PEREO2_Pos) | (CONF_RTC_PEREO3 << RTC_MODE0_EVCTRL_PEREO3_Pos)
68 | (CONF_RTC_PEREO4 << RTC_MODE0_EVCTRL_PEREO4_Pos) | (CONF_RTC_PEREO5 << RTC_MODE0_EVCTRL_PEREO5_Pos)
69 | (CONF_RTC_PEREO6 << RTC_MODE0_EVCTRL_PEREO6_Pos) | (CONF_RTC_PEREO7 << RTC_MODE0_EVCTRL_PEREO7_Pos)
70 | (CONF_RTC_COMPE0 << RTC_MODE0_EVCTRL_CMPEO_Pos) | (CONF_RTC_COMPE1 << RTC_MODE0_EVCTRL_CMPEO1_Pos)
71 | (CONF_RTC_TAMPEREO << RTC_MODE0_EVCTRL_TAMPEREO_Pos)
72 | (CONF_RTC_TAMPEVEI << RTC_MODE0_EVCTRL_TAMPEVEI_Pos) | (CONF_RTC_OVFEO << RTC_MODE0_EVCTRL_OVFEO_Pos));
73#endif
74
75 hri_rtcmode0_write_CTRLA_reg(dev->hw, RTC_MODE0_CTRLA_PRESCALER(CONF_RTC_PRESCALER) | RTC_MODE0_CTRLA_COUNTSYNC);
76
77 hri_rtc_write_TAMPCTRL_reg(
78 dev->hw,
79 (CONF_RTC_TAMPER_INACT_0 << RTC_TAMPCTRL_IN0ACT_Pos) | (CONF_RTC_TAMPER_INACT_1 << RTC_TAMPCTRL_IN1ACT_Pos)
80 | (CONF_RTC_TAMPER_INACT_2 << RTC_TAMPCTRL_IN2ACT_Pos)
81 | (CONF_RTC_TAMPER_INACT_3 << RTC_TAMPCTRL_IN3ACT_Pos)
82 | (CONF_RTC_TAMPER_INACT_4 << RTC_TAMPCTRL_IN4ACT_Pos) | (CONF_RTC_TAMP_LVL_0 << RTC_TAMPCTRL_TAMLVL0_Pos)
83 | (CONF_RTC_TAMP_LVL_1 << RTC_TAMPCTRL_TAMLVL1_Pos) | (CONF_RTC_TAMP_LVL_2 << RTC_TAMPCTRL_TAMLVL2_Pos)
84 | (CONF_RTC_TAMP_LVL_3 << RTC_TAMPCTRL_TAMLVL3_Pos) | (CONF_RTC_TAMP_LVL_4 << RTC_TAMPCTRL_TAMLVL4_Pos)
85 | (CONF_RTC_TAMP_DEBNC_0 << RTC_TAMPCTRL_DEBNC0_Pos) | (CONF_RTC_TAMP_DEBNC_1 << RTC_TAMPCTRL_DEBNC1_Pos)
86 | (CONF_RTC_TAMP_DEBNC_2 << RTC_TAMPCTRL_DEBNC2_Pos) | (CONF_RTC_TAMP_DEBNC_3 << RTC_TAMPCTRL_DEBNC3_Pos)
87 | (CONF_RTC_TAMP_DEBNC_4 << RTC_TAMPCTRL_DEBNC4_Pos));
88
89 if ((CONF_RTC_TAMPER_INACT_0 == TAMPER_MODE_ACTL) | (CONF_RTC_TAMPER_INACT_1 == TAMPER_MODE_ACTL)
90 | (CONF_RTC_TAMPER_INACT_2 == TAMPER_MODE_ACTL) | (CONF_RTC_TAMPER_INACT_3 == TAMPER_MODE_ACTL)
91 | (CONF_RTC_TAMPER_INACT_4 == TAMPER_MODE_ACTL)) {
92 hri_rtcmode0_set_CTRLB_RTCOUT_bit(dev->hw);
93 }
94 return ERR_NONE;
95}
96
97/**
98 * \brief Deinit the RTC module
99 */
100int32_t _calendar_deinit(struct calendar_dev *const dev)
101{
102 ASSERT(dev && dev->hw);
103
104 NVIC_DisableIRQ(RTC_IRQn);
105 dev->callback = NULL;
106
107 hri_rtcmode0_clear_CTRLA_ENABLE_bit(dev->hw);
108 hri_rtcmode0_set_CTRLA_SWRST_bit(dev->hw);
109
110 return ERR_NONE;
111}
112
113/**
114 * \brief Enable the RTC module
115 */
116int32_t _calendar_enable(struct calendar_dev *const dev)
117{
118 ASSERT(dev && dev->hw);
119
120 hri_rtcmode0_set_CTRLA_ENABLE_bit(dev->hw);
121
122 return ERR_NONE;
123}
124
125/**
126 * \brief Disable the RTC module
127 */
128int32_t _calendar_disable(struct calendar_dev *const dev)
129{
130 ASSERT(dev && dev->hw);
131
132 hri_rtcmode0_clear_CTRLA_ENABLE_bit(dev->hw);
133
134 return ERR_NONE;
135}
136
137/**
138 * \brief Set the current calendar time to desired time.
139 */
140int32_t _calendar_set_counter(struct calendar_dev *const dev, const uint32_t counter)
141{
142 ASSERT(dev && dev->hw);
143
144 hri_rtcmode0_write_COUNT_reg(dev->hw, counter);
145
146 return ERR_NONE;
147}
148
149/**
150 * \brief Get current counter
151 */
152uint32_t _calendar_get_counter(struct calendar_dev *const dev)
153{
154 ASSERT(dev && dev->hw);
155
156 return hri_rtcmode0_read_COUNT_reg(dev->hw);
157}
158
159/**
160 * \brief Set the compare for the specified value.
161 */
162int32_t _calendar_set_comp(struct calendar_dev *const dev, const uint32_t comp)
163{
164 ASSERT(dev && dev->hw);
165
166 hri_rtcmode0_write_COMP_reg(dev->hw, 0, comp);
167
168 return ERR_NONE;
169}
170
171/**
172 * \brief Get the compare value
173 */
174uint32_t _calendar_get_comp(struct calendar_dev *const dev)
175{
176 ASSERT(dev && dev->hw);
177
178 return hri_rtcmode0_read_COMP_reg(dev->hw, 0);
179}
180
181/**
182 * \brief Find tamper is detected on specified pin
183 */
184bool _is_tamper_detected(struct calendar_dev *const dev, enum tamper_id tamper_id_pin)
185{
186 bool value;
187
188 ASSERT(dev && dev->hw);
189
190 value = ((hri_rtc_read_TAMPID_reg(dev->hw) >> tamper_id_pin) & 0x01);
191 return value;
192}
193
194/**
195 * \brief Clear the Tamper ID flag
196 */
197int32_t _tamper_clear_tampid_flag(struct calendar_dev *const dev, enum tamper_id tamper_id_pin)
198{
199 ASSERT(dev && dev->hw);
200
201 hri_rtc_write_TAMPID_reg(dev->hw, (true << tamper_id_pin));
202
203 return ERR_NONE;
204}
205
206/**
207 * \brief Enable Tamper Debounce Asynchronous Feature
208 */
209int32_t _tamper_enable_debounce_asynchronous(struct calendar_dev *const dev)
210{
211 int32_t return_value;
212
213 hri_rtcmode0_write_CTRLA_ENABLE_bit(dev->hw, false);
214
215 while (hri_rtcmode0_read_SYNCBUSY_reg(dev->hw) & RTC_MODE2_CTRLA_ENABLE) {
216 }
217
218 if (hri_rtcmode0_read_CTRLA_reg(dev->hw) & RTC_MODE2_CTRLA_ENABLE) {
219 return_value = ERR_FAILURE;
220 } else {
221 hri_rtcmode0_write_CTRLB_DEBASYNC_bit(dev->hw, true);
222 return_value = ERR_NONE;
223 while (hri_rtcmode0_read_SYNCBUSY_reg(dev->hw) & RTC_MODE2_CTRLA_ENABLE) {
224 }
225 hri_rtcmode0_write_CTRLA_ENABLE_bit(dev->hw, true);
226 }
227
228 return return_value;
229}
230
231/**
232 * \brief Disable Tamper Debounce Asynchronous Feature
233 */
234int32_t _tamper_disable_debounce_asynchronous(struct calendar_dev *const dev)
235{
236 int32_t return_value;
237
238 hri_rtcmode0_write_CTRLA_ENABLE_bit(dev->hw, false);
239
240 while (hri_rtcmode0_read_SYNCBUSY_reg(dev->hw) & RTC_MODE2_CTRLA_ENABLE) {
241 }
242
243 if (hri_rtcmode0_read_CTRLA_reg(dev->hw) & RTC_MODE2_CTRLA_ENABLE) {
244 return_value = ERR_FAILURE;
245 } else {
246 hri_rtcmode0_write_CTRLB_DEBASYNC_bit(dev->hw, false);
247 return_value = ERR_NONE;
248 while (hri_rtcmode0_read_SYNCBUSY_reg(dev->hw) & RTC_MODE2_CTRLA_ENABLE) {
249 }
250 hri_rtcmode0_write_CTRLA_ENABLE_bit(dev->hw, true);
251 }
252
253 return return_value;
254}
255
256/**
257 * \brief Enable Tamper Debounce Majority Feature
258 */
259int32_t _tamper_enable_debounce_majority(struct calendar_dev *const dev)
260{
261 int32_t return_value;
262
263 hri_rtcmode0_write_CTRLA_ENABLE_bit(dev->hw, false);
264
265 while (hri_rtcmode0_read_SYNCBUSY_reg(dev->hw) & RTC_MODE2_CTRLA_ENABLE) {
266 }
267
268 if (hri_rtcmode0_read_CTRLA_reg(dev->hw) & RTC_MODE2_CTRLA_ENABLE) {
269 return_value = ERR_FAILURE;
270 } else {
271 hri_rtcmode0_write_CTRLB_DEBMAJ_bit(dev->hw, true);
272 return_value = ERR_NONE;
273
274 while (hri_rtcmode0_read_SYNCBUSY_reg(dev->hw) & RTC_MODE2_CTRLA_ENABLE) {
275 }
276 hri_rtcmode0_write_CTRLA_ENABLE_bit(dev->hw, true);
277 }
278
279 return return_value;
280}
281
282/**
283 * \brief Disable Tamper Debounce Majority Feature
284 */
285int32_t _tamper_disable_debounce_majority(struct calendar_dev *const dev)
286{
287 int32_t return_value;
288
289 hri_rtcmode0_write_CTRLA_ENABLE_bit(dev->hw, false);
290
291 while (hri_rtcmode0_read_SYNCBUSY_reg(dev->hw) & RTC_MODE2_CTRLA_ENABLE) {
292 }
293
294 if (hri_rtcmode0_read_CTRLA_reg(dev->hw) & RTC_MODE2_CTRLA_ENABLE) {
295 return_value = ERR_FAILURE;
296 } else {
297 hri_rtcmode0_write_CTRLB_DEBMAJ_bit(dev->hw, false);
298 return_value = ERR_NONE;
299
300 while (hri_rtcmode0_read_SYNCBUSY_reg(dev->hw) & RTC_MODE2_CTRLA_ENABLE) {
301 }
302 hri_rtcmode0_write_CTRLA_ENABLE_bit(dev->hw, true);
303 }
304
305 return return_value;
306}
307
308int32_t _tamper_register_callback(struct calendar_dev *const dev, tamper_drv_cb_t callback_tamper)
309{
310 ASSERT(dev && dev->hw);
311
312 /* Check callback */
313 if (callback_tamper != NULL) {
314 /* register the callback */
315 dev->callback_tamper = callback_tamper;
316
317 /* enable RTC_IRQn */
318 NVIC_ClearPendingIRQ(RTC_IRQn);
319 NVIC_EnableIRQ(RTC_IRQn);
320
321 /* enable tamper interrupt */
322 hri_rtcmode0_set_INTEN_TAMPER_bit(dev->hw);
323 } else {
324 /* disable tamper interrupt */
325 hri_rtcmode0_clear_INTEN_TAMPER_bit(dev->hw);
326
327 /* disable RTC_IRQn */
328 NVIC_DisableIRQ(RTC_IRQn);
329 }
330
331 return ERR_NONE;
332}
333/**
334 * \brief Registers callback for the specified callback type
335 */
336int32_t _calendar_register_callback(struct calendar_dev *const dev, calendar_drv_cb_alarm_t callback)
337{
338 ASSERT(dev && dev->hw);
339
340 /* Check callback */
341 if (callback != NULL) {
342 /* register the callback */
343 dev->callback = callback;
344
345 /* enable RTC_IRQn */
346 NVIC_ClearPendingIRQ(RTC_IRQn);
347 NVIC_EnableIRQ(RTC_IRQn);
348
349 /* enable cmp */
350 hri_rtcmode0_set_INTEN_CMP0_bit(dev->hw);
351 } else {
352 /* disable cmp */
353 hri_rtcmode0_clear_INTEN_CMP0_bit(dev->hw);
354
355 /* disable RTC_IRQn */
356 NVIC_DisableIRQ(RTC_IRQn);
357 }
358
359 return ERR_NONE;
360}
361
362/**
363 * \brief RTC interrupt handler
364 *
365 * \param[in] dev The pointer to calendar device struct
366 */
367static void _rtc_interrupt_handler(struct calendar_dev *dev)
368{
369 /* Read and mask interrupt flag register */
370 uint16_t interrupt_status = hri_rtcmode0_read_INTFLAG_reg(dev->hw);
371 uint16_t interrupt_enabled = hri_rtcmode0_read_INTEN_reg(dev->hw);
372
373 if ((interrupt_status & interrupt_enabled) & RTC_MODE2_INTFLAG_ALARM0) {
374 dev->callback(dev);
375
376 /* Clear interrupt flag */
377 hri_rtcmode0_clear_interrupt_CMP0_bit(dev->hw);
378 } else if ((interrupt_status & interrupt_enabled) & RTC_MODE2_INTFLAG_TAMPER) {
379 dev->callback_tamper(dev);
380
381 /* Clear interrupt flag */
382 hri_rtcmode0_clear_interrupt_TAMPER_bit(dev->hw);
383 }
384}
385/**
386 * \brief Set calendar IRQ
387 */
388void _calendar_set_irq(struct calendar_dev *const dev)
389{
390 (void)dev;
391 NVIC_SetPendingIRQ(RTC_IRQn);
392}
393
394/**
395 * \brief Rtc interrupt handler
396 */
397void RTC_Handler(void)
398{
399 _rtc_interrupt_handler(_rtc_dev);
400}