11c42de6dSgd /*
21c42de6dSgd  * CDDL HEADER START
31c42de6dSgd  *
41c42de6dSgd  * The contents of this file are subject to the terms of the
51c42de6dSgd  * Common Development and Distribution License (the "License").
61c42de6dSgd  * You may not use this file except in compliance with the License.
71c42de6dSgd  *
81c42de6dSgd  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91c42de6dSgd  * or http://www.opensolaris.org/os/licensing.
101c42de6dSgd  * See the License for the specific language governing permissions
111c42de6dSgd  * and limitations under the License.
121c42de6dSgd  *
131c42de6dSgd  * When distributing Covered Code, include this CDDL HEADER in each
141c42de6dSgd  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151c42de6dSgd  * If applicable, add the following below this CDDL HEADER, with the
161c42de6dSgd  * fields enclosed by brackets "[]" replaced with your own identifying
171c42de6dSgd  * information: Portions Copyright [yyyy] [name of copyright owner]
181c42de6dSgd  *
191c42de6dSgd  * CDDL HEADER END
201c42de6dSgd  */
211c42de6dSgd /*
22*8fc99e42STrevor Thompson  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
231c42de6dSgd  * Use is subject to license terms.
241c42de6dSgd  */
251c42de6dSgd 
261c42de6dSgd 
271c42de6dSgd /*
281c42de6dSgd  * tod driver module for ALI M5819P part
291c42de6dSgd  */
301c42de6dSgd 
311c42de6dSgd #include <sys/types.h>
321c42de6dSgd #include <sys/conf.h>
331c42de6dSgd #include <sys/kmem.h>
341c42de6dSgd #include <sys/open.h>
351c42de6dSgd #include <sys/ddi.h>
361c42de6dSgd #include <sys/sunddi.h>
371c42de6dSgd 
381c42de6dSgd #include <sys/todm5819p.h>
391c42de6dSgd #include <sys/rmc_comm_dp.h>
401c42de6dSgd #include <sys/rmc_comm_drvintf.h>
411c42de6dSgd #include <sys/modctl.h>
421c42de6dSgd #include <sys/stat.h>
431c42de6dSgd #include <sys/clock.h>
441c42de6dSgd #include <sys/reboot.h>
451c42de6dSgd #include <sys/machsystm.h>
461c42de6dSgd 
471c42de6dSgd static timestruc_t	todm5819p_rmc_get(void);
481c42de6dSgd static void		todm5819p_rmc_set(timestruc_t);
491c42de6dSgd static uint_t		todm5819p_rmc_set_watchdog_timer(uint_t);
501c42de6dSgd static uint_t		todm5819p_rmc_clear_watchdog_timer(void);
511c42de6dSgd static void		todm5819p_rmc_set_power_alarm(timestruc_t);
521c42de6dSgd static void		todm5819p_rmc_clear_power_alarm(void);
531c42de6dSgd static uint64_t		todm5819p_rmc_get_cpufrequency(void);
541c42de6dSgd 
551c42de6dSgd extern uint64_t		find_cpufrequency(volatile uint8_t *);
561c42de6dSgd 
571c42de6dSgd /*
581c42de6dSgd  * External variables
591c42de6dSgd  */
601c42de6dSgd extern int	watchdog_enable;
611c42de6dSgd extern int	watchdog_available;
621c42de6dSgd extern int	boothowto;
631c42de6dSgd 
641c42de6dSgd /*
651c42de6dSgd  * Global variables
661c42de6dSgd  */
671c42de6dSgd int m5819p_debug_flags;
681c42de6dSgd 
691c42de6dSgd /*
701c42de6dSgd  * Module linkage information for the kernel.
711c42de6dSgd  */
721c42de6dSgd static struct modlmisc modlmisc = {
731c42de6dSgd 	&mod_miscops, "tod module for ALI M5819P"
741c42de6dSgd };
751c42de6dSgd 
761c42de6dSgd static struct modlinkage modlinkage = {
771c42de6dSgd 	MODREV_1, (void *)&modlmisc, NULL
781c42de6dSgd };
791c42de6dSgd 
801c42de6dSgd static todinfo_t rtc_to_tod(struct rtc_t *);
811c42de6dSgd static void read_rtc(struct rtc_t *);
821c42de6dSgd static void write_rtc_time(struct rtc_t *);
831c42de6dSgd static void write_rtc_alarm(struct rtc_t *);
841c42de6dSgd 
851c42de6dSgd 
861c42de6dSgd int
_init(void)871c42de6dSgd _init(void)
881c42de6dSgd {
891c42de6dSgd 	if (strcmp(tod_module_name, "todm5819p_rmc") == 0) {
901c42de6dSgd 		M5819P_ADDR_REG = RTC_B;
911c42de6dSgd 		M5819P_DATA_REG = (RTC_DM | RTC_HM);
921c42de6dSgd 
931c42de6dSgd 		tod_ops.tod_get = todm5819p_rmc_get;
941c42de6dSgd 		tod_ops.tod_set = todm5819p_rmc_set;
951c42de6dSgd 
961c42de6dSgd 		tod_ops.tod_set_watchdog_timer =
971c42de6dSgd 		    todm5819p_rmc_set_watchdog_timer;
981c42de6dSgd 		tod_ops.tod_clear_watchdog_timer =
991c42de6dSgd 		    todm5819p_rmc_clear_watchdog_timer;
1001c42de6dSgd 		tod_ops.tod_set_power_alarm = todm5819p_rmc_set_power_alarm;
1011c42de6dSgd 		tod_ops.tod_clear_power_alarm = todm5819p_rmc_clear_power_alarm;
1021c42de6dSgd 		tod_ops.tod_get_cpufrequency = todm5819p_rmc_get_cpufrequency;
1031c42de6dSgd 		if (boothowto & RB_DEBUG) {
1041c42de6dSgd 			cmn_err(CE_WARN, "todm5819p_rmc: kernel debugger "
1051c42de6dSgd 			    "detected: hardware watchdog disabled");
1061c42de6dSgd 		}
1071c42de6dSgd 	}
1081c42de6dSgd 
1091c42de6dSgd 	return (mod_install(&modlinkage));
1101c42de6dSgd }
1111c42de6dSgd 
1121c42de6dSgd int
_fini(void)1131c42de6dSgd _fini(void)
1141c42de6dSgd {
1151c42de6dSgd 	if (strcmp(tod_module_name, "todm5819p_rmc") == 0)
1161c42de6dSgd 		return (EBUSY);
1171c42de6dSgd 
1181c42de6dSgd 	return (mod_remove(&modlinkage));
1191c42de6dSgd }
1201c42de6dSgd 
1211c42de6dSgd /*
1221c42de6dSgd  * The loadable-module _info(9E) entry point
1231c42de6dSgd  */
1241c42de6dSgd int
_info(struct modinfo * modinfop)1251c42de6dSgd _info(struct modinfo *modinfop)
1261c42de6dSgd {
1271c42de6dSgd 	return (mod_info(&modlinkage, modinfop));
1281c42de6dSgd }
1291c42de6dSgd 
1301c42de6dSgd 
1311c42de6dSgd /*
1321c42de6dSgd  * Read the current time from the clock chip and convert to UNIX form.
133*8fc99e42STrevor Thompson  * Assumes that the year in the clock chip is valid.
1341c42de6dSgd  * Must be called with tod_lock held.
1351c42de6dSgd  */
1361c42de6dSgd static timestruc_t
todm5819p_rmc_get(void)1371c42de6dSgd todm5819p_rmc_get(void)
1381c42de6dSgd {
1391c42de6dSgd 	int i;
1401c42de6dSgd 	int s;
1411c42de6dSgd 	timestruc_t ts;
1421c42de6dSgd 	struct rtc_t rtc;
1431c42de6dSgd 
1441c42de6dSgd 	ASSERT(MUTEX_HELD(&tod_lock));
1451c42de6dSgd 
1461c42de6dSgd 	/* set the hw watchdog timer if it's been activated */
1471c42de6dSgd 	if (watchdog_activated) {
1481c42de6dSgd 		int ret = 0;
1491c42de6dSgd 		ret = tod_ops.tod_set_watchdog_timer(0);
1501c42de6dSgd 		/*
1511c42de6dSgd 		 * The empty set_watchdog routine returns a 0. So if a
1521c42de6dSgd 		 * coded routine fails we will look for a -1 for a failure.
1531c42de6dSgd 		 */
1541c42de6dSgd 		if (ret == -1)
1551c42de6dSgd 			cmn_err(CE_WARN, "todm5819p: failed to set hardware "
1563ff9862dSJustin Frank 			    "watchdog timer.");
1571c42de6dSgd 	}
1581c42de6dSgd 
1591c42de6dSgd 	/*
1601c42de6dSgd 	 * Read current time from the tod. If the tod isn't accessible, wait and
1611c42de6dSgd 	 * retry.
1621c42de6dSgd 	 * Run critical in the time critical section to avoid being interrupted
1631c42de6dSgd 	 */
1641c42de6dSgd 	for (i = 0; i < TODM5819_UIP_RETRY_THRESH; i++) {
1651c42de6dSgd 		s = ddi_enter_critical();
1661c42de6dSgd 		M5819P_ADDR_REG = RTC_A;
1671c42de6dSgd 		if (!(M5819P_DATA_REG & RTC_UIP)) {
1681c42de6dSgd 			read_rtc(&rtc);
1691c42de6dSgd 			ddi_exit_critical(s);
1701c42de6dSgd 			break;
1711c42de6dSgd 		}
1721c42de6dSgd 		ddi_exit_critical(s);
1731c42de6dSgd 		drv_usecwait(TODM5819_UIP_WAIT_USEC);
1741c42de6dSgd 	}
1751c42de6dSgd 	if (i == TODM5819_UIP_RETRY_THRESH) {
1761c42de6dSgd 		/*
1771c42de6dSgd 		 * tod is inaccessible: just return current software time
1781c42de6dSgd 		 */
179*8fc99e42STrevor Thompson 		tod_status_set(TOD_GET_FAILED);
1801c42de6dSgd 		return (hrestime);
1811c42de6dSgd 	}
1821c42de6dSgd 
183*8fc99e42STrevor Thompson 	/* read was successful so ensure failure flag is clear */
184*8fc99e42STrevor Thompson 	tod_status_clear(TOD_GET_FAILED);
1853ff9862dSJustin Frank 
1861c42de6dSgd 	ts.tv_sec = tod_to_utc(rtc_to_tod(&rtc));
1871c42de6dSgd 	ts.tv_nsec = 0;
1881c42de6dSgd 	return (ts);
1891c42de6dSgd }
1901c42de6dSgd 
1911c42de6dSgd static todinfo_t
rtc_to_tod(struct rtc_t * rtc)1921c42de6dSgd rtc_to_tod(struct rtc_t *rtc)
1931c42de6dSgd {
1941c42de6dSgd 	todinfo_t tod;
1951c42de6dSgd 
1961c42de6dSgd 	/*
1971c42de6dSgd 	 * tod_year is base 1900 so this code needs to adjust the true year
1981c42de6dSgd 	 * retrieved from the rtc's century and year fields.
1991c42de6dSgd 	 */
2001c42de6dSgd 	tod.tod_year	= rtc->rtc_year + (rtc->rtc_century * 100) - 1900;
2011c42de6dSgd 	tod.tod_month	= rtc->rtc_mon;
2021c42de6dSgd 	tod.tod_day	= rtc->rtc_dom;
2031c42de6dSgd 	tod.tod_dow	= rtc->rtc_dow;
2041c42de6dSgd 	tod.tod_hour	= rtc->rtc_hrs;
2051c42de6dSgd 	tod.tod_min	= rtc->rtc_min;
2061c42de6dSgd 	tod.tod_sec	= rtc->rtc_sec;
2071c42de6dSgd 
2081c42de6dSgd 	return (tod);
2091c42de6dSgd }
2101c42de6dSgd 
2111c42de6dSgd static void
read_rtc(struct rtc_t * rtc)2121c42de6dSgd read_rtc(struct rtc_t *rtc)
2131c42de6dSgd {
2141c42de6dSgd 	M5819P_ADDR_REG = RTC_SEC;
2151c42de6dSgd 	rtc->rtc_sec = M5819P_DATA_REG;
2161c42de6dSgd 	M5819P_ADDR_REG = RTC_ASEC;
2171c42de6dSgd 	rtc->rtc_asec = M5819P_DATA_REG;
2181c42de6dSgd 	M5819P_ADDR_REG = RTC_MIN;
2191c42de6dSgd 	rtc->rtc_min = M5819P_DATA_REG;
2201c42de6dSgd 	M5819P_ADDR_REG = RTC_AMIN;
2211c42de6dSgd 	rtc->rtc_amin = M5819P_DATA_REG;
2221c42de6dSgd 	M5819P_ADDR_REG = RTC_HRS;
2231c42de6dSgd 	rtc->rtc_hrs = M5819P_DATA_REG;
2241c42de6dSgd 	M5819P_ADDR_REG = RTC_AHRS;
2251c42de6dSgd 	rtc->rtc_ahrs = M5819P_DATA_REG;
2261c42de6dSgd 	M5819P_ADDR_REG = RTC_DOW;
2271c42de6dSgd 	rtc->rtc_dow = M5819P_DATA_REG;
2281c42de6dSgd 	M5819P_ADDR_REG = RTC_DOM;
2291c42de6dSgd 	rtc->rtc_dom = M5819P_DATA_REG;
2301c42de6dSgd 	M5819P_ADDR_REG = RTC_MON;
2311c42de6dSgd 	rtc->rtc_mon = M5819P_DATA_REG;
2321c42de6dSgd 	M5819P_ADDR_REG = RTC_YEAR;
2331c42de6dSgd 	rtc->rtc_year = M5819P_DATA_REG;
2341c42de6dSgd 	M5819P_ADDR_REG = RTC_CENTURY;
2351c42de6dSgd 	rtc->rtc_century = M5819P_DATA_REG;
2361c42de6dSgd 
2371c42de6dSgd 	/* Read date alarm */
2381c42de6dSgd 	M5819P_ADDR_REG = RTC_ADOM_REG;
2391c42de6dSgd 	rtc->rtc_adom = (M5819P_DATA_REG) & RTC_ADOM;
2401c42de6dSgd }
2411c42de6dSgd 
2421c42de6dSgd /*
2431c42de6dSgd  * Write the specified time into the clock chip.
2441c42de6dSgd  * Must be called with tod_lock held.
2451c42de6dSgd  */
2461c42de6dSgd static void
todm5819p_rmc_set(timestruc_t ts)2471c42de6dSgd todm5819p_rmc_set(timestruc_t ts)
2481c42de6dSgd {
2491c42de6dSgd 	struct rtc_t	rtc;
2501c42de6dSgd 	todinfo_t tod = utc_to_tod(ts.tv_sec);
2511c42de6dSgd 	int year;
2521c42de6dSgd 	rmc_comm_msg_t request;
2531c42de6dSgd 	dp_set_date_time_t set_time_msg;
2541c42de6dSgd 
2551c42de6dSgd 	ASSERT(MUTEX_HELD(&tod_lock));
2561c42de6dSgd 
2571c42de6dSgd 	/* tod_year is base 1900 so this code needs to adjust */
2581c42de6dSgd 	year = 1900 + tod.tod_year;
2591c42de6dSgd 	rtc.rtc_year	= year % 100;
2601c42de6dSgd 	rtc.rtc_century = year / 100;
2611c42de6dSgd 	rtc.rtc_mon	= (uint8_t)tod.tod_month;
2621c42de6dSgd 	rtc.rtc_dom	= (uint8_t)tod.tod_day;
2631c42de6dSgd 	rtc.rtc_dow	= (uint8_t)tod.tod_dow;
2641c42de6dSgd 	rtc.rtc_hrs	= (uint8_t)tod.tod_hour;
2651c42de6dSgd 	rtc.rtc_min	= (uint8_t)tod.tod_min;
2661c42de6dSgd 	rtc.rtc_sec	= (uint8_t)tod.tod_sec;
2671c42de6dSgd 
2681c42de6dSgd 	write_rtc_time(&rtc);
2691c42de6dSgd 
2701c42de6dSgd 	set_time_msg.year	= year - 1900;
2711c42de6dSgd 	set_time_msg.month	= tod.tod_month - 1;
2721c42de6dSgd 	set_time_msg.day	= tod.tod_day;
2731c42de6dSgd 	set_time_msg.hour	= tod.tod_hour;
2741c42de6dSgd 	set_time_msg.minute	= tod.tod_min;
2751c42de6dSgd 	set_time_msg.second	= tod.tod_sec;
2761c42de6dSgd 
2771c42de6dSgd 	request.msg_type = DP_SET_DATE_TIME;
2781c42de6dSgd 	request.msg_len = sizeof (set_time_msg);
2791c42de6dSgd 	request.msg_buf = (caddr_t)&set_time_msg;
2801c42de6dSgd 
2811c42de6dSgd 	(void) rmc_comm_request_nowait(&request, 0);
2821c42de6dSgd }
2831c42de6dSgd 
2841c42de6dSgd void
write_rtc_time(struct rtc_t * rtc)2851c42de6dSgd write_rtc_time(struct rtc_t *rtc)
2861c42de6dSgd {
2871c42de6dSgd 	uint8_t	regb;
288*8fc99e42STrevor Thompson 	int	i;
2891c42de6dSgd 
2901c42de6dSgd 	/*
2911c42de6dSgd 	 * Freeze
2921c42de6dSgd 	 */
2931c42de6dSgd 	M5819P_ADDR_REG = RTC_B;
2941c42de6dSgd 	regb = M5819P_DATA_REG;
2951c42de6dSgd 	M5819P_DATA_REG = (regb | RTC_SET);
2961c42de6dSgd 
297*8fc99e42STrevor Thompson 	/*
298*8fc99e42STrevor Thompson 	 * If an update cycle is in progress wait for the UIP flag to
299*8fc99e42STrevor Thompson 	 * clear.  If we write whilst UIP is still set there is a slight
300*8fc99e42STrevor Thompson 	 * but real possibility of corrupting the RTC date and time
301*8fc99e42STrevor Thompson 	 * registers.
302*8fc99e42STrevor Thompson 	 *
303*8fc99e42STrevor Thompson 	 * The expected wait is one internal cycle of the chip.  We could
304*8fc99e42STrevor Thompson 	 * simply spin but this may hang a CPU if we were to have a broken
305*8fc99e42STrevor Thompson 	 * RTC chip where UIP is stuck, so we use a retry loop instead.
306*8fc99e42STrevor Thompson 	 * No critical section is needed here as the UIP flag will not be
307*8fc99e42STrevor Thompson 	 * re-asserted until we clear RTC_SET.
308*8fc99e42STrevor Thompson 	 */
309*8fc99e42STrevor Thompson 	M5819P_ADDR_REG = RTC_A;
310*8fc99e42STrevor Thompson 	for (i = 0; i < TODM5819_UIP_RETRY_THRESH; i++) {
311*8fc99e42STrevor Thompson 		if (!(M5819P_DATA_REG & RTC_UIP)) {
312*8fc99e42STrevor Thompson 			break;
313*8fc99e42STrevor Thompson 		}
314*8fc99e42STrevor Thompson 		drv_usecwait(TODM5819_UIP_WAIT_USEC);
315*8fc99e42STrevor Thompson 	}
316*8fc99e42STrevor Thompson 	if (i < TODM5819_UIP_RETRY_THRESH) {
317*8fc99e42STrevor Thompson 		M5819P_ADDR_REG = RTC_SEC;
318*8fc99e42STrevor Thompson 		M5819P_DATA_REG = rtc->rtc_sec;
319*8fc99e42STrevor Thompson 		M5819P_ADDR_REG = RTC_MIN;
320*8fc99e42STrevor Thompson 		M5819P_DATA_REG = rtc->rtc_min;
321*8fc99e42STrevor Thompson 		M5819P_ADDR_REG = RTC_HRS;
322*8fc99e42STrevor Thompson 		M5819P_DATA_REG = rtc->rtc_hrs;
323*8fc99e42STrevor Thompson 		M5819P_ADDR_REG = RTC_DOW;
324*8fc99e42STrevor Thompson 		M5819P_DATA_REG = rtc->rtc_dow;
325*8fc99e42STrevor Thompson 		M5819P_ADDR_REG = RTC_DOM;
326*8fc99e42STrevor Thompson 		M5819P_DATA_REG = rtc->rtc_dom;
327*8fc99e42STrevor Thompson 		M5819P_ADDR_REG = RTC_MON;
328*8fc99e42STrevor Thompson 		M5819P_DATA_REG = rtc->rtc_mon;
329*8fc99e42STrevor Thompson 		M5819P_ADDR_REG = RTC_YEAR;
330*8fc99e42STrevor Thompson 		M5819P_DATA_REG = rtc->rtc_year;
331*8fc99e42STrevor Thompson 		M5819P_ADDR_REG = RTC_CENTURY;
332*8fc99e42STrevor Thompson 		M5819P_DATA_REG = rtc->rtc_century;
333*8fc99e42STrevor Thompson 	} else {
334*8fc99e42STrevor Thompson 		cmn_err(CE_WARN, "todm5819p_rmc: Could not write the RTC\n");
335*8fc99e42STrevor Thompson 	}
3361c42de6dSgd 
3371c42de6dSgd 	/*
3381c42de6dSgd 	 * Unfreeze
3391c42de6dSgd 	 */
3401c42de6dSgd 	M5819P_ADDR_REG = RTC_B;
3411c42de6dSgd 	M5819P_DATA_REG = regb;
3421c42de6dSgd }
3431c42de6dSgd 
3441c42de6dSgd void
write_rtc_alarm(struct rtc_t * rtc)3451c42de6dSgd write_rtc_alarm(struct rtc_t *rtc)
3461c42de6dSgd {
3471c42de6dSgd 	M5819P_ADDR_REG = RTC_ASEC;
3481c42de6dSgd 	M5819P_DATA_REG = rtc->rtc_asec;
3491c42de6dSgd 	M5819P_ADDR_REG = RTC_AMIN;
3501c42de6dSgd 	M5819P_DATA_REG = rtc->rtc_amin;
3511c42de6dSgd 	M5819P_ADDR_REG = RTC_AHRS;
3521c42de6dSgd 	M5819P_DATA_REG = rtc->rtc_ahrs;
3531c42de6dSgd 
3541c42de6dSgd 	M5819P_ADDR_REG = RTC_ADOM_REG;
3551c42de6dSgd 	M5819P_DATA_REG = rtc->rtc_adom;
3561c42de6dSgd }
3571c42de6dSgd 
3581c42de6dSgd /*
3591c42de6dSgd  * program the rtc registers for alarm to go off at the specified time
3601c42de6dSgd  */
3611c42de6dSgd static void
todm5819p_rmc_set_power_alarm(timestruc_t ts)3621c42de6dSgd todm5819p_rmc_set_power_alarm(timestruc_t ts)
3631c42de6dSgd {
3641c42de6dSgd 	todinfo_t	tod;
3651c42de6dSgd 	uint8_t		regb;
3661c42de6dSgd 	struct rtc_t	rtc;
3671c42de6dSgd 
3681c42de6dSgd 	ASSERT(MUTEX_HELD(&tod_lock));
3691c42de6dSgd 	tod = utc_to_tod(ts.tv_sec);
3701c42de6dSgd 
3711c42de6dSgd 	/*
3721c42de6dSgd 	 * disable alarms and clear AF flag by reading reg C
3731c42de6dSgd 	 */
3741c42de6dSgd 	M5819P_ADDR_REG = RTC_B;
3751c42de6dSgd 	regb = M5819P_DATA_REG;
3761c42de6dSgd 	M5819P_DATA_REG = regb & ~RTC_AIE;
3771c42de6dSgd 	M5819P_ADDR_REG = RTC_C;
3781c42de6dSgd 	(void) M5819P_DATA_REG;
3791c42de6dSgd 
3801c42de6dSgd 	rtc.rtc_asec = (uint8_t)tod.tod_sec;
3811c42de6dSgd 	rtc.rtc_amin = (uint8_t)tod.tod_min;
3821c42de6dSgd 	rtc.rtc_ahrs = (uint8_t)tod.tod_hour;
3831c42de6dSgd 	rtc.rtc_adom = (uint8_t)tod.tod_day;
3841c42de6dSgd 
3851c42de6dSgd 	/*
3861c42de6dSgd 	 * Write alarm values and enable alarm
3871c42de6dSgd 	 */
3881c42de6dSgd 	write_rtc_alarm(&rtc);
3891c42de6dSgd 
3901c42de6dSgd 	M5819P_ADDR_REG = RTC_B;
3911c42de6dSgd 	M5819P_DATA_REG = regb | RTC_AIE;
3921c42de6dSgd }
3931c42de6dSgd 
3941c42de6dSgd /*
3951c42de6dSgd  * clear alarm interrupt
3961c42de6dSgd  */
3971c42de6dSgd static void
todm5819p_rmc_clear_power_alarm(void)3981c42de6dSgd todm5819p_rmc_clear_power_alarm(void)
3991c42de6dSgd {
4001c42de6dSgd 	uint8_t regb;
4011c42de6dSgd 
4021c42de6dSgd 	ASSERT(MUTEX_HELD(&tod_lock));
4031c42de6dSgd 
4041c42de6dSgd 	M5819P_ADDR_REG = RTC_B;
4051c42de6dSgd 	regb = M5819P_DATA_REG;
4061c42de6dSgd 	M5819P_DATA_REG = regb & ~RTC_AIE;
4071c42de6dSgd }
4081c42de6dSgd 
4091c42de6dSgd /*
4101c42de6dSgd  * Determine the cpu frequency by watching the TOD chip rollover twice.
4111c42de6dSgd  * Cpu clock rate is determined by computing the ticks added (in tick register)
4121c42de6dSgd  * during one second interval on TOD.
4131c42de6dSgd  */
4141c42de6dSgd uint64_t
todm5819p_rmc_get_cpufrequency(void)4151c42de6dSgd todm5819p_rmc_get_cpufrequency(void)
4161c42de6dSgd {
4171c42de6dSgd 	ASSERT(MUTEX_HELD(&tod_lock));
4181c42de6dSgd 	M5819P_ADDR_REG = RTC_SEC;
4191c42de6dSgd 	return (find_cpufrequency(v_rtc_data_reg));
4201c42de6dSgd }
4211c42de6dSgd 
4221c42de6dSgd /*ARGSUSED*/
4231c42de6dSgd static uint_t
todm5819p_rmc_set_watchdog_timer(uint_t timeoutval)4241c42de6dSgd todm5819p_rmc_set_watchdog_timer(uint_t timeoutval)
4251c42de6dSgd {
4261c42de6dSgd 	ASSERT(MUTEX_HELD(&tod_lock));
4271c42de6dSgd 	return (0);
4281c42de6dSgd }
4291c42de6dSgd 
4301c42de6dSgd static uint_t
todm5819p_rmc_clear_watchdog_timer(void)4311c42de6dSgd todm5819p_rmc_clear_watchdog_timer(void)
4321c42de6dSgd {
4331c42de6dSgd 	ASSERT(MUTEX_HELD(&tod_lock));
4341c42de6dSgd 	return (0);
4351c42de6dSgd }
436