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