diff options
Diffstat (limited to 'drivers/rtc/rtc-bfin.c')
-rw-r--r-- | drivers/rtc/rtc-bfin.c | 89 |
1 files changed, 56 insertions, 33 deletions
diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index aafd3e6ebb0d..b4b6087f2234 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Blackfin On-Chip Real Time Clock Driver | 2 | * Blackfin On-Chip Real Time Clock Driver |
3 | * Supports BF52[257]/BF53[123]/BF53[467]/BF54[24789] | 3 | * Supports BF51x/BF52x/BF53[123]/BF53[467]/BF54x |
4 | * | 4 | * |
5 | * Copyright 2004-2008 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 | * |
@@ -51,6 +51,7 @@ | |||
51 | #include <linux/platform_device.h> | 51 | #include <linux/platform_device.h> |
52 | #include <linux/rtc.h> | 52 | #include <linux/rtc.h> |
53 | #include <linux/seq_file.h> | 53 | #include <linux/seq_file.h> |
54 | #include <linux/slab.h> | ||
54 | 55 | ||
55 | #include <asm/blackfin.h> | 56 | #include <asm/blackfin.h> |
56 | 57 | ||
@@ -182,29 +183,33 @@ static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id) | |||
182 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | 183 | struct bfin_rtc *rtc = dev_get_drvdata(dev); |
183 | unsigned long events = 0; | 184 | unsigned long events = 0; |
184 | bool write_complete = false; | 185 | bool write_complete = false; |
185 | u16 rtc_istat, rtc_ictl; | 186 | u16 rtc_istat, rtc_istat_clear, rtc_ictl, bits; |
186 | 187 | ||
187 | dev_dbg_stamp(dev); | 188 | dev_dbg_stamp(dev); |
188 | 189 | ||
189 | rtc_istat = bfin_read_RTC_ISTAT(); | 190 | rtc_istat = bfin_read_RTC_ISTAT(); |
190 | rtc_ictl = bfin_read_RTC_ICTL(); | 191 | rtc_ictl = bfin_read_RTC_ICTL(); |
192 | rtc_istat_clear = 0; | ||
191 | 193 | ||
192 | if (rtc_istat & RTC_ISTAT_WRITE_COMPLETE) { | 194 | bits = RTC_ISTAT_WRITE_COMPLETE; |
193 | bfin_write_RTC_ISTAT(RTC_ISTAT_WRITE_COMPLETE); | 195 | if (rtc_istat & bits) { |
196 | rtc_istat_clear |= bits; | ||
194 | write_complete = true; | 197 | write_complete = true; |
195 | complete(&bfin_write_complete); | 198 | complete(&bfin_write_complete); |
196 | } | 199 | } |
197 | 200 | ||
198 | if (rtc_ictl & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)) { | 201 | bits = (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY); |
199 | if (rtc_istat & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)) { | 202 | if (rtc_ictl & bits) { |
200 | bfin_write_RTC_ISTAT(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY); | 203 | if (rtc_istat & bits) { |
204 | rtc_istat_clear |= bits; | ||
201 | events |= RTC_AF | RTC_IRQF; | 205 | events |= RTC_AF | RTC_IRQF; |
202 | } | 206 | } |
203 | } | 207 | } |
204 | 208 | ||
205 | if (rtc_ictl & RTC_ISTAT_SEC) { | 209 | bits = RTC_ISTAT_SEC; |
206 | if (rtc_istat & RTC_ISTAT_SEC) { | 210 | if (rtc_ictl & bits) { |
207 | bfin_write_RTC_ISTAT(RTC_ISTAT_SEC); | 211 | if (rtc_istat & bits) { |
212 | rtc_istat_clear |= bits; | ||
208 | events |= RTC_UF | RTC_IRQF; | 213 | events |= RTC_UF | RTC_IRQF; |
209 | } | 214 | } |
210 | } | 215 | } |
@@ -212,9 +217,10 @@ static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id) | |||
212 | if (events) | 217 | if (events) |
213 | rtc_update_irq(rtc->rtc_dev, 1, events); | 218 | rtc_update_irq(rtc->rtc_dev, 1, events); |
214 | 219 | ||
215 | if (write_complete || events) | 220 | if (write_complete || events) { |
221 | bfin_write_RTC_ISTAT(rtc_istat_clear); | ||
216 | return IRQ_HANDLED; | 222 | return IRQ_HANDLED; |
217 | else | 223 | } else |
218 | return IRQ_NONE; | 224 | return IRQ_NONE; |
219 | } | 225 | } |
220 | 226 | ||
@@ -363,7 +369,7 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev) | |||
363 | struct bfin_rtc *rtc; | 369 | struct bfin_rtc *rtc; |
364 | struct device *dev = &pdev->dev; | 370 | struct device *dev = &pdev->dev; |
365 | int ret = 0; | 371 | int ret = 0; |
366 | unsigned long timeout; | 372 | unsigned long timeout = jiffies + HZ; |
367 | 373 | ||
368 | dev_dbg_stamp(dev); | 374 | dev_dbg_stamp(dev); |
369 | 375 | ||
@@ -374,32 +380,32 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev) | |||
374 | platform_set_drvdata(pdev, rtc); | 380 | platform_set_drvdata(pdev, rtc); |
375 | device_init_wakeup(dev, 1); | 381 | device_init_wakeup(dev, 1); |
376 | 382 | ||
383 | /* Register our RTC with the RTC framework */ | ||
384 | rtc->rtc_dev = rtc_device_register(pdev->name, dev, &bfin_rtc_ops, | ||
385 | THIS_MODULE); | ||
386 | if (unlikely(IS_ERR(rtc->rtc_dev))) { | ||
387 | ret = PTR_ERR(rtc->rtc_dev); | ||
388 | goto err; | ||
389 | } | ||
390 | |||
377 | /* Grab the IRQ and init the hardware */ | 391 | /* Grab the IRQ and init the hardware */ |
378 | ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_SHARED, pdev->name, dev); | 392 | ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, 0, pdev->name, dev); |
379 | if (unlikely(ret)) | 393 | if (unlikely(ret)) |
380 | goto err; | 394 | goto err_reg; |
381 | /* sometimes the bootloader touched things, but the write complete was not | 395 | /* sometimes the bootloader touched things, but the write complete was not |
382 | * enabled, so let's just do a quick timeout here since the IRQ will not fire ... | 396 | * enabled, so let's just do a quick timeout here since the IRQ will not fire ... |
383 | */ | 397 | */ |
384 | timeout = jiffies + HZ; | ||
385 | while (bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING) | 398 | while (bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING) |
386 | if (time_after(jiffies, timeout)) | 399 | if (time_after(jiffies, timeout)) |
387 | break; | 400 | break; |
388 | bfin_rtc_reset(dev, RTC_ISTAT_WRITE_COMPLETE); | 401 | bfin_rtc_reset(dev, RTC_ISTAT_WRITE_COMPLETE); |
389 | bfin_write_RTC_SWCNT(0); | 402 | bfin_write_RTC_SWCNT(0); |
390 | 403 | ||
391 | /* Register our RTC with the RTC framework */ | ||
392 | rtc->rtc_dev = rtc_device_register(pdev->name, dev, &bfin_rtc_ops, THIS_MODULE); | ||
393 | if (unlikely(IS_ERR(rtc->rtc_dev))) { | ||
394 | ret = PTR_ERR(rtc->rtc_dev); | ||
395 | goto err_irq; | ||
396 | } | ||
397 | |||
398 | return 0; | 404 | return 0; |
399 | 405 | ||
400 | err_irq: | 406 | err_reg: |
401 | free_irq(IRQ_RTC, dev); | 407 | rtc_device_unregister(rtc->rtc_dev); |
402 | err: | 408 | err: |
403 | kfree(rtc); | 409 | kfree(rtc); |
404 | return ret; | 410 | return ret; |
405 | } | 411 | } |
@@ -421,21 +427,38 @@ static int __devexit bfin_rtc_remove(struct platform_device *pdev) | |||
421 | #ifdef CONFIG_PM | 427 | #ifdef CONFIG_PM |
422 | static int bfin_rtc_suspend(struct platform_device *pdev, pm_message_t state) | 428 | static int bfin_rtc_suspend(struct platform_device *pdev, pm_message_t state) |
423 | { | 429 | { |
424 | if (device_may_wakeup(&pdev->dev)) { | 430 | struct device *dev = &pdev->dev; |
431 | |||
432 | dev_dbg_stamp(dev); | ||
433 | |||
434 | if (device_may_wakeup(dev)) { | ||
425 | enable_irq_wake(IRQ_RTC); | 435 | enable_irq_wake(IRQ_RTC); |
426 | bfin_rtc_sync_pending(&pdev->dev); | 436 | bfin_rtc_sync_pending(dev); |
427 | } else | 437 | } else |
428 | bfin_rtc_int_clear(-1); | 438 | bfin_rtc_int_clear(0); |
429 | 439 | ||
430 | return 0; | 440 | return 0; |
431 | } | 441 | } |
432 | 442 | ||
433 | static int bfin_rtc_resume(struct platform_device *pdev) | 443 | static int bfin_rtc_resume(struct platform_device *pdev) |
434 | { | 444 | { |
435 | if (device_may_wakeup(&pdev->dev)) | 445 | struct device *dev = &pdev->dev; |
446 | |||
447 | dev_dbg_stamp(dev); | ||
448 | |||
449 | if (device_may_wakeup(dev)) | ||
436 | disable_irq_wake(IRQ_RTC); | 450 | disable_irq_wake(IRQ_RTC); |
437 | else | 451 | |
438 | bfin_write_RTC_ISTAT(-1); | 452 | /* |
453 | * Since only some of the RTC bits are maintained externally in the | ||
454 | * Vbat domain, we need to wait for the RTC MMRs to be synced into | ||
455 | * the core after waking up. This happens every RTC 1HZ. Once that | ||
456 | * has happened, we can go ahead and re-enable the important write | ||
457 | * complete interrupt event. | ||
458 | */ | ||
459 | while (!(bfin_read_RTC_ISTAT() & RTC_ISTAT_SEC)) | ||
460 | continue; | ||
461 | bfin_rtc_int_set(RTC_ISTAT_WRITE_COMPLETE); | ||
439 | 462 | ||
440 | return 0; | 463 | return 0; |
441 | } | 464 | } |