1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 30*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 31*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/esunddi.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/sunndi.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate #include <sys/platform_module.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate #include <sys/sunldi.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/file.h> 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate #define SHARED_PCF8584_PATH "/pci@8,700000/ebus@5/i2c@1,2e/nvram@0,a0" 44*7c478bd9Sstevel@tonic-gate static dev_info_t *shared_pcf8584_dip; 45*7c478bd9Sstevel@tonic-gate static kmutex_t excal_pcf8584_mutex; 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate int (*p2get_mem_unum)(int, uint64_t, char *, int, int *); 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate /* 50*7c478bd9Sstevel@tonic-gate * Excalibur fan information 51*7c478bd9Sstevel@tonic-gate */ 52*7c478bd9Sstevel@tonic-gate typedef struct xcalfan_info { 53*7c478bd9Sstevel@tonic-gate char *pathname; 54*7c478bd9Sstevel@tonic-gate int8_t val8; 55*7c478bd9Sstevel@tonic-gate ldi_handle_t lh; 56*7c478bd9Sstevel@tonic-gate } xcalfan_info_t; 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate static xcalfan_info_t xcalfans[] = { 59*7c478bd9Sstevel@tonic-gate {"/pci@8,700000/ebus@5/i2c@1,30/fan-control@0,48:2", 63, NULL}, 60*7c478bd9Sstevel@tonic-gate {"/pci@8,700000/ebus@5/i2c@1,30/fan-control@0,48:0", 63, NULL}, 61*7c478bd9Sstevel@tonic-gate {"/pci@8,700000/ebus@5/i2c@1,30/fan-control@0,48:4", 31, NULL} 62*7c478bd9Sstevel@tonic-gate }; 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate #define NFANS (sizeof (xcalfans) / sizeof (xcalfans[0])) 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate void 67*7c478bd9Sstevel@tonic-gate startup_platform(void) 68*7c478bd9Sstevel@tonic-gate { 69*7c478bd9Sstevel@tonic-gate mutex_init(&excal_pcf8584_mutex, NULL, NULL, NULL); 70*7c478bd9Sstevel@tonic-gate } 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate int 73*7c478bd9Sstevel@tonic-gate set_platform_tsb_spares() 74*7c478bd9Sstevel@tonic-gate { 75*7c478bd9Sstevel@tonic-gate return (0); 76*7c478bd9Sstevel@tonic-gate } 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate void 79*7c478bd9Sstevel@tonic-gate set_platform_defaults(void) 80*7c478bd9Sstevel@tonic-gate { 81*7c478bd9Sstevel@tonic-gate } 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate void 84*7c478bd9Sstevel@tonic-gate load_platform_drivers(void) 85*7c478bd9Sstevel@tonic-gate { 86*7c478bd9Sstevel@tonic-gate ldi_ident_t li; 87*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 88*7c478bd9Sstevel@tonic-gate char **drv; 89*7c478bd9Sstevel@tonic-gate int i, err; 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate static char *boot_time_drivers[] = { 92*7c478bd9Sstevel@tonic-gate "todds1287", 93*7c478bd9Sstevel@tonic-gate "us", 94*7c478bd9Sstevel@tonic-gate "mc-us3", 95*7c478bd9Sstevel@tonic-gate "bbc_beep", 96*7c478bd9Sstevel@tonic-gate "max1617", 97*7c478bd9Sstevel@tonic-gate "tda8444", 98*7c478bd9Sstevel@tonic-gate "seeprom", 99*7c478bd9Sstevel@tonic-gate NULL 100*7c478bd9Sstevel@tonic-gate }; 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate for (drv = boot_time_drivers; *drv; drv++) { 103*7c478bd9Sstevel@tonic-gate if ((i_ddi_attach_hw_nodes(*drv) != DDI_SUCCESS) && 104*7c478bd9Sstevel@tonic-gate (strcmp(*drv, "us") != 0)) 105*7c478bd9Sstevel@tonic-gate /* 106*7c478bd9Sstevel@tonic-gate * It is OK if 'us' driver doesn't load. It's 107*7c478bd9Sstevel@tonic-gate * not available in Core cluster. 108*7c478bd9Sstevel@tonic-gate */ 109*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "Failed to install \"%s\" driver.", 110*7c478bd9Sstevel@tonic-gate *drv); 111*7c478bd9Sstevel@tonic-gate } 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate /* 114*7c478bd9Sstevel@tonic-gate * mc-us3 must stay loaded for plat_get_mem_unum() 115*7c478bd9Sstevel@tonic-gate */ 116*7c478bd9Sstevel@tonic-gate (void) ddi_hold_driver(ddi_name_to_major("mc-us3")); 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate /* 119*7c478bd9Sstevel@tonic-gate * Figure out which pcf8584_dip is shared with OBP for the nvram 120*7c478bd9Sstevel@tonic-gate * device, so the lock can be acquired. 121*7c478bd9Sstevel@tonic-gate * 122*7c478bd9Sstevel@tonic-gate * This should really be done elsewhere, like startup_platform, but 123*7c478bd9Sstevel@tonic-gate * that runs before the devinfo tree is setup with configure(). 124*7c478bd9Sstevel@tonic-gate * So it is here until there is a better place. 125*7c478bd9Sstevel@tonic-gate */ 126*7c478bd9Sstevel@tonic-gate dip = e_ddi_hold_devi_by_path(SHARED_PCF8584_PATH, 0); 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate ASSERT(dip != NULL); 129*7c478bd9Sstevel@tonic-gate shared_pcf8584_dip = ddi_get_parent(dip); 130*7c478bd9Sstevel@tonic-gate 131*7c478bd9Sstevel@tonic-gate ndi_hold_devi(shared_pcf8584_dip); 132*7c478bd9Sstevel@tonic-gate ndi_rele_devi(dip); 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate li = ldi_ident_from_anon(); 135*7c478bd9Sstevel@tonic-gate for (i = 0; i < NFANS; ++i) { 136*7c478bd9Sstevel@tonic-gate err = ldi_open_by_name(xcalfans[i].pathname, 137*7c478bd9Sstevel@tonic-gate FWRITE, kcred, &xcalfans[i].lh, li); 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate if (err != 0) { 140*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "plat_fan_blast: " 141*7c478bd9Sstevel@tonic-gate "Failed to get fan device handle for %s", 142*7c478bd9Sstevel@tonic-gate xcalfans[i].pathname); 143*7c478bd9Sstevel@tonic-gate continue; 144*7c478bd9Sstevel@tonic-gate } 145*7c478bd9Sstevel@tonic-gate } 146*7c478bd9Sstevel@tonic-gate ldi_ident_release(li); 147*7c478bd9Sstevel@tonic-gate } 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 150*7c478bd9Sstevel@tonic-gate int 151*7c478bd9Sstevel@tonic-gate plat_cpu_poweron(struct cpu *cp) 152*7c478bd9Sstevel@tonic-gate { 153*7c478bd9Sstevel@tonic-gate return (ENOTSUP); /* not supported on this platform */ 154*7c478bd9Sstevel@tonic-gate } 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 157*7c478bd9Sstevel@tonic-gate int 158*7c478bd9Sstevel@tonic-gate plat_cpu_poweroff(struct cpu *cp) 159*7c478bd9Sstevel@tonic-gate { 160*7c478bd9Sstevel@tonic-gate return (ENOTSUP); /* not supported on this platform */ 161*7c478bd9Sstevel@tonic-gate } 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 164*7c478bd9Sstevel@tonic-gate void 165*7c478bd9Sstevel@tonic-gate plat_freelist_process(int mnode) 166*7c478bd9Sstevel@tonic-gate { 167*7c478bd9Sstevel@tonic-gate } 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate char *platform_module_list[] = { 170*7c478bd9Sstevel@tonic-gate "schppm", /* must attach before xcalppm */ 171*7c478bd9Sstevel@tonic-gate "xcalppm", 172*7c478bd9Sstevel@tonic-gate (char *)0 173*7c478bd9Sstevel@tonic-gate }; 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 176*7c478bd9Sstevel@tonic-gate void 177*7c478bd9Sstevel@tonic-gate plat_tod_fault(enum tod_fault_type tod_bad) 178*7c478bd9Sstevel@tonic-gate { 179*7c478bd9Sstevel@tonic-gate } 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 182*7c478bd9Sstevel@tonic-gate int 183*7c478bd9Sstevel@tonic-gate plat_get_mem_unum(int synd_code, uint64_t flt_addr, int flt_bus_id, 184*7c478bd9Sstevel@tonic-gate int flt_in_memory, ushort_t flt_status, char *buf, int buflen, int *lenp) 185*7c478bd9Sstevel@tonic-gate { 186*7c478bd9Sstevel@tonic-gate if (flt_in_memory && (p2get_mem_unum != NULL)) 187*7c478bd9Sstevel@tonic-gate return (p2get_mem_unum(synd_code, P2ALIGN(flt_addr, 8), 188*7c478bd9Sstevel@tonic-gate buf, buflen, lenp)); 189*7c478bd9Sstevel@tonic-gate else 190*7c478bd9Sstevel@tonic-gate return (ENOTSUP); 191*7c478bd9Sstevel@tonic-gate } 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate int 194*7c478bd9Sstevel@tonic-gate plat_get_cpu_unum(int cpuid, char *buf, int buflen, int *lenp) 195*7c478bd9Sstevel@tonic-gate { 196*7c478bd9Sstevel@tonic-gate if (snprintf(buf, buflen, "Slot %d", cpuid) >= buflen) { 197*7c478bd9Sstevel@tonic-gate return (ENOSPC); 198*7c478bd9Sstevel@tonic-gate } else { 199*7c478bd9Sstevel@tonic-gate *lenp = strlen(buf); 200*7c478bd9Sstevel@tonic-gate return (0); 201*7c478bd9Sstevel@tonic-gate } 202*7c478bd9Sstevel@tonic-gate } 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate /* 205*7c478bd9Sstevel@tonic-gate * Unfortunately, excal's BBC pcf8584 controller is used by both OBP 206*7c478bd9Sstevel@tonic-gate * and the OS's i2c drivers. The 'eeprom' command executes 207*7c478bd9Sstevel@tonic-gate * OBP code to handle property requests. If eeprom didn't do this, or if the 208*7c478bd9Sstevel@tonic-gate * controllers were partitioned so that all devices on a given controller were 209*7c478bd9Sstevel@tonic-gate * driven by either OBP or the OS, this wouldn't be necessary. 210*7c478bd9Sstevel@tonic-gate * 211*7c478bd9Sstevel@tonic-gate * Note that getprop doesn't have the same issue as it reads from cached 212*7c478bd9Sstevel@tonic-gate * memory in OBP. 213*7c478bd9Sstevel@tonic-gate */ 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate /* 216*7c478bd9Sstevel@tonic-gate * Common locking enter code 217*7c478bd9Sstevel@tonic-gate */ 218*7c478bd9Sstevel@tonic-gate void 219*7c478bd9Sstevel@tonic-gate plat_setprop_enter(void) 220*7c478bd9Sstevel@tonic-gate { 221*7c478bd9Sstevel@tonic-gate mutex_enter(&excal_pcf8584_mutex); 222*7c478bd9Sstevel@tonic-gate } 223*7c478bd9Sstevel@tonic-gate 224*7c478bd9Sstevel@tonic-gate /* 225*7c478bd9Sstevel@tonic-gate * Common locking exit code 226*7c478bd9Sstevel@tonic-gate */ 227*7c478bd9Sstevel@tonic-gate void 228*7c478bd9Sstevel@tonic-gate plat_setprop_exit(void) 229*7c478bd9Sstevel@tonic-gate { 230*7c478bd9Sstevel@tonic-gate mutex_exit(&excal_pcf8584_mutex); 231*7c478bd9Sstevel@tonic-gate } 232*7c478bd9Sstevel@tonic-gate 233*7c478bd9Sstevel@tonic-gate /* 234*7c478bd9Sstevel@tonic-gate * Called by pcf8584 driver 235*7c478bd9Sstevel@tonic-gate */ 236*7c478bd9Sstevel@tonic-gate void 237*7c478bd9Sstevel@tonic-gate plat_shared_i2c_enter(dev_info_t *dip) 238*7c478bd9Sstevel@tonic-gate { 239*7c478bd9Sstevel@tonic-gate if (dip == shared_pcf8584_dip) { 240*7c478bd9Sstevel@tonic-gate plat_setprop_enter(); 241*7c478bd9Sstevel@tonic-gate } 242*7c478bd9Sstevel@tonic-gate } 243*7c478bd9Sstevel@tonic-gate 244*7c478bd9Sstevel@tonic-gate /* 245*7c478bd9Sstevel@tonic-gate * Called by pcf8584 driver 246*7c478bd9Sstevel@tonic-gate */ 247*7c478bd9Sstevel@tonic-gate void 248*7c478bd9Sstevel@tonic-gate plat_shared_i2c_exit(dev_info_t *dip) 249*7c478bd9Sstevel@tonic-gate { 250*7c478bd9Sstevel@tonic-gate if (dip == shared_pcf8584_dip) { 251*7c478bd9Sstevel@tonic-gate plat_setprop_exit(); 252*7c478bd9Sstevel@tonic-gate } 253*7c478bd9Sstevel@tonic-gate } 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate /* 256*7c478bd9Sstevel@tonic-gate * Set platform fans to maximum speed 257*7c478bd9Sstevel@tonic-gate */ 258*7c478bd9Sstevel@tonic-gate void 259*7c478bd9Sstevel@tonic-gate plat_fan_blast(void) 260*7c478bd9Sstevel@tonic-gate { 261*7c478bd9Sstevel@tonic-gate struct uio uio; 262*7c478bd9Sstevel@tonic-gate struct iovec iov; 263*7c478bd9Sstevel@tonic-gate int8_t fv; 264*7c478bd9Sstevel@tonic-gate int err; 265*7c478bd9Sstevel@tonic-gate int i; 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate for (i = 0; i < NFANS; ++i) { 268*7c478bd9Sstevel@tonic-gate fv = xcalfans[i].val8; 269*7c478bd9Sstevel@tonic-gate bzero(&uio, sizeof (uio)); 270*7c478bd9Sstevel@tonic-gate bzero(&iov, sizeof (iov)); 271*7c478bd9Sstevel@tonic-gate iov.iov_base = &fv; 272*7c478bd9Sstevel@tonic-gate iov.iov_len = sizeof (fv); 273*7c478bd9Sstevel@tonic-gate uio.uio_iov = &iov; 274*7c478bd9Sstevel@tonic-gate uio.uio_iovcnt = 1; 275*7c478bd9Sstevel@tonic-gate uio.uio_loffset = 0; 276*7c478bd9Sstevel@tonic-gate uio.uio_segflg = UIO_SYSSPACE; 277*7c478bd9Sstevel@tonic-gate uio.uio_resid = sizeof (fv); 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate err = ldi_write(xcalfans[i].lh, &uio, kcred); 280*7c478bd9Sstevel@tonic-gate if (err != 0) { 281*7c478bd9Sstevel@tonic-gate if (err == EAGAIN) { 282*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "!plat_fan_blast: Cannot " 283*7c478bd9Sstevel@tonic-gate "write %d to %s now, try again later.", 284*7c478bd9Sstevel@tonic-gate xcalfans[i].val8, xcalfans[i].pathname); 285*7c478bd9Sstevel@tonic-gate } else { 286*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "plat_fan_blast: " 287*7c478bd9Sstevel@tonic-gate "Error %d while writing %d to %s.", err, 288*7c478bd9Sstevel@tonic-gate xcalfans[i].val8, xcalfans[i].pathname); 289*7c478bd9Sstevel@tonic-gate } 290*7c478bd9Sstevel@tonic-gate } 291*7c478bd9Sstevel@tonic-gate } 292*7c478bd9Sstevel@tonic-gate } 293