aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
authorScott Wood <scottwood@freescale.com>2006-12-10 05:19:00 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-10 12:55:40 -0500
commit884b4aaaa242a2db8c8252796f0118164a680ab5 (patch)
treeeea898cb8df58cace0a04025b5efdb8b2a2fd3d2 /drivers/rtc
parent9080d0ae0fd16628d688ce7d03d02ccf7011c6f0 (diff)
[PATCH] rtc: Add rtc_merge_alarm()
Add rtc_merge_alarm(), which can be used by rtc drivers to turn a partially specified alarm expiry (i.e. most significant fields set to -1, as with the RTC_ALM_SET ioctl()) into a fully specified expiry. If the most significant specified field is earlier than the current time, the least significant unspecified field is incremented. Signed-off-by: Scott Wood <scottwood@freescale.com> Acked-by: Alessandro Zummo <a.zummo@towertech.it> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/rtc-lib.c81
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}
118EXPORT_SYMBOL(rtc_tm_to_time); 118EXPORT_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 */
132void 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}
199EXPORT_SYMBOL(rtc_merge_alarm);
200
120MODULE_LICENSE("GPL"); 201MODULE_LICENSE("GPL");