diff options
Diffstat (limited to 'drivers/rtc/rtc-sa1100.c')
-rw-r--r-- | drivers/rtc/rtc-sa1100.c | 81 |
1 files changed, 11 insertions, 70 deletions
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index fb758db9d0f4..44cd81c72ea1 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c | |||
@@ -42,67 +42,8 @@ | |||
42 | #define RTC_DEF_TRIM 0 | 42 | #define RTC_DEF_TRIM 0 |
43 | 43 | ||
44 | static const unsigned long RTC_FREQ = 1024; | 44 | static const unsigned long RTC_FREQ = 1024; |
45 | static struct rtc_time rtc_alarm; | ||
46 | static DEFINE_SPINLOCK(sa1100_rtc_lock); | 45 | static DEFINE_SPINLOCK(sa1100_rtc_lock); |
47 | 46 | ||
48 | static inline int rtc_periodic_alarm(struct rtc_time *tm) | ||
49 | { | ||
50 | return (tm->tm_year == -1) || | ||
51 | ((unsigned)tm->tm_mon >= 12) || | ||
52 | ((unsigned)(tm->tm_mday - 1) >= 31) || | ||
53 | ((unsigned)tm->tm_hour > 23) || | ||
54 | ((unsigned)tm->tm_min > 59) || | ||
55 | ((unsigned)tm->tm_sec > 59); | ||
56 | } | ||
57 | |||
58 | /* | ||
59 | * Calculate the next alarm time given the requested alarm time mask | ||
60 | * and the current time. | ||
61 | */ | ||
62 | static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, | ||
63 | struct rtc_time *alrm) | ||
64 | { | ||
65 | unsigned long next_time; | ||
66 | unsigned long now_time; | ||
67 | |||
68 | next->tm_year = now->tm_year; | ||
69 | next->tm_mon = now->tm_mon; | ||
70 | next->tm_mday = now->tm_mday; | ||
71 | next->tm_hour = alrm->tm_hour; | ||
72 | next->tm_min = alrm->tm_min; | ||
73 | next->tm_sec = alrm->tm_sec; | ||
74 | |||
75 | rtc_tm_to_time(now, &now_time); | ||
76 | rtc_tm_to_time(next, &next_time); | ||
77 | |||
78 | if (next_time < now_time) { | ||
79 | /* Advance one day */ | ||
80 | next_time += 60 * 60 * 24; | ||
81 | rtc_time_to_tm(next_time, next); | ||
82 | } | ||
83 | } | ||
84 | |||
85 | static int rtc_update_alarm(struct rtc_time *alrm) | ||
86 | { | ||
87 | struct rtc_time alarm_tm, now_tm; | ||
88 | unsigned long now, time; | ||
89 | int ret; | ||
90 | |||
91 | do { | ||
92 | now = RCNR; | ||
93 | rtc_time_to_tm(now, &now_tm); | ||
94 | rtc_next_alarm_time(&alarm_tm, &now_tm, alrm); | ||
95 | ret = rtc_tm_to_time(&alarm_tm, &time); | ||
96 | if (ret != 0) | ||
97 | break; | ||
98 | |||
99 | RTSR = RTSR & (RTSR_HZE|RTSR_ALE|RTSR_AL); | ||
100 | RTAR = time; | ||
101 | } while (now != RCNR); | ||
102 | |||
103 | return ret; | ||
104 | } | ||
105 | |||
106 | static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) | 47 | static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) |
107 | { | 48 | { |
108 | struct platform_device *pdev = to_platform_device(dev_id); | 49 | struct platform_device *pdev = to_platform_device(dev_id); |
@@ -146,9 +87,6 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) | |||
146 | 87 | ||
147 | rtc_update_irq(rtc, 1, events); | 88 | rtc_update_irq(rtc, 1, events); |
148 | 89 | ||
149 | if (rtsr & RTSR_AL && rtc_periodic_alarm(&rtc_alarm)) | ||
150 | rtc_update_alarm(&rtc_alarm); | ||
151 | |||
152 | spin_unlock(&sa1100_rtc_lock); | 90 | spin_unlock(&sa1100_rtc_lock); |
153 | 91 | ||
154 | return IRQ_HANDLED; | 92 | return IRQ_HANDLED; |
@@ -224,7 +162,6 @@ static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
224 | { | 162 | { |
225 | u32 rtsr; | 163 | u32 rtsr; |
226 | 164 | ||
227 | memcpy(&alrm->time, &rtc_alarm, sizeof(struct rtc_time)); | ||
228 | rtsr = RTSR; | 165 | rtsr = RTSR; |
229 | alrm->enabled = (rtsr & RTSR_ALE) ? 1 : 0; | 166 | alrm->enabled = (rtsr & RTSR_ALE) ? 1 : 0; |
230 | alrm->pending = (rtsr & RTSR_AL) ? 1 : 0; | 167 | alrm->pending = (rtsr & RTSR_AL) ? 1 : 0; |
@@ -233,16 +170,20 @@ static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
233 | 170 | ||
234 | static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 171 | static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
235 | { | 172 | { |
173 | unsigned long time; | ||
236 | int ret; | 174 | int ret; |
237 | 175 | ||
238 | spin_lock_irq(&sa1100_rtc_lock); | 176 | spin_lock_irq(&sa1100_rtc_lock); |
239 | ret = rtc_update_alarm(&alrm->time); | 177 | ret = rtc_tm_to_time(&alrm->time, &time); |
240 | if (ret == 0) { | 178 | if (ret != 0) |
241 | if (alrm->enabled) | 179 | goto out; |
242 | RTSR |= RTSR_ALE; | 180 | RTSR = RTSR & (RTSR_HZE|RTSR_ALE|RTSR_AL); |
243 | else | 181 | RTAR = time; |
244 | RTSR &= ~RTSR_ALE; | 182 | if (alrm->enabled) |
245 | } | 183 | RTSR |= RTSR_ALE; |
184 | else | ||
185 | RTSR &= ~RTSR_ALE; | ||
186 | out: | ||
246 | spin_unlock_irq(&sa1100_rtc_lock); | 187 | spin_unlock_irq(&sa1100_rtc_lock); |
247 | 188 | ||
248 | return ret; | 189 | return ret; |