From patchwork Tue Aug 17 04:44:07 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [2/4] rtc-bfin: fix state restoration when resuming Date: Mon, 16 Aug 2010 18:44:07 -0000 From: Mike Frysinger X-Patchwork-Id: 61854 Message-Id: <1282020249-8807-2-git-send-email-vapier@gentoo.org> To: rtc-linux@googlegroups.com, Alessandro Zummo Cc: uclinux-dist-devel@blackfin.uclinux.org, Andrew Morton Much (but not all) of the RTC state is kept in the RTC peripheral which has its own power domain. Periodically (1 HZ), that state is synced from one power domain to the other (peripheral->core). When we are resuming, we need to wait for the sync to occur so that we don't get a mismatch of reading undefined state in the rest of the driver. Further, once the externally maintained bits have been synced back into the core, we then need to restore the bits maintained in the core. In our particular case, that is just the write completion interrupt bit. If we don't do any of this, working with the RTC causes ~5 second delays from time to time after waking up due to the write completion interrupt never firing. Reported-by: Michael Dean Reported-by: Michael Hennerich Signed-off-by: Mike Frysinger --- drivers/rtc/rtc-bfin.c | 13 +++++++++++-- 1 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index 65facfb..d4fb82d 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c @@ -435,8 +435,17 @@ static int bfin_rtc_resume(struct platform_device *pdev) { if (device_may_wakeup(&pdev->dev)) disable_irq_wake(IRQ_RTC); - else - bfin_write_RTC_ISTAT(-1); + + /* + * Since only some of the RTC bits are maintained externally in the + * Vbat domain, we need to wait for the RTC MMRs to be synced into + * the core after waking up. This happens every RTC 1HZ. Once that + * has happened, we can go ahead and re-enable the important write + * complete interrupt event. + */ + while (!(bfin_read_RTC_ISTAT() & RTC_ISTAT_SEC)) + continue; + bfin_rtc_int_set(RTC_ISTAT_WRITE_COMPLETE); return 0; }