static int sunxi_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) { if (!enabled) { sunxi_rtc_setaie(enabled); } return 0; }
static int __devexit sunxi_rtc_remove(struct platform_device *pdev) { struct rtc_device *rtc = platform_get_drvdata(pdev); free_irq(sunxi_rtc_alarmno, rtc); rtc_device_unregister(rtc); platform_set_drvdata(pdev, NULL); sunxi_rtc_setaie(0); return 0; }
static int __exit sunxi_rtc_remove(struct platform_device *pdev) { struct rtc_device *rtc = platform_get_drvdata(pdev); #ifdef SUNXI_ALARM free_irq(sunxi_rtc_alarmno, rtc); #endif rtc_device_unregister(rtc); platform_set_drvdata(pdev, NULL); #ifdef SUNXI_ALARM sunxi_rtc_setaie(0); #endif return 0; }
static int sunxi_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) { struct rtc_time *tm = &alrm->time; void __iomem *base = sunxi_rtc_base; unsigned int alarm_tmp = 0; unsigned int alarm_en; int ret = 0; struct rtc_time tm_now; unsigned long time_now = 0; unsigned long time_set = 0; unsigned long time_gap = 0; unsigned long time_gap_day = 0; unsigned long time_gap_hour = 0; unsigned long time_gap_minute = 0; unsigned long time_gap_second = 0; #ifdef RTC_ALARM_DEBUG printk("*****************************\n\n"); printk("line:%d,%s the alarm time: year:%d, month:%d, day:%d. hour:%d.minute:%d.second:%d\n",\ __LINE__, __func__, tm->tm_year, tm->tm_mon,\ tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); printk("*****************************\n\n"); #endif ret = sunxi_rtc_gettime(dev, &tm_now); #ifdef RTC_ALARM_DEBUG printk("line:%d,%s the current time: year:%d, month:%d, day:%d. hour:%d.minute:%d.second:%d\n",\ __LINE__, __func__, tm_now.tm_year, tm_now.tm_mon,\ tm_now.tm_mday, tm_now.tm_hour, tm_now.tm_min, tm_now.tm_sec); printk("*****************************\n\n"); #endif ret = rtc_tm_to_time(tm, &time_set); ret = rtc_tm_to_time(&tm_now, &time_now); if(time_set <= time_now){ dev_err(dev, "The time or date can`t set, The day has pass!!!\n"); return -EINVAL; } time_gap = time_set - time_now; time_gap_day = time_gap/(3600*24);//day time_gap_hour = (time_gap - time_gap_day*24*60*60)/3600;//hour time_gap_minute = (time_gap - time_gap_day*24*60*60 - time_gap_hour*60*60)/60;//minute time_gap_second = time_gap - time_gap_day*24*60*60 - time_gap_hour*60*60-time_gap_minute*60;//second if(time_gap_day > 255) { dev_err(dev, "The time or date can`t set, The day range of 0 to 255\n"); return -EINVAL; } #ifdef RTC_ALARM_DEBUG printk("line:%d,%s year:%d, month:%d, day:%ld. hour:%ld.minute:%ld.second:%ld\n",\ __LINE__, __func__, tm->tm_year, tm->tm_mon,\ time_gap_day, time_gap_hour, time_gap_minute, time_gap_second); printk("*****************************\n\n"); #endif /*clear the alarm counter enable bit*/ sunxi_rtc_setaie(0); /*clear the alarm count value!!!*/ writel(0x00000000, base + SUNXI_RTC_ALARM_DD_HH_MM_SS_REG); __udelay(100); /*rewrite the alarm count value!!!*/ alarm_tmp = ALARM_SET_SEC_VALUE(time_gap_second) | ALARM_SET_MIN_VALUE(time_gap_minute) | ALARM_SET_HOUR_VALUE(time_gap_hour) | ALARM_SET_DAY_VALUE(time_gap_day); writel(alarm_tmp, base + SUNXI_RTC_ALARM_DD_HH_MM_SS_REG);//0x10c /*clear the count enable alarm irq bit*/ writel(0x00000000, base + SUNXI_ALARM_INT_CTRL_REG); alarm_en = readl(base + SUNXI_ALARM_INT_CTRL_REG);//0x118 /*enable the counter alarm irq*/ alarm_en = readl(base + SUNXI_ALARM_INT_CTRL_REG);//0x118 alarm_en |= RTC_ENABLE_CNT_IRQ; writel(alarm_en, base + SUNXI_ALARM_INT_CTRL_REG);//enable the counter irq!!! if(alrm->enabled != 1){ printk("warning:the rtc counter interrupt isnot enable!!!,%s,%d\n", __func__, __LINE__); } /*decided whether we should start the counter to down count*/ sunxi_rtc_setaie(alrm->enabled); #ifdef RTC_ALARM_DEBUG printk("------------------------------------------\n\n"); printk("%d,10c reg val:%x\n", __LINE__, *(volatile int *)(0xf1c20c00+0x10c)); printk("%d,114 reg val:%x\n", __LINE__, *(volatile int *)(0xf1c20c00+0x114)); printk("%d,118 reg val:%x\n", __LINE__, *(volatile int *)(0xf1c20c00+0x118)); printk("%d,11c reg val:%x\n", __LINE__, *(volatile int *)(0xf1c20c00+0x11c)); printk("------------------------------------------\n\n"); #endif return 0; }
static int sunxi_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) { struct rtc_time *tm = &alrm->time; struct rtc_time tm_now; unsigned long time_now = 0; unsigned long time_set = 0; unsigned long time_gap = 0; unsigned long time_gap_day = 0; unsigned long time_gap_hour = 0; unsigned long time_gap_minute = 0; unsigned long time_gap_second = 0; int ret = 0; alarm_cnt_dd_hh_mm_ss acdhms = {0}; alarm_irq_enable airqen = {0}; pr_info("%s(%d): time to set %d-%d-%d %d:%d:%d\n", __func__, __LINE__, tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); ret = sunxi_rtc_gettime(dev, &tm_now); pr_info("%s(%d): get current time: %d-%d-%d %d:%d:%d\n", __func__, __LINE__, tm_now.tm_year + 1900, tm_now.tm_mon + 1, tm_now.tm_mday, tm_now.tm_hour, tm_now.tm_min, tm_now.tm_sec); ret = rtc_tm_to_time(tm, &time_set); ret = rtc_tm_to_time(&tm_now, &time_now); if(time_set <= time_now){ dev_err(dev, "%s(%d) err: the day has been passed!\n", __func__, __LINE__); return -EINVAL; } /* calc alarm gap from now */ time_gap = time_set - time_now; time_gap_day = time_gap/(3600*24); /* day */ time_gap_hour = (time_gap - time_gap_day*24*60*60)/3600; /* hour */ time_gap_minute = (time_gap - time_gap_day*24*60*60 - time_gap_hour*60*60)/60; /* minute */ time_gap_second = time_gap - time_gap_day*24*60*60 - time_gap_hour*60*60-time_gap_minute*60; /* second */ if(time_gap_day > 255) { dev_err(dev, "%s(%d) err: the day gap exceed 255\n", __func__, __LINE__); return -EINVAL; } pr_info("%s(%d): get gap day %d, hour %d, minute %d, second %d\n", __func__, __LINE__, (int)time_gap_day, (int)time_gap_hour, (int)time_gap_minute, (int)time_gap_second); /* diable alarm irq */ sunxi_rtc_setaie(0); /* clear the alarm count value */ writel(0x00000000, &rtc_reg_list->a_cnt_dd_hh_mm_ss); __udelay(100); /* rewrite the alarm count value */ writel(0, &rtc_reg_list->a_cnt_dd_hh_mm_ss); acdhms.day = time_gap_day; acdhms.hour = time_gap_hour; acdhms.minute = time_gap_minute; acdhms.second = time_gap_second; rtc_reg_list->a_cnt_dd_hh_mm_ss = acdhms; /* disable alarm wk/cnt irq */ writel(0x00000000, &rtc_reg_list->a_irq_enable); airqen= rtc_reg_list->a_irq_enable; /* enable alarm counter irq */ airqen.alarm_cnt_irq_en = 1; rtc_reg_list->a_irq_enable = airqen; if(alrm->enabled != 1) pr_err("%s(%d) maybe err: the rtc counter interrupt isnot enable!\n", __func__, __LINE__); /* decided whether we should start the counter to down count */ sunxi_rtc_setaie(alrm->enabled); pr_info("%s(%d) end\n", __func__, __LINE__); return 0; }
static int sunxi_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) { struct rtc_time *tm = &alrm->time; void __iomem *base = sunxi_rtc_base; unsigned int alarm_en; int ret = 0; struct rtc_time tm_now; unsigned long time_now = 0; unsigned long time_set = 0; unsigned long time_gap = 0; unsigned long time_gap_day = 0; unsigned long time_gap_hour = 0; unsigned long time_gap_minute = 0; unsigned long time_gap_second = 0; RTC_DBG("*****************************\n\n"); RTC_DBG("line:%d,%s the alarm time: year:%d, month:%d, day:%d. hour:%d.minute:%d.second:%d\n",\ __LINE__, __func__, tm->tm_year, tm->tm_mon,\ tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); RTC_DBG("*****************************\n\n"); ret = sunxi_rtc_gettime(dev, &tm_now); RTC_DBG("line:%d,%s the current time: year:%d, month:%d, day:%d. hour:%d.minute:%d.second:%d\n",\ __LINE__, __func__, tm_now.tm_year, tm_now.tm_mon,\ tm_now.tm_mday, tm_now.tm_hour, tm_now.tm_min, tm_now.tm_sec); RTC_DBG("*****************************\n\n"); ret = rtc_tm_to_time(tm, &time_set); ret = rtc_tm_to_time(&tm_now, &time_now); if(time_set <= time_now){ dev_err(dev, "The time or date can`t set, The day has pass!!!\n"); return -EINVAL; } time_gap = time_set - time_now; time_gap_day = time_gap/(3600*24);//day time_gap_hour = (time_gap - time_gap_day*24*60*60)/3600;//hour time_gap_minute = (time_gap - time_gap_day*24*60*60 - time_gap_hour*60*60)/60;//minute time_gap_second = time_gap - time_gap_day*24*60*60 - time_gap_hour*60*60-time_gap_minute*60;//second if(time_gap_day > 255) { dev_err(dev, "The time or date can`t set, The day range of 0 to 255\n"); return -EINVAL; } RTC_DBG("%s,line:%d,time_gap:%ld,alrm->enabled:%d\n", __func__, __LINE__, time_gap, alrm->enabled); RTC_DBG("*****************************\n\n"); /*clear the alarm counter enable bit*/ sunxi_rtc_setaie(0); /*clear the alarm count value!!!*/ writel(0x00000000, base + SUNXI_RTC_ALARM_COUNTER_REG); /*rewrite the alarm count value!!!*/ writel(time_gap, base + SUNXI_RTC_ALARM_COUNTER_REG);//0x0020 /*clear the count enable alarm irq bit*/ writel(0x00000000, base + SUNXI_ALARM_INT_CTRL_REG); alarm_en = readl(base + SUNXI_ALARM_INT_CTRL_REG);//0x002c /*enable the counter alarm irq*/ alarm_en = readl(base + SUNXI_ALARM_INT_CTRL_REG);//0x002c alarm_en |= RTC_ENABLE_CNT_IRQ; writel(alarm_en, base + SUNXI_ALARM_INT_CTRL_REG);//enable the counter irq!!! if(alrm->enabled != 1){ RTC_DBG("warning:the rtc counter interrupt isnot enable!!!,%s,%d\n", __func__, __LINE__); } /*decided whether we should start the counter to down count*/ sunxi_rtc_setaie(alrm->enabled); RTC_DBG("------------------------------------------\n\n"); RTC_DBG("%d,2c reg val:%x\n", __LINE__, *(volatile int *)(0xf1f00000+0x2c)); RTC_DBG("%d,30 reg val:%x\n", __LINE__, *(volatile int *)(0xf1f00000+0x30)); RTC_DBG("%d,28 reg val:%x\n", __LINE__, *(volatile int *)(0xf1f00000+0x28)); RTC_DBG("------------------------------------------\n\n"); return 0; }