Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 54780
b: refs/heads/master
c: f8245c2
h: refs/heads/master
v: v3
  • Loading branch information
David Brownell authored and Linus Torvalds committed May 8, 2007
1 parent 91737ef commit cd10681
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 37 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 416ce32e704d778c283f2f86cadd836cd5d3696c
refs/heads/master: f8245c26886c912627ebc49f714e4491261224c4
7 changes: 2 additions & 5 deletions trunk/Documentation/rtc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ RTC class framework, but can't be supported by the older driver.

* RTC_AIE_ON, RTC_AIE_OFF, RTC_ALM_SET, RTC_ALM_READ ... when the RTC
is connected to an IRQ line, it can often issue an alarm IRQ up to
24 hours in the future.
24 hours in the future. (Use RTC_WKALM_* by preference.)

* RTC_WKALM_SET, RTC_WKALM_RD ... RTCs that can issue alarms beyond
the next 24 hours use a slightly more powerful API, which supports
Expand Down Expand Up @@ -175,10 +175,7 @@ driver returns ENOIOCTLCMD. Some common examples:
called with appropriate values.

* RTC_ALM_SET, RTC_ALM_READ, RTC_WKALM_SET, RTC_WKALM_RD: the
set_alarm/read_alarm functions will be called. To differentiate
between the ALM and WKALM, check the larger fields of the rtc_wkalrm
struct (like tm_year). These will be set to -1 when using ALM and
will be set to proper values when using WKALM.
set_alarm/read_alarm functions will be called.

* RTC_IRQP_SET, RTC_IRQP_READ: the irq_set_freq function will be called
to set the frequency while the framework will handle the read for you
Expand Down
4 changes: 4 additions & 0 deletions trunk/drivers/rtc/interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
{
int err;

err = rtc_valid_tm(&alarm->time);
if (err != 0)
return err;

err = mutex_lock_interruptible(&rtc->ops_lock);
if (err)
return -EBUSY;
Expand Down
42 changes: 39 additions & 3 deletions trunk/drivers/rtc/rtc-dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,12 +277,48 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,

alarm.enabled = 0;
alarm.pending = 0;
alarm.time.tm_mday = -1;
alarm.time.tm_mon = -1;
alarm.time.tm_year = -1;
alarm.time.tm_wday = -1;
alarm.time.tm_yday = -1;
alarm.time.tm_isdst = -1;

/* RTC_ALM_SET alarms may be up to 24 hours in the future.
* Rather than expecting every RTC to implement "don't care"
* for day/month/year fields, just force the alarm to have
* the right values for those fields.
*
* RTC_WKALM_SET should be used instead. Not only does it
* eliminate the need for a separate RTC_AIE_ON call, it
* doesn't have the "alarm 23:59:59 in the future" race.
*
* NOTE: some legacy code may have used invalid fields as
* wildcards, exposing hardware "periodic alarm" capabilities.
* Not supported here.
*/
{
unsigned long now, then;

err = rtc_read_time(rtc, &tm);
if (err < 0)
return err;
rtc_tm_to_time(&tm, &now);

alarm.time.tm_mday = tm.tm_mday;
alarm.time.tm_mon = tm.tm_mon;
alarm.time.tm_year = tm.tm_year;
err = rtc_valid_tm(&alarm.time);
if (err < 0)
return err;
rtc_tm_to_time(&alarm.time, &then);

/* alarm may need to wrap into tomorrow */
if (then < now) {
rtc_time_to_tm(now + 24 * 60 * 60, &tm);
alarm.time.tm_mday = tm.tm_mday;
alarm.time.tm_mon = tm.tm_mon;
alarm.time.tm_year = tm.tm_year;
}
}

err = rtc_set_alarm(rtc, &alarm);
break;

Expand Down
28 changes: 0 additions & 28 deletions trunk/drivers/rtc/rtc-omap.c
Original file line number Diff line number Diff line change
Expand Up @@ -289,34 +289,6 @@ static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
u8 reg;

/* Much userspace code uses RTC_ALM_SET, thus "don't care" for
* day/month/year specifies alarms up to 24 hours in the future.
* So we need to handle that ... but let's ignore the "don't care"
* values for hours/minutes/seconds.
*/
if (alm->time.tm_mday <= 0
&& alm->time.tm_mon < 0
&& alm->time.tm_year < 0) {
struct rtc_time tm;
unsigned long now, then;

omap_rtc_read_time(dev, &tm);
rtc_tm_to_time(&tm, &now);

alm->time.tm_mday = tm.tm_mday;
alm->time.tm_mon = tm.tm_mon;
alm->time.tm_year = tm.tm_year;
rtc_tm_to_time(&alm->time, &then);

/* sometimes the alarm wraps into tomorrow */
if (then < now) {
rtc_time_to_tm(now + 24 * 60 * 60, &tm);
alm->time.tm_mday = tm.tm_mday;
alm->time.tm_mon = tm.tm_mon;
alm->time.tm_year = tm.tm_year;
}
}

if (tm2bcd(&alm->time) < 0)
return -EINVAL;

Expand Down

0 comments on commit cd10681

Please sign in to comment.