예제 #1
0
static void hibernate_restart(void) {
	uint32_t rtc_rtcsr,rtc_rtccr;
	while(!(rtc_read_reg(RTC_RTCCR) & RTCCR_WRDY));
	rtc_rtcsr = rtc_read_reg(RTC_RTCSR);
	rtc_rtccr = rtc_read_reg(RTC_RTCCR);
	rtc_write_reg(RTC_RTCSAR,rtc_rtcsr + 5);
	rtc_rtccr &= ~(1 << 4);
	rtc_write_reg(RTC_RTCCR,rtc_rtccr | 0x3<<2);

      	/* Clear reset status */
	cpm_outl(0,CPM_RSR);

	/* Set minimum wakeup_n pin low-level assertion time for wakeup: 1000ms */
	rtc_write_reg(RTC_HWFCR, HWFCR_WAIT_TIME(1000));

	/* Set reset pin low-level assertion time after wakeup: must  > 60ms */
	rtc_write_reg(RTC_HRCR, (125 << 5));

	/* clear wakeup status register */
	rtc_write_reg(RTC_HWRSR, 0x0);

	rtc_write_reg(RTC_HWCR, 0x9);
	/* Put CPU to hibernate mode */
	rtc_write_reg(RTC_HCR, 0x1);

	mdelay(200);
	while(1)
		printk("We should NOT come here.%08x\n",rtc_read_reg(RTC_HCR));

}
예제 #2
0
void alarm_disable(struct sunxi_rtc *rtc_dev)
{
	int reg_val = 0;
	/* disable alarm irq */
	rtc_write_reg(rtc_dev->ac100, ALM_INT_ENA_OFF, 0);

	/* clear alarm irq pending */
	reg_val = rtc_read_reg(rtc_dev->ac100, ALM_INT_STA_REG_OFF);
	if (reg_val & 1) {
		pr_err("%s(%d) maybe err: alarm irq pending is set, clear it! reg is 0x%x\n",
			__func__, __LINE__, reg_val);
		rtc_write_reg(rtc_dev->ac100, ALM_INT_STA_REG_OFF, 1);
	}

#ifdef CONFIG_ARCH_SUN8IW6P1
	/*
	 * shutdown alarm need alarm interrupt enable info when system startup, but
	 * the info be cleared in u-boot boot process for a problem. so store the
	 * info to RTC_GP_REG_N_OFF reg.
	 * */
	reg_val = rtc_read_reg(rtc_dev->ac100, RTC_GP_REG_N_OFF);
	reg_val &= ~0x1;
	rtc_write_reg(rtc_dev->ac100, RTC_GP_REG_N_OFF, reg_val);
#endif
}
예제 #3
0
파일: rtc.c 프로젝트: Dronecode/SiK
/// return the timer as a 8 bit value.
///
/// @return			The RTC clock in 25usec units
///
uint8_t
rtc_read_low(void)
{
	// capture the current counter value
	rtc_write_reg(RTC_CN, CN_CAPTURE);

	// wait for capture to complete
	while (rtc_read_reg(RTC_CN) & RTC_CN_CAP) ;

	// read the counter shadow
	return rtc_read_reg(RTC_CAPTURE0);
}
예제 #4
0
void jz_restart(char *command)
{
#if 1
	printk("Restarting after 4ms\n");

	REG_WDT_WCSR = WCSR_PRESCALE4 | WCSR_CLKIN_EXT;
	REG_WDT_WCNT = 0;
	REG_WDT_WDR = JZ_EXTAL / 1000;   /* reset after 4ms */
	REG_TCU_TSCR = TSCR_WDT; /* enable wdt clock */
	REG_WDT_WCER = WCER_TCEN;  /* wdt start */
#else
	printk("Restarting after 1s\n");
	/* clear wakeup status register */
	rtc_write_reg(RTC_HWRSR, 0x0);

	/* Scratch pad register to be reserved */
	rtc_write_reg(RTC_HSPR, HSPR_RTCV);

	/* RTC Alarm Wakeup Enable */
	rtc_set_reg(RTC_HWCR, HWCR_EALM);

	/* Set reset pin low-level assertion time after wakeup: must  > 60ms */
	rtc_write_reg(RTC_HRCR, HRCR_WAIT_TIME(60));

	/* Set minimum wakeup_n pin low-level assertion time for wakeup: 100ms */
	rtc_write_reg(RTC_HWFCR, HWFCR_WAIT_TIME(100));

	rtc_write_reg(RTC_RTCSAR, rtc_read_reg(RTC_RTCSR) + 1);
	rtc_set_reg(RTC_RTCCR, RTCCR_AIE | RTCCR_AE | RTCCR_RTCE); /* alarm enable, alarm interrupt enable */

	/* Put CPU to hibernate mode */
	rtc_write_reg(RTC_HCR, HCR_PD);
#endif
	while (1);
}
예제 #5
0
파일: rtc.c 프로젝트: Dronecode/SiK
/// return the RTC timer as a 16 bit value.
///
/// @return			The RTC clock in 25usec units
///
/// Note: this call takes about 50usec
uint16_t
rtc_read_count16(void)
{
	uint16_t ret;

	EX0_SAVE_DISABLE;

	// start a capture
	rtc_write_reg(RTC_CN, CN_CAPTURE);

	// wait for capture to complete
	while (rtc_read_reg(RTC_CN) & RTC_CN_CAP) ;

	// capture the current counter value registers
	// using a auto-incrementing strobe read
	RTC0ADR = RTC0ADR_BUSY | RTC0ADR_AUTO | RTC0ADR_SHORT;
	__asm
	NOP
	NOP
	NOP
	__endasm;
	ret = RTC0DAT;
	__asm
	NOP
	NOP
	NOP
	__endasm;
	ret |= (RTC0DAT<<8);

	EX0_RESTORE;

	return ret;
}
예제 #6
0
static void alarm_irq_work(struct work_struct *work)
{
	struct sunxi_rtc *rtc_dev = container_of(work, struct sunxi_rtc, work);
	int reg_val;

	mutex_lock(&rtc_dev->mutex);

	/* clear alarm irq pending */
	reg_val = rtc_read_reg(rtc_dev->ac100, ALM_INT_STA_REG_OFF);
	if (reg_val < 0) {
		mutex_unlock(&rtc_dev->mutex);
		pr_err("%s(%d) err: read alarm int status reg failed!\n", __func__, __LINE__);
		goto end;
	}

	if (reg_val & 1) {
		rtc_write_reg(rtc_dev->ac100, ALM_INT_STA_REG_OFF, 1);
		mutex_unlock(&rtc_dev->mutex);

		pr_err("%s(%d): alarm interrupt!\n", __func__, __LINE__);
		rtc_update_irq(rtc_dev->rtc, 1, RTC_AF | RTC_IRQF);
		goto end;
	}

	mutex_unlock(&rtc_dev->mutex);
end:
	arisc_enable_nmi_irq();
}
예제 #7
0
static int __init sunxi_rtc_probe(struct platform_device *pdev)
{
	struct sunxi_rtc *rtc_dev;
	int err = 0;
#ifdef CONFIG_ARCH_SUN8IW6P1
	int reg_val = 0;
#endif
	pr_debug("%s,line:%d\n", __func__, __LINE__);
	rtc_dev = kzalloc(sizeof(struct sunxi_rtc), GFP_KERNEL);
	if (!rtc_dev)
		return -ENOMEM;

	/* must before rtc_device_register, because it will call rtc_device_register -> __rtc_read_alarm ->
	 *  rtc_read_time-> __rtc_read_time -> sunxi_rtc_read_time, witch may use platform_get_drvdata. */
	platform_set_drvdata(pdev, rtc_dev);
	rtc_dev->ac100 = dev_get_drvdata(pdev->dev.parent);

#ifdef ENABLE_ALARM
	INIT_WORK(&rtc_dev->work, alarm_irq_work);
	device_init_wakeup(&pdev->dev, true); /* enable alarm wakeup */
#endif
	mutex_init(&rtc_dev->mutex);

	sunxi_rtc_hw_init(rtc_dev);

#ifdef CONFIG_ARCH_SUN8IW6P1
	/*
	 * restore alarm interrupt enable which is cleared by u-boot,
	 * rtc_device_register() need alarm interrupt enable bit to initialize alarm
	 * */
	reg_val = rtc_read_reg(rtc_dev->ac100, RTC_GP_REG_N_OFF);
	if (reg_val & 0x1) {
		rtc_write_reg(rtc_dev->ac100, ALM_INT_ENA_OFF, 1);
	}
#endif

	rtc_dev->rtc = rtc_device_register(RTC_NAME, &pdev->dev, &sunxi_rtc_ops, THIS_MODULE);
	if (IS_ERR(rtc_dev->rtc)) {
		err = PTR_ERR(rtc_dev->rtc);
		kfree(rtc_dev);
		return err;
	}

#ifdef ENABLE_ALARM
	sunxi_alarm_disable(rtc_dev);

	pr_info("%s(%d)!\n", __func__, __LINE__);
	err = arisc_nmi_cb_register(NMI_INT_TYPE_RTC, sunxi_irq_handle, (void *)rtc_dev);
	if (IS_ERR_VALUE(err)) {
		pr_err("%s(%d): request irq failed\n", __func__, __LINE__);
		rtc_device_unregister(rtc_dev->rtc);
		kfree(rtc_dev);
		return err;
	}
#endif

	return 0;
}
예제 #8
0
void sunxi_rtc_hw_init(struct sunxi_rtc *rtc_dev)
{
	int reg_val;

	/* reset rtc reg??? */

	/* set 24h mode */
	rtc_write_reg(rtc_dev->ac100, RTC_CTRL_REG_OFF, RTC_12H_24H_MODE);

	/* disable alarm irq remove to after rtc_device_register() */
	// rtc_write_reg(rtc_dev->ac100, ALM_INT_ENA_OFF, 0);

	/* clear alarm irq pending */
	reg_val = rtc_read_reg(rtc_dev->ac100, ALM_INT_STA_REG_OFF);
	if (!IS_ERR_VALUE(reg_val) && (reg_val & 1))
		rtc_write_reg(rtc_dev->ac100, ALM_INT_STA_REG_OFF, 1);
}
예제 #9
0
static int rtc_gettime(struct sunxi_rtc *rtc_dev, struct rtc_time *tm)
{
	struct rtc_time time_tmp;
	int tmp;

	/* get sec */
	tmp = rtc_read_reg(rtc_dev->ac100, RTC_SEC_REG_OFF);
	time_tmp.tm_sec = bcd2bin(tmp & 0x7f);

	/* get min */
	tmp = rtc_read_reg(rtc_dev->ac100, RTC_MIN_REG_OFF);
	time_tmp.tm_min = bcd2bin(tmp & 0x7f);

	/* get hour */
	tmp = rtc_read_reg(rtc_dev->ac100, RTC_HOU_REG_OFF);
	time_tmp.tm_hour = bcd2bin(tmp & 0x3f);

	/* get week day */
	tmp = rtc_read_reg(rtc_dev->ac100, RTC_WEE_REG_OFF);
	time_tmp.tm_wday = bcd2bin(tmp & 0x7);

	/* get day */
	tmp = rtc_read_reg(rtc_dev->ac100, RTC_DAY_REG_OFF);
	time_tmp.tm_mday = bcd2bin(tmp & 0x3f);

	/* get month */
	tmp = rtc_read_reg(rtc_dev->ac100, RTC_MON_REG_OFF);
	time_tmp.tm_mon = bcd2bin(tmp & 0x1f);
	time_tmp.tm_mon -= 1; /* month is 1..12 in RTC reg but 0..11 in linux */

	/* get year */
	tmp = rtc_read_reg(rtc_dev->ac100, RTC_YEA_REG_OFF);
	tmp = bcd2bin(tmp & 0xff);
	time_tmp.tm_year = reg_year_to_actual_year(tmp) - 1900; /* in linux, tm_year=0 is 1900 */

	pr_info("%s(%d): read time %d-%d-%d %d:%d:%d\n", __func__, __LINE__, time_tmp.tm_year + 1900,
		time_tmp.tm_mon + 1, time_tmp.tm_mday, time_tmp.tm_hour, time_tmp.tm_min, time_tmp.tm_sec);

	/* check if time read from rtc reg is OK */
	if (!time_valid(&time_tmp)) {
		pr_err("%s(%d) err: retrieved date/time is not valid.\n", __func__, __LINE__);
		return -EIO;
	}

	*tm = time_tmp;
	return 0;
}
예제 #10
0
파일: rtc.c 프로젝트: Dronecode/SiK
/// return the timer as a 32 bit value.
///
/// @return			The RTC clock in 25usec units
///
uint32_t
rtc_read_count(void)
{
	union {
		uint8_t		b[4];
		uint32_t	l;
	} mix;

	// start a capture
	rtc_write_reg(RTC_CN, CN_CAPTURE);

	// wait for capture to complete
	while (rtc_read_reg(RTC_CN) & RTC_CN_CAP) ;

	// capture the current counter value registers
	// using a auto-incrementing strobe read
	RTC0ADR = RTC0ADR_BUSY | RTC0ADR_AUTO | RTC0ADR_SHORT;
	__asm
	NOP
	NOP
	NOP
	__endasm;
	mix.b[0] = RTC0DAT;
	__asm
	NOP
	NOP
	NOP
	__endasm;
	mix.b[1] = RTC0DAT;
	__asm
	NOP
	NOP
	NOP
	__endasm;
	mix.b[2] = RTC0DAT;
	__asm
	NOP
	NOP
	NOP
	__endasm;
	mix.b[3] = RTC0DAT;

	return mix.l;
}
예제 #11
0
void alarm_enable(struct sunxi_rtc *rtc_dev)
{
#ifdef CONFIG_ARCH_SUN8IW6P1
	int reg_val = 0;
#endif
	/* enable alarm irq */
	rtc_write_reg(rtc_dev->ac100, ALM_INT_ENA_OFF, 1);

#ifdef CONFIG_ARCH_SUN8IW6P1
	/*
	 * shutdown alarm need alarm interrupt enable info when system startup, but
	 * the info be cleared in u-boot boot process for a problem. so store the
	 * info to RTC_GP_REG_N_OFF reg.
	 * */
	reg_val = rtc_read_reg(rtc_dev->ac100, RTC_GP_REG_N_OFF);
	reg_val |= 0x1;
	rtc_write_reg(rtc_dev->ac100, RTC_GP_REG_N_OFF, reg_val);
#endif
}
예제 #12
0
static int alarm_gettime(struct sunxi_rtc *rtc_dev, struct rtc_time *tm)
{
	int reg_val;

	/* get sec */
	reg_val = rtc_read_reg(rtc_dev->ac100, ALM_SEC_REG_OFF);
	tm->tm_sec = bcd2bin(reg_val & 0x7f);

	/* get minute */
	reg_val = rtc_read_reg(rtc_dev->ac100, ALM_MIN_REG_OFF);
	tm->tm_min = bcd2bin(reg_val & 0x7f);

	/* get hour */
	reg_val = rtc_read_reg(rtc_dev->ac100, ALM_HOU_REG_OFF);
	tm->tm_hour = bcd2bin(reg_val & 0x3f);

	/* get week */
	reg_val = rtc_read_reg(rtc_dev->ac100, ALM_WEEK_REG_OFF);
	tm->tm_wday = bcd2bin(reg_val & 0x7);

	/* get day */
	reg_val = rtc_read_reg(rtc_dev->ac100, ALM_DAY_REG_OFF);
	tm->tm_mday = bcd2bin(reg_val & 0x3f);

	/* get month */
	reg_val = rtc_read_reg(rtc_dev->ac100, ALM_MON_REG_OFF);
	reg_val = bcd2bin(reg_val & 0x1f);
	tm->tm_mon = reg_val - 1; /* month is 1..12 in RTC reg but 0..11 in linux */

	/* get year */
	reg_val = rtc_read_reg(rtc_dev->ac100, ALM_YEA_REG_OFF);
	reg_val = bcd2bin(reg_val & 0xff);
	tm->tm_year = reg_year_to_actual_year(reg_val) - 1900; /* tm_year is from 1900 in linux */

	pr_info("%s(%d): get alarm time %d-%d-%d %d:%d:%d success!\n", __func__, __LINE__, tm->tm_year + 1900,
		tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);

	/* check if time read from rtc reg is OK */
	if (!time_valid(tm)) {
		pr_err("%s(%d) err: get time is not valid.\n", __func__, __LINE__);
		return -EIO;
	}

	return 0;
}
예제 #13
0
static int sunxi_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct sunxi_rtc *rtc_dev = platform_get_drvdata(pdev);
	int ret = 0;
	int reg_val = 0;

	mutex_lock(&rtc_dev->mutex);
	/* get alarm time */
	if (alarm_gettime(rtc_dev, &alrm->time)) {
		pr_err("%s(%d) err: get alarm time failed!\n", __func__, __LINE__);
		ret = -EINVAL;
		goto end;
	}

	reg_val = rtc_read_reg(rtc_dev->ac100, ALM_INT_ENA_OFF);
	if (reg_val & 0x1)
		alrm->enabled = 1;

