.. | .. |
---|
| 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); |
---|