162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * arch/xtensa/platform-iss/setup.c
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Platform specific initialization.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Authors: Chris Zankel <chris@zankel.net>
962306a36Sopenharmony_ci *          Joe Taylor <joe@tensilica.com>
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * Copyright 2001 - 2005 Tensilica Inc.
1262306a36Sopenharmony_ci * Copyright 2017 Cadence Design Systems Inc.
1362306a36Sopenharmony_ci */
1462306a36Sopenharmony_ci#include <linux/init.h>
1562306a36Sopenharmony_ci#include <linux/kernel.h>
1662306a36Sopenharmony_ci#include <linux/notifier.h>
1762306a36Sopenharmony_ci#include <linux/panic_notifier.h>
1862306a36Sopenharmony_ci#include <linux/printk.h>
1962306a36Sopenharmony_ci#include <linux/reboot.h>
2062306a36Sopenharmony_ci#include <linux/string.h>
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#include <asm/platform.h>
2362306a36Sopenharmony_ci#include <asm/setup.h>
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#include <platform/simcall.h>
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_cistatic int iss_power_off(struct sys_off_data *unused)
2962306a36Sopenharmony_ci{
3062306a36Sopenharmony_ci	pr_info(" ** Called platform_power_off() **\n");
3162306a36Sopenharmony_ci	simc_exit(0);
3262306a36Sopenharmony_ci	return NOTIFY_DONE;
3362306a36Sopenharmony_ci}
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_cistatic int iss_restart(struct notifier_block *this,
3662306a36Sopenharmony_ci		       unsigned long event, void *ptr)
3762306a36Sopenharmony_ci{
3862306a36Sopenharmony_ci	/* Flush and reset the mmu, simulate a processor reset, and
3962306a36Sopenharmony_ci	 * jump to the reset vector. */
4062306a36Sopenharmony_ci	cpu_reset();
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	return NOTIFY_DONE;
4362306a36Sopenharmony_ci}
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_cistatic struct notifier_block iss_restart_block = {
4662306a36Sopenharmony_ci	.notifier_call = iss_restart,
4762306a36Sopenharmony_ci};
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_cistatic int
5062306a36Sopenharmony_ciiss_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	simc_exit(1);
5362306a36Sopenharmony_ci	return NOTIFY_DONE;
5462306a36Sopenharmony_ci}
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_cistatic struct notifier_block iss_panic_block = {
5762306a36Sopenharmony_ci	.notifier_call = iss_panic_event,
5862306a36Sopenharmony_ci};
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_civoid __init platform_setup(char **p_cmdline)
6162306a36Sopenharmony_ci{
6262306a36Sopenharmony_ci	static void *argv[COMMAND_LINE_SIZE / sizeof(void *)] __initdata;
6362306a36Sopenharmony_ci	static char cmdline[COMMAND_LINE_SIZE] __initdata;
6462306a36Sopenharmony_ci	int argc = simc_argc();
6562306a36Sopenharmony_ci	int argv_size = simc_argv_size();
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	if (argc > 1) {
6862306a36Sopenharmony_ci		if (argv_size > sizeof(argv)) {
6962306a36Sopenharmony_ci			pr_err("%s: command line too long: argv_size = %d\n",
7062306a36Sopenharmony_ci			       __func__, argv_size);
7162306a36Sopenharmony_ci		} else {
7262306a36Sopenharmony_ci			int i;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci			cmdline[0] = 0;
7562306a36Sopenharmony_ci			simc_argv((void *)argv);
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci			for (i = 1; i < argc; ++i) {
7862306a36Sopenharmony_ci				if (i > 1)
7962306a36Sopenharmony_ci					strcat(cmdline, " ");
8062306a36Sopenharmony_ci				strcat(cmdline, argv[i]);
8162306a36Sopenharmony_ci			}
8262306a36Sopenharmony_ci			*p_cmdline = cmdline;
8362306a36Sopenharmony_ci		}
8462306a36Sopenharmony_ci	}
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	atomic_notifier_chain_register(&panic_notifier_list, &iss_panic_block);
8762306a36Sopenharmony_ci	register_restart_handler(&iss_restart_block);
8862306a36Sopenharmony_ci	register_sys_off_handler(SYS_OFF_MODE_POWER_OFF,
8962306a36Sopenharmony_ci				 SYS_OFF_PRIO_PLATFORM,
9062306a36Sopenharmony_ci				 iss_power_off, NULL);
9162306a36Sopenharmony_ci}
92