summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2017-01-26 21:08:55 -0500
committerMichael Sevakis <jethead71@rockbox.org>2017-11-21 07:52:02 -0500
commitf4c42213062170ddfcc706b3c5ed19f47517c253 (patch)
tree65f8058970e97d939660cf1e39f844a06df66f84
parent12bc24adbf919dc945928b2dcda74d51d33708f7 (diff)
downloadrockbox-f4c42213062170ddfcc706b3c5ed19f47517c253.tar.gz
rockbox-f4c42213062170ddfcc706b3c5ed19f47517c253.zip
Convert i.MX31 and AMS target to use RTC interrupt
Instead of checking ticks, set a sticky dirty flag that indicates that the RTC needs to be read. This gives a timely update and more accurate readout without actually reading the RTC until it changes. The implementation should atomically read the flag and clear it. Setting the flag would typically happen in an RTC tick ISR. Change-Id: I6fd325f22845029a485c502c884812d3676026ea
-rw-r--r--firmware/common/timefuncs.c45
-rw-r--r--firmware/drivers/rtc/rtc_mc13783.c13
-rw-r--r--firmware/export/config.h10
-rw-r--r--firmware/target/arm/as3525/ascodec-as3525.c35
-rw-r--r--firmware/target/arm/as3525/rtc-target.h27
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/mc13783-target.h4
-rw-r--r--firmware/target/arm/imx31/rtc-target.h27
7 files changed, 140 insertions, 21 deletions
diff --git a/firmware/common/timefuncs.c b/firmware/common/timefuncs.c
index c8819ea76e..50addad27a 100644
--- a/firmware/common/timefuncs.c
+++ b/firmware/common/timefuncs.c
@@ -24,13 +24,21 @@
24 24
25#include "kernel.h" 25#include "kernel.h"
26#include "rtc.h" 26#include "rtc.h"
27#ifdef HAVE_RTC_IRQ
28#include "rtc-target.h"
29#endif
27#include "timefuncs.h" 30#include "timefuncs.h"
28#include "debug.h" 31#include "debug.h"
29 32
30static struct tm tm; 33static struct tm tm;
31 34
32#if !CONFIG_RTC 35#if !CONFIG_RTC
33static void fill_default_tm(struct tm *tm) 36static inline bool rtc_dirty(void)
37{
38 return true;
39}
40
41static inline int rtc_read_datetime(struct tm *tm)
34{ 42{
35 tm->tm_sec = 0; 43 tm->tm_sec = 0;
36 tm->tm_min = 0; 44 tm->tm_min = 0;
@@ -38,9 +46,9 @@ static void fill_default_tm(struct tm *tm)
38 tm->tm_mday = 1; 46 tm->tm_mday = 1;
39 tm->tm_mon = 0; 47 tm->tm_mon = 0;
40 tm->tm_year = 70; 48 tm->tm_year = 70;
41 tm->tm_wday = 1; 49 tm->tm_wday = 4;
42 tm->tm_yday = 0; /* Not implemented for now */ 50 tm->tm_yday = 0;
43 tm->tm_isdst = -1; /* Not implemented for now */ 51 return 1;
44} 52}
45#endif /* !CONFIG_RTC */ 53#endif /* !CONFIG_RTC */
46 54
@@ -58,24 +66,37 @@ bool valid_time(const struct tm *tm)
58 else 66 else
59 return true; 67 return true;
60} 68}
61#endif /* CONFIG_RTC */
62 69
63struct tm *get_time(void) 70/* Don't read the RTC more than once per second
71 * returns true if the rtc needs to be read
72 * targets may override with their own implementation
73 */
74#ifndef HAVE_RTC_IRQ
75static inline bool rtc_dirty(void)
64{ 76{
65#if CONFIG_RTC
66 static long timeout = 0; 77 static long timeout = 0;
67 78
68 /* Don't read the RTC more than once per second */ 79 /* Don't read the RTC more than once per second */
69 if (TIME_AFTER(current_tick, timeout)) 80 if (TIME_AFTER(current_tick, timeout))
70 { 81 {
71 /* Once per second, 1/10th of a second off */ 82 /* Once per second, 1/5th of a second off */
72 timeout = HZ * (current_tick / HZ + 1) + HZ / 5; 83 timeout = current_tick / HZ * HZ + 6*HZ / 5;
84 return true;
85 }
86
87 return false;
88}
89#endif /* HAVE_RTC_IRQ */
90#endif /* CONFIG_RTC */
91
92struct tm *get_time(void)
93{
94 if (rtc_dirty())
95 {
73 rtc_read_datetime(&tm); 96 rtc_read_datetime(&tm);
74 tm.tm_isdst = -1; /* Not implemented for now */ 97 tm.tm_isdst = -1; /* Not implemented for now */
75 } 98 }
76#else /* No RTC */ 99
77 fill_default_tm(&tm);
78#endif /* RTC */
79 return &tm; 100 return &tm;
80} 101}
81 102
diff --git a/firmware/drivers/rtc/rtc_mc13783.c b/firmware/drivers/rtc/rtc_mc13783.c
index a1f78f738d..aedf5f6fa5 100644
--- a/firmware/drivers/rtc/rtc_mc13783.c
+++ b/firmware/drivers/rtc/rtc_mc13783.c
@@ -69,6 +69,7 @@ static const unsigned char rtc_registers[RTC_NUM_REGS_RD] =
69 69
70/* was it an alarm that triggered power on ? */ 70/* was it an alarm that triggered power on ? */
71static bool alarm_start = false; 71static bool alarm_start = false;
72static unsigned long rtc_is_dirty = 1; /* force a read right away */
72 73
73static const unsigned short month_table[13] = 74static const unsigned short month_table[13] =
74{ 75{
@@ -96,6 +97,16 @@ static bool read_time_and_day(uint32_t regs[RTC_NUM_REGS_RD])
96 return true; 97 return true;
97} 98}
98 99
100void MC13783_EVENT_CB_1HZ(void)
101{
102 rtc_is_dirty = 1;
103}
104
105bool rtc_mc13783_dirty(void)
106{
107 return bitclr32(&rtc_is_dirty, 1);
108}
109
99/** Public APIs **/ 110/** Public APIs **/
100void rtc_init(void) 111void rtc_init(void)
101{ 112{
@@ -105,6 +116,8 @@ void rtc_init(void)
105 alarm_start = true; 116 alarm_start = true;
106 mc13783_write(MC13783_INTERRUPT_STATUS1, MC13783_TODAI); 117 mc13783_write(MC13783_INTERRUPT_STATUS1, MC13783_TODAI);
107 } 118 }
119
120 mc13783_enable_event(MC13783_INT_ID_1HZ, true);
108} 121}
109 122
110int rtc_read_datetime(struct tm *tm) 123int rtc_read_datetime(struct tm *tm)
diff --git a/firmware/export/config.h b/firmware/export/config.h
index 475bd573d4..a4f0ea94fd 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -742,6 +742,16 @@ Lyre prototype 1 */
742#endif /* CONFIG_RDS */ 742#endif /* CONFIG_RDS */
743#endif /* HAVE_RDS_CAP */ 743#endif /* HAVE_RDS_CAP */
744 744
745#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
746#if CONFIG_RTC == RTC_AS3514
747#if CONFIG_CPU == AS3525 || CONFIG_CPU == AS3525v2
748#define HAVE_RTC_IRQ
749#endif
750#elif CONFIG_RTC == RTC_MC13783
751#define HAVE_RTC_IRQ
752#endif
753#endif /* (CONFIG_PLATFORM & PLATFORM_NATIVE) */
754
745#ifndef CONFIG_ORIENTATION 755#ifndef CONFIG_ORIENTATION
746#if LCD_HEIGHT > LCD_WIDTH 756#if LCD_HEIGHT > LCD_WIDTH
747#define CONFIG_ORIENTATION SCREEN_PORTRAIT 757#define CONFIG_ORIENTATION SCREEN_PORTRAIT
diff --git a/firmware/target/arm/as3525/ascodec-as3525.c b/firmware/target/arm/as3525/ascodec-as3525.c
index 1bd07c57b1..a8ad9706f8 100644
--- a/firmware/target/arm/as3525/ascodec-as3525.c
+++ b/firmware/target/arm/as3525/ascodec-as3525.c
@@ -131,6 +131,16 @@ static unsigned long ascodec_enrd0_shadow = 0;
131 131
132static void ascodec_wait_cb(struct ascodec_request *req); 132static void ascodec_wait_cb(struct ascodec_request *req);
133 133
134/* RTC interrupt and status
135 * Caution: To avoid an extra variable, IRQ_RTC is used as a flag for
136 * ascodec_enrd0_shadow, which conflicts with RVDD_WASLOW, but we're not using
137 * that right now */
138#if CONFIG_RTC
139#define IFRTC_IRQ_RTC IRQ_RTC
140#else /* !CONFIG_RTC */
141#define IFRTC_IRQ_RTC 0
142#endif /* CONFIG_RTC */
143
134/** --debugging help-- **/ 144/** --debugging help-- **/
135 145
136#ifdef DEBUG 146#ifdef DEBUG
@@ -149,7 +159,6 @@ static struct int_audio_counters {
149 159
150#define COUNT_INT(x) IFDEBUG((int_audio_counters.int_##x)++) 160#define COUNT_INT(x) IFDEBUG((int_audio_counters.int_##x)++)
151 161
152
153/** --stock request and callback functionality -- **/ 162/** --stock request and callback functionality -- **/
154 163
155/* init for common request data (call before submitting) */ 164/* init for common request data (call before submitting) */
@@ -510,13 +519,12 @@ static void ascodec_int_audio_cb(struct ascodec_request *req)
510 } 519 }
511 } 520 }
512 521
522#if CONFIG_RTC
513 if (data[2] & IRQ_RTC) { /* rtc irq */ 523 if (data[2] & IRQ_RTC) { /* rtc irq */
514 /* 524 ascodec_enrd0_shadow |= IRQ_RTC;
515 * Can be configured for once per second or once per minute,
516 * default is once per second
517 */
518 COUNT_INT(rtc); 525 COUNT_INT(rtc);
519 } 526 }
527#endif /* CONFIG_RTC */
520 528
521 if (data[2] & IRQ_ADC) { /* adc finished */ 529 if (data[2] & IRQ_ADC) { /* adc finished */
522 COUNT_INT(adc); 530 COUNT_INT(adc);
@@ -580,6 +588,14 @@ int ascodec_read_charger(void)
580} 588}
581#endif /* CONFIG_CHARGING */ 589#endif /* CONFIG_CHARGING */
582 590
591#if CONFIG_RTC
592/* read sticky rtc dirty status */
593bool ascodec_rtc_dirty(void)
594{
595 return bitclr32(&ascodec_enrd0_shadow, IRQ_RTC) & IRQ_RTC;
596}
597#endif /* CONFIG_RTC */
598
583/* 599/*
584 * NOTE: 600 * NOTE:
585 * After the conversion to interrupts, ascodec_(lock|unlock) are only used by 601 * After the conversion to interrupts, ascodec_(lock|unlock) are only used by
@@ -635,8 +651,9 @@ void ascodec_init(void)
635 VIC_INT_ENABLE = INTERRUPT_I2C_AUDIO; 651 VIC_INT_ENABLE = INTERRUPT_I2C_AUDIO;
636 VIC_INT_ENABLE = INTERRUPT_AUDIO; 652 VIC_INT_ENABLE = INTERRUPT_AUDIO;
637 653
638 /* detect if USB was connected at startup since there is no transition */ 654 /* detect if USB was connected at startup since there is no transition;
639 ascodec_enrd0_shadow = ascodec_read(AS3514_IRQ_ENRD0); 655 force an initial read of the clock (if CONFIG_RTC) */
656 ascodec_enrd0_shadow = ascodec_read(AS3514_IRQ_ENRD0) | IFRTC_IRQ_RTC;
640 if(ascodec_enrd0_shadow & USB_STATUS) 657 if(ascodec_enrd0_shadow & USB_STATUS)
641 usb_insert_int(); 658 usb_insert_int();
642 659
@@ -651,10 +668,10 @@ void ascodec_init(void)
651 /* XIRQ = IRQ, active low reset signal, 6mA push-pull output */ 668 /* XIRQ = IRQ, active low reset signal, 6mA push-pull output */
652 ascodec_write_pmu(0x1a, 3, (1<<2)|3); /* 1A-3 = Out_Cntr3 register */ 669 ascodec_write_pmu(0x1a, 3, (1<<2)|3); /* 1A-3 = Out_Cntr3 register */
653 /* Generate irq on (rtc,) adc change */ 670 /* Generate irq on (rtc,) adc change */
654 ascodec_write(AS3514_IRQ_ENRD2, /*IRQ_RTC |*/ IRQ_ADC); 671 ascodec_write(AS3514_IRQ_ENRD2, IFRTC_IRQ_RTC | IRQ_ADC);
655#else 672#else
656 /* Generate irq for push-pull, active high, irq on rtc+adc change */ 673 /* Generate irq for push-pull, active high, irq on rtc+adc change */
657 ascodec_write(AS3514_IRQ_ENRD2, IRQ_PUSHPULL | IRQ_HIGHACTIVE | 674 ascodec_write(AS3514_IRQ_ENRD2, IRQ_PUSHPULL | IRQ_HIGHACTIVE |
658 /*IRQ_RTC |*/ IRQ_ADC); 675 IFRTC_IRQ_RTC | IRQ_ADC);
659#endif 676#endif
660} 677}
diff --git a/firmware/target/arm/as3525/rtc-target.h b/firmware/target/arm/as3525/rtc-target.h
new file mode 100644
index 0000000000..900aa357d0
--- /dev/null
+++ b/firmware/target/arm/as3525/rtc-target.h
@@ -0,0 +1,27 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2017 by Michael Sevakis
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef RTC_TARGET_H
22#define RTC_TARGET_H
23
24bool ascodec_rtc_dirty(void);
25#define rtc_dirty ascodec_rtc_dirty
26
27#endif /* RTC_TARGET_H */
diff --git a/firmware/target/arm/imx31/gigabeat-s/mc13783-target.h b/firmware/target/arm/imx31/gigabeat-s/mc13783-target.h
index 179c65cad6..4bb148e36c 100644
--- a/firmware/target/arm/imx31/gigabeat-s/mc13783-target.h
+++ b/firmware/target/arm/imx31/gigabeat-s/mc13783-target.h
@@ -46,6 +46,10 @@ static struct spi_node mc13783_spi =
46MC13783_EVENT_VECTOR_TBL_START() 46MC13783_EVENT_VECTOR_TBL_START()
47 /* ADC conversion complete */ 47 /* ADC conversion complete */
48 MC13783_EVENT_VECTOR(ADCDONE, 0) 48 MC13783_EVENT_VECTOR(ADCDONE, 0)
49#if CONFIG_RTC
50 /* RTC tick */
51 MC13783_EVENT_VECTOR(1HZ, 0)
52#endif /* CONFIG_RTC */
49 /* Power button */ 53 /* Power button */
50 MC13783_EVENT_VECTOR(ONOFD1, MC13783_ONOFD1S) 54 MC13783_EVENT_VECTOR(ONOFD1, MC13783_ONOFD1S)
51 /* Main charger detection */ 55 /* Main charger detection */
diff --git a/firmware/target/arm/imx31/rtc-target.h b/firmware/target/arm/imx31/rtc-target.h
new file mode 100644
index 0000000000..b6dc46204d
--- /dev/null
+++ b/firmware/target/arm/imx31/rtc-target.h
@@ -0,0 +1,27 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2017 by Michael Sevakis
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef RTC_TARGET_H
22#define RTC_TARGET_H
23
24bool rtc_mc13783_dirty(void);
25#define rtc_dirty rtc_mc13783_dirty
26
27#endif /* RTC_TARGET_H */