Esempio n. 1
0
static int
rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
	  unsigned long arg)
{
	struct rtc_time rtc_tm;
	ulong curr_time;

	switch (cmd) {
	case RTC_RD_TIME:	/* Read the time/date from RTC  */
		curr_time = rtc_get_time();
		to_tm(curr_time, &rtc_tm);
		rtc_tm.tm_year -= 1900;
		return copy_to_user((void *) arg, &rtc_tm, sizeof(rtc_tm)) ? 
			-EFAULT : 0;
	case RTC_SET_TIME:	/* Set the RTC */
		if (!capable(CAP_SYS_TIME))
			return -EACCES;

		if (copy_from_user(&rtc_tm, 
				   (struct rtc_time *) arg,
		                   sizeof(struct rtc_time))) 
			return -EFAULT;

		curr_time = mktime(rtc_tm.tm_year + 1900,
				   rtc_tm.tm_mon,
				   rtc_tm.tm_mday,
				   rtc_tm.tm_hour,
				   rtc_tm.tm_min, 
				   rtc_tm.tm_sec);
		return rtc_set_time(curr_time);
	default:
		return -EINVAL;
	}
}
static int alarm_set_rtc(struct timespec *ts)
{
	struct rtc_time new_rtc_tm;
	struct rtc_device *rtc_dev;
	unsigned long flags;
	int rv = 0;

	rtc_time_to_tm(ts->tv_sec, &new_rtc_tm);
	alarm_dbg(INFO, "set rtc %ld %ld - rtc %02d:%02d:%02d %02d/%02d/%04d\n",
	ts->tv_sec, ts->tv_nsec,
	new_rtc_tm.tm_hour, new_rtc_tm.tm_min,
	new_rtc_tm.tm_sec, new_rtc_tm.tm_mon + 1,
	new_rtc_tm.tm_mday,
	new_rtc_tm.tm_year + 1900);
	rtc_dev = alarmtimer_get_rtcdev();
	rv = do_settimeofday(ts);
	if (rv < 0)
		return rv;
	if (rtc_dev)
		rv = rtc_set_time(rtc_dev, &new_rtc_tm);

	spin_lock_irqsave(&alarm_slock, flags);
	alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK;
	wake_up(&alarm_wait_queue);
	spin_unlock_irqrestore(&alarm_slock, flags);

	return rv;
}
Esempio n. 3
0
static void
rtc_reset(void)
{
	struct rtc_date dt;
	struct rtc_time tm;
	
	RTC_ALRM_DIS();
	
	// Set date and time
	dt.ten_cent = 0;
	dt.cent     = 0;
	dt.ten_yr   = 0;
	dt.yr       = 0;
	dt.ten_mth  = 0;
	dt.mth      = 0;
	dt.ten_day  = 0;
	dt.day      = 0;
	
	tm.dow      = 0;
	tm.ten_hr   = 0;
	tm.hr       = 0;
	tm.ten_min  = 0;
	tm.min      = 0;
	tm.ten_sec  = 0;
	tm.sec      = 0;
	tm.sos      = 0;
	
	rtc_set_date(&dt);
	rtc_set_time(&tm);
}
Esempio n. 4
0
/**
 * \brief Set the time using a spinner widget
 */
static void set_time_application(void)
{
    struct keyboard_event input;
    struct calendar_date date;
    uint32_t timestamp;
    uint8_t tz_hours;
    uint8_t tz_minutes;
    struct gfx_mono_spinctrl hour_spinner;
    struct gfx_mono_spinctrl minute_spinner;
    struct gfx_mono_spinctrl_spincollection time_spinners;
    uint8_t spinner_status;
    int16_t spinner_results[2];

    // Prepare the spinner widget for time selection
    gfx_mono_spinctrl_init(&hour_spinner, SPINTYPE_INTEGER,
                           datetime_date_spinner_string_hour, NULL, 0, 23, 0);
    gfx_mono_spinctrl_init(&minute_spinner, SPINTYPE_INTEGER,
                           datetime_date_spinner_string_minute, NULL, 0, 59, 0);

    // Create time spincollector
    gfx_mono_spinctrl_spincollection_init(&time_spinners);
    gfx_mono_spinctrl_spincollection_add_spinner(&hour_spinner,
            &time_spinners);
    gfx_mono_spinctrl_spincollection_add_spinner(&minute_spinner,
            &time_spinners);

    // Get timezone settings
    tz_hours = timezone_get_hours();
    tz_minutes = timezone_get_minutes();

    timestamp = rtc_get_time();

    calendar_timestamp_to_date_tz(timestamp, tz_hours, tz_minutes, &date);

    // Set spinners to current time as initial position
    hour_spinner.integer_data = date.hour;
    minute_spinner.integer_data = date.minute;

    gfx_mono_spinctrl_spincollection_show(&time_spinners);

    do {
        do {
            keyboard_get_key_state(&input);
            // Wait for key release
        } while (input.type != KEYBOARD_RELEASE);
        // Send key to spinnercollection
        spinner_status = gfx_mono_spinctrl_spincollection_process_key(
                             &time_spinners, input.keycode, spinner_results);
    } while (spinner_status != GFX_MONO_SPINCTRL_EVENT_FINISH);

    date.hour = spinner_results[0];
    date.minute = spinner_results[1];

    timestamp = calendar_date_to_timestamp_tz(&date, tz_hours, tz_minutes);

    if(timestamp != 0) {
        rtc_set_time(timestamp);
    }
}
Esempio n. 5
0
static int
rtc_sub_alarm_test(u32 f_time, u32 f_date)
{
	volatile int	hit;
	int result = 0;
	
	rtc_reset();

	printf("RTC Time = W%d %d%d:%d%d:%d%d:%d\n", tm.dow, tm.ten_hr, tm.hr,	\
				tm.ten_min, tm.min, tm.ten_sec, tm.sec, tm.sos);

	printf("RTC Date = C%d%d %d%d/%d%d/%d%d\n", dt.ten_cent, dt.cent, dt.ten_yr, dt.yr,	\
				dt.ten_mth, dt.mth, dt.ten_day, dt.day);

	printf("Alarm Time = W%d %d%d:%d%d:%d%d:%d\n", tm_a.dow, tm_a.ten_hr, tm_a.hr,	\
				tm_a.ten_min, tm_a.min, tm_a.ten_sec, tm_a.sec, tm_a.sos);

	printf("Alarm Date = C%d%d %d%d/%d%d/%d%d\n", dt_a.ten_cent, dt_a.cent, dt_a.ten_yr, dt_a.yr,	\
				dt_a.ten_mth, dt_a.mth, dt_a.ten_day, dt_a.day);

	printf("Alarm Time on: ");
	if (f_time & SOCLE_RTC_TALRM_CSOS)
		printf("\"Sixteen of Second\" ");
	if (f_time & SOCLE_RTC_TALRM_CS)
		printf("\"Second\" ");
	if (f_time & SOCLE_RTC_TALRM_CM)
		printf("\"Minute\" ");
	if (f_time & SOCLE_RTC_TALRM_CH)
		printf("\"Hour\" ");
	if (f_time & SOCLE_RTC_TALRM_CDOW)
		printf("\"Day of Week\"");
	printf("\n");	

	printf("Alarm Date on: ");
	if (f_date & SOCLE_RTC_DALRM_CD)
		printf("\"Day\" ");
	if (f_date & SOCLE_RTC_DALRM_CM)
		printf("\"Month\" ");
	if (f_date & SOCLE_RTC_DALRM_CY)
		printf("\"Year\" ");
	if (f_date & SOCLE_RTC_DALRM_CC)
		printf("\"Century\"");
	printf("\n");

	rtc_set_time_alarm(&tm_a, f_time);
	rtc_set_date_alarm(&dt_a, f_date);

	hit = 0;

	rtc_set_date(&dt);
	rtc_set_time(&tm);

	printf("alarm after 15 second...\n");



	return result;
}
Esempio n. 6
0
static int __init rtc_hctosys(void)
{
	int err = -ENODEV;
	struct rtc_time tm;
	struct timespec tv = {
		.tv_nsec = NSEC_PER_SEC >> 1,
	};
	struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);

	if (rtc == NULL) {
		pr_err("%s: unable to open rtc device (%s)\n",
			__FILE__, CONFIG_RTC_HCTOSYS_DEVICE);
		goto err_open;
	}

	err = rtc_read_time(rtc, &tm);
	if (err) {
		dev_err(rtc->dev.parent,
			"hctosys: unable to read the hardware clock\n");
		goto err_read;

	}

	err = rtc_valid_tm(&tm);
	if (err) {
		dev_err(rtc->dev.parent,
			"hctosys: invalid date/time\n");
		goto err_invalid;
	}

	if(tm.tm_year < 100) {
		tm.tm_year += 13;
		rtc_set_time(rtc, &tm);
	}

	rtc_tm_to_time(&tm, &tv.tv_sec);

	do_settimeofday(&tv);

	dev_info(rtc->dev.parent,
		"setting system clock to "
		"%d-%02d-%02d %02d:%02d:%02d UTC (%u)\n",
		tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
		tm.tm_hour, tm.tm_min, tm.tm_sec,
		(unsigned int) tv.tv_sec);

