npe_misc.c revision db2bae3047e71d795bde12e3baa621f4b6cc8930
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim/*
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * CDDL HEADER START
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim *
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * The contents of this file are subject to the terms of the
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * Common Development and Distribution License (the "License").
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * You may not use this file except in compliance with the License.
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim *
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * or http://www.opensolaris.org/os/licensing.
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * See the License for the specific language governing permissions
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * and limitations under the License.
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim *
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * When distributing Covered Code, include this CDDL HEADER in each
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * If applicable, add the following below this CDDL HEADER, with the
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * fields enclosed by brackets "[]" replaced with your own identifying
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * information: Portions Copyright [yyyy] [name of copyright owner]
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim *
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * CDDL HEADER END
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim */
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim
cd3e933325e68e23516a196a8fea7f49b1e497c3Ali Bahrami/*
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * Use is subject to license terms.
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim */
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim/*
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * Library file that has miscellaneous support for npe(7d)
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim */
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim#include <sys/conf.h>
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim#include <sys/pci.h>
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim#include <sys/sunndi.h>
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim#include <sys/acpi/acpi.h>
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim#include <sys/acpi/acpi_pci.h>
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim#include <sys/acpica.h>
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim#include <sys/pci_cap.h>
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim#include <sys/pcie_impl.h>
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim#include <io/pciex/pcie_nvidia.h>
cd3e933325e68e23516a196a8fea7f49b1e497c3Ali Bahrami#include <io/pciex/pcie_nb5000.h>
cd3e933325e68e23516a196a8fea7f49b1e497c3Ali Bahrami
cd3e933325e68e23516a196a8fea7f49b1e497c3Ali Bahrami/*
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * Prototype declaration
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim */
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimvoid npe_query_acpi_mcfg(dev_info_t *dip);
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimvoid npe_ck804_fix_aer_ptr(ddi_acc_handle_t cfg_hdl);
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimint npe_disable_empty_bridges_workaround(dev_info_t *child);
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimvoid npe_nvidia_error_mask(ddi_acc_handle_t cfg_hdl);
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimvoid npe_intel_error_mask(ddi_acc_handle_t cfg_hdl);
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim/*
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * Default ecfga base address
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim */
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimint64_t npe_default_ecfga_base = 0xE0000000;
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimextern uint32_t npe_aer_uce_mask;
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimextern boolean_t pcie_full_scan;
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim/*
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * Query the MCFG table using ACPI. If MCFG is found, setup the
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * 'ecfga-base-address' (Enhanced Configuration Access base address)
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * property accordingly. Otherwise, set the value of the property
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * to the default value.
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim */
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimvoid
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimnpe_query_acpi_mcfg(dev_info_t *dip)
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim{
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim MCFG_TABLE *mcfgp;
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim CFG_BASE_ADDR_ALLOC *cfg_baap;
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim char *cfg_baa_endp;
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim uint64_t ecfga_base;
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim /* Query the MCFG table using ACPI */
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim if (AcpiGetTable(ACPI_SIG_MCFG, 1, (ACPI_TABLE_HEADER **)&mcfgp) ==
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim AE_OK) {
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim cfg_baap = (CFG_BASE_ADDR_ALLOC *)mcfgp->CfgBaseAddrAllocList;
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim cfg_baa_endp = ((char *)mcfgp) + mcfgp->Length;
while ((char *)cfg_baap < cfg_baa_endp) {
ecfga_base = cfg_baap->base_addr;
if (ecfga_base != (uint64_t)0) {
/*
* Setup the 'ecfga-base-address' property to
* the base_addr found in the MCFG and return.
*/
(void) ndi_prop_update_int64(DDI_DEV_T_NONE,
dip, "ecfga-base-address", ecfga_base);
return;
}
cfg_baap++;
}
}
/*
* If MCFG is not found or ecfga_base is not found in MCFG table,
* set the 'ecfga-base-address' property to the default value.
*/
(void) ndi_prop_update_int64(DDI_DEV_T_NONE, dip,
"ecfga-base-address", npe_default_ecfga_base);
}
/*
* Enable reporting of AER capability next pointer.
* This needs to be done only for CK8-04 devices
* by setting NV_XVR_VEND_CYA1 (offset 0xf40) bit 13
* NOTE: BIOS is disabling this, it needs to be enabled temporarily
*/
void
npe_ck804_fix_aer_ptr(ddi_acc_handle_t cfg_hdl)
{
ushort_t cya1;
if ((pci_config_get16(cfg_hdl, PCI_CONF_VENID) == NVIDIA_VENDOR_ID) &&
(pci_config_get16(cfg_hdl, PCI_CONF_DEVID) ==
NVIDIA_CK804_DEVICE_ID) &&
(pci_config_get8(cfg_hdl, PCI_CONF_REVID) >=
NVIDIA_CK804_AER_VALID_REVID)) {
cya1 = pci_config_get16(cfg_hdl, NVIDIA_CK804_VEND_CYA1_OFF);
if (!(cya1 & ~NVIDIA_CK804_VEND_CYA1_ERPT_MASK))
(void) pci_config_put16(cfg_hdl,
NVIDIA_CK804_VEND_CYA1_OFF,
cya1 | NVIDIA_CK804_VEND_CYA1_ERPT_VAL);
}
}
/*
* If the bridge is empty, disable it
*/
int
npe_disable_empty_bridges_workaround(dev_info_t *child)
{
/*
* Do not bind drivers to empty bridges.
* Fail above, if the bridge is found to be hotplug capable
*/
if (ddi_driver_major(child) == ddi_name_to_major("pcie_pci") &&
ddi_get_child(child) == NULL &&
ddi_prop_get_int(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
"pci-hotplug-type", INBAND_HPC_NONE) == INBAND_HPC_NONE)
return (1);
return (0);
}
void
npe_nvidia_error_mask(ddi_acc_handle_t cfg_hdl) {
uint32_t regs;
uint16_t vendor_id = pci_config_get16(cfg_hdl, PCI_CONF_VENID);
uint16_t dev_id = pci_config_get16(cfg_hdl, PCI_CONF_DEVID);
if ((vendor_id == NVIDIA_VENDOR_ID) && NVIDIA_PCIE_RC_DEV_ID(dev_id)) {
/* Disable ECRC for all devices */
regs = pcie_get_aer_uce_mask() | npe_aer_uce_mask |
PCIE_AER_UCE_ECRC;
pcie_set_aer_uce_mask(regs);
/*
* Turn full scan on since the Error Source ID register may not
* have the correct ID.
*/
pcie_full_scan = B_TRUE;
}
}
void
npe_intel_error_mask(ddi_acc_handle_t cfg_hdl) {
uint32_t regs;
uint16_t vendor_id = pci_config_get16(cfg_hdl, PCI_CONF_VENID);
if (vendor_id == INTEL_VENDOR_ID) {
/*
* Due to an errata in Intel's ESB2 southbridge, all ECRCs
* generation/checking need to be disabled. There is a
* workaround by setting a proprietary bit in the ESB2, but it
* is not well documented or understood. If that bit is set in
* the future, then ECRC generation/checking should be enabled
* again.
*
* Disable ECRC generation/checking by masking ECRC in the AER
* UE Mask. The pcie misc module would then automatically
* disable ECRC generation/checking in the AER Control register.
*/
regs = pcie_get_aer_uce_mask() | PCIE_AER_UCE_ECRC;
pcie_set_aer_uce_mask(regs);
}
}