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 | } |
