void set_power_on_alarm(long secs, bool enable) { int rc; struct timespec wall_time; long rtc_secs, alarm_time, alarm_delta; struct rtc_time rtc_time; struct rtc_wkalrm alarm; rc = mutex_lock_interruptible(&power_on_alarm_lock); if (rc != 0) return; if (enable) { power_on_alarm = secs; } else { if (power_on_alarm == secs) power_on_alarm = 0; else goto exit; } if (!power_on_alarm) goto disable_alarm; rtc_read_time(rtcdev, &rtc_time); getnstimeofday(&wall_time); rtc_tm_to_time(&rtc_time, &rtc_secs); alarm_delta = wall_time.tv_sec - rtc_secs; alarm_time = power_on_alarm - alarm_delta; /* *Substract ALARM_DELTA from actual alarm time *to power up the device before actual alarm *expiration */ #ifdef CONFIG_ZTEMT_PON_ALARM_DELTA if ((alarm_time - ALARM_DELTA) > rtc_secs) alarm_time -= ALARM_DELTA; else goto disable_alarm; #else if (alarm_time <= rtc_secs) goto disable_alarm; #endif rtc_time_to_tm(alarm_time, &alarm.time); alarm.enabled = 1; rc = rtc_set_alarm(rtcdev, &alarm); if (rc) goto disable_alarm; mutex_unlock(&power_on_alarm_lock); return; disable_alarm: power_on_alarm = 0; rtc_alarm_irq_enable(rtcdev, 0); exit: mutex_unlock(&power_on_alarm_lock); }
static int stm_sbc_rtc_restore(struct device *dev) { struct stm_sbc_rtc *rtc = dev_get_drvdata(dev); rtc_alarm_irq_enable(rtc->rtc_dev, 0); device_set_wakeup_enable(dev, false); return 0; }
int alarm_irq_enable(unsigned int enabled) { int err; if (pwr_rtc_dev != NULL) { err = rtc_alarm_irq_enable(pwr_rtc_dev, enabled); if (err < 0) return err; } return 0; }
static int st_rtc_resume(struct device *dev) { struct st_rtc *rtc = dev_get_drvdata(dev); rtc_alarm_irq_enable(rtc->rtc_dev, 0); /* * clean 'rtc->alarm' to allow a new * .set_alarm to the upper RTC layer */ memset(&rtc->alarm, 0, sizeof(struct rtc_wkalrm)); writel_relaxed(0, rtc->ioaddr + LPC_LPA_MSB_OFF); writel_relaxed(0, rtc->ioaddr + LPC_LPA_LSB_OFF); writel_relaxed(1, rtc->ioaddr + LPC_WDT_OFF); writel_relaxed(1, rtc->ioaddr + LPC_LPA_START_OFF); writel_relaxed(0, rtc->ioaddr + LPC_WDT_OFF); return 0; }
static int stm_rtc_resume(struct device *dev) { struct stm_rtc *rtc = dev_get_drvdata(dev); struct stm_plat_rtc_lpc *pdata = dev->platform_data; rtc_alarm_irq_enable(rtc->rtc_dev, 0); /* * clean 'rtc->alarm' to allow a new * a new .set_alarm to the upper RTC layer */ memset(&rtc->alarm, 0, sizeof(struct rtc_wkalrm)); if (pdata->need_wdt_reset) { writel(0, rtc->ioaddr + LPC_LPA_MSB_OFF); writel(0, rtc->ioaddr + LPC_LPA_LSB_OFF); writel(1, rtc->ioaddr + LPC_WDT_OFF); writel(1, rtc->ioaddr + LPC_LPA_START_OFF); writel(0, rtc->ioaddr + LPC_WDT_OFF); } return 0; }
static int disable_rtc_alarms(struct device *dev, void *data) { return (rtc_alarm_irq_enable((struct rtc_device *)dev, 0)); }