Commit | Line | Data |
---|---|---|
05d51e42 LV |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | ||
cfd6d63e | 3 | #include <linux/reboot.h> |
05d51e42 LV |
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; | |
cfd6d63e GU |
130 | |
131 | register_platform_power_off(virt_halt); | |
05d51e42 | 132 | } |