Browse Source

[libcpu/aarch64] add gicv3 support and bsp/rockchip/rk3568 (#5722)

* [libcpu/aarch64] add smp support

* [libcpu/aarch64] rt_hw_trap_irq get irq instead of iar when using gicv2

* [libcpu/aarch64] disable irq/fiq when switch thread

* [libcpu/aarch64] add gtimer frq set and stack align

* [libcpu/aarch64] add gicv3 support and bsp/rockchip/rk3568
GUI 3 years ago
parent
commit
f587a55bc2
57 changed files with 4107 additions and 920 deletions
  1. 1 0
      .github/workflows/action.yml
  2. 23 39
      bsp/qemu-virt64-aarch64/.config
  3. 5 5
      bsp/qemu-virt64-aarch64/README.md
  4. 3 3
      bsp/qemu-virt64-aarch64/README_zh.md
  5. 12 6
      bsp/qemu-virt64-aarch64/driver/Kconfig
  6. 12 2
      bsp/qemu-virt64-aarch64/driver/board.c
  7. 2 56
      bsp/qemu-virt64-aarch64/driver/board.h
  8. 4 0
      bsp/qemu-virt64-aarch64/driver/drv_uart.c
  9. 62 0
      bsp/qemu-virt64-aarch64/driver/drv_virtio.c
  10. 16 0
      bsp/qemu-virt64-aarch64/driver/drv_virtio.h
  11. 81 0
      bsp/qemu-virt64-aarch64/driver/virt.h
  12. 0 405
      bsp/qemu-virt64-aarch64/driver/virtio/drv_virtio_blk.c
  13. 0 85
      bsp/qemu-virt64-aarch64/driver/virtio/drv_virtio_blk.h
  14. 274 0
      bsp/qemu-virt64-aarch64/driver/virtio/virtio.c
  15. 96 36
      bsp/qemu-virt64-aarch64/driver/virtio/virtio.h
  16. 216 0
      bsp/qemu-virt64-aarch64/driver/virtio/virtio_blk.c
  17. 61 0
      bsp/qemu-virt64-aarch64/driver/virtio/virtio_blk.h
  18. 0 61
      bsp/qemu-virt64-aarch64/driver/virtio/virtio_mmio.c
  19. 44 62
      bsp/qemu-virt64-aarch64/driver/virtio/virtio_mmio.h
  20. 94 0
      bsp/qemu-virt64-aarch64/driver/virtio/virtio_queue.h
  21. 3 2
      bsp/qemu-virt64-aarch64/qemu.bat
  22. 3 2
      bsp/qemu-virt64-aarch64/qemu.sh
  23. 9 26
      bsp/qemu-virt64-aarch64/rtconfig.h
  24. 23 50
      bsp/raspberry-pi/raspi4-64/.config
  25. 4 0
      bsp/raspberry-pi/raspi4-64/driver/Kconfig
  26. 44 0
      bsp/raspberry-pi/raspi4-64/driver/drv_wdt.c
  27. 18 0
      bsp/raspberry-pi/raspi4-64/driver/mbox.c
  28. 1 0
      bsp/raspberry-pi/raspi4-64/driver/mbox.h
  29. 7 25
      bsp/raspberry-pi/raspi4-64/rtconfig.h
  30. 653 0
      bsp/rockchip/rk3568/.config
  31. 29 0
      bsp/rockchip/rk3568/Kconfig
  32. 55 0
      bsp/rockchip/rk3568/README.md
  33. 56 0
      bsp/rockchip/rk3568/README_zh.md
  34. 14 0
      bsp/rockchip/rk3568/SConscript
  35. 29 0
      bsp/rockchip/rk3568/SConstruct
  36. 9 0
      bsp/rockchip/rk3568/applications/SConscript
  37. 18 0
      bsp/rockchip/rk3568/applications/main.c
  38. 58 0
      bsp/rockchip/rk3568/driver/Kconfig
  39. 19 0
      bsp/rockchip/rk3568/driver/SConscript
  40. 124 0
      bsp/rockchip/rk3568/driver/board.c
  41. 24 0
      bsp/rockchip/rk3568/driver/board.h
  42. 358 0
      bsp/rockchip/rk3568/driver/drv_uart.c
  43. 16 0
      bsp/rockchip/rk3568/driver/drv_uart.h
  44. 116 0
      bsp/rockchip/rk3568/driver/rk3568.h
  45. 143 0
      bsp/rockchip/rk3568/link.lds
  46. 188 0
      bsp/rockchip/rk3568/rtconfig.h
  47. 53 0
      bsp/rockchip/rk3568/rtconfig.py
  48. 3 0
      include/rthw.h
  49. 0 4
      libcpu/aarch64/common/SConscript
  50. 40 28
      libcpu/aarch64/common/gic.c
  51. 6 4
      libcpu/aarch64/common/gic.h
  52. 849 0
      libcpu/aarch64/common/gicv3.c
  53. 77 0
      libcpu/aarch64/common/gicv3.h
  54. 10 1
      libcpu/aarch64/common/interrupt.c
  55. 11 3
      libcpu/aarch64/common/psci.c
  56. 4 1
      libcpu/aarch64/common/psci.h
  57. 27 14
      libcpu/aarch64/cortex-a/entry_point.S

+ 1 - 0
.github/workflows/action.yml

@@ -167,6 +167,7 @@ jobs:
          - {RTT_BSP: "qemu-virt64-aarch64", RTT_TOOL_CHAIN: "sourcery-aarch64"}
          - {RTT_BSP: "raspberry-pi/raspi3-64", RTT_TOOL_CHAIN: "sourcery-aarch64"}
          - {RTT_BSP: "raspberry-pi/raspi4-64", RTT_TOOL_CHAIN: "sourcery-aarch64"}
+         - {RTT_BSP: "rockchip/rk3568", RTT_TOOL_CHAIN: "sourcery-aarch64"}
     steps:
       - uses: actions/checkout@v2
       - name: Set up Python

+ 23 - 39
bsp/qemu-virt64-aarch64/.config

@@ -96,17 +96,8 @@ CONFIG_RT_USING_USER_MAIN=y
 CONFIG_RT_MAIN_THREAD_STACK_SIZE=8192
 CONFIG_RT_MAIN_THREAD_PRIORITY=10
 # CONFIG_RT_USING_LEGACY is not set
-
-#
-# C++ features
-#
-# CONFIG_RT_USING_CPLUSPLUS is not set
-
-#
-# Command shell
-#
-CONFIG_RT_USING_FINSH=y
 CONFIG_RT_USING_MSH=y
+CONFIG_RT_USING_FINSH=y
 CONFIG_FINSH_USING_MSH=y
 CONFIG_FINSH_THREAD_NAME="tshell"
 CONFIG_FINSH_THREAD_PRIORITY=20
@@ -120,10 +111,6 @@ CONFIG_FINSH_USING_DESCRIPTION=y
 # CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set
 # CONFIG_FINSH_USING_AUTH is not set
 CONFIG_FINSH_ARG_MAX=10
-
-#
-# Device virtual file system
-#
 CONFIG_RT_USING_DFS=y
 CONFIG_DFS_USING_POSIX=y
 CONFIG_DFS_USING_WORKDIR=y
@@ -157,12 +144,15 @@ CONFIG_RT_DFS_ELM_MUTEX_TIMEOUT=3000
 CONFIG_RT_USING_DFS_DEVFS=y
 # CONFIG_RT_USING_DFS_ROMFS is not set
 # CONFIG_RT_USING_DFS_RAMFS is not set
+# CONFIG_RT_USING_FAL is not set
 
 #
 # Device Drivers
 #
 CONFIG_RT_USING_DEVICE_IPC=y
-# CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set
+CONFIG_RT_USING_SYSTEM_WORKQUEUE=y
+CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048
+CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23
 CONFIG_RT_USING_SERIAL=y
 CONFIG_RT_USING_SERIAL_V1=y
 # CONFIG_RT_USING_SERIAL_V2 is not set
@@ -202,7 +192,7 @@ CONFIG_RT_USING_ALARM=y
 # CONFIG_RT_USING_USB_DEVICE is not set
 
 #
-# POSIX layer and C standard library
+# C/C++ and POSIX layer
 #
 CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
 
@@ -226,36 +216,16 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
 #
 # Socket is in the 'Network' category
 #
+# CONFIG_RT_USING_CPLUSPLUS is not set
 
 #
 # Network
 #
-
-#
-# Socket abstraction layer
-#
 # CONFIG_RT_USING_SAL is not set
-
-#
-# Network interface device
-#
 # CONFIG_RT_USING_NETDEV is not set
-
-#
-# light weight TCP/IP stack
-#
 # CONFIG_RT_USING_LWIP is not set
-
-#
-# AT commands
-#
 # CONFIG_RT_USING_AT is not set
 
-#
-# VBUS(Virtual Software BUS)
-#
-# CONFIG_RT_USING_VBUS is not set
-
 #
 # Utilities
 #
@@ -264,6 +234,7 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
 # CONFIG_RT_USING_UTEST is not set
 # CONFIG_RT_USING_VAR_EXPORT is not set
 # CONFIG_RT_USING_RT_LINK is not set
+# CONFIG_RT_USING_VBUS is not set
 
 #
 # RT-Thread Utestcases
@@ -277,6 +248,7 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
 #
 # IoT - internet of things
 #
+# CONFIG_PKG_USING_LWIP is not set
 # CONFIG_PKG_USING_LORAWAN_DRIVER is not set
 # CONFIG_PKG_USING_PAHOMQTT is not set
 # CONFIG_PKG_USING_UMQTT is not set
@@ -293,6 +265,7 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
 # CONFIG_PKG_USING_FREEMODBUS is not set
 # CONFIG_PKG_USING_LJSON is not set
 # CONFIG_PKG_USING_EZXML is not set
+# CONFIG_PKG_USING_SIMPLE_XML is not set
 # CONFIG_PKG_USING_NANOPB is not set
 
 #
@@ -332,6 +305,7 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
 # CONFIG_PKG_USING_JOYLINK is not set
 # CONFIG_PKG_USING_EZ_IOT_OS is not set
 # CONFIG_PKG_USING_NIMBLE is not set
+# CONFIG_PKG_USING_LLSYNC_SDK_ADAPTER is not set
 # CONFIG_PKG_USING_OTA_DOWNLOADER is not set
 # CONFIG_PKG_USING_IPMSG is not set
 # CONFIG_PKG_USING_LSSDP is not set
@@ -539,7 +513,8 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
 # CONFIG_PKG_USING_ARM_2D is not set
 # CONFIG_PKG_USING_MCUBOOT is not set
 # CONFIG_PKG_USING_TINYUSB is not set
-# CONFIG_PKG_USING_USB_STACK is not set
+# CONFIG_PKG_USING_CHERRYUSB is not set
+# CONFIG_PKG_USING_KMULTI_RTIMER is not set
 
 #
 # peripheral libraries and drivers
@@ -563,6 +538,7 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
 # CONFIG_PKG_USING_WM_LIBRARIES is not set
 # CONFIG_PKG_USING_KENDRYTE_SDK is not set
 # CONFIG_PKG_USING_INFRARED is not set
+# CONFIG_PKG_USING_MULTI_INFRARED is not set
 # CONFIG_PKG_USING_AGILE_BUTTON is not set
 # CONFIG_PKG_USING_AGILE_LED is not set
 # CONFIG_PKG_USING_AT24CXX is not set
@@ -619,6 +595,7 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
 # CONFIG_PKG_USING_SOFT_SERIAL is not set
 # CONFIG_PKG_USING_MB85RS16 is not set
 # CONFIG_PKG_USING_CW2015 is not set
+# CONFIG_PKG_USING_RFM300 is not set
 
 #
 # AI packages
@@ -637,6 +614,10 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
 # miscellaneous packages
 #
 
+#
+# project laboratory
+#
+
 #
 # samples: kernel and components samples
 #
@@ -669,6 +650,7 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
 # CONFIG_PKG_USING_CANFESTIVAL is not set
 # CONFIG_PKG_USING_ZLIB is not set
 # CONFIG_PKG_USING_MINIZIP is not set
+# CONFIG_PKG_USING_HEATSHRINK is not set
 # CONFIG_PKG_USING_DSTR is not set
 # CONFIG_PKG_USING_TINYFRAME is not set
 # CONFIG_PKG_USING_KENDRYTE_DEMO is not set
@@ -686,6 +668,7 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
 # CONFIG_PKG_USING_DESIGN_PATTERN is not set
 # CONFIG_PKG_USING_CONTROLLER is not set
 # CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set
+# CONFIG_PKG_USING_MFBD is not set
 CONFIG_SOC_VIRT64_AARCH64=y
 
 #
@@ -696,5 +679,6 @@ CONFIG_RT_USING_UART0=y
 CONFIG_BSP_USING_RTC=y
 CONFIG_BSP_USING_ALARM=y
 CONFIG_BSP_USING_VIRTIO_BLK=y
-CONFIG_RT_USING_VIRTIO_BLK0=y
 CONFIG_BSP_USING_GIC=y
+CONFIG_BSP_USING_GICV2=y
+# CONFIG_BSP_USING_GICV3 is not set

+ 5 - 5
bsp/qemu-virt64-aarch64/README.md

@@ -19,9 +19,9 @@ Enter directory `rt-thread/bsp/qemu-virt64-aarch64` and input:
 scons
 ```
 
-## 2. Execution
+## 3. Execution
 
-The project execution tool is `qemu-system-aarch64`
+The project execution tool is `qemu-system-aarch64`, the project can be configured to `Cortex-A53/A57/A72`, GIC supports `V2/V3` version, and `V2` of GIC can use 8 processors max.
 
 Download Windows platform from website:
 ```
@@ -33,7 +33,7 @@ sudo apt update
 sudo apt install qemu-system-arm
 ```
 
-Run qemu.bat or qemu.sh in terminal:
+Please fixup the exec scripts if modify the default configuration of the project. Run qemu.bat or qemu.sh in terminal:
 ```
 heap: [0x40042aa0 - 0x40142aa0]
 
@@ -45,10 +45,10 @@ Hi, this is RT-Thread!!
 msh />
 ```
 
-## 3. Condition
+## 4. Condition
 
 | Driver | Condition | Remark |
 | ------ | --------- | ------ |
 | UART   | Support   | UART0  |
 | RTC    | Support   | - |
-| VIRTIO BLK | Support | VIRTIO BLK0 |
+| VIRTIO BLK | Support | - |

+ 3 - 3
bsp/qemu-virt64-aarch64/README_zh.md

@@ -22,7 +22,7 @@ scons
 
 ## 3. 执行
 
-本工程执行环境为`qemu-system-aarch64`模拟器
+本工程执行环境为`qemu-system-aarch64`模拟器,工程可配置为使用`Cortex-A53/A57/A72`等芯片,GIC支持`V2/V3`版本,其中`V2`最多可配置8个处理器。
 
 Windows平台下,可以在此获取到QEMU:
 ```
@@ -34,7 +34,7 @@ sudo apt update
 sudo apt install qemu-system-arm
 ```
 
-在终端执行qemu.bat或qemu.sh可以看到程序运行:
+工程默认配置修改后请注意修改运行脚本。在终端执行qemu.bat或qemu.sh可以看到程序运行:
 ```
 heap: [0x40042aa0 - 0x40142aa0]
 
@@ -52,4 +52,4 @@ msh />
 | ------ | ----  | :------:  |
 | UART | 支持 | UART0 |
 | RTC  | 支持 | - |
-| VIRTIO BLK | 支持 | VIRTIO BLK0 |
+| VIRTIO BLK | 支持 | - |

+ 12 - 6
bsp/qemu-virt64-aarch64/driver/Kconfig

@@ -28,13 +28,19 @@ menu "AARCH64 qemu virt64 configs"
         bool "Using VirtIO BLK"
         default y
 
-        if BSP_USING_VIRTIO_BLK
-            config RT_USING_VIRTIO_BLK0
-            bool "Enabel VirtIO BLK 0"
-            default y
-        endif
-
     config BSP_USING_GIC
     bool
     default y
+
+    choice
+        prompt "GIC Version"
+        default BSP_USING_GICV2
+
+        config BSP_USING_GICV2
+            bool "GICv2"
+
+        config BSP_USING_GICV3
+            bool "GICv3"
+    endchoice
+
 endmenu

+ 12 - 2
bsp/qemu-virt64-aarch64/driver/board.c

@@ -17,6 +17,7 @@
 #include "board.h"
 #include <mmu.h>
 #include <gic.h>
+#include <gicv3.h>
 #include <psci.h>
 #include <gtimer.h>
 #include <cpuport.h>
@@ -29,8 +30,14 @@ struct mem_desc platform_mem_desc[] =
     {0x40000000, 0x80000000, 0x40000000, NORMAL_MEM},
     {PL031_RTC_BASE, PL031_RTC_BASE + 0x1000, PL031_RTC_BASE, DEVICE_MEM},
     {PL011_UART0_BASE, PL011_UART0_BASE + 0x1000, PL011_UART0_BASE, DEVICE_MEM},
-    {VIRTIO_MMIO_BLK0_BASE, VIRTIO_MMIO_BLK0_BASE + 0x1000, VIRTIO_MMIO_BLK0_BASE, DEVICE_MEM},
+    {VIRTIO_MMIO_BASE, VIRTIO_MMIO_BASE + VIRTIO_MAX_NR * VIRTIO_MMIO_SIZE, VIRTIO_MMIO_BASE, DEVICE_MEM},
+#ifdef BSP_USING_GICV2
     {GIC_PL390_DISTRIBUTOR_PPTR, GIC_PL390_DISTRIBUTOR_PPTR + 0x1000, GIC_PL390_DISTRIBUTOR_PPTR, DEVICE_MEM},
+#endif
+#ifdef BSP_USING_GICV3
+    {GIC_PL500_DISTRIBUTOR_PPTR, GIC_PL500_DISTRIBUTOR_PPTR + 0x1000, GIC_PL500_DISTRIBUTOR_PPTR, DEVICE_MEM},
+    {GIC_PL500_REDISTRIBUTOR_PPTR, GIC_PL500_REDISTRIBUTOR_PPTR + 0xf60000, GIC_PL500_REDISTRIBUTOR_PPTR, DEVICE_MEM},
+#endif
 };
 
 const rt_uint32_t platform_mem_desc_size = sizeof(platform_mem_desc)/sizeof(platform_mem_desc[0]);
@@ -58,7 +65,7 @@ void rt_hw_board_init(void)
     rt_hw_gtimer_init();
     rt_thread_idle_sethook(idle_wfi);
 
-    arm_psci_init(RT_NULL, RT_NULL);
+    arm_psci_init(PSCI_METHOD_HVC, RT_NULL, RT_NULL);
 
 #if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
     /* set console device */
@@ -113,6 +120,9 @@ void secondary_cpu_c_start(void)
     rt_hw_spin_lock(&_cpus_lock);
 
     arm_gic_cpu_init(0, platform_get_gic_cpu_base());
+#ifdef BSP_USING_GICV3
+    arm_gic_redist_init(0, platform_get_gic_redist_base());
+#endif
     rt_hw_vector_init();
     rt_hw_gtimer_local_enable();
     arm_gic_umask(0, IRQ_ARM_IPI_KICK);

+ 2 - 56
bsp/qemu-virt64-aarch64/driver/board.h

@@ -6,72 +6,18 @@
  * Change Logs:
  * Date           Author       Notes
  * 2017-5-30      Bernard      the first version
- * 2021-07-31     GuEe-GUI     add ARM GIC definitions
- * 2021-09-11     GuEe-GUI     rename right macros for gic
  */
 
 #ifndef BOARD_H__
 #define BOARD_H__
 
-#include <rthw.h>
-#include <rtdef.h>
-#include <stdint.h>
+#include <virt.h>
 
 extern unsigned char __bss_start;
 extern unsigned char __bss_end;
 
 #define RT_HW_HEAP_BEGIN    (void*)&__bss_end
-#define RT_HW_HEAP_END      (void*)(RT_HW_HEAP_BEGIN + 1 * 1024 * 1024)
-
-#define __REG32(x)  (*((volatile unsigned int *)(x)))
-
-#define VIRTIO_SPI_IRQ_BASE         32
-
-/* Virtio BLK */
-#define VIRTIO_MMIO_BLK0_BASE       0x0a000000
-#define VIRTIO_MMIO_BLK0_SIZE       0x00000200
-#define VIRTIO_MMIO_BLK0_IRQ        (VIRTIO_SPI_IRQ_BASE + 0x10)
-
-/* UART */
-#define PL011_UARTDR                0x000
-#define PL011_UARTFR                0x018
-#define PL011_UARTFR_TXFF_BIT       5
-#define PL011_UART0_BASE            0x09000000
-#define PL011_UART0_SIZE            0x00001000
-#define PL011_UART0_IRQNUM          (VIRTIO_SPI_IRQ_BASE + 1)
-
-/* RTC */
-#define PL031_RTC_BASE              0x9010000
-#define PL031_RTC_SIZE              0x00001000
-#define PL031_RTC_IRQNUM            (VIRTIO_SPI_IRQ_BASE + 2)
-
-/* DIST and CPU */
-#define GIC_PL390_DISTRIBUTOR_PPTR  0x08000000
-#define GIC_PL390_CONTROLLER_PPTR   0x08010000
-
-#define MAX_HANDLERS                96
-#define GIC_IRQ_START               0
-/* number of interrupts on board */
-#define ARM_GIC_NR_IRQS             96
-/* only one GIC available */
-#define ARM_GIC_MAX_NR              1
-
-/* ipi interrupt number */
-#define IRQ_ARM_IPI_KICK            0
-#define IRQ_ARM_IPI_CALL            1
-
-#define IRQ_ARM_VTIMER              27
-
-/* the basic constants and interfaces needed by gic */
-rt_inline rt_uint32_t platform_get_gic_dist_base(void)
-{
-    return GIC_PL390_DISTRIBUTOR_PPTR;
-}
-
-rt_inline rt_uint32_t platform_get_gic_cpu_base(void)
-{
-    return GIC_PL390_CONTROLLER_PPTR;
-}
+#define RT_HW_HEAP_END      (void*)(RT_HW_HEAP_BEGIN + 64 * 1024 * 1024)
 
 void rt_hw_board_init(void);
 

+ 4 - 0
bsp/qemu-virt64-aarch64/driver/drv_uart.c

@@ -14,6 +14,10 @@
 
 #include "board.h"
 
