diff options
author | Kumar Gala <galak@kernel.crashing.org> | 2007-06-27 12:07:51 -0400 |
---|---|---|
committer | Kumar Gala <galak@kernel.crashing.org> | 2007-06-29 02:58:43 -0400 |
commit | 58083dade53cd434e134cd26ae5e89061f6de1ff (patch) | |
tree | 4a70ca228ccab50c3036a37c7d1cd4e1a2825d76 /arch/powerpc | |
parent | 0b1d40c4d4dd8f276d8d9730204b3a0a17ab0d61 (diff) |
[POWERPC] Move common PCI code out of pci_32/pci_64
Moved the low hanging fruit that was either identical or close
to it between ppc32 & ppc64 for PCI into pci-common.c
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/kernel/pci-common.c | 314 | ||||
-rw-r--r-- | arch/powerpc/kernel/pci_32.c | 294 | ||||
-rw-r--r-- | arch/powerpc/kernel/pci_64.c | 309 |
3 files changed, 314 insertions, 603 deletions
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 3ca8cfb99dc2..b518b880d2eb 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c | |||
@@ -51,3 +51,317 @@ int pci_domain_nr(struct pci_bus *bus) | |||
51 | } | 51 | } |
52 | 52 | ||
53 | EXPORT_SYMBOL(pci_domain_nr); | 53 | EXPORT_SYMBOL(pci_domain_nr); |
54 | |||
55 | #ifdef CONFIG_PPC_OF | ||
56 | static ssize_t pci_show_devspec(struct device *dev, | ||
57 | struct device_attribute *attr, char *buf) | ||
58 | { | ||
59 | struct pci_dev *pdev; | ||
60 | struct device_node *np; | ||
61 | |||
62 | pdev = to_pci_dev (dev); | ||
63 | np = pci_device_to_OF_node(pdev); | ||
64 | if (np == NULL || np->full_name == NULL) | ||
65 | return 0; | ||
66 | return sprintf(buf, "%s", np->full_name); | ||
67 | } | ||
68 | static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); | ||
69 | #endif /* CONFIG_PPC_OF */ | ||
70 | |||
71 | /* Add sysfs properties */ | ||
72 | void pcibios_add_platform_entries(struct pci_dev *pdev) | ||
73 | { | ||
74 | #ifdef CONFIG_PPC_OF | ||
75 | device_create_file(&pdev->dev, &dev_attr_devspec); | ||
76 | #endif /* CONFIG_PPC_OF */ | ||
77 | } | ||
78 | |||
79 | char __init *pcibios_setup(char *str) | ||
80 | { | ||
81 | return str; | ||
82 | } | ||
83 | |||
84 | /* | ||
85 | * Reads the interrupt pin to determine if interrupt is use by card. | ||
86 | * If the interrupt is used, then gets the interrupt line from the | ||
87 | * openfirmware and sets it in the pci_dev and pci_config line. | ||
88 | */ | ||
89 | int pci_read_irq_line(struct pci_dev *pci_dev) | ||
90 | { | ||
91 | struct of_irq oirq; | ||
92 | unsigned int virq; | ||
93 | |||
94 | DBG("Try to map irq for %s...\n", pci_name(pci_dev)); | ||
95 | |||
96 | #ifdef DEBUG | ||
97 | memset(&oirq, 0xff, sizeof(oirq)); | ||
98 | #endif | ||
99 | /* Try to get a mapping from the device-tree */ | ||
100 | if (of_irq_map_pci(pci_dev, &oirq)) { | ||
101 | u8 line, pin; | ||
102 | |||
103 | /* If that fails, lets fallback to what is in the config | ||
104 | * space and map that through the default controller. We | ||
105 | * also set the type to level low since that's what PCI | ||
106 | * interrupts are. If your platform does differently, then | ||
107 | * either provide a proper interrupt tree or don't use this | ||
108 | * function. | ||
109 | */ | ||
110 | if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin)) | ||
111 | return -1; | ||
112 | if (pin == 0) | ||
113 | return -1; | ||
114 | if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) || | ||
115 | line == 0xff) { | ||
116 | return -1; | ||
117 | } | ||
118 | DBG(" -> no map ! Using irq line %d from PCI config\n", line); | ||
119 | |||
120 | virq = irq_create_mapping(NULL, line); | ||
121 | if (virq != NO_IRQ) | ||
122 | set_irq_type(virq, IRQ_TYPE_LEVEL_LOW); | ||
123 | } else { | ||
124 | DBG(" -> got one, spec %d cells (0x%08x 0x%08x...) on %s\n", | ||
125 | oirq.size, oirq.specifier[0], oirq.specifier[1], | ||
126 | oirq.controller->full_name); | ||
127 | |||
128 | virq = irq_create_of_mapping(oirq.controller, oirq.specifier, | ||
129 | oirq.size); | ||
130 | } | ||
131 | if(virq == NO_IRQ) { | ||
132 | DBG(" -> failed to map !\n"); | ||
133 | return -1; | ||
134 | } | ||
135 | |||
136 | DBG(" -> mapped to linux irq %d\n", virq); | ||
137 | |||
138 | pci_dev->irq = virq; | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | EXPORT_SYMBOL(pci_read_irq_line); | ||
143 | |||
144 | /* | ||
145 | * Platform support for /proc/bus/pci/X/Y mmap()s, | ||
146 | * modelled on the sparc64 implementation by Dave Miller. | ||
147 | * -- paulus. | ||
148 | */ | ||
149 | |||
150 | /* | ||
151 | * Adjust vm_pgoff of VMA such that it is the physical page offset | ||
152 | * corresponding to the 32-bit pci bus offset for DEV requested by the user. | ||
153 | * | ||
154 | * Basically, the user finds the base address for his device which he wishes | ||
155 | * to mmap. They read the 32-bit value from the config space base register, | ||
156 | * add whatever PAGE_SIZE multiple offset they wish, and feed this into the | ||
157 | * offset parameter of mmap on /proc/bus/pci/XXX for that device. | ||
158 | * | ||
159 | * Returns negative error code on failure, zero on success. | ||
160 | */ | ||
161 | static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, | ||
162 | resource_size_t *offset, | ||
163 | enum pci_mmap_state mmap_state) | ||
164 | { | ||
165 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | ||
166 | unsigned long io_offset = 0; | ||
167 | int i, res_bit; | ||
168 | |||
169 | if (hose == 0) | ||
170 | return NULL; /* should never happen */ | ||
171 | |||
172 | /* If memory, add on the PCI bridge address offset */ | ||
173 | if (mmap_state == pci_mmap_mem) { | ||
174 | #if 0 /* See comment in pci_resource_to_user() for why this is disabled */ | ||
175 | *offset += hose->pci_mem_offset; | ||
176 | #endif | ||
177 | res_bit = IORESOURCE_MEM; | ||
178 | } else { | ||
179 | io_offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||
180 | *offset += io_offset; | ||
181 | res_bit = IORESOURCE_IO; | ||
182 | } | ||
183 | |||
184 | /* | ||
185 | * Check that the offset requested corresponds to one of the | ||
186 | * resources of the device. | ||
187 | */ | ||
188 | for (i = 0; i <= PCI_ROM_RESOURCE; i++) { | ||
189 | struct resource *rp = &dev->resource[i]; | ||
190 | int flags = rp->flags; | ||
191 | |||
192 | /* treat ROM as memory (should be already) */ | ||
193 | if (i == PCI_ROM_RESOURCE) | ||
194 | flags |= IORESOURCE_MEM; | ||
195 | |||
196 | /* Active and same type? */ | ||
197 | if ((flags & res_bit) == 0) | ||
198 | continue; | ||
199 | |||
200 | /* In the range of this resource? */ | ||
201 | if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end) | ||
202 | continue; | ||
203 | |||
204 | /* found it! construct the final physical address */ | ||
205 | if (mmap_state == pci_mmap_io) | ||
206 | *offset += hose->io_base_phys - io_offset; | ||
207 | return rp; | ||
208 | } | ||
209 | |||
210 | return NULL; | ||
211 | } | ||
212 | |||
213 | /* | ||
214 | * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci | ||
215 | * device mapping. | ||
216 | */ | ||
217 | static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, | ||
218 | pgprot_t protection, | ||
219 | enum pci_mmap_state mmap_state, | ||
220 | int write_combine) | ||
221 | { | ||
222 | unsigned long prot = pgprot_val(protection); | ||
223 | |||
224 | /* Write combine is always 0 on non-memory space mappings. On | ||
225 | * memory space, if the user didn't pass 1, we check for a | ||
226 | * "prefetchable" resource. This is a bit hackish, but we use | ||
227 | * this to workaround the inability of /sysfs to provide a write | ||
228 | * combine bit | ||
229 | */ | ||
230 | if (mmap_state != pci_mmap_mem) | ||
231 | write_combine = 0; | ||
232 | else if (write_combine == 0) { | ||
233 | if (rp->flags & IORESOURCE_PREFETCH) | ||
234 | write_combine = 1; | ||
235 | } | ||
236 | |||
237 | /* XXX would be nice to have a way to ask for write-through */ | ||
238 | prot |= _PAGE_NO_CACHE; | ||
239 | if (write_combine) | ||
240 | prot &= ~_PAGE_GUARDED; | ||
241 | else | ||
242 | prot |= _PAGE_GUARDED; | ||
243 | |||
244 | return __pgprot(prot); | ||
245 | } | ||
246 | |||
247 | /* | ||
248 | * This one is used by /dev/mem and fbdev who have no clue about the | ||
249 | * PCI device, it tries to find the PCI device first and calls the | ||
250 | * above routine | ||
251 | */ | ||
252 | pgprot_t pci_phys_mem_access_prot(struct file *file, | ||
253 | unsigned long pfn, | ||
254 | unsigned long size, | ||
255 | pgprot_t protection) | ||
256 | { | ||
257 | struct pci_dev *pdev = NULL; | ||
258 | struct resource *found = NULL; | ||
259 | unsigned long prot = pgprot_val(protection); | ||
260 | unsigned long offset = pfn << PAGE_SHIFT; | ||
261 | int i; | ||
262 | |||
263 | if (page_is_ram(pfn)) | ||
264 | return __pgprot(prot); | ||
265 | |||
266 | prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; | ||
267 | |||
268 | for_each_pci_dev(pdev) { | ||
269 | for (i = 0; i <= PCI_ROM_RESOURCE; i++) { | ||
270 | struct resource *rp = &pdev->resource[i]; | ||
271 | int flags = rp->flags; | ||
272 | |||
273 | /* Active and same type? */ | ||
274 | if ((flags & IORESOURCE_MEM) == 0) | ||
275 | continue; | ||
276 | /* In the range of this resource? */ | ||
277 | if (offset < (rp->start & PAGE_MASK) || | ||
278 | offset > rp->end) | ||
279 | continue; | ||
280 | found = rp; | ||
281 | break; | ||
282 | } | ||
283 | if (found) | ||
284 | break; | ||
285 | } | ||
286 | if (found) { | ||
287 | if (found->flags & IORESOURCE_PREFETCH) | ||
288 | prot &= ~_PAGE_GUARDED; | ||
289 | pci_dev_put(pdev); | ||
290 | } | ||
291 | |||
292 | DBG("non-PCI map for %lx, prot: %lx\n", offset, prot); | ||
293 | |||
294 | return __pgprot(prot); | ||
295 | } | ||
296 | |||
297 | |||
298 | /* | ||
299 | * Perform the actual remap of the pages for a PCI device mapping, as | ||
300 | * appropriate for this architecture. The region in the process to map | ||
301 | * is described by vm_start and vm_end members of VMA, the base physical | ||
302 | * address is found in vm_pgoff. | ||
303 | * The pci device structure is provided so that architectures may make mapping | ||
304 | * decisions on a per-device or per-bus basis. | ||
305 | * | ||
306 | * Returns a negative error code on failure, zero on success. | ||
307 | */ | ||
308 | int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, | ||
309 | enum pci_mmap_state mmap_state, int write_combine) | ||
310 | { | ||
311 | resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT; | ||
312 | struct resource *rp; | ||
313 | int ret; | ||
314 | |||
315 | rp = __pci_mmap_make_offset(dev, &offset, mmap_state); | ||
316 | if (rp == NULL) | ||
317 | return -EINVAL; | ||
318 | |||
319 | vma->vm_pgoff = offset >> PAGE_SHIFT; | ||
320 | vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp, | ||
321 | vma->vm_page_prot, | ||
322 | mmap_state, write_combine); | ||
323 | |||
324 | ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, | ||
325 | vma->vm_end - vma->vm_start, vma->vm_page_prot); | ||
326 | |||
327 | return ret; | ||
328 | } | ||
329 | |||
330 | void pci_resource_to_user(const struct pci_dev *dev, int bar, | ||
331 | const struct resource *rsrc, | ||
332 | resource_size_t *start, resource_size_t *end) | ||
333 | { | ||
334 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | ||
335 | resource_size_t offset = 0; | ||
336 | |||
337 | if (hose == NULL) | ||
338 | return; | ||
339 | |||
340 | if (rsrc->flags & IORESOURCE_IO) | ||
341 | offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||
342 | |||
343 | /* We pass a fully fixed up address to userland for MMIO instead of | ||
344 | * a BAR value because X is lame and expects to be able to use that | ||
345 | * to pass to /dev/mem ! | ||
346 | * | ||
347 | * That means that we'll have potentially 64 bits values where some | ||
348 | * userland apps only expect 32 (like X itself since it thinks only | ||
349 | * Sparc has 64 bits MMIO) but if we don't do that, we break it on | ||
350 | * 32 bits CHRPs :-( | ||
351 | * | ||
352 | * Hopefully, the sysfs insterface is immune to that gunk. Once X | ||
353 | * has been fixed (and the fix spread enough), we can re-enable the | ||
354 | * 2 lines below and pass down a BAR value to userland. In that case | ||
355 | * we'll also have to re-enable the matching code in | ||
356 | * __pci_mmap_make_offset(). | ||
357 | * | ||
358 | * BenH. | ||
359 | */ | ||
360 | #if 0 | ||
361 | else if (rsrc->flags & IORESOURCE_MEM) | ||
362 | offset = hose->pci_mem_offset; | ||
363 | #endif | ||
364 | |||
365 | *start = rsrc->start - offset; | ||
366 | *end = rsrc->end - offset; | ||
367 | } | ||
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index c81ffa282977..3dd931ecce91 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c | |||
@@ -1028,34 +1028,12 @@ pci_create_OF_bus_map(void) | |||
1028 | } | 1028 | } |
1029 | } | 1029 | } |
1030 | 1030 | ||
1031 | static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf) | ||
1032 | { | ||
1033 | struct pci_dev *pdev; | ||
1034 | struct device_node *np; | ||
1035 | |||
1036 | pdev = to_pci_dev (dev); | ||
1037 | np = pci_device_to_OF_node(pdev); | ||
1038 | if (np == NULL || np->full_name == NULL) | ||
1039 | return 0; | ||
1040 | return sprintf(buf, "%s", np->full_name); | ||
1041 | } | ||
1042 | static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); | ||
1043 | |||
1044 | #else /* CONFIG_PPC_OF */ | 1031 | #else /* CONFIG_PPC_OF */ |
1045 | void pcibios_make_OF_bus_map(void) | 1032 | void pcibios_make_OF_bus_map(void) |
1046 | { | 1033 | { |
1047 | } | 1034 | } |
1048 | #endif /* CONFIG_PPC_OF */ | 1035 | #endif /* CONFIG_PPC_OF */ |
1049 | 1036 | ||
1050 | /* Add sysfs properties */ | ||
1051 | void pcibios_add_platform_entries(struct pci_dev *pdev) | ||
1052 | { | ||
1053 | #ifdef CONFIG_PPC_OF | ||
1054 | device_create_file(&pdev->dev, &dev_attr_devspec); | ||
1055 | #endif /* CONFIG_PPC_OF */ | ||
1056 | } | ||
1057 | |||
1058 | |||
1059 | #ifdef CONFIG_PPC_PMAC | 1037 | #ifdef CONFIG_PPC_PMAC |
1060 | /* | 1038 | /* |
1061 | * This set of routines checks for PCI<->PCI bridges that have closed | 1039 | * This set of routines checks for PCI<->PCI bridges that have closed |
@@ -1390,11 +1368,6 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) | |||
1390 | } | 1368 | } |
1391 | } | 1369 | } |
1392 | 1370 | ||
1393 | char __init *pcibios_setup(char *str) | ||
1394 | { | ||
1395 | return str; | ||
1396 | } | ||
1397 | |||
1398 | /* the next one is stolen from the alpha port... */ | 1371 | /* the next one is stolen from the alpha port... */ |
1399 | void __init | 1372 | void __init |
1400 | pcibios_update_irq(struct pci_dev *dev, int irq) | 1373 | pcibios_update_irq(struct pci_dev *dev, int irq) |
@@ -1403,64 +1376,6 @@ pcibios_update_irq(struct pci_dev *dev, int irq) | |||
1403 | /* XXX FIXME - update OF device tree node interrupt property */ | 1376 | /* XXX FIXME - update OF device tree node interrupt property */ |
1404 | } | 1377 | } |
1405 | 1378 | ||
1406 | #ifdef CONFIG_PPC_MERGE | ||
1407 | /* XXX This is a copy of the ppc64 version. This is temporary until we start | ||
1408 | * merging the 2 PCI layers | ||
1409 | */ | ||
1410 | /* | ||
1411 | * Reads the interrupt pin to determine if interrupt is use by card. | ||
1412 | * If the interrupt is used, then gets the interrupt line from the | ||
1413 | * openfirmware and sets it in the pci_dev and pci_config line. | ||
1414 | */ | ||
1415 | int pci_read_irq_line(struct pci_dev *pci_dev) | ||
1416 | { | ||
1417 | struct of_irq oirq; | ||
1418 | unsigned int virq; | ||
1419 | |||
1420 | DBG("Try to map irq for %s...\n", pci_name(pci_dev)); | ||
1421 | |||
1422 | /* Try to get a mapping from the device-tree */ | ||
1423 | if (of_irq_map_pci(pci_dev, &oirq)) { | ||
1424 | u8 line, pin; | ||
1425 | |||
1426 | /* If that fails, lets fallback to what is in the config | ||
1427 | * space and map that through the default controller. We | ||
1428 | * also set the type to level low since that's what PCI | ||
1429 | * interrupts are. If your platform does differently, then | ||
1430 | * either provide a proper interrupt tree or don't use this | ||
1431 | * function. | ||
1432 | */ | ||
1433 | if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin)) | ||
1434 | return -1; | ||
1435 | if (pin == 0) | ||
1436 | return -1; | ||
1437 | if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) || | ||
1438 | line == 0xff) { | ||
1439 | return -1; | ||
1440 | } | ||
1441 | DBG(" -> no map ! Using irq line %d from PCI config\n", line); | ||
1442 | |||
1443 | virq = irq_create_mapping(NULL, line); | ||
1444 | if (virq != NO_IRQ) | ||
1445 | set_irq_type(virq, IRQ_TYPE_LEVEL_LOW); | ||
1446 | } else { | ||
1447 | DBG(" -> got one, spec %d cells (0x%08x...) on %s\n", | ||
1448 | oirq.size, oirq.specifier[0], oirq.controller->full_name); | ||
1449 | |||
1450 | virq = irq_create_of_mapping(oirq.controller, oirq.specifier, | ||
1451 | oirq.size); | ||
1452 | } | ||
1453 | if(virq == NO_IRQ) { | ||
1454 | DBG(" -> failed to map !\n"); | ||
1455 | return -1; | ||
1456 | } | ||
1457 | pci_dev->irq = virq; | ||
1458 | |||
1459 | return 0; | ||
1460 | } | ||
1461 | EXPORT_SYMBOL(pci_read_irq_line); | ||
1462 | #endif /* CONFIG_PPC_MERGE */ | ||
1463 | |||
1464 | int pcibios_enable_device(struct pci_dev *dev, int mask) | 1379 | int pcibios_enable_device(struct pci_dev *dev, int mask) |
1465 | { | 1380 | { |
1466 | u16 cmd, old_cmd; | 1381 | u16 cmd, old_cmd; |
@@ -1503,176 +1418,6 @@ pci_bus_to_hose(int bus) | |||
1503 | return NULL; | 1418 | return NULL; |
1504 | } | 1419 | } |
1505 | 1420 | ||
1506 | static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, | ||
1507 | resource_size_t *offset, | ||
1508 | enum pci_mmap_state mmap_state) | ||
1509 | { | ||
1510 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | ||
1511 | unsigned long io_offset = 0; | ||
1512 | int i, res_bit; | ||
1513 | |||
1514 | if (hose == 0) | ||
1515 | return NULL; /* should never happen */ | ||
1516 | |||
1517 | /* If memory, add on the PCI bridge address offset */ | ||
1518 | if (mmap_state == pci_mmap_mem) { | ||
1519 | #if 0 /* See comment in pci_resource_to_user() for why this is disabled */ | ||
1520 | *offset += hose->pci_mem_offset; | ||
1521 | #endif | ||
1522 | res_bit = IORESOURCE_MEM; | ||
1523 | } else { | ||
1524 | io_offset = hose->io_base_virt - (void __iomem *)_IO_BASE; | ||
1525 | *offset += io_offset; | ||
1526 | res_bit = IORESOURCE_IO; | ||
1527 | } | ||
1528 | |||
1529 | /* | ||
1530 | * Check that the offset requested corresponds to one of the | ||
1531 | * resources of the device. | ||
1532 | */ | ||
1533 | for (i = 0; i <= PCI_ROM_RESOURCE; i++) { | ||
1534 | struct resource *rp = &dev->resource[i]; | ||
1535 | int flags = rp->flags; | ||
1536 | |||
1537 | /* treat ROM as memory (should be already) */ | ||
1538 | if (i == PCI_ROM_RESOURCE) | ||
1539 | flags |= IORESOURCE_MEM; | ||
1540 | |||
1541 | /* Active and same type? */ | ||
1542 | if ((flags & res_bit) == 0) | ||
1543 | continue; | ||
1544 | |||
1545 | /* In the range of this resource? */ | ||
1546 | if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end) | ||
1547 | continue; | ||
1548 | |||
1549 | /* found it! construct the final physical address */ | ||
1550 | if (mmap_state == pci_mmap_io) | ||
1551 | *offset += hose->io_base_phys - io_offset; | ||
1552 | return rp; | ||
1553 | } | ||
1554 | |||
1555 | return NULL; | ||
1556 | } | ||
1557 | |||
1558 | /* | ||
1559 | * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci | ||
1560 | * device mapping. | ||
1561 | */ | ||
1562 | static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, | ||
1563 | pgprot_t protection, | ||
1564 | enum pci_mmap_state mmap_state, | ||
1565 | int write_combine) | ||
1566 | { | ||
1567 | unsigned long prot = pgprot_val(protection); | ||
1568 | |||
1569 | /* Write combine is always 0 on non-memory space mappings. On | ||
1570 | * memory space, if the user didn't pass 1, we check for a | ||
1571 | * "prefetchable" resource. This is a bit hackish, but we use | ||
1572 | * this to workaround the inability of /sysfs to provide a write | ||
1573 | * combine bit | ||
1574 | */ | ||
1575 | if (mmap_state != pci_mmap_mem) | ||
1576 | write_combine = 0; | ||
1577 | else if (write_combine == 0) { | ||
1578 | if (rp->flags & IORESOURCE_PREFETCH) | ||
1579 | write_combine = 1; | ||
1580 | } | ||
1581 | |||
1582 | /* XXX would be nice to have a way to ask for write-through */ | ||
1583 | prot |= _PAGE_NO_CACHE; | ||
1584 | if (write_combine) | ||
1585 | prot &= ~_PAGE_GUARDED; | ||
1586 | else | ||
1587 | prot |= _PAGE_GUARDED; | ||
1588 | |||
1589 | return __pgprot(prot); | ||
1590 | } | ||
1591 | |||
1592 | /* | ||
1593 | * This one is used by /dev/mem and fbdev who have no clue about the | ||
1594 | * PCI device, it tries to find the PCI device first and calls the | ||
1595 | * above routine | ||
1596 | */ | ||
1597 | pgprot_t pci_phys_mem_access_prot(struct file *file, | ||
1598 | unsigned long pfn, | ||
1599 | unsigned long size, | ||
1600 | pgprot_t protection) | ||
1601 | { | ||
1602 | struct pci_dev *pdev = NULL; | ||
1603 | struct resource *found = NULL; | ||
1604 | unsigned long prot = pgprot_val(protection); | ||
1605 | unsigned long offset = pfn << PAGE_SHIFT; | ||
1606 | int i; | ||
1607 | |||
1608 | if (page_is_ram(pfn)) | ||
1609 | return __pgprot(prot); | ||
1610 | |||
1611 | prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; | ||
1612 | |||
1613 | for_each_pci_dev(pdev) { | ||
1614 | for (i = 0; i <= PCI_ROM_RESOURCE; i++) { | ||
1615 | struct resource *rp = &pdev->resource[i]; | ||
1616 | int flags = rp->flags; | ||
1617 | |||
1618 | /* Active and same type? */ | ||
1619 | if ((flags & IORESOURCE_MEM) == 0) | ||
1620 | continue; | ||
1621 | /* In the range of this resource? */ | ||
1622 | if (offset < (rp->start & PAGE_MASK) || | ||
1623 | offset > rp->end) | ||
1624 | continue; | ||
1625 | found = rp; | ||
1626 | break; | ||
1627 | } | ||
1628 | if (found) | ||
1629 | break; | ||
1630 | } | ||
1631 | if (found) { | ||
1632 | if (found->flags & IORESOURCE_PREFETCH) | ||
1633 | prot &= ~_PAGE_GUARDED; | ||
1634 | pci_dev_put(pdev); | ||
1635 | } | ||
1636 | |||
1637 | DBG("non-PCI map for %lx, prot: %lx\n", offset, prot); | ||
1638 | |||
1639 | return __pgprot(prot); | ||
1640 | } | ||
1641 | |||
1642 | |||
1643 | /* | ||
1644 | * Perform the actual remap of the pages for a PCI device mapping, as | ||
1645 | * appropriate for this architecture. The region in the process to map | ||
1646 | * is described by vm_start and vm_end members of VMA, the base physical | ||
1647 | * address is found in vm_pgoff. | ||
1648 | * The pci device structure is provided so that architectures may make mapping | ||
1649 | * decisions on a per-device or per-bus basis. | ||
1650 | * | ||
1651 | * Returns a negative error code on failure, zero on success. | ||
1652 | */ | ||
1653 | int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, | ||
1654 | enum pci_mmap_state mmap_state, | ||
1655 | int write_combine) | ||
1656 | { | ||
1657 | resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT; | ||
1658 | struct resource *rp; | ||
1659 | int ret; | ||
1660 | |||
1661 | rp = __pci_mmap_make_offset(dev, &offset, mmap_state); | ||
1662 | if (rp == NULL) | ||
1663 | return -EINVAL; | ||
1664 | |||
1665 | vma->vm_pgoff = offset >> PAGE_SHIFT; | ||
1666 | vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp, | ||
1667 | vma->vm_page_prot, | ||
1668 | mmap_state, write_combine); | ||
1669 | |||
1670 | ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, | ||
1671 | vma->vm_end - vma->vm_start, vma->vm_page_prot); | ||
1672 | |||
1673 | return ret; | ||
1674 | } | ||
1675 | |||
1676 | /* Provide information on locations of various I/O regions in physical | 1421 | /* Provide information on locations of various I/O regions in physical |
1677 | * memory. Do this on a per-card basis so that we choose the right | 1422 | * memory. Do this on a per-card basis so that we choose the right |
1678 | * root bridge. | 1423 | * root bridge. |
@@ -1715,45 +1460,6 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn) | |||
1715 | return result; | 1460 | return result; |
1716 | } | 1461 | } |
1717 | 1462 | ||
1718 | void pci_resource_to_user(const struct pci_dev *dev, int bar, | ||
1719 | const struct resource *rsrc, | ||
1720 | resource_size_t *start, resource_size_t *end) | ||
1721 | { | ||
1722 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | ||
1723 | resource_size_t offset = 0; | ||
1724 | |||
1725 | if (hose == NULL) | ||
1726 | return; | ||
1727 | |||
1728 | if (rsrc->flags & IORESOURCE_IO) | ||
1729 | offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||
1730 | |||
1731 | /* We pass a fully fixed up address to userland for MMIO instead of | ||
1732 | * a BAR value because X is lame and expects to be able to use that | ||
1733 | * to pass to /dev/mem ! | ||
1734 | * | ||
1735 | * That means that we'll have potentially 64 bits values where some | ||
1736 | * userland apps only expect 32 (like X itself since it thinks only | ||
1737 | * Sparc has 64 bits MMIO) but if we don't do that, we break it on | ||
1738 | * 32 bits CHRPs :-( | ||
1739 | * | ||
1740 | * Hopefully, the sysfs insterface is immune to that gunk. Once X | ||
1741 | * has been fixed (and the fix spread enough), we can re-enable the | ||
1742 | * 2 lines below and pass down a BAR value to userland. In that case | ||
1743 | * we'll also have to re-enable the matching code in | ||
1744 | * __pci_mmap_make_offset(). | ||
1745 | * | ||
1746 | * BenH. | ||
1747 | */ | ||
1748 | #if 0 | ||
1749 | else if (rsrc->flags & IORESOURCE_MEM) | ||
1750 | offset = hose->pci_mem_offset; | ||
1751 | #endif | ||
1752 | |||
1753 | *start = rsrc->start - offset; | ||
1754 | *end = rsrc->end - offset; | ||
1755 | } | ||
1756 | |||
1757 | unsigned long pci_address_to_pio(phys_addr_t address) | 1463 | unsigned long pci_address_to_pio(phys_addr_t address) |
1758 | { | 1464 | { |
1759 | struct pci_controller* hose = hose_head; | 1465 | struct pci_controller* hose = hose_head; |
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 57bdcd88f04a..384d2752fe60 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c | |||
@@ -601,11 +601,6 @@ static int __init pcibios_init(void) | |||
601 | 601 | ||
602 | subsys_initcall(pcibios_init); | 602 | subsys_initcall(pcibios_init); |
603 | 603 | ||
604 | char __init *pcibios_setup(char *str) | ||
605 | { | ||
606 | return str; | ||
607 | } | ||
608 | |||
609 | int pcibios_enable_device(struct pci_dev *dev, int mask) | 604 | int pcibios_enable_device(struct pci_dev *dev, int mask) |
610 | { | 605 | { |
611 | u16 cmd, oldcmd; | 606 | u16 cmd, oldcmd; |
@@ -647,211 +642,6 @@ int pci_proc_domain(struct pci_bus *bus) | |||
647 | } | 642 | } |
648 | } | 643 | } |
649 | 644 | ||
650 | /* | ||
651 | * Platform support for /proc/bus/pci/X/Y mmap()s, | ||
652 | * modelled on the sparc64 implementation by Dave Miller. | ||
653 | * -- paulus. | ||
654 | */ | ||
655 | |||
656 | /* | ||
657 | * Adjust vm_pgoff of VMA such that it is the physical page offset | ||
658 | * corresponding to the 32-bit pci bus offset for DEV requested by the user. | ||
659 | * | ||
660 | * Basically, the user finds the base address for his device which he wishes | ||
661 | * to mmap. They read the 32-bit value from the config space base register, | ||
662 | * add whatever PAGE_SIZE multiple offset they wish, and feed this into the | ||
663 | * offset parameter of mmap on /proc/bus/pci/XXX for that device. | ||
664 | * | ||
665 | * Returns negative error code on failure, zero on success. | ||
666 | */ | ||
667 | static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, | ||
668 | resource_size_t *offset, | ||
669 | enum pci_mmap_state mmap_state) | ||
670 | { | ||
671 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | ||
672 | unsigned long io_offset = 0; | ||
673 | int i, res_bit; | ||
674 | |||
675 | if (hose == 0) | ||
676 | return NULL; /* should never happen */ | ||
677 | |||
678 | /* If memory, add on the PCI bridge address offset */ | ||
679 | if (mmap_state == pci_mmap_mem) { | ||
680 | #if 0 /* See comment in pci_resource_to_user() for why this is disabled */ | ||
681 | *offset += hose->pci_mem_offset; | ||
682 | #endif | ||
683 | res_bit = IORESOURCE_MEM; | ||
684 | } else { | ||
685 | io_offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||
686 | *offset += io_offset; | ||
687 | res_bit = IORESOURCE_IO; | ||
688 | } | ||
689 | |||
690 | /* | ||
691 | * Check that the offset requested corresponds to one of the | ||
692 | * resources of the device. | ||
693 | */ | ||
694 | for (i = 0; i <= PCI_ROM_RESOURCE; i++) { | ||
695 | struct resource *rp = &dev->resource[i]; | ||
696 | int flags = rp->flags; | ||
697 | |||
698 | /* treat ROM as memory (should be already) */ | ||
699 | if (i == PCI_ROM_RESOURCE) | ||
700 | flags |= IORESOURCE_MEM; | ||
701 | |||
702 | /* Active and same type? */ | ||
703 | if ((flags & res_bit) == 0) | ||
704 | continue; | ||
705 | |||
706 | /* In the range of this resource? */ | ||
707 | if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end) | ||
708 | continue; | ||
709 | |||
710 | /* found it! construct the final physical address */ | ||
711 | if (mmap_state == pci_mmap_io) | ||
712 | *offset += hose->io_base_phys - io_offset; | ||
713 | return rp; | ||
714 | } | ||
715 | |||
716 | return NULL; | ||
717 | } | ||
718 | |||
719 | /* | ||
720 | * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci | ||
721 | * device mapping. | ||
722 | */ | ||
723 | static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, | ||
724 | pgprot_t protection, | ||
725 | enum pci_mmap_state mmap_state, | ||
726 | int write_combine) | ||
727 | { | ||
728 | unsigned long prot = pgprot_val(protection); | ||
729 | |||
730 | /* Write combine is always 0 on non-memory space mappings. On | ||
731 | * memory space, if the user didn't pass 1, we check for a | ||
732 | * "prefetchable" resource. This is a bit hackish, but we use | ||
733 | * this to workaround the inability of /sysfs to provide a write | ||
734 | * combine bit | ||
735 | */ | ||
736 | if (mmap_state != pci_mmap_mem) | ||
737 | write_combine = 0; | ||
738 | else if (write_combine == 0) { | ||
739 | if (rp->flags & IORESOURCE_PREFETCH) | ||
740 | write_combine = 1; | ||
741 | } | ||
742 | |||
743 | /* XXX would be nice to have a way to ask for write-through */ | ||
744 | prot |= _PAGE_NO_CACHE; | ||
745 | if (write_combine) | ||
746 | prot &= ~_PAGE_GUARDED; | ||
747 | else | ||
748 | prot |= _PAGE_GUARDED; | ||
749 | |||
750 | return __pgprot(prot); | ||
751 | } | ||
752 | |||
753 | /* | ||
754 | * This one is used by /dev/mem and fbdev who have no clue about the | ||
755 | * PCI device, it tries to find the PCI device first and calls the | ||
756 | * above routine | ||
757 | */ | ||
758 | pgprot_t pci_phys_mem_access_prot(struct file *file, | ||
759 | unsigned long pfn, | ||
760 | unsigned long size, | ||
761 | pgprot_t protection) | ||
762 | { | ||
763 | struct pci_dev *pdev = NULL; | ||
764 | struct resource *found = NULL; | ||
765 | unsigned long prot = pgprot_val(protection); | ||
766 | unsigned long offset = pfn << PAGE_SHIFT; | ||
767 | int i; | ||
768 | |||
769 | if (page_is_ram(pfn)) | ||
770 | return __pgprot(prot); | ||
771 | |||
772 | prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; | ||
773 | |||
774 | for_each_pci_dev(pdev) { | ||
775 | for (i = 0; i <= PCI_ROM_RESOURCE; i++) { | ||
776 | struct resource *rp = &pdev->resource[i]; | ||
777 | int flags = rp->flags; | ||
778 | |||
779 | /* Active and same type? */ | ||
780 | if ((flags & IORESOURCE_MEM) == 0) | ||
781 | continue; | ||
782 | /* In the range of this resource? */ | ||
783 | if (offset < (rp->start & PAGE_MASK) || | ||
784 | offset > rp->end) | ||
785 | continue; | ||
786 | found = rp; | ||
787 | break; | ||
788 | } | ||
789 | if (found) | ||
790 | break; | ||
791 | } | ||
792 | if (found) { | ||
793 | if (found->flags & IORESOURCE_PREFETCH) | ||
794 | prot &= ~_PAGE_GUARDED; | ||
795 | pci_dev_put(pdev); | ||
796 | } | ||
797 | |||
798 | DBG("non-PCI map for %lx, prot: %lx\n", offset, prot); | ||
799 | |||
800 | return __pgprot(prot); | ||
801 | } | ||
802 | |||
803 | |||
804 | /* | ||
805 | * Perform the actual remap of the pages for a PCI device mapping, as | ||
806 | * appropriate for this architecture. The region in the process to map | ||
807 | * is described by vm_start and vm_end members of VMA, the base physical | ||
808 | * address is found in vm_pgoff. | ||
809 | * The pci device structure is provided so that architectures may make mapping | ||
810 | * decisions on a per-device or per-bus basis. | ||
811 | * | ||
812 | * Returns a negative error code on failure, zero on success. | ||
813 | */ | ||
814 | int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, | ||
815 | enum pci_mmap_state mmap_state, int write_combine) | ||
816 | { | ||
817 | resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT; | ||
818 | struct resource *rp; | ||
819 | int ret; | ||
820 | |||
821 | rp = __pci_mmap_make_offset(dev, &offset, mmap_state); | ||
822 | if (rp == NULL) | ||
823 | return -EINVAL; | ||
824 | |||
825 | vma->vm_pgoff = offset >> PAGE_SHIFT; | ||
826 | vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp, | ||
827 | vma->vm_page_prot, | ||
828 | mmap_state, write_combine); | ||
829 | |||
830 | ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, | ||
831 | vma->vm_end - vma->vm_start, vma->vm_page_prot); | ||
832 | |||
833 | return ret; | ||
834 | } | ||
835 | |||
836 | static ssize_t pci_show_devspec(struct device *dev, | ||
837 | struct device_attribute *attr, char *buf) | ||
838 | { | ||
839 | struct pci_dev *pdev; | ||
840 | struct device_node *np; | ||
841 | |||
842 | pdev = to_pci_dev (dev); | ||
843 | np = pci_device_to_OF_node(pdev); | ||
844 | if (np == NULL || np->full_name == NULL) | ||
845 | return 0; | ||
846 | return sprintf(buf, "%s", np->full_name); | ||
847 | } | ||
848 | static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); | ||
849 | |||
850 | void pcibios_add_platform_entries(struct pci_dev *pdev) | ||
851 | { | ||
852 | device_create_file(&pdev->dev, &dev_attr_devspec); | ||
853 | } | ||
854 | |||
855 | void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, | 645 | void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, |
856 | struct device_node *dev, int prim) | 646 | struct device_node *dev, int prim) |
857 | { | 647 | { |
@@ -1167,105 +957,6 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) | |||
1167 | } | 957 | } |
1168 | EXPORT_SYMBOL(pcibios_fixup_bus); | 958 | EXPORT_SYMBOL(pcibios_fixup_bus); |
1169 | 959 | ||
1170 | /* | ||
1171 | * Reads the interrupt pin to determine if interrupt is use by card. | ||
1172 | * If the interrupt is used, then gets the interrupt line from the | ||
1173 | * openfirmware and sets it in the pci_dev and pci_config line. | ||
1174 | */ | ||
1175 | int pci_read_irq_line(struct pci_dev *pci_dev) | ||
1176 | { | ||
1177 | struct of_irq oirq; | ||
1178 | unsigned int virq; | ||
1179 | |||
1180 | DBG("Try to map irq for %s...\n", pci_name(pci_dev)); | ||
1181 | |||
1182 | #ifdef DEBUG | ||
1183 | memset(&oirq, 0xff, sizeof(oirq)); | ||
1184 | #endif | ||
1185 | /* Try to get a mapping from the device-tree */ | ||
1186 | if (of_irq_map_pci(pci_dev, &oirq)) { | ||
1187 | u8 line, pin; | ||
1188 | |||
1189 | /* If that fails, lets fallback to what is in the config | ||
1190 | * space and map that through the default controller. We | ||
1191 | * also set the type to level low since that's what PCI | ||
1192 | * interrupts are. If your platform does differently, then | ||
1193 | * either provide a proper interrupt tree or don't use this | ||
1194 | * function. | ||
1195 | */ | ||
1196 | if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin)) | ||
1197 | return -1; | ||
1198 | if (pin == 0) | ||
1199 | return -1; | ||
1200 | if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) || | ||
1201 | line == 0xff) { | ||
1202 | return -1; | ||
1203 | } | ||
1204 | DBG(" -> no map ! Using irq line %d from PCI config\n", line); | ||
1205 | |||
1206 | virq = irq_create_mapping(NULL, line); | ||
1207 | if (virq != NO_IRQ) | ||
1208 | set_irq_type(virq, IRQ_TYPE_LEVEL_LOW); | ||
1209 | } else { | ||
1210 | DBG(" -> got one, spec %d cells (0x%08x 0x%08x...) on %s\n", | ||
1211 | oirq.size, oirq.specifier[0], oirq.specifier[1], | ||
1212 | oirq.controller->full_name); | ||
1213 | |||
1214 | virq = irq_create_of_mapping(oirq.controller, oirq.specifier, | ||
1215 | oirq.size); | ||
1216 | } | ||
1217 | if(virq == NO_IRQ) { | ||
1218 | DBG(" -> failed to map !\n"); | ||
1219 | return -1; | ||
1220 | } | ||
1221 | |||
1222 | DBG(" -> mapped to linux irq %d\n", virq); | ||
1223 | |||
1224 | pci_dev->irq = virq; | ||
1225 | |||
1226 | return 0; | ||
1227 | } | ||
1228 | EXPORT_SYMBOL(pci_read_irq_line); | ||
1229 | |||
1230 | void pci_resource_to_user(const struct pci_dev *dev, int bar, | ||
1231 | const struct resource *rsrc, | ||
1232 | resource_size_t *start, resource_size_t *end) | ||
1233 | { | ||
1234 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | ||
1235 | resource_size_t offset = 0; | ||
1236 | |||
1237 | if (hose == NULL) | ||
1238 | return; | ||
1239 | |||
1240 | if (rsrc->flags & IORESOURCE_IO) | ||
1241 | offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||
1242 | |||
1243 | /* We pass a fully fixed up address to userland for MMIO instead of | ||
1244 | * a BAR value because X is lame and expects to be able to use that | ||
1245 | * to pass to /dev/mem ! | ||
1246 | * | ||
1247 | * That means that we'll have potentially 64 bits values where some | ||
1248 | * userland apps only expect 32 (like X itself since it thinks only | ||
1249 | * Sparc has 64 bits MMIO) but if we don't do that, we break it on | ||
1250 | * 32 bits CHRPs :-( | ||
1251 | * | ||
1252 | * Hopefully, the sysfs insterface is immune to that gunk. Once X | ||
1253 | * has been fixed (and the fix spread enough), we can re-enable the | ||
1254 | * 2 lines below and pass down a BAR value to userland. In that case | ||
1255 | * we'll also have to re-enable the matching code in | ||
1256 | * __pci_mmap_make_offset(). | ||
1257 | * | ||
1258 | * BenH. | ||
1259 | */ | ||
1260 | #if 0 | ||
1261 | else if (rsrc->flags & IORESOURCE_MEM) | ||
1262 | offset = hose->pci_mem_offset; | ||
1263 | #endif | ||
1264 | |||
1265 | *start = rsrc->start - offset; | ||
1266 | *end = rsrc->end - offset; | ||
1267 | } | ||
1268 | |||
1269 | struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node) | 960 | struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node) |
1270 | { | 961 | { |
1271 | if (!have_of) | 962 | if (!have_of) |