瀏覽代碼

[rpi4b] add new bsp for qemu-rpi4b

zhujiale 6 月之前
父節點
當前提交
c1db34983d
共有 31 個文件被更改,包括 8821 次插入0 次删除
  1. 1541 0
      bsp/raspberry-pi/raspi-dm2.0/.config
  2. 22 0
      bsp/raspberry-pi/raspi-dm2.0/Kconfig
  3. 33 0
      bsp/raspberry-pi/raspi-dm2.0/README.md
  4. 14 0
      bsp/raspberry-pi/raspi-dm2.0/SConscript
  5. 30 0
      bsp/raspberry-pi/raspi-dm2.0/SConstruct
  6. 14 0
      bsp/raspberry-pi/raspi-dm2.0/applications/SConscript
  7. 19 0
      bsp/raspberry-pi/raspi-dm2.0/applications/main.c
  8. 二進制
      bsp/raspberry-pi/raspi-dm2.0/bcm2711-rpi-4-b.dtb
  9. 13 0
      bsp/raspberry-pi/raspi-dm2.0/drivers/Kconfig
  10. 25 0
      bsp/raspberry-pi/raspi-dm2.0/drivers/SConscript
  11. 32 0
      bsp/raspberry-pi/raspi-dm2.0/drivers/board.c
  12. 35 0
      bsp/raspberry-pi/raspi-dm2.0/drivers/board.h
  13. 219 0
      bsp/raspberry-pi/raspi-dm2.0/drivers/drv_sd.c
  14. 117 0
      bsp/raspberry-pi/raspi-dm2.0/drivers/drv_sd.h
  15. 418 0
      bsp/raspberry-pi/raspi-dm2.0/drivers/drv_uart.c
  16. 108 0
      bsp/raspberry-pi/raspi-dm2.0/drivers/drv_uart.h
  17. 3 0
      bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/Kconfig
  18. 18 0
      bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/SConscript
  19. 74 0
      bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci-platform.h
  20. 815 0
      bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci.h
  21. 31 0
      bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci_dma.h
  22. 411 0
      bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci_host.h
  23. 76 0
      bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci_misc.h
  24. 125 0
      bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/sdhci-platform/sdhci-platform.c
  25. 3606 0
      bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/sdhci.c
  26. 303 0
      bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/src/fit-mmc.c
  27. 44 0
      bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/src/sdhci_dma.c
  28. 37 0
      bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/src/sdhci_voltage.c
  29. 9 0
      bsp/raspberry-pi/raspi-dm2.0/qemu.sh
  30. 575 0
      bsp/raspberry-pi/raspi-dm2.0/rtconfig.h
  31. 54 0
      bsp/raspberry-pi/raspi-dm2.0/rtconfig.py

+ 1541 - 0
bsp/raspberry-pi/raspi-dm2.0/.config

@@ -0,0 +1,1541 @@
+
+#
+# RT-Thread Kernel
+#
+CONFIG_RT_NAME_MAX=8
+# CONFIG_RT_USING_ARCH_DATA_TYPE is not set
+CONFIG_RT_USING_SMART=y
+# CONFIG_RT_USING_NANO is not set
+# CONFIG_RT_USING_AMP is not set
+CONFIG_RT_USING_SMP=y
+CONFIG_RT_CPUS_NR=4
+CONFIG_RT_ALIGN_SIZE=4
+# CONFIG_RT_THREAD_PRIORITY_8 is not set
+CONFIG_RT_THREAD_PRIORITY_32=y
+# CONFIG_RT_THREAD_PRIORITY_256 is not set
+CONFIG_RT_THREAD_PRIORITY_MAX=32
+CONFIG_RT_TICK_PER_SECOND=1000
+CONFIG_RT_USING_HOOK=y
+CONFIG_RT_HOOK_USING_FUNC_PTR=y
+# CONFIG_RT_USING_HOOKLIST is not set
+CONFIG_RT_USING_IDLE_HOOK=y
+CONFIG_RT_IDLE_HOOK_LIST_SIZE=4
+CONFIG_IDLE_THREAD_STACK_SIZE=16384
+CONFIG_SYSTEM_THREAD_STACK_SIZE=16384
+CONFIG_RT_USING_TIMER_SOFT=y
+CONFIG_RT_TIMER_THREAD_PRIO=4
+CONFIG_RT_TIMER_THREAD_STACK_SIZE=16384
+# CONFIG_RT_USING_TIMER_ALL_SOFT is not set
+CONFIG_RT_USING_CPU_USAGE_TRACER=y
+
+#
+# kservice optimization
+#
+# CONFIG_RT_USING_TINY_FFS is not set
+# end of kservice optimization
+
+#
+# klibc optimization
+#
+# CONFIG_RT_KLIBC_USING_STDLIB is not set
+# CONFIG_RT_KLIBC_USING_TINY_SIZE is not set
+CONFIG_RT_KLIBC_USING_PRINTF_LONGLONG=y
+# end of klibc optimization
+
+CONFIG_RT_USING_DEBUG=y
+# CONFIG_RT_DEBUGING_ASSERT is not set
+CONFIG_RT_DEBUGING_COLOR=y
+CONFIG_RT_DEBUGING_CONTEXT=y
+# CONFIG_RT_DEBUGING_AUTO_INIT is not set
+# CONFIG_RT_DEBUGING_PAGE_LEAK is not set
+# CONFIG_RT_DEBUGING_SPINLOCK is not set
+# CONFIG_RT_DEBUGING_CRITICAL is not set
+CONFIG_RT_USING_OVERFLOW_CHECK=y
+
+#
+# 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_MESSAGEQUEUE_PRIORITY is not set
+# CONFIG_RT_USING_SIGNALS is not set
+# end of Inter-Thread communication
+
+#
+# Memory Management
+#
+CONFIG_RT_PAGE_MAX_ORDER=11
+# CONFIG_RT_USING_MEMPOOL is not set
+# CONFIG_RT_USING_SMALL_MEM is not set
+CONFIG_RT_USING_SLAB=y
+# CONFIG_RT_USING_MEMHEAP is not set
+# CONFIG_RT_USING_SMALL_MEM_AS_HEAP is not set
+# CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set
+CONFIG_RT_USING_SLAB_AS_HEAP=y
+# CONFIG_RT_USING_USERHEAP is not set
+# CONFIG_RT_USING_NOHEAP is not set
+# CONFIG_RT_USING_MEMTRACE is not set
+# CONFIG_RT_USING_HEAP_ISR is not set
+CONFIG_RT_USING_HEAP=y
+# end of Memory Management
+
+CONFIG_RT_USING_DEVICE=y
+CONFIG_RT_USING_DEVICE_OPS=y
+CONFIG_RT_USING_INTERRUPT_INFO=y
+# CONFIG_RT_USING_THREADSAFE_PRINTF is not set
+CONFIG_RT_USING_SCHED_THREAD_CTX=y
+CONFIG_RT_USING_CONSOLE=y
+CONFIG_RT_CONSOLEBUF_SIZE=256
+CONFIG_RT_CONSOLE_DEVICE_NAME="uart0"
+CONFIG_RT_VER_NUM=0x50200
+CONFIG_RT_USING_STDC_ATOMIC=y
+CONFIG_RT_BACKTRACE_LEVEL_MAX_NR=32
+# end of RT-Thread Kernel
+
+#
+# AArch64 Architecture Configuration
+#
+CONFIG_ARCH_TEXT_OFFSET=0x200000
+CONFIG_ARCH_RAM_OFFSET=0x0
+CONFIG_ARCH_SECONDARY_CPU_STACK_SIZE=65536
+CONFIG_ARCH_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+# CONFIG_ARCH_USING_GENERIC_CPUID is not set
+CONFIG_ARCH_HEAP_SIZE=0x4000000
+CONFIG_ARCH_INIT_PAGE_SIZE=0x200000
+# end of AArch64 Architecture Configuration
+
+CONFIG_ARCH_CPU_64BIT=y
+CONFIG_RT_USING_CACHE=y
+CONFIG_RT_USING_CPU_FFS=y
+CONFIG_ARCH_MM_MMU=y
+CONFIG_ARCH_ARM=y
+CONFIG_ARCH_ARM_MMU=y
+CONFIG_KERNEL_VADDR_START=0xffff000000000000
+CONFIG_ARCH_ARMV8=y
+
+#
+# RT-Thread Components
+#
+CONFIG_RT_USING_COMPONENTS_INIT=y
+CONFIG_RT_USING_USER_MAIN=y
+CONFIG_RT_MAIN_THREAD_STACK_SIZE=8192
+CONFIG_RT_MAIN_THREAD_PRIORITY=10
+# CONFIG_RT_USING_LEGACY is not set
+CONFIG_RT_USING_MSH=y
+CONFIG_RT_USING_FINSH=y
+CONFIG_FINSH_USING_MSH=y
+CONFIG_FINSH_THREAD_NAME="tshell"
+CONFIG_FINSH_THREAD_PRIORITY=20
+CONFIG_FINSH_THREAD_STACK_SIZE=8192
+CONFIG_FINSH_USING_HISTORY=y
+CONFIG_FINSH_HISTORY_LINES=5
+CONFIG_FINSH_USING_SYMTAB=y
+CONFIG_FINSH_CMD_SIZE=80
+CONFIG_MSH_USING_BUILT_IN_COMMANDS=y
+CONFIG_FINSH_USING_DESCRIPTION=y
+# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set
+# CONFIG_FINSH_USING_AUTH is not set
+CONFIG_FINSH_ARG_MAX=10
+CONFIG_FINSH_USING_OPTION_COMPLETION=y
+
+#
+# DFS: device virtual file system
+#
+CONFIG_RT_USING_DFS=y
+CONFIG_DFS_USING_POSIX=y
+CONFIG_DFS_USING_WORKDIR=y
+CONFIG_DFS_FD_MAX=64
+CONFIG_RT_USING_DFS_V2=y
+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_DFS_ELM_MUTEX_TIMEOUT=3000
+# CONFIG_RT_DFS_ELM_USE_EXFAT is not set
+# end of elm-chan's FatFs, Generic FAT Filesystem Module
+
+CONFIG_RT_USING_DFS_DEVFS=y
+# CONFIG_RT_USING_DFS_ROMFS is not set
+CONFIG_RT_USING_DFS_PTYFS=y
+# CONFIG_RT_USING_DFS_CROMFS is not set
+CONFIG_RT_USING_DFS_TMPFS=y
+# CONFIG_RT_USING_DFS_MQUEUE is not set
+# CONFIG_RT_USING_DFS_NFS is not set
+CONFIG_RT_USING_PAGECACHE=y
+
+#
+# page cache config
+#
+CONFIG_RT_PAGECACHE_COUNT=4096
+CONFIG_RT_PAGECACHE_ASPACE_COUNT=1024
+CONFIG_RT_PAGECACHE_PRELOAD=4
+CONFIG_RT_PAGECACHE_HASH_NR=1024
+CONFIG_RT_PAGECACHE_GC_WORK_LEVEL=90
+CONFIG_RT_PAGECACHE_GC_STOP_LEVEL=70
+# end of page cache config
+# end of DFS: device virtual file system
+
+# CONFIG_RT_USING_FAL is not set
+
+#
+# Device Drivers
+#
+CONFIG_RT_USING_DM=y
+CONFIG_RT_USING_DEV_BUS=y
+CONFIG_RT_USING_DEVICE_IPC=y
+CONFIG_RT_UNAMED_PIPE_NUMBER=64
+CONFIG_RT_USING_SYSTEM_WORKQUEUE=y
+CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=16384
+CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23
+CONFIG_RT_USING_SERIAL=y
+CONFIG_RT_USING_SERIAL_V1=y
+# CONFIG_RT_USING_SERIAL_V2 is not set
+CONFIG_RT_SERIAL_USING_DMA=y
+CONFIG_RT_SERIAL_RB_BUFSZ=64
+# CONFIG_RT_USING_CAN is not set
+# CONFIG_RT_USING_CPUTIME is not set
+CONFIG_RT_USING_I2C=y
+# CONFIG_RT_I2C_DEBUG is not set
+CONFIG_RT_USING_I2C_BITOPS=y
+# CONFIG_RT_I2C_BITOPS_DEBUG is not set
+# CONFIG_RT_USING_SOFT_I2C is not set
+# CONFIG_RT_USING_PHY is not set
+# CONFIG_RT_USING_ADC is not set
+# CONFIG_RT_USING_DAC is not set
+CONFIG_RT_USING_NULL=y
+CONFIG_RT_USING_ZERO=y
+CONFIG_RT_USING_RANDOM=y
+# CONFIG_RT_USING_PWM is not set
+# CONFIG_RT_USING_PULSE_ENCODER is not set
+# CONFIG_RT_USING_INPUT_CAPTURE 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=y
+# CONFIG_RT_USING_ALARM is not set
+CONFIG_RT_USING_SOFT_RTC=y
+CONFIG_RT_USING_SDIO=y
+CONFIG_RT_SDIO_STACK_SIZE=16384
+CONFIG_RT_SDIO_THREAD_PRIORITY=15
+CONFIG_RT_MMCSD_STACK_SIZE=8192
+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_SPI_BITOPS is not set
+# CONFIG_RT_USING_QSPI is not set
+# CONFIG_RT_USING_SPI_MSD is not set
+# CONFIG_RT_USING_SFUD is not set
+# CONFIG_RT_USING_ENC28J60 is not set
+# CONFIG_RT_USING_SPI_WIFI is not set
+CONFIG_RT_USING_WDT=y
+# CONFIG_RT_USING_AUDIO is not set
+# CONFIG_RT_USING_SENSOR is not set
+CONFIG_RT_USING_TOUCH=y
+# CONFIG_RT_TOUCH_PIN_IRQ is not set
+CONFIG_RT_USING_LCD=y
+# CONFIG_RT_USING_HWCRYPTO is not set
+# CONFIG_RT_USING_WIFI is not set
+# CONFIG_RT_USING_VIRTIO is not set
+CONFIG_RT_USING_OFW=y
+# CONFIG_RT_USING_BUILTIN_FDT is not set
+CONFIG_RT_FDT_EARLYCON_MSG_SIZE=128
+CONFIG_RT_USING_OFW_BUS_RANGES_NUMBER=8
+# CONFIG_RT_USING_PCI is not set
+CONFIG_RT_USING_PIC=y
+# CONFIG_RT_USING_PIC_STATISTICS is not set
+CONFIG_MAX_HANDLERS=256
+CONFIG_RT_PIC_ARM_GIC=y
+# CONFIG_RT_PIC_ARM_GIC_V3 is not set
+CONFIG_RT_PIC_ARM_GIC_MAX_NR=1
+CONFIG_RT_USING_PIN=y
+# CONFIG_RT_USING_PINCTRL is not set
+CONFIG_RT_USING_KTIME=y
+CONFIG_RT_USING_CLK=y
+CONFIG_RT_USING_HWTIMER=y
+CONFIG_RT_HWTIMER_ARM_ARCH=y
+# CONFIG_RT_USING_CHERRYUSB is not set
+# end of Device Drivers
+
+#
+# C/C++ and POSIX layer
+#
+
+#
+# ISO-ANSI C layer
+#
+
+#
+# Timezone and Daylight Saving Time
+#
+# CONFIG_RT_LIBC_USING_FULL_TZ_DST is not set
+CONFIG_RT_LIBC_USING_LIGHT_TZ_DST=y
+CONFIG_RT_LIBC_TZ_DEFAULT_HOUR=8
+CONFIG_RT_LIBC_TZ_DEFAULT_MIN=0
+CONFIG_RT_LIBC_TZ_DEFAULT_SEC=0
+# end of Timezone and Daylight Saving Time
+# end of ISO-ANSI C layer
+
+#
+# POSIX (Portable Operating System Interface) layer
+#
+CONFIG_RT_USING_POSIX_FS=y
+CONFIG_RT_USING_POSIX_DEVIO=y
+CONFIG_RT_USING_POSIX_STDIO=y
+CONFIG_RT_USING_POSIX_POLL=y
+# CONFIG_RT_USING_POSIX_SELECT is not set
+# CONFIG_RT_USING_POSIX_EVENTFD is not set
+CONFIG_RT_USING_POSIX_EPOLL=y
+CONFIG_RT_USING_POSIX_SIGNALFD=y
+CONFIG_RT_SIGNALFD_MAX_NUM=10
+# CONFIG_RT_USING_POSIX_TIMERFD is not set
+# CONFIG_RT_USING_POSIX_SOCKET is not set
+CONFIG_RT_USING_POSIX_TERMIOS=y
+# CONFIG_RT_USING_POSIX_AIO is not set
+# CONFIG_RT_USING_POSIX_MMAN is not set
+CONFIG_RT_USING_POSIX_DELAY=y
+CONFIG_RT_USING_POSIX_CLOCK=y
+CONFIG_RT_USING_POSIX_TIMER=y
+# CONFIG_RT_USING_PTHREADS is not set
+# CONFIG_RT_USING_MODULE is not set
+
+#
+# Interprocess Communication (IPC)
+#
+# CONFIG_RT_USING_POSIX_PIPE is not set
+# CONFIG_RT_USING_POSIX_MESSAGE_QUEUE is not set
+# CONFIG_RT_USING_POSIX_MESSAGE_SEMAPHORE is not set
+
+#
+# Socket is in the 'Network' category
+#
+# end of Interprocess Communication (IPC)
+# end of POSIX (Portable Operating System Interface) layer
+
+# CONFIG_RT_USING_CPLUSPLUS is not set
+# end of C/C++ and POSIX layer
+
+#
+# Network
+#
+CONFIG_RT_USING_SAL=y
+CONFIG_SAL_INTERNET_CHECK=y
+
+#
+# Docking with protocol stacks
+#
+CONFIG_SAL_USING_LWIP=y
+# CONFIG_SAL_USING_AT is not set
+# CONFIG_SAL_USING_TLS is not set
+# end of Docking with protocol stacks
+
+CONFIG_SAL_USING_POSIX=y
+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_LINK_STATUS_CALLBACK is not set
+# CONFIG_NETDEV_USING_IPV6 is not set
+CONFIG_NETDEV_IPV4=1
+CONFIG_NETDEV_IPV6=0
+CONFIG_RT_USING_LWIP=y
+# CONFIG_RT_USING_LWIP_LOCAL_VERSION is not set
+# CONFIG_RT_USING_LWIP141 is not set
+# CONFIG_RT_USING_LWIP203 is not set
+CONFIG_RT_USING_LWIP212=y
+# CONFIG_RT_USING_LWIP_LATEST is not set
+CONFIG_RT_USING_LWIP_VER_NUM=0x20102
+# 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=y
+CONFIG_IP_SOF_BROADCAST=1
+CONFIG_IP_SOF_BROADCAST_RECV=1
+
+#
+# Static IPv4 Address
+#
+CONFIG_RT_LWIP_IPADDR="192.168.137.100"
+CONFIG_RT_LWIP_GWADDR="192.168.137.1"
+CONFIG_RT_LWIP_MSKADDR="255.255.255.0"
+# end of Static IPv4 Address
+
+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=16
+CONFIG_RT_LWIP_PBUF_NUM=16
+CONFIG_RT_LWIP_RAW_PCB_NUM=4
+CONFIG_RT_LWIP_UDP_PCB_NUM=8
+CONFIG_RT_LWIP_TCP_PCB_NUM=8
+CONFIG_RT_LWIP_TCP_SEG_NUM=40
+CONFIG_RT_LWIP_TCP_SND_BUF=8192
+CONFIG_RT_LWIP_TCP_WND=8192
+CONFIG_RT_LWIP_TCPTHREAD_PRIORITY=10
+CONFIG_RT_LWIP_TCPTHREAD_MBOX_SIZE=8
+CONFIG_RT_LWIP_TCPTHREAD_STACKSIZE=32768
+# CONFIG_LWIP_NO_RX_THREAD is not set
+CONFIG_LWIP_NO_TX_THREAD=y
+CONFIG_RT_LWIP_ETHTHREAD_PRIORITY=12
+CONFIG_RT_LWIP_ETHTHREAD_STACKSIZE=32768
+CONFIG_RT_LWIP_ETHTHREAD_MBOX_SIZE=8
+CONFIG_RT_LWIP_REASSEMBLY_FRAG=y
+CONFIG_LWIP_NETIF_STATUS_CALLBACK=1
+CONFIG_LWIP_NETIF_LINK_CALLBACK=1
+CONFIG_RT_LWIP_NETIF_NAMESIZE=6
+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=y
+CONFIG_LWIP_NETIF_LOOPBACK=1
+# CONFIG_RT_LWIP_STATS is not set
+# CONFIG_RT_LWIP_USING_HW_CHECKSUM is not set
+CONFIG_RT_LWIP_USING_PING=y
+# CONFIG_LWIP_USING_DHCPD is not set
+# CONFIG_RT_LWIP_DEBUG is not set
+# CONFIG_RT_USING_AT is not set
+# end of Network
+
+#
+# Memory protection
+#
+# CONFIG_RT_USING_MEM_PROTECTION is not set
+# CONFIG_RT_USING_HW_STACK_GUARD is not set
+# end of Memory protection
+
+#
+# Utilities
+#
+# CONFIG_RT_USING_RYM is not set
+# CONFIG_RT_USING_ULOG is not set
+CONFIG_RT_USING_UTEST=y
+CONFIG_UTEST_THR_STACK_SIZE=8192
+CONFIG_UTEST_THR_PRIORITY=20
+# CONFIG_RT_USING_VAR_EXPORT is not set
+CONFIG_RT_USING_RESOURCE_ID=y
+CONFIG_RT_USING_ADT=y
+CONFIG_RT_USING_ADT_AVL=y
+CONFIG_RT_USING_ADT_BITMAP=y
+CONFIG_RT_USING_ADT_HASHMAP=y
+CONFIG_RT_USING_ADT_REF=y
+# CONFIG_RT_USING_RT_LINK is not set
+# end of Utilities
+
+# CONFIG_RT_USING_VBUS is not set
+CONFIG_RT_USING_LWP=y
+CONFIG_LWP_DEBUG=y
+# CONFIG_LWP_DEBUG_INIT is not set
+CONFIG_RT_LWP_MAX_NR=30
+CONFIG_LWP_TASK_STACK_SIZE=16384
+CONFIG_RT_CH_MSG_MAX_NR=1024
+CONFIG_LWP_TID_MAX_NR=64
+CONFIG_RT_LWP_SHM_MAX_NR=64
+CONFIG_RT_USING_LDSO=y
+# CONFIG_ELF_DEBUG_ENABLE is not set
+# CONFIG_ELF_LOAD_RANDOMIZE is not set
+CONFIG_LWP_USING_TERMINAL=y
+CONFIG_LWP_PTY_MAX_PARIS_LIMIT=64
+CONFIG_RT_USING_VDSO=y
+
+#
+# Memory management
+#
+CONFIG_RT_USING_MEMBLOCK=y
+CONFIG_RT_INIT_MEMORY_REGIONS=128
+# end of Memory management
+
+#
+# Using USB legacy version
+#
+# CONFIG_RT_USING_USB_HOST is not set
+# CONFIG_RT_USING_USB_DEVICE is not set
+# end of Using USB legacy version
+
+# CONFIG_RT_USING_FDT is not set
+# end of RT-Thread Components
+
+#
+# RT-Thread Utestcases
+#
+CONFIG_RT_USING_UTESTCASES=y
+
+#
+# Utest Self Testcase
+#
+# CONFIG_UTEST_SELF_PASS_TC is not set
+# end of Utest Self Testcase
+
+#
+# Kernel Testcase
+#
+# CONFIG_UTEST_SLAB_TC is not set
+# CONFIG_UTEST_IRQ_TC is not set
+# CONFIG_UTEST_SEMAPHORE_TC is not set
+# CONFIG_UTEST_EVENT_TC is not set
+# CONFIG_UTEST_TIMER_TC is not set
+# CONFIG_UTEST_MESSAGEQUEUE_TC is not set
+# CONFIG_UTEST_SIGNAL_TC is not set
+# CONFIG_UTEST_MUTEX_TC is not set
+# CONFIG_UTEST_MAILBOX_TC is not set
+# CONFIG_UTEST_THREAD_TC is not set
+# CONFIG_UTEST_DEVICE_TC is not set
+# CONFIG_UTEST_ATOMIC_TC is not set
+# CONFIG_UTEST_HOOKLIST_TC is not set
+# CONFIG_UTEST_MTSAFE_KPRINT_TC is not set
+CONFIG_UTEST_SCHEDULER_TC=y
+
+#
+# Kernel SMP Testcase
+#
+# CONFIG_UTEST_SMP_AFFFINITY_TC is not set
+# CONFIG_UTEST_SMP_ASSIGNED_IDLE_CORE_TC is not set
+# CONFIG_UTEST_SMP_INTERRUPT_PRI_TC is not set
+# CONFIG_UTEST_SMP_SPINLOCK_TC is not set
+# CONFIG_UTEST_SMP_THREAD_PREEMPTION_TC is not set
+# end of Kernel SMP Testcase
+# end of Kernel Testcase
+
+#
+# CPP11 Testcase
+#
+# CONFIG_UTEST_CPP11_THREAD_TC is not set
+# end of CPP11 Testcase
+
+#
+# Utest Serial Testcase
+#
+# CONFIG_UTEST_SERIAL_TC is not set
+# end of Utest Serial Testcase
+
+#
+# Utest IPC Testcase
+#
+# CONFIG_UTEST_COMPLETION_TC is not set
+# end of Utest IPC Testcase
+
+#
+# RTT Posix Testcase
+#
+# CONFIG_RTT_POSIX_TESTCASE is not set
+# end of RTT Posix Testcase
+
+#
+# Memory Management Subsytem Testcase
+#
+# CONFIG_UTEST_MM_API_TC is not set
+# CONFIG_UTEST_MM_LWP_TC is not set
+# end of Memory Management Subsytem Testcase
+
+#
+# Tmpfs Testcase
+#
+# CONFIG_UTEST_TMPFS_CP is not set
+# end of Tmpfs Testcase
+
+#
+# SMP Testcase
+#
+# CONFIG_UTEST_SMP_CALL_FUNC is not set
+# end of SMP Testcase
+# end of RT-Thread Utestcases
+
+#
+# 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_FREEMODBUS is not set
+# CONFIG_PKG_USING_NANOPB is not set
+
+#
+# Wi-Fi
+#
+
+#
+# Marvell WiFi
+#
+# CONFIG_PKG_USING_WLANMARVELL is not set
+# end of Marvell WiFi
+
+#
+# Wiced WiFi
+#
+# CONFIG_PKG_USING_WLAN_WICED is not set
+# end of Wiced WiFi
+
+# CONFIG_PKG_USING_RW007 is not set
+
+#
+# CYW43012 WiFi
+#
+# CONFIG_PKG_USING_WLAN_CYW43012 is not set
+# end of CYW43012 WiFi
+
+#
+# BL808 WiFi
+#
+# CONFIG_PKG_USING_WLAN_BL808 is not set
+# end of BL808 WiFi
+
+#
+# CYW43439 WiFi
+#
+# CONFIG_PKG_USING_WLAN_CYW43439 is not set
+# end of CYW43439 WiFi
+# end of Wi-Fi
+
+# CONFIG_PKG_USING_COAP is not set
+# CONFIG_PKG_USING_NOPOLL is not set
+# CONFIG_PKG_USING_NETUTILS is not set
+# CONFIG_PKG_USING_CMUX is not set
+# CONFIG_PKG_USING_PPP_DEVICE is not set
+# CONFIG_PKG_USING_AT_DEVICE is not set
+# CONFIG_PKG_USING_ATSRV_SOCKET is not set
+# CONFIG_PKG_USING_WIZNET is not set
+# CONFIG_PKG_USING_ZB_COORDINATOR is not set
+
+#
+# IoT Cloud
+#
+# CONFIG_PKG_USING_ONENET is not set
+# CONFIG_PKG_USING_GAGENT_CLOUD is not set
+# CONFIG_PKG_USING_ALI_IOTKIT is not set
+# CONFIG_PKG_USING_AZURE is not set
+# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set
+# CONFIG_PKG_USING_JIOT-C-SDK is not set
+# CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set
+# CONFIG_PKG_USING_JOYLINK is not set
+# CONFIG_PKG_USING_IOTSHARP_SDK is not set
+# end of IoT Cloud
+
+# CONFIG_PKG_USING_NIMBLE is not set
+# CONFIG_PKG_USING_LLSYNC_SDK_ADAPTER is not set
+# CONFIG_PKG_USING_OTA_DOWNLOADER is not set
+# CONFIG_PKG_USING_IPMSG is not set
+# CONFIG_PKG_USING_LSSDP is not set
+# CONFIG_PKG_USING_AIRKISS_OPEN is not set
+# CONFIG_PKG_USING_LIBRWS is not set
+# CONFIG_PKG_USING_TCPSERVER is not set
+# CONFIG_PKG_USING_PROTOBUF_C is not set
+# CONFIG_PKG_USING_DLT645 is not set
+# CONFIG_PKG_USING_QXWZ is not set
+# CONFIG_PKG_USING_SMTP_CLIENT is not set
+# CONFIG_PKG_USING_ABUP_FOTA is not set
+# CONFIG_PKG_USING_LIBCURL2RTT is not set
+# CONFIG_PKG_USING_CAPNP is not set
+# CONFIG_PKG_USING_AGILE_TELNET is not set
+# CONFIG_PKG_USING_NMEALIB is not set
+# CONFIG_PKG_USING_PDULIB is not set
+# CONFIG_PKG_USING_BTSTACK is not set
+# CONFIG_PKG_USING_BT_CYW43012 is not set
+# CONFIG_PKG_USING_CYW43XX 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_BSAL is not set
+# CONFIG_PKG_USING_AGILE_MODBUS is not set
+# CONFIG_PKG_USING_AGILE_FTP is not set
+# CONFIG_PKG_USING_EMBEDDEDPROTO is not set
+# CONFIG_PKG_USING_RT_LINK_HW is not set
+# CONFIG_PKG_USING_RYANMQTT is not set
+# CONFIG_PKG_USING_RYANW5500 is not set
+# CONFIG_PKG_USING_LORA_PKT_FWD is not set
+# CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set
+# CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set
+# CONFIG_PKG_USING_HM is not set
+# CONFIG_PKG_USING_SMALL_MODBUS is not set
+# CONFIG_PKG_USING_NET_SERVER is not set
+# CONFIG_PKG_USING_ZFTP is not set
+# CONFIG_PKG_USING_WOL is not set
+# CONFIG_PKG_USING_ZEPHYR_POLLING is not set
+# CONFIG_PKG_USING_MATTER_ADAPTATION_LAYER is not set
+# CONFIG_PKG_USING_LHC_MODBUS is not set
+# CONFIG_PKG_USING_QMODBUS is not set
+# end of IoT - internet of things
+
+#
+# security packages
+#
+# CONFIG_PKG_USING_MBEDTLS is not set
+# CONFIG_PKG_USING_LIBSODIUM is not set
+# CONFIG_PKG_USING_LIBHYDROGEN 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
+# end of security packages
+
+#
+# language packages
+#
+
+#
+# JSON: JavaScript Object Notation, a lightweight data-interchange format
+#
+# CONFIG_PKG_USING_CJSON is not set
+# CONFIG_PKG_USING_LJSON is not set
+# CONFIG_PKG_USING_RT_CJSON_TOOLS is not set
+# CONFIG_PKG_USING_RAPIDJSON is not set
+# CONFIG_PKG_USING_JSMN is not set
+# CONFIG_PKG_USING_AGILE_JSMN is not set
+# CONFIG_PKG_USING_PARSON is not set
+# end of JSON: JavaScript Object Notation, a lightweight data-interchange format
+
+#
+# XML: Extensible Markup Language
+#
+# CONFIG_PKG_USING_SIMPLE_XML is not set
+# CONFIG_PKG_USING_EZXML is not set
+# end of XML: Extensible Markup Language
+
+# CONFIG_PKG_USING_LUATOS_SOC is not set
+# CONFIG_PKG_USING_LUA is not set
+# CONFIG_PKG_USING_JERRYSCRIPT is not set
+# CONFIG_PKG_USING_MICROPYTHON is not set
+# CONFIG_PKG_USING_PIKASCRIPT is not set
+# CONFIG_PKG_USING_RTT_RUST is not set
+# end of language packages
+
+#
+# multimedia packages
+#
+
+#
+# LVGL: powerful and easy-to-use embedded GUI library
+#
+# CONFIG_PKG_USING_LVGL is not set
+# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set
+# CONFIG_PKG_USING_GUI_GUIDER_DEMO is not set
+# end of LVGL: powerful and easy-to-use embedded GUI library
+
+#
+# u8g2: a monochrome graphic library
+#
+# CONFIG_PKG_USING_U8G2_OFFICIAL is not set
+# CONFIG_PKG_USING_U8G2 is not set
+# end of u8g2: a monochrome graphic library
+
+# CONFIG_PKG_USING_OPENMV is not set
+# CONFIG_PKG_USING_MUPDF is not set
+# CONFIG_PKG_USING_STEMWIN is not set
+# CONFIG_PKG_USING_WAVPLAYER is not set
+# CONFIG_PKG_USING_TJPGD is not set
+# CONFIG_PKG_USING_PDFGEN is not set
+# CONFIG_PKG_USING_HELIX is not set
+# CONFIG_PKG_USING_AZUREGUIX is not set
+# CONFIG_PKG_USING_TOUCHGFX2RTT is not set
+# CONFIG_PKG_USING_NUEMWIN is not set
+# CONFIG_PKG_USING_MP3PLAYER is not set
+# CONFIG_PKG_USING_TINYJPEG is not set
+# CONFIG_PKG_USING_UGUI is not set
+# CONFIG_PKG_USING_MCURSES is not set
+# CONFIG_PKG_USING_TERMBOX is not set
+# CONFIG_PKG_USING_VT100 is not set
+# CONFIG_PKG_USING_QRCODE is not set
+# CONFIG_PKG_USING_GUIENGINE is not set
+# CONFIG_PKG_USING_3GPP_AMRNB is not set
+# end of multimedia packages
+
+#
+# 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_RTT_AUTO_EXE_CMD is not set
+# CONFIG_PKG_USING_RDB is not set
+# CONFIG_PKG_USING_ULOG_EASYFLASH is not set
+# CONFIG_PKG_USING_LOGMGR is not set
+# CONFIG_PKG_USING_ADBD is not set
+# CONFIG_PKG_USING_COREMARK is not set
+# CONFIG_PKG_USING_DHRYSTONE is not set
+# CONFIG_PKG_USING_MEMORYPERF is not set
+# CONFIG_PKG_USING_NR_MICRO_SHELL is not set
+# CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set
+# CONFIG_PKG_USING_LUNAR_CALENDAR is not set
+# CONFIG_PKG_USING_BS8116A is not set
+# CONFIG_PKG_USING_GPS_RMC is not set
+# CONFIG_PKG_USING_URLENCODE is not set
+# CONFIG_PKG_USING_UMCN is not set
+# CONFIG_PKG_USING_LWRB2RTT is not set
+# CONFIG_PKG_USING_CPU_USAGE is not set
+# CONFIG_PKG_USING_GBK2UTF8 is not set
+# CONFIG_PKG_USING_VCONSOLE is not set
+# CONFIG_PKG_USING_KDB is not set
+# CONFIG_PKG_USING_WAMR is not set
+# CONFIG_PKG_USING_MICRO_XRCE_DDS_CLIENT is not set
+# CONFIG_PKG_USING_LWLOG is not set
+# CONFIG_PKG_USING_ANV_TRACE is not set
+# CONFIG_PKG_USING_ANV_MEMLEAK is not set
+# CONFIG_PKG_USING_ANV_TESTSUIT is not set
+# CONFIG_PKG_USING_ANV_BENCH is not set
+# CONFIG_PKG_USING_DEVMEM is not set
+# CONFIG_PKG_USING_REGEX is not set
+# CONFIG_PKG_USING_MEM_SANDBOX is not set
+# CONFIG_PKG_USING_SOLAR_TERMS is not set
+# CONFIG_PKG_USING_GAN_ZHI is not set
+# CONFIG_PKG_USING_FDT is not set
+# CONFIG_PKG_USING_CBOX is not set
+# CONFIG_PKG_USING_SNOWFLAKE is not set
+# CONFIG_PKG_USING_HASH_MATCH is not set
+# CONFIG_PKG_USING_ARMV7M_DWT_TOOL is not set
+# CONFIG_PKG_USING_VOFA_PLUS is not set
+# CONFIG_PKG_USING_ZDEBUG is not set
+# end of tools packages
+
+#
+# system packages
+#
+
+#
+# enhanced kernel services
+#
+# CONFIG_PKG_USING_RT_MEMCPY_CM is not set
+# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set
+# CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set
+# end of enhanced kernel services
+
+#
+# acceleration: Assembly language or algorithmic acceleration packages
+#
+# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set
+# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set
+# CONFIG_PKG_USING_QFPLIB_M3 is not set
+# end of acceleration: Assembly language or algorithmic acceleration packages
+
+#
+# CMSIS: ARM Cortex-M Microcontroller Software Interface Standard
+#
+# CONFIG_PKG_USING_CMSIS_5 is not set
+# CONFIG_PKG_USING_CMSIS_CORE is not set
+# CONFIG_PKG_USING_CMSIS_DSP is not set
+# CONFIG_PKG_USING_CMSIS_NN is not set
+# CONFIG_PKG_USING_CMSIS_RTOS1 is not set
+# CONFIG_PKG_USING_CMSIS_RTOS2 is not set
+# end of CMSIS: ARM Cortex-M Microcontroller Software Interface Standard
+
+#
+# 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
+# end of Micrium: Micrium software products porting for RT-Thread
+
+# CONFIG_PKG_USING_FREERTOS_WRAPPER is not set
+# CONFIG_PKG_USING_LITEOS_SDK is not set
+# CONFIG_PKG_USING_TZ_DATABASE 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_PERF_COUNTER is not set
+# CONFIG_PKG_USING_FILEX is not set
+# CONFIG_PKG_USING_LEVELX is not set
+# CONFIG_PKG_USING_FLASHDB is not set
+# CONFIG_PKG_USING_SQLITE is not set
+# CONFIG_PKG_USING_RTI is not set
+# CONFIG_PKG_USING_DFS_YAFFS is not set
+# CONFIG_PKG_USING_LITTLEFS is not set
+# CONFIG_PKG_USING_DFS_JFFS2 is not set
+# CONFIG_PKG_USING_DFS_UFFS is not set
+# CONFIG_PKG_USING_LWEXT4 is not set
+# CONFIG_PKG_USING_THREAD_POOL is not set
+# CONFIG_PKG_USING_ROBOTS is not set
+# CONFIG_PKG_USING_EV is not set
+# CONFIG_PKG_USING_SYSWATCH is not set
+# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set
+# CONFIG_PKG_USING_PLCCORE is not set
+# CONFIG_PKG_USING_RAMDISK is not set
+# CONFIG_PKG_USING_MININI is not set
+# CONFIG_PKG_USING_QBOOT is not set
+# CONFIG_PKG_USING_PPOOL is not set
+# CONFIG_PKG_USING_OPENAMP is not set
+# CONFIG_PKG_USING_RPMSG_LITE is not set
+# CONFIG_PKG_USING_LPM is not set
+# CONFIG_PKG_USING_TLSF is not set
+# CONFIG_PKG_USING_EVENT_RECORDER is not set
+# CONFIG_PKG_USING_ARM_2D is not set
+# CONFIG_PKG_USING_MCUBOOT is not set
+# CONFIG_PKG_USING_TINYUSB is not set
+# CONFIG_PKG_USING_CHERRYUSB is not set
+# CONFIG_PKG_USING_KMULTI_RTIMER is not set
+# CONFIG_PKG_USING_TFDB is not set
+# CONFIG_PKG_USING_QPC is not set
+# CONFIG_PKG_USING_AGILE_UPGRADE is not set
+# CONFIG_PKG_USING_FLASH_BLOB is not set
+# CONFIG_PKG_USING_MLIBC is not set
+# CONFIG_PKG_USING_TASK_MSG_BUS is not set
+# CONFIG_PKG_USING_SFDB is not set
+# CONFIG_PKG_USING_RTP is not set
+# CONFIG_PKG_USING_REB is not set
+# CONFIG_PKG_USING_R_RHEALSTONE is not set
+# end of system packages
+
+#
+# peripheral libraries and drivers
+#
+
+#
+# HAL & SDK Drivers
+#
+
+#
+# STM32 HAL & SDK Drivers
+#
+# CONFIG_PKG_USING_STM32L4_HAL_DRIVER is not set
+# CONFIG_PKG_USING_STM32L4_CMSIS_DRIVER is not set
+# CONFIG_PKG_USING_STM32WB55_SDK is not set
+# CONFIG_PKG_USING_STM32_SDIO is not set
+# end of STM32 HAL & SDK Drivers
+
+# CONFIG_PKG_USING_BLUETRUM_SDK is not set
+# CONFIG_PKG_USING_EMBARC_BSP is not set
+# CONFIG_PKG_USING_ESP_IDF is not set
+
+#
+# Kendryte SDK
+#
+# CONFIG_PKG_USING_K210_SDK is not set
+# CONFIG_PKG_USING_KENDRYTE_SDK is not set
+# end of Kendryte SDK
+
+# CONFIG_PKG_USING_NRF5X_SDK is not set
+# CONFIG_PKG_USING_NRFX is not set
+# CONFIG_PKG_USING_RASPBERRYPI_PICO_SDK is not set
+# end of HAL & SDK Drivers
+
+#
+# sensors drivers
+#
+# CONFIG_PKG_USING_LSM6DSM is not set
+# CONFIG_PKG_USING_LSM6DSL is not set
+# CONFIG_PKG_USING_LPS22HB is not set
+# CONFIG_PKG_USING_HTS221 is not set
+# CONFIG_PKG_USING_LSM303AGR is not set
+# CONFIG_PKG_USING_BME280 is not set
+# CONFIG_PKG_USING_BME680 is not set
+# CONFIG_PKG_USING_BMA400 is not set
+# CONFIG_PKG_USING_BMI160_BMX160 is not set
+# CONFIG_PKG_USING_SPL0601 is not set
+# CONFIG_PKG_USING_MS5805 is not set
+# CONFIG_PKG_USING_DA270 is not set
+# CONFIG_PKG_USING_DF220 is not set
+# CONFIG_PKG_USING_HSHCAL001 is not set
+# CONFIG_PKG_USING_BH1750 is not set
+# CONFIG_PKG_USING_MPU6XXX is not set
+# CONFIG_PKG_USING_AHT10 is not set
+# CONFIG_PKG_USING_AP3216C is not set
+# CONFIG_PKG_USING_TSL4531 is not set
+# CONFIG_PKG_USING_DS18B20 is not set
+# CONFIG_PKG_USING_DHT11 is not set
+# CONFIG_PKG_USING_DHTXX is not set
+# CONFIG_PKG_USING_GY271 is not set
+# CONFIG_PKG_USING_GP2Y10 is not set
+# CONFIG_PKG_USING_SGP30 is not set
+# CONFIG_PKG_USING_HDC1000 is not set
+# CONFIG_PKG_USING_BMP180 is not set
+# CONFIG_PKG_USING_BMP280 is not set
+# CONFIG_PKG_USING_SHTC1 is not set
+# CONFIG_PKG_USING_BMI088 is not set
+# CONFIG_PKG_USING_HMC5883 is not set
+# CONFIG_PKG_USING_MAX6675 is not set
+# CONFIG_PKG_USING_TMP1075 is not set
+# CONFIG_PKG_USING_SR04 is not set
+# CONFIG_PKG_USING_CCS811 is not set
+# CONFIG_PKG_USING_PMSXX is not set
+# CONFIG_PKG_USING_RT3020 is not set
+# CONFIG_PKG_USING_MLX90632 is not set
+# CONFIG_PKG_USING_MLX90393 is not set
+# CONFIG_PKG_USING_MLX90392 is not set
+# CONFIG_PKG_USING_MLX90397 is not set
+# CONFIG_PKG_USING_MS5611 is not set
+# CONFIG_PKG_USING_MAX31865 is not set
+# CONFIG_PKG_USING_VL53L0X is not set
+# CONFIG_PKG_USING_INA260 is not set
+# CONFIG_PKG_USING_MAX30102 is not set
+# CONFIG_PKG_USING_INA226 is not set
+# CONFIG_PKG_USING_LIS2DH12 is not set
+# CONFIG_PKG_USING_HS300X is not set
+# CONFIG_PKG_USING_ZMOD4410 is not set
+# CONFIG_PKG_USING_ISL29035 is not set
+# CONFIG_PKG_USING_MMC3680KJ is not set
+# CONFIG_PKG_USING_QMP6989 is not set
+# CONFIG_PKG_USING_BALANCE is not set
+# CONFIG_PKG_USING_SHT2X is not set
+# CONFIG_PKG_USING_SHT3X is not set
+# CONFIG_PKG_USING_SHT4X is not set
+# CONFIG_PKG_USING_AD7746 is not set
+# CONFIG_PKG_USING_ADT74XX is not set
+# CONFIG_PKG_USING_MAX17048 is not set
+# CONFIG_PKG_USING_AS7341 is not set
+# CONFIG_PKG_USING_CW2015 is not set
+# CONFIG_PKG_USING_ICM20608 is not set
+# CONFIG_PKG_USING_PAJ7620 is not set
+# CONFIG_PKG_USING_STHS34PF80 is not set
+# end of sensors drivers
+
+#
+# touch drivers
+#
+# CONFIG_PKG_USING_GT9147 is not set
+# CONFIG_PKG_USING_GT1151 is not set
+# CONFIG_PKG_USING_GT917S is not set
+# CONFIG_PKG_USING_GT911 is not set
+# CONFIG_PKG_USING_FT6206 is not set
+# CONFIG_PKG_USING_FT5426 is not set
+# CONFIG_PKG_USING_FT6236 is not set
+# CONFIG_PKG_USING_XPT2046_TOUCH is not set
+# CONFIG_PKG_USING_CST816X is not set
+# CONFIG_PKG_USING_CST812T is not set
+# end of touch drivers
+
+# CONFIG_PKG_USING_REALTEK_AMEBA 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_INFRARED is not set
+# CONFIG_PKG_USING_MULTI_INFRARED is not set
+# CONFIG_PKG_USING_AGILE_BUTTON is not set
+# CONFIG_PKG_USING_AGILE_LED is not set
+# CONFIG_PKG_USING_AT24CXX is not set
+# CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set
+# CONFIG_PKG_USING_PCA9685 is not set
+# CONFIG_PKG_USING_ILI9341 is not set
+# CONFIG_PKG_USING_I2C_TOOLS is not set
+# CONFIG_PKG_USING_NRF24L01 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_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_AGILE_CONSOLE is not set
+# CONFIG_PKG_USING_LD3320 is not set
+# CONFIG_PKG_USING_WK2124 is not set
+# CONFIG_PKG_USING_LY68L6400 is not set
+# CONFIG_PKG_USING_DM9051 is not set
+# CONFIG_PKG_USING_SSD1306 is not set
+# CONFIG_PKG_USING_QKEY is not set
+# CONFIG_PKG_USING_RS485 is not set
+# CONFIG_PKG_USING_RS232 is not set
+# CONFIG_PKG_USING_NES is not set
+# CONFIG_PKG_USING_VIRTUAL_SENSOR is not set
+# CONFIG_PKG_USING_VDEVICE is not set
+# CONFIG_PKG_USING_SGM706 is not set
+# CONFIG_PKG_USING_RDA58XX is not set
+# CONFIG_PKG_USING_LIBNFC is not set
+# CONFIG_PKG_USING_MFOC is not set
+# CONFIG_PKG_USING_TMC51XX is not set
+# CONFIG_PKG_USING_TCA9534 is not set
+# CONFIG_PKG_USING_KOBUKI is not set
+# CONFIG_PKG_USING_ROSSERIAL is not set
+# CONFIG_PKG_USING_MICRO_ROS is not set
+# CONFIG_PKG_USING_MCP23008 is not set
+# CONFIG_PKG_USING_MISAKA_AT24CXX is not set
+# CONFIG_PKG_USING_MISAKA_RGB_BLING is not set
+# CONFIG_PKG_USING_LORA_MODEM_DRIVER is not set
+# CONFIG_PKG_USING_SOFT_SERIAL is not set
+# CONFIG_PKG_USING_MB85RS16 is not set
+# CONFIG_PKG_USING_RFM300 is not set
+# CONFIG_PKG_USING_IO_INPUT_FILTER is not set
+# CONFIG_PKG_USING_LRF_NV7LIDAR is not set
+# CONFIG_PKG_USING_AIP650 is not set
+# CONFIG_PKG_USING_FINGERPRINT is not set
+# CONFIG_PKG_USING_BT_ECB02C is not set
+# CONFIG_PKG_USING_UAT is not set
+# CONFIG_PKG_USING_ST7789 is not set
+# CONFIG_PKG_USING_VS1003 is not set
+# CONFIG_PKG_USING_X9555 is not set
+# CONFIG_PKG_USING_SYSTEM_RUN_LED is not set
+# CONFIG_PKG_USING_BT_MX01 is not set
+# CONFIG_PKG_USING_RGPOWER is not set
+# CONFIG_PKG_USING_SPI_TOOLS is not set
+# end of peripheral libraries and drivers
+
+#
+# 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
+# CONFIG_PKG_USING_NCNN is not set
+# CONFIG_PKG_USING_R_TINYMAIX is not set
+# end of AI packages
+
+#
+# Signal Processing and Control Algorithm Packages
+#
+# CONFIG_PKG_USING_FIRE_PID_CURVE is not set
+# CONFIG_PKG_USING_QPID is not set
+# CONFIG_PKG_USING_UKAL is not set
+# CONFIG_PKG_USING_DIGITALCTRL is not set
+# CONFIG_PKG_USING_KISSFFT is not set
+# end of Signal Processing and Control Algorithm Packages
+
+#
+# miscellaneous packages
+#
+
+#
+# project laboratory
+#
+# end of project laboratory
+
+#
+# samples: kernel and components samples
+#
+# CONFIG_PKG_USING_KERNEL_SAMPLES is not set
+# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set
+# CONFIG_PKG_USING_NETWORK_SAMPLES is not set
+# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set
+# end of samples: kernel and components samples
+
+#
+# entertainment: terminal games and other interesting software packages
+#
+# CONFIG_PKG_USING_CMATRIX is not set
+# CONFIG_PKG_USING_SL is not set
+# CONFIG_PKG_USING_CAL is not set
+# CONFIG_PKG_USING_ACLOCK is not set
+# CONFIG_PKG_USING_THREES is not set
+# CONFIG_PKG_USING_2048 is not set
+# CONFIG_PKG_USING_SNAKE is not set
+# CONFIG_PKG_USING_TETRIS is not set
+# CONFIG_PKG_USING_DONUT is not set
+# CONFIG_PKG_USING_COWSAY is not set
+# CONFIG_PKG_USING_MORSE is not set
+# end of entertainment: terminal games and other interesting software 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_RALARAM is not set
+# CONFIG_PKG_USING_MULTIBUTTON is not set
+# CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set
+# CONFIG_PKG_USING_CANFESTIVAL is not set
+# CONFIG_PKG_USING_ZLIB is not set
+# CONFIG_PKG_USING_MINIZIP is not set
+# CONFIG_PKG_USING_HEATSHRINK is not set
+# CONFIG_PKG_USING_DSTR is not set
+# CONFIG_PKG_USING_TINYFRAME is not set
+# CONFIG_PKG_USING_KENDRYTE_DEMO is not set
+# CONFIG_PKG_USING_UPACKER is not set
+# CONFIG_PKG_USING_UPARAM is not set
+# CONFIG_PKG_USING_HELLO is not set
+# CONFIG_PKG_USING_VI is not set
+# CONFIG_PKG_USING_KI is not set
+# CONFIG_PKG_USING_ARMv7M_DWT is not set
+# CONFIG_PKG_USING_CRCLIB is not set
+# CONFIG_PKG_USING_LWGPS is not set
+# CONFIG_PKG_USING_STATE_MACHINE is not set
+# CONFIG_PKG_USING_DESIGN_PATTERN is not set
+# CONFIG_PKG_USING_CONTROLLER is not set
+# CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set
+# CONFIG_PKG_USING_MFBD is not set
+# CONFIG_PKG_USING_SLCAN2RTT is not set
+# CONFIG_PKG_USING_SOEM is not set
+# CONFIG_PKG_USING_QPARAM is not set
+# CONFIG_PKG_USING_CorevMCU_CLI is not set
+# end of miscellaneous packages
+
+#
+# Arduino libraries
+#
+# CONFIG_PKG_USING_RTDUINO is not set
+
+#
+# Projects and Demos
+#
+# CONFIG_PKG_USING_ARDUINO_MSGQ_C_CPP_DEMO is not set
+# CONFIG_PKG_USING_ARDUINO_SKETCH_LOADER_DEMO is not set
+# CONFIG_PKG_USING_ARDUINO_ULTRASOUND_RADAR is not set
+# CONFIG_PKG_USING_ARDUINO_NINEINONE_SENSOR_SHIELD is not set
+# CONFIG_PKG_USING_ARDUINO_SENSOR_KIT is not set
+# CONFIG_PKG_USING_ARDUINO_MATLAB_SUPPORT is not set
+# end of Projects and Demos
+
+#
+# Sensors
+#
+# CONFIG_PKG_USING_ARDUINO_SENSOR_DEVICE_DRIVERS is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SENSOR is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SENSORLAB is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL375 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL53L0X is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL53L1X is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL6180X is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31855 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31865 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31856 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX6675 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90614 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM9DS1 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AHTX0 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM9DS0 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP280 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADT7410 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP085 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BME680 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP9808 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP4728 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_INA219 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LTR390 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL345 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DHT is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP9600 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM6DS is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO055 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX1704X is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MMC56X3 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90393 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90395 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ICM20X is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DPS310 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTS221 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHT4X is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHT31 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL343 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BME280 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AS726X is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AMG88XX is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AM2320 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AM2315 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LTR329_LTR303 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP085_UNIFIED is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP183 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP183_UNIFIED is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP3XX is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MS8607 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS3MDL is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90640 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MMA8451 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MSA301 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPL115A2 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO08X is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO08X_RVC is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS2MDL is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM303DLH_MAG is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LC709203F is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_CAP1188 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_CCS811 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_NAU7802 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS331 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LPS2X is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LPS35HW is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM303_ACCEL is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS3DH is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCF8591 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPL3115A2 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPR121 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPRLS is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPU6050 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCT2075 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PM25AQI is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_EMC2101 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_FXAS21002C is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SCD30 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_FXOS8700 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HMC5883_UNIFIED is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SGP30 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP006 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TLA202X is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TCS34725 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI7021 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI1145 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SGP40 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHTC3 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HDC1000 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTU21DF is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AS7341 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTU31D is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_INA260 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP007_LIBRARY is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_L3GD20 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP117 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSC2007 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSL2561 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSL2591_LIBRARY is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VCNL4040 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML6070 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML6075 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML7700 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_LIS3DHTR is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_DHT is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_ADXL335 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_ADXL345 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_BME280 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_BMP280 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_H3LIS331DL is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_MMA7660 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_TSL2561 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_PAJ7620 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_VL53L0X is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_ITG3200 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_SHT31 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_HP20X is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_DRV2605L is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_BBM150 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_HMC5883L is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_LSM303DLH is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_TCS3414CS is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_MP503 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_BMP085 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_HIGHTEMP is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_VEML6070 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_SI1145 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_SHT35 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_AT42QT1070 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_LSM6DS3 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_HDC1000 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_HM3301 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_MCP9600 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_LTC2941 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_LDC1612 is not set
+# CONFIG_PKG_USING_ARDUINO_CAPACITIVESENSOR is not set
+# CONFIG_PKG_USING_ARDUINO_JARZEBSKI_MPU6050 is not set
+# end of Sensors
+
+#
+# Display
+#
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_GFX_LIBRARY is not set
+# CONFIG_PKG_USING_ARDUINO_U8G2 is not set
+# CONFIG_PKG_USING_ARDUINO_TFT_ESPI is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ST7735 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SSD1306 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ILI9341 is not set
+# CONFIG_PKG_USING_SEEED_TM1637 is not set
+# end of Display
+
+#
+# Timing
+#
+# CONFIG_PKG_USING_ARDUINO_RTCLIB is not set
+# CONFIG_PKG_USING_ARDUINO_MSTIMER2 is not set
+# CONFIG_PKG_USING_ARDUINO_TICKER is not set
+# CONFIG_PKG_USING_ARDUINO_TASKSCHEDULER is not set
+# end of Timing
+
+#
+# Data Processing
+#
+# CONFIG_PKG_USING_ARDUINO_KALMANFILTER is not set
+# CONFIG_PKG_USING_ARDUINO_ARDUINOJSON is not set
+# CONFIG_PKG_USING_ARDUINO_TENSORFLOW_LITE_MICRO is not set
+# CONFIG_PKG_USING_ARDUINO_RUNNINGMEDIAN is not set
+# end of Data Processing
+
+#
+# Data Storage
+#
+
+#
+# Communication
+#
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PN532 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI4713 is not set
+# end of Communication
+
+#
+# Device Control
+#
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCF8574 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCA9685 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TPA2016 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DRV2605 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DS1841 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DS3502 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_PCF85063TP is not set
+# end of Device Control
+
+#
+# Other
+#
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MFRC630 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI5351 is not set
+# end of Other
+
+#
+# Signal IO
+#
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BUSIO is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TCA8418 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP23017 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADS1X15 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AW9523 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP3008 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP4725 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BD3491FS is not set
+# end of Signal IO
+
+#
+# Uncategorized
+#
+# end of Arduino libraries
+# end of RT-Thread online packages
+
+#
+# Privated Packages of RealThread
+#
+# CONFIG_PKG_USING_CODEC is not set
+# CONFIG_PKG_USING_PLAYER is not set
+# CONFIG_PKG_USING_MPLAYER is not set
+# CONFIG_PKG_USING_PERSIMMON_SRC is not set
+# CONFIG_PKG_USING_JS_PERSIMMON is not set
+# CONFIG_PKG_USING_JERRYSCRIPT_WIN32 is not set
+
+#
+# Network Utilities
+#
+# CONFIG_PKG_USING_MDNS is not set
+# CONFIG_PKG_USING_UPNP is not set
+# end of Network Utilities
+
+# CONFIG_PKG_USING_WICED is not set
+# CONFIG_PKG_USING_CLOUDSDK is not set
+# CONFIG_PKG_USING_POWER_MANAGER is not set
+# CONFIG_PKG_USING_RT_OTA is not set
+# CONFIG_PKG_USING_RTINSIGHT is not set
+# CONFIG_PKG_USING_SMARTCONFIG is not set
+# CONFIG_PKG_USING_RTX is not set
+# CONFIG_RT_USING_TESTCASE is not set
+# CONFIG_PKG_USING_NGHTTP2 is not set
+# CONFIG_PKG_USING_AVS is not set
+# CONFIG_PKG_USING_ALI_LINKKIT is not set
+# CONFIG_PKG_USING_STS is not set
+# CONFIG_PKG_USING_DLMS is not set
+# CONFIG_PKG_USING_AUDIO_FRAMEWORK is not set
+# CONFIG_PKG_USING_ZBAR is not set
+# CONFIG_PKG_USING_MCF is not set
+# CONFIG_PKG_USING_URPC is not set
+# CONFIG_PKG_USING_DCM is not set
+# CONFIG_PKG_USING_EMQ is not set
+# CONFIG_PKG_USING_CFGM is not set
+# CONFIG_PKG_USING_RT_CMSIS_DAP is not set
+# CONFIG_PKG_USING_SMODULE is not set
+# CONFIG_PKG_USING_SNFD is not set
+# CONFIG_PKG_USING_UDBD is not set
+# CONFIG_PKG_USING_BENCHMARK is not set
+# CONFIG_PKG_USING_UBJSON is not set
+# CONFIG_PKG_USING_DATATYPE is not set
+# CONFIG_PKG_USING_FASTFS is not set
+# CONFIG_PKG_USING_RIL is not set
+# CONFIG_PKG_USING_WATCH_DCM_SVC is not set
+# CONFIG_PKG_USING_WATCH_APP_FWK is not set
+# CONFIG_PKG_USING_GUI_TEST is not set
+# CONFIG_PKG_USING_PMEM is not set
+# CONFIG_PKG_USING_LWRDP is not set
+# CONFIG_PKG_USING_MASAN is not set
+# CONFIG_PKG_USING_BSDIFF_LIB is not set
+# CONFIG_PKG_USING_PRC_DIFF is not set
+
+#
+# RT-Thread Smart
+#
+CONFIG_PKG_USING_UKERNEL=y
+CONFIG_PKG_UKERNEL_PATH="/realthread-packages/smart/ukernel"
+# CONFIG_PKG_USING_UKERNEL_V100 is not set
+CONFIG_PKG_USING_UKERNEL_LATEST_VERSION=y
+CONFIG_PKG_UKERNEL_VER="latest"
+# CONFIG_LWP_USING_CORE_DUMP is not set
+# CONFIG_RT_USING_GDBSERVER is not set
+# CONFIG_RT_USING_DFS_UFS is not set
+# CONFIG_SAL_USING_UNET is not set
+# CONFIG_RT_USING_MSH_KSHELL_AGENT is not set
+CONFIG_RT_USING_NETIF_LOOPBACK=y
+# CONFIG_UKERNEL_USING_PMQ is not set
+# CONFIG_UKERNEL_USING_UDD is not set
+# CONFIG_RT_USING_DEVICE_DRIVER_MODEL is not set
+# CONFIG_RT_USING_AARCH64_PMU is not set
+# CONFIG_RT_USING_SCHEDULER_EXT is not set
+CONFIG_RT_USING_DFS_PROCFS=y
+# CONFIG_RT_USING_DFS_CMDFS is not set
+CONFIG_SAL_USING_AF_UNIX=y
+# CONFIG_SAL_USING_AF_NETLINK is not set
+# CONFIG_PKG_USING_DMA_BUF is not set
+# CONFIG_PKG_USING_V4L2 is not set
+# CONFIG_RT_USING_TRACING is not set
+# end of RT-Thread Smart
+
+# CONFIG_PKG_USING_TRACE_AGENT is not set
+# CONFIG_PKG_USING_DLOG is not set
+CONFIG_PKG_USING_EXT4=y
+CONFIG_PKG_EXT4_PATH="/realthread-packages/ext4"
+# CONFIG_PKG_USING_EXT4_LATEST_VERSION is not set
+CONFIG_PKG_USING_EXT4_SMART_DFS_VERSION=y
+CONFIG_PKG_EXT4_VER="smart-dfs"
+# end of Privated Packages of RealThread
+
+CONFIG_BCM2711_SOC=y
+
+#
+# Hardware Drivers Config
+#
+CONFIG_BSP_USING_PL011=y
+CONFIG_BSP_USING_SDHCI=y
+CONFIG_RT_USING_SDHCI=y
+# end of Hardware Drivers Config

+ 22 - 0
bsp/raspberry-pi/raspi-dm2.0/Kconfig

@@ -0,0 +1,22 @@
+mainmenu "RT-Thread Project Configuration"
+
+BSP_DIR := .
+
+RTT_DIR := ../../..
+
+PKGS_DIR := packages
+
+source "$(RTT_DIR)/Kconfig"
+osource "$PKGS_DIR/Kconfig"
+
+config BCM2711_SOC
+    bool
+    select ARCH_ARMV8
+    select ARCH_ARM_MMU
+    select RT_USING_CACHE
+    select RT_USING_COMPONENTS_INIT
+    select RT_USING_USER_MAIN
+    select ARCH_CPU_64BIT
+    default y
+
+rsource "drivers/Kconfig"

+ 33 - 0
bsp/raspberry-pi/raspi-dm2.0/README.md

@@ -0,0 +1,33 @@
+# Raspberry PI 4-dm2.0BSP说明
+
+## 1. 简介
+
+树莓派4B的核心处理器为博通BCM2711(四核1.5GHz,Cortex A72架构,树莓派3是四核A53)。LPDDR4内存,由5V/3A USB-C供电或GPIO 5V。
+
+外设支持上,引入了双频Wi-Fi,蓝牙5.0,千兆网卡,MIPI CSI相机接口,两个USB口,40个扩展帧。
+
+这份RT-Thread BSP是针对 Raspberry Pi 4的一份移植,树莓派价格便宜, 使用者甚众,是研究和运行RT-Thread的可选平台之一。
+
+
+## 2. 编译说明
+
+推荐使用[env工具](https://www.rt-thread.org/download.html#download-rt-thread-env-tool),可以在console下进入到`bsp\raspberry-pi\raspi4-64`目录中,运行以下命令:
+
+```
+scons
+```
+
+来编译这个板级支持包。如果编译正确无误,会产生 `rtthread.elf`, `rtthread.bin` 文件。
+
+## 3. 支持情况
+
+| 驱动 | 支持情况  |  备注  |
+| ------ | ----  | :------:  |
+| UART | 支持 | pl011驱动 |
+| GPIO | 尚未支持 | 等待dm2.0相关代码合入主线 |
+| SPI | 尚未支持 | 等待gpio合入主线 |
+| WATCHDOG | 尚未支持 | 等待gpio合入主线 |
+| HDMI | 尚未支持 | 等待gpio合入主线 |
+| SDIO | 支持 | 能够正常运行在qemu,但是qemu对于raspi目前只支持pio传输,后续需要硬件进行详细测试 |
+| ETH | 尚未支持 | 等待gpio合入主线 |
+

+ 14 - 0
bsp/raspberry-pi/raspi-dm2.0/SConscript

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

+ 30 - 0
bsp/raspberry-pi/raspi-dm2.0/SConstruct

@@ -0,0 +1,30 @@
+import os
+import sys
+import rtconfig
+
+from rtconfig import RTT_ROOT
+
+sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
+from building import *
+
+TARGET = 'rtthread.' + rtconfig.TARGET_EXT
+
+DefaultEnvironment(tools=[])
+env = Environment(tools = ['mingw'],
+    AS   = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
+    CC   = rtconfig.CC, CFLAGS = rtconfig.CFLAGS,
+    CPP  = rtconfig.CPP, CXXFLAGS = rtconfig.CXXFLAGS,
+    AR   = rtconfig.AR, ARFLAGS = '-rc',
+    LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS)
+env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
+env['ASCOM'] = env['ASPPCOM']
+env['LINKCOM'] = '$LINK -o $TARGET $LINKFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS -Wl,--start-group $_LIBFLAGS -Wl,--end-group'
+
+Export('RTT_ROOT')
+Export('rtconfig')
+
+# prepare building environment
+objs = PrepareBuilding(env, RTT_ROOT)
+
+# make a building
+DoBuilding(TARGET, objs)

+ 14 - 0
bsp/raspberry-pi/raspi-dm2.0/applications/SConscript

@@ -0,0 +1,14 @@
+from building import *
+
+cwd     = GetCurrentDir()
+src     = Glob('*.c') + Glob('*.cpp')
+CPPPATH = [cwd, str(Dir('#'))]
+
+group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
+
+list = os.listdir(cwd)
+for item in list:
+    if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
+        group = group + SConscript(os.path.join(item, 'SConscript'))
+
+Return('group')

+ 19 - 0
bsp/raspberry-pi/raspi-dm2.0/applications/main.c

@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2006-2024 RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author         Notes
+ * 2020-04-16     bigmagic       first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <board.h>
+
+int main(int argc, char** argv)
+{
+    rt_kprintf("Hi, this is RT-Thread!!\n");
+    return 0;
+}

二進制
bsp/raspberry-pi/raspi-dm2.0/bcm2711-rpi-4-b.dtb


+ 13 - 0
bsp/raspberry-pi/raspi-dm2.0/drivers/Kconfig

@@ -0,0 +1,13 @@
+
+
+menu "Hardware Drivers Config"
+     config BSP_USING_PL011
+        bool "Enable pl011 for uart"
+        default n
+
+    config BSP_USING_SDHCI
+        bool "Enable sdhci driver"
+        select RT_USING_SDHCI
+        default y
+    rsource sdhci/Kconfig
+endmenu

+ 25 - 0
bsp/raspberry-pi/raspi-dm2.0/drivers/SConscript

@@ -0,0 +1,25 @@
+from building import *
+
+cwd     = GetCurrentDir()
+src     = ["board.c"]
+CPPPATH = [cwd, str(Dir('#'))]
+
+if GetDepend(['BSP_USING_PL011']):
+    src = src + ['drv_uart.c']
+
+if GetDepend(['BSP_USING_SDHCI']):
+    src = src + ['drv_sd.c']
+
+group = DefineGroup('driver', src, depend = [''], CPPPATH = CPPPATH)
+
+# build for sub-directory
+list = os.listdir(cwd)
+objs = []
+
+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'))
+group = group + objs
+
+Return('group')

+ 32 - 0
bsp/raspberry-pi/raspi-dm2.0/drivers/board.c

@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2006-2024 RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2024-10-28     zhujiale     The first version
+ */
+
+#define DBG_TAG "board"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <mm_aspace.h>
+#include <setup.h>
+#include "board.h"
+#include "drv_uart.h"
+
+#include "cp15.h"
+#include "mmu.h"
+#include <mm_page.h>
+
+#ifdef RT_USING_SMART
+#include <lwp_arch.h>
+#endif
+void rt_hw_board_init(void)
+{
+    rt_hw_common_setup();
+}

+ 35 - 0
bsp/raspberry-pi/raspi-dm2.0/drivers/board.h

@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2006-2024 RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2024-10-28     zhujiale     The first version
+ */
+
+#ifndef BOARD_H__
+#define BOARD_H__
+
+#include <stdint.h>
+#include "mmu.h"
+#include "ioremap.h"
+
+extern int __bss_end;
+#define HEAP_BEGIN      ((void*)&__bss_end)
+
+#ifdef RT_USING_SMART
+#define HEAP_END        ((size_t)KERNEL_VADDR_START + 32 * 1024 * 1024)
+#define PAGE_START      HEAP_END
+#define PAGE_END        ((size_t)KERNEL_VADDR_START + 128 * 1024 * 1024)
+#else
+#define KERNEL_VADDR_START 0x0
+
+#define HEAP_END        (KERNEL_VADDR_START + 32 * 1024 * 1024)
+#define PAGE_START      HEAP_END
+#define PAGE_END        ((size_t)PAGE_START + 128 * 1024 * 1024)
+#endif
+
+void rt_hw_board_init(void);
+
+#endif

+ 219 - 0
bsp/raspberry-pi/raspi-dm2.0/drivers/drv_sd.c

@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2006-2024 RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2024-10-28     zhujiale     The first version
+ */
+
+#include <sdhci.h>
+#include <rtdevice.h>
+#include "drv_sd.h"
+#define DBG_TAG "SDHCI"
+#ifdef DRV_DEBUG
+#define DBG_LVL DBG_LOG
+#else
+#define DBG_LVL DBG_INFO
+#endif /* DRV_DEBUG */
+#include <rtdbg.h>
+#define REG_OFFSET_IN_BITS(reg) ((reg) << 3 & 0x18)
+struct sdhci_iproc_data {
+    const struct sdhci_pltfm_data *pdata;
+    rt_uint32_t caps;
+    rt_uint32_t caps1;
+    rt_uint32_t mmc_caps;
+    rt_bool_t missing_caps;
+};
+
+struct sdhci_iproc_host {
+    const struct sdhci_iproc_data *data;
+    rt_uint32_t shadow_cmd;
+    rt_uint32_t shadow_blk;
+    rt_bool_t is_cmd_shadowed;
+    rt_bool_t is_blk_shadowed;
+};
+
+static inline rt_uint32_t sdhci_iproc_readl(struct sdhci_host *host, int reg)
+{
+    rt_uint32_t val = readl(host->ioaddr + reg);
+
+    return val;
+}
+
+static rt_uint16_t sdhci_iproc_readw(struct sdhci_host *host, int reg)
+{
+    struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+    struct sdhci_iproc_host *iproc_host = sdhci_pltfm_priv(pltfm_host);
+    rt_uint32_t val;
+    rt_uint16_t word;
+
+    if ((reg == SDHCI_TRANSFER_MODE) && iproc_host->is_cmd_shadowed)
+    {
+        /* Get the saved transfer mode */
+        val = iproc_host->shadow_cmd;
+    } else if ((reg == SDHCI_BLOCK_SIZE || reg == SDHCI_BLOCK_COUNT) &&
+           iproc_host->is_blk_shadowed)
+           {
+        /* Get the saved block info */
+        val = iproc_host->shadow_blk;
+    } else {
+        val = sdhci_iproc_readl(host, (reg & ~3));
+    }
+    word = val >> REG_OFFSET_IN_BITS(reg) & 0xffff;
+    return word;
+}
+
+static rt_uint8_t sdhci_iproc_readb(struct sdhci_host *host, int reg)
+{
+    rt_uint32_t val = sdhci_iproc_readl(host, (reg & ~3));
+    rt_uint8_t byte = val >> REG_OFFSET_IN_BITS(reg) & 0xff;
+    return byte;
+}
+
+static inline void sdhci_iproc_writel(struct sdhci_host *host, rt_uint32_t val, int reg)
+{
+    LOG_D("%s: writel [0x%02x] 0x%08x\n",
+         mmc_hostname(host->mmc), reg, val);
+    writel(val, host->ioaddr + reg);
+    if (host->clock <= 400000)
+    {
+        /* Round up to micro-second four SD clock delay */
+        if (host->clock)
+            rt_hw_us_delay((4 * 1000000 + host->clock - 1) / host->clock);
+        else
+            rt_hw_us_delay(10);
+    }
+}
+
+static void sdhci_iproc_writew(struct sdhci_host *host, rt_uint16_t val, int reg)
+{
+    struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+    struct sdhci_iproc_host *iproc_host = sdhci_pltfm_priv(pltfm_host);
+    rt_uint32_t word_shift = REG_OFFSET_IN_BITS(reg);
+    rt_uint32_t mask = 0xffff << word_shift;
+    rt_uint32_t oldval, newval;
+
+    if (reg == SDHCI_COMMAND)
+    {
+        /* Write the block now as we are issuing a command */
+        if (iproc_host->is_blk_shadowed)
+        {
+            sdhci_iproc_writel(host, iproc_host->shadow_blk,
+                SDHCI_BLOCK_SIZE);
+            iproc_host->is_blk_shadowed = false;
+        }
+        oldval = iproc_host->shadow_cmd;
+        iproc_host->is_cmd_shadowed = false;
+    } else if ((reg == SDHCI_BLOCK_SIZE || reg == SDHCI_BLOCK_COUNT) &&
+           iproc_host->is_blk_shadowed)
+           {
+        /* Block size and count are stored in shadow reg */
+        oldval = iproc_host->shadow_blk;
+    } else {
+        /* Read reg, all other registers are not shadowed */
+        oldval = sdhci_iproc_readl(host, (reg & ~3));
+    }
+    newval = (oldval & ~mask) | (val << word_shift);
+
+    if (reg == SDHCI_TRANSFER_MODE)
+    {
+        /* Save the transfer mode until the command is issued */
+        iproc_host->shadow_cmd = newval;
+        iproc_host->is_cmd_shadowed = true;
+    } else if (reg == SDHCI_BLOCK_SIZE || reg == SDHCI_BLOCK_COUNT)
+    {
+        /* Save the block info until the command is issued */
+        iproc_host->shadow_blk = newval;
+        iproc_host->is_blk_shadowed = true;
+    } else {
+        /* Command or other regular 32-bit write */
+        sdhci_iproc_writel(host, newval, reg & ~3);
+    }
+}
+
+static void sdhci_iproc_writeb(struct sdhci_host *host, rt_uint8_t val, int reg)
+{
+    rt_uint32_t oldval = sdhci_iproc_readl(host, (reg & ~3));
+    rt_uint32_t byte_shift = REG_OFFSET_IN_BITS(reg);
+    rt_uint32_t mask = 0xff << byte_shift;
+    rt_uint32_t newval = (oldval & ~mask) | (val << byte_shift);
+
+    sdhci_iproc_writel(host, newval, reg & ~3);
+}
+
+static const struct sdhci_ops sdhci_iproc_bcm2711_ops = {
+    .read_l = sdhci_iproc_readl,
+    .read_w = sdhci_iproc_readw,
+    .read_b = sdhci_iproc_readb,
+    .write_l = sdhci_iproc_writel,
+    .write_w = sdhci_iproc_writew,
+    .write_b = sdhci_iproc_writeb,
+    .set_clock = sdhci_set_clock,
+    .set_bus_width = sdhci_set_bus_width,
+    .reset = sdhci_reset,
+    .set_uhs_signaling = sdhci_set_uhs_signaling,
+};
+
+static const struct sdhci_pltfm_data sdhci_bcm2711_pltfm_data = {
+    .quirks = SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12,
+    .ops = &sdhci_iproc_bcm2711_ops,
+};
+
+static const struct sdhci_iproc_data bcm2711_data = {
+    .pdata = &sdhci_bcm2711_pltfm_data,
+    .mmc_caps = MMC_CAP_3_3V_DDR,
+};
+
+rt_err_t bcm2835_probe(struct rt_platform_device *pdev)
+{
+    struct sdhci_iproc_host *iproc_host;
+    const struct sdhci_iproc_data *iproc_data = NULL;
+    struct sdhci_host *host;
+    struct sdhci_pltfm_host *pltfm_host;
+    int ret;
+    iproc_data = &bcm2711_data;
+    host = sdhci_pltfm_init(pdev, iproc_data->pdata, sizeof(*iproc_host));
+    pltfm_host = sdhci_priv(host);
+    iproc_host = sdhci_pltfm_priv(pltfm_host);
+
+    iproc_host->data = iproc_data;
+
+    ret = mmc_of_parse(host->mmc);
+    if (ret)
+        goto err;
+
+    sdhci_get_property(pdev);
+
+    host->mmc->caps |= iproc_host->data->mmc_caps;
+
+    ret = sdhci_add_host(host);
+    if (ret)
+        goto err;
+
+    return 0;
+err:
+    return ret;
+}
+
+static const struct rt_ofw_node_id bcm2835_ofw_ids[] =
+{
+    /* { .compatible = "brcm,bcm2711-emmc2"},*/
+    { .compatible = "brcm,bcm2835-mmc"},
+    { /* sentinel */ }
+};
+
+static struct rt_platform_driver bcm2835_driver =
+{
+    .name = "bcm2835",
+    .ids = bcm2835_ofw_ids,
+
+    .probe = bcm2835_probe,
+    /* .remove = pl011_remove,*/
+};
+
+
+RT_PLATFORM_DRIVER_EXPORT(bcm2835_driver);
+
+

+ 117 - 0
bsp/raspberry-pi/raspi-dm2.0/drivers/drv_sd.h

@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2006-2024 RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2024-10-28     zhujiale     The first version
+ */
+
+#ifndef __DRV_SD_BCM2835_H_
+#define __DRV_SD_BCM2835_H_
+#include <drivers/dev_mmcsd_core.h>
+#include <rtthread.h>
+#include <drivers/mmcsd_cmd.h>
+#include <drivers/mmcsd_host.h>
+struct sdhci_bcm2835 {
+    struct sdhci_host *host;
+    struct rt_platform_device *pdev;
+    struct rt_mmcsd_req *mrq;
+
+    void *ioaddr;
+    rt_mutex_t mutex;
+};
+#define SDCMD  0x00 /* Command to SD card              - 16 R/W */
+#define SDARG  0x04 /* Argument to SD card             - 32 R/W */
+#define SDTOUT 0x08 /* Start value for timeout counter - 32 R/W */
+#define SDCDIV 0x0c /* Start value for clock divider   - 11 R/W */
+#define SDRSP0 0x10 /* SD card response (31:0)         - 32 R   */
+#define SDRSP1 0x14 /* SD card response (63:32)        - 32 R   */
+#define SDRSP2 0x18 /* SD card response (95:64)        - 32 R   */
+#define SDRSP3 0x1c /* SD card response (127:96)       - 32 R   */
+#define SDHSTS 0x20 /* SD host status                  - 11 R/W */
+#define SDVDD  0x30 /* SD card power control           -  1 R/W */
+#define SDEDM  0x34 /* Emergency Debug Mode            - 13 R/W */
+#define SDHCFG 0x38 /* Host configuration              -  2 R/W */
+#define SDHBCT 0x3c /* Host byte count (debug)         - 32 R/W */
+#define SDDATA 0x40 /* Data to/from SD card            - 32 R/W */
+#define SDHBLC 0x50 /* Host block count (SDIO/SDHC)    -  9 R/W */
+
+#define SDCMD_NEW_FLAG          0x8000
+#define SDCMD_FAIL_FLAG         0x4000
+#define SDCMD_BUSYWAIT          0x800
+#define SDCMD_NO_RESPONSE       0x400
+#define SDCMD_LONG_RESPONSE     0x200
+#define SDCMD_WRITE_CMD         0x80
+#define SDCMD_READ_CMD          0x40
+#define SDCMD_CMD_MASK          0x3f
+
+#define SDCDIV_MAX_CDIV         0x7ff
+
+#define SDHSTS_BUSY_IRPT        0x400
+#define SDHSTS_BLOCK_IRPT       0x200
+#define SDHSTS_SDIO_IRPT        0x100
+#define SDHSTS_REW_TIME_OUT     0x80
+#define SDHSTS_CMD_TIME_OUT     0x40
+#define SDHSTS_CRC16_ERROR      0x20
+#define SDHSTS_CRC7_ERROR       0x10
+#define SDHSTS_FIFO_ERROR       0x08
+/* Reserved */
+/* Reserved */
+#define SDHSTS_DATA_FLAG        0x01
+
+#define SDHSTS_TRANSFER_ERROR_MASK  (SDHSTS_CRC7_ERROR | \
+                     SDHSTS_CRC16_ERROR | \
+                     SDHSTS_REW_TIME_OUT | \
+                     SDHSTS_FIFO_ERROR)
+
+#define SDHSTS_ERROR_MASK       (SDHSTS_CMD_TIME_OUT | \
+                     SDHSTS_TRANSFER_ERROR_MASK)
+
+#define SDHCFG_BUSY_IRPT_EN BIT(10)
+#define SDHCFG_BLOCK_IRPT_EN    BIT(8)
+#define SDHCFG_SDIO_IRPT_EN BIT(5)
+#define SDHCFG_DATA_IRPT_EN BIT(4)
+#define SDHCFG_SLOW_CARD    BIT(3)
+#define SDHCFG_WIDE_EXT_BUS BIT(2)
+#define SDHCFG_WIDE_INT_BUS BIT(1)
+#define SDHCFG_REL_CMD_LINE BIT(0)
+
+#define SDVDD_POWER_OFF     0
+#define SDVDD_POWER_ON      1
+
+#define SDEDM_FORCE_DATA_MODE   BIT(19)
+#define SDEDM_CLOCK_PULSE   BIT(20)
+#define SDEDM_BYPASS        BIT(21)
+
+#define SDEDM_WRITE_THRESHOLD_SHIFT 9
+#define SDEDM_READ_THRESHOLD_SHIFT  14
+#define SDEDM_THRESHOLD_MASK        0x1f
+
+#define SDEDM_FSM_MASK      0xf
+#define SDEDM_FSM_IDENTMODE 0x0
+#define SDEDM_FSM_DATAMODE  0x1
+#define SDEDM_FSM_READDATA  0x2
+#define SDEDM_FSM_WRITEDATA 0x3
+#define SDEDM_FSM_READWAIT  0x4
+#define SDEDM_FSM_READCRC   0x5
+#define SDEDM_FSM_WRITECRC  0x6
+#define SDEDM_FSM_WRITEWAIT1    0x7
+#define SDEDM_FSM_POWERDOWN 0x8
+#define SDEDM_FSM_POWERUP   0x9
+#define SDEDM_FSM_WRITESTART1   0xa
+#define SDEDM_FSM_WRITESTART2   0xb
+#define SDEDM_FSM_GENPULSES 0xc
+#define SDEDM_FSM_WRITEWAIT2    0xd
+#define SDEDM_FSM_STARTPOWDOWN  0xf
+
+#define SDDATA_FIFO_WORDS   16
+
+#define FIFO_READ_THRESHOLD 4
+#define FIFO_WRITE_THRESHOLD    4
+#define SDDATA_FIFO_PIO_BURST   8
+
+#define PIO_THRESHOLD   1  /* Maximum block count for PIO (0 = always DMA) */
+
+#endif

+ 418 - 0
bsp/raspberry-pi/raspi-dm2.0/drivers/drv_uart.c

@@ -0,0 +1,418 @@
+/*
+ * Copyright (c) 2006-2024 RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-05-05     Bernard      The first version
+ * 2022-08-24     GuEe-GUI     add OFW support
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#include <cpuport.h>
+
+#include <ioremap.h>
+
+#include <drivers/serial_dm.h>
+
+#define PL011_OEIM          RT_BIT(10)  /* overrun error interrupt mask */
+#define PL011_BEIM          RT_BIT(9)   /* break error interrupt mask */
+#define PL011_PEIM          RT_BIT(8)   /* parity error interrupt mask */
+#define PL011_FEIM          RT_BIT(7)   /* framing error interrupt mask */
+#define PL011_RTIM          RT_BIT(6)   /* receive timeout interrupt mask */
+#define PL011_TXIM          RT_BIT(5)   /* transmit interrupt mask */
+#define PL011_RXIM          RT_BIT(4)   /* receive interrupt mask */
+#define PL011_DSRMIM        RT_BIT(3)   /* DSR interrupt mask */
+#define PL011_DCDMIM        RT_BIT(2)   /* DCD interrupt mask */
+#define PL011_CTSMIM        RT_BIT(1)   /* CTS interrupt mask */
+#define PL011_RIMIM         RT_BIT(0)   /* RI interrupt mask */
+
+#define PL011_DR            0x000
+#define PL011_FR            0x018
+#define PL011_IBRD          0x024
+#define PL011_FBRD          0x028
+#define PL011_LCR           0x02c
+#define PL011_CR            0x030
+#define PL011_IMSC          0x038
+#define PL011_RIS           0x03c
+#define PL011_DMACR         0x048
+
+#define PL011_LCRH_SPS      (1 << 7)
+#define PL011_LCRH_WLEN_8   (3 << 5)
+#define PL011_LCRH_WLEN_7   (2 << 5)
+#define PL011_LCRH_WLEN_6   (1 << 5)
+#define PL011_LCRH_WLEN_5   (0 << 5)
+#define PL011_LCRH_FEN      (1 << 4)
+#define PL011_LCRH_STP2     (1 << 3)
+#define PL011_LCRH_EPS      (1 << 2)
+#define PL011_LCRH_PEN      (1 << 1)
+#define PL011_LCRH_BRK      (1 << 0)
+
+#define PL011_LCRH_WLEN(n)  ((n - 5) << 5)
+
+#define PL011_CR_CTSEN      RT_BIT(15)
+#define PL011_CR_RTSEN      RT_BIT(14)
+#define PL011_CR_RTS        RT_BIT(11)
+#define PL011_CR_DTR        RT_BIT(10)
+#define PL011_CR_RXE        RT_BIT(9)
+#define PL011_CR_TXE        RT_BIT(8)
+#define PL011_CR_LBE        RT_BIT(7)
+#define PL011_CR_SIRLP      RT_BIT(2)
+#define PL011_CR_SIREN      RT_BIT(1)
+#define PL011_CR_UARTEN     RT_BIT(0)
+
+struct pl011
+{
+    struct rt_serial_device parent;
+
+    int irq;
+    void *base;
+    rt_ubase_t freq;
+    struct rt_clk *clk;
+    struct rt_clk *pclk;
+
+    struct rt_spinlock spinlock;
+};
+
+#define raw_to_pl011(raw) rt_container_of(raw, struct pl011, parent)
+
+rt_inline rt_uint32_t pl011_read(struct pl011 *pl011, int offset)
+{
+    return HWREG32(pl011->base + offset);
+}
+
+rt_inline void pl011_write(struct pl011 *pl011, int offset, rt_uint32_t value)
+{
+    HWREG32(pl011->base + offset) = value;
+}
+
+static void pl011_isr(int irqno, void *param)
+{
+    struct pl011 *pl011 = param;
+
+    /* Check irq */
+    if (pl011_read(pl011, PL011_RIS) & PL011_RXIM)
+    {
+        rt_base_t level = rt_spin_lock_irqsave(&pl011->spinlock);
+
+        rt_hw_serial_isr(&pl011->parent, RT_SERIAL_EVENT_RX_IND);
+
+        rt_spin_unlock_irqrestore(&pl011->spinlock, level);
+    }
+}
+
+static rt_err_t pl011_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
+{
+    rt_ubase_t quot;
+    struct pl011 *pl011 = raw_to_pl011(serial);
+
+    /* Clear UART setting */
+    pl011_write(pl011, PL011_CR, 0);
+    /* Disable FIFO */
+    pl011_write(pl011, PL011_LCR, 0);
+
+    if (cfg->baud_rate > pl011->freq / 16)
+    {
+        quot = RT_DIV_ROUND_CLOSEST(pl011->freq * 8, cfg->baud_rate);
+    }
+    else
+    {
+        quot = RT_DIV_ROUND_CLOSEST(pl011->freq * 4, cfg->baud_rate);
+    }
+
+    pl011_write(pl011, PL011_IBRD, quot >> 6);
+    pl011_write(pl011, PL011_FBRD, quot & 0x3f);
+    /* FIFO */
+    pl011_write(pl011, PL011_LCR, PL011_LCRH_WLEN(cfg->data_bits));
+
+    /* Art enable, TX/RX enable */
+    pl011_write(pl011, PL011_CR, PL011_CR_UARTEN | PL011_CR_TXE | PL011_CR_RXE);
+
+    return RT_EOK;
+}
+
+static rt_err_t pl011_uart_control(struct rt_serial_device *serial, int cmd, void *arg)
+{
+    struct pl011 *pl011 = raw_to_pl011(serial);
+
+    switch (cmd)
+    {
+    case RT_DEVICE_CTRL_CLR_INT:
+        /* Disable rx irq */
+        pl011_write(pl011, PL011_IMSC, pl011_read(pl011, PL011_IMSC) & ~PL011_RXIM);
+
+        rt_hw_interrupt_mask(pl011->irq);
+
+        break;
+
+    case RT_DEVICE_CTRL_SET_INT:
+        /* Enable rx irq */
+        pl011_write(pl011, PL011_IMSC, pl011_read(pl011, PL011_IMSC) | PL011_RXIM);
+
+        rt_hw_interrupt_umask(pl011->irq);
+
+        break;
+    }
+
+    return RT_EOK;
+}
+
+static int pl011_uart_putc(struct rt_serial_device *serial, char c)
+{
+    struct pl011 *pl011 = raw_to_pl011(serial);
+
+    while (pl011_read(pl011, PL011_FR) & PL011_TXIM)
+    {
+        rt_hw_cpu_relax();
+    }
+
+    pl011_write(pl011, PL011_DR, c);
+
+    return 1;
+}
+
+static int pl011_uart_getc(struct rt_serial_device *serial)
+{
+    int ch = -1;
+    struct pl011 *pl011 = raw_to_pl011(serial);
+
+    if (!(pl011_read(pl011, PL011_FR) & PL011_RXIM))
+    {
+        ch = pl011_read(pl011, PL011_DR);
+    }
+
+    return ch;
+}
+
+static const struct rt_uart_ops pl011_uart_ops =
+{
+    .configure = pl011_uart_configure,
+    .control = pl011_uart_control,
+    .putc = pl011_uart_putc,
+    .getc = pl011_uart_getc,
+};
+
+static void pl011_early_kick(struct rt_fdt_earlycon *con, int why)
+{
+    struct pl011 *pl011 = raw_to_pl011(con->data);
+
+    switch (why)
+    {
+    case FDT_EARLYCON_KICK_UPDATE:
+        pl011->base = rt_ioremap((void *)con->mmio, con->size);
+        break;
+
+    case FDT_EARLYCON_KICK_COMPLETED:
+        rt_iounmap(pl011->base);
+        break;
+
+    default:
+        break;
+    }
+}
+
+static rt_err_t pl011_early_setup(struct rt_fdt_earlycon *con, const char *options)
+{
+    rt_err_t err = RT_EOK;
+    static struct pl011 pl011 = { };
+
+    if (options && !con->mmio)
+    {
+        char *arg;
+
+        con->mmio = RT_NULL;
+
+        /*
+         *  The pl011 serial port must already be setup and configured in early.
+         *  Options are not yet supported.
+         *  pl011,<addr>
+         *  pl011,mmio32,<addr>
+         */
+        serial_for_each_args(arg, options)
+        {
+            if (!rt_strcmp(arg, "pl011") || !rt_strcmp(arg, "mmio32"))
+            {
+                continue;
+            }
+            if (!con->mmio)
+            {
+                con->mmio = (rt_ubase_t)serial_base_from_args(arg);
+                break;
+            }
+        }
+    }
+
+    if (!con->size)
+    {
+        con->size = 0x1000;
+    }
+
+    if (con->mmio)
+    {
+        pl011.base = rt_ioremap_early((void *)con->mmio, con->size);
+    }
+
+    if (pl011.base)
+    {
+        con->console_putc = (typeof(con->console_putc))&pl011_uart_putc;
+        con->console_kick = pl011_early_kick;
+        con->data = &pl011.parent;
+        pl011.parent.config = (typeof(pl011.parent.config))RT_SERIAL_CONFIG_DEFAULT;
+    }
+    else
+    {
+        err = -RT_ERROR;
+    }
+
+    return err;
+}
+RT_FDT_EARLYCON_EXPORT(pl011, "pl011", "arm,pl011", pl011_early_setup);
+
+static void pl011_free(struct pl011 *pl011)
+{
+    if (pl011->base)
+    {
+        rt_iounmap(pl011->base);
+    }
+
+    /* if (!rt_is_err_or_null(pl011->clk))*/
+    /* {*/
+    /*     rt_clk_disable(pl011->clk);*/
+    /*     rt_clk_put(pl011->clk);*/
+    /* }*/
+
+    /* if (!rt_is_err_or_null(pl011->pclk))*/
+    /* {*/
+    /*     rt_clk_disable_unprepare(pl011->pclk);*/
+    /*     rt_clk_put(pl011->pclk);*/
+    /* }*/
+
+    rt_free(pl011);
+}
+
+static rt_err_t pl011_probe(struct rt_platform_device *pdev)
+{
+    rt_err_t err;
+    const char *name;
+    char isr_name[RT_NAME_MAX];
+    struct rt_device *dev = &pdev->parent;
+    struct pl011 *pl011 = rt_calloc(1, sizeof(*pl011));
+    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
+
+    if (!pl011)
+    {
+        return -RT_ENOMEM;
+    }
+
+    pl011->base = rt_dm_dev_iomap(dev, 0);
+
+    if (!pl011->base)
+    {
+        err = -RT_EIO;
+
+        goto _fail;
+    }
+
+    pl011->irq = rt_dm_dev_get_irq(dev, 0);
+
+    if (pl011->irq < 0)
+    {
+        err = pl011->irq;
+
+        goto _fail;
+    }
+
+    /* pl011->clk = rt_clk_get_by_index(dev, 0);*/
+
+    /* if (rt_is_err(pl011->clk))*/
+    /* {*/
+    /*     err = rt_ptr_err(pl011->clk);*/
+
+    /*     goto _fail;*/
+    /* }*/
+
+    /* pl011->pclk = rt_clk_get_by_name(dev, "apb_pclk");*/
+
+    /* if (rt_is_err(pl011->pclk))*/
+    /* {*/
+    /*     err = rt_ptr_err(pl011->pclk);*/
+
+    /*     goto _fail;*/
+    /* }*/
+
+    /* if ((err = rt_clk_prepare_enable(pl011->pclk)))*/
+    /* {*/
+    /*     goto _fail;*/
+    /* }*/
+
+    rt_dm_dev_bind_fwdata(&pl011->parent.parent, dev->ofw_node, &pl011->parent);
+
+    /* rt_clk_enable(pl011->clk);*/
+    /* pl011->freq = rt_clk_get_rate(pl011->clk);*/
+
+    dev->user_data = pl011;
+
+    pl011->parent.ops = &pl011_uart_ops;
+    pl011->parent.config = config;
+
+    rt_spin_lock_init(&pl011->spinlock);
+
+    serial_dev_set_name(&pl011->parent);
+    name = rt_dm_dev_get_name(&pl011->parent.parent);
+
+    rt_hw_serial_register(&pl011->parent, name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, pl011);
+    rt_snprintf(isr_name, RT_NAME_MAX, "%s-pl011", name);
+    rt_hw_interrupt_install(pl011->irq, pl011_isr, pl011, isr_name);
+
+    return RT_EOK;
+
+_fail:
+    pl011_free(pl011);
+
+    return err;
+}
+
+static rt_err_t pl011_remove(struct rt_platform_device *pdev)
+{
+    struct rt_device *dev = &pdev->parent;
+    struct pl011 *pl011 = dev->user_data;
+
+    rt_dm_dev_unbind_fwdata(dev, RT_NULL);
+
+    rt_hw_interrupt_mask(pl011->irq);
+    rt_pic_detach_irq(pl011->irq, pl011);
+
+    rt_device_unregister(&pl011->parent.parent);
+
+    pl011_free(pl011);
+
+    return RT_EOK;
+}
+
+static const struct rt_ofw_node_id pl011_ofw_ids[] =
+{
+    { .type = "ttyAMA", .compatible = "arm,pl011" },
+    { .type = "ttyAMA", .compatible = "arm,pl011-axi" },
+    { /* sentinel */ }
+};
+
+static struct rt_platform_driver pl011_driver =
+{
+    .name = "serial-pl011",
+    .ids = pl011_ofw_ids,
+
+    .probe = pl011_probe,
+    .remove = pl011_remove,
+};
+
+static int pl011_drv_register(void)
+{
+    rt_platform_driver_register(&pl011_driver);
+
+    return 0;
+}
+INIT_DRIVER_EARLY_EXPORT(pl011_drv_register);

+ 108 - 0
bsp/raspberry-pi/raspi-dm2.0/drivers/drv_uart.h

@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2006-2024 RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author         Notes
+ * 2020-04-16     bigmagic       first version
+ */
+
+#ifndef DRV_UART_H__
+#define DRV_UART_H__
+
+/* register's bit*/
+#define PL011_FR_RI          (1 << 8)
+#define PL011_FR_TXFE        (1 << 7)
+#define PL011_FR_RXFF        (1 << 6)
+#define PL011_FR_TXFF        (1 << 5)
+#define PL011_FR_RXFE        (1 << 4)
+#define PL011_FR_BUSY        (1 << 3)
+#define PL011_FR_DCD         (1 << 2)
+#define PL011_FR_DSR         (1 << 1)
+#define PL011_FR_CTS         (1 << 0)
+
+#define PL011_LCRH_SPS       (1 << 7)
+#define PL011_LCRH_WLEN_8    (3 << 5)
+#define PL011_LCRH_WLEN_7    (2 << 5)
+#define PL011_LCRH_WLEN_6    (1 << 5)
+#define PL011_LCRH_WLEN_5    (0 << 5)
+#define PL011_LCRH_FEN       (1 << 4)
+#define PL011_LCRH_STP2      (1 << 3)
+#define PL011_LCRH_EPS       (1 << 2)
+#define PL011_LCRH_PEN       (1 << 1)
+#define PL011_LCRH_BRK       (1 << 0)
+
+#define PL011_CR_CTSEN       (1 << 15)
+#define PL011_CR_RTSEN       (1 << 14)
+#define PL011_CR_RTS         (1 << 11)
+#define PL011_CR_DTR         (1 << 10)
+#define PL011_CR_RXE         (1 << 9)
+#define PL011_CR_TXE         (1 << 8)
+#define PL011_CR_LBE         (1 << 7)
+#define PL011_CR_SIRLP       (1 << 2)
+#define PL011_CR_SIREN       (1 << 1)
+#define PL011_CR_UARTEN      (1 << 0)
+
+#define PL011_IMSC_TXIM      (1 << 5)
+#define PL011_IMSC_RXIM      (1 << 4)
+
+#define PL011_INTERRUPT_OVERRUN_ERROR   (1 << 10)
+#define PL011_INTERRUPT_BREAK_ERROR     (1 << 9)
+#define PL011_INTERRUPT_PARITY_ERROR    (1 << 8)
+#define PL011_INTERRUPT_FRAMING_ERROR   (1 << 7)
+#define PL011_INTERRUPT_RECEIVE_TIMEOUT (1 << 6)
+#define PL011_INTERRUPT_TRANSMIT        (1 << 5)
+#define PL011_INTERRUPT_RECEIVE         (1 << 4)
+#define PL011_INTERRUPT_nUARTCTS        (1 << 1)
+
+#define PL011_REG_DR(BASE)              HWREG32(BASE + 0x00)
+#define PL011_REG_RSRECR(BASE)          HWREG32(BASE + 0x04)
+#define PL011_REG_RESERVED0(BASE)       HWREG32(BASE + 0x08)
+#define PL011_REG_FR(BASE)              HWREG32(BASE + 0x18)
+#define PL011_REG_RESERVED1(BASE)       HWREG32(BASE + 0x1C)
+#define PL011_REG_ILPR(BASE)            HWREG32(BASE + 0x20)
+#define PL011_REG_IBRD(BASE)            HWREG32(BASE + 0x24)
+#define PL011_REG_FBRD(BASE)            HWREG32(BASE + 0x28)
+#define PL011_REG_LCRH(BASE)            HWREG32(BASE + 0x2C)
+#define PL011_REG_CR(BASE)              HWREG32(BASE + 0x30)
+#define PL011_REG_IFLS(BASE)            HWREG32(BASE + 0x34)
+#define PL011_REG_IMSC(BASE)            HWREG32(BASE + 0x38)
+#define PL011_REG_RIS(BASE)             HWREG32(BASE + 0x3C)
+#define PL011_REG_MIS(BASE)             HWREG32(BASE + 0x40)
+#define PL011_REG_ICR(BASE)             HWREG32(BASE + 0x44)
+#define PL011_REG_DMACR(BASE)           HWREG32(BASE + 0x48)
+#define PL011_REG_RESERVED2(BASE)       HWREG32(BASE + 0x4C)
+#define PL011_REG_ITCR(BASE)            HWREG32(BASE + 0x80)
+#define PL011_REG_ITIP(BASE)            HWREG32(BASE + 0x84)
+#define PL011_REG_ITOP(BASE)            HWREG32(BASE + 0x88)
+#define PL011_REG_TDR(BASE)             HWREG32(BASE + 0x8C)
+
+/*
+ *  Auxiliary
+ */
+#define AUX_IRQ(BASE)             HWREG32(BASE + 0x00)   /* Auxiliary Interrupt status 3 */
+#define AUX_ENABLES(BASE)         HWREG32(BASE + 0x04)   /* Auxiliary enables 3bit */
+#define AUX_MU_IO_REG(BASE)       HWREG32(BASE + 0x40)   /* Mini Uart I/O Data 8bit */
+#define AUX_MU_IER_REG(BASE)      HWREG32(BASE + 0x44)   /* Mini Uart Interrupt Enable 8bit */
+#define AUX_MU_IIR_REG(BASE)      HWREG32(BASE + 0x48)   /* Mini Uart Interrupt Identify 8bit */
+#define AUX_MU_LCR_REG(BASE)      HWREG32(BASE + 0x4C)   /* Mini Uart Line Control 8bit */
+#define AUX_MU_MCR_REG(BASE)      HWREG32(BASE + 0x50)   /* Mini Uart Modem Control 8bit */
+#define AUX_MU_LSR_REG(BASE)      HWREG32(BASE + 0x54)   /* Mini Uart Line Status 8bit */
+#define AUX_MU_MSR_REG(BASE)      HWREG32(BASE + 0x58)   /* Mini Uart Modem Status 8bit */
+#define AUX_MU_SCRATCH(BASE)      HWREG32(BASE + 0x5C)   /* Mini Uart Scratch 8bit */
+#define AUX_MU_CNTL_REG(BASE)     HWREG32(BASE + 0x60)   /* Mini Uart Extra Control 8bit */
+#define AUX_MU_STAT_REG(BASE)     HWREG32(BASE + 0x64)   /* Mini Uart Extra Status 32bit */
+#define AUX_MU_BAUD_REG(BASE)     HWREG32(BASE + 0x68)   /* Mini Uart Baudrate 16bit */
+#define AUX_SPI0_CNTL0_REG(BASE)  HWREG32(BASE + 0x80)   /* SPI 1 Control register 0 32bit */
+#define AUX_SPI0_CNTL1_REG(BASE)  HWREG32(BASE + 0x84)   /* SPI 1 Control register 1 8bit */
+#define AUX_SPI0_STAT_REG(BASE)   HWREG32(BASE + 0x88)   /* SPI 1 Status 32bit */
+#define AUX_SPI0_IO_REG(BASE)     HWREG32(BASE + 0x90)   /* SPI 1 Data 32bit */
+#define AUX_SPI0_PEEK_REG(BASE)   HWREG32(BASE + 0x94)   /* SPI 1 Peek 16bit */
+#define AUX_SPI1_CNTL0_REG(BASE)  HWREG32(BASE + 0xC0)   /* SPI 2 Control register 0 32bit */
+#define AUX_SPI1_CNTL1_REG(BASE)  HWREG32(BASE + 0xC4)   /* SPI 2 Control register 1 8bit */
+
+int rt_hw_uart_init(void);
+void rt_hw_earlycon_ioremap_early(void);
+
+#endif /* DRV_UART_H__ */

+ 3 - 0
bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/Kconfig

@@ -0,0 +1,3 @@
+menuconfig RT_USING_SDHCI
+    bool "Using sdhci for sd/mmc drivers"
+    default n

+ 18 - 0
bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/SConscript

@@ -0,0 +1,18 @@
+from building import *
+
+group = []
+
+if not GetDepend(['RT_USING_SDHCI']):
+    Return('group')
+
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/include']
+
+src = []
+src += Glob('*.c')
+src += Glob('src/*.c')
+src += Glob('sdhci-platform/*.c')
+
+group = DefineGroup('sdhci-drivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')

+ 74 - 0
bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci-platform.h

@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2006-2024 RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author        Notes
+ * 2024-08-16     zhujiale     first version
+ */
+
+#ifndef _DRIVERS_MMC_SDHCI_PLTFM_H
+#define _DRIVERS_MMC_SDHCI_PLTFM_H
+#include <rtthread.h>
+#include <drivers/core/dm.h>
+#include <drivers/ofw.h>
+#include <drivers/platform.h>
+#include <drivers/clk.h>
+#include "sdhci.h"
+
+struct sdhci_pltfm_data
+{
+    const struct sdhci_ops *ops;
+    unsigned int            quirks;
+    unsigned int            quirks2;
+};
+
+struct sdhci_pltfm_host
+{
+    struct rt_clk *clk;
+
+    /* migrate from sdhci_of_host */
+    unsigned int clock;
+    rt_uint64_t  xfer_mode_shadow;
+
+    unsigned long private[];
+};
+
+void sdhci_get_property(struct rt_platform_device *pdev);
+
+static inline void sdhci_get_of_property(struct rt_platform_device *pdev)
+{
+    return sdhci_get_property(pdev);
+}
+
+
+extern struct sdhci_host *sdhci_pltfm_init(struct rt_platform_device     *pdev,
+                                           const struct sdhci_pltfm_data *pdata,
+                                           size_t                         priv_size);
+extern void               sdhci_pltfm_free(struct rt_platform_device *pdev);
+
+extern int  sdhci_pltfm_init_and_add_host(struct rt_platform_device     *pdev,
+                                          const struct sdhci_pltfm_data *pdata,
+                                          size_t                         priv_size);
+extern void sdhci_pltfm_remove(struct rt_platform_device *pdev);
+
+extern unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host);
+
+static inline void *sdhci_pltfm_priv(struct sdhci_pltfm_host *host)
+{
+    return host->private;
+}
+
+extern const struct dev_pm_ops sdhci_pltfm_pmops;
+static inline int              sdhci_pltfm_suspend(struct rt_device *dev)
+{
+    return 0;
+}
+static inline int sdhci_pltfm_resume(struct rt_device *dev)
+{
+    return 0;
+}
+
+
+#endif

+ 815 - 0
bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci.h

@@ -0,0 +1,815 @@
+/*
+ * Copyright (c) 2006-2024 RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author        Notes
+ * 2024-08-16     zhujiale     first version
+ */
+#ifndef __SDHCI_HW_H
+#define __SDHCI_HW_H
+
+#include "sdhci_host.h"
+#include "sdhci_misc.h"
+#include "sdhci_dma.h"
+#include "sdhci-platform.h"
+#include <drivers/mmcsd_cmd.h>
+#include <drivers/mmcsd_host.h>
+#include <rtdevice.h>
+/*
+ * Controller registers
+ */
+#define lower_32_bits(n) ((rt_uint32_t)((n) & 0xffffffff))
+#define upper_32_bits(n) ((rt_uint32_t)(((n) >> 16) >> 16))
+
+#define MAX_TUNING_LOOP 40
+
+#define SDHCI_DMA_ADDRESS   0x00
+#define SDHCI_ARGUMENT2     SDHCI_DMA_ADDRESS
+#define SDHCI_32BIT_BLK_CNT SDHCI_DMA_ADDRESS
+
+#define SDHCI_BLOCK_SIZE             0x04
+#define SDHCI_MAKE_BLKSZ(dma, blksz) (((dma & 0x7) << 12) | (blksz & 0xFFF))
+
+#define SDHCI_BLOCK_COUNT 0x06
+
+#define SDHCI_ARGUMENT 0x08
+
+#define SDHCI_TRANSFER_MODE   0x0C
+#define SDHCI_TRNS_DMA        0x01
+#define SDHCI_TRNS_BLK_CNT_EN 0x02
+#define SDHCI_TRNS_AUTO_CMD12 0x04
+#define SDHCI_TRNS_AUTO_CMD23 0x08
+#define SDHCI_TRNS_AUTO_SEL   0x0C
+#define SDHCI_TRNS_READ       0x10
+#define SDHCI_TRNS_MULTI      0x20
+
+#define SDHCI_COMMAND       0x0E
+#define SDHCI_CMD_RESP_MASK 0x03
+#define SDHCI_CMD_CRC       0x08
+#define SDHCI_CMD_INDEX     0x10
+#define SDHCI_CMD_DATA      0x20
+#define SDHCI_CMD_ABORTCMD  0xC0
+
+#define SDHCI_CMD_RESP_NONE       0x00
+#define SDHCI_CMD_RESP_LONG       0x01
+#define SDHCI_CMD_RESP_SHORT      0x02
+#define SDHCI_CMD_RESP_SHORT_BUSY 0x03
+
+#define SDHCI_MAKE_CMD(c, f) (((c & 0xff) << 8) | (f & 0xff))
+#define SDHCI_GET_CMD(c)     ((c >> 8) & 0x3f)
+
+#define SDHCI_RESPONSE 0x10
+
+#define SDHCI_BUFFER 0x20
+
+#define SDHCI_PRESENT_STATE   0x24
+#define SDHCI_CMD_INHIBIT     0x00000001
+#define SDHCI_DATA_INHIBIT    0x00000002
+#define SDHCI_DOING_WRITE     0x00000100
+#define SDHCI_DOING_READ      0x00000200
+#define SDHCI_SPACE_AVAILABLE 0x00000400
+#define SDHCI_DATA_AVAILABLE  0x00000800
+#define SDHCI_CARD_PRESENT    0x00010000
+#define SDHCI_CARD_PRES_SHIFT 16
+#define SDHCI_CD_STABLE       0x00020000
+#define SDHCI_CD_LVL          0x00040000
+#define SDHCI_CD_LVL_SHIFT    18
+#define SDHCI_WRITE_PROTECT   0x00080000
+#define SDHCI_DATA_LVL_MASK   0x00F00000
+#define SDHCI_DATA_LVL_SHIFT  20
+#define SDHCI_DATA_0_LVL_MASK 0x00100000
+#define SDHCI_CMD_LVL         0x01000000
+
+#define SDHCI_HOST_CONTROL    0x28
+#define SDHCI_CTRL_LED        0x01
+#define SDHCI_CTRL_4BITBUS    0x02
+#define SDHCI_CTRL_HISPD      0x04
+#define SDHCI_CTRL_DMA_MASK   0x18
+#define SDHCI_CTRL_SDMA       0x00
+#define SDHCI_CTRL_ADMA1      0x08
+#define SDHCI_CTRL_ADMA32     0x10
+#define SDHCI_CTRL_ADMA64     0x18
+#define SDHCI_CTRL_ADMA3      0x18
+#define SDHCI_CTRL_8BITBUS    0x20
+#define SDHCI_CTRL_CDTEST_INS 0x40
+#define SDHCI_CTRL_CDTEST_EN  0x80
+
+#define SDHCI_POWER_CONTROL 0x29
+#define SDHCI_POWER_ON      0x01
+#define SDHCI_POWER_180     0x0A
+#define SDHCI_POWER_300     0x0C
+#define SDHCI_POWER_330     0x0E
+/*
+ * VDD2 - UHS2 or PCIe/NVMe
+ * VDD2 power on/off and voltage select
+ */
+#define SDHCI_VDD2_POWER_ON  0x10
+#define SDHCI_VDD2_POWER_120 0x80
+#define SDHCI_VDD2_POWER_180 0xA0
+
+#define SDHCI_BLOCK_GAP_CONTROL 0x2A
+
+#define SDHCI_WAKE_UP_CONTROL 0x2B
+#define SDHCI_WAKE_ON_INT     0x01
+#define SDHCI_WAKE_ON_INSERT  0x02
+#define SDHCI_WAKE_ON_REMOVE  0x04
+
+#define SDHCI_CLOCK_CONTROL    0x2C
+#define SDHCI_DIVIDER_SHIFT    8
+#define SDHCI_DIVIDER_HI_SHIFT 6
+#define SDHCI_DIV_MASK         0xFF
+#define SDHCI_DIV_MASK_LEN     8
+#define SDHCI_DIV_HI_MASK      0x300
+#define SDHCI_PROG_CLOCK_MODE  0x0020
+#define SDHCI_CLOCK_CARD_EN    0x0004
+#define SDHCI_CLOCK_PLL_EN     0x0008
+#define SDHCI_CLOCK_INT_STABLE 0x0002
+#define SDHCI_CLOCK_INT_EN     0x0001
+
+#define SDHCI_TIMEOUT_CONTROL 0x2E
+
+#define SDHCI_SOFTWARE_RESET 0x2F
+#define SDHCI_RESET_ALL      0x01
+#define SDHCI_RESET_CMD      0x02
+#define SDHCI_RESET_DATA     0x04
+
+#define SDHCI_INT_STATUS       0x30
+#define SDHCI_INT_ENABLE       0x34
+#define SDHCI_SIGNAL_ENABLE    0x38
+#define SDHCI_INT_RESPONSE     0x00000001
+#define SDHCI_INT_DATA_END     0x00000002
+#define SDHCI_INT_BLK_GAP      0x00000004
+#define SDHCI_INT_DMA_END      0x00000008
+#define SDHCI_INT_SPACE_AVAIL  0x00000010
+#define SDHCI_INT_DATA_AVAIL   0x00000020
+#define SDHCI_INT_CARD_INSERT  0x00000040
+#define SDHCI_INT_CARD_REMOVE  0x00000080
+#define SDHCI_INT_CARD_INT     0x00000100
+#define SDHCI_INT_RETUNE       0x00001000
+#define SDHCI_INT_CQE          0x00004000
+#define SDHCI_INT_ERROR        0x00008000
+#define SDHCI_INT_TIMEOUT      0x00010000
+#define SDHCI_INT_CRC          0x00020000
+#define SDHCI_INT_END_BIT      0x00040000
+#define SDHCI_INT_INDEX        0x00080000
+#define SDHCI_INT_DATA_TIMEOUT 0x00100000
+#define SDHCI_INT_DATA_CRC     0x00200000
+#define SDHCI_INT_DATA_END_BIT 0x00400000
+#define SDHCI_INT_BUS_POWER    0x00800000
+#define SDHCI_INT_AUTO_CMD_ERR 0x01000000
+#define SDHCI_INT_ADMA_ERROR   0x02000000
+
+#define SDHCI_INT_NORMAL_MASK 0x00007FFF
+#define SDHCI_INT_ERROR_MASK  0xFFFF8000
+
+#define SDHCI_INT_CMD_MASK  (SDHCI_INT_RESPONSE | SDHCI_INT_TIMEOUT | SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX | SDHCI_INT_AUTO_CMD_ERR)
+#define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT | SDHCI_INT_ADMA_ERROR | SDHCI_INT_BLK_GAP)
+#define SDHCI_INT_ALL_MASK  ((unsigned int)-1)
+
+#define SDHCI_CQE_INT_ERR_MASK ( \
+    SDHCI_INT_ADMA_ERROR | SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT)
+
+#define SDHCI_CQE_INT_MASK (SDHCI_CQE_INT_ERR_MASK | SDHCI_INT_CQE)
+
+#define SDHCI_AUTO_CMD_STATUS  0x3C
+#define SDHCI_AUTO_CMD_TIMEOUT 0x00000002
+#define SDHCI_AUTO_CMD_CRC     0x00000004
+#define SDHCI_AUTO_CMD_END_BIT 0x00000008
+#define SDHCI_AUTO_CMD_INDEX   0x00000010
+
+#define SDHCI_HOST_CONTROL2          0x3E
+#define SDHCI_CTRL_UHS_MASK          0x0007
+#define SDHCI_CTRL_UHS_SDR12         0x0000
+#define SDHCI_CTRL_UHS_SDR25         0x0001
+#define SDHCI_CTRL_UHS_SDR50         0x0002
+#define SDHCI_CTRL_UHS_SDR104        0x0003
+#define SDHCI_CTRL_UHS_DDR50         0x0004
+#define SDHCI_CTRL_HS400             0x0005 /* Non-standard */
+#define SDHCI_CTRL_VDD_180           0x0008
+#define SDHCI_CTRL_DRV_TYPE_MASK     0x0030
+#define SDHCI_CTRL_DRV_TYPE_B        0x0000
+#define SDHCI_CTRL_DRV_TYPE_A        0x0010
+#define SDHCI_CTRL_DRV_TYPE_C        0x0020
+#define SDHCI_CTRL_DRV_TYPE_D        0x0030
+#define SDHCI_CTRL_EXEC_TUNING       0x0040
+#define SDHCI_CTRL_TUNED_CLK         0x0080
+#define SDHCI_CMD23_ENABLE           0x0800
+#define SDHCI_CTRL_V4_MODE           0x1000
+#define SDHCI_CTRL_64BIT_ADDR        0x2000
+#define SDHCI_CTRL_PRESET_VAL_ENABLE 0x8000
+
+#define SDHCI_CAPABILITIES       0x40
+#define SDHCI_TIMEOUT_CLK_MASK   RT_GENMASK(5, 0)
+#define SDHCI_TIMEOUT_CLK_SHIFT  0
+#define SDHCI_TIMEOUT_CLK_UNIT   0x00000080
+#define SDHCI_CLOCK_BASE_MASK    RT_GENMASK(13, 8)
+#define SDHCI_CLOCK_BASE_SHIFT   8
+#define SDHCI_CLOCK_V3_BASE_MASK RT_GENMASK(15, 8)
+#define SDHCI_MAX_BLOCK_MASK     0x00030000
+#define SDHCI_MAX_BLOCK_SHIFT    16
+#define SDHCI_CAN_DO_8BIT        0x00040000
+#define SDHCI_CAN_DO_ADMA2       0x00080000
+#define SDHCI_CAN_DO_ADMA1       0x00100000
+#define SDHCI_CAN_DO_HISPD       0x00200000
+#define SDHCI_CAN_DO_SDMA        0x00400000
+#define SDHCI_CAN_DO_SUSPEND     0x00800000
+#define SDHCI_CAN_VDD_330        0x01000000
+#define SDHCI_CAN_VDD_300        0x02000000
+#define SDHCI_CAN_VDD_180        0x04000000
+#define SDHCI_CAN_64BIT_V4       0x08000000
+#define SDHCI_CAN_64BIT          0x10000000
+
+#define SDHCI_CAPABILITIES_1            0x44
+#define SDHCI_SUPPORT_SDR50             0x00000001
+#define SDHCI_SUPPORT_SDR104            0x00000002
+#define SDHCI_SUPPORT_DDR50             0x00000004
+#define SDHCI_DRIVER_TYPE_A             0x00000010
+#define SDHCI_DRIVER_TYPE_C             0x00000020
+#define SDHCI_DRIVER_TYPE_D             0x00000040
+#define SDHCI_RETUNING_TIMER_COUNT_MASK RT_GENMASK(11, 8)
+#define SDHCI_USE_SDR50_TUNING          0x00002000
+#define SDHCI_RETUNING_MODE_MASK        RT_GENMASK(15, 14)
+#define SDHCI_CLOCK_MUL_MASK            RT_GENMASK(23, 16)
+#define SDHCI_CAN_DO_ADMA3              0x08000000
+#define SDHCI_SUPPORT_HS400             0x80000000 /* Non-standard */
+
+#define SDHCI_MAX_CURRENT            0x48
+#define SDHCI_MAX_CURRENT_LIMIT      RT_GENMASK(7, 0)
+#define SDHCI_MAX_CURRENT_330_MASK   RT_GENMASK(7, 0)
+#define SDHCI_MAX_CURRENT_300_MASK   RT_GENMASK(15, 8)
+#define SDHCI_MAX_CURRENT_180_MASK   RT_GENMASK(23, 16)
+#define SDHCI_MAX_CURRENT_MULTIPLIER 4
+
+/* 4C-4F reserved for more max current */
+
+#define SDHCI_SET_ACMD12_ERROR 0x50
+#define SDHCI_SET_INT_ERROR    0x52
+
+#define SDHCI_ADMA_ERROR 0x54
+
+/* 55-57 reserved */
+
+#define SDHCI_ADMA_ADDRESS    0x58
+#define SDHCI_ADMA_ADDRESS_HI 0x5C
+
+/* 60-FB reserved */
+
+#define SDHCI_PRESET_FOR_HIGH_SPEED 0x64
+#define SDHCI_PRESET_FOR_SDR12      0x66
+#define SDHCI_PRESET_FOR_SDR25      0x68
+#define SDHCI_PRESET_FOR_SDR50      0x6A
+#define SDHCI_PRESET_FOR_SDR104     0x6C
+#define SDHCI_PRESET_FOR_DDR50      0x6E
+#define SDHCI_PRESET_FOR_HS400      0x74 /* Non-standard */
+#define SDHCI_PRESET_DRV_MASK       RT_GENMASK(15, 14)
+#define BIT(nr)                     ((1) << (nr))
+
+#define SDHCI_PRESET_CLKGEN_SEL      BIT(10)
+#define SDHCI_PRESET_SDCLK_FREQ_MASK RT_GENMASK(9, 0)
+
+#define SDHCI_SLOT_INT_STATUS 0xFC
+
+#define SDHCI_HOST_VERSION     0xFE
+#define SDHCI_VENDOR_VER_MASK  0xFF00
+#define SDHCI_VENDOR_VER_SHIFT 8
+#define SDHCI_SPEC_VER_MASK    0x00FF
+#define SDHCI_SPEC_VER_SHIFT   0
+#define SDHCI_SPEC_100         0
+#define SDHCI_SPEC_200         1
+#define SDHCI_SPEC_300         2
+#define SDHCI_SPEC_400         3
+#define SDHCI_SPEC_410         4
+#define SDHCI_SPEC_420         5
+
+/*
+ * End of controller registers.
+ */
+
+#define SDHCI_MAX_DIV_SPEC_200 256
+#define SDHCI_MAX_DIV_SPEC_300 2046
+
+/*
+ * Host SDMA buffer boundary. Valid values from 4K to 512K in powers of 2.
+ */
+#define SDHCI_DEFAULT_BOUNDARY_SIZE (512 * 1024)
+#define ilog2(v)                    __rt_ffs(v)
+#define SDHCI_DEFAULT_BOUNDARY_ARG  (ilog2(SDHCI_DEFAULT_BOUNDARY_SIZE) - 12)
+
+/* ADMA2 32-bit DMA descriptor size */
+#define SDHCI_ADMA2_32_DESC_SZ 8
+
+/* ADMA2 32-bit descriptor */
+struct sdhci_adma2_32_desc
+{
+    rt_uint16_t cmd;
+    rt_uint16_t len;
+    rt_uint16_t addr;
+} rt_align(4);
+/* ADMA2 data alignment */
+#define SDHCI_ADMA2_ALIGN 4
+#define SDHCI_ADMA2_MASK  (SDHCI_ADMA2_ALIGN - 1)
+
+/*
+ * ADMA2 descriptor alignment.  Some controllers (e.g. Intel) require 8 byte
+ * alignment for the descriptor table even in 32-bit DMA mode.  Memory
+ * allocation is at least 8 byte aligned anyway, so just stipulate 8 always.
+ */
+#define SDHCI_ADMA2_DESC_ALIGN 8
+
+/*
+ * ADMA2 64-bit DMA descriptor size
+ * According to SD Host Controller spec v4.10, there are two kinds of
+ * descriptors for 64-bit addressing mode: 96-bit Descriptor and 128-bit
+ * Descriptor, if Host Version 4 Enable is set in the Host Control 2
+ * register, 128-bit Descriptor will be selected.
+ */
+#define SDHCI_ADMA2_64_DESC_SZ(host) ((host)->v4_mode ? 16 : 12)
+
+/*
+ * ADMA2 64-bit descriptor. Note 12-byte descriptor can't always be 8-byte
+ * aligned.
+ */
+struct sdhci_adma2_64_desc
+{
+    rt_uint16_t cmd;
+    rt_uint16_t len;
+    rt_uint16_t addr_lo;
+    rt_uint16_t addr_hi;
+};
+
+#define ADMA2_TRAN_VALID    0x21
+#define ADMA2_NOP_END_VALID 0x3
+#define ADMA2_END           0x2
+
+/*
+ * Maximum segments assuming a 512KiB maximum requisition size and a minimum
+ * 4KiB page size. Note this also allows enough for multiple descriptors in
+ * case of PAGE_SIZE >= 64KiB.
+ */
+#define SDHCI_MAX_SEGS 128
+
+/* Allow for a command request and a data request at the same time */
+#define SDHCI_MAX_MRQS 2
+
+/*
+ * 48bit command and 136 bit response in 100KHz clock could take upto 2.48ms.
+ * However since the start time of the command, the time between
+ * command and response, and the time between response and start of data is
+ * not known, set the command transfer time to 10ms.
+ */
+#define MMC_CMD_TRANSFER_TIME (10 * 1000000L) /* max 10 ms */
+
+
+enum sdhci_cookie
+{
+    COOKIE_UNMAPPED,
+    COOKIE_PRE_MAPPED, /* mapped by sdhci_pre_req() */
+    COOKIE_MAPPED,     /* mapped by sdhci_prepare_data() */
+};
+
+struct sdhci_host
+{
+    /* Data set by hardware interface driver */
+    const char *hw_name; /* Hardware bus name */
+
+    unsigned int quirks; /* Deviations from spec. */
+
+    void *data_buf;
+/* Controller doesn't honor resets unless we touch the clock register */
+#define SDHCI_QUIRK_CLOCK_BEFORE_RESET (1 << 0)
+/* Controller has bad caps bits, but really supports DMA */
+#define SDHCI_QUIRK_FORCE_DMA (1 << 1)
+/* Controller doesn't like to be reset when there is no card inserted. */
+#define SDHCI_QUIRK_NO_CARD_NO_RESET (1 << 2)
+/* Controller doesn't like clearing the power reg before a change */
+#define SDHCI_QUIRK_SINGLE_POWER_WRITE (1 << 3)
+/* Controller has an unusable DMA engine */
+#define SDHCI_QUIRK_BROKEN_DMA (1 << 5)
+/* Controller has an unusable ADMA engine */
+#define SDHCI_QUIRK_BROKEN_ADMA (1 << 6)
+/* Controller can only DMA from 32-bit aligned addresses */
+#define SDHCI_QUIRK_32BIT_DMA_ADDR (1 << 7)
+/* Controller can only DMA chunk sizes that are a multiple of 32 bits */
+#define SDHCI_QUIRK_32BIT_DMA_SIZE (1 << 8)
+/* Controller can only ADMA chunks that are a multiple of 32 bits */
+#define SDHCI_QUIRK_32BIT_ADMA_SIZE (1 << 9)
+/* Controller needs to be reset after each request to stay stable */
+#define SDHCI_QUIRK_RESET_AFTER_REQUEST (1 << 10)
+/* Controller needs voltage and power writes to happen separately */
+#define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER (1 << 11)
+/* Controller provides an incorrect timeout value for transfers */
+#define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1 << 12)
+/* Controller has an issue with buffer bits for small transfers */
+#define SDHCI_QUIRK_BROKEN_SMALL_PIO (1 << 13)
+/* Controller does not provide transfer-complete interrupt when not busy */
+#define SDHCI_QUIRK_NO_BUSY_IRQ (1 << 14)
+/* Controller has unreliable card detection */
+#define SDHCI_QUIRK_BROKEN_CARD_DETECTION (1 << 15)
+/* Controller reports inverted write-protect state */
+#define SDHCI_QUIRK_INVERTED_WRITE_PROTECT (1 << 16)
+/* Controller has unusable command queue engine */
+#define SDHCI_QUIRK_BROKEN_CQE (1 << 17)
+/* Controller does not like fast PIO transfers */
+#define SDHCI_QUIRK_PIO_NEEDS_DELAY (1 << 18)
+/* Controller does not have a LED */
+#define SDHCI_QUIRK_NO_LED (1 << 19)
+/* Controller has to be forced to use block size of 2048 bytes */
+#define SDHCI_QUIRK_FORCE_BLK_SZ_2048 (1 << 20)
+/* Controller cannot do multi-block transfers */
+#define SDHCI_QUIRK_NO_MULTIBLOCK (1 << 21)
+/* Controller can only handle 1-bit data transfers */
+#define SDHCI_QUIRK_FORCE_1_BIT_DATA (1 << 22)
+/* Controller needs 10ms delay between applying power and clock */
+#define SDHCI_QUIRK_DELAY_AFTER_POWER (1 << 23)
+/* Controller uses SDCLK instead of TMCLK for data timeouts */
+#define SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK (1 << 24)
+/* Controller reports wrong base clock capability */
+#define SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN (1 << 25)
+/* Controller cannot support End Attribute in NOP ADMA descriptor */
+#define SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC (1 << 26)
+/* Controller uses Auto CMD12 command to stop the transfer */
+#define SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12 (1 << 28)
+/* Controller doesn't have HISPD bit field in HI-SPEED SD card */
+#define SDHCI_QUIRK_NO_HISPD_BIT (1 << 29)
+/* Controller treats ADMA descriptors with length 0000h incorrectly */
+#define SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC (1 << 30)
+/* The read-only detection via SDHCI_PRESENT_STATE register is unstable */
+#define SDHCI_QUIRK_UNSTABLE_RO_DETECT (1 << 31)
+
+    unsigned int quirks2; /* More deviations from spec. */
+
+#define SDHCI_QUIRK2_HOST_OFF_CARD_ON (1 << 0)
+#define SDHCI_QUIRK2_HOST_NO_CMD23    (1 << 1)
+/* The system physically doesn't support 1.8v, even if the host does */
+#define SDHCI_QUIRK2_NO_1_8_V             (1 << 2)
+#define SDHCI_QUIRK2_PRESET_VALUE_BROKEN  (1 << 3)
+#define SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON (1 << 4)
+/* Controller has a non-standard host control register */
+#define SDHCI_QUIRK2_BROKEN_HOST_CONTROL (1 << 5)
+/* Controller does not support HS200 */
+#define SDHCI_QUIRK2_BROKEN_HS200 (1 << 6)
+/* Controller does not support DDR50 */
+#define SDHCI_QUIRK2_BROKEN_DDR50 (1 << 7)
+/* Stop command (CMD12) can set Transfer Complete when not using MMC_RSP_BUSY */
+#define SDHCI_QUIRK2_STOP_WITH_TC (1 << 8)
+/* Controller does not support 64-bit DMA */
+#define SDHCI_QUIRK2_BROKEN_64_BIT_DMA (1 << 9)
+/* need clear transfer mode register before send cmd */
+#define SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD (1 << 10)
+/* Capability register bit-63 indicates HS400 support */
+#define SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 (1 << 11)
+/* forced tuned clock */
+#define SDHCI_QUIRK2_TUNING_WORK_AROUND (1 << 12)
+/* disable the block count for single block transactions */
+#define SDHCI_QUIRK2_SUPPORT_SINGLE (1 << 13)
+/* Controller broken with using ACMD23 */
+#define SDHCI_QUIRK2_ACMD23_BROKEN (1 << 14)
+/* Broken Clock divider zero in controller */
+#define SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN (1 << 15)
+/* Controller has CRC in 136 bit Command Response */
+#define SDHCI_QUIRK2_RSP_136_HAS_CRC (1 << 16)
+/*
+ * Disable HW timeout if the requested timeout is more than the maximum
+ * obtainable timeout.
+ */
+#define SDHCI_QUIRK2_DISABLE_HW_TIMEOUT (1 << 17)
+/*
+ * 32-bit block count may not support eMMC where upper bits of CMD23 are used
+ * for other purposes.  Consequently we support 16-bit block count by default.
+ * Otherwise, SDHCI_QUIRK2_USE_32BIT_BLK_CNT can be selected to use 32-bit
+ * block count.
+ */
+#define SDHCI_QUIRK2_USE_32BIT_BLK_CNT (1 << 18)
+/* Issue CMD and DATA reset together */
+#define SDHCI_QUIRK2_ISSUE_CMD_DAT_RESET_TOGETHER (1 << 19)
+
+    int          irq;           /* Device IRQ */
+    void        *ioaddr;        /* Mapped address */
+    char        *bounce_buffer; /* For packing SDMA reads/writes */
+    rt_uint64_t  bounce_addr;
+    unsigned int bounce_buffer_size;
+
+    const struct sdhci_ops *ops; /* Low level hw interface */
+
+    /* Internal data */
+    struct mmc_host    *mmc;          /* MMC structure */
+    struct mmc_host_ops mmc_host_ops; /* MMC host ops */
+    rt_uint64_t         dma_mask;     /* custom DMA mask */
+
+    rt_spinlock_t lock;
+    int           flags;                             /* Host attributes */
+#define SDHCI_USE_SDMA           (1 << 0)            /* Host is SDMA capable */
+#define SDHCI_USE_ADMA           (1 << 1)            /* Host is ADMA capable */
+#define SDHCI_REQ_USE_DMA        (1 << 2)            /* Use DMA for this req. */
+#define SDHCI_DEVICE_DEAD        (1 << 3)            /* Device unresponsive */
+#define SDHCI_SDR50_NEEDS_TUNING (1 << 4)            /* SDR50 needs tuning */
+#define SDHCI_AUTO_CMD12         (1 << 6)            /* Auto CMD12 support */
+#define SDHCI_AUTO_CMD23         (1 << 7)            /* Auto CMD23 support */
+#define SDHCI_PV_ENABLED         (1 << 8)            /* Preset value enabled */
+#define SDHCI_USE_64_BIT_DMA     (1 << 12)           /* Use 64-bit DMA */
+#define SDHCI_HS400_TUNING       (1 << 13)           /* Tuning for HS400 */
+#define SDHCI_SIGNALING_330      (1 << 14)           /* Host is capable of 3.3V signaling */
+#define SDHCI_SIGNALING_180      (1 << 15)           /* Host is capable of 1.8V signaling */
+#define SDHCI_SIGNALING_120      (1 << 16)           /* Host is capable of 1.2V signaling */
+
+    unsigned int version;                            /* SDHCI spec. version */
+
+    unsigned int max_clk;                            /* Max possible freq (MHz) */
+    unsigned int timeout_clk;                        /* Timeout freq (KHz) */
+    rt_uint8_t   max_timeout_count;                  /* Vendor specific max timeout count */
+    unsigned int clk_mul;                            /* Clock Muliplier value */
+
+    unsigned int clock;                              /* Current clock (MHz) */
+    rt_uint8_t   pwr;                                /* Current voltage */
+    rt_uint8_t   drv_type;                           /* Current UHS-I driver type */
+    rt_bool_t    reinit_uhs;                         /* Force UHS-related re-initialization */
+
+    rt_bool_t runtime_suspended;                     /* Host is runtime suspended */
+    rt_bool_t bus_on;                                /* Bus power prevents runtime suspend */
+    rt_bool_t preset_enabled;                        /* Preset is enabled */
+    rt_bool_t pending_reset;                         /* Cmd/data reset is pending */
+    rt_bool_t irq_wake_enabled;                      /* IRQ wakeup is enabled */
+    rt_bool_t v4_mode;                               /* Host Version 4 Enable */
+    rt_bool_t use_external_dma;                      /* Host selects to use external DMA */
+    rt_bool_t always_defer_done;                     /* Always defer to complete requests */
+
+    struct rt_mmcsd_req  *mrqs_done[SDHCI_MAX_MRQS]; /* Requests done */
+    struct rt_mmcsd_cmd  *cmd;                       /* Current command */
+    struct rt_mmcsd_cmd  *data_cmd;                  /* Current data command */
+    struct rt_mmcsd_cmd  *deferred_cmd;              /* Deferred command */
+    struct rt_mmcsd_data *data;                      /* Current data request */
+    unsigned int          data_early : 1;            /* Data finished before cmd */
+
+    unsigned int blocks;                /* remaining PIO blocks */
+
+    int sg_count;                       /* Mapped sg entries */
+    int max_adma;                       /* Max. length in ADMA descriptor */
+
+    void *adma_table;                   /* ADMA descriptor table */
+    void *align_buffer;                 /* Bounce buffer */
+
+    size_t adma_table_sz;               /* ADMA descriptor table size */
+    size_t align_buffer_sz;             /* Bounce buffer size */
+
+    rt_uint64_t adma_addr;              /* Mapped ADMA descr. table */
+    rt_uint64_t align_addr;             /* Mapped bounce buffer */
+
+    unsigned int desc_sz;               /* ADMA current descriptor size */
+    unsigned int alloc_desc_sz;         /* ADMA descr. max size host supports */
+
+    struct rt_workqueue *complete_wq;   /* Request completion wq */
+    struct rt_work       complete_work; /* Request completion work */
+
+    struct rt_workqueue *irq_wq;
+    struct rt_work       irq_work;
+
+    struct rt_timer timer;                    /* Timer for timeouts */
+    struct rt_timer data_timer;               /* Timer for data timeouts */
+
+    rt_uint32_t caps;                         /* CAPABILITY_0 */
+    rt_uint32_t caps1;                        /* CAPABILITY_1 */
+    rt_bool_t   read_caps;                    /* Capability flags have been read */
+
+    rt_bool_t    sdhci_core_to_disable_vqmmc; /* sdhci core can disable vqmmc */
+    unsigned int ocr_avail_sdio;              /* OCR bit masks */
+    unsigned int ocr_avail_sd;
+    unsigned int ocr_avail_mmc;
+    rt_uint32_t  ocr_mask; /* available voltages */
+
+    unsigned timing;       /* Current timing */
+
+    rt_uint32_t thread_isr;
+
+    /* cached registers */
+    rt_uint32_t ier;
+
+    rt_bool_t   cqe_on;         /* CQE is operating */
+    rt_uint32_t cqe_ier;        /* CQE interrupt mask */
+    rt_uint32_t cqe_err_ier;    /* CQE error interrupt mask */
+
+    rt_wqueue_t  buf_ready_int; /* Waitqueue for Buffer Read Ready interrupt */
+    unsigned int tuning_done;   /* Condition flag set when CMD19 succeeds */
+
+    unsigned int tuning_count;  /* Timer count for re-tuning */
+    unsigned int tuning_mode;   /* Re-tuning mode supported by host */
+    unsigned int tuning_err;    /* Error code for re-tuning */
+#define SDHCI_TUNING_MODE_1 0
+#define SDHCI_TUNING_MODE_2 1
+#define SDHCI_TUNING_MODE_3 2
+    /* Delay (ms) between tuning commands */
+    int tuning_delay;
+    int tuning_loop_count;
+
+    /* Host SDMA buffer boundary. */
+    rt_uint32_t sdma_boundary;
+
+    /* Host ADMA table count */
+    rt_uint32_t adma_table_cnt;
+    rt_uint64_t data_timeout;
+
+    unsigned long private[];
+};
+
+struct sdhci_ops
+{
+    rt_uint32_t     (*read_l)(struct sdhci_host *host, int reg);
+    rt_uint16_t     (*read_w)(struct sdhci_host *host, int reg);
+    rt_uint8_t      (*read_b)(struct sdhci_host *host, int reg);
+    void        (*write_l)(struct sdhci_host *host, rt_uint32_t val, int reg);
+    void        (*write_w)(struct sdhci_host *host, rt_uint16_t val, int reg);
+    void        (*write_b)(struct sdhci_host *host, rt_uint8_t val, int reg);
+    void (*set_clock)(struct sdhci_host *host, unsigned int clock);
+    void (*set_power)(struct sdhci_host *host, unsigned char mode,
+                      unsigned short vdd);
+
+    rt_uint32_t (*irq)(struct sdhci_host *host, rt_uint32_t intmask);
+
+    int (*set_dma_mask)(struct sdhci_host *host);
+    int (*enable_dma)(struct sdhci_host *host);
+    unsigned int (*get_max_clock)(struct sdhci_host *host);
+    unsigned int (*get_min_clock)(struct sdhci_host *host);
+    /* get_timeout_clock should return clk rate in unit of Hz */
+    unsigned int (*get_timeout_clock)(struct sdhci_host *host);
+    unsigned int (*get_max_timeout_count)(struct sdhci_host *host);
+    void (*set_timeout)(struct sdhci_host   *host,
+                        struct rt_mmcsd_cmd *cmd);
+    void (*set_bus_width)(struct sdhci_host *host, int width);
+    void (*platform_send_init_74_clocks)(struct sdhci_host *host,
+                                         rt_uint8_t         power_mode);
+    unsigned int (*get_ro)(struct sdhci_host *host);
+    void (*reset)(struct sdhci_host *host, rt_uint8_t mask);
+    int (*platform_execute_tuning)(struct sdhci_host *host, rt_uint32_t opcode);
+    void (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
+    void (*hw_reset)(struct sdhci_host *host);
+    void (*adma_workaround)(struct sdhci_host *host, rt_uint32_t intmask);
+    void (*card_event)(struct sdhci_host *host);
+    void (*voltage_switch)(struct sdhci_host *host);
+    void (*adma_write_desc)(struct sdhci_host *host, void **desc,
+                            rt_uint64_t addr, int len, unsigned int cmd);
+    void (*copy_to_bounce_buffer)(struct sdhci_host    *host,
+                                  struct rt_mmcsd_data *data,
+                                  unsigned int          length);
+    void (*request_done)(struct sdhci_host   *host,
+                         struct rt_mmcsd_req *mrq);
+    void (*dump_vendor_regs)(struct sdhci_host *host);
+};
+
+static inline rt_uint8_t rt_uint8_t_read(const volatile void *addr)
+{
+    return *(const volatile rt_uint8_t *)addr;
+}
+
+static inline rt_uint16_t rt_uint16_t_read(const volatile void *addr)
+{
+    return *(const volatile rt_uint16_t *)addr;
+}
+
+static inline rt_uint32_t rt_uint32_t_read(const volatile void *addr)
+{
+    return *(const volatile rt_uint32_t *)addr;
+}
+
+static inline void rt_uint8_t_write(rt_uint8_t value, volatile void *addr)
+{
+    *(volatile rt_uint8_t *)addr = value;
+}
+
+static inline void rt_uint16_t_write(rt_uint16_t value, volatile void *addr)
+{
+    *(volatile rt_uint16_t *)addr = value;
+}
+
+static inline void rt_uint32_t_write(rt_uint32_t value, volatile void *addr)
+{
+    *(volatile rt_uint32_t *)addr = value;
+}
+
+#define readb(c)        rt_uint8_t_read(c)
+#define readw(c)        rt_uint16_t_read(c)
+#define readl(c)        rt_uint32_t_read(c)
+#define readsb(p, d, l) ({ __raw_readsb(p,d,l); __iormb(); })
+#define readsw(p, d, l) ({ __raw_readsw(p,d,l); __iormb(); })
+#define readsl(p, d, l) ({ __raw_readsl(p,d,l); __iormb(); })
+
+#define writeb(v, c)     rt_uint8_t_write(v, c)
+#define writew(v, c)     rt_uint16_t_write(v, c)
+#define writel(v, c)     rt_uint32_t_write(v, c)
+#define writesb(p, d, l) ({ __iowmb(); __raw_writesb(p,d,l); })
+#define writesw(p, d, l) ({ __iowmb(); __raw_writesw(p,d,l); })
+#define writesl(p, d, l) ({ __iowmb(); __raw_writesl(p,d,l); })
+
+static inline void sdhci_writel(struct sdhci_host *host, rt_uint32_t val, int reg)
+{
+    if (host->ops->write_l)
+        host->ops->write_l(host, val, reg);
+    else
+        writel(val, host->ioaddr + reg);
+}
+
+static inline void sdhci_writew(struct sdhci_host *host, rt_uint16_t val, int reg)
+{
+    if (host->ops->write_w)
+        host->ops->write_w(host, val, reg);
+    else
+        writew(val, host->ioaddr + reg);
+}
+
+static inline void sdhci_writeb(struct sdhci_host *host, rt_uint8_t val, int reg)
+{
+    if (host->ops->write_b)
+        host->ops->write_b(host, val, reg);
+    else
+        writeb(val, host->ioaddr + reg);
+}
+
+static inline rt_uint32_t sdhci_readl(struct sdhci_host *host, int reg)
+{
+    if (host->ops->read_l)
+        return host->ops->read_l(host, reg);
+    else
+        return readl(host->ioaddr + reg);
+}
+
+static inline rt_uint16_t sdhci_readw(struct sdhci_host *host, int reg)
+{
+    if (host->ops->read_w)
+        return host->ops->read_w(host, reg);
+    else
+        return readw(host->ioaddr + reg);
+}
+
+static inline rt_uint8_t sdhci_readb(struct sdhci_host *host, int reg)
+{
+    if (host->ops->read_b)
+        return host->ops->read_b(host, reg);
+    else
+        return readb(host->ioaddr + reg);
+}
+
+struct sdhci_host *sdhci_alloc_host(struct rt_device *dev, size_t priv_size);
+void               sdhci_free_host(struct sdhci_host *host);
+
+static inline void *sdhci_priv(struct sdhci_host *host)
+{
+    return host->private;
+}
+
+void __sdhci_read_caps(struct sdhci_host *host, const rt_uint16_t *ver,
+                       const rt_uint32_t *caps, const rt_uint32_t *caps1);
+int  sdhci_setup_host(struct sdhci_host *host);
+void sdhci_cleanup_host(struct sdhci_host *host);
+int  __sdhci_add_host(struct sdhci_host *host);
+int  sdhci_add_host(struct sdhci_host *host);
+void sdhci_remove_host(struct sdhci_host *host, int dead);
+
+static inline void sdhci_read_caps(struct sdhci_host *host)
+{
+    __sdhci_read_caps(host, NULL, NULL, NULL);
+}
+
+rt_uint16_t sdhci_calc_clk(struct sdhci_host *host, unsigned int clock,
+                           unsigned int *actual_clock);
+void        sdhci_set_clock(struct sdhci_host *host, unsigned int clock);
+void        sdhci_enable_clk(struct sdhci_host *host, rt_uint16_t clk);
+void        sdhci_set_power(struct sdhci_host *host, unsigned char mode,
+                            unsigned short vdd);
+void        sdhci_set_power_and_bus_voltage(struct sdhci_host *host,
+                                            unsigned char      mode,
+                                            unsigned short     vdd);
+void        sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode,
+                                  unsigned short vdd);
+int         sdhci_get_cd_nogpio(struct mmc_host *mmc);
+void        sdhci_request(struct mmc_host *mmc, struct rt_mmcsd_req *mrq);
+int         sdhci_request_atomic(struct mmc_host *mmc, struct rt_mmcsd_req *mrq);
+void        sdhci_set_bus_width(struct sdhci_host *host, int width);
+void        sdhci_reset(struct sdhci_host *host, rt_uint8_t mask);
+void        sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing);
+int         sdhci_execute_tuning(struct mmc_host *mmc, rt_uint32_t opcode);
+int         __sdhci_execute_tuning(struct sdhci_host *host, rt_uint32_t opcode);
+void        sdhci_set_ios(struct mmc_host *mmc, struct rt_mmcsd_io_cfg *ios);
+int         sdhci_start_signal_voltage_switch(struct mmc_host        *mmc,
+                                              struct rt_mmcsd_io_cfg *ios);
+void        sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable);
+void        sdhci_adma_write_desc(struct sdhci_host *host, void **desc,
+                                  rt_uint64_t addr, int len, unsigned int cmd);
+
+void      sdhci_cqe_enable(struct mmc_host *mmc);
+void      sdhci_cqe_disable(struct mmc_host *mmc, rt_bool_t recovery);
+rt_bool_t sdhci_cqe_irq(struct sdhci_host *host, rt_uint32_t intmask, int *cmd_error,
+                        int *data_error);
+
+void sdhci_dumpregs(struct sdhci_host *host);
+void sdhci_enable_v4_mode(struct sdhci_host *host);
+
+void sdhci_start_tuning(struct sdhci_host *host);
+void sdhci_end_tuning(struct sdhci_host *host);
+void sdhci_reset_tuning(struct sdhci_host *host);
+void sdhci_send_tuning(struct sdhci_host *host, rt_uint32_t opcode);
+void sdhci_abort_tuning(struct sdhci_host *host, rt_uint32_t opcode);
+void sdhci_switch_external_dma(struct sdhci_host *host, rt_bool_t en);
+void sdhci_set_data_timeout_irq(struct sdhci_host *host, rt_bool_t enable);
+void __sdhci_set_timeout(struct sdhci_host *host, struct rt_mmcsd_cmd *cmd);
+
+#endif /* __SDHCI_HW_H */

+ 31 - 0
bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci_dma.h

@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2006-2024 RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author        Notes
+ * 2024-08-16     zhujiale     first version
+ */
+#ifndef __SDHCI_DMA_H__
+#define __SDHCI_DMA_H__
+
+#include "ioremap.h"
+#include <mm_aspace.h>
+enum dma_data_direction
+{
+    DMA_BIDIRECTIONAL = 0,
+    DMA_TO_DEVICE     = 1,
+    DMA_FROM_DEVICE   = 2,
+    DMA_NONE          = 3,
+};
+#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL << (n)) - 1))
+
+int           dma_set_mask_and_coherent(struct rt_device *dev, rt_uint64_t mask);
+unsigned long virt_to_phys(volatile void *address);
+void         *dma_alloc_coherent(struct rt_device *dev, size_t size,
+                                 rt_uint64_t *dma_handle);
+void          dma_free_coherent(struct rt_device *dev, size_t size,
+                                void *cpu_addr, unsigned long dma_handle);
+
+#endif

+ 411 - 0
bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci_host.h

@@ -0,0 +1,411 @@
+/*
+ * Copyright (c) 2006-2024 RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author        Notes
+ * 2024-08-16     zhujiale     first version
+ */
+#ifndef __SDHCI_MMC_H__
+#define __SDHCI_MMC_H__
+
+#include <rtthread.h>
+#include <drivers/mmcsd_cmd.h>
+#include <drivers/dev_mmcsd_core.h>
+#include <drivers/mmcsd_host.h>
+#include "sdhci_dma.h"
+#define mmc_dev(x) ((x)->parent)
+
+#define MMC_SEND_TUNING_BLOCK_HS200 SEND_TUNING_BLOCK_HS200
+#define MMC_SEND_TUNING_BLOCK       SEND_TUNING_BLOCK
+#define MMC_STOP_TRANSMISSION       STOP_TRANSMISSION
+#define MMC_BUS_TEST_R              14 /* adtc                    R1  */
+#define MMC_WRITE_MULTIPLE_BLOCK    WRITE_MULTIPLE_BLOCK
+#define MMC_READ_MULTIPLE_BLOCK     READ_MULTIPLE_BLOCK
+
+#define MMC_TIMING_UHS_DDR50  MMCSD_TIMING_UHS_DDR50
+#define MMC_TIMING_UHS_SDR50  MMCSD_TIMING_UHS_SDR50
+#define MMC_TIMING_MMC_HS200  MMCSD_TIMING_MMC_HS200
+#define MMC_TIMING_MMC_HS400  MMCSD_TIMING_MMC_HS400
+#define MMC_TIMING_UHS_SDR104 MMCSD_TIMING_UHS_SDR104
+#define MMC_TIMING_UHS_SDR25  MMCSD_TIMING_UHS_SDR25
+#define MMC_TIMING_MMC_DDR52  MMCSD_TIMING_MMC_DDR52
+#define MMC_TIMING_UHS_SDR12  MMCSD_TIMING_UHS_SDR12
+#define MMC_TIMING_SD_HS      MMCSD_TIMING_SD_HS
+#define MMC_TIMING_MMC_HS     MMCSD_TIMING_MMC_HS
+
+#define MMC_POWER_OFF       MMCSD_POWER_OFF
+#define MMC_POWER_UP        MMCSD_POWER_UP
+#define MMC_POWER_ON        MMCSD_POWER_ON
+#define MMC_POWER_UNDEFINED 3
+
+#define MMC_SET_DRIVER_TYPE_B 0
+#define MMC_SET_DRIVER_TYPE_A 1
+#define MMC_SET_DRIVER_TYPE_C 2
+#define MMC_SET_DRIVER_TYPE_D 3
+
+#define MMC_SIGNAL_VOLTAGE_330 0
+#define MMC_SIGNAL_VOLTAGE_180 1
+#define MMC_SIGNAL_VOLTAGE_120 2
+
+#define MMC_RSP_PRESENT (1 << 16)
+#define MMC_RSP_136     (1 << 17) /* 136 bit response */
+#define MMC_RSP_CRC     (1 << 18) /* expect valid crc */
+#define MMC_RSP_BUSY    (1 << 19) /* card may send busy */
+#define MMC_RSP_OPCODE  (1 << 20) /* response contains opcode */
+
+/*
+ * These are the native response types, and correspond to valid bit
+ * patterns of the above flags.  One additional valid pattern
+ * is all zeros, which means we don't expect a response.
+ */
+#define MMC_RSP_NONE (0)
+#define MMC_RSP_R1   (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
+#define MMC_RSP_R1B  (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE | MMC_RSP_BUSY)
+#define MMC_RSP_R2   (MMC_RSP_PRESENT | MMC_RSP_136 | MMC_RSP_CRC)
+#define MMC_RSP_R3   (MMC_RSP_PRESENT)
+#define MMC_RSP_R4   (MMC_RSP_PRESENT)
+#define MMC_RSP_R5   (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
+#define MMC_RSP_R6   (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
+#define MMC_RSP_R7   (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
+
+#define MMC_CMD_ADTC CMD_ADTC
+
+#define MMC_BUS_WIDTH_8 MMCSD_BUS_WIDTH_8
+#define MMC_BUS_WIDTH_4 MMCSD_BUS_WIDTH_4
+#define MMC_BUS_WIDTH_1 MMCSD_BUS_WIDTH_1
+
+#define MMC_PM_KEEP_POWER    (1 << 0) /* preserve card power during suspend */
+#define MMC_PM_WAKE_SDIO_IRQ (1 << 1) /* wake up host system on SDIO IRQ assertion */
+enum mmc_blk_status
+{
+    MMC_BLK_SUCCESS = 0,
+    MMC_BLK_PARTIAL,
+    MMC_BLK_CMD_ERR,
+    MMC_BLK_RETRY,
+    MMC_BLK_ABORT,
+    MMC_BLK_DATA_ERR,
+    MMC_BLK_ECC_ERR,
+    MMC_BLK_NOMEDIUM,
+    MMC_BLK_NEW_REQUEST,
+};
+
+/************************************************************************************************ */
+
+#define MMC_NUM_CLK_PHASES (MMC_TIMING_MMC_HS400 + 1)
+
+struct mmc_host;
+
+struct mmc_host_ops
+{
+    /*
+     * It is optional for the host to implement pre_req and post_req in
+     * order to support double buffering of requests (prepare one
+     * request while another request is active).
+     * pre_req() must always be followed by a post_req().
+     * To undo a call made to pre_req(), call post_req() with
+     * a nonzero err condition.
+     */
+    void (*post_req)(struct mmc_host *host, struct rt_mmcsd_req *req,
+                     int err);
+    void (*pre_req)(struct mmc_host *host, struct rt_mmcsd_req *req);
+    void (*request)(struct mmc_host *host, struct rt_mmcsd_req *req);
+
+    /*
+     * Avoid calling the next three functions too often or in a "fast
+     * path", since underlaying controller might implement them in an
+     * expensive and/or slow way. Also note that these functions might
+     * sleep, so don't call them in the atomic contexts!
+     */
+
+    /*
+     * Notes to the set_ios callback:
+     * ios->clock might be 0. For some controllers, setting 0Hz
+     * as any other frequency works. However, some controllers
+     * explicitly need to disable the clock. Otherwise e.g. voltage
+     * switching might fail because the SDCLK is not really quiet.
+     */
+    void (*set_ios)(struct mmc_host *host, struct rt_mmcsd_io_cfg *ios);
+
+    /*
+     * Return values for the get_ro callback should be:
+     *   0 for a read/write card
+     *   1 for a read-only card
+     *   -ENOSYS when not supported (equal to NULL callback)
+     *   or a negative errno value when something bad happened
+     */
+    int (*get_ro)(struct mmc_host *host);
+
+    /*
+     * Return values for the get_cd callback should be:
+     *   0 for a absent card
+     *   1 for a present card
+     *   -ENOSYS when not supported (equal to NULL callback)
+     *   or a negative errno value when something bad happened
+     */
+    int (*get_cd)(struct mmc_host *host);
+
+    void (*enable_sdio_irq)(struct mmc_host *host, int enable);
+    /* Mandatory callback when using MMC_CAP2_SDIO_IRQ_NOTHREAD. */
+    void (*ack_sdio_irq)(struct mmc_host *host);
+
+    int (*start_signal_voltage_switch)(struct mmc_host *host, struct rt_mmcsd_io_cfg *ios);
+
+    /* Check if the card is pulling dat[0:3] low */
+    int (*card_busy)(struct mmc_host *host);
+
+    /* The tuning command opcode value is different for SD and eMMC cards */
+    int (*execute_tuning)(struct mmc_host *host, unsigned opcode);
+
+    /* Prepare HS400 target operating frequency depending host driver */
+    int (*prepare_hs400_tuning)(struct mmc_host *host, struct rt_mmcsd_io_cfg *ios);
+
+    /* Prepare switch to DDR during the HS400 init sequence */
+    int (*hs400_prepare_ddr)(struct mmc_host *host);
+
+    /* Prepare for switching from HS400 to HS200 */
+    void (*hs400_downgrade)(struct mmc_host *host);
+
+    /* Complete selection of HS400 */
+    void (*hs400_complete)(struct mmc_host *host);
+
+    /* Prepare enhanced strobe depending host driver */
+    void (*hs400_enhanced_strobe)(struct mmc_host        *host,
+                                  struct rt_mmcsd_io_cfg *ios);
+
+    /* Reset the eMMC card via RST_n */
+    void (*hw_reset)(struct mmc_host *host);
+    void (*card_event)(struct mmc_host *host);
+};
+
+struct regulator;
+struct mmc_pwrseq;
+
+struct mmc_supply
+{
+    struct regulator *vmmc;  /* Card power supply */
+    struct regulator *vqmmc; /* Optional Vccq supply */
+};
+
+struct mmc_ctx
+{
+    struct task_struct *task;
+};
+
+/* VDD voltage 3.3 ~ 3.4 */
+#define MMC_VDD_34_35 0x00400000 /* VDD voltage 3.4 ~ 3.5 */
+#define MMC_VDD_35_36 0x00800000 /* VDD voltage 3.5 ~ 3.6 */
+
+#define MMC_CAP2_HS200_1_8V_SDR MMCSD_SUP_HS200_1V8
+#define MMC_CAP_4_BIT_DATA      MMCSD_BUSWIDTH_4
+#define MMC_CAP_8_BIT_DATA      MMCSD_BUSWIDTH_8
+#define MMC_CAP2_HS200          MMCSD_SUP_HS200
+#define MMC_CAP_MMC_HIGHSPEED   MMCSD_SUP_HIGHSPEED
+#define MMC_CAP_SD_HIGHSPEED    MMCSD_SUP_HIGHSPEED
+#define MMC_CAP_1_8V_DDR        MMCSD_SUP_DDR_1V8
+#define MMC_CAP_3_3V_DDR        MMCSD_SUP_DDR_3V3
+#define MMC_CAP_1_2V_DDR        MMCSD_SUP_DDR_1V2
+#define MMC_CAP_NONREMOVABLE    MMCSD_SUP_NONREMOVABLE
+
+
+#define MMC_CAP_UHS_DDR50          0
+#define MMC_CAP2_HS400             0
+#define MMC_CAP_UHS_SDR50          0
+#define MMC_CAP_UHS_SDR25          0
+#define MMC_CAP_UHS_SDR12          0
+#define MMC_CAP_UHS_SDR104         0
+#define MMC_CAP_UHS                0
+#define MMC_CAP2_HSX00_1_8V        0
+#define MMC_CAP2_HS400_ES          0
+#define MMC_CAP_NEEDS_POLL         0
+#define MMC_CAP2_HSX00_1_2V        0
+#define MMC_CAP2_HS400_1_8V        0
+#define MMC_CAP_DRIVER_TYPE_D      0
+#define MMC_CAP_DRIVER_TYPE_C      0
+#define MMC_SET_DRIVER_TYPE_B      0
+#define MMC_CAP_DRIVER_TYPE_A      0
+#define MMC_CAP2_SDIO_IRQ_NOTHREAD 0
+#define MMC_CAP_CMD23              0
+#define MMC_CAP_SDIO_IRQ           0
+
+#define MMC_CAP2_NO_SDIO (1 << 19)
+#define MMC_CAP2_NO_SD   (1 << 21)
+#define MMC_CAP2_NO_MMC  (1 << 22)
+#define MMC_CAP2_CQE     (1 << 23)
+
+#define MMC_VDD_165_195 VDD_165_195
+#define MMC_VDD_20_21   VDD_20_21
+#define MMC_VDD_29_30   VDD_29_30
+#define MMC_VDD_30_31   VDD_30_31
+#define MMC_VDD_32_33   VDD_32_33
+#define MMC_VDD_33_34   VDD_33_34
+
+
+struct mmc_host
+{
+    struct rt_mmcsd_host       rthost;
+    struct rt_device          *parent;
+    int                        index;
+    const struct mmc_host_ops *ops;
+    unsigned int               f_min;
+    unsigned int               f_max;
+    unsigned int               f_init;
+    rt_uint32_t                ocr_avail;
+    rt_uint32_t                ocr_avail_sdio; /* SDIO-specific OCR */
+    rt_uint32_t                ocr_avail_sd;   /* SD-specific OCR */
+    rt_uint32_t                ocr_avail_mmc;  /* MMC-specific OCR */
+    struct wakeup_source      *ws;             /* Enable consume of uevents */
+    rt_uint32_t                max_current_330;
+    rt_uint32_t                max_current_300;
+    rt_uint32_t                max_current_180;
+    rt_uint32_t                caps; /* Host capabilities */
+
+    rt_uint32_t caps2;               /* More host capabilities */
+
+
+    /* host specific block data */
+    unsigned int           max_seg_size;     /* see blk_queue_max_segment_size */
+    unsigned short         max_segs;         /* see blk_queue_max_segments */
+    unsigned short         unused;
+    unsigned int           max_req_size;     /* maximum number of bytes in one req */
+    unsigned int           max_blk_size;     /* maximum size of one mmc block */
+    unsigned int           max_blk_count;    /* maximum number of blocks in one req */
+    unsigned int           max_busy_timeout; /* max busy timeout in ms */
+    struct rt_mmcsd_io_cfg ios;              /* current io bus settings */
+    unsigned int           retune_period;
+    /* group bitfields together to minimize padding */
+    unsigned int use_spi_crc        : 1;
+    unsigned int claimed            : 1; /* host exclusively claimed */
+    unsigned int doing_init_tune    : 1; /* initial tuning in progress */
+    unsigned int can_retune         : 1; /* re-tuning can be used */
+    unsigned int doing_retune       : 1; /* re-tuning in progress */
+    unsigned int retune_now         : 1; /* do re-tuning at next req */
+    unsigned int retune_paused      : 1; /* re-tuning is temporarily disabled */
+    unsigned int retune_crc_disable : 1; /* don't trigger retune upon crc */
+    unsigned int can_dma_map_merge  : 1; /* merging can be used */
+    unsigned int vqmmc_enabled      : 1; /* vqmmc regulator is enabled */
+
+    int          need_retune;            /* re-tuning is needed */
+    int          hold_retune;            /* hold off re-tuning */
+    rt_bool_t    trigger_card_event;     /* card_event necessary */
+    unsigned int sdio_irqs;
+    rt_bool_t    sdio_irq_pending;
+
+    struct led_trigger *led; /* activity led */
+
+    struct mmc_supply supply;
+
+
+    /* Ongoing data transfer that allows commands during transfer */
+    struct rt_mmcsd_req *ongoing_mrq;
+
+
+    unsigned int actual_clock; /* Actual HC clock rate */
+    rt_uint32_t  pm_caps;
+    unsigned long private[];
+};
+
+
+static inline int mmc_card_is_removable(struct mmc_host *host)
+{
+    return !(host->caps & MMC_CAP_NONREMOVABLE);
+}
+
+struct device_node;
+
+struct mmc_host *mmc_alloc_host(int extra, struct rt_device *);
+int              mmc_add_host(struct mmc_host *);
+void             mmc_remove_host(struct mmc_host *);
+void             mmc_free_host(struct mmc_host *);
+int              mmc_of_parse(struct mmc_host *host);
+int              mmc_of_parse_voltage(struct mmc_host *host, rt_uint32_t *mask);
+
+static inline void *mmc_priv(struct mmc_host *host)
+{
+    return (void *)host->private;
+}
+
+
+#define mmc_host_is_spi(host) ((host)->caps & MMC_CAP_SPI)
+
+#define mmc_dev(x)      ((x)->parent)
+#define mmc_classdev(x) (&(x)->class_dev)
+#define mmc_hostname(x) (x->parent->parent.name)
+
+void mmc_detect_change(struct mmc_host *, unsigned long delay);
+void mmc_request_done(struct mmc_host *, struct rt_mmcsd_req *);
+void mmc_command_done(struct mmc_host *host, struct rt_mmcsd_req *mrq);
+
+void mmc_cqe_request_done(struct mmc_host *host, struct rt_mmcsd_req *mrq);
+
+/*
+ * May be called from host driver's system/runtime suspend/resume callbacks,
+ * to know if SDIO IRQs has been claimed.
+ */
+static inline rt_bool_t sdio_irq_claimed(struct mmc_host *host)
+{
+    return host->sdio_irqs > 0;
+}
+
+static inline int mmc_regulator_set_ocr(struct mmc_host  *mmc,
+                                        struct regulator *supply,
+                                        unsigned short    vdd_bit)
+{
+    return 0;
+}
+
+int  mmc_regulator_get_supply(struct mmc_host *mmc);
+int  mmc_regulator_enable_vqmmc(struct mmc_host *mmc);
+void mmc_regulator_disable_vqmmc(struct mmc_host *mmc);
+
+void mmc_retune_timer_stop(struct mmc_host *host);
+
+static inline void mmc_retune_needed(struct mmc_host *host)
+{
+    if (host->can_retune)
+        host->need_retune = 1;
+}
+
+static inline rt_bool_t mmc_can_retune(struct mmc_host *host)
+{
+    return host->can_retune == 1;
+}
+
+static inline rt_bool_t mmc_doing_retune(struct mmc_host *host)
+{
+    return host->doing_retune == 1;
+}
+
+static inline rt_bool_t mmc_doing_tune(struct mmc_host *host)
+{
+    return host->doing_retune == 1 || host->doing_init_tune == 1;
+}
+
+static inline int mmc_get_dma_dir(struct rt_mmcsd_data *data)
+{
+    return data->flags & DATA_DIR_WRITE ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+}
+
+static inline rt_bool_t mmc_op_multi(rt_uint32_t opcode)
+{
+    return opcode == MMC_WRITE_MULTIPLE_BLOCK || opcode == MMC_READ_MULTIPLE_BLOCK;
+}
+
+static inline rt_bool_t mmc_op_tuning(rt_uint32_t opcode)
+{
+    return opcode == MMC_SEND_TUNING_BLOCK || opcode == MMC_SEND_TUNING_BLOCK_HS200;
+}
+
+int       mmc_gpio_get_cd(struct mmc_host *host);
+void      mmc_detect_change(struct mmc_host *host, unsigned long delay);
+int       mmc_regulator_set_vqmmc(struct mmc_host *mmc, struct rt_mmcsd_io_cfg *ios);
+rt_bool_t mmc_can_gpio_ro(struct mmc_host *host);
+int       mmc_gpio_get_ro(struct mmc_host *host);
+
+int mmc_send_tuning(struct mmc_host *host, rt_uint32_t opcode, int *cmd_error);
+int mmc_send_abort_tuning(struct mmc_host *host, rt_uint32_t opcode);
+int mmc_of_parse(struct mmc_host *host);
+
+
+#endif

+ 76 - 0
bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci_misc.h

@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2006-2024 RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author        Notes
+ * 2024-08-16     zhujiale     first version
+ */
+#ifndef __SDHCI_MISC_H__
+#define __SDHCI_MISC_H__
+
+#include "sdhci_host.h"
+
+#define __BF_FIELD_CHECK(...)
+#define __bf_shf(x) (__builtin_ffsll(x) - 1)
+#define FIELD_GET(_mask, _reg)                                  \
+    ({                                                          \
+        __BF_FIELD_CHECK(_mask, _reg, 0U, "FIELD_GET: ");       \
+        (typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \
+    })
+
+#define FIELD_PREP(_mask, _val)                               \
+    ({                                                        \
+        __BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_PREP: ");  \
+        ((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask); \
+    })
+
+#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
+
+#define min_t(type, x, y) (((type)x < (type)y) ? x : y)
+#define max_t(type, x, y) (((type)x > (type)y) ? x : y)
+#define min(x, y)         ((x) < (y) ? (x) : (y))
+
+#define from_timer(var, callback_timer, timer_fieldname) \
+    container_of(callback_timer, typeof(*var), timer_fieldname)
+
+
+#define le32_to_cpu(x)   (x)
+#define le16_to_cpu(x)   (x)
+#define cpu_to_le16(x)   (x)
+#define cpu_to_le32(x)   (x)
+#define lower_32_bits(n) ((rt_uint32_t)((n) & 0xffffffff))
+#define upper_32_bits(n) ((rt_uint32_t)(((n) >> 16) >> 16))
+
+#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
+
+#define do_div(n, base) ({            \
+    uint32_t __base = (base);         \
+    uint32_t __rem;                   \
+    __rem = ((uint64_t)(n)) % __base; \
+    (n)   = ((uint64_t)(n)) / __base; \
+    __rem;                            \
+})
+
+#define fallthrough \
+    do {            \
+    } while (0)
+
+int       regulator_is_supported_voltage(struct regulator *regulator,
+                                         int min_uV, int max_uV);
+int       regulator_enable(struct regulator *regulator);
+rt_bool_t mmc_can_gpio_cd(struct mmc_host *host);
+
+struct regulator
+{
+    const char *supply_name;
+};
+
+int regulator_get_current_limit(struct regulator *regulator);
+
+int regulator_enable(struct regulator *regulator);
+
+void regulator_disable(struct regulator *regulator);
+
+#endif

+ 125 - 0
bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/sdhci-platform/sdhci-platform.c

@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2006-2024 RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author        Notes
+ * 2024-08-16     zhujiale     first version
+ */
+#include "sdhci-platform.h"
+
+static const struct sdhci_ops sdhci_pltfm_ops = {
+    .set_clock         = sdhci_set_clock,
+    .set_bus_width     = sdhci_set_bus_width,
+    .reset             = sdhci_reset,
+    .set_uhs_signaling = sdhci_set_uhs_signaling,
+};
+
+void sdhci_get_property(struct rt_platform_device *pdev)
+{
+    struct rt_device        *dev        = &pdev->parent;
+    struct sdhci_host       *host       = pdev->priv;
+    struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+    rt_uint32_t              bus_width;
+
+    if (rt_dm_dev_prop_read_bool(dev, "sdhci,auto-cmd12"))
+        host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
+
+    if (rt_dm_dev_prop_read_bool(dev, "sdhci,1-bit-only") || (rt_dm_dev_prop_read_u32(dev, "bus-width", &bus_width) == 0 && bus_width == 1))
+        host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA;
+
+    if (rt_dm_dev_prop_read_bool(dev, "broken-cd"))
+        host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+
+    if (rt_dm_dev_prop_read_bool(dev, "no-1-8-v"))
+        host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
+
+    rt_dm_dev_prop_read_u32(dev, "clock-frequency", &pltfm_host->clock);
+
+    if (rt_dm_dev_prop_read_bool(dev, "keep-power-in-suspend"))
+        host->mmc->pm_caps |= MMC_PM_KEEP_POWER;
+
+    if (rt_dm_dev_prop_read_bool(dev, "wakeup-source") || rt_dm_dev_prop_read_bool(dev, "enable-sdio-wakeup")) /* legacy */
+        host->mmc->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
+}
+
+struct sdhci_host *sdhci_pltfm_init(struct rt_platform_device     *pdev,
+                                    const struct sdhci_pltfm_data *pdata,
+                                    size_t                         priv_size)
+{
+    struct sdhci_host      *host;
+    struct rt_device       *dev = &pdev->parent;
+    void                   *ioaddr;
+    int                     irq;
+
+    ioaddr = rt_dm_dev_iomap(dev, 0);
+    if (!ioaddr)
+    {
+        return RT_NULL;
+    }
+
+    irq = rt_dm_dev_get_irq(dev, 0);
+    if (irq < 0)
+    {
+        return RT_NULL;
+    }
+    host = sdhci_alloc_host(dev, priv_size);
+    if (!host)
+    {
+        return RT_NULL;
+    }
+    host->irq     = irq;
+    host->ioaddr  = ioaddr;
+    host->hw_name = rt_dm_dev_get_name(dev);
+
+    if (pdata && pdata->ops)
+        host->ops = pdata->ops;
+    else
+        host->ops = &sdhci_pltfm_ops;
+    if (pdata)
+    {
+        host->quirks  = pdata->quirks;
+        host->quirks2 = pdata->quirks2;
+    }
+
+    pdev->priv = host;
+
+    return host;
+}
+
+int sdhci_pltfm_init_and_add_host(struct rt_platform_device     *pdev,
+                                  const struct sdhci_pltfm_data *pdata,
+                                  size_t                         priv_size)
+{
+    struct sdhci_host *host;
+    int                ret = 0;
+
+    host = sdhci_pltfm_init(pdev, pdata, priv_size);
+    if (!host)
+        return -RT_ERROR;
+
+    sdhci_get_property(pdev);
+
+    ret = sdhci_add_host(host);
+    if (ret)
+        sdhci_pltfm_free(pdev);
+
+    return ret;
+}
+
+void sdhci_pltfm_free(struct rt_platform_device *pdev)
+{
+    struct sdhci_host *host = pdev->priv;
+
+    sdhci_free_host(host);
+}
+
+void sdhci_pltfm_remove(struct rt_platform_device *pdev)
+{
+    struct sdhci_host *host = pdev->priv;
+    int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
+
+    sdhci_remove_host(host, dead);
+    sdhci_pltfm_free(pdev);
+}

+ 3606 - 0
bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/sdhci.c

@@ -0,0 +1,3606 @@
+/*
+ * Copyright (c) 2006-2024 RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author        Notes
+ * 2024-08-16     zhujiale     first version
+ */
+
+#include <rtthread.h>
+#include "sdhci.h"
+#include <string.h>
+#define DBG_TAG "SDHCI"
+#ifdef DRV_DEBUG
+#define DBG_LVL DBG_LOG
+#else
+#define DBG_LVL DBG_INFO
+#endif /* DRV_DEBUG */
+#include <rtdbg.h>
+static unsigned int debug_quirks = 0;
+static unsigned int debug_quirks2;
+/********************************************************* */
+/*                        cmd                              */
+/********************************************************* */
+
+
+void read_reg(struct sdhci_host *host)
+{
+    rt_kprintf("0x00 addddddddddddd           = %x \n", sdhci_readl(host, 0x00));
+    rt_kprintf("0x04 EMMC_BLOCKSIZE           = %x \n", sdhci_readw(host, 0x04));
+    rt_kprintf("0x06 EMMC_BLOCKCOUNT          = %x \n", sdhci_readw(host, 0x06));
+    rt_kprintf("0x08 SDHCI_ARGUMENT           = %x \n", sdhci_readl(host, 0x08));
+    rt_kprintf("0x0c EMMC_XFER_MODE           = %x \n", sdhci_readw(host, 0x0c));
+    rt_kprintf("0x0e SDHCI_COMMAND            = %x \n", sdhci_readw(host, 0x0e));
+    rt_kprintf("0x24 SDHCI_PRESENT_STATE      = %x \n", sdhci_readl(host, 0x24));
+    rt_kprintf("0x28 SDHCI_HOST_CONTROL       = %x \n", sdhci_readb(host, 0x28));
+    rt_kprintf("0x29 SDHCI_POWER_CONTROL      = %x \n", sdhci_readb(host, 0x29));
+    rt_kprintf("0x2a EMMC_BGAP_CTRL           = %x \n", sdhci_readb(host, 0x2a));
+    rt_kprintf("0x2c EMMC_CLK_CTRL            = %x \n", sdhci_readw(host, 0x2c));
+    rt_kprintf("0x2e EMMC_TOUT_CTRL           = %x \n", sdhci_readb(host, 0x2e));
+    rt_kprintf("0x2f EMMC_SW_RST              = %x \n", sdhci_readb(host, 0x2f));
+    rt_kprintf("0x30 SDHCI_INT_STATUS         = %x \n", sdhci_readw(host, 0x30));
+    rt_kprintf("0x32 SDHCI_ERR_INT_STATUS     = %x \n", sdhci_readw(host, 0x32));
+    rt_kprintf("0x34 SDHCI_INT_ENABLE         = %x \n", sdhci_readw(host, 0x34));
+    rt_kprintf("0x36 EMMC ERROR INT STATEN    = %x \n", sdhci_readw(host, 0x36));
+    rt_kprintf("0x38 EMMC NORMAL INT SIGNAL EN= %x \n", sdhci_readw(host, 0x38));
+    rt_kprintf("0x3a EMMC ERROR INT SIGNAL EN = %x \n", sdhci_readw(host, 0x3a));
+    rt_kprintf("0x3c EMMC_AUTO_CMD_STAT       = %x \n", sdhci_readw(host, 0x3c));
+    rt_kprintf("0x3e EMMC_HOST_CTRL2          = %x \n", sdhci_readw(host, 0x3e));
+    rt_kprintf("0x40 EMMC_CAPABILITIES1       = %x \n", sdhci_readl(host, 0x40));
+    rt_kprintf("0x44 EMMC_CAPABILITIES2       = %x \n", sdhci_readl(host, 0x44));
+    rt_kprintf("0x52 EMMC_FORC_ERR_INT_STAT   = %x \n", sdhci_readw(host, 0x52));
+    rt_kprintf("0x54 EMMC_ADMA_ERR_STAT       = %x \n", sdhci_readb(host, 0x54));
+    rt_kprintf("0x58 EMMC_ADMA_SA       = %x \n", sdhci_readl(host, 0x58));
+    rt_kprintf("0x66 EMMC_PRESET_SDR12        = %x \n", sdhci_readw(host, 0x66));
+    rt_kprintf("0x68 EMMC_PRESET_SDR25        = %x \n", sdhci_readw(host, 0x68));
+    rt_kprintf("0x6a EMMC_PRESET_SDR50        = %x \n", sdhci_readw(host, 0x6a));
+    rt_kprintf("0x6c EMMC_PRESET_SDR104       = %x \n", sdhci_readw(host, 0x6c));
+    rt_kprintf("0x6e EMMC_PRESET_DDR50        = %x \n", sdhci_readw(host, 0x6e));
+    rt_kprintf("0x78 EMMC_ADMA_ID             = %x \n", sdhci_readl(host, 0x78));
+    rt_kprintf("0xfe EMMC_HOST_CNTRL_VERS     = %x \n", sdhci_readw(host, 0xfe));
+
+}
+static inline rt_bool_t sdhci_has_requests(struct sdhci_host *host)
+{
+    return host->cmd || host->data_cmd;
+}
+
+static inline rt_bool_t sdhci_auto_cmd23(struct sdhci_host   *host,
+                                         struct rt_mmcsd_req *mrq)
+{
+    return mrq->sbc && (host->flags & SDHCI_AUTO_CMD23);
+}
+
+static inline rt_bool_t sdhci_auto_cmd12(struct sdhci_host   *host,
+                                         struct rt_mmcsd_req *mrq)
+{
+    return !mrq->sbc && (host->flags & SDHCI_AUTO_CMD12) && !mrq->cap_cmd_during_tfr;
+}
+
+static inline rt_bool_t sdhci_manual_cmd23(struct sdhci_host   *host,
+                                           struct rt_mmcsd_req *mrq)
+{
+    return mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23);
+}
+
+static inline rt_bool_t sdhci_data_line_cmd(struct rt_mmcsd_cmd *cmd)
+{
+    return cmd->data || cmd->flags & MMC_RSP_BUSY;
+}
+
+void sdhci_set_data_timeout_irq(struct sdhci_host *host, rt_bool_t enable)
+{
+    if (enable)
+        host->ier |= SDHCI_INT_DATA_TIMEOUT;
+    else
+        host->ier &= ~SDHCI_INT_DATA_TIMEOUT;
+    sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+    sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+}
+
+void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
+{
+    rt_uint16_t ctrl_2;
+
+    ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+    /* Select Bus Speed Mode for host */
+    ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
+    if ((timing == MMC_TIMING_MMC_HS200) || (timing == MMC_TIMING_UHS_SDR104))
+        ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
+    else if (timing == MMC_TIMING_UHS_SDR12)
+        ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
+    else if (timing == MMC_TIMING_UHS_SDR25)
+        ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
+    else if (timing == MMC_TIMING_UHS_SDR50)
+        ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
+    else if ((timing == MMC_TIMING_UHS_DDR50) || (timing == MMC_TIMING_MMC_DDR52))
+        ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
+    else if (timing == MMC_TIMING_MMC_HS400)
+        ctrl_2 |= SDHCI_CTRL_HS400; /* Non-standard */
+    sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
+}
+
+void sdhci_set_bus_width(struct sdhci_host *host, int width)
+{
+    rt_uint8_t ctrl;
+
+    ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
+    if (width == MMC_BUS_WIDTH_8)
+    {
+        ctrl &= ~SDHCI_CTRL_4BITBUS;
+        ctrl |= SDHCI_CTRL_8BITBUS;
+    }
+    else
+    {
+        if (host->mmc->caps & MMC_CAP_8_BIT_DATA)
+            ctrl &= ~SDHCI_CTRL_8BITBUS;
+        if (width == MMC_BUS_WIDTH_4)
+            ctrl |= SDHCI_CTRL_4BITBUS;
+        else
+            ctrl &= ~SDHCI_CTRL_4BITBUS;
+    }
+    sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+}
+
+static inline rt_bool_t sdhci_can_64bit_dma(struct sdhci_host *host)
+{
+    /*
+     * According to SD Host Controller spec v4.10, bit[27] added from
+     * version 4.10 in Capabilities Register is used as 64-bit System
+     * Address support for V4 mode.
+     */
+    if (host->version >= SDHCI_SPEC_410 && host->v4_mode)
+        return host->caps & SDHCI_CAN_64BIT_V4;
+
+    return host->caps & SDHCI_CAN_64BIT;
+}
+
+static void sdhci_do_enable_v4_mode(struct sdhci_host *host)
+{
+    rt_uint16_t ctrl2;
+
+    ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+    if (ctrl2 & SDHCI_CTRL_V4_MODE)
+        return;
+
+    ctrl2 |= SDHCI_CTRL_V4_MODE;
+    sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2);
+}
+
+void sdhci_cleanup_host(struct sdhci_host *host)
+{
+    struct mmc_host *mmc = host->mmc;
+
+    if (host->sdhci_core_to_disable_vqmmc)
+        regulator_disable(mmc->supply.vqmmc);
+
+    if (host->align_buffer)
+        dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz + host->adma_table_sz, host->align_buffer,
+                          host->align_addr);
+
+    host->adma_table   = NULL;
+    host->align_buffer = NULL;
+}
+
+static void sdhci_set_default_irqs(struct sdhci_host *host)
+{
+    host->ier = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE;
+
+    if (host->tuning_mode == SDHCI_TUNING_MODE_2 || host->tuning_mode == SDHCI_TUNING_MODE_3)
+        host->ier |= SDHCI_INT_RETUNE;
+
+    sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+    sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+}
+
+
+static inline void sdhci_auto_cmd_select(struct sdhci_host   *host,
+                                         struct rt_mmcsd_cmd *cmd,
+                                         rt_uint16_t         *mode)
+{
+    rt_bool_t   use_cmd12 = sdhci_auto_cmd12(host, cmd->mrq) && (cmd->cmd_code != SD_IO_RW_EXTENDED);
+    rt_bool_t   use_cmd23 = sdhci_auto_cmd23(host, cmd->mrq);
+    rt_uint16_t ctrl2;
+
+    /*
+     * In case of Version 4.10 or later, use of 'Auto CMD Auto
+     * Select' is recommended rather than use of 'Auto CMD12
+     * Enable' or 'Auto CMD23 Enable'. We require Version 4 Mode
+     * here because some controllers (e.g sdhci-of-dwmshc) expect it.
+     */
+    if (host->version >= SDHCI_SPEC_410 && host->v4_mode && (use_cmd12 || use_cmd23))
+    {
+        *mode |= SDHCI_TRNS_AUTO_SEL;
+
+        ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+        if (use_cmd23)
+            ctrl2 |= SDHCI_CMD23_ENABLE;
+        else
+            ctrl2 &= ~SDHCI_CMD23_ENABLE;
+        sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2);
+
+        return;
+    }
+
+    /*
+     * If we are sending CMD23, CMD12 never gets sent
+     * on successful completion (so no Auto-CMD12).
+     */
+    if (use_cmd12)
+        *mode |= SDHCI_TRNS_AUTO_CMD12;
+    else if (use_cmd23)
+        *mode |= SDHCI_TRNS_AUTO_CMD23;
+}
+
+
+static rt_bool_t sdhci_present_error(struct sdhci_host   *host,
+                                     struct rt_mmcsd_cmd *cmd, rt_bool_t present)
+{
+    if (!present || host->flags & SDHCI_DEVICE_DEAD)
+    {
+        cmd->err = -ENOMEDIUM;
+        return RT_TRUE;
+    }
+
+    return RT_FALSE;
+}
+
+static rt_uint16_t sdhci_get_preset_value(struct sdhci_host *host)
+{
+    rt_uint16_t preset = 0;
+
+    switch (host->timing)
+    {
+    case MMC_TIMING_MMC_HS:
+    case MMC_TIMING_SD_HS:
+        preset = sdhci_readw(host, SDHCI_PRESET_FOR_HIGH_SPEED);
+        break;
+    case MMC_TIMING_UHS_SDR12:
+        preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12);
+        break;
+    case MMC_TIMING_UHS_SDR25:
+        preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR25);
+        break;
+    case MMC_TIMING_UHS_SDR50:
+        preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR50);
+        break;
+    case MMC_TIMING_UHS_SDR104:
+    case MMC_TIMING_MMC_HS200:
+        preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR104);
+        break;
+    case MMC_TIMING_UHS_DDR50:
+    case MMC_TIMING_MMC_DDR52:
+        preset = sdhci_readw(host, SDHCI_PRESET_FOR_DDR50);
+        break;
+    case MMC_TIMING_MMC_HS400:
+        preset = sdhci_readw(host, SDHCI_PRESET_FOR_HS400);
+        break;
+    default:
+        preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12);
+        break;
+    }
+    return preset;
+}
+
+static void sdhci_set_card_detection(struct sdhci_host *host, rt_bool_t enable)
+{
+    rt_uint32_t present;
+
+    if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) || !mmc_card_is_removable(host->mmc))
+        return;
+
+    if (enable)
+    {
+        present = sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT;
+
+        host->ier |= present ? SDHCI_INT_CARD_REMOVE : SDHCI_INT_CARD_INSERT;
+    }
+    else
+    {
+        host->ier &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT);
+    }
+
+    sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+    sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+}
+
+static void sdhci_enable_card_detection(struct sdhci_host *host)
+{
+    sdhci_set_card_detection(host, RT_TRUE);
+}
+
+static inline int sdhci_external_dma_init(struct sdhci_host *host)
+{
+    return -EOPNOTSUPP;
+}
+
+static inline void sdhci_external_dma_release(struct sdhci_host *host)
+{
+}
+
+static inline void sdhci_external_dma_prepare_data(struct sdhci_host   *host,
+                                                   struct rt_mmcsd_cmd *cmd)
+{
+    /* This should never happen */
+}
+
+static inline void sdhci_external_dma_pre_transfer(struct sdhci_host   *host,
+                                                   struct rt_mmcsd_cmd *cmd)
+{
+}
+
+static inline struct dma_chan *sdhci_external_dma_channel(struct sdhci_host    *host,
+                                                          struct rt_mmcsd_data *data)
+{
+    return NULL;
+}
+
+/********************************************************* */
+/*                     reset                               */
+/********************************************************* */
+enum sdhci_reset_reason
+{
+    SDHCI_RESET_FOR_INIT,
+    SDHCI_RESET_FOR_REQUEST_ERROR,
+    SDHCI_RESET_FOR_REQUEST_ERROR_DATA_ONLY,
+    SDHCI_RESET_FOR_TUNING_ABORT,
+    SDHCI_RESET_FOR_CARD_REMOVED,
+    SDHCI_RESET_FOR_CQE_RECOVERY,
+};
+
+static rt_bool_t sdhci_needs_reset(struct sdhci_host *host, struct rt_mmcsd_req *mrq)
+{
+    return (!(host->flags & SDHCI_DEVICE_DEAD) && ((mrq->cmd && mrq->cmd->err) || (mrq->sbc && mrq->sbc->err) || (mrq->data && mrq->data->stop && mrq->data->stop->err) || (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST)));
+}
+
+static rt_bool_t sdhci_do_reset(struct sdhci_host *host, rt_uint8_t mask)
+{
+    if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET)
+    {
+        struct mmc_host *mmc = host->mmc;
+
+        if (!mmc->ops->get_cd(mmc))
+            return RT_FALSE;
+    }
+    if (host->ops->reset)
+    {
+        host->ops->reset(host, mask);
+    }
+    return RT_TRUE;
+}
+
+static void sdhci_reset_for_reason(struct sdhci_host *host, enum sdhci_reset_reason reason)
+{
+    if (host->quirks2 & SDHCI_QUIRK2_ISSUE_CMD_DAT_RESET_TOGETHER)
+    {
+        sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+        return;
+    }
+
+    switch (reason)
+    {
+    case SDHCI_RESET_FOR_INIT:
+        sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+        break;
+    case SDHCI_RESET_FOR_REQUEST_ERROR:
+    case SDHCI_RESET_FOR_TUNING_ABORT:
+    case SDHCI_RESET_FOR_CARD_REMOVED:
+    case SDHCI_RESET_FOR_CQE_RECOVERY:
+        sdhci_do_reset(host, SDHCI_RESET_CMD);
+        sdhci_do_reset(host, SDHCI_RESET_DATA);
+        break;
+    case SDHCI_RESET_FOR_REQUEST_ERROR_DATA_ONLY:
+        sdhci_do_reset(host, SDHCI_RESET_DATA);
+        break;
+    }
+}
+
+#define sdhci_reset_for(h, r) sdhci_reset_for_reason((h), SDHCI_RESET_FOR_##r)
+
+static void sdhci_reset_for_all(struct sdhci_host *host)
+{
+    if (sdhci_do_reset(host, SDHCI_RESET_ALL))
+    {
+        if (host->flags & (SDHCI_USE_SDMA))
+        {
+            if (host->ops->enable_dma)
+                host->ops->enable_dma(host);
+        }
+        /* Resetting the controller clears many */
+        host->preset_enabled = RT_FALSE;
+    }
+}
+
+
+static void sdhci_runtime_pm_bus_on(struct sdhci_host *host)
+{
+    if (host->bus_on)
+        return;
+    host->bus_on = RT_TRUE;
+}
+
+static void sdhci_runtime_pm_bus_off(struct sdhci_host *host)
+{
+    if (!host->bus_on)
+        return;
+    host->bus_on = RT_FALSE;
+}
+
+void sdhci_reset(struct sdhci_host *host, rt_uint8_t mask)
+{
+    ssize_t timeout;
+
+    sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET);
+
+    if (mask & SDHCI_RESET_ALL)
+    {
+        host->clock = 0;
+        /* Reset-all turns off SD Bus Power */
+        if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
+            sdhci_runtime_pm_bus_off(host);
+    }
+
+    timeout = rt_tick_from_millisecond(150);
+    while (1)
+    {
+        timeout = timeout - rt_tick_get();
+
+
+        if (!(sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask))
+            break;
+        if (timeout < 0)
+        {
+            rt_kprintf("%s: Reset 0x%x never completed.\n",
+                       mmc_hostname(host->mmc), (int)mask);
+            sdhci_dumpregs(host);
+            return;
+        }
+        rt_hw_us_delay(10);
+    }
+}
+
+/********************************************************* */
+/*                      data                               */
+/********************************************************* */
+static void sdhci_initialize_data(struct sdhci_host    *host,
+                                  struct rt_mmcsd_data *data)
+{
+    /* Sanity checks */
+    LOG_D(data->blksize * data->blks > 524288);
+    LOG_D(data->blksize > host->mmc->max_blk_size);
+    LOG_D(data->blks > 65535);
+
+    host->data               = data;
+    host->data_early         = 0;
+    host->data->bytes_xfered = 0;
+}
+
+static rt_ubase_t sdhci_sdma_address(struct sdhci_host *host)
+{
+    return (rt_ubase_t)rt_kmem_v2p(host->data->buf);
+}
+
+static void sdhci_set_adma_addr(struct sdhci_host *host, rt_uint32_t addr)
+{
+    sdhci_writel(host, lower_32_bits(addr), SDHCI_ADMA_ADDRESS);
+    if (host->flags & SDHCI_USE_64_BIT_DMA)
+        sdhci_writel(host, upper_32_bits(addr), SDHCI_ADMA_ADDRESS_HI);
+}
+
+static void sdhci_set_sdma_addr(struct sdhci_host *host, rt_uint32_t addr)
+{
+    if (host->v4_mode)
+        sdhci_set_adma_addr(host, addr);
+    else
+        sdhci_writel(host, addr, SDHCI_DMA_ADDRESS);
+}
+
+static void sdhci_config_dma(struct sdhci_host *host)
+{
+    rt_uint8_t  ctrl;
+    rt_uint16_t ctrl2;
+
+    if (host->version < SDHCI_SPEC_200)
+        return;
+
+    ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
+
+    /*
+     * Always adjust the DMA selection as some controllers
+     * (e.g. JMicron) can't do PIO properly when the selection
+     * is ADMA.
+     */
+    ctrl &= ~SDHCI_CTRL_DMA_MASK;
+    if (!(host->flags & SDHCI_REQ_USE_DMA))
+        goto out;
+
+    /* Note if DMA Select is zero then SDMA is selected */
+    if (host->flags & SDHCI_USE_64_BIT_DMA)
+    {
+        /*
+         * If v4 mode, all supported DMA can be 64-bit addressing if
+         * controller supports 64-bit system address, otherwise only
+         * ADMA can support 64-bit addressing.
+         */
+        if (host->v4_mode)
+        {
+            ctrl2  = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+            ctrl2 |= SDHCI_CTRL_64BIT_ADDR;
+            sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2);
+        }
+    }
+
+out:
+    sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+}
+
+static inline void sdhci_set_block_info(struct sdhci_host    *host,
+                                        struct rt_mmcsd_data *data)
+{
+    /* Set the DMA boundary value and block size */
+    sdhci_writew(host,
+                 SDHCI_MAKE_BLKSZ(7, data->blksize),
+                 SDHCI_BLOCK_SIZE);
+    /*
+     * For Version 4.10 onwards, if v4 mode is enabled, 32-bit Block Count
+     * can be supported, in that case 16-bit block count register must be 0.
+     */
+    if (host->version >= SDHCI_SPEC_410 && host->v4_mode && (host->quirks2 & SDHCI_QUIRK2_USE_32BIT_BLK_CNT))
+    {
+        if (sdhci_readw(host, SDHCI_BLOCK_COUNT))
+            sdhci_writew(host, 0, SDHCI_BLOCK_COUNT);
+        sdhci_writew(host, data->blks, SDHCI_32BIT_BLK_CNT);
+    }
+    else
+    {
+        sdhci_writew(host, data->blks, SDHCI_BLOCK_COUNT);
+    }
+}
+
+static void sdhci_set_transfer_irqs(struct sdhci_host *host)
+{
+    rt_uint32_t pio_irqs = SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL;
+    rt_uint32_t dma_irqs = SDHCI_INT_DMA_END;
+
+    if (host->flags & SDHCI_REQ_USE_DMA)
+        host->ier = (host->ier & ~pio_irqs) | dma_irqs;
+    else
+        host->ier = (host->ier & ~dma_irqs) | pio_irqs;
+
+    if (host->flags & (SDHCI_AUTO_CMD23 | SDHCI_AUTO_CMD12))
+        host->ier |= SDHCI_INT_AUTO_CMD_ERR;
+    else
+        host->ier &= ~SDHCI_INT_AUTO_CMD_ERR;
+    sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+    sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+}
+
+static void sdhci_prepare_data(struct sdhci_host *host, struct rt_mmcsd_cmd *cmd)
+{
+    struct rt_mmcsd_data *data = cmd->data;
+
+    sdhci_initialize_data(host, data);
+
+    if (host->flags & SDHCI_USE_SDMA)
+    {
+        unsigned int length_mask, offset_mask;
+
+        host->flags |= SDHCI_REQ_USE_DMA;
+
+        /*
+         * FIXME: This doesn't account for merging when mapping the
+         * scatterlist.
+         *
+         * The assumption here being that alignment and lengths are
+         * the same after DMA mapping to device address space.
+         */
+        length_mask = 0;
+        offset_mask = 0;
+        if (host->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE)
+            length_mask = 3;
+        if (host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR)
+            offset_mask = 3;
+
+
+        if (length_mask | offset_mask)
+        {
+            host->flags &= ~SDHCI_REQ_USE_DMA;
+        }
+    }
+
+    sdhci_config_dma(host);
+
+    if (host->flags & SDHCI_REQ_USE_DMA)
+    {
+        if (mmc_get_dma_dir(data) == DMA_FROM_DEVICE)
+            rt_hw_cpu_dcache_ops(RT_HW_CACHE_INVALIDATE, data->buf, data->blks * data->blksize);
+        else
+            rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, data->buf, data->blks * data->blksize);
+
+        sdhci_set_sdma_addr(host, sdhci_sdma_address(host));
+    }
+
+    if (!(host->flags & SDHCI_REQ_USE_DMA))
+    {
+        host->blocks = data->blks;
+    }
+
+    sdhci_set_transfer_irqs(host);
+
+    sdhci_set_block_info(host, data);
+}
+
+static void sdhci_set_mrq_done(struct sdhci_host *host, struct rt_mmcsd_req *mrq)
+{
+    int i;
+
+    for (i = 0; i < SDHCI_MAX_MRQS; i++)
+    {
+        if (host->mrqs_done[i] == mrq)
+        {
+            LOG_D(1);
+            return;
+        }
+    }
+
+    for (i = 0; i < SDHCI_MAX_MRQS; i++)
+    {
+        if (!host->mrqs_done[i])
+        {
+            host->mrqs_done[i] = mrq;
+            break;
+        }
+    }
+
+    LOG_D(i >= SDHCI_MAX_MRQS);
+}
+
+static inline rt_bool_t sdhci_defer_done(struct sdhci_host   *host,
+                                         struct rt_mmcsd_req *mrq)
+{
+    struct rt_mmcsd_data *data = mrq->data;
+
+    return host->pending_reset || host->always_defer_done || ((host->flags & SDHCI_REQ_USE_DMA) && data && data->host_cookie == COOKIE_MAPPED);
+}
+
+
+/********************************************************* */
+/*                        pio                              */
+/********************************************************* */
+
+static void sdhci_read_block_pio(struct sdhci_host *host,void **buf)
+{
+    rt_uint32_t scratch;
+    size_t      len;
+    rt_uint32_t blksize = host->data->blksize;
+    while (blksize)
+    {
+        len = min(4U, blksize);
+
+        scratch = sdhci_readl(host, SDHCI_BUFFER);
+        rt_memcpy(*buf, &scratch, len);
+
+        *buf     += len;
+        blksize -= len;
+    }
+}
+
+static void sdhci_write_block_pio(struct sdhci_host *host,void **buf)
+{
+    size_t      blksize, len;
+    rt_uint32_t scratch;
+    LOG_D("PIO writing\n");
+
+    blksize   = host->data->blksize;
+    scratch   = 0;
+    while (blksize)
+    {
+        len = min(4U, blksize);
+        rt_memcpy(&scratch, *buf, len);
+        *buf     += len;
+        blksize -= len;
+        sdhci_writel(host, scratch, SDHCI_BUFFER);
+    }
+}
+
+static void sdhci_transfer_pio(struct sdhci_host *host)
+{
+    rt_uint32_t mask;
+
+    if (host->blocks == 0)
+        return;
+
+    if (host->data->flags & DATA_DIR_READ)
+        mask = SDHCI_DATA_AVAILABLE;
+    else
+        mask = SDHCI_SPACE_AVAILABLE;
+
+    /*
+     * Some controllers (JMicron JMB38x) mess up the buffer bits
+     * for transfers < 4 bytes. As long as it is just one block,
+     * we can ignore the bits.
+     */
+    if ((host->quirks & SDHCI_QUIRK_BROKEN_SMALL_PIO) && (host->data->blks == 1))
+    {
+        mask = ~0;
+    }
+    void *buf = (void *)host->data->buf;
+    while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask)
+    {
+        if (host->quirks & SDHCI_QUIRK_PIO_NEEDS_DELAY)
+            rt_hw_us_delay(100);
+
+        if (host->data->flags & DATA_DIR_READ)
+            sdhci_read_block_pio(host,&buf);
+        else
+            sdhci_write_block_pio(host,&buf);
+
+        host->data->blks--;
+        if (host->data->blks == 0)
+            break;
+
+        /* host->data->buf += host->data->blksize;*/
+    }
+}
+
+/********************************************************* */
+/*                   config                                */
+/********************************************************* */
+
+
+static rt_bool_t sdhci_timing_has_preset(unsigned char timing)
+{
+    switch (timing)
+    {
+    case MMC_TIMING_UHS_SDR12:
+    case MMC_TIMING_UHS_SDR25:
+    case MMC_TIMING_UHS_SDR50:
+    case MMC_TIMING_UHS_SDR104:
+    case MMC_TIMING_UHS_DDR50:
+    case MMC_TIMING_MMC_DDR52:
+        return RT_TRUE;
+    }
+    return RT_FALSE;
+}
+
+static rt_bool_t sdhci_preset_needed(struct sdhci_host *host, unsigned char timing)
+{
+    return !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) && sdhci_timing_has_preset(timing);
+}
+
+static rt_bool_t sdhci_presetable_values_change(struct sdhci_host *host, struct rt_mmcsd_io_cfg *ios)
+{
+    /*
+     * Preset Values are: Driver Strength, Clock Generator and SDCLK/RCLK
+     * Frequency. Check if preset values need to be enabled, or the Driver
+     * Strength needs updating. Note, clock changes are handled separately.
+     */
+    return !host->preset_enabled && (sdhci_preset_needed(host, ios->timing) || host->drv_type != ios->drv_type);
+}
+
+
+static void sdhci_enable_preset_value(struct sdhci_host *host, rt_bool_t enable)
+{
+    /* Host Controller v3.00 defines preset value registers */
+    if (host->version < SDHCI_SPEC_300)
+        return;
+
+    /*
+     * We only enable or disable Preset Value if they are not already
+     * enabled or disabled respectively. Otherwise, we bail out.
+     */
+    if (host->preset_enabled != enable)
+    {
+        rt_uint16_t ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+
+        if (enable)
+            ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE;
+        else
+            ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
+
+        sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+
+        if (enable)
+            host->flags |= SDHCI_PV_ENABLED;
+        else
+            host->flags &= ~SDHCI_PV_ENABLED;
+
+        host->preset_enabled = enable;
+    }
+}
+
+static void sdhci_set_power_reg(struct sdhci_host *host, unsigned char mode,
+                                unsigned short vdd)
+{
+    struct mmc_host *mmc = host->mmc;
+
+    mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
+
+    if (mode != MMC_POWER_OFF)
+        sdhci_writeb(host, SDHCI_POWER_ON, SDHCI_POWER_CONTROL);
+    else
+        sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
+}
+
+void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode,
+                           unsigned short vdd)
+{
+    rt_uint8_t pwr = 0;
+
+    if (mode != MMC_POWER_OFF)
+    {
+        switch (1 << vdd)
+        {
+        case MMC_VDD_165_195:
+        /*
+         * Without a regulator, SDHCI does not support 2.0v
+         * so we only get here if the driver deliberately
+         * added the 2.0v range to ocr_avail. Map it to 1.8v
+         * for the purpose of turning on the power.
+         */
+        case MMC_VDD_20_21:
+            pwr = SDHCI_POWER_180;
+            break;
+        case MMC_VDD_29_30:
+        case MMC_VDD_30_31:
+            pwr = SDHCI_POWER_300;
+            break;
+        case MMC_VDD_32_33:
+        case MMC_VDD_33_34:
+        /*
+         * 3.4 ~ 3.6V are valid only for those platforms where it's
+         * known that the voltage range is supported by hardware.
+         */
+        case MMC_VDD_34_35:
+        case MMC_VDD_35_36:
+            pwr = SDHCI_POWER_330;
+            break;
+        default:
+            break;
+        }
+    }
+
+    if (host->pwr == pwr)
+        return;
+
+    host->pwr = pwr;
+
+    if (pwr == 0)
+    {
+        sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
+        if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
+            sdhci_runtime_pm_bus_off(host);
+    }
+    else
+    {
+        /*
+         * Spec says that we should clear the power reg before setting
+         * a new value. Some controllers don't seem to like this though.
+         */
+        if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
+            sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
+
+        /*
+         * At least the Marvell CaFe chip gets confused if we set the
+         * voltage and set turn on power at the same time, so set the
+         * voltage first.
+         */
+        if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)
+            sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+
+        pwr |= SDHCI_POWER_ON;
+
+        sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+
+        if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
+            sdhci_runtime_pm_bus_on(host);
+
+        /*
+         * Some controllers need an extra 10ms delay of 10ms before
+         * they can apply clock after applying power
+         */
+        if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
+            rt_thread_mdelay(10);
+    }
+}
+
+void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
+                     unsigned short vdd)
+{
+    if (!host->mmc->supply.vmmc)
+        sdhci_set_power_noreg(host, mode, vdd);
+    else
+        sdhci_set_power_reg(host, mode, vdd);
+}
+
+
+int sdhci_start_signal_voltage_switch(struct mmc_host        *mmc,
+                                      struct rt_mmcsd_io_cfg *ios)
+{
+    struct sdhci_host *host = mmc_priv(mmc);
+    rt_uint16_t        ctrl;
+    int                ret;
+
+    /*
+     * Signal Voltage Switching is only applicable for Host Controllers
+     * v3.00 and above.
+     */
+    if (host->version < SDHCI_SPEC_300)
+        return 0;
+
+    ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+
+    switch (ios->signal_voltage)
+    {
+    case MMC_SIGNAL_VOLTAGE_330:
+        if (!(host->flags & SDHCI_SIGNALING_330))
+            return -EINVAL;
+        /* Set 1.8V Signal Enable in the Host Control2 register to 0 */
+        ctrl &= ~SDHCI_CTRL_VDD_180;
+        sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+
+        if (!mmc->supply.vqmmc)
+        {
+            ret = mmc_regulator_set_vqmmc(mmc, ios);
+            if (ret < 0)
+            {
+                return -EIO;
+            }
+        }
+        /* Wait for 5ms */
+        rt_thread_mdelay(5);
+        /* 3.3V regulator output should be stable within 5 ms */
+        ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+        if (!(ctrl & SDHCI_CTRL_VDD_180))
+            return 0;
+        return -EAGAIN;
+    case MMC_SIGNAL_VOLTAGE_180:
+        if (!(host->flags & SDHCI_SIGNALING_180))
+            return -EINVAL;
+        if (!mmc->supply.vqmmc)
+        {
+            ret = mmc_regulator_set_vqmmc(mmc, ios);
+            if (ret < 0)
+            {
+                LOG_D("%s: Switching to 1.8V signalling voltage failed\n",
+                      mmc_hostname(mmc));
+                return -EIO;
+            }
+        }
+
+        /*
+         * Enable 1.8V Signal Enable in the Host Control2
+         * register
+         */
+        ctrl |= SDHCI_CTRL_VDD_180;
+        sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+
+        /* Some controller need to do more when switching */
+        if (host->ops->voltage_switch)
+            host->ops->voltage_switch(host);
+
+        /* 1.8V regulator output should be stable within 5 ms */
+        ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+        if (ctrl & SDHCI_CTRL_VDD_180)
+            return 0;
+
+        LOG_D("%s: 1.8V regulator output did not become stable\n",
+              mmc_hostname(mmc));
+
+        return -EAGAIN;
+    case MMC_SIGNAL_VOLTAGE_120:
+        if (!(host->flags & SDHCI_SIGNALING_120))
+            return -EINVAL;
+        if (!mmc->supply.vqmmc)
+        {
+            ret = mmc_regulator_set_vqmmc(mmc, ios);
+            if (ret < 0)
+            {
+                LOG_D("%s: Switching to 1.2V signalling voltage failed\n",
+                      mmc_hostname(mmc));
+                return -EIO;
+            }
+        }
+        return 0;
+    default:
+        /* No signal voltage switch required */
+        return 0;
+    }
+}
+
+
+static int sdhci_get_cd(struct mmc_host *mmc)
+{
+    struct sdhci_host *host    = mmc_priv(mmc);
+    int                gpio_cd = mmc_gpio_get_cd(mmc);
+
+    if (host->flags & SDHCI_DEVICE_DEAD)
+        return 0;
+
+    /* If nonremovable, assume that the card is always present. */
+    if (!mmc_card_is_removable(mmc))
+        return 1;
+
+    /*
+     * Try slot gpio detect, if defined it take precedence
+     * over build in controller functionality
+     */
+    if (gpio_cd >= 0)
+        return !!gpio_cd;
+
+    /* If polling, assume that the card is always present. */
+    if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
+        return 1;
+
+    /* Host native card detect */
+    return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
+}
+
+static int sdhci_check_ro(struct sdhci_host *host)
+{
+    int       is_readonly;
+    rt_base_t flags;
+    flags = rt_spin_lock_irqsave(&host->lock);
+
+    if (host->flags & SDHCI_DEVICE_DEAD)
+        is_readonly = 0;
+    else if (host->ops->get_ro)
+        is_readonly = host->ops->get_ro(host);
+    else if (mmc_can_gpio_ro(host->mmc))
+        is_readonly = mmc_gpio_get_ro(host->mmc);
+    else
+        is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE)
+                        & SDHCI_WRITE_PROTECT);
+
+    rt_spin_unlock_irqrestore(&host->lock, flags);
+
+    /* This quirk needs to be replaced by a callback-function later */
+    return host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT ? !is_readonly : is_readonly;
+}
+
+#define SAMPLE_COUNT 5
+static int sdhci_get_ro(struct mmc_host *mmc)
+{
+    struct sdhci_host *host = mmc_priv(mmc);
+    int                i, ro_count;
+
+    if (!(host->quirks & SDHCI_QUIRK_UNSTABLE_RO_DETECT))
+        return sdhci_check_ro(host);
+
+    ro_count = 0;
+    for (i = 0; i < SAMPLE_COUNT; i++)
+    {
+        if (sdhci_check_ro(host))
+        {
+            if (++ro_count > SAMPLE_COUNT / 2)
+                return 1;
+        }
+        rt_thread_mdelay(30);
+    }
+    return 0;
+}
+
+static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable)
+{
+    if (!(host->flags & SDHCI_DEVICE_DEAD))
+    {
+        if (enable)
+            host->ier |= SDHCI_INT_CARD_INT;
+        else
+            host->ier &= ~SDHCI_INT_CARD_INT;
+
+        sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+        sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+    }
+}
+
+static void sdhci_ack_sdio_irq(struct mmc_host *mmc)
+{
+    rt_base_t          flags;
+    struct sdhci_host *host = mmc_priv(mmc);
+    flags                   = rt_spin_lock_irqsave(&host->lock);
+    sdhci_enable_sdio_irq_nolock(host, RT_TRUE);
+    rt_spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static void sdhci_del_timer(struct sdhci_host *host, struct rt_mmcsd_req *mrq)
+{
+    if (sdhci_data_line_cmd(mrq->cmd))
+        rt_timer_stop(&host->data_timer);
+    else
+        rt_timer_stop(&host->timer);
+}
+
+static unsigned int sdhci_target_timeout(struct sdhci_host    *host,
+                                         struct rt_mmcsd_cmd  *cmd,
+                                         struct rt_mmcsd_data *data)
+{
+    unsigned int target_timeout;
+
+    /* timeout in us */
+    if (!data)
+    {
+        target_timeout = cmd->busy_timeout * 1000;
+    }
+    else
+    {
+        target_timeout = DIV_ROUND_UP(data->timeout_ns, 1000);
+        if (host->clock && data->timeout_clks)
+        {
+            rt_uint32_t val;
+
+            /*
+             * data->timeout_clks is in units of clock cycles.
+             * host->clock is in Hz.  target_timeout is in us.
+             * Hence, us = 1000000 * cycles / Hz.  Round up.
+             */
+            val = 1000000ULL * data->timeout_clks;
+            if (do_div(val, host->clock))
+                target_timeout++;
+            target_timeout += val;
+        }
+    }
+
+    return target_timeout;
+}
+
+static rt_uint8_t sdhci_calc_timeout(struct sdhci_host *host, struct rt_mmcsd_cmd *cmd,
+                                     rt_bool_t *too_big)
+{
+    rt_uint8_t            count;
+    struct rt_mmcsd_data *data;
+    unsigned              target_timeout, current_timeout;
+
+    *too_big = RT_FALSE;
+
+    /*
+     * If the host controller provides us with an incorrect timeout
+     * value, just skip the check and use the maximum. The hardware may take
+     * longer to time out, but that's much better than having a too-short
+     * timeout value.
+    */
+    if (host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL)
+        return host->max_timeout_count;
+
+    /* Unspecified command, assume max */
+    if (cmd == NULL)
+        return host->max_timeout_count;
+
+    data = cmd->data;
+    /* Unspecified timeout, assume max */
+    if (!data && !cmd->busy_timeout)
+        return host->max_timeout_count;
+
+    /* timeout in us */
+    target_timeout = sdhci_target_timeout(host, cmd, data);
+
+    /*
+     * Figure out needed cycles.
+     * We do this in steps in order to fit inside a 32 bit int.
+     * The first step is the minimum timeout, which will have a
+     * minimum resolution of 6 bits:
+     * (1) 2^13*1000 > 2^22,
+     * (2) host->timeout_clk < 2^16
+     *     =>
+     *     (1) / (2) > 2^6
+     */
+    count           = 0;
+    current_timeout = (1 << 13) * 1000 / host->timeout_clk;
+    while (current_timeout < target_timeout)
+    {
+        count++;
+        current_timeout <<= 1;
+        if (count > host->max_timeout_count)
+        {
+            if (!(host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT))
+                LOG_D("Too large timeout 0x%x requested for CMD%d!\n",
+                      count, cmd->cmd_code);
+            count    = host->max_timeout_count;
+            *too_big = RT_TRUE;
+            break;
+        }
+    }
+
+    return count;
+}
+
+static void sdhci_calc_sw_timeout(struct sdhci_host   *host,
+                                  struct rt_mmcsd_cmd *cmd)
+{
+    struct rt_mmcsd_data   *data      = cmd->data;
+    struct mmc_host        *mmc       = host->mmc;
+    struct rt_mmcsd_io_cfg *ios       = &mmc->ios;
+    unsigned char           bus_width = 1 << ios->bus_width;
+    unsigned int            blksz;
+    unsigned int            freq;
+    rt_uint64_t             target_timeout;
+    rt_uint64_t             transfer_time;
+
+    target_timeout  = sdhci_target_timeout(host, cmd, data);
+    target_timeout *= 1000L;
+
+    if (data)
+    {
+        blksz         = data->blksize;
+        freq          = mmc->actual_clock ?: host->clock;
+        transfer_time = (rt_uint64_t)blksz * 1000000000L * (8 / bus_width);
+        do_div(transfer_time, freq);
+        /* multiply by '2' to account for any unknowns */
+        transfer_time = transfer_time * 2;
+        /* calculate timeout for the entire data */
+        host->data_timeout = data->blks * target_timeout + transfer_time;
+    }
+    else
+    {
+        host->data_timeout = target_timeout;
+    }
+
+    if (host->data_timeout)
+        host->data_timeout += MMC_CMD_TRANSFER_TIME;
+}
+
+
+void __sdhci_set_timeout(struct sdhci_host *host, struct rt_mmcsd_cmd *cmd)
+{
+    rt_bool_t  too_big = RT_FALSE;
+    rt_uint8_t count   = sdhci_calc_timeout(host, cmd, &too_big);
+
+    if (too_big && host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT)
+    {
+        sdhci_calc_sw_timeout(host, cmd);
+        sdhci_set_data_timeout_irq(host, RT_FALSE);
+    }
+    else if (!(host->ier & SDHCI_INT_DATA_TIMEOUT))
+    {
+        sdhci_set_data_timeout_irq(host, RT_FALSE);
+    }
+
+    sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL);
+}
+
+static void sdhci_set_timeout(struct sdhci_host *host, struct rt_mmcsd_cmd *cmd)
+{
+    if (host->ops->set_timeout)
+        host->ops->set_timeout(host, cmd);
+    else
+        __sdhci_set_timeout(host, cmd);
+}
+
+static void sdhci_mod_timer(struct sdhci_host *host, struct rt_mmcsd_req *mrq,
+                            unsigned long timeout)
+{
+    if (sdhci_data_line_cmd(mrq->cmd))
+    {
+        rt_tick_t tick = rt_tick_get();
+
+        if (timeout < tick)
+        {
+            timeout = tick;
+        }
+        tick = timeout - tick;
+
+        rt_timer_stop(&host->data_timer);
+        rt_timer_control(&host->data_timer, RT_TIMER_CTRL_SET_TIME, &tick);
+        rt_timer_start(&host->data_timer);
+    }
+    else
+    {
+        rt_tick_t tick = rt_tick_get();
+
+        if (timeout < tick)
+        {
+            timeout = tick;
+        }
+        tick = timeout - tick;
+
+        rt_timer_stop(&host->timer);
+        rt_timer_control(&host->timer, RT_TIMER_CTRL_SET_TIME, &tick);
+        rt_timer_start(&host->timer);
+    }
+}
+
+static void __sdhci_finish_mrq(struct sdhci_host *host, struct rt_mmcsd_req *mrq)
+{
+    if (host->cmd && host->cmd->mrq == mrq)
+        host->cmd = NULL;
+
+    if (host->data_cmd && host->data_cmd->mrq == mrq)
+        host->data_cmd = NULL;
+
+    if (host->deferred_cmd && host->deferred_cmd->mrq == mrq)
+        host->deferred_cmd = NULL;
+
+    if (host->data && host->data->mrq == mrq)
+        host->data = NULL;
+
+    if (sdhci_needs_reset(host, mrq))
+        host->pending_reset = RT_TRUE;
+
+    sdhci_set_mrq_done(host, mrq);
+
+    sdhci_del_timer(host, mrq);
+}
+
+static void sdhci_finish_mrq(struct sdhci_host *host, struct rt_mmcsd_req *mrq)
+{
+    __sdhci_finish_mrq(host, mrq);
+
+    rt_workqueue_submit_work(host->complete_wq, &host->complete_work, 0);
+}
+
+static void sdhci_error_out_mrqs(struct sdhci_host *host, int err)
+{
+    if (host->data_cmd)
+    {
+        host->data_cmd->err = err;
+        sdhci_finish_mrq(host, host->data_cmd->mrq);
+    }
+
+    if (host->cmd)
+    {
+        host->cmd->err = err;
+        sdhci_finish_mrq(host, host->cmd->mrq);
+    }
+}
+
+static void sdhci_card_event(struct mmc_host *mmc)
+{
+    struct sdhci_host *host = mmc_priv(mmc);
+    rt_uint32_t        flags;
+    int                present;
+
+    /* First check if client has provided their own card event */
+    if (host->ops->card_event)
+        host->ops->card_event(host);
+
+    present = mmc->ops->get_cd(mmc);
+
+    flags = rt_spin_lock_irqsave(&host->lock);
+
+    /* Check sdhci_has_requests() first in case we are runtime suspended */
+    if (sdhci_has_requests(host) && !present)
+    {
+        rt_kprintf("%s: Card removed during transfer!\n",
+                   mmc_hostname(mmc));
+        rt_kprintf("%s: Resetting controller.\n",
+                   mmc_hostname(mmc));
+
+        sdhci_do_reset(host, SDHCI_RESET_CMD);
+        sdhci_do_reset(host, SDHCI_RESET_DATA);
+        sdhci_error_out_mrqs(host, -ENOMEDIUM);
+    }
+
+    rt_spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static int sdhci_card_busy(struct mmc_host *mmc)
+{
+    struct sdhci_host *host = mmc_priv(mmc);
+    rt_uint32_t        present_state;
+
+    /* Check whether DAT[0] is 0 */
+    present_state = sdhci_readl(host, SDHCI_PRESENT_STATE);
+
+    return !(present_state & SDHCI_DATA_0_LVL_MASK);
+}
+
+
+static int sdhci_prepare_hs400_tuning(struct mmc_host *mmc, struct rt_mmcsd_io_cfg *ios)
+{
+    struct sdhci_host *host = mmc_priv(mmc);
+    rt_uint32_t        flags;
+
+    flags        = rt_spin_lock_irqsave(&host->lock);
+    host->flags |= SDHCI_HS400_TUNING;
+    rt_spin_unlock_irqrestore(&host->lock, flags);
+
+    return 0;
+}
+
+
+static void sdhci_set_transfer_mode(struct sdhci_host   *host,
+                                    struct rt_mmcsd_cmd *cmd)
+{
+    rt_uint16_t           mode = 0;
+    struct rt_mmcsd_data *data = cmd->data;
+
+    if (data == NULL)
+    {
+        if (host->quirks2 & SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD)
+        {
+            /* must not clear SDHCI_TRANSFER_MODE when tuning */
+            if (!mmc_op_tuning(cmd->cmd_code))
+                sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE);
+        }
+        else
+        {
+            /* clear Auto CMD settings for no data CMDs */
+            mode = sdhci_readw(host, SDHCI_TRANSFER_MODE);
+            sdhci_writew(host, mode & ~(SDHCI_TRNS_AUTO_CMD12 | SDHCI_TRNS_AUTO_CMD23), SDHCI_TRANSFER_MODE);
+        }
+        return;
+    }
+
+
+    if (!(host->quirks2 & SDHCI_QUIRK2_SUPPORT_SINGLE))
+        mode = SDHCI_TRNS_BLK_CNT_EN;
+
+    if (mmc_op_multi(cmd->cmd_code) || data->blks > 1)
+    {
+        mode = SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_MULTI;
+        sdhci_auto_cmd_select(host, cmd, &mode);
+        if (sdhci_auto_cmd23(host, cmd->mrq))
+            sdhci_writel(host, cmd->mrq->sbc->arg, SDHCI_ARGUMENT2);
+    }
+
+    if (data->flags & DATA_DIR_READ)
+        mode |= SDHCI_TRNS_READ;
+    if (host->flags & SDHCI_REQ_USE_DMA)
+        mode |= SDHCI_TRNS_DMA;
+
+    sdhci_writew(host, mode, SDHCI_TRANSFER_MODE);
+}
+
+static rt_bool_t sdhci_send_command(struct sdhci_host *host, struct rt_mmcsd_cmd *cmd)
+{
+    int           flags;
+    rt_uint32_t   mask;
+    unsigned long timeout;
+    /* Initially, a command has no error */
+    cmd->err = 0;
+
+    if ((host->quirks2 & SDHCI_QUIRK2_STOP_WITH_TC) && cmd->cmd_code == MMC_STOP_TRANSMISSION)
+        cmd->flags |= MMC_RSP_BUSY;
+
+    mask = SDHCI_CMD_INHIBIT;
+    if (sdhci_data_line_cmd(cmd))
+        mask |= SDHCI_DATA_INHIBIT;
+
+    /* We shouldn't wait for data inihibit for stop commands, even
+       though they might use busy signaling */
+    if (cmd->mrq->data && (cmd == cmd->mrq->data->stop))
+        mask &= ~SDHCI_DATA_INHIBIT;
+
+    if (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask)
+        return RT_FALSE;
+
+    host->cmd          = cmd;
+    host->data_timeout = 0;
+    if (sdhci_data_line_cmd(cmd))
+    {
+        host->data_cmd = cmd;
+        sdhci_set_timeout(host, cmd);
+    }
+
+    if (cmd->data)
+    {
+        if (host->use_external_dma)
+            sdhci_external_dma_prepare_data(host, cmd);
+        else
+            sdhci_prepare_data(host, cmd);
+    }
+    sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT);
+
+    sdhci_set_transfer_mode(host, cmd);
+
+    if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY))
+    {
+        /*
+         * This does not happen in practice because 136-bit response
+         * commands never have busy waiting, so rather than complicate
+         * the error path, just remove busy waiting and continue.
+         */
+        cmd->flags &= ~MMC_RSP_BUSY;
+    }
+
+    if (!(cmd->flags & MMC_RSP_PRESENT))
+        flags = SDHCI_CMD_RESP_NONE;
+    else if (cmd->flags & MMC_RSP_136)
+        flags = SDHCI_CMD_RESP_LONG;
+    else if (cmd->flags & MMC_RSP_BUSY)
+        flags = SDHCI_CMD_RESP_SHORT_BUSY;
+    else
+        flags = SDHCI_CMD_RESP_SHORT;
+
+    if (cmd->flags & MMC_RSP_CRC)
+        flags |= SDHCI_CMD_CRC;
+    if (cmd->flags & MMC_RSP_OPCODE)
+        flags |= SDHCI_CMD_INDEX;
+
+    /* CMD19 is special in that the Data Present Select should be set */
+    if (cmd->data || mmc_op_tuning(cmd->cmd_code))
+        flags |= SDHCI_CMD_DATA;
+
+    timeout = rt_tick_get();
+    if (host->data_timeout)
+        timeout += rt_tick_from_millisecond(host->data_timeout * 1000);
+    else if (!cmd->data && cmd->busy_timeout > 9000)
+        timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * RT_TICK_PER_SECOND + RT_TICK_PER_SECOND;
+    else
+        timeout += 10 * RT_TICK_PER_SECOND;
+    sdhci_mod_timer(host, cmd->mrq, timeout);
+
+    if (host->use_external_dma)
+        sdhci_external_dma_pre_transfer(host, cmd);
+
+    sdhci_writew(host, SDHCI_MAKE_CMD(cmd->cmd_code, flags), SDHCI_COMMAND);
+    return RT_TRUE;
+}
+
+/********************************************************* */
+/*                        dma                              */
+/********************************************************* */
+static void __sdhci_finish_data(struct sdhci_host *host, rt_bool_t sw_data_timeout)
+{
+    struct rt_mmcsd_cmd  *data_cmd = host->data_cmd;
+    struct rt_mmcsd_data *data     = host->data;
+
+    host->data     = NULL;
+    host->data_cmd = NULL;
+
+    /*
+     * The controller needs a reset of internal state machines upon error
+     * conditions.
+     */
+    if (data->err)
+    {
+        if (!host->cmd || host->cmd == data_cmd)
+            sdhci_reset_for(host, REQUEST_ERROR);
+        else
+            sdhci_reset_for(host, REQUEST_ERROR_DATA_ONLY);
+    }
+
+    /*
+     * The specification states that the block count register must
+     * be updated, but it does not specify at what point in the
+     * data flow. That makes the register entirely useless to read
+     * back so we have to assume that nothing made it to the card
+     * in the event of an error.
+     */
+    if (data->err)
+    {
+        data->bytes_xfered = 0;
+    }
+    else
+    {
+        data->bytes_xfered = data->blksize * data->blks;
+    }
+    /*
+     * Need to send CMD12 if -
+     * a) open-ended multiblock transfer not using auto CMD12 (no CMD23)
+     * b) error in multiblock transfer
+     */
+    if (data->stop && ((!data->mrq->sbc && !sdhci_auto_cmd12(host, data->mrq)) || data->err))
+    {
+        /*
+         * 'cap_cmd_during_tfr' request must not use the command line
+         * after mmc_command_done() has been called. It is upper layer's
+         * responsibility to send the stop command if required.
+         */
+        if (data->mrq->cap_cmd_during_tfr)
+        {
+            __sdhci_finish_mrq(host, data->mrq);
+        }
+        else
+        {
+            /* Avoid triggering warning in sdhci_send_command() */
+            host->cmd = NULL;
+            if (!sdhci_send_command(host, data->stop))
+            {
+                if (sw_data_timeout)
+                {
+                    /*
+                     * This is anyway a sw data timeout, so
+                     * give up now.
+                     */
+                    data->stop->err = -EIO;
+                    __sdhci_finish_mrq(host, data->mrq);
+                }
+                else
+                {
+                    host->deferred_cmd = data->stop;
+                }
+            }
+        }
+    }
+    else
+    {
+        __sdhci_finish_mrq(host, data->mrq);
+    }
+}
+
+static void sdhci_finish_data(struct sdhci_host *host)
+{
+    __sdhci_finish_data(host, RT_FALSE);
+}
+
+
+/********************************************************* */
+/*                     irq                                 */
+/********************************************************* */
+static void sdhci_data_irq(struct sdhci_host *host, rt_uint32_t intmask)
+{
+    rt_uint32_t command;
+    /*
+     * CMD19 generates _only_ Buffer Read Ready interrupt if
+     * use sdhci_send_tuning.
+     * Need to exclude this case: PIO mode and use mmc_send_tuning,
+     * If not, sdhci_transfer_pio will never be called, make the
+     * SDHCI_INT_DATA_AVAIL always there, stuck in irq storm.
+     */
+    if (intmask & SDHCI_INT_DATA_AVAIL && !host->data)
+    {
+        command = SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND));
+        if (command == MMC_SEND_TUNING_BLOCK || command == MMC_SEND_TUNING_BLOCK_HS200)
+        {
+            host->tuning_done = 1;
+            rt_wqueue_wakeup(&host->buf_ready_int, 0);
+            return;
+        }
+    }
+
+    if (!host->data)
+    {
+        struct rt_mmcsd_cmd *data_cmd = host->data_cmd;
+
+        /*
+         * The "data complete" interrupt is also used to
+         * indicate that a busy state has ended. See comment
+         * above in sdhci_cmd_irq().
+         */
+        if (data_cmd && (data_cmd->flags & MMC_RSP_BUSY))
+        {
+            if (intmask & SDHCI_INT_DATA_TIMEOUT)
+            {
+                host->data_cmd = NULL;
+                data_cmd->err  = -ETIMEDOUT;
+                __sdhci_finish_mrq(host, data_cmd->mrq);
+                return;
+            }
+            if (intmask & SDHCI_INT_DATA_END)
+            {
+                host->data_cmd = NULL;
+                /*
+                 * Some cards handle busy-end interrupt
+                 * before the command completed, so make
+                 * sure we do things in the proper order.
+                 */
+                if (host->cmd == data_cmd)
+                    return;
+
+                __sdhci_finish_mrq(host, data_cmd->mrq);
+                return;
+            }
+        }
+
+        /*
+         * SDHCI recovers from errors by resetting the cmd and data
+         * circuits. Until that is done, there very well might be more
+         * interrupts, so ignore them in that case.
+         */
+        if (host->pending_reset)
+            return;
+        rt_kprintf("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n",
+                   mmc_hostname(host->mmc), (unsigned)intmask);
+        sdhci_dumpregs(host);
+
+        return;
+    }
+
+    if (intmask & SDHCI_INT_DATA_TIMEOUT)
+        host->data->err = -ETIMEDOUT;
+    else if (intmask & SDHCI_INT_DATA_END_BIT)
+        host->data->err = -EILSEQ;
+    else if ((intmask & SDHCI_INT_DATA_CRC) && SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)) != MMC_BUS_TEST_R)
+    {
+        host->data->err = -EILSEQ;
+    }
+    if (host->data->err)
+    {
+        sdhci_finish_data(host);
+    }
+    else
+    {
+        if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL))
+            sdhci_transfer_pio(host);
+
+        /*
+         * We currently don't do anything fancy with DMA
+         * boundaries, but as we can't disable the feature
+         * we need to at least restart the transfer.
+         *
+         * According to the spec sdhci_readl(host, SDHCI_DMA_ADDRESS)
+         * should return a valid address to continue from, but as
+         * some controllers are faulty, don't trust them.
+         */
+        if (intmask & SDHCI_INT_DMA_END)
+        {
+            rt_uint32_t dmastart, dmanow;
+
+            dmastart = sdhci_sdma_address(host);
+            dmanow   = dmastart + host->data->bytes_xfered;
+            /*
+             * Force update to the next DMA block boundary.
+             */
+            dmanow                   = (dmanow & ~((rt_uint32_t)SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) + SDHCI_DEFAULT_BOUNDARY_SIZE;
+            host->data->bytes_xfered = dmanow - dmastart;
+            LOG_D("DMA base %pad, transferred 0x%06x bytes, next %pad\n",
+                  &dmastart, host->data->bytes_xfered, &dmanow);
+            sdhci_set_sdma_addr(host, dmanow);
+        }
+
+        if (intmask & SDHCI_INT_DATA_END)
+        {
+            if (host->cmd == host->data_cmd)
+            {
+                /*
+                 * Data managed to finish before the
+                 * command completed. Make sure we do
+                 * things in the proper order.
+                 */
+                host->data_early = 1;
+            }
+            else
+            {
+                sdhci_finish_data(host);
+            }
+        }
+    }
+}
+
+static void sdhci_read_rsp_136(struct sdhci_host *host, struct rt_mmcsd_cmd *cmd)
+{
+    int i, reg;
+
+    for (i = 0; i < 4; i++)
+    {
+        reg          = SDHCI_RESPONSE + (3 - i) * 4;
+        cmd->resp[i] = sdhci_readl(host, reg);
+    }
+
+    if (host->quirks2 & SDHCI_QUIRK2_RSP_136_HAS_CRC)
+        return;
+
+    /* CRC is stripped so we need to do some shifting */
+    for (i = 0; i < 4; i++)
+    {
+        cmd->resp[i] <<= 8;
+        if (i != 3)
+            cmd->resp[i] |= cmd->resp[i + 1] >> 24;
+    }
+}
+
+static void sdhci_finish_command(struct sdhci_host *host)
+{
+    struct rt_mmcsd_cmd *cmd = host->cmd;
+
+    host->cmd = NULL;
+
+    if (cmd->flags & MMC_RSP_PRESENT)
+    {
+        if (cmd->flags & MMC_RSP_136)
+        {
+            sdhci_read_rsp_136(host, cmd);
+        }
+        else
+        {
+            cmd->resp[0] = sdhci_readl(host, SDHCI_RESPONSE);
+        }
+    }
+    /*
+     * The host can send and interrupt when the busy state has
+     * ended, allowing us to wait without wasting CPU cycles.
+     * The busy signal uses DAT0 so this is similar to waiting
+     * for data to complete.
+     *
+     * Note: The 1.0 specification is a bit ambiguous about this
+     *       feature so there might be some problems with older
+     *       controllers.
+     */
+    if (cmd->flags & MMC_RSP_BUSY)
+    {
+        if (cmd->data)
+        {
+            LOG_D("Cannot wait for busy signal when also doing a data transfer");
+        }
+        else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ) && cmd == host->data_cmd)
+        {
+            /* Command complete before busy is ended */
+            return;
+        }
+    }
+
+    /* Finished CMD23, now send actual command. */
+    if (cmd == cmd->mrq->sbc)
+    {
+        if (!sdhci_send_command(host, cmd->mrq->cmd))
+        {
+            host->deferred_cmd = cmd->mrq->cmd;
+        }
+    }
+    else
+    {
+        /* Processed actual command. */
+        if (host->data && host->data_early)
+            sdhci_finish_data(host);
+
+        if (!cmd->data)
+            __sdhci_finish_mrq(host, cmd->mrq);
+    }
+}
+
+
+static void sdhci_cmd_irq(struct sdhci_host *host, rt_uint32_t intmask, rt_uint32_t *intmask_p)
+{
+    /* Handle auto-CMD12 error */
+    if (intmask & SDHCI_INT_AUTO_CMD_ERR && host->data_cmd)
+    {
+        struct rt_mmcsd_req *mrq             = host->data_cmd->mrq;
+        rt_uint16_t          auto_cmd_status = sdhci_readw(host, SDHCI_AUTO_CMD_STATUS);
+        int                  data_err_bit    = (auto_cmd_status & SDHCI_AUTO_CMD_TIMEOUT) ? SDHCI_INT_DATA_TIMEOUT : SDHCI_INT_DATA_CRC;
+
+        /* Treat auto-CMD12 error the same as data error */
+        if (!mrq->sbc && (host->flags & SDHCI_AUTO_CMD12))
+        {
+            *intmask_p |= data_err_bit;
+            return;
+        }
+    }
+
+    if (!host->cmd)
+    {
+        /*
+         * SDHCI recovers from errors by resetting the cmd and data
+         * circuits.  Until that is done, there very well might be more
+         * interrupts, so ignore them in that case.
+         */
+        if (host->pending_reset)
+            return;
+        rt_kprintf("%s: Got command interrupt 0x%08x even though no command operation was in progress.\n",
+                   mmc_hostname(host->mmc), (unsigned)intmask);
+        sdhci_dumpregs(host);
+        return;
+    }
+    if (intmask & (SDHCI_INT_TIMEOUT | SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX))
+    {
+        if (intmask & SDHCI_INT_TIMEOUT)
+            host->cmd->err = -ETIMEDOUT;
+        else
+            host->cmd->err = -EILSEQ;
+
+        /* Treat data command CRC error the same as data CRC error */
+        if (host->cmd->data && (intmask & (SDHCI_INT_CRC | SDHCI_INT_TIMEOUT)) == SDHCI_INT_CRC)
+        {
+            host->cmd   = NULL;
+            *intmask_p |= SDHCI_INT_DATA_CRC;
+            return;
+        }
+
+        __sdhci_finish_mrq(host, host->cmd->mrq);
+        return;
+    }
+
+    /* Handle auto-CMD23 error */
+    if (intmask & SDHCI_INT_AUTO_CMD_ERR)
+    {
+        struct rt_mmcsd_req *mrq             = host->cmd->mrq;
+        rt_uint16_t          auto_cmd_status = sdhci_readw(host, SDHCI_AUTO_CMD_STATUS);
+        int                  err             = (auto_cmd_status & SDHCI_AUTO_CMD_TIMEOUT) ? -ETIMEDOUT : -EILSEQ;
+
+        if (mrq->sbc && (host->flags & SDHCI_AUTO_CMD23))
+        {
+            mrq->sbc->err = err;
+            __sdhci_finish_mrq(host, mrq);
+            return;
+        }
+    }
+
+    if (intmask & SDHCI_INT_RESPONSE)
+        sdhci_finish_command(host);
+}
+
+static void sdhci_irq(int irq, void *dev_id)
+{
+    struct rt_mmcsd_req *mrqs_done[SDHCI_MAX_MRQS] = {0};
+    struct sdhci_host   *host                      = dev_id;
+    rt_uint32_t          intmask, mask, unexpected = 0;
+    int                  max_loops = 16;
+    int                  i, result;
+    rt_spin_lock(&host->lock);
+
+    if (host->runtime_suspended)
+    {
+        rt_spin_unlock(&host->lock);
+    }
+
+    intmask = sdhci_readl(host, SDHCI_INT_STATUS);
+    if (!intmask || intmask == 0xffffffff)
+    {
+        result = 0;
+        goto out;
+    }
+
+    do {
+        LOG_D("IRQ status 0x%08x\n", intmask);
+
+        if (host->ops->irq)
+        {
+            intmask = host->ops->irq(host, intmask);
+            if (!intmask)
+                goto cont;
+        }
+
+        /* Clear selected interrupts. */
+        mask = intmask & (SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | SDHCI_INT_BUS_POWER);
+        sdhci_writel(host, mask, SDHCI_INT_STATUS);
+
+        if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE))
+        {
+            rt_uint32_t present = sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT;
+
+            /*
+             * There is a observation on i.mx esdhc.  INSERT
+             * bit will be immediately set again when it gets
+             * cleared, if a card is inserted.  We have to mask
+             * the irq to prevent interrupt storm which will
+             * freeze the system.  And the REMOVE gets the
+             * same situation.
+             *
+             * More testing are needed here to ensure it works
+             * for other platforms though.
+             */
+            host->ier &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
+            host->ier |= present ? SDHCI_INT_CARD_REMOVE : SDHCI_INT_CARD_INSERT;
+            sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+            sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+
+            sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
+
+            host->thread_isr |= intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
+            result            = RT_EOK;
+        }
+
+        if (intmask & SDHCI_INT_CMD_MASK)
+            sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK, &intmask);
+
+        if (intmask & SDHCI_INT_DATA_MASK)
+            sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
+
+        if (intmask & SDHCI_INT_BUS_POWER)
+            rt_kprintf("%s: Card is consuming too much power!\n",
+                       mmc_hostname(host->mmc));
+
+        intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE | SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | SDHCI_INT_ERROR | SDHCI_INT_BUS_POWER | SDHCI_INT_RETUNE | SDHCI_INT_CARD_INT);
+
+        if (intmask)
+        {
+            unexpected |= intmask;
+            sdhci_writel(host, intmask, SDHCI_INT_STATUS);
+        }
+    cont:
+        intmask = sdhci_readl(host, SDHCI_INT_STATUS);
+    } while (intmask && --max_loops);
+
+    /* Determine if mrqs can be completed immediately */
+    for (i = 0; i < SDHCI_MAX_MRQS; i++)
+    {
+        struct rt_mmcsd_req *mrq = host->mrqs_done[i];
+
+        if (!mrq)
+            continue;
+
+        if (sdhci_defer_done(host, mrq))
+        {
+            result = RT_EOK;
+        }
+        else
+        {
+            mrqs_done[i]       = mrq;
+            host->mrqs_done[i] = NULL;
+        }
+    }
+out:
+    if (host->deferred_cmd)
+        result = RT_EOK;
+
+    rt_spin_unlock(&host->lock);
+
+    /* Process mrqs ready for immediate completion */
+    for (i = 0; i < SDHCI_MAX_MRQS; i++)
+    {
+        if (!mrqs_done[i])
+            continue;
+
+        if (host->ops->request_done)
+            host->ops->request_done(host, mrqs_done[i]);
+        else
+            mmc_request_done(host->mmc, mrqs_done[i]);
+    }
+
+    if (unexpected)
+    {
+        sdhci_dumpregs(host);
+    }
+
+    if (result == RT_EOK)
+    {
+        rt_workqueue_submit_work(host->irq_wq, &host->irq_work, 0);
+    }
+}
+
+static rt_bool_t sdhci_send_command_retry(struct sdhci_host   *host,
+                                          struct rt_mmcsd_cmd *cmd,
+                                          unsigned long        flags)
+{
+    struct rt_mmcsd_cmd *deferred_cmd = host->deferred_cmd;
+    int                  timeout      = 10; /* Approx. 10 ms */
+    rt_bool_t            present;
+    while (!sdhci_send_command(host, cmd))
+    {
+        if (!timeout--)
+        {
+            rt_kprintf("%s: Controller never released inhibit bit(s).\n",
+                       mmc_hostname(host->mmc));
+            sdhci_dumpregs(host);
+            cmd->err = -EIO;
+            return RT_FALSE;
+        }
+
+        rt_spin_unlock_irqrestore(&host->lock, flags);
+
+        rt_thread_mdelay(1);
+
+        present = host->mmc->ops->get_cd(host->mmc);
+
+        flags = rt_spin_lock_irqsave(&host->lock);
+
+        /* A deferred command might disappear, handle that */
+        if (cmd == deferred_cmd && cmd != host->deferred_cmd)
+            return RT_TRUE;
+
+        if (sdhci_present_error(host, cmd, present))
+            return RT_FALSE;
+    }
+
+    if (cmd == host->deferred_cmd)
+        host->deferred_cmd = NULL;
+
+    return RT_TRUE;
+}
+
+static rt_bool_t sdhci_request_done(struct sdhci_host *host)
+{
+    rt_base_t            flags;
+    struct rt_mmcsd_req *mrq;
+    int                  i;
+
+    flags = rt_spin_lock_irqsave(&host->lock);
+
+    for (i = 0; i < SDHCI_MAX_MRQS; i++)
+    {
+        mrq = host->mrqs_done[i];
+        if (mrq)
+            break;
+    }
+
+    if (!mrq)
+    {
+        rt_spin_unlock_irqrestore(&host->lock, flags);
+        return RT_TRUE;
+    }
+
+    /*
+     * The controller needs a reset of internal state machines
+     * upon error conditions.
+     */
+    if (sdhci_needs_reset(host, mrq))
+    {
+        /*
+         * Do not finish until command and data lines are available for
+         * reset. Note there can only be one other mrq, so it cannot
+         * also be in mrqs_done, otherwise host->cmd and host->data_cmd
+         * would both be null.
+         */
+        if (host->cmd || host->data_cmd)
+        {
+            rt_spin_unlock_irqrestore(&host->lock, flags);
+            return RT_TRUE;
+        }
+
+        /* Some controllers need this kick or reset won't work here */
+        if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)
+            /* This is to force an update */
+            host->ops->set_clock(host, host->clock);
+
+        sdhci_do_reset(host, SDHCI_RESET_CMD);
+        sdhci_do_reset(host, SDHCI_RESET_DATA);
+
+        host->pending_reset = RT_FALSE;
+    }
+
+    /*
+     * Always unmap the data buffers if they were mapped by
+     * sdhci_prepare_data() whenever we finish with a request.
+     * This avoids leaking DMA mappings on error.
+     */
+    if (host->flags & SDHCI_REQ_USE_DMA)
+    {
+        struct rt_mmcsd_data *data = mrq->data;
+
+        if (host->use_external_dma && data && (mrq->cmd->err || data->err))
+        {
+            host->mrqs_done[i] = NULL;
+            sdhci_set_mrq_done(host, mrq);
+        }
+    }
+
+    host->mrqs_done[i] = NULL;
+
+    rt_spin_unlock_irqrestore(&host->lock, flags);
+
+    if (host->ops->request_done)
+        host->ops->request_done(host, mrq);
+    else
+        mmc_request_done(host->mmc, mrq);
+
+    return RT_FALSE;
+}
+
+
+static void sdhci_thread_irq(struct rt_work *work, void *work_data)
+{
+    struct sdhci_host   *host = work_data;
+    struct rt_mmcsd_cmd *cmd;
+    rt_base_t            flags;
+    rt_uint32_t          isr;
+
+    while (!sdhci_request_done(host));
+
+    flags = rt_spin_lock_irqsave(&host->lock);
+
+    isr              = host->thread_isr;
+    host->thread_isr = 0;
+
+    cmd = host->deferred_cmd;
+    if (cmd && !sdhci_send_command_retry(host, cmd, flags))
+        sdhci_finish_mrq(host, cmd->mrq);
+
+    rt_spin_unlock_irqrestore(&host->lock, flags);
+
+    if (isr & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE))
+    {
+        struct mmc_host *mmc = host->mmc;
+
+        mmc->ops->card_event(mmc);
+    }
+}
+
+
+void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+    struct sdhci_host *host = mmc_priv(mmc);
+    rt_uint32_t        flags;
+
+    flags = rt_spin_lock_irqsave(&host->lock);
+    sdhci_enable_sdio_irq_nolock(host, enable);
+    rt_spin_unlock_irqrestore(&host->lock, flags);
+}
+
+
+/********************************************************* */
+/*                     request                             */
+/********************************************************* */
+
+void sdhci_request(struct mmc_host *mmc, struct rt_mmcsd_req *mrq)
+{
+    struct sdhci_host   *host = mmc_priv(mmc);
+    struct rt_mmcsd_cmd *cmd;
+    rt_base_t            flags;
+    rt_bool_t            present;
+
+    /* Firstly check card presence */
+    present = mmc->ops->get_cd(mmc);
+
+    flags = rt_spin_lock_irqsave(&host->lock);
+
+    if (sdhci_present_error(host, mrq->cmd, present))
+        goto out_finish;
+
+    cmd = sdhci_manual_cmd23(host, mrq) ? mrq->sbc : mrq->cmd;
+
+    if (!sdhci_send_command_retry(host, cmd, flags))
+        goto out_finish;
+
+    rt_spin_unlock_irqrestore(&host->lock, flags);
+
+    return;
+
+out_finish:
+    sdhci_finish_mrq(host, mrq);
+    rt_spin_unlock_irqrestore(&host->lock, flags);
+}
+
+
+static void sdhci_complete_work(struct rt_work *work, void *work_data)
+{
+    struct sdhci_host *host = work_data;
+
+    while (!sdhci_request_done(host));
+}
+
+
+/********************************************************* */
+/*                     timer                               */
+/********************************************************* */
+static void sdhci_timeout_timer(void *parameter)
+{
+    struct sdhci_host *host = parameter;
+    rt_base_t          flags;
+
+    flags = rt_spin_lock_irqsave(&host->lock);
+
+    if (host->cmd && !sdhci_data_line_cmd(host->cmd))
+    {
+        rt_kprintf("%s: Timeout waiting for hardware cmd interrupt.\n",
+                   mmc_hostname(host->mmc));
+        sdhci_dumpregs(host);
+
+        host->cmd->err = -ETIMEDOUT;
+        sdhci_finish_mrq(host, host->cmd->mrq);
+    }
+
+    rt_spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static void sdhci_timeout_data_timer(void *parameter)
+{
+    struct sdhci_host *host = parameter;
+    rt_base_t          flags;
+
+    flags = rt_spin_lock_irqsave(&host->lock);
+
+    if (host->data || host->data_cmd || (host->cmd && sdhci_data_line_cmd(host->cmd)))
+    {
+        rt_kprintf("%s: Timeout waiting for hardware interrupt.\n",
+                   mmc_hostname(host->mmc));
+        sdhci_dumpregs(host);
+
+        if (host->data)
+        {
+            host->data->err = -ETIMEDOUT;
+            __sdhci_finish_data(host, RT_TRUE);
+            rt_workqueue_submit_work(host->complete_wq, &host->complete_work, 0);
+        }
+        else if (host->data_cmd)
+        {
+            host->data_cmd->err = -ETIMEDOUT;
+            sdhci_finish_mrq(host, host->data_cmd->mrq);
+        }
+        else
+        {
+            host->cmd->err = -ETIMEDOUT;
+            sdhci_finish_mrq(host, host->cmd->mrq);
+        }
+    }
+
+    rt_spin_unlock_irqrestore(&host->lock, flags);
+}
+
+
+/********************************************************* */
+/*                     tuning                              */
+/********************************************************* */
+int sdhci_execute_tuning(struct mmc_host *mmc, rt_uint32_t opcode)
+{
+    struct sdhci_host *host         = mmc_priv(mmc);
+    int                err          = 0;
+    unsigned int       tuning_count = 0;
+    rt_bool_t          hs400_tuning;
+
+    hs400_tuning = host->flags & SDHCI_HS400_TUNING;
+
+    if (host->tuning_mode == SDHCI_TUNING_MODE_1)
+        tuning_count = host->tuning_count;
+
+    /*
+     * The Host Controller needs tuning in case of SDR104 and DDR50
+     * mode, and for SDR50 mode when Use Tuning for SDR50 is set in
+     * the Capabilities register.
+     * If the Host Controller supports the HS200 mode then the
+     * tuning function has to be executed.
+     */
+    switch (host->timing)
+    {
+    /* HS400 tuning is done in HS200 mode */
+    case MMC_TIMING_MMC_HS400:
+        err = -EINVAL;
+        goto out;
+
+    case MMC_TIMING_MMC_HS200:
+        /*
+         * Periodic re-tuning for HS400 is not expected to be needed, so
+         * disable it here.
+         */
+        if (hs400_tuning)
+            tuning_count = 0;
+        break;
+
+    case MMC_TIMING_UHS_SDR104:
+    case MMC_TIMING_UHS_DDR50:
+        break;
+
+    case MMC_TIMING_UHS_SDR50:
+        if (host->flags & SDHCI_SDR50_NEEDS_TUNING)
+            break;
+        fallthrough;
+
+    default:
+        goto out;
+    }
+
+    if (host->ops->platform_execute_tuning)
+    {
+        err = host->ops->platform_execute_tuning(host, opcode);
+        goto out;
+    }
+
+    mmc->retune_period = tuning_count;
+
+    if (host->tuning_delay < 0)
+        host->tuning_delay = opcode == MMC_SEND_TUNING_BLOCK;
+
+    sdhci_start_tuning(host);
+
+    host->tuning_err = __sdhci_execute_tuning(host, opcode);
+
+    sdhci_end_tuning(host);
+out:
+    host->flags &= ~SDHCI_HS400_TUNING;
+
+    return err;
+}
+
+int __sdhci_execute_tuning(struct sdhci_host *host, rt_uint32_t opcode)
+{
+    int i;
+
+    /*
+     * Issue opcode repeatedly till Execute Tuning is set to 0 or the number
+     * of loops reaches tuning loop count.
+     */
+    for (i = 0; i < host->tuning_loop_count; i++)
+    {
+        rt_uint16_t ctrl;
+
+        sdhci_send_tuning(host, opcode);
+
+        if (!host->tuning_done)
+        {
+            sdhci_abort_tuning(host, opcode);
+            return -ETIMEDOUT;
+        }
+
+        /* Spec does not require a delay between tuning cycles */
+        if (host->tuning_delay > 0)
+            rt_thread_mdelay(host->tuning_delay);
+
+        ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+        if (!(ctrl & SDHCI_CTRL_EXEC_TUNING))
+        {
+            if (ctrl & SDHCI_CTRL_TUNED_CLK)
+                return 0; /* Success! */
+            break;
+        }
+    }
+
+    LOG_D("%s: Tuning failed, falling back to fixed sampling clock\n",
+          mmc_hostname(host->mmc));
+    sdhci_reset_tuning(host);
+    return -EAGAIN;
+}
+
+void sdhci_start_tuning(struct sdhci_host *host)
+{
+    rt_uint16_t ctrl;
+
+    ctrl  = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+    ctrl |= SDHCI_CTRL_EXEC_TUNING;
+    if (host->quirks2 & SDHCI_QUIRK2_TUNING_WORK_AROUND)
+        ctrl |= SDHCI_CTRL_TUNED_CLK;
+    sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+
+    /*
+     * As per the Host Controller spec v3.00, tuning command
+     * generates Buffer Read Ready interrupt, so enable that.
+     *
+     * Note: The spec clearly says that when tuning sequence
+     * is being performed, the controller does not generate
+     * interrupts other than Buffer Read Ready interrupt. But
+     * to make sure we don't hit a controller bug, we _only_
+     * enable Buffer Read Ready interrupt here.
+     */
+    sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
+    sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
+}
+
+void sdhci_end_tuning(struct sdhci_host *host)
+{
+    sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+    sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+}
+
+void sdhci_abort_tuning(struct sdhci_host *host, rt_uint32_t opcode)
+{
+    sdhci_reset_tuning(host);
+
+    sdhci_reset_for(host, TUNING_ABORT);
+
+    sdhci_end_tuning(host);
+}
+
+void sdhci_send_tuning(struct sdhci_host *host, rt_uint32_t opcode)
+{
+    struct mmc_host    *mmc = host->mmc;
+    struct rt_mmcsd_cmd cmd = {};
+    struct rt_mmcsd_req mrq = {};
+    unsigned long       flags;
+    rt_uint32_t         b = host->sdma_boundary;
+
+    flags = rt_spin_lock_irqsave(&host->lock);
+
+    cmd.cmd_code = opcode;
+    cmd.flags    = MMC_RSP_R1 | MMC_CMD_ADTC;
+    cmd.mrq      = &mrq;
+
+    mrq.cmd = &cmd;
+    /*
+     * In response to CMD19, the card sends 64 bytes of tuning
+     * block to the Host Controller. So we set the block size
+     * to 64 here.
+     */
+    if (cmd.cmd_code == MMC_SEND_TUNING_BLOCK_HS200 && mmc->ios.bus_width == MMC_BUS_WIDTH_8)
+        sdhci_writew(host, SDHCI_MAKE_BLKSZ(b, 128), SDHCI_BLOCK_SIZE);
+    else
+        sdhci_writew(host, SDHCI_MAKE_BLKSZ(b, 64), SDHCI_BLOCK_SIZE);
+
+    /*
+     * The tuning block is sent by the card to the host controller.
+     * So we set the TRNS_READ bit in the Transfer Mode register.
+     * This also takes care of setting DMA Enable and Multi Block
+     * Select in the same register to 0.
+     */
+    sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
+
+    if (!sdhci_send_command_retry(host, &cmd, flags))
+    {
+        rt_spin_unlock_irqrestore(&host->lock, flags);
+        host->tuning_done = 0;
+        return;
+    }
+
+    host->cmd = NULL;
+
+    sdhci_del_timer(host, &mrq);
+
+    host->tuning_done = 0;
+
+    rt_spin_unlock_irqrestore(&host->lock, flags);
+}
+
+void sdhci_reset_tuning(struct sdhci_host *host)
+{
+    rt_uint16_t ctrl;
+
+    ctrl  = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+    ctrl &= ~SDHCI_CTRL_TUNED_CLK;
+    ctrl &= ~SDHCI_CTRL_EXEC_TUNING;
+    sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+}
+
+
+/********************************************************* */
+/*                     error                               */
+/********************************************************* */
+
+void sdhci_dumpregs(struct sdhci_host *host)
+{
+#define SDHCI_DUMP rt_kprintf
+    SDHCI_DUMP("============ SDHCI REGISTER DUMP ===========\n");
+
+    SDHCI_DUMP("Sys addr:  0x%08x | Version:  0x%08x\n",
+               sdhci_readl(host, SDHCI_DMA_ADDRESS),
+               sdhci_readw(host, SDHCI_HOST_VERSION));
+    SDHCI_DUMP("Blk size:  0x%08x | Blk cnt:  0x%08x\n",
+               sdhci_readw(host, SDHCI_BLOCK_SIZE),
+               sdhci_readw(host, SDHCI_BLOCK_COUNT));
+    SDHCI_DUMP("Argument:  0x%08x | Trn mode: 0x%08x\n",
+               sdhci_readl(host, SDHCI_ARGUMENT),
+               sdhci_readw(host, SDHCI_TRANSFER_MODE));
+    SDHCI_DUMP("Present:   0x%08x | Host ctl: 0x%08x\n",
+               sdhci_readl(host, SDHCI_PRESENT_STATE),
+               sdhci_readb(host, SDHCI_HOST_CONTROL));
+    SDHCI_DUMP("Power:     0x%08x | Blk gap:  0x%08x\n",
+               sdhci_readb(host, SDHCI_POWER_CONTROL),
+               sdhci_readb(host, SDHCI_BLOCK_GAP_CONTROL));
+    SDHCI_DUMP("Wake-up:   0x%08x | Clock:    0x%08x\n",
+               sdhci_readb(host, SDHCI_WAKE_UP_CONTROL),
+               sdhci_readw(host, SDHCI_CLOCK_CONTROL));
+    SDHCI_DUMP("Timeout:   0x%08x | Int stat: 0x%08x\n",
+               sdhci_readb(host, SDHCI_TIMEOUT_CONTROL),
+               sdhci_readl(host, SDHCI_INT_STATUS));
+    SDHCI_DUMP("Int enab:  0x%08x | Sig enab: 0x%08x\n",
+               sdhci_readl(host, SDHCI_INT_ENABLE),
+               sdhci_readl(host, SDHCI_SIGNAL_ENABLE));
+    SDHCI_DUMP("ACmd stat: 0x%08x | Slot int: 0x%08x\n",
+               sdhci_readw(host, SDHCI_AUTO_CMD_STATUS),
+               sdhci_readw(host, SDHCI_SLOT_INT_STATUS));
+    SDHCI_DUMP("Caps:      0x%08x | Caps_1:   0x%08x\n",
+               sdhci_readl(host, SDHCI_CAPABILITIES),
+               sdhci_readl(host, SDHCI_CAPABILITIES_1));
+    SDHCI_DUMP("Cmd:       0x%08x | Max curr: 0x%08x\n",
+               sdhci_readw(host, SDHCI_COMMAND),
+               sdhci_readl(host, SDHCI_MAX_CURRENT));
+    SDHCI_DUMP("Resp[0]:   0x%08x | Resp[1]:  0x%08x\n",
+               sdhci_readl(host, SDHCI_RESPONSE),
+               sdhci_readl(host, SDHCI_RESPONSE + 4));
+    SDHCI_DUMP("Resp[2]:   0x%08x | Resp[3]:  0x%08x\n",
+               sdhci_readl(host, SDHCI_RESPONSE + 8),
+               sdhci_readl(host, SDHCI_RESPONSE + 12));
+    SDHCI_DUMP("Host ctl2: 0x%08x\n",
+               sdhci_readw(host, SDHCI_HOST_CONTROL2));
+
+
+    if (host->ops->dump_vendor_regs)
+        host->ops->dump_vendor_regs(host);
+
+    SDHCI_DUMP("============================================\n");
+}
+
+
+static const struct mmc_host_ops sdhci_ops = {
+    .request                     = sdhci_request,
+    .set_ios                     = sdhci_set_ios,
+    .get_cd                      = sdhci_get_cd,
+    .get_ro                      = sdhci_get_ro,
+    .enable_sdio_irq             = sdhci_enable_sdio_irq,
+    .ack_sdio_irq                = sdhci_ack_sdio_irq,
+    .start_signal_voltage_switch = sdhci_start_signal_voltage_switch,
+    .prepare_hs400_tuning        = sdhci_prepare_hs400_tuning,
+    .execute_tuning              = sdhci_execute_tuning,
+    .card_event                  = sdhci_card_event,
+    .card_busy                   = sdhci_card_busy,
+};
+
+
+void sdhci_remove_host(struct sdhci_host *host, int dead)
+{
+    struct mmc_host *mmc = host->mmc;
+    unsigned long    flags;
+
+    if (dead)
+    {
+        flags = rt_spin_lock_irqsave(&host->lock);
+
+        host->flags |= SDHCI_DEVICE_DEAD;
+
+        if (sdhci_has_requests(host))
+        {
+            rt_kprintf("%s: Controller removed during "
+                       " transfer!\n",
+                       mmc_hostname(mmc));
+            sdhci_error_out_mrqs(host, -ENOMEDIUM);
+        }
+
+        rt_spin_unlock_irqrestore(&host->lock, flags);
+    }
+
+    sdhci_set_card_detection(host, RT_FALSE);
+
+    mmc_remove_host(mmc);
+
+
+    if (!dead)
+        sdhci_reset_for_all(host);
+
+    sdhci_writel(host, 0, SDHCI_INT_ENABLE);
+    sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
+
+    rt_timer_delete(&host->timer);
+    rt_timer_delete(&host->data_timer);
+
+    rt_workqueue_destroy(host->complete_wq);
+
+    if (host->use_external_dma)
+        sdhci_external_dma_release(host);
+
+    host->align_buffer = NULL;
+}
+
+rt_uint16_t sdhci_calc_clk(struct sdhci_host *host, unsigned int clock,
+                           unsigned int *actual_clock)
+{
+    int         div      = 0; /* Initialized for compiler warning */
+    int         real_div = div, clk_mul = 1;
+    rt_uint16_t clk             = 0;
+    rt_bool_t   switch_base_clk = RT_FALSE;
+
+    if (host->version >= SDHCI_SPEC_300)
+    {
+        if (host->preset_enabled)
+        {
+            rt_uint16_t pre_val;
+
+            clk     = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+            pre_val = sdhci_get_preset_value(host);
+            div     = FIELD_GET(SDHCI_PRESET_SDCLK_FREQ_MASK, pre_val);
+            if (host->clk_mul && (pre_val & SDHCI_PRESET_CLKGEN_SEL))
+            {
+                clk      = SDHCI_PROG_CLOCK_MODE;
+                real_div = div + 1;
+                clk_mul  = host->clk_mul;
+            }
+            else
+            {
+                real_div = max_t(int, 1, div << 1);
+            }
+            goto clock_set;
+        }
+
+        /*
+         * Check if the Host Controller supports Programmable Clock
+         * Mode.
+         */
+        if (host->clk_mul)
+        {
+            for (div = 1; div <= 1024; div++)
+            {
+                if ((host->max_clk * host->clk_mul / div)
+                    <= clock)
+                    break;
+            }
+            if ((host->max_clk * host->clk_mul / div) <= clock)
+            {
+                /*
+                 * Set Programmable Clock Mode in the Clock
+                 * Control register.
+                 */
+                clk      = SDHCI_PROG_CLOCK_MODE;
+                real_div = div;
+                clk_mul  = host->clk_mul;
+                div--;
+            }
+            else
+            {
+                /*
+                 * Divisor can be too small to reach clock
+                 * speed requirement. Then use the base clock.
+                 */
+                switch_base_clk = RT_TRUE;
+            }
+        }
+
+        if (!host->clk_mul || switch_base_clk)
+        {
+            /* Version 3.00 divisors must be a multiple of 2. */
+            if (host->max_clk <= clock)
+                div = 1;
+            else
+            {
+                for (div  = 2; div < SDHCI_MAX_DIV_SPEC_300;
+                     div += 2)
+                {
+                    if ((host->max_clk / div) <= clock)
+                        break;
+                }
+            }
+            real_div   = div;
+            div      >>= 1;
+            if ((host->quirks2 & SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN)
+                && !div && host->max_clk <= 25000000)
+                div = 1;
+        }
+    }
+    else
+    {
+        /* Version 2.00 divisors must be a power of 2. */
+        for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2)
+        {
+            if ((host->max_clk / div) <= clock)
+                break;
+        }
+        real_div   = div;
+        div      >>= 1;
+    }
+
+clock_set:
+    if (real_div)
+        *actual_clock = (host->max_clk * clk_mul) / real_div;
+    clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
+    clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
+           << SDHCI_DIVIDER_HI_SHIFT;
+
+    return clk;
+}
+
+void sdhci_enable_clk(struct sdhci_host *host, rt_uint16_t clk)
+{
+    long timeout;
+
+    clk |= SDHCI_CLOCK_INT_EN;
+    sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+
+    /* Wait max 150 ms */
+    timeout = rt_tick_from_millisecond(150);
+    while (1)
+    {
+        timeout = timeout - rt_tick_get();
+
+        clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+        if (clk & SDHCI_CLOCK_INT_STABLE)
+            break;
+        if (timeout < 0)
+        {
+            rt_kprintf("%s: Internal clock never stabilised.\n",
+                       mmc_hostname(host->mmc));
+            sdhci_dumpregs(host);
+            return;
+        }
+        rt_hw_us_delay(10);
+    }
+
+    if (host->version >= SDHCI_SPEC_410 && host->v4_mode)
+    {
+        clk |= SDHCI_CLOCK_PLL_EN;
+        clk &= ~SDHCI_CLOCK_INT_STABLE;
+        sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+
+        /* Wait max 150 ms */
+        timeout = rt_tick_from_millisecond(150);
+        while (1)
+        {
+            timeout = timeout - rt_tick_get();
+
+            clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+            if (clk & SDHCI_CLOCK_INT_STABLE)
+                break;
+            if (timeout < 0)
+            {
+                rt_kprintf("%s: PLL clock never stabilised.\n",
+                           mmc_hostname(host->mmc));
+                sdhci_dumpregs(host);
+                return;
+            }
+            rt_hw_us_delay(10);
+        }
+    }
+
+    clk |= SDHCI_CLOCK_CARD_EN;
+    sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+}
+
+void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+    rt_uint16_t clk;
+
+    host->mmc->actual_clock = 0;
+
+    sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
+
+    if (clock == 0)
+        return;
+
+    clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
+    sdhci_enable_clk(host, clk);
+}
+
+void __sdhci_read_caps(struct sdhci_host *host, const rt_uint16_t *ver,
+                       const rt_uint32_t *caps, const rt_uint32_t *caps1)
+{
+    rt_uint16_t v;
+    rt_uint64_t dt_caps_mask = 0;
+    rt_uint64_t dt_caps      = 0;
+
+    if (host->read_caps)
+        return;
+
+    host->read_caps = RT_TRUE;
+
+    if (debug_quirks)
+        host->quirks = debug_quirks;
+
+    if (debug_quirks2)
+        host->quirks2 = debug_quirks2;
+
+    sdhci_reset_for_all(host);
+
+    if (host->v4_mode)
+        sdhci_do_enable_v4_mode(host);
+#ifdef RT_USING_OFW
+    rt_ofw_prop_read_u64(mmc_dev(host->mmc)->ofw_node,
+                         "sdhci-caps-mask", &dt_caps_mask);
+    rt_ofw_prop_read_u64(mmc_dev(host->mmc)->ofw_node,
+                         "sdhci-caps", &dt_caps);
+#endif
+    v             = ver ? *ver : sdhci_readw(host, SDHCI_HOST_VERSION);
+    host->version = (v & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT;
+
+    if (caps)
+    {
+        host->caps = *caps;
+    }
+    else
+    {
+        host->caps  = sdhci_readl(host, SDHCI_CAPABILITIES);
+        host->caps &= ~lower_32_bits(dt_caps_mask);
+        host->caps |= lower_32_bits(dt_caps);
+    }
+
+    if (host->version < SDHCI_SPEC_300)
+        return;
+
+    if (caps1)
+    {
+        host->caps1 = *caps1;
+    }
+    else
+    {
+        host->caps1  = sdhci_readl(host, SDHCI_CAPABILITIES_1);
+        host->caps1 &= ~upper_32_bits(dt_caps_mask);
+        host->caps1 |= upper_32_bits(dt_caps);
+    }
+}
+
+struct sdhci_host *sdhci_alloc_host(struct rt_device *dev,
+                                    size_t            priv_size)
+{
+    struct mmc_host   *mmc;
+    struct sdhci_host *host;
+
+    mmc = mmc_alloc_host(sizeof(struct sdhci_host) + priv_size, dev);
+    if (!mmc)
+        return NULL;
+
+    host               = mmc_priv(mmc);
+    host->mmc          = mmc;
+    host->mmc_host_ops = sdhci_ops;
+    mmc->ops           = &host->mmc_host_ops;
+
+    host->flags = SDHCI_SIGNALING_330;
+
+    host->cqe_ier     = SDHCI_CQE_INT_MASK;
+    host->cqe_err_ier = SDHCI_CQE_INT_ERR_MASK;
+
+    host->tuning_delay      = -1;
+    host->tuning_loop_count = MAX_TUNING_LOOP;
+
+    host->sdma_boundary = SDHCI_DEFAULT_BOUNDARY_ARG;
+
+    /*
+     * The DMA table descriptor count is calculated as the maximum
+     * number of segments times 2, to allow for an alignment
+     * descriptor for each segment, plus 1 for a nop end descriptor.
+     */
+
+    host->max_timeout_count = 0xE;
+
+    return host;
+}
+
+int sdhci_setup_host(struct sdhci_host *host)
+{
+    struct mmc_host *mmc;
+    size_t           max_current_caps;
+    unsigned int     ocr_avail;
+    unsigned int     override_timeout_clk;
+    size_t           max_clk;
+    int              ret          = 0;
+    bool             enable_vqmmc = RT_FALSE;
+
+    RT_ASSERT(host != NULL);
+
+
+    mmc = host->mmc;
+
+    /*
+     * If there are external regulators, get them. Note this must be done
+     * early before resetting the host and reading the capabilities so that
+     * the host can take the appropriate action if regulators are not
+     * available.
+     */
+    if (!mmc->supply.vqmmc)
+    {
+        if (ret)
+            return ret;
+        enable_vqmmc = RT_TRUE;
+    }
+
+    LOG_D("Version:   0x%08x | Present:  0x%08x\n",
+          sdhci_readw(host, SDHCI_HOST_VERSION),
+          sdhci_readl(host, SDHCI_PRESENT_STATE));
+    LOG_D("Caps:      0x%08x | Caps_1:   0x%08x\n",
+          sdhci_readl(host, SDHCI_CAPABILITIES),
+          sdhci_readl(host, SDHCI_CAPABILITIES_1));
+
+    sdhci_read_caps(host);
+
+    override_timeout_clk = host->timeout_clk;
+
+    if (host->version > SDHCI_SPEC_420)
+    {
+        rt_kprintf("%s: Unknown controller version (%d). You may experience problems.\n",
+                   mmc_hostname(mmc), host->version);
+    }
+
+    if (host->quirks & SDHCI_QUIRK_FORCE_DMA)
+        host->flags |= SDHCI_USE_SDMA;
+    else if (!(host->caps & SDHCI_CAN_DO_SDMA))
+        LOG_D("Controller doesn't have SDMA capability\n");
+    else
+        host->flags |= SDHCI_USE_SDMA;
+
+    if ((host->quirks & SDHCI_QUIRK_BROKEN_DMA) && (host->flags & SDHCI_USE_SDMA))
+    {
+        LOG_D("Disabling DMA as it is marked broken\n");
+        host->flags &= ~SDHCI_USE_SDMA;
+    }
+
+    if (sdhci_can_64bit_dma(host))
+        host->flags |= SDHCI_USE_64_BIT_DMA;
+
+    if (host->flags & SDHCI_USE_SDMA)
+    {
+        if (host->ops->set_dma_mask)
+            ret = host->ops->set_dma_mask(host);
+
+        if (!ret && host->ops->enable_dma)
+            ret = host->ops->enable_dma(host);
+
+        if (ret)
+        {
+            rt_kprintf("%s: No suitable DMA available - falling back to PIO\n",
+                       mmc_hostname(mmc));
+            host->flags &= ~SDHCI_USE_SDMA;
+
+            ret = 0;
+        }
+    }
+
+    /* SDMA does not support 64-bit DMA if v4 mode not set */
+    if ((host->flags & SDHCI_USE_64_BIT_DMA) && !host->v4_mode)
+        host->flags &= ~SDHCI_USE_SDMA;
+    /*
+     * If we use DMA, then it's up to the caller to set the DMA
+     * mask, but PIO does not need the hw shim so we set a new
+     * mask here in that case.
+     */
+
+    if (!(host->flags & SDHCI_USE_SDMA))
+    {
+        host->dma_mask = DMA_BIT_MASK(64);
+    }
+    if (host->version >= SDHCI_SPEC_300)
+        host->max_clk = FIELD_GET(SDHCI_CLOCK_V3_BASE_MASK, host->caps);
+    else
+        host->max_clk = FIELD_GET(SDHCI_CLOCK_BASE_MASK, host->caps);
+
+    host->max_clk *= 1000000;
+    if (host->max_clk == 0 || host->quirks & SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN)
+    {
+        if (!host->ops->get_max_clock)
+        {
+            rt_kprintf("%s: Hardware doesn't specify base clock frequency.  %p \n",
+                       mmc_hostname(mmc), host->ops->get_max_clock);
+            ret = -ENODEV;
+            goto undma;
+        }
+        host->max_clk = host->ops->get_max_clock(host);
+    }
+
+    /*
+     * In case of Host Controller v3.00, find out whether clock
+     * multiplier is supported.
+     */
+    host->clk_mul = FIELD_GET(SDHCI_CLOCK_MUL_MASK, host->caps1);
+
+    /*
+     * In case the value in Clock Multiplier is 0, then programmable
+     * clock mode is not supported, otherwise the actual clock
+     * multiplier is one more than the value of Clock Multiplier
+     * in the Capabilities Register.
+     */
+    if (host->clk_mul)
+        host->clk_mul += 1;
+
+    /*
+     * Set host parameters.
+     */
+    max_clk = host->max_clk;
+
+    if (host->ops->get_min_clock)
+        mmc->f_min = host->ops->get_min_clock(host);
+    else if (host->version >= SDHCI_SPEC_300)
+    {
+        if (host->clk_mul)
+            max_clk = host->max_clk * host->clk_mul;
+        /*
+         * Divided Clock Mode minimum clock rate is always less than
+         * Programmable Clock Mode minimum clock rate.
+         */
+        mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300;
+    }
+    else
+        mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200;
+
+    if (!mmc->f_max || mmc->f_max > max_clk)
+        mmc->f_max = max_clk;
+
+    if (!(host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK))
+    {
+        host->timeout_clk = FIELD_GET(SDHCI_TIMEOUT_CLK_MASK, host->caps);
+
+        if (host->caps & SDHCI_TIMEOUT_CLK_UNIT)
+            host->timeout_clk *= 1000;
+
+        if (host->timeout_clk == 0)
+        {
+            if (!host->ops->get_timeout_clock)
+            {
+                rt_kprintf("%s: Hardware doesn't specify timeout clock frequency.\n",
+                           mmc_hostname(mmc));
+                ret = -ENODEV;
+                goto undma;
+            }
+
+            host->timeout_clk =
+                DIV_ROUND_UP(host->ops->get_timeout_clock(host),
+                             1000);
+        }
+
+        if (override_timeout_clk)
+            host->timeout_clk = override_timeout_clk;
+
+        mmc->max_busy_timeout  = host->ops->get_max_timeout_count ? host->ops->get_max_timeout_count(host) : 1 << 27;
+        mmc->max_busy_timeout /= host->timeout_clk;
+    }
+
+    if (host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT && !host->ops->get_max_timeout_count)
+        mmc->max_busy_timeout = 0;
+
+    mmc->caps  |= MMC_CAP_SDIO_IRQ | MMC_CAP_CMD23;
+    mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
+
+    if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12)
+        host->flags |= SDHCI_AUTO_CMD12;
+
+    /*
+     * For v3 mode, Auto-CMD23 stuff only works in ADMA or PIO.
+     * For v4 mode, SDMA may use Auto-CMD23 as well.
+     */
+    if ((host->version >= SDHCI_SPEC_300) && (!(host->flags & SDHCI_USE_SDMA) || host->v4_mode) && !(host->quirks2 & SDHCI_QUIRK2_ACMD23_BROKEN))
+    {
+        host->flags |= SDHCI_AUTO_CMD23;
+        LOG_D("Auto-CMD23 available\n");
+    }
+    else
+    {
+        LOG_D("Auto-CMD23 unavailable\n");
+    }
+
+    /*
+     * A controller may support 8-bit width, but the board itself
+     * might not have the pins brought out.  Boards that support
+     * 8-bit width must set "mmc->caps |= MMC_CAP_8_BIT_DATA;" in
+     * their platform code before calling sdhci_add_host(), and we
+     * won't assume 8-bit width for hosts without that CAP.
+     */
+    if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA))
+        mmc->caps |= MMC_CAP_4_BIT_DATA;
+
+    if (host->quirks2 & SDHCI_QUIRK2_HOST_NO_CMD23)
+        mmc->caps &= ~MMC_CAP_CMD23;
+
+    if (host->caps & SDHCI_CAN_DO_HISPD)
+        mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
+    if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) && mmc_card_is_removable(mmc) && mmc_gpio_get_cd(mmc) < 0)
+        mmc->caps |= MMC_CAP_NEEDS_POLL;
+
+    if (mmc->supply.vqmmc)
+    {
+        if (enable_vqmmc)
+        {
+            host->sdhci_core_to_disable_vqmmc = !ret;
+        }
+
+        /* If vqmmc provides no 1.8V signalling, then there's no UHS */
+        if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 1700000,
+                                            1950000))
+            host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50);
+
+        /* In eMMC case vqmmc might be a fixed 1.8V regulator */
+        if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 2700000,
+                                            3600000))
+            host->flags &= ~SDHCI_SIGNALING_330;
+
+        if (ret)
+        {
+            rt_kprintf("%s: Failed to enable vqmmc regulator: %d\n",
+                       mmc_hostname(mmc), ret);
+            mmc->supply.vqmmc = (void *)-EINVAL;
+        }
+    }
+    if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V)
+    {
+        host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50);
+        /*
+         * The SDHCI controller in a SoC might support HS200/HS400
+         * (indicated using mmc-hs200-1_8v/mmc-hs400-1_8v dt property),
+         * but if the board is modeled such that the IO lines are not
+         * connected to 1.8v then HS200/HS400 cannot be supported.
+         * Disable HS200/HS400 if the board does not have 1.8v connected
+         * to the IO lines. (Applicable for other modes in 1.8v)
+         */
+        mmc->caps2 &= ~(MMC_CAP2_HSX00_1_8V | MMC_CAP2_HS400_ES);
+        mmc->caps  &= ~(MMC_CAP_1_8V_DDR | MMC_CAP_UHS);
+    }
+
+    /* Any UHS-I mode in caps implies SDR12 and SDR25 support. */
+    if (host->caps1 & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50))
+        mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25;
+
+    /* SDR104 supports also implies SDR50 support */
+    if (host->caps1 & SDHCI_SUPPORT_SDR104)
+    {
+        mmc->caps |= MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50;
+        /* SD3.0: SDR104 is supported so (for eMMC) the caps2
+         * field can be promoted to support HS200.
+         */
+        if (!(host->quirks2 & SDHCI_QUIRK2_BROKEN_HS200))
+            mmc->caps2 |= MMC_CAP2_HS200;
+    }
+    else if (host->caps1 & SDHCI_SUPPORT_SDR50)
+    {
+        mmc->caps |= MMC_CAP_UHS_SDR50;
+    }
+
+    if (host->quirks2 & SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 && (host->caps1 & SDHCI_SUPPORT_HS400))
+        mmc->caps2 |= MMC_CAP2_HS400;
+    if ((mmc->caps2 & MMC_CAP2_HSX00_1_2V) && (!mmc->supply.vqmmc || !regulator_is_supported_voltage(mmc->supply.vqmmc, 1100000, 1300000)))
+        mmc->caps2 &= ~MMC_CAP2_HSX00_1_2V;
+    if ((host->caps1 & SDHCI_SUPPORT_DDR50) && !(host->quirks2 & SDHCI_QUIRK2_BROKEN_DDR50))
+        mmc->caps |= MMC_CAP_UHS_DDR50;
+
+    /* Does the host need tuning for SDR50? */
+    if (host->caps1 & SDHCI_USE_SDR50_TUNING)
+        host->flags |= SDHCI_SDR50_NEEDS_TUNING;
+
+    /* Driver Type(s) (A, C, D) supported by the host */
+    if (host->caps1 & SDHCI_DRIVER_TYPE_A)
+        mmc->caps |= MMC_CAP_DRIVER_TYPE_A;
+    if (host->caps1 & SDHCI_DRIVER_TYPE_C)
+        mmc->caps |= MMC_CAP_DRIVER_TYPE_C;
+    if (host->caps1 & SDHCI_DRIVER_TYPE_D)
+        mmc->caps |= MMC_CAP_DRIVER_TYPE_D;
+
+    /* Initial value for re-tuning timer count */
+    host->tuning_count = FIELD_GET(SDHCI_RETUNING_TIMER_COUNT_MASK,
+                                   host->caps1);
+
+    /*
+     * In case Re-tuning Timer is not disabled, the actual value of
+     * re-tuning timer will be 2 ^ (n - 1).
+     */
+    if (host->tuning_count)
+        host->tuning_count = 1 << (host->tuning_count - 1);
+
+    /* Re-tuning mode supported by the Host Controller */
+    host->tuning_mode = FIELD_GET(SDHCI_RETUNING_MODE_MASK, host->caps1);
+
+    ocr_avail = 0;
+
+    /*
+     * According to SD Host Controller spec v3.00, if the Host System
+     * can afford more than 150mA, Host Driver should set XPC to 1. Also
+     * the value is meaningful only if Voltage Support in the Capabilities
+     * register is set. The actual current value is 4 times the register
+     * value.
+     */
+    max_current_caps = sdhci_readl(host, SDHCI_MAX_CURRENT);
+
+    if (!max_current_caps && mmc->supply.vmmc)
+    {
+        int curr = regulator_get_current_limit(mmc->supply.vmmc);
+        if (curr > 0)
+        {
+            /* convert to SDHCI_MAX_CURRENT format */
+            curr = curr / 1000; /* convert to mA */
+            curr = curr / SDHCI_MAX_CURRENT_MULTIPLIER;
+
+            curr = min_t(rt_uint32_t, curr, SDHCI_MAX_CURRENT_LIMIT);
+            max_current_caps =
+                FIELD_PREP(SDHCI_MAX_CURRENT_330_MASK, curr) | FIELD_PREP(SDHCI_MAX_CURRENT_300_MASK, curr) | FIELD_PREP(SDHCI_MAX_CURRENT_180_MASK, curr);
+        }
+    }
+
+    if (host->caps & SDHCI_CAN_VDD_330)
+    {
+        ocr_avail |= MMC_VDD_32_33 | MMC_VDD_33_34;
+
+        mmc->max_current_330 = FIELD_GET(SDHCI_MAX_CURRENT_330_MASK,
+                                         max_current_caps)
+                               * SDHCI_MAX_CURRENT_MULTIPLIER;
+    }
+    if (host->caps & SDHCI_CAN_VDD_300)
+    {
+        ocr_avail |= MMC_VDD_29_30 | MMC_VDD_30_31;
+
+        mmc->max_current_300 = FIELD_GET(SDHCI_MAX_CURRENT_300_MASK,
+                                         max_current_caps)
+                               * SDHCI_MAX_CURRENT_MULTIPLIER;
+    }
+    if (host->caps & SDHCI_CAN_VDD_180)
+    {
+        ocr_avail |= MMC_VDD_165_195;
+
+        mmc->max_current_180 = FIELD_GET(SDHCI_MAX_CURRENT_180_MASK,
+                                         max_current_caps)
+                               * SDHCI_MAX_CURRENT_MULTIPLIER;
+    }
+
+    /* If OCR set by host, use it instead. */
+    if (host->ocr_mask)
+        ocr_avail = host->ocr_mask;
+
+    /* If OCR set by external regulators, give it highest prio. */
+    if (mmc->ocr_avail)
+        ocr_avail = mmc->ocr_avail;
+
+    mmc->ocr_avail      = ocr_avail;
+    mmc->ocr_avail_sdio = ocr_avail;
+    if (host->ocr_avail_sdio)
+        mmc->ocr_avail_sdio &= host->ocr_avail_sdio;
+    mmc->ocr_avail_sd = ocr_avail;
+    if (host->ocr_avail_sd)
+        mmc->ocr_avail_sd &= host->ocr_avail_sd;
+    else /* normal SD controllers don't support 1.8V */
+        mmc->ocr_avail_sd &= ~MMC_VDD_165_195;
+    mmc->ocr_avail_mmc = ocr_avail;
+    if (host->ocr_avail_mmc)
+        mmc->ocr_avail_mmc &= host->ocr_avail_mmc;
+
+    if (mmc->ocr_avail == 0)
+    {
+        rt_kprintf("%s: Hardware doesn't report any support voltages.\n",
+                   mmc_hostname(mmc));
+        ret = -ENODEV;
+        goto unreg;
+    }
+
+    if ((mmc->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR)) || (mmc->caps2 & (MMC_CAP2_HS200_1_8V_SDR | MMC_CAP2_HS400_1_8V)))
+        host->flags |= SDHCI_SIGNALING_180;
+
+    if (mmc->caps2 & MMC_CAP2_HSX00_1_2V)
+        host->flags |= SDHCI_SIGNALING_120;
+
+    rt_spin_lock_init(&host->lock);
+
+    /*
+     * Maximum number of sectors in one transfer. Limited by SDMA boundary
+     * size (512KiB). Note some tuning modes impose a 4MiB limit, but this
+     * is less anyway.
+     */
+    mmc->max_req_size = 524288;
+
+    /*
+     * Maximum number of segments. Depends on if the hardware
+     * can do scatter/gather or not.
+     */
+    if (host->flags & SDHCI_USE_SDMA)
+    {
+        mmc->max_segs = 1;
+    }
+    else
+    { /* PIO */
+        mmc->max_segs = SDHCI_MAX_SEGS;
+    }
+    /*
+     * Maximum segment size. Could be one segment with the maximum number
+     * of bytes. When doing hardware scatter/gather, each entry cannot
+     * be larger than 64 KiB though.
+     */
+    mmc->max_seg_size = mmc->max_req_size;
+
+    /*
+     * Maximum block size. This varies from controller to controller and
+     * is specified in the capabilities register.
+     */
+    if (host->quirks & SDHCI_QUIRK_FORCE_BLK_SZ_2048)
+    {
+        mmc->max_blk_size = 2;
+    }
+    else
+    {
+        mmc->max_blk_size = (host->caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT;
+        if (mmc->max_blk_size >= 3)
+        {
+            rt_kprintf("%s: Invalid maximum block size, assuming 512 bytes\n",
+                       mmc_hostname(mmc));
+            mmc->max_blk_size = 0;
+        }
+    }
+
+    mmc->max_blk_size = 512 << mmc->max_blk_size;
+
+    /*
+     * Maximum block count.
+     */
+    mmc->max_blk_count = (host->quirks & SDHCI_QUIRK_NO_MULTIBLOCK) ? 1 : 65535;
+    return 0;
+
+unreg:
+undma:
+    return ret;
+}
+
+static void sdhci_init(struct sdhci_host *host, int soft)
+{
+    struct mmc_host *mmc = host->mmc;
+    rt_base_t        flags;
+
+    if (soft)
+    {
+        sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+    }
+    else
+    {
+        sdhci_do_reset(host, SDHCI_RESET_ALL);
+    }
+    if (host->v4_mode)
+    {
+        sdhci_do_enable_v4_mode(host);
+    }
+    flags = rt_spin_lock_irqsave(&host->lock);
+    sdhci_set_default_irqs(host);
+    rt_spin_unlock_irqrestore(&host->lock, flags);
+
+    host->cqe_on = RT_FALSE;
+
+    if (soft)
+    {
+        /* force clock reconfiguration */
+        host->clock      = 0;
+        host->reinit_uhs = RT_TRUE;
+        mmc->ops->set_ios(mmc, &mmc->ios);
+    }
+}
+
+static void sdhci_reinit(struct sdhci_host *host)
+{
+    rt_uint32_t cd = host->ier & (SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT);
+
+    sdhci_init(host, 0);
+    sdhci_enable_card_detection(host);
+
+    /*
+     * A change to the card detect bits indicates a change in present state,
+     * refer sdhci_set_card_detection(). A card detect interrupt might have
+     * been missed while the host controller was being reset, so trigger a
+     * rescan to check.
+     */
+    if (cd != (host->ier & (SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT)))
+        mmc_detect_change(host->mmc, rt_tick_from_millisecond(200));
+}
+
+int __sdhci_add_host(struct sdhci_host *host)
+{
+    struct mmc_host *mmc = host->mmc;
+    int              ret;
+
+    if ((mmc->caps2 & MMC_CAP2_CQE) && (host->quirks & SDHCI_QUIRK_BROKEN_CQE))
+    {
+        mmc->caps2 &= ~MMC_CAP2_CQE;
+    }
+
+    host->complete_wq = rt_workqueue_create("sdhci", 4096, 20);
+    if (!host->complete_wq)
+        return -ENOMEM;
+
+    rt_work_init(&host->complete_work, sdhci_complete_work, host);
+
+    rt_timer_init(&host->timer, "sdhci_timer", sdhci_timeout_timer, host, 0, RT_TIMER_FLAG_SOFT_TIMER);
+    rt_timer_init(&host->data_timer, "sdhci_data_timer", sdhci_timeout_data_timer, host, 0, RT_TIMER_FLAG_SOFT_TIMER);
+
+    rt_wqueue_init(&host->buf_ready_int);
+
+    sdhci_init(host, 0);
+
+    host->irq_wq = rt_workqueue_create("sdhci_irq", 8192, 1);
+    rt_work_init(&host->irq_work, sdhci_thread_irq, host);
+    rt_hw_interrupt_install(host->irq, sdhci_irq, host, mmc_hostname(mmc));
+    rt_pic_irq_unmask(host->irq);
+    ret = mmc_add_host(mmc);
+    if (ret)
+        goto unirq;
+
+    rt_kprintf("%s: SDHCI controller on %s [%s] using %s\n",
+               mmc_hostname(mmc), host->hw_name, mmc_dev(mmc)->parent.name,
+               (host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO");
+
+    sdhci_enable_card_detection(host);
+
+    return 0;
+
+unirq:
+    sdhci_reset_for_all(host);
+    sdhci_writel(host, 0, SDHCI_INT_ENABLE);
+    sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
+
+    return ret;
+}
+
+int sdhci_add_host(struct sdhci_host *host)
+{
+    int ret;
+    ret = sdhci_setup_host(host);
+    if (ret)
+        return ret;
+
+    ret = __sdhci_add_host(host);
+    if (ret)
+        goto cleanup;
+
+    return 0;
+
+cleanup:
+    sdhci_cleanup_host(host);
+
+    return ret;
+}
+
+void sdhci_set_ios(struct mmc_host *mmc, struct rt_mmcsd_io_cfg *ios)
+{
+    struct sdhci_host *host           = mmc_priv(mmc);
+    rt_bool_t          reinit_uhs     = host->reinit_uhs;
+    rt_bool_t          turning_on_clk = RT_FALSE;
+    rt_uint8_t         ctrl;
+
+    host->reinit_uhs = RT_FALSE;
+
+    if (ios->power_mode == MMC_POWER_UNDEFINED)
+        return;
+
+    if (host->flags & SDHCI_DEVICE_DEAD)
+    {
+        if (mmc->supply.vmmc && ios->power_mode == MMC_POWER_OFF)
+            mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
+        return;
+    }
+
+    /*
+     * Reset the chip on each power off.
+     * Should clear out any weird states.
+     */
+    if (ios->power_mode == MMC_POWER_OFF)
+    {
+        sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
+        sdhci_reinit(host);
+    }
+
+    if (host->version >= SDHCI_SPEC_300 && (ios->power_mode == MMC_POWER_UP) && !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN))
+        sdhci_enable_preset_value(host, RT_FALSE);
+
+    if (!ios->clock || ios->clock != host->clock)
+    {
+        turning_on_clk = ios->clock && !host->clock;
+
+        host->ops->set_clock(host, ios->clock);
+        host->clock = ios->clock;
+
+        if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK && host->clock)
+        {
+            host->timeout_clk = mmc->actual_clock ? mmc->actual_clock / 1000 : host->clock / 1000;
+            mmc->max_busy_timeout =
+                host->ops->get_max_timeout_count ? host->ops->get_max_timeout_count(host) : 1 << 27;
+            mmc->max_busy_timeout /= host->timeout_clk;
+        }
+    }
+
+    if (host->ops->set_power)
+        host->ops->set_power(host, ios->power_mode, ios->vdd);
+    else
+        sdhci_set_power(host, ios->power_mode, ios->vdd);
+
+    if (host->ops->platform_send_init_74_clocks)
+        host->ops->platform_send_init_74_clocks(host, ios->power_mode);
+
+    host->ops->set_bus_width(host, ios->bus_width);
+
+    /*
+     * Special case to avoid multiple clock changes during voltage
+     * switching.
+     */
+    if (!reinit_uhs && turning_on_clk && host->timing == ios->timing && host->version >= SDHCI_SPEC_300 && !sdhci_presetable_values_change(host, ios))
+        return;
+
+    ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
+
+    if (!(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT))
+    {
+        if (ios->timing == MMC_TIMING_SD_HS || ios->timing == MMC_TIMING_MMC_HS || ios->timing == MMC_TIMING_MMC_HS400 || ios->timing == MMC_TIMING_MMC_HS200 || ios->timing == MMC_TIMING_MMC_DDR52 || ios->timing == MMC_TIMING_UHS_SDR50 || ios->timing == MMC_TIMING_UHS_SDR104 || ios->timing == MMC_TIMING_UHS_DDR50 || ios->timing == MMC_TIMING_UHS_SDR25)
+            ctrl |= SDHCI_CTRL_HISPD;
+        else
+            ctrl &= ~SDHCI_CTRL_HISPD;
+    }
+
+    if (host->version >= SDHCI_SPEC_300)
+    {
+        rt_uint16_t clk, ctrl_2;
+
+        /*
+         * According to SDHCI Spec v3.00, if the Preset Value
+         * Enable in the Host Control 2 register is set, we
+         * need to reset SD Clock Enable before changing High
+         * Speed Enable to avoid generating clock glitches.
+         */
+        clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+        if (clk & SDHCI_CLOCK_CARD_EN)
+        {
+            clk &= ~SDHCI_CLOCK_CARD_EN;
+            sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+        }
+
+        sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+
+        if (!host->preset_enabled)
+        {
+            /*
+             * We only need to set Driver Strength if the
+             * preset value enable is not set.
+             */
+            ctrl_2  = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+            ctrl_2 &= ~SDHCI_CTRL_DRV_TYPE_MASK;
+            if (ios->drv_type == MMC_SET_DRIVER_TYPE_A)
+                ctrl_2 |= SDHCI_CTRL_DRV_TYPE_A;
+            else if (ios->drv_type == MMC_SET_DRIVER_TYPE_B)
+                ctrl_2 |= SDHCI_CTRL_DRV_TYPE_B;
+            else if (ios->drv_type == MMC_SET_DRIVER_TYPE_C)
+                ctrl_2 |= SDHCI_CTRL_DRV_TYPE_C;
+            else if (ios->drv_type == MMC_SET_DRIVER_TYPE_D)
+                ctrl_2 |= SDHCI_CTRL_DRV_TYPE_D;
+            else
+            {
+                LOG_D("%s: invalid driver type, default to driver type B\n",
+                      mmc_hostname(mmc));
+                ctrl_2 |= SDHCI_CTRL_DRV_TYPE_B;
+            }
+
+            sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
+            host->drv_type = ios->drv_type;
+        }
+
+        host->ops->set_uhs_signaling(host, ios->timing);
+        host->timing = ios->timing;
+
+        if (sdhci_preset_needed(host, ios->timing))
+        {
+            rt_uint16_t preset;
+
+            sdhci_enable_preset_value(host, RT_TRUE);
+            preset         = sdhci_get_preset_value(host);
+            ios->drv_type  = FIELD_GET(SDHCI_PRESET_DRV_MASK,
+                                       preset);
+            host->drv_type = ios->drv_type;
+        }
+
+        /* Re-enable SD Clock */
+        host->ops->set_clock(host, host->clock);
+    }
+    else
+        sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+}
+void sdhci_free_host(struct sdhci_host *host)
+{
+    sdhci_cleanup_host(host);
+    rt_free(host);
+}

+ 303 - 0
bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/src/fit-mmc.c

@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 2006-2024 RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author        Notes
+ * 2024-08-16     zhujiale     first version
+ */
+#include <rtthread.h>
+#include "sdhci.h"
+#include <rtdbg.h>
+#include <mmu.h>
+#include <drivers/core/dm.h>
+
+
+static void plat_request(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
+{
+    struct mmc_host *mmc   = (struct mmc_host *)host;
+    rt_uint32_t      flags = req->cmd->flags;
+
+    switch (flags & RESP_MASK)
+    {
+    case RESP_NONE:
+        flags |= MMC_RSP_NONE;
+        break;
+    case RESP_R1:
+        flags |= MMC_RSP_R1;
+        break;
+    case RESP_R1B:
+        flags |= MMC_RSP_R1B;
+        break;
+    case RESP_R2:
+        flags |= MMC_RSP_R2;
+        break;
+    case RESP_R3:
+        flags |= MMC_RSP_R3;
+        break;
+    case RESP_R4:
+        flags |= MMC_RSP_R4;
+        break;
+    case RESP_R5:
+        flags |= MMC_RSP_R5;
+        break;
+    case RESP_R6:
+        flags |= MMC_RSP_R6;
+        break;
+    case RESP_R7:
+        flags |= MMC_RSP_R7;
+        break;
+    }
+    if (req->data)
+    {
+        if ((rt_uint64_t)rt_kmem_v2p(req->data->buf) > 0xffffffff)
+        {
+            void *dma_buffer = rt_malloc(ARCH_PAGE_SIZE);
+            void *req_buf    = NULL;
+
+            if (req->data->blks * req->data->blksize > ARCH_PAGE_SIZE)
+            {
+                dma_buffer = rt_realloc(dma_buffer, req->data->blks * req->data->blksize);
+            }
+
+            if (req->data->flags & DATA_DIR_WRITE)
+            {
+                rt_memcpy(dma_buffer, req->data->buf, req->data->blks * req->data->blksize);
+                req->data->buf = dma_buffer;
+            }
+            else if (req->data->flags & DATA_DIR_READ)
+            {
+                req_buf        = req->data->buf;
+                req->data->buf = dma_buffer;
+            }
+            req->cmd->flags |= flags;
+            mmc->ops->request(mmc, req);
+
+            rt_sem_take(&host->sem_ack, RT_WAITING_FOREVER);
+
+            if (req->data->flags & DATA_DIR_READ)
+            {
+                rt_memcpy(req_buf, dma_buffer, req->data->blksize * req->data->blks);
+                req->data->buf = req_buf;
+            }
+
+            rt_free(dma_buffer);
+            rt_sem_release(&host->sem_ack);
+        }
+        else
+        {
+            req->cmd->flags |= flags;
+            mmc->ops->request(mmc, req);
+        }
+    }
+    else
+    {
+        req->cmd->flags |= flags;
+        mmc->ops->request(mmc, req);
+    }
+}
+
+static void plat_set_ioconfig(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *iocfg)
+{
+    struct mmc_host *mmc = (struct mmc_host *)host;
+
+    LOG_D("clock:%d,width:%d,power:%d,vdd:%d,timing:%d\n",
+          iocfg->clock, iocfg->bus_width,
+          iocfg->power_mode, iocfg->vdd, iocfg->timing);
+
+    mmc->ops->set_ios(mmc, iocfg);
+}
+
+static rt_int32_t plat_get_card_status(struct rt_mmcsd_host *host)
+{
+    struct mmc_host *mmc = (struct mmc_host *)host;
+
+    return mmc->ops->get_cd(mmc);
+}
+
+static rt_int32_t plat_execute_tuning(struct rt_mmcsd_host *host, rt_int32_t opcode)
+{
+    struct mmc_host *mmc = (struct mmc_host *)host;
+
+    return mmc->ops->execute_tuning(mmc, opcode);
+}
+
+static void plat_enable_sdio_irq(struct rt_mmcsd_host *host, rt_int32_t en)
+{
+    struct mmc_host *mmc = (struct mmc_host *)host;
+
+    return mmc->ops->enable_sdio_irq(mmc, en);
+}
+
+
+static const struct rt_mmcsd_host_ops rt_mmcsd_ops = {
+    .request         = plat_request,
+    .set_iocfg       = plat_set_ioconfig,
+    .get_card_status = plat_get_card_status,
+    .enable_sdio_irq = plat_enable_sdio_irq,
+    .execute_tuning  = plat_execute_tuning,
+};
+
+
+void mmc_request_done(struct mmc_host *host, struct rt_mmcsd_req *mrq)
+{
+    mmcsd_req_complete(&host->rthost);
+}
+
+/*add host in rtt while sdhci complete*/
+int mmc_add_host(struct mmc_host *mmc)
+{
+    mmc->rthost.ops           = &rt_mmcsd_ops;
+    mmc->rthost.flags         = mmc->caps;
+    mmc->rthost.freq_max      = mmc->f_max;
+    mmc->rthost.freq_min      = 400000;
+    mmc->rthost.max_dma_segs  = mmc->max_segs;
+    mmc->rthost.max_seg_size  = mmc->max_seg_size;
+    mmc->rthost.max_blk_size  = mmc->max_blk_size;
+    mmc->rthost.max_blk_count = mmc->max_blk_count;
+    mmc->rthost.valid_ocr     = VDD_33_34 | VDD_32_33 | VDD_31_32 | VDD_30_31 | VDD_165_195 | VDD_20_21;
+
+
+    mmcsd_change(&mmc->rthost);
+    return 0;
+}
+
+struct mmc_host *mmc_alloc_host(int extra, struct rt_device *dev)
+{
+    struct mmc_host *mmc;
+
+    mmc = rt_malloc(sizeof(*mmc) + extra);
+    if (mmc)
+    {
+        rt_memset(mmc, 0, sizeof(*mmc) + extra);
+        mmc->parent = dev;
+        mmcsd_host_init(&mmc->rthost);
+    }
+
+    return mmc;
+}
+
+void mmc_remove_host(struct mmc_host *host)
+{
+    rt_free(host);
+}
+
+int mmc_abort_tuning(struct mmc_host *host, rt_uint32_t opcode)
+{
+    return 0;
+}
+
+
+int mmc_gpio_get_cd(struct mmc_host *host)
+{
+    return -ENOSYS;
+}
+
+void mmc_detect_change(struct mmc_host *host, unsigned long delay)
+{
+}
+
+
+int mmc_regulator_set_vqmmc(struct mmc_host *mmc, struct rt_mmcsd_io_cfg *ios)
+{
+    return 0;
+}
+
+rt_bool_t mmc_can_gpio_ro(struct mmc_host *host)
+{
+    return RT_FALSE;
+}
+
+int mmc_gpio_get_ro(struct mmc_host *host)
+{
+    return 0;
+}
+
+int mmc_send_abort_tuning(struct mmc_host *host, rt_uint32_t opcode)
+{
+    return 0;
+}
+int mmc_of_parse(struct mmc_host *host)
+{
+    struct rt_device *dev = host->parent;
+    rt_uint32_t       bus_width;
+
+    if (!dev || !dev->ofw_node)
+        return 0;
+
+    /* "bus-width" is translated to MMC_CAP_*_BIT_DATA flags */
+    if (rt_dm_dev_prop_read_u32(dev, "bus-width", &bus_width) < 0)
+    {
+        bus_width = 1;
+    }
+
+    switch (bus_width)
+    {
+    case 8:
+        host->caps |= MMC_CAP_8_BIT_DATA;
+        break; /* Hosts capable of 8-bit can also do 4 bits */
+    case 4:
+        host->caps |= MMC_CAP_4_BIT_DATA;
+        break;
+    case 1:
+        break;
+    default:
+        return -EINVAL;
+    }
+
+    /* f_max is obtained from the optional "max-frequency" property */
+    rt_dm_dev_prop_read_u32(dev, "max-frequency", &host->f_max);
+
+    if (rt_dm_dev_prop_read_bool(dev, "cap-mmc-highspeed"))
+    {
+        host->caps |= MMC_CAP_MMC_HIGHSPEED;
+    }
+
+    if (rt_dm_dev_prop_read_bool(dev, "mmc-hs200-1_8v"))
+    {
+        host->caps |= MMC_CAP2_HS200_1_8V_SDR;
+    }
+
+    if (rt_dm_dev_prop_read_bool(dev, "non-removable"))
+    {
+        host->caps |= MMC_CAP_NONREMOVABLE;
+    }
+
+    if (rt_dm_dev_prop_read_bool(dev, "no-sdio"))
+    {
+        host->caps2 |= MMC_CAP2_NO_SDIO;
+    }
+
+    if (rt_dm_dev_prop_read_bool(dev, "no-sd"))
+    {
+        host->caps2 |= MMC_CAP2_NO_SD;
+    }
+
+    if (rt_dm_dev_prop_read_bool(dev, "mmc-ddr-3_3v"))
+    {
+        host->caps |= MMC_CAP_3_3V_DDR;
+    }
+
+    if (rt_dm_dev_prop_read_bool(dev, "mmc-ddr-1_8v"))
+    {
+        host->caps |= MMC_CAP_1_8V_DDR;
+    }
+
+    if (rt_dm_dev_prop_read_bool(dev, "mmc-ddr-1_2v"))
+    {
+        host->caps |= MMC_CAP_1_2V_DDR;
+    }
+
+    return 0;
+}
+
+
+void mmc_free_host(struct mmc_host *host)
+{
+}
+
+rt_bool_t mmc_can_gpio_cd(struct mmc_host *host)
+{
+    return RT_FALSE;
+}

+ 44 - 0
bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/src/sdhci_dma.c

@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2006-2024 RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author        Notes
+ * 2024-08-16     zhujiale     first version
+ */
+#include "sdhci.h"
+#include <rtthread.h>
+
+
+int dma_set_mask_and_coherent(struct rt_device *dev, rt_uint64_t mask)
+{
+    return 0;
+}
+
+unsigned long virt_to_phys(volatile void *address)
+{
+    return (unsigned long)((rt_uint64_t)address + PV_OFFSET);
+}
+void *dma_alloc_coherent(struct rt_device *dev, size_t size,
+                         rt_uint64_t *dma_handle)
+{
+    void *v;
+
+    v = rt_malloc_align(size, 2048);
+    rt_kprintf("v = %p \n", v);
+    if (v)
+    {
+        *dma_handle = virt_to_phys(v);
+        v           = rt_ioremap((void *)*dma_handle, size);
+        rt_kprintf("v = %p *dma_handle = %p \n", v, *dma_handle);
+    }
+
+    return v;
+}
+
+void dma_free_coherent(struct rt_device *dev, size_t size,
+                       void *cpu_addr, unsigned long dma_handle)
+{
+    rt_free(cpu_addr);
+}

+ 37 - 0
bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/src/sdhci_voltage.c

@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2006-2024 RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author        Notes
+ * 2024-08-16     zhujiale     first version
+ */
+#include "sdhci.h"
+
+int mmc_regulator_get_supply(struct mmc_host *mmc)
+{
+    mmc->supply.vmmc  = -RT_NULL;
+    mmc->supply.vqmmc = -RT_NULL;
+
+    return 0;
+}
+int regulator_get_current_limit(struct regulator *regulator)
+{
+    return 0;
+}
+
+int regulator_is_supported_voltage(struct regulator *regulator,
+
+                                   int min_uV, int max_uV)
+{
+    return 0;
+}
+
+int regulator_enable(struct regulator *regulator)
+{
+    return 0;
+}
+void regulator_disable(struct regulator *regulator)
+{
+}

+ 9 - 0
bsp/raspberry-pi/raspi-dm2.0/qemu.sh

@@ -0,0 +1,9 @@
+if [ ! -f "sd.bin" ]; then
+    dd if=/dev/zero of=sd.bin bs=1024 count=65536
+fi
+
+qemu-system-aarch64 -M raspi4b -serial stdio \
+    -kernel rtthread.bin \
+    -drive if=sd,file=sd.bin \
+    -dtb bcm2711-rpi-4-b.dtb \
+    -append 'printk.time=0 earlycon=pl011,0xfe201000 console=ttyAMA0 root=ram0 rw'

+ 575 - 0
bsp/raspberry-pi/raspi-dm2.0/rtconfig.h

@@ -0,0 +1,575 @@
+#ifndef RT_CONFIG_H__
+#define RT_CONFIG_H__
+
+/* RT-Thread Kernel */
+
+#define RT_NAME_MAX 8
+#define RT_USING_SMART
+#define RT_USING_SMP
+#define RT_CPUS_NR 4
+#define RT_ALIGN_SIZE 4
+#define RT_THREAD_PRIORITY_32
+#define RT_THREAD_PRIORITY_MAX 32
+#define RT_TICK_PER_SECOND 1000
+#define RT_USING_HOOK
+#define RT_HOOK_USING_FUNC_PTR
+#define RT_USING_IDLE_HOOK
+#define RT_IDLE_HOOK_LIST_SIZE 4
+#define IDLE_THREAD_STACK_SIZE 16384
+#define SYSTEM_THREAD_STACK_SIZE 16384
+#define RT_USING_TIMER_SOFT
+#define RT_TIMER_THREAD_PRIO 4
+#define RT_TIMER_THREAD_STACK_SIZE 16384
+#define RT_USING_CPU_USAGE_TRACER
+
+/* kservice optimization */
+
+/* end of kservice optimization */
+
+/* klibc optimization */
+
+#define RT_KLIBC_USING_PRINTF_LONGLONG
+/* end of klibc optimization */
+#define RT_USING_DEBUG
+#define RT_DEBUGING_COLOR
+#define RT_DEBUGING_CONTEXT
+#define RT_USING_OVERFLOW_CHECK
+
+/* Inter-Thread communication */
+
+#define RT_USING_SEMAPHORE
+#define RT_USING_MUTEX
+#define RT_USING_EVENT
+#define RT_USING_MAILBOX
+#define RT_USING_MESSAGEQUEUE
+/* end of Inter-Thread communication */
+
+/* Memory Management */
+
+#define RT_PAGE_MAX_ORDER 11
+#define RT_USING_SLAB
+#define RT_USING_SLAB_AS_HEAP
+#define RT_USING_HEAP
+/* end of Memory Management */
+#define RT_USING_DEVICE
+#define RT_USING_DEVICE_OPS
+#define RT_USING_INTERRUPT_INFO
+#define RT_USING_SCHED_THREAD_CTX
+#define RT_USING_CONSOLE
+#define RT_CONSOLEBUF_SIZE 256
+#define RT_CONSOLE_DEVICE_NAME "uart0"
+#define RT_VER_NUM 0x50200
+#define RT_USING_STDC_ATOMIC
+#define RT_BACKTRACE_LEVEL_MAX_NR 32
+/* end of RT-Thread Kernel */
+
+/* AArch64 Architecture Configuration */
+
+#define ARCH_TEXT_OFFSET 0x200000
+#define ARCH_RAM_OFFSET 0x0
+#define ARCH_SECONDARY_CPU_STACK_SIZE 65536
+#define ARCH_HAVE_EFFICIENT_UNALIGNED_ACCESS
+#define ARCH_HEAP_SIZE 0x4000000
+#define ARCH_INIT_PAGE_SIZE 0x200000
+/* end of AArch64 Architecture Configuration */
+#define ARCH_CPU_64BIT
+#define RT_USING_CACHE
+#define RT_USING_CPU_FFS
+#define ARCH_MM_MMU
+#define ARCH_ARM
+#define ARCH_ARM_MMU
+#define KERNEL_VADDR_START 0xffff000000000000
+#define ARCH_ARMV8
+
+/* RT-Thread Components */
+
+#define RT_USING_COMPONENTS_INIT
+#define RT_USING_USER_MAIN
+#define RT_MAIN_THREAD_STACK_SIZE 8192
+#define RT_MAIN_THREAD_PRIORITY 10
+#define RT_USING_MSH
+#define RT_USING_FINSH
+#define FINSH_USING_MSH
+#define FINSH_THREAD_NAME "tshell"
+#define FINSH_THREAD_PRIORITY 20
+#define FINSH_THREAD_STACK_SIZE 8192
+#define FINSH_USING_HISTORY
+#define FINSH_HISTORY_LINES 5
+#define FINSH_USING_SYMTAB
+#define FINSH_CMD_SIZE 80
+#define MSH_USING_BUILT_IN_COMMANDS
+#define FINSH_USING_DESCRIPTION
+#define FINSH_ARG_MAX 10
+#define FINSH_USING_OPTION_COMPLETION
+
+/* DFS: device virtual file system */
+
+#define RT_USING_DFS
+#define DFS_USING_POSIX
+#define DFS_USING_WORKDIR
+#define DFS_FD_MAX 64
+#define RT_USING_DFS_V2
+#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_DFS_ELM_MUTEX_TIMEOUT 3000
+/* end of elm-chan's FatFs, Generic FAT Filesystem Module */
+#define RT_USING_DFS_DEVFS
+#define RT_USING_DFS_PTYFS
+#define RT_USING_DFS_TMPFS
+#define RT_USING_PAGECACHE
+
+/* page cache config */
+
+#define RT_PAGECACHE_COUNT 4096
+#define RT_PAGECACHE_ASPACE_COUNT 1024
+#define RT_PAGECACHE_PRELOAD 4
+#define RT_PAGECACHE_HASH_NR 1024
+#define RT_PAGECACHE_GC_WORK_LEVEL 90
+#define RT_PAGECACHE_GC_STOP_LEVEL 70
+/* end of page cache config */
+/* end of DFS: device virtual file system */
+
+/* Device Drivers */
+
+#define RT_USING_DM
+#define RT_USING_DEV_BUS
+#define RT_USING_DEVICE_IPC
+#define RT_UNAMED_PIPE_NUMBER 64
+#define RT_USING_SYSTEM_WORKQUEUE
+#define RT_SYSTEM_WORKQUEUE_STACKSIZE 16384
+#define RT_SYSTEM_WORKQUEUE_PRIORITY 23
+#define RT_USING_SERIAL
+#define RT_USING_SERIAL_V1
+#define RT_SERIAL_USING_DMA
+#define RT_SERIAL_RB_BUFSZ 64
+#define RT_USING_I2C
+#define RT_USING_I2C_BITOPS
+#define RT_USING_NULL
+#define RT_USING_ZERO
+#define RT_USING_RANDOM
+#define RT_USING_RTC
+#define RT_USING_SOFT_RTC
+#define RT_USING_SDIO
+#define RT_SDIO_STACK_SIZE 16384
+#define RT_SDIO_THREAD_PRIORITY 15
+#define RT_MMCSD_STACK_SIZE 8192
+#define RT_MMCSD_THREAD_PREORITY 22
+#define RT_MMCSD_MAX_PARTITION 16
+#define RT_USING_SPI
+#define RT_USING_WDT
+#define RT_USING_TOUCH
+#define RT_USING_LCD
+#define RT_USING_OFW
+#define RT_FDT_EARLYCON_MSG_SIZE 128
+#define RT_USING_OFW_BUS_RANGES_NUMBER 8
+#define RT_USING_PIC
+#define MAX_HANDLERS 256
+#define RT_PIC_ARM_GIC
+#define RT_PIC_ARM_GIC_MAX_NR 1
+#define RT_USING_PIN
+#define RT_USING_KTIME
+#define RT_USING_CLK
+#define RT_USING_HWTIMER
+#define RT_HWTIMER_ARM_ARCH
+/* end of Device Drivers */
+
+/* C/C++ and POSIX layer */
+
+/* ISO-ANSI C layer */
+
+/* Timezone and Daylight Saving Time */
+
+#define RT_LIBC_USING_LIGHT_TZ_DST
+#define RT_LIBC_TZ_DEFAULT_HOUR 8
+#define RT_LIBC_TZ_DEFAULT_MIN 0
+#define RT_LIBC_TZ_DEFAULT_SEC 0
+/* end of Timezone and Daylight Saving Time */
+/* end of ISO-ANSI C layer */
+
+/* POSIX (Portable Operating System Interface) layer */
+
+#define RT_USING_POSIX_FS
+#define RT_USING_POSIX_DEVIO
+#define RT_USING_POSIX_STDIO
+#define RT_USING_POSIX_POLL
+#define RT_USING_POSIX_EPOLL
+#define RT_USING_POSIX_SIGNALFD
+#define RT_SIGNALFD_MAX_NUM 10
+#define RT_USING_POSIX_TERMIOS
+#define RT_USING_POSIX_DELAY
+#define RT_USING_POSIX_CLOCK
+#define RT_USING_POSIX_TIMER
+
+/* Interprocess Communication (IPC) */
+
+
+/* Socket is in the 'Network' category */
+
+/* end of Interprocess Communication (IPC) */
+/* end of POSIX (Portable Operating System Interface) layer */
+/* end of C/C++ and POSIX layer */
+
+/* Network */
+
+#define RT_USING_SAL
+#define SAL_INTERNET_CHECK
+
+/* Docking with protocol stacks */
+
+#define SAL_USING_LWIP
+/* end of Docking with protocol stacks */
+#define SAL_USING_POSIX
+#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
+#define RT_USING_LWIP
+#define RT_USING_LWIP212
+#define RT_USING_LWIP_VER_NUM 0x20102
+#define RT_LWIP_MEM_ALIGNMENT 4
+#define RT_LWIP_IGMP
+#define RT_LWIP_ICMP
+#define RT_LWIP_DNS
+#define RT_LWIP_DHCP
+#define IP_SOF_BROADCAST 1
+#define IP_SOF_BROADCAST_RECV 1
+
+/* Static IPv4 Address */
+
+#define RT_LWIP_IPADDR "192.168.137.100"
+#define RT_LWIP_GWADDR "192.168.137.1"
+#define RT_LWIP_MSKADDR "255.255.255.0"
+/* end of Static IPv4 Address */
+#define RT_LWIP_UDP
+#define RT_LWIP_TCP
+#define RT_LWIP_RAW
+#define RT_MEMP_NUM_NETCONN 16
+#define RT_LWIP_PBUF_NUM 16
+#define RT_LWIP_RAW_PCB_NUM 4
+#define RT_LWIP_UDP_PCB_NUM 8
+#define RT_LWIP_TCP_PCB_NUM 8
+#define RT_LWIP_TCP_SEG_NUM 40
+#define RT_LWIP_TCP_SND_BUF 8192
+#define RT_LWIP_TCP_WND 8192
+#define RT_LWIP_TCPTHREAD_PRIORITY 10
+#define RT_LWIP_TCPTHREAD_MBOX_SIZE 8
+#define RT_LWIP_TCPTHREAD_STACKSIZE 32768
+#define LWIP_NO_TX_THREAD
+#define RT_LWIP_ETHTHREAD_PRIORITY 12
+#define RT_LWIP_ETHTHREAD_STACKSIZE 32768
+#define RT_LWIP_ETHTHREAD_MBOX_SIZE 8
+#define RT_LWIP_REASSEMBLY_FRAG
+#define LWIP_NETIF_STATUS_CALLBACK 1
+#define LWIP_NETIF_LINK_CALLBACK 1
+#define RT_LWIP_NETIF_NAMESIZE 6
+#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 RT_LWIP_NETIF_LOOPBACK
+#define LWIP_NETIF_LOOPBACK 1
+#define RT_LWIP_USING_PING
+/* end of Network */
+
+/* Memory protection */
+
+/* end of Memory protection */
+
+/* Utilities */
+
+#define RT_USING_UTEST
+#define UTEST_THR_STACK_SIZE 8192
+#define UTEST_THR_PRIORITY 20
+#define RT_USING_RESOURCE_ID
+#define RT_USING_ADT
+#define RT_USING_ADT_AVL
+#define RT_USING_ADT_BITMAP
+#define RT_USING_ADT_HASHMAP
+#define RT_USING_ADT_REF
+/* end of Utilities */
+#define RT_USING_LWP
+#define LWP_DEBUG
+#define RT_LWP_MAX_NR 30
+#define LWP_TASK_STACK_SIZE 16384
+#define RT_CH_MSG_MAX_NR 1024
+#define LWP_TID_MAX_NR 64
+#define RT_LWP_SHM_MAX_NR 64
+#define RT_USING_LDSO
+#define LWP_USING_TERMINAL
+#define LWP_PTY_MAX_PARIS_LIMIT 64
+#define RT_USING_VDSO
+
+/* Memory management */
+
+#define RT_USING_MEMBLOCK
+#define RT_INIT_MEMORY_REGIONS 128
+/* end of Memory management */
+
+/* Using USB legacy version */
+
+/* end of Using USB legacy version */
+/* end of RT-Thread Components */
+
+/* RT-Thread Utestcases */
+
+#define RT_USING_UTESTCASES
+
+/* Utest Self Testcase */
+
+/* end of Utest Self Testcase */
+
+/* Kernel Testcase */
+
+#define UTEST_SCHEDULER_TC
+
+/* Kernel SMP Testcase */
+
+/* end of Kernel SMP Testcase */
+/* end of Kernel Testcase */
+
+/* CPP11 Testcase */
+
+/* end of CPP11 Testcase */
+
+/* Utest Serial Testcase */
+
+/* end of Utest Serial Testcase */
+
+/* Utest IPC Testcase */
+
+/* end of Utest IPC Testcase */
+
+/* RTT Posix Testcase */
+
+/* end of RTT Posix Testcase */
+
+/* Memory Management Subsytem Testcase */
+
+/* end of Memory Management Subsytem Testcase */
+
+/* Tmpfs Testcase */
+
+/* end of Tmpfs Testcase */
+
+/* SMP Testcase */
+
+/* end of SMP Testcase */
+/* end of RT-Thread Utestcases */
+
+/* RT-Thread online packages */
+
+/* IoT - internet of things */
+
+
+/* Wi-Fi */
+
+/* Marvell WiFi */
+
+/* end of Marvell WiFi */
+
+/* Wiced WiFi */
+
+/* end of Wiced WiFi */
+
+/* CYW43012 WiFi */
+
+/* end of CYW43012 WiFi */
+
+/* BL808 WiFi */
+
+/* end of BL808 WiFi */
+
+/* CYW43439 WiFi */
+
+/* end of CYW43439 WiFi */
+/* end of Wi-Fi */
+
+/* IoT Cloud */
+
+/* end of IoT Cloud */
+/* end of IoT - internet of things */
+
+/* security packages */
+
+/* end of security packages */
+
+/* language packages */
+
+/* JSON: JavaScript Object Notation, a lightweight data-interchange format */
+
+/* end of JSON: JavaScript Object Notation, a lightweight data-interchange format */
+
+/* XML: Extensible Markup Language */
+
+/* end of XML: Extensible Markup Language */
+/* end of language packages */
+
+/* multimedia packages */
+
+/* LVGL: powerful and easy-to-use embedded GUI library */
+
+/* end of LVGL: powerful and easy-to-use embedded GUI library */
+
+/* u8g2: a monochrome graphic library */
+
+/* end of u8g2: a monochrome graphic library */
+/* end of multimedia packages */
+
+/* tools packages */
+
+/* end of tools packages */
+
+/* system packages */
+
+/* enhanced kernel services */
+
+/* end of enhanced kernel services */
+
+/* acceleration: Assembly language or algorithmic acceleration packages */
+
+/* end of acceleration: Assembly language or algorithmic acceleration packages */
+
+/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */
+
+/* end of CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */
+
+/* Micrium: Micrium software products porting for RT-Thread */
+
+/* end of Micrium: Micrium software products porting for RT-Thread */
+/* end of system packages */
+
+/* peripheral libraries and drivers */
+
+/* HAL & SDK Drivers */
+
+/* STM32 HAL & SDK Drivers */
+
+/* end of STM32 HAL & SDK Drivers */
+
+/* Kendryte SDK */
+
+/* end of Kendryte SDK */
+/* end of HAL & SDK Drivers */
+
+/* sensors drivers */
+
+/* end of sensors drivers */
+
+/* touch drivers */
+
+/* end of touch drivers */
+/* end of peripheral libraries and drivers */
+
+/* AI packages */
+
+/* end of AI packages */
+
+/* Signal Processing and Control Algorithm Packages */
+
+/* end of Signal Processing and Control Algorithm Packages */
+
+/* miscellaneous packages */
+
+/* project laboratory */
+
+/* end of project laboratory */
+
+/* samples: kernel and components samples */
+
+/* end of samples: kernel and components samples */
+
+/* entertainment: terminal games and other interesting software packages */
+
+/* end of entertainment: terminal games and other interesting software packages */
+/* end of miscellaneous packages */
+
+/* Arduino libraries */
+
+
+/* Projects and Demos */
+
+/* end of Projects and Demos */
+
+/* Sensors */
+
+/* end of Sensors */
+
+/* Display */
+
+/* end of Display */
+
+/* Timing */
+
+/* end of Timing */
+
+/* Data Processing */
+
+/* end of Data Processing */
+
+/* Data Storage */
+
+/* Communication */
+
+/* end of Communication */
+
+/* Device Control */
+
+/* end of Device Control */
+
+/* Other */
+
+/* end of Other */
+
+/* Signal IO */
+
+/* end of Signal IO */
+
+/* Uncategorized */
+
+/* end of Arduino libraries */
+/* end of RT-Thread online packages */
+
+/* Privated Packages of RealThread */
+
+
+/* Network Utilities */
+
+/* end of Network Utilities */
+
+/* RT-Thread Smart */
+
+#define PKG_USING_UKERNEL
+#define PKG_USING_UKERNEL_LATEST_VERSION
+#define RT_USING_NETIF_LOOPBACK
+#define RT_USING_DFS_PROCFS
+#define SAL_USING_AF_UNIX
+/* end of RT-Thread Smart */
+#define PKG_USING_EXT4
+#define PKG_USING_EXT4_SMART_DFS_VERSION
+/* end of Privated Packages of RealThread */
+#define BCM2711_SOC
+
+/* Hardware Drivers Config */
+
+#define BSP_USING_PL011
+#define BSP_USING_SDHCI
+#define RT_USING_SDHCI
+/* end of Hardware Drivers Config */
+
+#endif

+ 54 - 0
bsp/raspberry-pi/raspi-dm2.0/rtconfig.py

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