+#define PL011_UARTDR            0x000
+#define PL011_UARTFR            0x018
+#define PL011_UARTFR_TXFF_BIT   5
+
 unsigned int readl(volatile void *addr)
 {
     return *(volatile unsigned int *)addr;

+ 62 - 0
bsp/qemu-virt64-aarch64/driver/drv_virtio.c

@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021-11-11     GuEe-GUI     the first version
+ */
+
+#include <rtthread.h>
+
+#include <virtio.h>
+#ifdef BSP_USING_VIRTIO_BLK
+#include <virtio_blk.h>
+#endif
+
+#include <board.h>
+
+static virtio_device_init_handler virtio_device_init_handlers[] =
+{
+#ifdef BSP_USING_VIRTIO_BLK
+    [VIRTIO_DEVICE_ID_BLOCK]    = rt_virtio_blk_init,
+#endif
+};
+
+int rt_virtio_devices_init(void)
+{
+    int i;
+    rt_uint32_t irq = VIRTIO_IRQ_BASE;
+    rt_ubase_t mmio_base = VIRTIO_MMIO_BASE;
+    struct virtio_mmio_config *mmio_config;
+    virtio_device_init_handler init_handler;
+
+    if (sizeof(virtio_device_init_handlers) == 0)
+    {
+        /* The compiler will optimize the codes after here. */
+        return 0;
+    }
+
+    for (i = 0; i < VIRTIO_MAX_NR; ++i, ++irq, mmio_base += VIRTIO_MMIO_SIZE)
+    {
+        mmio_config = (struct virtio_mmio_config *)mmio_base;
+
+        if (mmio_config->magic != VIRTIO_MAGIC_VALUE ||
+            mmio_config->version != RT_USING_VIRTIO_VERSION ||
+            mmio_config->vendor_id != VIRTIO_VENDOR_ID)
+        {
+            continue;
+        }
+
+        init_handler = virtio_device_init_handlers[mmio_config->device_id];
+
+        if (init_handler != RT_NULL)
+        {
+            init_handler((rt_ubase_t *)mmio_base, irq);
+        }
+    }
+
+    return 0;
+}
+INIT_DEVICE_EXPORT(rt_virtio_devices_init);

+ 16 - 0
bsp/qemu-virt64-aarch64/driver/drv_virtio.h

@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021-11-11     GuEe-GUI     the first version
+ */
+
+#ifndef __DRV_VIRTIO_H__
+#define __DRV_VIRTIO_H__
+
+int rt_virtio_devices_init(void);
+
+#endif /* __DRV_VIRTIO_H__ */

+ 81 - 0
bsp/qemu-virt64-aarch64/driver/virt.h

@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021-02-17     GuEe-GUI     the first version
+ */
+
+#ifndef VIRT_H__
+#define VIRT_H__
+
+#include <rtdef.h>
+
+/* UART */
+#define PL011_UART0_BASE    0x09000000
+#define PL011_UART0_SIZE    0x00001000
+#define PL011_UART0_IRQNUM  (32 + 1)
+
+/* RTC */
+#define PL031_RTC_BASE      0x9010000
+#define PL031_RTC_SIZE      0x00001000
+#define PL031_RTC_IRQNUM    (32 + 2)
+
+/* VirtIO */
+#define VIRTIO_MMIO_BASE    0x0a000000
+#define VIRTIO_MMIO_SIZE    0x00000200
+#define VIRTIO_MAX_NR       32
+#define VIRTIO_IRQ_BASE     (32 + 16)
+#define VIRTIO_VENDOR_ID    0x554d4551  /* "QEMU" */
+
+/* GIC */
+#define MAX_HANDLERS        96
+#define GIC_IRQ_START       0
+#define ARM_GIC_NR_IRQS     96
+#define ARM_GIC_MAX_NR      1
+
+#define IRQ_ARM_IPI_KICK    0
+#define IRQ_ARM_IPI_CALL    1
+
+/* GICv2 */
+#define GIC_PL390_DISTRIBUTOR_PPTR      0x08000000
+#define GIC_PL390_CONTROLLER_PPTR       0x08010000
+
+/* GICv3 */
+#define GIC_PL500_DISTRIBUTOR_PPTR      GIC_PL390_DISTRIBUTOR_PPTR
+#define GIC_PL500_REDISTRIBUTOR_PPTR    0x080a0000
+#define GIC_PL500_CONTROLLER_PPTR       GIC_PL390_CONTROLLER_PPTR
+#define GIC_PL500_ITS_PPTR              0x08080000
+
+/* the basic constants and interfaces needed by gic */
+rt_inline rt_uint32_t platform_get_gic_dist_base(void)
+{
+#ifdef BSP_USING_GICV2
+    return GIC_PL390_DISTRIBUTOR_PPTR;
+#else
+    return GIC_PL500_DISTRIBUTOR_PPTR;
+#endif
+}
+
+rt_inline rt_uint32_t platform_get_gic_redist_base(void)
+{
+    return GIC_PL500_REDISTRIBUTOR_PPTR;
+}
+
+rt_inline rt_uint32_t platform_get_gic_cpu_base(void)
+{
+#ifdef BSP_USING_GICV2
+    return GIC_PL390_CONTROLLER_PPTR;
+#else
+    return GIC_PL500_CONTROLLER_PPTR;
+#endif
+}
+
+rt_inline rt_uint32_t platform_get_gic_its_base(void)
+{
+    return GIC_PL500_ITS_PPTR;
+}
+
+#endif

+ 0 - 405
bsp/qemu-virt64-aarch64/driver/virtio/drv_virtio_blk.c

@@ -1,405 +0,0 @@
-/*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date           Author       Notes
- * 2021-9-16      GuEe-GUI     the first version
- */
-
-#include <rtconfig.h>
-#include <rtthread.h>
-#include <rthw.h>
-#include <cpuport.h>
-#include <board.h>
-
-#include "virtio.h"
-#include "virtio_mmio.h"
-#include "drv_virtio_blk.h"
-
-#ifdef BSP_USING_VIRTIO_BLK
-
-#ifdef RT_USING_VIRTIO_BLK0
-static struct virtio_blk blk0;
-static struct virtio_blk_device virtio_blk_dev0;
-#endif /* RT_USING_VIRTIO_BLK0 */
-
-static int alloc_desc(struct virtio_blk *blk)
-{
-    int i;
-    for(i = 0; i < QUEUE_SIZE; i++)
-    {
-        if (blk->free[i])
-        {
-            blk->free[i] = 0;
-            return i;
-        }
-    }
-    return -RT_ERROR;
-}
-
-static void free_desc(struct virtio_blk *blk, int i)
-{
-    if (i >= QUEUE_SIZE)
-    {
-        rt_kprintf("Out of queue number");
-        RT_ASSERT(0);
-    }
-    if (blk0.free[i])
-    {
-        rt_kprintf("Already freed");
-        RT_ASSERT(0);
-    }
-    blk->desc[i].addr = 0;
-    blk->desc[i].len = 0;
-    blk->desc[i].flags = 0;
-    blk->desc[i].next = 0;
-    blk->free[i] = 1;
-}
-
-static void free_chain(struct virtio_blk *blk, int i)
-{
-    int flag, nxt;
-    for (;;)
-    {
-        flag = blk->desc[i].flags;
-        nxt = blk->desc[i].next;
-
-        free_desc(blk, i);
-
-        if (flag & VRING_DESC_F_NEXT)
-        {
-            i = nxt;
-        }
-        else
-        {
-            break;
-        }
-    }
-}
-
-static int alloc3_desc(struct virtio_blk *blk, int *idx)
-{
-    for (int i = 0; i < 3; ++i)
-    {
-        idx[i] = alloc_desc(blk);
-        if (idx[i] < 0)
-        {
-            for (int j = 0; j < i; ++j)
-            {
-                free_desc(blk, idx[j]);
-            }
-            return -RT_ERROR;
-        }
-    }
-    return 0;
-}
-
-static int virtio_blk_device_init(struct virtio_blk_device *virtio_blk_dev)
-{
-    uint32_t status = 0;
-    uint32_t max;
-    uint64_t features;
-    int i;
-
-#ifdef RT_USING_SMP
-    rt_spin_lock_init(&virtio_blk_dev->spinlock);
-#endif
-
-    if (virtio_mmio_read32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_MAGIC_VALUE) != VIRTIO_MMIO_MAGIC ||
-        virtio_mmio_read32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_VERSION) != 1 ||
-        virtio_mmio_read32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_DEVICE_ID) != 2 ||
-        virtio_mmio_read32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_VENDOR_ID) != VIRTIO_MMIO_VENDOR)
-    {
-        rt_kprintf("Could not find virtio disk");
-
-        return -RT_ERROR;
-    }
-
-    status |= VIRTIO_STAT_ACKNOWLEDGE;
-    virtio_mmio_write32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_STATUS, status);
-
-    status |= VIRTIO_STAT_DRIVER;
-    virtio_mmio_write32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_STATUS, status);
-
-    /* negotiate features */
-    features = virtio_mmio_read32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_DEVICE_FEATURES);
-    features &= ~(1 << VIRTIO_BLK_F_RO);
-    features &= ~(1 << VIRTIO_BLK_F_SCSI);
-    features &= ~(1 << VIRTIO_BLK_F_CONFIG_WCE);
-    features &= ~(1 << VIRTIO_BLK_F_MQ);
-    features &= ~(1 << VIRTIO_F_ANY_LAYOUT);
-    features &= ~(1 << VIRTIO_RING_F_EVENT_IDX);
-    features &= ~(1 << VIRTIO_RING_F_INDIRECT_DESC);
-    virtio_mmio_write32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_DRIVER_FEATURES, features);
-
-    /* tell device that feature negotiation is complete */
-    status |= VIRTIO_STAT_FEATURES_OK;
-    virtio_mmio_write32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_STATUS, status);
-
-    /* tell device we're completely ready */
-    status |= VIRTIO_STAT_DRIVER_OK;
-    virtio_mmio_write32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_STATUS, status);
-
-    virtio_mmio_write32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_GUEST_PAGE_SIZE, PAGE_SIZE);
-
-    /* initialize queue 0 */
-    virtio_mmio_write32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_QUEUE_SEL, 0);
-
-    max = virtio_mmio_read32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_QUEUE_NUM_MAX);
-    if (max == 0)
-    {
-        rt_kprintf("Virtio disk has no queue 0");
-        RT_ASSERT(0);
-    }
-    if (max < QUEUE_SIZE)
-    {
-        rt_kprintf("Virtio disk max queue too short");
-        RT_ASSERT(0);
-    }
-    virtio_mmio_write32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_QUEUE_NUM, QUEUE_SIZE);
-
-    rt_memset(virtio_blk_dev->blk->pages, 0, sizeof(virtio_blk_dev->blk->pages));
-    virtio_mmio_write32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_QUEUE_PFN, ((uint64_t)blk0.pages) >> PAGE_SHIFT);
-
-    virtio_blk_dev->blk->desc = (struct virtq_desc *)virtio_blk_dev->blk->pages;
-    virtio_blk_dev->blk->avail = (struct virtq_avail *)(virtio_blk_dev->blk->pages + QUEUE_SIZE * sizeof(struct virtq_desc));
-    virtio_blk_dev->blk->used = (struct virtq_used *)(virtio_blk_dev->blk->pages + PAGE_SIZE);
-
-    /* all QUEUE_SIZE descriptors start out unused */
-    for (i = 0; i < QUEUE_SIZE; ++i)
-    {
-        virtio_blk_dev->blk->free[i] = 1;
-    }
-
-    return RT_EOK;
-}
-
-static void virtio_blk_rw(struct virtio_blk_device *virtio_blk_dev, struct virtio_blk_buf *buf, int flag)
-{
-    struct virtio_blk *blk = virtio_blk_dev->blk;
-    uint64_t sector = buf->block_no * (VIRTIO_BLK_BUF_DATA_SIZE / 512);
-    int idx[3];
-    struct virtio_blk_req *req;
-
-#ifdef RT_USING_SMP
-    rt_base_t level;
-
-    level = rt_spin_lock_irqsave(&virtio_blk_dev->spinlock);
-#endif
-
-    /* allocate the three descriptors */
-    for (;;)
-    {
-        if (alloc3_desc(blk, idx) == 0)
-        {
-            break;
-        }
-    }
-
-    req = &(blk->ops[idx[0]]);
-    req->type = flag;
-    req->reserved = 0;
-    req->sector = sector;
-
-    blk->desc[idx[0]].addr = (uint64_t)req;
-    blk->desc[idx[0]].len = sizeof(struct virtio_blk_req);
-    blk->desc[idx[0]].flags = VRING_DESC_F_NEXT;
-    blk->desc[idx[0]].next = idx[1];
-
-    blk->desc[idx[1]].addr = (uint64_t)buf->data;
-    blk->desc[idx[1]].len = VIRTIO_BLK_BUF_DATA_SIZE;
-
-    blk->desc[idx[1]].flags = flag ? 0 : VRING_DESC_F_WRITE;
-
-    blk->desc[idx[1]].flags |= VRING_DESC_F_NEXT;
-    blk->desc[idx[1]].next = idx[2];
-
-    /* device writes 0 on success */
-    blk->info[idx[0]].status = 0xff;
-    blk->desc[idx[2]].addr = (uint64_t)&(blk->info[idx[0]].status);
-    blk->desc[idx[2]].len = 1;
-    /* device writes the status */
-    blk->desc[idx[2]].flags = VRING_DESC_F_WRITE;
-    blk->desc[idx[2]].next = 0;
-
-    /* record struct buf for virtio_blk_isr() */
-    buf->valid = 1;
-    blk->info[idx[0]].buf = buf;
-
-    /* tell the device the first index in our chain of descriptors */
-    blk->avail->ring[blk->avail->idx % QUEUE_SIZE] = idx[0];
-
-    rt_hw_dsb();
-
-    /* tell the device another avail ring entry is available */
-    blk->avail->idx += 1;
-
-    rt_hw_dsb();
-
-    /* value is queue number */
-    virtio_mmio_write32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_QUEUE_NOTIFY, 0);
-
-    /* wait for virtio_blk_isr() to done */
-    while (buf->valid == 1)
-    {
-#ifdef RT_USING_SMP
-        rt_spin_unlock_irqrestore(&virtio_blk_dev->spinlock, level);
-#endif
-        rt_thread_yield();
-#ifdef RT_USING_SMP
-        level = rt_spin_lock_irqsave(&virtio_blk_dev->spinlock);
-#endif
-    }
-
-    blk->info[idx[0]].buf = 0;
-    free_chain(blk, idx[0]);
-
-#ifdef RT_USING_SMP
-    rt_spin_unlock_irqrestore(&virtio_blk_dev->spinlock, level);
-#endif
-}
-
-static void virtio_blk_isr(int irqno, void *param)
-{
-    int id;
-    struct virtio_blk_device *virtio_blk_dev = (struct virtio_blk_device *)param;
-    struct virtio_blk *blk = virtio_blk_dev->blk;
-    struct virtio_blk_buf *buf_tmp;
-
-#ifdef RT_USING_SMP
-    rt_base_t level;
-
-    level = rt_spin_lock_irqsave(&virtio_blk_dev->spinlock);
-#endif
-
-    virtio_mmio_write32(
-        virtio_blk_dev->mmio_base,
-        VIRTIO_MMIO_INTERRUPT_ACK,
-        virtio_mmio_read32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_INTERRUPT_STATUS) & 0x3);
-
-    rt_hw_dsb();
-
-    /*
-     * the device increments disk.used->idx
-     * when it adds an entry to the used ring
-     */
-    while (blk->used_idx != blk->used->idx)
-    {
-        rt_hw_dsb();
-        id = blk->used->ring[blk->used_idx % QUEUE_SIZE].id;
-
-        if (blk->info[id].status != 0)
-        {
-            rt_kprintf("Virtio BLK Status");
-            RT_ASSERT(0);
-        }
-
-        buf_tmp = blk->info[id].buf;
-
-        /* done with buf */
-        buf_tmp->valid = 0;
-        rt_thread_yield();
-
-        blk->used_idx += 1;
-    }
-
-#ifdef RT_USING_SMP
-    rt_spin_unlock_irqrestore(&virtio_blk_dev->spinlock, level);
-#endif
-}
-
-static rt_err_t virtio_blk_init(rt_device_t dev)
-{
-    return RT_EOK;
-}
-
-static rt_err_t virtio_blk_open(rt_device_t dev, rt_uint16_t oflag)
-{
-    return RT_EOK;
-}
-
-static rt_err_t virtio_blk_close(rt_device_t dev)
-{
-    return RT_EOK;
-}
-
-static rt_size_t virtio_blk_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
-{
-    struct virtio_blk_device *virtio_blk_dev = (struct virtio_blk_device *)dev;
-    struct virtio_blk_buf buf =
-    {
-        .block_no = (uint32_t)pos,
-        .data = (uint8_t *)buffer
-    };
-
-    virtio_blk_rw(virtio_blk_dev, &buf, VIRTIO_BLK_T_IN);
-
-    return size;
-}
-
-static rt_size_t virtio_blk_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
-{
-    struct virtio_blk_device *virtio_blk_dev = (struct virtio_blk_device *)dev;
-    struct virtio_blk_buf buf =
-    {
-        .block_no = (uint32_t)pos,
-        .data = (uint8_t *)buffer
-    };
-
-    virtio_blk_rw(virtio_blk_dev, &buf, VIRTIO_BLK_T_OUT);
-
-    return size;
-}
-
-static rt_err_t virtio_blk_control(rt_device_t dev, int cmd, void *args)
-{
-    if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME)
-    {
-        struct rt_device_blk_geometry *geometry;
-
-        geometry = (struct rt_device_blk_geometry *)args;
-        if (geometry == RT_NULL)
-        {
-            return -RT_ERROR;
-        }
-
-        geometry->bytes_per_sector = VIRTIO_BLK_BYTES_PER_SECTOR;
-        geometry->block_size = VIRTIO_BLK_BLOCK_SIZE;
-        geometry->sector_count = VIRTIO_BLK_SECTOR_COUNT;
-    }
-
-    return RT_EOK;
-}
-
-const static struct rt_device_ops virtio_blk_ops =
-{
-    virtio_blk_init,
-    virtio_blk_open,
-    virtio_blk_close,
-    virtio_blk_read,
-    virtio_blk_write,
-    virtio_blk_control
-};
-
-int rt_virtio_blk_init(void)
-{
-    rt_err_t status = RT_EOK;
-
-#ifdef RT_USING_VIRTIO_BLK0
-    virtio_blk_dev0.parent.type = RT_Device_Class_Block;
-    virtio_blk_dev0.parent.ops  = &virtio_blk_ops;
-    virtio_blk_dev0.blk = &blk0;
-    virtio_blk_dev0.mmio_base = (uint32_t *)VIRTIO_MMIO_BLK0_BASE;
-
-    status = virtio_blk_device_init(&virtio_blk_dev0);
-    rt_device_register((rt_device_t)&virtio_blk_dev0, "virtio-blk0", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE);
-    rt_hw_interrupt_install(VIRTIO_MMIO_BLK0_IRQ, virtio_blk_isr, &virtio_blk_dev0, "virtio-blk0");
-    rt_hw_interrupt_umask(VIRTIO_MMIO_BLK0_IRQ);
-#endif /* RT_USING_VIRTIO_BLK0 */
-
-    return status;
-}
-INIT_DEVICE_EXPORT(rt_virtio_blk_init);
-#endif /* BSP_USING_VIRTIO_BLK */

+ 0 - 85
bsp/qemu-virt64-aarch64/driver/virtio/drv_virtio_blk.h

@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date           Author       Notes
- * 2021-9-16      GuEe-GUI     the first version
- */
-
-#ifndef DRV_VIRTIO_BLK_H__
-#define DRV_VIRTIO_BLK_H__
-
-#include <rthw.h>
-#include <stdint.h>
-#include "virtio.h"
-
-#define VIRTIO_BLK_BUF_DATA_SIZE        512
-#define VIRTIO_BLK_BYTES_PER_SECTOR     512
-#define VIRTIO_BLK_BLOCK_SIZE           512
-#define VIRTIO_BLK_SECTOR_COUNT         0x40000 /* 128MB */
-
-#define VIRTIO_BLK_F_RO                 5   /* Disk is read-only */
-#define VIRTIO_BLK_F_SCSI               7   /* Supports scsi command passthru */
-#define VIRTIO_BLK_F_CONFIG_WCE         11  /* Writeback mode available in config */
-#define VIRTIO_BLK_F_MQ                 12  /* Support more than one vq */
-
-#define VIRTIO_BLK_T_IN                 0   /* Read the blk */
-#define VIRTIO_BLK_T_OUT                1   /* Write the blk */
-
-#define VIRTIO_F_ANY_LAYOUT             27
-#define VIRTIO_RING_F_INDIRECT_DESC     28
-#define VIRTIO_RING_F_EVENT_IDX         29
-
-struct virtio_blk_buf
-{
-    int valid;
-    uint32_t block_no;
-    uint8_t *data;
-};
-
-struct virtio_blk_req
-{
-    uint32_t type;
-    uint32_t reserved;
-    uint64_t sector;
-};
-
-/*
- * virtio_blk must be a static variable because
- * pages must consist of two contiguous pages of
- * page-aligned physical memory
- */
-struct virtio_blk
-{
-    char pages[2 * PAGE_SIZE];
-    struct virtq_desc *desc;
-    struct virtq_avail *avail;
-    struct virtq_used *used;
-
-    char free[QUEUE_SIZE];
-    uint16_t used_idx;
-    struct
-    {
-        struct virtio_blk_buf *buf;
-        char status;
-    } info[QUEUE_SIZE];
-
-    struct virtio_blk_req ops[QUEUE_SIZE];
-} __attribute__ ((aligned (PAGE_SIZE)));
-
-struct virtio_blk_device
-{
-    struct rt_device parent;
-    struct virtio_blk *blk;
-
-    uint32_t *mmio_base;
-#ifdef RT_USING_SMP
-    struct rt_spinlock spinlock;
-#endif
-};
-
-int rt_hw_virtio_blk_init(void);
-
-#endif /* DRV_VIRTIO_BLK_H__ */

+ 274 - 0
bsp/qemu-virt64-aarch64/driver/virtio/virtio.c

@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021-11-11     GuEe-GUI     the first version
+ */
+
+#include <rtthread.h>
+#include <cpuport.h>
+
+#include <virtio.h>
+
+rt_inline void _virtio_dev_check(struct virtio_device *dev)
+{
+    RT_ASSERT(dev != RT_NULL);
+    RT_ASSERT(dev->mmio_config != RT_NULL);
+}
+
+void virtio_reset_device(struct virtio_device *dev)
+{
+    _virtio_dev_check(dev);
+
+    dev->mmio_config->status = 0;
+}
+
+void virtio_status_acknowledge_driver(struct virtio_device *dev)
+{
+    _virtio_dev_check(dev);
+
+    dev->mmio_config->status |= VIRTIO_STATUS_ACKNOWLEDGE | VIRTIO_STATUS_DRIVER;
+}
+
+void virtio_status_driver_ok(struct virtio_device *dev)
+{
+    _virtio_dev_check(dev);
+
+    dev->mmio_config->status |= VIRTIO_STATUS_FEATURES_OK | VIRTIO_STATUS_DRIVER_OK;
+}
+
+void virtio_interrupt_ack(struct virtio_device *dev, rt_uint32_t ack)
+{
+    _virtio_dev_check(dev);
+
+    dev->mmio_config->interrupt_ack = ack;
+}
+
+rt_err_t virtio_queue_init(struct virtio_device *dev, rt_uint32_t queue_index, rt_size_t ring_size)
+{
+    int i;
+    void *pages;
+    rt_ubase_t pages_paddr;
+    rt_size_t pages_total_size;
+    struct virtq *queue;
+
+    _virtio_dev_check(dev);
+
+    RT_ASSERT(dev->mmio_config->queue_num_max > 0);
+    RT_ASSERT(dev->mmio_config->queue_num_max > queue_index);
+    /* ring_size is power of 2 */
+    RT_ASSERT(ring_size > 0);
+    RT_ASSERT(((ring_size - 1) & ring_size) == 0);
+
+    queue = &dev->queues[queue_index];
+    pages_total_size = VIRTIO_PAGE_ALIGN(
+            VIRTQ_DESC_TOTAL_SIZE(ring_size) + VIRTQ_AVAIL_TOTAL_SIZE(ring_size) + VIRTQ_USED_TOTAL_SIZE(ring_size));
+
+    pages = rt_malloc_align(pages_total_size, VIRTIO_PAGE_SIZE);
+
+    if (pages == RT_NULL)
+    {
+        return -RT_ENOMEM;
+    }
+
+    queue->free = rt_malloc(sizeof(rt_bool_t) * ring_size);
+
+    if (queue->free == RT_NULL)
+    {
+        rt_free_align(pages);
+        return -RT_ENOMEM;
+    }
+
+    rt_memset(pages, 0, pages_total_size);
+    pages_paddr = VIRTIO_VA2PA(pages);
+
+    dev->mmio_config->guest_page_size = VIRTIO_PAGE_SIZE;
+    dev->mmio_config->queue_sel = queue_index;
+    dev->mmio_config->queue_num = ring_size;
+    dev->mmio_config->queue_align = VIRTIO_PAGE_SIZE;
+    dev->mmio_config->queue_pfn = pages_paddr >> VIRTIO_PAGE_SHIFT;
+
+    queue->num = ring_size;
+    queue->desc = (struct virtq_desc *)pages_paddr;
+    queue->avail = (struct virtq_avail *)(pages_paddr + VIRTQ_DESC_TOTAL_SIZE(ring_size));
+    queue->used = (struct virtq_used *)VIRTIO_PAGE_ALIGN(
+            (rt_ubase_t)&queue->avail->ring[ring_size] + VIRTQ_AVAIL_RES_SIZE);
+
+    queue->used_idx = 0;
+
+    /* All descriptors start out unused */
+    for (i = 0; i < ring_size; ++i)
+    {
+        queue->free[i] = RT_TRUE;
+    }
+
+    return RT_EOK;
+}
+
+void virtio_queue_destroy(struct virtio_device *dev, rt_uint32_t queue_index)
+{
+    struct virtq *queue;
+
+    _virtio_dev_check(dev);
+
+    RT_ASSERT(dev->mmio_config->queue_num_max > 0);
+    RT_ASSERT(dev->mmio_config->queue_num_max > queue_index);
+
+    queue = &dev->queues[queue_index];
+
+    RT_ASSERT(queue->num > 0);
+
+    rt_free(queue->free);
+    rt_free_align((void *)queue->desc);
+
+    dev->mmio_config->queue_sel = queue_index;
+    dev->mmio_config->queue_pfn = RT_NULL;
+
+    queue->num = 0;
+    queue->desc = RT_NULL;
+    queue->avail = RT_NULL;
+    queue->used = RT_NULL;
+}
+
+void virtio_queue_notify(struct virtio_device *dev, rt_uint32_t queue_index)
+{
+    _virtio_dev_check(dev);
+
+    dev->mmio_config->queue_notify = queue_index;
+}
+
+void virtio_submit_chain(struct virtio_device *dev, rt_uint32_t queue_index, rt_uint16_t desc_index)
+{
+    rt_size_t ring_size;
+    struct virtq *queue;
+
+    _virtio_dev_check(dev);
+
+    queue = &dev->queues[queue_index];
+    ring_size = queue->num;
+
+    /* Tell the device the first index in our chain of descriptors */
+    queue->avail->ring[queue->avail->idx % ring_size] = desc_index;
+    rt_hw_dsb();
+
+    /* Tell the device another avail ring entry is available */
+    queue->avail->idx++;
+    rt_hw_dsb();
+}
+
+rt_uint16_t virtio_alloc_desc(struct virtio_device *dev, rt_uint32_t queue_index)
+{
+    int i;
+    rt_size_t ring_size;
+    struct virtq *queue;
+
+    _virtio_dev_check(dev);
+
+    RT_ASSERT(queue_index < RT_USING_VIRTIO_QUEUE_MAX_NR);
+
+    queue = &dev->queues[queue_index];
+    ring_size = queue->num;
+
+    for (i = 0; i < ring_size; ++i)
+    {
+        if (queue->free[i])
+        {
+            queue->free[i] = RT_FALSE;
+
+            return (rt_uint16_t)i;
+        }
+    }
+
+    return RT_UINT16_MAX;
+}
+
+void virtio_free_desc(struct virtio_device *dev, rt_uint32_t queue_index, rt_uint16_t desc_index)
+{
+    struct virtq *queue;
+
+    _virtio_dev_check(dev);
+
+    queue = &dev->queues[queue_index];
+
+    RT_ASSERT(queue_index + 1 < RT_USING_VIRTIO_QUEUE_MAX_NR);
+    RT_ASSERT(!queue->free[desc_index]);
+
+    queue->desc[desc_index].addr = 0;
+    queue->desc[desc_index].len = 0;
+    queue->desc[desc_index].flags = 0;
+    queue->desc[desc_index].next = 0;
+
+    queue->free[desc_index] = RT_TRUE;
+}
+
+rt_err_t virtio_alloc_desc_chain(struct virtio_device *dev, rt_uint32_t queue_index, rt_size_t count,
+        rt_uint16_t *indexs)
+{
+    int i, j;
+
+    _virtio_dev_check(dev);
+
+    RT_ASSERT(indexs != RT_NULL);
+
+    for (i = 0; i < count; ++i)
+    {
+        indexs[i] = virtio_alloc_desc(dev, queue_index);
+
+        if (indexs[i] == RT_UINT16_MAX)
+        {
+            for (j = 0; j < i; ++j)
+            {
+                virtio_free_desc(dev, queue_index, indexs[j]);
+            }
+
+            return -RT_ERROR;
+        }
+    }
+
+    return RT_EOK;
+}
+
+void virtio_free_desc_chain(struct virtio_device *dev, rt_uint32_t queue_index, rt_uint16_t desc_index)
+{
+    rt_uint16_t flags, next;
+    struct virtq_desc *desc;
+
+    _virtio_dev_check(dev);
+
+    desc = &dev->queues[queue_index].desc[0];
+
+    for (;;)
+    {
+        flags = desc[desc_index].flags;
+        next = desc[desc_index].next;
+
+        virtio_free_desc(dev, queue_index, desc_index);
+
+        if (flags & VIRTQ_DESC_F_NEXT)
+        {
+            desc_index = next;
+        }
+        else
+        {
+            break;
+        }
+    }
+}
+
+void virtio_fill_desc(struct virtio_device *dev, rt_uint32_t queue_index, rt_uint16_t desc_index,
+        rt_uint64_t addr, rt_uint32_t len, rt_uint16_t flags, rt_uint16_t next)
+{
+    struct virtq_desc *desc;
+
+    _virtio_dev_check(dev);
+
+    desc = &dev->queues[queue_index].desc[desc_index];
+
+    desc->addr = addr;
+    desc->len = len;
+    desc->flags = flags;
+    desc->next = next;
+}

+ 96 - 36
bsp/qemu-virt64-aarch64/driver/virtio/virtio.h

@@ -6,55 +6,115 @@
  * Change Logs:
  * Date           Author       Notes
  * 2021-9-16      GuEe-GUI     the first version
+ * 2021-11-11     GuEe-GUI     modify to virtio common interface
  */
 
-#ifndef VIRTIO_H__
-#define VIRTIO_H__
+#ifndef __VIRTIO_H__
+#define __VIRTIO_H__
 
-#include <stdint.h>
+#include <rthw.h>
+#include <rtdef.h>
 
-#define PAGE_SIZE   4096
-#define PAGE_SHIFT  12
+#ifndef RT_USING_VIRTIO_VERSION
+#define RT_USING_VIRTIO_VERSION 0x1
+#endif
 
-#define VIRTIO_STAT_ACKNOWLEDGE     1
-#define VIRTIO_STAT_DRIVER          2
-#define VIRTIO_STAT_DRIVER_OK       4
-#define VIRTIO_STAT_FEATURES_OK     8
-#define VIRTIO_STAT_NEEDS_RESET     64
-#define VIRTIO_STAT_FAILED          128
+#ifndef RT_USING_VIRTIO_QUEUE_MAX_NR
+#define RT_USING_VIRTIO_QUEUE_MAX_NR 4
+#endif
 
-#define QUEUE_SIZE  8
+#include <virtio_mmio.h>
+#include <virtio_queue.h>
 
-struct virtq_desc
-{
-    uint64_t addr;
-    uint32_t len;
-    uint16_t flags;
-    uint16_t next;
-};
+#define VIRTIO_MAGIC_VALUE          0x74726976 /* "virt" */
 
-#define VRING_DESC_F_NEXT  1    // chained with another descriptor
-#define VRING_DESC_F_WRITE 2    // device writes (vs read)
+#define VIRTIO_STATUS_ACKNOWLEDGE   (1 << 0)
+#define VIRTIO_STATUS_DRIVER        (1 << 1)
+#define VIRTIO_STATUS_DRIVER_OK     (1 << 2)
+#define VIRTIO_STATUS_FEATURES_OK   (1 << 3)
+#define VIRTIO_STATUS_NEEDS_RESET   (1 << 6)
+#define VIRTIO_STATUS_FAILED        (1 << 7)
 
-struct virtq_avail
-{
-    uint16_t flags;             // always zero
-    uint16_t idx;               // driver will write ring[idx] next
-    uint16_t ring[QUEUE_SIZE];  // descriptor numbers of chain heads
-    uint16_t unused;
-};
+#define VIRTIO_F_NOTIFY_ON_EMPTY    24
+#define VIRTIO_F_ANY_LAYOUT         27
+#define VIRTIO_F_RING_INDIRECT_DESC 28
+#define VIRTIO_F_RING_EVENT_IDX     29
+#define VIRTIO_F_VERSION_1          32
+#define VIRTIO_F_RING_PACKED        34
 
-struct virtq_used_elem
+#define VIRTIO_VA2PA(vaddr)         ((rt_ubase_t)vaddr)
+#define VIRTIO_PAGE_SHIFT           12
+#define VIRTIO_PAGE_SIZE            (1 << VIRTIO_PAGE_SHIFT)
+#define VIRTIO_PAGE_ALIGN(addr)     (RT_ALIGN(addr, VIRTIO_PAGE_SIZE))
+
+enum
 {
-    uint32_t id;   // index of start of completed descriptor chain
-    uint32_t len;
+    /* virtio 1.0 */
+    VIRTIO_DEVICE_ID_INVALID        = 0,    /* Invalid device */
+    VIRTIO_DEVICE_ID_NET            = 1,    /* Net */
+    VIRTIO_DEVICE_ID_BLOCK          = 2,    /* Block */
+    VIRTIO_DEVICE_ID_CONSOLE        = 3,    /* Console */
+    VIRTIO_DEVICE_ID_RNG            = 4,    /* Rng */
+    VIRTIO_DEVICE_ID_BALLOON        = 5,    /* Balloon */
+    VIRTIO_DEVICE_ID_IOMEM          = 6,    /* IO memory */
+    VIRTIO_DEVICE_ID_RPMSG          = 7,    /* Remote processor messaging */
+    VIRTIO_DEVICE_ID_SCSI           = 8,    /* SCSI */
+    VIRTIO_DEVICE_ID_9P             = 9,    /* 9p console */
+    VIRTIO_DEVICE_ID_MAC80211_WLAN  = 10,   /* Mac80211 wlan */
+    VIRTIO_DEVICE_ID_RPROC_SERIAL   = 11,   /* Remoteproc serial link */
+    VIRTIO_DEVICE_ID_CAIF           = 12,   /* CAIF */
+    VIRTIO_DEVICE_ID_MEM_BALLOON    = 13,   /* Memory balloon */
+    VIRTIO_DEVICE_ID_GPU            = 16,   /* GPU */
+    VIRTIO_DEVICE_ID_TIME           = 17,   /* Timer/clock device */
+    VIRTIO_DEVICE_ID_INPUT          = 18,   /* Input */
+    /* virtio 1.1 */
+    VIRTIO_DEVICE_ID_SOCKET         = 19,   /* Socket device */
+    VIRTIO_DEVICE_ID_CRYPTO         = 20,   /* Crypto device */
+    VIRTIO_DEVICE_ID_SIG_DIS_MOD    = 21,   /* Signal Distribution Module */
+    VIRTIO_DEVICE_ID_PSTORE         = 22,   /* Pstore device */
+    VIRTIO_DEVICE_ID_IOMMU          = 23,   /* IOMMU device */
+    VIRTIO_DEVICE_ID_MEM            = 24,   /* Memory device */
+
+    VIRTIO_DEVICE_TYPE_SIZE
 };
 
-struct virtq_used
+struct virtio_device
 {
-    uint16_t flags;                         // always zero
-    uint16_t idx;                           // device increments when it adds a ring[] entry
-    struct virtq_used_elem ring[QUEUE_SIZE];
+    rt_uint32_t irq;
+
+    struct virtq queues[RT_USING_VIRTIO_QUEUE_MAX_NR];
+    union
+    {
+        rt_ubase_t *mmio_base;
+        struct virtio_mmio_config *mmio_config;
+    };
+
+#ifdef RT_USING_SMP
+    struct rt_spinlock spinlock;
+#endif
+
+    void *priv;
 };
 
