1 /* 2 * MPC85xx DS Board Setup 3 * 4 * Author Xianghua Xiao (x.xiao@freescale.com) 5 * Roy Zang <tie-fei.zang@freescale.com> 6 * - Add PCI/PCI Exprees support 7 * Copyright 2007 Freescale Semiconductor Inc. 8 * 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License as published by the 11 * Free Software Foundation; either version 2 of the License, or (at your 12 * option) any later version. 13 */ 14 15 #include <linux/stddef.h> 16 #include <linux/kernel.h> 17 #include <linux/pci.h> 18 #include <linux/kdev_t.h> 19 #include <linux/delay.h> 20 #include <linux/seq_file.h> 21 #include <linux/interrupt.h> 22 #include <linux/of_platform.h> 23 #include <linux/lmb.h> 24 25 #include <asm/system.h> 26 #include <asm/time.h> 27 #include <asm/machdep.h> 28 #include <asm/pci-bridge.h> 29 #include <mm/mmu_decl.h> 30 #include <asm/prom.h> 31 #include <asm/udbg.h> 32 #include <asm/mpic.h> 33 #include <asm/i8259.h> 34 #include <asm/swiotlb.h> 35 36 #include <sysdev/fsl_soc.h> 37 #include <sysdev/fsl_pci.h> 38 39 #undef DEBUG 40 41 #ifdef DEBUG 42 #define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args) 43 #else 44 #define DBG(fmt, args...) 45 #endif 46 47 #ifdef CONFIG_PPC_I8259 48 static void mpc85xx_8259_cascade(unsigned int irq, struct irq_desc *desc) 49 { 50 unsigned int cascade_irq = i8259_irq(); 51 52 if (cascade_irq != NO_IRQ) { 53 generic_handle_irq(cascade_irq); 54 } 55 desc->chip->eoi(irq); 56 } 57 #endif /* CONFIG_PPC_I8259 */ 58 59 void __init mpc85xx_ds_pic_init(void) 60 { 61 struct mpic *mpic; 62 struct resource r; 63 struct device_node *np; 64 #ifdef CONFIG_PPC_I8259 65 struct device_node *cascade_node = NULL; 66 int cascade_irq; 67 #endif 68 unsigned long root = of_get_flat_dt_root(); 69 70 np = of_find_node_by_type(NULL, "open-pic"); 71 if (np == NULL) { 72 printk(KERN_ERR "Could not find open-pic node\n"); 73 return; 74 } 75 76 if (of_address_to_resource(np, 0, &r)) { 77 printk(KERN_ERR "Failed to map mpic register space\n"); 78 of_node_put(np); 79 return; 80 } 81 82 if (of_flat_dt_is_compatible(root, "fsl,MPC8572DS-CAMP")) { 83 mpic = mpic_alloc(np, r.start, 84 MPIC_PRIMARY | 85 MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS, 86 0, 256, " OpenPIC "); 87 } else { 88 mpic = mpic_alloc(np, r.start, 89 MPIC_PRIMARY | MPIC_WANTS_RESET | 90 MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS | 91 MPIC_SINGLE_DEST_CPU, 92 0, 256, " OpenPIC "); 93 } 94 95 BUG_ON(mpic == NULL); 96 of_node_put(np); 97 98 mpic_init(mpic); 99 100 #ifdef CONFIG_PPC_I8259 101 /* Initialize the i8259 controller */ 102 for_each_node_by_type(np, "interrupt-controller") 103 if (of_device_is_compatible(np, "chrp,iic")) { 104 cascade_node = np; 105 break; 106 } 107 108 if (cascade_node == NULL) { 109 printk(KERN_DEBUG "Could not find i8259 PIC\n"); 110 return; 111 } 112 113 cascade_irq = irq_of_parse_and_map(cascade_node, 0); 114 if (cascade_irq == NO_IRQ) { 115 printk(KERN_ERR "Failed to map cascade interrupt\n"); 116 return; 117 } 118 119 DBG("mpc85xxds: cascade mapped to irq %d\n", cascade_irq); 120 121 i8259_init(cascade_node, 0); 122 of_node_put(cascade_node); 123 124 set_irq_chained_handler(cascade_irq, mpc85xx_8259_cascade); 125 #endif /* CONFIG_PPC_I8259 */ 126 } 127 128 #ifdef CONFIG_PCI 129 static int primary_phb_addr; 130 extern int uli_exclude_device(struct pci_controller *hose, 131 u_char bus, u_char devfn); 132 133 static int mpc85xx_exclude_device(struct pci_controller *hose, 134 u_char bus, u_char devfn) 135 { 136 struct device_node* node; 137 struct resource rsrc; 138 139 node = hose->dn; 140 of_address_to_resource(node, 0, &rsrc); 141 142 if ((rsrc.start & 0xfffff) == primary_phb_addr) { 143 return uli_exclude_device(hose, bus, devfn); 144 } 145 146 return PCIBIOS_SUCCESSFUL; 147 } 148 #endif /* CONFIG_PCI */ 149 150 /* 151 * Setup the architecture 152 */ 153 #ifdef CONFIG_SMP 154 extern void __init mpc85xx_smp_init(void); 155 #endif 156 static void __init mpc85xx_ds_setup_arch(void) 157 { 158 #ifdef CONFIG_PCI 159 struct device_node *np; 160 struct pci_controller *hose; 161 #endif 162 dma_addr_t max = 0xffffffff; 163 164 if (ppc_md.progress) 165 ppc_md.progress("mpc85xx_ds_setup_arch()", 0); 166 167 #ifdef CONFIG_PCI 168 for_each_node_by_type(np, "pci") { 169 if (of_device_is_compatible(np, "fsl,mpc8540-pci") || 170 of_device_is_compatible(np, "fsl,mpc8548-pcie") || 171 of_device_is_compatible(np, "fsl,p2020-pcie")) { 172 struct resource rsrc; 173 of_address_to_resource(np, 0, &rsrc); 174 if ((rsrc.start & 0xfffff) == primary_phb_addr) 175 fsl_add_bridge(np, 1); 176 else 177 fsl_add_bridge(np, 0); 178 179 hose = pci_find_hose_for_OF_device(np); 180 max = min(max, hose->dma_window_base_cur + 181 hose->dma_window_size); 182 } 183 } 184 185 ppc_md.pci_exclude_device = mpc85xx_exclude_device; 186 #endif 187 188 #ifdef CONFIG_SMP 189 mpc85xx_smp_init(); 190 #endif 191 192 #ifdef CONFIG_SWIOTLB 193 if (lmb_end_of_DRAM() > max) { 194 ppc_swiotlb_enable = 1; 195 set_pci_dma_ops(&swiotlb_dma_ops); 196 ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb; 197 } 198 #endif 199 200 printk("MPC85xx DS board from Freescale Semiconductor\n"); 201 } 202 203 /* 204 * Called very early, device-tree isn't unflattened 205 */ 206 static int __init mpc8544_ds_probe(void) 207 { 208 unsigned long root = of_get_flat_dt_root(); 209 210 if (of_flat_dt_is_compatible(root, "MPC8544DS")) { 211 #ifdef CONFIG_PCI 212 primary_phb_addr = 0xb000; 213 #endif 214 return 1; 215 } 216 217 return 0; 218 } 219 220 static struct of_device_id __initdata mpc85xxds_ids[] = { 221 { .type = "soc", }, 222 { .compatible = "soc", }, 223 { .compatible = "simple-bus", }, 224 { .compatible = "gianfar", }, 225 {}, 226 }; 227 228 static int __init mpc85xxds_publish_devices(void) 229 { 230 return of_platform_bus_probe(NULL, mpc85xxds_ids, NULL); 231 } 232 machine_device_initcall(mpc8544_ds, mpc85xxds_publish_devices); 233 machine_device_initcall(mpc8572_ds, mpc85xxds_publish_devices); 234 machine_device_initcall(p2020_ds, mpc85xxds_publish_devices); 235 236 machine_arch_initcall(mpc8544_ds, swiotlb_setup_bus_notifier); 237 machine_arch_initcall(mpc8572_ds, swiotlb_setup_bus_notifier); 238 machine_arch_initcall(p2020_ds, swiotlb_setup_bus_notifier); 239 240 /* 241 * Called very early, device-tree isn't unflattened 242 */ 243 static int __init mpc8572_ds_probe(void) 244 { 245 unsigned long root = of_get_flat_dt_root(); 246 247 if (of_flat_dt_is_compatible(root, "fsl,MPC8572DS")) { 248 #ifdef CONFIG_PCI 249 primary_phb_addr = 0x8000; 250 #endif 251 return 1; 252 } 253 254 return 0; 255 } 256 257 /* 258 * Called very early, device-tree isn't unflattened 259 */ 260 static int __init p2020_ds_probe(void) 261 { 262 unsigned long root = of_get_flat_dt_root(); 263 264 if (of_flat_dt_is_compatible(root, "fsl,P2020DS")) { 265 #ifdef CONFIG_PCI 266 primary_phb_addr = 0x9000; 267 #endif 268 return 1; 269 } 270 271 return 0; 272 } 273 274 define_machine(mpc8544_ds) { 275 .name = "MPC8544 DS", 276 .probe = mpc8544_ds_probe, 277 .setup_arch = mpc85xx_ds_setup_arch, 278 .init_IRQ = mpc85xx_ds_pic_init, 279 #ifdef CONFIG_PCI 280 .pcibios_fixup_bus = fsl_pcibios_fixup_bus, 281 #endif 282 .get_irq = mpic_get_irq, 283 .restart = fsl_rstcr_restart, 284 .calibrate_decr = generic_calibrate_decr, 285 .progress = udbg_progress, 286 }; 287 288 define_machine(mpc8572_ds) { 289 .name = "MPC8572 DS", 290 .probe = mpc8572_ds_probe, 291 .setup_arch = mpc85xx_ds_setup_arch, 292 .init_IRQ = mpc85xx_ds_pic_init, 293 #ifdef CONFIG_PCI 294 .pcibios_fixup_bus = fsl_pcibios_fixup_bus, 295 #endif 296 .get_irq = mpic_get_irq, 297 .restart = fsl_rstcr_restart, 298 .calibrate_decr = generic_calibrate_decr, 299 .progress = udbg_progress, 300 }; 301 302 define_machine(p2020_ds) { 303 .name = "P2020 DS", 304 .probe = p2020_ds_probe, 305 .setup_arch = mpc85xx_ds_setup_arch, 306 .init_IRQ = mpc85xx_ds_pic_init, 307 #ifdef CONFIG_PCI 308 .pcibios_fixup_bus = fsl_pcibios_fixup_bus, 309 #endif 310 .get_irq = mpic_get_irq, 311 .restart = fsl_rstcr_restart, 312 .calibrate_decr = generic_calibrate_decr, 313 .progress = udbg_progress, 314 }; 315