1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate */ 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/open.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate #include <sys/todm5819.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/clock.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/reboot.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/machsystm.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/poll.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/pbio.h> 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate static timestruc_t todm5819_get(void); 49*7c478bd9Sstevel@tonic-gate static void todm5819_set(timestruc_t); 50*7c478bd9Sstevel@tonic-gate static uint_t todm5819_set_watchdog_timer(uint_t); 51*7c478bd9Sstevel@tonic-gate static uint_t todm5819_clear_watchdog_timer(void); 52*7c478bd9Sstevel@tonic-gate static void todm5819_set_power_alarm(timestruc_t); 53*7c478bd9Sstevel@tonic-gate static void todm5819_clear_power_alarm(void); 54*7c478bd9Sstevel@tonic-gate static uint64_t todm5819_get_cpufrequency(void); 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate extern uint64_t find_cpufrequency(volatile uint8_t *); 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate /* 59*7c478bd9Sstevel@tonic-gate * External variables 60*7c478bd9Sstevel@tonic-gate */ 61*7c478bd9Sstevel@tonic-gate extern int watchdog_enable; 62*7c478bd9Sstevel@tonic-gate extern int watchdog_available; 63*7c478bd9Sstevel@tonic-gate extern int boothowto; 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate /* 66*7c478bd9Sstevel@tonic-gate * Global variables 67*7c478bd9Sstevel@tonic-gate */ 68*7c478bd9Sstevel@tonic-gate int m5819_debug_flags; 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate static todinfo_t rtc_to_tod(struct rtc_t *); 71*7c478bd9Sstevel@tonic-gate static uint_t read_rtc(struct rtc_t *); 72*7c478bd9Sstevel@tonic-gate static void write_rtc_time(struct rtc_t *); 73*7c478bd9Sstevel@tonic-gate static void write_rtc_alarm(struct rtc_t *); 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate static struct modlmisc modlmisc = { 77*7c478bd9Sstevel@tonic-gate &mod_miscops, "tod module for ALI M5819", 78*7c478bd9Sstevel@tonic-gate }; 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 81*7c478bd9Sstevel@tonic-gate MODREV_1, &modlmisc, NULL 82*7c478bd9Sstevel@tonic-gate }; 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate int 86*7c478bd9Sstevel@tonic-gate _init(void) 87*7c478bd9Sstevel@tonic-gate { 88*7c478bd9Sstevel@tonic-gate if (strcmp(tod_module_name, "todm5819") == 0 || 89*7c478bd9Sstevel@tonic-gate strcmp(tod_module_name, "m5819") == 0) { 90*7c478bd9Sstevel@tonic-gate RTC_PUT8(RTC_B, (RTC_DM | RTC_HM)); 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate tod_ops.tod_get = todm5819_get; 93*7c478bd9Sstevel@tonic-gate tod_ops.tod_set = todm5819_set; 94*7c478bd9Sstevel@tonic-gate tod_ops.tod_set_watchdog_timer = 95*7c478bd9Sstevel@tonic-gate todm5819_set_watchdog_timer; 96*7c478bd9Sstevel@tonic-gate tod_ops.tod_clear_watchdog_timer = 97*7c478bd9Sstevel@tonic-gate todm5819_clear_watchdog_timer; 98*7c478bd9Sstevel@tonic-gate tod_ops.tod_set_power_alarm = todm5819_set_power_alarm; 99*7c478bd9Sstevel@tonic-gate tod_ops.tod_clear_power_alarm = todm5819_clear_power_alarm; 100*7c478bd9Sstevel@tonic-gate tod_ops.tod_get_cpufrequency = todm5819_get_cpufrequency; 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate /* 103*7c478bd9Sstevel@tonic-gate * check if hardware watchdog timer is available and user 104*7c478bd9Sstevel@tonic-gate * enabled it. 105*7c478bd9Sstevel@tonic-gate */ 106*7c478bd9Sstevel@tonic-gate if (watchdog_enable) { 107*7c478bd9Sstevel@tonic-gate if (!watchdog_available) { 108*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "m5819: Hardware watchdog " 109*7c478bd9Sstevel@tonic-gate "unavailable"); 110*7c478bd9Sstevel@tonic-gate } else if (boothowto & RB_DEBUG) { 111*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "m5819: Hardware watchdog " 112*7c478bd9Sstevel@tonic-gate "disabled [debugger]"); 113*7c478bd9Sstevel@tonic-gate } 114*7c478bd9Sstevel@tonic-gate } 115*7c478bd9Sstevel@tonic-gate } 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate return (mod_install(&modlinkage)); 118*7c478bd9Sstevel@tonic-gate } 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate int 121*7c478bd9Sstevel@tonic-gate _fini(void) 122*7c478bd9Sstevel@tonic-gate { 123*7c478bd9Sstevel@tonic-gate if (strcmp(tod_module_name, "m5819") == 0 || 124*7c478bd9Sstevel@tonic-gate strcmp(tod_module_name, "todm5819") == 0) { 125*7c478bd9Sstevel@tonic-gate return (EBUSY); 126*7c478bd9Sstevel@tonic-gate } else { 127*7c478bd9Sstevel@tonic-gate return (mod_remove(&modlinkage)); 128*7c478bd9Sstevel@tonic-gate } 129*7c478bd9Sstevel@tonic-gate } 130*7c478bd9Sstevel@tonic-gate 131*7c478bd9Sstevel@tonic-gate /* 132*7c478bd9Sstevel@tonic-gate * The loadable-module _info(9E) entry point 133*7c478bd9Sstevel@tonic-gate */ 134*7c478bd9Sstevel@tonic-gate int 135*7c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 136*7c478bd9Sstevel@tonic-gate { 137*7c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 138*7c478bd9Sstevel@tonic-gate } 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate /* 142*7c478bd9Sstevel@tonic-gate * Read the current time from the clock chip and convert to UNIX form. 143*7c478bd9Sstevel@tonic-gate * Assumes that the year in the clock chip is valid. 144*7c478bd9Sstevel@tonic-gate * Must be called with tod_lock held. 145*7c478bd9Sstevel@tonic-gate */ 146*7c478bd9Sstevel@tonic-gate static timestruc_t 147*7c478bd9Sstevel@tonic-gate todm5819_get(void) 148*7c478bd9Sstevel@tonic-gate { 149*7c478bd9Sstevel@tonic-gate int i; 150*7c478bd9Sstevel@tonic-gate timestruc_t ts; 151*7c478bd9Sstevel@tonic-gate struct rtc_t rtc; 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&tod_lock)); 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate /* 156*7c478bd9Sstevel@tonic-gate * Read from the tod, and if it isnt accessible wait 157*7c478bd9Sstevel@tonic-gate * before retrying. 158*7c478bd9Sstevel@tonic-gate */ 159*7c478bd9Sstevel@tonic-gate for (i = 0; i < TODM5819_UIP_RETRY_THRESH; i++) { 160*7c478bd9Sstevel@tonic-gate if (read_rtc(&rtc)) 161*7c478bd9Sstevel@tonic-gate break; 162*7c478bd9Sstevel@tonic-gate drv_usecwait(TODM5819_UIP_WAIT_USEC); 163*7c478bd9Sstevel@tonic-gate } 164*7c478bd9Sstevel@tonic-gate if (i == TODM5819_UIP_RETRY_THRESH) { 165*7c478bd9Sstevel@tonic-gate /* 166*7c478bd9Sstevel@tonic-gate * We couldnt read from the tod 167*7c478bd9Sstevel@tonic-gate */ 168*7c478bd9Sstevel@tonic-gate tod_fault_reset(); 169*7c478bd9Sstevel@tonic-gate return (hrestime); 170*7c478bd9Sstevel@tonic-gate } 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate DPRINTF("todm5819_get: century=%d year=%d dom=%d hrs=%d\n", 173*7c478bd9Sstevel@tonic-gate rtc.rtc_century, rtc.rtc_year, rtc.rtc_dom, rtc.rtc_hrs); 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate ts.tv_sec = tod_to_utc(rtc_to_tod(&rtc)); 176*7c478bd9Sstevel@tonic-gate ts.tv_nsec = 0; 177*7c478bd9Sstevel@tonic-gate return (ts); 178*7c478bd9Sstevel@tonic-gate } 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate static todinfo_t 181*7c478bd9Sstevel@tonic-gate rtc_to_tod(struct rtc_t *rtc) 182*7c478bd9Sstevel@tonic-gate { 183*7c478bd9Sstevel@tonic-gate todinfo_t tod; 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate /* 186*7c478bd9Sstevel@tonic-gate * tod_year is base 1900 so this code needs to adjust the true 187*7c478bd9Sstevel@tonic-gate * year retrieved from the rtc's century and year fields. 188*7c478bd9Sstevel@tonic-gate */ 189*7c478bd9Sstevel@tonic-gate tod.tod_year = rtc->rtc_year + (rtc->rtc_century * 100) - 1900; 190*7c478bd9Sstevel@tonic-gate tod.tod_month = rtc->rtc_mon; 191*7c478bd9Sstevel@tonic-gate tod.tod_day = rtc->rtc_dom; 192*7c478bd9Sstevel@tonic-gate tod.tod_dow = rtc->rtc_dow; 193*7c478bd9Sstevel@tonic-gate tod.tod_hour = rtc->rtc_hrs; 194*7c478bd9Sstevel@tonic-gate tod.tod_min = rtc->rtc_min; 195*7c478bd9Sstevel@tonic-gate tod.tod_sec = rtc->rtc_sec; 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate return (tod); 198*7c478bd9Sstevel@tonic-gate } 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate uint_t 201*7c478bd9Sstevel@tonic-gate read_rtc(struct rtc_t *rtc) 202*7c478bd9Sstevel@tonic-gate { 203*7c478bd9Sstevel@tonic-gate int s; 204*7c478bd9Sstevel@tonic-gate uint_t rtc_readable = 0; 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate s = splhi(); 207*7c478bd9Sstevel@tonic-gate /* 208*7c478bd9Sstevel@tonic-gate * If UIP bit is not set we have at least 274us 209*7c478bd9Sstevel@tonic-gate * to read the values. Otherwise we have up to 210*7c478bd9Sstevel@tonic-gate * 336us to wait before we can read it 211*7c478bd9Sstevel@tonic-gate */ 212*7c478bd9Sstevel@tonic-gate if (!(RTC_GET8(RTC_A) & RTC_UIP)) { 213*7c478bd9Sstevel@tonic-gate rtc_readable = 1; 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate rtc->rtc_sec = RTC_GET8(RTC_SEC); 216*7c478bd9Sstevel@tonic-gate rtc->rtc_asec = RTC_GET8(RTC_ASEC); 217*7c478bd9Sstevel@tonic-gate rtc->rtc_min = RTC_GET8(RTC_MIN); 218*7c478bd9Sstevel@tonic-gate rtc->rtc_amin = RTC_GET8(RTC_AMIN); 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate rtc->rtc_hrs = RTC_GET8(RTC_HRS); 221*7c478bd9Sstevel@tonic-gate rtc->rtc_ahrs = RTC_GET8(RTC_AHRS); 222*7c478bd9Sstevel@tonic-gate rtc->rtc_dow = RTC_GET8(RTC_DOW); 223*7c478bd9Sstevel@tonic-gate rtc->rtc_dom = RTC_GET8(RTC_DOM); 224*7c478bd9Sstevel@tonic-gate rtc->rtc_adom = RTC_GET8(RTC_D) & 0x3f; 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate rtc->rtc_mon = RTC_GET8(RTC_MON); 227*7c478bd9Sstevel@tonic-gate rtc->rtc_year = RTC_GET8(RTC_YEAR); 228*7c478bd9Sstevel@tonic-gate rtc->rtc_century = RTC_GET8(RTC_CENTURY); 229*7c478bd9Sstevel@tonic-gate rtc->rtc_amon = 0; 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate /* Clear wakeup data */ 232*7c478bd9Sstevel@tonic-gate rtc->apc_wdwr = 0; 233*7c478bd9Sstevel@tonic-gate rtc->apc_wdmr = 0; 234*7c478bd9Sstevel@tonic-gate rtc->apc_wmr = 0; 235*7c478bd9Sstevel@tonic-gate rtc->apc_wyr = 0; 236*7c478bd9Sstevel@tonic-gate rtc->apc_wcr = 0; 237*7c478bd9Sstevel@tonic-gate } 238*7c478bd9Sstevel@tonic-gate splx(s); 239*7c478bd9Sstevel@tonic-gate return (rtc_readable); 240*7c478bd9Sstevel@tonic-gate } 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate /* 243*7c478bd9Sstevel@tonic-gate * Write the specified time into the clock chip. 244*7c478bd9Sstevel@tonic-gate * Must be called with tod_lock held. 245*7c478bd9Sstevel@tonic-gate */ 246*7c478bd9Sstevel@tonic-gate static void 247*7c478bd9Sstevel@tonic-gate todm5819_set(timestruc_t ts) 248*7c478bd9Sstevel@tonic-gate { 249*7c478bd9Sstevel@tonic-gate struct rtc_t rtc; 250*7c478bd9Sstevel@tonic-gate todinfo_t tod = utc_to_tod(ts.tv_sec); 251*7c478bd9Sstevel@tonic-gate int year; 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&tod_lock)); 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate /* tod_year is base 1900 so this code needs to adjust */ 256*7c478bd9Sstevel@tonic-gate year = 1900 + tod.tod_year; 257*7c478bd9Sstevel@tonic-gate rtc.rtc_year = year % 100; 258*7c478bd9Sstevel@tonic-gate rtc.rtc_century = year / 100; 259*7c478bd9Sstevel@tonic-gate rtc.rtc_mon = (uint8_t)tod.tod_month; 260*7c478bd9Sstevel@tonic-gate rtc.rtc_dom = (uint8_t)tod.tod_day; 261*7c478bd9Sstevel@tonic-gate rtc.rtc_dow = (uint8_t)tod.tod_dow; 262*7c478bd9Sstevel@tonic-gate rtc.rtc_hrs = (uint8_t)tod.tod_hour; 263*7c478bd9Sstevel@tonic-gate rtc.rtc_min = (uint8_t)tod.tod_min; 264*7c478bd9Sstevel@tonic-gate rtc.rtc_sec = (uint8_t)tod.tod_sec; 265*7c478bd9Sstevel@tonic-gate DPRINTF("todm5819_set: century=%d year=%d dom=%d hrs=%d\n", 266*7c478bd9Sstevel@tonic-gate rtc.rtc_century, rtc.rtc_year, rtc.rtc_dom, rtc.rtc_hrs); 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate write_rtc_time(&rtc); 269*7c478bd9Sstevel@tonic-gate } 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate void 272*7c478bd9Sstevel@tonic-gate write_rtc_time(struct rtc_t *rtc) 273*7c478bd9Sstevel@tonic-gate { 274*7c478bd9Sstevel@tonic-gate uint8_t regb; 275*7c478bd9Sstevel@tonic-gate 276*7c478bd9Sstevel@tonic-gate /* 277*7c478bd9Sstevel@tonic-gate * Freeze 278*7c478bd9Sstevel@tonic-gate */ 279*7c478bd9Sstevel@tonic-gate regb = RTC_GET8(RTC_B); 280*7c478bd9Sstevel@tonic-gate RTC_PUT8(RTC_B, (regb | RTC_SET)); 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate RTC_PUT8(RTC_SEC, (rtc->rtc_sec)); 283*7c478bd9Sstevel@tonic-gate RTC_PUT8(RTC_ASEC, (rtc->rtc_asec)); 284*7c478bd9Sstevel@tonic-gate RTC_PUT8(RTC_MIN, (rtc->rtc_min)); 285*7c478bd9Sstevel@tonic-gate RTC_PUT8(RTC_AMIN, (rtc->rtc_amin)); 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate RTC_PUT8(RTC_HRS, (rtc->rtc_hrs)); 288*7c478bd9Sstevel@tonic-gate RTC_PUT8(RTC_AHRS, (rtc->rtc_ahrs)); 289*7c478bd9Sstevel@tonic-gate RTC_PUT8(RTC_DOW, (rtc->rtc_dow)); 290*7c478bd9Sstevel@tonic-gate RTC_PUT8(RTC_DOM, (rtc->rtc_dom)); 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate RTC_PUT8(RTC_MON, (rtc->rtc_mon)); 293*7c478bd9Sstevel@tonic-gate RTC_PUT8(RTC_YEAR, (rtc->rtc_year)); 294*7c478bd9Sstevel@tonic-gate RTC_PUT8(RTC_CENTURY, (rtc->rtc_century)); 295*7c478bd9Sstevel@tonic-gate 296*7c478bd9Sstevel@tonic-gate /* 297*7c478bd9Sstevel@tonic-gate * Unfreeze 298*7c478bd9Sstevel@tonic-gate */ 299*7c478bd9Sstevel@tonic-gate RTC_PUT8(RTC_B, regb); 300*7c478bd9Sstevel@tonic-gate } 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate void 304*7c478bd9Sstevel@tonic-gate write_rtc_alarm(struct rtc_t *rtc) 305*7c478bd9Sstevel@tonic-gate { 306*7c478bd9Sstevel@tonic-gate RTC_PUT8(RTC_ASEC, (rtc->rtc_asec)); 307*7c478bd9Sstevel@tonic-gate RTC_PUT8(RTC_AMIN, (rtc->rtc_amin)); 308*7c478bd9Sstevel@tonic-gate RTC_PUT8(RTC_AHRS, (rtc->rtc_ahrs)); 309*7c478bd9Sstevel@tonic-gate RTC_PUT8(RTC_D, (rtc->rtc_adom)); 310*7c478bd9Sstevel@tonic-gate } 311*7c478bd9Sstevel@tonic-gate 312*7c478bd9Sstevel@tonic-gate /* 313*7c478bd9Sstevel@tonic-gate * program the rtc registers for alarm to go off at the specified time 314*7c478bd9Sstevel@tonic-gate */ 315*7c478bd9Sstevel@tonic-gate static void 316*7c478bd9Sstevel@tonic-gate todm5819_set_power_alarm(timestruc_t ts) 317*7c478bd9Sstevel@tonic-gate { 318*7c478bd9Sstevel@tonic-gate todinfo_t tod; 319*7c478bd9Sstevel@tonic-gate uint8_t regb; 320*7c478bd9Sstevel@tonic-gate struct rtc_t rtc; 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&tod_lock)); 323*7c478bd9Sstevel@tonic-gate tod = utc_to_tod(ts.tv_sec); 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate /* 326*7c478bd9Sstevel@tonic-gate * disable alarms 327*7c478bd9Sstevel@tonic-gate */ 328*7c478bd9Sstevel@tonic-gate regb = RTC_GET8(RTC_B); 329*7c478bd9Sstevel@tonic-gate RTC_PUT8(RTC_B, (regb & ~RTC_AIE)); 330*7c478bd9Sstevel@tonic-gate 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate rtc.rtc_asec = (uint8_t)tod.tod_sec; 333*7c478bd9Sstevel@tonic-gate rtc.rtc_amin = (uint8_t)tod.tod_min; 334*7c478bd9Sstevel@tonic-gate rtc.rtc_ahrs = (uint8_t)tod.tod_hour; 335*7c478bd9Sstevel@tonic-gate rtc.rtc_adom = (uint8_t)tod.tod_day; 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate write_rtc_alarm(&rtc); 338*7c478bd9Sstevel@tonic-gate /* 339*7c478bd9Sstevel@tonic-gate * Enable alarm. 340*7c478bd9Sstevel@tonic-gate */ 341*7c478bd9Sstevel@tonic-gate RTC_PUT8(RTC_B, (regb | RTC_AIE)); 342*7c478bd9Sstevel@tonic-gate } 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate /* 345*7c478bd9Sstevel@tonic-gate * clear alarm interrupt 346*7c478bd9Sstevel@tonic-gate */ 347*7c478bd9Sstevel@tonic-gate static void 348*7c478bd9Sstevel@tonic-gate todm5819_clear_power_alarm(void) 349*7c478bd9Sstevel@tonic-gate { 350*7c478bd9Sstevel@tonic-gate uint8_t regb; 351*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&tod_lock)); 352*7c478bd9Sstevel@tonic-gate 353*7c478bd9Sstevel@tonic-gate regb = RTC_GET8(RTC_B); 354*7c478bd9Sstevel@tonic-gate RTC_PUT8(RTC_B, (regb & ~RTC_AIE)); 355*7c478bd9Sstevel@tonic-gate } 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate /* 358*7c478bd9Sstevel@tonic-gate * Determine the cpu frequency by watching the TOD chip rollover twice. 359*7c478bd9Sstevel@tonic-gate * Cpu clock rate is determined by computing the ticks added (in tick register) 360*7c478bd9Sstevel@tonic-gate * during one second interval on TOD. 361*7c478bd9Sstevel@tonic-gate */ 362*7c478bd9Sstevel@tonic-gate uint64_t 363*7c478bd9Sstevel@tonic-gate todm5819_get_cpufrequency(void) 364*7c478bd9Sstevel@tonic-gate { 365*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&tod_lock)); 366*7c478bd9Sstevel@tonic-gate M5819_ADDR_REG = RTC_SEC; 367*7c478bd9Sstevel@tonic-gate return (find_cpufrequency(v_rtc_data_reg)); 368*7c478bd9Sstevel@tonic-gate } 369*7c478bd9Sstevel@tonic-gate 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 372*7c478bd9Sstevel@tonic-gate static uint_t 373*7c478bd9Sstevel@tonic-gate todm5819_set_watchdog_timer(uint_t timeoutval) 374*7c478bd9Sstevel@tonic-gate { 375*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&tod_lock)); 376*7c478bd9Sstevel@tonic-gate return (0); 377*7c478bd9Sstevel@tonic-gate } 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate static uint_t 380*7c478bd9Sstevel@tonic-gate todm5819_clear_watchdog_timer(void) 381*7c478bd9Sstevel@tonic-gate { 382*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&tod_lock)); 383*7c478bd9Sstevel@tonic-gate return (0); 384*7c478bd9Sstevel@tonic-gate } 385