diff options
Diffstat (limited to 'drivers/rtc')
40 files changed, 1001 insertions, 264 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index ce2aabf5c550..53eb4e55b289 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -8,7 +8,7 @@ config RTC_LIB | |||
8 | menuconfig RTC_CLASS | 8 | menuconfig RTC_CLASS |
9 | bool "Real Time Clock" | 9 | bool "Real Time Clock" |
10 | default n | 10 | default n |
11 | depends on !S390 | 11 | depends on !S390 && !UML |
12 | select RTC_LIB | 12 | select RTC_LIB |
13 | help | 13 | help |
14 | Generic RTC class support. If you say yes here, you will | 14 | Generic RTC class support. If you say yes here, you will |
@@ -981,11 +981,11 @@ config RTC_DRV_COH901331 | |||
981 | 981 | ||
982 | 982 | ||
983 | config RTC_DRV_STMP | 983 | config RTC_DRV_STMP |
984 | tristate "Freescale STMP3xxx RTC" | 984 | tristate "Freescale STMP3xxx/i.MX23/i.MX28 RTC" |
985 | depends on ARCH_STMP3XXX | 985 | depends on ARCH_MXS |
986 | help | 986 | help |
987 | If you say yes here you will get support for the onboard | 987 | If you say yes here you will get support for the onboard |
988 | STMP3xxx RTC. | 988 | STMP3xxx/i.MX23/i.MX28 RTC. |
989 | 989 | ||
990 | This driver can also be built as a module. If so, the module | 990 | This driver can also be built as a module. If so, the module |
991 | will be called rtc-stmp3xxx. | 991 | will be called rtc-stmp3xxx. |
@@ -1006,10 +1006,10 @@ config RTC_DRV_MC13XXX | |||
1006 | 1006 | ||
1007 | config RTC_DRV_MPC5121 | 1007 | config RTC_DRV_MPC5121 |
1008 | tristate "Freescale MPC5121 built-in RTC" | 1008 | tristate "Freescale MPC5121 built-in RTC" |
1009 | depends on PPC_MPC512x && RTC_CLASS | 1009 | depends on PPC_MPC512x || PPC_MPC52xx |
1010 | help | 1010 | help |
1011 | If you say yes here you will get support for the | 1011 | If you say yes here you will get support for the |
1012 | built-in RTC MPC5121. | 1012 | built-in RTC on MPC5121 or on MPC5200. |
1013 | 1013 | ||
1014 | This driver can also be built as a module. If so, the module | 1014 | This driver can also be built as a module. If so, the module |
1015 | will be called rtc-mpc5121. | 1015 | will be called rtc-mpc5121. |
@@ -1034,6 +1034,16 @@ config RTC_DRV_LPC32XX | |||
1034 | This driver can also be buillt as a module. If so, the module | 1034 | This driver can also be buillt as a module. If so, the module |
1035 | will be called rtc-lpc32xx. | 1035 | will be called rtc-lpc32xx. |
1036 | 1036 | ||
1037 | config RTC_DRV_PM8XXX | ||
1038 | tristate "Qualcomm PMIC8XXX RTC" | ||
1039 | depends on MFD_PM8XXX | ||
1040 | help | ||
1041 | If you say yes here you get support for the | ||
1042 | Qualcomm PMIC8XXX RTC. | ||
1043 | |||
1044 | To compile this driver as a module, choose M here: the | ||
1045 | module will be called rtc-pm8xxx. | ||
1046 | |||
1037 | config RTC_DRV_TEGRA | 1047 | config RTC_DRV_TEGRA |
1038 | tristate "NVIDIA Tegra Internal RTC driver" | 1048 | tristate "NVIDIA Tegra Internal RTC driver" |
1039 | depends on RTC_CLASS && ARCH_TEGRA | 1049 | depends on RTC_CLASS && ARCH_TEGRA |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 0ffefe877bfa..6e6982335c10 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -77,6 +77,7 @@ obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o | |||
77 | obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o | 77 | obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o |
78 | obj-$(CONFIG_RTC_DRV_PL030) += rtc-pl030.o | 78 | obj-$(CONFIG_RTC_DRV_PL030) += rtc-pl030.o |
79 | obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o | 79 | obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o |
80 | obj-$(CONFIG_RTC_DRV_PM8XXX) += rtc-pm8xxx.o | ||
80 | obj-$(CONFIG_RTC_DRV_PS3) += rtc-ps3.o | 81 | obj-$(CONFIG_RTC_DRV_PS3) += rtc-ps3.o |
81 | obj-$(CONFIG_RTC_DRV_PUV3) += rtc-puv3.o | 82 | obj-$(CONFIG_RTC_DRV_PUV3) += rtc-puv3.o |
82 | obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o | 83 | obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o |
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 4194e59e14cd..e8326f26fa2f 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c | |||
@@ -21,16 +21,13 @@ | |||
21 | #include "rtc-core.h" | 21 | #include "rtc-core.h" |
22 | 22 | ||
23 | 23 | ||
24 | static DEFINE_IDR(rtc_idr); | 24 | static DEFINE_IDA(rtc_ida); |
25 | static DEFINE_MUTEX(idr_lock); | ||
26 | struct class *rtc_class; | 25 | struct class *rtc_class; |
27 | 26 | ||
28 | static void rtc_device_release(struct device *dev) | 27 | static void rtc_device_release(struct device *dev) |
29 | { | 28 | { |
30 | struct rtc_device *rtc = to_rtc_device(dev); | 29 | struct rtc_device *rtc = to_rtc_device(dev); |
31 | mutex_lock(&idr_lock); | 30 | ida_simple_remove(&rtc_ida, rtc->id); |
32 | idr_remove(&rtc_idr, rtc->id); | ||
33 | mutex_unlock(&idr_lock); | ||
34 | kfree(rtc); | 31 | kfree(rtc); |
35 | } | 32 | } |
36 | 33 | ||
@@ -41,20 +38,41 @@ static void rtc_device_release(struct device *dev) | |||
41 | * system's wall clock; restore it on resume(). | 38 | * system's wall clock; restore it on resume(). |
42 | */ | 39 | */ |
43 | 40 | ||
44 | static time_t oldtime; | 41 | static struct timespec old_rtc, old_system, old_delta; |
45 | static struct timespec oldts; | 42 | |
46 | 43 | ||
47 | static int rtc_suspend(struct device *dev, pm_message_t mesg) | 44 | static int rtc_suspend(struct device *dev, pm_message_t mesg) |
48 | { | 45 | { |
49 | struct rtc_device *rtc = to_rtc_device(dev); | 46 | struct rtc_device *rtc = to_rtc_device(dev); |
50 | struct rtc_time tm; | 47 | struct rtc_time tm; |
51 | 48 | struct timespec delta, delta_delta; | |
52 | if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0) | 49 | if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0) |
53 | return 0; | 50 | return 0; |
54 | 51 | ||
52 | /* snapshot the current RTC and system time at suspend*/ | ||
55 | rtc_read_time(rtc, &tm); | 53 | rtc_read_time(rtc, &tm); |
56 | ktime_get_ts(&oldts); | 54 | getnstimeofday(&old_system); |
57 | rtc_tm_to_time(&tm, &oldtime); | 55 | rtc_tm_to_time(&tm, &old_rtc.tv_sec); |
56 | |||
57 | |||
58 | /* | ||
59 | * To avoid drift caused by repeated suspend/resumes, | ||
60 | * which each can add ~1 second drift error, | ||
61 | * try to compensate so the difference in system time | ||
62 | * and rtc time stays close to constant. | ||
63 | */ | ||
64 | delta = timespec_sub(old_system, old_rtc); | ||
65 | delta_delta = timespec_sub(delta, old_delta); | ||
66 | if (abs(delta_delta.tv_sec) >= 2) { | ||
67 | /* | ||
68 | * if delta_delta is too large, assume time correction | ||
69 | * has occured and set old_delta to the current delta. | ||
70 | */ | ||
71 | old_delta = delta; | ||
72 | } else { | ||
73 | /* Otherwise try to adjust old_system to compensate */ | ||
74 | old_system = timespec_sub(old_system, delta_delta); | ||
75 | } | ||
58 | 76 | ||
59 | return 0; | 77 | return 0; |
60 | } | 78 | } |
@@ -63,32 +81,42 @@ static int rtc_resume(struct device *dev) | |||
63 | { | 81 | { |
64 | struct rtc_device *rtc = to_rtc_device(dev); | 82 | struct rtc_device *rtc = to_rtc_device(dev); |
65 | struct rtc_time tm; | 83 | struct rtc_time tm; |
66 | time_t newtime; | 84 | struct timespec new_system, new_rtc; |
67 | struct timespec time; | 85 | struct timespec sleep_time; |
68 | struct timespec newts; | ||
69 | 86 | ||
70 | if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0) | 87 | if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0) |
71 | return 0; | 88 | return 0; |
72 | 89 | ||
73 | ktime_get_ts(&newts); | 90 | /* snapshot the current rtc and system time at resume */ |
91 | getnstimeofday(&new_system); | ||
74 | rtc_read_time(rtc, &tm); | 92 | rtc_read_time(rtc, &tm); |
75 | if (rtc_valid_tm(&tm) != 0) { | 93 | if (rtc_valid_tm(&tm) != 0) { |
76 | pr_debug("%s: bogus resume time\n", dev_name(&rtc->dev)); | 94 | pr_debug("%s: bogus resume time\n", dev_name(&rtc->dev)); |
77 | return 0; | 95 | return 0; |
78 | } | 96 | } |
79 | rtc_tm_to_time(&tm, &newtime); | 97 | rtc_tm_to_time(&tm, &new_rtc.tv_sec); |
80 | if (newtime <= oldtime) { | 98 | new_rtc.tv_nsec = 0; |
81 | if (newtime < oldtime) | 99 | |
100 | if (new_rtc.tv_sec <= old_rtc.tv_sec) { | ||
101 | if (new_rtc.tv_sec < old_rtc.tv_sec) | ||
82 | pr_debug("%s: time travel!\n", dev_name(&rtc->dev)); | 102 | pr_debug("%s: time travel!\n", dev_name(&rtc->dev)); |
83 | return 0; | 103 | return 0; |
84 | } | 104 | } |
85 | /* calculate the RTC time delta */ | ||
86 | set_normalized_timespec(&time, newtime - oldtime, 0); | ||
87 | 105 | ||
88 | /* subtract kernel time between rtc_suspend to rtc_resume */ | 106 | /* calculate the RTC time delta (sleep time)*/ |
89 | time = timespec_sub(time, timespec_sub(newts, oldts)); | 107 | sleep_time = timespec_sub(new_rtc, old_rtc); |
108 | |||
109 | /* | ||
110 | * Since these RTC suspend/resume handlers are not called | ||
111 | * at the very end of suspend or the start of resume, | ||
112 | * some run-time may pass on either sides of the sleep time | ||
113 | * so subtract kernel run-time between rtc_suspend to rtc_resume | ||
114 | * to keep things accurate. | ||
115 | */ | ||
116 | sleep_time = timespec_sub(sleep_time, | ||
117 | timespec_sub(new_system, old_system)); | ||
90 | 118 | ||
91 | timekeeping_inject_sleeptime(&time); | 119 | timekeeping_inject_sleeptime(&sleep_time); |
92 | return 0; | 120 | return 0; |
93 | } | 121 | } |
94 | 122 | ||
@@ -115,25 +143,16 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev, | |||
115 | struct rtc_wkalrm alrm; | 143 | struct rtc_wkalrm alrm; |
116 | int id, err; | 144 | int id, err; |
117 | 145 | ||
118 | if (idr_pre_get(&rtc_idr, GFP_KERNEL) == 0) { | 146 | id = ida_simple_get(&rtc_ida, 0, 0, GFP_KERNEL); |
119 | err = -ENOMEM; | 147 | if (id < 0) { |
148 | err = id; | ||
120 | goto exit; | 149 | goto exit; |
121 | } | 150 | } |
122 | 151 | ||
123 | |||
124 | mutex_lock(&idr_lock); | ||
125 | err = idr_get_new(&rtc_idr, NULL, &id); | ||
126 | mutex_unlock(&idr_lock); | ||
127 | |||
128 | if (err < 0) | ||
129 | goto exit; | ||
130 | |||
131 | id = id & MAX_ID_MASK; | ||
132 | |||
133 | rtc = kzalloc(sizeof(struct rtc_device), GFP_KERNEL); | 152 | rtc = kzalloc(sizeof(struct rtc_device), GFP_KERNEL); |
134 | if (rtc == NULL) { | 153 | if (rtc == NULL) { |
135 | err = -ENOMEM; | 154 | err = -ENOMEM; |
136 | goto exit_idr; | 155 | goto exit_ida; |
137 | } | 156 | } |
138 | 157 | ||
139 | rtc->id = id; | 158 | rtc->id = id; |
@@ -191,10 +210,8 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev, | |||
191 | exit_kfree: | 210 | exit_kfree: |
192 | kfree(rtc); | 211 | kfree(rtc); |
193 | 212 | ||
194 | exit_idr: | 213 | exit_ida: |
195 | mutex_lock(&idr_lock); | 214 | ida_simple_remove(&rtc_ida, id); |
196 | idr_remove(&rtc_idr, id); | ||
197 | mutex_unlock(&idr_lock); | ||
198 | 215 | ||
199 | exit: | 216 | exit: |
200 | dev_err(dev, "rtc core: unable to register %s, err = %d\n", | 217 | dev_err(dev, "rtc core: unable to register %s, err = %d\n", |
@@ -245,7 +262,7 @@ static void __exit rtc_exit(void) | |||
245 | { | 262 | { |
246 | rtc_dev_exit(); | 263 | rtc_dev_exit(); |
247 | class_destroy(rtc_class); | 264 | class_destroy(rtc_class); |
248 | idr_destroy(&rtc_idr); | 265 | ida_destroy(&rtc_ida); |
249 | } | 266 | } |
250 | 267 | ||
251 | subsys_initcall(rtc_init); | 268 | subsys_initcall(rtc_init); |
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index df68618f6dbb..8e286259a007 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c | |||
@@ -13,6 +13,7 @@ | |||
13 | 13 | ||
14 | #include <linux/rtc.h> | 14 | #include <linux/rtc.h> |
15 | #include <linux/sched.h> | 15 | #include <linux/sched.h> |
16 | #include <linux/module.h> | ||
16 | #include <linux/log2.h> | 17 | #include <linux/log2.h> |
17 | #include <linux/workqueue.h> | 18 | #include <linux/workqueue.h> |
18 | 19 | ||
@@ -636,6 +637,29 @@ void rtc_irq_unregister(struct rtc_device *rtc, struct rtc_task *task) | |||
636 | } | 637 | } |
637 | EXPORT_SYMBOL_GPL(rtc_irq_unregister); | 638 | EXPORT_SYMBOL_GPL(rtc_irq_unregister); |
638 | 639 | ||
640 | static int rtc_update_hrtimer(struct rtc_device *rtc, int enabled) | ||
641 | { | ||
642 | /* | ||
643 | * We always cancel the timer here first, because otherwise | ||
644 | * we could run into BUG_ON(timer->state != HRTIMER_STATE_CALLBACK); | ||
645 | * when we manage to start the timer before the callback | ||
646 | * returns HRTIMER_RESTART. | ||
647 | * | ||
648 | * We cannot use hrtimer_cancel() here as a running callback | ||
649 | * could be blocked on rtc->irq_task_lock and hrtimer_cancel() | ||
650 | * would spin forever. | ||
651 | */ | ||
652 | if (hrtimer_try_to_cancel(&rtc->pie_timer) < 0) | ||
653 | return -1; | ||
654 | |||
655 | if (enabled) { | ||
656 | ktime_t period = ktime_set(0, NSEC_PER_SEC / rtc->irq_freq); | ||
657 | |||
658 | hrtimer_start(&rtc->pie_timer, period, HRTIMER_MODE_REL); | ||
659 | } | ||
660 | return 0; | ||
661 | } | ||
662 | |||
639 | /** | 663 | /** |
640 | * rtc_irq_set_state - enable/disable 2^N Hz periodic IRQs | 664 | * rtc_irq_set_state - enable/disable 2^N Hz periodic IRQs |
641 | * @rtc: the rtc device | 665 | * @rtc: the rtc device |
@@ -651,21 +675,21 @@ int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled | |||
651 | int err = 0; | 675 | int err = 0; |
652 | unsigned long flags; | 676 | unsigned long flags; |
653 | 677 | ||
678 | retry: | ||
654 | spin_lock_irqsave(&rtc->irq_task_lock, flags); | 679 | spin_lock_irqsave(&rtc->irq_task_lock, flags); |
655 | if (rtc->irq_task != NULL && task == NULL) | 680 | if (rtc->irq_task != NULL && task == NULL) |
656 | err = -EBUSY; | 681 | err = -EBUSY; |
657 | if (rtc->irq_task != task) | 682 | if (rtc->irq_task != task) |
658 | err = -EACCES; | 683 | err = -EACCES; |
659 | 684 | if (!err) { | |
660 | if (enabled) { | 685 | if (rtc_update_hrtimer(rtc, enabled) < 0) { |
661 | ktime_t period = ktime_set(0, NSEC_PER_SEC/rtc->irq_freq); | 686 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); |
662 | hrtimer_start(&rtc->pie_timer, period, HRTIMER_MODE_REL); | 687 | cpu_relax(); |
663 | } else { | 688 | goto retry; |
664 | hrtimer_cancel(&rtc->pie_timer); | 689 | } |
690 | rtc->pie_enabled = enabled; | ||
665 | } | 691 | } |
666 | rtc->pie_enabled = enabled; | ||
667 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); | 692 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); |
668 | |||
669 | return err; | 693 | return err; |
670 | } | 694 | } |
671 | EXPORT_SYMBOL_GPL(rtc_irq_set_state); | 695 | EXPORT_SYMBOL_GPL(rtc_irq_set_state); |
@@ -685,22 +709,20 @@ int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq) | |||
685 | int err = 0; | 709 | int err = 0; |
686 | unsigned long flags; | 710 | unsigned long flags; |
687 | 711 | ||
688 | if (freq <= 0) | 712 | if (freq <= 0 || freq > RTC_MAX_FREQ) |
689 | return -EINVAL; | 713 | return -EINVAL; |
690 | 714 | retry: | |
691 | spin_lock_irqsave(&rtc->irq_task_lock, flags); | 715 | spin_lock_irqsave(&rtc->irq_task_lock, flags); |
692 | if (rtc->irq_task != NULL && task == NULL) | 716 | if (rtc->irq_task != NULL && task == NULL) |
693 | err = -EBUSY; | 717 | err = -EBUSY; |
694 | if (rtc->irq_task != task) | 718 | if (rtc->irq_task != task) |
695 | err = -EACCES; | 719 | err = -EACCES; |
696 | if (err == 0) { | 720 | if (!err) { |
697 | rtc->irq_freq = freq; | 721 | rtc->irq_freq = freq; |
698 | if (rtc->pie_enabled) { | 722 | if (rtc->pie_enabled && rtc_update_hrtimer(rtc, 1) < 0) { |
699 | ktime_t period; | 723 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); |
700 | hrtimer_cancel(&rtc->pie_timer); | 724 | cpu_relax(); |
701 | period = ktime_set(0, NSEC_PER_SEC/rtc->irq_freq); | 725 | goto retry; |
702 | hrtimer_start(&rtc->pie_timer, period, | ||
703 | HRTIMER_MODE_REL); | ||
704 | } | 726 | } |
705 | } | 727 | } |
706 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); | 728 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); |
diff --git a/drivers/rtc/rtc-at32ap700x.c b/drivers/rtc/rtc-at32ap700x.c index e725d51e773d..8dd08305aae1 100644 --- a/drivers/rtc/rtc-at32ap700x.c +++ b/drivers/rtc/rtc-at32ap700x.c | |||
@@ -223,7 +223,7 @@ static int __init at32_rtc_probe(struct platform_device *pdev) | |||
223 | } | 223 | } |
224 | 224 | ||
225 | rtc->irq = irq; | 225 | rtc->irq = irq; |
226 | rtc->regs = ioremap(regs->start, regs->end - regs->start + 1); | 226 | rtc->regs = ioremap(regs->start, resource_size(regs)); |
227 | if (!rtc->regs) { | 227 | if (!rtc->regs) { |
228 | ret = -ENOMEM; | 228 | ret = -ENOMEM; |
229 | dev_dbg(&pdev->dev, "could not map I/O memory\n"); | 229 | dev_dbg(&pdev->dev, "could not map I/O memory\n"); |
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 911e75cdc125..05beb6c1ca79 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
@@ -606,7 +606,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
606 | * (needing ioremap etc), not i/o space resources like this ... | 606 | * (needing ioremap etc), not i/o space resources like this ... |
607 | */ | 607 | */ |
608 | ports = request_region(ports->start, | 608 | ports = request_region(ports->start, |
609 | ports->end + 1 - ports->start, | 609 | resource_size(ports), |
610 | driver_name); | 610 | driver_name); |
611 | if (!ports) { | 611 | if (!ports) { |
612 | dev_dbg(dev, "i/o registers already in use\n"); | 612 | dev_dbg(dev, "i/o registers already in use\n"); |
@@ -750,7 +750,7 @@ cleanup1: | |||
750 | cmos_rtc.dev = NULL; | 750 | cmos_rtc.dev = NULL; |
751 | rtc_device_unregister(cmos_rtc.rtc); | 751 | rtc_device_unregister(cmos_rtc.rtc); |
752 | cleanup0: | 752 | cleanup0: |
753 | release_region(ports->start, ports->end + 1 - ports->start); | 753 | release_region(ports->start, resource_size(ports)); |
754 | return retval; | 754 | return retval; |
755 | } | 755 | } |
756 | 756 | ||
@@ -779,7 +779,7 @@ static void __exit cmos_do_remove(struct device *dev) | |||
779 | cmos->rtc = NULL; | 779 | cmos->rtc = NULL; |
780 | 780 | ||
781 | ports = cmos->iomem; | 781 | ports = cmos->iomem; |
782 | release_region(ports->start, ports->end + 1 - ports->start); | 782 | release_region(ports->start, resource_size(ports)); |
783 | cmos->iomem = NULL; | 783 | cmos->iomem = NULL; |
784 | 784 | ||
785 | cmos->dev = NULL; | 785 | cmos->dev = NULL; |
diff --git a/drivers/rtc/rtc-dm355evm.c b/drivers/rtc/rtc-dm355evm.c index 58d4e18530da..2322c43af201 100644 --- a/drivers/rtc/rtc-dm355evm.c +++ b/drivers/rtc/rtc-dm355evm.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | 15 | ||
16 | #include <linux/i2c/dm355evm_msp.h> | 16 | #include <linux/i2c/dm355evm_msp.h> |
17 | #include <linux/module.h> | ||
17 | 18 | ||
18 | 19 | ||
19 | /* | 20 | /* |
diff --git a/drivers/rtc/rtc-ds1286.c b/drivers/rtc/rtc-ds1286.c index 47e681df31e2..68e6caf25496 100644 --- a/drivers/rtc/rtc-ds1286.c +++ b/drivers/rtc/rtc-ds1286.c | |||
@@ -343,7 +343,7 @@ static int __devinit ds1286_probe(struct platform_device *pdev) | |||
343 | if (!priv) | 343 | if (!priv) |
344 | return -ENOMEM; | 344 | return -ENOMEM; |
345 | 345 | ||
346 | priv->size = res->end - res->start + 1; | 346 | priv->size = resource_size(res); |
347 | if (!request_mem_region(res->start, priv->size, pdev->name)) { | 347 | if (!request_mem_region(res->start, priv->size, pdev->name)) { |
348 | ret = -EBUSY; | 348 | ret = -EBUSY; |
349 | goto out; | 349 | goto out; |
diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index 57fbcc149ba7..3a33b1fdbe0f 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c | |||
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | #include <linux/spi/spi.h> | 18 | #include <linux/spi/spi.h> |
19 | #include <linux/spi/ds1305.h> | 19 | #include <linux/spi/ds1305.h> |
20 | #include <linux/module.h> | ||
20 | 21 | ||
21 | 22 | ||
22 | /* | 23 | /* |
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index b2005b44e4f7..62b0763b7b9a 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c | |||
@@ -34,6 +34,7 @@ enum ds_type { | |||
34 | ds_1388, | 34 | ds_1388, |
35 | ds_3231, | 35 | ds_3231, |
36 | m41t00, | 36 | m41t00, |
37 | mcp7941x, | ||
37 | rx_8025, | 38 | rx_8025, |
38 | // rs5c372 too? different address... | 39 | // rs5c372 too? different address... |
39 | }; | 40 | }; |
@@ -43,6 +44,7 @@ enum ds_type { | |||
43 | #define DS1307_REG_SECS 0x00 /* 00-59 */ | 44 | #define DS1307_REG_SECS 0x00 /* 00-59 */ |
44 | # define DS1307_BIT_CH 0x80 | 45 | # define DS1307_BIT_CH 0x80 |
45 | # define DS1340_BIT_nEOSC 0x80 | 46 | # define DS1340_BIT_nEOSC 0x80 |
47 | # define MCP7941X_BIT_ST 0x80 | ||
46 | #define DS1307_REG_MIN 0x01 /* 00-59 */ | 48 | #define DS1307_REG_MIN 0x01 /* 00-59 */ |
47 | #define DS1307_REG_HOUR 0x02 /* 00-23, or 1-12{am,pm} */ | 49 | #define DS1307_REG_HOUR 0x02 /* 00-23, or 1-12{am,pm} */ |
48 | # define DS1307_BIT_12HR 0x40 /* in REG_HOUR */ | 50 | # define DS1307_BIT_12HR 0x40 /* in REG_HOUR */ |
@@ -50,6 +52,7 @@ enum ds_type { | |||
50 | # define DS1340_BIT_CENTURY_EN 0x80 /* in REG_HOUR */ | 52 | # define DS1340_BIT_CENTURY_EN 0x80 /* in REG_HOUR */ |
51 | # define DS1340_BIT_CENTURY 0x40 /* in REG_HOUR */ | 53 | # define DS1340_BIT_CENTURY 0x40 /* in REG_HOUR */ |
52 | #define DS1307_REG_WDAY 0x03 /* 01-07 */ | 54 | #define DS1307_REG_WDAY 0x03 /* 01-07 */ |
55 | # define MCP7941X_BIT_VBATEN 0x08 | ||
53 | #define DS1307_REG_MDAY 0x04 /* 01-31 */ | 56 | #define DS1307_REG_MDAY 0x04 /* 01-31 */ |
54 | #define DS1307_REG_MONTH 0x05 /* 01-12 */ | 57 | #define DS1307_REG_MONTH 0x05 /* 01-12 */ |
55 | # define DS1337_BIT_CENTURY 0x80 /* in REG_MONTH */ | 58 | # define DS1337_BIT_CENTURY 0x80 /* in REG_MONTH */ |
@@ -137,6 +140,8 @@ static const struct chip_desc chips[] = { | |||
137 | }, | 140 | }, |
138 | [m41t00] = { | 141 | [m41t00] = { |
139 | }, | 142 | }, |
143 | [mcp7941x] = { | ||
144 | }, | ||
140 | [rx_8025] = { | 145 | [rx_8025] = { |
141 | }, }; | 146 | }, }; |
142 | 147 | ||
@@ -149,6 +154,7 @@ static const struct i2c_device_id ds1307_id[] = { | |||
149 | { "ds1340", ds_1340 }, | 154 | { "ds1340", ds_1340 }, |
150 | { "ds3231", ds_3231 }, | 155 | { "ds3231", ds_3231 }, |
151 | { "m41t00", m41t00 }, | 156 | { "m41t00", m41t00 }, |
157 | { "mcp7941x", mcp7941x }, | ||
152 | { "pt7c4338", ds_1307 }, | 158 | { "pt7c4338", ds_1307 }, |
153 | { "rx8025", rx_8025 }, | 159 | { "rx8025", rx_8025 }, |
154 | { } | 160 | { } |
@@ -365,6 +371,10 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t) | |||
365 | buf[DS1307_REG_HOUR] |= DS1340_BIT_CENTURY_EN | 371 | buf[DS1307_REG_HOUR] |= DS1340_BIT_CENTURY_EN |
366 | | DS1340_BIT_CENTURY; | 372 | | DS1340_BIT_CENTURY; |
367 | break; | 373 | break; |
374 | case mcp7941x: | ||
375 | buf[DS1307_REG_SECS] |= MCP7941X_BIT_ST; | ||
376 | buf[DS1307_REG_WDAY] |= MCP7941X_BIT_VBATEN; | ||
377 | break; | ||
368 | default: | 378 | default: |
369 | break; | 379 | break; |
370 | } | 380 | } |
@@ -809,6 +819,23 @@ read_rtc: | |||
809 | dev_warn(&client->dev, "SET TIME!\n"); | 819 | dev_warn(&client->dev, "SET TIME!\n"); |
810 | } | 820 | } |
811 | break; | 821 | break; |
822 | case mcp7941x: | ||
823 | /* make sure that the backup battery is enabled */ | ||
824 | if (!(ds1307->regs[DS1307_REG_WDAY] & MCP7941X_BIT_VBATEN)) { | ||
825 | i2c_smbus_write_byte_data(client, DS1307_REG_WDAY, | ||
826 | ds1307->regs[DS1307_REG_WDAY] | ||
827 | | MCP7941X_BIT_VBATEN); | ||
828 | } | ||
829 | |||
830 | /* clock halted? turn it on, so clock can tick. */ | ||
831 | if (!(tmp & MCP7941X_BIT_ST)) { | ||
832 | i2c_smbus_write_byte_data(client, DS1307_REG_SECS, | ||
833 | MCP7941X_BIT_ST); | ||
834 | dev_warn(&client->dev, "SET TIME!\n"); | ||
835 | goto read_rtc; | ||
836 | } | ||
837 | |||
838 | break; | ||
812 | case rx_8025: | 839 | case rx_8025: |
813 | case ds_1337: | 840 | case ds_1337: |
814 | case ds_1339: | 841 | case ds_1339: |
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index fbabc773dded..586c244a05d8 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/rtc.h> | 23 | #include <linux/rtc.h> |
24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
26 | #include <linux/module.h> | ||
26 | 27 | ||
27 | #define DRV_VERSION "0.6" | 28 | #define DRV_VERSION "0.6" |
28 | 29 | ||
@@ -490,7 +491,7 @@ ds1511_rtc_probe(struct platform_device *pdev) | |||
490 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | 491 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
491 | if (!pdata) | 492 | if (!pdata) |
492 | return -ENOMEM; | 493 | return -ENOMEM; |
493 | pdata->size = res->end - res->start + 1; | 494 | pdata->size = resource_size(res); |
494 | if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size, | 495 | if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size, |
495 | pdev->name)) | 496 | pdev->name)) |
496 | return -EBUSY; | 497 | return -EBUSY; |
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index fee41b97c9e8..1350029044e6 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/rtc.h> | 18 | #include <linux/rtc.h> |
19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/module.h> | ||
21 | 22 | ||
22 | #define DRV_VERSION "0.3" | 23 | #define DRV_VERSION "0.3" |
23 | 24 | ||
diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c index 06dfb54f99b6..a319402a5447 100644 --- a/drivers/rtc/rtc-ds1672.c +++ b/drivers/rtc/rtc-ds1672.c | |||
@@ -11,6 +11,7 @@ | |||
11 | 11 | ||
12 | #include <linux/i2c.h> | 12 | #include <linux/i2c.h> |
13 | #include <linux/rtc.h> | 13 | #include <linux/rtc.h> |
14 | #include <linux/module.h> | ||
14 | 15 | ||
15 | #define DRV_VERSION "0.4" | 16 | #define DRV_VERSION "0.4" |
16 | 17 | ||
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index 042630c90dd3..e3e0f92b60f0 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/rtc.h> | 21 | #include <linux/rtc.h> |
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/module.h> | ||
24 | 25 | ||
25 | #define DRV_VERSION "0.4" | 26 | #define DRV_VERSION "0.4" |
26 | 27 | ||
@@ -173,7 +174,7 @@ static int __devinit ds1742_rtc_probe(struct platform_device *pdev) | |||
173 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | 174 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
174 | if (!pdata) | 175 | if (!pdata) |
175 | return -ENOMEM; | 176 | return -ENOMEM; |
176 | pdata->size = res->end - res->start + 1; | 177 | pdata->size = resource_size(res); |
177 | if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size, | 178 | if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size, |
178 | pdev->name)) | 179 | pdev->name)) |
179 | return -EBUSY; | 180 | return -EBUSY; |
diff --git a/drivers/rtc/rtc-em3027.c b/drivers/rtc/rtc-em3027.c index d8e1c2578553..8414dea5fb14 100644 --- a/drivers/rtc/rtc-em3027.c +++ b/drivers/rtc/rtc-em3027.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/i2c.h> | 14 | #include <linux/i2c.h> |
15 | #include <linux/rtc.h> | 15 | #include <linux/rtc.h> |
16 | #include <linux/bcd.h> | 16 | #include <linux/bcd.h> |
17 | #include <linux/module.h> | ||
17 | 18 | ||
18 | /* Registers */ | 19 | /* Registers */ |
19 | #define EM3027_REG_ON_OFF_CTRL 0x00 | 20 | #define EM3027_REG_ON_OFF_CTRL 0x00 |
diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c index 335551d333b2..14a42a1edc66 100644 --- a/drivers/rtc/rtc-ep93xx.c +++ b/drivers/rtc/rtc-ep93xx.c | |||
@@ -36,6 +36,7 @@ | |||
36 | */ | 36 | */ |
37 | struct ep93xx_rtc { | 37 | struct ep93xx_rtc { |
38 | void __iomem *mmio_base; | 38 | void __iomem *mmio_base; |
39 | struct rtc_device *rtc; | ||
39 | }; | 40 | }; |
40 | 41 | ||
41 | static int ep93xx_rtc_get_swcomp(struct device *dev, unsigned short *preload, | 42 | static int ep93xx_rtc_get_swcomp(struct device *dev, unsigned short *preload, |
@@ -130,7 +131,6 @@ static int __init ep93xx_rtc_probe(struct platform_device *pdev) | |||
130 | { | 131 | { |
131 | struct ep93xx_rtc *ep93xx_rtc; | 132 | struct ep93xx_rtc *ep93xx_rtc; |
132 | struct resource *res; | 133 | struct resource *res; |
133 | struct rtc_device *rtc; | ||
134 | int err; | 134 | int err; |
135 | 135 | ||
136 | ep93xx_rtc = devm_kzalloc(&pdev->dev, sizeof(*ep93xx_rtc), GFP_KERNEL); | 136 | ep93xx_rtc = devm_kzalloc(&pdev->dev, sizeof(*ep93xx_rtc), GFP_KERNEL); |
@@ -151,12 +151,12 @@ static int __init ep93xx_rtc_probe(struct platform_device *pdev) | |||
151 | return -ENXIO; | 151 | return -ENXIO; |
152 | 152 | ||
153 | pdev->dev.platform_data = ep93xx_rtc; | 153 | pdev->dev.platform_data = ep93xx_rtc; |
154 | platform_set_drvdata(pdev, rtc); | 154 | platform_set_drvdata(pdev, ep93xx_rtc); |
155 | 155 | ||
156 | rtc = rtc_device_register(pdev->name, | 156 | ep93xx_rtc->rtc = rtc_device_register(pdev->name, |
157 | &pdev->dev, &ep93xx_rtc_ops, THIS_MODULE); | 157 | &pdev->dev, &ep93xx_rtc_ops, THIS_MODULE); |
158 | if (IS_ERR(rtc)) { | 158 | if (IS_ERR(ep93xx_rtc->rtc)) { |
159 | err = PTR_ERR(rtc); | 159 | err = PTR_ERR(ep93xx_rtc->rtc); |
160 | goto exit; | 160 | goto exit; |
161 | } | 161 | } |
162 | 162 | ||
@@ -167,7 +167,7 @@ static int __init ep93xx_rtc_probe(struct platform_device *pdev) | |||
167 | return 0; | 167 | return 0; |
168 | 168 | ||
169 | fail: | 169 | fail: |
170 | rtc_device_unregister(rtc); | 170 | rtc_device_unregister(ep93xx_rtc->rtc); |
171 | exit: | 171 | exit: |
172 | platform_set_drvdata(pdev, NULL); | 172 | platform_set_drvdata(pdev, NULL); |
173 | pdev->dev.platform_data = NULL; | 173 | pdev->dev.platform_data = NULL; |
@@ -176,11 +176,11 @@ exit: | |||
176 | 176 | ||
177 | static int __exit ep93xx_rtc_remove(struct platform_device *pdev) | 177 | static int __exit ep93xx_rtc_remove(struct platform_device *pdev) |
178 | { | 178 | { |
179 | struct rtc_device *rtc = platform_get_drvdata(pdev); | 179 | struct ep93xx_rtc *ep93xx_rtc = platform_get_drvdata(pdev); |
180 | 180 | ||
181 | sysfs_remove_group(&pdev->dev.kobj, &ep93xx_rtc_sysfs_files); | 181 | sysfs_remove_group(&pdev->dev.kobj, &ep93xx_rtc_sysfs_files); |
182 | platform_set_drvdata(pdev, NULL); | 182 | platform_set_drvdata(pdev, NULL); |
183 | rtc_device_unregister(rtc); | 183 | rtc_device_unregister(ep93xx_rtc->rtc); |
184 | pdev->dev.platform_data = NULL; | 184 | pdev->dev.platform_data = NULL; |
185 | 185 | ||
186 | return 0; | 186 | return 0; |
diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c index 2dd3c0163272..d93a9608b1f0 100644 --- a/drivers/rtc/rtc-imxdi.c +++ b/drivers/rtc/rtc-imxdi.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/module.h> | 35 | #include <linux/module.h> |
36 | #include <linux/platform_device.h> | 36 | #include <linux/platform_device.h> |
37 | #include <linux/rtc.h> | 37 | #include <linux/rtc.h> |
38 | #include <linux/sched.h> | ||
38 | #include <linux/workqueue.h> | 39 | #include <linux/workqueue.h> |
39 | 40 | ||
40 | /* DryIce Register Definitions */ | 41 | /* DryIce Register Definitions */ |
diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c index ddbc797ea6cd..6186833973ee 100644 --- a/drivers/rtc/rtc-isl12022.c +++ b/drivers/rtc/rtc-isl12022.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/bcd.h> | 15 | #include <linux/bcd.h> |
16 | #include <linux/rtc.h> | 16 | #include <linux/rtc.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/module.h> | ||
18 | 19 | ||
19 | #define DRV_VERSION "0.1" | 20 | #define DRV_VERSION "0.1" |
20 | 21 | ||
diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c index 075f1708deae..c4cf05731118 100644 --- a/drivers/rtc/rtc-lib.c +++ b/drivers/rtc/rtc-lib.c | |||
@@ -85,6 +85,8 @@ void rtc_time_to_tm(unsigned long time, struct rtc_time *tm) | |||
85 | time -= tm->tm_hour * 3600; | 85 | time -= tm->tm_hour * 3600; |
86 | tm->tm_min = time / 60; | 86 | tm->tm_min = time / 60; |
87 | tm->tm_sec = time - tm->tm_min * 60; | 87 | tm->tm_sec = time - tm->tm_min * 60; |
88 | |||
89 | tm->tm_isdst = 0; | ||
88 | } | 90 | } |
89 | EXPORT_SYMBOL(rtc_time_to_tm); | 91 | EXPORT_SYMBOL(rtc_time_to_tm); |
90 | 92 | ||
diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c index 7410875e5838..8e2a24e33ed6 100644 --- a/drivers/rtc/rtc-m48t35.c +++ b/drivers/rtc/rtc-m48t35.c | |||
@@ -154,7 +154,7 @@ static int __devinit m48t35_probe(struct platform_device *pdev) | |||
154 | if (!priv) | 154 | if (!priv) |
155 | return -ENOMEM; | 155 | return -ENOMEM; |
156 | 156 | ||
157 | priv->size = res->end - res->start + 1; | 157 | priv->size = resource_size(res); |
158 | /* | 158 | /* |
159 | * kludge: remove the #ifndef after ioc3 resource | 159 | * kludge: remove the #ifndef after ioc3 resource |
160 | * conflicts are resolved | 160 | * conflicts are resolved |
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index 3978f4caf724..28365388fb6c 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c | |||
@@ -433,7 +433,7 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | |||
433 | 433 | ||
434 | if (!m48t59->ioaddr) { | 434 | if (!m48t59->ioaddr) { |
435 | /* ioaddr not mapped externally */ | 435 | /* ioaddr not mapped externally */ |
436 | m48t59->ioaddr = ioremap(res->start, res->end - res->start + 1); | 436 | m48t59->ioaddr = ioremap(res->start, resource_size(res)); |
437 | if (!m48t59->ioaddr) | 437 | if (!m48t59->ioaddr) |
438 | goto out; | 438 | goto out; |
439 | } | 439 | } |
diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c index a1a278bc340d..9d0c3b478d55 100644 --- a/drivers/rtc/rtc-mc13xxx.c +++ b/drivers/rtc/rtc-mc13xxx.c | |||
@@ -309,7 +309,7 @@ static irqreturn_t mc13xxx_rtc_reset_handler(int irq, void *dev) | |||
309 | return IRQ_HANDLED; | 309 | return IRQ_HANDLED; |
310 | } | 310 | } |
311 | 311 | ||
312 | static int __devinit mc13xxx_rtc_probe(struct platform_device *pdev) | 312 | static int __init mc13xxx_rtc_probe(struct platform_device *pdev) |
313 | { | 313 | { |
314 | int ret; | 314 | int ret; |
315 | struct mc13xxx_rtc *priv; | 315 | struct mc13xxx_rtc *priv; |
@@ -378,7 +378,7 @@ err_reset_irq_request: | |||
378 | return ret; | 378 | return ret; |
379 | } | 379 | } |
380 | 380 | ||
381 | static int __devexit mc13xxx_rtc_remove(struct platform_device *pdev) | 381 | static int __exit mc13xxx_rtc_remove(struct platform_device *pdev) |
382 | { | 382 | { |
383 | struct mc13xxx_rtc *priv = platform_get_drvdata(pdev); | 383 | struct mc13xxx_rtc *priv = platform_get_drvdata(pdev); |
384 | 384 | ||
@@ -410,7 +410,7 @@ const struct platform_device_id mc13xxx_rtc_idtable[] = { | |||
410 | 410 | ||
411 | static struct platform_driver mc13xxx_rtc_driver = { | 411 | static struct platform_driver mc13xxx_rtc_driver = { |
412 | .id_table = mc13xxx_rtc_idtable, | 412 | .id_table = mc13xxx_rtc_idtable, |
413 | .remove = __devexit_p(mc13xxx_rtc_remove), | 413 | .remove = __exit_p(mc13xxx_rtc_remove), |
414 | .driver = { | 414 | .driver = { |
415 | .name = DRIVER_NAME, | 415 | .name = DRIVER_NAME, |
416 | .owner = THIS_MODULE, | 416 | .owner = THIS_MODULE, |
diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c index 09ccd8d3ba2a..da60915818b6 100644 --- a/drivers/rtc/rtc-mpc5121.c +++ b/drivers/rtc/rtc-mpc5121.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright 2007, Domen Puncer <domen.puncer@telargo.com> | 4 | * Copyright 2007, Domen Puncer <domen.puncer@telargo.com> |
5 | * Copyright 2008, Freescale Semiconductor, Inc. All rights reserved. | 5 | * Copyright 2008, Freescale Semiconductor, Inc. All rights reserved. |
6 | * Copyright 2011, Dmitry Eremin-Solenikov | ||
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
@@ -145,6 +146,55 @@ static int mpc5121_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
145 | return 0; | 146 | return 0; |
146 | } | 147 | } |
147 | 148 | ||
149 | static int mpc5200_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
150 | { | ||
151 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); | ||
152 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | ||
153 | int tmp; | ||
154 | |||
155 | tm->tm_sec = in_8(®s->second); | ||
156 | tm->tm_min = in_8(®s->minute); | ||
157 | |||
158 | /* 12 hour format? */ | ||
159 | if (in_8(®s->hour) & 0x20) | ||
160 | tm->tm_hour = (in_8(®s->hour) >> 1) + | ||
161 | (in_8(®s->hour) & 1 ? 12 : 0); | ||
162 | else | ||
163 | tm->tm_hour = in_8(®s->hour); | ||
164 | |||
165 | tmp = in_8(®s->wday_mday); | ||
166 | tm->tm_mday = tmp & 0x1f; | ||
167 | tm->tm_mon = in_8(®s->month) - 1; | ||
168 | tm->tm_year = in_be16(®s->year) - 1900; | ||
169 | tm->tm_wday = (tmp >> 5) % 7; | ||
170 | tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); | ||
171 | tm->tm_isdst = 0; | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static int mpc5200_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
177 | { | ||
178 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); | ||
179 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | ||
180 | |||
181 | mpc5121_rtc_update_smh(regs, tm); | ||
182 | |||
183 | /* date */ | ||
184 | out_8(®s->month_set, tm->tm_mon + 1); | ||
185 | out_8(®s->weekday_set, tm->tm_wday ? tm->tm_wday : 7); | ||
186 | out_8(®s->date_set, tm->tm_mday); | ||
187 | out_be16(®s->year_set, tm->tm_year + 1900); | ||
188 | |||
189 | /* set date sequence */ | ||
190 | out_8(®s->set_date, 0x1); | ||
191 | out_8(®s->set_date, 0x3); | ||
192 | out_8(®s->set_date, 0x1); | ||
193 | out_8(®s->set_date, 0x0); | ||
194 | |||
195 | return 0; | ||
196 | } | ||
197 | |||
148 | static int mpc5121_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | 198 | static int mpc5121_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
149 | { | 199 | { |
150 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); | 200 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); |
@@ -248,11 +298,18 @@ static const struct rtc_class_ops mpc5121_rtc_ops = { | |||
248 | .alarm_irq_enable = mpc5121_rtc_alarm_irq_enable, | 298 | .alarm_irq_enable = mpc5121_rtc_alarm_irq_enable, |
249 | }; | 299 | }; |
250 | 300 | ||
301 | static const struct rtc_class_ops mpc5200_rtc_ops = { | ||
302 | .read_time = mpc5200_rtc_read_time, | ||
303 | .set_time = mpc5200_rtc_set_time, | ||
304 | .read_alarm = mpc5121_rtc_read_alarm, | ||
305 | .set_alarm = mpc5121_rtc_set_alarm, | ||
306 | .alarm_irq_enable = mpc5121_rtc_alarm_irq_enable, | ||
307 | }; | ||
308 | |||
251 | static int __devinit mpc5121_rtc_probe(struct platform_device *op) | 309 | static int __devinit mpc5121_rtc_probe(struct platform_device *op) |
252 | { | 310 | { |
253 | struct mpc5121_rtc_data *rtc; | 311 | struct mpc5121_rtc_data *rtc; |
254 | int err = 0; | 312 | int err = 0; |
255 | u32 ka; | ||
256 | 313 | ||
257 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); | 314 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); |
258 | if (!rtc) | 315 | if (!rtc) |
@@ -287,15 +344,22 @@ static int __devinit mpc5121_rtc_probe(struct platform_device *op) | |||
287 | goto out_dispose2; | 344 | goto out_dispose2; |
288 | } | 345 | } |
289 | 346 | ||
290 | ka = in_be32(&rtc->regs->keep_alive); | 347 | if (of_device_is_compatible(op->dev.of_node, "fsl,mpc5121-rtc")) { |
291 | if (ka & 0x02) { | 348 | u32 ka; |
292 | dev_warn(&op->dev, | 349 | ka = in_be32(&rtc->regs->keep_alive); |
293 | "mpc5121-rtc: Battery or oscillator failure!\n"); | 350 | if (ka & 0x02) { |
294 | out_be32(&rtc->regs->keep_alive, ka); | 351 | dev_warn(&op->dev, |
352 | "mpc5121-rtc: Battery or oscillator failure!\n"); | ||
353 | out_be32(&rtc->regs->keep_alive, ka); | ||
354 | } | ||
355 | |||
356 | rtc->rtc = rtc_device_register("mpc5121-rtc", &op->dev, | ||
357 | &mpc5121_rtc_ops, THIS_MODULE); | ||
358 | } else { | ||
359 | rtc->rtc = rtc_device_register("mpc5200-rtc", &op->dev, | ||
360 | &mpc5200_rtc_ops, THIS_MODULE); | ||
295 | } | 361 | } |
296 | 362 | ||
297 | rtc->rtc = rtc_device_register("mpc5121-rtc", &op->dev, | ||
298 | &mpc5121_rtc_ops, THIS_MODULE); | ||
299 | if (IS_ERR(rtc->rtc)) { | 363 | if (IS_ERR(rtc->rtc)) { |
300 | err = PTR_ERR(rtc->rtc); | 364 | err = PTR_ERR(rtc->rtc); |
301 | goto out_free_irq; | 365 | goto out_free_irq; |
@@ -340,6 +404,7 @@ static int __devexit mpc5121_rtc_remove(struct platform_device *op) | |||
340 | 404 | ||
341 | static struct of_device_id mpc5121_rtc_match[] __devinitdata = { | 405 | static struct of_device_id mpc5121_rtc_match[] __devinitdata = { |
342 | { .compatible = "fsl,mpc5121-rtc", }, | 406 | { .compatible = "fsl,mpc5121-rtc", }, |
407 | { .compatible = "fsl,mpc5200-rtc", }, | ||
343 | {}, | 408 | {}, |
344 | }; | 409 | }; |
345 | 410 | ||
diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c index 0cec5650d56a..d33544802a2e 100644 --- a/drivers/rtc/rtc-mrst.c +++ b/drivers/rtc/rtc-mrst.c | |||
@@ -332,9 +332,8 @@ vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq) | |||
332 | if (!iomem) | 332 | if (!iomem) |
333 | return -ENODEV; | 333 | return -ENODEV; |
334 | 334 | ||
335 | iomem = request_mem_region(iomem->start, | 335 | iomem = request_mem_region(iomem->start, resource_size(iomem), |
336 | iomem->end + 1 - iomem->start, | 336 | driver_name); |
337 | driver_name); | ||
338 | if (!iomem) { | 337 | if (!iomem) { |
339 | dev_dbg(dev, "i/o mem already in use.\n"); | 338 | dev_dbg(dev, "i/o mem already in use.\n"); |
340 | return -EBUSY; | 339 | return -EBUSY; |
diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c index 60627a764514..768e2edb9678 100644 --- a/drivers/rtc/rtc-mv.c +++ b/drivers/rtc/rtc-mv.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
16 | #include <linux/gfp.h> | 16 | #include <linux/gfp.h> |
17 | #include <linux/module.h> | ||
17 | 18 | ||
18 | 19 | ||
19 | #define RTC_TIME_REG_OFFS 0 | 20 | #define RTC_TIME_REG_OFFS 0 |
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index bcae8dd41496..7789002bdd5c 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c | |||
@@ -368,7 +368,7 @@ static int __init omap_rtc_probe(struct platform_device *pdev) | |||
368 | pr_info("%s: already running\n", pdev->name); | 368 | pr_info("%s: already running\n", pdev->name); |
369 | 369 | ||
370 | /* force to 24 hour mode */ | 370 | /* force to 24 hour mode */ |
371 | new_ctrl = reg & ~(OMAP_RTC_CTRL_SPLIT|OMAP_RTC_CTRL_AUTO_COMP); | 371 | new_ctrl = reg & (OMAP_RTC_CTRL_SPLIT|OMAP_RTC_CTRL_AUTO_COMP); |
372 | new_ctrl |= OMAP_RTC_CTRL_STOP; | 372 | new_ctrl |= OMAP_RTC_CTRL_STOP; |
373 | 373 | ||
374 | /* BOARD-SPECIFIC CUSTOMIZATION CAN GO HERE: | 374 | /* BOARD-SPECIFIC CUSTOMIZATION CAN GO HERE: |
diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index 71bab0ef5443..2ee3bbf7e5ea 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/slab.h> | 42 | #include <linux/slab.h> |
43 | #include <linux/rtc.h> | 43 | #include <linux/rtc.h> |
44 | #include <linux/spi/spi.h> | 44 | #include <linux/spi/spi.h> |
45 | #include <linux/module.h> | ||
45 | 46 | ||
46 | #define DRV_VERSION "0.6" | 47 | #define DRV_VERSION "0.6" |
47 | 48 | ||
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index b42c0c679266..606fdfab34e2 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/bcd.h> | 18 | #include <linux/bcd.h> |
19 | #include <linux/rtc.h> | 19 | #include <linux/rtc.h> |
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/module.h> | ||
21 | 22 | ||
22 | #define DRV_VERSION "0.4.3" | 23 | #define DRV_VERSION "0.4.3" |
23 | 24 | ||
diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c new file mode 100644 index 000000000000..d420e9d877e8 --- /dev/null +++ b/drivers/rtc/rtc-pm8xxx.c | |||
@@ -0,0 +1,550 @@ | |||
1 | /* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/rtc.h> | ||
16 | #include <linux/pm.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/spinlock.h> | ||
19 | |||
20 | #include <linux/mfd/pm8xxx/core.h> | ||
21 | #include <linux/mfd/pm8xxx/rtc.h> | ||
22 | |||
23 | |||
24 | /* RTC Register offsets from RTC CTRL REG */ | ||
25 | #define PM8XXX_ALARM_CTRL_OFFSET 0x01 | ||
26 | #define PM8XXX_RTC_WRITE_OFFSET 0x02 | ||
27 | #define PM8XXX_RTC_READ_OFFSET 0x06 | ||
28 | #define PM8XXX_ALARM_RW_OFFSET 0x0A | ||
29 | |||
30 | /* RTC_CTRL register bit fields */ | ||
31 | #define PM8xxx_RTC_ENABLE BIT(7) | ||
32 | #define PM8xxx_RTC_ALARM_ENABLE BIT(1) | ||
33 | #define PM8xxx_RTC_ALARM_CLEAR BIT(0) | ||
34 | |||
35 | #define NUM_8_BIT_RTC_REGS 0x4 | ||
36 | |||
37 | /** | ||
38 | * struct pm8xxx_rtc - rtc driver internal structure | ||
39 | * @rtc: rtc device for this driver. | ||
40 | * @rtc_alarm_irq: rtc alarm irq number. | ||
41 | * @rtc_base: address of rtc control register. | ||
42 | * @rtc_read_base: base address of read registers. | ||
43 | * @rtc_write_base: base address of write registers. | ||
44 | * @alarm_rw_base: base address of alarm registers. | ||
45 | * @ctrl_reg: rtc control register. | ||
46 | * @rtc_dev: device structure. | ||
47 | * @ctrl_reg_lock: spinlock protecting access to ctrl_reg. | ||
48 | */ | ||
49 | struct pm8xxx_rtc { | ||
50 | struct rtc_device *rtc; | ||
51 | int rtc_alarm_irq; | ||
52 | int rtc_base; | ||
53 | int rtc_read_base; | ||
54 | int rtc_write_base; | ||
55 | int alarm_rw_base; | ||
56 | u8 ctrl_reg; | ||
57 | struct device *rtc_dev; | ||
58 | spinlock_t ctrl_reg_lock; | ||
59 | }; | ||
60 | |||
61 | /* | ||
62 | * The RTC registers need to be read/written one byte at a time. This is a | ||
63 | * hardware limitation. | ||
64 | */ | ||
65 | static int pm8xxx_read_wrapper(struct pm8xxx_rtc *rtc_dd, u8 *rtc_val, | ||
66 | int base, int count) | ||
67 | { | ||
68 | int i, rc; | ||
69 | struct device *parent = rtc_dd->rtc_dev->parent; | ||
70 | |||
71 | for (i = 0; i < count; i++) { | ||
72 | rc = pm8xxx_readb(parent, base + i, &rtc_val[i]); | ||
73 | if (rc < 0) { | ||
74 | dev_err(rtc_dd->rtc_dev, "PMIC read failed\n"); | ||
75 | return rc; | ||
76 | } | ||
77 | } | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | static int pm8xxx_write_wrapper(struct pm8xxx_rtc *rtc_dd, u8 *rtc_val, | ||
83 | int base, int count) | ||
84 | { | ||
85 | int i, rc; | ||
86 | struct device *parent = rtc_dd->rtc_dev->parent; | ||
87 | |||
88 | for (i = 0; i < count; i++) { | ||
89 | rc = pm8xxx_writeb(parent, base + i, rtc_val[i]); | ||
90 | if (rc < 0) { | ||
91 | dev_err(rtc_dd->rtc_dev, "PMIC write failed\n"); | ||
92 | return rc; | ||
93 | } | ||
94 | } | ||
95 | |||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | /* | ||
100 | * Steps to write the RTC registers. | ||
101 | * 1. Disable alarm if enabled. | ||
102 | * 2. Write 0x00 to LSB. | ||
103 | * 3. Write Byte[1], Byte[2], Byte[3] then Byte[0]. | ||
104 | * 4. Enable alarm if disabled in step 1. | ||
105 | */ | ||
106 | static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
107 | { | ||
108 | int rc, i; | ||
109 | unsigned long secs, irq_flags; | ||
110 | u8 value[NUM_8_BIT_RTC_REGS], reg = 0, alarm_enabled = 0, ctrl_reg; | ||
111 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); | ||
112 | |||
113 | rtc_tm_to_time(tm, &secs); | ||
114 | |||
115 | for (i = 0; i < NUM_8_BIT_RTC_REGS; i++) { | ||
116 | value[i] = secs & 0xFF; | ||
117 | secs >>= 8; | ||
118 | } | ||
119 | |||
120 | dev_dbg(dev, "Seconds value to be written to RTC = %lu\n", secs); | ||
121 | |||
122 | spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
123 | ctrl_reg = rtc_dd->ctrl_reg; | ||
124 | |||
125 | if (ctrl_reg & PM8xxx_RTC_ALARM_ENABLE) { | ||
126 | alarm_enabled = 1; | ||
127 | ctrl_reg &= ~PM8xxx_RTC_ALARM_ENABLE; | ||
128 | rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, | ||
129 | 1); | ||
130 | if (rc < 0) { | ||
131 | dev_err(dev, "Write to RTC control register " | ||
132 | "failed\n"); | ||
133 | goto rtc_rw_fail; | ||
134 | } | ||
135 | rtc_dd->ctrl_reg = ctrl_reg; | ||
136 | } else | ||
137 | spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
138 | |||
139 | /* Write 0 to Byte[0] */ | ||
140 | reg = 0; | ||
141 | rc = pm8xxx_write_wrapper(rtc_dd, ®, rtc_dd->rtc_write_base, 1); | ||
142 | if (rc < 0) { | ||
143 | dev_err(dev, "Write to RTC write data register failed\n"); | ||
144 | goto rtc_rw_fail; | ||
145 | } | ||
146 | |||
147 | /* Write Byte[1], Byte[2], Byte[3] */ | ||
148 | rc = pm8xxx_write_wrapper(rtc_dd, value + 1, | ||
149 | rtc_dd->rtc_write_base + 1, 3); | ||
150 | if (rc < 0) { | ||
151 | dev_err(dev, "Write to RTC write data register failed\n"); | ||
152 | goto rtc_rw_fail; | ||
153 | } | ||
154 | |||
155 | /* Write Byte[0] */ | ||
156 | rc = pm8xxx_write_wrapper(rtc_dd, value, rtc_dd->rtc_write_base, 1); | ||
157 | if (rc < 0) { | ||
158 | dev_err(dev, "Write to RTC write data register failed\n"); | ||
159 | goto rtc_rw_fail; | ||
160 | } | ||
161 | |||
162 | if (alarm_enabled) { | ||
163 | ctrl_reg |= PM8xxx_RTC_ALARM_ENABLE; | ||
164 | rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, | ||
165 | 1); | ||
166 | if (rc < 0) { | ||
167 | dev_err(dev, "Write to RTC control register " | ||
168 | "failed\n"); | ||
169 | goto rtc_rw_fail; | ||
170 | } | ||
171 | rtc_dd->ctrl_reg = ctrl_reg; | ||
172 | } | ||
173 | |||
174 | rtc_rw_fail: | ||
175 | if (alarm_enabled) | ||
176 | spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
177 | |||
178 | return rc; | ||
179 | } | ||
180 | |||
181 | static int pm8xxx_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
182 | { | ||
183 | int rc; | ||
184 | u8 value[NUM_8_BIT_RTC_REGS], reg; | ||
185 | unsigned long secs; | ||
186 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); | ||
187 | |||
188 | rc = pm8xxx_read_wrapper(rtc_dd, value, rtc_dd->rtc_read_base, | ||
189 | NUM_8_BIT_RTC_REGS); | ||
190 | if (rc < 0) { | ||
191 | dev_err(dev, "RTC read data register failed\n"); | ||
192 | return rc; | ||
193 | } | ||
194 | |||
195 | /* | ||
196 | * Read the LSB again and check if there has been a carry over. | ||
197 | * If there is, redo the read operation. | ||
198 | */ | ||
199 | rc = pm8xxx_read_wrapper(rtc_dd, ®, rtc_dd->rtc_read_base, 1); | ||
200 | if (rc < 0) { | ||
201 | dev_err(dev, "RTC read data register failed\n"); | ||
202 | return rc; | ||
203 | } | ||
204 | |||
205 | if (unlikely(reg < value[0])) { | ||
206 | rc = pm8xxx_read_wrapper(rtc_dd, value, | ||
207 | rtc_dd->rtc_read_base, NUM_8_BIT_RTC_REGS); | ||
208 | if (rc < 0) { | ||
209 | dev_err(dev, "RTC read data register failed\n"); | ||
210 | return rc; | ||
211 | } | ||
212 | } | ||
213 | |||
214 | secs = value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24); | ||
215 | |||
216 | rtc_time_to_tm(secs, tm); | ||
217 | |||
218 | rc = rtc_valid_tm(tm); | ||
219 | if (rc < 0) { | ||
220 | dev_err(dev, "Invalid time read from RTC\n"); | ||
221 | return rc; | ||
222 | } | ||
223 | |||
224 | dev_dbg(dev, "secs = %lu, h:m:s == %d:%d:%d, d/m/y = %d/%d/%d\n", | ||
225 | secs, tm->tm_hour, tm->tm_min, tm->tm_sec, | ||
226 | tm->tm_mday, tm->tm_mon, tm->tm_year); | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static int pm8xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
232 | { | ||
233 | int rc, i; | ||
234 | u8 value[NUM_8_BIT_RTC_REGS], ctrl_reg; | ||
235 | unsigned long secs, irq_flags; | ||
236 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); | ||
237 | |||
238 | rtc_tm_to_time(&alarm->time, &secs); | ||
239 | |||
240 | for (i = 0; i < NUM_8_BIT_RTC_REGS; i++) { | ||
241 | value[i] = secs & 0xFF; | ||
242 | secs >>= 8; | ||
243 | } | ||
244 | |||
245 | spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
246 | |||
247 | rc = pm8xxx_write_wrapper(rtc_dd, value, rtc_dd->alarm_rw_base, | ||
248 | NUM_8_BIT_RTC_REGS); | ||
249 | if (rc < 0) { | ||
250 | dev_err(dev, "Write to RTC ALARM register failed\n"); | ||
251 | goto rtc_rw_fail; | ||
252 | } | ||
253 | |||
254 | ctrl_reg = rtc_dd->ctrl_reg; | ||
255 | ctrl_reg = alarm->enabled ? (ctrl_reg | PM8xxx_RTC_ALARM_ENABLE) : | ||
256 | (ctrl_reg & ~PM8xxx_RTC_ALARM_ENABLE); | ||
257 | |||
258 | rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1); | ||
259 | if (rc < 0) { | ||
260 | dev_err(dev, "Write to RTC control register failed\n"); | ||
261 | goto rtc_rw_fail; | ||
262 | } | ||
263 | |||
264 | rtc_dd->ctrl_reg = ctrl_reg; | ||
265 | |||
266 | dev_dbg(dev, "Alarm Set for h:r:s=%d:%d:%d, d/m/y=%d/%d/%d\n", | ||
267 | alarm->time.tm_hour, alarm->time.tm_min, | ||
268 | alarm->time.tm_sec, alarm->time.tm_mday, | ||
269 | alarm->time.tm_mon, alarm->time.tm_year); | ||
270 | rtc_rw_fail: | ||
271 | spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
272 | return rc; | ||
273 | } | ||
274 | |||
275 | static int pm8xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
276 | { | ||
277 | int rc; | ||
278 | u8 value[NUM_8_BIT_RTC_REGS]; | ||
279 | unsigned long secs; | ||
280 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); | ||
281 | |||
282 | rc = pm8xxx_read_wrapper(rtc_dd, value, rtc_dd->alarm_rw_base, | ||
283 | NUM_8_BIT_RTC_REGS); | ||
284 | if (rc < 0) { | ||
285 | dev_err(dev, "RTC alarm time read failed\n"); | ||
286 | return rc; | ||
287 | } | ||
288 | |||
289 | secs = value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24); | ||
290 | |||
291 | rtc_time_to_tm(secs, &alarm->time); | ||
292 | |||
293 | rc = rtc_valid_tm(&alarm->time); | ||
294 | if (rc < 0) { | ||
295 | dev_err(dev, "Invalid alarm time read from RTC\n"); | ||
296 | return rc; | ||
297 | } | ||
298 | |||
299 | dev_dbg(dev, "Alarm set for - h:r:s=%d:%d:%d, d/m/y=%d/%d/%d\n", | ||
300 | alarm->time.tm_hour, alarm->time.tm_min, | ||
301 | alarm->time.tm_sec, alarm->time.tm_mday, | ||
302 | alarm->time.tm_mon, alarm->time.tm_year); | ||
303 | |||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | static int pm8xxx_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) | ||
308 | { | ||
309 | int rc; | ||
310 | unsigned long irq_flags; | ||
311 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); | ||
312 | u8 ctrl_reg; | ||
313 | |||
314 | spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
315 | ctrl_reg = rtc_dd->ctrl_reg; | ||
316 | ctrl_reg = (enable) ? (ctrl_reg | PM8xxx_RTC_ALARM_ENABLE) : | ||
317 | (ctrl_reg & ~PM8xxx_RTC_ALARM_ENABLE); | ||
318 | |||
319 | rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1); | ||
320 | if (rc < 0) { | ||
321 | dev_err(dev, "Write to RTC control register failed\n"); | ||
322 | goto rtc_rw_fail; | ||
323 | } | ||
324 | |||
325 | rtc_dd->ctrl_reg = ctrl_reg; | ||
326 | |||
327 | rtc_rw_fail: | ||
328 | spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
329 | return rc; | ||
330 | } | ||
331 | |||
332 | static struct rtc_class_ops pm8xxx_rtc_ops = { | ||
333 | .read_time = pm8xxx_rtc_read_time, | ||
334 | .set_alarm = pm8xxx_rtc_set_alarm, | ||
335 | .read_alarm = pm8xxx_rtc_read_alarm, | ||
336 | .alarm_irq_enable = pm8xxx_rtc_alarm_irq_enable, | ||
337 | }; | ||
338 | |||
339 | static irqreturn_t pm8xxx_alarm_trigger(int irq, void *dev_id) | ||
340 | { | ||
341 | struct pm8xxx_rtc *rtc_dd = dev_id; | ||
342 | u8 ctrl_reg; | ||
343 | int rc; | ||
344 | unsigned long irq_flags; | ||
345 | |||
346 | rtc_update_irq(rtc_dd->rtc, 1, RTC_IRQF | RTC_AF); | ||
347 | |||
348 | spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
349 | |||
350 | /* Clear the alarm enable bit */ | ||
351 | ctrl_reg = rtc_dd->ctrl_reg; | ||
352 | ctrl_reg &= ~PM8xxx_RTC_ALARM_ENABLE; | ||
353 | |||
354 | rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1); | ||
355 | if (rc < 0) { | ||
356 | spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
357 | dev_err(rtc_dd->rtc_dev, "Write to RTC control register " | ||
358 | "failed\n"); | ||
359 | goto rtc_alarm_handled; | ||
360 | } | ||
361 | |||
362 | rtc_dd->ctrl_reg = ctrl_reg; | ||
363 | spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
364 | |||
365 | /* Clear RTC alarm register */ | ||
366 | rc = pm8xxx_read_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base + | ||
367 | PM8XXX_ALARM_CTRL_OFFSET, 1); | ||
368 | if (rc < 0) { | ||
369 | dev_err(rtc_dd->rtc_dev, "RTC Alarm control register read " | ||
370 | "failed\n"); | ||
371 | goto rtc_alarm_handled; | ||
372 | } | ||
373 | |||
374 | ctrl_reg &= ~PM8xxx_RTC_ALARM_CLEAR; | ||
375 | rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base + | ||
376 | PM8XXX_ALARM_CTRL_OFFSET, 1); | ||
377 | if (rc < 0) | ||
378 | dev_err(rtc_dd->rtc_dev, "Write to RTC Alarm control register" | ||
379 | " failed\n"); | ||
380 | |||
381 | rtc_alarm_handled: | ||
382 | return IRQ_HANDLED; | ||
383 | } | ||
384 | |||
385 | static int __devinit pm8xxx_rtc_probe(struct platform_device *pdev) | ||
386 | { | ||
387 | int rc; | ||
388 | u8 ctrl_reg; | ||
389 | bool rtc_write_enable = false; | ||
390 | struct pm8xxx_rtc *rtc_dd; | ||
391 | struct resource *rtc_resource; | ||
392 | const struct pm8xxx_rtc_platform_data *pdata = | ||
393 | dev_get_platdata(&pdev->dev); | ||
394 | |||
395 | if (pdata != NULL) | ||
396 | rtc_write_enable = pdata->rtc_write_enable; | ||
397 | |||
398 | rtc_dd = kzalloc(sizeof(*rtc_dd), GFP_KERNEL); | ||
399 | if (rtc_dd == NULL) { | ||
400 | dev_err(&pdev->dev, "Unable to allocate memory!\n"); | ||
401 | return -ENOMEM; | ||
402 | } | ||
403 | |||
404 | /* Initialise spinlock to protect RTC control register */ | ||
405 | spin_lock_init(&rtc_dd->ctrl_reg_lock); | ||
406 | |||
407 | rtc_dd->rtc_alarm_irq = platform_get_irq(pdev, 0); | ||
408 | if (rtc_dd->rtc_alarm_irq < 0) { | ||
409 | dev_err(&pdev->dev, "Alarm IRQ resource absent!\n"); | ||
410 | rc = -ENXIO; | ||
411 | goto fail_rtc_enable; | ||
412 | } | ||
413 | |||
414 | rtc_resource = platform_get_resource_byname(pdev, IORESOURCE_IO, | ||
415 | "pmic_rtc_base"); | ||
416 | if (!(rtc_resource && rtc_resource->start)) { | ||
417 | dev_err(&pdev->dev, "RTC IO resource absent!\n"); | ||
418 | rc = -ENXIO; | ||
419 | goto fail_rtc_enable; | ||
420 | } | ||
421 | |||
422 | rtc_dd->rtc_base = rtc_resource->start; | ||
423 | |||
424 | /* Setup RTC register addresses */ | ||
425 | rtc_dd->rtc_write_base = rtc_dd->rtc_base + PM8XXX_RTC_WRITE_OFFSET; | ||
426 | rtc_dd->rtc_read_base = rtc_dd->rtc_base + PM8XXX_RTC_READ_OFFSET; | ||
427 | rtc_dd->alarm_rw_base = rtc_dd->rtc_base + PM8XXX_ALARM_RW_OFFSET; | ||
428 | |||
429 | rtc_dd->rtc_dev = &pdev->dev; | ||
430 | |||
431 | /* Check if the RTC is on, else turn it on */ | ||
432 | rc = pm8xxx_read_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1); | ||
433 | if (rc < 0) { | ||
434 | dev_err(&pdev->dev, "RTC control register read failed!\n"); | ||
435 | goto fail_rtc_enable; | ||
436 | } | ||
437 | |||
438 | if (!(ctrl_reg & PM8xxx_RTC_ENABLE)) { | ||
439 | ctrl_reg |= PM8xxx_RTC_ENABLE; | ||
440 | rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, | ||
441 | 1); | ||
442 | if (rc < 0) { | ||
443 | dev_err(&pdev->dev, "Write to RTC control register " | ||
444 | "failed\n"); | ||
445 | goto fail_rtc_enable; | ||
446 | } | ||
447 | } | ||
448 | |||
449 | rtc_dd->ctrl_reg = ctrl_reg; | ||
450 | if (rtc_write_enable == true) | ||
451 | pm8xxx_rtc_ops.set_time = pm8xxx_rtc_set_time; | ||
452 | |||
453 | platform_set_drvdata(pdev, rtc_dd); | ||
454 | |||
455 | /* Register the RTC device */ | ||
456 | rtc_dd->rtc = rtc_device_register("pm8xxx_rtc", &pdev->dev, | ||
457 | &pm8xxx_rtc_ops, THIS_MODULE); | ||
458 | if (IS_ERR(rtc_dd->rtc)) { | ||
459 | dev_err(&pdev->dev, "%s: RTC registration failed (%ld)\n", | ||
460 | __func__, PTR_ERR(rtc_dd->rtc)); | ||
461 | rc = PTR_ERR(rtc_dd->rtc); | ||
462 | goto fail_rtc_enable; | ||
463 | } | ||
464 | |||
465 | /* Request the alarm IRQ */ | ||
466 | rc = request_any_context_irq(rtc_dd->rtc_alarm_irq, | ||
467 | pm8xxx_alarm_trigger, IRQF_TRIGGER_RISING, | ||
468 | "pm8xxx_rtc_alarm", rtc_dd); | ||
469 | if (rc < 0) { | ||
470 | dev_err(&pdev->dev, "Request IRQ failed (%d)\n", rc); | ||
471 | goto fail_req_irq; | ||
472 | } | ||
473 | |||
474 | device_init_wakeup(&pdev->dev, 1); | ||
475 | |||
476 | dev_dbg(&pdev->dev, "Probe success !!\n"); | ||
477 | |||
478 | return 0; | ||
479 | |||
480 | fail_req_irq: | ||
481 | rtc_device_unregister(rtc_dd->rtc); | ||
482 | fail_rtc_enable: | ||
483 | platform_set_drvdata(pdev, NULL); | ||
484 | kfree(rtc_dd); | ||
485 | return rc; | ||
486 | } | ||
487 | |||
488 | static int __devexit pm8xxx_rtc_remove(struct platform_device *pdev) | ||
489 | { | ||
490 | struct pm8xxx_rtc *rtc_dd = platform_get_drvdata(pdev); | ||
491 | |||
492 | device_init_wakeup(&pdev->dev, 0); | ||
493 | free_irq(rtc_dd->rtc_alarm_irq, rtc_dd); | ||
494 | rtc_device_unregister(rtc_dd->rtc); | ||
495 | platform_set_drvdata(pdev, NULL); | ||
496 | kfree(rtc_dd); | ||
497 | |||
498 | return 0; | ||
499 | } | ||
500 | |||
501 | #ifdef CONFIG_PM_SLEEP | ||
502 | static int pm8xxx_rtc_resume(struct device *dev) | ||
503 | { | ||
504 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); | ||
505 | |||
506 | if (device_may_wakeup(dev)) | ||
507 | disable_irq_wake(rtc_dd->rtc_alarm_irq); | ||
508 | |||
509 | return 0; | ||
510 | } | ||
511 | |||
512 | static int pm8xxx_rtc_suspend(struct device *dev) | ||
513 | { | ||
514 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); | ||
515 | |||
516 | if (device_may_wakeup(dev)) | ||
517 | enable_irq_wake(rtc_dd->rtc_alarm_irq); | ||
518 | |||
519 | return 0; | ||
520 | } | ||
521 | #endif | ||
522 | |||
523 | SIMPLE_DEV_PM_OPS(pm8xxx_rtc_pm_ops, pm8xxx_rtc_suspend, pm8xxx_rtc_resume); | ||
524 | |||
525 | static struct platform_driver pm8xxx_rtc_driver = { | ||
526 | .probe = pm8xxx_rtc_probe, | ||
527 | .remove = __devexit_p(pm8xxx_rtc_remove), | ||
528 | .driver = { | ||
529 | .name = PM8XXX_RTC_DEV_NAME, | ||
530 | .owner = THIS_MODULE, | ||
531 | .pm = &pm8xxx_rtc_pm_ops, | ||
532 | }, | ||
533 | }; | ||
534 | |||
535 | static int __init pm8xxx_rtc_init(void) | ||
536 | { | ||
537 | return platform_driver_register(&pm8xxx_rtc_driver); | ||
538 | } | ||
539 | module_init(pm8xxx_rtc_init); | ||
540 | |||
541 | static void __exit pm8xxx_rtc_exit(void) | ||
542 | { | ||
543 | platform_driver_unregister(&pm8xxx_rtc_driver); | ||
544 | } | ||
545 | module_exit(pm8xxx_rtc_exit); | ||
546 | |||
547 | MODULE_ALIAS("platform:rtc-pm8xxx"); | ||
548 | MODULE_DESCRIPTION("PMIC8xxx RTC driver"); | ||
549 | MODULE_LICENSE("GPL v2"); | ||
550 | MODULE_AUTHOR("Anirudh Ghayal <aghayal@codeaurora.org>"); | ||
diff --git a/drivers/rtc/rtc-puv3.c b/drivers/rtc/rtc-puv3.c index 46f14b82f3ab..b3eba3cddd42 100644 --- a/drivers/rtc/rtc-puv3.c +++ b/drivers/rtc/rtc-puv3.c | |||
@@ -267,9 +267,8 @@ static int puv3_rtc_probe(struct platform_device *pdev) | |||
267 | return -ENOENT; | 267 | return -ENOENT; |
268 | } | 268 | } |
269 | 269 | ||
270 | puv3_rtc_mem = request_mem_region(res->start, | 270 | puv3_rtc_mem = request_mem_region(res->start, resource_size(res), |
271 | res->end-res->start+1, | 271 | pdev->name); |
272 | pdev->name); | ||
273 | 272 | ||
274 | if (puv3_rtc_mem == NULL) { | 273 | if (puv3_rtc_mem == NULL) { |
275 | dev_err(&pdev->dev, "failed to reserve memory region\n"); | 274 | dev_err(&pdev->dev, "failed to reserve memory region\n"); |
diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c index 368d0e63cf83..971bc8e08da6 100644 --- a/drivers/rtc/rtc-rs5c348.c +++ b/drivers/rtc/rtc-rs5c348.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/rtc.h> | 23 | #include <linux/rtc.h> |
24 | #include <linux/workqueue.h> | 24 | #include <linux/workqueue.h> |
25 | #include <linux/spi/spi.h> | 25 | #include <linux/spi/spi.h> |
26 | #include <linux/module.h> | ||
26 | 27 | ||
27 | #define DRV_VERSION "0.2" | 28 | #define DRV_VERSION "0.2" |
28 | 29 | ||
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index 85c1b848dd72..d29f5432c6e8 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/rtc.h> | 14 | #include <linux/rtc.h> |
15 | #include <linux/bcd.h> | 15 | #include <linux/bcd.h> |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/module.h> | ||
17 | 18 | ||
18 | #define DRV_VERSION "0.6" | 19 | #define DRV_VERSION "0.6" |
19 | 20 | ||
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 16512ecae31a..7639ab906f02 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c | |||
@@ -51,17 +51,43 @@ static enum s3c_cpu_type s3c_rtc_cpu_type; | |||
51 | 51 | ||
52 | static DEFINE_SPINLOCK(s3c_rtc_pie_lock); | 52 | static DEFINE_SPINLOCK(s3c_rtc_pie_lock); |
53 | 53 | ||
54 | static void s3c_rtc_alarm_clk_enable(bool enable) | ||
55 | { | ||
56 | static DEFINE_SPINLOCK(s3c_rtc_alarm_clk_lock); | ||
57 | static bool alarm_clk_enabled; | ||
58 | unsigned long irq_flags; | ||
59 | |||
60 | spin_lock_irqsave(&s3c_rtc_alarm_clk_lock, irq_flags); | ||
61 | if (enable) { | ||
62 | if (!alarm_clk_enabled) { | ||
63 | clk_enable(rtc_clk); | ||
64 | alarm_clk_enabled = true; | ||
65 | } | ||
66 | } else { | ||
67 | if (alarm_clk_enabled) { | ||
68 | clk_disable(rtc_clk); | ||
69 | alarm_clk_enabled = false; | ||
70 | } | ||
71 | } | ||
72 | spin_unlock_irqrestore(&s3c_rtc_alarm_clk_lock, irq_flags); | ||
73 | } | ||
74 | |||
54 | /* IRQ Handlers */ | 75 | /* IRQ Handlers */ |
55 | 76 | ||
56 | static irqreturn_t s3c_rtc_alarmirq(int irq, void *id) | 77 | static irqreturn_t s3c_rtc_alarmirq(int irq, void *id) |
57 | { | 78 | { |
58 | struct rtc_device *rdev = id; | 79 | struct rtc_device *rdev = id; |
59 | 80 | ||
81 | clk_enable(rtc_clk); | ||
60 | rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF); | 82 | rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF); |
61 | 83 | ||
62 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) | 84 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) |
63 | writeb(S3C2410_INTP_ALM, s3c_rtc_base + S3C2410_INTP); | 85 | writeb(S3C2410_INTP_ALM, s3c_rtc_base + S3C2410_INTP); |
64 | 86 | ||
87 | clk_disable(rtc_clk); | ||
88 | |||
89 | s3c_rtc_alarm_clk_enable(false); | ||
90 | |||
65 | return IRQ_HANDLED; | 91 | return IRQ_HANDLED; |
66 | } | 92 | } |
67 | 93 | ||
@@ -69,11 +95,13 @@ static irqreturn_t s3c_rtc_tickirq(int irq, void *id) | |||
69 | { | 95 | { |
70 | struct rtc_device *rdev = id; | 96 | struct rtc_device *rdev = id; |
71 | 97 | ||
98 | clk_enable(rtc_clk); | ||
72 | rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF); | 99 | rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF); |
73 | 100 | ||
74 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) | 101 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) |
75 | writeb(S3C2410_INTP_TIC, s3c_rtc_base + S3C2410_INTP); | 102 | writeb(S3C2410_INTP_TIC, s3c_rtc_base + S3C2410_INTP); |
76 | 103 | ||
104 | clk_disable(rtc_clk); | ||
77 | return IRQ_HANDLED; | 105 | return IRQ_HANDLED; |
78 | } | 106 | } |
79 | 107 | ||
@@ -84,12 +112,16 @@ static int s3c_rtc_setaie(struct device *dev, unsigned int enabled) | |||
84 | 112 | ||
85 | pr_debug("%s: aie=%d\n", __func__, enabled); | 113 | pr_debug("%s: aie=%d\n", __func__, enabled); |
86 | 114 | ||
115 | clk_enable(rtc_clk); | ||
87 | tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN; | 116 | tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN; |
88 | 117 | ||
89 | if (enabled) | 118 | if (enabled) |
90 | tmp |= S3C2410_RTCALM_ALMEN; | 119 | tmp |= S3C2410_RTCALM_ALMEN; |
91 | 120 | ||
92 | writeb(tmp, s3c_rtc_base + S3C2410_RTCALM); | 121 | writeb(tmp, s3c_rtc_base + S3C2410_RTCALM); |
122 | clk_disable(rtc_clk); | ||
123 | |||
124 | s3c_rtc_alarm_clk_enable(enabled); | ||
93 | 125 | ||
94 | return 0; | 126 | return 0; |
95 | } | 127 | } |
@@ -103,6 +135,7 @@ static int s3c_rtc_setfreq(struct device *dev, int freq) | |||
103 | if (!is_power_of_2(freq)) | 135 | if (!is_power_of_2(freq)) |
104 | return -EINVAL; | 136 | return -EINVAL; |
105 | 137 | ||
138 | clk_enable(rtc_clk); | ||
106 | spin_lock_irq(&s3c_rtc_pie_lock); | 139 | spin_lock_irq(&s3c_rtc_pie_lock); |
107 | 140 | ||
108 | if (s3c_rtc_cpu_type == TYPE_S3C2410) { | 141 | if (s3c_rtc_cpu_type == TYPE_S3C2410) { |
@@ -114,6 +147,7 @@ static int s3c_rtc_setfreq(struct device *dev, int freq) | |||
114 | 147 | ||
115 | writel(tmp, s3c_rtc_base + S3C2410_TICNT); | 148 | writel(tmp, s3c_rtc_base + S3C2410_TICNT); |
116 | spin_unlock_irq(&s3c_rtc_pie_lock); | 149 | spin_unlock_irq(&s3c_rtc_pie_lock); |
150 | clk_disable(rtc_clk); | ||
117 | 151 | ||
118 | return 0; | 152 | return 0; |
119 | } | 153 | } |
@@ -125,6 +159,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) | |||
125 | unsigned int have_retried = 0; | 159 | unsigned int have_retried = 0; |
126 | void __iomem *base = s3c_rtc_base; | 160 | void __iomem *base = s3c_rtc_base; |
127 | 161 | ||
162 | clk_enable(rtc_clk); | ||
128 | retry_get_time: | 163 | retry_get_time: |
129 | rtc_tm->tm_min = readb(base + S3C2410_RTCMIN); | 164 | rtc_tm->tm_min = readb(base + S3C2410_RTCMIN); |
130 | rtc_tm->tm_hour = readb(base + S3C2410_RTCHOUR); | 165 | rtc_tm->tm_hour = readb(base + S3C2410_RTCHOUR); |
@@ -143,10 +178,6 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) | |||
143 | goto retry_get_time; | 178 | goto retry_get_time; |
144 | } | 179 | } |
145 | 180 | ||
146 | pr_debug("read time %04d.%02d.%02d %02d:%02d:%02d\n", | ||
147 | 1900 + rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday, | ||
148 | rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec); | ||
149 | |||
150 | rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec); | 181 | rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec); |
151 | rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min); | 182 | rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min); |
152 | rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour); | 183 | rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour); |
@@ -155,8 +186,14 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) | |||
155 | rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year); | 186 | rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year); |
156 | 187 | ||
157 | rtc_tm->tm_year += 100; | 188 | rtc_tm->tm_year += 100; |
189 | |||
190 | pr_debug("read time %04d.%02d.%02d %02d:%02d:%02d\n", | ||
191 | 1900 + rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday, | ||
192 | rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec); | ||
193 | |||
158 | rtc_tm->tm_mon -= 1; | 194 | rtc_tm->tm_mon -= 1; |
159 | 195 | ||
196 | clk_disable(rtc_clk); | ||
160 | return rtc_valid_tm(rtc_tm); | 197 | return rtc_valid_tm(rtc_tm); |
161 | } | 198 | } |
162 | 199 | ||
@@ -165,6 +202,7 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) | |||
165 | void __iomem *base = s3c_rtc_base; | 202 | void __iomem *base = s3c_rtc_base; |
166 | int year = tm->tm_year - 100; | 203 | int year = tm->tm_year - 100; |
167 | 204 | ||
205 | clk_enable(rtc_clk); | ||
168 | pr_debug("set time %04d.%02d.%02d %02d:%02d:%02d\n", | 206 | pr_debug("set time %04d.%02d.%02d %02d:%02d:%02d\n", |
169 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, | 207 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, |
170 | tm->tm_hour, tm->tm_min, tm->tm_sec); | 208 | tm->tm_hour, tm->tm_min, tm->tm_sec); |
@@ -182,6 +220,7 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) | |||
182 | writeb(bin2bcd(tm->tm_mday), base + S3C2410_RTCDATE); | 220 | writeb(bin2bcd(tm->tm_mday), base + S3C2410_RTCDATE); |
183 | writeb(bin2bcd(tm->tm_mon + 1), base + S3C2410_RTCMON); | 221 | writeb(bin2bcd(tm->tm_mon + 1), base + S3C2410_RTCMON); |
184 | writeb(bin2bcd(year), base + S3C2410_RTCYEAR); | 222 | writeb(bin2bcd(year), base + S3C2410_RTCYEAR); |
223 | clk_disable(rtc_clk); | ||
185 | 224 | ||
186 | return 0; | 225 | return 0; |
187 | } | 226 | } |
@@ -192,6 +231,7 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
192 | void __iomem *base = s3c_rtc_base; | 231 | void __iomem *base = s3c_rtc_base; |
193 | unsigned int alm_en; | 232 | unsigned int alm_en; |
194 | 233 | ||
234 | clk_enable(rtc_clk); | ||
195 | alm_tm->tm_sec = readb(base + S3C2410_ALMSEC); | 235 | alm_tm->tm_sec = readb(base + S3C2410_ALMSEC); |
196 | alm_tm->tm_min = readb(base + S3C2410_ALMMIN); | 236 | alm_tm->tm_min = readb(base + S3C2410_ALMMIN); |
197 | alm_tm->tm_hour = readb(base + S3C2410_ALMHOUR); | 237 | alm_tm->tm_hour = readb(base + S3C2410_ALMHOUR); |
@@ -243,6 +283,7 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
243 | else | 283 | else |
244 | alm_tm->tm_year = -1; | 284 | alm_tm->tm_year = -1; |
245 | 285 | ||
286 | clk_disable(rtc_clk); | ||
246 | return 0; | 287 | return 0; |
247 | } | 288 | } |
248 | 289 | ||
@@ -252,12 +293,12 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
252 | void __iomem *base = s3c_rtc_base; | 293 | void __iomem *base = s3c_rtc_base; |
253 | unsigned int alrm_en; | 294 | unsigned int alrm_en; |
254 | 295 | ||
296 | clk_enable(rtc_clk); | ||
255 | pr_debug("s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n", | 297 | pr_debug("s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n", |
256 | alrm->enabled, | 298 | alrm->enabled, |
257 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, | 299 | 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, |
258 | tm->tm_hour, tm->tm_min, tm->tm_sec); | 300 | tm->tm_hour, tm->tm_min, tm->tm_sec); |
259 | 301 | ||
260 | |||
261 | alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; | 302 | alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; |
262 | writeb(0x00, base + S3C2410_RTCALM); | 303 | writeb(0x00, base + S3C2410_RTCALM); |
263 | 304 | ||
@@ -282,6 +323,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
282 | 323 | ||
283 | s3c_rtc_setaie(dev, alrm->enabled); | 324 | s3c_rtc_setaie(dev, alrm->enabled); |
284 | 325 | ||
326 | clk_disable(rtc_clk); | ||
285 | return 0; | 327 | return 0; |
286 | } | 328 | } |
287 | 329 | ||
@@ -289,6 +331,7 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) | |||
289 | { | 331 | { |
290 | unsigned int ticnt; | 332 | unsigned int ticnt; |
291 | 333 | ||
334 | clk_enable(rtc_clk); | ||
292 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { | 335 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { |
293 | ticnt = readw(s3c_rtc_base + S3C2410_RTCCON); | 336 | ticnt = readw(s3c_rtc_base + S3C2410_RTCCON); |
294 | ticnt &= S3C64XX_RTCCON_TICEN; | 337 | ticnt &= S3C64XX_RTCCON_TICEN; |
@@ -298,52 +341,11 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) | |||
298 | } | 341 | } |
299 | 342 | ||
300 | seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt ? "yes" : "no"); | 343 | seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt ? "yes" : "no"); |
344 | clk_disable(rtc_clk); | ||
301 | return 0; | 345 | return 0; |
302 | } | 346 | } |
303 | 347 | ||
304 | static int s3c_rtc_open(struct device *dev) | ||
305 | { | ||
306 | struct platform_device *pdev = to_platform_device(dev); | ||
307 | struct rtc_device *rtc_dev = platform_get_drvdata(pdev); | ||
308 | int ret; | ||
309 | |||
310 | ret = request_irq(s3c_rtc_alarmno, s3c_rtc_alarmirq, | ||
311 | IRQF_DISABLED, "s3c2410-rtc alarm", rtc_dev); | ||
312 | |||
313 | if (ret) { | ||
314 | dev_err(dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret); | ||
315 | return ret; | ||
316 | } | ||
317 | |||
318 | ret = request_irq(s3c_rtc_tickno, s3c_rtc_tickirq, | ||
319 | IRQF_DISABLED, "s3c2410-rtc tick", rtc_dev); | ||
320 | |||
321 | if (ret) { | ||
322 | dev_err(dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret); | ||
323 | goto tick_err; | ||
324 | } | ||
325 | |||
326 | return ret; | ||
327 | |||
328 | tick_err: | ||
329 | free_irq(s3c_rtc_alarmno, rtc_dev); | ||
330 | return ret; | ||
331 | } | ||
332 | |||
333 | static void s3c_rtc_release(struct device *dev) | ||
334 | { | ||
335 | struct platform_device *pdev = to_platform_device(dev); | ||
336 | struct rtc_device *rtc_dev = platform_get_drvdata(pdev); | ||
337 | |||
338 | /* do not clear AIE here, it may be needed for wake */ | ||
339 | |||
340 | free_irq(s3c_rtc_alarmno, rtc_dev); | ||
341 | free_irq(s3c_rtc_tickno, rtc_dev); | ||
342 | } | ||
343 | |||
344 | static const struct rtc_class_ops s3c_rtcops = { | 348 | static const struct rtc_class_ops s3c_rtcops = { |
345 | .open = s3c_rtc_open, | ||
346 | .release = s3c_rtc_release, | ||
347 | .read_time = s3c_rtc_gettime, | 349 | .read_time = s3c_rtc_gettime, |
348 | .set_time = s3c_rtc_settime, | 350 | .set_time = s3c_rtc_settime, |
349 | .read_alarm = s3c_rtc_getalarm, | 351 | .read_alarm = s3c_rtc_getalarm, |
@@ -360,6 +362,7 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en) | |||
360 | if (s3c_rtc_base == NULL) | 362 | if (s3c_rtc_base == NULL) |
361 | return; | 363 | return; |
362 | 364 | ||
365 | clk_enable(rtc_clk); | ||
363 | if (!en) { | 366 | if (!en) { |
364 | tmp = readw(base + S3C2410_RTCCON); | 367 | tmp = readw(base + S3C2410_RTCCON); |
365 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) | 368 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) |
@@ -399,18 +402,21 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en) | |||
399 | base + S3C2410_RTCCON); | 402 | base + S3C2410_RTCCON); |
400 | } | 403 | } |
401 | } | 404 | } |
405 | clk_disable(rtc_clk); | ||
402 | } | 406 | } |
403 | 407 | ||
404 | static int __devexit s3c_rtc_remove(struct platform_device *dev) | 408 | static int __devexit s3c_rtc_remove(struct platform_device *dev) |
405 | { | 409 | { |
406 | struct rtc_device *rtc = platform_get_drvdata(dev); | 410 | struct rtc_device *rtc = platform_get_drvdata(dev); |
407 | 411 | ||
412 | free_irq(s3c_rtc_alarmno, rtc); | ||
413 | free_irq(s3c_rtc_tickno, rtc); | ||
414 | |||
408 | platform_set_drvdata(dev, NULL); | 415 | platform_set_drvdata(dev, NULL); |
409 | rtc_device_unregister(rtc); | 416 | rtc_device_unregister(rtc); |
410 | 417 | ||
411 | s3c_rtc_setaie(&dev->dev, 0); | 418 | s3c_rtc_setaie(&dev->dev, 0); |
412 | 419 | ||
413 | clk_disable(rtc_clk); | ||
414 | clk_put(rtc_clk); | 420 | clk_put(rtc_clk); |
415 | rtc_clk = NULL; | 421 | rtc_clk = NULL; |
416 | 422 | ||
@@ -455,8 +461,7 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
455 | return -ENOENT; | 461 | return -ENOENT; |
456 | } | 462 | } |
457 | 463 | ||
458 | s3c_rtc_mem = request_mem_region(res->start, | 464 | s3c_rtc_mem = request_mem_region(res->start, resource_size(res), |
459 | res->end-res->start+1, | ||
460 | pdev->name); | 465 | pdev->name); |
461 | 466 | ||
462 | if (s3c_rtc_mem == NULL) { | 467 | if (s3c_rtc_mem == NULL) { |
@@ -465,7 +470,7 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
465 | goto err_nores; | 470 | goto err_nores; |
466 | } | 471 | } |
467 | 472 | ||
468 | s3c_rtc_base = ioremap(res->start, res->end - res->start + 1); | 473 | s3c_rtc_base = ioremap(res->start, resource_size(res)); |
469 | if (s3c_rtc_base == NULL) { | 474 | if (s3c_rtc_base == NULL) { |
470 | dev_err(&pdev->dev, "failed ioremap()\n"); | 475 | dev_err(&pdev->dev, "failed ioremap()\n"); |
471 | ret = -EINVAL; | 476 | ret = -EINVAL; |
@@ -530,8 +535,32 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
530 | 535 | ||
531 | s3c_rtc_setfreq(&pdev->dev, 1); | 536 | s3c_rtc_setfreq(&pdev->dev, 1); |
532 | 537 | ||
538 | ret = request_irq(s3c_rtc_alarmno, s3c_rtc_alarmirq, | ||
539 | IRQF_DISABLED, "s3c2410-rtc alarm", rtc); | ||
540 | if (ret) { | ||
541 | dev_err(&pdev->dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret); | ||
542 | goto err_alarm_irq; | ||
543 | } | ||
544 | |||
545 | ret = request_irq(s3c_rtc_tickno, s3c_rtc_tickirq, | ||
546 | IRQF_DISABLED, "s3c2410-rtc tick", rtc); | ||
547 | if (ret) { | ||
548 | dev_err(&pdev->dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret); | ||
549 | free_irq(s3c_rtc_alarmno, rtc); | ||
550 | goto err_tick_irq; | ||
551 | } | ||
552 | |||
553 | clk_disable(rtc_clk); | ||
554 | |||
533 | return 0; | 555 | return 0; |
534 | 556 | ||
557 | err_tick_irq: | ||
558 | free_irq(s3c_rtc_alarmno, rtc); | ||
559 | |||
560 | err_alarm_irq: | ||
561 | platform_set_drvdata(pdev, NULL); | ||
562 | rtc_device_unregister(rtc); | ||
563 | |||
535 | err_nortc: | 564 | err_nortc: |
536 | s3c_rtc_enable(pdev, 0); | 565 | s3c_rtc_enable(pdev, 0); |
537 | clk_disable(rtc_clk); | 566 | clk_disable(rtc_clk); |
@@ -555,6 +584,7 @@ static int ticnt_save, ticnt_en_save; | |||
555 | 584 | ||
556 | static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) | 585 | static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) |
557 | { | 586 | { |
587 | clk_enable(rtc_clk); | ||
558 | /* save TICNT for anyone using periodic interrupts */ | 588 | /* save TICNT for anyone using periodic interrupts */ |
559 | ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); | 589 | ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); |
560 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { | 590 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { |
@@ -569,6 +599,7 @@ static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) | |||
569 | else | 599 | else |
570 | dev_err(&pdev->dev, "enable_irq_wake failed\n"); | 600 | dev_err(&pdev->dev, "enable_irq_wake failed\n"); |
571 | } | 601 | } |
602 | clk_disable(rtc_clk); | ||
572 | 603 | ||
573 | return 0; | 604 | return 0; |
574 | } | 605 | } |
@@ -577,6 +608,7 @@ static int s3c_rtc_resume(struct platform_device *pdev) | |||
577 | { | 608 | { |
578 | unsigned int tmp; | 609 | unsigned int tmp; |
579 | 610 | ||
611 | clk_enable(rtc_clk); | ||
580 | s3c_rtc_enable(pdev, 1); | 612 | s3c_rtc_enable(pdev, 1); |
581 | writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); | 613 | writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); |
582 | if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) { | 614 | if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) { |
@@ -588,6 +620,7 @@ static int s3c_rtc_resume(struct platform_device *pdev) | |||
588 | disable_irq_wake(s3c_rtc_alarmno); | 620 | disable_irq_wake(s3c_rtc_alarmno); |
589 | wake_en = false; | 621 | wake_en = false; |
590 | } | 622 | } |
623 | clk_disable(rtc_clk); | ||
591 | 624 | ||
592 | return 0; | 625 | return 0; |
593 | } | 626 | } |
diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c index 3b943673cd3e..ed3e9b599031 100644 --- a/drivers/rtc/rtc-stk17ta8.c +++ b/drivers/rtc/rtc-stk17ta8.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/rtc.h> | 21 | #include <linux/rtc.h> |
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/module.h> | ||
24 | 25 | ||
25 | #define DRV_VERSION "0.1" | 26 | #define DRV_VERSION "0.1" |
26 | 27 | ||
diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c index 572e9534b591..7315068daa59 100644 --- a/drivers/rtc/rtc-stmp3xxx.c +++ b/drivers/rtc/rtc-stmp3xxx.c | |||
@@ -6,6 +6,7 @@ | |||
6 | * | 6 | * |
7 | * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved. | 7 | * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved. |
8 | * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. | 8 | * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. |
9 | * Copyright 2011 Wolfram Sang, Pengutronix e.K. | ||
9 | */ | 10 | */ |
10 | 11 | ||
11 | /* | 12 | /* |
@@ -18,21 +19,41 @@ | |||
18 | */ | 19 | */ |
19 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
20 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/io.h> | ||
21 | #include <linux/init.h> | 23 | #include <linux/init.h> |
22 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
23 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
24 | #include <linux/rtc.h> | 26 | #include <linux/rtc.h> |
25 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
26 | 28 | ||
27 | #include <mach/platform.h> | 29 | #include <mach/common.h> |
28 | #include <mach/stmp3xxx.h> | 30 | |
29 | #include <mach/regs-rtc.h> | 31 | #define STMP3XXX_RTC_CTRL 0x0 |
32 | #define STMP3XXX_RTC_CTRL_SET 0x4 | ||
33 | #define STMP3XXX_RTC_CTRL_CLR 0x8 | ||
34 | #define STMP3XXX_RTC_CTRL_ALARM_IRQ_EN 0x00000001 | ||
35 | #define STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN 0x00000002 | ||
36 | #define STMP3XXX_RTC_CTRL_ALARM_IRQ 0x00000004 | ||
37 | |||
38 | #define STMP3XXX_RTC_STAT 0x10 | ||
39 | #define STMP3XXX_RTC_STAT_STALE_SHIFT 16 | ||
40 | #define STMP3XXX_RTC_STAT_RTC_PRESENT 0x80000000 | ||
41 | |||
42 | #define STMP3XXX_RTC_SECONDS 0x30 | ||
43 | |||
44 | #define STMP3XXX_RTC_ALARM 0x40 | ||
45 | |||
46 | #define STMP3XXX_RTC_PERSISTENT0 0x60 | ||
47 | #define STMP3XXX_RTC_PERSISTENT0_SET 0x64 | ||
48 | #define STMP3XXX_RTC_PERSISTENT0_CLR 0x68 | ||
49 | #define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN 0x00000002 | ||
50 | #define STMP3XXX_RTC_PERSISTENT0_ALARM_EN 0x00000004 | ||
51 | #define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE 0x00000080 | ||
30 | 52 | ||
31 | struct stmp3xxx_rtc_data { | 53 | struct stmp3xxx_rtc_data { |
32 | struct rtc_device *rtc; | 54 | struct rtc_device *rtc; |
33 | unsigned irq_count; | ||
34 | void __iomem *io; | 55 | void __iomem *io; |
35 | int irq_alarm, irq_1msec; | 56 | int irq_alarm; |
36 | }; | 57 | }; |
37 | 58 | ||
38 | static void stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data) | 59 | static void stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data) |
@@ -42,8 +63,8 @@ static void stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data) | |||
42 | * NEW_REGS/STALE_REGS bitfields go. In fact it's 0x1=P0, | 63 | * NEW_REGS/STALE_REGS bitfields go. In fact it's 0x1=P0, |
43 | * 0x2=P1, .., 0x20=P5, 0x40=ALARM, 0x80=SECONDS | 64 | * 0x2=P1, .., 0x20=P5, 0x40=ALARM, 0x80=SECONDS |
44 | */ | 65 | */ |
45 | while (__raw_readl(rtc_data->io + HW_RTC_STAT) & | 66 | while (readl(rtc_data->io + STMP3XXX_RTC_STAT) & |
46 | BF(0x80, RTC_STAT_STALE_REGS)) | 67 | (0x80 << STMP3XXX_RTC_STAT_STALE_SHIFT)) |
47 | cpu_relax(); | 68 | cpu_relax(); |
48 | } | 69 | } |
49 | 70 | ||
@@ -53,7 +74,7 @@ static int stmp3xxx_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) | |||
53 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); | 74 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); |
54 | 75 | ||
55 | stmp3xxx_wait_time(rtc_data); | 76 | stmp3xxx_wait_time(rtc_data); |
56 | rtc_time_to_tm(__raw_readl(rtc_data->io + HW_RTC_SECONDS), rtc_tm); | 77 | rtc_time_to_tm(readl(rtc_data->io + STMP3XXX_RTC_SECONDS), rtc_tm); |
57 | return 0; | 78 | return 0; |
58 | } | 79 | } |
59 | 80 | ||
@@ -61,7 +82,7 @@ static int stmp3xxx_rtc_set_mmss(struct device *dev, unsigned long t) | |||
61 | { | 82 | { |
62 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); | 83 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); |
63 | 84 | ||
64 | __raw_writel(t, rtc_data->io + HW_RTC_SECONDS); | 85 | writel(t, rtc_data->io + STMP3XXX_RTC_SECONDS); |
65 | stmp3xxx_wait_time(rtc_data); | 86 | stmp3xxx_wait_time(rtc_data); |
66 | return 0; | 87 | return 0; |
67 | } | 88 | } |
@@ -70,47 +91,34 @@ static int stmp3xxx_rtc_set_mmss(struct device *dev, unsigned long t) | |||
70 | static irqreturn_t stmp3xxx_rtc_interrupt(int irq, void *dev_id) | 91 | static irqreturn_t stmp3xxx_rtc_interrupt(int irq, void *dev_id) |
71 | { | 92 | { |
72 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev_id); | 93 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev_id); |
73 | u32 status; | 94 | u32 status = readl(rtc_data->io + STMP3XXX_RTC_CTRL); |
74 | u32 events = 0; | ||
75 | |||
76 | status = __raw_readl(rtc_data->io + HW_RTC_CTRL) & | ||
77 | (BM_RTC_CTRL_ALARM_IRQ | BM_RTC_CTRL_ONEMSEC_IRQ); | ||
78 | 95 | ||
79 | if (status & BM_RTC_CTRL_ALARM_IRQ) { | 96 | if (status & STMP3XXX_RTC_CTRL_ALARM_IRQ) { |
80 | stmp3xxx_clearl(BM_RTC_CTRL_ALARM_IRQ, | 97 | writel(STMP3XXX_RTC_CTRL_ALARM_IRQ, |
81 | rtc_data->io + HW_RTC_CTRL); | 98 | rtc_data->io + STMP3XXX_RTC_CTRL_CLR); |
82 | events |= RTC_AF | RTC_IRQF; | 99 | rtc_update_irq(rtc_data->rtc, 1, RTC_AF | RTC_IRQF); |
100 | return IRQ_HANDLED; | ||
83 | } | 101 | } |
84 | 102 | ||
85 | if (status & BM_RTC_CTRL_ONEMSEC_IRQ) { | 103 | return IRQ_NONE; |
86 | stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ, | ||
87 | rtc_data->io + HW_RTC_CTRL); | ||
88 | if (++rtc_data->irq_count % 1000 == 0) { | ||
89 | events |= RTC_UF | RTC_IRQF; | ||
90 | rtc_data->irq_count = 0; | ||
91 | } | ||
92 | } | ||
93 | |||
94 | if (events) | ||
95 | rtc_update_irq(rtc_data->rtc, 1, events); | ||
96 | |||
97 | return IRQ_HANDLED; | ||
98 | } | 104 | } |
99 | 105 | ||
100 | static int stmp3xxx_alarm_irq_enable(struct device *dev, unsigned int enabled) | 106 | static int stmp3xxx_alarm_irq_enable(struct device *dev, unsigned int enabled) |
101 | { | 107 | { |
102 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); | 108 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); |
103 | void __iomem *p = rtc_data->io + HW_RTC_PERSISTENT0, | ||
104 | *ctl = rtc_data->io + HW_RTC_CTRL; | ||
105 | 109 | ||
106 | if (enabled) { | 110 | if (enabled) { |
107 | stmp3xxx_setl(BM_RTC_PERSISTENT0_ALARM_EN | | 111 | writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN | |
108 | BM_RTC_PERSISTENT0_ALARM_WAKE_EN, p); | 112 | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN, |
109 | stmp3xxx_setl(BM_RTC_CTRL_ALARM_IRQ_EN, ctl); | 113 | rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET); |
114 | writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN, | ||
115 | rtc_data->io + STMP3XXX_RTC_CTRL_SET); | ||
110 | } else { | 116 | } else { |
111 | stmp3xxx_clearl(BM_RTC_PERSISTENT0_ALARM_EN | | 117 | writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN | |
112 | BM_RTC_PERSISTENT0_ALARM_WAKE_EN, p); | 118 | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN, |
113 | stmp3xxx_clearl(BM_RTC_CTRL_ALARM_IRQ_EN, ctl); | 119 | rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR); |
120 | writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN, | ||
121 | rtc_data->io + STMP3XXX_RTC_CTRL_CLR); | ||
114 | } | 122 | } |
115 | return 0; | 123 | return 0; |
116 | } | 124 | } |
@@ -119,7 +127,7 @@ static int stmp3xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | |||
119 | { | 127 | { |
120 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); | 128 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); |
121 | 129 | ||
122 | rtc_time_to_tm(__raw_readl(rtc_data->io + HW_RTC_ALARM), &alm->time); | 130 | rtc_time_to_tm(readl(rtc_data->io + STMP3XXX_RTC_ALARM), &alm->time); |
123 | return 0; | 131 | return 0; |
124 | } | 132 | } |
125 | 133 | ||
@@ -129,7 +137,10 @@ static int stmp3xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | |||
129 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); | 137 | struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); |
130 | 138 | ||
131 | rtc_tm_to_time(&alm->time, &t); | 139 | rtc_tm_to_time(&alm->time, &t); |
132 | __raw_writel(t, rtc_data->io + HW_RTC_ALARM); | 140 | writel(t, rtc_data->io + STMP3XXX_RTC_ALARM); |
141 | |||
142 | stmp3xxx_alarm_irq_enable(dev, alm->enabled); | ||
143 | |||
133 | return 0; | 144 | return 0; |
134 | } | 145 | } |
135 | 146 | ||
@@ -149,11 +160,11 @@ static int stmp3xxx_rtc_remove(struct platform_device *pdev) | |||
149 | if (!rtc_data) | 160 | if (!rtc_data) |
150 | return 0; | 161 | return 0; |
151 | 162 | ||
152 | stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ_EN | BM_RTC_CTRL_ALARM_IRQ_EN, | 163 | writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN, |
153 | rtc_data->io + HW_RTC_CTRL); | 164 | rtc_data->io + STMP3XXX_RTC_CTRL_CLR); |
154 | free_irq(rtc_data->irq_alarm, &pdev->dev); | 165 | free_irq(rtc_data->irq_alarm, &pdev->dev); |
155 | free_irq(rtc_data->irq_1msec, &pdev->dev); | ||
156 | rtc_device_unregister(rtc_data->rtc); | 166 | rtc_device_unregister(rtc_data->rtc); |
167 | platform_set_drvdata(pdev, NULL); | ||
157 | iounmap(rtc_data->io); | 168 | iounmap(rtc_data->io); |
158 | kfree(rtc_data); | 169 | kfree(rtc_data); |
159 | 170 | ||
@@ -185,20 +196,26 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev) | |||
185 | } | 196 | } |
186 | 197 | ||
187 | rtc_data->irq_alarm = platform_get_irq(pdev, 0); | 198 | rtc_data->irq_alarm = platform_get_irq(pdev, 0); |
188 | rtc_data->irq_1msec = platform_get_irq(pdev, 1); | ||
189 | 199 | ||
190 | if (!(__raw_readl(HW_RTC_STAT + rtc_data->io) & | 200 | if (!(readl(STMP3XXX_RTC_STAT + rtc_data->io) & |
191 | BM_RTC_STAT_RTC_PRESENT)) { | 201 | STMP3XXX_RTC_STAT_RTC_PRESENT)) { |
192 | dev_err(&pdev->dev, "no device onboard\n"); | 202 | dev_err(&pdev->dev, "no device onboard\n"); |
193 | err = -ENODEV; | 203 | err = -ENODEV; |
194 | goto out_remap; | 204 | goto out_remap; |
195 | } | 205 | } |
196 | 206 | ||
197 | stmp3xxx_reset_block(rtc_data->io, true); | 207 | platform_set_drvdata(pdev, rtc_data); |
198 | stmp3xxx_clearl(BM_RTC_PERSISTENT0_ALARM_EN | | 208 | |
199 | BM_RTC_PERSISTENT0_ALARM_WAKE_EN | | 209 | mxs_reset_block(rtc_data->io); |
200 | BM_RTC_PERSISTENT0_ALARM_WAKE, | 210 | writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN | |
201 | rtc_data->io + HW_RTC_PERSISTENT0); | 211 | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN | |
212 | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE, | ||
213 | rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR); | ||
214 | |||
215 | writel(STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN | | ||
216 | STMP3XXX_RTC_CTRL_ALARM_IRQ_EN, | ||
217 | rtc_data->io + STMP3XXX_RTC_CTRL_CLR); | ||
218 | |||
202 | rtc_data->rtc = rtc_device_register(pdev->name, &pdev->dev, | 219 | rtc_data->rtc = rtc_device_register(pdev->name, &pdev->dev, |
203 | &stmp3xxx_rtc_ops, THIS_MODULE); | 220 | &stmp3xxx_rtc_ops, THIS_MODULE); |
204 | if (IS_ERR(rtc_data->rtc)) { | 221 | if (IS_ERR(rtc_data->rtc)) { |
@@ -206,33 +223,20 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev) | |||
206 | goto out_remap; | 223 | goto out_remap; |
207 | } | 224 | } |
208 | 225 | ||
209 | rtc_data->irq_count = 0; | 226 | err = request_irq(rtc_data->irq_alarm, stmp3xxx_rtc_interrupt, 0, |
210 | err = request_irq(rtc_data->irq_alarm, stmp3xxx_rtc_interrupt, | 227 | "RTC alarm", &pdev->dev); |
211 | IRQF_DISABLED, "RTC alarm", &pdev->dev); | ||
212 | if (err) { | 228 | if (err) { |
213 | dev_err(&pdev->dev, "Cannot claim IRQ%d\n", | 229 | dev_err(&pdev->dev, "Cannot claim IRQ%d\n", |
214 | rtc_data->irq_alarm); | 230 | rtc_data->irq_alarm); |
215 | goto out_irq_alarm; | 231 | goto out_irq_alarm; |
216 | } | 232 | } |
217 | err = request_irq(rtc_data->irq_1msec, stmp3xxx_rtc_interrupt, | ||
218 | IRQF_DISABLED, "RTC tick", &pdev->dev); | ||
219 | if (err) { | ||
220 | dev_err(&pdev->dev, "Cannot claim IRQ%d\n", | ||
221 | rtc_data->irq_1msec); | ||
222 | goto out_irq1; | ||
223 | } | ||
224 | |||
225 | platform_set_drvdata(pdev, rtc_data); | ||
226 | 233 | ||
227 | return 0; | 234 | return 0; |
228 | 235 | ||
229 | out_irq1: | ||
230 | free_irq(rtc_data->irq_alarm, &pdev->dev); | ||
231 | out_irq_alarm: | 236 | out_irq_alarm: |
232 | stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ_EN | BM_RTC_CTRL_ALARM_IRQ_EN, | ||
233 | rtc_data->io + HW_RTC_CTRL); | ||
234 | rtc_device_unregister(rtc_data->rtc); | 237 | rtc_device_unregister(rtc_data->rtc); |
235 | out_remap: | 238 | out_remap: |
239 | platform_set_drvdata(pdev, NULL); | ||
236 | iounmap(rtc_data->io); | 240 | iounmap(rtc_data->io); |
237 | out_free: | 241 | out_free: |
238 | kfree(rtc_data); | 242 | kfree(rtc_data); |
@@ -249,11 +253,11 @@ static int stmp3xxx_rtc_resume(struct platform_device *dev) | |||
249 | { | 253 | { |
250 | struct stmp3xxx_rtc_data *rtc_data = platform_get_drvdata(dev); | 254 | struct stmp3xxx_rtc_data *rtc_data = platform_get_drvdata(dev); |
251 | 255 | ||
252 | stmp3xxx_reset_block(rtc_data->io, true); | 256 | mxs_reset_block(rtc_data->io); |
253 | stmp3xxx_clearl(BM_RTC_PERSISTENT0_ALARM_EN | | 257 | writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN | |
254 | BM_RTC_PERSISTENT0_ALARM_WAKE_EN | | 258 | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN | |
255 | BM_RTC_PERSISTENT0_ALARM_WAKE, | 259 | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE, |
256 | rtc_data->io + HW_RTC_PERSISTENT0); | 260 | rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR); |
257 | return 0; | 261 | return 0; |
258 | } | 262 | } |
259 | #else | 263 | #else |
@@ -286,5 +290,6 @@ module_init(stmp3xxx_rtc_init); | |||
286 | module_exit(stmp3xxx_rtc_exit); | 290 | module_exit(stmp3xxx_rtc_exit); |
287 | 291 | ||
288 | MODULE_DESCRIPTION("STMP3xxx RTC Driver"); | 292 | MODULE_DESCRIPTION("STMP3xxx RTC Driver"); |
289 | MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com>"); | 293 | MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com> and " |
294 | "Wolfram Sang <w.sang@pengutronix.de>"); | ||
290 | MODULE_LICENSE("GPL"); | 295 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c index 2fc31aac3f4e..75259fe38602 100644 --- a/drivers/rtc/rtc-tegra.c +++ b/drivers/rtc/rtc-tegra.c | |||
@@ -343,7 +343,7 @@ static int __devinit tegra_rtc_probe(struct platform_device *pdev) | |||
343 | 343 | ||
344 | /* set context info. */ | 344 | /* set context info. */ |
345 | info->pdev = pdev; | 345 | info->pdev = pdev; |
346 | info->tegra_rtc_lock = __SPIN_LOCK_UNLOCKED(info->tegra_rtc_lock); | 346 | spin_lock_init(&info->tegra_rtc_lock); |
347 | 347 | ||
348 | platform_set_drvdata(pdev, info); | 348 | platform_set_drvdata(pdev, info); |
349 | 349 | ||
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index f9a2799c44d6..20687d55e7a7 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c | |||
@@ -275,7 +275,7 @@ static int twl_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
275 | goto out; | 275 | goto out; |
276 | 276 | ||
277 | save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M; | 277 | save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M; |
278 | twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); | 278 | ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); |
279 | if (ret < 0) | 279 | if (ret < 0) |
280 | goto out; | 280 | goto out; |
281 | 281 | ||
@@ -362,14 +362,6 @@ static irqreturn_t twl_rtc_interrupt(int irq, void *rtc) | |||
362 | int res; | 362 | int res; |
363 | u8 rd_reg; | 363 | u8 rd_reg; |
364 | 364 | ||
365 | #ifdef CONFIG_LOCKDEP | ||
366 | /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which | ||
367 | * we don't want and can't tolerate. Although it might be | ||
368 | * friendlier not to borrow this thread context... | ||
369 | */ | ||
370 | local_irq_enable(); | ||
371 | #endif | ||
372 | |||
373 | res = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); | 365 | res = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); |
374 | if (res) | 366 | if (res) |
375 | goto out; | 367 | goto out; |
@@ -428,24 +420,12 @@ static struct rtc_class_ops twl_rtc_ops = { | |||
428 | static int __devinit twl_rtc_probe(struct platform_device *pdev) | 420 | static int __devinit twl_rtc_probe(struct platform_device *pdev) |
429 | { | 421 | { |
430 | struct rtc_device *rtc; | 422 | struct rtc_device *rtc; |
431 | int ret = 0; | 423 | int ret = -EINVAL; |
432 | int irq = platform_get_irq(pdev, 0); | 424 | int irq = platform_get_irq(pdev, 0); |
433 | u8 rd_reg; | 425 | u8 rd_reg; |
434 | 426 | ||
435 | if (irq <= 0) | 427 | if (irq <= 0) |
436 | return -EINVAL; | 428 | goto out1; |
437 | |||
438 | rtc = rtc_device_register(pdev->name, | ||
439 | &pdev->dev, &twl_rtc_ops, THIS_MODULE); | ||
440 | if (IS_ERR(rtc)) { | ||
441 | ret = PTR_ERR(rtc); | ||
442 | dev_err(&pdev->dev, "can't register RTC device, err %ld\n", | ||
443 | PTR_ERR(rtc)); | ||
444 | goto out0; | ||
445 | |||
446 | } | ||
447 | |||
448 | platform_set_drvdata(pdev, rtc); | ||
449 | 429 | ||
450 | ret = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); | 430 | ret = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); |
451 | if (ret < 0) | 431 | if (ret < 0) |
@@ -462,14 +442,6 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev) | |||
462 | if (ret < 0) | 442 | if (ret < 0) |
463 | goto out1; | 443 | goto out1; |
464 | 444 | ||
465 | ret = request_irq(irq, twl_rtc_interrupt, | ||
466 | IRQF_TRIGGER_RISING, | ||
467 | dev_name(&rtc->dev), rtc); | ||
468 | if (ret < 0) { | ||
469 | dev_err(&pdev->dev, "IRQ is not free.\n"); | ||
470 | goto out1; | ||
471 | } | ||
472 | |||
473 | if (twl_class_is_6030()) { | 445 | if (twl_class_is_6030()) { |
474 | twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK, | 446 | twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK, |
475 | REG_INT_MSK_LINE_A); | 447 | REG_INT_MSK_LINE_A); |
@@ -480,28 +452,44 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev) | |||
480 | /* Check RTC module status, Enable if it is off */ | 452 | /* Check RTC module status, Enable if it is off */ |
481 | ret = twl_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG); | 453 | ret = twl_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG); |
482 | if (ret < 0) | 454 | if (ret < 0) |
483 | goto out2; | 455 | goto out1; |
484 | 456 | ||
485 | if (!(rd_reg & BIT_RTC_CTRL_REG_STOP_RTC_M)) { | 457 | if (!(rd_reg & BIT_RTC_CTRL_REG_STOP_RTC_M)) { |
486 | dev_info(&pdev->dev, "Enabling TWL-RTC.\n"); | 458 | dev_info(&pdev->dev, "Enabling TWL-RTC.\n"); |
487 | rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M; | 459 | rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M; |
488 | ret = twl_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG); | 460 | ret = twl_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG); |
489 | if (ret < 0) | 461 | if (ret < 0) |
490 | goto out2; | 462 | goto out1; |
491 | } | 463 | } |
492 | 464 | ||
493 | /* init cached IRQ enable bits */ | 465 | /* init cached IRQ enable bits */ |
494 | ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); | 466 | ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); |
495 | if (ret < 0) | 467 | if (ret < 0) |
468 | goto out1; | ||
469 | |||
470 | rtc = rtc_device_register(pdev->name, | ||
471 | &pdev->dev, &twl_rtc_ops, THIS_MODULE); | ||
472 | if (IS_ERR(rtc)) { | ||
473 | ret = PTR_ERR(rtc); | ||
474 | dev_err(&pdev->dev, "can't register RTC device, err %ld\n", | ||
475 | PTR_ERR(rtc)); | ||
476 | goto out1; | ||
477 | } | ||
478 | |||
479 | ret = request_threaded_irq(irq, NULL, twl_rtc_interrupt, | ||
480 | IRQF_TRIGGER_RISING, | ||
481 | dev_name(&rtc->dev), rtc); | ||
482 | if (ret < 0) { | ||
483 | dev_err(&pdev->dev, "IRQ is not free.\n"); | ||
496 | goto out2; | 484 | goto out2; |
485 | } | ||
497 | 486 | ||
498 | return ret; | 487 | platform_set_drvdata(pdev, rtc); |
488 | return 0; | ||
499 | 489 | ||
500 | out2: | 490 | out2: |
501 | free_irq(irq, rtc); | ||
502 | out1: | ||
503 | rtc_device_unregister(rtc); | 491 | rtc_device_unregister(rtc); |
504 | out0: | 492 | out1: |
505 | return ret; | 493 | return ret; |
506 | } | 494 | } |
507 | 495 | ||
diff --git a/drivers/rtc/rtc-tx4939.c b/drivers/rtc/rtc-tx4939.c index ec6313d15359..aac0ffed4345 100644 --- a/drivers/rtc/rtc-tx4939.c +++ b/drivers/rtc/rtc-tx4939.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/rtc.h> | 11 | #include <linux/rtc.h> |
12 | #include <linux/platform_device.h> | 12 | #include <linux/platform_device.h> |
13 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
14 | #include <linux/module.h> | ||
14 | #include <linux/io.h> | 15 | #include <linux/io.h> |
15 | #include <linux/gfp.h> | 16 | #include <linux/gfp.h> |
16 | #include <asm/txx9/tx4939.h> | 17 | #include <asm/txx9/tx4939.h> |
diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c index efd6066b5cd2..f93f412423c6 100644 --- a/drivers/rtc/rtc-vt8500.c +++ b/drivers/rtc/rtc-vt8500.c | |||
@@ -74,6 +74,8 @@ | |||
74 | #define VT8500_RTC_CR_SM_SEC (1 << 3) /* 0: 1Hz/60, 1: 1Hz */ | 74 | #define VT8500_RTC_CR_SM_SEC (1 << 3) /* 0: 1Hz/60, 1: 1Hz */ |
75 | #define VT8500_RTC_CR_CALIB (1 << 4) /* Enable calibration */ | 75 | #define VT8500_RTC_CR_CALIB (1 << 4) /* Enable calibration */ |
76 | 76 | ||
77 | #define VT8500_RTC_IS_ALARM (1 << 0) /* Alarm interrupt status */ | ||
78 | |||
77 | struct vt8500_rtc { | 79 | struct vt8500_rtc { |
78 | void __iomem *regbase; | 80 | void __iomem *regbase; |
79 | struct resource *res; | 81 | struct resource *res; |
@@ -96,7 +98,7 @@ static irqreturn_t vt8500_rtc_irq(int irq, void *dev_id) | |||
96 | 98 | ||
97 | spin_unlock(&vt8500_rtc->lock); | 99 | spin_unlock(&vt8500_rtc->lock); |
98 | 100 | ||
99 | if (isr & 1) | 101 | if (isr & VT8500_RTC_IS_ALARM) |
100 | events |= RTC_AF | RTC_IRQF; | 102 | events |= RTC_AF | RTC_IRQF; |
101 | 103 | ||
102 | rtc_update_irq(vt8500_rtc->rtc, 1, events); | 104 | rtc_update_irq(vt8500_rtc->rtc, 1, events); |
@@ -161,8 +163,8 @@ static int vt8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
161 | alrm->time.tm_sec = bcd2bin((alarm & TIME_SEC_MASK)); | 163 | alrm->time.tm_sec = bcd2bin((alarm & TIME_SEC_MASK)); |
162 | 164 | ||
163 | alrm->enabled = (alarm & ALARM_ENABLE_MASK) ? 1 : 0; | 165 | alrm->enabled = (alarm & ALARM_ENABLE_MASK) ? 1 : 0; |
166 | alrm->pending = (isr & VT8500_RTC_IS_ALARM) ? 1 : 0; | ||
164 | 167 | ||
165 | alrm->pending = (isr & 1) ? 1 : 0; | ||
166 | return rtc_valid_tm(&alrm->time); | 168 | return rtc_valid_tm(&alrm->time); |
167 | } | 169 | } |
168 | 170 | ||
diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c index b00aad2620d4..8c051d3179db 100644 --- a/drivers/rtc/rtc-x1205.c +++ b/drivers/rtc/rtc-x1205.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/bcd.h> | 21 | #include <linux/bcd.h> |
22 | #include <linux/rtc.h> | 22 | #include <linux/rtc.h> |
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/module.h> | ||
24 | 25 | ||
25 | #define DRV_VERSION "1.0.8" | 26 | #define DRV_VERSION "1.0.8" |
26 | 27 | ||