diff options
author | Paul Mundt <lethal@linux-sh.org> | 2010-02-01 06:01:50 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2010-02-01 06:01:50 -0500 |
commit | b6c58b1d987a5795086c5c2babd8c7367d2fdb8c (patch) | |
tree | 3ec992af50f44dd09ff125165ea1c4ef41b2aecc /arch/sh | |
parent | ef407beefbd9928792ccc93857e408e0057bc17b (diff) |
sh: Improved multi-resource handling for SH7780 PCI.
The SH7780 PCI controller supports 3 different ranges of PCI memory in
addition to its PCI I/O window. In the case of 29-bit mode, only 2 memory
windows are supported, while in 32-bit mode all 3 are visible. This
attempts to make the resource handling completely dynamic and to permit
platforms to map in as many apertures as they can handle.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh')
-rw-r--r-- | arch/sh/drivers/pci/fixups-dreamcast.c | 2 | ||||
-rw-r--r-- | arch/sh/drivers/pci/fixups-se7751.c | 6 | ||||
-rw-r--r-- | arch/sh/drivers/pci/pci-dreamcast.c | 28 | ||||
-rw-r--r-- | arch/sh/drivers/pci/pci-sh5.c | 15 | ||||
-rw-r--r-- | arch/sh/drivers/pci/pci-sh7751.c | 32 | ||||
-rw-r--r-- | arch/sh/drivers/pci/pci-sh7780.c | 86 | ||||
-rw-r--r-- | arch/sh/drivers/pci/pci-sh7780.h | 14 | ||||
-rw-r--r-- | arch/sh/drivers/pci/pci.c | 37 | ||||
-rw-r--r-- | arch/sh/include/asm/pci.h | 5 |
9 files changed, 133 insertions, 92 deletions
diff --git a/arch/sh/drivers/pci/fixups-dreamcast.c b/arch/sh/drivers/pci/fixups-dreamcast.c index ed7f489936f1..942ef4f155f5 100644 --- a/arch/sh/drivers/pci/fixups-dreamcast.c +++ b/arch/sh/drivers/pci/fixups-dreamcast.c | |||
@@ -39,7 +39,7 @@ static void __init gapspci_fixup_resources(struct pci_dev *dev) | |||
39 | /* | 39 | /* |
40 | * We also assume that dev->devfn == 0 | 40 | * We also assume that dev->devfn == 0 |
41 | */ | 41 | */ |
42 | dev->resource[1].start = p->io_resource->start + 0x100; | 42 | dev->resource[1].start = p->resources[0].start + 0x100; |
43 | dev->resource[1].end = dev->resource[1].start + 0x200 - 1; | 43 | dev->resource[1].end = dev->resource[1].start + 0x200 - 1; |
44 | 44 | ||
45 | /* | 45 | /* |
diff --git a/arch/sh/drivers/pci/fixups-se7751.c b/arch/sh/drivers/pci/fixups-se7751.c index 475fa9f0fe2c..a4c7d3a4efca 100644 --- a/arch/sh/drivers/pci/fixups-se7751.c +++ b/arch/sh/drivers/pci/fixups-se7751.c | |||
@@ -97,12 +97,12 @@ int pci_fixup_pcic(struct pci_channel *chan) | |||
97 | * meaning all calls go straight through... use BUG_ON to | 97 | * meaning all calls go straight through... use BUG_ON to |
98 | * catch erroneous assumption. | 98 | * catch erroneous assumption. |
99 | */ | 99 | */ |
100 | BUG_ON(chan->mem_resource->start != SH7751_PCI_MEMORY_BASE); | 100 | BUG_ON(chan->resources[1].start != SH7751_PCI_MEMORY_BASE); |
101 | 101 | ||
102 | PCIC_WRITE(SH7751_PCIMBR, chan->mem_resource->start); | 102 | PCIC_WRITE(SH7751_PCIMBR, chan->resources[1].start); |
103 | 103 | ||
104 | /* Set IOBR for window containing area specified in pci.h */ | 104 | /* Set IOBR for window containing area specified in pci.h */ |
105 | PCIC_WRITE(SH7751_PCIIOBR, (chan->io_resource->start & SH7751_PCIIOBR_MASK)); | 105 | PCIC_WRITE(SH7751_PCIIOBR, (chan->resources[0].start & SH7751_PCIIOBR_MASK)); |
106 | 106 | ||
107 | /* All done, may as well say so... */ | 107 | /* All done, may as well say so... */ |
108 | printk("SH7751 PCI: Finished initialization of the PCI controller\n"); | 108 | printk("SH7751 PCI: Finished initialization of the PCI controller\n"); |
diff --git a/arch/sh/drivers/pci/pci-dreamcast.c b/arch/sh/drivers/pci/pci-dreamcast.c index bd5a1e50ebf6..633694193af8 100644 --- a/arch/sh/drivers/pci/pci-dreamcast.c +++ b/arch/sh/drivers/pci/pci-dreamcast.c | |||
@@ -25,25 +25,25 @@ | |||
25 | #include <asm/irq.h> | 25 | #include <asm/irq.h> |
26 | #include <mach/pci.h> | 26 | #include <mach/pci.h> |
27 | 27 | ||
28 | static struct resource gapspci_io_resource = { | 28 | static struct resource gapspci_resources[] = { |
29 | .name = "GAPSPCI IO", | 29 | { |
30 | .start = GAPSPCI_BBA_CONFIG, | 30 | .name = "GAPSPCI IO", |
31 | .end = GAPSPCI_BBA_CONFIG + GAPSPCI_BBA_CONFIG_SIZE - 1, | 31 | .start = GAPSPCI_BBA_CONFIG, |
32 | .flags = IORESOURCE_IO, | 32 | .end = GAPSPCI_BBA_CONFIG + GAPSPCI_BBA_CONFIG_SIZE - 1, |
33 | }; | 33 | .flags = IORESOURCE_IO, |
34 | 34 | }, { | |
35 | static struct resource gapspci_mem_resource = { | 35 | .name = "GAPSPCI mem", |
36 | .name = "GAPSPCI mem", | 36 | .start = GAPSPCI_DMA_BASE, |
37 | .start = GAPSPCI_DMA_BASE, | 37 | .end = GAPSPCI_DMA_BASE + GAPSPCI_DMA_SIZE - 1, |
38 | .end = GAPSPCI_DMA_BASE + GAPSPCI_DMA_SIZE - 1, | 38 | .flags = IORESOURCE_MEM, |
39 | .flags = IORESOURCE_MEM, | 39 | }, |
40 | }; | 40 | }; |
41 | 41 | ||
42 | static struct pci_channel dreamcast_pci_controller = { | 42 | static struct pci_channel dreamcast_pci_controller = { |
43 | .pci_ops = &gapspci_pci_ops, | 43 | .pci_ops = &gapspci_pci_ops, |
44 | .io_resource = &gapspci_io_resource, | 44 | .resources = gapspci_resources, |
45 | .nr_resources = ARRAY_SIZE(gapspci_resources), | ||
45 | .io_offset = 0x00000000, | 46 | .io_offset = 0x00000000, |
46 | .mem_resource = &gapspci_mem_resource, | ||
47 | .mem_offset = 0x00000000, | 47 | .mem_offset = 0x00000000, |
48 | }; | 48 | }; |
49 | 49 | ||
diff --git a/arch/sh/drivers/pci/pci-sh5.c b/arch/sh/drivers/pci/pci-sh5.c index bce73faabc88..0bf296c78795 100644 --- a/arch/sh/drivers/pci/pci-sh5.c +++ b/arch/sh/drivers/pci/pci-sh5.c | |||
@@ -89,14 +89,13 @@ static irqreturn_t pcish5_serr_irq(int irq, void *dev_id) | |||
89 | return IRQ_NONE; | 89 | return IRQ_NONE; |
90 | } | 90 | } |
91 | 91 | ||
92 | static struct resource sh5_io_resource = { /* place holder */ }; | 92 | static struct resource sh5_pci_resources[2]; |
93 | static struct resource sh5_mem_resource = { /* place holder */ }; | ||
94 | 93 | ||
95 | static struct pci_channel sh5pci_controller = { | 94 | static struct pci_channel sh5pci_controller = { |
96 | .pci_ops = &sh5_pci_ops, | 95 | .pci_ops = &sh5_pci_ops, |
97 | .mem_resource = &sh5_mem_resource, | 96 | .resources = sh5_pci_resources, |
97 | .nr_resources = ARRAY_SIZE(sh5_pci_resources), | ||
98 | .mem_offset = 0x00000000, | 98 | .mem_offset = 0x00000000, |
99 | .io_resource = &sh5_io_resource, | ||
100 | .io_offset = 0x00000000, | 99 | .io_offset = 0x00000000, |
101 | }; | 100 | }; |
102 | 101 | ||
@@ -210,11 +209,11 @@ static int __init sh5pci_init(void) | |||
210 | SH5PCI_WRITE(AINTM, ~0); | 209 | SH5PCI_WRITE(AINTM, ~0); |
211 | SH5PCI_WRITE(PINTM, ~0); | 210 | SH5PCI_WRITE(PINTM, ~0); |
212 | 211 | ||
213 | sh5_io_resource.start = PCI_IO_AREA; | 212 | sh5_pci_resources[0].start = PCI_IO_AREA; |
214 | sh5_io_resource.end = PCI_IO_AREA + 0x10000; | 213 | sh5_pci_resources[0].end = PCI_IO_AREA + 0x10000; |
215 | 214 | ||
216 | sh5_mem_resource.start = memStart; | 215 | sh5_pci_resources[1].start = memStart; |
217 | sh5_mem_resource.end = memStart + memSize; | 216 | sh5_pci_resources[1].end = memStart + memSize; |
218 | 217 | ||
219 | return register_pci_controller(&sh5pci_controller); | 218 | return register_pci_controller(&sh5pci_controller); |
220 | } | 219 | } |
diff --git a/arch/sh/drivers/pci/pci-sh7751.c b/arch/sh/drivers/pci/pci-sh7751.c index 6ad5beb524aa..17811e5d287b 100644 --- a/arch/sh/drivers/pci/pci-sh7751.c +++ b/arch/sh/drivers/pci/pci-sh7751.c | |||
@@ -44,25 +44,25 @@ static int __init __area_sdram_check(struct pci_channel *chan, | |||
44 | return 1; | 44 | return 1; |
45 | } | 45 | } |
46 | 46 | ||
47 | static struct resource sh7751_io_resource = { | 47 | static struct resource sh7751_pci_resources[] = { |
48 | .name = "SH7751_IO", | 48 | { |
49 | .start = SH7751_PCI_IO_BASE, | 49 | .name = "SH7751_IO", |
50 | .end = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1, | 50 | .start = SH7751_PCI_IO_BASE, |
51 | .flags = IORESOURCE_IO | 51 | .end = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1, |
52 | }; | 52 | .flags = IORESOURCE_IO |
53 | 53 | }, { | |
54 | static struct resource sh7751_mem_resource = { | 54 | .name = "SH7751_mem", |
55 | .name = "SH7751_mem", | 55 | .start = SH7751_PCI_MEMORY_BASE, |
56 | .start = SH7751_PCI_MEMORY_BASE, | 56 | .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1, |
57 | .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1, | 57 | .flags = IORESOURCE_MEM |
58 | .flags = IORESOURCE_MEM | 58 | }, |
59 | }; | 59 | }; |
60 | 60 | ||
61 | static struct pci_channel sh7751_pci_controller = { | 61 | static struct pci_channel sh7751_pci_controller = { |
62 | .pci_ops = &sh4_pci_ops, | 62 | .pci_ops = &sh4_pci_ops, |
63 | .mem_resource = &sh7751_mem_resource, | 63 | .resources = sh7751_pci_resources, |
64 | .nr_resources = ARRAY_SIZE(sh7751_pci_resources), | ||
64 | .mem_offset = 0x00000000, | 65 | .mem_offset = 0x00000000, |
65 | .io_resource = &sh7751_io_resource, | ||
66 | .io_offset = 0x00000000, | 66 | .io_offset = 0x00000000, |
67 | .io_map_base = SH7751_PCI_IO_BASE, | 67 | .io_map_base = SH7751_PCI_IO_BASE, |
68 | }; | 68 | }; |
@@ -128,13 +128,13 @@ static int __init sh7751_pci_init(void) | |||
128 | /* Set the local 16MB PCI memory space window to | 128 | /* Set the local 16MB PCI memory space window to |
129 | * the lowest PCI mapped address | 129 | * the lowest PCI mapped address |
130 | */ | 130 | */ |
131 | word = chan->mem_resource->start & SH4_PCIMBR_MASK; | 131 | word = chan->resources[1].start & SH4_PCIMBR_MASK; |
132 | pr_debug("PCI: Setting upper bits of Memory window to 0x%x\n", word); | 132 | pr_debug("PCI: Setting upper bits of Memory window to 0x%x\n", word); |
133 | pci_write_reg(chan, word , SH4_PCIMBR); | 133 | pci_write_reg(chan, word , SH4_PCIMBR); |
134 | 134 | ||
135 | /* Make sure the MSB's of IO window are set to access PCI space | 135 | /* Make sure the MSB's of IO window are set to access PCI space |
136 | * correctly */ | 136 | * correctly */ |
137 | word = chan->io_resource->start & SH4_PCIIOBR_MASK; | 137 | word = chan->resources[0].start & SH4_PCIIOBR_MASK; |
138 | pr_debug("PCI: Setting upper bits of IO window to 0x%x\n", word); | 138 | pr_debug("PCI: Setting upper bits of IO window to 0x%x\n", word); |
139 | pci_write_reg(chan, word, SH4_PCIIOBR); | 139 | pci_write_reg(chan, word, SH4_PCIIOBR); |
140 | 140 | ||
diff --git a/arch/sh/drivers/pci/pci-sh7780.c b/arch/sh/drivers/pci/pci-sh7780.c index 86373314f458..472f67aec337 100644 --- a/arch/sh/drivers/pci/pci-sh7780.c +++ b/arch/sh/drivers/pci/pci-sh7780.c | |||
@@ -21,27 +21,40 @@ | |||
21 | #include <asm/mmu.h> | 21 | #include <asm/mmu.h> |
22 | #include <asm/sizes.h> | 22 | #include <asm/sizes.h> |
23 | 23 | ||
24 | static struct resource sh7785_io_resource = { | 24 | static struct resource sh7785_pci_resources[] = { |
25 | .name = "SH7785_IO", | 25 | { |
26 | .start = 0x1000, | 26 | .name = "SH7785_IO", |
27 | .end = SH7780_PCI_IO_SIZE - 1, | 27 | .start = 0x1000, |
28 | .flags = IORESOURCE_IO | 28 | .end = SZ_4M - 1, |
29 | }; | 29 | .flags = IORESOURCE_IO, |
30 | 30 | }, { | |
31 | static struct resource sh7785_mem_resource = { | 31 | .name = "PCI MEM 0", |
32 | .name = "SH7785_mem", | 32 | .start = 0xfd000000, |
33 | .start = SH7780_PCI_MEMORY_BASE, | 33 | .end = 0xfd000000 + SZ_16M - 1, |
34 | .end = SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1, | 34 | .flags = IORESOURCE_MEM, |
35 | .flags = IORESOURCE_MEM | 35 | }, { |
36 | .name = "PCI MEM 1", | ||
37 | .start = 0x10000000, | ||
38 | .end = 0x10000000 + SZ_64M - 1, | ||
39 | .flags = IORESOURCE_MEM, | ||
40 | }, { | ||
41 | /* | ||
42 | * 32-bit only resources must be last. | ||
43 | */ | ||
44 | .name = "PCI MEM 2", | ||
45 | .start = 0xc0000000, | ||
46 | .end = 0xc0000000 + SZ_512M - 1, | ||
47 | .flags = IORESOURCE_MEM | IORESOURCE_MEM_32BIT, | ||
48 | }, | ||
36 | }; | 49 | }; |
37 | 50 | ||
38 | static struct pci_channel sh7780_pci_controller = { | 51 | static struct pci_channel sh7780_pci_controller = { |
39 | .pci_ops = &sh4_pci_ops, | 52 | .pci_ops = &sh4_pci_ops, |
40 | .mem_resource = &sh7785_mem_resource, | 53 | .resources = sh7785_pci_resources, |
41 | .mem_offset = 0x00000000, | 54 | .nr_resources = ARRAY_SIZE(sh7785_pci_resources), |
42 | .io_resource = &sh7785_io_resource, | 55 | .io_offset = 0, |
43 | .io_offset = 0x00000000, | 56 | .mem_offset = 0, |
44 | .io_map_base = SH7780_PCI_IO_BASE, | 57 | .io_map_base = 0xfe200000, |
45 | .serr_irq = evt2irq(0xa00), | 58 | .serr_irq = evt2irq(0xa00), |
46 | .err_irq = evt2irq(0xaa0), | 59 | .err_irq = evt2irq(0xaa0), |
47 | }; | 60 | }; |
@@ -231,7 +244,7 @@ static int __init sh7780_pci_init(void) | |||
231 | size_t memsize; | 244 | size_t memsize; |
232 | unsigned int id; | 245 | unsigned int id; |
233 | const char *type; | 246 | const char *type; |
234 | int ret; | 247 | int ret, i; |
235 | 248 | ||
236 | printk(KERN_NOTICE "PCI: Starting intialization.\n"); | 249 | printk(KERN_NOTICE "PCI: Starting intialization.\n"); |
237 | 250 | ||
@@ -279,8 +292,6 @@ static int __init sh7780_pci_init(void) | |||
279 | */ | 292 | */ |
280 | __raw_writel(SH4_PCICR_PREFIX, chan->reg_base + SH4_PCICR); | 293 | __raw_writel(SH4_PCICR_PREFIX, chan->reg_base + SH4_PCICR); |
281 | 294 | ||
282 | __raw_writel(0, chan->reg_base + PCI_BASE_ADDRESS_0); | ||
283 | |||
284 | memphys = __pa(memory_start); | 295 | memphys = __pa(memory_start); |
285 | memsize = roundup_pow_of_two(memory_end - memory_start); | 296 | memsize = roundup_pow_of_two(memory_end - memory_start); |
286 | 297 | ||
@@ -324,9 +335,40 @@ static int __init sh7780_pci_init(void) | |||
324 | __raw_writel(0, chan->reg_base + SH7780_PCICSCR1); | 335 | __raw_writel(0, chan->reg_base + SH7780_PCICSCR1); |
325 | __raw_writel(0, chan->reg_base + SH7780_PCICSAR1); | 336 | __raw_writel(0, chan->reg_base + SH7780_PCICSAR1); |
326 | 337 | ||
327 | __raw_writel(0xfd000000, chan->reg_base + SH7780_PCIMBR0); | 338 | /* |
328 | __raw_writel(0x00fc0000, chan->reg_base + SH7780_PCIMBMR0); | 339 | * Setup the memory BARs |
340 | */ | ||
341 | for (i = 0; i < chan->nr_resources; i++) { | ||
342 | struct resource *res = chan->resources + (i + 1); | ||
343 | resource_size_t size; | ||
344 | |||
345 | if (unlikely(res->flags & IORESOURCE_IO)) | ||
346 | continue; | ||
347 | |||
348 | /* | ||
349 | * Make sure we're in the right physical addressing mode | ||
350 | * for dealing with the resource. | ||
351 | */ | ||
352 | if ((res->flags & IORESOURCE_MEM_32BIT) && __in_29bit_mode()) { | ||
353 | chan->nr_resources--; | ||
354 | continue; | ||
355 | } | ||
329 | 356 | ||
357 | size = resource_size(res); | ||
358 | |||
359 | /* | ||
360 | * The MBMR mask is calculated in units of 256kB, which | ||
361 | * keeps things pretty simple. | ||
362 | */ | ||
363 | __raw_writel(((roundup_pow_of_two(size) / SZ_256K) - 1) << 18, | ||
364 | chan->reg_base + SH7780_PCIMBMR(i)); | ||
365 | __raw_writel(res->start, chan->reg_base + SH7780_PCIMBR(i)); | ||
366 | } | ||
367 | |||
368 | /* | ||
369 | * And I/O. | ||
370 | */ | ||
371 | __raw_writel(0, chan->reg_base + PCI_BASE_ADDRESS_0); | ||
330 | __raw_writel(0, chan->reg_base + SH7780_PCIIOBR); | 372 | __raw_writel(0, chan->reg_base + SH7780_PCIIOBR); |
331 | __raw_writel(0, chan->reg_base + SH7780_PCIIOBMR); | 373 | __raw_writel(0, chan->reg_base + SH7780_PCIIOBMR); |
332 | 374 | ||
diff --git a/arch/sh/drivers/pci/pci-sh7780.h b/arch/sh/drivers/pci/pci-sh7780.h index dee069c3865d..205dcbefe275 100644 --- a/arch/sh/drivers/pci/pci-sh7780.h +++ b/arch/sh/drivers/pci/pci-sh7780.h | |||
@@ -26,12 +26,6 @@ | |||
26 | #define SH7780_PCI_CONFIG_BASE 0xFD000000 /* Config space base addr */ | 26 | #define SH7780_PCI_CONFIG_BASE 0xFD000000 /* Config space base addr */ |
27 | #define SH7780_PCI_CONFIG_SIZE 0x01000000 /* Config space size */ | 27 | #define SH7780_PCI_CONFIG_SIZE 0x01000000 /* Config space size */ |
28 | 28 | ||
29 | #define SH7780_PCI_MEMORY_BASE 0xFD000000 /* Memory space base addr */ | ||
30 | #define SH7780_PCI_MEM_SIZE 0x01000000 /* Size of Memory window */ | ||
31 | |||
32 | #define SH7780_PCI_IO_BASE 0xFE200000 /* IO space base address */ | ||
33 | #define SH7780_PCI_IO_SIZE 0x00400000 /* Size of IO window */ | ||
34 | |||
35 | #define SH7780_PCIREG_BASE 0xFE040000 /* PCI regs base address */ | 29 | #define SH7780_PCIREG_BASE 0xFE040000 /* PCI regs base address */ |
36 | 30 | ||
37 | /* SH7780 PCI Config Registers */ | 31 | /* SH7780 PCI Config Registers */ |
@@ -46,12 +40,8 @@ | |||
46 | #define SH7780_PCIPINT 0x1CC /* Power Mgmnt Int. Register */ | 40 | #define SH7780_PCIPINT 0x1CC /* Power Mgmnt Int. Register */ |
47 | #define SH7780_PCIPINTM 0x1D0 /* Power Mgmnt Mask Register */ | 41 | #define SH7780_PCIPINTM 0x1D0 /* Power Mgmnt Mask Register */ |
48 | 42 | ||
49 | #define SH7780_PCIMBR0 0x1E0 | 43 | #define SH7780_PCIMBR(x) (0x1E0 + ((x) * 8)) |
50 | #define SH7780_PCIMBMR0 0x1E4 | 44 | #define SH7780_PCIMBMR(x) (0x1E4 + ((x) * 8)) |
51 | #define SH7780_PCIMBR1 0x1E8 | ||
52 | #define SH7780_PCIMBMR1 0x1EC | ||
53 | #define SH7780_PCIMBR2 0x1F0 | ||
54 | #define SH7780_PCIMBMR2 0x1F4 | ||
55 | #define SH7780_PCIIOBR 0x1F8 | 45 | #define SH7780_PCIIOBR 0x1F8 |
56 | #define SH7780_PCIIOBMR 0x1FC | 46 | #define SH7780_PCIIOBMR 0x1FC |
57 | #define SH7780_PCICSCR0 0x210 /* Cache Snoop1 Cnt. Register */ | 47 | #define SH7780_PCICSCR0 0x210 /* Cache Snoop1 Cnt. Register */ |
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index 8e42dfbbe76a..f4a69833fce2 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c | |||
@@ -60,11 +60,18 @@ static DEFINE_MUTEX(pci_scan_mutex); | |||
60 | 60 | ||
61 | int __devinit register_pci_controller(struct pci_channel *hose) | 61 | int __devinit register_pci_controller(struct pci_channel *hose) |
62 | { | 62 | { |
63 | if (request_resource(&iomem_resource, hose->mem_resource) < 0) | 63 | int i; |
64 | goto out; | 64 | |
65 | if (request_resource(&ioport_resource, hose->io_resource) < 0) { | 65 | for (i = 0; i < hose->nr_resources; i++) { |
66 | release_resource(hose->mem_resource); | 66 | struct resource *res = hose->resources + i; |
67 | goto out; | 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 | } | ||
68 | } | 75 | } |
69 | 76 | ||
70 | *hose_tail = hose; | 77 | *hose_tail = hose; |
@@ -96,6 +103,9 @@ int __devinit register_pci_controller(struct pci_channel *hose) | |||
96 | return 0; | 103 | return 0; |
97 | 104 | ||
98 | out: | 105 | out: |
106 | for (--i; i >= 0; i--) | ||
107 | release_resource(&hose->resources[i]); | ||
108 | |||
99 | printk(KERN_WARNING "Skipping PCI bus scan due to resource conflict\n"); | 109 | printk(KERN_WARNING "Skipping PCI bus scan due to resource conflict\n"); |
100 | return -1; | 110 | return -1; |
101 | } | 111 | } |
@@ -149,11 +159,13 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) | |||
149 | { | 159 | { |
150 | struct pci_dev *dev = bus->self; | 160 | struct pci_dev *dev = bus->self; |
151 | struct list_head *ln; | 161 | struct list_head *ln; |
152 | struct pci_channel *chan = bus->sysdata; | 162 | struct pci_channel *hose = bus->sysdata; |
153 | 163 | ||
154 | if (!dev) { | 164 | if (!dev) { |
155 | bus->resource[0] = chan->io_resource; | 165 | int i; |
156 | bus->resource[1] = chan->mem_resource; | 166 | |
167 | for (i = 0; i < hose->nr_resources; i++) | ||
168 | bus->resource[i] = hose->resources + i; | ||
157 | } | 169 | } |
158 | 170 | ||
159 | for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) { | 171 | for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) { |
@@ -174,21 +186,18 @@ void pcibios_align_resource(void *data, struct resource *res, | |||
174 | resource_size_t size, resource_size_t align) | 186 | resource_size_t size, resource_size_t align) |
175 | { | 187 | { |
176 | struct pci_dev *dev = data; | 188 | struct pci_dev *dev = data; |
177 | struct pci_channel *chan = dev->sysdata; | 189 | struct pci_channel *hose = dev->sysdata; |
178 | resource_size_t start = res->start; | 190 | resource_size_t start = res->start; |
179 | 191 | ||
180 | if (res->flags & IORESOURCE_IO) { | 192 | if (res->flags & IORESOURCE_IO) { |
181 | if (start < PCIBIOS_MIN_IO + chan->io_resource->start) | 193 | if (start < PCIBIOS_MIN_IO + hose->resources[0].start) |
182 | start = PCIBIOS_MIN_IO + chan->io_resource->start; | 194 | start = PCIBIOS_MIN_IO + hose->resources[0].start; |
183 | 195 | ||
184 | /* | 196 | /* |
185 | * Put everything into 0x00-0xff region modulo 0x400. | 197 | * Put everything into 0x00-0xff region modulo 0x400. |
186 | */ | 198 | */ |
187 | if (start & 0x300) | 199 | if (start & 0x300) |
188 | start = (start + 0x3ff) & ~0x3ff; | 200 | start = (start + 0x3ff) & ~0x3ff; |
189 | } else if (res->flags & IORESOURCE_MEM) { | ||
190 | if (start < PCIBIOS_MIN_MEM + chan->mem_resource->start) | ||
191 | start = PCIBIOS_MIN_MEM + chan->mem_resource->start; | ||
192 | } | 201 | } |
193 | 202 | ||
194 | res->start = start; | 203 | res->start = start; |
diff --git a/arch/sh/include/asm/pci.h b/arch/sh/include/asm/pci.h index 1de83f2161f7..6d762cca2312 100644 --- a/arch/sh/include/asm/pci.h +++ b/arch/sh/include/asm/pci.h | |||
@@ -18,8 +18,9 @@ struct pci_channel { | |||
18 | struct pci_bus *bus; | 18 | struct pci_bus *bus; |
19 | 19 | ||
20 | struct pci_ops *pci_ops; | 20 | struct pci_ops *pci_ops; |
21 | struct resource *io_resource; | 21 | |
22 | struct resource *mem_resource; | 22 | struct resource *resources; |
23 | unsigned int nr_resources; | ||
23 | 24 | ||
24 | unsigned long io_offset; | 25 | unsigned long io_offset; |
25 | unsigned long mem_offset; | 26 | unsigned long mem_offset; |