]>
Commit | Line | Data |
---|---|---|
fe0fe473 AF |
1 | /* |
2 | * QEMU RISC-V Board Compatible with OpenTitan FPGA platform | |
3 | * | |
4 | * Copyright (c) 2020 Western Digital | |
5 | * | |
6 | * Provides a board compatible with the OpenTitan FPGA platform: | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify it | |
9 | * under the terms and conditions of the GNU General Public License, | |
10 | * version 2 or later, as published by the Free Software Foundation. | |
11 | * | |
12 | * This program is distributed in the hope it will be useful, but WITHOUT | |
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
15 | * more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License along with | |
18 | * this program. If not, see <http://www.gnu.org/licenses/>. | |
19 | */ | |
20 | ||
21 | #include "qemu/osdep.h" | |
22 | #include "hw/riscv/opentitan.h" | |
23 | #include "qapi/error.h" | |
24 | #include "hw/boards.h" | |
25 | #include "hw/misc/unimp.h" | |
26 | #include "hw/riscv/boot.h" | |
27 | #include "exec/address-spaces.h" | |
28 | ||
29 | static const struct MemmapEntry { | |
30 | hwaddr base; | |
31 | hwaddr size; | |
32 | } ibex_memmap[] = { | |
33 | [IBEX_ROM] = { 0x00008000, 0xc000 }, | |
34 | [IBEX_RAM] = { 0x10000000, 0x10000 }, | |
35 | [IBEX_FLASH] = { 0x20000000, 0x80000 }, | |
36 | [IBEX_UART] = { 0x40000000, 0x10000 }, | |
37 | [IBEX_GPIO] = { 0x40010000, 0x10000 }, | |
38 | [IBEX_SPI] = { 0x40020000, 0x10000 }, | |
39 | [IBEX_FLASH_CTRL] = { 0x40030000, 0x10000 }, | |
40 | [IBEX_PINMUX] = { 0x40070000, 0x10000 }, | |
41 | [IBEX_RV_TIMER] = { 0x40080000, 0x10000 }, | |
42 | [IBEX_PLIC] = { 0x40090000, 0x10000 }, | |
43 | [IBEX_PWRMGR] = { 0x400A0000, 0x10000 }, | |
44 | [IBEX_RSTMGR] = { 0x400B0000, 0x10000 }, | |
45 | [IBEX_CLKMGR] = { 0x400C0000, 0x10000 }, | |
46 | [IBEX_AES] = { 0x40110000, 0x10000 }, | |
47 | [IBEX_HMAC] = { 0x40120000, 0x10000 }, | |
48 | [IBEX_ALERT_HANDLER] = { 0x40130000, 0x10000 }, | |
49 | [IBEX_NMI_GEN] = { 0x40140000, 0x10000 }, | |
50 | [IBEX_USBDEV] = { 0x40150000, 0x10000 }, | |
51 | [IBEX_PADCTRL] = { 0x40160000, 0x10000 } | |
52 | }; | |
53 | ||
54 | static void riscv_opentitan_init(MachineState *machine) | |
55 | { | |
56 | const struct MemmapEntry *memmap = ibex_memmap; | |
57 | OpenTitanState *s = g_new0(OpenTitanState, 1); | |
58 | MemoryRegion *sys_mem = get_system_memory(); | |
59 | MemoryRegion *main_mem = g_new(MemoryRegion, 1); | |
60 | ||
61 | /* Initialize SoC */ | |
62 | object_initialize_child(OBJECT(machine), "soc", &s->soc, | |
9fc7fc4d | 63 | TYPE_RISCV_IBEX_SOC); |
ce189ab2 | 64 | qdev_realize(DEVICE(&s->soc), NULL, &error_abort); |
fe0fe473 AF |
65 | |
66 | memory_region_init_ram(main_mem, NULL, "riscv.lowrisc.ibex.ram", | |
67 | memmap[IBEX_RAM].size, &error_fatal); | |
68 | memory_region_add_subregion(sys_mem, | |
69 | memmap[IBEX_RAM].base, main_mem); | |
70 | ||
71 | ||
72 | if (machine->firmware) { | |
73 | riscv_load_firmware(machine->firmware, memmap[IBEX_RAM].base, NULL); | |
74 | } | |
75 | ||
76 | if (machine->kernel_filename) { | |
77 | riscv_load_kernel(machine->kernel_filename, NULL); | |
78 | } | |
79 | } | |
80 | ||
81 | static void riscv_opentitan_machine_init(MachineClass *mc) | |
82 | { | |
83 | mc->desc = "RISC-V Board compatible with OpenTitan"; | |
84 | mc->init = riscv_opentitan_init; | |
85 | mc->max_cpus = 1; | |
86 | mc->default_cpu_type = TYPE_RISCV_CPU_IBEX; | |
87 | } | |
88 | ||
89 | DEFINE_MACHINE("opentitan", riscv_opentitan_machine_init) | |
90 | ||
91 | static void riscv_lowrisc_ibex_soc_init(Object *obj) | |
92 | { | |
93 | LowRISCIbexSoCState *s = RISCV_IBEX_SOC(obj); | |
94 | ||
db873cc5 | 95 | object_initialize_child(obj, "cpus", &s->cpus, TYPE_RISCV_HART_ARRAY); |
fe0fe473 AF |
96 | } |
97 | ||
98 | static void riscv_lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp) | |
99 | { | |
100 | const struct MemmapEntry *memmap = ibex_memmap; | |
101 | MachineState *ms = MACHINE(qdev_get_machine()); | |
102 | LowRISCIbexSoCState *s = RISCV_IBEX_SOC(dev_soc); | |
103 | MemoryRegion *sys_mem = get_system_memory(); | |
104 | ||
105 | object_property_set_str(OBJECT(&s->cpus), ms->cpu_type, "cpu-type", | |
106 | &error_abort); | |
107 | object_property_set_int(OBJECT(&s->cpus), ms->smp.cpus, "num-harts", | |
108 | &error_abort); | |
db873cc5 | 109 | sysbus_realize(SYS_BUS_DEVICE(&s->cpus), &error_abort); |
fe0fe473 AF |
110 | |
111 | /* Boot ROM */ | |
112 | memory_region_init_rom(&s->rom, OBJECT(dev_soc), "riscv.lowrisc.ibex.rom", | |
113 | memmap[IBEX_ROM].size, &error_fatal); | |
114 | memory_region_add_subregion(sys_mem, | |
115 | memmap[IBEX_ROM].base, &s->rom); | |
116 | ||
117 | /* Flash memory */ | |
118 | memory_region_init_rom(&s->flash_mem, OBJECT(dev_soc), "riscv.lowrisc.ibex.flash", | |
119 | memmap[IBEX_FLASH].size, &error_fatal); | |
120 | memory_region_add_subregion(sys_mem, memmap[IBEX_FLASH].base, | |
121 | &s->flash_mem); | |
122 | ||
123 | create_unimplemented_device("riscv.lowrisc.ibex.uart", | |
124 | memmap[IBEX_UART].base, memmap[IBEX_UART].size); | |
125 | create_unimplemented_device("riscv.lowrisc.ibex.gpio", | |
126 | memmap[IBEX_GPIO].base, memmap[IBEX_GPIO].size); | |
127 | create_unimplemented_device("riscv.lowrisc.ibex.spi", | |
128 | memmap[IBEX_SPI].base, memmap[IBEX_SPI].size); | |
129 | create_unimplemented_device("riscv.lowrisc.ibex.flash_ctrl", | |
130 | memmap[IBEX_FLASH_CTRL].base, memmap[IBEX_FLASH_CTRL].size); | |
131 | create_unimplemented_device("riscv.lowrisc.ibex.rv_timer", | |
132 | memmap[IBEX_RV_TIMER].base, memmap[IBEX_RV_TIMER].size); | |
133 | create_unimplemented_device("riscv.lowrisc.ibex.pwrmgr", | |
134 | memmap[IBEX_PWRMGR].base, memmap[IBEX_PWRMGR].size); | |
135 | create_unimplemented_device("riscv.lowrisc.ibex.rstmgr", | |
136 | memmap[IBEX_RSTMGR].base, memmap[IBEX_RSTMGR].size); | |
137 | create_unimplemented_device("riscv.lowrisc.ibex.clkmgr", | |
138 | memmap[IBEX_CLKMGR].base, memmap[IBEX_CLKMGR].size); | |
139 | create_unimplemented_device("riscv.lowrisc.ibex.aes", | |
140 | memmap[IBEX_AES].base, memmap[IBEX_AES].size); | |
141 | create_unimplemented_device("riscv.lowrisc.ibex.hmac", | |
142 | memmap[IBEX_HMAC].base, memmap[IBEX_HMAC].size); | |
143 | create_unimplemented_device("riscv.lowrisc.ibex.plic", | |
144 | memmap[IBEX_PLIC].base, memmap[IBEX_PLIC].size); | |
145 | create_unimplemented_device("riscv.lowrisc.ibex.pinmux", | |
146 | memmap[IBEX_PINMUX].base, memmap[IBEX_PINMUX].size); | |
147 | create_unimplemented_device("riscv.lowrisc.ibex.alert_handler", | |
148 | memmap[IBEX_ALERT_HANDLER].base, memmap[IBEX_ALERT_HANDLER].size); | |
149 | create_unimplemented_device("riscv.lowrisc.ibex.nmi_gen", | |
150 | memmap[IBEX_NMI_GEN].base, memmap[IBEX_NMI_GEN].size); | |
151 | create_unimplemented_device("riscv.lowrisc.ibex.usbdev", | |
152 | memmap[IBEX_USBDEV].base, memmap[IBEX_USBDEV].size); | |
153 | create_unimplemented_device("riscv.lowrisc.ibex.padctrl", | |
154 | memmap[IBEX_PADCTRL].base, memmap[IBEX_PADCTRL].size); | |
155 | } | |
156 | ||
157 | static void riscv_lowrisc_ibex_soc_class_init(ObjectClass *oc, void *data) | |
158 | { | |
159 | DeviceClass *dc = DEVICE_CLASS(oc); | |
160 | ||
161 | dc->realize = riscv_lowrisc_ibex_soc_realize; | |
162 | /* Reason: Uses serial_hds in realize function, thus can't be used twice */ | |
163 | dc->user_creatable = false; | |
164 | } | |
165 | ||
166 | static const TypeInfo riscv_lowrisc_ibex_soc_type_info = { | |
167 | .name = TYPE_RISCV_IBEX_SOC, | |
168 | .parent = TYPE_DEVICE, | |
169 | .instance_size = sizeof(LowRISCIbexSoCState), | |
170 | .instance_init = riscv_lowrisc_ibex_soc_init, | |
171 | .class_init = riscv_lowrisc_ibex_soc_class_init, | |
172 | }; | |
173 | ||
174 | static void riscv_lowrisc_ibex_soc_register_types(void) | |
175 | { | |
176 | type_register_static(&riscv_lowrisc_ibex_soc_type_info); | |
177 | } | |
178 | ||
179 | type_init(riscv_lowrisc_ibex_soc_register_types) |