11708Sstevel /*
21708Sstevel * CDDL HEADER START
31708Sstevel *
41708Sstevel * The contents of this file are subject to the terms of the
57696SRichard.Bean@Sun.COM * Common Development and Distribution License (the "License").
67696SRichard.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*11752STrevor.Thompson@Sun.COM * Copyright 2010 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 = {
757696SRichard.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
_init(void)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,
102*11752STrevor.Thompson@Sun.COM "h# %p \" unix-get-tod\" $find if execute else 3drop then",
103*11752STrevor.Thompson@Sun.COM (void *)&ssc_time);
1041708Sstevel
1051708Sstevel prom_interpret(obp_string, 0, 0, 0, 0, 0);
1061708Sstevel
1071708Sstevel if (ssc_time == (time_t)0) {
1081708Sstevel cmn_err(CE_WARN, "Initial date is invalid. "
109*11752STrevor.Thompson@Sun.COM "This can be caused by older firmware.");
1101708Sstevel cmn_err(CE_CONT, "Please flashupdate the System "
111*11752STrevor.Thompson@Sun.COM "Controller firmware to the latest version.\n");
1121708Sstevel cmn_err(CE_CONT, "Attempting to set the date and time "
113*11752STrevor.Thompson@Sun.COM "based on the last shutdown.\n");
1141708Sstevel cmn_err(CE_CONT, "Please inspect the date and time and "
115*11752STrevor.Thompson@Sun.COM "correct if necessary.\n");
1161708Sstevel }
1171708Sstevel
1181708Sstevel hrestime.tv_sec = ssc_time;
1191708Sstevel
1201708Sstevel DCMNERR(CE_NOTE, "todsg: _init(): time from OBP 0x%lX",
121*11752STrevor.Thompson@Sun.COM ssc_time);
1221708Sstevel /*
1231708Sstevel * Verify whether the received date/clock has overflowed
1241708Sstevel * an integer(32bit), so that we capture any corrupted
1251708Sstevel * date from SC, thereby preventing boot failure.
1261708Sstevel */
1271708Sstevel if (TIMESPEC_OVERFLOW(&hrestime)) {
1281708Sstevel cmn_err(CE_WARN, "Date overflow detected.");
1291708Sstevel cmn_err(CE_CONT, "Attempting to set the date and time "
130*11752STrevor.Thompson@Sun.COM "based on the last shutdown.\n");
1311708Sstevel cmn_err(CE_CONT, "Please inspect the date and time and "
132*11752STrevor.Thompson@Sun.COM "correct if necessary.\n");
1331708Sstevel
1341708Sstevel /*
1351708Sstevel * By setting hrestime.tv_sec to zero
1361708Sstevel * we force the vfs_mountroot() to set
1371708Sstevel * the date from the last shutdown.
1381708Sstevel */
1391708Sstevel hrestime.tv_sec = (time_t)0;
1401708Sstevel /*
1411708Sstevel * Save the skew so that we can update
1421708Sstevel * IOSRAM when it becomes accessible.
1431708Sstevel */
1441708Sstevel skew_adjust = -ssc_time;
1451708Sstevel }
1461708Sstevel
1471708Sstevel DCMNERR(CE_NOTE, "todsg:_init(): set tod_ops");
1481708Sstevel
1491708Sstevel tod_ops.tod_get = todsg_get;
1501708Sstevel tod_ops.tod_set = todsg_set;
1511708Sstevel tod_ops.tod_set_watchdog_timer = todsg_set_watchdog_timer;
1521708Sstevel tod_ops.tod_clear_watchdog_timer = todsg_clear_watchdog_timer;
1531708Sstevel tod_ops.tod_set_power_alarm = todsg_set_power_alarm;
1541708Sstevel tod_ops.tod_clear_power_alarm = todsg_clear_power_alarm;
1551708Sstevel tod_ops.tod_get_cpufrequency = todsg_get_cpufrequency;
1561708Sstevel }
1571708Sstevel
1581708Sstevel return (mod_install(&modlinkage));
1591708Sstevel
1601708Sstevel }
1611708Sstevel
1621708Sstevel int
_fini(void)1631708Sstevel _fini(void)
1641708Sstevel {
1651708Sstevel if (strcmp(tod_module_name, "todsg") == 0)
1661708Sstevel return (EBUSY);
1671708Sstevel else
1681708Sstevel return (mod_remove(&modlinkage));
1691708Sstevel }
1701708Sstevel
1711708Sstevel int
_info(struct modinfo * modinfop)1721708Sstevel _info(struct modinfo *modinfop)
1731708Sstevel {
1741708Sstevel return (mod_info(&modlinkage, modinfop));
1751708Sstevel }
1761708Sstevel
1771708Sstevel static int
update_heartbeat(void)1781708Sstevel update_heartbeat(void)
1791708Sstevel {
1801708Sstevel tod_iosram_t tod_buf;
1811708Sstevel int complained = 0;
1821708Sstevel
1831708Sstevel /* Update the heartbeat */
1841708Sstevel if (i_am_alive == UINT32_MAX)
1851708Sstevel i_am_alive = 0;
1861708Sstevel else
1871708Sstevel i_am_alive++;
1881708Sstevel if (iosram_write(SBBC_TOD_KEY, OFFSET(tod_buf, tod_i_am_alive),
189*11752STrevor.Thompson@Sun.COM (char *)&i_am_alive, sizeof (uint32_t))) {
1901708Sstevel complained++;
1911708Sstevel cmn_err(CE_WARN, "update_heartbeat(): write heartbeat failed");
1921708Sstevel }
1931708Sstevel return (complained);
1941708Sstevel }
1951708Sstevel
1961708Sstevel static int
verify_sc_tod_version(void)1971708Sstevel verify_sc_tod_version(void)
1981708Sstevel {
1991708Sstevel uint32_t magic;
2001708Sstevel tod_iosram_t tod_buf;
2011708Sstevel
2021708Sstevel if (!todsg_use_sc)
2031708Sstevel return (FALSE);
2041708Sstevel /*
2051708Sstevel * read tod_version only when the first time and
2061708Sstevel * when there has been a previous sc down time
2071708Sstevel */
2081708Sstevel if (!sc_tod_version || is_sc_down >= SC_DOWN_COUNT_THRESHOLD) {
2091708Sstevel if (iosram_read(SBBC_TOD_KEY, OFFSET(tod_buf, tod_magic),
210*11752STrevor.Thompson@Sun.COM (char *)&magic, sizeof (uint32_t)) ||
211*11752STrevor.Thompson@Sun.COM magic != TODSG_MAGIC) {
2121708Sstevel cmn_err(CE_WARN, "get_sc_tod_version(): "
213*11752STrevor.Thompson@Sun.COM "TOD SRAM magic error");
2141708Sstevel return (FALSE);
2151708Sstevel }
2161708Sstevel if (iosram_read(SBBC_TOD_KEY, OFFSET(tod_buf, tod_version),
217*11752STrevor.Thompson@Sun.COM (char *)&sc_tod_version, sizeof (uint32_t))) {
2181708Sstevel cmn_err(CE_WARN, "get_sc_tod_version(): "
219*11752STrevor.Thompson@Sun.COM "read tod version failed");
2201708Sstevel sc_tod_version = 0;
2211708Sstevel return (FALSE);
2221708Sstevel }
2231708Sstevel }
2241708Sstevel if (sc_tod_version >= SC_TOD_MIN_REV) {
2251708Sstevel return (TRUE);
2261708Sstevel } else {
2271708Sstevel todsg_use_sc = 0;
228*11752STrevor.Thompson@Sun.COM cmn_err(CE_WARN, "todsg_get(): incorrect firmware version, "
229*11752STrevor.Thompson@Sun.COM "(%d): expected version >= %d.", sc_tod_version,
230*11752STrevor.Thompson@Sun.COM SC_TOD_MIN_REV);
2311708Sstevel }
2321708Sstevel return (FALSE);
2331708Sstevel }
2341708Sstevel
2351708Sstevel static int
update_tod_skew(time_t skew)2361708Sstevel update_tod_skew(time_t skew)
2371708Sstevel {
2381708Sstevel time_t domain_skew;
2391708Sstevel tod_iosram_t tod_buf;
2401708Sstevel int complained = 0;
2411708Sstevel
2421708Sstevel DCMNERR(CE_NOTE, "update_tod_skew(): skew 0x%lX", skew);
2431708Sstevel
2441708Sstevel if (iosram_read(SBBC_TOD_KEY, OFFSET(tod_buf, tod_domain_skew),
245*11752STrevor.Thompson@Sun.COM (char *)&domain_skew, sizeof (time_t))) {
2461708Sstevel complained++;
247*11752STrevor.Thompson@Sun.COM cmn_err(CE_WARN,
248*11752STrevor.Thompson@Sun.COM "update_tod_skew(): read tod domain skew failed");
2491708Sstevel }
2501708Sstevel domain_skew += skew;
2511708Sstevel /* we shall update the skew_adjust too now */
2521708Sstevel domain_skew += skew_adjust;
2531708Sstevel if (!complained && iosram_write(SBBC_TOD_KEY,
254*11752STrevor.Thompson@Sun.COM OFFSET(tod_buf, tod_domain_skew), (char *)&domain_skew,
255*11752STrevor.Thompson@Sun.COM sizeof (time_t))) {
2561708Sstevel complained++;
257*11752STrevor.Thompson@Sun.COM cmn_err(CE_WARN,
258*11752STrevor.Thompson@Sun.COM "update_tod_skew(): write domain skew failed");
2591708Sstevel }
2601708Sstevel if (!complained)
2611708Sstevel skew_adjust = 0;
2621708Sstevel return (complained);
2631708Sstevel }
2641708Sstevel
2651708Sstevel /*
2661708Sstevel * Return time value read from IOSRAM.
2671708Sstevel * Must be called with tod_lock held.
2681708Sstevel */
2691708Sstevel static timestruc_t
todsg_get(void)2701708Sstevel todsg_get(void)
2711708Sstevel {
2721708Sstevel tod_iosram_t tod_buf;
2731708Sstevel time_t seconds;
2741708Sstevel time_t domain_skew;
2751708Sstevel int complained = 0;
2761708Sstevel static time_t pre_seconds = (time_t)0;
2771708Sstevel
2781708Sstevel ASSERT(MUTEX_HELD(&tod_lock));
2791708Sstevel
2801708Sstevel if (!verify_sc_tod_version()) {
2811708Sstevel /* if we can't use SC */
2821708Sstevel goto return_hrestime;
2831708Sstevel }
2841708Sstevel if (watchdog_activated != 0 || watchdog_enable != 0)
2851708Sstevel complained = update_heartbeat();
2861708Sstevel if (!complained && (iosram_read(SBBC_TOD_KEY,
287*11752STrevor.Thompson@Sun.COM OFFSET(tod_buf, tod_get_value), (char *)&seconds,
288*11752STrevor.Thompson@Sun.COM sizeof (time_t)))) {
2891708Sstevel complained++;
2901708Sstevel cmn_err(CE_WARN, "todsg_get(): read 64-bit tod value failed");
2911708Sstevel }
2921708Sstevel if (!complained && skew_adjust) {
2931708Sstevel /*
2941708Sstevel * This is our first chance to update IOSRAM
2951708Sstevel * with local copy of the skew, so update it.
2961708Sstevel */
2971708Sstevel complained = update_tod_skew(0);
2981708Sstevel }
2991708Sstevel if (!complained && iosram_read(SBBC_TOD_KEY,
300*11752STrevor.Thompson@Sun.COM OFFSET(tod_buf, tod_domain_skew), (char *)&domain_skew,
301*11752STrevor.Thompson@Sun.COM sizeof (time_t))) {
3021708Sstevel complained++;
3031708Sstevel cmn_err(CE_WARN, "todsg_get(): read tod domain skew failed");
3041708Sstevel }
3051708Sstevel
3061708Sstevel if (complained) {
3071708Sstevel cmn_err(CE_WARN, "todsg_get(): turned off using tod");
3081708Sstevel todsg_use_sc = 0;
3091708Sstevel goto return_hrestime;
3101708Sstevel }
3111708Sstevel
3121708Sstevel /*
3131708Sstevel * If the SC gets rebooted, and we are using NTP, then we need
3141708Sstevel * to sync the IOSRAM to hrestime when the SC comes back. We
3151708Sstevel * can determine that either NTP slew (or date -a) was called if
3161708Sstevel * the global timedelta was non-zero at any point while the SC
3171708Sstevel * was away. If timedelta remains zero throughout, then the
3181708Sstevel * default action will be to sync hrestime to IOSRAM
3191708Sstevel */
3201708Sstevel if (seconds != pre_seconds) { /* SC still alive */
3211708Sstevel pre_seconds = seconds;
3221708Sstevel if (is_sc_down >= SC_DOWN_COUNT_THRESHOLD && adjust_sc_down) {
3231708Sstevel skew_adjust = hrestime.tv_sec - (seconds + domain_skew);
3241708Sstevel complained = update_tod_skew(0);
3251708Sstevel if (!complained && (iosram_read(SBBC_TOD_KEY,
326*11752STrevor.Thompson@Sun.COM OFFSET(tod_buf, tod_domain_skew),
327*11752STrevor.Thompson@Sun.COM (char *)&domain_skew, sizeof (time_t)))) {
3281708Sstevel complained++;
3291708Sstevel cmn_err(CE_WARN, "todsg_get(): "
330*11752STrevor.Thompson@Sun.COM "read tod domain skew failed");
3311708Sstevel }
3321708Sstevel }
3331708Sstevel is_sc_down = 0;
3341708Sstevel adjust_sc_down = 0;
3351708Sstevel
3361708Sstevel /*
3371708Sstevel * If complained then domain_skew is invalid.
3381708Sstevel * Hand back hrestime instead.
3391708Sstevel */
3401708Sstevel if (!complained) {
341*11752STrevor.Thompson@Sun.COM /*
342*11752STrevor.Thompson@Sun.COM * The read was successful so ensure the failure
343*11752STrevor.Thompson@Sun.COM * flag is clear.
344*11752STrevor.Thompson@Sun.COM */
345*11752STrevor.Thompson@Sun.COM tod_status_clear(TOD_GET_FAILED);
3461708Sstevel timestruc_t ts = {0, 0};
3471708Sstevel ts.tv_sec = seconds + domain_skew;
3481708Sstevel return (ts);
3491708Sstevel } else {
3501708Sstevel goto return_hrestime;
3511708Sstevel }
3521708Sstevel }
3531708Sstevel
3541708Sstevel /* SC/TOD is down */
3551708Sstevel is_sc_down++;
3561708Sstevel if (timedelta != 0) {
3571708Sstevel adjust_sc_down = 1;
3581708Sstevel }
3591708Sstevel
3601708Sstevel return_hrestime:
3611708Sstevel /*
362*11752STrevor.Thompson@Sun.COM * We need to inform the tod_validate() code to stop checking until
363*11752STrevor.Thompson@Sun.COM * the SC comes back up again. Note we will return hrestime below
364*11752STrevor.Thompson@Sun.COM * which may be different to the previous TOD value we returned.
3651708Sstevel */
366*11752STrevor.Thompson@Sun.COM tod_status_set(TOD_GET_FAILED);
3671708Sstevel return (hrestime);
3681708Sstevel }
3691708Sstevel
3701708Sstevel static void
todsg_set(timestruc_t ts)3711708Sstevel todsg_set(timestruc_t ts)
3721708Sstevel {
3731708Sstevel int complained = 0;
3741708Sstevel tod_iosram_t tod_buf;
3751708Sstevel time_t domain_skew;
3761708Sstevel time_t seconds;
3771708Sstevel time_t hwtod;
3781708Sstevel
3791708Sstevel ASSERT(MUTEX_HELD(&tod_lock));
3801708Sstevel
3811708Sstevel if (!verify_sc_tod_version()) {
3821708Sstevel /* if we can't use SC */
3831708Sstevel return;
3841708Sstevel }
3851708Sstevel /*
3861708Sstevel * If the SC is down just note the fact that we should
3871708Sstevel * have adjusted the hardware skew which caters for calls
3881708Sstevel * to stime(). (eg NTP step, as opposed to NTP skew)
3891708Sstevel */
3901708Sstevel if (is_sc_down) {
3911708Sstevel adjust_sc_down = 1;
3921708Sstevel return;
3931708Sstevel }
3941708Sstevel /*
3951708Sstevel * reason to update i_am_alive here:
3961708Sstevel * To work around a generic Solaris bug that can
3971708Sstevel * cause tod_get() to be starved by too frequent
3981708Sstevel * calls to the stime() system call.
3991708Sstevel */
4001708Sstevel if (watchdog_activated != 0 || watchdog_enable != 0)
4011708Sstevel complained = update_heartbeat();
4021708Sstevel
4031708Sstevel /*
4041708Sstevel * We are passed hrestime from clock.c so we need to read the
4051708Sstevel * IOSRAM for the hardware's idea of the time to see if we need
4061708Sstevel * to update the skew.
4071708Sstevel */
4081708Sstevel if (!complained && (iosram_read(SBBC_TOD_KEY,
409*11752STrevor.Thompson@Sun.COM OFFSET(tod_buf, tod_get_value), (char *)&seconds,
410*11752STrevor.Thompson@Sun.COM sizeof (time_t)))) {
4111708Sstevel complained++;
4121708Sstevel cmn_err(CE_WARN, "todsg_set(): read 64-bit tod value failed");
4131708Sstevel }
4141708Sstevel
4151708Sstevel if (!complained && iosram_read(SBBC_TOD_KEY,
416*11752STrevor.Thompson@Sun.COM OFFSET(tod_buf, tod_domain_skew), (char *)&domain_skew,
417*11752STrevor.Thompson@Sun.COM sizeof (time_t))) {
4181708Sstevel complained++;
4191708Sstevel cmn_err(CE_WARN, "todsg_set(): read tod domain skew failed");
4201708Sstevel }
4211708Sstevel
4221708Sstevel /*
4231708Sstevel * Only update the skew if the time passed differs from
4241708Sstevel * what the hardware thinks & no errors talking to SC
4251708Sstevel */
4261708Sstevel if (!complained && (ts.tv_sec != (seconds + domain_skew))) {
4271708Sstevel hwtod = seconds + domain_skew;
4281708Sstevel complained = update_tod_skew(ts.tv_sec - hwtod);
4291708Sstevel
4301708Sstevel DCMNERR(CE_NOTE, "todsg_set(): set time %lX (%lX)%s",
431*11752STrevor.Thompson@Sun.COM ts.tv_sec, hwtod, complained ? " failed" : "");
4321708Sstevel }
4331708Sstevel
4341708Sstevel if (complained) {
4351708Sstevel cmn_err(CE_WARN, "todsg_set(): turned off using tod");
4361708Sstevel todsg_use_sc = 0;
4371708Sstevel }
4381708Sstevel }
4391708Sstevel
4401708Sstevel static uint32_t
todsg_set_watchdog_timer(uint32_t timeoutval)4411708Sstevel todsg_set_watchdog_timer(uint32_t timeoutval)
4421708Sstevel {
4431708Sstevel tod_iosram_t tod_buf;
4441708Sstevel
4451708Sstevel ASSERT(MUTEX_HELD(&tod_lock));
4461708Sstevel
4471708Sstevel if (!verify_sc_tod_version()) {
4481708Sstevel DCMNERR(CE_NOTE, "todsg_set_watchdog_timer(): "
449*11752STrevor.Thompson@Sun.COM "verify_sc_tod_version failed");
4501708Sstevel return (0);
4511708Sstevel }
4521708Sstevel DCMNERR(CE_NOTE, "todsg_set_watchdog_timer(): "
453*11752STrevor.Thompson@Sun.COM "set watchdog timer value = %d", timeoutval);
4541708Sstevel
4551708Sstevel if (iosram_write(SBBC_TOD_KEY, OFFSET(tod_buf, tod_timeout_period),
456*11752STrevor.Thompson@Sun.COM (char *)&timeoutval, sizeof (uint32_t))) {
4571708Sstevel DCMNERR(CE_NOTE, "todsg_set_watchdog_timer(): "
458*11752STrevor.Thompson@Sun.COM "write new timeout value failed");
4591708Sstevel return (0);
4601708Sstevel }
4611708Sstevel watchdog_activated = 1;
4621708Sstevel return (timeoutval);
4631708Sstevel }
4641708Sstevel
4651708Sstevel static uint32_t
todsg_clear_watchdog_timer(void)4661708Sstevel todsg_clear_watchdog_timer(void)
4671708Sstevel {
4681708Sstevel tod_iosram_t tod_buf;
4691708Sstevel uint32_t r_timeout_period;
4701708Sstevel uint32_t w_timeout_period;
4711708Sstevel
4721708Sstevel ASSERT(MUTEX_HELD(&tod_lock));
4731708Sstevel
4741708Sstevel if ((watchdog_activated == 0) || !verify_sc_tod_version()) {
4751708Sstevel DCMNERR(CE_NOTE, "todsg_set_watchdog_timer(): "
476*11752STrevor.Thompson@Sun.COM "either watchdog not activated or "
477*11752STrevor.Thompson@Sun.COM "verify_sc_tod_version failed");
4781708Sstevel return (0);
4791708Sstevel }
4801708Sstevel if (iosram_read(SBBC_TOD_KEY, OFFSET(tod_buf, tod_timeout_period),
481*11752STrevor.Thompson@Sun.COM (char *)&r_timeout_period, sizeof (uint32_t))) {
4821708Sstevel DCMNERR(CE_NOTE, "todsg_clear_watchdog_timer(): "
483*11752STrevor.Thompson@Sun.COM "read timeout value failed");
4841708Sstevel return (0);
4851708Sstevel }
4861708Sstevel DCMNERR(CE_NOTE, "todsg_clear_watchdog_timer(): "
487*11752STrevor.Thompson@Sun.COM "clear watchdog timer (old value=%d)", r_timeout_period);
4881708Sstevel w_timeout_period = 0;
4891708Sstevel if (iosram_write(SBBC_TOD_KEY, OFFSET(tod_buf, tod_timeout_period),
490*11752STrevor.Thompson@Sun.COM (char *)&w_timeout_period, sizeof (uint32_t))) {
4911708Sstevel DCMNERR(CE_NOTE, "todsg_clear_watchdog_timer(): "
492*11752STrevor.Thompson@Sun.COM "write zero timeout value failed");
4931708Sstevel return (0);
4941708Sstevel }
4951708Sstevel watchdog_activated = 0;
4961708Sstevel return (r_timeout_period);
4971708Sstevel }
4981708Sstevel
4991708Sstevel /*
5001708Sstevel * Null function.
5011708Sstevel */
5021708Sstevel /* ARGSUSED */
5031708Sstevel static void
todsg_set_power_alarm(timestruc_t ts)5041708Sstevel todsg_set_power_alarm(timestruc_t ts)
5051708Sstevel {
5061708Sstevel ASSERT(MUTEX_HELD(&tod_lock));
5071708Sstevel }
5081708Sstevel
5091708Sstevel /*
5101708Sstevel * Null function
5111708Sstevel */
5121708Sstevel static void
todsg_clear_power_alarm()5131708Sstevel todsg_clear_power_alarm()
5141708Sstevel {
5151708Sstevel ASSERT(MUTEX_HELD(&tod_lock));
5161708Sstevel }
5171708Sstevel
5181708Sstevel /*
5191708Sstevel * Get clock freq from the cpunode
5201708Sstevel */
5211708Sstevel uint64_t
todsg_get_cpufrequency(void)5221708Sstevel todsg_get_cpufrequency(void)
5231708Sstevel {
5241708Sstevel
5251708Sstevel DCMNERR(CE_NOTE, "todsg_get_cpufrequency(): frequency=%ldMHz",
526*11752STrevor.Thompson@Sun.COM cpunodes[CPU->cpu_id].clock_freq/1000000);
5271708Sstevel
5281708Sstevel return (cpunodes[CPU->cpu_id].clock_freq);
5291708Sstevel }
530