summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bsp/ft2004/.config726
-rw-r--r--bsp/ft2004/Kconfig30
-rw-r--r--bsp/ft2004/README.md236
-rw-r--r--bsp/ft2004/SConscript14
-rw-r--r--bsp/ft2004/SConstruct32
-rw-r--r--bsp/ft2004/applications/SConscript11
-rw-r--r--bsp/ft2004/applications/main.c77
-rw-r--r--bsp/ft2004/drivers/SConscript14
-rw-r--r--bsp/ft2004/drivers/board.c155
-rw-r--r--bsp/ft2004/drivers/board.h29
-rw-r--r--bsp/ft2004/drivers/drv_can.c270
-rw-r--r--bsp/ft2004/drivers/drv_can.h38
-rw-r--r--bsp/ft2004/drivers/drv_eth.c691
-rw-r--r--bsp/ft2004/drivers/drv_eth.h25
-rw-r--r--bsp/ft2004/drivers/drv_log.h27
-rw-r--r--bsp/ft2004/drivers/drv_qspi.c424
-rw-r--r--bsp/ft2004/drivers/drv_qspi.h29
-rw-r--r--bsp/ft2004/drivers/drv_qspi_flash.c39
-rw-r--r--bsp/ft2004/drivers/drv_sdcard.c154
-rw-r--r--bsp/ft2004/drivers/drv_sdctrl.c659
-rw-r--r--bsp/ft2004/drivers/drv_sdctrl.h47
-rw-r--r--bsp/ft2004/drivers/drv_spi.c449
-rw-r--r--bsp/ft2004/drivers/drv_spi.h29
-rw-r--r--bsp/ft2004/drivers/drv_spi_flash.c43
-rw-r--r--bsp/ft2004/drivers/drv_usart.c192
-rw-r--r--bsp/ft2004/drivers/drv_usart.h25
-rw-r--r--bsp/ft2004/drivers/ft2004.c88
-rw-r--r--bsp/ft2004/drivers/ft2004.h25
-rw-r--r--bsp/ft2004/drivers/ft2004_cpu.S44
-rw-r--r--bsp/ft2004/drivers/secondary_cpu.c86
-rw-r--r--bsp/ft2004/drivers/serial.h20
-rw-r--r--bsp/ft2004/figures/onchipPeripheral.pngbin0 -> 22293 bytes
-rw-r--r--bsp/ft2004/figures/rttPing通过界面.pngbin0 -> 10980 bytes
-rw-r--r--bsp/ft2004/figures/rttsd调试.pngbin0 -> 22374 bytes
-rw-r--r--bsp/ft2004/figures/启动演示图.pngbin0 -> 24488 bytes
-rw-r--r--bsp/ft2004/ft_aarch32.lds110
-rw-r--r--bsp/ft2004/libraries/.gitignore4
-rw-r--r--bsp/ft2004/libraries/Kconfig146
-rw-r--r--bsp/ft2004/libraries/LICENSE202
-rw-r--r--bsp/ft2004/libraries/SConscript129
-rw-r--r--bsp/ft2004/libraries/bsp/ft_can/ft_can.c299
-rw-r--r--bsp/ft2004/libraries/bsp/ft_can/ft_can.h142
-rw-r--r--bsp/ft2004/libraries/bsp/ft_can/ft_can_calc.c269
-rw-r--r--bsp/ft2004/libraries/bsp/ft_can/ft_can_g.c39
-rw-r--r--bsp/ft2004/libraries/bsp/ft_can/ft_can_hw.c55
-rw-r--r--bsp/ft2004/libraries/bsp/ft_can/ft_can_hw.h161
-rw-r--r--bsp/ft2004/libraries/bsp/ft_can/ft_can_intr.c118
-rw-r--r--bsp/ft2004/libraries/bsp/ft_can/ft_can_sinit.c40
-rw-r--r--bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac.c109
-rw-r--r--bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac.h319
-rw-r--r--bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_desc.c357
-rw-r--r--bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_desc.h20
-rw-r--r--bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_g.c47
-rw-r--r--bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_hw.c566
-rw-r--r--bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_hw.h577
-rw-r--r--bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_intr.c174
-rw-r--r--bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_sinit.c34
-rw-r--r--bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio.c107
-rw-r--r--bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio.h73
-rw-r--r--bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio_hw.h92
-rw-r--r--bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c.c510
-rw-r--r--bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c.h197
-rw-r--r--bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_g.c13
-rw-r--r--bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_hw.h321
-rw-r--r--bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_irq.c182
-rw-r--r--bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_selftest.c20
-rw-r--r--bsp/ft2004/libraries/bsp/ft_qspi/ft_qspi.c585
-rw-r--r--bsp/ft2004/libraries/bsp/ft_qspi/ft_qspi.h184
-rw-r--r--bsp/ft2004/libraries/bsp/ft_qspi/qspi_g.c26
-rw-r--r--bsp/ft2004/libraries/bsp/ft_qspi/qspi_hw.c25
-rw-r--r--bsp/ft2004/libraries/bsp/ft_qspi/qspi_hw.h199
-rw-r--r--bsp/ft2004/libraries/bsp/ft_qspi/qspi_sinit.c34
-rw-r--r--bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl.c552
-rw-r--r--bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl.h235
-rw-r--r--bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_g.c31
-rw-r--r--bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_hw.c41
-rw-r--r--bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_hw.h210
-rw-r--r--bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_intr.c110
-rw-r--r--bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_option.c61
-rw-r--r--bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_sinit.c33
-rw-r--r--bsp/ft2004/libraries/bsp/ft_spi/ft_spi.c192
-rw-r--r--bsp/ft2004/libraries/bsp/ft_spi/ft_spi.h95
-rw-r--r--bsp/ft2004/libraries/bsp/ft_spi/ft_spi_hw.h330
-rw-r--r--bsp/ft2004/libraries/bsp/ft_spi/ft_spi_irq.c13
-rw-r--r--bsp/ft2004/libraries/bsp/ft_uart/ft_uart.c329
-rw-r--r--bsp/ft2004/libraries/bsp/ft_uart/ft_uart.h120
-rw-r--r--bsp/ft2004/libraries/bsp/ft_uart/ft_uart_g.c34
-rw-r--r--bsp/ft2004/libraries/bsp/ft_uart/ft_uart_hw.c46
-rw-r--r--bsp/ft2004/libraries/bsp/ft_uart/ft_uart_hw.h221
-rw-r--r--bsp/ft2004/libraries/bsp/ft_uart/ft_uart_intr.c196
-rw-r--r--bsp/ft2004/libraries/bsp/ft_uart/ft_uart_options.c102
-rw-r--r--bsp/ft2004/libraries/bsp/ft_uart/ft_uart_selftest.c13
-rw-r--r--bsp/ft2004/libraries/bsp/ft_uart/ft_uart_sinit.c41
-rw-r--r--bsp/ft2004/libraries/bsp/include/ft_parameters.h180
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/ft_assert.c43
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/ft_assert.h154
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/ft_cache.c86
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/ft_cache.h32
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/ft_cpu.c145
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/ft_cpu.h26
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/ft_debug.c67
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/ft_debug.h78
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/ft_error_code.h72
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/ft_generic_timer.c327
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/ft_generic_timer.h57
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/ft_io.h164
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/ft_list.h23
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/ft_math.c19
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/ft_math.h24
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/ft_mux.c90
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/ft_mux.h75
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/ft_printf.c96
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/ft_printf.h29
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/ft_psci.c78
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/ft_psci.h31
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/ft_smc.S36
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/ft_smc.h43
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/ft_status.h82
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/ft_trace.c57
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/ft_trace.h52
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/ft_types.h75
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/inbyte.c21
-rw-r--r--bsp/ft2004/libraries/bsp/standlone/outbyte.c21
-rw-r--r--bsp/ft2004/libraries/cpu/ft_aarch32_asm.h319
-rw-r--r--bsp/ft2004/libraries/doc/ChangeLog.md90
-rw-r--r--bsp/ft2004/libraries/doc/figures/v0.3.0_add.pngbin0 -> 297513 bytes
-rw-r--r--bsp/ft2004/libraries/include/asmArm.h37
-rw-r--r--bsp/ft2004/libraries/readme.md69
-rw-r--r--bsp/ft2004/make.sh16
-rw-r--r--bsp/ft2004/rtconfig.h286
-rw-r--r--bsp/ft2004/rtconfig.py59
131 files changed, 17377 insertions, 0 deletions
diff --git a/bsp/ft2004/.config b/bsp/ft2004/.config
new file mode 100644
index 0000000000..1a27a6c8b4
--- /dev/null
+++ b/bsp/ft2004/.config
@@ -0,0 +1,726 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# RT-Thread Project Configuration
+#
+
+#
+# RT-Thread Kernel
+#
+CONFIG_RT_NAME_MAX=32
+# CONFIG_RT_USING_ARCH_DATA_TYPE is not set
+CONFIG_RT_USING_SMP=y
+CONFIG_RT_CPUS_NR=4
+CONFIG_RT_ALIGN_SIZE=128
+# 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_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=512
+
+#
+# kservice optimization
+#
+# CONFIG_RT_KSERVICE_USING_STDLIB is not set
+# CONFIG_RT_KSERVICE_USING_TINY_SIZE 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 is not set
+CONFIG_RT_USING_MEMHEAP=y
+# CONFIG_RT_USING_NOHEAP is not set
+# CONFIG_RT_USING_SMALL_MEM is not set
+CONFIG_RT_USING_SLAB=y
+# CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set
+# CONFIG_RT_USING_USERHEAP is not set
+# CONFIG_RT_USING_MEMTRACE is not set
+CONFIG_RT_USING_HEAP=y
+
+#
+# Kernel Device Object
+#
+CONFIG_RT_USING_DEVICE=y
+# CONFIG_RT_USING_DEVICE_OPS is not set
+CONFIG_RT_USING_INTERRUPT_INFO=y
+CONFIG_RT_USING_CONSOLE=y
+CONFIG_RT_CONSOLEBUF_SIZE=4096
+CONFIG_RT_CONSOLE_DEVICE_NAME="uart1"
+CONFIG_RT_VER_NUM=0x40004
+CONFIG_ARCH_ARM=y
+# CONFIG_RT_USING_CPU_FFS is not set
+CONFIG_ARCH_ARM_CORTEX_A=y
+# CONFIG_RT_SMP_AUTO_BOOT is not set
+# CONFIG_RT_USING_GIC_V2 is not set
+CONFIG_RT_USING_GIC_V3=y
+# CONFIG_RT_NO_USING_GIC is not set
+# 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=2048
+CONFIG_RT_MAIN_THREAD_PRIORITY=10
+
+#
+# C++ features
+#
+# CONFIG_RT_USING_CPLUSPLUS is not set
+
+#
+# Command shell
+#
+CONFIG_RT_USING_FINSH=y
+CONFIG_FINSH_THREAD_NAME="tshell"
+CONFIG_FINSH_USING_HISTORY=y
+CONFIG_FINSH_HISTORY_LINES=5
+CONFIG_FINSH_USING_SYMTAB=y
+CONFIG_FINSH_USING_DESCRIPTION=y
+# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set
+CONFIG_FINSH_THREAD_PRIORITY=20
+CONFIG_FINSH_THREAD_STACK_SIZE=4096
+CONFIG_FINSH_CMD_SIZE=128
+# CONFIG_FINSH_USING_AUTH is not set
+CONFIG_FINSH_USING_MSH=y
+CONFIG_FINSH_USING_MSH_DEFAULT=y
+# CONFIG_FINSH_USING_MSH_ONLY is not set
+CONFIG_FINSH_ARG_MAX=10
+
+#
+# Device virtual file system
+#
+CONFIG_RT_USING_DFS=y
+CONFIG_DFS_USING_WORKDIR=y
+CONFIG_DFS_FILESYSTEMS_MAX=2
+CONFIG_DFS_FILESYSTEM_TYPES_MAX=2
+CONFIG_DFS_FD_MAX=16
+# CONFIG_RT_USING_DFS_MNTTABLE is not set
+CONFIG_RT_USING_DFS_ELMFAT=y
+
+#
+# elm-chan's FatFs, Generic FAT Filesystem Module
+#
+CONFIG_RT_DFS_ELM_CODE_PAGE=437
+CONFIG_RT_DFS_ELM_WORD_ACCESS=y
+# CONFIG_RT_DFS_ELM_USE_LFN_0 is not set
+# CONFIG_RT_DFS_ELM_USE_LFN_1 is not set
+# CONFIG_RT_DFS_ELM_USE_LFN_2 is not set
+CONFIG_RT_DFS_ELM_USE_LFN_3=y
+CONFIG_RT_DFS_ELM_USE_LFN=3
+CONFIG_RT_DFS_ELM_LFN_UNICODE_0=y
+# CONFIG_RT_DFS_ELM_LFN_UNICODE_1 is not set
+# CONFIG_RT_DFS_ELM_LFN_UNICODE_2 is not set
+# CONFIG_RT_DFS_ELM_LFN_UNICODE_3 is not set
+CONFIG_RT_DFS_ELM_LFN_UNICODE=0
+CONFIG_RT_DFS_ELM_MAX_LFN=255
+CONFIG_RT_DFS_ELM_DRIVES=2
+CONFIG_RT_DFS_ELM_MAX_SECTOR_SIZE=512
+# CONFIG_RT_DFS_ELM_USE_ERASE is not set
+CONFIG_RT_DFS_ELM_REENTRANT=y
+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
+
+#
+# Device Drivers
+#
+CONFIG_RT_USING_DEVICE_IPC=y
+CONFIG_RT_PIPE_BUFSZ=512
+# CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set
+CONFIG_RT_USING_SERIAL=y
+CONFIG_RT_SERIAL_USING_DMA=y
+CONFIG_RT_SERIAL_RB_BUFSZ=256
+CONFIG_RT_USING_CAN=y
+# CONFIG_RT_CAN_USING_HDR 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 is not set
+# 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=y
+CONFIG_RT_SDIO_STACK_SIZE=512
+CONFIG_RT_SDIO_THREAD_PRIORITY=15
+CONFIG_RT_MMCSD_STACK_SIZE=1024
+CONFIG_RT_MMCSD_THREAD_PREORITY=22
+CONFIG_RT_MMCSD_MAX_PARTITION=16
+# CONFIG_RT_SDIO_DEBUG is not set
+CONFIG_RT_USING_SPI=y
+CONFIG_RT_USING_QSPI=y
+# CONFIG_RT_USING_SPI_MSD is not set
+CONFIG_RT_USING_SFUD=y
+CONFIG_RT_SFUD_USING_SFDP=y
+CONFIG_RT_SFUD_USING_FLASH_INFO_TABLE=y
+CONFIG_RT_SFUD_USING_QSPI=y
+CONFIG_RT_SFUD_SPI_MAX_HZ=50000000
+# CONFIG_RT_DEBUG_SFUD is not set
+# CONFIG_RT_USING_ENC28J60 is not set
+# CONFIG_RT_USING_SPI_WIFI 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_HOST is not set
+# CONFIG_RT_USING_USB_DEVICE is not set
+
+#
+# POSIX layer and C standard library
+#
+CONFIG_RT_USING_LIBC=y
+# CONFIG_RT_USING_PTHREADS is not set
+CONFIG_RT_USING_POSIX=y
+# CONFIG_RT_USING_POSIX_MMAP is not set
+# CONFIG_RT_USING_POSIX_TERMIOS is not set
+# CONFIG_RT_USING_POSIX_GETLINE is not set
+# CONFIG_RT_USING_POSIX_AIO is not set
+# CONFIG_RT_USING_MODULE is not set
+CONFIG_RT_LIBC_FIXED_TIMEZONE=8
+
+#
+# Network
+#
+
+#
+# Socket abstraction layer
+#
+# CONFIG_RT_USING_SAL is not set
+
+#
+# Network interface device
+#
+CONFIG_RT_USING_NETDEV=y
+CONFIG_NETDEV_USING_IFCONFIG=y
+CONFIG_NETDEV_USING_PING=y
+CONFIG_NETDEV_USING_NETSTAT=y
+CONFIG_NETDEV_USING_AUTO_DEFAULT=y
+# CONFIG_NETDEV_USING_IPV6 is not set
+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_LWIP141 is not set
+# CONFIG_RT_USING_LWIP202 is not set
+CONFIG_RT_USING_LWIP212=y
+# CONFIG_RT_USING_LWIP_IPV6 is not set
+CONFIG_RT_LWIP_MEM_ALIGNMENT=4
+CONFIG_RT_LWIP_IGMP=y
+CONFIG_RT_LWIP_ICMP=y
+# CONFIG_RT_LWIP_SNMP is not set
+CONFIG_RT_LWIP_DNS=y
+# CONFIG_RT_LWIP_DHCP is not set
+
+#
+# Static IPv4 Address
+#
+CONFIG_RT_LWIP_IPADDR="192.168.3.20"
+CONFIG_RT_LWIP_GWADDR="192.168.3.1"
+CONFIG_RT_LWIP_MSKADDR="255.255.255.0"
+CONFIG_RT_LWIP_UDP=y
+CONFIG_RT_LWIP_TCP=y
+CONFIG_RT_LWIP_RAW=y
+# CONFIG_RT_LWIP_PPP is not set
+CONFIG_RT_MEMP_NUM_NETCONN=8
+CONFIG_RT_LWIP_PBUF_NUM=16
+CONFIG_RT_LWIP_RAW_PCB_NUM=4
+CONFIG_RT_LWIP_UDP_PCB_NUM=4
+CONFIG_RT_LWIP_TCP_PCB_NUM=4
+CONFIG_RT_LWIP_TCP_SEG_NUM=40
+CONFIG_RT_LWIP_TCP_SND_BUF=8196
+CONFIG_RT_LWIP_TCP_WND=8196
+CONFIG_RT_LWIP_TCPTHREAD_PRIORITY=10
+CONFIG_RT_LWIP_TCPTHREAD_MBOX_SIZE=8
+CONFIG_RT_LWIP_TCPTHREAD_STACKSIZE=1024
+# CONFIG_LWIP_NO_RX_THREAD is not set
+# CONFIG_LWIP_NO_TX_THREAD is not set
+CONFIG_RT_LWIP_ETHTHREAD_PRIORITY=12
+CONFIG_RT_LWIP_ETHTHREAD_STACKSIZE=1024
+CONFIG_RT_LWIP_ETHTHREAD_MBOX_SIZE=8
+# CONFIG_RT_LWIP_REASSEMBLY_FRAG is not set
+CONFIG_LWIP_NETIF_STATUS_CALLBACK=1
+CONFIG_LWIP_NETIF_LINK_CALLBACK=1
+CONFIG_SO_REUSE=1
+CONFIG_LWIP_SO_RCVTIMEO=1
+CONFIG_LWIP_SO_SNDTIMEO=1
+CONFIG_LWIP_SO_RCVBUF=1
+CONFIG_LWIP_SO_LINGER=0
+# CONFIG_RT_LWIP_NETIF_LOOPBACK is not set
+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_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
+#
+# CONFIG_RT_USING_RYM is not set
+CONFIG_RT_USING_ULOG=y
+# CONFIG_ULOG_OUTPUT_LVL_A is not set
+# CONFIG_ULOG_OUTPUT_LVL_E is not set
+CONFIG_ULOG_OUTPUT_LVL_W=y
+# CONFIG_ULOG_OUTPUT_LVL_I is not set
+# CONFIG_ULOG_OUTPUT_LVL_D is not set
+CONFIG_ULOG_OUTPUT_LVL=4
+# CONFIG_ULOG_USING_ISR_LOG is not set
+CONFIG_ULOG_ASSERT_ENABLE=y
+CONFIG_ULOG_LINE_BUF_SIZE=128
+# CONFIG_ULOG_USING_ASYNC_OUTPUT is not set
+
+#
+# log format
+#
+# CONFIG_ULOG_OUTPUT_FLOAT is not set
+CONFIG_ULOG_USING_COLOR=y
+CONFIG_ULOG_OUTPUT_TIME=y
+# CONFIG_ULOG_TIME_USING_TIMESTAMP is not set
+CONFIG_ULOG_OUTPUT_LEVEL=y
+CONFIG_ULOG_OUTPUT_TAG=y
+# CONFIG_ULOG_OUTPUT_THREAD_NAME is not set
+CONFIG_ULOG_BACKEND_USING_CONSOLE=y
+# CONFIG_ULOG_USING_FILTER is not set
+# CONFIG_ULOG_USING_SYSLOG is not set
+# CONFIG_RT_USING_UTEST is not set
+# CONFIG_RT_USING_RT_LINK is not set
+# CONFIG_RT_USING_LWP is not set
+
+#
+# RT-Thread Utestcases
+#
+# CONFIG_RT_USING_UTESTCASES is not set
+
+#
+# RT-Thread online packages
+#
+
+#
+# IoT - internet of things
+#
+# 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_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
+
+#
+# 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_NIMBLE 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
+
+#
+# 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_LUA is not set
+# CONFIG_PKG_USING_JERRYSCRIPT is not set
+# CONFIG_PKG_USING_MICROPYTHON is not set
+
+#
+# multimedia packages
+#
+# 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
+
+#
+# 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_QRCODE 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
+
+#
+# system packages
+#
+
+#
+# acceleration: Assembly language or algorithmic acceleration packages
+#
+# CONFIG_PKG_USING_RT_MEMCPY_CM is not set
+# 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
+
+#
+# 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_PKG_USING_GUIENGINE is not set
+# CONFIG_PKG_USING_PERSIMMON 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_LITTLEVGL2RTT is not set
+# CONFIG_PKG_USING_CMSIS 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_RT_KPRINTF_THREADSAFE 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
+
+#
+# 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_U8G2 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_ROSSERIAL 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_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
+
+#
+# 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
+#
+# 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_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
+
+#
+# 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
+# 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_VT100 is not set
+# CONFIG_PKG_USING_UKAL is not set
+# CONFIG_PKG_USING_CRCLIB is not set
+
+#
+# entertainment: terminal games and other interesting software packages
+#
+# 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_ACLOCK is not set
+# CONFIG_PKG_USING_LWGPS is not set
+# CONFIG_PKG_USING_STATE_MACHINE is not set
+# CONFIG_PKG_USING_MCURSES is not set
+# CONFIG_PKG_USING_COWSAY is not set
+CONFIG_FT2004=y
+
+#
+# Hardware Drivers Config
+#
+
+#
+# On-chip Peripheral Drivers
+#
+CONFIG_BSP_USING_UART=y
+CONFIG_RT_USING_UART1=y
+# CONFIG_RT_USING_UART0 is not set
+CONFIG_BSP_USING_SDC=y
+# CONFIG_BSP_SDC_DEBUG_PRINT is not set
+# CONFIG_BSP_SDC_USE_IRQ is not set
+CONFIG_BSP_USING_GMAC=y
+# CONFIG_BSP_USING_GMAC0 is not set
+CONFIG_BSP_USING_GMAC1=y
+CONFIG_RT_LWIP_ETH_PAD_SIZE=2
+# CONFIG_RAW_DATA_PRINT is not set
+CONFIG_BSP_USE_SPI=y
+# CONFIG_BSP_SPI_DEBUG is not set
+CONFIG_BSP_USE_GPIO=y
+# CONFIG_BSP_GPIO_DEBUG is not set
+CONFIG_BSP_USE_CAN=y
+CONFIG_BSP_USING_CAN0=y
+# CONFIG_BSP_USING_CAN1 is not set
+# CONFIG_BSP_USING_CAN0_DEBUG is not set
+
+#
+# Board extended module Drivers
+#
diff --git a/bsp/ft2004/Kconfig b/bsp/ft2004/Kconfig
new file mode 100644
index 0000000000..1bee562e48
--- /dev/null
+++ b/bsp/ft2004/Kconfig
@@ -0,0 +1,30 @@
+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 FT2004
+ bool
+ select ARCH_ARM_CORTEX_A
+ select RT_USING_COMPONENTS_INIT
+ select RT_USING_USER_MAIN
+ default y
+
+
+source "./libraries/Kconfig"
diff --git a/bsp/ft2004/README.md b/bsp/ft2004/README.md
new file mode 100644
index 0000000000..e39a505b5d
--- /dev/null
+++ b/bsp/ft2004/README.md
@@ -0,0 +1,236 @@
+# ft2004 四核开发板 BSP 说明
+
+## 简介
+
+本文档为 飞腾技术公司 ft2000/4 开发板的 BSP (板级支持包) 说明。
+
+主要内容如下:
+
+- 开发板资源介绍
+- BSP 外设支持
+- 使用方法
+- 相关实验
+
+### 1. 开发板资源介绍
+
+FT-2000/4 是一款面向桌面应用的高性能通用 4 核处理器。每 2 个核构成 1
+个处理器核簇(Cluster),并共享 L2 Cache。主要技术特征如下:
+
+- 兼容 ARM v8 64 位指令系统,兼容 32 位指令
+- 支持单精度、双精度浮点运算指令
+- 支持 ASIMD 处理指令
+- 集成 2 个 DDR4 通道,可对 DDR 存储数据进行实时加密
+- 集成 34 Lane PCIE3.0 接口:2 个 X16(每个可拆分成 2 个 X8),2 个 X1
+- 集成 2 个 GMAC,RGMII 接口,支持 10/100/1000 自适应
+- 集成 1 个 SD 卡控制器,兼容 SD 2.0 规范
+- 集成 1 个 HDAudio,支持音频输出,可同时支持最多 4 个 Codec
+- 集成 SM2、SM3、SM4 模块
+- 集成 4 个 UART,1 个 LPC,32 个 GPIO,4 个 I2C,1 个 QSPI,2 个通
+ 用 SPI,2 个 WDT,16 个外部中断(和 GPIO 共用 IO)
+- 集成温度传感器
+
+### 2. BSP 外设支持
+
+| 外设名 | 支持情况 | 备注 |
+| -------- | -------- | ---------------------- |
+| ft_gicv3 | 支持 | gicv3 中断控制器 |
+| ft_gmac | 支持 | ft gmac 千兆网卡控制器 |
+| ft_i2c | 支持 | FT I2C |
+| ft_qspi | 支持 | FT qspi 控制器 |
+| ft_sd | 支持 | FT mmcsd 控制器 |
+| ft_uart | 支持 | PrimeCell PL011 |
+| ft_spi | 支持 | FT spi 控制器 |
+| ft_gpio | 支持 | FT gpio 控制器 |
+| ft_can | 支持 | FT can 控制器 |
+
+### 3. 使用方法
+
+#### ubuntu 上环境搭建
+
+1. 在 ubuntu 环境下通过指令,下载并安装交叉编译链
+
+```
+sudo apt-get install gcc-arm-none-eabi
+```
+
+2. 安装之后,通过指令,确定交叉编译链安装完毕
+
+```
+arm-none-eabi-gcc -v
+```
+
+3. 搭建 tftp 环境
+
+ - 在主机安装 tftp 服务
+ > 使用 ubuntu 完成下列操作
+
+ ```
+ sudo apt-get install tftp-hpa tftpd-hpa
+ sudo apt-get install xinetd
+ ```
+
+ - 新建 tftboot 目录,如:
+ `/mnt/d/tftboot`
+
+ > 需要给 tftboot 目录执行权限`chmod 777 /**/tftboot`
+
+ - 配置主机 tftpboot 服务
+
+ 新建并配置文件/etc/xinetd.d/tftp
+
+ ```
+ # /etc/xinetd.d/tftp
+
+ server tftp
+ {
+ socket_type = dgram
+ protocol = udp
+ wait = yes
+ user = root
+ server = /usr/sbin/in.tftpd
+ server_args = -s /mnt/d/tftboot
+ disable = no
+ per_source = 11
+ cps = 100 2
+ flags = IPv4
+ }
+ ```
+
+ - 启动主机 tftp 服务
+
+ ```
+ sudo service tftpd-hpa start
+ ```
+
+ - 修改主机 tftp 配置
+ 修改/etc/default/tftpd-hpa
+
+ ```
+ sudo nano /etc/default/tftpd-hpa
+ # /etc/default/tftpd-hpa
+
+ TFTP_USERNAME="tftp"
+ TFTP_DIRECTORY="/mnt/d/tftboot"
+ TFTP_ADDRESS=":69"
+ TFTP_OPTIONS="-l -c -s"
+ ```
+
+ - 重启主机 tftp 服务
+ > 每次开机要重启一次
+
+ ```
+ sudo service tftpd-hpa restart
+ ```
+
+ - 测试主机 tftp 服务的可用性
+ > 登录 tftp 服务,获取一个文件
+
+ ```
+ $ tftp 192.168.4.50
+ tftp> get test1234
+ tftp> q
+ ```
+
+#### 执行
+
+1. 将本 bsp 包拷贝至 RT-THREAD bsp/目录下
+
+1. 在 Ubuntu 终端下,切换至 bsp 目录
+
+```
+cd rt-thread/bsp/ft2004
+```
+
+3. 使用 scons -c 清空工程缓存
+
+4. 使用 scons --menuconfig 配置需要的外设
+
+![](./figures/onchipPeripheral.png)
+
+5. 使用 scons 编译代码,得到 rtthread.bin,并将 rtthread.bin 放入之前配置的 tftp 路径下。
+
+6. 连接开发板对应串口到 PC, 在终端工具里打开相应的串口(115200-8-1-N)。
+
+7. 将开发板网线接入局域网中
+
+8. 本开发板自带 uboot,使用 uboot 自带 指令进行将 bin 文件下载至 ram 中
+
+```
+setenv ipaddr 192.168.x.x # 设置开发板ip
+setenv serverip 192.168.x.x # 设置tftp服务器ip
+setenv gatewayip 192.168.x.x # 设置网关ip
+tftpboot 80100000 rtthread.bin # 在主机 /tftpboot目录中的rtthread.bin文件下载到开发板内存的80100000地址中。
+```
+
+7. 执行跳转指令,便可以正常执行
+
+```
+bootvx32 80100000
+或
+boot32 80100000
+```
+
+![](./figures/启动演示图.png)
+
+### 5. 相关实验
+
+#### 网卡
+
+- 主机 ping 本机 指令 sudo ping 192.168.3.20 (默认)
+
+- rtt ping 主机 指令 ping 192.168.x.x (根据实际情况)
+
+- 通过界面
+
+![](./figures/rttPing通过界面.png)
+
+#### sd 卡调试
+
+- 通过基本命令进行,mv ,echo ,ls ,cd ,rm ....
+
+![](./figures/rttsd调试.png)
+
+#### spi flash 卡调试
+
+- 找一块有 spi flash 插槽的 ft-2004 开发板,插入 sf25s 或 gd25q 系列 spi flash
+- 配置 rt-thread 的编译选项,打开 BSP_USE_SPI 和 BSP_USE_GPIO 配置,关闭 BSP_USE_QSPI 配置,打开 rt-thread 的 SFUD 调试开关
+- 编译 rt-thread,加载版本启动,启动后显示 spi flash probe 成功
+- 执行 sf 基本操作,read, write, erase
+
+#### 推荐指令
+
+1. sf probe S25FS256
+
+2. sf read 0x1FFF000 16
+
+3. sf write 0x1FFF000 16 25 68 78 95 15 75 20
+
+4. sf read 0x1FFF000 16
+
+5. sf erase 0x1FFF000 16
+
+#### can 测试
+
+1. 使用 scons menuconfig 选中 Enable Can
+
+2. 然后选中 Enable can0 ,Enable can0 work in loop back
+
+3. 烧录程序并且烧录
+
+4. 打开 can 盒,将波特率设为 1000000
+
+5. 然后通过 can 盒发送对应的数据(标准帧,扩展帧),就可以看见回复同样的内容
+
+## 6. 参考资源
+
+- ARM Architecture Reference Manual
+
+- FT-2000/4 软件编程手册-V1.4
+
+## 7. 联系人信息
+
+请联系飞腾嵌入式软件部
+
+
diff --git a/bsp/ft2004/SConscript b/bsp/ft2004/SConscript
new file mode 100644
index 0000000000..fe0ae941ae
--- /dev/null
+++ b/bsp/ft2004/SConscript
@@ -0,0 +1,14 @@
+# for module compiling
+import os
+Import('RTT_ROOT')
+
+cwd = str(Dir('#'))
+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/ft2004/SConstruct b/bsp/ft2004/SConstruct
new file mode 100644
index 0000000000..e3c1df26fa
--- /dev/null
+++ b/bsp/ft2004/SConstruct
@@ -0,0 +1,32 @@
+import os
+import sys
+import rtconfig
+
+if os.getenv('RTT_ROOT'):
+ RTT_ROOT = os.getenv('RTT_ROOT')
+else:
+ RTT_ROOT = os.path.join(os.getcwd(), '..', '..')
+
+sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
+from building import *
+
+TARGET = 'ft2004.' + rtconfig.TARGET_EXT
+
+DefaultEnvironment(tools=[])
+env = Environment(tools = ['mingw'],
+ AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
+ CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS,
+ CXX= rtconfig.CXX, CXXFLAGS = rtconfig.CFLAGS,
+ 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)
+
+# make a building
+DoBuilding(TARGET, objs)
diff --git a/bsp/ft2004/applications/SConscript b/bsp/ft2004/applications/SConscript
new file mode 100644
index 0000000000..a526af2c75
--- /dev/null
+++ b/bsp/ft2004/applications/SConscript
@@ -0,0 +1,11 @@
+Import('RTT_ROOT')
+Import('rtconfig')
+from building import *
+
+cwd = GetCurrentDir()
+src = Glob('*.c')
+CPPPATH = [cwd]
+
+group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/ft2004/applications/main.c b/bsp/ft2004/applications/main.c
new file mode 100644
index 0000000000..95fad98370
--- /dev/null
+++ b/bsp/ft2004/applications/main.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2012-12-05 Bernard the first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include "ft_cpu.h"
+#include "ft_generic_timer.h"
+
+#include <board.h>
+
+#ifdef RT_USING_SMP
+
+struct rt_thread test_core[RT_CPUS_NR];
+static char *core_thread_name[RT_CPUS_NR] = {
+ "core0_test",
+ "core1_test",
+ "core2_test",
+ "core3_test"};
+static rt_uint8_t core_stack[RT_CPUS_NR][1024];
+
+static void demo_core_thread(void *parameter)
+{
+ rt_base_t level;
+ while (1)
+ {
+ /* code */
+ level = rt_cpus_lock();
+ rt_kprintf("Hi, core%d \r\n", FCpu_IdGet());
+ rt_cpus_unlock(level);
+ rt_thread_mdelay(20000);
+ }
+}
+
+void demo_core(void)
+{
+ rt_ubase_t i;
+ rt_uint8_t cpu_id = 0;
+ for (i = 0; i < RT_CPUS_NR; i++)
+ {
+ cpu_id = i;
+ rt_thread_init(&test_core[i],
+ core_thread_name[i],
+ demo_core_thread,
+ RT_NULL,
+ &core_stack[i],
+ 1024,
+ 20,
+ 32);
+
+ rt_thread_control(&test_core[i], RT_THREAD_CTRL_BIND_CPU, (void *)cpu_id);
+ rt_thread_startup(&test_core[i]);
+ }
+}
+#endif
+
+int main(void)
+{
+ int count = 1;
+
+#ifdef RT_USING_SMP
+ demo_core();
+#endif
+
+ while (count++)
+ {
+ rt_thread_mdelay(2000);
+ }
+
+ return RT_EOK;
+}
diff --git a/bsp/ft2004/drivers/SConscript b/bsp/ft2004/drivers/SConscript
new file mode 100644
index 0000000000..b18c98833e
--- /dev/null
+++ b/bsp/ft2004/drivers/SConscript
@@ -0,0 +1,14 @@
+
+from building import *
+
+cwd = GetCurrentDir()
+src = Glob('*.S')
+src += Glob('*.c')
+
+
+
+CPPPATH = [cwd]
+
+group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/ft2004/drivers/board.c b/bsp/ft2004/drivers/board.c
new file mode 100644
index 0000000000..408a58d344
--- /dev/null
+++ b/bsp/ft2004/drivers/board.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2021-03-04 Carl the first version
+ *
+ */
+
+#include <rtthread.h>
+#include "ft_printf.h"
+#include "ft_assert.h"
+#include "ft_cpu.h"
+#include "ft_psci.h"
+#include "ft_parameters.h"
+#include "board.h"
+#include "gtimer.h"
+#include "ft_generic_timer.h"
+#include <gicv3.h>
+
+#include "interrupt.h"
+#include <mmu.h>
+#include "cp15.h"
+#include "ft2004.h"
+
+#define DDR_MEM (SHARED | AP_RW | DOMAIN0 | MEMWT | DESC_SEC)
+
+struct mem_desc platform_mem_desc[] = {
+ {0x80000000,
+ 0x80000000 + 0x7f000000,
+ 0x80000000,
+ DDR_MEM},
+ {0, //< QSPI
+ 0x1FFFFFFF,
+ 0,
+ DEVICE_MEM},
+ {0x20000000, //<! LPC
+ 0x27FFFFFF,
+ 0x20000000,
+ DEVICE_MEM},
+ {FT_DEV_BASE_ADDR, //<! Device register
+ FT_DEV_END_ADDR,
+ FT_DEV_BASE_ADDR,
+ DEVICE_MEM},
+ {0x30000000, //<! debug
+ 0x39FFFFFF,
+ 0x30000000,
+ DEVICE_MEM},
+ {0x3A000000, //<! Internal register space in the on-chip network
+ 0x3AFFFFFF,
+ 0x3A000000,
+ DEVICE_MEM},
+ {FT_PCI_CONFIG_BASEADDR,
+ FT_PCI_CONFIG_BASEADDR + FT_PCI_CONFIG_REG_LENGTH,
+ FT_PCI_CONFIG_BASEADDR,
+ DEVICE_MEM},
+ {FT_PCI_IO_CONFIG_BASEADDR,
+ FT_PCI_IO_CONFIG_BASEADDR + FT_PCI_IO_CONFIG_REG_LENGTH,
+ FT_PCI_IO_CONFIG_BASEADDR,
+ DEVICE_MEM},
+ {FT_PCI_MEM32_BASEADDR,
+ FT_PCI_MEM32_BASEADDR + FT_PCI_MEM32_REG_LENGTH,
+ FT_PCI_MEM32_BASEADDR,
+ DEVICE_MEM},
+};
+
+const rt_uint32_t platform_mem_desc_size = sizeof(platform_mem_desc) / sizeof(platform_mem_desc[0]);
+
+rt_uint32_t platform_get_gic_dist_base(void)
+{
+ return FT_GICV3_DISTRIBUTOR_BASEADDRESS;
+}
+
+static rt_uint32_t timerStep;
+
+void rt_hw_timer_isr(int vector, void *parameter)
+{
+ gtimer_set_load_value(timerStep);
+ rt_tick_increase();
+}
+
+int rt_hw_timer_init(void)
+{
+ rt_hw_interrupt_install(30, rt_hw_timer_isr, RT_NULL, "tick");
+ rt_hw_interrupt_umask(30);
+ timerStep = gtimer_get_counter_frequency();
+ timerStep /= RT_TICK_PER_SECOND;
+ gtimer_set_load_value(timerStep);
+ gtimer_set_control(1);
+ return 0;
+}
+INIT_BOARD_EXPORT(rt_hw_timer_init);
+
+static void AssertCallback(const char *File, s32 Line)
+{
+ Ft_printf("Assert Error is %s : %d \r\n", File, Line);
+}
+
+#ifdef RT_USING_SMP
+void rt_hw_ipi_handler_install(int ipi_vector, rt_isr_handler_t ipi_isr_handler);
+#endif
+
+/**
+ * This function will initialize hardware board
+ */
+void rt_hw_board_init(void)
+{
+ /* bsp debug */
+ FCpu_SpinLockInit();
+ Ft_GenericTimer_Init(0, RT_NULL);
+ Ft_vsprintfRegister((vsprintf_p)rt_vsprintf);
+ Ft_assertSetCallBack((Ft_assertCallback)AssertCallback);
+
+ /* interrupt init */
+ arm_gic_redist_address_set(0, FT_GICV3_RD_BASEADDRESS + 0, 0);
+
+#if RT_CPUS_NR == 2
+ Ft_printf("arm_gic_redist_address_set is 2 \r\n");
+ arm_gic_redist_address_set(0, FT_GICV3_RD_BASEADDRESS + (2U << 16), 1);
+#elif RT_CPUS_NR == 3
+ arm_gic_redist_address_set(0, FT_GICV3_RD_BASEADDRESS + (2U << 16), 1);
+ arm_gic_redist_address_set(0, FT_GICV3_RD_BASEADDRESS + 2 * (2U << 16), 2);
+#elif RT_CPUS_NR == 4
+ arm_gic_redist_address_set(0, FT_GICV3_RD_BASEADDRESS + (2U << 16), 1);
+ arm_gic_redist_address_set(0, FT_GICV3_RD_BASEADDRESS + 2 * (2U << 16), 2);
+ arm_gic_redist_address_set(0, FT_GICV3_RD_BASEADDRESS + 3 * (2U << 16), 3);
+#endif
+
+ rt_hw_interrupt_init();
+
+ rt_components_board_init();
+ rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
+
+/* 初始化内存池 */
+#ifdef RT_USING_HEAP
+ rt_system_heap_init(HEAP_BEGIN, HEAP_END);
+#endif
+
+#ifdef RT_USING_SMP
+ /* install IPI handle */
+ rt_hw_interrupt_set_priority(RT_SCHEDULE_IPI, 16);
+ rt_hw_ipi_handler_install(RT_SCHEDULE_IPI, rt_scheduler_ipi_handler);
+ rt_hw_interrupt_umask(RT_SCHEDULE_IPI);
+#endif
+}
+
+static void ft_reset(void)
+{
+ FPsci_Reset();
+}
+MSH_CMD_EXPORT_ALIAS(ft_reset, ft_reset, ft_reset);
+
+/*@}*/
diff --git a/bsp/ft2004/drivers/board.h b/bsp/ft2004/drivers/board.h
new file mode 100644
index 0000000000..4900ed2e79
--- /dev/null
+++ b/bsp/ft2004/drivers/board.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2013-07-06 Bernard the first version
+ */
+
+#ifndef __BOARD_H__
+#define __BOARD_H__
+
+#include "ft_parameters.h"
+#include "ft2004.h"
+
+#if defined(__CC_ARM)
+extern int Image$$RW_IRAM1$$ZI$$Limit;
+#define HEAP_BEGIN ((void *)&Image$$RW_IRAM1$$ZI$$Limit)
+#elif defined(__GNUC__)
+extern int __bss_end;
+#define HEAP_BEGIN ((void *)&__bss_end)
+#endif
+
+#define HEAP_END (void *)(0x80000000 + 1024 * 1024 * 1024)
+
+void rt_hw_board_init(void);
+
+#endif
diff --git a/bsp/ft2004/drivers/drv_can.c b/bsp/ft2004/drivers/drv_can.c
new file mode 100644
index 0000000000..ff03755761
--- /dev/null
+++ b/bsp/ft2004/drivers/drv_can.c
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2021-05-11 Carl the first version
+ */
+
+#include "drv_can.h"
+#include "interrupt.h"
+#include <string.h>
+
+#ifdef BSP_USE_CAN
+
+#define LOG_TAG "drv_can"
+#include <drv_log.h>
+
+#define _CAN0_NAME "can0"
+#define _CAN1_NAME "can1"
+
+#define RTHW_CAN_WAIT(_can) rt_sem_take(&_can->recv_semaphore, RT_WAITING_FOREVER);
+#define RTHW_CAN_SEND(_can) rt_sem_release(&_can->recv_semaphore);
+
+#ifdef BSP_USING_CAN0
+struct ft2004_can drv_can0 =
+ {
+ .name = _CAN0_NAME,
+ .can_handle.Config.InstanceId = 0};
+#endif
+
+#ifdef BSP_USING_CAN1
+struct ft2004_can drv_can1 =
+ {
+ .name = _CAN1_NAME,
+ .can_handle.Config.InstanceId = 1};
+#endif
+
+static void _can_recv_irq(void *args)
+{
+ struct ft2004_can *drv_can = (struct ft2004_can *)args;
+ RTHW_CAN_SEND(drv_can);
+}
+
+static void rt_hw_inner_can_isr(int irqno, void *param)
+{
+ FCan_IntrHandler(param);
+}
+
+static rt_err_t _can_config(struct rt_can_device *can, struct can_configure *cfg)
+{
+ struct FCan_Bittiming bit_timing = {0};
+ struct ft2004_can *drv_can;
+ RT_ASSERT(can);
+ RT_ASSERT(cfg);
+ drv_can = (struct ft2004_can *)can->parent.user_data;
+ RT_ASSERT(drv_can);
+
+ FCan_CfgInitialize(&drv_can->can_handle, FCan_LookupConfig(drv_can->can_handle.Config.InstanceId));
+
+ FCan_SetHandler(&drv_can->can_handle, FCAN_HANDLER_RECV, _can_recv_irq, drv_can);
+
+ bit_timing.bitrate = cfg->baud_rate;
+
+ if (FCan_CalcBittiming(&bit_timing) != FCAN_SUCCESS)
+ {
+ LOG_E("Setting baud rate %x is not valid \r\n", bit_timing.bitrate);
+ return -RT_ERROR;
+ }
+
+ FCan_SetTiming(&drv_can->can_handle, &bit_timing);
+
+ rt_hw_interrupt_set_priority(drv_can->can_handle.Config.IrqNum, 16);
+ rt_hw_interrupt_install(drv_can->can_handle.Config.IrqNum, rt_hw_inner_can_isr, &drv_can->can_handle, drv_can->name);
+ rt_hw_interrupt_umask(drv_can->can_handle.Config.IrqNum);
+
+ FCan_Enable(&drv_can->can_handle);
+
+ return RT_EOK;
+}
+
+static rt_err_t _can_control(struct rt_can_device *can, int cmd, void *arg)
+{
+ return RT_EOK;
+}
+
+static int _can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t box_num)
+{
+ struct ft2004_can *drv_can;
+ struct rt_can_msg *pmsg = (struct rt_can_msg *)buf;
+ struct FCan_Frame can_frame = {0};
+ RT_ASSERT(can);
+ drv_can = (struct ft2004_can *)can->parent.user_data;
+ RT_ASSERT(drv_can);
+
+ /* Check the parameters */
+ RT_ASSERT(pmsg->len <= 8U);
+
+ if (RT_CAN_STDID == pmsg->ide)
+ {
+ can_frame.CanId = pmsg->id;
+ }
+ else
+ {
+ can_frame.CanId = pmsg->id;
+ can_frame.CanId |= CAN_EFF_FLAG;
+ }
+
+ if (RT_CAN_DTR == pmsg->rtr)
+ {
+ }
+ else
+ {
+ can_frame.CanId |= CAN_RTR_FLAG;
+ }
+
+ can_frame.CanDlc = pmsg->len & 0x0FU;
+ memcpy(can_frame.data, pmsg->data, 8);
+
+ return (FCan_SendByIrq(&drv_can->can_handle, &can_frame, 1, RT_NULL) == 1) ? RT_EOK : -RT_ERROR;
+}
+
+static int _can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t fifo)
+{
+ struct ft2004_can *drv_can;
+ struct rt_can_msg *pmsg = (struct rt_can_msg *)buf;
+ RT_ASSERT(can);
+ struct FCan_Frame recv_frame = {0};
+ drv_can = (struct ft2004_can *)can->parent.user_data;
+ RT_ASSERT(drv_can);
+
+ RTHW_CAN_WAIT(drv_can);
+
+ if (FCan_RecvByIrq(&drv_can->can_handle, &recv_frame, 1) == 0)
+ {
+ LOG_E("rx msg is error");
+ return -RT_ERROR;
+ }
+
+ if (CAN_EFF_FLAG & recv_frame.CanId)
+ {
+ pmsg->ide = RT_CAN_EXTID;
+ pmsg->id = (recv_frame.CanId & ~(RT_CAN_EXTID));
+ }
+ else
+ {
+ pmsg->ide = RT_CAN_STDID;
+ pmsg->id = recv_frame.CanId;
+ }
+
+ if (CAN_RTR_FLAG & recv_frame.CanId)
+ {
+ pmsg->id &= ~CAN_RTR_FLAG;
+ pmsg->rtr = RT_CAN_RTR;
+ }
+ else
+ {
+ pmsg->rtr = RT_CAN_DTR;
+ }
+
+ /* get len */
+ pmsg->len = recv_frame.CanDlc;
+ return RT_EOK;
+}
+
+static const struct rt_can_ops _can_ops =
+ {
+ _can_config,
+ _can_control,
+ _can_sendmsg,
+ _can_recvmsg,
+};
+
+int rt_hw_can_init(void)
+{
+#ifdef BSP_USING_CAN0
+ drv_can0.can_handle.Config.InstanceId = 0;
+ rt_sem_init(&drv_can0.recv_semaphore, "can0_recv", 0, RT_IPC_FLAG_FIFO);
+ drv_can0.device.config.ticks = 20000;
+ drv_can0.device.config.baud_rate = 1000000;
+ rt_hw_can_register(&drv_can0.device,
+ drv_can0.name,
+ &_can_ops,
+ &drv_can0);
+
+#endif
+
+#ifdef BSP_USING_CAN1
+ drv_can1.can_handle.Config.InstanceId = 1;
+ drv_can0.device.config.baud_rate = 1000000;
+ rt_sem_init(&drv_can1.recv_semaphore, "can1_recv", 0, RT_IPC_FLAG_FIFO);
+ rt_hw_can_register(&drv_can1.device,
+ drv_can1.name,
+ &_can_ops,
+ &drv_can1);
+
+#endif
+ return 0;
+}
+
+INIT_BOARD_EXPORT(rt_hw_can_init);
+
+#ifdef BSP_USING_CAN0_DEBUG
+
+struct can_test_struct
+{
+ const char *name;
+ struct rt_can_filter_config *filter;
+ rt_device_t candev;
+ struct rt_semaphore _sem;
+};
+
+static struct can_test_struct can0_test_obj = {
+ .name = _CAN0_NAME};
+
+void can_recv_irq(void *param)
+{
+ struct can_test_struct *_can_obj = (struct can_test_struct *)param;
+ rt_kprintf("can_recv_iqr \r\n");
+ rt_sem_release(&_can_obj->_sem);
+}
+
+static void rt_can_test_loopback_thread_entry(void *param)
+{
+ struct can_test_struct *_can_obj = (struct can_test_struct *)param;
+ struct FCan_Frame recv_frame;
+ struct ft2004_can *drv_can;
+ rt_uint32_t i;
+ _can_obj->candev = rt_device_find(_can_obj->name);
+ RT_ASSERT(_can_obj->candev);
+ drv_can = (struct ft2004_can *)_can_obj->candev->user_data;
+ rt_sem_init(&_can_obj->_sem, "canrx_wait", 0, RT_IPC_FLAG_FIFO);
+ rt_device_open(_can_obj->candev, RT_DEVICE_OFLAG_RDWR);
+
+ while (1)
+ {
+ rt_kprintf(" start to wait loopback \r\n");
+ RTHW_CAN_WAIT(drv_can);
+ while (0 != FCan_RecvByIrq(&drv_can->can_handle, &recv_frame, 1))
+ {
+ rt_kprintf("CanId %x \r\n", recv_frame.CanId);
+ rt_kprintf("CanDlc %x \r\n", recv_frame.CanDlc);
+ for (i = 0; i < recv_frame.CanDlc; i++)
+ {
+ rt_kprintf("data [%d] %x \r\n", i, recv_frame.data[i]);
+ }
+ FCan_SendByIrq(&drv_can->can_handle, &recv_frame, 1, RT_NULL);
+ }
+ }
+}
+
+int rt_can0_test(void)
+{
+ rt_thread_t tid;
+
+ tid = rt_thread_create("can0_loopback",
+ rt_can_test_loopback_thread_entry, &can0_test_obj,
+ 1024, 16, 20);
+ if (tid != RT_NULL)
+ rt_thread_startup(tid);
+
+ return 0;
+}
+
+INIT_APP_EXPORT(rt_can0_test);
+
+#endif
+
+#endif
diff --git a/bsp/ft2004/drivers/drv_can.h b/bsp/ft2004/drivers/drv_can.h
new file mode 100644
index 0000000000..92e809eb1e
--- /dev/null
+++ b/bsp/ft2004/drivers/drv_can.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2021-05-11 Carl the first version
+ */
+
+#ifndef __DRV_CAN_H__
+#define __DRV_CAN_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <board.h>
+#include <rtdevice.h>
+#include <rtthread.h>
+#include "ft_can.h"
+
+ struct ft2004_can
+ {
+ const char *name;
+ FCan_t can_handle;
+ struct rt_semaphore recv_semaphore;
+ struct rt_can_device device; /* inherit from can device */
+ };
+
+ int rt_hw_can_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // !
diff --git a/bsp/ft2004/drivers/drv_eth.c b/bsp/ft2004/drivers/drv_eth.c
new file mode 100644
index 0000000000..e7148631e4
--- /dev/null
+++ b/bsp/ft2004/drivers/drv_eth.c
@@ -0,0 +1,691 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2021-03-09 Carl the first version
+ */
+
+#include "board.h"
+#include <netif/ethernetif.h>
+#include "lwipopts.h"
+#include "ft_parameters.h"
+#include "ft_gmac.h"
+#include "ft_cache.h"
+#include "ft_gmac_hw.h"
+#include "ft_status.h"
+#include "ft_io.h"
+#include "drv_eth.h"
+
+#ifdef BSP_USING_GMAC
+
+#define LOG_TAG "drv.gmac"
+#include <drv_log.h>
+
+#define MAX_ADDR_LEN 6
+
+#define LINK_THREAD_STACK_LENGTH 0x400
+
+struct drv_gmac
+{
+ struct eth_device parent; /* inherit from ethernet device */
+ Ft_Gmac_t Gmac; /* Gmac driver */
+#ifndef PHY_USING_INTERRUPT_MODE
+ rt_timer_t poll_link_timer;
+#endif
+ rt_uint8_t *rx_buffer; /* Buffer for RxDesc */
+ rt_uint8_t *tx_buffer; /* Buffer for TxDesc */
+ uint32_t eth_speed; /* eth_speed */
+ uint32_t eth_mode; /* ETH_Duplex_Mode */
+ rt_uint8_t dev_addr[MAX_ADDR_LEN]; /* MAC address */
+ struct rt_event link_event;
+
+ struct rt_thread _link_thread;
+ rt_uint8_t _link_thread_stack[LINK_THREAD_STACK_LENGTH];
+
+ rt_thread_t _debug_tid;
+};
+
+static void rt_ft2004_status_check(void *Args, u32 MacPhyStatus);
+
+//
+#if defined(RAW_DATA_PRINT)
+#if defined(ETH_RX_DUMP) || defined(ETH_TX_DUMP)
+#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
+static void dump_hex(const rt_uint8_t *ptr, rt_size_t buflen)
+{
+ unsigned char *buf = (unsigned char *)ptr;
+ int i, j;
+
+ for (i = 0; i < buflen; i += 16)
+ {
+ rt_kprintf("%08X: ", i);
+
+ for (j = 0; j < 16; j++)
+ if (i + j < buflen)
+ rt_kprintf("%02X ", buf[i + j]);
+ else
+ rt_kprintf(" ");
+ rt_kprintf(" ");
+
+ for (j = 0; j < 16; j++)
+ if (i + j < buflen)
+ rt_kprintf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
+ rt_kprintf("\n");
+ }
+}
+#endif
+#endif
+
+/**
+ * @name: rt_gmacmem_create
+ * @msg: Initialize the Gmac TX/Rx Describe Memory 。
+ * @param {*}
+ * @return {*}
+ */
+static void rt_gmacmem_create(struct drv_gmac *pOsGmac)
+{
+ pOsGmac->rx_buffer = rt_calloc(1, RX_DESCNUM * GMAC_MAX_PACKET_SIZE);
+ if (pOsGmac->rx_buffer == NULL)
+ {
+ LOG_E("rx_buffer Malloc is error ");
+ RT_ASSERT(0)
+ }
+
+ pOsGmac->tx_buffer = rt_calloc(1, TX_DESCNUM * GMAC_MAX_PACKET_SIZE);
+ if (pOsGmac->tx_buffer == NULL)
+ {
+ LOG_E("tx_buffer Malloc is error ");
+ RT_ASSERT(0)
+ }
+
+ pOsGmac->Gmac.TxDesc = rt_calloc(1, TX_DESCNUM * sizeof(FGmac_DmaDesc_t));
+ if (pOsGmac->Gmac.TxDesc == NULL)
+ {
+ LOG_E("TxDesc Malloc is error ");
+ RT_ASSERT(0)
+ }
+
+ pOsGmac->Gmac.RxDesc = rt_calloc(1, RX_DESCNUM * sizeof(FGmac_DmaDesc_t) + 128);
+ if (pOsGmac->Gmac.RxDesc == NULL)
+ {
+ LOG_E("RxDesc Malloc is error ");
+ RT_ASSERT(0)
+ }
+
+#define ROUND_UP(x, align) (((long)(x) + ((long)align - 1)) & \
+ ~((long)align - 1))
+
+ pOsGmac->Gmac.RxDesc = (FGmac_DmaDesc_t *)ROUND_UP(pOsGmac->Gmac.RxDesc, 128);
+ LOG_D("RxDesc fit after addr %x ", pOsGmac->Gmac.RxDesc);
+}
+
+static void rt_gmacmem_free(struct drv_gmac *pOsGmac)
+{
+ if (pOsGmac->rx_buffer)
+ {
+ rt_free(pOsGmac->rx_buffer);
+ }
+
+ if (pOsGmac->tx_buffer)
+ {
+ rt_free(pOsGmac->tx_buffer);
+ }
+
+ if (pOsGmac->Gmac.RxDesc)
+ {
+ rt_free(pOsGmac->Gmac.RxDesc);
+ }
+
+ if (pOsGmac->Gmac.TxDesc)
+ {
+ rt_free(pOsGmac->Gmac.TxDesc);
+ }
+}
+
+static void rt_hw_gmac_isr(int irqno, void *param)
+{
+ FGmac_IntrHandler(param);
+}
+
+static void rt_hw_gmac_recv_isr(void *Args)
+{
+ struct drv_gmac *pOsMac;
+ rt_err_t result = 0;
+
+ if (RT_NULL == Args)
+ {
+ LOG_E("Args is NULL");
+ return;
+ }
+
+ pOsMac = (struct drv_gmac *)Args;
+ result = eth_device_ready(&(pOsMac->parent));
+ if (result != RT_EOK)
+ {
+ LOG_I("RxCpltCallback err = %d", result);
+ }
+}
+
+static rt_err_t
+rt_ft2004_gmac_start(struct drv_gmac *pOsMac)
+{
+ Ft_Gmac_t *pGmac;
+ pGmac = &pOsMac->Gmac;
+
+ if (FST_SUCCESS != Ft_Gmac_HwInitialize(pGmac))
+ {
+ return -RT_ERROR;
+ }
+
+ FGmac_SetHandler(pGmac, FT_GMAC_RX_COMPLETE_CB_ID, rt_hw_gmac_recv_isr, pOsMac);
+ FGmac_SetHandler(pGmac, FT_GMAC_MAC_PHY_STATUS_CB_ID, rt_ft2004_status_check, pOsMac);
+
+ /* Initialize Rx Description list : ring Mode */
+ FGmac_DmaRxDescRingInit(pGmac, pGmac->RxDesc, pOsMac->rx_buffer, GMAC_MAX_PACKET_SIZE, RX_DESCNUM);
+
+ /* Initialize Tx Description list : ring Mode */
+ FGmac_DmaTxDescRingInit(pGmac, pGmac->TxDesc, pOsMac->tx_buffer, GMAC_MAX_PACKET_SIZE, TX_DESCNUM);
+
+ Ft_Gmac_Start(pGmac);
+ /* Gmac interrupt init */
+ rt_hw_interrupt_install(pGmac->Config.IRQ_NUM, rt_hw_gmac_isr, pGmac, "Gmac");
+ rt_hw_interrupt_umask(pGmac->Config.IRQ_NUM);
+ return RT_EOK;
+}
+
+void rt_ft2004_gmac_stop(struct drv_gmac *pOsMac)
+{
+ Ft_Gmac_t *pGmac;
+ pGmac = &pOsMac->Gmac;
+ Ft_Gmac_Stop(pGmac);
+}
+
+/* GMAC initialization function */
+static rt_err_t rt_ft2004_gmac_init(rt_device_t dev)
+{
+ struct drv_gmac *pOsMac;
+ struct eth_device *pGmacParent;
+ FGmac_Config_t *pConfig;
+
+ pGmacParent = rt_container_of(dev, struct eth_device, parent);
+ if (NULL == pGmacParent)
+ {
+ return -RT_ENOMEM;
+ }
+
+ pOsMac = rt_container_of(pGmacParent, struct drv_gmac, parent);
+ if (NULL == pOsMac)
+ {
+ return -RT_ENOMEM;
+ }
+
+ pConfig = Ft_Gmac_LookupConfig(pOsMac->Gmac.Config.InstanceId);
+ if (NULL == pConfig)
+ {
+ return -RT_ENOMEM;
+ }
+
+ Ft_Gmac_UseDefaultMacAddr(&pOsMac->Gmac, pOsMac->Gmac.Config.MacAddr);
+
+ if (FST_SUCCESS != Ft_GmacCfgInitialize(&pOsMac->Gmac, pConfig))
+ {
+ return -RT_ERROR;
+ }
+
+ return rt_ft2004_gmac_start(pOsMac);
+}
+
+static rt_err_t rt_ft2004_gmac_open(rt_device_t dev, rt_uint16_t oflag)
+{
+ LOG_D("gmac open");
+ return RT_EOK;
+}
+
+static rt_err_t rt_ft2004_gmac_close(rt_device_t dev)
+{
+ LOG_D("gmac close");
+ return RT_EOK;
+}
+
+static rt_size_t rt_ft2004_gmac_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
+{
+ LOG_D("gmac read");
+ rt_set_errno(-RT_ENOSYS);
+ return 0;
+}
+
+static rt_size_t rt_ft2004_gmac_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
+{
+ LOG_D("gmac write");
+ rt_set_errno(-RT_ENOSYS);
+ return 0;
+}
+
+static rt_err_t rt_ft2004_gmac_control(rt_device_t dev, int cmd, void *args)
+{
+
+ struct drv_gmac *pOsMac;
+ struct eth_device *pGmacParent;
+
+ pGmacParent = rt_container_of(dev, struct eth_device, parent);
+ if (NULL == pGmacParent)
+ {
+ return -RT_ENOMEM;
+ }
+
+ pOsMac = rt_container_of(pGmacParent, struct drv_gmac, parent);
+ if (NULL == pOsMac)
+ {
+ return -RT_ENOMEM;
+ }
+
+ switch (cmd)
+ {
+ case NIOCTL_GADDR:
+ /* get mac address */
+ if (args)
+ rt_memcpy(args, pOsMac->dev_addr, 6);
+ else
+ return -RT_ERROR;
+ break;
+
+ default:
+ break;
+ }
+
+ return RT_EOK;
+}
+
+rt_err_t rt_ft2004_gmac_tx(rt_device_t dev, struct pbuf *p)
+{
+ struct drv_gmac *pOsMac;
+ Ft_Gmac_t *pGmac;
+ struct eth_device *pGmacParent;
+
+ err_t errval;
+ struct pbuf *q;
+ u8 *Buffer = NULL;
+ volatile FGmac_DmaDesc_t *DmaTxDesc;
+
+ u32 FrameLength = 0;
+ u32 BufferOffset = 0;
+ u32 BytesLeftToCopy = 0;
+ u32 PayLoadOffset = 0;
+
+ pGmacParent = rt_container_of(dev, struct eth_device, parent);
+ if (NULL == pGmacParent)
+ {
+ return -RT_ENOMEM;
+ }
+
+ pOsMac = rt_container_of(pGmacParent, struct drv_gmac, parent);
+ if (NULL == pOsMac)
+ {
+ return -RT_ENOMEM;
+ }
+
+ pGmac = &pOsMac->Gmac;
+ DmaTxDesc = &pGmac->TxDesc[pGmac->TxDescRingData.DescBufIndex];
+ Buffer = (u8 *)DmaTxDesc->Buffer1Addr;
+
+ if (Buffer == NULL)
+ {
+ LOG_E("Buffer is NULL \r\n");
+ RT_ASSERT(0)
+ }
+
+#if RT_LWIP_ETH_PAD_SIZE
+ pbuf_header(p, -RT_LWIP_ETH_PAD_SIZE); /* reclaim the padding word */
+#endif
+
+ for (q = p; q != NULL; q = q->next)
+ {
+ /* Is this buffer available? If not, goto error */
+ if ((DmaTxDesc->Status & DMA_TDES0_OWN) != 0)
+ {
+ errval = ERR_USE;
+ LOG_E("error errval = ERR_USE; \r\n");
+ goto error;
+ }
+
+ /* Get bytes in current lwIP buffer */
+ BytesLeftToCopy = q->len;
+ PayLoadOffset = 0;
+ /* Check if the length of data to copy is bigger than Tx buffer size*/
+ while ((BytesLeftToCopy + BufferOffset) > GMAC_MAX_PACKET_SIZE)
+ {
+ /* Copy data to Tx buffer*/
+ memcpy((u8 *)((u8 *)Buffer + BufferOffset), (u8 *)((u8 *)q->payload + PayLoadOffset), (GMAC_MAX_PACKET_SIZE - BufferOffset));
+ FCache_cpuDcacheClean((rt_uint32_t *)DmaTxDesc->Buffer1Addr, GMAC_MAX_PACKET_SIZE);
+ GMAC_INC_DESC(pGmac->TxDescRingData.DescBufIndex, pGmac->TxDescRingData.DescMaxNumber);
+ /* Point to next descriptor */
+ DmaTxDesc = &pGmac->TxDesc[pGmac->TxDescRingData.DescBufIndex];
+
+ /* Check if the Bufferis available */
+ if ((DmaTxDesc->Status & DMA_TDES0_OWN) != (u32)0)
+ {
+ errval = ERR_USE;
+ LOG_E("Check if the Bufferis available \r\n");
+ goto error;
+ }
+
+ Buffer = (u8 *)(DmaTxDesc->Buffer1Addr);
+ BytesLeftToCopy = BytesLeftToCopy - (GMAC_MAX_PACKET_SIZE - BufferOffset);
+ PayLoadOffset = PayLoadOffset + (GMAC_MAX_PACKET_SIZE - BufferOffset);
+ FrameLength = FrameLength + (GMAC_MAX_PACKET_SIZE - BufferOffset);
+ BufferOffset = 0;
+
+ if (Buffer == NULL)
+ {
+ LOG_E(" error Buffer is 0 \r\n");
+ RT_ASSERT(0)
+ }
+ }
+
+ /* Copy the remaining bytes */
+ memcpy((u8 *)((u8 *)Buffer + BufferOffset), (u8 *)((u8 *)q->payload + PayLoadOffset), BytesLeftToCopy);
+ BufferOffset = BufferOffset + BytesLeftToCopy;
+ FrameLength = FrameLength + BytesLeftToCopy;
+ }
+ /* 指向下一个位置 */
+ FCache_cpuDcacheClean((rt_uint32_t *)DmaTxDesc->Buffer1Addr, GMAC_MAX_PACKET_SIZE);
+ GMAC_INC_DESC(pGmac->TxDescRingData.DescBufIndex, pGmac->TxDescRingData.DescMaxNumber);
+#if RT_LWIP_ETH_PAD_SIZE
+ pbuf_header(p, RT_LWIP_ETH_PAD_SIZE); /* reclaim the padding word */
+#endif
+
+#ifdef ETH_TX_DUMP
+ dump_hex(Buffer, p->tot_len);
+#endif
+
+ FGmac_TransmitframeRingPoll(pGmac, FrameLength);
+error:
+ FGmac_SetTransmitUnderflow(pGmac);
+ return errval;
+}
+
+struct pbuf *rt_ft2004_gmac_rx(rt_device_t dev)
+{
+ struct drv_gmac *pOsMac;
+ Ft_Gmac_t *pGmac;
+ struct eth_device *pGmacParent;
+
+ struct pbuf *p = NULL;
+ struct pbuf *q = NULL;
+ u16 Length = 0;
+ u8 *Buffer;
+ volatile FGmac_DmaDesc_t *DmaRxDesc;
+ u32 BufferOffset = 0;
+ u32 PayLoadOffset = 0;
+ u32 BytesLeftToCopy = 0;
+ u32 DescBufIndex; /* For Current Desc buffer buf position */
+
+ pGmacParent = rt_container_of(dev, struct eth_device, parent);
+ if (NULL == pGmacParent)
+ {
+ return RT_NULL;
+ }
+
+ pOsMac = rt_container_of(pGmacParent, struct drv_gmac, parent);
+ if (NULL == pOsMac)
+ {
+ return RT_NULL;
+ }
+
+ pGmac = &pOsMac->Gmac;
+
+ /* get received frame */
+ if (FST_SUCCESS != FGmac_RingGetReceivedFrame_IT(pGmac))
+ {
+ return NULL;
+ }
+
+ DescBufIndex = pGmac->RxDescRingData.DescBufIndex;
+ Length = (pGmac->RxDesc[DescBufIndex].Status & DMA_RDES0_FRAME_LEN_MASK) >> DMA_RDES0_FRAME_LEN_SHIFT;
+ Buffer = (u8 *)pGmac->RxDesc[DescBufIndex].Buffer1Addr;
+
+#if RT_LWIP_ETH_PAD_SIZE
+ Length += RT_LWIP_ETH_PAD_SIZE; /* allow room for Ethernet padding */
+#endif
+
+ if (Length > 0)
+ {
+ /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */
+ p = pbuf_alloc(PBUF_RAW, Length, PBUF_POOL);
+ }
+
+#ifdef ETH_RX_DUMP
+ dump_hex(Buffer, (u32)Length);
+#endif
+
+ if (p != NULL)
+ {
+#if RT_LWIP_ETH_PAD_SIZE
+ pbuf_header(p, -RT_LWIP_ETH_PAD_SIZE); /* drop the padding word */
+#endif
+ DmaRxDesc = &pGmac->RxDesc[DescBufIndex];
+ BufferOffset = 0;
+ for (q = p; q != NULL; q = q->next)
+ {
+ BytesLeftToCopy = q->len;
+ PayLoadOffset = 0;
+ /* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size*/
+ while ((BytesLeftToCopy + BufferOffset) > GMAC_MAX_PACKET_SIZE)
+ {
+ /* Copy data to pbuf */
+ memcpy((u8 *)((u8 *)q->payload + PayLoadOffset), (u8 *)((u8 *)Buffer + BufferOffset), (GMAC_MAX_PACKET_SIZE - BufferOffset));
+
+ /* Point to next descriptor */
+ GMAC_INC_DESC(DescBufIndex, pGmac->RxDescRingData.DescMaxNumber);
+ if (DescBufIndex == pGmac->RxDescRingData.DescIndex)
+ {
+ break;
+ }
+
+ DmaRxDesc = &pGmac->RxDesc[DescBufIndex];
+ Buffer = (u8 *)(DmaRxDesc->Buffer1Addr);
+
+ BytesLeftToCopy = BytesLeftToCopy - (GMAC_MAX_PACKET_SIZE - BufferOffset);
+ PayLoadOffset = PayLoadOffset + (GMAC_MAX_PACKET_SIZE - BufferOffset);
+ BufferOffset = 0;
+ }
+ /* Copy remaining data in pbuf */
+ memcpy((u8 *)((u8 *)q->payload + PayLoadOffset), (u8 *)((u8 *)Buffer + BufferOffset), BytesLeftToCopy);
+ BufferOffset = BufferOffset + BytesLeftToCopy;
+ }
+
+#if RT_LWIP_ETH_PAD_SIZE
+ pbuf_header(p, RT_LWIP_ETH_PAD_SIZE); /* reclaim the padding word */
+#endif
+ }
+
+ /* Release descriptors to DMA */
+ /* Point to first descriptor */
+ DmaRxDesc = &pGmac->RxDesc[DescBufIndex];
+ /* Set Own bit in Rx descriptors: gives the buffers back to DMA */
+ for (DescBufIndex = pGmac->RxDescRingData.DescBufIndex; DescBufIndex != pGmac->RxDescRingData.DescIndex; GMAC_INC_DESC(DescBufIndex, pGmac->RxDescRingData.DescMaxNumber))
+ {
+ FCache_cpuDcacheInvalidate((rt_uint32_t *)pGmac->RxDesc[DescBufIndex].Buffer1Addr, GMAC_MAX_PACKET_SIZE);
+ DmaRxDesc->Status |= DMA_RDES0_OWN;
+ DmaRxDesc = &pGmac->RxDesc[DescBufIndex];
+ }
+
+ /* Sync index */
+ pGmac->RxDescRingData.DescBufIndex = pGmac->RxDescRingData.DescIndex;
+ FGmac_ResumeTransmissionReception(pGmac);
+
+ return p;
+}
+
+static void rt_ft2004_status_check(void *Args, u32 MacPhyStatus)
+{
+ struct drv_gmac *pOsMac;
+ pOsMac = (struct drv_gmac *)Args;
+
+ if (MacPhyStatus & 0x8)
+ {
+ rt_event_send(&pOsMac->link_event, FT_NETIF_LINKUP);
+ }
+ else
+ {
+ rt_event_send(&pOsMac->link_event, FT_NETIF_DOWN);
+ }
+}
+
+static void ethernet_link_thread(void *Args)
+{
+ struct drv_gmac *pOsMac;
+ rt_uint32_t status;
+ u32 LastStatus = FT_NETIF_DOWN;
+ u32 Flg;
+ if (RT_NULL == Args)
+ {
+ return;
+ }
+
+ pOsMac = (struct drv_gmac *)Args;
+
+ while (1)
+ {
+ status = 0;
+ if (rt_event_recv(&pOsMac->link_event, FT_NETIF_LINKUP | FT_NETIF_DOWN, RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_OR,
+ RT_WAITING_FOREVER, &status) != RT_EOK)
+ {
+ LOG_E("wait completed timeout");
+ continue;
+ }
+
+ if (status & FT_NETIF_DOWN)
+ {
+ eth_device_linkchange(&pOsMac->parent, RT_FALSE);
+ LastStatus = FT_NETIF_DOWN;
+ }
+ else if (status & FT_NETIF_LINKUP)
+ {
+ Flg = (LastStatus == FT_NETIF_LINKUP) ? 0 : 1;
+ LastStatus = FT_NETIF_LINKUP;
+ }
+ else
+ {
+ LOG_I(" EventGroup is error \r\n");
+ RT_ASSERT(0)
+ }
+
+ if (Flg)
+ {
+ Flg = 0;
+ // eth_device_linkchange(&pOsMac->parent, RT_FALSE);
+ LOG_I(" Start Linkup \r\n");
+ rt_ft2004_gmac_stop(pOsMac);
+ rt_ft2004_gmac_start(pOsMac);
+ LOG_I(" HardWare is ok \r\n");
+ if (LastStatus == FT_NETIF_LINKUP)
+ {
+ rt_thread_mdelay(5000);
+ eth_device_linkchange(&pOsMac->parent, RT_TRUE);
+ }
+ }
+ }
+}
+
+#ifdef BSP_USING_GMAC0
+struct drv_gmac os_drv_gmac0;
+static char *os_drv_gmac0_name = "gmac0";
+#endif
+
+#ifdef BSP_USING_GMAC1
+struct drv_gmac os_drv_gmac1;
+static char *os_drv_gmac1_name = "gmac1";
+
+#endif
+
+static int rt_hw_gmac_init(struct drv_gmac *pOsMac, const char *name)
+{
+ rt_err_t state = RT_EOK;
+ // rt_thread_t tid;
+ rt_gmacmem_free(pOsMac);
+ rt_gmacmem_create(pOsMac);
+
+ pOsMac->eth_speed = GMAC_SPEED_1000M;
+ pOsMac->eth_mode = GMAC_MODE_FULLDUPLEX;
+
+ pOsMac->parent.parent.init = rt_ft2004_gmac_init;
+ pOsMac->parent.parent.open = rt_ft2004_gmac_open;
+ pOsMac->parent.parent.close = rt_ft2004_gmac_close;
+ pOsMac->parent.parent.read = rt_ft2004_gmac_read;
+ pOsMac->parent.parent.write = rt_ft2004_gmac_write;
+ pOsMac->parent.parent.control = rt_ft2004_gmac_control;
+ pOsMac->parent.parent.user_data = RT_NULL;
+
+ pOsMac->parent.eth_rx = rt_ft2004_gmac_rx;
+ pOsMac->parent.eth_tx = rt_ft2004_gmac_tx;
+ Ft_Gmac_UseDefaultMacAddr(&pOsMac->Gmac, pOsMac->dev_addr);
+ state = rt_event_init(&pOsMac->link_event, name, RT_IPC_FLAG_FIFO);
+ LOG_I("rt_event_init is ok \r\n");
+ if (RT_EOK != state)
+ {
+ rt_kprintf("init gmac0 event failed.\n");
+ return -RT_ERROR;
+ }
+
+ /* register eth device */
+ state = eth_device_init(&(pOsMac->parent), name);
+ if (RT_EOK != state)
+ {
+ LOG_E("gmac device init faild: %d", state);
+ return -RT_ERROR;
+ }
+
+ state = rt_thread_init(&pOsMac->_link_thread,
+ name,
+ ethernet_link_thread,
+ pOsMac,
+ &pOsMac->_link_thread_stack[0],
+ sizeof(pOsMac->_link_thread_stack),
+ 10, 2);
+
+ if (RT_EOK == state)
+ {
+ rt_thread_startup(&pOsMac->_link_thread);
+ }
+ else
+ {
+ LOG_E("rt_thread_init is error");
+ return -RT_ERROR;
+ }
+
+ return RT_EOK;
+}
+
+static int rt_hw_ft2004_eth_init(void)
+{
+ rt_err_t state = RT_EOK;
+
+#ifdef BSP_USING_GMAC0
+ os_drv_gmac0.Gmac.Config.InstanceId = 0;
+ state = rt_hw_gmac_init(&os_drv_gmac0, os_drv_gmac0_name);
+ if (RT_EOK != state)
+ {
+ goto __exit;
+ }
+#endif
+
+#ifdef BSP_USING_GMAC1
+ os_drv_gmac1.Gmac.Config.InstanceId = 1;
+ state = rt_hw_gmac_init(&os_drv_gmac1, os_drv_gmac1_name);
+ if (RT_EOK != state)
+ {
+ goto __exit;
+ }
+#endif
+
+__exit:
+ return state;
+}
+
+INIT_DEVICE_EXPORT(rt_hw_ft2004_eth_init);
+
+#endif
diff --git a/bsp/ft2004/drivers/drv_eth.h b/bsp/ft2004/drivers/drv_eth.h
new file mode 100644
index 0000000000..ed68b71728
--- /dev/null
+++ b/bsp/ft2004/drivers/drv_eth.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2021-03-09 Carl the first version
+ */
+#ifndef __DRV_ETH_H__
+#define __DRV_ETH_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define FT_NETIF_LINKUP 0x1U
+#define FT_NETIF_DOWN 0x2U
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // !
diff --git a/bsp/ft2004/drivers/drv_log.h b/bsp/ft2004/drivers/drv_log.h
new file mode 100644
index 0000000000..3fe511789b
--- /dev/null
+++ b/bsp/ft2004/drivers/drv_log.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2018-11-15 SummerGift first version
+ */
+
+/*
+ * NOTE: DO NOT include this file on the header file.
+ */
+
+#ifndef LOG_TAG
+#define DBG_TAG "drv"
+#else
+#define DBG_TAG LOG_TAG
+#endif /* LOG_TAG */
+
+#ifdef DRV_DEBUG
+#define DBG_LVL DBG_LOG
+#else
+#define DBG_LVL DBG_INFO
+#endif /* DRV_DEBUG */
+
+#include <rtdbg.h>
diff --git a/bsp/ft2004/drivers/drv_qspi.c b/bsp/ft2004/drivers/drv_qspi.c
new file mode 100644
index 0000000000..9c5cbf4a9f
--- /dev/null
+++ b/bsp/ft2004/drivers/drv_qspi.c
@@ -0,0 +1,424 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2021-04-11 Carl the first version
+ */
+
+#include "drv_qspi.h"
+#include <rtthread.h>
+#include "rtdevice.h"
+#include "ft_qspi.h"
+#include "ft_parameters.h"
+
+#ifdef BSP_USE_QSPI
+
+#define DRV_DEBUG
+#define LOG_TAG "drv.qspi"
+#include <drv_log.h>
+
+struct ft2004_qspi_bus
+{
+ FQSpi_t fqspi;
+ char *name;
+ rt_uint32_t init; /* 1 is init already */
+};
+
+static struct rt_spi_bus _qspi_bus;
+static struct ft2004_qspi_bus _ft2004_qspi_bus;
+
+static int ft2004_qspi_init(struct rt_qspi_device *device, struct rt_qspi_configuration *qspi_cfg)
+{
+
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(qspi_cfg != RT_NULL);
+
+ // struct rt_spi_configuration *cfg = &qspi_cfg->parent;
+ struct ft2004_qspi_bus *qspi_bus_p = device->parent.bus->parent.user_data;
+
+ if (qspi_bus_p->init == 0)
+ {
+ qspi_bus_p->init = 1;
+ FQSpi_CfgInitialize(&qspi_bus_p->fqspi, FQSpi_LookupConfig(0));
+ }
+
+ return RT_EOK;
+}
+
+static rt_err_t ft2004_cmdOperation(struct ft2004_qspi_bus *qspi_bus_p, struct rt_spi_message *message)
+{
+ struct rt_qspi_message *qspi_message = (struct rt_qspi_message *)message;
+ const rt_uint8_t *sndb = message->send_buf;
+ rt_uint8_t *rcvb = message->recv_buf;
+ ft_error_t ret;
+ RT_ASSERT(qspi_bus_p != RT_NULL);
+ RT_ASSERT(message != RT_NULL);
+
+ struct FQSpi_CmdPack cmd_pack = {0};
+
+ if (qspi_message->instruction.qspi_lines == 0)
+ {
+ LOG_E("instruction is not valid");
+ return RT_ERROR;
+ }
+
+ cmd_pack.cmd = qspi_message->instruction.content;
+
+ if (qspi_message->address.qspi_lines != 0)
+ {
+ cmd_pack.flags |= FQSPI_CMD_NEED_ADDR_MASK;
+ cmd_pack.addr = qspi_message->address.content;
+ }
+
+ if (qspi_message->address.size == 24)
+ {
+ cmd_pack.flags |= FQSPI_CMD_ADDRESS_3BYTE_MASK;
+ }
+ else if (qspi_message->address.size == 32)
+ {
+ cmd_pack.flags |= FQSPI_CMD_ADDRESS_4BYTE_MASK;
+ }
+
+ if (qspi_message->qspi_data_lines != 0)
+ {
+ if (sndb && (message->length > 0))
+ {
+ cmd_pack.flags |= FQSPI_CMD_NEED_SET_MASK;
+ cmd_pack.txBuf = sndb;
+ cmd_pack.length = message->length;
+ }
+ else if (rcvb && (message->length > 0))
+ {
+ cmd_pack.flags |= FQSPI_CMD_NEED_GET_MASK;
+ cmd_pack.rxBuf = rcvb;
+ cmd_pack.length = message->length;
+ }
+ else
+ {
+ cmd_pack.flags &= ~(FQSPI_CMD_NEED_GET_MASK | FQSPI_CMD_NEED_SET_MASK);
+ }
+ }
+
+ if (qspi_message->dummy_cycles)
+ {
+ cmd_pack.flags |= FQSPI_CMD_NEED_DUMMY_MASK;
+ cmd_pack.dummyCycle = qspi_message->dummy_cycles;
+ }
+
+ if (cmd_pack.cmd == 0x20)
+ {
+ if (qspi_message->address.size == 32)
+ {
+ cmd_pack.cmd = 0xdc;
+ }
+ }
+
+#ifdef BSP_QSPI_DEBUG
+ LOG_I("flags %x", cmd_pack.flags);
+#endif
+
+ ret = FQSpi_CmdOperation(&qspi_bus_p->fqspi, &cmd_pack);
+
+#ifdef BSP_QSPI_DEBUG
+ if (ret == FQSPI_SUCCESS)
+ if (cmd_pack.cmd == 5)
+ {
+ LOG_I("cmd05 0x%x", cmd_pack.rxBuf[0]);
+ }
+#endif
+
+ return (ret == FQSPI_SUCCESS) ? RT_EOK : RT_ERROR;
+}
+
+static rt_uint32_t ft2004_qspi_xfer(struct ft2004_qspi_bus *qspi_bus_p, struct rt_spi_message *message)
+{
+ struct rt_qspi_message *qspi_message = (struct rt_qspi_message *)message;
+ rt_uint32_t ret_length = 0;
+ const rt_uint8_t *sndb = message->send_buf;
+ rt_uint8_t *rcvb = message->recv_buf;
+ rt_int32_t length = message->length;
+ rt_uint32_t cmd;
+ rt_uint32_t addr;
+ FQSpi_t *qspi_p;
+ FQSpi_Config_t *qspi_config_p;
+ struct FQSpi_DataPack data_pack = {0};
+ qspi_p = &qspi_bus_p->fqspi;
+ qspi_config_p = &qspi_bus_p->fqspi.config;
+
+ cmd = qspi_message->instruction.content;
+ addr = qspi_message->address.content;
+
+#ifdef BSP_QSPI_DEBUG
+ LOG_I("cmd is %x ", cmd);
+ LOG_I("length %d , rcvb %x sndb %x addr %x dummy_cycles %x ", length, rcvb, sndb, addr, qspi_message->dummy_cycles);
+#endif
+
+ if (qspi_config_p->channel >= FT_QSPI_MAX_CS_NUM)
+ {
+ LOG_E("invalid channel[%x] ", qspi_config_p->channel);
+ return RT_ERROR;
+ }
+ switch (cmd)
+ {
+ case FQSPI_FLASH_CMD_PP:
+ {
+ if (RT_NULL != sndb)
+ {
+ data_pack.cmd = cmd;
+ data_pack.addr = addr;
+ if (qspi_message->address.size == 24)
+ {
+ data_pack.flags |= FQSPI_DATA_ADDRESS_3BYTE_MASK;
+ }
+ else
+ {
+ data_pack.flags |= FQSPI_DATA_ADDRESS_4BYTE_MASK;
+ }
+
+ LOG_E("write flags %x ", data_pack.flags);
+ data_pack.txBuf = sndb;
+ data_pack.length = length;
+ ret_length = ((FQSpi_Write(qspi_p, &data_pack) == FQSPI_SUCCESS) ? length : 0);
+ }
+ else
+ {
+ LOG_E("pp cmd %x sndb is null", cmd);
+ ret_length = 0;
+ }
+ }
+ break;
+ case FQSPI_FLASH_CMD_WRDI: /* for sufd qspi fast read */
+ FQSpi_FlashRegSet(qspi_p, cmd, RT_NULL, 0);
+ case FQSPI_FLASH_CMD_READ:
+ {
+ if (RT_NULL != rcvb)
+ {
+ data_pack.cmd = FQSPI_FLASH_CMD_READ;
+ data_pack.addr = addr;
+ if (qspi_message->address.size == 24)
+ {
+ data_pack.flags |= FQSPI_DATA_ADDRESS_3BYTE_MASK;
+ }
+ else
+ {
+ data_pack.flags |= FQSPI_DATA_ADDRESS_4BYTE_MASK;
+ }
+
+ if (qspi_message->dummy_cycles)
+ {
+ data_pack.flags |= FQSPI_DATA_NEED_DUMMY_MASK;
+ data_pack.dummyCycle = qspi_message->dummy_cycles;
+ }
+ data_pack.rxBuf = rcvb;
+ data_pack.length = length;
+
+ ret_length = ((FQSpi_Read(qspi_p, &data_pack) == FQSPI_SUCCESS) ? length : 0);
+ }
+ else
+ {
+ // LOG_E("read cmd %x rcvb is null", cmd);
+ ret_length = 0;
+ }
+ }
+ break;
+
+ default:
+ {
+ if (ft2004_cmdOperation(qspi_bus_p, message) == RT_EOK)
+ {
+ ret_length = 1;
+ }
+ else
+ {
+ LOG_E("ft2004_cmdOperation error");
+ ret_length = 0;
+ }
+ }
+ }
+
+ return ret_length;
+}
+
+static rt_uint32_t qspixfer(struct rt_spi_device *device, struct rt_spi_message *message)
+{
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(device->bus != RT_NULL);
+ struct ft2004_qspi_bus *qspi_bus_p = device->bus->parent.user_data;
+
+ return ft2004_qspi_xfer(qspi_bus_p, message);
+}
+
+static rt_err_t qspi_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration)
+{
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(configuration != RT_NULL);
+
+ struct rt_qspi_device *qspi_device = (struct rt_qspi_device *)device;
+ return ft2004_qspi_init(qspi_device, &qspi_device->config);
+}
+
+static const struct rt_spi_ops ft2004_qspi_ops =
+ {
+ .configure = qspi_configure,
+ .xfer = qspixfer,
+};
+
+static int ft2004_qspi_register_bus(struct ft2004_qspi_bus *qspi_bus, const char *name)
+{
+ RT_ASSERT(qspi_bus != RT_NULL);
+ RT_ASSERT(name != RT_NULL);
+
+ _qspi_bus.parent.user_data = qspi_bus;
+ return rt_qspi_bus_register(&_qspi_bus, name, &ft2004_qspi_ops);
+}
+
+rt_err_t ft2004_qspi_bus_attach_device(const char *bus_name, const char *device_name, rt_uint8_t data_line_width, void (*enter_qspi_mode)(), void (*exit_qspi_mode)())
+{
+ struct rt_qspi_device *qspi_device = RT_NULL;
+ rt_err_t result = RT_EOK;
+
+ RT_ASSERT(bus_name != RT_NULL);
+ RT_ASSERT(device_name != RT_NULL);
+ RT_ASSERT(data_line_width == 1 || data_line_width == 2 || data_line_width == 4);
+
+ qspi_device = (struct rt_qspi_device *)rt_malloc(sizeof(struct rt_qspi_device));
+ if (qspi_device == RT_NULL)
+ {
+ LOG_E("no memory, qspi bus attach device failed!");
+ result = RT_ENOMEM;
+ goto __exit;
+ }
+
+ qspi_device->enter_qspi_mode = enter_qspi_mode;
+ qspi_device->exit_qspi_mode = exit_qspi_mode;
+ qspi_device->config.qspi_dl_width = data_line_width;
+
+ result = rt_spi_bus_attach_device(&qspi_device->parent, device_name, bus_name, RT_NULL);
+
+__exit:
+ if (result != RT_EOK)
+ {
+ if (qspi_device)
+ {
+ rt_free(qspi_device);
+ }
+ }
+
+ return result;
+}
+
+static int rt_hw_qspi_bus_init(void)
+{
+ return ft2004_qspi_register_bus(&_ft2004_qspi_bus, FT2004_QSPI_NAME);
+}
+INIT_BOARD_EXPORT(rt_hw_qspi_bus_init);
+#ifdef BSP_QSPI_DEBUG
+static void cmd05_check(void)
+{
+ struct FQSpi_CmdPack cmd_pack = {0};
+ u8 rx_buffer[1];
+
+ cmd_pack.cmd = 0x6;
+ FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
+
+ rt_memset(&cmd_pack, 0, sizeof(&cmd_pack));
+ cmd_pack.cmd = 0x5;
+ cmd_pack.flags = FQSPI_CMD_NEED_GET_MASK;
+ cmd_pack.rxBuf = rx_buffer;
+ cmd_pack.length = sizeof(rx_buffer);
+
+ FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
+
+ for (u32 i = 0; i < cmd_pack.length; i++)
+ {
+ LOG_I("cnt %d, 0x%x ", i, rx_buffer[i]);
+ }
+
+ rt_memset(&cmd_pack, 0, sizeof(&cmd_pack));
+ cmd_pack.cmd = 0x4;
+ FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
+
+ rt_memset(&cmd_pack, 0, sizeof(&cmd_pack));
+ cmd_pack.cmd = 0x5;
+ cmd_pack.flags = FQSPI_CMD_NEED_GET_MASK;
+ cmd_pack.rxBuf = rx_buffer;
+ cmd_pack.length = sizeof(rx_buffer);
+
+ FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
+
+ for (u32 i = 0; i < cmd_pack.length; i++)
+ {
+ LOG_I("cnt %d, 0x%x ", i, rx_buffer[i]);
+ }
+}
+MSH_CMD_EXPORT_ALIAS(cmd05_check, cmd05_check, cmd05_check);
+#endif
+
+#ifdef BSP_QSPI_DEBUG
+static void cmd35_check(void)
+{
+ struct FQSpi_CmdPack cmd_pack = {0};
+ u8 rx_buffer[1];
+
+ cmd_pack.cmd = 0x6;
+ FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
+
+ rt_memset(&cmd_pack, 0, sizeof(&cmd_pack));
+ cmd_pack.cmd = 0x5;
+ cmd_pack.flags = FQSPI_CMD_NEED_GET_MASK;
+ cmd_pack.rxBuf = rx_buffer;
+ cmd_pack.length = sizeof(rx_buffer);
+
+ FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
+
+ for (u32 i = 0; i < cmd_pack.length; i++)
+ {
+ LOG_I("cnt %d, 0x%x ", i, rx_buffer[i]);
+ }
+
+ cmd_pack.cmd = 0xB7;
+ FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
+
+ rt_memset(&cmd_pack, 0, sizeof(&cmd_pack));
+ cmd_pack.cmd = 0x35;
+ cmd_pack.flags = FQSPI_CMD_NEED_GET_MASK;
+ cmd_pack.rxBuf = rx_buffer;
+ cmd_pack.length = sizeof(rx_buffer);
+
+ FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
+
+ for (u32 i = 0; i < cmd_pack.length; i++)
+ {
+ LOG_I("cnt %d, 0x%x ", i, rx_buffer[i]);
+ }
+}
+MSH_CMD_EXPORT_ALIAS(cmd35_check, cmd35_check, cmd35_check);
+#endif
+#ifdef BSP_QSPI_DEBUG
+static void cmd15_check(void)
+{
+ struct FQSpi_CmdPack cmd_pack = {0};
+ u8 rx_buffer[1];
+
+ // cmd_pack.cmd = 0xB7;
+ // FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
+
+ rt_memset(&cmd_pack, 0, sizeof(&cmd_pack));
+ cmd_pack.cmd = 0x15;
+ cmd_pack.flags = FQSPI_CMD_NEED_GET_MASK;
+ cmd_pack.rxBuf = rx_buffer;
+ cmd_pack.length = sizeof(rx_buffer);
+
+ FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
+
+ for (u32 i = 0; i < cmd_pack.length; i++)
+ {
+ LOG_I("cnt %d, 0x%x ", i, rx_buffer[i]);
+ }
+}
+MSH_CMD_EXPORT_ALIAS(cmd15_check, cmd15_check, cmd15_check);
+#endif
+#endif
diff --git a/bsp/ft2004/drivers/drv_qspi.h b/bsp/ft2004/drivers/drv_qspi.h
new file mode 100644
index 0000000000..29566f9af6
--- /dev/null
+++ b/bsp/ft2004/drivers/drv_qspi.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2021-04-11 Carl the first version
+ */
+
+#ifndef __DRT_QSPI_H__
+#define __DRT_QSPI_H__
+
+#include <rtthread.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define FT2004_QSPI_NAME "qspi"
+
+ rt_err_t ft2004_qspi_bus_attach_device(const char *bus_name, const char *device_name, rt_uint8_t data_line_width, void (*enter_qspi_mode)(), void (*exit_qspi_mode)());
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // !DRT_QSPI_H
diff --git a/bsp/ft2004/drivers/drv_qspi_flash.c b/bsp/ft2004/drivers/drv_qspi_flash.c
new file mode 100644
index 0000000000..102cd5fc5b
--- /dev/null
+++ b/bsp/ft2004/drivers/drv_qspi_flash.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2021-04-08 Carl the first version
+ */
+
+#include <board.h>
+#include <drv_qspi.h>
+#include <rtdevice.h>
+#include <rthw.h>
+#include <finsh.h>
+
+#ifdef BSP_USE_QSPI
+
+#include "spi_flash.h"
+#include "spi_flash_sfud.h"
+#define _QSPI_DEVICE_NAME "qspiflash"
+
+static int
+rt_hw_qspi_flash_with_sfud_init(void)
+{
+ ft2004_qspi_bus_attach_device(FT2004_QSPI_NAME, _QSPI_DEVICE_NAME, 1, RT_NULL, RT_NULL);
+
+ /* init gd */
+ rt_kprintf("start rt_sfud_flash_probe \r\n");
+ if (RT_NULL == rt_sfud_flash_probe("GD25LQ256D", _QSPI_DEVICE_NAME))
+ {
+ return -RT_ERROR;
+ }
+
+ return RT_EOK;
+}
+INIT_COMPONENT_EXPORT(rt_hw_qspi_flash_with_sfud_init);
+
+#endif /* BSP_USING_QSPI_FLASH */
diff --git a/bsp/ft2004/drivers/drv_sdcard.c b/bsp/ft2004/drivers/drv_sdcard.c
new file mode 100644
index 0000000000..a6494089f6
--- /dev/null
+++ b/bsp/ft2004/drivers/drv_sdcard.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2021-03-18 Carl the first version
+ */
+
+#include <rtthread.h>
+
+#ifdef BSP_USING_SDC
+
+#include <dfs_elm.h>
+#include <dfs_fs.h>
+#include <dfs_posix.h>
+#include "drv_sdctrl.h"
+
+#define DBG_TAG "app.card"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+static rt_err_t _sdcard_mount(void)
+{
+ rt_device_t device;
+
+ device = rt_device_find("sd0");
+ rt_kprintf("rt_device_find %x \r\n", device);
+ if (device == NULL)
+ {
+ mmcsd_wait_cd_changed(0);
+ ft2004_mmcsd_change();
+ if (mmcsd_wait_cd_changed(rt_tick_from_millisecond(5000)) == -RT_ETIMEOUT)
+ {
+ rt_kprintf("timeout \r\n");
+ return RT_ERROR;
+ }
+ device = rt_device_find("sd0");
+ }
+
+ rt_thread_mdelay(1000);
+ LOG_I("dfs_mount \r\n");
+ if (device != RT_NULL)
+ {
+ if (dfs_mount("sd0", "/", "elm", 0, 0) == RT_EOK)
+ {
+ LOG_I("sd card mount to '/'");
+ }
+ else
+ {
+ LOG_W("sd card mount to '/' failed!");
+ return RT_ERROR;
+ }
+ }
+
+ return RT_EOK;
+}
+
+static void _sdcard_unmount(void)
+{
+ rt_thread_mdelay(200);
+ dfs_unmount("/");
+ LOG_I("Unmount \"/\"");
+
+ mmcsd_wait_cd_changed(0);
+ ft2004_mmcsd_change();
+ mmcsd_wait_cd_changed(rt_tick_from_millisecond(5000));
+ LOG_I("Unmount is over \r\n");
+}
+
+static void sd_mount(void *parameter)
+{
+ rt_uint8_t state = 0; /* 1. is valid card ,0 is removal */
+#ifdef BSP_SDC_IRQ_CARD_REMOVE
+ rt_uint32_t status;
+#endif
+ while (1)
+ {
+ switch (state)
+ {
+ case 0:
+ if (ft2004_card_status() == 1)
+ {
+#ifdef BSP_SDC_IRQ_CARD_REMOVE
+ ft2004_card_remove_check(0, RT_NULL); /* Clear removal flag bit */
+#endif
+ if (_sdcard_mount() == RT_EOK)
+ {
+ state = 1;
+ }
+ else
+ {
+ /* For the critical case of frequent plug */
+ rt_kprintf("dfs_unmount \r\n");
+ _sdcard_unmount();
+ ft2004_sdctrl_reset();
+ }
+ }
+ else
+ {
+ rt_thread_mdelay(100);
+ }
+ break;
+ case 1:
+
+#ifdef BSP_SDC_IRQ_CARD_REMOVE
+ if (ft2004_card_remove_check(RT_WAITING_FOREVER, &status) == RT_EOK)
+ {
+ if (status & SDCTR_CARD_REMOVE_FLG)
+ {
+ state = 0;
+ _sdcard_unmount();
+ }
+ }
+#else
+ if (ft2004_card_status() == 0)
+ {
+ state = 0;
+ _sdcard_unmount();
+ }
+#endif
+ else
+ {
+ rt_thread_mdelay(100);
+ }
+ break;
+ default:
+ state = 0;
+ break;
+ }
+ }
+}
+
+int ft2004_sdcard_mount(void)
+{
+ rt_thread_t tid;
+
+ tid = rt_thread_create("sd_mount", sd_mount, RT_NULL,
+ 8192, 2, 20);
+
+ if (tid != RT_NULL)
+ {
+ rt_thread_startup(tid);
+ }
+ else
+ {
+ LOG_E("create sd_mount thread err!");
+ }
+ return RT_EOK;
+}
+INIT_APP_EXPORT(ft2004_sdcard_mount);
+
+#endif /* BSP_USING_SDCARD */
diff --git a/bsp/ft2004/drivers/drv_sdctrl.c b/bsp/ft2004/drivers/drv_sdctrl.c
new file mode 100644
index 0000000000..1f6a4df7e5
--- /dev/null
+++ b/bsp/ft2004/drivers/drv_sdctrl.c
@@ -0,0 +1,659 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2021-03-18 Carl the first version
+ */
+
+#include "drv_sdctrl.h"
+#include "ft_sdctrl_hw.h"
+#include "ft_sdctrl.h"
+#include "ft_debug.h"
+#include "ft_types.h"
+#include "ft_generic_timer.h"
+#include <drivers/mmcsd_core.h>
+#include "interrupt.h"
+#include "rtconfig.h"
+#include "ft_cache.h"
+
+#ifdef BSP_USING_SDC
+
+#define LOG_TAG "drv.sdmmc"
+#include <drv_log.h>
+
+#define RTHW_SDCTRL_LOCK(_sdctrl) rt_mutex_take(&_sdctrl->mutex, RT_WAITING_FOREVER)
+#define RTHW_SDCTRL_UNLOCK(_sdctrl) rt_mutex_release(&_sdctrl->mutex);
+
+struct mmcsd_pkg
+{
+ struct rt_mmcsd_cmd *cmd;
+ void *buff;
+ rt_uint32_t flag;
+};
+
+typedef struct
+{
+ FtsdCtrl_t ft_sdctrl;
+ struct rt_mmcsd_host *host;
+ struct rt_event event;
+ struct rt_mutex mutex;
+ struct mmcsd_pkg *pkg;
+} ft_sdctrl_class_t;
+
+ft_sdctrl_class_t sdctrl_class;
+
+ALIGN(SDCTR_ALIGN_LEN)
+static rt_uint8_t cache_buf[SDCTR_BUFF_SIZE];
+
+static void rthw_sdctrl_send_command(ft_sdctrl_class_t *class_p, struct mmcsd_pkg *pkg);
+
+static void demo_dump_sdc(void)
+{
+ Ft_DumpHexWord((const rt_uint32_t *)(0x28207C00), 256);
+}
+MSH_CMD_EXPORT_ALIAS(demo_dump_sdc, dump_sdc, output all dump_sdc);
+
+static void rthw_sdctrl_delay(u32 delayCnt)
+{
+ Ft_GenericTimer_UsDelay(delayCnt);
+}
+
+static u32 rthw_sdctrl_rasp2type(u32 rasp)
+{
+
+ switch (rasp)
+ {
+ case RESP_NONE:
+ return FTSDCTRL_CMD_RES_NONE;
+ case RESP_R2:
+ return FTSDCTRL_CMD_RES_LONG;
+ default:
+ return FTSDCTRL_CMD_RES_SHORT;
+ }
+
+ return FTSDCTRL_CMD_RES_SHORT;
+}
+
+static void rthw_sdctrl_transfer_by_dma(ft_sdctrl_class_t *class_p, struct mmcsd_pkg *pkg)
+{
+ struct rt_mmcsd_data *data;
+ struct rt_mmcsd_cmd *cmd;
+ u32 rasp;
+ u32 *buff;
+ FtsdCtrl_t *ft_sdctrl_p;
+
+ if ((RT_NULL == class_p))
+ {
+ LOG_E("rthw_sdctrl_transfer_by_dma invalid class_p");
+ return;
+ }
+ ft_sdctrl_p = &class_p->ft_sdctrl;
+
+ if ((RT_NULL == pkg))
+ {
+ LOG_E("rthw_sdctrl_transfer_by_dma invalid args");
+ return;
+ }
+
+ data = pkg->cmd->data;
+ if (RT_NULL == data)
+ {
+ LOG_E("rthw_sdctrl_transfer_by_dma invalid args");
+ return;
+ }
+
+ buff = pkg->buff;
+ if (RT_NULL == buff)
+ {
+ LOG_E("rthw_sdctrl_transfer_by_dma invalid args");
+ return;
+ }
+
+ cmd = pkg->cmd;
+ rasp = resp_type(pkg->cmd);
+ rasp = rthw_sdctrl_rasp2type(rasp);
+
+ if (data->flags & DATA_DIR_WRITE)
+ {
+#ifdef BSP_SDC_DEBUG_PRINT
+ rt_kprintf("DATA_DIR_WRITE %x \r\n", cmd->arg);
+#endif
+ FCache_cpuDcacheClean(buff, data->blks * data->blksize);
+
+ /* data, card, blk: card : data + blk */
+ FSdCtrl_WriteData(ft_sdctrl_p, (UINTPTR)buff, cmd->arg, data->blks);
+ cmd->err = FSdCtrl_WaitCmdEnd(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay, rasp, cmd->resp);
+
+#ifdef BSP_SDC_DEBUG_PRINT
+ for (int i = 0; i < 4; i++)
+ {
+ rt_kprintf("cmdRsp[%d] %x \r\n", i, cmd->resp[i]);
+ }
+ Ft_DumpHexWord(buff, 256);
+#endif
+ FSdCtrl_WaitWriteDataEnd(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay, data->blks);
+ FCache_cpuDcacheInvalidate(buff, data->blks * data->blksize);
+ }
+ else if (data->flags & DATA_DIR_READ)
+ {
+#ifdef BSP_SDC_DEBUG_PRINT
+ rt_kprintf("DATA_DIR_READ %x \r\n", cmd->arg);
+#endif
+ if ((cmd->flags & CMD_ADTC) && (data->blksize < 512))
+ {
+#ifdef BSP_SDC_DEBUG_PRINT
+ LOG_E("CMD_ADTC \r\n");
+#endif
+ FSdCtrl_DoACmd(ft_sdctrl_p, cmd->cmd_code, rasp, cmd->arg);
+ rt_thread_mdelay(10);
+ }
+
+ FCache_cpuDcacheInvalidate(buff, data->blks * data->blksize);
+ FSdCtrl_ReadData(ft_sdctrl_p, (UINTPTR)buff, cmd->arg, data->blks);
+ cmd->err = FSdCtrl_WaitCmdEnd(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay, rasp, cmd->resp);
+#ifdef BSP_SDC_DEBUG_PRINT
+ for (int i = 0; i < 4; i++)
+ {
+ rt_kprintf("cmdRsp[%d] %x \r\n", i, cmd->resp[i]);
+ }
+#endif
+ FSdCtrl_WaitReadDataEnd(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay, data->blks);
+ FCache_cpuDcacheClean(buff, data->blks * data->blksize);
+#ifdef BSP_SDC_DEBUG_PRINT
+ Ft_DumpHexWord(buff, data->blks * data->blksize);
+#endif
+ }
+}
+
+static void rthw_sdctrl_docmd(ft_sdctrl_class_t *class_p, struct mmcsd_pkg *pkg)
+{
+ struct rt_mmcsd_cmd *cmd;
+ u32 rasp;
+ FtsdCtrl_t *ft_sdctrl_p;
+
+ if ((RT_NULL == class_p))
+ {
+ LOG_E("rthw_sdctrl_docmd invalid class_p");
+ return;
+ }
+
+ ft_sdctrl_p = &class_p->ft_sdctrl;
+
+ if ((RT_NULL == pkg))
+ {
+ LOG_E("rthw_sdctrl_docmd invalid args");
+ return;
+ }
+
+ cmd = pkg->cmd;
+ rasp = resp_type(pkg->cmd);
+ rasp = rthw_sdctrl_rasp2type(rasp);
+ FSdCtrl_DoCmd(ft_sdctrl_p, pkg->cmd->cmd_code, rasp, cmd->arg);
+ cmd->err = FSdCtrl_WaitCmdEnd(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay, rasp, cmd->resp);
+
+#ifdef BSP_SDC_DEBUG_PRINT
+ for (int i = 0; i < 4; i++)
+ {
+ rt_kprintf("cmdRsp[%d] %x \r\n", i, cmd->resp[i]);
+ }
+#endif
+}
+
+static void rthw_sdctrl_send_command(ft_sdctrl_class_t *class_p, struct mmcsd_pkg *pkg)
+{
+ struct rt_mmcsd_cmd *cmd = pkg->cmd;
+ struct rt_mmcsd_data *data = cmd->data;
+ /* save pkg */
+ class_p->pkg = pkg;
+
+ /* config data reg */
+ if (data != RT_NULL && data->blks)
+ {
+ /* transfer config */
+ rthw_sdctrl_transfer_by_dma(class_p, pkg);
+ }
+ else
+ {
+ rthw_sdctrl_docmd(class_p, pkg);
+ }
+}
+
+/**
+ * @brief This function send sdio request.
+ * @param host rt_mmcsd_host
+ * @param req request
+ * @retval None
+ */
+static void rthw_sdctrl_request(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
+{
+ struct mmcsd_pkg pkg;
+ ft_sdctrl_class_t *class_p = host->private_data;
+ struct rt_mmcsd_data *data;
+
+ RTHW_SDCTRL_LOCK(class_p);
+ if (req->cmd != RT_NULL)
+ {
+ rt_memset(&pkg, 0, sizeof(pkg));
+ data = req->cmd->data;
+ pkg.cmd = req->cmd;
+
+ if (pkg.cmd->cmd_code == 5 || pkg.cmd->cmd_code == 1)
+ {
+ rt_kprintf("cmd_code is not vaild %x \r\n", pkg.cmd->cmd_code);
+ pkg.cmd->err = RT_EINVAL;
+ goto _exit;
+ }
+
+#ifdef BSP_SDC_DEBUG_PRINT
+ struct rt_mmcsd_cmd *cmd;
+ cmd = req->cmd;
+ LOG_E("CMD:%d ARG:0x%08x RES:%s%s%s%s%s%s%s%s%s rw:%c len:%d blksize:%d",
+ cmd->cmd_code,
+ cmd->arg,
+ resp_type(cmd) == RESP_NONE ? "NONE" : "",
+ resp_type(cmd) == RESP_R1 ? "R1" : "",
+ resp_type(cmd) == RESP_R1B ? "R1B" : "",
+ resp_type(cmd) == RESP_R2 ? "R2" : "",
+ resp_type(cmd) == RESP_R3 ? "R3" : "",
+ resp_type(cmd) == RESP_R4 ? "R4" : "",
+ resp_type(cmd) == RESP_R5 ? "R5" : "",
+ resp_type(cmd) == RESP_R6 ? "R6" : "",
+ resp_type(cmd) == RESP_R7 ? "R7" : "",
+ data ? (data->flags & DATA_DIR_WRITE ? 'w' : 'r') : '-',
+ data ? data->blks * data->blksize : 0,
+ data ? data->blksize : 0);
+#endif
+
+ if (data != RT_NULL)
+ {
+ rt_uint32_t size = data->blks * data->blksize;
+
+ RT_ASSERT(size <= SDCTR_BUFF_SIZE);
+ pkg.buff = data->buf;
+ if ((rt_uint32_t)data->buf & (SDCTR_ALIGN_LEN - 1))
+ {
+ pkg.buff = cache_buf;
+ if (data->flags & DATA_DIR_WRITE)
+ {
+ rt_memcpy(cache_buf, data->buf, size);
+ }
+ }
+ }
+
+ rthw_sdctrl_send_command(class_p, &pkg);
+
+ if ((data != RT_NULL) && (data->flags & DATA_DIR_READ) && ((rt_uint32_t)data->buf & (SDCTR_ALIGN_LEN - 1)))
+ {
+ rt_memcpy(data->buf, cache_buf, data->blksize * data->blks);
+ }
+ }
+
+ if (req->stop != RT_NULL)
+ {
+ rt_memset(&pkg, 0, sizeof(pkg));
+ pkg.cmd = req->stop;
+ rthw_sdctrl_send_command(class_p, &pkg);
+ }
+
+_exit:
+
+ RTHW_SDCTRL_UNLOCK(class_p);
+ mmcsd_req_complete(class_p->host);
+}
+
+static void rthw_sdctrl_clk_divider(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
+{
+ ft_sdctrl_class_t *class_p = host->private_data;
+ FtsdCtrl_t *sd_ctrl = &(class_p->ft_sdctrl);
+
+ /* bus mode is pull push */
+ FSdCtrl_ClkFreqSetup(sd_ctrl, io_cfg->clock);
+ return;
+}
+
+static void rthw_sdctrl_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
+{
+ ft_sdctrl_class_t *class_p = host->private_data;
+ RTHW_SDCTRL_LOCK(class_p);
+
+ /* calculate and set clk divider */
+ rthw_sdctrl_clk_divider(host, io_cfg);
+
+ RTHW_SDCTRL_UNLOCK(class_p);
+}
+
+rt_int32_t rthw_sdctrl_detect(struct rt_mmcsd_host *host)
+{
+ ft_sdctrl_class_t *class_p = host->private_data;
+
+ return FSdCtrl_CardDetect(&class_p->ft_sdctrl);
+}
+
+static const struct rt_mmcsd_host_ops ops =
+ {
+ rthw_sdctrl_request,
+ rthw_sdctrl_iocfg,
+ rthw_sdctrl_detect,
+ RT_NULL,
+};
+
+void rthw_sdctrl_nomarl_callback(void *args)
+{
+ FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)args;
+ rt_uint32_t status;
+ ft_sdctrl_class_t *class_p;
+ if (RT_NULL == pFtsdCtrl)
+ {
+ return;
+ }
+
+ class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl);
+
+ status = FSdCtrl_GetNormalIrqStatus(pFtsdCtrl);
+
+ if (status & NORMAL_INT_STATUS_CR)
+ {
+ rt_event_send(&class_p->event, SDCTR_CARD_REMOVE_FLG);
+ }
+ else if (status & NORMAL_INT_STATUS_CC)
+ {
+ rt_event_send(&class_p->event, SDCTR_CMD_IS_COMPLETE_FLG);
+ }
+ else if (status & NORMAL_INT_STATUS_EI)
+ {
+ rt_event_send(&class_p->event, SDCTR_CMD_IS_ERROR_FLG);
+ }
+
+ return;
+}
+
+void rthw_sdctrl_dma_callback(void *args)
+{
+ FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)args;
+ rt_uint32_t status;
+ ft_sdctrl_class_t *class_p;
+
+ if (RT_NULL == pFtsdCtrl)
+ {
+ return;
+ }
+
+ class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl);
+
+ status = FSdCtrl_GetDataIrqStatus(pFtsdCtrl);
+
+ if (status & BD_ISR_REG_TRS)
+ {
+ /* send write complete event */
+ rt_event_send(&class_p->event, SDCTR_WRITE_IS_COMPLETE_FLG);
+ }
+
+ if (status & BD_ISR_REG_RESPE)
+ {
+ /* send read complete event */
+ rt_event_send(&class_p->event, SDCTR_READ_IS_COMPLETE_FLG);
+ }
+
+ if (status & BD_ISR_REG_DAIS)
+ {
+ /* send dma errror event */
+ rt_event_send(&class_p->event, SDCTR_DMA_IS_ERROR_FLG);
+ }
+}
+
+void rthw_sdctrl_error_callback(void *args)
+{
+ FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)args;
+ rt_uint32_t status;
+ ft_sdctrl_class_t *class_p;
+
+ if (RT_NULL == pFtsdCtrl)
+ {
+ return;
+ }
+
+ class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl);
+
+ status = FSdCtrl_GetErrorIrqStatus(pFtsdCtrl);
+
+ if (status & SDCTR_CMD_TIMEOUT_FLG)
+ {
+ rt_event_send(&class_p->event, SDCTR_CMD_TIMEOUT_FLG);
+ }
+
+ if (status & ERROR_INT_EN_CNR)
+ {
+ rt_event_send(&class_p->event, SDCTR_CMD_RECEIVE_IS_ERROR_FLG);
+ }
+
+ if (status & ERROR_INT_EN_CCRCE)
+ {
+ rt_event_send(&class_p->event, SDCTR_CMD_CRC_IS_ERROR_FLG);
+ }
+}
+
+void rthw_sdctrl_normal_irq(int vector, void *param)
+{
+ FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)param;
+ FSdCtrl_NormalIrq(pFtsdCtrl);
+}
+
+void rthw_sdctrl_dma_irq(int vector, void *param)
+{
+ FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)param;
+ FSdCtrl_DmaIrq(pFtsdCtrl);
+}
+
+void rthw_sdctrl_err_irq(int vector, void *param)
+{
+ FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)param;
+ FSdCtrl_ErrIrq(pFtsdCtrl);
+}
+
+ft_error_t rthw_sdctrl_cmd_wait(FtsdCtrl_t *pFtsdCtrl)
+{
+ rt_uint32_t status;
+ ft_sdctrl_class_t *class_p;
+
+ if (RT_NULL == pFtsdCtrl)
+ {
+ return FTSDC_INVALID_PARAM;
+ }
+
+ class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl);
+
+ if (rt_event_recv(&class_p->event, SDCTR_CMD_IS_COMPLETE_FLG | SDCTR_CMD_IS_ERROR_FLG | SDCTR_CMD_CRC_IS_ERROR_FLG, RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_OR,
+ rt_tick_from_millisecond(50000), &status) != RT_EOK)
+ {
+ /* wait cmd completed timeout */
+ LOG_E("wait cmd completed timeout");
+ return FTSDC_TIMEOUT;
+ }
+
+ if (SDCTR_CMD_IS_COMPLETE_FLG == (status & SDCTR_CMD_IS_COMPLETE_FLG))
+ {
+ return FTSDC_SUCCESS;
+ }
+ else
+ {
+ LOG_E("wait cmd is error %x ", status);
+ return FTSDC_FAILURE;
+ }
+}
+
+ft_error_t rthw_sdctrl_read_wait(FtsdCtrl_t *pFtsdCtrl)
+{
+ rt_uint32_t status;
+ ft_sdctrl_class_t *class_p;
+
+ if (RT_NULL == pFtsdCtrl)
+ {
+ return FTSDC_INVALID_PARAM;
+ }
+
+ class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl);
+
+ if (rt_event_recv(&class_p->event, SDCTR_READ_IS_COMPLETE_FLG | SDCTR_CMD_RECEIVE_IS_ERROR_FLG,
+ RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_OR,
+ rt_tick_from_millisecond(50000), &status) != RT_EOK)
+ {
+ /* wait read completed timeout */
+ LOG_E("wait read completed timeout");
+ return FTSDC_TIMEOUT;
+ }
+
+ if (SDCTR_READ_IS_COMPLETE_FLG == (status & SDCTR_READ_IS_COMPLETE_FLG))
+ {
+ return FTSDC_SUCCESS;
+ }
+ else
+ {
+ LOG_E("wait read is error %x ", status);
+ return FTSDC_FAILURE;
+ }
+}
+
+ft_error_t rthw_sdctrl_write_wait(FtsdCtrl_t *pFtsdCtrl)
+{
+ rt_uint32_t status;
+ ft_sdctrl_class_t *class_p;
+
+ if (RT_NULL == pFtsdCtrl)
+ {
+ return FTSDC_INVALID_PARAM;
+ }
+
+ class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl);
+
+ if (rt_event_recv(&class_p->event, SDCTR_WRITE_IS_COMPLETE_FLG, RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_OR,
+ rt_tick_from_millisecond(50000), &status) != RT_EOK)
+ {
+ /* wait write completed timeout */
+ LOG_E("wait write completed timeout");
+ return FTSDC_TIMEOUT;
+ }
+
+ if (SDCTR_WRITE_IS_COMPLETE_FLG == (status & SDCTR_WRITE_IS_COMPLETE_FLG))
+ {
+ return FTSDC_SUCCESS;
+ }
+ else
+ {
+ LOG_E("wait write is error %x ", status);
+ return FTSDC_FAILURE;
+ }
+}
+
+static rt_err_t rthw_sdctrl_create(ft_sdctrl_class_t *class_p)
+{
+ struct rt_mmcsd_host *host;
+
+ host = mmcsd_alloc_host();
+ if (host == RT_NULL)
+ {
+ LOG_E("L:%d F:%s mmcsd alloc host fail");
+ return RT_ENOMEM;
+ }
+
+ class_p->ft_sdctrl.config = *(FSdCtrl_Config_t *)FSdCtrl_LookupConfig(0);
+ rt_event_init(&class_p->event, "sdctrl", RT_IPC_FLAG_FIFO);
+ rt_mutex_init(&class_p->mutex, "sdctrl", RT_IPC_FLAG_FIFO);
+
+ class_p->host = host;
+ host->ops = &ops;
+ /* range of sd work speed */
+ host->freq_min = 400 * 1000;
+ host->freq_max = 48 * 1000000;
+ host->valid_ocr = 0X00FFFF80; /* The voltage range supported is 1.65v-3.6v */
+ host->flags = MMCSD_BUSWIDTH_4;
+ host->private_data = class_p;
+ /* ready to change */
+
+ return RT_EOK;
+}
+
+int rthw_sdctrl_init(void)
+{
+
+ FtsdCtrl_t *ft_sdctrl_p;
+#ifdef BSP_SDC_USE_IRQ
+ FSdCtrl_Config_t *config_p;
+ FSdCtrl_NormalIrqSelect_t normalIrqFlgs = 0;
+#endif
+
+ rt_kprintf("rthw_sdctrl_init \r\n");
+ RT_ASSERT(rthw_sdctrl_create(&sdctrl_class) == RT_EOK);
+ ft_sdctrl_p = &sdctrl_class.ft_sdctrl;
+
+ FSdCtrl_Reset(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay);
+ FsdCtrl_Init(ft_sdctrl_p);
+
+#ifdef BSP_SDC_USE_IRQ
+ config_p = &ft_sdctrl_p->config;
+#ifdef BSP_SDC_IRQ_CARD_REMOVE
+ normalIrqFlgs |= NORMAL_IRQ_CR;
+
+#endif
+ normalIrqFlgs |= NORMAL_IRQ_CC;
+ /* register handler、irq enable bit and wait callback */
+ FSdCtrl_SetHandler(ft_sdctrl_p, FTSDCTRL_CMDIRQID, rthw_sdctrl_nomarl_callback, ft_sdctrl_p);
+ FSdCtrl_NormalIrqSet(ft_sdctrl_p, normalIrqFlgs);
+ FSdCtrl_CmdWaitRegister(ft_sdctrl_p, rthw_sdctrl_cmd_wait);
+
+ FSdCtrl_SetHandler(ft_sdctrl_p, FTSDCTRL_DMADATAIRQID, rthw_sdctrl_dma_callback, ft_sdctrl_p);
+ FSdCtrl_BdIrqSet(ft_sdctrl_p, BD_IRQ_TRS | BD_IRQ_RESPE);
+ FSdCtrl_WriteWaitRegister(ft_sdctrl_p, rthw_sdctrl_write_wait);
+ FSdCtrl_ReadWaitRegister(ft_sdctrl_p, rthw_sdctrl_read_wait);
+
+ config_p->workMode = FTSDCTRL_CMD_IRQ_MASK | FTSDCTRL_DATA_WRITE_IRQ_MASK | FTSDCTRL_DATA_READ_IRQ_MASK;
+
+#else
+
+#endif
+
+ /* install normal irq */
+
+ rt_hw_interrupt_install(ft_sdctrl_p->config.normalIrqNum, rthw_sdctrl_normal_irq,
+ &sdctrl_class.ft_sdctrl, "normalIrq");
+ rt_hw_interrupt_umask(ft_sdctrl_p->config.normalIrqNum);
+
+ rt_hw_interrupt_install(ft_sdctrl_p->config.dmaIrqNum, rthw_sdctrl_dma_irq,
+ &sdctrl_class.ft_sdctrl, "dmaIrq");
+ rt_hw_interrupt_umask(ft_sdctrl_p->config.dmaIrqNum);
+
+ return 0;
+}
+
+INIT_DEVICE_EXPORT(rthw_sdctrl_init);
+
+void ft2004_mmcsd_change(void)
+{
+ mmcsd_change(sdctrl_class.host);
+}
+
+rt_bool_t ft2004_card_status(void)
+{
+ return FSdCtrl_CardDetect(&sdctrl_class.ft_sdctrl);
+}
+
+rt_err_t ft2004_card_remove_check(rt_int32_t timeout, rt_uint32_t *status)
+{
+ return rt_event_recv(&sdctrl_class.event, SDCTR_CARD_REMOVE_FLG, RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_OR,
+ timeout, status);
+}
+
+void ft2004_sdctrl_reset(void)
+{
+ FSdCtrl_Reset(&sdctrl_class.ft_sdctrl, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay);
+ FsdCtrl_Init(&sdctrl_class.ft_sdctrl);
+
+#ifdef BSP_SDC_USE_IRQ
+ FSdCtrl_NormalIrqSet(&sdctrl_class.ft_sdctrl, NORMAL_IRQ_CC | NORMAL_IRQ_CR | NORMAL_IRQ_EI);
+ FSdCtrl_BdIrqSet(&sdctrl_class.ft_sdctrl, BD_IRQ_TRS | BD_IRQ_RESPE);
+#endif
+}
+
+#endif
diff --git a/bsp/ft2004/drivers/drv_sdctrl.h b/bsp/ft2004/drivers/drv_sdctrl.h
new file mode 100644
index 0000000000..dba34f2525
--- /dev/null
+++ b/bsp/ft2004/drivers/drv_sdctrl.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2021-03-18 Carl the first version
+ */
+
+#ifndef __DRV_SDCTRL_H__
+#define __DRV_SDCTRL_H__
+
+#include <rtthread.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define SDCTR_CMD_IS_COMPLETE_FLG 0x1UL /* Command is complete */
+#define SDCTR_WRITE_IS_COMPLETE_FLG 0x2UL
+#define SDCTR_READ_IS_COMPLETE_FLG 0x4UL
+#define SDCTR_CMD_IS_ERROR_FLG 0x8UL
+#define SDCTR_CMD_CRC_IS_ERROR_FLG 0x10UL /* Command CRC error */
+#define SDCTR_DMA_IS_ERROR_FLG 0x20UL /* */
+#define SDCTR_CARD_REMOVE_FLG 0x40UL /* Card remove */
+#define SDCTR_CMD_TIMEOUT_FLG 0x70UL /* command timeout */
+#define SDCTR_CMD_RECEIVE_IS_ERROR_FLG 0x80UL /* CMD receive is error */
+
+#ifndef SDCTR_BUFF_SIZE
+#define SDCTR_BUFF_SIZE (512 * 128)
+#endif
+
+#ifndef SDCTR_ALIGN_LEN
+#define SDCTR_ALIGN_LEN (32)
+#endif
+
+ void ft2004_mmcsd_change(void);
+ rt_bool_t ft2004_card_status(void);
+ rt_err_t ft2004_card_remove_check(rt_int32_t timeout, rt_uint32_t *status);
+ void ft2004_sdctrl_reset(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif // !
diff --git a/bsp/ft2004/drivers/drv_spi.c b/bsp/ft2004/drivers/drv_spi.c
new file mode 100644
index 0000000000..0ac38709e4
--- /dev/null
+++ b/bsp/ft2004/drivers/drv_spi.c
@@ -0,0 +1,449 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-25 14:01:29
+ * @LastEditTime: 2021-05-26 15:42:52
+ * @Description:  This files is for
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include "drv_spi.h"
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <string.h>
+#include "ft_spi.h"
+#include "ft_mux.h"
+#include "ft_trace.h"
+#include "ft_generic_timer.h"
+
+#ifdef BSP_USE_SPI
+
+#define DRV_DEBUG
+#define LOG_TAG "drv.spi"
+#include <drv_log.h>
+
+typedef void (*spi_cs_handler_t)(const rt_bool_t select);
+typedef struct
+{
+ FSpi_Ctrl_t spi_ctrl;
+ struct rt_spi_bus spi_bus;
+ uint16_t spi_cs_pin;
+ spi_cs_handler_t spi_cs_handler;
+} ft2004_spi_class;
+
+void ft2004_spi_cs(const rt_bool_t select);
+static ft2004_spi_class spi_obj = {
+ .spi_cs_handler = ft2004_spi_cs,
+ .spi_ctrl = {
+ .CtrlId = SPI_CTRL_ID_0,
+ .DevId = SPI_DEV_ID_0,
+ .IsReady = FALSE,
+ .CsPin = 5, /* use pin 5 in gpio group a as cs signal pin */
+ },
+};
+static const FSpi_Conf_t spi_conf[NUM_OF_SPI_CTRL] =
+ {
+ {
+ .DevAddr = {0x00, 0x00, 0x00, 0x00},
+ .DevAddrLen = SPI_4_BYTE_ADDR,
+ .WorkMode = SPI_CTRL_MASTER_MODE,
+ /* mode 2 CPOL = 1, CPHA = 0 */
+ .Cpol = SPI_CTRL_CPOL_HIGH,
+ .Cpha = SPI_CTRL_CPHA_1EDGE,
+ .BaudRDiv = SPI_SCKDV_4,
+ },
+ {
+ .DevAddr = {0x00, 0x00, 0x00, 0x00},
+ .DevAddrLen = SPI_4_BYTE_ADDR,
+ .WorkMode = SPI_CTRL_MASTER_MODE,
+ .Cpol = SPI_CTRL_CPOL_HIGH,
+ .Cpha = SPI_CTRL_CPHA_1EDGE,
+ .BaudRDiv = SPI_SCKDV_MAX,
+ }};
+
+inline static ft2004_spi_class *ft2004_spi_get_class()
+{
+ return &spi_obj;
+}
+
+inline static FSpi_Ctrl_t *ft2004_spi_get_ctrl()
+{
+ return &(ft2004_spi_get_class()->spi_ctrl);
+}
+
+static const FSpi_Conf_t *ft2004_lookup_conf(FT_IN FSpi_CtrlId_t CtrlId)
+{
+ return &spi_conf[CtrlId];
+}
+
+void ft2004_spi_cs(const rt_bool_t select)
+{
+ FSpi_Ctrl_t *ctrl_p = ft2004_spi_get_ctrl();
+ FSpi_SelectSlave(ctrl_p, ctrl_p->DevId, (bool_t)select);
+}
+
+/**spi flash operations***/
+u32 ft2004_spi_transcation(const u8 tx_data, u8 *rx_data_p)
+{
+ FSpi_Ctrl_t *ctrl_p = ft2004_spi_get_ctrl();
+ u32 ret = ERR_SPI_OK;
+
+ ret = FSpi_ReadWriteByte(ctrl_p, tx_data, rx_data_p);
+ return ret;
+}
+/**spi flash operations***/
+
+static rt_err_t ft2004_spi_init(struct rt_spi_configuration *cfg)
+{
+ FSpi_Ctrl_t *ctrl_p = ft2004_spi_get_ctrl();
+ FSpi_DevId_t dev_id;
+ u32 ret = ERR_SPI_OK;
+
+ //RT_ASSERT(cfg != RT_NULL);
+ RT_ASSERT(ctrl_p != RT_NULL);
+ dev_id = ctrl_p->DevId;
+
+ /* get spi flash default config */
+ ctrl_p->Config = *(ft2004_lookup_conf(dev_id));
+
+ /* change config according to inputs, cfg could be RT_NULL */
+
+ /* reset ctrl block */
+ ctrl_p->IsReady = FALSE;
+
+ /* set spi pin mux */
+ Ft_setSpiMux(ctrl_p->CtrlId);
+
+ /* init spi ctrl */
+ ret = FSpi_Init(ctrl_p);
+
+ if (ERR_SPI_OK == ret)
+ {
+ return RT_EOK;
+ }
+ else
+ {
+ return -RT_ERROR;
+ }
+}
+
+static rt_uint32_t spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
+{
+ rt_size_t message_length, loop;
+ rt_uint8_t *recv_buf;
+ const rt_uint8_t *send_buf;
+ u32 tx_rx_result = ERR_SPI_OK;
+ spi_cs_handler_t cs_handler = ft2004_spi_get_class()->spi_cs_handler;
+
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(device->bus != RT_NULL);
+ RT_ASSERT(device->bus->parent.user_data != RT_NULL);
+ RT_ASSERT(message != RT_NULL);
+
+ if (message->cs_take && cs_handler)
+ {
+ cs_handler(TRUE);
+ }
+
+ message_length = message->length;
+ recv_buf = message->recv_buf;
+ send_buf = message->send_buf;
+
+ /* handle msg */
+ for (loop = 0; loop < message_length; loop++)
+ {
+ /* start data exchange */
+ if ((message->recv_buf) && (message->send_buf))
+ {
+ /* need tx and rx */
+ tx_rx_result |= ft2004_spi_transcation(*send_buf, recv_buf);
+ send_buf++;
+ recv_buf++;
+ }
+ else if (message->send_buf)
+ {
+ /* tx only */
+ tx_rx_result |= ft2004_spi_transcation(*send_buf, RT_NULL);
+ send_buf++;
+ }
+ else
+ {
+ /* rx only */
+ tx_rx_result |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, recv_buf);
+ recv_buf++;
+ }
+ }
+
+ if (ERR_SPI_OK != tx_rx_result)
+ {
+ LOG_E("spi transfer error : 0x%x", tx_rx_result);
+ message->length = 0;
+ }
+ else
+ {
+ }
+
+ if (message->cs_release && cs_handler)
+ {
+ cs_handler(FALSE);
+ }
+
+ return message->length;
+}
+
+static rt_err_t spi_configure(struct rt_spi_device *device,
+ struct rt_spi_configuration *configuration)
+{
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(configuration != RT_NULL);
+
+ return ft2004_spi_init(configuration);
+}
+
+static const struct rt_spi_ops ft2004_spi_ops =
+ {
+ .configure = spi_configure,
+ .xfer = spi_xfer,
+};
+
+/**
+ * Attach the spi device to SPI bus, this function must be used after initialization.
+ */
+rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, uint16_t cs_gpio_pin)
+{
+ rt_err_t result;
+ struct rt_spi_device *spi_device;
+ ft2004_spi_class *spi_class = ft2004_spi_get_class();
+
+ RT_ASSERT(spi_class != RT_NULL);
+
+ spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
+ RT_ASSERT(spi_device != RT_NULL);
+
+ result = rt_spi_bus_attach_device(spi_device, device_name, bus_name, RT_NULL);
+
+ LOG_I("attach result 0x%x", result);
+
+ if (result != RT_EOK)
+ {
+ if (spi_device)
+ {
+ rt_free(spi_device);
+ }
+ }
+ return result;
+}
+
+static int rt_hw_spi_bus_init(void)
+{
+ rt_err_t result;
+ ft2004_spi_class *spi_class = ft2004_spi_get_class();
+
+ LOG_I("init spi ctrl");
+ spi_class->spi_bus.parent.user_data = &spi_class->spi_bus;
+ result = rt_spi_bus_register(&spi_class->spi_bus, SPI_BUS_NAME, &ft2004_spi_ops);
+ return result;
+}
+
+int rt_hw_spi_init(void)
+{
+ return rt_hw_spi_bus_init();
+}
+INIT_BOARD_EXPORT(rt_hw_spi_init);
+
+static void rthw_spi_delay(u32 delayCnt)
+{
+ Ft_GenericTimer_UsDelay(delayCnt);
+}
+
+/************spi flash operatiosn implemented for sample test****************/
+/* definition of s25fs maunfactor id */
+typedef struct
+{
+ u8 Mid;
+ u8 MemoryType;
+ u8 Density;
+ u8 RemainBytes;
+ u8 PhySectArch;
+ u8 FamilyID;
+} ft2004_manuid_t;
+
+/* definition of cmd for s25fs */
+#define S25FS_ENABLE_WR 0x06
+#define S25FS_DISABLE_WR 0x04
+#define S25FS_READ_ID 0x9F
+#define S25FS_READ_4BYTE_ADD 0x13
+#define S25FS_ERASE_4BYTE_ADD 0x21
+#define S25FS_READ_STATUS_1 0x05
+#define S25FS_READ_FLASH_PARAM 0x5A
+
+static void ft2004_dump_manuid(const ft2004_manuid_t *pId)
+{
+ rt_kprintf("0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\r\n",
+ pId->Mid, pId->MemoryType, pId->Density, pId->RemainBytes,
+ pId->PhySectArch, pId->FamilyID);
+}
+
+static u32 ft2004_read_in_4byte_addr(const u32 ReadAddr, const u32 BytesToRead, u8 *pBuf)
+{
+ u32 ret = ERR_SPI_OK;
+ u32 loop;
+
+ RT_ASSERT(RT_NULL != pBuf);
+
+ ft2004_spi_cs(TRUE);
+ ret |= ft2004_spi_transcation(S25FS_READ_4BYTE_ADD, RT_NULL);
+ /* only 4-bytes address, MSB first */
+ ret |= ft2004_spi_transcation((u8)(ReadAddr >> 24), RT_NULL);
+ ret |= ft2004_spi_transcation((u8)(ReadAddr >> 16), RT_NULL);
+ ret |= ft2004_spi_transcation((u8)(ReadAddr >> 8), RT_NULL);
+ ret |= ft2004_spi_transcation((u8)ReadAddr, RT_NULL);
+ /* read out data */
+ for (loop = 0; loop < BytesToRead; loop++)
+ {
+ ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, pBuf + loop);
+ if (ERR_SPI_OK != ret)
+ {
+ break;
+ }
+ }
+ ft2004_spi_cs(FALSE);
+ return ret;
+}
+
+u32 ft2004_spi_enable_wr(const bool_t enable)
+{
+ u32 ret = ERR_SPI_OK;
+ ft2004_spi_cs(TRUE);
+ if (enable)
+ {
+ ret |= ft2004_spi_transcation(S25FS_ENABLE_WR, RT_NULL);
+ }
+ else
+ {
+ ret |= ft2004_spi_transcation(S25FS_DISABLE_WR, RT_NULL);
+ }
+ ft2004_spi_cs(FALSE);
+ return ret;
+}
+
+u32 ft2004_erase_sector_in_4byte_addr(const u32 sector_addr)
+{
+ u32 Ret = ERR_SPI_OK;
+
+ ft2004_spi_enable_wr(TRUE);
+ LOG_I("erase sector 0x%x", Ret);
+ if (ERR_SPI_OK != Ret)
+ {
+ return Ret;
+ }
+
+ ft2004_spi_cs(TRUE);
+ Ret |= ft2004_spi_transcation(S25FS_ERASE_4BYTE_ADD, RT_NULL);
+ Ret |= ft2004_spi_transcation((u8)(sector_addr >> 24), RT_NULL);
+ Ret |= ft2004_spi_transcation((u8)(sector_addr >> 16), RT_NULL);
+ Ret |= ft2004_spi_transcation((u8)(sector_addr >> 8), RT_NULL);
+ Ret |= ft2004_spi_transcation((u8)(sector_addr), RT_NULL);
+ ft2004_spi_cs(FALSE);
+
+ return Ret;
+}
+
+u32 ft2004_spi_read_params(const u32 Addr)
+{
+ u32 Ret = ERR_SPI_OK;
+ u8 dat[8] = {0};
+ u32 loop;
+
+ ft2004_spi_cs(TRUE);
+ Ret |= ft2004_spi_transcation(S25FS_READ_FLASH_PARAM, RT_NULL);
+ Ret |= ft2004_spi_transcation((u8)(Addr >> 16), RT_NULL);
+ Ret |= ft2004_spi_transcation((u8)(Addr >> 8), RT_NULL);
+ Ret |= ft2004_spi_transcation((u8)(Addr), RT_NULL);
+ for (loop = 0; loop < 8; loop++)
+ {
+ Ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, dat + loop);
+ rt_kprintf("%d: 0x%x", loop, *(dat + loop));
+ }
+
+ ft2004_spi_cs(FALSE);
+ return Ret;
+}
+
+static u32 ft2004_spi_readid_for_test(ft2004_manuid_t *pId)
+{
+ FSpi_Ctrl_t *ctrl_p = ft2004_spi_get_ctrl();
+ u32 ret = ERR_SPI_OK;
+
+ if (!ctrl_p->IsReady)
+ {
+ return ERR_SPI_NOT_READY;
+ }
+
+ RT_ASSERT(RT_NULL != pId);
+
+ ft2004_spi_cs(TRUE);
+
+ /* shifting the command code “90H” followed by a 24-bit address */
+ ret |= ft2004_spi_transcation(S25FS_READ_ID, RT_NULL);
+
+ /* Manufacturer ID and the Device ID are shifted out */
+ ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->Mid);
+ ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->MemoryType);
+ ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->Density);
+ ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->RemainBytes);
+ ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->PhySectArch);
+ ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->FamilyID);
+ ft2004_spi_cs(FALSE);
+
+ if (ERR_SPI_OK == ret)
+ {
+ ft2004_dump_manuid(pId);
+ }
+
+ return ret;
+}
+
+static void spi_9f_s25fs_sample(int argc, char *argv[])
+{
+ ft2004_manuid_t dev_id;
+ u32 ret = ERR_SPI_OK;
+ u32 delay = SPI_TIMEOUT * 10;
+
+ rt_kprintf("test s25fs spi flash\r\n");
+ ret |= ft2004_spi_init(RT_NULL);
+ ret |= ft2004_spi_readid_for_test(&dev_id);
+
+ rt_kprintf("result is: 0x%x \r\n", ret);
+ while (--delay)
+ {
+ rthw_spi_delay(10);
+ }
+}
+MSH_CMD_EXPORT(spi_9f_s25fs_sample, "spi s25fs cmd 9fH sample");
+
+static u8 read_buf[256];
+static void spi_5a_s25fs_sample(int argc, char *argv[])
+{
+ u32 ret = ERR_SPI_OK;
+ u32 delay = SPI_TIMEOUT * 10;
+ u32 read_addr = 0x0000;
+
+ rt_kprintf("test s25fs spi flash\r\n");
+ ret |= ft2004_spi_init(RT_NULL);
+ ret |= ft2004_spi_read_params(read_addr);
+ ret |= ft2004_read_in_4byte_addr(read_addr, 256, read_buf);
+ rt_kprintf("result is: 0x%x \r\n", ret);
+ while (--delay)
+ {
+ rthw_spi_delay(10);
+ }
+}
+MSH_CMD_EXPORT(spi_5a_s25fs_sample, "spi s25fs cmd 5aH sample");
+
+#endif
diff --git a/bsp/ft2004/drivers/drv_spi.h b/bsp/ft2004/drivers/drv_spi.h
new file mode 100644
index 0000000000..5b31ab678c
--- /dev/null
+++ b/bsp/ft2004/drivers/drv_spi.h
@@ -0,0 +1,29 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-25 14:01:39
+ * @LastEditTime: 2021-04-29 09:40:13
+ * @Description:  This files is for
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+#ifndef FT_DRIVERS_RTT_SPI_H
+#define FT_DRIVERS_RTT_SPI_H
+
+#include <rtthread.h>
+
+#define SPI_BUS_NAME "spi0"
+#define SPI_DEV_NAME "S25FS256"
+
+rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, uint16_t cs_gpio_pin);
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#endif
diff --git a/bsp/ft2004/drivers/drv_spi_flash.c b/bsp/ft2004/drivers/drv_spi_flash.c
new file mode 100644
index 0000000000..26d8b44712
--- /dev/null
+++ b/bsp/ft2004/drivers/drv_spi_flash.c
@@ -0,0 +1,43 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-25 14:01:16
+ * @LastEditTime: 2021-04-30 14:43:12
+ * @Description:  This files is for
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include <board.h>
+#include <drv_spi.h>
+#include <rtdevice.h>
+#include <rthw.h>
+#include <finsh.h>
+#include "ft_spi.h"
+
+#ifdef BSP_USE_SPI
+
+#include "spi_flash.h"
+#include "spi_flash_sfud.h"
+
+static int rt_hw_spi_flash_init(void)
+{
+ uint16_t cs_pin = 5;
+ rt_hw_spi_device_attach(SPI_BUS_NAME, SPI_DEV_NAME, cs_pin);
+
+ rt_kprintf("attach spi flash\r\n");
+ /* lookup flah */
+ if (RT_NULL == rt_sfud_flash_probe("S25FS256S", SPI_DEV_NAME))
+ {
+ rt_kprintf("attach spi flash failed\r\n");
+ return -RT_ERROR;
+ }
+
+ return RT_EOK;
+}
+INIT_COMPONENT_EXPORT(rt_hw_spi_flash_init);
+#endif
diff --git a/bsp/ft2004/drivers/drv_usart.c b/bsp/ft2004/drivers/drv_usart.c
new file mode 100644
index 0000000000..96ac3c97eb
--- /dev/null
+++ b/bsp/ft2004/drivers/drv_usart.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2021-03-04 Carl the first version
+ */
+
+#include "board.h"
+#include "drv_usart.h"
+#include "interrupt.h"
+#include "serial.h"
+#include "rtconfig.h"
+
+#ifdef RT_USING_SERIAL
+
+extern u32 FUart_GetInterruptMask(Ft_Uart *uart_ptr);
+
+static void Ft_Os_Uart_Callback(void *Args, u32 Event, u32 EventData);
+
+static void rt_hw_uart_isr(int irqno, void *param)
+{
+ Ft_Uart *uart_ptr = (Ft_Uart *)param;
+ FUart_InterruptHandler(uart_ptr);
+}
+
+static rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
+{
+ struct drv_usart *uart = RT_NULL;
+ Ft_Uart *uart_ptr = RT_NULL;
+ u32 RegTemp;
+ u32 ret;
+ RT_ASSERT(serial != RT_NULL);
+ RT_ASSERT(cfg != RT_NULL);
+ uart = rt_container_of(serial, struct drv_usart, serial);
+ uart_ptr = uart->handle;
+
+ RT_ASSERT(FUart_CfgInitialize(uart_ptr, FUart_LookupConfig(uart_ptr->Config.InstanceId)) == FST_SUCCESS);
+ FUart_SetHandler(uart_ptr, Ft_Os_Uart_Callback, serial);
+ rt_hw_interrupt_install(uart_ptr->Config.IsrNum, rt_hw_uart_isr, uart_ptr, "uart");
+ rt_hw_interrupt_umask(uart_ptr->Config.IsrNum);
+
+ //<! 设置波特率
+ ret = FUart_SetBaudRate(uart_ptr, cfg->baud_rate);
+ RT_ASSERT(ret == FST_SUCCESS);
+
+ //<! 打开接收中断
+ RegTemp = FUart_GetInterruptMask(uart_ptr);
+ RegTemp |= UARTMIS_RTMIS;
+ FUart_SetInterruptMask(uart_ptr, RegTemp);
+ FUart_SetOptions(uart_ptr, FUART_OPTION_UARTEN | FUART_OPTION_RXEN | FUART_OPTION_TXEN | FUART_OPTION_FIFOEN);
+ return RT_EOK;
+}
+
+static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg)
+{
+ struct drv_usart *uart = RT_NULL;
+ Ft_Uart *uart_ptr = RT_NULL;
+ RT_ASSERT(serial != RT_NULL);
+
+ uart = rt_container_of(serial, struct drv_usart, serial);
+ uart_ptr = uart->handle;
+
+ switch (cmd)
+ {
+ case RT_DEVICE_CTRL_CLR_INT:
+ /* disable rx irq */
+ rt_hw_interrupt_mask(uart_ptr->Config.IsrNum);
+ break;
+
+ case RT_DEVICE_CTRL_SET_INT:
+ /* enable rx irq */
+ rt_hw_interrupt_umask(uart_ptr->Config.IsrNum);
+ break;
+ }
+
+ return RT_EOK;
+}
+
+static void Ft_Os_Uart_Callback(void *Args, u32 Event, u32 EventData)
+{
+ struct rt_serial_device *serial = (struct rt_serial_device *)Args;
+
+ if (FUART_EVENT_RECV_DATA == Event || FUART_EVENT_RECV_TOUT == Event)
+ {
+ rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
+ }
+ else if (FUART_EVENT_RECV_ERROR == Event)
+ {
+ }
+ else if (FUART_EVENT_SENT_DATA == Event)
+ {
+ }
+ else if (FUART_EVENT_PARE_FRAME_BRKE == Event)
+ {
+ }
+ else if (FUART_EVENT_RECV_ORERR == Event)
+ {
+ }
+
+ if (FUART_EVENT_SENT_DATA == Event)
+ {
+ }
+ else
+ {
+ }
+}
+
+static int uart_putc(struct rt_serial_device *serial, char c)
+{
+ struct drv_usart *uart = RT_NULL;
+ Ft_Uart *uart_ptr = RT_NULL;
+ RT_ASSERT(serial != RT_NULL);
+
+ uart = rt_container_of(serial, struct drv_usart, serial);
+ uart_ptr = uart->handle;
+
+ FUart_SendByte(uart_ptr->Config.BaseAddress, c);
+
+ return 1;
+}
+
+static int uart_getc(struct rt_serial_device *serial)
+{
+ int ch;
+ struct drv_usart *uart = RT_NULL;
+ Ft_Uart *uart_ptr = RT_NULL;
+ RT_ASSERT(serial != RT_NULL);
+
+ uart = rt_container_of(serial, struct drv_usart, serial);
+ uart_ptr = uart->handle;
+
+ ch = FUart_GetChar(uart_ptr->Config.BaseAddress);
+ if (ch == 0xff)
+ ch = -1;
+
+ return ch;
+}
+
+static const struct rt_uart_ops _uart_ops =
+ {
+ uart_configure,
+ uart_control,
+ uart_putc,
+ uart_getc,
+};
+
+#ifdef RT_USING_UART0
+static Ft_Uart Ft_Uart0;
+static struct drv_usart _RtUart0;
+#endif
+
+#ifdef RT_USING_UART1
+static Ft_Uart Ft_Uart1;
+static struct drv_usart _RtUart1;
+#endif
+
+int rt_hw_uart_init(void)
+{
+
+ struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
+
+#ifdef RT_USING_UART0
+ config.bufsz = RT_SERIAL_RB_BUFSZ;
+ _RtUart0.serial.ops = &_uart_ops;
+ _RtUart0.serial.config = config;
+ Ft_Uart0.Config.InstanceId = FT_UART0_ID;
+ _RtUart0.Handle = &Ft_Uart0;
+
+ rt_hw_serial_register(&_RtUart0.serial, "uart0",
+ RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
+ &_RtUart0);
+#endif
+
+#ifdef RT_USING_UART1
+ config.bufsz = RT_SERIAL_RB_BUFSZ;
+ _RtUart1.serial.ops = &_uart_ops;
+ _RtUart1.serial.config = config;
+ Ft_Uart1.Config.InstanceId = FT_UART1_ID;
+ _RtUart1.handle = &Ft_Uart1;
+ rt_hw_serial_register(&_RtUart1.serial, "uart1",
+ RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
+ &_RtUart1);
+#endif
+
+ return 0;
+}
+INIT_BOARD_EXPORT(rt_hw_uart_init);
+
+#endif /* RT_USING_SERIAL */
diff --git a/bsp/ft2004/drivers/drv_usart.h b/bsp/ft2004/drivers/drv_usart.h
new file mode 100644
index 0000000000..aff47caa29
--- /dev/null
+++ b/bsp/ft2004/drivers/drv_usart.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2021-03-04 Carl the first version
+ */
+
+#ifndef __DRV_USART_H__
+#define __DRV_USART_H__
+
+#include <rtthread.h>
+#include "rtdevice.h"
+#include "ft_uart.h"
+
+struct drv_usart
+{
+ Ft_Uart *handle;
+
+ struct rt_serial_device serial;
+};
+
+#endif // !
diff --git a/bsp/ft2004/drivers/ft2004.c b/bsp/ft2004/drivers/ft2004.c
new file mode 100644
index 0000000000..da04993276
--- /dev/null
+++ b/bsp/ft2004/drivers/ft2004.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2021-04-29 Carl the first version
+ *
+ */
+
+#include <rtthread.h>
+#include "ft2004.h"
+#include "gicv3.h"
+
+rt_uint64_t get_main_cpu_affval(void)
+{
+ return 0;
+}
+
+rt_uint32_t arm_gic_cpumask_to_affval(rt_uint32_t *cpu_mask, rt_uint32_t *cluster_id, rt_uint32_t *target_list)
+{
+
+ if (*cpu_mask == 0)
+ {
+ return 0;
+ }
+
+ *target_list = 0;
+ *cluster_id = 0;
+
+ if (*cpu_mask & 0x3)
+ {
+ if ((*cpu_mask & 0x3) == 0x3)
+ {
+ *target_list = 3;
+ }
+ else if ((*cpu_mask & 0x1))
+ {
+ *target_list = 1;
+ }
+ else
+ {
+ *target_list = 2;
+ }
+ *cpu_mask &= ~0x3;
+ }
+ else if (*cpu_mask & 0xc)
+ {
+ *cluster_id = 0x100;
+ if ((*cpu_mask & 0xc) == 0xc)
+ {
+ *target_list = 3;
+ }
+ else if ((*cpu_mask & 0x4))
+ {
+ *target_list = 1;
+ }
+ else
+ {
+ *target_list = 2;
+ }
+ *cpu_mask &= ~0xc;
+ }
+ else
+ {
+ *cpu_mask = 0;
+ return 0;
+ }
+
+ return 1;
+}
+
+#ifdef RT_USING_SMP
+
+void send_core_isg(void)
+{
+ for (size_t i = 0; i <= 0xf; i++)
+ {
+ /* code */
+ rt_kprintf("i %x \r\n", i);
+ arm_gic_send_affinity_sgi(0, 0, i, 0);
+ rt_thread_mdelay(100);
+ }
+}
+MSH_CMD_EXPORT(send_core_isg, send_core_isg);
+
+#endif
diff --git a/bsp/ft2004/drivers/ft2004.h b/bsp/ft2004/drivers/ft2004.h
new file mode 100644
index 0000000000..fe3293ab94
--- /dev/null
+++ b/bsp/ft2004/drivers/ft2004.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2021-04-29 Carl the first version
+ *
+ */
+
+#ifndef __FT2004_H__
+#define __FT2004_H__
+
+#include <rthw.h>
+#include <rtthread.h>
+
+#define ARM_GIC_NR_IRQS 160
+#define ARM_GIC_MAX_NR 1
+#define MAX_HANDLERS 160
+#define GIC_IRQ_START 0
+
+rt_uint64_t get_main_cpu_affval(void);
+
+#endif // !
diff --git a/bsp/ft2004/drivers/ft2004_cpu.S b/bsp/ft2004/drivers/ft2004_cpu.S
new file mode 100644
index 0000000000..2e713a5b20
--- /dev/null
+++ b/bsp/ft2004/drivers/ft2004_cpu.S
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2021-04-29 Carl the first version
+ *
+ */
+
+#include "rtconfig.h"
+
+.globl rt_hw_cpu_id
+rt_hw_cpu_id:
+ mrc p15, 0, r0, c0, c0, 5
+ ubfx r0, r0, #0, #12
+ cmp r0, #0
+ beq core0
+ cmp r0, #1
+ beq core1
+ cmp r0, #256
+ beq core2
+ mov r1 ,#257
+ cmp r0, r1
+ beq core3
+ b default
+core0:
+ mov r0, #0
+ b return
+core1:
+ mov r0, #1
+ b return
+core2:
+ mov r0, #2
+ b return
+core3:
+ mov r0, #3
+ b return
+default:
+ and r0, r0, #15
+return:
+ bx lr
+
diff --git a/bsp/ft2004/drivers/secondary_cpu.c b/bsp/ft2004/drivers/secondary_cpu.c
new file mode 100644
index 0000000000..5ffcadbefe
--- /dev/null
+++ b/bsp/ft2004/drivers/secondary_cpu.c
@@ -0,0 +1,86 @@
+/*
+ * @ : Copyright (c) 2020 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-05-26 10:09:45
+ * @LastEditTime: 2021-05-26 10:31:44
+ * @Description:  This files is for
+ *
+ * @Modify History:
+ *  Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include <rtthread.h>
+#include "board.h"
+#include <gicv3.h>
+
+#ifdef RT_USING_SMP
+#include <interrupt.h>
+#include "ft_psci.h"
+#include "ft_generic_timer.h"
+
+extern int rt_hw_timer_init(void);
+extern void secondary_cpu_start(void);
+
+void rt_hw_secondary_cpu_up(void)
+{
+
+ rt_uint32_t i;
+ rt_uint32_t cpu_mask = 0;
+
+ rt_kprintf("rt_hw_secondary_cpu_up is processing \r\n");
+ for (i = 1; i < RT_CPUS_NR; i++)
+ {
+ if (i == 1)
+ {
+ /* code */
+ FPsci_CpuOn(1 << i, (rt_uint32_t)secondary_cpu_start);
+ cpu_mask = 2;
+ }
+ else if (i == 2)
+ {
+ FPsci_CpuOn(1 << i, (rt_uint32_t)secondary_cpu_start);
+ cpu_mask = 4;
+ }
+ else if (i == 3)
+ {
+ FPsci_CpuOn(1 << i, (rt_uint32_t)secondary_cpu_start);
+ cpu_mask = 8;
+ }
+ else
+ {
+ continue;
+ }
+
+ __asm__ volatile("dsb" ::
+ : "memory");
+ rt_hw_ipi_send(RT_SCHEDULE_IPI, cpu_mask);
+ Ft_GenericTimer_UsDelay(1000000);
+ }
+}
+
+void secondary_cpu_c_start(void)
+{
+ rt_hw_vector_init();
+ rt_hw_spin_lock(&_cpus_lock);
+
+ arm_gic_cpu_init(0);
+ arm_gic_redist_init(0);
+
+ rt_hw_timer_init();
+
+ rt_hw_interrupt_set_priority(RT_SCHEDULE_IPI, 16);
+ rt_hw_interrupt_umask(RT_SCHEDULE_IPI);
+
+ rt_system_scheduler_start();
+}
+
+void rt_hw_secondary_cpu_idle_exec(void)
+{
+ asm volatile("wfe" ::
+ : "memory", "cc");
+}
+
+#endif
diff --git a/bsp/ft2004/drivers/serial.h b/bsp/ft2004/drivers/serial.h
new file mode 100644
index 0000000000..cf4e337a1f
--- /dev/null
+++ b/bsp/ft2004/drivers/serial.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2021-04-29 Carl the first version
+ *
+ */
+
+#ifndef __UART_H__
+#define __UART_H__
+
+#include <board.h>
+
+int rt_hw_uart_init(void);
+
+#endif
+
diff --git a/bsp/ft2004/figures/onchipPeripheral.png b/bsp/ft2004/figures/onchipPeripheral.png
new file mode 100644
index 0000000000..3b5833bcca
--- /dev/null
+++ b/bsp/ft2004/figures/onchipPeripheral.png
Binary files differ
diff --git a/bsp/ft2004/figures/rttPing通过界面.png b/bsp/ft2004/figures/rttPing通过界面.png
new file mode 100644
index 0000000000..0c287ea571
--- /dev/null
+++ b/bsp/ft2004/figures/rttPing通过界面.png
Binary files differ
diff --git a/bsp/ft2004/figures/rttsd调试.png b/bsp/ft2004/figures/rttsd调试.png
new file mode 100644
index 0000000000..98d1b5fa2b
--- /dev/null
+++ b/bsp/ft2004/figures/rttsd调试.png
Binary files differ
diff --git a/bsp/ft2004/figures/启动演示图.png b/bsp/ft2004/figures/启动演示图.png
new file mode 100644
index 0000000000..46a117c96f
--- /dev/null
+++ b/bsp/ft2004/figures/启动演示图.png
Binary files differ
diff --git a/bsp/ft2004/ft_aarch32.lds b/bsp/ft2004/ft_aarch32.lds
new file mode 100644
index 0000000000..d37332d97f
--- /dev/null
+++ b/bsp/ft2004/ft_aarch32.lds
@@ -0,0 +1,110 @@
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+
+SECTIONS
+{
+ . = 0x80100000;
+
+ __text_start = .;
+ .text :
+ {
+ *(.vectors)
+ *(.text)
+ *(.text.*)
+
+ /* section information for finsh shell */
+ . = ALIGN(4);
+ __fsymtab_start = .;
+ KEEP(*(FSymTab))
+ __fsymtab_end = .;
+ . = ALIGN(4);
+ __vsymtab_start = .;
+ KEEP(*(VSymTab))
+ __vsymtab_end = .;
+ . = ALIGN(4);
+
+ /* section information for modules */
+ . = ALIGN(4);
+ __rtmsymtab_start = .;
+ KEEP(*(RTMSymTab))
+ __rtmsymtab_end = .;
+
+ /* section information for initialization */
+ . = ALIGN(4);
+ __rt_init_start = .;
+ KEEP(*(SORT(.rti_fn*)))
+ __rt_init_end = .;
+ } =0
+ __text_end = .;
+
+ __rodata_start = .;
+ .rodata : { *(.rodata) *(.rodata.*) }
+ __rodata_end = .;
+
+ . = ALIGN(4);
+ .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 * 1024);
+ .l1_page_table :
+ {
+ __l1_page_table_start = .;
+ . += 16K;
+ }
+
+ . = ALIGN(8);
+ __data_start = .;
+ .data :
+ {
+ *(.data)
+ *(.data.*)
+ }
+ __data_end = .;
+
+ . = ALIGN(8);
+ __bss_start = .;
+ .bss :
+ {
+ *(.bss)
+ *(.bss.*)
+ *(COMMON)
+ . = ALIGN(4);
+ }
+ . = ALIGN(4);
+ __bss_end = .;
+
+ .heap :
+ {
+ . = ALIGN(8);
+ __end__ = .;
+ PROVIDE(end = .);
+ __HeapBase = .;
+ . += 0x400;
+ __HeapLimit = .;
+ __heap_limit = .; /* Add for _sbrk */
+ }
+
+ /* 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) }
+
+ _end = .;
+}
diff --git a/bsp/ft2004/libraries/.gitignore b/bsp/ft2004/libraries/.gitignore
new file mode 100644
index 0000000000..fcfda9fc84
--- /dev/null
+++ b/bsp/ft2004/libraries/.gitignore
@@ -0,0 +1,4 @@
+*.o
+*.elf
+*.bin
+*.map
diff --git a/bsp/ft2004/libraries/Kconfig b/bsp/ft2004/libraries/Kconfig
new file mode 100644
index 0000000000..c544395596
--- /dev/null
+++ b/bsp/ft2004/libraries/Kconfig
@@ -0,0 +1,146 @@
+menu "Hardware Drivers Config"
+
+menu "On-chip Peripheral Drivers"
+ menuconfig BSP_USING_UART
+ bool "Enable UART"
+ default y
+ select RT_USING_SERIAL
+ if BSP_USING_UART
+ config RT_USING_UART1
+ bool "Enable UART1"
+ default y
+
+ config RT_USING_UART0
+ bool "Enable UART0"
+ default n
+
+ endif
+
+ menuconfig BSP_USING_SDC
+ bool "Enable sd controller"
+ select RT_USING_SDIO
+ select RT_USING_DFS
+ select RT_USING_DFS_ELMFAT
+ default n
+
+ if BSP_USING_SDC
+
+ config BSP_SDC_DEBUG_PRINT
+ bool "Enable sd controller debug print"
+ default n
+
+
+ config BSP_SDC_USE_IRQ
+ bool "Use interrupt to handle when cmd complete, dma complete"
+ default n
+
+ if BSP_SDC_USE_IRQ
+ config BSP_SDC_IRQ_CARD_REMOVE
+ bool "Use interrupt to determine if the card is pulled out"
+ default n
+
+ endif
+
+ endif
+
+ menuconfig BSP_USING_GMAC
+ bool "Enable gmac"
+ default n
+ select RT_USING_NETDEV
+
+
+ if BSP_USING_GMAC
+ config BSP_USING_GMAC0
+ bool "Enable GMAC0"
+ default y
+
+ config BSP_USING_GMAC1
+ bool "Enable GMAC1"
+ default n
+
+ config RT_LWIP_ETH_PAD_SIZE
+ int "set lwip ETH_PAD_SIZE"
+ range 2 256
+ default 2
+
+ config RAW_DATA_PRINT
+ bool "Enable mac raw data print"
+ default n
+
+ if RAW_DATA_PRINT
+ config ETH_RX_DUMP
+ bool "Enable gmac receive raw data print "
+ default n
+
+ config ETH_TX_DUMP
+ bool "Enable gmac send raw data print "
+ default n
+ endif
+
+ endif
+
+
+ # menuconfig BSP_USE_QSPI
+ # bool "Enable Qspi"
+ # select RT_USING_SFUD
+ # select RT_SFUD_USING_QSPI
+ # default n
+
+ # if BSP_USE_QSPI
+ # config BSP_QSPI_DEBUG
+ # bool "Enable qspi debug print"
+ # default n
+ # endif
+
+ menuconfig BSP_USE_SPI
+ bool "Enable Spi"
+ select RT_USING_SFUD
+ select RT_SFUD_USING_SPI
+ select RT_SFUD_USING_SFDP
+ select RT_SFUD_USING_FLASH_INFO_TABLE
+ select BSP_USE_GPIO
+ default n
+ if BSP_USE_SPI
+ config BSP_SPI_DEBUG
+ bool "Enable spi debug print"
+ default n
+ endif
+
+ menuconfig BSP_USE_GPIO
+ bool "Enable Gpio"
+ default n
+ if BSP_USE_GPIO
+ config BSP_GPIO_DEBUG
+ bool "Enable gpio debug print"
+ default n
+ endif
+
+ menuconfig BSP_USE_CAN
+ bool "Enable Can"
+ select RT_USING_CAN
+ default n
+
+ if BSP_USE_CAN
+ config BSP_USING_CAN0
+ bool "Enable can0"
+ default n
+ config BSP_USING_CAN1
+ bool "Enable can1"
+ default n
+
+ if BSP_USING_CAN0
+ config BSP_USING_CAN0_DEBUG
+ bool "Enable can0 work in loop back"
+ default n
+ endif
+
+ endif
+
+
+endmenu
+
+menu "Board extended module Drivers"
+
+endmenu
+
+endmenu
diff --git a/bsp/ft2004/libraries/LICENSE b/bsp/ft2004/libraries/LICENSE
new file mode 100644
index 0000000000..7a4a3ea242
--- /dev/null
+++ b/bsp/ft2004/libraries/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License. \ No newline at end of file
diff --git a/bsp/ft2004/libraries/SConscript b/bsp/ft2004/libraries/SConscript
new file mode 100644
index 0000000000..e279d05ea1
--- /dev/null
+++ b/bsp/ft2004/libraries/SConscript
@@ -0,0 +1,129 @@
+'''
+ : Copyright (c) 2020 Phytium Information Technology, Inc. 
+ 
+SPDX-License-Identifier: Apache-2.0.
+
+Date: 2021-05-24 14:30:13
+LastEditTime: 2021-05-26 14:58:34
+Description:  This files is for 
+
+Modify History:
+ Ver   Who        Date         Changes
+----- ------     --------    --------------------------------------
+'''
+from building import *
+import rtconfig
+Import('RTT_ROOT')
+
+# get current directory
+cwd = GetCurrentDir()
+
+# The set of source files associated with this SConscript file.
+src = Split("""
+bsp/standlone/ft_assert.c
+bsp/standlone/ft_generic_timer.c
+bsp/standlone/ft_printf.c
+bsp/standlone/ft_trace.c
+bsp/standlone/ft_mux.c
+bsp/standlone/inbyte.c
+bsp/standlone/outbyte.c
+bsp/standlone/ft_cache.c
+bsp/standlone/ft_cpu.c
+bsp/standlone/ft_smc.S
+bsp/standlone/ft_psci.c
+bsp/standlone/ft_debug.c
+""")
+
+
+
+if GetDepend(['RT_USING_SERIAL']):
+ src += ['bsp/ft_uart/ft_uart_g.c']
+ src += ['bsp/ft_uart/ft_uart_hw.c']
+ src += ['bsp/ft_uart/ft_uart_intr.c']
+ src += ['bsp/ft_uart/ft_uart_options.c']
+ src += ['bsp/ft_uart/ft_uart_selftest.c']
+ src += ['bsp/ft_uart/ft_uart_sinit.c']
+ src += ['bsp/ft_uart/ft_uart.c']
+
+if GetDepend(['RT_USING_I2C']):
+ None
+
+if GetDepend(['RT_USING_USB_HOST']) or GetDepend(['RT_USING_USB_DEVICE']):
+ None
+
+if GetDepend(['BSP_USE_CAN']):
+ src += ['bsp/ft_can/ft_can_g.c']
+ src += ['bsp/ft_can/ft_can_hw.c']
+ src += ['bsp/ft_can/ft_can_intr.c']
+ src += ['bsp/ft_can/ft_can_sinit.c']
+ src += ['bsp/ft_can/ft_can.c']
+ src += ['bsp/ft_can/ft_can_calc.c']
+ None
+
+
+if GetDepend(['RT_USING_HWTIMER']) or GetDepend(['RT_USING_PWM']):
+ None
+
+if GetDepend(['RT_USING_ADC']):
+ None
+
+if GetDepend(['RT_USING_RTC']):
+ None
+
+if GetDepend(['RT_USING_WDT']):
+ None
+
+if GetDepend(['RT_USING_AUDIO']):
+ None
+
+if GetDepend(['BSP_USING_ON_CHIP_FLASH']):
+ None
+
+if GetDepend(['BSP_USING_GMAC']):
+ src += ['bsp/ft_gmac/ft_gmac_desc.c']
+ src += ['bsp/ft_gmac/ft_gmac_g.c']
+ src += ['bsp/ft_gmac/ft_gmac_hw.c']
+ src += ['bsp/ft_gmac/ft_gmac_intr.c']
+ src += ['bsp/ft_gmac/ft_gmac_sinit.c']
+ src += ['bsp/ft_gmac/ft_gmac.c']
+
+if GetDepend(['BSP_USING_SDC']):
+ src += ['bsp/ft_sd/ft_sdctrl_option.c']
+ src += ['bsp/ft_sd/ft_sdctrl_sinit.c']
+ src += ['bsp/ft_sd/ft_sdctrl_intr.c']
+ src += ['bsp/ft_sd/ft_sdctrl_g.c']
+ src += ['bsp/ft_sd/ft_sdctrl_hw.c']
+ src += ['bsp/ft_sd/ft_sdctrl.c']
+
+if GetDepend(['BSP_USE_QSPI']):
+ src += ['bsp/ft_qspi/qspi_g.c']
+ src += ['bsp/ft_qspi/qspi_hw.c']
+ src += ['bsp/ft_qspi/ft_qspi.c']
+ src += ['bsp/ft_qspi/qspi_sinit.c']
+
+if GetDepend(['BSP_USE_SPI']):
+ src += ['bsp/ft_spi/ft_spi.c']
+ src += ['bsp/ft_spi/ft_spi_irq.c']
+
+if GetDepend(['BSP_USE_GPIO']):
+ src += ['bsp/ft_gpio/ft_gpio.c']
+
+path = [cwd + '/bsp/standlone/',
+ cwd + '/bsp/ft_gicv3',
+ cwd + '/bsp/ft_gmac',
+ cwd + '/bsp/ft_uart',
+ cwd + '/bsp/ft_sd',
+ cwd + '/bsp/ft_qspi',
+ cwd + '/bsp/ft_can',
+ cwd + '/bsp/ft_spi',
+ cwd + '/bsp/ft_gpio',
+ cwd + '/bsp/include',
+ cwd + '/include',
+ cwd + '/cpu', ]
+
+
+CPPDEFINES = ['USE_FT_DRIVER']
+group = DefineGroup('FT_DRIVER', src, depend=[
+ ''], CPPPATH=path, CPPDEFINES=CPPDEFINES)
+
+Return('group')
diff --git a/bsp/ft2004/libraries/bsp/ft_can/ft_can.c b/bsp/ft2004/libraries/bsp/ft_can/ft_can.c
new file mode 100644
index 0000000000..9546670715
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_can/ft_can.c
@@ -0,0 +1,299 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-29 10:21:53
+ * @LastEditTime: 2021-05-25 16:41:38
+ * @Description:  Description of file
+ * @Modify History:
+ * * * Ver   Who        Date         Changes
+ * * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_can.h"
+#include "ft_can_hw.h"
+#include "ft_assert.h"
+#include "ft_debug.h"
+#include "string.h"
+
+#define FT_CAN_DEBUG_TAG "FT_CAN"
+
+#define FT_CAN_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__)
+#define FT_CAN_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__)
+#define FT_CAN_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__)
+
+ft_error_t
+FCan_CfgInitialize(FCan_t *Can_p, FCan_Config_t *Config_p)
+{
+ Ft_assertNonvoid(Can_p != NULL);
+ Ft_assertNonvoid(Config_p != NULL);
+ Can_p->Config = *Config_p;
+ Can_p->IsReady = FT_COMPONENT_IS_READLY;
+ FCan_Reset(Can_p);
+ return FCAN_SUCCESS;
+}
+
+void FCan_GetErrorCnt(FCan_t *Can_p, u32 *TxErr, u32 *RxErr)
+{
+ FCan_Config_t *Config_p;
+ Ft_assertVoid(Can_p != NULL);
+ Ft_assertVoid(Can_p->IsReady == FT_COMPONENT_IS_READLY);
+ Config_p = &Can_p->Config;
+
+ *RxErr = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_ERR_CNT_OFFSET) & FCAN_ERR_CNT_RFN_MASK;
+ *TxErr = (FCan_ReadReg(Config_p->CanBaseAddress, FCAN_ERR_CNT_OFFSET) & FCAN_ERR_CNT_TFN_MASK) >> FCAN_ERR_CNT_TFN_SHIFT;
+}
+
+u32 FCan_RecvByIrq(FCan_t *Can_p, struct FCan_Frame *Frame_p, u32 FrameNumber)
+{
+ u32 FifoCnt = 0;
+ FCan_Config_t *Config_p;
+ u32 CanId;
+ u32 Dlc;
+ u32 CanFrameIndex = 0;
+ u32 RxValue;
+ Ft_assertZeroNum(Can_p != NULL);
+ Ft_assertZeroNum(Can_p->IsReady == FT_COMPONENT_IS_READLY);
+ Config_p = &Can_p->Config;
+
+ FifoCnt = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_FIFO_CNT_OFFSET) & 0x3f;
+
+ if (0 == FifoCnt)
+ {
+ return 0;
+ }
+
+ FrameNumber = (FrameNumber > FifoCnt) ? FifoCnt : FrameNumber;
+
+ while (FrameNumber)
+ {
+ /* Read a frame from Phytium CAN */
+ CanId = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_RX_FIFO_OFFSET);
+ /* if CanId is big-endian ,use swap change to little-endian */
+ CanId = FT_SWAP32(CanId);
+ /* Identifier extension */
+ if (CanId & FCAN_IDR_IDE_MASK)
+ {
+ Dlc = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_RX_FIFO_OFFSET);
+ Dlc = FT_SWAP32(Dlc);
+ Dlc = ((Dlc & FCAN_IDR_EDLC_MASK) >> FCAN_IDR_EDLC_SHIFT);
+
+ Frame_p[CanFrameIndex].CanId = (CanId & FCAN_IDR_ID1_MASK) >> 3;
+ Frame_p[CanFrameIndex].CanId |= (CanId & FCAN_IDR_ID2_MASK) >> FCAN_IDR_ID2_SHIFT;
+ Frame_p[CanFrameIndex].CanId |= CAN_EFF_FLAG;
+
+ if (CanId & FCAN_IDR_RTR_MASK)
+ {
+ Frame_p[CanFrameIndex].CanId |= CAN_RTR_FLAG;
+ }
+ }
+ else
+ {
+ Dlc = ((CanId & FCAN_IDR_DLC_MASK) >> FCAN_IDR_SDLC_SHIFT);
+
+ /* The received frame is a standard format frame */
+ Frame_p[CanFrameIndex].CanId = (CanId & FCAN_IDR_ID1_MASK) >> FCAN_IDR_ID1_SHIFT;
+ if (CanId & FCAN_IDR_SRR_MASK)
+ {
+ Frame_p[CanFrameIndex].CanId |= CAN_RTR_FLAG;
+ }
+ }
+
+ Frame_p[CanFrameIndex].CanDlc = (Dlc > sizeof(Frame_p[CanFrameIndex].data)) ? sizeof(Frame_p[CanFrameIndex].data) : Dlc;
+
+ if (!(Frame_p[CanFrameIndex].CanId & CAN_RTR_FLAG))
+ {
+ if (Frame_p[CanFrameIndex].CanDlc > 0)
+ {
+ RxValue = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_RX_FIFO_OFFSET);
+ memcpy(Frame_p[CanFrameIndex].data, &RxValue, sizeof(RxValue));
+ }
+
+ if (Frame_p[CanFrameIndex].CanDlc > 4)
+ {
+ RxValue = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_RX_FIFO_OFFSET);
+ memcpy(&Frame_p[CanFrameIndex].data[4], &RxValue, sizeof(RxValue));
+ }
+ }
+ FrameNumber--;
+ CanFrameIndex++;
+ }
+
+ return (CanFrameIndex + 1);
+}
+
+static void FCan_SendFifo(FCan_t *Can_p, struct FCan_Frame *Frame_p)
+{
+ u32 Id, Dlc;
+ FCan_Config_t *Config_p;
+ u32 SendBuffer = 0;
+ Ft_assertVoid(Can_p != NULL);
+ Ft_assertVoid(Can_p->IsReady == FT_COMPONENT_IS_READLY);
+ Config_p = &Can_p->Config;
+ if (Frame_p->CanId & CAN_EFF_FLAG)
+ {
+ /* Extended CAN ID format */
+ Id = ((Frame_p->CanId & CAN_EFF_MASK) << FCAN_IDR_ID2_SHIFT) &
+ FCAN_IDR_ID2_MASK;
+ Id |= (((Frame_p->CanId & CAN_EFF_MASK) >>
+ (CAN_EFF_ID_BITS - CAN_SFF_ID_BITS))
+ << FCAN_IDR_ID1_SHIFT) &
+ FCAN_IDR_ID1_MASK;
+
+ Id |= FCAN_IDR_IDE_MASK | FCAN_IDR_SRR_MASK;
+ if (Frame_p->CanId & CAN_RTR_FLAG)
+ {
+ Id |= FCAN_IDR_RTR_MASK;
+ }
+
+ Dlc = Frame_p->CanDlc << FCAN_IDR_EDLC_SHIFT;
+
+ FCan_WriteReg(Config_p->CanBaseAddress, FCAN_TX_FIFO_OFFSET, FT_SWAP32(Id));
+ FCan_WriteReg(Config_p->CanBaseAddress, FCAN_TX_FIFO_OFFSET, FT_SWAP32(Dlc));
+ }
+ else
+ {
+ /* Standard CAN ID format */
+ Id = ((Frame_p->CanId & CAN_SFF_MASK) << FCAN_IDR_ID1_SHIFT) &
+ FCAN_IDR_ID1_MASK;
+ if (Frame_p->CanId & CAN_RTR_FLAG)
+ Id |= FCAN_IDR_SRR_MASK;
+
+ Dlc = ((Frame_p->CanDlc << FCAN_IDR_SDLC_SHIFT) | FCAN_IDR_PAD_MASK);
+ Id |= Dlc;
+ FCan_WriteReg(Config_p->CanBaseAddress, FCAN_TX_FIFO_OFFSET, FT_SWAP32(Id));
+ }
+
+ if (!(Frame_p->CanId & CAN_RTR_FLAG))
+ {
+ if (Frame_p->CanDlc > 0)
+ {
+ memcpy(&SendBuffer, Frame_p->data, 4);
+ FCan_WriteReg(Config_p->CanBaseAddress, FCAN_TX_FIFO_OFFSET, SendBuffer);
+ }
+
+ if (Frame_p->CanDlc > 4)
+ {
+ memcpy(&SendBuffer, &Frame_p->data[4], 4);
+ FCan_WriteReg(Config_p->CanBaseAddress, FCAN_TX_FIFO_OFFSET, SendBuffer);
+ }
+ }
+}
+
+u32 FCan_SendByIrq(FCan_t *Can_p,
+ struct FCan_Frame *Frame_p,
+ u32 FrameNumber, void (*UserIrqWait)(void))
+{
+ FCan_Config_t *Config_p;
+ u32 FrameIndex = 0;
+ u32 NeedSendOnce;
+ u32 cnt = 0;
+ Ft_assertZeroNum(Can_p != NULL);
+ Ft_assertZeroNum(Can_p->IsReady == FT_COMPONENT_IS_READLY);
+ Config_p = &Can_p->Config;
+
+ if (NULL == Frame_p)
+ {
+ FT_CAN_DEBUG_E("Frame_p is NULL , %s: %d", __FILE__, __LINE__);
+ return 0;
+ }
+
+ if (0 == FrameNumber)
+ {
+ FT_CAN_DEBUG_E("FrameNumber is 0 , %s: %d", __FILE__, __LINE__);
+ return 0;
+ }
+
+ for (; 0 < FrameNumber;)
+ {
+ if (FrameNumber > Config_p->TxFifoDeepth)
+ {
+ NeedSendOnce = Config_p->TxFifoDeepth;
+ FrameNumber -= Config_p->TxFifoDeepth;
+ }
+ else
+ {
+ NeedSendOnce = FrameNumber;
+ FrameNumber = 0;
+ }
+ Ft_printf("shut down tranmission \r\n");
+ /*shut down tranmission*/
+ FCan_ClearBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
+ FCan_ClearBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_TXREQ_MASK);
+ FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
+ Ft_printf("NeedSendOnce %d \r\n", NeedSendOnce);
+ for (cnt = 0; cnt < NeedSendOnce; cnt++)
+ {
+ FCan_SendFifo(Can_p, &Frame_p[FrameIndex]);
+ FrameIndex++;
+ }
+ Can_p->TxFifoCnt = NeedSendOnce;
+
+ /* triggers tranmission */
+ FCan_ClearBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
+ FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_TXREQ_MASK);
+ FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_TXREQ_MASK | FCAN_CTRL_XFER_MASK);
+
+ if (UserIrqWait)
+ {
+ UserIrqWait();
+ }
+ else
+ {
+ while (0 != Can_p->TxFifoCnt)
+ {
+ };
+ }
+ }
+
+ return FrameIndex + 1;
+}
+
+ft_error_t FCan_SetTiming(FCan_t *Can_p,
+ struct FCan_Bittiming *Bittiming_p)
+{
+ u32 Btr = 0;
+ FCan_Config_t *Config_p;
+ u32 IsConfigMode;
+ Ft_assertNonvoid(Can_p != NULL);
+ Ft_assertNonvoid(Can_p->IsReady == FT_COMPONENT_IS_READLY);
+ Config_p = &Can_p->Config;
+
+ Ft_assertNonvoid(Bittiming_p->brp != 0);
+ Ft_assertNonvoid(Bittiming_p->prop_seg != 0);
+ Ft_assertNonvoid(Bittiming_p->phase_seg1 != 0);
+ Ft_assertNonvoid(Bittiming_p->phase_seg2 != 0);
+
+ /* Setting Baud Rate prescalar value in BRPR Register */
+ Btr = (Bittiming_p->brp - 1) << 16;
+ Btr |= (Bittiming_p->prop_seg - 1) << 2;
+ Btr |= (Bittiming_p->phase_seg1 - 1) << 5;
+ Btr |= (Bittiming_p->phase_seg2 - 1) << 8;
+ Btr |= (Bittiming_p->sjw - 1);
+
+ IsConfigMode = (FCan_ReadReg(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET) & FCAN_CTRL_XFER_MASK);
+
+ if (IsConfigMode)
+ {
+ FCan_WriteReg(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
+ }
+
+ FCan_WriteReg(Config_p->CanBaseAddress, FCAN_DAT_RATE_CTRL_OFFSET, Btr);
+ FCan_WriteReg(Config_p->CanBaseAddress, FCAN_ARB_RATE_CTRL_OFFSET, Btr);
+
+ /*Enable Transfer*/
+ FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
+
+ return FCAN_SUCCESS;
+}
+
+void FCan_Enable(FCan_t *Can_p)
+{
+ FCan_Config_t *Config_p;
+ Ft_assertVoid(Can_p != NULL);
+ Ft_assertVoid(Can_p->IsReady == FT_COMPONENT_IS_READLY);
+ Config_p = &Can_p->Config;
+
+ FCan_WriteReg(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
+}
diff --git a/bsp/ft2004/libraries/bsp/ft_can/ft_can.h b/bsp/ft2004/libraries/bsp/ft_can/ft_can.h
new file mode 100644
index 0000000000..35998daf05
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_can/ft_can.h
@@ -0,0 +1,142 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-27 15:08:44
+ * @LastEditTime: 2021-04-27 15:08:44
+ * @Description:  Description of file
+ * @Modify History:
+ * * * Ver   Who        Date         Changes
+ * * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef FT_CAN_H
+#define FT_CAN_H
+
+#include "ft_types.h"
+#include "ft_error_code.h"
+
+#define FCAN_SUCCESS FST_SUCCESS /* SUCCESS */
+#define FCAN_FAILURE FT_MAKE_ERRCODE(errCan, errBspGeneral, FST_FAILURE) /* Normal */
+#define FCAN_TIMEOUT FT_MAKE_ERRCODE(errCan, errBspGeneral, FST_TIMEOUT) /* Timeout */
+#define FCAN_EILSEQ FT_MAKE_ERRCODE(errCan, errBspGeneral, FST_EILSEQ) /* Illegal byte sequence. */
+#define FCAN_INVALID_PARAM FT_MAKE_ERRCODE(errCan, errBspGeneral, FST_INVALID_PARAM) /* Invalid param. */
+
+#define FCAN_HANDLER_SEND 1U /**< Handler type for frame sending interrupt */
+#define FCAN_HANDLER_RECV 2U /**< Handler type for frame reception interrupt*/
+#define FCAN_HANDLER_ERROR 3U /**< Handler type for error interrupt */
+#define FCAN_DATA_LENGTH 8U
+
+/* CAN payload length and DLC definitions according to ISO 11898-1 */
+#define CAN_MAX_DLC 8
+#define CAN_MAX_DLEN 8
+#define CAN_MAX_CTL 3
+#define CAN_SFF_ID_BITS 11
+#define CAN_EFF_ID_BITS 29
+
+/* special address description flags for the CAN_ID */
+#define CAN_EFF_FLAG 0x80000000U /* EFF/SFF is set in the MSB */
+#define CAN_RTR_FLAG 0x40000000U /* remote transmission request */
+#define CAN_ERR_FLAG 0x20000000U /* error message frame */
+
+/* valid bits in CAN ID for frame formats */
+#define CAN_SFF_MASK 0x000007FFU /* standard frame format (SFF) */
+#define CAN_EFF_MASK 0x1FFFFFFFU /* extended frame format (EFF) */
+#define CAN_ERR_MASK 0x1FFFFFFFU /* omit EFF, RTR, ERR flags */
+
+/* Frame type */
+#define STANDARD_FRAME 0 /* standard frame */
+#define EXTEND_FRAME 1 /* extended frame */
+
+typedef void (*FCan_irqHandler_t)(void *Args);
+
+struct FCan_Frame
+{
+ u32 CanId;
+ u8 CanDlc;
+ u8 data[FCAN_DATA_LENGTH];
+};
+
+struct FCan_Bittiming
+{
+ u32 bitrate; /* Bit-rate in bits/second */
+ u32 sample_point; /* Sample point in one-tenth of a percent */
+ u32 tq; /* Time quanta (TQ) in nanoseconds */
+ u32 prop_seg; /* Propagation segment in TQs */
+ u32 phase_seg1; /* Phase buffer segment 1 in TQs */
+ u32 phase_seg2; /* Phase buffer segment 2 in TQs */
+ u32 sjw; /* Synchronisation jump width in TQs */
+ u32 brp; /* Bit-rate prescaler */
+};
+
+typedef struct
+{
+ u32 InstanceId; /* Id of device */
+ u32 CanBaseAddress; /* Can base Address */
+ u32 IrqNum;
+ u32 BaudRate;
+ u32 TxFifoDeepth; /* The depth of the full frame , */
+} FCan_Config_t;
+
+typedef struct
+{
+ FCan_Config_t Config;
+ u32 IsReady; /* Device is initialized and ready */
+
+ volatile u32 TxFifoCnt;
+
+ FCan_irqHandler_t SendHandler;
+ void *SendRef;
+
+ FCan_irqHandler_t RecvHandler;
+ void *RecvRef;
+
+ FCan_irqHandler_t ErrorHandler;
+ void *ErrorRef;
+
+} FCan_t;
+
+FCan_Config_t *FCan_LookupConfig(u32 InstanceId);
+
+/**
+ * @name: FCan_CfgInitialize
+ * @msg: This function initializes a Can instance/driver.
+ * @in param Can_p: Can_p is a pointer to the FCan_t instance.
+ * @in param Config_p: Config_p points to the FCan_t device configuration structure.
+ * @return {*}
+ */
+ft_error_t FCan_CfgInitialize(FCan_t *Can_p, FCan_Config_t *Config_p);
+
+/**
+ * @name: FCan_SetHandler
+ * @msg: This routine installs an asynchronous callback function for the given
+ * @inout param Can_p: Can_p is a pointer to the FCan_t instance.
+ * @in param HandlerType: specifies which handler is to be attached.
+ * @in param IrqCallBackFunc: IrqCallBackFunc is the address of the callback function.
+ * @in param IrqCallBackRef: IrqCallBackRef is a user data item that will be passed to the
+ * callback function when it is invoked.
+ * @return {*}
+ * @param {FCan_t} *Can_p
+ * @param {u32} HandlerType
+ * @param {FCan_irqHandler_t} *IrqCallBackFunc
+ * @param {void} *IrqCallBackRef
+ */
+ft_error_t FCan_SetHandler(FCan_t *Can_p, u32 HandlerType, FCan_irqHandler_t IrqCallBackFunc, void *IrqCallBackRef);
+
+ft_error_t FCan_SetTiming(FCan_t *Can_p,
+ struct FCan_Bittiming *Bittiming_p);
+
+void FCan_IntrHandler(void *InstancePtr);
+
+ft_error_t FCan_CalcBittiming(struct FCan_Bittiming *Bt_p);
+
+u32 FCan_SendByIrq(FCan_t *Can_p,
+ struct FCan_Frame *Frame_p,
+ u32 FrameNumber, void (*UserIrqWait)(void));
+
+u32 FCan_RecvByIrq(FCan_t *Can_p, struct FCan_Frame *Frame_p, u32 FrameNumber);
+
+void FCan_Enable(FCan_t *Can_p);
+
+#endif // !FT_CAN_H
diff --git a/bsp/ft2004/libraries/bsp/ft_can/ft_can_calc.c b/bsp/ft2004/libraries/bsp/ft_can/ft_can_calc.c
new file mode 100644
index 0000000000..c897b2e303
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_can/ft_can_calc.c
@@ -0,0 +1,269 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-05-06 09:30:51
+ * @LastEditTime: 2021-05-25 16:41:10
+ * @Description:  Description of file
+ * @Modify History:
+ * * * Ver   Who        Date         Changes
+ * * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_can.h"
+
+#include "ft_debug.h"
+#include "string.h"
+
+#ifndef max
+#define max(x, y) (((x) < (y)) ? (y) : (x))
+#endif
+
+#ifndef min
+#define min(x, y) (((x) < (y)) ? (x) : (y))
+#endif
+
+#define FT_CAN_DEBUG_TAG "FT_CAN"
+
+#define FT_CAN_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__)
+#define FT_CAN_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__)
+#define FT_CAN_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__)
+
+#define CAN_CLK_FREQ 600000000
+#define CAN_CALC_SYNC_SEG 1
+#define FCAN_TSEG1_MIN 1
+#define FCAN_TSEG1_MAX 8
+#define FCAN_TSEG2_MIN 1
+#define FCAN_TSEG2_MAX 8
+#define FCAN_SJW_MAX 4
+#define FCAN_BRP_MIN 1
+#define FCAN_BRP_MAX 512
+#define FCAN_BRP_INC 1
+#define FCAN_CALC_SYNC_SEG 1
+#define CAN_CALC_MAX_ERROR 50 /* in one-tenth of a percent */
+#define BEST_BITRATE_ERROR (2147483647 * 2U + 1)
+
+#define clamp(x, low, high) (min(max(low, x), high))
+
+typedef struct can_bittiming_const
+{
+ char name[16]; /* Name of the CAN controller hardware */
+ u32 tseg1_min; /* Time segement 1 = prop_seg + phase_seg1 */
+ u32 tseg1_max;
+ u32 tseg2_min; /* Time segement 2 = phase_seg2 */
+ u32 tseg2_max;
+ u32 sjw_max; /* Synchronisation jump width */
+ u32 brp_min; /* Bit-rate prescaler */
+ u32 brp_max;
+ u32 brp_inc;
+} FTCAN_BITTIMING_CONST;
+
+static const struct can_bittiming_const ftcan_bittiming_const = {
+ .name = "vxbftCan",
+ .tseg1_min = 1,
+ .tseg1_max = 8,
+ .tseg2_min = 1,
+ .tseg2_max = 8,
+ .sjw_max = 4,
+ .brp_min = 1,
+ .brp_max = 512,
+ .brp_inc = 1,
+};
+
+static int abs(
+ int i /* integer for which to return absolute value */
+)
+{
+ return (i >= 0 ? i : -i);
+}
+
+static u32 div64_32(u64 *n, u32 base)
+{
+ u64 rem = *n;
+ u64 b = base;
+ u64 res, d = 1;
+ u32 high = rem >> 32;
+
+ /* Reduce the thing a bit first */
+ res = 0;
+ if (high >= base)
+ {
+ high /= base;
+ res = (u64)high << 32;
+ rem -= (u64)(high * base) << 32;
+ }
+
+ while ((u64)b > 0 && b < rem)
+ {
+ b = b + b;
+ d = d + d;
+ }
+
+ do
+ {
+ if (rem >= b)
+ {
+ rem -= b;
+ res += d;
+ }
+ b >>= 1;
+ d >>= 1;
+ } while (d);
+
+ *n = res;
+ return rem;
+}
+
+s32 can_update_sample_point(const struct can_bittiming_const *btc,
+ u32 sample_point_nominal, u32 tseg,
+ u32 *tseg1_ptr, u32 *tseg2_ptr,
+ u32 *sample_point_error_ptr)
+{
+ u32 sample_point_error, best_sample_point_error = BEST_BITRATE_ERROR;
+ u32 sample_point, best_sample_point = 0;
+ u32 tseg1, tseg2;
+ s32 i;
+
+ for (i = 0; i <= 1; i++)
+ {
+ tseg2 = tseg + CAN_CALC_SYNC_SEG - (sample_point_nominal * (tseg + CAN_CALC_SYNC_SEG)) / 1000 - i;
+ tseg2 = clamp(tseg2, btc->tseg2_min, btc->tseg2_max);
+ tseg1 = tseg - tseg2;
+ if (tseg1 > btc->tseg1_max)
+ {
+ tseg1 = btc->tseg1_max;
+ tseg2 = tseg - tseg1;
+ }
+
+ sample_point = 1000 * (tseg + CAN_CALC_SYNC_SEG - tseg2) / (tseg + CAN_CALC_SYNC_SEG);
+ sample_point_error = abs(sample_point_nominal - sample_point);
+
+ if ((sample_point <= sample_point_nominal) && (sample_point_error < best_sample_point_error))
+ {
+ best_sample_point = sample_point;
+ best_sample_point_error = sample_point_error;
+ *tseg1_ptr = tseg1;
+ *tseg2_ptr = tseg2;
+ }
+ }
+
+ if (sample_point_error_ptr)
+ *sample_point_error_ptr = best_sample_point_error;
+
+ return best_sample_point;
+}
+
+ft_error_t FCan_CalcBittiming(struct FCan_Bittiming *Bt_p)
+{
+ u32 bitrate; /* current bitrate */
+ u32 bitrate_error; /* difference between current and nominal value */
+ u32 best_bitrate_error = BEST_BITRATE_ERROR;
+ u32 sample_point_error; /* difference between current and nominal value */
+ u32 best_sample_point_error = BEST_BITRATE_ERROR;
+ u32 sample_point_nominal; /* nominal sample point */
+ u32 best_tseg = 0; /* current best value for tseg */
+ u32 best_brp = 0; /* current best value for brp */
+ u32 brp, tsegall, tseg, tseg1 = 0, tseg2 = 0;
+ u64 v64;
+ const struct can_bittiming_const *btc = &ftcan_bittiming_const;
+ struct FCan_Bittiming *bt = Bt_p;
+
+ if (bt->sample_point)
+ {
+ sample_point_nominal = bt->sample_point;
+ }
+ else
+ {
+ if (bt->bitrate > 800000)
+ sample_point_nominal = 750;
+ else if (bt->bitrate > 500000)
+ sample_point_nominal = 800;
+ else
+ sample_point_nominal = 875;
+ }
+
+ for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1;
+ tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--)
+ {
+ tsegall = CAN_CALC_SYNC_SEG + tseg / 2;
+
+ /* Compute all possible tseg choices (tseg=tseg1+tseg2) */
+ brp = CAN_CLK_FREQ / (tsegall * bt->bitrate) + tseg % 2;
+
+ /* choose brp step which is possible in system */
+ brp = (brp / btc->brp_inc) * btc->brp_inc;
+
+ if ((brp < btc->brp_min) || (brp > btc->brp_max))
+ continue;
+
+ bitrate = CAN_CLK_FREQ / (brp * tsegall);
+
+ bitrate_error = abs(bt->bitrate - bitrate);
+ /* tseg brp biterror */
+ if (bitrate_error > best_bitrate_error)
+ continue;
+
+ /* reset sample point error if we have a better bitrate */
+ if (bitrate_error < best_bitrate_error)
+ best_sample_point_error = BEST_BITRATE_ERROR;
+
+ can_update_sample_point(btc, sample_point_nominal, tseg / 2, &tseg1, &tseg2, &sample_point_error);
+ if (sample_point_error > best_sample_point_error)
+ continue;
+
+ best_sample_point_error = sample_point_error;
+ best_bitrate_error = bitrate_error;
+ best_tseg = tseg / 2;
+ best_brp = brp;
+
+ if (bitrate_error == 0 && sample_point_error == 0)
+ break;
+ }
+
+ if (best_bitrate_error)
+ {
+ /* Error in one-tenth of a percent */
+ v64 = (u64)best_bitrate_error * 1000;
+ div64_32(&v64, bt->bitrate);
+ bitrate_error = (u32)v64;
+ if (bitrate_error > CAN_CALC_MAX_ERROR)
+ {
+ FT_CAN_DEBUG_E("bitrate error");
+ }
+ return FCAN_FAILURE;
+ FT_CAN_DEBUG_E("bitrate error 2");
+ }
+
+ /* real sample point */
+ bt->sample_point = can_update_sample_point(btc, sample_point_nominal, best_tseg,
+ &tseg1, &tseg2, NULL);
+
+ v64 = (u64)best_brp * 1000 * 1000 * 1000;
+ div64_32(&v64, CAN_CLK_FREQ);
+ bt->tq = (u64)v64;
+ bt->prop_seg = tseg1 / 2;
+ bt->phase_seg1 = tseg1 - bt->prop_seg;
+ bt->phase_seg2 = tseg2;
+
+ /* check for sjw user settings */
+ if (!bt->sjw || !btc->sjw_max)
+ {
+ bt->sjw = 1;
+ }
+ else
+ {
+ /* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */
+ if (bt->sjw > btc->sjw_max)
+ bt->sjw = btc->sjw_max;
+ /* bt->sjw must not be higher than tseg2 */
+ if (tseg2 < bt->sjw)
+ bt->sjw = tseg2;
+ }
+
+ bt->brp = best_brp;
+
+ /* real bitrate */
+ bt->bitrate = CAN_CLK_FREQ / (bt->brp * (CAN_CALC_SYNC_SEG + tseg1 + tseg2));
+ return FCAN_SUCCESS;
+}
diff --git a/bsp/ft2004/libraries/bsp/ft_can/ft_can_g.c b/bsp/ft2004/libraries/bsp/ft_can/ft_can_g.c
new file mode 100644
index 0000000000..77edbc84fc
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_can/ft_can_g.c
@@ -0,0 +1,39 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-27 15:31:44
+ * @LastEditTime: 2021-04-27 15:31:44
+ * @Description:  Description of file
+ * @Modify History:
+ * * * Ver   Who        Date         Changes
+ * * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_can.h"
+#include "ft_parameters.h"
+
+FCan_Config_t FCan_Config[FT_CAN_NUM] =
+ {
+ {
+ .InstanceId = 0, /* Id of device */
+ .CanBaseAddress = FT_CAN0_BASEADDR, /* Can base Address */
+ .IrqNum = FT_CAN0_IRQNUM,
+ .BaudRate = 250000,
+ .TxFifoDeepth = 16,
+ },
+ {
+ .InstanceId = 1, /* Id of device */
+ .CanBaseAddress = FT_CAN1_BASEADDR, /* Can base Address */
+ .IrqNum = FT_CAN1_IRQNUM,
+ .BaudRate = 250000,
+ .TxFifoDeepth = 16,
+ },
+ {
+ .InstanceId = 2, /* Id of device */
+ .CanBaseAddress = FT_CAN2_BASEADDR, /* Can base Address */
+ .IrqNum = FT_CAN2_IRQNUM,
+ .BaudRate = 250000,
+ .TxFifoDeepth = 16,
+ }};
diff --git a/bsp/ft2004/libraries/bsp/ft_can/ft_can_hw.c b/bsp/ft2004/libraries/bsp/ft_can/ft_can_hw.c
new file mode 100644
index 0000000000..1af32abf46
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_can/ft_can_hw.c
@@ -0,0 +1,55 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-27 13:52:41
+ * @LastEditTime: 2021-04-27 13:52:41
+ * @Description:  Description of file
+ * @Modify History:
+ * * * Ver   Who        Date         Changes
+ * * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_can_hw.h"
+#include "ft_can.h"
+#include "ft_mux.h"
+#include "ft_parameters.h"
+#include "ft_math.h"
+#include "ft_assert.h"
+#include "ft_debug.h"
+
+#define CAN_HW_DEBUG_TAG "CAN_HW"
+
+#define CAN_HW_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(CAN_HW_DEBUG_TAG, format, ##__VA_ARGS__)
+#define CAN_HW_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(CAN_HW_DEBUG_TAG, format, ##__VA_ARGS__)
+#define CAN_HW_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(CAN_HW_DEBUG_TAG, format, ##__VA_ARGS__)
+
+void FCan_Reset(FCan_t *Can_p)
+{
+ u32 RegValue;
+ FCan_Config_t *Config_p;
+ Ft_assertVoid(Can_p != NULL);
+ Ft_assertVoid(Can_p->IsReady == FT_COMPONENT_IS_READLY);
+ Config_p = &Can_p->Config;
+
+ RegValue = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET);
+
+ if (RegValue & FCAN_CTRL_XFER_MASK)
+ {
+ CAN_HW_DEBUG_E("FT can is not in configration mode\n");
+ Ft_assertVoid(0);
+ return;
+ }
+
+ FCan_WriteReg(FT_PIN_DEMUX_BASE, FT_PIN_DEMUX_REG204_OFFSET, 0x89999990); // Reuse can IO
+
+ FCan_WriteReg(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_RESET_MASK);
+ FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_AIME_MASK);
+ FCan_WriteReg(Config_p->CanBaseAddress, FCAN_ACC_ID0_MASK_OFFSET, FCAN_ACC_IDN_MASK);
+ FCan_WriteReg(Config_p->CanBaseAddress, FCAN_ACC_ID1_MASK_OFFSET, FCAN_ACC_IDN_MASK);
+ FCan_WriteReg(Config_p->CanBaseAddress, FCAN_ACC_ID2_MASK_OFFSET, FCAN_ACC_IDN_MASK);
+ FCan_WriteReg(Config_p->CanBaseAddress, FCAN_ACC_ID3_MASK_OFFSET, FCAN_ACC_IDN_MASK);
+ FCan_ClearBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_RESET_MASK);
+ FCan_WriteReg(Config_p->CanBaseAddress, FCAN_INTR_OFFSET, FCAN_INTR_TEIE_MASK | FCAN_INTR_REIE_MASK);
+}
diff --git a/bsp/ft2004/libraries/bsp/ft_can/ft_can_hw.h b/bsp/ft2004/libraries/bsp/ft_can/ft_can_hw.h
new file mode 100644
index 0000000000..634a765774
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_can/ft_can_hw.h
@@ -0,0 +1,161 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-27 13:52:47
+ * @LastEditTime: 2021-04-27 13:52:47
+ * @Description:  Description of file
+ * @Modify History:
+ * * * Ver   Who        Date         Changes
+ * * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef FT_CAN_HW_H
+#define FT_CAN_HW_H
+
+#include "ft_types.h"
+#include "ft_io.h"
+#include "ft_can.h"
+
+/***ft CAN REGISTER offset*/
+#define FCAN_CTRL_OFFSET 0x00 /* Global control register */
+#define FCAN_INTR_OFFSET 0x04 /* Interrupt register */
+#define FCAN_ARB_RATE_CTRL_OFFSET 0x08 /* Arbitration rate control register */
+#define FCAN_DAT_RATE_CTRL_OFFSET 0x0C /* Data rate control register */
+#define FCAN_ACC_ID0_OFFSET 0x10 /* Acceptance identifier0 register */
+#define FCAN_ACC_ID1_OFFSET 0x14 /* Acceptance identifier1 register */
+#define FCAN_ACC_ID2_OFFSET 0x18 /* Acceptance identifier2 register */
+#define FCAN_ACC_ID3_OFFSET 0x1C /* Acceptance identifier3 register */
+#define FCAN_ACC_ID0_MASK_OFFSET 0x20 /* Acceptance identifier0 mask register */
+#define FCAN_ACC_ID1_MASK_OFFSET 0x24 /* Acceptance identifier1 mask register */
+#define FCAN_ACC_ID2_MASK_OFFSET 0x28 /* Acceptance identifier2 mask register */
+#define FCAN_ACC_ID3_MASK_OFFSET 0x2C /* Acceptance identifier3 mask register */
+#define FCAN_XFER_STS_OFFSET 0x30 /* Transfer status register */
+#define FCAN_ERR_CNT_OFFSET 0x34 /* Error counter register */
+#define FCAN_FIFO_CNT_OFFSET 0x38 /* FIFO counter register */
+#define FCAN_DMA_CTRL_OFFSET 0x3C /* DMA request control register */
+#define FCAN_TX_FIFO_OFFSET 0x100 /* TX FIFO shadow register */
+#define FCAN_RX_FIFO_OFFSET 0x200 /* RX FIFO shadow register */
+
+/*----------------------------------------------------------------------------*/
+/* CAN register bit masks - FCAN_<REG>_<BIT>_MASK */
+/*----------------------------------------------------------------------------*/
+
+/* FCAN_CTRL mask */
+#define FCAN_CTRL_XFER_MASK (0x1 << 0) /* RW */ /*Transfer enable*/
+#define FCAN_CTRL_TXREQ_MASK (0x1 << 1) /* RW */ /*Transmit request*/
+#define FCAN_CTRL_AIME_MASK (0x1 << 2) /* RW */ /*Acceptance identifier mask enable*/
+#define FCAN_CTRL_RESET_MASK (0x1 << 6)
+
+/* FCAN_INTR mask */
+#define FCAN_INTR_STATUS_MASK (0xFF << 0) /* RO */ /*the interrupt status*/
+#define FCAN_INTR_BOIS_MASK (0x1 << 0) /* RO */ /*Bus off interrupt status*/
+#define FCAN_INTR_PWIS_MASK (0x1 << 1) /* RO */ /*Passive warning interrupt status*/
+#define FCAN_INTR_PEIS_MASK (0x1 << 2) /* RO */ /*Passive error interrupt status*/
+#define FCAN_INTR_RFIS_MASK (0x1 << 3) /* RO */ /*RX FIFO full interrupt status*/
+#define FCAN_INTR_TFIS_MASK (0x1 << 4) /* RO */ /*TX FIFO empty interrupt status*/
+#define FCAN_INTR_REIS_MASK (0x1 << 5) /* RO */ /*RX frame end interrupt status*/
+#define FCAN_INTR_TEIS_MASK (0x1 << 6) /* RO */ /*TX frame end interrupt status*/
+#define FCAN_INTR_EIS_MASK (0x1 << 7) /* RO */ /*Error interrupt status*/
+
+#define FCAN_INTR_EN_MASK (0xFF << 8) /* RO */ /*the interrupt enable*/
+#define FCAN_INTR_BOIE_MASK (0x1 << 8) /* RW */ /*Bus off interrupt enable*/
+#define FCAN_INTR_PWIE_MASK (0x1 << 9) /* RW */ /*Passive warning interrupt enable*/
+#define FCAN_INTR_PEIE_MASK (0x1 << 10) /* RW */ /*Passive error interrupt enable*/
+#define FCAN_INTR_RFIE_MASK (0x1 << 11) /* RW */ /*RX FIFO full interrupt enable*/
+#define FCAN_INTR_TFIE_MASK (0x1 << 12) /* RW */ /*TX FIFO empty interrupt enable*/
+#define FCAN_INTR_REIE_MASK (0x1 << 13) /* RW */ /*RX frame end interrupt enable*/
+#define FCAN_INTR_TEIE_MASK (0x1 << 14) /* RW */ /*TX frame end interrupt enable*/
+#define FCAN_INTR_EIE_MASK (0x1 << 15) /* RW */ /*Error interrupt enable*/
+
+#define FCAN_INTR_BOIC_MASK (0x1 << 16) /* WO */ /*Bus off interrupt clear*/
+#define FCAN_INTR_PWIC_MASK (0x1 << 17) /* WO */ /*Passive warning interrupt clear*/
+#define FCAN_INTR_PEIC_MASK (0x1 << 18) /* WO */ /*Passive error interrupt clear*/
+#define FCAN_INTR_RFIC_MASK (0x1 << 19) /* WO */ /*RX FIFO full interrupt clear*/
+#define FCAN_INTR_TFIC_MASK (0x1 << 20) /* WO */ /*TX FIFO empty interrupt clear*/
+#define FCAN_INTR_REIC_MASK (0x1 << 21) /* WO */ /*RX frame end interrupt clear*/
+#define FCAN_INTR_TEIC_MASK (0x1 << 22) /* WO */ /*TX frame end interrupt clear*/
+#define FCAN_INTR_EIC_MASK (0x1 << 23) /* WO */ /*Error interrupt clear*/
+
+/* FCAN_ACC_ID(0-3)_MASK mask */
+#define FCAN_ACC_IDN_MASK 0x1FFFFFFF /* WO */ /*don’t care the matching */
+/* FCAN_DAT_RATE_CTRL mask */
+
+/* FCAN_ERR_CNT_OFFSET mask */
+#define FCAN_ERR_CNT_RFN_MASK (0xFF << 0) /* RO */ /*Receive error counter*/
+#define FCAN_ERR_CNT_TFN_MASK (0xFF << 16) /* RO */ /*Transmit error counter*/
+
+/* FCAN_FIFO_CNT_OFFSET mask */
+#define FCAN_FIFO_CNT_RFN_MASK (0xFF << 0) /* RO */ /*Receive FIFO valid data number*/
+#define FCAN_FIFO_CNT_TFN_MASK (0xFF << 16) /* RO */ /*Transmit FIFO valid data number*/
+
+#define FCAN_ERR_CNT_TFN_SHIFT 16 /* Tx Error Count shift */
+#define FCAN_FIFO_CNT_TFN_SHIFT 16 /* Tx FIFO Count shift*/
+#define FCAN_IDR_ID1_SHIFT 21 /* Standard Messg Identifier */
+#define FCAN_IDR_ID2_SHIFT 1 /* Extended Message Identifier */
+#define FCAN_IDR_SDLC_SHIFT 14
+#define FCAN_IDR_EDLC_SHIFT 26
+#define FCAN_ACC_IDN_SHIFT 18 /*Standard ACC ID shift*/
+
+#define FCAN_IDR_ID2_MASK 0x0007FFFE /* Extended message ident */
+#define FCAN_IDR_ID1_MASK 0xFFE00000 /* Standard msg identifier */
+#define FCAN_IDR_IDE_MASK 0x00080000 /* Identifier extension */
+#define FCAN_IDR_SRR_MASK 0x00100000 /* Substitute remote TXreq */
+#define FCAN_IDR_RTR_MASK 0x00000001 /* Extended frames remote TX request */
+#define FCAN_IDR_DLC_MASK 0x0003C000 /* Standard msg dlc */
+#define FCAN_IDR_PAD_MASK 0x00003FFF /* Standard msg padding 1 */
+#define FCAN_IDR_EDLC_MASK 0x3C000000 /* Extended msg dlc */
+
+/* Can timming */
+#define FCAN_TSEG1_MIN 1
+#define FCAN_TSEG1_MAX 8
+#define FCAN_TSEG2_MIN 1
+#define FCAN_TSEG2_MAX 8
+#define FCAN_SJW_MAX 4
+#define FCAN_BRP_MIN 1
+#define FCAN_BRP_MAX 512
+#define FCAN_BRP_INC 1
+#define FCAN_CALC_SYNC_SEG 1
+
+/**
+*
+* This macro reads the given register.
+*
+* @param BaseAddr is the base address of the device.
+* @param RegOffset is the register offset to be read.
+*
+* @return The 32-bit value of the register
+*
+* @note None.
+*
+*****************************************************************************/
+#define FCan_ReadReg(BaseAddr, RegOffset) \
+ Ft_in32((BaseAddr) + (u32)(RegOffset))
+
+/****************************************************************************/
+/**
+*
+* This macro writes the given register.
+*
+* @param BaseAddr is the base address of the device.
+* @param RegOffset is the register offset to be written.
+* @param Data is the 32-bit value to write to the register.
+*
+* @return None.
+*
+* @note None.
+*
+*****************************************************************************/
+#define FCan_WriteReg(BaseAddr, RegOffset, Data) \
+ Ft_out32((BaseAddr) + (u32)(RegOffset), (u32)(Data))
+
+#define FCan_SetBit(BaseAddr, RegOffset, Data) \
+ Ft_setBit32((BaseAddr) + (u32)(RegOffset), (u32)(Data))
+
+#define FCan_ClearBit(BaseAddr, RegOffset, Data) \
+ Ft_clearBit32((BaseAddr) + (u32)(RegOffset), (u32)(Data))
+
+void FCan_Reset(FCan_t *Can_p);
+
+#endif // !
diff --git a/bsp/ft2004/libraries/bsp/ft_can/ft_can_intr.c b/bsp/ft2004/libraries/bsp/ft_can/ft_can_intr.c
new file mode 100644
index 0000000000..6fb4cdd074
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_can/ft_can_intr.c
@@ -0,0 +1,118 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-29 10:40:47
+ * @LastEditTime: 2021-04-29 10:40:47
+ * @Description:  Description of file
+ * @Modify History:
+ * * * Ver   Who        Date         Changes
+ * * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_can.h"
+#include "ft_can_hw.h"
+#include "ft_assert.h"
+#include "ft_types.h"
+
+ft_error_t FCan_SetHandler(FCan_t *Can_p, u32 HandlerType, FCan_irqHandler_t IrqCallBackFunc, void *IrqCallBackRef)
+{
+ ft_error_t status = FCAN_SUCCESS;
+ Ft_assertNonvoid(Can_p != NULL);
+ Ft_assertNonvoid(Can_p->IsReady == FT_COMPONENT_IS_READLY);
+ switch (HandlerType)
+ {
+ case FCAN_HANDLER_SEND:
+ Can_p->SendHandler = IrqCallBackFunc;
+ Can_p->SendRef = IrqCallBackRef;
+ break;
+ case FCAN_HANDLER_RECV:
+ Can_p->RecvHandler = IrqCallBackFunc;
+ Can_p->RecvRef = IrqCallBackRef;
+ break;
+ case FCAN_HANDLER_ERROR:
+ Can_p->ErrorHandler = IrqCallBackFunc;
+ Can_p->ErrorRef = IrqCallBackRef;
+ break;
+ default:
+ status = FCAN_FAILURE;
+ }
+
+ return status;
+}
+
+static void FCan_TxInterrupt(FCan_t *Can_p)
+{
+ FCan_Config_t *Config_p = &Can_p->Config;
+ FCan_SetBit(Config_p->CanBaseAddress, FCAN_INTR_OFFSET, FCAN_INTR_TEIC_MASK | FCAN_INTR_REIC_MASK);
+
+ if (0 != Can_p->TxFifoCnt)
+ {
+ Can_p->TxFifoCnt--;
+ FCan_ClearBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
+ FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_TXREQ_MASK);
+ FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
+ }
+ else
+ {
+ if (Can_p->SendHandler)
+ {
+ Can_p->SendHandler(Can_p->SendRef);
+ }
+ }
+}
+
+static void FCan_ErrorInterrupt(FCan_t *Can_p)
+{
+ if (Can_p->ErrorHandler)
+ {
+ Can_p->ErrorHandler(Can_p->ErrorRef);
+ }
+}
+
+static void FCan_RxInterrupt(FCan_t *Can_p)
+{
+ if (Can_p->RecvHandler)
+ {
+ Can_p->RecvHandler(Can_p->RecvRef);
+ }
+}
+
+void FCan_IntrHandler(void *InstancePtr)
+{
+ u32 Irq;
+ FCan_t *Can_p = (FCan_t *)InstancePtr;
+ FCan_Config_t *Config_p;
+ Ft_assertVoid(Can_p != NULL);
+ Ft_assertVoid(Can_p->IsReady == FT_COMPONENT_IS_READLY);
+ Config_p = &Can_p->Config;
+ Irq = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_INTR_OFFSET);
+
+ if (0 == Irq)
+ {
+ return;
+ }
+
+ /* Check for the type of error interrupt and Processing it */
+ if (Irq & FCAN_INTR_TEIS_MASK)
+ {
+ Irq &= ~FCAN_INTR_REIS_MASK;
+ FCan_TxInterrupt(Can_p);
+ }
+
+ if (Irq & (FCAN_INTR_EIS_MASK | FCAN_INTR_RFIS_MASK |
+ FCAN_INTR_BOIS_MASK | FCAN_INTR_PEIS_MASK | FCAN_INTR_PWIS_MASK))
+ {
+ FCan_SetBit(Config_p->CanBaseAddress, FCAN_INTR_OFFSET, (FCAN_INTR_EIC_MASK | FCAN_INTR_RFIC_MASK | FCAN_INTR_BOIC_MASK | FCAN_INTR_PEIC_MASK | FCAN_INTR_PWIC_MASK));
+ FCan_ErrorInterrupt(Can_p);
+ }
+
+ if (Irq & FCAN_INTR_REIS_MASK)
+ {
+ FCan_SetBit(Config_p->CanBaseAddress, FCAN_INTR_OFFSET, FCAN_INTR_REIE_MASK);
+ FCan_RxInterrupt(Can_p);
+ FCan_SetBit(Config_p->CanBaseAddress, FCAN_INTR_OFFSET, FCAN_INTR_REIC_MASK);
+ FCan_SetBit(Config_p->CanBaseAddress, FCAN_INTR_OFFSET, FCAN_INTR_REIE_MASK);
+ }
+}
diff --git a/bsp/ft2004/libraries/bsp/ft_can/ft_can_sinit.c b/bsp/ft2004/libraries/bsp/ft_can/ft_can_sinit.c
new file mode 100644
index 0000000000..d9b3c816a8
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_can/ft_can_sinit.c
@@ -0,0 +1,40 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-27 15:31:57
+ * @LastEditTime: 2021-04-27 15:31:57
+ * @Description:  Description of file
+ * @Modify History:
+ * * * Ver   Who        Date         Changes
+ * * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_can.h"
+#include "ft_parameters.h"
+
+extern FCan_Config_t FCan_Config[FT_CAN_NUM];
+
+/**
+ * @name:
+ * @msg:
+ * @in param:
+ * @return {*}
+ * @param {u32} InstanceId
+ */
+FCan_Config_t *FCan_LookupConfig(u32 InstanceId)
+{
+ FCan_Config_t *CfgPtr = NULL;
+ u32 Index;
+
+ for (Index = 0; Index < (u32)FT_CAN_NUM; Index++)
+ {
+ if (FCan_Config[Index].InstanceId == InstanceId)
+ {
+ CfgPtr = &FCan_Config[Index];
+ break;
+ }
+ }
+ return (FCan_Config_t *)CfgPtr;
+}
diff --git a/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac.c b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac.c
new file mode 100644
index 0000000000..c4ed19b408
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac.c
@@ -0,0 +1,109 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-05-25 16:43:14
+ * @Description:  This files is for gmac ctrl
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_gmac.h"
+#include "ft_gmac_hw.h"
+#include "ft_assert.h"
+#include "ft_io.h"
+#include "ft_status.h"
+#include "ft_printf.h"
+#include "ft_parameters.h"
+
+static void Ft_Gmac_StubHandler(void *args)
+{
+ Ft_assertVoidAlways();
+}
+
+static void Ft_Gmac_StubErrorHandler(void *CallBackRef, u32 ErrorWord)
+{
+ // Ft_assertVoidAlways();
+}
+
+s32 Ft_Gmac_HwInitialize(Ft_Gmac_t *Gmac)
+{
+ Ft_assertNonvoid(Gmac != NULL);
+ Ft_assertNonvoid(Gmac->IsReady == FT_COMPONENT_IS_READLY);
+ return FGmac_InitializeHw(&Gmac->Config);
+}
+
+s32 Ft_GmacCfgInitialize(Ft_Gmac_t *Gmac, FGmac_Config_t *Config)
+{
+ Ft_assertNonvoid(Gmac != NULL);
+ Ft_assertNonvoid(Config != NULL);
+
+ Gmac->Config = *Config;
+ Gmac->IsReady = FT_COMPONENT_IS_READLY;
+
+ FGmac_SetHandler(Gmac, FT_GMAC_TX_COMPLETE_CB_ID, Ft_Gmac_StubHandler, Gmac);
+ FGmac_SetHandler(Gmac, FT_GMAC_RX_COMPLETE_CB_ID, Ft_Gmac_StubHandler, Gmac);
+ FGmac_SetHandler(Gmac, FT_GMAC_DMA_ERROR_CB_ID, Ft_Gmac_StubErrorHandler, Gmac);
+
+ return FST_SUCCESS;
+}
+
+s32 Ft_Gmac_Start(Ft_Gmac_t *Gmac)
+{
+ FGmac_Config_t *Config = NULL;
+ Ft_assertNonvoid(Gmac != NULL);
+ Ft_assertNonvoid(Gmac->IsReady == FT_COMPONENT_IS_READLY);
+ Config = &Gmac->Config;
+
+ FGmac_DMAReceptionTransmissionEnable(Config);
+ FGmac_ReceptionTransmissionEnable(Config);
+
+ /* Clear Tx and Rx process stopped flags */
+ Ft_out32(Gmac->Config.BaseAddress + DMA_INTR_ENA_OFFSET, DMA_INTR_ENA_RIE | DMA_INTR_ENA_AIE | DMA_INTR_ENA_NIE);
+
+ return FST_SUCCESS;
+}
+
+s32 Ft_Gmac_Stop(Ft_Gmac_t *Gmac)
+{
+ FGmac_Config_t *Config = NULL;
+ Ft_assertNonvoid(Gmac != NULL);
+ Ft_assertNonvoid(Gmac->IsReady == FT_COMPONENT_IS_READLY);
+ Config = &Gmac->Config;
+
+ FGmac_TransmissionDisable(Config);
+ FGmac_ReceptionDisable(Config);
+ FGmac_DMATransmissionDisable(Config);
+ FGmac_DMAReceptionDisable(Config);
+ return FST_SUCCESS;
+}
+
+void Ft_Gmac_Phy_Debug(Ft_Gmac_t *Gmac)
+{
+
+ Ft_printf("\r\n ****************************** \r\n");
+}
+
+
+void Ft_Gmac_UseDefaultMacAddr(Ft_Gmac_t *Gmac, u8 *MacAddr)
+{
+ u32 MacAddrLo;
+ u32 MacAddrHi;
+ FGmac_Config_t *pConfig;
+ Ft_assertNoneReturn(Gmac != NULL);
+ pConfig = &Gmac->Config;
+
+ MacAddrLo = Ft_in32(pConfig->BaseAddress + GMAC_MAC_ADDR0_LOWER16BIT_OFFSET);
+ MacAddrHi = Ft_in32(pConfig->BaseAddress + GMAC_MAC_ADDR0_UPPER16BIT_OFFSET);
+
+ MacAddr[0] = MacAddrLo & 0xFF;
+ MacAddr[1] = (MacAddrLo >> 8) & 0xFF;
+ MacAddr[2] = (MacAddrLo >> 16) & 0xFF;
+ MacAddr[3] = (MacAddrLo >> 24) & 0xFF;
+ MacAddr[4] = MacAddrHi & 0xFF;
+ MacAddr[5] = (MacAddrHi >> 8) & 0xFF;
+}
diff --git a/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac.h b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac.h
new file mode 100644
index 0000000000..332c431456
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac.h
@@ -0,0 +1,319 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-05-24 14:32:56
+ * @Description:  This files is for
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ * 1.00a hh 2021-02-05 First release
+ */
+
+#ifndef FT_GMAC_H
+#define FT_GMAC_H
+
+#include "ft_types.h"
+#define GMAC_INC_DESC(x, y) (x) = (((x) + 1) % y)
+/**
+ * @name: Callback invoked when frame(s) have been sent or received in interrupt
+ * driven DMA mode .to set the send callback ,invoke FGmac_SetHandler()
+ * @msg:
+ * @param {void} *CallBackRef
+ * @return {*}
+ */
+typedef void (*FGmac_IntrCallback_t)(void *CallBackRef);
+
+/**
+ * @name: FGmac_ErrIntrCallback_t
+ * @msg: Callback whem asynchronous error occurs. To set this callback, invoke
+ * FGmac_ErrIntrCallback_t .
+ * @param {void} *CallBackRef
+ * @param {u32} ErrorWord definition varies with Error
+ * @return {*}
+ */
+typedef void (*FGmac_ErrIntrCallback_t)(void *CallBackRef, u32 ErrorWord);
+
+/**
+ *
+ *
+ */
+typedef void (*Ft_Gmac_MacPhyStatus_Callback)(void *CallBackRef, u32 MacPhyStatus);
+
+/** GMAC_SPEED */
+#define GMAC_SPEED_10M 0x00000001U
+#define GMAC_SPEED_100M 0x00000002U
+#define GMAC_SPEED_1000M 0x00000004U
+
+#define IS_RIGHT_SPEED()
+
+/* GMAC_AutoNegotiation */
+#define GMAC_AUTONEGOTIATION_ENABLE 0x00000001U
+#define GMAC_AUTONEGOTIATION_DISABLE 0x00000000U
+
+/* GMAC_Duplex_Mode */
+#define GMAC_MODE_FULLDUPLEX 0x00000001U
+#define GMAC_MODE_HALFDUPLEX 0x00000000U
+
+/* GMAC_Rx_Mode */
+#define GMAC_RXPOLLING_MODE 0x00000000U
+#define GMAC_RXINTERRUPT_MODE 0x00000001U
+
+/* GMAC_Checksum_Mode */
+#define GMAC_CHECKSUM_BY_SOFTWARE 0x00000000U
+#define GMAC_CHECKSUM_BY_HARDWARE 0x00000001U
+
+/* GMAC_Media_Interface */
+#define GMAC_MEDIA_INTERFACE_RGMII 0x00000000U
+#define GMAC_MEDIA_INTERFACE_MII 0x00000001U
+
+/* Gmac Error value */
+
+#define GMAC_ERROR_TRANSMIT_PROCESS_STOPPED 0x00000001U
+#define GMAC_ERROR_TRANSMIT_UNAVAILABLE_STATUS 0x00000002U
+#define GMAC_ERROR_TRANSMIT_JABBER_TIMEOUT 0x00000004U
+#define GMAC_ERROR_RECEIVE_FIFO_OVERFLOW 0x00000008U
+#define GMAC_ERROR_TRANSMIT_UNDERFLOW 0x00000010U
+#define GMAC_ERROR_RECEIVE_BUFFER_UNAVAILABLE 0x00000020U
+#define GMAC_ERROR_RECEIVE_PROCESS_STOPPED 0x00000040U
+#define GMAC_ERROR_RECEIVE_WATCHDOG_TIMEOUT 0x00000080U
+#define GMAC_ERROR_EARLY_TRANSMIT_INTERRUPT 0x000000100U
+#define GMAC_ERROR_FATAL_BUS_ERROR 0x000000200U
+#define GMAC_ERROR_UNDEFINED 0x000000400U
+
+typedef enum
+{
+ FT_GMAC_TX_COMPLETE_CB_ID = 0x01U, /*!< Gmac Tx Complete Callback ID */
+ FT_GMAC_RX_COMPLETE_CB_ID = 0x02U, /*!< Gmac Rx Complete Callback ID */
+ FT_GMAC_DMA_ERROR_CB_ID = 0x03U, /*!< Gmac DMA Error Callback ID */
+ FT_GMAC_MAC_PHY_STATUS_CB_ID = 0x04U, /*!< */
+} FGmac_IsrCallbackSelect_t;
+
+/* Gmac DMA Descriptors data structure definition */
+
+typedef struct
+{
+ volatile u32 Status; /*!< Status */
+ u32 Control; /*!< Control and Buffer1, Buffer2 lengths */
+ u32 Buffer1Addr; /*!< Buffer1 address pointer */
+ u32 Buffer2NextDescAddr; /*!< Buffer2 or next descriptor address pointer */
+} FGmac_DmaDesc_t;
+
+/* Received Frame Informations structure definition */
+typedef struct
+{
+ FGmac_DmaDesc_t *FSRxDesc; /*!< First Segment Rx Desc */
+ FGmac_DmaDesc_t *LSRxDesc; /*!< Last Segment Rx Desc */
+ u32 SegCount; /*!< Segment count */
+ u32 length; /*!< Frame length */
+ u32 buffer; /*!< Frame buffer */
+} FGmac_DmaRxFrameInfos;
+
+typedef struct
+{
+ u32 InstanceId; /* Id of device */
+ uintptr_t CommonAddress; /* Gmac Common Register */
+ uintptr_t BaseAddress; /* Physical base address of Mac Private Address */
+ u32 IRQ_NUM;
+ u32 IRQPriority;
+ s32 PhyAddr; /* Phy Ic Addre1 ,-1 is need to auto check*/
+ u32 clkMDC; /* MDC clock access PHY. [1.0MHz ~2.5MHz] */
+ u32 AutoNegotiation; /* Selects or not the AutoNegotiation mode for the external PHY
+ The AutoNegotiation allows an automatic setting of the Speed (10/100/1000Mbps)
+ and the mode (half/full-duplex).
+ This parameter can be a value of @ref GMAC_AutoNegotiation */
+ u32 Speed; /* Sets the Ethernet speed: 10/100/1000 Mbps.
+ This parameter can be a value of @ref GMAC_SPEED */
+ u32 DuplexMode; /* Selects the MAC duplex mode: Half-Duplex or Full-Duplex mode
+ This parameter can be a value of @ref GMAC_Duplex_Mode */
+ u32 RxMode; /* Selects the Ethernet Rx mode: Polling mode, Interrupt mode.
+ This parameter can be a value of @ref GMAC_Rx_Mode */
+ u32 ChecksumMode; /* Selects if the checksum is check by hardware or by software.
+ This parameter can be a value of @ref GMAC_Checksum_Mode */
+ u32 MediaInterface; /* Selects the media-independent interface or the reduced media-independent interface.
+ This parameter can be a value of @ref GMAC_Media_Interface */
+ u8 MacAddr[6]; /* 6 bytes Mac address */
+
+} FGmac_Config_t;
+
+/* Only for Dma ring structure */
+struct DescRingData
+{
+ u32 DescIndex; /* For Current Desc position */
+ u32 DescBufIndex; /* For Current Desc buffer buf position */
+ u32 DescMaxNumber; /* Max Number for Desc and Desc buffer */
+ u8 *DescBufBase; /* Desc buffer Base */
+};
+
+typedef struct
+{
+ FGmac_Config_t Config; /* Hardware configuration */
+ u32 IsReady; /* Device is initialised and ready */
+ u32 Options; /* Current options word */
+
+ FGmac_DmaDesc_t *RxDesc; /*!< Rx descriptor to Get */
+ struct DescRingData RxDescRingData;
+ FGmac_DmaDesc_t *TxDesc; /*!< Tx descriptor to Set */
+ struct DescRingData TxDescRingData;
+
+ FGmac_IntrCallback_t SendHandler;
+ FGmac_IntrCallback_t RecvHandler;
+ Ft_Gmac_MacPhyStatus_Callback StatusHandler;
+ void *SendArgs;
+ void *RecvArgs;
+ void *StatusArgs;
+ FGmac_ErrIntrCallback_t ErrorHandler;
+ void *ErrorArgs;
+
+ FGmac_DmaRxFrameInfos DMARxFrameInfos; /* Only for chain structure */
+
+} Ft_Gmac_t;
+
+/**
+ * @name: FGmac_DmaRxDescRingInit
+ * @msg: 化标准 DMA 接收描述符 在ring结构下的初始化。
+ * @param {Ft_Gmac_t} *Gmac Gmac对象
+ * @param {FGmac_DmaDesc_t} *DMARxDescTab 用户定义的静态 DMA 接收描述符表格
+ * @param {u8} *RxBuff 用户定义的用于匹配 DMA 接收描述符表格的缓冲区
+ * @param {u32} DescBufPerLength 每个缓冲区的大小
+ * @param {u32} RxBuffCount 缓冲区的总数量
+ * @return {s32} Common_status 参数。
+ */
+s32 FGmac_DmaRxDescRingInit(Ft_Gmac_t *Gmac,
+ FGmac_DmaDesc_t *DMATxDescTab,
+ u8 *TxBuff,
+ u32 DescBufPerLength,
+ u32 TxBuffCount);
+
+/**
+ * @name: FGmac_DmaTxDescRingInit
+ * @msg: 标准 DMA 发送描述符 在ring结构下的初始化。
+ * @param {Ft_Gmac_t} *Gmac Gmac对象
+ * @param {FGmac_DmaDesc_t} *DMATxDescTab 用户定义的静态 DMA 发送描述符表格
+ * @param {u8} *TxBuff 用户定义的用于匹配 DMA 发送描述符表格的缓冲区
+ * @param {u32} DescBufPerLength 每个缓冲区的大小
+ * @param {u32} TxBuffCount 缓冲区的总数量
+ * @return {s32} Common_status 参数
+ */
+s32 FGmac_DmaTxDescRingInit(Ft_Gmac_t *Gmac,
+ FGmac_DmaDesc_t *DMATxDescTab,
+ u8 *TxBuff,
+ u32 DescBufPerLength,
+ u32 TxBuffCount);
+
+/**
+ * @name: FGmac_TransmitframeRingPoll
+ * @msg: 轮询的方式发送DMA发送表述符
+ * @param {Ft_Gmac_t} *Gmac Gmac对象
+ * @param {uint32_t} FrameLength 需要发送数据的有效长度
+ * @return {s32} Common_status 参数
+ */
+s32 FGmac_TransmitframeRingPoll(Ft_Gmac_t *Gmac, uint32_t FrameLength);
+
+/**
+ * @name: FGmac_RingGetReceivedFrame_IT
+ * @msg: 检查标准ring结构的DMA接收符中是否有完整的数据包。
+ * @param {Ft_Gmac_t} *Gmac Gmac对象
+ * @return {s32} Common_status 参数
+ */
+s32 FGmac_RingGetReceivedFrame_IT(Ft_Gmac_t *Gmac);
+
+/**
+ * @name: FGmac_ResumeTransmission
+ * @msg: 检查 DMA_STATUS_TU 符号是否存在,如果存在将其置位,恢复DMA 描述符的发送 。
+ * @param {Ft_Gmac_t} *Gmac Gmac对象
+ * @return {void}
+ */
+void FGmac_ResumeTransmission(Ft_Gmac_t *Gmac);
+
+/**
+ * @name: FGmac_SetTransmitUnderflow
+ * @msg: 检查 DMA_STATUS_UNF 符号是否存在,如果存在将其置位,恢复DMA 描述符的发送 。
+ * @param {Ft_Gmac_t} *Gmac Gmac对象
+ * @return {void}
+ */
+void FGmac_SetTransmitUnderflow(Ft_Gmac_t *Gmac);
+
+/**
+ * @name: FGmac_ResumeTransmissionReception
+ * @msg: 检查 DMA_STATUS_RU 符号是否存在,如果存在将其置位,恢复DMA 描述符的接收 。
+ * @param {Ft_Gmac_t} *Gmac
+ * @return {void}
+ */
+void FGmac_ResumeTransmissionReception(Ft_Gmac_t *Gmac);
+
+/**
+ * @name: Ft_Gmac_LookupConfig
+ * @msg: 获取 Gmac 静态预设配置参数 。
+ * @param {u32} InstanceId Gmac 实例编号。
+ * @return {FGmac_Config_t *} 返回Gmac的静态配置
+ */
+FGmac_Config_t *Ft_Gmac_LookupConfig(u32 InstanceId);
+
+/**
+ * @name: Ft_Gmac_HwInitialize
+ * @msg: 对于Gmac Mac 层 与Phy 层的硬件部分进行预设初始化配置
+ * @param {Ft_Gmac_t} *Gmac Gmac对象。
+ * @return {s32} Common_status 参数
+ */
+s32 Ft_Gmac_HwInitialize(Ft_Gmac_t *Gmac);
+
+/**
+ * @name: Ft_GmacCfgInitialize
+ * @msg: 初始化,硬件配置相关参数。
+ * @param {Ft_Gmac_t} *Gmac Gmac对象。
+ * @param {FGmac_Config_t} *Config
+ * @return {s32} Common_status 参数
+ */
+s32 Ft_GmacCfgInitialize(Ft_Gmac_t *Gmac, FGmac_Config_t *Config);
+
+/**
+ * @name: Ft_Gmac_Start
+ * @msg: 开启Gmac 的 发送接收功能,并且开启中断功能。
+ * @param {Ft_Gmac_t} *Gmac Gmac对象。
+ * @return {s32} Common_status 参数
+ */
+s32 Ft_Gmac_Start(Ft_Gmac_t *Gmac);
+
+/**
+ * @name: Ft_Gmac_Stop
+ * @msg: 关闭Gmac 的 发送接收功能。
+ * @param {Ft_Gmac_t} *Gmac Gmac对象。
+ * @return {s32} Common_status 参数
+ */
+s32 Ft_Gmac_Stop(Ft_Gmac_t *Gmac);
+
+/**
+ * @name: FGmac_IntrHandler
+ * @msg: Gmac 中断函数,用于响应Gmac 相关所以函数
+ * @param {void} *Args Ft_Gmac_t *Gmac 参数传入
+ * @return {void}
+ */
+void FGmac_IntrHandler(void *Args);
+
+/**
+ * @name: FGmac_SetHandler
+ * @msg: 根据SelectIndex 配置 中断过程中响应函数
+ * @param {Ft_Gmac_t} *Gmac Gmac对象。
+ * @param {FGmac_IsrCallbackSelect_t} SelectIndex
+ * @param {void} *FuncPtr
+ * @param {void} *Args
+ * @return {s32} Common_status 参数
+ */
+s32 FGmac_SetHandler(Ft_Gmac_t *Gmac, FGmac_IsrCallbackSelect_t SelectIndex, void *FuncPtr, void *Args);
+
+void Ft_Gmac_Phy_Debug(Ft_Gmac_t *Gmac);
+
+/**
+ * @name: Ft_Gmac_UseDefaultMacAddr
+ * @msg: 在有uboot的模式之下,使用默认的Mac0配置参数。
+ * @in param{Ft_Gmac_t *}: Gmac对象
+ * @out param{u8 *}: 输出的Mac参数
+ * @return {None}:
+ */
+void Ft_Gmac_UseDefaultMacAddr(Ft_Gmac_t *Gmac, u8 *MacAddr);
+
+#endif // !GMAC_H
diff --git a/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_desc.c b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_desc.c
new file mode 100644
index 0000000000..6071e08df9
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_desc.c
@@ -0,0 +1,357 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-05-25 16:42:13
+ * @Description:  This files is for gmac description
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_gmac_desc.h"
+#include "ft_gmac_hw.h"
+#include "ft_parameters.h"
+
+#include "ft_io.h"
+#include "ft_status.h"
+#include "ft_assert.h"
+#include "ft_cache.h"
+#include "ft_debug.h"
+#include <string.h>
+
+#define GMAC_DESC_DEBUG_TAG "GMAC_DESC"
+
+#define GMAC_DESC_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(GMAC_DESC_DEBUG_TAG, format, ##__VA_ARGS__)
+#define GMAC_DESC_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(GMAC_DESC_DEBUG_TAG, format, ##__VA_ARGS__)
+#define GMAC_DESC_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(GMAC_DESC_DEBUG_TAG, format, ##__VA_ARGS__)
+
+void FGmac_ResumeTransmission(Ft_Gmac_t *Gmac)
+{
+ /* When Tx Buffer unavailable flag is set: clear it and resume transmission */
+ if ((Ft_in32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET) & DMA_STATUS_TU) == DMA_STATUS_TU)
+ {
+ /* Clear TBUS GMAC DMA flag */
+ Ft_out32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET, DMA_STATUS_TU);
+
+ /* Resume DMA transmission*/
+ Ft_out32(Gmac->Config.BaseAddress + DMA_XMT_POLL_DEMAND_OFFSET, 0xff);
+ }
+}
+
+void FGmac_SetTransmitUnderflow(Ft_Gmac_t *Gmac)
+{
+ /* When Tx Buffer unavailable flag is set: clear it and resume transmission */
+ if ((Ft_in32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET) & DMA_STATUS_UNF) == DMA_STATUS_UNF)
+ {
+ /* Clear TBUS GMAC DMA flag */
+ Ft_out32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET, DMA_STATUS_UNF);
+
+ /* Resume DMA transmission*/
+ Ft_out32(Gmac->Config.BaseAddress + DMA_XMT_POLL_DEMAND_OFFSET, 0xff);
+ }
+}
+
+s32 FGmac_DMATxDescChainInit(Ft_Gmac_t *Gmac, FGmac_DmaDesc_t *DMATxDescTab, u8 *TxBuff, u32 TxBuffCount)
+{
+ u32 i;
+ FGmac_DmaDesc_t *TxDesc;
+ Ft_assertNonvoid(Gmac != NULL);
+ Ft_assertNonvoid(Gmac->IsReady == FT_COMPONENT_IS_READLY);
+
+ /* Make Each DmaTx descriptor with initialized value*/
+ for (i = 0; i < TxBuffCount; i++)
+ {
+ TxDesc = DMATxDescTab + i;
+ TxDesc->Control = DMA_TDES1_SECOND_ADDRESS_CHAINED;
+ TxDesc->Buffer1Addr = (u32)(&TxBuff[i * GMAC_MAX_PACKET_SIZE]);
+
+ /* Initialize the next descriptor with the Next Descriptor Polling Enable */
+ if (i < (TxBuffCount - 1))
+ {
+ /* Set next descriptor address register with next descriptor base address */
+ TxDesc->Buffer2NextDescAddr = (u32)(DMATxDescTab + i + 1);
+ Ft_printf(" Buffer2NextDescAddr %x \r\n", TxDesc->Buffer2NextDescAddr);
+ }
+ else
+ {
+ /* For last descriptor, set next descriptor address register equal to the first descriptor base address */
+ TxDesc->Buffer2NextDescAddr = (u32)DMATxDescTab;
+ Ft_printf(" Buffer2NextDescAddr %x \r\n", TxDesc->Buffer2NextDescAddr);
+ }
+ }
+ Ft_printf("DMATxDescTab addr is %x", DMATxDescTab);
+
+ return FST_SUCCESS;
+}
+
+s32 FGmac_DmaTxDescRingInit(Ft_Gmac_t *Gmac, FGmac_DmaDesc_t *DMATxDescTab, u8 *TxBuff, u32 DescBufPerLength, u32 TxBuffCount)
+{
+ u32 i;
+ FGmac_DmaDesc_t *TxDesc;
+ Ft_assertNonvoid(Gmac != NULL);
+ Ft_assertNonvoid(Gmac->IsReady == FT_COMPONENT_IS_READLY);
+
+ memset(&Gmac->TxDescRingData, 0, sizeof(Gmac->TxDescRingData));
+ Gmac->TxDescRingData.DescMaxNumber = TxBuffCount;
+ memset(DMATxDescTab, 0, sizeof(FGmac_DmaDesc_t) * TxBuffCount);
+ DMATxDescTab[TxBuffCount - 1].Control |= DMA_TDES1_END_RING;
+ for (i = 0; i < TxBuffCount; i++)
+ {
+ TxDesc = DMATxDescTab + i;
+ FCache_cpuDcacheInvalidate(&TxBuff[i * DescBufPerLength], DescBufPerLength);
+ TxDesc->Buffer1Addr = (u32)(&TxBuff[i * DescBufPerLength]);
+ }
+ Ft_out32(Gmac->Config.BaseAddress + DMA_TX_BASE_ADDR_OFFSET, (u32)DMATxDescTab);
+ return FST_SUCCESS;
+}
+
+s32 FGmac_TransmitframeRingPoll(Ft_Gmac_t *Gmac, uint32_t FrameLength)
+{
+ u32 Size = 0U;
+ u32 i = 0U;
+ u32 BufCount = 0U;
+ FGmac_DmaDesc_t *TxDesc;
+
+ if (0U == FrameLength)
+ {
+ return FST_SUCCESS;
+ }
+
+ if (FrameLength > GMAC_MAX_PACKET_SIZE)
+ {
+ BufCount = FrameLength / GMAC_MAX_PACKET_SIZE;
+ if (FrameLength % GMAC_MAX_PACKET_SIZE)
+ {
+ BufCount++;
+ }
+ }
+ else
+ {
+ BufCount = 1U;
+ }
+
+ if (BufCount == 1U)
+ {
+
+ TxDesc = &Gmac->TxDesc[Gmac->TxDescRingData.DescIndex];
+ /* Set LAST and FIRST segment */
+ TxDesc->Control |= (DMA_TDES1_FIRST_SEGMENT | DMA_TDES1_LAST_SEGMENT);
+
+ /* Set frame size */
+ TxDesc->Control &= ~(DMA_TDES1_BUFFER1_SIZE_MASK);
+ TxDesc->Control |= (FrameLength & DMA_TDES1_BUFFER1_SIZE_MASK);
+ /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
+ TxDesc->Status |= (DMA_TDES0_OWN);
+ GMAC_INC_DESC(Gmac->TxDescRingData.DescIndex, Gmac->TxDescRingData.DescMaxNumber);
+ }
+ else
+ {
+ for (i = 0U; i < BufCount; i++)
+ {
+ TxDesc = &Gmac->TxDesc[Gmac->TxDescRingData.DescIndex];
+ /* Clear FIRST and LAST segment bits */
+ TxDesc->Control &= ~(DMA_TDES1_FIRST_SEGMENT | DMA_TDES1_LAST_SEGMENT);
+
+ if (i == 0U)
+ {
+ /* Setting the first segment bit */
+ TxDesc->Control |= DMA_TDES1_FIRST_SEGMENT;
+ }
+
+ /* Program size */
+ TxDesc->Control &= ~(DMA_TDES1_BUFFER1_SIZE_MASK);
+ TxDesc->Control |= (GMAC_MAX_PACKET_SIZE & DMA_TDES1_BUFFER1_SIZE_MASK);
+
+ if (i == (BufCount - 1U))
+ {
+ /* Setting the last segment bit */
+ TxDesc->Control |= (DMA_TDES1_LAST_SEGMENT);
+ Size = FrameLength - (BufCount - 1U) * GMAC_MAX_PACKET_SIZE;
+ TxDesc->Control &= ~(DMA_TDES1_BUFFER1_SIZE_MASK);
+ TxDesc->Control |= (Size & DMA_TDES1_BUFFER1_SIZE_MASK);
+ }
+
+ /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
+ TxDesc->Status |= (DMA_TDES0_OWN);
+
+ GMAC_INC_DESC(Gmac->TxDescRingData.DescIndex, Gmac->TxDescRingData.DescMaxNumber);
+ }
+ }
+
+ FGmac_ResumeTransmission(Gmac);
+
+ return FST_SUCCESS;
+}
+
+s32 FGmac_DMARxDescChainInit(Ft_Gmac_t *Gmac, FGmac_DmaDesc_t *DMARxDescTab, u8 *RxBuff, u32 RxBuffCount)
+{
+ u32 i;
+ FGmac_DmaDesc_t *RxDesc;
+ Ft_assertNonvoid(Gmac != NULL);
+ Ft_assertNonvoid(Gmac->IsReady == FT_COMPONENT_IS_READLY);
+
+ for (i = 0; i < RxBuffCount; i++)
+ {
+ RxDesc = DMARxDescTab + i;
+ /* Set Own bit of the Rx descriptor Status */
+ RxDesc->Status = DMA_RDES0_OWN;
+
+ /* Set Buffer1 size and Second Address Chained bit */
+ RxDesc->Control = DMA_RDES1_BUFFER1_SIZE_MASK & (u32)(GMAC_MAX_PACKET_SIZE);
+ RxDesc->Control |= DMA_RDES1_SECOND_ADDRESS_CHAINED;
+ /* Set Buffer1 address pointer */
+ RxDesc->Buffer1Addr = (u32)(&RxBuff[i * GMAC_MAX_PACKET_SIZE]);
+
+ /* Initialize the next descriptor with the Next Descriptor Polling Enable */
+ if (i < (RxBuffCount - 1))
+ {
+ /* Set next descriptor address register with next descriptor base address */
+ RxDesc->Buffer2NextDescAddr = (u32)(DMARxDescTab + i + 1);
+ }
+ else
+ {
+ /* For last descriptor, set next descriptor address register equal to the first descriptor base address */
+ RxDesc->Buffer2NextDescAddr = (u32)(DMARxDescTab);
+ }
+
+ // Ft_printf("rx Buffer2NextDescAddr %x \r\n", RxDesc->Buffer2NextDescAddr);
+ }
+ Ft_out32(Gmac->Config.BaseAddress + DMA_RCV_BASE_ADDR_OFFSET, (u32)DMARxDescTab);
+ return FST_SUCCESS;
+}
+
+s32 FGmac_DmaRxDescRingInit(Ft_Gmac_t *Gmac, FGmac_DmaDesc_t *DMARxDescTab, u8 *RxBuff, u32 DescBufPerLength, u32 RxBuffCount)
+{
+ u32 i;
+ FGmac_DmaDesc_t *RxDesc;
+ Ft_assertNonvoid(Gmac != NULL);
+ Ft_assertNonvoid(Gmac->IsReady == FT_COMPONENT_IS_READLY);
+
+ memset(&Gmac->RxDescRingData, 0, sizeof(Gmac->RxDescRingData));
+ Gmac->RxDescRingData.DescMaxNumber = RxBuffCount;
+ memset(DMARxDescTab, 0, sizeof(FGmac_DmaDesc_t) * RxBuffCount);
+
+ for (i = 0; i < RxBuffCount; i++)
+ {
+ RxDesc = DMARxDescTab + i;
+ /* Set Own bit of the Rx descriptor Status */
+ RxDesc->Status = DMA_RDES0_OWN;
+ /* Set Buffer1 size and Second Address Chained bit */
+ RxDesc->Control = DMA_RDES1_BUFFER1_SIZE_MASK & (u32)(DescBufPerLength);
+ /* Set Buffer1 address pointer */
+ FCache_cpuDcacheInvalidate(&RxBuff[i * DescBufPerLength], DescBufPerLength);
+ RxDesc->Buffer1Addr = (u32)(&RxBuff[i * DescBufPerLength]);
+
+ if (i == (RxBuffCount - 1))
+ {
+ RxDesc->Control |= DMA_RDES1_END_RING;
+ }
+ }
+
+ Ft_out32(Gmac->Config.BaseAddress + DMA_RCV_BASE_ADDR_OFFSET, (u32)DMARxDescTab);
+
+ return FST_SUCCESS;
+}
+
+void FGmac_ResumeTransmissionReception(Ft_Gmac_t *Gmac)
+{
+ /* When Rx Buffer unavailable flag is set: clear it and resume transmission */
+ if ((Ft_in32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET) & DMA_STATUS_RU) == DMA_STATUS_RU)
+ {
+ /* Clear RBUS GMAC DMA flag */
+ Ft_out32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET, DMA_STATUS_RU);
+
+ /* Resume DMA transmission*/
+ Ft_out32(Gmac->Config.BaseAddress + DMA_RCV_POLL_DEMAND_OFFSET, 0xff);
+ }
+}
+
+s32 FGmac_RingGetReceivedFrame_IT(Ft_Gmac_t *Gmac)
+{
+ u32 DescriptorsCounter = 0U;
+ FGmac_DmaDesc_t *RxDesc;
+ RxDesc = &Gmac->RxDesc[Gmac->RxDescRingData.DescIndex];
+
+ while (((RxDesc->Status & DMA_RDES0_OWN) == 0) && DescriptorsCounter < Gmac->RxDescRingData.DescMaxNumber)
+ {
+ DescriptorsCounter++;
+
+ /* Check if first segment in frame */
+ if ((RxDesc->Status & (DMA_RDES0_FIRST_DESCRIPTOR | DMA_RDES0_LAST_DESCRIPTOR)) == (u32)DMA_RDES0_FIRST_DESCRIPTOR)
+ {
+ // GMAC_DESC_DEBUG_I("find first frame");
+ Gmac->RxDescRingData.DescBufIndex = Gmac->RxDescRingData.DescIndex;
+ /* Point to next descriptor */
+ GMAC_INC_DESC(Gmac->RxDescRingData.DescIndex, Gmac->RxDescRingData.DescMaxNumber);
+ RxDesc = &Gmac->RxDesc[Gmac->RxDescRingData.DescIndex];
+ } /* Check if intermediate segment */
+ else if ((RxDesc->Status & (DMA_RDES0_FIRST_DESCRIPTOR | DMA_RDES0_LAST_DESCRIPTOR)) == 0)
+ {
+ // GMAC_DESC_DEBUG_I("find invaild frame");
+ /* Point to next descriptor */
+ GMAC_INC_DESC(Gmac->RxDescRingData.DescIndex, Gmac->RxDescRingData.DescMaxNumber);
+ RxDesc = &Gmac->RxDesc[Gmac->RxDescRingData.DescIndex];
+ } /* Should be last segment */
+ else
+ {
+ Gmac->RxDescRingData.DescBufIndex = Gmac->RxDescRingData.DescIndex;
+ GMAC_INC_DESC(Gmac->RxDescRingData.DescIndex, Gmac->RxDescRingData.DescMaxNumber);
+ return FST_SUCCESS;
+ }
+ }
+ return FST_FAILURE;
+}
+
+s32 FGmac_GetReceivedFrame(Ft_Gmac_t *Gmac)
+{
+ u32 FrameLength = 0U;
+ /* Check if segment is not owned by DMA */
+ if ((Gmac->RxDesc->Status & DMA_RDES0_OWN) == 0)
+ {
+ if ((Gmac->RxDesc->Status & DMA_RDES0_LAST_DESCRIPTOR) != 0)
+ {
+ /* increment segment count */
+ Gmac->DMARxFrameInfos.SegCount++;
+
+ /* Check if last segment is first segment: one segment contains the frame */
+ if (1U == Gmac->DMARxFrameInfos.SegCount)
+ {
+ (Gmac->DMARxFrameInfos).FSRxDesc = Gmac->RxDesc;
+ }
+
+ Gmac->DMARxFrameInfos.LSRxDesc = Gmac->RxDesc;
+
+ /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */
+ FrameLength = (((Gmac->RxDesc)->Status & DMA_RDES0_FRAME_LEN_MASK) >> 16U) - 4U;
+ Gmac->DMARxFrameInfos.length = FrameLength;
+
+ /* Get the address of the buffer start address */
+ Gmac->DMARxFrameInfos.buffer = ((Gmac->DMARxFrameInfos).FSRxDesc)->Buffer1Addr;
+ /* point to next descriptor */
+ Gmac->RxDesc = (FGmac_DmaDesc_t *)((Gmac->RxDesc)->Buffer2NextDescAddr);
+
+ return FST_SUCCESS;
+ }
+ /* Check if first segment */
+ else if ((Gmac->RxDesc->Status & DMA_RDES0_FIRST_DESCRIPTOR) == (u32)DMA_RDES0_FIRST_DESCRIPTOR)
+ {
+ (Gmac->DMARxFrameInfos).FSRxDesc = Gmac->RxDesc;
+ (Gmac->DMARxFrameInfos).LSRxDesc = NULL;
+ (Gmac->DMARxFrameInfos).SegCount = 1U;
+ /* Point to next descriptor */
+ Gmac->RxDesc = (FGmac_DmaDesc_t *)(Gmac->RxDesc->Buffer2NextDescAddr);
+ } /* Check if intermediate segment */
+ else
+ {
+ (Gmac->DMARxFrameInfos).SegCount++;
+ /* Point to next descriptor */
+ Gmac->RxDesc = (FGmac_DmaDesc_t *)(Gmac->RxDesc->Buffer2NextDescAddr);
+ }
+ }
+
+ return FST_FAILURE;
+}
diff --git a/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_desc.h b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_desc.h
new file mode 100644
index 0000000000..91dd19bba2
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_desc.h
@@ -0,0 +1,20 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-04-07 13:24:16
+ * @Description:  This files is for gmac descrption
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef GMAC_DESC_H
+#define GMAC_DESC_H
+
+#include "ft_gmac.h"
+
+#endif // !
diff --git a/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_g.c b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_g.c
new file mode 100644
index 0000000000..48ca3ddbeb
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_g.c
@@ -0,0 +1,47 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-04-07 13:24:30
+ * @Description:  This files is for gmac config
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_gmac.h"
+#include "ft_parameters.h"
+
+FGmac_Config_t Gmac_ConfigTable[FT_GMAC_INSTANCES_NUM] = {
+ {FT_GMAC0_ID,
+ FT_GMAC_COMMON_ADDR,
+ FT_GMAC0_BASEADDR,
+ GMAC0_ISRNUM,
+ GMAC0_ISRPRIORITY,
+ 0,
+ 5,
+ GMAC_AUTONEGOTIATION_ENABLE,
+ GMAC_SPEED_1000M,
+ GMAC_MODE_FULLDUPLEX,
+ GMAC_RXINTERRUPT_MODE,
+ GMAC_CHECKSUM_BY_SOFTWARE,
+ GMAC_MEDIA_INTERFACE_RGMII,
+ FT_GMAC0_DEFAULT_ADDR},
+ {FT_GMAC1_ID,
+ FT_GMAC_COMMON_ADDR,
+ FT_GMAC1_BASEADDR,
+ GMAC1_ISRNUM,
+ GMAC1_ISRPRIORITY,
+ 0,
+ 5,
+ GMAC_AUTONEGOTIATION_ENABLE,
+ GMAC_SPEED_1000M,
+ GMAC_MODE_FULLDUPLEX,
+ GMAC_RXINTERRUPT_MODE,
+ GMAC_CHECKSUM_BY_SOFTWARE,
+ GMAC_MEDIA_INTERFACE_RGMII,
+ {0}},
+};
diff --git a/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_hw.c b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_hw.c
new file mode 100644
index 0000000000..a46bad28b3
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_hw.c
@@ -0,0 +1,566 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-05-25 16:42:23
+ * @Description:  This files is for gmac register
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_gmac_hw.h"
+#include "ft_types.h"
+#include "ft_generic_timer.h"
+#include "ft_assert.h"
+#include "ft_status.h"
+#include "ft_io.h"
+#include "ft_debug.h"
+#define PHY_CONFIG_DELAY_US 100
+
+#define GMAC_HW_DEBUG_TAG "GMAC_HW"
+
+#define GMAC_HW_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(GMAC_HW_DEBUG_TAG, format, ##__VA_ARGS__)
+#define GMAC_HW_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(GMAC_HW_DEBUG_TAG, format, ##__VA_ARGS__)
+#define GMAC_HW_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(GMAC_HW_DEBUG_TAG, format, ##__VA_ARGS__)
+
+s32 Gmac_WritePHYRegister(FGmac_Config_t *Config, u16 PHYReg, u32 RegValue)
+{
+ u32 TmpReg;
+ u32 Wait_Counter = 0;
+
+ TmpReg = Ft_in32(Config->BaseAddress + GMAC_MII_ADDR_OFFSET);
+
+ TmpReg |= GMAC_MII_ADDR_CR(Config->clkMDC);
+ TmpReg |= GMAC_MII_ADDR_PA(Config->PhyAddr); /* Set the PHY device address */
+ TmpReg |= GMAC_MII_ADDR_GR(PHYReg); /* Set the PHY register address */
+ TmpReg |= GMAC_MII_ADDR_GW; /* Set the write mode */
+ TmpReg |= GMAC_MII_ADDR_GB; /* Set the MII Busy bit */
+
+ Ft_out32(Config->BaseAddress + GMAC_MII_DATA_OFFSET, RegValue);
+ Ft_out32(Config->BaseAddress + GMAC_MII_ADDR_OFFSET, TmpReg);
+
+ /* Check for the Busy flag */
+ while ((Ft_in32(Config->BaseAddress + GMAC_MII_ADDR_OFFSET) & GMAC_MII_ADDR_GB) == GMAC_MII_ADDR_GB)
+ {
+ if (10000000 <= ++Wait_Counter)
+ {
+ GMAC_HW_DEBUG_E("Gmac_WritePHYRegister FST_ERROR_COUNT_MAX \r\n");
+ return FST_ERROR_COUNT_MAX;
+ }
+ }
+ return FST_SUCCESS;
+}
+
+s32 FGmac_ReadPHYRegister(FGmac_Config_t *Config, u16 PHYReg, u32 *RegValue)
+{
+ u32 TmpReg;
+ u32 Wait_Counter = 0;
+
+ TmpReg = 0;
+ TmpReg |= GMAC_MII_ADDR_CR(Config->clkMDC);
+ TmpReg |= GMAC_MII_ADDR_PA(Config->PhyAddr); /* Set the PHY device address */
+ TmpReg |= GMAC_MII_ADDR_GR(PHYReg); /* Set the PHY register address */
+ TmpReg &= ~GMAC_MII_ADDR_GW; /* Set the read mode */
+ TmpReg |= GMAC_MII_ADDR_GB; /* Set the MII Busy bit */
+
+ while ((Ft_in32(Config->BaseAddress + GMAC_MII_ADDR_OFFSET) & GMAC_MII_ADDR_GB) == GMAC_MII_ADDR_GB)
+ {
+ if (10000000 <= ++Wait_Counter)
+ {
+ GMAC_HW_DEBUG_E("wait GMAC_MII_ADDR_GB is error \r\n");
+ *RegValue = 0xffff;
+ return FST_ERROR_COUNT_MAX;
+ }
+ }
+
+ Ft_out32(Config->BaseAddress + GMAC_MII_ADDR_OFFSET, TmpReg);
+
+ while ((Ft_in32(Config->BaseAddress + GMAC_MII_ADDR_OFFSET) & GMAC_MII_ADDR_GB) == GMAC_MII_ADDR_GB)
+ {
+ if (10000000 <= ++Wait_Counter)
+ {
+ GMAC_HW_DEBUG_E("wait GMAC_MII_ADDR_GB 2 is error \r\n");
+ *RegValue = 0xffff;
+ return FST_ERROR_COUNT_MAX;
+ }
+ }
+ *RegValue = Ft_in32(Config->BaseAddress + GMAC_MII_DATA_OFFSET);
+ return FST_SUCCESS;
+}
+
+static s32 FGmac_PhyAddrGet(FGmac_Config_t *Config)
+{
+ u32 i = 0;
+ u32 phyId1;
+ u32 phyId2;
+ u8 flag = 0;
+
+ for (i = 0; i < 32; i++)
+ {
+ Config->PhyAddr = i;
+ FGmac_ReadPHYRegister(Config, PHY_ID1_REG_OFFSET, &phyId1);
+ FGmac_ReadPHYRegister(Config, PHY_ID2_REG_OFFSET, &phyId2);
+
+ if ((phyId2 & 0xffff) != 0xffff)
+ {
+ if ((0 == i) && (0x1c == phyId1) && ((phyId2 >> 10) == 0x32))
+ {
+ continue;
+ }
+ flag = 1;
+ break;
+ }
+ }
+ return (flag == 1) ? FST_SUCCESS : FST_FAILURE;
+}
+
+
+static void FGmac_MACAddressConfig(FGmac_Config_t *Config, u32 MacAddr, u8 *Addr)
+{
+ u32 tmpreg;
+ /* Calculate the selected MAC address high register */
+ tmpreg = ((u32)Addr[5] << 8) | (u32)Addr[4];
+ /* Load the selected MAC address high register */
+ Ft_out32(Config->BaseAddress + GMAC_MAC_ADDR0_UPPER16BIT_OFFSET + MacAddr, tmpreg);
+ /* Calculate the selected MAC address low register */
+ tmpreg = ((u32)Addr[3] << 24) | ((u32)Addr[2] << 16) | ((u32)Addr[1] << 8) | Addr[0];
+ /* Load the selected MAC address low register */
+ Ft_out32(Config->BaseAddress + GMAC_MAC_ADDR0_LOWER16BIT_OFFSET + MacAddr, tmpreg);
+}
+
+
+static void FGmac_MACDMAInit(FGmac_Config_t *Config)
+{
+ u32 RegValue = 0;
+ Ft_assertVoid(FGmac_PhyAddrGet(Config) == FST_SUCCESS);
+ RegValue = Ft_in32(Config->BaseAddress + GMAC_CONTROL_OFFSET);
+ /* MACCR Configuration **************************************/
+ /* Set the WD bit according to ETH Watchdog value */
+ /* Set the JD: bit according to ETH Jabber value */
+ /* Set the IFG bit according to ETH InterFrameGap value */
+ /* Set the DCRS bit according to ETH CarrierSense value */
+ /* Set the FES bit according to ETH Speed value */
+ /* Set the DO bit according to ETH ReceiveOwn value */
+ /* Set the LM bit according to ETH LoopbackMode value */
+ /* Set the DM bit according to ETH Mode value */
+ /* Set the IPCO bit according to ETH ChecksumOffload value */
+ /* Set the DR bit according to ETH RetryTransmission value */
+ /* Set the ACS bit according to ETH AutomaticPadCRCStrip value */
+ /* Set the BL bit according to ETH BackOffLimit value */
+ /* Set the DC bit according to ETH DeferralCheck value */
+ RegValue &= ~GMAC_CONTROL_WD;
+ RegValue &= ~GMAC_CONTROL_JD;
+ RegValue |= GMAC_CONTROL_IFG(0);
+ RegValue &= ~GMAC_CONTROL_DCRS;
+ RegValue &= ~GMAC_CONTROL_DO;
+ RegValue &= ~GMAC_CONTROL_LM;
+ if (Config->ChecksumMode)
+ {
+ RegValue |= GMAC_CONTROL_IPC;
+ }
+ else
+ {
+ RegValue &= ~GMAC_CONTROL_IPC;
+ }
+
+ RegValue |= GMAC_CONTROL_DR;
+ RegValue &= ~GMAC_CONTROL_ACS;
+ RegValue |= GMAC_CONTROL_BL(0);
+ RegValue &= ~GMAC_CONTROL_DC;
+ if (Config->DuplexMode == GMAC_MODE_FULLDUPLEX)
+ {
+ RegValue |= GMAC_CONTROL_DM;
+ }
+ else
+ {
+ RegValue &= ~GMAC_CONTROL_DM;
+ }
+
+ RegValue &= ~GMAC_CONTROL_FES;
+ Ft_out32(Config->BaseAddress + GMAC_CONTROL_OFFSET, RegValue);
+ Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US);
+
+ /*----------------------- GMAC MACFFR Configuration --------------------*/
+ /* Set the RA bit according to ETH ReceiveAll value */
+ /* Set the SAF and SAIF bits according to ETH SourceAddrFilter value */
+ /* Set the PCF bit according to ETH PassControlFrames value */
+ /* Set the DBF bit according to ETH BroadcastFramesReception value */
+ /* Set the DAIF bit according to ETH DestinationAddrFilter value */
+ /* Set the PR bit according to ETH PromiscuousMode value */
+ /* Set the PM, HMC and HPF bits according to ETH MulticastFramesFilter value */
+ /* Set the HUC and HPF bits according to ETH UnicastFramesFilter value */
+ /* Write to MACFFR */
+ RegValue = Ft_in32(Config->BaseAddress + GMAC_FRAME_FILTER_OFFSET);
+ RegValue |= GMAC_FRAME_FILTER_RA;
+ RegValue |= GMAC_FRAME_FILTER_PCF(2);
+ RegValue &= ~GMAC_FRAME_FILTER_PM;
+ RegValue &= ~GMAC_FRAME_FILTER_DBF;
+ RegValue &= ~GMAC_FRAME_FILTER_DAIF;
+ RegValue &= ~GMAC_FRAME_FILTER_PR;
+ Ft_out32(Config->BaseAddress + GMAC_FRAME_FILTER_OFFSET, RegValue);
+ Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US);
+
+ /*--------------- MACHTHR and MACHTLR Configuration --------------*/
+ Ft_out32(Config->BaseAddress + GMAC_HASH_HIGH_OFFSET, 0);
+ Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US);
+ Ft_out32(Config->BaseAddress + GMAC_HASH_LOW_OFFSET, 0);
+ Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US);
+
+ /*----------------------- MACFCR Configuration -------------------*/
+ /* Set the PT bit according to ETH PauseTime value */
+ /* Set the DZPQ bit according to ETH ZeroQuantaPause value */
+ /* Set the PLT bit according to ETH PauseLowThreshold value */
+ /* Set the UP bit according to ETH UnicastPauseFrameDetect value */
+ /* Set the RFE bit according to ETH ReceiveFlowControl value */
+ /* Set the TFE bit according to ETH TransmitFlowControl value */
+ RegValue = Ft_in32(Config->BaseAddress + GMAC_FLOW_CTRL_OFFSET);
+ RegValue |= GMAC_FLOW_DZPQ;
+ RegValue |= GMAC_FLOW_PLT(0);
+ RegValue &= ~GMAC_FLOW_RFE;
+ RegValue &= ~GMAC_FLOW_TFE;
+ Ft_out32(Config->BaseAddress + GMAC_FLOW_CTRL_OFFSET, RegValue);
+ Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US);
+
+ /*----------------------- MACVLANTR Configuration ----------------*/
+ /* Set the ETV bit according to ETH VLANTagComparison value */
+ /* Set the VL bit according to ETH VLANTagIdentifier value */
+ RegValue = GMAC_VLAN_TAG_VL(0);
+ RegValue &= ~GMAC_VLAN_TAG_ETV;
+ Ft_out32(Config->BaseAddress + GMAC_VLAN_TAG_OFFSET, RegValue);
+ Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US);
+
+ /* DMA default initialization ************************************/
+ /* Set the DT bit according to ETH DropTCPIPChecksumErrorFrame value */
+ /* Set the RSF bit according to ETH ReceiveStoreForward value */
+ /* Set the DFF bit according to ETH FlushReceivedFrame value */
+ /* Set the TSF bit according to ETH TransmitStoreForward value */
+ /* Set the TTC bit according to ETH TransmitThresholdControl value */
+ /* Set the FEF bit according to ETH ForwardErrorFrames value */
+ /* Set the FUF bit according to ETH ForwardUndersizedGoodFrames value */
+ /* Set the RTC bit according to ETH ReceiveThresholdControl value */
+ /* Set the OSF bit according to ETH SecondFrameOperate value */
+ RegValue = Ft_in32(Config->BaseAddress + DMA_OP_OFFSET);
+ RegValue &= DMA_OP_CLEAR_MASK;
+ RegValue &= ~DMA_OP_DT;
+ RegValue |= DMA_OP_RSF;
+ RegValue &= ~DMA_OP_DFF;
+ RegValue |= DMA_OP_TSF;
+ RegValue |= DMA_OP_TTC(7);
+ RegValue |= DMA_OP_OSF;
+ Ft_out32(Config->BaseAddress + DMA_OP_OFFSET, RegValue);
+ Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US);
+
+ /* DMABMR Configuration ------------------*/
+ /* Set the AAL bit according to ETH AddressAlignedBeats value */
+ /* Set the FB bit according to ETH FixedBurst value */
+ /* Set the RPBL and 4*PBL bits according to ETH RxDMABurstLength value */
+ /* Set the PBL and 4*PBL bits according to ETH TxDMABurstLength value */
+ /* Set the Enhanced DMA descriptors bit according to ETH EnhancedDescriptorFormat value*/
+ /* Set the DSL bit according to ETH DesciptorSkipLength value */
+ /* Set the PR and DA bits according to ETH DMAArbitration value */
+ RegValue = Ft_in32(Config->BaseAddress + DMA_BUS_MODE_OFFSET);
+ RegValue |= DMA_BUS_AAL;
+ RegValue |= DMA_BUS_FB;
+ RegValue |= DMA_BUS_RPBL(32);
+ RegValue |= DMA_BUS_PBL(32);
+ RegValue |= DMA_BUS_ATDS;
+ RegValue |= DMA_BUS_PR(0);
+ RegValue |= DMA_BUS_USP;
+ Ft_out32(Config->BaseAddress + DMA_BUS_MODE_OFFSET, RegValue);
+ Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US);
+ Ft_out32(Config->BaseAddress + DMA_AXI_BUS_MOD_OFFSET, 0x0000000e);
+ FGmac_MACAddressConfig(Config, 0, Config->MacAddr);
+}
+
+s32 FGmac_InitializeHw(FGmac_Config_t *Config)
+{
+ u32 Wait_Counter = 0;
+ u32 RegValue;
+ s32 ret = FST_SUCCESS;
+
+ /*Gmac Software reset */
+ Ft_out32(Config->BaseAddress + DMA_BUS_MODE_OFFSET, DMA_BUS_SWR);
+
+ while ((Ft_in32(Config->BaseAddress + DMA_BUS_MODE_OFFSET) & DMA_BUS_SWR) == DMA_BUS_SWR)
+ {
+ if (++Wait_Counter > 30)
+ {
+ GMAC_HW_DEBUG_E("DMA_BUS_MODE_OFFSET wait is too long ,Addr %x \r\n", Config->BaseAddress);
+ return FST_ERROR_COUNT_MAX;
+ }
+ Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US);
+ }
+ Wait_Counter = 0;
+ Ft_out32(Config->BaseAddress + DMA_BUS_MODE_OFFSET, DMA_BUS_INIT);
+
+ Ft_out32(Config->BaseAddress + DMA_OP_OFFSET, Ft_in32(Config->BaseAddress + DMA_OP_OFFSET) | DMA_OP_FTF);
+
+ while ((Ft_in32(Config->BaseAddress + DMA_OP_OFFSET) & DMA_OP_FTF) == DMA_OP_FTF)
+ {
+ if (++Wait_Counter > 30)
+ {
+ GMAC_HW_DEBUG_E("DMA_OP_OFFSET wait is too long \r\n");
+ return FST_ERROR_COUNT_MAX;
+ }
+ Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US);
+ }
+
+ Wait_Counter = 0;
+
+ /* GMAC Init */
+ Ft_out32(Config->BaseAddress + GMAC_CONTROL_OFFSET, GMAC_CONTROL_INIT);
+ /* disable flow control */
+ Ft_out32(Config->BaseAddress + GMAC_FLOW_CTRL_OFFSET, 0);
+
+ Ft_out32(Config->BaseAddress + DMA_STATUS_OFFSET, DMA_STATUS_INIT);
+
+ Ft_out32(Config->BaseAddress + DMA_INTR_ENA_OFFSET, 0);
+
+ /* get Phy addr */
+ Ft_assertNonvoid(FGmac_PhyAddrGet(Config) == FST_SUCCESS);
+
+ /*-------------------------------- MAC Initialization ----------------------*/
+ /*-------------------- PHY initialization and configuration ----------------*/
+ /* Put the PHY in reset mode */
+ if (Gmac_WritePHYRegister(Config, PHY_BCR_OFFSET, PHY_RESET) != FST_SUCCESS)
+ {
+ GMAC_HW_DEBUG_E("PHY_BCR_OFFSET is error \r\n");
+ return FST_FAILURE;
+ }
+
+ do
+ {
+ FGmac_ReadPHYRegister(Config, PHY_BCR_OFFSET, &RegValue);
+ Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US);
+
+ if (++Wait_Counter > 30)
+ {
+ GMAC_HW_DEBUG_E("PHY_BCR_OFFSET wait is too long \r\n");
+ ret = FST_ERROR_COUNT_MAX;
+ goto gmac_init;
+ }
+ } while ((RegValue & PHY_RESET) == PHY_RESET);
+
+ Wait_Counter = 0;
+ if (Config->AutoNegotiation == GMAC_AUTONEGOTIATION_ENABLE)
+ {
+ do
+ {
+ FGmac_ReadPHYRegister(Config, PHY_BSR_OFFSET, &RegValue);
+
+ if (++Wait_Counter > 30)
+ {
+ GMAC_HW_DEBUG_E("PHY_BSR_OFFSET 1 wait is too long \r\n");
+ ret = FST_ERROR_COUNT_MAX;
+ goto gmac_init;
+ }
+ Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US);
+
+ } while ((RegValue & PHY_LINKED_STATUS) != PHY_LINKED_STATUS);
+
+ Wait_Counter = 0;
+ if (Gmac_WritePHYRegister(Config, PHY_BCR_OFFSET, PHY_AUTONEGOTIATION | PHY_RESTART_AUTONEGOTIATION) != FST_SUCCESS)
+ {
+ GMAC_HW_DEBUG_E("PHY_BCR_OFFSET 2 is error \r\n");
+ ret = FST_FAILURE;
+ goto gmac_init;
+ }
+
+ do
+ {
+ FGmac_ReadPHYRegister(Config, PHY_BSR_OFFSET, &RegValue);
+ if (++Wait_Counter > 30)
+ {
+ GMAC_HW_DEBUG_E("PHY_BSR_OFFSET 2 wait is too long \r\n");
+ ret = FST_ERROR_COUNT_MAX;
+ goto gmac_init;
+ }
+ } while ((RegValue & PHY_AUTONEGO_COMPLETE) != PHY_AUTONEGO_COMPLETE);
+
+ if (FGmac_ReadPHYRegister(Config, PHY_SPECIFIC_STATUS_OFFSET, &RegValue) != FST_SUCCESS)
+ {
+ GMAC_HW_DEBUG_E("PHY_SPECIFIC_STATUS_OFFSET is error \r\n");
+ ret = FST_FAILURE;
+ goto gmac_init;
+ }
+ /* Configure the MAC with the Duplex Mode fixed by the auto-negotiation process */
+ if ((RegValue & PHY_SPECIFIC_STATUS_DUPLEX) != PHY_SPECIFIC_STATUS_DUPLEX)
+ {
+ /* Set Ethernet duplex mode to Full-duplex following the auto-negotiation */
+ Config->DuplexMode = GMAC_MODE_HALFDUPLEX;
+ }
+ else
+ {
+ /* Set Ethernet duplex mode to Half-duplex following the auto-negotiation */
+ Config->DuplexMode = GMAC_MODE_FULLDUPLEX;
+ }
+ }
+ else
+ {
+ RegValue = 0;
+ if (Config->DuplexMode == GMAC_MODE_FULLDUPLEX)
+ {
+ if (Config->Speed == GMAC_SPEED_1000M)
+ {
+ RegValue = PHY_FULLDUPLEX_1000M;
+ }
+ else if (Config->Speed == GMAC_SPEED_100M)
+ {
+ RegValue = PHY_FULLDUPLEX_100M;
+ }
+ else if (Config->Speed == GMAC_SPEED_10M)
+ {
+ RegValue = PHY_FULLDUPLEX_10M;
+ }
+ }
+ else
+ {
+ if (Config->Speed == GMAC_SPEED_1000M)
+ {
+ RegValue = PHY_HALFDUPLEX_1000M;
+ }
+ else if (Config->Speed == GMAC_SPEED_100M)
+ {
+ RegValue = PHY_HALFDUPLEX_100M;
+ }
+ else if (Config->Speed == GMAC_SPEED_10M)
+ {
+ RegValue = PHY_HALFDUPLEX_10M;
+ }
+ }
+
+ /* AutoNegotiation Disable */
+ if (Gmac_WritePHYRegister(Config, PHY_BCR_OFFSET, RegValue) != FST_SUCCESS)
+ {
+ GMAC_HW_DEBUG_E("PHY_BCR_OFFSET 3 is error \r\n");
+ ret = FST_FAILURE;
+ goto gmac_init;
+ }
+ }
+ Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US);
+
+gmac_init:
+
+ FGmac_MACDMAInit(Config);
+ return ret;
+}
+
+void FGmac_TransmissionEnable(FGmac_Config_t *Config)
+{
+ u32 RegValue;
+ RegValue = Ft_in32(Config->BaseAddress + GMAC_CONTROL_OFFSET);
+ RegValue |= GMAC_CONTROL_TE;
+ Ft_out32(Config->BaseAddress + GMAC_CONTROL_OFFSET, RegValue);
+}
+
+void FGmac_TransmissionDisable(FGmac_Config_t *Config)
+{
+ u32 RegValue;
+ RegValue = Ft_in32(Config->BaseAddress + GMAC_CONTROL_OFFSET);
+ RegValue &= ~GMAC_CONTROL_TE;
+ Ft_out32(Config->BaseAddress + GMAC_CONTROL_OFFSET, RegValue);
+}
+
+void FGmac_ReceptionEnable(FGmac_Config_t *Config)
+{
+ u32 RegValue;
+ RegValue = Ft_in32(Config->BaseAddress + GMAC_CONTROL_OFFSET);
+ RegValue |= GMAC_CONTROL_RE;
+ Ft_out32(Config->BaseAddress + GMAC_CONTROL_OFFSET, RegValue);
+}
+
+void FGmac_ReceptionDisable(FGmac_Config_t *Config)
+{
+ u32 RegValue;
+ RegValue = Ft_in32(Config->BaseAddress + GMAC_CONTROL_OFFSET);
+ RegValue &= ~GMAC_CONTROL_RE;
+ Ft_out32(Config->BaseAddress + GMAC_CONTROL_OFFSET, RegValue);
+}
+
+void FGmac_FlushTransmitFIFO(FGmac_Config_t *Config)
+{
+ u32 RegValue;
+ RegValue = Ft_in32(Config->BaseAddress + DMA_OP_OFFSET);
+ RegValue |= DMA_OP_FTF;
+ Ft_out32(Config->BaseAddress + DMA_OP_OFFSET, RegValue);
+}
+
+void FGmac_DMATransmissionEnable(FGmac_Config_t *Config)
+{
+ u32 RegValue;
+ RegValue = Ft_in32(Config->BaseAddress + DMA_OP_OFFSET);
+ RegValue |= DMA_OP_ST;
+ Ft_out32(Config->BaseAddress + DMA_OP_OFFSET, RegValue);
+}
+
+/**
+ * @name: FGmac_DMATransmissionDisable
+ * @msg: Disable the DMA transmission
+ * @param {FGmac_Config_t} *Config
+ * @return {*}
+ */
+void FGmac_DMATransmissionDisable(FGmac_Config_t *Config)
+{
+ u32 RegValue;
+ RegValue = Ft_in32(Config->BaseAddress + DMA_OP_OFFSET);
+ RegValue &= ~DMA_OP_ST;
+ Ft_out32(Config->BaseAddress + DMA_OP_OFFSET, RegValue);
+}
+
+/**
+ * @name: FGmac_DMAReceptionEnable
+ * @msg: Enable the DMA reception
+ * @param {FGmac_Config_t} *Config
+ * @return {*}
+ */
+void FGmac_DMAReceptionEnable(FGmac_Config_t *Config)
+{
+ u32 RegValue;
+ RegValue = Ft_in32(Config->BaseAddress + DMA_OP_OFFSET);
+ RegValue |= DMA_OP_SR;
+ Ft_out32(Config->BaseAddress + DMA_OP_OFFSET, RegValue);
+}
+
+void FGmac_DMAReceptionDisable(FGmac_Config_t *Config)
+{
+ u32 RegValue;
+ RegValue = Ft_in32(Config->BaseAddress + DMA_OP_OFFSET);
+ RegValue &= ~DMA_OP_SR;
+ Ft_out32(Config->BaseAddress + DMA_OP_OFFSET, RegValue);
+}
+
+void FGmac_DMAReceptionTransmissionEnable(FGmac_Config_t *Config)
+{
+ u32 RegValue;
+ RegValue = Ft_in32(Config->BaseAddress + DMA_OP_OFFSET);
+ RegValue |= (DMA_OP_SR | DMA_OP_ST);
+ Ft_out32(Config->BaseAddress + DMA_OP_OFFSET, RegValue);
+}
+
+void FGmac_DMAReceptionTransmissionDisable(FGmac_Config_t *Config)
+{
+ u32 RegValue;
+ RegValue = Ft_in32(Config->BaseAddress + DMA_OP_OFFSET);
+ RegValue &= ~(DMA_OP_SR | DMA_OP_ST);
+ Ft_out32(Config->BaseAddress + DMA_OP_OFFSET, RegValue);
+}
+
+void FGmac_ReceptionTransmissionEnable(FGmac_Config_t *Config)
+{
+ u32 RegValue;
+ RegValue = Ft_in32(Config->BaseAddress + GMAC_CONTROL_OFFSET);
+ RegValue |= (GMAC_CONTROL_RE | GMAC_CONTROL_TE);
+ Ft_out32(Config->BaseAddress + GMAC_CONTROL_OFFSET, RegValue);
+}
+
+void FGmac_ReceptionTransmissionDisable(FGmac_Config_t *Config)
+{
+ u32 RegValue;
+ RegValue = Ft_in32(Config->BaseAddress + GMAC_CONTROL_OFFSET);
+ RegValue &= ~(GMAC_CONTROL_RE | GMAC_CONTROL_TE);
+ Ft_out32(Config->BaseAddress + GMAC_CONTROL_OFFSET, RegValue);
+}
diff --git a/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_hw.h b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_hw.h
new file mode 100644
index 0000000000..6556880863
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_hw.h
@@ -0,0 +1,577 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-04-07 13:25:10
+ * @Description:  This files is for gmac register
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef GMAC_HW_H
+#define GMAC_HW_H
+#include "ft_types.h"
+#include "ft_gmac.h"
+/* Register Offset */
+
+#define GMAC_CONTROL_OFFSET 0x00000000U /* Configuration */
+#define GMAC_FRAME_FILTER_OFFSET 0x00000004U /* Frame Filter */
+#define GMAC_HASH_HIGH_OFFSET 0x00000008U /* Multicast Hash Table High */
+#define GMAC_HASH_LOW_OFFSET 0x0000000cU /* Multicast Hash Table Low */
+#define GMAC_MII_ADDR_OFFSET 0x00000010U /* MII Address */
+#define GMAC_MII_DATA_OFFSET 0x00000014U /* MII Data */
+#define GMAC_FLOW_CTRL_OFFSET 0x00000018U /* Flow Control */
+#define GMAC_VLAN_TAG_OFFSET 0x0000001cU /* VLAN Tag */
+#define GMAC_VERSION_OFFSET 0x00000020U /* GMAC CORE Version */
+#define GMAC_INTERNAL_MODULE_STATUS_OFFSET 0x00000024U /* 给出各种内部块的状态以进行调试。 */
+#define GMAC_LPI_CONTROL_STATUS_OFFSET 0x00000030U /* 控制低功耗空闲(LPI)操作并提供内核的 LPI 状态。 */
+#define GMAC_LPI_TIMER_CONTROL_OFFSET 0x00000034U /* 控制 LPI 状态中的超时值。 */
+#define GMAC_ISR_STATUS_OFFSET 0x00000038U /* 中断状态。 */
+#define GMAC_ISR_MASK_OFFSET 0x0000003CU /* 生成中断的掩码 */
+#define GMAC_MAC_ADDR0_UPPER16BIT_OFFSET 0x00000040U /* 第一个 MAC 地址的高 16 位。 */
+#define GMAC_MAC_ADDR0_LOWER16BIT_OFFSET 0x00000044U /* 第一个 MAC 地址的低 32 位。。 */
+#define GMAC_MAC_ADDR1_UPPER16BIT_OFFSET 0x00000048U /* 第二个 MAC 地址的高 16 位。 */
+#define GMAC_MAC_ADDR1_LOWER16BIT_OFFSET 0x0000004CU /* 第二个 MAC 地址的低 32 位。。 */
+#define GMAC_MAC_MAC_PHY_STATUS 0x000000D8U /* MAC PHY 状态 */
+
+#define DMA_BUS_MODE_OFFSET 0x00001000U /* Bus Mode */
+#define DMA_XMT_POLL_DEMAND_OFFSET 0x00001004U /* Transmit Poll Demand */
+#define DMA_RCV_POLL_DEMAND_OFFSET 0x00001008U /* Received Poll Demand */
+#define DMA_RCV_BASE_ADDR_OFFSET 0x0000100cU /* Receive List Base */
+#define DMA_TX_BASE_ADDR_OFFSET 0x00001010U /* Transmit List Base */
+#define DMA_STATUS_OFFSET 0x00001014U /* Status Register */
+#define DMA_OP_OFFSET 0x00001018U /* Ctrl (Operational Mode) */
+#define DMA_INTR_ENA_OFFSET 0x0000101cU /* Interrupt Enable */
+#define DMA_MISSED_FRAME_CTR_OFFSET 0x00001020U /* Missed Frame Counter */
+#define DMA_RX_WATCHDOG_OFFSET 0x1024U /* Receive Interrupt Watchdog */
+#define DMA_AXI_BUS_MOD_OFFSET 0x1028U /* 控制 AXI 主行为 */
+#define DMA_AXI_BUS_STATUS_OFFSET 0x102CU /* 控制 AXI 状态 */
+
+/* MMC control */
+#define MMC_CNTRL 0x0100U /* MMC Control */
+#define MMC_RX_INTR 0x0104U /* MMC RX Interrupt */
+#define MMC_TX_INTR 0x0108U /* MMC TX Interrupt */
+#define MMC_RX_INTR_MASK 0x010cU /* MMC Interrupt Mask */
+#define MMC_TX_INTR_MASK 0x0110U /* MMC Interrupt Mask */
+#define MMC_RX_IPC_INTR_MASK 0x0200U
+#define MMC_RX_IPC_INTR 0x0208U
+
+/** MAC 配置寄存器 **/
+#define GMAC_CONTROL_2K 0x08000000U /* IEEE 802.3as 2K packets */
+#define GMAC_CONTROL_CST 0x2000000U
+#define GMAC_CONTROL_TC 0x01000000U /* Transmit Conf. in RGMII/SGMII */
+#define GMAC_CONTROL_WD 0x00800000U /* Disable Watchdog on receive */
+#define GMAC_CONTROL_JD 0x00400000U /* Jabber disable */
+#define GMAC_CONTROL_BE 0x00200000U /* Frame Burst Enable */
+#define GMAC_CONTROL_JE 0x00100000U /* Jumbo frame */
+#define GMAC_CONTROL_IFG(x) ((x & 7) << 17) /* 帧内间隔 ,000 96bit times 001 88bit times 010 80bit times … 111 40bit times*/
+#define GMAC_CONTROL_DCRS 0x00010000U /* Disable carrier sense */
+#define GMAC_CONTROL_PS 0x00008000U /* Port Select 0:GMII 1:MII */
+#define GMAC_CONTROL_FES 0x00004000U /* Speed 0:10 1:100 */
+#define GMAC_CONTROL_DO 0x00002000U /* Disable Rx Own */
+#define GMAC_CONTROL_LM 0x00001000U /* Loop-back mode */
+#define GMAC_CONTROL_DM 0x00000800U /* Duplex Mode . 1 is Duplex */
+#define GMAC_CONTROL_IPC 0x00000400U /* Checksum Offload */
+#define GMAC_CONTROL_DR 0x00000200U /* Disable Retry */
+#define GMAC_CONTROL_LUD 0x00000100U /* Link up/down */
+#define GMAC_CONTROL_ACS 0x00000080U /* Auto Pad/FCS Stripping */
+#define GMAC_CONTROL_BL(x) ((x & 3) << 5)
+#define GMAC_CONTROL_DC 0x00000010U /* Deferral Check */
+#define GMAC_CONTROL_TE 0x00000008U /* Transmitter Enable */
+#define GMAC_CONTROL_RE 0x00000004U /* Receiver Enable */
+#define GMAC_CONTROL_INIT (GMAC_CONTROL_DO | GMAC_CONTROL_JD | GMAC_CONTROL_ACS | GMAC_CONTROL_IPC | GMAC_CONTROL_BE | GMAC_CONTROL_DM | GMAC_CONTROL_WD | GMAC_CONTROL_CST)
+
+/** Frame Filter **/
+#define GMAC_FRAME_FILTER_PR 0x00000001U
+#define GMAC_FRAME_FILTER_HUC 0x00000002U
+#define GMAC_FRAME_FILTER_HMC 0x00000004U
+#define GMAC_FRAME_FILTER_DAIF 0x00000008U
+#define GMAC_FRAME_FILTER_PM 0x00000010U
+#define GMAC_FRAME_FILTER_DBF 0x00000020U
+#define GMAC_FRAME_FILTER_PCF(x) ((x & 3) << 6)
+#define GMAC_FRAME_FILTER_SAIF 0x00000100U
+#define GMAC_FRAME_FILTER_SAF 0x00000200U
+#define GMAC_FRAME_FILTER_HPF 0x00000400U
+#define GMAC_FRAME_FILTER_RA 0x80000000U
+
+/** 哈希表高位寄存器 **/
+#define GMAC_HASH_HIGH_HTH 0xffffffffUL /* 该字段包含 Hash 表的高 32 位。 */
+
+/** 哈希表低位寄存器 **/
+#define GMAC_HASH_LOW_HTH 0xffffffffUL /* 该字段包含 Hash 表的低 32 位。 */
+
+/** GMII 地址寄存器 **/
+#define GMAC_MII_ADDR_GB 0x00000001
+#define GMAC_MII_ADDR_GW 0x00000002
+#define GMAC_MII_ADDR_CR(x) ((x & 0xf) << 2)
+#define GMAC_MII_ADDR_GR(x) ((x & 0x1f) << 6)
+#define GMAC_MII_ADDR_PA(x) ((x & 0x1f) << 11)
+
+/** GMII 数据寄存器 **/
+#define GMAC_MII_DATA_GD 0x0000ffffU
+
+/** 流控寄存器 **/
+#define GMAC_FLOW_FCB 0x00000001U
+#define GMAC_FLOW_BPA GMAC_FLOW_FCB
+#define GMAC_FLOW_TFE 0x00000002U
+#define GMAC_FLOW_RFE 0x00000004U
+#define GMAC_FLOW_UP 0x00000008U
+#define GMAC_FLOW_PLT(x) ((x & 3) << 3)
+#define GMAC_FLOW_DZPQ 0x00000080U
+#define GMAC_FLOW_PT 0xffff0000U
+
+/** VLAN 标记寄存器 **/
+// #define GMAC_VLAN_TAG_VL 0x0000ffffU
+#define GMAC_VLAN_TAG_VL(x) (x & 0xffffU)
+#define GMAC_VLAN_TAG_ETV 0x00010000U
+
+/** 版本寄存器 **/
+#define GMAC_VERSION_UDV 0x00FF0000U /* 用户定义版本号 */
+#define GMAC_VERSION_SDV 0x000000ffU /* 硬件定议版本号 */
+
+/** LPI 控制和状态寄存器 **/
+#define GMAC_LPI_CONTROL_STATUS_TLPIEN 0x00000001U
+#define GMAC_LPI_CONTROL_STATUS_TLPIEX 0x00000002U
+#define GMAC_LPI_CONTROL_STATUS_RLPIEN 0x00000004U
+#define GMAC_LPI_CONTROL_STATUS_RLPIEX 0x00000008U
+#define GMAC_LPI_CONTROL_STATUS_TLPIST 0x00000100U
+#define GMAC_LPI_CONTROL_STATUS_RLPIST 0x00000200U
+#define GMAC_LPI_CONTROL_STATUS_LPIEN 0x00010000U
+#define GMAC_LPI_CONTROL_STATUS_PLS 0x00020000U
+#define GMAC_LPI_CONTROL_STATUS_PLSEN 0x00040000U
+#define GMAC_LPI_CONTROL_STATUS_LPITXA 0x00080000U
+
+/** LPI 定时器控制寄存器 **/
+#define GMAC_LPI_TIMER_TWT 0x0000ffffU
+#define GMAC_LPI_TIMER_LIT 0x3FF0000U
+
+/** 中断状态寄存器 **/
+#define GMAC_ISR_STATUS_RSIS 0x00000001U
+#define GMAC_ISR_STATUS_PCSLSC 0x00000002U
+#define GMAC_ISR_STATUS_PCSANC 0x00000004U
+#define GMAC_ISR_STATUS_PMTIS 0x00000008U
+#define GMAC_ISR_STATUS_MMCIS 0x00000010U
+#define GMAC_ISR_STATUS_MMCRIS 0x00000020U
+#define GMAC_ISR_STATUS_MMCTIS 0x00000040U
+#define GMAC_ISR_STATUS_MMCRCOIS 0x00000080U
+#define GMAC_ISR_STATUS_TIS 0x00000200U
+#define GMAC_ISR_STATUS_LPIIS 0x00000400U
+
+/** 中断屏蔽寄存器 **/
+#define GMAC_ISR_MASK_RSIM 0x00000001U /* RGMII/SMII 中断屏蔽 */
+#define GMAC_ISR_MASK_PCSLSIM 0x00000002U
+#define GMAC_ISR_MASK_PCSANCIM 0x00000004U
+#define GMAC_ISR_MASK_PMTIM 0x00000008U
+#define GMAC_ISR_MASK_TIM 0x00000020U
+#define GMAC_ISR_MASK_LPIIM 0x00000040U
+
+/** MAC 地址 0 高寄存器 **/
+#define GMAC_MAC_ADDR0_UPPER16BIT_A 0x0000ffffU
+
+/** MAC 地址 0 低寄存器 **/
+#define GMAC_MAC_ADDR0_LOWERER16BIT_A 0xffffffffU
+
+/** MAC 地址 1 高寄存器 **/
+#define GMAC_MAC_ADDR1_UPPER16BIT_A 0x0000ffffU
+#define GMAC_MAC_ADDR1_UPPER16BIT_MBC 0x3f000000U
+#define GMAC_MAC_ADDR1_UPPER16BIT_SA 0x40000000U
+#define GMAC_MAC_ADDR1_UPPER16BIT_AE 0x80000000U
+
+/** MAC 地址 1 低寄存器 **/
+#define GMAC_MAC_ADDR1_LOWER16BIT_A 0xffffffffU
+
+/* GMAC DMA 寄存器 */
+/** 总线模式寄存器 **/
+#define DMA_BUS_PRWG 0x030000000U
+#define DMA_BUS_TXPR 0x08000000U
+#define DMA_BUS_MB 0x04000000U
+#define DMA_BUS_AAL 0x02000000U
+#define DMA_BUS_8xPBL 0x01000000U
+#define DMA_BUS_USP 0x00800000U
+#define DMA_BUS_RPBL(x) ((x & 0x3f) << 17)
+#define DMA_BUS_FB 0x00010000U /* Fixed Burst */
+#define DMA_BUS_PR(x) ((x & 0x3) << 14) /* 00: 1:1 ,01: 2:1 ,10: 3:1 ,11: 4:1 */
+#define DMA_BUS_PBL(x) ((x & 0x3f) << 8)
+#define DMA_BUS_ATDS 0x00000080U
+#define DMA_BUS_DSL 0x0000007CU /* Descriptor Skip Length */
+#define DMA_BUS_DA 0x00000002U /* DMA Arbitration Scheme,Rx High Pro */
+#define DMA_BUS_SWR 0x00000001U /* Software Reset */
+
+#define DMA_BUS_INIT (DMA_BUS_FB | DMA_BUS_PBL(16) | DMA_BUS_RPBL(16))
+
+/** 发送轮询请求寄存器 **/
+#define DMA_XMT_POLL_DEMAND_TPD 0xffffffffU
+
+/** 发送轮询请求寄存器 **/
+#define DMA_RCV_POLL_DEMAND_RPD 0xffffffffU
+
+/** 接收描述符列表地址寄存器 **/
+#define DMA_RCV_BASE_ADDR_START_REC_LIST 0xfffffff0U
+
+/** 发送描述符列表地址寄存器 **/
+#define DMA_TX_BASE_ADDR_START_TRA_LIST 0xfffffff0U
+
+/**
+ * @brief Bit definition of TDES0 register: DMA Tx descriptor status register
+ */
+#define BIT(bitnum) (1 << (bitnum % 32))
+#define GENMASK(h, l) \
+ (((~0UL) - (1UL << (l)) + 1) & (~0UL >> (32 - 1 - (h))))
+
+#define DMA_TDES0_DEFERRED BIT(0)
+#define DMA_TDES0_UNDERFLOW_ERROR BIT(1)
+#define DMA_TDES0_EXCESSIVE_DEFERRAL BIT(2)
+#define DMA_TDES0_COLLISION_COUNT_MASK GENMASK(6, 3)
+#define DMA_TDES0_VLAN_FRAME BIT(7)
+#define DMA_TDES0_EXCESSIVE_COLLISIONS BIT(8)
+#define DMA_TDES0_LATE_COLLISION BIT(9)
+#define DMA_TDES0_NO_CARRIER BIT(10)
+#define DMA_TDES0_LOSS_CARRIER BIT(11)
+#define DMA_TDES0_PAYLOAD_ERROR BIT(12)
+#define DMA_TDES0_FRAME_FLUSHED BIT(13)
+#define DMA_TDES0_JABBER_TIMEOUT BIT(14)
+#define DMA_TDES0_ERROR_SUMMARY BIT(15)
+#define DMA_TDES0_IP_HEADER_ERROR BIT(16)
+#define DMA_TDES0_TIME_STAMP_STATUS BIT(17)
+#define DMA_TDES0_OWN ((u32)BIT(31)) /* silence sparse */
+/* TDES1 */
+#define DMA_TDES1_BUFFER1_SIZE_MASK GENMASK(10, 0)
+#define DMA_TDES1_BUFFER2_SIZE_MASK GENMASK(21, 11)
+#define DMA_TDES1_BUFFER2_SIZE_SHIFT 11
+#define DMA_TDES1_TIME_STAMP_ENABLE BIT(22)
+#define DMA_TDES1_DISABLE_PADDING BIT(23)
+#define DMA_TDES1_SECOND_ADDRESS_CHAINED BIT(24)
+#define DMA_TDES1_END_RING BIT(25)
+#define DMA_TDES1_CRC_DISABLE BIT(26)
+#define DMA_TDES1_CHECKSUM_INSERTION_MASK GENMASK(28, 27)
+#define DMA_TDES1_CHECKSUM_INSERTION_SHIFT 27
+#define DMA_TDES1_FIRST_SEGMENT BIT(29)
+#define DMA_TDES1_LAST_SEGMENT BIT(30)
+#define DMA_TDES1_INTERRUPT BIT(31)
+
+/* Bit definition of RDES0 register: DMA Rx descriptor status register */
+/* RDES0 */
+#define DMA_RDES0_PAYLOAD_CSUM_ERR BIT(0)
+#define DMA_RDES0_CRC_ERROR BIT(1)
+#define DMA_RDES0_DRIBBLING BIT(2)
+#define DMA_RDES0_MII_ERROR BIT(3)
+#define DMA_RDES0_RECEIVE_WATCHDOG BIT(4)
+#define DMA_RDES0_FRAME_TYPE BIT(5)
+#define DMA_RDES0_COLLISION BIT(6)
+#define DMA_RDES0_IPC_CSUM_ERROR BIT(7)
+#define DMA_RDES0_LAST_DESCRIPTOR BIT(8)
+#define DMA_RDES0_FIRST_DESCRIPTOR BIT(9)
+#define DMA_RDES0_VLAN_TAG BIT(10)
+#define DMA_RDES0_OVERFLOW_ERROR BIT(11)
+#define DMA_RDES0_LENGTH_ERROR BIT(12)
+#define DMA_RDES0_SA_FILTER_FAIL BIT(13)
+#define DMA_RDES0_DESCRIPTOR_ERROR BIT(14)
+#define DMA_RDES0_ERROR_SUMMARY BIT(15)
+#define DMA_RDES0_FRAME_LEN_MASK (0x3FFF << 16) /*GENMASK(29, 16)*/
+#define DMA_RDES0_FRAME_LEN_SHIFT 16
+#define DMA_RDES0_DA_FILTER_FAIL BIT(30)
+#define DMA_RDES0_OWN BIT(31)
+/* RDES1 */
+#define DMA_RDES1_BUFFER1_SIZE_MASK GENMASK(10, 0)
+#define DMA_RDES1_BUFFER2_SIZE_MASK GENMASK(21, 11)
+#define DMA_RDES1_BUFFER2_SIZE_SHIFT 11
+#define DMA_RDES1_SECOND_ADDRESS_CHAINED BIT(24)
+#define DMA_RDES1_END_RING BIT(25)
+#define DMA_RDES1_DISABLE_IC BIT(31)
+
+/** DMA Status register defines **/
+#define DMA_STATUS_GLPII 0x40000000 /* GMAC LPI interrupt */
+#define DMA_STATUS_GPI 0x10000000 /* PMT interrupt */
+#define DMA_STATUS_GMI 0x08000000 /* MMC interrupt */
+#define DMA_STATUS_GLI 0x04000000 /* GMAC Line interface int */
+#define DMA_STATUS_EB_MASK 0x00380000 /* Error Bits Mask */
+#define DMA_STATUS_EB_TX_ABORT 0x00080000 /* Error Bits - TX Abort */
+#define DMA_STATUS_EB_RX_ABORT 0x00100000 /* Error Bits - RX Abort */
+#define DMA_STATUS_TS_MASK 0x00700000 /* Transmit Process State */
+#define DMA_STATUS_RS_MASK 0x000e0000 /* Receive Process State */
+#define DMA_STATUS_NIS 0x00010000 /* Normal Interrupt Summary */
+#define DMA_STATUS_AIS 0x00008000 /* Abnormal Interrupt Summary */
+#define DMA_STATUS_ERI 0x00004000 /* Early Receive Interrupt */
+#define DMA_STATUS_FBI 0x00002000 /* Fatal Bus Error Interrupt */
+#define DMA_STATUS_ETI 0x00000400 /* Early Transmit Interrupt */
+#define DMA_STATUS_RWT 0x00000200 /* Receive Watchdog Timeout */
+#define DMA_STATUS_RPS 0x00000100 /* Receive Process Stopped */
+#define DMA_STATUS_RU 0x00000080 /* Receive Buffer Unavailable */
+#define DMA_STATUS_RI 0x00000040 /* Receive Interrupt */
+#define DMA_STATUS_UNF 0x00000020 /* Transmit Underflow */
+#define DMA_STATUS_OVF 0x00000010 /* Receive Overflow */
+#define DMA_STATUS_TJT 0x00000008 /* Transmit Jabber Timeout */
+#define DMA_STATUS_TU 0x00000004 /* Transmit Buffer Unavailable */
+#define DMA_STATUS_TPS 0x00000002 /* Transmit Process Stopped */
+#define DMA_STATUS_TI 0x00000001 /* Transmit Interrupt */
+#define DMA_STATUS_INIT 0xFFFFFFFF
+
+/** DMA 操作模式寄存器 **/
+#define DMA_OP_DT 0x04000000U /* No Dropping of TCP/IP csum Err Frame */
+#define DMA_OP_RSF 0x02000000U /* Rx Store and Forward */
+#define DMA_OP_DFF 0x01000000U /* */
+#define DMA_OP_TSF 0x000200000U /* Tx Store and Forward */
+#define DMA_OP_FTF 0x000100000U /* Flush Tx FIFO */
+#define DMA_OP_TTC(x) ((x & 7) << 14) /* Tx Threshold Control ,• 000 64 , 001 128 , 010 192 ,011 256 ,100 40 , 101 32 , 110 24 , 111 16*/
+#define DMA_OP_ST 0x000002000U /* Start/Stop Tx */
+#define DMA_OP_RFD(x) ((x & 0x3) << 11) /* Threshold for DeActive Flow Control */
+#define DMA_OP_RFA 0x000000600U /* Threshold for Active Flow Control */
+#define DMA_OP_EFC 0x000000100U /* Enable HW Flow control */
+#define DMA_OP_FEF 0x000000080U /* Forward Error Frame */
+#define DMA_OP_FUF 0x000000040U /* Forward Undersize Good Frame */
+#define DMA_OP_RTC 0x000000018U /* Rx Threshold Control */
+#define DMA_OP_OSF 0x000000004U /* Operate On Second Mode */
+#define DMA_OP_SR 0x00000002U /* Start/Stop Rx */
+#define DMA_OP_CLEAR_MASK ((u32)0xF8DE3F23U)
+#define DMA_OP_INIT (DMA_OP_SR | DMA_OP_RSF)
+
+/** 中断使能寄存器 **/
+#define DMA_INTR_ENA_TIE 0x00000001U /* Transmit Interrupt */
+#define DMA_INTR_ENA_TSE 0x00000002U /* 传输停止启用 */
+#define DMA_INTR_ENA_TUE 0x00000004U /* Transmit Buffer Unavailable */
+#define DMA_INTR_ENA_THE 0x00000008U /* 发送 Jabber 超时启用 */
+#define DMA_INTR_ENA_OVE 0x00000010U /* 溢出中断使能 */
+#define DMA_INTR_ENA_UNE 0x00000020U /* 下溢中断使能 */
+#define DMA_INTR_ENA_RIE 0x00000040U /* Receive Interrupt */
+#define DMA_INTR_ENA_RUE 0x00000080U /* 接收缓冲区不可用启用 */
+#define DMA_INTR_ENA_RSE 0x00000100U /* 接收已停止启用 */
+#define DMA_INTR_ENA_RWE 0x00000200U /* 接收看门狗超时使能 */
+#define DMA_INTR_ENA_ETE 0x00000400U /* 早期发送中断使能 */
+#define DMA_INTR_ENA_FBE 0x00002000U /* Fatal Bus Error */
+#define DMA_INTR_ENA_ERE 0x00004000U /* Early Receive */
+#define DMA_INTR_ENA_AIE 0x00008000 /* Abnormal Summary */
+#define DMA_INTR_ENA_NIE 0x00010000 /* Normal Summary */
+
+#define DMA_INTR_DEFAULT (DMA_INTR_ENA_TIE | DMA_INTR_ENA_TSE | DMA_INTR_ENA_TUE | DMA_INTR_ENA_THE | DMA_INTR_ENA_OVE | DMA_INTR_ENA_UNE | DMA_INTR_ENA_RIE | DMA_INTR_ENA_RUE | DMA_INTR_ENA_RSE | DMA_INTR_ENA_RWE | DMA_INTR_ENA_ETE | DMA_INTR_ENA_FBE | DMA_INTR_ENA_ERE | DMA_INTR_ENA_AIE | DMA_INTR_ENA_NIE)
+
+/** 丢帧和缓冲区溢出计数器寄存器 **/
+#define DMA_MISSED_FRAME_CTR_CMIS 0x0000FFFFUDMA_MISSED_FRAME
+#define DMA_MISSED_FRAME_CTR_OVMIS 0x00010000U
+#define DMA_MISSED_FRAME_CTR_CFIFO 0x0ffe0000U
+#define DMA_MISSED_FRAME_CTR_OVFIFO 0x10000000U
+
+/** 接收中断看门狗定时器寄存器 **/
+#define DMA_RX_WATCHDOG_RIWT 0x0000000fU
+
+/** AXI_BUS_MOD **/
+#define DMA_AXI_BUS_MOD_UNDEF 0x00000001U /* AXI 未定义的突发长度 */
+#define DMA_AXI_BUS_MOD_BLEN4 0x00000002U /* AXI 突发长度 4 */
+#define DMA_AXI_BUS_MOD_BLEN8 0x00000004U /* AXI 突发长度 8 */
+#define DMA_AXI_BUS_MOD_BLEN16 0x00000008U /* AXI 突发长度 16 */
+#define DMA_AXI_BUS_MOD_BLEN32 0x00000010U /* AXI 突发长度 32 */
+#define DMA_AXI_BUS_MOD_BLEN64 0x00000020U /* AXI 突发长度 64 */
+#define DMA_AXI_BUS_MOD_BLEN128 0x00000040U /* AXI 突发长度 128 */
+#define DMA_AXI_BUS_MOD_BLEN256 0x00000080U /* AXI 突发长度 256 */
+#define DMA_AXI_BUS_MOD_AXI_AAL 0x00001000U /* 地址对齐的节拍 */
+#define DMA_AXI_BUS_MOD_RD_OSR_LMT(x) ((x & 0xf) << 16) /* XI 最大读取未决请求限制此值限 制 AXI 读取接口上的最大未完成请求。 */
+#define DMA_AXI_BUS_MOD_WR_OSR_LMT(x) ((x & 0xf) << 20) /* AXI 最大写入未决请求限制此值 限制 AXI 写入接口上的最大未完成请求。 */
+#define DMA_AXI_BUS_MOD_UNLCK_ON_MGK_RWK 0x40000000U
+#define DMA_AXI_BUS_MOD_EN_LPI 0x80000000U
+
+/** MMC Control **/
+#define MMC_DEFAULT_MASK 0xffffffff
+
+/* Common PHY Registers (AR8035) */
+
+#define PHY_BCR_OFFSET ((u16)0x00) /* Transceiver Basic Control Register */
+#define PHY_BSR_OFFSET ((u16)0x01) /* Transceiver Basic Status Register */
+#define PHY_ID1_REG_OFFSET ((u16)0x02) /* PHY ID1 Identifier */
+#define PHY_ID2_REG_OFFSET ((u16)0x03) /* PHY ID2 Identifier */
+#define PHY_AUTO_NEGOTIATION_ADVERTISEMENT_OFFSET ((u16)0x04)
+#define PHY_EXTENDED_CONTROL_REGISTER_OFFSET ((u16)0x9)
+#define PHY_SPECIFIC_STATUS_OFFSET ((u16)0x11)
+#define PHY_INTERRUPT_ENABLE_OFFSET ((u16)0x12)
+#define PHY_INTERRUPT_STATUS_OFFSET ((u16)0x13)
+#define PHY_DEBUG_ADDR_OFFSET ((u16)0x1D)
+#define PHY_DEBUG_DATA_OFFSET ((u16)0x1E)
+
+/* MII control register bit */
+
+#define PHY_BCR_1000 0x0040 /* 1 = 1000mb when \
+ PHY_BCR_100 is also 1 */
+#define PHY_BCR_COLL_TEST 0x0080 /* collision test */
+#define PHY_BCR_FDX 0x0100 /* FDX =1, half duplex =0 */
+#define PHY_BCR_RESTART 0x0200 /* restart auto negotiation */
+#define PHY_BCR_ISOLATE 0x0400 /* isolate PHY from MII */
+#define PHY_BCR_POWER_DOWN 0x0800 /* power down */
+#define PHY_BCR_AUTO_EN 0x1000 /* auto-negotiation enable */
+#define PHY_BCR_100 0x2000 /* 0 = 10mb, 1 = 100mb */
+#define PHY_BCR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */
+#define PHY_BCR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */
+#define PHY_BCR_NORM_EN 0x0000 /* just enable the PHY */
+#define PHY_BCR_DEF_0_MASK 0xca7f /* they must return zero */
+#define PHY_BCR_RES_MASK 0x003f /* reserved bits,return zero */
+
+#define PHY_ANAR_10TX_HD ((u16)0x0020)
+#define PHY_ANAR_10TX_FD ((u16)0x0040)
+#define PHY_ANAR_100TX_HD ((u16)0x0080)
+#define PHY_ANAR_100TX_FD ((u16)0x0100)
+#define PHY_ANAR_100T_4 ((u16)0x0200)
+#define PHY_ANAR_PAUSE ((u16)0x0400)
+#define PHY_ANAR_ASM_PAUSE ((u16)0x0800)
+#define PHY_ANAR_REMORT_FAULT ((u16)0x2000)
+#define PHY_ANAR_NEXT_PAGE ((u16)0x8000)
+#define PHY_ANAR_PAUSE_MASK ((u16)0x0c00)
+
+#define PHY_BSR_EXTENDED_STATUS ((u16)0x100)
+
+#define PHY_EXTENDED_CONTROL_1000T_FD ((u16)0x200)
+#define PHY_EXTENDED_CONTROL_1000T_HD ((u16)0x100)
+
+#define PHY_RESET ((u16)0x8000U) /* PHY Reset */
+#define PHY_LOOPBACK ((u16)0x4000U) /* Select loop-back mode */
+#define PHY_FULLDUPLEX_1000M ((u16)0x2140U) /* Set the full-duplex mode at 1000 Mb/s */
+#define PHY_HALFDUPLEX_1000M ((u16)0x2040U) /* Set the half-duplex mode at 1000 Mb/s */
+#define PHY_FULLDUPLEX_100M ((u16)0x2100U) /* Set the full-duplex mode at 100 Mb/s */
+#define PHY_HALFDUPLEX_100M ((u16)0x2000U) /* Set the half-duplex mode at 100 Mb/s */
+#define PHY_FULLDUPLEX_10M ((u16)0x0100U) /* Set the full-duplex mode at 10 Mb/s */
+#define PHY_HALFDUPLEX_10M ((u16)0x0000U) /* Set the half-duplex mode at 10 Mb/s */
+#define PHY_AUTONEGOTIATION ((u16)0x1000U) /* Enable auto-negotiation function */
+#define PHY_RESTART_AUTONEGOTIATION ((u16)0x0200U) /* Restart auto-negotiation function */
+#define PHY_POWERDOWN ((u16)0x0800U) /* Select the power down mode */
+#define PHY_ISOLATE ((u16)0x0400U) /* Isolate PHY from MII */
+
+#define PHY_AUTONEGO_COMPLETE ((u16)0x0020U) /* Auto-Negotiation process completed */
+#define PHY_LINKED_STATUS ((u16)0x0004U) /* Valid link established */
+#define PHY_JABBER_DETECTION ((u16)0x0002U) /* Jabber condition detected */
+
+#define PHY_SPECIFIC_STATUS_DUPLEX ((u16)0x2000) /* 0 is Half-duplex ,1 is Full-duplex */
+#define PHY_SPECIFIC_STATUS_SPEED ((u16)0xc000) /* 0 is 10Mbps ,1 is 100Mbps , 2 is 1000Mbps */
+
+#define PHY_INTERRUPT_ENABLE_WAKE_ON_LAN 0x00000001U /* Wake on LAN interrupt enable,0 Interrupt disable , 1 Interrupt enable */
+#define PHY_INTERRUPT_ENABLE_POLARITY_CHANGED 0x00000002U /* Polarity Changed interrupt enable,0 Interrupt disable , 1 Interrupt enable */
+#define PHY_INTERRUPT_ENABLE_WIRESPEED_DOWNGRADE 0x00000020U /* Wirespeed downgrade Interrupt ,0 Interrupt disable , 1 Interrupt enable*/
+#define PHY_INTERRUPT_ENABLE_LINK_SUCCESS 0x00000400U /* Link success interrupt ,0 Interrupt disable , 1 Interrupt enable*/
+#define PHY_INTERRUPT_ENABLE_LINK_FAIL 0x00000800U /* Link fail interrupt, 0 Interrupt disable , 1 Interrupt enable */
+#define PHY_INTERRUPT_ENABLE_PAGE_RECEIVED 0x00001000U /* Page Received, 0 Interrupt disable , 1 Interrupt enable */
+#define PHY_INTERRUPT_ENABLE_DUPLEX_CHANGED 0x00002000U /* Duplex Changed, 0 Interrupt disable , 1 Interrupt enable*/
+#define PHY_INTERRUPT_ENABLE_SPEED_CHANGED 0x00004000U /* Speed Changed , 0 Interrupt disable , 1 Interrupt enable */
+#define PHY_INTERRUPT_ENABLE_AUTO_NEGOTIATION_ERROR 0x00008000U /* Auto-Negotiation Error , 0 Interrupt disable , 1 Interrupt enable */
+
+#define PHY_INTERRUPT_STATUS_WAKE_ON_LAN 0x00000001U /* Wake on LAN ,0 No Wake-on-LAN packet is received , 1 Wake-on-LAN packet is received */
+#define PHY_INTERRUPT_STATUS_POLARITY_CHANGED 0x00000002U /* Polarity Changed ,0 Polarity changed , 1 Polarity not changed */
+#define PHY_INTERRUPT_STATUS_WIRESPEED_DOWNGRADE 0x00000020U /* Wirespeed downgrade Interrupt ,0 No Smartspeed interrupt detected , 1 Smartspeed interrupt detected */
+#define PHY_INTERRUPT_STATUS_LINK_SUCCESS 0x00000400U /* Link success interrupt ,0 Link up not happened , 1 Link up happened.*/
+#define PHY_INTERRUPT_STATUS_LINK_FAIL 0x00000800U /* Link fail interrupt, 0 Link down not happened , 1 Link down happened. */
+#define PHY_INTERRUPT_STATUS_PAGE_RECEIVED 0x00001000U /* Page Received, 0 Page not received , 1 Page received */
+#define PHY_INTERRUPT_STATUS_DUPLEX_CHANGED 0x00002000U /* Duplex Changed, 0 Duplex not changed , 1 Duplex changed*/
+#define PHY_INTERRUPT_STATUS_SPEED_CHANGED 0x00004000U /* Speed Changed , 0 Speed not changed , 1 Speed changed */
+#define PHY_INTERRUPT_STATUS_AUTO_NEGOTIATION_ERROR 0x00008000U /* Auto-Negotiation Error , 0 No Auto-Negotiation Error , 1 Auto-Negotiation Error */
+
+/**
+ * @name: FGmac_InitializeHw
+ * @msg: 初始化Mac层与Phy层参数 。
+ * @param {FGmac_Config_t} *Config 包含Mac层 与Phy层,配置参数。
+ * @return {s32} Common_status 参数。
+ */
+s32 FGmac_InitializeHw(FGmac_Config_t *Config);
+
+/**
+ * @name: FGmac_ReadPHYRegister
+ * @msg: 读取Phy 中的寄存器
+ * @param {FGmac_Config_t} *Config 提供读取的基地址,与Phy读取过程中需要的相关参数。
+ * @param {u16} PHYReg 需要读取Phy 芯片的寄存器地址。
+ * @param {u32} *RegValue 读取出来的寄存器参数
+ * @return {s32} Common_status 参数。
+ */
+s32 FGmac_ReadPHYRegister(FGmac_Config_t *Config, u16 PHYReg, u32 *RegValue);
+
+/**
+ * @name: Gmac_WritePHYRegister
+ * @msg: 向Phy 中的特定寄存器写入参数。
+ * @param {FGmac_Config_t} *Config 提供读取的基地址,与Phy读取过程中需要的相关参数。
+ * @param {u16} PHYReg 需要读取Phy 芯片的寄存器地址。
+ * @param {u32} RegValue 需要写入的寄存器参数
+ * @return {s32} Common_status 参数。
+ */
+s32 Gmac_WritePHYRegister(FGmac_Config_t *Config, u16 PHYReg, u32 RegValue);
+
+/**
+ * @name: FGmac_TransmissionEnable
+ * @msg: 使能 Gmac 开始发送功能
+ * @param {FGmac_Config_t} *Config 提供Mac的基地址。
+ * @return {None}
+ */
+void FGmac_TransmissionEnable(FGmac_Config_t *Config);
+
+/**
+ * @name: FGmac_TransmissionDisable
+ * @msg: 禁止 Gmac 开始发送功能
+ * @param {FGmac_Config_t} *Config 提供Mac的基地址。
+ * @return {None}
+ */
+void FGmac_TransmissionDisable(FGmac_Config_t *Config);
+
+/**
+ * @name: FGmac_ReceptionEnable
+ * @msg: 使能 Gmac 开始接收功能
+ * @param {FGmac_Config_t} *Config 提供Mac的基地址。
+ * @return {None}
+ */
+void FGmac_ReceptionEnable(FGmac_Config_t *Config);
+
+/**
+ * @name: FGmac_ReceptionDisable
+ * @msg: 禁止 Gmac 开始接收功能
+ * @param {FGmac_Config_t} *Config 提供Mac的基地址。
+ * @return {None}
+ */
+void FGmac_ReceptionDisable(FGmac_Config_t *Config);
+
+/**
+ * @name: FGmac_DMAReceptionTransmissionEnable
+ * @msg: 使能 Gmac 开始DMA描述符接收与写入功能
+ * @param {FGmac_Config_t} *Config 提供Mac的基地址。
+ * @return {*}
+ */
+void FGmac_DMAReceptionTransmissionEnable(FGmac_Config_t *Config);
+
+/**
+ * @name: FGmac_ReceptionTransmissionEnable
+ * @msg: 使能 Gmac 开始接收与发送功能
+ * @param {FGmac_Config_t} *Config 提供Mac的基地址。
+ * @return {*}
+ */
+void FGmac_ReceptionTransmissionEnable(FGmac_Config_t *Config);
+
+/**
+ * @name: FGmac_FlushTransmitFIFO
+ * @msg: 刷新 Gmac 发送 FIFO
+ * @param {FGmac_Config_t} *Config 提供Mac的基地址。
+ * @return {*}
+ */
+void FGmac_FlushTransmitFIFO(FGmac_Config_t *Config);
+
+/**
+ * @name: FGmac_DMATransmissionEnable
+ * @msg: 使能 DMA描述符发送功能
+ * @param {FGmac_Config_t} *Config 提供Mac的基地址。
+ * @return {*}
+ */
+void FGmac_DMATransmissionEnable(FGmac_Config_t *Config);
+/**
+ * @name: FGmac_DMATransmissionDisable
+ * @msg: 关闭 DMA描述符发送功能
+ * @param {FGmac_Config_t} *Config 提供Mac的基地址。
+ * @return {*}
+ */
+void FGmac_DMATransmissionDisable(FGmac_Config_t *Config);
+/**
+ * @name: FGmac_DMAReceptionEnable
+ * @msg: 使能 DMA描述符接收功能
+ * @param {FGmac_Config_t} *Config 提供Mac的基地址。
+ * @return {*}
+ */
+void FGmac_DMAReceptionEnable(FGmac_Config_t *Config);
+/**
+ * @name: FGmac_DMAReceptionEnable
+ * @msg: 使能 DMA描述符接收功能
+ * @param {FGmac_Config_t} *Config 提供Mac的基地址。
+ * @return {*}
+ */
+void FGmac_DMAReceptionDisable(FGmac_Config_t *Config);
+#endif // !
diff --git a/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_intr.c b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_intr.c
new file mode 100644
index 0000000000..0c57a118ee
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_intr.c
@@ -0,0 +1,174 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-05-25 16:42:56
+ * @Description:  This files is for gmac irq
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_gmac_hw.h"
+#include "ft_gmac.h"
+#include "ft_status.h"
+#include "ft_assert.h"
+#include "ft_io.h"
+
+#include "ft_debug.h"
+#define GMAC_INTR_DEBUG_TAG "GMAC_INTR"
+
+#define GMAC_INTR_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(GMAC_INTR_DEBUG_TAG, format, ##__VA_ARGS__)
+#define GMAC_INTR_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(GMAC_INTR_DEBUG_TAG, format, ##__VA_ARGS__)
+#define GMAC_INTR_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(GMAC_INTR_DEBUG_TAG, format, ##__VA_ARGS__)
+
+s32 FGmac_SetHandler(Ft_Gmac_t *Gmac, FGmac_IsrCallbackSelect_t SelectIndex, void *FuncPtr,
+ void *Args)
+{
+ Ft_assertNonvoid(Gmac != NULL);
+ Ft_assertNonvoid(FuncPtr != NULL);
+ Ft_assertNonvoid(Gmac->IsReady == FT_COMPONENT_IS_READLY);
+
+ switch (SelectIndex)
+ {
+ case FT_GMAC_TX_COMPLETE_CB_ID:
+ /* code */
+ Gmac->SendHandler = FuncPtr;
+ Gmac->SendArgs = Args;
+ break;
+ case FT_GMAC_RX_COMPLETE_CB_ID:
+ Gmac->RecvHandler = FuncPtr;
+ Gmac->RecvArgs = Args;
+ break;
+ case FT_GMAC_DMA_ERROR_CB_ID:
+ Gmac->ErrorHandler = FuncPtr;
+ Gmac->ErrorArgs = Args;
+ break;
+ case FT_GMAC_MAC_PHY_STATUS_CB_ID:
+ Gmac->StatusHandler = FuncPtr;
+ Gmac->StatusArgs = Args;
+ break;
+ default:
+ return FST_FAILURE;
+ }
+
+ return FST_SUCCESS;
+}
+
+
+__STATIC_INLINE u32 FGmac_ErrorCheck(Ft_Gmac_t *Gmac)
+{
+ u32 RegValue = 0;
+ u32 ErrIsr_RegValue = 0;
+ u32 RetValue = 0;
+ RegValue = Ft_in32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET);
+ ErrIsr_RegValue = Ft_in32(Gmac->Config.BaseAddress + DMA_INTR_ENA_OFFSET);
+
+ if (((RegValue & DMA_STATUS_TPS) == DMA_STATUS_TPS) && ((ErrIsr_RegValue & DMA_INTR_ENA_TSE) == DMA_INTR_ENA_TSE))
+ {
+ RetValue |= GMAC_ERROR_TRANSMIT_PROCESS_STOPPED;
+ }
+
+ if (((RegValue & DMA_STATUS_TU) == DMA_STATUS_TU) && ((ErrIsr_RegValue & DMA_INTR_ENA_TUE) == DMA_INTR_ENA_TUE))
+ {
+ RetValue |= GMAC_ERROR_TRANSMIT_UNAVAILABLE_STATUS;
+ }
+
+ if (((RegValue & DMA_STATUS_TJT) == DMA_STATUS_TJT) && ((ErrIsr_RegValue & DMA_INTR_ENA_THE) == DMA_INTR_ENA_THE))
+ {
+ RetValue |= GMAC_ERROR_TRANSMIT_JABBER_TIMEOUT;
+ }
+
+ if (((RegValue & DMA_STATUS_OVF) == DMA_STATUS_OVF) && ((ErrIsr_RegValue & DMA_INTR_ENA_OVE) == DMA_INTR_ENA_OVE))
+ {
+ RetValue |= GMAC_ERROR_RECEIVE_FIFO_OVERFLOW;
+ }
+
+ if (((RegValue & DMA_STATUS_UNF) == DMA_STATUS_UNF) && ((ErrIsr_RegValue & DMA_INTR_ENA_UNE) == DMA_INTR_ENA_UNE))
+ {
+ RetValue |= GMAC_ERROR_TRANSMIT_UNDERFLOW;
+ }
+
+ if (((RegValue & DMA_STATUS_RU) == DMA_STATUS_RU) && ((ErrIsr_RegValue & DMA_INTR_ENA_RUE) == DMA_INTR_ENA_RUE))
+ {
+ RetValue |= GMAC_ERROR_RECEIVE_BUFFER_UNAVAILABLE;
+ }
+
+ if (((RegValue & DMA_STATUS_RPS) == DMA_STATUS_RPS) && ((ErrIsr_RegValue & DMA_INTR_ENA_RSE) == DMA_INTR_ENA_RSE))
+ {
+ RetValue |= GMAC_ERROR_RECEIVE_PROCESS_STOPPED;
+ }
+
+ if (((RegValue & DMA_STATUS_RWT) == DMA_STATUS_RWT) && ((ErrIsr_RegValue & DMA_INTR_ENA_RWE) == DMA_INTR_ENA_RWE))
+ {
+ RetValue |= GMAC_ERROR_RECEIVE_WATCHDOG_TIMEOUT;
+ }
+
+ if (((RegValue & DMA_STATUS_ETI) == DMA_STATUS_ETI) && ((ErrIsr_RegValue & DMA_INTR_ENA_ETE) == DMA_INTR_ENA_ETE))
+ {
+ RetValue |= GMAC_ERROR_EARLY_TRANSMIT_INTERRUPT;
+ }
+
+ if (((RegValue & DMA_STATUS_FBI) == DMA_STATUS_FBI) && ((ErrIsr_RegValue & DMA_INTR_ENA_FBE) == DMA_INTR_ENA_FBE))
+ {
+ RetValue |= GMAC_ERROR_FATAL_BUS_ERROR;
+ }
+
+ if (0U == RetValue)
+ {
+ RetValue |= GMAC_ERROR_UNDEFINED;
+ }
+ Ft_printf("error RetValue %x \r\n", RetValue);
+ return RetValue;
+}
+
+
+void FGmac_IntrHandler(void *Args)
+{
+ Ft_Gmac_t *Gmac;
+ u32 RegValue;
+ u32 MACRegValue;
+ Ft_assertVoid(Args != NULL);
+ Gmac = (Ft_Gmac_t *)Args;
+
+ RegValue = Ft_in32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET);
+ if ((RegValue)&DMA_STATUS_GLI)
+ {
+ MACRegValue = Ft_in32(Gmac->Config.BaseAddress + GMAC_MAC_MAC_PHY_STATUS);
+ if (Gmac->StatusHandler)
+ {
+ Gmac->StatusHandler(Gmac->StatusArgs, MACRegValue);
+ }
+ }
+
+ /* Frame received */
+ if ((RegValue & (DMA_STATUS_RI)) != 0)
+ {
+ if (Gmac->RecvHandler)
+ {
+ Gmac->RecvHandler(Gmac->RecvArgs);
+ }
+
+ Ft_out32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET, DMA_STATUS_RI);
+ }
+ else if ((RegValue & DMA_STATUS_TI) == DMA_STATUS_TI)
+ {
+ Ft_printf("DMA_STATUS_TI %x \r\n", RegValue);
+ Ft_printf("ti debug %x \r\n", Ft_in32(Gmac->Config.BaseAddress + GMAC_INTERNAL_MODULE_STATUS_OFFSET));
+
+ Ft_out32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET, DMA_STATUS_TI);
+ }
+
+ Ft_out32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET, DMA_STATUS_NIS);
+
+ /* DMA Error */
+ if ((Ft_in32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET) & DMA_STATUS_AIS) == DMA_STATUS_AIS)
+ {
+ if (Gmac->ErrorHandler)
+ Gmac->ErrorHandler(Gmac->ErrorArgs, FGmac_ErrorCheck(Gmac));
+ Ft_out32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET, Ft_in32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET));
+ }
+}
diff --git a/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_sinit.c b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_sinit.c
new file mode 100644
index 0000000000..909e05dc22
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_sinit.c
@@ -0,0 +1,34 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-05-25 16:43:06
+ * @Description:  This files is for gmac static init
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_gmac.h"
+#include "ft_parameters.h"
+
+extern FGmac_Config_t Gmac_ConfigTable[FT_GMAC_INSTANCES_NUM];
+
+FGmac_Config_t *Ft_Gmac_LookupConfig(u32 InstanceId)
+{
+ FGmac_Config_t *CfgPtr = NULL;
+ u32 Index;
+ for (Index = 0; Index < (u32)FT_GMAC_INSTANCES_NUM; Index++)
+ {
+ if (Gmac_ConfigTable[Index].InstanceId == InstanceId)
+ {
+ CfgPtr = &Gmac_ConfigTable[Index];
+ break;
+ }
+ }
+
+ return (FGmac_Config_t *)CfgPtr;
+}
diff --git a/bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio.c b/bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio.c
new file mode 100644
index 0000000000..37c442f39e
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio.c
@@ -0,0 +1,107 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-27 17:55:31
+ * @LastEditTime: 2021-05-25 16:43:31
+ * @Description:  This files is for
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_gpio.h"
+#include "ft_gpio_hw.h"
+#include "ft_assert.h"
+#include "ft_debug.h"
+
+#define GPIO_MAX_PIN 7
+#define GPIO_MAX_CTRL_ID 1
+
+void FGpio_SetGroupModeA(FT_IN u32 ctrlId, FT_IN u8 pin, FT_IN u32 mode)
+{
+ u32 RegVal;
+ Ft_assertNoneReturn(ctrlId <= GPIO_MAX_CTRL_ID);
+ Ft_assertNoneReturn(pin <= GPIO_MAX_PIN);
+
+ RegVal = FGpioA_ReadReg(ctrlId, GPIO_INTEN);
+ switch (mode)
+ {
+ case GPIO_MODE_GPIO:
+ RegVal &= ~(1 << pin);
+ break;
+ case GPIO_MODE_INT:
+ RegVal |= (1 << pin);
+ break;
+ default:
+ Ft_assertNoneReturn(0);
+ break;
+ }
+
+ FGpioA_WriteReg(ctrlId, GPIO_INTEN, RegVal);
+ return;
+}
+
+static void FGpio_SetPinInOutA(FT_IN u32 ctrlId, FT_IN u8 pin, FT_IN u8 inOut)
+{
+ u32 RegVal;
+ Ft_assertNoneReturn(ctrlId <= GPIO_MAX_CTRL_ID);
+ Ft_assertNoneReturn(pin <= GPIO_MAX_PIN);
+
+ RegVal = FGpioA_ReadReg(ctrlId, GPIO_SWPORTA_DDR);
+ if (inOut != (RegVal & (0x1 << pin)))
+ {
+ if (GPIO_INPUT == inOut)
+ {
+ RegVal &= ~(0x1 << pin);
+ }
+ else if (GPIO_OUTPUT == inOut)
+ {
+ RegVal |= (0x1 << pin);
+ }
+ else
+ {
+ Ft_assertNoneReturn(0);
+ }
+
+ FGpioA_WriteReg(ctrlId, GPIO_SWPORTA_DDR, RegVal);
+ }
+
+ return;
+}
+
+u32 FGpio_ReadPinA(FT_IN u32 ctrlId, FT_IN u8 pin)
+{
+ u32 RegVal;
+ u32 OnOff;
+ Ft_assertNoneReturn(ctrlId <= GPIO_MAX_CTRL_ID);
+ Ft_assertNoneReturn(pin <= GPIO_MAX_PIN);
+
+ FGpio_SetPinInOutA(ctrlId, pin, GPIO_INPUT);
+ RegVal = FGpioA_ReadReg(ctrlId, GPIO_EXT_PORTA);
+ OnOff = (RegVal & (0x1 << pin)) ? GPIO_ON : GPIO_OFF;
+ return OnOff;
+}
+
+void FGpio_WritePinA(FT_IN u32 ctrlId, FT_IN u8 pin, FT_IN u8 onOff)
+{
+ u32 RegVal;
+ Ft_assertNoneReturn(ctrlId <= GPIO_MAX_CTRL_ID);
+ Ft_assertNoneReturn(pin <= GPIO_MAX_PIN);
+ Ft_assertNoneReturn((onOff == GPIO_OFF) || (onOff == GPIO_ON));
+
+ FGpio_SetPinInOutA(ctrlId, pin, GPIO_OUTPUT);
+ RegVal = FGpioA_ReadReg(ctrlId, GPIO_SWPORTA_DR);
+ if (GPIO_OFF == onOff)
+ {
+ RegVal &= ~(1 << pin);
+ }
+ else
+ {
+ RegVal |= (1 << pin);
+ }
+ FGpioA_WriteReg(ctrlId, GPIO_SWPORTA_DR, RegVal);
+ return;
+}
diff --git a/bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio.h b/bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio.h
new file mode 100644
index 0000000000..b875470e53
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio.h
@@ -0,0 +1,73 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-27 17:55:12
+ * @LastEditTime: 2021-04-30 14:38:45
+ * @Description:  This files is for
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef FT_BSP_GPIO_H
+#define FT_BSP_GPIO_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "ft_types.h"
+#include "ft_gpio_hw.h"
+
+/* gpio mode: gpio/int */
+#define GPIO_MODE_GPIO 0
+#define GPIO_MODE_INT 1
+
+/* define debug utilities */
+#define FT_GPIO_DEBUG_TAG "FT_GPIO"
+#define FT_GPIO_ENABLE_DEBUG
+#define FT_GPIO_ERROR(format, ...) FT_DEBUG_PRINT_E(FT_GPIO_DEBUG_TAG, format, ##__VA_ARGS__)
+#ifdef FT_GPIO_ENABLE_DEBUG
+#define FT_GPIO_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FT_GPIO_DEBUG_TAG, format, ##__VA_ARGS__)
+#define FT_GPIO_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FT_GPIO_DEBUG_TAG, format, ##__VA_ARGS__)
+#else
+#define FT_GPIO_DEBUG_I(format, ...)
+#define FT_GPIO_DEBUG_W(format, ...)
+#endif
+
+ /**
+ * @name: FGpio_SetGroupModeA
+ * @msg: set gpio mode, polling or intr
+ * @return {*}
+ * @param {FT_IN u32} ctrlId
+ * @param {FT_IN u8} pin
+ * @param {FT_IN u32} mode
+ */
+ void FGpio_SetGroupModeA(FT_IN u32 CtrlId, FT_IN u8 Pin, FT_IN u32 Mode);
+ /**
+ * @name: FGpio_ReadPinA
+ * @msg: get gpio pin status
+ * @return {*}
+ * @param {FT_IN u32} ctrlId
+ * @param {FT_IN u8} pin
+ */
+ u32 FGpio_ReadPinA(FT_IN u32 CtrlId, FT_IN u8 Pin);
+ /**
+ * @name: FGpio_WritePinA
+ * @msg: set gpio pin status
+ * @return {*}
+ * @param {FT_IN u32} ctrlId
+ * @param {FT_IN u8} pin
+ * @param {FT_IN u8} onOff
+ */
+ void FGpio_WritePinA(FT_IN u32 CtrlId, FT_IN u8 Pin, FT_IN u8 OnOff);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio_hw.h b/bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio_hw.h
new file mode 100644
index 0000000000..77d9071fd4
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio_hw.h
@@ -0,0 +1,92 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-27 17:55:22
+ * @LastEditTime: 2021-04-28 08:39:20
+ * @Description:  This files is for
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef FT_BSP_GPIO_HW_H
+#define FT_BSP_GPIO_HW_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "ft_types.h"
+#include "ft_io.h"
+
+#define GPIO_CTRL_ID_0 0
+#define GPIO_CTRL_ID_1 1
+
+/* base address of gpio register */
+#define GPIO_CTRL0_PA_BASE 0x28004000
+#define GPIO_CTRL1_PA_BASE 0x28005000
+#define GPIO_GROUPA_OFFSET 0x0
+#define GPIO_GROUPB_OFFSET 0xc
+
+/* offset of register map */
+#define GPIO_SWPORTA_DR 0x00 //A 组端口输出寄存器
+#define GPIO_SWPORTA_DDR 0x04 //A 组端口方向控制寄存器
+#define GPIO_EXT_PORTA 0x08 //A 组端口输入寄存器
+
+#define GPIO_SWPORTB_DR 0x0c //B 组端口输出寄存器
+#define GPIO_SWPORTB_DDR 0x10 //B 组端口方向控制寄存器
+#define GPIO_EXT_PORTB 0x14 //B 组端口输入寄存器
+
+#define GPIO_INTEN 0x18 //A 组端口中断使能寄存器
+#define GPIO_INTMASK 0x1c //A 组端口中断屏蔽寄存器
+#define GPIO_INTTYPE_LEVEL 0x20 //A 组端口中断等级寄存器
+#define GPIO_INT_POLARITY 0x24 //A 组端口中断极性寄存器
+#define GPIO_INTSTATUS 0x28 //A 组端口中断状态寄存器
+#define GPIO_RAW_INTSTATUS 0x2c //A 组端口原始中断状态寄存器
+
+#define GPIO_LS_SYNC 0x30 //配置中断同步寄存器
+#define GPIO_DEBOUNCE 0x34 //防反跳配置寄存器
+#define GPIO_PORTA_EOI 0x38 //A 组端口中断清除寄存器
+
+/* misc marco */
+#define GPIO_GROUP_A 0
+#define GPIO_OFF 0
+#define GPIO_ON 1
+#define GPIO_INPUT 0
+#define GPIO_OUTPUT 1
+
+ inline static u32 FGpio_GetBaseAddr(FT_IN u32 ctrlId, FT_IN u32 groupId)
+ {
+ static const u32 CtrlAddr[2] = {GPIO_CTRL0_PA_BASE, GPIO_CTRL1_PA_BASE};
+ static const u32 GroupOff[2] = {GPIO_GROUPA_OFFSET, GPIO_GROUPB_OFFSET};
+ return CtrlAddr[ctrlId] + GroupOff[groupId];
+ }
+
+/**
+ * @name: FGpio_WriteReg
+ * @msg: write gpio register
+ * @param {u32} BaseAddress base addr of i2c
+ * @param {u32} RegOffset addr offset of i2c register
+ * @param {u32} RegisterValue val to be write into register
+ * @return {void}
+ */
+#define FGpioA_WriteReg(ctrlId, RegOffset, RegisterValue) Ft_out32(FGpio_GetBaseAddr(ctrlId, GPIO_GROUP_A) + (u32)RegOffset, (u32)RegisterValue)
+
+/**
+ * @name: FGpio_ReadReg
+ * @msg: read gpio register
+ * @param {u32} BaseAddress base addr of i2c
+ * @param {u32} RegOffset addr offset of i2c register
+ * @return {u32} val read from register
+ */
+#define FGpioA_ReadReg(ctrlId, RegOffset) Ft_in32(FGpio_GetBaseAddr(ctrlId, GPIO_GROUP_A) + (u32)RegOffset)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c.c b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c.c
new file mode 100644
index 0000000000..57985f906f
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c.c
@@ -0,0 +1,510 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-05-25 16:45:00
+ * @Description:  This files is for i2c user interface
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include "ft_mux.h"
+#include "ft_i2c_hw.h"
+#include "ft_i2c.h"
+#include "ft_generic_timer.h"
+
+/* reset val of register */
+#define I2C_CON_DEFAULT 0x7F
+#define I2C_TAR_DEFAULT 0x1055
+#define I2C_SAR_DEFAULT 0x55
+#define I2C_DATA_CMD_DEFAULT 0x0
+#define I2C_SS_SCL_LCNT_DEFAULT 0x1D6
+#define I2C_SS_SCL_HCNT_DEFAULT 0x190
+#define I2C_FS_SCL_LCNT_DEFAULT 0x82
+#define I2C_FS_SCL_HCNT_DEFAULT 0x3C
+#define I2C_HS_SCL_LCNT_DEFAULT 0x10
+#define I2C_HS_SCL_HCNT_DEFAULT 0x6
+#define I2C_INTR_MASK_DEFAULT 0x8FF
+//#define I2C_RX_TL_DEFAULT 0x0
+//#define I2C_TX_TL_DEFAULT 0x0
+#define I2C_SCL_HCNT_DEFAULT 0x2f
+#define I2C_SCL_LCNT_DEFAULT 0x2f
+//#define I2C_RX_TL_SET 0xff
+//#define I2C_TX_TL_SET 0xff
+
+#define I2C_RX_TL_BY_BYTE 0x0
+#define I2C_TX_TL_BY_BYTE 0x0
+#define I2C_RX_TL_BY_FIFO 0x01
+#define I2C_TX_TL_BY_FIFO 0x01
+
+LOCAL const u32 g_I2cSpeedMask[MAX_I2C_SPEED] = {I2C_STANDARD_SPEED_MASK,
+ I2C_FAST_SPEED_MASK,
+ I2C_HIGH_SPEED_MASK};
+LOCAL const u32 g_I2cSclLcntReg[MAX_I2C_SPEED] = {I2C_SS_SCL_LCNT,
+ I2C_FS_SCL_LCNT, I2C_HS_SCL_LCNT};
+LOCAL const u32 g_I2cSclHcntReg[MAX_I2C_SPEED] = {I2C_SS_SCL_HCNT,
+ I2C_FS_SCL_LCNT, I2C_HS_SCL_LCNT};
+
+void FI2C_resetReg(u32 BaseAddr)
+{
+ /* set default value for register */
+ FI2C_WriteReg(BaseAddr, I2C_CON, I2C_CON_DEFAULT);
+ FI2C_WriteReg(BaseAddr, I2C_TAR, I2C_TAR_DEFAULT);
+ FI2C_WriteReg(BaseAddr, I2C_SAR, I2C_SAR_DEFAULT);
+ FI2C_WriteReg(BaseAddr, I2C_DATA_CMD, I2C_DATA_CMD_DEFAULT);
+ FI2C_WriteReg(BaseAddr, I2C_SS_SCL_LCNT, I2C_SS_SCL_LCNT_DEFAULT);
+ FI2C_WriteReg(BaseAddr, I2C_SS_SCL_HCNT, I2C_SS_SCL_HCNT_DEFAULT);
+ FI2C_WriteReg(BaseAddr, I2C_FS_SCL_LCNT, I2C_FS_SCL_LCNT_DEFAULT);
+ FI2C_WriteReg(BaseAddr, I2C_FS_SCL_HCNT, I2C_FS_SCL_HCNT_DEFAULT);
+ FI2C_WriteReg(BaseAddr, I2C_HS_SCL_LCNT, I2C_HS_SCL_LCNT_DEFAULT);
+ FI2C_WriteReg(BaseAddr, I2C_HS_SCL_HCNT, I2C_HS_SCL_HCNT_DEFAULT);
+ FI2C_WriteReg(BaseAddr, I2C_INTR_MASK, I2C_INTR_MASK_DEFAULT);
+ FI2C_WriteReg(BaseAddr, I2C_RX_TL, I2C_RX_TL_DEFAULT);
+ FI2C_WriteReg(BaseAddr, I2C_TX_TL, I2C_TX_TL_DEFAULT);
+}
+
+inline LOCAL void FI2C_setSclClk(FT_IN u32 BaseAddr, FT_IN FI2C_SpeedType_t SpeedType,
+ FT_IN u32 SclLcnt, FT_IN u32 SclHcnt)
+{
+ u32 SclLcntAddr = g_I2cSclLcntReg[SpeedType];
+ u32 SclHcntAddr = g_I2cSclHcntReg[SpeedType];
+
+ FI2C_WriteReg(BaseAddr, SclLcntAddr, SclLcnt);
+ FI2C_WriteReg(BaseAddr, SclHcntAddr, SclHcnt);
+
+ return;
+}
+
+inline LOCAL void FI2C_setCtrlParam(FT_IN u32 BaseAddr, FT_IN FI2C_SpeedType_t SpeedType, FT_IN bool_t Is7BitAddr)
+{
+ u32 RegVal;
+
+ RegVal = I2C_CON_ME | g_I2cSpeedMask[SpeedType];
+ RegVal |= ((TRUE == Is7BitAddr) ? I2C_CON_MASTER_ADR_7BIT : I2C_CON_MASTER_ADR_10BIT);
+ RegVal |= I2C_CON_RESTART_EN | I2C_CON_SLAVE_DISABLE;
+
+ FI2C_WriteReg(BaseAddr, I2C_CON, RegVal);
+ return;
+}
+
+void FI2C_initMasterCfg(FT_IN FI2C_Instance_t id,
+ FT_IN FI2C_WorkMode_t mode,
+ FT_IN bool_t UseWRFifo,
+ FT_IN u32 PageSize,
+ FT_INOUT FI2C_Config_t *pCfg)
+{
+ Ft_assertNoneReturn(NULL != pCfg);
+
+ pCfg->InstanceId = id;
+ pCfg->BaseAddress = g_FI2cRegBaseAddr[id];
+ pCfg->IrqNum = g_FI2cIrqNum[id];
+ pCfg->IrqPriority = I2C_DEFAULT_IRQ_PRIORITY;
+ pCfg->BusSpeed = I2C_STANDARD_SPEED;
+ pCfg->SclLcnt = I2C_SCL_LCNT_DEFAULT;
+ pCfg->SclHcnt = I2C_SCL_HCNT_DEFAULT;
+ pCfg->WRByFifo = UseWRFifo;
+ if (TRUE == pCfg->WRByFifo)
+ {
+ pCfg->RxThres = I2C_RX_TL_BY_FIFO;
+ pCfg->TxThres = I2C_TX_TL_BY_FIFO;
+ }
+ else
+ {
+ pCfg->RxThres = I2C_RX_TL_BY_BYTE;
+ pCfg->TxThres = I2C_TX_TL_BY_BYTE;
+ }
+ pCfg->Is7BitAddr = TRUE;
+ pCfg->BlockSize = PageSize;
+
+ if (I2C_POLLING_MODE == mode)
+ {
+ pCfg->IsPolling = TRUE;
+ }
+ else if (I2C_IRQ_MODE == mode)
+ {
+ pCfg->IsPolling = FALSE;
+ }
+ else
+ {
+ Ft_assertNoneReturn(0);
+ }
+
+ return;
+}
+
+void FI2C_initMaster(FT_IN FI2C_Instance_t id,
+ FT_IN FI2C_WorkMode_t mode,
+ FT_IN u32 SlaveAddr,
+ FT_IN bool_t UseWRFifo,
+ FT_IN u32 PageSize,
+ FT_INOUT FI2C_t *pDev)
+{
+ u32 RxDepth;
+ u32 TxDepth;
+
+ Ft_assertNoneReturn(NULL != pDev);
+
+ memset(pDev, 0, sizeof(FI2C_t));
+
+ /* setup i2c bus mux */
+ Ft_setI2cMux(id);
+
+ /* setup i2c config as master */
+ FI2C_initMasterCfg(id, mode, UseWRFifo, PageSize, &pDev->Config);
+ pDev->SlaveAddr = SlaveAddr;
+ pDev->DelayHandle = Ft_GenericTimer_UsDelay;
+
+ /* init irq handler */
+ pDev->pRxEvent = NULL;
+ pDev->pTxEvent = NULL;
+
+ pDev->pIrqCallBack = NULL;
+ pDev->pWaitCallBack = NULL;
+
+ FI2C_DISABLE_I2C_BUS(pDev);
+ FI2C_CLR_ALL_IRQ_STATUS(pDev);
+
+ /* reset reg val */
+ FI2C_resetReg(pDev->Config.BaseAddress);
+
+ /* set scl high && low level */
+ FI2C_setSclClk(pDev->Config.BaseAddress,
+ pDev->Config.BusSpeed,
+ pDev->Config.SclLcnt,
+ pDev->Config.SclHcnt);
+
+ /* set ctrl parameters */
+ FI2C_setCtrlParam(pDev->Config.BaseAddress,
+ pDev->Config.BusSpeed,
+ pDev->Config.Is7BitAddr);
+
+ /* set rx & tx trigger level */
+ RxDepth = FI2C_GET_RX_BUFFER_DEPTH(pDev);
+ TxDepth = FI2C_GET_TX_BUFFER_DEPTH(pDev);
+
+ /* threshold shall not greater than depth */
+
+ FI2C_SET_TX_TL(pDev, FT_MIN(pDev->Config.TxThres, TxDepth));
+ FI2C_SET_RX_TL(pDev, FT_MIN(pDev->Config.RxThres, RxDepth));
+ pDev->IsReady = TRUE;
+ return;
+}
+
+void FI2C_deInitMaster(FT_INOUT FI2C_t *pDev)
+{
+ /* assert no memory need to release */
+ pDev->IsReady = FALSE;
+}
+
+inline LOCAL void FI2C_sendRestartCmd(FT_IN u32 BaseAddr)
+{
+ u32 RegVal = FI2C_ReadReg(BaseAddr, I2C_CON);
+ RegVal |= I2C_CON_RESTART_EN;
+ FI2C_WriteReg(BaseAddr, I2C_CON, RegVal);
+}
+
+inline LOCAL void FI2C_setTarAddr(FT_IN u32 BaseAddr, FT_IN u32 SlaveAddr)
+{
+ u32 RegVal = (SlaveAddr & I2C_TAR_ADR_MASK);
+ FI2C_WriteReg(BaseAddr, I2C_TAR, RegVal);
+}
+
+inline LOCAL void FI2C_sendWriteCmd(FT_IN u32 BaseAddr, FT_IN u32 PageAddr)
+{
+ u32 RegVal = I2C_DATA_CMD_RESTART | (PageAddr & I2C_DATA_CMD_DAT_MASK);
+ FI2C_WriteReg(BaseAddr, I2C_DATA_CMD, RegVal);
+}
+
+inline LOCAL void FI2C_sendStartReadCmd(FT_IN u32 BaseAddr, FT_IN u32 PageAddr)
+{
+ /* send read cmd */
+ u32 RegVal = I2C_DATA_CMD_STOP | I2C_DATA_CMD_RESTART | (PageAddr & 0xff);
+ FI2C_WriteReg(BaseAddr, I2C_DATA_CMD, RegVal);
+}
+
+void FI2C_sendStopCmd(FT_IN u32 BaseAddr)
+{
+ /* send stop signal */
+ u32 RegVal = I2C_DATA_CMD_STOP;
+ FI2C_WriteReg(BaseAddr, I2C_DATA_CMD, RegVal);
+}
+
+LOCAL bool_t FI2C_blockWaitForStatus(FT_IN u32 stMask, FT_INOUT FI2C_t *pDev)
+{
+ u32 timeout = 0;
+ bool_t IsFree = FALSE;
+
+ Ft_assertNoneReturn(NULL != pDev);
+
+ /* Wait until Specific Status Bit in I2C_STATUS is 1 */
+ while ((!FI2C_CHECK_STATUS(pDev, stMask)) && (timeout < I2C_TIMEOUT))
+ {
+ pDev->DelayHandle(5000);
+ timeout++;
+ }
+
+ /* check if status wait successful or timeout */
+ if (I2C_TIMEOUT != timeout)
+ {
+ IsFree = TRUE;
+ }
+ else
+ {
+ FT_I2C_ERROR("wait status 0x%x failed!!! reg val is 0x%x",
+ stMask, FI2C_GET_STATUS(pDev));
+ }
+
+ return IsFree;
+}
+
+u32 FI2C_writeByByte(FT_IN u32 len, FT_IN u8 *pI2cBuf, FT_IN u8 PageAddr, FT_INOUT FI2C_t *pDev)
+{
+ u32 loop;
+ bool_t isNotTimeout;
+ u32 ret = ERR_I2C_OK;
+ Ft_assertNoneReturn((NULL != pDev) && (NULL != pI2cBuf));
+
+ if (!pDev->IsReady)
+ {
+ return ERR_I2C_NOT_READY;
+ }
+
+ if (pDev->Config.BlockSize <= len)
+ {
+ return ERR_I2C_SIZE_TOO_LARGE;
+ }
+
+ FI2C_DISABLE_I2C_BUS(pDev);
+ FI2C_sendRestartCmd(pDev->Config.BaseAddress);
+ FI2C_setTarAddr(pDev->Config.BaseAddress, pDev->SlaveAddr);
+ FI2C_ENABLE_I2C_BUS(pDev);
+
+ FI2C_sendWriteCmd(pDev->Config.BaseAddress, PageAddr);
+
+ for (loop = 0; loop < len; loop++)
+ {
+ if (!pDev->Config.IsPolling)
+ {
+ FI2C_setIrq(pDev, I2C_IRQ_TX_EMPTY, TRUE);
+ }
+ pDev->DelayHandle(2);
+ FI2C_SET_TX_DATA(pDev, pI2cBuf[loop]);
+
+ /* wait until TX fifo is empty */
+ if (pDev->Config.IsPolling)
+ {
+ isNotTimeout = FI2C_blockWaitForStatus(I2C_STATUS_TFE, pDev);
+ if (!isNotTimeout)
+ {
+ ret = ERR_I2C_WRITE_TIMEOUT;
+ goto EXIT;
+ }
+ }
+ else
+ {
+ pDev->LastIrqErr = ERR_I2C_OK;
+ if (pDev->pWaitCallBack)
+ {
+ pDev->pWaitCallBack(I2C_IRQ_TYPE_TX_COMPLETE, pDev);
+ }
+ else
+ {
+ ret = ERR_I2C_INVALID_HANDLER;
+ goto EXIT;
+ }
+
+ if (ERR_I2C_OK != pDev->LastIrqErr)
+ {
+ ret = pDev->LastIrqErr;
+ goto EXIT;
+ }
+ }
+
+ pDev->DelayHandle(2);
+ }
+
+EXIT:
+ FI2C_SEND_TX_STOP_CMD(pDev);
+ pDev->DelayHandle(2);
+
+ return ret;
+}
+
+u32 FI2C_readByByte(FT_IN u32 len, FT_OUT u8 *pI2cBuf, FT_IN u8 PageAddr, FT_INOUT FI2C_t *pDev)
+{
+ u32 loop;
+ bool_t isNotTimeout;
+ u32 ret = ERR_I2C_OK;
+ Ft_assertNoneReturn((NULL != pDev) && (NULL != pI2cBuf));
+
+ if (!pDev->IsReady)
+ {
+ return ERR_I2C_NOT_READY;
+ }
+
+ FI2C_DISABLE_I2C_BUS(pDev);
+ FI2C_sendRestartCmd(pDev->Config.BaseAddress);
+ FI2C_CLR_ALL_IRQ_STATUS(pDev);
+ FI2C_setTarAddr(pDev->Config.BaseAddress, pDev->SlaveAddr);
+ FI2C_ENABLE_I2C_BUS(pDev);
+
+ /* assign page addr when start read */
+ FI2C_sendStartReadCmd(pDev->Config.BaseAddress, PageAddr);
+
+ /* read contents */
+ for (loop = 0; loop < len; loop++)
+ {
+ if (!pDev->Config.IsPolling)
+ {
+ FI2C_setIrq(pDev, I2C_IRQ_RX_FULL, TRUE);
+ }
+
+ FI2C_SEND_RX_NEXT_CMD(pDev);
+ pDev->DelayHandle(2);
+
+ /* wait until data reach and start fetch data */
+ if (pDev->Config.IsPolling)
+ {
+ isNotTimeout = FI2C_blockWaitForStatus(I2C_STATUS_RFNE, pDev);
+ if (!isNotTimeout)
+ {
+ ret = ERR_I2C_READ_TIMEOUT;
+ goto EXIT;
+ }
+ }
+ else
+ {
+ pDev->LastIrqErr = ERR_I2C_OK;
+ if (pDev->pWaitCallBack)
+ {
+ pDev->pWaitCallBack(I2C_IRQ_TYPE_RX_COMPLETE, pDev);
+ }
+ else
+ {
+ ret = ERR_I2C_INVALID_HANDLER;
+ goto EXIT;
+ }
+
+ if (ERR_I2C_OK != pDev->LastIrqErr)
+ {
+ ret = pDev->LastIrqErr;
+ goto EXIT;
+ }
+ }
+
+ pI2cBuf[loop] = FI2C_GET_RX_DATA(pDev);
+ pDev->DelayHandle(2);
+ }
+
+EXIT:
+ FI2C_SEND_RX_STOP_CMD(pDev);
+ pDev->DelayHandle(2);
+ return ret;
+}
+
+u32 FI2C_writeByFifo(FT_IN u8 PageAddr, FT_INOUT FI2C_t *pDev)
+{
+ u32 loop;
+ u32 ret = ERR_I2C_OK;
+ u32 timeout = I2C_TIMEOUT / 10;
+ Ft_assertNoneReturn(NULL != pDev);
+
+ if (!pDev->IsReady)
+ {
+ return ERR_I2C_NOT_READY;
+ }
+
+ if (pDev->Config.IsPolling)
+ {
+ return ERR_I2C_NOT_SUPPORT;
+ }
+
+ FI2C_DISABLE_I2C_BUS(pDev);
+ FI2C_sendRestartCmd(pDev->Config.BaseAddress);
+ FI2C_setTarAddr(pDev->Config.BaseAddress, pDev->SlaveAddr);
+ FI2C_ENABLE_I2C_BUS(pDev);
+
+ FI2C_sendWriteCmd(pDev->Config.BaseAddress, PageAddr);
+
+ /* enable TX Empty, disable Rx Full */
+ FI2C_setIrq(pDev, I2C_IRQ_TX_EMPTY, TRUE);
+ FI2C_setIrq(pDev, I2C_IRQ_RX_FULL, FALSE);
+
+ pDev->LastIrqErr = ERR_I2C_OK;
+ if (pDev->pWaitCallBack)
+ {
+ pDev->pWaitCallBack(I2C_IRQ_TYPE_TX_COMPLETE, pDev);
+ }
+ else
+ {
+ ret = ERR_I2C_INVALID_HANDLER;
+ }
+
+ if (ERR_I2C_OK != pDev->LastIrqErr)
+ {
+ ret = pDev->LastIrqErr;
+ }
+
+ return ret;
+}
+
+u32 FI2C_readByFifo(FT_IN u8 PageAddr, FT_INOUT FI2C_t *pDev)
+{
+ u32 loop;
+ u32 ret = ERR_I2C_OK;
+ u32 timeout = I2C_TIMEOUT / 10;
+ Ft_assertNoneReturn((NULL != pDev));
+
+ if (!pDev->IsReady)
+ {
+ return ERR_I2C_NOT_READY;
+ }
+
+ if (pDev->Config.IsPolling)
+ {
+ return ERR_I2C_NOT_SUPPORT;
+ }
+
+ FI2C_DISABLE_I2C_BUS(pDev);
+ FI2C_sendRestartCmd(pDev->Config.BaseAddress);
+ FI2C_setTarAddr(pDev->Config.BaseAddress, pDev->SlaveAddr);
+ FI2C_ENABLE_I2C_BUS(pDev);
+
+ /* assign page addr when start read */
+ FI2C_sendStartReadCmd(pDev->Config.BaseAddress, PageAddr);
+
+ FI2C_setIrq(pDev, I2C_IRQ_RX_FULL, TRUE);
+ FI2C_setIrq(pDev, I2C_IRQ_TX_EMPTY, FALSE);
+ FI2C_SET_RX_TL(pDev, 1);
+
+ pDev->DelayHandle(2);
+ FT_I2C_DEBUG_I("rx tl is 0x%x irq mask 0x%x",
+ FI2C_GET_RX_TL(pDev),
+ FI2C_getIrqMask(pDev));
+
+ FI2C_SEND_RX_NEXT_CMD(pDev);
+ pDev->DelayHandle(2);
+
+ pDev->LastIrqErr = ERR_I2C_OK;
+ if (pDev->pWaitCallBack)
+ {
+ pDev->pWaitCallBack(I2C_IRQ_TYPE_RX_COMPLETE, pDev);
+ }
+ else
+ {
+ ret = ERR_I2C_INVALID_HANDLER;
+ }
+
+ if (ERR_I2C_OK != pDev->LastIrqErr)
+ {
+ ret = pDev->LastIrqErr;
+ }
+ FI2C_SET_RX_TL(pDev, 0);
+ return ret;
+}
diff --git a/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c.h b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c.h
new file mode 100644
index 0000000000..20bab542b7
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c.h
@@ -0,0 +1,197 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-04-07 13:32:20
+ * @Description:  This files is for i2c user interface
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef FT_BSP_I2C_H
+#define FT_BSP_I2C_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "ft_types.h"
+#include "ft_debug.h"
+#include "ft_assert.h"
+#include "ft_error_code.h"
+#include "ft_i2c_hw.h"
+
+ /* I2C Ctrl instance */
+ typedef enum
+ {
+ I2C_CTRL_ID_0 = 0,
+ I2C_CTRL_ID_1,
+ I2C_CTRL_ID_2,
+ I2C_CTRL_ID_3,
+
+ MAX_I2C_CTRL_ID,
+ } FI2C_Instance_t;
+
+ static const u32 g_FI2cIrqNum[MAX_I2C_CTRL_ID] = {
+ 44, 45, 46, 47};
+
+ static const u32 g_FI2cRegBaseAddr[MAX_I2C_CTRL_ID] = {
+ I2C0_BASE_ADDRESS, I2C1_BASE_ADDRESS,
+ I2C2_BASE_ADDRESS, I2C3_BASE_ADDRESS};
+
+#define I2C_DEFAULT_IRQ_PRIORITY 0
+
+ /* Type of I2C device */
+ typedef enum
+ {
+ I2C_MASTER_DEV = 0,
+ I2C_SLAVE_DEV,
+
+ MAX_I2C_DEV
+ } FI2C_DevType_t;
+
+ /* I2C work mode type */
+ typedef enum
+ {
+ I2C_POLLING_MODE = 0,
+ I2C_IRQ_MODE,
+
+ MAX_I2C_WORKMODE
+ } FI2C_WorkMode_t;
+
+ /* Type of I2C bus speed */
+ typedef enum
+ {
+ I2C_STANDARD_SPEED = 0,
+ I2C_FAST_SPEED,
+ I2C_HIGH_SPEED,
+
+ MAX_I2C_SPEED,
+ } FI2C_SpeedType_t;
+
+ /* I2C error code Submodule */
+ typedef enum
+ {
+ I2C_ERR_MODE_DEF = 0,
+
+ MAX_I2C_ERR_MODE,
+ } FI2C_Submodule_t;
+
+ /* I2C irq type */
+ typedef enum
+ {
+ I2C_IRQ_TYPE_NONE = 0,
+ I2C_IRQ_TYPE_TX_COMPLETE,
+ I2C_IRQ_TYPE_RX_COMPLETE,
+
+ MAX_I2C_IRQ_TYPE
+ } FI2C_IrqType_t;
+
+ /* I2C config info */
+ typedef struct
+ {
+ FI2C_Instance_t InstanceId; /* Id of I2C ctrl instance */
+ u32 BaseAddress; /* base address of I2C register */
+ FI2C_DevType_t WorkMode; /* work as master or slave */
+ FI2C_SpeedType_t BusSpeed; /* bus speed setting */
+ u32 SclLcnt;
+ u32 SclHcnt;
+ u32 RxThres;
+ u32 TxThres;
+ bool_t Is7BitAddr; /* TRUE: use 7 bit addr, FALSE: use 10 bit addr */
+ bool_t IsPolling; /* is polling */
+ u32 IrqNum; /* irq num of I2C in system */
+ u32 IrqPriority; /* irq priority */
+ u32 BlockSize; /* block size, for eeprom */
+ bool_t WRByFifo;
+ } FI2C_Config_t;
+
+ /* I2C RX/TX buffer */
+ typedef struct
+ {
+ u8 *BytePtr;
+ u32 TotalBytes;
+ u32 DataLength;
+ u32 CurIndex;
+ } FI2C_Buffer_t;
+
+ typedef void (*FI2C_IrqCallBackHandler_t)(FT_IN u32 IrqType,
+ FT_INOUT void *pDev,
+ FT_INOUT void *pArg);
+ typedef void (*FI2C_IrqWaitHandler_t)(FT_IN u32 IrqType,
+ FT_INOUT void *pDev);
+ typedef int32_t (*FI2C_DelayHandler_t)(FT_IN u32);
+
+ /* I2C device info */
+ typedef struct
+ {
+ FI2C_Config_t Config; /* Configuration data structure */
+
+ void *pRxEvent;
+ void *pTxEvent;
+ FI2C_IrqCallBackHandler_t pIrqCallBack;
+ FI2C_IrqWaitHandler_t pWaitCallBack;
+ u32 LastIrqErr;
+ FI2C_Buffer_t RxBuf;
+ FI2C_Buffer_t TxBuf;
+
+ FI2C_DelayHandler_t DelayHandle;
+ bool_t IsReady; /* Device is ininitialized and ready*/
+ u16 SlaveAddr; /* address of I2C slave device for master */
+ } FI2C_t;
+
+ void FI2C_initMaster(FT_IN FI2C_Instance_t id,
+ FT_IN FI2C_WorkMode_t mode,
+ FT_IN u32 SlaveAddr,
+ FT_IN bool_t UseWRFifo,
+ FT_IN u32 PageSize,
+ FT_INOUT FI2C_t *pDev);
+ u32 FI2C_writeByByte(FT_IN u32 len, FT_IN u8 *pI2cBuf, FT_IN u8 PageAddr,
+ FT_INOUT FI2C_t *pDev);
+ u32 FI2C_readByByte(FT_IN u32 len, FT_OUT u8 *pI2cBuf, FT_IN u8 PageAddr,
+ FT_INOUT FI2C_t *pDev);
+ u32 FI2C_setIrqHandler(FT_IN FI2C_IrqType_t IrqType, FT_IN FI2C_DelayHandler_t pHandler, FT_IN void *pArgs,
+ FT_INOUT FI2C_t *pDev);
+ void FI2C_irqHandler(void *pArgs);
+ void FI2C_irqHandler4Fifo(void *pArgs);
+ u32 FI2C_getIrqMask(FT_IN FI2C_t *pDev);
+ void FI2C_setIrqMask(FT_IN FI2C_t *pDev, FT_IN u32 mask);
+ void FI2C_setIrq(FT_IN FI2C_t *pDev, FT_IN u32 maskBit, FT_IN bool_t enable);
+ bool_t FI2C_checkIfIntr(FT_IN FI2C_t *pDev);
+ u32 FI2C_writeByFifo(FT_IN u8 PageAddr, FT_INOUT FI2C_t *pDev);
+ u32 FI2C_readByFifo(FT_IN u8 PageAddr, FT_INOUT FI2C_t *pDev);
+ void FI2C_deInitMaster(FT_INOUT FI2C_t *pDev);
+
+#define FT_I2C_DEBUG_TAG "FT_I2C"
+//#define FT_I2C_ENABLE_DEBUG
+#define FT_I2C_ERROR(format, ...) FT_DEBUG_PRINT_E(FT_I2C_DEBUG_TAG, format, ##__VA_ARGS__)
+#ifdef FT_I2C_ENABLE_DEBUG
+#define FT_I2C_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FT_I2C_DEBUG_TAG, format, ##__VA_ARGS__)
+#define FT_I2C_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FT_I2C_DEBUG_TAG, format, ##__VA_ARGS__)
+#else
+#define FT_I2C_DEBUG_I(format, ...)
+#define FT_I2C_DEBUG_W(format, ...)
+#endif
+
+#define ERR_I2C_OK ERR_SUCCESS
+#define ERR_I2C_NOT_READY FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 1)
+#define ERR_I2C_WRITE_TIMEOUT FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 2)
+#define ERR_I2C_READ_TIMEOUT FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 3)
+#define ERR_I2C_SIZE_TOO_LARGE FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 4)
+#define ERR_I2C_NOT_SUPPORT FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 5)
+#define ERR_I2C_INVALID_PARAM FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 6)
+#define ERR_I2C_INVALID_HANDLER FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 7)
+#define ERR_I2C_INVALID_NO_MEM FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 8)
+#define ERR_I2C_BUS_NOT_ENABLED FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 9)
+#define ERR_I2C_EVT_TIMEOUT FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 0xA)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_g.c b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_g.c
new file mode 100644
index 0000000000..3d9bd40994
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_g.c
@@ -0,0 +1,13 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-20 15:35:23
+ * @LastEditTime: 2021-04-20 15:35:24
+ * @Description:  This files is for
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
diff --git a/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_hw.h b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_hw.h
new file mode 100644
index 0000000000..53f7de7bfe
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_hw.h
@@ -0,0 +1,321 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-04-07 13:26:58
+ * @Description:  This files is for i2c register definition
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef FT_BSP_I2C_HW_H
+#define FT_BSP_I2C_HW_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "ft_types.h"
+#include "ft_io.h"
+
+/* i2c 1~4 reg base address */
+#define I2C0_BASE_ADDRESS 0x28006000U
+#define I2C1_BASE_ADDRESS 0x28007000U
+#define I2C2_BASE_ADDRESS 0x28008000U
+#define I2C3_BASE_ADDRESS 0x28009000U
+
+/* defines */
+#define I2C_TIMEOUT 5000
+
+#define I2C_MAX_READ_SIZE 1
+#define SEM_TIMEOUT 2
+
+ /* Register Definition */
+
+#define I2C_CON 0x00
+#define I2C_TAR 0x04
+#define I2C_SAR 0x08
+#define I2C_HS_MADDR 0x0C
+#define I2C_DATA_CMD 0x10
+#define I2C_SS_SCL_HCNT 0x14
+#define I2C_SS_SCL_LCNT 0x18
+#define I2C_FS_SCL_HCNT 0x1C
+#define I2C_FS_SCL_LCNT 0x20
+#define I2C_HS_SCL_HCNT 0x24
+#define I2C_HS_SCL_LCNT 0x28
+#define I2C_INTR_STAT 0x2C
+#define I2C_INTR_MASK 0x30
+#define I2C_RAW_INTR_STAT 0x34
+#define I2C_RX_TL 0x38
+#define I2C_TX_TL 0x3C
+#define I2C_CLR_INTR 0x40
+#define I2C_CLR_RX_UNDER 0x44
+#define I2C_CLR_RX_OVER 0x48
+#define I2C_CLR_TX_OVER 0x4C
+#define I2C_CLR_RD_REQ 0x50
+#define I2C_CLR_TX_ABRT 0x54
+#define I2C_CLR_RX_DONE 0x58
+#define I2C_CLR_ACTIVITY 0x5c
+#define I2C_CLR_STOP_DET 0x60
+#define I2C_CLR_START_DET 0x64
+#define I2C_CLR_GEN_CALL 0x68
+#define I2C_ENABLE 0x6C
+#define I2C_STATUS 0x70
+#define I2C_TXFLR 0x74
+#define I2C_RXFLR 0x78
+#define I2C_TX_ABRT_SOURCE 0x80
+#define I2C_SLV_DATA_NACK_ONLY 0x84
+#define I2C_DMA_CR 0x88
+#define I2C_DMA_TDLR 0x8c
+#define I2C_DMA_RDLR 0x90
+#define I2C_SDA_SETUP 0x94
+#define I2C_ACK_GENERAL_CALL 0x98
+#define I2C_ENABLE_STATUS 0x9C
+#define I2C_COMP_PARAM_1 0xf4
+#define I2C_COMP_VERSION 0xf8
+#define I2C_COMP_TYPE 0xfc
+
+#define I2C_RAW_INTR_STAT_RX_UNDER 0x1
+#define I2C_RAW_INTR_STAT_RX_OVER 0x2
+#define I2C_RAW_INTR_STAT_RX_FULL 0x4
+#define I2C_RAW_INTR_STAT_TX_OVER 0x8
+#define I2C_RAW_INTR_STAT_TX_EMPTY 0x10
+
+ /* Default parameters */
+
+#define I2C_CON_ME (0x1 << 0)
+#define I2C_CON_MS_SS (0x1 << 1)
+#define I2C_CON_MS_FS (0x2 << 1)
+#define I2C_CON_MS_HS (0x3 << 1)
+#define I2C_CON_SLAVE_ADR_7BIT (0x0 << 3)
+#define I2C_CON_SLAVE_ADR_10BIT (0x1 << 3)
+#define I2C_CON_MASTER_ADR_7BIT (0x0 << 4)
+#define I2C_CON_MASTER_ADR_10BIT (0x1 << 4)
+#define I2C_CON_RESTART_EN (0x1 << 5)
+#define I2C_CON_SLAVE_DISABLE (0x1 << 6)
+
+/* 0110 0011 0x63 */
+#define I2C_CON_DEFAULT_MASTER (I2C_CON_ME | I2C_CON_MS_FS /*I2C_CON_MS_SS*/ /* | I2C_CON_RESTART_EN*/ | \
+ I2C_CON_SLAVE_ADR_7BIT | I2C_CON_SLAVE_DISABLE)
+#define I2C_CTR_DEFAULT (I2C_CON_ME | I2C_CON_MASTER_ADR_7BIT | \
+ I2C_CON_SLAVE_DISABLE)
+
+#define I2C_IRQ_NONE_MASK 0x0
+#define I2C_IRQ_ALL_MASK 0x8ff
+
+#define I2C_TAR_STARTBYTE (0x1 << 10)
+#define I2C_TAR_SPECIAL_STARTBYTE (0x1 << 11)
+#define I2C_TAR_ADR_7BIT (0x0 << 12)
+#define I2C_TAR_ADR_10BIT (0x1 << 12)
+#define I2C_TAR_ADR_MASK 0x3ff /* bit [9: 0] */
+
+#define I2C_SLAVE_DISABLE_DEFAULT 0
+#define I2C_RESTART_EN_DEFAULT 1
+#define I2C_10BITADDR_MASTER_DEFAULT 0
+#define I2C_10BITADDR_SLAVE_DEFAULT 1
+#define I2C_MAX_SPEED_MODE_DEFAULT 3
+#define I2C_MASTER_MODE_DEFAULT 1
+
+#define I2C_STANDARD_SPEED_MASK (0x01 << 1)
+#define I2C_FAST_SPEED_MASK (0x02 << 1)
+#define I2C_HIGH_SPEED_MASK (0x03 << 1)
+
+#define I2C_DEFAULT_TAR_ADDR_DEFAULT 0x055
+#define I2C_DEFAULT_SLAVE_ADDR_DEFAULT 0x055
+#define I2C_COMP_VERSION_DEFAULT 0x3131352A
+
+#define I2C_HS_MASTER_CODE_DEFAULT 1
+#define I2C_SS_SCL_HIGH_COUNT_DEFAULT 0x0190
+#define I2C_SS_SCL_LOW_COUNT_DEFAULT 0x01d6
+#define I2C_FS_SCL_HIGH_COUNT_DEFAULT 0x003c
+#define I2C_FS_SCL_LOW_COUNT_DEFAULT 0x0082
+#define I2C_HS_SCL_HIGH_COUNT_DEFAULT 0x006
+#define I2C_HS_SCL_LOW_COUNT_DEFAULT 0x0010
+#define I2C_RX_TL_DEFAULT 0
+#define I2C_TX_TL_DEFAULT 0
+#define I2C_DEFAULT_SDA_SETUP_DEFAULT 0x64
+#define I2C_DEFAULT_ACK_GENERAL_CALL_DEFAULT 1
+#define I2C_DYNAMI2C_TAR_UPDATE_DEFAULT 1
+#define I2C_RX_BUFFER_DEPTH_DEFAULT 8
+#define I2C_TX_BUFFER_DEPTH_DEFAULT 8
+#define I2C_ADD_ENCODED_PARAMS_DEFAULT 1
+#define I2C_HAS_DMA_DEFAULT 0
+#define I2C_INTR_IO_DEFAULT 0
+#define I2C_HC_COUNT_VALUES_DEFAULT 0
+#define APB_DATA_WIDTH_DEFAULT 0
+#define I2C_SLV_DATA_NACK_ONLY_DEFAULT 0
+#define I2C_USE_COUNTS_DEFAULT 0
+#define I2C_CLK_TYPE_DEFAULT 1
+#define I2C_CLOCK_PERIOD_DEFAULT 10
+
+ /* Raw Interrupt Status */
+
+#define I2C_IRQ_NONE (0x0)
+#define I2C_IRQ_RX_UNDER (0x01 << 0)
+#define I2C_IRQ_RX_OVER (0x01 << 1)
+#define I2C_IRQ_RX_FULL (0x01 << 2)
+#define I2C_IRQ_TX_OVER (0x01 << 3)
+#define I2C_IRQ_TX_EMPTY (0x01 << 4)
+#define I2C_IRQ_RD_REQ (0x01 << 5)
+#define I2C_IRQ_TX_ABRT (0x01 << 6)
+#define I2C_IRQ_RX_DONE (0x01 << 7)
+#define I2C_IRQ_ACTIVITY (0x01 << 8)
+#define I2C_IRQ_STOP_DET (0x01 << 9)
+#define I2C_IRQ_START_DET (0x01 << 10)
+#define I2C_IRQ_GEN_CALL (0x01 << 11)
+#define I2C_IRQ_ALL 0xFFF
+
+ /* Default IRQ Mask Bit Setting */
+
+#define I2C_IRQ_DEFAULT_MASK (I2C_IRQ_RX_FULL | I2C_IRQ_TX_EMPTY | \
+ I2C_IRQ_TX_ABRT | I2C_IRQ_STOP_DET | \
+ I2C_IRQ_START_DET)
+
+ /* Data command stop bit */
+
+#define I2C_DATA_CMD_WR_STOP_BIT (0x02 << 8) /* bit 8=0:W, bit 9=1: stop */
+#define I2C_DATA_CMD_RD_STOP_BIT (0x03 << 8) /* bit 8=1:R, bit 9=1: stop */
+#define I2C_DATA_CMD_DAT_MASK 0xff /* bit [7:0] , TX and RX data */
+#define I2C_DATA_CMD_WR (0x00 << 8)
+#define I2C_DATA_CMD_RD (0x01 << 8)
+#define I2C_DATA_CMD_STOP (0x01 << 9)
+#define I2C_DATA_CMD_RESTART (0X01 << 10)
+
+ /* I2C TX Abort Source*/
+
+#define I2C_ABRT_7B_ADDR_NOACK 0x001
+#define I2C_ABRT_10_ADDR1_NOACK 0x002
+#define I2C_ABRT_10_ADDR2_NOACK 0x004
+#define I2C_ABRT_TXDATA_NOACK 0x008
+#define I2C_ABRT_GCALL_NOACK 0x010
+#define I2C_ABRT_GCALL_READ 0x020
+#define I2C_ABRT_HS_ACKDET 0x040
+#define I2C_ABRT_SBYTE_ACKDET 0x080
+#define I2C_ABRT_HS_NORSTRT 0x100
+#define I2C_ABRT_SBYTE_NORSTRT 0x200
+#define I2C_ABRT_10B_RD_NORSTRT 0x400
+#define I2C_ABRT_MASTER_DIS 0x800
+#define I2C_ABRT_ARB_LOST 0x1000
+#define I2C_ABRT_SLVFLUSH_TXFIFO 0x2000
+#define I2C_ABRT_SLV_ARBLOST 0x5000
+#define I2C_ABRT_SLVRD_INTX 0x8000
+
+ /* Minimum High and Low period in nanosecends */
+
+#define SS_MIN_SCL_HIGH 4000
+#define SS_MIN_SCL_LOW 4700
+#define FS_MIN_SCL_HIGH 600
+#define FS_MIN_SCL_LOW 1300
+#define HS_MIN_SCL_HIGH_100PF 60
+#define HS_MIN_SCL_LOW_100PF 120
+
+ /* I2C_STATUS (RO) */
+
+#define I2C_STATUS_ACTIVITY (0x1 << 0) /* I2C ctrl is enabled */
+#define I2C_STATUS_TFNF (0x1 << 1) /* TX FIFO is not full */
+#define I2C_STATUS_TFE (0x1 << 2) /* TX FIFO is empty */
+#define I2C_STATUS_RFNE (0x1 << 3) /* RX FIFO is not empty */
+#define I2C_STATUS_RFF (0x1 << 4) /* RX FIFO is full */
+#define I2C_STATUS_MST_ACTIVITY (0x1 << 5) /* Master is not idle */
+#define I2C_STATUS_SLV_ACTIVITY (0x1 << 6) /* Slave is not idle */
+
+ /* Interrupts status */
+
+#define I2C_INTR_RX_UNDER (0x1 << 0)
+#define I2C_INTR_RX_OVER (0x1 << 1)
+#define I2C_INTR_RX_FULL (0x1 << 2)
+#define I2C_INTR_TX_OVER (0x1 << 3)
+#define I2C_INTR_TX_EMPTY (0x1 << 4)
+#define I2C_INTR_RD_REQ (0x1 << 5)
+#define I2C_INTR_TX_ABRT (0x1 << 6)
+#define I2C_INTR_RX_DONE (0x1 << 7)
+#define I2C_INTR_ACTIVITY (0x1 << 8)
+#define I2C_INTR_STOP_DET (0x1 << 9)
+#define I2C_INTR_START_DET (0x1 << 10)
+#define I2C_INTR_GEN_CALL (0x1 << 11)
+
+#define I2C_TX_BUFFER_DEPTH_MASK 0xFF0000 /* bit [23: 16] */
+#define I2C_RX_BUFFER_DEPTH_MASK 0x00FF00 /* bit [15: 8] */
+
+#define I2C_INTR_MAX_BITS 12
+
+#define I2C_ENABLE_CONTROLLER 0x01
+#define I2C_DISABLE_CONTROLLER 0x00
+
+#define I2C_DATA_CMD_READ (0x01 << 8)
+#define I2C_DATA_CMD_WRITE (0x00 << 8)
+
+#define I2C_TAR_DEFAULT_ADDR 0x55
+#define FT2000_I2C_CLK (48000000) /* I2C clock */
+/**
+ * @name: FI2c_WriteReg
+ * @msg: write i2c register
+ * @param {u32} BaseAddress base addr of i2c
+ * @param {u32} RegOffset addr offset of i2c register
+ * @param {u32} RegisterValue val to be write into register
+ * @return {void}
+ */
+#define FI2C_WriteReg(BaseAddress, RegOffset, RegisterValue) Ft_out32(BaseAddress + (u32)RegOffset, (u32)RegisterValue)
+
+/**
+ * @name: FI2c_ReadReg
+ * @msg: read i2c register
+ * @param {u32} BaseAddress base addr of i2c
+ * @param {u32} RegOffset addr offset of i2c register
+ * @return {u32} val read from register
+ */
+#define FI2C_ReadReg(BaseAddress, RegOffset) Ft_in32(BaseAddress + (u32)RegOffset)
+
+ /*
+* the following macros convert from BCD to binary and back.
+* Be careful that the arguments are chars, only char width returned.
+*/
+
+#define BCD_TO_BIN(bcd) ((((((bcd)&0xf0) >> 4) * 10) + ((bcd)&0xf)) & 0xff)
+#define BIN_TO_BCD(bin) (((((bin) / 10) << 4) + ((bin) % 10)) & 0xff)
+
+#define FI2C_GET_BASE_ADDR(pDev) ((pDev)->Config.BaseAddress)
+#define FI2C_ENABLE_I2C_BUS(pDev) (FI2C_WriteReg(FI2C_GET_BASE_ADDR(pDev), I2C_ENABLE, I2C_ENABLE_CONTROLLER))
+#define FI2C_DISABLE_I2C_BUS(pDev) (FI2C_WriteReg(FI2C_GET_BASE_ADDR(pDev), I2C_ENABLE, I2C_DISABLE_CONTROLLER))
+#define FI2C_IS_I2C_BUS_ENABLED(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_ENABLE))
+
+#define FI2C_GET_STATUS(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_STATUS))
+#define FI2C_CHECK_STATUS(pDev, stMask) (FI2C_GET_STATUS(pDev) & (stMask))
+#define FI2C_CLR_ALL_IRQ_STATUS(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_CLR_INTR))
+#define FI2C_GET_IRQ_STATUS(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_INTR_STAT))
+#define FI2C_GET_IRQ_MASK(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_INTR_MASK))
+#define FI2C_SET_IRQ_MASK(pDev, mask) (FI2C_WriteReg(FI2C_GET_BASE_ADDR(pDev), I2C_INTR_MASK, (mask)))
+
+#define FI2C_GET_TX_TL(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_TX_TL))
+#define FI2C_GET_RX_TL(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_RX_TL))
+#define FI2C_SET_TX_TL(pDev, TxThres) (FI2C_WriteReg(FI2C_GET_BASE_ADDR(pDev), I2C_TX_TL, (TxThres)))
+#define FI2C_SET_RX_TL(pDev, RxThres) (FI2C_WriteReg(FI2C_GET_BASE_ADDR(pDev), I2C_RX_TL, (RxThres)))
+
+#define FI2C_GET_TXFLR(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_TXFLR))
+#define FI2C_GET_RXFLR(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_RXFLR))
+
+#define FI2C_CLR_IRQ_RX_OVER(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_CLR_RX_OVER))
+#define FI2C_CLR_IRQ_TX_OVER(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_CLR_TX_OVER))
+
+#define FI2C_GET_COMP_PARAM_1(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_COMP_PARAM_1))
+#define FI2C_GET_TX_BUFFER_DEPTH(pDev) ((I2C_TX_BUFFER_DEPTH_MASK & FI2C_GET_COMP_PARAM_1(pDev)) >> 16)
+#define FI2C_GET_RX_BUFFER_DEPTH(pDev) ((I2C_RX_BUFFER_DEPTH_MASK & FI2C_GET_COMP_PARAM_1(pDev)) >> 8)
+
+#define FI2C_SEND_TX_STOP_CMD(pDev) (FI2C_WriteReg(FI2C_GET_BASE_ADDR(pDev), I2C_DATA_CMD, I2C_DATA_CMD_STOP))
+#define FI2C_SET_TX_DATA(pDev, data) (FI2C_WriteReg(FI2C_GET_BASE_ADDR(pDev), I2C_DATA_CMD, ((u32)(data)&I2C_DATA_CMD_DAT_MASK)))
+#define FI2C_GET_RX_DATA(pDev) (u8)(I2C_DATA_CMD_DAT_MASK & (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_DATA_CMD)))
+#define FI2C_SEND_RX_NEXT_CMD(pDev) (FI2C_WriteReg(FI2C_GET_BASE_ADDR(pDev), I2C_DATA_CMD, I2C_DATA_CMD_STOP | I2C_DATA_CMD_RESTART | I2C_DATA_CMD_RD))
+#define FI2C_SEND_RX_STOP_CMD(pDev) (FI2C_WriteReg(FI2C_GET_BASE_ADDR(pDev), I2C_DATA_CMD, I2C_DATA_CMD_STOP | I2C_DATA_CMD_RD))
+
+ void FI2C_resetReg(u32 BaseAddr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_irq.c b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_irq.c
new file mode 100644
index 0000000000..85b39edf1b
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_irq.c
@@ -0,0 +1,182 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-20 15:35:44
+ * @LastEditTime: 2021-05-25 16:44:45
+ * @Description:  This files is for
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_i2c.h"
+
+void FI2C_irqHandler(void *pArgs)
+{
+ FI2C_t *pDev;
+ u32 RegVal;
+ FI2C_IrqType_t IrqType = I2C_IRQ_TYPE_NONE;
+
+ Ft_assertNoneReturn(NULL != pArgs);
+ pDev = (FI2C_t *)pArgs;
+
+ RegVal = FI2C_GET_IRQ_STATUS(pDev);
+ if (I2C_IRQ_RX_FULL & RegVal)
+ {
+ IrqType = I2C_IRQ_TYPE_RX_COMPLETE;
+ }
+ else if (I2C_IRQ_TX_EMPTY & RegVal)
+ {
+ IrqType = I2C_IRQ_TYPE_TX_COMPLETE;
+ }
+
+ if ((NULL != pDev->pIrqCallBack) && (I2C_IRQ_TYPE_NONE != IrqType))
+ {
+ pDev->pIrqCallBack(IrqType, pDev, NULL);
+ }
+
+ if (I2C_IRQ_TYPE_RX_COMPLETE == IrqType)
+ {
+ FI2C_setIrq(pDev, I2C_IRQ_RX_FULL, FALSE);
+ }
+ else if (I2C_IRQ_TYPE_TX_COMPLETE == IrqType)
+ {
+ FI2C_setIrq(pDev, I2C_IRQ_TX_EMPTY, FALSE);
+ }
+
+ FI2C_CLR_ALL_IRQ_STATUS(pDev);
+ return;
+}
+
+void FI2C_irqHandler4Fifo(void *pArgs)
+{
+ FI2C_t *pDev;
+ u32 RegVal;
+ u32 BytesToRx;
+ FI2C_IrqType_t IrqType = I2C_IRQ_TYPE_NONE;
+
+ Ft_assertNoneReturn(NULL != pArgs);
+ pDev = (FI2C_t *)pArgs;
+
+ /* check if i2c controller is enabled */
+ if (!FI2C_IS_I2C_BUS_ENABLED(pDev))
+ {
+ pDev->LastIrqErr = ERR_I2C_BUS_NOT_ENABLED;
+ return;
+ }
+
+ /* check there is no interrupt */
+ if (!FI2C_checkIfIntr(pDev))
+ {
+ pDev->LastIrqErr = ERR_I2C_INVALID_PARAM;
+ return;
+ }
+
+ /* read interrupt status */
+ RegVal = FI2C_GET_IRQ_STATUS(pDev);
+ if (I2C_IRQ_RX_FULL & RegVal)
+ {
+ IrqType = I2C_IRQ_TYPE_RX_COMPLETE;
+ BytesToRx = FI2C_GET_RXFLR(pDev);
+
+ while ((pDev->RxBuf.CurIndex < pDev->RxBuf.DataLength) &&
+ (0 < BytesToRx))
+ {
+ /* read one byte */
+ pDev->RxBuf.BytePtr[pDev->RxBuf.CurIndex] = FI2C_GET_RX_DATA(pDev);
+
+ pDev->RxBuf.CurIndex++;
+ BytesToRx--;
+ pDev->DelayHandle(10);
+
+ /* read next byte */
+ if (pDev->RxBuf.CurIndex != pDev->RxBuf.DataLength)
+ {
+ FI2C_SEND_RX_NEXT_CMD(pDev);
+ }
+ else
+ {
+ FI2C_SEND_RX_STOP_CMD(pDev);
+ pDev->DelayHandle(10);
+ FI2C_setIrq(pDev, I2C_IRQ_RX_FULL, FALSE);
+ }
+ }
+ }
+ else if (I2C_IRQ_TX_EMPTY & RegVal)
+ {
+ IrqType = I2C_IRQ_TYPE_TX_COMPLETE;
+
+ if (pDev->TxBuf.CurIndex == pDev->TxBuf.DataLength)
+ {
+ FI2C_SEND_TX_STOP_CMD(pDev);
+ pDev->DelayHandle(10);
+ FI2C_setIrq(pDev, I2C_IRQ_TX_EMPTY, FALSE);
+ }
+ else
+ {
+ FI2C_SET_TX_DATA(pDev, pDev->TxBuf.BytePtr[pDev->TxBuf.CurIndex]);
+ pDev->TxBuf.CurIndex++;
+ }
+ }
+
+ if ((NULL != pDev->pIrqCallBack) && (I2C_IRQ_TYPE_NONE != IrqType))
+ {
+ pDev->pIrqCallBack(IrqType, pDev, NULL);
+ }
+
+ pDev->LastIrqErr = ERR_I2C_OK;
+ return;
+}
+
+u32 FI2C_getIrqMask(FT_IN FI2C_t *pDev)
+{
+ u32 RegVal;
+ Ft_assertNoneReturn(NULL != pDev);
+
+ RegVal = FI2C_GET_IRQ_MASK(pDev);
+ return RegVal;
+}
+
+void FI2C_setIrqMask(FT_IN FI2C_t *pDev, FT_IN u32 mask)
+{
+ u32 RegVal;
+ Ft_assertNoneReturn(NULL != pDev);
+
+ RegVal = mask & I2C_IRQ_ALL_MASK;
+ FI2C_SET_IRQ_MASK(pDev, RegVal);
+ return;
+}
+
+void FI2C_setIrq(FT_IN FI2C_t *pDev, FT_IN u32 maskBit, FT_IN bool_t enable)
+{
+ Ft_assertNoneReturn(0x0 != maskBit);
+
+ if (TRUE == enable)
+ {
+ FI2C_setIrqMask(pDev, FI2C_getIrqMask(pDev) | maskBit);
+ }
+ else
+ {
+ FI2C_setIrqMask(pDev, FI2C_getIrqMask(pDev) & (~maskBit));
+ }
+ return;
+}
+
+bool_t FI2C_checkIfIntr(FT_IN FI2C_t *pDev)
+{
+ u32 RegVal;
+ Ft_assertNoneReturn(NULL != pDev);
+
+ RegVal = FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_RAW_INTR_STAT);
+ if (0 == (RegVal & (~I2C_IRQ_ACTIVITY)))
+ {
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
diff --git a/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_selftest.c b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_selftest.c
new file mode 100644
index 0000000000..4a43df0ce4
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_selftest.c
@@ -0,0 +1,20 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-04-07 13:27:24
+ * @Description:  This files is for i2c test cases
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include <time.h>
+#include <string.h>
+#include "ft_i2c_hw.h"
+#include "ft_i2c.h"
+#include "ft_status.h"
+#include "ft_printf.h"
diff --git a/bsp/ft2004/libraries/bsp/ft_qspi/ft_qspi.c b/bsp/ft2004/libraries/bsp/ft_qspi/ft_qspi.c
new file mode 100644
index 0000000000..3476e20333
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_qspi/ft_qspi.c
@@ -0,0 +1,585 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-05 22:15:53
+ * @LastEditTime: 2021-05-25 16:45:36
+ * @Description:  Description of file
+ * @Modify History:
+ * * * Ver   Who        Date         Changes
+ * * ----- ------     --------    --------------------------------------
+ * * 1.00 hh 2021.04-06 init
+ */
+
+#include "ft_qspi.h"
+#include "qspi_hw.h"
+#include "ft_io.h"
+#include "ft_assert.h"
+#include "ft_types.h"
+#include "string.h"
+
+#include "ft_debug.h"
+
+#define FTQSPI_DEBUG_TAG "FTQSPI"
+
+#define FTQSPI_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FTQSPI_DEBUG_TAG, format, ##__VA_ARGS__)
+#define FTQSPI_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(FTQSPI_DEBUG_TAG, format, ##__VA_ARGS__)
+#define FTQSPI_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FTQSPI_DEBUG_TAG, format, ##__VA_ARGS__)
+
+ft_error_t FQSpi_CfgInitialize(FQSpi_t *pQspi, FQSpi_Config_t *pConfig)
+{
+ Ft_assertNonvoid(pQspi != NULL);
+ Ft_assertNonvoid(pConfig != NULL);
+
+ pQspi->config = *pConfig;
+ pQspi->isReady = FT_COMPONENT_IS_READLY;
+
+ FQSpi_Reset(pQspi);
+
+ return FQSPI_SUCCESS;
+}
+
+/**
+ * @name: FQSpi_MemcpyToReg
+ * @msg: Memory copy To Register
+ * @in param {FQSpi_t} *pQspi
+ * @in param {u8} *buf
+ * @in param {u32} length
+ * @return {ft_error_t}
+ */
+static ft_error_t FQSpi_MemcpyToReg(FQSpi_t *pQspi, FT_IN u8 *buf, u32 length)
+{
+ u32 val = 0;
+ FQSpi_Config_t *pConfig = NULL;
+ Ft_assertNonvoid(pQspi != NULL);
+ Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
+ pConfig = &pQspi->config;
+ if (!buf || (length > 4))
+ {
+ return FQSPI_FAILURE;
+ }
+
+ if (1 == length)
+ {
+ val = buf[0];
+ }
+ else if (2 == length)
+ {
+ val = buf[1];
+ val = (val << 8) + buf[0];
+ }
+ else if (3 == length)
+ {
+ val = buf[2];
+ val = (val << 8) + buf[1];
+ val = (val << 8) + buf[0];
+ }
+ else if (4 == length)
+ {
+ val = buf[3];
+ val = (val << 8) + buf[2];
+ val = (val << 8) + buf[1];
+ val = (val << 8) + buf[0];
+ }
+
+ Ft_out32(pConfig->baseAddress + FT_REG_QSPI_LD_PORT_OFFSET, val);
+ return FQSPI_SUCCESS;
+}
+
+/**
+ * @name: FQSpi_MemcpyFromReg
+ * @msg: Memory copy from Register
+ * @in param {FT_INFQSpi_t} *pQspi
+ * @out param {u8} *buf
+ * @in param {u32} length
+ * @return {*}
+ */
+static ft_error_t FQSpi_MemcpyFromReg(FQSpi_t *pQspi, u8 *buf, u32 length)
+{
+ s32 i;
+ u32 val = 0;
+ FQSpi_Config_t *pConfig = NULL;
+ Ft_assertNonvoid(pQspi != NULL);
+ Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
+ pConfig = &pQspi->config;
+
+ for (i = 0; i < length; i++)
+ {
+ /* code */
+ if (0 == i % 4)
+ {
+ val = Ft_in32(pConfig->baseAddress + FT_REG_QSPI_LD_PORT_OFFSET);
+ }
+ buf[i] = (u8)(val >> (i % 4) * 8) & 0xff;
+ }
+
+ return FQSPI_SUCCESS;
+}
+
+/**
+ * @name: FQSpi_FlashRead
+ * @msg: Reads bytes data from flash addr to buf
+ * @in param pQspi:
+ * @in param cmd: Read the instruction byte of the command
+ * @in param addr: Read the data start character
+ * @out param rxBuf: Read buffer
+ * @in param length: need read length
+ * @return {*}
+ */
+ft_error_t FQSpi_FlashRead(FQSpi_t *pQspi,
+ FT_IN u8 cmd,
+ FT_IN u32 addr,
+ FT_OUT u8 *rxBuf,
+ u32 length)
+{
+ FQSpi_Config_t *pConfig = NULL;
+ FQSpi_RdCfgReg_t rdCfgReg;
+ Ft_assertNonvoid(pQspi != NULL);
+ Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
+ pConfig = &pQspi->config;
+
+ if ((NULL == rxBuf) || (0 == length))
+ {
+ return FQSPI_FAILURE;
+ }
+
+ rdCfgReg.data = 0;
+
+ rdCfgReg.val.rdCmd = cmd;
+ rdCfgReg.val.dBuffer = 1;
+ rdCfgReg.val.rdAddrSel = pConfig->addrMode;
+ rdCfgReg.val.rdSckSel = pConfig->clkDiv;
+ rdCfgReg.val.rdTransfer = pConfig->transMode;
+ Ft_out32(pConfig->baseAddress + FT_REG_QSPI_RD_CFG_OFFSET, rdCfgReg.data);
+
+ memcpy(rxBuf, (char *)(addr), length);
+
+ return FQSPI_SUCCESS;
+}
+
+/**
+ * @name: FQSpi_FlashWrite
+ * @msg: Writes one page into flash,changing bits from 1 to 0
+ * @in param pQspi:
+ * @in param cmd: write the instruction byte of the command
+ * @in param addr: write the data start character
+ * @in param txBuf: write buffer
+ * @in param length: need write length
+ * @return {*}
+ */
+ft_error_t FQSpi_FlashWrite(FQSpi_t *pQspi,
+ FT_IN u8 cmd,
+ FT_IN u32 addr,
+ FT_IN u8 *txBuf,
+ u32 length)
+{
+
+ FQSpi_Config_t *pConfig = NULL;
+ FQSpi_WrCfgReg_t wrCfgReg;
+ u32 index = 0;
+ u32 val = 0;
+ u32 *pu32Buf = NULL;
+ Ft_assertNonvoid(pQspi != NULL);
+ Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
+ pConfig = &pQspi->config;
+
+ if ((NULL == txBuf) || (0 == length))
+ {
+ return FQSPI_FAILURE;
+ }
+
+ pu32Buf = (u32 *)txBuf;
+
+ wrCfgReg.data = 0;
+ wrCfgReg.val.wrCmd = cmd;
+ wrCfgReg.val.wrWait = 1;
+ wrCfgReg.val.wrSckSel = pConfig->clkDiv;
+ wrCfgReg.val.wrAddrsel = pConfig->addrMode;
+ wrCfgReg.val.wrTransfer = pConfig->transMode;
+ wrCfgReg.val.wrMode = 1;
+
+ Ft_out32(pConfig->baseAddress + FT_REG_QSPI_WR_CFG_OFFSET, wrCfgReg.data);
+
+ while (length)
+ {
+ if (length >= 4)
+ {
+ Ft_out32(addr + index, pu32Buf[index / 4]);
+ length -= 4;
+ index += 4;
+ }
+ else
+ {
+ if (1 == length)
+ {
+ val = txBuf[index] | 0xFFFFFF00;
+ }
+ else if (2 == length)
+ {
+ val = txBuf[index] | (txBuf[index + 1] << 8) | 0xFFFF0000;
+ }
+ else
+ {
+ val = txBuf[index] | (txBuf[index + 1] << 8) | (txBuf[index + 2] << 8) | 0xFF000000;
+ }
+
+ Ft_out32(addr + index, val);
+ length = 0;
+ }
+ }
+
+ Ft_out32(pConfig->baseAddress + FT_REG_QSPI_FLUSH_OFFSET, 1);
+ return FQSPI_SUCCESS;
+}
+
+/**
+ * @name: FQSpi_FlashRegSet
+ * @msg: Set registers of flash
+ * @in param cmd: Command byte
+ * @in param writebuf: write buffer
+ * @in param length: need write length
+ * @return {*}
+ */
+ft_error_t FQSpi_FlashRegSet(FQSpi_t *pQspi,
+ FT_IN u8 cmd,
+ FT_IN u8 *writebuf,
+ u32 length)
+{
+ FQSpi_Config_t *pConfig = NULL;
+ FQSpi_CmdPortReg_t cmdPortReg;
+ Ft_assertNonvoid(pQspi != NULL);
+ Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
+ pConfig = &pQspi->config;
+
+ cmdPortReg.data = 0;
+ cmdPortReg.val.cmd = cmd;
+ cmdPortReg.val.wait = 1;
+ cmdPortReg.val.sckSel = pConfig->clkDiv;
+ cmdPortReg.val.transfer = pConfig->transMode;
+ cmdPortReg.val.cs = pConfig->channel;
+
+ if (length == 0)
+ {
+ Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data);
+ Ft_out32(pConfig->baseAddress + FT_REG_QSPI_LD_PORT_OFFSET, 1);
+ }
+ else
+ {
+ cmdPortReg.val.dataTransfer = 1;
+ cmdPortReg.val.rwMum = length;
+ Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data);
+ FQSpi_MemcpyToReg(pQspi, writebuf, length);
+ }
+
+ return FQSPI_SUCCESS;
+}
+
+ft_error_t FQSpi_FlashRegSetWithaddr(FQSpi_t *pQspi,
+ FT_IN u8 cmd,
+ FT_IN u32 addr,
+ FT_IN u8 *writebuf,
+ u32 length)
+{
+ FQSpi_Config_t *pConfig = NULL;
+ FQSpi_CmdPortReg_t cmdPortReg;
+ Ft_assertNonvoid(pQspi != NULL);
+ Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
+ pConfig = &pQspi->config;
+
+ cmdPortReg.data = 0;
+ cmdPortReg.val.cmd = cmd;
+ cmdPortReg.val.wait = 1;
+ cmdPortReg.val.sckSel = pConfig->clkDiv;
+ cmdPortReg.val.transfer = pConfig->transMode;
+ cmdPortReg.val.cs = pConfig->channel;
+ cmdPortReg.val.cmdAddr = 1;
+ cmdPortReg.val.addrSel = pConfig->addrMode;
+
+ Ft_out32(pConfig->baseAddress + FT_REG_QSPI_ADDR_PORT_OFFSET, addr);
+
+ if (length == 0)
+ {
+ Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data);
+ Ft_out32(pConfig->baseAddress + FT_REG_QSPI_LD_PORT_OFFSET, 0);
+ }
+ else
+ {
+ cmdPortReg.val.dataTransfer = 1;
+ cmdPortReg.val.rwMum = length;
+ Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data);
+ FQSpi_MemcpyToReg(pQspi, writebuf, length);
+ }
+
+ return FQSPI_SUCCESS;
+}
+
+ft_error_t FQSpi_FlashRegGet(FQSpi_t *pQspi,
+ FT_IN u8 cmd,
+ u8 *readbuf,
+ u32 length)
+{
+ FQSpi_Config_t *pConfig = NULL;
+ FQSpi_CmdPortReg_t cmdPortReg;
+ Ft_assertNonvoid(pQspi != NULL);
+ Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
+ pConfig = &pQspi->config;
+
+ cmdPortReg.data = 0;
+ cmdPortReg.val.cmd = cmd;
+ cmdPortReg.val.wait = 1;
+ cmdPortReg.val.sckSel = pConfig->clkDiv;
+ cmdPortReg.val.transfer = pConfig->transMode;
+ cmdPortReg.val.cs = pConfig->channel;
+ cmdPortReg.val.dataTransfer = 1;
+ cmdPortReg.val.pBuffer = 1;
+
+ Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data);
+ FQSpi_MemcpyFromReg(pQspi, readbuf, length);
+ return FQSPI_SUCCESS;
+}
+
+ft_error_t FQSpi_FlashRegGetWithAddr(FQSpi_t *pQspi,
+ FT_IN u8 cmd,
+ FT_IN u32 addr,
+ FT_IN u32 dummyCycle,
+ u8 *readbuf,
+ u32 length)
+{
+ FQSpi_Config_t *pConfig = NULL;
+ FQSpi_CmdPortReg_t cmdPortReg;
+ Ft_assertNonvoid(pQspi != NULL);
+ Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
+ pConfig = &pQspi->config;
+
+ cmdPortReg.data = 0;
+ cmdPortReg.val.cmd = cmd;
+ cmdPortReg.val.wait = 1;
+ cmdPortReg.val.sckSel = pConfig->clkDiv;
+ cmdPortReg.val.transfer = pConfig->transMode;
+ cmdPortReg.val.cs = pConfig->channel;
+ cmdPortReg.val.dataTransfer = 1;
+ cmdPortReg.val.pBuffer = 1;
+ cmdPortReg.val.cmdAddr = 1;
+
+ cmdPortReg.val.addrSel = pConfig->addrMode;
+ cmdPortReg.val.latency = 1;
+ cmdPortReg.val.dummy = dummyCycle - 1;
+
+ Ft_out32(pConfig->baseAddress + FT_REG_QSPI_ADDR_PORT_OFFSET, addr);
+ Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data);
+ FQSpi_MemcpyFromReg(pQspi, readbuf, length);
+ return FQSPI_SUCCESS;
+}
+
+ft_error_t FQSpi_Write(FQSpi_t *pQspi, struct FQSpi_DataPack *pDataPack)
+{
+ FQSpi_Config_t *pConfig = NULL;
+ FQSpi_WrCfgReg_t wrCfgReg;
+ u32 length;
+ u32 index = 0;
+ u32 val = 0;
+ const u32 *pu32Buf = NULL;
+ Ft_assertNonvoid(pQspi != NULL);
+ Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
+ pConfig = &pQspi->config;
+
+ if ((FQSPI_DATA_ADDRESS_3BYTE_MASK | FQSPI_DATA_ADDRESS_4BYTE_MASK) == (pDataPack->flags & (FQSPI_DATA_ADDRESS_3BYTE_MASK | FQSPI_DATA_ADDRESS_4BYTE_MASK)))
+ {
+ FTQSPI_DEBUG_E(" Two addresses are not allowed at the same time ");
+ return FQSPI_FAILURE;
+ }
+
+ if (0 == (pDataPack->flags & (FQSPI_DATA_ADDRESS_3BYTE_MASK | FQSPI_DATA_ADDRESS_4BYTE_MASK)))
+ {
+ FTQSPI_DEBUG_E(" There is no address configuration ");
+ return FQSPI_FAILURE;
+ }
+
+ if (NULL == pDataPack->txBuf)
+ {
+ FTQSPI_DEBUG_E("pDataPack->txBuf is null");
+ return FQSPI_FAILURE;
+ }
+
+ pu32Buf = (const u32 *)pDataPack->txBuf;
+ wrCfgReg.data = 0;
+
+ if (FQSPI_DATA_ADDRESS_3BYTE_MASK == (pDataPack->flags & FQSPI_DATA_ADDRESS_3BYTE_MASK))
+ {
+ wrCfgReg.val.wrAddrsel = FT_QSPI_ADDR_SEL_3;
+ }
+ else if (FQSPI_DATA_ADDRESS_4BYTE_MASK == (pDataPack->flags & FQSPI_DATA_ADDRESS_4BYTE_MASK))
+ {
+ wrCfgReg.val.wrAddrsel = FT_QSPI_ADDR_SEL_4;
+ }
+
+ wrCfgReg.val.wrCmd = pDataPack->cmd;
+ wrCfgReg.val.wrWait = 1;
+ wrCfgReg.val.wrSckSel = pConfig->clkDiv;
+ wrCfgReg.val.wrTransfer = pConfig->transMode;
+ wrCfgReg.val.wrMode = 1;
+ length = pDataPack->length;
+
+ Ft_out32(pConfig->baseAddress + FT_REG_QSPI_WR_CFG_OFFSET, wrCfgReg.data);
+
+ while (length)
+ {
+ if (length >= 4)
+ {
+ Ft_out32(pDataPack->addr + index, pu32Buf[index / 4]);
+ length -= 4;
+ index += 4;
+ }
+ else
+ {
+ if (1 == length)
+ {
+ val = pDataPack->txBuf[index] | 0xFFFFFF00;
+ }
+ else if (2 == length)
+ {
+ val = pDataPack->txBuf[index] | (pDataPack->txBuf[index + 1] << 8) | 0xFFFF0000;
+ }
+ else
+ {
+ val = pDataPack->txBuf[index] | (pDataPack->txBuf[index + 1] << 8) | (pDataPack->txBuf[index + 2] << 8) | 0xFF000000;
+ }
+ FTQSPI_DEBUG_I("val is 0x%x", val);
+ Ft_out32(pDataPack->addr + index, val);
+ length = 0;
+ }
+ }
+
+ Ft_out32(pConfig->baseAddress + FT_REG_QSPI_FLUSH_OFFSET, 1);
+ return FQSPI_SUCCESS;
+}
+
+ft_error_t FQSpi_Read(FQSpi_t *pQspi, struct FQSpi_DataPack *pDataPack)
+{
+ FQSpi_Config_t *pConfig = NULL;
+ FQSpi_RdCfgReg_t rdCfgReg;
+ Ft_assertNonvoid(pQspi != NULL);
+ Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
+ pConfig = &pQspi->config;
+
+ if ((FQSPI_DATA_ADDRESS_3BYTE_MASK | FQSPI_DATA_ADDRESS_4BYTE_MASK) == (pDataPack->flags & (FQSPI_DATA_ADDRESS_3BYTE_MASK | FQSPI_DATA_ADDRESS_4BYTE_MASK)))
+ {
+ FTQSPI_DEBUG_E(" Two addresses are not allowed at the same time ");
+ return FQSPI_FAILURE;
+ }
+
+ if (0 == (pDataPack->flags & (FQSPI_DATA_ADDRESS_3BYTE_MASK | FQSPI_DATA_ADDRESS_4BYTE_MASK)))
+ {
+ FTQSPI_DEBUG_E(" There is no address configuration ");
+ return FQSPI_FAILURE;
+ }
+
+ if (NULL == pDataPack->rxBuf)
+ {
+ FTQSPI_DEBUG_E("pDataPack->rxBuf is null");
+ return FQSPI_FAILURE;
+ }
+
+ rdCfgReg.data = 0;
+
+ if (FQSPI_DATA_NEED_DUMMY_MASK == (pDataPack->flags & FQSPI_DATA_NEED_DUMMY_MASK))
+ {
+ rdCfgReg.val.rdLatency = 1;
+ rdCfgReg.val.dummy = pDataPack->dummyCycle - 1;
+ }
+
+ if (FQSPI_DATA_ADDRESS_3BYTE_MASK == (pDataPack->flags & FQSPI_DATA_ADDRESS_3BYTE_MASK))
+ {
+ rdCfgReg.val.rdAddrSel = FT_QSPI_ADDR_SEL_3;
+ }
+ else if (FQSPI_DATA_ADDRESS_4BYTE_MASK == (pDataPack->flags & FQSPI_DATA_ADDRESS_4BYTE_MASK))
+ {
+ rdCfgReg.val.rdAddrSel = FT_QSPI_ADDR_SEL_4;
+ }
+
+ rdCfgReg.val.rdCmd = pDataPack->cmd;
+ rdCfgReg.val.dBuffer = 1;
+ rdCfgReg.val.rdSckSel = pConfig->clkDiv;
+ rdCfgReg.val.rdTransfer = pConfig->transMode;
+
+ Ft_out32(pConfig->baseAddress + FT_REG_QSPI_RD_CFG_OFFSET, rdCfgReg.data);
+
+ memcpy(pDataPack->rxBuf, (char *)(pDataPack->addr), pDataPack->length);
+
+ return FQSPI_SUCCESS;
+}
+
+ft_error_t
+FQSpi_CmdOperation(FQSpi_t *pQspi, struct FQSpi_CmdPack *pCmdPack)
+{
+ FQSpi_Config_t *pConfig = NULL;
+ FQSpi_CmdPortReg_t cmdPortReg;
+ Ft_assertNonvoid(pQspi != NULL);
+ Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
+ pConfig = &pQspi->config;
+ if ((FQSPI_CMD_ADDRESS_3BYTE_MASK | FQSPI_CMD_ADDRESS_4BYTE_MASK) == (pCmdPack->flags & (FQSPI_CMD_ADDRESS_3BYTE_MASK | FQSPI_CMD_ADDRESS_4BYTE_MASK)))
+ {
+ FTQSPI_DEBUG_E(" Two addresses are not allowed at the same time ");
+ return FQSPI_FAILURE;
+ }
+
+ cmdPortReg.data = 0;
+ cmdPortReg.val.cmd = pCmdPack->cmd;
+ cmdPortReg.val.wait = 1;
+ cmdPortReg.val.sckSel = pConfig->clkDiv;
+ cmdPortReg.val.transfer = pConfig->transMode;
+ cmdPortReg.val.cs = pConfig->channel;
+
+ if (FQSPI_CMD_NEED_ADDR_MASK == (pCmdPack->flags & FQSPI_CMD_NEED_ADDR_MASK))
+ {
+ // FTQSPI_DEBUG_I(" send addr is 0x%x ", pCmdPack->addr);
+ cmdPortReg.val.cmdAddr = 1;
+ Ft_out32(pConfig->baseAddress + FT_REG_QSPI_ADDR_PORT_OFFSET, pCmdPack->addr);
+ }
+
+ if (FQSPI_CMD_NEED_DUMMY_MASK == (pCmdPack->flags & FQSPI_CMD_NEED_DUMMY_MASK))
+ {
+ cmdPortReg.val.latency = 1;
+ cmdPortReg.val.dummy = pCmdPack->dummyCycle - 1;
+ }
+
+ if (FQSPI_CMD_ADDRESS_3BYTE_MASK == (pCmdPack->flags & FQSPI_CMD_ADDRESS_3BYTE_MASK))
+ {
+ cmdPortReg.val.addrSel = FT_QSPI_ADDR_SEL_3;
+ }
+ else if (FQSPI_CMD_ADDRESS_4BYTE_MASK == (pCmdPack->flags & FQSPI_CMD_ADDRESS_4BYTE_MASK))
+ {
+ cmdPortReg.val.addrSel = FT_QSPI_ADDR_SEL_4;
+ }
+
+ if (FQSPI_CMD_NEED_SET_MASK == (pCmdPack->flags & (FQSPI_CMD_NEED_SET_MASK)))
+ {
+ cmdPortReg.val.dataTransfer = 1;
+ cmdPortReg.val.rwMum = pCmdPack->length;
+ Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data);
+ FQSpi_MemcpyToReg(pQspi, pCmdPack->txBuf, pCmdPack->length);
+ }
+ else if (FQSPI_CMD_NEED_GET_MASK == (pCmdPack->flags & (FQSPI_CMD_NEED_GET_MASK)))
+ {
+ cmdPortReg.val.dataTransfer = 1;
+ cmdPortReg.val.pBuffer = 1;
+ Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data);
+ FQSpi_MemcpyFromReg(pQspi, pCmdPack->rxBuf, pCmdPack->length);
+ }
+ else
+ {
+ Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data);
+
+ if (FQSPI_CMD_NEED_ADDR_MASK == (pCmdPack->flags & FQSPI_CMD_NEED_ADDR_MASK))
+ {
+ Ft_out32(pConfig->baseAddress + FT_REG_QSPI_LD_PORT_OFFSET, 0);
+ }
+ else
+ {
+ Ft_out32(pConfig->baseAddress + FT_REG_QSPI_LD_PORT_OFFSET, 1);
+ }
+ }
+
+ return FQSPI_SUCCESS;
+}
diff --git a/bsp/ft2004/libraries/bsp/ft_qspi/ft_qspi.h b/bsp/ft2004/libraries/bsp/ft_qspi/ft_qspi.h
new file mode 100644
index 0000000000..61aa626f63
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_qspi/ft_qspi.h
@@ -0,0 +1,184 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-05 21:31:10
+ * @LastEditTime: 2021-04-05 21:31:10
+ * @Description:  Description of file
+ * @Modify History:
+ * * * Ver   Who        Date         Changes
+ * * ----- ------     --------    --------------------------------------
+ * * v1.0 hh 2021-04-05 init
+ */
+
+#ifndef FT_QSPI_H
+#define FT_QSPI_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "ft_types.h"
+#include "ft_error_code.h"
+
+#define FQSPI_SUCCESS FST_SUCCESS /* SUCCESS */
+#define FQSPI_FAILURE FT_MAKE_ERRCODE(errQspi, errBspGeneral, FST_FAILURE) /* Normal */
+#define FQSPI_TIMEOUT FT_MAKE_ERRCODE(errQspi, errBspGeneral, FST_TIMEOUT) /* Timeout */
+#define FQSPI_EILSEQ FT_MAKE_ERRCODE(errQspi, errBspGeneral, FST_EILSEQ) /* Illegal byte sequence. */
+#define FQSPI_INVALID_PARAM FT_MAKE_ERRCODE(errQspi, errBspGeneral, FST_INVALID_PARAM) /* Invalid param. */
+
+/* qspi bsp command instruction operation */
+#define FQSPI_CMD_NEED_ADDR_MASK 0x1U
+#define FQSPI_CMD_NEED_DUMMY_MASK 0x2U
+#define FQSPI_CMD_NEED_GET_MASK 0x4U
+#define FQSPI_CMD_NEED_SET_MASK 0x08U
+#define FQSPI_CMD_ADDRESS_3BYTE_MASK 0x10U
+#define FQSPI_CMD_ADDRESS_4BYTE_MASK 0x20U
+
+/* qspi cmd of transfer operation */
+#define FQSPI_DATA_NEED_DUMMY_MASK 0x1U
+#define FQSPI_DATA_ADDRESS_3BYTE_MASK 0x2U
+#define FQSPI_DATA_ADDRESS_4BYTE_MASK 0x4U
+
+#define FQSPI_FLASH_CMD_WRR 0x01 /* Write status register */
+#define FQSPI_FLASH_CMD_PP 0x02 /* Page program */
+#define FQSPI_FLASH_CMD_READ 0x03 /* Normal read data bytes */
+#define FQSPI_FLASH_CMD_WRDI 0x04 /* Write disable */
+#define FQSPI_FLASH_CMD_RDSR1 0x05 /* Read status register */
+#define FQSPI_FLASH_CMD_WREN 0x06 /* Write enable */
+#define FQSPI_FLASH_CMD_RDSR2 0x07 /* Read status register */
+#define FQSPI_FLASH_CMD_FAST_READ 0x0B /* Fast read data bytes */
+#define FQSPI_FLASH_CMD_4FAST_READ 0x0C /* Fast read data bytes */
+#define FQSPI_FLASH_CMD_4PP 0x12 /* Page program */
+#define FQSPI_FLASH_CMD_4READ 0x13 /* Normal read data bytes */
+#define FQSPI_FLASH_CMD_P4E 0x20 /* Erase 4kb sector */
+#define FQSPI_FLASH_CMD_4P4E 0x21 /* Erase 4kb sector */
+#define FQSPI_FLASH_CMD_QPP 0x32 /* Quad Page program */
+#define FQSPI_FLASH_CMD_4QPP 0x34 /* Quad Page program */
+#define FQSPI_FLASH_CMD_RDCR 0x35 /* Read config register */
+#define FQSPI_FLASH_CMD_BE 0x60 /* Bulk erase */
+#define FQSPI_FLASH_CMD_RDAR 0x65 /* Read Any Register */
+#define FQSPI_FLASH_CMD_QOR 0x6B /* Quad read data bytes */
+#define FQSPI_FLASH_CMD_4QOR 0x6C /* Quad read data bytes */
+#define FQSPI_FLASH_CMD_WRAR 0x71 /* Write Any Register */
+#define FQSPI_FLASH_CMD_RDID 0x9F /* Read JEDEC ID */
+#define FQSPI_FLASH_CMD_4BAM 0xB7 /* Enter 4 Bytes Mode */
+#define FQSPI_FLASH_CMD_4BE 0xC7 /* Bulk erase */
+#define FQSPI_FLASH_CMD_SE 0xD8 /* Sector erase */
+#define FQSPI_FLASH_CMD_4SE 0xDC /* Sector erase */
+#define FQSPI_FLASH_CMD_4BEX 0xE9 /* Exit 4 Bytes Mode */
+#define FQSPI_FLASH_CMD_QIOR 0xEB /* Quad read data bytes */
+#define FQSPI_FLASH_CMD_4QIOR 0xEC /* Quad read data bytes */
+#define FQSPI_FLASH_DISCOVERABLE_PARAMETER 0x5a
+#define FQSPI_CMD_ENABLE_RESET 0x66
+#define FQSPI_CMD_RESET 0x99
+
+ struct FQSpi_DataPack
+ {
+ u32 flags; /* Follow qspi cmd of transfer operation */
+ u32 cmd; /* Command instruction */
+ u32 addr; /* Flash address */
+ u32 dummyCycle; /* dummy Cycle */
+ const u8 *txBuf;
+ u8 *rxBuf; /* Need send or read buffer */
+ u32 length; /* Buffer length */
+ };
+
+ struct FQSpi_CmdPack
+ {
+ u32 flags; /* Follow qspi bsp command instruction operation */
+ u32 cmd; /* Command instruction */
+ u32 addr; /* Command address */
+ u32 dummyCycle; /* dummy Cycle */
+ const u8 *txBuf;
+ u8 *rxBuf; /* Need send or read buffer */
+ u32 length; /* Buffer length */
+ };
+
+ typedef struct
+ {
+ u32 instanceId; /* Id of device */
+ uintptr_t baseAddress; /* Base address of qspi */
+ u32 transMode; /* Transfer mode */
+ u32 capacity; /* Flash capacity */
+ u32 addrMode; /**/
+ u32 clkDiv;
+ u32 qspiDevNum; /*Qspi device number */
+ u32 channel; /* Cs number */
+ u32 bitWidth; /* Transfer unit width */
+ } FQSpi_Config_t;
+
+ typedef struct
+ {
+ FQSpi_Config_t config;
+ u32 isReady; /**< Device is initialized and ready */
+
+ } FQSpi_t;
+
+ /**
+ * @name: FQSpi_LookupConfig
+ * @msg: FQSpi_LookupConfig returns a reference FQSpi_Config_t structure based on the
+ * unique device id.
+ * @in param {u32} instanceId : unique device
+ * @return {FQSpi_Config_t} FQSpi_Config_t is a reference to a config record in the configuration
+ * table (in qspi_g.c) corresponding to <i>instanceId</i>, or NULL if no match is found.
+ */
+ FQSpi_Config_t *FQSpi_LookupConfig(u32 instanceId);
+
+ /**
+ * @name: FQSpi_CfgInitialize
+ * @msg: This function intializes the configuration for the qspi instance
+ * @in param {FQSpi_t *} pQspi: A pointer to the qspi instance
+ * @in param {FQSpi_Config_t *} pConfig: A pointer to the qspi instance config record
+ * @return {ft_error_t}
+ */
+ ft_error_t FQSpi_CfgInitialize(FQSpi_t *pQspi, FQSpi_Config_t *pConfig);
+
+ /**
+ * @name: FQSpi_CmdOperation
+ * @msg: This function send command instruction by the struct FQSpi_CmdPack
+ * @in param {FQSpi_t *} pQspi: A pointer to the qspi instance
+ * @in param {struct FQSpi_CmdPack *} pCmdPack: Need to send command instruction package
+ * @return {ft_error_t}
+ */
+ ft_error_t FQSpi_CmdOperation(FQSpi_t *pQspi, struct FQSpi_CmdPack *pCmdPack);
+
+ /**
+ * @name: FQSpi_Read
+ * @msg: This function reads flash data from a specific address by {struct FQSpi_DataPack}
+ * @in param {FQSpi_t *} pQspi: A pointer to the qspi instance
+ * @in param {struct FQSpi_DataPack *} pDataPack: Need to read data package
+ * @return {ft_error_t}
+ */
+ ft_error_t FQSpi_Read(FQSpi_t *pQspi, struct FQSpi_DataPack *pDataPack);
+
+ /**
+ * @name: FQSpi_Write
+ * @msg: This function writes data from a specific address by {struct FQSpi_DataPack}
+ * @in param {FQSpi_t *} pQspi: A pointer to the qspi instance
+ * @in param {struct FQSpi_DataPack *} pDataPack: Need to read data package
+ * @return {ft_error_t}
+ */
+ ft_error_t FQSpi_Write(FQSpi_t *pQspi, struct FQSpi_DataPack *pDataPack);
+
+ /**
+ * @name: FQSpi_FlashRegSet
+ * @msg: This function sends command instruction with specific parameters
+ * @in param {FQSpi_t *} pQspi: A pointer to the qspi instance
+ * @in param {FT_IN u8} cmd: Command instruction
+ * @in param {FT_IN u8 *} writebuf: Data that needs to be sent through command instruction registers
+ * @in param {u32} length: Data length
+ * @return {ft_error_t}
+ */
+ ft_error_t FQSpi_FlashRegSet(FQSpi_t *pQspi,
+ FT_IN u8 cmd,
+ FT_IN u8 *writebuf,
+ u32 length);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/bsp/ft2004/libraries/bsp/ft_qspi/qspi_g.c b/bsp/ft2004/libraries/bsp/ft_qspi/qspi_g.c
new file mode 100644
index 0000000000..18833f60d0
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_qspi/qspi_g.c
@@ -0,0 +1,26 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 11:31:12
+ * @LastEditTime: 2021-04-07 11:31:13
+ * @Description:  Description of file
+ * @Modify History:
+ * * * Ver   Who        Date         Changes
+ * * ----- ------     --------    --------------------------------------
+ * * v1.0 hh 2021-04-07 init
+ */
+#include "ft_qspi.h"
+#include "ft_parameters.h"
+
+FQSpi_Config_t FqSpi_ConfigTable[FT_QSPI_NUM] = {
+ {.instanceId = FT_QSPI_INSTANCE, /* Id of device */
+ .baseAddress = FT_QSPI_BASEADDR, /* Base address of qspi */
+ .transMode = FT_QSPI_TRANSFER_1_1_1, /* Transfer mode */
+ .capacity = FT_QSPI_FLASH_CAP_32MB, /* Flash capacity */
+ .addrMode = FT_QSPI_ADDR_SEL_3, /**/
+ .clkDiv = FT_QSPI_SCK_DIV_128,
+ .qspiDevNum = 1,
+ .channel = 0,
+ .bitWidth = 8}};
diff --git a/bsp/ft2004/libraries/bsp/ft_qspi/qspi_hw.c b/bsp/ft2004/libraries/bsp/ft_qspi/qspi_hw.c
new file mode 100644
index 0000000000..1fb8e05c0d
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_qspi/qspi_hw.c
@@ -0,0 +1,25 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-02 18:32:42
+ * @LastEditTime: 2021-04-02 18:32:43
+ * @Description:  Description of file
+ * @Modify History:
+ * * * Ver   Who        Date         Changes
+ * * ----- ------     --------    --------------------------------------
+ */
+#include "qspi_hw.h"
+#include "ft_qspi.h"
+#include "ft_assert.h"
+#include "ft_io.h"
+
+void FQSpi_Reset(FQSpi_t *pQspi)
+{
+ FQSpi_Config_t *pConfig = NULL;
+ Ft_assertVoid(pQspi != NULL);
+ pConfig = &pQspi->config;
+ Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CAP_OFFSET,
+ FT_REG_QSPI_CAP_FLASH_NUM(pConfig->qspiDevNum) | FT_REG_QSPI_CAP_FLASH_CAP(pConfig->capacity));
+}
diff --git a/bsp/ft2004/libraries/bsp/ft_qspi/qspi_hw.h b/bsp/ft2004/libraries/bsp/ft_qspi/qspi_hw.h
new file mode 100644
index 0000000000..c7b9cb9651
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_qspi/qspi_hw.h
@@ -0,0 +1,199 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-02 18:32:54
+ * @LastEditTime: 2021-05-24 14:33:45
+ * @Description:  Description of file
+ *
+ * @Modify History:
+ * * * Ver   Who        Date         Changes
+ * * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef QSPI_HW_H
+#define QSPI_HW_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "ft_qspi.h"
+#include "ft_types.h"
+
+/* register definition */
+#define FT_REG_QSPI_CAP_OFFSET (0x00) /* Flash capacity setting register */
+#define FT_REG_QSPI_RD_CFG_OFFSET (0x04) /* Address access reads configuration registers */
+#define FT_REG_QSPI_WR_CFG_OFFSET (0x08) /* Write buffer flush register */
+#define FT_REG_QSPI_FLUSH_OFFSET (0x0C) /* Write buffer flush register */
+#define FT_REG_QSPI_CMD_PORT_OFFSET (0x10) /* Command port register */
+#define FT_REG_QSPI_ADDR_PORT_OFFSET (0x14) /* Address port register */
+#define FT_REG_QSPI_HD_PORT_OFFSET (0x18) /* Upper bit port register */
+#define FT_REG_QSPI_LD_PORT_OFFSET (0x1C) /* low bit port register */
+#define FT_REG_QSPI_FUN_SET_OFFSET (0x20) /* CS setting register */
+#define FT_REG_QSPI_WIP_RD_OFFSET (0x24) /* WIP reads the Settings register */
+#define FT_REG_QSPI_WP_OFFSET (0x28) /* WP register */
+#define FT_REG_QSPI_MODE_OFFSET (0x2C) /* Mode setting register */
+
+/*QSPI_CAP*/
+#define FT_REG_QSPI_CAP_FLASH_NUM(data) ((data) << 3) /* Flash number */
+#define FT_REG_QSPI_CAP_FLASH_CAP(data) ((data) << 0) /* The flash capacity */
+
+/* RD_CFG */
+#define FT_RD_CFG_CMD(data) ((data) << 24) /* Read Command */
+#define FT_RD_CFG_THROUGH(data) ((data) << 23) /* The programming flag in the status register */
+#define FT_RD_CFG_TRANSFER(data) ((data) << 20) /* */
+#define FT_RD_CFG_ADDR_SEL(data) ((data) << 19) /* */
+#define FT_RD_CFG_LATENCY(data) ((data) << 18) /* */
+#define FT_RD_CFG_MODE_BYTE(data) ((data) << 17) /* */
+#define FT_RD_CFG_CMD_SIGN(data) ((data) << 9) /* */
+#define FT_RD_CFG_DUMMY(data) ((data) << 4) /* */
+#define FT_RD_CFG_D_BUFFER(data) ((data) << 3) /* */
+#define FT_RD_CFG_SCK_SEL(data) ((data) << 0) /* */
+
+/*QSPI_WR_CFG*/
+#define FT_WR_CFG_CMD(data) ((data) << 24)
+#define FT_WR_CFG_WAIT(data) ((data) << 9)
+#define FT_WR_CFG_THROUGH(data) ((data) << 8)
+#define FT_WR_CFG_TRANSFER(data) ((data) << 5)
+#define FT_WR_CFG_ADDRSEL(data) ((data) << 4)
+#define FT_WR_CFG_MODE(data) ((data) << 3)
+#define FT_WR_CFG_SCK_SEL(data) ((data) << 0)
+
+/*QSPI_CMD_PORT*/
+#define FT_CMD_PORT_CMD(data) ((data) << 24)
+#define FT_CMD_PORT_WAIT(data) ((data) << 22)
+#define FT_CMD_PORT_THROUGH(data) ((data) << 21)
+#define FT_CMD_PORT_CS(data) ((data) << 19)
+#define FT_CMD_PORT_TRANSFER(data) ((data) << 16)
+#define FT_CMD_PORT_ADDR(data) ((data) << 15)
+#define FT_CMD_PORT_LATENCY(data) ((data) << 14)
+#define FT_CMD_PORT_DATA_TRANS(data) ((data) << 13)
+#define FT_CMD_PORT_ADDR_SEL(data) ((data) << 12)
+#define FT_CMD_PORT_DUMMY(data) ((data) << 7)
+#define FT_CMD_PORT_P_BUFFER(data) ((data) << 6)
+#define FT_CMD_PORT_RW_NUM(data) ((data) << 3)
+#define FT_CMD_PORT_CLK_SEL(data) ((data) << 0)
+
+/*QSPI_FUN_SET*/
+#define FT_FUN_SET_CS_HOLD(data) ((data) << 24)
+#define FT_FUN_SET_CS_SETUP(data) ((data) << 16)
+#define FT_FUN_SET_CS_DELAY(data) ((data) << 0)
+
+/*QSPI_WIP_RD*/
+#define FT_WIP_RD_CMD(data) ((data) << 24)
+#define FT_WIP_RD_TRANSFER(data) ((data) << 3)
+#define FT_WIP_RD_SCK_SEL(data) ((data) << 0)
+
+/*QSPI_WP*/
+#define FT_WP_EN(data) ((data) << 17)
+#define FT_WP_WP(data) ((data) << 16)
+#define FT_WP_HOLD(data) ((data) << 8)
+#define FT_WP_SETUP(data) ((data) << 0)
+
+/*QSPI_MODE*/
+#define FT_MODE_VALID(data) ((data) << 8)
+#define FT_MODE_MODE(data) ((data) << 0)
+
+#define FT_QSPI_FLASH_CAP_4MB 0
+#define FT_QSPI_FLASH_CAP_8MB 1
+#define FT_QSPI_FLASH_CAP_16MB 2
+#define FT_QSPI_FLASH_CAP_32MB 3
+#define FT_QSPI_FLASH_CAP_64MB 4
+#define FT_QSPI_FLASH_CAP_128MB 5
+#define FT_QSPI_FLASH_CAP_256MB 6
+
+#define FT_QSPI_ADDR_SEL_3 0
+#define FT_QSPI_ADDR_SEL_4 1
+
+#define FT_QSPI_SCK_DIV_128 0
+#define FT_QSPI_SCK_DIV_2 1
+#define FT_QSPI_SCK_DIV_4 2
+#define FT_QSPI_SCK_DIV_8 3
+#define FT_QSPI_SCK_DIV_16 4
+#define FT_QSPI_SCK_DIV_32 5
+#define FT_QSPI_SCK_DIV_64 6
+
+#define FT_QSPI_TRANSFER_1_1_1 0
+#define FT_QSPI_TRANSFER_1_1_2 1
+#define FT_QSPI_TRANSFER_1_1_4 2
+#define FT_QSPI_TRANSFER_1_2_2 3
+#define FT_QSPI_TRANSFER_1_4_4 4
+#define FT_QSPI_TRANSFER_2_2_2 5
+#define FT_QSPI_TRANSFER_4_4_4 6
+
+ /* typedefs */
+ /*QSPI_RD_CFG*/
+ typedef union
+ {
+ u32 data;
+ struct
+ {
+ u32 rdSckSel : 3; /* 2:0 */
+ u32 dBuffer : 1; /* 3 */
+ u32 dummy : 5; /* 8:4 */
+ u32 cmdSign : 8; /* 16:9 */
+ u32 modeByte : 1; /* 17 */
+ u32 rdLatency : 1; /* 18 */
+ u32 rdAddrSel : 1; /* 19 */
+ u32 rdTransfer : 3; /* 22:20 */
+ u32 rdThrough : 1; /* 23 */
+ u32 rdCmd : 8; /* 31:24 */
+ } val;
+ } FQSpi_RdCfgReg_t;
+
+ /*QSPI_WR_CFG*/
+ typedef union
+ {
+ u32 data;
+ struct
+ {
+ u32 wrSckSel : 3; /* 2:0 */
+ u32 wrMode : 1; /* 3 */
+ u32 wrAddrsel : 1; /* 4 */
+ u32 wrTransfer : 3; /* 7:5 */
+ u32 wrThrough : 1; /* 8 */
+ u32 wrWait : 1; /* 9 */
+ u32 wrRes : 14; /* 23:10 */
+ u32 wrCmd : 8; /* 31:24 */
+ } val;
+ } FQSpi_WrCfgReg_t;
+
+ /*QSPI_CMD_PORT*/
+ typedef union
+ {
+ u32 data;
+ struct
+ {
+ u32 sckSel : 3; /* 2:0 */
+ u32 rwMum : 3; /* 5:3 */
+ u32 pBuffer : 1; /* 6 */
+ u32 dummy : 5; /* 11:7 */
+ u32 addrSel : 1; /* 12 */
+ u32 dataTransfer : 1; /* 13 */
+ u32 latency : 1; /* 14 */
+ u32 cmdAddr : 1; /* 15 */
+ u32 transfer : 3; /* 18:16 */
+ u32 cs : 2; /* 20:19 */
+ u32 through : 1; /* 21 */
+ u32 wait : 1; /* 22 */
+ u32 res : 1; /* 23 */
+ u32 cmd : 8; /* 31:24 */
+ } val;
+ } FQSpi_CmdPortReg_t;
+
+ /**
+ * @name: FQSpi_Reset
+ * @msg: This routine performs the QSPI controller initialization.
+ * @in param: pQspi
+ * @return {*}
+ */
+ void FQSpi_Reset(FQSpi_t *pQspi);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // !
diff --git a/bsp/ft2004/libraries/bsp/ft_qspi/qspi_sinit.c b/bsp/ft2004/libraries/bsp/ft_qspi/qspi_sinit.c
new file mode 100644
index 0000000000..36c1e313a2
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_qspi/qspi_sinit.c
@@ -0,0 +1,34 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 13:22:01
+ * @LastEditTime: 2021-04-07 13:22:01
+ * @Description:  Description of file
+ * @Modify History:
+ * * * Ver   Who        Date         Changes
+ * * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_qspi.h"
+#include "ft_parameters.h"
+
+extern FQSpi_Config_t FqSpi_ConfigTable[FT_QSPI_NUM];
+
+FQSpi_Config_t *FQSpi_LookupConfig(u32 instanceId)
+{
+ FQSpi_Config_t *pFQSpi_Config_t = NULL;
+
+ u32 Index;
+ for (Index = 0; Index < (u32)FT_GMAC_INSTANCES_NUM; Index++)
+ {
+ if (FqSpi_ConfigTable[Index].instanceId == instanceId)
+ {
+ pFQSpi_Config_t = &FqSpi_ConfigTable[Index];
+ break;
+ }
+ }
+
+ return pFQSpi_Config_t;
+}
diff --git a/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl.c b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl.c
new file mode 100644
index 0000000000..cf2eb5c7b0
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl.c
@@ -0,0 +1,552 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-03-31 14:59:20
+ * @LastEditTime: 2021-05-25 16:49:01
+ * @Description:  This files is for implemenation of sd ctrl
+ *
+ * @Modify History: * * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_parameters.h"
+#include "ft_assert.h"
+#include "ft_io.h"
+#include "ft_sdctrl.h"
+#include "ft_sdctrl_hw.h"
+#include "ft_debug.h"
+#include "ft_printf.h"
+#include "ft_trace.h"
+#include "ft_cache.h"
+#define FT_SD_CTRL_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FT_SD_CTRL_DEBUG_TAG, format, ##__VA_ARGS__)
+#define FT_SD_CTRL_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(FT_SD_CTRL_DEBUG_TAG, format, ##__VA_ARGS__)
+#define FT_SD_CTRL_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FT_SD_CTRL_DEBUG_TAG, format, ##__VA_ARGS__)
+
+void FSdCtrl_ClkFreqSetup(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN u32 sdClk)
+{
+ FSdCtrl_Config_t *pConfig;
+ u32 clkDiv;
+ u32 inputClk;
+ u32 tmpSdFreq;
+ u32 workSpeed;
+
+ Ft_assertVoid(FT_NULL != pFtsdCtrl);
+ pConfig = &pFtsdCtrl->config;
+ inputClk = pConfig->inputClockHz;
+
+ /* sd work speed is limit to 25MHz */
+ workSpeed = (sdClk < SD_CLK_FREQ_25MHZ) ? sdClk : SD_CLK_FREQ_25MHZ;
+
+ /* if sd clk freq is valid and is two times greater than io input clk */
+ if ((SD_CLK_FREQ_400KHZ < workSpeed) && (inputClk > (2 * workSpeed)))
+ {
+ clkDiv = (u32)(inputClk / (2 * workSpeed)) - 1;
+
+ /* calculte sd freq one more time base on divsor */
+ tmpSdFreq = (u32)inputClk / (2 * (clkDiv + 1));
+
+ /* if calculated sd freq is greater than the real val */
+ if (tmpSdFreq > workSpeed)
+ {
+ clkDiv += 1;
+ }
+ }
+ else
+ {
+ clkDiv = SD_FRRQ_DIV_DEFAULT;
+ }
+
+ Ft_out32(pConfig->baseAddress + CLOCK_DIV_REG_OFFSET, clkDiv);
+
+ return;
+}
+
+ft_error_t FsdCtrl_Init(FT_INOUT FtsdCtrl_t *pFtsdCtrl)
+{
+ FSdCtrl_Config_t *pConfig;
+ Ft_assertNonvoid(FT_NULL != pFtsdCtrl);
+ pConfig = &pFtsdCtrl->config;
+
+ /* Disable card detection */
+ Ft_out32(pConfig->baseAddress + SD_SEN_REG_OFFSET, 0);
+
+ /* Disable all interrupts */
+ Ft_out32(pConfig->baseAddress + NORMAL_INT_EN_REG_OFFSET, 0);
+ Ft_out32(pConfig->baseAddress + ERROR_INT_EN_REG_OFFSET, 0);
+ Ft_out32(pConfig->baseAddress + BD_ISR_EN_REG_OFFSET, 0);
+ // Ft_out32(pConfig->baseAddress + NORMAL_INT_EN_REG_OFFSET, NORMAL_INT_EN_ECCRCE);
+
+ /* Clear status register */
+ Ft_out32(pConfig->baseAddress + NORMAL_INT_STATUS_REG, 0);
+ Ft_out32(pConfig->baseAddress + ERROR_INT_STATUS_REG, 0);
+ Ft_out32(pConfig->baseAddress + BD_ISR_REG, 0);
+
+ /* Set default ctrl register */
+ Ft_out32(pConfig->baseAddress + CONTROLL_SETTING_REG_OFFSET, 0x0f00);
+
+ /* Set default drive and sampling register */
+ Ft_out32(pConfig->baseAddress + SD_DRV_REG_OFFSET, 0);
+ Ft_out32(pConfig->baseAddress + SD_SAMP_REG_OFFSET, 0);
+
+ /* Configure to default cmd data timeout */
+ Ft_out32(pConfig->baseAddress + TIMEOUT_CMD_REG_OFFSET, 0xFFFFFFFF);
+ //FSdCtrl_ClkFreqSetup(pFtsdCtrl, 1);
+
+ Ft_out32(pConfig->baseAddress + CLOCK_DIV_REG_OFFSET, SD_FRRQ_DIV_DEFAULT);
+ Ft_out32(pConfig->baseAddress + SD_SAMP_REG_OFFSET, SD_SAMP_DEFAULT);
+
+ pFtsdCtrl->isReady = FT_COMPONENT_IS_READLY;
+
+ return FTSDC_SUCCESS;
+}
+
+bool_t FSdCtrl_CardDetect(FT_INOUT FtsdCtrl_t *pFtsdCtrl)
+{
+ FSdCtrl_Config_t *pConfig;
+ u32 status;
+
+ Ft_assertBool(FT_NULL != pFtsdCtrl);
+ pConfig = &pFtsdCtrl->config;
+ status = Ft_in32(pConfig->baseAddress + STATUS_REG);
+
+ /* check card-detection signal */
+ if (((status)&STATUS_REG_CDSL) == STATUS_REG_CDSL)
+ {
+ pConfig->cardDetect = 0;
+ }
+ else
+ {
+ pConfig->cardDetect = 1;
+ }
+
+ return pConfig->cardDetect;
+}
+
+void FSdCtrl_ResetDma(FT_INOUT FtsdCtrl_t *pFtsdCtrl)
+{
+ FSdCtrl_Config_t *pConfig;
+ Ft_assertVoid(FT_NULL != pFtsdCtrl);
+ pConfig = &pFtsdCtrl->config;
+
+ Ft_setBit32((UINTPTR)(pConfig->baseAddress + SOFTWARE_RESET_REG_OFFSET), SOFTWARE_RESET_BDRST);
+ Ft_clearBit32((UINTPTR)(pConfig->baseAddress + SOFTWARE_RESET_REG_OFFSET), SOFTWARE_RESET_BDRST);
+}
+
+u32 FSdCtrl_PrepareCmdRaw(FT_IN u32 cmdIndex, FT_IN u32 rspType)
+{
+ u32 rawCmd = 0;
+
+ rawCmd |= CMD_SETTING_CMDI(cmdIndex);
+
+ switch (rspType)
+ {
+ case FTSDCTRL_CMD_RES_NONE:
+ rawCmd |= CMD_SETTING_RTS(0);
+ break;
+ case FTSDCTRL_CMD_RES_LONG:
+ rawCmd |= CMD_SETTING_RTS(1);
+ break;
+ case FTSDCTRL_CMD_RES_SHORT:
+ rawCmd |= CMD_SETTING_RTS(2);
+ break;
+ default:
+ rawCmd |= CMD_SETTING_RTS(0);
+ break;
+ }
+
+ return rawCmd;
+}
+
+void FSdCtrl_WriteData(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN UINTPTR dataAddr,
+ FT_IN UINTPTR cardAddr, FT_IN u32 blkNum)
+{
+
+ FSdCtrl_Config_t *pConfig;
+ Ft_assertVoid(FT_NULL != pFtsdCtrl);
+ pConfig = &pFtsdCtrl->config;
+
+ /* write 1 to clear data status register and command status register */
+ Ft_out32(pConfig->baseAddress + BD_ISR_REG, BD_ISR_REG_TRS);
+ Ft_out32(pConfig->baseAddress + NORMAL_INT_STATUS_REG, NORMAL_INT_STATUS_CC);
+
+ /* set DMA BD */
+ Ft_setBit32((UINTPTR)(pConfig->baseAddress + SOFTWARE_RESET_REG_OFFSET), SOFTWARE_RESET_BDRST);
+ Ft_clearBit32((UINTPTR)(pConfig->baseAddress + SOFTWARE_RESET_REG_OFFSET), SOFTWARE_RESET_BDRST);
+
+ /* set transfer lenth */
+ Ft_out32(pConfig->baseAddress + BLK_CNT_REG, blkNum);
+
+ /* set DMA discriptor data low address,data high address,card low address,card high address*/
+ Ft_out32(pConfig->baseAddress + DAT_IN_M_TX_BD, dataAddr);
+ Ft_out32(pConfig->baseAddress + DAT_IN_M_TX_BD, 0);
+ Ft_out32(pConfig->baseAddress + DAT_IN_M_TX_BD, cardAddr);
+ Ft_out32(pConfig->baseAddress + DAT_IN_M_TX_BD, 0);
+}
+
+void FSdCtrl_ReadData(FT_INOUT FtsdCtrl_t *pFtsdCtrl,
+ FT_IN UINTPTR dataAddr,
+ FT_IN UINTPTR cardAddr,
+ FT_IN u32 blkNum)
+{
+ FSdCtrl_Config_t *pConfig;
+ Ft_assertVoid(FT_NULL != pFtsdCtrl);
+ pConfig = &pFtsdCtrl->config;
+
+ /* clear data status register and command status register */
+ Ft_out32(pConfig->baseAddress + BD_ISR_REG, BD_ISR_EN_ETRS);
+ Ft_out32(pConfig->baseAddress + NORMAL_INT_STATUS_REG, NORMAL_INT_EN_ECC);
+
+ /* set DMA BD */
+ Ft_setBit32((UINTPTR)(pConfig->baseAddress + SOFTWARE_RESET_REG_OFFSET), SOFTWARE_RESET_BDRST);
+ Ft_clearBit32((UINTPTR)(pConfig->baseAddress + SOFTWARE_RESET_REG_OFFSET), SOFTWARE_RESET_BDRST);
+
+ /* set transfer lenth */
+ Ft_out32(pConfig->baseAddress + BLK_CNT_REG, blkNum);
+
+ /* set DMA discriptor data low address,data high address,card low address,card high address*/
+
+ Ft_out32(pConfig->baseAddress + DAT_IN_M_RX_BD, dataAddr);
+ Ft_out32(pConfig->baseAddress + DAT_IN_M_RX_BD, 0);
+ Ft_out32(pConfig->baseAddress + DAT_IN_M_RX_BD, cardAddr);
+ Ft_out32(pConfig->baseAddress + DAT_IN_M_RX_BD, 0);
+}
+
+static ft_error_t FsdCtrl_privateSendCmd(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN pFtsdCtrl_delayTimer_t pDelayTimer_fun, FT_IN u32 cmd, FT_IN u32 respType, FT_IN u32 arg)
+{
+ u32 temp;
+ u32 sd_cmd;
+ u32 sd_arg;
+ FSdCtrl_Config_t *pConfig;
+ Ft_assertNonvoid(FT_NULL != pFtsdCtrl);
+ pConfig = &pFtsdCtrl->config;
+
+ /* enable cmd finished irq */
+ Ft_out32(pConfig->baseAddress + NORMAL_INT_STATUS_REG, NORMAL_INT_EN_ECC);
+ Ft_out32(pConfig->baseAddress + NORMAL_INT_STATUS_REG, 0);
+
+ Ft_out32(pConfig->baseAddress + ERROR_INT_STATUS_REG, BD_ISR_EN_ETRS);
+ Ft_out32(pConfig->baseAddress + ERROR_INT_STATUS_REG, 0);
+
+ /* prepare cmd msg, along with arg */
+ sd_cmd = FSdCtrl_PrepareCmdRaw(cmd, respType);
+ sd_arg = arg;
+
+ /* send cmd and arg */
+ Ft_out32(pConfig->baseAddress + CMD_SETTING_REG_OFFSET, sd_cmd);
+ Ft_out32(pConfig->baseAddress + ARGUMENT_REG_OFFSET, sd_arg);
+
+ if (pConfig->workMode & FTSDCTRL_CMD_IRQ_MASK)
+ {
+ if (pFtsdCtrl->cmdWaitCallback)
+ {
+ /* if irq is enabled and call back registered, enter call back procedure */
+ return pFtsdCtrl->cmdWaitCallback(pFtsdCtrl);
+ }
+ else
+ {
+ return FTSDC_INVALID_PARAM;
+ }
+ }
+ else
+ {
+ temp = Ft_in32(pConfig->baseAddress + NORMAL_INT_STATUS_REG);
+ /* polling wait for cmd-finished response */
+ while (NORMAL_INT_STATUS_CC != (temp & NORMAL_INT_STATUS_CC))
+ {
+ temp = Ft_in32(pConfig->baseAddress + NORMAL_INT_STATUS_REG);
+ pDelayTimer_fun(1);
+ }
+ }
+
+ return FTSDC_SUCCESS;
+}
+
+ft_error_t FSdCtrl_WaitWriteDataEnd(FT_INOUT FtsdCtrl_t *pFtsdCtrl,
+ FT_IN pFtsdCtrl_delayTimer_t pDelayTimer_fun,
+ FT_IN u32 blkNum)
+{
+ u32 status;
+ u32 statusMask;
+ ft_error_t ret;
+ s32 timeout = 1000;
+ FSdCtrl_Config_t *pConfig;
+
+ Ft_assertNonvoid(FT_NULL != pFtsdCtrl);
+ pConfig = &pFtsdCtrl->config;
+
+ if (pConfig->workMode & FTSDCTRL_DATA_WRITE_IRQ_MASK)
+ {
+ /* enter irq mode */
+ if (NULL == pFtsdCtrl->writeWaitCallback)
+ {
+ return FTSDC_INVALID_PARAM;
+ }
+
+ ret = pFtsdCtrl->writeWaitCallback(pFtsdCtrl);
+ if (FTSDC_SUCCESS != ret)
+ {
+ return FTSDC_EILSEQ;
+ }
+ }
+ else
+ {
+ /* wait for DMA-error or DMA-finished status */
+ statusMask = BD_ISR_REG_DAIS | BD_ISR_REG_TRS;
+ do
+ {
+ status = (Ft_in32(pConfig->baseAddress + BD_ISR_REG) & statusMask);
+ pDelayTimer_fun(1);
+ timeout--;
+ } while ((!status) && timeout);
+
+ if (status & BD_ISR_REG_DAIS)
+ {
+ if (status & (BD_ISR_REG_TRE | BD_ISR_REG_NRCRC | BD_ISR_REG_CMDE))
+ {
+ return FTSDC_EILSEQ;
+ }
+ else if (!timeout)
+ {
+ return FTSDC_TIMEOUT;
+ }
+ }
+ }
+
+ /* multi block needs MMC_STOP_TRANSMISSION to stop process*/
+ if (blkNum > 1)
+ {
+ return FsdCtrl_privateSendCmd(pFtsdCtrl, pDelayTimer_fun, 12, CMD_SETTING_RTS(2), 0);
+ }
+
+ return FTSDC_SUCCESS;
+}
+
+ft_error_t FSdCtrl_WaitReadDataEnd(FT_INOUT FtsdCtrl_t *pFtsdCtrl,
+ FT_IN pFtsdCtrl_delayTimer_t pDelayTimer_fun,
+ FT_IN u32 blkNum)
+{
+ u32 status;
+ u32 statusMask;
+ ft_error_t ret;
+ s32 timeout = 1000;
+ FSdCtrl_Config_t *pConfig;
+
+ Ft_assertNonvoid(FT_NULL != pFtsdCtrl);
+ pConfig = &pFtsdCtrl->config;
+
+ if (pConfig->workMode & FTSDCTRL_DATA_READ_IRQ_MASK)
+ {
+ if (pFtsdCtrl->readWaitCallback)
+ {
+ ret = pFtsdCtrl->readWaitCallback(pFtsdCtrl);
+ if (FTSDC_SUCCESS != ret)
+ {
+ return FTSDC_EILSEQ;
+ }
+ }
+ else
+ {
+ return FTSDC_INVALID_PARAM;
+ }
+ }
+ else
+ {
+ /* wait for DMA-error or Read-finish status */
+ statusMask = BD_ISR_REG_DAIS | BD_ISR_REG_RESPE;
+ do
+ {
+ status = (Ft_in32(pConfig->baseAddress + BD_ISR_REG) & statusMask);
+ pDelayTimer_fun(1);
+ timeout--;
+ } while ((!status) && timeout);
+
+ if (status & BD_ISR_REG_DAIS)
+ {
+ /* error handle */
+ if (status & (BD_ISR_REG_TRE | BD_ISR_REG_NRCRC | BD_ISR_REG_CMDE))
+ {
+ return FTSDC_EILSEQ;
+ }
+ else if (!timeout)
+ {
+ return FTSDC_TIMEOUT;
+ }
+ }
+ }
+
+ // /* multi block needs MMC_STOP_TRANSMISSION to stop process*/
+ if (blkNum > 1)
+ {
+ return FsdCtrl_privateSendCmd(pFtsdCtrl, pDelayTimer_fun, 12, CMD_SETTING_RTS(2), 0);
+ }
+
+ return FTSDC_SUCCESS;
+}
+
+ft_error_t FSdCtrl_WaitCmdEnd(FT_OUT FtsdCtrl_t *pFtsdCtrl,
+ FT_IN pFtsdCtrl_delayTimer_t pDelayTimer_fun,
+ FT_IN u32 rspType,
+ FT_OUT u32 *cmdRsp)
+{
+ u32 status;
+ u32 statusMask;
+ s32 timeout = 1000;
+ const FSdCtrl_Config_t *pConfig;
+ ft_error_t result = FST_SUCCESS;
+
+ Ft_assertNonvoid(FT_NULL != pFtsdCtrl);
+ pConfig = &pFtsdCtrl->config;
+
+ if (pConfig->workMode & FTSDCTRL_CMD_IRQ_MASK)
+ {
+ if (pFtsdCtrl->cmdWaitCallback)
+ {
+ result = pFtsdCtrl->cmdWaitCallback(pFtsdCtrl);
+ }
+ else
+ {
+ return FTSDC_INVALID_PARAM;
+ }
+ status = Ft_in32(pConfig->baseAddress + NORMAL_INT_STATUS_REG);
+ }
+ else
+ {
+ /* wait for cmd-error or cmd-finish respones */
+ statusMask = NORMAL_INT_STATUS_EI | NORMAL_INT_STATUS_CC;
+
+ do
+ {
+ status = (Ft_in32(pConfig->baseAddress + NORMAL_INT_STATUS_REG) & statusMask);
+ pDelayTimer_fun(1);
+ timeout--;
+
+ } while ((!status) && timeout);
+ }
+
+ if (status & NORMAL_INT_STATUS_EI)
+ {
+ /* error handle */
+ status = Ft_in32(pConfig->baseAddress + ERROR_INT_STATUS_REG);
+
+ if (!timeout)
+ {
+ return FTSDC_TIMEOUT;
+ }
+ else if ((status & NORMAL_INT_EN_ECCRCE))
+ {
+ return FTSDC_EILSEQ;
+ }
+ }
+
+ if (rspType != FTSDCTRL_CMD_RES_NONE)
+ {
+ /* get cmd respones */
+ if (rspType == FTSDCTRL_CMD_RES_LONG)
+ {
+ cmdRsp[0] = Ft_in32(pConfig->baseAddress + CMD_RESP_1);
+ cmdRsp[1] = Ft_in32(pConfig->baseAddress + CMD_RESP_2);
+ cmdRsp[2] = Ft_in32(pConfig->baseAddress + CMD_RESP_3);
+ cmdRsp[3] = Ft_in32(pConfig->baseAddress + CMD_RESP_4);
+ }
+ else
+ {
+ cmdRsp[0] = Ft_in32(pConfig->baseAddress + CMD_RESP_1);
+ cmdRsp[1] = 0;
+ cmdRsp[2] = 0;
+ cmdRsp[3] = 0;
+ }
+ }
+
+ return result;
+}
+
+void FSdCtrl_DoCmd(FT_INOUT FtsdCtrl_t *pFtsdCtrl,
+ FT_IN u32 cmdIndex,
+ FT_IN u32 rspType,
+ u32 arg)
+{
+ u32 cmd;
+
+ FSdCtrl_Config_t *pConfig;
+ Ft_assertVoid(FT_NULL != pFtsdCtrl);
+ pConfig = &pFtsdCtrl->config;
+
+ /* clear normal interrupt status */
+ Ft_out32(pConfig->baseAddress + NORMAL_INT_STATUS_REG, NORMAL_INT_STATUS_EI);
+
+ /* set command*/
+ cmd = FSdCtrl_PrepareCmdRaw(cmdIndex, rspType);
+ Ft_out32(pConfig->baseAddress + CMD_SETTING_REG_OFFSET, cmd);
+
+ if (cmdIndex == 41)
+ {
+ arg = 0x40ff8000;
+ }
+
+ Ft_out32(pConfig->baseAddress + ARGUMENT_REG_OFFSET, arg);
+}
+
+void FSdCtrl_DoACmd(FT_INOUT FtsdCtrl_t *pFtsdCtrl,
+ FT_IN u32 cmdIndex,
+ FT_IN u32 rspType,
+ u32 arg)
+{
+ u32 cmd;
+
+ FSdCtrl_Config_t *pConfig;
+ Ft_assertVoid(FT_NULL != pFtsdCtrl);
+ pConfig = &pFtsdCtrl->config;
+
+ /* clear normal interrupt status */
+ Ft_out32(pConfig->baseAddress + NORMAL_INT_STATUS_REG, NORMAL_INT_EN_ECC);
+ /* set command*/
+ cmd = FSdCtrl_PrepareCmdRaw(cmdIndex, rspType);
+ cmd |= CMD_SETTING_TRTY(2);
+ Ft_out32(pConfig->baseAddress + CMD_SETTING_REG_OFFSET, cmd);
+}
+
+void FSdCtrl_WriteWaitRegister(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN pFtsdCtrl_irqWaitCallback_t callBack)
+{
+ Ft_assertVoid(FT_NULL != pFtsdCtrl);
+ pFtsdCtrl->writeWaitCallback = callBack;
+}
+
+void FSdCtrl_ReadWaitRegister(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN pFtsdCtrl_irqWaitCallback_t callBack)
+{
+ Ft_assertVoid(FT_NULL != pFtsdCtrl);
+ pFtsdCtrl->readWaitCallback = callBack;
+}
+
+void FSdCtrl_CmdWaitRegister(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN pFtsdCtrl_irqWaitCallback_t callBack)
+{
+ Ft_assertVoid(FT_NULL != pFtsdCtrl);
+ pFtsdCtrl->cmdWaitCallback = callBack;
+}
+
+u32 FSdCtrl_GetNormalIrqStatus(FT_INOUT FtsdCtrl_t *pFtsdCtrl)
+{
+ Ft_assertNonvoid(FT_NULL != pFtsdCtrl);
+ FSdCtrl_Config_t *pConfig;
+ pConfig = &pFtsdCtrl->config;
+ return Ft_in32(pConfig->baseAddress + NORMAL_INT_STATUS_REG);
+}
+
+u32 FSdCtrl_GetDataIrqStatus(FT_INOUT FtsdCtrl_t *pFtsdCtrl)
+{
+ Ft_assertNonvoid(FT_NULL != pFtsdCtrl);
+ FSdCtrl_Config_t *pConfig;
+ pConfig = &pFtsdCtrl->config;
+
+ return Ft_in32(pConfig->baseAddress + BD_ISR_REG);
+}
+
+u32 FSdCtrl_GetErrorIrqStatus(FT_INOUT FtsdCtrl_t *pFtsdCtrl)
+{
+ Ft_assertNonvoid(FT_NULL != pFtsdCtrl);
+ FSdCtrl_Config_t *pConfig;
+ pConfig = &pFtsdCtrl->config;
+
+ return Ft_in32(pConfig->baseAddress + ERROR_INT_STATUS_REG);
+}
diff --git a/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl.h b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl.h
new file mode 100644
index 0000000000..88a0e9ee2b
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl.h
@@ -0,0 +1,235 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-03-31 14:59:20
+ * @LastEditTime: 2021-04-19 17:04:44
+ * @Description:  This files is for implementation of sd ctrl
+ *
+ * @Modify History: * * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef FTSDCTRL_H
+#define FTSDCTRL_H
+#include "ft_types.h"
+#include "ft_error_code.h"
+
+/* sd ctrl module debug tag */
+#define FT_SD_CTRL_DEBUG_TAG "FT_SD_CTRL"
+
+/* definition of errcode for sd module */
+#define FTSDC_SUCCESS FST_SUCCESS /* 成功 */
+#define FTSDC_FAILURE FT_MAKE_ERRCODE(errModeSdCtrl, errBspGeneral, FST_FAILURE) /* Normal */
+#define FTSDC_TIMEOUT FT_MAKE_ERRCODE(errModeSdCtrl, errBspGeneral, FST_TIMEOUT) /* Timeout */
+#define FTSDC_EILSEQ FT_MAKE_ERRCODE(errModeSdCtrl, errBspGeneral, FST_EILSEQ) /* Illegal byte sequence. */
+#define FTSDC_INVALID_PARAM FT_MAKE_ERRCODE(errModeSdCtrl, errBspGeneral, FST_INVALID_PARAM) /* Illegal byte sequence. */
+
+/* type of response to sd cmds */
+#define FTSDCTRL_CMD_RES_NONE 0 /* No response */
+#define FTSDCTRL_CMD_RES_LONG 1 /* The response length is long, code length is 128 */
+#define FTSDCTRL_CMD_RES_SHORT 2 /* The response length is short, code length is 32 */
+
+/* irq enable bits */
+#define FTSDCTRL_DATA_WRITE_IRQ_MASK 0x1
+#define FTSDCTRL_DATA_READ_IRQ_MASK 0x2
+#define FTSDCTRL_CMD_IRQ_MASK 0x4
+
+/* type of irq callback */
+typedef enum
+{
+ FTSDCTRL_DMADATAIRQID = 0x1U, /* Select dma interrupt */
+ FTSDCTRL_CMDIRQID = 0x2U, /* Select cmd interrupt */
+ FTSDCTRL_ERRORIRQID = 0x3U, /* Select error interrupt */
+} FSdCtrl_IrqCallbackSelect_t;
+
+/* normal irq enable bits for NORMAL_INT_EN_REG_OFFSET */
+typedef enum
+{
+ NORMAL_IRQ_CC = 1, /* Command completion interrupt */
+ NORMAL_IRQ_CR = 2, /* Card removal interrupt */
+ NORMAL_IRQ_EI = 4 /* Command error interrupt */
+} FSdCtrl_NormalIrqSelect_t;
+
+/* error irq enable bits for ERROR_INT_EN_REG_OFFSET */
+typedef enum
+{
+ ERROR_IRQ_CTE = 1, /* Command timeout error interrupted */
+ ERROR_IRQ_CCRCE = 2, /* Command CRC error interrupt */
+ ERROR_IRQ_CIR = 4, /* Command index error interrupt */
+ ERROR_IRQ_CNR = 8 /* Command response error interrupted */
+} FSdCtrl_ErrorIrqSelect_t;
+
+/* data trans irq bits for BD_ISR_EN_REG_OFFSET */
+typedef enum
+{
+ BD_IRQ_TRS = 1, /* DMA transmission has been interrupted */
+ BD_IRQ_DTE = 2, /* Timeout interrupt */
+ BD_IRQ_CMDE = 4, /* Command response error interrupted */
+ BD_IRQ_TRE = 8, /* Command response error interrupt CRC response error interrupt */
+ BD_IRQ_NRCRC = 0x10, /* No CRC response interruption */
+ BD_IRQ_DATFRAX = 0x20, /* AXI bus forces to release interrupts */
+ BD_IRQ_RESPE = 0x40, /* Read SD card operation, AXI BR channel complete interrupt */
+ BD_IRQ_DAIS = 0x80, /* DMA error interrupt */
+} FSdCtrl_BdIrqSelect;
+
+/* types of irq */
+typedef enum
+{
+ FTSDC_NORMAL_ISR = 0U,
+ FTSDC_BD_ISR,
+ FTSDC_ERROR_ISR
+} FSdCtrl_IsrCallbackSelect_t;
+
+/* voltage supply range type of SD Card follow POWER_CONTROLL_REG
+*/
+typedef enum
+{
+ FSDC_HIGH_V = 0, /* SD card operate within the voltage range of 2.7-3.6 V */
+ FSDC_DUAL_V, /* SD card operate within the Low Voltage Range (T.B.D) and 2.7-3.6 V */
+
+ MAX_FSDC_VOLTAGE_TYPE
+} FSdCtrl_VRangeType_t;
+
+/* read-write property of SD Card */
+typedef enum
+{
+ FSDC_RW_CARD = 0,
+ FSDC_RO_CARD,
+
+ MAX_FSDC_WR_CARD_TYPE
+} FSdCtrl_WRType_t;
+
+/* capacity type of SD Card */
+typedef enum
+{
+ FSDC_SD_CARD = 0,
+ FSDC_SDHC_CARD,
+ FSDC_SDXC_CARD,
+
+ MAX_FSDC_CARD_CAPACITY_TYPE
+} FSdCtrl_CapacityType_t;
+
+/* speed class of SD Card */
+typedef enum
+{
+ FSDC_CLASS0 = 0,
+ FSDC_CLASS2,
+ FSDC_CLASS4,
+ FSDC_CLASS6,
+
+ MAX_FSDC_CLASS_TYPE
+} FSdCtrl_ClassType_t;
+
+/**
+ * This typedef contains configuration information for the sd device.
+ */
+typedef struct
+{
+ u32 instanceId; /* Unique ID of device */
+ u32 baseAddress; /* Base address of the device */
+ u32 inputClockHz; /* Input clock frequency */
+ u32 cardDetect; /* Card Detect */
+ u32 writeProtect; /* Write Protect */
+ u32 busWidth; /* Bus Width */
+ u32 dmaIrqNum; /* dma irq number */
+ u32 normalIrqNum; /* normal irq number */
+ u32 errIrqNum; /* error irq number */
+ u8 workMode; /* Work mode for data transfers ,
+ If the mask bit is 0, polling is used ,
+ follow irq enable bits*/
+} FSdCtrl_Config_t;
+
+typedef void (*FtsdCtrl_irqCallback_t)(void *args);
+
+/* irq callback and iput args */
+typedef struct
+{
+ FtsdCtrl_irqCallback_t pDmaDataCallback; /* DMA data interrupt function pointer */
+ void *pDmaDataArgs;
+
+ FtsdCtrl_irqCallback_t pCmdCallback; /* Commond interrupt function pointer */
+ void *pCmdArgs;
+
+ FtsdCtrl_irqCallback_t pErrorCallback; /* Error interrupt function pointer */
+ void *pErrorArgs;
+} FSdCtrl_IrqConfig_t;
+
+typedef struct FtsdCtrl FtsdCtrl_t;
+typedef void (*pFtsdCtrl_delayTimer_t)(ft_base_t delayUs);
+typedef ft_error_t (*pFtsdCtrl_irqWaitCallback_t)(FtsdCtrl_t *FtsdCtrl);
+
+/* ctrl instance of sd */
+struct FtsdCtrl
+{
+ FSdCtrl_Config_t config;
+ u32 isReady; /* Device is initialized and ready */
+ /*************reserved**************/
+ FSdCtrl_VRangeType_t voltageType;
+ FSdCtrl_WRType_t writeReadType;
+ FSdCtrl_CapacityType_t capacityType;
+ FSdCtrl_ClassType_t speedClassType;
+ /*************reserved**************/
+ FSdCtrl_IrqConfig_t irqConfig;
+ pFtsdCtrl_irqWaitCallback_t writeWaitCallback; /* function pointer .Used to determine whether the data transmission is complete*/
+ pFtsdCtrl_irqWaitCallback_t readWaitCallback; /* function pointer .Used to determine whether the data received is complete*/
+ pFtsdCtrl_irqWaitCallback_t cmdWaitCallback; /* function pointer . Used to determine whether the command is complete */
+};
+
+u32 FSdCtrl_PrepareCmdRaw(FT_IN u32 cmdIndex, FT_IN u32 rspType);
+void FSdCtrl_WriteData(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN UINTPTR dataAddr, FT_IN UINTPTR cmdArg, FT_IN u32 blkNum);
+void FSdCtrl_ReadData(FT_INOUT FtsdCtrl_t *pFtsdCtrl,
+ FT_IN UINTPTR dataAddr,
+ FT_IN UINTPTR cardAddr,
+ FT_IN u32 blkNum);
+ft_error_t FSdCtrl_WaitCmdEnd(FT_OUT FtsdCtrl_t *pFtsdCtrl,
+ FT_IN pFtsdCtrl_delayTimer_t pDelayTimer_fun,
+ FT_IN u32 rspType,
+ FT_OUT u32 *cmdRsp);
+ft_error_t FSdCtrl_WaitReadDataEnd(FT_INOUT FtsdCtrl_t *pFtsdCtrl,
+ FT_IN pFtsdCtrl_delayTimer_t pDelayTimer_fun,
+ FT_IN u32 blkNum);
+ft_error_t FSdCtrl_WaitWriteDataEnd(FT_INOUT FtsdCtrl_t *pFtsdCtrl,
+ FT_IN pFtsdCtrl_delayTimer_t pDelayTimer_fun,
+ FT_IN u32 blkNum);
+
+void FSdCtrl_DoCmd(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN u32 cmdIndex, FT_IN u32 rspType, u32 arg);
+void FSdCtrl_DoACmd(FT_INOUT FtsdCtrl_t *pFtsdCtrl,
+ FT_IN u32 cmdIndex,
+ FT_IN u32 rspType,
+ u32 arg);
+void FSdCtrl_NormalIrq(FT_INOUT FtsdCtrl_t *pFtsdCtrl);
+void FSdCtrl_DmaIrq(FT_INOUT FtsdCtrl_t *pFtsdCtrl);
+void FSdCtrl_ErrIrq(FT_INOUT FtsdCtrl_t *pFtsdCtrl);
+bool_t FSdCtrl_CardDetect(FT_INOUT FtsdCtrl_t *pFtsdCtrl);
+
+FSdCtrl_Config_t *FSdCtrl_LookupConfig(u32 instanceId);
+/* This routine performs per device specific initialization of Phytium SDHC.*/
+ft_error_t FsdCtrl_Init(FT_INOUT FtsdCtrl_t *pFtsdCtrl);
+void FSdCtrl_ClkFreqSetup(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN u32 sdClk);
+void FSdCtrl_ResetDma(FT_INOUT FtsdCtrl_t *pFtsdCtrl);
+/* reset sd ctrl during init */
+void FSdCtrl_Reset(FT_INOUT FtsdCtrl_t *pFtsdCtrl, pFtsdCtrl_delayTimer_t fDelayTimer);
+
+/* set irq call backs */
+ft_error_t FSdCtrl_SetHandler(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN FSdCtrl_IrqCallbackSelect_t selectIndex,
+ void *FuncPtr,
+ void *Args);
+
+/* register call-backs to determinate wheather write、read and cmd is complete */
+void FSdCtrl_WriteWaitRegister(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN pFtsdCtrl_irqWaitCallback_t callBack);
+void FSdCtrl_ReadWaitRegister(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN pFtsdCtrl_irqWaitCallback_t callBack);
+void FSdCtrl_CmdWaitRegister(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN pFtsdCtrl_irqWaitCallback_t callBack);
+void FSdCtrl_ErrWaitRegister(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN pFtsdCtrl_irqWaitCallback_t callBack);
+
+/* get irq status */
+u32 FSdCtrl_GetNormalIrqStatus(FT_INOUT FtsdCtrl_t *pFtsdCtrl);
+u32 FSdCtrl_GetDataIrqStatus(FT_INOUT FtsdCtrl_t *pFtsdCtrl);
+u32 FSdCtrl_GetErrorIrqStatus(FT_INOUT FtsdCtrl_t *pFtsdCtrl);
+
+/* enable selected normal irq */
+void FSdCtrl_NormalIrqSet(FtsdCtrl_t *pFtsdCtrl, FT_IN FSdCtrl_NormalIrqSelect_t flgs);
+void FSdCtrl_BdIrqSet(FtsdCtrl_t *pFtsdCtrl, FT_IN FSdCtrl_BdIrqSelect flgs);
+
+#endif //
diff --git a/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_g.c b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_g.c
new file mode 100644
index 0000000000..3492f89049
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_g.c
@@ -0,0 +1,31 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-03-31 14:59:20
+ * @LastEditTime: 2021-05-24 14:34:13
+ * @Description:  This files is for sd ctrl config definition
+ *
+ * @Modify History: * * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_sdctrl.h"
+#include "ft_parameters.h"
+
+/* configs of sd ctrl */
+FSdCtrl_Config_t FSdCtrl_Config[FT_SDC_NUM] =
+ {
+ {
+ .instanceId = FT_SDC_INSTANCE,
+ .baseAddress = FT_SDC_BASEADDR,
+ .inputClockHz = FT_SDC_FREQ,
+ .cardDetect = 1,
+ .writeProtect = 0,
+ .busWidth = 1,
+ .dmaIrqNum = 52,
+ .normalIrqNum = 53,
+ .errIrqNum = 54,
+ .workMode = 0 /*FTSDCTRL_CMD_IRQ_MASK | FTSDCTRL_DATA_WRITE_IRQ_MASK | FTSDCTRL_DATA_READ_IRQ_MASK*/
+ }};
diff --git a/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_hw.c b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_hw.c
new file mode 100644
index 0000000000..83a9c05dde
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_hw.c
@@ -0,0 +1,41 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-03-31 14:59:20
+ * @LastEditTime: 2021-05-25 16:46:46
+ * @Description:  This files is for sd ctrl register-related implementations
+ *
+ * @Modify History: * * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_sdctrl_hw.h"
+#include "ft_sdctrl.h"
+
+#include "ft_io.h"
+#include "ft_types.h"
+#include "ft_assert.h"
+#include "ft_generic_timer.h"
+
+void FSdCtrl_Reset(FT_INOUT FtsdCtrl_t *pFtsdCtrl, pFtsdCtrl_delayTimer_t fDelayTimer)
+{
+ FSdCtrl_Config_t *pConfig;
+ Ft_assertVoid(FT_NULL != pFtsdCtrl);
+
+ pConfig = &pFtsdCtrl->config;
+ /* trigger software reset for 1us */
+ Ft_setBit32(pConfig->baseAddress + SOFTWARE_RESET_REG_OFFSET, SOFTWARE_RESET_SRST);
+ /* Wait for reset is ok */
+ Ft_GenericTimer_UsDelay(1);
+ Ft_clearBit32(pConfig->baseAddress + SOFTWARE_RESET_REG_OFFSET, SOFTWARE_RESET_SRST);
+
+ /* wait dat[0] to be high-lev */
+ while ((!(Ft_in32(pConfig->baseAddress + STATUS_REG) & STATUS_REG_DLSL(1))))
+ {
+ fDelayTimer(1);
+ }
+
+ return;
+}
diff --git a/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_hw.h b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_hw.h
new file mode 100644
index 0000000000..931c3ad7db
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_hw.h
@@ -0,0 +1,210 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-03-31 14:59:20
+ * @LastEditTime: 2021-04-19 16:17:39
+ * @Description:  This files is for sd ctrl register
+ *
+ * @Modify History: * * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef _SDCTRL_HW_H
+#define _SDCTRL_HW_H
+
+#include "ft_sdctrl.h"
+
+/* Register Offset */
+
+#define CONTROLL_SETTING_REG_OFFSET 0x00 /* Controller configuration register */
+#define ARGUMENT_REG_OFFSET 0x04 /* Parameter register */
+#define CMD_SETTING_REG_OFFSET 0x08 /* Command register */
+#define CLOCK_DIV_REG_OFFSET 0x0C /* Clock division register */
+#define SOFTWARE_RESET_REG_OFFSET 0x10 /* Reset control register */
+#define POWER_CONTROLL_REG_OFFSET 0x14 /* Power control register */
+#define TIMEOUT_CMD_REG_OFFSET 0x18 /* cmd Timeout setting register */
+#define TIMEOUT_DATA_REG_OFFSET 0x1C /* Data timeout setting register */
+#define NORMAL_INT_EN_REG_OFFSET 0x20 /* Interrupt Enable Register */
+#define ERROR_INT_EN_REG_OFFSET 0x24 /* error Interrupt Enable Register */
+#define BD_ISR_EN_REG_OFFSET 0x28 /* Data Transfer Interrupt Enable Register */
+#define CAPABILIES_REG_OFFSET 0x2c /* capabilies register */
+#define SD_DRV_REG_OFFSET 0x30 /* SD card driver phase register */
+#define SD_SAMP_REG_OFFSET 0x34 /* SD card sampling phase register */
+#define SD_SEN_REG_OFFSET 0x38 /* Card detection controller */
+#define HDS_AXI_REG_CONF1_OFFSET 0x3c /* AXI boundary configuration register 1 */
+#define DAT_IN_M_RX_BD 0x40 /* SD BD RX address register */
+#define DAT_IN_M_TX_BD 0x60 /* SD BD TX address register */
+#define BLK_CNT_REG 0x80 /* Block reads and writes configuration registers */
+#define HDS_AXI_REG_CONF2 0xa8 /* AXI boundary configuration register 2 */
+#define NORMAL_INT_STATUS_REG 0xc0 /* Interrupt status register */
+#define ERROR_INT_STATUS_REG 0xc4 /* ERROR interrupt register */
+#define BD_ISR_REG 0xc8 /* Data Transfer Interrupt Status Register */
+#define BD_STATUS 0xcc /* BD descriptor register */
+#define STATUS_REG 0xd0 /* state register */
+#define BLOCK 0xd4 /* Block length register */
+#define CMD_RESP_1 0xe0 /* Command response register 1 */
+#define CMD_RESP_2 0xe4 /* Command response register 2 */
+#define CMD_RESP_3 0xe8 /* Command response register 3 */
+#define CMD_RESP_4 0xec /* Command response register 4 */
+
+/* Controller configuration register */
+#define CONTROLL_SETTING_PERMDR(x) ((x & 3) << 8) /* Read operation corresponding to the size of the end selection: 00: small end alignment,01: large end alignment,10: SD protocol mode */
+#define CONTROLL_SETTING_PERMDW(x) ((x & 3) << 10) /* Write operation corresponding to the size of the endian selection: 00: small endian alignment 01: large endian alignment 10: SD protocol mode*/
+
+/* Parameter register */
+#define ARGUMENT_REG(x) (x & 0xffffffff)
+
+/* Command register */
+#define CMD_SETTING_RTS(x) ((x & 3) << 0) /* 0: No response 01: Response byte length 136 10: Response byte length 48 11: Response byte length 48 */
+#define CMD_SETTING_CRCE (1U << 3) /* 0: CRC check is not performed on CMD response 1: CRC check is performed on CMD response */
+#define CMD_SETTING_CICE (1U << 4) /* 0:CMD 响应时,不执行索引检查 1:CMD 响应时,执行索引检查 */
+#define CMD_SETTING_CMDW(x) ((x & 3) << 6)
+#define CMD_SETTING_CMDI(x) ((x & 0x3f) << 8) /* 命令索引 */
+#define CMD_SETTING_TRTY(x) ((x & 3) << 14) /* 10: adtc 指令 ,其它: 读写操作 */
+
+/* 时钟分频寄存器 */
+#define CLOCK_DIV_RE(x) (x & 0xffffffff) /* CLKD-时钟分频系数 SD_frequency= 600M/ (2*(clock_d+1)) */
+
+/* 复位控制寄存器 */
+#define SOFTWARE_RESET_SRST (1U) /* 控制器软复位 */
+#define SOFTWARE_RESET_BDRST (4U) /* DMA BD 清 0 */
+#define SOFTWARE_RESET_CFCLF (8U) /* 卡插入拔出状态触发标志清 0 */
+
+/* cmd 超时设置寄存器 */
+#define TIMEOUT_CMD_REG(x) (x & 0xffffffff) /* command 超时参数 */
+
+/* 数据超时设置寄存器 */
+#define TIMEOUT_DATA_REG(x) (x & 0xffffffff) /* data 超时参数 */
+
+/* 中断使能寄存器 */
+#define NORMAL_INT_EN_ECC 1U /* 命令完成中断使能 */
+#define NORMAL_INT_EN_ECCRCE 2U /* 卡拔出中断使能 */
+#define NORMAL_INT_EN_ECIE (1U << 15) /* 错误中断使能 */
+
+/* error 中断使能寄存器 */
+#define ERROR_INT_EN_CNR (1U << 4) /* Command response error interrupted */
+#define ERROR_INT_EN_CIR (1U << 3) /* 命令索引错误中断使能 */
+#define ERROR_INT_EN_CCRCE (1U << 1) /* 命令 CRC 错误中断使能 */
+#define ERROR_INT_EN_CTE (1U << 0) /* 命令超时中断使能 */
+
+/* 数据传输中断使能寄存器 */
+#define BD_ISR_EN_ETRS (1U << 0) /* DMA 传输完成中断使能 */
+#define BD_ISR_EN_EDTE (1U << 3) /* 数据超时中断使能 */
+#define BD_ISR_EN_ECMDE (1U << 4) /* 命令响应错误中断使能 */
+#define BD_ISR_EN_ETRE (1U << 5) /* 传输错误中断使能 */
+#define BD_ISR_EN_ENRCRCE (1U << 6) /* CRC 校验错误中断使能 */
+#define BD_ISR_EN_EDATFRAXE (1U << 7) /* AXI 总线错误中断使能 */
+#define BD_ISR_EN_RESPE (1U << 8) /* 读 SD 卡操作,AXI BR 通道完成中断 */
+#define BD_ISR_EN_EDAISE (1U << 15) /* DMA 错误中断使能 */
+#define BD_ISR_ALL_MASK (BD_ISR_EN_ETRS | BD_ISR_EN_EDTE | \
+ BD_ISR_EN_ECMDE | BD_ISR_EN_ETRE | \
+ BD_ISR_EN_ENRCRCE | BD_ISR_EN_EDATFRAXE | \
+ BD_ISR_EN_RESPE | BD_ISR_EN_EDAISE)
+
+/* 状态寄存器 */
+#define CAPABILIES_REG(x) (x & 0xffffffff)
+
+/* SD 卡驱动相位寄存器 */
+#define SD_DRV_REG(x) (x & 0xffffffff) /* 卡驱动相位配置参数 */
+
+/* SD 卡采样相位寄存器 */
+#define SD_SAMP_REG(x) (x & 0xffffffff) /* 卡采样相位配置参数 */
+#define SD_SAMP_DEFAULT 11 /* when SD card work in high-speed mode, \
+ the best sampling pharse is needed to \
+ get the correct data */
+#define SD_FRRQ_DIV_DEFAULT 5 /* default freq div */
+#define SD_CLK_FREQ_400KHZ 400000
+#define SD_CLK_FREQ_25MHZ 25000000
+
+/* 卡检测控制器 */
+#define SD_SEN_REG_CREFR (1U << 1) /* 卡拔出时自动释放 AXI 总线选择 */
+#define SD_SEN_REG_CRES (1U << 2) /* CARD 在位状态标志选择 0: 卡在位-0,不在位-1 1: 卡在位-1,不在位-0 */
+#define SD_SEN_REG_DEBNCE(x) ((x & 0xffffff) << 8) /* 去抖时钟分频参数 */
+
+/* AXI 边界配置寄存器 1 */
+#define HDS_AXI_REG_CONF1_AWDOMAIN_HDS_M(x) ((x & 0x3) << 0)
+#define HDS_AXI_REG_CONF1_AWBAR_HDS_M(x) ((x & 0x3) << 2)
+#define HDS_AXI_REG_CONF1_ARSNOOP_HDS_M(x) ((x & 0xf) << 4)
+#define HDS_AXI_REG_CONF1_ARREGION_HDS_M(x) ((x & 0xf) << 8)
+#define HDS_AXI_REG_CONF1_ARDOMAIN_HDS_M(x) ((x & 0x3) << 12)
+#define HDS_AXI_REG_CONF1_ARBAR_HDS_M(x) ((x & 0x3) << 14)
+#define HDS_AXI_REG_CONF1_AWSNOOP_HDS_M(x) ((x & 0x7) << 16)
+#define HDS_AXI_REG_CONF1_AWREGION_HDS_M(x) ((x & 0xF) << 19)
+
+/* SD BD RX 地址寄存器 */
+#define DAT_IN_M_RX_BD_MASK(x) (x & 0xffffffff) /* dma 读卡地址配置:4 个 cycle ,系统低 4B-系统高 4B-SD 低 4B- SD 高 4B */
+
+/* SD BD TX 地址寄存器 */
+#define DAT_IN_M_TX_BD_MASK(x) (x & 0xffffffff) /* dma 写卡地址配置:4 个 cycle ,系统低 4B-系统高 4B-SD 低 4B- SD 高 4B */
+
+/* 块读写配置寄存器 */
+#define BLK_CNT(x) (x & 0xffffffff) /* dma block num setting */
+
+/* AXI 边界配置寄存器 2 */
+#define HDS_AXI_REG_CONF2_D_ARPROT(x) ((x & 0x7) << 27)
+#define HDS_AXI_REG_CONF2_SD_AWPROT(x) ((x & 0x7) << 24)
+#define HDS_AXI_REG_CONF2_SD_ARCACHE_M(x) ((x & 0xf) << 20)
+#define HDS_AXI_REG_CONF2_SD_AWCACHE_M(x) ((x & 0xf) << 16)
+#define HDS_AXI_REG_CONF2_RESERVED(x) ((x & 0x3) << 14)
+#define HDS_AXI_REG_CONF2_HDA_ARPRO(x) ((x & 0x7) << 11)
+#define HDS_AXI_REG_CONF2_HDA_AWPROT(x) ((x & 0x7) << 8)
+#define HDS_AXI_REG_CONF2_HDA_ARCACHE_M(x) ((x & 0xf) << 4)
+#define HDS_AXI_REG_CONF2_HDA_AWCACHE_M(x) ((x & 0xf) << 0)
+
+/* 中断状态寄存器 */
+#define NORMAL_INT_STATUS_EI (1U << 15) /* 命令错误中断 */
+#define NORMAL_INT_STATUS_CR (1U << 1) /* 卡移除中断 */
+#define NORMAL_INT_STATUS_CC 1U /* 命令完成中断 */
+#define NORMAL_INT_STATUS_ALL_MASK (NORMAL_INT_STATUS_EI | NORMAL_INT_STATUS_CR | NORMAL_INT_STATUS_CC)
+
+/* error 中断寄存器 */
+#define ERROR_INT_STATUS_CNR (1U << 4) /* 命令响应错误中断 */
+#define ERROR_INT_STATUS_CIR (1U << 3) /* 命令索引错误中断 */
+#define ERROR_INT_STATUS_CCRCE (1U << 1) /* 命令 CRC 错误中断 */
+#define ERROR_INT_STATUS_CTE 1U /* 命令超时错误中断 */
+#define ERROR_INT_STATUS_ALL_MASK (ERROR_INT_STATUS_CNR | ERROR_INT_STATUS_CIR | ERROR_INT_STATUS_CCRCE | ERROR_INT_STATUS_CTE)
+
+/* 数据传输中断状态寄存器 */
+#define BD_ISR_REG_DAIS (1U << 15) /* DMA 错误中断*/
+#define BD_ISR_REG_RESPE (1U << 8) /* 读 SD 卡操作,AXI BR 通道完成中断*/
+#define BD_ISR_REG_DATFRAX (1U << 7) /* axi 总线强制释放中断*/
+#define BD_ISR_REG_NRCRC (1U << 6) /* 无 CRC 响应中断*/
+#define BD_ISR_REG_TRE (1U << 5) /* CRC 响应错误中断*/
+#define BD_ISR_REG_CMDE (1U << 4) /* 命令响应错误中断*/
+#define BD_ISR_REG_DTE (1U << 3) /* 超时中断*/
+#define BD_ISR_REG_TRS (1U << 0) /* DMA 传输完成中断*/
+
+/* bd 描述符寄存器 */
+#define BD_STATUS_REG(x) (x & 0xffffffff) /* bd 描述符寄存器 */
+
+/* 状态寄存器 */
+#define STATUS_REG_DATMAST(x) ((x & 0xf) << 27) /* data_master 状态机 */
+#define STATUS_REG_CDIF (1U << 26) /* 卡在位标志 */
+#define STATUS_REG_CDRF (1U << 25) /* 卡不在位标志 */
+#define STATUS_REG_CLSL (1U << 24) /* 命令闲信号 */
+#define STATUS_REG_DLSL(x) ((x & 0xf) << 20) /* 线信号 */
+#define STATUS_REG_CDSL (1U << 19) /* 卡检测管脚信号 */
+#define STATUS_REG_CST(x) ((x & 0xf) << 12) /* cmd_host state 状态机 */
+#define STATUS_REG_CSM(x) ((x & 0X1F) << 7)
+#define STATUS_REG_DAT_AVA (1 << 6) /* DAT_AVA 当前命令状态流程运转完 */
+#define STATUS_REG_CRC_VALID (1 << 5)
+#define STATUS_REG_CICMD 1U /* RO 0x0 CMD 总线状态 */
+
+/* 块长度寄存器 */
+#define BLOCK_RGE(x) (x & 0xffffffff) /* 块长度寄存器 */
+
+/* 命令响应寄存器 1 */
+#define CMD_RESP_1_REG(x) (x & 0xffffffff)
+
+/* 命令响应寄存器 2 */
+#define CMD_RESP_2_REG(x) (x & 0xffffffff)
+
+/* 命令响应寄存器 3 */
+#define CMD_RESP_3_REG(x) (x & 0xffffffff)
+
+/* 命令响应寄存器 4 */
+#define CMD_RESP_4_REG(x) (x & 0xffffffff)
+
+#endif // !
diff --git a/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_intr.c b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_intr.c
new file mode 100644
index 0000000000..88bbc41f53
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_intr.c
@@ -0,0 +1,110 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-03-31 14:59:20
+ * @LastEditTime: 2021-05-25 16:46:54
+ * @Description:  This files is for sd ctrl irq handling
+ *
+ * @Modify History: * * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_sdctrl.h"
+#include "ft_sdctrl_hw.h"
+#include "ft_assert.h"
+#include "ft_types.h"
+#include "ft_io.h"
+#include "ft_printf.h"
+#include "ft_debug.h"
+
+#ifndef LOG_LOCAL_LEVEL
+#define LOG_LOCAL_LEVEL FT_LOG_NONE
+#endif
+#define FT_SD_CTRL_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FT_SD_CTRL_DEBUG_TAG, format, ##__VA_ARGS__)
+#define FT_SD_CTRL_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(FT_SD_CTRL_DEBUG_TAG, format, ##__VA_ARGS__)
+#define FT_SD_CTRL_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FT_SD_CTRL_DEBUG_TAG, format, ##__VA_ARGS__)
+
+void FSdCtrl_NormalIrq(FT_INOUT FtsdCtrl_t *pFtsdCtrl)
+{
+ FSdCtrl_Config_t *pConfig;
+ FSdCtrl_IrqConfig_t *irqConfig;
+ Ft_assertVoid(FT_NULL != pFtsdCtrl);
+ pConfig = &pFtsdCtrl->config;
+ irqConfig = &pFtsdCtrl->irqConfig;
+
+ //FT_SD_CTRL_DEBUG_I("enter cmd irq procedure\r\n");
+ if (irqConfig->pCmdCallback)
+ {
+ irqConfig->pCmdCallback(irqConfig->pCmdArgs);
+ }
+
+ /* clear interrupts */
+ Ft_out32(pConfig->baseAddress + NORMAL_INT_STATUS_REG, NORMAL_INT_STATUS_ALL_MASK);
+ Ft_out32(pConfig->baseAddress + NORMAL_INT_STATUS_REG, 0);
+}
+
+void FSdCtrl_DmaIrq(FT_INOUT FtsdCtrl_t *pFtsdCtrl)
+{
+ FSdCtrl_Config_t *pConfig;
+ FSdCtrl_IrqConfig_t *irqConfig;
+ Ft_assertVoid(FT_NULL != pFtsdCtrl);
+ pConfig = &pFtsdCtrl->config;
+ irqConfig = &pFtsdCtrl->irqConfig;
+
+ if (irqConfig->pDmaDataCallback)
+ {
+ irqConfig->pDmaDataCallback(irqConfig->pDmaDataArgs);
+ }
+
+ /* clear interrupts */
+ Ft_out32(pConfig->baseAddress + BD_ISR_REG, BD_ISR_ALL_MASK);
+ Ft_out32(pConfig->baseAddress + BD_ISR_REG, 0);
+}
+
+void FSdCtrl_ErrIrq(FT_INOUT FtsdCtrl_t *pFtsdCtrl)
+{
+ FSdCtrl_Config_t *pConfig;
+ FSdCtrl_IrqConfig_t *irqConfig;
+ Ft_assertVoid(FT_NULL != pFtsdCtrl);
+ pConfig = &pFtsdCtrl->config;
+ irqConfig = &pFtsdCtrl->irqConfig;
+
+ if (irqConfig->pErrorCallback)
+ {
+ irqConfig->pErrorCallback(irqConfig->pErrorArgs);
+ }
+
+ /* clear interrupts */
+ Ft_out32(pConfig->baseAddress + ERROR_INT_STATUS_REG, ERROR_INT_STATUS_ALL_MASK);
+ Ft_out32(pConfig->baseAddress + ERROR_INT_STATUS_REG, 0);
+}
+
+ft_error_t FSdCtrl_SetHandler(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN FSdCtrl_IrqCallbackSelect_t selectIndex,
+ void *FuncPtr, void *Args)
+{
+ Ft_assertNonvoid(pFtsdCtrl != NULL);
+ Ft_assertNonvoid(FuncPtr != NULL);
+ Ft_assertNonvoid(pFtsdCtrl->isReady == FT_COMPONENT_IS_READLY);
+
+ switch (selectIndex)
+ {
+ case FTSDCTRL_DMADATAIRQID:
+ pFtsdCtrl->irqConfig.pDmaDataCallback = FuncPtr;
+ pFtsdCtrl->irqConfig.pDmaDataArgs = Args;
+ break;
+ case FTSDCTRL_CMDIRQID:
+ pFtsdCtrl->irqConfig.pCmdCallback = FuncPtr;
+ pFtsdCtrl->irqConfig.pCmdArgs = Args;
+ break;
+ case FTSDCTRL_ERRORIRQID:
+ pFtsdCtrl->irqConfig.pErrorCallback = FuncPtr;
+ pFtsdCtrl->irqConfig.pErrorArgs = Args;
+ break;
+ default:
+ return FTSDC_FAILURE;
+ }
+
+ return FTSDC_SUCCESS;
+}
diff --git a/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_option.c b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_option.c
new file mode 100644
index 0000000000..0799b0be4c
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_option.c
@@ -0,0 +1,61 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-03-31 14:59:20
+ * @LastEditTime: 2021-05-25 16:47:05
+ * @Description:  This files is for sd ctrl option setting
+ *
+ * @Modify History: * * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_sdctrl.h"
+#include "ft_sdctrl_hw.h"
+#include "ft_types.h"
+#include "ft_io.h"
+#include "ft_printf.h"
+#include "ft_assert.h"
+
+void FSdCtrl_NormalIrqSet(FtsdCtrl_t *pFtsdCtrl, FT_IN FSdCtrl_NormalIrqSelect_t flgs)
+{
+ FSdCtrl_Config_t *pConfig;
+ u32 regValue;
+ Ft_assertVoid(FT_NULL != pFtsdCtrl);
+ pConfig = &pFtsdCtrl->config;
+
+ /* */
+ regValue = ((flgs & NORMAL_IRQ_CC) ? NORMAL_INT_EN_ECC : 0) | ((flgs & NORMAL_IRQ_CR) ? NORMAL_INT_EN_ECCRCE : 0) |
+ ((flgs & NORMAL_IRQ_EI) ? NORMAL_INT_EN_ECIE : 0);
+
+ Ft_out32(pConfig->baseAddress + NORMAL_INT_EN_REG_OFFSET, regValue);
+}
+
+void FsdCtrl_errorIrqSet(FtsdCtrl_t *pFtsdCtrl, FT_IN FSdCtrl_ErrorIrqSelect_t flgs)
+{
+ FSdCtrl_Config_t *pConfig;
+ u32 regValue;
+ Ft_assertVoid(FT_NULL != pFtsdCtrl);
+ pConfig = &pFtsdCtrl->config;
+
+ regValue = ((flgs & ERROR_IRQ_CTE) ? ERROR_INT_EN_CTE : 0) | ((flgs & ERROR_IRQ_CCRCE) ? ERROR_INT_EN_CCRCE : 0) |
+ ((flgs & ERROR_IRQ_CIR) ? ERROR_INT_EN_CIR : 0) | ((flgs & ERROR_IRQ_CNR) ? ERROR_INT_EN_CNR : 0);
+
+ Ft_out32(pConfig->baseAddress + ERROR_INT_EN_REG_OFFSET, regValue);
+}
+
+void FSdCtrl_BdIrqSet(FtsdCtrl_t *pFtsdCtrl, FT_IN FSdCtrl_BdIrqSelect flgs)
+{
+ FSdCtrl_Config_t *pConfig;
+ u32 regValue;
+ Ft_assertVoid(FT_NULL != pFtsdCtrl);
+ pConfig = &pFtsdCtrl->config;
+
+ regValue = ((flgs & BD_IRQ_TRS) ? BD_ISR_EN_ETRS : 0) | ((flgs & BD_IRQ_DTE) ? BD_ISR_EN_EDTE : 0) |
+ ((flgs & BD_IRQ_CMDE) ? BD_ISR_EN_ECMDE : 0) | ((flgs & BD_IRQ_TRE) ? BD_ISR_EN_ETRE : 0) |
+ ((flgs & BD_IRQ_NRCRC) ? BD_ISR_EN_ENRCRCE : 0) | ((flgs & BD_IRQ_DATFRAX) ? BD_ISR_EN_EDATFRAXE : 0) |
+ ((flgs & BD_IRQ_RESPE) ? BD_ISR_EN_RESPE : 0) | ((flgs & BD_IRQ_DAIS) ? BD_ISR_EN_EDAISE : 0);
+
+ Ft_out32(pConfig->baseAddress + BD_ISR_EN_REG_OFFSET, regValue);
+}
diff --git a/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_sinit.c b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_sinit.c
new file mode 100644
index 0000000000..47827413d2
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_sinit.c
@@ -0,0 +1,33 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-03-31 14:59:20
+ * @LastEditTime: 2021-05-25 16:47:14
+ * @Description:  This files is for sd ctrl static initialization
+ *
+ * @Modify History: * * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_sdctrl.h"
+#include "ft_parameters.h"
+
+extern FSdCtrl_Config_t FSdCtrl_Config[FT_SDC_NUM];
+
+FSdCtrl_Config_t *FSdCtrl_LookupConfig(u32 instanceId)
+{
+ FSdCtrl_Config_t *CfgPtr = NULL;
+ u32 Index;
+ for (Index = 0; Index < (u32)FT_GMAC_INSTANCES_NUM; Index++)
+ {
+ if (FSdCtrl_Config[Index].instanceId == instanceId)
+ {
+ CfgPtr = &FSdCtrl_Config[Index];
+ break;
+ }
+ }
+
+ return (FSdCtrl_Config_t *)CfgPtr;
+}
diff --git a/bsp/ft2004/libraries/bsp/ft_spi/ft_spi.c b/bsp/ft2004/libraries/bsp/ft_spi/ft_spi.c
new file mode 100644
index 0000000000..cc2a74a045
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_spi/ft_spi.c
@@ -0,0 +1,192 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-25 14:00:25
+ * @LastEditTime: 2021-05-24 14:34:28
+ * @Description:  This files is for
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_assert.h"
+#include "ft_spi.h"
+#include "ft_spi_hw.h"
+#include "ft_generic_timer.h"
+#include "ft_gpio.h"
+
+void FSpi_DumpAllStatus(FT_IN FSpi_Ctrl_t *pCtrl, FT_IN char *tag)
+{
+ FT_SPI_DEBUG_I("***%s status******\r\n", tag);
+ FT_SPI_DEBUG_I("busy: %d", SPI_STATUS_REG(pCtrl)->val.Busy);
+ FT_SPI_DEBUG_I("tx fifo not empty: %d", SPI_STATUS_REG(pCtrl)->val.Tfnf);
+ FT_SPI_DEBUG_I("tx fifo empty: %d", SPI_STATUS_REG(pCtrl)->val.Tfe);
+ FT_SPI_DEBUG_I("rx fifo not empty: %d", SPI_STATUS_REG(pCtrl)->val.Rfne);
+ FT_SPI_DEBUG_I("rx fifo full: %d", SPI_STATUS_REG(pCtrl)->val.Rff);
+ FT_SPI_DEBUG_I("trans error: %d", SPI_STATUS_REG(pCtrl)->val.Txe);
+ FT_SPI_DEBUG_I("trans conflict error: %d", SPI_STATUS_REG(pCtrl)->val.Dcol);
+}
+
+u32 FSpi_ReadWriteByte(FT_INOUT FSpi_Ctrl_t *pCtrl, FT_IN u8 TxData,
+ FT_OUT u8 *pRxData)
+{
+ u32 Retry = 0;
+ u32 Ret = ERR_SPI_OK;
+ u16 RxData;
+
+ if (!pCtrl->IsReady)
+ {
+ return ERR_SPI_NOT_READY;
+ }
+
+ while (FSPI_TX_FIFO_NOT_EMPTY(pCtrl))
+ {
+ //Ft_GenericTimer_UsDelay(2);
+ if ((Retry++) > SPI_TIMEOUT)
+ {
+ Ret = ERR_SPI_TX_TIMEOUT;
+ goto __EXIT;
+ }
+ }
+ FSPI_WRITE_DATA(pCtrl, (u16)TxData);
+
+ Retry = 0;
+
+ while (FSPI_RX_FIFO_EMPTY(pCtrl))
+ {
+ //Ft_GenericTimer_UsDelay(2);
+ if ((Retry++) > SPI_TIMEOUT)
+ {
+ Ret = ERR_SPI_RX_TIMEOUT;
+ goto __EXIT;
+ }
+ }
+ RxData = FSPI_READ_DATA(pCtrl);
+
+ if (pRxData)
+ {
+ *pRxData = (u8)RxData;
+ }
+
+__EXIT:
+ return Ret;
+}
+
+u32 FSpi_Init(FT_INOUT FSpi_Ctrl_t *pCtrl)
+{
+ u32 Ret = ERR_SPI_OK;
+
+ FSPI_DISABLE(pCtrl);
+
+ /* config spi ctrl register */
+ SPI_CTRL0_REG(pCtrl)->val.Dfs = SPI_DFS_DEFAULT;
+ SPI_CTRL0_REG(pCtrl)->val.Frf = SPI_FRF_DEFAULT;
+
+ if (SPI_CTRL_CPHA_1EDGE == pCtrl->Config.Cpha)
+ {
+ SPI_CTRL0_REG(pCtrl)->val.Scph = SPI_SCPH_SW_CLK_AT_DATA_BEG;
+ }
+ else if (SPI_CTRL_CPHA_2EDGE == pCtrl->Config.Cpha)
+ {
+ SPI_CTRL0_REG(pCtrl)->val.Scph = SPI_SCPH_SW_CLK_AT_DATA_MID;
+ }
+ else
+ {
+ Ft_assertNoneReturn(0);
+ }
+
+ if (SPI_CTRL_CPOL_LOW == pCtrl->Config.Cpol)
+ {
+ SPI_CTRL0_REG(pCtrl)->val.Scpol = SPI_SCPOL_NOT_ACT_LOW;
+ }
+ else if (SPI_CTRL_CPOL_HIGH == pCtrl->Config.Cpol)
+ {
+ SPI_CTRL0_REG(pCtrl)->val.Scpol = SPI_SCPOL_NOT_ACT_HIGH;
+ }
+ else
+ {
+ Ft_assertNoneReturn(0);
+ }
+
+ SPI_CTRL0_REG(pCtrl)->val.Tmod = SPI_TMOD_TX_RX_MODE;
+ SPI_CTRL0_REG(pCtrl)->val.SlvOE = SPI_SLV_OE_DISABLE;
+ SPI_CTRL0_REG(pCtrl)->val.Srl = SPI_SRL_NORMAL_MODE;
+ SPI_CTRL0_REG(pCtrl)->val.Cfs = SPI_CFS_DEFAULT;
+
+ /* config spi clock */
+ FSPI_SET_BAUDR(pCtrl, pCtrl->Config.BaudRDiv);
+
+ /* config rx and tx fifo, fifo depth to trigger intr */
+ SPI_TXFTL_REG(pCtrl)->val.Tft = 0;
+ SPI_RXFTL_REG(pCtrl)->val.Rft = 0;
+ SPI_TXFL_REG(pCtrl)->val.Txtfl = 0;
+ SPI_RXFL_REG(pCtrl)->val.Rxtfl = 0;
+
+ SPI_RXSAMPLE_DLY_REG(pCtrl)->val.Rsd = SPI_DEFAULT_RSD;
+
+ FSPI_ENABLE(pCtrl);
+
+ /* set spi ready flag */
+ if (ERR_SPI_OK == Ret)
+ {
+ pCtrl->IsReady = TRUE;
+ }
+
+ return Ret;
+}
+
+static void FSpi_ToggleCSPin(FT_INOUT FSpi_Ctrl_t *pCtrl, FT_IN FSpi_DevId_t DevId,
+ FT_IN bool_t select)
+{
+ u32 setVal = ((TRUE == select) ? GPIO_OFF : GPIO_ON);
+
+ Ft_assertNoneReturn(NULL != pCtrl);
+
+ if (FGpio_ReadPinA(GPIO_CTRL_ID_1, pCtrl->CsPin) != setVal)
+ {
+ FGpio_WritePinA(GPIO_CTRL_ID_1, pCtrl->CsPin, setVal);
+ }
+
+ Ft_GenericTimer_UsDelay(10);
+ return;
+}
+
+void FSpi_SelectSlave(FT_INOUT FSpi_Ctrl_t *pCtrl, FT_IN FSpi_DevId_t DevId,
+ FT_IN bool_t select)
+{
+ FSpi_SeReg_t *pSelReg;
+ u32 setVal = ((TRUE == select) ? SPI_SE_SELECTED : SPI_SE_UNSELECTED);
+
+ FSPI_DISABLE(pCtrl);
+ /* enable or disable specific spi slave device */
+ pSelReg = SPI_SE_REG(pCtrl);
+ switch (DevId)
+ {
+ case SPI_DEV_ID_0:
+ pSelReg->val.SelSlave_0 = setVal;
+ break;
+ case SPI_DEV_ID_1:
+ pSelReg->val.SelSlave_1 = setVal;
+ Ft_assertNoneReturn(0);
+ break;
+ case SPI_DEV_ID_2:
+ pSelReg->val.SelSlave_2 = setVal;
+ Ft_assertNoneReturn(0);
+ break;
+ case SPI_DEV_ID_3:
+ pSelReg->val.SelSlave_3 = setVal;
+ Ft_assertNoneReturn(0);
+ break;
+ default:
+ Ft_assertNoneReturn(0);
+ break;
+ }
+
+ FSpi_ToggleCSPin(pCtrl, DevId, select);
+ FSPI_ENABLE(pCtrl);
+
+ return;
+}
diff --git a/bsp/ft2004/libraries/bsp/ft_spi/ft_spi.h b/bsp/ft2004/libraries/bsp/ft_spi/ft_spi.h
new file mode 100644
index 0000000000..15893f0eaa
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_spi/ft_spi.h
@@ -0,0 +1,95 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-25 13:59:05
+ * @LastEditTime: 2021-04-30 16:11:46
+ * @Description:  This files is for
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef FT_BSP_SPI_H
+#define FT_BSP_SPI_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "ft_types.h"
+#include "ft_spi_hw.h"
+#include "ft_error_code.h"
+#include "ft_debug.h"
+
+ typedef struct
+ {
+ u8 WorkMode;
+#define SPI_CTRL_MASTER_MODE (u8)0x0
+#define SPI_CTRL_SLAVE_MODE (u8)0x1
+ u8 DevAddrLen;
+#define SPI_3_BYTE_ADDR (u8)0x3
+#define SPI_4_BYTE_ADDR (u8)0x4
+ u8 Cpol;
+#define SPI_CTRL_CPOL_LOW (u8)0x0
+#define SPI_CTRL_CPOL_HIGH (u8)0x1
+ u8 Cpha;
+#define SPI_CTRL_CPHA_1EDGE (u8)0x0
+#define SPI_CTRL_CPHA_2EDGE (u8)0x1
+ u8 DevAddr[4];
+ u32 BaudRDiv;
+ } FSpi_Conf_t;
+
+ typedef struct
+ {
+ FSpi_Conf_t Config;
+ FSpi_CtrlId_t CtrlId;
+ FSpi_DevId_t DevId; /* support only one slave at the moment */
+ bool_t IsReady;
+ u16 CsPin; /* cs pin in gpio group A */
+ } FSpi_Ctrl_t;
+
+/* misc marco */
+#define SPI_TIMEOUT 5000
+#define SPI_DUMMY_TX_DATA 0xFF
+
+/* ctrl member shortcut */
+#define FSPI_DEV_ADDR_LEN(pCtrl) (pCtrl->Config.DevAddrLen)
+#define FSPI_IS_3_BYTE_ADDR(pCtrl) (SPI_3_BYTE_ADDR == FSPI_DEV_ADDR_LEN(pCtrl))
+#define FSPI_DEV_ADDR(pCtrl) (pCtrl->Config.DevAddr)
+
+/* define error code */
+#define ERR_SPI_OK ERR_SUCCESS
+#define ERR_SPI_GENERAL FT_CODE_ERR(ERR_MODE_SPI, 0, 1)
+#define ERR_SPI_NOT_READY FT_CODE_ERR(ERR_MODE_SPI, 0, 2)
+#define ERR_SPI_TX_TIMEOUT FT_CODE_ERR(ERR_MODE_SPI, 0, 3)
+#define ERR_SPI_RX_TIMEOUT FT_CODE_ERR(ERR_MODE_SPI, 0, 4)
+
+/* spi flash error code */
+#define ERR_SPI_WAIT_TIMEOUT FT_CODE_ERR(ERR_MODE_SPI, 1, 1)
+
+/* define debug utilities */
+#define FT_SPI_DEBUG_TAG "FT_SPI"
+#define FT_SPI_ENABLE_DEBUG
+#define FT_SPI_ERROR(format, ...) FT_DEBUG_PRINT_E(FT_SPI_DEBUG_TAG, format, ##__VA_ARGS__)
+#ifdef FT_SPI_ENABLE_DEBUG
+#define FT_SPI_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FT_SPI_DEBUG_TAG, format, ##__VA_ARGS__)
+#define FT_SPI_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FT_SPI_DEBUG_TAG, format, ##__VA_ARGS__)
+#else
+#define FT_SPI_DEBUG_I(format, ...)
+#define FT_SPI_DEBUG_W(format, ...)
+#endif
+
+ u32 FSpi_Init(FT_INOUT FSpi_Ctrl_t *pCtrl);
+ u32 FSpi_ReadWriteByte(FT_INOUT FSpi_Ctrl_t *pCtrl, FT_IN u8 TxData,
+ FT_OUT u8 *pRxData);
+ void FSpi_SelectSlave(FT_INOUT FSpi_Ctrl_t *pCtrl, FT_IN FSpi_DevId_t DevId,
+ FT_IN bool_t select);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/bsp/ft2004/libraries/bsp/ft_spi/ft_spi_hw.h b/bsp/ft2004/libraries/bsp/ft_spi/ft_spi_hw.h
new file mode 100644
index 0000000000..b4872e0de3
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_spi/ft_spi_hw.h
@@ -0,0 +1,330 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-25 13:59:44
+ * @LastEditTime: 2021-04-30 15:42:30
+ * @Description:  This files is for
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+#ifndef FT_BSP_SPI_HW_H
+#define FT_BSP_SPI_HW_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "ft_types.h"
+
+/* offset map of SPI register */
+#define SPI_CTRL_R0 0x00 //Ctrl register 0
+#define SPI_CTRL_R1 0x04 //Ctrl register 1
+#define SPI_SSI_EN_R 0x08 //SPI enable register
+#define SPI_MW_CR 0x0c //Microwire ctrl register
+#define SPI_SE_R 0x10 //Slave enable register
+#define SPI_BAUD_R 0x14 //Baudrate set register
+#define SPI_TXFTL_R 0x18 //Tx threshold register
+#define SPI_RXFTL_R 0x1c //Rx threshold register
+#define SPI_TXFL_R 0x20 //Tx level register
+#define SPI_RXFL_R 0x24 //Rx level register
+#define SPI_S_R 0x28 //Status register
+#define SPI_IM_R 0x2c //Intr mask register
+#define SPI_RIS_R 0x34 //Intr status register
+#define SPI_TXOI_CR 0x38 //TX FIFO overflow intr clear register
+#define SPI_RXOI_CR 0x3c //RX FIFO overflow intr clear register
+#define SPI_RXUI_CR 0x40 //TX FIFO underflow intr clear register
+#define SPI_MSTI_CR 0x44 //Multi slave intr clear register
+#define SPI_IC_R 0x48 //Intr clear register
+#define SPI_DMA_CR 0x4c //DMA ctrl register
+#define SPI_DMA_TDL_R 0x50 //DMA TX Data level register
+#define SPI_DMA_RDL_R 0x54 //DMA RX Data level register
+#define SPI_ID_R 0x58 //Identification register
+#define SPI_D_R 0xec //Data register
+#define SPI_RX_SAMPLE_DLY 0xfc //RX Data delay register
+
+ typedef enum
+ {
+ SPI_CTRL_ID_0 = 0,
+ SPI_CTRL_ID_1,
+
+ NUM_OF_SPI_CTRL,
+ } FSpi_CtrlId_t;
+
+ typedef enum
+ {
+ SPI_DEV_ID_0 = 0,
+ SPI_DEV_ID_1,
+ SPI_DEV_ID_2,
+ SPI_DEV_ID_3,
+
+ NUM_OF_SPI_DEV,
+ } FSpi_DevId_t;
+
+ /* base address of SPI register */
+ const static u32 g_SpiBaseAddr[NUM_OF_SPI_CTRL] = {0x2800c000, 0x28013000};
+
+ typedef union
+ {
+ u32 data;
+ struct
+ {
+ u32 Dfs : 4; /* 3:0, select data length */
+#define SPI_DFS_DEFAULT 0x7
+ u32 Frf : 2; /* 5:4, selcet trans mode */
+#define SPI_FRF_DEFAULT 0x0
+ u32 Scph : 1; /* 6, serial clock phase */
+#define SPI_SCPH_SW_CLK_AT_DATA_MID 0x0 /* second edge */
+#define SPI_SCPH_SW_CLK_AT_DATA_BEG 0x1 /* first edge */
+ u32 Scpol : 1; /* 7, serial clock Polarity */
+#define SPI_SCPOL_NOT_ACT_LOW 0x0
+#define SPI_SCPOL_NOT_ACT_HIGH 0x1
+ u32 Tmod : 2; /* 9:8, ctrl trans mode, indicate if tx rx data is valid */
+#define SPI_TMOD_TX_RX_MODE 0x0
+#define SPI_TMOD_TX_MODE 0x1
+#define SPI_TMOD_RX_MODE 0x2
+#define SPI_TMOD_EEPROM_MODE 0x3
+ u32 SlvOE : 1; /* 10, enable slave tx logic */
+#define SPI_SLV_OE_ENABLE 0x0
+#define SPI_SLV_OE_DISABLE 0x1
+ u32 Srl : 1; /* 11, shift register loopback */
+#define SPI_SRL_NORMAL_MODE 0x0
+#define SPI_SRL_TEST_MODE 0x1
+ u32 Cfs : 4; /* 15:12, ctrl data size, applied in Microwire mode */
+#define SPI_CFS_DEFAULT 0x0
+ u32 Reserve : 16;
+ } val;
+ } FSpi_CtrlReg0_t;
+
+ typedef union
+ {
+ u32 data;
+ struct
+ {
+ u32 ndf : 16; /* 15:0 valid when TMOD = 10, TMOD = 11 */
+#define SPI_NDF_DEFAULT 16
+ u32 Reserve : 16;
+ } val;
+ } FSpi_CtrlReg1_t;
+
+ typedef struct
+ {
+ u32 CPOL;
+ u32 CPHA;
+ } FSpi_ClockMode_t;
+
+ static const FSpi_ClockMode_t g_FSpi_ClockMode[4] =
+ {
+ {.CPOL = SPI_SCPOL_NOT_ACT_LOW, .CPHA = SPI_SCPH_SW_CLK_AT_DATA_BEG}, /* low level logic, sample at rising edge, shift at falling edge */
+ {.CPOL = SPI_SCPOL_NOT_ACT_LOW, .CPHA = SPI_SCPH_SW_CLK_AT_DATA_MID}, /* low level logic, sample at falling edge, shift at rising edge */
+ {.CPOL = SPI_SCPOL_NOT_ACT_HIGH, .CPHA = SPI_SCPH_SW_CLK_AT_DATA_MID}, /* high level logic, sample at falling edge, shift at rising edge */
+ {.CPOL = SPI_SCPOL_NOT_ACT_HIGH, .CPHA = SPI_SCPH_SW_CLK_AT_DATA_BEG}, /* high level logic, sample at rising edge, shift at falling edge */
+ };
+
+ typedef union
+ {
+ u32 data;
+ struct
+ {
+ u32 SsiEn : 1; /* 0, enable or disable all SPI op */
+ u32 Reserve : 31;
+ } val;
+ } FSpi_SsiEnReg_t;
+
+ typedef union
+ {
+ u32 data;
+ struct
+ {
+ u32 MwMod : 1; /* 0 microwire trans mode */
+#define SPI_MWMODE_NO_CONTINUOUES 0
+#define SPI_MWMODE_CONTINUOUES 1
+ u32 Mdd : 1; /* 1 microwire ctrl bit */
+#define SPI_MWMDD_RXFROM_EXT_DEV 0
+#define SPI_MWMDD_TXTO_EXT_DEV 1
+ u32 Mhs : 1; /* 2 microwire handshake */
+#define SPI_MWMHS_DISABLE 0
+#define SPI_MWMHS_ENABLE 1
+ u32 Reserve : 29;
+ } val;
+ } FSpi_MwcrReg_t;
+
+ typedef union
+ {
+ u32 data;
+ struct
+ {
+ u32 SelSlave_0 : 1; /* 3:0, select specifc slave device */
+ u32 SelSlave_1 : 1;
+ u32 SelSlave_2 : 1;
+ u32 SelSlave_3 : 1;
+#define SPI_SE_SELECTED 0x1
+#define SPI_SE_UNSELECTED 0x0
+ u32 Reserve : 28;
+ } val;
+ } FSpi_SeReg_t;
+
+ typedef union
+ {
+ u32 data;
+ struct
+ {
+ u32 Sckdv : 16; /* 15:0, SSI clk divider, must be times of 2 */
+#define SPI_SCKDV_MIN (2)
+#define SPI_SCKDV_4 (4)
+#define SPI_SCKDV_8 (8)
+#define SPI_SCKDV_16 (16)
+#define SPI_SCKDV_32 (20)
+#define SPI_SCKDV_64 (28)
+#define SPI_SCKDV_128 (128)
+#define SPI_SCKDV_256 (256)
+#define SPI_SCKDV_1024 (1024)
+#define SPI_SCKDV_4096 (4096)
+#define SPI_SCKDV_12800 (12800)
+#define SPI_SCKDV_56800 (56800)
+#define SPI_SCKDV_MAX (65534)
+ u32 Reserve : 16;
+ } val;
+ } FSpi_BaudrReg_t;
+
+ typedef union
+ {
+ u32 data;
+ struct
+ {
+ u32 Tft : 8; /* 7:0, TX FIFO threshold */
+ u32 Reserve : 24;
+ } val;
+
+ } FSpi_TxFtlrReg_t;
+
+ typedef union
+ {
+ u32 data;
+ struct
+ {
+ u32 Rft : 8; /* 7:0, RX FIFO threshold */
+ u32 Reserve : 24;
+ } val;
+
+ } FSpi_RxFtlrReg_t;
+
+ typedef union
+ {
+ u32 data;
+ struct
+ {
+ u32 Txtfl : 8; /* 7:0, TX FIFO level, num of valid num */
+ u32 Reserve : 24;
+ } val;
+
+ } FSpi_TxFlrReg_t;
+
+ typedef union
+ {
+ u32 data;
+ struct
+ {
+ u32 Rxtfl : 8; /* 7:0, RX FIFO level, num of valid num */
+ u32 Reserve : 24;
+ } val;
+
+ } FSpi_RxFlrReg_t;
+
+ typedef union
+ {
+ u32 data;
+ struct
+ {
+ u32 Busy : 1; /* 0, SPI bus busy bit */
+ u32 Tfnf : 1; /* 1, tx FIFO not empty */
+#define SPI_TX_FIFO_FULL 0x0
+#define SPI_TX_FIFO_NOT_FULL 0x1
+ u32 Tfe : 1; /* 2, tx FIFO empty */
+#define SPI_TX_FIFO_NOT_EMPTY 0x0
+#define SPI_TX_FIFO_EMPTY 0x1
+ u32 Rfne : 1; /* 3, rx FIFO not emptu */
+#define SPI_RX_FIFO_EMPTY 0x0
+#define SPI_RX_FIFO_NOT_EMPTY 0x1
+ u32 Rff : 1; /* 4, rx FIFO full */
+#define SPI_RX_FIFO_NOT_FULL 0x0
+#define SPI_RX_FIFO_FULL 0x1
+ u32 Txe : 1; /* 5, trans error */
+#define SPI_TX_NO_ERR 0x0
+#define SPI_TX_ERR 0x1
+ u32 Dcol : 1; /* 6, trans conflict error */
+#define SPI_TX_NO_COLERR 0x0
+#define SPI_TX_COLERR 0x1
+ u32 Reserve : 25;
+ } val;
+ } FSpi_StatusReg_t; /* Read-Only */
+
+ typedef union
+ {
+ u32 IdCode : 32;
+ } FSpi_IDReg_t;
+
+ typedef union
+ {
+ u32 data;
+ struct
+ {
+ u32 Dr : 16; /* 15:0, RX and TX fifo */
+#define SPI_8BIT_MASK 0xFF
+#define SPI_16BIT_MASK 0xFFFF
+ u32 Reserve : 16;
+ } val;
+ } FSpi_DataReg_t;
+
+ typedef union
+ {
+ u32 data;
+ struct
+ {
+ u32 Rsd : 8; /* 7:0, RX data delay */
+#define SPI_DEFAULT_RSD 0x6
+ u32 Reserve : 24;
+ } val;
+ } FSpi_RxSampleDlyReg_t;
+
+#define SPI_CTL_ID(pCtrl) ((pCtrl)->CtrlId)
+#define SPI_BASE_ADDR(pCtrl) (g_SpiBaseAddr[SPI_CTL_ID(pCtrl)])
+
+/* select slave device */
+#define SPI_SE_REG(pCtrl) ((FSpi_SeReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_SE_R))
+/* set speed */
+#define SPI_BAUDR_REG(pCtrl) ((FSpi_BaudrReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_BAUD_R))
+#define FSPI_SET_BAUDR(pCtrl, div) (SPI_BAUDR_REG(pCtrl)->val.Sckdv = (div))
+#define FSPI_GET_BAUDR(pCtrl) (SPI_BAUDR_REG(pCtrl)->val.Sckdv)
+/* check status */
+#define SPI_STATUS_REG(pCtrl) ((FSpi_StatusReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_S_R))
+#define FSPI_TX_FIFO_NOT_EMPTY(pCtrl) (SPI_TX_FIFO_NOT_EMPTY == (SPI_STATUS_REG(pCtrl)->val.Tfe))
+#define FSPI_RX_FIFO_EMPTY(pCtrl) (SPI_RX_FIFO_EMPTY == (SPI_STATUS_REG(pCtrl)->val.Rfne))
+/* enable/disable spi bus */
+#define SPI_SSIEN_REG(pCtrl) ((FSpi_SsiEnReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_SSI_EN_R))
+#define FSPI_ENABLE(pCtrl) (SPI_SSIEN_REG(pCtrl)->val.SsiEn = 1)
+#define FSPI_DISABLE(pCtrl) (SPI_SSIEN_REG(pCtrl)->val.SsiEn = 0)
+/* shortcut to access register */
+#define SPI_CTRL0_REG(pCtrl) ((FSpi_CtrlReg0_t *)(SPI_BASE_ADDR(pCtrl) + SPI_CTRL_R0))
+#define SPI_CTRL1_REG(pCtrl) ((FSpi_CtrlReg1_t *)(SPI_BASE_ADDR(pCtrl) + SPI_CTRL_R1))
+#define SPI_TXFTL_REG(pCtrl) ((FSpi_TxFtlrReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_TXFTL_R))
+#define SPI_RXFTL_REG(pCtrl) ((FSpi_RxFtlrReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_RXFTL_R))
+#define SPI_TXFL_REG(pCtrl) ((FSpi_TxFlrReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_TXFL_R))
+#define SPI_RXFL_REG(pCtrl) ((FSpi_RxFlrReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_RXFL_R))
+#define SPI_ID_REG(pCtrl) ((FSpi_IDReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_ID_R))
+#define FSPI_GET_ID(pCtrl) (SPI_ID_REG(pCtrl)->IdCode)
+#define SPI_DATA_REG(pCtrl) ((FSpi_DataReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_D_R))
+#define FSPI_READ_DATA(pCtrl) (u16)(SPI_DATA_REG(pCtrl)->val.Dr)
+#define FSPI_WRITE_DATA(pCtrl, dat) (SPI_DATA_REG(pCtrl)->val.Dr = (u16)(dat))
+#define SPI_RXSAMPLE_DLY_REG(pCtrl) ((FSpi_RxSampleDlyReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_RX_SAMPLE_DLY))
+#define SPI_MWCTRL_REG(pCtrl) ((FSpi_MwcrReg_t *)SPI_BASE_ADDR(pCtrl) + SPI_MW_CR)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/bsp/ft2004/libraries/bsp/ft_spi/ft_spi_irq.c b/bsp/ft2004/libraries/bsp/ft_spi/ft_spi_irq.c
new file mode 100644
index 0000000000..a3a0b7a429
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_spi/ft_spi_irq.c
@@ -0,0 +1,13 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-25 14:00:39
+ * @LastEditTime: 2021-04-25 14:00:39
+ * @Description:  This files is for
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
diff --git a/bsp/ft2004/libraries/bsp/ft_uart/ft_uart.c b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart.c
new file mode 100644
index 0000000000..a72c66841e
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart.c
@@ -0,0 +1,329 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-05-24 10:48:22
+ * @Description:  This files is for uart functions
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+/***************************** Include Files ********************************/
+
+#include "ft_status.h"
+#include "ft_uart.h"
+#include "ft_io.h"
+#include "ft_error_code.h"
+
+u32 FUart_SendBuffer(Ft_Uart *UartPtr);
+u32 FUart_ReceiveBuffer(Ft_Uart *UartPtr);
+
+static void FUart_StubHandler(void *Args, u32 Event,
+ u32 ByteCount);
+
+/**
+ * @name: FUart_CfgInitialize
+ * @msg: initalize uart configure
+ * @return {*}
+ * @param {Ft_Uart} *UartPtr
+ * @param {FUart_Config_t} *Config
+ */
+s32 FUart_CfgInitialize(Ft_Uart *UartPtr, FUart_Config_t *Config)
+{
+ u32 RegValue = 0;
+
+ Ft_assertNonvoid(UartPtr != NULL);
+ Ft_assertNonvoid(Config != NULL);
+
+ UartPtr->Config.InstanceId = Config->InstanceId;
+ UartPtr->Config.BaseAddress = Config->BaseAddress;
+ UartPtr->Config.RefClockHz = Config->RefClockHz;
+ UartPtr->Config.IsrNum = Config->IsrNum;
+
+ UartPtr->Handler = FUart_StubHandler;
+
+ UartPtr->SendBuffer.BytePtr = NULL;
+ UartPtr->SendBuffer.RequestedBytes = 0;
+ UartPtr->SendBuffer.RemainingBytes = 0;
+
+ UartPtr->ReceiveBuffer.BytePtr = NULL;
+ UartPtr->ReceiveBuffer.RequestedBytes = 0;
+ UartPtr->ReceiveBuffer.RemainingBytes = 0;
+ UartPtr->rxbs_error = 0;
+ UartPtr->IsReady = FT_COMPONENT_IS_READLY;
+ //<! 设置波特率
+
+ /*
+ * Set up the default data format: 8 bit data, 1 stop bit, no
+ * parity
+ */
+ RegValue = ((FUART_FORMAT_WORDLENGTH_8BIT << 5) & UARTLCR_H_WLEN); //<! 8bit word length
+ RegValue |= (0 << 3) & UARTLCR_H_STP2; //<! 1 stopbit
+ RegValue |= (0 << 1) & UARTLCR_H_PEN; //<! no parity
+ RegValue |= (1 << 4) & UARTLCR_H_FEN; //<! fifo en
+ FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTLCR_H_OFFSET, RegValue);
+
+ /* Set the RX FIFO trigger at 8 data bytes.Tx FIFO trigger is 8 data bytes*/
+ RegValue = (1 << 3) | (1 << 0);
+ FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTIFLS_OFFSET, RegValue);
+
+ /* Disable all interrupts, polled mode is the default */
+ RegValue = 0;
+ FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET, RegValue);
+ return FST_SUCCESS;
+}
+
+/**
+ * @name: FUart_Send
+ * @msg:
+ * @param {Ft_Uart} *UartPtr
+ * @param {u8} *Buffer
+ * @param {u32} Length
+ * @return {u32} The Number of bytes actully sent.
+ */
+u32 FUart_Send(Ft_Uart *UartPtr, u8 *BytePtr, u32 Length)
+{
+ u32 RegValue = 0;
+ u32 SentCount = 0;
+ Ft_assertNonvoid(UartPtr != NULL);
+ Ft_assertNonvoid(BytePtr != NULL);
+ Ft_assertNonvoid(UartPtr->IsReady == FT_COMPONENT_IS_READLY);
+
+ /*
+ * Disable the UART transmit interrupts to allow this call to stop a
+ * previous operation that may be interrupt driven.
+ */
+ RegValue = FT_UART_ReadReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET);
+ RegValue &= ~(UARTIMSC_TXIM);
+ FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET, RegValue);
+
+ UartPtr->SendBuffer.BytePtr = BytePtr;
+ UartPtr->SendBuffer.RequestedBytes = Length;
+ UartPtr->SendBuffer.RemainingBytes = Length;
+
+ SentCount = FUart_SendBuffer(UartPtr);
+
+ return SentCount;
+}
+
+/**
+ * @name: FUart_PutChar
+ * @msg: send a char through uart
+ * @return {*}
+ * @param {Ft_Uart} *UartPtr
+ * @param {s8} Data
+ */
+void FUart_PutChar(Ft_Uart *UartPtr, s8 Data)
+{
+ Ft_assertVoid(UartPtr != NULL);
+ Ft_assertVoid(UartPtr->IsReady == FT_COMPONENT_IS_READLY);
+
+ while (!FT_UART_IsTransmitFull(UartPtr->Config.BaseAddress))
+ {
+ FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTDR_OFFSET, Data);
+ break;
+ }
+}
+
+static void FUart_StubHandler(void *Args, u32 Event,
+ u32 ByteCount)
+{
+ (void)Args;
+ (void)Event;
+ (void)ByteCount;
+
+ Ft_assertVoidAlways();
+}
+
+/**
+ * @name: FUart_SendBuffer
+ * @msg: send data buffer through uart
+ * @return {*}
+ * @param {Ft_Uart} *UartPtr
+ */
+u32 FUart_SendBuffer(Ft_Uart *UartPtr)
+{
+ u32 SentCount = 0U;
+ u32 RegValue;
+
+ /*
+ * If the TX FIFO is full, send nothing.
+ * Otherwise put bytes into the TX FIFO unil it is full, or all of the
+ * data has been put into the FIFO.
+ */
+ while ((!FT_UART_IsTransmitFull(UartPtr->Config.BaseAddress)) && (UartPtr->SendBuffer.RemainingBytes > SentCount))
+ {
+ FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTDR_OFFSET, (u32)UartPtr->SendBuffer.BytePtr[SentCount]);
+ SentCount++;
+ }
+
+ /* Update the buffer to reflect the bytes that were sent from it */
+ UartPtr->SendBuffer.BytePtr += SentCount;
+ UartPtr->SendBuffer.RemainingBytes -= SentCount;
+
+ RegValue = FT_UART_ReadReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET);
+ RegValue |= (UARTIMSC_TXIM);
+ FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET, RegValue);
+
+ return SentCount;
+}
+
+/**
+ * @name: FUart_Receive
+ * @msg: receive data through uart
+ * @return {*}
+ * @param {Ft_Uart} *UartPtr
+ * @param {u8} *BytePtr
+ * @param {u32} Length
+ */
+u32 FUart_Receive(Ft_Uart *UartPtr, u8 *BytePtr, u32 Length)
+{
+ u32 Received;
+ u32 BackRegValue;
+
+ Ft_assertNonvoid(UartPtr != NULL);
+ Ft_assertNonvoid(BytePtr != NULL);
+ Ft_assertNonvoid(UartPtr->IsReady == FT_COMPONENT_IS_READLY);
+
+ /*
+ * Disable all the interrupts.
+ * This stops a previous operation that may be interrupt driven
+ */
+ BackRegValue = FT_UART_ReadReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET);
+ FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET, 0);
+
+ UartPtr->ReceiveBuffer.BytePtr = BytePtr;
+ UartPtr->ReceiveBuffer.RequestedBytes = Length;
+ UartPtr->ReceiveBuffer.RemainingBytes = Length;
+
+ Received = FUart_ReceiveBuffer(UartPtr);
+ FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET, BackRegValue);
+
+ return Received;
+}
+
+/**
+ * @name: Ft_Uart_ReceiveBuffer
+ * @msg: handling uart receive buffer
+ * @return {*}
+ * @param {Ft_Uart} *UartPtr
+ */
+u32 FUart_ReceiveBuffer(Ft_Uart *UartPtr)
+{
+
+ u32 ReceivedCount = 0U;
+ u32 Event;
+ u32 EventData;
+ u32 ByteValue;
+
+ while ((ReceivedCount < UartPtr->ReceiveBuffer.RemainingBytes) && !FT_UART_IsReceiveData(UartPtr->Config.BaseAddress))
+ {
+ ByteValue = FT_UART_ReadReg(UartPtr->Config.BaseAddress, UARTDR_OFFSET);
+
+ if (UartPtr->rxbs_error)
+ {
+ if ((ByteValue & UARTDR_ALLE) != 0)
+ {
+ EventData = ByteValue;
+ Event = FUART_EVENT_PARE_FRAME_BRKE;
+
+ if (UartPtr->Handler)
+ {
+ UartPtr->Handler(UartPtr->Args, Event, EventData);
+ }
+ }
+ }
+ UartPtr->ReceiveBuffer.BytePtr[ReceivedCount] = (u8)(ByteValue & 0xff);
+ ReceivedCount++;
+ }
+
+ UartPtr->rxbs_error = 0;
+
+ if (UartPtr->ReceiveBuffer.BytePtr != NULL)
+ {
+ UartPtr->ReceiveBuffer.BytePtr += ReceivedCount;
+ }
+ UartPtr->ReceiveBuffer.RemainingBytes -= ReceivedCount;
+
+ return ReceivedCount;
+}
+
+/**
+ * @name: FUart_BlockSend
+ * @msg: initiate uart block send
+ * @return {*}
+ * @param {Ft_Uart} *UartPtr
+ * @param {u8} *BytePtr
+ * @param {u32} Length
+ */
+void FUart_BlockSend(Ft_Uart *UartPtr, u8 *BytePtr, u32 Length)
+{
+ u32 index;
+
+ Ft_assertVoid(UartPtr != NULL);
+ Ft_assertVoid(BytePtr != NULL);
+ Ft_assertVoid(UartPtr->IsReady == FT_COMPONENT_IS_READLY);
+
+ for (index = 0; index < Length; index++)
+ {
+ FUart_SendByte(UartPtr->Config.BaseAddress, BytePtr[index]);
+ }
+}
+
+/**
+ * @name: FUart_BlockReceive
+ * @msg: initiate uart block receive
+ * @return {*}
+ * @param {Ft_Uart} *UartPtr
+ */
+u8 FUart_BlockReceive(Ft_Uart *UartPtr)
+{
+ Ft_assertNonvoid(UartPtr != NULL);
+ Ft_assertNonvoid(UartPtr->IsReady == FT_COMPONENT_IS_READLY);
+ return FUart_RecvByte(UartPtr->Config.BaseAddress);
+}
+
+/**
+ * @name: FUart_SetBaudRate
+ * @msg: set baudrate of UART trans
+ * @return {*}
+ * @param {Ft_Uart} *UartPtr
+ * @param {u32} BaudRate
+ */
+u32 FUart_SetBaudRate(Ft_Uart *UartPtr, u32 BaudRate)
+{
+ u32 temp;
+ u32 divider;
+ u32 remainder;
+ u32 fraction;
+
+ Ft_assertNonvoid(NULL != UartPtr);
+ if ((BaudRate * 2) > UartPtr->Config.RefClockHz)
+ {
+ return ERR_INPUT_BAUD_NO_SUPPORT;
+ }
+
+ /* calculate baud rate divisor */
+ temp = 16 * BaudRate;
+ divider = UartPtr->Config.RefClockHz / temp;
+ remainder = UartPtr->Config.RefClockHz % temp;
+ temp = (128 * remainder) / temp;
+ fraction = temp / 2;
+
+ if (0 != (temp & 1))
+ {
+ fraction++;
+ }
+
+ FUart_ClearSpecificOptions(UartPtr, FUART_OPTION_RXEN | FUART_OPTION_TXEN);
+ /* set baud register */
+ FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTIBRD_OFFSET, divider);
+ FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTFBRD_OFFSET, fraction);
+ FUart_SetSpecificOptions(UartPtr, FUART_OPTION_RXEN | FUART_OPTION_TXEN);
+
+ return ERR_SUCCESS;
+}
diff --git a/bsp/ft2004/libraries/bsp/ft_uart/ft_uart.h b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart.h
new file mode 100644
index 0000000000..e342067030
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart.h
@@ -0,0 +1,120 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-05-24 10:13:51
+ * @Description:  This files is for uart functions
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef FT_UART_H
+#define FT_UART_H
+
+#include "ft_types.h"
+#include "ft_assert.h"
+#include "ft_status.h"
+#include "ft_uart_hw.h"
+
+#define FUART_BAUDRATE 115200U
+
+/* Config options */
+#define FUART_OPTION_UARTEN 0x1U
+#define FUART_OPTION_RXEN 0x2U
+#define FUART_OPTION_TXEN 0x4U
+#define FUART_OPTION_FIFOEN 0x8U
+
+/* Data format values */
+#define FUART_FORMAT_WORDLENGTH_8BIT 0x3
+#define FUART_FORMAT_WORDLENGTH_7BIT 0x2
+#define FUART_FORMAT_WORDLENGTH_6BIT 0x1
+#define FUART_FORMAT_WORDLENGTH_5BIT 0x0
+
+#define FUART_FORMAT_NO_PARITY 0U
+#define FUART_FORMAT_MARK_PARITY 1U
+#define FUART_FORMAT_SPACE_PARITY 2U
+#define FUART_FORMAT_ODD_PARTY 3U
+#define FUART_FORMAT_EVEN_PARITY 4U
+
+#define FUART_FORMAT_2_STOP_BIT 0U
+#define FUART_FORMAT_1_STOP_BIT 1U
+
+/* Callback events */
+
+#define FUART_EVENT_RECV_DATA 1U /**< Data receiving done */
+#define FUART_EVENT_RECV_TOUT 2U /**< A receive timeout occurred */
+#define FUART_EVENT_SENT_DATA 3U /**< Data transmission done */
+#define FUART_EVENT_RECV_ERROR 4U /**< A receive error detected */
+#define FUART_EVENT_MODEM 5U /**< Modem status changed */
+#define FUART_EVENT_PARE_FRAME_BRKE 6U /**< A receive parity, frame, break \
+ * error detected */
+#define FUART_EVENT_RECV_ORERR 7U /**< A receive overrun error detected */
+
+/**************************** Type Definitions ******************************/
+typedef struct
+{
+ u32 InstanceId; /* Id of device*/
+ u32 BaseAddress;
+ u32 RefClockHz;
+ u32 IsrNum;
+} FUart_Config_t;
+
+typedef struct
+{
+ u8 *BytePtr;
+ u32 RequestedBytes;
+ u32 RemainingBytes;
+} FUart_Buffer_t;
+
+typedef struct
+{
+ u32 BaudRate; /**< In bps, ie 1200 */
+ u32 DataBits; /**< Number of data bits */
+ u32 Parity; /**< Parity */
+ u8 StopBits; /**< Number of stop bits */
+} FUart_Format_t;
+
+typedef void (*FUart_Handler_t)(void *Args, u32 Event, u32 EventData);
+
+typedef struct
+{
+ FUart_Config_t Config; /* Configuration data structure */
+ u32 InputClockHz;
+ u32 IsReady; /* Device is ininitialized and ready*/
+ u32 BaudRate;
+
+ FUart_Buffer_t SendBuffer;
+ FUart_Buffer_t ReceiveBuffer;
+
+ FUart_Handler_t Handler;
+ void *Args;
+ uint8_t rxbs_error; /* 接收过程中出现错误 ,0 无错误,1 存在错误*/
+
+} Ft_Uart;
+
+/* define SD MMC error code */
+typedef enum
+{
+ ERR_SUB_MODE_UART_GENERAL = 0
+} FT_UART_ERR_SUB_MODE;
+
+#define ERR_INPUT_BAUD_NO_SUPPORT FT_CODE_ERR(ERR_MODE_UART, ERR_SUB_MODE_UART_GENERAL, 0x1)
+
+void FUart_PutChar(Ft_Uart *UartPtr, s8 Data);
+u32 FUart_Send(Ft_Uart *UartPtr, u8 *Buffer, u32 Length);
+u32 FUart_Receive(Ft_Uart *UartPtr, u8 *BytePtr, u32 Length);
+s32 FUart_CfgInitialize(Ft_Uart *UartPtr, FUart_Config_t *Config);
+FUart_Config_t *FUart_LookupConfig(u32 InstanceId);
+void FUart_SetOptions(Ft_Uart *UartPtr, u32 Options);
+void FUart_SetSpecificOptions(Ft_Uart *UartPtr, u32 Options);
+void FUart_ClearSpecificOptions(Ft_Uart *UartPtr, u32 Options);
+void FUart_InterruptHandler(Ft_Uart *UartPtr);
+void FUart_SetHandler(Ft_Uart *UartPtr, FUart_Handler_t FuncPtr,
+ void *Args);
+void FUart_SetInterruptMask(Ft_Uart *UartPtr, u32 Mask);
+u32 FUart_SetBaudRate(Ft_Uart *UartPtr, u32 BaudRate);
+#endif // !
diff --git a/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_g.c b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_g.c
new file mode 100644
index 0000000000..87e76f92d9
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_g.c
@@ -0,0 +1,34 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-04-07 13:42:30
+ * @Description:  This files is for uart config
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_uart.h"
+#include "ft_parameters.h"
+
+FUart_Config_t FUart_Config_tTable[FT_UART_NUM] = {
+ {FT_UART0_ID,
+ FT_UART0_BASE_ADDR,
+ FT_UART0_CLK_FREQ_HZ,
+ 38},
+ {FT_UART1_ID,
+ FT_UART1_BASE_ADDR,
+ FT_UART1_CLK_FREQ_HZ,
+ 39},
+ {FT_UART2_ID,
+ FT_UART2_BASE_ADDR,
+ FT_UART2_CLK_FREQ_HZ,
+ 40},
+ {FT_UART3_ID,
+ FT_UART3_BASE_ADDR,
+ FT_UART3_CLK_FREQ_HZ,
+ 41}};
diff --git a/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_hw.c b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_hw.c
new file mode 100644
index 0000000000..541f86a6a1
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_hw.c
@@ -0,0 +1,46 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-05-25 16:49:30
+ * @Description:  This files is for uart register function
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_uart_hw.h"
+
+void FUart_SendByte(u32 BaseAddress, u8 Byte)
+{
+ while (FT_UART_IsTransmitFull(BaseAddress))
+ {
+ ;
+ }
+ FT_UART_WriteReg(BaseAddress, UARTDR_OFFSET, (u32)Byte);
+}
+
+u8 FUart_RecvByte(u32 BaseAddress)
+{
+ u32 RecievedByte;
+ while (FT_UART_IsReceiveData(BaseAddress))
+ {
+ ;
+ }
+ RecievedByte = FT_UART_ReadReg(BaseAddress, UARTDR_OFFSET);
+ return RecievedByte;
+}
+
+u8 FUart_GetChar(u32 BaseAddress)
+{
+ u32 RecievedByte;
+ if (FT_UART_IsReceiveData(BaseAddress))
+ {
+ return 0xff;
+ }
+ RecievedByte = FT_UART_ReadReg(BaseAddress, UARTDR_OFFSET);
+ return RecievedByte;
+}
diff --git a/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_hw.h b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_hw.h
new file mode 100644
index 0000000000..8cadd40419
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_hw.h
@@ -0,0 +1,221 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-03-31 14:59:20
+ * @LastEditTime: 2021-04-02 14:14:34
+ * @Description:  This files is for definition of uart register
+ *
+ * @Modify History: * * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef FT_UART_HW_H
+#define FT_UART_HW_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "ft_types.h"
+#include "ft_assert.h"
+#include "ft_io.h"
+
+ /************************** Constant Definitions *****************************/
+
+ /** @name Register Map
+ *
+ * Register offsets for the UART.
+ * @{
+ */
+
+#define UARTDR_OFFSET 0U /* 数据寄存器 */
+#define UARTRSR_OFFSET 4U /* 接收状态寄存器/错误清除寄存器 */
+#define UARTECR_OFFSET UARTRSR_OFFSET
+#define UARTFTR_OFFSET 0x18U /* 标志寄存器 */
+#define UARTILPR_OFFSET 0x020U /* 低功耗计数寄存器 */
+#define UARTIBRD_OFFSET 0x024U /* 波特率整数值配置寄存器 */
+#define UARTFBRD_OFFSET 0x028U /* 波特率小数值配置寄存器 */
+#define UARTLCR_H_OFFSET 0x02cU /* 线控寄存器 */
+#define UARTCR_OFFSET 0x030U /* 控制寄存器 */
+#define UARTIFLS_OFFSET 0x034U /* FIFO阈值选择寄存器 */
+#define UARTIMSC_OFFSET 0x038U /* 中断屏蔽选择清除寄存器 */
+#define UARTRIS_OFFSET 0x03cU /* 中断状态寄存器 */
+#define UARTMIS_OFFSET 0x040U /* 中断屏蔽状态寄存器 */
+#define UARTICR_OFFSET 0x044U /* 中断清除寄存器 */
+#define UARTDMACR_OFFSET 0x048U /* DMA控制寄存器 */
+
+ /* 数据寄存器 RW */
+
+#define UARTDR_OE 0x800U /* 如果接收到数据并且接收的 FIFO 已满,该位设置为 1 */
+#define UARTDR_BE 0x400U /* 突发错误 */
+#define UARTDR_PE 0x200U /* 奇偶校验错误。 */
+#define UARTDR_FE 0x100U /* 帧错误。 */
+#define UARTDR_ALLE (UARTDR_OE | UARTDR_BE | UARTDR_PE | UARTDR_FE)
+#define UARTDR_DATA 0xffU /* R 接收数据 ,W 传输数据 */
+
+ /* 接收状态寄存器 RW */
+
+#define UARTRSR_OE 0x8U /* 溢出错误。 */
+#define UARTRSR_BE 0x4U /* 突发错误 */
+#define UARTRSR_PE 0x2U /* 奇偶校验错误。 */
+#define UARTRSR_FE 0x1U /* 帧错误 */
+
+#define UARTECR_CLE 0xffU /* 清除 */
+
+/* 标志寄存器 RO */
+#define UARTFTR_RI 0x100U /* Ring indicator */
+#define UARTFTR_TXFE 0x80U /* Transmit FIFO empty */
+#define UARTFTR_RXFF 0x40U /* Receive FIFO full */
+#define UARTFTR_TXFF 0x20U /* Transmit FIFO full. */
+#define UARTFTR_RXFE 0x10U /* Receive FIFO empty */
+#define UARTFTR_BUSY 0x08U /* UART busy */
+#define UARTFTR_DCD 0x04U /* Data carrier detect. */
+#define UARTFTR_DSR 0x02U /* Data set ready. */
+#define UARTFTR_CTS 0x1U /* Clear to send */
+
+/* IrDA 低功耗计数寄存器 RW */
+#define UARTILPR_ILPDVSR 0xffU /* 8-bit low-power divisor value. These bits are cleared to 0 at reset */
+
+/* 波特率整数值配置寄存器 RW */
+#define UARTIBRD_BAUD_DIVFRAC 0xffffU /* The fractional baud rate divisor. */
+
+/* 波特率小数值配置寄存器 RW */
+#define UARTFBRD_BAUD_DIVFRAC 0x3fU /* The fractional baud rate divisor. */
+
+/* 线控寄存器 RW */
+#define UARTLCR_H_SPS 0x80U /* Stick parity select. */
+#define UARTLCR_H_WLEN 0x60U /* Word length. */
+#define UARTLCR_H_FEN 0x10U /* Enable FIFOs. */
+#define UARTLCR_H_STP2 0x08U /* Two stop bits select. */
+#define UARTLCR_H_EPS 0x04U /* Even parity select. */
+#define UARTLCR_H_PEN 0x02U /* Parity enable. */
+#define UARTLCR_H_BRK 0x01U /* send break */
+
+/* 控制寄存器 RW */
+#define UARTCR_CTSEN 0x8000U /* CTS hardware flow control enable. */
+#define UARTCR_RTSEN 0x4000U /* RTS hardware flow control enable. */
+#define UARTCR_OUT2 0x2000U /* This bit is the complement of the UART Out2 (nUARTOut2) modem status output. */
+#define UARTCR_Out1 0x1000U /* This bit is the complement of the UART Out1 (nUARTOut1) modem status output. */
+#define UARTCR_RTS 0x0800U /* Request to send. */
+#define UARTCR_DTR 0x0400U /* Data transmit ready */
+#define UARTCR_RXE 0x0200U /* Receive enable. */
+#define UARTCR_TXE 0x0100U /* Transmit enable. */
+#define UARTCR_LBE 0x0080U /* Loop back enable.*/
+#define UARTCR_SIRLP 0x4U /* IrDA SIR low power mode. */
+#define UARTCR_SIREN 0x2U /* SIR enable. */
+#define UARTCR_UARTEN 0x1U /* UART enable. */
+
+/* FIFO阈值选择寄存器 RW */
+#define UARTIFLS_RXIFLSEL 0x38U /* Receive interrupt FIFO level select. */
+#define UARTIFLS_TXIFLSEL 0x7U /* Transmit interrupt FIFO level select. */
+
+/* 中断屏蔽选择清除寄存器 RW */
+#define UARTIMSC_OEIM 0x400U /* Overrun error interrupt mask. */
+#define UARTIMSC_BEIM 0x200U /* Break error interrupt mask */
+#define UARTIMSC_PEIM 0x100U /* Parity error interrupt mask. */
+#define UARTIMSC_FEIM 0x80U /* Framing error interrupt mask. */
+#define UARTIMSC_RTIM 0x40U /* Receive timeout interrupt mask. */
+#define UARTIMSC_TXIM 0x20U /* Transmit interrupt mask. */
+#define UARTIMSC_RXIM 0x10U /* Receive interrupt mask. */
+#define UARTIMSC_DSRMIM 0x8U /* nUARTDSR modem interrupt mask. */
+#define UARTIMSC_DCDMIM 0x4U /* nUARTDCD modem interrupt mask. */
+#define UARTIMSC_CTSMIM 0x2U /* nUARTCTS modem interrupt mask. */
+#define UARTIMSC_RIMIM 0x1U /* nUARTRI modem interrupt mask. */
+#define UARTIMSC_ALLM 0x3ffU /* all interrupt mask */
+
+ /* 中断状态寄存器 RO */
+
+#define UARTRIS_OEIS 0x400U /* Overrun error interrupt mask. */
+#define UARTRIS_BEIS 0x200U /* Break error interrupt mask */
+#define UARTRIS_PEIS 0x100U /* Parity error interrupt mask. */
+#define UARTRIS_FEIS 0x80U /* Framing error interrupt mask. */
+#define UARTRIS_RTIS 0x40U /* Receive timeout interrupt mask. */
+#define UARTRIS_TXIS 0x20U /* Transmit interrupt mask. */
+#define UARTRIS_RXIS 0x10U /* Receive interrupt mask. */
+#define UARTRIS_DSRMIS 0x8U /* nUARTDSR modem interrupt mask. */
+#define UARTRIS_DCDMIS 0x4U /* nUARTDCD modem interrupt mask. */
+#define UARTRIS_CTSMIS 0x2U /* nUARTCTS modem interrupt mask. */
+#define UARTRIS_RIMIS 0x1U /* nUARTRI modem interrupt mask. */
+
+ /* 中断屏蔽状态寄存器 R0 */
+
+#define UARTMIS_OEMIS 0x400U /* Overrun error interrupt mask. */
+#define UARTMIS_BEMIS 0x200U /* Break error interrupt mask */
+#define UARTMIS_PEMIS 0x100U /* Parity error interrupt mask. */
+#define UARTMIS_FEMIS 0x80U /* Framing error interrupt mask. */
+#define UARTMIS_RTMIS 0x40U /* Receive timeout interrupt mask. */
+#define UARTMIS_TXMIS 0x20U /* Transmit interrupt mask. */
+#define UARTMIS_RXMIS 0x10U /* Receive interrupt mask. */
+#define UARTMIS_DSRMMIS 0x8U /* nUARTDSR modem interrupt mask. */
+#define UARTMIS_DCDMMIS 0x4U /* nUARTDCD modem interrupt mask. */
+#define UARTMIS_CTSMMIS 0x2U /* nUARTCTS modem interrupt mask. */
+#define UARTMIS_RIMMIS 0x1U /* nUARTRI modem interrupt mask. */
+
+/* 中断清除寄存器 WO */
+#define UARTICR_OEIC 0x400U /* Overrun error interrupt mask. */
+#define UARTICR_BEIC 0x200U /* Break error interrupt mask */
+#define UARTICR_PEIC 0x100U /* Parity error interrupt mask. */
+#define UARTICR_FEIC 0x80U /* Framing error interrupt mask. */
+#define UARTICR_RTIC 0x40U /* Receive timeout interrupt mask. */
+#define UARTICR_TXIC 0x20U /* Transmit interrupt mask. */
+#define UARTICR_RXIC 0x10U /* Receive interrupt mask. */
+#define UARTICR_DSRMIC 0x8U /* nUARTDSR modem interrupt mask. */
+#define UARTICR_DCDMIC 0x4U /* nUARTDCD modem interrupt mask. */
+#define UARTICR_CTSMIC 0x2U /* nUARTCTS modem interrupt mask. */
+#define UARTICR_RIMIC 0x1U /* nUARTRI modem interrupt mask. */
+
+/* DMA控制寄存器 RW */
+#define UARTDMACR_DMAONERR 0x4U /* DMA on error. */
+#define UARTDMACR_TXDMAE 0x2U /* Transmit DMA enable. */
+#define UARTDMACR_RXDMAE 0x1U /* Receive DMA enable. */
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/**
+ * @name: FT_UART_ReadReg
+ * @msg: 读取串口寄存器
+ * @param {u32} BaseAddress 串口的基地址
+ * @param {u32} RegOffset 串口的寄存器的偏移
+ * @return {u32} 寄存器参数
+ */
+#define FT_UART_ReadReg(BaseAddress, RegOffset) Ft_in32(BaseAddress + (u32)RegOffset)
+
+/**
+ * @name: FT_UART_WriteReg
+ * @msg: 写入串口寄存器
+ * @param {u32} BaseAddress 串口的基地址
+ * @param {u32} RegOffset 串口的寄存器的偏移
+ * @param {u32} RegisterValue 写入寄存器参数
+ * @return {void}
+ */
+#define FT_UART_WriteReg(BaseAddress, RegOffset, RegisterValue) Ft_out32(BaseAddress + (u32)RegOffset, (u32)RegisterValue)
+
+/**
+ * @name: FT_UART_ISRECEIVEDATA
+ * @msg: 用于确认是否接收到数据
+ * @param {u32} BaseAddress 串口的基地址
+ * @return {bool} true 是存在数据 , false 是不存在数据
+ *
+ */
+#define FT_UART_IsReceiveData(BaseAddress) (Ft_in32(BaseAddress + UARTFTR_OFFSET) & UARTFTR_RXFE)
+
+/**
+ * @name: FT_UART_ISTRANSMITFULL
+ * @msg: 用于确认是否能够发送数据
+ * @param {u32} BaseAddress 串口的基地址
+ * @return {bool} true 是数据已满 , false 可以发送数据
+ */
+#define FT_UART_IsTransmitFull(BaseAddress) ((Ft_in32(BaseAddress + UARTFTR_OFFSET) & (u32)UARTFTR_TXFF) == UARTFTR_TXFF)
+
+ void FUart_SendByte(u32 BaseAddress, u8 Byte);
+ u8 FUart_RecvByte(u32 BaseAddress);
+ u8 FUart_GetChar(u32 BaseAddress);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_intr.c b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_intr.c
new file mode 100644
index 0000000000..de1e92649f
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_intr.c
@@ -0,0 +1,196 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-05-25 16:49:42
+ * @Description:  This files is for uart irq functions
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_uart.h"
+
+extern u32 FUart_SendBuffer(Ft_Uart *UartPtr);
+extern u32 FUart_ReceiveBuffer(Ft_Uart *UartPtr);
+
+static void FUart_receiveErrorHandler(Ft_Uart *UartPtr, u32 InterruptStatus);
+static void FUart_receiveDataHandler(Ft_Uart *UartPtr);
+static void FUart_receiveTimeoutHandler(Ft_Uart *UartPtr);
+static void FUart_sendDataHandler(Ft_Uart *UartPtr, u32 InterruptStatus);
+
+/**
+ * @name: FUart_GetInterruptMask
+ * @msg: 此函数获取所有串口中断的mask。
+ * @param {Ft_Uart} *UartPtr
+ * @return {u32} mask
+ */
+u32 FUart_GetInterruptMask(Ft_Uart *UartPtr)
+{
+ Ft_assertNonvoid(UartPtr != NULL);
+
+ return FT_UART_ReadReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET);
+}
+
+void FUart_SetInterruptMask(Ft_Uart *UartPtr, u32 Mask)
+{
+ u32 TempMask = Mask;
+ Ft_assertVoid(UartPtr != NULL);
+
+ TempMask &= UARTIMSC_ALLM;
+
+ FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET, TempMask);
+}
+
+/**
+ * @name: FUart_SetHandler
+ * @msg: 设置中断回调函数
+ * @param {*}
+ * @return {*}
+ */
+void FUart_SetHandler(Ft_Uart *UartPtr, FUart_Handler_t FuncPtr,
+ void *Args)
+{
+ Ft_assertVoid(UartPtr != NULL);
+ Ft_assertVoid(FuncPtr != NULL);
+ Ft_assertVoid(UartPtr->IsReady == FT_COMPONENT_IS_READLY);
+
+ UartPtr->Handler = FuncPtr;
+ UartPtr->Args = Args;
+}
+
+/**
+ * @name: FUart_InterruptHandler
+ * @msg: 串口中断函数入口
+ * @param {Ft_Uart} *UartPtr
+ * @return {*}
+ */
+void FUart_InterruptHandler(Ft_Uart *UartPtr)
+{
+ u32 RegValue = 0;
+ Ft_assertVoid(UartPtr != NULL);
+ Ft_assertVoid(UartPtr->IsReady == FT_COMPONENT_IS_READLY);
+ //Ft_printf("FUart_InterruptHandler %x\r\n", UartPtr);
+ RegValue = FT_UART_ReadReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET);
+
+ RegValue &= FT_UART_ReadReg(UartPtr->Config.BaseAddress, UARTMIS_OFFSET);
+
+ if ((RegValue & ((u32)UARTMIS_RXMIS)) != (u32)0)
+ {
+ /* Received data interrupt */
+ FUart_receiveDataHandler(UartPtr);
+ }
+
+ if ((RegValue & ((u32)UARTMIS_TXMIS)) != (u32)0)
+ {
+ /* Transmit data interrupt */
+ FUart_sendDataHandler(UartPtr, RegValue);
+ }
+
+ if (((RegValue) & ((u32)UARTMIS_OEMIS | (u32)UARTMIS_BEMIS | (u32)UARTMIS_PEMIS | (u32)UARTMIS_FEMIS)) != (u32)0)
+ {
+ /* Received Error Status interrupt */
+ FUart_receiveErrorHandler(UartPtr, RegValue);
+ }
+
+ if ((RegValue & ((u32)UARTMIS_RTMIS)) != (u32)0)
+ {
+ /* Received Timeout interrupt */
+ FUart_receiveTimeoutHandler(UartPtr);
+ }
+
+ if (((RegValue) & ((u32)UARTMIS_DSRMMIS | (u32)UARTMIS_DCDMMIS | (u32)UARTMIS_CTSMMIS | (u32)UARTMIS_RIMMIS)) != (u32)0)
+ {
+ /* Modem status interrupt */
+ }
+
+ /* Clear the interrupt status. */
+ FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTICR_OFFSET,
+ RegValue);
+}
+
+static void FUart_receiveErrorHandler(Ft_Uart *UartPtr, u32 InterruptStatus)
+{
+ UartPtr->rxbs_error = 0;
+
+ if (((InterruptStatus) & ((u32)UARTMIS_OEMIS | (u32)UARTMIS_BEMIS | (u32)UARTMIS_PEMIS | (u32)UARTMIS_FEMIS)) != 0)
+ {
+ UartPtr->rxbs_error = 1;
+ }
+
+ (void)FUart_ReceiveBuffer(UartPtr);
+
+ if (0 == UartPtr->rxbs_error)
+ {
+ if (UartPtr->Handler)
+ {
+ UartPtr->Handler(UartPtr->Args, FUART_EVENT_RECV_ERROR, UartPtr->ReceiveBuffer.RequestedBytes - UartPtr->ReceiveBuffer.RemainingBytes);
+ }
+ }
+}
+
+static void FUart_receiveDataHandler(Ft_Uart *UartPtr)
+{
+ if ((u32)0 != UartPtr->ReceiveBuffer.RemainingBytes)
+ {
+ (void)FUart_ReceiveBuffer(UartPtr);
+ }
+
+ if ((u32)0 == UartPtr->ReceiveBuffer.RemainingBytes)
+ {
+ if (UartPtr->Handler)
+ {
+ UartPtr->Handler(UartPtr->Args, FUART_EVENT_RECV_DATA, UartPtr->ReceiveBuffer.RequestedBytes - UartPtr->ReceiveBuffer.RemainingBytes);
+ }
+ }
+}
+
+static void FUart_receiveTimeoutHandler(Ft_Uart *UartPtr)
+{
+ u32 Event;
+
+ if ((u32)0 != UartPtr->ReceiveBuffer.RemainingBytes)
+ {
+ (void)FUart_ReceiveBuffer(UartPtr);
+ }
+
+ if ((u32)0 == UartPtr->ReceiveBuffer.RemainingBytes)
+ {
+ Event = FUART_EVENT_RECV_TOUT;
+ }
+ else
+ {
+ Event = FUART_EVENT_RECV_DATA;
+ }
+
+ if (UartPtr->Handler)
+ {
+ UartPtr->Handler(UartPtr->Args, Event, UartPtr->ReceiveBuffer.RequestedBytes - UartPtr->ReceiveBuffer.RemainingBytes);
+ }
+}
+
+static void FUart_sendDataHandler(Ft_Uart *UartPtr, u32 InterruptStatus)
+{
+ u32 RegValue;
+ if (UartPtr->SendBuffer.RemainingBytes == (u32)0)
+ {
+ //<! close send isr
+ RegValue = FT_UART_ReadReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET);
+ RegValue &= ~UARTIMSC_TXIM;
+ FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET, RegValue);
+ if (UartPtr->Handler)
+ {
+ UartPtr->Handler(UartPtr->Args, FUART_EVENT_RECV_DATA, UartPtr->ReceiveBuffer.RequestedBytes - UartPtr->ReceiveBuffer.RemainingBytes);
+ }
+ }
+ else if (InterruptStatus & UARTMIS_TXMIS)
+ {
+ FUart_SendBuffer(UartPtr);
+ }
+ else
+ {
+ }
+}
diff --git a/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_options.c b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_options.c
new file mode 100644
index 0000000000..0016f0c732
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_options.c
@@ -0,0 +1,102 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-05-24 10:47:33
+ * @Description:  This files is for uart option setting
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_uart.h"
+#include "ft_uart_hw.h"
+#include "ft_types.h"
+/************************** Variable Definitions ****************************/
+/*
+ * The following data type is a map from an option to the offset in the
+ * register to which it belongs as well as its bit mask in that register.
+ */
+typedef struct
+{
+ u32 Option;
+ u32 RegisterOffset;
+ u32 Mask;
+} Mapping;
+
+static Mapping OptionTable[] = {
+ {FUART_OPTION_UARTEN, UARTCR_OFFSET, UARTCR_UARTEN},
+ {FUART_OPTION_RXEN, UARTCR_OFFSET, UARTCR_RXE},
+ {FUART_OPTION_TXEN, UARTCR_OFFSET, UARTCR_TXE},
+ {FUART_OPTION_FIFOEN, UARTLCR_H_OFFSET, UARTLCR_H_FEN}};
+
+#define FT_UART_NUM_OPITIONS (sizeof(OptionTable) / sizeof(Mapping))
+
+void FUart_SetOptions(Ft_Uart *UartPtr, u32 Options)
+{
+ u32 Index;
+ u32 RegValue;
+ Ft_assertVoid(UartPtr != NULL);
+ Ft_assertVoid(UartPtr->IsReady == FT_COMPONENT_IS_READLY);
+
+ for (Index = 0; Index < FT_UART_NUM_OPITIONS; Index++)
+ {
+ RegValue = FT_UART_ReadReg(UartPtr->Config.BaseAddress, OptionTable[Index].RegisterOffset);
+
+ if ((Options & OptionTable[Index].Option) != (u32)(0))
+ {
+ RegValue |= OptionTable[Index].Mask;
+ }
+ else
+ {
+ RegValue &= ~OptionTable[Index].Mask;
+ }
+
+ FT_UART_WriteReg(UartPtr->Config.BaseAddress, OptionTable[Index].RegisterOffset, RegValue);
+ }
+}
+
+void FUart_SetSpecificOptions(Ft_Uart *UartPtr, u32 Options)
+{
+ u32 Index;
+ u32 RegValue;
+ Ft_assertVoid(UartPtr != NULL);
+
+ for (Index = 0; Index < FT_UART_NUM_OPITIONS; Index++)
+ {
+ if ((Options & OptionTable[Index].Option) == (u32)(0))
+ {
+ continue;
+ }
+
+ RegValue = FT_UART_ReadReg(UartPtr->Config.BaseAddress, OptionTable[Index].RegisterOffset);
+
+ /* set specific options */
+ RegValue |= OptionTable[Index].Mask;
+ FT_UART_WriteReg(UartPtr->Config.BaseAddress, OptionTable[Index].RegisterOffset, RegValue);
+ }
+}
+
+void FUart_ClearSpecificOptions(FT_IN Ft_Uart *UartPtr, FT_IN u32 Options)
+{
+ u32 Index;
+ u32 RegValue;
+ Ft_assertVoid(UartPtr != NULL);
+
+ for (Index = 0; Index < FT_UART_NUM_OPITIONS; Index++)
+ {
+ if ((Options & OptionTable[Index].Option) == (u32)(0))
+ {
+ continue;
+ }
+
+ RegValue = FT_UART_ReadReg(UartPtr->Config.BaseAddress, OptionTable[Index].RegisterOffset);
+
+ /* remove specific options */
+ RegValue &= ~OptionTable[Index].Mask;
+ FT_UART_WriteReg(UartPtr->Config.BaseAddress, OptionTable[Index].RegisterOffset, RegValue);
+ }
+}
diff --git a/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_selftest.c b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_selftest.c
new file mode 100644
index 0000000000..b31a0e2ed0
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_selftest.c
@@ -0,0 +1,13 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-04-07 13:44:41
+ * @Description:  This files is for uart test cases
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
diff --git a/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_sinit.c b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_sinit.c
new file mode 100644
index 0000000000..8c228db78c
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_sinit.c
@@ -0,0 +1,41 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-04-07 13:44:56
+ * @Description:  This files is for uart static init
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_uart.h"
+#include "ft_parameters.h"
+
+extern FUart_Config_t FUart_Config_tTable[FT_UART_NUM];
+
+/**
+ * @name: Ft_Uart_LookupConfig
+ * @msg: 获取串口的基本配置
+ * @param {u16} InstanceId FT_UARTX_ID
+ * @return {*}
+ */
+FUart_Config_t *FUart_LookupConfig(u32 InstanceId)
+{
+ FUart_Config_t *CfgPtr = NULL;
+ u32 Index;
+
+ for (Index = 0; Index < (u32)FT_UART_NUM; Index++)
+ {
+ if (FUart_Config_tTable[Index].InstanceId == InstanceId)
+ {
+ CfgPtr = &FUart_Config_tTable[Index];
+ break;
+ }
+ }
+
+ return (FUart_Config_t *)CfgPtr;
+}
diff --git a/bsp/ft2004/libraries/bsp/include/ft_parameters.h b/bsp/ft2004/libraries/bsp/include/ft_parameters.h
new file mode 100644
index 0000000000..9764bfae30
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/include/ft_parameters.h
@@ -0,0 +1,180 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * Date: 2021-03-30 14:57:03
+ * @LastEditTime: 2021-05-24 14:35:00
+ * Description:  definitions of BSP parameters
+ * Modify History:
+ * * * Ver Who Date Changes
+ * * ----- ------ -------- ----------------------------------------------
+ * 1.00 Huanghe 2021/3/1 init
+ */
+
+#ifndef FT_PARAMETERS_H
+#define FT_PARAMETERS_H
+
+/* Device register address */
+#define FT_DEV_BASE_ADDR 0x28000000
+#define FT_DEV_END_ADDR 0x2FFFFFFF
+
+/******** UART ************/
+
+#define FT_UART_NUM 4
+#define FT_UART_REG_LENGTH 0x18000
+
+#define FT_UART0_ID 0
+#define FT_UART0_BASE_ADDR 0x28000000
+#define FT_UART0_CLK_FREQ_HZ 48000000
+
+#define FT_UART1_ID 1
+#define FT_UART1_BASE_ADDR 0x28001000
+#define FT_UART1_CLK_FREQ_HZ 48000000
+
+#define FT_UART2_ID 2
+#define FT_UART2_BASE_ADDR 0x28002000
+#define FT_UART2_CLK_FREQ_HZ 48000000
+
+#define FT_UART3_BASE_ADDR 0x28003000
+#define FT_UART3_ID 3
+#define FT_UART3_CLK_FREQ_HZ 48000000
+
+#define FT_STDOUT_BASEADDRESS FT_UART1_BASE_ADDR
+#define FT_STDIN_BASEADDRESS FT_UART1_BASE_ADDR
+
+/****** GIC v3 *****/
+#define FT_GICV3_INSTANCES_NUM 1U
+#define GICV3_REG_LENGTH 0x00009000
+
+/*
+ * The maximum priority value that can be used in the GIC.
+ */
+#define GICV3_MAX_INTR_PRIO_VAL 240U
+#define GICV3_INTR_PRIO_MASK 0x000000f0U
+
+#define ARM_GIC_IPI_COUNT 16 /* MPCore IPI count */
+#define SGI_INT_MAX 16
+#define SPI_START_INT_NUM 32 /* SPI start at ID32 */
+#define PPI_START_INT_NUM 16 /* PPI start at ID16 */
+#define GIC_INT_MAX_NUM 1020 /* GIC max interrupts count */
+
+#define FT_GICV3_BASEADDRESS 0x29900000U
+#define FT_GICV3_DISTRIBUTOR_BASEADDRESS (FT_GICV3_BASEADDRESS + 0)
+#define FT_GICV3_RD_BASEADDRESS (FT_GICV3_BASEADDRESS + 0x80000U)
+#define FT_GICV3_SGI_BASEADDRESS (FT_GICV3_RD_BASEADDRESS + (1U << 16))
+
+#define FT_GICV3_VECTORTABLE_NUM GIC_INT_MAX_NUM
+
+/** Gmac **/
+#define FT_GMAC_INSTANCES_NUM 2U
+#define FT_GMAC_REG_LENGTH 0x00009000
+
+#define FT_GMAC_COMMON_ADDR 0x2820B000U
+
+#define FT_GMAC0_ID 0
+#define FT_GMAC0_BASEADDR 0x2820C000U
+#define FT_GMAC0_DEFAULT_ADDR \
+ { \
+ 0x11, 0x1c, 0x2c, 0x5c, 0x66, 0x88 \
+ }
+
+#define FT_GMAC1_ID 1
+#define FT_GMAC1_BASEADDR 0x28210000U
+
+/** @defgroup ENET_Buffers_setting
+ * @{
+ */
+#define GMAC_MAX_PACKET_SIZE 1600 /* GMAC_HEADER + GMAC_EXTRA + VLAN_TAG + MAX_GMAC_PAYLOAD + GMAC_CRC */
+#define GMAC_HEADER 14 /* 6 byte Dest addr, 6 byte Src addr, 2 byte length/type */
+#define GMAC_CRC 4 /* Gmac CRC */
+#define GMAC_EXTRA 2 /* Extra bytes in some cases */
+#define VLAN_TAG 4 /* optional 802.1q VLAN Tag */
+#define MIN_GMAC_PAYLOAD 46 /* Minimum Gmac payload size */
+#define MAX_GMAC_PAYLOAD 1500 /* Maximum Gmac payload size */
+#define JUMBO_FRAME_PAYLOAD 9000 /* Jumbo frame payload size */
+#define RX_DESCNUM 1024U /* Rx buffers of size GMAC_MAX_PACKET_SIZE */
+#define TX_DESCNUM 1024U /* Tx buffers of size GMAC_MAX_PACKET_SIZE */
+
+#define PHY_USING_AR8035
+
+#define GMAC0_ISRNUM 81
+#define GMAC0_ISRPRIORITY 0
+
+#define GMAC1_ISRNUM 82
+#define GMAC1_ISRPRIORITY 0
+
+/* SDC */
+#define FT_SDC_NUM 1
+#define FT_SDC_INSTANCE 0
+#define FT_SDC_BASEADDR 0x28207C00U
+#define FT_SDC_REG_LENGTH 0x4000
+#define FT_SDC_FREQ 600000000
+
+/* pin MUX/DEMUX */
+
+#define FT_PIN_MUX_BASEADDR 0x28180000
+#define FT_PIN_MUX_REG_LENGTH 0x10000
+
+/* CAN */
+
+#define FT_CAN_NUM 3
+#define FT_CAN_REG_LENGTH 0x1000
+#define FT_CAN0_BASEADDR 0x28207000
+#define FT_CAN1_BASEADDR 0x28207400
+#define FT_CAN2_BASEADDR 0x28207800
+#define FT_CAN0_IRQNUM 119
+#define FT_CAN1_IRQNUM 123
+#define FT_CAN2_IRQNUM 124
+#define FT_CAN_BAUDRATE 1000000 /* 1M */
+#define FT_CAN_CLK 600000000
+
+/* pci */
+
+#define FT_PCI_CONFIG_BASEADDR 0x40000000
+#define FT_PCI_CONFIG_REG_LENGTH 0x10000000
+
+#define FT_PCI_IO_CONFIG_BASEADDR 0x50000000
+#define FT_PCI_IO_CONFIG_REG_LENGTH 0x08000000
+
+#define FT_PCI_MEM32_BASEADDR 0x58000000
+#define FT_PCI_MEM32_REG_LENGTH 0x27000000
+
+/* qspi */
+#define FT_QSPI_NUM 1U
+#define FT_QSPI_INSTANCE 0
+#define FT_QSPI_MAX_CS_NUM 4
+#define FT_QSPI_BASEADDR 0x28014000
+
+#define FT_QSPI_FLASH_CAP_4MB 0
+#define FT_QSPI_FLASH_CAP_8MB 1
+#define FT_QSPI_FLASH_CAP_16MB 2
+#define FT_QSPI_FLASH_CAP_32MB 3
+#define FT_QSPI_FLASH_CAP_64MB 4
+#define FT_QSPI_FLASH_CAP_128MB 5
+#define FT_QSPI_FLASH_CAP_256MB 6
+
+#define FT_QSPI_ADDR_SEL_3 0
+#define FT_QSPI_ADDR_SEL_4 1
+
+#define FT_QSPI_SCK_DIV_128 0
+#define FT_QSPI_SCK_DIV_2 1
+#define FT_QSPI_SCK_DIV_4 2
+#define FT_QSPI_SCK_DIV_8 3
+#define FT_QSPI_SCK_DIV_16 4
+#define FT_QSPI_SCK_DIV_32 5
+#define FT_QSPI_SCK_DIV_64 6
+
+#define FT_QSPI_TRANSFER_1_1_1 0
+#define FT_QSPI_TRANSFER_1_1_2 1
+#define FT_QSPI_TRANSFER_1_1_4 2
+#define FT_QSPI_TRANSFER_1_2_2 3
+#define FT_QSPI_TRANSFER_1_4_4 4
+#define FT_QSPI_TRANSFER_2_2_2 5
+#define FT_QSPI_TRANSFER_4_4_4 6
+
+/* smp */
+
+#define FT_SMP_EN
+
+#endif // !
diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_assert.c b/bsp/ft2004/libraries/bsp/standlone/ft_assert.c
new file mode 100644
index 0000000000..7ec987b2be
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/ft_assert.c
@@ -0,0 +1,43 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-05-18 13:43:09
+ * @Description:  This files is for type definition
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_types.h"
+#include "ft_assert.h"
+
+/************* 全局变量 用于判断驱动是否出现断言 *****************/
+u32 Ft_assertStatus;
+
+/************** 断言是否需要无限等待,1 等待,0不等待 ******************/
+s32 Ft_assertWait = 1;
+
+/* 当断言发生时,将会调用此函数 */
+static Ft_assertCallback Ft_assertCallbackRoutine = NULL;
+
+/************************** Function Prototypes ******************************/
+void Ft_assert(FT_IN char *File, s32 Line)
+{
+ if (Ft_assertCallbackRoutine != NULL)
+ {
+ Ft_assertCallbackRoutine(File, Line);
+ }
+
+ while (Ft_assertWait != 0)
+ {
+ }
+}
+
+void Ft_assertSetCallBack(Ft_assertCallback Routine)
+{
+ Ft_assertCallbackRoutine = Routine;
+}
diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_assert.h b/bsp/ft2004/libraries/bsp/standlone/ft_assert.h
new file mode 100644
index 0000000000..09e685e4af
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/ft_assert.h
@@ -0,0 +1,154 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-05-18 13:43:19
+ * @Description:  This files is for assert function
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef Ft_assert_H
+#define Ft_assert_H
+
+#include "ft_types.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define Fassert_NONE 0U
+#define Fassert_OCCURRED 1U
+
+ extern u32 Ft_assertStatus;
+ extern s32 Ft_assertWait;
+ extern void Ft_assert(FT_IN char *File, s32 Line);
+
+ typedef void (*Ft_assertCallback)(FT_IN char *File, s32 Line);
+
+/**
+ * @name: Ft_assertVoid
+ * @msg: 断言函数不带返回值
+ * @param {*}
+ * @return {*}
+ */
+#define Ft_assertVoid(Expression) \
+ { \
+ if (Expression) \
+ { \
+ Ft_assertStatus = Fassert_NONE; \
+ } \
+ else \
+ { \
+ Ft_assert(__FILE__, __LINE__); \
+ Ft_assertStatus = Fassert_OCCURRED; \
+ return; \
+ } \
+ }
+
+/**
+ * @name:
+ * @msg:
+ * @in param:
+ * @inout param:
+ * @out param:
+ * @return {*}
+ */
+#define Ft_assertBool(Expression) \
+ { \
+ if (Expression) \
+ { \
+ Ft_assertStatus = Fassert_NONE; \
+ } \
+ else \
+ { \
+ Ft_assert(__FILE__, __LINE__); \
+ Ft_assertStatus = Fassert_OCCURRED; \
+ return FALSE; \
+ } \
+ }
+
+/**
+ * @name: Ft_assertZeroNum
+ * @msg: 断言函数带返回值0
+ * @param {*}
+ * @return {*}
+ */
+#define Ft_assertZeroNum(Expression) \
+ { \
+ if (Expression) \
+ { \
+ Ft_assertStatus = Fassert_NONE; \
+ } \
+ else \
+ { \
+ Ft_assert(__FILE__, __LINE__); \
+ Ft_assertStatus = Fassert_OCCURRED; \
+ return FST_ASSERT_RETURN; \
+ } \
+ }
+
+/**
+ * @name: Ft_assertNonvoid
+ * @msg: 断言函数带返回值FST_ASSERT_RETURN
+ * @param {*}
+ * @return {*}
+ */
+#define Ft_assertNonvoid(Expression) \
+ { \
+ if (Expression) \
+ { \
+ Ft_assertStatus = Fassert_NONE; \
+ } \
+ else \
+ { \
+ Ft_assert(__FILE__, __LINE__); \
+ Ft_assertStatus = Fassert_OCCURRED; \
+ return FST_ASSERT_RETURN; \
+ } \
+ }
+
+/**
+ * @name: Ft_assertNoneReturn
+ * @msg: 断言函数不返回
+ * @param {*}
+ * @return {*}
+ */
+#define Ft_assertNoneReturn(Expression) \
+ { \
+ if (Expression) \
+ { \
+ Ft_assertStatus = Fassert_NONE; \
+ } \
+ else \
+ { \
+ Ft_assert(__FILE__, __LINE__); \
+ Ft_assertStatus = Fassert_OCCURRED; \
+ } \
+ }
+
+#define Ft_assertVoidAlways() \
+ { \
+ Ft_assert(__FILE__, __LINE__); \
+ Ft_assertStatus = Fassert_OCCURRED; \
+ return; \
+ }
+
+#define Ft_assertNonvoidAlways() \
+ { \
+ Ft_assert(__FILE__, __LINE__); \
+ Ft_assertStatus = Fassert_OCCURRED; \
+ return FST_ASSERT_RETURN; \
+ }
+
+ void Ft_assertSetCallBack(Ft_assertCallback routine);
+#ifdef __cplusplus
+}
+#endif
+
+#endif // !
diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_cache.c b/bsp/ft2004/libraries/bsp/standlone/ft_cache.c
new file mode 100644
index 0000000000..d99c8d3350
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/ft_cache.c
@@ -0,0 +1,86 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-16 14:00:59
+ * @LastEditTime: 2021-04-16 16:07:27
+ * @Description:  This files is for
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_cache.h"
+
+__STATIC_INLINE u32 FCache_cacheLineSize(void)
+{
+ u32 ctr;
+ asm volatile("mrc p15, 0, %0, c0, c0, 1"
+ : "=r"(ctr));
+ return 4 << ((ctr >> 16) & 0xF);
+}
+
+void FCache_cpuDcacheInvalidate(void *addr, ft_base_t size)
+{
+ u32 lineSize = FCache_cacheLineSize();
+ u32 startAddr = (u32)addr;
+ u32 endAddr = (u32)addr + size + lineSize - 1;
+
+ asm volatile("dmb" ::
+ : "memory");
+
+ startAddr &= ~(lineSize - 1);
+ endAddr &= ~(lineSize - 1);
+
+ while (startAddr < endAddr)
+ {
+ asm volatile("mcr p15, 0, %0, c7, c6, 1" ::"r"(startAddr)); /* dcimvac */
+ startAddr += lineSize;
+ }
+
+ asm volatile("dsb" ::
+ : "memory");
+}
+
+void FCache_cpuDcacheClean(void *addr, ft_base_t size)
+{
+ u32 lineSize = FCache_cacheLineSize();
+ u32 startAddr = (u32)addr;
+ u32 endAddr = (u32)addr + size + lineSize - 1;
+
+ asm volatile("dmb" ::
+ : "memory");
+
+ startAddr &= ~(lineSize - 1);
+ endAddr &= ~(lineSize - 1);
+
+ while (startAddr < endAddr)
+ {
+ asm volatile("mcr p15, 0, %0, c7, c10, 1" ::"r"(startAddr)); /* dccmvac */
+ startAddr += lineSize;
+ }
+
+ asm volatile("dsb" ::
+ : "memory");
+}
+
+void FCache_cpuIcacheInvalidate(void *addr, ft_base_t size)
+{
+ u32 lineSize = FCache_cacheLineSize();
+ u32 startAddr = (u32)addr;
+ u32 endAddr = (u32)addr + size + lineSize - 1;
+
+ asm volatile("dmb" ::
+ : "memory");
+ startAddr &= ~(lineSize - 1);
+ endAddr &= ~(lineSize - 1);
+ while (startAddr < endAddr)
+ {
+ asm volatile("mcr p15, 0, %0, c7, c5, 1" ::"r"(startAddr)); /* icimvau */
+ startAddr += lineSize;
+ }
+ asm volatile("dsb\n\tisb" ::
+ : "memory");
+}
diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_cache.h b/bsp/ft2004/libraries/bsp/standlone/ft_cache.h
new file mode 100644
index 0000000000..a0c78d7a9c
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/ft_cache.h
@@ -0,0 +1,32 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-13 21:52:20
+ * @LastEditTime: 2021-04-13 21:52:20
+ * @Description:  Description of file
+ * @Modify History:
+ * * * Ver   Who        Date         Changes
+ * * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef FT_CACHE_H
+#define FT_CACHE_H
+
+#include "ft_types.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void FCache_cpuDcacheInvalidate(void *addr, ft_base_t size);
+ void FCache_cpuDcacheClean(void *addr, ft_base_t size);
+ void FCache_cpuIcacheInvalidate(void *addr, ft_base_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // !FT_CACHE_H
diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_cpu.c b/bsp/ft2004/libraries/bsp/standlone/ft_cpu.c
new file mode 100644
index 0000000000..5162395c25
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/ft_cpu.c
@@ -0,0 +1,145 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-20 11:32:32
+ * @LastEditTime: 2021-05-25 10:51:19
+ * @Description:  Description of file
+ * @Modify History:
+ * * * Ver   Who        Date         Changes
+ * * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_parameters.h"
+#include "ft_cpu.h"
+#include "ft_assert.h"
+#include "ft_printf.h"
+
+#ifdef FT_SMP_EN
+
+typedef union
+{
+ u32 Slock;
+ struct ArchTicket
+ {
+ u16 owner;
+ u16 next;
+ } Tickets;
+} FCpu_Lock_t;
+
+struct FCpu
+{
+ u32 IsReady;
+ FCpu_Lock_t Clock;
+};
+
+struct FCpu FCpu_Lock = {0};
+
+const u32 SoftAffiTable[4] = {0, 1, 0x100, 0x101};
+
+/**
+ * @name: FCpu_IdGet
+ * @msg: In a multiprocessor system, provides an additional PE identification mechanism for scheduling
+ purposes.
+ * @return {Aff0} Affinity level 0. The most significant affinity level field, for this PE in the system.
+ */
+s32 FCpu_IdGet(void)
+{
+ s32 cpu_id;
+ __asm__ volatile(
+ "mrc p15, 0, %0, c0, c0, 5"
+ : "=r"(cpu_id));
+ // Ft_printf("error cpu_id %x \r\n", cpu_id);
+ // cpu_id &= 0xf;
+
+ switch ((cpu_id & 0xfff))
+ {
+ case 1:
+ return 1;
+ case 0x100:
+ return 2;
+ case 0x101:
+ return 3;
+ default:
+ return (cpu_id & 0xf);
+ }
+}
+
+s32 FCpu_AffinityGet(void)
+{
+ s32 AffinityId;
+ __asm__ volatile(
+ "mrc p15, 0, %0, c0, c0, 5"
+ : "=r"(AffinityId));
+
+ return AffinityId & 0xfff;
+}
+
+void FCpu_SpinLockInit(void)
+{
+ FCpu_Lock.Clock.Slock = 0;
+ FCpu_Lock.IsReady = FT_COMPONENT_IS_READLY;
+}
+
+void FCpu_SpinLock(void)
+{
+ u32 Tmp;
+ u32 Newval;
+ FCpu_Lock_t LockVal;
+ Ft_assertVoid(FCpu_Lock.IsReady == FT_COMPONENT_IS_READLY);
+
+ __asm__ __volatile__(
+ "pld [%0]" ::"r"(&FCpu_Lock.Clock.Slock));
+
+ __asm__ __volatile__(
+ "1: ldrex %0, [%3]\n"
+ " add %1, %0, %4\n"
+ " strex %2, %1, [%3]\n"
+ " teq %2, #0\n"
+ " bne 1b"
+ : "=&r"(LockVal), "=&r"(Newval), "=&r"(Tmp)
+ : "r"(&FCpu_Lock.Clock.Slock), "I"(1 << 16)
+ : "cc");
+
+ while (LockVal.Tickets.next != LockVal.Tickets.owner)
+ {
+ __asm__ __volatile__("wfe" ::
+ : "memory");
+ LockVal.Tickets.owner = *(volatile unsigned short *)(&FCpu_Lock.Clock.Tickets.owner);
+ }
+
+ __asm__ volatile("dmb" ::
+ : "memory");
+}
+
+void FCpu_SpinUnlock(void)
+{
+ Ft_assertVoid(FCpu_Lock.IsReady == FT_COMPONENT_IS_READLY);
+ __asm__ volatile("dmb" ::
+ : "memory");
+ FCpu_Lock.Clock.Tickets.owner++;
+ __asm__ volatile("dsb ishst\nsev" ::
+ : "memory");
+}
+
+#else /*RT_USING_SMP*/
+
+s32 FCpu_IdGet(void)
+{
+ return 0;
+}
+void FCpu_SpinLockInit(void)
+{
+ return;
+}
+void FCpu_SpinLock(void)
+{
+ return;
+}
+void FCpu_SpinUnlock(void)
+{
+ return;
+}
+
+#endif
diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_cpu.h b/bsp/ft2004/libraries/bsp/standlone/ft_cpu.h
new file mode 100644
index 0000000000..7d941f00e1
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/ft_cpu.h
@@ -0,0 +1,26 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-20 11:33:54
+ * @LastEditTime: 2021-04-20 11:33:55
+ * @Description:  Description of file
+ * @Modify History:
+ * * * Ver   Who        Date         Changes
+ * * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef FT_CPU_H
+#define FT_CPU_H
+
+#include "ft_types.h"
+#include "ft_error_code.h"
+extern const u32 SoftAffiTable[4];
+s32 FCpu_IdGet(void);
+void FCpu_SpinLockInit(void);
+void FCpu_SpinLock(void);
+void FCpu_SpinUnlock(void);
+s32 FCpu_AffinityGet(void);
+
+#endif // !FT_SPIN_H
diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_debug.c b/bsp/ft2004/libraries/bsp/standlone/ft_debug.c
new file mode 100644
index 0000000000..79628b7def
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/ft_debug.c
@@ -0,0 +1,67 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-25 16:44:23
+ * @LastEditTime: 2021-04-25 16:44:23
+ * @Description:  Description of file
+ * @Modify History:
+ * * * Ver   Who        Date         Changes
+ * * ----- ------     --------    --------------------------------------
+ */
+#include "ft_debug.h"
+
+#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
+void Ft_DumpHexByte(const u8 *ptr, ft_base_t buflen)
+{
+ unsigned char *buf = (unsigned char *)ptr;
+ int i, j;
+
+ for (i = 0; i < buflen; i += 16)
+ {
+ Ft_printf("0x%08X: ", ptr + i);
+
+ for (j = 0; j < 16; j++)
+ if (i + j < buflen)
+ Ft_printf("%02X ", buf[i + j]);
+ else
+ Ft_printf(" ");
+ Ft_printf(" ");
+
+ for (j = 0; j < 16; j++)
+ if (i + j < buflen)
+ Ft_printf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
+ Ft_printf("\r\n");
+ }
+}
+
+void Ft_DumpHexWord(const u32 *ptr, ft_base_t buflen)
+{
+ u32 *buf = (u32 *)ptr;
+ int i, j;
+ buflen = buflen / 4;
+ for (i = 0; i < buflen; i += 4)
+ {
+ Ft_printf("0x%08X: ", ptr + i);
+
+ for (j = 0; j < 4; j++)
+ {
+ if (i + j < buflen)
+ {
+ Ft_printf("%08X ", buf[i + j]);
+ }
+ else
+ {
+ Ft_printf(" ");
+ }
+ }
+
+ Ft_printf(" ");
+
+ for (j = 0; j < 16; j++)
+ if (i + j < buflen)
+ Ft_printf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
+ Ft_printf("\r\n");
+ }
+}
diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_debug.h b/bsp/ft2004/libraries/bsp/standlone/ft_debug.h
new file mode 100644
index 0000000000..ef11bd8d9b
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/ft_debug.h
@@ -0,0 +1,78 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-04-25 17:19:03
+ * @Description:  This files is for debug functions
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef FT_DEBUG_H
+#define FT_DEBUG_H
+
+#include "ft_printf.h"
+
+typedef enum
+{
+ FT_LOG_NONE, /*!< No log output */
+ FT_LOG_ERROR, /*!< Critical errors, software module can not recover on its own */
+ FT_LOG_WARN, /*!< Error conditions from which recovery measures have been taken */
+ FT_LOG_INFO, /*!< Information messages which describe normal flow of events */
+ FT_LOG_DEBUG, /*!< Extra information which is not necessary for normal use (values, pointers, sizes, etc). */
+ FT_LOG_VERBOSE /*!< Bigger chunks of debugging information, or frequent messages which can potentially flood the output. */
+} ft_log_level_t;
+
+#define LOG_COLOR_BLACK "30"
+#define LOG_COLOR_RED "31"
+#define LOG_COLOR_GREEN "32"
+#define LOG_COLOR_BROWN "33"
+#define LOG_COLOR_BLUE "34"
+#define LOG_COLOR_PURPLE "35"
+#define LOG_COLOR_CYAN "36"
+#define LOG_COLOR(COLOR) "\033[0;" COLOR "m"
+#define LOG_BOLD(COLOR) "\033[1;" COLOR "m"
+#define LOG_RESET_COLOR "\033[0m"
+#define LOG_COLOR_E LOG_COLOR(LOG_COLOR_RED)
+#define LOG_COLOR_W LOG_COLOR(LOG_COLOR_BROWN)
+#define LOG_COLOR_I LOG_COLOR(LOG_COLOR_GREEN)
+#define LOG_COLOR_D
+#define LOG_COLOR_V
+
+#ifndef LOG_LOCAL_LEVEL
+#define LOG_LOCAL_LEVEL FT_LOG_VERBOSE
+#endif
+
+#define LOG_FORMAT(letter, format) LOG_COLOR_##letter " %s: " format LOG_RESET_COLOR "\r\n"
+
+#define PORT_KPRINTF Ft_printf
+
+#define LOG_EARLY_IMPL(tag, format, log_level, log_tag_letter, ...) \
+ do \
+ { \
+ if (LOG_LOCAL_LEVEL < log_level) \
+ break; \
+ PORT_KPRINTF(LOG_FORMAT(log_tag_letter, format), tag, ##__VA_ARGS__); \
+ } while (0)
+
+#define EARLY_LOGE(tag, format, ...) LOG_EARLY_IMPL(tag, format, FT_LOG_ERROR, E, ##__VA_ARGS__)
+#define EARLY_LOGI(tag, format, ...) LOG_EARLY_IMPL(tag, format, FT_LOG_INFO, I, ##__VA_ARGS__)
+#define EARLY_LOGD(tag, format, ...) LOG_EARLY_IMPL(tag, format, FT_LOG_DEBUG, D, ##__VA_ARGS__)
+#define EARLY_LOGW(tag, format, ...) LOG_EARLY_IMPL(tag, format, FT_LOG_WARN, W, ##__VA_ARGS__)
+#define EARLY_LOGV(tag, format, ...) LOG_EARLY_IMPL(tag, format, FT_LOG_VERBOSE, W, ##__VA_ARGS__)
+
+#define FT_DEBUG_PRINT_I(TAG, format, ...) EARLY_LOGI(TAG, format, ##__VA_ARGS__)
+#define FT_DEBUG_PRINT_E(TAG, format, ...) EARLY_LOGE(TAG, format, ##__VA_ARGS__)
+#define FT_DEBUG_PRINT_D(TAG, format, ...) EARLY_LOGD(TAG, format, ##__VA_ARGS__)
+#define FT_DEBUG_PRINT_W(TAG, format, ...) EARLY_LOGW(TAG, format, ##__VA_ARGS__)
+#define FT_DEBUG_PRINT_V(TAG, format, ...) EARLY_LOGV(TAG, format, ##__VA_ARGS__)
+
+#define FT_RAW_PRINTF(format, ...) PORT_KPRINTF(format, ##__VA_ARGS__)
+
+void Ft_DumpHexWord(const u32 *ptr, ft_base_t buflen);
+void Ft_DumpHexByte(const u8 *ptr, ft_base_t buflen);
+#endif // !
diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_error_code.h b/bsp/ft2004/libraries/bsp/standlone/ft_error_code.h
new file mode 100644
index 0000000000..9c1a309367
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/ft_error_code.h
@@ -0,0 +1,72 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:30
+ * @LastEditTime: 2021-05-24 10:12:07
+ * @Description:  This files is for error code functions
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef _FT_ERROR_CODE_H
+#define _FT_ERROR_CODE_H
+
+#include "ft_status.h"
+#include "ft_types.h"
+
+typedef ft_base_t ft_error_t;
+
+/* 系统错误码模块定义 */
+typedef enum _ft_errcode_module_mask
+{
+ errModGeneral = 0,
+ errModBsp,
+ ERR_MODE_UART,
+ errModeI2c,
+ errModeGmac,
+ errModeSdCtrl,
+ errCan,
+ errGicV3,
+ errQspi,
+ ERR_MODE_SD_MMC,
+ ERR_MODE_SPI,
+
+ errModMaxMask = 255,
+} ft_errcode_module_mask_t;
+
+/* BSP模块的错误子模块定义 */
+typedef enum _ft_errcode_bsp_mask
+{
+ errBspGeneral = 0,
+ errBspClk,
+ errBspRtc,
+ errPort,
+ errBspModMaxMask = 255
+} ft_errcode_bsp_mask_t;
+
+#define FT_ERRCODE_SYS_MODULE_OFFSET 24
+#define FT_ERRCODE_SUB_MODULE_OFFSET 16
+
+#define FT_ERRCODE_SYS_MODULE_MASK (0xff << FT_ERRCODE_SYS_MODULE_OFFSET) /* bit 24 .. 31 */
+#define FT_ERRCODE_SUB_MODULE_MASK (0xff << FT_ERRCODE_SUB_MODULE_OFFSET) /* bit 16 .. 23 */
+#define FT_ERRCODE_TAIL_VALUE_MASK (0xffff) /* bit 1 .. 15 */
+
+/* Offset error code */
+#define FT_ERRCODE_OFFSET(code, offset, mask) \
+ (((code) << offset) & mask)
+
+/* Assembly error code */
+#define FT_MAKE_ERRCODE(sys_mode, sub_mode, tail) \
+ ((FT_ERRCODE_OFFSET(sys_mode, FT_ERRCODE_SYS_MODULE_OFFSET, FT_ERRCODE_SYS_MODULE_MASK)) | \
+ (FT_ERRCODE_OFFSET(sub_mode, FT_ERRCODE_SUB_MODULE_OFFSET, FT_ERRCODE_SUB_MODULE_MASK)) | \
+ (tail & FT_ERRCODE_TAIL_VALUE_MASK))
+#define FT_CODE_ERR FT_MAKE_ERRCODE
+
+#define ERR_SUCCESS FT_MAKE_ERRCODE(errModGeneral, errBspGeneral, FST_SUCCESS) /* 成功 */
+#define ERR_GENERAL FT_MAKE_ERRCODE(errModGeneral, errBspGeneral, FST_FAILURE) /* 一般错误 */
+
+#endif
diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_generic_timer.c b/bsp/ft2004/libraries/bsp/standlone/ft_generic_timer.c
new file mode 100644
index 0000000000..e4e1ab6d5f
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/ft_generic_timer.c
@@ -0,0 +1,327 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-05-25 10:51:35
+ * @Description:  This files is for generic timer functions
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_status.h"
+#include "ft_types.h"
+#include "ft_generic_timer.h"
+#include "ft_printf.h"
+#include "ft_assert.h"
+#include "ft_aarch32_asm.h"
+#include "ft_cpu.h"
+
+#define GENERICTIMER_ASM(x) __asm__ volatile(x)
+#define USEVIRTUAL 0
+#define USE_ISRNUM GEN_TIMER_PHYSICAL_NOSECURE_IRQN
+
+static volatile u32 _TickCnt;
+static volatile u32 _Tickms;
+
+typedef struct ft_Generictimer
+{
+ u64 Frequency;
+ u64 MaxCount;
+ u64 TicksPerUs;
+ u32 Isr_PeriodMsec;
+ u32 Isr_PeriodCnt; //<! 中断周期填充值
+ u8 UseVirtual;
+ u8 InitFlg; //<! 初始化标志,1 is 完成初始化,0 is 尚未初始化
+ u8 Isr_IsEnable; //<! 1 is init , 2 is open, 0 is close
+ Ft_GenericTimer_Isr_Callback Callback;
+} ft_Generictimer_handler_t;
+
+ft_Generictimer_handler_t Ft_GenericTimer_Handler = {0};
+
+/**
+ * @name: GenericTimer_WriteReg
+ * @msg:
+ * @in IsVirtual{u8}: 1 使用 虚拟计数器,0 使用物理计数器
+ * @in reg{u32}: 需要写入寄存器类型, GEN_TIMER_REG_CTL ,GEN_TIMER_REG_TVAL 。
+ * @in val{u32}: 需要写入参数 GEN_TIMER_CTRL_ENABLE GEN_TIMER_CTRL_IMASK GEN_TIMER_CTRL_ISTATUS
+ * @return {*}
+ */
+__STATIC_INLINE void GenericTimer_WriteReg(FT_IN u8 IsVirtual, FT_IN u32 reg, FT_IN u32 val)
+{
+ if (IsVirtual)
+ {
+ if (reg == GEN_TIMER_REG_CTL)
+ {
+ arm_aarch32_cnthv_ctl_set(val);
+ }
+ else
+ {
+ arm_aarch32_cnthv_tval_set(val);
+ }
+ }
+ else
+ {
+ if (reg == GEN_TIMER_REG_CTL)
+ {
+ arm_aarch32_cntp_ctl_set(val);
+ }
+ else
+ {
+ arm_aarch32_cntp_tval_set(val);
+ }
+ }
+
+ GENERICTIMER_ASM("ISB");
+}
+
+/**
+ * @name: GenericTimer_ReadReg
+ * @msg: 读取GenericTimer 寄存器参数。
+ * @in IsVirtual{u8}: 1 使用 虚拟计数器,0 使用物理计数器
+ * @in reg{u32}: 需要写入寄存器类型, GEN_TIMER_REG_CTL ,GEN_TIMER_REG_TVAL 。
+ * @return {u32} 读取寄存器参数
+ */
+__STATIC_INLINE u32 GenericTimer_ReadReg(FT_IN u8 IsVirtual, FT_IN u32 reg)
+{
+ u32 val = 0;
+
+ if (IsVirtual)
+ {
+ if (reg == GEN_TIMER_REG_CTL)
+ {
+ val = arm_aarch32_cnthv_ctl_get();
+ }
+ else
+ {
+ val = arm_aarch32_cnthv_tval_get();
+ }
+ }
+ else
+ {
+ if (reg == GEN_TIMER_REG_CTL)
+ {
+ val = arm_aarch32_cntp_ctl_get();
+ }
+ else
+ {
+ val = arm_aarch32_cntp_ctl_get();
+ }
+ }
+
+ return val;
+}
+
+/**
+ * @name: GenericTimer_GetTimerCnt
+ * @msg: 获取定时器定时器计数值。
+ * @in IsVirtual{u8}: 1 使用 虚拟计数器,0 使用物理计数器
+ * @return {u64} timer count value.
+ */
+__STATIC_INLINE u64 GenericTimer_GetTimerCnt(FT_IN u8 IsVirtual)
+{
+
+ GENERICTIMER_ASM("ISB");
+
+ if (IsVirtual)
+ {
+ return arm_aarch32_cntvct_get();
+ }
+ else
+ {
+ return arm_aarch32_cntpct_get();
+ }
+}
+
+/**
+ * @name: Ft_GenericTimer_UsDelay
+ * @msg: 使用定时器进行us级别延时
+ * @in param{u32}: DelayUs 需要延时的us
+ * @param {u32} DelayUs
+ */
+int32_t Ft_GenericTimer_UsDelay(FT_IN u32 DelayUs)
+{
+ register volatile u64 oldVal;
+ register volatile u64 newVal;
+ register volatile u64 decElapsed = 0;
+ register volatile u64 totalDelta;
+
+ int loopcount = 0;
+
+ if (Ft_GenericTimer_Handler.InitFlg == 0)
+ {
+ return FST_FAILURE;
+ }
+
+ if (DelayUs == 0)
+ {
+ return FST_FAILURE;
+ }
+
+ if (Ft_GenericTimer_Handler.TicksPerUs != 48)
+ {
+ //Ft_printf("ticksPerUs-%d should be 48 for this board, please check it!\r\n", Ft_GenericTimer_Handler.TicksPerUs);
+ }
+
+ totalDelta = Ft_GenericTimer_Handler.TicksPerUs * (u64)DelayUs;
+ oldVal = GenericTimer_GetTimerCnt(Ft_GenericTimer_Handler.UseVirtual);
+
+ while (decElapsed < totalDelta)
+ {
+ loopcount++;
+ newVal = GenericTimer_GetTimerCnt(Ft_GenericTimer_Handler.UseVirtual);
+
+ if (newVal == oldVal)
+ {
+ continue;
+ }
+
+ /* no rollover. count down... */
+
+ if (newVal < oldVal)
+ {
+ decElapsed += (oldVal - newVal);
+ }
+ /* rollover */
+ else
+ {
+ decElapsed += ((Ft_GenericTimer_Handler.MaxCount - oldVal) + newVal);
+ }
+
+ oldVal = newVal;
+ }
+
+ return FST_SUCCESS;
+}
+
+/**
+ * @name: Ft_GenericTimer_IsrSet
+ * @msg: 配置与控制 GenericTimer 中断参数
+ * @in param{u32}: HzRate 设置需要中断频率,输入参数应该小于等于 1000。
+ * @in param{u32}: Cmd 1 使能中断,0关闭中断。
+ * @return {int32_t}: 设置是否成功
+ */
+int32_t Ft_GenericTimer_IsrSet(FT_IN u32 HzRate, FT_IN u32 Cmd)
+{
+
+ Ft_assertNonvoid(HzRate <= 1000);
+ Ft_assertNonvoid(Ft_GenericTimer_Handler.InitFlg != 0);
+
+ if (Cmd == 1)
+ {
+ if (Ft_GenericTimer_Handler.Isr_IsEnable == 2)
+ {
+ //<! turn off isr
+ GenericTimer_WriteReg(Ft_GenericTimer_Handler.UseVirtual, GEN_TIMER_REG_CTL,
+ GEN_TIMER_CTRL_IMASK);
+ }
+
+ Ft_GenericTimer_Handler.Isr_IsEnable = 1;
+ Ft_GenericTimer_Handler.Isr_PeriodCnt = Ft_GenericTimer_Handler.Frequency / HzRate;
+ Ft_GenericTimer_Handler.Isr_PeriodMsec = 1000 / HzRate;
+ /* update the timer value register with maxTimerCount */
+ GenericTimer_WriteReg(Ft_GenericTimer_Handler.UseVirtual, GEN_TIMER_REG_TVAL,
+ Ft_GenericTimer_Handler.Isr_PeriodCnt);
+
+ /* set up the timer control register */
+ GenericTimer_WriteReg(Ft_GenericTimer_Handler.UseVirtual, GEN_TIMER_REG_CTL,
+ GEN_TIMER_CTRL_ENABLE);
+ }
+ else if (Cmd == 0)
+ {
+ Ft_GenericTimer_Handler.Isr_IsEnable = 0;
+ Ft_GenericTimer_Handler.Isr_PeriodCnt = Ft_GenericTimer_Handler.Frequency / HzRate;
+ //<! turn off isr
+ GenericTimer_WriteReg(Ft_GenericTimer_Handler.UseVirtual, GEN_TIMER_REG_CTL,
+ GEN_TIMER_CTRL_IMASK);
+ }
+ else
+ {
+ return FST_FAILURE;
+ }
+ return FST_SUCCESS;
+}
+
+/**
+ * @name: Ft_GenericTimer_IrqHandler
+ * @msg: 中断函数
+ * @in param{void *}: param 用户定义变量。
+ */
+void Ft_GenericTimer_IrqHandler(void *param)
+{
+ /* update the timer value register with maxTimerCount */
+ GenericTimer_WriteReg(Ft_GenericTimer_Handler.UseVirtual, GEN_TIMER_REG_TVAL,
+ Ft_GenericTimer_Handler.Isr_PeriodCnt);
+
+ /* set up the timer control register */
+ GenericTimer_WriteReg(Ft_GenericTimer_Handler.UseVirtual, GEN_TIMER_REG_CTL,
+ GEN_TIMER_CTRL_ENABLE);
+
+ if (Ft_GenericTimer_Handler.Callback)
+ {
+ Ft_GenericTimer_Handler.Callback(param);
+ }
+
+ _TickCnt++;
+
+ _Tickms += Ft_GenericTimer_Handler.Isr_PeriodMsec;
+}
+
+void Ft_GenericTimer_Debug(void)
+{
+ Ft_printf("GenericTimer_ReadReg %x \r\n", GenericTimer_ReadReg(Ft_GenericTimer_Handler.UseVirtual, GEN_TIMER_REG_CTL));
+}
+
+/**
+ * @name: Ft_GenericTimer_GetTick
+ * @msg: 获取中断计数次数
+ * @return {u32} _TickCnt
+ */
+u32 Ft_GenericTimer_GetTick(void)
+{
+ return _TickCnt;
+}
+
+/**
+ * @name: Ft_GenericTimer_Msec
+ * @msg: 获取中断ms级别计数
+ * @return {u32}
+ */
+u32 Ft_GenericTimer_Msec(void)
+{
+ return _Tickms;
+}
+
+/**
+ * @name: Ft_GenericTimer_Init
+ * @msg: GenericTimer 初始化
+ * @in param { u8} UseVirtual 1 使用 虚拟时钟,0使用真实时钟。
+ * @in param { Ft_GenericTimer_Isr_Callback} 中断回调函数。
+ * @return {*}
+ */
+void Ft_GenericTimer_Init(FT_IN u8 UseVirtual, FT_IN Ft_GenericTimer_Isr_Callback Callback)
+{
+ Ft_GenericTimer_Handler.Frequency = arm_aarch32_cntfrq_get();
+
+ Ft_GenericTimer_Handler.TicksPerUs = Ft_GenericTimer_Handler.Frequency / 1000000;
+
+ Ft_GenericTimer_Handler.MaxCount = 0xffffffffffffffffull;
+ Ft_GenericTimer_Handler.Callback = Callback;
+ Ft_GenericTimer_Handler.UseVirtual = UseVirtual;
+ Ft_GenericTimer_Handler.InitFlg = 1;
+ Ft_GenericTimer_Handler.Isr_IsEnable = 0;
+ _Tickms = 0;
+ _TickCnt = 0;
+
+ //<! 开启时钟
+ /* update the timer value register with maxTimerCount */
+ GenericTimer_WriteReg(Ft_GenericTimer_Handler.UseVirtual, GEN_TIMER_REG_TVAL,
+ Ft_GenericTimer_Handler.MaxCount);
+
+ /* set up the timer control register */
+ GenericTimer_WriteReg(Ft_GenericTimer_Handler.UseVirtual, GEN_TIMER_REG_CTL,
+ GEN_TIMER_CTRL_ENABLE);
+}
diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_generic_timer.h b/bsp/ft2004/libraries/bsp/standlone/ft_generic_timer.h
new file mode 100644
index 0000000000..98d2860440
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/ft_generic_timer.h
@@ -0,0 +1,57 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-04-07 15:27:27
+ * @Description:  This files is for generic timer functions
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef FT_GENERIC_TIMER_H
+#define FT_GENERIC_TIMER_H
+
+#include "ft_types.h"
+
+/* GenericTimer */
+
+#define ARMV7_GEN_TIMER_NAME "armv7GenTimer"
+#define ARMV7_GEN_TIMER_MAX_COUNT 0x7fffffff
+#define ARMV7_GEN_TIMER_DEFAULT_TPS 60
+#define ARMV7_GEN_TIMER_DEFAULT_MIN_FREQ 10
+#define ARMV7_GEN_TIMER_DEFAULT_MAX_FREQ 5000
+#define ARMV7_GEN_TIMER_MAX_CLK_FREQ 50000000
+#define ARMV7_GEN_TIMER_MIN_CLK_FREQ 1000000
+
+#define GEN_TIMER_REG_CTL 0 //<! Control register for the Hyp mode physical timer.
+#define GEN_TIMER_REG_TVAL 1 //<! Holds the timer value for the Hyp mode physical timer.
+
+#define GEN_TIMER_CTRL_ENABLE (1 << 0)
+#define GEN_TIMER_CTRL_IMASK (1 << 1)
+#define GEN_TIMER_CTRL_ISTATUS (1 << 2)
+
+#define GEN_TIMER_SECURE_PHY_PPI (0)
+#define GEN_TIMER_NON_SECURE_PHY_PPI (1)
+#define GEN_TIMER_VIRTURE_PPI (2)
+#define GEN_TIMER_HYP_PPI (3)
+#define GEN_TIMER_MAX_PPI (4)
+
+#define GEN_TIMER_VIRTUAL_IRQN 27 /**< Virtual Timer Interrupt */
+#define GEN_TIMER_VIRTUAL_NOSECURE_IRQN 28
+#define GEN_TIMER_PHYSICAL_IRQn 29
+#define GEN_TIMER_PHYSICAL_NOSECURE_IRQN 30 /**< Secure Physical Timer Interrupt */
+
+typedef void (*Ft_GenericTimer_Isr_Callback)(void *args);
+
+void Ft_GenericTimer_Init(FT_IN u8 UseVirtual, FT_IN Ft_GenericTimer_Isr_Callback Callback);
+int32_t Ft_GenericTimer_IsrSet(FT_IN u32 HzRate, FT_IN u32 Cmd);
+void Ft_GenericTimer_IrqHandler(void *param);
+int32_t Ft_GenericTimer_UsDelay(FT_IN u32 DelayUs);
+u32 Ft_GenericTimer_GetTick(void);
+u32 Ft_GenericTimer_Msec(void);
+
+#endif // !
diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_io.h b/bsp/ft2004/libraries/bsp/standlone/ft_io.h
new file mode 100644
index 0000000000..50b9b9ff65
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/ft_io.h
@@ -0,0 +1,164 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-04-07 15:29:06
+ * @Description:  This files is for general reigster io functions
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef FT_IO_H
+#define FT_IO_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "ft_types.h"
+
+#if defined(__GNUC__) || defined(__ICCARM__) || defined(__MICROBLAZE__)
+#define INLINE inline
+#else
+#define INLINE __inline
+#endif
+
+ /**
+ * @name: Ft_in8
+ * @msg: Read byte value
+ * @in param {UINTPTR}: Addr 需要读取的地址
+ * @return {u8} Byte Value
+ */
+ static INLINE u8 Ft_in8(FT_IN UINTPTR Addr)
+ {
+ return *(volatile u8 *)Addr;
+ }
+
+ /**
+ * @name: Ft_in16
+ * @msg: Read half-word value
+ * @in param {UINTPTR}: Addr 需要读取的地址
+ * @return {u16} Half-word Value
+ */
+ static INLINE u16 Ft_in16(FT_IN UINTPTR Addr)
+ {
+ return *(volatile u16 *)Addr;
+ }
+
+ /**
+ * @name: Ft_in32
+ * @msg: Read word value
+ * @in param {UINTPTR}: Addr 需要读取的地址
+ * @return {u16} Word Value
+ */
+ static INLINE u32 Ft_in32(FT_IN UINTPTR Addr)
+ {
+ return *(volatile u32 *)Addr;
+ }
+
+ /**
+ * @name: Ft_in64
+ * @msg: Read u64 value
+ * @in param {UINTPTR}: Addr 需要读取的地址
+ * @return {u16} u64 Value
+ */
+ static INLINE u64 Ft_in64(FT_IN UINTPTR Addr)
+ {
+ return *(volatile u64 *)Addr;
+ }
+
+ /**
+ * @name: Ft_out8
+ * @msg: write byte value
+ * @in param {UINTPTR}: Addr 需要写入的地址
+ * @in param {u8}: Need write value
+ * @return {*}
+ */
+ static INLINE void Ft_out8(FT_IN UINTPTR Addr, FT_IN u8 Value)
+ {
+ volatile u8 *LocalAddr = (volatile u8 *)Addr;
+ *LocalAddr = Value;
+ }
+
+ /**
+ * @name: Ft_out16
+ * @msg: write half-word value
+ * @in param {UINTPTR}: Addr 需要写入的地址
+ * @in param {u16}: Need write value
+ * @return {*}
+ */
+ static INLINE void Ft_out16(FT_IN UINTPTR Addr, FT_IN u16 Value)
+ {
+ volatile u16 *LocalAddr = (volatile u16 *)Addr;
+ *LocalAddr = Value;
+ }
+
+ /**
+ * @name: Ft_out32
+ * @msg: write half-word value
+ * @in param {UINTPTR}: Addr 需要写入的地址
+ * @in param {u32}: Need write value
+ * @return {*}
+ */
+ static INLINE void Ft_out32(FT_IN UINTPTR Addr, FT_IN u32 Value)
+ {
+ volatile u32 *LocalAddr = (volatile u32 *)Addr;
+ *LocalAddr = Value;
+ }
+
+ /**
+ * @name: Ft_out64
+ * @msg: write u64 value
+ * @in param {UINTPTR}: Addr 需要写入的地址
+ * @in param {u64}: Need write value
+ * @return {*}
+ */
+ static INLINE void Ft_out64(FT_IN UINTPTR Addr, FT_IN u64 Value)
+ {
+ volatile u64 *LocalAddr = (volatile u64 *)Addr;
+ *LocalAddr = Value;
+ }
+
+ /**
+ * @name: Ft_setBit32
+ * @msg:
+ * @in param {FT_INUINTPTR} addr
+ * @in param {FT_INu32} offset
+ * @in param {FT_INu32} value
+ */
+ static INLINE void Ft_setBit32(FT_IN UINTPTR addr, FT_IN u32 value)
+ {
+ u32 lastValue;
+ lastValue = Ft_in32(addr);
+ lastValue |= value;
+ Ft_out32(addr, lastValue);
+ }
+
+ /**
+ * @name: Ft_clearBit32
+ * @msg:
+ * @in param:
+ * @inout param:
+ * @out param:
+ * @return {*}
+ * @param {FT_INUINTPTR} addr
+ * @param {FT_INu32} value
+ */
+ static INLINE void Ft_clearBit32(FT_IN UINTPTR addr, FT_IN u32 value)
+ {
+ u32 lastValue;
+ lastValue = Ft_in32(addr);
+ lastValue &= ~value;
+ Ft_out32(addr, lastValue);
+ }
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // !
diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_list.h b/bsp/ft2004/libraries/bsp/standlone/ft_list.h
new file mode 100644
index 0000000000..bbb3e4e78f
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/ft_list.h
@@ -0,0 +1,23 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-04-07 15:29:20
+ * @Description:  This files is for list data structure
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef FT_LIST_H
+#define FT_LIST_H
+
+#include "ft_types.h"
+
+#define container_of(ptr, type, member) \
+ ((type *)((s8 *)(ptr) - (u32)(&((type *)0)->member)))
+
+#endif // ! FT_LIST_H
diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_math.c b/bsp/ft2004/libraries/bsp/standlone/ft_math.c
new file mode 100644
index 0000000000..244ed1700e
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/ft_math.c
@@ -0,0 +1,19 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-28 22:15:48
+ * @LastEditTime: 2021-04-28 22:15:48
+ * @Description:  Description of file
+ * @Modify History:
+ * * * Ver   Who        Date         Changes
+ * * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_math.h"
+
+u32 Ft_Abs(s32 num)
+{
+ return (num >= 0 ? num : -num);
+}
diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_math.h b/bsp/ft2004/libraries/bsp/standlone/ft_math.h
new file mode 100644
index 0000000000..7456f18386
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/ft_math.h
@@ -0,0 +1,24 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-28 22:15:19
+ * @LastEditTime: 2021-04-28 22:15:19
+ * @Description:  Description of file
+ * @Modify History:
+ * * * Ver   Who        Date         Changes
+ * * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef FT_MATH_H
+#define FT_MATH_H
+
+#include "ft_types.h"
+
+#define FT_INT_MAX 2147483647
+#define FT_UINT_MAX (FT_INT_MAX * 2U + 1)
+
+u32 Ft_Abs(s32 num);
+
+#endif // !FT_MATH_H
diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_mux.c b/bsp/ft2004/libraries/bsp/standlone/ft_mux.c
new file mode 100644
index 0000000000..7127b9e564
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/ft_mux.c
@@ -0,0 +1,90 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-05-25 10:51:59
+ * @Description:  This files is for pin mux
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_mux.h"
+#include "ft_io.h"
+#include "ft_assert.h"
+#include "ft_printf.h"
+
+/**
+ * Description: enable i2c 1 ~ 3 pin pad mux
+ * Date: 2021-03-24 13:34:06
+ * Param:
+ * return {*}
+ * param {FT_IN u32} I2cId, i2c 0 ~ 3
+ */
+void Ft_setI2cMux(FT_IN u32 I2cId)
+{
+ u32 RegValue;
+
+ switch (I2cId)
+ {
+ case I2C0_ID:
+ /* i2c0 is by default enabled */
+ break;
+ case I2C1_ID:
+ /* select i2c1 SCL, SDA mux */
+ RegValue = Ft_in32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG200_OFFSET);
+ RegValue |= (I2C1_SCL_PIN_REG200_BIT | I2C1_SDA_PIN_REG200_BIT);
+ Ft_out32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG200_OFFSET, RegValue);
+ break;
+ case I2C2_ID:
+ Ft_assertNoneReturn(0);
+ break;
+ case I2C3_ID:
+ Ft_assertNoneReturn(0);
+ break;
+ default:
+ Ft_assertNoneReturn(0);
+ break;
+ }
+
+ return;
+}
+
+void Ft_setSpiMux(FT_IN u32 SpiId)
+{
+ u32 RegValue;
+
+ switch (SpiId)
+ {
+ case SPI0_ID:
+ /* spi0 is by default enabled */
+ RegValue = Ft_in32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG208_OFFSET);
+ /* clear specific bits to choose Func 0 */
+ RegValue |= SPI1_PORTA5_PIN_REG208_BIT;
+ Ft_out32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG208_OFFSET, RegValue);
+ Ft_printf("bef reg 208 0x%x\r\n", Ft_in32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG208_OFFSET));
+
+ break;
+ case SPI1_ID:
+ /* select spi cs, sck, so, si pin mux */
+ Ft_printf("bef reg 210 0x%x\r\n", Ft_in32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG210_OFFSET));
+ RegValue = Ft_in32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG210_OFFSET);
+ RegValue |= SPI1_CSN0_PIN_REG210_BIT;
+ Ft_out32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG210_OFFSET, RegValue);
+ Ft_printf("aft reg 210 0x%x\r\n", Ft_in32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG210_OFFSET));
+
+ Ft_printf("bef reg 214 0x%x\r\n", Ft_in32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG214_OFFSET));
+ RegValue = Ft_in32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG214_OFFSET);
+ RegValue |= SPI1_SCK_PIN_REG214_BIT | SPI1_SO_PIN_REG214_BIT | SPI1_SI_PIN_REG214_BIT;
+ Ft_out32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG214_OFFSET, RegValue);
+ Ft_printf("aft reg 214 0x%x\r\n", Ft_in32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG214_OFFSET));
+ break;
+ default:
+ break;
+ }
+
+ return;
+}
diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_mux.h b/bsp/ft2004/libraries/bsp/standlone/ft_mux.h
new file mode 100644
index 0000000000..c482154353
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/ft_mux.h
@@ -0,0 +1,75 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-05-26 15:39:16
+ * @Description:  This files is for pin mux
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef FT_BSP_MUX_H
+#define FT_BSP_MUX_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "ft_types.h"
+
+/* pad pin multi-function demu */
+#define FT_PIN_DEMUX_BASE 0x28180000
+#define FT_PIN_DEMUX_REG200_OFFSET 0x200
+#define FT_PIN_DEMUX_REG204_OFFSET 0x204
+#define FT_PIN_DEMUX_REG208_OFFSET 0x208
+#define FT_PIN_DEMUX_REG210_OFFSET 0x210
+#define FT_PIN_DEMUX_REG214_OFFSET 0x214
+
+/* i2c mux function option */
+#define I2C1_SCL_PIN_REG200_MASK ((u32)0x3 << 28) /* all_pll_lock_pad [29:28] */
+#define I2C1_SCL_PIN_REG200_BIT ((u32)0x2 << 28)
+#define I2C1_SDA_PIN_REG200_MASK ((u32)0x3 << 24) /* cru_clk_obv_pad [25:24] */
+#define I2C1_SDA_PIN_REG200_BIT ((u32)0x2 << 24)
+#define I2C2_SCL_PIN_REG204_MASK ((u32)0x3 << 8) /* swdo_swj_pad [9: 8] */
+#define I2C2_SCL_PIN_REG204_BIT ((u32)0x2 << 8)
+#define I2C2_SDA_PIN_REG204_MASK ((u32)0x3 << 6) /* tdo_swj_pad [7: 6] */
+#define I2C2_SDA_PIN_REG204_BIT ((u32)0x2 << 6)
+#define I2C3_SCL_PIN_REG204_MASK ((u32)0x3 << 0) /* hdt_mb_done_state_pad [1 : 0] */
+#define I2C3_SCL_PIN_REG204_BIT ((u32)0x2 << 0)
+#define I2C3_SDA_PIN_REG208_MASK ((u32)0x3 << 30) /* hdt_mb_fail_state_pad [31 : 30] */
+#define I2C3_SDA_PIN_REG208_BIT ((u32)0x2 << 30)
+
+#define SPI1_PORTA5_PIN_REG208_BIT ((u32)0x1 << 16)
+
+#define SPI1_CSN0_PIN_REG210_MASK ((u32)0x3 << 0) /* uart_2_rxd_pad [1 : 0] */
+#define SPI1_CSN0_PIN_REG210_BIT ((u32)0x1 << 0)
+#define SPI1_SCK_PIN_REG214_MASK ((u32)0x3 << 28) /* uart_2_txd_pad [29 : 28] */
+#define SPI1_SCK_PIN_REG214_BIT ((u32)0x1 << 28)
+#define SPI1_SO_PIN_REG214_MASK ((u32)0x3 << 24) /* uart_3_rxd_pad [25 : 24] */
+#define SPI1_SO_PIN_REG214_BIT ((u32)0x1 << 24)
+#define SPI1_SI_PIN_REG214_MASK ((u32)0x3 << 20) /* uart_3_txd_pad [21 : 20] */
+#define SPI1_SI_PIN_REG214_BIT ((u32)0x1 << 20)
+
+/* i2c ctrl instance */
+#define I2C0_ID 0
+#define I2C1_ID 1
+#define I2C2_ID 2
+#define I2C3_ID 3
+
+/* spi ctrl instance */
+#define SPI0_ID 0
+#define SPI1_ID 1
+
+ void Ft_setI2cMux(FT_IN u32 I2cId);
+ void Ft_setSpiMux(FT_IN u32 SpiId);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_printf.c b/bsp/ft2004/libraries/bsp/standlone/ft_printf.c
new file mode 100644
index 0000000000..db6a50f532
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/ft_printf.c
@@ -0,0 +1,96 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-05-26 15:20:14
+ * @Description:  This files is for printf function
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_printf.h"
+#include "stdio.h"
+#include "ft_aarch32_asm.h"
+
+static char print_buffer[PRINTF_BUFFER_LENGTH];
+
+extern void outbyte(char byte);
+
+vsprintf_p Vsprintf_pFun = (vsprintf_p)vsprintf;
+
+void Ft_vsprintfRegister(vsprintf_p f)
+{
+ Vsprintf_pFun = f;
+}
+
+void Ft_printf(const char *fmt, ...)
+{
+ va_list args;
+ size_t i;
+ size_t length;
+#ifdef NEED_CLOSE_ISR
+ IRQ_DISABLE();
+#endif
+ va_start(args, fmt);
+
+ length = Vsprintf_pFun(print_buffer, fmt, args);
+ va_end(args);
+ for (i = 0; i < length; i++)
+ {
+ outbyte(print_buffer[i]);
+ }
+
+#ifdef NEED_CLOSE_ISR
+ IRQ_ENABLE();
+#endif
+}
+
+char *Ft_itoa(int num, char *str, int radix)
+{
+ char index[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ unsigned unum;
+ int i = 0;
+ int j;
+ int k;
+ char temp;
+
+ if (radix == 10 && num < 0)
+ {
+ unum = (unsigned)-num;
+ str[i++] = '-';
+ }
+ else
+ {
+ unum = (unsigned)num;
+ }
+
+ do
+ {
+ str[i++] = index[unum % (unsigned)radix];
+ unum /= radix;
+ } while (unum);
+
+ str[i] = '\0';
+
+ if (str[0] == '-')
+ {
+ k = 1;
+ }
+ else
+ {
+ k = 0;
+ }
+
+ for (j = k; j <= (i - 1) / 2; j++)
+ {
+ temp = str[j];
+ str[j] = str[i - 1 + k - j];
+ str[i - 1 + k - j] = temp;
+ }
+
+ return str;
+}
diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_printf.h b/bsp/ft2004/libraries/bsp/standlone/ft_printf.h
new file mode 100644
index 0000000000..4d1d3ea867
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/ft_printf.h
@@ -0,0 +1,29 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-05-26 15:39:25
+ * @Description:  This files is for printf functions
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef Ft_printf_H
+#define Ft_printf_H
+
+#include <stdarg.h>
+#include "ft_types.h"
+
+#define PRINTF_BUFFER_LENGTH 4096
+
+typedef s32 (*vsprintf_p)(char *buf, const char *format, va_list arg_ptr);
+
+void Ft_vsprintfRegister(vsprintf_p f);
+void Ft_printf(const char *fmt, ...);
+char *Ft_itoa(int num, char *str, int radix);
+
+#endif // !
diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_psci.c b/bsp/ft2004/libraries/bsp/standlone/ft_psci.c
new file mode 100644
index 0000000000..1ca9e3379f
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/ft_psci.c
@@ -0,0 +1,78 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-21 10:43:52
+ * @LastEditTime: 2021-04-21 10:43:53
+ * @Description:  Description of file
+ * @Modify History:
+ * * * Ver   Who        Date         Changes
+ * * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_psci.h"
+#include "ft_smc.h"
+#include "ft_cpu.h"
+#include "ft_printf.h"
+
+#define PSCI_CPUON_NUM 0x84000003
+#define PSCI_RESET_NUM 0x84000009
+
+/**
+ * @name: FPsci_CpuOn
+ * @msg: Power up a core
+ * @in param CpuList: Bits[24:31]: Must be zero.
+ * Bits[16:23] Aff2: Match Aff2 of target core MPIDR
+ * Bits[8:15] Aff1: Match Aff1 of target core MPIDR
+ * Bits[0:7] Aff0: Match Aff0 of target core MPIDR
+ * @in param BootAddr: a 32-bit entry point physical address (or IPA).
+ * @return {None}
+ */
+void FPsci_CpuOn(s32 CpuIdMask, u32 BootAddr)
+{
+
+ FSmc_Data_t Input = {0};
+ FSmc_Data_t Output = {0};
+ Input.FunctionIdentifier = PSCI_CPUON_NUM;
+
+ if ((1 << 0) == CpuIdMask)
+ {
+ Input.a1 = SoftAffiTable[0];
+ }
+ else if ((1 << 1) == CpuIdMask)
+ {
+ Input.a1 = SoftAffiTable[1];
+ }
+ else if ((1 << 2) == CpuIdMask)
+ {
+ Input.a1 = SoftAffiTable[2];
+ }
+ else if ((1 << 3) == CpuIdMask)
+ {
+ Input.a1 = SoftAffiTable[3];
+ }
+ else
+ {
+ return;
+ }
+
+ /*input.a2 = (u32)(BootAddr >> 32);*/
+ Input.a2 = (u32)(BootAddr & 0xFFFFFFFF);
+ FSmc_Call(&Input, &Output);
+ __asm__ volatile("NOP");
+}
+
+void FPsci_Reset(void)
+{
+
+ FSmc_Data_t Input = {0};
+ FSmc_Data_t Output = {0};
+
+ Input.FunctionIdentifier = PSCI_RESET_NUM;
+ FSmc_Call(&Input, &Output);
+
+ __asm__ volatile("NOP");
+ while (1)
+ ;
+}
diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_psci.h b/bsp/ft2004/libraries/bsp/standlone/ft_psci.h
new file mode 100644
index 0000000000..b963c0092a
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/ft_psci.h
@@ -0,0 +1,31 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-21 10:43:59
+ * @LastEditTime: 2021-04-21 10:44:00
+ * @Description:  Description of file
+ * @Modify History:
+ * * * Ver   Who        Date         Changes
+ * * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef FT_PSCI_H
+#define FT_PSCI_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "ft_types.h"
+
+ void FPsci_CpuOn(s32 CpuIdMask, u32 BootAddr);
+ void FPsci_Reset(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // !
diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_smc.S b/bsp/ft2004/libraries/bsp/standlone/ft_smc.S
new file mode 100644
index 0000000000..c610350eb5
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/ft_smc.S
@@ -0,0 +1,36 @@
+
+
+/*******************************************************************************
+*
+* FSmc_Call - initiate SMC call
+*
+* This routine initiates SMC call which traps the processor into Monitor Mode.
+* The ARM SMC Call Convetion defines that up to eight registers can be exchanged
+* during an SMC call. The input parameter contains eight INT32 valeus which are
+* to be passed in the SMC call; similarily the output parameter also contains
+* eight INT32 values which are returned from the SMC call.
+*
+* \NOMANUAL
+*
+* RETURNS: OK
+*
+* void FSmc_Call
+* (
+* FSmc_Data_t * input, /@ r0 - input register values @/
+* FSmc_Data_t * output /@ r1 - output register values @/
+* )
+*/
+
+.arm
+.align 4
+.globl FSmc_Call
+FSmc_Call:
+ STMDB sp!, {r0-r7} /* save clobbered registers to stack */
+ ldr r12, [sp, #(4 * 0)] /* get 1st argument (ptr to input struct) */
+ ldmia r12, {r0-r7} /* save input argument to r0-r7 */
+ smc #0
+ ldr r12, [sp, #(4 * 1)] /* get 2th argument (ptr to output result) */
+ stmia r12, {r0-r7} /* get output argument from r0-r7 */
+ ldmfd sp!, {r0-r7} /* restore clobbered registers from stack */
+ bx lr
+.size FSmc_Call, .- FSmc_Call
diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_smc.h b/bsp/ft2004/libraries/bsp/standlone/ft_smc.h
new file mode 100644
index 0000000000..c241c09eca
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/ft_smc.h
@@ -0,0 +1,43 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-21 11:53:38
+ * @LastEditTime: 2021-04-21 11:53:38
+ * @Description:  Description of file
+ * @Modify History:
+ * * * Ver   Who        Date         Changes
+ * * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef FT_SMC_H
+#define FT_SMC_H
+
+#include "ft_types.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ typedef struct
+ {
+ /* data */
+ u32 FunctionIdentifier;
+ u32 a1;
+ u32 a2;
+ u32 a3;
+ u32 a4;
+ u32 a5;
+ u32 a6;
+
+ } FSmc_Data_t;
+
+ void FSmc_Call(FSmc_Data_t *Input, FSmc_Data_t *Output);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // !FT_SMC_H
diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_status.h b/bsp/ft2004/libraries/bsp/standlone/ft_status.h
new file mode 100644
index 0000000000..a30ac32cf8
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/ft_status.h
@@ -0,0 +1,82 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-04-07 15:31:10
+ * @Description:  This files is for definition of status
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef FT_STATUS_H
+#define FT_STATUS_H
+
+/**
+@name Common Status Codes
+*/
+
+typedef enum
+{
+ FST_SUCCESS = 0L,
+ FST_FAILURE = 1L,
+ FST_INSTANCE_NOT_FOUND = 2L,
+ FST_DEVICE_BLOCK_NOT_FOUND = 3L,
+ FST_INVALID_VERSION = 4L,
+ FST_DEVICE_IS_STARTED = 5L,
+ FST_DEVICE_IS_STOPPED = 6L,
+ FST_FIFO_ERROR = 7L, /* An error occurred during an \
+ operation with a FIFO such as \
+ an underrun or overrun, this \
+ error requires the device to \
+ be reset */
+ FST_RESET_ERROR = 8L, /* An error occurred which requires \
+ the device to be reset */
+ FST_DMA_ERROR = 9L, /* A DMA error occurred, this error \
+ typically requires the device \
+ using the DMA to be reset */
+ FST_NOT_POLLED = 10L, /* The device is not configured for \
+ polled mode operation */
+ FST_FIFO_NO_ROOM = 11L, /* A FIFO did not have room to put \
+ the specified data into */
+ FST_BUFFER_TOO_SMALL = 12L, /* The buffer is not large enough \
+ to hold the expected data */
+ FST_NO_DATA = 13L, /* There was no data available */
+ FST_REGISTER_ERROR = 14L, /* A register did not contain the \
+ expected value */
+ FST_INVALID_PARAM = 15L, /* An invalid parameter was passed \
+ into the function */
+ FST_NOT_SGDMA = 16L, /* The device is not configured for \
+ scatter-gather DMA operation */
+ FST_LOOPBACK_ERROR = 17L, /* A loopback test failed */
+ FST_NO_CALLBACK = 18L, /* A callback has not yet been \
+ registered */
+ FST_NO_FEATURE = 19L, /* Device is not configured with \
+ the requested feature */
+ FST_NOT_INTERRUPT = 20L, /* Device is not configured for \
+ interrupt mode operation */
+ FST_DEVICE_BUSY = 21L, /* Device is busy */
+ FST_ERROR_COUNT_MAX = 22L, /* The error counters of a device \
+ have maxed out */
+ FST_IS_STARTED = 23L, /* Used when part of device is \
+ already started i.e. \
+ sub channel */
+ FST_IS_STOPPED = 24L, /* Used when part of device is \
+ already stopped i.e. \
+ sub channel */
+ FST_DATA_LOST = 26L, /* Driver defined error */
+ FST_RECV_ERROR = 27L, /* Generic receive error */
+ FST_SEND_ERROR = 28L, /* Generic transmit error */
+ FST_NOT_ENABLED = 29L, /* A requested service is not \
+ available because it has not \
+ been enabled */
+ FST_ASSERT_RETURN = 30L, /* Assert occurs defined error */
+ FST_TIMEOUT = 31L,
+ FST_EILSEQ = 32L, /* Illegal byte sequence. */
+ FST_STATUS_MAX_VALUE = 0xffff /* Status max value */
+} Common_status;
+
+#endif // !FT_STATUS_H
diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_trace.c b/bsp/ft2004/libraries/bsp/standlone/ft_trace.c
new file mode 100644
index 0000000000..b3cc4d831d
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/ft_trace.c
@@ -0,0 +1,57 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-15 11:27:24
+ * @LastEditTime: 2021-05-25 10:52:32
+ * @Description:  This files is for
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+
+#include "ft_trace.h"
+#include "ft_printf.h"
+
+
+void Sdmmc_TraceHeapAlloc(const char *tag)
+{
+
+}
+
+void dump_hex(const u8 *ptr, u32 buflen, const char *tag)
+{
+ unsigned char *buf = (unsigned char *)ptr;
+ u32 i, j;
+
+ Ft_printf("dump hex for %s\r\n", tag);
+ for (i = 0; i < buflen; i += 16)
+ {
+ Ft_printf("%08X: ", ptr + i);
+
+ for (j = 0; j < 16; j++)
+ {
+ if (i + j < buflen)
+ {
+ Ft_printf("%02X ", buf[i + j]);
+ }
+ else
+ {
+ Ft_printf(" ");
+ }
+ }
+ Ft_printf(" ");
+
+ for (j = 0; j < 16; j++)
+ {
+ if (i + j < buflen)
+ {
+ Ft_printf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
+ }
+ }
+ Ft_printf("\r\n");
+ }
+}
diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_trace.h b/bsp/ft2004/libraries/bsp/standlone/ft_trace.h
new file mode 100644
index 0000000000..1c2ac0cb2d
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/ft_trace.h
@@ -0,0 +1,52 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-15 11:27:14
+ * @LastEditTime: 2021-04-16 13:40:55
+ * @Description:  This files is for
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef _FT_TRACE_H_
+#define _FT_TRACE_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "ft_debug.h"
+
+/* define debug log function */
+#define FT_MEM_TRACE_ENABLED
+#define FT_MEM_TRACE_TAG "FT_MEM"
+#ifdef FT_MEM_TRACE_ENABLED
+#define FT_MEM_TRACE(format, ...) FT_DEBUG_PRINT_I(FT_MEM_TRACE_TAG, format, ##__VA_ARGS__)
+#else
+#define FT_MEM_TRACE(format, ...)
+#endif
+
+#define FT_LOGIC_TRACE_ENABLED
+#define FT_LOGIC_TRACE_TAG "FT_LOGIC"
+#ifdef FT_LOGIC_TRACE_ENABLED
+#define FT_LOGIC_TRACE(format, ...) FT_DEBUG_PRINT_I(FT_LOGIC_TRACE_TAG, format, ##__VA_ARGS__)
+#define FT_MEM_TRACE_DUMP(buf, buflen, tag) dump_hex((buf), (buflen), (tag))
+#else
+#define FT_LOGIC_TRACE(format, ...)
+#define FT_MEM_TRACE_DUMP(buf, buflen, tag)
+#endif
+
+#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
+ void dump_hex(const u8 *ptr, u32 buflen, const char *tag);
+ void Sdmmc_TraceHeapAlloc(const char *tag);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_types.h b/bsp/ft2004/libraries/bsp/standlone/ft_types.h
new file mode 100644
index 0000000000..970d3e4e06
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/ft_types.h
@@ -0,0 +1,75 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-05-11 10:18:14
+ * @Description:  This files is for definition of system-level types
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#ifndef FT_TYPES_H
+#define FT_TYPES_H
+#include <stdint.h>
+#include <stddef.h>
+
+/* Constant Definitions */
+
+#ifndef TRUE
+#define TRUE 1U
+#endif
+
+#ifndef FALSE
+#define FALSE 0U
+#endif
+
+#ifndef NULL
+#define NULL 0U
+#endif
+
+#define FT_NULL NULL
+
+#define FT_COMPONENT_IS_READLY 0x11111111U
+#define FT_COMPONENT_IS_STARTED 0x22222222U
+
+#define __STATIC_INLINE static inline
+
+#define FT_OUT /* 表示输出参数,指针指向的值会修改,且不会读 */
+#define FT_IN /* 表示输入参数,指针指向的值不会修改 */
+#define FT_INOUT /* 表示输入输出参数,指针指向的值会修改,且会读取 */
+#define FT_IO volatile
+
+typedef char s8;
+typedef unsigned char u8;
+typedef short s16;
+typedef unsigned short u16;
+typedef int s32;
+typedef unsigned int u32;
+typedef unsigned long long u64;
+typedef long long s64;
+typedef int ft_base_t;
+typedef ft_base_t bool_t;
+
+typedef intptr_t INTPTR;
+typedef uintptr_t UINTPTR;
+typedef ptrdiff_t PTRDIFF;
+
+#define __STATIC_INLINE static inline
+#define LOCAL static
+
+#define LLSB(x) ((x)&0xff) /* 32bit word byte/word swap macros */
+#define LNLSB(x) (((x) >> 8) & 0xff)
+#define LNMSB(x) (((x) >> 16) & 0xff)
+#define LMSB(x) (((x) >> 24) & 0xff)
+#define U32SWAP(x) ((LLSB(x) << 24) | \
+ (LNLSB(x) << 16) | \
+ (LNMSB(x) << 8) | \
+ (LMSB(x)))
+
+#define FT_SWAP32(x) U32SWAP((u32)x)
+
+#endif //
diff --git a/bsp/ft2004/libraries/bsp/standlone/inbyte.c b/bsp/ft2004/libraries/bsp/standlone/inbyte.c
new file mode 100644
index 0000000000..6eff625890
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/inbyte.c
@@ -0,0 +1,21 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-04-07 15:31:34
+ * @Description:  This files is for
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_parameters.h"
+#include "ft_uart_hw.h"
+
+u8 inbyte(void)
+{
+ return FUart_RecvByte(FT_STDIN_BASEADDRESS);
+}
diff --git a/bsp/ft2004/libraries/bsp/standlone/outbyte.c b/bsp/ft2004/libraries/bsp/standlone/outbyte.c
new file mode 100644
index 0000000000..3a9a1bb21c
--- /dev/null
+++ b/bsp/ft2004/libraries/bsp/standlone/outbyte.c
@@ -0,0 +1,21 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-04-07 09:53:07
+ * @LastEditTime: 2021-04-07 17:54:32
+ * @Description:  This files is for
+ *
+ * @Modify History:
+ * Ver   Who        Date         Changes
+ * ----- ------     --------    --------------------------------------
+ */
+
+#include "ft_parameters.h"
+#include "ft_uart_hw.h"
+
+void outbyte(char byte)
+{
+ FUart_SendByte(FT_STDOUT_BASEADDRESS, byte);
+}
diff --git a/bsp/ft2004/libraries/cpu/ft_aarch32_asm.h b/bsp/ft2004/libraries/cpu/ft_aarch32_asm.h
new file mode 100644
index 0000000000..d39b221a2d
--- /dev/null
+++ b/bsp/ft2004/libraries/cpu/ft_aarch32_asm.h
@@ -0,0 +1,319 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-01-22 16:30:56
+ * @LastEditTime: 2021-05-24 14:35:53
+ * @LastEditors: Please set LastEditors
+ * @Description: In User Settings Edit
+ * @FilePath: \project_freertos\devices\ft2004\bsp\core\ft_asm.h
+ */
+
+#ifndef FT_AARCH32_ASM_H
+#define FT_AARCH32_ASM_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "ft_types.h"
+
+#define __ASM __asm
+#define __STRINGIFY(x) #x
+/* C语言实现MCR指令 */
+#define __MCR(coproc, opcode_1, src, CRn, CRm, opcode_2) \
+ __ASM volatile("MCR " __STRINGIFY(p##coproc) ", " __STRINGIFY(opcode_1) ", " \
+ "%0, " __STRINGIFY(c##CRn) ", " __STRINGIFY(c##CRm) ", " __STRINGIFY(opcode_2) \
+ : \
+ : "r"(src) \
+ : "memory");
+
+/* C语言实现MRC指令 */
+#define __MRC(coproc, opcode_1, CRn, CRm, opcode_2) \
+ ({ \
+ u32 __dst; \
+ __ASM volatile("MRC " __STRINGIFY(p##coproc) ", " __STRINGIFY(opcode_1) ", " \
+ "%0, " __STRINGIFY(c##CRn) ", " __STRINGIFY(c##CRm) ", " __STRINGIFY(opcode_2) \
+ : "=r"(__dst)::"memory"); \
+ __dst; \
+ })
+
+ __attribute__((always_inline)) __STATIC_INLINE u32 __get_VBAR(void)
+ {
+ return __MRC(15, 0, 12, 0, 0);
+ }
+
+ __attribute__((always_inline)) __STATIC_INLINE void __set_VBAR(u32 vbar)
+ {
+ __MCR(15, 0, vbar, 12, 0, 0);
+ }
+
+ __attribute__((always_inline)) __STATIC_INLINE void sys_icc_igrpen0_set(u32 value)
+ {
+ __MCR(15, 0, value, 12, 12, 6);
+ }
+
+ __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_igrpen0_get(void)
+ {
+ return __MRC(15, 0, 12, 12, 6);
+ }
+
+ __attribute__((always_inline)) __STATIC_INLINE void sys_icc_igrpen1_set(u32 value)
+ {
+ __MCR(15, 0, value, 12, 12, 7);
+ }
+
+ __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_igrpen1_get(void)
+ {
+ return __MRC(15, 0, 12, 12, 7);
+ }
+
+ __attribute__((always_inline)) __STATIC_INLINE void sys_icc_ctlr_set(u32 value)
+ {
+ __MCR(15, 0, value, 12, 12, 4);
+ }
+
+ __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_ctlr_get(void)
+ {
+ return __MRC(15, 0, 12, 12, 4);
+ }
+
+ __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_hppir0_get(void)
+ {
+ return __MRC(15, 0, 12, 8, 2);
+ }
+
+ __attribute__((always_inline)) __STATIC_INLINE void sys_icc_bpr_set(u32 value)
+ {
+ __MCR(15, 0, value, 12, 12, 3);
+ }
+
+ __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_bpr_get(void)
+ {
+ return __MRC(15, 0, 12, 12, 3);
+ }
+
+ __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_hppir1_get(void)
+ {
+ return __MRC(15, 0, 12, 12, 2);
+ }
+
+ __attribute__((always_inline)) __STATIC_INLINE void sys_icc_eoir0_set(u32 value)
+ {
+ __MCR(15, 0, value, 12, 8, 1);
+ }
+
+ __attribute__((always_inline)) __STATIC_INLINE void sys_icc_eoir1_set(u32 value)
+ {
+ __MCR(15, 0, value, 12, 12, 1);
+ }
+
+ __attribute__((always_inline)) __STATIC_INLINE void sys_icc_pmr_set(u32 value)
+ {
+ __MCR(15, 0, value, 4, 6, 0);
+ }
+
+ __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_pmr_get(void)
+ {
+ return __MRC(15, 0, 4, 6, 0);
+ }
+
+ __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_iar1_get(void)
+ {
+ return __MRC(15, 0, 12, 12, 0);
+ }
+
+ __attribute__((always_inline)) __STATIC_INLINE void sys_icc_sre_set(u32 value)
+ {
+ __MCR(15, 0, value, 12, 12, 5);
+ }
+
+ __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_sre_get(void)
+ {
+ return __MRC(15, 0, 12, 12, 5);
+ }
+
+ __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_rpr_get(void)
+ {
+ return __MRC(15, 0, 12, 11, 3);
+ }
+
+ /* Generic Timer registers */
+ /**
+ * @name: arm_aarch32_cntfrq_get
+ * @msg: This register is provided so that software can discover the frequency of the system counter.
+ * @return {__STATIC_INLINEu32}: frequency of the system counter
+ */
+ __attribute__((always_inline)) __STATIC_INLINE u32 arm_aarch32_cntfrq_get(void)
+ {
+ return __MRC(15, 0, 14, 0, 0);
+ }
+
+ /**
+ * @name: arm_aarch32_cnthv_tval_get
+ * @msg: Provides AArch32 access to the timer value for the EL2 virtual timer.
+ * @return {__STATIC_INLINEu32}: EL2 virtual timer Cnt.
+ */
+ __attribute__((always_inline)) __STATIC_INLINE u32 arm_aarch32_cnthv_tval_get(void)
+ {
+ return __MRC(15, 0, 14, 3, 0);
+ }
+
+ /**
+ * @name: arm_aarch32_cnthv_ctl_set
+ * @msg: Provides AArch32 access to the control register for the EL2 virtual timer.
+ * @in param {u32}: RegValue;ENABLE: bit [0] 0 Timer disabled,1 Timer enabled.
+ * IMASK,bit [1]: 0 Timer interrupt is not masked by the IMASK bit. 1 Timer interrupt is masked by the IMASK bit.
+ * ISTATUS, bit [2]: 0 Timer condition is not met. 1 Timer condition is met. rea-only
+ */
+ __attribute__((always_inline)) __STATIC_INLINE void arm_aarch32_cnthv_ctl_set(u32 RegValue)
+ {
+ __MCR(15, 0, RegValue, 14, 3, 1);
+ }
+
+ /**
+ * @name: arm_aarch32_cnthv_ctl_get
+ * @msg: Provides AArch32 access to the control register for the EL2 virtual timer.
+ * @return {__STATIC_INLINEu32}: RegValue;ENABLE: bit [0] 0 Timer disabled,1 Timer enabled.
+ * IMASK,bit [1]: 0 Timer interrupt is not masked by the IMASK bit. 1 Timer interrupt is masked by the IMASK bit.
+ * ISTATUS, bit [2]: 0 Timer condition is not met. 1 Timer condition is met. read-only
+ */
+ __attribute__((always_inline)) __STATIC_INLINE u32 arm_aarch32_cnthv_ctl_get(void)
+ {
+ return __MRC(15, 0, 14, 3, 1);
+ }
+
+ /**
+ * @name: arm_aarch32_cnthv_tval_set
+ * @msg: Provides AArch32 access to the timer value for the EL2 virtual timer.
+ * @in param {u32}: TimerValue, bits [31:0] The TimerValue view of the EL2 virtual timer.
+ */
+ __attribute__((always_inline)) __STATIC_INLINE void arm_aarch32_cnthv_tval_set(u32 RegValue)
+ {
+ __MCR(15, 0, RegValue, 14, 3, 0);
+ }
+
+ /**
+ * @name: arm_aarch32_cntvct_get
+ * @msg: Read the register that holds the 64-bit virtual count value. The virtual count value is equal to the physical count value visible in CNTPCT minus the virtual offset visible in CNTVOFF.
+ * @return {__STATIC_INLINEu64}Bits [63:0] Virtual count value.
+ */
+ __attribute__((always_inline)) __STATIC_INLINE u64 arm_aarch32_cntvct_get(void)
+ {
+ /* "r0" --- low,
+ "r1" --- hi
+ */
+ u32 low;
+ u32 hi;
+ __asm__ volatile(
+ ".word 0xec510f1e \n" /* mrrc p15, 1, r0, r1, c14 */
+ "mov %0, r0 \n"
+ "mov %1, r1 \n"
+ : "=&r"(low), "=&r"(hi));
+ return (((u64)hi) << 32) | low;
+ }
+
+ /* physical */
+
+ /**
+ * @name: arm_aarch32_cntp_tval_get
+ * @msg: Read the register that holds the timer value for the EL1 physical timer.
+ * @return {__STATIC_INLINEu32}: TimerValue, bits [31:0] The TimerValue view of the EL1 physical timer.
+ */
+ __attribute__((always_inline)) __STATIC_INLINE u32 arm_aarch32_cntp_tval_get(void)
+ {
+ return __MRC(15, 0, 14, 2, 0);
+ }
+
+ /**
+ * @name: arm_aarch32_cntp_tval_set
+ * @msg: write the register that control register for the EL1 physical timer.
+ * @in param {u32}: TimerValue, bits [31:0] The TimerValue view of the EL1 physical timer.
+ */
+ __attribute__((always_inline)) __STATIC_INLINE void arm_aarch32_cntp_tval_set(u32 RegValue)
+ {
+ __MCR(15, 0, RegValue, 14, 2, 0);
+ }
+
+ /**
+ * @name: arm_aarch32_cntp_ctl_set
+ * @msg: write the register that control register for the EL1 physical timer.
+ * @in param {u32}: ENABLE, bit[0] Enables the timer ; IMASK, bit [1] Timer interrupt mask bit; ISTATUS, bit [2] The status of the timer.
+ */
+ __attribute__((always_inline)) __STATIC_INLINE void arm_aarch32_cntp_ctl_set(u32 RegValue)
+ {
+ __MCR(15, 0, RegValue, 14, 2, 1);
+ }
+
+ /**
+ * @name: arm_aarch32_cntp_ctl_get
+ * @msg: Read the register that control register for the EL1 physical timer.
+ * @return {__STATIC_INLINEu32}: ENABLE, bit[0] Enables the timer ; IMASK, bit [1] Timer interrupt mask bit; ISTATUS, bit [2] The status of the timer.
+ */
+ __attribute__((always_inline)) __STATIC_INLINE u32 arm_aarch32_cntp_ctl_get(void)
+ {
+ return __MRC(15, 0, 14, 2, 1);
+ }
+
+ /**
+ * @name: arm_aarch32_cntpct_get
+ * @msg: Read the register that holds the 64-bit physical count value.
+ * @return {__STATIC_INLINEu64} CompareValue, bits [63:0] Physical count value.
+ */
+ __attribute__((always_inline)) __STATIC_INLINE u64 arm_aarch32_cntpct_get(void)
+ {
+ /* "r0" --- low,
+ "r1" --- hi
+ */
+ u32 low;
+ u32 hi;
+ __asm__ volatile(
+
+ ".word 0xec510f0e \n" /* mrrc p15, 0, r0, r1, c14 */
+ "mov %0, r0 \n"
+ "mov %1, r1 \n"
+ : "=&r"(low), "=&r"(hi));
+ return (((u64)hi) << 32) | low;
+ }
+
+#define IRQ_DISABLE() \
+ __asm volatile("CPSID i" :: \
+ : "memory"); \
+ __asm volatile("DSB"); \
+ __asm volatile("ISB");
+
+#define IRQ_ENABLE() \
+ __asm volatile("CPSIE i" :: \
+ : "memory"); \
+ __asm volatile("DSB"); \
+ __asm volatile("ISB");
+
+ /* the exception stack without VFP registers */
+ struct ft_hw_exp_stack
+ {
+ u32 r0;
+ u32 r1;
+ u32 r2;
+ u32 r3;
+ u32 r4;
+ u32 r5;
+ u32 r6;
+ u32 r7;
+ u32 r8;
+ u32 r9;
+ u32 r10;
+ u32 fp;
+ u32 ip;
+ u32 sp;
+ u32 lr;
+ u32 pc;
+ u32 cpsr;
+ };
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // !
diff --git a/bsp/ft2004/libraries/doc/ChangeLog.md b/bsp/ft2004/libraries/doc/ChangeLog.md
new file mode 100644
index 0000000000..b0d6bd9d11
--- /dev/null
+++ b/bsp/ft2004/libraries/doc/ChangeLog.md
@@ -0,0 +1,90 @@
+# FT2004-driver ChangeLog
+
+Change log since v0.1.0
+
+# FT2004-driver V0.4.2 Change Log
+
+## bsp/ft_can
+
+1. support can controller
+
+## drivers/rtthread
+
+1. adapt can drivers to rt-thread
+
+# FT2004-driver V0.4.2 Change Log
+
+## bsp/ft_spi
+
+1. support spi ctrl to read and write spi flash in rt-thread
+2. notes that spi chip select pin is ctrl in the way of gpio
+
+## bsp/ft_gpio
+
+1. support group A gpio ctrl, include w/r status, change direction
+
+## component/s25fsxx
+
+1. support s24fs serial spi flash operations
+
+## drivers/rtthread
+
+1. adapt spi drivers to rt-thread SFUD flash support component
+
+# FT2004-driver V0.4.1 Change Log
+
+## bsp/ft_i2c
+
+1. support irq read and write for i2c
+2. delete unused rtc and eeprom component
+
+# FT2004-driver V0.4.0 Change Log
+
+## component/sdmmc
+
+1. add sd2.0 comand support
+2. modify function and variable name by code convention
+
+# FT2004-driver V0.3.2 Change Log
+
+## Docs
+
+1. add ChangeLog.md
+
+## bsp/standlone
+
+1. Added ft_cache.c ft_cache.h
+
+## bsp/ft_gmac
+
+1. Added descriptor cache handling
+
+## drivers/rtthread
+
+1. Modify the bug for drv_qspi
+
+1. Added cache to drv_sdctrl
+
+# FT2004-driver V0.3.1 Change Log
+
+## Docs
+
+1. add ChangeLog.md
+
+## bsp/ft_qspi
+
+1. Complete the writing of QSPI driver
+
+2. Test bsp api in rtthread
+
+## drivers/rtthread
+
+1. add drv_qspi.c
+
+2. Access to the SUFD framework
+
+3. Test functions through the rtthread device management framework
+
+## exhibition
+
+![](./figures/v0.3.0_add.png)
diff --git a/bsp/ft2004/libraries/doc/figures/v0.3.0_add.png b/bsp/ft2004/libraries/doc/figures/v0.3.0_add.png
new file mode 100644
index 0000000000..d7e6b39849
--- /dev/null
+++ b/bsp/ft2004/libraries/doc/figures/v0.3.0_add.png
Binary files differ
diff --git a/bsp/ft2004/libraries/include/asmArm.h b/bsp/ft2004/libraries/include/asmArm.h
new file mode 100644
index 0000000000..7dd7153690
--- /dev/null
+++ b/bsp/ft2004/libraries/include/asmArm.h
@@ -0,0 +1,37 @@
+/*
+ * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0.
+ *
+ * @Date: 2021-01-20 10:07:04
+ * @LastEditTime: 2021-05-24 14:36:34
+ * @LastEditors: Please set LastEditors
+ * @Description: In User Settings Edit
+ * @FilePath: \project_freertos\devices\ft2004\gcc\asmArm.h
+ */
+#ifndef ASMARM_H
+#define ASMARM_H
+
+#define FUNC_LABEL(func) \
+ func:
+
+#if (defined __GNUC__)
+#define FUNC_BEGIN(func) \
+ .thumb; \
+ .thumb_func; \
+ .balign 4; \
+ FUNC_LABEL(func)
+#else /* !__GNUC__ */
+#define FUNC_BEGIN(func) \
+ .thumb; \
+ .balign 4; \
+ FUNC_LABEL(func)
+#endif /* __GNUC__ */
+
+#define FUNC(sym) sym
+#define FUNC_END(func) .size FUNC(func), .- FUNC(func)
+
+#define Swap64(var64) var64
+#define Swap32(var32) var32
+
+#endif // !ASMARM_H
diff --git a/bsp/ft2004/libraries/readme.md b/bsp/ft2004/libraries/readme.md
new file mode 100644
index 0000000000..c8d372b5f2
--- /dev/null
+++ b/bsp/ft2004/libraries/readme.md
@@ -0,0 +1,69 @@
+# README
+
+- FT2004 rtos 驱动介绍
+
+## 1. 当前版本
+
+- V0.4.2
+
+## 2. 关于此文档
+
+- 本文档提供此项目框架性和基本功能介绍
+
+- 详细的硬件 bsp 介绍请阅读 doc 文件中模块子文档。
+
+## 3. 编译器版本
+
+- gcc-arm-none-eabi-10-2020-q4-major
+
+## 4. 文件结构介绍
+
+| 目录名 | 内容 |
+| --------- | ---------------------------------------- |
+| bsp | 存放芯片上的外设,例如网卡,i2c 和串口等 |
+| component | 板载外设驱动 ,rtc、eeprom、sdmmc 等 |
+| cpu | cpu 架构方面指令 |
+| doc | 具体外设文档 |
+| drivers | 与不同 rtos 进行耦合的驱动 |
+| gcc | gcc 编译环境下的启动、链接文件 |
+| include | 平台相关的包含 |
+
+## 5. 支持外设
+
+| 外设名 | 备注 |
+| -------- | ---------------------- |
+| ft_gicv3 | gicv3 中断控制器 |
+| ft_gmac | ft gmac 千兆网卡控制器 |
+| ft_i2c | FT I2C |
+| ft_qspi | FT qspi 控制器 |
+| ft_sd | FT mmcsd 控制器 |
+| ft_uart | PrimeCell PL011 |
+| ft_spi | FT spi 控制器 |
+| ft_gpio | FT gpio 控制器 |
+| ft_can | FT can 控制器 |
+
+## 6. 使用实例
+
+[freertos](https://gitee.com/phytium_embedded/ft2004-freertos)
+
+## 7. 参考资源
+
+armv8 Architecture Reference Manual
+
+FT-2000/4 软件编程手册-V1.4
+
+FT-2000/4 硬件设计指导手册
+
+FT-2000 四核处理器数据手册 V1.6
+
+## 8. 贡献方法
+
+请联系飞腾嵌入式软件部
+
+
+
+## 9. 许可协议
+
+Apache License.
diff --git a/bsp/ft2004/make.sh b/bsp/ft2004/make.sh
new file mode 100644
index 0000000000..4fd5c685e0
--- /dev/null
+++ b/bsp/ft2004/make.sh
@@ -0,0 +1,16 @@
+###
+ # @Author: hh
+ # @Date: 2020-12-23 13:53:50
+ # @LastEditTime: 2021-05-18 16:48:25
+ # @LastEditors: Please set LastEditors
+ # @Description: In User Settings Edit
+ # @FilePath: \ft\bare\2_base\factory.sh
+###
+#/bin/sh
+# scons --clean
+# ./update.sh
+scons -j8
+rm /mnt/d/project/tftp/rtthread.bin
+cp ./rtthread.bin /mnt/d/project/tftp/
+
+# arm-none-eabi-objdump -D -m arm ft2004.elf > rtt.dis \ No newline at end of file
diff --git a/bsp/ft2004/rtconfig.h b/bsp/ft2004/rtconfig.h
new file mode 100644
index 0000000000..20bba6a139
--- /dev/null
+++ b/bsp/ft2004/rtconfig.h
@@ -0,0 +1,286 @@
+#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 32
+#define RT_USING_SMP
+#define RT_CPUS_NR 4
+#define RT_ALIGN_SIZE 128
+#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_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 512
+
+/* 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_MEMHEAP
+#define RT_USING_SLAB
+#define RT_USING_HEAP
+
+/* Kernel Device Object */
+
+#define RT_USING_DEVICE
+#define RT_USING_INTERRUPT_INFO
+#define RT_USING_CONSOLE
+#define RT_CONSOLEBUF_SIZE 4096
+#define RT_CONSOLE_DEVICE_NAME "uart1"
+#define RT_VER_NUM 0x40004
+#define ARCH_ARM
+#define ARCH_ARM_CORTEX_A
+#define RT_USING_GIC_V3
+
+/* RT-Thread Components */
+
+#define RT_USING_COMPONENTS_INIT
+#define RT_USING_USER_MAIN
+#define RT_MAIN_THREAD_STACK_SIZE 2048
+#define RT_MAIN_THREAD_PRIORITY 10
+
+/* C++ features */
+
+
+/* Command shell */
+
+#define RT_USING_FINSH
+#define FINSH_THREAD_NAME "tshell"
+#define FINSH_USING_HISTORY
+#define FINSH_HISTORY_LINES 5
+#define FINSH_USING_SYMTAB
+#define FINSH_USING_DESCRIPTION
+#define FINSH_THREAD_PRIORITY 20
+#define FINSH_THREAD_STACK_SIZE 4096
+#define FINSH_CMD_SIZE 128
+#define FINSH_USING_MSH
+#define FINSH_USING_MSH_DEFAULT
+#define FINSH_ARG_MAX 10
+
+/* Device virtual file system */
+
+#define RT_USING_DFS
+#define DFS_USING_WORKDIR
+#define DFS_FILESYSTEMS_MAX 2
+#define DFS_FILESYSTEM_TYPES_MAX 2
+#define DFS_FD_MAX 16
+#define RT_USING_DFS_ELMFAT
+
+/* elm-chan's FatFs, Generic FAT Filesystem Module */
+
+#define RT_DFS_ELM_CODE_PAGE 437
+#define RT_DFS_ELM_WORD_ACCESS
+#define RT_DFS_ELM_USE_LFN_3
+#define RT_DFS_ELM_USE_LFN 3
+#define RT_DFS_ELM_LFN_UNICODE_0
+#define RT_DFS_ELM_LFN_UNICODE 0
+#define RT_DFS_ELM_MAX_LFN 255
+#define RT_DFS_ELM_DRIVES 2
+#define RT_DFS_ELM_MAX_SECTOR_SIZE 512
+#define RT_DFS_ELM_REENTRANT
+#define RT_USING_DFS_DEVFS
+
+/* Device Drivers */
+
+#define RT_USING_DEVICE_IPC
+#define RT_PIPE_BUFSZ 512
+#define RT_USING_SERIAL
+#define RT_SERIAL_USING_DMA
+#define RT_SERIAL_RB_BUFSZ 256
+#define RT_USING_CAN
+#define RT_USING_SDIO
+#define RT_SDIO_STACK_SIZE 512
+#define RT_SDIO_THREAD_PRIORITY 15
+#define RT_MMCSD_STACK_SIZE 1024
+#define RT_MMCSD_THREAD_PREORITY 22
+#define RT_MMCSD_MAX_PARTITION 16
+#define RT_USING_SPI
+#define RT_USING_QSPI
+#define RT_USING_SFUD
+#define RT_SFUD_USING_SFDP
+#define RT_SFUD_USING_FLASH_INFO_TABLE
+#define RT_SFUD_USING_QSPI
+#define RT_SFUD_SPI_MAX_HZ 50000000
+
+/* Using USB */
+
+
+/* POSIX layer and C standard library */
+
+#define RT_USING_LIBC
+#define RT_USING_POSIX
+#define RT_LIBC_FIXED_TIMEZONE 8
+
+/* Network */
+
+/* Socket abstraction layer */
+
+
+/* Network interface device */
+
+#define RT_USING_NETDEV
+#define NETDEV_USING_IFCONFIG
+#define NETDEV_USING_PING
+#define NETDEV_USING_NETSTAT
+#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_LWIP212
+#define RT_LWIP_MEM_ALIGNMENT 4
+#define RT_LWIP_IGMP
+#define RT_LWIP_ICMP
+#define RT_LWIP_DNS
+
+/* Static IPv4 Address */
+
+#define RT_LWIP_IPADDR "192.168.3.20"
+#define RT_LWIP_GWADDR "192.168.3.1"
+#define RT_LWIP_MSKADDR "255.255.255.0"
+#define RT_LWIP_UDP
+#define RT_LWIP_TCP
+#define RT_LWIP_RAW
+#define RT_MEMP_NUM_NETCONN 8
+#define RT_LWIP_PBUF_NUM 16
+#define RT_LWIP_RAW_PCB_NUM 4
+#define RT_LWIP_UDP_PCB_NUM 4
+#define RT_LWIP_TCP_PCB_NUM 4
+#define RT_LWIP_TCP_SEG_NUM 40
+#define RT_LWIP_TCP_SND_BUF 8196
+#define RT_LWIP_TCP_WND 8196
+#define RT_LWIP_TCPTHREAD_PRIORITY 10
+#define RT_LWIP_TCPTHREAD_MBOX_SIZE 8
+#define RT_LWIP_TCPTHREAD_STACKSIZE 1024
+#define RT_LWIP_ETHTHREAD_PRIORITY 12
+#define RT_LWIP_ETHTHREAD_STACKSIZE 1024
+#define RT_LWIP_ETHTHREAD_MBOX_SIZE 8
+#define LWIP_NETIF_STATUS_CALLBACK 1
+#define LWIP_NETIF_LINK_CALLBACK 1
+#define SO_REUSE 1
+#define LWIP_SO_RCVTIMEO 1
+#define LWIP_SO_SNDTIMEO 1
+#define LWIP_SO_RCVBUF 1
+#define LWIP_SO_LINGER 0
+#define LWIP_NETIF_LOOPBACK 0
+#define RT_LWIP_USING_PING
+
+/* AT commands */
+
+
+/* VBUS(Virtual Software BUS) */
+
+
+/* Utilities */
+
+#define RT_USING_ULOG
+#define ULOG_OUTPUT_LVL_W
+#define ULOG_OUTPUT_LVL 4
+#define ULOG_ASSERT_ENABLE
+#define ULOG_LINE_BUF_SIZE 128
+
+/* log format */
+
+#define ULOG_USING_COLOR
+#define ULOG_OUTPUT_TIME
+#define ULOG_OUTPUT_LEVEL
+#define ULOG_OUTPUT_TAG
+#define ULOG_BACKEND_USING_CONSOLE
+
+/* 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 */
+
+
+/* tools packages */
+
+
+/* system packages */
+
+/* acceleration: Assembly language or algorithmic acceleration packages */
+
+
+/* Micrium: Micrium software products porting for RT-Thread */
+
+
+/* peripheral libraries and drivers */
+
+
+/* AI packages */
+
+
+/* miscellaneous packages */
+
+
+/* samples: kernel and components samples */
+
+
+/* entertainment: terminal games and other interesting software packages */
+
+#define FT2004
+
+/* Hardware Drivers Config */
+
+/* On-chip Peripheral Drivers */
+
+#define BSP_USING_UART
+#define RT_USING_UART1
+#define BSP_USING_SDC
+#define BSP_USING_GMAC
+#define BSP_USING_GMAC1
+#define RT_LWIP_ETH_PAD_SIZE 2
+#define BSP_USE_SPI
+#define BSP_USE_GPIO
+#define BSP_USE_CAN
+#define BSP_USING_CAN0
+
+/* Board extended module Drivers */
+
+
+#endif
diff --git a/bsp/ft2004/rtconfig.py b/bsp/ft2004/rtconfig.py
new file mode 100644
index 0000000000..ea482b8282
--- /dev/null
+++ b/bsp/ft2004/rtconfig.py
@@ -0,0 +1,59 @@
+import os
+
+
+# toolchains options
+ARCH='arm'
+CPU='cortex-a'
+CROSS_TOOL='gcc'
+
+if os.getenv('RTT_CC'):
+ CROSS_TOOL = os.getenv('RTT_CC')
+
+# only support GNU GCC compiler.
+PLATFORM = 'gcc'
+EXEC_PATH = '/usr/lib/arm-none-eabi/bin'
+if os.getenv('RTT_EXEC_PATH'):
+ EXEC_PATH = os.getenv('RTT_EXEC_PATH')
+
+BUILD = 'debug'
+
+LIBPATH = '/usr/lib/arm-none-eabi/lib'
+
+
+if PLATFORM == 'gcc':
+ # toolchains
+ PREFIX = 'arm-none-eabi-'
+ 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'
+ STRIP = PREFIX + 'strip'
+
+
+ DEVICE = ' -march=armv8-a -mfpu=vfpv4-d16 -ftree-vectorize -ffast-math -mfloat-abi=soft --specs=nano.specs --specs=nosys.specs -fno-builtin '
+ # DEVICE = ' -march=armv7-a -mfpu=vfpv3-d16 -ftree-vectorize -ffast-math -mfloat-abi=hard'
+ CFLAGS = DEVICE + ' -Wall'
+ AFLAGS = ' -c'+ DEVICE + ' -fsingle-precision-constant -fno-builtin -x assembler-with-cpp -D__ASSEMBLY__'
+ LINK_SCRIPT = 'ft_aarch32.lds'
+ LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,system_vectors'+\
+ ' -T %s' % LINK_SCRIPT
+
+ CPATH = ''
+ LPATH = LIBPATH
+
+ # generate debug info in all cases
+ AFLAGS += ' -gdwarf-2'
+ CFLAGS += ' -g -gdwarf-2'
+
+ if BUILD == 'debug':
+ CFLAGS += ' -O0'
+ else:
+ CFLAGS += ' -O2'
+
+ POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' +\
+ SIZE + ' $TARGET \n'