xref: /illumos-gate/usr/src/uts/i86pc/io/pciex/npe_misc.c (revision 4e93fb0f6383eaac21897dcdae56b87118131e4d)
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 2007 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 <io/pciex/pcie_nvidia.h>
40 
41 /*
42  * Prototype declaration
43  */
44 void	npe_query_acpi_mcfg(dev_info_t *dip);
45 void	npe_ck804_fix_aer_ptr(ddi_acc_handle_t cfg_hdl);
46 int	npe_disable_empty_bridges_workaround(dev_info_t *child);
47 
48 /*
49  * Default ecfga base address
50  */
51 int64_t npe_default_ecfga_base = 0xE0000000;
52 
53 /*
54  * Query the MCFG table using ACPI.  If MCFG is found, setup the
55  * 'ecfga-base-address' (Enhanced Configuration Access base address)
56  * property accordingly.  Otherwise, set the value of the property
57  * to the default value.
58  */
59 void
60 npe_query_acpi_mcfg(dev_info_t *dip)
61 {
62 	MCFG_TABLE *mcfgp;
63 	CFG_BASE_ADDR_ALLOC *cfg_baap;
64 	char *cfg_baa_endp;
65 	uint64_t ecfga_base;
66 
67 	/* Query the MCFG table using ACPI */
68 	if (AcpiGetFirmwareTable(MCFG_SIG, 1, ACPI_LOGICAL_ADDRESSING,
69 	    (ACPI_TABLE_HEADER **)&mcfgp) == AE_OK) {
70 
71 		cfg_baap = (CFG_BASE_ADDR_ALLOC *)mcfgp->CfgBaseAddrAllocList;
72 		cfg_baa_endp = ((char *)mcfgp) + mcfgp->Length;
73 
74 		while ((char *)cfg_baap < cfg_baa_endp) {
75 			ecfga_base = ACPI_GET_ADDRESS(cfg_baap->base_addr);
76 			if (ecfga_base != (uint64_t)0) {
77 				/*
78 				 * Setup the 'ecfga-base-address' property to
79 				 * the base_addr found in the MCFG and return.
80 				 */
81 				(void) ndi_prop_update_int64(DDI_DEV_T_NONE,
82 				    dip, "ecfga-base-address", ecfga_base);
83 				return;
84 			}
85 			cfg_baap++;
86 		}
87 	}
88 	/*
89 	 * If MCFG is not found or ecfga_base is not found in MCFG table,
90 	 * set the 'ecfga-base-address' property to the default value.
91 	 */
92 	(void) ndi_prop_update_int64(DDI_DEV_T_NONE, dip,
93 	    "ecfga-base-address", npe_default_ecfga_base);
94 }
95 
96 
97 /*
98  * Enable reporting of AER capability next pointer.
99  * This needs to be done only for CK8-04 devices
100  * by setting NV_XVR_VEND_CYA1 (offset 0xf40) bit 13
101  * NOTE: BIOS is disabling this, it needs to be enabled temporarily
102  */
103 void
104 npe_ck804_fix_aer_ptr(ddi_acc_handle_t cfg_hdl)
105 {
106 	ushort_t cya1;
107 
108 	if ((pci_config_get16(cfg_hdl, PCI_CONF_VENID) == NVIDIA_VENDOR_ID) &&
109 	    (pci_config_get16(cfg_hdl, PCI_CONF_DEVID) ==
110 	    NVIDIA_CK804_DEVICE_ID) &&
111 	    (pci_config_get8(cfg_hdl, PCI_CONF_REVID) >=
112 	    NVIDIA_CK804_AER_VALID_REVID)) {
113 		cya1 =  pci_config_get16(cfg_hdl, NVIDIA_CK804_VEND_CYA1_OFF);
114 		if (!(cya1 & ~NVIDIA_CK804_VEND_CYA1_ERPT_MASK))
115 			(void) pci_config_put16(cfg_hdl,
116 			    NVIDIA_CK804_VEND_CYA1_OFF,
117 			    cya1 | NVIDIA_CK804_VEND_CYA1_ERPT_VAL);
118 	}
119 }
120 
121 
122 /*
123  * If the bridge is empty, disable it
124  */
125 int
126 npe_disable_empty_bridges_workaround(dev_info_t *child)
127 {
128 	/*
129 	 * Do not bind drivers to empty bridges.
130 	 * Fail above, if the bridge is found to be hotplug capable
131 	 */
132 	if (ddi_driver_major(child) == ddi_name_to_major("pcie_pci") &&
133 	    ddi_get_child(child) == NULL &&
134 	    ddi_prop_get_int(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
135 	    "pci-hotplug-type", INBAND_HPC_NONE) == INBAND_HPC_NONE)
136 		return (1);
137 
138 	return (0);
139 }
140