diff options
Diffstat (limited to 'drivers/rtc/rtc-lib.c')
-rw-r--r-- | drivers/rtc/rtc-lib.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c index ba795a4db1e9..7bbc26a34bd2 100644 --- a/drivers/rtc/rtc-lib.c +++ b/drivers/rtc/rtc-lib.c | |||
@@ -117,4 +117,85 @@ int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time) | |||
117 | } | 117 | } |
118 | EXPORT_SYMBOL(rtc_tm_to_time); | 118 | EXPORT_SYMBOL(rtc_tm_to_time); |
119 | 119 | ||
120 | |||
121 | /* Merge the valid (i.e. non-negative) fields of alarm into the current | ||
122 | * time. If the valid alarm fields are earlier than the equivalent | ||
123 | * fields in the time, carry one into the least significant invalid | ||
124 | * field, so that the alarm expiry is in the future. It assumes that the | ||
125 | * least significant invalid field is more significant than the most | ||
126 | * significant valid field, and that the seconds field is valid. | ||
127 | * | ||
128 | * This is used by alarms that take relative (rather than absolute) | ||
129 | * times, and/or have a simple binary second counter instead of | ||
130 | * day/hour/minute/sec registers. | ||
131 | */ | ||
132 | void rtc_merge_alarm(struct rtc_time *now, struct rtc_time *alarm) | ||
133 | { | ||
134 | int *alarmp = &alarm->tm_sec; | ||
135 | int *timep = &now->tm_sec; | ||
136 | int carry_into, i; | ||
137 | |||
138 | /* Ignore everything past the 6th element (tm_year). */ | ||
139 | for (i = 5; i > 0; i--) { | ||
140 | if (alarmp[i] < 0) | ||
141 | alarmp[i] = timep[i]; | ||
142 | else | ||
143 | break; | ||
144 | } | ||
145 | |||
146 | /* No carry needed if all fields are valid. */ | ||
147 | if (i == 5) | ||
148 | return; | ||
149 | |||
150 | for (carry_into = i + 1; i >= 0; i--) { | ||
151 | if (alarmp[i] < timep[i]) | ||
152 | break; | ||
153 | |||
154 | if (alarmp[i] > timep[i]) | ||
155 | return; | ||
156 | } | ||
157 | |||
158 | switch (carry_into) { | ||
159 | case 1: | ||
160 | alarm->tm_min++; | ||
161 | |||
162 | if (alarm->tm_min < 60) | ||
163 | return; | ||
164 | |||
165 | alarm->tm_min = 0; | ||
166 | /* fall-through */ | ||
167 | |||
168 | case 2: | ||
169 | alarm->tm_hour++; | ||
170 | |||
171 | if (alarm->tm_hour < 60) | ||
172 | return; | ||
173 | |||
174 | alarm->tm_hour = 0; | ||
175 | /* fall-through */ | ||
176 | |||
177 | case 3: | ||
178 | alarm->tm_mday++; | ||
179 | |||
180 | if (alarm->tm_mday <= rtc_days_in_month[alarm->tm_mon]) | ||
181 | return; | ||
182 | |||
183 | alarm->tm_mday = 1; | ||
184 | /* fall-through */ | ||
185 | |||
186 | case 4: | ||
187 | alarm->tm_mon++; | ||
188 | |||
189 | if (alarm->tm_mon <= 12) | ||
190 | return; | ||
191 | |||
192 | alarm->tm_mon = 1; | ||
193 | /* fall-through */ | ||
194 | |||
195 | case 5: | ||
196 | alarm->tm_year++; | ||
197 | } | ||
198 | } | ||
199 | EXPORT_SYMBOL(rtc_merge_alarm); | ||
200 | |||
120 | MODULE_LICENSE("GPL"); | 201 | MODULE_LICENSE("GPL"); |