1 /* 2 * GE IMP3A Board Setup 3 * 4 * Author Martyn Welch <martyn.welch@ge.com> 5 * 6 * Copyright 2010 GE Intelligent Platforms Embedded Systems, Inc. 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 * 13 * Based on: mpc85xx_ds.c (MPC85xx DS Board Setup) 14 * Copyright 2007 Freescale Semiconductor Inc. 15 */ 16 17 #include <linux/stddef.h> 18 #include <linux/kernel.h> 19 #include <linux/pci.h> 20 #include <linux/kdev_t.h> 21 #include <linux/delay.h> 22 #include <linux/seq_file.h> 23 #include <linux/interrupt.h> 24 #include <linux/of_platform.h> 25 #include <linux/memblock.h> 26 27 #include <asm/time.h> 28 #include <asm/machdep.h> 29 #include <asm/pci-bridge.h> 30 #include <mm/mmu_decl.h> 31 #include <asm/prom.h> 32 #include <asm/udbg.h> 33 #include <asm/mpic.h> 34 #include <asm/swiotlb.h> 35 #include <asm/nvram.h> 36 37 #include <sysdev/fsl_soc.h> 38 #include <sysdev/fsl_pci.h> 39 #include "smp.h" 40 41 #include "mpc85xx.h" 42 #include <sysdev/ge/ge_pic.h> 43 44 void __iomem *imp3a_regs; 45 46 void __init ge_imp3a_pic_init(void) 47 { 48 struct mpic *mpic; 49 struct device_node *np; 50 struct device_node *cascade_node = NULL; 51 unsigned long root = of_get_flat_dt_root(); 52 53 if (of_flat_dt_is_compatible(root, "fsl,MPC8572DS-CAMP")) { 54 mpic = mpic_alloc(NULL, 0, 55 MPIC_NO_RESET | 56 MPIC_BIG_ENDIAN | 57 MPIC_SINGLE_DEST_CPU, 58 0, 256, " OpenPIC "); 59 } else { 60 mpic = mpic_alloc(NULL, 0, 61 MPIC_BIG_ENDIAN | 62 MPIC_SINGLE_DEST_CPU, 63 0, 256, " OpenPIC "); 64 } 65 66 BUG_ON(mpic == NULL); 67 mpic_init(mpic); 68 /* 69 * There is a simple interrupt handler in the main FPGA, this needs 70 * to be cascaded into the MPIC 71 */ 72 for_each_node_by_type(np, "interrupt-controller") 73 if (of_device_is_compatible(np, "gef,fpga-pic-1.00")) { 74 cascade_node = np; 75 break; 76 } 77 78 if (cascade_node == NULL) { 79 printk(KERN_WARNING "IMP3A: No FPGA PIC\n"); 80 return; 81 } 82 83 gef_pic_init(cascade_node); 84 of_node_put(cascade_node); 85 } 86 87 #ifdef CONFIG_PCI 88 static int primary_phb_addr; 89 #endif /* CONFIG_PCI */ 90 91 /* 92 * Setup the architecture 93 */ 94 static void __init ge_imp3a_setup_arch(void) 95 { 96 struct device_node *regs; 97 #ifdef CONFIG_PCI 98 struct device_node *np; 99 struct pci_controller *hose; 100 #endif 101 dma_addr_t max = 0xffffffff; 102 103 if (ppc_md.progress) 104 ppc_md.progress("ge_imp3a_setup_arch()", 0); 105 106 #ifdef CONFIG_PCI 107 for_each_node_by_type(np, "pci") { 108 if (of_device_is_compatible(np, "fsl,mpc8540-pci") || 109 of_device_is_compatible(np, "fsl,mpc8548-pcie") || 110 of_device_is_compatible(np, "fsl,p2020-pcie")) { 111 struct resource rsrc; 112 of_address_to_resource(np, 0, &rsrc); 113 if ((rsrc.start & 0xfffff) == primary_phb_addr) 114 fsl_add_bridge(np, 1); 115 else 116 fsl_add_bridge(np, 0); 117 118 hose = pci_find_hose_for_OF_device(np); 119 max = min(max, hose->dma_window_base_cur + 120 hose->dma_window_size); 121 } 122 } 123 #endif 124 125 mpc85xx_smp_init(); 126 127 #ifdef CONFIG_SWIOTLB 128 if ((memblock_end_of_DRAM() - 1) > max) { 129 ppc_swiotlb_enable = 1; 130 set_pci_dma_ops(&swiotlb_dma_ops); 131 ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb; 132 } 133 #endif 134 135 /* Remap basic board registers */ 136 regs = of_find_compatible_node(NULL, NULL, "ge,imp3a-fpga-regs"); 137 if (regs) { 138 imp3a_regs = of_iomap(regs, 0); 139 if (imp3a_regs == NULL) 140 printk(KERN_WARNING "Unable to map board registers\n"); 141 of_node_put(regs); 142 } 143 144 #if defined(CONFIG_MMIO_NVRAM) 145 mmio_nvram_init(); 146 #endif 147 148 printk(KERN_INFO "GE Intelligent Platforms IMP3A 3U cPCI SBC\n"); 149 } 150 151 /* Return the PCB revision */ 152 static unsigned int ge_imp3a_get_pcb_rev(void) 153 { 154 unsigned int reg; 155 156 reg = ioread16(imp3a_regs); 157 return (reg >> 8) & 0xff; 158 } 159 160 /* Return the board (software) revision */ 161 static unsigned int ge_imp3a_get_board_rev(void) 162 { 163 unsigned int reg; 164 165 reg = ioread16(imp3a_regs + 0x2); 166 return reg & 0xff; 167 } 168 169 /* Return the FPGA revision */ 170 static unsigned int ge_imp3a_get_fpga_rev(void) 171 { 172 unsigned int reg; 173 174 reg = ioread16(imp3a_regs + 0x2); 175 return (reg >> 8) & 0xff; 176 } 177 178 /* Return compactPCI Geographical Address */ 179 static unsigned int ge_imp3a_get_cpci_geo_addr(void) 180 { 181 unsigned int reg; 182 183 reg = ioread16(imp3a_regs + 0x6); 184 return (reg & 0x0f00) >> 8; 185 } 186 187 /* Return compactPCI System Controller Status */ 188 static unsigned int ge_imp3a_get_cpci_is_syscon(void) 189 { 190 unsigned int reg; 191 192 reg = ioread16(imp3a_regs + 0x6); 193 return reg & (1 << 12); 194 } 195 196 static void ge_imp3a_show_cpuinfo(struct seq_file *m) 197 { 198 seq_printf(m, "Vendor\t\t: GE Intelligent Platforms\n"); 199 200 seq_printf(m, "Revision\t: %u%c\n", ge_imp3a_get_pcb_rev(), 201 ('A' + ge_imp3a_get_board_rev() - 1)); 202 203 seq_printf(m, "FPGA Revision\t: %u\n", ge_imp3a_get_fpga_rev()); 204 205 seq_printf(m, "cPCI geo. addr\t: %u\n", ge_imp3a_get_cpci_geo_addr()); 206 207 seq_printf(m, "cPCI syscon\t: %s\n", 208 ge_imp3a_get_cpci_is_syscon() ? "yes" : "no"); 209 } 210 211 /* 212 * Called very early, device-tree isn't unflattened 213 */ 214 static int __init ge_imp3a_probe(void) 215 { 216 unsigned long root = of_get_flat_dt_root(); 217 218 if (of_flat_dt_is_compatible(root, "ge,IMP3A")) { 219 #ifdef CONFIG_PCI 220 primary_phb_addr = 0x9000; 221 #endif 222 return 1; 223 } 224 225 return 0; 226 } 227 228 machine_device_initcall(ge_imp3a, mpc85xx_common_publish_devices); 229 230 machine_arch_initcall(ge_imp3a, swiotlb_setup_bus_notifier); 231 232 define_machine(ge_imp3a) { 233 .name = "GE_IMP3A", 234 .probe = ge_imp3a_probe, 235 .setup_arch = ge_imp3a_setup_arch, 236 .init_IRQ = ge_imp3a_pic_init, 237 .show_cpuinfo = ge_imp3a_show_cpuinfo, 238 #ifdef CONFIG_PCI 239 .pcibios_fixup_bus = fsl_pcibios_fixup_bus, 240 #endif 241 .get_irq = mpic_get_irq, 242 .restart = fsl_rstcr_restart, 243 .calibrate_decr = generic_calibrate_decr, 244 .progress = udbg_progress, 245 }; 246