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/memblock.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 struct irq_chip *chip = irq_desc_get_chip(desc); 51 unsigned int cascade_irq = i8259_irq(); 52 53 if (cascade_irq != NO_IRQ) { 54 generic_handle_irq(cascade_irq); 55 } 56 chip->irq_eoi(&desc->irq_data); 57 } 58 #endif /* CONFIG_PPC_I8259 */ 59 60 void __init mpc85xx_ds_pic_init(void) 61 { 62 struct mpic *mpic; 63 struct resource r; 64 struct device_node *np; 65 #ifdef CONFIG_PPC_I8259 66 struct device_node *cascade_node = NULL; 67 int cascade_irq; 68 #endif 69 unsigned long root = of_get_flat_dt_root(); 70 71 np = of_find_node_by_type(NULL, "open-pic"); 72 if (np == NULL) { 73 printk(KERN_ERR "Could not find open-pic node\n"); 74 return; 75 } 76 77 if (of_address_to_resource(np, 0, &r)) { 78 printk(KERN_ERR "Failed to map mpic register space\n"); 79 of_node_put(np); 80 return; 81 } 82 83 if (of_flat_dt_is_compatible(root, "fsl,MPC8572DS-CAMP")) { 84 mpic = mpic_alloc(np, r.start, 85 MPIC_PRIMARY | 86 MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS | 87 MPIC_SINGLE_DEST_CPU, 88 0, 256, " OpenPIC "); 89 } else { 90 mpic = mpic_alloc(np, r.start, 91 MPIC_PRIMARY | MPIC_WANTS_RESET | 92 MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS | 93 MPIC_SINGLE_DEST_CPU, 94 0, 256, " OpenPIC "); 95 } 96 97 BUG_ON(mpic == NULL); 98 of_node_put(np); 99 100 mpic_init(mpic); 101 102 #ifdef CONFIG_PPC_I8259 103 /* Initialize the i8259 controller */ 104 for_each_node_by_type(np, "interrupt-controller") 105 if (of_device_is_compatible(np, "chrp,iic")) { 106 cascade_node = np; 107 break; 108 } 109 110 if (cascade_node == NULL) { 111 printk(KERN_DEBUG "Could not find i8259 PIC\n"); 112 return; 113 } 114 115 cascade_irq = irq_of_parse_and_map(cascade_node, 0); 116 if (cascade_irq == NO_IRQ) { 117 printk(KERN_ERR "Failed to map cascade interrupt\n"); 118 return; 119 } 120 121 DBG("mpc85xxds: cascade mapped to irq %d\n", cascade_irq); 122 123 i8259_init(cascade_node, 0); 124 of_node_put(cascade_node); 125 126 irq_set_chained_handler(cascade_irq, mpc85xx_8259_cascade); 127 #endif /* CONFIG_PPC_I8259 */ 128 } 129 130 #ifdef CONFIG_PCI 131 static int primary_phb_addr; 132 extern int uli_exclude_device(struct pci_controller *hose, 133 u_char bus, u_char devfn); 134 135 static int mpc85xx_exclude_device(struct pci_controller *hose, 136 u_char bus, u_char devfn) 137 { 138 struct device_node* node; 139 struct resource rsrc; 140 141 node = hose->dn; 142 of_address_to_resource(node, 0, &rsrc); 143 144 if ((rsrc.start & 0xfffff) == primary_phb_addr) { 145 return uli_exclude_device(hose, bus, devfn); 146 } 147 148 return PCIBIOS_SUCCESSFUL; 149 } 150 #endif /* CONFIG_PCI */ 151 152 /* 153 * Setup the architecture 154 */ 155 #ifdef CONFIG_SMP 156 extern void __init mpc85xx_smp_init(void); 157 #endif 158 static void __init mpc85xx_ds_setup_arch(void) 159 { 160 #ifdef CONFIG_PCI 161 struct device_node *np; 162 struct pci_controller *hose; 163 #endif 164 dma_addr_t max = 0xffffffff; 165 166 if (ppc_md.progress) 167 ppc_md.progress("mpc85xx_ds_setup_arch()", 0); 168 169 #ifdef CONFIG_PCI 170 for_each_node_by_type(np, "pci") { 171 if (of_device_is_compatible(np, "fsl,mpc8540-pci") || 172 of_device_is_compatible(np, "fsl,mpc8548-pcie") || 173 of_device_is_compatible(np, "fsl,p2020-pcie")) { 174 struct resource rsrc; 175 of_address_to_resource(np, 0, &rsrc); 176 if ((rsrc.start & 0xfffff) == primary_phb_addr) 177 fsl_add_bridge(np, 1); 178 else 179 fsl_add_bridge(np, 0); 180 181 hose = pci_find_hose_for_OF_device(np); 182 max = min(max, hose->dma_window_base_cur + 183 hose->dma_window_size); 184 } 185 } 186 187 ppc_md.pci_exclude_device = mpc85xx_exclude_device; 188 #endif 189 190 #ifdef CONFIG_SMP 191 mpc85xx_smp_init(); 192 #endif 193 194 #ifdef CONFIG_SWIOTLB 195 if (memblock_end_of_DRAM() > max) { 196 ppc_swiotlb_enable = 1; 197 set_pci_dma_ops(&swiotlb_dma_ops); 198 ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb; 199 } 200 #endif 201 202 printk("MPC85xx DS board from Freescale Semiconductor\n"); 203 } 204 205 /* 206 * Called very early, device-tree isn't unflattened 207 */ 208 static int __init mpc8544_ds_probe(void) 209 { 210 unsigned long root = of_get_flat_dt_root(); 211 212 if (of_flat_dt_is_compatible(root, "MPC8544DS")) { 213 #ifdef CONFIG_PCI 214 primary_phb_addr = 0xb000; 215 #endif 216 return 1; 217 } 218 219 return 0; 220 } 221 222 static struct of_device_id __initdata mpc85xxds_ids[] = { 223 { .type = "soc", }, 224 { .compatible = "soc", }, 225 { .compatible = "simple-bus", }, 226 { .compatible = "gianfar", }, 227 {}, 228 }; 229 230 static int __init mpc85xxds_publish_devices(void) 231 { 232 return of_platform_bus_probe(NULL, mpc85xxds_ids, NULL); 233 } 234 machine_device_initcall(mpc8544_ds, mpc85xxds_publish_devices); 235 machine_device_initcall(mpc8572_ds, mpc85xxds_publish_devices); 236 machine_device_initcall(p2020_ds, mpc85xxds_publish_devices); 237 238 machine_arch_initcall(mpc8544_ds, swiotlb_setup_bus_notifier); 239 machine_arch_initcall(mpc8572_ds, swiotlb_setup_bus_notifier); 240 machine_arch_initcall(p2020_ds, swiotlb_setup_bus_notifier); 241 242 /* 243 * Called very early, device-tree isn't unflattened 244 */ 245 static int __init mpc8572_ds_probe(void) 246 { 247 unsigned long root = of_get_flat_dt_root(); 248 249 if (of_flat_dt_is_compatible(root, "fsl,MPC8572DS")) { 250 #ifdef CONFIG_PCI 251 primary_phb_addr = 0x8000; 252 #endif 253 return 1; 254 } 255 256 return 0; 257 } 258 259 /* 260 * Called very early, device-tree isn't unflattened 261 */ 262 static int __init p2020_ds_probe(void) 263 { 264 unsigned long root = of_get_flat_dt_root(); 265 266 if (of_flat_dt_is_compatible(root, "fsl,P2020DS")) { 267 #ifdef CONFIG_PCI 268 primary_phb_addr = 0x9000; 269 #endif 270 return 1; 271 } 272 273 return 0; 274 } 275 276 define_machine(mpc8544_ds) { 277 .name = "MPC8544 DS", 278 .probe = mpc8544_ds_probe, 279 .setup_arch = mpc85xx_ds_setup_arch, 280 .init_IRQ = mpc85xx_ds_pic_init, 281 #ifdef CONFIG_PCI 282 .pcibios_fixup_bus = fsl_pcibios_fixup_bus, 283 #endif 284 .get_irq = mpic_get_irq, 285 .restart = fsl_rstcr_restart, 286 .calibrate_decr = generic_calibrate_decr, 287 .progress = udbg_progress, 288 }; 289 290 define_machine(mpc8572_ds) { 291 .name = "MPC8572 DS", 292 .probe = mpc8572_ds_probe, 293 .setup_arch = mpc85xx_ds_setup_arch, 294 .init_IRQ = mpc85xx_ds_pic_init, 295 #ifdef CONFIG_PCI 296 .pcibios_fixup_bus = fsl_pcibios_fixup_bus, 297 #endif 298 .get_irq = mpic_get_irq, 299 .restart = fsl_rstcr_restart, 300 .calibrate_decr = generic_calibrate_decr, 301 .progress = udbg_progress, 302 }; 303 304 define_machine(p2020_ds) { 305 .name = "P2020 DS", 306 .probe = p2020_ds_probe, 307 .setup_arch = mpc85xx_ds_setup_arch, 308 .init_IRQ = mpc85xx_ds_pic_init, 309 #ifdef CONFIG_PCI 310 .pcibios_fixup_bus = fsl_pcibios_fixup_bus, 311 #endif 312 .get_irq = mpic_get_irq, 313 .restart = fsl_rstcr_restart, 314 .calibrate_decr = generic_calibrate_decr, 315 .progress = udbg_progress, 316 }; 317