1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * arch/xtensa/platforms/xt2000/setup.c 4 * 5 * Platform specific functions for the XT2000 board. 6 * 7 * Authors: Chris Zankel <chris@zankel.net> 8 * Joe Taylor <joe@tensilica.com> 9 * 10 * Copyright 2001 - 2004 Tensilica Inc. 11 */ 12#include <linux/stddef.h> 13#include <linux/kernel.h> 14#include <linux/init.h> 15#include <linux/errno.h> 16#include <linux/reboot.h> 17#include <linux/kdev_t.h> 18#include <linux/types.h> 19#include <linux/major.h> 20#include <linux/console.h> 21#include <linux/delay.h> 22#include <linux/stringify.h> 23#include <linux/platform_device.h> 24#include <linux/serial.h> 25#include <linux/serial_8250.h> 26#include <linux/timer.h> 27 28#include <asm/processor.h> 29#include <asm/platform.h> 30#include <asm/bootparam.h> 31#include <platform/hardware.h> 32#include <platform/serial.h> 33 34/* Assumes s points to an 8-chr string. No checking for NULL. */ 35 36static void led_print (int f, char *s) 37{ 38 unsigned long* led_addr = (unsigned long*) (XT2000_LED_ADDR + 0xE0) + f; 39 int i; 40 for (i = f; i < 8; i++) 41 if ((*led_addr++ = *s++) == 0) 42 break; 43} 44 45static int xt2000_power_off(struct sys_off_data *unused) 46{ 47 led_print (0, "POWEROFF"); 48 local_irq_disable(); 49 while (1); 50 return NOTIFY_DONE; 51} 52 53static int xt2000_restart(struct notifier_block *this, 54 unsigned long event, void *ptr) 55{ 56 /* Flush and reset the mmu, simulate a processor reset, and 57 * jump to the reset vector. */ 58 cpu_reset(); 59 60 return NOTIFY_DONE; 61} 62 63static struct notifier_block xt2000_restart_block = { 64 .notifier_call = xt2000_restart, 65}; 66 67void __init platform_setup(char** cmdline) 68{ 69 led_print (0, "LINUX "); 70} 71 72/* Heartbeat. Let the LED blink. */ 73 74static void xt2000_heartbeat(struct timer_list *unused); 75 76static DEFINE_TIMER(heartbeat_timer, xt2000_heartbeat); 77 78static void xt2000_heartbeat(struct timer_list *unused) 79{ 80 static int i; 81 82 led_print(7, i ? "." : " "); 83 i ^= 1; 84 mod_timer(&heartbeat_timer, jiffies + HZ / 2); 85} 86 87//#define RS_TABLE_SIZE 2 88 89#define _SERIAL_PORT(_base,_irq) \ 90{ \ 91 .mapbase = (_base), \ 92 .membase = (void*)(_base), \ 93 .irq = (_irq), \ 94 .uartclk = DUART16552_XTAL_FREQ, \ 95 .iotype = UPIO_MEM, \ 96 .flags = UPF_BOOT_AUTOCONF, \ 97 .regshift = 2, \ 98} 99 100static struct plat_serial8250_port xt2000_serial_data[] = { 101#if XCHAL_HAVE_BE 102 _SERIAL_PORT(DUART16552_1_ADDR + 3, DUART16552_1_INTNUM), 103 _SERIAL_PORT(DUART16552_2_ADDR + 3, DUART16552_2_INTNUM), 104#else 105 _SERIAL_PORT(DUART16552_1_ADDR, DUART16552_1_INTNUM), 106 _SERIAL_PORT(DUART16552_2_ADDR, DUART16552_2_INTNUM), 107#endif 108 { } 109}; 110 111static struct platform_device xt2000_serial8250_device = { 112 .name = "serial8250", 113 .id = PLAT8250_DEV_PLATFORM, 114 .dev = { 115 .platform_data = xt2000_serial_data, 116 }, 117}; 118 119static struct resource xt2000_sonic_res[] = { 120 { 121 .start = SONIC83934_ADDR, 122 .end = SONIC83934_ADDR + 0xff, 123 .flags = IORESOURCE_MEM, 124 }, 125 { 126 .start = SONIC83934_INTNUM, 127 .end = SONIC83934_INTNUM, 128 .flags = IORESOURCE_IRQ, 129 }, 130}; 131 132static struct platform_device xt2000_sonic_device = { 133 .name = "xtsonic", 134 .num_resources = ARRAY_SIZE(xt2000_sonic_res), 135 .resource = xt2000_sonic_res, 136}; 137 138static int __init xt2000_setup_devinit(void) 139{ 140 platform_device_register(&xt2000_serial8250_device); 141 platform_device_register(&xt2000_sonic_device); 142 mod_timer(&heartbeat_timer, jiffies + HZ / 2); 143 register_restart_handler(&xt2000_restart_block); 144 register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, 145 SYS_OFF_PRIO_DEFAULT, 146 xt2000_power_off, NULL); 147 return 0; 148} 149 150device_initcall(xt2000_setup_devinit); 151