static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) { u8 reg; /* Much userspace code uses RTC_ALM_SET, thus "don't care" for * day/month/year specifies alarms up to 24 hours in the future. * So we need to handle that ... but let's ignore the "don't care" * values for hours/minutes/seconds. */ if (alm->time.tm_mday <= 0 && alm->time.tm_mon < 0 && alm->time.tm_year < 0) { struct rtc_time tm; unsigned long now, then; omap_rtc_read_time(dev, &tm); rtc_tm_to_time(&tm, &now); alm->time.tm_mday = tm.tm_mday; alm->time.tm_mon = tm.tm_mon; alm->time.tm_year = tm.tm_year; rtc_tm_to_time(&alm->time, &then); /* sometimes the alarm wraps into tomorrow */ if (then < now) { rtc_time_to_tm(now + 24 * 60 * 60, &tm); alm->time.tm_mday = tm.tm_mday; alm->time.tm_mon = tm.tm_mon; alm->time.tm_year = tm.tm_year; } } if (tm2bcd(&alm->time) < 0) return -EINVAL; local_irq_disable(); rtc_wait_not_busy(); rtc_write(alm->time.tm_year, OMAP_RTC_ALARM_YEARS_REG); rtc_write(alm->time.tm_mon, OMAP_RTC_ALARM_MONTHS_REG); rtc_write(alm->time.tm_mday, OMAP_RTC_ALARM_DAYS_REG); rtc_write(alm->time.tm_hour, OMAP_RTC_ALARM_HOURS_REG); rtc_write(alm->time.tm_min, OMAP_RTC_ALARM_MINUTES_REG); rtc_write(alm->time.tm_sec, OMAP_RTC_ALARM_SECONDS_REG); reg = rtc_read(OMAP_RTC_INTERRUPTS_REG); if (alm->enabled) reg |= OMAP_RTC_INTERRUPTS_IT_ALARM; else reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM; rtc_write(reg, OMAP_RTC_INTERRUPTS_REG); local_irq_enable(); return 0; }
static int omap_rtc_resume(struct platform_device *pdev) { struct rtc_time rtc_tm; struct timespec time; time.tv_nsec = 0; omap_rtc_read_time(NULL, &rtc_tm); rtc_tm_to_time(&rtc_tm, &time.tv_sec); restore_time_delta(&rtc_delta, &time); if (device_may_wakeup(&pdev->dev)) disable_irq_wake(omap_rtc_alarm); else rtc_write(irqstat, OMAP_RTC_INTERRUPTS_REG); return 0; }
/* * rtc_power_off: Set the pmic power off sequence. The RTC generates * pmic_pwr_enable control, which can be used to control an external * PMIC. */ static void rtc_power_off(void) { u32 val; struct rtc_time tm; unsigned long time; /* Set PMIC power enable */ val = readl(rtc_base + OMAP_RTC_PMIC_REG); writel(val | OMAP_RTC_PMIC_POWER_EN_EN, rtc_base + OMAP_RTC_PMIC_REG); /* Read rtc time */ omap_rtc_read_time(NULL, &tm); /* Convert Gregorian date to seconds since 01-01-1970 00:00:00 */ rtc_tm_to_time(&tm, &time); /* Add shutdown time to the current value */ time += SHUTDOWN_TIME_SEC; /* Convert seconds since 01-01-1970 00:00:00 to Gregorian date */ rtc_time_to_tm(time, &tm); if (tm2bcd(&tm) < 0) return; pr_info("System will go to power_off state in approx. %d secs\n", SHUTDOWN_TIME_SEC); /* * pmic_pwr_enable is controlled by means of ALARM2 event. So here * programming alarm2 expiry time and enabling alarm2 interrupt */ rtc_write(tm.tm_sec, OMAP_RTC_ALARM2_SECONDS_REG); rtc_write(tm.tm_min, OMAP_RTC_ALARM2_MINUTES_REG); rtc_write(tm.tm_hour, OMAP_RTC_ALARM2_HOURS_REG); rtc_write(tm.tm_mday, OMAP_RTC_ALARM2_DAYS_REG); rtc_write(tm.tm_mon, OMAP_RTC_ALARM2_MONTHS_REG); rtc_write(tm.tm_year, OMAP_RTC_ALARM2_YEARS_REG); /* Enable alarm2 interrupt */ val = readl(rtc_base + OMAP_RTC_INTERRUPTS_REG); writel(val | OMAP_RTC_INTERRUPTS_IT_ALARM2, rtc_base + OMAP_RTC_INTERRUPTS_REG); }
static int omap_rtc_suspend(struct platform_device *pdev, pm_message_t state) { struct rtc_time rtc_tm; struct timespec time; time.tv_nsec = 0; omap_rtc_read_time(NULL, &rtc_tm); rtc_tm_to_time(&rtc_tm, &time.tv_sec); save_time_delta(&rtc_delta, &time); irqstat = rtc_read(OMAP_RTC_INTERRUPTS_REG); /* FIXME the RTC alarm is not currently acting as a wakeup event * source, and in fact this enable() call is just saving a flag * that's never used... */ if (device_may_wakeup(&pdev->dev)) enable_irq_wake(omap_rtc_alarm); else rtc_write(0, OMAP_RTC_INTERRUPTS_REG); return 0; }