end:
	mutex_unlock(&rtc_dev->mutex);
	return ret;
}
예제 #14
0
파일: cmos_rtc.c 프로젝트: UIKit0/TSOS
/*
 * Reads the date and time from the RTC. This is kind of slow.
 */
static void rtc_read(void) {
    uint8_t century = 0;
    uint8_t last_second;
    uint8_t last_minute;
    uint8_t last_hour;
    uint8_t last_day;
    uint8_t last_month;
    uint8_t last_year;
    uint8_t last_century;
    uint8_t registerB;

    while (rtc_update_in_progress());
    time.second = rtc_read_reg(0x00);
    time.minute = rtc_read_reg(0x02);
    time.hour = rtc_read_reg(0x04);
    time.day = rtc_read_reg(0x07);
    time.month = rtc_read_reg(0x08);
    time.year = rtc_read_reg(0x09);

    // Read century
    century = rtc_read_reg(0x32);

    // Repeat the RTC read process until the values are consistent
    do {
        last_second = time.second;
        last_minute = time.minute;
        last_hour = time.hour;
        last_day = time.day;
        last_month = time.month;
        last_year = time.year;
        last_century = century;

        // Wait for there to not be an update
        while(rtc_update_in_progress());

        time.second = rtc_read_reg(0x00);
        time.minute = rtc_read_reg(0x02);
        time.hour = rtc_read_reg(0x04);
        time.day = rtc_read_reg(0x07);
        time.month = rtc_read_reg(0x08);
        time.year = rtc_read_reg(0x09);

        century = rtc_read_reg(0x32);
    } while((last_second != time.second) || (last_minute != time.minute) || (last_hour != time.hour) ||
            (last_day != time.day) || (last_month != time.month) || (last_year != time.year) ||
            (last_century != century));

    // Read register B (determine if 24 hour time)
    registerB = rtc_read_reg(0x0B);

    // Convert BCD to binary values if necessary
    if (!(registerB & 0x04)) {
        time.second = (time.second & 0x0F) + ((time.second / 16) * 10);
        time.minute = (time.minute & 0x0F) + ((time.minute / 16) * 10);
        time.hour = ((time.hour & 0x0F) + (((time.hour & 0x70) / 16) * 10) ) | (time.hour & 0x80);
        time.day = (time.day & 0x0F) + ((time.day / 16) * 10);
        time.month = (time.month & 0x0F) + ((time.month / 16) * 10);
        time.year = (time.year & 0x0F) + ((time.year / 16) * 10);

        century = (century & 0x0F) + ((century / 16) * 10);
    }

    // Convert 12 hour clock to 24 hour clock if necessary
    if (!(registerB & 0x02) && (time.hour & 0x80)) {
        time.hour = ((time.hour & 0x7F) + 12) % 24;
    }

    // Calculate the full (4-digit) year
    time.year += century * 100;
}