/* Currently, the vRTC doesn't support UIE ON/OFF */ static int mrst_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) { struct mrst_rtc *mrst = dev_get_drvdata(dev); unsigned long flags; switch (cmd) { case RTC_AIE_OFF: case RTC_AIE_ON: if (!is_valid_irq(mrst->irq)) return -EINVAL; break; default: /* PIE ON/OFF is handled by mrst_irq_set_state() */ return -ENOIOCTLCMD; } spin_lock_irqsave(&rtc_lock, flags); switch (cmd) { case RTC_AIE_OFF: /* alarm off */ mrst_irq_disable(mrst, RTC_AIE); break; case RTC_AIE_ON: /* alarm on */ mrst_irq_enable(mrst, RTC_AIE); break; } spin_unlock_irqrestore(&rtc_lock, flags); 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); } 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_alarm_irq_enable(struct device *dev, unsigned int enabled) { struct mrst_rtc *mrst = dev_get_drvdata(dev); if (enabled) mrst_irq_enable(mrst, RTC_AIE); else mrst_irq_disable(mrst, RTC_AIE); return 0; }
/* Currently, the vRTC doesn't support UIE ON/OFF */ static int mrst_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) { struct mrst_rtc *mrst = dev_get_drvdata(dev); unsigned long flags; spin_lock_irqsave(&rtc_lock, flags); if (enabled) mrst_irq_enable(mrst, RTC_AIE); else mrst_irq_disable(mrst, RTC_AIE); spin_unlock_irqrestore(&rtc_lock, flags); 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 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 int vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq) { int retval = 0; unsigned char rtc_control; unsigned char enable_bit_save = 0; /* There can be only one ... */ if (mrst_rtc.dev) return -EBUSY; if (!iomem) return -ENODEV; iomem = request_mem_region(iomem->start, iomem->end + 1 - iomem->start, driver_name); if (!iomem) { dev_dbg(dev, "i/o mem already in use.\n"); return -EBUSY; } mrst_rtc.irq = rtc_irq; mrst_rtc.iomem = iomem; mrst_rtc.dev = dev; dev_set_drvdata(dev, &mrst_rtc); mrst_rtc.rtc = rtc_device_register(driver_name, dev, &mrst_rtc_ops, THIS_MODULE); if (IS_ERR(mrst_rtc.rtc)) { retval = PTR_ERR(mrst_rtc.rtc); goto cleanup0; } rename_region(iomem, dev_name(&mrst_rtc.rtc->dev)); printk(KERN_ALERT"(%s) +------------rtc info-----------+\n",__func__); spin_lock_irq(&rtc_lock); enable_bit_save = vrtc_cmos_read(RTC_CONTROL); enable_bit_save &= (RTC_PIE | RTC_AIE); mrst_irq_disable(&mrst_rtc, RTC_PIE | RTC_AIE); rtc_control = vrtc_cmos_read(RTC_CONTROL); spin_unlock_irq(&rtc_lock); printk(KERN_ALERT"read PIE_AIE_save = 0x%02x, then clear. rtc_control = 0x%02x\n",enable_bit_save,rtc_control); if (!(rtc_control & RTC_24H) || (rtc_control & (RTC_DM_BINARY))) dev_dbg(dev, "TODO: support more than 24-hr BCD mode\n"); if (is_valid_irq(rtc_irq)) { retval = request_irq(rtc_irq, mrst_rtc_irq, IRQF_NO_SUSPEND, dev_name(&mrst_rtc.rtc->dev), mrst_rtc.rtc); if (retval < 0) { dev_dbg(dev, "IRQ %d is already in use, err %d\n", rtc_irq, retval); goto cleanup1; } } /* make RTC device wake capable from sleep */ device_init_wakeup(dev, true); if ((__intel_mid_cpu_chip == INTEL_MID_CPU_CHIP_PENWELL) || (__intel_mid_cpu_chip == INTEL_MID_CPU_CHIP_CLOVERVIEW)) { retval = rpmsg_send_command(vrtc_mrst_instance, IPCMSG_GET_HOBADDR, 0, NULL, &oshob_base, 0, 1); if (retval < 0) { dev_dbg(dev, "Unable to get OSHOB base address, err %d\n", retval); goto cleanup1; } oshob_addr = ioremap_nocache(oshob_base+OSHOB_ALARM_OFFSET, 4); if (!oshob_addr) { dev_dbg(dev, "Unable to do ioremap for OSHOB\n"); retval = -ENOMEM; goto cleanup1; } } spin_lock_irq(&rtc_lock); if(enable_bit_save) mrst_irq_enable(&mrst_rtc, enable_bit_save);//add for power off rtc issue spin_unlock_irq(&rtc_lock); rtc_control = vrtc_cmos_read(RTC_CONTROL); printk(KERN_ALERT"read resume rtc_control = 0x%02x.\n",rtc_control); printk(KERN_ALERT"(%s) +-------------------------------+\n",__func__); dev_dbg(dev, "vRTC driver initialised\n"); return 0; cleanup1: rtc_device_unregister(mrst_rtc.rtc); cleanup0: dev_set_drvdata(dev, NULL); mrst_rtc.dev = NULL; release_mem_region(iomem->start, resource_size(iomem)); dev_err(dev, "rtc-mrst: unable to initialise\n"); return retval; }