diff options
author | Arnd Bergmann <arnd@arndb.de> | 2011-12-28 05:46:03 -0500 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2011-12-28 05:46:03 -0500 |
commit | 15db3e823c3246e3bd31fe454f5c8927eb85caf2 (patch) | |
tree | f91811c5872ede20ec86f4256a9f60befa6b8a61 /drivers/rtc | |
parent | d7bd1b8a6104bcdc53611689fec8715a236a22c8 (diff) | |
parent | edf3ff5bac2582b57de4e7c6569fee5d7c1c0a42 (diff) |
Merge branch 'drivers/rtc-sa1100' into next/drivers
* drivers/rtc-sa1100:
ARM: sa1100: clean up of the clock support
ARM: pxa: add dummy clock for sa1100-rtc
RTC: sa1100: support sa1100, pxa and mmp soc families
RTC: sa1100: remove redundant code of setting alarm
RTC: sa1100: Clean out ost register
Conflicts:
arch/arm/mach-pxa/pxa25x.c
arch/arm/mach-pxa/pxa27x.c
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/Kconfig | 2 | ||||
-rw-r--r-- | drivers/rtc/rtc-sa1100.c | 300 |
2 files changed, 184 insertions, 118 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 53eb4e55b289..877cf6fdcf24 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -774,7 +774,7 @@ config RTC_DRV_EP93XX | |||
774 | 774 | ||
775 | config RTC_DRV_SA1100 | 775 | config RTC_DRV_SA1100 |
776 | tristate "SA11x0/PXA2xx" | 776 | tristate "SA11x0/PXA2xx" |
777 | depends on ARCH_SA1100 || ARCH_PXA | 777 | depends on ARCH_SA1100 || ARCH_PXA || ARCH_MMP |
778 | help | 778 | help |
779 | If you say Y here you will get access to the real time clock | 779 | If you say Y here you will get access to the real time clock |
780 | built into your SA11x0 or PXA2xx CPU. | 780 | built into your SA11x0 or PXA2xx CPU. |
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index 0b40bb88a884..fc1ffe97fca1 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c | |||
@@ -27,35 +27,42 @@ | |||
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/fs.h> | 28 | #include <linux/fs.h> |
29 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
30 | #include <linux/string.h> | ||
31 | #include <linux/pm.h> | 30 | #include <linux/pm.h> |
32 | #include <linux/bitops.h> | 31 | #include <linux/slab.h> |
32 | #include <linux/clk.h> | ||
33 | #include <linux/io.h> | ||
33 | 34 | ||
34 | #include <mach/hardware.h> | 35 | #include <mach/hardware.h> |
35 | #include <asm/irq.h> | 36 | #include <asm/irq.h> |
36 | 37 | ||
37 | #ifdef CONFIG_ARCH_PXA | ||
38 | #include <mach/regs-rtc.h> | ||
39 | #include <mach/regs-ost.h> | ||
40 | #endif | ||
41 | |||
42 | #define RTC_DEF_DIVIDER (32768 - 1) | 38 | #define RTC_DEF_DIVIDER (32768 - 1) |
43 | #define RTC_DEF_TRIM 0 | 39 | #define RTC_DEF_TRIM 0 |
44 | 40 | #define RTC_FREQ 1024 | |
45 | static const unsigned long RTC_FREQ = 1024; | 41 | |
46 | static struct rtc_time rtc_alarm; | 42 | #define RCNR 0x00 /* RTC Count Register */ |
47 | static DEFINE_SPINLOCK(sa1100_rtc_lock); | 43 | #define RTAR 0x04 /* RTC Alarm Register */ |
48 | 44 | #define RTSR 0x08 /* RTC Status Register */ | |
49 | static inline int rtc_periodic_alarm(struct rtc_time *tm) | 45 | #define RTTR 0x0c /* RTC Timer Trim Register */ |
50 | { | 46 | |
51 | return (tm->tm_year == -1) || | 47 | #define RTSR_HZE (1 << 3) /* HZ interrupt enable */ |
52 | ((unsigned)tm->tm_mon >= 12) || | 48 | #define RTSR_ALE (1 << 2) /* RTC alarm interrupt enable */ |
53 | ((unsigned)(tm->tm_mday - 1) >= 31) || | 49 | #define RTSR_HZ (1 << 1) /* HZ rising-edge detected */ |
54 | ((unsigned)tm->tm_hour > 23) || | 50 | #define RTSR_AL (1 << 0) /* RTC alarm detected */ |
55 | ((unsigned)tm->tm_min > 59) || | 51 | |
56 | ((unsigned)tm->tm_sec > 59); | 52 | #define rtc_readl(sa1100_rtc, reg) \ |
57 | } | 53 | readl_relaxed((sa1100_rtc)->base + (reg)) |
58 | 54 | #define rtc_writel(sa1100_rtc, reg, value) \ | |
55 | writel_relaxed((value), (sa1100_rtc)->base + (reg)) | ||
56 | |||
57 | struct sa1100_rtc { | ||
58 | struct resource *ress; | ||
59 | void __iomem *base; | ||
60 | struct clk *clk; | ||
61 | int irq_1Hz; | ||
62 | int irq_Alrm; | ||
63 | struct rtc_device *rtc; | ||
64 | spinlock_t lock; /* Protects this structure */ | ||
65 | }; | ||
59 | /* | 66 | /* |
60 | * Calculate the next alarm time given the requested alarm time mask | 67 | * Calculate the next alarm time given the requested alarm time mask |
61 | * and the current time. | 68 | * and the current time. |
@@ -83,46 +90,26 @@ static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, | |||
83 | } | 90 | } |
84 | } | 91 | } |
85 | 92 | ||
86 | static int rtc_update_alarm(struct rtc_time *alrm) | ||
87 | { | ||
88 | struct rtc_time alarm_tm, now_tm; | ||
89 | unsigned long now, time; | ||
90 | int ret; | ||
91 | |||
92 | do { | ||
93 | now = RCNR; | ||
94 | rtc_time_to_tm(now, &now_tm); | ||
95 | rtc_next_alarm_time(&alarm_tm, &now_tm, alrm); | ||
96 | ret = rtc_tm_to_time(&alarm_tm, &time); | ||
97 | if (ret != 0) | ||
98 | break; | ||
99 | |||
100 | RTSR = RTSR & (RTSR_HZE|RTSR_ALE|RTSR_AL); | ||
101 | RTAR = time; | ||
102 | } while (now != RCNR); | ||
103 | |||
104 | return ret; | ||
105 | } | ||
106 | |||
107 | static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) | 93 | static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) |
108 | { | 94 | { |
109 | struct platform_device *pdev = to_platform_device(dev_id); | 95 | struct platform_device *pdev = to_platform_device(dev_id); |
110 | struct rtc_device *rtc = platform_get_drvdata(pdev); | 96 | struct sa1100_rtc *sa1100_rtc = platform_get_drvdata(pdev); |
111 | unsigned int rtsr; | 97 | unsigned int rtsr; |
112 | unsigned long events = 0; | 98 | unsigned long events = 0; |
113 | 99 | ||
114 | spin_lock(&sa1100_rtc_lock); | 100 | spin_lock(&sa1100_rtc->lock); |
115 | 101 | ||
116 | rtsr = RTSR; | ||
117 | /* clear interrupt sources */ | 102 | /* clear interrupt sources */ |
118 | RTSR = 0; | 103 | rtsr = rtc_readl(sa1100_rtc, RTSR); |
104 | rtc_writel(sa1100_rtc, RTSR, 0); | ||
105 | |||
119 | /* Fix for a nasty initialization problem the in SA11xx RTSR register. | 106 | /* Fix for a nasty initialization problem the in SA11xx RTSR register. |
120 | * See also the comments in sa1100_rtc_probe(). */ | 107 | * See also the comments in sa1100_rtc_probe(). */ |
121 | if (rtsr & (RTSR_ALE | RTSR_HZE)) { | 108 | if (rtsr & (RTSR_ALE | RTSR_HZE)) { |
122 | /* This is the original code, before there was the if test | 109 | /* This is the original code, before there was the if test |
123 | * above. This code does not clear interrupts that were not | 110 | * above. This code does not clear interrupts that were not |
124 | * enabled. */ | 111 | * enabled. */ |
125 | RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2); | 112 | rtc_writel(sa1100_rtc, RTSR, (RTSR_AL | RTSR_HZ) & (rtsr >> 2)); |
126 | } else { | 113 | } else { |
127 | /* For some reason, it is possible to enter this routine | 114 | /* For some reason, it is possible to enter this routine |
128 | * without interruptions enabled, it has been tested with | 115 | * without interruptions enabled, it has been tested with |
@@ -131,13 +118,13 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) | |||
131 | * This situation leads to an infinite "loop" of interrupt | 118 | * This situation leads to an infinite "loop" of interrupt |
132 | * routine calling and as a result the processor seems to | 119 | * routine calling and as a result the processor seems to |
133 | * lock on its first call to open(). */ | 120 | * lock on its first call to open(). */ |
134 | RTSR = RTSR_AL | RTSR_HZ; | 121 | rtc_writel(sa1100_rtc, RTSR, (RTSR_AL | RTSR_HZ)); |
135 | } | 122 | } |
136 | 123 | ||
137 | /* clear alarm interrupt if it has occurred */ | 124 | /* clear alarm interrupt if it has occurred */ |
138 | if (rtsr & RTSR_AL) | 125 | if (rtsr & RTSR_AL) |
139 | rtsr &= ~RTSR_ALE; | 126 | rtsr &= ~RTSR_ALE; |
140 | RTSR = rtsr & (RTSR_ALE | RTSR_HZE); | 127 | rtc_writel(sa1100_rtc, RTSR, rtsr & (RTSR_ALE | RTSR_HZE)); |
141 | 128 | ||
142 | /* update irq data & counter */ | 129 | /* update irq data & counter */ |
143 | if (rtsr & RTSR_AL) | 130 | if (rtsr & RTSR_AL) |
@@ -145,91 +132,100 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) | |||
145 | if (rtsr & RTSR_HZ) | 132 | if (rtsr & RTSR_HZ) |
146 | events |= RTC_UF | RTC_IRQF; | 133 | events |= RTC_UF | RTC_IRQF; |
147 | 134 | ||
148 | rtc_update_irq(rtc, 1, events); | 135 | rtc_update_irq(sa1100_rtc->rtc, 1, events); |
149 | 136 | ||
150 | if (rtsr & RTSR_AL && rtc_periodic_alarm(&rtc_alarm)) | 137 | spin_unlock(&sa1100_rtc->lock); |
151 | rtc_update_alarm(&rtc_alarm); | ||
152 | |||
153 | spin_unlock(&sa1100_rtc_lock); | ||
154 | 138 | ||
155 | return IRQ_HANDLED; | 139 | return IRQ_HANDLED; |
156 | } | 140 | } |
157 | 141 | ||
158 | static int sa1100_rtc_open(struct device *dev) | 142 | static int sa1100_rtc_open(struct device *dev) |
159 | { | 143 | { |
144 | struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); | ||
160 | int ret; | 145 | int ret; |
161 | struct platform_device *plat_dev = to_platform_device(dev); | ||
162 | struct rtc_device *rtc = platform_get_drvdata(plat_dev); | ||
163 | 146 | ||
164 | ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED, | 147 | ret = request_irq(sa1100_rtc->irq_1Hz, sa1100_rtc_interrupt, |
165 | "rtc 1Hz", dev); | 148 | IRQF_DISABLED, "rtc 1Hz", dev); |
166 | if (ret) { | 149 | if (ret) { |
167 | dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz); | 150 | dev_err(dev, "IRQ %d already in use.\n", sa1100_rtc->irq_1Hz); |
168 | goto fail_ui; | 151 | goto fail_ui; |
169 | } | 152 | } |
170 | ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, IRQF_DISABLED, | 153 | ret = request_irq(sa1100_rtc->irq_Alrm, sa1100_rtc_interrupt, |
171 | "rtc Alrm", dev); | 154 | IRQF_DISABLED, "rtc Alrm", dev); |
172 | if (ret) { | 155 | if (ret) { |
173 | dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm); | 156 | dev_err(dev, "IRQ %d already in use.\n", sa1100_rtc->irq_Alrm); |
174 | goto fail_ai; | 157 | goto fail_ai; |
175 | } | 158 | } |
176 | rtc->max_user_freq = RTC_FREQ; | 159 | sa1100_rtc->rtc->max_user_freq = RTC_FREQ; |
177 | rtc_irq_set_freq(rtc, NULL, RTC_FREQ); | 160 | rtc_irq_set_freq(sa1100_rtc->rtc, NULL, RTC_FREQ); |
178 | 161 | ||
179 | return 0; | 162 | return 0; |
180 | 163 | ||
181 | fail_ai: | 164 | fail_ai: |
182 | free_irq(IRQ_RTC1Hz, dev); | 165 | free_irq(sa1100_rtc->irq_1Hz, dev); |
183 | fail_ui: | 166 | fail_ui: |
184 | return ret; | 167 | return ret; |
185 | } | 168 | } |
186 | 169 | ||
187 | static void sa1100_rtc_release(struct device *dev) | 170 | static void sa1100_rtc_release(struct device *dev) |
188 | { | 171 | { |
189 | spin_lock_irq(&sa1100_rtc_lock); | 172 | struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); |
190 | RTSR = 0; | 173 | |
191 | OIER &= ~OIER_E1; | 174 | spin_lock_irq(&sa1100_rtc->lock); |
192 | OSSR = OSSR_M1; | 175 | rtc_writel(sa1100_rtc, RTSR, 0); |
193 | spin_unlock_irq(&sa1100_rtc_lock); | 176 | spin_unlock_irq(&sa1100_rtc->lock); |
194 | 177 | ||
195 | free_irq(IRQ_RTCAlrm, dev); | 178 | free_irq(sa1100_rtc->irq_Alrm, dev); |
196 | free_irq(IRQ_RTC1Hz, dev); | 179 | free_irq(sa1100_rtc->irq_1Hz, dev); |
197 | } | 180 | } |
198 | 181 | ||
199 | static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | 182 | static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) |
200 | { | 183 | { |
201 | spin_lock_irq(&sa1100_rtc_lock); | 184 | struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); |
185 | unsigned int rtsr; | ||
186 | |||
187 | spin_lock_irq(&sa1100_rtc->lock); | ||
188 | |||
189 | rtsr = rtc_readl(sa1100_rtc, RTSR); | ||
202 | if (enabled) | 190 | if (enabled) |
203 | RTSR |= RTSR_ALE; | 191 | rtsr |= RTSR_ALE; |
204 | else | 192 | else |
205 | RTSR &= ~RTSR_ALE; | 193 | rtsr &= ~RTSR_ALE; |
206 | spin_unlock_irq(&sa1100_rtc_lock); | 194 | rtc_writel(sa1100_rtc, RTSR, rtsr); |
195 | |||
196 | spin_unlock_irq(&sa1100_rtc->lock); | ||
207 | return 0; | 197 | return 0; |
208 | } | 198 | } |
209 | 199 | ||
210 | static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm) | 200 | static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm) |
211 | { | 201 | { |
212 | rtc_time_to_tm(RCNR, tm); | 202 | struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); |
203 | |||
204 | rtc_time_to_tm(rtc_readl(sa1100_rtc, RCNR), tm); | ||
213 | return 0; | 205 | return 0; |
214 | } | 206 | } |
215 | 207 | ||
216 | static int sa1100_rtc_set_time(struct device *dev, struct rtc_time *tm) | 208 | static int sa1100_rtc_set_time(struct device *dev, struct rtc_time *tm) |
217 | { | 209 | { |
210 | struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); | ||
218 | unsigned long time; | 211 | unsigned long time; |
219 | int ret; | 212 | int ret; |
220 | 213 | ||
221 | ret = rtc_tm_to_time(tm, &time); | 214 | ret = rtc_tm_to_time(tm, &time); |
222 | if (ret == 0) | 215 | if (ret == 0) |
223 | RCNR = time; | 216 | rtc_writel(sa1100_rtc, RCNR, time); |
224 | return ret; | 217 | return ret; |
225 | } | 218 | } |
226 | 219 | ||
227 | static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 220 | static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
228 | { | 221 | { |
229 | u32 rtsr; | 222 | struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); |
223 | unsigned long time; | ||
224 | unsigned int rtsr; | ||
230 | 225 | ||
231 | memcpy(&alrm->time, &rtc_alarm, sizeof(struct rtc_time)); | 226 | time = rtc_readl(sa1100_rtc, RCNR); |
232 | rtsr = RTSR; | 227 | rtc_time_to_tm(time, &alrm->time); |
228 | rtsr = rtc_readl(sa1100_rtc, RTSR); | ||
233 | alrm->enabled = (rtsr & RTSR_ALE) ? 1 : 0; | 229 | alrm->enabled = (rtsr & RTSR_ALE) ? 1 : 0; |
234 | alrm->pending = (rtsr & RTSR_AL) ? 1 : 0; | 230 | alrm->pending = (rtsr & RTSR_AL) ? 1 : 0; |
235 | return 0; | 231 | return 0; |
@@ -237,26 +233,39 @@ static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
237 | 233 | ||
238 | static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 234 | static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
239 | { | 235 | { |
240 | int ret; | 236 | struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); |
237 | struct rtc_time now_tm, alarm_tm; | ||
238 | unsigned long time, alarm; | ||
239 | unsigned int rtsr; | ||
241 | 240 | ||
242 | spin_lock_irq(&sa1100_rtc_lock); | 241 | spin_lock_irq(&sa1100_rtc->lock); |
243 | ret = rtc_update_alarm(&alrm->time); | ||
244 | if (ret == 0) { | ||
245 | if (alrm->enabled) | ||
246 | RTSR |= RTSR_ALE; | ||
247 | else | ||
248 | RTSR &= ~RTSR_ALE; | ||
249 | } | ||
250 | spin_unlock_irq(&sa1100_rtc_lock); | ||
251 | 242 | ||
252 | return ret; | 243 | time = rtc_readl(sa1100_rtc, RCNR); |
244 | rtc_time_to_tm(time, &now_tm); | ||
245 | rtc_next_alarm_time(&alarm_tm, &now_tm, &alrm->time); | ||
246 | rtc_tm_to_time(&alarm_tm, &alarm); | ||
247 | rtc_writel(sa1100_rtc, RTAR, alarm); | ||
248 | |||
249 | rtsr = rtc_readl(sa1100_rtc, RTSR); | ||
250 | if (alrm->enabled) | ||
251 | rtsr |= RTSR_ALE; | ||
252 | else | ||
253 | rtsr &= ~RTSR_ALE; | ||
254 | rtc_writel(sa1100_rtc, RTSR, rtsr); | ||
255 | |||
256 | spin_unlock_irq(&sa1100_rtc->lock); | ||
257 | |||
258 | return 0; | ||
253 | } | 259 | } |
254 | 260 | ||
255 | static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq) | 261 | static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq) |
256 | { | 262 | { |
257 | seq_printf(seq, "trim/divider\t\t: 0x%08x\n", (u32) RTTR); | 263 | struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); |
258 | seq_printf(seq, "RTSR\t\t\t: 0x%08x\n", (u32)RTSR); | ||
259 | 264 | ||
265 | seq_printf(seq, "trim/divider\t\t: 0x%08x\n", | ||
266 | rtc_readl(sa1100_rtc, RTTR)); | ||
267 | seq_printf(seq, "RTSR\t\t\t: 0x%08x\n", | ||
268 | rtc_readl(sa1100_rtc, RTSR)); | ||
260 | return 0; | 269 | return 0; |
261 | } | 270 | } |
262 | 271 | ||
@@ -273,7 +282,51 @@ static const struct rtc_class_ops sa1100_rtc_ops = { | |||
273 | 282 | ||
274 | static int sa1100_rtc_probe(struct platform_device *pdev) | 283 | static int sa1100_rtc_probe(struct platform_device *pdev) |
275 | { | 284 | { |
276 | struct rtc_device *rtc; | 285 | struct sa1100_rtc *sa1100_rtc; |
286 | unsigned int rttr; | ||
287 | int ret; | ||
288 | |||
289 | sa1100_rtc = kzalloc(sizeof(struct sa1100_rtc), GFP_KERNEL); | ||
290 | if (!sa1100_rtc) | ||
291 | return -ENOMEM; | ||
292 | |||
293 | spin_lock_init(&sa1100_rtc->lock); | ||
294 | platform_set_drvdata(pdev, sa1100_rtc); | ||
295 | |||
296 | ret = -ENXIO; | ||
297 | sa1100_rtc->ress = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
298 | if (!sa1100_rtc->ress) { | ||
299 | dev_err(&pdev->dev, "No I/O memory resource defined\n"); | ||
300 | goto err_ress; | ||
301 | } | ||
302 | |||
303 | sa1100_rtc->irq_1Hz = platform_get_irq(pdev, 0); | ||
304 | if (sa1100_rtc->irq_1Hz < 0) { | ||
305 | dev_err(&pdev->dev, "No 1Hz IRQ resource defined\n"); | ||
306 | goto err_ress; | ||
307 | } | ||
308 | sa1100_rtc->irq_Alrm = platform_get_irq(pdev, 1); | ||
309 | if (sa1100_rtc->irq_Alrm < 0) { | ||
310 | dev_err(&pdev->dev, "No alarm IRQ resource defined\n"); | ||
311 | goto err_ress; | ||
312 | } | ||
313 | |||
314 | ret = -ENOMEM; | ||
315 | sa1100_rtc->base = ioremap(sa1100_rtc->ress->start, | ||
316 | resource_size(sa1100_rtc->ress)); | ||
317 | if (!sa1100_rtc->base) { | ||
318 | dev_err(&pdev->dev, "Unable to map pxa RTC I/O memory\n"); | ||
319 | goto err_map; | ||
320 | } | ||
321 | |||
322 | sa1100_rtc->clk = clk_get(&pdev->dev, NULL); | ||
323 | if (IS_ERR(sa1100_rtc->clk)) { | ||
324 | dev_err(&pdev->dev, "failed to find rtc clock source\n"); | ||
325 | ret = PTR_ERR(sa1100_rtc->clk); | ||
326 | goto err_clk; | ||
327 | } | ||
328 | clk_prepare(sa1100_rtc->clk); | ||
329 | clk_enable(sa1100_rtc->clk); | ||
277 | 330 | ||
278 | /* | 331 | /* |
279 | * According to the manual we should be able to let RTTR be zero | 332 | * According to the manual we should be able to let RTTR be zero |
@@ -282,24 +335,24 @@ static int sa1100_rtc_probe(struct platform_device *pdev) | |||
282 | * If the clock divider is uninitialized then reset it to the | 335 | * If the clock divider is uninitialized then reset it to the |
283 | * default value to get the 1Hz clock. | 336 | * default value to get the 1Hz clock. |
284 | */ | 337 | */ |
285 | if (RTTR == 0) { | 338 | if (rtc_readl(sa1100_rtc, RTTR) == 0) { |
286 | RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16); | 339 | rttr = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16); |
287 | dev_warn(&pdev->dev, "warning: " | 340 | rtc_writel(sa1100_rtc, RTTR, rttr); |
288 | "initializing default clock divider/trim value\n"); | 341 | dev_warn(&pdev->dev, "warning: initializing default clock" |
342 | " divider/trim value\n"); | ||
289 | /* The current RTC value probably doesn't make sense either */ | 343 | /* The current RTC value probably doesn't make sense either */ |
290 | RCNR = 0; | 344 | rtc_writel(sa1100_rtc, RCNR, 0); |
291 | } | 345 | } |
292 | 346 | ||
293 | device_init_wakeup(&pdev->dev, 1); | 347 | device_init_wakeup(&pdev->dev, 1); |
294 | 348 | ||
295 | rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops, | 349 | sa1100_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, |
296 | THIS_MODULE); | 350 | &sa1100_rtc_ops, THIS_MODULE); |
297 | 351 | if (IS_ERR(sa1100_rtc->rtc)) { | |
298 | if (IS_ERR(rtc)) | 352 | dev_err(&pdev->dev, "Failed to register RTC device -> %d\n", |
299 | return PTR_ERR(rtc); | 353 | ret); |
300 | 354 | goto err_rtc_reg; | |
301 | platform_set_drvdata(pdev, rtc); | 355 | } |
302 | |||
303 | /* Fix for a nasty initialization problem the in SA11xx RTSR register. | 356 | /* Fix for a nasty initialization problem the in SA11xx RTSR register. |
304 | * See also the comments in sa1100_rtc_interrupt(). | 357 | * See also the comments in sa1100_rtc_interrupt(). |
305 | * | 358 | * |
@@ -322,33 +375,46 @@ static int sa1100_rtc_probe(struct platform_device *pdev) | |||
322 | * | 375 | * |
323 | * Notice that clearing bit 1 and 0 is accomplished by writting ONES to | 376 | * Notice that clearing bit 1 and 0 is accomplished by writting ONES to |
324 | * the corresponding bits in RTSR. */ | 377 | * the corresponding bits in RTSR. */ |
325 | RTSR = RTSR_AL | RTSR_HZ; | 378 | rtc_writel(sa1100_rtc, RTSR, (RTSR_AL | RTSR_HZ)); |
326 | 379 | ||
327 | return 0; | 380 | return 0; |
381 | |||
382 | err_rtc_reg: | ||
383 | err_clk: | ||
384 | iounmap(sa1100_rtc->base); | ||
385 | err_ress: | ||
386 | err_map: | ||
387 | kfree(sa1100_rtc); | ||
388 | return ret; | ||
328 | } | 389 | } |
329 | 390 | ||
330 | static int sa1100_rtc_remove(struct platform_device *pdev) | 391 | static int sa1100_rtc_remove(struct platform_device *pdev) |
331 | { | 392 | { |
332 | struct rtc_device *rtc = platform_get_drvdata(pdev); | 393 | struct sa1100_rtc *sa1100_rtc = platform_get_drvdata(pdev); |
333 | |||
334 | if (rtc) | ||
335 | rtc_device_unregister(rtc); | ||
336 | 394 | ||
395 | rtc_device_unregister(sa1100_rtc->rtc); | ||
396 | clk_disable(sa1100_rtc->clk); | ||
397 | clk_unprepare(sa1100_rtc->clk); | ||
398 | iounmap(sa1100_rtc->base); | ||
337 | return 0; | 399 | return 0; |
338 | } | 400 | } |
339 | 401 | ||
340 | #ifdef CONFIG_PM | 402 | #ifdef CONFIG_PM |
341 | static int sa1100_rtc_suspend(struct device *dev) | 403 | static int sa1100_rtc_suspend(struct device *dev) |
342 | { | 404 | { |
405 | struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); | ||
406 | |||
343 | if (device_may_wakeup(dev)) | 407 | if (device_may_wakeup(dev)) |
344 | enable_irq_wake(IRQ_RTCAlrm); | 408 | enable_irq_wake(sa1100_rtc->irq_Alrm); |
345 | return 0; | 409 | return 0; |
346 | } | 410 | } |
347 | 411 | ||
348 | static int sa1100_rtc_resume(struct device *dev) | 412 | static int sa1100_rtc_resume(struct device *dev) |
349 | { | 413 | { |
414 | struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); | ||
415 | |||
350 | if (device_may_wakeup(dev)) | 416 | if (device_may_wakeup(dev)) |
351 | disable_irq_wake(IRQ_RTCAlrm); | 417 | disable_irq_wake(sa1100_rtc->irq_Alrm); |
352 | return 0; | 418 | return 0; |
353 | } | 419 | } |
354 | 420 | ||