18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2009 Extreme Engineering Solutions, Inc. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * X-ES board-specific functionality 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Based on mpc85xx_ds code from Freescale Semiconductor, Inc. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Author: Nate Case <ncase@xes-inc.com> 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/stddef.h> 138c2ecf20Sopenharmony_ci#include <linux/kernel.h> 148c2ecf20Sopenharmony_ci#include <linux/pci.h> 158c2ecf20Sopenharmony_ci#include <linux/kdev_t.h> 168c2ecf20Sopenharmony_ci#include <linux/delay.h> 178c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 188c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 198c2ecf20Sopenharmony_ci#include <linux/of_platform.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#include <asm/time.h> 228c2ecf20Sopenharmony_ci#include <asm/machdep.h> 238c2ecf20Sopenharmony_ci#include <asm/pci-bridge.h> 248c2ecf20Sopenharmony_ci#include <mm/mmu_decl.h> 258c2ecf20Sopenharmony_ci#include <asm/prom.h> 268c2ecf20Sopenharmony_ci#include <asm/udbg.h> 278c2ecf20Sopenharmony_ci#include <asm/mpic.h> 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#include <sysdev/fsl_soc.h> 308c2ecf20Sopenharmony_ci#include <sysdev/fsl_pci.h> 318c2ecf20Sopenharmony_ci#include "smp.h" 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#include "mpc85xx.h" 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci/* A few bit definitions needed for fixups on some boards */ 368c2ecf20Sopenharmony_ci#define MPC85xx_L2CTL_L2E 0x80000000 /* L2 enable */ 378c2ecf20Sopenharmony_ci#define MPC85xx_L2CTL_L2I 0x40000000 /* L2 flash invalidate */ 388c2ecf20Sopenharmony_ci#define MPC85xx_L2CTL_L2SIZ_MASK 0x30000000 /* L2 SRAM size (R/O) */ 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_civoid __init xes_mpc85xx_pic_init(void) 418c2ecf20Sopenharmony_ci{ 428c2ecf20Sopenharmony_ci struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN, 438c2ecf20Sopenharmony_ci 0, 256, " OpenPIC "); 448c2ecf20Sopenharmony_ci BUG_ON(mpic == NULL); 458c2ecf20Sopenharmony_ci mpic_init(mpic); 468c2ecf20Sopenharmony_ci} 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cistatic void xes_mpc85xx_configure_l2(void __iomem *l2_base) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci volatile uint32_t ctl, tmp; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci asm volatile("msync; isync"); 538c2ecf20Sopenharmony_ci tmp = in_be32(l2_base); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci /* 568c2ecf20Sopenharmony_ci * xMon may have enabled part of L2 as SRAM, so we need to set it 578c2ecf20Sopenharmony_ci * up for all cache mode just to be safe. 588c2ecf20Sopenharmony_ci */ 598c2ecf20Sopenharmony_ci printk(KERN_INFO "xes_mpc85xx: Enabling L2 as cache\n"); 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci ctl = MPC85xx_L2CTL_L2E | MPC85xx_L2CTL_L2I; 628c2ecf20Sopenharmony_ci if (of_machine_is_compatible("MPC8540") || 638c2ecf20Sopenharmony_ci of_machine_is_compatible("MPC8560")) 648c2ecf20Sopenharmony_ci /* 658c2ecf20Sopenharmony_ci * Assume L2 SRAM is used fully for cache, so set 668c2ecf20Sopenharmony_ci * L2BLKSZ (bits 4:5) to match L2SIZ (bits 2:3). 678c2ecf20Sopenharmony_ci */ 688c2ecf20Sopenharmony_ci ctl |= (tmp & MPC85xx_L2CTL_L2SIZ_MASK) >> 2; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci asm volatile("msync; isync"); 718c2ecf20Sopenharmony_ci out_be32(l2_base, ctl); 728c2ecf20Sopenharmony_ci asm volatile("msync; isync"); 738c2ecf20Sopenharmony_ci} 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistatic void xes_mpc85xx_fixups(void) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci struct device_node *np; 788c2ecf20Sopenharmony_ci int err; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci /* 818c2ecf20Sopenharmony_ci * Legacy xMon firmware on some X-ES boards does not enable L2 828c2ecf20Sopenharmony_ci * as cache. We must ensure that they get enabled here. 838c2ecf20Sopenharmony_ci */ 848c2ecf20Sopenharmony_ci for_each_node_by_name(np, "l2-cache-controller") { 858c2ecf20Sopenharmony_ci struct resource r[2]; 868c2ecf20Sopenharmony_ci void __iomem *l2_base; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci /* Only MPC8548, MPC8540, and MPC8560 boards are affected */ 898c2ecf20Sopenharmony_ci if (!of_device_is_compatible(np, 908c2ecf20Sopenharmony_ci "fsl,mpc8548-l2-cache-controller") && 918c2ecf20Sopenharmony_ci !of_device_is_compatible(np, 928c2ecf20Sopenharmony_ci "fsl,mpc8540-l2-cache-controller") && 938c2ecf20Sopenharmony_ci !of_device_is_compatible(np, 948c2ecf20Sopenharmony_ci "fsl,mpc8560-l2-cache-controller")) 958c2ecf20Sopenharmony_ci continue; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci err = of_address_to_resource(np, 0, &r[0]); 988c2ecf20Sopenharmony_ci if (err) { 998c2ecf20Sopenharmony_ci printk(KERN_WARNING "xes_mpc85xx: Could not get " 1008c2ecf20Sopenharmony_ci "resource for device tree node '%pOF'", 1018c2ecf20Sopenharmony_ci np); 1028c2ecf20Sopenharmony_ci continue; 1038c2ecf20Sopenharmony_ci } 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci l2_base = ioremap(r[0].start, resource_size(&r[0])); 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci xes_mpc85xx_configure_l2(l2_base); 1088c2ecf20Sopenharmony_ci } 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci/* 1128c2ecf20Sopenharmony_ci * Setup the architecture 1138c2ecf20Sopenharmony_ci */ 1148c2ecf20Sopenharmony_cistatic void __init xes_mpc85xx_setup_arch(void) 1158c2ecf20Sopenharmony_ci{ 1168c2ecf20Sopenharmony_ci struct device_node *root; 1178c2ecf20Sopenharmony_ci const char *model = "Unknown"; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci root = of_find_node_by_path("/"); 1208c2ecf20Sopenharmony_ci if (root == NULL) 1218c2ecf20Sopenharmony_ci return; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci model = of_get_property(root, "model", NULL); 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci printk(KERN_INFO "X-ES MPC85xx-based single-board computer: %s\n", 1268c2ecf20Sopenharmony_ci model + strlen("xes,")); 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci xes_mpc85xx_fixups(); 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci mpc85xx_smp_init(); 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci fsl_pci_assign_primary(); 1338c2ecf20Sopenharmony_ci} 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_cimachine_arch_initcall(xes_mpc8572, mpc85xx_common_publish_devices); 1368c2ecf20Sopenharmony_cimachine_arch_initcall(xes_mpc8548, mpc85xx_common_publish_devices); 1378c2ecf20Sopenharmony_cimachine_arch_initcall(xes_mpc8540, mpc85xx_common_publish_devices); 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci/* 1408c2ecf20Sopenharmony_ci * Called very early, device-tree isn't unflattened 1418c2ecf20Sopenharmony_ci */ 1428c2ecf20Sopenharmony_cistatic int __init xes_mpc8572_probe(void) 1438c2ecf20Sopenharmony_ci{ 1448c2ecf20Sopenharmony_ci return of_machine_is_compatible("xes,MPC8572"); 1458c2ecf20Sopenharmony_ci} 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_cistatic int __init xes_mpc8548_probe(void) 1488c2ecf20Sopenharmony_ci{ 1498c2ecf20Sopenharmony_ci return of_machine_is_compatible("xes,MPC8548"); 1508c2ecf20Sopenharmony_ci} 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_cistatic int __init xes_mpc8540_probe(void) 1538c2ecf20Sopenharmony_ci{ 1548c2ecf20Sopenharmony_ci return of_machine_is_compatible("xes,MPC8540"); 1558c2ecf20Sopenharmony_ci} 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_cidefine_machine(xes_mpc8572) { 1588c2ecf20Sopenharmony_ci .name = "X-ES MPC8572", 1598c2ecf20Sopenharmony_ci .probe = xes_mpc8572_probe, 1608c2ecf20Sopenharmony_ci .setup_arch = xes_mpc85xx_setup_arch, 1618c2ecf20Sopenharmony_ci .init_IRQ = xes_mpc85xx_pic_init, 1628c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI 1638c2ecf20Sopenharmony_ci .pcibios_fixup_bus = fsl_pcibios_fixup_bus, 1648c2ecf20Sopenharmony_ci .pcibios_fixup_phb = fsl_pcibios_fixup_phb, 1658c2ecf20Sopenharmony_ci#endif 1668c2ecf20Sopenharmony_ci .get_irq = mpic_get_irq, 1678c2ecf20Sopenharmony_ci .calibrate_decr = generic_calibrate_decr, 1688c2ecf20Sopenharmony_ci .progress = udbg_progress, 1698c2ecf20Sopenharmony_ci}; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_cidefine_machine(xes_mpc8548) { 1728c2ecf20Sopenharmony_ci .name = "X-ES MPC8548", 1738c2ecf20Sopenharmony_ci .probe = xes_mpc8548_probe, 1748c2ecf20Sopenharmony_ci .setup_arch = xes_mpc85xx_setup_arch, 1758c2ecf20Sopenharmony_ci .init_IRQ = xes_mpc85xx_pic_init, 1768c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI 1778c2ecf20Sopenharmony_ci .pcibios_fixup_bus = fsl_pcibios_fixup_bus, 1788c2ecf20Sopenharmony_ci .pcibios_fixup_phb = fsl_pcibios_fixup_phb, 1798c2ecf20Sopenharmony_ci#endif 1808c2ecf20Sopenharmony_ci .get_irq = mpic_get_irq, 1818c2ecf20Sopenharmony_ci .calibrate_decr = generic_calibrate_decr, 1828c2ecf20Sopenharmony_ci .progress = udbg_progress, 1838c2ecf20Sopenharmony_ci}; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_cidefine_machine(xes_mpc8540) { 1868c2ecf20Sopenharmony_ci .name = "X-ES MPC8540", 1878c2ecf20Sopenharmony_ci .probe = xes_mpc8540_probe, 1888c2ecf20Sopenharmony_ci .setup_arch = xes_mpc85xx_setup_arch, 1898c2ecf20Sopenharmony_ci .init_IRQ = xes_mpc85xx_pic_init, 1908c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI 1918c2ecf20Sopenharmony_ci .pcibios_fixup_bus = fsl_pcibios_fixup_bus, 1928c2ecf20Sopenharmony_ci .pcibios_fixup_phb = fsl_pcibios_fixup_phb, 1938c2ecf20Sopenharmony_ci#endif 1948c2ecf20Sopenharmony_ci .get_irq = mpic_get_irq, 1958c2ecf20Sopenharmony_ci .calibrate_decr = generic_calibrate_decr, 1968c2ecf20Sopenharmony_ci .progress = udbg_progress, 1978c2ecf20Sopenharmony_ci}; 198