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, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #pragma ident   "%Z%%M% %I%     %E% SMI"
  28 
  29 #include <sys/param.h>
  30 #include <sys/systm.h>
  31 #include <sys/sysmacros.h>
  32 #include <sys/sunddi.h>
  33 #include <sys/esunddi.h>
  34 #include <sys/sunndi.h>
  35 
  36 #include <sys/platform_module.h>
  37 #include <sys/errno.h>
  38 
  39 #define SHARED_SMBUS_PATH       "/pci@1f,0/pci@1,1/pmu@3/i2c@0,0/i2c-nvram@0,8e"
  40 static dev_info_t *shared_smbus_dip;
  41 static kmutex_t snowbird_smbus_mutex;
  42 
  43 void
  44 startup_platform(void)
  45 {
  46         mutex_init(&snowbird_smbus_mutex, NULL, NULL, NULL);
  47 }
  48 
  49 int
  50 set_platform_tsb_spares()
  51 {
  52         return (0);
  53 }
  54 
  55 void
  56 set_platform_defaults(void)
  57 {
  58         extern char *tod_module_name;
  59         tod_module_name = "todds1307";
  60 }
  61 
  62 /*
  63  * Definitions for accessing the pci config space of the isa node
  64  * of Southbridge.
  65  */
  66 #define PLATFORM_ISA_PATHNAME   "/pci@1f,0/isa@7"
  67 #define PLATFORM_ISA_PATHNAME_WITH_SIMBA        "/pci@1f,0/pci@1,1/isa@7"
  68 ddi_acc_handle_t        platform_isa_handle;    /* handle for isa pci space */
  69 
  70 void
  71 load_platform_drivers(void)
  72 {
  73         dev_info_t              *dip;           /* dip of the isa driver */
  74 
  75         if (ddi_install_driver("power") != DDI_SUCCESS)
  76                 cmn_err(CE_WARN, "Failed to install \"power\" driver.");
  77 
  78         /*
  79          * It is OK to return error because 'us' driver is not available
  80          * in all clusters (e.g. missing in Core cluster).
  81          */
  82         (void) ddi_install_driver("us");
  83 
  84         /*
  85          * Install Isa driver. This is required for the southbridge IDE
  86          * workaround - to reset the IDE channel during IDE bus reset.
  87          * Panic the system in case ISA driver could not be loaded or
  88          * any problem in accessing its pci config space. Since the register
  89          * to reset the channel for IDE is in ISA config space!.
  90          */
  91         dip = e_ddi_hold_devi_by_path(PLATFORM_ISA_PATHNAME_WITH_SIMBA, 0);
  92 
  93         if (dip == NULL)
  94             dip = e_ddi_hold_devi_by_path(PLATFORM_ISA_PATHNAME, 0);
  95 
  96         if (dip == NULL) {
  97                 cmn_err(CE_PANIC, "Could not install the isa driver\n");
  98                 return;
  99         }
 100 
 101         if (pci_config_setup(dip, &platform_isa_handle) != DDI_SUCCESS) {
 102                 cmn_err(CE_PANIC, "Could not get the config space of isa\n");
 103                 return;
 104         }
 105 
 106         /*
 107          * Figure out which smbus_dip is shared with OBP for the nvram
 108          * device, so the lock can be acquired.
 109          *
 110          * This should really be done elsewhere, like startup_platform, but
 111          * that runs before the devinfo tree is setup with configure().
 112          * So it is here until there is a better place.
 113          */
 114         dip = e_ddi_hold_devi_by_path(SHARED_SMBUS_PATH, 0);
 115 
 116         if (dip != NULL) {
 117                 ASSERT(dip != NULL);
 118                 shared_smbus_dip = ddi_get_parent(dip);
 119 
 120                 ndi_hold_devi(shared_smbus_dip);
 121                 ndi_rele_devi(dip);
 122         } else {
 123                 shared_smbus_dip = NULL;
 124         }
 125 
 126         /*
 127          * Install the TOD driver
 128          */
 129         if (ddi_install_driver("todds1307") != DDI_SUCCESS)
 130                 cmn_err(CE_WARN, "Failed to install \"todds1307\" driver.");
 131 }
 132 
 133 /*
 134  * This routine provides a workaround for a bug in the SB chip which
 135  * can cause data corruption. Will be invoked from the IDE HBA driver for
 136  * Acer SouthBridge at the time of IDE bus reset.
 137  */
 138 /*ARGSUSED*/
 139 int
 140 plat_ide_chipreset(dev_info_t *dip, int chno)
 141 {
 142         uint8_t val;
 143         int     ret = DDI_SUCCESS;
 144 
 145         val = pci_config_get8(platform_isa_handle, 0x58);
 146         /*
 147          * The dip passed as the argument is not used for snowbird.
 148          * This will be needed for platforms which have multiple on-board SB,
 149          * The dip passed will be used to match the corresponding ISA node.
 150          */
 151         switch (chno) {
 152                 case 0:
 153                         /*
 154                          * First disable the primary channel then re-enable it.
 155                          * As per ALI no wait should be required in between have
 156                          * given 1ms delay in between to be on safer side.
 157                          * bit 2 of register 0x58 when 0 disable the channel 0.
 158                          * bit 2 of register 0x58 when 1 enables the channel 0.
 159                          */
 160                         pci_config_put8(platform_isa_handle, 0x58, val & 0xFB);
 161                         drv_usecwait(1000);
 162                         pci_config_put8(platform_isa_handle, 0x58, val);
 163                         break;
 164                 case 1:
 165                         /*
 166                          * bit 3 of register 0x58 when 0 disable the channel 1.
 167                          * bit 3 of register 0x58 when 1 enables the channel 1.
 168                          */
 169                         pci_config_put8(platform_isa_handle, 0x58, val & 0xF7);
 170                         drv_usecwait(1000);
 171                         pci_config_put8(platform_isa_handle, 0x58, val);
 172                         break;
 173                 default:
 174                         /*
 175                          * Unknown channel number passed. Return failure.
 176                          */
 177                         ret = DDI_FAILURE;
 178         }
 179 
 180         return (ret);
 181 }
 182 
 183 
 184 
 185 /*ARGSUSED*/
 186 int
 187 plat_cpu_poweron(struct cpu *cp)
 188 {
 189         return (ENOTSUP);       /* not supported on this platform */
 190 }
 191 
 192 /*ARGSUSED*/
 193 int
 194 plat_cpu_poweroff(struct cpu *cp)
 195 {
 196         return (ENOTSUP);       /* not supported on this platform */
 197 }
 198 
 199 /*ARGSUSED*/
 200 void
 201 plat_freelist_process(int mnode)
 202 {
 203 }
 204 
 205 char *platform_module_list[] = {
 206         (char *)0
 207 };
 208 
 209 /*ARGSUSED*/
 210 void
 211 plat_tod_fault(enum tod_fault_type tod_bad)
 212 {
 213 }
 214 
 215 /*
 216  * Unfortunately, snowbird's smbus controller is used by both OBP
 217  * and the OS's i2c drivers.  The 'eeprom' command executes
 218  * OBP code to handle property requests.  If eeprom didn't do this, or if the
 219  * controllers were partitioned so that all devices on a given controller were
 220  * driven by either OBP or the OS, this wouldn't be necessary.
 221  *
 222  * Note that getprop doesn't have the same issue as it reads from cached
 223  * memory in OBP.
 224  */
 225 
 226 /*
 227  * Common locking enter code
 228  */
 229 void
 230 plat_setprop_enter(void)
 231 {
 232         mutex_enter(&snowbird_smbus_mutex);
 233 }
 234 
 235 /*
 236  * Common locking exit code
 237  */
 238 void
 239 plat_setprop_exit(void)
 240 {
 241         mutex_exit(&snowbird_smbus_mutex);
 242 }
 243 
 244 /*
 245  * Called by smbus driver
 246  */
 247 void
 248 plat_shared_i2c_enter(dev_info_t *dip)
 249 {
 250         if (dip == shared_smbus_dip) {
 251                 plat_setprop_enter();
 252         }
 253 }
 254 
 255 /*
 256  * Called by smbus driver
 257  */
 258 void
 259 plat_shared_i2c_exit(dev_info_t *dip)
 260 {
 261         if (dip == shared_smbus_dip) {
 262                 plat_setprop_exit();
 263         }
 264 }