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;