| 1 | Kendryte K230 virt reference platform (``k230``) |
| 2 | ========================================================================== |
| 3 | The ``k230`` machine is compatible with the Kendryte K230 SDK. |
| 4 | |
| 5 | The K230 is a chip from the AIoT SoC series made by Kendryte ® — a part of |
| 6 | Canaan Inc. It uses a brand-new multi-heterogeneous unit accelerated computing |
| 7 | structure. |
| 8 | |
| 9 | This chip has 2 RISC-V computing cores and a new-generation KPU (Knowledge |
| 10 | Process Unit) smart computing unit. |
| 11 | |
| 12 | For more information, see <https://www.kendryte.com/en/proDetail/230> |
| 13 | |
| 14 | Supported devices |
| 15 | ----------------- |
| 16 | The ``k230`` machine supports the following devices: |
| 17 | |
| 18 | * 1 c908 cores (little core) |
| 19 | * Core Local Interruptor (CLINT) |
| 20 | * Platform-Level Interrupt Controller (PLIC) |
| 21 | * 2 K230 Watchdog Timer |
| 22 | * 5 UART |
| 23 | * K230 DDRC CFG and DDR PHY |
| 24 | * System Direct Memory Access (SDMA) |
| 25 | * GZIP Decompress Engine (Decomp_gzip) |
| 26 | |
| 27 | Boot options |
| 28 | ------------ |
| 29 | The ``k230`` machine supports K230 SDK boot through M-mode U-Boot, which then |
| 30 | starts OpenSBI/Linux with ``bootm``. It also supports direct Linux boot. |
| 31 | |
| 32 | The DDRC CFG and DDR PHY models allow the K230 SDK U-Boot SPL to complete DDR |
| 33 | initialization before loading the next boot stage. |
| 34 | |
| 35 | K230 SDK Linux kernels use T-HEAD C9xx private MAEE page table attributes. QEMU |
| 36 | does not implement MAEE in the generic RISC-V MMU, so such kernels need to be |
| 37 | built with standard RISC-V PTE bits before they can boot under QEMU. |
| 38 | |
| 39 | Running |
| 40 | ------- |
| 41 | |
| 42 | Direct Linux boot |
| 43 | ~~~~~~~~~~~~~~~~~ |
| 44 | |
| 45 | This flow lets QEMU load OpenSBI, Linux, initrd, and DTB directly, without |
| 46 | running SDK U-Boot. The Linux Image must be rebuilt with standard RISC-V PTE |
| 47 | bits before running under QEMU. |
| 48 | |
| 49 | .. code-block:: bash |
| 50 | |
| 51 | $ SDK=k230_sdk/output/k230_canmv_defconfig |
| 52 | $ qemu-system-riscv64 -machine k230 \ |
| 53 | -kernel "$SDK/images/little-core/Image" \ |
| 54 | -dtb "/tmp/user-k230-qemu.dtb" \ |
| 55 | -initrd "$SDK/images/little-core/rootfs.cpio.gz" \ |
| 56 | -append "console=ttyS0,115200 earlycon=sbi cma=0" \ |
| 57 | -nographic |
| 58 | |
| 59 | Direct boot uses the SDK little-core RAM layout for OpenSBI at |
| 60 | ``0x08000000``, Linux at ``0x08200000``, and the DTB at ``0x0a000000``. The |
| 61 | initrd is placed by QEMU's generic RISC-V boot helper, and QEMU writes the |
| 62 | initrd range and kernel command line into ``/chosen``. The DTB passed with |
| 63 | ``-dtb`` should be derived from ``$SDK/images/little-core/k230.dtb`` and must |
| 64 | describe that initrd location as usable memory and disable any devices that are |
| 65 | not emulated by this machine. |
| 66 | |
| 67 | U-Boot boot |
| 68 | ~~~~~~~~~~~ |
| 69 | |
| 70 | This flow starts SDK U-Boot in M-mode with ``-bios``. Until the SDK storage |
| 71 | path is modeled, place OpenSBI, Linux, initrd, and DTB in RAM with loader |
| 72 | devices and run ``bootm`` manually. The Linux Image must be rebuilt with |
| 73 | standard RISC-V PTE bits before running under QEMU. |
| 74 | |
| 75 | .. code-block:: bash |
| 76 | |
| 77 | $ SDK=k230_sdk/output/k230_canmv_defconfig |
| 78 | $ IMAGE=$SDK/images/little-core/Image |
| 79 | $ INITRD=$SDK/images/little-core/rootfs.cpio.gz |
| 80 | $ DTB=$SDK/images/little-core/k230.dtb |
| 81 | $ FWJUMP_UIMAGE=/tmp/k230-fw-jump.uImage |
| 82 | $ INITRD_END=$(printf "0x%x" $((0x0a100000 + $(stat -c %s "$INITRD")))) |
| 83 | $ "$SDK/little/buildroot-ext/host/bin/mkimage" \ |
| 84 | -A riscv -O linux -T kernel -C none \ |
| 85 | -a 0x8000000 -e 0x8000000 -n opensbi \ |
| 86 | -d "$SDK/images/little-core/fw_jump.bin" "$FWJUMP_UIMAGE" |
| 87 | $ qemu-system-riscv64 -machine k230 \ |
| 88 | -bios "$SDK/little/uboot/u-boot" \ |
| 89 | -device loader,file="$FWJUMP_UIMAGE",addr=0xc100000,force-raw=on \ |
| 90 | -device loader,file="$IMAGE",addr=0x8200000,force-raw=on \ |
| 91 | -device loader,file="$INITRD",addr=0xa100000,force-raw=on \ |
| 92 | -device loader,file="$DTB",addr=0xa000000,force-raw=on \ |
| 93 | -nographic |
| 94 | |
| 95 | The loader addresses mirror the SDK ``k230_canmv_defconfig`` output. Read the |
| 96 | U-Boot addresses from the generated environment, and read the Linux RAM base |
| 97 | from the generated ``hw/k230.dts.txt``. This replaces the SDK storage and |
| 98 | decompression steps. |
| 99 | |
| 100 | Press Enter to stop autoboot. At the U-Boot prompt, run these commands: |
| 101 | |
| 102 | .. code-block:: bash |
| 103 | |
| 104 | K230# setenv bootargs console=ttyS0,115200 earlycon=sbi cma=0 |
| 105 | K230# fdt addr 0xa000000 |
| 106 | K230# fdt resize 8192 |
| 107 | K230# fdt set /chosen linux,initrd-start <0x0 0xa100000> |
| 108 | K230# fdt set /chosen linux,initrd-end <0x0 ${INITRD_END}> |
| 109 | K230# fdt set /soc/sdhci0@91580000 status disabled |
| 110 | K230# fdt set /soc/sdhci1@91581000 status disabled |
| 111 | K230# bootm 0xc100000 - 0xa000000 |
| 112 | |
| 113 | Use ``setenv`` so ``bootm`` writes the kernel command line into |
| 114 | ``/chosen/bootargs``. The ``fdt`` commands select the loaded DTB, add space for |
| 115 | edits, describe the initrd range in ``/chosen``, and disable SDHCI nodes because |
| 116 | this machine does not emulate those controllers yet. Replace ``${INITRD_END}`` |
| 117 | with the host-calculated value above when typing the command. ``cma=0`` avoids |
| 118 | the SDK kernel reserving too much of the little-core memory window for initramfs |
| 119 | boot. |