1d58fda43Sjbeloro /* 206e46062Sjbeloro * CDDL HEADER START 306e46062Sjbeloro * 406e46062Sjbeloro * The contents of this file are subject to the terms of the 506e46062Sjbeloro * Common Development and Distribution License (the "License"). 606e46062Sjbeloro * You may not use this file except in compliance with the License. 706e46062Sjbeloro * 806e46062Sjbeloro * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 906e46062Sjbeloro * or http://www.opensolaris.org/os/licensing. 1006e46062Sjbeloro * See the License for the specific language governing permissions 1106e46062Sjbeloro * and limitations under the License. 1206e46062Sjbeloro * 1306e46062Sjbeloro * When distributing Covered Code, include this CDDL HEADER in each 1406e46062Sjbeloro * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1506e46062Sjbeloro * If applicable, add the following below this CDDL HEADER, with the 1606e46062Sjbeloro * fields enclosed by brackets "[]" replaced with your own identifying 1706e46062Sjbeloro * information: Portions Copyright [yyyy] [name of copyright owner] 1806e46062Sjbeloro * 1906e46062Sjbeloro * CDDL HEADER END 2006e46062Sjbeloro */ 2106e46062Sjbeloro 2206e46062Sjbeloro /* 23*07d06da5SSurya Prakki * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24d58fda43Sjbeloro * Use is subject to license terms. 25d58fda43Sjbeloro */ 26d58fda43Sjbeloro 27d58fda43Sjbeloro #include <sys/param.h> 28d58fda43Sjbeloro #include <sys/systm.h> 29d58fda43Sjbeloro #include <sys/sysmacros.h> 30d58fda43Sjbeloro #include <sys/sunddi.h> 31d58fda43Sjbeloro #include <sys/esunddi.h> 32d58fda43Sjbeloro 33d58fda43Sjbeloro #include <sys/platform_module.h> 34d58fda43Sjbeloro #include <sys/errno.h> 35d58fda43Sjbeloro #include <sys/cpu_sgnblk_defs.h> 36d58fda43Sjbeloro #include <sys/rmc_comm_dp.h> 37d58fda43Sjbeloro #include <sys/rmc_comm_drvintf.h> 38d58fda43Sjbeloro #include <sys/modctl.h> 39d58fda43Sjbeloro #include <sys/lgrp.h> 40d58fda43Sjbeloro #include <sys/memnode.h> 41d58fda43Sjbeloro #include <sys/promif.h> 42d58fda43Sjbeloro 43d58fda43Sjbeloro /* Anything related to shared i2c access applies to Seattle only */ 44d58fda43Sjbeloro #define SHARED_MI2CV_PATH "/i2c@1f,530000" 45d58fda43Sjbeloro static dev_info_t *shared_mi2cv_dip; 46d58fda43Sjbeloro static kmutex_t mi2cv_mutex; 47d58fda43Sjbeloro 48d58fda43Sjbeloro int (*p2get_mem_unum)(int, uint64_t, char *, int, int *); 49d58fda43Sjbeloro static void cpu_sgn_update(ushort_t, uchar_t, uchar_t, int); 50d58fda43Sjbeloro int (*rmc_req_now)(rmc_comm_msg_t *, uint8_t) = NULL; 51d58fda43Sjbeloro 52d58fda43Sjbeloro void 53d58fda43Sjbeloro startup_platform(void) 54d58fda43Sjbeloro { 55d58fda43Sjbeloro mutex_init(&mi2cv_mutex, NULL, NULL, NULL); 56d58fda43Sjbeloro } 57d58fda43Sjbeloro 58d58fda43Sjbeloro int 59d58fda43Sjbeloro set_platform_tsb_spares() 60d58fda43Sjbeloro { 61d58fda43Sjbeloro return (0); 62d58fda43Sjbeloro } 63d58fda43Sjbeloro 64d58fda43Sjbeloro void 65d58fda43Sjbeloro set_platform_defaults(void) 66d58fda43Sjbeloro { 67d58fda43Sjbeloro extern char *tod_module_name; 68d58fda43Sjbeloro /* Set appropriate tod module */ 69d58fda43Sjbeloro if (tod_module_name == NULL) 70d58fda43Sjbeloro tod_module_name = "todm5823"; 71d58fda43Sjbeloro 72d58fda43Sjbeloro cpu_sgn_func = cpu_sgn_update; 73d58fda43Sjbeloro } 74d58fda43Sjbeloro 75d58fda43Sjbeloro /* 76986c3e85Szx151605 * these two dummy functions are loaded over the original 77986c3e85Szx151605 * todm5823 set and clear_power_alarm functions. On Seattle 78986c3e85Szx151605 * these functions are not supported, and thus we need to provide 79986c3e85Szx151605 * dummy functions that just returns. 80986c3e85Szx151605 * On Seattle, clock chip is not persistant across reboots, 81986c3e85Szx151605 * and moreover it has a bug sending memory access. 82986c3e85Szx151605 * This fix is done by writing over the original 83986c3e85Szx151605 * tod_ops function pointer with our dummy replacement functions. 84986c3e85Szx151605 */ 85986c3e85Szx151605 /*ARGSUSED*/ 86986c3e85Szx151605 static void 87986c3e85Szx151605 dummy_todm5823_set_power_alarm(timestruc_t ts) 88986c3e85Szx151605 { 89986c3e85Szx151605 } 90986c3e85Szx151605 91986c3e85Szx151605 static void 92986c3e85Szx151605 dummy_todm5823_clear_power_alarm(void) 93986c3e85Szx151605 { 94986c3e85Szx151605 } 95986c3e85Szx151605 96986c3e85Szx151605 /* 97d58fda43Sjbeloro * Definitions for accessing the pci config space of the isa node 98d58fda43Sjbeloro * of Southbridge. 99d58fda43Sjbeloro */ 100d58fda43Sjbeloro static ddi_acc_handle_t isa_handle = NULL; /* handle for isa pci space */ 101d58fda43Sjbeloro 102d58fda43Sjbeloro /* 103d58fda43Sjbeloro * Definition for accessing rmclomv 104d58fda43Sjbeloro */ 105d58fda43Sjbeloro #define RMCLOMV_PATHNAME "/pseudo/rmclomv@0" 106d58fda43Sjbeloro 107d58fda43Sjbeloro void 108d58fda43Sjbeloro load_platform_drivers(void) 109d58fda43Sjbeloro { 110d58fda43Sjbeloro dev_info_t *rmclomv_dip; 111d58fda43Sjbeloro /* 112d58fda43Sjbeloro * It is OK to return error because 'us' driver is not available 113d58fda43Sjbeloro * in all clusters (e.g. missing in Core cluster). 114d58fda43Sjbeloro */ 115d58fda43Sjbeloro (void) i_ddi_attach_hw_nodes("us"); 116d58fda43Sjbeloro 117d58fda43Sjbeloro 118d58fda43Sjbeloro /* 119d58fda43Sjbeloro * mc-us3i must stay loaded for plat_get_mem_unum() 120d58fda43Sjbeloro */ 121d58fda43Sjbeloro if (i_ddi_attach_hw_nodes("mc-us3i") != DDI_SUCCESS) 122d58fda43Sjbeloro cmn_err(CE_WARN, "mc-us3i driver failed to install"); 123d58fda43Sjbeloro (void) ddi_hold_driver(ddi_name_to_major("mc-us3i")); 124d58fda43Sjbeloro 125d58fda43Sjbeloro /* 12606e46062Sjbeloro * load the power button driver 12706e46062Sjbeloro */ 12806e46062Sjbeloro if (i_ddi_attach_hw_nodes("power") != DDI_SUCCESS) 12906e46062Sjbeloro cmn_err(CE_WARN, "power button driver failed to install"); 13006e46062Sjbeloro else 13106e46062Sjbeloro (void) ddi_hold_driver(ddi_name_to_major("power")); 13206e46062Sjbeloro 13306e46062Sjbeloro /* 134d58fda43Sjbeloro * load the GPIO driver for the ALOM reset and watchdog lines 135d58fda43Sjbeloro */ 136d58fda43Sjbeloro if (i_ddi_attach_hw_nodes("pmugpio") != DDI_SUCCESS) 137d58fda43Sjbeloro cmn_err(CE_WARN, "pmugpio failed to install"); 138d58fda43Sjbeloro else { 139d58fda43Sjbeloro extern int watchdog_enable, watchdog_available; 140d58fda43Sjbeloro extern int disable_watchdog_on_exit; 141d58fda43Sjbeloro 142d58fda43Sjbeloro /* 143d58fda43Sjbeloro * Disable an active h/w watchdog timer upon exit to OBP. 144d58fda43Sjbeloro */ 145d58fda43Sjbeloro disable_watchdog_on_exit = 1; 146d58fda43Sjbeloro 147d58fda43Sjbeloro watchdog_enable = 1; 148d58fda43Sjbeloro watchdog_available = 1; 149d58fda43Sjbeloro } 150d58fda43Sjbeloro (void) ddi_hold_driver(ddi_name_to_major("pmugpio")); 151d58fda43Sjbeloro 152d58fda43Sjbeloro /* 153d58fda43Sjbeloro * Figure out which mi2cv dip is shared with OBP for the nvram 154d58fda43Sjbeloro * device, so the lock can be acquired. 155d58fda43Sjbeloro */ 156d58fda43Sjbeloro shared_mi2cv_dip = e_ddi_hold_devi_by_path(SHARED_MI2CV_PATH, 0); 157d58fda43Sjbeloro /* 158d58fda43Sjbeloro * Load the environmentals driver (rmclomv) 159d58fda43Sjbeloro * 160d58fda43Sjbeloro * We need this driver to handle events from the RMC when state 161d58fda43Sjbeloro * changes occur in the environmental data. 162d58fda43Sjbeloro */ 163d58fda43Sjbeloro if (i_ddi_attach_hw_nodes("rmc_comm") != DDI_SUCCESS) { 164d58fda43Sjbeloro cmn_err(CE_WARN, "rmc_comm failed to install"); 165d58fda43Sjbeloro } else { 166d58fda43Sjbeloro (void) ddi_hold_driver(ddi_name_to_major("rmc_comm")); 167d58fda43Sjbeloro 168d58fda43Sjbeloro rmclomv_dip = e_ddi_hold_devi_by_path(RMCLOMV_PATHNAME, 0); 169d58fda43Sjbeloro if (rmclomv_dip == NULL) { 170d58fda43Sjbeloro cmn_err(CE_WARN, "Could not install rmclomv driver\n"); 171d58fda43Sjbeloro } 172d58fda43Sjbeloro } 173d58fda43Sjbeloro 174d58fda43Sjbeloro /* 175986c3e85Szx151605 * These two dummy functions are loaded over the original 176986c3e85Szx151605 * todm5823 set and clear_power_alarm functions. On Seattle, 177986c3e85Szx151605 * these functionalities are not supported. 178986c3e85Szx151605 * The load_platform_drivers(void) is called from post_startup() 179986c3e85Szx151605 * which is after all the initialization of the tod module is 180986c3e85Szx151605 * finished, then we replace 2 of the tod_ops function pointers 181986c3e85Szx151605 * with our dummy version. 182986c3e85Szx151605 */ 183986c3e85Szx151605 tod_ops.tod_set_power_alarm = dummy_todm5823_set_power_alarm; 184986c3e85Szx151605 tod_ops.tod_clear_power_alarm = dummy_todm5823_clear_power_alarm; 185986c3e85Szx151605 186986c3e85Szx151605 /* 187d58fda43Sjbeloro * create a handle to the rmc_comm_request_nowait() function 188d58fda43Sjbeloro * inside the rmc_comm module. 189d58fda43Sjbeloro * 190d58fda43Sjbeloro * The Seattle/Boston todm5823 driver will use this handle to 191d58fda43Sjbeloro * use the rmc_comm_request_nowait() function to send time/date 192d58fda43Sjbeloro * updates to ALOM. 193d58fda43Sjbeloro */ 194d58fda43Sjbeloro rmc_req_now = (int (*)(rmc_comm_msg_t *, uint8_t)) 195d58fda43Sjbeloro modgetsymvalue("rmc_comm_request_nowait", 0); 196d58fda43Sjbeloro } 197d58fda43Sjbeloro 198d58fda43Sjbeloro /* 199d58fda43Sjbeloro * This routine is needed if a device error or timeout occurs before the 200d58fda43Sjbeloro * driver is loaded. 201d58fda43Sjbeloro */ 202d58fda43Sjbeloro /*ARGSUSED*/ 203d58fda43Sjbeloro int 204d58fda43Sjbeloro plat_ide_chipreset(dev_info_t *dip, int chno) 205d58fda43Sjbeloro { 206d58fda43Sjbeloro int ret = DDI_SUCCESS; 207d58fda43Sjbeloro 208d58fda43Sjbeloro if (isa_handle == NULL) { 209d58fda43Sjbeloro return (DDI_FAILURE); 210d58fda43Sjbeloro } 211d58fda43Sjbeloro 212d58fda43Sjbeloro /* 213d58fda43Sjbeloro * This will be filled in with the reset logic 214d58fda43Sjbeloro * for the ULI1573 when that becomes available. 215d58fda43Sjbeloro * currently this is just a stub. 216d58fda43Sjbeloro */ 217d58fda43Sjbeloro return (ret); 218d58fda43Sjbeloro } 219d58fda43Sjbeloro 220d58fda43Sjbeloro 221d58fda43Sjbeloro /*ARGSUSED*/ 222d58fda43Sjbeloro int 223d58fda43Sjbeloro plat_cpu_poweron(struct cpu *cp) 224d58fda43Sjbeloro { 225d58fda43Sjbeloro return (ENOTSUP); /* not supported on this platform */ 226d58fda43Sjbeloro } 227d58fda43Sjbeloro 228d58fda43Sjbeloro /*ARGSUSED*/ 229d58fda43Sjbeloro int 230d58fda43Sjbeloro plat_cpu_poweroff(struct cpu *cp) 231d58fda43Sjbeloro { 232d58fda43Sjbeloro return (ENOTSUP); /* not supported on this platform */ 233d58fda43Sjbeloro } 234d58fda43Sjbeloro 235d58fda43Sjbeloro /*ARGSUSED*/ 236d58fda43Sjbeloro void 237d58fda43Sjbeloro plat_freelist_process(int mnode) 238d58fda43Sjbeloro { 239d58fda43Sjbeloro } 240d58fda43Sjbeloro 241d58fda43Sjbeloro char *platform_module_list[] = { 242d58fda43Sjbeloro "mi2cv", 243d58fda43Sjbeloro "pca9556", 244d58fda43Sjbeloro (char *)0 245d58fda43Sjbeloro }; 246d58fda43Sjbeloro 247d58fda43Sjbeloro /*ARGSUSED*/ 248d58fda43Sjbeloro void 249d58fda43Sjbeloro plat_tod_fault(enum tod_fault_type tod_bad) 250d58fda43Sjbeloro { 251d58fda43Sjbeloro } 252d58fda43Sjbeloro 253d58fda43Sjbeloro /*ARGSUSED*/ 254d58fda43Sjbeloro int 255d58fda43Sjbeloro plat_get_mem_unum(int synd_code, uint64_t flt_addr, int flt_bus_id, 256d58fda43Sjbeloro int flt_in_memory, ushort_t flt_status, char *buf, int buflen, int *lenp) 257d58fda43Sjbeloro { 258d58fda43Sjbeloro if (flt_in_memory && (p2get_mem_unum != NULL)) 259d58fda43Sjbeloro return (p2get_mem_unum(synd_code, P2ALIGN(flt_addr, 8), 260d58fda43Sjbeloro buf, buflen, lenp)); 261d58fda43Sjbeloro else 262d58fda43Sjbeloro return (ENOTSUP); 263d58fda43Sjbeloro } 264d58fda43Sjbeloro 26506e46062Sjbeloro /* 26606e46062Sjbeloro * This platform hook gets called from mc_add_mem_unum_label() in the mc-us3i 26706e46062Sjbeloro * driver giving each platform the opportunity to add platform 26806e46062Sjbeloro * specific label information to the unum for ECC error logging purposes. 26906e46062Sjbeloro */ 27006e46062Sjbeloro /*ARGSUSED*/ 27106e46062Sjbeloro void 27206e46062Sjbeloro plat_add_mem_unum_label(char *unum, int mcid, int bank, int dimm) 27306e46062Sjbeloro { 27406e46062Sjbeloro char old_unum[UNUM_NAMLEN]; 27506e46062Sjbeloro int printed; 27606e46062Sjbeloro int buflen = UNUM_NAMLEN; 277*07d06da5SSurya Prakki (void) strcpy(old_unum, unum); 27806e46062Sjbeloro printed = snprintf(unum, buflen, "MB/P%d/B%d", mcid, bank); 27906e46062Sjbeloro buflen -= printed; 28006e46062Sjbeloro unum += printed; 28106e46062Sjbeloro 28206e46062Sjbeloro if (dimm != -1) { 28306e46062Sjbeloro printed = snprintf(unum, buflen, "/D%d", dimm); 28406e46062Sjbeloro buflen -= printed; 28506e46062Sjbeloro unum += printed; 28606e46062Sjbeloro } 28706e46062Sjbeloro 288*07d06da5SSurya Prakki (void) snprintf(unum, buflen, ": %s", old_unum); 28906e46062Sjbeloro } 29006e46062Sjbeloro 291d58fda43Sjbeloro /*ARGSUSED*/ 292d58fda43Sjbeloro int 293d58fda43Sjbeloro plat_get_cpu_unum(int cpuid, char *buf, int buflen, int *lenp) 294d58fda43Sjbeloro { 295d58fda43Sjbeloro if (snprintf(buf, buflen, "MB") >= buflen) { 296d58fda43Sjbeloro return (ENOSPC); 297d58fda43Sjbeloro } else { 298d58fda43Sjbeloro *lenp = strlen(buf); 299d58fda43Sjbeloro return (0); 300d58fda43Sjbeloro } 301d58fda43Sjbeloro } 302d58fda43Sjbeloro 303d58fda43Sjbeloro /* 304d58fda43Sjbeloro * Our nodename has been set, pass it along to the RMC. 305d58fda43Sjbeloro */ 306d58fda43Sjbeloro void 307d58fda43Sjbeloro plat_nodename_set(void) 308d58fda43Sjbeloro { 309d58fda43Sjbeloro rmc_comm_msg_t req; /* request */ 310d58fda43Sjbeloro int (*rmc_req_res)(rmc_comm_msg_t *, rmc_comm_msg_t *, time_t) = NULL; 311d58fda43Sjbeloro 312d58fda43Sjbeloro /* 313d58fda43Sjbeloro * find the symbol for the mailbox routine 314d58fda43Sjbeloro */ 315d58fda43Sjbeloro rmc_req_res = (int (*)(rmc_comm_msg_t *, rmc_comm_msg_t *, time_t)) 316d58fda43Sjbeloro modgetsymvalue("rmc_comm_request_response", 0); 317d58fda43Sjbeloro 318d58fda43Sjbeloro if (rmc_req_res == NULL) { 319d58fda43Sjbeloro return; 320d58fda43Sjbeloro } 321d58fda43Sjbeloro 322d58fda43Sjbeloro /* 323d58fda43Sjbeloro * construct the message telling the RMC our nodename 324d58fda43Sjbeloro */ 325d58fda43Sjbeloro req.msg_type = DP_SET_CPU_NODENAME; 326d58fda43Sjbeloro req.msg_len = strlen(utsname.nodename) + 1; 327d58fda43Sjbeloro req.msg_bytes = 0; 328d58fda43Sjbeloro req.msg_buf = (caddr_t)utsname.nodename; 329d58fda43Sjbeloro 330d58fda43Sjbeloro /* 331d58fda43Sjbeloro * ship it 332d58fda43Sjbeloro */ 333d58fda43Sjbeloro (void) (rmc_req_res)(&req, NULL, 2000); 334d58fda43Sjbeloro } 335d58fda43Sjbeloro 336d58fda43Sjbeloro sig_state_t current_sgn; 337d58fda43Sjbeloro 338d58fda43Sjbeloro /* 339d58fda43Sjbeloro * cpu signatures - we're only interested in the overall system 340d58fda43Sjbeloro * "signature" on this platform - not individual cpu signatures 341d58fda43Sjbeloro */ 342d58fda43Sjbeloro /*ARGSUSED*/ 343d58fda43Sjbeloro static void 344d58fda43Sjbeloro cpu_sgn_update(ushort_t sig, uchar_t state, uchar_t sub_state, int cpuid) 345d58fda43Sjbeloro { 346d58fda43Sjbeloro dp_cpu_signature_t signature; 347d58fda43Sjbeloro rmc_comm_msg_t req; /* request */ 348d58fda43Sjbeloro int (*rmc_req_now)(rmc_comm_msg_t *, uint8_t) = NULL; 349d58fda43Sjbeloro 350d58fda43Sjbeloro 351d58fda43Sjbeloro /* 352d58fda43Sjbeloro * Differentiate a panic reboot from a non-panic reboot in the 353d58fda43Sjbeloro * setting of the substate of the signature. 354d58fda43Sjbeloro * 355d58fda43Sjbeloro * If the new substate is REBOOT and we're rebooting due to a panic, 356d58fda43Sjbeloro * then set the new substate to a special value indicating a panic 357d58fda43Sjbeloro * reboot, SIGSUBST_PANIC_REBOOT. 358d58fda43Sjbeloro * 359d58fda43Sjbeloro * A panic reboot is detected by a current (previous) signature 360d58fda43Sjbeloro * state of SIGST_EXIT, and a new signature substate of SIGSUBST_REBOOT. 361d58fda43Sjbeloro * The domain signature state SIGST_EXIT is used as the panic flow 362d58fda43Sjbeloro * progresses. 363d58fda43Sjbeloro * 364d58fda43Sjbeloro * At the end of the panic flow, the reboot occurs but we should know 365d58fda43Sjbeloro * one that was involuntary, something that may be quite useful to know 366d58fda43Sjbeloro * at OBP level. 367d58fda43Sjbeloro */ 368d58fda43Sjbeloro if (state == SIGST_EXIT && sub_state == SIGSUBST_REBOOT) { 369d58fda43Sjbeloro if (current_sgn.state_t.state == SIGST_EXIT && 370d58fda43Sjbeloro current_sgn.state_t.sub_state != SIGSUBST_REBOOT) 371d58fda43Sjbeloro sub_state = SIGSUBST_PANIC_REBOOT; 372d58fda43Sjbeloro } 373d58fda43Sjbeloro 374d58fda43Sjbeloro /* 375d58fda43Sjbeloro * offline and detached states only apply to a specific cpu 376d58fda43Sjbeloro * so ignore them. 377d58fda43Sjbeloro */ 378d58fda43Sjbeloro if (state == SIGST_OFFLINE || state == SIGST_DETACHED) { 379d58fda43Sjbeloro return; 380d58fda43Sjbeloro } 381d58fda43Sjbeloro 382d58fda43Sjbeloro current_sgn.signature = CPU_SIG_BLD(sig, state, sub_state); 383d58fda43Sjbeloro 384d58fda43Sjbeloro /* 385d58fda43Sjbeloro * find the symbol for the mailbox routine 386d58fda43Sjbeloro */ 387d58fda43Sjbeloro rmc_req_now = (int (*)(rmc_comm_msg_t *, uint8_t)) 388d58fda43Sjbeloro modgetsymvalue("rmc_comm_request_nowait", 0); 389d58fda43Sjbeloro if (rmc_req_now == NULL) { 390d58fda43Sjbeloro return; 391d58fda43Sjbeloro } 392d58fda43Sjbeloro 393d58fda43Sjbeloro signature.cpu_id = -1; 394d58fda43Sjbeloro signature.sig = sig; 395d58fda43Sjbeloro signature.states = state; 396d58fda43Sjbeloro signature.sub_state = sub_state; 397d58fda43Sjbeloro req.msg_type = DP_SET_CPU_SIGNATURE; 398d58fda43Sjbeloro req.msg_len = (int)(sizeof (signature)); 399d58fda43Sjbeloro req.msg_bytes = 0; 400d58fda43Sjbeloro req.msg_buf = (caddr_t)&signature; 401d58fda43Sjbeloro 402d58fda43Sjbeloro /* 403ec5d0d67Sphilippm * We need to tell the SP that the host is about to stop running. The 404ec5d0d67Sphilippm * SP will then allow the date to be set at its console, it will change 405ec5d0d67Sphilippm * state of the activity indicator, it will display the correct host 406ec5d0d67Sphilippm * status, and it will stop sending console messages and alerts to the 407ec5d0d67Sphilippm * host communication channel. 408ec5d0d67Sphilippm * 409ec5d0d67Sphilippm * This requires the RMC_COMM_DREQ_URGENT as we want to 410ec5d0d67Sphilippm * be sure activity indicators will reflect the correct status. 411ec5d0d67Sphilippm * 412ec5d0d67Sphilippm * When sub_state SIGSUBST_DUMP is sent, the urgent flag 413ec5d0d67Sphilippm * (RMC_COMM_DREQ_URGENT) is not required as SIGSUBST_PANIC_REBOOT 414ec5d0d67Sphilippm * has already been sent and changed activity indicators. 415d58fda43Sjbeloro */ 416d58fda43Sjbeloro if (state == SIGST_EXIT && (sub_state == SIGSUBST_HALT || 417d58fda43Sjbeloro sub_state == SIGSUBST_REBOOT || sub_state == SIGSUBST_ENVIRON || 418d58fda43Sjbeloro sub_state == SIGSUBST_PANIC_REBOOT)) 419d58fda43Sjbeloro (void) (rmc_req_now)(&req, RMC_COMM_DREQ_URGENT); 420d58fda43Sjbeloro else 42169bbc664Sfw157321 (void) (rmc_req_now)(&req, 0); 422d58fda43Sjbeloro } 423d58fda43Sjbeloro 424d58fda43Sjbeloro /* 425d58fda43Sjbeloro * Fiesta support for lgroups. 426d58fda43Sjbeloro * 427d58fda43Sjbeloro * On fiesta platform, an lgroup platform handle == CPU id 428d58fda43Sjbeloro */ 429d58fda43Sjbeloro 430d58fda43Sjbeloro /* 431d58fda43Sjbeloro * Macro for extracting the CPU number from the CPU id 432d58fda43Sjbeloro */ 433d58fda43Sjbeloro #define CPUID_TO_LGRP(id) ((id) & 0x7) 434d58fda43Sjbeloro #define PLATFORM_MC_SHIFT 36 435d58fda43Sjbeloro 436d58fda43Sjbeloro /* 437d58fda43Sjbeloro * Return the platform handle for the lgroup containing the given CPU 438d58fda43Sjbeloro */ 439d58fda43Sjbeloro void * 440d58fda43Sjbeloro plat_lgrp_cpu_to_hand(processorid_t id) 441d58fda43Sjbeloro { 442bd9d7d01Sanovick return ((void *)(uintptr_t)CPUID_TO_LGRP(id)); 443d58fda43Sjbeloro } 444d58fda43Sjbeloro 445d58fda43Sjbeloro /* 446d58fda43Sjbeloro * Platform specific lgroup initialization 447d58fda43Sjbeloro */ 448d58fda43Sjbeloro void 449d58fda43Sjbeloro plat_lgrp_init(void) 450d58fda43Sjbeloro { 451d58fda43Sjbeloro pnode_t curnode; 452d1a96f96Sanovick char tmp_name[sizeof (OBP_CPU) + 1]; /* extra padding */ 453d58fda43Sjbeloro int portid; 454d58fda43Sjbeloro int cpucnt = 0; 455d58fda43Sjbeloro int max_portid = -1; 456d58fda43Sjbeloro extern uint32_t lgrp_expand_proc_thresh; 457d58fda43Sjbeloro extern uint32_t lgrp_expand_proc_diff; 458d58fda43Sjbeloro extern pgcnt_t lgrp_mem_free_thresh; 459d58fda43Sjbeloro extern uint32_t lgrp_loadavg_tolerance; 460d58fda43Sjbeloro extern uint32_t lgrp_loadavg_max_effect; 461d58fda43Sjbeloro extern uint32_t lgrp_load_thresh; 462d58fda43Sjbeloro extern lgrp_mem_policy_t lgrp_mem_policy_root; 463d58fda43Sjbeloro 464d58fda43Sjbeloro /* 465d58fda43Sjbeloro * Count the number of CPUs installed to determine if 466d58fda43Sjbeloro * NUMA optimization should be enabled or not. 467d58fda43Sjbeloro * 468d58fda43Sjbeloro * All CPU nodes reside in the root node and have a 469d58fda43Sjbeloro * device type "cpu". 470d58fda43Sjbeloro */ 471d58fda43Sjbeloro curnode = prom_rootnode(); 472d58fda43Sjbeloro for (curnode = prom_childnode(curnode); curnode; 473d58fda43Sjbeloro curnode = prom_nextnode(curnode)) { 474d1a96f96Sanovick bzero(tmp_name, sizeof (tmp_name)); 475d1a96f96Sanovick if (prom_bounded_getprop(curnode, OBP_DEVICETYPE, tmp_name, 476d1a96f96Sanovick sizeof (OBP_CPU)) == -1 || strcmp(tmp_name, OBP_CPU) != 0) 477d58fda43Sjbeloro continue; 478d58fda43Sjbeloro 479d58fda43Sjbeloro cpucnt++; 480d1a96f96Sanovick 481d58fda43Sjbeloro if (prom_getprop(curnode, "portid", (caddr_t)&portid) != 482d58fda43Sjbeloro -1 && portid > max_portid) 483d58fda43Sjbeloro max_portid = portid; 484d58fda43Sjbeloro } 485d58fda43Sjbeloro if (cpucnt <= 1) 486d58fda43Sjbeloro max_mem_nodes = 1; 487d58fda43Sjbeloro else if (max_portid >= 0 && max_portid < MAX_MEM_NODES) 488d58fda43Sjbeloro max_mem_nodes = max_portid + 1; 489d58fda43Sjbeloro 490d58fda43Sjbeloro /* 491d58fda43Sjbeloro * Set tuneables for fiesta architecture 492d58fda43Sjbeloro * 493d58fda43Sjbeloro * lgrp_expand_proc_thresh is the minimum load on the lgroups 494d58fda43Sjbeloro * this process is currently running on before considering 495d58fda43Sjbeloro * expanding threads to another lgroup. 496d58fda43Sjbeloro * 497d58fda43Sjbeloro * lgrp_expand_proc_diff determines how much less the remote lgroup 498d58fda43Sjbeloro * must be loaded before expanding to it. 499d58fda43Sjbeloro * 500d58fda43Sjbeloro * Optimize for memory bandwidth by spreading multi-threaded 501d58fda43Sjbeloro * program to different lgroups. 502d58fda43Sjbeloro */ 503d58fda43Sjbeloro lgrp_expand_proc_thresh = lgrp_loadavg_max_effect - 1; 504d58fda43Sjbeloro lgrp_expand_proc_diff = lgrp_loadavg_max_effect / 2; 505d58fda43Sjbeloro lgrp_loadavg_tolerance = lgrp_loadavg_max_effect / 2; 506d58fda43Sjbeloro lgrp_mem_free_thresh = 1; /* home lgrp must have some memory */ 507d58fda43Sjbeloro lgrp_expand_proc_thresh = lgrp_loadavg_max_effect - 1; 508d58fda43Sjbeloro lgrp_mem_policy_root = LGRP_MEM_POLICY_NEXT; 509d58fda43Sjbeloro lgrp_load_thresh = 0; 510d58fda43Sjbeloro 511d58fda43Sjbeloro mem_node_pfn_shift = PLATFORM_MC_SHIFT - MMU_PAGESHIFT; 512d58fda43Sjbeloro } 513d58fda43Sjbeloro 514d58fda43Sjbeloro /* 515d58fda43Sjbeloro * Return latency between "from" and "to" lgroups 516d58fda43Sjbeloro * 517d58fda43Sjbeloro * This latency number can only be used for relative comparison 518d58fda43Sjbeloro * between lgroups on the running system, cannot be used across platforms, 519d58fda43Sjbeloro * and may not reflect the actual latency. It is platform and implementation 520d58fda43Sjbeloro * specific, so platform gets to decide its value. It would be nice if the 521d58fda43Sjbeloro * number was at least proportional to make comparisons more meaningful though. 522d58fda43Sjbeloro * NOTE: The numbers below are supposed to be load latencies for uncached 523d58fda43Sjbeloro * memory divided by 10. 524d58fda43Sjbeloro */ 525d58fda43Sjbeloro int 526d58fda43Sjbeloro plat_lgrp_latency(void *from, void *to) 527d58fda43Sjbeloro { 528d58fda43Sjbeloro /* 529d58fda43Sjbeloro * Return remote latency when there are more than two lgroups 530d58fda43Sjbeloro * (root and child) and getting latency between two different 531d58fda43Sjbeloro * lgroups or root is involved 532d58fda43Sjbeloro */ 533d58fda43Sjbeloro if (lgrp_optimizations() && (from != to || from == 534d58fda43Sjbeloro (void *) LGRP_DEFAULT_HANDLE || to == (void *) LGRP_DEFAULT_HANDLE)) 535d58fda43Sjbeloro return (17); 536d58fda43Sjbeloro else 537d58fda43Sjbeloro return (12); 538d58fda43Sjbeloro } 539d58fda43Sjbeloro 540d58fda43Sjbeloro int 541d58fda43Sjbeloro plat_pfn_to_mem_node(pfn_t pfn) 542d58fda43Sjbeloro { 543d58fda43Sjbeloro ASSERT(max_mem_nodes > 1); 544d58fda43Sjbeloro return (pfn >> mem_node_pfn_shift); 545d58fda43Sjbeloro } 546d58fda43Sjbeloro 547d58fda43Sjbeloro /* 548d58fda43Sjbeloro * Assign memnode to lgroups 549d58fda43Sjbeloro */ 550d58fda43Sjbeloro void 551d58fda43Sjbeloro plat_fill_mc(pnode_t nodeid) 552d58fda43Sjbeloro { 553d58fda43Sjbeloro int portid; 554d58fda43Sjbeloro 555d58fda43Sjbeloro /* 556d58fda43Sjbeloro * Memory controller portid == global CPU id 557d58fda43Sjbeloro */ 558d58fda43Sjbeloro if ((prom_getprop(nodeid, "portid", (caddr_t)&portid) == -1) || 559d58fda43Sjbeloro (portid < 0)) 560d58fda43Sjbeloro return; 561d58fda43Sjbeloro 562d58fda43Sjbeloro if (portid < max_mem_nodes) 563d58fda43Sjbeloro plat_assign_lgrphand_to_mem_node((lgrp_handle_t)portid, portid); 564d58fda43Sjbeloro } 565d58fda43Sjbeloro 566d58fda43Sjbeloro /* 567d58fda43Sjbeloro * Common locking enter code 568d58fda43Sjbeloro */ 569d58fda43Sjbeloro void 570d58fda43Sjbeloro plat_setprop_enter(void) 571d58fda43Sjbeloro { 572d58fda43Sjbeloro mutex_enter(&mi2cv_mutex); 573d58fda43Sjbeloro } 574d58fda43Sjbeloro 575d58fda43Sjbeloro /* 576d58fda43Sjbeloro * Common locking exit code 577d58fda43Sjbeloro */ 578d58fda43Sjbeloro void 579d58fda43Sjbeloro plat_setprop_exit(void) 580d58fda43Sjbeloro { 581d58fda43Sjbeloro mutex_exit(&mi2cv_mutex); 582d58fda43Sjbeloro } 583d58fda43Sjbeloro 584d58fda43Sjbeloro /* 585d58fda43Sjbeloro * Called by mi2cv driver 586d58fda43Sjbeloro */ 587d58fda43Sjbeloro void 588d58fda43Sjbeloro plat_shared_i2c_enter(dev_info_t *i2cnexus_dip) 589d58fda43Sjbeloro { 590d58fda43Sjbeloro if (i2cnexus_dip == shared_mi2cv_dip) { 591d58fda43Sjbeloro plat_setprop_enter(); 592d58fda43Sjbeloro } 593d58fda43Sjbeloro } 594d58fda43Sjbeloro 595d58fda43Sjbeloro /* 596d58fda43Sjbeloro * Called by mi2cv driver 597d58fda43Sjbeloro */ 598d58fda43Sjbeloro void 599d58fda43Sjbeloro plat_shared_i2c_exit(dev_info_t *i2cnexus_dip) 600d58fda43Sjbeloro { 601d58fda43Sjbeloro if (i2cnexus_dip == shared_mi2cv_dip) { 602d58fda43Sjbeloro plat_setprop_exit(); 603d58fda43Sjbeloro } 604d58fda43Sjbeloro } 605d58fda43Sjbeloro /* 606d58fda43Sjbeloro * Called by todm5823 driver 607d58fda43Sjbeloro */ 608d58fda43Sjbeloro void 609d58fda43Sjbeloro plat_rmc_comm_req(struct rmc_comm_msg *request) 610d58fda43Sjbeloro { 611d58fda43Sjbeloro if (rmc_req_now) 612d58fda43Sjbeloro (void) rmc_req_now(request, 0); 613d58fda43Sjbeloro } 614