162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * arch/xtensa/platforms/xt2000/setup.c
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Platform specific functions for the XT2000 board.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Authors:	Chris Zankel <chris@zankel.net>
862306a36Sopenharmony_ci *		Joe Taylor <joe@tensilica.com>
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci * Copyright 2001 - 2004 Tensilica Inc.
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci#include <linux/stddef.h>
1362306a36Sopenharmony_ci#include <linux/kernel.h>
1462306a36Sopenharmony_ci#include <linux/init.h>
1562306a36Sopenharmony_ci#include <linux/errno.h>
1662306a36Sopenharmony_ci#include <linux/reboot.h>
1762306a36Sopenharmony_ci#include <linux/kdev_t.h>
1862306a36Sopenharmony_ci#include <linux/types.h>
1962306a36Sopenharmony_ci#include <linux/major.h>
2062306a36Sopenharmony_ci#include <linux/console.h>
2162306a36Sopenharmony_ci#include <linux/delay.h>
2262306a36Sopenharmony_ci#include <linux/stringify.h>
2362306a36Sopenharmony_ci#include <linux/platform_device.h>
2462306a36Sopenharmony_ci#include <linux/serial.h>
2562306a36Sopenharmony_ci#include <linux/serial_8250.h>
2662306a36Sopenharmony_ci#include <linux/timer.h>
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#include <asm/processor.h>
2962306a36Sopenharmony_ci#include <asm/platform.h>
3062306a36Sopenharmony_ci#include <asm/bootparam.h>
3162306a36Sopenharmony_ci#include <platform/hardware.h>
3262306a36Sopenharmony_ci#include <platform/serial.h>
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci/* Assumes s points to an 8-chr string.  No checking for NULL. */
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_cistatic void led_print (int f, char *s)
3762306a36Sopenharmony_ci{
3862306a36Sopenharmony_ci	unsigned long* led_addr = (unsigned long*) (XT2000_LED_ADDR + 0xE0) + f;
3962306a36Sopenharmony_ci	int i;
4062306a36Sopenharmony_ci	for (i = f; i < 8; i++)
4162306a36Sopenharmony_ci		if ((*led_addr++ = *s++) == 0)
4262306a36Sopenharmony_ci		    break;
4362306a36Sopenharmony_ci}
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_cistatic int xt2000_power_off(struct sys_off_data *unused)
4662306a36Sopenharmony_ci{
4762306a36Sopenharmony_ci	led_print (0, "POWEROFF");
4862306a36Sopenharmony_ci	local_irq_disable();
4962306a36Sopenharmony_ci	while (1);
5062306a36Sopenharmony_ci	return NOTIFY_DONE;
5162306a36Sopenharmony_ci}
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_cistatic int xt2000_restart(struct notifier_block *this,
5462306a36Sopenharmony_ci			  unsigned long event, void *ptr)
5562306a36Sopenharmony_ci{
5662306a36Sopenharmony_ci	/* Flush and reset the mmu, simulate a processor reset, and
5762306a36Sopenharmony_ci	 * jump to the reset vector. */
5862306a36Sopenharmony_ci	cpu_reset();
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	return NOTIFY_DONE;
6162306a36Sopenharmony_ci}
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistatic struct notifier_block xt2000_restart_block = {
6462306a36Sopenharmony_ci	.notifier_call = xt2000_restart,
6562306a36Sopenharmony_ci};
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_civoid __init platform_setup(char** cmdline)
6862306a36Sopenharmony_ci{
6962306a36Sopenharmony_ci	led_print (0, "LINUX   ");
7062306a36Sopenharmony_ci}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci/* Heartbeat. Let the LED blink. */
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_cistatic void xt2000_heartbeat(struct timer_list *unused);
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_cistatic DEFINE_TIMER(heartbeat_timer, xt2000_heartbeat);
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_cistatic void xt2000_heartbeat(struct timer_list *unused)
7962306a36Sopenharmony_ci{
8062306a36Sopenharmony_ci	static int i;
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	led_print(7, i ? "." : " ");
8362306a36Sopenharmony_ci	i ^= 1;
8462306a36Sopenharmony_ci	mod_timer(&heartbeat_timer, jiffies + HZ / 2);
8562306a36Sopenharmony_ci}
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci//#define RS_TABLE_SIZE 2
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci#define _SERIAL_PORT(_base,_irq)					\
9062306a36Sopenharmony_ci{									\
9162306a36Sopenharmony_ci	.mapbase	= (_base),					\
9262306a36Sopenharmony_ci	.membase	= (void*)(_base),				\
9362306a36Sopenharmony_ci	.irq		= (_irq),					\
9462306a36Sopenharmony_ci	.uartclk	= DUART16552_XTAL_FREQ,				\
9562306a36Sopenharmony_ci	.iotype		= UPIO_MEM,					\
9662306a36Sopenharmony_ci	.flags		= UPF_BOOT_AUTOCONF,				\
9762306a36Sopenharmony_ci	.regshift	= 2,						\
9862306a36Sopenharmony_ci}
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_cistatic struct plat_serial8250_port xt2000_serial_data[] = {
10162306a36Sopenharmony_ci#if XCHAL_HAVE_BE
10262306a36Sopenharmony_ci	_SERIAL_PORT(DUART16552_1_ADDR + 3, DUART16552_1_INTNUM),
10362306a36Sopenharmony_ci	_SERIAL_PORT(DUART16552_2_ADDR + 3, DUART16552_2_INTNUM),
10462306a36Sopenharmony_ci#else
10562306a36Sopenharmony_ci	_SERIAL_PORT(DUART16552_1_ADDR, DUART16552_1_INTNUM),
10662306a36Sopenharmony_ci	_SERIAL_PORT(DUART16552_2_ADDR, DUART16552_2_INTNUM),
10762306a36Sopenharmony_ci#endif
10862306a36Sopenharmony_ci	{ }
10962306a36Sopenharmony_ci};
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_cistatic struct platform_device xt2000_serial8250_device = {
11262306a36Sopenharmony_ci	.name		= "serial8250",
11362306a36Sopenharmony_ci	.id		= PLAT8250_DEV_PLATFORM,
11462306a36Sopenharmony_ci	.dev		= {
11562306a36Sopenharmony_ci	    .platform_data = xt2000_serial_data,
11662306a36Sopenharmony_ci	},
11762306a36Sopenharmony_ci};
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_cistatic struct resource xt2000_sonic_res[] = {
12062306a36Sopenharmony_ci	{
12162306a36Sopenharmony_ci		.start = SONIC83934_ADDR,
12262306a36Sopenharmony_ci		.end   = SONIC83934_ADDR + 0xff,
12362306a36Sopenharmony_ci		.flags = IORESOURCE_MEM,
12462306a36Sopenharmony_ci	},
12562306a36Sopenharmony_ci	{
12662306a36Sopenharmony_ci		.start = SONIC83934_INTNUM,
12762306a36Sopenharmony_ci		.end = SONIC83934_INTNUM,
12862306a36Sopenharmony_ci		.flags = IORESOURCE_IRQ,
12962306a36Sopenharmony_ci	},
13062306a36Sopenharmony_ci};
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_cistatic struct platform_device xt2000_sonic_device = {
13362306a36Sopenharmony_ci	.name		= "xtsonic",
13462306a36Sopenharmony_ci	.num_resources	= ARRAY_SIZE(xt2000_sonic_res),
13562306a36Sopenharmony_ci	.resource		= xt2000_sonic_res,
13662306a36Sopenharmony_ci};
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_cistatic int __init xt2000_setup_devinit(void)
13962306a36Sopenharmony_ci{
14062306a36Sopenharmony_ci	platform_device_register(&xt2000_serial8250_device);
14162306a36Sopenharmony_ci	platform_device_register(&xt2000_sonic_device);
14262306a36Sopenharmony_ci	mod_timer(&heartbeat_timer, jiffies + HZ / 2);
14362306a36Sopenharmony_ci	register_restart_handler(&xt2000_restart_block);
14462306a36Sopenharmony_ci	register_sys_off_handler(SYS_OFF_MODE_POWER_OFF,
14562306a36Sopenharmony_ci				 SYS_OFF_PRIO_DEFAULT,
14662306a36Sopenharmony_ci				 xt2000_power_off, NULL);
14762306a36Sopenharmony_ci	return 0;
14862306a36Sopenharmony_ci}
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_cidevice_initcall(xt2000_setup_devinit);
151