On 12/4/2025 1:02 AM, Daniel Henrique Barboza wrote: > > > On 11/30/25 6:21 AM, Chao Liu wrote: >> K230 Board Compatible with kendryte K230 SDK. >> >> Preliminarily supports the C908 small core, which can >> run the U-Boot and Linux kernel compiled by the K230 SDK. >> >> Signed-off-by: Chao Liu <[email protected]> >> --- >> MAINTAINERS | 7 + >> hw/riscv/Kconfig | 10 + >> hw/riscv/k230.c | 483 ++++++++++++++++++++++++++++++++++++++++ >> hw/riscv/meson.build | 2 +- >> include/hw/riscv/k230.h | 149 +++++++++++++ >> 5 files changed, 650 insertions(+), 1 deletion(-) >> create mode 100644 hw/riscv/k230.c >> create mode 100644 include/hw/riscv/k230.h >> >> diff --git a/MAINTAINERS b/MAINTAINERS >> index a07086ed76..703d9e6b82 100644 >> --- a/MAINTAINERS >> +++ b/MAINTAINERS >> @@ -1710,6 +1710,13 @@ F: docs/system/riscv/xiangshan-kunminghu.rst >> F: hw/riscv/xiangshan_kmh.c >> F: include/hw/riscv/xiangshan_kmh.h >> +K230 Machines >> +M: Chao Liu <[email protected]> >> +S: Maintained >> +F: docs/system/riscv/k230.rst > > Nit: at this point there's no k230.rst file (it's on patch 5). A minor > comment. > I found this issue too, and I will fix it in PATCH v2
Thanks, Chao > LGTM otherwise. Thanks, > > Daniel > >> +F: hw/riscv/k230.c >> +F: include/hw/riscv/k230.h >> + >> RX Machines >> ----------- >> rx-gdbsim >> diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig >> index fc9c35bd98..624f166244 100644 >> --- a/hw/riscv/Kconfig >> +++ b/hw/riscv/Kconfig >> @@ -128,3 +128,13 @@ config XIANGSHAN_KUNMINGHU >> select RISCV_APLIC >> select RISCV_IMSIC >> select SERIAL_MM >> + >> +config K230 >> + bool >> + default y >> + depends on RISCV64 >> + select RISCV_ACLINT >> + select RISCV_APLIC >> + select RISCV_IMSIC >> + select SERIAL_MM >> + select UNIMP >> \ No newline at end of file >> diff --git a/hw/riscv/k230.c b/hw/riscv/k230.c >> new file mode 100644 >> index 0000000000..f41e9b7002 >> --- /dev/null >> +++ b/hw/riscv/k230.c >> @@ -0,0 +1,483 @@ >> +/* >> + * QEMU RISC-V Virt Board Compatible with Kendryte K230 SDK >> + * >> + * Copyright (c) 2025 Chao Liu <[email protected]> >> + * SPDX-License-Identifier: GPL-2.0-or-later >> + * >> + * Provides a board compatible with the Kendryte K230 SDK >> + * >> + * Documentation: K230_Technical_Reference_Manual_V0.3.1_20241118.pdf >> + * >> + * For more information, see <https://www.kendryte.com/en/proDetail/230> >> + * >> + * This program is free software; you can redistribute it and/or modify it >> + * under the terms and conditions of the GNU General Public License, >> + * version 2 or later, as published by the Free Software Foundation. >> + * >> + * This program is distributed in the hope it will be useful, but WITHOUT >> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or >> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for >> + * more details. >> + * >> + * You should have received a copy of the GNU General Public License along >> with >> + * this program. If not, see <http://www.gnu.org/licenses/>. >> + */ >> + >> +#include "qemu/osdep.h" >> +#include "cpu-qom.h" >> +#include "qemu/cutils.h" >> +#include "qemu/error-report.h" >> +#include "qapi/error.h" >> +#include "system/system.h" >> +#include "system/memory.h" >> +#include "target/riscv/cpu.h" >> +#include "chardev/char.h" >> +#include "hw/loader.h" >> +#include "hw/sysbus.h" >> +#include "hw/riscv/k230.h" >> +#include "hw/riscv/boot.h" >> +#include "hw/intc/riscv_aclint.h" >> +#include "hw/intc/sifive_plic.h" >> +#include "hw/char/serial-mm.h" >> +#include "hw/misc/unimp.h" >> + >> +static const MemMapEntry memmap[] = { >> + [K230_DEV_DDRC] = { 0x00000000, 0x80000000 }, >> + [K230_DEV_KPU_L2_CACHE] = { 0x80000000, 0x00200000 }, >> + [K230_DEV_SRAM] = { 0x80200000, 0x00200000 }, >> + [K230_DEV_KPU_CFG] = { 0x80400000, 0x00000800 }, >> + [K230_DEV_FFT] = { 0x80400800, 0x00000400 }, >> + [K230_DEV_AI_2D_ENGINE] = { 0x80400C00, 0x00000800 }, >> + [K230_DEV_GSDMA] = { 0x80800000, 0x00004000 }, >> + [K230_DEV_DMA] = { 0x80804000, 0x00004000 }, >> + [K230_DEV_DECOMP_GZIP] = { 0x80808000, 0x00004000 }, >> + [K230_DEV_NON_AI_2D] = { 0x8080C000, 0x00004000 }, >> + [K230_DEV_ISP] = { 0x90000000, 0x00008000 }, >> + [K230_DEV_DEWARP] = { 0x90008000, 0x00001000 }, >> + [K230_DEV_RX_CSI] = { 0x90009000, 0x00002000 }, >> + [K230_DEV_H264] = { 0x90400000, 0x00010000 }, >> + [K230_DEV_2P5D] = { 0x90800000, 0x00040000 }, >> + [K230_DEV_VO] = { 0x90840000, 0x00010000 }, >> + [K230_DEV_VO_CFG] = { 0x90850000, 0x00001000 }, >> + [K230_DEV_3D_ENGINE] = { 0x90A00000, 0x00000800 }, >> + [K230_DEV_PMU] = { 0x91000000, 0x00000C00 }, >> + [K230_DEV_RTC] = { 0x91000C00, 0x00000400 }, >> + [K230_DEV_CMU] = { 0x91100000, 0x00001000 }, >> + [K230_DEV_RMU] = { 0x91101000, 0x00001000 }, >> + [K230_DEV_BOOT] = { 0x91102000, 0x00001000 }, >> + [K230_DEV_PWR] = { 0x91103000, 0x00001000 }, >> + [K230_DEV_MAILBOX] = { 0x91104000, 0x00001000 }, >> + [K230_DEV_IOMUX] = { 0x91105000, 0x00000800 }, >> + [K230_DEV_TIMER] = { 0x91105800, 0x00000800 }, >> + [K230_DEV_WDT0] = { 0x91106000, 0x00000800 }, >> + [K230_DEV_WDT1] = { 0x91106800, 0x00000800 }, >> + [K230_DEV_TS] = { 0x91107000, 0x00000800 }, >> + [K230_DEV_HDI] = { 0x91107800, 0x00000800 }, >> + [K230_DEV_STC] = { 0x91108000, 0x00000800 }, >> + [K230_DEV_BOOTROM] = { 0x91200000, 0x00010000 }, >> + [K230_DEV_SECURITY] = { 0x91210000, 0x00008000 }, >> + [K230_DEV_UART0] = { 0x91400000, 0x00001000 }, >> + [K230_DEV_UART1] = { 0x91401000, 0x00001000 }, >> + [K230_DEV_UART2] = { 0x91402000, 0x00001000 }, >> + [K230_DEV_UART3] = { 0x91403000, 0x00001000 }, >> + [K230_DEV_UART4] = { 0x91404000, 0x00001000 }, >> + [K230_DEV_I2C0] = { 0x91405000, 0x00001000 }, >> + [K230_DEV_I2C1] = { 0x91406000, 0x00001000 }, >> + [K230_DEV_I2C2] = { 0x91407000, 0x00001000 }, >> + [K230_DEV_I2C3] = { 0x91408000, 0x00001000 }, >> + [K230_DEV_I2C4] = { 0x91409000, 0x00001000 }, >> + [K230_DEV_PWM] = { 0x9140A000, 0x00001000 }, >> + [K230_DEV_GPIO0] = { 0x9140B000, 0x00001000 }, >> + [K230_DEV_GPIO1] = { 0x9140C000, 0x00001000 }, >> + [K230_DEV_ADC] = { 0x9140D000, 0x00001000 }, >> + [K230_DEV_CODEC] = { 0x9140E000, 0x00001000 }, >> + [K230_DEV_I2S] = { 0x9140F000, 0x00001000 }, >> + [K230_DEV_USB0] = { 0x91500000, 0x00010000 }, >> + [K230_DEV_USB1] = { 0x91540000, 0x00010000 }, >> + [K230_DEV_SD0] = { 0x91580000, 0x00001000 }, >> + [K230_DEV_SD1] = { 0x91581000, 0x00001000 }, >> + [K230_DEV_QSPI0] = { 0x91582000, 0x00001000 }, >> + [K230_DEV_QSPI1] = { 0x91583000, 0x00001000 }, >> + [K230_DEV_SPI] = { 0x91584000, 0x00001000 }, >> + [K230_DEV_HI_SYS_CFG] = { 0x91585000, 0x00000400 }, >> + [K230_DEV_DDRC_CFG] = { 0x98000000, 0x02000000 }, >> + [K230_DEV_FLASH] = { 0xC0000000, 0x08000000 }, >> + [K230_DEV_PLIC] = { 0xF0000000, 0x00400000 }, >> + [K230_DEV_CLINT] = { 0xF0400000, 0x00400000 }, >> +}; >> + >> +static void k230_soc_init(Object *obj) >> +{ >> + K230SoCState *s = RISCV_K230_SOC(obj); >> + RISCVHartArrayState *cpu0 = &s->c908_cpu; >> + >> + object_initialize_child(obj, "c908-cpu", cpu0, TYPE_RISCV_HART_ARRAY); >> + qdev_prop_set_uint32(DEVICE(cpu0), "hartid-base", 0); >> + qdev_prop_set_string(DEVICE(cpu0), "cpu-type", >> TYPE_RISCV_CPU_THEAD_C908); >> + qdev_prop_set_uint64(DEVICE(cpu0), "resetvec", >> + memmap[K230_DEV_BOOTROM].base); >> +} >> + >> +static DeviceState *k230_create_plic(int base_hartid, int hartid_count) >> +{ >> + g_autofree char *plic_hart_config = NULL; >> + >> + /* Per-socket PLIC hart topology configuration string */ >> + plic_hart_config = riscv_plic_hart_config_string(hartid_count); >> + >> + /* Per-socket PLIC */ >> + return sifive_plic_create(memmap[K230_DEV_PLIC].base, >> + plic_hart_config, hartid_count, base_hartid, >> + K230_PLIC_NUM_SOURCES, >> + K230_PLIC_NUM_PRIORITIES, >> + K230_PLIC_PRIORITY_BASE, >> K230_PLIC_PENDING_BASE, >> + K230_PLIC_ENABLE_BASE, >> K230_PLIC_ENABLE_STRIDE, >> + K230_PLIC_CONTEXT_BASE, >> + K230_PLIC_CONTEXT_STRIDE, >> + memmap[K230_DEV_PLIC].size); >> +} >> + >> +static void k230_soc_realize(DeviceState *dev, Error **errp) >> +{ >> + K230SoCState *s = RISCV_K230_SOC(dev); >> + MemoryRegion *sys_mem = get_system_memory(); >> + int c908_cpus; >> + >> + sysbus_realize(SYS_BUS_DEVICE(&s->c908_cpu), &error_fatal); >> + >> + c908_cpus = s->c908_cpu.num_harts; >> + >> + /* SRAM */ >> + memory_region_init_ram(&s->sram, OBJECT(dev), "sram", >> + memmap[K230_DEV_SRAM].size, &error_fatal); >> + memory_region_add_subregion(sys_mem, memmap[K230_DEV_SRAM].base, >> + &s->sram); >> + >> + /* BootROM */ >> + memory_region_init_rom(&s->bootrom, OBJECT(dev), "bootrom", >> + memmap[K230_DEV_BOOTROM].size, &error_fatal); >> + memory_region_add_subregion(sys_mem, memmap[K230_DEV_BOOTROM].base, >> + &s->bootrom); >> + >> + /* PLIC */ >> + s->c908_plic = k230_create_plic(C908_CPU_HARTID, c908_cpus); >> + >> + /* CLINT */ >> + riscv_aclint_swi_create(memmap[K230_DEV_CLINT].base, >> + C908_CPU_HARTID, c908_cpus, false); >> + riscv_aclint_mtimer_create(memmap[K230_DEV_CLINT].base + 0x4000, >> + RISCV_ACLINT_DEFAULT_MTIMER_SIZE, >> + C908_CPU_HARTID, c908_cpus, >> + RISCV_ACLINT_DEFAULT_MTIMECMP, >> + RISCV_ACLINT_DEFAULT_MTIME, >> + RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, true); >> + >> + /* UART */ >> + serial_mm_init(sys_mem, memmap[K230_DEV_UART0].base, 2, >> + qdev_get_gpio_in(DEVICE(s->c908_plic), K230_UART0_IRQ), >> + 399193, serial_hd(0), DEVICE_LITTLE_ENDIAN); >> + serial_mm_init(sys_mem, memmap[K230_DEV_UART1].base, 2, >> + qdev_get_gpio_in(DEVICE(s->c908_plic), K230_UART1_IRQ), >> + 399193, serial_hd(1), DEVICE_LITTLE_ENDIAN); >> + serial_mm_init(sys_mem, memmap[K230_DEV_UART2].base, 2, >> + qdev_get_gpio_in(DEVICE(s->c908_plic), K230_UART2_IRQ), >> + 399193, serial_hd(2), DEVICE_LITTLE_ENDIAN); >> + serial_mm_init(sys_mem, memmap[K230_DEV_UART3].base, 2, >> + qdev_get_gpio_in(DEVICE(s->c908_plic), K230_UART3_IRQ), >> + 399193, serial_hd(3), DEVICE_LITTLE_ENDIAN); >> + serial_mm_init(sys_mem, memmap[K230_DEV_UART4].base, 2, >> + qdev_get_gpio_in(DEVICE(s->c908_plic), K230_UART4_IRQ), >> + 399193, serial_hd(4), DEVICE_LITTLE_ENDIAN); >> + >> + /* unimplemented devices */ >> + create_unimplemented_device("kpu.l2-cache", >> + memmap[K230_DEV_KPU_L2_CACHE].base, >> + memmap[K230_DEV_KPU_L2_CACHE].size); >> + >> + create_unimplemented_device("kpu_cfg", memmap[K230_DEV_KPU_CFG].base, >> + memmap[K230_DEV_KPU_CFG].size); >> + >> + create_unimplemented_device("fft", memmap[K230_DEV_FFT].base, >> + memmap[K230_DEV_FFT].size); >> + >> + create_unimplemented_device("2d-engine.ai", >> + memmap[K230_DEV_AI_2D_ENGINE].base, >> + memmap[K230_DEV_AI_2D_ENGINE].size); >> + >> + create_unimplemented_device("gsdma", memmap[K230_DEV_GSDMA].base, >> + memmap[K230_DEV_GSDMA].size); >> + >> + create_unimplemented_device("dma", memmap[K230_DEV_DMA].base, >> + memmap[K230_DEV_DMA].size); >> + >> + create_unimplemented_device("decomp-gzip", >> + memmap[K230_DEV_DECOMP_GZIP].base, >> + memmap[K230_DEV_DECOMP_GZIP].size); >> + >> + create_unimplemented_device("2d-engine.non-ai", >> + memmap[K230_DEV_NON_AI_2D].base, >> + memmap[K230_DEV_NON_AI_2D].size); >> + >> + create_unimplemented_device("isp", memmap[K230_DEV_ISP].base, >> + memmap[K230_DEV_ISP].size); >> + >> + create_unimplemented_device("dewarp", memmap[K230_DEV_DEWARP].base, >> + memmap[K230_DEV_DEWARP].size); >> + >> + create_unimplemented_device("rx-csi", memmap[K230_DEV_RX_CSI].base, >> + memmap[K230_DEV_RX_CSI].size); >> + >> + create_unimplemented_device("vpu", memmap[K230_DEV_H264].base, >> + memmap[K230_DEV_H264].size); >> + >> + create_unimplemented_device("gpu", memmap[K230_DEV_2P5D].base, >> + memmap[K230_DEV_2P5D].size); >> + >> + create_unimplemented_device("vo", memmap[K230_DEV_VO].base, >> + memmap[K230_DEV_VO].size); >> + >> + create_unimplemented_device("vo_cfg", memmap[K230_DEV_VO_CFG].base, >> + memmap[K230_DEV_VO_CFG].size); >> + >> + create_unimplemented_device("3d-engine", >> memmap[K230_DEV_3D_ENGINE].base, >> + memmap[K230_DEV_3D_ENGINE].size); >> + >> + create_unimplemented_device("pmu", memmap[K230_DEV_PMU].base, >> + memmap[K230_DEV_PMU].size); >> + >> + create_unimplemented_device("rtc", memmap[K230_DEV_RTC].base, >> + memmap[K230_DEV_RTC].size); >> + >> + create_unimplemented_device("cmu", memmap[K230_DEV_CMU].base, >> + memmap[K230_DEV_CMU].size); >> + >> + create_unimplemented_device("rmu", memmap[K230_DEV_RMU].base, >> + memmap[K230_DEV_RMU].size); >> + >> + create_unimplemented_device("boot", memmap[K230_DEV_BOOT].base, >> + memmap[K230_DEV_BOOT].size); >> + >> + create_unimplemented_device("pwr", memmap[K230_DEV_PWR].base, >> + memmap[K230_DEV_PWR].size); >> + >> + create_unimplemented_device("ipcm", memmap[K230_DEV_MAILBOX].base, >> + memmap[K230_DEV_MAILBOX].size); >> + >> + create_unimplemented_device("iomux", memmap[K230_DEV_IOMUX].base, >> + memmap[K230_DEV_IOMUX].size); >> + >> + create_unimplemented_device("timer", memmap[K230_DEV_TIMER].base, >> + memmap[K230_DEV_TIMER].size); >> + >> + create_unimplemented_device("wdt0", memmap[K230_DEV_WDT0].base, >> + memmap[K230_DEV_WDT0].size); >> + >> + create_unimplemented_device("wdt1", memmap[K230_DEV_WDT1].base, >> + memmap[K230_DEV_WDT1].size); >> + >> + create_unimplemented_device("ts", memmap[K230_DEV_TS].base, >> + memmap[K230_DEV_TS].size); >> + >> + create_unimplemented_device("hdi", memmap[K230_DEV_HDI].base, >> + memmap[K230_DEV_HDI].size); >> + >> + create_unimplemented_device("stc", memmap[K230_DEV_STC].base, >> + memmap[K230_DEV_STC].size); >> + >> + create_unimplemented_device("security", memmap[K230_DEV_SECURITY].base, >> + memmap[K230_DEV_SECURITY].size); >> + >> + create_unimplemented_device("i2c0", memmap[K230_DEV_I2C0].base, >> + memmap[K230_DEV_I2C0].size); >> + >> + create_unimplemented_device("i2c1", memmap[K230_DEV_I2C1].base, >> + memmap[K230_DEV_I2C1].size); >> + >> + create_unimplemented_device("i2c2", memmap[K230_DEV_I2C2].base, >> + memmap[K230_DEV_I2C2].size); >> + >> + create_unimplemented_device("i2c3", memmap[K230_DEV_I2C3].base, >> + memmap[K230_DEV_I2C3].size); >> + >> + create_unimplemented_device("i2c4", memmap[K230_DEV_I2C4].base, >> + memmap[K230_DEV_I2C4].size); >> + >> + create_unimplemented_device("pwm", memmap[K230_DEV_PWM].base, >> + memmap[K230_DEV_PWM].size); >> + >> + create_unimplemented_device("gpio0", memmap[K230_DEV_GPIO0].base, >> + memmap[K230_DEV_GPIO0].size); >> + >> + create_unimplemented_device("gpio1", memmap[K230_DEV_GPIO1].base, >> + memmap[K230_DEV_GPIO1].size); >> + >> + create_unimplemented_device("adc", memmap[K230_DEV_ADC].base, >> + memmap[K230_DEV_ADC].size); >> + >> + create_unimplemented_device("codec", memmap[K230_DEV_CODEC].base, >> + memmap[K230_DEV_CODEC].size); >> + >> + create_unimplemented_device("i2s", memmap[K230_DEV_I2S].base, >> + memmap[K230_DEV_I2S].size); >> + >> + create_unimplemented_device("usb0", memmap[K230_DEV_USB0].base, >> + memmap[K230_DEV_USB0].size); >> + >> + create_unimplemented_device("usb1", memmap[K230_DEV_USB1].base, >> + memmap[K230_DEV_USB1].size); >> + >> + create_unimplemented_device("sd0", memmap[K230_DEV_SD0].base, >> + memmap[K230_DEV_SD0].size); >> + >> + create_unimplemented_device("sd1", memmap[K230_DEV_SD1].base, >> + memmap[K230_DEV_SD1].size); >> + >> + create_unimplemented_device("qspi0", memmap[K230_DEV_QSPI0].base, >> + memmap[K230_DEV_QSPI0].size); >> + >> + create_unimplemented_device("qspi1", memmap[K230_DEV_QSPI1].base, >> + memmap[K230_DEV_QSPI1].size); >> + >> + create_unimplemented_device("spi", memmap[K230_DEV_SPI].base, >> + memmap[K230_DEV_SPI].size); >> + >> + create_unimplemented_device("hi_sys_cfg", >> memmap[K230_DEV_HI_SYS_CFG].base, >> + memmap[K230_DEV_HI_SYS_CFG].size); >> + >> + create_unimplemented_device("ddrc_cfg", memmap[K230_DEV_DDRC_CFG].base, >> + memmap[K230_DEV_DDRC_CFG].size); >> + >> + create_unimplemented_device("flash", memmap[K230_DEV_FLASH].base, >> + memmap[K230_DEV_FLASH].size); >> +} >> + >> +static void k230_soc_class_init(ObjectClass *oc, const void *data) >> +{ >> + DeviceClass *dc = DEVICE_CLASS(oc); >> + >> + dc->realize = k230_soc_realize; >> +} >> + >> +static const TypeInfo k230_soc_type_info = { >> + .name = TYPE_RISCV_K230_SOC, >> + .parent = TYPE_DEVICE, >> + .instance_size = sizeof(K230SoCState), >> + .instance_init = k230_soc_init, >> + .class_init = k230_soc_class_init, >> +}; >> + >> +static void k230_soc_register_types(void) >> +{ >> + type_register_static(&k230_soc_type_info); >> +} >> + >> +type_init(k230_soc_register_types) >> + >> +static void k230_machine_done(Notifier *notifier, void *data) >> +{ >> + K230MachineState *s = container_of(notifier, K230MachineState, >> + machine_done); >> + MachineState *machine = MACHINE(s); >> + hwaddr start_addr = memmap[K230_DEV_DDRC].base; >> + target_ulong firmware_end_addr, kernel_start_addr; >> + const char *firmware_name = >> riscv_default_firmware_name(&s->soc.c908_cpu); >> + uint64_t kernel_entry = 0; >> + RISCVBootInfo boot_info; >> + >> + firmware_end_addr = riscv_find_and_load_firmware(machine, firmware_name, >> + &start_addr, NULL); >> + >> + /* Mask ROM reset vector */ >> + uint32_t reset_vec[] = { >> + /* 0x91200000: auipc t0, 0x0 */ 0x00000297, >> + /* 0x91200004: addi t0, t0, 36 # <trap> */ 0x02428293, >> + /* 0x91200008: csrw mtvec, t0 */ 0x30529073, >> + /* 0x9120000C: csrr a0, misa */ 0x301012F3, >> + /* 0x91200010: lui t0, 0x1 */ 0x000012B7, >> + /* 0x91200014: slli t0, t0, 1 */ 0x00129293, >> + /* 0x91200018: and t0, a0, t0 */ 0x005572B3, >> + /* 0x9120001C: bnez t0, loop */ 0x00511063, >> + /* entry: */ >> + /* 0x91200020: addiw t0, zero, 1 */ 0x0010029b, >> + /* 0x91200024: slli t0, t0, 0x1b */ 0x01b29293, >> + /* 0x91200028: jr t0 # uboot 0x8000000 */ 0x00028067, >> + /* loop: */ >> + /* 0x9120002C: j 0x9120002C # <loop> */ 0x0000006f, >> + /* trap: */ >> + /* 0x91200030: j 0x91200030 # <trap> */ 0x0000006f, >> + }; >> + >> + /* copy in the reset vector in little_endian byte order */ >> + for (int i = 0; i < sizeof(reset_vec) >> 2; i++) { >> + reset_vec[i] = cpu_to_le32(reset_vec[i]); >> + } >> + rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec), >> + memmap[K230_DEV_BOOTROM].base, >> &address_space_memory); >> + >> + riscv_boot_info_init(&boot_info, &s->soc.c908_cpu); >> + >> + if (machine->kernel_filename && !kernel_entry) { >> + kernel_start_addr = riscv_calc_kernel_start_addr(&boot_info, >> + firmware_end_addr); >> + riscv_load_kernel(machine, &boot_info, kernel_start_addr, >> + true, NULL); >> + kernel_entry = boot_info.image_low_addr; >> + } >> +} >> + >> +static void k230_machine_init(MachineState *machine) >> +{ >> + MachineClass *mc = MACHINE_GET_CLASS(machine); >> + >> + K230MachineState *s = RISCV_K230_MACHINE(machine); >> + MemoryRegion *sys_mem = get_system_memory(); >> + >> + if (machine->ram_size < mc->default_ram_size) { >> + char *sz = size_to_str(mc->default_ram_size); >> + error_report("Invalid RAM size, should be %s", sz); >> + g_free(sz); >> + exit(EXIT_FAILURE); >> + } >> + >> + /* Initialize SoC */ >> + object_initialize_child(OBJECT(machine), "soc", &s->soc, >> + TYPE_RISCV_K230_SOC); >> + qdev_realize(DEVICE(&s->soc), NULL, &error_fatal); >> + >> + /* Data Memory */ >> + memory_region_add_subregion(sys_mem, memmap[K230_DEV_DDRC].base, >> + machine->ram); >> + >> + s->machine_done.notify = k230_machine_done; >> + qemu_add_machine_init_done_notifier(&s->machine_done); >> +} >> + >> +static void k230_machine_instance_init(Object *obj) >> +{ >> +} >> + >> +static void k230_machine_class_init(ObjectClass *oc, const void *data) >> +{ >> + MachineClass *mc = MACHINE_CLASS(oc); >> + >> + mc->desc = "RISC-V Board compatible with Kendryte K230 SDK"; >> + mc->init = k230_machine_init; >> + mc->default_cpus = 2; >> + mc->default_ram_id = "riscv.K230.ram"; /* DDR */ >> + mc->default_ram_size = memmap[K230_DEV_DDRC].size; >> +} >> + >> +static const TypeInfo k230_machine_typeinfo = { >> + .name = TYPE_RISCV_K230_MACHINE, >> + .parent = TYPE_MACHINE, >> + .class_init = k230_machine_class_init, >> + .instance_init = k230_machine_instance_init, >> + .instance_size = sizeof(K230MachineState), >> +}; >> + >> +static void k230_machine_init_register_types(void) >> +{ >> + type_register_static(&k230_machine_typeinfo); >> +} >> + >> +type_init(k230_machine_init_register_types) >> diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build >> index 2a8d5b136c..1e5ce511d4 100644 >> --- a/hw/riscv/meson.build >> +++ b/hw/riscv/meson.build >> @@ -14,5 +14,5 @@ riscv_ss.add(when: 'CONFIG_RISCV_IOMMU', if_true: files( >> 'riscv-iommu.c', 'riscv-iommu-pci.c', 'riscv-iommu-sys.c', >> 'riscv-iommu- >> hpm.c')) >> riscv_ss.add(when: 'CONFIG_MICROBLAZE_V', if_true: files('microblaze-v- >> generic.c')) >> riscv_ss.add(when: 'CONFIG_XIANGSHAN_KUNMINGHU', if_true: >> files('xiangshan_kmh.c')) >> - >> +riscv_ss.add(when: 'CONFIG_K230', if_true: files('k230.c')) >> hw_arch += {'riscv': riscv_ss} >> diff --git a/include/hw/riscv/k230.h b/include/hw/riscv/k230.h >> new file mode 100644 >> index 0000000000..3158381e8f >> --- /dev/null >> +++ b/include/hw/riscv/k230.h >> @@ -0,0 +1,149 @@ >> +/* >> + * QEMU RISC-V Virt Board Compatible with kendryte K230 SDK >> + * >> + * Copyright (c) 2025 Chao Liu <[email protected]> >> + * SPDX-License-Identifier: GPL-2.0-or-later >> + * >> + * Provides a board compatible with the kendryte K230 SDK >> + * >> + * Documentation: K230_Technical_Reference_Manual_V0.3.1_20241118.pdf >> + * >> + * For more information, see <https://www.kendryte.com/en/proDetail/230> >> + * >> + * This program is free software; you can redistribute it and/or modify it >> + * under the terms and conditions of the GNU General Public License, >> + * version 2 or later, as published by the Free Software Foundation. >> + * >> + * This program is distributed in the hope it will be useful, but WITHOUT >> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or >> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for >> + * more details. >> + * >> + * You should have received a copy of the GNU General Public License along >> with >> + * this program. If not, see <http://www.gnu.org/licenses/>. >> + */ >> +#ifndef HW_K230_H >> +#define HW_K230_H >> + >> +#include "hw/boards.h" >> +#include "hw/riscv/riscv_hart.h" >> + >> +#define C908_CPU_HARTID (0) >> + >> +#define TYPE_RISCV_K230_SOC "riscv.k230.soc" >> +#define RISCV_K230_SOC(obj) \ >> + OBJECT_CHECK(K230SoCState, (obj), TYPE_RISCV_K230_SOC) >> + >> +typedef struct K230SoCState { >> + /*< private >*/ >> + DeviceState parent_obj; >> + >> + /*< public >*/ >> + RISCVHartArrayState c908_cpu; /* Small core */ >> + >> + MemoryRegion sram; >> + MemoryRegion bootrom; >> + >> + DeviceState *c908_plic; >> +} K230SoCState; >> + >> +#define TYPE_RISCV_K230_MACHINE MACHINE_TYPE_NAME("k230") >> +#define RISCV_K230_MACHINE(obj) \ >> + OBJECT_CHECK(K230MachineState, (obj), TYPE_RISCV_K230_MACHINE) >> + >> +typedef struct K230MachineState { >> + /*< private >*/ >> + MachineState parent_obj; >> + >> + /*< public >*/ >> + K230SoCState soc; >> + Notifier machine_done; >> +} K230MachineState; >> + >> +enum { >> + K230_DEV_DDRC, >> + K230_DEV_KPU_L2_CACHE, >> + K230_DEV_SRAM, >> + K230_DEV_KPU_CFG, >> + K230_DEV_FFT, >> + K230_DEV_AI_2D_ENGINE, >> + K230_DEV_GSDMA, >> + K230_DEV_DMA, >> + K230_DEV_DECOMP_GZIP, >> + K230_DEV_NON_AI_2D, >> + K230_DEV_ISP, >> + K230_DEV_DEWARP, >> + K230_DEV_RX_CSI, >> + K230_DEV_H264, >> + K230_DEV_2P5D, >> + K230_DEV_VO, >> + K230_DEV_VO_CFG, >> + K230_DEV_3D_ENGINE, >> + K230_DEV_PMU, >> + K230_DEV_RTC, >> + K230_DEV_CMU, >> + K230_DEV_RMU, >> + K230_DEV_BOOT, >> + K230_DEV_PWR, >> + K230_DEV_MAILBOX, >> + K230_DEV_IOMUX, >> + K230_DEV_TIMER, >> + K230_DEV_WDT0, >> + K230_DEV_WDT1, >> + K230_DEV_TS, >> + K230_DEV_HDI, >> + K230_DEV_STC, >> + K230_DEV_BOOTROM, >> + K230_DEV_SECURITY, >> + K230_DEV_UART0, >> + K230_DEV_UART1, >> + K230_DEV_UART2, >> + K230_DEV_UART3, >> + K230_DEV_UART4, >> + K230_DEV_I2C0, >> + K230_DEV_I2C1, >> + K230_DEV_I2C2, >> + K230_DEV_I2C3, >> + K230_DEV_I2C4, >> + K230_DEV_PWM, >> + K230_DEV_GPIO0, >> + K230_DEV_GPIO1, >> + K230_DEV_ADC, >> + K230_DEV_CODEC, >> + K230_DEV_I2S, >> + K230_DEV_USB0, >> + K230_DEV_USB1, >> + K230_DEV_SD0, >> + K230_DEV_SD1, >> + K230_DEV_QSPI0, >> + K230_DEV_QSPI1, >> + K230_DEV_SPI, >> + K230_DEV_HI_SYS_CFG, >> + K230_DEV_DDRC_CFG, >> + K230_DEV_FLASH, >> + K230_DEV_PLIC, >> + K230_DEV_CLINT, >> +}; >> + >> +enum { >> + K230_UART0_IRQ = 16, >> + K230_UART1_IRQ = 17, >> + K230_UART2_IRQ = 18, >> + K230_UART3_IRQ = 19, >> + K230_UART4_IRQ = 20, >> +}; >> + >> +/* >> + * Integrates with the interrupt controller (PLIC), >> + * which can process 208 interrupt external sources >> + */ >> +#define K230_PLIC_NUM_SOURCES 208 >> +#define K230_PLIC_NUM_PRIORITIES 7 >> +#define K230_PLIC_PRIORITY_BASE 0x00 >> +#define K230_PLIC_PENDING_BASE 0x1000 >> +#define K230_PLIC_ENABLE_BASE 0x2000 >> +#define K230_PLIC_ENABLE_STRIDE 0x80 >> +#define K230_PLIC_CONTEXT_BASE 0x200000 >> +#define K230_PLIC_CONTEXT_STRIDE 0x1000 >> + >> +#endif >
