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 { 95 int ok = 0; 96 97 /* 98 * ASSERT is for debugging, but we don't want the machine 99 * falling over because for some reason we didn't get a valid 100 * pointer. 101 */ 102 ASSERT(fadt); 103 if (fadt == NULL) { 104 return; 105 } 106 107 if (fadt->DayAlarm) { 108 pc_rtc_offset.day_alrm = fadt->DayAlarm; 109 ok = 1; 110 } 111 112 if (fadt->MonthAlarm) { 113 pc_rtc_offset.mon_alrm = fadt->MonthAlarm; 114 ok = 1; 115 } 116 117 if (fadt->Century) { 118 pc_rtc_offset.century = fadt->Century; 119 ok = 1; 120 } 121 122 pc_rtc_offset.loaded = ok; 123 } 124 125 126 /* 127 * Write the specified time into the clock chip. 128 * Must be called with tod_lock held. 129 */ 130 /*ARGSUSED*/ 131 static void 132 todpc_set(tod_ops_t *top, timestruc_t ts) 133 { 134 todinfo_t tod = utc_to_tod(ts.tv_sec - ggmtl()); 135 struct rtc_t rtc; 136 137 ASSERT(MUTEX_HELD(&tod_lock)); 138 139 if (todpc_rtcget((unsigned char *)&rtc)) 140 return; 141 142 /* 143 * rtc bytes are in binary-coded decimal, so we have to convert. 144 * We assume that we wrap the rtc year back to zero at 2000. 145 */ 146 /* LINTED: YRBASE = 0 for x86 */ 147 tod.tod_year -= YRBASE; 148 if (tod.tod_year >= 100) { 149 tod.tod_year -= 100; 150 rtc.rtc_century = BYTE_TO_BCD(20); /* 20xx year */ 151 } else 152 rtc.rtc_century = BYTE_TO_BCD(19); /* 19xx year */ 153 rtc.rtc_yr = BYTE_TO_BCD(tod.tod_year); 154 rtc.rtc_mon = BYTE_TO_BCD(tod.tod_month); 155 rtc.rtc_dom = BYTE_TO_BCD(tod.tod_day); 156 /* dow < 10, so no conversion */ 157 rtc.rtc_dow = (unsigned char)tod.tod_dow; 158 rtc.rtc_hr = BYTE_TO_BCD(tod.tod_hour); 159 rtc.rtc_min = BYTE_TO_BCD(tod.tod_min); 160 rtc.rtc_sec = BYTE_TO_BCD(tod.tod_sec); 161 162 todpc_rtcput((unsigned char *)&rtc); 163 } 164 165 /* 166 * Read the current time from the clock chip and convert to UNIX form. 167 * Assumes that the year in the clock chip is valid. 168 * Must be called with tod_lock held. 169 */ 170 /*ARGSUSED*/ 171 static timestruc_t 172 todpc_get(tod_ops_t *top) 173 { 174 timestruc_t ts; 175 todinfo_t tod; 176 struct rtc_t rtc; 177 int compute_century; 178 static int century_warn = 1; /* only warn once, not each time called */ 179 static int range_warn = 1; 180 181 ASSERT(MUTEX_HELD(&tod_lock)); 182 183 if (todpc_rtcget((unsigned char *)&rtc)) { 184 tod_status_set(TOD_GET_FAILED); 185 return (hrestime); 186 } 187 188 /* assume that we wrap the rtc year back to zero at 2000 */ 189 tod.tod_year = BCD_TO_BYTE(rtc.rtc_yr); 190 if (tod.tod_year < 69) { 191 if (range_warn && tod.tod_year > 38) { 192 cmn_err(CE_WARN, "hardware real-time clock is out " 193 "of range -- time needs to be reset"); 194 range_warn = 0; 195 } 196 tod.tod_year += 100 + YRBASE; /* 20xx year */ 197 compute_century = 20; 198 } else { 199 /* LINTED: YRBASE = 0 for x86 */ 200 tod.tod_year += YRBASE; /* 19xx year */ 201 compute_century = 19; 202 } 203 if (century_warn && BCD_TO_BYTE(rtc.rtc_century) != compute_century) { 204 cmn_err(CE_NOTE, 205 "The hardware real-time clock appears to have the " 206 "wrong century: %d.\nSolaris will still operate " 207 "correctly, but other OS's/firmware agents may " 208 "not.\nUse date(1) to set the date to the current " 209 "time to correct the RTC.", 210 BCD_TO_BYTE(rtc.rtc_century)); 211 century_warn = 0; 212 } 213 tod.tod_month = BCD_TO_BYTE(rtc.rtc_mon); 214 tod.tod_day = BCD_TO_BYTE(rtc.rtc_dom); 215 tod.tod_dow = rtc.rtc_dow; /* dow < 10, so no conversion needed */ 216 tod.tod_hour = BCD_TO_BYTE(rtc.rtc_hr); 217 tod.tod_min = BCD_TO_BYTE(rtc.rtc_min); 218 tod.tod_sec = BCD_TO_BYTE(rtc.rtc_sec); 219 220 /* read was successful so ensure failure flag is clear */ 221 tod_status_clear(TOD_GET_FAILED); 222 223 ts.tv_sec = tod_to_utc(tod) + ggmtl(); 224 ts.tv_nsec = 0; 225 226 return (ts); 227 } 228 229 #include <sys/promif.h> 230 /* 231 * Write the specified wakeup alarm into the clock chip. 232 * Must be called with tod_lock held. 233 */ 234 void 235 /*ARGSUSED*/ 236 todpc_setalarm(tod_ops_t *top, int nsecs) 237 { 238 struct rtc_t rtc; 239 int delta, asec, amin, ahr, adom, amon; 240 int day_alrm = pc_rtc_offset.day_alrm; 241 int mon_alrm = pc_rtc_offset.mon_alrm; 242 243 ASSERT(MUTEX_HELD(&tod_lock)); 244 245 /* A delay of zero is not allowed */ 246 if (nsecs == 0) 247 return; 248 249 /* Make sure that we delay no less than the minimum time */ 250 if (nsecs < clock_min_alarm) 251 nsecs = clock_min_alarm; 252 253 if (todpc_rtcget((unsigned char *)&rtc)) 254 return; 255 256 /* 257 * Compute alarm secs, mins and hrs, and where appropriate, dom 258 * and mon. rtc bytes are in binary-coded decimal, so we have 259 * to convert. 260 */ 261 delta = nsecs + BCD_TO_BYTE(rtc.rtc_sec); 262 asec = delta % 60; 263 264 delta = (delta / 60) + BCD_TO_BYTE(rtc.rtc_min); 265 amin = delta % 60; 266 267 delta = (delta / 60) + BCD_TO_BYTE(rtc.rtc_hr); 268 ahr = delta % 24; 269 270 if (day_alrm == 0 && delta >= 24) { 271 prom_printf("No day alarm - set to end of today!\n"); 272 asec = 59; 273 amin = 59; 274 ahr = 23; 275 } else { 276 int mon = BCD_TO_BYTE(rtc.rtc_mon); 277 static int dpm[] = 278 {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 279 280 adom = (delta / 24) + BCD_TO_BYTE(rtc.rtc_dom); 281 282 if (mon_alrm == 0) { 283 if (adom > dpm[mon]) { 284 prom_printf("No mon alarm - " 285 "set to end of current month!\n"); 286 asec = 59; 287 amin = 59; 288 ahr = 23; 289 adom = dpm[mon]; 290 } 291 } else { 292 for (amon = mon; 293 amon <= 12 && adom > dpm[amon]; amon++) { 294 adom -= dpm[amon]; 295 } 296 if (amon > 12) { 297 prom_printf("Alarm too far in future - " 298 "set to end of current year!\n"); 299 asec = 59; 300 amin = 59; 301 ahr = 23; 302 adom = dpm[12]; 303 amon = 12; 304 } 305 rtc.rtc_amon = BYTE_TO_BCD(amon); 306 } 307 308 rtc.rtc_adom = BYTE_TO_BCD(adom); 309 } 310 311 rtc.rtc_asec = BYTE_TO_BCD(asec); 312 rtc.rtc_amin = BYTE_TO_BCD(amin); 313 rtc.rtc_ahr = BYTE_TO_BCD(ahr); 314 315 rtc.rtc_statusb |= RTC_AIE; /* Enable alarm interrupt */ 316 317 todpc_rtcput((unsigned char *)&rtc); 318 } 319 320 /* 321 * Clear an alarm. This is effectively setting an alarm of 0. 322 */ 323 void 324 /*ARGSUSED*/ 325 todpc_clralarm(tod_ops_t *top) 326 { 327 mutex_enter(&tod_lock); 328 todpc_setalarm(top, 0); 329 mutex_exit(&tod_lock); 330 } 331 332 /* 333 * Routine to read contents of real time clock to the specified buffer. 334 * Returns ENXIO if clock not valid, or EAGAIN if clock data cannot be read 335 * else 0. 336 * Some RTC hardware is very slow at asserting the validity flag on 337 * startup. The routine will busy wait for the RTC to become valid. 338 * The routine will also busy wait for the Update-In-Progress flag to clear. 339 * On completion of the reads the Seconds register is re-read and the 340 * UIP flag is rechecked to confirm that an clock update did not occur 341 * during the accesses. Routine will error exit after 256 attempts. 342 * (See bugid 1158298.) 343 * Routine returns RTC_NREG (which is 15) bytes of data, as given in the 344 * technical reference. This data includes both time and status registers. 345 */ 346 347 static int 348 todpc_rtcget(unsigned char *buf) 349 { 350 unsigned char reg; 351 int i; 352 int uip_try = 256; 353 int vrt_try = 512; 354 unsigned char *rawp; 355 unsigned char century = RTC_CENTURY; 356 unsigned char day_alrm; 357 unsigned char mon_alrm; 358 359 ASSERT(MUTEX_HELD(&tod_lock)); 360 361 day_alrm = pc_rtc_offset.day_alrm; 362 mon_alrm = pc_rtc_offset.mon_alrm; 363 if (pc_rtc_offset.century != 0) { 364 century = pc_rtc_offset.century; 365 } 366 367 for (;;) { 368 if (vrt_try-- < 0) 369 return (ENXIO); 370 outb(RTC_ADDR, RTC_D); /* check if clock valid */ 371 reg = inb(RTC_DATA); 372 if ((reg & RTC_VRT) != 0) 373 break; 374 drv_usecwait(5000); /* Delay for 5000 us */ 375 } 376 377 378 checkuip: 379 if (uip_try-- < 0) 380 return (EAGAIN); 381 outb(RTC_ADDR, RTC_A); /* check if update in progress */ 382 reg = inb(RTC_DATA); 383 if (reg & RTC_UIP) { 384 tenmicrosec(); 385 goto checkuip; 386 } 387 388 for (i = 0, rawp = buf; i < RTC_NREG; i++) { 389 outb(RTC_ADDR, i); 390 *rawp++ = inb(RTC_DATA); 391 } 392 outb(RTC_ADDR, century); /* do century */ 393 ((struct rtc_t *)buf)->rtc_century = inb(RTC_DATA); 394 395 if (day_alrm > 0) { 396 outb(RTC_ADDR, day_alrm); 397 ((struct rtc_t *)buf)->rtc_adom = inb(RTC_DATA) & 0x3f; 398 } 399 if (mon_alrm > 0) { 400 outb(RTC_ADDR, mon_alrm); 401 ((struct rtc_t *)buf)->rtc_amon = inb(RTC_DATA); 402 } 403 404 outb(RTC_ADDR, 0); /* re-read Seconds register */ 405 reg = inb(RTC_DATA); 406 if (reg != ((struct rtc_t *)buf)->rtc_sec || 407 (((struct rtc_t *)buf)->rtc_statusa & RTC_UIP)) 408 /* update occured during reads */ 409 goto checkuip; 410 411 return (0); 412 } 413 414 /* 415 * This routine writes the contents of the given buffer to the real time 416 * clock. It is given RTC_NREGP bytes of data, which are the 10 bytes used 417 * to write the time and set the alarm. It should be called with the priority 418 * raised to 5. 419 */ 420 static void 421 todpc_rtcput(unsigned char *buf) 422 { 423 unsigned char reg; 424 int i; 425 unsigned char century = RTC_CENTURY; 426 unsigned char day_alrm = pc_rtc_offset.day_alrm; 427 unsigned char mon_alrm = pc_rtc_offset.mon_alrm; 428 unsigned char tmp; 429 430 if (pc_rtc_offset.century != 0) { 431 century = pc_rtc_offset.century; 432 } 433 434 outb(RTC_ADDR, RTC_B); 435 reg = inb(RTC_DATA); 436 outb(RTC_ADDR, RTC_B); 437 outb(RTC_DATA, reg | RTC_SET); /* allow time set now */ 438 for (i = 0; i < RTC_NREGP; i++) { /* set the time */ 439 outb(RTC_ADDR, i); 440 outb(RTC_DATA, buf[i]); 441 } 442 outb(RTC_ADDR, century); /* do century */ 443 outb(RTC_DATA, ((struct rtc_t *)buf)->rtc_century); 444 445 if (day_alrm > 0) { 446 outb(RTC_ADDR, day_alrm); 447 /* preserve RTC_VRT bit; some virt envs accept writes there */ 448 tmp = inb(RTC_DATA) & RTC_VRT; 449 tmp |= ((struct rtc_t *)buf)->rtc_adom & ~RTC_VRT; 450 outb(RTC_DATA, tmp); 451 } 452 if (mon_alrm > 0) { 453 outb(RTC_ADDR, mon_alrm); 454 outb(RTC_DATA, ((struct rtc_t *)buf)->rtc_amon); 455 } 456 457 outb(RTC_ADDR, RTC_B); 458 reg = inb(RTC_DATA); 459 outb(RTC_ADDR, RTC_B); 460 outb(RTC_DATA, reg & ~RTC_SET); /* allow time update */ 461 } 462 463 static tod_ops_t todpc_ops = { 464 TOD_OPS_VERSION, 465 todpc_get, 466 todpc_set, 467 NULL, 468 NULL, 469 todpc_setalarm, 470 todpc_clralarm, 471 NULL 472 }; 473 474 /* 475 * Initialize for the default TOD ops vector for use on hardware. 476 */ 477 478 tod_ops_t *tod_ops = &todpc_ops; 479