summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBertrik Sikken <bertrik@sikken.nl>2010-07-16 10:05:48 +0000
committerBertrik Sikken <bertrik@sikken.nl>2010-07-16 10:05:48 +0000
commit0da83cfc08e367a4b6ba0d8995c9d61c1b2ca33e (patch)
tree7f8aea29c9032628a5f52f071cea5a05f49d329f
parentbb22ac539b7eec73ee367e642bceacf20122d7a3 (diff)
downloadrockbox-0da83cfc08e367a4b6ba0d8995c9d61c1b2ca33e.tar.gz
rockbox-0da83cfc08e367a4b6ba0d8995c9d61c1b2ca33e.zip
Fix failing AMSv2 power-down when the wake-up alarm timer is set - FS #11453 by me
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27447 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/drivers/rtc/rtc_as3514.c116
1 files changed, 75 insertions, 41 deletions
diff --git a/firmware/drivers/rtc/rtc_as3514.c b/firmware/drivers/rtc/rtc_as3514.c
index 81137bda14..ac44c7d89c 100644
--- a/firmware/drivers/rtc/rtc_as3514.c
+++ b/firmware/drivers/rtc/rtc_as3514.c
@@ -52,31 +52,82 @@ static inline bool is_leapyear(int year)
52} 52}
53 53
54#ifdef HAVE_RTC_ALARM /* as3543 */ 54#ifdef HAVE_RTC_ALARM /* as3543 */
55static int wakeup_h; 55struct {
56static int wakeup_m; 56 unsigned int seconds; /* total seconds to wakeup */
57static bool alarm_enabled = false; 57 bool enabled; /* alarm enabled or not */
58 unsigned char flag; /* flag used by the OF */
59 int hour; /* wake-up hour */
60 int min; /* wake-up minute */
61} alarm;
58 62
59void rtc_set_alarm(int h, int m) 63void rtc_set_alarm(int h, int m)
60{ 64{
61 wakeup_h = h; 65 alarm.hour = h;
62 wakeup_m = m; 66 alarm.min = m;
63} 67}
64 68
65void rtc_get_alarm(int *h, int *m) 69void rtc_get_alarm(int *h, int *m)
66{ 70{
67 *h = wakeup_h; 71 *h = alarm.hour;
68 *m = wakeup_m; 72 *m = alarm.min;
73}
74
75/* Reads the AS3543 wakeup register */
76static void alarm_read(void)
77{
78 unsigned char buf[6];
79 unsigned int i;
80 int oldstatus;
81
82 /* read raw data */
83 oldstatus = disable_irq_save();
84 ascodec_read(0);
85 for (i = 0; i < sizeof(buf); i++) {
86 buf[i] = ascodec_read(AS3543_WAKEUP);
87 }
88 restore_irq(oldstatus);
89
90 /* decode */
91 alarm.seconds = buf[0] | (buf[1] << 8) | ((buf[2] & 0x7F) << 16);
92 alarm.enabled = buf[2] & (1 << 7);
93 alarm.flag = buf[3];
94 alarm.hour = buf[4];
95 alarm.min = buf[5];
96}
97
98/* Writes the AS3543 wakeup register */
99static void alarm_write(void)
100{
101 unsigned char buf[6];
102 unsigned int i;
103 int oldstatus;
104
105 /* encode */
106 buf[0] = alarm.seconds & 0xFF;
107 buf[1] = (alarm.seconds >> 8) & 0xFF;
108 buf[2] = ((alarm.seconds >> 16) & 0x7F) | (alarm.enabled ? (1 << 7) : 0);
109 buf[3] = alarm.flag;
110 buf[4] = alarm.hour;
111 buf[5] = alarm.min;
112
113 /* write raw data */
114 oldstatus = disable_irq_save();
115 ascodec_read(0);
116 for (i = 0; i < sizeof(buf); i++) {
117 ascodec_write(AS3543_WAKEUP, buf[i]);
118 }
119 restore_irq(oldstatus);
69} 120}
70 121
71void rtc_alarm_poweroff(void) 122void rtc_alarm_poweroff(void)
72{ 123{
73 if(!alarm_enabled) 124 if(!alarm.enabled)
74 return; 125 return;
75 126
76 struct tm tm; 127 struct tm tm;
77 rtc_read_datetime(&tm); 128 rtc_read_datetime(&tm);
78 int hours = wakeup_h - tm.tm_hour; 129 int hours = alarm.hour - tm.tm_hour;
79 int mins = wakeup_m - tm.tm_min; 130 int mins = alarm.min - tm.tm_min;
80 if(mins < 0) 131 if(mins < 0)
81 { 132 {
82 mins += 60; 133 mins += 60;
@@ -91,26 +142,15 @@ void rtc_alarm_poweroff(void)
91 142
92 seconds -= tm.tm_sec; 143 seconds -= tm.tm_sec;
93 144
94 disable_irq(); 145 /* write wakeup register */
95 146 alarm.seconds = seconds;
96 ascodec_write(AS3543_WAKEUP, seconds); 147 alarm.enabled = true;
97 seconds >>= 8; 148 alarm_write();
98 ascodec_write(AS3543_WAKEUP, seconds);
99 seconds >>= 8;
100 seconds |= 1<<7; /* enable bit */
101 ascodec_write(AS3543_WAKEUP, seconds);
102
103 /* write 0x80 to prevent the OF refreshing its database from the microSD */
104 ascodec_write(AS3543_WAKEUP, 0x80);
105
106 /* write our desired time of wake up to detect power-up from RTC */
107 ascodec_write(AS3543_WAKEUP, wakeup_h);
108 ascodec_write(AS3543_WAKEUP, wakeup_m);
109 149
110 /* enable hearbeat watchdog */ 150 /* enable heartbeat watchdog */
111 ascodec_write(AS3514_SYSTEM, (1<<3) | (1<<0)); 151 ascodec_write(AS3514_SYSTEM, (1<<3) | (1<<0));
112 152
113 /* In_Cntr : disable hearbeat source */ 153 /* In_Cntr : disable heartbeat source */
114 ascodec_write_pmu(0x1a, 4, ascodec_read_pmu(0x1a, 4) & ~(3<<2)); 154 ascodec_write_pmu(0x1a, 4, ascodec_read_pmu(0x1a, 4) & ~(3<<2));
115 155
116 while(1); 156 while(1);
@@ -118,31 +158,25 @@ void rtc_alarm_poweroff(void)
118 158
119void rtc_enable_alarm(bool enable) 159void rtc_enable_alarm(bool enable)
120{ 160{
121 alarm_enabled = enable; 161 alarm.enabled = enable;
122} 162}
123 163
124bool rtc_check_alarm_started(bool release_alarm) 164bool rtc_check_alarm_started(bool release_alarm)
125{ 165{
126 (void) release_alarm; 166 /* read wakeup register and check if alarm was enabled */
127 167 alarm_read();
128 /* 3 first reads give the 23 bits counter and enable bit */ 168 if (!alarm.enabled) {
129 ascodec_read(AS3543_WAKEUP); /* bits 7:0 */
130 ascodec_read(AS3543_WAKEUP); /* bits 15:8 */
131 if(!(ascodec_read(AS3543_WAKEUP) & (1<<7))) /* enable bit */
132 return false; 169 return false;
133 170 }
134 /* skip WAKEUP[3] which the OF uses for other purposes */
135 ascodec_read(AS3543_WAKEUP);
136 171
137 /* subsequent reads give the 16 bytes static SRAM */ 172 alarm.enabled = !release_alarm;
138 wakeup_h = ascodec_read(AS3543_WAKEUP); 173 alarm_write();
139 wakeup_m = ascodec_read(AS3543_WAKEUP);
140 174
141 struct tm tm; 175 struct tm tm;
142 rtc_read_datetime(&tm); 176 rtc_read_datetime(&tm);
143 177
144 /* were we powered up at the programmed time ? */ 178 /* were we powered up at the programmed time ? */
145 return wakeup_h == tm.tm_hour && wakeup_m == tm.tm_min; 179 return alarm.hour == tm.tm_hour && alarm.min == tm.tm_min;
146} 180}
147 181
148bool rtc_check_alarm_flag(void) 182bool rtc_check_alarm_flag(void)