201 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			201 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
#include <common.h>
 | 
						|
#include <command.h>
 | 
						|
#include <dm.h>
 | 
						|
#include <rtc.h>
 | 
						|
#include <asm/io.h>
 | 
						|
#include <compiler.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <asm/armv7.h>
 | 
						|
#include <asm/arch/IOAddress.h>
 | 
						|
#include <asm/arch/hardware.h>
 | 
						|
#include <asm/nvt-common/nvt_types.h>
 | 
						|
#include <asm/nvt-common/nvt_common.h>
 | 
						|
#include <asm/nvt-common/rcw_macro.h>
 | 
						|
#include "rtc_reg.h"
 | 
						|
 | 
						|
 | 
						|
#define RTC_INT_KEY     0xA
 | 
						|
#define RTC_INT_OSC_ANALOG_CFG 0x9
 | 
						|
#define YEAR_OFFSET 1900
 | 
						|
 | 
						|
#define RTC_GETREG(ofs)        INW(IOADDR_RTC_REG_BASE+(ofs))
 | 
						|
#define RTC_SETREG(ofs, value) OUTW(IOADDR_RTC_REG_BASE +(ofs),(value))
 | 
						|
 | 
						|
static const unsigned short rtc_ydays[2][13] = {
 | 
						|
        /* Normal years */
 | 
						|
        { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
 | 
						|
        /* Leap years */
 | 
						|
        { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
 | 
						|
};
 | 
						|
 | 
						|
void rtc_trigger_cset(void)
 | 
						|
{
 | 
						|
        union RTC_STATUS_REG status_reg;
 | 
						|
        union RTC_CTRL_REG ctrl_reg;
 | 
						|
 | 
						|
        /*Wait for RTC SRST done*/
 | 
						|
        do {
 | 
						|
                status_reg.reg = RTC_GETREG(RTC_STATUS_REG_OFS);
 | 
						|
        } while (status_reg.bit.srst_sts == 1);
 | 
						|
 | 
						|
        /*Wait for RTC is ready for next CSET*/
 | 
						|
        do {
 | 
						|
                ctrl_reg.reg = RTC_GETREG(RTC_CTRL_REG_OFS);
 | 
						|
        } while (ctrl_reg.bit.cset == 1);
 | 
						|
 | 
						|
        /*Trigger CSET*/
 | 
						|
        ctrl_reg.reg = RTC_GETREG(RTC_CTRL_REG_OFS);
 | 
						|
        ctrl_reg.bit.cset = 1;
 | 
						|
        ctrl_reg.bit.cset_inten = 1;
 | 
						|
        RTC_SETREG(RTC_CTRL_REG_OFS, ctrl_reg.reg);
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
int rtc_get(struct rtc_time *tm)
 | 
						|
{
 | 
						|
	uint32_t days, months, years, month_days;
 | 
						|
        union RTC_TIMER_REG timer_reg;
 | 
						|
        union RTC_DAYKEY_REG daykey_reg;
 | 
						|
 | 
						|
 | 
						|
        timer_reg.reg = RTC_GETREG(RTC_TIMER_REG_OFS);
 | 
						|
        daykey_reg.reg = RTC_GETREG(RTC_DAYKEY_REG_OFS);
 | 
						|
        days = daykey_reg.bit.day;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
        for (years = 0; days >= rtc_ydays[is_leap_year(years + 1900)][12]; years++) {
 | 
						|
                days -= rtc_ydays[is_leap_year(years + 1900)][12];
 | 
						|
        }
 | 
						|
 | 
						|
        for (months = 1; months < 13; months++) {
 | 
						|
                if (days <= rtc_ydays[is_leap_year(years + 1900)][months]) {
 | 
						|
                        days -= rtc_ydays[is_leap_year(years + 1900)][months-1];
 | 
						|
                        months--;
 | 
						|
                        break;
 | 
						|
                }
 | 
						|
        }
 | 
						|
 | 
						|
        month_days =  rtc_ydays[is_leap_year(years + 1900)][months+1] - rtc_ydays[is_leap_year(years + 1900)][months];
 | 
						|
 | 
						|
        if (days == month_days) {
 | 
						|
                months++;
 | 
						|
                days = 1;
 | 
						|
        } else
 | 
						|
                days++; /*Align linux time format*/
 | 
						|
 | 
						|
 | 
						|
 | 
						|
        tm->tm_sec  = timer_reg.bit.sec;
 | 
						|
        tm->tm_min  = timer_reg.bit.min;
 | 
						|
        tm->tm_hour = timer_reg.bit.hour;
 | 
						|
        tm->tm_mday = days;
 | 
						|
        tm->tm_mon  = months;
 | 
						|
        tm->tm_year = years + YEAR_OFFSET;
 | 
						|
		rtc_calc_weekday(tm);
 | 
						|
 | 
						|
        debug("after read time: sec = %d, min = %d, hour = %d, mday = %d," \
 | 
						|
        "mon = %d, year = %d, wday = %d, yday = %d," \
 | 
						|
        "\n", tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_mday, \
 | 
						|
        tm->tm_mon, tm->tm_year, tm->tm_wday, tm->tm_yday);
 | 
						|
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
int rtc_set(struct rtc_time *tm)
 | 
						|
{
 | 
						|
 | 
						|
	int year_looper ;
 | 
						|
	uint32_t days = 0;
 | 
						|
	union RTC_TIMER_REG timer_reg;
 | 
						|
	union RTC_DAYKEY_REG daykey_reg;
 | 
						|
	union RTC_CTRL_REG ctrl_reg;
 | 
						|
 | 
						|
	debug("Set DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
 | 
						|
		tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday,
 | 
						|
		tm->tm_hour, tm->tm_min, tm->tm_sec);
 | 
						|
 | 
						|
	tm->tm_year=tm->tm_year - YEAR_OFFSET;
 | 
						|
 | 
						|
	for (year_looper = 0; year_looper < tm->tm_year; year_looper++)
 | 
						|
			days += rtc_ydays[is_leap_year(year_looper + 1900)][12];
 | 
						|
 | 
						|
	days += rtc_ydays[is_leap_year(year_looper + 1900)][tm->tm_mon];
 | 
						|
	tm->tm_mday--; /*subtract the day which is not ended*/
 | 
						|
	days += tm->tm_mday;
 | 
						|
 | 
						|
 | 
						|
	ctrl_reg.reg = RTC_GETREG(RTC_CTRL_REG_OFS);
 | 
						|
	ctrl_reg.bit.cset = 0;
 | 
						|
	ctrl_reg.bit.day_sel = 1;
 | 
						|
	ctrl_reg.bit.time_sel = 1;
 | 
						|
	RTC_SETREG(RTC_CTRL_REG_OFS, ctrl_reg.reg);
 | 
						|
 | 
						|
	timer_reg.reg = 0;
 | 
						|
	timer_reg.bit.sec = tm->tm_sec;
 | 
						|
	timer_reg.bit.min = tm->tm_min;
 | 
						|
	timer_reg.bit.hour = tm->tm_hour;
 | 
						|
	RTC_SETREG(RTC_TIMER_REG_OFS, timer_reg.reg);
 | 
						|
 | 
						|
	daykey_reg.reg = RTC_GETREG(RTC_DAYKEY_REG_OFS);
 | 
						|
	daykey_reg.bit.day = days;
 | 
						|
	RTC_SETREG(RTC_DAYKEY_REG_OFS, daykey_reg.reg);
 | 
						|
 | 
						|
	rtc_trigger_cset();
 | 
						|
 | 
						|
	return 0;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
void rtc_reset(void)
 | 
						|
{
 | 
						|
	//u32 reg_data;
 | 
						|
 | 
						|
 | 
						|
	union RTC_OSCAN_REG oscan_reg;
 | 
						|
	union RTC_STATUS_REG status_reg;
 | 
						|
	union RTC_DAYKEY_REG daykey_reg;
 | 
						|
	union RTC_CTRL_REG ctrl_reg;
 | 
						|
 | 
						|
	// Wait for previous SRST done
 | 
						|
	do {
 | 
						|
			status_reg.reg = RTC_GETREG(RTC_STATUS_REG_OFS);
 | 
						|
	} while (status_reg.bit.srst_sts);
 | 
						|
 | 
						|
	// Wait for RTC is ready for next CSET
 | 
						|
	do {
 | 
						|
			ctrl_reg.reg = RTC_GETREG(RTC_CTRL_REG_OFS);
 | 
						|
	} while (ctrl_reg.bit.cset);
 | 
						|
 | 
						|
	// Do software reset
 | 
						|
	ctrl_reg.reg = 0;
 | 
						|
	ctrl_reg.bit.srst = 1;
 | 
						|
	RTC_SETREG(RTC_CTRL_REG_OFS, ctrl_reg.reg);
 | 
						|
 | 
						|
	// Wait for RTC is ready for next CSET
 | 
						|
	do {
 | 
						|
			ctrl_reg.reg = RTC_GETREG(RTC_CTRL_REG_OFS);
 | 
						|
	} while (ctrl_reg.bit.srst);
 | 
						|
 | 
						|
 | 
						|
	ctrl_reg.reg = RTC_GETREG(RTC_CTRL_REG_OFS);
 | 
						|
	ctrl_reg.bit.cset = 0;
 | 
						|
	ctrl_reg.bit.key_sel = 1;
 | 
						|
	ctrl_reg.bit.pwralarmday_sel = 1;
 | 
						|
	ctrl_reg.bit.day_sel = 1;
 | 
						|
	RTC_SETREG(RTC_CTRL_REG_OFS, ctrl_reg.reg);
 | 
						|
 | 
						|
	daykey_reg.reg = RTC_GETREG(RTC_DAYKEY_REG_OFS);
 | 
						|
	daykey_reg.bit.key = RTC_INT_KEY;
 | 
						|
	RTC_SETREG(RTC_DAYKEY_REG_OFS, daykey_reg.reg);
 | 
						|
 | 
						|
	/*Set OSC analog parameter*/
 | 
						|
	oscan_reg.reg = RTC_GETREG(RTC_OSCAN_REG_OFS);
 | 
						|
	oscan_reg.bit.osc_analogcfg = RTC_INT_OSC_ANALOG_CFG;
 | 
						|
	RTC_SETREG(RTC_OSCAN_REG_OFS, oscan_reg.reg);
 | 
						|
 | 
						|
	rtc_trigger_cset();
 | 
						|
 | 
						|
}
 |