-#endif /* VIRTIO_H__ */
+typedef rt_err_t (*virtio_device_init_handler)(rt_ubase_t *mmio_base, rt_uint32_t irq);
+
+void virtio_reset_device(struct virtio_device *dev);
+void virtio_status_acknowledge_driver(struct virtio_device *dev);
+void virtio_status_driver_ok(struct virtio_device *dev);
+void virtio_interrupt_ack(struct virtio_device *dev, rt_uint32_t ack);
+
+rt_err_t virtio_queue_init(struct virtio_device *dev, rt_uint32_t queue_index, rt_size_t ring_size);
+void virtio_queue_destroy(struct virtio_device *dev, rt_uint32_t queue_index);
+void virtio_queue_notify(struct virtio_device *dev, rt_uint32_t queue_index);
+
+void virtio_submit_chain(struct virtio_device *dev, rt_uint32_t queue_index, rt_uint16_t desc_index);
+
+rt_uint16_t virtio_alloc_desc(struct virtio_device *dev, rt_uint32_t queue_index);
+void virtio_free_desc(struct virtio_device *dev, rt_uint32_t queue_index, rt_uint16_t desc_index);
+rt_err_t virtio_alloc_desc_chain(struct virtio_device *dev, rt_uint32_t queue_index, rt_size_t count,
+        rt_uint16_t *indexs);
+void virtio_free_desc_chain(struct virtio_device *dev, rt_uint32_t queue_index, rt_uint16_t desc_index);
+void virtio_fill_desc(struct virtio_device *dev, rt_uint32_t queue_index, rt_uint16_t desc_index,
+        rt_uint64_t addr, rt_uint32_t len, rt_uint16_t flags, rt_uint16_t next);
+
+#endif /* __VIRTIO_H__ */

+ 216 - 0
bsp/qemu-virt64-aarch64/driver/virtio/virtio_blk.c

@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021-9-16      GuEe-GUI     the first version
+ * 2021-11-11     GuEe-GUI     using virtio common interface
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <cpuport.h>
+
+#include <virtio_blk.h>
+
+#ifdef BSP_USING_VIRTIO_BLK
+static void virtio_blk_rw(struct virtio_blk_device *virtio_blk_dev, rt_off_t pos, void *buffer, int flags)
+{
+    rt_uint16_t idx[3];
+    struct virtio_device *virtio_dev = &virtio_blk_dev->virtio_dev;
+
+#ifdef RT_USING_SMP
+    rt_base_t level = rt_spin_lock_irqsave(&virtio_dev->spinlock);
+#endif
+
+    /* Allocate 3 descriptors */
+    while (virtio_alloc_desc_chain(virtio_dev, 0, 3, idx))
+    {
+    }
+
+    virtio_blk_dev->info[idx[0]].status = 0xff;
+    virtio_blk_dev->info[idx[0]].valid = RT_TRUE;
+    virtio_blk_dev->info[idx[0]].req.type = flags;
+    virtio_blk_dev->info[idx[0]].req.ioprio = 0;
+    virtio_blk_dev->info[idx[0]].req.sector = pos * (VIRTIO_BLK_BUF_DATA_SIZE / 512);
+
+    flags = flags == VIRTIO_BLK_T_OUT ? 0 : VIRTQ_DESC_F_WRITE;
+
+    virtio_fill_desc(virtio_dev, 0, idx[0],
+            VIRTIO_VA2PA(&virtio_blk_dev->info[idx[0]].req), sizeof(struct virtio_blk_req), VIRTQ_DESC_F_NEXT, idx[1]);
+
+    virtio_fill_desc(virtio_dev, 0, idx[1],
+            VIRTIO_VA2PA(buffer), VIRTIO_BLK_BUF_DATA_SIZE, flags | VIRTQ_DESC_F_NEXT, idx[2]);
+
+    virtio_fill_desc(virtio_dev, 0, idx[2],
+            VIRTIO_VA2PA(&virtio_blk_dev->info[idx[0]].status), 1, VIRTQ_DESC_F_WRITE, 0);
+
+    virtio_submit_chain(virtio_dev, 0, idx[0]);
+
+    virtio_queue_notify(virtio_dev, 0);
+
+    /* Wait for virtio_blk_isr() to done */
+    while (virtio_blk_dev->info[idx[0]].valid)
+    {
+#ifdef RT_USING_SMP
+        rt_spin_unlock_irqrestore(&virtio_dev->spinlock, level);
+#endif
+        rt_thread_yield();
+
+#ifdef RT_USING_SMP
+        level = rt_spin_lock_irqsave(&virtio_dev->spinlock);
+#endif
+    }
+
+    virtio_free_desc_chain(virtio_dev, 0, idx[0]);
+
+#ifdef RT_USING_SMP
+    rt_spin_unlock_irqrestore(&virtio_dev->spinlock, level);
+#endif
+}
+
+static rt_size_t virtio_blk_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
+{
+    virtio_blk_rw((struct virtio_blk_device *)dev, pos, buffer, VIRTIO_BLK_T_IN);
+
+    return size;
+}
+
+static rt_size_t virtio_blk_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
+{
+    virtio_blk_rw((struct virtio_blk_device *)dev, pos, (void *)buffer, VIRTIO_BLK_T_OUT);
+
+    return size;
+}
+
+static rt_err_t virtio_blk_control(rt_device_t dev, int cmd, void *args)
+{
+    rt_err_t status = RT_EOK;
+    struct virtio_blk_device *virtio_blk_dev = (struct virtio_blk_device *)dev;
+
+    switch (cmd)
+    {
+    case RT_DEVICE_CTRL_BLK_GETGEOME:
+        {
+            struct rt_device_blk_geometry *geometry = (struct rt_device_blk_geometry *)args;
+
+            if (geometry == RT_NULL)
+            {
+                status = -RT_ERROR;
+                break;
+            }
+
+            geometry->bytes_per_sector = VIRTIO_BLK_BYTES_PER_SECTOR;
+            geometry->block_size = VIRTIO_BLK_BLOCK_SIZE;
+            geometry->sector_count = virtio_blk_dev->virtio_dev.mmio_config->config[0];
+        }
+        break;
+    default:
+        break;
+    }
+
+    return status;
+}
+
+const static struct rt_device_ops virtio_blk_ops =
+{
+    RT_NULL,
+    RT_NULL,
+    RT_NULL,
+    virtio_blk_read,
+    virtio_blk_write,
+    virtio_blk_control
+};
+
+static void virtio_blk_isr(int irqno, void *param)
+{
+    rt_uint32_t id;
+    struct virtio_blk_device *virtio_blk_dev = (struct virtio_blk_device *)param;
+    struct virtio_device *virtio_dev = &virtio_blk_dev->virtio_dev;
+
+#ifdef RT_USING_SMP
+    rt_base_t level = rt_spin_lock_irqsave(&virtio_dev->spinlock);
+#endif
+
+    virtio_interrupt_ack(virtio_dev, virtio_dev->mmio_config->interrupt_status & 0x3);
+    rt_hw_dsb();
+
+    /* The device increments disk.used->idx when it adds an entry to the used ring */
+    while (virtio_dev->queues[0].used_idx != virtio_dev->queues[0].used->idx)
+    {
+        rt_hw_dsb();
+        id = virtio_dev->queues[0].used->ring[virtio_dev->queues[0].used_idx % VIRTIO_BLK_QUEUE_RING_SIZE].id;
+
+        RT_ASSERT(virtio_blk_dev->info[id].status == 0);
+
+        /* Done with buffer */
+        virtio_blk_dev->info[id].valid = RT_FALSE;
+        rt_thread_yield();
+
+        virtio_dev->queues[0].used_idx++;
+    }
+
+#ifdef RT_USING_SMP
+    rt_spin_unlock_irqrestore(&virtio_dev->spinlock, level);
+#endif
+}
+
+rt_err_t rt_virtio_blk_init(rt_ubase_t *mmio_base, rt_uint32_t irq)
+{
+    static int dev_no = 0;
+    char dev_name[RT_NAME_MAX];
+    struct virtio_device *virtio_dev;
+    struct virtio_blk_device *virtio_blk_dev;
+
+    virtio_blk_dev = rt_malloc(sizeof(struct virtio_blk_device));
+
+    if (virtio_blk_dev == RT_NULL)
+    {
+        return -RT_ENOMEM;
+    }
+
+    virtio_dev = &virtio_blk_dev->virtio_dev;
+    virtio_dev->irq = irq;
+    virtio_dev->mmio_base = mmio_base;
+
+#ifdef RT_USING_SMP
+    rt_spin_lock_init(&virtio_dev->spinlock);
+#endif
+
+    virtio_reset_device(virtio_dev);
+    virtio_status_acknowledge_driver(virtio_dev);
+
+    /* Negotiate features */
+    virtio_dev->mmio_config->driver_features = virtio_dev->mmio_config->device_features & ~(
+            (1 << VIRTIO_BLK_F_RO) |
+            (1 << VIRTIO_BLK_F_MQ) |
+            (1 << VIRTIO_BLK_F_SCSI) |
+            (1 << VIRTIO_BLK_F_CONFIG_WCE) |
+            (1 << VIRTIO_F_ANY_LAYOUT) |
+            (1 << VIRTIO_F_RING_EVENT_IDX) |
+            (1 << VIRTIO_F_RING_INDIRECT_DESC));
+
+    /* Tell device that feature negotiation is complete and we're completely ready */
+    virtio_status_driver_ok(virtio_dev);
+
+    /* Initialize queue 0 */
+    if (virtio_queue_init(virtio_dev, 0, VIRTIO_BLK_QUEUE_RING_SIZE) != RT_EOK)
+    {
+        rt_free(virtio_blk_dev);
+
+        return -RT_ENOMEM;
+    }
+
+    virtio_blk_dev->parent.type = RT_Device_Class_Block;
+    virtio_blk_dev->parent.ops  = &virtio_blk_ops;
+
+    rt_snprintf(dev_name, RT_NAME_MAX, "%s%d", "virtio-blk", dev_no++);
+
+    rt_hw_interrupt_install(irq, virtio_blk_isr, virtio_blk_dev, dev_name);
+    rt_hw_interrupt_umask(irq);
+
+    return rt_device_register((rt_device_t)virtio_blk_dev, dev_name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE);
+}
+#endif /* BSP_USING_VIRTIO_BLK */

+ 61 - 0
bsp/qemu-virt64-aarch64/driver/virtio/virtio_blk.h

@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021-9-16      GuEe-GUI     the first version
+ * 2021-11-11     GuEe-GUI     using virtio common interface
+ */
+
+#ifndef __VIRTIO_BLK_H__
+#define __VIRTIO_BLK_H__
+
+#include <rtdef.h>
+
+#include <virtio.h>
+
+#define VIRTIO_BLK_BUF_DATA_SIZE    512
+#define VIRTIO_BLK_BYTES_PER_SECTOR 512
+#define VIRTIO_BLK_BLOCK_SIZE       512
+#define VIRTIO_BLK_QUEUE_RING_SIZE  4
+
+#define VIRTIO_BLK_F_RO             5   /* Disk is read-only */
+#define VIRTIO_BLK_F_SCSI           7   /* Supports scsi command passthru */
+#define VIRTIO_BLK_F_CONFIG_WCE     11  /* Writeback mode available in config */
+#define VIRTIO_BLK_F_MQ             12  /* Support more than one vq */
+
+#define VIRTIO_BLK_T_IN             0   /* Read the blk */
+#define VIRTIO_BLK_T_OUT            1   /* Write the blk */
+#define VIRTIO_BLK_T_SCSI_CMD       2
+#define VIRTIO_BLK_T_SCSI_CMD_OUT   3
+#define VIRTIO_BLK_T_FLUSH          4
+#define VIRTIO_BLK_T_FLUSH_OUT      5
+
+struct virtio_blk_req
+{
+    rt_uint32_t type;
+    rt_uint32_t ioprio;
+    rt_uint64_t sector;
+};
+
+struct virtio_blk_device
+{
+    struct rt_device parent;
+
+    struct virtio_device virtio_dev;
+
+    struct
+    {
+        rt_bool_t valid;
+        rt_uint8_t status;
+
+        struct virtio_blk_req req;
+
+    } info[VIRTIO_BLK_QUEUE_RING_SIZE];
+};
+
+rt_err_t rt_virtio_blk_init(rt_ubase_t *mmio_base, rt_uint32_t irq);
+
+#endif /* __VIRTIO_BLK_H__ */

+ 0 - 61
bsp/qemu-virt64-aarch64/driver/virtio/virtio_mmio.c

