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 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Library file that has miscellaneous support for npe(7d) 29 */ 30 31 #include <sys/conf.h> 32 #include <sys/pci.h> 33 #include <sys/sunndi.h> 34 #include <sys/acpi/acpi.h> 35 #include <sys/acpi/acpi_pci.h> 36 #include <sys/acpica.h> 37 #include <sys/pci_cap.h> 38 #include <sys/pcie_impl.h> 39 #include <sys/x86_archext.h> 40 #include <io/pciex/pcie_nvidia.h> 41 #include <io/pciex/pcie_nb5000.h> 42 43 /* 44 * Prototype declaration 45 */ 46 void npe_query_acpi_mcfg(dev_info_t *dip); 47 void npe_ck804_fix_aer_ptr(ddi_acc_handle_t cfg_hdl); 48 int npe_disable_empty_bridges_workaround(dev_info_t *child); 49 void npe_nvidia_error_mask(ddi_acc_handle_t cfg_hdl); 50 void npe_intel_error_mask(ddi_acc_handle_t cfg_hdl); 51 boolean_t npe_is_child_pci(dev_info_t *dip); 52 boolean_t check_and_set_mmcfg(dev_info_t *dip); 53 54 /* 55 * Default ecfga base address 56 */ 57 int64_t npe_default_ecfga_base = 0xE0000000; 58 59 extern uint32_t npe_aer_uce_mask; 60 extern boolean_t pcie_full_scan; 61 62 /* AMD's northbridges vendor-id and device-ids */ 63 #define AMD_NTBRDIGE_VID 0x1022 /* AMD vendor-id */ 64 #define AMD_HT_NTBRIDGE_DID 0x1100 /* HT Configuration */ 65 #define AMD_AM_NTBRIDGE_DID 0x1101 /* Address Map */ 66 #define AMD_DC_NTBRIDGE_DID 0x1102 /* DRAM Controller */ 67 #define AMD_MC_NTBRIDGE_DID 0x1103 /* Misc Controller */ 68 #define AMD_K10_NTBRIDGE_DID_0 0x1200 69 #define AMD_K10_NTBRIDGE_DID_1 0x1201 70 #define AMD_K10_NTBRIDGE_DID_2 0x1202 71 #define AMD_K10_NTBRIDGE_DID_3 0x1203 72 #define AMD_K10_NTBRIDGE_DID_4 0x1204 73 74 /* 75 * Check if the given device is an AMD northbridge 76 */ 77 #define IS_BAD_AMD_NTBRIDGE(vid, did) \ 78 (((vid) == AMD_NTBRDIGE_VID) && \ 79 (((did) == AMD_HT_NTBRIDGE_DID) || \ 80 ((did) == AMD_AM_NTBRIDGE_DID) || \ 81 ((did) == AMD_DC_NTBRIDGE_DID) || \ 82 ((did) == AMD_MC_NTBRIDGE_DID))) 83 84 #define IS_K10_AMD_NTBRIDGE(vid, did) \ 85 (((vid) == AMD_NTBRDIGE_VID) && \ 86 (((did) == AMD_K10_NTBRIDGE_DID_0) || \ 87 ((did) == AMD_K10_NTBRIDGE_DID_1) || \ 88 ((did) == AMD_K10_NTBRIDGE_DID_2) || \ 89 ((did) == AMD_K10_NTBRIDGE_DID_3) || \ 90 ((did) == AMD_K10_NTBRIDGE_DID_4))) 91 92 #define MSR_AMD_NB_MMIO_CFG_BADDR 0xc0010058 93 #define AMD_MMIO_CFG_BADDR_ADDR_MASK 0xFFFFFFF00000ULL 94 #define AMD_MMIO_CFG_BADDR_ENA_MASK 0x000000000001ULL 95 #define AMD_MMIO_CFG_BADDR_ENA_ON 0x000000000001ULL 96 #define AMD_MMIO_CFG_BADDR_ENA_OFF 0x000000000000ULL 97 98 99 /* 100 * Query the MCFG table using ACPI. If MCFG is found, setup the 101 * 'ecfg' property accordingly. Otherwise, set the values 102 * to the default values. 103 */ 104 void 105 npe_query_acpi_mcfg(dev_info_t *dip) 106 { 107 MCFG_TABLE *mcfgp; 108 CFG_BASE_ADDR_ALLOC *cfg_baap; 109 char *cfg_baa_endp; 110 int64_t ecfginfo[4]; 111 int ecfg_found = 0; 112 113 /* Query the MCFG table using ACPI */ 114 if ((acpica_init() == AE_OK) && (AcpiGetTable(ACPI_SIG_MCFG, 1, 115 (ACPI_TABLE_HEADER **)&mcfgp) == AE_OK)) { 116 117 cfg_baap = (CFG_BASE_ADDR_ALLOC *)mcfgp->CfgBaseAddrAllocList; 118 cfg_baa_endp = ((char *)mcfgp) + mcfgp->Length; 119 120 while ((char *)cfg_baap < cfg_baa_endp) { 121 if (cfg_baap->base_addr != (uint64_t)0 && 122 cfg_baap->segment == 0) { 123 /* 124 * Set up the 'ecfg' property to hold 125 * base_addr, segment, and first/last bus. 126 * We only do the first entry that maps 127 * segment 0; nonzero segments are not yet 128 * known, or handled. If they appear, 129 * we'll need to figure out which bus node 130 * should have which entry by examining the 131 * ACPI _SEG method on each bus node. 132 */ 133 ecfginfo[0] = cfg_baap->base_addr; 134 ecfginfo[1] = cfg_baap->segment; 135 ecfginfo[2] = cfg_baap->start_bno; 136 ecfginfo[3] = cfg_baap->end_bno; 137 (void) ndi_prop_update_int64_array( 138 DDI_DEV_T_NONE, dip, "ecfg", 139 ecfginfo, 4); 140 ecfg_found = 1; 141 break; 142 } 143 cfg_baap++; 144 } 145 } 146 if (ecfg_found) 147 return; 148 /* 149 * If MCFG is not found or ecfga_base is not found in MCFG table, 150 * set the property to the default values. 151 */ 152 ecfginfo[0] = npe_default_ecfga_base; 153 ecfginfo[1] = 0; /* segment 0 */ 154 ecfginfo[2] = 0; /* first bus 0 */ 155 ecfginfo[3] = 0xff; /* last bus ff */ 156 (void) ndi_prop_update_int64_array(DDI_DEV_T_NONE, dip, 157 "ecfg", ecfginfo, 4); 158 } 159 160 161 /* 162 * Enable reporting of AER capability next pointer. 163 * This needs to be done only for CK8-04 devices 164 * by setting NV_XVR_VEND_CYA1 (offset 0xf40) bit 13 165 * NOTE: BIOS is disabling this, it needs to be enabled temporarily 166 */ 167 void 168 npe_ck804_fix_aer_ptr(ddi_acc_handle_t cfg_hdl) 169 { 170 ushort_t cya1; 171 172 if ((pci_config_get16(cfg_hdl, PCI_CONF_VENID) == NVIDIA_VENDOR_ID) && 173 (pci_config_get16(cfg_hdl, PCI_CONF_DEVID) == 174 NVIDIA_CK804_DEVICE_ID) && 175 (pci_config_get8(cfg_hdl, PCI_CONF_REVID) >= 176 NVIDIA_CK804_AER_VALID_REVID)) { 177 cya1 = pci_config_get16(cfg_hdl, NVIDIA_CK804_VEND_CYA1_OFF); 178 if (!(cya1 & ~NVIDIA_CK804_VEND_CYA1_ERPT_MASK)) 179 (void) pci_config_put16(cfg_hdl, 180 NVIDIA_CK804_VEND_CYA1_OFF, 181 cya1 | NVIDIA_CK804_VEND_CYA1_ERPT_VAL); 182 } 183 } 184 185 /* 186 * If the bridge is empty, disable it 187 */ 188 int 189 npe_disable_empty_bridges_workaround(dev_info_t *child) 190 { 191 /* 192 * Do not bind drivers to empty bridges. 193 * Fail above, if the bridge is found to be hotplug capable 194 */ 195 if (ddi_driver_major(child) == ddi_name_to_major("pcie_pci") && 196 ddi_get_child(child) == NULL && 197 ddi_prop_get_int(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, 198 "pci-hotplug-type", INBAND_HPC_NONE) == INBAND_HPC_NONE) 199 return (1); 200 201 return (0); 202 } 203 204 void 205 npe_nvidia_error_mask(ddi_acc_handle_t cfg_hdl) { 206 uint32_t regs; 207 uint16_t vendor_id = pci_config_get16(cfg_hdl, PCI_CONF_VENID); 208 uint16_t dev_id = pci_config_get16(cfg_hdl, PCI_CONF_DEVID); 209 210 if ((vendor_id == NVIDIA_VENDOR_ID) && NVIDIA_PCIE_RC_DEV_ID(dev_id)) { 211 /* Disable ECRC for all devices */ 212 regs = pcie_get_aer_uce_mask() | npe_aer_uce_mask | 213 PCIE_AER_UCE_ECRC; 214 pcie_set_aer_uce_mask(regs); 215 216 /* 217 * Turn full scan on since the Error Source ID register may not 218 * have the correct ID. 219 */ 220 pcie_full_scan = B_TRUE; 221 } 222 } 223 224 void 225 npe_intel_error_mask(ddi_acc_handle_t cfg_hdl) { 226 uint32_t regs; 227 uint16_t vendor_id = pci_config_get16(cfg_hdl, PCI_CONF_VENID); 228 229 if (vendor_id == INTEL_VENDOR_ID) { 230 /* 231 * Due to an errata in Intel's ESB2 southbridge, all ECRCs 232 * generation/checking need to be disabled. There is a 233 * workaround by setting a proprietary bit in the ESB2, but it 234 * is not well documented or understood. If that bit is set in 235 * the future, then ECRC generation/checking should be enabled 236 * again. 237 * 238 * Disable ECRC generation/checking by masking ECRC in the AER 239 * UE Mask. The pcie misc module would then automatically 240 * disable ECRC generation/checking in the AER Control register. 241 */ 242 regs = pcie_get_aer_uce_mask() | PCIE_AER_UCE_ECRC; 243 pcie_set_aer_uce_mask(regs); 244 } 245 } 246 247 /* 248 * Check's if this child is a PCI device. 249 * Child is a PCI device if: 250 * parent has a dev_type of "pci" 251 * -and- 252 * child does not have a dev_type of "pciex" 253 * 254 * If the parent is not of dev_type "pci", then assume it is "pciex" and all 255 * children should support using PCIe style MMCFG access. 256 * 257 * If parent's dev_type is "pci" and child is "pciex", then also enable using 258 * PCIe style MMCFG access. This covers the case where NPE is "pci" and a PCIe 259 * RP is beneath. 260 */ 261 boolean_t 262 npe_child_is_pci(dev_info_t *dip) { 263 char *dev_type; 264 boolean_t parent_is_pci, child_is_pciex; 265 266 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_get_parent(dip), 267 DDI_PROP_DONTPASS, "device_type", &dev_type) == 268 DDI_PROP_SUCCESS) { 269 parent_is_pci = (strcmp(dev_type, "pci") == 0); 270 ddi_prop_free(dev_type); 271 } else { 272 parent_is_pci = B_FALSE; 273 } 274 275 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 276 "device_type", &dev_type) == DDI_PROP_SUCCESS) { 277 child_is_pciex = (strcmp(dev_type, "pciex") == 0); 278 ddi_prop_free(dev_type); 279 } else { 280 child_is_pciex = B_FALSE; 281 } 282 283 return (parent_is_pci && !child_is_pciex); 284 } 285 286 /* 287 * Checks to see if MMCFG is supported and enables it if necessary. 288 * Returns: TRUE is MMCFG is support, FLASE is not. 289 * 290 * In general if a device sits below a parent who's "dev_type" is "pciex" the 291 * support MMCFG. Otherwise, default back to legacy IOCFG access. 292 * 293 * Enable Legacy PCI config space access for AMD K8 north bridges. 294 * Host bridge: AMD HyperTransport Technology Configuration 295 * Host bridge: AMD Address Map 296 * Host bridge: AMD DRAM Controller 297 * Host bridge: AMD Miscellaneous Control 298 * These devices do not support MMCFG access. 299 * 300 * Enable MMCFG via msr for AMD K10 north bridges 301 */ 302 boolean_t 303 npe_check_and_set_mmcfg(dev_info_t *dip) 304 { 305 int vendor_id, device_id; 306 int64_t data; 307 308 vendor_id = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 309 "vendor-id", -1); 310 device_id = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 311 "device-id", -1); 312 313 if (IS_K10_AMD_NTBRIDGE(vendor_id, device_id)) { 314 data = ddi_prop_get_int64(DDI_DEV_T_ANY, dip, 0, 315 "ecfga-base-address", 0); 316 data &= AMD_MMIO_CFG_BADDR_ADDR_MASK; 317 data |= AMD_MMIO_CFG_BADDR_ENA_ON; 318 wrmsr(MSR_AMD_NB_MMIO_CFG_BADDR, data); 319 } 320 321 return !(npe_child_is_pci(dip) || 322 IS_BAD_AMD_NTBRIDGE(vendor_id, device_id)); 323 } 324