/* * IRQ handler for the RTC */ static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id) { struct platform_device *pdev = dev_id; struct rtc_device *rtc = platform_get_drvdata(pdev); unsigned int rtsr; unsigned long events = 0; rtsr = at91_rtc_read(AT91_RTC_SR) & at91_rtc_read_imr(); if (rtsr) { /* this interrupt is shared! Is it ours? */ if (rtsr & AT91_RTC_ALARM) events |= (RTC_AF | RTC_IRQF); if (rtsr & AT91_RTC_SECEV) events |= (RTC_UF | RTC_IRQF); if (rtsr & AT91_RTC_ACKUPD) complete(&at91_rtc_updated); at91_rtc_write(AT91_RTC_SCCR, rtsr); /* clear status reg */ rtc_update_irq(rtc, 1, events); dev_dbg(&pdev->dev, "%s(): num=%ld, events=0x%02lx\n", __func__, events >> 8, events & 0x000000FF); return IRQ_HANDLED; } return IRQ_NONE; /* not handled */ }
/* * Provide additional RTC information in /proc/driver/rtc */ static int at91_rtc_proc(struct device *dev, struct seq_file *seq) { unsigned long imr = at91_rtc_read_imr(); seq_printf(seq, "update_IRQ\t: %s\n", (imr & AT91_RTC_ACKUPD) ? "yes" : "no"); seq_printf(seq, "periodic_IRQ\t: %s\n", (imr & AT91_RTC_SECEV) ? "yes" : "no"); return 0; }
static int at91_rtc_suspend(struct device *dev) { /* this IRQ is shared with DBGU and other hardware which isn't * necessarily doing PM like we are... */ at91_rtc_imr = at91_rtc_read_imr() & (AT91_RTC_ALARM|AT91_RTC_SECEV); if (at91_rtc_imr) { if (device_may_wakeup(dev)) enable_irq_wake(irq); else at91_rtc_write_idr(at91_rtc_imr); } return 0; }
/* * Read alarm time and date in RTC */ static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) { struct rtc_time *tm = &alrm->time; at91_rtc_decodetime(AT91_RTC_TIMALR, AT91_RTC_CALALR, tm); tm->tm_year = -1; alrm->enabled = (at91_rtc_read_imr() & AT91_RTC_ALARM) ? 1 : 0; dev_dbg(dev, "%s(): %ptR %sabled\n", __func__, tm, alrm->enabled ? "en" : "dis"); return 0; }
/* * Read alarm time and date in RTC */ static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) { struct rtc_time *tm = &alrm->time; at91_rtc_decodetime(AT91_RTC_TIMALR, AT91_RTC_CALALR, tm); tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); tm->tm_year = at91_alarm_year - 1900; alrm->enabled = (at91_rtc_read_imr() & AT91_RTC_ALARM) ? 1 : 0; dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); return 0; }