/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* tod driver module for OPL (implements a soft tod)
*/
#include <sys/sysmacros.h>
#include <sys/autoconf.h>
#include <sys/prom_plat.h>
#include <sys/opl_module.h>
/*
* Debug stuff
*/
#ifdef DEBUG
int todopl_debug = 0;
#else
#endif
#define abs(x) ((x) < 0 ? -(x) : (x))
static timestruc_t todopl_get(void);
static void todopl_set(timestruc_t);
static uint_t todopl_clear_watchdog_timer(void);
static void todopl_set_power_alarm(timestruc_t);
static void todopl_clear_power_alarm(void);
static uint64_t todopl_get_cpufrequency(void);
/*
* Module linkage information for the kernel.
*/
&mod_miscops, "Soft tod module for OPL 1.11"
};
};
/*
* The TOD OPL logic description.
*
* The todopl driver uses promif functions prom_opl_get_tod() and
* prom_opl_set_diff(). These functions call FJSV,get-tod and
* FJSV,set-domain-time OBP client services.
*
* At the system boot or reboot:
*
* FJSV,tod-get
* OS ---------> OBP SCF I/F
* -----------> XSCF
* <-----------
* <-------- time, diff
* time+diff, stick
*
* Note that on first powerup domain boot, diff is zero.
*
* When system updates the time via date(1m):
*
* FJSV,set-domain-time
* OS ---------> OBP SRAM
* diff_delta diff += diff_delta -------------> XSCF
*
* diff_delta = new time - current domain time (hrestime)
*
*
* In theory, FJSV,get-tod and FJSV,set-domain-time should never fails.
* But, if call to FJSV,get-tod fails on boot, the domain will be unable
* to calculate "diff" properly and synchronization between Domain and
* SP will be broken. In this particular case, we notify users that
* "there is no time synchronization" and the logic will attempt to
* resync with the SP whenever the OS tries to do a TOD update.
* (e.g. via date(1m) or NTP).
*/
int
_init(void)
{
/*
* Get TOD time from OBP and adjust it.
*/
if (obp_time != 0) {
/*
* adjust OBP time by stick counts
*/
"todopl: cpu stick 0x%lx sys_time 0x%lx\n",
} else {
/*
* A date of zero causes the root filesystem driver
* to try to set the date from the last shutdown.
*/
enable_time_sync = 0;
"based on the last shutdown.\n");
"between Domain and Service Processor.\n");
"correct if necessary.\n");
}
/*
* Check that the date has not overflowed a 32-bit integer.
*/
if (TIMESPEC_OVERFLOW(&hrestime)) {
"based on the last shutdown.\n");
"correct if necessary.\n");
}
/*
* Flag warning if user tried to use hardware watchdog
*/
if (watchdog_enable) {
}
}
return (mod_install(&modlinkage));
}
int
_fini(void)
{
return (EBUSY);
else
return (mod_remove(&modlinkage));
}
int
{
}
/*
* OPL tod_get is simplified to return hrestime
* Must be called with tod_lock held.
*/
static timestruc_t
todopl_get(void)
{
return (hrestime);
}
/*
* Must be called with tod_lock held.
*
* When running NTP, tod_set is called at least once per second in order
* to update the hardware clock. To minimize pressure on SP, we want only
* to record significant time changes on the SP (when date(1M) is run).
* We have 30 seconds threshold requirement before recording the time change.
*/
/* ARGSUSED */
static void
{
/*
* Send time difference to SP
*/
if (enable_time_sync)
else {
/*
* We did not get a successful initial time
* Try again here.
*/
if (obp_time != 0) {
/*
* adjust OBP time by stick counts
*/
/*
* Sync up by computing the diff using the
*/
enable_time_sync = 1;
}
}
}
}
/*
* No watchdog function.
*/
/* ARGSUSED */
static uint_t
{
return (0);
}
/*
* No watchdog function
*/
static uint_t
{
return (0);
}
/*
* Null function.
*/
/* ARGSUSED */
static void
{
}
/*
* Null function
*/
static void
{
}
/*
* Get clock freq from the cpunode. This function is only called
* when use_stick = 0, otherwise, system_clock_freq gets used instead.
*/
todopl_get_cpufrequency(void)
{
}