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_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;
}
Example #3
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;
}