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 sys_off_data *unused) 54 { 55 /* Flush and reset the mmu, simulate a processor reset, and 56 * jump to the reset vector. */ 57 cpu_reset(); 58 59 return NOTIFY_DONE; 60 } 61 62 void __init platform_setup(char** cmdline) 63 { 64 led_print (0, "LINUX "); 65 } 66 67 /* Heartbeat. Let the LED blink. */ 68 69 static void xt2000_heartbeat(struct timer_list *unused); 70 71 static DEFINE_TIMER(heartbeat_timer, xt2000_heartbeat); 72 73 static void xt2000_heartbeat(struct timer_list *unused) 74 { 75 static int i; 76 77 led_print(7, i ? "." : " "); 78 i ^= 1; 79 mod_timer(&heartbeat_timer, jiffies + HZ / 2); 80 } 81 82 //#define RS_TABLE_SIZE 2 83 84 #define _SERIAL_PORT(_base,_irq) \ 85 { \ 86 .mapbase = (_base), \ 87 .membase = (void*)(_base), \ 88 .irq = (_irq), \ 89 .uartclk = DUART16552_XTAL_FREQ, \ 90 .iotype = UPIO_MEM, \ 91 .flags = UPF_BOOT_AUTOCONF, \ 92 .regshift = 2, \ 93 } 94 95 static struct plat_serial8250_port xt2000_serial_data[] = { 96 #if XCHAL_HAVE_BE 97 _SERIAL_PORT(DUART16552_1_ADDR + 3, DUART16552_1_INTNUM), 98 _SERIAL_PORT(DUART16552_2_ADDR + 3, DUART16552_2_INTNUM), 99 #else 100 _SERIAL_PORT(DUART16552_1_ADDR, DUART16552_1_INTNUM), 101 _SERIAL_PORT(DUART16552_2_ADDR, DUART16552_2_INTNUM), 102 #endif 103 { } 104 }; 105 106 static struct platform_device xt2000_serial8250_device = { 107 .name = "serial8250", 108 .id = PLAT8250_DEV_PLATFORM, 109 .dev = { 110 .platform_data = xt2000_serial_data, 111 }, 112 }; 113 114 static struct resource xt2000_sonic_res[] = { 115 { 116 .start = SONIC83934_ADDR, 117 .end = SONIC83934_ADDR + 0xff, 118 .flags = IORESOURCE_MEM, 119 }, 120 { 121 .start = SONIC83934_INTNUM, 122 .end = SONIC83934_INTNUM, 123 .flags = IORESOURCE_IRQ, 124 }, 125 }; 126 127 static struct platform_device xt2000_sonic_device = { 128 .name = "xtsonic", 129 .num_resources = ARRAY_SIZE(xt2000_sonic_res), 130 .resource = xt2000_sonic_res, 131 }; 132 133 static int __init xt2000_setup_devinit(void) 134 { 135 platform_device_register(&xt2000_serial8250_device); 136 platform_device_register(&xt2000_sonic_device); 137 mod_timer(&heartbeat_timer, jiffies + HZ / 2); 138 register_sys_off_handler(SYS_OFF_MODE_RESTART, 139 SYS_OFF_PRIO_PLATFORM, 140 xt2000_restart, NULL); 141 register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, 142 SYS_OFF_PRIO_DEFAULT, 143 xt2000_power_off, NULL); 144 return 0; 145 } 146 147 device_initcall(xt2000_setup_devinit); 148