aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/Kconfig2
-rw-r--r--drivers/rtc/rtc-sa1100.c81
2 files changed, 12 insertions, 71 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 3a125b835546..c2365d45508d 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -748,7 +748,7 @@ config HAVE_S3C_RTC
748 748
749config RTC_DRV_S3C 749config RTC_DRV_S3C
750 tristate "Samsung S3C series SoC RTC" 750 tristate "Samsung S3C series SoC RTC"
751 depends on ARCH_S3C2410 || ARCH_S3C64XX || HAVE_S3C_RTC 751 depends on ARCH_S3C64XX || HAVE_S3C_RTC
752 help 752 help
753 RTC (Realtime Clock) driver for the clock inbuilt into the 753 RTC (Realtime Clock) driver for the clock inbuilt into the
754 Samsung S3C24XX series of SoCs. This can provide periodic 754 Samsung S3C24XX series of SoCs. This can provide periodic
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index cb9a585312cc..91d58bdc7f88 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
44static const unsigned long RTC_FREQ = 1024; 44static const unsigned long RTC_FREQ = 1024;
45static struct rtc_time rtc_alarm;
46static DEFINE_SPINLOCK(sa1100_rtc_lock); 45static DEFINE_SPINLOCK(sa1100_rtc_lock);
47 46
48static 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 */
62static 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
85static 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
106static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) 47static 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;
@@ -225,7 +163,6 @@ static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
225{ 163{
226 u32 rtsr; 164 u32 rtsr;
227 165
228 memcpy(&alrm->time, &rtc_alarm, sizeof(struct rtc_time));
229 rtsr = RTSR; 166 rtsr = RTSR;
230 alrm->enabled = (rtsr & RTSR_ALE) ? 1 : 0; 167 alrm->enabled = (rtsr & RTSR_ALE) ? 1 : 0;
231 alrm->pending = (rtsr & RTSR_AL) ? 1 : 0; 168 alrm->pending = (rtsr & RTSR_AL) ? 1 : 0;
@@ -234,16 +171,20 @@ static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
234 171
235static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) 172static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
236{ 173{
174 unsigned long time;
237 int ret; 175 int ret;
238 176
239 spin_lock_irq(&sa1100_rtc_lock); 177 spin_lock_irq(&sa1100_rtc_lock);
240 ret = rtc_update_alarm(&alrm->time); 178 ret = rtc_tm_to_time(&alrm->time, &time);
241 if (ret == 0) { 179 if (ret != 0)
242 if (alrm->enabled) 180 goto out;
243 RTSR |= RTSR_ALE; 181 RTSR = RTSR & (RTSR_HZE|RTSR_ALE|RTSR_AL);
244 else 182 RTAR = time;
245 RTSR &= ~RTSR_ALE; 183 if (alrm->enabled)
246 } 184 RTSR |= RTSR_ALE;
185 else
186 RTSR &= ~RTSR_ALE;
187out:
247 spin_unlock_irq(&sa1100_rtc_lock); 188 spin_unlock_irq(&sa1100_rtc_lock);
248 189
249 return ret; 190 return ret;