aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/i386/pci/mmconfig-shared.c121
1 files changed, 119 insertions, 2 deletions
diff --git a/arch/i386/pci/mmconfig-shared.c b/arch/i386/pci/mmconfig-shared.c
index 779c987acc5b..d72f0439147c 100644
--- a/arch/i386/pci/mmconfig-shared.c
+++ b/arch/i386/pci/mmconfig-shared.c
@@ -3,6 +3,7 @@
3 * MMCONFIG - common code between i386 and x86-64. 3 * MMCONFIG - common code between i386 and x86-64.
4 * 4 *
5 * This code does: 5 * This code does:
6 * - known chipset handling
6 * - ACPI decoding and validation 7 * - ACPI decoding and validation
7 * 8 *
8 * Per-architecture code takes care of the mappings and accesses 9 * Per-architecture code takes care of the mappings and accesses
@@ -55,12 +56,128 @@ static __init void unreachable_devices(void)
55 } 56 }
56} 57}
57 58
59static __init const char *pci_mmcfg_e7520(void)
60{
61 u32 win;
62 pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0xce, 2, &win);
63
64 pci_mmcfg_config_num = 1;
65 pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL);
66 if (!pci_mmcfg_config)
67 return NULL;
68 pci_mmcfg_config[0].address = (win & 0xf000) << 16;
69 pci_mmcfg_config[0].pci_segment = 0;
70 pci_mmcfg_config[0].start_bus_number = 0;
71 pci_mmcfg_config[0].end_bus_number = 255;
72
73 return "Intel Corporation E7520 Memory Controller Hub";
74}
75
76static __init const char *pci_mmcfg_intel_945(void)
77{
78 u32 pciexbar, mask = 0, len = 0;
79
80 pci_mmcfg_config_num = 1;
81
82 pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0x48, 4, &pciexbar);
83
84 /* Enable bit */
85 if (!(pciexbar & 1))
86 pci_mmcfg_config_num = 0;
87
88 /* Size bits */
89 switch ((pciexbar >> 1) & 3) {
90 case 0:
91 mask = 0xf0000000U;
92 len = 0x10000000U;
93 break;
94 case 1:
95 mask = 0xf8000000U;
96 len = 0x08000000U;
97 break;
98 case 2:
99 mask = 0xfc000000U;
100 len = 0x04000000U;
101 break;
102 default:
103 pci_mmcfg_config_num = 0;
104 }
105
106 /* Errata #2, things break when not aligned on a 256Mb boundary */
107 /* Can only happen in 64M/128M mode */
108
109 if ((pciexbar & mask) & 0x0fffffffU)
110 pci_mmcfg_config_num = 0;
111
112 if (pci_mmcfg_config_num) {
113 pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL);
114 if (!pci_mmcfg_config)
115 return NULL;
116 pci_mmcfg_config[0].address = pciexbar & mask;
117 pci_mmcfg_config[0].pci_segment = 0;
118 pci_mmcfg_config[0].start_bus_number = 0;
119 pci_mmcfg_config[0].end_bus_number = (len >> 20) - 1;
120 }
121
122 return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub";
123}
124
125struct pci_mmcfg_hostbridge_probe {
126 u32 vendor;
127 u32 device;
128 const char *(*probe)(void);
129};
130
131static __initdata struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] = {
132 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 },
133 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 },
134};
135
136static int __init pci_mmcfg_check_hostbridge(void)
137{
138 u32 l;
139 u16 vendor, device;
140 int i;
141 const char *name;
142
143 pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0, 4, &l);
144 vendor = l & 0xffff;
145 device = (l >> 16) & 0xffff;
146
147 pci_mmcfg_config_num = 0;
148 pci_mmcfg_config = NULL;
149 name = NULL;
150
151 for (i = 0; !name && i < ARRAY_SIZE(pci_mmcfg_probes); i++)
152 if ((pci_mmcfg_probes[i].vendor == PCI_ANY_ID ||
153 pci_mmcfg_probes[i].vendor == vendor) &&
154 (pci_mmcfg_probes[i].device == PCI_ANY_ID ||
155 pci_mmcfg_probes[i].device == device))
156 name = pci_mmcfg_probes[i].probe();
157
158 if (name) {
159 if (pci_mmcfg_config_num)
160 printk(KERN_INFO "PCI: Found %s with MMCONFIG support.\n", name);
161 else
162 printk(KERN_INFO "PCI: Found %s without MMCONFIG support.\n",
163 name);
164 }
165
166 return name != NULL;
167}
168
58void __init pci_mmcfg_init(int type) 169void __init pci_mmcfg_init(int type)
59{ 170{
171 int known_bridge = 0;
172
60 if ((pci_probe & PCI_PROBE_MMCONF) == 0) 173 if ((pci_probe & PCI_PROBE_MMCONF) == 0)
61 return; 174 return;
62 175
63 acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg); 176 if (type == 1 && pci_mmcfg_check_hostbridge())
177 known_bridge = 1;
178
179 if (!known_bridge)
180 acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
64 181
65 if ((pci_mmcfg_config_num == 0) || 182 if ((pci_mmcfg_config_num == 0) ||
66 (pci_mmcfg_config == NULL) || 183 (pci_mmcfg_config == NULL) ||
@@ -69,7 +186,7 @@ void __init pci_mmcfg_init(int type)
69 186
70 /* Only do this check when type 1 works. If it doesn't work 187 /* Only do this check when type 1 works. If it doesn't work
71 assume we run on a Mac and always use MCFG */ 188 assume we run on a Mac and always use MCFG */
72 if (type == 1 && 189 if (type == 1 && !known_bridge &&
73 !e820_all_mapped(pci_mmcfg_config[0].address, 190 !e820_all_mapped(pci_mmcfg_config[0].address,
74 pci_mmcfg_config[0].address + MMCONFIG_APER_MIN, 191 pci_mmcfg_config[0].address + MMCONFIG_APER_MIN,
75 E820_RESERVED)) { 192 E820_RESERVED)) {