diff options
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/Kconfig | 6 | ||||
-rw-r--r-- | drivers/rtc/class.c | 65 | ||||
-rw-r--r-- | drivers/rtc/rtc-stmp3xxx.c | 153 | ||||
-rw-r--r-- | drivers/rtc/rtc-vt8500.c | 6 |
4 files changed, 134 insertions, 96 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index ce2aabf5c550..dcb61e23b985 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -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. |
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 4194e59e14cd..01a7df5317c1 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c | |||
@@ -41,20 +41,41 @@ static void rtc_device_release(struct device *dev) | |||
41 | * system's wall clock; restore it on resume(). | 41 | * system's wall clock; restore it on resume(). |
42 | */ | 42 | */ |
43 | 43 | ||
44 | static time_t oldtime; | 44 | static struct timespec old_rtc, old_system, old_delta; |
45 | static struct timespec oldts; | 45 | |
46 | 46 | ||
47 | static int rtc_suspend(struct device *dev, pm_message_t mesg) | 47 | static int rtc_suspend(struct device *dev, pm_message_t mesg) |
48 | { | 48 | { |
49 | struct rtc_device *rtc = to_rtc_device(dev); | 49 | struct rtc_device *rtc = to_rtc_device(dev); |
50 | struct rtc_time tm; | 50 | struct rtc_time tm; |
51 | 51 | struct timespec delta, delta_delta; | |
52 | if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0) | 52 | if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0) |
53 | return 0; | 53 | return 0; |
54 | 54 | ||
55 | /* snapshot the current RTC and system time at suspend*/ | ||
55 | rtc_read_time(rtc, &tm); | 56 | rtc_read_time(rtc, &tm); |
56 | ktime_get_ts(&oldts); | 57 | getnstimeofday(&old_system); |
57 | rtc_tm_to_time(&tm, &oldtime); | 58 | rtc_tm_to_time(&tm, &old_rtc.tv_sec); |
59 | |||
60 | |||
61 | /* | ||
62 | * To avoid drift caused by repeated suspend/resumes, | ||
63 | * which each can add ~1 second drift error, | ||
64 | * try to compensate so the difference in system time | ||
65 | * and rtc time stays close to constant. | ||
66 | */ | ||
67 | delta = timespec_sub(old_system, old_rtc); | ||
68 | delta_delta = timespec_sub(delta, old_delta); | ||
69 | if (abs(delta_delta.tv_sec) >= 2) { | ||
70 | /* | ||
71 | * if delta_delta is too large, assume time correction | ||
72 | * has occured and set old_delta to the current delta. | ||
73 | */ | ||
74 | old_delta = delta; | ||
75 | } else { | ||
76 | /* Otherwise try to adjust old_system to compensate */ | ||
77 | old_system = timespec_sub(old_system, delta_delta); | ||
78 | } | ||
58 | 79 | ||
59 | return 0; | 80 | return 0; |
60 | } | 81 | } |
@@ -63,32 +84,42 @@ static int rtc_resume(struct device *dev) | |||
63 | { | 84 | { |
64 | struct rtc_device *rtc = to_rtc_device(dev); | 85 | struct rtc_device *rtc = to_rtc_device(dev); |
65 | struct rtc_time tm; | 86 | struct rtc_time tm; |
66 | time_t newtime; | 87 | struct timespec new_system, new_rtc; |
67 | struct timespec time; | 88 | struct timespec sleep_time; |
68 | struct timespec newts; | ||
69 | 89 | ||
70 | if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0) | 90 | if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0) |
71 | return 0; | 91 | return 0; |
72 | 92 | ||
73 | ktime_get_ts(&newts); | 93 | /* snapshot the current rtc and system time at resume */ |
94 | getnstimeofday(&new_system); | ||
74 | rtc_read_time(rtc, &tm); | 95 | rtc_read_time(rtc, &tm); |
75 | if (rtc_valid_tm(&tm) != 0) { | 96 | if (rtc_valid_tm(&tm) != 0) { |
76 | pr_debug("%s: bogus resume time\n", dev_name(&rtc->dev)); | 97 | pr_debug("%s: bogus resume time\n", dev_name(&rtc->dev)); |
77 | return 0; | 98 | return 0; |
78 | } | 99 | } |
79 | rtc_tm_to_time(&tm, &newtime); | 100 | rtc_tm_to_time(&tm, &new_rtc.tv_sec); |
80 | if (newtime <= oldtime) { | 101 | new_rtc.tv_nsec = 0; |
81 | if (newtime < oldtime) | 102 | |
103 | if (new_rtc.tv_sec <= old_rtc.tv_sec) { | ||
104 | if (new_rtc.tv_sec < old_rtc.tv_sec) | ||
82 | pr_debug("%s: time travel!\n", dev_name(&rtc->dev)); | 105 | pr_debug("%s: time travel!\n", dev_name(&rtc->dev)); |
83 | return 0; | 106 | return 0; |
84 | } | 107 | } |
85 | /* calculate the RTC time delta */ | ||
86 | set_normalized_timespec(&time, newtime - oldtime, 0); | ||
87 | 108 | ||
88 | /* subtract kernel time between rtc_suspend to rtc_resume */ | 109 | /* calculate the RTC time delta (sleep time)*/ |
89 | time = timespec_sub(time, timespec_sub(newts, oldts)); | 110 | sleep_time = timespec_sub(new_rtc, old_rtc); |
111 | |||
112 | /* | ||
113 | * Since these RTC suspend/resume handlers are not called | ||
114 | * at the very end of suspend or the start of resume, | ||
115 | * some run-time may pass on either sides of the sleep time | ||
116 | * so subtract kernel run-time between rtc_suspend to rtc_resume | ||
117 | * to keep things accurate. | ||
118 | */ | ||
119 | sleep_time = timespec_sub(sleep_time, | ||
120 | timespec_sub(new_system, old_system)); | ||
90 | 121 | ||
91 | timekeeping_inject_sleeptime(&time); | 122 | timekeeping_inject_sleeptime(&sleep_time); |
92 | return 0; | 123 | return 0; |
93 | } | 124 | } |
94 | 125 | ||
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-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 | ||