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 2008 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 
  27 /*
  28  *      The "todds1287" module has implementation for both tod
  29  *      and power button (pbio) interfaces.  This driver controls
  30  *      RTC & APC units of National Semiconductor's 87317 SuperI/O
  31  *      chip.  The tod interface accesses the RTC unit and pbio
  32  *      interface accesses the APC unit of SuperI/O.  Since both
  33  *      units are implemented in the same Logical Device, registers
  34  *      for both units are accessible through a common set of index
  35  *      address & data registers.  That is why both interfaces are
  36  *      implemented in a same driver.
  37  *
  38  *      The APC unit is used to implement the power button.  When the
  39  *      button momentarily is pressed, an interrupt is generated and
  40  *      at the same time a Fail-safe timer starts to run.  If the
  41  *      timer is not stopped in 21 seconds, the power to system is
  42  *      turned off.  So the first task in the interrupt handler is to
  43  *      reset the Fail-safe timer.  Note that OBP is not clearing
  44  *      the Fail-safe timer due to limitation in handling interrupts,
  45  *      so when OBP is running, the power button should be pressed
  46  *      and held for 4 seconds for the power to go off, otherwise
  47  *      a momentarily press will delay the power-off for 21 seconds.
  48  *
  49  *      PSARC/1999/393 describes the pbio(7I) interface.
  50  */
  51 
  52 #include <sys/types.h>
  53 #include <sys/conf.h>
  54 #include <sys/kmem.h>
  55 #include <sys/open.h>
  56 #include <sys/ddi.h>
  57 #include <sys/sunddi.h>
  58 
  59 #include <sys/todds1287.h>
  60 #include <sys/modctl.h>
  61 #include <sys/stat.h>
  62 #include <sys/clock.h>
  63 #include <sys/reboot.h>
  64 #include <sys/machsystm.h>
  65 #include <sys/poll.h>
  66 #include <sys/pbio.h>
  67 
  68 #define ABORT_INCREMENT_DELAY   10
  69 
  70 static timestruc_t todds_get(void);
  71 static void todds_set(timestruc_t);
  72 static uint_t todds_set_watchdog_timer(uint_t);
  73 static uint_t todds_clear_watchdog_timer(void);
  74 static void todds_set_power_alarm(timestruc_t);
  75 static void todds_clear_power_alarm(void);
  76 static uint64_t todds_get_cpufrequency(void);
  77 
  78 extern uint64_t find_cpufrequency(volatile uint8_t *);
  79 
  80 /*
  81  * External variables
  82  */
  83 extern int      watchdog_activated;
  84 extern uint_t   watchdog_timeout_seconds;
  85 extern volatile uint8_t *v_pmc_addr_reg;
  86 
  87 /*
  88  * Global variables
  89  */
  90 int ds1287_debug_flags;
  91 int ds1287_caddr_warn;
  92 
  93 /*
  94  * cb ops
  95  */
  96 static int ds1287_open(dev_t *, int, int, cred_t *);
  97 static int ds1287_close(dev_t, int, int, cred_t *);
  98 static int ds1287_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
  99 static int ds1287_chpoll(dev_t, short, int, short *, struct pollhead **);
 100 
 101 static void read_rtc(struct rtc_t *);
 102 static void write_rtc_time(struct rtc_t *);
 103 static void write_rtc_alarm(struct rtc_t *);
 104 static void select_bank(int bank);
 105 static uint_t ds1287_intr(caddr_t);
 106 static uint_t ds1287_softintr(caddr_t);
 107 static void ds1287_timeout(caddr_t);
 108 static uint_t ds1287_issue_shutdown(caddr_t);
 109 static void ds1287_log_message(void);
 110 
 111 static struct cb_ops ds1287_cbops = {
 112         ds1287_open,                    /* open */
 113         ds1287_close,                   /* close */
 114         nodev,                          /* strategy */
 115         nodev,                          /* print */
 116         nodev,                          /* dump */
 117         nodev,                          /* read */
 118         nodev,                          /* write */
 119         ds1287_ioctl,                   /* ioctl */
 120         nodev,                          /* devmap */
 121         nodev,                          /* mmap */
 122         nodev,                          /* segmap */
 123         ds1287_chpoll,                  /* poll */
 124         ddi_prop_op,                    /* cb_prop_op */
 125         NULL,                           /* streamtab */
 126         D_NEW | D_MP,                   /* Driver compatibility flag */
 127         CB_REV,                         /* rev */
 128         nodev,                          /* int (*cb_aread)() */
 129         nodev                           /* int (*cb_awrite)() */
 130 };
 131 
 132 /*
 133  * dev ops
 134  */
 135 static int ds1287_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
 136 static int ds1287_attach(dev_info_t *, ddi_attach_cmd_t);
 137 static int ds1287_detach(dev_info_t *, ddi_detach_cmd_t);
 138 
 139 static struct dev_ops ds1287_ops = {
 140         DEVO_REV,                       /* devo_rev */
 141         0,                              /* refcnt */
 142         ds1287_getinfo,                 /* getinfo */
 143         nulldev,                        /* identify */
 144         nulldev,                        /* probe */
 145         ds1287_attach,                  /* attach */
 146         ds1287_detach,                  /* detach */
 147         nodev,                          /* reset */
 148         &ds1287_cbops,                      /* cb_ops */
 149         (struct bus_ops *)NULL,         /* bus_ops */
 150         NULL,                           /* power */
 151         ddi_quiesce_not_supported,      /* devo_quiesce */
 152 };
 153 
 154 
 155 static void     *ds1287_state;
 156 static int      instance = -1;
 157 
 158 /* Driver Tunables */
 159 static int      ds1287_interrupt_priority = 15;
 160 static int      ds1287_softint_priority = 2;
 161 static hrtime_t power_button_debounce = MSEC2NSEC(10);
 162 static hrtime_t power_button_abort_interval = 1.5 * NANOSEC;
 163 static int      power_button_abort_presses = 3;
 164 static int      power_button_abort_enable = 1;
 165 static int      power_button_enable = 1;
 166 
 167 static int      power_button_pressed = 0;
 168 static int      power_button_cancel = 0;
 169 static int      power_button_timeouts = 0;
 170 static int      timeout_cancel = 0;
 171 static int      additional_presses = 0;
 172 
 173 static ddi_iblock_cookie_t ds1287_lo_iblock;
 174 static ddi_iblock_cookie_t ds1287_hi_iblock;
 175 static ddi_softintr_t   ds1287_softintr_id;
 176 static kmutex_t ds1287_reg_mutex;       /* Protects ds1287 Registers */
 177 
 178 static struct modldrv modldrv = {
 179         &mod_driverops,     /* Type of module. This one is a driver */
 180         "ds1287 clock driver",  /* Name of the module. */
 181         &ds1287_ops,                /* driver ops */
 182 };
 183 
 184 static struct modlinkage modlinkage = {
 185         MODREV_1, &modldrv, NULL
 186 };
 187 
 188 
 189 int
 190 _init(void)
 191 {
 192         int status;
 193 
 194         status = ddi_soft_state_init(&ds1287_state, sizeof (struct ds1287), 0);
 195         if (status != 0) {
 196                 return (status);
 197         }
 198 
 199         if ((status = mod_install(&modlinkage)) != 0) {
 200                 ddi_soft_state_fini(&ds1287_state);
 201                 return (status);
 202         }
 203 
 204 
 205         ds1287_hi_iblock = (ddi_iblock_cookie_t)(uintptr_t)
 206             ipltospl(ds1287_interrupt_priority);
 207         mutex_init(&ds1287_reg_mutex, NULL, MUTEX_DRIVER, ds1287_hi_iblock);
 208 
 209         mutex_enter(&ds1287_reg_mutex);
 210         /* Select Bank 1 */
 211         select_bank(1);
 212         DS1287_ADDR_REG = RTC_B;
 213         DS1287_DATA_REG = (RTC_DM | RTC_HM);
 214         mutex_exit(&ds1287_reg_mutex);
 215 
 216         tod_ops.tod_get = todds_get;
 217         tod_ops.tod_set = todds_set;
 218 
 219         /*
 220          * If v_pmc_addr_reg isn't set, it's because it wasn't set in
 221          * sun4u/os/fillsysinfo.c:have_pmc(). This means the real (pmc)
 222          * watchdog routines (sun4u/io/pmc.c) will not be used. If the
 223          * user were to set watchdog_enable in /etc/system, we'll need to
 224          * use our own NOP routines.
 225          */
 226         if (v_pmc_addr_reg == NULL) {
 227                 tod_ops.tod_set_watchdog_timer = todds_set_watchdog_timer;
 228                 tod_ops.tod_clear_watchdog_timer = todds_clear_watchdog_timer;
 229         }
 230         tod_ops.tod_set_power_alarm = todds_set_power_alarm;
 231         tod_ops.tod_clear_power_alarm = todds_clear_power_alarm;
 232         tod_ops.tod_get_cpufrequency = todds_get_cpufrequency;
 233 
 234         return (status);
 235 }
 236 
 237 int
 238 _fini(void)
 239 {
 240         if (strcmp(tod_module_name, "todds1287") == 0)
 241                 return (EBUSY);
 242 
 243         return (mod_remove(&modlinkage));
 244 }
 245 
 246 /*
 247  * The loadable-module _info(9E) entry point
 248  */
 249 int
 250 _info(struct modinfo *modinfop)
 251 {
 252         return (mod_info(&modlinkage, modinfop));
 253 }
 254 
 255 /*ARGSUSED*/
 256 static int
 257 ds1287_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
 258     void **result)
 259 {
 260         struct ds1287 *softsp;
 261 
 262         if (instance == -1)
 263                 return (DDI_FAILURE);
 264 
 265         switch (infocmd) {
 266         case DDI_INFO_DEVT2DEVINFO:
 267                 if ((softsp = ddi_get_soft_state(ds1287_state, instance))
 268                     == NULL)
 269                         return (DDI_FAILURE);
 270                 *result = (void *)softsp->dip;
 271                 return (DDI_SUCCESS);
 272 
 273         case DDI_INFO_DEVT2INSTANCE:
 274                 *result = (void *)(uintptr_t)instance;
 275                 return (DDI_SUCCESS);
 276 
 277         default:
 278                 return (DDI_FAILURE);
 279         }
 280 }
 281 
 282 static int
 283 ds1287_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 284 {
 285         struct ds1287 *softsp;
 286 
 287         DPRINTF("ds1287_attach\n");
 288         switch (cmd) {
 289         case DDI_ATTACH:
 290                 break;
 291         case DDI_RESUME:
 292                 return (DDI_SUCCESS);
 293         default:
 294                 return (DDI_FAILURE);
 295         }
 296 
 297         if (instance != -1) {
 298                 cmn_err(CE_WARN, "ds1287_attach: Another instance is already "
 299                     "attached.");
 300                 return (DDI_FAILURE);
 301         }
 302 
 303         instance = ddi_get_instance(dip);
 304 
 305         if (v_rtc_addr_reg == NULL) {
 306                 cmn_err(CE_WARN, "ds1287_attach: v_rtc_addr_reg is NULL");
 307                 return (DDI_FAILURE);
 308         }
 309 
 310         /*
 311          * Allocate softc information.
 312          */
 313         if (ddi_soft_state_zalloc(ds1287_state, instance) != DDI_SUCCESS) {
 314                 cmn_err(CE_WARN, "ds1287_attach: Failed to allocate "
 315                     "soft states.");
 316                 return (DDI_FAILURE);
 317         }
 318 
 319         softsp = ddi_get_soft_state(ds1287_state, instance);
 320         DPRINTF("ds1287_attach: instance=%d softsp=0x%p\n", instance,
 321             (void *)softsp);
 322 
 323         softsp->dip = dip;
 324 
 325         if (ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP,
 326             "interrupt-priorities", (caddr_t)&ds1287_interrupt_priority,
 327             sizeof (int)) != DDI_PROP_SUCCESS) {
 328                 cmn_err(CE_WARN, "ds1287_attach: Failed to create \""
 329                     "interrupt-priorities\" property.");
 330                 goto error;
 331         }
 332 
 333         /* add the softint */
 334         ds1287_lo_iblock = (ddi_iblock_cookie_t)(uintptr_t)
 335             ipltospl(ds1287_softint_priority);
 336 
 337         if (ddi_add_softintr(dip, DDI_SOFTINT_FIXED, &ds1287_softintr_id,
 338             &ds1287_lo_iblock, NULL, ds1287_softintr, (caddr_t)softsp) !=
 339             DDI_SUCCESS) {
 340                 cmn_err(CE_WARN, "ds1287_attach: Failed to add low interrupt.");
 341                 goto error1;
 342         }
 343 
 344         /* add the hi interrupt */
 345         if (ddi_add_intr(dip, 0, NULL, (ddi_idevice_cookie_t *)
 346             &ds1287_hi_iblock, ds1287_intr, NULL) != DDI_SUCCESS) {
 347                 cmn_err(CE_WARN, "ds1287_attach: Failed to add high "
 348                     "interrupt.");
 349                 goto error2;
 350         }
 351 
 352         /*
 353          * Combination of instance number and clone number 0 is used for
 354          * creating the minor node.
 355          */
 356         if (ddi_create_minor_node(dip, "power_button", S_IFCHR,
 357             (instance << 8) + 0, "ddi_power_button", NULL) == DDI_FAILURE) {
 358                 cmn_err(CE_WARN, "ds1287_attach: Failed to create minor node");
 359                 goto error3;
 360         }
 361 
 362         ddi_report_dev(dip);
 363 
 364         return (DDI_SUCCESS);
 365 
 366 error3:
 367         ddi_remove_intr(dip, 0, NULL);
 368 error2:
 369         ddi_remove_softintr(ds1287_softintr_id);
 370 error1:
 371         (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "interrupt-priorities");
 372 error:
 373         ddi_soft_state_free(ds1287_state, instance);
 374         return (DDI_FAILURE);
 375 }
 376 
 377 /*ARGSUSED*/
 378 static int
 379 ds1287_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 380 {
 381         DPRINTF("ds1287_detach\n");
 382         switch (cmd) {
 383         case DDI_DETACH:
 384                 /*
 385                  * Since it needs to always handle the power button, fail
 386                  * to detach.
 387                  */
 388                 return (DDI_FAILURE);
 389         case DDI_SUSPEND:
 390                 return (DDI_SUCCESS);
 391         default:
 392                 return (DDI_FAILURE);
 393         }
 394 }
 395 
 396 /*ARGSUSED1*/
 397 static int
 398 ds1287_open(dev_t *devp, int flags, int otyp, cred_t *credp)
 399 {
 400         struct ds1287 *softsp;
 401         int clone;
 402 
 403         if (otyp != OTYP_CHR)
 404                 return (EINVAL);
 405 
 406         if ((softsp = ddi_get_soft_state(ds1287_state, instance)) ==
 407             NULL)
 408                 return (ENXIO);
 409 
 410         mutex_enter(&softsp->ds1287_mutex);
 411         for (clone = 1; clone < DS1287_MAX_CLONE; clone++)
 412                 if (!softsp->clones[clone])
 413                         break;
 414 
 415         if (clone == DS1287_MAX_CLONE) {
 416                 cmn_err(CE_WARN, "ds1287_open: No more allocation left "
 417                     "to clone a minor.");
 418                 mutex_exit(&softsp->ds1287_mutex);
 419                 return (ENXIO);
 420         }
 421 
 422         *devp = makedevice(getmajor(*devp), (instance << 8) + clone);
 423         softsp->clones[clone] = 1;
 424         mutex_exit(&softsp->ds1287_mutex);
 425 
 426         return (0);
 427 }
 428 
 429 /*ARGSUSED*/
 430 static int
 431 ds1287_close(dev_t dev, int flags, int otyp, cred_t *credp)
 432 {
 433         struct ds1287 *softsp;
 434         int clone;
 435 
 436         if (otyp != OTYP_CHR)
 437                 return (EINVAL);
 438 
 439         if ((softsp = ddi_get_soft_state(ds1287_state, instance)) ==
 440             NULL)
 441                 return (ENXIO);
 442 
 443         clone = DS1287_MINOR_TO_CLONE(getminor(dev));
 444         mutex_enter(&softsp->ds1287_mutex);
 445         if (softsp->monitor_on == clone)
 446                 softsp->monitor_on = 0;
 447         softsp->clones[clone] = 0;
 448         mutex_exit(&softsp->ds1287_mutex);
 449 
 450         return (0);
 451 }
 452 
 453 /*ARGSUSED4*/
 454 static int
 455 ds1287_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
 456         cred_t *credp, int *rvalp)
 457 {
 458         struct ds1287 *softsp;
 459         int clone;
 460 
 461         if ((softsp = ddi_get_soft_state(ds1287_state, instance)) ==
 462             NULL)
 463                 return (ENXIO);
 464 
 465         clone = DS1287_MINOR_TO_CLONE(getminor(dev));
 466         switch (cmd) {
 467         case PB_BEGIN_MONITOR:
 468                 DPRINTF("ds1287_ioctl: PB_BEGIN_MONITOR is called.\n");
 469                 mutex_enter(&softsp->ds1287_mutex);
 470                 if (softsp->monitor_on) {
 471                         mutex_exit(&softsp->ds1287_mutex);
 472                         return (EBUSY);
 473                 }
 474                 softsp->monitor_on = clone;
 475                 mutex_exit(&softsp->ds1287_mutex);
 476                 return (0);
 477 
 478         case PB_END_MONITOR:
 479                 DPRINTF("ds1287_ioctl: PB_END_MONITOR is called.\n");
 480                 mutex_enter(&softsp->ds1287_mutex);
 481 
 482                 /*
 483                  * If PB_END_MONITOR is called without first
 484                  * calling PB_BEGIN_MONITOR, an error will be
 485                  * returned.
 486                  */
 487                 if (!softsp->monitor_on) {
 488                         mutex_exit(&softsp->ds1287_mutex);
 489                         return (ENXIO);
 490                 }
 491 
 492                 /*
 493                  * This clone is not monitoring the button.
 494                  */
 495                 if (softsp->monitor_on != clone) {
 496                         mutex_exit(&softsp->ds1287_mutex);
 497                         return (EINVAL);
 498                 }
 499                 softsp->monitor_on = 0;
 500                 mutex_exit(&softsp->ds1287_mutex);
 501                 return (0);
 502 
 503         case PB_GET_EVENTS:
 504                 DPRINTF("ds1287_ioctl: PB_GET_EVENTS is called.\n");
 505                 mutex_enter(&softsp->ds1287_mutex);
 506                 if (ddi_copyout((void *)&softsp->events, (void *)arg,
 507                     sizeof (int), mode) != 0) {
 508                         mutex_exit(&softsp->ds1287_mutex);
 509                         return (EFAULT);
 510                 }
 511 
 512                 /*
 513                  * This ioctl returned the events detected since last
 514                  * call.  Note that any application can get the events
 515                  * and clear the event register.
 516                  */
 517                 softsp->events = 0;
 518                 mutex_exit(&softsp->ds1287_mutex);
 519                 return (0);
 520 
 521         /*
 522          * This ioctl is used by the test suite.
 523          */
 524         case PB_CREATE_BUTTON_EVENT:
 525                 DPRINTF("ds1287_ioctl: PB_CREATE_BUTTON_EVENT is called.\n");
 526                 (void) ds1287_intr(NULL);
 527                 return (0);
 528 
 529         default:
 530                 return (ENOTTY);
 531         }
 532 }
 533 
 534 /*ARGSUSED*/
 535 static int
 536 ds1287_chpoll(dev_t dev, short events, int anyyet,
 537     short *reventsp, struct pollhead **phpp)
 538 {
 539         struct ds1287 *softsp;
 540 
 541         if ((softsp = ddi_get_soft_state(ds1287_state, instance)) == NULL)
 542                 return (ENXIO);
 543 
 544         mutex_enter(&softsp->ds1287_mutex);
 545         *reventsp = 0;
 546         if (softsp->events)
 547                 *reventsp = POLLRDNORM|POLLIN;
 548         else {
 549                 if (!anyyet)
 550                         *phpp = &softsp->pollhd;
 551         }
 552         mutex_exit(&softsp->ds1287_mutex);
 553 
 554         return (0);
 555 }
 556 
 557 static void
 558 ds1287_log_message(void)
 559 {
 560         struct ds1287 *softsp;
 561 
 562         if ((softsp = ddi_get_soft_state(ds1287_state, instance)) == NULL) {
 563                 cmn_err(CE_WARN, "ds1287: Failed to get internal state!");
 564                 return;
 565         }
 566 
 567         mutex_enter(&softsp->ds1287_mutex);
 568         softsp->shutdown_pending = 0;
 569         cmn_err(CE_WARN, "ds1287: Failed to shut down the system!");
 570         mutex_exit(&softsp->ds1287_mutex);
 571 }
 572 
 573 /*
 574  * To facilitate a power button abort, ds1287_intr() now posts
 575  * a softint (calling ds1287_softintr()) for all power button presses and
 576  * counts the number of button presses. An abort is issued if the desired
 577  * number of button presses within the given time interval.
 578  *
 579  * Two variables are used to synchronize between the high level intr;
 580  * the softint handler and timeout handler
 581  *
 582  * power_button_cancel  - Indicates that an abort happened and the number
 583  *                        of outstanding timeouts that have to be cancelled
 584  *
 585  * power_button_pressed - Indicates the number of button presses outstanding
 586  *                        which have not been serviced
 587  */
 588 /*ARGSUSED*/
 589 static uint_t
 590 ds1287_intr(caddr_t ignore)
 591 {
 592         hrtime_t tstamp;
 593         static hrtime_t o_tstamp = 0;
 594         static hrtime_t power_button_tstamp = 0;
 595         static int power_button_cnt;
 596         uint8_t apcr1;
 597 
 598         /*
 599          * Stop the Fail-safe timer that starts running
 600          * after power button is pressed.  If it is not
 601          * stopped in 21 seconds, system powers off.
 602          */
 603         mutex_enter(&ds1287_reg_mutex);
 604         select_bank(2);
 605         DS1287_ADDR_REG = APC_APCR1;
 606         apcr1 = DS1287_DATA_REG;
 607         apcr1 |= APC_FSTRC;
 608         DS1287_DATA_REG = apcr1;
 609         select_bank(1);
 610         mutex_exit(&ds1287_reg_mutex);
 611 
 612         tstamp = gethrtime();
 613 
 614         /* need to deal with power button debounce */
 615         if (o_tstamp && (tstamp - o_tstamp) < power_button_debounce) {
 616                 o_tstamp = tstamp;
 617                 return (DDI_INTR_CLAIMED);
 618         }
 619         o_tstamp = tstamp;
 620 
 621         power_button_cnt++;
 622 
 623         mutex_enter(&ds1287_reg_mutex);
 624         power_button_pressed++;
 625         mutex_exit(&ds1287_reg_mutex);
 626 
 627         /*
 628          * If power button abort is enabled and power button was pressed
 629          * power_button_abort_presses times within power_button_abort_interval
 630          * then call abort_sequence_enter();
 631          */
 632         if (power_button_abort_enable) {
 633                 if (power_button_abort_presses == 1 ||
 634                     tstamp < (power_button_tstamp +
 635                     power_button_abort_interval)) {
 636                         if (power_button_cnt == power_button_abort_presses) {
 637                                 mutex_enter(&ds1287_reg_mutex);
 638                                 power_button_cancel += power_button_timeouts;
 639                                 power_button_pressed = 0;
 640                                 mutex_exit(&ds1287_reg_mutex);
 641                                 power_button_cnt = 0;
 642                                 abort_sequence_enter("Power Button Abort");
 643                                 return (DDI_INTR_CLAIMED);
 644                         }
 645                 } else {
 646                         power_button_cnt = 1;
 647                         power_button_tstamp = tstamp;
 648                 }
 649         }
 650 
 651         if (!power_button_enable)
 652                 return (DDI_INTR_CLAIMED);
 653 
 654         /* post softint to issue timeout for power button action */
 655         ddi_trigger_softintr(ds1287_softintr_id);
 656 
 657         return (DDI_INTR_CLAIMED);
 658 }
 659 
 660 /*
 661  * Handle the softints....
 662  *
 663  * If only one softint is posted for several button presses, record
 664  * the number of additional presses just incase this was actually not quite
 665  * an Abort sequence so that we can log this event later.
 666  *
 667  * Issue a timeout with a duration being a fraction larger than
 668  * the specified Abort interval inorder to perform a power down if required.
 669  */
 670 static uint_t
 671 ds1287_softintr(caddr_t arg)
 672 {
 673         struct ds1287 *softsp = (struct ds1287 *)arg;
 674 
 675         DPRINTF("ds1287_softintr\n");
 676 
 677         if (!power_button_abort_enable)
 678                 return (ds1287_issue_shutdown(arg));
 679 
 680         mutex_enter(&ds1287_reg_mutex);
 681         if (!power_button_pressed) {
 682                 mutex_exit(&ds1287_reg_mutex);
 683                 return (DDI_INTR_CLAIMED);
 684         }
 685 
 686         /*
 687          * Schedule a timeout to do the necessary
 688          * work for shutdown, only one timeout for
 689          * n presses if power button was pressed
 690          * more than once before softint fired
 691          */
 692         if (power_button_pressed > 1)
 693                 additional_presses += power_button_pressed - 1;
 694 
 695         timeout_cancel = 0;
 696         power_button_pressed = 0;
 697         power_button_timeouts++;
 698         mutex_exit(&ds1287_reg_mutex);
 699         (void) timeout((void(*)(void *))ds1287_timeout,
 700             softsp, NSEC_TO_TICK(power_button_abort_interval) +
 701             ABORT_INCREMENT_DELAY);
 702 
 703         return (DDI_INTR_CLAIMED);
 704 }
 705 
 706 /*
 707  * Upon receiving a timeout the following is determined:
 708  *
 709  * If an  Abort sequence was issued, then we cancel all outstanding timeouts
 710  * and additional presses prior to the Abort sequence.
 711  *
 712  * If we had multiple timeouts issued and the abort sequence was not met,
 713  * then we had more than one button press to power down the machine. We
 714  * were probably trying to issue an abort. So log a message indicating this
 715  * and cancel all outstanding timeouts.
 716  *
 717  * If we had just one timeout and the abort sequence was not met then
 718  * we really did want to power down the machine, so call ds1287_issue_shutdown()
 719  * to do the work and schedule a power down
 720  */
 721 static void
 722 ds1287_timeout(caddr_t arg)
 723 {
 724         static int first = 0;
 725 
 726         DPRINTF("ds1287_timeout\n");
 727 
 728         /*
 729          * Abort was generated cancel all outstanding power
 730          * button timeouts
 731          */
 732         mutex_enter(&ds1287_reg_mutex);
 733         if (power_button_cancel) {
 734                 power_button_cancel--;
 735                 power_button_timeouts--;
 736                 if (!first) {
 737                         first++;
 738                         additional_presses = 0;
 739                 }
 740                 mutex_exit(&ds1287_reg_mutex);
 741                 return;
 742         }
 743         first = 0;
 744 
 745         /*
 746          * We get here if the timeout(s) have fired and they were
 747          * not issued prior to an abort.
 748          *
 749          * If we had more than one press in the interval we were
 750          * probably trying to issue an abort, but didnt press the
 751          * required number within the interval. Hence cancel all
 752          * timeouts and do not continue towards shutdown.
 753          */
 754         if (!timeout_cancel) {
 755                 timeout_cancel = power_button_timeouts +
 756                     additional_presses;
 757 
 758                 power_button_timeouts--;
 759                 if (!power_button_timeouts)
 760                         additional_presses = 0;
 761 
 762                 if (timeout_cancel > 1) {
 763                         mutex_exit(&ds1287_reg_mutex);
 764                         cmn_err(CE_NOTE, "Power Button pressed "
 765                             "%d times, cancelling all requests",
 766                             timeout_cancel);
 767                         return;
 768                 }
 769                 mutex_exit(&ds1287_reg_mutex);
 770 
 771                 /* Go and do the work to request shutdown */
 772                 (void) ds1287_issue_shutdown(arg);
 773                 return;
 774         }
 775 
 776         power_button_timeouts--;
 777         if (!power_button_timeouts)
 778                 additional_presses = 0;
 779         mutex_exit(&ds1287_reg_mutex);
 780 }
 781 
 782 static uint_t
 783 ds1287_issue_shutdown(caddr_t arg)
 784 {
 785         struct ds1287 *softsp = (struct ds1287 *)arg;
 786 
 787         DPRINTF("ds1287_issue_shutdown\n");
 788 
 789         mutex_enter(&softsp->ds1287_mutex);
 790         softsp->events |= PB_BUTTON_PRESS;
 791         if (softsp->monitor_on != 0) {
 792                 mutex_exit(&softsp->ds1287_mutex);
 793                 pollwakeup(&softsp->pollhd, POLLRDNORM);
 794                 pollwakeup(&softsp->pollhd, POLLIN);
 795                 return (DDI_INTR_CLAIMED);
 796         }
 797 
 798         if (!softsp->shutdown_pending) {
 799                 cmn_err(CE_WARN, "Power button is pressed, powering down "
 800                     "the system!");
 801                 softsp->shutdown_pending = 1;
 802                 do_shutdown();
 803 
 804                 /*
 805                  * Wait a while for "do_shutdown()" to shut down the system
 806                  * before logging an error message.
 807                  */
 808                 (void) timeout((void(*)(void *))ds1287_log_message, NULL,
 809                     100 * hz);
 810         }
 811         mutex_exit(&softsp->ds1287_mutex);
 812 
 813         return (DDI_INTR_CLAIMED);
 814 }
 815 
 816 /*
 817  * Read the current time from the clock chip and convert to UNIX form.
 818  * Assumes that the year in the clock chip is valid.
 819  * Must be called with tod_lock held.
 820  */
 821 static timestruc_t
 822 todds_get(void)
 823 {
 824         timestruc_t ts;
 825         todinfo_t tod;
 826         struct rtc_t rtc;
 827 
 828         ASSERT(MUTEX_HELD(&tod_lock));
 829 
 830         read_rtc(&rtc);
 831         DPRINTF("todds_get: century=%d year=%d dom=%d hrs=%d\n",
 832             rtc.rtc_century, rtc.rtc_year, rtc.rtc_dom, rtc.rtc_hrs);
 833 
 834         /*
 835          * tod_year is base 1900 so this code needs to adjust the true
 836          * year retrieved from the rtc's century and year fields.
 837          */
 838         tod.tod_year    = rtc.rtc_year + (rtc.rtc_century * 100) - 1900;
 839         tod.tod_month   = rtc.rtc_mon;
 840         tod.tod_day     = rtc.rtc_dom;
 841         tod.tod_dow     = rtc.rtc_dow;
 842         tod.tod_hour    = rtc.rtc_hrs;
 843         tod.tod_min     = rtc.rtc_min;
 844         tod.tod_sec     = rtc.rtc_sec;
 845 
 846         ts.tv_sec = tod_to_utc(tod);
 847         ts.tv_nsec = 0;
 848 
 849         /* set the hw watchdog timer if it's been activated */
 850         if (watchdog_activated) {
 851                 int ret = 0;
 852                 ret = tod_ops.tod_set_watchdog_timer(watchdog_timeout_seconds);
 853                 if (ret == 0)
 854                         cmn_err(CE_WARN, "ds1287: failed to set hardware "
 855                             "watchdog timer.");
 856         }
 857 
 858         return (ts);
 859 }
 860 
 861 void
 862 read_rtc(struct rtc_t *rtc)
 863 {
 864         uint8_t regb;
 865 
 866         /*
 867          * Some SuperIO tod devices don't seem to properly initialize
 868          * the CADDR register to place the Century register at bank 1
 869          * address 0x48.
 870          */
 871         mutex_enter(&ds1287_reg_mutex);
 872 
 873         select_bank(2);
 874         DS1287_ADDR_REG = RTC_CADDR;
 875         regb = DS1287_DATA_REG;
 876         if (regb != 0xc8) {
 877                 if (!ds1287_caddr_warn) {
 878                         ds1287_caddr_warn = 1;
 879                         cmn_err(CE_WARN, "ds1287: century address register "
 880                             "incorrect (exp 0xc8, obs %x)", regb);
 881                 }
 882                 DS1287_DATA_REG = 0xc8;
 883         }
 884 
 885         select_bank(1);
 886         /*
 887          * Freeze clock update
 888          */
 889         DS1287_ADDR_REG = RTC_B;
 890         regb = DS1287_DATA_REG;
 891         DS1287_DATA_REG = (regb | RTC_SET);
 892 
 893         DS1287_ADDR_REG = RTC_SEC;
 894         rtc->rtc_sec = DS1287_DATA_REG;
 895         DS1287_ADDR_REG = RTC_ASEC;
 896         rtc->rtc_asec = DS1287_DATA_REG;
 897         DS1287_ADDR_REG = RTC_MIN;
 898         rtc->rtc_min = DS1287_DATA_REG;
 899         DS1287_ADDR_REG = RTC_AMIN;
 900         rtc->rtc_amin = DS1287_DATA_REG;
 901         DS1287_ADDR_REG = RTC_HRS;
 902         rtc->rtc_hrs = DS1287_DATA_REG;
 903         DS1287_ADDR_REG = RTC_AHRS;
 904         rtc->rtc_ahrs = DS1287_DATA_REG;
 905         DS1287_ADDR_REG = RTC_DOW;
 906         rtc->rtc_dow = DS1287_DATA_REG;
 907         DS1287_ADDR_REG = RTC_DOM;
 908         rtc->rtc_dom = DS1287_DATA_REG;
 909         DS1287_ADDR_REG = RTC_MON;
 910         rtc->rtc_mon = DS1287_DATA_REG;
 911         DS1287_ADDR_REG = RTC_YEAR;
 912         rtc->rtc_year = DS1287_DATA_REG;
 913         DS1287_ADDR_REG = RTC_CENTURY;
 914         rtc->rtc_century = DS1287_DATA_REG;
 915 
 916         /* Read date alarm */
 917         DS1287_ADDR_REG = RTC_ADOM;
 918         rtc->rtc_adom = DS1287_DATA_REG;
 919         DS1287_ADDR_REG = RTC_AMON;
 920         rtc->rtc_amon = DS1287_DATA_REG;
 921 
 922         /* Read wakeup data */
 923         select_bank(2);
 924         DS1287_ADDR_REG = APC_WDWR;
 925         rtc->apc_wdwr = DS1287_DATA_REG;
 926         DS1287_ADDR_REG = APC_WDMR;
 927         rtc->apc_wdmr = DS1287_DATA_REG;
 928         DS1287_ADDR_REG = APC_WMR;
 929         rtc->apc_wmr = DS1287_DATA_REG;
 930         DS1287_ADDR_REG = APC_WYR;
 931         rtc->apc_wyr = DS1287_DATA_REG;
 932         DS1287_ADDR_REG = APC_WCR;
 933         rtc->apc_wcr = DS1287_DATA_REG;
 934 
 935         /*
 936          * Unfreeze clock update
 937          */
 938         DS1287_ADDR_REG = RTC_B;
 939         DS1287_DATA_REG = regb;
 940 
 941         mutex_exit(&ds1287_reg_mutex);
 942 }
 943 
 944 /*
 945  * Write the specified time into the clock chip.
 946  * Must be called with tod_lock held.
 947  */
 948 static void
 949 todds_set(timestruc_t ts)
 950 {
 951         struct rtc_t    rtc;
 952         todinfo_t tod = utc_to_tod(ts.tv_sec);
 953         int year;
 954 
 955         ASSERT(MUTEX_HELD(&tod_lock));
 956 
 957         /* tod_year is base 1900 so this code needs to adjust */
 958         year = 1900 + tod.tod_year;
 959         rtc.rtc_year    = year % 100;
 960         rtc.rtc_century = year / 100;
 961         rtc.rtc_mon     = (uint8_t)tod.tod_month;
 962         rtc.rtc_dom     = (uint8_t)tod.tod_day;
 963         rtc.rtc_dow     = (uint8_t)tod.tod_dow;
 964         rtc.rtc_hrs     = (uint8_t)tod.tod_hour;
 965         rtc.rtc_min     = (uint8_t)tod.tod_min;
 966         rtc.rtc_sec     = (uint8_t)tod.tod_sec;
 967         DPRINTF("todds_set: century=%d year=%d dom=%d hrs=%d\n",
 968             rtc.rtc_century, rtc.rtc_year, rtc.rtc_dom, rtc.rtc_hrs);
 969 
 970         write_rtc_time(&rtc);
 971 }
 972 
 973 void
 974 write_rtc_time(struct rtc_t *rtc)
 975 {
 976         uint8_t regb;
 977 
 978         /*
 979          * Some SuperIO tod devices don't seem to properly initialize
 980          * the CADDR register to place the Century register at bank 1
 981          * address 0x48.
 982          */
 983         mutex_enter(&ds1287_reg_mutex);
 984 
 985         select_bank(2);
 986         DS1287_ADDR_REG = RTC_CADDR;
 987         regb = DS1287_DATA_REG;
 988         if (regb != 0xc8) {
 989                 if (!ds1287_caddr_warn) {
 990                         ds1287_caddr_warn = 1;
 991                         cmn_err(CE_WARN, "ds1287: century address register "
 992                             "incorrect (exp 0xc8, obs %x)", regb);
 993                 }
 994                 DS1287_DATA_REG = 0xc8;
 995         }
 996 
 997         select_bank(1);
 998 
 999         /*
1000          * Freeze
1001          */
1002         DS1287_ADDR_REG = RTC_B;
1003         regb = DS1287_DATA_REG;
1004 
1005         DS1287_DATA_REG = (regb | RTC_SET);
1006 
1007         DS1287_ADDR_REG = RTC_SEC;
1008         DS1287_DATA_REG = rtc->rtc_sec;
1009         DS1287_ADDR_REG = RTC_MIN;
1010         DS1287_DATA_REG = rtc->rtc_min;
1011         DS1287_ADDR_REG = RTC_HRS;
1012         DS1287_DATA_REG = rtc->rtc_hrs;
1013         DS1287_ADDR_REG = RTC_DOW;
1014         DS1287_DATA_REG = rtc->rtc_dow;
1015         DS1287_ADDR_REG = RTC_DOM;
1016         DS1287_DATA_REG = rtc->rtc_dom;
1017         DS1287_ADDR_REG = RTC_MON;
1018         DS1287_DATA_REG = rtc->rtc_mon;
1019         DS1287_ADDR_REG = RTC_YEAR;
1020         DS1287_DATA_REG = rtc->rtc_year;
1021         DS1287_ADDR_REG = RTC_CENTURY;
1022         DS1287_DATA_REG = rtc->rtc_century;
1023 
1024         /*
1025          * Unfreeze
1026          */
1027         DS1287_ADDR_REG = RTC_B;
1028         DS1287_DATA_REG = regb;
1029 
1030         mutex_exit(&ds1287_reg_mutex);
1031 }
1032 
1033 void
1034 write_rtc_alarm(struct rtc_t *rtc)
1035 {
1036         mutex_enter(&ds1287_reg_mutex);
1037 
1038         select_bank(1);
1039         DS1287_ADDR_REG = RTC_ASEC;
1040         DS1287_DATA_REG = rtc->rtc_asec;
1041         DS1287_ADDR_REG = RTC_AMIN;
1042         DS1287_DATA_REG = rtc->rtc_amin;
1043         DS1287_ADDR_REG = RTC_AHRS;
1044         DS1287_DATA_REG = rtc->rtc_ahrs;
1045         DS1287_ADDR_REG = RTC_ADOM;
1046         DS1287_DATA_REG = rtc->rtc_adom;
1047         DS1287_ADDR_REG = RTC_AMON;
1048         DS1287_DATA_REG = rtc->rtc_amon;
1049 
1050         select_bank(2);
1051         DS1287_ADDR_REG = APC_WDWR;
1052         DS1287_DATA_REG = rtc->apc_wdwr;
1053         DS1287_ADDR_REG = APC_WDMR;
1054         DS1287_DATA_REG = rtc->apc_wdmr;
1055         DS1287_ADDR_REG = APC_WMR;
1056         DS1287_DATA_REG = rtc->apc_wmr;
1057         DS1287_ADDR_REG = APC_WYR;
1058         DS1287_DATA_REG = rtc->apc_wyr;
1059         DS1287_ADDR_REG = APC_WCR;
1060         DS1287_DATA_REG = rtc->apc_wcr;
1061 
1062         mutex_exit(&ds1287_reg_mutex);
1063 }
1064 
1065 /*
1066  * program the rtc registers for alarm to go off at the specified time
1067  */
1068 static void
1069 todds_set_power_alarm(timestruc_t ts)
1070 {
1071         todinfo_t       tod;
1072         uint8_t         apcr2;
1073         struct rtc_t    rtc;
1074 
1075         ASSERT(MUTEX_HELD(&tod_lock));
1076         tod = utc_to_tod(ts.tv_sec);
1077         mutex_enter(&ds1287_reg_mutex);
1078 
1079         /* Clear Time Match Detect */
1080         select_bank(2);
1081         DS1287_ADDR_REG = APC_APSR;
1082         apcr2 = DS1287_DATA_REG;
1083 
1084         /* Disable Time Match Enable */
1085         DS1287_ADDR_REG = APC_APCR2;
1086         apcr2 = DS1287_DATA_REG;
1087         DS1287_DATA_REG = (apcr2 & (~APC_TME));
1088 
1089         mutex_exit(&ds1287_reg_mutex);
1090 
1091         rtc.rtc_asec = (uint8_t)tod.tod_sec;
1092         rtc.rtc_amin = (uint8_t)tod.tod_min;
1093         rtc.rtc_ahrs = (uint8_t)tod.tod_hour;
1094         rtc.rtc_adom = (uint8_t)tod.tod_day;
1095         rtc.rtc_amon = (uint8_t)tod.tod_month;
1096 
1097         rtc.apc_wdwr = (uint8_t)tod.tod_dow;
1098         rtc.apc_wdmr = (uint8_t)tod.tod_day;
1099         rtc.apc_wmr = (uint8_t)tod.tod_month;
1100         rtc.apc_wyr = tod.tod_year % 100;
1101         rtc.apc_wcr = (tod.tod_year / 100) + 19;
1102 
1103         write_rtc_alarm(&rtc);
1104 
1105         mutex_enter(&ds1287_reg_mutex);
1106         /* Enable Time Match enable */
1107         select_bank(2);
1108         DS1287_ADDR_REG = APC_APCR2;
1109         DS1287_DATA_REG = (apcr2 | APC_TME);
1110 
1111         mutex_exit(&ds1287_reg_mutex);
1112 }
1113 
1114 /*
1115  * clear alarm interrupt
1116  */
1117 static void
1118 todds_clear_power_alarm(void)
1119 {
1120         uint8_t apcr2;
1121 
1122         ASSERT(MUTEX_HELD(&tod_lock));
1123 
1124         mutex_enter(&ds1287_reg_mutex);
1125 
1126         /* Clear Time Match Detect */
1127         select_bank(2);
1128         DS1287_ADDR_REG = APC_APSR;
1129         apcr2 = DS1287_DATA_REG;
1130 
1131         /* Disable Time Match Enable */
1132         DS1287_ADDR_REG = APC_APCR2;
1133         apcr2 = DS1287_DATA_REG;
1134         DS1287_DATA_REG = (apcr2 & (~APC_TME));
1135 
1136         mutex_exit(&ds1287_reg_mutex);
1137 }
1138 
1139 /*
1140  * Determine the cpu frequency by watching the TOD chip rollover twice.
1141  * Cpu clock rate is determined by computing the ticks added (in tick register)
1142  * during one second interval on TOD.
1143  */
1144 uint64_t
1145 todds_get_cpufrequency(void)
1146 {
1147         uint64_t cpu_freq;
1148 
1149         ASSERT(MUTEX_HELD(&tod_lock));
1150         mutex_enter(&ds1287_reg_mutex);
1151 
1152         select_bank(1);
1153         DS1287_ADDR_REG = RTC_SEC;
1154         cpu_freq = find_cpufrequency(v_rtc_data_reg);
1155 
1156         mutex_exit(&ds1287_reg_mutex);
1157         return (cpu_freq);
1158 }
1159 
1160 static void
1161 select_bank(int bank)
1162 {
1163         uint8_t rega;
1164         int banksel;
1165 
1166         /* Select Bank 1 */
1167         DS1287_ADDR_REG = RTC_A;
1168         rega = DS1287_DATA_REG;
1169         rega = rega & ~(RTC_DIV0 | RTC_DIV1 | RTC_DIV2);
1170         switch (bank) {
1171         case 0:
1172                 banksel = RTC_DIV1;
1173                 break;
1174         case 1:
1175                 banksel = RTC_DIV0 | RTC_DIV1;
1176                 break;
1177         case 2:
1178                 banksel = RTC_DIV2;
1179                 break;
1180         }
1181         rega |= banksel;
1182         DS1287_DATA_REG = rega;
1183 }
1184 
1185 /*ARGSUSED*/
1186 static uint_t
1187 todds_set_watchdog_timer(uint_t timeoutval)
1188 {
1189         ASSERT(MUTEX_HELD(&tod_lock));
1190         return (0);
1191 }
1192 
1193 static uint_t
1194 todds_clear_watchdog_timer(void)
1195 {
1196         ASSERT(MUTEX_HELD(&tod_lock));
1197         return (0);
1198 }