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