diff options
Diffstat (limited to 'arch/arm/mach-ixp2000/ixdp2800.c')
-rw-r--r-- | arch/arm/mach-ixp2000/ixdp2800.c | 147 |
1 files changed, 134 insertions, 13 deletions
diff --git a/arch/arm/mach-ixp2000/ixdp2800.c b/arch/arm/mach-ixp2000/ixdp2800.c index c4683aaff84a..aec13c7108a9 100644 --- a/arch/arm/mach-ixp2000/ixdp2800.c +++ b/arch/arm/mach-ixp2000/ixdp2800.c | |||
@@ -65,19 +65,102 @@ static struct sys_timer ixdp2800_timer = { | |||
65 | /************************************************************************* | 65 | /************************************************************************* |
66 | * IXDP2800 PCI | 66 | * IXDP2800 PCI |
67 | *************************************************************************/ | 67 | *************************************************************************/ |
68 | static void __init ixdp2800_slave_disable_pci_master(void) | ||
69 | { | ||
70 | *IXP2000_PCI_CMDSTAT &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); | ||
71 | } | ||
72 | |||
73 | static void __init ixdp2800_master_wait_for_slave(void) | ||
74 | { | ||
75 | volatile u32 *addr; | ||
76 | |||
77 | printk(KERN_INFO "IXDP2800: waiting for slave NPU to configure " | ||
78 | "its BAR sizes\n"); | ||
79 | |||
80 | addr = ixp2000_pci_config_addr(0, IXDP2X00_SLAVE_NPU_DEVFN, | ||
81 | PCI_BASE_ADDRESS_1); | ||
82 | do { | ||
83 | *addr = 0xffffffff; | ||
84 | cpu_relax(); | ||
85 | } while (*addr != 0xfe000008); | ||
86 | |||
87 | addr = ixp2000_pci_config_addr(0, IXDP2X00_SLAVE_NPU_DEVFN, | ||
88 | PCI_BASE_ADDRESS_2); | ||
89 | do { | ||
90 | *addr = 0xffffffff; | ||
91 | cpu_relax(); | ||
92 | } while (*addr != 0xc0000008); | ||
93 | |||
94 | /* | ||
95 | * Configure the slave's SDRAM BAR by hand. | ||
96 | */ | ||
97 | *addr = 0x40000008; | ||
98 | } | ||
99 | |||
100 | static void __init ixdp2800_slave_wait_for_master_enable(void) | ||
101 | { | ||
102 | printk(KERN_INFO "IXDP2800: waiting for master NPU to enable us\n"); | ||
103 | |||
104 | while ((*IXP2000_PCI_CMDSTAT & PCI_COMMAND_MASTER) == 0) | ||
105 | cpu_relax(); | ||
106 | } | ||
107 | |||
68 | void __init ixdp2800_pci_preinit(void) | 108 | void __init ixdp2800_pci_preinit(void) |
69 | { | 109 | { |
70 | printk("ixdp2x00_pci_preinit called\n"); | 110 | printk("ixdp2x00_pci_preinit called\n"); |
71 | 111 | ||
72 | *IXP2000_PCI_ADDR_EXT = 0x0000e000; | 112 | *IXP2000_PCI_ADDR_EXT = 0x0001e000; |
113 | |||
114 | if (!ixdp2x00_master_npu()) | ||
115 | ixdp2800_slave_disable_pci_master(); | ||
73 | 116 | ||
74 | *IXP2000_PCI_DRAM_BASE_ADDR_MASK = (0x40000000 - 1) & ~0xfffff; | ||
75 | *IXP2000_PCI_SRAM_BASE_ADDR_MASK = (0x2000000 - 1) & ~0x3ffff; | 117 | *IXP2000_PCI_SRAM_BASE_ADDR_MASK = (0x2000000 - 1) & ~0x3ffff; |
118 | *IXP2000_PCI_DRAM_BASE_ADDR_MASK = (0x40000000 - 1) & ~0xfffff; | ||
76 | 119 | ||
77 | ixp2000_pci_preinit(); | 120 | ixp2000_pci_preinit(); |
121 | |||
122 | if (ixdp2x00_master_npu()) { | ||
123 | /* | ||
124 | * Wait until the slave set its SRAM/SDRAM BAR sizes | ||
125 | * correctly before we proceed to scan and enumerate | ||
126 | * the bus. | ||
127 | */ | ||
128 | ixdp2800_master_wait_for_slave(); | ||
129 | |||
130 | /* | ||
131 | * We configure the SDRAM BARs by hand because they | ||
132 | * are 1G and fall outside of the regular allocated | ||
133 | * PCI address space. | ||
134 | */ | ||
135 | *IXP2000_PCI_SDRAM_BAR = 0x00000008; | ||
136 | } else { | ||
137 | /* | ||
138 | * Wait for the master to complete scanning the bus | ||
139 | * and assigning resources before we proceed to scan | ||
140 | * the bus ourselves. Set pci=firmware to honor the | ||
141 | * master's resource assignment. | ||
142 | */ | ||
143 | ixdp2800_slave_wait_for_master_enable(); | ||
144 | pcibios_setup("firmware"); | ||
145 | } | ||
78 | } | 146 | } |
79 | 147 | ||
80 | int ixdp2800_pci_setup(int nr, struct pci_sys_data *sys) | 148 | /* |
149 | * We assign the SDRAM BARs for the two IXP2800 CPUs by hand, outside | ||
150 | * of the regular PCI window, because there's only 512M of outbound PCI | ||
151 | * memory window on each IXP, while we need 1G for each of the BARs. | ||
152 | */ | ||
153 | static void __devinit ixp2800_pci_fixup(struct pci_dev *dev) | ||
154 | { | ||
155 | if (machine_is_ixdp2800()) { | ||
156 | dev->resource[2].start = 0; | ||
157 | dev->resource[2].end = 0; | ||
158 | dev->resource[2].flags = 0; | ||
159 | } | ||
160 | } | ||
161 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IXP2800, ixp2800_pci_fixup); | ||
162 | |||
163 | static int __init ixdp2800_pci_setup(int nr, struct pci_sys_data *sys) | ||
81 | { | 164 | { |
82 | sys->mem_offset = 0x00000000; | 165 | sys->mem_offset = 0x00000000; |
83 | 166 | ||
@@ -129,22 +212,47 @@ static int __init ixdp2800_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | |||
129 | } else return IRQ_IXP2000_PCIB; /* Slave NIC interrupt */ | 212 | } else return IRQ_IXP2000_PCIB; /* Slave NIC interrupt */ |
130 | } | 213 | } |
131 | 214 | ||
132 | static void ixdp2800_pci_postinit(void) | 215 | static void __init ixdp2800_master_enable_slave(void) |
133 | { | 216 | { |
134 | struct pci_dev *dev; | 217 | volatile u32 *addr; |
135 | 218 | ||
136 | if (ixdp2x00_master_npu()) { | 219 | printk(KERN_INFO "IXDP2800: enabling slave NPU\n"); |
137 | dev = pci_find_slot(1, IXDP2800_SLAVE_ENET_DEVFN); | 220 | |
138 | pci_remove_bus_device(dev); | 221 | addr = (volatile u32 *)ixp2000_pci_config_addr(0, |
139 | } else { | 222 | IXDP2X00_SLAVE_NPU_DEVFN, |
140 | dev = pci_find_slot(1, IXDP2800_MASTER_ENET_DEVFN); | 223 | PCI_COMMAND); |
141 | pci_remove_bus_device(dev); | 224 | |
225 | *addr |= PCI_COMMAND_MASTER; | ||
226 | } | ||
142 | 227 | ||
228 | static void __init ixdp2800_master_wait_for_slave_bus_scan(void) | ||
229 | { | ||
230 | volatile u32 *addr; | ||
231 | |||
232 | printk(KERN_INFO "IXDP2800: waiting for slave to finish bus scan\n"); | ||
233 | |||
234 | addr = (volatile u32 *)ixp2000_pci_config_addr(0, | ||
235 | IXDP2X00_SLAVE_NPU_DEVFN, | ||
236 | PCI_COMMAND); | ||
237 | while ((*addr & PCI_COMMAND_MEMORY) == 0) | ||
238 | cpu_relax(); | ||
239 | } | ||
240 | |||
241 | static void __init ixdp2800_slave_signal_bus_scan_completion(void) | ||
242 | { | ||
243 | printk(KERN_INFO "IXDP2800: bus scan done, signaling master\n"); | ||
244 | *IXP2000_PCI_CMDSTAT |= PCI_COMMAND_MEMORY; | ||
245 | } | ||
246 | |||
247 | static void __init ixdp2800_pci_postinit(void) | ||
248 | { | ||
249 | if (!ixdp2x00_master_npu()) { | ||
143 | ixdp2x00_slave_pci_postinit(); | 250 | ixdp2x00_slave_pci_postinit(); |
251 | ixdp2800_slave_signal_bus_scan_completion(); | ||
144 | } | 252 | } |
145 | } | 253 | } |
146 | 254 | ||
147 | struct hw_pci ixdp2800_pci __initdata = { | 255 | struct __initdata hw_pci ixdp2800_pci __initdata = { |
148 | .nr_controllers = 1, | 256 | .nr_controllers = 1, |
149 | .setup = ixdp2800_pci_setup, | 257 | .setup = ixdp2800_pci_setup, |
150 | .preinit = ixdp2800_pci_preinit, | 258 | .preinit = ixdp2800_pci_preinit, |
@@ -155,8 +263,21 @@ struct hw_pci ixdp2800_pci __initdata = { | |||
155 | 263 | ||
156 | int __init ixdp2800_pci_init(void) | 264 | int __init ixdp2800_pci_init(void) |
157 | { | 265 | { |
158 | if (machine_is_ixdp2800()) | 266 | if (machine_is_ixdp2800()) { |
267 | struct pci_dev *dev; | ||
268 | |||
159 | pci_common_init(&ixdp2800_pci); | 269 | pci_common_init(&ixdp2800_pci); |
270 | if (ixdp2x00_master_npu()) { | ||
271 | dev = pci_find_slot(1, IXDP2800_SLAVE_ENET_DEVFN); | ||
272 | pci_remove_bus_device(dev); | ||
273 | |||
274 | ixdp2800_master_enable_slave(); | ||
275 | ixdp2800_master_wait_for_slave_bus_scan(); | ||
276 | } else { | ||
277 | dev = pci_find_slot(1, IXDP2800_MASTER_ENET_DEVFN); | ||
278 | pci_remove_bus_device(dev); | ||
279 | } | ||
280 | } | ||
160 | 281 | ||
161 | return 0; | 282 | return 0; |
162 | } | 283 | } |