18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * GE SBC310 board support 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Author: Martyn Welch <martyn.welch@ge.com> 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Based on: mpc86xx_hpcn.c (MPC86xx HPCN board specific routines) 108c2ecf20Sopenharmony_ci * Copyright 2006 Freescale Semiconductor Inc. 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * NEC fixup adapted from arch/mips/pci/fixup-lm2e.c 138c2ecf20Sopenharmony_ci */ 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <linux/stddef.h> 168c2ecf20Sopenharmony_ci#include <linux/kernel.h> 178c2ecf20Sopenharmony_ci#include <linux/pci.h> 188c2ecf20Sopenharmony_ci#include <linux/kdev_t.h> 198c2ecf20Sopenharmony_ci#include <linux/delay.h> 208c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 218c2ecf20Sopenharmony_ci#include <linux/of_platform.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#include <asm/time.h> 248c2ecf20Sopenharmony_ci#include <asm/machdep.h> 258c2ecf20Sopenharmony_ci#include <asm/pci-bridge.h> 268c2ecf20Sopenharmony_ci#include <asm/prom.h> 278c2ecf20Sopenharmony_ci#include <mm/mmu_decl.h> 288c2ecf20Sopenharmony_ci#include <asm/udbg.h> 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#include <asm/mpic.h> 318c2ecf20Sopenharmony_ci#include <asm/nvram.h> 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#include <sysdev/fsl_pci.h> 348c2ecf20Sopenharmony_ci#include <sysdev/fsl_soc.h> 358c2ecf20Sopenharmony_ci#include <sysdev/ge/ge_pic.h> 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#include "mpc86xx.h" 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#undef DEBUG 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci#ifdef DEBUG 428c2ecf20Sopenharmony_ci#define DBG (fmt...) do { printk(KERN_ERR "SBC310: " fmt); } while (0) 438c2ecf20Sopenharmony_ci#else 448c2ecf20Sopenharmony_ci#define DBG (fmt...) do { } while (0) 458c2ecf20Sopenharmony_ci#endif 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_civoid __iomem *sbc310_regs; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cistatic void __init gef_sbc310_init_irq(void) 508c2ecf20Sopenharmony_ci{ 518c2ecf20Sopenharmony_ci struct device_node *cascade_node = NULL; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci mpc86xx_init_irq(); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci /* 568c2ecf20Sopenharmony_ci * There is a simple interrupt handler in the main FPGA, this needs 578c2ecf20Sopenharmony_ci * to be cascaded into the MPIC 588c2ecf20Sopenharmony_ci */ 598c2ecf20Sopenharmony_ci cascade_node = of_find_compatible_node(NULL, NULL, "gef,fpga-pic"); 608c2ecf20Sopenharmony_ci if (!cascade_node) { 618c2ecf20Sopenharmony_ci printk(KERN_WARNING "SBC310: No FPGA PIC\n"); 628c2ecf20Sopenharmony_ci return; 638c2ecf20Sopenharmony_ci } 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci gef_pic_init(cascade_node); 668c2ecf20Sopenharmony_ci of_node_put(cascade_node); 678c2ecf20Sopenharmony_ci} 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cistatic void __init gef_sbc310_setup_arch(void) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci struct device_node *regs; 728c2ecf20Sopenharmony_ci printk(KERN_INFO "GE Intelligent Platforms SBC310 6U VPX SBC\n"); 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 758c2ecf20Sopenharmony_ci mpc86xx_smp_init(); 768c2ecf20Sopenharmony_ci#endif 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci fsl_pci_assign_primary(); 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci /* Remap basic board registers */ 818c2ecf20Sopenharmony_ci regs = of_find_compatible_node(NULL, NULL, "gef,fpga-regs"); 828c2ecf20Sopenharmony_ci if (regs) { 838c2ecf20Sopenharmony_ci sbc310_regs = of_iomap(regs, 0); 848c2ecf20Sopenharmony_ci if (sbc310_regs == NULL) 858c2ecf20Sopenharmony_ci printk(KERN_WARNING "Unable to map board registers\n"); 868c2ecf20Sopenharmony_ci of_node_put(regs); 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci#if defined(CONFIG_MMIO_NVRAM) 908c2ecf20Sopenharmony_ci mmio_nvram_init(); 918c2ecf20Sopenharmony_ci#endif 928c2ecf20Sopenharmony_ci} 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci/* Return the PCB revision */ 958c2ecf20Sopenharmony_cistatic unsigned int gef_sbc310_get_board_id(void) 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci unsigned int reg; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci reg = ioread32(sbc310_regs); 1008c2ecf20Sopenharmony_ci return reg & 0xff; 1018c2ecf20Sopenharmony_ci} 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci/* Return the PCB revision */ 1048c2ecf20Sopenharmony_cistatic unsigned int gef_sbc310_get_pcb_rev(void) 1058c2ecf20Sopenharmony_ci{ 1068c2ecf20Sopenharmony_ci unsigned int reg; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci reg = ioread32(sbc310_regs); 1098c2ecf20Sopenharmony_ci return (reg >> 8) & 0xff; 1108c2ecf20Sopenharmony_ci} 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci/* Return the board (software) revision */ 1138c2ecf20Sopenharmony_cistatic unsigned int gef_sbc310_get_board_rev(void) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci unsigned int reg; 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci reg = ioread32(sbc310_regs); 1188c2ecf20Sopenharmony_ci return (reg >> 16) & 0xff; 1198c2ecf20Sopenharmony_ci} 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci/* Return the FPGA revision */ 1228c2ecf20Sopenharmony_cistatic unsigned int gef_sbc310_get_fpga_rev(void) 1238c2ecf20Sopenharmony_ci{ 1248c2ecf20Sopenharmony_ci unsigned int reg; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci reg = ioread32(sbc310_regs); 1278c2ecf20Sopenharmony_ci return (reg >> 24) & 0xf; 1288c2ecf20Sopenharmony_ci} 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_cistatic void gef_sbc310_show_cpuinfo(struct seq_file *m) 1318c2ecf20Sopenharmony_ci{ 1328c2ecf20Sopenharmony_ci uint svid = mfspr(SPRN_SVR); 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci seq_printf(m, "Vendor\t\t: GE Intelligent Platforms\n"); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci seq_printf(m, "Board ID\t: 0x%2.2x\n", gef_sbc310_get_board_id()); 1378c2ecf20Sopenharmony_ci seq_printf(m, "Revision\t: %u%c\n", gef_sbc310_get_pcb_rev(), 1388c2ecf20Sopenharmony_ci ('A' + gef_sbc310_get_board_rev() - 1)); 1398c2ecf20Sopenharmony_ci seq_printf(m, "FPGA Revision\t: %u\n", gef_sbc310_get_fpga_rev()); 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci seq_printf(m, "SVR\t\t: 0x%x\n", svid); 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci} 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_cistatic void gef_sbc310_nec_fixup(struct pci_dev *pdev) 1468c2ecf20Sopenharmony_ci{ 1478c2ecf20Sopenharmony_ci unsigned int val; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci /* Do not do the fixup on other platforms! */ 1508c2ecf20Sopenharmony_ci if (!machine_is(gef_sbc310)) 1518c2ecf20Sopenharmony_ci return; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci printk(KERN_INFO "Running NEC uPD720101 Fixup\n"); 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci /* Ensure only ports 1 & 2 are enabled */ 1568c2ecf20Sopenharmony_ci pci_read_config_dword(pdev, 0xe0, &val); 1578c2ecf20Sopenharmony_ci pci_write_config_dword(pdev, 0xe0, (val & ~7) | 0x2); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci /* System clock is 48-MHz Oscillator and EHCI Enabled. */ 1608c2ecf20Sopenharmony_ci pci_write_config_dword(pdev, 0xe4, 1 << 5); 1618c2ecf20Sopenharmony_ci} 1628c2ecf20Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB, 1638c2ecf20Sopenharmony_ci gef_sbc310_nec_fixup); 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci/* 1668c2ecf20Sopenharmony_ci * Called very early, device-tree isn't unflattened 1678c2ecf20Sopenharmony_ci * 1688c2ecf20Sopenharmony_ci * This function is called to determine whether the BSP is compatible with the 1698c2ecf20Sopenharmony_ci * supplied device-tree, which is assumed to be the correct one for the actual 1708c2ecf20Sopenharmony_ci * board. It is expected thati, in the future, a kernel may support multiple 1718c2ecf20Sopenharmony_ci * boards. 1728c2ecf20Sopenharmony_ci */ 1738c2ecf20Sopenharmony_cistatic int __init gef_sbc310_probe(void) 1748c2ecf20Sopenharmony_ci{ 1758c2ecf20Sopenharmony_ci if (of_machine_is_compatible("gef,sbc310")) 1768c2ecf20Sopenharmony_ci return 1; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci return 0; 1798c2ecf20Sopenharmony_ci} 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_cimachine_arch_initcall(gef_sbc310, mpc86xx_common_publish_devices); 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_cidefine_machine(gef_sbc310) { 1848c2ecf20Sopenharmony_ci .name = "GE SBC310", 1858c2ecf20Sopenharmony_ci .probe = gef_sbc310_probe, 1868c2ecf20Sopenharmony_ci .setup_arch = gef_sbc310_setup_arch, 1878c2ecf20Sopenharmony_ci .init_IRQ = gef_sbc310_init_irq, 1888c2ecf20Sopenharmony_ci .show_cpuinfo = gef_sbc310_show_cpuinfo, 1898c2ecf20Sopenharmony_ci .get_irq = mpic_get_irq, 1908c2ecf20Sopenharmony_ci .time_init = mpc86xx_time_init, 1918c2ecf20Sopenharmony_ci .calibrate_decr = generic_calibrate_decr, 1928c2ecf20Sopenharmony_ci .progress = udbg_progress, 1938c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI 1948c2ecf20Sopenharmony_ci .pcibios_fixup_bus = fsl_pcibios_fixup_bus, 1958c2ecf20Sopenharmony_ci#endif 1968c2ecf20Sopenharmony_ci}; 197