aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/drivers/pci/pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/drivers/pci/pci.c')
-rw-r--r--arch/sh/drivers/pci/pci.c173
1 files changed, 138 insertions, 35 deletions
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
index c481df639022..953af139e230 100644
--- a/arch/sh/drivers/pci/pci.c
+++ b/arch/sh/drivers/pci/pci.c
@@ -33,15 +33,22 @@ static int pci_initialized;
33static void __devinit pcibios_scanbus(struct pci_channel *hose) 33static void __devinit pcibios_scanbus(struct pci_channel *hose)
34{ 34{
35 static int next_busno; 35 static int next_busno;
36 static int need_domain_info;
36 struct pci_bus *bus; 37 struct pci_bus *bus;
37 38
38 bus = pci_scan_bus(next_busno, hose->pci_ops, hose); 39 bus = pci_scan_bus(next_busno, hose->pci_ops, hose);
40 hose->bus = bus;
41
42 need_domain_info = need_domain_info || hose->index;
43 hose->need_domain_info = need_domain_info;
39 if (bus) { 44 if (bus) {
40 next_busno = bus->subordinate + 1; 45 next_busno = bus->subordinate + 1;
41 /* Don't allow 8-bit bus number overflow inside the hose - 46 /* Don't allow 8-bit bus number overflow inside the hose -
42 reserve some space for bridges. */ 47 reserve some space for bridges. */
43 if (next_busno > 224) 48 if (next_busno > 224) {
44 next_busno = 0; 49 next_busno = 0;
50 need_domain_info = 1;
51 }
45 52
46 pci_bus_size_bridges(bus); 53 pci_bus_size_bridges(bus);
47 pci_bus_assign_resources(bus); 54 pci_bus_assign_resources(bus);
@@ -51,10 +58,21 @@ static void __devinit pcibios_scanbus(struct pci_channel *hose)
51 58
52static DEFINE_MUTEX(pci_scan_mutex); 59static DEFINE_MUTEX(pci_scan_mutex);
53 60
54void __devinit register_pci_controller(struct pci_channel *hose) 61int __devinit register_pci_controller(struct pci_channel *hose)
55{ 62{
56 request_resource(&iomem_resource, hose->mem_resource); 63 int i;
57 request_resource(&ioport_resource, hose->io_resource); 64
65 for (i = 0; i < hose->nr_resources; i++) {
66 struct resource *res = hose->resources + i;
67
68 if (res->flags & IORESOURCE_IO) {
69 if (request_resource(&ioport_resource, res) < 0)
70 goto out;
71 } else {
72 if (request_resource(&iomem_resource, res) < 0)
73 goto out;
74 }
75 }
58 76
59 *hose_tail = hose; 77 *hose_tail = hose;
60 hose_tail = &hose->next; 78 hose_tail = &hose->next;
@@ -68,6 +86,11 @@ void __devinit register_pci_controller(struct pci_channel *hose)
68 } 86 }
69 87
70 /* 88 /*
89 * Setup the ERR/PERR and SERR timers, if available.
90 */
91 pcibios_enable_timers(hose);
92
93 /*
71 * Scan the bus if it is register after the PCI subsystem 94 * Scan the bus if it is register after the PCI subsystem
72 * initialization. 95 * initialization.
73 */ 96 */
@@ -76,6 +99,15 @@ void __devinit register_pci_controller(struct pci_channel *hose)
76 pcibios_scanbus(hose); 99 pcibios_scanbus(hose);
77 mutex_unlock(&pci_scan_mutex); 100 mutex_unlock(&pci_scan_mutex);
78 } 101 }
102
103 return 0;
104
105out:
106 for (--i; i >= 0; i--)
107 release_resource(&hose->resources[i]);
108
109 printk(KERN_WARNING "Skipping PCI bus scan due to resource conflict\n");
110 return -1;
79} 111}
80 112
81static int __init pcibios_init(void) 113static int __init pcibios_init(void)
@@ -127,11 +159,13 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
127{ 159{
128 struct pci_dev *dev = bus->self; 160 struct pci_dev *dev = bus->self;
129 struct list_head *ln; 161 struct list_head *ln;
130 struct pci_channel *chan = bus->sysdata; 162 struct pci_channel *hose = bus->sysdata;
131 163
132 if (!dev) { 164 if (!dev) {
133 bus->resource[0] = chan->io_resource; 165 int i;
134 bus->resource[1] = chan->mem_resource; 166
167 for (i = 0; i < hose->nr_resources; i++)
168 bus->resource[i] = hose->resources + i;
135 } 169 }
136 170
137 for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) { 171 for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
@@ -148,34 +182,29 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
148 * addresses to be allocated in the 0x000-0x0ff region 182 * addresses to be allocated in the 0x000-0x0ff region
149 * modulo 0x400. 183 * modulo 0x400.
150 */ 184 */
151void pcibios_align_resource(void *data, struct resource *res, 185resource_size_t pcibios_align_resource(void *data, const struct resource *res,
152 resource_size_t size, resource_size_t align) 186 resource_size_t size, resource_size_t align)
153{ 187{
154 struct pci_dev *dev = data; 188 struct pci_dev *dev = data;
155 struct pci_channel *chan = dev->sysdata; 189 struct pci_channel *hose = dev->sysdata;
156 resource_size_t start = res->start; 190 resource_size_t start = res->start;
157 191
158 if (res->flags & IORESOURCE_IO) { 192 if (res->flags & IORESOURCE_IO) {
159 if (start < PCIBIOS_MIN_IO + chan->io_resource->start) 193 if (start < PCIBIOS_MIN_IO + hose->resources[0].start)
160 start = PCIBIOS_MIN_IO + chan->io_resource->start; 194 start = PCIBIOS_MIN_IO + hose->resources[0].start;
161 195
162 /* 196 /*
163 * Put everything into 0x00-0xff region modulo 0x400. 197 * Put everything into 0x00-0xff region modulo 0x400.
164 */ 198 */
165 if (start & 0x300) { 199 if (start & 0x300)
166 start = (start + 0x3ff) & ~0x3ff; 200 start = (start + 0x3ff) & ~0x3ff;
167 res->start = start;
168 }
169 } else if (res->flags & IORESOURCE_MEM) {
170 if (start < PCIBIOS_MIN_MEM + chan->mem_resource->start)
171 start = PCIBIOS_MIN_MEM + chan->mem_resource->start;
172 } 201 }
173 202
174 res->start = start; 203 return start;
175} 204}
176 205
177void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, 206void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
178 struct resource *res) 207 struct resource *res)
179{ 208{
180 struct pci_channel *hose = dev->sysdata; 209 struct pci_channel *hose = dev->sysdata;
181 unsigned long offset = 0; 210 unsigned long offset = 0;
@@ -189,9 +218,8 @@ void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
189 region->end = res->end - offset; 218 region->end = res->end - offset;
190} 219}
191 220
192void __devinit 221void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
193pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, 222 struct pci_bus_region *region)
194 struct pci_bus_region *region)
195{ 223{
196 struct pci_channel *hose = dev->sysdata; 224 struct pci_channel *hose = dev->sysdata;
197 unsigned long offset = 0; 225 unsigned long offset = 0;
@@ -274,6 +302,86 @@ char * __devinit pcibios_setup(char *str)
274 return str; 302 return str;
275} 303}
276 304
305static void __init
306pcibios_bus_report_status_early(struct pci_channel *hose,
307 int top_bus, int current_bus,
308 unsigned int status_mask, int warn)
309{
310 unsigned int pci_devfn;
311 u16 status;
312 int ret;
313
314 for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++) {
315 if (PCI_FUNC(pci_devfn))
316 continue;
317 ret = early_read_config_word(hose, top_bus, current_bus,
318 pci_devfn, PCI_STATUS, &status);
319 if (ret != PCIBIOS_SUCCESSFUL)
320 continue;
321 if (status == 0xffff)
322 continue;
323
324 early_write_config_word(hose, top_bus, current_bus,
325 pci_devfn, PCI_STATUS,
326 status & status_mask);
327 if (warn)
328 printk("(%02x:%02x: %04X) ", current_bus,
329 pci_devfn, status);
330 }
331}
332
333/*
334 * We can't use pci_find_device() here since we are
335 * called from interrupt context.
336 */
337static void __init_refok
338pcibios_bus_report_status(struct pci_bus *bus, unsigned int status_mask,
339 int warn)
340{
341 struct pci_dev *dev;
342
343 list_for_each_entry(dev, &bus->devices, bus_list) {
344 u16 status;
345
346 /*
347 * ignore host bridge - we handle
348 * that separately
349 */
350 if (dev->bus->number == 0 && dev->devfn == 0)
351 continue;
352
353 pci_read_config_word(dev, PCI_STATUS, &status);
354 if (status == 0xffff)
355 continue;
356
357 if ((status & status_mask) == 0)
358 continue;
359
360 /* clear the status errors */
361 pci_write_config_word(dev, PCI_STATUS, status & status_mask);
362
363 if (warn)
364 printk("(%s: %04X) ", pci_name(dev), status);
365 }
366
367 list_for_each_entry(dev, &bus->devices, bus_list)
368 if (dev->subordinate)
369 pcibios_bus_report_status(dev->subordinate, status_mask, warn);
370}
371
372void __init_refok pcibios_report_status(unsigned int status_mask, int warn)
373{
374 struct pci_channel *hose;
375
376 for (hose = hose_head; hose; hose = hose->next) {
377 if (unlikely(!hose->bus))
378 pcibios_bus_report_status_early(hose, hose_head->index,
379 hose->index, status_mask, warn);
380 else
381 pcibios_bus_report_status(hose->bus, status_mask, warn);
382 }
383}
384
277int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, 385int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
278 enum pci_mmap_state mmap_state, int write_combine) 386 enum pci_mmap_state mmap_state, int write_combine)
279{ 387{
@@ -302,9 +410,15 @@ static void __iomem *ioport_map_pci(struct pci_dev *dev,
302{ 410{
303 struct pci_channel *chan = dev->sysdata; 411 struct pci_channel *chan = dev->sysdata;
304 412
305 if (!chan->io_map_base) 413 if (unlikely(!chan->io_map_base)) {
306 chan->io_map_base = generic_io_base; 414 chan->io_map_base = generic_io_base;
307 415
416 if (pci_domains_supported)
417 panic("To avoid data corruption io_map_base MUST be "
418 "set with multiple PCI domains.");
419 }
420
421
308 return (void __iomem *)(chan->io_map_base + port); 422 return (void __iomem *)(chan->io_map_base + port);
309} 423}
310 424
@@ -321,20 +435,9 @@ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
321 435
322 if (flags & IORESOURCE_IO) 436 if (flags & IORESOURCE_IO)
323 return ioport_map_pci(dev, start, len); 437 return ioport_map_pci(dev, start, len);
324
325 /*
326 * Presently the IORESOURCE_MEM case is a bit special, most
327 * SH7751 style PCI controllers have PCI memory at a fixed
328 * location in the address space where no remapping is desired.
329 * With the IORESOURCE_MEM case more care has to be taken
330 * to inhibit page table mapping for legacy cores, but this is
331 * punted off to __ioremap().
332 * -- PFM.
333 */
334 if (flags & IORESOURCE_MEM) { 438 if (flags & IORESOURCE_MEM) {
335 if (flags & IORESOURCE_CACHEABLE) 439 if (flags & IORESOURCE_CACHEABLE)
336 return ioremap(start, len); 440 return ioremap(start, len);
337
338 return ioremap_nocache(start, len); 441 return ioremap_nocache(start, len);
339 } 442 }
340 443