@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date           Author       Notes
- * 2021-9-16      GuEe-GUI     the first version
- */
-
-#include <rtthread.h>
-#include <cpuport.h>
-
-#include "virtio_mmio.h"
-
-void virtio_mmio_print_configs(uint32_t *device_base)
-{
-    rt_kprintf("MagicValue:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_MAGIC_VALUE));
-    rt_kprintf("Version:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_VERSION));
-    rt_kprintf("DeviceID:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_DEVICE_ID));
-    rt_kprintf("VendorID:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_VENDOR_ID));
-    rt_kprintf("DeviceFeatures0:\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_HOST_FEATURES));
-    rt_kprintf("DeviceFeaturesSel0:\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_HOST_FEATURES_SEL));
-
-    virtio_mmio_write32(device_base, VIRTIO_MMIO_HOST_FEATURES_SEL, 1);
-    rt_hw_dsb();
-
-    rt_kprintf("DeviceFeatures1:\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_HOST_FEATURES));
-    rt_kprintf("DriverFeatures:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_GUEST_FEATURES));
-    rt_kprintf("DriverFeaturesSel:\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_GUEST_FEATURES_SEL));
-    rt_kprintf("PageSize:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_GUEST_PAGE_SIZE));
-
-    virtio_mmio_write32(device_base, VIRTIO_MMIO_QUEUE_SEL, 0);
-    rt_hw_dsb();
-
-    rt_kprintf("QueueSel:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_SEL));
-    rt_kprintf("QueueNumMax:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_NUM_MAX));
-    rt_kprintf("QueueNum:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_NUM));
-
-    virtio_mmio_write32(device_base, VIRTIO_MMIO_QUEUE_SEL, 1);
-    rt_hw_dsb();
-
-    rt_kprintf("QueueSel:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_SEL));
-    rt_kprintf("QueueNumMax1:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_NUM_MAX));
-    rt_kprintf("QueueNum1:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_NUM));
-    rt_kprintf("QueueAlign:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_ALIGN));
-    rt_kprintf("QueuePFN:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_PFN));
-    rt_kprintf("QueueReady:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_READY));
-    rt_kprintf("QueueNotify:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_NOTIFY));
-    rt_kprintf("InterruptStatus:\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_INTERRUPT_STATUS));
-    rt_kprintf("InterruptACK:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_INTERRUPT_ACK));
-    rt_kprintf("Status:\t\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_STATUS));
-    rt_kprintf("QueueDescLow:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_DESC_LOW));
-    rt_kprintf("QueueDescHigh:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_DESC_HIGH));
-    rt_kprintf("QueueDriverLow:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_AVAIL_LOW));
-    rt_kprintf("QueueDriverHigh:\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_AVAIL_HIGH));
-    rt_kprintf("QueueDeviceLow:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_USED_LOW));
-    rt_kprintf("QueueDeviceHigh:\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_USED_HIGH));
-    rt_kprintf("ConfigGeneration:\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_CONFIG_GENERATION));
-    rt_kprintf("Config:\t\t\t 0x%x\n", virtio_mmio_read32(device_base,VIRTIO_MMIO_CONFIG));
-}

+ 44 - 62
bsp/qemu-virt64-aarch64/driver/virtio/virtio_mmio.h

@@ -6,70 +6,52 @@
  * Change Logs:
  * Date           Author       Notes
  * 2021-9-16      GuEe-GUI     the first version
+ * 2021-11-11     GuEe-GUI     modify to virtio common interface
  */
 
-#ifndef VIRTIO_MMIO_H
-#define VIRTIO_MMIO_H
+#ifndef __VIRTIO_MMIO_H__
+#define __VIRTIO_MMIO_H__
 
-#include <stdint.h>
-#include <stddef.h>
+#include <rtdef.h>
 
-#define VIRTIO_MMIO_MAGIC               0x74726976
-#define VIRTIO_MMIO_VENDOR              0x554d4551
-
-#define VIRTIO_MMIO_MAGIC_VALUE         0x000   /* VIRTIO_MMIO_MAGIC */
-#define VIRTIO_MMIO_VERSION             0x004   /* version: 1 is legacy */
-#define VIRTIO_MMIO_DEVICE_ID           0x008   /* device type: 1 is net, 2 is disk */
-#define VIRTIO_MMIO_VENDOR_ID           0x00c   /* VIRTIO_MMIO_VENDOR */
-#define VIRTIO_MMIO_DEVICE_FEATURES     0x010
-#define VIRTIO_MMIO_DRIVER_FEATURES     0x020
-#define VIRTIO_MMIO_HOST_FEATURES       0x010
-#define VIRTIO_MMIO_HOST_FEATURES_SEL   0x014
-#define VIRTIO_MMIO_GUEST_FEATURES      0x020
-#define VIRTIO_MMIO_GUEST_FEATURES_SEL  0x024
-#define VIRTIO_MMIO_GUEST_PAGE_SIZE     0x028   /* version 1 only */
-#define VIRTIO_MMIO_QUEUE_SEL           0x030
-#define VIRTIO_MMIO_QUEUE_NUM_MAX       0x034
-#define VIRTIO_MMIO_QUEUE_NUM           0x038
-#define VIRTIO_MMIO_QUEUE_ALIGN         0x03c   /* version 1 only */
-#define VIRTIO_MMIO_QUEUE_PFN           0x040   /* version 1 only */
-#define VIRTIO_MMIO_QUEUE_READY         0x044   /* requires version 2 */
-#define VIRTIO_MMIO_QUEUE_NOTIFY        0x050
-#define VIRTIO_MMIO_INTERRUPT_STATUS    0x060
-#define VIRTIO_MMIO_INTERRUPT_ACK       0x064
-#define VIRTIO_MMIO_STATUS              0x070
-#define VIRTIO_MMIO_QUEUE_DESC_LOW      0x080   /* requires version 2 */
-#define VIRTIO_MMIO_QUEUE_DESC_HIGH     0x084   /* requires version 2 */
-#define VIRTIO_MMIO_QUEUE_AVAIL_LOW     0x090   /* requires version 2 */
-#define VIRTIO_MMIO_QUEUE_AVAIL_HIGH    0x094   /* requires version 2 */
-#define VIRTIO_MMIO_QUEUE_USED_LOW      0x0a0   /* requires version 2 */
-#define VIRTIO_MMIO_QUEUE_USED_HIGH     0x0a4   /* requires version 2 */
-#define VIRTIO_MMIO_CONFIG_GENERATION   0x100   /* requires version 2 */
-#define VIRTIO_MMIO_CONFIG              0x100
-#define VIRTIO_MMIO_INT_VRING           (1 << 0)
-#define VIRTIO_MMIO_INT_CONFIG          (1 << 1)
-#define VIRTIO_MMIO_VRING_ALIGN         4096
-
-static inline uint32_t virtio_mmio_read32(uint32_t *base, size_t offset)
-{
-    return *((volatile uint32_t*) (((uintptr_t) base) + offset));
-}
-
-static inline uint16_t virtio_mmio_read16(uint32_t *base, size_t offset)
-{
-    return *((volatile uint16_t*) (((uintptr_t) base) + offset));
-}
-
-static inline uint8_t virtio_mmio_read8(uint32_t *base, size_t offset)
-{
-    return *((volatile uint8_t*) (((uintptr_t) base) + offset));
-}
-
-static inline void virtio_mmio_write32(uint32_t *base, size_t offset, uint32_t val)
+struct virtio_mmio_config
 {
-    *((volatile uint32_t*) (((uintptr_t) base) + offset)) = val;
-}
-
-void virtio_mmio_print_configs(uint32_t *device_base);
-
-#endif /* VIRTIO_MMIO_H */
+    rt_uint32_t magic;                  /* [0x00]<RO> Magic value */
+    rt_uint32_t version;                /* [0x04]<RO> Device version number */
+    rt_uint32_t device_id;              /* [0x08]<RO> Virtio Subsystem Device ID */
+    rt_uint32_t vendor_id;              /* [0x0c]<RO> Virtio Subsystem Vendor ID */
+    rt_uint32_t device_features;        /* [0x10]<RO> Flags representing features the device supports */
+    rt_uint32_t device_features_sel;    /* [0x14]<WO> Device (host) features word selection. */
+    rt_uint32_t res0[2];                /* [0x18] */
+    rt_uint32_t driver_features;        /* [0x20]<WO> Device features understood and activated by the driver */
+    rt_uint32_t driver_features_sel;    /* [0x24]<WO> Activated (guest) features word selection */
+    rt_uint32_t guest_page_size;        /* [0x28]<WO> Guest page size, this value should be a power of 2 */
+    rt_uint32_t res1[1];                /* [0x2c] */
+    rt_uint32_t queue_sel;              /* [0x30]<WO> Virtual queue index */
+    rt_uint32_t queue_num_max;          /* [0x34]<RO> Maximum virtual queue size */
+    rt_uint32_t queue_num;              /* [0x38]<WO> Virtual queue size */
+    rt_uint32_t queue_align;            /* [0x3c]<WO> Used Ring alignment in the virtual queue */
+    rt_uint32_t queue_pfn;              /* [0x40]<RW> Guest physical page number of the virtual queue */
+    rt_uint32_t queue_ready;            /* [0x44]<RW> Virtual queue ready bit */
+    rt_uint32_t res2[2];                /* [0x48] */
+    rt_uint32_t queue_notify;           /* [0x50]<WO> Queue notifier */
+    rt_uint32_t res3[3];                /* [0x54] */
+    rt_uint32_t interrupt_status;       /* [0x60]<RO> Interrupt status */
+    rt_uint32_t interrupt_ack;          /* [0x64]<WO> Interrupt acknowledge */
+    rt_uint32_t res4[2];                /* [0x68] */
+    rt_uint32_t status;                 /* [0x70]<RW> Device status */
+    rt_uint32_t res5[3];                /* [0x74] */
+    rt_uint32_t queue_desc_low;         /* [0x80]<WO> Virtual queue’s Descriptor Area 64 bit long physical address */
+    rt_uint32_t queue_desc_high;        /* [0x84]<WO> */
+    rt_uint32_t res6[2];                /* [0x88] */
+    rt_uint32_t queue_driver_low;       /* [0x90]<WO> Virtual queue’s Driver Area 64 bit long physical address */
+    rt_uint32_t queue_driver_high;      /* [0x94]<WO> */
+    rt_uint32_t res7[2];                /* [0x98] */
+    rt_uint32_t queue_device_low;       /* [0xa0]<WO> Virtual queue’s Device Area 64 bit long physical address */
+    rt_uint32_t queue_device_high;      /* [0xa4]<WO> */
+    rt_uint32_t res8[21];               /* [0xa8] */
+    rt_uint32_t config_generation;      /* [0xfc]<RO> Configuration atomicity value */
+    rt_uint32_t config[];               /* [0x100+]<RO> Configuration space */
+} __attribute__((packed));
+
+#endif /* __VIRTIO_MMIO_H__ */

+ 94 - 0
bsp/qemu-virt64-aarch64/driver/virtio/virtio_queue.h

@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021-11-11     GuEe-GUI     the first version
+ */
+
+#ifndef __VIRTIO_QUEUE_H__
+#define __VIRTIO_QUEUE_H__
+
+#include <rtdef.h>
+
+#define VIRTQ_DESC_F_NEXT           1 /* This marks a buffer as continuing via the next field. */
+#define VIRTQ_DESC_F_WRITE          2 /* This marks a buffer as write-only (otherwise read-only). */
+#define VIRTQ_DESC_F_INDIRECT       4 /* This means the buffer contains a list of buffer descriptors. */
+
+/*
+ * The device uses this in used->flags to advise the driver: don't kick me
+ * when you add a buffer.  It's unreliable, so it's simply an optimization.
+ */
+#define VIRTQ_USED_F_NO_NOTIFY      1
+
+/*
+ * The driver uses this in avail->flags to advise the device: don't
+ * interrupt me when you consume a buffer.  It's unreliable, so it's
+ * simply an optimization.
+ */
+#define VIRTQ_AVAIL_F_NO_INTERRUPT  1
+
+/* Virtqueue descriptors: 16 bytes. These can chain together via "next". */
+struct virtq_desc
+{
+    rt_uint64_t addr;   /* Address (guest-physical). */
+    rt_uint32_t len;    /* Length. */
+    rt_uint16_t flags;  /* The flags as indicated above. */
+    rt_uint16_t next;   /* We chain unused descriptors via this, too */
+};
+
+struct virtq_avail
+{
+    rt_uint16_t flags;  /* Notifications */
+    rt_uint16_t idx;    /* Where the driver would put the next descriptor entry in the ring (modulo the queue size) */
+    rt_uint16_t ring[];
+
+    /*
+     * Only if VIRTIO_F_RING_EVENT_IDX
+     * rt_uint16_t used_event;
+     */
+};
+
+struct virtq_used_elem
+{
+    rt_uint32_t id;     /* Index of start of used descriptor chain. */
+    rt_uint32_t len;    /* Total length of the descriptor chain which was written to. */
+};
+
+struct virtq_used
+{
+    rt_uint16_t flags;
+    rt_uint16_t idx;
+    struct virtq_used_elem ring[];
+
+    /*
+     * Only if VIRTIO_F_RING_EVENT_IDX
+     * rt_uint16_t avail_event;
+     */
+};
+
+struct virtq
+{
+    rt_uint32_t num;
+
+    struct virtq_desc *desc;
+    struct virtq_avail *avail;
+    struct virtq_used *used;
+
+    /* Helper of driver */
+    rt_uint32_t used_idx;
+    rt_bool_t *free;
+};
+
+#define VIRTQ_DESC_TOTAL_SIZE(ring_size)    (sizeof(struct virtq_desc) * (ring_size))
+/* flags, idx, used_event + ring * ring_size */
+#define VIRTQ_AVAIL_TOTAL_SIZE(ring_size)   (sizeof(rt_uint16_t) * 3 + sizeof(rt_uint16_t) * (ring_size))
+/* flags, idx, avail_event + ring * ring_size */
+#define VIRTQ_USED_TOTAL_SIZE(ring_size)    (sizeof(rt_uint16_t) * 3 + sizeof(struct virtq_used_elem) * (ring_size))
+
+#define VIRTQ_AVAIL_RES_SIZE    (sizeof(rt_uint16_t))   /* used_event */
+#define VIRTQ_USED_RES_SIZE     (sizeof(rt_uint16_t))   /* avail_event */
+
+#endif /* __VIRTIO_QUEUE_H__ */

+ 3 - 2
bsp/qemu-virt64-aarch64/qemu.bat

@@ -3,5 +3,6 @@ if exist sd.bin goto run
 qemu-img create -f raw sd.bin 64M
 
 :run
-qemu-system-aarch64 -M virt -cpu cortex-a53 -smp 4 -kernel rtthread.elf -nographic ^
--drive if=none,file=sd.bin,format=raw,id=blk0 -device virtio-blk-device,drive=blk0,bus=virtio-mmio-bus.0
+qemu-system-aarch64 -M virt,gic-version=2 -cpu cortex-a53 -smp 4 -kernel rtthread.elf -nographic ^
+-drive if=none,file=sd.bin,format=raw,id=blk0 -device virtio-blk-device,drive=blk0,bus=virtio-mmio-bus.0 ^
+-netdev user,id=net0 -device virtio-net-device,netdev=net0,bus=virtio-mmio-bus.1

+ 3 - 2
bsp/qemu-virt64-aarch64/qemu.sh

@@ -1,5 +1,6 @@
 if [ ! -f "sd.bin" ]; then
 dd if=/dev/zero of=sd.bin bs=1024 count=65536
 fi
-qemu-system-aarch64 -M virt -cpu cortex-a53 -smp 4 -kernel rtthread.elf -nographic \
--drive if=none,file=sd.bin,format=raw,id=blk0 -device virtio-blk-device,drive=blk0,bus=virtio-mmio-bus.0
+qemu-system-aarch64 -M virt,gic-version=2 -cpu cortex-a53 -smp 4 -kernel rtthread.elf -nographic \
+-drive if=none,file=sd.bin,format=raw,id=blk0 -device virtio-blk-device,drive=blk0,bus=virtio-mmio-bus.0 \
+-netdev user,id=net0 -device virtio-net-device,netdev=net0,bus=virtio-mmio-bus.1

+ 9 - 26
bsp/qemu-virt64-aarch64/rtconfig.h

@@ -61,14 +61,8 @@
 #define RT_USING_USER_MAIN
 #define RT_MAIN_THREAD_STACK_SIZE 8192
 #define RT_MAIN_THREAD_PRIORITY 10
-
-/* C++ features */
-
-
-/* Command shell */
-
-#define RT_USING_FINSH
 #define RT_USING_MSH
+#define RT_USING_FINSH
 #define FINSH_USING_MSH
 #define FINSH_THREAD_NAME "tshell"
 #define FINSH_THREAD_PRIORITY 20
@@ -80,9 +74,6 @@
 #define MSH_USING_BUILT_IN_COMMANDS
 #define FINSH_USING_DESCRIPTION
 #define FINSH_ARG_MAX 10
-
-/* Device virtual file system */
-
 #define RT_USING_DFS
 #define DFS_USING_POSIX
 #define DFS_USING_WORKDIR
@@ -109,6 +100,9 @@
 /* Device Drivers */
 
 #define RT_USING_DEVICE_IPC
+#define RT_USING_SYSTEM_WORKQUEUE
+#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048
+#define RT_SYSTEM_WORKQUEUE_PRIORITY 23
 #define RT_USING_SERIAL
 #define RT_USING_SERIAL_V1
 #define RT_SERIAL_RB_BUFSZ 64
@@ -119,7 +113,7 @@
 /* Using USB */
 
 
-/* POSIX layer and C standard library */
+/* C/C++ and POSIX layer */
 
 #define RT_LIBC_DEFAULT_TIMEZONE 8
 
@@ -131,21 +125,8 @@
 
 /* Socket is in the 'Network' category */
 
-/* Network */
-
-/* Socket abstraction layer */
 
-
-/* Network interface device */
-
-
-/* light weight TCP/IP stack */
-
-
-/* AT commands */
-
-
-/* VBUS(Virtual Software BUS) */
+/* Network */
 
 
 /* Utilities */
@@ -215,6 +196,8 @@
 
 /* miscellaneous packages */
 
+/* project laboratory */
+
 /* samples: kernel and components samples */
 
 
@@ -229,7 +212,7 @@
 #define BSP_USING_RTC
 #define BSP_USING_ALARM
 #define BSP_USING_VIRTIO_BLK
-#define RT_USING_VIRTIO_BLK0
 #define BSP_USING_GIC
+#define BSP_USING_GICV2
 
 #endif

+ 23 - 50
bsp/raspberry-pi/raspi4-64/.config

@@ -94,17 +94,8 @@ CONFIG_RT_USING_USER_MAIN=y
 CONFIG_RT_MAIN_THREAD_STACK_SIZE=4096
 CONFIG_RT_MAIN_THREAD_PRIORITY=10
 # CONFIG_RT_USING_LEGACY is not set
-
-#
-# C++ features
-#
-# CONFIG_RT_USING_CPLUSPLUS is not set
-
-#
-# Command shell
-#
-CONFIG_RT_USING_FINSH=y
 CONFIG_RT_USING_MSH=y
+CONFIG_RT_USING_FINSH=y
 CONFIG_FINSH_USING_MSH=y
 CONFIG_FINSH_THREAD_NAME="tshell"
 CONFIG_FINSH_THREAD_PRIORITY=20
@@ -118,10 +109,6 @@ CONFIG_FINSH_USING_DESCRIPTION=y
 # CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set
 # CONFIG_FINSH_USING_AUTH is not set
 CONFIG_FINSH_ARG_MAX=10
-
-#
-# Device virtual file system
-#
 CONFIG_RT_USING_DFS=y
 CONFIG_DFS_USING_POSIX=y
 CONFIG_DFS_USING_WORKDIR=y
@@ -156,6 +143,7 @@ CONFIG_RT_USING_DFS_DEVFS=y
 # CONFIG_RT_USING_DFS_ROMFS is not set
 # CONFIG_RT_USING_DFS_RAMFS is not set
 # CONFIG_RT_USING_DFS_NFS is not set
+# CONFIG_RT_USING_FAL is not set
 
 #
 # Device Drivers
@@ -209,7 +197,7 @@ CONFIG_RT_USING_WDT=y
 # CONFIG_RT_USING_USB_DEVICE is not set
 
 #
-# POSIX layer and C standard library
+# C/C++ and POSIX layer
 #
 CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
 
@@ -233,25 +221,11 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
 #
 # Socket is in the 'Network' category
 #
-
-#
-# Interprocess Communication (IPC)
-#
-# CONFIG_RT_USING_POSIX_PIPE is not set
-# CONFIG_RT_USING_POSIX_MESSAGE_QUEUE is not set
-# CONFIG_RT_USING_POSIX_MESSAGE_SEMAPHORE is not set
-
-#
-# Socket is in the 'Network' category
-#
+# CONFIG_RT_USING_CPLUSPLUS is not set
 
 #
 # Network
 #
-
-#
-# Socket abstraction layer
-#
 CONFIG_RT_USING_SAL=y
 CONFIG_SAL_INTERNET_CHECK=y
 
@@ -261,10 +235,6 @@ CONFIG_SAL_INTERNET_CHECK=y
 CONFIG_SAL_USING_LWIP=y
 # CONFIG_SAL_USING_POSIX is not set
 CONFIG_SAL_SOCKETS_NUM=16
-
-#
-# Network interface device
-#
 CONFIG_RT_USING_NETDEV=y
 CONFIG_NETDEV_USING_IFCONFIG=y
 CONFIG_NETDEV_USING_PING=y
@@ -274,14 +244,13 @@ CONFIG_NETDEV_USING_AUTO_DEFAULT=y
 CONFIG_NETDEV_IPV4=1
 CONFIG_NETDEV_IPV6=0
 # CONFIG_NETDEV_IPV6_SCOPES is not set
-
-#
-# light weight TCP/IP stack
-#
 CONFIG_RT_USING_LWIP=y
+# CONFIG_RT_USING_LWIP_LOCAL_VERSION is not set
 # CONFIG_RT_USING_LWIP141 is not set
 CONFIG_RT_USING_LWIP203=y
 # CONFIG_RT_USING_LWIP212 is not set
+# CONFIG_RT_USING_LWIP_LATEST is not set
+CONFIG_RT_USING_LWIP_VER_NUM=0x20003
 # CONFIG_RT_USING_LWIP_IPV6 is not set
 CONFIG_RT_LWIP_MEM_ALIGNMENT=4
 CONFIG_RT_LWIP_IGMP=y
@@ -331,18 +300,9 @@ CONFIG_LWIP_NETIF_LOOPBACK=0
 # CONFIG_RT_LWIP_STATS is not set
 # CONFIG_RT_LWIP_USING_HW_CHECKSUM is not set
 CONFIG_RT_LWIP_USING_PING=y
+# CONFIG_LWIP_USING_DHCPD is not set
 # CONFIG_RT_LWIP_DEBUG is not set
-
-#
-# AT commands
-#
 # CONFIG_RT_USING_AT is not set
-# CONFIG_LWIP_USING_DHCPD is not set
-
-#
-# VBUS(Virtual Software BUS)
-#
-# CONFIG_RT_USING_VBUS is not set
 
 #
 # Utilities
@@ -354,6 +314,7 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y
 # CONFIG_RT_USING_UTEST is not set
 # CONFIG_RT_USING_VAR_EXPORT is not set
 # CONFIG_RT_USING_RT_LINK is not set
+# CONFIG_RT_USING_VBUS is not set
 
 #
 # RT-Thread Utestcases
@@ -367,6 +328,7 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y
 #
 # IoT - internet of things
 #
+# CONFIG_PKG_USING_LWIP is not set
 # CONFIG_PKG_USING_LORAWAN_DRIVER is not set
 # CONFIG_PKG_USING_PAHOMQTT is not set
 # CONFIG_PKG_USING_UMQTT is not set
@@ -383,6 +345,7 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y
 # CONFIG_PKG_USING_FREEMODBUS is not set
 # CONFIG_PKG_USING_LJSON is not set
 # CONFIG_PKG_USING_EZXML is not set
+# CONFIG_PKG_USING_SIMPLE_XML is not set
 # CONFIG_PKG_USING_NANOPB is not set
 
 #
@@ -422,6 +385,7 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y
 # CONFIG_PKG_USING_JOYLINK is not set
 # CONFIG_PKG_USING_EZ_IOT_OS is not set
 # CONFIG_PKG_USING_NIMBLE is not set
+# CONFIG_PKG_USING_LLSYNC_SDK_ADAPTER is not set
 # CONFIG_PKG_USING_OTA_DOWNLOADER is not set
 # CONFIG_PKG_USING_IPMSG is not set
 # CONFIG_PKG_USING_LSSDP is not set
@@ -629,8 +593,8 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y
 # CONFIG_PKG_USING_ARM_2D is not set
 # CONFIG_PKG_USING_MCUBOOT is not set
 # CONFIG_PKG_USING_TINYUSB is not set
-# CONFIG_PKG_USING_USB_STACK is not set
-# CONFIG_PKG_USING_LUATOS_SOC is not set
+# CONFIG_PKG_USING_CHERRYUSB is not set
+# CONFIG_PKG_USING_KMULTI_RTIMER is not set
 
 #
 # peripheral libraries and drivers
@@ -654,6 +618,7 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y
 # CONFIG_PKG_USING_WM_LIBRARIES is not set
 # CONFIG_PKG_USING_KENDRYTE_SDK is not set
 # CONFIG_PKG_USING_INFRARED is not set
+# CONFIG_PKG_USING_MULTI_INFRARED is not set
 # CONFIG_PKG_USING_AGILE_BUTTON is not set
 # CONFIG_PKG_USING_AGILE_LED is not set
 # CONFIG_PKG_USING_AT24CXX is not set
@@ -710,6 +675,7 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y
 # CONFIG_PKG_USING_SOFT_SERIAL is not set
 # CONFIG_PKG_USING_MB85RS16 is not set
 # CONFIG_PKG_USING_CW2015 is not set
+# CONFIG_PKG_USING_RFM300 is not set
 
 #
 # AI packages
@@ -728,6 +694,10 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y
 # miscellaneous packages
 #
 
+#
+# project laboratory
+#
+
 #
 # samples: kernel and components samples
 #
@@ -760,6 +730,7 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y
 # CONFIG_PKG_USING_CANFESTIVAL is not set
 # CONFIG_PKG_USING_ZLIB is not set
 # CONFIG_PKG_USING_MINIZIP is not set
+# CONFIG_PKG_USING_HEATSHRINK is not set
 # CONFIG_PKG_USING_DSTR is not set
 # CONFIG_PKG_USING_TINYFRAME is not set
 # CONFIG_PKG_USING_KENDRYTE_DEMO is not set
@@ -777,6 +748,7 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y
 # CONFIG_PKG_USING_DESIGN_PATTERN is not set
 # CONFIG_PKG_USING_CONTROLLER is not set
 # CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set
+# CONFIG_PKG_USING_MFBD is not set
 CONFIG_BCM2711_SOC=y
 
 #
@@ -793,6 +765,7 @@ CONFIG_RT_USING_UART0=y
 # CONFIG_RT_USING_UART4 is not set
 # CONFIG_RT_USING_UART5 is not set
 CONFIG_BSP_USING_GIC=y
+CONFIG_BSP_USING_GICV2=y
 CONFIG_BSP_USING_PIN=y
 CONFIG_BSP_USING_CORETIMER=y
 # CONFIG_BSP_USING_SYSTIMER is not set

+ 4 - 0
bsp/raspberry-pi/raspi4-64/driver/Kconfig

@@ -31,6 +31,10 @@ menu "Hardware Drivers Config"
             bool
             default y
 
+            config BSP_USING_GICV2
+                bool
+                default y
+
         config BSP_USING_PIN
             bool "Using PIN"
             select RT_USING_PIN

+ 44 - 0
bsp/raspberry-pi/raspi4-64/driver/drv_wdt.c

@@ -10,6 +10,8 @@
 
 #include <rthw.h>
 #include "drv_wdt.h"
+#include "drv_gpio.h"
+#include "mbox.h"
 #include "raspi4.h"
 
 #ifdef BSP_USING_WDT
@@ -122,6 +124,48 @@ int rt_hw_wdt_init(void)
 }
 INIT_DEVICE_EXPORT(rt_hw_wdt_init);
 
+void poweroff(void)
+{
+    unsigned long r;
+
+    rt_kprintf("poweroff...\n");
+
+    /* power off devices one by one */
+    for (r = 0; r < 16; ++r)
+    {
+        bcm271x_mbox_poweroff_devices(r);
+    }
+
+    /* power off gpio pins (but not VCC pins) */
+    GPIO_REG_GPFSEL0(GPIO_BASE) = 0;
+    GPIO_REG_GPFSEL1(GPIO_BASE) = 0;
+    GPIO_REG_GPFSEL2(GPIO_BASE) = 0;
+    GPIO_REG_GPFSEL3(GPIO_BASE) = 0;
+    GPIO_REG_GPFSEL4(GPIO_BASE) = 0;
+    GPIO_REG_GPFSEL5(GPIO_BASE) = 0;
+    GPIO_REG_GPPUD(GPIO_BASE) = 0;
+    rt_thread_mdelay(150);
+
+    GPIO_REG_GPPUDCLK0(GPIO_BASE) = 0xffffffff;
+    GPIO_REG_GPPUDCLK1(GPIO_BASE) = 0xffffffff;
+    rt_thread_mdelay(150);
+
+    /* flush GPIO setup */
+    GPIO_REG_GPPUDCLK0(GPIO_BASE) = 0;
+    GPIO_REG_GPPUDCLK1(GPIO_BASE) = 0;
+
+    /* power off the SoC (GPU + CPU), partition 63 used to indicate halt */
+    r = PM_RSTS;
+    r &= ~0xfffffaaa;
+    r |= 0x555;
+    PM_RSTS |= PM_PASSWORD | r;
+    PM_WDOG |= PM_PASSWORD | 0x0A;
+    PM_RSTC |= PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET;
+
+    while (1) {};
+}
+MSH_CMD_EXPORT(poweroff, poweroff...);
+
 void reboot(void)
 {
     unsigned int r;

+ 18 - 0
bsp/raspberry-pi/raspi4-64/driver/mbox.c

@@ -53,6 +53,24 @@ int mbox_call(unsigned char ch, int mmu_enable)
     return 0;
 }
 
+int bcm271x_mbox_poweroff_devices(int id)
+{
+    mbox[0] = 8 * 4;                /* length of the message */
+    mbox[1] = MBOX_REQUEST;         /* this is a request message */
+
+    mbox[2] = MBOX_TAG_SETPOWER;    /* set power state */
+    mbox[3] = 8;                    /* buffer size */
+    mbox[4] = 8;                    /* len */
+
+    mbox[5] = (unsigned int)id;     /* device id */
+    mbox[6] = 0;                    /* bit 0: off, bit 1: no wait */
+
+    mbox[7] = MBOX_TAG_LAST;
+    mbox_call(8, MBOX_CH_PROP);
+
+    return 0;
+}
+
 int bcm271x_mbox_get_touch(void)
 {
     mbox[0] = 8 * 4;                    // length of the message

+ 1 - 0
bsp/raspberry-pi/raspi4-64/driver/mbox.h

@@ -161,6 +161,7 @@ enum
 #define PWM_CLK_ID                      (0x00000000a)
 
 int mbox_call(unsigned char ch, int mmu_enable);
+int bcm271x_mbox_poweroff_devices(int id);
 int bcm271x_mbox_get_touch(void);
 int bcm271x_notify_reboot(void);
 int bcm271x_notify_xhci_reset(void);

+ 7 - 25
bsp/raspberry-pi/raspi4-64/rtconfig.h

@@ -56,14 +56,8 @@
 #define RT_USING_USER_MAIN
 #define RT_MAIN_THREAD_STACK_SIZE 4096
 #define RT_MAIN_THREAD_PRIORITY 10
-
-/* C++ features */
-
-
-/* Command shell */
-
-#define RT_USING_FINSH
 #define RT_USING_MSH
+#define RT_USING_FINSH
 #define FINSH_USING_MSH
 #define FINSH_THREAD_NAME "tshell"
 #define FINSH_THREAD_PRIORITY 20
@@ -75,9 +69,6 @@
 #define MSH_USING_BUILT_IN_COMMANDS
 #define FINSH_USING_DESCRIPTION
 #define FINSH_ARG_MAX 10
-
-/* Device virtual file system */
-
 #define RT_USING_DFS
 #define DFS_USING_POSIX
 #define DFS_USING_WORKDIR
@@ -125,7 +116,7 @@
 /* Using USB */
 
 
-/* POSIX layer and C standard library */
+/* C/C++ and POSIX layer */
 
 #define RT_LIBC_DEFAULT_TIMEZONE 8
 
@@ -137,9 +128,8 @@
 
 /* Socket is in the 'Network' category */
 
-/* Network */
 
-/* Socket abstraction layer */
+/* Network */
 
 #define RT_USING_SAL
 #define SAL_INTERNET_CHECK
@@ -148,9 +138,6 @@
 
 #define SAL_USING_LWIP
 #define SAL_SOCKETS_NUM 16
-
-/* Network interface device */
-
 #define RT_USING_NETDEV
 #define NETDEV_USING_IFCONFIG
 #define NETDEV_USING_PING
@@ -158,11 +145,9 @@
 #define NETDEV_USING_AUTO_DEFAULT
 #define NETDEV_IPV4 1
 #define NETDEV_IPV6 0
-
-/* light weight TCP/IP stack */
-
 #define RT_USING_LWIP
 #define RT_USING_LWIP203
+#define RT_USING_LWIP_VER_NUM 0x20003
 #define RT_LWIP_MEM_ALIGNMENT 4
 #define RT_LWIP_IGMP
 #define RT_LWIP_ICMP
@@ -203,12 +188,6 @@
 #define LWIP_NETIF_LOOPBACK 0
 #define RT_LWIP_USING_PING
 
-/* AT commands */
-
-
-/* VBUS(Virtual Software BUS) */
-
-
 /* Utilities */
 
 #define RT_USING_RYM
@@ -278,6 +257,8 @@
 
 /* miscellaneous packages */
 
+/* project laboratory */
+
 /* samples: kernel and components samples */
 
 
@@ -292,6 +273,7 @@
 #define BSP_USING_UART
 #define RT_USING_UART0
 #define BSP_USING_GIC
+#define BSP_USING_GICV2
 #define BSP_USING_PIN
 #define BSP_USING_CORETIMER
 #define BSP_USING_WDT

+ 653 - 0
bsp/rockchip/rk3568/.config

@@ -0,0 +1,653 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# RT-Thread Project Configuration
+#
+
+#
+# RT-Thread Kernel
+#
+CONFIG_RT_NAME_MAX=8
+# CONFIG_RT_USING_ARCH_DATA_TYPE is not set
+# CONFIG_RT_USING_SMP is not set
+CONFIG_RT_ALIGN_SIZE=4
+# CONFIG_RT_THREAD_PRIORITY_8 is not set
+CONFIG_RT_THREAD_PRIORITY_32=y
+# CONFIG_RT_THREAD_PRIORITY_256 is not set
+CONFIG_RT_THREAD_PRIORITY_MAX=32
+CONFIG_RT_TICK_PER_SECOND=100
+CONFIG_RT_USING_OVERFLOW_CHECK=y
+CONFIG_RT_USING_HOOK=y
+CONFIG_RT_HOOK_USING_FUNC_PTR=y
+CONFIG_RT_USING_IDLE_HOOK=y
+CONFIG_RT_IDLE_HOOK_LIST_SIZE=4
+CONFIG_IDLE_THREAD_STACK_SIZE=4096
+CONFIG_RT_USING_TIMER_SOFT=y
+CONFIG_RT_TIMER_THREAD_PRIO=4
+CONFIG_RT_TIMER_THREAD_STACK_SIZE=4096
+
+#
+# kservice optimization
+#
+# CONFIG_RT_KSERVICE_USING_STDLIB is not set
+# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set
+# CONFIG_RT_USING_TINY_FFS is not set
+# CONFIG_RT_PRINTF_LONGLONG is not set
+CONFIG_RT_DEBUG=y
+CONFIG_RT_DEBUG_COLOR=y
+# CONFIG_RT_DEBUG_INIT_CONFIG is not set
+# CONFIG_RT_DEBUG_THREAD_CONFIG is not set
+# CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set
+# CONFIG_RT_DEBUG_IPC_CONFIG is not set
+# CONFIG_RT_DEBUG_TIMER_CONFIG is not set
+# CONFIG_RT_DEBUG_IRQ_CONFIG is not set
+# CONFIG_RT_DEBUG_MEM_CONFIG is not set
+# CONFIG_RT_DEBUG_SLAB_CONFIG is not set
+# CONFIG_RT_DEBUG_MEMHEAP_CONFIG is not set
+# CONFIG_RT_DEBUG_MODULE_CONFIG is not set
+
+#
+# Inter-Thread communication
+#
+CONFIG_RT_USING_SEMAPHORE=y
+CONFIG_RT_USING_MUTEX=y
+CONFIG_RT_USING_EVENT=y
+CONFIG_RT_USING_MAILBOX=y
+CONFIG_RT_USING_MESSAGEQUEUE=y
+# CONFIG_RT_USING_SIGNALS is not set
+
+#
+# Memory Management
+#
+CONFIG_RT_USING_MEMPOOL=y
+CONFIG_RT_USING_SMALL_MEM=y
+# CONFIG_RT_USING_SLAB is not set
+CONFIG_RT_USING_MEMHEAP=y
+CONFIG_RT_MEMHEAP_FAST_MODE=y
+# CONFIG_RT_MEMHEAP_BSET_MODE is not set
+CONFIG_RT_USING_SMALL_MEM_AS_HEAP=y
+# CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set
+# CONFIG_RT_USING_SLAB_AS_HEAP is not set
+# CONFIG_RT_USING_USERHEAP is not set
+# CONFIG_RT_USING_NOHEAP is not set
+CONFIG_RT_USING_MEMTRACE=y
+# CONFIG_RT_USING_HEAP_ISR is not set
+CONFIG_RT_USING_HEAP=y
+
+#
+# Kernel Device Object
+#
+CONFIG_RT_USING_DEVICE=y
+CONFIG_RT_USING_DEVICE_OPS=y
+# CONFIG_RT_USING_INTERRUPT_INFO is not set
+CONFIG_RT_USING_CONSOLE=y
+CONFIG_RT_CONSOLEBUF_SIZE=128
+CONFIG_RT_CONSOLE_DEVICE_NAME="uart2"
+CONFIG_RT_VER_NUM=0x40100
+CONFIG_ARCH_CPU_64BIT=y
+# CONFIG_RT_USING_CPU_FFS is not set
+CONFIG_ARCH_ARMV8=y
+# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set
+
+#
+# RT-Thread Components
+#
+CONFIG_RT_USING_COMPONENTS_INIT=y
+CONFIG_RT_USING_USER_MAIN=y
+CONFIG_RT_MAIN_THREAD_STACK_SIZE=8192
+CONFIG_RT_MAIN_THREAD_PRIORITY=10
+# CONFIG_RT_USING_LEGACY is not set
+CONFIG_RT_USING_MSH=y
+CONFIG_RT_USING_FINSH=y
+CONFIG_FINSH_USING_MSH=y
+CONFIG_FINSH_THREAD_NAME="tshell"
+CONFIG_FINSH_THREAD_PRIORITY=20
+CONFIG_FINSH_THREAD_STACK_SIZE=4096
+CONFIG_FINSH_USING_HISTORY=y
+CONFIG_FINSH_HISTORY_LINES=5
+CONFIG_FINSH_USING_SYMTAB=y
+CONFIG_FINSH_CMD_SIZE=80
+CONFIG_MSH_USING_BUILT_IN_COMMANDS=y
+CONFIG_FINSH_USING_DESCRIPTION=y
+# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set
+# CONFIG_FINSH_USING_AUTH is not set
+CONFIG_FINSH_ARG_MAX=10
+# CONFIG_RT_USING_DFS is not set
+# CONFIG_RT_USING_FAL is not set
+
+#
+# Device Drivers
+#
+CONFIG_RT_USING_DEVICE_IPC=y
+# CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set
+CONFIG_RT_USING_SERIAL=y
+CONFIG_RT_USING_SERIAL_V1=y
+# CONFIG_RT_USING_SERIAL_V2 is not set
+# CONFIG_RT_SERIAL_USING_DMA is not set
+CONFIG_RT_SERIAL_RB_BUFSZ=64
+# CONFIG_RT_USING_CAN is not set
+# CONFIG_RT_USING_HWTIMER is not set
+# CONFIG_RT_USING_CPUTIME is not set
+# CONFIG_RT_USING_I2C is not set
+# CONFIG_RT_USING_PHY is not set
+CONFIG_RT_USING_PIN=y
+# CONFIG_RT_USING_ADC is not set
+# CONFIG_RT_USING_DAC is not set
+# CONFIG_RT_USING_PWM is not set
+# CONFIG_RT_USING_MTD_NOR is not set
+# CONFIG_RT_USING_MTD_NAND is not set
+# CONFIG_RT_USING_PM is not set
+# CONFIG_RT_USING_RTC is not set
+# CONFIG_RT_USING_SDIO is not set
+# CONFIG_RT_USING_SPI is not set
+# CONFIG_RT_USING_WDT is not set
+# CONFIG_RT_USING_AUDIO is not set
+# CONFIG_RT_USING_SENSOR is not set
+# CONFIG_RT_USING_TOUCH is not set
+# CONFIG_RT_USING_HWCRYPTO is not set
+# CONFIG_RT_USING_PULSE_ENCODER is not set
+# CONFIG_RT_USING_INPUT_CAPTURE is not set
+# CONFIG_RT_USING_WIFI is not set
+
+#
+# Using USB
+#
+# CONFIG_RT_USING_USB is not set
+# CONFIG_RT_USING_USB_HOST is not set
+# CONFIG_RT_USING_USB_DEVICE is not set
+
+#
+# C/C++ and POSIX layer
+#
+CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
+
+#
+# POSIX (Portable Operating System Interface) layer
+#
+# CONFIG_RT_USING_POSIX_FS is not set
+# CONFIG_RT_USING_POSIX_DELAY is not set
+# CONFIG_RT_USING_POSIX_CLOCK is not set
+# CONFIG_RT_USING_POSIX_TIMER is not set
+# CONFIG_RT_USING_PTHREADS is not set
+# CONFIG_RT_USING_MODULE is not set
+
+#
+# Interprocess Communication (IPC)
+#
+# CONFIG_RT_USING_POSIX_PIPE is not set
+# CONFIG_RT_USING_POSIX_MESSAGE_QUEUE is not set
+# CONFIG_RT_USING_POSIX_MESSAGE_SEMAPHORE is not set
+
+#
+# Socket is in the 'Network' category
+#
+# CONFIG_RT_USING_CPLUSPLUS is not set
+
+#
+# Network
+#
+# CONFIG_RT_USING_SAL is not set
+# CONFIG_RT_USING_NETDEV is not set
+# CONFIG_RT_USING_LWIP is not set
+# CONFIG_RT_USING_AT is not set
+
+#
+# Utilities
+#
+# CONFIG_RT_USING_RYM is not set
+# CONFIG_RT_USING_ULOG is not set
+# CONFIG_RT_USING_UTEST is not set
+# CONFIG_RT_USING_VAR_EXPORT is not set
+# CONFIG_RT_USING_RT_LINK is not set
+# CONFIG_RT_USING_VBUS is not set
+
+#
+# RT-Thread Utestcases
+#
+# CONFIG_RT_USING_UTESTCASES is not set
+
+#
+# RT-Thread online packages
+#
+
+#
+# IoT - internet of things
+#
+# CONFIG_PKG_USING_LWIP is not set
+# CONFIG_PKG_USING_LORAWAN_DRIVER is not set
+# CONFIG_PKG_USING_PAHOMQTT is not set
+# CONFIG_PKG_USING_UMQTT is not set
+# CONFIG_PKG_USING_WEBCLIENT is not set
+# CONFIG_PKG_USING_WEBNET is not set
+# CONFIG_PKG_USING_MONGOOSE is not set
+# CONFIG_PKG_USING_MYMQTT is not set
+# CONFIG_PKG_USING_KAWAII_MQTT is not set
+# CONFIG_PKG_USING_BC28_MQTT is not set
+# CONFIG_PKG_USING_WEBTERMINAL is not set
+# CONFIG_PKG_USING_CJSON is not set
+# CONFIG_PKG_USING_JSMN is not set
+# CONFIG_PKG_USING_LIBMODBUS is not set
+# CONFIG_PKG_USING_FREEMODBUS is not set
+# CONFIG_PKG_USING_LJSON is not set
+# CONFIG_PKG_USING_EZXML is not set
+# CONFIG_PKG_USING_SIMPLE_XML is not set
+# CONFIG_PKG_USING_NANOPB is not set
+
+#
+# Wi-Fi
+#
+
+#
+# Marvell WiFi
+#
+# CONFIG_PKG_USING_WLANMARVELL is not set
+
+#
+# Wiced WiFi
+#
+# CONFIG_PKG_USING_WLAN_WICED is not set
+# CONFIG_PKG_USING_RW007 is not set
+# CONFIG_PKG_USING_COAP is not set
+# CONFIG_PKG_USING_NOPOLL is not set
+# CONFIG_PKG_USING_NETUTILS is not set
+# CONFIG_PKG_USING_CMUX is not set
+# CONFIG_PKG_USING_PPP_DEVICE is not set
+# CONFIG_PKG_USING_AT_DEVICE is not set
+# CONFIG_PKG_USING_ATSRV_SOCKET is not set
+# CONFIG_PKG_USING_WIZNET is not set
+# CONFIG_PKG_USING_ZB_COORDINATOR is not set
+
+#
+# IoT Cloud
+#
+# CONFIG_PKG_USING_ONENET is not set
+# CONFIG_PKG_USING_GAGENT_CLOUD is not set
+# CONFIG_PKG_USING_ALI_IOTKIT is not set
+# CONFIG_PKG_USING_AZURE is not set
+# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set
+# CONFIG_PKG_USING_JIOT-C-SDK is not set
+# CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set
+# CONFIG_PKG_USING_JOYLINK is not set
+# CONFIG_PKG_USING_EZ_IOT_OS is not set
+# CONFIG_PKG_USING_NIMBLE is not set
+# CONFIG_PKG_USING_LLSYNC_SDK_ADAPTER is not set
+# CONFIG_PKG_USING_OTA_DOWNLOADER is not set
+# CONFIG_PKG_USING_IPMSG is not set
+# CONFIG_PKG_USING_LSSDP is not set
+# CONFIG_PKG_USING_AIRKISS_OPEN is not set
+# CONFIG_PKG_USING_LIBRWS is not set
+# CONFIG_PKG_USING_TCPSERVER is not set
+# CONFIG_PKG_USING_PROTOBUF_C is not set
+# CONFIG_PKG_USING_DLT645 is not set
+# CONFIG_PKG_USING_QXWZ is not set
+# CONFIG_PKG_USING_SMTP_CLIENT is not set
+# CONFIG_PKG_USING_ABUP_FOTA is not set
+# CONFIG_PKG_USING_LIBCURL2RTT is not set
+# CONFIG_PKG_USING_CAPNP is not set
+# CONFIG_PKG_USING_RT_CJSON_TOOLS is not set
+# CONFIG_PKG_USING_AGILE_TELNET is not set
+# CONFIG_PKG_USING_NMEALIB is not set
+# CONFIG_PKG_USING_AGILE_JSMN is not set
+# CONFIG_PKG_USING_PDULIB is not set
+# CONFIG_PKG_USING_BTSTACK is not set
+# CONFIG_PKG_USING_LORAWAN_ED_STACK is not set
+# CONFIG_PKG_USING_WAYZ_IOTKIT is not set
+# CONFIG_PKG_USING_MAVLINK is not set
+# CONFIG_PKG_USING_RAPIDJSON is not set
+# CONFIG_PKG_USING_BSAL is not set
+# CONFIG_PKG_USING_AGILE_MODBUS is not set
+# CONFIG_PKG_USING_AGILE_FTP is not set
+# CONFIG_PKG_USING_EMBEDDEDPROTO is not set
+# CONFIG_PKG_USING_RT_LINK_HW is not set
+# CONFIG_PKG_USING_LORA_PKT_FWD is not set
+# CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set
+# CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set
+# CONFIG_PKG_USING_HM is not set
+# CONFIG_PKG_USING_SMALL_MODBUS is not set
+# CONFIG_PKG_USING_NET_SERVER is not set
+
+#
+# security packages
+#
+# CONFIG_PKG_USING_MBEDTLS is not set
+# CONFIG_PKG_USING_LIBSODIUM is not set
+# CONFIG_PKG_USING_TINYCRYPT is not set
+# CONFIG_PKG_USING_TFM is not set
+# CONFIG_PKG_USING_YD_CRYPTO is not set
+
+#
+# language packages
+#
+# CONFIG_PKG_USING_LUATOS_SOC is not set
+# CONFIG_PKG_USING_LUA is not set
+# CONFIG_PKG_USING_JERRYSCRIPT is not set
+# CONFIG_PKG_USING_MICROPYTHON is not set
+# CONFIG_PKG_USING_PIKASCRIPT is not set
+
+#
+# multimedia packages
+#
+
+#
+# LVGL: powerful and easy-to-use embedded GUI library
+#
+# CONFIG_PKG_USING_LVGL is not set
+# CONFIG_PKG_USING_LITTLEVGL2RTT is not set
+# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set
+
+#
+# u8g2: a monochrome graphic library
+#
+# CONFIG_PKG_USING_U8G2_OFFICIAL is not set
+# CONFIG_PKG_USING_U8G2 is not set
+# CONFIG_PKG_USING_OPENMV is not set
+# CONFIG_PKG_USING_MUPDF is not set
+# CONFIG_PKG_USING_STEMWIN is not set
+# CONFIG_PKG_USING_WAVPLAYER is not set
+# CONFIG_PKG_USING_TJPGD is not set
+# CONFIG_PKG_USING_PDFGEN is not set
+# CONFIG_PKG_USING_HELIX is not set
+# CONFIG_PKG_USING_AZUREGUIX is not set
+# CONFIG_PKG_USING_TOUCHGFX2RTT is not set
+# CONFIG_PKG_USING_NUEMWIN is not set
+# CONFIG_PKG_USING_MP3PLAYER is not set
+# CONFIG_PKG_USING_TINYJPEG is not set
+# CONFIG_PKG_USING_UGUI is not set
+
+#
+# PainterEngine: A cross-platform graphics application framework written in C language
+#
+# CONFIG_PKG_USING_PAINTERENGINE is not set
+# CONFIG_PKG_USING_PAINTERENGINE_AUX is not set
+# CONFIG_PKG_USING_MCURSES is not set
+# CONFIG_PKG_USING_TERMBOX is not set
+# CONFIG_PKG_USING_VT100 is not set
+# CONFIG_PKG_USING_QRCODE is not set
+
+#
+# tools packages
+#
+# CONFIG_PKG_USING_CMBACKTRACE is not set
+# CONFIG_PKG_USING_EASYFLASH is not set
+# CONFIG_PKG_USING_EASYLOGGER is not set
+# CONFIG_PKG_USING_SYSTEMVIEW is not set
+# CONFIG_PKG_USING_SEGGER_RTT is not set
+# CONFIG_PKG_USING_RDB is not set
+# CONFIG_PKG_USING_ULOG_EASYFLASH is not set
+# CONFIG_PKG_USING_ULOG_FILE is not set
+# CONFIG_PKG_USING_LOGMGR is not set
+# CONFIG_PKG_USING_ADBD is not set
+# CONFIG_PKG_USING_COREMARK is not set
+# CONFIG_PKG_USING_DHRYSTONE is not set
+# CONFIG_PKG_USING_MEMORYPERF is not set
+# CONFIG_PKG_USING_NR_MICRO_SHELL is not set
+# CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set
+# CONFIG_PKG_USING_LUNAR_CALENDAR is not set
+# CONFIG_PKG_USING_BS8116A is not set
+# CONFIG_PKG_USING_GPS_RMC is not set
+# CONFIG_PKG_USING_URLENCODE is not set
+# CONFIG_PKG_USING_UMCN is not set
+# CONFIG_PKG_USING_LWRB2RTT is not set
+# CONFIG_PKG_USING_CPU_USAGE is not set
+# CONFIG_PKG_USING_GBK2UTF8 is not set
+# CONFIG_PKG_USING_VCONSOLE is not set
+# CONFIG_PKG_USING_KDB is not set
+# CONFIG_PKG_USING_WAMR is not set
+# CONFIG_PKG_USING_MICRO_XRCE_DDS_CLIENT is not set
+# CONFIG_PKG_USING_LWLOG is not set
+# CONFIG_PKG_USING_ANV_TRACE is not set
+# CONFIG_PKG_USING_ANV_MEMLEAK is not set
+# CONFIG_PKG_USING_ANV_TESTSUIT is not set
+# CONFIG_PKG_USING_ANV_BENCH is not set
+# CONFIG_PKG_USING_DEVMEM is not set
+# CONFIG_PKG_USING_REGEX is not set
+# CONFIG_PKG_USING_MEM_SANDBOX is not set
+# CONFIG_PKG_USING_SOLAR_TERMS is not set
+# CONFIG_PKG_USING_GAN_ZHI is not set
+# CONFIG_PKG_USING_FDT is not set
+
+#
+# system packages
+#
+
+#
+# enhanced kernel services
+#
+# CONFIG_PKG_USING_RT_MEMCPY_CM is not set
+# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set
+# CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set
+
+#
+# POSIX extension functions
+#
+# CONFIG_PKG_USING_POSIX_GETLINE is not set
+# CONFIG_PKG_USING_POSIX_WCWIDTH is not set
+# CONFIG_PKG_USING_POSIX_ITOA is not set
+# CONFIG_PKG_USING_POSIX_STRINGS is not set
+
+#
+# acceleration: Assembly language or algorithmic acceleration packages
+#
+# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set
+# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set
+# CONFIG_PKG_USING_QFPLIB_M3 is not set
+
+#
+# CMSIS: ARM Cortex-M Microcontroller Software Interface Standard
+#
+# CONFIG_PKG_USING_CMSIS_5 is not set
+# CONFIG_PKG_USING_CMSIS_RTOS2 is not set
+
+#
+# Micrium: Micrium software products porting for RT-Thread
+#
+# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set
+# CONFIG_PKG_USING_UCOSII_WRAPPER is not set
+# CONFIG_PKG_USING_UC_CRC is not set
+# CONFIG_PKG_USING_UC_CLK is not set
+# CONFIG_PKG_USING_UC_COMMON is not set
+# CONFIG_PKG_USING_UC_MODBUS is not set
+# CONFIG_RT_USING_ARDUINO is not set
+# CONFIG_PKG_USING_GUIENGINE is not set
+# CONFIG_PKG_USING_CAIRO is not set
+# CONFIG_PKG_USING_PIXMAN is not set
+# CONFIG_PKG_USING_PARTITION is not set
+# CONFIG_PKG_USING_FAL is not set
+# CONFIG_PKG_USING_FLASHDB is not set
+# CONFIG_PKG_USING_SQLITE is not set
+# CONFIG_PKG_USING_RTI is not set
+# CONFIG_PKG_USING_DFS_YAFFS is not set
+# CONFIG_PKG_USING_LITTLEFS is not set
+# CONFIG_PKG_USING_DFS_JFFS2 is not set
+# CONFIG_PKG_USING_DFS_UFFS is not set
+# CONFIG_PKG_USING_LWEXT4 is not set
+# CONFIG_PKG_USING_THREAD_POOL is not set
+# CONFIG_PKG_USING_ROBOTS is not set
+# CONFIG_PKG_USING_EV is not set
+# CONFIG_PKG_USING_SYSWATCH is not set
+# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set
+# CONFIG_PKG_USING_PLCCORE is not set
+# CONFIG_PKG_USING_RAMDISK is not set
+# CONFIG_PKG_USING_MININI is not set
+# CONFIG_PKG_USING_QBOOT is not set
+# CONFIG_PKG_USING_PPOOL is not set
+# CONFIG_PKG_USING_OPENAMP is not set
+# CONFIG_PKG_USING_LPM is not set
+# CONFIG_PKG_USING_TLSF is not set
+# CONFIG_PKG_USING_EVENT_RECORDER is not set
+# CONFIG_PKG_USING_ARM_2D is not set
+# CONFIG_PKG_USING_MCUBOOT is not set
+# CONFIG_PKG_USING_TINYUSB is not set
+# CONFIG_PKG_USING_CHERRYUSB is not set
+# CONFIG_PKG_USING_KMULTI_RTIMER is not set
+
+#
+# peripheral libraries and drivers
+#
+# CONFIG_PKG_USING_SENSORS_DRIVERS is not set
+# CONFIG_PKG_USING_REALTEK_AMEBA is not set
+# CONFIG_PKG_USING_SHT2X is not set
+# CONFIG_PKG_USING_SHT3X is not set
+# CONFIG_PKG_USING_AS7341 is not set
+# CONFIG_PKG_USING_STM32_SDIO is not set
+# CONFIG_PKG_USING_ICM20608 is not set
+# CONFIG_PKG_USING_BUTTON is not set
+# CONFIG_PKG_USING_PCF8574 is not set
+# CONFIG_PKG_USING_SX12XX is not set
+# CONFIG_PKG_USING_SIGNAL_LED is not set
+# CONFIG_PKG_USING_LEDBLINK is not set
+# CONFIG_PKG_USING_LITTLED is not set
+# CONFIG_PKG_USING_LKDGUI is not set
+# CONFIG_PKG_USING_NRF5X_SDK is not set
+# CONFIG_PKG_USING_NRFX is not set
+# CONFIG_PKG_USING_WM_LIBRARIES is not set
+# CONFIG_PKG_USING_KENDRYTE_SDK is not set
+# CONFIG_PKG_USING_INFRARED is not set
+# CONFIG_PKG_USING_MULTI_INFRARED is not set
+# CONFIG_PKG_USING_AGILE_BUTTON is not set
+# CONFIG_PKG_USING_AGILE_LED is not set
+# CONFIG_PKG_USING_AT24CXX is not set
+# CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set
+# CONFIG_PKG_USING_AD7746 is not set
+# CONFIG_PKG_USING_PCA9685 is not set
+# CONFIG_PKG_USING_I2C_TOOLS is not set
+# CONFIG_PKG_USING_NRF24L01 is not set
+# CONFIG_PKG_USING_TOUCH_DRIVERS is not set
+# CONFIG_PKG_USING_MAX17048 is not set
+# CONFIG_PKG_USING_RPLIDAR is not set
+# CONFIG_PKG_USING_AS608 is not set
+# CONFIG_PKG_USING_RC522 is not set
+# CONFIG_PKG_USING_WS2812B is not set
+# CONFIG_PKG_USING_EMBARC_BSP is not set
+# CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set
+# CONFIG_PKG_USING_MULTI_RTIMER is not set
+# CONFIG_PKG_USING_MAX7219 is not set
+# CONFIG_PKG_USING_BEEP is not set
+# CONFIG_PKG_USING_EASYBLINK is not set
+# CONFIG_PKG_USING_PMS_SERIES is not set
+# CONFIG_PKG_USING_CAN_YMODEM is not set
+# CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set
+# CONFIG_PKG_USING_QLED is not set
+# CONFIG_PKG_USING_PAJ7620 is not set
+# CONFIG_PKG_USING_AGILE_CONSOLE is not set
+# CONFIG_PKG_USING_LD3320 is not set
+# CONFIG_PKG_USING_WK2124 is not set
+# CONFIG_PKG_USING_LY68L6400 is not set
+# CONFIG_PKG_USING_DM9051 is not set
+# CONFIG_PKG_USING_SSD1306 is not set
+# CONFIG_PKG_USING_QKEY is not set
+# CONFIG_PKG_USING_RS485 is not set
+# CONFIG_PKG_USING_RS232 is not set
+# CONFIG_PKG_USING_NES is not set
+# CONFIG_PKG_USING_VIRTUAL_SENSOR is not set
+# CONFIG_PKG_USING_VDEVICE is not set
+# CONFIG_PKG_USING_SGM706 is not set
+# CONFIG_PKG_USING_STM32WB55_SDK is not set
+# CONFIG_PKG_USING_RDA58XX is not set
+# CONFIG_PKG_USING_LIBNFC is not set
+# CONFIG_PKG_USING_MFOC is not set
+# CONFIG_PKG_USING_TMC51XX is not set
+# CONFIG_PKG_USING_TCA9534 is not set
+# CONFIG_PKG_USING_KOBUKI is not set
+# CONFIG_PKG_USING_ROSSERIAL is not set
+# CONFIG_PKG_USING_MICRO_ROS is not set
+# CONFIG_PKG_USING_MCP23008 is not set
+# CONFIG_PKG_USING_BLUETRUM_SDK is not set
+# CONFIG_PKG_USING_MISAKA_AT24CXX is not set
+# CONFIG_PKG_USING_MISAKA_RGB_BLING is not set
+# CONFIG_PKG_USING_LORA_MODEM_DRIVER is not set
+# CONFIG_PKG_USING_BL_MCU_SDK is not set
+# CONFIG_PKG_USING_SOFT_SERIAL is not set
+# CONFIG_PKG_USING_MB85RS16 is not set
+# CONFIG_PKG_USING_CW2015 is not set
+# CONFIG_PKG_USING_RFM300 is not set
+
+#
+# AI packages
+#
+# CONFIG_PKG_USING_LIBANN is not set
+# CONFIG_PKG_USING_NNOM is not set
+# CONFIG_PKG_USING_ONNX_BACKEND is not set
+# CONFIG_PKG_USING_ONNX_PARSER is not set
+# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set
+# CONFIG_PKG_USING_ELAPACK is not set
+# CONFIG_PKG_USING_ULAPACK is not set
+# CONFIG_PKG_USING_QUEST is not set
+# CONFIG_PKG_USING_NAXOS is not set
+
+#
+# miscellaneous packages
+#
+
+#
+# project laboratory
+#
+
+#
+# samples: kernel and components samples
+#
+# CONFIG_PKG_USING_KERNEL_SAMPLES is not set
+# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set
+# CONFIG_PKG_USING_NETWORK_SAMPLES is not set
+# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set
+
+#
+# entertainment: terminal games and other interesting software packages
+#
+# CONFIG_PKG_USING_CMATRIX is not set
+# CONFIG_PKG_USING_SL is not set
+# CONFIG_PKG_USING_CAL is not set
+# CONFIG_PKG_USING_ACLOCK is not set
+# CONFIG_PKG_USING_THREES is not set
+# CONFIG_PKG_USING_2048 is not set
+# CONFIG_PKG_USING_SNAKE is not set
+# CONFIG_PKG_USING_TETRIS is not set
+# CONFIG_PKG_USING_DONUT is not set
+# CONFIG_PKG_USING_COWSAY is not set
+# CONFIG_PKG_USING_LIBCSV is not set
+# CONFIG_PKG_USING_OPTPARSE is not set
+# CONFIG_PKG_USING_FASTLZ is not set
+# CONFIG_PKG_USING_MINILZO is not set
+# CONFIG_PKG_USING_QUICKLZ is not set
+# CONFIG_PKG_USING_LZMA is not set
+# CONFIG_PKG_USING_MULTIBUTTON is not set
+# CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set
+# CONFIG_PKG_USING_CANFESTIVAL is not set
+# CONFIG_PKG_USING_ZLIB is not set
+# CONFIG_PKG_USING_MINIZIP is not set
+# CONFIG_PKG_USING_HEATSHRINK is not set
+# CONFIG_PKG_USING_DSTR is not set
+# CONFIG_PKG_USING_TINYFRAME is not set
+# CONFIG_PKG_USING_KENDRYTE_DEMO is not set
+# CONFIG_PKG_USING_DIGITALCTRL is not set
+# CONFIG_PKG_USING_UPACKER is not set
+# CONFIG_PKG_USING_UPARAM is not set
+# CONFIG_PKG_USING_HELLO is not set
+# CONFIG_PKG_USING_VI is not set
+# CONFIG_PKG_USING_KI is not set
+# CONFIG_PKG_USING_ARMv7M_DWT is not set
+# CONFIG_PKG_USING_UKAL is not set
+# CONFIG_PKG_USING_CRCLIB is not set
+# CONFIG_PKG_USING_LWGPS is not set
+# CONFIG_PKG_USING_STATE_MACHINE is not set
+# CONFIG_PKG_USING_DESIGN_PATTERN is not set
+# CONFIG_PKG_USING_CONTROLLER is not set
+# CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set
+# CONFIG_PKG_USING_MFBD is not set
+CONFIG_SOC_RK3568=y
+
+#
+# Hardware Drivers Config
+#
+CONFIG_BSP_USING_UART=y
+# CONFIG_RT_USING_UART0 is not set
+# CONFIG_RT_USING_UART1 is not set
+CONFIG_RT_USING_UART2=y
+# CONFIG_RT_USING_UART3 is not set
+# CONFIG_RT_USING_UART4 is not set
+# CONFIG_RT_USING_UART5 is not set
+# CONFIG_RT_USING_UART6 is not set
+# CONFIG_RT_USING_UART7 is not set
+# CONFIG_RT_USING_UART8 is not set
+# CONFIG_RT_USING_UART9 is not set
+CONFIG_BSP_USING_GIC=y
+CONFIG_BSP_USING_GICV3=y

+ 29 - 0
bsp/rockchip/rk3568/Kconfig

@@ -0,0 +1,29 @@
+mainmenu "RT-Thread Project Configuration"
+
+config BSP_DIR
+    string
+    option env="BSP_ROOT"
+    default "."
+
+config RTT_DIR
+    string
+    option env="RTT_ROOT"
+    default "../../.."
+
+config PKGS_DIR
+    string
+    option env="PKGS_ROOT"
+    default "packages"
+
+source "$RTT_DIR/Kconfig"
+source "$PKGS_DIR/Kconfig"
+
+config SOC_RK3568
+    bool
+    select ARCH_ARMV8
+    select ARCH_CPU_64BIT
+    select RT_USING_COMPONENTS_INIT
+    select RT_USING_USER_MAIN
+    default y
+
+source "$BSP_DIR/driver/Kconfig"

+ 55 - 0
bsp/rockchip/rk3568/README.md

@@ -0,0 +1,55 @@
+# RK3568 BSP Introduction
+
+[中文页](README_zh.md) | English
+
+## 1. Introduction
+
+RK3568 is a general-purpose SOC, quad-core 64-bit Cortex-A55 processor, with 22nm lithography process, has frequency up to 2.0GHz and Mali G52 GPU, support 4K decoding and 1080P encoding. Support mangy interfaces such as SATA/PCIE/USB3.0, an 0.8T NPU for lightweight AI applications. Support dual Gigabit Ethernet ports, LPDDR4 memory, etc.
+
+This project ported RT-Thread on RK3568, you can use the RADXA ROCK 3A version of the RK3568 in low-priced, which can even replace the Raspberry Pi 4B.
+
+## 2. Compiling
+
+Usage ARM Developer GNU ToolChain, it support Linux and Windows:
+```
+https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-a/downloads/
+```
+Download the `xxx-aarch64-none-elf` of x86_64 hosted platform, set the `RTT_EXEC_PATH` is system environment after decompress the binary.
+
+Enter directory `rt-thread/bsp/qemu-virt64-aarch64` and input:
+```
+scons
+```
+
+## 3. Execution
+
+RK3568 has different Kernel install methods according to different boardsit, recommend to install into the SD card: ([Official](https://wiki.t-firefly.com/en/ROC-RK3568-PC/hardware_doc.html)|[RADXA ROCK 3A](https://wiki.radxa.com/Rock3/install/microSD)).
+
+After install Kernel, storage the `rtthread.bin` to EFI partition (the second partition), and add this line in the front of `boot.cmd` in this partition:
+```shell
+fatload mmc 1:1 0x208000 /rtthread.bin;dcache flush;go 0x208000
+```
+After modifying the script, build a binary script `boot.scr ` in this partition:
+```shell
+# Install the uboot-mkimage package on Linux, or use MSYS2 to install the u-boot-tools package on Windows
+mkimage -C none -A arm -T script -d boot.cmd boot.scr
+```
+
+According to different boards, the serial port can support up to UART0~9, this project uses UART2 ([Official](https://wiki.t-firefly.com/en/ROC-RK3568-PC/debug.html)|[RADXA ROCK 3A](https://wiki.radxa.com/Rock3/dev/serial-console)) by default, the baud rate is 1500000, please make sure that the serial port used supports this baud rate.
+
+```
+heap: [0x002663f0 - 0x042663f0]
+
+ \ | /
+- RT -     Thread Operating System
+ / | \     4.1.0 build Mar 19 2022 17:17:29
+ 2006 - 2022 Copyright by RT-Thread team
+Hi, this is RT-Thread!!
+msh />
+```
+
+## 4. Condition
+
+| Driver | Condition | Remark |
+| ------ | --------- | ------ |
+| UART   | Support   | UART0~9 |

+ 56 - 0
bsp/rockchip/rk3568/README_zh.md

@@ -0,0 +1,56 @@
+# RK3568 板级支持包说明
+
+中文页 | [English](README.md)
+
+## 1. 简介
+
+RK3568 是一款定位中高端的通用型 SOC,采用 22nm 制程工艺,集成四核 2GHz,Cortex-A55 架构和 Mali G52 GPU,支持 4K 解码和 1080P 编码。支持 SATA/PCIE/USB3.0 等各类型外围接口,内置独立的 0.8T NPU,可用于轻量级 AI 应用。支持双千兆以太网口,LPDDR4 内存等。
+
+这份 RT-Thread BSP是针对 RK3568 的一份移植。开发者可选择使用 RADXA ROCK 3A 版本的 RK3568 廉价体验,其甚至可超量替代树莓派4B。
+
+## 2. 编译说明
+
+建议使用ARM Developer GNU交叉编译工具链,目前支持Linux/Windows平台:
+```
+https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-a/downloads/
+```
+下载x86_64 Hosted平台下载对应的`xxx-aarch64-none-elf`二进制包,解压后设置`RTT_EXEC_PATH`环境变量为该编译器的bin目录下即可。
+
+进入到`rt-thread/bsp/rockchip/rk3568`目录进行输入:
+```
+scons
+```
+可以看到正常生成`rtthread.elf`与`rtthread.bin`文件。
+
+## 3. 执行
+
+RK3568 根据不同的开发板实现有不同的 Kernel 烧写方式,推荐烧录进 SD 卡:([官方板](https://wiki.t-firefly.com/zh_CN/ROC-RK3568-PC/hardware_doc.html)|[RADXA ROCK 3A](https://wiki.radxa.com/Rock3/install/microSD))。
+
+在烧写完 Kernel 后,将`rtthread.bin`放入 EFI 分区(第二分区),并在该分区的`boot.cmd`最前面中添加如下行:
+```shell
+fatload mmc 1:1 0x208000 /rtthread.bin;dcache flush;go 0x208000
+```
+修改脚本后,在该分区生成二进制脚本`boot.scr`:
+```shell
+# Linux 下安装 uboot-mkimage 软件包,Windows 下使用 MSYS2 安装 u-boot-tools 软件包
+mkimage -C none -A arm -T script -d boot.cmd boot.scr
+```
+
+根据不同的开发板实现串口最多可支持到 UART0~9,本工程默认使用 UART2([官方板](https://wiki.t-firefly.com/zh_CN/ROC-RK3568-PC/debug.html)|[RADXA ROCK 3A](https://wiki.radxa.com/Rock3/dev/serial-console)),波特率 1500000,请确保使用的串口支持该波特率。
+
+```
+heap: [0x002663f0 - 0x042663f0]
+
+ \ | /
+- RT -     Thread Operating System
+ / | \     4.1.0 build Mar 19 2022 17:17:29
+ 2006 - 2022 Copyright by RT-Thread team
+Hi, this is RT-Thread!!
+msh />
+```
+
+## 4.支持情况
+
+| 驱动 | 支持情况  |  备注  |
+| ------ | ----  | :------:  |
+| UART | 支持 | UART0~9 |

+ 14 - 0
bsp/rockchip/rk3568/SConscript

@@ -0,0 +1,14 @@
+# for module compiling
+import os
+from building import *
+
+cwd  = GetCurrentDir()
+objs = []
+list = os.listdir(cwd)
+
+for d in list:
+    path = os.path.join(cwd, d)
+    if os.path.isfile(os.path.join(path, 'SConscript')):
+        objs = objs + SConscript(os.path.join(d, 'SConscript'))
+
+Return('objs')

+ 29 - 0
bsp/rockchip/rk3568/SConstruct

@@ -0,0 +1,29 @@
+import os
+import sys
+import rtconfig
+
+from rtconfig import RTT_ROOT
+
+sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
+from building import *
+
+TARGET = 'rtthread.' + rtconfig.TARGET_EXT
+
+DefaultEnvironment(tools=[])
+env = Environment(tools = ['mingw'],
+    AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
+    CC = rtconfig.CC, CFLAGS = rtconfig.CFLAGS,
+    CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS,
+    AR = rtconfig.AR, ARFLAGS = '-rc',
+    LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS)
+env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
+env['ASCOM'] = env['ASPPCOM']
+
+Export('RTT_ROOT')
+Export('rtconfig')
+
+# prepare building environment
+objs = PrepareBuilding(env, RTT_ROOT, has_libcpu = False)
+
+# make a building
+DoBuilding(TARGET, objs)

+ 9 - 0
bsp/rockchip/rk3568/applications/SConscript

@@ -0,0 +1,9 @@
+from building import *
+
+cwd     = GetCurrentDir()
+src     = Glob('*.c') + Glob('*.cpp')
+CPPPATH = [cwd]
+
+group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')

+ 18 - 0
bsp/rockchip/rk3568/applications/main.c

@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2017-5-30      Bernard      the first version
+ */
+
+#include <rtthread.h>
+
+int main(int argc, char** argv)
+{
+    rt_kprintf("Hi, this is RT-Thread!!\n");
+
+    return 0;
+}

+ 58 - 0
bsp/rockchip/rk3568/driver/Kconfig

@@ -0,0 +1,58 @@
+menu "Hardware Drivers Config"
+
+    menuconfig BSP_USING_UART
+        bool "Using UART"
+        select RT_USING_SERIAL
+        default y
+
+        if BSP_USING_UART
+            config RT_USING_UART0
+                bool "Enable UART 0"
+                default n
+
+            config RT_USING_UART1
+                bool "Enable UART 1"
+                default n
+
+            config RT_USING_UART2
+                bool "Enable UART 2"
+                default y
+
+            config RT_USING_UART3
+                bool "Enable UART 3"
+                default n
+
+            config RT_USING_UART4
+                bool "Enable UART 4"
+                default n
+
+            config RT_USING_UART5
+                bool "Enable UART 5"
+                default n
+
+            config RT_USING_UART6
+                bool "Enable UART 6"
+                default n
+
+            config RT_USING_UART7
+                bool "Enable UART 7"
+                default n
+
+            config RT_USING_UART8
+                bool "Enable UART 8"
+                default n
+
+            config RT_USING_UART9
+                bool "Enable UART 9"
+                default n
+        endif
+
+    config BSP_USING_GIC
+        bool
+        default y
+
+        config BSP_USING_GICV3
+            bool
+            default y
+
+endmenu

+ 19 - 0
bsp/rockchip/rk3568/driver/SConscript

@@ -0,0 +1,19 @@
+# RT-Thread building script for component
+
+from building import *
+
+cwd     = GetCurrentDir()
+src     = Glob('*.c')
+list    = os.listdir(cwd)
+CPPPATH = [cwd]
+objs    = []
+
+group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
+
+for d in list:
+    path = os.path.join(cwd, d)
+    if os.path.isfile(os.path.join(path, 'SConscript')):
+        objs = objs + SConscript(os.path.join(d, 'SConscript'))
+objs = objs + group
+
+Return('objs')

+ 124 - 0
bsp/rockchip/rk3568/driver/board.c

@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2022-3-08      GuEe-GUI     the first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+
+#include <mmu.h>
+#include <psci.h>
+#include <gicv3.h>
+#include <gtimer.h>
+#include <cpuport.h>
+#include <interrupt.h>
+
+#include <board.h>
+#include <drv_uart.h>
+
+struct mem_desc platform_mem_desc[] =
+{
+    {0x200000, 0x80000000, 0x200000, NORMAL_MEM},
+    {UART0_MMIO_BASE, UART0_MMIO_BASE + 0x10000, UART0_MMIO_BASE, DEVICE_MEM},
+    {UART1_MMIO_BASE, UART1_MMIO_BASE + 0x90000, UART1_MMIO_BASE, DEVICE_MEM},
+    {GIC_PL600_DISTRIBUTOR_PPTR, GIC_PL600_DISTRIBUTOR_PPTR + 0x10000, GIC_PL600_DISTRIBUTOR_PPTR, DEVICE_MEM},
+    {GIC_PL600_REDISTRIBUTOR_PPTR, GIC_PL600_REDISTRIBUTOR_PPTR + 0xc0000, GIC_PL600_REDISTRIBUTOR_PPTR, DEVICE_MEM},
+};
+
+const rt_uint32_t platform_mem_desc_size = sizeof(platform_mem_desc) / sizeof(platform_mem_desc[0]);
+
+void idle_wfi(void)
+{
+    __asm__ volatile ("wfi");
+}
+
+void rt_hw_board_init(void)
+{
+    rt_hw_init_mmu_table(platform_mem_desc, platform_mem_desc_size);
+    rt_hw_mmu_init();
+
+    /* initialize hardware interrupt */
+    rt_hw_interrupt_init();
+    /* initialize uart */
+    rt_hw_uart_init();
+    /* initialize timer for os tick */
+    rt_hw_gtimer_init();
+
+    rt_thread_idle_sethook(idle_wfi);
+
+    arm_psci_init(PSCI_METHOD_SMC, RT_NULL, RT_NULL);
+
+#if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
+    /* set console device */
+    rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
+#endif
+
+#ifdef RT_USING_HEAP
+    /* initialize memory system */
+    rt_kprintf("heap: [0x%08x - 0x%08x]\n", RT_HW_HEAP_BEGIN, RT_HW_HEAP_END);
+    rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END);
+#endif
+
+#ifdef RT_USING_COMPONENTS_INIT
+    rt_components_board_init();
+#endif
+
+#ifdef RT_USING_SMP
+    /* install IPI handle */
+    rt_hw_ipi_handler_install(RT_SCHEDULE_IPI, rt_scheduler_ipi_handler);
+    arm_gic_umask(0, IRQ_ARM_IPI_KICK);
+#endif
+}
+
+void reboot(void)
+{
+    arm_psci_system_reboot();
+}
+MSH_CMD_EXPORT(reboot, reboot...);
+
+#ifdef RT_USING_SMP
+rt_uint64_t rt_cpu_mpidr_early[] =
+{
+    [0] = 0x81000000,
+    [1] = 0x81000100,
+    [2] = 0x81000200,
+    [3] = 0x81000300,
+};
+
+void rt_hw_secondary_cpu_up(void)
+{
+    int i;
+    extern void secondary_cpu_start(void);
+
+    for (i = 1; i < RT_CPUS_NR; ++i)
+    {
+        arm_psci_cpu_on(rt_cpu_mpidr_early[i], (rt_uint64_t)secondary_cpu_start);
+    }
+}
+
+void secondary_cpu_c_start(void)
+{
+    rt_hw_mmu_init();
+    rt_hw_spin_lock(&_cpus_lock);
+
+    arm_gic_cpu_init(0, platform_get_gic_cpu_base());
+    arm_gic_redist_init(0, platform_get_gic_redist_base());
+    rt_hw_vector_init();
+    rt_hw_gtimer_local_enable();
+    arm_gic_umask(0, IRQ_ARM_IPI_KICK);
+
+    rt_kprintf("\rcall cpu %d on success\n", rt_hw_cpu_id());
+
+    rt_system_scheduler_start();
+}
+
+void rt_hw_secondary_cpu_idle_exec(void)
+{
+    __WFE();
+}
+#endif

+ 24 - 0
bsp/rockchip/rk3568/driver/board.h

@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2017-5-30      Bernard      the first version
+ */
+
+#ifndef __BOARD_H__
+#define __BOARD_H__
+
+#include <rk3568.h>
+
+extern unsigned char __bss_start;
+extern unsigned char __bss_end;
+
+#define RT_HW_HEAP_BEGIN    (void *)&__bss_end
+#define RT_HW_HEAP_END      (void *)(RT_HW_HEAP_BEGIN + 64 * 1024 * 1024)
+
+void rt_hw_board_init(void);
+
+#endif /* __BOARD_H__ */

+ 358 - 0
bsp/rockchip/rk3568/driver/drv_uart.c

@@ -0,0 +1,358 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2022-3-08      GuEe-GUI     the first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#include <board.h>
+
+/*
+ * The Synopsys DesignWare 8250 has an extra feature whereby it detects if the
+ * LCR is written whilst busy. If it is, then a busy detect interrupt is
+ * raised, the LCR needs to be rewritten and the uart status register read.
+ */
+
+#define UART_RX             0    /* In: Receive buffer */
+#define UART_TX             0    /* Out: Transmit buffer */
+
+#define UART_DLL            0    /* Out: Divisor Latch Low */
+#define UART_DLM            1    /* Out: Divisor Latch High */
+
+#define UART_IER            1    /* Out: Interrupt Enable Register */
+#define UART_IER_RDI        0x01 /* Enable receiver data interrupt */
+
+#define UART_SSR            0x22 /* In: Software Reset Register */
+#define UART_USR            0x1f /* UART Status Register */
+
+#define UART_LCR            3    /* Out: Line Control Register */
+#define UART_LCR_DLAB       0x80 /* Divisor latch access bit */
+#define UART_LCR_SPAR       0x20 /* Stick parity (?) */
+#define UART_LCR_PARITY     0x8  /* Parity Enable */
+#define UART_LCR_STOP       0x4  /* Stop bits: 0=1 bit, 1=2 bits */
+#define UART_LCR_WLEN8      0x3  /* Wordlength: 8 bits */
+
+#define UART_MCR            4    /* Out: Modem Control Register */
+#define UART_MCR_RTS        0x02 /* RTS complement */
+
+#define UART_LSR            5    /* In: Line Status Register */
+#define UART_LSR_BI         0x10 /* Break interrupt indicator */
+#define UART_LSR_DR         0x01 /* Receiver data ready */
+
+#define UART_IIR            2    /* In: Interrupt ID Register */
+#define UART_IIR_NO_INT     0x01 /* No interrupts pending */
+#define UART_IIR_BUSY       0x07 /* DesignWare APB Busy Detect */
+#define UART_IIR_RX_TIMEOUT 0x0c /* OMAP RX Timeout interrupt */
+
+#define UART_FCR            2    /* Out: FIFO Control Register */
+#define UART_FCR_EN_FIFO    0x01 /* Enable the FIFO */
+#define UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */
+#define UART_FCR_CLEAR_XMIT 0x04 /* Clear the XMIT FIFO */
+
+#define UART_REG_SHIFT      0x2  /* Register Shift*/
+#define UART_INPUT_CLK      24000000
+
+struct hw_uart_device
+{
+    rt_ubase_t hw_base;
+    rt_uint32_t irqno;
+#ifdef RT_USING_SMP
+    struct rt_spinlock spinlock;
+#endif
+};
+
+#define BSP_DEFINE_UART_DEVICE(no)                  \
+static struct hw_uart_device _uart##no##_device =   \
+{                                                   \
+    UART##no##_MMIO_BASE,                           \
+    UART##no##_IRQ                                  \
+};                                                  \
+static struct rt_serial_device _serial##no;
+
+#ifdef RT_USING_UART0
+BSP_DEFINE_UART_DEVICE(0);
+#endif
+
+#ifdef RT_USING_UART1
+BSP_DEFINE_UART_DEVICE(1);
+#endif
+
+#ifdef RT_USING_UART2
+BSP_DEFINE_UART_DEVICE(2);
+#endif
+
+#ifdef RT_USING_UART3
+BSP_DEFINE_UART_DEVICE(3);
+#endif
+
+#ifdef RT_USING_UART4
+BSP_DEFINE_UART_DEVICE(4);
+#endif
+
+#ifdef RT_USING_UART5
+BSP_DEFINE_UART_DEVICE(5);
+#endif
+
+#ifdef RT_USING_UART6
+BSP_DEFINE_UART_DEVICE(6);
+#endif
+
+#ifdef RT_USING_UART7
+BSP_DEFINE_UART_DEVICE(7);
+#endif
+
+#ifdef RT_USING_UART8
+BSP_DEFINE_UART_DEVICE(8);
+#endif
+
+#ifdef RT_USING_UART9
+BSP_DEFINE_UART_DEVICE(9);
+#endif
+
+rt_inline rt_uint32_t dw8250_read32(rt_ubase_t addr, rt_ubase_t offset)
+{
+    return *((volatile rt_uint32_t *)(addr + (offset << UART_REG_SHIFT)));
+}
+
+rt_inline void dw8250_write32(rt_ubase_t addr, rt_ubase_t offset, rt_uint32_t value)
+{
+    *((volatile rt_uint32_t *)(addr + (offset << UART_REG_SHIFT))) = value;
+
+    if (offset == UART_LCR)
+    {
+        int tries = 1000;
+
+        /* Make sure LCR write wasn't ignored */
+        while (tries--)
+        {
+            unsigned int lcr = dw8250_read32(addr, UART_LCR);
+
+            if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR))
+            {
+                return;
+            }
+
+            dw8250_write32(addr, UART_FCR, UART_FCR_EN_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+            dw8250_read32(addr, UART_RX);
+
+            *((volatile rt_uint32_t *)(addr + (offset << UART_REG_SHIFT))) = value;
+        }
+    }
+}
+
+static rt_err_t dw8250_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
+{
+    rt_base_t base, rate;
+    struct hw_uart_device *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+    uart = (struct hw_uart_device *)serial->parent.user_data;
+    base = uart->hw_base;
+
+#ifdef RT_USING_SMP
+    rt_spin_lock_init(&uart->spinlock);
+#endif
+
+    /* Resset UART */
+    dw8250_write32(base, UART_SSR, 1);
+    dw8250_write32(base, UART_SSR, 0);
+
+    dw8250_write32(base, UART_IER, !UART_IER_RDI);
+    dw8250_write32(base, UART_FCR, UART_FCR_EN_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+
+    /* Disable flow ctrl */
+    dw8250_write32(base, UART_MCR, 0);
+    /* Clear RTS */
+    dw8250_write32(base, UART_MCR, dw8250_read32(base, UART_MCR) | UART_MCR_RTS);
+
+    rate = UART_INPUT_CLK / 16 / serial->config.baud_rate;
+
+    /* Enable access DLL & DLH */
+    dw8250_write32(base, UART_LCR, dw8250_read32(base, UART_LCR) | UART_LCR_DLAB);
+    dw8250_write32(base, UART_DLL, (rate & 0xff));
+    dw8250_write32(base, UART_DLM, (rate & 0xff00) >> 8);
+    /* Clear DLAB bit */
+    dw8250_write32(base, UART_LCR, dw8250_read32(base, UART_LCR) & (~UART_LCR_DLAB));
+
+    dw8250_write32(base, UART_LCR, (dw8250_read32(base, UART_LCR) & (~UART_LCR_WLEN8)) | UART_LCR_WLEN8);
+    dw8250_write32(base, UART_LCR, dw8250_read32(base, UART_LCR) & (~UART_LCR_STOP));
+    dw8250_write32(base, UART_LCR, dw8250_read32(base, UART_LCR) & (~UART_LCR_PARITY));
+
+    dw8250_write32(base, UART_IER, UART_IER_RDI);
+
+    return RT_EOK;
+}
+
+static rt_err_t dw8250_uart_control(struct rt_serial_device *serial, int cmd, void *arg)
+{
+    struct hw_uart_device *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+    uart = (struct hw_uart_device *)serial->parent.user_data;
+
+    switch (cmd)
+    {
+        case RT_DEVICE_CTRL_CLR_INT:
+            /* Disable rx irq */
+            dw8250_write32(uart->hw_base, UART_IER, !UART_IER_RDI);
+            rt_hw_interrupt_mask(uart->irqno);
+            break;
+
+        case RT_DEVICE_CTRL_SET_INT:
+            /* Enable rx irq */
+            dw8250_write32(uart->hw_base, UART_IER, UART_IER_RDI);
+            rt_hw_interrupt_umask(uart->irqno);
+            break;
+    }
+
+    return RT_EOK;
+}
+
+static int dw8250_uart_putc(struct rt_serial_device *serial, char c)
+{
+    rt_base_t base;
+    struct hw_uart_device *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+    uart = (struct hw_uart_device *)serial->parent.user_data;
+    base = uart->hw_base;
+
+    while ((dw8250_read32(base, UART_USR) & 0x2) == 0)
+    {
+    }
+
+    dw8250_write32(base, UART_TX, c);
+
+    return 1;
+}
+
+static int dw8250_uart_getc(struct rt_serial_device *serial)
+{
+    int ch = -1;
+    rt_base_t base;
+    struct hw_uart_device *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+    uart = (struct hw_uart_device *)serial->parent.user_data;
+    base = uart->hw_base;
+
+    if ((dw8250_read32(base, UART_LSR) & 0x1))
+    {
+        ch = dw8250_read32(base, UART_RX) & 0xff;
+    }
+
+    return ch;
+}
+
+static const struct rt_uart_ops _uart_ops =
+{
+    dw8250_uart_configure,
+    dw8250_uart_control,
+    dw8250_uart_putc,
+    dw8250_uart_getc,
+};
+
+static void rt_hw_uart_isr(int irqno, void *param)
+{
+    unsigned int iir, status;
+    struct rt_serial_device *serial = (struct rt_serial_device *)param;
+    struct hw_uart_device *uart = (struct hw_uart_device *)serial->parent.user_data;
+
+    iir = dw8250_read32(uart->hw_base, UART_IIR);
+
+    /* If don't do this in non-DMA mode then the "RX TIMEOUT" interrupt will fire forever. */
+    if ((iir & 0x3f) == UART_IIR_RX_TIMEOUT)
+    {
+#ifdef RT_USING_SMP
+        rt_base_t level = rt_spin_lock_irqsave(&uart->spinlock);
+#endif
+
+        status = dw8250_read32(uart->hw_base, UART_LSR);
+
+        if (!(status & (UART_LSR_DR | UART_LSR_BI)))
+        {
+            dw8250_read32(uart->hw_base, UART_RX);
+        }
+
+#ifdef RT_USING_SMP
+        rt_spin_unlock_irqrestore(&uart->spinlock, level);
+#endif
+    }
+
+    if (!(iir & UART_IIR_NO_INT))
+    {
+        rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
+    }
+
+    if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY)
+    {
+        /* Clear the USR */
+        dw8250_read32(uart->hw_base, UART_USR);
+
+        return;
+    }
+}
+
+int rt_hw_uart_init(void)
+{
+    struct hw_uart_device *uart;
+    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
+
+    config.baud_rate = 1500000;
+
+#define BSP_INSTALL_UART_DEVICE(no)     \
+    uart = &_uart##no##_device;         \
+    _serial##no.ops    = &_uart_ops;    \
+    _serial##no.config = config;        \
+    rt_hw_serial_register(&_serial##no, "uart" #no, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, uart); \
+    rt_hw_interrupt_install(uart->irqno, rt_hw_uart_isr, &_serial##no, "uart" #no);
+
+#ifdef RT_USING_UART0
+    BSP_INSTALL_UART_DEVICE(0);
+#endif
+
+#ifdef RT_USING_UART1
+    BSP_INSTALL_UART_DEVICE(1);
+#endif
+
+#ifdef RT_USING_UART2
+    BSP_INSTALL_UART_DEVICE(2);
+#endif
+
+#ifdef RT_USING_UART3
+    BSP_INSTALL_UART_DEVICE(3);
+#endif
+
+#ifdef RT_USING_UART4
+    BSP_INSTALL_UART_DEVICE(4);
+#endif
+
+#ifdef RT_USING_UART5
+    BSP_INSTALL_UART_DEVICE(5);
+#endif
+
+#ifdef RT_USING_UART6
+    BSP_INSTALL_UART_DEVICE(6);
+#endif
+
+#ifdef RT_USING_UART7
+    BSP_INSTALL_UART_DEVICE(7);
+#endif
+
+#ifdef RT_USING_UART8
+    BSP_INSTALL_UART_DEVICE(8);
+#endif
+
+#ifdef RT_USING_UART9
+    BSP_INSTALL_UART_DEVICE(9);
+#endif
+
+    return 0;
+}

+ 16 - 0
bsp/rockchip/rk3568/driver/drv_uart.h

@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2022-3-08      GuEe-GUI     the first version
+ */
+
+#ifndef __DRV_UART_H__
+#define __DRV_UART_H__
+
+int rt_hw_uart_init(void);
+
+#endif /* __DRV_UART_H__ */

+ 116 - 0
bsp/rockchip/rk3568/driver/rk3568.h

@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2022-3-08      GuEe-GUI     the first version
+ */
+
+#ifndef __RK3568_H__
+#define __RK3568_H__
+
+/* UART */
+#define UART_MMIO_BASE  0xfe650000
+#define UART0_MMIO_BASE 0xfdd50000
+#define UART1_MMIO_BASE (UART_MMIO_BASE + 0)
+#define UART2_MMIO_BASE (UART_MMIO_BASE + 0x10000)
+#define UART3_MMIO_BASE (UART_MMIO_BASE + 0x20000)
+#define UART4_MMIO_BASE (UART_MMIO_BASE + 0x30000)
+#define UART5_MMIO_BASE (UART_MMIO_BASE + 0x40000)
+#define UART6_MMIO_BASE (UART_MMIO_BASE + 0x50000)
+#define UART7_MMIO_BASE (UART_MMIO_BASE + 0x60000)
+#define UART8_MMIO_BASE (UART_MMIO_BASE + 0x70000)
+#define UART9_MMIO_BASE (UART_MMIO_BASE + 0x80000)
+
+#define UART_MMIO_SIZE  0x100
+
+#define UART_IRQ_BASE   (32 + 116)
+#define UART0_IRQ       (UART_IRQ_BASE + 0)
+#define UART1_IRQ       (UART_IRQ_BASE + 1)
+#define UART2_IRQ       (UART_IRQ_BASE + 2)
+#define UART3_IRQ       (UART_IRQ_BASE + 3)
+#define UART4_IRQ       (UART_IRQ_BASE + 4)
+#define UART5_IRQ       (UART_IRQ_BASE + 5)
+#define UART6_IRQ       (UART_IRQ_BASE + 6)
+#define UART7_IRQ       (UART_IRQ_BASE + 7)
+#define UART8_IRQ       (UART_IRQ_BASE + 8)
+#define UART9_IRQ       (UART_IRQ_BASE + 9)
+
+/* GPIO */
+#define GPIO0_MMIO_BASE 0xfdd60000
+#define GPIO1_MMIO_BASE 0xfe740000
+#define GPIO2_MMIO_BASE 0xfe750000
+#define GPIO3_MMIO_BASE 0xfe760000
+#define GPIO4_MMIO_BASE 0xfe770000
+
+#define GPIO_MMIO_SIZE  0x100
+
+#define GPIO_IRQ_BASE   (32 + 33)
+#define GPIO0_IRQ       (GPIO_IRQ_BASE + 0)
+#define GPIO1_IRQ       (GPIO_IRQ_BASE + 1)
+#define GPIO2_IRQ       (GPIO_IRQ_BASE + 2)
+#define GPIO3_IRQ       (GPIO_IRQ_BASE + 3)
+#define GPIO4_IRQ       (GPIO_IRQ_BASE + 4)
+
+/* MMC */
+#define MMC0_MMIO_BASE  0xfe310000  /* sdhci */
+#define MMC1_MMIO_BASE  0xfe2b0000  /* sdmmc0 */
+#define MMC2_MMIO_BASE  0xfe2c0000  /* sdmmc1 */
+#define MMC3_MMIO_BASE  0xfe000000  /* sdmmc2 */
+
+#define MMC0_MMIO_SIZE  0x10000
+#define MMC_MMIO_SIZE   0x4000
+
+#define MMC0_IRQ        (32 + 19)
+#define MMC1_IRQ        (32 + 98)
+#define MMC2_IRQ        (32 + 99)
+#define MMC3_IRQ        (32 + 100)
+
+/* Ethernet */
+#define GMAC0_MMIO_BASE 0xfe2a0000
+#define GMAC1_MMIO_BASE 0xfe010000
+
+#define GMAC_MMIO_SIZE  0x10000
+
+#define GMAC0_MAC_IRQ   (32 + 27)
+#define GMAC0_WAKE_IRQ  (32 + 24)
+#define GMAC1_MAC_IRQ   (32 + 32)
+#define GMAC1_WAKE_IRQ  (32 + 29)
+
+/* GIC */
+#define MAX_HANDLERS        256
+#define GIC_IRQ_START       0
+#define ARM_GIC_NR_IRQS     256
+#define ARM_GIC_MAX_NR      1
+
+#define IRQ_ARM_IPI_KICK    0
+#define IRQ_ARM_IPI_CALL    1
+
+#define GIC_PL600_DISTRIBUTOR_PPTR      0xfd400000
+#define GIC_PL600_REDISTRIBUTOR_PPTR    0xfd460000
+#define GIC_PL600_CONTROLLER_PPTR       RT_NULL
+#define GIC_PL600_ITS_PPTR              0xfd440000
+
+rt_inline rt_uint32_t platform_get_gic_dist_base(void)
+{
+    return GIC_PL600_DISTRIBUTOR_PPTR;
+}
+
+rt_inline rt_uint32_t platform_get_gic_redist_base(void)
+{
+    return GIC_PL600_REDISTRIBUTOR_PPTR;
+}
+
+rt_inline rt_uint32_t platform_get_gic_cpu_base(void)
+{
+    return GIC_PL600_CONTROLLER_PPTR;
+}
+
+rt_inline rt_uint32_t platform_get_gic_its_base(void)
+{
+    return GIC_PL600_ITS_PPTR;
+}
+
+#endif /* __RK3568_H__ */

+ 143 - 0
bsp/rockchip/rk3568/link.lds

@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2017-5-30      bernard      first version
+ */
+
+OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64")
+OUTPUT_ARCH(aarch64)
+
+SECTIONS
+{
+    . = 0x208000;
+    . = ALIGN(4096);
+    .text :
+    {
+        KEEP(*(.text.entrypoint))       /* The entry point */
+        *(.vectors)
+        *(.text)                        /* remaining code */
+        *(.text.*)                      /* remaining code */
+
+        *(.rodata)                      /* read-only data (constants) */
+        *(.rodata*)
+        *(.glue_7)
+        *(.glue_7t)
+        *(.gnu.linkonce.t*)
+
+        *(COMMON)
+
+        /* section information for finsh shell */
+        . = ALIGN(16);
+        __fsymtab_start = .;
+        KEEP(*(FSymTab))
+        __fsymtab_end = .;
+        . = ALIGN(16);
+        __vsymtab_start = .;
+        KEEP(*(VSymTab))
+        __vsymtab_end = .;
+        . = ALIGN(16);
+
+        /* section information for initial. */
+        . = ALIGN(16);
+        __rt_init_start = .;
+        KEEP(*(SORT(.rti_fn*)))
+        __rt_init_end = .;
+        . = ALIGN(16);
+
+        . = ALIGN(16);
+        _etext = .;
+    }
+
+    .eh_frame_hdr :
+    {
+        *(.eh_frame_hdr)
+        *(.eh_frame_entry)
+    }
+    .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
+
+    . = ALIGN(16);
+    .data :
+    {
+        *(.data)
+        *(.data.*)
+
+        *(.data1)
+        *(.data1.*)
+
+        . = ALIGN(16);
+        _gp = ABSOLUTE(.);     /* Base of small data */
+
+        *(.sdata)
+        *(.sdata.*)
+    }
+
+    . = ALIGN(16);
+    .ctors :
+    {
+        PROVIDE(__ctors_start__ = .);
+        KEEP(*(SORT(.ctors.*)))
+        KEEP(*(.ctors))
+        PROVIDE(__ctors_end__ = .);
+    }
+
+    .dtors :
+    {
+        PROVIDE(__dtors_start__ = .);
+        KEEP(*(SORT(.dtors.*)))
+        KEEP(*(.dtors))
+        PROVIDE(__dtors_end__ = .);
+    }
+
+    . = ALIGN(16);
+    .bss :
+    {
+        PROVIDE(__bss_start = .);
+        *(.bss)
+        *(.bss.*)
+        *(.dynbss)
+
+        . = ALIGN(16);
+        PROVIDE(__bss_end = .);
+    }
+    _end = .;
+
+    /* Stabs debugging sections.  */
+    .stab          0 : { *(.stab) }
+    .stabstr       0 : { *(.stabstr) }
+    .stab.excl     0 : { *(.stab.excl) }
+    .stab.exclstr  0 : { *(.stab.exclstr) }
+    .stab.index    0 : { *(.stab.index) }
+    .stab.indexstr 0 : { *(.stab.indexstr) }
+    .comment       0 : { *(.comment) }
+    /* DWARF debug sections.
+     * Symbols in the DWARF debugging sections are relative to the beginning
+     * of the section so we begin them at 0.  */
+    /* DWARF 1 */
+    .debug          0 : { *(.debug) }
+    .line           0 : { *(.line) }
+    /* GNU DWARF 1 extensions */
+    .debug_srcinfo  0 : { *(.debug_srcinfo) }
+    .debug_sfnames  0 : { *(.debug_sfnames) }
+    /* DWARF 1.1 and DWARF 2 */
+    .debug_aranges  0 : { *(.debug_aranges) }
+    .debug_pubnames 0 : { *(.debug_pubnames) }
+    /* DWARF 2 */
+    .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+    .debug_abbrev   0 : { *(.debug_abbrev) }
+    .debug_line     0 : { *(.debug_line) }
+    .debug_frame    0 : { *(.debug_frame) }
+    .debug_str      0 : { *(.debug_str) }
+    .debug_loc      0 : { *(.debug_loc) }
+    .debug_macinfo  0 : { *(.debug_macinfo) }
+    /* SGI/MIPS DWARF 2 extensions */
+    .debug_weaknames 0 : { *(.debug_weaknames) }
+    .debug_funcnames 0 : { *(.debug_funcnames) }
+    .debug_typenames 0 : { *(.debug_typenames) }
+    .debug_varnames  0 : { *(.debug_varnames) }
+}
+
+__bss_size = SIZEOF(.bss);

+ 188 - 0
bsp/rockchip/rk3568/rtconfig.h

@@ -0,0 +1,188 @@
+#ifndef RT_CONFIG_H__
+#define RT_CONFIG_H__
+
+/* Automatically generated file; DO NOT EDIT. */
+/* RT-Thread Project Configuration */
+
+/* RT-Thread Kernel */
+
+#define RT_NAME_MAX 8
+#define RT_ALIGN_SIZE 4
+#define RT_THREAD_PRIORITY_32
+#define RT_THREAD_PRIORITY_MAX 32
+#define RT_TICK_PER_SECOND 100
+#define RT_USING_OVERFLOW_CHECK
+#define RT_USING_HOOK
+#define RT_HOOK_USING_FUNC_PTR
+#define RT_USING_IDLE_HOOK
+#define RT_IDLE_HOOK_LIST_SIZE 4
+#define IDLE_THREAD_STACK_SIZE 4096
+#define RT_USING_TIMER_SOFT
+#define RT_TIMER_THREAD_PRIO 4
+#define RT_TIMER_THREAD_STACK_SIZE 4096
+
+/* kservice optimization */
+
+#define RT_DEBUG
+#define RT_DEBUG_COLOR
+
+/* Inter-Thread communication */
+
+#define RT_USING_SEMAPHORE
+#define RT_USING_MUTEX
+#define RT_USING_EVENT
+#define RT_USING_MAILBOX
+#define RT_USING_MESSAGEQUEUE
+
+/* Memory Management */
+
+#define RT_USING_MEMPOOL
+#define RT_USING_SMALL_MEM
+#define RT_USING_MEMHEAP
+#define RT_MEMHEAP_FAST_MODE
+#define RT_USING_SMALL_MEM_AS_HEAP
+#define RT_USING_MEMTRACE
+#define RT_USING_HEAP
+
+/* Kernel Device Object */
+
+#define RT_USING_DEVICE
+#define RT_USING_DEVICE_OPS
+#define RT_USING_CONSOLE
+#define RT_CONSOLEBUF_SIZE 128
+#define RT_CONSOLE_DEVICE_NAME "uart2"
+#define RT_VER_NUM 0x40100
+#define ARCH_CPU_64BIT
+#define ARCH_ARMV8
+
+/* RT-Thread Components */
+
+#define RT_USING_COMPONENTS_INIT
+#define RT_USING_USER_MAIN
+#define RT_MAIN_THREAD_STACK_SIZE 8192
+#define RT_MAIN_THREAD_PRIORITY 10
+#define RT_USING_MSH
+#define RT_USING_FINSH
+#define FINSH_USING_MSH
+#define FINSH_THREAD_NAME "tshell"
+#define FINSH_THREAD_PRIORITY 20
+#define FINSH_THREAD_STACK_SIZE 4096
+#define FINSH_USING_HISTORY
+#define FINSH_HISTORY_LINES 5
+#define FINSH_USING_SYMTAB
+#define FINSH_CMD_SIZE 80
+#define MSH_USING_BUILT_IN_COMMANDS
+#define FINSH_USING_DESCRIPTION
+#define FINSH_ARG_MAX 10
+
+/* Device Drivers */
+
+#define RT_USING_DEVICE_IPC
+#define RT_USING_SERIAL
+#define RT_USING_SERIAL_V1
+#define RT_SERIAL_RB_BUFSZ 64
+#define RT_USING_PIN
+
+/* Using USB */
+
+
+/* C/C++ and POSIX layer */
+
+#define RT_LIBC_DEFAULT_TIMEZONE 8
+
+/* POSIX (Portable Operating System Interface) layer */
+
+
+/* Interprocess Communication (IPC) */
+
+
+/* Socket is in the 'Network' category */
+
+
+/* Network */
+
+
+/* Utilities */
+
+
+/* RT-Thread Utestcases */
+
+
+/* RT-Thread online packages */
+
+/* IoT - internet of things */
+
+
+/* Wi-Fi */
+
+/* Marvell WiFi */
+
+
+/* Wiced WiFi */
+
+
+/* IoT Cloud */
+
+
+/* security packages */
+
+
+/* language packages */
+
+
+/* multimedia packages */
+
+/* LVGL: powerful and easy-to-use embedded GUI library */
+
+
+/* u8g2: a monochrome graphic library */
+
+
+/* PainterEngine: A cross-platform graphics application framework written in C language */
+
+
+/* tools packages */
+
+
+/* system packages */
+
+/* enhanced kernel services */
+
+
+/* POSIX extension functions */
+
+
+/* acceleration: Assembly language or algorithmic acceleration packages */
+
+
+/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */
+
+
+/* Micrium: Micrium software products porting for RT-Thread */
+
+
+/* peripheral libraries and drivers */
+
+
+/* AI packages */
+
+
+/* miscellaneous packages */
+
+/* project laboratory */
+
+/* samples: kernel and components samples */
+
+
+/* entertainment: terminal games and other interesting software packages */
+
+#define SOC_RK3568
+
+/* Hardware Drivers Config */
+
+#define BSP_USING_UART
+#define RT_USING_UART2
+#define BSP_USING_GIC
+#define BSP_USING_GICV3
+
+#endif

+ 53 - 0
bsp/rockchip/rk3568/rtconfig.py

@@ -0,0 +1,53 @@
+import os
+
+# toolchains options
+ARCH        ='aarch64'
+CPU         ='cortex-a'
+CROSS_TOOL  ='gcc'
+
+if os.getenv('RTT_ROOT'):
+    RTT_ROOT = os.getenv('RTT_ROOT')
+else:
+    RTT_ROOT = os.path.join(os.getcwd(), '..', '..', '..')
+
+if os.getenv('RTT_CC'):
+    CROSS_TOOL = os.getenv('RTT_CC')
+
+PLATFORM    = 'gcc'
+EXEC_PATH   = r'/opt/gcc-arm-8.3-2019.03-x86_64-aarch64-elf/bin/'
+
+if os.getenv('RTT_EXEC_PATH'):
+    EXEC_PATH = os.getenv('RTT_EXEC_PATH')
+
+BUILD = 'debug'
+
+if PLATFORM == 'gcc':
+    # toolchains
+    PREFIX = 'aarch64-none-elf-'
+    CC      = PREFIX + 'gcc'
+    CXX     = PREFIX + 'g++'
+    AS      = PREFIX + 'gcc'
+    AR      = PREFIX + 'ar'
+    LINK    = PREFIX + 'gcc'
+    TARGET_EXT = 'elf'
+    SIZE    = PREFIX + 'size'
+    OBJDUMP = PREFIX + 'objdump'
+    OBJCPY  = PREFIX + 'objcopy'
+
+    DEVICE = ' -g -march=armv8-a -mtune=cortex-a55'
+    CFLAGS = DEVICE + ' -Wall'
+    AFLAGS = ' -c' + ' -x assembler-with-cpp -D__ASSEMBLY__'
+    LFLAGS  = DEVICE + ' -nostartfiles -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,system_vectors -T link.lds'
+    CPATH   = ''
+    LPATH   = ''
+
+    if BUILD == 'debug':
+        CFLAGS += ' -O0 -gdwarf-2'
+        AFLAGS += ' -gdwarf-2'
+    else:
+        CFLAGS += ' -O2'
+
+    CXXFLAGS = CFLAGS
+
+DUMP_ACTION = OBJDUMP + ' -D -S $TARGET > rtt.asm\n'
+POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n'

+ 3 - 0
include/rthw.h

@@ -26,6 +26,9 @@ extern "C" {
 /*
  * Some macros define
  */
+#ifndef HWREG64
+#define HWREG64(x)          (*((volatile rt_uint64_t *)(x)))
+#endif
 #ifndef HWREG32
 #define HWREG32(x)          (*((volatile rt_uint32_t *)(x)))
 #endif

+ 0 - 4
libcpu/aarch64/common/SConscript

@@ -6,10 +6,6 @@ Import('rtconfig')
 
 cwd     = GetCurrentDir()
 src     = Glob('*.c') + Glob('*.cpp') + Glob('*.S')
-
-if not GetDepend('BSP_USING_GIC'):
-    SrcRemove(src, 'gic.c')
-
 CPPPATH = [cwd]
 
 group = DefineGroup('common', src, depend = [''], CPPPATH = CPPPATH)

+ 40 - 28
libcpu/aarch64/common/gic.c

@@ -9,20 +9,25 @@
  * 2014-04-03     Grissiom     many enhancements
  * 2018-11-22     Jesven       add rt_hw_ipi_send()
  *                             add rt_hw_ipi_handler_install()
+ * 2022-03-08     GuEe-GUI     add BSP bind SPI CPU self support
  */
 
 #include <rthw.h>
 #include <rtthread.h>
 
+#if defined(BSP_USING_GIC) && defined(BSP_USING_GICV2)
+
 #include <gic.h>
 #include <cpuport.h>
 
+#include <board.h>
+
 struct arm_gic
 {
     rt_uint64_t offset;         /* the first interrupt index in the vector table */
 
     rt_uint64_t dist_hw_base;   /* the base address of the gic distributor */
-    rt_uint64_t cpu_hw_base;    /* the base addrees of the gic cpu interface */
+    rt_uint64_t cpu_hw_base;    /* the base address of the gic cpu interface */
 };
 
 /* 'ARM_GIC_MAX_NR' is the number of cores */
@@ -30,33 +35,33 @@ static struct arm_gic _gic_table[ARM_GIC_MAX_NR];
 
 /** Macro to access the Generic Interrupt Controller Interface (GICC)
 */
-#define GIC_CPU_CTRL(hw_base)               __REG32((hw_base) + 0x00U)
-#define GIC_CPU_PRIMASK(hw_base)            __REG32((hw_base) + 0x04U)
-#define GIC_CPU_BINPOINT(hw_base)           __REG32((hw_base) + 0x08U)
-#define GIC_CPU_INTACK(hw_base)             __REG32((hw_base) + 0x0cU)
-#define GIC_CPU_EOI(hw_base)                __REG32((hw_base) + 0x10U)
-#define GIC_CPU_RUNNINGPRI(hw_base)         __REG32((hw_base) + 0x14U)
-#define GIC_CPU_HIGHPRI(hw_base)            __REG32((hw_base) + 0x18U)
-#define GIC_CPU_IIDR(hw_base)               __REG32((hw_base) + 0xFCU)
+#define GIC_CPU_CTRL(hw_base)               HWREG32((hw_base) + 0x00U)
+#define GIC_CPU_PRIMASK(hw_base)            HWREG32((hw_base) + 0x04U)
+#define GIC_CPU_BINPOINT(hw_base)           HWREG32((hw_base) + 0x08U)
+#define GIC_CPU_INTACK(hw_base)             HWREG32((hw_base) + 0x0cU)
+#define GIC_CPU_EOI(hw_base)                HWREG32((hw_base) + 0x10U)
+#define GIC_CPU_RUNNINGPRI(hw_base)         HWREG32((hw_base) + 0x14U)
+#define GIC_CPU_HIGHPRI(hw_base)            HWREG32((hw_base) + 0x18U)
+#define GIC_CPU_IIDR(hw_base)               HWREG32((hw_base) + 0xFCU)
 
 /** Macro to access the Generic Interrupt Controller Distributor (GICD)
 */
-#define GIC_DIST_CTRL(hw_base)              __REG32((hw_base) + 0x000U)
-#define GIC_DIST_TYPE(hw_base)              __REG32((hw_base) + 0x004U)
-#define GIC_DIST_IGROUP(hw_base, n)         __REG32((hw_base) + 0x080U + ((n)/32U) * 4U)
-#define GIC_DIST_ENABLE_SET(hw_base, n)     __REG32((hw_base) + 0x100U + ((n)/32U) * 4U)
-#define GIC_DIST_ENABLE_CLEAR(hw_base, n)   __REG32((hw_base) + 0x180U + ((n)/32U) * 4U)
-#define GIC_DIST_PENDING_SET(hw_base, n)    __REG32((hw_base) + 0x200U + ((n)/32U) * 4U)
-#define GIC_DIST_PENDING_CLEAR(hw_base, n)  __REG32((hw_base) + 0x280U + ((n)/32U) * 4U)
-#define GIC_DIST_ACTIVE_SET(hw_base, n)     __REG32((hw_base) + 0x300U + ((n)/32U) * 4U)
-#define GIC_DIST_ACTIVE_CLEAR(hw_base, n)   __REG32((hw_base) + 0x380U + ((n)/32U) * 4U)
-#define GIC_DIST_PRI(hw_base, n)            __REG32((hw_base) + 0x400U +  ((n)/4U) * 4U)
-#define GIC_DIST_TARGET(hw_base, n)         __REG32((hw_base) + 0x800U +  ((n)/4U) * 4U)
-#define GIC_DIST_CONFIG(hw_base, n)         __REG32((hw_base) + 0xc00U + ((n)/16U) * 4U)
-#define GIC_DIST_SOFTINT(hw_base)           __REG32((hw_base) + 0xf00U)
-#define GIC_DIST_CPENDSGI(hw_base, n)       __REG32((hw_base) + 0xf10U + ((n)/4U) * 4U)
-#define GIC_DIST_SPENDSGI(hw_base, n)       __REG32((hw_base) + 0xf20U + ((n)/4U) * 4U)
-#define GIC_DIST_ICPIDR2(hw_base)           __REG32((hw_base) + 0xfe8U)
+#define GIC_DIST_CTRL(hw_base)              HWREG32((hw_base) + 0x000U)
+#define GIC_DIST_TYPE(hw_base)              HWREG32((hw_base) + 0x004U)
+#define GIC_DIST_IGROUP(hw_base, n)         HWREG32((hw_base) + 0x080U + ((n)/32U) * 4U)
+#define GIC_DIST_ENABLE_SET(hw_base, n)     HWREG32((hw_base) + 0x100U + ((n)/32U) * 4U)
+#define GIC_DIST_ENABLE_CLEAR(hw_base, n)   HWREG32((hw_base) + 0x180U + ((n)/32U) * 4U)
+#define GIC_DIST_PENDING_SET(hw_base, n)    HWREG32((hw_base) + 0x200U + ((n)/32U) * 4U)
+#define GIC_DIST_PENDING_CLEAR(hw_base, n)  HWREG32((hw_base) + 0x280U + ((n)/32U) * 4U)
+#define GIC_DIST_ACTIVE_SET(hw_base, n)     HWREG32((hw_base) + 0x300U + ((n)/32U) * 4U)
+#define GIC_DIST_ACTIVE_CLEAR(hw_base, n)   HWREG32((hw_base) + 0x380U + ((n)/32U) * 4U)
+#define GIC_DIST_PRI(hw_base, n)            HWREG32((hw_base) + 0x400U +  ((n)/4U) * 4U)
+#define GIC_DIST_TARGET(hw_base, n)         HWREG32((hw_base) + 0x800U +  ((n)/4U) * 4U)
+#define GIC_DIST_CONFIG(hw_base, n)         HWREG32((hw_base) + 0xc00U + ((n)/16U) * 4U)
+#define GIC_DIST_SOFTINT(hw_base)           HWREG32((hw_base) + 0xf00U)
+#define GIC_DIST_CPENDSGI(hw_base, n)       HWREG32((hw_base) + 0xf10U + ((n)/4U) * 4U)
+#define GIC_DIST_SPENDSGI(hw_base, n)       HWREG32((hw_base) + 0xf20U + ((n)/4U) * 4U)
+#define GIC_DIST_ICPIDR2(hw_base)           HWREG32((hw_base) + 0xfe8U)
 
 static unsigned int _gic_max_irq;
 
@@ -179,7 +184,7 @@ void arm_gic_clear_pending_irq(rt_uint64_t index, int irq)
     }
 }
 
-void arm_gic_set_configuration(rt_uint64_t index, int irq, uint32_t config)
+void arm_gic_set_configuration(rt_uint64_t index, int irq, rt_uint32_t config)
 {
     rt_uint64_t icfgr;
     rt_uint64_t shift;
@@ -323,6 +328,8 @@ void arm_gic_send_sgi(rt_uint64_t index, int irq, rt_uint64_t target_list, rt_ui
 
     GIC_DIST_SOFTINT(_gic_table[index].dist_hw_base) =
         ((filter_list & 0x3U) << 24U) | ((target_list & 0xFFUL) << 16U) | (irq & 0x0FUL);
+
+    __DSB();
 }
 
 rt_uint64_t arm_gic_get_high_pending_irq(rt_uint64_t index)
@@ -341,8 +348,8 @@ rt_uint64_t arm_gic_get_interface_id(rt_uint64_t index)
 
 void arm_gic_set_group(rt_uint64_t index, int irq, rt_uint64_t group)
 {
-    uint32_t igroupr;
-    uint32_t shift;
+    rt_uint32_t igroupr;
+    rt_uint32_t shift;
 
     RT_ASSERT(index < ARM_GIC_MAX_NR);
     RT_ASSERT(group <= 1U);
@@ -373,6 +380,10 @@ int arm_gic_dist_init(rt_uint64_t index, rt_uint64_t dist_base, int irq_start)
     unsigned int gic_type, i;
     rt_uint64_t cpumask = 1U << 0U;
 
+#ifdef ARM_SPI_BIND_CPU_ID
+    cpumask = 1U << ARM_SPI_BIND_CPU_ID;
+#endif
+
     RT_ASSERT(index < ARM_GIC_MAX_NR);
 
     _gic_table[index].dist_hw_base = dist_base;
@@ -502,3 +513,4 @@ long gic_dump(void)
 }
 MSH_CMD_EXPORT(gic_dump, show gic status);
 
+#endif /* defined(BSP_USING_GIC) && defined(BSP_USING_GICV2) */

+ 6 - 4
libcpu/aarch64/common/gic.h

@@ -11,9 +11,9 @@
 #ifndef __GIC_H__
 #define __GIC_H__
 
-#include <rthw.h>
-#include <stdint.h>
-#include <board.h>
+#include <rtdef.h>
+
+#if defined(BSP_USING_GIC) && defined(BSP_USING_GICV2)
 
 int arm_gic_get_active_irq(rt_uint64_t index);
 void arm_gic_ack(rt_uint64_t index, int irq);
@@ -25,7 +25,7 @@ rt_uint64_t arm_gic_get_pending_irq(rt_uint64_t index, int irq);
 void arm_gic_set_pending_irq(rt_uint64_t index, int irq);
 void arm_gic_clear_pending_irq(rt_uint64_t index, int irq);
 
-void arm_gic_set_configuration(rt_uint64_t index, int irq, uint32_t config);
+void arm_gic_set_configuration(rt_uint64_t index, int irq, rt_uint32_t config);
 rt_uint64_t arm_gic_get_configuration(rt_uint64_t index, int irq);
 
 void arm_gic_clear_active(rt_uint64_t index, int irq);
@@ -59,5 +59,7 @@ int arm_gic_cpu_init(rt_uint64_t index, rt_uint64_t cpu_base);
 void arm_gic_dump_type(rt_uint64_t index);
 void arm_gic_dump(rt_uint64_t index);
 
+#endif /* defined(BSP_USING_GIC) && defined(BSP_USING_GICV2) */
+
 #endif
 

+ 849 - 0
libcpu/aarch64/common/gicv3.c

@@ -0,0 +1,849 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2013-07-20     Bernard      first version
+ * 2014-04-03     Grissiom     many enhancements
+ * 2018-11-22     Jesven       add rt_hw_ipi_send()
+ *                             add rt_hw_ipi_handler_install()
+ * 2022-03-08     GuEe-GUI     add BSP bind SPI CPU self support
+ *                             add GICv3 AArch64 system register interface
+ *                             modify arm_gic_redist_init() args
+ *                             modify arm_gic_cpu_init() args
+ *                             modify arm_gic_send_affinity_sgi() args
+ *                             remove arm_gic_redist_address_set()
+ *                             remove arm_gic_cpu_interface_address_set()
+ *                             remove arm_gic_secondary_cpu_init()
+ *                             remove get_main_cpu_affval()
+ *                             remove arm_gic_cpumask_to_affval()
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+
+#if defined(BSP_USING_GIC) && defined(BSP_USING_GICV3)
+
+#include <gicv3.h>
+#include <cpuport.h>
+
+#include <board.h>
+
+#ifndef ARM_SPI_BIND_CPU_ID
+#define ARM_SPI_BIND_CPU_ID 0
+#endif
+
+#ifndef RT_USING_SMP
+#define RT_CPUS_NR 1
+extern int rt_hw_cpu_id(void);
+#else
+extern rt_uint64_t rt_cpu_mpidr_early[];
+#endif /* RT_USING_SMP */
+
+struct arm_gic
+{
+    rt_uint64_t offset;                     /* the first interrupt index in the vector table */
+    rt_uint64_t redist_hw_base[RT_CPUS_NR]; /* the pointer of the gic redistributor */
+    rt_uint64_t dist_hw_base;               /* the base address of the gic distributor */
+    rt_uint64_t cpu_hw_base[RT_CPUS_NR];    /* the base address of the gic cpu interface */
+};
+
+/* 'ARM_GIC_MAX_NR' is the number of cores */
+static struct arm_gic _gic_table[ARM_GIC_MAX_NR];
+static unsigned int _gic_max_irq;
+
+#define GET_GICV3_REG(reg, out) __asm__ volatile ("mrs %0, " reg:"=r"(out)::"memory");
+#define SET_GICV3_REG(reg, in)  __asm__ volatile ("msr " reg ", %0"::"r"(in):"memory");
+
+/* AArch64 System register interface to GICv3 */
+#define ICC_IAR0_EL1    "S3_0_C12_C8_0"
+#define ICC_IAR1_EL1    "S3_0_C12_C12_0"
+#define ICC_EOIR0_EL1   "S3_0_C12_C8_1"
+#define ICC_EOIR1_EL1   "S3_0_C12_C12_1"
+#define ICC_HPPIR0_EL1  "S3_0_C12_C8_2"
+#define ICC_HPPIR1_EL1  "S3_0_C12_C12_2"
+#define ICC_BPR0_EL1    "S3_0_C12_C8_3"
+#define ICC_BPR1_EL1    "S3_0_C12_C12_3"
+#define ICC_DIR_EL1     "S3_0_C12_C11_1"
+#define ICC_PMR_EL1     "S3_0_C4_C6_0"
+#define ICC_RPR_EL1     "S3_0_C12_C11_3"
+#define ICC_CTLR_EL1    "S3_0_C12_C12_4"
+#define ICC_CTLR_EL3    "S3_6_C12_C12_4"
+#define ICC_SRE_EL1     "S3_0_C12_C12_5"
+#define ICC_SRE_EL2     "S3_4_C12_C9_5"
+#define ICC_SRE_EL3     "S3_6_C12_C12_5"
+#define ICC_IGRPEN0_EL1 "S3_0_C12_C12_6"
+#define ICC_IGRPEN1_EL1 "S3_0_C12_C12_7"
+#define ICC_IGRPEN1_EL3 "S3_6_C12_C12_7"
+#define ICC_SGI0R_EL1   "S3_0_C12_C11_7"
+#define ICC_SGI1R_EL1   "S3_0_C12_C11_5"
+#define ICC_ASGI1R_EL1  "S3_0_C12_C11_6"
+
+/* Macro to access the Distributor Control Register (GICD_CTLR) */
+#define GICD_CTLR_RWP       (1 << 31)
+#define GICD_CTLR_E1NWF     (1 << 7)
+#define GICD_CTLR_DS        (1 << 6)
+#define GICD_CTLR_ARE_NS    (1 << 5)
+#define GICD_CTLR_ARE_S     (1 << 4)
+#define GICD_CTLR_ENGRP1S   (1 << 2)
+#define GICD_CTLR_ENGRP1NS  (1 << 1)
+#define GICD_CTLR_ENGRP0    (1 << 0)
+
+/* Macro to access the Redistributor Control Register (GICR_CTLR) */
+#define GICR_CTLR_UWP       (1 << 31)
+#define GICR_CTLR_DPG1S     (1 << 26)
+#define GICR_CTLR_DPG1NS    (1 << 25)
+#define GICR_CTLR_DPG0      (1 << 24)
+#define GICR_CTLR_RWP       (1 << 3)
+#define GICR_CTLR_IR        (1 << 2)
+#define GICR_CTLR_CES       (1 << 1)
+#define GICR_CTLR_EnableLPI (1 << 0)
+
+/* Macro to access the Generic Interrupt Controller Interface (GICC) */
+#define GIC_CPU_CTRL(hw_base)               HWREG32((hw_base) + 0x00U)
+#define GIC_CPU_PRIMASK(hw_base)            HWREG32((hw_base) + 0x04U)
+#define GIC_CPU_BINPOINT(hw_base)           HWREG32((hw_base) + 0x08U)
+#define GIC_CPU_INTACK(hw_base)             HWREG32((hw_base) + 0x0cU)
+#define GIC_CPU_EOI(hw_base)                HWREG32((hw_base) + 0x10U)
+#define GIC_CPU_RUNNINGPRI(hw_base)         HWREG32((hw_base) + 0x14U)
+#define GIC_CPU_HIGHPRI(hw_base)            HWREG32((hw_base) + 0x18U)
+#define GIC_CPU_IIDR(hw_base)               HWREG32((hw_base) + 0xFCU)
+
+/* Macro to access the Generic Interrupt Controller Distributor (GICD) */
+#define GIC_DIST_CTRL(hw_base)              HWREG32((hw_base) + 0x000U)
+#define GIC_DIST_TYPE(hw_base)              HWREG32((hw_base) + 0x004U)
+#define GIC_DIST_IGROUP(hw_base, n)         HWREG32((hw_base) + 0x080U + ((n) / 32U) * 4U)
+#define GIC_DIST_ENABLE_SET(hw_base, n)     HWREG32((hw_base) + 0x100U + ((n) / 32U) * 4U)
+#define GIC_DIST_ENABLE_CLEAR(hw_base, n)   HWREG32((hw_base) + 0x180U + ((n) / 32U) * 4U)
+#define GIC_DIST_PENDING_SET(hw_base, n)    HWREG32((hw_base) + 0x200U + ((n) / 32U) * 4U)
+#define GIC_DIST_PENDING_CLEAR(hw_base, n)  HWREG32((hw_base) + 0x280U + ((n) / 32U) * 4U)
+#define GIC_DIST_ACTIVE_SET(hw_base, n)     HWREG32((hw_base) + 0x300U + ((n) / 32U) * 4U)
+#define GIC_DIST_ACTIVE_CLEAR(hw_base, n)   HWREG32((hw_base) + 0x380U + ((n) / 32U) * 4U)
+#define GIC_DIST_PRI(hw_base, n)            HWREG32((hw_base) + 0x400U + ((n) / 4U) * 4U)
+#define GIC_DIST_TARGET(hw_base, n)         HWREG32((hw_base) + 0x800U + ((n) / 4U) * 4U)
+#define GIC_DIST_CONFIG(hw_base, n)         HWREG32((hw_base) + 0xc00U + ((n) / 16U) * 4U)
+#define GIC_DIST_SOFTINT(hw_base)           HWREG32((hw_base) + 0xf00U)
+#define GIC_DIST_CPENDSGI(hw_base, n)       HWREG32((hw_base) + 0xf10U + ((n) / 4U) * 4U)
+#define GIC_DIST_SPENDSGI(hw_base, n)       HWREG32((hw_base) + 0xf20U + ((n) / 4U) * 4U)
+#define GIC_DIST_ICPIDR2(hw_base)           HWREG32((hw_base) + 0xfe8U)
+#define GIC_DIST_IROUTER(hw_base, n)        HWREG64((hw_base) + 0x6000U + (n) * 8U)
+
+/* SGI base address is at 64K offset from Redistributor base address */
+#define GIC_RSGI_OFFSET 0x10000
+
+/* Macro to access the Generic Interrupt Controller Redistributor (GICR) */
+#define GIC_RDIST_CTRL(hw_base)             HWREG32((hw_base) + 0x000U)
+#define GIC_RDIST_IIDR(hw_base)             HWREG32((hw_base) + 0x004U)
+#define GIC_RDIST_TYPER(hw_base)            HWREG64((hw_base) + 0x008U)
+#define GIC_RDIST_TSTATUSR(hw_base)         HWREG32((hw_base) + 0x010U)
+#define GIC_RDIST_WAKER(hw_base)            HWREG32((hw_base) + 0x014U)
+#define GIC_RDIST_SETLPIR(hw_base)          HWREG32((hw_base) + 0x040U)
+#define GIC_RDIST_CLRLPIR(hw_base)          HWREG32((hw_base) + 0x048U)
+#define GIC_RDIST_PROPBASER(hw_base)        HWREG32((hw_base) + 0x070U)
+#define GIC_RDIST_PENDBASER(hw_base)        HWREG32((hw_base) + 0x078U)
+#define GIC_RDIST_INVLPIR(hw_base)          HWREG32((hw_base) + 0x0A0U)
+#define GIC_RDIST_INVALLR(hw_base)          HWREG32((hw_base) + 0x0B0U)
+#define GIC_RDIST_SYNCR(hw_base)            HWREG32((hw_base) + 0x0C0U)
+
+#define GIC_RDISTSGI_IGROUPR0(hw_base, n)   HWREG32((hw_base) + GIC_RSGI_OFFSET + 0x080U + (n) * 4U)
+#define GIC_RDISTSGI_ISENABLER0(hw_base)    HWREG32((hw_base) + GIC_RSGI_OFFSET + 0x100U)
+#define GIC_RDISTSGI_ICENABLER0(hw_base)    HWREG32((hw_base) + GIC_RSGI_OFFSET + 0x180U)
+#define GIC_RDISTSGI_ISPENDR0(hw_base)      HWREG32((hw_base) + GIC_RSGI_OFFSET + 0x200U)
+#define GIC_RDISTSGI_ICPENDR0(hw_base)      HWREG32((hw_base) + GIC_RSGI_OFFSET + 0x280U)
+#define GIC_RDISTSGI_ISACTIVER0(hw_base)    HWREG32((hw_base) + GIC_RSGI_OFFSET + 0x300U)
+#define GIC_RDISTSGI_ICACTIVER0(hw_base)    HWREG32((hw_base) + GIC_RSGI_OFFSET + 0x380U)
+#define GIC_RDISTSGI_IPRIORITYR(hw_base, n) HWREG32((hw_base) + GIC_RSGI_OFFSET + 0x400U + ((n) / 4U) * 4U)
+#define GIC_RDISTSGI_ICFGR0(hw_base)        HWREG32((hw_base) + GIC_RSGI_OFFSET + 0xC00U)
+#define GIC_RDISTSGI_ICFGR1(hw_base)        HWREG32((hw_base) + GIC_RSGI_OFFSET + 0xC04U)
+#define GIC_RDISTSGI_IGRPMODR0(hw_base, n)  HWREG32((hw_base) + GIC_RSGI_OFFSET + 0xD00U + (n) * 4)
+#define GIC_RDISTSGI_NSACR(hw_base)         HWREG32((hw_base) + GIC_RSGI_OFFSET + 0xE00U)
+
+int arm_gic_get_active_irq(rt_uint64_t index)
+{
+    int irq;
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    GET_GICV3_REG(ICC_IAR1_EL1, irq);
+
+    irq = (irq & 0x1ffffff) + _gic_table[index].offset;
+    return irq;
+}
+
+void arm_gic_ack(rt_uint64_t index, int irq)
+{
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+    RT_ASSERT(irq >= 0);
+
+    __DSB();
+    SET_GICV3_REG(ICC_EOIR1_EL1, irq);
+}
+
+void arm_gic_mask(rt_uint64_t index, int irq)
+{
+    rt_uint64_t mask = 1 << (irq % 32);
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0);
+
+    if (irq < 32)
+    {
+        rt_int32_t cpu_id = rt_hw_cpu_id();
+
+        GIC_RDISTSGI_ICENABLER0(_gic_table[index].redist_hw_base[cpu_id]) = mask;
+    }
+    else
+    {
+        GIC_DIST_ENABLE_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
+    }
+}
+
+void arm_gic_umask(rt_uint64_t index, int irq)
+{
+    rt_uint64_t mask = 1 << (irq % 32);
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0);
+
+    if (irq < 32)
+    {
+        rt_int32_t cpu_id = rt_hw_cpu_id();
+
+        GIC_RDISTSGI_ISENABLER0(_gic_table[index].redist_hw_base[cpu_id]) = mask;
+    }
+    else
+    {
+        GIC_DIST_ENABLE_SET(_gic_table[index].dist_hw_base, irq) = mask;
+    }
+}
+
+rt_uint64_t arm_gic_get_pending_irq(rt_uint64_t index, int irq)
+{
+    rt_uint64_t pend;
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0);
+
+    if (irq >= 16)
+    {
+        pend = (GIC_DIST_PENDING_SET(_gic_table[index].dist_hw_base, irq) >> (irq % 32)) & 0x1;
+    }
+    else
+    {
+        /* INTID 0-15 Software Generated Interrupt */
+        pend = (GIC_DIST_SPENDSGI(_gic_table[index].dist_hw_base, irq) >> ((irq % 4) * 8)) & 0xff;
+        /* No CPU identification offered */
+        if (pend != 0)
+        {
+            pend = 1;
+        }
+        else
+        {
+            pend = 0;
+        }
+    }
+
+    return pend;
+}
+
+void arm_gic_set_pending_irq(rt_uint64_t index, int irq)
+{
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0);
+
+    if (irq >= 16)
+    {
+        GIC_DIST_PENDING_SET(_gic_table[index].dist_hw_base, irq) = 1 << (irq % 32);
+    }
+    else
+    {
+        /* INTID 0-15 Software Generated Interrupt */
+        /* Forward the interrupt to the CPU interface that requested it */
+        GIC_DIST_SOFTINT(_gic_table[index].dist_hw_base) = (irq | 0x02000000);
+    }
+}
+
+void arm_gic_clear_pending_irq(rt_uint64_t index, int irq)
+{
+    rt_uint64_t mask;
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0);
+
+    if (irq >= 16)
+    {
+        mask = 1 << (irq % 32);
+        GIC_DIST_PENDING_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
+    }
+    else
+    {
+        mask = 1 << ((irq % 4) * 8);
+        GIC_DIST_CPENDSGI(_gic_table[index].dist_hw_base, irq) = mask;
+    }
+}
+
+void arm_gic_set_configuration(rt_uint64_t index, int irq, rt_uint32_t config)
+{
+    rt_uint64_t icfgr;
+    rt_uint64_t shift;
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0);
+
+    icfgr = GIC_DIST_CONFIG(_gic_table[index].dist_hw_base, irq);
+    shift = (irq % 16) << 1;
+
+    icfgr &= (~(3 << shift));
+    icfgr |= (config << shift);
+
+    GIC_DIST_CONFIG(_gic_table[index].dist_hw_base, irq) = icfgr;
+}
+
+rt_uint64_t arm_gic_get_configuration(rt_uint64_t index, int irq)
+{
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0);
+
+    return (GIC_DIST_CONFIG(_gic_table[index].dist_hw_base, irq) >> ((irq % 16) >> 1));
+}
+
+void arm_gic_clear_active(rt_uint64_t index, int irq)
+{
+    rt_uint64_t mask = 1 << (irq % 32);
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0);
+
+    GIC_DIST_ACTIVE_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
+}
+
+/* Set up the cpu mask for the specific interrupt */
+void arm_gic_set_cpu(rt_uint64_t index, int irq, unsigned int cpumask)
+{
+    rt_uint64_t old_tgt;
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0);
+
+    old_tgt = GIC_DIST_TARGET(_gic_table[index].dist_hw_base, irq);
+
+    old_tgt &= ~(0x0ff << ((irq % 4) * 8));
+    old_tgt |= cpumask << ((irq % 4) * 8);
+
+    GIC_DIST_TARGET(_gic_table[index].dist_hw_base, irq) = old_tgt;
+}
+
+rt_uint64_t arm_gic_get_target_cpu(rt_uint64_t index, int irq)
+{
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0);
+
+    return (GIC_DIST_TARGET(_gic_table[index].dist_hw_base, irq) >> ((irq % 4) * 8)) & 0xff;
+}
+
+void arm_gic_set_priority(rt_uint64_t index, int irq, rt_uint64_t priority)
+{
+    rt_uint64_t mask;
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0);
+
+    if (irq < 32)
+    {
+        rt_int32_t cpu_id = rt_hw_cpu_id();
+
+        mask = GIC_RDISTSGI_IPRIORITYR(_gic_table[index].redist_hw_base[cpu_id], irq);
+        mask &= ~(0xff << ((irq % 4) * 8));
+        mask |= ((priority & 0xff) << ((irq % 4) * 8));
+        GIC_RDISTSGI_IPRIORITYR(_gic_table[index].redist_hw_base[cpu_id], irq) = mask;
+    }
+    else
+    {
+        mask = GIC_DIST_PRI(_gic_table[index].dist_hw_base, irq);
+        mask &= ~(0xff << ((irq % 4) * 8));
+        mask |= ((priority & 0xff) << ((irq % 4) * 8));
+        GIC_DIST_PRI(_gic_table[index].dist_hw_base, irq) = mask;
+    }
+}
+
+rt_uint64_t arm_gic_get_priority(rt_uint64_t index, int irq)
+{
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0);
+
+    if (irq < 32)
+    {
+        rt_int32_t cpu_id = rt_hw_cpu_id();
+
+        return (GIC_RDISTSGI_IPRIORITYR(_gic_table[index].redist_hw_base[cpu_id], irq) >> ((irq % 4) * 8)) & 0xff;
+    }
+    else
+    {
+        return (GIC_DIST_PRI(_gic_table[index].dist_hw_base, irq) >> ((irq % 4) * 8)) & 0xff;
+    }
+}
+
+void arm_gic_set_system_register_enable_mask(rt_uint64_t index, rt_uint64_t value)
+{
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    value &= 0xff;
+    /* set priority mask */
+    SET_GICV3_REG(ICC_SRE_EL1, value);
+    __ISB();
+}
+
+rt_uint64_t arm_gic_get_system_register_enable_mask(rt_uint64_t index)
+{
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+    rt_uint64_t value;
+
+    GET_GICV3_REG(ICC_SRE_EL1, value);
+    return value;
+}
+
+void arm_gic_set_interface_prior_mask(rt_uint64_t index, rt_uint64_t priority)
+{
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    priority &= 0xff;
+    /* set priority mask */
+    SET_GICV3_REG(ICC_PMR_EL1, priority);
+}
+
+rt_uint64_t arm_gic_get_interface_prior_mask(rt_uint64_t index)
+{
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+    rt_uint64_t priority;
+
+    GET_GICV3_REG(ICC_PMR_EL1, priority);
+    return priority;
+}
+
+void arm_gic_set_binary_point(rt_uint64_t index, rt_uint64_t binary_point)
+{
+    index = index;
+    binary_point &= 0x7;
+
+    SET_GICV3_REG(ICC_BPR1_EL1, binary_point);
+}
+
+rt_uint64_t arm_gic_get_binary_point(rt_uint64_t index)
+{
+    rt_uint64_t binary_point;
+
+    index = index;
+    GET_GICV3_REG(ICC_BPR1_EL1, binary_point);
+    return binary_point;
+}
+
+rt_uint64_t arm_gic_get_irq_status(rt_uint64_t index, int irq)
+{
+    rt_uint64_t pending, active;
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0);
+
+    active = (GIC_DIST_ACTIVE_SET(_gic_table[index].dist_hw_base, irq) >> (irq % 32)) & 0x1;
+    pending = (GIC_DIST_PENDING_SET(_gic_table[index].dist_hw_base, irq) >> (irq % 32)) & 0x1;
+
+    return ((active << 1) | pending);
+}
+
+#ifdef RT_USING_SMP
+void arm_gic_send_affinity_sgi(rt_uint64_t index, int irq, rt_uint64_t cpu_masks[], rt_uint64_t routing_mode)
+{
+    const int cpu_mask_cpu_max_nr = sizeof(cpu_masks[0]) * 8;
+    rt_uint64_t int_id = (irq & 0xf) << 24;
+    rt_uint64_t irm = routing_mode << 40; /* Interrupt Routing Mode */
+
+    if (routing_mode == GICV3_ROUTED_TO_SPEC)
+    {
+        int cpu_id, cpu_mask_bit, i, cpu_masks_nr = RT_CPUS_NR / cpu_mask_cpu_max_nr;
+        rt_uint16_t target_list;
+        rt_uint64_t rs = 0; /* Range Selector */
+        rt_uint64_t affinity_val, next_affinity_val;
+
+        if (cpu_masks_nr * cpu_mask_cpu_max_nr != RT_CPUS_NR)
+        {
+            ++cpu_masks_nr;
+        }
+
+        for (i = cpu_id = 0; i < cpu_masks_nr;)
+        {
+            /* No cpu in this mask */
+            if (cpu_masks[i] == 0)
+            {
+                ++i;
+                cpu_id += cpu_mask_cpu_max_nr;
+                continue;
+            }
+
+            /* Get last cpu affinity value */
+            affinity_val = rt_cpu_mpidr_early[cpu_id] & 0xff00ffff00ULL;
+
+            /* Read 16 cpus information */
+            for (cpu_mask_bit = 0; cpu_mask_bit < 16; ++cpu_mask_bit, ++cpu_id)
+            {
+                /* MPIDR_EL1: aff3[39:32], aff2[23:16], aff1[15:8] */
+                next_affinity_val = rt_cpu_mpidr_early[cpu_id] & 0xff00ffff00ULL;
+
+                /* Affinity value is different, read end */
+                if (affinity_val != next_affinity_val)
+                {
+                    break;
+                }
+            }
+
+            /* Get all valid cpu mask */
+            target_list = (0xffff >> (16 - cpu_mask_bit)) & cpu_masks[i];
+            /* Clear read mask */
+            cpu_masks[i] >>= cpu_mask_bit;
+            /* ICC_SGI1R_EL1: aff3[55:48], aff2[39:32], aff1[23:16] */
+            affinity_val <<= 8;
+
+            __DSB();
+            /* Interrupts routed to the PEs specified by Aff3.Aff2.Aff1.<target list>. */
+            SET_GICV3_REG(ICC_SGI1R_EL1, affinity_val | (rs << 44) | irm | int_id | target_list);
+            __ISB();
+
+            /* Check if reset the range selector */
+            rs = affinity_val != next_affinity_val ? 0 : rs + 1;
+        }
+    }
+    else
+    {
+        __DSB();
+        /* Interrupts routed to all PEs in the system, excluding "self". */
+        SET_GICV3_REG(ICC_SGI1R_EL1, irm | int_id);
+        __ISB();
+    }
+}
+#endif /* RT_USING_SMP */
+
+rt_uint64_t arm_gic_get_high_pending_irq(rt_uint64_t index)
+{
+    rt_uint64_t irq;
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    index = index;
+    GET_GICV3_REG(ICC_HPPIR1_EL1, irq);
+
+    return irq;
+}
+
+rt_uint64_t arm_gic_get_interface_id(rt_uint64_t index)
+{
+    rt_uint64_t ret = 0;
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    if (_gic_table[index].cpu_hw_base != RT_NULL)
+    {
+        ret = GIC_CPU_IIDR(_gic_table[index].cpu_hw_base);
+    }
+
+    return ret;
+}
+
+void arm_gic_set_group(rt_uint64_t index, int irq, rt_uint64_t group)
+{
+    rt_uint64_t igroupr;
+    rt_uint64_t shift;
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+    RT_ASSERT(group <= 1);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0);
+
+    igroupr = GIC_DIST_IGROUP(_gic_table[index].dist_hw_base, irq);
+    shift = (irq % 32);
+    igroupr &= (~(1U << shift));
+    igroupr |= ((group & 0x1U) << shift);
+
+    GIC_DIST_IGROUP(_gic_table[index].dist_hw_base, irq) = igroupr;
+}
+
+rt_uint64_t arm_gic_get_group(rt_uint64_t index, int irq)
+{
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    irq = irq - _gic_table[index].offset;
+    RT_ASSERT(irq >= 0);
+
+    return (GIC_DIST_IGROUP(_gic_table[index].dist_hw_base, irq) >> (irq % 32)) & 0x1UL;
+}
+
+static int arm_gicv3_wait_rwp(rt_uint64_t index, rt_uint64_t irq)
+{
+    rt_uint64_t rwp_bit;
+    rt_uint64_t base;
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    if (irq < 32)
+    {
+        rt_int32_t cpu_id = rt_hw_cpu_id();
+
+        base = _gic_table[index].redist_hw_base[cpu_id];
+        rwp_bit = GICR_CTLR_RWP;
+    }
+    else
+    {
+        base = _gic_table[index].dist_hw_base;
+        rwp_bit = GICD_CTLR_RWP;
+    }
+
+    while (HWREG32(base) & rwp_bit)
+    {
+    }
+
+    return 0;
+}
+
+int arm_gic_dist_init(rt_uint64_t index, rt_uint64_t dist_base, int irq_start)
+{
+    int i;
+    unsigned int gic_type;
+    rt_uint64_t main_cpu_affinity_val;
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    _gic_table[index].dist_hw_base = dist_base;
+    _gic_table[index].offset = irq_start;
+
+
+    /* Find out how many interrupts are supported. */
+    gic_type = GIC_DIST_TYPE(dist_base);
+    _gic_max_irq = ((gic_type & 0x1f) + 1) * 32;
+
+    /*
+     * The GIC only supports up to 1020 interrupt sources.
+     * Limit this to either the architected maximum, or the
+     * platform maximum.
+     */
+    if (_gic_max_irq > 1020)
+    {
+        _gic_max_irq = 1020;
+    }
+    if (_gic_max_irq > ARM_GIC_NR_IRQS) /* the platform maximum interrupts */
+    {
+        _gic_max_irq = ARM_GIC_NR_IRQS;
+    }
+
+    GIC_DIST_CTRL(dist_base) = 0;
+    /* Wait for register write pending */
+    arm_gicv3_wait_rwp(0, 32);
+
+    /* Set all global interrupts to be level triggered, active low. */
+    for (i = 32; i < _gic_max_irq; i += 16)
+    {
+        GIC_DIST_CONFIG(dist_base, i) = 0;
+    }
+
+    arm_gicv3_wait_rwp(0, 32);
+
+#ifdef RT_USING_SMP
+    main_cpu_affinity_val = rt_cpu_mpidr_early[ARM_SPI_BIND_CPU_ID];
+#else
+    __asm__ volatile ("mrs %0, mpidr_el1":"=r"(main_cpu_affinity_val));
+#endif
+
+    /* aff3[39:32], aff2[23:16], aff1[15:8], aff0[7:0] */
+    main_cpu_affinity_val &= 0xff00ffffffULL;
+
+    /* Set all global interrupts to this CPU only. */
+    for (i = 32; i < _gic_max_irq; i++)
+    {
+        GIC_DIST_IROUTER(dist_base, i) = main_cpu_affinity_val | (GICV3_ROUTED_TO_SPEC << 31);
+    }
+
+    arm_gicv3_wait_rwp(0, 32);
+
+    /* Set priority on spi interrupts. */
+    for (i = 32; i < _gic_max_irq; i += 4)
+    {
+        GIC_DIST_PRI(dist_base, i) = 0xa0a0a0a0;
+    }
+
+    arm_gicv3_wait_rwp(0, 32);
+    /* Disable all interrupts. */
+    for (i = 0; i < _gic_max_irq; i += 32)
+    {
+        GIC_DIST_PENDING_CLEAR(dist_base, i) = 0xffffffff;
+        GIC_DIST_ENABLE_CLEAR(dist_base, i) = 0xffffffff;
+    }
+
+    arm_gicv3_wait_rwp(0, 32);
+    /* All interrupts defaults to IGROUP1(IRQ). */
+    for (i = 0; i < _gic_max_irq; i += 32)
+    {
+        GIC_DIST_IGROUP(dist_base, i) = 0xffffffff;
+    }
+
+    arm_gicv3_wait_rwp(0, 32);
+
+    /*
+     * The Distributor control register (GICD_CTLR) must be configured to enable the interrupt groups and to set the routing mode.
+     * Enable Affinity routing (ARE bits) The ARE bits in GICD_CTLR control whether affinity routing is enabled.
+     * If affinity routing is not enabled, GICv3 can be configured for legacy operation.
+     * Whether affinity routing is enabled or not can be controlled separately for Secure and Non-secure state.
+     * Enables GICD_CTLR contains separate enable bits for Group 0, Secure Group 1 and Non-secure Group 1:
+     * GICD_CTLR.EnableGrp1S enables distribution of Secure Group 1 interrupts.
+     * GICD_CTLR.EnableGrp1NS enables distribution of Non-secure Group 1 interrupts.
+     * GICD_CTLR.EnableGrp0 enables distribution of Group 0 interrupts.
+     */
+    GIC_DIST_CTRL(dist_base) = GICD_CTLR_ARE_NS | GICD_CTLR_ENGRP1NS;
+
+    return 0;
+}
+
+int arm_gic_redist_init(rt_uint64_t index, rt_uint64_t redist_base)
+{
+    int i;
+    int cpu_id = rt_hw_cpu_id();
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    redist_base += cpu_id * (2 << 16);
+    _gic_table[index].redist_hw_base[cpu_id] = redist_base;
+
+    /* redistributor enable */
+    GIC_RDIST_WAKER(redist_base) &= ~(1 << 1);
+    while (GIC_RDIST_WAKER(redist_base) & (1 << 2))
+    {
+    }
+
+    /* Disable all sgi and ppi interrupt */
+    GIC_RDISTSGI_ICENABLER0(redist_base) = 0xffffffff;
+    arm_gicv3_wait_rwp(0, 0);
+
+    /* Clear all inetrrupt pending */
+    GIC_RDISTSGI_ICPENDR0(redist_base) = 0xffffffff;
+
+    /* the corresponding interrupt is Group 1 or Non-secure Group 1. */
+    GIC_RDISTSGI_IGROUPR0(redist_base, 0) = 0xffffffff;
+    GIC_RDISTSGI_IGRPMODR0(redist_base, 0) = 0xffffffff;
+
+    /* Configure default priorities for SGI 0:15 and PPI 16:31. */
+    for (i = 0; i < 32; i += 4)
+    {
+        GIC_RDISTSGI_IPRIORITYR(redist_base, i) = 0xa0a0a0a0U;
+    }
+
+    /* Trigger level for PPI interrupts*/
+    GIC_RDISTSGI_ICFGR1(redist_base) = 0;
+    return 0;
+}
+
+int arm_gic_cpu_init(rt_uint64_t index, rt_uint64_t cpu_base)
+{
+    rt_uint64_t value;
+    int cpu_id = rt_hw_cpu_id();
+
+    RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+    _gic_table[index].cpu_hw_base[cpu_id] = cpu_base;
+
+    value = arm_gic_get_system_register_enable_mask(index);
+    value |= (1 << 0);
+    arm_gic_set_system_register_enable_mask(index, value);
+    SET_GICV3_REG(ICC_CTLR_EL1, 0);
+
+    arm_gic_set_interface_prior_mask(index, 0xff);
+
+    /* Enable group1 interrupt */
+    value = 1;
+    SET_GICV3_REG(ICC_IGRPEN1_EL1, value);
+
+    arm_gic_set_binary_point(0, 0);
+
+    /* ICC_BPR0_EL1 determines the preemption group for both Group 0 and Group 1 interrupts. */
+    value  = 1;         /* ICC_BPR0_EL1 determines the preemption group for both Group 0 and Group 1 interrupts.*/
+    value |= 1 << 18;   /* Targeted SGIs with affinity level 0 values of 0 - 255 are supported. */
+    SET_GICV3_REG(ICC_CTLR_EL1, value);
+
+    return 0;
+}
+
+void arm_gic_dump_type(rt_uint64_t index)
+{
+    unsigned int gic_type;
+
+    gic_type = GIC_DIST_TYPE(_gic_table[index].dist_hw_base);
+    rt_kprintf("GICv%d on %p, max IRQs: %d, %s security extension(%08x)\n",
+               (GIC_DIST_ICPIDR2(_gic_table[index].dist_hw_base) >> 4) & 0xf,
+               _gic_table[index].dist_hw_base,
+               _gic_max_irq,
+               gic_type & (1 << 10) ? "has" : "no",
+               gic_type);
+}
+
+void arm_gic_dump(rt_uint64_t index)
+{
+    int i;
+    unsigned int val;
+
+    val = arm_gic_get_high_pending_irq(0);
+    rt_kprintf("--- high pending priority: %d(%08x)\n", val, val);
+
+    rt_kprintf("--- hw mask ---\n");
+    for (i = 0; i < _gic_max_irq / 32; ++i)
+    {
+        rt_kprintf("0x%08x, ", GIC_DIST_ENABLE_SET(_gic_table[index].dist_hw_base, i * 32));
+    }
+
+    rt_kprintf("\b\b\n--- hw pending ---\n");
+    for (i = 0; i < _gic_max_irq / 32; ++i)
+    {
+        rt_kprintf("0x%08x, ", GIC_DIST_PENDING_SET(_gic_table[index].dist_hw_base, i * 32));
+    }
+
+    rt_kprintf("\b\b\n--- hw active ---\n");
+    for (i = 0; i < _gic_max_irq / 32; ++i)
+    {
+        rt_kprintf("0x%08x, ", GIC_DIST_ACTIVE_SET(_gic_table[index].dist_hw_base, i * 32));
+    }
+
+    rt_kprintf("\b\b\n");
+}
+
+long gic_dump(void)
+{
+    arm_gic_dump_type(0);
+    arm_gic_dump(0);
+
+    return 0;
+}
+MSH_CMD_EXPORT(gic_dump, show gic status);
+
+#endif /* defined(BSP_USING_GIC) && defined(BSP_USING_GICV3) */

+ 77 - 0
libcpu/aarch64/common/gicv3.h

@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2013-07-20     Bernard      first version
+ * 2014-04-03     Grissiom     many enhancements
+ * 2018-11-22     Jesven       add rt_hw_ipi_send()
+ *                             add rt_hw_ipi_handler_install()
+ */
+
+#ifndef __GICV3_H__
+#define __GICV3_H__
+
+#include <rtdef.h>
+
+#if defined(BSP_USING_GIC) && defined(BSP_USING_GICV3)
+
+#define GICV3_ROUTED_TO_ALL   1UL
+#define GICV3_ROUTED_TO_SPEC  0UL
+
+int arm_gic_get_active_irq(rt_uint64_t index);
+void arm_gic_ack(rt_uint64_t index, int irq);
+
+void arm_gic_mask(rt_uint64_t index, int irq);
+void arm_gic_umask(rt_uint64_t index, int irq);
+
+rt_uint64_t arm_gic_get_pending_irq(rt_uint64_t index, int irq);
+void arm_gic_set_pending_irq(rt_uint64_t index, int irq);
+void arm_gic_clear_pending_irq(rt_uint64_t index, int irq);
+
+void arm_gic_set_configuration(rt_uint64_t index, int irq, rt_uint32_t config);
+rt_uint64_t arm_gic_get_configuration(rt_uint64_t index, int irq);
+
+void arm_gic_clear_active(rt_uint64_t index, int irq);
+
+void arm_gic_set_cpu(rt_uint64_t index, int irq, unsigned int cpumask);
+rt_uint64_t arm_gic_get_target_cpu(rt_uint64_t index, int irq);
+
+void arm_gic_set_priority(rt_uint64_t index, int irq, rt_uint64_t priority);
+rt_uint64_t arm_gic_get_priority(rt_uint64_t index, int irq);
+
+void arm_gic_set_interface_prior_mask(rt_uint64_t index, rt_uint64_t priority);
+rt_uint64_t arm_gic_get_interface_prior_mask(rt_uint64_t index);
+
+void arm_gic_set_binary_point(rt_uint64_t index, rt_uint64_t binary_point);
+rt_uint64_t arm_gic_get_binary_point(rt_uint64_t index);
+
+rt_uint64_t arm_gic_get_irq_status(rt_uint64_t index, int irq);
+
+#ifdef RT_USING_SMP
+void arm_gic_send_affinity_sgi(rt_uint64_t index, int irq, rt_uint64_t cpu_masks[], rt_uint64_t routing_mode);
+#endif
+
+rt_uint64_t arm_gic_get_high_pending_irq(rt_uint64_t index);
+
+rt_uint64_t arm_gic_get_interface_id(rt_uint64_t index);
+
+void arm_gic_set_group(rt_uint64_t index, int irq, rt_uint64_t group);
+rt_uint64_t arm_gic_get_group(rt_uint64_t index, int irq);
+
+int arm_gic_redist_address_set(rt_uint64_t index, rt_uint64_t redist_addr, int cpu_id);
+int arm_gic_cpu_interface_address_set(rt_uint64_t index, rt_uint64_t interface_addr, int cpu_id);
+
+int arm_gic_dist_init(rt_uint64_t index, rt_uint64_t dist_base, int irq_start);
+int arm_gic_redist_init(rt_uint64_t index, rt_uint64_t redist_base);
+int arm_gic_cpu_init(rt_uint64_t index, rt_uint64_t cpu_base);
+
+void arm_gic_dump_type(rt_uint64_t index);
+void arm_gic_dump(rt_uint64_t index);
+
+#endif /* defined(BSP_USING_GIC) && defined(BSP_USING_GICV3) */
+
+#endif
+

+ 10 - 1
libcpu/aarch64/common/interrupt.c

@@ -13,6 +13,7 @@
 #include <rtthread.h>
 #include "interrupt.h"
 #include "gic.h"
+#include "gicv3.h"
 #include "armv8.h"
 #include "mmu.h"
 #include "cpuport.h"
@@ -52,6 +53,9 @@ void rt_hw_interrupt_init(void)
     /* initialize ARM GIC */
     arm_gic_dist_init(0, platform_get_gic_dist_base(), GIC_IRQ_START);
     arm_gic_cpu_init(0, platform_get_gic_cpu_base());
+#ifdef BSP_USING_GICV3
+    arm_gic_redist_init(0, platform_get_gic_redist_base());
+#endif
 #endif
 }
 
@@ -346,7 +350,11 @@ rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
 void rt_hw_ipi_send(int ipi_vector, unsigned int cpu_mask)
 {
 #ifdef BSP_USING_GIC
+#ifdef BSP_USING_GICV2
     arm_gic_send_sgi(0, ipi_vector, cpu_mask, 0);
+#else
+    arm_gic_send_affinity_sgi(0, ipi_vector, (rt_uint64_t *)&cpu_mask, GICV3_ROUTED_TO_SPEC);
+#endif
 #else
     int i;
 
@@ -359,8 +367,9 @@ void rt_hw_ipi_send(int ipi_vector, unsigned int cpu_mask)
             IPI_MAILBOX_SET(i) = 1 << ipi_vector;
         }
     }
-#endif
+
     __DSB();
+#endif
 }
 
 void rt_hw_ipi_handler_install(int ipi_vector, rt_isr_handler_t ipi_isr_handler)

+ 11 - 3
libcpu/aarch64/common/psci.c

@@ -29,11 +29,19 @@ static psci_call_handle psci_call = psci_smc_call;
 static uint64_t shutdown_args[3] = {0, 0, 0};
 static uint64_t reboot_args[3] = {0, 0, 0};
 
-void arm_psci_init(uint64_t *platform_shutdown_args, uint64_t *platform_reboot_args)
+void arm_psci_init(uint64_t method, uint64_t *platform_shutdown_args, uint64_t *platform_reboot_args)
 {
-    if (rt_hw_get_current_el() < 2)
+    switch (method)
     {
-        psci_call = psci_hvc_call;
+    case PSCI_METHOD_SMC:
+        psci_call = psci_smc_call;
+        break;
+    case PSCI_METHOD_HVC:
+        if (rt_hw_get_current_el() < 2)
+        {
+            psci_call = psci_hvc_call;
+        }
+        break;
     }
 
     if (platform_shutdown_args != RT_NULL)

+ 4 - 1
libcpu/aarch64/common/psci.h

@@ -18,6 +18,9 @@
  */
 #define PSCI_VER_0_2                        0x00000002
 
+#define PSCI_METHOD_SMC                     3
+#define PSCI_METHOD_HVC                     2
+
 /* PSCI 0.2 interface */
 #define PSCI_0_2_FN_BASE                    0x84000000
 #define PSCI_0_2_FN(n)                      (PSCI_0_2_FN_BASE + (n))
@@ -114,7 +117,7 @@
 #define PSCI_RET_DISABLED                   (-8)
 #define PSCI_RET_INVALID_ADDRESS            (-9)
 
-void arm_psci_init(uint64_t *platform_shutdown_args, uint64_t *platform_reboot_args);
+void arm_psci_init(uint64_t method, uint64_t *platform_shutdown_args, uint64_t *platform_reboot_args);
 
 uint32_t arm_psci_get_version();
 uint32_t arm_psci_get_affinity_info(uint64_t target_affinity, uint64_t lowest_affinity_level);

+ 27 - 14
libcpu/aarch64/cortex-a/entry_point.S

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2020, RT-Thread Development Team
+ * Copyright (c) 2006-2022, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -11,19 +11,28 @@
  */
 
 #include "rtconfig.h"
-.section ".text.entrypoint","ax"
 
 #define SECONDARY_STACK_SIZE 4096
 
+.section ".text.entrypoint","ax"
+
 .globl _start
 .globl secondary_cpu_start
 _start:
+#ifdef RT_USING_SMP
     mrs     x1, mpidr_el1
-    and     x1, x1, #0xff
-    cbnz    x1, cpu_idle            /* If cpu id > 0, stop slave cores */
+    adr     x4, .boot_cpu_mpidr
+    str     x1, [x4]
+    dsb     sy
+#endif
+
+    bl      __asm_flush_dcache_all  /* The kernel and data must flush to DDR */
 
 secondary_cpu_start:
 #ifdef RT_USING_SMP
+    adr     x4, .boot_cpu_mpidr
+    ldr     x4, [x4]
+    dsb     sy
     /* Read cpu mpidr_el1 */
     mrs     x1, mpidr_el1
 
@@ -34,6 +43,7 @@ secondary_cpu_start:
 cpu_id_confirm:
     add     x2, x2, #1              /* Next cpu id inc */
     ldr     x3, [x0], #8
+    dsb     sy
     cmp     x3, #0
     beq     cpu_idle                /* Mean that `rt_cpu_mpidr_early' table is end */
     cmp     x3, x1
@@ -42,7 +52,8 @@ cpu_id_confirm:
     /* Get cpu id success */
     sub     x0, x2, #1
     msr     tpidr_el1, x0           /* Save cpu id global */
-    cbz     x0, cpu_setup           /* Only go to cpu_setup when cpu id = 0 */
+    cmp     x3, x4                  /* If it is boot cpu */
+    beq     boot_cpu_setup
 
     /* Set current cpu's stack top */
     sub     x0, x0, #1
@@ -53,14 +64,9 @@ cpu_id_confirm:
     b       cpu_check_el
 #else
     msr     tpidr_el1, xzr
-    b       cpu_setup
 #endif /* RT_USING_SMP */
 
-cpu_idle:
-    wfe
-    b       cpu_idle
-
-cpu_setup:
+boot_cpu_setup:
     ldr     x1, =_start
 
 cpu_check_el:
@@ -75,7 +81,7 @@ cpu_check_el:
     mov     x2, #(1 << 0)           /* EL0 and EL1 are in Non-Secure state */
     orr     x2, x2, #(1 << 4)       /* RES1 */
     orr     x2, x2, #(1 << 5)       /* RES1 */
-    orr     x2, x2, #(1 << 7)       /* SMC instructions are undefined at EL1 and above */
+    bic     x2, x2, #(1 << 7)       /* SMC instructions are enabled at EL1 and above */
     orr     x2, x2, #(1 << 8)       /* HVC instructions are enabled at EL1 and above */
     orr     x2, x2, #(1 << 10)      /* The next lower level is AArch64 */
     msr     scr_el3, x2
@@ -91,7 +97,7 @@ cpu_check_el:
     eret
 
 cpu_not_in_el3:                     /* Running at EL2 or EL1 */
-    cmp     x0, #4                  /* EL1 = 0100  */
+    cmp     x0, #4                  /* EL1 = 0100 */
     beq     cpu_in_el1
 
 cpu_in_el2:
@@ -159,9 +165,16 @@ clean_bss_check:
 
 jump_to_entry:
     b       rtthread_startup
-    b       cpu_idle                /* For failsafe, halt this core too */
+
+cpu_idle:
+    wfe
+    b       cpu_idle
 
 #ifdef RT_USING_SMP
+.align 3
+.boot_cpu_mpidr:
+    .quad 0x0
+
 .align 12
 .secondary_cpu_stack:
 .space (SECONDARY_STACK_SIZE * (RT_CPUS_NR - 1))