1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * MPC85xx DS Board Setup 4 * 5 * Author Xianghua Xiao (x.xiao@freescale.com) 6 * Roy Zang <tie-fei.zang@freescale.com> 7 * - Add PCI/PCI Exprees support 8 * Copyright 2007 Freescale Semiconductor Inc. 9 */ 10 11 #include <linux/stddef.h> 12 #include <linux/kernel.h> 13 #include <linux/pci.h> 14 #include <linux/kdev_t.h> 15 #include <linux/delay.h> 16 #include <linux/seq_file.h> 17 #include <linux/interrupt.h> 18 #include <linux/of_irq.h> 19 #include <linux/of_platform.h> 20 21 #include <asm/time.h> 22 #include <asm/machdep.h> 23 #include <asm/pci-bridge.h> 24 #include <mm/mmu_decl.h> 25 #include <asm/udbg.h> 26 #include <asm/mpic.h> 27 #include <asm/i8259.h> 28 #include <asm/swiotlb.h> 29 30 #include <sysdev/fsl_soc.h> 31 #include <sysdev/fsl_pci.h> 32 #include "smp.h" 33 34 #include "mpc85xx.h" 35 36 #undef DEBUG 37 38 #ifdef DEBUG 39 #define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args) 40 #else 41 #define DBG(fmt, args...) 42 #endif 43 44 #ifdef CONFIG_PPC_I8259 45 static void mpc85xx_8259_cascade(struct irq_desc *desc) 46 { 47 struct irq_chip *chip = irq_desc_get_chip(desc); 48 unsigned int cascade_irq = i8259_irq(); 49 50 if (cascade_irq) { 51 generic_handle_irq(cascade_irq); 52 } 53 chip->irq_eoi(&desc->irq_data); 54 } 55 #endif /* CONFIG_PPC_I8259 */ 56 57 void __init mpc85xx_ds_pic_init(void) 58 { 59 struct mpic *mpic; 60 #ifdef CONFIG_PPC_I8259 61 struct device_node *np; 62 struct device_node *cascade_node = NULL; 63 int cascade_irq; 64 #endif 65 if (of_machine_is_compatible("fsl,MPC8572DS-CAMP")) { 66 mpic = mpic_alloc(NULL, 0, 67 MPIC_NO_RESET | 68 MPIC_BIG_ENDIAN | 69 MPIC_SINGLE_DEST_CPU, 70 0, 256, " OpenPIC "); 71 } else { 72 mpic = mpic_alloc(NULL, 0, 73 MPIC_BIG_ENDIAN | 74 MPIC_SINGLE_DEST_CPU, 75 0, 256, " OpenPIC "); 76 } 77 78 BUG_ON(mpic == NULL); 79 mpic_init(mpic); 80 81 #ifdef CONFIG_PPC_I8259 82 /* Initialize the i8259 controller */ 83 for_each_node_by_type(np, "interrupt-controller") 84 if (of_device_is_compatible(np, "chrp,iic")) { 85 cascade_node = np; 86 break; 87 } 88 89 if (cascade_node == NULL) { 90 printk(KERN_DEBUG "Could not find i8259 PIC\n"); 91 return; 92 } 93 94 cascade_irq = irq_of_parse_and_map(cascade_node, 0); 95 if (!cascade_irq) { 96 printk(KERN_ERR "Failed to map cascade interrupt\n"); 97 return; 98 } 99 100 DBG("mpc85xxds: cascade mapped to irq %d\n", cascade_irq); 101 102 i8259_init(cascade_node, 0); 103 of_node_put(cascade_node); 104 105 irq_set_chained_handler(cascade_irq, mpc85xx_8259_cascade); 106 #endif /* CONFIG_PPC_I8259 */ 107 } 108 109 #ifdef CONFIG_PCI 110 extern int uli_exclude_device(struct pci_controller *hose, 111 u_char bus, u_char devfn); 112 113 static struct device_node *pci_with_uli; 114 115 static int mpc85xx_exclude_device(struct pci_controller *hose, 116 u_char bus, u_char devfn) 117 { 118 if (hose->dn == pci_with_uli) 119 return uli_exclude_device(hose, bus, devfn); 120 121 return PCIBIOS_SUCCESSFUL; 122 } 123 #endif /* CONFIG_PCI */ 124 125 static void __init mpc85xx_ds_uli_init(void) 126 { 127 #ifdef CONFIG_PCI 128 struct device_node *node; 129 130 /* See if we have a ULI under the primary */ 131 132 node = of_find_node_by_name(NULL, "uli1575"); 133 while ((pci_with_uli = of_get_parent(node))) { 134 of_node_put(node); 135 node = pci_with_uli; 136 137 if (pci_with_uli == fsl_pci_primary) { 138 ppc_md.pci_exclude_device = mpc85xx_exclude_device; 139 break; 140 } 141 } 142 #endif 143 } 144 145 /* 146 * Setup the architecture 147 */ 148 static void __init mpc85xx_ds_setup_arch(void) 149 { 150 if (ppc_md.progress) 151 ppc_md.progress("mpc85xx_ds_setup_arch()", 0); 152 153 swiotlb_detect_4g(); 154 fsl_pci_assign_primary(); 155 mpc85xx_ds_uli_init(); 156 mpc85xx_smp_init(); 157 158 printk("MPC85xx DS board from Freescale Semiconductor\n"); 159 } 160 161 /* 162 * Called very early, device-tree isn't unflattened 163 */ 164 static int __init mpc8544_ds_probe(void) 165 { 166 return !!of_machine_is_compatible("MPC8544DS"); 167 } 168 169 machine_arch_initcall(mpc8544_ds, mpc85xx_common_publish_devices); 170 machine_arch_initcall(mpc8572_ds, mpc85xx_common_publish_devices); 171 machine_arch_initcall(p2020_ds, mpc85xx_common_publish_devices); 172 173 /* 174 * Called very early, device-tree isn't unflattened 175 */ 176 static int __init mpc8572_ds_probe(void) 177 { 178 return !!of_machine_is_compatible("fsl,MPC8572DS"); 179 } 180 181 /* 182 * Called very early, device-tree isn't unflattened 183 */ 184 static int __init p2020_ds_probe(void) 185 { 186 return !!of_machine_is_compatible("fsl,P2020DS"); 187 } 188 189 define_machine(mpc8544_ds) { 190 .name = "MPC8544 DS", 191 .probe = mpc8544_ds_probe, 192 .setup_arch = mpc85xx_ds_setup_arch, 193 .init_IRQ = mpc85xx_ds_pic_init, 194 #ifdef CONFIG_PCI 195 .pcibios_fixup_bus = fsl_pcibios_fixup_bus, 196 .pcibios_fixup_phb = fsl_pcibios_fixup_phb, 197 #endif 198 .get_irq = mpic_get_irq, 199 .calibrate_decr = generic_calibrate_decr, 200 .progress = udbg_progress, 201 }; 202 203 define_machine(mpc8572_ds) { 204 .name = "MPC8572 DS", 205 .probe = mpc8572_ds_probe, 206 .setup_arch = mpc85xx_ds_setup_arch, 207 .init_IRQ = mpc85xx_ds_pic_init, 208 #ifdef CONFIG_PCI 209 .pcibios_fixup_bus = fsl_pcibios_fixup_bus, 210 .pcibios_fixup_phb = fsl_pcibios_fixup_phb, 211 #endif 212 .get_irq = mpic_get_irq, 213 .calibrate_decr = generic_calibrate_decr, 214 .progress = udbg_progress, 215 }; 216 217 define_machine(p2020_ds) { 218 .name = "P2020 DS", 219 .probe = p2020_ds_probe, 220 .setup_arch = mpc85xx_ds_setup_arch, 221 .init_IRQ = mpc85xx_ds_pic_init, 222 #ifdef CONFIG_PCI 223 .pcibios_fixup_bus = fsl_pcibios_fixup_bus, 224 .pcibios_fixup_phb = fsl_pcibios_fixup_phb, 225 #endif 226 .get_irq = mpic_get_irq, 227 .calibrate_decr = generic_calibrate_decr, 228 .progress = udbg_progress, 229 }; 230