static int mrst_set_alarm(struct device *dev, struct rtc_wkalrm *t) { struct mrst_rtc *mrst = dev_get_drvdata(dev); unsigned char hrs, min, sec; unsigned char wday, mday, mon, year; int ret = 0; if (!is_valid_irq(mrst->irq)) return -EIO; hrs = t->time.tm_hour; min = t->time.tm_min; sec = t->time.tm_sec; wday = t->time.tm_wday; mday = t->time.tm_mday; mon = t->time.tm_mon; year = t->time.tm_year; spin_lock_irq(&rtc_lock); /* Next rtc irq must not be from previous alarm setting */ mrst_irq_disable(mrst, RTC_AIE); /* Update alarm */ vrtc_cmos_write(hrs, RTC_HOURS_ALARM); vrtc_cmos_write(min, RTC_MINUTES_ALARM); vrtc_cmos_write(sec, RTC_SECONDS_ALARM); if ((__intel_mid_cpu_chip == INTEL_MID_CPU_CHIP_PENWELL) || (__intel_mid_cpu_chip == INTEL_MID_CPU_CHIP_CLOVERVIEW)) { /* Support for date-field in Alarm using OSHOB * Since, vRTC doesn't have Alarm-registers for date-fields, * write date-fields into OSHOB for SCU to sync to MSIC-RTC */ writeb(wday, oshob_addr+OSHOB_DAYW_OFFSET); writeb(mday, oshob_addr+OSHOB_DAYM_OFFSET); writeb(mon+1, oshob_addr+OSHOB_MON_OFFSET); /* Adjust for the 1972/1900 */ writeb(year-72, oshob_addr+OSHOB_YEAR_OFFSET); } spin_unlock_irq(&rtc_lock); /* In moorestown vrtc used to be powered off & was not a wake source * in Standby. In penwell vRTC is kept on even during standby. * hence this ipc message need not be sent */ if (__intel_mid_cpu_chip == INTEL_MID_CPU_CHIP_LINCROFT) { ret = rpmsg_send_simple_command(vrtc_mrst_instance, IPCMSG_VRTC, IPC_CMD_VRTC_SETALARM); if (ret) return ret; } spin_lock_irq(&rtc_lock); if (t->enabled) mrst_irq_enable(mrst, RTC_AIE); spin_unlock_irq(&rtc_lock); return 0; }
static int mrst_resume(struct device *dev) { struct mrst_rtc *mrst = dev_get_drvdata(dev); unsigned char tmp = mrst->suspend_ctrl; /* Re-enable any irqs previously active */ if (tmp & RTC_IRQMASK) { unsigned char mask; if (mrst->enabled_wake) { disable_irq_wake(mrst->irq); mrst->enabled_wake = 0; } spin_lock_irq(&rtc_lock); do { vrtc_cmos_write(tmp, RTC_CONTROL); mask = vrtc_cmos_read(RTC_INTR_FLAGS); mask &= (tmp & RTC_IRQMASK) | RTC_IRQF; if (!is_intr(mask)) break; rtc_update_irq(mrst->rtc, 1, mask); tmp &= ~RTC_AIE; } while (mask & RTC_AIE); spin_unlock_irq(&rtc_lock); } dev_dbg(&mrst_rtc.rtc->dev, "resume, ctrl %02x\n", tmp); return 0; }
static int mrst_suspend(struct device *dev, pm_message_t mesg) { struct mrst_rtc *mrst = dev_get_drvdata(dev); unsigned char tmp; /* Only the alarm might be a wakeup event source */ spin_lock_irq(&rtc_lock); mrst->suspend_ctrl = tmp = vrtc_cmos_read(RTC_CONTROL); if (tmp & (RTC_PIE | RTC_AIE)) { unsigned char mask; if (device_may_wakeup(dev)) mask = RTC_IRQMASK & ~RTC_AIE; else mask = RTC_IRQMASK; tmp &= ~mask; vrtc_cmos_write(tmp, RTC_CONTROL); mrst_checkintr(mrst, tmp); } spin_unlock_irq(&rtc_lock); if (tmp & RTC_AIE) { mrst->enabled_wake = 1; enable_irq_wake(mrst->irq); } dev_dbg(&mrst_rtc.rtc->dev, "suspend%s, ctrl %02x\n", (tmp & RTC_AIE) ? ", alarm may wake" : "", tmp); return 0; }
static int mrst_set_alarm(struct device *dev, struct rtc_wkalrm *t) { struct mrst_rtc *mrst = dev_get_drvdata(dev); unsigned char hrs, min, sec; unsigned char wday, mday, mon, year; int ret = 0; if (!is_valid_irq(mrst->irq)) return -EIO; hrs = t->time.tm_hour; min = t->time.tm_min; sec = t->time.tm_sec; wday = t->time.tm_wday; mday = t->time.tm_mday; mon = t->time.tm_mon; year = t->time.tm_year; spin_lock_irq(&rtc_lock); /* Next rtc irq must not be from previous alarm setting */ mrst_irq_disable(mrst, RTC_AIE); /* Update alarm */ vrtc_cmos_write(hrs, RTC_HOURS_ALARM); vrtc_cmos_write(min, RTC_MINUTES_ALARM); vrtc_cmos_write(sec, RTC_SECONDS_ALARM); if ((__intel_mid_cpu_chip == INTEL_MID_CPU_CHIP_PENWELL) || (__intel_mid_cpu_chip == INTEL_MID_CPU_CHIP_CLOVERVIEW)) { /* Support for date-field in Alarm using OSHOB * Since, vRTC doesn't have Alarm-registers for date-fields, * write date-fields into OSHOB for SCU to sync to MSIC-RTC */ writeb(wday, oshob_addr+OSHOB_DAYW_OFFSET); writeb(mday, oshob_addr+OSHOB_DAYM_OFFSET); writeb(mon+1, oshob_addr+OSHOB_MON_OFFSET); /* Adjust for the 1972/1900 */ writeb(year-72, oshob_addr+OSHOB_YEAR_OFFSET); } if (t->enabled) mrst_irq_enable(mrst, RTC_AIE); spin_unlock_irq(&rtc_lock); return 0; }
static void mrst_irq_disable(struct mrst_rtc *mrst, unsigned char mask) { unsigned char rtc_control; rtc_control = vrtc_cmos_read(RTC_CONTROL); rtc_control &= ~mask; vrtc_cmos_write(rtc_control, RTC_CONTROL); mrst_checkintr(mrst, rtc_control); }
/* Only care about the minutes and seconds */ int vrtc_set_mmss(unsigned long nowtime) { int real_sec, real_min; unsigned long flags; int vrtc_min; spin_lock_irqsave(&rtc_lock, flags); vrtc_min = vrtc_cmos_read(RTC_MINUTES); real_sec = nowtime % 60; real_min = nowtime / 60; if (((abs(real_min - vrtc_min) + 15)/30) & 1) real_min += 30; real_min %= 60; vrtc_cmos_write(real_sec, RTC_SECONDS); vrtc_cmos_write(real_min, RTC_MINUTES); spin_unlock_irqrestore(&rtc_lock, flags); return 0; }
static int mrst_set_time(struct device *dev, struct rtc_time *time) { int ret; unsigned long flags; unsigned char mon, day, hrs, min, sec; unsigned int yrs; yrs = time->tm_year; mon = time->tm_mon + 1; /* tm_mon starts at zero */ day = time->tm_mday; hrs = time->tm_hour; min = time->tm_min; sec = time->tm_sec; if (yrs < 72 || yrs > 138) return -EINVAL; yrs -= 72; spin_lock_irqsave(&rtc_lock, flags); vrtc_cmos_write(yrs, RTC_YEAR); vrtc_cmos_write(mon, RTC_MONTH); vrtc_cmos_write(day, RTC_DAY_OF_MONTH); vrtc_cmos_write(hrs, RTC_HOURS); vrtc_cmos_write(min, RTC_MINUTES); vrtc_cmos_write(sec, RTC_SECONDS); spin_unlock_irqrestore(&rtc_lock, flags); ret = intel_scu_ipc_simple_command(IPCMSG_VRTC, IPC_CMD_VRTC_SETTIME); return ret; }
int vrtc_set_mmss(unsigned long nowtime) { unsigned long flags; struct rtc_time tm; int year; int retval = 0; rtc_time_to_tm(nowtime, &tm); if (!rtc_valid_tm(&tm) && tm.tm_year >= 72) { /* * tm.year is the number of years since 1900, and the * vrtc need the years since 1972. */ year = tm.tm_year - 72; spin_lock_irqsave(&rtc_lock, flags); vrtc_cmos_write(year, RTC_YEAR); vrtc_cmos_write(tm.tm_mon, RTC_MONTH); vrtc_cmos_write(tm.tm_mday, RTC_DAY_OF_MONTH); vrtc_cmos_write(tm.tm_hour, RTC_HOURS); vrtc_cmos_write(tm.tm_min, RTC_MINUTES); vrtc_cmos_write(tm.tm_sec, RTC_SECONDS); spin_unlock_irqrestore(&rtc_lock, flags); } else { pr_err("%s: Invalid vRTC value: write of %lx to vRTC failed\n", __FUNCTION__, nowtime); retval = -EINVAL; } return retval; }
static int mrst_set_alarm(struct device *dev, struct rtc_wkalrm *t) { struct mrst_rtc *mrst = dev_get_drvdata(dev); unsigned char hrs, min, sec; int ret = 0; if (!mrst->irq) return -EIO; hrs = t->time.tm_hour; min = t->time.tm_min; sec = t->time.tm_sec; spin_lock_irq(&rtc_lock); /* Next rtc irq must not be from previous alarm setting */ mrst_irq_disable(mrst, RTC_AIE); /* Update alarm */ vrtc_cmos_write(hrs, RTC_HOURS_ALARM); vrtc_cmos_write(min, RTC_MINUTES_ALARM); vrtc_cmos_write(sec, RTC_SECONDS_ALARM); spin_unlock_irq(&rtc_lock); ret = intel_scu_ipc_simple_command(IPCMSG_VRTC, IPC_CMD_VRTC_SETALARM); if (ret) return ret; spin_lock_irq(&rtc_lock); if (t->enabled) mrst_irq_enable(mrst, RTC_AIE); spin_unlock_irq(&rtc_lock); return 0; }
static void mrst_irq_enable(struct mrst_rtc *mrst, unsigned char mask) { unsigned char rtc_control; /* * Flush any pending IRQ status, notably for update irqs, * before we enable new IRQs */ rtc_control = vrtc_cmos_read(RTC_CONTROL); mrst_checkintr(mrst, rtc_control); rtc_control |= mask; vrtc_cmos_write(rtc_control, RTC_CONTROL); mrst_checkintr(mrst, rtc_control); }