err_invalid:
err_read:
	rtc_class_close(rtc);

	rtc_hctohc(tm);
err_open:
	rtc_hctosys_ret = err;

	return err;
}

late_initcall(rtc_hctosys);
Esempio n. 7
0
static void _rtc_settime(char **argv)
{
    struct tm now;

    if (_parse_time(argv, &now) == 0) {
        if (rtc_set_time(&now) == -1) {
            puts("rtc: error setting time");
        }
    }
}
Esempio n. 8
0
void set_timestamp(uint32_t time)
{
  #ifdef RTC
    rtc_set_time(time);
  #else
    ATOMIC_BLOCK(ATOMIC_FORCEON)
    {
      timestamp = time;
    }
  #endif
}
Esempio n. 9
0
int set_rtc_time(struct rtc_time *time)
{
	unsigned long nowtime;
	int ret;

	spin_lock(&mips_rtc_lock);
	nowtime = mktime(time->tm_year+1900, time->tm_mon+1,
			time->tm_mday, time->tm_hour, time->tm_min,
			time->tm_sec);
	ret = rtc_set_time(nowtime);
	spin_unlock(&mips_rtc_lock);

	return ret;
}
Esempio n. 10
0
static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
{
	void __iomem *base = s3c_rtc_base;
//	int year = tm->tm_year;//- 100;
	int year = tm->tm_year-100;
#ifdef CONFIG_RTC_DRV_S5M
	struct rtc_device *rtc1 ;
#endif

	printk("%s() %d-%d-%d %d:%d:%d\n", __FUNCTION__,
			tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
			tm->tm_hour, tm->tm_min, tm->tm_sec);
	pr_debug("set time %04d.%02d.%02d %02d:%02d:%02d\n",
		 1900 + tm->tm_year, tm->tm_mon+1, tm->tm_mday,
		 tm->tm_hour, tm->tm_min, tm->tm_sec);

	/* we get around y2k by simply not supporting it */
	
//	printk("year %d\n",year);
//	if (year < 70) {
//		dev_err(dev, "rtc only supports from year 1970\n");
//		return -EINVAL;
//	}


	writeb(bin2bcd(tm->tm_sec),  base + S3C2410_RTCSEC);
	writeb(bin2bcd(tm->tm_min),  base + S3C2410_RTCMIN);
	writeb(bin2bcd(tm->tm_hour), base + S3C2410_RTCHOUR);
	writeb(bin2bcd(tm->tm_mday), base + S3C2410_RTCDATE);
	writeb(bin2bcd(tm->tm_mon + 1), base + S3C2410_RTCMON);
	writeb(bin2bcd(year), base + S3C2410_RTCYEAR);

#ifdef CONFIG_RTC_DRV_S5M
	rtc1 = rtc_class_open("rtc1");
	if(rtc1 == NULL)
	{
		pr_err("!!!!!! %s: unable to open rtc1 device!!!!!\n",
				__FILE__);
	}
	else
	{
		rtc_set_time(rtc1,tm);
		rtc_class_close(rtc1);
	}
#endif
	return 0;
}
Esempio n. 11
0
extern int
rtc_set_time_test(int autotest)
{
	rtc_time_t time;
	
	printf("Please input the RTC time, ex: on Monday, 5:30:40:00 PM\n");
	printf("Set Time = 1:17:30:40:00, Your Time = ");
	scanf("%d:%1d%1d:%1d%1d:%1d%1d:%d", &time.dow, &time.ten_hr, &time.hr,	\
				&time.ten_min, &time.min, &time.ten_sec, &time.sec, &time.sos);
	
	PDEBUG("Input Time = %d:%d%d:%d%d:%d%d:%d\n", time.dow, time.ten_hr, time.hr,	\
				time.ten_min, time.min, time.ten_sec, time.sec, time.sos);

	rtc_set_time(&time);

	return 0;
}
Esempio n. 12
0
void rt_timer_interrupt(struct pt_regs *regs)
{
    int cpu = smp_processor_id();
    int cpuA = ((cputoslice(cpu)) == 0);
    int irq = 9;				/* XXX Assign number */

    irq_enter();
    write_seqlock(&xtime_lock);

again:
    LOCAL_HUB_S(cpuA ? PI_RT_PEND_A : PI_RT_PEND_B, 0);	/* Ack  */
    ct_cur[cpu] += CYCLES_PER_JIFFY;
    LOCAL_HUB_S(cpuA ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, ct_cur[cpu]);

    if (LOCAL_HUB_L(PI_RT_COUNT) >= ct_cur[cpu])
        goto again;

    kstat_this_cpu.irqs[irq]++;		/* kstat only for bootcpu? */

    if (cpu == 0)
        do_timer(regs);

#ifdef CONFIG_SMP
    update_process_times(user_mode(regs));
#endif /* CONFIG_SMP */

    /*
     * If we have an externally synchronized Linux clock, then update
     * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
     * called as close as possible to when a second starts.
     */
    if ((time_status & STA_UNSYNC) == 0 &&
            xtime.tv_sec > last_rtc_update + 660 &&
            (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
            (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
        if (rtc_set_time(xtime.tv_sec) == 0) {
            last_rtc_update = xtime.tv_sec;
        } else {
            last_rtc_update = xtime.tv_sec - 600;
            /* do it again in 60 s */
        }
    }

    write_sequnlock(&xtime_lock);
    irq_exit();
}
Esempio n. 13
0
void main(void)
{
    struct tm timeinfo;

    rtc_init();
    
    // Give RTC a initial value: 2015/4/15 (Wed) 12:00:00
    rtc_set_time(2015, 4, 15, 3, 12, 0, 0);

    while (1) {
        rtc_read_time(&timeinfo);
        DBG_8195A("%d-%d-%d[%d] %d:%d:%d\r\n", timeinfo.tm_year, timeinfo.tm_mon, timeinfo.tm_mday,
            timeinfo.tm_wday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
        wait_ms(1000);
    }
    rtc_deinit();
}
Esempio n. 14
0
/**
* \brief Configure RTC for test
* \Set alarm ewery second
*/
void configure_rtc (void)
{
  	uint32_t status;
	struct _time MTU = {00, 00, 00};
	struct _time MTA = {18, 30, 00};
	struct _date MDT = {2015, 06, 01, 1};

	rtc_set_hour_mode(0); // mode 24h
	status = rtc_set_time(&MTU);
	status |= rtc_set_date(&MDT);
	status |= rtc_set_time_alarm(&MTA);
	status |= rtc_set_time_event (RTC_CR_TIMEVSEL_MINUTE);
	rtc_disable_it (RTC_IER_ACKEN | RTC_IER_ALREN | RTC_IER_SECEN | RTC_IER_TIMEN | RTC_IER_CALEN);
	rtc_enable_it (RTC_IER_SECEN);

	aic_set_source_vector(ID_SYSC, rtc_irq_handler);
	aic_enable(ID_SYSC);
}
Esempio n. 15
0
static int rtc_post_load(void *opaque, int version_id)
{
    RTCState *s = opaque;

    if (version_id <= 2) {
        rtc_set_time(s);
        s->offset = 0;
        check_update_timer(s);
    }

#ifdef TARGET_I386
    if (version_id >= 2) {
        if (s->lost_tick_policy == LOST_TICK_SLEW) {
            rtc_coalesced_timer_update(s);
        }
    }
#endif
    return 0;
}
Esempio n. 16
0
/**
 * RTCの時間を設定します。
 *
 * @param[in] year 年を指定します。
 * @param[in] mon  月を指定します。
 * @param[in] day  日を指定します。
 * @param[in] hour 時を指定します。
 * @param[in] min  分を指定します。
 * @param[in] sec  秒を指定します。
 * @param[in] week 曜日を指定します。
 *
 * @return 時間の設定に成功した場合はtrueを返却します。失敗した場合はfalseを返却します。
 *
 * @attention なし
 ***************************************************************************/
bool RTC::setDateTime(int year, int mon, int day, int hour, int min, int sec, int week)
{
	bool bError = true;
	RTC_TIMETYPE time;

	time.year   = year;
	time.mon    = mon;
	time.day    = day;
	time.hour   = hour;
	time.min    = min;
	time.second = sec;
	time.weekday= week;

	if (rtc_set_time(&time) == 0) {
		bError = false;
	}

	return (bError);
}
static int alarm_set_rtc(struct timespec *ts)
{
	struct rtc_time new_rtc_tm;
	struct rtc_device *rtc_dev;
	unsigned long flags;
	int rv = 0;

	rtc_time_to_tm(ts->tv_sec, &new_rtc_tm);
	rtc_dev = alarmtimer_get_rtcdev();
	rv = do_settimeofday(ts);
	if (rv < 0)
		return rv;
	if (rtc_dev)
		rv = rtc_set_time(rtc_dev, &new_rtc_tm);

	spin_lock_irqsave(&alarm_slock, flags);
	alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK;
	wake_up(&alarm_wait_queue);
	spin_unlock_irqrestore(&alarm_slock, flags);

	return rv;
}
Esempio n. 18
0
THD_FUNCTION(TimeKeeper::TimekeeperThread, arg) {
  chRegSetThreadName("Timekeeper");
  TimeKeeper *self = static_cast<TimeKeeper *>(arg);

  self->GNSS.subscribe(&gps);

  while (!chThdShouldTerminateX()) {
    if ((gps.fresh) && (gps.fix > 0) && (0 == gps.msec)) {
      int64_t tmp = 1000000;
      tmp *= mktime(&gps.time);

      osalSysLock();
      time_gps_us = tmp;
      if (! time_verified) {
        time_verified = true;
        unix_usec = time_gps_us;
      }
      osalSysUnlock();

      /* now correct time in internal RTC (if needed) */
      int32_t t1 = time_gps_us / 1000000;
      int32_t t2 = rtc_get_time_unix(nullptr);
      int32_t dt = t1 - t2;

      if (abs(dt) > TIME_CORRECTION_THRESHOLD)
        rtc_set_time(&gps.time);
    }

    if (gps.fresh) {
      gps.fresh = false;
    }

    osalThreadSleepMilliseconds(20);
  }

  self->GNSS.unsubscribe(&gps);
  chThdExit(MSG_OK);
}
Esempio n. 19
0
/**
 * \brief Callback function for RTC compare interrupt handler
 *
 * The function executes when the RTC compare interrupt occurs and loop
 * through all timeout channels. The timeout_array[channel_index] which
 * contains the remaining ticks before timeout is decremented and the timeout
 * active/expired masks are updated.
 */
static void tick_handler(uint32_t time)
{
	uint8_t i;

	/* Loop through all timeout channels */
	for (i = 0; i < TIMEOUT_COUNT; i++) {
		/* Skip processing on current channel if not active */
		if (!(timeout_active & (1 << i))) {
			continue;
		}

		/* Decrement current channel with one tick */
		timeout_array[i].count--;

		/* Skip further processing on current channel if not expired */
		if (timeout_array[i].count) {
			continue;
		} else {
			/* Update expired bit mask with current channel */
			timeout_expired |= 1 << i;

			/* If Periodic timer, reset timeout counter to period
			 * time */
			if (timeout_array[i].period) {
				timeout_array[i].count
					= timeout_array[i].period;
			}
			/* If not periodic timeout, set current channel to
			 * in-active */
			else {
				timeout_active &= ~(1 << i);
			}
		}
	}
	/* Reset RTC before next tick */
	rtc_set_time(0);
	rtc_set_alarm(TIMEOUT_COMP);
}
Esempio n. 20
0
/**
 * \brief Initialize RTC32 and VBAT
 *
 * This function checks the RTC32 and VBAT systems' status, initializing them if
 * necessary. If the status is OK, only the RTC32 is reset.
 *
 * To ensure that WDT resets occur with correct timing, the RTC32 is reset to
 * the last time which was read out from it.
 */
static void main_init_rtc32(void)
{
    /* RTC32 clock must be enabled after sysclk_init() to check VBAT */
    sysclk_enable_module(SYSCLK_PORT_GEN, SYSCLK_RTC);
    while (RTC32.SYNCCTRL & RTC32_SYNCBUSY_bm) {
        /* Wait for synchronization */
    }

    /* Initialize the RTC32 and VBAT if its status is not OK */
    if (rtc_vbat_system_check(false) != VBAT_STATUS_OK) {
        rtc_init();
        /* Otherwise, just ensure the RTC32 is enabled with correct period */
    } else {
        RTC32.CTRL = ~RTC32_ENABLE_bm;
        while (RTC32.SYNCCTRL & RTC32_SYNCBUSY_bm) {
        }
        RTC32.PER = 0xffffffff;
        RTC32.CTRL = RTC32_ENABLE_bm;
    }

    /* Reset the time */
    rtc_set_time(classb_last_wdt_reset);
}
Esempio n. 21
0
static int __init rtc_hctosys(void)
{
	int err, rtc_init = 0;
	struct rtc_time tm;
	struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);

	if (rtc == NULL) {
		printk("%s: unable to open rtc device (%s)\n",
			__FILE__, CONFIG_RTC_HCTOSYS_DEVICE);
		return -ENODEV;
	}

	err = rtc_read_time(rtc, &tm);
	
	#if 1	// charles debug
		printk("============== RTC Debug Param =================\n");
		printk("tm_year = %d\n", tm.tm_year);	printk("tm_mon  = %d\n", tm.tm_mon);
		printk("tm_mday = %d\n", tm.tm_mday);	printk("tm_hour = %d\n", tm.tm_hour);
		printk("tm_min  = %d\n", tm.tm_min);	printk("tm_sec  = %d\n", tm.tm_sec);
		printk("================================================\n");
	#endif

	// android system time valid check, 
	// rtc read time is invalid, set to default system time 2010, jan, 1, 00:00:00
	if((tm.tm_year+1900)<=1970 || (tm.tm_year+1900)>2037) {
		printk("%s[%d]: invalid system time -> set to default system time.. \n", __FILE__,__LINE__);
		rtc_init = 1;
	}
	
	if (err == 0) {

		err = rtc_valid_tm(&tm);

		if(err || rtc_init)	{
			// RTC default value setting (2010-01-01, 0:0:0)
			tm.tm_year = 110;	tm.tm_mon = 0;		tm.tm_mday = 1;
			tm.tm_hour = 0;		tm.tm_min = 0;		tm.tm_sec = 0;

			err = rtc_valid_tm(&tm);

			if(err == 0)	{
				printk("============== RTC set to default system time =================\n");
				printk("tm_year = %d\n", tm.tm_year);		printk("tm_mon  = %d\n", tm.tm_mon);
				printk("tm_mday = %d\n", tm.tm_mday);		printk("tm_hour = %d\n", tm.tm_hour);
				printk("tm_min  = %d\n", tm.tm_min);		printk("tm_sec  = %d\n", tm.tm_sec);
				printk("===============================================================\n");
				rtc_set_time(rtc, &tm);
			}
		}

		if (err == 0) {
			struct timespec tv;

			tv.tv_nsec = NSEC_PER_SEC >> 1;

			rtc_tm_to_time(&tm, &tv.tv_sec);

			do_settimeofday(&tv);

			dev_info(rtc->dev.parent,
				"setting system clock to "
				"%d-%02d-%02d %02d:%02d:%02d UTC (%u)\n",
				tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
				tm.tm_hour, tm.tm_min, tm.tm_sec,
				(unsigned int) tv.tv_sec);
		}
		else
Esempio n. 22
0
static void cmos_ioport_write(void *opaque, hwaddr addr,
                              uint64_t data, unsigned size)
{
    RTCState *s = opaque;

    if ((addr & 1) == 0) {
        s->cmos_index = data & 0x7f;
    } else {
        CMOS_DPRINTF("cmos: write index=0x%02x val=0x%02x\n",
                     s->cmos_index, data);
        switch(s->cmos_index) {
        case RTC_SECONDS_ALARM:
        case RTC_MINUTES_ALARM:
        case RTC_HOURS_ALARM:
            s->cmos_data[s->cmos_index] = data;
            check_update_timer(s);
            break;
	case RTC_IBM_PS2_CENTURY_BYTE:
            s->cmos_index = RTC_CENTURY;
            /* fall through */
        case RTC_CENTURY:
        case RTC_SECONDS:
        case RTC_MINUTES:
        case RTC_HOURS:
        case RTC_DAY_OF_WEEK:
        case RTC_DAY_OF_MONTH:
        case RTC_MONTH:
        case RTC_YEAR:
            s->cmos_data[s->cmos_index] = data;
            /* if in set mode, do not update the time */
            if (rtc_running(s)) {
                rtc_set_time(s);
                check_update_timer(s);
            }
            break;
        case RTC_REG_A:
            if ((data & 0x60) == 0x60) {
                if (rtc_running(s)) {
                    rtc_update_time(s);
                }
                /* What happens to UIP when divider reset is enabled is
                 * unclear from the datasheet.  Shouldn't matter much
                 * though.
                 */
                s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
            } else if (((s->cmos_data[RTC_REG_A] & 0x60) == 0x60) &&
                    (data & 0x70)  <= 0x20) {
                /* when the divider reset is removed, the first update cycle
                 * begins one-half second later*/
                if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
                    s->offset = 500000000;
                    rtc_set_time(s);
                }
                s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
            }
            /* UIP bit is read only */
            s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
                (s->cmos_data[RTC_REG_A] & REG_A_UIP);
            periodic_timer_update(s, qemu_get_clock_ns(rtc_clock));
            check_update_timer(s);
            break;
        case RTC_REG_B:
            if (data & REG_B_SET) {
                /* update cmos to when the rtc was stopping */
                if (rtc_running(s)) {
                    rtc_update_time(s);
                }
                /* set mode: reset UIP mode */
                s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
                data &= ~REG_B_UIE;
            } else {
                /* if disabling set mode, update the time */
                if ((s->cmos_data[RTC_REG_B] & REG_B_SET) &&
                    (s->cmos_data[RTC_REG_A] & 0x70) <= 0x20) {
                    s->offset = get_guest_rtc_ns(s) % NSEC_PER_SEC;
                    rtc_set_time(s);
                }
            }
            /* if an interrupt flag is already set when the interrupt
             * becomes enabled, raise an interrupt immediately.  */
            if (data & s->cmos_data[RTC_REG_C] & REG_C_MASK) {
                s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
                qemu_irq_raise(s->irq);
            } else {
                s->cmos_data[RTC_REG_C] &= ~REG_C_IRQF;
                qemu_irq_lower(s->irq);
            }
            s->cmos_data[RTC_REG_B] = data;
            periodic_timer_update(s, qemu_get_clock_ns(rtc_clock));
            check_update_timer(s);
            break;
        case RTC_REG_C:
        case RTC_REG_D:
            /* cannot write to them */
            break;
        default:
            s->cmos_data[s->cmos_index] = data;
            break;
        }
    }
}
Esempio n. 23
0
extern int
auto_poweroff_alarm_test(int autotest)
{
	int count_down_s = 5;
	
	rtc_reset();

	// Set alarm date and alarm time
	// alarm date = C21 06/12/31
	dt_a.ten_cent = 2;
	dt_a.cent     = 1;
	dt_a.ten_yr   = 0;
	dt_a.yr       = 6;
	dt_a.ten_mth  = 1;
	dt_a.mth      = 2;
	dt_a.ten_day  = 3;
	dt_a.day      = 1;
	rtc_set_date_alarm(&dt_a,
			SOCLE_RTC_DALRM_CD	|
			SOCLE_RTC_DALRM_CM	|
			SOCLE_RTC_DALRM_CY	|
			SOCLE_RTC_DALRM_CC);

	// alarm time = Wed 17:58:1count_down_s.10
	tm_a.dow      = 3;
	tm_a.ten_hr   = 1;
	tm_a.hr       = 7;
	tm_a.ten_min  = 5;
	tm_a.min      = 8;
	tm_a.ten_sec  = 1;
	tm_a.sec      = count_down_s;
	tm_a.sos      = 10;
	rtc_set_time_alarm(&tm_a,
			SOCLE_RTC_TALRM_CSOS	|
			SOCLE_RTC_TALRM_CS	|
			SOCLE_RTC_TALRM_CM	|
			SOCLE_RTC_TALRM_CH	|
			SOCLE_RTC_TALRM_CDOW);

	// Set date and time
	// date = C21 06/12/31
	dt.ten_cent = 2;
	dt.cent     = 1;
	dt.ten_yr   = 0;
	dt.yr       = 6;
	dt.ten_mth  = 1;
	dt.mth      = 2;
	dt.ten_day  = 3;
	dt.day      = 1;
	rtc_set_date(&dt);
	
	// time = Wed 17:58:10.2
	tm.dow      = 3;
	tm.ten_hr   = 1;
	tm.hr       = 7;
	tm.ten_min  = 5;
	tm.min      = 8;
	tm.ten_sec  = 1;
	tm.sec      = 0;
	tm.sos      = 2;
	rtc_set_time(&tm);

	printf("Count down %d seconds...\n", count_down_s);

	printf("Sleeping...\n");
	EN_RTC_ALARM_POWER_ON();
	ENTER_RTC_POWER_OFF_MODE();
	
	return 0;
}
Esempio n. 24
0
static int
rtc_sub_alarm_test(u32_t f_time, u32_t f_date)
{
	volatile int	hit;
	int result = 0;
	
	rtc_reset();

	printf("RTC Time = W%d %d%d:%d%d:%d%d:%d\n", tm.dow, tm.ten_hr, tm.hr,	\
				tm.ten_min, tm.min, tm.ten_sec, tm.sec, tm.sos);

	printf("RTC Date = C%d%d %d%d/%d%d/%d%d\n", dt.ten_cent, dt.cent, dt.ten_yr, dt.yr,	\
				dt.ten_mth, dt.mth, dt.ten_day, dt.day);

	printf("Alarm Time = W%d %d%d:%d%d:%d%d:%d\n", tm_a.dow, tm_a.ten_hr, tm_a.hr,	\
				tm_a.ten_min, tm_a.min, tm_a.ten_sec, tm_a.sec, tm_a.sos);

	printf("Alarm Date = C%d%d %d%d/%d%d/%d%d\n", dt_a.ten_cent, dt_a.cent, dt_a.ten_yr, dt_a.yr,	\
				dt_a.ten_mth, dt_a.mth, dt_a.ten_day, dt_a.day);

	printf("Alarm Time on: ");
	if (f_time & SOCLE_RTC_TALRM_CSOS)
		printf("\"Sixteen of Second\" ");
	if (f_time & SOCLE_RTC_TALRM_CS)
		printf("\"Second\" ");
	if (f_time & SOCLE_RTC_TALRM_CM)
		printf("\"Minute\" ");
	if (f_time & SOCLE_RTC_TALRM_CH)
		printf("\"Hour\" ");
	if (f_time & SOCLE_RTC_TALRM_CDOW)
		printf("\"Day of Week\"");
	printf("\n");	

	printf("Alarm Date on: ");
	if (f_date & SOCLE_RTC_DALRM_CD)
		printf("\"Day\" ");
	if (f_date & SOCLE_RTC_DALRM_CM)
		printf("\"Month\" ");
	if (f_date & SOCLE_RTC_DALRM_CY)
		printf("\"Year\" ");
	if (f_date & SOCLE_RTC_DALRM_CC)
		printf("\"Century\"");
	printf("\n");

	rtc_set_time_alarm(&tm_a, f_time);
	rtc_set_date_alarm(&dt_a, f_date);

	hit = 0;

	// enable interrupt
	request_irq(RTC_INT, rtc_isr_alarm_hit, (void *)&hit);

	rtc_set_date(&dt);
	rtc_set_time(&tm);

	printf("Waiting for the alarm...\n");
	
	if (socle_wait_for_int(&hit, 10)) {
		printf("Timeout!!\n");
		result = -1;
	}

	// disable interrupt
	free_irq(RTC_INT);

	return result;
}
Esempio n. 25
0
File: rtc.c Progetto: 0day-ci/xen
static int rtc_ioport_write(void *opaque, uint32_t addr, uint32_t data)
{
    RTCState *s = opaque;
    struct domain *d = vrtc_domain(s);
    uint32_t orig;

    spin_lock(&s->lock);

    if ( (addr & 1) == 0 )
    {
        data &= 0x7f;
        s->hw.cmos_index = data;
        spin_unlock(&s->lock);
        return (data < RTC_CMOS_SIZE);
    }

    if ( s->hw.cmos_index >= RTC_CMOS_SIZE )
    {
        spin_unlock(&s->lock);
        return 0;
    }

    orig = s->hw.cmos_data[s->hw.cmos_index];
    switch ( s->hw.cmos_index )
    {
    case RTC_SECONDS_ALARM:
    case RTC_MINUTES_ALARM:
    case RTC_HOURS_ALARM:
        s->hw.cmos_data[s->hw.cmos_index] = data;
        alarm_timer_update(s);
        break;
    case RTC_SECONDS:
    case RTC_MINUTES:
    case RTC_HOURS:
    case RTC_DAY_OF_WEEK:
    case RTC_DAY_OF_MONTH:
    case RTC_MONTH:
    case RTC_YEAR:
        /* if in set mode, just write the register */
        if ( (s->hw.cmos_data[RTC_REG_B] & RTC_SET) )
            s->hw.cmos_data[s->hw.cmos_index] = data;
        else
        {
            /* Fetch the current time and update just this field. */
            s->current_tm = gmtime(get_localtime(d));
            rtc_copy_date(s);
            s->hw.cmos_data[s->hw.cmos_index] = data;
            rtc_set_time(s);
        }
        alarm_timer_update(s);
        break;
    case RTC_REG_A:
        /* UIP bit is read only */
        s->hw.cmos_data[RTC_REG_A] = (data & ~RTC_UIP) | (orig & RTC_UIP);
        if ( (data ^ orig) & ~RTC_UIP )
            rtc_timer_update(s);
        break;
    case RTC_REG_B:
        if ( data & RTC_SET )
        {
            /* set mode: reset UIP mode */
            s->hw.cmos_data[RTC_REG_A] &= ~RTC_UIP;
            /* adjust cmos before stopping */
            if (!(orig & RTC_SET))
            {
                s->current_tm = gmtime(get_localtime(d));
                rtc_copy_date(s);
            }
        }
        else
        {
            /* if disabling set mode, update the time */
            if ( orig & RTC_SET )
                rtc_set_time(s);
        }
        check_for_pf_ticks(s);
        s->hw.cmos_data[RTC_REG_B] = data;
        /*
         * If the interrupt is already set when the interrupt becomes
         * enabled, raise an interrupt immediately.
         */
        rtc_update_irq(s);
        if ( (data ^ orig) & RTC_PIE )
        {
            TRACE_0D(TRC_HVM_EMUL_RTC_STOP_TIMER);
            destroy_periodic_time(&s->pt);
            s->period = 0;
            rtc_timer_update(s);
        }
        if ( (data ^ orig) & RTC_SET )
            check_update_timer(s);
        if ( (data ^ orig) & (RTC_24H | RTC_DM_BINARY | RTC_SET) )
            alarm_timer_update(s);
        break;
    case RTC_REG_C:
    case RTC_REG_D:
        /* cannot write to them */
        break;
    }

    spin_unlock(&s->lock);

    return 1;
}
Esempio n. 26
0
static int tcube_rtc_ioctl(struct inode *inode, struct file *file,
			   unsigned int cmd, unsigned long arg)
{
	struct rtc_time tm;
	unsigned long curr_time;
#if defined(RTC_ALARM_SUPPORT)
	unsigned char ctrl_reg[2];
#endif

	switch (cmd) {
	case RTC_AIE_OFF:
#if defined(RTC_ALARM_SUPPORT)
		spin_lock_irq (&rtc_lock);
		rtc_get_ctrl_reg(&ctrl_reg[0]);
		ctrl_reg[0] ^= 0x40;
		rtc_set_ctrl_reg(&ctrl_reg[0]);
		spin_unlock_irq (&rtc_lock);
#else
		return -EINVAL;
#endif
		break;

	case RTC_AIE_ON:
#if defined(RTC_ALARM_SUPPORT)
		spin_lock_irq (&rtc_lock);
		rtc_get_ctrl_reg(&ctrl_reg[0]);
		ctrl_reg[0] |= 0x40;
		rtc_set_ctrl_reg(&ctrl_reg[0]);
		spin_unlock_irq (&rtc_lock);
#else
		return -EINVAL;
#endif
		break;

	case RTC_UIE_OFF:
		return -EINVAL;
		break;

	case RTC_UIE_ON:
		return -EINVAL;
		break;

	case RTC_ALM_READ:
		rtc_get_alm_time(&tm);
		break;

	case RTC_ALM_SET:
		if (copy_from_user (&tm, (struct rtc_time*)arg, sizeof (tm)))
			return -EFAULT;
		return rtc_set_alm_time(&tm);

	case RTC_RD_TIME:	/* Read the time/date from RTC  */
		curr_time = rtc_get_time();
		to_tm(curr_time, &tm);
		tm.tm_year -= 1900;
		break;

	case RTC_SET_TIME:	/* Set the time/date from RTC  */
		if (!capable(CAP_SYS_TIME))
			return -EACCES;
		if (copy_from_user (&tm, (struct rtc_time*)arg, sizeof (tm)))
			return -EFAULT;
		tm.tm_year += 1900;
		if (tm.tm_year < 1970 || (unsigned)tm.tm_mon >= 12 ||
		    tm.tm_mday < 1 || tm.tm_mday > (days_in_mo[tm.tm_mon] +
				(tm.tm_mon == 1 && is_leap(tm.tm_year))) ||
		    (unsigned)tm.tm_hour >= 24 ||
		    (unsigned)tm.tm_min >= 60 ||
		    (unsigned)tm.tm_sec >= 60)
			return -EINVAL;
		curr_time = mktime (tm.tm_year,
				    tm.tm_mon + 1, /* tm_mon starts from 0 */
				    tm.tm_mday,
				    tm.tm_hour,
				    tm.tm_min,
			       	    tm.tm_sec);
		return rtc_set_time(curr_time);

	case RTC_PIE_ON:
	case RTC_PIE_OFF:
	case RTC_IRQP_READ:
	case RTC_IRQP_SET:
	case RTC_EPOCH_READ:
	case RTC_EPOCH_SET:
	case RTC_WKALM_SET:
	case RTC_WKALM_RD:
	default:
		return -EINVAL;
	}
	return copy_to_user ((void *)arg, &tm, sizeof (tm)) ? -EFAULT : 0;
}
Esempio n. 27
0
static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
		     unsigned long arg)
{
	struct rtc_ops *ops = file->private_data;
	struct rtc_time tm;
	struct rtc_wkalrm alrm;
	void __user *uarg = (void __user *)arg;
	int ret = -EINVAL;

	switch (cmd) {
	case RTC_ALM_READ:
		ret = rtc_read_alarm(ops, &alrm);
		if (ret)
			break;
		ret = copy_to_user(uarg, &alrm.time, sizeof(tm));
		if (ret)
			ret = -EFAULT;
		break;

	case RTC_ALM_SET:
		ret = copy_from_user(&alrm.time, uarg, sizeof(tm));
		if (ret) {
			ret = -EFAULT;
			break;
		}
		alrm.enabled = 0;
		alrm.pending = 0;
		alrm.time.tm_mday = -1;
		alrm.time.tm_mon = -1;
		alrm.time.tm_year = -1;
		alrm.time.tm_wday = -1;
		alrm.time.tm_yday = -1;
		alrm.time.tm_isdst = -1;
		ret = rtc_set_alarm(ops, &alrm);
		break;

	case RTC_RD_TIME:
		ret = rtc_read_time(ops, &tm);
		if (ret)
			break;
		ret = copy_to_user(uarg, &tm, sizeof(tm));
		if (ret)
			ret = -EFAULT;
		break;

	case RTC_SET_TIME:
		if (!capable(CAP_SYS_TIME)) {
			ret = -EACCES;
			break;
		}
		ret = copy_from_user(&tm, uarg, sizeof(tm));
		if (ret) {
			ret = -EFAULT;
			break;
		}
		ret = rtc_set_time(ops, &tm);
		break;

	case RTC_EPOCH_SET:
#ifndef rtc_epoch
		/*
		 * There were no RTC clocks before 1900.
		 */
		if (arg < 1900) {
			ret = -EINVAL;
			break;
		}
		if (!capable(CAP_SYS_TIME)) {
			ret = -EACCES;
			break;
		}
		rtc_epoch = arg;
		ret = 0;
#endif
		break;

	case RTC_EPOCH_READ:
		ret = put_user(rtc_epoch, (unsigned long __user *)uarg);
		break;

	case RTC_WKALM_SET:
		ret = copy_from_user(&alrm, uarg, sizeof(alrm));
		if (ret) {
			ret = -EFAULT;
			break;
		}
		ret = rtc_set_alarm(ops, &alrm);
		break;

	case RTC_WKALM_RD:
		ret = rtc_read_alarm(ops, &alrm);
		if (ret)
			break;
		ret = copy_to_user(uarg, &alrm, sizeof(alrm));
		if (ret)
			ret = -EFAULT;
		break;

	default:
		if (ops->ioctl)
			ret = ops->ioctl(cmd, arg);
		break;
	}
	return ret;
}
Esempio n. 28
0
static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
{
    RTCState *s = opaque;

    if ((addr & 1) == 0) {
        s->cmos_index = data & 0x7f;
    } else {
#ifdef DEBUG_CMOS
        printf("cmos: write index=0x%02x val=0x%02x\n",
               s->cmos_index, data);
#endif
        switch(s->cmos_index) {
        case RTC_SECONDS_ALARM:
        case RTC_MINUTES_ALARM:
        case RTC_HOURS_ALARM:
            /* XXX: not supported */
            s->cmos_data[s->cmos_index] = data;
            break;
        case RTC_SECONDS:
        case RTC_MINUTES:
        case RTC_HOURS:
        case RTC_DAY_OF_WEEK:
        case RTC_DAY_OF_MONTH:
        case RTC_MONTH:
        case RTC_YEAR:
            s->cmos_data[s->cmos_index] = data;
            /* if in set mode, do not update the time */
            if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
                rtc_set_time(s);
            }
            break;
        case RTC_REG_A:
            /* UIP bit is read only */
            s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
                (s->cmos_data[RTC_REG_A] & REG_A_UIP);
            rtc_timer_update(s, qemu_get_clock(vm_clock));
            break;
        case RTC_REG_B:
            if (data & REG_B_SET) {
                /* set mode: reset UIP mode */
                s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
                data &= ~REG_B_UIE;
            } else {
                /* if disabling set mode, update the time */
                if (s->cmos_data[RTC_REG_B] & REG_B_SET) {
                    rtc_set_time(s);
                }
            }
            s->cmos_data[RTC_REG_B] = data;
            rtc_timer_update(s, qemu_get_clock(vm_clock));
            break;
        case RTC_REG_C:
        case RTC_REG_D:
            /* cannot write to them */
            break;
        default:
            s->cmos_data[s->cmos_index] = data;
            break;
        }
    }
}
Esempio n. 29
0
int
main(int argc, char *argv[])
{
	int r, i;
	struct tm t;
	endpoint_t user, caller;
	message m;
	int ipc_status, reply_status;

	env_setargs(argc, argv);

	r = i2cdriver_env_parse(&bus, &addresses[0], valid_addrs);
	if (r < 0) {
		log_warn(&log, "Expecting -args 'bus=X address=0xYY'\n");
		log_warn(&log, "Example -args 'bus=1 address=0x48'\n");
		return EXIT_FAILURE;
	} else if (r > 0) {
		log_warn(&log,
		    "Invalid slave address for device, expecting 0x48\n");
		return EXIT_FAILURE;
	}

	sef_local_startup();

	while (TRUE) {

		/* Receive Message */
		r = sef_receive_status(ANY, &m, &ipc_status);
		if (r != OK) {
			log_warn(&log, "sef_receive_status() failed\n");
			continue;
		}

		if (is_ipc_notify(ipc_status)) {

			if (m.m_source == DS_PROC_NR) {
				for (i = 0; i < NADDRESSES; i++) {
					/* changed state, update endpoint */
					i2cdriver_handle_bus_update
					    (&bus_endpoint, bus, addresses[i]);
				}
			}

			/* Do not reply to notifications. */
			continue;
		}

		caller = m.m_source;

		log_debug(&log, "Got message 0x%x from 0x%x\n", m.m_type,
		    caller);

		switch (m.m_type) {
		case RTCDEV_GET_TIME_G:
			/* Any user can read the time */
			reply_status = rtc_get_time(&t, m.RTCDEV_FLAGS);
			if (reply_status != OK) {
				break;
			}

			/* write results back to calling process */
			reply_status =
			    store_t(caller, (cp_grant_id_t) m.RTCDEV_GRANT,
			    &t);
			break;

		case RTCDEV_SET_TIME_G:
			/* Only super user is allowed to set the time */
			if (getnuid(caller) == SUPER_USER) {
				/* read time from calling process */
				reply_status =
				    fetch_t(caller,
				    (cp_grant_id_t) m.RTCDEV_GRANT, &t);
				if (reply_status != OK) {
					break;
				}

				reply_status =
				    rtc_set_time(&t, m.RTCDEV_FLAGS);
			} else {
				reply_status = EPERM;
			}
			break;

		case RTCDEV_PWR_OFF:
			reply_status = ENOSYS;
			break;

		default:
			/* Unrecognized call */
			reply_status = EINVAL;
			break;
		}

		/* Send Reply */
		m.m_type = RTCDEV_REPLY;
		m.RTCDEV_STATUS = reply_status;

		log_debug(&log, "Sending Reply");

		r = sendnb(caller, &m);
		if (r != OK) {
			log_warn(&log, "sendnb() failed\n");
			continue;
		}
	}

	rtc_exit();

	return 0;
}
Esempio n. 30
0
static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
{
    RTCState *s = opaque;

    if ((addr & 1) == 0) {
        s->cmos_index = data & 0x7f;
    } else {
        CMOS_DPRINTF("cmos: write index=0x%02x val=0x%02x\n",
                     s->cmos_index, data);
        switch(s->cmos_index) {
        case RTC_SECONDS_ALARM:
        case RTC_MINUTES_ALARM:
        case RTC_HOURS_ALARM:
            s->cmos_data[s->cmos_index] = data;
            break;
        case RTC_SECONDS:
        case RTC_MINUTES:
        case RTC_HOURS:
        case RTC_DAY_OF_WEEK:
        case RTC_DAY_OF_MONTH:
        case RTC_MONTH:
        case RTC_YEAR:
            s->cmos_data[s->cmos_index] = data;
            /* if in set mode, do not update the time */
            if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
                rtc_set_time(s);
            }
            break;
        case RTC_REG_A:
            /* UIP bit is read only */
            s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
                (s->cmos_data[RTC_REG_A] & REG_A_UIP);
            rtc_timer_update(s, qemu_get_clock_ns(rtc_clock));
            break;
        case RTC_REG_B:
            if (data & REG_B_SET) {
                /* set mode: reset UIP mode */
                s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
                data &= ~REG_B_UIE;
            } else {
                /* if disabling set mode, update the time */
                if (s->cmos_data[RTC_REG_B] & REG_B_SET) {
                    rtc_set_time(s);
                }
            }
            if (((s->cmos_data[RTC_REG_B] ^ data) & (REG_B_DM | REG_B_24H)) &&
                !(data & REG_B_SET)) {
                /* If the time format has changed and not in set mode,
                   update the registers immediately. */
                s->cmos_data[RTC_REG_B] = data;
                rtc_copy_date(s);
            } else {
                s->cmos_data[RTC_REG_B] = data;
            }
            rtc_timer_update(s, qemu_get_clock_ns(rtc_clock));
            break;
        case RTC_REG_C:
        case RTC_REG_D:
            /* cannot write to them */
            break;
        default:
            s->cmos_data[s->cmos_index] = data;
            break;
        }
    }
}