diff options
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/bios32.c | 54 |
1 files changed, 49 insertions, 5 deletions
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index 2b2f25e7fef5..b244696de1a3 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/io.h> | 13 | #include <linux/io.h> |
14 | 14 | ||
15 | #include <asm/mach-types.h> | 15 | #include <asm/mach-types.h> |
16 | #include <asm/mach/map.h> | ||
16 | #include <asm/mach/pci.h> | 17 | #include <asm/mach/pci.h> |
17 | 18 | ||
18 | static int debug_pci; | 19 | static int debug_pci; |
@@ -423,6 +424,38 @@ static int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) | |||
423 | return irq; | 424 | return irq; |
424 | } | 425 | } |
425 | 426 | ||
427 | static int __init pcibios_init_resources(int busnr, struct pci_sys_data *sys) | ||
428 | { | ||
429 | int ret; | ||
430 | struct pci_host_bridge_window *window; | ||
431 | |||
432 | if (list_empty(&sys->resources)) { | ||
433 | pci_add_resource_offset(&sys->resources, | ||
434 | &iomem_resource, sys->mem_offset); | ||
435 | } | ||
436 | |||
437 | list_for_each_entry(window, &sys->resources, list) { | ||
438 | if (resource_type(window->res) == IORESOURCE_IO) | ||
439 | return 0; | ||
440 | } | ||
441 | |||
442 | sys->io_res.start = (busnr * SZ_64K) ? : pcibios_min_io; | ||
443 | sys->io_res.end = (busnr + 1) * SZ_64K - 1; | ||
444 | sys->io_res.flags = IORESOURCE_IO; | ||
445 | sys->io_res.name = sys->io_res_name; | ||
446 | sprintf(sys->io_res_name, "PCI%d I/O", busnr); | ||
447 | |||
448 | ret = request_resource(&ioport_resource, &sys->io_res); | ||
449 | if (ret) { | ||
450 | pr_err("PCI: unable to allocate I/O port region (%d)\n", ret); | ||
451 | return ret; | ||
452 | } | ||
453 | pci_add_resource_offset(&sys->resources, &sys->io_res, | ||
454 | sys->io_offset); | ||
455 | |||
456 | return 0; | ||
457 | } | ||
458 | |||
426 | static void __init pcibios_init_hw(struct hw_pci *hw, struct list_head *head) | 459 | static void __init pcibios_init_hw(struct hw_pci *hw, struct list_head *head) |
427 | { | 460 | { |
428 | struct pci_sys_data *sys = NULL; | 461 | struct pci_sys_data *sys = NULL; |
@@ -445,11 +478,10 @@ static void __init pcibios_init_hw(struct hw_pci *hw, struct list_head *head) | |||
445 | ret = hw->setup(nr, sys); | 478 | ret = hw->setup(nr, sys); |
446 | 479 | ||
447 | if (ret > 0) { | 480 | if (ret > 0) { |
448 | if (list_empty(&sys->resources)) { | 481 | ret = pcibios_init_resources(nr, sys); |
449 | pci_add_resource_offset(&sys->resources, | 482 | if (ret) { |
450 | &ioport_resource, sys->io_offset); | 483 | kfree(sys); |
451 | pci_add_resource_offset(&sys->resources, | 484 | break; |
452 | &iomem_resource, sys->mem_offset); | ||
453 | } | 485 | } |
454 | 486 | ||
455 | if (hw->scan) | 487 | if (hw->scan) |
@@ -627,3 +659,15 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, | |||
627 | 659 | ||
628 | return 0; | 660 | return 0; |
629 | } | 661 | } |
662 | |||
663 | void __init pci_map_io_early(unsigned long pfn) | ||
664 | { | ||
665 | struct map_desc pci_io_desc = { | ||
666 | .virtual = PCI_IO_VIRT_BASE, | ||
667 | .type = MT_DEVICE, | ||
668 | .length = SZ_64K, | ||
669 | }; | ||
670 | |||
671 | pci_io_desc.pfn = pfn; | ||
672 | iotable_init(&pci_io_desc, 1); | ||
673 | } | ||