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 36 static 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 45 static 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 53 static 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 63 static struct notifier_block xt2000_restart_block = { 64 .notifier_call = xt2000_restart, 65 }; 66 67 void __init platform_setup(char** cmdline) 68 { 69 led_print (0, "LINUX "); 70 } 71 72 /* Heartbeat. Let the LED blink. */ 73 74 static void xt2000_heartbeat(struct timer_list *unused); 75 76 static DEFINE_TIMER(heartbeat_timer, xt2000_heartbeat); 77 78 static 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 100 static 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 111 static 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 119 static 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 132 static struct platform_device xt2000_sonic_device = { 133 .name = "xtsonic", 134 .num_resources = ARRAY_SIZE(xt2000_sonic_res), 135 .resource = xt2000_sonic_res, 136 }; 137 138 static 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 150 device_initcall(xt2000_setup_devinit); 151