aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2012-02-23 22:19:02 -0500
committerBjorn Helgaas <bhelgaas@google.com>2012-02-23 22:19:02 -0500
commit96a6b9ad05a2d5654f168d3ad9d9696d3b03a7c2 (patch)
tree8ca03136d6ab471f757da885cdabd485649dce7a /arch
parentaa23bdc0a8a29029ac4c89163a4b63a029580720 (diff)
mips/PCI: get rid of device resource fixups
Tell the PCI core about host bridge address translation so it can take care of bus-to-resource conversion for us. Here's the wrinkle on Cobalt: we can't generate normal I/O port addresses on PCI because the GT-64111 doesn't do any address translation, so we have this: CPU I/O port addresses [io 0x0000-0xffffff] PCI bus I/O port addresses [io 0x10000000-0x10ffffff] Legacy-mode IDE controllers start out with the legacy bus addresses, e.g., 0x1f0, assigned by pci_setup_device(). These are outside the range of addresses GT-64111 can generate on PCI, but pcibios_fixup_device_resources() converted them to CPU addresses anyway by adding io_offset. Therefore, we had to pre-adjust them in cobalt_legacy_ide_fixup(). With io_offset = 0xf0000000, we had this: res->start = 0x1f0 initialized in pci_setup_device() res->start = 0x100001f0 -= io_offset in cobalt_legacy_ide_fixup() res->start = 0x1f0 += io_offset in pcibios_fixup_device_resources() The difference after this patch is that the generic pci_bus_to_resource() only adds the offset if the bus address is inside a host bridge window. Since 0x1f0 is not a valid bus address and is not inside any windows, it is unaffected, so we now have this: region->start = 0x1f0 initialized in pci_setup_device() res->start = 0x1f0 no offset by pci_bus_to_resource() That means we can remove both pcibios_fixup_device_resources() and cobalt_legacy_ide_fixup(). I would *rather* set the host bridge offset to zero (which corresponds to what the GT-64111 actually does), and have both CPU and PCI addresses of [io 0x10000000-0x10ffffff]. However, that would require changes to generic code that assumes legacy I/O addresses, such as pic1_io_resource ([io 0x0020-0x00021]), and we'd have to keep a Cobalt IDE fixup. Of course, none of this changes the fact that references to I/O port 0x1f0 actually go to port 0x100001f0, not 0x1f0, on the Cobalt PCI bus. Fortunately the VT82C586 IDE controller only decodes the low 24 address bits, so it does work. CC: Ralf Baechle <ralf@linux-mips.org> CC: Yoichi Yuasa <yuasa@linux-mips.org> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/include/asm/pci.h6
-rw-r--r--arch/mips/pci/fixup-cobalt.c61
-rw-r--r--arch/mips/pci/pci.c70
3 files changed, 4 insertions, 133 deletions
diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h
index 1e4fa3da3f70..6420e8df4e45 100644
--- a/arch/mips/include/asm/pci.h
+++ b/arch/mips/include/asm/pci.h
@@ -113,11 +113,7 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
113} 113}
114#endif 114#endif
115 115
116extern void pcibios_resource_to_bus(struct pci_dev *dev, 116#define ARCH_HAS_GENERIC_PCI_OFFSETS
117 struct pci_bus_region *region, struct resource *res);
118
119extern void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
120 struct pci_bus_region *region);
121 117
122#define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index 118#define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
123 119
diff --git a/arch/mips/pci/fixup-cobalt.c b/arch/mips/pci/fixup-cobalt.c
index acacd1407c63..9553b14002dd 100644
--- a/arch/mips/pci/fixup-cobalt.c
+++ b/arch/mips/pci/fixup-cobalt.c
@@ -51,67 +51,6 @@ static void qube_raq_galileo_early_fixup(struct pci_dev *dev)
51DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_GT64111, 51DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_GT64111,
52 qube_raq_galileo_early_fixup); 52 qube_raq_galileo_early_fixup);
53 53
54static void __devinit cobalt_legacy_ide_resource_fixup(struct pci_dev *dev,
55 struct resource *res)
56{
57 struct pci_controller *hose = (struct pci_controller *)dev->sysdata;
58 unsigned long offset = hose->io_offset;
59 struct resource orig = *res;
60
61 if (!(res->flags & IORESOURCE_IO) ||
62 !(res->flags & IORESOURCE_PCI_FIXED))
63 return;
64
65 res->start -= offset;
66 res->end -= offset;
67 dev_printk(KERN_DEBUG, &dev->dev, "converted legacy %pR to bus %pR\n",
68 &orig, res);
69}
70
71static void __devinit cobalt_legacy_ide_fixup(struct pci_dev *dev)
72{
73 u32 class;
74 u8 progif;
75
76 /*
77 * If the IDE controller is in legacy mode, pci_setup_device() fills in
78 * the resources with the legacy addresses that normally appear on the
79 * PCI bus, just as if we had read them from a BAR.
80 *
81 * However, with the GT-64111, those legacy addresses, e.g., 0x1f0,
82 * will never appear on the PCI bus because it converts memory accesses
83 * in the PCI I/O region (which is never at address zero) into I/O port
84 * accesses with no address translation.
85 *
86 * For example, if GT_DEF_PCI0_IO_BASE is 0x10000000, a load or store
87 * to physical address 0x100001f0 will become a PCI access to I/O port
88 * 0x100001f0. There's no way to generate an access to I/O port 0x1f0,
89 * but the VT82C586 IDE controller does respond at 0x100001f0 because
90 * it only decodes the low 24 bits of the address.
91 *
92 * When this quirk runs, the pci_dev resources should contain bus
93 * addresses, not Linux I/O port numbers, so convert legacy addresses
94 * like 0x1f0 to bus addresses like 0x100001f0. Later, we'll convert
95 * them back with pcibios_fixup_bus() or pcibios_bus_to_resource().
96 */
97 class = dev->class >> 8;
98 if (class != PCI_CLASS_STORAGE_IDE)
99 return;
100
101 pci_read_config_byte(dev, PCI_CLASS_PROG, &progif);
102 if ((progif & 1) == 0) {
103 cobalt_legacy_ide_resource_fixup(dev, &dev->resource[0]);
104 cobalt_legacy_ide_resource_fixup(dev, &dev->resource[1]);
105 }
106 if ((progif & 4) == 0) {
107 cobalt_legacy_ide_resource_fixup(dev, &dev->resource[2]);
108 cobalt_legacy_ide_resource_fixup(dev, &dev->resource[3]);
109 }
110}
111
112DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1,
113 cobalt_legacy_ide_fixup);
114
115static void qube_raq_via_bmIDE_fixup(struct pci_dev *dev) 54static void qube_raq_via_bmIDE_fixup(struct pci_dev *dev)
116{ 55{
117 unsigned short cfgword; 56 unsigned short cfgword;
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
index 19f6d194a568..0514866fa925 100644
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -88,8 +88,9 @@ static void __devinit pcibios_scanbus(struct pci_controller *hose)
88 if (hose->get_busno && pci_has_flag(PCI_PROBE_ONLY)) 88 if (hose->get_busno && pci_has_flag(PCI_PROBE_ONLY))
89 next_busno = (*hose->get_busno)(); 89 next_busno = (*hose->get_busno)();
90 90
91 pci_add_resource(&resources, hose->mem_resource); 91 pci_add_resource_offset(&resources,
92 pci_add_resource(&resources, hose->io_resource); 92 hose->mem_resource, hose->mem_offset);
93 pci_add_resource_offset(&resources, hose->io_resource, hose->io_offset);
93 bus = pci_scan_root_bus(NULL, next_busno, hose->pci_ops, hose, 94 bus = pci_scan_root_bus(NULL, next_busno, hose->pci_ops, hose,
94 &resources); 95 &resources);
95 if (!bus) 96 if (!bus)
@@ -247,45 +248,13 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
247 return pcibios_plat_dev_init(dev); 248 return pcibios_plat_dev_init(dev);
248} 249}
249 250
250static void pcibios_fixup_device_resources(struct pci_dev *dev,
251 struct pci_bus *bus)
252{
253 /* Update device resources. */
254 struct pci_controller *hose = (struct pci_controller *)bus->sysdata;
255 unsigned long offset = 0;
256 int i;
257
258 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
259 if (!dev->resource[i].start)
260 continue;
261 if (dev->resource[i].flags & IORESOURCE_IO)
262 offset = hose->io_offset;
263 else if (dev->resource[i].flags & IORESOURCE_MEM)
264 offset = hose->mem_offset;
265
266 dev->resource[i].start += offset;
267 dev->resource[i].end += offset;
268 }
269}
270
271void __devinit pcibios_fixup_bus(struct pci_bus *bus) 251void __devinit pcibios_fixup_bus(struct pci_bus *bus)
272{ 252{
273 /* Propagate hose info into the subordinate devices. */
274
275 struct list_head *ln;
276 struct pci_dev *dev = bus->self; 253 struct pci_dev *dev = bus->self;
277 254
278 if (pci_has_flag(PCI_PROBE_ONLY) && dev && 255 if (pci_has_flag(PCI_PROBE_ONLY) && dev &&
279 (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { 256 (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
280 pci_read_bridge_bases(bus); 257 pci_read_bridge_bases(bus);
281 pcibios_fixup_device_resources(dev, bus);
282 }
283
284 for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
285 dev = pci_dev_b(ln);
286
287 if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
288 pcibios_fixup_device_resources(dev, bus);
289 } 258 }
290} 259}
291 260
@@ -295,40 +264,7 @@ pcibios_update_irq(struct pci_dev *dev, int irq)
295 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); 264 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
296} 265}
297 266
298void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
299 struct resource *res)
300{
301 struct pci_controller *hose = (struct pci_controller *)dev->sysdata;
302 unsigned long offset = 0;
303
304 if (res->flags & IORESOURCE_IO)
305 offset = hose->io_offset;
306 else if (res->flags & IORESOURCE_MEM)
307 offset = hose->mem_offset;
308
309 region->start = res->start - offset;
310 region->end = res->end - offset;
311}
312
313void __devinit
314pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
315 struct pci_bus_region *region)
316{
317 struct pci_controller *hose = (struct pci_controller *)dev->sysdata;
318 unsigned long offset = 0;
319
320 if (res->flags & IORESOURCE_IO)
321 offset = hose->io_offset;
322 else if (res->flags & IORESOURCE_MEM)
323 offset = hose->mem_offset;
324
325 res->start = region->start + offset;
326 res->end = region->end + offset;
327}
328
329#ifdef CONFIG_HOTPLUG 267#ifdef CONFIG_HOTPLUG
330EXPORT_SYMBOL(pcibios_resource_to_bus);
331EXPORT_SYMBOL(pcibios_bus_to_resource);
332EXPORT_SYMBOL(PCIBIOS_MIN_IO); 268EXPORT_SYMBOL(PCIBIOS_MIN_IO);
333EXPORT_SYMBOL(PCIBIOS_MIN_MEM); 269EXPORT_SYMBOL(PCIBIOS_MIN_MEM);
334#endif 270#endif