18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * GE IMP3A Board Setup 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Author Martyn Welch <martyn.welch@ge.com> 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright 2010 GE Intelligent Platforms Embedded Systems, Inc. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Based on: mpc85xx_ds.c (MPC85xx DS Board Setup) 108c2ecf20Sopenharmony_ci * Copyright 2007 Freescale Semiconductor Inc. 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <linux/stddef.h> 148c2ecf20Sopenharmony_ci#include <linux/kernel.h> 158c2ecf20Sopenharmony_ci#include <linux/pci.h> 168c2ecf20Sopenharmony_ci#include <linux/kdev_t.h> 178c2ecf20Sopenharmony_ci#include <linux/delay.h> 188c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 198c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 208c2ecf20Sopenharmony_ci#include <linux/of_platform.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#include <asm/time.h> 238c2ecf20Sopenharmony_ci#include <asm/machdep.h> 248c2ecf20Sopenharmony_ci#include <asm/pci-bridge.h> 258c2ecf20Sopenharmony_ci#include <mm/mmu_decl.h> 268c2ecf20Sopenharmony_ci#include <asm/prom.h> 278c2ecf20Sopenharmony_ci#include <asm/udbg.h> 288c2ecf20Sopenharmony_ci#include <asm/mpic.h> 298c2ecf20Sopenharmony_ci#include <asm/swiotlb.h> 308c2ecf20Sopenharmony_ci#include <asm/nvram.h> 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#include <sysdev/fsl_soc.h> 338c2ecf20Sopenharmony_ci#include <sysdev/fsl_pci.h> 348c2ecf20Sopenharmony_ci#include "smp.h" 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#include "mpc85xx.h" 378c2ecf20Sopenharmony_ci#include <sysdev/ge/ge_pic.h> 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_civoid __iomem *imp3a_regs; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_civoid __init ge_imp3a_pic_init(void) 428c2ecf20Sopenharmony_ci{ 438c2ecf20Sopenharmony_ci struct mpic *mpic; 448c2ecf20Sopenharmony_ci struct device_node *np; 458c2ecf20Sopenharmony_ci struct device_node *cascade_node = NULL; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci if (of_machine_is_compatible("fsl,MPC8572DS-CAMP")) { 488c2ecf20Sopenharmony_ci mpic = mpic_alloc(NULL, 0, 498c2ecf20Sopenharmony_ci MPIC_NO_RESET | 508c2ecf20Sopenharmony_ci MPIC_BIG_ENDIAN | 518c2ecf20Sopenharmony_ci MPIC_SINGLE_DEST_CPU, 528c2ecf20Sopenharmony_ci 0, 256, " OpenPIC "); 538c2ecf20Sopenharmony_ci } else { 548c2ecf20Sopenharmony_ci mpic = mpic_alloc(NULL, 0, 558c2ecf20Sopenharmony_ci MPIC_BIG_ENDIAN | 568c2ecf20Sopenharmony_ci MPIC_SINGLE_DEST_CPU, 578c2ecf20Sopenharmony_ci 0, 256, " OpenPIC "); 588c2ecf20Sopenharmony_ci } 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci BUG_ON(mpic == NULL); 618c2ecf20Sopenharmony_ci mpic_init(mpic); 628c2ecf20Sopenharmony_ci /* 638c2ecf20Sopenharmony_ci * There is a simple interrupt handler in the main FPGA, this needs 648c2ecf20Sopenharmony_ci * to be cascaded into the MPIC 658c2ecf20Sopenharmony_ci */ 668c2ecf20Sopenharmony_ci for_each_node_by_type(np, "interrupt-controller") 678c2ecf20Sopenharmony_ci if (of_device_is_compatible(np, "gef,fpga-pic-1.00")) { 688c2ecf20Sopenharmony_ci cascade_node = np; 698c2ecf20Sopenharmony_ci break; 708c2ecf20Sopenharmony_ci } 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci if (cascade_node == NULL) { 738c2ecf20Sopenharmony_ci printk(KERN_WARNING "IMP3A: No FPGA PIC\n"); 748c2ecf20Sopenharmony_ci return; 758c2ecf20Sopenharmony_ci } 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci gef_pic_init(cascade_node); 788c2ecf20Sopenharmony_ci of_node_put(cascade_node); 798c2ecf20Sopenharmony_ci} 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cistatic void ge_imp3a_pci_assign_primary(void) 828c2ecf20Sopenharmony_ci{ 838c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI 848c2ecf20Sopenharmony_ci struct device_node *np; 858c2ecf20Sopenharmony_ci struct resource rsrc; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci for_each_node_by_type(np, "pci") { 888c2ecf20Sopenharmony_ci if (of_device_is_compatible(np, "fsl,mpc8540-pci") || 898c2ecf20Sopenharmony_ci of_device_is_compatible(np, "fsl,mpc8548-pcie") || 908c2ecf20Sopenharmony_ci of_device_is_compatible(np, "fsl,p2020-pcie")) { 918c2ecf20Sopenharmony_ci of_address_to_resource(np, 0, &rsrc); 928c2ecf20Sopenharmony_ci if ((rsrc.start & 0xfffff) == 0x9000) 938c2ecf20Sopenharmony_ci fsl_pci_primary = np; 948c2ecf20Sopenharmony_ci } 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci#endif 978c2ecf20Sopenharmony_ci} 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci/* 1008c2ecf20Sopenharmony_ci * Setup the architecture 1018c2ecf20Sopenharmony_ci */ 1028c2ecf20Sopenharmony_cistatic void __init ge_imp3a_setup_arch(void) 1038c2ecf20Sopenharmony_ci{ 1048c2ecf20Sopenharmony_ci struct device_node *regs; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci if (ppc_md.progress) 1078c2ecf20Sopenharmony_ci ppc_md.progress("ge_imp3a_setup_arch()", 0); 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci mpc85xx_smp_init(); 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci ge_imp3a_pci_assign_primary(); 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci swiotlb_detect_4g(); 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci /* Remap basic board registers */ 1168c2ecf20Sopenharmony_ci regs = of_find_compatible_node(NULL, NULL, "ge,imp3a-fpga-regs"); 1178c2ecf20Sopenharmony_ci if (regs) { 1188c2ecf20Sopenharmony_ci imp3a_regs = of_iomap(regs, 0); 1198c2ecf20Sopenharmony_ci if (imp3a_regs == NULL) 1208c2ecf20Sopenharmony_ci printk(KERN_WARNING "Unable to map board registers\n"); 1218c2ecf20Sopenharmony_ci of_node_put(regs); 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci#if defined(CONFIG_MMIO_NVRAM) 1258c2ecf20Sopenharmony_ci mmio_nvram_init(); 1268c2ecf20Sopenharmony_ci#endif 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci printk(KERN_INFO "GE Intelligent Platforms IMP3A 3U cPCI SBC\n"); 1298c2ecf20Sopenharmony_ci} 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci/* Return the PCB revision */ 1328c2ecf20Sopenharmony_cistatic unsigned int ge_imp3a_get_pcb_rev(void) 1338c2ecf20Sopenharmony_ci{ 1348c2ecf20Sopenharmony_ci unsigned int reg; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci reg = ioread16(imp3a_regs); 1378c2ecf20Sopenharmony_ci return (reg >> 8) & 0xff; 1388c2ecf20Sopenharmony_ci} 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci/* Return the board (software) revision */ 1418c2ecf20Sopenharmony_cistatic unsigned int ge_imp3a_get_board_rev(void) 1428c2ecf20Sopenharmony_ci{ 1438c2ecf20Sopenharmony_ci unsigned int reg; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci reg = ioread16(imp3a_regs + 0x2); 1468c2ecf20Sopenharmony_ci return reg & 0xff; 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci/* Return the FPGA revision */ 1508c2ecf20Sopenharmony_cistatic unsigned int ge_imp3a_get_fpga_rev(void) 1518c2ecf20Sopenharmony_ci{ 1528c2ecf20Sopenharmony_ci unsigned int reg; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci reg = ioread16(imp3a_regs + 0x2); 1558c2ecf20Sopenharmony_ci return (reg >> 8) & 0xff; 1568c2ecf20Sopenharmony_ci} 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci/* Return compactPCI Geographical Address */ 1598c2ecf20Sopenharmony_cistatic unsigned int ge_imp3a_get_cpci_geo_addr(void) 1608c2ecf20Sopenharmony_ci{ 1618c2ecf20Sopenharmony_ci unsigned int reg; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci reg = ioread16(imp3a_regs + 0x6); 1648c2ecf20Sopenharmony_ci return (reg & 0x0f00) >> 8; 1658c2ecf20Sopenharmony_ci} 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci/* Return compactPCI System Controller Status */ 1688c2ecf20Sopenharmony_cistatic unsigned int ge_imp3a_get_cpci_is_syscon(void) 1698c2ecf20Sopenharmony_ci{ 1708c2ecf20Sopenharmony_ci unsigned int reg; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci reg = ioread16(imp3a_regs + 0x6); 1738c2ecf20Sopenharmony_ci return reg & (1 << 12); 1748c2ecf20Sopenharmony_ci} 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_cistatic void ge_imp3a_show_cpuinfo(struct seq_file *m) 1778c2ecf20Sopenharmony_ci{ 1788c2ecf20Sopenharmony_ci seq_printf(m, "Vendor\t\t: GE Intelligent Platforms\n"); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci seq_printf(m, "Revision\t: %u%c\n", ge_imp3a_get_pcb_rev(), 1818c2ecf20Sopenharmony_ci ('A' + ge_imp3a_get_board_rev() - 1)); 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci seq_printf(m, "FPGA Revision\t: %u\n", ge_imp3a_get_fpga_rev()); 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci seq_printf(m, "cPCI geo. addr\t: %u\n", ge_imp3a_get_cpci_geo_addr()); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci seq_printf(m, "cPCI syscon\t: %s\n", 1888c2ecf20Sopenharmony_ci ge_imp3a_get_cpci_is_syscon() ? "yes" : "no"); 1898c2ecf20Sopenharmony_ci} 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci/* 1928c2ecf20Sopenharmony_ci * Called very early, device-tree isn't unflattened 1938c2ecf20Sopenharmony_ci */ 1948c2ecf20Sopenharmony_cistatic int __init ge_imp3a_probe(void) 1958c2ecf20Sopenharmony_ci{ 1968c2ecf20Sopenharmony_ci return of_machine_is_compatible("ge,IMP3A"); 1978c2ecf20Sopenharmony_ci} 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_cimachine_arch_initcall(ge_imp3a, mpc85xx_common_publish_devices); 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_cidefine_machine(ge_imp3a) { 2028c2ecf20Sopenharmony_ci .name = "GE_IMP3A", 2038c2ecf20Sopenharmony_ci .probe = ge_imp3a_probe, 2048c2ecf20Sopenharmony_ci .setup_arch = ge_imp3a_setup_arch, 2058c2ecf20Sopenharmony_ci .init_IRQ = ge_imp3a_pic_init, 2068c2ecf20Sopenharmony_ci .show_cpuinfo = ge_imp3a_show_cpuinfo, 2078c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI 2088c2ecf20Sopenharmony_ci .pcibios_fixup_bus = fsl_pcibios_fixup_bus, 2098c2ecf20Sopenharmony_ci .pcibios_fixup_phb = fsl_pcibios_fixup_phb, 2108c2ecf20Sopenharmony_ci#endif 2118c2ecf20Sopenharmony_ci .get_irq = mpic_get_irq, 2128c2ecf20Sopenharmony_ci .calibrate_decr = generic_calibrate_decr, 2138c2ecf20Sopenharmony_ci .progress = udbg_progress, 2148c2ecf20Sopenharmony_ci}; 215