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 /*
  23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #include <sys/param.h>
  28 #include <sys/systm.h>
  29 #include <sys/sunddi.h>
  30 #include <sys/esunddi.h>
  31 #include <sys/sunndi.h>
  32 #include <sys/ddi.h>
  33 #include <sys/modctl.h>
  34 #include <sys/sysmacros.h>
  35 #include <sys/note.h>
  36 
  37 #include <sys/platform_module.h>
  38 #include <sys/errno.h>
  39 #include <sys/i2c/clients/i2c_client.h>
  40 #include <sys/cherrystone.h>
  41 #include <sys/machsystm.h>
  42 #include <sys/promif.h>
  43 #include <vm/page.h>
  44 #include <sys/memnode.h>
  45 #include <vm/vm_dep.h>
  46 
  47 /* Cherrystone Keyswitch Information */
  48 #define CHERRY_KEY_POLL_PORT    3
  49 #define CHERRY_KEY_POLL_BIT     2
  50 #define CHERRY_KEY_POLL_INTVL   10
  51 
  52 #define SHARED_PCF8584_PATH "/pci@9,700000/ebus@1/i2c@1,2e/nvram@4,a4"
  53 static dev_info_t *shared_pcf8584_dip;
  54 static kmutex_t cherry_pcf8584_mutex;
  55 
  56 static  boolean_t       key_locked_bit;
  57 static  clock_t         keypoll_timeout_hz;
  58 
  59 /*
  60  * Table that maps memory slices to a specific memnode.
  61  */
  62 int slice_to_memnode[CHERRYSTONE_MAX_SLICE];
  63 
  64 /*
  65  * For software memory interleaving support.
  66  */
  67 static void update_mem_bounds(int, int, int, uint64_t, uint64_t);
  68 
  69 static uint64_t
  70 slice_table[CHERRYSTONE_SBD_SLOTS][CHERRYSTONE_CPUS_PER_BOARD]
  71                 [CHERRYSTONE_BANKS_PER_MC][2];
  72 
  73 #define SLICE_PA        0
  74 #define SLICE_SPAN      1
  75 
  76 /* Function prototypes */
  77 int (*p2get_mem_unum)(int, uint64_t, char *, int, int *);
  78 
  79 int (*cherry_ssc050_get_port_bit) (dev_info_t *, int, int, uint8_t *, int);
  80 extern  void (*abort_seq_handler)();
  81 
  82 static  int cherry_dev_search(dev_info_t *, void *);
  83 static  void keyswitch_poll(void *);
  84 static  void cherry_abort_seq_handler(char *msg);
  85 
  86 /* Function definitions from this point forward. */
  87 
  88 int
  89 set_platform_tsb_spares()
  90 {
  91         return (0);
  92 }
  93 
  94 void
  95 startup_platform(void)
  96 {
  97         /*
  98          * Disable an active h/w watchdog timer
  99          * upon exit to OBP.
 100          */
 101         extern int disable_watchdog_on_exit;
 102         disable_watchdog_on_exit = 1;
 103 
 104         mutex_init(&cherry_pcf8584_mutex, NULL, NULL, NULL);
 105 }
 106 
 107 #pragma weak mmu_init_large_pages
 108 
 109 void
 110 set_platform_defaults(void)
 111 {
 112         extern void mmu_init_large_pages(size_t);
 113 
 114         if ((mmu_page_sizes == max_mmu_page_sizes) &&
 115             (mmu_ism_pagesize != DEFAULT_ISM_PAGESIZE)) {
 116                 if (&mmu_init_large_pages)
 117                         mmu_init_large_pages(mmu_ism_pagesize);
 118         }
 119 }
 120 
 121 void
 122 load_platform_modules(void)
 123 {
 124         if (modload("drv", "pmc") < 0) {
 125                 cmn_err(CE_NOTE, "pmc driver failed to load");
 126         }
 127 }
 128 
 129 void
 130 load_platform_drivers(void)
 131 {
 132         char            **drv;
 133         dev_info_t      *i2cnexus_dip;
 134         dev_info_t      *keysw_dip = NULL;
 135 
 136         static char     *boot_time_drivers[] = {
 137                 "todds1287",
 138                 "mc-us3",
 139                 "ssc050",
 140                 NULL
 141         };
 142 
 143         for (drv = boot_time_drivers; *drv; drv++) {
 144                 if (i_ddi_attach_hw_nodes(*drv) != DDI_SUCCESS)
 145                         cmn_err(CE_WARN, "Failed to install \"%s\" driver.",
 146                             *drv);
 147         }
 148 
 149         /*
 150          * mc-us3 and ssc050 must stay loaded for plat_get_mem_unum()
 151          * and keyswitch_poll()
 152          */
 153         (void) ddi_hold_driver(ddi_name_to_major("mc-us3"));
 154         (void) ddi_hold_driver(ddi_name_to_major("ssc050"));
 155 
 156         /* Gain access into the ssc050_get_port function */
 157         cherry_ssc050_get_port_bit = (int (*) (dev_info_t *, int, int,
 158             uint8_t *, int)) modgetsymvalue("ssc050_get_port_bit", 0);
 159         if (cherry_ssc050_get_port_bit == NULL) {
 160                 cmn_err(CE_WARN, "cannot find ssc050_get_port_bit");
 161                 return;
 162         }
 163 
 164         e_ddi_walk_driver("i2c-ssc050", cherry_dev_search, (void *)&keysw_dip);
 165         ASSERT(keysw_dip != NULL);
 166 
 167         /*
 168          * prevent detach of i2c-ssc050
 169          */
 170         e_ddi_hold_devi(keysw_dip);
 171 
 172         keypoll_timeout_hz = drv_sectohz(10);
 173         keyswitch_poll(keysw_dip);
 174         abort_seq_handler = cherry_abort_seq_handler;
 175 
 176         /*
 177          * Figure out which pcf8584_dip is shared with OBP for the nvram
 178          * device, so the lock can be acquired.
 179          */
 180 
 181         i2cnexus_dip = e_ddi_hold_devi_by_path(SHARED_PCF8584_PATH, 0);
 182 
 183         ASSERT(i2cnexus_dip != NULL);
 184         shared_pcf8584_dip = ddi_get_parent(i2cnexus_dip);
 185 
 186         ndi_hold_devi(shared_pcf8584_dip);
 187         ndi_rele_devi(i2cnexus_dip);
 188 }
 189 
 190 static int
 191 cherry_dev_search(dev_info_t *dip, void *arg)
 192 {
 193         int             *dev_regs; /* Info about where the device is. */
 194         uint_t          len;
 195         int             err;
 196 
 197         if (strcmp(ddi_binding_name(dip), "i2c-ssc050") != 0)
 198                 return (DDI_WALK_CONTINUE);
 199 
 200         err = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
 201             DDI_PROP_DONTPASS, "reg", &dev_regs, &len);
 202         if (err != DDI_PROP_SUCCESS) {
 203                 return (DDI_WALK_CONTINUE);
 204         }
 205         /*
 206          * regs[0] contains the bus number and regs[1]
 207          * contains the device address of the i2c device.
 208          * 0x82 is the device address of the i2c device
 209          * from which  the key switch position is read.
 210          */
 211         if (dev_regs[0] == 0 && dev_regs[1] == 0x82) {
 212                 *((dev_info_t **)arg) = dip;
 213                 ddi_prop_free(dev_regs);
 214                 return (DDI_WALK_TERMINATE);
 215         }
 216         ddi_prop_free(dev_regs);
 217         return (DDI_WALK_CONTINUE);
 218 }
 219 
 220 static void
 221 keyswitch_poll(void *arg)
 222 {
 223         dev_info_t      *dip = arg;
 224         uchar_t port_byte;
 225         int     port = CHERRY_KEY_POLL_PORT;
 226         int     bit = CHERRY_KEY_POLL_BIT;
 227         int     err;
 228 
 229         err = cherry_ssc050_get_port_bit(dip, port, bit,
 230             &port_byte, I2C_NOSLEEP);
 231         if (err != 0) {
 232                 cmn_err(CE_WARN, "keyswitch polling disabled: "
 233                     "errno=%d while reading ssc050", err);
 234                 return;
 235         }
 236 
 237         key_locked_bit = (boolean_t)((port_byte & 0x1));
 238         (void) timeout(keyswitch_poll, (caddr_t)dip, keypoll_timeout_hz);
 239 }
 240 
 241 static void
 242 cherry_abort_seq_handler(char *msg)
 243 {
 244         if (key_locked_bit == 0)
 245                 cmn_err(CE_CONT, "KEY in LOCKED position, "
 246                     "ignoring debug enter sequence");
 247         else  {
 248                 debug_enter(msg);
 249         }
 250 }
 251 
 252 
 253 /*ARGSUSED*/
 254 int
 255 plat_cpu_poweron(struct cpu *cp)
 256 {
 257         return (ENOTSUP);       /* not supported on this platform */
 258 }
 259 
 260 /*ARGSUSED*/
 261 int
 262 plat_cpu_poweroff(struct cpu *cp)
 263 {
 264         return (ENOTSUP);       /* not supported on this platform */
 265 }
 266 
 267 /*
 268  * Given a pfn, return the board and beginning/end of the page's
 269  * memory controller's address range.
 270  */
 271 static int
 272 plat_discover_slice(pfn_t pfn, pfn_t *first, pfn_t *last)
 273 {
 274         int bd, cpu, bank;
 275 
 276         for (bd = 0; bd < CHERRYSTONE_SBD_SLOTS; bd++) {
 277                 for (cpu = 0; cpu < CHERRYSTONE_CPUS_PER_BOARD; cpu++) {
 278                         for (bank = 0; bank < CHERRYSTONE_BANKS_PER_MC;
 279                             bank++) {
 280                                 uint64_t *slice = slice_table[bd][cpu][bank];
 281                                 uint64_t base = btop(slice[SLICE_PA]);
 282                                 uint64_t len = btop(slice[SLICE_SPAN]);
 283                                 if (len && pfn >= base && pfn < (base + len)) {
 284                                         *first = base;
 285                                         *last = base + len - 1;
 286                                         return (bd);
 287                                 }
 288                         }
 289                 }
 290         }
 291         panic("plat_discover_slice: no slice for pfn 0x%lx\n", pfn);
 292         /* NOTREACHED */
 293 }
 294 
 295 /*ARGSUSED*/
 296 void
 297 plat_freelist_process(int mnode)
 298 {}
 299 
 300 /*
 301  * Called for each board/cpu/PA range detected in plat_fill_mc().
 302  */
 303 static void
 304 update_mem_bounds(int boardid, int cpuid, int bankid,
 305         uint64_t base, uint64_t size)
 306 {
 307         uint64_t        end;
 308         int             mnode;
 309 
 310         slice_table[boardid][cpuid][bankid][SLICE_PA] = base;
 311         slice_table[boardid][cpuid][bankid][SLICE_SPAN] = size;
 312 
 313         end = base + size - 1;
 314 
 315         /*
 316          * First see if this board already has a memnode associated
 317          * with it.  If not, see if this slice has a memnode.  This
 318          * covers the cases where a single slice covers multiple
 319          * boards (cross-board interleaving) and where a single
 320          * board has multiple slices (1+GB DIMMs).
 321          */
 322         if ((mnode = plat_lgrphand_to_mem_node(boardid)) == -1) {
 323                 if ((mnode = slice_to_memnode[PA_2_SLICE(base)]) == -1)
 324                         mnode = mem_node_alloc();
 325 
 326                 ASSERT(mnode >= 0);
 327                 ASSERT(mnode < MAX_MEM_NODES);
 328                 plat_assign_lgrphand_to_mem_node(boardid, mnode);
 329         }
 330 
 331         base = P2ALIGN(base, (1ul << PA_SLICE_SHIFT));
 332 
 333         while (base < end) {
 334                 slice_to_memnode[PA_2_SLICE(base)] = mnode;
 335                 base += (1ul << PA_SLICE_SHIFT);
 336         }
 337 }
 338 
 339 /*
 340  * Dynamically detect memory slices in the system by decoding
 341  * the cpu memory decoder registers at boot time.
 342  */
 343 void
 344 plat_fill_mc(pnode_t nodeid)
 345 {
 346         uint64_t        mc_addr, saf_addr;
 347         uint64_t        mc_decode[CHERRYSTONE_BANKS_PER_MC];
 348         uint64_t        base, size;
 349         uint64_t        saf_mask;
 350         uint64_t        offset;
 351         uint32_t        regs[4];
 352         int             len;
 353         int             local_mc;
 354         int             portid;
 355         int             boardid;
 356         int             cpuid;
 357         int             i;
 358 
 359         if ((prom_getprop(nodeid, "portid", (caddr_t)&portid) < 0) ||
 360             (portid == -1))
 361                 return;
 362 
 363         /*
 364          * Decode the board number from the MC portid.  Assumes
 365          * portid == safari agentid.
 366          */
 367         boardid = CHERRYSTONE_GETSLOT(portid);
 368         cpuid = CHERRYSTONE_GETSID(portid);
 369 
 370         /*
 371          * The "reg" property returns 4 32-bit values. The first two are
 372          * combined to form a 64-bit address.  The second two are for a
 373          * 64-bit size, but we don't actually need to look at that value.
 374          */
 375         len = prom_getproplen(nodeid, "reg");
 376         if (len != (sizeof (uint32_t) * 4)) {
 377                 prom_printf("Warning: malformed 'reg' property\n");
 378                 return;
 379         }
 380         if (prom_getprop(nodeid, "reg", (caddr_t)regs) < 0)
 381                 return;
 382         mc_addr = ((uint64_t)regs[0]) << 32;
 383         mc_addr |= (uint64_t)regs[1];
 384 
 385         /*
 386          * Figure out whether the memory controller we are examining
 387          * belongs to this CPU or a different one.
 388          */
 389         saf_addr = lddsafaddr(8);
 390         saf_mask = (uint64_t)SAF_MASK;
 391         if ((mc_addr & saf_mask) == saf_addr)
 392                 local_mc = 1;
 393         else
 394                 local_mc = 0;
 395 
 396         for (i = 0; i < CHERRYSTONE_BANKS_PER_MC; i++) {
 397                 /*
 398                  * Memory decode masks are at offsets 0x10 - 0x28.
 399                  */
 400                 offset = 0x10 + (i << 3);
 401 
 402                 /*
 403                  * If the memory controller is local to this CPU, we use
 404                  * the special ASI to read the decode registers.
 405                  * Otherwise, we load the values from a magic address in
 406                  * I/O space.
 407                  */
 408                 if (local_mc)
 409                         mc_decode[i] = lddmcdecode(offset);
 410                 else
 411                         mc_decode[i] = lddphysio(mc_addr | offset);
 412 
 413                 /*
 414                  * If the upper bit is set, we have a valid mask
 415                  */
 416                 if ((int64_t)mc_decode[i] < 0) {
 417                         /*
 418                          * The memory decode register is a bitmask field,
 419                          * so we can decode that into both a base and
 420                          * a span.
 421                          */
 422                         base = MC_BASE(mc_decode[i]) << PHYS2UM_SHIFT;
 423                         size = MC_UK2SPAN(mc_decode[i]);
 424                         update_mem_bounds(boardid, cpuid, i, base, size);
 425                 }
 426         }
 427 }
 428 
 429 /*
 430  * This routine is run midway through the boot process.  By the time we get
 431  * here, we know about all the active CPU boards in the system, and we have
 432  * extracted information about each board's memory from the memory
 433  * controllers.  We have also figured out which ranges of memory will be
 434  * assigned to which memnodes, so we walk the slice table to build the table
 435  * of memnodes.
 436  */
 437 /* ARGSUSED */
 438 void
 439 plat_build_mem_nodes(prom_memlist_t *list, size_t  nelems)
 440 {
 441         int     slice;
 442         pfn_t   basepfn;
 443         pgcnt_t npgs;
 444 
 445         mem_node_pfn_shift = PFN_SLICE_SHIFT;
 446         mem_node_physalign = (1ull << PA_SLICE_SHIFT);
 447         npgs = 1ull << PFN_SLICE_SHIFT;
 448 
 449         for (slice = 0; slice < CHERRYSTONE_MAX_SLICE; slice++) {
 450                 if (slice_to_memnode[slice] == -1)
 451                         continue;
 452                 basepfn = (uint64_t)slice << PFN_SLICE_SHIFT;
 453                 mem_node_add_slice(basepfn, basepfn + npgs - 1);
 454         }
 455 }
 456 
 457 
 458 
 459 /*
 460  * Cherrystone support for lgroups.
 461  *
 462  * On Cherrystone, an lgroup platform handle == slot number.
 463  *
 464  * Mappings between lgroup handles and memnodes are managed
 465  * in addition to mappings between memory slices and memnodes
 466  * to support cross-board interleaving as well as multiple
 467  * slices per board (e.g. >1GB DIMMs). The initial mapping
 468  * of memnodes to lgroup handles is determined at boot time.
 469  */
 470 
 471 int
 472 plat_pfn_to_mem_node(pfn_t pfn)
 473 {
 474         return (slice_to_memnode[PFN_2_SLICE(pfn)]);
 475 }
 476 
 477 /*
 478  * Return the platform handle for the lgroup containing the given CPU
 479  *
 480  * For Cherrystone, lgroup platform handle == slot/board number
 481  */
 482 lgrp_handle_t
 483 plat_lgrp_cpu_to_hand(processorid_t id)
 484 {
 485         return (CHERRYSTONE_GETSLOT(id));
 486 }
 487 
 488 /*
 489  * Platform specific lgroup initialization
 490  */
 491 void
 492 plat_lgrp_init(void)
 493 {
 494         int i;
 495 
 496         /*
 497          * Initialize lookup tables to invalid values so we catch
 498          * any illegal use of them.
 499          */
 500         for (i = 0; i < CHERRYSTONE_MAX_SLICE; i++) {
 501                 slice_to_memnode[i] = -1;
 502         }
 503 }
 504 
 505 /*
 506  * Return latency between "from" and "to" lgroups
 507  *
 508  * This latency number can only be used for relative comparison
 509  * between lgroups on the running system, cannot be used across platforms,
 510  * and may not reflect the actual latency.  It is platform and implementation
 511  * specific, so platform gets to decide its value.  It would be nice if the
 512  * number was at least proportional to make comparisons more meaningful though.
 513  * NOTE: The numbers below are supposed to be load latencies for uncached
 514  * memory divided by 10.
 515  */
 516 int
 517 plat_lgrp_latency(lgrp_handle_t from, lgrp_handle_t to)
 518 {
 519         /*
 520          * Return min remote latency when there are more than two lgroups
 521          * (root and child) and getting latency between two different lgroups
 522          * or root is involved
 523          */
 524         if (lgrp_optimizations() && (from != to ||
 525             from == LGRP_DEFAULT_HANDLE || to == LGRP_DEFAULT_HANDLE))
 526                 return (21);
 527         else
 528                 return (19);
 529 }
 530 
 531 /*
 532  * No platform drivers on this platform
 533  */
 534 char *platform_module_list[] = {
 535         (char *)0
 536 };
 537 
 538 /*ARGSUSED*/
 539 void
 540 plat_tod_fault(enum tod_fault_type tod_bad)
 541 {
 542 }
 543 
 544 /*ARGSUSED*/
 545 int
 546 plat_get_mem_unum(int synd_code, uint64_t flt_addr, int flt_bus_id,
 547     int flt_in_memory, ushort_t flt_status, char *buf, int buflen, int *lenp)
 548 {
 549         if (flt_in_memory && (p2get_mem_unum != NULL))
 550                 return (p2get_mem_unum(synd_code, P2ALIGN(flt_addr, 8),
 551                     buf, buflen, lenp));
 552         else
 553                 return (ENOTSUP);
 554 }
 555 
 556 /*
 557  * This platform hook gets called from mc_add_mem_unum_label() in the mc-us3
 558  * driver giving each platform the opportunity to add platform
 559  * specific label information to the unum for ECC error logging purposes.
 560  */
 561 void
 562 plat_add_mem_unum_label(char *unum, int mcid, int bank, int dimm)
 563 {
 564         _NOTE(ARGUNUSED(bank, dimm))
 565 
 566         char board = CHERRYSTONE_GETSLOT_LABEL(mcid);
 567         char old_unum[UNUM_NAMLEN];
 568 
 569         (void) strcpy(old_unum, unum);
 570         (void) snprintf(unum, UNUM_NAMLEN, "Slot %c: %s", board, old_unum);
 571 }
 572 
 573 int
 574 plat_get_cpu_unum(int cpuid, char *buf, int buflen, int *lenp)
 575 {
 576         char board = CHERRYSTONE_GETSLOT_LABEL(cpuid);
 577 
 578         if (snprintf(buf, buflen, "Slot %c", board) >= buflen) {
 579                 return (ENOSPC);
 580         } else {
 581                 *lenp = strlen(buf);
 582                 return (0);
 583         }
 584 }
 585 
 586 /*
 587  * Cherrystone's BBC pcf8584 controller is used by both OBP and the OS's i2c
 588  * drivers.  The 'eeprom' command executes OBP code to handle property requests.
 589  * If eeprom didn't do this, or if the controllers were partitioned so that all
 590  * devices on a given controller were driven by either OBP or the OS, this
 591  * wouldn't be necessary.
 592  *
 593  * Note that getprop doesn't have the same issue as it reads from cached
 594  * memory in OBP.
 595  */
 596 
 597 /*
 598  * Common locking enter code
 599  */
 600 void
 601 plat_setprop_enter(void)
 602 {
 603         mutex_enter(&cherry_pcf8584_mutex);
 604 }
 605 
 606 /*
 607  * Common locking exit code
 608  */
 609 void
 610 plat_setprop_exit(void)
 611 {
 612         mutex_exit(&cherry_pcf8584_mutex);
 613 }
 614 
 615 /*
 616  * Called by pcf8584 driver
 617  */
 618 void
 619 plat_shared_i2c_enter(dev_info_t *i2cnexus_dip)
 620 {
 621         if (i2cnexus_dip == shared_pcf8584_dip) {
 622                 plat_setprop_enter();
 623         }
 624 }
 625 
 626 /*
 627  * Called by pcf8584 driver
 628  */
 629 void
 630 plat_shared_i2c_exit(dev_info_t *i2cnexus_dip)
 631 {
 632         if (i2cnexus_dip == shared_pcf8584_dip) {
 633                 plat_setprop_exit();
 634         }
 635 }