1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <linux/reboot.h> 4 #include <linux/serial_core.h> 5 #include <clocksource/timer-goldfish.h> 6 7 #include <asm/bootinfo.h> 8 #include <asm/bootinfo-virt.h> 9 #include <asm/byteorder.h> 10 #include <asm/machdep.h> 11 #include <asm/virt.h> 12 #include <asm/config.h> 13 14 struct virt_booter_data virt_bi_data; 15 16 #define VIRT_CTRL_REG_FEATURES 0x00 17 #define VIRT_CTRL_REG_CMD 0x04 18 19 static struct resource ctrlres; 20 21 enum { 22 CMD_NOOP, 23 CMD_RESET, 24 CMD_HALT, 25 CMD_PANIC, 26 }; 27 28 static void virt_get_model(char *str) 29 { 30 /* str is 80 characters long */ 31 sprintf(str, "QEMU Virtual M68K Machine (%u.%u.%u)", 32 (u8)(virt_bi_data.qemu_version >> 24), 33 (u8)(virt_bi_data.qemu_version >> 16), 34 (u8)(virt_bi_data.qemu_version >> 8)); 35 } 36 37 static void virt_halt(void) 38 { 39 void __iomem *base = (void __iomem *)virt_bi_data.ctrl.mmio; 40 41 iowrite32be(CMD_HALT, base + VIRT_CTRL_REG_CMD); 42 local_irq_disable(); 43 while (1) 44 ; 45 } 46 47 static void virt_reset(void) 48 { 49 void __iomem *base = (void __iomem *)virt_bi_data.ctrl.mmio; 50 51 iowrite32be(CMD_RESET, base + VIRT_CTRL_REG_CMD); 52 local_irq_disable(); 53 while (1) 54 ; 55 } 56 57 /* 58 * Parse a virtual-m68k-specific record in the bootinfo 59 */ 60 61 int __init virt_parse_bootinfo(const struct bi_record *record) 62 { 63 int unknown = 0; 64 const void *data = record->data; 65 66 switch (be16_to_cpu(record->tag)) { 67 case BI_VIRT_QEMU_VERSION: 68 virt_bi_data.qemu_version = be32_to_cpup(data); 69 break; 70 case BI_VIRT_GF_PIC_BASE: 71 virt_bi_data.pic.mmio = be32_to_cpup(data); 72 data += 4; 73 virt_bi_data.pic.irq = be32_to_cpup(data); 74 break; 75 case BI_VIRT_GF_RTC_BASE: 76 virt_bi_data.rtc.mmio = be32_to_cpup(data); 77 data += 4; 78 virt_bi_data.rtc.irq = be32_to_cpup(data); 79 break; 80 case BI_VIRT_GF_TTY_BASE: 81 virt_bi_data.tty.mmio = be32_to_cpup(data); 82 data += 4; 83 virt_bi_data.tty.irq = be32_to_cpup(data); 84 break; 85 case BI_VIRT_CTRL_BASE: 86 virt_bi_data.ctrl.mmio = be32_to_cpup(data); 87 data += 4; 88 virt_bi_data.ctrl.irq = be32_to_cpup(data); 89 break; 90 case BI_VIRT_VIRTIO_BASE: 91 virt_bi_data.virtio.mmio = be32_to_cpup(data); 92 data += 4; 93 virt_bi_data.virtio.irq = be32_to_cpup(data); 94 break; 95 default: 96 unknown = 1; 97 break; 98 } 99 return unknown; 100 } 101 102 static void __init virt_sched_init(void) 103 { 104 goldfish_timer_init(virt_bi_data.rtc.irq, 105 (void __iomem *)virt_bi_data.rtc.mmio); 106 } 107 108 void __init config_virt(void) 109 { 110 char earlycon[24]; 111 112 snprintf(earlycon, sizeof(earlycon), "early_gf_tty,0x%08x", 113 virt_bi_data.tty.mmio); 114 setup_earlycon(earlycon); 115 116 ctrlres = (struct resource) 117 DEFINE_RES_MEM_NAMED(virt_bi_data.ctrl.mmio, 0x100, 118 "virtctrl"); 119 120 if (request_resource(&iomem_resource, &ctrlres)) { 121 pr_err("Cannot allocate virt controller resource\n"); 122 return; 123 } 124 125 mach_init_IRQ = virt_init_IRQ; 126 mach_sched_init = virt_sched_init; 127 mach_get_model = virt_get_model; 128 mach_reset = virt_reset; 129 mach_halt = virt_halt; 130 131 register_platform_power_off(virt_halt); 132 } 133