Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pci-asb2305.c
Go to the documentation of this file.
1 /* ASB2305 PCI resource stuff
2  *
3  * Copyright (C) 2001 Red Hat, Inc. All Rights Reserved.
4  * Written by David Howells ([email protected])
5  * - Derived from arch/i386/pci-i386.c
6  * - Copyright 1997--2000 Martin Mares <[email protected]>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public Licence
10  * as published by the Free Software Foundation; either version
11  * 2 of the Licence, or (at your option) any later version.
12  */
13 #include <linux/types.h>
14 #include <linux/kernel.h>
15 #include <linux/pci.h>
16 #include <linux/init.h>
17 #include <linux/ioport.h>
18 #include <linux/errno.h>
19 #include "pci-asb2305.h"
20 
21 /*
22  * We need to avoid collisions with `mirrored' VGA ports
23  * and other strange ISA hardware, so we always want the
24  * addresses to be allocated in the 0x000-0x0ff region
25  * modulo 0x400.
26  *
27  * Why? Because some silly external IO cards only decode
28  * the low 10 bits of the IO address. The 0x00-0xff region
29  * is reserved for motherboard devices that decode all 16
30  * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
31  * but we want to try to avoid allocating at 0x2900-0x2bff
32  * which might have be mirrored at 0x0100-0x03ff..
33  */
36 {
38 
39 #if 0
40  struct pci_dev *dev = data;
41 
43  "### PCIBIOS_ALIGN_RESOURCE(%s,,{%08lx-%08lx,%08lx},%lx)\n",
44  pci_name(dev),
45  res->start,
46  res->end,
47  res->flags,
48  size
49  );
50 #endif
51 
52  if ((res->flags & IORESOURCE_IO) && (start & 0x300))
53  start = (start + 0x3ff) & ~0x3ff;
54 
55  return start;
56 }
57 
58 
59 /*
60  * Handle resources of PCI devices. If the world were perfect, we could
61  * just allocate all the resource regions and do nothing more. It isn't.
62  * On the other hand, we cannot just re-allocate all devices, as it would
63  * require us to know lots of host bridge internals. So we attempt to
64  * keep as much of the original configuration as possible, but tweak it
65  * when it's found to be wrong.
66  *
67  * Known BIOS problems we have to work around:
68  * - I/O or memory regions not configured
69  * - regions configured, but not enabled in the command register
70  * - bogus I/O addresses above 64K used
71  * - expansion ROMs left enabled (this may sound harmless, but given
72  * the fact the PCI specs explicitly allow address decoders to be
73  * shared between expansion ROMs and other resource regions, it's
74  * at least dangerous)
75  *
76  * Our solution:
77  * (1) Allocate resources for all buses behind PCI-to-PCI bridges.
78  * This gives us fixed barriers on where we can allocate.
79  * (2) Allocate resources for all enabled devices. If there is
80  * a collision, just mark the resource as unallocated. Also
81  * disable expansion ROMs during this step.
82  * (3) Try to allocate resources for disabled devices. If the
83  * resources were assigned correctly, everything goes well,
84  * if they weren't, they won't disturb allocation of other
85  * resources.
86  * (4) Assign new addresses to resources which were either
87  * not configured at all or misconfigured. If explicitly
88  * requested by the user, configure expansion ROM address
89  * as well.
90  */
92 {
93  struct pci_bus *bus;
94  struct pci_dev *dev;
95  int idx;
96  struct resource *r;
97 
98  /* Depth-First Search on bus tree */
99  list_for_each_entry(bus, bus_list, node) {
100  dev = bus->self;
101  if (dev) {
102  for (idx = PCI_BRIDGE_RESOURCES;
103  idx < PCI_NUM_RESOURCES;
104  idx++) {
105  r = &dev->resource[idx];
106  if (!r->flags)
107  continue;
108  if (!r->start ||
109  pci_claim_resource(dev, idx) < 0) {
110  printk(KERN_ERR "PCI:"
111  " Cannot allocate resource"
112  " region %d of bridge %s\n",
113  idx, pci_name(dev));
114  /* Something is wrong with the region.
115  * Invalidate the resource to prevent
116  * child resource allocations in this
117  * range. */
118  r->start = r->end = 0;
119  r->flags = 0;
120  }
121  }
122  }
124  }
125 }
126 
127 static void __init pcibios_allocate_resources(int pass)
128 {
129  struct pci_dev *dev = NULL;
130  int idx, disabled;
131  u16 command;
132  struct resource *r;
133 
134  for_each_pci_dev(dev) {
135  pci_read_config_word(dev, PCI_COMMAND, &command);
136  for (idx = 0; idx < 6; idx++) {
137  r = &dev->resource[idx];
138  if (r->parent) /* Already allocated */
139  continue;
140  if (!r->start) /* Address not assigned */
141  continue;
142  if (r->flags & IORESOURCE_IO)
143  disabled = !(command & PCI_COMMAND_IO);
144  else
145  disabled = !(command & PCI_COMMAND_MEMORY);
146  if (pass == disabled) {
147  DBG("PCI[%s]: Resource %08lx-%08lx"
148  " (f=%lx, d=%d, p=%d)\n",
149  pci_name(dev), r->start, r->end, r->flags,
150  disabled, pass);
151  if (pci_claim_resource(dev, idx) < 0) {
152  printk(KERN_ERR "PCI:"
153  " Cannot allocate resource"
154  " region %d of device %s\n",
155  idx, pci_name(dev));
156  /* We'll assign a new address later */
157  r->end -= r->start;
158  r->start = 0;
159  }
160  }
161  }
162  if (!pass) {
163  r = &dev->resource[PCI_ROM_RESOURCE];
164  if (r->flags & IORESOURCE_ROM_ENABLE) {
165  /* Turn the ROM off, leave the resource region,
166  * but keep it unregistered. */
167  u32 reg;
168  DBG("PCI: Switching off ROM of %s\n",
169  pci_name(dev));
171  pci_read_config_dword(
172  dev, dev->rom_base_reg, &reg);
173  pci_write_config_dword(
174  dev, dev->rom_base_reg,
175  reg & ~PCI_ROM_ADDRESS_ENABLE);
176  }
177  }
178  }
179 }
180 
181 static int __init pcibios_assign_resources(void)
182 {
183  struct pci_dev *dev = NULL;
184  struct resource *r;
185 
186  if (!(pci_probe & PCI_ASSIGN_ROMS)) {
187  /* Try to use BIOS settings for ROMs, otherwise let
188  pci_assign_unassigned_resources() allocate the new
189  addresses. */
190  for_each_pci_dev(dev) {
191  r = &dev->resource[PCI_ROM_RESOURCE];
192  if (!r->flags || !r->start)
193  continue;
194  if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) {
195  r->end -= r->start;
196  r->start = 0;
197  }
198  }
199  }
200 
202 
203  return 0;
204 }
205 
206 fs_initcall(pcibios_assign_resources);
207 
209 {
210  DBG("PCI: Allocating resources\n");
211  pcibios_allocate_bus_resources(&pci_root_buses);
212  pcibios_allocate_resources(0);
213  pcibios_allocate_resources(1);
214 }
215 
216 int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
217  enum pci_mmap_state mmap_state, int write_combine)
218 {
219  unsigned long prot;
220 
221  /* Leave vm_pgoff as-is, the PCI space address is the physical
222  * address on this platform.
223  */
224  vma->vm_flags |= VM_LOCKED | VM_IO;
225 
226  prot = pgprot_val(vma->vm_page_prot);
227  prot &= ~_PAGE_CACHE;
228  vma->vm_page_prot = __pgprot(prot);
229 
230  /* Write-combine setting is ignored */
231  if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
232  vma->vm_end - vma->vm_start,
233  vma->vm_page_prot))
234  return -EAGAIN;
235 
236  return 0;
237 }