summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGUI <[email protected]>2022-03-29 11:08:25 +0800
committerGitHub <[email protected]>2022-03-29 11:08:25 +0800
commitf587a55bc2006f4316383425d518b734e42bb4a2 (patch)
tree155cc0f274c4cb79d2ed8761e25532abbcabfad2
parentd23493d05db47bcf066894dd1e1cb43b77a76d54 (diff)
[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
-rw-r--r--.github/workflows/action.yml1
-rw-r--r--bsp/qemu-virt64-aarch64/.config62
-rw-r--r--bsp/qemu-virt64-aarch64/README.md10
-rw-r--r--bsp/qemu-virt64-aarch64/README_zh.md6
-rw-r--r--bsp/qemu-virt64-aarch64/driver/Kconfig18
-rw-r--r--bsp/qemu-virt64-aarch64/driver/board.c14
-rw-r--r--bsp/qemu-virt64-aarch64/driver/board.h58
-rw-r--r--bsp/qemu-virt64-aarch64/driver/drv_uart.c4
-rw-r--r--bsp/qemu-virt64-aarch64/driver/drv_virtio.c62
-rw-r--r--bsp/qemu-virt64-aarch64/driver/drv_virtio.h16
-rw-r--r--bsp/qemu-virt64-aarch64/driver/virt.h81
-rw-r--r--bsp/qemu-virt64-aarch64/driver/virtio/drv_virtio_blk.c405
-rw-r--r--bsp/qemu-virt64-aarch64/driver/virtio/drv_virtio_blk.h85
-rw-r--r--bsp/qemu-virt64-aarch64/driver/virtio/virtio.c274
-rw-r--r--bsp/qemu-virt64-aarch64/driver/virtio/virtio.h132
-rw-r--r--bsp/qemu-virt64-aarch64/driver/virtio/virtio_blk.c216
-rw-r--r--bsp/qemu-virt64-aarch64/driver/virtio/virtio_blk.h61
-rw-r--r--bsp/qemu-virt64-aarch64/driver/virtio/virtio_mmio.c61
-rw-r--r--bsp/qemu-virt64-aarch64/driver/virtio/virtio_mmio.h104
-rw-r--r--bsp/qemu-virt64-aarch64/driver/virtio/virtio_queue.h94
-rw-r--r--bsp/qemu-virt64-aarch64/qemu.bat5
-rw-r--r--bsp/qemu-virt64-aarch64/qemu.sh5
-rw-r--r--bsp/qemu-virt64-aarch64/rtconfig.h35
-rw-r--r--bsp/raspberry-pi/raspi4-64/.config73
-rw-r--r--bsp/raspberry-pi/raspi4-64/driver/Kconfig4
-rw-r--r--bsp/raspberry-pi/raspi4-64/driver/drv_wdt.c44
-rw-r--r--bsp/raspberry-pi/raspi4-64/driver/mbox.c18
-rw-r--r--bsp/raspberry-pi/raspi4-64/driver/mbox.h1
-rw-r--r--bsp/raspberry-pi/raspi4-64/rtconfig.h32
-rw-r--r--bsp/rockchip/rk3568/.config653
-rw-r--r--bsp/rockchip/rk3568/Kconfig29
-rw-r--r--bsp/rockchip/rk3568/README.md55
-rw-r--r--bsp/rockchip/rk3568/README_zh.md56
-rw-r--r--bsp/rockchip/rk3568/SConscript14
-rw-r--r--bsp/rockchip/rk3568/SConstruct29
-rw-r--r--bsp/rockchip/rk3568/applications/SConscript9
-rw-r--r--bsp/rockchip/rk3568/applications/main.c18
-rw-r--r--bsp/rockchip/rk3568/driver/Kconfig58
-rw-r--r--bsp/rockchip/rk3568/driver/SConscript19
-rw-r--r--bsp/rockchip/rk3568/driver/board.c124
-rw-r--r--bsp/rockchip/rk3568/driver/board.h24
-rw-r--r--bsp/rockchip/rk3568/driver/drv_uart.c358
-rw-r--r--bsp/rockchip/rk3568/driver/drv_uart.h16
-rw-r--r--bsp/rockchip/rk3568/driver/rk3568.h116
-rw-r--r--bsp/rockchip/rk3568/link.lds143
-rw-r--r--bsp/rockchip/rk3568/rtconfig.h188
-rw-r--r--bsp/rockchip/rk3568/rtconfig.py53
-rw-r--r--include/rthw.h3
-rw-r--r--libcpu/aarch64/common/SConscript4
-rw-r--r--libcpu/aarch64/common/gic.c68
-rw-r--r--libcpu/aarch64/common/gic.h10
-rw-r--r--libcpu/aarch64/common/gicv3.c849
-rw-r--r--libcpu/aarch64/common/gicv3.h77
-rw-r--r--libcpu/aarch64/common/interrupt.c11
-rw-r--r--libcpu/aarch64/common/psci.c14
-rw-r--r--libcpu/aarch64/common/psci.h5
-rw-r--r--libcpu/aarch64/cortex-a/entry_point.S41
57 files changed, 4106 insertions, 919 deletions
diff --git a/.github/workflows/action.yml b/.github/workflows/action.yml
index a1f6d6f51c..5b6fed8a79 100644
--- a/.github/workflows/action.yml
+++ b/.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
diff --git a/bsp/qemu-virt64-aarch64/.config b/bsp/qemu-virt64-aarch64/.config
index 2bd46d496d..76f4b53481 100644
--- a/bsp/qemu-virt64-aarch64/.config
+++ b/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,37 +216,17 @@ 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
#
# CONFIG_RT_USING_RYM is not set
@@ -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
@@ -638,6 +615,10 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
#
#
+# project laboratory
+#
+
+#
# samples: kernel and components samples
#
# CONFIG_PKG_USING_KERNEL_SAMPLES is not set
@@ -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
diff --git a/bsp/qemu-virt64-aarch64/README.md b/bsp/qemu-virt64-aarch64/README.md
index 32616794a5..b0999e61d8 100644
--- a/bsp/qemu-virt64-aarch64/README.md
+++ b/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 | \ No newline at end of file
+| VIRTIO BLK | Support | - | \ No newline at end of file
diff --git a/bsp/qemu-virt64-aarch64/README_zh.md b/bsp/qemu-virt64-aarch64/README_zh.md
index f9b38c0108..e723e83ac1 100644
--- a/bsp/qemu-virt64-aarch64/README_zh.md
+++ b/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 | \ No newline at end of file
+| VIRTIO BLK | 支持 | - | \ No newline at end of file
diff --git a/bsp/qemu-virt64-aarch64/driver/Kconfig b/bsp/qemu-virt64-aarch64/driver/Kconfig
index acf9f082ea..5d617eb42a 100644
--- a/bsp/qemu-virt64-aarch64/driver/Kconfig
+++ b/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
diff --git a/bsp/qemu-virt64-aarch64/driver/board.c b/bsp/qemu-virt64-aarch64/driver/board.c
index 12e2a85269..7547bd75aa 100644
--- a/bsp/qemu-virt64-aarch64/driver/board.c
+++ b/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);
diff --git a/bsp/qemu-virt64-aarch64/driver/board.h b/bsp/qemu-virt64-aarch64/driver/board.h
index 0bf37a575c..63d0d69f67 100644
--- a/bsp/qemu-virt64-aarch64/driver/board.h
+++ b/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);
diff --git a/bsp/qemu-virt64-aarch64/driver/drv_uart.c b/bsp/qemu-virt64-aarch64/driver/drv_uart.c
index 0d6cdaf15b..ac2a9f11ab 100644
--- a/bsp/qemu-virt64-aarch64/driver/drv_uart.c
+++ b/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;
diff --git a/bsp/qemu-virt64-aarch64/driver/drv_virtio.c b/bsp/qemu-virt64-aarch64/driver/drv_virtio.c
new file mode 100644
index 0000000000..33f91ab725
--- /dev/null
+++ b/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);
diff --git a/bsp/qemu-virt64-aarch64/driver/drv_virtio.h b/bsp/qemu-virt64-aarch64/driver/drv_virtio.h
new file mode 100644
index 0000000000..954338a386
--- /dev/null
+++ b/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__ */
diff --git a/bsp/qemu-virt64-aarch64/driver/virt.h b/bsp/qemu-virt64-aarch64/driver/virt.h
new file mode 100644
index 0000000000..ed90db899d
--- /dev/null
+++ b/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
diff --git a/bsp/qemu-virt64-aarch64/driver/virtio/drv_virtio_blk.c b/bsp/qemu-virt64-aarch64/driver/virtio/drv_virtio_blk.c
deleted file mode 100644
index 02e6b7986f..0000000000
--- a/bsp/qemu-virt64-aarch64/driver/virtio/drv_virtio_blk.c
+++ /dev/null
@@ -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 */
diff --git a/bsp/qemu-virt64-aarch64/driver/virtio/drv_virtio_blk.h b/bsp/qemu-virt64-aarch64/driver/virtio/drv_virtio_blk.h
deleted file mode 100644
index 3ab23f7afe..0000000000
--- a/bsp/qemu-virt64-aarch64/driver/virtio/drv_virtio_blk.h
+++ /dev/null
@@ -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__ */
diff --git a/bsp/qemu-virt64-aarch64/driver/virtio/virtio.c b/bsp/qemu-virt64-aarch64/driver/virtio/virtio.c
new file mode 100644
index 0000000000..faf05eb297
--- /dev/null
+++ b/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;
+}
diff --git a/bsp/qemu-virt64-aarch64/driver/virtio/virtio.h b/bsp/qemu-virt64-aarch64/driver/virtio/virtio.h
index e87b68cd88..8a1dffa8c7 100644
--- a/bsp/qemu-virt64-aarch64/driver/virtio/virtio.h
+++ b/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__ */
diff --git a/bsp/qemu-virt64-aarch64/driver/virtio/virtio_blk.c b/bsp/qemu-virt64-aarch64/driver/virtio/virtio_blk.c
new file mode 100644
index 0000000000..aac6ff7511
--- /dev/null
+++ b/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 */
diff --git a/bsp/qemu-virt64-aarch64/driver/virtio/virtio_blk.h b/bsp/qemu-virt64-aarch64/driver/virtio/virtio_blk.h
new file mode 100644
index 0000000000..dfc08a1c55
--- /dev/null
+++ b/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__ */
diff --git a/bsp/qemu-virt64-aarch64/driver/virtio/virtio_mmio.c b/bsp/qemu-virt64-aarch64/driver/virtio/virtio_mmio.c
deleted file mode 100644
index 72328bf61c..0000000000
--- a/bsp/qemu-virt64-aarch64/driver/virtio/virtio_mmio.c
+++ /dev/null
@@ -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));
-}
diff --git a/bsp/qemu-virt64-aarch64/driver/virtio/virtio_mmio.h b/bsp/qemu-virt64-aarch64/driver/virtio/virtio_mmio.h
index fd7611aa85..4082aa6682 100644
--- a/bsp/qemu-virt64-aarch64/driver/virtio/virtio_mmio.h
+++ b/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)
+struct virtio_mmio_config
{
- 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)
-{
- *((volatile uint32_t*) (((uintptr_t) base) + offset)) = val;
-}
-
-void virtio_mmio_print_configs(uint32_t *device_base);
+ 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 */
+#endif /* __VIRTIO_MMIO_H__ */
diff --git a/bsp/qemu-virt64-aarch64/driver/virtio/virtio_queue.h b/bsp/qemu-virt64-aarch64/driver/virtio/virtio_queue.h
new file mode 100644
index 0000000000..ba8d5d4268
--- /dev/null
+++ b/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__ */
diff --git a/bsp/qemu-virt64-aarch64/qemu.bat b/bsp/qemu-virt64-aarch64/qemu.bat
index 708bd271c5..0e078cfe15 100644
--- a/bsp/qemu-virt64-aarch64/qemu.bat
+++ b/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
diff --git a/bsp/qemu-virt64-aarch64/qemu.sh b/bsp/qemu-virt64-aarch64/qemu.sh
index 677d640b01..34886682ee 100644
--- a/bsp/qemu-virt64-aarch64/qemu.sh
+++ b/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
diff --git a/bsp/qemu-virt64-aarch64/rtconfig.h b/bsp/qemu-virt64-aarch64/rtconfig.h
index 2aefe60171..51cb859f2a 100644
--- a/bsp/qemu-virt64-aarch64/rtconfig.h
+++ b/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
diff --git a/bsp/raspberry-pi/raspi4-64/.config b/bsp/raspberry-pi/raspi4-64/.config
index a2c217c07a..d5b8d6e0a5 100644
--- a/bsp/raspberry-pi/raspi4-64/.config
+++ b/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
@@ -729,6 +695,10 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y
#
#
+# project laboratory
+#
+
+#
# samples: kernel and components samples
#
# CONFIG_PKG_USING_KERNEL_SAMPLES is not set
@@ -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
diff --git a/bsp/raspberry-pi/raspi4-64/driver/Kconfig b/bsp/raspberry-pi/raspi4-64/driver/Kconfig
index 1eaf56faca..ec2a36d289 100644
--- a/bsp/raspberry-pi/raspi4-64/driver/Kconfig
+++ b/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
diff --git a/bsp/raspberry-pi/raspi4-64/driver/drv_wdt.c b/bsp/raspberry-pi/raspi4-64/driver/drv_wdt.c
index 0d2a854ab8..ac7d1addb8 100644
--- a/bsp/raspberry-pi/raspi4-64/driver/drv_wdt.c
+++ b/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;
diff --git a/bsp/raspberry-pi/raspi4-64/driver/mbox.c b/bsp/raspberry-pi/raspi4-64/driver/mbox.c
index 6d1c276d78..c497c6365f 100644
--- a/bsp/raspberry-pi/raspi4-64/driver/mbox.c
+++ b/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
diff --git a/bsp/raspberry-pi/raspi4-64/driver/mbox.h b/bsp/raspberry-pi/raspi4-64/driver/mbox.h
index c13170afba..c3c73c339f 100644
--- a/bsp/raspberry-pi/raspi4-64/driver/mbox.h
+++ b/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);
diff --git a/bsp/raspberry-pi/raspi4-64/rtconfig.h b/bsp/raspberry-pi/raspi4-64/rtconfig.h
index 3091cbfa2e..9d7fa35137 100644
--- a/bsp/raspberry-pi/raspi4-64/rtconfig.h
+++ b/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
diff --git a/bsp/rockchip/rk3568/.config b/bsp/rockchip/rk3568/.config
new file mode 100644
index 0000000000..cdd09053ce
--- /dev/null
+++ b/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
diff --git a/bsp/rockchip/rk3568/Kconfig b/bsp/rockchip/rk3568/Kconfig
new file mode 100644
index 0000000000..b784130e0a
--- /dev/null
+++ b/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"
diff --git a/bsp/rockchip/rk3568/README.md b/bsp/rockchip/rk3568/README.md
new file mode 100644
index 0000000000..6522e5a738
--- /dev/null
+++ b/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 |
diff --git a/bsp/rockchip/rk3568/README_zh.md b/bsp/rockchip/rk3568/README_zh.md
new file mode 100644
index 0000000000..e4ed2bf4a6
--- /dev/null
+++ b/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 |
diff --git a/bsp/rockchip/rk3568/SConscript b/bsp/rockchip/rk3568/SConscript
new file mode 100644
index 0000000000..744d8d7821
--- /dev/null
+++ b/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')
diff --git a/bsp/rockchip/rk3568/SConstruct b/bsp/rockchip/rk3568/SConstruct
new file mode 100644
index 0000000000..ec6fe0187f
--- /dev/null
+++ b/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)
diff --git a/bsp/rockchip/rk3568/applications/SConscript b/bsp/rockchip/rk3568/applications/SConscript
new file mode 100644
index 0000000000..c583d3016e
--- /dev/null
+++ b/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')
diff --git a/bsp/rockchip/rk3568/applications/main.c b/bsp/rockchip/rk3568/applications/main.c
new file mode 100644
index 0000000000..780e49d091
--- /dev/null
+++ b/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;
+}
diff --git a/bsp/rockchip/rk3568/driver/Kconfig b/bsp/rockchip/rk3568/driver/Kconfig
new file mode 100644
index 0000000000..55041eba5b
--- /dev/null
+++ b/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
diff --git a/bsp/rockchip/rk3568/driver/SConscript b/bsp/rockchip/rk3568/driver/SConscript
new file mode 100644
index 0000000000..17f80c100b
--- /dev/null
+++ b/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')
diff --git a/bsp/rockchip/rk3568/driver/board.c b/bsp/rockchip/rk3568/driver/board.c
new file mode 100644
index 0000000000..42e112745d
--- /dev/null
+++ b/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
diff --git a/bsp/rockchip/rk3568/driver/board.h b/bsp/rockchip/rk3568/driver/board.h
new file mode 100644
index 0000000000..d2900cf405
--- /dev/null
+++ b/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__ */
diff --git a/bsp/rockchip/rk3568/driver/drv_uart.c b/bsp/rockchip/rk3568/driver/drv_uart.c
new file mode 100644
index 0000000000..477c2f077d
--- /dev/null
+++ b/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;
+}
diff --git a/bsp/rockchip/rk3568/driver/drv_uart.h b/bsp/rockchip/rk3568/driver/drv_uart.h
new file mode 100644
index 0000000000..acc6ac0ea4
--- /dev/null
+++ b/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__ */
diff --git a/bsp/rockchip/rk3568/driver/rk3568.h b/bsp/rockchip/rk3568/driver/rk3568.h
new file mode 100644
index 0000000000..f248463323
--- /dev/null
+++ b/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__ */
diff --git a/bsp/rockchip/rk3568/link.lds b/bsp/rockchip/rk3568/link.lds
new file mode 100644
index 0000000000..406e8c4a6c
--- /dev/null
+++ b/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);
diff --git a/bsp/rockchip/rk3568/rtconfig.h b/bsp/rockchip/rk3568/rtconfig.h
new file mode 100644
index 0000000000..5b3909cd14
--- /dev/null
+++ b/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
diff --git a/bsp/rockchip/rk3568/rtconfig.py b/bsp/rockchip/rk3568/rtconfig.py
new file mode 100644
index 0000000000..aad7072dbc
--- /dev/null
+++ b/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'
diff --git a/include/rthw.h b/include/rthw.h
index 5672a8f992..bf497b4c3f 100644
--- a/include/rthw.h
+++ b/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
diff --git a/libcpu/aarch64/common/SConscript b/libcpu/aarch64/common/SConscript
index 915b9d29aa..72fb8e26c3 100644
--- a/libcpu/aarch64/common/SConscript
+++ b/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)
diff --git a/libcpu/aarch64/common/gic.c b/libcpu/aarch64/common/gic.c
index 7a2c368d23..95a710c480 100644
--- a/libcpu/aarch64/common/gic.c
+++ b/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) */
diff --git a/libcpu/aarch64/common/gic.h b/libcpu/aarch64/common/gic.h
index 54ab2bda18..7ea0d6d3af 100644
--- a/libcpu/aarch64/common/gic.h
+++ b/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
diff --git a/libcpu/aarch64/common/gicv3.c b/libcpu/aarch64/common/gicv3.c
new file mode 100644
index 0000000000..67010f1d57
--- /dev/null
+++ b/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) */
diff --git a/libcpu/aarch64/common/gicv3.h b/libcpu/aarch64/common/gicv3.h
new file mode 100644
index 0000000000..0cb6bda03a
--- /dev/null
+++ b/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
+
diff --git a/libcpu/aarch64/common/interrupt.c b/libcpu/aarch64/common/interrupt.c
index f31003b2c0..c5db2d46af 100644
--- a/libcpu/aarch64/common/interrupt.c
+++ b/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,8 +350,12 @@ 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;
__DSB();
@@ -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)
diff --git a/libcpu/aarch64/common/psci.c b/libcpu/aarch64/common/psci.c
index 400db977ee..65e84ebf0a 100644
--- a/libcpu/aarch64/common/psci.c
+++ b/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)
diff --git a/libcpu/aarch64/common/psci.h b/libcpu/aarch64/common/psci.h
index e8b2e3129d..999489a801 100644
--- a/libcpu/aarch64/common/psci.h
+++ b/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);
diff --git a/libcpu/aarch64/cortex-a/entry_point.S b/libcpu/aarch64/cortex-a/entry_point.S
index 5bf2b8a3a6..c605a41631 100644
--- a/libcpu/aarch64/cortex-a/entry_point.S
+++ b/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))