162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Gemini Device Tree boot support
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci#include <linux/kernel.h>
662306a36Sopenharmony_ci#include <linux/init.h>
762306a36Sopenharmony_ci#include <linux/io.h>
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <asm/mach/arch.h>
1062306a36Sopenharmony_ci#include <asm/mach/map.h>
1162306a36Sopenharmony_ci#include <asm/system_misc.h>
1262306a36Sopenharmony_ci#include <asm/proc-fns.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_GEMINI
1562306a36Sopenharmony_ci/* This is needed for LL-debug/earlyprintk/debug-macro.S */
1662306a36Sopenharmony_cistatic struct map_desc gemini_io_desc[] __initdata = {
1762306a36Sopenharmony_ci	{
1862306a36Sopenharmony_ci		.virtual = CONFIG_DEBUG_UART_VIRT,
1962306a36Sopenharmony_ci		.pfn = __phys_to_pfn(CONFIG_DEBUG_UART_PHYS),
2062306a36Sopenharmony_ci		.length = SZ_4K,
2162306a36Sopenharmony_ci		.type = MT_DEVICE,
2262306a36Sopenharmony_ci	},
2362306a36Sopenharmony_ci};
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistatic void __init gemini_map_io(void)
2662306a36Sopenharmony_ci{
2762306a36Sopenharmony_ci	iotable_init(gemini_io_desc, ARRAY_SIZE(gemini_io_desc));
2862306a36Sopenharmony_ci}
2962306a36Sopenharmony_ci#else
3062306a36Sopenharmony_ci#define gemini_map_io NULL
3162306a36Sopenharmony_ci#endif
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_cistatic void gemini_idle(void)
3462306a36Sopenharmony_ci{
3562306a36Sopenharmony_ci	/*
3662306a36Sopenharmony_ci	 * Because of broken hardware we have to enable interrupts or the CPU
3762306a36Sopenharmony_ci	 * will never wakeup... Acctualy it is not very good to enable
3862306a36Sopenharmony_ci	 * interrupts first since scheduler can miss a tick, but there is
3962306a36Sopenharmony_ci	 * no other way around this. Platforms that needs it for power saving
4062306a36Sopenharmony_ci	 * should enable it in init code, since by default it is
4162306a36Sopenharmony_ci	 * disabled.
4262306a36Sopenharmony_ci	 */
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	/* FIXME: Enabling interrupts here is racy! */
4562306a36Sopenharmony_ci	raw_local_irq_enable();
4662306a36Sopenharmony_ci	cpu_do_idle();
4762306a36Sopenharmony_ci	raw_local_irq_disable();
4862306a36Sopenharmony_ci}
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cistatic void __init gemini_init_machine(void)
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	arm_pm_idle = gemini_idle;
5362306a36Sopenharmony_ci}
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_cistatic const char *gemini_board_compat[] = {
5662306a36Sopenharmony_ci	"cortina,gemini",
5762306a36Sopenharmony_ci	NULL,
5862306a36Sopenharmony_ci};
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ciDT_MACHINE_START(GEMINI_DT, "Gemini (Device Tree)")
6162306a36Sopenharmony_ci	.map_io		= gemini_map_io,
6262306a36Sopenharmony_ci	.init_machine	= gemini_init_machine,
6362306a36Sopenharmony_ci	.dt_compat	= gemini_board_compat,
6462306a36Sopenharmony_ciMACHINE_END
65