diff options
author | Bertrik Sikken <bertrik@sikken.nl> | 2010-07-16 10:05:48 +0000 |
---|---|---|
committer | Bertrik Sikken <bertrik@sikken.nl> | 2010-07-16 10:05:48 +0000 |
commit | 0da83cfc08e367a4b6ba0d8995c9d61c1b2ca33e (patch) | |
tree | 7f8aea29c9032628a5f52f071cea5a05f49d329f /firmware | |
parent | bb22ac539b7eec73ee367e642bceacf20122d7a3 (diff) | |
download | rockbox-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
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/drivers/rtc/rtc_as3514.c | 116 |
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 */ |
55 | static int wakeup_h; | 55 | struct { |
56 | static int wakeup_m; | 56 | unsigned int seconds; /* total seconds to wakeup */ |
57 | static 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 | ||
59 | void rtc_set_alarm(int h, int m) | 63 | void 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 | ||
65 | void rtc_get_alarm(int *h, int *m) | 69 | void 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 */ | ||
76 | static 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 */ | ||
99 | static 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 | ||
71 | void rtc_alarm_poweroff(void) | 122 | void 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 | ||
119 | void rtc_enable_alarm(bool enable) | 159 | void rtc_enable_alarm(bool enable) |
120 | { | 160 | { |
121 | alarm_enabled = enable; | 161 | alarm.enabled = enable; |
122 | } | 162 | } |
123 | 163 | ||
124 | bool rtc_check_alarm_started(bool release_alarm) | 164 | bool 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 | ||
148 | bool rtc_check_alarm_flag(void) | 182 | bool rtc_check_alarm_flag(void) |