/* * Program DS1307 with the specified time. * Must be called with tod_lock held. The TOD * chip supports date from 1969-2068 only. We must * reject requests to set date below 2000. */ static void todds1307_set(timestruc_t ts) { struct rtc_t rtc; todinfo_t tod = utc_to_tod(ts.tv_sec); int year; ASSERT(MUTEX_HELD(&tod_lock)); /* * Year is base 1900, valid year range 1969-2068 */ if ((tod.tod_year < 69) || (tod.tod_year > 168)) return; year = tod.tod_year; if (year >= 100) year -= 100; rtc.rtc_year = int2bcd(year); rtc.rtc_mon = int2bcd(tod.tod_month); rtc.rtc_dom = int2bcd(tod.tod_day); rtc.rtc_dow = int2bcd(tod.tod_dow); rtc.rtc_hrs = int2bcd(tod.tod_hour); rtc.rtc_min = int2bcd(tod.tod_min); rtc.rtc_sec = int2bcd(tod.tod_sec); todds1307_write_rtc(&rtc); }
/* * program the rtc registers for alarm to go off at the specified time */ static void todbq4802_set_power_alarm(timestruc_t ts) { todinfo_t tod; uint8_t regc; struct rtc_t rtc; ASSERT(MUTEX_HELD(&tod_lock)); tod = utc_to_tod(ts.tv_sec); /* * disable alarms and clear AF flag by reading reg Flags (D) */ regc = BQ4802_DATA_REG(RTC_ENABLES); BQ4802_DATA_REG(RTC_ENABLES) = regc & ~(RTC_AIE | RTC_ABE); (void) BQ4802_DATA_REG(RTC_FLAGS); rtc.rtc_asec = (uint8_t)tod.tod_sec; rtc.rtc_amin = (uint8_t)tod.tod_min; rtc.rtc_ahrs = (uint8_t)tod.tod_hour; rtc.rtc_adom = (uint8_t)tod.tod_day; DPRINTF("todbq4802_set_alarm: dom=%d hrs=%d min=%d sec=%d\n", rtc.rtc_adom, rtc.rtc_ahrs, rtc.rtc_amin, rtc.rtc_asec); /* * Write alarm values and enable alarm */ write_rtc_alarm(&rtc); BQ4802_DATA_REG(RTC_ENABLES) = regc | RTC_AIE | RTC_ABE; }
/* * program the rtc registers for alarm to go off at the specified time */ static void todm5819_set_power_alarm(timestruc_t ts) { todinfo_t tod; uint8_t regb; struct rtc_t rtc; ASSERT(MUTEX_HELD(&tod_lock)); tod = utc_to_tod(ts.tv_sec); /* * disable alarms */ regb = RTC_GET8(RTC_B); RTC_PUT8(RTC_B, (regb & ~RTC_AIE)); rtc.rtc_asec = (uint8_t)tod.tod_sec; rtc.rtc_amin = (uint8_t)tod.tod_min; rtc.rtc_ahrs = (uint8_t)tod.tod_hour; rtc.rtc_adom = (uint8_t)tod.tod_day; write_rtc_alarm(&rtc); /* * Enable alarm. */ RTC_PUT8(RTC_B, (regb | RTC_AIE)); }
/* * program the rtc registers for alarm to go off at the specified time */ static void todds_set_power_alarm(timestruc_t ts) { todinfo_t tod; uint8_t apcr2; struct rtc_t rtc; ASSERT(MUTEX_HELD(&tod_lock)); tod = utc_to_tod(ts.tv_sec); mutex_enter(&ds1287_reg_mutex); /* Clear Time Match Detect */ select_bank(2); DS1287_ADDR_REG = APC_APSR; apcr2 = DS1287_DATA_REG; /* Disable Time Match Enable */ DS1287_ADDR_REG = APC_APCR2; apcr2 = DS1287_DATA_REG; DS1287_DATA_REG = (apcr2 & (~APC_TME)); mutex_exit(&ds1287_reg_mutex); rtc.rtc_asec = (uint8_t)tod.tod_sec; rtc.rtc_amin = (uint8_t)tod.tod_min; rtc.rtc_ahrs = (uint8_t)tod.tod_hour; rtc.rtc_adom = (uint8_t)tod.tod_day; rtc.rtc_amon = (uint8_t)tod.tod_month; rtc.apc_wdwr = (uint8_t)tod.tod_dow; rtc.apc_wdmr = (uint8_t)tod.tod_day; rtc.apc_wmr = (uint8_t)tod.tod_month; rtc.apc_wyr = tod.tod_year % 100; rtc.apc_wcr = (tod.tod_year / 100) + 19; write_rtc_alarm(&rtc); mutex_enter(&ds1287_reg_mutex); /* Enable Time Match enable */ select_bank(2); DS1287_ADDR_REG = APC_APCR2; DS1287_DATA_REG = (apcr2 | APC_TME); mutex_exit(&ds1287_reg_mutex); }
/* * Write the specified time into the clock chip. * Must be called with tod_lock held. */ static void todbq4802_set(timestruc_t ts) { struct rtc_t rtc; todinfo_t tod = utc_to_tod(ts.tv_sec); int year; ASSERT(MUTEX_HELD(&tod_lock)); /* tod_year is base 1900 so this code needs to adjust */ year = 1900 + tod.tod_year; rtc.rtc_year = year % 100; rtc.rtc_century = year / 100; rtc.rtc_mon = (uint8_t)tod.tod_month; rtc.rtc_dom = (uint8_t)tod.tod_day; rtc.rtc_dow = (uint8_t)tod.tod_dow; rtc.rtc_hrs = (uint8_t)tod.tod_hour; rtc.rtc_min = (uint8_t)tod.tod_min; rtc.rtc_sec = (uint8_t)tod.tod_sec; DPRINTF("todbq4802_set: year=%d dom=%d hrs=%d min=%d sec=%d\n", rtc.rtc_year, rtc.rtc_dom, rtc.rtc_hrs, rtc.rtc_min, rtc.rtc_sec); write_rtc_time(&rtc); }
static timestruc_t todxen_get(tod_ops_t *top) { todinfo_t tod; timestruc_t ts, wcts; shared_info_t *si = HYPERVISOR_shared_info; uint32_t xen_wc_version; hrtime_t now; ASSERT(MUTEX_HELD(&tod_lock)); /* * Pick up the wallclock base time */ do { xen_wc_version = si->wc_version; membar_consumer(); wcts.tv_sec = si->wc_sec; wcts.tv_nsec = si->wc_nsec; membar_consumer(); } while ((si->wc_version & 1) | (xen_wc_version ^ si->wc_version)); /* * Compute the TOD as the wallclock (boot) time plus time-since-boot * (/not/ hrtime!) and normalize. */ now = xpv_getsystime() + (hrtime_t)wcts.tv_nsec + (hrtime_t)wcts.tv_sec * NANOSEC; ts.tv_sec = (time_t)(now / NANOSEC); ts.tv_nsec = (long)(now % NANOSEC); /* * Apply GMT lag correction from /etc/rtc_config to get UTC time */ ts.tv_sec += ggmtl(); /* * Validate the TOD in case of total insanity */ tod = utc_to_tod(ts.tv_sec); if (tod.tod_year < 69) { static int range_warn = 1; /* warn only once */ if (range_warn) { /* * If we're dom0, go invoke the underlying driver; the * routine should complain if it discovers something * wrong. */ if (DOMAIN_IS_INITDOMAIN(xen_info)) (void) TODOP_GET(top->tod_next); /* * Check the virtual hardware. */ if (tod.tod_year > 38) cmn_err(CE_WARN, "hypervisor wall clock is out " "of range -- time needs to be reset"); range_warn = 0; } tod.tod_year += 100; ts.tv_sec = tod_to_utc(tod); } return (ts); }