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/drivers/pci/pci-sh7780.c | |
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/drivers/pci/pci-sh7780.c')
-rw-r--r-- | arch/sh/drivers/pci/pci-sh7780.c | 86 |
1 files changed, 64 insertions, 22 deletions
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 | ||