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