1
2
3
4
5
6
7
8
9
10
11
12
13
14#undef DEBUG
15
16#include <linux/kernel.h>
17#include <linux/pci.h>
18#include <linux/string.h>
19#include <linux/init.h>
20#include <linux/bootmem.h>
21#include <linux/mm.h>
22#include <linux/list.h>
23#include <linux/syscalls.h>
24#include <linux/irq.h>
25#include <linux/vmalloc.h>
26
27#include <asm/processor.h>
28#include <asm/io.h>
29#include <asm/prom.h>
30#include <asm/pci-bridge.h>
31#include <asm/byteorder.h>
32#include <asm/machdep.h>
33#include <asm/ppc-pci.h>
34
35unsigned long pci_probe_only = 1;
36
37
38
39
40
41
42
43unsigned long pci_io_base = ISA_IO_BASE;
44EXPORT_SYMBOL(pci_io_base);
45
46static int __init pcibios_init(void)
47{
48 struct pci_controller *hose, *tmp;
49
50 printk(KERN_INFO "PCI: Probing PCI hardware\n");
51
52
53
54
55 ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
56
57 if (pci_probe_only)
58 pci_add_flags(PCI_PROBE_ONLY);
59
60
61
62
63 pci_add_flags(PCI_ENABLE_PROC_DOMAINS | PCI_COMPAT_DOMAIN_0);
64
65
66 list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
67 pcibios_scan_phb(hose);
68 pci_bus_add_devices(hose->bus);
69 }
70
71
72 pcibios_resource_survey();
73
74 printk(KERN_DEBUG "PCI: Probing PCI hardware done\n");
75
76 return 0;
77}
78
79subsys_initcall(pcibios_init);
80
81#ifdef CONFIG_HOTPLUG
82
83int pcibios_unmap_io_space(struct pci_bus *bus)
84{
85 struct pci_controller *hose;
86
87 WARN_ON(bus == NULL);
88
89
90
91
92
93
94
95
96
97
98
99 if (bus->self) {
100#ifdef CONFIG_PPC_STD_MMU_64
101 struct resource *res = bus->resource[0];
102#endif
103
104 pr_debug("IO unmapping for PCI-PCI bridge %s\n",
105 pci_name(bus->self));
106
107#ifdef CONFIG_PPC_STD_MMU_64
108 __flush_hash_table_range(&init_mm, res->start + _IO_BASE,
109 res->end + _IO_BASE + 1);
110#endif
111 return 0;
112 }
113
114
115 hose = pci_bus_to_host(bus);
116
117
118 if (hose->io_base_alloc == 0)
119 return 0;
120
121 pr_debug("IO unmapping for PHB %s\n", hose->dn->full_name);
122 pr_debug(" alloc=0x%p\n", hose->io_base_alloc);
123
124
125 vunmap(hose->io_base_alloc);
126
127 return 0;
128}
129EXPORT_SYMBOL_GPL(pcibios_unmap_io_space);
130
131#endif
132
133int __devinit pcibios_map_io_space(struct pci_bus *bus)
134{
135 struct vm_struct *area;
136 unsigned long phys_page;
137 unsigned long size_page;
138 unsigned long io_virt_offset;
139 struct pci_controller *hose;
140
141 WARN_ON(bus == NULL);
142
143
144
145
146 if (bus->self) {
147 pr_debug("IO mapping for PCI-PCI bridge %s\n",
148 pci_name(bus->self));
149 pr_debug(" virt=0x%016llx...0x%016llx\n",
150 bus->resource[0]->start + _IO_BASE,
151 bus->resource[0]->end + _IO_BASE);
152 return 0;
153 }
154
155
156 hose = pci_bus_to_host(bus);
157 phys_page = _ALIGN_DOWN(hose->io_base_phys, PAGE_SIZE);
158 size_page = _ALIGN_UP(hose->pci_io_size, PAGE_SIZE);
159
160
161 hose->io_base_alloc = NULL;
162
163
164 if (hose->pci_io_size == 0 || hose->io_base_phys == 0)
165 return 0;
166
167
168
169
170
171
172
173 area = __get_vm_area(size_page, 0, PHB_IO_BASE, PHB_IO_END);
174 if (area == NULL)
175 return -ENOMEM;
176 hose->io_base_alloc = area->addr;
177 hose->io_base_virt = (void __iomem *)(area->addr +
178 hose->io_base_phys - phys_page);
179
180 pr_debug("IO mapping for PHB %s\n", hose->dn->full_name);
181 pr_debug(" phys=0x%016llx, virt=0x%p (alloc=0x%p)\n",
182 hose->io_base_phys, hose->io_base_virt, hose->io_base_alloc);
183 pr_debug(" size=0x%016llx (alloc=0x%016lx)\n",
184 hose->pci_io_size, size_page);
185
186
187 if (__ioremap_at(phys_page, area->addr, size_page,
188 _PAGE_NO_CACHE | _PAGE_GUARDED) == NULL)
189 return -ENOMEM;
190
191
192 io_virt_offset = (unsigned long)hose->io_base_virt - _IO_BASE;
193 hose->io_resource.start += io_virt_offset;
194 hose->io_resource.end += io_virt_offset;
195
196 pr_debug(" hose->io_resource=%pR\n", &hose->io_resource);
197
198 return 0;
199}
200EXPORT_SYMBOL_GPL(pcibios_map_io_space);
201
202void __devinit pcibios_setup_phb_io_space(struct pci_controller *hose)
203{
204 pcibios_map_io_space(hose->bus);
205}
206
207#define IOBASE_BRIDGE_NUMBER 0
208#define IOBASE_MEMORY 1
209#define IOBASE_IO 2
210#define IOBASE_ISA_IO 3
211#define IOBASE_ISA_MEM 4
212
213long sys_pciconfig_iobase(long which, unsigned long in_bus,
214 unsigned long in_devfn)
215{
216 struct pci_controller* hose;
217 struct list_head *ln;
218 struct pci_bus *bus = NULL;
219 struct device_node *hose_node;
220
221
222
223
224
225
226 if (in_bus == 0 && of_machine_is_compatible("MacRISC4")) {
227 struct device_node *agp;
228
229 agp = of_find_compatible_node(NULL, NULL, "u3-agp");
230 if (agp)
231 in_bus = 0xf0;
232 of_node_put(agp);
233 }
234
235
236
237
238
239 for (ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) {
240 bus = pci_bus_b(ln);
241 if (in_bus >= bus->number && in_bus <= bus->subordinate)
242 break;
243 bus = NULL;
244 }
245 if (bus == NULL || bus->dev.of_node == NULL)
246 return -ENODEV;
247
248 hose_node = bus->dev.of_node;
249 hose = PCI_DN(hose_node)->phb;
250
251 switch (which) {
252 case IOBASE_BRIDGE_NUMBER:
253 return (long)hose->first_busno;
254 case IOBASE_MEMORY:
255 return (long)hose->pci_mem_offset;
256 case IOBASE_IO:
257 return (long)hose->io_base_phys;
258 case IOBASE_ISA_IO:
259 return (long)isa_io_base;
260 case IOBASE_ISA_MEM:
261 return -EINVAL;
262 }
263
264 return -EOPNOTSUPP;
265}
266
267#ifdef CONFIG_NUMA
268int pcibus_to_node(struct pci_bus *bus)
269{
270 struct pci_controller *phb = pci_bus_to_host(bus);
271 return phb->node;
272}
273EXPORT_SYMBOL(pcibus_to_node);
274#endif
275