diff options
-rw-r--r-- | arch/sh/drivers/pci/pci-new.c | 97 | ||||
-rw-r--r-- | arch/sh/drivers/pci/pci-sh7780.c | 87 | ||||
-rw-r--r-- | arch/sh/include/asm/pci.h | 29 |
3 files changed, 130 insertions, 83 deletions
diff --git a/arch/sh/drivers/pci/pci-new.c b/arch/sh/drivers/pci/pci-new.c index c92e65045c68..78b7292c6aa8 100644 --- a/arch/sh/drivers/pci/pci-new.c +++ b/arch/sh/drivers/pci/pci-new.c | |||
@@ -13,40 +13,90 @@ | |||
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/dma-debug.h> | 14 | #include <linux/dma-debug.h> |
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <linux/mutex.h> | ||
16 | 17 | ||
17 | static int __init pcibios_init(void) | 18 | /* |
19 | * The PCI controller list. | ||
20 | */ | ||
21 | static struct pci_channel *hose_head, **hose_tail = &hose_head; | ||
22 | |||
23 | static int pci_initialized; | ||
24 | |||
25 | static void __devinit pcibios_scanbus(struct pci_channel *hose) | ||
18 | { | 26 | { |
19 | struct pci_channel *p; | 27 | static int next_busno; |
20 | struct pci_bus *bus; | 28 | struct pci_bus *bus; |
21 | int busno; | 29 | |
22 | 30 | /* Catch botched conversion attempts */ | |
23 | /* init channels */ | 31 | BUG_ON(hose->init); |
24 | busno = 0; | 32 | |
25 | for (p = board_pci_channels; p->init; p++) { | 33 | bus = pci_scan_bus(next_busno, hose->pci_ops, hose); |
26 | if (p->init(p) == 0) | 34 | if (bus) { |
27 | p->enabled = 1; | 35 | next_busno = bus->subordinate + 1; |
28 | else | 36 | /* Don't allow 8-bit bus number overflow inside the hose - |
29 | pr_err("Unable to init pci channel %d\n", busno); | 37 | reserve some space for bridges. */ |
30 | busno++; | 38 | if (next_busno > 224) |
39 | next_busno = 0; | ||
40 | |||
41 | pci_bus_size_bridges(bus); | ||
42 | pci_bus_assign_resources(bus); | ||
43 | pci_enable_bridges(bus); | ||
31 | } | 44 | } |
45 | } | ||
32 | 46 | ||
33 | /* scan the buses */ | 47 | static DEFINE_MUTEX(pci_scan_mutex); |
34 | busno = 0; | ||
35 | for (p = board_pci_channels; p->init; p++) { | ||
36 | if (p->enabled) { | ||
37 | bus = pci_scan_bus(busno, p->pci_ops, p); | ||
38 | busno = bus->subordinate + 1; | ||
39 | 48 | ||
40 | pci_bus_size_bridges(bus); | 49 | void __devinit register_pci_controller(struct pci_channel *hose) |
41 | pci_bus_assign_resources(bus); | 50 | { |
42 | pci_enable_bridges(bus); | 51 | if (request_resource(&iomem_resource, hose->mem_resource) < 0) |
43 | } | 52 | goto out; |
53 | if (request_resource(&ioport_resource, hose->io_resource) < 0) { | ||
54 | release_resource(hose->mem_resource); | ||
55 | goto out; | ||
56 | } | ||
57 | |||
58 | *hose_tail = hose; | ||
59 | hose_tail = &hose->next; | ||
60 | |||
61 | /* | ||
62 | * Do not panic here but later - this might hapen before console init. | ||
63 | */ | ||
64 | if (!hose->io_map_base) { | ||
65 | printk(KERN_WARNING | ||
66 | "registering PCI controller with io_map_base unset\n"); | ||
67 | } | ||
68 | |||
69 | /* | ||
70 | * Scan the bus if it is register after the PCI subsystem | ||
71 | * initialization. | ||
72 | */ | ||
73 | if (pci_initialized) { | ||
74 | mutex_lock(&pci_scan_mutex); | ||
75 | pcibios_scanbus(hose); | ||
76 | mutex_unlock(&pci_scan_mutex); | ||
44 | } | 77 | } |
45 | 78 | ||
79 | return; | ||
80 | |||
81 | out: | ||
82 | printk(KERN_WARNING | ||
83 | "Skipping PCI bus scan due to resource conflict\n"); | ||
84 | } | ||
85 | |||
86 | static int __init pcibios_init(void) | ||
87 | { | ||
88 | struct pci_channel *hose; | ||
89 | |||
90 | /* Scan all of the recorded PCI controllers. */ | ||
91 | for (hose = hose_head; hose; hose = hose->next) | ||
92 | pcibios_scanbus(hose); | ||
93 | |||
46 | pci_fixup_irqs(pci_common_swizzle, pcibios_map_platform_irq); | 94 | pci_fixup_irqs(pci_common_swizzle, pcibios_map_platform_irq); |
47 | 95 | ||
48 | dma_debug_add_bus(&pci_bus_type); | 96 | dma_debug_add_bus(&pci_bus_type); |
49 | 97 | ||
98 | pci_initialized = 1; | ||
99 | |||
50 | return 0; | 100 | return 0; |
51 | } | 101 | } |
52 | subsys_initcall(pcibios_init); | 102 | subsys_initcall(pcibios_init); |
@@ -74,7 +124,6 @@ static void pcibios_fixup_device_resources(struct pci_dev *dev, | |||
74 | } | 124 | } |
75 | } | 125 | } |
76 | 126 | ||
77 | |||
78 | /* | 127 | /* |
79 | * Called after each bus is probed, but before its children | 128 | * Called after each bus is probed, but before its children |
80 | * are examined. | 129 | * are examined. |
@@ -186,5 +235,3 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq) | |||
186 | { | 235 | { |
187 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); | 236 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); |
188 | } | 237 | } |
189 | |||
190 | EXPORT_SYMBOL(board_pci_channels); | ||
diff --git a/arch/sh/drivers/pci/pci-sh7780.c b/arch/sh/drivers/pci/pci-sh7780.c index f02d9dfcf252..4dd6e3b94a67 100644 --- a/arch/sh/drivers/pci/pci-sh7780.c +++ b/arch/sh/drivers/pci/pci-sh7780.c | |||
@@ -15,11 +15,47 @@ | |||
15 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
16 | #include "pci-sh4.h" | 16 | #include "pci-sh4.h" |
17 | 17 | ||
18 | static int __init sh7780_pci_init(struct pci_channel *chan) | 18 | extern u8 pci_cache_line_size; |
19 | |||
20 | static struct resource sh7785_io_resource = { | ||
21 | .name = "SH7785_IO", | ||
22 | .start = SH7780_PCI_IO_BASE, | ||
23 | .end = SH7780_PCI_IO_BASE + SH7780_PCI_IO_SIZE - 1, | ||
24 | .flags = IORESOURCE_IO | ||
25 | }; | ||
26 | |||
27 | static struct resource sh7785_mem_resource = { | ||
28 | .name = "SH7785_mem", | ||
29 | .start = SH7780_PCI_MEMORY_BASE, | ||
30 | .end = SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1, | ||
31 | .flags = IORESOURCE_MEM | ||
32 | }; | ||
33 | |||
34 | static struct pci_channel sh7780_pci_controller = { | ||
35 | .pci_ops = &sh4_pci_ops, | ||
36 | .mem_resource = &sh7785_mem_resource, | ||
37 | .io_resource = &sh7785_io_resource, | ||
38 | }; | ||
39 | |||
40 | static struct sh4_pci_address_map sh7780_pci_map = { | ||
41 | .window0 = { | ||
42 | #if defined(CONFIG_32BIT) | ||
43 | .base = SH7780_32BIT_DDR_BASE_ADDR, | ||
44 | .size = 0x40000000, | ||
45 | #else | ||
46 | .base = SH7780_CS0_BASE_ADDR, | ||
47 | .size = 0x20000000, | ||
48 | #endif | ||
49 | }, | ||
50 | }; | ||
51 | |||
52 | static int __init sh7780_pci_init(void) | ||
19 | { | 53 | { |
54 | struct pci_channel *chan = &sh7780_pci_controller; | ||
20 | unsigned int id; | 55 | unsigned int id; |
21 | const char *type = NULL; | 56 | const char *type = NULL; |
22 | int ret; | 57 | int ret; |
58 | u32 word; | ||
23 | 59 | ||
24 | printk(KERN_NOTICE "PCI: Starting intialization.\n"); | 60 | printk(KERN_NOTICE "PCI: Starting intialization.\n"); |
25 | 61 | ||
@@ -55,52 +91,6 @@ static int __init sh7780_pci_init(struct pci_channel *chan) | |||
55 | return ret; | 91 | return ret; |
56 | 92 | ||
57 | /* | 93 | /* |
58 | * Platform specific initialization (BSC registers, and memory space | ||
59 | * mapping) will be called via the platform defined function | ||
60 | * pcibios_init_platform(). | ||
61 | */ | ||
62 | return pcibios_init_platform(); | ||
63 | } | ||
64 | |||
65 | extern u8 pci_cache_line_size; | ||
66 | |||
67 | static struct resource sh7785_io_resource = { | ||
68 | .name = "SH7785_IO", | ||
69 | .start = SH7780_PCI_IO_BASE, | ||
70 | .end = SH7780_PCI_IO_BASE + SH7780_PCI_IO_SIZE - 1, | ||
71 | .flags = IORESOURCE_IO | ||
72 | }; | ||
73 | |||
74 | static struct resource sh7785_mem_resource = { | ||
75 | .name = "SH7785_mem", | ||
76 | .start = SH7780_PCI_MEMORY_BASE, | ||
77 | .end = SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1, | ||
78 | .flags = IORESOURCE_MEM | ||
79 | }; | ||
80 | |||
81 | struct pci_channel board_pci_channels[] = { | ||
82 | { sh7780_pci_init, &sh4_pci_ops, &sh7785_io_resource, &sh7785_mem_resource, 0, 0xff }, | ||
83 | { NULL, NULL, NULL, 0, 0 }, | ||
84 | }; | ||
85 | |||
86 | static struct sh4_pci_address_map sh7780_pci_map = { | ||
87 | .window0 = { | ||
88 | #if defined(CONFIG_32BIT) | ||
89 | .base = SH7780_32BIT_DDR_BASE_ADDR, | ||
90 | .size = 0x40000000, | ||
91 | #else | ||
92 | .base = SH7780_CS0_BASE_ADDR, | ||
93 | .size = 0x20000000, | ||
94 | #endif | ||
95 | }, | ||
96 | }; | ||
97 | |||
98 | int __init pcibios_init_platform(void) | ||
99 | { | ||
100 | struct pci_channel *chan = &board_pci_channels[0]; | ||
101 | u32 word; | ||
102 | |||
103 | /* | ||
104 | * Set the class and sub-class codes. | 94 | * Set the class and sub-class codes. |
105 | */ | 95 | */ |
106 | __raw_writeb(PCI_CLASS_BRIDGE_HOST >> 8, | 96 | __raw_writeb(PCI_CLASS_BRIDGE_HOST >> 8, |
@@ -153,5 +143,8 @@ int __init pcibios_init_platform(void) | |||
153 | 143 | ||
154 | __set_io_port_base(SH7780_PCI_IO_BASE); | 144 | __set_io_port_base(SH7780_PCI_IO_BASE); |
155 | 145 | ||
146 | register_pci_controller(chan); | ||
147 | |||
156 | return 0; | 148 | return 0; |
157 | } | 149 | } |
150 | arch_initcall(sh7780_pci_init); | ||
diff --git a/arch/sh/include/asm/pci.h b/arch/sh/include/asm/pci.h index 82a9369511b5..e057ebdb4618 100644 --- a/arch/sh/include/asm/pci.h +++ b/arch/sh/include/asm/pci.h | |||
@@ -17,17 +17,22 @@ | |||
17 | * external) PCI controllers. | 17 | * external) PCI controllers. |
18 | */ | 18 | */ |
19 | struct pci_channel { | 19 | struct pci_channel { |
20 | int (*init)(struct pci_channel *chan); | 20 | struct pci_channel *next; |
21 | struct pci_ops *pci_ops; | 21 | |
22 | struct resource *io_resource; | 22 | int (*init)(struct pci_channel *chan); |
23 | struct resource *mem_resource; | 23 | |
24 | int first_devfn; | 24 | struct pci_ops *pci_ops; |
25 | int last_devfn; | 25 | struct resource *io_resource; |
26 | int enabled; | 26 | struct resource *mem_resource; |
27 | unsigned long reg_base; | 27 | |
28 | unsigned long io_base; | 28 | int first_devfn; |
29 | 29 | int last_devfn; | |
30 | unsigned long io_map_base; | 30 | int enabled; |
31 | |||
32 | unsigned long reg_base; | ||
33 | unsigned long io_base; | ||
34 | |||
35 | unsigned long io_map_base; | ||
31 | }; | 36 | }; |
32 | 37 | ||
33 | /* | 38 | /* |
@@ -35,6 +40,8 @@ struct pci_channel { | |||
35 | */ | 40 | */ |
36 | extern struct pci_channel board_pci_channels[]; | 41 | extern struct pci_channel board_pci_channels[]; |
37 | 42 | ||
43 | extern void register_pci_controller(struct pci_channel *hose); | ||
44 | |||
38 | extern unsigned long PCIBIOS_MIN_IO, PCIBIOS_MIN_MEM; | 45 | extern unsigned long PCIBIOS_MIN_IO, PCIBIOS_MIN_MEM; |
39 | 46 | ||
40 | struct pci_dev; | 47 | struct pci_dev; |