18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * misc setup functions for MPC83xx
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Maintainer: Kumar Gala <galak@kernel.crashing.org>
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/stddef.h>
98c2ecf20Sopenharmony_ci#include <linux/kernel.h>
108c2ecf20Sopenharmony_ci#include <linux/of_platform.h>
118c2ecf20Sopenharmony_ci#include <linux/pci.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <asm/debug.h>
148c2ecf20Sopenharmony_ci#include <asm/io.h>
158c2ecf20Sopenharmony_ci#include <asm/hw_irq.h>
168c2ecf20Sopenharmony_ci#include <asm/ipic.h>
178c2ecf20Sopenharmony_ci#include <sysdev/fsl_soc.h>
188c2ecf20Sopenharmony_ci#include <sysdev/fsl_pci.h>
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#include <mm/mmu_decl.h>
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#include "mpc83xx.h"
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_cistatic __be32 __iomem *restart_reg_base;
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_cistatic int __init mpc83xx_restart_init(void)
278c2ecf20Sopenharmony_ci{
288c2ecf20Sopenharmony_ci	/* map reset restart_reg_baseister space */
298c2ecf20Sopenharmony_ci	restart_reg_base = ioremap(get_immrbase() + 0x900, 0xff);
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci	return 0;
328c2ecf20Sopenharmony_ci}
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ciarch_initcall(mpc83xx_restart_init);
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_civoid __noreturn mpc83xx_restart(char *cmd)
378c2ecf20Sopenharmony_ci{
388c2ecf20Sopenharmony_ci#define RST_OFFSET	0x00000900
398c2ecf20Sopenharmony_ci#define RST_PROT_REG	0x00000018
408c2ecf20Sopenharmony_ci#define RST_CTRL_REG	0x0000001c
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	local_irq_disable();
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	if (restart_reg_base) {
458c2ecf20Sopenharmony_ci		/* enable software reset "RSTE" */
468c2ecf20Sopenharmony_ci		out_be32(restart_reg_base + (RST_PROT_REG >> 2), 0x52535445);
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci		/* set software hard reset */
498c2ecf20Sopenharmony_ci		out_be32(restart_reg_base + (RST_CTRL_REG >> 2), 0x2);
508c2ecf20Sopenharmony_ci	} else {
518c2ecf20Sopenharmony_ci		printk (KERN_EMERG "Error: Restart registers not mapped, spinning!\n");
528c2ecf20Sopenharmony_ci	}
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	for (;;) ;
558c2ecf20Sopenharmony_ci}
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_cilong __init mpc83xx_time_init(void)
588c2ecf20Sopenharmony_ci{
598c2ecf20Sopenharmony_ci#define SPCR_OFFSET	0x00000110
608c2ecf20Sopenharmony_ci#define SPCR_TBEN	0x00400000
618c2ecf20Sopenharmony_ci	__be32 __iomem *spcr = ioremap(get_immrbase() + SPCR_OFFSET, 4);
628c2ecf20Sopenharmony_ci	__be32 tmp;
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	tmp = in_be32(spcr);
658c2ecf20Sopenharmony_ci	out_be32(spcr, tmp | SPCR_TBEN);
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	iounmap(spcr);
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	return 0;
708c2ecf20Sopenharmony_ci}
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_civoid __init mpc83xx_ipic_init_IRQ(void)
738c2ecf20Sopenharmony_ci{
748c2ecf20Sopenharmony_ci	struct device_node *np;
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	/* looking for fsl,pq2pro-pic which is asl compatible with fsl,ipic */
778c2ecf20Sopenharmony_ci	np = of_find_compatible_node(NULL, NULL, "fsl,ipic");
788c2ecf20Sopenharmony_ci	if (!np)
798c2ecf20Sopenharmony_ci		np = of_find_node_by_type(NULL, "ipic");
808c2ecf20Sopenharmony_ci	if (!np)
818c2ecf20Sopenharmony_ci		return;
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	ipic_init(np, 0);
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	of_node_put(np);
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	/* Initialize the default interrupt mapping priorities,
888c2ecf20Sopenharmony_ci	 * in case the boot rom changed something on us.
898c2ecf20Sopenharmony_ci	 */
908c2ecf20Sopenharmony_ci	ipic_set_default_priority();
918c2ecf20Sopenharmony_ci}
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_cistatic const struct of_device_id of_bus_ids[] __initconst = {
948c2ecf20Sopenharmony_ci	{ .type = "soc", },
958c2ecf20Sopenharmony_ci	{ .compatible = "soc", },
968c2ecf20Sopenharmony_ci	{ .compatible = "simple-bus" },
978c2ecf20Sopenharmony_ci	{ .compatible = "gianfar" },
988c2ecf20Sopenharmony_ci	{ .compatible = "gpio-leds", },
998c2ecf20Sopenharmony_ci	{ .type = "qe", },
1008c2ecf20Sopenharmony_ci	{ .compatible = "fsl,qe", },
1018c2ecf20Sopenharmony_ci	{},
1028c2ecf20Sopenharmony_ci};
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ciint __init mpc83xx_declare_of_platform_devices(void)
1058c2ecf20Sopenharmony_ci{
1068c2ecf20Sopenharmony_ci	of_platform_bus_probe(NULL, of_bus_ids, NULL);
1078c2ecf20Sopenharmony_ci	return 0;
1088c2ecf20Sopenharmony_ci}
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI
1118c2ecf20Sopenharmony_civoid __init mpc83xx_setup_pci(void)
1128c2ecf20Sopenharmony_ci{
1138c2ecf20Sopenharmony_ci	struct device_node *np;
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
1168c2ecf20Sopenharmony_ci		mpc83xx_add_bridge(np);
1178c2ecf20Sopenharmony_ci	for_each_compatible_node(np, "pci", "fsl,mpc8314-pcie")
1188c2ecf20Sopenharmony_ci		mpc83xx_add_bridge(np);
1198c2ecf20Sopenharmony_ci}
1208c2ecf20Sopenharmony_ci#endif
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_civoid __init mpc83xx_setup_arch(void)
1238c2ecf20Sopenharmony_ci{
1248c2ecf20Sopenharmony_ci	if (ppc_md.progress)
1258c2ecf20Sopenharmony_ci		ppc_md.progress("mpc83xx_setup_arch()", 0);
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	if (!__map_without_bats) {
1288c2ecf20Sopenharmony_ci		phys_addr_t immrbase = get_immrbase();
1298c2ecf20Sopenharmony_ci		int immrsize = IS_ALIGNED(immrbase, SZ_2M) ? SZ_2M : SZ_1M;
1308c2ecf20Sopenharmony_ci		unsigned long va = fix_to_virt(FIX_IMMR_BASE);
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci		setbat(-1, va, immrbase, immrsize, PAGE_KERNEL_NCG);
1338c2ecf20Sopenharmony_ci		update_bats();
1348c2ecf20Sopenharmony_ci	}
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci	mpc83xx_setup_pci();
1378c2ecf20Sopenharmony_ci}
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ciint machine_check_83xx(struct pt_regs *regs)
1408c2ecf20Sopenharmony_ci{
1418c2ecf20Sopenharmony_ci	u32 mask = 1 << (31 - IPIC_MCP_WDT);
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	if (!(regs->msr & SRR1_MCE_MCP) || !(ipic_get_mcp_status() & mask))
1448c2ecf20Sopenharmony_ci		return machine_check_generic(regs);
1458c2ecf20Sopenharmony_ci	ipic_clear_mcp_status(mask);
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	if (debugger_fault_handler(regs))
1488c2ecf20Sopenharmony_ci		return 1;
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	die("Watchdog NMI Reset", regs, 0);
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	return 1;
1538c2ecf20Sopenharmony_ci}
154