1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2018 Gary Mills 23 * Copyright 2012 Nexenta Systems, Inc. All rights reserved. 24 */ 25 /* 26 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 27 * Use is subject to license terms. 28 */ 29 30 /* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */ 31 /* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */ 32 /* All Rights Reserved */ 33 34 /* Copyright (c) 1987, 1988 Microsoft Corporation */ 35 /* All Rights Reserved */ 36 37 #include <sys/param.h> 38 #include <sys/time.h> 39 #include <sys/systm.h> 40 41 #include <sys/cpuvar.h> 42 #include <sys/clock.h> 43 #include <sys/debug.h> 44 #include <sys/rtc.h> 45 #include <sys/archsystm.h> 46 #include <sys/sysmacros.h> 47 #include <sys/lockstat.h> 48 #include <sys/stat.h> 49 #include <sys/sunddi.h> 50 #include <sys/ddi.h> 51 52 #include <sys/acpi/acpi.h> 53 #include <sys/acpica.h> 54 55 static int todpc_rtcget(unsigned char *buf); 56 static void todpc_rtcput(unsigned char *buf); 57 58 #define CLOCK_RES 1000 /* 1 microsec in nanosecs */ 59 60 int clock_res = CLOCK_RES; 61 62 /* 63 * The minimum sleep time till an alarm can be fired. 64 * This can be tuned in /etc/system, but if the value is too small, 65 * there is a danger that it will be missed if it takes too long to 66 * get from the set point to sleep. Or that it can fire quickly, and 67 * generate a power spike on the hardware. And small values are 68 * probably only usefull for test setups. 69 */ 70 int clock_min_alarm = 4; 71 72 /* 73 * Machine-dependent clock routines. 74 */ 75 76 extern long gmt_lag; 77 78 struct rtc_offset { 79 int8_t loaded; 80 uint8_t day_alrm; 81 uint8_t mon_alrm; 82 uint8_t century; 83 }; 84 85 static struct rtc_offset pc_rtc_offset = {0, 0, 0, 0}; 86 87 88 /* 89 * Entry point for ACPI to pass RTC or other clock values that 90 * are useful to TOD. 91 */ 92 void 93 pc_tod_set_rtc_offsets(ACPI_TABLE_FADT *fadt) { 94 int ok = 0; 95 96 /* 97 * ASSERT is for debugging, but we don't want the machine 98 * falling over because for some reason we didn't get a valid 99 * pointer. 100 */ 101 ASSERT(fadt); 102 if (fadt == NULL) { 103 return; 104 } 105 106 if (fadt->DayAlarm) { 107 pc_rtc_offset.day_alrm = fadt->DayAlarm; 108 ok = 1; 109 } 110 111 if (fadt->MonthAlarm) { 112 pc_rtc_offset.mon_alrm = fadt->MonthAlarm; 113 ok = 1; 114 } 115 116 if (fadt->Century) { 117 pc_rtc_offset.century = fadt->Century; 118 ok = 1; 119 } 120 121 pc_rtc_offset.loaded = ok; 122 } 123 124 125 /* 126 * Write the specified time into the clock chip. 127 * Must be called with tod_lock held. 128 */ 129 /*ARGSUSED*/ 130 static void 131 todpc_set(tod_ops_t *top, timestruc_t ts) 132 { 133 todinfo_t tod = utc_to_tod(ts.tv_sec - ggmtl()); 134 struct rtc_t rtc; 135 136 ASSERT(MUTEX_HELD(&tod_lock)); 137 138 if (todpc_rtcget((unsigned char *)&rtc)) 139 return; 140 141 /* 142 * rtc bytes are in binary-coded decimal, so we have to convert. 143 * We assume that we wrap the rtc year back to zero at 2000. 144 */ 145 /* LINTED: YRBASE = 0 for x86 */ 146 tod.tod_year -= YRBASE; 147 if (tod.tod_year >= 100) { 148 tod.tod_year -= 100; 149 rtc.rtc_century = BYTE_TO_BCD(20); /* 20xx year */ 150 } else 151 rtc.rtc_century = BYTE_TO_BCD(19); /* 19xx year */ 152 rtc.rtc_yr = BYTE_TO_BCD(tod.tod_year); 153 rtc.rtc_mon = BYTE_TO_BCD(tod.tod_month); 154 rtc.rtc_dom = BYTE_TO_BCD(tod.tod_day); 155 /* dow < 10, so no conversion */ 156 rtc.rtc_dow = (unsigned char)tod.tod_dow; 157 rtc.rtc_hr = BYTE_TO_BCD(tod.tod_hour); 158 rtc.rtc_min = BYTE_TO_BCD(tod.tod_min); 159 rtc.rtc_sec = BYTE_TO_BCD(tod.tod_sec); 160 161 todpc_rtcput((unsigned char *)&rtc); 162 } 163 164 /* 165 * Read the current time from the clock chip and convert to UNIX form. 166 * Assumes that the year in the clock chip is valid. 167 * Must be called with tod_lock held. 168 */ 169 /*ARGSUSED*/ 170 static timestruc_t 171 todpc_get(tod_ops_t *top) 172 { 173 timestruc_t ts; 174 todinfo_t tod; 175 struct rtc_t rtc; 176 int compute_century; 177 static int century_warn = 1; /* only warn once, not each time called */ 178 static int range_warn = 1; 179 180 ASSERT(MUTEX_HELD(&tod_lock)); 181 182 if (todpc_rtcget((unsigned char *)&rtc)) { 183 tod_status_set(TOD_GET_FAILED); 184 return (hrestime); 185 } 186 187 /* assume that we wrap the rtc year back to zero at 2000 */ 188 tod.tod_year = BCD_TO_BYTE(rtc.rtc_yr); 189 if (tod.tod_year < 69) { 190 if (range_warn && tod.tod_year > 38) { 191 cmn_err(CE_WARN, "hardware real-time clock is out " 192 "of range -- time needs to be reset"); 193 range_warn = 0; 194 } 195 tod.tod_year += 100 + YRBASE; /* 20xx year */ 196 compute_century = 20; 197 } else { 198 /* LINTED: YRBASE = 0 for x86 */ 199 tod.tod_year += YRBASE; /* 19xx year */ 200 compute_century = 19; 201 } 202 if (century_warn && BCD_TO_BYTE(rtc.rtc_century) != compute_century) { 203 cmn_err(CE_NOTE, 204 "The hardware real-time clock appears to have the " 205 "wrong century: %d.\nSolaris will still operate " 206 "correctly, but other OS's/firmware agents may " 207 "not.\nUse date(1) to set the date to the current " 208 "time to correct the RTC.", 209 BCD_TO_BYTE(rtc.rtc_century)); 210 century_warn = 0; 211 } 212 tod.tod_month = BCD_TO_BYTE(rtc.rtc_mon); 213 tod.tod_day = BCD_TO_BYTE(rtc.rtc_dom); 214 tod.tod_dow = rtc.rtc_dow; /* dow < 10, so no conversion needed */ 215 tod.tod_hour = BCD_TO_BYTE(rtc.rtc_hr); 216 tod.tod_min = BCD_TO_BYTE(rtc.rtc_min); 217 tod.tod_sec = BCD_TO_BYTE(rtc.rtc_sec); 218 219 /* read was successful so ensure failure flag is clear */ 220 tod_status_clear(TOD_GET_FAILED); 221 222 ts.tv_sec = tod_to_utc(tod) + ggmtl(); 223 ts.tv_nsec = 0; 224 225 return (ts); 226 } 227 228 #include <sys/promif.h> 229 /* 230 * Write the specified wakeup alarm into the clock chip. 231 * Must be called with tod_lock held. 232 */ 233 void 234 /*ARGSUSED*/ 235 todpc_setalarm(tod_ops_t *top, int nsecs) 236 { 237 struct rtc_t rtc; 238 int delta, asec, amin, ahr, adom, amon; 239 int day_alrm = pc_rtc_offset.day_alrm; 240 int mon_alrm = pc_rtc_offset.mon_alrm; 241 242 ASSERT(MUTEX_HELD(&tod_lock)); 243 244 /* A delay of zero is not allowed */ 245 if (nsecs == 0) 246 return; 247 248 /* Make sure that we delay no less than the minimum time */ 249 if (nsecs < clock_min_alarm) 250 nsecs = clock_min_alarm; 251 252 if (todpc_rtcget((unsigned char *)&rtc)) 253 return; 254 255 /* 256 * Compute alarm secs, mins and hrs, and where appropriate, dom 257 * and mon. rtc bytes are in binary-coded decimal, so we have 258 * to convert. 259 */ 260 delta = nsecs + BCD_TO_BYTE(rtc.rtc_sec); 261 asec = delta % 60; 262 263 delta = (delta / 60) + BCD_TO_BYTE(rtc.rtc_min); 264 amin = delta % 60; 265 266 delta = (delta / 60) + BCD_TO_BYTE(rtc.rtc_hr); 267 ahr = delta % 24; 268 269 if (day_alrm == 0 && delta >= 24) { 270 prom_printf("No day alarm - set to end of today!\n"); 271 asec = 59; 272 amin = 59; 273 ahr = 23; 274 } else { 275 int mon = BCD_TO_BYTE(rtc.rtc_mon); 276 static int dpm[] = 277 {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 278 279 adom = (delta / 24) + BCD_TO_BYTE(rtc.rtc_dom); 280 281 if (mon_alrm == 0) { 282 if (adom > dpm[mon]) { 283 prom_printf("No mon alarm - " 284 "set to end of current month!\n"); 285 asec = 59; 286 amin = 59; 287 ahr = 23; 288 adom = dpm[mon]; 289 } 290 } else { 291 for (amon = mon; 292 amon <= 12 && adom > dpm[amon]; amon++) { 293 adom -= dpm[amon]; 294 } 295 if (amon > 12) { 296 prom_printf("Alarm too far in future - " 297 "set to end of current year!\n"); 298 asec = 59; 299 amin = 59; 300 ahr = 23; 301 adom = dpm[12]; 302 amon = 12; 303 } 304 rtc.rtc_amon = BYTE_TO_BCD(amon); 305 } 306 307 rtc.rtc_adom = BYTE_TO_BCD(adom); 308 } 309 310 rtc.rtc_asec = BYTE_TO_BCD(asec); 311 rtc.rtc_amin = BYTE_TO_BCD(amin); 312 rtc.rtc_ahr = BYTE_TO_BCD(ahr); 313 314 rtc.rtc_statusb |= RTC_AIE; /* Enable alarm interrupt */ 315 316 todpc_rtcput((unsigned char *)&rtc); 317 } 318 319 /* 320 * Clear an alarm. This is effectively setting an alarm of 0. 321 */ 322 void 323 /*ARGSUSED*/ 324 todpc_clralarm(tod_ops_t *top) 325 { 326 mutex_enter(&tod_lock); 327 todpc_setalarm(top, 0); 328 mutex_exit(&tod_lock); 329 } 330 331 /* 332 * Routine to read contents of real time clock to the specified buffer. 333 * Returns ENXIO if clock not valid, or EAGAIN if clock data cannot be read 334 * else 0. 335 * Some RTC hardware is very slow at asserting the validity flag on 336 * startup. The routine will busy wait for the RTC to become valid. 337 * The routine will also busy wait for the Update-In-Progress flag to clear. 338 * On completion of the reads the Seconds register is re-read and the 339 * UIP flag is rechecked to confirm that an clock update did not occur 340 * during the accesses. Routine will error exit after 256 attempts. 341 * (See bugid 1158298.) 342 * Routine returns RTC_NREG (which is 15) bytes of data, as given in the 343 * technical reference. This data includes both time and status registers. 344 */ 345 346 static int 347 todpc_rtcget(unsigned char *buf) 348 { 349 unsigned char reg; 350 int i; 351 int uip_try = 256; 352 int vrt_try = 512; 353 unsigned char *rawp; 354 unsigned char century = RTC_CENTURY; 355 unsigned char day_alrm; 356 unsigned char mon_alrm; 357 358 ASSERT(MUTEX_HELD(&tod_lock)); 359 360 day_alrm = pc_rtc_offset.day_alrm; 361 mon_alrm = pc_rtc_offset.mon_alrm; 362 if (pc_rtc_offset.century != 0) { 363 century = pc_rtc_offset.century; 364 } 365 366 for (;;) { 367 if (vrt_try-- < 0) 368 return (ENXIO); 369 outb(RTC_ADDR, RTC_D); /* check if clock valid */ 370 reg = inb(RTC_DATA); 371 if ((reg & RTC_VRT) != 0) 372 break; 373 drv_usecwait(5000); /* Delay for 5000 us */ 374 } 375 376 377 checkuip: 378 if (uip_try-- < 0) 379 return (EAGAIN); 380 outb(RTC_ADDR, RTC_A); /* check if update in progress */ 381 reg = inb(RTC_DATA); 382 if (reg & RTC_UIP) { 383 tenmicrosec(); 384 goto checkuip; 385 } 386 387 for (i = 0, rawp = buf; i < RTC_NREG; i++) { 388 outb(RTC_ADDR, i); 389 *rawp++ = inb(RTC_DATA); 390 } 391 outb(RTC_ADDR, century); /* do century */ 392 ((struct rtc_t *)buf)->rtc_century = inb(RTC_DATA); 393 394 if (day_alrm > 0) { 395 outb(RTC_ADDR, day_alrm); 396 ((struct rtc_t *)buf)->rtc_adom = inb(RTC_DATA) & 0x3f; 397 } 398 if (mon_alrm > 0) { 399 outb(RTC_ADDR, mon_alrm); 400 ((struct rtc_t *)buf)->rtc_amon = inb(RTC_DATA); 401 } 402 403 outb(RTC_ADDR, 0); /* re-read Seconds register */ 404 reg = inb(RTC_DATA); 405 if (reg != ((struct rtc_t *)buf)->rtc_sec || 406 (((struct rtc_t *)buf)->rtc_statusa & RTC_UIP)) 407 /* update occured during reads */ 408 goto checkuip; 409 410 return (0); 411 } 412 413 /* 414 * This routine writes the contents of the given buffer to the real time 415 * clock. It is given RTC_NREGP bytes of data, which are the 10 bytes used 416 * to write the time and set the alarm. It should be called with the priority 417 * raised to 5. 418 */ 419 static void 420 todpc_rtcput(unsigned char *buf) 421 { 422 unsigned char reg; 423 int i; 424 unsigned char century = RTC_CENTURY; 425 unsigned char day_alrm = pc_rtc_offset.day_alrm; 426 unsigned char mon_alrm = pc_rtc_offset.mon_alrm; 427 unsigned char tmp; 428 429 if (pc_rtc_offset.century != 0) { 430 century = pc_rtc_offset.century; 431 } 432 433 outb(RTC_ADDR, RTC_B); 434 reg = inb(RTC_DATA); 435 outb(RTC_ADDR, RTC_B); 436 outb(RTC_DATA, reg | RTC_SET); /* allow time set now */ 437 for (i = 0; i < RTC_NREGP; i++) { /* set the time */ 438 outb(RTC_ADDR, i); 439 outb(RTC_DATA, buf[i]); 440 } 441 outb(RTC_ADDR, century); /* do century */ 442 outb(RTC_DATA, ((struct rtc_t *)buf)->rtc_century); 443 444 if (day_alrm > 0) { 445 outb(RTC_ADDR, day_alrm); 446 /* preserve RTC_VRT bit; some virt envs accept writes there */ 447 tmp = inb(RTC_DATA) & RTC_VRT; 448 tmp |= ((struct rtc_t *)buf)->rtc_adom & ~RTC_VRT; 449 outb(RTC_DATA, tmp); 450 } 451 if (mon_alrm > 0) { 452 outb(RTC_ADDR, mon_alrm); 453 outb(RTC_DATA, ((struct rtc_t *)buf)->rtc_amon); 454 } 455 456 outb(RTC_ADDR, RTC_B); 457 reg = inb(RTC_DATA); 458 outb(RTC_ADDR, RTC_B); 459 outb(RTC_DATA, reg & ~RTC_SET); /* allow time update */ 460 } 461 462 static tod_ops_t todpc_ops = { 463 TOD_OPS_VERSION, 464 todpc_get, 465 todpc_set, 466 NULL, 467 NULL, 468 todpc_setalarm, 469 todpc_clralarm, 470 NULL 471 }; 472 473 /* 474 * Initialize for the default TOD ops vector for use on hardware. 475 */ 476 477 tod_ops_t *tod_ops = &todpc_ops;