diff options
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/rtc-cmos.c | 193 |
1 files changed, 131 insertions, 62 deletions
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 94b89a2d9c2e..e9984650ea95 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
@@ -36,28 +36,9 @@ | |||
36 | #include <linux/platform_device.h> | 36 | #include <linux/platform_device.h> |
37 | #include <linux/mod_devicetable.h> | 37 | #include <linux/mod_devicetable.h> |
38 | 38 | ||
39 | #ifdef CONFIG_HPET_EMULATE_RTC | ||
40 | #include <asm/hpet.h> | ||
41 | #endif | ||
42 | |||
43 | /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ | 39 | /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ |
44 | #include <asm-generic/rtc.h> | 40 | #include <asm-generic/rtc.h> |
45 | 41 | ||
46 | #ifndef CONFIG_HPET_EMULATE_RTC | ||
47 | #define is_hpet_enabled() 0 | ||
48 | #define hpet_set_alarm_time(hrs, min, sec) do { } while (0) | ||
49 | #define hpet_set_periodic_freq(arg) 0 | ||
50 | #define hpet_mask_rtc_irq_bit(arg) do { } while (0) | ||
51 | #define hpet_set_rtc_irq_bit(arg) do { } while (0) | ||
52 | #define hpet_rtc_timer_init() do { } while (0) | ||
53 | #define hpet_register_irq_handler(h) 0 | ||
54 | #define hpet_unregister_irq_handler(h) do { } while (0) | ||
55 | static irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) | ||
56 | { | ||
57 | return 0; | ||
58 | } | ||
59 | #endif | ||
60 | |||
61 | struct cmos_rtc { | 42 | struct cmos_rtc { |
62 | struct rtc_device *rtc; | 43 | struct rtc_device *rtc; |
63 | struct device *dev; | 44 | struct device *dev; |
@@ -96,6 +77,72 @@ static inline int is_intr(u8 rtc_intr) | |||
96 | 77 | ||
97 | /*----------------------------------------------------------------*/ | 78 | /*----------------------------------------------------------------*/ |
98 | 79 | ||
80 | /* Much modern x86 hardware has HPETs (10+ MHz timers) which, because | ||
81 | * many BIOS programmers don't set up "sane mode" IRQ routing, are mostly | ||
82 | * used in a broken "legacy replacement" mode. The breakage includes | ||
83 | * HPET #1 hijacking the IRQ for this RTC, and being unavailable for | ||
84 | * other (better) use. | ||
85 | * | ||
86 | * When that broken mode is in use, platform glue provides a partial | ||
87 | * emulation of hardware RTC IRQ facilities using HPET #1. We don't | ||
88 | * want to use HPET for anything except those IRQs though... | ||
89 | */ | ||
90 | #ifdef CONFIG_HPET_EMULATE_RTC | ||
91 | #include <asm/hpet.h> | ||
92 | #else | ||
93 | |||
94 | static inline int is_hpet_enabled(void) | ||
95 | { | ||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | static inline int hpet_mask_rtc_irq_bit(unsigned long mask) | ||
100 | { | ||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static inline int hpet_set_rtc_irq_bit(unsigned long mask) | ||
105 | { | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static inline int | ||
110 | hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned char sec) | ||
111 | { | ||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static inline int hpet_set_periodic_freq(unsigned long freq) | ||
116 | { | ||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | static inline int hpet_rtc_dropped_irq(void) | ||
121 | { | ||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | static inline int hpet_rtc_timer_init(void) | ||
126 | { | ||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | extern irq_handler_t hpet_rtc_interrupt; | ||
131 | |||
132 | static inline int hpet_register_irq_handler(irq_handler_t handler) | ||
133 | { | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static inline int hpet_unregister_irq_handler(irq_handler_t handler) | ||
138 | { | ||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | #endif | ||
143 | |||
144 | /*----------------------------------------------------------------*/ | ||
145 | |||
99 | static int cmos_read_time(struct device *dev, struct rtc_time *t) | 146 | static int cmos_read_time(struct device *dev, struct rtc_time *t) |
100 | { | 147 | { |
101 | /* REVISIT: if the clock has a "century" register, use | 148 | /* REVISIT: if the clock has a "century" register, use |
@@ -216,13 +263,14 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
216 | sec = t->time.tm_sec; | 263 | sec = t->time.tm_sec; |
217 | sec = (sec < 60) ? BIN2BCD(sec) : 0xff; | 264 | sec = (sec < 60) ? BIN2BCD(sec) : 0xff; |
218 | 265 | ||
219 | hpet_set_alarm_time(t->time.tm_hour, t->time.tm_min, t->time.tm_sec); | ||
220 | spin_lock_irq(&rtc_lock); | 266 | spin_lock_irq(&rtc_lock); |
221 | 267 | ||
222 | /* next rtc irq must not be from previous alarm setting */ | 268 | /* next rtc irq must not be from previous alarm setting */ |
223 | rtc_control = CMOS_READ(RTC_CONTROL); | 269 | rtc_control = CMOS_READ(RTC_CONTROL); |
224 | rtc_control &= ~RTC_AIE; | 270 | rtc_control &= ~RTC_AIE; |
225 | CMOS_WRITE(rtc_control, RTC_CONTROL); | 271 | CMOS_WRITE(rtc_control, RTC_CONTROL); |
272 | hpet_mask_rtc_irq_bit(RTC_AIE); | ||
273 | |||
226 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); | 274 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); |
227 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; | 275 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; |
228 | if (is_intr(rtc_intr)) | 276 | if (is_intr(rtc_intr)) |
@@ -240,9 +288,16 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
240 | CMOS_WRITE(mon, cmos->mon_alrm); | 288 | CMOS_WRITE(mon, cmos->mon_alrm); |
241 | } | 289 | } |
242 | 290 | ||
291 | /* FIXME the HPET alarm glue currently ignores day_alrm | ||
292 | * and mon_alrm ... | ||
293 | */ | ||
294 | hpet_set_alarm_time(t->time.tm_hour, t->time.tm_min, t->time.tm_sec); | ||
295 | |||
243 | if (t->enabled) { | 296 | if (t->enabled) { |
244 | rtc_control |= RTC_AIE; | 297 | rtc_control |= RTC_AIE; |
245 | CMOS_WRITE(rtc_control, RTC_CONTROL); | 298 | CMOS_WRITE(rtc_control, RTC_CONTROL); |
299 | hpet_set_rtc_irq_bit(RTC_AIE); | ||
300 | |||
246 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); | 301 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); |
247 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; | 302 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; |
248 | if (is_intr(rtc_intr)) | 303 | if (is_intr(rtc_intr)) |
@@ -270,8 +325,8 @@ static int cmos_irq_set_freq(struct device *dev, int freq) | |||
270 | f = 16 - f; | 325 | f = 16 - f; |
271 | 326 | ||
272 | spin_lock_irqsave(&rtc_lock, flags); | 327 | spin_lock_irqsave(&rtc_lock, flags); |
273 | if (!hpet_set_periodic_freq(freq)) | 328 | hpet_set_periodic_freq(freq); |
274 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT); | 329 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT); |
275 | spin_unlock_irqrestore(&rtc_lock, flags); | 330 | spin_unlock_irqrestore(&rtc_lock, flags); |
276 | 331 | ||
277 | return 0; | 332 | return 0; |
@@ -289,11 +344,13 @@ static int cmos_irq_set_state(struct device *dev, int enabled) | |||
289 | spin_lock_irqsave(&rtc_lock, flags); | 344 | spin_lock_irqsave(&rtc_lock, flags); |
290 | rtc_control = CMOS_READ(RTC_CONTROL); | 345 | rtc_control = CMOS_READ(RTC_CONTROL); |
291 | 346 | ||
292 | if (enabled) | 347 | if (enabled) { |
293 | rtc_control |= RTC_PIE; | 348 | rtc_control |= RTC_PIE; |
294 | else | 349 | hpet_set_rtc_irq_bit(RTC_PIE); |
350 | } else { | ||
295 | rtc_control &= ~RTC_PIE; | 351 | rtc_control &= ~RTC_PIE; |
296 | 352 | hpet_mask_rtc_irq_bit(RTC_PIE); | |
353 | } | ||
297 | CMOS_WRITE(rtc_control, RTC_CONTROL); | 354 | CMOS_WRITE(rtc_control, RTC_CONTROL); |
298 | 355 | ||
299 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); | 356 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); |
@@ -319,11 +376,10 @@ cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
319 | case RTC_AIE_ON: | 376 | case RTC_AIE_ON: |
320 | case RTC_UIE_OFF: | 377 | case RTC_UIE_OFF: |
321 | case RTC_UIE_ON: | 378 | case RTC_UIE_ON: |
322 | case RTC_PIE_OFF: | ||
323 | case RTC_PIE_ON: | ||
324 | if (!is_valid_irq(cmos->irq)) | 379 | if (!is_valid_irq(cmos->irq)) |
325 | return -EINVAL; | 380 | return -EINVAL; |
326 | break; | 381 | break; |
382 | /* PIE ON/OFF is handled by cmos_irq_set_state() */ | ||
327 | default: | 383 | default: |
328 | return -ENOIOCTLCMD; | 384 | return -ENOIOCTLCMD; |
329 | } | 385 | } |
@@ -347,17 +403,8 @@ cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
347 | rtc_control |= RTC_UIE; | 403 | rtc_control |= RTC_UIE; |
348 | hpet_set_rtc_irq_bit(RTC_UIE); | 404 | hpet_set_rtc_irq_bit(RTC_UIE); |
349 | break; | 405 | break; |
350 | case RTC_PIE_OFF: /* periodic off */ | ||
351 | rtc_control &= ~RTC_PIE; | ||
352 | hpet_mask_rtc_irq_bit(RTC_PIE); | ||
353 | break; | ||
354 | case RTC_PIE_ON: /* periodic on */ | ||
355 | rtc_control |= RTC_PIE; | ||
356 | hpet_set_rtc_irq_bit(RTC_PIE); | ||
357 | break; | ||
358 | } | 406 | } |
359 | if (!is_hpet_enabled()) | 407 | CMOS_WRITE(rtc_control, RTC_CONTROL); |
360 | CMOS_WRITE(rtc_control, RTC_CONTROL); | ||
361 | 408 | ||
362 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); | 409 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); |
363 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; | 410 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; |
@@ -505,18 +552,19 @@ static irqreturn_t cmos_interrupt(int irq, void *p) | |||
505 | u8 rtc_control; | 552 | u8 rtc_control; |
506 | 553 | ||
507 | spin_lock(&rtc_lock); | 554 | spin_lock(&rtc_lock); |
508 | /* | 555 | |
509 | * In this case it is HPET RTC interrupt handler | 556 | /* When the HPET interrupt handler calls us, the interrupt |
510 | * calling us, with the interrupt information | 557 | * status is passed as arg1 instead of the irq number. But |
511 | * passed as arg1, instead of irq. | 558 | * always clear irq status, even when HPET is in the way. |
559 | * | ||
560 | * Note that HPET and RTC are almost certainly out of phase, | ||
561 | * giving different IRQ status ... | ||
512 | */ | 562 | */ |
563 | irqstat = CMOS_READ(RTC_INTR_FLAGS); | ||
564 | rtc_control = CMOS_READ(RTC_CONTROL); | ||
513 | if (is_hpet_enabled()) | 565 | if (is_hpet_enabled()) |
514 | irqstat = (unsigned long)irq & 0xF0; | 566 | irqstat = (unsigned long)irq & 0xF0; |
515 | else { | 567 | irqstat &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; |
516 | irqstat = CMOS_READ(RTC_INTR_FLAGS); | ||
517 | rtc_control = CMOS_READ(RTC_CONTROL); | ||
518 | irqstat &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; | ||
519 | } | ||
520 | 568 | ||
521 | /* All Linux RTC alarms should be treated as if they were oneshot. | 569 | /* All Linux RTC alarms should be treated as if they were oneshot. |
522 | * Similar code may be needed in system wakeup paths, in case the | 570 | * Similar code may be needed in system wakeup paths, in case the |
@@ -526,6 +574,8 @@ static irqreturn_t cmos_interrupt(int irq, void *p) | |||
526 | rtc_control = CMOS_READ(RTC_CONTROL); | 574 | rtc_control = CMOS_READ(RTC_CONTROL); |
527 | rtc_control &= ~RTC_AIE; | 575 | rtc_control &= ~RTC_AIE; |
528 | CMOS_WRITE(rtc_control, RTC_CONTROL); | 576 | CMOS_WRITE(rtc_control, RTC_CONTROL); |
577 | hpet_mask_rtc_irq_bit(RTC_AIE); | ||
578 | |||
529 | CMOS_READ(RTC_INTR_FLAGS); | 579 | CMOS_READ(RTC_INTR_FLAGS); |
530 | } | 580 | } |
531 | spin_unlock(&rtc_lock); | 581 | spin_unlock(&rtc_lock); |
@@ -632,8 +682,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
632 | * do something about other clock frequencies. | 682 | * do something about other clock frequencies. |
633 | */ | 683 | */ |
634 | cmos_rtc.rtc->irq_freq = 1024; | 684 | cmos_rtc.rtc->irq_freq = 1024; |
635 | if (!hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq)) | 685 | hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq); |
636 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT); | 686 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT); |
637 | 687 | ||
638 | /* disable irqs. | 688 | /* disable irqs. |
639 | * | 689 | * |
@@ -643,6 +693,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
643 | rtc_control = CMOS_READ(RTC_CONTROL); | 693 | rtc_control = CMOS_READ(RTC_CONTROL); |
644 | rtc_control &= ~(RTC_PIE | RTC_AIE | RTC_UIE); | 694 | rtc_control &= ~(RTC_PIE | RTC_AIE | RTC_UIE); |
645 | CMOS_WRITE(rtc_control, RTC_CONTROL); | 695 | CMOS_WRITE(rtc_control, RTC_CONTROL); |
696 | hpet_mask_rtc_irq_bit(RTC_PIE | RTC_AIE | RTC_UIE); | ||
697 | |||
646 | CMOS_READ(RTC_INTR_FLAGS); | 698 | CMOS_READ(RTC_INTR_FLAGS); |
647 | 699 | ||
648 | spin_unlock_irq(&rtc_lock); | 700 | spin_unlock_irq(&rtc_lock); |
@@ -690,7 +742,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
690 | goto cleanup2; | 742 | goto cleanup2; |
691 | } | 743 | } |
692 | 744 | ||
693 | pr_info("%s: alarms up to one %s%s\n", | 745 | pr_info("%s: alarms up to one %s%s%s\n", |
694 | cmos_rtc.rtc->dev.bus_id, | 746 | cmos_rtc.rtc->dev.bus_id, |
695 | is_valid_irq(rtc_irq) | 747 | is_valid_irq(rtc_irq) |
696 | ? (cmos_rtc.mon_alrm | 748 | ? (cmos_rtc.mon_alrm |
@@ -698,8 +750,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
698 | : (cmos_rtc.day_alrm | 750 | : (cmos_rtc.day_alrm |
699 | ? "month" : "day")) | 751 | ? "month" : "day")) |
700 | : "no", | 752 | : "no", |
701 | cmos_rtc.century ? ", y3k" : "" | 753 | cmos_rtc.century ? ", y3k" : "", |
702 | ); | 754 | is_hpet_enabled() ? ", hpet irqs" : ""); |
703 | 755 | ||
704 | return 0; | 756 | return 0; |
705 | 757 | ||
@@ -720,8 +772,10 @@ static void cmos_do_shutdown(void) | |||
720 | 772 | ||
721 | spin_lock_irq(&rtc_lock); | 773 | spin_lock_irq(&rtc_lock); |
722 | rtc_control = CMOS_READ(RTC_CONTROL); | 774 | rtc_control = CMOS_READ(RTC_CONTROL); |
723 | rtc_control &= ~(RTC_PIE|RTC_AIE|RTC_UIE); | 775 | rtc_control &= ~RTC_IRQMASK; |
724 | CMOS_WRITE(rtc_control, RTC_CONTROL); | 776 | CMOS_WRITE(rtc_control, RTC_CONTROL); |
777 | hpet_mask_rtc_irq_bit(RTC_IRQMASK); | ||
778 | |||
725 | CMOS_READ(RTC_INTR_FLAGS); | 779 | CMOS_READ(RTC_INTR_FLAGS); |
726 | spin_unlock_irq(&rtc_lock); | 780 | spin_unlock_irq(&rtc_lock); |
727 | } | 781 | } |
@@ -764,12 +818,16 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg) | |||
764 | cmos->suspend_ctrl = tmp = CMOS_READ(RTC_CONTROL); | 818 | cmos->suspend_ctrl = tmp = CMOS_READ(RTC_CONTROL); |
765 | if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) { | 819 | if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) { |
766 | unsigned char irqstat; | 820 | unsigned char irqstat; |
821 | unsigned char mask; | ||
767 | 822 | ||
768 | if (do_wake) | 823 | if (do_wake) |
769 | tmp &= ~(RTC_PIE|RTC_UIE); | 824 | mask = RTC_IRQMASK & ~RTC_AIE; |
770 | else | 825 | else |
771 | tmp &= ~(RTC_PIE|RTC_AIE|RTC_UIE); | 826 | mask = RTC_IRQMASK; |
827 | tmp &= ~mask; | ||
772 | CMOS_WRITE(tmp, RTC_CONTROL); | 828 | CMOS_WRITE(tmp, RTC_CONTROL); |
829 | hpet_mask_rtc_irq_bit(mask); | ||
830 | |||
773 | irqstat = CMOS_READ(RTC_INTR_FLAGS); | 831 | irqstat = CMOS_READ(RTC_INTR_FLAGS); |
774 | irqstat &= (tmp & RTC_IRQMASK) | RTC_IRQF; | 832 | irqstat &= (tmp & RTC_IRQMASK) | RTC_IRQF; |
775 | if (is_intr(irqstat)) | 833 | if (is_intr(irqstat)) |
@@ -799,7 +857,8 @@ static int cmos_resume(struct device *dev) | |||
799 | unsigned char tmp = cmos->suspend_ctrl; | 857 | unsigned char tmp = cmos->suspend_ctrl; |
800 | 858 | ||
801 | /* re-enable any irqs previously active */ | 859 | /* re-enable any irqs previously active */ |
802 | if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) { | 860 | if (tmp & RTC_IRQMASK) { |
861 | unsigned char mask; | ||
803 | 862 | ||
804 | if (cmos->enabled_wake) { | 863 | if (cmos->enabled_wake) { |
805 | if (cmos->wake_off) | 864 | if (cmos->wake_off) |
@@ -810,18 +869,28 @@ static int cmos_resume(struct device *dev) | |||
810 | } | 869 | } |
811 | 870 | ||
812 | spin_lock_irq(&rtc_lock); | 871 | spin_lock_irq(&rtc_lock); |
813 | CMOS_WRITE(tmp, RTC_CONTROL); | 872 | do { |
814 | tmp = CMOS_READ(RTC_INTR_FLAGS); | 873 | CMOS_WRITE(tmp, RTC_CONTROL); |
815 | tmp &= (cmos->suspend_ctrl & RTC_IRQMASK) | RTC_IRQF; | 874 | hpet_set_rtc_irq_bit(tmp & RTC_IRQMASK); |
816 | if (is_intr(tmp)) | 875 | |
817 | rtc_update_irq(cmos->rtc, 1, tmp); | 876 | mask = CMOS_READ(RTC_INTR_FLAGS); |
877 | mask &= (tmp & RTC_IRQMASK) | RTC_IRQF; | ||
878 | if (!is_intr(mask)) | ||
879 | break; | ||
880 | |||
881 | /* force one-shot behavior if HPET blocked | ||
882 | * the wake alarm's irq | ||
883 | */ | ||
884 | rtc_update_irq(cmos->rtc, 1, mask); | ||
885 | tmp &= ~RTC_AIE; | ||
886 | hpet_mask_rtc_irq_bit(RTC_AIE); | ||
887 | } while (mask & RTC_AIE); | ||
818 | spin_unlock_irq(&rtc_lock); | 888 | spin_unlock_irq(&rtc_lock); |
819 | } | 889 | } |
820 | 890 | ||
821 | pr_debug("%s: resume, ctrl %02x\n", | 891 | pr_debug("%s: resume, ctrl %02x\n", |
822 | cmos_rtc.rtc->dev.bus_id, | 892 | cmos_rtc.rtc->dev.bus_id, |
823 | cmos->suspend_ctrl); | 893 | tmp); |
824 | |||
825 | 894 | ||
826 | return 0; | 895 | return 0; |
827 | } | 896 | } |