diff options
Diffstat (limited to 'drivers/rtc/rtc-bfin.c')
-rw-r--r-- | drivers/rtc/rtc-bfin.c | 81 |
1 files changed, 36 insertions, 45 deletions
diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index d4fb82d85e9b..90d866272c8e 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Blackfin On-Chip Real Time Clock Driver | 2 | * Blackfin On-Chip Real Time Clock Driver |
3 | * Supports BF51x/BF52x/BF53[123]/BF53[467]/BF54x | 3 | * Supports BF51x/BF52x/BF53[123]/BF53[467]/BF54x |
4 | * | 4 | * |
5 | * Copyright 2004-2009 Analog Devices Inc. | 5 | * Copyright 2004-2010 Analog Devices Inc. |
6 | * | 6 | * |
7 | * Enter bugs at http://blackfin.uclinux.org/ | 7 | * Enter bugs at http://blackfin.uclinux.org/ |
8 | * | 8 | * |
@@ -20,9 +20,9 @@ | |||
20 | * write would be discarded and things quickly fall apart. | 20 | * write would be discarded and things quickly fall apart. |
21 | * | 21 | * |
22 | * To keep this delay from significantly degrading performance (we, in theory, | 22 | * To keep this delay from significantly degrading performance (we, in theory, |
23 | * would have to sleep for up to 1 second everytime we wanted to write a | 23 | * would have to sleep for up to 1 second every time we wanted to write a |
24 | * register), we only check the write pending status before we start to issue | 24 | * register), we only check the write pending status before we start to issue |
25 | * a new write. We bank on the idea that it doesnt matter when the sync | 25 | * a new write. We bank on the idea that it doesn't matter when the sync |
26 | * happens so long as we don't attempt another write before it does. The only | 26 | * happens so long as we don't attempt another write before it does. The only |
27 | * time userspace would take this penalty is when they try and do multiple | 27 | * time userspace would take this penalty is when they try and do multiple |
28 | * operations right after another ... but in this case, they need to take the | 28 | * operations right after another ... but in this case, they need to take the |
@@ -183,29 +183,33 @@ static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id) | |||
183 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | 183 | struct bfin_rtc *rtc = dev_get_drvdata(dev); |
184 | unsigned long events = 0; | 184 | unsigned long events = 0; |
185 | bool write_complete = false; | 185 | bool write_complete = false; |
186 | u16 rtc_istat, rtc_ictl; | 186 | u16 rtc_istat, rtc_istat_clear, rtc_ictl, bits; |
187 | 187 | ||
188 | dev_dbg_stamp(dev); | 188 | dev_dbg_stamp(dev); |
189 | 189 | ||
190 | rtc_istat = bfin_read_RTC_ISTAT(); | 190 | rtc_istat = bfin_read_RTC_ISTAT(); |
191 | rtc_ictl = bfin_read_RTC_ICTL(); | 191 | rtc_ictl = bfin_read_RTC_ICTL(); |
192 | rtc_istat_clear = 0; | ||
192 | 193 | ||
193 | if (rtc_istat & RTC_ISTAT_WRITE_COMPLETE) { | 194 | bits = RTC_ISTAT_WRITE_COMPLETE; |
194 | bfin_write_RTC_ISTAT(RTC_ISTAT_WRITE_COMPLETE); | 195 | if (rtc_istat & bits) { |
196 | rtc_istat_clear |= bits; | ||
195 | write_complete = true; | 197 | write_complete = true; |
196 | complete(&bfin_write_complete); | 198 | complete(&bfin_write_complete); |
197 | } | 199 | } |
198 | 200 | ||
199 | if (rtc_ictl & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)) { | 201 | bits = (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY); |
200 | if (rtc_istat & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)) { | 202 | if (rtc_ictl & bits) { |
201 | bfin_write_RTC_ISTAT(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY); | 203 | if (rtc_istat & bits) { |
204 | rtc_istat_clear |= bits; | ||
202 | events |= RTC_AF | RTC_IRQF; | 205 | events |= RTC_AF | RTC_IRQF; |
203 | } | 206 | } |
204 | } | 207 | } |
205 | 208 | ||
206 | if (rtc_ictl & RTC_ISTAT_SEC) { | 209 | bits = RTC_ISTAT_SEC; |
207 | if (rtc_istat & RTC_ISTAT_SEC) { | 210 | if (rtc_ictl & bits) { |
208 | bfin_write_RTC_ISTAT(RTC_ISTAT_SEC); | 211 | if (rtc_istat & bits) { |
212 | rtc_istat_clear |= bits; | ||
209 | events |= RTC_UF | RTC_IRQF; | 213 | events |= RTC_UF | RTC_IRQF; |
210 | } | 214 | } |
211 | } | 215 | } |
@@ -213,9 +217,10 @@ static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id) | |||
213 | if (events) | 217 | if (events) |
214 | rtc_update_irq(rtc->rtc_dev, 1, events); | 218 | rtc_update_irq(rtc->rtc_dev, 1, events); |
215 | 219 | ||
216 | if (write_complete || events) | 220 | if (write_complete || events) { |
221 | bfin_write_RTC_ISTAT(rtc_istat_clear); | ||
217 | return IRQ_HANDLED; | 222 | return IRQ_HANDLED; |
218 | else | 223 | } else |
219 | return IRQ_NONE; | 224 | return IRQ_NONE; |
220 | } | 225 | } |
221 | 226 | ||
@@ -235,40 +240,18 @@ static void bfin_rtc_int_set_alarm(struct bfin_rtc *rtc) | |||
235 | */ | 240 | */ |
236 | bfin_rtc_int_set(rtc->rtc_alarm.tm_yday == -1 ? RTC_ISTAT_ALARM : RTC_ISTAT_ALARM_DAY); | 241 | bfin_rtc_int_set(rtc->rtc_alarm.tm_yday == -1 ? RTC_ISTAT_ALARM : RTC_ISTAT_ALARM_DAY); |
237 | } | 242 | } |
238 | static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 243 | |
244 | static int bfin_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
239 | { | 245 | { |
240 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | 246 | struct bfin_rtc *rtc = dev_get_drvdata(dev); |
241 | int ret = 0; | ||
242 | 247 | ||
243 | dev_dbg_stamp(dev); | 248 | dev_dbg_stamp(dev); |
244 | 249 | if (enabled) | |
245 | bfin_rtc_sync_pending(dev); | ||
246 | |||
247 | switch (cmd) { | ||
248 | case RTC_UIE_ON: | ||
249 | dev_dbg_stamp(dev); | ||
250 | bfin_rtc_int_set(RTC_ISTAT_SEC); | ||
251 | break; | ||
252 | case RTC_UIE_OFF: | ||
253 | dev_dbg_stamp(dev); | ||
254 | bfin_rtc_int_clear(~RTC_ISTAT_SEC); | ||
255 | break; | ||
256 | |||
257 | case RTC_AIE_ON: | ||
258 | dev_dbg_stamp(dev); | ||
259 | bfin_rtc_int_set_alarm(rtc); | 250 | bfin_rtc_int_set_alarm(rtc); |
260 | break; | 251 | else |
261 | case RTC_AIE_OFF: | ||
262 | dev_dbg_stamp(dev); | ||
263 | bfin_rtc_int_clear(~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); | 252 | bfin_rtc_int_clear(~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); |
264 | break; | ||
265 | 253 | ||
266 | default: | 254 | return 0; |
267 | dev_dbg_stamp(dev); | ||
268 | ret = -ENOIOCTLCMD; | ||
269 | } | ||
270 | |||
271 | return ret; | ||
272 | } | 255 | } |
273 | 256 | ||
274 | static int bfin_rtc_read_time(struct device *dev, struct rtc_time *tm) | 257 | static int bfin_rtc_read_time(struct device *dev, struct rtc_time *tm) |
@@ -351,12 +334,12 @@ static int bfin_rtc_proc(struct device *dev, struct seq_file *seq) | |||
351 | } | 334 | } |
352 | 335 | ||
353 | static struct rtc_class_ops bfin_rtc_ops = { | 336 | static struct rtc_class_ops bfin_rtc_ops = { |
354 | .ioctl = bfin_rtc_ioctl, | ||
355 | .read_time = bfin_rtc_read_time, | 337 | .read_time = bfin_rtc_read_time, |
356 | .set_time = bfin_rtc_set_time, | 338 | .set_time = bfin_rtc_set_time, |
357 | .read_alarm = bfin_rtc_read_alarm, | 339 | .read_alarm = bfin_rtc_read_alarm, |
358 | .set_alarm = bfin_rtc_set_alarm, | 340 | .set_alarm = bfin_rtc_set_alarm, |
359 | .proc = bfin_rtc_proc, | 341 | .proc = bfin_rtc_proc, |
342 | .alarm_irq_enable = bfin_rtc_alarm_irq_enable, | ||
360 | }; | 343 | }; |
361 | 344 | ||
362 | static int __devinit bfin_rtc_probe(struct platform_device *pdev) | 345 | static int __devinit bfin_rtc_probe(struct platform_device *pdev) |
@@ -422,9 +405,13 @@ static int __devexit bfin_rtc_remove(struct platform_device *pdev) | |||
422 | #ifdef CONFIG_PM | 405 | #ifdef CONFIG_PM |
423 | static int bfin_rtc_suspend(struct platform_device *pdev, pm_message_t state) | 406 | static int bfin_rtc_suspend(struct platform_device *pdev, pm_message_t state) |
424 | { | 407 | { |
425 | if (device_may_wakeup(&pdev->dev)) { | 408 | struct device *dev = &pdev->dev; |
409 | |||
410 | dev_dbg_stamp(dev); | ||
411 | |||
412 | if (device_may_wakeup(dev)) { | ||
426 | enable_irq_wake(IRQ_RTC); | 413 | enable_irq_wake(IRQ_RTC); |
427 | bfin_rtc_sync_pending(&pdev->dev); | 414 | bfin_rtc_sync_pending(dev); |
428 | } else | 415 | } else |
429 | bfin_rtc_int_clear(0); | 416 | bfin_rtc_int_clear(0); |
430 | 417 | ||
@@ -433,7 +420,11 @@ static int bfin_rtc_suspend(struct platform_device *pdev, pm_message_t state) | |||
433 | 420 | ||
434 | static int bfin_rtc_resume(struct platform_device *pdev) | 421 | static int bfin_rtc_resume(struct platform_device *pdev) |
435 | { | 422 | { |
436 | if (device_may_wakeup(&pdev->dev)) | 423 | struct device *dev = &pdev->dev; |
424 | |||
425 | dev_dbg_stamp(dev); | ||
426 | |||
427 | if (device_may_wakeup(dev)) | ||
437 | disable_irq_wake(IRQ_RTC); | 428 | disable_irq_wake(IRQ_RTC); |
438 | 429 | ||
439 | /* | 430 | /* |