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 2008 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 /* 30 * Library file that has miscellaneous support for npe(7d) 31 */ 32 33 #include <sys/conf.h> 34 #include <sys/pci.h> 35 #include <sys/sunndi.h> 36 #include <sys/acpi/acpi.h> 37 #include <sys/acpi/acpi_pci.h> 38 #include <sys/acpica.h> 39 #include <sys/pci_cap.h> 40 #include <sys/pcie_impl.h> 41 #include <io/pciex/pcie_nvidia.h> 42 #include <io/pciex/pcie_nb5000.h> 43 44 /* 45 * Prototype declaration 46 */ 47 void npe_query_acpi_mcfg(dev_info_t *dip); 48 void npe_ck804_fix_aer_ptr(ddi_acc_handle_t cfg_hdl); 49 int npe_disable_empty_bridges_workaround(dev_info_t *child); 50 void npe_nvidia_error_mask(ddi_acc_handle_t cfg_hdl); 51 void npe_intel_error_mask(ddi_acc_handle_t cfg_hdl); 52 53 /* 54 * Default ecfga base address 55 */ 56 int64_t npe_default_ecfga_base = 0xE0000000; 57 58 extern uint32_t npe_aer_uce_mask; 59 extern boolean_t pcie_full_scan; 60 61 /* 62 * Query the MCFG table using ACPI. If MCFG is found, setup the 63 * 'ecfga-base-address' (Enhanced Configuration Access base address) 64 * property accordingly. Otherwise, set the value of the property 65 * to the default value. 66 */ 67 void 68 npe_query_acpi_mcfg(dev_info_t *dip) 69 { 70 MCFG_TABLE *mcfgp; 71 CFG_BASE_ADDR_ALLOC *cfg_baap; 72 char *cfg_baa_endp; 73 uint64_t ecfga_base; 74 75 /* Query the MCFG table using ACPI */ 76 if (AcpiGetFirmwareTable(MCFG_SIG, 1, ACPI_LOGICAL_ADDRESSING, 77 (ACPI_TABLE_HEADER **)&mcfgp) == AE_OK) { 78 79 cfg_baap = (CFG_BASE_ADDR_ALLOC *)mcfgp->CfgBaseAddrAllocList; 80 cfg_baa_endp = ((char *)mcfgp) + mcfgp->Length; 81 82 while ((char *)cfg_baap < cfg_baa_endp) { 83 ecfga_base = ACPI_GET_ADDRESS(cfg_baap->base_addr); 84 if (ecfga_base != (uint64_t)0) { 85 /* 86 * Setup the 'ecfga-base-address' property to 87 * the base_addr found in the MCFG and return. 88 */ 89 (void) ndi_prop_update_int64(DDI_DEV_T_NONE, 90 dip, "ecfga-base-address", ecfga_base); 91 return; 92 } 93 cfg_baap++; 94 } 95 } 96 /* 97 * If MCFG is not found or ecfga_base is not found in MCFG table, 98 * set the 'ecfga-base-address' property to the default value. 99 */ 100 (void) ndi_prop_update_int64(DDI_DEV_T_NONE, dip, 101 "ecfga-base-address", npe_default_ecfga_base); 102 } 103 104 105 /* 106 * Enable reporting of AER capability next pointer. 107 * This needs to be done only for CK8-04 devices 108 * by setting NV_XVR_VEND_CYA1 (offset 0xf40) bit 13 109 * NOTE: BIOS is disabling this, it needs to be enabled temporarily 110 */ 111 void 112 npe_ck804_fix_aer_ptr(ddi_acc_handle_t cfg_hdl) 113 { 114 ushort_t cya1; 115 116 if ((pci_config_get16(cfg_hdl, PCI_CONF_VENID) == NVIDIA_VENDOR_ID) && 117 (pci_config_get16(cfg_hdl, PCI_CONF_DEVID) == 118 NVIDIA_CK804_DEVICE_ID) && 119 (pci_config_get8(cfg_hdl, PCI_CONF_REVID) >= 120 NVIDIA_CK804_AER_VALID_REVID)) { 121 cya1 = pci_config_get16(cfg_hdl, NVIDIA_CK804_VEND_CYA1_OFF); 122 if (!(cya1 & ~NVIDIA_CK804_VEND_CYA1_ERPT_MASK)) 123 (void) pci_config_put16(cfg_hdl, 124 NVIDIA_CK804_VEND_CYA1_OFF, 125 cya1 | NVIDIA_CK804_VEND_CYA1_ERPT_VAL); 126 } 127 } 128 129 /* 130 * If the bridge is empty, disable it 131 */ 132 int 133 npe_disable_empty_bridges_workaround(dev_info_t *child) 134 { 135 /* 136 * Do not bind drivers to empty bridges. 137 * Fail above, if the bridge is found to be hotplug capable 138 */ 139 if (ddi_driver_major(child) == ddi_name_to_major("pcie_pci") && 140 ddi_get_child(child) == NULL && 141 ddi_prop_get_int(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, 142 "pci-hotplug-type", INBAND_HPC_NONE) == INBAND_HPC_NONE) 143 return (1); 144 145 return (0); 146 } 147 148 void 149 npe_nvidia_error_mask(ddi_acc_handle_t cfg_hdl) { 150 uint32_t regs; 151 uint16_t vendor_id = pci_config_get16(cfg_hdl, PCI_CONF_VENID); 152 uint16_t dev_id = pci_config_get16(cfg_hdl, PCI_CONF_DEVID); 153 154 if ((vendor_id == NVIDIA_VENDOR_ID) && NVIDIA_PCIE_RC_DEV_ID(dev_id)) { 155 /* Disable ECRC for all devices */ 156 regs = pcie_get_aer_uce_mask() | npe_aer_uce_mask | 157 PCIE_AER_UCE_ECRC; 158 pcie_set_aer_uce_mask(regs); 159 160 /* 161 * Turn full scan on since the Error Source ID register may not 162 * have the correct ID. 163 */ 164 pcie_full_scan = B_TRUE; 165 } 166 } 167 168 void 169 npe_intel_error_mask(ddi_acc_handle_t cfg_hdl) { 170 uint32_t regs; 171 uint16_t vendor_id = pci_config_get16(cfg_hdl, PCI_CONF_VENID); 172 173 if (vendor_id == INTEL_VENDOR_ID) { 174 /* 175 * Due to an errata in Intel's ESB2 southbridge, all ECRCs 176 * generation/checking need to be disabled. There is a 177 * workaround by setting a proprietary bit in the ESB2, but it 178 * is not well documented or understood. If that bit is set in 179 * the future, then ECRC generation/checking should be enabled 180 * again. 181 * 182 * Disable ECRC generation/checking by masking ECRC in the AER 183 * UE Mask. The pcie misc module would then automatically 184 * disable ECRC generation/checking in the AER Control register. 185 */ 186 regs = pcie_get_aer_uce_mask() | PCIE_AER_UCE_ECRC; 187 pcie_set_aer_uce_mask(regs); 188 } 189 } 190