diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2011-10-28 18:28:03 -0400 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2012-01-06 15:11:12 -0500 |
commit | 6361d72b04d1f77736142bc3911a32b814370729 (patch) | |
tree | aebfdcf273040f6f5ff82dda01ca111da886cf58 | |
parent | 2b591616ada6cf499a4e83bf453761e40dc53059 (diff) |
x86/PCI: read Broadcom CNB20LE host bridge info before PCI scan
We currently read the CNB20LE aperture information in a PCI quirk,
which happens after we've already created the root bus. This patch
changes it to read the apertures earlier so we can create the root
bus with the correct resources.
I believe the CNB20LE lives at "pci 0000:00:00" based on
https://lkml.org/lkml/2010/8/13/220
CC: Ira W. Snyder <iws@ovro.caltech.edu>
CC: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
-rw-r--r-- | arch/x86/pci/broadcom_bus.c | 62 |
1 files changed, 39 insertions, 23 deletions
diff --git a/arch/x86/pci/broadcom_bus.c b/arch/x86/pci/broadcom_bus.c index ab8269b0da29..f3a7c569a403 100644 --- a/arch/x86/pci/broadcom_bus.c +++ b/arch/x86/pci/broadcom_bus.c | |||
@@ -15,10 +15,11 @@ | |||
15 | #include <linux/pci.h> | 15 | #include <linux/pci.h> |
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <asm/pci_x86.h> | 17 | #include <asm/pci_x86.h> |
18 | #include <asm/pci-direct.h> | ||
18 | 19 | ||
19 | #include "bus_numa.h" | 20 | #include "bus_numa.h" |
20 | 21 | ||
21 | static void __devinit cnb20le_res(struct pci_dev *dev) | 22 | static void __init cnb20le_res(u8 bus, u8 slot, u8 func) |
22 | { | 23 | { |
23 | struct pci_root_info *info; | 24 | struct pci_root_info *info; |
24 | struct resource res; | 25 | struct resource res; |
@@ -26,21 +27,12 @@ static void __devinit cnb20le_res(struct pci_dev *dev) | |||
26 | u8 fbus, lbus; | 27 | u8 fbus, lbus; |
27 | int i; | 28 | int i; |
28 | 29 | ||
29 | #ifdef CONFIG_ACPI | ||
30 | /* | ||
31 | * We should get host bridge information from ACPI unless the BIOS | ||
32 | * doesn't support it. | ||
33 | */ | ||
34 | if (acpi_os_get_root_pointer()) | ||
35 | return; | ||
36 | #endif | ||
37 | |||
38 | info = &pci_root_info[pci_root_num]; | 30 | info = &pci_root_info[pci_root_num]; |
39 | pci_root_num++; | 31 | pci_root_num++; |
40 | 32 | ||
41 | /* read the PCI bus numbers */ | 33 | /* read the PCI bus numbers */ |
42 | pci_read_config_byte(dev, 0x44, &fbus); | 34 | fbus = read_pci_config_byte(bus, slot, func, 0x44); |
43 | pci_read_config_byte(dev, 0x45, &lbus); | 35 | lbus = read_pci_config_byte(bus, slot, func, 0x45); |
44 | info->bus_min = fbus; | 36 | info->bus_min = fbus; |
45 | info->bus_max = lbus; | 37 | info->bus_max = lbus; |
46 | 38 | ||
@@ -59,8 +51,8 @@ static void __devinit cnb20le_res(struct pci_dev *dev) | |||
59 | } | 51 | } |
60 | 52 | ||
61 | /* read the non-prefetchable memory window */ | 53 | /* read the non-prefetchable memory window */ |
62 | pci_read_config_word(dev, 0xc0, &word1); | 54 | word1 = read_pci_config_16(bus, slot, func, 0xc0); |
63 | pci_read_config_word(dev, 0xc2, &word2); | 55 | word2 = read_pci_config_16(bus, slot, func, 0xc2); |
64 | if (word1 != word2) { | 56 | if (word1 != word2) { |
65 | res.start = (word1 << 16) | 0x0000; | 57 | res.start = (word1 << 16) | 0x0000; |
66 | res.end = (word2 << 16) | 0xffff; | 58 | res.end = (word2 << 16) | 0xffff; |
@@ -69,8 +61,8 @@ static void __devinit cnb20le_res(struct pci_dev *dev) | |||
69 | } | 61 | } |
70 | 62 | ||
71 | /* read the prefetchable memory window */ | 63 | /* read the prefetchable memory window */ |
72 | pci_read_config_word(dev, 0xc4, &word1); | 64 | word1 = read_pci_config_16(bus, slot, func, 0xc4); |
73 | pci_read_config_word(dev, 0xc6, &word2); | 65 | word2 = read_pci_config_16(bus, slot, func, 0xc6); |
74 | if (word1 != word2) { | 66 | if (word1 != word2) { |
75 | res.start = (word1 << 16) | 0x0000; | 67 | res.start = (word1 << 16) | 0x0000; |
76 | res.end = (word2 << 16) | 0xffff; | 68 | res.end = (word2 << 16) | 0xffff; |
@@ -79,8 +71,8 @@ static void __devinit cnb20le_res(struct pci_dev *dev) | |||
79 | } | 71 | } |
80 | 72 | ||
81 | /* read the IO port window */ | 73 | /* read the IO port window */ |
82 | pci_read_config_word(dev, 0xd0, &word1); | 74 | word1 = read_pci_config_16(bus, slot, func, 0xd0); |
83 | pci_read_config_word(dev, 0xd2, &word2); | 75 | word2 = read_pci_config_16(bus, slot, func, 0xd2); |
84 | if (word1 != word2) { | 76 | if (word1 != word2) { |
85 | res.start = word1; | 77 | res.start = word1; |
86 | res.end = word2; | 78 | res.end = word2; |
@@ -92,13 +84,37 @@ static void __devinit cnb20le_res(struct pci_dev *dev) | |||
92 | res.start = fbus; | 84 | res.start = fbus; |
93 | res.end = lbus; | 85 | res.end = lbus; |
94 | res.flags = IORESOURCE_BUS; | 86 | res.flags = IORESOURCE_BUS; |
95 | dev_info(&dev->dev, "CNB20LE PCI Host Bridge (domain %04x %pR)\n", | 87 | printk(KERN_INFO "CNB20LE PCI Host Bridge (domain 0000 %pR)\n", &res); |
96 | pci_domain_nr(dev->bus), &res); | ||
97 | 88 | ||
98 | for (i = 0; i < info->res_num; i++) | 89 | for (i = 0; i < info->res_num; i++) |
99 | dev_info(&dev->dev, "host bridge window %pR\n", &info->res[i]); | 90 | printk(KERN_INFO "host bridge window %pR\n", &info->res[i]); |
100 | } | 91 | } |
101 | 92 | ||
102 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_LE, | 93 | static int __init broadcom_postcore_init(void) |
103 | cnb20le_res); | 94 | { |
95 | u8 bus = 0, slot = 0; | ||
96 | u32 id; | ||
97 | u16 vendor, device; | ||
98 | |||
99 | #ifdef CONFIG_ACPI | ||
100 | /* | ||
101 | * We should get host bridge information from ACPI unless the BIOS | ||
102 | * doesn't support it. | ||
103 | */ | ||
104 | if (acpi_os_get_root_pointer()) | ||
105 | return 0; | ||
106 | #endif | ||
107 | |||
108 | id = read_pci_config(bus, slot, 0, PCI_VENDOR_ID); | ||
109 | vendor = id & 0xffff; | ||
110 | device = (id >> 16) & 0xffff; | ||
111 | |||
112 | if (vendor == PCI_VENDOR_ID_SERVERWORKS && | ||
113 | device == PCI_DEVICE_ID_SERVERWORKS_LE) { | ||
114 | cnb20le_res(bus, slot, 0); | ||
115 | cnb20le_res(bus, slot, 1); | ||
116 | } | ||
117 | return 0; | ||
118 | } | ||
104 | 119 | ||
120 | postcore_initcall(broadcom_postcore_init); | ||