From c1db34983df5372799c801836786b66666414db4 Mon Sep 17 00:00:00 2001 From: zhujiale <945386260@qq.com> Date: Mon, 28 Oct 2024 15:57:45 +0800 Subject: [PATCH] [rpi4b] add new bsp for qemu-rpi4b --- bsp/raspberry-pi/raspi-dm2.0/.config | 1541 +++++++ bsp/raspberry-pi/raspi-dm2.0/Kconfig | 22 + bsp/raspberry-pi/raspi-dm2.0/README.md | 33 + bsp/raspberry-pi/raspi-dm2.0/SConscript | 14 + bsp/raspberry-pi/raspi-dm2.0/SConstruct | 30 + .../raspi-dm2.0/applications/SConscript | 14 + .../raspi-dm2.0/applications/main.c | 19 + .../raspi-dm2.0/bcm2711-rpi-4-b.dtb | Bin 0 -> 49833 bytes bsp/raspberry-pi/raspi-dm2.0/drivers/Kconfig | 13 + .../raspi-dm2.0/drivers/SConscript | 25 + bsp/raspberry-pi/raspi-dm2.0/drivers/board.c | 32 + bsp/raspberry-pi/raspi-dm2.0/drivers/board.h | 35 + bsp/raspberry-pi/raspi-dm2.0/drivers/drv_sd.c | 219 + bsp/raspberry-pi/raspi-dm2.0/drivers/drv_sd.h | 117 + .../raspi-dm2.0/drivers/drv_uart.c | 418 ++ .../raspi-dm2.0/drivers/drv_uart.h | 108 + .../raspi-dm2.0/drivers/sdhci/Kconfig | 3 + .../raspi-dm2.0/drivers/sdhci/SConscript | 18 + .../drivers/sdhci/include/sdhci-platform.h | 74 + .../raspi-dm2.0/drivers/sdhci/include/sdhci.h | 815 ++++ .../drivers/sdhci/include/sdhci_dma.h | 31 + .../drivers/sdhci/include/sdhci_host.h | 411 ++ .../drivers/sdhci/include/sdhci_misc.h | 76 + .../sdhci/sdhci-platform/sdhci-platform.c | 125 + .../raspi-dm2.0/drivers/sdhci/sdhci.c | 3606 +++++++++++++++++ .../raspi-dm2.0/drivers/sdhci/src/fit-mmc.c | 303 ++ .../raspi-dm2.0/drivers/sdhci/src/sdhci_dma.c | 44 + .../drivers/sdhci/src/sdhci_voltage.c | 37 + bsp/raspberry-pi/raspi-dm2.0/qemu.sh | 9 + bsp/raspberry-pi/raspi-dm2.0/rtconfig.h | 575 +++ bsp/raspberry-pi/raspi-dm2.0/rtconfig.py | 54 + 31 files changed, 8821 insertions(+) create mode 100644 bsp/raspberry-pi/raspi-dm2.0/.config create mode 100644 bsp/raspberry-pi/raspi-dm2.0/Kconfig create mode 100644 bsp/raspberry-pi/raspi-dm2.0/README.md create mode 100644 bsp/raspberry-pi/raspi-dm2.0/SConscript create mode 100644 bsp/raspberry-pi/raspi-dm2.0/SConstruct create mode 100644 bsp/raspberry-pi/raspi-dm2.0/applications/SConscript create mode 100644 bsp/raspberry-pi/raspi-dm2.0/applications/main.c create mode 100644 bsp/raspberry-pi/raspi-dm2.0/bcm2711-rpi-4-b.dtb create mode 100644 bsp/raspberry-pi/raspi-dm2.0/drivers/Kconfig create mode 100644 bsp/raspberry-pi/raspi-dm2.0/drivers/SConscript create mode 100644 bsp/raspberry-pi/raspi-dm2.0/drivers/board.c create mode 100644 bsp/raspberry-pi/raspi-dm2.0/drivers/board.h create mode 100644 bsp/raspberry-pi/raspi-dm2.0/drivers/drv_sd.c create mode 100644 bsp/raspberry-pi/raspi-dm2.0/drivers/drv_sd.h create mode 100644 bsp/raspberry-pi/raspi-dm2.0/drivers/drv_uart.c create mode 100644 bsp/raspberry-pi/raspi-dm2.0/drivers/drv_uart.h create mode 100644 bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/Kconfig create mode 100644 bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/SConscript create mode 100644 bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci-platform.h create mode 100644 bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci.h create mode 100644 bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci_dma.h create mode 100644 bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci_host.h create mode 100644 bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci_misc.h create mode 100644 bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/sdhci-platform/sdhci-platform.c create mode 100644 bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/sdhci.c create mode 100644 bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/src/fit-mmc.c create mode 100644 bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/src/sdhci_dma.c create mode 100644 bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/src/sdhci_voltage.c create mode 100644 bsp/raspberry-pi/raspi-dm2.0/qemu.sh create mode 100644 bsp/raspberry-pi/raspi-dm2.0/rtconfig.h create mode 100644 bsp/raspberry-pi/raspi-dm2.0/rtconfig.py diff --git a/bsp/raspberry-pi/raspi-dm2.0/.config b/bsp/raspberry-pi/raspi-dm2.0/.config new file mode 100644 index 0000000000..85349c254a --- /dev/null +++ b/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 diff --git a/bsp/raspberry-pi/raspi-dm2.0/Kconfig b/bsp/raspberry-pi/raspi-dm2.0/Kconfig new file mode 100644 index 0000000000..f62b1758e9 --- /dev/null +++ b/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" diff --git a/bsp/raspberry-pi/raspi-dm2.0/README.md b/bsp/raspberry-pi/raspi-dm2.0/README.md new file mode 100644 index 0000000000..9b16c4f3e8 --- /dev/null +++ b/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合入主线 | + diff --git a/bsp/raspberry-pi/raspi-dm2.0/SConscript b/bsp/raspberry-pi/raspi-dm2.0/SConscript new file mode 100644 index 0000000000..c7ef7659ec --- /dev/null +++ b/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') diff --git a/bsp/raspberry-pi/raspi-dm2.0/SConstruct b/bsp/raspberry-pi/raspi-dm2.0/SConstruct new file mode 100644 index 0000000000..55cab35463 --- /dev/null +++ b/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) diff --git a/bsp/raspberry-pi/raspi-dm2.0/applications/SConscript b/bsp/raspberry-pi/raspi-dm2.0/applications/SConscript new file mode 100644 index 0000000000..bda7b8b585 --- /dev/null +++ b/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') diff --git a/bsp/raspberry-pi/raspi-dm2.0/applications/main.c b/bsp/raspberry-pi/raspi-dm2.0/applications/main.c new file mode 100644 index 0000000000..882e458d93 --- /dev/null +++ b/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 +#include +#include + +int main(int argc, char** argv) +{ + rt_kprintf("Hi, this is RT-Thread!!\n"); + return 0; +} diff --git a/bsp/raspberry-pi/raspi-dm2.0/bcm2711-rpi-4-b.dtb b/bsp/raspberry-pi/raspi-dm2.0/bcm2711-rpi-4-b.dtb new file mode 100644 index 0000000000000000000000000000000000000000..759c21568f9085d1b260f3d4910930536dae5b3d GIT binary patch literal 49833 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 literal 0 HcmV?d00001 diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/Kconfig b/bsp/raspberry-pi/raspi-dm2.0/drivers/Kconfig new file mode 100644 index 0000000000..34d491f587 --- /dev/null +++ b/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 diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/SConscript b/bsp/raspberry-pi/raspi-dm2.0/drivers/SConscript new file mode 100644 index 0000000000..1a8ce83b72 --- /dev/null +++ b/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') diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/board.c b/bsp/raspberry-pi/raspi-dm2.0/drivers/board.c new file mode 100644 index 0000000000..7261199d46 --- /dev/null +++ b/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 + +#include +#include +#include +#include +#include "board.h" +#include "drv_uart.h" + +#include "cp15.h" +#include "mmu.h" +#include + +#ifdef RT_USING_SMART +#include +#endif +void rt_hw_board_init(void) +{ + rt_hw_common_setup(); +} diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/board.h b/bsp/raspberry-pi/raspi-dm2.0/drivers/board.h new file mode 100644 index 0000000000..88e8269855 --- /dev/null +++ b/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 +#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 diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/drv_sd.c b/bsp/raspberry-pi/raspi-dm2.0/drivers/drv_sd.c new file mode 100644 index 0000000000..2e8103c995 --- /dev/null +++ b/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 +#include +#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 +#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); + + diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/drv_sd.h b/bsp/raspberry-pi/raspi-dm2.0/drivers/drv_sd.h new file mode 100644 index 0000000000..506b1fafd9 --- /dev/null +++ b/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 +#include +#include +#include +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 diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/drv_uart.c b/bsp/raspberry-pi/raspi-dm2.0/drivers/drv_uart.c new file mode 100644 index 0000000000..a72bbcd6e8 --- /dev/null +++ b/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 +#include +#include + +#include + +#include + +#include + +#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, + * pl011,mmio32, + */ + 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); diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/drv_uart.h b/bsp/raspberry-pi/raspi-dm2.0/drivers/drv_uart.h new file mode 100644 index 0000000000..b47afcce14 --- /dev/null +++ b/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__ */ diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/Kconfig b/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/Kconfig new file mode 100644 index 0000000000..ab101b8be5 --- /dev/null +++ b/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 diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/SConscript b/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/SConscript new file mode 100644 index 0000000000..3eab8df97a --- /dev/null +++ b/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') diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci-platform.h b/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci-platform.h new file mode 100644 index 0000000000..bc5c7dab2a --- /dev/null +++ b/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 +#include +#include +#include +#include +#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 diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci.h b/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci.h new file mode 100644 index 0000000000..e58517d394 --- /dev/null +++ b/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 +#include +#include +/* + * 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 */ diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci_dma.h b/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci_dma.h new file mode 100644 index 0000000000..934e5c5bb1 --- /dev/null +++ b/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 +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 diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci_host.h b/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci_host.h new file mode 100644 index 0000000000..23d3a1fc65 --- /dev/null +++ b/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 +#include +#include +#include +#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 diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci_misc.h b/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci_misc.h new file mode 100644 index 0000000000..2205b1bac3 --- /dev/null +++ b/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 diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/sdhci-platform/sdhci-platform.c b/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/sdhci-platform/sdhci-platform.c new file mode 100644 index 0000000000..4272b24dea --- /dev/null +++ b/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); +} diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/sdhci.c b/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/sdhci.c new file mode 100644 index 0000000000..7d5d85f50f --- /dev/null +++ b/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 +#include "sdhci.h" +#include +#define DBG_TAG "SDHCI" +#ifdef DRV_DEBUG +#define DBG_LVL DBG_LOG +#else +#define DBG_LVL DBG_INFO +#endif /* DRV_DEBUG */ +#include +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); +} diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/src/fit-mmc.c b/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/src/fit-mmc.c new file mode 100644 index 0000000000..7c9eea3ba5 --- /dev/null +++ b/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 +#include "sdhci.h" +#include +#include +#include + + +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; +} diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/src/sdhci_dma.c b/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/src/sdhci_dma.c new file mode 100644 index 0000000000..29d296f9de --- /dev/null +++ b/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 + + +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); +} diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/src/sdhci_voltage.c b/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/src/sdhci_voltage.c new file mode 100644 index 0000000000..44ed683db9 --- /dev/null +++ b/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) +{ +} diff --git a/bsp/raspberry-pi/raspi-dm2.0/qemu.sh b/bsp/raspberry-pi/raspi-dm2.0/qemu.sh new file mode 100644 index 0000000000..b795a9bcb5 --- /dev/null +++ b/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' diff --git a/bsp/raspberry-pi/raspi-dm2.0/rtconfig.h b/bsp/raspberry-pi/raspi-dm2.0/rtconfig.h new file mode 100644 index 0000000000..a1a0ca4169 --- /dev/null +++ b/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 diff --git a/bsp/raspberry-pi/raspi-dm2.0/rtconfig.py b/bsp/raspberry-pi/raspi-dm2.0/rtconfig.py new file mode 100644 index 0000000000..106618e010 --- /dev/null +++ b/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'