| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Port for PPC64 David Engebretsen, IBM Corp. |
|---|
| 3 | 4 | * Contains common pci routines for ppc64 platform, pSeries and iSeries brands. |
|---|
| 4 | 5 | * |
|---|
| 5 | 6 | * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM |
|---|
| 6 | 7 | * Rework, based on alpha PCI code. |
|---|
| 7 | | - * |
|---|
| 8 | | - * This program is free software; you can redistribute it and/or |
|---|
| 9 | | - * modify it under the terms of the GNU General Public License |
|---|
| 10 | | - * as published by the Free Software Foundation; either version |
|---|
| 11 | | - * 2 of the License, or (at your option) any later version. |
|---|
| 12 | 8 | */ |
|---|
| 13 | 9 | |
|---|
| 14 | 10 | #undef DEBUG |
|---|
| .. | .. |
|---|
| 58 | 54 | pci_add_flags(PCI_ENABLE_PROC_DOMAINS | PCI_COMPAT_DOMAIN_0); |
|---|
| 59 | 55 | |
|---|
| 60 | 56 | /* Scan all of the recorded PCI controllers. */ |
|---|
| 61 | | - list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { |
|---|
| 57 | + list_for_each_entry_safe(hose, tmp, &hose_list, list_node) |
|---|
| 62 | 58 | pcibios_scan_phb(hose); |
|---|
| 63 | | - pci_bus_add_devices(hose->bus); |
|---|
| 64 | | - } |
|---|
| 65 | 59 | |
|---|
| 66 | 60 | /* Call common code to handle resource allocation */ |
|---|
| 67 | 61 | pcibios_resource_survey(); |
|---|
| 62 | + |
|---|
| 63 | + /* Add devices. */ |
|---|
| 64 | + list_for_each_entry_safe(hose, tmp, &hose_list, list_node) |
|---|
| 65 | + pci_bus_add_devices(hose->bus); |
|---|
| 66 | + |
|---|
| 67 | + /* Call machine dependent fixup */ |
|---|
| 68 | + if (ppc_md.pcibios_fixup) |
|---|
| 69 | + ppc_md.pcibios_fixup(); |
|---|
| 68 | 70 | |
|---|
| 69 | 71 | printk(KERN_DEBUG "PCI: Probing PCI hardware done\n"); |
|---|
| 70 | 72 | |
|---|
| .. | .. |
|---|
| 98 | 100 | pci_name(bus->self)); |
|---|
| 99 | 101 | |
|---|
| 100 | 102 | #ifdef CONFIG_PPC_BOOK3S_64 |
|---|
| 101 | | - __flush_hash_table_range(&init_mm, res->start + _IO_BASE, |
|---|
| 103 | + __flush_hash_table_range(res->start + _IO_BASE, |
|---|
| 102 | 104 | res->end + _IO_BASE + 1); |
|---|
| 103 | 105 | #endif |
|---|
| 104 | 106 | return 0; |
|---|
| .. | .. |
|---|
| 107 | 109 | /* Get the host bridge */ |
|---|
| 108 | 110 | hose = pci_bus_to_host(bus); |
|---|
| 109 | 111 | |
|---|
| 110 | | - /* Check if we have IOs allocated */ |
|---|
| 111 | | - if (hose->io_base_alloc == NULL) |
|---|
| 112 | | - return 0; |
|---|
| 113 | | - |
|---|
| 114 | 112 | pr_debug("IO unmapping for PHB %pOF\n", hose->dn); |
|---|
| 115 | 113 | pr_debug(" alloc=0x%p\n", hose->io_base_alloc); |
|---|
| 116 | 114 | |
|---|
| 117 | | - /* This is a PHB, we fully unmap the IO area */ |
|---|
| 118 | | - vunmap(hose->io_base_alloc); |
|---|
| 119 | | - |
|---|
| 115 | + iounmap(hose->io_base_alloc); |
|---|
| 120 | 116 | return 0; |
|---|
| 121 | 117 | } |
|---|
| 122 | 118 | EXPORT_SYMBOL_GPL(pcibios_unmap_io_space); |
|---|
| 123 | 119 | |
|---|
| 124 | | -static int pcibios_map_phb_io_space(struct pci_controller *hose) |
|---|
| 120 | +void __iomem *ioremap_phb(phys_addr_t paddr, unsigned long size) |
|---|
| 125 | 121 | { |
|---|
| 126 | 122 | struct vm_struct *area; |
|---|
| 123 | + unsigned long addr; |
|---|
| 124 | + |
|---|
| 125 | + WARN_ON_ONCE(paddr & ~PAGE_MASK); |
|---|
| 126 | + WARN_ON_ONCE(size & ~PAGE_MASK); |
|---|
| 127 | + |
|---|
| 128 | + /* |
|---|
| 129 | + * Let's allocate some IO space for that guy. We don't pass VM_IOREMAP |
|---|
| 130 | + * because we don't care about alignment tricks that the core does in |
|---|
| 131 | + * that case. Maybe we should due to stupid card with incomplete |
|---|
| 132 | + * address decoding but I'd rather not deal with those outside of the |
|---|
| 133 | + * reserved 64K legacy region. |
|---|
| 134 | + */ |
|---|
| 135 | + area = __get_vm_area_caller(size, 0, PHB_IO_BASE, PHB_IO_END, |
|---|
| 136 | + __builtin_return_address(0)); |
|---|
| 137 | + if (!area) |
|---|
| 138 | + return NULL; |
|---|
| 139 | + |
|---|
| 140 | + addr = (unsigned long)area->addr; |
|---|
| 141 | + if (ioremap_page_range(addr, addr + size, paddr, |
|---|
| 142 | + pgprot_noncached(PAGE_KERNEL))) { |
|---|
| 143 | + unmap_kernel_range(addr, size); |
|---|
| 144 | + return NULL; |
|---|
| 145 | + } |
|---|
| 146 | + |
|---|
| 147 | + return (void __iomem *)addr; |
|---|
| 148 | +} |
|---|
| 149 | +EXPORT_SYMBOL_GPL(ioremap_phb); |
|---|
| 150 | + |
|---|
| 151 | +static int pcibios_map_phb_io_space(struct pci_controller *hose) |
|---|
| 152 | +{ |
|---|
| 127 | 153 | unsigned long phys_page; |
|---|
| 128 | 154 | unsigned long size_page; |
|---|
| 129 | 155 | unsigned long io_virt_offset; |
|---|
| 130 | 156 | |
|---|
| 131 | | - phys_page = _ALIGN_DOWN(hose->io_base_phys, PAGE_SIZE); |
|---|
| 132 | | - size_page = _ALIGN_UP(hose->pci_io_size, PAGE_SIZE); |
|---|
| 157 | + phys_page = ALIGN_DOWN(hose->io_base_phys, PAGE_SIZE); |
|---|
| 158 | + size_page = ALIGN(hose->pci_io_size, PAGE_SIZE); |
|---|
| 133 | 159 | |
|---|
| 134 | 160 | /* Make sure IO area address is clear */ |
|---|
| 135 | 161 | hose->io_base_alloc = NULL; |
|---|
| .. | .. |
|---|
| 144 | 170 | * with incomplete address decoding but I'd rather not deal with |
|---|
| 145 | 171 | * those outside of the reserved 64K legacy region. |
|---|
| 146 | 172 | */ |
|---|
| 147 | | - area = __get_vm_area(size_page, 0, PHB_IO_BASE, PHB_IO_END); |
|---|
| 148 | | - if (area == NULL) |
|---|
| 173 | + hose->io_base_alloc = ioremap_phb(phys_page, size_page); |
|---|
| 174 | + if (!hose->io_base_alloc) |
|---|
| 149 | 175 | return -ENOMEM; |
|---|
| 150 | | - hose->io_base_alloc = area->addr; |
|---|
| 151 | | - hose->io_base_virt = (void __iomem *)(area->addr + |
|---|
| 152 | | - hose->io_base_phys - phys_page); |
|---|
| 176 | + hose->io_base_virt = hose->io_base_alloc + |
|---|
| 177 | + hose->io_base_phys - phys_page; |
|---|
| 153 | 178 | |
|---|
| 154 | 179 | pr_debug("IO mapping for PHB %pOF\n", hose->dn); |
|---|
| 155 | 180 | pr_debug(" phys=0x%016llx, virt=0x%p (alloc=0x%p)\n", |
|---|
| 156 | 181 | hose->io_base_phys, hose->io_base_virt, hose->io_base_alloc); |
|---|
| 157 | 182 | pr_debug(" size=0x%016llx (alloc=0x%016lx)\n", |
|---|
| 158 | 183 | hose->pci_io_size, size_page); |
|---|
| 159 | | - |
|---|
| 160 | | - /* Establish the mapping */ |
|---|
| 161 | | - if (__ioremap_at(phys_page, area->addr, size_page, |
|---|
| 162 | | - pgprot_val(pgprot_noncached(__pgprot(0)))) == NULL) |
|---|
| 163 | | - return -ENOMEM; |
|---|
| 164 | 184 | |
|---|
| 165 | 185 | /* Fixup hose IO resource */ |
|---|
| 166 | 186 | io_virt_offset = pcibios_io_space_offset(hose); |
|---|