diff options
Diffstat (limited to 'drivers/rtc')
| -rw-r--r-- | drivers/rtc/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/rtc/rtc-sa1100.c | 81 |
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 | ||
| 749 | config RTC_DRV_S3C | 749 | config 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 | ||
| 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; |
| @@ -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 | ||
| 235 | static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 172 | static 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; | ||
| 187 | out: | ||
| 247 | spin_unlock_irq(&sa1100_rtc_lock); | 188 | spin_unlock_irq(&sa1100_rtc_lock); |
| 248 | 189 | ||
| 249 | return ret; | 190 | return ret; |
