master
c 567 lines 22.4 KB
Raw
1 /*
2 * QEMU RISC-V Virt Board Compatible with Kendryte K230 SDK
3 *
4 * Copyright (c) 2025 Chao Liu <chao.liu.zevorn@gmail.com>
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 *
8 * Provides a board compatible with the Kendryte K230 SDK
9 *
10 * K230 Technical Reference Manual V0.3.1 (2024-11-18):
11 * https://github.com/revyos/external-docs/blob/master/K230/en-us/K230_Technical_Reference_Manual_V0.3.1_20241118.pdf
12 *
13 * For more information, see <https://www.kendryte.com/en/proDetail/230>
14 */
15
16 #include "qemu/osdep.h"
17 #include "cpu-qom.h"
18 #include "qemu/cutils.h"
19 #include "qemu/error-report.h"
20 #include "qapi/error.h"
21 #include "system/device_tree.h"
22 #include "system/system.h"
23 #include "system/memory.h"
24 #include "target/riscv/cpu.h"
25 #include "hw/core/loader.h"
26 #include "hw/core/sysbus.h"
27 #include "hw/riscv/k230.h"
28 #include "hw/riscv/boot.h"
29 #include "hw/riscv/machines-qom.h"
30 #include "hw/intc/riscv_aclint.h"
31 #include "hw/intc/sifive_plic.h"
32 #include "hw/char/serial-mm.h"
33 #include "hw/misc/unimp.h"
34
35 /* Align K230_SDK k230_canmv_defconfig */
36 #define K230_DIRECT_OPENSBI_ADDR 0x8000000
37 #define K230_DIRECT_KERNEL_ADDR 0x8200000
38 #define K230_DIRECT_DTB_ADDR 0xa000000
39
40 static const MemMapEntry memmap[] = {
41 [K230_DEV_DDRC] = { 0x00000000, 0x80000000 },
42 [K230_DEV_KPU_L2_CACHE] = { 0x80000000, 0x00200000 },
43 [K230_DEV_SRAM] = { 0x80200000, 0x00200000 },
44 [K230_DEV_KPU_CFG] = { 0x80400000, 0x00000800 },
45 [K230_DEV_FFT] = { 0x80400800, 0x00000400 },
46 [K230_DEV_AI_2D_ENGINE] = { 0x80400C00, 0x00000800 },
47 [K230_DEV_GSDMA] = { 0x80800000, 0x00004000 },
48 [K230_DEV_DMA] = { 0x80804000, 0x00004000 },
49 [K230_DEV_DECOMP_GZIP] = { 0x80808000, 0x00004000 },
50 [K230_DEV_NON_AI_2D] = { 0x8080C000, 0x00004000 },
51 [K230_DEV_ISP] = { 0x90000000, 0x00008000 },
52 [K230_DEV_DEWARP] = { 0x90008000, 0x00001000 },
53 [K230_DEV_RX_CSI] = { 0x90009000, 0x00002000 },
54 [K230_DEV_H264] = { 0x90400000, 0x00010000 },
55 [K230_DEV_2P5D] = { 0x90800000, 0x00040000 },
56 [K230_DEV_VO] = { 0x90840000, 0x00010000 },
57 [K230_DEV_VO_CFG] = { 0x90850000, 0x00001000 },
58 [K230_DEV_3D_ENGINE] = { 0x90A00000, 0x00000800 },
59 [K230_DEV_PMU] = { 0x91000000, 0x00000C00 },
60 [K230_DEV_RTC] = { 0x91000C00, 0x00000400 },
61 [K230_DEV_CMU] = { 0x91100000, 0x00001000 },
62 [K230_DEV_RMU] = { 0x91101000, 0x00001000 },
63 [K230_DEV_BOOT] = { 0x91102000, 0x00001000 },
64 [K230_DEV_PWR] = { 0x91103000, 0x00001000 },
65 [K230_DEV_MAILBOX] = { 0x91104000, 0x00001000 },
66 [K230_DEV_IOMUX] = { 0x91105000, 0x00000800 },
67 [K230_DEV_TIMER] = { 0x91105800, 0x00000800 },
68 [K230_DEV_WDT0] = { 0x91106000, 0x00000800 },
69 [K230_DEV_WDT1] = { 0x91106800, 0x00000800 },
70 [K230_DEV_TS] = { 0x91107000, 0x00000800 },
71 [K230_DEV_HDI] = { 0x91107800, 0x00000800 },
72 [K230_DEV_STC] = { 0x91108000, 0x00000800 },
73 [K230_DEV_BOOTROM] = { 0x91200000, 0x00010000 },
74 [K230_DEV_SECURITY] = { 0x91210000, 0x00008000 },
75 [K230_DEV_UART0] = { 0x91400000, 0x00001000 },
76 [K230_DEV_UART1] = { 0x91401000, 0x00001000 },
77 [K230_DEV_UART2] = { 0x91402000, 0x00001000 },
78 [K230_DEV_UART3] = { 0x91403000, 0x00001000 },
79 [K230_DEV_UART4] = { 0x91404000, 0x00001000 },
80 [K230_DEV_I2C0] = { 0x91405000, 0x00001000 },
81 [K230_DEV_I2C1] = { 0x91406000, 0x00001000 },
82 [K230_DEV_I2C2] = { 0x91407000, 0x00001000 },
83 [K230_DEV_I2C3] = { 0x91408000, 0x00001000 },
84 [K230_DEV_I2C4] = { 0x91409000, 0x00001000 },
85 [K230_DEV_PWM] = { 0x9140A000, 0x00001000 },
86 [K230_DEV_GPIO0] = { 0x9140B000, 0x00001000 },
87 [K230_DEV_GPIO1] = { 0x9140C000, 0x00001000 },
88 [K230_DEV_ADC] = { 0x9140D000, 0x00001000 },
89 [K230_DEV_CODEC] = { 0x9140E000, 0x00001000 },
90 [K230_DEV_I2S] = { 0x9140F000, 0x00001000 },
91 [K230_DEV_USB0] = { 0x91500000, 0x00010000 },
92 [K230_DEV_USB1] = { 0x91540000, 0x00010000 },
93 [K230_DEV_SD0] = { 0x91580000, 0x00001000 },
94 [K230_DEV_SD1] = { 0x91581000, 0x00001000 },
95 [K230_DEV_QSPI0] = { 0x91582000, 0x00001000 },
96 [K230_DEV_QSPI1] = { 0x91583000, 0x00001000 },
97 [K230_DEV_SPI] = { 0x91584000, 0x00001000 },
98 [K230_DEV_HI_SYS_CFG] = { 0x91585000, 0x00000400 },
99 [K230_DEV_DDRC_CFG] = { 0x98000000, 0x02000000 },
100 [K230_DEV_DDR_PHY] = { 0x9A000000, 0x00400000 },
101 [K230_DEV_FLASH] = { 0xC0000000, 0x08000000 },
102 [K230_DEV_PLIC] = { 0xF00000000, 0x00400000 },
103 [K230_DEV_CLINT] = { 0xF04000000, 0x00400000 },
104 };
105
106 static void k230_soc_init(Object *obj)
107 {
108 K230SoCState *s = RISCV_K230_SOC(obj);
109 RISCVHartArrayState *cpu0 = &s->c908_cpu;
110
111 object_initialize_child(obj, "c908-cpu", cpu0, TYPE_RISCV_HART_ARRAY);
112 object_initialize_child(obj, "ddr-cfg", &s->ddr_cfg,
113 TYPE_K230_DDR_CFG);
114 object_initialize_child(obj, "ddr-phy", &s->ddr_phy,
115 TYPE_K230_DDR_PHY);
116 s->ddr_cfg.phy = &s->ddr_phy;
117 object_initialize_child(obj, "k230-wdt0", &s->wdt[0], TYPE_K230_WDT);
118 object_initialize_child(obj, "k230-wdt1", &s->wdt[1], TYPE_K230_WDT);
119 object_initialize_child(obj, "k230-gsdma", &s->gsdma, TYPE_K230_GSDMA);
120 object_initialize_child(obj, "k230-decomp-gzip", &s->decomp_gzip,
121 TYPE_K230_DECOMP_GZIP);
122
123 qdev_prop_set_uint32(DEVICE(cpu0), "hartid-base", 0);
124 qdev_prop_set_string(DEVICE(cpu0), "cpu-type", TYPE_RISCV_CPU_THEAD_C908);
125 qdev_prop_set_uint64(DEVICE(cpu0), "resetvec",
126 memmap[K230_DEV_BOOTROM].base);
127 }
128
129 static DeviceState *k230_create_plic(int base_hartid, int hartid_count)
130 {
131 g_autofree char *plic_hart_config = NULL;
132
133 /* Per-socket PLIC hart topology configuration string */
134 plic_hart_config = riscv_plic_hart_config_string(hartid_count);
135
136 /* Per-socket PLIC */
137 return sifive_plic_create(memmap[K230_DEV_PLIC].base,
138 plic_hart_config, hartid_count, base_hartid,
139 K230_PLIC_NUM_SOURCES,
140 K230_PLIC_NUM_PRIORITIES,
141 K230_PLIC_PRIORITY_BASE, K230_PLIC_PENDING_BASE,
142 K230_PLIC_ENABLE_BASE, K230_PLIC_ENABLE_STRIDE,
143 K230_PLIC_CONTEXT_BASE,
144 K230_PLIC_CONTEXT_STRIDE,
145 memmap[K230_DEV_PLIC].size);
146 }
147
148 static void k230_create_uart(MemoryRegion *sys_mem, DeviceState *plic,
149 int index)
150 {
151 int uart_dev = K230_DEV_UART0 + index;
152 g_autofree char *name = g_strdup_printf("uart%d", index);
153
154 /* Cover the non-16550 part of the SDK's 0x1000 UART window. */
155 create_unimplemented_device(name, memmap[uart_dev].base,
156 memmap[uart_dev].size);
157
158 serial_mm_init(sys_mem, memmap[uart_dev].base, 2,
159 qdev_get_gpio_in(plic, K230_UART0_IRQ + index),
160 399193, serial_hd(index), DEVICE_LITTLE_ENDIAN);
161 }
162
163 static void k230_soc_realize(DeviceState *dev, Error **errp)
164 {
165 K230SoCState *s = RISCV_K230_SOC(dev);
166 MemoryRegion *sys_mem = get_system_memory();
167 int c908_cpus;
168
169 sysbus_realize(SYS_BUS_DEVICE(&s->c908_cpu), &error_fatal);
170 if (!sysbus_realize(SYS_BUS_DEVICE(&s->ddr_cfg), errp)) {
171 return;
172 }
173 if (!sysbus_realize(SYS_BUS_DEVICE(&s->ddr_phy), errp)) {
174 return;
175 }
176 sysbus_mmio_map(SYS_BUS_DEVICE(&s->ddr_cfg), 0,
177 memmap[K230_DEV_DDRC_CFG].base);
178 sysbus_mmio_map(SYS_BUS_DEVICE(&s->ddr_phy), 0,
179 memmap[K230_DEV_DDR_PHY].base);
180
181 c908_cpus = s->c908_cpu.num_harts;
182
183 /* SRAM */
184 memory_region_init_ram(&s->sram, OBJECT(dev), "sram",
185 memmap[K230_DEV_SRAM].size, &error_fatal);
186 memory_region_add_subregion(sys_mem, memmap[K230_DEV_SRAM].base,
187 &s->sram);
188
189 /* BootROM */
190 memory_region_init_rom(&s->bootrom, OBJECT(dev), "bootrom",
191 memmap[K230_DEV_BOOTROM].size, &error_fatal);
192 memory_region_add_subregion(sys_mem, memmap[K230_DEV_BOOTROM].base,
193 &s->bootrom);
194
195 /* PLIC */
196 s->c908_plic = k230_create_plic(C908_CPU_HARTID, c908_cpus);
197
198 /* CLINT */
199 riscv_aclint_swi_create(memmap[K230_DEV_CLINT].base,
200 C908_CPU_HARTID, c908_cpus, false);
201 riscv_aclint_mtimer_create(memmap[K230_DEV_CLINT].base + 0x4000,
202 RISCV_ACLINT_DEFAULT_MTIMER_SIZE,
203 C908_CPU_HARTID, c908_cpus,
204 RISCV_ACLINT_DEFAULT_MTIMECMP,
205 RISCV_ACLINT_DEFAULT_MTIME,
206 RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, true);
207
208 /* UART */
209 for (int i = 0; i < K230_UART_COUNT; i++) {
210 k230_create_uart(sys_mem, DEVICE(s->c908_plic), i);
211 }
212
213 /* Watchdog */
214 for (int i = 0; i < 2; i++) {
215 if (!sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), errp)) {
216 return;
217 }
218 }
219
220 sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[0]), 0, memmap[K230_DEV_WDT0].base);
221 sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt[0]), 0,
222 qdev_get_gpio_in(DEVICE(s->c908_plic), K230_WDT0_IRQ));
223
224 sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[1]), 0, memmap[K230_DEV_WDT1].base);
225 sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt[1]), 0,
226 qdev_get_gpio_in(DEVICE(s->c908_plic), K230_WDT1_IRQ));
227
228 /* Gsdma */
229 if (!sysbus_realize(SYS_BUS_DEVICE(&s->gsdma), errp)) {
230 return;
231 }
232 sysbus_mmio_map(SYS_BUS_DEVICE(&s->gsdma), 0, memmap[K230_DEV_GSDMA].base);
233 sysbus_connect_irq(SYS_BUS_DEVICE(&s->gsdma), 0,
234 qdev_get_gpio_in(DEVICE(s->c908_plic), K230_GSDMA_IRQ));
235
236 /* Decomp gzip */
237 qdev_prop_set_uint64(DEVICE(&s->decomp_gzip), "sram-base",
238 memmap[K230_DEV_SRAM].base);
239 if (!sysbus_realize(SYS_BUS_DEVICE(&s->decomp_gzip), errp)) {
240 return;
241 }
242 sysbus_mmio_map(SYS_BUS_DEVICE(&s->decomp_gzip), 0,
243 memmap[K230_DEV_DECOMP_GZIP].base);
244 for (int i = 0; i < K230_DECOMP_GZIP_NUM_GPIOS_OUT; i++) {
245 qdev_connect_gpio_out(DEVICE(&s->decomp_gzip), i,
246 qdev_get_gpio_in(DEVICE(&s->gsdma), i));
247 }
248 for (int i = 0; i < K230_DECOMP_GZIP_NUM_GPIOS_IN; i++) {
249 qdev_connect_gpio_out(DEVICE(&s->gsdma), i,
250 qdev_get_gpio_in(DEVICE(&s->decomp_gzip), i));
251 }
252
253 /* Noc stub, the k230 decomp_gzip driver in uboot will access this region */
254 create_unimplemented_device("noc-stub", 0x91302000, 0x1000);
255
256 /* unimplemented devices */
257 create_unimplemented_device("kpu.l2-cache",
258 memmap[K230_DEV_KPU_L2_CACHE].base,
259 memmap[K230_DEV_KPU_L2_CACHE].size);
260
261 create_unimplemented_device("kpu_cfg", memmap[K230_DEV_KPU_CFG].base,
262 memmap[K230_DEV_KPU_CFG].size);
263
264 create_unimplemented_device("fft", memmap[K230_DEV_FFT].base,
265 memmap[K230_DEV_FFT].size);
266
267 create_unimplemented_device("2d-engine.ai",
268 memmap[K230_DEV_AI_2D_ENGINE].base,
269 memmap[K230_DEV_AI_2D_ENGINE].size);
270
271 create_unimplemented_device("dma", memmap[K230_DEV_DMA].base,
272 memmap[K230_DEV_DMA].size);
273
274 create_unimplemented_device("2d-engine.non-ai",
275 memmap[K230_DEV_NON_AI_2D].base,
276 memmap[K230_DEV_NON_AI_2D].size);
277
278 create_unimplemented_device("isp", memmap[K230_DEV_ISP].base,
279 memmap[K230_DEV_ISP].size);
280
281 create_unimplemented_device("dewarp", memmap[K230_DEV_DEWARP].base,
282 memmap[K230_DEV_DEWARP].size);
283
284 create_unimplemented_device("rx-csi", memmap[K230_DEV_RX_CSI].base,
285 memmap[K230_DEV_RX_CSI].size);
286
287 create_unimplemented_device("vpu", memmap[K230_DEV_H264].base,
288 memmap[K230_DEV_H264].size);
289
290 create_unimplemented_device("gpu", memmap[K230_DEV_2P5D].base,
291 memmap[K230_DEV_2P5D].size);
292
293 create_unimplemented_device("vo", memmap[K230_DEV_VO].base,
294 memmap[K230_DEV_VO].size);
295
296 create_unimplemented_device("vo_cfg", memmap[K230_DEV_VO_CFG].base,
297 memmap[K230_DEV_VO_CFG].size);
298
299 create_unimplemented_device("3d-engine", memmap[K230_DEV_3D_ENGINE].base,
300 memmap[K230_DEV_3D_ENGINE].size);
301
302 create_unimplemented_device("pmu", memmap[K230_DEV_PMU].base,
303 memmap[K230_DEV_PMU].size);
304
305 create_unimplemented_device("rtc", memmap[K230_DEV_RTC].base,
306 memmap[K230_DEV_RTC].size);
307
308 create_unimplemented_device("cmu", memmap[K230_DEV_CMU].base,
309 memmap[K230_DEV_CMU].size);
310
311 create_unimplemented_device("rmu", memmap[K230_DEV_RMU].base,
312 memmap[K230_DEV_RMU].size);
313
314 create_unimplemented_device("boot", memmap[K230_DEV_BOOT].base,
315 memmap[K230_DEV_BOOT].size);
316
317 create_unimplemented_device("pwr", memmap[K230_DEV_PWR].base,
318 memmap[K230_DEV_PWR].size);
319
320 create_unimplemented_device("ipcm", memmap[K230_DEV_MAILBOX].base,
321 memmap[K230_DEV_MAILBOX].size);
322
323 create_unimplemented_device("iomux", memmap[K230_DEV_IOMUX].base,
324 memmap[K230_DEV_IOMUX].size);
325
326 create_unimplemented_device("timer", memmap[K230_DEV_TIMER].base,
327 memmap[K230_DEV_TIMER].size);
328
329 create_unimplemented_device("wdt0", memmap[K230_DEV_WDT0].base,
330 memmap[K230_DEV_WDT0].size);
331
332 create_unimplemented_device("wdt1", memmap[K230_DEV_WDT1].base,
333 memmap[K230_DEV_WDT1].size);
334
335 create_unimplemented_device("ts", memmap[K230_DEV_TS].base,
336 memmap[K230_DEV_TS].size);
337
338 create_unimplemented_device("hdi", memmap[K230_DEV_HDI].base,
339 memmap[K230_DEV_HDI].size);
340
341 create_unimplemented_device("stc", memmap[K230_DEV_STC].base,
342 memmap[K230_DEV_STC].size);
343
344 create_unimplemented_device("security", memmap[K230_DEV_SECURITY].base,
345 memmap[K230_DEV_SECURITY].size);
346
347 create_unimplemented_device("i2c0", memmap[K230_DEV_I2C0].base,
348 memmap[K230_DEV_I2C0].size);
349
350 create_unimplemented_device("i2c1", memmap[K230_DEV_I2C1].base,
351 memmap[K230_DEV_I2C1].size);
352
353 create_unimplemented_device("i2c2", memmap[K230_DEV_I2C2].base,
354 memmap[K230_DEV_I2C2].size);
355
356 create_unimplemented_device("i2c3", memmap[K230_DEV_I2C3].base,
357 memmap[K230_DEV_I2C3].size);
358
359 create_unimplemented_device("i2c4", memmap[K230_DEV_I2C4].base,
360 memmap[K230_DEV_I2C4].size);
361
362 create_unimplemented_device("pwm", memmap[K230_DEV_PWM].base,
363 memmap[K230_DEV_PWM].size);
364
365 create_unimplemented_device("gpio0", memmap[K230_DEV_GPIO0].base,
366 memmap[K230_DEV_GPIO0].size);
367
368 create_unimplemented_device("gpio1", memmap[K230_DEV_GPIO1].base,
369 memmap[K230_DEV_GPIO1].size);
370
371 create_unimplemented_device("adc", memmap[K230_DEV_ADC].base,
372 memmap[K230_DEV_ADC].size);
373
374 create_unimplemented_device("codec", memmap[K230_DEV_CODEC].base,
375 memmap[K230_DEV_CODEC].size);
376
377 create_unimplemented_device("i2s", memmap[K230_DEV_I2S].base,
378 memmap[K230_DEV_I2S].size);
379
380 create_unimplemented_device("usb0", memmap[K230_DEV_USB0].base,
381 memmap[K230_DEV_USB0].size);
382
383 create_unimplemented_device("usb1", memmap[K230_DEV_USB1].base,
384 memmap[K230_DEV_USB1].size);
385
386 create_unimplemented_device("sd0", memmap[K230_DEV_SD0].base,
387 memmap[K230_DEV_SD0].size);
388
389 create_unimplemented_device("sd1", memmap[K230_DEV_SD1].base,
390 memmap[K230_DEV_SD1].size);
391
392 create_unimplemented_device("qspi0", memmap[K230_DEV_QSPI0].base,
393 memmap[K230_DEV_QSPI0].size);
394
395 create_unimplemented_device("qspi1", memmap[K230_DEV_QSPI1].base,
396 memmap[K230_DEV_QSPI1].size);
397
398 create_unimplemented_device("spi", memmap[K230_DEV_SPI].base,
399 memmap[K230_DEV_SPI].size);
400
401 create_unimplemented_device("hi_sys_cfg", memmap[K230_DEV_HI_SYS_CFG].base,
402 memmap[K230_DEV_HI_SYS_CFG].size);
403
404 create_unimplemented_device("flash", memmap[K230_DEV_FLASH].base,
405 memmap[K230_DEV_FLASH].size);
406 }
407
408 static void k230_soc_class_init(ObjectClass *oc, const void *data)
409 {
410 DeviceClass *dc = DEVICE_CLASS(oc);
411
412 dc->realize = k230_soc_realize;
413 }
414
415 static const TypeInfo k230_soc_type_info = {
416 .name = TYPE_RISCV_K230_SOC,
417 .parent = TYPE_DEVICE,
418 .instance_size = sizeof(K230SoCState),
419 .instance_init = k230_soc_init,
420 .class_init = k230_soc_class_init,
421 };
422
423 static void k230_soc_register_types(void)
424 {
425 type_register_static(&k230_soc_type_info);
426 }
427
428 type_init(k230_soc_register_types)
429
430 static void k230_direct_boot(K230MachineState *s, MachineState *machine)
431 {
432 const char *firmware_name = riscv_default_firmware_name(&s->soc.c908_cpu);
433 RISCVBootInfo boot_info = {0};
434 hwaddr start_addr = K230_DIRECT_OPENSBI_ADDR;
435 hwaddr firmware_end_addr = 0;
436 hwaddr kernel_entry = 0;
437 int fdt_size = 0;
438
439 if (machine->firmware && !strcmp(machine->firmware, "none")) {
440 error_report("K230 direct boot requires OpenSBI firmware; omit "
441 "-bios none or pass OpenSBI with -bios");
442 exit(EXIT_FAILURE);
443 }
444
445 if (!machine->dtb) {
446 error_report("K230 direct boot requires -dtb");
447 exit(EXIT_FAILURE);
448 }
449
450 machine->fdt = load_device_tree(machine->dtb, &fdt_size);
451 if (!machine->fdt) {
452 error_report("load_device_tree() failed");
453 exit(EXIT_FAILURE);
454 }
455
456 qemu_fdt_add_path(machine->fdt, "/chosen");
457
458 riscv_boot_info_init(&boot_info, &s->soc.c908_cpu);
459 riscv_load_kernel(machine, &boot_info, K230_DIRECT_KERNEL_ADDR, true, NULL);
460 kernel_entry = boot_info.image_low_addr;
461
462 riscv_load_fdt(K230_DIRECT_DTB_ADDR, machine->fdt);
463
464 firmware_end_addr = riscv_find_and_load_firmware(machine, &boot_info,
465 firmware_name,
466 &start_addr, NULL);
467 if (firmware_end_addr > K230_DIRECT_KERNEL_ADDR) {
468 error_report("K230 firmware overlaps kernel address 0x%x",
469 K230_DIRECT_KERNEL_ADDR);
470 exit(EXIT_FAILURE);
471 }
472
473 riscv_setup_rom_reset_vec(machine, &s->soc.c908_cpu, start_addr,
474 memmap[K230_DEV_BOOTROM].base,
475 memmap[K230_DEV_BOOTROM].size, kernel_entry,
476 K230_DIRECT_DTB_ADDR);
477 }
478
479 static void k230_firmware_boot(K230MachineState *s, MachineState *machine)
480 {
481 const char *firmware_name = riscv_default_firmware_name(&s->soc.c908_cpu);
482 hwaddr start_addr = memmap[K230_DEV_DDRC].base;
483 RISCVBootInfo boot_info = {0};
484
485 if (machine->dtb || (machine->kernel_cmdline && *machine->kernel_cmdline)) {
486 error_report("K230 firmware boot does not support -dtb or -append");
487 exit(EXIT_FAILURE);
488 }
489
490 riscv_boot_info_init(&boot_info, &s->soc.c908_cpu);
491 riscv_find_and_load_firmware(machine, &boot_info, firmware_name,
492 &start_addr, NULL);
493
494 riscv_setup_rom_reset_vec(machine, &s->soc.c908_cpu, start_addr,
495 memmap[K230_DEV_BOOTROM].base,
496 memmap[K230_DEV_BOOTROM].size, 0, 0);
497 }
498
499 static void k230_machine_done(Notifier *notifier, void *data)
500 {
501 K230MachineState *s = container_of(notifier, K230MachineState,
502 machine_done);
503 MachineState *machine = MACHINE(s);
504
505 if (machine->kernel_filename) {
506 k230_direct_boot(s, machine);
507 } else {
508 k230_firmware_boot(s, machine);
509 }
510 }
511
512 static void k230_machine_init(MachineState *machine)
513 {
514 MachineClass *mc = MACHINE_GET_CLASS(machine);
515 K230MachineState *s = RISCV_K230_MACHINE(machine);
516 MemoryRegion *sys_mem = get_system_memory();
517
518 if (machine->ram_size < mc->default_ram_size) {
519 char *sz = size_to_str(mc->default_ram_size);
520 error_report("Invalid RAM size, should be %s", sz);
521 g_free(sz);
522 exit(EXIT_FAILURE);
523 }
524
525 /* Initialize SoC */
526 object_initialize_child(OBJECT(machine), "soc", &s->soc,
527 TYPE_RISCV_K230_SOC);
528 qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
529
530 /* Data Memory */
531 memory_region_add_subregion(sys_mem, memmap[K230_DEV_DDRC].base,
532 machine->ram);
533
534 s->machine_done.notify = k230_machine_done;
535 qemu_add_machine_init_done_notifier(&s->machine_done);
536 }
537
538 static void k230_machine_instance_init(Object *obj)
539 {
540 }
541
542 static void k230_machine_class_init(ObjectClass *oc, const void *data)
543 {
544 MachineClass *mc = MACHINE_CLASS(oc);
545
546 mc->desc = "RISC-V Board compatible with Kendryte K230 SDK";
547 mc->init = k230_machine_init;
548 mc->default_cpus = 1;
549 mc->default_ram_id = "riscv.K230.ram"; /* DDR */
550 mc->default_ram_size = memmap[K230_DEV_DDRC].size;
551 }
552
553 static const TypeInfo k230_machine_typeinfo = {
554 .name = TYPE_RISCV_K230_MACHINE,
555 .parent = TYPE_MACHINE,
556 .class_init = k230_machine_class_init,
557 .instance_init = k230_machine_instance_init,
558 .instance_size = sizeof(K230MachineState),
559 .interfaces = riscv64_machine_interfaces,
560 };
561
562 static void k230_machine_init_register_types(void)
563 {
564 type_register_static(&k230_machine_typeinfo);
565 }
566
567 type_init(k230_machine_init_register_types)