18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * MPC85xx DS Board Setup 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Author Xianghua Xiao (x.xiao@freescale.com) 68c2ecf20Sopenharmony_ci * Roy Zang <tie-fei.zang@freescale.com> 78c2ecf20Sopenharmony_ci * - Add PCI/PCI Exprees support 88c2ecf20Sopenharmony_ci * Copyright 2007 Freescale Semiconductor Inc. 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/stddef.h> 128c2ecf20Sopenharmony_ci#include <linux/kernel.h> 138c2ecf20Sopenharmony_ci#include <linux/pci.h> 148c2ecf20Sopenharmony_ci#include <linux/kdev_t.h> 158c2ecf20Sopenharmony_ci#include <linux/delay.h> 168c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 178c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 188c2ecf20Sopenharmony_ci#include <linux/of_platform.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#include <asm/time.h> 218c2ecf20Sopenharmony_ci#include <asm/machdep.h> 228c2ecf20Sopenharmony_ci#include <asm/pci-bridge.h> 238c2ecf20Sopenharmony_ci#include <mm/mmu_decl.h> 248c2ecf20Sopenharmony_ci#include <asm/prom.h> 258c2ecf20Sopenharmony_ci#include <asm/udbg.h> 268c2ecf20Sopenharmony_ci#include <asm/mpic.h> 278c2ecf20Sopenharmony_ci#include <asm/i8259.h> 288c2ecf20Sopenharmony_ci#include <asm/swiotlb.h> 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#include <sysdev/fsl_soc.h> 318c2ecf20Sopenharmony_ci#include <sysdev/fsl_pci.h> 328c2ecf20Sopenharmony_ci#include "smp.h" 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#include "mpc85xx.h" 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#undef DEBUG 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#ifdef DEBUG 398c2ecf20Sopenharmony_ci#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args) 408c2ecf20Sopenharmony_ci#else 418c2ecf20Sopenharmony_ci#define DBG(fmt, args...) 428c2ecf20Sopenharmony_ci#endif 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_I8259 458c2ecf20Sopenharmony_cistatic void mpc85xx_8259_cascade(struct irq_desc *desc) 468c2ecf20Sopenharmony_ci{ 478c2ecf20Sopenharmony_ci struct irq_chip *chip = irq_desc_get_chip(desc); 488c2ecf20Sopenharmony_ci unsigned int cascade_irq = i8259_irq(); 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci if (cascade_irq) { 518c2ecf20Sopenharmony_ci generic_handle_irq(cascade_irq); 528c2ecf20Sopenharmony_ci } 538c2ecf20Sopenharmony_ci chip->irq_eoi(&desc->irq_data); 548c2ecf20Sopenharmony_ci} 558c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC_I8259 */ 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_civoid __init mpc85xx_ds_pic_init(void) 588c2ecf20Sopenharmony_ci{ 598c2ecf20Sopenharmony_ci struct mpic *mpic; 608c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_I8259 618c2ecf20Sopenharmony_ci struct device_node *np; 628c2ecf20Sopenharmony_ci struct device_node *cascade_node = NULL; 638c2ecf20Sopenharmony_ci int cascade_irq; 648c2ecf20Sopenharmony_ci#endif 658c2ecf20Sopenharmony_ci if (of_machine_is_compatible("fsl,MPC8572DS-CAMP")) { 668c2ecf20Sopenharmony_ci mpic = mpic_alloc(NULL, 0, 678c2ecf20Sopenharmony_ci MPIC_NO_RESET | 688c2ecf20Sopenharmony_ci MPIC_BIG_ENDIAN | 698c2ecf20Sopenharmony_ci MPIC_SINGLE_DEST_CPU, 708c2ecf20Sopenharmony_ci 0, 256, " OpenPIC "); 718c2ecf20Sopenharmony_ci } else { 728c2ecf20Sopenharmony_ci mpic = mpic_alloc(NULL, 0, 738c2ecf20Sopenharmony_ci MPIC_BIG_ENDIAN | 748c2ecf20Sopenharmony_ci MPIC_SINGLE_DEST_CPU, 758c2ecf20Sopenharmony_ci 0, 256, " OpenPIC "); 768c2ecf20Sopenharmony_ci } 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci BUG_ON(mpic == NULL); 798c2ecf20Sopenharmony_ci mpic_init(mpic); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_I8259 828c2ecf20Sopenharmony_ci /* Initialize the i8259 controller */ 838c2ecf20Sopenharmony_ci for_each_node_by_type(np, "interrupt-controller") 848c2ecf20Sopenharmony_ci if (of_device_is_compatible(np, "chrp,iic")) { 858c2ecf20Sopenharmony_ci cascade_node = np; 868c2ecf20Sopenharmony_ci break; 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci if (cascade_node == NULL) { 908c2ecf20Sopenharmony_ci printk(KERN_DEBUG "Could not find i8259 PIC\n"); 918c2ecf20Sopenharmony_ci return; 928c2ecf20Sopenharmony_ci } 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci cascade_irq = irq_of_parse_and_map(cascade_node, 0); 958c2ecf20Sopenharmony_ci if (!cascade_irq) { 968c2ecf20Sopenharmony_ci printk(KERN_ERR "Failed to map cascade interrupt\n"); 978c2ecf20Sopenharmony_ci return; 988c2ecf20Sopenharmony_ci } 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci DBG("mpc85xxds: cascade mapped to irq %d\n", cascade_irq); 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci i8259_init(cascade_node, 0); 1038c2ecf20Sopenharmony_ci of_node_put(cascade_node); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci irq_set_chained_handler(cascade_irq, mpc85xx_8259_cascade); 1068c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC_I8259 */ 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI 1108c2ecf20Sopenharmony_ciextern int uli_exclude_device(struct pci_controller *hose, 1118c2ecf20Sopenharmony_ci u_char bus, u_char devfn); 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_cistatic struct device_node *pci_with_uli; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_cistatic int mpc85xx_exclude_device(struct pci_controller *hose, 1168c2ecf20Sopenharmony_ci u_char bus, u_char devfn) 1178c2ecf20Sopenharmony_ci{ 1188c2ecf20Sopenharmony_ci if (hose->dn == pci_with_uli) 1198c2ecf20Sopenharmony_ci return uli_exclude_device(hose, bus, devfn); 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci return PCIBIOS_SUCCESSFUL; 1228c2ecf20Sopenharmony_ci} 1238c2ecf20Sopenharmony_ci#endif /* CONFIG_PCI */ 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_cistatic void __init mpc85xx_ds_uli_init(void) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI 1288c2ecf20Sopenharmony_ci struct device_node *node; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci /* See if we have a ULI under the primary */ 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci node = of_find_node_by_name(NULL, "uli1575"); 1338c2ecf20Sopenharmony_ci while ((pci_with_uli = of_get_parent(node))) { 1348c2ecf20Sopenharmony_ci of_node_put(node); 1358c2ecf20Sopenharmony_ci node = pci_with_uli; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci if (pci_with_uli == fsl_pci_primary) { 1388c2ecf20Sopenharmony_ci ppc_md.pci_exclude_device = mpc85xx_exclude_device; 1398c2ecf20Sopenharmony_ci break; 1408c2ecf20Sopenharmony_ci } 1418c2ecf20Sopenharmony_ci } 1428c2ecf20Sopenharmony_ci#endif 1438c2ecf20Sopenharmony_ci} 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci/* 1468c2ecf20Sopenharmony_ci * Setup the architecture 1478c2ecf20Sopenharmony_ci */ 1488c2ecf20Sopenharmony_cistatic void __init mpc85xx_ds_setup_arch(void) 1498c2ecf20Sopenharmony_ci{ 1508c2ecf20Sopenharmony_ci if (ppc_md.progress) 1518c2ecf20Sopenharmony_ci ppc_md.progress("mpc85xx_ds_setup_arch()", 0); 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci swiotlb_detect_4g(); 1548c2ecf20Sopenharmony_ci fsl_pci_assign_primary(); 1558c2ecf20Sopenharmony_ci mpc85xx_ds_uli_init(); 1568c2ecf20Sopenharmony_ci mpc85xx_smp_init(); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci printk("MPC85xx DS board from Freescale Semiconductor\n"); 1598c2ecf20Sopenharmony_ci} 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci/* 1628c2ecf20Sopenharmony_ci * Called very early, device-tree isn't unflattened 1638c2ecf20Sopenharmony_ci */ 1648c2ecf20Sopenharmony_cistatic int __init mpc8544_ds_probe(void) 1658c2ecf20Sopenharmony_ci{ 1668c2ecf20Sopenharmony_ci return !!of_machine_is_compatible("MPC8544DS"); 1678c2ecf20Sopenharmony_ci} 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cimachine_arch_initcall(mpc8544_ds, mpc85xx_common_publish_devices); 1708c2ecf20Sopenharmony_cimachine_arch_initcall(mpc8572_ds, mpc85xx_common_publish_devices); 1718c2ecf20Sopenharmony_cimachine_arch_initcall(p2020_ds, mpc85xx_common_publish_devices); 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci/* 1748c2ecf20Sopenharmony_ci * Called very early, device-tree isn't unflattened 1758c2ecf20Sopenharmony_ci */ 1768c2ecf20Sopenharmony_cistatic int __init mpc8572_ds_probe(void) 1778c2ecf20Sopenharmony_ci{ 1788c2ecf20Sopenharmony_ci return !!of_machine_is_compatible("fsl,MPC8572DS"); 1798c2ecf20Sopenharmony_ci} 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci/* 1828c2ecf20Sopenharmony_ci * Called very early, device-tree isn't unflattened 1838c2ecf20Sopenharmony_ci */ 1848c2ecf20Sopenharmony_cistatic int __init p2020_ds_probe(void) 1858c2ecf20Sopenharmony_ci{ 1868c2ecf20Sopenharmony_ci return !!of_machine_is_compatible("fsl,P2020DS"); 1878c2ecf20Sopenharmony_ci} 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_cidefine_machine(mpc8544_ds) { 1908c2ecf20Sopenharmony_ci .name = "MPC8544 DS", 1918c2ecf20Sopenharmony_ci .probe = mpc8544_ds_probe, 1928c2ecf20Sopenharmony_ci .setup_arch = mpc85xx_ds_setup_arch, 1938c2ecf20Sopenharmony_ci .init_IRQ = mpc85xx_ds_pic_init, 1948c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI 1958c2ecf20Sopenharmony_ci .pcibios_fixup_bus = fsl_pcibios_fixup_bus, 1968c2ecf20Sopenharmony_ci .pcibios_fixup_phb = fsl_pcibios_fixup_phb, 1978c2ecf20Sopenharmony_ci#endif 1988c2ecf20Sopenharmony_ci .get_irq = mpic_get_irq, 1998c2ecf20Sopenharmony_ci .calibrate_decr = generic_calibrate_decr, 2008c2ecf20Sopenharmony_ci .progress = udbg_progress, 2018c2ecf20Sopenharmony_ci}; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_cidefine_machine(mpc8572_ds) { 2048c2ecf20Sopenharmony_ci .name = "MPC8572 DS", 2058c2ecf20Sopenharmony_ci .probe = mpc8572_ds_probe, 2068c2ecf20Sopenharmony_ci .setup_arch = mpc85xx_ds_setup_arch, 2078c2ecf20Sopenharmony_ci .init_IRQ = mpc85xx_ds_pic_init, 2088c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI 2098c2ecf20Sopenharmony_ci .pcibios_fixup_bus = fsl_pcibios_fixup_bus, 2108c2ecf20Sopenharmony_ci .pcibios_fixup_phb = fsl_pcibios_fixup_phb, 2118c2ecf20Sopenharmony_ci#endif 2128c2ecf20Sopenharmony_ci .get_irq = mpic_get_irq, 2138c2ecf20Sopenharmony_ci .calibrate_decr = generic_calibrate_decr, 2148c2ecf20Sopenharmony_ci .progress = udbg_progress, 2158c2ecf20Sopenharmony_ci}; 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_cidefine_machine(p2020_ds) { 2188c2ecf20Sopenharmony_ci .name = "P2020 DS", 2198c2ecf20Sopenharmony_ci .probe = p2020_ds_probe, 2208c2ecf20Sopenharmony_ci .setup_arch = mpc85xx_ds_setup_arch, 2218c2ecf20Sopenharmony_ci .init_IRQ = mpc85xx_ds_pic_init, 2228c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI 2238c2ecf20Sopenharmony_ci .pcibios_fixup_bus = fsl_pcibios_fixup_bus, 2248c2ecf20Sopenharmony_ci .pcibios_fixup_phb = fsl_pcibios_fixup_phb, 2258c2ecf20Sopenharmony_ci#endif 2268c2ecf20Sopenharmony_ci .get_irq = mpic_get_irq, 2278c2ecf20Sopenharmony_ci .calibrate_decr = generic_calibrate_decr, 2288c2ecf20Sopenharmony_ci .progress = udbg_progress, 2298c2ecf20Sopenharmony_ci}; 230