11708Sstevel /* 21708Sstevel * CDDL HEADER START 31708Sstevel * 41708Sstevel * The contents of this file are subject to the terms of the 5*7696SRichard.Bean@Sun.COM * Common Development and Distribution License (the "License"). 6*7696SRichard.Bean@Sun.COM * You may not use this file except in compliance with the License. 71708Sstevel * 81708Sstevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91708Sstevel * or http://www.opensolaris.org/os/licensing. 101708Sstevel * See the License for the specific language governing permissions 111708Sstevel * and limitations under the License. 121708Sstevel * 131708Sstevel * When distributing Covered Code, include this CDDL HEADER in each 141708Sstevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151708Sstevel * If applicable, add the following below this CDDL HEADER, with the 161708Sstevel * fields enclosed by brackets "[]" replaced with your own identifying 171708Sstevel * information: Portions Copyright [yyyy] [name of copyright owner] 181708Sstevel * 191708Sstevel * CDDL HEADER END 201708Sstevel */ 211708Sstevel /* 22*7696SRichard.Bean@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 231708Sstevel * Use is subject to license terms. 241708Sstevel */ 251708Sstevel 261708Sstevel /* 271708Sstevel * tod driver module for Serengeti 281708Sstevel * This module implements a soft tod since 291708Sstevel * Serengeti has no tod part. 301708Sstevel */ 311708Sstevel 321708Sstevel #include <sys/modctl.h> 331708Sstevel #include <sys/systm.h> 341708Sstevel #include <sys/cpuvar.h> 351708Sstevel #include <sys/promif.h> 361708Sstevel #include <sys/sgsbbc_iosram.h> 371708Sstevel #include <sys/todsg.h> 381708Sstevel #include <sys/cmn_err.h> 391708Sstevel #include <sys/time.h> 401708Sstevel #include <sys/sysmacros.h> 411708Sstevel #include <sys/clock.h> 421708Sstevel 431708Sstevel #if defined(DEBUG) || defined(lint) 441708Sstevel static int todsg_debug = 0; 451708Sstevel #define DCMNERR if (todsg_debug) cmn_err 461708Sstevel #else 471708Sstevel #define DCMNERR 481708Sstevel #endif /* DEBUG */ 491708Sstevel 501708Sstevel #define OFFSET(base, field) ((char *)&base.field - (char *)&base) 511708Sstevel #define SC_DOWN_COUNT_THRESHOLD 2 521708Sstevel #define SC_TOD_MIN_REV 2 531708Sstevel 541708Sstevel static timestruc_t todsg_get(void); 551708Sstevel static void todsg_set(timestruc_t); 561708Sstevel static uint32_t todsg_set_watchdog_timer(uint_t); 571708Sstevel static uint32_t todsg_clear_watchdog_timer(void); 581708Sstevel static void todsg_set_power_alarm(timestruc_t); 591708Sstevel static void todsg_clear_power_alarm(void); 601708Sstevel static uint64_t todsg_get_cpufrequency(void); 611708Sstevel static int update_heartbeat(void); 621708Sstevel static int verify_sc_tod_version(void); 631708Sstevel static int update_tod_skew(time_t skew); 641708Sstevel 651708Sstevel static uint32_t i_am_alive = 0; 661708Sstevel static uint32_t sc_tod_version = 0; 671708Sstevel static time_t skew_adjust = 0; 681708Sstevel static int is_sc_down = 0; 691708Sstevel static int adjust_sc_down = 0; 701708Sstevel 711708Sstevel /* 721708Sstevel * Module linkage information for the kernel. 731708Sstevel */ 741708Sstevel static struct modlmisc modlmisc = { 75*7696SRichard.Bean@Sun.COM &mod_miscops, "Serengeti tod module" 761708Sstevel }; 771708Sstevel 781708Sstevel static struct modlinkage modlinkage = { 791708Sstevel MODREV_1, (void *)&modlmisc, NULL 801708Sstevel }; 811708Sstevel 821708Sstevel int 831708Sstevel _init(void) 841708Sstevel { 851708Sstevel 861708Sstevel DCMNERR(CE_NOTE, "todsg:_init(): begins"); 871708Sstevel 881708Sstevel if (strcmp(tod_module_name, "todsg") == 0) { 891708Sstevel time_t ssc_time = (time_t)0; 901708Sstevel char obp_string[80]; 911708Sstevel 921708Sstevel /* 931708Sstevel * To obtain the initial start of day time, we use an 941708Sstevel * OBP callback; this is because the iosram is not yet 951708Sstevel * accessible from the OS at this early stage of startup. 961708Sstevel */ 971708Sstevel 981708Sstevel /* 991708Sstevel * Set the string to pass to OBP 1001708Sstevel */ 1011708Sstevel (void) sprintf(obp_string, 1021708Sstevel "h# %p \" unix-get-tod\" $find if execute else " 1031708Sstevel "3drop then", 1041708Sstevel (void *)&ssc_time); 1051708Sstevel 1061708Sstevel prom_interpret(obp_string, 0, 0, 0, 0, 0); 1071708Sstevel 1081708Sstevel if (ssc_time == (time_t)0) { 1091708Sstevel cmn_err(CE_WARN, "Initial date is invalid. " 1101708Sstevel "This can be caused by older firmware."); 1111708Sstevel cmn_err(CE_CONT, "Please flashupdate the System " 1121708Sstevel "Controller firmware to the latest version.\n"); 1131708Sstevel cmn_err(CE_CONT, "Attempting to set the date and time " 1141708Sstevel "based on the last shutdown.\n"); 1151708Sstevel cmn_err(CE_CONT, "Please inspect the date and time and " 1161708Sstevel "correct if necessary.\n"); 1171708Sstevel } 1181708Sstevel 1191708Sstevel hrestime.tv_sec = ssc_time; 1201708Sstevel 1211708Sstevel DCMNERR(CE_NOTE, "todsg: _init(): time from OBP 0x%lX", 1221708Sstevel ssc_time); 1231708Sstevel /* 1241708Sstevel * Verify whether the received date/clock has overflowed 1251708Sstevel * an integer(32bit), so that we capture any corrupted 1261708Sstevel * date from SC, thereby preventing boot failure. 1271708Sstevel */ 1281708Sstevel if (TIMESPEC_OVERFLOW(&hrestime)) { 1291708Sstevel cmn_err(CE_WARN, "Date overflow detected."); 1301708Sstevel cmn_err(CE_CONT, "Attempting to set the date and time " 1311708Sstevel "based on the last shutdown.\n"); 1321708Sstevel cmn_err(CE_CONT, "Please inspect the date and time and " 1331708Sstevel "correct if necessary.\n"); 1341708Sstevel 1351708Sstevel /* 1361708Sstevel * By setting hrestime.tv_sec to zero 1371708Sstevel * we force the vfs_mountroot() to set 1381708Sstevel * the date from the last shutdown. 1391708Sstevel */ 1401708Sstevel hrestime.tv_sec = (time_t)0; 1411708Sstevel /* 1421708Sstevel * Save the skew so that we can update 1431708Sstevel * IOSRAM when it becomes accessible. 1441708Sstevel */ 1451708Sstevel skew_adjust = -ssc_time; 1461708Sstevel } 1471708Sstevel 1481708Sstevel DCMNERR(CE_NOTE, "todsg:_init(): set tod_ops"); 1491708Sstevel 1501708Sstevel tod_ops.tod_get = todsg_get; 1511708Sstevel tod_ops.tod_set = todsg_set; 1521708Sstevel tod_ops.tod_set_watchdog_timer = todsg_set_watchdog_timer; 1531708Sstevel tod_ops.tod_clear_watchdog_timer = todsg_clear_watchdog_timer; 1541708Sstevel tod_ops.tod_set_power_alarm = todsg_set_power_alarm; 1551708Sstevel tod_ops.tod_clear_power_alarm = todsg_clear_power_alarm; 1561708Sstevel tod_ops.tod_get_cpufrequency = todsg_get_cpufrequency; 1571708Sstevel } 1581708Sstevel 1591708Sstevel return (mod_install(&modlinkage)); 1601708Sstevel 1611708Sstevel } 1621708Sstevel 1631708Sstevel int 1641708Sstevel _fini(void) 1651708Sstevel { 1661708Sstevel if (strcmp(tod_module_name, "todsg") == 0) 1671708Sstevel return (EBUSY); 1681708Sstevel else 1691708Sstevel return (mod_remove(&modlinkage)); 1701708Sstevel } 1711708Sstevel 1721708Sstevel int 1731708Sstevel _info(struct modinfo *modinfop) 1741708Sstevel { 1751708Sstevel return (mod_info(&modlinkage, modinfop)); 1761708Sstevel } 1771708Sstevel 1781708Sstevel static int 1791708Sstevel update_heartbeat(void) 1801708Sstevel { 1811708Sstevel tod_iosram_t tod_buf; 1821708Sstevel int complained = 0; 1831708Sstevel 1841708Sstevel /* Update the heartbeat */ 1851708Sstevel if (i_am_alive == UINT32_MAX) 1861708Sstevel i_am_alive = 0; 1871708Sstevel else 1881708Sstevel i_am_alive++; 1891708Sstevel if (iosram_write(SBBC_TOD_KEY, OFFSET(tod_buf, tod_i_am_alive), 1901708Sstevel (char *)&i_am_alive, sizeof (uint32_t))) { 1911708Sstevel complained++; 1921708Sstevel cmn_err(CE_WARN, "update_heartbeat(): write heartbeat failed"); 1931708Sstevel } 1941708Sstevel return (complained); 1951708Sstevel } 1961708Sstevel 1971708Sstevel static int 1981708Sstevel verify_sc_tod_version(void) 1991708Sstevel { 2001708Sstevel uint32_t magic; 2011708Sstevel tod_iosram_t tod_buf; 2021708Sstevel 2031708Sstevel if (!todsg_use_sc) 2041708Sstevel return (FALSE); 2051708Sstevel /* 2061708Sstevel * read tod_version only when the first time and 2071708Sstevel * when there has been a previous sc down time 2081708Sstevel */ 2091708Sstevel if (!sc_tod_version || is_sc_down >= SC_DOWN_COUNT_THRESHOLD) { 2101708Sstevel if (iosram_read(SBBC_TOD_KEY, OFFSET(tod_buf, tod_magic), 2111708Sstevel (char *)&magic, sizeof (uint32_t)) || 2121708Sstevel magic != TODSG_MAGIC) { 2131708Sstevel cmn_err(CE_WARN, "get_sc_tod_version(): " 2141708Sstevel "TOD SRAM magic error"); 2151708Sstevel return (FALSE); 2161708Sstevel } 2171708Sstevel if (iosram_read(SBBC_TOD_KEY, OFFSET(tod_buf, tod_version), 2181708Sstevel (char *)&sc_tod_version, sizeof (uint32_t))) { 2191708Sstevel cmn_err(CE_WARN, "get_sc_tod_version(): " 2201708Sstevel "read tod version failed"); 2211708Sstevel sc_tod_version = 0; 2221708Sstevel return (FALSE); 2231708Sstevel } 2241708Sstevel } 2251708Sstevel if (sc_tod_version >= SC_TOD_MIN_REV) { 2261708Sstevel return (TRUE); 2271708Sstevel } else { 2281708Sstevel todsg_use_sc = 0; 2291708Sstevel cmn_err(CE_WARN, 2301708Sstevel "todsg_get(): incorrect firmware version, " 2311708Sstevel "(%d): expected version >= %d.", 2321708Sstevel sc_tod_version, SC_TOD_MIN_REV); 2331708Sstevel } 2341708Sstevel return (FALSE); 2351708Sstevel } 2361708Sstevel 2371708Sstevel static int 2381708Sstevel update_tod_skew(time_t skew) 2391708Sstevel { 2401708Sstevel time_t domain_skew; 2411708Sstevel tod_iosram_t tod_buf; 2421708Sstevel int complained = 0; 2431708Sstevel 2441708Sstevel DCMNERR(CE_NOTE, "update_tod_skew(): skew 0x%lX", skew); 2451708Sstevel 2461708Sstevel if (iosram_read(SBBC_TOD_KEY, OFFSET(tod_buf, tod_domain_skew), 2471708Sstevel (char *)&domain_skew, sizeof (time_t))) { 2481708Sstevel complained++; 2491708Sstevel cmn_err(CE_WARN, "update_tod_skew(): " 2501708Sstevel "read tod domain skew failed"); 2511708Sstevel } 2521708Sstevel domain_skew += skew; 2531708Sstevel /* we shall update the skew_adjust too now */ 2541708Sstevel domain_skew += skew_adjust; 2551708Sstevel if (!complained && iosram_write(SBBC_TOD_KEY, 2561708Sstevel OFFSET(tod_buf, tod_domain_skew), 2571708Sstevel (char *)&domain_skew, sizeof (time_t))) { 2581708Sstevel complained++; 2591708Sstevel cmn_err(CE_WARN, "update_tod_skew(): " 2601708Sstevel "write domain skew failed"); 2611708Sstevel } 2621708Sstevel if (!complained) 2631708Sstevel skew_adjust = 0; 2641708Sstevel return (complained); 2651708Sstevel } 2661708Sstevel 2671708Sstevel 2681708Sstevel /* 2691708Sstevel * Return time value read from IOSRAM. 2701708Sstevel * Must be called with tod_lock held. 2711708Sstevel */ 2721708Sstevel static timestruc_t 2731708Sstevel todsg_get(void) 2741708Sstevel { 2751708Sstevel tod_iosram_t tod_buf; 2761708Sstevel time_t seconds; 2771708Sstevel time_t domain_skew; 2781708Sstevel int complained = 0; 2791708Sstevel static time_t pre_seconds = (time_t)0; 2801708Sstevel 2811708Sstevel ASSERT(MUTEX_HELD(&tod_lock)); 2821708Sstevel 2831708Sstevel if (!verify_sc_tod_version()) { 2841708Sstevel /* if we can't use SC */ 2851708Sstevel goto return_hrestime; 2861708Sstevel } 2871708Sstevel if (watchdog_activated != 0 || watchdog_enable != 0) 2881708Sstevel complained = update_heartbeat(); 2891708Sstevel if (!complained && (iosram_read(SBBC_TOD_KEY, 2901708Sstevel OFFSET(tod_buf, tod_get_value), 2911708Sstevel (char *)&seconds, sizeof (time_t)))) { 2921708Sstevel complained++; 2931708Sstevel cmn_err(CE_WARN, "todsg_get(): read 64-bit tod value failed"); 2941708Sstevel } 2951708Sstevel if (!complained && skew_adjust) { 2961708Sstevel /* 2971708Sstevel * This is our first chance to update IOSRAM 2981708Sstevel * with local copy of the skew, so update it. 2991708Sstevel */ 3001708Sstevel complained = update_tod_skew(0); 3011708Sstevel } 3021708Sstevel if (!complained && iosram_read(SBBC_TOD_KEY, 3031708Sstevel OFFSET(tod_buf, tod_domain_skew), 3041708Sstevel (char *)&domain_skew, sizeof (time_t))) { 3051708Sstevel complained++; 3061708Sstevel cmn_err(CE_WARN, "todsg_get(): read tod domain skew failed"); 3071708Sstevel } 3081708Sstevel 3091708Sstevel if (complained) { 3101708Sstevel cmn_err(CE_WARN, "todsg_get(): turned off using tod"); 3111708Sstevel todsg_use_sc = 0; 3121708Sstevel goto return_hrestime; 3131708Sstevel } 3141708Sstevel 3151708Sstevel /* 3161708Sstevel * If the SC gets rebooted, and we are using NTP, then we need 3171708Sstevel * to sync the IOSRAM to hrestime when the SC comes back. We 3181708Sstevel * can determine that either NTP slew (or date -a) was called if 3191708Sstevel * the global timedelta was non-zero at any point while the SC 3201708Sstevel * was away. If timedelta remains zero throughout, then the 3211708Sstevel * default action will be to sync hrestime to IOSRAM 3221708Sstevel */ 3231708Sstevel if (seconds != pre_seconds) { /* SC still alive */ 3241708Sstevel pre_seconds = seconds; 3251708Sstevel if (is_sc_down >= SC_DOWN_COUNT_THRESHOLD && adjust_sc_down) { 3261708Sstevel skew_adjust = hrestime.tv_sec - (seconds + domain_skew); 3271708Sstevel complained = update_tod_skew(0); 3281708Sstevel if (!complained && (iosram_read(SBBC_TOD_KEY, 3291708Sstevel OFFSET(tod_buf, tod_domain_skew), 3301708Sstevel (char *)&domain_skew, sizeof (time_t)))) { 3311708Sstevel complained++; 3321708Sstevel cmn_err(CE_WARN, "todsg_get(): " 3331708Sstevel "read tod domain skew failed"); 3341708Sstevel } 3351708Sstevel } 3361708Sstevel is_sc_down = 0; 3371708Sstevel adjust_sc_down = 0; 3381708Sstevel 3391708Sstevel /* 3401708Sstevel * If complained then domain_skew is invalid. 3411708Sstevel * Hand back hrestime instead. 3421708Sstevel */ 3431708Sstevel if (!complained) { 3441708Sstevel timestruc_t ts = {0, 0}; 3451708Sstevel ts.tv_sec = seconds + domain_skew; 3461708Sstevel return (ts); 3471708Sstevel } else { 3481708Sstevel goto return_hrestime; 3491708Sstevel } 3501708Sstevel } 3511708Sstevel 3521708Sstevel /* SC/TOD is down */ 3531708Sstevel is_sc_down++; 3541708Sstevel if (timedelta != 0) { 3551708Sstevel adjust_sc_down = 1; 3561708Sstevel } 3571708Sstevel 3581708Sstevel return_hrestime: 3591708Sstevel /* 3601708Sstevel * We need to inform the tod_validate code to stop checking till 3611708Sstevel * SC come back up again. Note that we will return hrestime below 3621708Sstevel * which can be different that the previous TOD value we returned 3631708Sstevel */ 3641708Sstevel tod_fault_reset(); 3651708Sstevel return (hrestime); 3661708Sstevel } 3671708Sstevel 3681708Sstevel static void 3691708Sstevel todsg_set(timestruc_t ts) 3701708Sstevel { 3711708Sstevel int complained = 0; 3721708Sstevel tod_iosram_t tod_buf; 3731708Sstevel time_t domain_skew; 3741708Sstevel time_t seconds; 3751708Sstevel time_t hwtod; 3761708Sstevel 3771708Sstevel ASSERT(MUTEX_HELD(&tod_lock)); 3781708Sstevel 3791708Sstevel if (!verify_sc_tod_version()) { 3801708Sstevel /* if we can't use SC */ 3811708Sstevel return; 3821708Sstevel } 3831708Sstevel /* 3841708Sstevel * If the SC is down just note the fact that we should 3851708Sstevel * have adjusted the hardware skew which caters for calls 3861708Sstevel * to stime(). (eg NTP step, as opposed to NTP skew) 3871708Sstevel */ 3881708Sstevel if (is_sc_down) { 3891708Sstevel adjust_sc_down = 1; 3901708Sstevel return; 3911708Sstevel } 3921708Sstevel /* 3931708Sstevel * reason to update i_am_alive here: 3941708Sstevel * To work around a generic Solaris bug that can 3951708Sstevel * cause tod_get() to be starved by too frequent 3961708Sstevel * calls to the stime() system call. 3971708Sstevel */ 3981708Sstevel if (watchdog_activated != 0 || watchdog_enable != 0) 3991708Sstevel complained = update_heartbeat(); 4001708Sstevel 4011708Sstevel /* 4021708Sstevel * We are passed hrestime from clock.c so we need to read the 4031708Sstevel * IOSRAM for the hardware's idea of the time to see if we need 4041708Sstevel * to update the skew. 4051708Sstevel */ 4061708Sstevel if (!complained && (iosram_read(SBBC_TOD_KEY, 4071708Sstevel OFFSET(tod_buf, tod_get_value), 4081708Sstevel (char *)&seconds, sizeof (time_t)))) { 4091708Sstevel complained++; 4101708Sstevel cmn_err(CE_WARN, "todsg_set(): read 64-bit tod value failed"); 4111708Sstevel } 4121708Sstevel 4131708Sstevel if (!complained && iosram_read(SBBC_TOD_KEY, 4141708Sstevel OFFSET(tod_buf, tod_domain_skew), 4151708Sstevel (char *)&domain_skew, sizeof (time_t))) { 4161708Sstevel complained++; 4171708Sstevel cmn_err(CE_WARN, "todsg_set(): read tod domain skew failed"); 4181708Sstevel } 4191708Sstevel 4201708Sstevel /* 4211708Sstevel * Only update the skew if the time passed differs from 4221708Sstevel * what the hardware thinks & no errors talking to SC 4231708Sstevel */ 4241708Sstevel if (!complained && (ts.tv_sec != (seconds + domain_skew))) { 4251708Sstevel hwtod = seconds + domain_skew; 4261708Sstevel complained = update_tod_skew(ts.tv_sec - hwtod); 4271708Sstevel 4281708Sstevel DCMNERR(CE_NOTE, "todsg_set(): set time %lX (%lX)%s", 4291708Sstevel ts.tv_sec, hwtod, complained ? " failed" : ""); 4301708Sstevel 4311708Sstevel } 4321708Sstevel 4331708Sstevel if (complained) { 4341708Sstevel cmn_err(CE_WARN, "todsg_set(): turned off using tod"); 4351708Sstevel todsg_use_sc = 0; 4361708Sstevel } 4371708Sstevel } 4381708Sstevel 4391708Sstevel static uint32_t 4401708Sstevel todsg_set_watchdog_timer(uint32_t timeoutval) 4411708Sstevel { 4421708Sstevel tod_iosram_t tod_buf; 4431708Sstevel 4441708Sstevel ASSERT(MUTEX_HELD(&tod_lock)); 4451708Sstevel 4461708Sstevel if (!verify_sc_tod_version()) { 4471708Sstevel DCMNERR(CE_NOTE, "todsg_set_watchdog_timer(): " 4481708Sstevel "verify_sc_tod_version failed"); 4491708Sstevel return (0); 4501708Sstevel } 4511708Sstevel DCMNERR(CE_NOTE, "todsg_set_watchdog_timer(): " 4521708Sstevel "set watchdog timer value = %d", timeoutval); 4531708Sstevel 4541708Sstevel if (iosram_write(SBBC_TOD_KEY, OFFSET(tod_buf, tod_timeout_period), 4551708Sstevel (char *)&timeoutval, sizeof (uint32_t))) { 4561708Sstevel DCMNERR(CE_NOTE, "todsg_set_watchdog_timer(): " 4571708Sstevel "write new timeout value failed"); 4581708Sstevel return (0); 4591708Sstevel } 4601708Sstevel watchdog_activated = 1; 4611708Sstevel return (timeoutval); 4621708Sstevel } 4631708Sstevel 4641708Sstevel static uint32_t 4651708Sstevel todsg_clear_watchdog_timer(void) 4661708Sstevel { 4671708Sstevel tod_iosram_t tod_buf; 4681708Sstevel uint32_t r_timeout_period; 4691708Sstevel uint32_t w_timeout_period; 4701708Sstevel 4711708Sstevel ASSERT(MUTEX_HELD(&tod_lock)); 4721708Sstevel 4731708Sstevel if ((watchdog_activated == 0) || !verify_sc_tod_version()) { 4741708Sstevel DCMNERR(CE_NOTE, "todsg_set_watchdog_timer(): " 4751708Sstevel "either watchdog not activated or " 4761708Sstevel "verify_sc_tod_version failed"); 4771708Sstevel return (0); 4781708Sstevel } 4791708Sstevel if (iosram_read(SBBC_TOD_KEY, OFFSET(tod_buf, tod_timeout_period), 4801708Sstevel (char *)&r_timeout_period, sizeof (uint32_t))) { 4811708Sstevel DCMNERR(CE_NOTE, "todsg_clear_watchdog_timer(): " 4821708Sstevel "read timeout value failed"); 4831708Sstevel return (0); 4841708Sstevel } 4851708Sstevel DCMNERR(CE_NOTE, "todsg_clear_watchdog_timer(): " 4861708Sstevel "clear watchdog timer (old value=%d)", r_timeout_period); 4871708Sstevel w_timeout_period = 0; 4881708Sstevel if (iosram_write(SBBC_TOD_KEY, OFFSET(tod_buf, tod_timeout_period), 4891708Sstevel (char *)&w_timeout_period, sizeof (uint32_t))) { 4901708Sstevel DCMNERR(CE_NOTE, "todsg_clear_watchdog_timer(): " 4911708Sstevel "write zero timeout value failed"); 4921708Sstevel return (0); 4931708Sstevel } 4941708Sstevel watchdog_activated = 0; 4951708Sstevel return (r_timeout_period); 4961708Sstevel } 4971708Sstevel 4981708Sstevel /* 4991708Sstevel * Null function. 5001708Sstevel */ 5011708Sstevel /* ARGSUSED */ 5021708Sstevel static void 5031708Sstevel todsg_set_power_alarm(timestruc_t ts) 5041708Sstevel { 5051708Sstevel ASSERT(MUTEX_HELD(&tod_lock)); 5061708Sstevel } 5071708Sstevel 5081708Sstevel /* 5091708Sstevel * Null function 5101708Sstevel */ 5111708Sstevel static void 5121708Sstevel todsg_clear_power_alarm() 5131708Sstevel { 5141708Sstevel ASSERT(MUTEX_HELD(&tod_lock)); 5151708Sstevel } 5161708Sstevel 5171708Sstevel /* 5181708Sstevel * Get clock freq from the cpunode 5191708Sstevel */ 5201708Sstevel uint64_t 5211708Sstevel todsg_get_cpufrequency(void) 5221708Sstevel { 5231708Sstevel 5241708Sstevel DCMNERR(CE_NOTE, "todsg_get_cpufrequency(): frequency=%ldMHz", 5251708Sstevel cpunodes[CPU->cpu_id].clock_freq/1000000); 5261708Sstevel 5271708Sstevel return (cpunodes[CPU->cpu_id].clock_freq); 5281708Sstevel } 529