162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2009 Extreme Engineering Solutions, Inc.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * X-ES board-specific functionality
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Based on mpc85xx_ds code from Freescale Semiconductor, Inc.
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * Author: Nate Case <ncase@xes-inc.com>
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/stddef.h>
1362306a36Sopenharmony_ci#include <linux/kernel.h>
1462306a36Sopenharmony_ci#include <linux/pci.h>
1562306a36Sopenharmony_ci#include <linux/kdev_t.h>
1662306a36Sopenharmony_ci#include <linux/delay.h>
1762306a36Sopenharmony_ci#include <linux/seq_file.h>
1862306a36Sopenharmony_ci#include <linux/interrupt.h>
1962306a36Sopenharmony_ci#include <linux/of.h>
2062306a36Sopenharmony_ci#include <linux/of_address.h>
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#include <asm/time.h>
2362306a36Sopenharmony_ci#include <asm/machdep.h>
2462306a36Sopenharmony_ci#include <asm/pci-bridge.h>
2562306a36Sopenharmony_ci#include <mm/mmu_decl.h>
2662306a36Sopenharmony_ci#include <asm/udbg.h>
2762306a36Sopenharmony_ci#include <asm/mpic.h>
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#include <sysdev/fsl_soc.h>
3062306a36Sopenharmony_ci#include <sysdev/fsl_pci.h>
3162306a36Sopenharmony_ci#include "smp.h"
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci#include "mpc85xx.h"
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci/* A few bit definitions needed for fixups on some boards */
3662306a36Sopenharmony_ci#define MPC85xx_L2CTL_L2E		0x80000000 /* L2 enable */
3762306a36Sopenharmony_ci#define MPC85xx_L2CTL_L2I		0x40000000 /* L2 flash invalidate */
3862306a36Sopenharmony_ci#define MPC85xx_L2CTL_L2SIZ_MASK	0x30000000 /* L2 SRAM size (R/O) */
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_civoid __init xes_mpc85xx_pic_init(void)
4162306a36Sopenharmony_ci{
4262306a36Sopenharmony_ci	struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN,
4362306a36Sopenharmony_ci			0, 256, " OpenPIC  ");
4462306a36Sopenharmony_ci	BUG_ON(mpic == NULL);
4562306a36Sopenharmony_ci	mpic_init(mpic);
4662306a36Sopenharmony_ci}
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_cistatic void __init xes_mpc85xx_configure_l2(void __iomem *l2_base)
4962306a36Sopenharmony_ci{
5062306a36Sopenharmony_ci	volatile uint32_t ctl, tmp;
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	asm volatile("msync; isync");
5362306a36Sopenharmony_ci	tmp = in_be32(l2_base);
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	/*
5662306a36Sopenharmony_ci	 * xMon may have enabled part of L2 as SRAM, so we need to set it
5762306a36Sopenharmony_ci	 * up for all cache mode just to be safe.
5862306a36Sopenharmony_ci	 */
5962306a36Sopenharmony_ci	printk(KERN_INFO "xes_mpc85xx: Enabling L2 as cache\n");
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	ctl = MPC85xx_L2CTL_L2E | MPC85xx_L2CTL_L2I;
6262306a36Sopenharmony_ci	if (of_machine_is_compatible("MPC8540") ||
6362306a36Sopenharmony_ci	    of_machine_is_compatible("MPC8560"))
6462306a36Sopenharmony_ci		/*
6562306a36Sopenharmony_ci		 * Assume L2 SRAM is used fully for cache, so set
6662306a36Sopenharmony_ci		 * L2BLKSZ (bits 4:5) to match L2SIZ (bits 2:3).
6762306a36Sopenharmony_ci		 */
6862306a36Sopenharmony_ci		ctl |= (tmp & MPC85xx_L2CTL_L2SIZ_MASK) >> 2;
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	asm volatile("msync; isync");
7162306a36Sopenharmony_ci	out_be32(l2_base, ctl);
7262306a36Sopenharmony_ci	asm volatile("msync; isync");
7362306a36Sopenharmony_ci}
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_cistatic void __init xes_mpc85xx_fixups(void)
7662306a36Sopenharmony_ci{
7762306a36Sopenharmony_ci	struct device_node *np;
7862306a36Sopenharmony_ci	int err;
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	/*
8162306a36Sopenharmony_ci	 * Legacy xMon firmware on some X-ES boards does not enable L2
8262306a36Sopenharmony_ci	 * as cache.  We must ensure that they get enabled here.
8362306a36Sopenharmony_ci	 */
8462306a36Sopenharmony_ci	for_each_node_by_name(np, "l2-cache-controller") {
8562306a36Sopenharmony_ci		struct resource r[2];
8662306a36Sopenharmony_ci		void __iomem *l2_base;
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci		/* Only MPC8548, MPC8540, and MPC8560 boards are affected */
8962306a36Sopenharmony_ci		if (!of_device_is_compatible(np,
9062306a36Sopenharmony_ci				    "fsl,mpc8548-l2-cache-controller") &&
9162306a36Sopenharmony_ci		    !of_device_is_compatible(np,
9262306a36Sopenharmony_ci				    "fsl,mpc8540-l2-cache-controller") &&
9362306a36Sopenharmony_ci		    !of_device_is_compatible(np,
9462306a36Sopenharmony_ci				    "fsl,mpc8560-l2-cache-controller"))
9562306a36Sopenharmony_ci			continue;
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci		err = of_address_to_resource(np, 0, &r[0]);
9862306a36Sopenharmony_ci		if (err) {
9962306a36Sopenharmony_ci			printk(KERN_WARNING "xes_mpc85xx: Could not get "
10062306a36Sopenharmony_ci			       "resource for device tree node '%pOF'",
10162306a36Sopenharmony_ci			       np);
10262306a36Sopenharmony_ci			continue;
10362306a36Sopenharmony_ci		}
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci		l2_base = ioremap(r[0].start, resource_size(&r[0]));
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci		xes_mpc85xx_configure_l2(l2_base);
10862306a36Sopenharmony_ci	}
10962306a36Sopenharmony_ci}
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci/*
11262306a36Sopenharmony_ci * Setup the architecture
11362306a36Sopenharmony_ci */
11462306a36Sopenharmony_cistatic void __init xes_mpc85xx_setup_arch(void)
11562306a36Sopenharmony_ci{
11662306a36Sopenharmony_ci	struct device_node *root;
11762306a36Sopenharmony_ci	const char *model = "Unknown";
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	root = of_find_node_by_path("/");
12062306a36Sopenharmony_ci	if (root == NULL)
12162306a36Sopenharmony_ci		return;
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	model = of_get_property(root, "model", NULL);
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	printk(KERN_INFO "X-ES MPC85xx-based single-board computer: %s\n",
12662306a36Sopenharmony_ci	       model + strlen("xes,"));
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci	xes_mpc85xx_fixups();
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	mpc85xx_smp_init();
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	fsl_pci_assign_primary();
13362306a36Sopenharmony_ci}
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_cimachine_arch_initcall(xes_mpc8572, mpc85xx_common_publish_devices);
13662306a36Sopenharmony_cimachine_arch_initcall(xes_mpc8548, mpc85xx_common_publish_devices);
13762306a36Sopenharmony_cimachine_arch_initcall(xes_mpc8540, mpc85xx_common_publish_devices);
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_cidefine_machine(xes_mpc8572) {
14062306a36Sopenharmony_ci	.name			= "X-ES MPC8572",
14162306a36Sopenharmony_ci	.compatible		= "xes,MPC8572",
14262306a36Sopenharmony_ci	.setup_arch		= xes_mpc85xx_setup_arch,
14362306a36Sopenharmony_ci	.init_IRQ		= xes_mpc85xx_pic_init,
14462306a36Sopenharmony_ci#ifdef CONFIG_PCI
14562306a36Sopenharmony_ci	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
14662306a36Sopenharmony_ci	.pcibios_fixup_phb      = fsl_pcibios_fixup_phb,
14762306a36Sopenharmony_ci#endif
14862306a36Sopenharmony_ci	.get_irq		= mpic_get_irq,
14962306a36Sopenharmony_ci	.progress		= udbg_progress,
15062306a36Sopenharmony_ci};
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_cidefine_machine(xes_mpc8548) {
15362306a36Sopenharmony_ci	.name			= "X-ES MPC8548",
15462306a36Sopenharmony_ci	.compatible		= "xes,MPC8548",
15562306a36Sopenharmony_ci	.setup_arch		= xes_mpc85xx_setup_arch,
15662306a36Sopenharmony_ci	.init_IRQ		= xes_mpc85xx_pic_init,
15762306a36Sopenharmony_ci#ifdef CONFIG_PCI
15862306a36Sopenharmony_ci	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
15962306a36Sopenharmony_ci	.pcibios_fixup_phb      = fsl_pcibios_fixup_phb,
16062306a36Sopenharmony_ci#endif
16162306a36Sopenharmony_ci	.get_irq		= mpic_get_irq,
16262306a36Sopenharmony_ci	.progress		= udbg_progress,
16362306a36Sopenharmony_ci};
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_cidefine_machine(xes_mpc8540) {
16662306a36Sopenharmony_ci	.name			= "X-ES MPC8540",
16762306a36Sopenharmony_ci	.compatible		= "xes,MPC8540",
16862306a36Sopenharmony_ci	.setup_arch		= xes_mpc85xx_setup_arch,
16962306a36Sopenharmony_ci	.init_IRQ		= xes_mpc85xx_pic_init,
17062306a36Sopenharmony_ci#ifdef CONFIG_PCI
17162306a36Sopenharmony_ci	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
17262306a36Sopenharmony_ci	.pcibios_fixup_phb      = fsl_pcibios_fixup_phb,
17362306a36Sopenharmony_ci#endif
17462306a36Sopenharmony_ci	.get_irq		= mpic_get_irq,
17562306a36Sopenharmony_ci	.progress		= udbg_progress,
17662306a36Sopenharmony_ci};
177