diff options
Diffstat (limited to 'drivers/pci/setup-bus.c')
-rw-r--r-- | drivers/pci/setup-bus.c | 66 |
1 files changed, 50 insertions, 16 deletions
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index c48cd377b3f5..1bd41ac2abd9 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c | |||
@@ -134,18 +134,12 @@ EXPORT_SYMBOL(pci_setup_cardbus); | |||
134 | config space writes, so it's quite possible that an I/O window of | 134 | config space writes, so it's quite possible that an I/O window of |
135 | the bridge will have some undesirable address (e.g. 0) after the | 135 | the bridge will have some undesirable address (e.g. 0) after the |
136 | first write. Ditto 64-bit prefetchable MMIO. */ | 136 | first write. Ditto 64-bit prefetchable MMIO. */ |
137 | static void pci_setup_bridge(struct pci_bus *bus) | 137 | static void pci_setup_bridge_io(struct pci_bus *bus) |
138 | { | 138 | { |
139 | struct pci_dev *bridge = bus->self; | 139 | struct pci_dev *bridge = bus->self; |
140 | struct resource *res; | 140 | struct resource *res; |
141 | struct pci_bus_region region; | 141 | struct pci_bus_region region; |
142 | u32 l, bu, lu, io_upper16; | 142 | u32 l, io_upper16; |
143 | |||
144 | if (pci_is_enabled(bridge)) | ||
145 | return; | ||
146 | |||
147 | dev_info(&bridge->dev, "PCI bridge to [bus %02x-%02x]\n", | ||
148 | bus->secondary, bus->subordinate); | ||
149 | 143 | ||
150 | /* Set up the top and bottom of the PCI I/O segment for this bus. */ | 144 | /* Set up the top and bottom of the PCI I/O segment for this bus. */ |
151 | res = bus->resource[0]; | 145 | res = bus->resource[0]; |
@@ -158,8 +152,7 @@ static void pci_setup_bridge(struct pci_bus *bus) | |||
158 | /* Set up upper 16 bits of I/O base/limit. */ | 152 | /* Set up upper 16 bits of I/O base/limit. */ |
159 | io_upper16 = (region.end & 0xffff0000) | (region.start >> 16); | 153 | io_upper16 = (region.end & 0xffff0000) | (region.start >> 16); |
160 | dev_info(&bridge->dev, " bridge window %pR\n", res); | 154 | dev_info(&bridge->dev, " bridge window %pR\n", res); |
161 | } | 155 | } else { |
162 | else { | ||
163 | /* Clear upper 16 bits of I/O base/limit. */ | 156 | /* Clear upper 16 bits of I/O base/limit. */ |
164 | io_upper16 = 0; | 157 | io_upper16 = 0; |
165 | l = 0x00f0; | 158 | l = 0x00f0; |
@@ -171,21 +164,35 @@ static void pci_setup_bridge(struct pci_bus *bus) | |||
171 | pci_write_config_dword(bridge, PCI_IO_BASE, l); | 164 | pci_write_config_dword(bridge, PCI_IO_BASE, l); |
172 | /* Update upper 16 bits of I/O base/limit. */ | 165 | /* Update upper 16 bits of I/O base/limit. */ |
173 | pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, io_upper16); | 166 | pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, io_upper16); |
167 | } | ||
168 | |||
169 | static void pci_setup_bridge_mmio(struct pci_bus *bus) | ||
170 | { | ||
171 | struct pci_dev *bridge = bus->self; | ||
172 | struct resource *res; | ||
173 | struct pci_bus_region region; | ||
174 | u32 l; | ||
174 | 175 | ||
175 | /* Set up the top and bottom of the PCI Memory segment | 176 | /* Set up the top and bottom of the PCI Memory segment for this bus. */ |
176 | for this bus. */ | ||
177 | res = bus->resource[1]; | 177 | res = bus->resource[1]; |
178 | pcibios_resource_to_bus(bridge, ®ion, res); | 178 | pcibios_resource_to_bus(bridge, ®ion, res); |
179 | if (res->flags & IORESOURCE_MEM) { | 179 | if (res->flags & IORESOURCE_MEM) { |
180 | l = (region.start >> 16) & 0xfff0; | 180 | l = (region.start >> 16) & 0xfff0; |
181 | l |= region.end & 0xfff00000; | 181 | l |= region.end & 0xfff00000; |
182 | dev_info(&bridge->dev, " bridge window %pR\n", res); | 182 | dev_info(&bridge->dev, " bridge window %pR\n", res); |
183 | } | 183 | } else { |
184 | else { | ||
185 | l = 0x0000fff0; | 184 | l = 0x0000fff0; |
186 | dev_info(&bridge->dev, " bridge window [mem disabled]\n"); | 185 | dev_info(&bridge->dev, " bridge window [mem disabled]\n"); |
187 | } | 186 | } |
188 | pci_write_config_dword(bridge, PCI_MEMORY_BASE, l); | 187 | pci_write_config_dword(bridge, PCI_MEMORY_BASE, l); |
188 | } | ||
189 | |||
190 | static void pci_setup_bridge_mmio_pref(struct pci_bus *bus) | ||
191 | { | ||
192 | struct pci_dev *bridge = bus->self; | ||
193 | struct resource *res; | ||
194 | struct pci_bus_region region; | ||
195 | u32 l, bu, lu; | ||
189 | 196 | ||
190 | /* Clear out the upper 32 bits of PREF limit. | 197 | /* Clear out the upper 32 bits of PREF limit. |
191 | If PCI_PREF_BASE_UPPER32 was non-zero, this temporarily | 198 | If PCI_PREF_BASE_UPPER32 was non-zero, this temporarily |
@@ -204,8 +211,7 @@ static void pci_setup_bridge(struct pci_bus *bus) | |||
204 | lu = upper_32_bits(region.end); | 211 | lu = upper_32_bits(region.end); |
205 | } | 212 | } |
206 | dev_info(&bridge->dev, " bridge window %pR\n", res); | 213 | dev_info(&bridge->dev, " bridge window %pR\n", res); |
207 | } | 214 | } else { |
208 | else { | ||
209 | l = 0x0000fff0; | 215 | l = 0x0000fff0; |
210 | dev_info(&bridge->dev, " bridge window [mem pref disabled]\n"); | 216 | dev_info(&bridge->dev, " bridge window [mem pref disabled]\n"); |
211 | } | 217 | } |
@@ -214,10 +220,38 @@ static void pci_setup_bridge(struct pci_bus *bus) | |||
214 | /* Set the upper 32 bits of PREF base & limit. */ | 220 | /* Set the upper 32 bits of PREF base & limit. */ |
215 | pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu); | 221 | pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu); |
216 | pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu); | 222 | pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu); |
223 | } | ||
224 | |||
225 | static void __pci_setup_bridge(struct pci_bus *bus, unsigned long type) | ||
226 | { | ||
227 | struct pci_dev *bridge = bus->self; | ||
228 | |||
229 | if (pci_is_enabled(bridge)) | ||
230 | return; | ||
231 | |||
232 | dev_info(&bridge->dev, "PCI bridge to [bus %02x-%02x]\n", | ||
233 | bus->secondary, bus->subordinate); | ||
234 | |||
235 | if (type & IORESOURCE_IO) | ||
236 | pci_setup_bridge_io(bus); | ||
237 | |||
238 | if (type & IORESOURCE_MEM) | ||
239 | pci_setup_bridge_mmio(bus); | ||
240 | |||
241 | if (type & IORESOURCE_PREFETCH) | ||
242 | pci_setup_bridge_mmio_pref(bus); | ||
217 | 243 | ||
218 | pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl); | 244 | pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl); |
219 | } | 245 | } |
220 | 246 | ||
247 | static void pci_setup_bridge(struct pci_bus *bus) | ||
248 | { | ||
249 | unsigned long type = IORESOURCE_IO | IORESOURCE_MEM | | ||
250 | IORESOURCE_PREFETCH; | ||
251 | |||
252 | __pci_setup_bridge(bus, type); | ||
253 | } | ||
254 | |||
221 | /* Check whether the bridge supports optional I/O and | 255 | /* Check whether the bridge supports optional I/O and |
222 | prefetchable memory ranges. If not, the respective | 256 | prefetchable memory ranges. If not, the respective |
223 | base/limit registers must be read-only and read as 0. */ | 257 | base/limit registers must be read-only and read as 0. */ |