diff --git a/bsp/ft2004/.config b/bsp/ft2004/.config new file mode 100644 index 0000000000000000000000000000000000000000..6bcf2ddb8dc00693b069dea6808bdedb8f96cdb8 --- /dev/null +++ b/bsp/ft2004/.config @@ -0,0 +1,686 @@ +# +# Automatically generated file; DO NOT EDIT. +# RT-Thread Project Configuration +# + +# +# RT-Thread Kernel +# +CONFIG_RT_NAME_MAX=32 +# CONFIG_RT_USING_ARCH_DATA_TYPE is not set +CONFIG_RT_USING_SMP=y +CONFIG_RT_CPUS_NR=4 +CONFIG_RT_ALIGN_SIZE=128 +# CONFIG_RT_THREAD_PRIORITY_8 is not set +CONFIG_RT_THREAD_PRIORITY_32=y +# CONFIG_RT_THREAD_PRIORITY_256 is not set +CONFIG_RT_THREAD_PRIORITY_MAX=32 +CONFIG_RT_TICK_PER_SECOND=100 +CONFIG_RT_USING_OVERFLOW_CHECK=y +CONFIG_RT_USING_HOOK=y +CONFIG_RT_USING_IDLE_HOOK=y +CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 +CONFIG_IDLE_THREAD_STACK_SIZE=4096 +CONFIG_RT_USING_TIMER_SOFT=y +CONFIG_RT_TIMER_THREAD_PRIO=4 +CONFIG_RT_TIMER_THREAD_STACK_SIZE=512 + +# +# kservice optimization +# +# CONFIG_RT_KSERVICE_USING_STDLIB is not set +# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set +CONFIG_RT_DEBUG=y +CONFIG_RT_DEBUG_COLOR=y +# CONFIG_RT_DEBUG_INIT_CONFIG is not set +# CONFIG_RT_DEBUG_THREAD_CONFIG is not set +# CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set +# CONFIG_RT_DEBUG_IPC_CONFIG is not set +# CONFIG_RT_DEBUG_TIMER_CONFIG is not set +# CONFIG_RT_DEBUG_IRQ_CONFIG is not set +# CONFIG_RT_DEBUG_MEM_CONFIG is not set +# CONFIG_RT_DEBUG_SLAB_CONFIG is not set +# CONFIG_RT_DEBUG_MEMHEAP_CONFIG is not set +# CONFIG_RT_DEBUG_MODULE_CONFIG is not set + +# +# Inter-Thread communication +# +CONFIG_RT_USING_SEMAPHORE=y +CONFIG_RT_USING_MUTEX=y +CONFIG_RT_USING_EVENT=y +CONFIG_RT_USING_MAILBOX=y +CONFIG_RT_USING_MESSAGEQUEUE=y +# CONFIG_RT_USING_SIGNALS is not set + +# +# Memory Management +# +# CONFIG_RT_USING_MEMPOOL is not set +CONFIG_RT_USING_MEMHEAP=y +# CONFIG_RT_USING_NOHEAP is not set +# CONFIG_RT_USING_SMALL_MEM is not set +CONFIG_RT_USING_SLAB=y +# CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set +# CONFIG_RT_USING_USERHEAP is not set +# CONFIG_RT_USING_MEMTRACE is not set +CONFIG_RT_USING_HEAP=y + +# +# Kernel Device Object +# +CONFIG_RT_USING_DEVICE=y +# CONFIG_RT_USING_DEVICE_OPS is not set +CONFIG_RT_USING_INTERRUPT_INFO=y +CONFIG_RT_USING_CONSOLE=y +CONFIG_RT_CONSOLEBUF_SIZE=4096 +CONFIG_RT_CONSOLE_DEVICE_NAME="uart1" +CONFIG_RT_VER_NUM=0x40004 +CONFIG_ARCH_ARM=y +# CONFIG_RT_USING_CPU_FFS is not set +CONFIG_ARCH_ARM_CORTEX_A=y +# CONFIG_RT_SMP_AUTO_BOOT is not set +# CONFIG_RT_USING_GIC_V2 is not set +CONFIG_RT_USING_GIC_V3=y +# CONFIG_RT_NO_USING_GIC is not set +# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set + +# +# RT-Thread Components +# +CONFIG_RT_USING_COMPONENTS_INIT=y +CONFIG_RT_USING_USER_MAIN=y +CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 +CONFIG_RT_MAIN_THREAD_PRIORITY=10 + +# +# C++ features +# +# CONFIG_RT_USING_CPLUSPLUS is not set + +# +# Command shell +# +CONFIG_RT_USING_FINSH=y +CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_USING_HISTORY=y +CONFIG_FINSH_HISTORY_LINES=5 +CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_USING_DESCRIPTION=y +# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_CMD_SIZE=128 +# CONFIG_FINSH_USING_AUTH is not set +CONFIG_FINSH_USING_MSH=y +CONFIG_FINSH_USING_MSH_DEFAULT=y +# CONFIG_FINSH_USING_MSH_ONLY is not set +CONFIG_FINSH_ARG_MAX=10 + +# +# Device virtual file system +# +CONFIG_RT_USING_DFS=y +CONFIG_DFS_USING_WORKDIR=y +CONFIG_DFS_FILESYSTEMS_MAX=2 +CONFIG_DFS_FILESYSTEM_TYPES_MAX=2 +CONFIG_DFS_FD_MAX=16 +# CONFIG_RT_USING_DFS_MNTTABLE is not set +CONFIG_RT_USING_DFS_ELMFAT=y + +# +# elm-chan's FatFs, Generic FAT Filesystem Module +# +CONFIG_RT_DFS_ELM_CODE_PAGE=437 +CONFIG_RT_DFS_ELM_WORD_ACCESS=y +# CONFIG_RT_DFS_ELM_USE_LFN_0 is not set +# CONFIG_RT_DFS_ELM_USE_LFN_1 is not set +# CONFIG_RT_DFS_ELM_USE_LFN_2 is not set +CONFIG_RT_DFS_ELM_USE_LFN_3=y +CONFIG_RT_DFS_ELM_USE_LFN=3 +CONFIG_RT_DFS_ELM_LFN_UNICODE_0=y +# CONFIG_RT_DFS_ELM_LFN_UNICODE_1 is not set +# CONFIG_RT_DFS_ELM_LFN_UNICODE_2 is not set +# CONFIG_RT_DFS_ELM_LFN_UNICODE_3 is not set +CONFIG_RT_DFS_ELM_LFN_UNICODE=0 +CONFIG_RT_DFS_ELM_MAX_LFN=255 +CONFIG_RT_DFS_ELM_DRIVES=2 +CONFIG_RT_DFS_ELM_MAX_SECTOR_SIZE=512 +# CONFIG_RT_DFS_ELM_USE_ERASE is not set +CONFIG_RT_DFS_ELM_REENTRANT=y +CONFIG_RT_USING_DFS_DEVFS=y +# CONFIG_RT_USING_DFS_ROMFS is not set +# CONFIG_RT_USING_DFS_RAMFS is not set +# CONFIG_RT_USING_DFS_NFS is not set + +# +# Device Drivers +# +CONFIG_RT_USING_DEVICE_IPC=y +CONFIG_RT_PIPE_BUFSZ=512 +# CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set +CONFIG_RT_USING_SERIAL=y +CONFIG_RT_SERIAL_USING_DMA=y +CONFIG_RT_SERIAL_RB_BUFSZ=256 +CONFIG_RT_USING_CAN=y +# CONFIG_RT_CAN_USING_HDR is not set +# CONFIG_RT_USING_HWTIMER is not set +# CONFIG_RT_USING_CPUTIME is not set +# CONFIG_RT_USING_I2C is not set +# CONFIG_RT_USING_PHY is not set +# CONFIG_RT_USING_PIN is not set +# CONFIG_RT_USING_ADC is not set +# CONFIG_RT_USING_DAC is not set +# CONFIG_RT_USING_PWM is not set +# CONFIG_RT_USING_MTD_NOR is not set +# CONFIG_RT_USING_MTD_NAND is not set +# CONFIG_RT_USING_PM is not set +# CONFIG_RT_USING_RTC is not set +CONFIG_RT_USING_SDIO=y +CONFIG_RT_SDIO_STACK_SIZE=512 +CONFIG_RT_SDIO_THREAD_PRIORITY=15 +CONFIG_RT_MMCSD_STACK_SIZE=1024 +CONFIG_RT_MMCSD_THREAD_PREORITY=22 +CONFIG_RT_MMCSD_MAX_PARTITION=16 +# CONFIG_RT_SDIO_DEBUG is not set +CONFIG_RT_USING_SPI=y +CONFIG_RT_USING_QSPI=y +# CONFIG_RT_USING_SPI_MSD is not set +CONFIG_RT_USING_SFUD=y +CONFIG_RT_SFUD_USING_SFDP=y +CONFIG_RT_SFUD_USING_FLASH_INFO_TABLE=y +CONFIG_RT_SFUD_USING_QSPI=y +CONFIG_RT_SFUD_SPI_MAX_HZ=50000000 +# CONFIG_RT_DEBUG_SFUD is not set +# CONFIG_RT_USING_ENC28J60 is not set +# CONFIG_RT_USING_SPI_WIFI is not set +# CONFIG_RT_USING_WDT is not set +# CONFIG_RT_USING_AUDIO is not set +# CONFIG_RT_USING_SENSOR is not set +# CONFIG_RT_USING_TOUCH is not set +# CONFIG_RT_USING_HWCRYPTO is not set +# CONFIG_RT_USING_PULSE_ENCODER is not set +# CONFIG_RT_USING_INPUT_CAPTURE is not set +# CONFIG_RT_USING_WIFI is not set + +# +# Using USB +# +# CONFIG_RT_USING_USB_HOST is not set +# CONFIG_RT_USING_USB_DEVICE is not set + +# +# POSIX layer and C standard library +# +# CONFIG_RT_USING_LIBC is not set +# CONFIG_RT_USING_PTHREADS is not set +CONFIG_RT_LIBC_USING_TIME=y +CONFIG_RT_LIBC_FIXED_TIMEZONE=8 + +# +# Network +# + +# +# Socket abstraction layer +# +# CONFIG_RT_USING_SAL is not set + +# +# Network interface device +# +CONFIG_RT_USING_NETDEV=y +CONFIG_NETDEV_USING_IFCONFIG=y +CONFIG_NETDEV_USING_PING=y +CONFIG_NETDEV_USING_NETSTAT=y +CONFIG_NETDEV_USING_AUTO_DEFAULT=y +# CONFIG_NETDEV_USING_IPV6 is not set +CONFIG_NETDEV_IPV4=1 +CONFIG_NETDEV_IPV6=0 +# CONFIG_NETDEV_IPV6_SCOPES is not set + +# +# light weight TCP/IP stack +# +CONFIG_RT_USING_LWIP=y +# CONFIG_RT_USING_LWIP141 is not set +# CONFIG_RT_USING_LWIP202 is not set +CONFIG_RT_USING_LWIP212=y +# CONFIG_RT_USING_LWIP_IPV6 is not set +CONFIG_RT_LWIP_MEM_ALIGNMENT=4 +CONFIG_RT_LWIP_IGMP=y +CONFIG_RT_LWIP_ICMP=y +# CONFIG_RT_LWIP_SNMP is not set +CONFIG_RT_LWIP_DNS=y +# CONFIG_RT_LWIP_DHCP is not set + +# +# Static IPv4 Address +# +CONFIG_RT_LWIP_IPADDR="192.168.3.20" +CONFIG_RT_LWIP_GWADDR="192.168.3.1" +CONFIG_RT_LWIP_MSKADDR="255.255.255.0" +CONFIG_RT_LWIP_UDP=y +CONFIG_RT_LWIP_TCP=y +CONFIG_RT_LWIP_RAW=y +# CONFIG_RT_LWIP_PPP is not set +CONFIG_RT_MEMP_NUM_NETCONN=8 +CONFIG_RT_LWIP_PBUF_NUM=16 +CONFIG_RT_LWIP_RAW_PCB_NUM=4 +CONFIG_RT_LWIP_UDP_PCB_NUM=4 +CONFIG_RT_LWIP_TCP_PCB_NUM=4 +CONFIG_RT_LWIP_TCP_SEG_NUM=40 +CONFIG_RT_LWIP_TCP_SND_BUF=8196 +CONFIG_RT_LWIP_TCP_WND=8196 +CONFIG_RT_LWIP_TCPTHREAD_PRIORITY=10 +CONFIG_RT_LWIP_TCPTHREAD_MBOX_SIZE=8 +CONFIG_RT_LWIP_TCPTHREAD_STACKSIZE=1024 +# CONFIG_LWIP_NO_RX_THREAD is not set +# CONFIG_LWIP_NO_TX_THREAD is not set +CONFIG_RT_LWIP_ETHTHREAD_PRIORITY=12 +CONFIG_RT_LWIP_ETHTHREAD_STACKSIZE=1024 +CONFIG_RT_LWIP_ETHTHREAD_MBOX_SIZE=8 +# CONFIG_RT_LWIP_REASSEMBLY_FRAG is not set +CONFIG_LWIP_NETIF_STATUS_CALLBACK=1 +CONFIG_LWIP_NETIF_LINK_CALLBACK=1 +CONFIG_SO_REUSE=1 +CONFIG_LWIP_SO_RCVTIMEO=1 +CONFIG_LWIP_SO_SNDTIMEO=1 +CONFIG_LWIP_SO_RCVBUF=1 +CONFIG_LWIP_SO_LINGER=0 +# CONFIG_RT_LWIP_NETIF_LOOPBACK is not set +CONFIG_LWIP_NETIF_LOOPBACK=0 +# CONFIG_RT_LWIP_STATS is not set +# CONFIG_RT_LWIP_USING_HW_CHECKSUM is not set +CONFIG_RT_LWIP_USING_PING=y +# CONFIG_RT_LWIP_DEBUG is not set + +# +# AT commands +# +# CONFIG_RT_USING_AT is not set +# CONFIG_LWIP_USING_DHCPD is not set + +# +# VBUS(Virtual Software BUS) +# +# CONFIG_RT_USING_VBUS is not set + +# +# Utilities +# +# CONFIG_RT_USING_RYM is not set +# CONFIG_RT_USING_ULOG is not set +# CONFIG_RT_USING_UTEST is not set +# CONFIG_RT_USING_RT_LINK is not set +# CONFIG_RT_USING_LWP is not set + +# +# RT-Thread Utestcases +# +# CONFIG_RT_USING_UTESTCASES is not set + +# +# RT-Thread online packages +# + +# +# IoT - internet of things +# +# CONFIG_PKG_USING_LORAWAN_DRIVER is not set +# CONFIG_PKG_USING_PAHOMQTT is not set +# CONFIG_PKG_USING_UMQTT is not set +# CONFIG_PKG_USING_WEBCLIENT is not set +# CONFIG_PKG_USING_WEBNET is not set +# CONFIG_PKG_USING_MONGOOSE is not set +# CONFIG_PKG_USING_MYMQTT is not set +# CONFIG_PKG_USING_KAWAII_MQTT is not set +# CONFIG_PKG_USING_BC28_MQTT is not set +# CONFIG_PKG_USING_WEBTERMINAL is not set +# CONFIG_PKG_USING_CJSON is not set +# CONFIG_PKG_USING_JSMN is not set +# CONFIG_PKG_USING_LIBMODBUS is not set +# CONFIG_PKG_USING_FREEMODBUS is not set +# CONFIG_PKG_USING_LJSON is not set +# CONFIG_PKG_USING_EZXML is not set +# CONFIG_PKG_USING_NANOPB is not set + +# +# Wi-Fi +# + +# +# Marvell WiFi +# +# CONFIG_PKG_USING_WLANMARVELL is not set + +# +# Wiced WiFi +# +# CONFIG_PKG_USING_WLAN_WICED is not set +# CONFIG_PKG_USING_RW007 is not set +# CONFIG_PKG_USING_COAP is not set +# CONFIG_PKG_USING_NOPOLL is not set +# CONFIG_PKG_USING_NETUTILS is not set +# CONFIG_PKG_USING_CMUX is not set +# CONFIG_PKG_USING_PPP_DEVICE is not set +# CONFIG_PKG_USING_AT_DEVICE is not set +# CONFIG_PKG_USING_ATSRV_SOCKET is not set +# CONFIG_PKG_USING_WIZNET is not set + +# +# IoT Cloud +# +# CONFIG_PKG_USING_ONENET is not set +# CONFIG_PKG_USING_GAGENT_CLOUD is not set +# CONFIG_PKG_USING_ALI_IOTKIT is not set +# CONFIG_PKG_USING_AZURE is not set +# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set +# CONFIG_PKG_USING_JIOT-C-SDK is not set +# CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set +# CONFIG_PKG_USING_JOYLINK is not set +# CONFIG_PKG_USING_NIMBLE is not set +# CONFIG_PKG_USING_OTA_DOWNLOADER is not set +# CONFIG_PKG_USING_IPMSG is not set +# CONFIG_PKG_USING_LSSDP is not set +# CONFIG_PKG_USING_AIRKISS_OPEN is not set +# CONFIG_PKG_USING_LIBRWS is not set +# CONFIG_PKG_USING_TCPSERVER is not set +# CONFIG_PKG_USING_PROTOBUF_C is not set +# CONFIG_PKG_USING_DLT645 is not set +# CONFIG_PKG_USING_QXWZ is not set +# CONFIG_PKG_USING_SMTP_CLIENT is not set +# CONFIG_PKG_USING_ABUP_FOTA is not set +# CONFIG_PKG_USING_LIBCURL2RTT is not set +# CONFIG_PKG_USING_CAPNP is not set +# CONFIG_PKG_USING_RT_CJSON_TOOLS is not set +# CONFIG_PKG_USING_AGILE_TELNET is not set +# CONFIG_PKG_USING_NMEALIB is not set +# CONFIG_PKG_USING_AGILE_JSMN is not set +# CONFIG_PKG_USING_PDULIB is not set +# CONFIG_PKG_USING_BTSTACK is not set +# CONFIG_PKG_USING_LORAWAN_ED_STACK is not set +# CONFIG_PKG_USING_WAYZ_IOTKIT is not set +# CONFIG_PKG_USING_MAVLINK is not set +# CONFIG_PKG_USING_RAPIDJSON is not set +# CONFIG_PKG_USING_BSAL is not set +# CONFIG_PKG_USING_AGILE_MODBUS is not set +# CONFIG_PKG_USING_AGILE_FTP is not set +# CONFIG_PKG_USING_EMBEDDEDPROTO is not set + +# +# security packages +# +# CONFIG_PKG_USING_MBEDTLS is not set +# CONFIG_PKG_USING_libsodium is not set +# CONFIG_PKG_USING_TINYCRYPT is not set +# CONFIG_PKG_USING_TFM is not set +# CONFIG_PKG_USING_YD_CRYPTO is not set + +# +# language packages +# +# CONFIG_PKG_USING_LUA is not set +# CONFIG_PKG_USING_JERRYSCRIPT is not set +# CONFIG_PKG_USING_MICROPYTHON is not set + +# +# multimedia packages +# +# CONFIG_PKG_USING_OPENMV is not set +# CONFIG_PKG_USING_MUPDF is not set +# CONFIG_PKG_USING_STEMWIN is not set +# CONFIG_PKG_USING_WAVPLAYER is not set +# CONFIG_PKG_USING_TJPGD is not set +# CONFIG_PKG_USING_PDFGEN is not set +# CONFIG_PKG_USING_HELIX is not set +# CONFIG_PKG_USING_AZUREGUIX is not set +# CONFIG_PKG_USING_TOUCHGFX2RTT is not set + +# +# 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_RDB is not set +# CONFIG_PKG_USING_QRCODE is not set +# CONFIG_PKG_USING_ULOG_EASYFLASH is not set +# CONFIG_PKG_USING_ULOG_FILE is not set +# CONFIG_PKG_USING_LOGMGR is not set +# CONFIG_PKG_USING_ADBD is not set +# CONFIG_PKG_USING_COREMARK is not set +# CONFIG_PKG_USING_DHRYSTONE is not set +# CONFIG_PKG_USING_MEMORYPERF is not set +# CONFIG_PKG_USING_NR_MICRO_SHELL is not set +# CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set +# CONFIG_PKG_USING_LUNAR_CALENDAR is not set +# CONFIG_PKG_USING_BS8116A is not set +# CONFIG_PKG_USING_GPS_RMC is not set +# CONFIG_PKG_USING_URLENCODE is not set +# CONFIG_PKG_USING_UMCN is not set +# CONFIG_PKG_USING_LWRB2RTT is not set +# CONFIG_PKG_USING_CPU_USAGE is not set +# CONFIG_PKG_USING_GBK2UTF8 is not set +# CONFIG_PKG_USING_VCONSOLE is not set +# CONFIG_PKG_USING_KDB is not set +# CONFIG_PKG_USING_WAMR is not set +# CONFIG_PKG_USING_MICRO_XRCE_DDS_CLIENT is not set +# CONFIG_PKG_USING_LWLOG is not set +# CONFIG_PKG_USING_ANV_TRACE is not set +# CONFIG_PKG_USING_ANV_MEMLEAK is not set +# CONFIG_PKG_USING_ANV_TESTSUIT is not set +# CONFIG_PKG_USING_ANV_BENCH is not set +# CONFIG_PKG_USING_DEVMEM is not set +# CONFIG_PKG_USING_MEM_SANDBOX is not set + +# +# system packages +# +# CONFIG_PKG_USING_GUIENGINE is not set +# CONFIG_PKG_USING_PERSIMMON is not set +# CONFIG_PKG_USING_CAIRO is not set +# CONFIG_PKG_USING_PIXMAN is not set +# CONFIG_PKG_USING_PARTITION is not set +# CONFIG_PKG_USING_FAL is not set +# CONFIG_PKG_USING_FLASHDB is not set +# CONFIG_PKG_USING_SQLITE is not set +# CONFIG_PKG_USING_RTI is not set +# CONFIG_PKG_USING_LITTLEVGL2RTT is not set +# CONFIG_PKG_USING_CMSIS is not set +# CONFIG_PKG_USING_DFS_YAFFS is not set +# CONFIG_PKG_USING_LITTLEFS is not set +# CONFIG_PKG_USING_DFS_JFFS2 is not set +# CONFIG_PKG_USING_DFS_UFFS is not set +# CONFIG_PKG_USING_LWEXT4 is not set +# CONFIG_PKG_USING_THREAD_POOL is not set +# CONFIG_PKG_USING_ROBOTS is not set +# CONFIG_PKG_USING_EV is not set +# CONFIG_PKG_USING_SYSWATCH is not set +# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set +# CONFIG_PKG_USING_PLCCORE is not set +# CONFIG_PKG_USING_RAMDISK is not set +# CONFIG_PKG_USING_MININI is not set +# CONFIG_PKG_USING_QBOOT is not set + +# +# Micrium: Micrium software products porting for RT-Thread +# +# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set +# CONFIG_PKG_USING_UCOSII_WRAPPER is not set +# CONFIG_PKG_USING_UC_CRC is not set +# CONFIG_PKG_USING_UC_CLK is not set +# CONFIG_PKG_USING_UC_COMMON is not set +# CONFIG_PKG_USING_UC_MODBUS is not set +# CONFIG_PKG_USING_PPOOL is not set +# CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# CONFIG_PKG_USING_RT_MEMCPY_CM is not set +# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set +# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set +# CONFIG_PKG_USING_QFPLIB_M3 is not set +# CONFIG_PKG_USING_LPM is not set +# CONFIG_PKG_USING_TLSF is not set +# CONFIG_PKG_USING_EVENT_RECORDER is not set + +# +# peripheral libraries and drivers +# +# CONFIG_PKG_USING_SENSORS_DRIVERS is not set +# CONFIG_PKG_USING_REALTEK_AMEBA is not set +# CONFIG_PKG_USING_SHT2X is not set +# CONFIG_PKG_USING_SHT3X is not set +# CONFIG_PKG_USING_AS7341 is not set +# CONFIG_PKG_USING_STM32_SDIO is not set +# CONFIG_PKG_USING_ICM20608 is not set +# CONFIG_PKG_USING_U8G2 is not set +# CONFIG_PKG_USING_BUTTON is not set +# CONFIG_PKG_USING_PCF8574 is not set +# CONFIG_PKG_USING_SX12XX is not set +# CONFIG_PKG_USING_SIGNAL_LED is not set +# CONFIG_PKG_USING_LEDBLINK is not set +# CONFIG_PKG_USING_LITTLED is not set +# CONFIG_PKG_USING_LKDGUI is not set +# CONFIG_PKG_USING_NRF5X_SDK is not set +# CONFIG_PKG_USING_NRFX is not set +# CONFIG_PKG_USING_WM_LIBRARIES is not set +# CONFIG_PKG_USING_KENDRYTE_SDK is not set +# CONFIG_PKG_USING_INFRARED is not set +# CONFIG_PKG_USING_ROSSERIAL is not set +# CONFIG_PKG_USING_AGILE_BUTTON is not set +# CONFIG_PKG_USING_AGILE_LED is not set +# CONFIG_PKG_USING_AT24CXX is not set +# CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set +# CONFIG_PKG_USING_AD7746 is not set +# CONFIG_PKG_USING_PCA9685 is not set +# CONFIG_PKG_USING_I2C_TOOLS is not set +# CONFIG_PKG_USING_NRF24L01 is not set +# CONFIG_PKG_USING_TOUCH_DRIVERS is not set +# CONFIG_PKG_USING_MAX17048 is not set +# CONFIG_PKG_USING_RPLIDAR is not set +# CONFIG_PKG_USING_AS608 is not set +# CONFIG_PKG_USING_RC522 is not set +# CONFIG_PKG_USING_WS2812B is not set +# CONFIG_PKG_USING_EMBARC_BSP is not set +# CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set +# CONFIG_PKG_USING_MULTI_RTIMER is not set +# CONFIG_PKG_USING_MAX7219 is not set +# CONFIG_PKG_USING_BEEP is not set +# CONFIG_PKG_USING_EASYBLINK is not set +# CONFIG_PKG_USING_PMS_SERIES is not set +# CONFIG_PKG_USING_CAN_YMODEM is not set +# CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set +# CONFIG_PKG_USING_QLED is not set +# CONFIG_PKG_USING_PAJ7620 is not set +# CONFIG_PKG_USING_AGILE_CONSOLE is not set +# CONFIG_PKG_USING_LD3320 is not set +# CONFIG_PKG_USING_WK2124 is not set +# CONFIG_PKG_USING_LY68L6400 is not set +# CONFIG_PKG_USING_DM9051 is not set +# CONFIG_PKG_USING_SSD1306 is not set +# CONFIG_PKG_USING_QKEY is not set +# CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_NES is not set +# CONFIG_PKG_USING_VIRTUAL_SENSOR is not set +# CONFIG_PKG_USING_VDEVICE is not set +# CONFIG_PKG_USING_SGM706 is not set +# CONFIG_PKG_USING_STM32WB55_SDK is not set +# CONFIG_PKG_USING_RDA58XX is not set +# CONFIG_PKG_USING_LIBNFC is not set +# CONFIG_PKG_USING_MFOC is not set +# CONFIG_PKG_USING_TMC51XX is not set + +# +# AI packages +# +# CONFIG_PKG_USING_LIBANN is not set +# CONFIG_PKG_USING_NNOM is not set +# CONFIG_PKG_USING_ONNX_BACKEND is not set +# CONFIG_PKG_USING_ONNX_PARSER is not set +# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set +# CONFIG_PKG_USING_ELAPACK is not set +# CONFIG_PKG_USING_ULAPACK is not set +# CONFIG_PKG_USING_QUEST is not set +# CONFIG_PKG_USING_NAXOS is not set + +# +# miscellaneous packages +# +# CONFIG_PKG_USING_LIBCSV is not set +# CONFIG_PKG_USING_OPTPARSE is not set +# CONFIG_PKG_USING_FASTLZ is not set +# CONFIG_PKG_USING_MINILZO is not set +# CONFIG_PKG_USING_QUICKLZ is not set +# CONFIG_PKG_USING_LZMA is not set +# CONFIG_PKG_USING_MULTIBUTTON is not set +# CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set +# CONFIG_PKG_USING_CANFESTIVAL is not set +# CONFIG_PKG_USING_ZLIB is not set +# CONFIG_PKG_USING_DSTR is not set +# CONFIG_PKG_USING_TINYFRAME is not set +# CONFIG_PKG_USING_KENDRYTE_DEMO is not set +# CONFIG_PKG_USING_DIGITALCTRL is not set +# CONFIG_PKG_USING_UPACKER is not set +# CONFIG_PKG_USING_UPARAM is not set + +# +# samples: kernel and components samples +# +# CONFIG_PKG_USING_KERNEL_SAMPLES is not set +# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set +# CONFIG_PKG_USING_NETWORK_SAMPLES is not set +# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set +# CONFIG_PKG_USING_HELLO is not set +# CONFIG_PKG_USING_VI is not set +# CONFIG_PKG_USING_KI is not set +# CONFIG_PKG_USING_ARMv7M_DWT is not set +# CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_UKAL is not set +# CONFIG_PKG_USING_CRCLIB is not set + +# +# entertainment: terminal games and other interesting software packages +# +# CONFIG_PKG_USING_THREES is not set +# CONFIG_PKG_USING_2048 is not set +# CONFIG_PKG_USING_SNAKE is not set +# CONFIG_PKG_USING_TETRIS is not set +# CONFIG_PKG_USING_DONUT is not set +# CONFIG_PKG_USING_ACLOCK is not set +# CONFIG_PKG_USING_LWGPS is not set +# CONFIG_PKG_USING_STATE_MACHINE is not set +# CONFIG_PKG_USING_MCURSES is not set +# CONFIG_PKG_USING_COWSAY is not set +CONFIG_FT2004=y + +# +# Hardware Drivers Config +# + +# +# On-chip Peripheral Drivers +# +CONFIG_BSP_USING_UART=y +CONFIG_RT_USING_UART1=y +# CONFIG_RT_USING_UART0 is not set +CONFIG_BSP_USING_SDC=y +# CONFIG_BSP_SDC_DEBUG_PRINT is not set +# CONFIG_BSP_SDC_USE_IRQ is not set +CONFIG_BSP_USING_GMAC=y +# CONFIG_BSP_USING_GMAC0 is not set +CONFIG_BSP_USING_GMAC1=y +CONFIG_RT_LWIP_ETH_PAD_SIZE=2 +# CONFIG_RAW_DATA_PRINT is not set +CONFIG_BSP_USE_SPI=y +# CONFIG_BSP_SPI_DEBUG is not set +CONFIG_BSP_USE_GPIO=y +# CONFIG_BSP_GPIO_DEBUG is not set +CONFIG_BSP_USE_CAN=y +CONFIG_BSP_USING_CAN0=y +# CONFIG_BSP_USING_CAN1 is not set +# CONFIG_BSP_USING_CAN0_DEBUG is not set + +# +# Board extended module Drivers +# diff --git a/bsp/ft2004/Kconfig b/bsp/ft2004/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..1bee562e48e901f03990016b09cccb60bce50a2f --- /dev/null +++ b/bsp/ft2004/Kconfig @@ -0,0 +1,30 @@ +mainmenu "RT-Thread Project Configuration" + +config BSP_DIR + string + option env="BSP_ROOT" + default "." + +config RTT_DIR + string + option env="RTT_ROOT" + default "../.." + +config PKGS_DIR + string + option env="PKGS_ROOT" + default "packages" + +source "$RTT_DIR/Kconfig" +source "$PKGS_DIR/Kconfig" + + +config FT2004 + bool + select ARCH_ARM_CORTEX_A + select RT_USING_COMPONENTS_INIT + select RT_USING_USER_MAIN + default y + + +source "./libraries/Kconfig" diff --git a/bsp/ft2004/README.md b/bsp/ft2004/README.md new file mode 100644 index 0000000000000000000000000000000000000000..96229d3c18c9eee01c6cc7ab5cc10a306f25867a --- /dev/null +++ b/bsp/ft2004/README.md @@ -0,0 +1,236 @@ +# ft2004 四核开发板 BSP 说明 + +## 简介 + +本文档为 飞腾技术公司 ft2000/4 开发板的 BSP (板级支持包) 说明。 + +主要内容如下: + +- 开发板资源介绍 +- BSP 外设支持 +- 使用方法 +- 相关实验 + +### 1. 开发板资源介绍 + +FT-2000/4 是一款面向桌面应用的高性能通用 4 核处理器。每 2 个核构成 1 +个处理器核簇(Cluster),并共享 L2 Cache。主要技术特征如下: + +- 兼容 ARM v8 64 位指令系统,兼容 32 位指令 +- 支持单精度、双精度浮点运算指令 +- 支持 ASIMD 处理指令 +- 集成 2 个 DDR4 通道,可对 DDR 存储数据进行实时加密 +- 集成 34 Lane PCIE3.0 接口:2 个 X16(每个可拆分成 2 个 X8),2 个 X1 +- 集成 2 个 GMAC,RGMII 接口,支持 10/100/1000 自适应 +- 集成 1 个 SD 卡控制器,兼容 SD 2.0 规范 +- 集成 1 个 HDAudio,支持音频输出,可同时支持最多 4 个 Codec +- 集成 SM2、SM3、SM4 模块 +- 集成 4 个 UART,1 个 LPC,32 个 GPIO,4 个 I2C,1 个 QSPI,2 个通 + 用 SPI,2 个 WDT,16 个外部中断(和 GPIO 共用 IO) +- 集成温度传感器 + +### 2. BSP 外设支持 + +| 外设名 | 支持情况 | 备注 | +| -------- | -------- | ---------------------- | +| ft_gicv3 | 支持 | gicv3 中断控制器 | +| ft_gmac | 支持 | ft gmac 千兆网卡控制器 | +| ft_i2c | 支持 | FT I2C | +| ft_qspi | 支持 | FT qspi 控制器 | +| ft_sd | 支持 | FT mmcsd 控制器 | +| ft_uart | 支持 | PrimeCell PL011 | +| ft_spi | 支持 | FT spi 控制器 | +| ft_gpio | 支持 | FT gpio 控制器 | +| ft_can | 支持 | FT can 控制器 | + +### 3. 使用方法 + +#### ubuntu 上环境搭建 + +1. 在 ubuntu 环境下通过指令,下载并安装交叉编译链 + +``` +sudo apt-get install gcc-arm-none-eabi +``` + +2. 安装之后,通过指令,确定交叉编译链安装完毕 + +``` +arm-none-eabi-gcc -v +``` + +3. 搭建 tftp 环境 + + - 在主机安装 tftp 服务 + > 使用 ubuntu 完成下列操作 + + ``` + sudo apt-get install tftp-hpa tftpd-hpa + sudo apt-get install xinetd + ``` + + - 新建 tftboot 目录,如: + `/mnt/d/tftboot` + + > 需要给 tftboot 目录执行权限`chmod 777 /**/tftboot` + + - 配置主机 tftpboot 服务 + + 新建并配置文件/etc/xinetd.d/tftp + + ``` + # /etc/xinetd.d/tftp + + server tftp + { + socket_type = dgram + protocol = udp + wait = yes + user = root + server = /usr/sbin/in.tftpd + server_args = -s /mnt/d/tftboot + disable = no + per_source = 11 + cps = 100 2 + flags = IPv4 + } + ``` + + - 启动主机 tftp 服务 + + ``` + sudo service tftpd-hpa start + ``` + + - 修改主机 tftp 配置 + 修改/etc/default/tftpd-hpa + + ``` + sudo nano /etc/default/tftpd-hpa + # /etc/default/tftpd-hpa + + TFTP_USERNAME="tftp" + TFTP_DIRECTORY="/mnt/d/tftboot" + TFTP_ADDRESS=":69" + TFTP_OPTIONS="-l -c -s" + ``` + + - 重启主机 tftp 服务 + > 每次开机要重启一次 + + ``` + sudo service tftpd-hpa restart + ``` + + - 测试主机 tftp 服务的可用性 + > 登录 tftp 服务,获取一个文件 + + ``` + $ tftp 192.168.4.50 + tftp> get test1234 + tftp> q + ``` + +#### 执行 + +1. 将本 bsp 包拷贝至 RT-THREAD bsp/目录下 + +1. 在 Ubuntu 终端下,切换至 bsp 目录 + +``` +cd xxx/bsp/ft2004 +``` + +3. 使用 scons -c 清空工程缓存 + +4. 使用 scons --menuconfig 配置需要的外设 + +![](./figures/onchipPeripheral.png) + +5. 使用 scons 编译代码,得到 rtthread.bin,并将 rtthread.bin 放入之前配置的 tftp 路径下。 + +6. 连接开发板对应串口到 PC, 在终端工具里打开相应的串口(115200-8-1-N)。 + +7. 将开发板网线接入局域网中 + +8. 本开发板自带 uboot,使用 uboot 自带 指令进行将 bin 文件下载至 ram 中 + +``` +setenv ipaddr 192.168.x.x +setenv serverip 192.168.x.x +setenv gatewayip 192.168.x.x +tftpboot 80100000 rtthread.bin +``` + +7. 执行跳转指令,便可以正常执行 + +``` +bootvx32 80100000 +或 +boot32 80100000 +``` + +![](./figures/启动演示图.png) + +### 5. 相关实验 + +#### 网卡 + +- 主机 ping 本机 指令 sudo ping 192.168.3.20 (默认) + +- rtt ping 主机 指令 ping 192.168.x.x (根据实际情况) + +- 通过界面 + +![](./figures/rttPing通过界面.png) + +#### sd 卡调试 + +- 通过基本命令进行,mv ,echo ,ls ,cd ,rm .... + +![](./figures/rttsd调试.png) + +#### spi flash 卡调试 + +- 找一块有 spi flash 插槽的 ft-2004 开发板,插入 sf25s 或 gd25q 系列 spi flash +- 配置 rt-thread 的编译选项,打开 BSP_USE_SPI 和 BSP_USE_GPIO 配置,关闭 BSP_USE_QSPI 配置,打开 rt-thread 的 SFUD 调试开关 +- 编译 rt-thread,加载版本启动,启动后显示 spi flash probe 成功 +- 执行 sf 基本操作,read, write, erase + +#### 推荐指令 + +1. sf probe S25FS256 + +2. sf read 0x1FFF000 16 + +3. sf write 0x1FFF000 16 25 68 78 95 15 75 20 + +4. sf read 0x1FFF000 16 + +5. sf erase 0x1FFF000 16 + +#### can 测试 + +1. 使用 scons menuconfig 选中 Enable Can + +2. 然后选中 Enable can0 ,Enable can0 work in loop back + +3. 烧录程序并且烧录 + +4. 打开 can 盒,将波特率设为 1000000 + +5. 然后通过 can 盒发送对应的数据(标准帧,扩展帧),就可以看见回复同样的内容 + +## 6. 参考资源 + +- ARM Architecture Reference Manual + +- FT-2000/4 软件编程手册-V1.4 + +## 7. 联系人信息 + +请联系飞腾嵌入式软件部 + +huanghe@phytium.com.cn + +zhugengyu@phytium.com.cn diff --git a/bsp/ft2004/SConscript b/bsp/ft2004/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..fe0ae941ae9a759ae478de901caec1c961e56af8 --- /dev/null +++ b/bsp/ft2004/SConscript @@ -0,0 +1,14 @@ +# for module compiling +import os +Import('RTT_ROOT') + +cwd = str(Dir('#')) +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/ft2004/SConstruct b/bsp/ft2004/SConstruct new file mode 100644 index 0000000000000000000000000000000000000000..4b65c0b4d5f1b18207e913c6e8464acd6e1b4abd --- /dev/null +++ b/bsp/ft2004/SConstruct @@ -0,0 +1,40 @@ +''' +Author: your name +Date: 2021-03-01 18:57:53 +LastEditTime: 2021-04-25 09:47:24 +LastEditors: Please set LastEditors +Description: In User Settings Edit +FilePath: \rtthread\bsp\ft2004\SConstruct +''' +import os +import sys +import rtconfig + +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') +else: + RTT_ROOT = os.path.join(os.getcwd(), '..', '..') + +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +from building import * + +TARGET = 'ft2004.' + rtconfig.TARGET_EXT + +DefaultEnvironment(tools=[]) +env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, + CXX= rtconfig.CXX, CXXFLAGS = rtconfig.CFLAGS, + AR = rtconfig.AR, ARFLAGS = '-rc', + LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) +env.PrependENVPath('PATH', rtconfig.EXEC_PATH) +env['ASCOM'] = env['ASPPCOM'] + +Export('RTT_ROOT') +Export('rtconfig') + +# prepare building environment +objs = PrepareBuilding(env, RTT_ROOT) + +# make a building +DoBuilding(TARGET, objs) diff --git a/bsp/ft2004/applications/SConscript b/bsp/ft2004/applications/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..01eb940dfb35f92c503a78b0b49a4354590f9f3a --- /dev/null +++ b/bsp/ft2004/applications/SConscript @@ -0,0 +1,11 @@ +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +cwd = os.path.join(str(Dir('#')), 'applications') +src = Glob('*.c') +CPPPATH = [cwd, str(Dir('#'))] + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/ft2004/applications/startup.c b/bsp/ft2004/applications/startup.c new file mode 100644 index 0000000000000000000000000000000000000000..5b40540234d23a08feb608d4b061227af4b82c60 --- /dev/null +++ b/bsp/ft2004/applications/startup.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2012-12-05 Bernard the first version + */ + +#include +#include +#include "ft_cpu.h" +#include "ft_generic_timer.h" + +#include + +#ifdef RT_USING_SMP + +struct rt_thread test_core[RT_CPUS_NR]; +static char *core_thread_name[RT_CPUS_NR] = { + "core0_test", + "core1_test", + "core2_test", + "core3_test"}; +static rt_uint8_t core_stack[RT_CPUS_NR][1024]; + +static void demo_core_thread(void *parameter) +{ + while (1) + { + /* code */ + FCpu_SpinLock(); + rt_kprintf("Hi, core%d \r\n", FCpu_IdGet()); + FCpu_SpinUnlock(); + rt_thread_mdelay(20000); + } +} + +void demo_core(void) +{ + rt_ubase_t i; + rt_uint8_t cpu_id = 0; + for (i = 0; i < RT_CPUS_NR; i++) + { + cpu_id = i; + rt_thread_init(&test_core[i], + core_thread_name[i], + demo_core_thread, + RT_NULL, + &core_stack[i], + 1024, + 20, + 32); + + rt_thread_control(&test_core[i], RT_THREAD_CTRL_BIND_CPU, (void *)cpu_id); + rt_thread_startup(&test_core[i]); + } +} +#endif + +extern long gic_dis_dump(void); + +int main(void) +{ + int count = 1; + +#ifdef RT_USING_SMP + demo_core(); +#endif + + while (count++) + { + rt_thread_mdelay(2000); + } + + return RT_EOK; +} diff --git a/bsp/ft2004/drivers/SConscript b/bsp/ft2004/drivers/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..17cbe606b73d933f5aa32c22a40116f1c08a7a0b --- /dev/null +++ b/bsp/ft2004/drivers/SConscript @@ -0,0 +1,12 @@ + +from building import * + +cwd = GetCurrentDir() +src = Glob('*.S') +src += Glob('*.c') + +CPPPATH = [cwd] + +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/ft2004/drivers/board.c b/bsp/ft2004/drivers/board.c new file mode 100644 index 0000000000000000000000000000000000000000..e9e284f90d0ba3c006cdd99039e8ea8c6c49de35 --- /dev/null +++ b/bsp/ft2004/drivers/board.c @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-03-04 Carl the first version + * + */ + +#include +#include "ft_printf.h" +#include "ft_assert.h" +#include "ft_cpu.h" +#include "ft_psci.h" +#include "ft_parameters.h" +#include "board.h" +#include "ft_generic_timer.h" +#include "ft_aarch32_asm.h" +#include + +#include "interrupt.h" +#include +#include "cp15.h" +#include "ft2004.h" + +#define DDR_MEM (SHARED | AP_RW | DOMAIN0 | MEMWT | DESC_SEC) + +struct mem_desc platform_mem_desc[] = { + {0x80000000, + 0x80000000 + 0x7f000000, + 0x80000000, + DDR_MEM}, + {0, //< QSPI + 0x1FFFFFFF, + 0, + DEVICE_MEM}, + {0x20000000, // + +extern void secondary_cpu_start(void); +extern void secondary2_cpu_start(void); +extern void secondary3_cpu_start(void); + +void rt_hw_secondary_cpu_up(void) +{ + + rt_uint32_t i; + rt_uint32_t cpu_mask = 0; + + rt_kprintf("rt_hw_secondary_cpu_up is processing \r\n"); + for (i = 1; i < RT_CPUS_NR; i++) + { + if (i == 1) + { + /* code */ + FPsci_CpuOn(1 << i, (rt_uint32_t)secondary_cpu_start); + cpu_mask = 2; + } + else if (i == 2) + { + FPsci_CpuOn(1 << i, (rt_uint32_t)secondary_cpu_start); + cpu_mask = 4; + } + else if (i == 3) + { + FPsci_CpuOn(1 << i, (rt_uint32_t)secondary_cpu_start); + cpu_mask = 8; + } + else + { + continue; + } + + __asm__ volatile("dsb" :: + : "memory"); + rt_hw_ipi_send(RT_SCHEDULE_IPI, cpu_mask); + Ft_GenericTimer_UsDelay(1000000); + } +} + +void secondary_cpu_c_start(void) +{ + rt_kprintf("cpu_id %x \r\n", FCpu_IdGet()); + rt_hw_vector_init(); + rt_hw_spin_lock(&_cpus_lock); + + arm_gic_cpu_init(0); + arm_gic_redist_init(0); + + rt_hw_timer_init(); + + rt_hw_interrupt_set_priority(RT_SCHEDULE_IPI, 16); + rt_hw_interrupt_umask(RT_SCHEDULE_IPI); + + Ft_printf("secondary_cpu_c_start is ok \r\n"); + + rt_system_scheduler_start(); +} + +void rt_hw_secondary_cpu_idle_exec(void) +{ + asm volatile("wfe" :: + : "memory", "cc"); +} + +#endif + +/*@}*/ diff --git a/bsp/ft2004/drivers/board.h b/bsp/ft2004/drivers/board.h new file mode 100644 index 0000000000000000000000000000000000000000..e21f8b53bf786676d1b8ba79e2220709e16dc932 --- /dev/null +++ b/bsp/ft2004/drivers/board.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2013-07-06 Bernard the first version + */ + +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#include "ft_parameters.h" +#include "ft2004.h" + +#if defined(__CC_ARM) +extern int Image$$RW_IRAM1$$ZI$$Limit; +#define HEAP_BEGIN ((void *)&Image$$RW_IRAM1$$ZI$$Limit) +#elif defined(__GNUC__) +extern int __bss_end; +#define HEAP_BEGIN ((void *)&__bss_end) +#endif + +#define HEAP_END (void *)(0x80000000 + 1024 * 1024 * 1024) + +void rt_hw_board_init(void); + +#endif diff --git a/bsp/ft2004/drivers/ft2004.c b/bsp/ft2004/drivers/ft2004.c new file mode 100644 index 0000000000000000000000000000000000000000..7ea513ce4113d459768d5656405c3beee0e86536 --- /dev/null +++ b/bsp/ft2004/drivers/ft2004.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-04-29 Carl the first version + * + */ + +#include +#include "ft2004.h" +#include "gicv3.h" + +// int rt_hw_cpu_id(void) +// { +// int cpu_id; +// __asm__ volatile( +// "mrc p15, 0, %0, c0, c0, 5" +// : "=r"(cpu_id)); +// switch ((cpu_id & 0xfff)) +// { +// case 1: +// return 1; +// case 0x100: +// return 2; +// case 0x101: +// return 3; +// default: +// return (cpu_id & 0xf); +// } +// } + +rt_uint64_t get_main_cpu_affval(void) +{ + return 0; +} + +rt_uint32_t arm_gic_cpumask_to_affval(rt_uint32_t *cpu_mask, rt_uint32_t *cluster_id, rt_uint32_t *target_list) +{ + + if (*cpu_mask == 0) + { + return 0; + } + + *target_list = 0; + *cluster_id = 0; + + if (*cpu_mask & 0x3) + { + if ((*cpu_mask & 0x3) == 0x3) + { + *target_list = 3; + } + else if ((*cpu_mask & 0x1)) + { + *target_list = 1; + } + else + { + *target_list = 2; + } + *cpu_mask &= ~0x3; + } + else if (*cpu_mask & 0xc) + { + *cluster_id = 0x100; + if ((*cpu_mask & 0xc) == 0xc) + { + *target_list = 3; + } + else if ((*cpu_mask & 0x4)) + { + *target_list = 1; + } + else + { + *target_list = 2; + } + *cpu_mask &= ~0xc; + } + else + { + *cpu_mask = 0; + return 0; + } + + return 1; +} + +#ifdef RT_USING_SMP + +void send_core_isg(void) +{ + for (size_t i = 0; i <= 0xf; i++) + { + /* code */ + rt_kprintf("i %x \r\n", i); + arm_gic_send_affinity_sgi(0, 0, i, 0); + rt_thread_mdelay(100); + } +} +MSH_CMD_EXPORT(send_core_isg, send_core_isg); + +#endif \ No newline at end of file diff --git a/bsp/ft2004/drivers/ft2004.h b/bsp/ft2004/drivers/ft2004.h new file mode 100644 index 0000000000000000000000000000000000000000..058c54fb8fb50f6d2572dad487f22a7e526a84ca --- /dev/null +++ b/bsp/ft2004/drivers/ft2004.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-04-29 Carl the first version + * + */ + +#ifndef __FT2004_H__ +#define __FT2004_H__ + +#include +#include + +#define ARM_GIC_NR_IRQS 160 +#define ARM_GIC_MAX_NR 1 +#define MAX_HANDLERS 160 +#define GIC_IRQ_START 0 + +rt_uint64_t get_main_cpu_affval(void); + +#endif // ! diff --git a/bsp/ft2004/drivers/ft2004_cpu.S b/bsp/ft2004/drivers/ft2004_cpu.S new file mode 100644 index 0000000000000000000000000000000000000000..1f9e62c2c316c76fe054c09e1fdb9ffa720d47e2 --- /dev/null +++ b/bsp/ft2004/drivers/ft2004_cpu.S @@ -0,0 +1,40 @@ + +#include "rtconfig.h" + +.globl rt_hw_cpu_id +rt_hw_cpu_id: + push {fp} + add fp, sp, #0 + sub sp, sp, #12 + mrc p15, 0, r3, c0, c0, 5 + str r3, [fp, #-8] + ldr r3, [fp, #-8] + ubfx r3, r3, #0, #12 + movw r2, #257 + cmp r3, r2 + beq core3 + movw r2, #257 + cmp r3, r2 + bgt default + cmp r3, #1 + beq core1 + cmp r3, #256 + beq core2 + b default +core1: + mov r3, #1 + b return +core2: + mov r3, #2 + b return +core3: + mov r3, #3 + b return +default: + ldr r3, [fp, #-8] + and r3, r3, #15 +return: + mov r0, r3 + add sp, fp, #0 + pop {fp} + bx lr diff --git a/bsp/ft2004/drivers/secondary_cpu.cold b/bsp/ft2004/drivers/secondary_cpu.cold new file mode 100644 index 0000000000000000000000000000000000000000..a644b617e6681e85490e6fe13b20d1fb11b64ba9 --- /dev/null +++ b/bsp/ft2004/drivers/secondary_cpu.cold @@ -0,0 +1,43 @@ +/* + * @[H]: Copyright (C) 2014-2021 Phytium Technology.  All rights reserved. + * + *  Permission is hereby granted, free of charge, to any person obtaining a copy + *  of this software and associated documentation files (the "Software"), to deal + *  in the Software without restriction, including without limitation the rights + *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + *  copies of the Software, and to permit persons to whom the Software is + *  furnished to do so, subject to the following conditions: + * + *  The above copyright notice and this permission notice shall be included in + *  all copies or substantial portions of the Software. + * + *  Use of the Software is limited solely to applications: + *  (a) running on a Phytium device, or + *  (b) that interact with a Phytium device through a bus or interconnect. + * + *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + *  PHYTIUM  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + *  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + *  SOFTWARE. + * + *  Except as contained in this notice, the name of the Phytium shall not be used + *  in advertising or otherwise to promote the sale, use or other dealings in + *  this Software without prior written authorization from Phytium.  + * + * @Date: 2021-04-19 08:52:58 + * @LastEditTime: 2021-04-19 08:52:58 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + */ + +#include +#include +#include + +#include "board.h" +#include "gic.h" diff --git a/bsp/ft2004/drivers/serial.h b/bsp/ft2004/drivers/serial.h new file mode 100644 index 0000000000000000000000000000000000000000..6abc1394fccb6ccf8419bfe4698d657cf967893a --- /dev/null +++ b/bsp/ft2004/drivers/serial.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-04-29 Carl the first version + * + */ + +#ifndef __UART_H__ +#define __UART_H__ + +#include + +int rt_hw_uart_init(void); + +#endif + diff --git a/bsp/ft2004/figures/onchipPeripheral.png b/bsp/ft2004/figures/onchipPeripheral.png new file mode 100644 index 0000000000000000000000000000000000000000..3b5833bccae8cbdbf191f50921bac2c94d15823b Binary files /dev/null and b/bsp/ft2004/figures/onchipPeripheral.png differ diff --git "a/bsp/ft2004/figures/rttPing\351\200\232\350\277\207\347\225\214\351\235\242.png" "b/bsp/ft2004/figures/rttPing\351\200\232\350\277\207\347\225\214\351\235\242.png" new file mode 100644 index 0000000000000000000000000000000000000000..0c287ea571a93f64720178b4fbae140181acf130 Binary files /dev/null and "b/bsp/ft2004/figures/rttPing\351\200\232\350\277\207\347\225\214\351\235\242.png" differ diff --git "a/bsp/ft2004/figures/rttsd\350\260\203\350\257\225.png" "b/bsp/ft2004/figures/rttsd\350\260\203\350\257\225.png" new file mode 100644 index 0000000000000000000000000000000000000000..98d1b5fa2b1b8f6137584dad78699f48ae8e272a Binary files /dev/null and "b/bsp/ft2004/figures/rttsd\350\260\203\350\257\225.png" differ diff --git "a/bsp/ft2004/figures/\345\220\257\345\212\250\346\274\224\347\244\272\345\233\276.png" "b/bsp/ft2004/figures/\345\220\257\345\212\250\346\274\224\347\244\272\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..46a117c96f43cc19da42c3b4e0ba72325eb3e204 Binary files /dev/null and "b/bsp/ft2004/figures/\345\220\257\345\212\250\346\274\224\347\244\272\345\233\276.png" differ diff --git a/bsp/ft2004/ft_aarch32.lds b/bsp/ft2004/ft_aarch32.lds new file mode 100644 index 0000000000000000000000000000000000000000..d37332d97fa0570b816781c07261caf7ed8bf7dc --- /dev/null +++ b/bsp/ft2004/ft_aarch32.lds @@ -0,0 +1,110 @@ +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) + +SECTIONS +{ + . = 0x80100000; + + __text_start = .; + .text : + { + *(.vectors) + *(.text) + *(.text.*) + + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(4); + + /* section information for modules */ + . = ALIGN(4); + __rtmsymtab_start = .; + KEEP(*(RTMSymTab)) + __rtmsymtab_end = .; + + /* section information for initialization */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + } =0 + __text_end = .; + + __rodata_start = .; + .rodata : { *(.rodata) *(.rodata.*) } + __rodata_end = .; + + . = ALIGN(4); + .ctors : + { + PROVIDE(__ctors_start__ = .); + KEEP(*(SORT(.ctors.*))) + KEEP(*(.ctors)) + PROVIDE(__ctors_end__ = .); + } + + .dtors : + { + PROVIDE(__dtors_start__ = .); + KEEP(*(SORT(.dtors.*))) + KEEP(*(.dtors)) + PROVIDE(__dtors_end__ = .); + } + + . = ALIGN(16 * 1024); + .l1_page_table : + { + __l1_page_table_start = .; + . += 16K; + } + + . = ALIGN(8); + __data_start = .; + .data : + { + *(.data) + *(.data.*) + } + __data_end = .; + + . = ALIGN(8); + __bss_start = .; + .bss : + { + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(4); + } + . = ALIGN(4); + __bss_end = .; + + .heap : + { + . = ALIGN(8); + __end__ = .; + PROVIDE(end = .); + __HeapBase = .; + . += 0x400; + __HeapLimit = .; + __heap_limit = .; /* Add for _sbrk */ + } + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + + _end = .; +} diff --git a/bsp/ft2004/libraries/.gitignore b/bsp/ft2004/libraries/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..fcfda9fc84532a03a0cb77e666215b9f689507d3 --- /dev/null +++ b/bsp/ft2004/libraries/.gitignore @@ -0,0 +1,4 @@ +*.o +*.elf +*.bin +*.map diff --git a/bsp/ft2004/libraries/Kconfig b/bsp/ft2004/libraries/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..c5443955960139a6b42b7ba6b3a7059e53461161 --- /dev/null +++ b/bsp/ft2004/libraries/Kconfig @@ -0,0 +1,146 @@ +menu "Hardware Drivers Config" + +menu "On-chip Peripheral Drivers" + menuconfig BSP_USING_UART + bool "Enable UART" + default y + select RT_USING_SERIAL + if BSP_USING_UART + config RT_USING_UART1 + bool "Enable UART1" + default y + + config RT_USING_UART0 + bool "Enable UART0" + default n + + endif + + menuconfig BSP_USING_SDC + bool "Enable sd controller" + select RT_USING_SDIO + select RT_USING_DFS + select RT_USING_DFS_ELMFAT + default n + + if BSP_USING_SDC + + config BSP_SDC_DEBUG_PRINT + bool "Enable sd controller debug print" + default n + + + config BSP_SDC_USE_IRQ + bool "Use interrupt to handle when cmd complete, dma complete" + default n + + if BSP_SDC_USE_IRQ + config BSP_SDC_IRQ_CARD_REMOVE + bool "Use interrupt to determine if the card is pulled out" + default n + + endif + + endif + + menuconfig BSP_USING_GMAC + bool "Enable gmac" + default n + select RT_USING_NETDEV + + + if BSP_USING_GMAC + config BSP_USING_GMAC0 + bool "Enable GMAC0" + default y + + config BSP_USING_GMAC1 + bool "Enable GMAC1" + default n + + config RT_LWIP_ETH_PAD_SIZE + int "set lwip ETH_PAD_SIZE" + range 2 256 + default 2 + + config RAW_DATA_PRINT + bool "Enable mac raw data print" + default n + + if RAW_DATA_PRINT + config ETH_RX_DUMP + bool "Enable gmac receive raw data print " + default n + + config ETH_TX_DUMP + bool "Enable gmac send raw data print " + default n + endif + + endif + + + # menuconfig BSP_USE_QSPI + # bool "Enable Qspi" + # select RT_USING_SFUD + # select RT_SFUD_USING_QSPI + # default n + + # if BSP_USE_QSPI + # config BSP_QSPI_DEBUG + # bool "Enable qspi debug print" + # default n + # endif + + menuconfig BSP_USE_SPI + bool "Enable Spi" + select RT_USING_SFUD + select RT_SFUD_USING_SPI + select RT_SFUD_USING_SFDP + select RT_SFUD_USING_FLASH_INFO_TABLE + select BSP_USE_GPIO + default n + if BSP_USE_SPI + config BSP_SPI_DEBUG + bool "Enable spi debug print" + default n + endif + + menuconfig BSP_USE_GPIO + bool "Enable Gpio" + default n + if BSP_USE_GPIO + config BSP_GPIO_DEBUG + bool "Enable gpio debug print" + default n + endif + + menuconfig BSP_USE_CAN + bool "Enable Can" + select RT_USING_CAN + default n + + if BSP_USE_CAN + config BSP_USING_CAN0 + bool "Enable can0" + default n + config BSP_USING_CAN1 + bool "Enable can1" + default n + + if BSP_USING_CAN0 + config BSP_USING_CAN0_DEBUG + bool "Enable can0 work in loop back" + default n + endif + + endif + + +endmenu + +menu "Board extended module Drivers" + +endmenu + +endmenu diff --git a/bsp/ft2004/libraries/LICENSE b/bsp/ft2004/libraries/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..7a4a3ea2424c09fbe48d455aed1eaa94d9124835 --- /dev/null +++ b/bsp/ft2004/libraries/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/bsp/ft2004/libraries/SConscript b/bsp/ft2004/libraries/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..49476ebd87e69b2697e34e44869427d764d22e48 --- /dev/null +++ b/bsp/ft2004/libraries/SConscript @@ -0,0 +1,145 @@ +''' + : Copyright (c) 2020 Phytium Information Technology, Inc. +The right to copy, distribute, modify, or otherwise make use +of this software may be licensed only pursuant to the terms +of an applicable Phytium license agreement. +Date: 2021-04-25 09:19:07 +LastEditTime: 2021-04-30 15:36:54 +Description:  This files is for + +Modify History: + Ver   Who        Date         Changes +----- ------     --------    -------------------------------------- +''' +from building import * +import rtconfig +Import('RTT_ROOT') + +# get current directory +cwd = GetCurrentDir() + +# The set of source files associated with this SConscript file. +src = Split(""" +bsp/ft_gicv3/ft_gicv3_g.c +bsp/ft_gicv3/ft_gicv3_hw.c +bsp/ft_gicv3/ft_gicv3_sinit.c +bsp/ft_gicv3/ft_gicv3.c +bsp/standlone/ft_assert.c +bsp/standlone/ft_generic_timer.c +bsp/standlone/ft_printf.c +bsp/standlone/ft_trace.c +bsp/standlone/ft_mux.c +bsp/standlone/inbyte.c +bsp/standlone/outbyte.c +bsp/standlone/ft_cache.c +bsp/standlone/ft_cpu.c +bsp/standlone/ft_smc.S +bsp/standlone/ft_psci.c +bsp/standlone/ft_debug.c +/usr/lib/arm-none-eabi/lib/libnosys.a + +""") +# + +if GetDepend(['RT_USING_SERIAL']): + src += ['bsp/ft_uart/ft_uart_g.c'] + src += ['bsp/ft_uart/ft_uart_hw.c'] + src += ['bsp/ft_uart/ft_uart_intr.c'] + src += ['bsp/ft_uart/ft_uart_options.c'] + src += ['bsp/ft_uart/ft_uart_selftest.c'] + src += ['bsp/ft_uart/ft_uart_sinit.c'] + src += ['bsp/ft_uart/ft_uart.c'] + src += ['drivers/rtthread/drv_usart.c'] + +if GetDepend(['RT_USING_I2C']): + None + +if GetDepend(['RT_USING_USB_HOST']) or GetDepend(['RT_USING_USB_DEVICE']): + None + +if GetDepend(['BSP_USE_CAN']): + src += ['bsp/ft_can/ft_can_g.c'] + src += ['bsp/ft_can/ft_can_hw.c'] + src += ['bsp/ft_can/ft_can_intr.c'] + src += ['bsp/ft_can/ft_can_sinit.c'] + src += ['bsp/ft_can/ft_can.c'] + src += ['bsp/ft_can/ft_can_calc.c'] + src += ['drivers/rtthread/drv_can.c'] + None + + +if GetDepend(['RT_USING_HWTIMER']) or GetDepend(['RT_USING_PWM']): + None + +if GetDepend(['RT_USING_ADC']): + None + +if GetDepend(['RT_USING_RTC']): + None + +if GetDepend(['RT_USING_WDT']): + None + +if GetDepend(['RT_USING_AUDIO']): + None + +if GetDepend(['BSP_USING_ON_CHIP_FLASH']): + None + +if GetDepend(['BSP_USING_GMAC']): + src += ['bsp/ft_gmac/ft_gmac_desc.c'] + src += ['bsp/ft_gmac/ft_gmac_g.c'] + src += ['bsp/ft_gmac/ft_gmac_hw.c'] + src += ['bsp/ft_gmac/ft_gmac_intr.c'] + src += ['bsp/ft_gmac/ft_gmac_sinit.c'] + src += ['bsp/ft_gmac/ft_gmac.c'] + src += ['drivers/rtthread/drv_eth.c'] + +if GetDepend(['BSP_USING_SDC']): + src += ['bsp/ft_sd/ft_sdctrl_option.c'] + src += ['bsp/ft_sd/ft_sdctrl_sinit.c'] + src += ['bsp/ft_sd/ft_sdctrl_intr.c'] + src += ['bsp/ft_sd/ft_sdctrl_g.c'] + src += ['bsp/ft_sd/ft_sdctrl_hw.c'] + src += ['bsp/ft_sd/ft_sdctrl.c'] + src += ['drivers/rtthread/drv_sdctrl.c'] + src += ['drivers/rtthread/drv_sdcard.c'] + +if GetDepend(['BSP_USE_QSPI']): + src += ['bsp/ft_qspi/qspi_g.c'] + src += ['bsp/ft_qspi/qspi_hw.c'] + src += ['bsp/ft_qspi/ft_qspi.c'] + src += ['bsp/ft_qspi/qspi_sinit.c'] + src += ['drivers/rtthread/drv_qspi.c'] + src += ['drivers/rtthread/ports/drv_qspi_flash.c'] + +if GetDepend(['BSP_USE_SPI']): + src += ['bsp/ft_spi/ft_spi.c'] + src += ['bsp/ft_spi/ft_spi_irq.c'] + src += ['drivers/rtthread/drv_spi.c'] + src += ['drivers/rtthread/ports/drv_spi_flash.c'] + +if GetDepend(['BSP_USE_GPIO']): + src += ['bsp/ft_gpio/ft_gpio.c'] + +path = [cwd + '/drivers/', + cwd + '/bsp/standlone/', + cwd + '/bsp/ft_gicv3', + cwd + '/bsp/ft_gmac', + cwd + '/bsp/ft_uart', + cwd + '/bsp/ft_sd', + cwd + '/bsp/ft_qspi', + cwd + '/bsp/ft_can', + cwd + '/bsp/ft_spi', + cwd + '/bsp/ft_gpio', + cwd + '/bsp/include', + cwd + '/include', + cwd + '/drivers/rtthread', + cwd + '/cpu', ] + + +CPPDEFINES = ['USE_FT_DRIVER'] +group = DefineGroup('FT_DRIVER', src, depend=[ + ''], CPPPATH=path, CPPDEFINES=CPPDEFINES) + +Return('group') diff --git a/bsp/ft2004/libraries/bsp/bsp.mk b/bsp/ft2004/libraries/bsp/bsp.mk new file mode 100644 index 0000000000000000000000000000000000000000..f7910e96f8afeac6ed15f91b7250953ae67bfd82 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/bsp.mk @@ -0,0 +1,21 @@ + + +INCDIRS += $(DEVICE_PATH)/bsp/standlone \ + $(DEVICE_PATH)/bsp/include \ + $(DEVICE_PATH)/bsp/ft_uart \ + $(DEVICE_PATH)/bsp/ft_gicv3 \ + $(DEVICE_PATH)/bsp/ft_gmac \ + $(DEVICE_PATH)/bsp/ft_i2c \ + $(DEVICE_PATH)/bsp/ft_sd + + + + +SRCDIRS += $(DEVICE_PATH)/bsp/standlone \ + $(DEVICE_PATH)/bsp/ft_uart \ + $(DEVICE_PATH)/bsp/ft_gicv3 \ + $(DEVICE_PATH)/bsp/ft_gmac \ + $(DEVICE_PATH)/bsp/ft_i2c \ + $(DEVICE_PATH)/bsp/ft_sd + + \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/ft_can/ft_can.c b/bsp/ft2004/libraries/bsp/ft_can/ft_can.c new file mode 100644 index 0000000000000000000000000000000000000000..9aafafb6a8c3f36385d1a929e81b651abf423777 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_can/ft_can.c @@ -0,0 +1,336 @@ +/* + * @[H]: Copyright (C) 2014-2021 Phytium Technology.  All rights reserved. + * + *  Permission is hereby granted, free of charge, to any person obtaining a copy + *  of this software and associated documentation files (the "Software"), to deal + *  in the Software without restriction, including without limitation the rights + *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + *  copies of the Software, and to permit persons to whom the Software is + *  furnished to do so, subject to the following conditions: + * + *  The above copyright notice and this permission notice shall be included in + *  all copies or substantial portions of the Software. + * + *  Use of the Software is limited solely to applications: + *  (a) running on a Phytium device, or + *  (b) that interact with a Phytium device through a bus or interconnect. + * + *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + *  PHYTIUM  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + *  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + *  SOFTWARE. + * + *  Except as contained in this notice, the name of the Phytium shall not be used + *  in advertising or otherwise to promote the sale, use or other dealings in + *  this Software without prior written authorization from Phytium.  + * + * @Date: 2021-04-29 10:21:53 + * @LastEditTime: 2021-04-29 10:21:53 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + */ + +#include "ft_can.h" +#include "ft_can_hw.h" +#include "ft_assert.h" +#include "ft_debug.h" +#include "string.h" + +#define FT_CAN_DEBUG_TAG "FT_CAN" + +#define FT_CAN_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__) +#define FT_CAN_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__) +#define FT_CAN_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__) + +ft_error_t +FCan_CfgInitialize(FCan_t *Can_p, FCan_Config_t *Config_p) +{ + Ft_assertNonvoid(Can_p != NULL); + Ft_assertNonvoid(Config_p != NULL); + Can_p->Config = *Config_p; + Can_p->IsReady = FT_COMPONENT_IS_READLY; + FCan_Reset(Can_p); + return FCAN_SUCCESS; +} + +void FCan_GetErrorCnt(FCan_t *Can_p, u32 *TxErr, u32 *RxErr) +{ + FCan_Config_t *Config_p; + Ft_assertVoid(Can_p != NULL); + Ft_assertVoid(Can_p->IsReady == FT_COMPONENT_IS_READLY); + Config_p = &Can_p->Config; + + *RxErr = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_ERR_CNT_OFFSET) & FCAN_ERR_CNT_RFN_MASK; + *TxErr = (FCan_ReadReg(Config_p->CanBaseAddress, FCAN_ERR_CNT_OFFSET) & FCAN_ERR_CNT_TFN_MASK) >> FCAN_ERR_CNT_TFN_SHIFT; +} + +u32 FCan_RecvByIrq(FCan_t *Can_p, struct FCan_Frame *Frame_p, u32 FrameNumber) +{ + u32 FifoCnt = 0; + FCan_Config_t *Config_p; + u32 CanId; + u32 Dlc; + u32 CanFrameIndex = 0; + u32 RxValue; + Ft_assertZeroNum(Can_p != NULL); + Ft_assertZeroNum(Can_p->IsReady == FT_COMPONENT_IS_READLY); + Config_p = &Can_p->Config; + + FifoCnt = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_FIFO_CNT_OFFSET) & 0x3f; + + if (0 == FifoCnt) + { + return 0; + } + + FrameNumber = (FrameNumber > FifoCnt) ? FifoCnt : FrameNumber; + + while (FrameNumber) + { + /* Read a frame from Phytium CAN */ + CanId = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_RX_FIFO_OFFSET); + /* if CanId is big-endian ,use swap change to little-endian */ + CanId = FT_SWAP32(CanId); + /* Identifier extension */ + if (CanId & FCAN_IDR_IDE_MASK) + { + Dlc = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_RX_FIFO_OFFSET); + Dlc = FT_SWAP32(Dlc); + Dlc = ((Dlc & FCAN_IDR_EDLC_MASK) >> FCAN_IDR_EDLC_SHIFT); + + Frame_p[CanFrameIndex].CanId = (CanId & FCAN_IDR_ID1_MASK) >> 3; + Frame_p[CanFrameIndex].CanId |= (CanId & FCAN_IDR_ID2_MASK) >> FCAN_IDR_ID2_SHIFT; + Frame_p[CanFrameIndex].CanId |= CAN_EFF_FLAG; + + if (CanId & FCAN_IDR_RTR_MASK) + { + Frame_p[CanFrameIndex].CanId |= CAN_RTR_FLAG; + } + } + else + { + Dlc = ((CanId & FCAN_IDR_DLC_MASK) >> FCAN_IDR_SDLC_SHIFT); + + /* The received frame is a standard format frame */ + Frame_p[CanFrameIndex].CanId = (CanId & FCAN_IDR_ID1_MASK) >> FCAN_IDR_ID1_SHIFT; + if (CanId & FCAN_IDR_SRR_MASK) + { + Frame_p[CanFrameIndex].CanId |= CAN_RTR_FLAG; + } + } + + Frame_p[CanFrameIndex].CanDlc = (Dlc > sizeof(Frame_p[CanFrameIndex].data)) ? sizeof(Frame_p[CanFrameIndex].data) : Dlc; + + if (!(Frame_p[CanFrameIndex].CanId & CAN_RTR_FLAG)) + { + if (Frame_p[CanFrameIndex].CanDlc > 0) + { + RxValue = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_RX_FIFO_OFFSET); + memcpy(Frame_p[CanFrameIndex].data, &RxValue, sizeof(RxValue)); + } + + if (Frame_p[CanFrameIndex].CanDlc > 4) + { + RxValue = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_RX_FIFO_OFFSET); + memcpy(&Frame_p[CanFrameIndex].data[4], &RxValue, sizeof(RxValue)); + } + } + FrameNumber--; + CanFrameIndex++; + } + + return (CanFrameIndex + 1); +} + +static void FCan_SendFifo(FCan_t *Can_p, struct FCan_Frame *Frame_p) +{ + u32 Id, Dlc; + FCan_Config_t *Config_p; + u32 SendBuffer = 0; + Ft_assertVoid(Can_p != NULL); + Ft_assertVoid(Can_p->IsReady == FT_COMPONENT_IS_READLY); + Config_p = &Can_p->Config; + if (Frame_p->CanId & CAN_EFF_FLAG) + { + /* Extended CAN ID format */ + Id = ((Frame_p->CanId & CAN_EFF_MASK) << FCAN_IDR_ID2_SHIFT) & + FCAN_IDR_ID2_MASK; + Id |= (((Frame_p->CanId & CAN_EFF_MASK) >> + (CAN_EFF_ID_BITS - CAN_SFF_ID_BITS)) + << FCAN_IDR_ID1_SHIFT) & + FCAN_IDR_ID1_MASK; + + Id |= FCAN_IDR_IDE_MASK | FCAN_IDR_SRR_MASK; + if (Frame_p->CanId & CAN_RTR_FLAG) + { + Id |= FCAN_IDR_RTR_MASK; + } + + Dlc = Frame_p->CanDlc << FCAN_IDR_EDLC_SHIFT; + + FCan_WriteReg(Config_p->CanBaseAddress, FCAN_TX_FIFO_OFFSET, FT_SWAP32(Id)); + FCan_WriteReg(Config_p->CanBaseAddress, FCAN_TX_FIFO_OFFSET, FT_SWAP32(Dlc)); + } + else + { + /* Standard CAN ID format */ + Id = ((Frame_p->CanId & CAN_SFF_MASK) << FCAN_IDR_ID1_SHIFT) & + FCAN_IDR_ID1_MASK; + if (Frame_p->CanId & CAN_RTR_FLAG) + Id |= FCAN_IDR_SRR_MASK; + + Dlc = ((Frame_p->CanDlc << FCAN_IDR_SDLC_SHIFT) | FCAN_IDR_PAD_MASK); + Id |= Dlc; + FCan_WriteReg(Config_p->CanBaseAddress, FCAN_TX_FIFO_OFFSET, FT_SWAP32(Id)); + } + + if (!(Frame_p->CanId & CAN_RTR_FLAG)) + { + if (Frame_p->CanDlc > 0) + { + memcpy(&SendBuffer, Frame_p->data, 4); + FCan_WriteReg(Config_p->CanBaseAddress, FCAN_TX_FIFO_OFFSET, SendBuffer); + } + + if (Frame_p->CanDlc > 4) + { + memcpy(&SendBuffer, &Frame_p->data[4], 4); + FCan_WriteReg(Config_p->CanBaseAddress, FCAN_TX_FIFO_OFFSET, SendBuffer); + } + } +} + +u32 FCan_SendByIrq(FCan_t *Can_p, + struct FCan_Frame *Frame_p, + u32 FrameNumber, void (*UserIrqWait)(void)) +{ + FCan_Config_t *Config_p; + u32 FrameIndex = 0; + u32 NeedSendOnce; + u32 cnt = 0; + Ft_assertZeroNum(Can_p != NULL); + Ft_assertZeroNum(Can_p->IsReady == FT_COMPONENT_IS_READLY); + Config_p = &Can_p->Config; + + if (NULL == Frame_p) + { + FT_CAN_DEBUG_E("Frame_p is NULL , %s: %d", __FILE__, __LINE__); + return 0; + } + + if (0 == FrameNumber) + { + FT_CAN_DEBUG_E("FrameNumber is 0 , %s: %d", __FILE__, __LINE__); + return 0; + } + + for (; 0 < FrameNumber;) + { + if (FrameNumber > Config_p->TxFifoDeepth) + { + NeedSendOnce = Config_p->TxFifoDeepth; + FrameNumber -= Config_p->TxFifoDeepth; + } + else + { + NeedSendOnce = FrameNumber; + FrameNumber = 0; + } + Ft_printf("shut down tranmission \r\n"); + /*shut down tranmission*/ + FCan_ClearBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK); + FCan_ClearBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_TXREQ_MASK); + FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK); + Ft_printf("NeedSendOnce %d \r\n", NeedSendOnce); + for (cnt = 0; cnt < NeedSendOnce; cnt++) + { + FCan_SendFifo(Can_p, &Frame_p[FrameIndex]); + FrameIndex++; + } + Can_p->TxFifoCnt = NeedSendOnce; + + /* triggers tranmission */ + FCan_ClearBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK); + FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_TXREQ_MASK); + FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_TXREQ_MASK | FCAN_CTRL_XFER_MASK); + + if (UserIrqWait) + { + UserIrqWait(); + } + else + { + while (0 != Can_p->TxFifoCnt) + { + }; + } + } + + return FrameIndex + 1; +} + +ft_error_t FCan_SetTiming(FCan_t *Can_p, + struct FCan_Bittiming *Bittiming_p) +{ + u32 Btr = 0; + FCan_Config_t *Config_p; + u32 IsConfigMode; + Ft_assertNonvoid(Can_p != NULL); + Ft_assertNonvoid(Can_p->IsReady == FT_COMPONENT_IS_READLY); + Config_p = &Can_p->Config; + + Ft_assertNonvoid(Bittiming_p->brp != 0); + Ft_assertNonvoid(Bittiming_p->prop_seg != 0); + Ft_assertNonvoid(Bittiming_p->phase_seg1 != 0); + Ft_assertNonvoid(Bittiming_p->phase_seg2 != 0); + + /* Setting Baud Rate prescalar value in BRPR Register */ + Btr = (Bittiming_p->brp - 1) << 16; + Btr |= (Bittiming_p->prop_seg - 1) << 2; + Btr |= (Bittiming_p->phase_seg1 - 1) << 5; + Btr |= (Bittiming_p->phase_seg2 - 1) << 8; + Btr |= (Bittiming_p->sjw - 1); + + IsConfigMode = (FCan_ReadReg(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET) & FCAN_CTRL_XFER_MASK); + + if (IsConfigMode) + { + FCan_WriteReg(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK); + } + + FCan_WriteReg(Config_p->CanBaseAddress, FCAN_DAT_RATE_CTRL_OFFSET, Btr); + FCan_WriteReg(Config_p->CanBaseAddress, FCAN_ARB_RATE_CTRL_OFFSET, Btr); + + /*Enable Transfer*/ + FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK); + + return FCAN_SUCCESS; +} + +void FCan_Enable(FCan_t *Can_p) +{ + FCan_Config_t *Config_p; + Ft_assertVoid(Can_p != NULL); + Ft_assertVoid(Can_p->IsReady == FT_COMPONENT_IS_READLY); + Config_p = &Can_p->Config; + + FCan_WriteReg(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK); +} + +// ft_error_t FCan_SetIdFilter(FCan_t *Can_p, u32) +// { +// FCan_Config_t *Config_p; +// Ft_assertVoid(Can_p != NULL); +// Ft_assertVoid(Can_p->IsReady == FT_COMPONENT_IS_READLY); +// Config_p = &Can_p->Config; + +// u32 IdRegOffset[4] = {FCAN_ACC_ID0_OFFSET, FCAN_ACC_ID1_OFFSET, FCAN_ACC_ID2_OFFSET, FCAN_ACC_ID3_OFFSET}; +// u32 MaskRegOffset[4] = {FCAN_ACC_ID0_MASK_OFFSET, FCAN_ACC_ID1_MASK_OFFSET, FCAN_ACC_ID2_MASK_OFFSET, FCAN_ACC_ID3_MASK_OFFSET}; + +// return FCAN_SUCCESS; +// } diff --git a/bsp/ft2004/libraries/bsp/ft_can/ft_can.h b/bsp/ft2004/libraries/bsp/ft_can/ft_can.h new file mode 100644 index 0000000000000000000000000000000000000000..acb8fc8b4c096b7af3a7abcf172510f9a08c9410 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_can/ft_can.h @@ -0,0 +1,166 @@ +/* + * @[H]: Copyright (C) 2014-2021 Phytium Technology.  All rights reserved. + * + *  Permission is hereby granted, free of charge, to any person obtaining a copy + *  of this software and associated documentation files (the "Software"), to deal + *  in the Software without restriction, including without limitation the rights + *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + *  copies of the Software, and to permit persons to whom the Software is + *  furnished to do so, subject to the following conditions: + * + *  The above copyright notice and this permission notice shall be included in + *  all copies or substantial portions of the Software. + * + *  Use of the Software is limited solely to applications: + *  (a) running on a Phytium device, or + *  (b) that interact with a Phytium device through a bus or interconnect. + * + *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + *  PHYTIUM  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + *  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + *  SOFTWARE. + * + *  Except as contained in this notice, the name of the Phytium shall not be used + *  in advertising or otherwise to promote the sale, use or other dealings in + *  this Software without prior written authorization from Phytium.  + * + * @Date: 2021-04-27 15:08:44 + * @LastEditTime: 2021-04-27 15:08:44 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + */ + +#ifndef FT_CAN_H +#define FT_CAN_H + +#include "ft_types.h" +#include "ft_error_code.h" + +#define FCAN_SUCCESS FST_SUCCESS /* SUCCESS */ +#define FCAN_FAILURE FT_MAKE_ERRCODE(errCan, errBspGeneral, FST_FAILURE) /* Normal */ +#define FCAN_TIMEOUT FT_MAKE_ERRCODE(errCan, errBspGeneral, FST_TIMEOUT) /* Timeout */ +#define FCAN_EILSEQ FT_MAKE_ERRCODE(errCan, errBspGeneral, FST_EILSEQ) /* Illegal byte sequence. */ +#define FCAN_INVALID_PARAM FT_MAKE_ERRCODE(errCan, errBspGeneral, FST_INVALID_PARAM) /* Invalid param. */ + +#define FCAN_HANDLER_SEND 1U /**< Handler type for frame sending interrupt */ +#define FCAN_HANDLER_RECV 2U /**< Handler type for frame reception interrupt*/ +#define FCAN_HANDLER_ERROR 3U /**< Handler type for error interrupt */ +#define FCAN_DATA_LENGTH 8U + +/* CAN payload length and DLC definitions according to ISO 11898-1 */ +#define CAN_MAX_DLC 8 +#define CAN_MAX_DLEN 8 +#define CAN_MAX_CTL 3 +#define CAN_SFF_ID_BITS 11 +#define CAN_EFF_ID_BITS 29 + +/* special address description flags for the CAN_ID */ +#define CAN_EFF_FLAG 0x80000000U /* EFF/SFF is set in the MSB */ +#define CAN_RTR_FLAG 0x40000000U /* remote transmission request */ +#define CAN_ERR_FLAG 0x20000000U /* error message frame */ + +/* valid bits in CAN ID for frame formats */ +#define CAN_SFF_MASK 0x000007FFU /* standard frame format (SFF) */ +#define CAN_EFF_MASK 0x1FFFFFFFU /* extended frame format (EFF) */ +#define CAN_ERR_MASK 0x1FFFFFFFU /* omit EFF, RTR, ERR flags */ + +/* Frame type */ +#define STANDARD_FRAME 0 /* standard frame */ +#define EXTEND_FRAME 1 /* extended frame */ + +typedef void (*FCan_irqHandler_t)(void *Args); + +struct FCan_Frame +{ + u32 CanId; + u8 CanDlc; + u8 data[FCAN_DATA_LENGTH]; +}; + +struct FCan_Bittiming +{ + u32 bitrate; /* Bit-rate in bits/second */ + u32 sample_point; /* Sample point in one-tenth of a percent */ + u32 tq; /* Time quanta (TQ) in nanoseconds */ + u32 prop_seg; /* Propagation segment in TQs */ + u32 phase_seg1; /* Phase buffer segment 1 in TQs */ + u32 phase_seg2; /* Phase buffer segment 2 in TQs */ + u32 sjw; /* Synchronisation jump width in TQs */ + u32 brp; /* Bit-rate prescaler */ +}; + +typedef struct +{ + u32 InstanceId; /* Id of device */ + u32 CanBaseAddress; /* Can base Address */ + u32 IrqNum; + u32 BaudRate; + u32 TxFifoDeepth; /* The depth of the full frame , */ +} FCan_Config_t; + +typedef struct +{ + FCan_Config_t Config; + u32 IsReady; /* Device is initialized and ready */ + + volatile u32 TxFifoCnt; + + FCan_irqHandler_t SendHandler; + void *SendRef; + + FCan_irqHandler_t RecvHandler; + void *RecvRef; + + FCan_irqHandler_t ErrorHandler; + void *ErrorRef; + +} FCan_t; + +FCan_Config_t *FCan_LookupConfig(u32 InstanceId); + +/** + * @name: FCan_CfgInitialize + * @msg: This function initializes a Can instance/driver. + * @in param Can_p: Can_p is a pointer to the FCan_t instance. + * @in param Config_p: Config_p points to the FCan_t device configuration structure. + * @return {*} + */ +ft_error_t FCan_CfgInitialize(FCan_t *Can_p, FCan_Config_t *Config_p); + +/** + * @name: FCan_SetHandler + * @msg: This routine installs an asynchronous callback function for the given + * @inout param Can_p: Can_p is a pointer to the FCan_t instance. + * @in param HandlerType: specifies which handler is to be attached. + * @in param IrqCallBackFunc: IrqCallBackFunc is the address of the callback function. + * @in param IrqCallBackRef: IrqCallBackRef is a user data item that will be passed to the + * callback function when it is invoked. + * @return {*} + * @param {FCan_t} *Can_p + * @param {u32} HandlerType + * @param {FCan_irqHandler_t} *IrqCallBackFunc + * @param {void} *IrqCallBackRef + */ +ft_error_t FCan_SetHandler(FCan_t *Can_p, u32 HandlerType, FCan_irqHandler_t IrqCallBackFunc, void *IrqCallBackRef); + +ft_error_t FCan_SetTiming(FCan_t *Can_p, + struct FCan_Bittiming *Bittiming_p); + +void FCan_IntrHandler(void *InstancePtr); + +ft_error_t FCan_CalcBittiming(struct FCan_Bittiming *Bt_p); + +u32 FCan_SendByIrq(FCan_t *Can_p, + struct FCan_Frame *Frame_p, + u32 FrameNumber, void (*UserIrqWait)(void)); + +u32 FCan_RecvByIrq(FCan_t *Can_p, struct FCan_Frame *Frame_p, u32 FrameNumber); + +void FCan_Enable(FCan_t *Can_p); + +#endif // !FT_CAN_H diff --git a/bsp/ft2004/libraries/bsp/ft_can/ft_can_calc.c b/bsp/ft2004/libraries/bsp/ft_can/ft_can_calc.c new file mode 100644 index 0000000000000000000000000000000000000000..c2a9d7d8ee748fdb5ef8881a8f72bb6aea7d5515 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_can/ft_can_calc.c @@ -0,0 +1,298 @@ +/* + * @[H]: Copyright (C) 2014-2021 Phytium Technology.  All rights reserved. + * + *  Permission is hereby granted, free of charge, to any person obtaining a copy + *  of this software and associated documentation files (the "Software"), to deal + *  in the Software without restriction, including without limitation the rights + *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + *  copies of the Software, and to permit persons to whom the Software is + *  furnished to do so, subject to the following conditions: + * + *  The above copyright notice and this permission notice shall be included in + *  all copies or substantial portions of the Software. + * + *  Use of the Software is limited solely to applications: + *  (a) running on a Phytium device, or + *  (b) that interact with a Phytium device through a bus or interconnect. + * + *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + *  PHYTIUM  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + *  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + *  SOFTWARE. + * + *  Except as contained in this notice, the name of the Phytium shall not be used + *  in advertising or otherwise to promote the sale, use or other dealings in + *  this Software without prior written authorization from Phytium.  + * + * @Date: 2021-05-06 09:30:51 + * @LastEditTime: 2021-05-06 09:30:51 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + */ + +#include "ft_can.h" + +#include "ft_debug.h" +#include "string.h" + +#ifndef max +#define max(x, y) (((x) < (y)) ? (y) : (x)) +#endif + +#ifndef min +#define min(x, y) (((x) < (y)) ? (x) : (y)) +#endif + +#define FT_CAN_DEBUG_TAG "FT_CAN" + +#define FT_CAN_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__) +#define FT_CAN_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__) +#define FT_CAN_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__) + +#define CAN_CLK_FREQ 600000000 +#define CAN_CALC_SYNC_SEG 1 +#define FCAN_TSEG1_MIN 1 +#define FCAN_TSEG1_MAX 8 +#define FCAN_TSEG2_MIN 1 +#define FCAN_TSEG2_MAX 8 +#define FCAN_SJW_MAX 4 +#define FCAN_BRP_MIN 1 +#define FCAN_BRP_MAX 512 +#define FCAN_BRP_INC 1 +#define FCAN_CALC_SYNC_SEG 1 +#define CAN_CALC_MAX_ERROR 50 /* in one-tenth of a percent */ +#define BEST_BITRATE_ERROR (2147483647 * 2U + 1) + +#define clamp(x, low, high) (min(max(low, x), high)) + +typedef struct can_bittiming_const +{ + char name[16]; /* Name of the CAN controller hardware */ + u32 tseg1_min; /* Time segement 1 = prop_seg + phase_seg1 */ + u32 tseg1_max; + u32 tseg2_min; /* Time segement 2 = phase_seg2 */ + u32 tseg2_max; + u32 sjw_max; /* Synchronisation jump width */ + u32 brp_min; /* Bit-rate prescaler */ + u32 brp_max; + u32 brp_inc; +} FTCAN_BITTIMING_CONST; + +static const struct can_bittiming_const ftcan_bittiming_const = { + .name = "vxbftCan", + .tseg1_min = 1, + .tseg1_max = 8, + .tseg2_min = 1, + .tseg2_max = 8, + .sjw_max = 4, + .brp_min = 1, + .brp_max = 512, + .brp_inc = 1, +}; + +static int abs( + int i /* integer for which to return absolute value */ +) +{ + return (i >= 0 ? i : -i); +} + +static u32 div64_32(u64 *n, u32 base) +{ + u64 rem = *n; + u64 b = base; + u64 res, d = 1; + u32 high = rem >> 32; + + /* Reduce the thing a bit first */ + res = 0; + if (high >= base) + { + high /= base; + res = (u64)high << 32; + rem -= (u64)(high * base) << 32; + } + + while ((u64)b > 0 && b < rem) + { + b = b + b; + d = d + d; + } + + do + { + if (rem >= b) + { + rem -= b; + res += d; + } + b >>= 1; + d >>= 1; + } while (d); + + *n = res; + return rem; +} + +s32 can_update_sample_point(const struct can_bittiming_const *btc, + u32 sample_point_nominal, u32 tseg, + u32 *tseg1_ptr, u32 *tseg2_ptr, + u32 *sample_point_error_ptr) +{ + u32 sample_point_error, best_sample_point_error = BEST_BITRATE_ERROR; + u32 sample_point, best_sample_point = 0; + u32 tseg1, tseg2; + s32 i; + + for (i = 0; i <= 1; i++) + { + tseg2 = tseg + CAN_CALC_SYNC_SEG - (sample_point_nominal * (tseg + CAN_CALC_SYNC_SEG)) / 1000 - i; + tseg2 = clamp(tseg2, btc->tseg2_min, btc->tseg2_max); + tseg1 = tseg - tseg2; + if (tseg1 > btc->tseg1_max) + { + tseg1 = btc->tseg1_max; + tseg2 = tseg - tseg1; + } + + sample_point = 1000 * (tseg + CAN_CALC_SYNC_SEG - tseg2) / (tseg + CAN_CALC_SYNC_SEG); + sample_point_error = abs(sample_point_nominal - sample_point); + + if ((sample_point <= sample_point_nominal) && (sample_point_error < best_sample_point_error)) + { + best_sample_point = sample_point; + best_sample_point_error = sample_point_error; + *tseg1_ptr = tseg1; + *tseg2_ptr = tseg2; + } + } + + if (sample_point_error_ptr) + *sample_point_error_ptr = best_sample_point_error; + + return best_sample_point; +} + +ft_error_t FCan_CalcBittiming(struct FCan_Bittiming *Bt_p) +{ + u32 bitrate; /* current bitrate */ + u32 bitrate_error; /* difference between current and nominal value */ + u32 best_bitrate_error = BEST_BITRATE_ERROR; + u32 sample_point_error; /* difference between current and nominal value */ + u32 best_sample_point_error = BEST_BITRATE_ERROR; + u32 sample_point_nominal; /* nominal sample point */ + u32 best_tseg = 0; /* current best value for tseg */ + u32 best_brp = 0; /* current best value for brp */ + u32 brp, tsegall, tseg, tseg1 = 0, tseg2 = 0; + u64 v64; + const struct can_bittiming_const *btc = &ftcan_bittiming_const; + struct FCan_Bittiming *bt = Bt_p; + + if (bt->sample_point) + { + sample_point_nominal = bt->sample_point; + } + else + { + if (bt->bitrate > 800000) + sample_point_nominal = 750; + else if (bt->bitrate > 500000) + sample_point_nominal = 800; + else + sample_point_nominal = 875; + } + + for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1; + tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--) + { + tsegall = CAN_CALC_SYNC_SEG + tseg / 2; + + /* Compute all possible tseg choices (tseg=tseg1+tseg2) */ + brp = CAN_CLK_FREQ / (tsegall * bt->bitrate) + tseg % 2; + + /* choose brp step which is possible in system */ + brp = (brp / btc->brp_inc) * btc->brp_inc; + + if ((brp < btc->brp_min) || (brp > btc->brp_max)) + continue; + + bitrate = CAN_CLK_FREQ / (brp * tsegall); + + bitrate_error = abs(bt->bitrate - bitrate); + /* tseg brp biterror */ + if (bitrate_error > best_bitrate_error) + continue; + + /* reset sample point error if we have a better bitrate */ + if (bitrate_error < best_bitrate_error) + best_sample_point_error = BEST_BITRATE_ERROR; + + can_update_sample_point(btc, sample_point_nominal, tseg / 2, &tseg1, &tseg2, &sample_point_error); + if (sample_point_error > best_sample_point_error) + continue; + + best_sample_point_error = sample_point_error; + best_bitrate_error = bitrate_error; + best_tseg = tseg / 2; + best_brp = brp; + + if (bitrate_error == 0 && sample_point_error == 0) + break; + } + + if (best_bitrate_error) + { + /* Error in one-tenth of a percent */ + v64 = (u64)best_bitrate_error * 1000; + div64_32(&v64, bt->bitrate); + bitrate_error = (u32)v64; + if (bitrate_error > CAN_CALC_MAX_ERROR) + { + // FTCAN_LOGMSG("bitrate error %d.%d%% too high\n", + // bitrate_error / 10, bitrate_error % 10, 3, 4, 5, 6); + FT_CAN_DEBUG_E("bitrate error"); + } + return FCAN_FAILURE; + FT_CAN_DEBUG_E("bitrate error 2"); + // FTCAN_LOGMSG("bitrate error %d.%d%%\n", + // bitrate_error / 10, bitrate_error % 10, 3, 4, 5, 6); + } + + /* real sample point */ + bt->sample_point = can_update_sample_point(btc, sample_point_nominal, best_tseg, + &tseg1, &tseg2, NULL); + + v64 = (u64)best_brp * 1000 * 1000 * 1000; + div64_32(&v64, CAN_CLK_FREQ); + bt->tq = (u64)v64; + bt->prop_seg = tseg1 / 2; + bt->phase_seg1 = tseg1 - bt->prop_seg; + bt->phase_seg2 = tseg2; + + /* check for sjw user settings */ + if (!bt->sjw || !btc->sjw_max) + { + bt->sjw = 1; + } + else + { + /* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */ + if (bt->sjw > btc->sjw_max) + bt->sjw = btc->sjw_max; + /* bt->sjw must not be higher than tseg2 */ + if (tseg2 < bt->sjw) + bt->sjw = tseg2; + } + + bt->brp = best_brp; + + /* real bitrate */ + bt->bitrate = CAN_CLK_FREQ / (bt->brp * (CAN_CALC_SYNC_SEG + tseg1 + tseg2)); + // FT_CAN_DEBUG_I(" tq 0x%x ,prop_seg 0x%x , phase_seg1 0x%x, phase_seg2 0x%x ,brp 0x%x \r\n", bt->tq, bt->prop_seg, bt->phase_seg1, bt->phase_seg2, bt->brp); + return FCAN_SUCCESS; +} diff --git a/bsp/ft2004/libraries/bsp/ft_can/ft_can_g.c b/bsp/ft2004/libraries/bsp/ft_can/ft_can_g.c new file mode 100644 index 0000000000000000000000000000000000000000..daac715f95f0cb47b4eadb604db70e8027539c68 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_can/ft_can_g.c @@ -0,0 +1,63 @@ +/* + * @[H]: Copyright (C) 2014-2021 Phytium Technology.  All rights reserved. + * + *  Permission is hereby granted, free of charge, to any person obtaining a copy + *  of this software and associated documentation files (the "Software"), to deal + *  in the Software without restriction, including without limitation the rights + *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + *  copies of the Software, and to permit persons to whom the Software is + *  furnished to do so, subject to the following conditions: + * + *  The above copyright notice and this permission notice shall be included in + *  all copies or substantial portions of the Software. + * + *  Use of the Software is limited solely to applications: + *  (a) running on a Phytium device, or + *  (b) that interact with a Phytium device through a bus or interconnect. + * + *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + *  PHYTIUM  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + *  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + *  SOFTWARE. + * + *  Except as contained in this notice, the name of the Phytium shall not be used + *  in advertising or otherwise to promote the sale, use or other dealings in + *  this Software without prior written authorization from Phytium.  + * + * @Date: 2021-04-27 15:31:44 + * @LastEditTime: 2021-04-27 15:31:44 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + */ + +#include "ft_can.h" +#include "ft_parameters.h" + +FCan_Config_t FCan_Config[FT_CAN_NUM] = + { + { + .InstanceId = 0, /* Id of device */ + .CanBaseAddress = FT_CAN0_BASEADDR, /* Can base Address */ + .IrqNum = FT_CAN0_IRQNUM, + .BaudRate = 250000, + .TxFifoDeepth = 16, + }, + { + .InstanceId = 1, /* Id of device */ + .CanBaseAddress = FT_CAN1_BASEADDR, /* Can base Address */ + .IrqNum = FT_CAN1_IRQNUM, + .BaudRate = 250000, + .TxFifoDeepth = 16, + }, + { + .InstanceId = 2, /* Id of device */ + .CanBaseAddress = FT_CAN2_BASEADDR, /* Can base Address */ + .IrqNum = FT_CAN2_IRQNUM, + .BaudRate = 250000, + .TxFifoDeepth = 16, + }}; diff --git a/bsp/ft2004/libraries/bsp/ft_can/ft_can_hw.c b/bsp/ft2004/libraries/bsp/ft_can/ft_can_hw.c new file mode 100644 index 0000000000000000000000000000000000000000..3bbd2b53a47255d1428504d37990ad9ee582c139 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_can/ft_can_hw.c @@ -0,0 +1,79 @@ +/* + * @[H]: Copyright (C) 2014-2021 Phytium Technology.  All rights reserved. + * + *  Permission is hereby granted, free of charge, to any person obtaining a copy + *  of this software and associated documentation files (the "Software"), to deal + *  in the Software without restriction, including without limitation the rights + *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + *  copies of the Software, and to permit persons to whom the Software is + *  furnished to do so, subject to the following conditions: + * + *  The above copyright notice and this permission notice shall be included in + *  all copies or substantial portions of the Software. + * + *  Use of the Software is limited solely to applications: + *  (a) running on a Phytium device, or + *  (b) that interact with a Phytium device through a bus or interconnect. + * + *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + *  PHYTIUM  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + *  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + *  SOFTWARE. + * + *  Except as contained in this notice, the name of the Phytium shall not be used + *  in advertising or otherwise to promote the sale, use or other dealings in + *  this Software without prior written authorization from Phytium.  + * + * @Date: 2021-04-27 13:52:41 + * @LastEditTime: 2021-04-27 13:52:41 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + */ + +#include "ft_can_hw.h" +#include "ft_can.h" +#include "ft_mux.h" +#include "ft_parameters.h" +#include "ft_math.h" +#include "ft_assert.h" +#include "ft_debug.h" + +#define CAN_HW_DEBUG_TAG "CAN_HW" + +#define CAN_HW_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(CAN_HW_DEBUG_TAG, format, ##__VA_ARGS__) +#define CAN_HW_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(CAN_HW_DEBUG_TAG, format, ##__VA_ARGS__) +#define CAN_HW_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(CAN_HW_DEBUG_TAG, format, ##__VA_ARGS__) + +void FCan_Reset(FCan_t *Can_p) +{ + u32 RegValue; + FCan_Config_t *Config_p; + Ft_assertVoid(Can_p != NULL); + Ft_assertVoid(Can_p->IsReady == FT_COMPONENT_IS_READLY); + Config_p = &Can_p->Config; + + RegValue = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET); + + if (RegValue & FCAN_CTRL_XFER_MASK) + { + CAN_HW_DEBUG_E("FT can is not in configration mode\n"); + Ft_assertVoid(0); + return; + } + + FCan_WriteReg(FT_PIN_DEMUX_BASE, FT_PIN_DEMUX_REG204_OFFSET, 0x89999990); // Reuse can IO + + FCan_WriteReg(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_RESET_MASK); + FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_AIME_MASK); + FCan_WriteReg(Config_p->CanBaseAddress, FCAN_ACC_ID0_MASK_OFFSET, FCAN_ACC_IDN_MASK); + FCan_WriteReg(Config_p->CanBaseAddress, FCAN_ACC_ID1_MASK_OFFSET, FCAN_ACC_IDN_MASK); + FCan_WriteReg(Config_p->CanBaseAddress, FCAN_ACC_ID2_MASK_OFFSET, FCAN_ACC_IDN_MASK); + FCan_WriteReg(Config_p->CanBaseAddress, FCAN_ACC_ID3_MASK_OFFSET, FCAN_ACC_IDN_MASK); + FCan_ClearBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_RESET_MASK); + FCan_WriteReg(Config_p->CanBaseAddress, FCAN_INTR_OFFSET, FCAN_INTR_TEIE_MASK | FCAN_INTR_REIE_MASK); +} \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/ft_can/ft_can_hw.h b/bsp/ft2004/libraries/bsp/ft_can/ft_can_hw.h new file mode 100644 index 0000000000000000000000000000000000000000..3378571f95f3fd7539785f01196a3c03d6d6d4e4 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_can/ft_can_hw.h @@ -0,0 +1,185 @@ +/* + * @[H]: Copyright (C) 2014-2021 Phytium Technology.  All rights reserved. + * + *  Permission is hereby granted, free of charge, to any person obtaining a copy + *  of this software and associated documentation files (the "Software"), to deal + *  in the Software without restriction, including without limitation the rights + *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + *  copies of the Software, and to permit persons to whom the Software is + *  furnished to do so, subject to the following conditions: + * + *  The above copyright notice and this permission notice shall be included in + *  all copies or substantial portions of the Software. + * + *  Use of the Software is limited solely to applications: + *  (a) running on a Phytium device, or + *  (b) that interact with a Phytium device through a bus or interconnect. + * + *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + *  PHYTIUM  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + *  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + *  SOFTWARE. + * + *  Except as contained in this notice, the name of the Phytium shall not be used + *  in advertising or otherwise to promote the sale, use or other dealings in + *  this Software without prior written authorization from Phytium.  + * + * @Date: 2021-04-27 13:52:47 + * @LastEditTime: 2021-04-27 13:52:47 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + */ + +#ifndef FT_CAN_HW_H +#define FT_CAN_HW_H + +#include "ft_types.h" +#include "ft_io.h" +#include "ft_can.h" + +/***ft CAN REGISTER offset*/ +#define FCAN_CTRL_OFFSET 0x00 /* Global control register */ +#define FCAN_INTR_OFFSET 0x04 /* Interrupt register */ +#define FCAN_ARB_RATE_CTRL_OFFSET 0x08 /* Arbitration rate control register */ +#define FCAN_DAT_RATE_CTRL_OFFSET 0x0C /* Data rate control register */ +#define FCAN_ACC_ID0_OFFSET 0x10 /* Acceptance identifier0 register */ +#define FCAN_ACC_ID1_OFFSET 0x14 /* Acceptance identifier1 register */ +#define FCAN_ACC_ID2_OFFSET 0x18 /* Acceptance identifier2 register */ +#define FCAN_ACC_ID3_OFFSET 0x1C /* Acceptance identifier3 register */ +#define FCAN_ACC_ID0_MASK_OFFSET 0x20 /* Acceptance identifier0 mask register */ +#define FCAN_ACC_ID1_MASK_OFFSET 0x24 /* Acceptance identifier1 mask register */ +#define FCAN_ACC_ID2_MASK_OFFSET 0x28 /* Acceptance identifier2 mask register */ +#define FCAN_ACC_ID3_MASK_OFFSET 0x2C /* Acceptance identifier3 mask register */ +#define FCAN_XFER_STS_OFFSET 0x30 /* Transfer status register */ +#define FCAN_ERR_CNT_OFFSET 0x34 /* Error counter register */ +#define FCAN_FIFO_CNT_OFFSET 0x38 /* FIFO counter register */ +#define FCAN_DMA_CTRL_OFFSET 0x3C /* DMA request control register */ +#define FCAN_TX_FIFO_OFFSET 0x100 /* TX FIFO shadow register */ +#define FCAN_RX_FIFO_OFFSET 0x200 /* RX FIFO shadow register */ + +/*----------------------------------------------------------------------------*/ +/* CAN register bit masks - FCAN___MASK */ +/*----------------------------------------------------------------------------*/ + +/* FCAN_CTRL mask */ +#define FCAN_CTRL_XFER_MASK (0x1 << 0) /* RW */ /*Transfer enable*/ +#define FCAN_CTRL_TXREQ_MASK (0x1 << 1) /* RW */ /*Transmit request*/ +#define FCAN_CTRL_AIME_MASK (0x1 << 2) /* RW */ /*Acceptance identifier mask enable*/ +#define FCAN_CTRL_RESET_MASK (0x1 << 6) + +/* FCAN_INTR mask */ +#define FCAN_INTR_STATUS_MASK (0xFF << 0) /* RO */ /*the interrupt status*/ +#define FCAN_INTR_BOIS_MASK (0x1 << 0) /* RO */ /*Bus off interrupt status*/ +#define FCAN_INTR_PWIS_MASK (0x1 << 1) /* RO */ /*Passive warning interrupt status*/ +#define FCAN_INTR_PEIS_MASK (0x1 << 2) /* RO */ /*Passive error interrupt status*/ +#define FCAN_INTR_RFIS_MASK (0x1 << 3) /* RO */ /*RX FIFO full interrupt status*/ +#define FCAN_INTR_TFIS_MASK (0x1 << 4) /* RO */ /*TX FIFO empty interrupt status*/ +#define FCAN_INTR_REIS_MASK (0x1 << 5) /* RO */ /*RX frame end interrupt status*/ +#define FCAN_INTR_TEIS_MASK (0x1 << 6) /* RO */ /*TX frame end interrupt status*/ +#define FCAN_INTR_EIS_MASK (0x1 << 7) /* RO */ /*Error interrupt status*/ + +#define FCAN_INTR_EN_MASK (0xFF << 8) /* RO */ /*the interrupt enable*/ +#define FCAN_INTR_BOIE_MASK (0x1 << 8) /* RW */ /*Bus off interrupt enable*/ +#define FCAN_INTR_PWIE_MASK (0x1 << 9) /* RW */ /*Passive warning interrupt enable*/ +#define FCAN_INTR_PEIE_MASK (0x1 << 10) /* RW */ /*Passive error interrupt enable*/ +#define FCAN_INTR_RFIE_MASK (0x1 << 11) /* RW */ /*RX FIFO full interrupt enable*/ +#define FCAN_INTR_TFIE_MASK (0x1 << 12) /* RW */ /*TX FIFO empty interrupt enable*/ +#define FCAN_INTR_REIE_MASK (0x1 << 13) /* RW */ /*RX frame end interrupt enable*/ +#define FCAN_INTR_TEIE_MASK (0x1 << 14) /* RW */ /*TX frame end interrupt enable*/ +#define FCAN_INTR_EIE_MASK (0x1 << 15) /* RW */ /*Error interrupt enable*/ + +#define FCAN_INTR_BOIC_MASK (0x1 << 16) /* WO */ /*Bus off interrupt clear*/ +#define FCAN_INTR_PWIC_MASK (0x1 << 17) /* WO */ /*Passive warning interrupt clear*/ +#define FCAN_INTR_PEIC_MASK (0x1 << 18) /* WO */ /*Passive error interrupt clear*/ +#define FCAN_INTR_RFIC_MASK (0x1 << 19) /* WO */ /*RX FIFO full interrupt clear*/ +#define FCAN_INTR_TFIC_MASK (0x1 << 20) /* WO */ /*TX FIFO empty interrupt clear*/ +#define FCAN_INTR_REIC_MASK (0x1 << 21) /* WO */ /*RX frame end interrupt clear*/ +#define FCAN_INTR_TEIC_MASK (0x1 << 22) /* WO */ /*TX frame end interrupt clear*/ +#define FCAN_INTR_EIC_MASK (0x1 << 23) /* WO */ /*Error interrupt clear*/ + +/* FCAN_ACC_ID(0-3)_MASK mask */ +#define FCAN_ACC_IDN_MASK 0x1FFFFFFF /* WO */ /*don’t care the matching */ +/* FCAN_DAT_RATE_CTRL mask */ + +/* FCAN_ERR_CNT_OFFSET mask */ +#define FCAN_ERR_CNT_RFN_MASK (0xFF << 0) /* RO */ /*Receive error counter*/ +#define FCAN_ERR_CNT_TFN_MASK (0xFF << 16) /* RO */ /*Transmit error counter*/ + +/* FCAN_FIFO_CNT_OFFSET mask */ +#define FCAN_FIFO_CNT_RFN_MASK (0xFF << 0) /* RO */ /*Receive FIFO valid data number*/ +#define FCAN_FIFO_CNT_TFN_MASK (0xFF << 16) /* RO */ /*Transmit FIFO valid data number*/ + +#define FCAN_ERR_CNT_TFN_SHIFT 16 /* Tx Error Count shift */ +#define FCAN_FIFO_CNT_TFN_SHIFT 16 /* Tx FIFO Count shift*/ +#define FCAN_IDR_ID1_SHIFT 21 /* Standard Messg Identifier */ +#define FCAN_IDR_ID2_SHIFT 1 /* Extended Message Identifier */ +#define FCAN_IDR_SDLC_SHIFT 14 +#define FCAN_IDR_EDLC_SHIFT 26 +#define FCAN_ACC_IDN_SHIFT 18 /*Standard ACC ID shift*/ + +#define FCAN_IDR_ID2_MASK 0x0007FFFE /* Extended message ident */ +#define FCAN_IDR_ID1_MASK 0xFFE00000 /* Standard msg identifier */ +#define FCAN_IDR_IDE_MASK 0x00080000 /* Identifier extension */ +#define FCAN_IDR_SRR_MASK 0x00100000 /* Substitute remote TXreq */ +#define FCAN_IDR_RTR_MASK 0x00000001 /* Extended frames remote TX request */ +#define FCAN_IDR_DLC_MASK 0x0003C000 /* Standard msg dlc */ +#define FCAN_IDR_PAD_MASK 0x00003FFF /* Standard msg padding 1 */ +#define FCAN_IDR_EDLC_MASK 0x3C000000 /* Extended msg dlc */ + +/* Can timming */ +#define FCAN_TSEG1_MIN 1 +#define FCAN_TSEG1_MAX 8 +#define FCAN_TSEG2_MIN 1 +#define FCAN_TSEG2_MAX 8 +#define FCAN_SJW_MAX 4 +#define FCAN_BRP_MIN 1 +#define FCAN_BRP_MAX 512 +#define FCAN_BRP_INC 1 +#define FCAN_CALC_SYNC_SEG 1 + +/** +* +* This macro reads the given register. +* +* @param BaseAddr is the base address of the device. +* @param RegOffset is the register offset to be read. +* +* @return The 32-bit value of the register +* +* @note None. +* +*****************************************************************************/ +#define FCan_ReadReg(BaseAddr, RegOffset) \ + Ft_in32((BaseAddr) + (u32)(RegOffset)) + +/****************************************************************************/ +/** +* +* This macro writes the given register. +* +* @param BaseAddr is the base address of the device. +* @param RegOffset is the register offset to be written. +* @param Data is the 32-bit value to write to the register. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +#define FCan_WriteReg(BaseAddr, RegOffset, Data) \ + Ft_out32((BaseAddr) + (u32)(RegOffset), (u32)(Data)) + +#define FCan_SetBit(BaseAddr, RegOffset, Data) \ + Ft_setBit32((BaseAddr) + (u32)(RegOffset), (u32)(Data)) + +#define FCan_ClearBit(BaseAddr, RegOffset, Data) \ + Ft_clearBit32((BaseAddr) + (u32)(RegOffset), (u32)(Data)) + +void FCan_Reset(FCan_t *Can_p); + +#endif // ! diff --git a/bsp/ft2004/libraries/bsp/ft_can/ft_can_intr.c b/bsp/ft2004/libraries/bsp/ft_can/ft_can_intr.c new file mode 100644 index 0000000000000000000000000000000000000000..ddd3cb13b2d860f4b30ae6fd07793f8bf4f5b39f --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_can/ft_can_intr.c @@ -0,0 +1,142 @@ +/* + * @[H]: Copyright (C) 2014-2021 Phytium Technology.  All rights reserved. + * + *  Permission is hereby granted, free of charge, to any person obtaining a copy + *  of this software and associated documentation files (the "Software"), to deal + *  in the Software without restriction, including without limitation the rights + *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + *  copies of the Software, and to permit persons to whom the Software is + *  furnished to do so, subject to the following conditions: + * + *  The above copyright notice and this permission notice shall be included in + *  all copies or substantial portions of the Software. + * + *  Use of the Software is limited solely to applications: + *  (a) running on a Phytium device, or + *  (b) that interact with a Phytium device through a bus or interconnect. + * + *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + *  PHYTIUM  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + *  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + *  SOFTWARE. + * + *  Except as contained in this notice, the name of the Phytium shall not be used + *  in advertising or otherwise to promote the sale, use or other dealings in + *  this Software without prior written authorization from Phytium.  + * + * @Date: 2021-04-29 10:40:47 + * @LastEditTime: 2021-04-29 10:40:47 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + */ + +#include "ft_can.h" +#include "ft_can_hw.h" +#include "ft_assert.h" +#include "ft_types.h" + +ft_error_t FCan_SetHandler(FCan_t *Can_p, u32 HandlerType, FCan_irqHandler_t IrqCallBackFunc, void *IrqCallBackRef) +{ + ft_error_t status = FCAN_SUCCESS; + Ft_assertNonvoid(Can_p != NULL); + Ft_assertNonvoid(Can_p->IsReady == FT_COMPONENT_IS_READLY); + switch (HandlerType) + { + case FCAN_HANDLER_SEND: + Can_p->SendHandler = IrqCallBackFunc; + Can_p->SendRef = IrqCallBackRef; + break; + case FCAN_HANDLER_RECV: + Can_p->RecvHandler = IrqCallBackFunc; + Can_p->RecvRef = IrqCallBackRef; + break; + case FCAN_HANDLER_ERROR: + Can_p->ErrorHandler = IrqCallBackFunc; + Can_p->ErrorRef = IrqCallBackRef; + break; + default: + status = FCAN_FAILURE; + } + + return status; +} + +static void FCan_TxInterrupt(FCan_t *Can_p) +{ + FCan_Config_t *Config_p = &Can_p->Config; + FCan_SetBit(Config_p->CanBaseAddress, FCAN_INTR_OFFSET, FCAN_INTR_TEIC_MASK | FCAN_INTR_REIC_MASK); + + if (0 != Can_p->TxFifoCnt) + { + Can_p->TxFifoCnt--; + FCan_ClearBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK); + FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_TXREQ_MASK); + FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK); + } + else + { + if (Can_p->SendHandler) + { + Can_p->SendHandler(Can_p->SendRef); + } + } +} + +static void FCan_ErrorInterrupt(FCan_t *Can_p) +{ + if (Can_p->ErrorHandler) + { + Can_p->ErrorHandler(Can_p->ErrorRef); + } +} + +static void FCan_RxInterrupt(FCan_t *Can_p) +{ + if (Can_p->RecvHandler) + { + Can_p->RecvHandler(Can_p->RecvRef); + } +} + +void FCan_IntrHandler(void *InstancePtr) +{ + u32 Irq; + FCan_t *Can_p = (FCan_t *)InstancePtr; + FCan_Config_t *Config_p; + Ft_assertVoid(Can_p != NULL); + Ft_assertVoid(Can_p->IsReady == FT_COMPONENT_IS_READLY); + Config_p = &Can_p->Config; + Irq = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_INTR_OFFSET); + + if (0 == Irq) + { + return; + } + + /* Check for the type of error interrupt and Processing it */ + if (Irq & FCAN_INTR_TEIS_MASK) + { + Irq &= ~FCAN_INTR_REIS_MASK; + FCan_TxInterrupt(Can_p); + } + + if (Irq & (FCAN_INTR_EIS_MASK | FCAN_INTR_RFIS_MASK | + FCAN_INTR_BOIS_MASK | FCAN_INTR_PEIS_MASK | FCAN_INTR_PWIS_MASK)) + { + FCan_SetBit(Config_p->CanBaseAddress, FCAN_INTR_OFFSET, (FCAN_INTR_EIC_MASK | FCAN_INTR_RFIC_MASK | FCAN_INTR_BOIC_MASK | FCAN_INTR_PEIC_MASK | FCAN_INTR_PWIC_MASK)); + FCan_ErrorInterrupt(Can_p); + } + + if (Irq & FCAN_INTR_REIS_MASK) + { + FCan_SetBit(Config_p->CanBaseAddress, FCAN_INTR_OFFSET, FCAN_INTR_REIE_MASK); + FCan_RxInterrupt(Can_p); + FCan_SetBit(Config_p->CanBaseAddress, FCAN_INTR_OFFSET, FCAN_INTR_REIC_MASK); + FCan_SetBit(Config_p->CanBaseAddress, FCAN_INTR_OFFSET, FCAN_INTR_REIE_MASK); + } +} \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/ft_can/ft_can_sinit.c b/bsp/ft2004/libraries/bsp/ft_can/ft_can_sinit.c new file mode 100644 index 0000000000000000000000000000000000000000..c413031a97d3261995ed6e55e5e2d0367ce1134b --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_can/ft_can_sinit.c @@ -0,0 +1,64 @@ +/* + * @[H]: Copyright (C) 2014-2021 Phytium Technology.  All rights reserved. + * + *  Permission is hereby granted, free of charge, to any person obtaining a copy + *  of this software and associated documentation files (the "Software"), to deal + *  in the Software without restriction, including without limitation the rights + *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + *  copies of the Software, and to permit persons to whom the Software is + *  furnished to do so, subject to the following conditions: + * + *  The above copyright notice and this permission notice shall be included in + *  all copies or substantial portions of the Software. + * + *  Use of the Software is limited solely to applications: + *  (a) running on a Phytium device, or + *  (b) that interact with a Phytium device through a bus or interconnect. + * + *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + *  PHYTIUM  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + *  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + *  SOFTWARE. + * + *  Except as contained in this notice, the name of the Phytium shall not be used + *  in advertising or otherwise to promote the sale, use or other dealings in + *  this Software without prior written authorization from Phytium.  + * + * @Date: 2021-04-27 15:31:57 + * @LastEditTime: 2021-04-27 15:31:57 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + */ + +#include "ft_can.h" +#include "ft_parameters.h" + +extern FCan_Config_t FCan_Config[FT_CAN_NUM]; + +/** + * @name: + * @msg: + * @in param: + * @return {*} + * @param {u32} InstanceId + */ +FCan_Config_t *FCan_LookupConfig(u32 InstanceId) +{ + FCan_Config_t *CfgPtr = NULL; + u32 Index; + + for (Index = 0; Index < (u32)FT_CAN_NUM; Index++) + { + if (FCan_Config[Index].InstanceId == InstanceId) + { + CfgPtr = &FCan_Config[Index]; + break; + } + } + return (FCan_Config_t *)CfgPtr; +} diff --git a/bsp/ft2004/libraries/bsp/ft_gicv3/ft_gicv3.c b/bsp/ft2004/libraries/bsp/ft_gicv3/ft_gicv3.c new file mode 100644 index 0000000000000000000000000000000000000000..70b20aad0ed2eaea9c3ed14ee001388096621bbe --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gicv3/ft_gicv3.c @@ -0,0 +1,194 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-05-18 18:07:24 + * @Description:  This files is for gic v3.0 + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_types.h" +#include "ft_assert.h" +#include "ft_printf.h" +#include "ft_io.h" +#include "ft_gicv3_hw.h" +#include "ft_gicv3.h" + +/************************** Variable Definitions *****************************/ +static u32 CpuId = 0; + +/************************** Function Prototypes ******************************/ + +static void FGicv3_stubHandler(void *Args) +{ + Ft_assertVoid(Args != NULL); + + ((FGicv3 *)Args)->UnhandledInterrupts++; +} + +/** + * @name: Ft_GicV3_ConfigInitalize + * @msg: gicv3 initialization + * @param {FGicv3} *GicPtr + * @param {Ft_Gicv3_Config} *ConfigPtr + * @return {*} + */ +s32 FGicv3_Config_tInitalize(FGicv3 *GicPtr, FGicv3_Config_t *ConfigPtr) +{ + u32 InstanceId; + Ft_assertNonvoid(GicPtr != NULL); + Ft_assertNonvoid(ConfigPtr != NULL); + + if (GicPtr->IsReady != FT_COMPONENT_IS_READLY) + { + + GicPtr->IsReady = 0U; + GicPtr->Config = ConfigPtr; + + for (InstanceId = 0; InstanceId < FT_GICV3_VECTORTABLE_NUM; InstanceId++) + { + if (GicPtr->Config->HanderTable[InstanceId].Handler == NULL) + { + GicPtr->Config->HanderTable[InstanceId].Handler = FGicv3_stubHandler; + } + GicPtr->Config->HanderTable[InstanceId].Args = GicPtr; + } + + FGicV3_Stop(GicPtr->Config, CpuId); + FGicv3_InstanceInitialize(GicPtr->Config); + GicPtr->IsReady = FT_COMPONENT_IS_READLY; + } + else + { + FGicv3_InstanceInitialize(GicPtr->Config); + } + + return FST_SUCCESS; +} + +/** + * @name: Ft_GicV3_Connect + * @msg: 使中断处理函数与中断源进行连接,Args 作为参数,在调用时被传入中断处理函数 + * @param {FGicv3} GicPtr + * @param {u32} InterruptID + * @param {Ft_FGicv3_InterruptHandler} InterruptHandler + * @param {void *} Args + * @return {s32} + */ +s32 FGicV3_Connect(FGicv3 *GicPtr, + u32 InterruptID, + FGicv3_InterruptHandler_t InterruptHandler, + u32 Priority, + void *Args) +{ + Ft_assertNonvoid(GicPtr != NULL); + Ft_assertNonvoid(InterruptID < GIC_INT_MAX_NUM); + Ft_assertNonvoid(NULL != InterruptHandler); + Ft_assertNonvoid(GicPtr->IsReady == FT_COMPONENT_IS_READLY); + + if (FST_SUCCESS == FGicv3_RegisterHandler(GicPtr->Config, InterruptID, InterruptHandler, Args)) + { + return FGicV3_SetPriTrigTypeByDistAddr(GicPtr->Config->Gicv3DistributorAddress, + InterruptID, + GIC_TRIGGER_LEVEL_SENSITIVE, + Priority); + } + else + { + return FST_FAILURE; + } +} + +/** + * @name: FGicV3_Disconnect + * @msg: 断开中断源与中断函数间联系,并且关闭中断 + * @param {FGicv3} + * @param {InterruptID} 中断ID号 + * @return {*} + */ +void FGicV3_Disconnect(FGicv3 *GicPtr, + u32 InterruptID) +{ + Ft_assertVoid(GicPtr != NULL); + Ft_assertVoid(InterruptID < GIC_INT_MAX_NUM); + Ft_assertVoid(GicPtr->IsReady == FT_COMPONENT_IS_READLY); + + FGicV3_DisableInterrupt(GicPtr->Config, InterruptID); + + GicPtr->Config->HanderTable[InterruptID].Handler = FGicv3_stubHandler; + GicPtr->Config->HanderTable[InterruptID].Args = GicPtr; +} + +/** + * @name: FGicV3_Enable + * @msg: 开启Gic 中对应InterruptID 的中断 + * @param {FGicv3 *} GicPtr + * @param {InterruptID} 中断ID + * @return {void} + */ +void FGicV3_Enable(FGicv3 *GicPtr, + u32 InterruptID) +{ + Ft_assertVoid(GicPtr != NULL); + Ft_assertVoid(InterruptID < GIC_INT_MAX_NUM); + Ft_assertVoid(GicPtr->IsReady == FT_COMPONENT_IS_READLY); + + FGicV3_EnableInterrupt(GicPtr->Config, InterruptID); +} + +/** + * @name: FGicV3_SetPriority + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + */ +void FGicV3_SetPriority(FGicv3 *GicPtr, + u32 InterruptID, u32 Priority) +{ + Ft_assertVoid(GicPtr != NULL); + Ft_assertVoid(InterruptID < GIC_INT_MAX_NUM); + Ft_assertVoid(GicPtr->IsReady == FT_COMPONENT_IS_READLY); + FGicV3_SetPriTrigTypeByDistAddr(GicPtr->Config->Gicv3DistributorAddress, + InterruptID, + GIC_TRIGGER_LEVEL_SENSITIVE, + Priority); +} + +/** + * @name: FGicV3_Disable + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + */ +void FGicV3_Disable(FGicv3 *GicPtr, + u32 InterruptID) +{ + Ft_assertVoid(GicPtr != NULL); + Ft_assertVoid(InterruptID < GIC_INT_MAX_NUM); + Ft_assertVoid(GicPtr->IsReady == FT_COMPONENT_IS_READLY); + + FGicV3_DisableInterrupt(GicPtr->Config, InterruptID); +} + +/** + * @name: System_IrqHandler + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + * @param {u32} IccIar_num + */ +void System_IrqHandler(u32 IccIar_num) +{ + FGicv3_InterruptHandler(IccIar_num & 0x3FFUL, 0); +} diff --git a/bsp/ft2004/libraries/bsp/ft_gicv3/ft_gicv3.h b/bsp/ft2004/libraries/bsp/ft_gicv3/ft_gicv3.h new file mode 100644 index 0000000000000000000000000000000000000000..4eb9233ec48438a2e0a4a5e223a7261ef87344e0 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gicv3/ft_gicv3.h @@ -0,0 +1,85 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-27 16:01:32 + * @Description:  This files is for gic v3.0 + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ +#ifndef FT_GICV3_H +#define FT_GICV3_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ft_parameters.h" +#include "ft_types.h" +#include "ft_status.h" + +#include "ft_error_code.h" + +#define FGICV3_SUCCESS FST_SUCCESS /* SUCCESS */ +#define FGICV3_FAILURE FT_MAKE_ERRCODE(errGicV3, errBspGeneral, FST_FAILURE) /* Normal */ +#define FGICV3_TIMEOUT FT_MAKE_ERRCODE(errGicV3, errBspGeneral, FST_TIMEOUT) /* Timeout */ +#define FGICV3_EILSEQ FT_MAKE_ERRCODE(errGicV3, errBspGeneral, FST_EILSEQ) /* Illegal byte sequence. */ +#define FGICV3_INVALID_PARAM FT_MAKE_ERRCODE(errGicV3, errBspGeneral, FST_INVALID_PARAM) /* Invalid param. */ + + typedef void (*FGicv3_InterruptHandler_t)(void *data); + + /***************************Type Definitions*************************************/ + /* + Handler 是对应与中断向量表中的函数 + Args 是默认传入的参数 + */ + typedef struct + { + FGicv3_InterruptHandler_t Handler; + void *Args; + } FGicv3_VectorTableEntry_t; + + /***** Typedef contains configuration for the device *******/ + typedef struct + { + u32 InstanceId; /* Id of device */ + u32 Gicv3BaseAddress; /* gicv3 base Address */ + u32 Gicv3DistributorAddress; /* gicv3 Distributor Address */ + u32 Gicv3RdAddress; /* the overall behavior of the Redistributor, for controlling LPIs, and for generating */ + u32 Gicv3SgiAddress; /* controlling and generating PPIs and SGIs. */ + FGicv3_VectorTableEntry_t HanderTable[FT_GICV3_VECTORTABLE_NUM]; /* Vector table */ + } FGicv3_Config_t; + + typedef struct + { + FGicv3_Config_t *Config; + u32 IsReady; /* Device is initialised and ready */ + u32 UnhandledInterrupts; /**< Intc Statistics */ + } FGicv3; + + s32 FGicv3_Config_tInitalize(FGicv3 *GicPtr, FGicv3_Config_t *ConfigPtr); + s32 FGicV3_Connect(FGicv3 *GicPtr, + u32 InterruptID, + FGicv3_InterruptHandler_t InterruptHandler, + u32 Priority, + void *Args); + void FGicV3_Disconnect(FGicv3 *GicPtr, + u32 InterruptID); + void FGicV3_Enable(FGicv3 *GicPtr, + u32 InterruptID); + void FGicV3_Disable(FGicv3 *GicPtr, + u32 InterruptID); + FGicv3_Config_t *FGicv3_LookupConfig(u32 InstanceId); + void System_IrqHandler(u32 IccIar_num); + void FGicV3_SetPriority(FGicv3 *GicPtr, u32 InterruptID, u32 Priority); + +#ifdef __cplusplus +} +#endif + +#endif // ! \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/ft_gicv3/ft_gicv3_g.c b/bsp/ft2004/libraries/bsp/ft_gicv3/ft_gicv3_g.c new file mode 100644 index 0000000000000000000000000000000000000000..1de252deae1778f68242dfdffb0f16d9a3447eba --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gicv3/ft_gicv3_g.c @@ -0,0 +1,25 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-29 18:57:47 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_parameters.h" +#include "ft_gicv3.h" + +FGicv3_Config_t g_FGicv3_Config_tTable[FT_GICV3_INSTANCES_NUM] = { + { + .InstanceId = 0, /* Id of device */ + .Gicv3BaseAddress = FT_GICV3_BASEADDRESS, /* gicv3 base Address */ + .Gicv3DistributorAddress = FT_GICV3_DISTRIBUTOR_BASEADDRESS, /* gicv3 Distributor Address */ + .Gicv3RdAddress = FT_GICV3_RD_BASEADDRESS, /* the overall behavior of the Redistributor, for controlling LPIs, and for generating */ + .Gicv3SgiAddress = FT_GICV3_SGI_BASEADDRESS, /* controlling and generating PPIs and SGIs. */ + }}; \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/ft_gicv3/ft_gicv3_hw.c b/bsp/ft2004/libraries/bsp/ft_gicv3/ft_gicv3_hw.c new file mode 100644 index 0000000000000000000000000000000000000000..8be3e8dd5f630134d4b402758dd581010088654b --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gicv3/ft_gicv3_hw.c @@ -0,0 +1,745 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-05-18 18:08:20 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_types.h" +#include "ft_assert.h" +#include "ft_io.h" +#include "ft_status.h" +#include "ft_printf.h" +#include "ft_cpu.h" +#include "ft_aarch32_asm.h" +#include "ft_parameters.h" +#include "asmArm.h" +#include "ft_gicv3.h" +#include "ft_gicv3_hw.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define GIC_IPI_PRIORITY 0 +#define GIC_PRIORITY_LEVEL_STEP 0x10 +#define GIC_SPI_PRIORITY_DEFAULT 0x10101010 +#define ARM_GICV3_MSI_START 125 +#define ARM_GICV3_MSI_CNT 34 + +#define ARM_GICV3_PHYS_REG(offset) (armGicBase + offset) +#define ARM_GICV3_VIRT_REG(offset) (armGicBase + offset) + +#define ARM_GICV3_MSI_CAP_ADDR_OFF 0x40 +#define ARM_GICV3_MSI_ANSWER_OFF 0x48 +#define ARM_GICV3_MSI_CAP_PHYS_ADDR ARM_GICV3_PHYS_REG(ARM_GICV3_MSI_CAP_ADDR_OFF) +#define ARM_GICV3_MSI_ANSWER_ADDR ARM_GICV3_VIRT_REG(ARM_GICV3_MSI_ANSWER_OFF) + +/********************************Variable Definitions************************************************/ +extern FGicv3_Config_t g_FGicv3_Config_tTable[FT_GICV3_INSTANCES_NUM]; +static u32 g_FGicVersion = 3; + +/************************** Function Prototypes ******************************/ + +/* assembly functions */ + +/** + * @name: FGiv3_ClrMsiIntr + * @msg: 清除msi 中断,暂时没有启用 + * @param {Ft_Gicv3_Config} *Config + * @param {u32} irq + * @return {*} + */ +void FGiv3_ClrMsiIntr(FGicv3_Config_t *Config, u32 irq) +{ + // *(volatile u32 *)(ARM_GICV3_MSI_ANSWER_ADDR) = irq; + return; +} + +static __inline__ void __dsb(void) +{ + __asm__ volatile( + "dsb" + : /* no output */ + : /* no input */ + : "memory"); +} + +/** + * @name: Gicv3_Init + * @msg: + * @param {*} + * @return {*} + */ +// static void +// Gicv3_Init(FGicv3_Config_t *Config, s32 CpuID) +// { +// u32 value = 0; +// u32 count = 1000; +// s32 regGicLineNum = 0; + +// u32 aGicCfg = 0; +// s32 i = 0; + +// Ft_out32((UINTPTR)(Config->Gicv3DistributorAddress + GICD_CTLR_OFFSET), 0xB7); +// while (1) +// { +// if ((Ft_in32((UINTPTR)(Config->Gicv3DistributorAddress + GICD_CTLR_OFFSET)) & 0x80000000) == 0) +// { +// break; +// } +// } +// //Gicv3RdAddress, CpuID))); +// value &= ~GICC_WAKER_PROCESSORSLEEP_IN; +// Ft_out32(Ft_in32(GICR_WAKER_CPU(Config->Gicv3RdAddress, CpuID)), value); +// while (--count) +// { +// value = Ft_in32(Ft_in32(GICR_WAKER_CPU(Config->Gicv3RdAddress, CpuID))); +// if (1 ^ (value & GICC_WAKER_CHILDRENASLEEP_QUIESCENT)) +// break; +// } + +// //!< GICR_WAKER_OFFSET is 0 +// value = Ft_in32(Config->Gicv3SgiAddress + GICR_ISENABLER0_OFFSET); +// Ft_out32(GICR_INTENCLR_CPU(Config->Gicv3SgiAddress, CpuID), Swap32(ALL_PPI_INT_MASK)); +// Ft_out32(GICR_INTENABLE_CPU(Config->Gicv3SgiAddress, CpuID), ALL_SGI_INT_MASK); + +// // val = *GICR_IntEnable; +// // *GICR_INTENCLR_CPU(Config->Gicv3SgiAddress, CpuID) = SWAP32(ALL_PPI_INT_MASK); +// // *GICR_INTENABLE_CPU(Config->Gicv3SgiAddress, CpuID) = ALL_SGI_INT_MASK; + +// if (CpuID == 0 && g_FGicVersion < 3) +// { +// Ft_out32(Config->Gicv3DistributorAddress + GICD_CTLR_OFFSET, 0); +// //Gicv3DistributorAddress + GICD_TYPER_OFFSET)) & 0x1f); +// regGicLineNum = (regGicLineNum + 1) * SPI_START_INT_NUM; +// //= 3) +// { +// /* +// The Distributor control register (GICD_CTLR) must be configured to enable the interrupt groups and to set the routing mode. +// Enable Affinity routing (ARE bits) The ARE bits in GICD_CTLR control whether affinity routing is enabled. +// If affinity routing is not enabled, GICv3 can be configured for legacy operation . +// Whether affinity routing is enabled or not can be controlled separately for Secure and Non-secure state. +// Enables GICD_CTLR contains separate enable bits for Group 0, Secure Group 1 and Non-secure Group 1: +// GICD_CTLR.EnableGrp1S enables distribution of Secure Group 1 interrupts. +// GICD_CTLR.EnableGrp1NS enables distribution of Non-secure Group 1 interrupts. +// GICD_CTLR.EnableGrp0 enables distribution of Group 0 interrupts. +// */ +// Ft_out32(Config->Gicv3DistributorAddress + GICD_CTLR_OFFSET, 0x37); +// Ft_out32(Config->Gicv3SgiAddress + GICR_ICENABLER0_OFFSET, Swap32(ALL_PPI_INT_MASK)); +// Ft_out32(Config->Gicv3SgiAddress + GICR_ISENABLER0_OFFSET, ALL_SGI_INT_MASK); +// } +// else if (g_FGicVersion < 2) +// { +// Ft_out32(Config->Gicv3DistributorAddress + GICD_ICENABLE_OFFSET, 0); +// } + +// /* Get the max priority */ +// Ft_out32((UINTPTR)GIC_PRIO(Config->Gicv3DistributorAddress, SPI_START_INT_NUM), Swap32(0xff)); +// g_FGicv3_PriorityLevelMax = Ft_in32((UINTPTR)GIC_PRIO(Config->Gicv3DistributorAddress, SPI_START_INT_NUM)); +// Ft_out32((UINTPTR)GIC_PRIO(Config->Gicv3DistributorAddress, SPI_START_INT_NUM), Swap32(0)); + +// /* clear all pending PPI and SGI interrupts in the distributor */ +// if (g_FGicVersion >= 3) +// { +// Ft_out32((Config->Gicv3SgiAddress + GICR_ICPENDR0_OFFSET), Swap32(ALL_PPI_INT_MASK | ALL_SGI_INT_MASK)); +// } +// else +// { +// Ft_out32((Config->Gicv3DistributorAddress + GICD_ICPENDR_OFFSET), Swap32(ALL_PPI_INT_MASK | ALL_SGI_INT_MASK)); +// } + +// /* set default priority for all PPI and SGI interrupts to level 0(highest) */ +// for (i = 0; i < SPI_START_INT_NUM; i += 4) +// { +// /* code */ +// Ft_out32((UINTPTR)GIC_PRIO(Config->Gicv3DistributorAddress, i), GIC_IPI_PRIORITY); +// } + +// if (CpuID == 0) +// { +// /* +// * Disable all SPI interrupts +// * Clear all pending SPI interrupts in the distributor +// */ +// for (i = SPI_START_INT_NUM; i < GIC_INT_MAX_NUM; i += BITS_PER_WORD) +// { +// Ft_out32((UINTPTR)GIC_INTPENDCLR(Config->Gicv3DistributorAddress, i), 0xffffffff); +// //Gicv3DistributorAddress, i), 0xffffffff); +// //Gicv3DistributorAddress, i), GIC_SPI_PRIORITY_DEFAULT); +// if (g_FGicVersion < 3) +// { +// Ft_out32((UINTPTR)GIC_CPUTARG(Config->Gicv3DistributorAddress, i), Swap32(GIC_CPU_DIR_DEFAULT)); +// i += 4; +// } +// else +// { +// Ft_out32((UINTPTR)GIC_INTRPUTE_HIGH(Config->Gicv3DistributorAddress, i), GIC_V3_CPU_DIR_DEFAULT_HIGH); +// Ft_out32((UINTPTR)GIC_INTRPUTE_LOW(Config->Gicv3DistributorAddress, i), GIC_V3_CPU_DIR_DEFAULT_LOW); +// i++; +// } +// } +// } + +// /* setting whether 1-N/N-N and Level/Edge triggered */ + +// for (i = SPI_START_INT_NUM; i < regGicLineNum; i += CONFIGS_PER_WORD) +// { +// Ft_out32((UINTPTR)GIC_CONFIG(Config->Gicv3DistributorAddress, i), 0x55555555); /* 1-N, Level */ +// } + +// for (i = ARM_GICV3_MSI_START; i < ARM_GICV3_MSI_CNT; i++) +// { +// /* +// data = arm_gicv3_drv.rd32(ARM_GICV3_ICDICRn(i)); +// data |= EDGE_TRIGGER << ((i % 16) << 1); +// arm_gicv3_drv.wr32(ARM_GICV3_ICDICRn(i), data); +// */ + +// aGicCfg = Swap32(Ft_in32((UINTPTR)GIC_CONFIG(Config->Gicv3DistributorAddress, i))); +// aGicCfg |= BIT(((i % CONFIGS_PER_WORD) * GIC_INT_TRIGGER_SHIFT + 1)); +// Ft_out32((UINTPTR)GIC_CONFIG(Config->Gicv3DistributorAddress, i), aGicCfg); +// } + +// sys_icc_bpr_set(0); //Gicv3DistributorAddress + GICD_CTLR_OFFSET, Swap32(GIC_CONTROL_ENABLE)); +// } +// } + +static ft_error_t FGicv3_DistInit(u32 Gicv3DistributorAddress, s32 CpuID) +{ + s32 i = 0; + s32 regGicLineNum = 0; + + regGicLineNum = (s32)(Swap32(*(volatile u32 *)(Gicv3DistributorAddress + GICD_TYPER_OFFSET)) & 0x1f); + regGicLineNum = (regGicLineNum + 1) * SPI_START_INT_NUM; + + Ft_out32((UINTPTR)(Gicv3DistributorAddress + GICD_CTLR_OFFSET), 0xB7); + while (1) + { + if ((Ft_in32((UINTPTR)(Gicv3DistributorAddress + GICD_CTLR_OFFSET)) & 0x80000000) == 0) + { + break; + } + } + + if (CpuID == 0 && g_FGicVersion >= 3) + { + /* + The Distributor control register (GICD_CTLR) must be configured to enable the interrupt groups and to set the routing mode. + Enable Affinity routing (ARE bits) The ARE bits in GICD_CTLR control whether affinity routing is enabled. + If affinity routing is not enabled, GICv3 can be configured for legacy operation . + Whether affinity routing is enabled or not can be controlled separately for Secure and Non-secure state. + Enables GICD_CTLR contains separate enable bits for Group 0, Secure Group 1 and Non-secure Group 1: + GICD_CTLR.EnableGrp1S enables distribution of Secure Group 1 interrupts. + GICD_CTLR.EnableGrp1NS enables distribution of Non-secure Group 1 interrupts. + GICD_CTLR.EnableGrp0 enables distribution of Group 0 interrupts. + */ + Ft_out32(Gicv3DistributorAddress + GICD_CTLR_OFFSET, 0x37); + } + + for (i = 0; i < SPI_START_INT_NUM; i += 4) + { + /* code */ + Ft_out32((UINTPTR)GIC_PRIO(Gicv3DistributorAddress, i), GIC_IPI_PRIORITY); + } + + if (CpuID == 0) + { + /* + * Disable all SPI interrupts + * Clear all pending SPI interrupts in the distributor + */ + for (i = SPI_START_INT_NUM; i < GIC_INT_MAX_NUM; i += BITS_PER_WORD) + { + Ft_out32((UINTPTR)GIC_INTPENDCLR(Gicv3DistributorAddress, i), 0xffffffff); + //= 3) + { + Ft_out32((Gicv3SgiAddress + GICR_ICPENDR0_OFFSET), Swap32(ALL_PPI_INT_MASK | ALL_SGI_INT_MASK)); + } + + if (CpuId == 0 && g_FGicVersion >= 3) + { + Ft_out32(Gicv3SgiAddress + GICR_ICENABLER0_OFFSET, Swap32(ALL_PPI_INT_MASK)); + Ft_out32(Gicv3SgiAddress + GICR_ISENABLER0_OFFSET, ALL_SGI_INT_MASK); + } + return FST_SUCCESS; +} + +static ft_error_t FGicv3_CpuInit(void) +{ + u32 value = 0; + + value = sys_icc_sre_get(); + value |= ICC_SRE_SRE; + sys_icc_sre_set(value); + + sys_icc_ctlr_set(0); + sys_icc_pmr_set(GICV3_INTR_PRIO_MASK); + + sys_icc_igrpen0_set(1); + + if (sys_icc_igrpen0_get() != 1) + { + Ft_assertNonvoid(0); + } + + sys_icc_igrpen1_set(1); + if ((sys_icc_igrpen1_get() & 1) != 1) + { + Ft_assertNonvoid(0); + } + + sys_icc_bpr_set(0); //Gicv3DistributorAddress, CpuID); + FGicv3_RdInit(Config->Gicv3RdAddress, CpuID); + FGicv3_SgiInit(Config->Gicv3SgiAddress, CpuID); + FGicv3_CpuInit(); +} + +/** + * @name: FGicV3_Stop + * @msg: 此方法用于移除当前CPU 所有的中断 并且停止GIC。 + * @return {*} + */ +void FGicV3_Stop(FGicv3_Config_t *Config, u8 CpuID) +{ + u32 RegValue = 0; + u32 LocalCpuID = ((u32)0x1 << CpuID); + u32 InterruptID = 0; + u32 DistDisable = 0; + + if (NULL == Config) + { + Ft_assertVoid(0); + } + + /* if distributor is already disable , no need to do anything */ + RegValue = Ft_in32(Config->Gicv3DistributorAddress + GICD_CTLR_OFFSET); + + if ((RegValue & GICD_CTLR_MASK) == 0U) + { + return; + } + + LocalCpuID |= (LocalCpuID << 8U); + LocalCpuID |= (LocalCpuID << 16U); + + for (InterruptID = 32U; InterruptID < GIC_INT_MAX_NUM; InterruptID += 4) + { + RegValue = Ft_in32((UINTPTR)GIC_CPUTARG(Config->Gicv3DistributorAddress, InterruptID)); + + if ((RegValue != LocalCpuID) && (RegValue != 0)) + { + /* 如果其他 */ + DistDisable = 0; + } + + /* Remove current CPU from interrupt target register */ + RegValue &= (~LocalCpuID); + Ft_out32((UINTPTR)GIC_CPUTARG(Config->Gicv3DistributorAddress, InterruptID), RegValue); + } + + /* + * If GIC distributor is safe to be disabled, disable all the interrupt + * and then disable distributor. + */ + if (DistDisable == 1) + { + for (InterruptID = 0; InterruptID < GIC_INT_MAX_NUM; InterruptID += 32U) + { + Ft_out32((UINTPTR)GIC_INTENCLR(Config->Gicv3DistributorAddress, InterruptID), 0xFFFFFFFFU); + } + Ft_out32(Config->Gicv3DistributorAddress + GICD_CTLR_OFFSET, 0U); + } +} + +/** + * @name: FGicv3_InstanceInitialize + * @msg: + * @param {u32} InstanceId 对应的gic 编号 + * @return {*} + */ +s32 FGicv3_InstanceInitialize(FGicv3_Config_t *Config) +{ + s32 CpuId = 0; + + CpuId = FCpu_IdGet(); + + Gicv3_Init(Config, CpuId); + return FST_SUCCESS; +} + +/** + * @name: FGicv3_InterruptHandler + * @msg: + * @param {void} InstanceId,选择对应的gic 控制器 + * @return {*} + */ +void FGicv3_InterruptHandler(u32 CurrentLevel, u32 InstanceId) +{ + FGicv3_Config_t *Config = NULL; + FGicv3_VectorTableEntry_t *TablePtr = NULL; + + Config = &g_FGicv3_Config_tTable[(u32)InstanceId]; + /* Read the icc_iar register to identify the hightest priority interrupt ID + and make sure it is valid. */ + // Ft_printf("is vaild InstanceId %d \r\n", CurrentLevel); + if (GIC_INT_SPURIOUS == CurrentLevel) + { + goto _exit; + } + + if (GIC_INT_MAX_NUM < CurrentLevel) + { + goto _exit; + } + + /* + * Jump into the Isr handler . + */ + TablePtr = &(Config->HanderTable[CurrentLevel]); + if (NULL != TablePtr) + { + TablePtr->Handler(TablePtr->Args); + } + + if (ARM_GICV3_MSI_START < CurrentLevel && (CurrentLevel <= ARM_GICV3_MSI_START + ARM_GICV3_MSI_CNT)) + { + // arm_gicv3_msi_intr_clear(CurrentLevel); + } +_exit: + return; +} + +/** + * @name: FGicv3_RegisterHandler + * @msg: + * @param {u32} InstanceId 选择对应的gic 控制器 + * @param {Ft_FGicv3_InterruptHandler} InterruptHandler 将会被添加进入向量表中的中断函数 + * @param {void} *Args ,参数将会被传入到 InterruptHandler 中 + * @return {*} + */ +s32 FGicv3_RegisterHandler(FGicv3_Config_t *Config, u32 InterruptID, FGicv3_InterruptHandler_t InterruptHandler, void *Args) +{ + Ft_assertNonvoid(Config != NULL); + + if (InterruptID > FT_GICV3_VECTORTABLE_NUM) + { + return FST_FAILURE; + } + + if (NULL != InterruptHandler) + { + Config->HanderTable[InterruptID].Handler = InterruptHandler; + } + + if (NULL != Args) + { + Config->HanderTable[InterruptID].Args = Args; + } + + return FST_SUCCESS; +} + +/** + * @name: GicV3_LookupConfigByBaseAddress + * @msg: + * @param {*} + * @return {*} + */ +static FGicv3_Config_t *Gicv3_LookupConfigByBaseAddress(u32 GicBaseAddress) +{ + FGicv3_Config_t *Config = NULL; + u32 instance = 0; + + for (instance = 0; instance < FT_GICV3_INSTANCES_NUM; instance++) + { + if (g_FGicv3_Config_tTable[instance].Gicv3BaseAddress == GicBaseAddress) + Config = &g_FGicv3_Config_tTable[instance]; + break; + } + + return Config; +} + +/** + * @name: FGicV3_SetPriTrigTypeByDistAddr + * @msg: + * @param {u32} GicBaseAddress + * @param {u32} InterruptID + * @param { u8} Trigger 0b00 Corresponding interrupt is level-sensitive. 0b01 Corresponding interrupt is edge-triggered. + * @param { u8} Priorty + * @return {*} + */ +s32 FGicV3_SetPriTrigTypeByDistAddr(u32 GicBaseAddress, u32 InterruptID, u8 Trigger, u8 Priorty) +{ + FGicv3_Config_t *Config = NULL; + u32 RegValue = 0; + Ft_assertNonvoid(InterruptID < FT_GICV3_VECTORTABLE_NUM); + Ft_assertNonvoid(Trigger <= GIC_TRIGGER_EDGE_SENSITIVE); + Ft_assertNonvoid(Priorty <= GICV3_MAX_INTR_PRIO_VAL); + Config = Gicv3_LookupConfigByBaseAddress(GicBaseAddress); + Ft_assertNonvoid(Config != NULL); + + if (InterruptID < SPI_START_INT_NUM) + { + /* 读出当前对应32 位 4组中断优先级配置参数 ,并设置对应的中断优先级*/ + RegValue = Ft_in32((UINTPTR)GIR_PRIO(Config->Gicv3SgiAddress, InterruptID)); + RegValue &= ~(GICD_IPRIORITYR_MASK << ((InterruptID % 4U) * 8U)); + RegValue |= (u32)Priorty << ((InterruptID % 4U) * 8U); + Ft_out32((UINTPTR)GIR_PRIO(Config->Gicv3SgiAddress, InterruptID), RegValue); + } + else + { + /* 读出当前对应32 位 4组中断优先级配置参数 ,并设置对应的中断优先级*/ + RegValue = Ft_in32((UINTPTR)GIC_PRIO(Config->Gicv3DistributorAddress, InterruptID)); + RegValue &= ~(GICD_IPRIORITYR_MASK << ((InterruptID % 4U) * 8U)); + RegValue |= (u32)Priorty << ((InterruptID % 4U) * 8U); + Ft_out32((UINTPTR)GIC_PRIO(Config->Gicv3DistributorAddress, InterruptID), RegValue); + + /* 读取出32位 16 组 中断触发源配置,并且进行设置*/ + RegValue = Ft_in32((UINTPTR)GIC_CONFIG(Config->Gicv3DistributorAddress, InterruptID)); + RegValue &= ~(GICD_ICFGR_MASK << ((InterruptID % 16U) * 2U)); + RegValue |= (u32)Trigger << ((InterruptID % 16U) * 2U); + Ft_out32((UINTPTR)GIC_CONFIG(Config->Gicv3DistributorAddress, InterruptID), RegValue); + } + return FST_SUCCESS; +} + +/** + * @name: FGicV3_GetPriTrigTypeByDistAddr + * @msg: + * @param {u32} GicBaseAddress + * @param {u32} InterruptID + * @param { u8} Trigger + * @param { u8} Priorty + * @return {*} + */ +void FGicV3_GetPriTrigTypeByDistAddr(u32 GicBaseAddress, u32 InterruptID, u8 *Trigger, u8 *Priorty) +{ + u32 RegValue = 0; + Ft_assertVoid(InterruptID < FT_GICV3_VECTORTABLE_NUM); + Ft_assertVoid(*Trigger <= GIC_TRIGGER_EDGE_SENSITIVE); + Ft_assertVoid(*Priorty <= GICV3_MAX_INTR_PRIO_VAL); + + /* + * 获取中断优先级 + */ + RegValue = Ft_in32((UINTPTR)GIC_PRIO(GicBaseAddress, InterruptID)); + RegValue = RegValue >> ((InterruptID % 4U) * 8U); + *Priorty = (u8)(RegValue & GICD_IPRIORITYR_MASK); + + /* + * 获取当前中断触发信息 + */ + RegValue = Ft_in32((UINTPTR)GIC_CONFIG(GicBaseAddress, InterruptID)); + RegValue = RegValue >> ((InterruptID % 16U) * 2U); + *Trigger = (u8)RegValue & GICD_ICFGR_MASK; +} + +/** + * @name: FGicV3_InterruptUnmapByDistAddr + * @msg: 清除寄存器中的CPU中的 target PEs + * @param {u32} GicBaseAddress + * @param {u32} InterruptID + * @param { u8} cpu + * @return {*} + */ +void FGicV3_InterruptUnmapByDistAddr(u32 GicBaseAddress, u32 InterruptID, u8 CpuID) +{ + u32 RegValue = 0; + Ft_assertVoid(InterruptID < GIC_INT_MAX_NUM); + RegValue = Ft_in32((UINTPTR)GIC_CPUTARG(GicBaseAddress, InterruptID)); + RegValue &= ~(1U << (((InterruptID % 4) * 8U) + CpuID)); + Ft_out32((UINTPTR)GIC_CPUTARG(GicBaseAddress, InterruptID), RegValue); +} + +/** + * @name: + * @msg: + * @param {Ft_Gicv3_Config} *Config + * @param {u32} InterruptID + * @return {*} + */ +void FGicV3_DisableInterrupt(FGicv3_Config_t *Config, u32 InterruptID) +{ + u32 RegValue; + s32 CpuId = 0; + Ft_assertVoid(InterruptID < GIC_INT_MAX_NUM); + + // RegValue = 0x1U << (InterruptID % 32U); + + if (InterruptID < SPI_START_INT_NUM) + { + CpuId = FCpu_IdGet(); + RegValue = Ft_in32(GICR_INTENCLR_CPU(Config->Gicv3SgiAddress, CpuId)); + RegValue |= (0x1U << (InterruptID % 32U)); + Ft_out32(GICR_INTENCLR_CPU(Config->Gicv3SgiAddress, CpuId), RegValue); + } + else + { + RegValue = Ft_in32((UINTPTR)GIC_INTENCLR(Config->Gicv3SgiAddress, InterruptID)); + RegValue |= (0x1U << (InterruptID % 32U)); + Ft_out32((UINTPTR)GIC_INTENCLR(Config->Gicv3SgiAddress, InterruptID), RegValue); + } +} + +/** + * @name: FGicV3_EnableInterrupt + * @msg: + * @param {u32} GicBaseAddress + * @param {u32} InterruptID + * @return {*} + */ +void FGicV3_EnableInterrupt(FGicv3_Config_t *Config, u32 InterruptID) +{ + u32 RegValue; + s32 CpuId = 0; + Ft_assertVoid(InterruptID < GIC_INT_MAX_NUM); + + if (InterruptID < SPI_START_INT_NUM) + { + CpuId = FCpu_IdGet(); + // Ft_printf("cpuid is %x \r\n", CpuId); + // Ft_printf("before GICR_ISENABLER0_OFFSET %x \r\n", Ft_in32(GICR_INTENABLE_CPU(Config->Gicv3SgiAddress, CpuId))); + RegValue = Ft_in32(GICR_INTENABLE_CPU(Config->Gicv3SgiAddress, CpuId)); + RegValue |= (0x1U << (InterruptID % 32U)); + Ft_out32(GICR_INTENABLE_CPU(Config->Gicv3SgiAddress, CpuId), RegValue); + // Ft_printf("GICR_ISENABLER0_OFFSET %x \r\n", Ft_in32(GICR_INTENABLE_CPU(Config->Gicv3SgiAddress, CpuId))); + } + else + { + RegValue = Ft_in32((UINTPTR)GICD_ISENABLER(Config->Gicv3DistributorAddress, InterruptID)); + RegValue |= (0x1U << (InterruptID % 32U)); + Ft_out32((UINTPTR)GICD_ISENABLER(Config->Gicv3DistributorAddress, InterruptID), RegValue); + } +} + +/** + * @name: FGicv3_Ack + * @msg: Writes to this register to inform the CPU interface that it has completed the processing of the + specified Group 1 interrupt. + * @in param {u32} InterruptID + * @in param {s32} SrcCpu + * @return {*} + */ +ft_error_t FGicv3_Ack(u32 InterruptID, s32 CpuId) +{ + sys_icc_eoir1_set(InterruptID); + return FST_SUCCESS; +} diff --git a/bsp/ft2004/libraries/bsp/ft_gicv3/ft_gicv3_hw.h b/bsp/ft2004/libraries/bsp/ft_gicv3/ft_gicv3_hw.h new file mode 100644 index 0000000000000000000000000000000000000000..f9c9f06acf4abfbcf1aa19a70e030698e6c8bdef --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gicv3/ft_gicv3_hw.h @@ -0,0 +1,248 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-26 10:49:20 + * @Description:  This files is for gic v2.0 register implementation + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef GICV3_HW_H +#define GICV3_HW_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ft_parameters.h" +#include "ft_gicv3.h" + /* interrupt priority */ + +#define SHIFT_PER_WORD 5 +#define BITS_PER_WORD 32 +#define CONFIGS_PER_WORD 16 +#define PRIOS_PER_WORD 4 +#define TARGETS_PER_WORD 4 +#define NWORD(bitnum) (bitnum / 32) +#define BIT(bitnum) (1 << (bitnum % BITS_PER_WORD)) + +#define GIC_PRIO(gic_dist_addr, Periph) ((volatile u32 *)(gic_dist_addr + GICD_IPRIORITYR_OFFSET + \ + (0x4 * (Periph / PRIOS_PER_WORD)))) + +#define GIR_PRIO(gic_redist_addr, Periph) ((volatile u32 *)(gic_redist_addr + GICR_IPRIORITYR_OFFSET + \ + (0x4 * (Periph / PRIOS_PER_WORD)))) + + /* clear interrupt enable */ + +#define GIC_INTENCLR(gic_dist_addr, Periph) ((volatile u32 *)(gic_dist_addr + GICD_ICENABLE_OFFSET + \ + (0x4 * NWORD(Periph)))) + + /* set interrupt enable */ +#define GICD_ISENABLER(gic_dist_addr, Periph) ((volatile u32 *)(gic_dist_addr + GICD_ISENABLER_OFFSET + \ + (0x4 * NWORD(Periph)))) + + /* clear pending interrupt */ + +#define GIC_INTPENDCLR(gic_dist_addr, Periph) ((volatile u32 *)(gic_dist_addr + GICD_ICPENDR_OFFSET + \ + (0x4 * NWORD(Periph)))) + + /* CPU target */ + +#define GIC_CPUTARG(gic_dist_addr, Periph) ((volatile u32 *)(gic_dist_addr + GICD_ITARGETSR_OFFSET + \ + (0x4 * (Periph / TARGETS_PER_WORD)))) + + /* Interrupt Routing */ + +#define GIC_INTRPUTE_LOW(gic_dist_addr, Periph) ((volatile u32 *)(gic_dist_addr + GICD_IROUTER_E_OFFSET + \ + (0x8 * (Periph)))) + +#define GIC_INTRPUTE_HIGH(gic_dist_addr, Periph) ((volatile u32 *)(gic_dist_addr + GICD_IROUTER_E_OFFSET + \ + (0x8 * (Periph)) + 4)) /* interrupt configuration */ + +#define GIC_CONFIG(gic_dist_addr, Periph) ((volatile u32 *)(gic_dist_addr + GICD_ICFGR_OFFSET + \ + (0x4 * (Periph / CONFIGS_PER_WORD)))) + +#define GIC_TRIGGER_LEVEL_SENSITIVE 0 +#define GIC_TRIGGER_EDGE_SENSITIVE 1 + + /* ARM GIC interrupt distributor and CPU interface register access macros */ + +#define GIC_CPU_DIR_DEFAULT 0x01010101 /* all interrupts are directed to CPU0 */ +#define GIC_V3_CPU_DIR_DEFAULT_LOW 0x0llu /* all interrupts are directed to CPU0 */ +#define GIC_V3_CPU_DIR_DEFAULT_HIGH 0 +#define GIC_CONTROL_ENABLE 0x01 + +#define GIC_INT_ALL_ENABLED 0xFF /* priority 0-0xFF can run */ +#define GIC_INT_ALL_DISABLED 0x00 /* nothing higher than 0 hence disabled */ +#define GIC_INT_SPURIOUS 0x3FF /* no interrupt currently */ +#define GIC_INT_ONEMINUS_HIGH 0x55555555 /* interrupt config to 1-N, High */ +#define GIC_CPU_BINP_DEFAULT 0x07 /* split all priority to subpriority */ +#define GIC_CPU_BINP_PREEMPT_VAL 0x1 /* split all priority to group-priority */ +#define GIC_CPU_BINP_NONPREEMPT_VAL 0x07 /* split all priority to sub-priority */ +#define GIC_CPU_CONTROL_ENABLE 0x1 /* enable the processor interface */ +#define GIC_CPU_ALL_ENABLED 0xFF /* priority 0-E can run */ +#define GIC_CPU_ALL_DISABLED 0x00 /* nothing higher than 0 */ +#define GIC_SGI_SRC_CPU_ID_MASK 0x1C00 +#define GIC_INT_HIGHEST_PRIORITY 0x0 /* the highest priority for interrupts */ +#define GIC_INT_LOWEST_PRIORITY 0x1F /* the lowest priority for interrupts */ +#define GIC_INT_PRIORITY_SHIFT 0x8 +#define GIC_INT_PRIORITY_MASK 0xFF + +#define GIC_INT_TRIGGER_SHIFT 0x2 + /************ Distributor register map ****************/ + +#define GICD_CTLR_OFFSET 0x00000000U /* Distributor Control Register */ +#define GICD_TYPER_OFFSET 0x00000004U /* Interrupt Controller Type Register */ +#define GICD_IIDR_OFFSET 0x00000008U /* Distributor Implementer Identification Register */ +#define GICD_TYPER2_OFFSET 0x0000000CU /* Interrupt controller Type Register 2 */ +#define GICD_STATUSR_OFFSET 0x00000010U /* Error Reporting Status Register, optional */ +#define GICD_SETSPI_NSR_OFFSET 0x00000040U /* Set SPI Register */ +#define GICD_CLRSPI_NSR_OFFSET 0x00000048U /* Clear SPI Register */ +#define GICD_SETSPI_SR_OFFSET 0x00000050U /* Set SPI, Secure Register */ +#define GICD_CLRSPI_SR_OFFSET 0x00000058U /* Clear SPI, Secure Register */ +#define GICD_IGROUPR_OFFSET 0x00000080U /* Interrupt Group Registers */ +#define GICD_ISENABLER_OFFSET 0x00000100U /* Interrupt Set-Enable Registers */ +#define GICD_ICENABLE_OFFSET 0x00000180U /* Interrupt Clear-Enable Registers */ +#define GICD_ISPENDR_OFFSET 0x00000200U /* Interrupt Set-Pending Registers */ +#define GICD_ICPENDR_OFFSET 0x00000280U /* Interrupt Clear-Pending Registers */ +#define GICD_ISACTIVER_OFFSET 0x00000300U /* Interrupt Set-Active Registers */ +#define GICD_ICACTIVER_OFFSET 0x00000380U /* Interrupt Clear-Active Registers */ +#define GICD_IPRIORITYR_OFFSET 0x00000400U /* Interrupt Priority Registers */ +#define GICD_ITARGETSR_OFFSET 0x00000800U /* Interrupt Processor Targets Registers */ +#define GICD_ICFGR_OFFSET 0x00000C00U /* Interrupt Configuration Registers */ +#define GICD_IGRPMODR_OFFSET 0x00000D00U /* Interrupt Group Modifier Registers */ +#define GICD_NSACR_OFFSET 0x000000E00U /* Non-secure Access Control Registers */ +#define GICD_SGIR_OFFSET 0x000000F00U /* Software Generated Interrupt Register */ +#define GICD_CPENDSGIR_OFFSET 0x000000F10U /* SGI Clear-Pending Registers */ +#define GICD_SPENDSGIR_OFFSET 0x000000F20U /* SGI Set-Pending Registers */ +#define GICD_IGROUPR_E_OFFSET 0x000001000U /* Interrupt Group Registers for extended SPI range */ +#define GICD_ISENABLER_E_OFFSET 0x000001200U /* Interrupt Set-Enable for extended SPI range */ +#define GICD_ICENABLER_E_OFFSET 0x000001400U /* Interrupt Clear-Enable for extended SPI range */ +#define GICD_ISPENDR_E_OFFSET 0x000001600U /* Interrupt Set-Pend for extended SPI range */ +#define GICD_ICPENDR_E_OFFSET 0x000001800U /* Interrupt Clear-Pend for extended SPI range */ +#define GICD_ISACTIVER_E_OFFSET 0x000001A00U /* Interrupt Set-Active for extended SPI range */ +#define GICD_ICACTIVER_E_OFFSET 0x000001C00U /* Interrupt Clear-Active for extended SPI range */ +#define GICD_IPRIORITYR_E_OFFSET 0x000002000U /* Interrupt Priority for extended SPI range */ +#define GICD_ICFGR_E_OFFSET 0x000003000U /* Extended SPI Configuration Register */ +#define GICD_IGRPMODR_E_OFFSET 0x000003400U /* Interrupt Group Modifier for extended SPI range */ +#define GICD_NSACR_E_OFFSET 0x000003600U /* Non-secure Access Control Registers for extended SPI range */ +#define GICD_IROUTER_E_OFFSET 0x000006000U /* Interrupt Routing Registers */ +#define GICD_IROUTER_E_E_OFFSET 0x000008000U /* Interrupt Routing Registers for extended SPI range */ + + /************ physical LPI Redistributor register map ****************/ + +#define GICR_CTLR_OFFSET 0x0000 /*See the register description Redistributor Control Register*/ +#define GICR_IIDR_OFFSET 0x0004 /*IMPLEMENTATION DEFINED Implementer Identification Register*/ +#define GICR_TYPER_OFFSET 0x0008 /*IMPLEMENTATION DEFINED Redistributor Type Register*/ +#define GICR_STATUSR_OFFSET 0x0010 /*0x0000 0000 Error Reporting Status Register, optional*/ +#define GICR_WAKER_OFFSET 0x0014 /*See the register description Redistributor Wake Register*/ +#define GICR_MPAMIDR_OFFSET 0x0018 /*- Report maximum PARTID and PMG Register*/ +#define GICR_PARTIDR_OFFSET 0x001C /*0 Set PARTID and PMG Register*/ +#define GICR_SETLPIRa_OFFSET 0x0040 /*- Set LPI Pending Register*/ +#define GICR_CLRLPIRa_OFFSET 0x0048 /*- Clear LPI Pending Register*/ +#define GICR_PROPBASER_OFFSET 0x0070 /*- Redistributor Properties Base Address Register*/ +#define GICR_PENDBASER_OFFSET 0x0078 /*- Redistributor LPI Pending Table Base Address*/ +#define GICR_INVLPIRA_OFFSET 0x00A0 /*Redistributor Invalidate LPI Register*/ +#define GICR_INVALLRA_OFFSET 0x00B0 /*Redistributor Invalidate All Register */ +#define GICR_SYNCRA_OFFSET 0x00C0 /*Redistributor Synchronize Register*/ + +#define GICR_WAKER_CPU(gicr_addr, cpu) ((gicr_addr + cpu * (2 << 16) + GICR_WAKER_OFFSET)) + +/******************* SGI and PPI Redistributor register map ************************/ +#define GICR_IGROUPR0_OFFSET 0x0080 /* Interrupt Group Register 0*/ +#define GICR_ISENABLER0_OFFSET 0x0100 /* DEFINED Interrupt Set-Enable Register 0*/ +#define GICR_ICENABLER0_OFFSET 0x0180 /* DEFINED Interrupt Clear-Enable Register 0*/ +#define GICR_ISPENDR0_OFFSET 0x0200 /* Interrupt Set-Pend Register 0*/ +#define GICR_ICPENDR0_OFFSET 0x0280 /* Interrupt Clear-Pend Register 0*/ +#define GICR_ISACTIVER0_OFFSET 0x0300 /* Interrupt Set-Active Register 0*/ +#define GICR_ICACTIVER0_OFFSET 0x0380 /* Interrupt Clear-Active Register 0*/ +#define GICR_IPRIORITYR_OFFSET 0x0400 /* Interrupt Priority Registers*/ +#define GICR_IGROUPR_E_OFFSET 0x0084 /*Interrupt Group Registers for extended PPI range*/ +#define GICR_ISENABLER_E_OFFSET 0x0104 /* Interrupt Set-Enable for extended PPI range*/ +#define GICR_ICENABLER_E_OFFSET 0x0184 /* Interrupt Clear-Enable for extended PPI range*/ +#define GICR_ISPENDR_E_OFFSET 0x0204 /* Interrupt Set-Pend for extended PPI range*/ +#define GICR_ICPENDR_E_OFFSET 0x0284 /* Interrupt Clear-Pend for extended PPI range*/ +#define GICR_ISACTIVER_E_OFFSET 0x0304 /* Interrupt Set-Active for extended PPI range*/ +#define GICR_ICACTIVER_E_OFFSET 0x0384 /* Interrput Clear-Active for extended PPI range*/ +#define GICR_IPRIORITYR_E_OFFSET 0x0420 /* Interrupt Priority for extended PPI range*/ +#define GICR_ICFGR_E_OFFSET 0x0C08 /* Extended PPI Configuration Register */ +#define GICR_IGRPMODR_E_OFFSET 0x0D04 /* Interrupt Group Modifier for extended PPI range */ +#define GICR_ICFGR0_OFFSET 0x0C00 /*SGI Configuration Register*/ +#define GICR_ICFGR1_OFFSET 0x0C04 /*PPI Configuration Register*/ +#define GICR_IGRPMODR0_OFFSET 0x0D00 /*Interrupt Group Modifier Register 0*/ +#define GICR_NSACR_OFFSET 0x0E00 /* Secure Access Control Register*/ + +#define GICR_INTENABLE_CPU(gic_dist_addr, cpu) ((gic_dist_addr + cpu * (2 << 16) + GICR_ISENABLER0_OFFSET)) +#define GICR_INTENCLR_CPU(gic_dist_addr, cpu) ((gic_dist_addr + cpu * (2 << 16) + GICR_ICENABLER0_OFFSET)) + +/****************** CPU interface register map *************************/ +#ifdef CPU_GICC_SUPPORT + +#define GICC_CTLR_OFFSET 0x0000 /*See the register description CPU Interface Control Register*/ +#define GICC_PMR_OFFSET 0x0004 /* Interrupt Priority Mask Register*/ +#define GICC_BPR_OFFSET 0x0008 /* Binary Point Register*/ +#define GICC_IAR_OFFSET 0x000C /* Interrupt Acknowledge Register*/ +#define GICC_EOIR_OFFSET 0x0010 /* End of Interrupt Register*/ +#define GICC_RPR_OFFSET 0x0014 /* Running Priority Register*/ +#define GICC_HPPIR_OFFSET 0x0018 /* Highest Priority Pending Interrupt Register*/ +#define GICC_ABPR_OFFSET 0x001C /* Aliased Binary Point Register*/ +#define GICC_AIAR_OFFSET 0x0020 /* Aliased Interrupt Acknowledge Register*/ +#define GICC_AEOIR_OFFSET 0x0024 /* Aliased End of Interrupt Register*/ +#define GICC_AHPPIR_OFFSET 0x0028 /* Aliased Highest Priority Pending Interrupt Register*/ +#define GICC_STATUSR_OFFSET 0x002C /* Error Reporting Status Register, optional*/ +#define GICC_APR_OFFSET 0x00D0 /* Active Priorities Registers*/ +#define GICC_NSAPR_OFFSET 0x00E0 /* Non-secure Active Priorities Registers*/ +#define GICC_IIDR_OFFSET 0x00FC /* CPU Interface Identification Register */ +#define GICC_DIR_OFFSET 0x1000 /* Deactivate Interrupt Register */ + +#endif + + /** Redistributor Wake Register **/ + +#define GICC_WAKER_PROCESSORSLEEP_IN (1U << 1) +#define GICC_WAKER_PROCESSORSLEEP_NOT_IN (0U << 1) + +#define GICC_WAKER_CHILDRENASLEEP_ACTIVE (0U << 2) +#define GICC_WAKER_CHILDRENASLEEP_QUIESCENT (1U << 2) + + /** GICR_ISENABLER0 **/ + +#define ALL_PPI_INT_MASK 0xFFFF0000 /* bit field for all PPI interrupts */ +#define ALL_SGI_INT_MASK 0x0000FFFF /* bit field for all SGI interrupts */ + + /** ICC_SRE **/ + +#define ICC_SRE_SRE (1U << 0) + +/** GICD_IPRIORITYR **/ +#define GICD_IPRIORITYR_MASK 0xffU + +/** GICD_ICFGR **/ +#define GICD_ICFGR_MASK 0x03 + + /** GICD_CTLR **/ + +#define GICD_CTLR_MASK 1 + + /**************************** Function Prototypes ****************************************/ + s32 FGicv3_InstanceInitialize(FGicv3_Config_t *Config); + void FGicv3_InterruptHandler(u32 CurrentLevel, u32 InstanceId); + s32 FGicv3_RegisterHandler(FGicv3_Config_t *Config, u32 InterruptID, FGicv3_InterruptHandler_t InterruptHandler, void *Args); + s32 FGicV3_SetPriTrigTypeByDistAddr(u32 GicBaseAddress, u32 InterruptID, u8 Trigger, u8 Priorty); + void FGicV3_GetPriTrigTypeByDistAddr(u32 GicBaseAddress, u32 InterruptID, u8 *Trigger, u8 *Priorty); + void FGicV3_InterruptUnmapByDistAddr(u32 GicBaseAddress, u32 InterruptID, u8 CpuID); + void FGicV3_DisableInterrupt(FGicv3_Config_t *Config, u32 InterruptID); + void FGicV3_EnableInterrupt(FGicv3_Config_t *Config, u32 InterruptID); + void FGicV3_Stop(FGicv3_Config_t *Config, u8 CpuID); + +#ifdef __cplusplus +} +#endif + +#endif // \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/ft_gicv3/ft_gicv3_sinit.c b/bsp/ft2004/libraries/bsp/ft_gicv3/ft_gicv3_sinit.c new file mode 100644 index 0000000000000000000000000000000000000000..c8ee7015ff4a27ff7293233de6fd530834a208fb --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gicv3/ft_gicv3_sinit.c @@ -0,0 +1,47 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-07 16:28:25 + * @Description:  This files is for gic v2.0 static init + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_types.h" +#include "ft_assert.h" +#include "ft_parameters.h" +#include "ft_gicv3.h" + +/************************** Variable Definitions *****************************/ +extern FGicv3_Config_t g_FGicv3_Config_tTable[FT_GICV3_INSTANCES_NUM]; + +/** + * @name: Ft_Gicv3_lookupConfig + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + * @param {u32} InstanceId + */ +FGicv3_Config_t *FGicv3_LookupConfig(u32 InstanceId) +{ + FGicv3_Config_t *Config = NULL; + u32 Index = 0; + + for (Index = 0; Index < FT_GICV3_INSTANCES_NUM; Index++) + { + if (g_FGicv3_Config_tTable[Index].InstanceId == InstanceId) + { + Config = &g_FGicv3_Config_tTable[Index]; + break; + } + } + + return Config; +} diff --git a/bsp/ft2004/libraries/bsp/ft_gicv3/ft_gicv3_test.c b/bsp/ft2004/libraries/bsp/ft_gicv3/ft_gicv3_test.c new file mode 100644 index 0000000000000000000000000000000000000000..8b5a90e50eaebe35e867179aaf1000d0cc3215a8 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gicv3/ft_gicv3_test.c @@ -0,0 +1,13 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-07 13:35:03 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ diff --git a/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac.c b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac.c new file mode 100644 index 0000000000000000000000000000000000000000..fae9e4b7e1df8293c519414cf8b4be994cb5e3ac --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac.c @@ -0,0 +1,171 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-07 13:23:19 + * @Description:  This files is for gmac ctrl + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_gmac.h" +#include "ft_gmac_hw.h" +#include "ft_assert.h" +#include "ft_io.h" +#include "ft_status.h" +#include "ft_printf.h" +#include "ft_parameters.h" + +static void Ft_Gmac_StubHandler(void *args) +{ + Ft_assertVoidAlways(); +} + +static void Ft_Gmac_StubErrorHandler(void *CallBackRef, u32 ErrorWord) +{ + // Ft_assertVoidAlways(); +} + +s32 Ft_Gmac_HwInitialize(Ft_Gmac_t *Gmac) +{ + Ft_assertNonvoid(Gmac != NULL); + Ft_assertNonvoid(Gmac->IsReady == FT_COMPONENT_IS_READLY); + return FGmac_InitializeHw(&Gmac->Config); +} + +/** + * @name: Ft_GmacCfgInitialize + * @msg: + * @param {Ft_Gmac_t} *Gmac + * @param {FGmac_Config_t} *Config + * @return {*} + */ +s32 Ft_GmacCfgInitialize(Ft_Gmac_t *Gmac, FGmac_Config_t *Config) +{ + Ft_assertNonvoid(Gmac != NULL); + Ft_assertNonvoid(Config != NULL); + + Gmac->Config = *Config; + Gmac->IsReady = FT_COMPONENT_IS_READLY; + + FGmac_SetHandler(Gmac, FT_GMAC_TX_COMPLETE_CB_ID, Ft_Gmac_StubHandler, Gmac); + FGmac_SetHandler(Gmac, FT_GMAC_RX_COMPLETE_CB_ID, Ft_Gmac_StubHandler, Gmac); + FGmac_SetHandler(Gmac, FT_GMAC_DMA_ERROR_CB_ID, Ft_Gmac_StubErrorHandler, Gmac); + + return FST_SUCCESS; +} + +/** + * @name: Ft_Gmac_Start + * @msg: Enable GMAC MAC and DMA rx/tx + * @param {Ft_Gmac_t} *Gmac + * @return {*} + */ +s32 Ft_Gmac_Start(Ft_Gmac_t *Gmac) +{ + FGmac_Config_t *Config = NULL; + Ft_assertNonvoid(Gmac != NULL); + Ft_assertNonvoid(Gmac->IsReady == FT_COMPONENT_IS_READLY); + Config = &Gmac->Config; + + FGmac_DMAReceptionTransmissionEnable(Config); + FGmac_ReceptionTransmissionEnable(Config); + + /* Clear Tx and Rx process stopped flags */ + Ft_out32(Gmac->Config.BaseAddress + DMA_INTR_ENA_OFFSET, DMA_INTR_ENA_RIE | DMA_INTR_ENA_AIE | DMA_INTR_ENA_NIE); + + return FST_SUCCESS; +} + +/** + * @name: Ft_Gmac_Stop + * @msg: + * @param {Ft_Gmac_t} *Gmac + * @return {*} + */ +s32 Ft_Gmac_Stop(Ft_Gmac_t *Gmac) +{ + FGmac_Config_t *Config = NULL; + Ft_assertNonvoid(Gmac != NULL); + Ft_assertNonvoid(Gmac->IsReady == FT_COMPONENT_IS_READLY); + Config = &Gmac->Config; + + FGmac_TransmissionDisable(Config); + FGmac_ReceptionDisable(Config); + FGmac_DMATransmissionDisable(Config); + FGmac_DMAReceptionDisable(Config); + return FST_SUCCESS; +} + +void Ft_Gmac_Phy_Debug(Ft_Gmac_t *Gmac) +{ + // FGmac_Config_t *Config; + // Config = &Gmac->Config; + // Gmac_WritePHYRegister(Config, PHY_DEBUG_ADDR_OFFSET, 0x12); + // FGmac_ReadPHYRegister(Config, PHY_DEBUG_DATA_OFFSET, &RegValue); + + // Ft_printf("PHY_DEBUG_OFFSET 0x12 %x \r\n", RegValue); + // Ft_assertVoid(Gmac_WritePHYRegister(Config, PHY_DEBUG_ADDR_OFFSET, 0x10) == FST_SUCCESS); + // Ft_assertVoid(FGmac_ReadPHYRegister(Config, 0x1f, &RegValue) == FST_SUCCESS); + // Ft_printf("chip check 0x1f %x \r\n", RegValue); + // Ft_printf("chip check GMAC_CONTROL_OFFSET %x \r\n", Ft_in32(Config->BaseAddress + GMAC_CONTROL_OFFSET)); + + // Ft_printf("MAC 配置寄存器 %x \r\n", Ft_in32(Config->BaseAddress + GMAC_CONTROL_OFFSET)); + // Ft_printf("中断状态寄存器 %x \r\n", Ft_in32(Config->BaseAddress + GMAC_ISR_STATUS_OFFSET)); + // Ft_printf("中断屏蔽寄存器 %x \r\n", Ft_in32(Config->BaseAddress + GMAC_ISR_MASK_OFFSET)); + // Ft_printf("寄存器 54 %x \r\n", Ft_in32(Config->BaseAddress + GMAC_MAC_MAC_PHY_STATUS)); + + // Ft_printf("DMA 总线模式寄存器 %x \r\n", Ft_in32(Config->BaseAddress + DMA_BUS_MODE_OFFSET)); + // Ft_printf("DMA 状态寄存器 %x \r\n", Ft_in32(Config->BaseAddress + DMA_STATUS_OFFSET)); + // Ft_printf("DMA 操作模式寄存器 %x \r\n", Ft_in32(Config->BaseAddress + DMA_OP_OFFSET)); + // Ft_printf("DMA 中断使能寄存器 %x \r\n", Ft_in32(Config->BaseAddress + DMA_INTR_ENA_OFFSET)); + // Ft_printf("DMA 中断遮蔽寄存器 %x \r\n", Ft_in32(Config->BaseAddress + DMA_MISSED_FRAME_CTR_OFFSET)); + // Ft_printf("DMA AXI 总线模式寄存器 %x \r\n", Ft_in32(Config->BaseAddress + DMA_AXI_BUS_MOD_OFFSET)); + // Ft_printf("DMA AXI 状态寄存器 %x \r\n", Ft_in32(Config->BaseAddress + DMA_AXI_BUS_STATUS_OFFSET)); + // Ft_printf("接收描述符列表地址寄存器 %x \r\n", Ft_in32(Config->BaseAddress + DMA_RCV_BASE_ADDR_OFFSET)); + // Ft_printf("发送描述符列表地址寄存器 %x \r\n", Ft_in32(Config->BaseAddress + DMA_TX_BASE_ADDR_OFFSET)); + + // Ft_printf("当前主机接收描述符寄存器 %x \r\n", Ft_in32(Config->BaseAddress + 0x104c)); + // Ft_printf("当前接收缓冲区地址 %x \r\n", Ft_in32(Config->BaseAddress + 0x1054)); + + // Ft_printf("当前主机发送描述符寄存器 %x \r\n", Ft_in32(Config->BaseAddress + 0x1048)); + // Ft_printf("当前发送缓冲区地址 %x \r\n", Ft_in32(Config->BaseAddress + 0x1050)); + + // Ft_printf("接收描述符列表地址寄存器 %x \r\n", Ft_in32(Config->BaseAddress + DMA_RCV_BASE_ADDR_OFFSET)); + // Ft_printf("发送描述符列表地址寄存器 %x \r\n", Ft_in32(Config->BaseAddress + DMA_TX_BASE_ADDR_OFFSET)); + + Ft_printf("\r\n ****************************** \r\n"); +} + +/** + * @name: Ft_Gmac_UseDefaultMacAddr + * @msg: set default mac address + * @in param: + * @inout param: + * @out param: + * @return {*} + * @param {Ft_Gmac_t} *Gmac + * @param {u8} *MacAddr + */ +void Ft_Gmac_UseDefaultMacAddr(Ft_Gmac_t *Gmac, u8 *MacAddr) +{ + u32 MacAddrLo; + u32 MacAddrHi; + FGmac_Config_t *pConfig; + Ft_assertNoneReturn(Gmac != NULL); + pConfig = &Gmac->Config; + + MacAddrLo = Ft_in32(pConfig->BaseAddress + GMAC_MAC_ADDR0_LOWER16BIT_OFFSET); + MacAddrHi = Ft_in32(pConfig->BaseAddress + GMAC_MAC_ADDR0_UPPER16BIT_OFFSET); + + MacAddr[0] = MacAddrLo & 0xFF; + MacAddr[1] = (MacAddrLo >> 8) & 0xFF; + MacAddr[2] = (MacAddrLo >> 16) & 0xFF; + MacAddr[3] = (MacAddrLo >> 24) & 0xFF; + MacAddr[4] = MacAddrHi & 0xFF; + MacAddr[5] = (MacAddrHi >> 8) & 0xFF; +} diff --git a/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac.h b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac.h new file mode 100644 index 0000000000000000000000000000000000000000..f149d3603bb7727a29f8d309dd51a961fe938416 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac.h @@ -0,0 +1,319 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-05-18 18:10:36 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + * 1.00a hh 2021-02-05 First release + */ + +#ifndef FT_GMAC_H +#define FT_GMAC_H + +#include "ft_types.h" +#define GMAC_INC_DESC(x, y) (x) = (((x) + 1) % y) +/** + * @name: Callback invoked when frame(s) have been sent or received in interrupt + * driven DMA mode .to set the send callback ,invoke FGmac_SetHandler() + * @msg: + * @param {void} *CallBackRef + * @return {*} + */ +typedef void (*FGmac_IntrCallback_t)(void *CallBackRef); + +/** + * @name: FGmac_ErrIntrCallback_t + * @msg: Callback whem asynchronous error occurs. To set this callback, invoke + * FGmac_ErrIntrCallback_t . + * @param {void} *CallBackRef + * @param {u32} ErrorWord definition varies with Error + * @return {*} + */ +typedef void (*FGmac_ErrIntrCallback_t)(void *CallBackRef, u32 ErrorWord); + +/** + * + * + */ +typedef void (*Ft_Gmac_MacPhyStatus_Callback)(void *CallBackRef, u32 MacPhyStatus); + +/** GMAC_SPEED */ +#define GMAC_SPEED_10M 0x00000001U +#define GMAC_SPEED_100M 0x00000002U +#define GMAC_SPEED_1000M 0x00000004U + +#define IS_RIGHT_SPEED() + +/* GMAC_AutoNegotiation */ +#define GMAC_AUTONEGOTIATION_ENABLE 0x00000001U +#define GMAC_AUTONEGOTIATION_DISABLE 0x00000000U + +/* GMAC_Duplex_Mode */ +#define GMAC_MODE_FULLDUPLEX 0x00000001U +#define GMAC_MODE_HALFDUPLEX 0x00000000U + +/* GMAC_Rx_Mode */ +#define GMAC_RXPOLLING_MODE 0x00000000U +#define GMAC_RXINTERRUPT_MODE 0x00000001U + +/* GMAC_Checksum_Mode */ +#define GMAC_CHECKSUM_BY_SOFTWARE 0x00000000U +#define GMAC_CHECKSUM_BY_HARDWARE 0x00000001U + +/* GMAC_Media_Interface */ +#define GMAC_MEDIA_INTERFACE_RGMII 0x00000000U +#define GMAC_MEDIA_INTERFACE_MII 0x00000001U + +/* Gmac Error value */ + +#define GMAC_ERROR_TRANSMIT_PROCESS_STOPPED 0x00000001U +#define GMAC_ERROR_TRANSMIT_UNAVAILABLE_STATUS 0x00000002U +#define GMAC_ERROR_TRANSMIT_JABBER_TIMEOUT 0x00000004U +#define GMAC_ERROR_RECEIVE_FIFO_OVERFLOW 0x00000008U +#define GMAC_ERROR_TRANSMIT_UNDERFLOW 0x00000010U +#define GMAC_ERROR_RECEIVE_BUFFER_UNAVAILABLE 0x00000020U +#define GMAC_ERROR_RECEIVE_PROCESS_STOPPED 0x00000040U +#define GMAC_ERROR_RECEIVE_WATCHDOG_TIMEOUT 0x00000080U +#define GMAC_ERROR_EARLY_TRANSMIT_INTERRUPT 0x000000100U +#define GMAC_ERROR_FATAL_BUS_ERROR 0x000000200U +#define GMAC_ERROR_UNDEFINED 0x000000400U + +typedef enum +{ + FT_GMAC_TX_COMPLETE_CB_ID = 0x01U, /*!< Gmac Tx Complete Callback ID */ + FT_GMAC_RX_COMPLETE_CB_ID = 0x02U, /*!< Gmac Rx Complete Callback ID */ + FT_GMAC_DMA_ERROR_CB_ID = 0x03U, /*!< Gmac DMA Error Callback ID */ + FT_GMAC_MAC_PHY_STATUS_CB_ID = 0x04U, /*!< */ +} FGmac_IsrCallbackSelect_t; + +/* Gmac DMA Descriptors data structure definition */ + +typedef struct +{ + volatile u32 Status; /*!< Status */ + u32 Control; /*!< Control and Buffer1, Buffer2 lengths */ + u32 Buffer1Addr; /*!< Buffer1 address pointer */ + u32 Buffer2NextDescAddr; /*!< Buffer2 or next descriptor address pointer */ +} FGmac_DmaDesc_t; + +/* Received Frame Informations structure definition */ +typedef struct +{ + FGmac_DmaDesc_t *FSRxDesc; /*!< First Segment Rx Desc */ + FGmac_DmaDesc_t *LSRxDesc; /*!< Last Segment Rx Desc */ + u32 SegCount; /*!< Segment count */ + u32 length; /*!< Frame length */ + u32 buffer; /*!< Frame buffer */ +} FGmac_DmaRxFrameInfos; + +typedef struct +{ + u32 InstanceId; /* Id of device */ + uintptr_t CommonAddress; /* Gmac Common Register */ + uintptr_t BaseAddress; /* Physical base address of Mac Private Address */ + u32 IRQ_NUM; + u32 IRQPriority; + s32 PhyAddr; /* Phy Ic Addre1 ,-1 is need to auto check*/ + u32 clkMDC; /* MDC clock access PHY. [1.0MHz ~2.5MHz] */ + u32 AutoNegotiation; /* Selects or not the AutoNegotiation mode for the external PHY + The AutoNegotiation allows an automatic setting of the Speed (10/100/1000Mbps) + and the mode (half/full-duplex). + This parameter can be a value of @ref GMAC_AutoNegotiation */ + u32 Speed; /* Sets the Ethernet speed: 10/100/1000 Mbps. + This parameter can be a value of @ref GMAC_SPEED */ + u32 DuplexMode; /* Selects the MAC duplex mode: Half-Duplex or Full-Duplex mode + This parameter can be a value of @ref GMAC_Duplex_Mode */ + u32 RxMode; /* Selects the Ethernet Rx mode: Polling mode, Interrupt mode. + This parameter can be a value of @ref GMAC_Rx_Mode */ + u32 ChecksumMode; /* Selects if the checksum is check by hardware or by software. + This parameter can be a value of @ref GMAC_Checksum_Mode */ + u32 MediaInterface; /* Selects the media-independent interface or the reduced media-independent interface. + This parameter can be a value of @ref GMAC_Media_Interface */ + u8 MacAddr[6]; /* 6 bytes Mac address */ + +} FGmac_Config_t; + +/* Only for Dma ring structure */ +struct DescRingData +{ + u32 DescIndex; /* For Current Desc position */ + u32 DescBufIndex; /* For Current Desc buffer buf position */ + u32 DescMaxNumber; /* Max Number for Desc and Desc buffer */ + u8 *DescBufBase; /* Desc buffer Base */ +}; + +typedef struct +{ + FGmac_Config_t Config; /* Hardware configuration */ + u32 IsReady; /* Device is initialised and ready */ + u32 Options; /* Current options word */ + + FGmac_DmaDesc_t *RxDesc; /*!< Rx descriptor to Get */ + struct DescRingData RxDescRingData; + FGmac_DmaDesc_t *TxDesc; /*!< Tx descriptor to Set */ + struct DescRingData TxDescRingData; + + FGmac_IntrCallback_t SendHandler; + FGmac_IntrCallback_t RecvHandler; + Ft_Gmac_MacPhyStatus_Callback StatusHandler; + void *SendArgs; + void *RecvArgs; + void *StatusArgs; + FGmac_ErrIntrCallback_t ErrorHandler; + void *ErrorArgs; + + FGmac_DmaRxFrameInfos DMARxFrameInfos; /* Only for chain structure */ + +} Ft_Gmac_t; + +/** + * @name: FGmac_DmaRxDescRingInit + * @msg: 化标准 DMA 接收描述符 在ring结构下的初始化。 + * @param {Ft_Gmac_t} *Gmac Gmac对象 + * @param {FGmac_DmaDesc_t} *DMARxDescTab 用户定义的静态 DMA 接收描述符表格 + * @param {u8} *RxBuff 用户定义的用于匹配 DMA 接收描述符表格的缓冲区 + * @param {u32} DescBufPerLength 每个缓冲区的大小 + * @param {u32} RxBuffCount 缓冲区的总数量 + * @return {s32} Common_status 参数。 + */ +s32 FGmac_DmaRxDescRingInit(Ft_Gmac_t *Gmac, + FGmac_DmaDesc_t *DMATxDescTab, + u8 *TxBuff, + u32 DescBufPerLength, + u32 TxBuffCount); + +/** + * @name: FGmac_DmaTxDescRingInit + * @msg: 标准 DMA 发送描述符 在ring结构下的初始化。 + * @param {Ft_Gmac_t} *Gmac Gmac对象 + * @param {FGmac_DmaDesc_t} *DMATxDescTab 用户定义的静态 DMA 发送描述符表格 + * @param {u8} *TxBuff 用户定义的用于匹配 DMA 发送描述符表格的缓冲区 + * @param {u32} DescBufPerLength 每个缓冲区的大小 + * @param {u32} TxBuffCount 缓冲区的总数量 + * @return {s32} Common_status 参数 + */ +s32 FGmac_DmaTxDescRingInit(Ft_Gmac_t *Gmac, + FGmac_DmaDesc_t *DMATxDescTab, + u8 *TxBuff, + u32 DescBufPerLength, + u32 TxBuffCount); + +/** + * @name: FGmac_TransmitframeRingPoll + * @msg: 轮询的方式发送DMA发送表述符 + * @param {Ft_Gmac_t} *Gmac Gmac对象 + * @param {uint32_t} FrameLength 需要发送数据的有效长度 + * @return {s32} Common_status 参数 + */ +s32 FGmac_TransmitframeRingPoll(Ft_Gmac_t *Gmac, uint32_t FrameLength); + +/** + * @name: FGmac_RingGetReceivedFrame_IT + * @msg: 检查标准ring结构的DMA接收符中是否有完整的数据包。 + * @param {Ft_Gmac_t} *Gmac Gmac对象 + * @return {s32} Common_status 参数 + */ +s32 FGmac_RingGetReceivedFrame_IT(Ft_Gmac_t *Gmac); + +/** + * @name: FGmac_ResumeTransmission + * @msg: 检查 DMA_STATUS_TU 符号是否存在,如果存在将其置位,恢复DMA 描述符的发送 。 + * @param {Ft_Gmac_t} *Gmac Gmac对象 + * @return {void} + */ +void FGmac_ResumeTransmission(Ft_Gmac_t *Gmac); + +/** + * @name: FGmac_SetTransmitUnderflow + * @msg: 检查 DMA_STATUS_UNF 符号是否存在,如果存在将其置位,恢复DMA 描述符的发送 。 + * @param {Ft_Gmac_t} *Gmac Gmac对象 + * @return {void} + */ +void FGmac_SetTransmitUnderflow(Ft_Gmac_t *Gmac); + +/** + * @name: FGmac_ResumeTransmissionReception + * @msg: 检查 DMA_STATUS_RU 符号是否存在,如果存在将其置位,恢复DMA 描述符的接收 。 + * @param {Ft_Gmac_t} *Gmac + * @return {void} + */ +void FGmac_ResumeTransmissionReception(Ft_Gmac_t *Gmac); + +/** + * @name: Ft_Gmac_LookupConfig + * @msg: 获取 Gmac 静态预设配置参数 。 + * @param {u32} InstanceId Gmac 实例编号。 + * @return {FGmac_Config_t *} 返回Gmac的静态配置 + */ +FGmac_Config_t *Ft_Gmac_LookupConfig(u32 InstanceId); + +/** + * @name: Ft_Gmac_HwInitialize + * @msg: 对于Gmac Mac 层 与Phy 层的硬件部分进行预设初始化配置 + * @param {Ft_Gmac_t} *Gmac Gmac对象。 + * @return {s32} Common_status 参数 + */ +s32 Ft_Gmac_HwInitialize(Ft_Gmac_t *Gmac); + +/** + * @name: Ft_GmacCfgInitialize + * @msg: 初始化,硬件配置相关参数。 + * @param {Ft_Gmac_t} *Gmac Gmac对象。 + * @param {FGmac_Config_t} *Config + * @return {s32} Common_status 参数 + */ +s32 Ft_GmacCfgInitialize(Ft_Gmac_t *Gmac, FGmac_Config_t *Config); + +/** + * @name: Ft_Gmac_Start + * @msg: 开启Gmac 的 发送接收功能,并且开启中断功能。 + * @param {Ft_Gmac_t} *Gmac Gmac对象。 + * @return {s32} Common_status 参数 + */ +s32 Ft_Gmac_Start(Ft_Gmac_t *Gmac); + +/** + * @name: Ft_Gmac_Stop + * @msg: 关闭Gmac 的 发送接收功能。 + * @param {Ft_Gmac_t} *Gmac Gmac对象。 + * @return {s32} Common_status 参数 + */ +s32 Ft_Gmac_Stop(Ft_Gmac_t *Gmac); + +/** + * @name: FGmac_IntrHandler + * @msg: Gmac 中断函数,用于响应Gmac 相关所以函数 + * @param {void} *Args Ft_Gmac_t *Gmac 参数传入 + * @return {void} + */ +void FGmac_IntrHandler(void *Args); + +/** + * @name: FGmac_SetHandler + * @msg: 根据SelectIndex 配置 中断过程中响应函数 + * @param {Ft_Gmac_t} *Gmac Gmac对象。 + * @param {FGmac_IsrCallbackSelect_t} SelectIndex + * @param {void} *FuncPtr + * @param {void} *Args + * @return {s32} Common_status 参数 + */ +s32 FGmac_SetHandler(Ft_Gmac_t *Gmac, FGmac_IsrCallbackSelect_t SelectIndex, void *FuncPtr, void *Args); + +void Ft_Gmac_Phy_Debug(Ft_Gmac_t *Gmac); + +/** + * @name: Ft_Gmac_UseDefaultMacAddr + * @msg: 在有uboot的模式之下,使用默认的Mac0配置参数。 + * @in param{Ft_Gmac_t *}: Gmac对象 + * @out param{u8 *}: 输出的Mac参数 + * @return {None}: + */ +void Ft_Gmac_UseDefaultMacAddr(Ft_Gmac_t *Gmac, u8 *MacAddr); + +#endif // !GMAC_H \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_desc.c b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_desc.c new file mode 100644 index 0000000000000000000000000000000000000000..4971974efbce29be9c06356d07fdc23a236fbba6 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_desc.c @@ -0,0 +1,529 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-05-18 17:58:33 + * @Description:  This files is for gmac description + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_gmac_desc.h" +#include "ft_gmac_hw.h" +#include "ft_parameters.h" + +#include "ft_io.h" +#include "ft_status.h" +#include "ft_assert.h" +#include "ft_cache.h" +#include "ft_debug.h" +#include + +#define GMAC_DESC_DEBUG_TAG "GMAC_DESC" + +#define GMAC_DESC_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(GMAC_DESC_DEBUG_TAG, format, ##__VA_ARGS__) +#define GMAC_DESC_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(GMAC_DESC_DEBUG_TAG, format, ##__VA_ARGS__) +#define GMAC_DESC_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(GMAC_DESC_DEBUG_TAG, format, ##__VA_ARGS__) + +void FGmac_ResumeTransmission(Ft_Gmac_t *Gmac) +{ + /* When Tx Buffer unavailable flag is set: clear it and resume transmission */ + if ((Ft_in32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET) & DMA_STATUS_TU) == DMA_STATUS_TU) + { + /* Clear TBUS GMAC DMA flag */ + Ft_out32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET, DMA_STATUS_TU); + + /* Resume DMA transmission*/ + Ft_out32(Gmac->Config.BaseAddress + DMA_XMT_POLL_DEMAND_OFFSET, 0xff); + } +} + +void FGmac_SetTransmitUnderflow(Ft_Gmac_t *Gmac) +{ + /* When Tx Buffer unavailable flag is set: clear it and resume transmission */ + if ((Ft_in32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET) & DMA_STATUS_UNF) == DMA_STATUS_UNF) + { + /* Clear TBUS GMAC DMA flag */ + Ft_out32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET, DMA_STATUS_UNF); + + /* Resume DMA transmission*/ + Ft_out32(Gmac->Config.BaseAddress + DMA_XMT_POLL_DEMAND_OFFSET, 0xff); + } +} + +/** + * @name: FGmac_DMATxDescChainInit + * @msg: + * @param {Ft_Gmac_t} *Gmac + * @param {FGmac_DmaDesc_t} *DMATxDescTab + * @param {u8} *TxBuff + * @param {u32} TxBuffCount + * @return {*} + */ +s32 FGmac_DMATxDescChainInit(Ft_Gmac_t *Gmac, FGmac_DmaDesc_t *DMATxDescTab, u8 *TxBuff, u32 TxBuffCount) +{ + u32 i; + FGmac_DmaDesc_t *TxDesc; + Ft_assertNonvoid(Gmac != NULL); + Ft_assertNonvoid(Gmac->IsReady == FT_COMPONENT_IS_READLY); + + /* Make Each DmaTx descriptor with initialized value*/ + for (i = 0; i < TxBuffCount; i++) + { + TxDesc = DMATxDescTab + i; + TxDesc->Control = DMA_TDES1_SECOND_ADDRESS_CHAINED; + TxDesc->Buffer1Addr = (u32)(&TxBuff[i * GMAC_MAX_PACKET_SIZE]); + + /* Initialize the next descriptor with the Next Descriptor Polling Enable */ + if (i < (TxBuffCount - 1)) + { + /* Set next descriptor address register with next descriptor base address */ + TxDesc->Buffer2NextDescAddr = (u32)(DMATxDescTab + i + 1); + Ft_printf(" Buffer2NextDescAddr %x \r\n", TxDesc->Buffer2NextDescAddr); + } + else + { + /* For last descriptor, set next descriptor address register equal to the first descriptor base address */ + TxDesc->Buffer2NextDescAddr = (u32)DMATxDescTab; + Ft_printf(" Buffer2NextDescAddr %x \r\n", TxDesc->Buffer2NextDescAddr); + } + } + Ft_printf("DMATxDescTab addr is %x", DMATxDescTab); + + return FST_SUCCESS; +} + +/** + * @name: Ft_Gmac_DMATxDescRingInit + * @msg: + * @param {Ft_Gmac_t} *Gmac + * @param {FGmac_DmaDesc_t} *DMATxDescTab + * @param {u8} *TxBuff + * @param {u32} DescBufPerLength + * @param {u32} TxBuffCount + * @return {*} + */ +s32 FGmac_DmaTxDescRingInit(Ft_Gmac_t *Gmac, FGmac_DmaDesc_t *DMATxDescTab, u8 *TxBuff, u32 DescBufPerLength, u32 TxBuffCount) +{ + u32 i; + FGmac_DmaDesc_t *TxDesc; + Ft_assertNonvoid(Gmac != NULL); + Ft_assertNonvoid(Gmac->IsReady == FT_COMPONENT_IS_READLY); + + memset(&Gmac->TxDescRingData, 0, sizeof(Gmac->TxDescRingData)); + Gmac->TxDescRingData.DescMaxNumber = TxBuffCount; + memset(DMATxDescTab, 0, sizeof(FGmac_DmaDesc_t) * TxBuffCount); + DMATxDescTab[TxBuffCount - 1].Control |= DMA_TDES1_END_RING; + for (i = 0; i < TxBuffCount; i++) + { + TxDesc = DMATxDescTab + i; + FCache_cpuDcacheInvalidate(&TxBuff[i * DescBufPerLength], DescBufPerLength); + TxDesc->Buffer1Addr = (u32)(&TxBuff[i * DescBufPerLength]); + } + Ft_out32(Gmac->Config.BaseAddress + DMA_TX_BASE_ADDR_OFFSET, (u32)DMATxDescTab); + return FST_SUCCESS; +} + +// static s32 FGmac_transmitframe(Ft_Gmac_t *Gmac, uint32_t FrameLength) +// { +// u32 Size = 0U; +// u32 i = 0U; +// u32 BufCount = 0U; + +// if (0U == FrameLength) +// { +// return FST_SUCCESS; +// } + +// if ((Gmac->TxDesc->Status & DMA_TDES0_OWN) == DMA_TDES0_OWN) +// { +// return FST_FAILURE; +// } + +// if (FrameLength > GMAC_MAX_PACKET_SIZE) +// { +// BufCount = FrameLength / GMAC_MAX_PACKET_SIZE; +// if (FrameLength % GMAC_MAX_PACKET_SIZE) +// { +// BufCount++; +// } +// } +// else +// { +// BufCount = 1U; +// } + +// if (BufCount == 1U) +// { +// /* Set LAST and FIRST segment */ +// Gmac->TxDesc->Control |= DMA_TDES1_FIRST_SEGMENT | DMA_TDES1_LAST_SEGMENT; +// /* Set frame size */ +// Gmac->TxDesc->Control &= ~(DMA_TDES1_BUFFER1_SIZE_MASK); +// Gmac->TxDesc->Control |= (FrameLength & DMA_TDES1_BUFFER1_SIZE_MASK); +// /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */ +// Gmac->TxDesc->Status |= (DMA_TDES0_OWN); +// /* Point to next descriptor */ +// Gmac->TxDesc = (FGmac_DmaDesc_t *)(Gmac->TxDesc->Buffer2NextDescAddr); +// } +// else +// { +// for (i = 0U; i < BufCount; i++) +// { +// /* Clear FIRST and LAST segment bits */ +// Gmac->TxDesc->Control &= ~(DMA_TDES1_FIRST_SEGMENT | DMA_TDES1_LAST_SEGMENT); + +// if (i == 0U) +// { +// /* Setting the first segment bit */ +// Gmac->TxDesc->Control |= DMA_TDES1_FIRST_SEGMENT; +// } + +// /* Program size */ +// Gmac->TxDesc->Control &= ~(DMA_TDES1_BUFFER1_SIZE_MASK); +// Gmac->TxDesc->Control |= (GMAC_MAX_PACKET_SIZE & DMA_TDES1_BUFFER1_SIZE_MASK); + +// if (i == (BufCount - 1U)) +// { +// /* Setting the last segment bit */ +// Gmac->TxDesc->Control |= DMA_TDES1_LAST_SEGMENT; +// Size = FrameLength - (BufCount - 1U) * GMAC_MAX_PACKET_SIZE; +// Gmac->TxDesc->Control &= ~(DMA_TDES1_BUFFER1_SIZE_MASK); +// Gmac->TxDesc->Control |= (Size & DMA_TDES1_BUFFER1_SIZE_MASK); +// } + +// /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */ +// Gmac->TxDesc->Status |= (DMA_TDES0_OWN); +// /* point to next descriptor */ +// Gmac->TxDesc = (FGmac_DmaDesc_t *)(Gmac->TxDesc->Buffer2NextDescAddr); +// } +// } + +// FGmac_ResumeTransmission(Gmac); + +// return FST_SUCCESS; +// } + +s32 FGmac_TransmitframeRingPoll(Ft_Gmac_t *Gmac, uint32_t FrameLength) +{ + u32 Size = 0U; + u32 i = 0U; + u32 BufCount = 0U; + FGmac_DmaDesc_t *TxDesc; + + if (0U == FrameLength) + { + return FST_SUCCESS; + } + + if (FrameLength > GMAC_MAX_PACKET_SIZE) + { + BufCount = FrameLength / GMAC_MAX_PACKET_SIZE; + if (FrameLength % GMAC_MAX_PACKET_SIZE) + { + BufCount++; + } + } + else + { + BufCount = 1U; + } + + if (BufCount == 1U) + { + + TxDesc = &Gmac->TxDesc[Gmac->TxDescRingData.DescIndex]; + /* Set LAST and FIRST segment */ + TxDesc->Control |= (DMA_TDES1_FIRST_SEGMENT | DMA_TDES1_LAST_SEGMENT); + + /* Set frame size */ + TxDesc->Control &= ~(DMA_TDES1_BUFFER1_SIZE_MASK); + TxDesc->Control |= (FrameLength & DMA_TDES1_BUFFER1_SIZE_MASK); + /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */ + TxDesc->Status |= (DMA_TDES0_OWN); + GMAC_INC_DESC(Gmac->TxDescRingData.DescIndex, Gmac->TxDescRingData.DescMaxNumber); + } + else + { + for (i = 0U; i < BufCount; i++) + { + TxDesc = &Gmac->TxDesc[Gmac->TxDescRingData.DescIndex]; + /* Clear FIRST and LAST segment bits */ + TxDesc->Control &= ~(DMA_TDES1_FIRST_SEGMENT | DMA_TDES1_LAST_SEGMENT); + + if (i == 0U) + { + /* Setting the first segment bit */ + TxDesc->Control |= DMA_TDES1_FIRST_SEGMENT; + } + + /* Program size */ + TxDesc->Control &= ~(DMA_TDES1_BUFFER1_SIZE_MASK); + TxDesc->Control |= (GMAC_MAX_PACKET_SIZE & DMA_TDES1_BUFFER1_SIZE_MASK); + + if (i == (BufCount - 1U)) + { + /* Setting the last segment bit */ + TxDesc->Control |= (DMA_TDES1_LAST_SEGMENT); + Size = FrameLength - (BufCount - 1U) * GMAC_MAX_PACKET_SIZE; + TxDesc->Control &= ~(DMA_TDES1_BUFFER1_SIZE_MASK); + TxDesc->Control |= (Size & DMA_TDES1_BUFFER1_SIZE_MASK); + } + + /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */ + TxDesc->Status |= (DMA_TDES0_OWN); + + GMAC_INC_DESC(Gmac->TxDescRingData.DescIndex, Gmac->TxDescRingData.DescMaxNumber); + } + } + + FGmac_ResumeTransmission(Gmac); + + return FST_SUCCESS; +} + +/** + * @name: + * @msg: + * @param {Ft_Gmac_t} *Gmac + * @param {FGmac_DmaDesc_t} *DMARxDescTab + * @param {u8} *RxBuff + * @param {u32} RxBuffCount + * @return {*} + */ +s32 FGmac_DMARxDescChainInit(Ft_Gmac_t *Gmac, FGmac_DmaDesc_t *DMARxDescTab, u8 *RxBuff, u32 RxBuffCount) +{ + u32 i; + FGmac_DmaDesc_t *RxDesc; + Ft_assertNonvoid(Gmac != NULL); + Ft_assertNonvoid(Gmac->IsReady == FT_COMPONENT_IS_READLY); + + for (i = 0; i < RxBuffCount; i++) + { + RxDesc = DMARxDescTab + i; + /* Set Own bit of the Rx descriptor Status */ + RxDesc->Status = DMA_RDES0_OWN; + + /* Set Buffer1 size and Second Address Chained bit */ + RxDesc->Control = DMA_RDES1_BUFFER1_SIZE_MASK & (u32)(GMAC_MAX_PACKET_SIZE); + RxDesc->Control |= DMA_RDES1_SECOND_ADDRESS_CHAINED; + /* Set Buffer1 address pointer */ + RxDesc->Buffer1Addr = (u32)(&RxBuff[i * GMAC_MAX_PACKET_SIZE]); + + /* Initialize the next descriptor with the Next Descriptor Polling Enable */ + if (i < (RxBuffCount - 1)) + { + /* Set next descriptor address register with next descriptor base address */ + RxDesc->Buffer2NextDescAddr = (u32)(DMARxDescTab + i + 1); + } + else + { + /* For last descriptor, set next descriptor address register equal to the first descriptor base address */ + RxDesc->Buffer2NextDescAddr = (u32)(DMARxDescTab); + } + + // Ft_printf("rx Buffer2NextDescAddr %x \r\n", RxDesc->Buffer2NextDescAddr); + } + Ft_out32(Gmac->Config.BaseAddress + DMA_RCV_BASE_ADDR_OFFSET, (u32)DMARxDescTab); + return FST_SUCCESS; +} + +s32 FGmac_DmaRxDescRingInit(Ft_Gmac_t *Gmac, FGmac_DmaDesc_t *DMARxDescTab, u8 *RxBuff, u32 DescBufPerLength, u32 RxBuffCount) +{ + u32 i; + FGmac_DmaDesc_t *RxDesc; + Ft_assertNonvoid(Gmac != NULL); + Ft_assertNonvoid(Gmac->IsReady == FT_COMPONENT_IS_READLY); + + memset(&Gmac->RxDescRingData, 0, sizeof(Gmac->RxDescRingData)); + Gmac->RxDescRingData.DescMaxNumber = RxBuffCount; + memset(DMARxDescTab, 0, sizeof(FGmac_DmaDesc_t) * RxBuffCount); + + for (i = 0; i < RxBuffCount; i++) + { + RxDesc = DMARxDescTab + i; + /* Set Own bit of the Rx descriptor Status */ + RxDesc->Status = DMA_RDES0_OWN; + /* Set Buffer1 size and Second Address Chained bit */ + RxDesc->Control = DMA_RDES1_BUFFER1_SIZE_MASK & (u32)(DescBufPerLength); + /* Set Buffer1 address pointer */ + FCache_cpuDcacheInvalidate(&RxBuff[i * DescBufPerLength], DescBufPerLength); + RxDesc->Buffer1Addr = (u32)(&RxBuff[i * DescBufPerLength]); + + if (i == (RxBuffCount - 1)) + { + RxDesc->Control |= DMA_RDES1_END_RING; + } + } + + Ft_out32(Gmac->Config.BaseAddress + DMA_RCV_BASE_ADDR_OFFSET, (u32)DMARxDescTab); + + return FST_SUCCESS; +} + +/** + * @name: FGmac_ResumeTransmissionReception + * @msg: + * @param {Ft_Gmac_t} *Gmac + * @return {*} + */ +void FGmac_ResumeTransmissionReception(Ft_Gmac_t *Gmac) +{ + /* When Rx Buffer unavailable flag is set: clear it and resume transmission */ + if ((Ft_in32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET) & DMA_STATUS_RU) == DMA_STATUS_RU) + { + /* Clear RBUS GMAC DMA flag */ + Ft_out32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET, DMA_STATUS_RU); + + /* Resume DMA transmission*/ + Ft_out32(Gmac->Config.BaseAddress + DMA_RCV_POLL_DEMAND_OFFSET, 0xff); + } +} + +/** + * @name: Gmac_GetReceivedFrame_IT + * @msg: Gets the received frame in interrupt mode. + * @param {Ft_Gmac_t} *Gmac + * @return {*} + */ +// static s32 FGmac_chainGetReceivedFrame_IT(Ft_Gmac_t *Gmac) +// { +// u32 DescriptorsCounter = 0U; +// GMAC_DESC_DEBUG_I(" Gmac->RxDesc->Status %x \r\n", Gmac->RxDesc->Status); +// while (((Gmac->RxDesc->Status & DMA_RDES0_OWN) == 0) && DescriptorsCounter < RX_DESCNUM) +// { +// DescriptorsCounter++; +// /* Check if first segment in frame */ +// if ((Gmac->RxDesc->Status & (DMA_RDES0_FIRST_DESCRIPTOR | DMA_RDES0_LAST_DESCRIPTOR)) == (u32)DMA_RDES0_FIRST_DESCRIPTOR) +// { +// Gmac->DMARxFrameInfos.FSRxDesc = Gmac->RxDesc; +// Gmac->DMARxFrameInfos.SegCount = 1U; +// /* Point to next descriptor */ +// Gmac->RxDesc = (FGmac_DmaDesc_t *)(Gmac->RxDesc->Buffer2NextDescAddr); +// } /* Check if intermediate segment */ +// else if ((Gmac->RxDesc->Status & (DMA_RDES0_FIRST_DESCRIPTOR | DMA_RDES0_LAST_DESCRIPTOR)) == 0) +// { +// /* Increment segment count */ +// Gmac->DMARxFrameInfos.SegCount++; +// /* Point to next descriptor */ +// Gmac->RxDesc = (FGmac_DmaDesc_t *)(Gmac->RxDesc->Buffer2NextDescAddr); +// } /* Should be last segment */ +// else +// { +// Gmac->DMARxFrameInfos.LSRxDesc = Gmac->RxDesc; +// Gmac->DMARxFrameInfos.SegCount++; + +// /* Check if last segment is first segment: one segment contains the frame */ +// if (1U == Gmac->DMARxFrameInfos.SegCount) +// { +// Gmac->DMARxFrameInfos.FSRxDesc = Gmac->RxDesc; +// } + +// Gmac->DMARxFrameInfos.length = ((Gmac->RxDesc->Status & DMA_RDES0_FRAME_LEN_MASK) >> 16U); + +// /* Get address of the buffer start address */ +// Gmac->DMARxFrameInfos.buffer = Gmac->DMARxFrameInfos.FSRxDesc->Buffer1Addr; + +// /* Point to next descriptor */ +// Gmac->RxDesc = (FGmac_DmaDesc_t *)(Gmac->RxDesc->Buffer2NextDescAddr); + +// return FST_SUCCESS; +// } +// } +// return FST_FAILURE; +// } + +s32 FGmac_RingGetReceivedFrame_IT(Ft_Gmac_t *Gmac) +{ + u32 DescriptorsCounter = 0U; + FGmac_DmaDesc_t *RxDesc; + RxDesc = &Gmac->RxDesc[Gmac->RxDescRingData.DescIndex]; + + while (((RxDesc->Status & DMA_RDES0_OWN) == 0) && DescriptorsCounter < Gmac->RxDescRingData.DescMaxNumber) + { + DescriptorsCounter++; + + /* Check if first segment in frame */ + if ((RxDesc->Status & (DMA_RDES0_FIRST_DESCRIPTOR | DMA_RDES0_LAST_DESCRIPTOR)) == (u32)DMA_RDES0_FIRST_DESCRIPTOR) + { + // GMAC_DESC_DEBUG_I("find first frame"); + Gmac->RxDescRingData.DescBufIndex = Gmac->RxDescRingData.DescIndex; + /* Point to next descriptor */ + GMAC_INC_DESC(Gmac->RxDescRingData.DescIndex, Gmac->RxDescRingData.DescMaxNumber); + RxDesc = &Gmac->RxDesc[Gmac->RxDescRingData.DescIndex]; + } /* Check if intermediate segment */ + else if ((RxDesc->Status & (DMA_RDES0_FIRST_DESCRIPTOR | DMA_RDES0_LAST_DESCRIPTOR)) == 0) + { + // GMAC_DESC_DEBUG_I("find invaild frame"); + /* Point to next descriptor */ + GMAC_INC_DESC(Gmac->RxDescRingData.DescIndex, Gmac->RxDescRingData.DescMaxNumber); + RxDesc = &Gmac->RxDesc[Gmac->RxDescRingData.DescIndex]; + } /* Should be last segment */ + else + { + Gmac->RxDescRingData.DescBufIndex = Gmac->RxDescRingData.DescIndex; + GMAC_INC_DESC(Gmac->RxDescRingData.DescIndex, Gmac->RxDescRingData.DescMaxNumber); + return FST_SUCCESS; + } + } + return FST_FAILURE; +} + +/** + * @name: FGmac_GetReceivedFrame + * @msg: Check for received frames. + * @param {Ft_Gmac_t} *Gmac + * @return {*} + */ +s32 FGmac_GetReceivedFrame(Ft_Gmac_t *Gmac) +{ + u32 FrameLength = 0U; + /* Check if segment is not owned by DMA */ + if ((Gmac->RxDesc->Status & DMA_RDES0_OWN) == 0) + { + if ((Gmac->RxDesc->Status & DMA_RDES0_LAST_DESCRIPTOR) != 0) + { + /* increment segment count */ + Gmac->DMARxFrameInfos.SegCount++; + + /* Check if last segment is first segment: one segment contains the frame */ + if (1U == Gmac->DMARxFrameInfos.SegCount) + { + (Gmac->DMARxFrameInfos).FSRxDesc = Gmac->RxDesc; + } + + Gmac->DMARxFrameInfos.LSRxDesc = Gmac->RxDesc; + + /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */ + FrameLength = (((Gmac->RxDesc)->Status & DMA_RDES0_FRAME_LEN_MASK) >> 16U) - 4U; + Gmac->DMARxFrameInfos.length = FrameLength; + + /* Get the address of the buffer start address */ + Gmac->DMARxFrameInfos.buffer = ((Gmac->DMARxFrameInfos).FSRxDesc)->Buffer1Addr; + /* point to next descriptor */ + Gmac->RxDesc = (FGmac_DmaDesc_t *)((Gmac->RxDesc)->Buffer2NextDescAddr); + + return FST_SUCCESS; + } + /* Check if first segment */ + else if ((Gmac->RxDesc->Status & DMA_RDES0_FIRST_DESCRIPTOR) == (u32)DMA_RDES0_FIRST_DESCRIPTOR) + { + (Gmac->DMARxFrameInfos).FSRxDesc = Gmac->RxDesc; + (Gmac->DMARxFrameInfos).LSRxDesc = NULL; + (Gmac->DMARxFrameInfos).SegCount = 1U; + /* Point to next descriptor */ + Gmac->RxDesc = (FGmac_DmaDesc_t *)(Gmac->RxDesc->Buffer2NextDescAddr); + } /* Check if intermediate segment */ + else + { + (Gmac->DMARxFrameInfos).SegCount++; + /* Point to next descriptor */ + Gmac->RxDesc = (FGmac_DmaDesc_t *)(Gmac->RxDesc->Buffer2NextDescAddr); + } + } + + return FST_FAILURE; +} diff --git a/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_desc.h b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_desc.h new file mode 100644 index 0000000000000000000000000000000000000000..f66a591f86c61a0fdd8c18ffce462b2b6e525c54 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_desc.h @@ -0,0 +1,20 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-07 13:24:16 + * @Description:  This files is for gmac descrption + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef GMAC_DESC_H +#define GMAC_DESC_H + +#include "ft_gmac.h" + +#endif // ! \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_g.c b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_g.c new file mode 100644 index 0000000000000000000000000000000000000000..4e9cb78cdcf959fe6c46d9fc11eb3c4bd0c0439f --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_g.c @@ -0,0 +1,47 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-07 13:24:30 + * @Description:  This files is for gmac config + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_gmac.h" +#include "ft_parameters.h" + +FGmac_Config_t Gmac_ConfigTable[FT_GMAC_INSTANCES_NUM] = { + {FT_GMAC0_ID, + FT_GMAC_COMMON_ADDR, + FT_GMAC0_BASEADDR, + GMAC0_ISRNUM, + GMAC0_ISRPRIORITY, + 0, + 5, + GMAC_AUTONEGOTIATION_ENABLE, + GMAC_SPEED_1000M, + GMAC_MODE_FULLDUPLEX, + GMAC_RXINTERRUPT_MODE, + GMAC_CHECKSUM_BY_SOFTWARE, + GMAC_MEDIA_INTERFACE_RGMII, + FT_GMAC0_DEFAULT_ADDR}, + {FT_GMAC1_ID, + FT_GMAC_COMMON_ADDR, + FT_GMAC1_BASEADDR, + GMAC1_ISRNUM, + GMAC1_ISRPRIORITY, + 0, + 5, + GMAC_AUTONEGOTIATION_ENABLE, + GMAC_SPEED_1000M, + GMAC_MODE_FULLDUPLEX, + GMAC_RXINTERRUPT_MODE, + GMAC_CHECKSUM_BY_SOFTWARE, + GMAC_MEDIA_INTERFACE_RGMII, + {0}}, +}; diff --git a/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_hw.c b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_hw.c new file mode 100644 index 0000000000000000000000000000000000000000..5adf90ece0269887ee01d9d0f20b9034d1a83a03 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_hw.c @@ -0,0 +1,582 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-19 17:50:52 + * @Description:  This files is for gmac register + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_gmac_hw.h" +#include "ft_types.h" +#include "ft_generic_timer.h" +#include "ft_assert.h" +#include "ft_status.h" +#include "ft_io.h" +#include "ft_debug.h" +#define PHY_CONFIG_DELAY_US 100 + +#define GMAC_HW_DEBUG_TAG "GMAC_HW" + +#define GMAC_HW_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(GMAC_HW_DEBUG_TAG, format, ##__VA_ARGS__) +#define GMAC_HW_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(GMAC_HW_DEBUG_TAG, format, ##__VA_ARGS__) +#define GMAC_HW_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(GMAC_HW_DEBUG_TAG, format, ##__VA_ARGS__) + +/** + * @name: Gmac_WritePHYRegister + * @msg: + * @param {*} + * @return {*} + */ +s32 Gmac_WritePHYRegister(FGmac_Config_t *Config, u16 PHYReg, u32 RegValue) +{ + u32 TmpReg; + u32 Wait_Counter = 0; + + TmpReg = Ft_in32(Config->BaseAddress + GMAC_MII_ADDR_OFFSET); + + TmpReg |= GMAC_MII_ADDR_CR(Config->clkMDC); + TmpReg |= GMAC_MII_ADDR_PA(Config->PhyAddr); /* Set the PHY device address */ + TmpReg |= GMAC_MII_ADDR_GR(PHYReg); /* Set the PHY register address */ + TmpReg |= GMAC_MII_ADDR_GW; /* Set the write mode */ + TmpReg |= GMAC_MII_ADDR_GB; /* Set the MII Busy bit */ + + Ft_out32(Config->BaseAddress + GMAC_MII_DATA_OFFSET, RegValue); + Ft_out32(Config->BaseAddress + GMAC_MII_ADDR_OFFSET, TmpReg); + + /* Check for the Busy flag */ + while ((Ft_in32(Config->BaseAddress + GMAC_MII_ADDR_OFFSET) & GMAC_MII_ADDR_GB) == GMAC_MII_ADDR_GB) + { + if (10000000 <= ++Wait_Counter) + { + GMAC_HW_DEBUG_E("Gmac_WritePHYRegister FST_ERROR_COUNT_MAX \r\n"); + return FST_ERROR_COUNT_MAX; + } + } + return FST_SUCCESS; +} + +s32 FGmac_ReadPHYRegister(FGmac_Config_t *Config, u16 PHYReg, u32 *RegValue) +{ + u32 TmpReg; + u32 Wait_Counter = 0; + + TmpReg = 0; + TmpReg |= GMAC_MII_ADDR_CR(Config->clkMDC); + TmpReg |= GMAC_MII_ADDR_PA(Config->PhyAddr); /* Set the PHY device address */ + TmpReg |= GMAC_MII_ADDR_GR(PHYReg); /* Set the PHY register address */ + TmpReg &= ~GMAC_MII_ADDR_GW; /* Set the read mode */ + TmpReg |= GMAC_MII_ADDR_GB; /* Set the MII Busy bit */ + + while ((Ft_in32(Config->BaseAddress + GMAC_MII_ADDR_OFFSET) & GMAC_MII_ADDR_GB) == GMAC_MII_ADDR_GB) + { + if (10000000 <= ++Wait_Counter) + { + GMAC_HW_DEBUG_E("wait GMAC_MII_ADDR_GB is error \r\n"); + *RegValue = 0xffff; + return FST_ERROR_COUNT_MAX; + } + } + + Ft_out32(Config->BaseAddress + GMAC_MII_ADDR_OFFSET, TmpReg); + + while ((Ft_in32(Config->BaseAddress + GMAC_MII_ADDR_OFFSET) & GMAC_MII_ADDR_GB) == GMAC_MII_ADDR_GB) + { + if (10000000 <= ++Wait_Counter) + { + GMAC_HW_DEBUG_E("wait GMAC_MII_ADDR_GB 2 is error \r\n"); + *RegValue = 0xffff; + return FST_ERROR_COUNT_MAX; + } + } + *RegValue = Ft_in32(Config->BaseAddress + GMAC_MII_DATA_OFFSET); + return FST_SUCCESS; +} + +static s32 FGmac_PhyAddrGet(FGmac_Config_t *Config) +{ + u32 i = 0; + u32 phyId1; + u32 phyId2; + u8 flag = 0; + + for (i = 0; i < 32; i++) + { + Config->PhyAddr = i; + FGmac_ReadPHYRegister(Config, PHY_ID1_REG_OFFSET, &phyId1); + FGmac_ReadPHYRegister(Config, PHY_ID2_REG_OFFSET, &phyId2); + + if ((phyId2 & 0xffff) != 0xffff) + { + if ((0 == i) && (0x1c == phyId1) && ((phyId2 >> 10) == 0x32)) + { + continue; + } + flag = 1; + break; + } + } + return (flag == 1) ? FST_SUCCESS : FST_FAILURE; +} + +/** + * @name: FGmac_MACAddressConfig + * @msg: + * @param {*} + * @return {*} + */ +static void FGmac_MACAddressConfig(FGmac_Config_t *Config, u32 MacAddr, u8 *Addr) +{ + u32 tmpreg; + /* Calculate the selected MAC address high register */ + tmpreg = ((u32)Addr[5] << 8) | (u32)Addr[4]; + /* Load the selected MAC address high register */ + Ft_out32(Config->BaseAddress + GMAC_MAC_ADDR0_UPPER16BIT_OFFSET + MacAddr, tmpreg); + /* Calculate the selected MAC address low register */ + tmpreg = ((u32)Addr[3] << 24) | ((u32)Addr[2] << 16) | ((u32)Addr[1] << 8) | Addr[0]; + /* Load the selected MAC address low register */ + Ft_out32(Config->BaseAddress + GMAC_MAC_ADDR0_LOWER16BIT_OFFSET + MacAddr, tmpreg); +} + +/** + * @name: FGmac_MACDMAInit + * @msg: + * @param {Config} + * @return {*} + */ +static void FGmac_MACDMAInit(FGmac_Config_t *Config) +{ + u32 RegValue = 0; + Ft_assertVoid(FGmac_PhyAddrGet(Config) == FST_SUCCESS); + RegValue = Ft_in32(Config->BaseAddress + GMAC_CONTROL_OFFSET); + /* MACCR Configuration **************************************/ + /* Set the WD bit according to ETH Watchdog value */ + /* Set the JD: bit according to ETH Jabber value */ + /* Set the IFG bit according to ETH InterFrameGap value */ + /* Set the DCRS bit according to ETH CarrierSense value */ + /* Set the FES bit according to ETH Speed value */ + /* Set the DO bit according to ETH ReceiveOwn value */ + /* Set the LM bit according to ETH LoopbackMode value */ + /* Set the DM bit according to ETH Mode value */ + /* Set the IPCO bit according to ETH ChecksumOffload value */ + /* Set the DR bit according to ETH RetryTransmission value */ + /* Set the ACS bit according to ETH AutomaticPadCRCStrip value */ + /* Set the BL bit according to ETH BackOffLimit value */ + /* Set the DC bit according to ETH DeferralCheck value */ + RegValue &= ~GMAC_CONTROL_WD; + RegValue &= ~GMAC_CONTROL_JD; + RegValue |= GMAC_CONTROL_IFG(0); + RegValue &= ~GMAC_CONTROL_DCRS; + RegValue &= ~GMAC_CONTROL_DO; + RegValue &= ~GMAC_CONTROL_LM; + if (Config->ChecksumMode) + { + RegValue |= GMAC_CONTROL_IPC; + } + else + { + RegValue &= ~GMAC_CONTROL_IPC; + } + + RegValue |= GMAC_CONTROL_DR; + RegValue &= ~GMAC_CONTROL_ACS; + RegValue |= GMAC_CONTROL_BL(0); + RegValue &= ~GMAC_CONTROL_DC; + if (Config->DuplexMode == GMAC_MODE_FULLDUPLEX) + { + RegValue |= GMAC_CONTROL_DM; + } + else + { + RegValue &= ~GMAC_CONTROL_DM; + } + + RegValue &= ~GMAC_CONTROL_FES; + Ft_out32(Config->BaseAddress + GMAC_CONTROL_OFFSET, RegValue); + Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US); + + /*----------------------- GMAC MACFFR Configuration --------------------*/ + /* Set the RA bit according to ETH ReceiveAll value */ + /* Set the SAF and SAIF bits according to ETH SourceAddrFilter value */ + /* Set the PCF bit according to ETH PassControlFrames value */ + /* Set the DBF bit according to ETH BroadcastFramesReception value */ + /* Set the DAIF bit according to ETH DestinationAddrFilter value */ + /* Set the PR bit according to ETH PromiscuousMode value */ + /* Set the PM, HMC and HPF bits according to ETH MulticastFramesFilter value */ + /* Set the HUC and HPF bits according to ETH UnicastFramesFilter value */ + /* Write to MACFFR */ + RegValue = Ft_in32(Config->BaseAddress + GMAC_FRAME_FILTER_OFFSET); + RegValue |= GMAC_FRAME_FILTER_RA; + RegValue |= GMAC_FRAME_FILTER_PCF(2); + RegValue &= ~GMAC_FRAME_FILTER_PM; + RegValue &= ~GMAC_FRAME_FILTER_DBF; + RegValue &= ~GMAC_FRAME_FILTER_DAIF; + RegValue &= ~GMAC_FRAME_FILTER_PR; + Ft_out32(Config->BaseAddress + GMAC_FRAME_FILTER_OFFSET, RegValue); + Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US); + + /*--------------- MACHTHR and MACHTLR Configuration --------------*/ + Ft_out32(Config->BaseAddress + GMAC_HASH_HIGH_OFFSET, 0); + Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US); + Ft_out32(Config->BaseAddress + GMAC_HASH_LOW_OFFSET, 0); + Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US); + + /*----------------------- MACFCR Configuration -------------------*/ + /* Set the PT bit according to ETH PauseTime value */ + /* Set the DZPQ bit according to ETH ZeroQuantaPause value */ + /* Set the PLT bit according to ETH PauseLowThreshold value */ + /* Set the UP bit according to ETH UnicastPauseFrameDetect value */ + /* Set the RFE bit according to ETH ReceiveFlowControl value */ + /* Set the TFE bit according to ETH TransmitFlowControl value */ + RegValue = Ft_in32(Config->BaseAddress + GMAC_FLOW_CTRL_OFFSET); + RegValue |= GMAC_FLOW_DZPQ; + RegValue |= GMAC_FLOW_PLT(0); + RegValue &= ~GMAC_FLOW_RFE; + RegValue &= ~GMAC_FLOW_TFE; + Ft_out32(Config->BaseAddress + GMAC_FLOW_CTRL_OFFSET, RegValue); + Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US); + + /*----------------------- MACVLANTR Configuration ----------------*/ + /* Set the ETV bit according to ETH VLANTagComparison value */ + /* Set the VL bit according to ETH VLANTagIdentifier value */ + RegValue = GMAC_VLAN_TAG_VL(0); + RegValue &= ~GMAC_VLAN_TAG_ETV; + Ft_out32(Config->BaseAddress + GMAC_VLAN_TAG_OFFSET, RegValue); + Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US); + + /* DMA default initialization ************************************/ + /* Set the DT bit according to ETH DropTCPIPChecksumErrorFrame value */ + /* Set the RSF bit according to ETH ReceiveStoreForward value */ + /* Set the DFF bit according to ETH FlushReceivedFrame value */ + /* Set the TSF bit according to ETH TransmitStoreForward value */ + /* Set the TTC bit according to ETH TransmitThresholdControl value */ + /* Set the FEF bit according to ETH ForwardErrorFrames value */ + /* Set the FUF bit according to ETH ForwardUndersizedGoodFrames value */ + /* Set the RTC bit according to ETH ReceiveThresholdControl value */ + /* Set the OSF bit according to ETH SecondFrameOperate value */ + RegValue = Ft_in32(Config->BaseAddress + DMA_OP_OFFSET); + RegValue &= DMA_OP_CLEAR_MASK; + RegValue &= ~DMA_OP_DT; + RegValue |= DMA_OP_RSF; + RegValue &= ~DMA_OP_DFF; + RegValue |= DMA_OP_TSF; + RegValue |= DMA_OP_TTC(7); + RegValue |= DMA_OP_OSF; + Ft_out32(Config->BaseAddress + DMA_OP_OFFSET, RegValue); + Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US); + + /* DMABMR Configuration ------------------*/ + /* Set the AAL bit according to ETH AddressAlignedBeats value */ + /* Set the FB bit according to ETH FixedBurst value */ + /* Set the RPBL and 4*PBL bits according to ETH RxDMABurstLength value */ + /* Set the PBL and 4*PBL bits according to ETH TxDMABurstLength value */ + /* Set the Enhanced DMA descriptors bit according to ETH EnhancedDescriptorFormat value*/ + /* Set the DSL bit according to ETH DesciptorSkipLength value */ + /* Set the PR and DA bits according to ETH DMAArbitration value */ + RegValue = Ft_in32(Config->BaseAddress + DMA_BUS_MODE_OFFSET); + RegValue |= DMA_BUS_AAL; + RegValue |= DMA_BUS_FB; + RegValue |= DMA_BUS_RPBL(32); + RegValue |= DMA_BUS_PBL(32); + RegValue |= DMA_BUS_ATDS; + RegValue |= DMA_BUS_PR(0); + RegValue |= DMA_BUS_USP; + Ft_out32(Config->BaseAddress + DMA_BUS_MODE_OFFSET, RegValue); + Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US); + Ft_out32(Config->BaseAddress + DMA_AXI_BUS_MOD_OFFSET, 0x0000000e); + FGmac_MACAddressConfig(Config, 0, Config->MacAddr); +} + +s32 FGmac_InitializeHw(FGmac_Config_t *Config) +{ + u32 Wait_Counter = 0; + u32 RegValue; + s32 ret = FST_SUCCESS; + + /*Gmac Software reset */ + Ft_out32(Config->BaseAddress + DMA_BUS_MODE_OFFSET, DMA_BUS_SWR); + + while ((Ft_in32(Config->BaseAddress + DMA_BUS_MODE_OFFSET) & DMA_BUS_SWR) == DMA_BUS_SWR) + { + if (++Wait_Counter > 30) + { + GMAC_HW_DEBUG_E("DMA_BUS_MODE_OFFSET wait is too long ,Addr %x \r\n", Config->BaseAddress); + return FST_ERROR_COUNT_MAX; + } + Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US); + } + Wait_Counter = 0; + Ft_out32(Config->BaseAddress + DMA_BUS_MODE_OFFSET, DMA_BUS_INIT); + + Ft_out32(Config->BaseAddress + DMA_OP_OFFSET, Ft_in32(Config->BaseAddress + DMA_OP_OFFSET) | DMA_OP_FTF); + + while ((Ft_in32(Config->BaseAddress + DMA_OP_OFFSET) & DMA_OP_FTF) == DMA_OP_FTF) + { + if (++Wait_Counter > 30) + { + GMAC_HW_DEBUG_E("DMA_OP_OFFSET wait is too long \r\n"); + return FST_ERROR_COUNT_MAX; + } + Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US); + } + + Wait_Counter = 0; + + /* GMAC Init */ + Ft_out32(Config->BaseAddress + GMAC_CONTROL_OFFSET, GMAC_CONTROL_INIT); + /* disable flow control */ + Ft_out32(Config->BaseAddress + GMAC_FLOW_CTRL_OFFSET, 0); + + Ft_out32(Config->BaseAddress + DMA_STATUS_OFFSET, DMA_STATUS_INIT); + + Ft_out32(Config->BaseAddress + DMA_INTR_ENA_OFFSET, 0); + + /* get Phy addr */ + Ft_assertNonvoid(FGmac_PhyAddrGet(Config) == FST_SUCCESS); + + /*-------------------------------- MAC Initialization ----------------------*/ + /*-------------------- PHY initialization and configuration ----------------*/ + /* Put the PHY in reset mode */ + if (Gmac_WritePHYRegister(Config, PHY_BCR_OFFSET, PHY_RESET) != FST_SUCCESS) + { + GMAC_HW_DEBUG_E("PHY_BCR_OFFSET is error \r\n"); + return FST_FAILURE; + } + + do + { + FGmac_ReadPHYRegister(Config, PHY_BCR_OFFSET, &RegValue); + Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US); + + if (++Wait_Counter > 30) + { + GMAC_HW_DEBUG_E("PHY_BCR_OFFSET wait is too long \r\n"); + ret = FST_ERROR_COUNT_MAX; + goto gmac_init; + } + } while ((RegValue & PHY_RESET) == PHY_RESET); + + Wait_Counter = 0; + if (Config->AutoNegotiation == GMAC_AUTONEGOTIATION_ENABLE) + { + do + { + FGmac_ReadPHYRegister(Config, PHY_BSR_OFFSET, &RegValue); + + if (++Wait_Counter > 30) + { + GMAC_HW_DEBUG_E("PHY_BSR_OFFSET 1 wait is too long \r\n"); + ret = FST_ERROR_COUNT_MAX; + goto gmac_init; + } + Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US); + + } while ((RegValue & PHY_LINKED_STATUS) != PHY_LINKED_STATUS); + + Wait_Counter = 0; + if (Gmac_WritePHYRegister(Config, PHY_BCR_OFFSET, PHY_AUTONEGOTIATION | PHY_RESTART_AUTONEGOTIATION) != FST_SUCCESS) + { + GMAC_HW_DEBUG_E("PHY_BCR_OFFSET 2 is error \r\n"); + ret = FST_FAILURE; + goto gmac_init; + } + + do + { + FGmac_ReadPHYRegister(Config, PHY_BSR_OFFSET, &RegValue); + if (++Wait_Counter > 30) + { + GMAC_HW_DEBUG_E("PHY_BSR_OFFSET 2 wait is too long \r\n"); + ret = FST_ERROR_COUNT_MAX; + goto gmac_init; + } + } while ((RegValue & PHY_AUTONEGO_COMPLETE) != PHY_AUTONEGO_COMPLETE); + + if (FGmac_ReadPHYRegister(Config, PHY_SPECIFIC_STATUS_OFFSET, &RegValue) != FST_SUCCESS) + { + GMAC_HW_DEBUG_E("PHY_SPECIFIC_STATUS_OFFSET is error \r\n"); + ret = FST_FAILURE; + goto gmac_init; + } + /* Configure the MAC with the Duplex Mode fixed by the auto-negotiation process */ + if ((RegValue & PHY_SPECIFIC_STATUS_DUPLEX) != PHY_SPECIFIC_STATUS_DUPLEX) + { + /* Set Ethernet duplex mode to Full-duplex following the auto-negotiation */ + Config->DuplexMode = GMAC_MODE_HALFDUPLEX; + } + else + { + /* Set Ethernet duplex mode to Half-duplex following the auto-negotiation */ + Config->DuplexMode = GMAC_MODE_FULLDUPLEX; + } + } + else + { + RegValue = 0; + if (Config->DuplexMode == GMAC_MODE_FULLDUPLEX) + { + if (Config->Speed == GMAC_SPEED_1000M) + { + RegValue = PHY_FULLDUPLEX_1000M; + } + else if (Config->Speed == GMAC_SPEED_100M) + { + RegValue = PHY_FULLDUPLEX_100M; + } + else if (Config->Speed == GMAC_SPEED_10M) + { + RegValue = PHY_FULLDUPLEX_10M; + } + } + else + { + if (Config->Speed == GMAC_SPEED_1000M) + { + RegValue = PHY_HALFDUPLEX_1000M; + } + else if (Config->Speed == GMAC_SPEED_100M) + { + RegValue = PHY_HALFDUPLEX_100M; + } + else if (Config->Speed == GMAC_SPEED_10M) + { + RegValue = PHY_HALFDUPLEX_10M; + } + } + + /* AutoNegotiation Disable */ + if (Gmac_WritePHYRegister(Config, PHY_BCR_OFFSET, RegValue) != FST_SUCCESS) + { + GMAC_HW_DEBUG_E("PHY_BCR_OFFSET 3 is error \r\n"); + ret = FST_FAILURE; + goto gmac_init; + } + } + Ft_GenericTimer_UsDelay(PHY_CONFIG_DELAY_US); + +gmac_init: + + FGmac_MACDMAInit(Config); + return ret; +} + +void FGmac_TransmissionEnable(FGmac_Config_t *Config) +{ + u32 RegValue; + RegValue = Ft_in32(Config->BaseAddress + GMAC_CONTROL_OFFSET); + RegValue |= GMAC_CONTROL_TE; + Ft_out32(Config->BaseAddress + GMAC_CONTROL_OFFSET, RegValue); +} + +void FGmac_TransmissionDisable(FGmac_Config_t *Config) +{ + u32 RegValue; + RegValue = Ft_in32(Config->BaseAddress + GMAC_CONTROL_OFFSET); + RegValue &= ~GMAC_CONTROL_TE; + Ft_out32(Config->BaseAddress + GMAC_CONTROL_OFFSET, RegValue); +} + +void FGmac_ReceptionEnable(FGmac_Config_t *Config) +{ + u32 RegValue; + RegValue = Ft_in32(Config->BaseAddress + GMAC_CONTROL_OFFSET); + RegValue |= GMAC_CONTROL_RE; + Ft_out32(Config->BaseAddress + GMAC_CONTROL_OFFSET, RegValue); +} + +void FGmac_ReceptionDisable(FGmac_Config_t *Config) +{ + u32 RegValue; + RegValue = Ft_in32(Config->BaseAddress + GMAC_CONTROL_OFFSET); + RegValue &= ~GMAC_CONTROL_RE; + Ft_out32(Config->BaseAddress + GMAC_CONTROL_OFFSET, RegValue); +} + +void FGmac_FlushTransmitFIFO(FGmac_Config_t *Config) +{ + u32 RegValue; + RegValue = Ft_in32(Config->BaseAddress + DMA_OP_OFFSET); + RegValue |= DMA_OP_FTF; + Ft_out32(Config->BaseAddress + DMA_OP_OFFSET, RegValue); +} + +void FGmac_DMATransmissionEnable(FGmac_Config_t *Config) +{ + u32 RegValue; + RegValue = Ft_in32(Config->BaseAddress + DMA_OP_OFFSET); + RegValue |= DMA_OP_ST; + Ft_out32(Config->BaseAddress + DMA_OP_OFFSET, RegValue); +} + +/** + * @name: FGmac_DMATransmissionDisable + * @msg: Disable the DMA transmission + * @param {FGmac_Config_t} *Config + * @return {*} + */ +void FGmac_DMATransmissionDisable(FGmac_Config_t *Config) +{ + u32 RegValue; + RegValue = Ft_in32(Config->BaseAddress + DMA_OP_OFFSET); + RegValue &= ~DMA_OP_ST; + Ft_out32(Config->BaseAddress + DMA_OP_OFFSET, RegValue); +} + +/** + * @name: FGmac_DMAReceptionEnable + * @msg: Enable the DMA reception + * @param {FGmac_Config_t} *Config + * @return {*} + */ +void FGmac_DMAReceptionEnable(FGmac_Config_t *Config) +{ + u32 RegValue; + RegValue = Ft_in32(Config->BaseAddress + DMA_OP_OFFSET); + RegValue |= DMA_OP_SR; + Ft_out32(Config->BaseAddress + DMA_OP_OFFSET, RegValue); +} + +void FGmac_DMAReceptionDisable(FGmac_Config_t *Config) +{ + u32 RegValue; + RegValue = Ft_in32(Config->BaseAddress + DMA_OP_OFFSET); + RegValue &= ~DMA_OP_SR; + Ft_out32(Config->BaseAddress + DMA_OP_OFFSET, RegValue); +} + +void FGmac_DMAReceptionTransmissionEnable(FGmac_Config_t *Config) +{ + u32 RegValue; + RegValue = Ft_in32(Config->BaseAddress + DMA_OP_OFFSET); + RegValue |= (DMA_OP_SR | DMA_OP_ST); + Ft_out32(Config->BaseAddress + DMA_OP_OFFSET, RegValue); +} + +void FGmac_DMAReceptionTransmissionDisable(FGmac_Config_t *Config) +{ + u32 RegValue; + RegValue = Ft_in32(Config->BaseAddress + DMA_OP_OFFSET); + RegValue &= ~(DMA_OP_SR | DMA_OP_ST); + Ft_out32(Config->BaseAddress + DMA_OP_OFFSET, RegValue); +} + +void FGmac_ReceptionTransmissionEnable(FGmac_Config_t *Config) +{ + u32 RegValue; + RegValue = Ft_in32(Config->BaseAddress + GMAC_CONTROL_OFFSET); + RegValue |= (GMAC_CONTROL_RE | GMAC_CONTROL_TE); + Ft_out32(Config->BaseAddress + GMAC_CONTROL_OFFSET, RegValue); +} + +void FGmac_ReceptionTransmissionDisable(FGmac_Config_t *Config) +{ + u32 RegValue; + RegValue = Ft_in32(Config->BaseAddress + GMAC_CONTROL_OFFSET); + RegValue &= ~(GMAC_CONTROL_RE | GMAC_CONTROL_TE); + Ft_out32(Config->BaseAddress + GMAC_CONTROL_OFFSET, RegValue); +} \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_hw.h b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_hw.h new file mode 100644 index 0000000000000000000000000000000000000000..4842b72c6938e6f23d8d20a30162859c3db3de0f --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_hw.h @@ -0,0 +1,577 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-07 13:25:10 + * @Description:  This files is for gmac register + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef GMAC_HW_H +#define GMAC_HW_H +#include "ft_types.h" +#include "ft_gmac.h" +/* Register Offset */ + +#define GMAC_CONTROL_OFFSET 0x00000000U /* Configuration */ +#define GMAC_FRAME_FILTER_OFFSET 0x00000004U /* Frame Filter */ +#define GMAC_HASH_HIGH_OFFSET 0x00000008U /* Multicast Hash Table High */ +#define GMAC_HASH_LOW_OFFSET 0x0000000cU /* Multicast Hash Table Low */ +#define GMAC_MII_ADDR_OFFSET 0x00000010U /* MII Address */ +#define GMAC_MII_DATA_OFFSET 0x00000014U /* MII Data */ +#define GMAC_FLOW_CTRL_OFFSET 0x00000018U /* Flow Control */ +#define GMAC_VLAN_TAG_OFFSET 0x0000001cU /* VLAN Tag */ +#define GMAC_VERSION_OFFSET 0x00000020U /* GMAC CORE Version */ +#define GMAC_INTERNAL_MODULE_STATUS_OFFSET 0x00000024U /* 给出各种内部块的状态以进行调试。 */ +#define GMAC_LPI_CONTROL_STATUS_OFFSET 0x00000030U /* 控制低功耗空闲(LPI)操作并提供内核的 LPI 状态。 */ +#define GMAC_LPI_TIMER_CONTROL_OFFSET 0x00000034U /* 控制 LPI 状态中的超时值。 */ +#define GMAC_ISR_STATUS_OFFSET 0x00000038U /* 中断状态。 */ +#define GMAC_ISR_MASK_OFFSET 0x0000003CU /* 生成中断的掩码 */ +#define GMAC_MAC_ADDR0_UPPER16BIT_OFFSET 0x00000040U /* 第一个 MAC 地址的高 16 位。 */ +#define GMAC_MAC_ADDR0_LOWER16BIT_OFFSET 0x00000044U /* 第一个 MAC 地址的低 32 位。。 */ +#define GMAC_MAC_ADDR1_UPPER16BIT_OFFSET 0x00000048U /* 第二个 MAC 地址的高 16 位。 */ +#define GMAC_MAC_ADDR1_LOWER16BIT_OFFSET 0x0000004CU /* 第二个 MAC 地址的低 32 位。。 */ +#define GMAC_MAC_MAC_PHY_STATUS 0x000000D8U /* MAC PHY 状态 */ + +#define DMA_BUS_MODE_OFFSET 0x00001000U /* Bus Mode */ +#define DMA_XMT_POLL_DEMAND_OFFSET 0x00001004U /* Transmit Poll Demand */ +#define DMA_RCV_POLL_DEMAND_OFFSET 0x00001008U /* Received Poll Demand */ +#define DMA_RCV_BASE_ADDR_OFFSET 0x0000100cU /* Receive List Base */ +#define DMA_TX_BASE_ADDR_OFFSET 0x00001010U /* Transmit List Base */ +#define DMA_STATUS_OFFSET 0x00001014U /* Status Register */ +#define DMA_OP_OFFSET 0x00001018U /* Ctrl (Operational Mode) */ +#define DMA_INTR_ENA_OFFSET 0x0000101cU /* Interrupt Enable */ +#define DMA_MISSED_FRAME_CTR_OFFSET 0x00001020U /* Missed Frame Counter */ +#define DMA_RX_WATCHDOG_OFFSET 0x1024U /* Receive Interrupt Watchdog */ +#define DMA_AXI_BUS_MOD_OFFSET 0x1028U /* 控制 AXI 主行为 */ +#define DMA_AXI_BUS_STATUS_OFFSET 0x102CU /* 控制 AXI 状态 */ + +/* MMC control */ +#define MMC_CNTRL 0x0100U /* MMC Control */ +#define MMC_RX_INTR 0x0104U /* MMC RX Interrupt */ +#define MMC_TX_INTR 0x0108U /* MMC TX Interrupt */ +#define MMC_RX_INTR_MASK 0x010cU /* MMC Interrupt Mask */ +#define MMC_TX_INTR_MASK 0x0110U /* MMC Interrupt Mask */ +#define MMC_RX_IPC_INTR_MASK 0x0200U +#define MMC_RX_IPC_INTR 0x0208U + +/** MAC 配置寄存器 **/ +#define GMAC_CONTROL_2K 0x08000000U /* IEEE 802.3as 2K packets */ +#define GMAC_CONTROL_CST 0x2000000U +#define GMAC_CONTROL_TC 0x01000000U /* Transmit Conf. in RGMII/SGMII */ +#define GMAC_CONTROL_WD 0x00800000U /* Disable Watchdog on receive */ +#define GMAC_CONTROL_JD 0x00400000U /* Jabber disable */ +#define GMAC_CONTROL_BE 0x00200000U /* Frame Burst Enable */ +#define GMAC_CONTROL_JE 0x00100000U /* Jumbo frame */ +#define GMAC_CONTROL_IFG(x) ((x & 7) << 17) /* 帧内间隔 ,000 96bit times 001 88bit times 010 80bit times … 111 40bit times*/ +#define GMAC_CONTROL_DCRS 0x00010000U /* Disable carrier sense */ +#define GMAC_CONTROL_PS 0x00008000U /* Port Select 0:GMII 1:MII */ +#define GMAC_CONTROL_FES 0x00004000U /* Speed 0:10 1:100 */ +#define GMAC_CONTROL_DO 0x00002000U /* Disable Rx Own */ +#define GMAC_CONTROL_LM 0x00001000U /* Loop-back mode */ +#define GMAC_CONTROL_DM 0x00000800U /* Duplex Mode . 1 is Duplex */ +#define GMAC_CONTROL_IPC 0x00000400U /* Checksum Offload */ +#define GMAC_CONTROL_DR 0x00000200U /* Disable Retry */ +#define GMAC_CONTROL_LUD 0x00000100U /* Link up/down */ +#define GMAC_CONTROL_ACS 0x00000080U /* Auto Pad/FCS Stripping */ +#define GMAC_CONTROL_BL(x) ((x & 3) << 5) +#define GMAC_CONTROL_DC 0x00000010U /* Deferral Check */ +#define GMAC_CONTROL_TE 0x00000008U /* Transmitter Enable */ +#define GMAC_CONTROL_RE 0x00000004U /* Receiver Enable */ +#define GMAC_CONTROL_INIT (GMAC_CONTROL_DO | GMAC_CONTROL_JD | GMAC_CONTROL_ACS | GMAC_CONTROL_IPC | GMAC_CONTROL_BE | GMAC_CONTROL_DM | GMAC_CONTROL_WD | GMAC_CONTROL_CST) + +/** Frame Filter **/ +#define GMAC_FRAME_FILTER_PR 0x00000001U +#define GMAC_FRAME_FILTER_HUC 0x00000002U +#define GMAC_FRAME_FILTER_HMC 0x00000004U +#define GMAC_FRAME_FILTER_DAIF 0x00000008U +#define GMAC_FRAME_FILTER_PM 0x00000010U +#define GMAC_FRAME_FILTER_DBF 0x00000020U +#define GMAC_FRAME_FILTER_PCF(x) ((x & 3) << 6) +#define GMAC_FRAME_FILTER_SAIF 0x00000100U +#define GMAC_FRAME_FILTER_SAF 0x00000200U +#define GMAC_FRAME_FILTER_HPF 0x00000400U +#define GMAC_FRAME_FILTER_RA 0x80000000U + +/** 哈希表高位寄存器 **/ +#define GMAC_HASH_HIGH_HTH 0xffffffffUL /* 该字段包含 Hash 表的高 32 位。 */ + +/** 哈希表低位寄存器 **/ +#define GMAC_HASH_LOW_HTH 0xffffffffUL /* 该字段包含 Hash 表的低 32 位。 */ + +/** GMII 地址寄存器 **/ +#define GMAC_MII_ADDR_GB 0x00000001 +#define GMAC_MII_ADDR_GW 0x00000002 +#define GMAC_MII_ADDR_CR(x) ((x & 0xf) << 2) +#define GMAC_MII_ADDR_GR(x) ((x & 0x1f) << 6) +#define GMAC_MII_ADDR_PA(x) ((x & 0x1f) << 11) + +/** GMII 数据寄存器 **/ +#define GMAC_MII_DATA_GD 0x0000ffffU + +/** 流控寄存器 **/ +#define GMAC_FLOW_FCB 0x00000001U +#define GMAC_FLOW_BPA GMAC_FLOW_FCB +#define GMAC_FLOW_TFE 0x00000002U +#define GMAC_FLOW_RFE 0x00000004U +#define GMAC_FLOW_UP 0x00000008U +#define GMAC_FLOW_PLT(x) ((x & 3) << 3) +#define GMAC_FLOW_DZPQ 0x00000080U +#define GMAC_FLOW_PT 0xffff0000U + +/** VLAN 标记寄存器 **/ +// #define GMAC_VLAN_TAG_VL 0x0000ffffU +#define GMAC_VLAN_TAG_VL(x) (x & 0xffffU) +#define GMAC_VLAN_TAG_ETV 0x00010000U + +/** 版本寄存器 **/ +#define GMAC_VERSION_UDV 0x00FF0000U /* 用户定义版本号 */ +#define GMAC_VERSION_SDV 0x000000ffU /* 硬件定议版本号 */ + +/** LPI 控制和状态寄存器 **/ +#define GMAC_LPI_CONTROL_STATUS_TLPIEN 0x00000001U +#define GMAC_LPI_CONTROL_STATUS_TLPIEX 0x00000002U +#define GMAC_LPI_CONTROL_STATUS_RLPIEN 0x00000004U +#define GMAC_LPI_CONTROL_STATUS_RLPIEX 0x00000008U +#define GMAC_LPI_CONTROL_STATUS_TLPIST 0x00000100U +#define GMAC_LPI_CONTROL_STATUS_RLPIST 0x00000200U +#define GMAC_LPI_CONTROL_STATUS_LPIEN 0x00010000U +#define GMAC_LPI_CONTROL_STATUS_PLS 0x00020000U +#define GMAC_LPI_CONTROL_STATUS_PLSEN 0x00040000U +#define GMAC_LPI_CONTROL_STATUS_LPITXA 0x00080000U + +/** LPI 定时器控制寄存器 **/ +#define GMAC_LPI_TIMER_TWT 0x0000ffffU +#define GMAC_LPI_TIMER_LIT 0x3FF0000U + +/** 中断状态寄存器 **/ +#define GMAC_ISR_STATUS_RSIS 0x00000001U +#define GMAC_ISR_STATUS_PCSLSC 0x00000002U +#define GMAC_ISR_STATUS_PCSANC 0x00000004U +#define GMAC_ISR_STATUS_PMTIS 0x00000008U +#define GMAC_ISR_STATUS_MMCIS 0x00000010U +#define GMAC_ISR_STATUS_MMCRIS 0x00000020U +#define GMAC_ISR_STATUS_MMCTIS 0x00000040U +#define GMAC_ISR_STATUS_MMCRCOIS 0x00000080U +#define GMAC_ISR_STATUS_TIS 0x00000200U +#define GMAC_ISR_STATUS_LPIIS 0x00000400U + +/** 中断屏蔽寄存器 **/ +#define GMAC_ISR_MASK_RSIM 0x00000001U /* RGMII/SMII 中断屏蔽 */ +#define GMAC_ISR_MASK_PCSLSIM 0x00000002U +#define GMAC_ISR_MASK_PCSANCIM 0x00000004U +#define GMAC_ISR_MASK_PMTIM 0x00000008U +#define GMAC_ISR_MASK_TIM 0x00000020U +#define GMAC_ISR_MASK_LPIIM 0x00000040U + +/** MAC 地址 0 高寄存器 **/ +#define GMAC_MAC_ADDR0_UPPER16BIT_A 0x0000ffffU + +/** MAC 地址 0 低寄存器 **/ +#define GMAC_MAC_ADDR0_LOWERER16BIT_A 0xffffffffU + +/** MAC 地址 1 高寄存器 **/ +#define GMAC_MAC_ADDR1_UPPER16BIT_A 0x0000ffffU +#define GMAC_MAC_ADDR1_UPPER16BIT_MBC 0x3f000000U +#define GMAC_MAC_ADDR1_UPPER16BIT_SA 0x40000000U +#define GMAC_MAC_ADDR1_UPPER16BIT_AE 0x80000000U + +/** MAC 地址 1 低寄存器 **/ +#define GMAC_MAC_ADDR1_LOWER16BIT_A 0xffffffffU + +/* GMAC DMA 寄存器 */ +/** 总线模式寄存器 **/ +#define DMA_BUS_PRWG 0x030000000U +#define DMA_BUS_TXPR 0x08000000U +#define DMA_BUS_MB 0x04000000U +#define DMA_BUS_AAL 0x02000000U +#define DMA_BUS_8xPBL 0x01000000U +#define DMA_BUS_USP 0x00800000U +#define DMA_BUS_RPBL(x) ((x & 0x3f) << 17) +#define DMA_BUS_FB 0x00010000U /* Fixed Burst */ +#define DMA_BUS_PR(x) ((x & 0x3) << 14) /* 00: 1:1 ,01: 2:1 ,10: 3:1 ,11: 4:1 */ +#define DMA_BUS_PBL(x) ((x & 0x3f) << 8) +#define DMA_BUS_ATDS 0x00000080U +#define DMA_BUS_DSL 0x0000007CU /* Descriptor Skip Length */ +#define DMA_BUS_DA 0x00000002U /* DMA Arbitration Scheme,Rx High Pro */ +#define DMA_BUS_SWR 0x00000001U /* Software Reset */ + +#define DMA_BUS_INIT (DMA_BUS_FB | DMA_BUS_PBL(16) | DMA_BUS_RPBL(16)) + +/** 发送轮询请求寄存器 **/ +#define DMA_XMT_POLL_DEMAND_TPD 0xffffffffU + +/** 发送轮询请求寄存器 **/ +#define DMA_RCV_POLL_DEMAND_RPD 0xffffffffU + +/** 接收描述符列表地址寄存器 **/ +#define DMA_RCV_BASE_ADDR_START_REC_LIST 0xfffffff0U + +/** 发送描述符列表地址寄存器 **/ +#define DMA_TX_BASE_ADDR_START_TRA_LIST 0xfffffff0U + +/** + * @brief Bit definition of TDES0 register: DMA Tx descriptor status register + */ +#define BIT(bitnum) (1 << (bitnum % 32)) +#define GENMASK(h, l) \ + (((~0UL) - (1UL << (l)) + 1) & (~0UL >> (32 - 1 - (h)))) + +#define DMA_TDES0_DEFERRED BIT(0) +#define DMA_TDES0_UNDERFLOW_ERROR BIT(1) +#define DMA_TDES0_EXCESSIVE_DEFERRAL BIT(2) +#define DMA_TDES0_COLLISION_COUNT_MASK GENMASK(6, 3) +#define DMA_TDES0_VLAN_FRAME BIT(7) +#define DMA_TDES0_EXCESSIVE_COLLISIONS BIT(8) +#define DMA_TDES0_LATE_COLLISION BIT(9) +#define DMA_TDES0_NO_CARRIER BIT(10) +#define DMA_TDES0_LOSS_CARRIER BIT(11) +#define DMA_TDES0_PAYLOAD_ERROR BIT(12) +#define DMA_TDES0_FRAME_FLUSHED BIT(13) +#define DMA_TDES0_JABBER_TIMEOUT BIT(14) +#define DMA_TDES0_ERROR_SUMMARY BIT(15) +#define DMA_TDES0_IP_HEADER_ERROR BIT(16) +#define DMA_TDES0_TIME_STAMP_STATUS BIT(17) +#define DMA_TDES0_OWN ((u32)BIT(31)) /* silence sparse */ +/* TDES1 */ +#define DMA_TDES1_BUFFER1_SIZE_MASK GENMASK(10, 0) +#define DMA_TDES1_BUFFER2_SIZE_MASK GENMASK(21, 11) +#define DMA_TDES1_BUFFER2_SIZE_SHIFT 11 +#define DMA_TDES1_TIME_STAMP_ENABLE BIT(22) +#define DMA_TDES1_DISABLE_PADDING BIT(23) +#define DMA_TDES1_SECOND_ADDRESS_CHAINED BIT(24) +#define DMA_TDES1_END_RING BIT(25) +#define DMA_TDES1_CRC_DISABLE BIT(26) +#define DMA_TDES1_CHECKSUM_INSERTION_MASK GENMASK(28, 27) +#define DMA_TDES1_CHECKSUM_INSERTION_SHIFT 27 +#define DMA_TDES1_FIRST_SEGMENT BIT(29) +#define DMA_TDES1_LAST_SEGMENT BIT(30) +#define DMA_TDES1_INTERRUPT BIT(31) + +/* Bit definition of RDES0 register: DMA Rx descriptor status register */ +/* RDES0 */ +#define DMA_RDES0_PAYLOAD_CSUM_ERR BIT(0) +#define DMA_RDES0_CRC_ERROR BIT(1) +#define DMA_RDES0_DRIBBLING BIT(2) +#define DMA_RDES0_MII_ERROR BIT(3) +#define DMA_RDES0_RECEIVE_WATCHDOG BIT(4) +#define DMA_RDES0_FRAME_TYPE BIT(5) +#define DMA_RDES0_COLLISION BIT(6) +#define DMA_RDES0_IPC_CSUM_ERROR BIT(7) +#define DMA_RDES0_LAST_DESCRIPTOR BIT(8) +#define DMA_RDES0_FIRST_DESCRIPTOR BIT(9) +#define DMA_RDES0_VLAN_TAG BIT(10) +#define DMA_RDES0_OVERFLOW_ERROR BIT(11) +#define DMA_RDES0_LENGTH_ERROR BIT(12) +#define DMA_RDES0_SA_FILTER_FAIL BIT(13) +#define DMA_RDES0_DESCRIPTOR_ERROR BIT(14) +#define DMA_RDES0_ERROR_SUMMARY BIT(15) +#define DMA_RDES0_FRAME_LEN_MASK (0x3FFF << 16) /*GENMASK(29, 16)*/ +#define DMA_RDES0_FRAME_LEN_SHIFT 16 +#define DMA_RDES0_DA_FILTER_FAIL BIT(30) +#define DMA_RDES0_OWN BIT(31) +/* RDES1 */ +#define DMA_RDES1_BUFFER1_SIZE_MASK GENMASK(10, 0) +#define DMA_RDES1_BUFFER2_SIZE_MASK GENMASK(21, 11) +#define DMA_RDES1_BUFFER2_SIZE_SHIFT 11 +#define DMA_RDES1_SECOND_ADDRESS_CHAINED BIT(24) +#define DMA_RDES1_END_RING BIT(25) +#define DMA_RDES1_DISABLE_IC BIT(31) + +/** DMA Status register defines **/ +#define DMA_STATUS_GLPII 0x40000000 /* GMAC LPI interrupt */ +#define DMA_STATUS_GPI 0x10000000 /* PMT interrupt */ +#define DMA_STATUS_GMI 0x08000000 /* MMC interrupt */ +#define DMA_STATUS_GLI 0x04000000 /* GMAC Line interface int */ +#define DMA_STATUS_EB_MASK 0x00380000 /* Error Bits Mask */ +#define DMA_STATUS_EB_TX_ABORT 0x00080000 /* Error Bits - TX Abort */ +#define DMA_STATUS_EB_RX_ABORT 0x00100000 /* Error Bits - RX Abort */ +#define DMA_STATUS_TS_MASK 0x00700000 /* Transmit Process State */ +#define DMA_STATUS_RS_MASK 0x000e0000 /* Receive Process State */ +#define DMA_STATUS_NIS 0x00010000 /* Normal Interrupt Summary */ +#define DMA_STATUS_AIS 0x00008000 /* Abnormal Interrupt Summary */ +#define DMA_STATUS_ERI 0x00004000 /* Early Receive Interrupt */ +#define DMA_STATUS_FBI 0x00002000 /* Fatal Bus Error Interrupt */ +#define DMA_STATUS_ETI 0x00000400 /* Early Transmit Interrupt */ +#define DMA_STATUS_RWT 0x00000200 /* Receive Watchdog Timeout */ +#define DMA_STATUS_RPS 0x00000100 /* Receive Process Stopped */ +#define DMA_STATUS_RU 0x00000080 /* Receive Buffer Unavailable */ +#define DMA_STATUS_RI 0x00000040 /* Receive Interrupt */ +#define DMA_STATUS_UNF 0x00000020 /* Transmit Underflow */ +#define DMA_STATUS_OVF 0x00000010 /* Receive Overflow */ +#define DMA_STATUS_TJT 0x00000008 /* Transmit Jabber Timeout */ +#define DMA_STATUS_TU 0x00000004 /* Transmit Buffer Unavailable */ +#define DMA_STATUS_TPS 0x00000002 /* Transmit Process Stopped */ +#define DMA_STATUS_TI 0x00000001 /* Transmit Interrupt */ +#define DMA_STATUS_INIT 0xFFFFFFFF + +/** DMA 操作模式寄存器 **/ +#define DMA_OP_DT 0x04000000U /* No Dropping of TCP/IP csum Err Frame */ +#define DMA_OP_RSF 0x02000000U /* Rx Store and Forward */ +#define DMA_OP_DFF 0x01000000U /* */ +#define DMA_OP_TSF 0x000200000U /* Tx Store and Forward */ +#define DMA_OP_FTF 0x000100000U /* Flush Tx FIFO */ +#define DMA_OP_TTC(x) ((x & 7) << 14) /* Tx Threshold Control ,• 000 64 , 001 128 , 010 192 ,011 256 ,100 40 , 101 32 , 110 24 , 111 16*/ +#define DMA_OP_ST 0x000002000U /* Start/Stop Tx */ +#define DMA_OP_RFD(x) ((x & 0x3) << 11) /* Threshold for DeActive Flow Control */ +#define DMA_OP_RFA 0x000000600U /* Threshold for Active Flow Control */ +#define DMA_OP_EFC 0x000000100U /* Enable HW Flow control */ +#define DMA_OP_FEF 0x000000080U /* Forward Error Frame */ +#define DMA_OP_FUF 0x000000040U /* Forward Undersize Good Frame */ +#define DMA_OP_RTC 0x000000018U /* Rx Threshold Control */ +#define DMA_OP_OSF 0x000000004U /* Operate On Second Mode */ +#define DMA_OP_SR 0x00000002U /* Start/Stop Rx */ +#define DMA_OP_CLEAR_MASK ((u32)0xF8DE3F23U) +#define DMA_OP_INIT (DMA_OP_SR | DMA_OP_RSF) + +/** 中断使能寄存器 **/ +#define DMA_INTR_ENA_TIE 0x00000001U /* Transmit Interrupt */ +#define DMA_INTR_ENA_TSE 0x00000002U /* 传输停止启用 */ +#define DMA_INTR_ENA_TUE 0x00000004U /* Transmit Buffer Unavailable */ +#define DMA_INTR_ENA_THE 0x00000008U /* 发送 Jabber 超时启用 */ +#define DMA_INTR_ENA_OVE 0x00000010U /* 溢出中断使能 */ +#define DMA_INTR_ENA_UNE 0x00000020U /* 下溢中断使能 */ +#define DMA_INTR_ENA_RIE 0x00000040U /* Receive Interrupt */ +#define DMA_INTR_ENA_RUE 0x00000080U /* 接收缓冲区不可用启用 */ +#define DMA_INTR_ENA_RSE 0x00000100U /* 接收已停止启用 */ +#define DMA_INTR_ENA_RWE 0x00000200U /* 接收看门狗超时使能 */ +#define DMA_INTR_ENA_ETE 0x00000400U /* 早期发送中断使能 */ +#define DMA_INTR_ENA_FBE 0x00002000U /* Fatal Bus Error */ +#define DMA_INTR_ENA_ERE 0x00004000U /* Early Receive */ +#define DMA_INTR_ENA_AIE 0x00008000 /* Abnormal Summary */ +#define DMA_INTR_ENA_NIE 0x00010000 /* Normal Summary */ + +#define DMA_INTR_DEFAULT (DMA_INTR_ENA_TIE | DMA_INTR_ENA_TSE | DMA_INTR_ENA_TUE | DMA_INTR_ENA_THE | DMA_INTR_ENA_OVE | DMA_INTR_ENA_UNE | DMA_INTR_ENA_RIE | DMA_INTR_ENA_RUE | DMA_INTR_ENA_RSE | DMA_INTR_ENA_RWE | DMA_INTR_ENA_ETE | DMA_INTR_ENA_FBE | DMA_INTR_ENA_ERE | DMA_INTR_ENA_AIE | DMA_INTR_ENA_NIE) + +/** 丢帧和缓冲区溢出计数器寄存器 **/ +#define DMA_MISSED_FRAME_CTR_CMIS 0x0000FFFFUDMA_MISSED_FRAME +#define DMA_MISSED_FRAME_CTR_OVMIS 0x00010000U +#define DMA_MISSED_FRAME_CTR_CFIFO 0x0ffe0000U +#define DMA_MISSED_FRAME_CTR_OVFIFO 0x10000000U + +/** 接收中断看门狗定时器寄存器 **/ +#define DMA_RX_WATCHDOG_RIWT 0x0000000fU + +/** AXI_BUS_MOD **/ +#define DMA_AXI_BUS_MOD_UNDEF 0x00000001U /* AXI 未定义的突发长度 */ +#define DMA_AXI_BUS_MOD_BLEN4 0x00000002U /* AXI 突发长度 4 */ +#define DMA_AXI_BUS_MOD_BLEN8 0x00000004U /* AXI 突发长度 8 */ +#define DMA_AXI_BUS_MOD_BLEN16 0x00000008U /* AXI 突发长度 16 */ +#define DMA_AXI_BUS_MOD_BLEN32 0x00000010U /* AXI 突发长度 32 */ +#define DMA_AXI_BUS_MOD_BLEN64 0x00000020U /* AXI 突发长度 64 */ +#define DMA_AXI_BUS_MOD_BLEN128 0x00000040U /* AXI 突发长度 128 */ +#define DMA_AXI_BUS_MOD_BLEN256 0x00000080U /* AXI 突发长度 256 */ +#define DMA_AXI_BUS_MOD_AXI_AAL 0x00001000U /* 地址对齐的节拍 */ +#define DMA_AXI_BUS_MOD_RD_OSR_LMT(x) ((x & 0xf) << 16) /* XI 最大读取未决请求限制此值限 制 AXI 读取接口上的最大未完成请求。 */ +#define DMA_AXI_BUS_MOD_WR_OSR_LMT(x) ((x & 0xf) << 20) /* AXI 最大写入未决请求限制此值 限制 AXI 写入接口上的最大未完成请求。 */ +#define DMA_AXI_BUS_MOD_UNLCK_ON_MGK_RWK 0x40000000U +#define DMA_AXI_BUS_MOD_EN_LPI 0x80000000U + +/** MMC Control **/ +#define MMC_DEFAULT_MASK 0xffffffff + +/* Common PHY Registers (AR8035) */ + +#define PHY_BCR_OFFSET ((u16)0x00) /* Transceiver Basic Control Register */ +#define PHY_BSR_OFFSET ((u16)0x01) /* Transceiver Basic Status Register */ +#define PHY_ID1_REG_OFFSET ((u16)0x02) /* PHY ID1 Identifier */ +#define PHY_ID2_REG_OFFSET ((u16)0x03) /* PHY ID2 Identifier */ +#define PHY_AUTO_NEGOTIATION_ADVERTISEMENT_OFFSET ((u16)0x04) +#define PHY_EXTENDED_CONTROL_REGISTER_OFFSET ((u16)0x9) +#define PHY_SPECIFIC_STATUS_OFFSET ((u16)0x11) +#define PHY_INTERRUPT_ENABLE_OFFSET ((u16)0x12) +#define PHY_INTERRUPT_STATUS_OFFSET ((u16)0x13) +#define PHY_DEBUG_ADDR_OFFSET ((u16)0x1D) +#define PHY_DEBUG_DATA_OFFSET ((u16)0x1E) + +/* MII control register bit */ + +#define PHY_BCR_1000 0x0040 /* 1 = 1000mb when \ + PHY_BCR_100 is also 1 */ +#define PHY_BCR_COLL_TEST 0x0080 /* collision test */ +#define PHY_BCR_FDX 0x0100 /* FDX =1, half duplex =0 */ +#define PHY_BCR_RESTART 0x0200 /* restart auto negotiation */ +#define PHY_BCR_ISOLATE 0x0400 /* isolate PHY from MII */ +#define PHY_BCR_POWER_DOWN 0x0800 /* power down */ +#define PHY_BCR_AUTO_EN 0x1000 /* auto-negotiation enable */ +#define PHY_BCR_100 0x2000 /* 0 = 10mb, 1 = 100mb */ +#define PHY_BCR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */ +#define PHY_BCR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */ +#define PHY_BCR_NORM_EN 0x0000 /* just enable the PHY */ +#define PHY_BCR_DEF_0_MASK 0xca7f /* they must return zero */ +#define PHY_BCR_RES_MASK 0x003f /* reserved bits,return zero */ + +#define PHY_ANAR_10TX_HD ((u16)0x0020) +#define PHY_ANAR_10TX_FD ((u16)0x0040) +#define PHY_ANAR_100TX_HD ((u16)0x0080) +#define PHY_ANAR_100TX_FD ((u16)0x0100) +#define PHY_ANAR_100T_4 ((u16)0x0200) +#define PHY_ANAR_PAUSE ((u16)0x0400) +#define PHY_ANAR_ASM_PAUSE ((u16)0x0800) +#define PHY_ANAR_REMORT_FAULT ((u16)0x2000) +#define PHY_ANAR_NEXT_PAGE ((u16)0x8000) +#define PHY_ANAR_PAUSE_MASK ((u16)0x0c00) + +#define PHY_BSR_EXTENDED_STATUS ((u16)0x100) + +#define PHY_EXTENDED_CONTROL_1000T_FD ((u16)0x200) +#define PHY_EXTENDED_CONTROL_1000T_HD ((u16)0x100) + +#define PHY_RESET ((u16)0x8000U) /* PHY Reset */ +#define PHY_LOOPBACK ((u16)0x4000U) /* Select loop-back mode */ +#define PHY_FULLDUPLEX_1000M ((u16)0x2140U) /* Set the full-duplex mode at 1000 Mb/s */ +#define PHY_HALFDUPLEX_1000M ((u16)0x2040U) /* Set the half-duplex mode at 1000 Mb/s */ +#define PHY_FULLDUPLEX_100M ((u16)0x2100U) /* Set the full-duplex mode at 100 Mb/s */ +#define PHY_HALFDUPLEX_100M ((u16)0x2000U) /* Set the half-duplex mode at 100 Mb/s */ +#define PHY_FULLDUPLEX_10M ((u16)0x0100U) /* Set the full-duplex mode at 10 Mb/s */ +#define PHY_HALFDUPLEX_10M ((u16)0x0000U) /* Set the half-duplex mode at 10 Mb/s */ +#define PHY_AUTONEGOTIATION ((u16)0x1000U) /* Enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGOTIATION ((u16)0x0200U) /* Restart auto-negotiation function */ +#define PHY_POWERDOWN ((u16)0x0800U) /* Select the power down mode */ +#define PHY_ISOLATE ((u16)0x0400U) /* Isolate PHY from MII */ + +#define PHY_AUTONEGO_COMPLETE ((u16)0x0020U) /* Auto-Negotiation process completed */ +#define PHY_LINKED_STATUS ((u16)0x0004U) /* Valid link established */ +#define PHY_JABBER_DETECTION ((u16)0x0002U) /* Jabber condition detected */ + +#define PHY_SPECIFIC_STATUS_DUPLEX ((u16)0x2000) /* 0 is Half-duplex ,1 is Full-duplex */ +#define PHY_SPECIFIC_STATUS_SPEED ((u16)0xc000) /* 0 is 10Mbps ,1 is 100Mbps , 2 is 1000Mbps */ + +#define PHY_INTERRUPT_ENABLE_WAKE_ON_LAN 0x00000001U /* Wake on LAN interrupt enable,0 Interrupt disable , 1 Interrupt enable */ +#define PHY_INTERRUPT_ENABLE_POLARITY_CHANGED 0x00000002U /* Polarity Changed interrupt enable,0 Interrupt disable , 1 Interrupt enable */ +#define PHY_INTERRUPT_ENABLE_WIRESPEED_DOWNGRADE 0x00000020U /* Wirespeed downgrade Interrupt ,0 Interrupt disable , 1 Interrupt enable*/ +#define PHY_INTERRUPT_ENABLE_LINK_SUCCESS 0x00000400U /* Link success interrupt ,0 Interrupt disable , 1 Interrupt enable*/ +#define PHY_INTERRUPT_ENABLE_LINK_FAIL 0x00000800U /* Link fail interrupt, 0 Interrupt disable , 1 Interrupt enable */ +#define PHY_INTERRUPT_ENABLE_PAGE_RECEIVED 0x00001000U /* Page Received, 0 Interrupt disable , 1 Interrupt enable */ +#define PHY_INTERRUPT_ENABLE_DUPLEX_CHANGED 0x00002000U /* Duplex Changed, 0 Interrupt disable , 1 Interrupt enable*/ +#define PHY_INTERRUPT_ENABLE_SPEED_CHANGED 0x00004000U /* Speed Changed , 0 Interrupt disable , 1 Interrupt enable */ +#define PHY_INTERRUPT_ENABLE_AUTO_NEGOTIATION_ERROR 0x00008000U /* Auto-Negotiation Error , 0 Interrupt disable , 1 Interrupt enable */ + +#define PHY_INTERRUPT_STATUS_WAKE_ON_LAN 0x00000001U /* Wake on LAN ,0 No Wake-on-LAN packet is received , 1 Wake-on-LAN packet is received */ +#define PHY_INTERRUPT_STATUS_POLARITY_CHANGED 0x00000002U /* Polarity Changed ,0 Polarity changed , 1 Polarity not changed */ +#define PHY_INTERRUPT_STATUS_WIRESPEED_DOWNGRADE 0x00000020U /* Wirespeed downgrade Interrupt ,0 No Smartspeed interrupt detected , 1 Smartspeed interrupt detected */ +#define PHY_INTERRUPT_STATUS_LINK_SUCCESS 0x00000400U /* Link success interrupt ,0 Link up not happened , 1 Link up happened.*/ +#define PHY_INTERRUPT_STATUS_LINK_FAIL 0x00000800U /* Link fail interrupt, 0 Link down not happened , 1 Link down happened. */ +#define PHY_INTERRUPT_STATUS_PAGE_RECEIVED 0x00001000U /* Page Received, 0 Page not received , 1 Page received */ +#define PHY_INTERRUPT_STATUS_DUPLEX_CHANGED 0x00002000U /* Duplex Changed, 0 Duplex not changed , 1 Duplex changed*/ +#define PHY_INTERRUPT_STATUS_SPEED_CHANGED 0x00004000U /* Speed Changed , 0 Speed not changed , 1 Speed changed */ +#define PHY_INTERRUPT_STATUS_AUTO_NEGOTIATION_ERROR 0x00008000U /* Auto-Negotiation Error , 0 No Auto-Negotiation Error , 1 Auto-Negotiation Error */ + +/** + * @name: FGmac_InitializeHw + * @msg: 初始化Mac层与Phy层参数 。 + * @param {FGmac_Config_t} *Config 包含Mac层 与Phy层,配置参数。 + * @return {s32} Common_status 参数。 + */ +s32 FGmac_InitializeHw(FGmac_Config_t *Config); + +/** + * @name: FGmac_ReadPHYRegister + * @msg: 读取Phy 中的寄存器 + * @param {FGmac_Config_t} *Config 提供读取的基地址,与Phy读取过程中需要的相关参数。 + * @param {u16} PHYReg 需要读取Phy 芯片的寄存器地址。 + * @param {u32} *RegValue 读取出来的寄存器参数 + * @return {s32} Common_status 参数。 + */ +s32 FGmac_ReadPHYRegister(FGmac_Config_t *Config, u16 PHYReg, u32 *RegValue); + +/** + * @name: Gmac_WritePHYRegister + * @msg: 向Phy 中的特定寄存器写入参数。 + * @param {FGmac_Config_t} *Config 提供读取的基地址,与Phy读取过程中需要的相关参数。 + * @param {u16} PHYReg 需要读取Phy 芯片的寄存器地址。 + * @param {u32} RegValue 需要写入的寄存器参数 + * @return {s32} Common_status 参数。 + */ +s32 Gmac_WritePHYRegister(FGmac_Config_t *Config, u16 PHYReg, u32 RegValue); + +/** + * @name: FGmac_TransmissionEnable + * @msg: 使能 Gmac 开始发送功能 + * @param {FGmac_Config_t} *Config 提供Mac的基地址。 + * @return {None} + */ +void FGmac_TransmissionEnable(FGmac_Config_t *Config); + +/** + * @name: FGmac_TransmissionDisable + * @msg: 禁止 Gmac 开始发送功能 + * @param {FGmac_Config_t} *Config 提供Mac的基地址。 + * @return {None} + */ +void FGmac_TransmissionDisable(FGmac_Config_t *Config); + +/** + * @name: FGmac_ReceptionEnable + * @msg: 使能 Gmac 开始接收功能 + * @param {FGmac_Config_t} *Config 提供Mac的基地址。 + * @return {None} + */ +void FGmac_ReceptionEnable(FGmac_Config_t *Config); + +/** + * @name: FGmac_ReceptionDisable + * @msg: 禁止 Gmac 开始接收功能 + * @param {FGmac_Config_t} *Config 提供Mac的基地址。 + * @return {None} + */ +void FGmac_ReceptionDisable(FGmac_Config_t *Config); + +/** + * @name: FGmac_DMAReceptionTransmissionEnable + * @msg: 使能 Gmac 开始DMA描述符接收与写入功能 + * @param {FGmac_Config_t} *Config 提供Mac的基地址。 + * @return {*} + */ +void FGmac_DMAReceptionTransmissionEnable(FGmac_Config_t *Config); + +/** + * @name: FGmac_ReceptionTransmissionEnable + * @msg: 使能 Gmac 开始接收与发送功能 + * @param {FGmac_Config_t} *Config 提供Mac的基地址。 + * @return {*} + */ +void FGmac_ReceptionTransmissionEnable(FGmac_Config_t *Config); + +/** + * @name: FGmac_FlushTransmitFIFO + * @msg: 刷新 Gmac 发送 FIFO + * @param {FGmac_Config_t} *Config 提供Mac的基地址。 + * @return {*} + */ +void FGmac_FlushTransmitFIFO(FGmac_Config_t *Config); + +/** + * @name: FGmac_DMATransmissionEnable + * @msg: 使能 DMA描述符发送功能 + * @param {FGmac_Config_t} *Config 提供Mac的基地址。 + * @return {*} + */ +void FGmac_DMATransmissionEnable(FGmac_Config_t *Config); +/** + * @name: FGmac_DMATransmissionDisable + * @msg: 关闭 DMA描述符发送功能 + * @param {FGmac_Config_t} *Config 提供Mac的基地址。 + * @return {*} + */ +void FGmac_DMATransmissionDisable(FGmac_Config_t *Config); +/** + * @name: FGmac_DMAReceptionEnable + * @msg: 使能 DMA描述符接收功能 + * @param {FGmac_Config_t} *Config 提供Mac的基地址。 + * @return {*} + */ +void FGmac_DMAReceptionEnable(FGmac_Config_t *Config); +/** + * @name: FGmac_DMAReceptionEnable + * @msg: 使能 DMA描述符接收功能 + * @param {FGmac_Config_t} *Config 提供Mac的基地址。 + * @return {*} + */ +void FGmac_DMAReceptionDisable(FGmac_Config_t *Config); +#endif // ! \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_intr.c b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_intr.c new file mode 100644 index 0000000000000000000000000000000000000000..e6ac067493aded1bc03902e2ca88fee07a0319d4 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_intr.c @@ -0,0 +1,194 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-05-18 13:48:57 + * @Description:  This files is for gmac irq + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_gmac_hw.h" +#include "ft_gmac.h" +#include "ft_status.h" +#include "ft_assert.h" +#include "ft_io.h" + +#include "ft_debug.h" +#define GMAC_INTR_DEBUG_TAG "GMAC_INTR" + +#define GMAC_INTR_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(GMAC_INTR_DEBUG_TAG, format, ##__VA_ARGS__) +#define GMAC_INTR_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(GMAC_INTR_DEBUG_TAG, format, ##__VA_ARGS__) +#define GMAC_INTR_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(GMAC_INTR_DEBUG_TAG, format, ##__VA_ARGS__) + +/** + * @name: FGmac_SetHandler + * @msg: + * @param {Ft_Gmac_t} *Gmac + * @param {FGmac_IsrCallbackSelect_t} SelectIndex + * @param {void} *FuncPtr + * @param {void} *Args + * @return {*} + */ +s32 FGmac_SetHandler(Ft_Gmac_t *Gmac, FGmac_IsrCallbackSelect_t SelectIndex, void *FuncPtr, + void *Args) +{ + Ft_assertNonvoid(Gmac != NULL); + Ft_assertNonvoid(FuncPtr != NULL); + Ft_assertNonvoid(Gmac->IsReady == FT_COMPONENT_IS_READLY); + + switch (SelectIndex) + { + case FT_GMAC_TX_COMPLETE_CB_ID: + /* code */ + Gmac->SendHandler = FuncPtr; + Gmac->SendArgs = Args; + break; + case FT_GMAC_RX_COMPLETE_CB_ID: + Gmac->RecvHandler = FuncPtr; + Gmac->RecvArgs = Args; + break; + case FT_GMAC_DMA_ERROR_CB_ID: + Gmac->ErrorHandler = FuncPtr; + Gmac->ErrorArgs = Args; + break; + case FT_GMAC_MAC_PHY_STATUS_CB_ID: + Gmac->StatusHandler = FuncPtr; + Gmac->StatusArgs = Args; + break; + default: + return FST_FAILURE; + } + + return FST_SUCCESS; +} + +/** + * @name: FGmac_ErrorCheck + * @msg: + * @param {Ft_Gmac_t} *Gmac + * @return {*} + */ +__STATIC_INLINE u32 FGmac_ErrorCheck(Ft_Gmac_t *Gmac) +{ + u32 RegValue = 0; + u32 ErrIsr_RegValue = 0; + u32 RetValue = 0; + RegValue = Ft_in32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET); + ErrIsr_RegValue = Ft_in32(Gmac->Config.BaseAddress + DMA_INTR_ENA_OFFSET); + + if (((RegValue & DMA_STATUS_TPS) == DMA_STATUS_TPS) && ((ErrIsr_RegValue & DMA_INTR_ENA_TSE) == DMA_INTR_ENA_TSE)) + { + RetValue |= GMAC_ERROR_TRANSMIT_PROCESS_STOPPED; + } + + if (((RegValue & DMA_STATUS_TU) == DMA_STATUS_TU) && ((ErrIsr_RegValue & DMA_INTR_ENA_TUE) == DMA_INTR_ENA_TUE)) + { + RetValue |= GMAC_ERROR_TRANSMIT_UNAVAILABLE_STATUS; + } + + if (((RegValue & DMA_STATUS_TJT) == DMA_STATUS_TJT) && ((ErrIsr_RegValue & DMA_INTR_ENA_THE) == DMA_INTR_ENA_THE)) + { + RetValue |= GMAC_ERROR_TRANSMIT_JABBER_TIMEOUT; + } + + if (((RegValue & DMA_STATUS_OVF) == DMA_STATUS_OVF) && ((ErrIsr_RegValue & DMA_INTR_ENA_OVE) == DMA_INTR_ENA_OVE)) + { + RetValue |= GMAC_ERROR_RECEIVE_FIFO_OVERFLOW; + } + + if (((RegValue & DMA_STATUS_UNF) == DMA_STATUS_UNF) && ((ErrIsr_RegValue & DMA_INTR_ENA_UNE) == DMA_INTR_ENA_UNE)) + { + RetValue |= GMAC_ERROR_TRANSMIT_UNDERFLOW; + } + + if (((RegValue & DMA_STATUS_RU) == DMA_STATUS_RU) && ((ErrIsr_RegValue & DMA_INTR_ENA_RUE) == DMA_INTR_ENA_RUE)) + { + RetValue |= GMAC_ERROR_RECEIVE_BUFFER_UNAVAILABLE; + } + + if (((RegValue & DMA_STATUS_RPS) == DMA_STATUS_RPS) && ((ErrIsr_RegValue & DMA_INTR_ENA_RSE) == DMA_INTR_ENA_RSE)) + { + RetValue |= GMAC_ERROR_RECEIVE_PROCESS_STOPPED; + } + + if (((RegValue & DMA_STATUS_RWT) == DMA_STATUS_RWT) && ((ErrIsr_RegValue & DMA_INTR_ENA_RWE) == DMA_INTR_ENA_RWE)) + { + RetValue |= GMAC_ERROR_RECEIVE_WATCHDOG_TIMEOUT; + } + + if (((RegValue & DMA_STATUS_ETI) == DMA_STATUS_ETI) && ((ErrIsr_RegValue & DMA_INTR_ENA_ETE) == DMA_INTR_ENA_ETE)) + { + RetValue |= GMAC_ERROR_EARLY_TRANSMIT_INTERRUPT; + } + + if (((RegValue & DMA_STATUS_FBI) == DMA_STATUS_FBI) && ((ErrIsr_RegValue & DMA_INTR_ENA_FBE) == DMA_INTR_ENA_FBE)) + { + RetValue |= GMAC_ERROR_FATAL_BUS_ERROR; + } + + if (0U == RetValue) + { + RetValue |= GMAC_ERROR_UNDEFINED; + } + Ft_printf("error RetValue %x \r\n", RetValue); + return RetValue; +} + +/** + * @name: FGmac_IntrHandler + * @msg: + * @param {void} *Args + * @return {*} + */ +void FGmac_IntrHandler(void *Args) +{ + Ft_Gmac_t *Gmac; + u32 RegValue; + u32 MACRegValue; + Ft_assertVoid(Args != NULL); + Gmac = (Ft_Gmac_t *)Args; + + RegValue = Ft_in32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET); + if ((RegValue)&DMA_STATUS_GLI) + { + MACRegValue = Ft_in32(Gmac->Config.BaseAddress + GMAC_MAC_MAC_PHY_STATUS); + if (Gmac->StatusHandler) + { + Gmac->StatusHandler(Gmac->StatusArgs, MACRegValue); + } + } + + /* Frame received */ + if ((RegValue & (DMA_STATUS_RI)) != 0) + { + if (Gmac->RecvHandler) + { + Gmac->RecvHandler(Gmac->RecvArgs); + } + + Ft_out32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET, DMA_STATUS_RI); + } + else if ((RegValue & DMA_STATUS_TI) == DMA_STATUS_TI) + { + Ft_printf("DMA_STATUS_TI %x \r\n", RegValue); + Ft_printf("ti debug %x \r\n", Ft_in32(Gmac->Config.BaseAddress + GMAC_INTERNAL_MODULE_STATUS_OFFSET)); + // if (Gmac->SendHandler) + // Gmac->SendHandler(Gmac->SendArgs); + Ft_out32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET, DMA_STATUS_TI); + } + + Ft_out32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET, DMA_STATUS_NIS); + + /* DMA Error */ + if ((Ft_in32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET) & DMA_STATUS_AIS) == DMA_STATUS_AIS) + { + if (Gmac->ErrorHandler) + Gmac->ErrorHandler(Gmac->ErrorArgs, FGmac_ErrorCheck(Gmac)); + Ft_out32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET, Ft_in32(Gmac->Config.BaseAddress + DMA_STATUS_OFFSET)); + } +} diff --git a/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_sinit.c b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_sinit.c new file mode 100644 index 0000000000000000000000000000000000000000..852888143565d651a4ff3e53a45ddc49fee5e480 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gmac/ft_gmac_sinit.c @@ -0,0 +1,43 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-07 13:26:04 + * @Description:  This files is for gmac static init + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_gmac.h" +#include "ft_parameters.h" + +extern FGmac_Config_t Gmac_ConfigTable[FT_GMAC_INSTANCES_NUM]; + +/** + * @name: Ft_Gmac_LookupConfig + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + * @param {u32} InstanceId + */ +FGmac_Config_t *Ft_Gmac_LookupConfig(u32 InstanceId) +{ + FGmac_Config_t *CfgPtr = NULL; + u32 Index; + for (Index = 0; Index < (u32)FT_GMAC_INSTANCES_NUM; Index++) + { + if (Gmac_ConfigTable[Index].InstanceId == InstanceId) + { + CfgPtr = &Gmac_ConfigTable[Index]; + break; + } + } + + return (FGmac_Config_t *)CfgPtr; +} diff --git a/bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio.c b/bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio.c new file mode 100644 index 0000000000000000000000000000000000000000..0162a936c9a00eb92214bf48f930b840a0e433b1 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio.c @@ -0,0 +1,108 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-27 17:55:31 + * @LastEditTime: 2021-04-28 15:47:10 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_gpio.h" +#include "ft_gpio_hw.h" +#include "ft_assert.h" +#include "ft_debug.h" + +#define GPIO_MAX_PIN 7 +#define GPIO_MAX_CTRL_ID 1 + +void FGpio_SetGroupModeA(FT_IN u32 ctrlId, FT_IN u8 pin, FT_IN u32 mode) +{ + u32 RegVal; + Ft_assertNoneReturn(ctrlId <= GPIO_MAX_CTRL_ID); + Ft_assertNoneReturn(pin <= GPIO_MAX_PIN); + + RegVal = FGpioA_ReadReg(ctrlId, GPIO_INTEN); + switch(mode) + { + case GPIO_MODE_GPIO: + RegVal &= ~(1 << pin); + break; + case GPIO_MODE_INT: + RegVal |= (1 << pin); + break; + default: + Ft_assertNoneReturn(0); + break; + } + + FGpioA_WriteReg(ctrlId, GPIO_INTEN, RegVal); + return; +} + +static void FGpio_SetPinInOutA(FT_IN u32 ctrlId, FT_IN u8 pin, FT_IN u8 inOut) +{ + u32 RegVal; + Ft_assertNoneReturn(ctrlId <= GPIO_MAX_CTRL_ID); + Ft_assertNoneReturn(pin <= GPIO_MAX_PIN); + + RegVal = FGpioA_ReadReg(ctrlId, GPIO_SWPORTA_DDR); + if (inOut != (RegVal & (0x1 << pin))) + { + if (GPIO_INPUT == inOut) + { + RegVal &= ~(0x1 << pin); + } + else if (GPIO_OUTPUT == inOut) + { + RegVal |= (0x1 << pin); + } + else + { + Ft_assertNoneReturn(0); + } + + FGpioA_WriteReg(ctrlId, GPIO_SWPORTA_DDR, RegVal); + } + + return; +} + +u32 FGpio_ReadPinA(FT_IN u32 ctrlId, FT_IN u8 pin) +{ + u32 RegVal; + u32 OnOff; + Ft_assertNoneReturn(ctrlId <= GPIO_MAX_CTRL_ID); + Ft_assertNoneReturn(pin <= GPIO_MAX_PIN); + + FGpio_SetPinInOutA(ctrlId, pin, GPIO_INPUT); + RegVal = FGpioA_ReadReg(ctrlId, GPIO_EXT_PORTA); + OnOff = (RegVal & (0x1 << pin)) ? GPIO_ON : GPIO_OFF; + //FT_GPIO_DEBUG_I("ctrl %d, pin %d is %d", ctrlId, pin, OnOff); + return OnOff; +} + +void FGpio_WritePinA(FT_IN u32 ctrlId, FT_IN u8 pin, FT_IN u8 onOff) +{ + u32 RegVal; + Ft_assertNoneReturn(ctrlId <= GPIO_MAX_CTRL_ID); + Ft_assertNoneReturn(pin <= GPIO_MAX_PIN); + Ft_assertNoneReturn((onOff == GPIO_OFF) || (onOff == GPIO_ON)); + + FGpio_SetPinInOutA(ctrlId, pin, GPIO_OUTPUT); + RegVal = FGpioA_ReadReg(ctrlId, GPIO_SWPORTA_DR); + if (GPIO_OFF == onOff) + { + RegVal &= ~(1 << pin); + } + else + { + RegVal |= (1 << pin); + } + FGpioA_WriteReg(ctrlId, GPIO_SWPORTA_DR, RegVal); + return; +} \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio.h b/bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio.h new file mode 100644 index 0000000000000000000000000000000000000000..bef9b4883c3e480b30c4db817223e1d66150bcc5 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio.h @@ -0,0 +1,73 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-27 17:55:12 + * @LastEditTime: 2021-04-30 14:38:45 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef FT_BSP_GPIO_H +#define FT_BSP_GPIO_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ft_types.h" +#include "ft_gpio_hw.h" + +/* gpio mode: gpio/int */ +#define GPIO_MODE_GPIO 0 +#define GPIO_MODE_INT 1 + +/* define debug utilities */ +#define FT_GPIO_DEBUG_TAG "FT_GPIO" +#define FT_GPIO_ENABLE_DEBUG +#define FT_GPIO_ERROR(format, ...) FT_DEBUG_PRINT_E(FT_GPIO_DEBUG_TAG, format, ##__VA_ARGS__) +#ifdef FT_GPIO_ENABLE_DEBUG +#define FT_GPIO_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FT_GPIO_DEBUG_TAG, format, ##__VA_ARGS__) +#define FT_GPIO_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FT_GPIO_DEBUG_TAG, format, ##__VA_ARGS__) +#else +#define FT_GPIO_DEBUG_I(format, ...) +#define FT_GPIO_DEBUG_W(format, ...) +#endif + +/** + * @name: FGpio_SetGroupModeA + * @msg: set gpio mode, polling or intr + * @return {*} + * @param {FT_IN u32} ctrlId + * @param {FT_IN u8} pin + * @param {FT_IN u32} mode + */ +void FGpio_SetGroupModeA(FT_IN u32 CtrlId, FT_IN u8 Pin, FT_IN u32 Mode); +/** + * @name: FGpio_ReadPinA + * @msg: get gpio pin status + * @return {*} + * @param {FT_IN u32} ctrlId + * @param {FT_IN u8} pin + */ +u32 FGpio_ReadPinA(FT_IN u32 CtrlId, FT_IN u8 Pin); +/** + * @name: FGpio_WritePinA + * @msg: set gpio pin status + * @return {*} + * @param {FT_IN u32} ctrlId + * @param {FT_IN u8} pin + * @param {FT_IN u8} onOff + */ +void FGpio_WritePinA(FT_IN u32 CtrlId, FT_IN u8 Pin, FT_IN u8 OnOff); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio_hw.h b/bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio_hw.h new file mode 100644 index 0000000000000000000000000000000000000000..d8f52154581dec1bca3f9542856d469a97ac79f9 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_gpio/ft_gpio_hw.h @@ -0,0 +1,93 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-27 17:55:22 + * @LastEditTime: 2021-04-28 08:39:20 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef FT_BSP_GPIO_HW_H +#define FT_BSP_GPIO_HW_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ft_types.h" +#include "ft_io.h" + +#define GPIO_CTRL_ID_0 0 +#define GPIO_CTRL_ID_1 1 + +/* base address of gpio register */ +#define GPIO_CTRL0_PA_BASE 0x28004000 +#define GPIO_CTRL1_PA_BASE 0x28005000 +#define GPIO_GROUPA_OFFSET 0x0 +#define GPIO_GROUPB_OFFSET 0xc + +/* offset of register map */ +#define GPIO_SWPORTA_DR 0x00 //A 组端口输出寄存器 +#define GPIO_SWPORTA_DDR 0x04 //A 组端口方向控制寄存器 +#define GPIO_EXT_PORTA 0x08 //A 组端口输入寄存器 + +#define GPIO_SWPORTB_DR 0x0c //B 组端口输出寄存器 +#define GPIO_SWPORTB_DDR 0x10 //B 组端口方向控制寄存器 +#define GPIO_EXT_PORTB 0x14 //B 组端口输入寄存器 + +#define GPIO_INTEN 0x18 //A 组端口中断使能寄存器 +#define GPIO_INTMASK 0x1c //A 组端口中断屏蔽寄存器 +#define GPIO_INTTYPE_LEVEL 0x20 //A 组端口中断等级寄存器 +#define GPIO_INT_POLARITY 0x24 //A 组端口中断极性寄存器 +#define GPIO_INTSTATUS 0x28 //A 组端口中断状态寄存器 +#define GPIO_RAW_INTSTATUS 0x2c //A 组端口原始中断状态寄存器 + +#define GPIO_LS_SYNC 0x30 //配置中断同步寄存器 +#define GPIO_DEBOUNCE 0x34 //防反跳配置寄存器 +#define GPIO_PORTA_EOI 0x38 //A 组端口中断清除寄存器 + +/* misc marco */ +#define GPIO_GROUP_A 0 +#define GPIO_OFF 0 +#define GPIO_ON 1 +#define GPIO_INPUT 0 +#define GPIO_OUTPUT 1 + +inline static u32 FGpio_GetBaseAddr(FT_IN u32 ctrlId, FT_IN u32 groupId) +{ + static const u32 CtrlAddr[2] = {GPIO_CTRL0_PA_BASE, GPIO_CTRL1_PA_BASE}; + static const u32 GroupOff[2] = {GPIO_GROUPA_OFFSET, GPIO_GROUPB_OFFSET}; + return CtrlAddr[ctrlId] + GroupOff[groupId]; +} + +/** + * @name: FGpio_WriteReg + * @msg: write gpio register + * @param {u32} BaseAddress base addr of i2c + * @param {u32} RegOffset addr offset of i2c register + * @param {u32} RegisterValue val to be write into register + * @return {void} + */ +#define FGpioA_WriteReg(ctrlId, RegOffset, RegisterValue) Ft_out32(FGpio_GetBaseAddr(ctrlId, GPIO_GROUP_A) + (u32)RegOffset, (u32)RegisterValue) + +/** + * @name: FGpio_ReadReg + * @msg: read gpio register + * @param {u32} BaseAddress base addr of i2c + * @param {u32} RegOffset addr offset of i2c register + * @return {u32} val read from register + */ +#define FGpioA_ReadReg(ctrlId, RegOffset) Ft_in32(FGpio_GetBaseAddr(ctrlId, GPIO_GROUP_A) + (u32)RegOffset) + + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c.c b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c.c new file mode 100644 index 0000000000000000000000000000000000000000..2fe11534a2868ba1527b5a85d49c67706e3395da --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c.c @@ -0,0 +1,516 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-27 15:46:38 + * @Description:  This files is for i2c user interface + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include +#include +#include "ft_mux.h" +#include "ft_i2c_hw.h" +#include "ft_i2c.h" +#include "ft_generic_timer.h" + +/* reset val of register */ +#define I2C_CON_DEFAULT 0x7F +#define I2C_TAR_DEFAULT 0x1055 +#define I2C_SAR_DEFAULT 0x55 +#define I2C_DATA_CMD_DEFAULT 0x0 +#define I2C_SS_SCL_LCNT_DEFAULT 0x1D6 +#define I2C_SS_SCL_HCNT_DEFAULT 0x190 +#define I2C_FS_SCL_LCNT_DEFAULT 0x82 +#define I2C_FS_SCL_HCNT_DEFAULT 0x3C +#define I2C_HS_SCL_LCNT_DEFAULT 0x10 +#define I2C_HS_SCL_HCNT_DEFAULT 0x6 +#define I2C_INTR_MASK_DEFAULT 0x8FF +//#define I2C_RX_TL_DEFAULT 0x0 +//#define I2C_TX_TL_DEFAULT 0x0 +#define I2C_SCL_HCNT_DEFAULT 0x2f +#define I2C_SCL_LCNT_DEFAULT 0x2f +//#define I2C_RX_TL_SET 0xff +//#define I2C_TX_TL_SET 0xff + +#define I2C_RX_TL_BY_BYTE 0x0 +#define I2C_TX_TL_BY_BYTE 0x0 +#define I2C_RX_TL_BY_FIFO 0x01 +#define I2C_TX_TL_BY_FIFO 0x01 + +LOCAL const u32 g_I2cSpeedMask[MAX_I2C_SPEED] = {I2C_STANDARD_SPEED_MASK, + I2C_FAST_SPEED_MASK, + I2C_HIGH_SPEED_MASK}; +LOCAL const u32 g_I2cSclLcntReg[MAX_I2C_SPEED] = {I2C_SS_SCL_LCNT, + I2C_FS_SCL_LCNT, I2C_HS_SCL_LCNT}; +LOCAL const u32 g_I2cSclHcntReg[MAX_I2C_SPEED] = {I2C_SS_SCL_HCNT, + I2C_FS_SCL_LCNT, I2C_HS_SCL_LCNT}; + +void FI2C_resetReg(u32 BaseAddr) +{ + /* set default value for register */ + FI2C_WriteReg(BaseAddr, I2C_CON, I2C_CON_DEFAULT); + FI2C_WriteReg(BaseAddr, I2C_TAR, I2C_TAR_DEFAULT); + FI2C_WriteReg(BaseAddr, I2C_SAR, I2C_SAR_DEFAULT); + FI2C_WriteReg(BaseAddr, I2C_DATA_CMD, I2C_DATA_CMD_DEFAULT); + FI2C_WriteReg(BaseAddr, I2C_SS_SCL_LCNT, I2C_SS_SCL_LCNT_DEFAULT); + FI2C_WriteReg(BaseAddr, I2C_SS_SCL_HCNT, I2C_SS_SCL_HCNT_DEFAULT); + FI2C_WriteReg(BaseAddr, I2C_FS_SCL_LCNT, I2C_FS_SCL_LCNT_DEFAULT); + FI2C_WriteReg(BaseAddr, I2C_FS_SCL_HCNT, I2C_FS_SCL_HCNT_DEFAULT); + FI2C_WriteReg(BaseAddr, I2C_HS_SCL_LCNT, I2C_HS_SCL_LCNT_DEFAULT); + FI2C_WriteReg(BaseAddr, I2C_HS_SCL_HCNT, I2C_HS_SCL_HCNT_DEFAULT); + FI2C_WriteReg(BaseAddr, I2C_INTR_MASK, I2C_INTR_MASK_DEFAULT); + FI2C_WriteReg(BaseAddr, I2C_RX_TL, I2C_RX_TL_DEFAULT); + FI2C_WriteReg(BaseAddr, I2C_TX_TL, I2C_TX_TL_DEFAULT); +} + +inline LOCAL void FI2C_setSclClk(FT_IN u32 BaseAddr, FT_IN FI2C_SpeedType_t SpeedType, + FT_IN u32 SclLcnt, FT_IN u32 SclHcnt) +{ + u32 SclLcntAddr = g_I2cSclLcntReg[SpeedType]; + u32 SclHcntAddr = g_I2cSclHcntReg[SpeedType]; + + FI2C_WriteReg(BaseAddr, SclLcntAddr, SclLcnt); + FI2C_WriteReg(BaseAddr, SclHcntAddr, SclHcnt); + + return; +} + +inline LOCAL void FI2C_setCtrlParam(FT_IN u32 BaseAddr, FT_IN FI2C_SpeedType_t SpeedType, FT_IN bool_t Is7BitAddr) +{ + u32 RegVal; + + RegVal = I2C_CON_ME | g_I2cSpeedMask[SpeedType]; + RegVal |= ((TRUE == Is7BitAddr) ? I2C_CON_MASTER_ADR_7BIT : I2C_CON_MASTER_ADR_10BIT); + RegVal |= I2C_CON_RESTART_EN | I2C_CON_SLAVE_DISABLE; + + FI2C_WriteReg(BaseAddr, I2C_CON, RegVal); + return; +} + +void FI2C_initMasterCfg(FT_IN FI2C_Instance_t id, + FT_IN FI2C_WorkMode_t mode, + FT_IN bool_t UseWRFifo, + FT_IN u32 PageSize, + FT_INOUT FI2C_Config_t *pCfg) +{ + Ft_assertNoneReturn(NULL != pCfg); + + pCfg->InstanceId = id; + pCfg->BaseAddress = g_FI2cRegBaseAddr[id]; + pCfg->IrqNum = g_FI2cIrqNum[id]; + pCfg->IrqPriority = I2C_DEFAULT_IRQ_PRIORITY; + pCfg->BusSpeed = I2C_STANDARD_SPEED; + pCfg->SclLcnt = I2C_SCL_LCNT_DEFAULT; + pCfg->SclHcnt = I2C_SCL_HCNT_DEFAULT; + pCfg->WRByFifo = UseWRFifo; + if (TRUE == pCfg->WRByFifo) + { + pCfg->RxThres = I2C_RX_TL_BY_FIFO; + pCfg->TxThres = I2C_TX_TL_BY_FIFO; + } + else + { + pCfg->RxThres = I2C_RX_TL_BY_BYTE; + pCfg->TxThres = I2C_TX_TL_BY_BYTE; + } + pCfg->Is7BitAddr = TRUE; + pCfg->BlockSize = PageSize; + + if (I2C_POLLING_MODE == mode) + { + pCfg->IsPolling = TRUE; + } + else if (I2C_IRQ_MODE == mode) + { + pCfg->IsPolling = FALSE; + } + else + { + Ft_assertNoneReturn(0); + } + + return; +} + +void FI2C_initMaster(FT_IN FI2C_Instance_t id, + FT_IN FI2C_WorkMode_t mode, + FT_IN u32 SlaveAddr, + FT_IN bool_t UseWRFifo, + FT_IN u32 PageSize, + FT_INOUT FI2C_t *pDev) +{ + u32 RxDepth; + u32 TxDepth; + + Ft_assertNoneReturn(NULL != pDev); + + memset(pDev, 0, sizeof(FI2C_t)); + + /* setup i2c bus mux */ + Ft_setI2cMux(id); + + /* setup i2c config as master */ + FI2C_initMasterCfg(id, mode, UseWRFifo, PageSize, &pDev->Config); + pDev->SlaveAddr = SlaveAddr; + pDev->DelayHandle = Ft_GenericTimer_UsDelay; + + /* init irq handler */ + pDev->pRxEvent = NULL; + pDev->pTxEvent = NULL; + + pDev->pIrqCallBack = NULL; + pDev->pWaitCallBack = NULL; + + FI2C_DISABLE_I2C_BUS(pDev); + FI2C_CLR_ALL_IRQ_STATUS(pDev); + + /* reset reg val */ + FI2C_resetReg(pDev->Config.BaseAddress); + + /* set scl high && low level */ + FI2C_setSclClk(pDev->Config.BaseAddress, + pDev->Config.BusSpeed, + pDev->Config.SclLcnt, + pDev->Config.SclHcnt); + + /* set ctrl parameters */ + FI2C_setCtrlParam(pDev->Config.BaseAddress, + pDev->Config.BusSpeed, + pDev->Config.Is7BitAddr); + + /* set rx & tx trigger level */ + RxDepth = FI2C_GET_RX_BUFFER_DEPTH(pDev); + TxDepth = FI2C_GET_TX_BUFFER_DEPTH(pDev); + + /* threshold shall not greater than depth */ + // FT_I2C_DEBUG_I("set rx thres 0x%x, tx thres 0x%x", + // FT_MIN(pDev->Config.RxThres, RxDepth), + // FT_MIN(pDev->Config.TxThres, TxDepth)); + FI2C_SET_TX_TL(pDev, FT_MIN(pDev->Config.TxThres, TxDepth)); + FI2C_SET_RX_TL(pDev, FT_MIN(pDev->Config.RxThres, RxDepth)); + pDev->IsReady = TRUE; + return; +} + +void FI2C_deInitMaster(FT_INOUT FI2C_t *pDev) +{ + /* assert no memory need to release */ + pDev->IsReady = FALSE; +} + +inline LOCAL void FI2C_sendRestartCmd(FT_IN u32 BaseAddr) +{ + u32 RegVal = FI2C_ReadReg(BaseAddr, I2C_CON); + RegVal |= I2C_CON_RESTART_EN; + FI2C_WriteReg(BaseAddr, I2C_CON, RegVal); +} + +inline LOCAL void FI2C_setTarAddr(FT_IN u32 BaseAddr, FT_IN u32 SlaveAddr) +{ + u32 RegVal = (SlaveAddr & I2C_TAR_ADR_MASK); + FI2C_WriteReg(BaseAddr, I2C_TAR, RegVal); +} + +inline LOCAL void FI2C_sendWriteCmd(FT_IN u32 BaseAddr, FT_IN u32 PageAddr) +{ + u32 RegVal = I2C_DATA_CMD_RESTART | (PageAddr & I2C_DATA_CMD_DAT_MASK); + FI2C_WriteReg(BaseAddr, I2C_DATA_CMD, RegVal); +} + +inline LOCAL void FI2C_sendStartReadCmd(FT_IN u32 BaseAddr, FT_IN u32 PageAddr) +{ + /* send read cmd */ + u32 RegVal = I2C_DATA_CMD_STOP | I2C_DATA_CMD_RESTART | (PageAddr & 0xff); + FI2C_WriteReg(BaseAddr, I2C_DATA_CMD, RegVal); +} + +void FI2C_sendStopCmd(FT_IN u32 BaseAddr) +{ + /* send stop signal */ + u32 RegVal = I2C_DATA_CMD_STOP; + FI2C_WriteReg(BaseAddr, I2C_DATA_CMD, RegVal); +} + +LOCAL bool_t FI2C_blockWaitForStatus(FT_IN u32 stMask, FT_INOUT FI2C_t *pDev) +{ + u32 timeout = 0; + bool_t IsFree = FALSE; + + Ft_assertNoneReturn(NULL != pDev); + + /* Wait until Specific Status Bit in I2C_STATUS is 1 */ + while ((!FI2C_CHECK_STATUS(pDev, stMask)) && (timeout < I2C_TIMEOUT)) + { + pDev->DelayHandle(5000); + timeout++; + } + + /* check if status wait successful or timeout */ + if (I2C_TIMEOUT != timeout) + { + IsFree = TRUE; + } + else + { + FT_I2C_ERROR("wait status 0x%x failed!!! reg val is 0x%x", + stMask, FI2C_GET_STATUS(pDev)); + } + + return IsFree; +} + +u32 FI2C_writeByByte(FT_IN u32 len, FT_IN u8 *pI2cBuf, FT_IN u8 PageAddr, FT_INOUT FI2C_t *pDev) +{ + u32 loop; + bool_t isNotTimeout; + u32 ret = ERR_I2C_OK; + Ft_assertNoneReturn((NULL != pDev) && (NULL != pI2cBuf)); + + if (!pDev->IsReady) + { + return ERR_I2C_NOT_READY; + } + + if (pDev->Config.BlockSize <= len) + { + return ERR_I2C_SIZE_TOO_LARGE; + } + + FI2C_DISABLE_I2C_BUS(pDev); + FI2C_sendRestartCmd(pDev->Config.BaseAddress); + FI2C_setTarAddr(pDev->Config.BaseAddress, pDev->SlaveAddr); + FI2C_ENABLE_I2C_BUS(pDev); + + // FT_I2C_DEBUG_I("get rx thres 0x%x, tx thres 0x%x", + // FI2C_GET_TXFLR(pDev), + // FI2C_GET_RXFLR(pDev)); + + FI2C_sendWriteCmd(pDev->Config.BaseAddress, PageAddr); + + for (loop = 0; loop < len; loop++) + { + if (!pDev->Config.IsPolling) + { + FI2C_setIrq(pDev, I2C_IRQ_TX_EMPTY, TRUE); + } + pDev->DelayHandle(2); + FI2C_SET_TX_DATA(pDev, pI2cBuf[loop]); + + /* wait until TX fifo is empty */ + if (pDev->Config.IsPolling) + { + isNotTimeout = FI2C_blockWaitForStatus(I2C_STATUS_TFE, pDev); + if (!isNotTimeout) + { + ret = ERR_I2C_WRITE_TIMEOUT; + goto EXIT; + } + } + else + { + pDev->LastIrqErr = ERR_I2C_OK; + if (pDev->pWaitCallBack) + { + pDev->pWaitCallBack(I2C_IRQ_TYPE_TX_COMPLETE, pDev); + } + else + { + ret = ERR_I2C_INVALID_HANDLER; + goto EXIT; + } + + if (ERR_I2C_OK != pDev->LastIrqErr) + { + ret = pDev->LastIrqErr; + goto EXIT; + } + } + + pDev->DelayHandle(2); + } + +EXIT: + FI2C_SEND_TX_STOP_CMD(pDev); + pDev->DelayHandle(2); + + return ret; +} + +u32 FI2C_readByByte(FT_IN u32 len, FT_OUT u8 *pI2cBuf, FT_IN u8 PageAddr, FT_INOUT FI2C_t *pDev) +{ + u32 loop; + bool_t isNotTimeout; + u32 ret = ERR_I2C_OK; + Ft_assertNoneReturn((NULL != pDev) && (NULL != pI2cBuf)); + + if (!pDev->IsReady) + { + return ERR_I2C_NOT_READY; + } + + FI2C_DISABLE_I2C_BUS(pDev); + FI2C_sendRestartCmd(pDev->Config.BaseAddress); + FI2C_CLR_ALL_IRQ_STATUS(pDev); + FI2C_setTarAddr(pDev->Config.BaseAddress, pDev->SlaveAddr); + FI2C_ENABLE_I2C_BUS(pDev); + + /* assign page addr when start read */ + FI2C_sendStartReadCmd(pDev->Config.BaseAddress, PageAddr); + + /* read contents */ + for (loop = 0; loop < len; loop++) + { + if (!pDev->Config.IsPolling) + { + FI2C_setIrq(pDev, I2C_IRQ_RX_FULL, TRUE); + } + + FI2C_SEND_RX_NEXT_CMD(pDev); + pDev->DelayHandle(2); + + /* wait until data reach and start fetch data */ + if (pDev->Config.IsPolling) + { + isNotTimeout = FI2C_blockWaitForStatus(I2C_STATUS_RFNE, pDev); + if (!isNotTimeout) + { + ret = ERR_I2C_READ_TIMEOUT; + goto EXIT; + } + } + else + { + pDev->LastIrqErr = ERR_I2C_OK; + if (pDev->pWaitCallBack) + { + pDev->pWaitCallBack(I2C_IRQ_TYPE_RX_COMPLETE, pDev); + } + else + { + ret = ERR_I2C_INVALID_HANDLER; + goto EXIT; + } + + if (ERR_I2C_OK != pDev->LastIrqErr) + { + ret = pDev->LastIrqErr; + goto EXIT; + } + } + + pI2cBuf[loop] = FI2C_GET_RX_DATA(pDev); + pDev->DelayHandle(2); + } + +EXIT: + FI2C_SEND_RX_STOP_CMD(pDev); + pDev->DelayHandle(2); + return ret; +} + +u32 FI2C_writeByFifo(FT_IN u8 PageAddr, FT_INOUT FI2C_t *pDev) +{ + u32 loop; + u32 ret = ERR_I2C_OK; + u32 timeout = I2C_TIMEOUT / 10; + Ft_assertNoneReturn(NULL != pDev); + + if (!pDev->IsReady) + { + return ERR_I2C_NOT_READY; + } + + if (pDev->Config.IsPolling) + { + return ERR_I2C_NOT_SUPPORT; + } + + FI2C_DISABLE_I2C_BUS(pDev); + FI2C_sendRestartCmd(pDev->Config.BaseAddress); + FI2C_setTarAddr(pDev->Config.BaseAddress, pDev->SlaveAddr); + FI2C_ENABLE_I2C_BUS(pDev); + + FI2C_sendWriteCmd(pDev->Config.BaseAddress, PageAddr); + + /* enable TX Empty, disable Rx Full */ + FI2C_setIrq(pDev, I2C_IRQ_TX_EMPTY, TRUE); + FI2C_setIrq(pDev, I2C_IRQ_RX_FULL, FALSE); + + pDev->LastIrqErr = ERR_I2C_OK; + if (pDev->pWaitCallBack) + { + pDev->pWaitCallBack(I2C_IRQ_TYPE_TX_COMPLETE, pDev); + } + else + { + ret = ERR_I2C_INVALID_HANDLER; + } + + if (ERR_I2C_OK != pDev->LastIrqErr) + { + ret = pDev->LastIrqErr; + } + + return ret; +} + +u32 FI2C_readByFifo(FT_IN u8 PageAddr, FT_INOUT FI2C_t *pDev) +{ + u32 loop; + u32 ret = ERR_I2C_OK; + u32 timeout = I2C_TIMEOUT / 10; + Ft_assertNoneReturn((NULL != pDev)); + + if (!pDev->IsReady) + { + return ERR_I2C_NOT_READY; + } + + if (pDev->Config.IsPolling) + { + return ERR_I2C_NOT_SUPPORT; + } + + FI2C_DISABLE_I2C_BUS(pDev); + FI2C_sendRestartCmd(pDev->Config.BaseAddress); + FI2C_setTarAddr(pDev->Config.BaseAddress, pDev->SlaveAddr); + FI2C_ENABLE_I2C_BUS(pDev); + + /* assign page addr when start read */ + FI2C_sendStartReadCmd(pDev->Config.BaseAddress, PageAddr); + + FI2C_setIrq(pDev, I2C_IRQ_RX_FULL, TRUE); + FI2C_setIrq(pDev, I2C_IRQ_TX_EMPTY, FALSE); + FI2C_SET_RX_TL(pDev, 1); + //FT_MIN(pDev->RxBuf.DataLength, FI2C_GET_RX_BUFFER_DEPTH(pDev))); + pDev->DelayHandle(2); + FT_I2C_DEBUG_I("rx tl is 0x%x irq mask 0x%x", + FI2C_GET_RX_TL(pDev), + FI2C_getIrqMask(pDev)); + + FI2C_SEND_RX_NEXT_CMD(pDev); + pDev->DelayHandle(2); + + pDev->LastIrqErr = ERR_I2C_OK; + if (pDev->pWaitCallBack) + { + pDev->pWaitCallBack(I2C_IRQ_TYPE_RX_COMPLETE, pDev); + } + else + { + ret = ERR_I2C_INVALID_HANDLER; + } + + if (ERR_I2C_OK != pDev->LastIrqErr) + { + ret = pDev->LastIrqErr; + } + FI2C_SET_RX_TL(pDev, 0); + return ret; +} \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c.h b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c.h new file mode 100644 index 0000000000000000000000000000000000000000..290e15aa24e14586eec3d3749f02f3208fdc5082 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c.h @@ -0,0 +1,201 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-07 13:32:20 + * @Description:  This files is for i2c user interface + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + + +#ifndef FT_BSP_I2C_H +#define FT_BSP_I2C_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ft_types.h" +#include "ft_debug.h" +#include "ft_assert.h" +#include "ft_error_code.h" +#include "ft_i2c_hw.h" + +/* I2C Ctrl instance */ +typedef enum +{ + I2C_CTRL_ID_0 = 0, + I2C_CTRL_ID_1, + I2C_CTRL_ID_2, + I2C_CTRL_ID_3, + + MAX_I2C_CTRL_ID, +} FI2C_Instance_t; + +static const u32 g_FI2cIrqNum[MAX_I2C_CTRL_ID] = { + 44, 45, 46, 47 +}; + +static const u32 g_FI2cRegBaseAddr[MAX_I2C_CTRL_ID] = { + I2C0_BASE_ADDRESS, I2C1_BASE_ADDRESS, + I2C2_BASE_ADDRESS, I2C3_BASE_ADDRESS +}; + +#define I2C_DEFAULT_IRQ_PRIORITY 0 + +/* Type of I2C device */ +typedef enum +{ + I2C_MASTER_DEV = 0, + I2C_SLAVE_DEV, + + MAX_I2C_DEV +} FI2C_DevType_t; + +/* I2C work mode type */ +typedef enum +{ + I2C_POLLING_MODE = 0, + I2C_IRQ_MODE, + + MAX_I2C_WORKMODE +} FI2C_WorkMode_t; + +/* Type of I2C bus speed */ +typedef enum +{ + I2C_STANDARD_SPEED = 0, + I2C_FAST_SPEED, + I2C_HIGH_SPEED, + + MAX_I2C_SPEED, +} FI2C_SpeedType_t; + +/* I2C error code Submodule */ +typedef enum +{ + I2C_ERR_MODE_DEF = 0, + + MAX_I2C_ERR_MODE, +} FI2C_Submodule_t; + +/* I2C irq type */ +typedef enum +{ + I2C_IRQ_TYPE_NONE = 0, + I2C_IRQ_TYPE_TX_COMPLETE, + I2C_IRQ_TYPE_RX_COMPLETE, + + MAX_I2C_IRQ_TYPE +} +FI2C_IrqType_t; + +/* I2C config info */ +typedef struct +{ + FI2C_Instance_t InstanceId;/* Id of I2C ctrl instance */ + u32 BaseAddress; /* base address of I2C register */ + FI2C_DevType_t WorkMode; /* work as master or slave */ + FI2C_SpeedType_t BusSpeed; /* bus speed setting */ + u32 SclLcnt; + u32 SclHcnt; + u32 RxThres; + u32 TxThres; + bool_t Is7BitAddr; /* TRUE: use 7 bit addr, FALSE: use 10 bit addr */ + bool_t IsPolling; /* is polling */ + u32 IrqNum; /* irq num of I2C in system */ + u32 IrqPriority; /* irq priority */ + u32 BlockSize; /* block size, for eeprom */ + bool_t WRByFifo; +} FI2C_Config_t; + +/* I2C RX/TX buffer */ +typedef struct +{ + u8 *BytePtr; + u32 TotalBytes; + u32 DataLength; + u32 CurIndex; +} FI2C_Buffer_t; + +typedef void (*FI2C_IrqCallBackHandler_t)(FT_IN u32 IrqType, + FT_INOUT void *pDev, + FT_INOUT void *pArg); +typedef void (*FI2C_IrqWaitHandler_t)(FT_IN u32 IrqType, + FT_INOUT void *pDev); +typedef int32_t (*FI2C_DelayHandler_t)(FT_IN u32); + +/* I2C device info */ +typedef struct +{ + FI2C_Config_t Config; /* Configuration data structure */ + + void *pRxEvent; + void *pTxEvent; + FI2C_IrqCallBackHandler_t pIrqCallBack; + FI2C_IrqWaitHandler_t pWaitCallBack; + u32 LastIrqErr; + FI2C_Buffer_t RxBuf; + FI2C_Buffer_t TxBuf; + + FI2C_DelayHandler_t DelayHandle; + bool_t IsReady; /* Device is ininitialized and ready*/ + u16 SlaveAddr; /* address of I2C slave device for master */ +} FI2C_t; + +void FI2C_initMaster(FT_IN FI2C_Instance_t id, + FT_IN FI2C_WorkMode_t mode, + FT_IN u32 SlaveAddr, + FT_IN bool_t UseWRFifo, + FT_IN u32 PageSize, + FT_INOUT FI2C_t *pDev); +u32 FI2C_writeByByte(FT_IN u32 len, FT_IN u8 *pI2cBuf, FT_IN u8 PageAddr, + FT_INOUT FI2C_t *pDev); +u32 FI2C_readByByte(FT_IN u32 len, FT_OUT u8 *pI2cBuf, FT_IN u8 PageAddr, + FT_INOUT FI2C_t *pDev); +u32 FI2C_setIrqHandler(FT_IN FI2C_IrqType_t IrqType, FT_IN FI2C_DelayHandler_t pHandler, FT_IN void *pArgs, + FT_INOUT FI2C_t *pDev); +void FI2C_irqHandler(void *pArgs); +void FI2C_irqHandler4Fifo(void *pArgs); +u32 FI2C_getIrqMask(FT_IN FI2C_t *pDev); +void FI2C_setIrqMask(FT_IN FI2C_t *pDev, FT_IN u32 mask); +void FI2C_setIrq(FT_IN FI2C_t *pDev, FT_IN u32 maskBit, FT_IN bool_t enable); +bool_t FI2C_checkIfIntr(FT_IN FI2C_t *pDev); +u32 FI2C_writeByFifo(FT_IN u8 PageAddr, FT_INOUT FI2C_t *pDev); +u32 FI2C_readByFifo(FT_IN u8 PageAddr, FT_INOUT FI2C_t *pDev); +void FI2C_deInitMaster(FT_INOUT FI2C_t *pDev); + +#define FT_I2C_DEBUG_TAG "FT_I2C" +//#define FT_I2C_ENABLE_DEBUG +#define FT_I2C_ERROR(format, ...) FT_DEBUG_PRINT_E(FT_I2C_DEBUG_TAG, format, ##__VA_ARGS__) +#ifdef FT_I2C_ENABLE_DEBUG +#define FT_I2C_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FT_I2C_DEBUG_TAG, format, ##__VA_ARGS__) +#define FT_I2C_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FT_I2C_DEBUG_TAG, format, ##__VA_ARGS__) +#else +#define FT_I2C_DEBUG_I(format, ...) +#define FT_I2C_DEBUG_W(format, ...) +#endif + +#define ERR_I2C_OK ERR_SUCCESS +#define ERR_I2C_NOT_READY FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 1) +#define ERR_I2C_WRITE_TIMEOUT FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 2) +#define ERR_I2C_READ_TIMEOUT FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 3) +#define ERR_I2C_SIZE_TOO_LARGE FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 4) +#define ERR_I2C_NOT_SUPPORT FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 5) +#define ERR_I2C_INVALID_PARAM FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 6) +#define ERR_I2C_INVALID_HANDLER FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 7) +#define ERR_I2C_INVALID_NO_MEM FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 8) +#define ERR_I2C_BUS_NOT_ENABLED FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 9) +#define ERR_I2C_EVT_TIMEOUT FT_CODE_ERR(errModeI2c, I2C_ERR_MODE_DEF, 0xA) + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_g.c b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_g.c new file mode 100644 index 0000000000000000000000000000000000000000..3d6c929641e77a1f750e3d50f2684ac444de2e8a --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_g.c @@ -0,0 +1,13 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-20 15:35:23 + * @LastEditTime: 2021-04-20 15:35:24 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ diff --git a/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_hw.h b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_hw.h new file mode 100644 index 0000000000000000000000000000000000000000..99a767fd8a494ff43f79c5f6fa63baf32e433442 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_hw.h @@ -0,0 +1,322 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-07 13:26:58 + * @Description:  This files is for i2c register definition + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + + +#ifndef FT_BSP_I2C_HW_H +#define FT_BSP_I2C_HW_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ft_types.h" +#include "ft_io.h" + +/* i2c 1~4 reg base address */ +#define I2C0_BASE_ADDRESS 0x28006000U +#define I2C1_BASE_ADDRESS 0x28007000U +#define I2C2_BASE_ADDRESS 0x28008000U +#define I2C3_BASE_ADDRESS 0x28009000U + +/* defines */ +#define I2C_TIMEOUT 5000 + +#define I2C_MAX_READ_SIZE 1 +#define SEM_TIMEOUT 2 + + /* Register Definition */ + +#define I2C_CON 0x00 +#define I2C_TAR 0x04 +#define I2C_SAR 0x08 +#define I2C_HS_MADDR 0x0C +#define I2C_DATA_CMD 0x10 +#define I2C_SS_SCL_HCNT 0x14 +#define I2C_SS_SCL_LCNT 0x18 +#define I2C_FS_SCL_HCNT 0x1C +#define I2C_FS_SCL_LCNT 0x20 +#define I2C_HS_SCL_HCNT 0x24 +#define I2C_HS_SCL_LCNT 0x28 +#define I2C_INTR_STAT 0x2C +#define I2C_INTR_MASK 0x30 +#define I2C_RAW_INTR_STAT 0x34 +#define I2C_RX_TL 0x38 +#define I2C_TX_TL 0x3C +#define I2C_CLR_INTR 0x40 +#define I2C_CLR_RX_UNDER 0x44 +#define I2C_CLR_RX_OVER 0x48 +#define I2C_CLR_TX_OVER 0x4C +#define I2C_CLR_RD_REQ 0x50 +#define I2C_CLR_TX_ABRT 0x54 +#define I2C_CLR_RX_DONE 0x58 +#define I2C_CLR_ACTIVITY 0x5c +#define I2C_CLR_STOP_DET 0x60 +#define I2C_CLR_START_DET 0x64 +#define I2C_CLR_GEN_CALL 0x68 +#define I2C_ENABLE 0x6C +#define I2C_STATUS 0x70 +#define I2C_TXFLR 0x74 +#define I2C_RXFLR 0x78 +#define I2C_TX_ABRT_SOURCE 0x80 +#define I2C_SLV_DATA_NACK_ONLY 0x84 +#define I2C_DMA_CR 0x88 +#define I2C_DMA_TDLR 0x8c +#define I2C_DMA_RDLR 0x90 +#define I2C_SDA_SETUP 0x94 +#define I2C_ACK_GENERAL_CALL 0x98 +#define I2C_ENABLE_STATUS 0x9C +#define I2C_COMP_PARAM_1 0xf4 +#define I2C_COMP_VERSION 0xf8 +#define I2C_COMP_TYPE 0xfc + +#define I2C_RAW_INTR_STAT_RX_UNDER 0x1 +#define I2C_RAW_INTR_STAT_RX_OVER 0x2 +#define I2C_RAW_INTR_STAT_RX_FULL 0x4 +#define I2C_RAW_INTR_STAT_TX_OVER 0x8 +#define I2C_RAW_INTR_STAT_TX_EMPTY 0x10 + + /* Default parameters */ + +#define I2C_CON_ME (0x1 << 0) +#define I2C_CON_MS_SS (0x1 << 1) +#define I2C_CON_MS_FS (0x2 << 1) +#define I2C_CON_MS_HS (0x3 << 1) +#define I2C_CON_SLAVE_ADR_7BIT (0x0 << 3) +#define I2C_CON_SLAVE_ADR_10BIT (0x1 << 3) +#define I2C_CON_MASTER_ADR_7BIT (0x0 << 4) +#define I2C_CON_MASTER_ADR_10BIT (0x1 << 4) +#define I2C_CON_RESTART_EN (0x1 << 5) +#define I2C_CON_SLAVE_DISABLE (0x1 << 6) + +/* 0110 0011 0x63 */ +#define I2C_CON_DEFAULT_MASTER (I2C_CON_ME | I2C_CON_MS_FS /*I2C_CON_MS_SS*/ /* | I2C_CON_RESTART_EN*/ | \ + I2C_CON_SLAVE_ADR_7BIT | I2C_CON_SLAVE_DISABLE) +#define I2C_CTR_DEFAULT (I2C_CON_ME | I2C_CON_MASTER_ADR_7BIT | \ + I2C_CON_SLAVE_DISABLE) + +#define I2C_IRQ_NONE_MASK 0x0 +#define I2C_IRQ_ALL_MASK 0x8ff + +#define I2C_TAR_STARTBYTE (0x1 << 10) +#define I2C_TAR_SPECIAL_STARTBYTE (0x1 << 11) +#define I2C_TAR_ADR_7BIT (0x0 << 12) +#define I2C_TAR_ADR_10BIT (0x1 << 12) +#define I2C_TAR_ADR_MASK 0x3ff /* bit [9: 0] */ + +#define I2C_SLAVE_DISABLE_DEFAULT 0 +#define I2C_RESTART_EN_DEFAULT 1 +#define I2C_10BITADDR_MASTER_DEFAULT 0 +#define I2C_10BITADDR_SLAVE_DEFAULT 1 +#define I2C_MAX_SPEED_MODE_DEFAULT 3 +#define I2C_MASTER_MODE_DEFAULT 1 + +#define I2C_STANDARD_SPEED_MASK (0x01 << 1) +#define I2C_FAST_SPEED_MASK (0x02 << 1) +#define I2C_HIGH_SPEED_MASK (0x03 << 1) + +#define I2C_DEFAULT_TAR_ADDR_DEFAULT 0x055 +#define I2C_DEFAULT_SLAVE_ADDR_DEFAULT 0x055 +#define I2C_COMP_VERSION_DEFAULT 0x3131352A + +#define I2C_HS_MASTER_CODE_DEFAULT 1 +#define I2C_SS_SCL_HIGH_COUNT_DEFAULT 0x0190 +#define I2C_SS_SCL_LOW_COUNT_DEFAULT 0x01d6 +#define I2C_FS_SCL_HIGH_COUNT_DEFAULT 0x003c +#define I2C_FS_SCL_LOW_COUNT_DEFAULT 0x0082 +#define I2C_HS_SCL_HIGH_COUNT_DEFAULT 0x006 +#define I2C_HS_SCL_LOW_COUNT_DEFAULT 0x0010 +#define I2C_RX_TL_DEFAULT 0 +#define I2C_TX_TL_DEFAULT 0 +#define I2C_DEFAULT_SDA_SETUP_DEFAULT 0x64 +#define I2C_DEFAULT_ACK_GENERAL_CALL_DEFAULT 1 +#define I2C_DYNAMI2C_TAR_UPDATE_DEFAULT 1 +#define I2C_RX_BUFFER_DEPTH_DEFAULT 8 +#define I2C_TX_BUFFER_DEPTH_DEFAULT 8 +#define I2C_ADD_ENCODED_PARAMS_DEFAULT 1 +#define I2C_HAS_DMA_DEFAULT 0 +#define I2C_INTR_IO_DEFAULT 0 +#define I2C_HC_COUNT_VALUES_DEFAULT 0 +#define APB_DATA_WIDTH_DEFAULT 0 +#define I2C_SLV_DATA_NACK_ONLY_DEFAULT 0 +#define I2C_USE_COUNTS_DEFAULT 0 +#define I2C_CLK_TYPE_DEFAULT 1 +#define I2C_CLOCK_PERIOD_DEFAULT 10 + + /* Raw Interrupt Status */ + +#define I2C_IRQ_NONE (0x0) +#define I2C_IRQ_RX_UNDER (0x01 << 0) +#define I2C_IRQ_RX_OVER (0x01 << 1) +#define I2C_IRQ_RX_FULL (0x01 << 2) +#define I2C_IRQ_TX_OVER (0x01 << 3) +#define I2C_IRQ_TX_EMPTY (0x01 << 4) +#define I2C_IRQ_RD_REQ (0x01 << 5) +#define I2C_IRQ_TX_ABRT (0x01 << 6) +#define I2C_IRQ_RX_DONE (0x01 << 7) +#define I2C_IRQ_ACTIVITY (0x01 << 8) +#define I2C_IRQ_STOP_DET (0x01 << 9) +#define I2C_IRQ_START_DET (0x01 << 10) +#define I2C_IRQ_GEN_CALL (0x01 << 11) +#define I2C_IRQ_ALL 0xFFF + + /* Default IRQ Mask Bit Setting */ + +#define I2C_IRQ_DEFAULT_MASK (I2C_IRQ_RX_FULL | I2C_IRQ_TX_EMPTY | \ + I2C_IRQ_TX_ABRT | I2C_IRQ_STOP_DET | \ + I2C_IRQ_START_DET) + + /* Data command stop bit */ + +#define I2C_DATA_CMD_WR_STOP_BIT (0x02 << 8) /* bit 8=0:W, bit 9=1: stop */ +#define I2C_DATA_CMD_RD_STOP_BIT (0x03 << 8) /* bit 8=1:R, bit 9=1: stop */ +#define I2C_DATA_CMD_DAT_MASK 0xff /* bit [7:0] , TX and RX data */ +#define I2C_DATA_CMD_WR (0x00 << 8) +#define I2C_DATA_CMD_RD (0x01 << 8) +#define I2C_DATA_CMD_STOP (0x01 << 9) +#define I2C_DATA_CMD_RESTART (0X01 << 10) + + /* I2C TX Abort Source*/ + +#define I2C_ABRT_7B_ADDR_NOACK 0x001 +#define I2C_ABRT_10_ADDR1_NOACK 0x002 +#define I2C_ABRT_10_ADDR2_NOACK 0x004 +#define I2C_ABRT_TXDATA_NOACK 0x008 +#define I2C_ABRT_GCALL_NOACK 0x010 +#define I2C_ABRT_GCALL_READ 0x020 +#define I2C_ABRT_HS_ACKDET 0x040 +#define I2C_ABRT_SBYTE_ACKDET 0x080 +#define I2C_ABRT_HS_NORSTRT 0x100 +#define I2C_ABRT_SBYTE_NORSTRT 0x200 +#define I2C_ABRT_10B_RD_NORSTRT 0x400 +#define I2C_ABRT_MASTER_DIS 0x800 +#define I2C_ABRT_ARB_LOST 0x1000 +#define I2C_ABRT_SLVFLUSH_TXFIFO 0x2000 +#define I2C_ABRT_SLV_ARBLOST 0x5000 +#define I2C_ABRT_SLVRD_INTX 0x8000 + + /* Minimum High and Low period in nanosecends */ + +#define SS_MIN_SCL_HIGH 4000 +#define SS_MIN_SCL_LOW 4700 +#define FS_MIN_SCL_HIGH 600 +#define FS_MIN_SCL_LOW 1300 +#define HS_MIN_SCL_HIGH_100PF 60 +#define HS_MIN_SCL_LOW_100PF 120 + + /* I2C_STATUS (RO) */ + +#define I2C_STATUS_ACTIVITY (0x1 << 0) /* I2C ctrl is enabled */ +#define I2C_STATUS_TFNF (0x1 << 1) /* TX FIFO is not full */ +#define I2C_STATUS_TFE (0x1 << 2) /* TX FIFO is empty */ +#define I2C_STATUS_RFNE (0x1 << 3) /* RX FIFO is not empty */ +#define I2C_STATUS_RFF (0x1 << 4) /* RX FIFO is full */ +#define I2C_STATUS_MST_ACTIVITY (0x1 << 5) /* Master is not idle */ +#define I2C_STATUS_SLV_ACTIVITY (0x1 << 6) /* Slave is not idle */ + + /* Interrupts status */ + +#define I2C_INTR_RX_UNDER (0x1 << 0) +#define I2C_INTR_RX_OVER (0x1 << 1) +#define I2C_INTR_RX_FULL (0x1 << 2) +#define I2C_INTR_TX_OVER (0x1 << 3) +#define I2C_INTR_TX_EMPTY (0x1 << 4) +#define I2C_INTR_RD_REQ (0x1 << 5) +#define I2C_INTR_TX_ABRT (0x1 << 6) +#define I2C_INTR_RX_DONE (0x1 << 7) +#define I2C_INTR_ACTIVITY (0x1 << 8) +#define I2C_INTR_STOP_DET (0x1 << 9) +#define I2C_INTR_START_DET (0x1 << 10) +#define I2C_INTR_GEN_CALL (0x1 << 11) + +#define I2C_TX_BUFFER_DEPTH_MASK 0xFF0000 /* bit [23: 16] */ +#define I2C_RX_BUFFER_DEPTH_MASK 0x00FF00 /* bit [15: 8] */ + +#define I2C_INTR_MAX_BITS 12 + +#define I2C_ENABLE_CONTROLLER 0x01 +#define I2C_DISABLE_CONTROLLER 0x00 + +#define I2C_DATA_CMD_READ (0x01 << 8) +#define I2C_DATA_CMD_WRITE (0x00 << 8) + +#define I2C_TAR_DEFAULT_ADDR 0x55 +#define FT2000_I2C_CLK (48000000) /* I2C clock */ +/** + * @name: FI2c_WriteReg + * @msg: write i2c register + * @param {u32} BaseAddress base addr of i2c + * @param {u32} RegOffset addr offset of i2c register + * @param {u32} RegisterValue val to be write into register + * @return {void} + */ +#define FI2C_WriteReg(BaseAddress, RegOffset, RegisterValue) Ft_out32(BaseAddress + (u32)RegOffset, (u32)RegisterValue) + +/** + * @name: FI2c_ReadReg + * @msg: read i2c register + * @param {u32} BaseAddress base addr of i2c + * @param {u32} RegOffset addr offset of i2c register + * @return {u32} val read from register + */ +#define FI2C_ReadReg(BaseAddress, RegOffset) Ft_in32(BaseAddress + (u32)RegOffset) + +/* +* the following macros convert from BCD to binary and back. +* Be careful that the arguments are chars, only char width returned. +*/ + +#define BCD_TO_BIN(bcd) ((((((bcd)&0xf0) >> 4) * 10) + ((bcd)&0xf)) & 0xff) +#define BIN_TO_BCD(bin) (((((bin) / 10) << 4) + ((bin) % 10)) & 0xff) + +#define FI2C_GET_BASE_ADDR(pDev) ((pDev)->Config.BaseAddress) +#define FI2C_ENABLE_I2C_BUS(pDev) (FI2C_WriteReg(FI2C_GET_BASE_ADDR(pDev), I2C_ENABLE, I2C_ENABLE_CONTROLLER)) +#define FI2C_DISABLE_I2C_BUS(pDev) (FI2C_WriteReg(FI2C_GET_BASE_ADDR(pDev), I2C_ENABLE, I2C_DISABLE_CONTROLLER)) +#define FI2C_IS_I2C_BUS_ENABLED(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_ENABLE)) + +#define FI2C_GET_STATUS(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_STATUS)) +#define FI2C_CHECK_STATUS(pDev, stMask) (FI2C_GET_STATUS(pDev) & (stMask)) +#define FI2C_CLR_ALL_IRQ_STATUS(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_CLR_INTR)) +#define FI2C_GET_IRQ_STATUS(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_INTR_STAT)) +#define FI2C_GET_IRQ_MASK(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_INTR_MASK)) +#define FI2C_SET_IRQ_MASK(pDev, mask) (FI2C_WriteReg(FI2C_GET_BASE_ADDR(pDev), I2C_INTR_MASK, (mask))) + +#define FI2C_GET_TX_TL(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_TX_TL)) +#define FI2C_GET_RX_TL(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_RX_TL)) +#define FI2C_SET_TX_TL(pDev, TxThres) (FI2C_WriteReg(FI2C_GET_BASE_ADDR(pDev), I2C_TX_TL, (TxThres))) +#define FI2C_SET_RX_TL(pDev, RxThres) (FI2C_WriteReg(FI2C_GET_BASE_ADDR(pDev), I2C_RX_TL, (RxThres))) + +#define FI2C_GET_TXFLR(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_TXFLR)) +#define FI2C_GET_RXFLR(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_RXFLR)) + +#define FI2C_CLR_IRQ_RX_OVER(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_CLR_RX_OVER)) +#define FI2C_CLR_IRQ_TX_OVER(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_CLR_TX_OVER)) + +#define FI2C_GET_COMP_PARAM_1(pDev) (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_COMP_PARAM_1)) +#define FI2C_GET_TX_BUFFER_DEPTH(pDev) ((I2C_TX_BUFFER_DEPTH_MASK & FI2C_GET_COMP_PARAM_1(pDev)) >> 16 ) +#define FI2C_GET_RX_BUFFER_DEPTH(pDev) ((I2C_RX_BUFFER_DEPTH_MASK & FI2C_GET_COMP_PARAM_1(pDev)) >> 8) + +#define FI2C_SEND_TX_STOP_CMD(pDev) (FI2C_WriteReg(FI2C_GET_BASE_ADDR(pDev), I2C_DATA_CMD, I2C_DATA_CMD_STOP)) +#define FI2C_SET_TX_DATA(pDev, data) (FI2C_WriteReg(FI2C_GET_BASE_ADDR(pDev), I2C_DATA_CMD, ((u32)(data) & I2C_DATA_CMD_DAT_MASK))) +#define FI2C_GET_RX_DATA(pDev) (u8)(I2C_DATA_CMD_DAT_MASK & (FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_DATA_CMD))) +#define FI2C_SEND_RX_NEXT_CMD(pDev) (FI2C_WriteReg(FI2C_GET_BASE_ADDR(pDev), I2C_DATA_CMD, I2C_DATA_CMD_STOP | I2C_DATA_CMD_RESTART | I2C_DATA_CMD_RD)) +#define FI2C_SEND_RX_STOP_CMD(pDev) (FI2C_WriteReg(FI2C_GET_BASE_ADDR(pDev), I2C_DATA_CMD, I2C_DATA_CMD_STOP | I2C_DATA_CMD_RD)) + +void FI2C_resetReg(u32 BaseAddr); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_irq.c b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_irq.c new file mode 100644 index 0000000000000000000000000000000000000000..edab5525d2b372471460b0453c6b1994d976722d --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_irq.c @@ -0,0 +1,193 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-20 15:35:44 + * @LastEditTime: 2021-04-23 08:53:12 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_i2c.h" + +void FI2C_irqHandler(void *pArgs) +{ + FI2C_t *pDev; + u32 RegVal; + FI2C_IrqType_t IrqType = I2C_IRQ_TYPE_NONE; + + Ft_assertNoneReturn(NULL != pArgs); + pDev = (FI2C_t *)pArgs; + + RegVal = FI2C_GET_IRQ_STATUS(pDev); + if (I2C_IRQ_RX_FULL & RegVal) + { + IrqType = I2C_IRQ_TYPE_RX_COMPLETE; + } + else if (I2C_IRQ_TX_EMPTY & RegVal) + { + IrqType = I2C_IRQ_TYPE_TX_COMPLETE; + } + + if ((NULL != pDev->pIrqCallBack) && (I2C_IRQ_TYPE_NONE != IrqType)) + { + pDev->pIrqCallBack(IrqType, pDev, NULL); + } + + if (I2C_IRQ_TYPE_RX_COMPLETE == IrqType) + { + FI2C_setIrq(pDev, I2C_IRQ_RX_FULL, FALSE); + } + else if (I2C_IRQ_TYPE_TX_COMPLETE == IrqType) + { + FI2C_setIrq(pDev, I2C_IRQ_TX_EMPTY, FALSE); + } + + FI2C_CLR_ALL_IRQ_STATUS(pDev); + return; +} + +void FI2C_irqHandler4Fifo(void *pArgs) +{ + FI2C_t *pDev; + u32 RegVal; + u32 BytesToRx; + FI2C_IrqType_t IrqType = I2C_IRQ_TYPE_NONE; + + Ft_assertNoneReturn(NULL != pArgs); + pDev = (FI2C_t *)pArgs; + + /* check if i2c controller is enabled */ + if (!FI2C_IS_I2C_BUS_ENABLED(pDev)) + { + pDev->LastIrqErr = ERR_I2C_BUS_NOT_ENABLED; + return; + } + + /* check there is no interrupt */ + if (!FI2C_checkIfIntr(pDev)) + { + pDev->LastIrqErr = ERR_I2C_INVALID_PARAM; + return; + } + + /* read interrupt status */ + RegVal = FI2C_GET_IRQ_STATUS(pDev); + if (I2C_IRQ_RX_FULL & RegVal) + { + IrqType = I2C_IRQ_TYPE_RX_COMPLETE; + BytesToRx = FI2C_GET_RXFLR(pDev); + //FT_I2C_DEBUG_I("I2C_IRQ_RX_FULL bytes to rx %d", BytesToRx); + + while ((pDev->RxBuf.CurIndex < pDev->RxBuf.DataLength) && + (0 < BytesToRx)) + { + /* read one byte */ + pDev->RxBuf.BytePtr[pDev->RxBuf.CurIndex] = FI2C_GET_RX_DATA(pDev); + // FT_I2C_DEBUG_I("read 0x%x with idx %d, len %d remain %d", + // pDev->RxBuf.BytePtr[pDev->RxBuf.CurIndex], + // pDev->RxBuf.CurIndex, + // pDev->RxBuf.DataLength, + // BytesToRx); + pDev->RxBuf.CurIndex++; + BytesToRx--; + pDev->DelayHandle(10); + + /* read next byte */ + if (pDev->RxBuf.CurIndex != pDev->RxBuf.DataLength) + { + FI2C_SEND_RX_NEXT_CMD(pDev); + } + else + { + FI2C_SEND_RX_STOP_CMD(pDev); + pDev->DelayHandle(10); + FI2C_setIrq(pDev, I2C_IRQ_RX_FULL, FALSE); + //FT_I2C_DEBUG_I("stop and disable I2C_IRQ_RX_FULL"); + } + } + } + else if (I2C_IRQ_TX_EMPTY & RegVal) + { + IrqType = I2C_IRQ_TYPE_TX_COMPLETE; + // FT_I2C_DEBUG_I("I2C_IRQ_TX_EMPTY idx %d, len %d", + // pDev->TxBuf.CurIndex, + // pDev->TxBuf.DataLength); + if (pDev->TxBuf.CurIndex == pDev->TxBuf.DataLength) + { + FI2C_SEND_TX_STOP_CMD(pDev); + pDev->DelayHandle(10); + //FT_I2C_DEBUG_I("stop and disable I2C_IRQ_TX_EMPTY"); + FI2C_setIrq(pDev, I2C_IRQ_TX_EMPTY, FALSE); + } + else + { + //FT_I2C_DEBUG_I("TX 0x%x", pDev->TxBuf.BytePtr[pDev->TxBuf.CurIndex]); + FI2C_SET_TX_DATA(pDev, pDev->TxBuf.BytePtr[pDev->TxBuf.CurIndex]); + pDev->TxBuf.CurIndex++; + } + } + + if ((NULL != pDev->pIrqCallBack) && (I2C_IRQ_TYPE_NONE != IrqType)) + { + pDev->pIrqCallBack(IrqType, pDev, NULL); + } + + pDev->LastIrqErr = ERR_I2C_OK; + return; +} + +u32 FI2C_getIrqMask(FT_IN FI2C_t *pDev) +{ + u32 RegVal; + Ft_assertNoneReturn(NULL != pDev); + + RegVal = FI2C_GET_IRQ_MASK(pDev); + return RegVal; +} + + +void FI2C_setIrqMask(FT_IN FI2C_t *pDev, FT_IN u32 mask) +{ + u32 RegVal; + Ft_assertNoneReturn(NULL != pDev); + + RegVal = mask & I2C_IRQ_ALL_MASK; + FI2C_SET_IRQ_MASK(pDev, RegVal); + return; +} + +void FI2C_setIrq(FT_IN FI2C_t *pDev, FT_IN u32 maskBit, FT_IN bool_t enable) +{ + Ft_assertNoneReturn(0x0 != maskBit); + + if (TRUE == enable) + { + FI2C_setIrqMask(pDev, FI2C_getIrqMask(pDev) | maskBit); + } + else + { + FI2C_setIrqMask(pDev, FI2C_getIrqMask(pDev) & (~maskBit)); + } + return; +} + +bool_t FI2C_checkIfIntr(FT_IN FI2C_t *pDev) +{ + u32 RegVal; + Ft_assertNoneReturn(NULL != pDev); + + RegVal = FI2C_ReadReg(FI2C_GET_BASE_ADDR(pDev), I2C_RAW_INTR_STAT); + if (0 == (RegVal & (~I2C_IRQ_ACTIVITY))) + { + return FALSE; + } + else + { + return TRUE; + } +} \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_selftest.c b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_selftest.c new file mode 100644 index 0000000000000000000000000000000000000000..f94b6d6d1a1c714dfbd5f900416f4c38e3e8fc13 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_i2c/ft_i2c_selftest.c @@ -0,0 +1,21 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-07 13:27:24 + * @Description:  This files is for i2c test cases + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + + +#include +#include +#include "ft_i2c_hw.h" +#include "ft_i2c.h" +#include "ft_status.h" +#include "ft_printf.h" diff --git a/bsp/ft2004/libraries/bsp/ft_qspi/ft_qspi.c b/bsp/ft2004/libraries/bsp/ft_qspi/ft_qspi.c new file mode 100644 index 0000000000000000000000000000000000000000..5827123707d89de7e4a163b5165b39ff33d49a1d --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_qspi/ft_qspi.c @@ -0,0 +1,626 @@ +/* + * @[H]: Copyright (C) 2014-2021 Tianjin Phytium Technology.  All rights reserved. + * + *  Permission is hereby granted, free of charge, to any person obtaining a copy + *  of this software and associated documentation files (the "Software"), to deal + *  in the Software without restriction, including without limitation the rights + *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + *  copies of the Software, and to permit persons to whom the Software is + *  furnished to do so, subject to the following conditions: + * + *  The above copyright notice and this permission notice shall be included in + *  all copies or substantial portions of the Software. + * + *  Use of the Software is limited solely to applications: + *  (a) running on a Phytium device, or + *  (b) that interact with a Phytium device through a bus or interconnect. + * + *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + *  PHYTIUM  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + *  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + *  SOFTWARE. + * + *  Except as contained in this notice, the name of the Phytium shall not be used + *  in advertising or otherwise to promote the sale, use or other dealings in + *  this Software without prior written authorization from Phytium.  + * + * @Date: 2021-04-05 22:15:53 + * @LastEditTime: 2021-04-06 09:10:20 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + * * 1.00 hh 2021.04-06 init + */ + +#include "ft_qspi.h" +#include "qspi_hw.h" +#include "ft_io.h" +#include "ft_assert.h" +#include "ft_types.h" +#include "string.h" + +#include "ft_debug.h" + +#define FTQSPI_DEBUG_TAG "FTQSPI" + +#define FTQSPI_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FTQSPI_DEBUG_TAG, format, ##__VA_ARGS__) +#define FTQSPI_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(FTQSPI_DEBUG_TAG, format, ##__VA_ARGS__) +#define FTQSPI_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FTQSPI_DEBUG_TAG, format, ##__VA_ARGS__) + +ft_error_t FQSpi_CfgInitialize(FQSpi_t *pQspi, FQSpi_Config_t *pConfig) +{ + Ft_assertNonvoid(pQspi != NULL); + Ft_assertNonvoid(pConfig != NULL); + + pQspi->config = *pConfig; + pQspi->isReady = FT_COMPONENT_IS_READLY; + + FQSpi_Reset(pQspi); + + return FQSPI_SUCCESS; +} + +/** + * @name: FQSpi_MemcpyToReg + * @msg: Memory copy To Register + * @in param {FQSpi_t} *pQspi + * @in param {u8} *buf + * @in param {u32} length + * @return {ft_error_t} + */ +static ft_error_t FQSpi_MemcpyToReg(FQSpi_t *pQspi, FT_IN u8 *buf, u32 length) +{ + u32 val = 0; + FQSpi_Config_t *pConfig =NULL; + Ft_assertNonvoid(pQspi != NULL); + Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY); + pConfig = &pQspi->config; + if (!buf || (length > 4)) + { + return FQSPI_FAILURE; + } + + if (1 == length) + { + val = buf[0]; + } + else if (2 == length) + { + val = buf[1]; + val = (val << 8) + buf[0]; + } + else if (3 == length) + { + val = buf[2]; + val = (val << 8) + buf[1]; + val = (val << 8) + buf[0]; + } + else if (4 == length) + { + val = buf[3]; + val = (val << 8) + buf[2]; + val = (val << 8) + buf[1]; + val = (val << 8) + buf[0]; + } + + Ft_out32(pConfig->baseAddress + FT_REG_QSPI_LD_PORT_OFFSET, val); + return FQSPI_SUCCESS; +} + +/** + * @name: FQSpi_MemcpyFromReg + * @msg: Memory copy from Register + * @in param {FT_INFQSpi_t} *pQspi + * @out param {u8} *buf + * @in param {u32} length + * @return {*} + */ +static ft_error_t FQSpi_MemcpyFromReg(FQSpi_t *pQspi, u8 *buf, u32 length) +{ + s32 i; + u32 val = 0; + FQSpi_Config_t *pConfig =NULL; + Ft_assertNonvoid(pQspi != NULL); + Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY); + pConfig = &pQspi->config; + + for (i = 0; i < length; i++) + { + /* code */ + if (0 == i % 4) + { + val = Ft_in32(pConfig->baseAddress + FT_REG_QSPI_LD_PORT_OFFSET); + } + buf[i] = (u8)(val >> (i % 4) * 8) & 0xff; + } + + return FQSPI_SUCCESS; +} + +/** + * @name: FQSpi_FlashRead + * @msg: Reads bytes data from flash addr to buf + * @in param pQspi: + * @in param cmd: Read the instruction byte of the command + * @in param addr: Read the data start character + * @out param rxBuf: Read buffer + * @in param length: need read length + * @return {*} + */ +ft_error_t FQSpi_FlashRead(FQSpi_t *pQspi, + FT_IN u8 cmd, + FT_IN u32 addr, + FT_OUT u8 *rxBuf, + u32 length) +{ + FQSpi_Config_t *pConfig =NULL; + FQSpi_RdCfgReg_t rdCfgReg; + Ft_assertNonvoid(pQspi != NULL); + Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY); + pConfig = &pQspi->config; + + if ((NULL == rxBuf) || (0 == length)) + { + return FQSPI_FAILURE; + } + + rdCfgReg.data = 0; + + rdCfgReg.val.rdCmd = cmd; + rdCfgReg.val.dBuffer = 1; + rdCfgReg.val.rdAddrSel = pConfig->addrMode; + rdCfgReg.val.rdSckSel = pConfig->clkDiv; + rdCfgReg.val.rdTransfer = pConfig->transMode; + Ft_out32(pConfig->baseAddress + FT_REG_QSPI_RD_CFG_OFFSET, rdCfgReg.data); + + memcpy(rxBuf, (char *)(addr), length); + + return FQSPI_SUCCESS; +} + +/** + * @name: FQSpi_FlashWrite + * @msg: Writes one page into flash,changing bits from 1 to 0 + * @in param pQspi: + * @in param cmd: write the instruction byte of the command + * @in param addr: write the data start character + * @in param txBuf: write buffer + * @in param length: need write length + * @return {*} + */ +ft_error_t FQSpi_FlashWrite(FQSpi_t *pQspi, + FT_IN u8 cmd, + FT_IN u32 addr, + FT_IN u8 *txBuf, + u32 length) +{ + + FQSpi_Config_t *pConfig =NULL; + FQSpi_WrCfgReg_t wrCfgReg; + u32 index = 0; + u32 val = 0; + u32 *pu32Buf = NULL; + Ft_assertNonvoid(pQspi != NULL); + Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY); + pConfig = &pQspi->config; + + if ((NULL == txBuf) || (0 == length)) + { + return FQSPI_FAILURE; + } + + pu32Buf = (u32 *)txBuf; + + wrCfgReg.data = 0; + wrCfgReg.val.wrCmd = cmd; + wrCfgReg.val.wrWait = 1; + wrCfgReg.val.wrSckSel = pConfig->clkDiv; + wrCfgReg.val.wrAddrsel = pConfig->addrMode; + wrCfgReg.val.wrTransfer = pConfig->transMode; + wrCfgReg.val.wrMode = 1; + + Ft_out32(pConfig->baseAddress + FT_REG_QSPI_WR_CFG_OFFSET, wrCfgReg.data); + + while (length) + { + if (length >= 4) + { + Ft_out32(addr + index, pu32Buf[index / 4]); + length -= 4; + index += 4; + } + else + { + if (1 == length) + { + val = txBuf[index] | 0xFFFFFF00; + } + else if (2 == length) + { + val = txBuf[index] | (txBuf[index + 1] << 8) | 0xFFFF0000; + } + else + { + val = txBuf[index] | (txBuf[index + 1] << 8) | (txBuf[index + 2] << 8) | 0xFF000000; + } + + Ft_out32(addr + index, val); + length = 0; + } + } + + Ft_out32(pConfig->baseAddress + FT_REG_QSPI_FLUSH_OFFSET, 1); + return FQSPI_SUCCESS; +} + +/** + * @name: FQSpi_FlashRegSet + * @msg: Set registers of flash + * @in param cmd: Command byte + * @in param writebuf: write buffer + * @in param length: need write length + * @return {*} + */ +ft_error_t FQSpi_FlashRegSet(FQSpi_t *pQspi, + FT_IN u8 cmd, + FT_IN u8 *writebuf, + u32 length) +{ + FQSpi_Config_t *pConfig =NULL; + FQSpi_CmdPortReg_t cmdPortReg; + Ft_assertNonvoid(pQspi != NULL); + Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY); + pConfig = &pQspi->config; + + cmdPortReg.data = 0; + cmdPortReg.val.cmd = cmd; + cmdPortReg.val.wait = 1; + cmdPortReg.val.sckSel = pConfig->clkDiv; + cmdPortReg.val.transfer = pConfig->transMode; + cmdPortReg.val.cs = pConfig->channel; + + if (length == 0) + { + Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data); + Ft_out32(pConfig->baseAddress + FT_REG_QSPI_LD_PORT_OFFSET, 1); + } + else + { + cmdPortReg.val.dataTransfer = 1; + cmdPortReg.val.rwMum = length; + Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data); + FQSpi_MemcpyToReg(pQspi, writebuf, length); + } + + return FQSPI_SUCCESS; +} + +/** + * @name: FQSpi_FlashRegSetWithaddr + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + */ +ft_error_t FQSpi_FlashRegSetWithaddr(FQSpi_t *pQspi, + FT_IN u8 cmd, + FT_IN u32 addr, + FT_IN u8 *writebuf, + u32 length) +{ + FQSpi_Config_t *pConfig =NULL; + FQSpi_CmdPortReg_t cmdPortReg; + Ft_assertNonvoid(pQspi != NULL); + Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY); + pConfig = &pQspi->config; + + cmdPortReg.data = 0; + cmdPortReg.val.cmd = cmd; + cmdPortReg.val.wait = 1; + cmdPortReg.val.sckSel = pConfig->clkDiv; + cmdPortReg.val.transfer = pConfig->transMode; + cmdPortReg.val.cs = pConfig->channel; + cmdPortReg.val.cmdAddr = 1; + cmdPortReg.val.addrSel = pConfig->addrMode; + + Ft_out32(pConfig->baseAddress + FT_REG_QSPI_ADDR_PORT_OFFSET, addr); + + if (length == 0) + { + Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data); + Ft_out32(pConfig->baseAddress + FT_REG_QSPI_LD_PORT_OFFSET, 0); + } + else + { + cmdPortReg.val.dataTransfer = 1; + cmdPortReg.val.rwMum = length; + Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data); + FQSpi_MemcpyToReg(pQspi, writebuf, length); + } + + return FQSPI_SUCCESS; +} + +/** + * @name: + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + */ +ft_error_t FQSpi_FlashRegGet(FQSpi_t *pQspi, + FT_IN u8 cmd, + u8 *readbuf, + u32 length) +{ + FQSpi_Config_t *pConfig =NULL; + FQSpi_CmdPortReg_t cmdPortReg; + Ft_assertNonvoid(pQspi != NULL); + Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY); + pConfig = &pQspi->config; + + cmdPortReg.data = 0; + cmdPortReg.val.cmd = cmd; + cmdPortReg.val.wait = 1; + cmdPortReg.val.sckSel = pConfig->clkDiv; + cmdPortReg.val.transfer = pConfig->transMode; + cmdPortReg.val.cs = pConfig->channel; + cmdPortReg.val.dataTransfer = 1; + cmdPortReg.val.pBuffer = 1; + + Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data); + FQSpi_MemcpyFromReg(pQspi, readbuf, length); + return FQSPI_SUCCESS; +} + +ft_error_t FQSpi_FlashRegGetWithAddr(FQSpi_t *pQspi, + FT_IN u8 cmd, + FT_IN u32 addr, + FT_IN u32 dummyCycle, + u8 *readbuf, + u32 length) +{ + FQSpi_Config_t *pConfig =NULL; + FQSpi_CmdPortReg_t cmdPortReg; + Ft_assertNonvoid(pQspi != NULL); + Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY); + pConfig = &pQspi->config; + + cmdPortReg.data = 0; + cmdPortReg.val.cmd = cmd; + cmdPortReg.val.wait = 1; + cmdPortReg.val.sckSel = pConfig->clkDiv; + cmdPortReg.val.transfer = pConfig->transMode; + cmdPortReg.val.cs = pConfig->channel; + cmdPortReg.val.dataTransfer = 1; + cmdPortReg.val.pBuffer = 1; + cmdPortReg.val.cmdAddr = 1; + + cmdPortReg.val.addrSel = pConfig->addrMode; + cmdPortReg.val.latency = 1; + cmdPortReg.val.dummy = dummyCycle - 1; + + Ft_out32(pConfig->baseAddress + FT_REG_QSPI_ADDR_PORT_OFFSET, addr); + Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data); + FQSpi_MemcpyFromReg(pQspi, readbuf, length); + return FQSPI_SUCCESS; +} + +ft_error_t FQSpi_Write(FQSpi_t *pQspi, struct FQSpi_DataPack *pDataPack) +{ + FQSpi_Config_t *pConfig =NULL; + FQSpi_WrCfgReg_t wrCfgReg; + u32 length; + u32 index = 0; + u32 val = 0; + const u32 *pu32Buf = NULL; + Ft_assertNonvoid(pQspi != NULL); + Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY); + pConfig = &pQspi->config; + + if ((FQSPI_DATA_ADDRESS_3BYTE_MASK | FQSPI_DATA_ADDRESS_4BYTE_MASK) == (pDataPack->flags & (FQSPI_DATA_ADDRESS_3BYTE_MASK | FQSPI_DATA_ADDRESS_4BYTE_MASK))) + { + FTQSPI_DEBUG_E(" Two addresses are not allowed at the same time "); + return FQSPI_FAILURE; + } + + if (0 == (pDataPack->flags & (FQSPI_DATA_ADDRESS_3BYTE_MASK | FQSPI_DATA_ADDRESS_4BYTE_MASK))) + { + FTQSPI_DEBUG_E(" There is no address configuration "); + return FQSPI_FAILURE; + } + + if (NULL == pDataPack->txBuf) + { + FTQSPI_DEBUG_E("pDataPack->txBuf is null"); + return FQSPI_FAILURE; + } + + pu32Buf = (const u32 *)pDataPack->txBuf; + wrCfgReg.data = 0; + + if (FQSPI_DATA_ADDRESS_3BYTE_MASK == (pDataPack->flags & FQSPI_DATA_ADDRESS_3BYTE_MASK)) + { + wrCfgReg.val.wrAddrsel = FT_QSPI_ADDR_SEL_3; + } + else if (FQSPI_DATA_ADDRESS_4BYTE_MASK == (pDataPack->flags & FQSPI_DATA_ADDRESS_4BYTE_MASK)) + { + wrCfgReg.val.wrAddrsel = FT_QSPI_ADDR_SEL_4; + } + + wrCfgReg.val.wrCmd = pDataPack->cmd; + wrCfgReg.val.wrWait = 1; + wrCfgReg.val.wrSckSel = pConfig->clkDiv; + wrCfgReg.val.wrTransfer = pConfig->transMode; + wrCfgReg.val.wrMode = 1; + length = pDataPack->length; + + Ft_out32(pConfig->baseAddress + FT_REG_QSPI_WR_CFG_OFFSET, wrCfgReg.data); + + while (length) + { + if (length >= 4) + { + Ft_out32(pDataPack->addr + index, pu32Buf[index / 4]); + length -= 4; + index += 4; + } + else + { + if (1 == length) + { + val = pDataPack->txBuf[index] | 0xFFFFFF00; + } + else if (2 == length) + { + val = pDataPack->txBuf[index] | (pDataPack->txBuf[index + 1] << 8) | 0xFFFF0000; + } + else + { + val = pDataPack->txBuf[index] | (pDataPack->txBuf[index + 1] << 8) | (pDataPack->txBuf[index + 2] << 8) | 0xFF000000; + } + FTQSPI_DEBUG_I("val is 0x%x", val); + Ft_out32(pDataPack->addr + index, val); + length = 0; + } + } + + Ft_out32(pConfig->baseAddress + FT_REG_QSPI_FLUSH_OFFSET, 1); + return FQSPI_SUCCESS; +} + +ft_error_t FQSpi_Read(FQSpi_t *pQspi, struct FQSpi_DataPack *pDataPack) +{ + FQSpi_Config_t *pConfig =NULL; + FQSpi_RdCfgReg_t rdCfgReg; + Ft_assertNonvoid(pQspi != NULL); + Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY); + pConfig = &pQspi->config; + + if ((FQSPI_DATA_ADDRESS_3BYTE_MASK | FQSPI_DATA_ADDRESS_4BYTE_MASK) == (pDataPack->flags & (FQSPI_DATA_ADDRESS_3BYTE_MASK | FQSPI_DATA_ADDRESS_4BYTE_MASK))) + { + FTQSPI_DEBUG_E(" Two addresses are not allowed at the same time "); + return FQSPI_FAILURE; + } + + if (0 == (pDataPack->flags & (FQSPI_DATA_ADDRESS_3BYTE_MASK | FQSPI_DATA_ADDRESS_4BYTE_MASK))) + { + FTQSPI_DEBUG_E(" There is no address configuration "); + return FQSPI_FAILURE; + } + + if (NULL == pDataPack->rxBuf) + { + FTQSPI_DEBUG_E("pDataPack->rxBuf is null"); + return FQSPI_FAILURE; + } + + rdCfgReg.data = 0; + + if (FQSPI_DATA_NEED_DUMMY_MASK == (pDataPack->flags & FQSPI_DATA_NEED_DUMMY_MASK)) + { + rdCfgReg.val.rdLatency = 1; + rdCfgReg.val.dummy = pDataPack->dummyCycle - 1; + } + + if (FQSPI_DATA_ADDRESS_3BYTE_MASK == (pDataPack->flags & FQSPI_DATA_ADDRESS_3BYTE_MASK)) + { + rdCfgReg.val.rdAddrSel = FT_QSPI_ADDR_SEL_3; + } + else if (FQSPI_DATA_ADDRESS_4BYTE_MASK == (pDataPack->flags & FQSPI_DATA_ADDRESS_4BYTE_MASK)) + { + rdCfgReg.val.rdAddrSel = FT_QSPI_ADDR_SEL_4; + } + + rdCfgReg.val.rdCmd = pDataPack->cmd; + rdCfgReg.val.dBuffer = 1; + rdCfgReg.val.rdSckSel = pConfig->clkDiv; + rdCfgReg.val.rdTransfer = pConfig->transMode; + + Ft_out32(pConfig->baseAddress + FT_REG_QSPI_RD_CFG_OFFSET, rdCfgReg.data); + + memcpy(pDataPack->rxBuf, (char *)(pDataPack->addr), pDataPack->length); + + return FQSPI_SUCCESS; +} + +ft_error_t +FQSpi_CmdOperation(FQSpi_t *pQspi, struct FQSpi_CmdPack *pCmdPack) +{ + FQSpi_Config_t *pConfig =NULL; + FQSpi_CmdPortReg_t cmdPortReg; + Ft_assertNonvoid(pQspi != NULL); + Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY); + pConfig = &pQspi->config; + if ((FQSPI_CMD_ADDRESS_3BYTE_MASK | FQSPI_CMD_ADDRESS_4BYTE_MASK) == (pCmdPack->flags & (FQSPI_CMD_ADDRESS_3BYTE_MASK | FQSPI_CMD_ADDRESS_4BYTE_MASK))) + { + FTQSPI_DEBUG_E(" Two addresses are not allowed at the same time "); + return FQSPI_FAILURE; + } + + cmdPortReg.data = 0; + cmdPortReg.val.cmd = pCmdPack->cmd; + cmdPortReg.val.wait = 1; + cmdPortReg.val.sckSel = pConfig->clkDiv; + cmdPortReg.val.transfer = pConfig->transMode; + cmdPortReg.val.cs = pConfig->channel; + + if (FQSPI_CMD_NEED_ADDR_MASK == (pCmdPack->flags & FQSPI_CMD_NEED_ADDR_MASK)) + { + // FTQSPI_DEBUG_I(" send addr is 0x%x ", pCmdPack->addr); + cmdPortReg.val.cmdAddr = 1; + Ft_out32(pConfig->baseAddress + FT_REG_QSPI_ADDR_PORT_OFFSET, pCmdPack->addr); + } + + if (FQSPI_CMD_NEED_DUMMY_MASK == (pCmdPack->flags & FQSPI_CMD_NEED_DUMMY_MASK)) + { + cmdPortReg.val.latency = 1; + cmdPortReg.val.dummy = pCmdPack->dummyCycle - 1; + } + + if (FQSPI_CMD_ADDRESS_3BYTE_MASK == (pCmdPack->flags & FQSPI_CMD_ADDRESS_3BYTE_MASK)) + { + cmdPortReg.val.addrSel = FT_QSPI_ADDR_SEL_3; + } + else if (FQSPI_CMD_ADDRESS_4BYTE_MASK == (pCmdPack->flags & FQSPI_CMD_ADDRESS_4BYTE_MASK)) + { + cmdPortReg.val.addrSel = FT_QSPI_ADDR_SEL_4; + } + + if (FQSPI_CMD_NEED_SET_MASK == (pCmdPack->flags & (FQSPI_CMD_NEED_SET_MASK))) + { + cmdPortReg.val.dataTransfer = 1; + cmdPortReg.val.rwMum = pCmdPack->length; + Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data); + FQSpi_MemcpyToReg(pQspi, pCmdPack->txBuf, pCmdPack->length); + } + else if (FQSPI_CMD_NEED_GET_MASK == (pCmdPack->flags & (FQSPI_CMD_NEED_GET_MASK))) + { + cmdPortReg.val.dataTransfer = 1; + cmdPortReg.val.pBuffer = 1; + Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data); + FQSpi_MemcpyFromReg(pQspi, pCmdPack->rxBuf, pCmdPack->length); + } + else + { + // FTQSPI_DEBUG_I(" Use no data way 0x%x", cmdPortReg.data); + Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data); + + if (FQSPI_CMD_NEED_ADDR_MASK == (pCmdPack->flags & FQSPI_CMD_NEED_ADDR_MASK)) + { + Ft_out32(pConfig->baseAddress + FT_REG_QSPI_LD_PORT_OFFSET, 0); + } + else + { + Ft_out32(pConfig->baseAddress + FT_REG_QSPI_LD_PORT_OFFSET, 1); + } + } + + return FQSPI_SUCCESS; +} diff --git a/bsp/ft2004/libraries/bsp/ft_qspi/ft_qspi.h b/bsp/ft2004/libraries/bsp/ft_qspi/ft_qspi.h new file mode 100644 index 0000000000000000000000000000000000000000..41f594e412d41d84d3134c063b7077060ea88eb1 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_qspi/ft_qspi.h @@ -0,0 +1,208 @@ +/* + * @[H]: Copyright (C) 2014-2021 Phytium Technology.  All rights reserved. + * + *  Permission is hereby granted, free of charge, to any person obtaining a copy + *  of this software and associated documentation files (the "Software"), to deal + *  in the Software without restriction, including without limitation the rights + *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + *  copies of the Software, and to permit persons to whom the Software is + *  furnished to do so, subject to the following conditions: + * + *  The above copyright notice and this permission notice shall be included in + *  all copies or substantial portions of the Software. + * + *  Use of the Software is limited solely to applications: + *  (a) running on a Phytium device, or + *  (b) that interact with a Phytium device through a bus or interconnect. + * + *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + *  PHYTIUM  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + *  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + *  SOFTWARE. + * + *  Except as contained in this notice, the name of the Phytium shall not be used + *  in advertising or otherwise to promote the sale, use or other dealings in + *  this Software without prior written authorization from Phytium.  + * + * @Date: 2021-04-05 21:31:10 + * @LastEditTime: 2021-04-05 21:31:10 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + * * v1.0 hh 2021-04-05 init + */ + +#ifndef FT_QSPI_H +#define FT_QSPI_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ft_types.h" +#include "ft_error_code.h" + +#define FQSPI_SUCCESS FST_SUCCESS /* SUCCESS */ +#define FQSPI_FAILURE FT_MAKE_ERRCODE(errQspi, errBspGeneral, FST_FAILURE) /* Normal */ +#define FQSPI_TIMEOUT FT_MAKE_ERRCODE(errQspi, errBspGeneral, FST_TIMEOUT) /* Timeout */ +#define FQSPI_EILSEQ FT_MAKE_ERRCODE(errQspi, errBspGeneral, FST_EILSEQ) /* Illegal byte sequence. */ +#define FQSPI_INVALID_PARAM FT_MAKE_ERRCODE(errQspi, errBspGeneral, FST_INVALID_PARAM) /* Invalid param. */ + +/* qspi bsp command instruction operation */ +#define FQSPI_CMD_NEED_ADDR_MASK 0x1U +#define FQSPI_CMD_NEED_DUMMY_MASK 0x2U +#define FQSPI_CMD_NEED_GET_MASK 0x4U +#define FQSPI_CMD_NEED_SET_MASK 0x08U +#define FQSPI_CMD_ADDRESS_3BYTE_MASK 0x10U +#define FQSPI_CMD_ADDRESS_4BYTE_MASK 0x20U + +/* qspi cmd of transfer operation */ +#define FQSPI_DATA_NEED_DUMMY_MASK 0x1U +#define FQSPI_DATA_ADDRESS_3BYTE_MASK 0x2U +#define FQSPI_DATA_ADDRESS_4BYTE_MASK 0x4U + +#define FQSPI_FLASH_CMD_WRR 0x01 /* Write status register */ +#define FQSPI_FLASH_CMD_PP 0x02 /* Page program */ +#define FQSPI_FLASH_CMD_READ 0x03 /* Normal read data bytes */ +#define FQSPI_FLASH_CMD_WRDI 0x04 /* Write disable */ +#define FQSPI_FLASH_CMD_RDSR1 0x05 /* Read status register */ +#define FQSPI_FLASH_CMD_WREN 0x06 /* Write enable */ +#define FQSPI_FLASH_CMD_RDSR2 0x07 /* Read status register */ +#define FQSPI_FLASH_CMD_FAST_READ 0x0B /* Fast read data bytes */ +#define FQSPI_FLASH_CMD_4FAST_READ 0x0C /* Fast read data bytes */ +#define FQSPI_FLASH_CMD_4PP 0x12 /* Page program */ +#define FQSPI_FLASH_CMD_4READ 0x13 /* Normal read data bytes */ +#define FQSPI_FLASH_CMD_P4E 0x20 /* Erase 4kb sector */ +#define FQSPI_FLASH_CMD_4P4E 0x21 /* Erase 4kb sector */ +#define FQSPI_FLASH_CMD_QPP 0x32 /* Quad Page program */ +#define FQSPI_FLASH_CMD_4QPP 0x34 /* Quad Page program */ +#define FQSPI_FLASH_CMD_RDCR 0x35 /* Read config register */ +#define FQSPI_FLASH_CMD_BE 0x60 /* Bulk erase */ +#define FQSPI_FLASH_CMD_RDAR 0x65 /* Read Any Register */ +#define FQSPI_FLASH_CMD_QOR 0x6B /* Quad read data bytes */ +#define FQSPI_FLASH_CMD_4QOR 0x6C /* Quad read data bytes */ +#define FQSPI_FLASH_CMD_WRAR 0x71 /* Write Any Register */ +#define FQSPI_FLASH_CMD_RDID 0x9F /* Read JEDEC ID */ +#define FQSPI_FLASH_CMD_4BAM 0xB7 /* Enter 4 Bytes Mode */ +#define FQSPI_FLASH_CMD_4BE 0xC7 /* Bulk erase */ +#define FQSPI_FLASH_CMD_SE 0xD8 /* Sector erase */ +#define FQSPI_FLASH_CMD_4SE 0xDC /* Sector erase */ +#define FQSPI_FLASH_CMD_4BEX 0xE9 /* Exit 4 Bytes Mode */ +#define FQSPI_FLASH_CMD_QIOR 0xEB /* Quad read data bytes */ +#define FQSPI_FLASH_CMD_4QIOR 0xEC /* Quad read data bytes */ +#define FQSPI_FLASH_DISCOVERABLE_PARAMETER 0x5a +#define FQSPI_CMD_ENABLE_RESET 0x66 +#define FQSPI_CMD_RESET 0x99 + + struct FQSpi_DataPack + { + u32 flags; /* Follow qspi cmd of transfer operation */ + u32 cmd; /* Command instruction */ + u32 addr; /* Flash address */ + u32 dummyCycle; /* dummy Cycle */ + const u8 *txBuf; + u8 *rxBuf; /* Need send or read buffer */ + u32 length; /* Buffer length */ + }; + + struct FQSpi_CmdPack + { + u32 flags; /* Follow qspi bsp command instruction operation */ + u32 cmd; /* Command instruction */ + u32 addr; /* Command address */ + u32 dummyCycle; /* dummy Cycle */ + const u8 *txBuf; + u8 *rxBuf; /* Need send or read buffer */ + u32 length; /* Buffer length */ + }; + + typedef struct + { + u32 instanceId; /* Id of device */ + uintptr_t baseAddress; /* Base address of qspi */ + u32 transMode; /* Transfer mode */ + u32 capacity; /* Flash capacity */ + u32 addrMode; /**/ + u32 clkDiv; + u32 qspiDevNum; /*Qspi device number */ + u32 channel; /* Cs number */ + u32 bitWidth; /* Transfer unit width */ + } FQSpi_Config_t; + + typedef struct + { + FQSpi_Config_t config; + u32 isReady; /**< Device is initialized and ready */ + + } FQSpi_t; + + /** + * @name: FQSpi_LookupConfig + * @msg: FQSpi_LookupConfig returns a reference FQSpi_Config_t structure based on the + * unique device id. + * @in param {u32} instanceId : unique device + * @return {FQSpi_Config_t} FQSpi_Config_t is a reference to a config record in the configuration + * table (in qspi_g.c) corresponding to instanceId, or NULL if no match is found. + */ + FQSpi_Config_t *FQSpi_LookupConfig(u32 instanceId); + + /** + * @name: FQSpi_CfgInitialize + * @msg: This function intializes the configuration for the qspi instance + * @in param {FQSpi_t *} pQspi: A pointer to the qspi instance + * @in param {FQSpi_Config_t *} pConfig: A pointer to the qspi instance config record + * @return {ft_error_t} + */ + ft_error_t FQSpi_CfgInitialize(FQSpi_t *pQspi, FQSpi_Config_t *pConfig); + + /** + * @name: FQSpi_CmdOperation + * @msg: This function send command instruction by the struct FQSpi_CmdPack + * @in param {FQSpi_t *} pQspi: A pointer to the qspi instance + * @in param {struct FQSpi_CmdPack *} pCmdPack: Need to send command instruction package + * @return {ft_error_t} + */ + ft_error_t FQSpi_CmdOperation(FQSpi_t *pQspi, struct FQSpi_CmdPack *pCmdPack); + + /** + * @name: FQSpi_Read + * @msg: This function reads flash data from a specific address by {struct FQSpi_DataPack} + * @in param {FQSpi_t *} pQspi: A pointer to the qspi instance + * @in param {struct FQSpi_DataPack *} pDataPack: Need to read data package + * @return {ft_error_t} + */ + ft_error_t FQSpi_Read(FQSpi_t *pQspi, struct FQSpi_DataPack *pDataPack); + + /** + * @name: FQSpi_Write + * @msg: This function writes data from a specific address by {struct FQSpi_DataPack} + * @in param {FQSpi_t *} pQspi: A pointer to the qspi instance + * @in param {struct FQSpi_DataPack *} pDataPack: Need to read data package + * @return {ft_error_t} + */ + ft_error_t FQSpi_Write(FQSpi_t *pQspi, struct FQSpi_DataPack *pDataPack); + + /** + * @name: FQSpi_FlashRegSet + * @msg: This function sends command instruction with specific parameters + * @in param {FQSpi_t *} pQspi: A pointer to the qspi instance + * @in param {FT_IN u8} cmd: Command instruction + * @in param {FT_IN u8 *} writebuf: Data that needs to be sent through command instruction registers + * @in param {u32} length: Data length + * @return {ft_error_t} + */ + ft_error_t FQSpi_FlashRegSet(FQSpi_t *pQspi, + FT_IN u8 cmd, + FT_IN u8 *writebuf, + u32 length); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/ft_qspi/qspi_g.c b/bsp/ft2004/libraries/bsp/ft_qspi/qspi_g.c new file mode 100644 index 0000000000000000000000000000000000000000..044c0e427cd711b82f79b776ef0a7ad9f49346c9 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_qspi/qspi_g.c @@ -0,0 +1,50 @@ +/* + * @[H]: Copyright (C) 2014-2021 Tianjin Phytium Technology.  All rights reserved. + * + *  Permission is hereby granted, free of charge, to any person obtaining a copy + *  of this software and associated documentation files (the "Software"), to deal + *  in the Software without restriction, including without limitation the rights + *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + *  copies of the Software, and to permit persons to whom the Software is + *  furnished to do so, subject to the following conditions: + * + *  The above copyright notice and this permission notice shall be included in + *  all copies or substantial portions of the Software. + * + *  Use of the Software is limited solely to applications: + *  (a) running on a Phytium device, or + *  (b) that interact with a Phytium device through a bus or interconnect. + * + *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + *  PHYTIUM  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + *  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + *  SOFTWARE. + * + *  Except as contained in this notice, the name of the Phytium shall not be used + *  in advertising or otherwise to promote the sale, use or other dealings in + *  this Software without prior written authorization from Phytium.  + * + * @Date: 2021-04-07 11:31:12 + * @LastEditTime: 2021-04-07 11:31:13 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + * * v1.0 hh 2021-04-07 init + */ +#include "ft_qspi.h" +#include "ft_parameters.h" + +FQSpi_Config_t FqSpi_ConfigTable[FT_QSPI_NUM] = { + {.instanceId = FT_QSPI_INSTANCE, /* Id of device */ + .baseAddress = FT_QSPI_BASEADDR, /* Base address of qspi */ + .transMode = FT_QSPI_TRANSFER_1_1_1, /* Transfer mode */ + .capacity = FT_QSPI_FLASH_CAP_32MB, /* Flash capacity */ + .addrMode = FT_QSPI_ADDR_SEL_3, /**/ + .clkDiv = FT_QSPI_SCK_DIV_128, + .qspiDevNum = 1, + .channel = 0, + .bitWidth = 8}}; \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/ft_qspi/qspi_hw.c b/bsp/ft2004/libraries/bsp/ft_qspi/qspi_hw.c new file mode 100644 index 0000000000000000000000000000000000000000..fe3bb24cc8ef586b26bcf60b4ebe716990fe9436 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_qspi/qspi_hw.c @@ -0,0 +1,49 @@ +/* + * @[H]: Copyright (C) 2014-2021 Tianjin Phytium Technology.  All rights reserved. + * + *  Permission is hereby granted, free of charge, to any person obtaining a copy + *  of this software and associated documentation files (the "Software"), to deal + *  in the Software without restriction, including without limitation the rights + *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + *  copies of the Software, and to permit persons to whom the Software is + *  furnished to do so, subject to the following conditions: + * + *  The above copyright notice and this permission notice shall be included in + *  all copies or substantial portions of the Software. + * + *  Use of the Software is limited solely to applications: + *  (a) running on a Phytium device, or + *  (b) that interact with a Phytium device through a bus or interconnect. + * + *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + *  PHYTIUM  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + *  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + *  SOFTWARE. + * + *  Except as contained in this notice, the name of the Phytium shall not be used + *  in advertising or otherwise to promote the sale, use or other dealings in + *  this Software without prior written authorization from Phytium.  + * + * @Date: 2021-04-02 18:32:42 + * @LastEditTime: 2021-04-02 18:32:43 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + */ +#include "qspi_hw.h" +#include "ft_qspi.h" +#include "ft_assert.h" +#include "ft_io.h" + +void FQSpi_Reset(FQSpi_t *pQspi) +{ + FQSpi_Config_t *pConfig = NULL; + Ft_assertVoid(pQspi != NULL); + pConfig = &pQspi->config; + Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CAP_OFFSET, + FT_REG_QSPI_CAP_FLASH_NUM(pConfig->qspiDevNum) | FT_REG_QSPI_CAP_FLASH_CAP(pConfig->capacity)); +} diff --git a/bsp/ft2004/libraries/bsp/ft_qspi/qspi_hw.h b/bsp/ft2004/libraries/bsp/ft_qspi/qspi_hw.h new file mode 100644 index 0000000000000000000000000000000000000000..cabe5da888daf7cadd8d2c588b4ba20a9f1e34d8 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_qspi/qspi_hw.h @@ -0,0 +1,223 @@ +/* + * @[H]: Copyright (C) 2014-2021 Tianjin Phytium Technology.  All rights reserved. + * + *  Permission is hereby granted, free of charge, to any person obtaining a copy + *  of this software and associated documentation files (the "Software"), to deal + *  in the Software without restriction, including without limitation the rights + *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + *  copies of the Software, and to permit persons to whom the Software is + *  furnished to do so, subject to the following conditions: + * + *  The above copyright notice and this permission notice shall be included in + *  all copies or substantial portions of the Software. + * + *  Use of the Software is limited solely to applications: + *  (a) running on a Phytium device, or + *  (b) that interact with a Phytium device through a bus or interconnect. + * + *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + *  PHYTIUM  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + *  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + *  SOFTWARE. + * + *  Except as contained in this notice, the name of the Phytium shall not be used + *  in advertising or otherwise to promote the sale, use or other dealings in + *  this Software without prior written authorization from Phytium.  + * + * @Date: 2021-04-02 18:32:54 + * @LastEditTime: 2021-04-02 21:30:00 + * @Description:  Description of file + * + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + */ + +#ifndef QSPI_HW_H +#define QSPI_HW_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ft_qspi.h" +#include "ft_types.h" + +/* register definition */ +#define FT_REG_QSPI_CAP_OFFSET (0x00) /* Flash capacity setting register */ +#define FT_REG_QSPI_RD_CFG_OFFSET (0x04) /* Address access reads configuration registers */ +#define FT_REG_QSPI_WR_CFG_OFFSET (0x08) /* Write buffer flush register */ +#define FT_REG_QSPI_FLUSH_OFFSET (0x0C) /* Write buffer flush register */ +#define FT_REG_QSPI_CMD_PORT_OFFSET (0x10) /* Command port register */ +#define FT_REG_QSPI_ADDR_PORT_OFFSET (0x14) /* Address port register */ +#define FT_REG_QSPI_HD_PORT_OFFSET (0x18) /* Upper bit port register */ +#define FT_REG_QSPI_LD_PORT_OFFSET (0x1C) /* low bit port register */ +#define FT_REG_QSPI_FUN_SET_OFFSET (0x20) /* CS setting register */ +#define FT_REG_QSPI_WIP_RD_OFFSET (0x24) /* WIP reads the Settings register */ +#define FT_REG_QSPI_WP_OFFSET (0x28) /* WP register */ +#define FT_REG_QSPI_MODE_OFFSET (0x2C) /* Mode setting register */ + +/*QSPI_CAP*/ +#define FT_REG_QSPI_CAP_FLASH_NUM(data) ((data) << 3) /* Flash number */ +#define FT_REG_QSPI_CAP_FLASH_CAP(data) ((data) << 0) /* The flash capacity */ + +/* RD_CFG */ +#define FT_RD_CFG_CMD(data) ((data) << 24) /* Read Command */ +#define FT_RD_CFG_THROUGH(data) ((data) << 23) /* The programming flag in the status register */ +#define FT_RD_CFG_TRANSFER(data) ((data) << 20) /* */ +#define FT_RD_CFG_ADDR_SEL(data) ((data) << 19) /* */ +#define FT_RD_CFG_LATENCY(data) ((data) << 18) /* */ +#define FT_RD_CFG_MODE_BYTE(data) ((data) << 17) /* */ +#define FT_RD_CFG_CMD_SIGN(data) ((data) << 9) /* */ +#define FT_RD_CFG_DUMMY(data) ((data) << 4) /* */ +#define FT_RD_CFG_D_BUFFER(data) ((data) << 3) /* */ +#define FT_RD_CFG_SCK_SEL(data) ((data) << 0) /* */ + +/*QSPI_WR_CFG*/ +#define FT_WR_CFG_CMD(data) ((data) << 24) +#define FT_WR_CFG_WAIT(data) ((data) << 9) +#define FT_WR_CFG_THROUGH(data) ((data) << 8) +#define FT_WR_CFG_TRANSFER(data) ((data) << 5) +#define FT_WR_CFG_ADDRSEL(data) ((data) << 4) +#define FT_WR_CFG_MODE(data) ((data) << 3) +#define FT_WR_CFG_SCK_SEL(data) ((data) << 0) + +/*QSPI_CMD_PORT*/ +#define FT_CMD_PORT_CMD(data) ((data) << 24) +#define FT_CMD_PORT_WAIT(data) ((data) << 22) +#define FT_CMD_PORT_THROUGH(data) ((data) << 21) +#define FT_CMD_PORT_CS(data) ((data) << 19) +#define FT_CMD_PORT_TRANSFER(data) ((data) << 16) +#define FT_CMD_PORT_ADDR(data) ((data) << 15) +#define FT_CMD_PORT_LATENCY(data) ((data) << 14) +#define FT_CMD_PORT_DATA_TRANS(data) ((data) << 13) +#define FT_CMD_PORT_ADDR_SEL(data) ((data) << 12) +#define FT_CMD_PORT_DUMMY(data) ((data) << 7) +#define FT_CMD_PORT_P_BUFFER(data) ((data) << 6) +#define FT_CMD_PORT_RW_NUM(data) ((data) << 3) +#define FT_CMD_PORT_CLK_SEL(data) ((data) << 0) + +/*QSPI_FUN_SET*/ +#define FT_FUN_SET_CS_HOLD(data) ((data) << 24) +#define FT_FUN_SET_CS_SETUP(data) ((data) << 16) +#define FT_FUN_SET_CS_DELAY(data) ((data) << 0) + +/*QSPI_WIP_RD*/ +#define FT_WIP_RD_CMD(data) ((data) << 24) +#define FT_WIP_RD_TRANSFER(data) ((data) << 3) +#define FT_WIP_RD_SCK_SEL(data) ((data) << 0) + +/*QSPI_WP*/ +#define FT_WP_EN(data) ((data) << 17) +#define FT_WP_WP(data) ((data) << 16) +#define FT_WP_HOLD(data) ((data) << 8) +#define FT_WP_SETUP(data) ((data) << 0) + +/*QSPI_MODE*/ +#define FT_MODE_VALID(data) ((data) << 8) +#define FT_MODE_MODE(data) ((data) << 0) + +#define FT_QSPI_FLASH_CAP_4MB 0 +#define FT_QSPI_FLASH_CAP_8MB 1 +#define FT_QSPI_FLASH_CAP_16MB 2 +#define FT_QSPI_FLASH_CAP_32MB 3 +#define FT_QSPI_FLASH_CAP_64MB 4 +#define FT_QSPI_FLASH_CAP_128MB 5 +#define FT_QSPI_FLASH_CAP_256MB 6 + +#define FT_QSPI_ADDR_SEL_3 0 +#define FT_QSPI_ADDR_SEL_4 1 + +#define FT_QSPI_SCK_DIV_128 0 +#define FT_QSPI_SCK_DIV_2 1 +#define FT_QSPI_SCK_DIV_4 2 +#define FT_QSPI_SCK_DIV_8 3 +#define FT_QSPI_SCK_DIV_16 4 +#define FT_QSPI_SCK_DIV_32 5 +#define FT_QSPI_SCK_DIV_64 6 + +#define FT_QSPI_TRANSFER_1_1_1 0 +#define FT_QSPI_TRANSFER_1_1_2 1 +#define FT_QSPI_TRANSFER_1_1_4 2 +#define FT_QSPI_TRANSFER_1_2_2 3 +#define FT_QSPI_TRANSFER_1_4_4 4 +#define FT_QSPI_TRANSFER_2_2_2 5 +#define FT_QSPI_TRANSFER_4_4_4 6 + + /* typedefs */ + /*QSPI_RD_CFG*/ + typedef union + { + u32 data; + struct + { + u32 rdSckSel : 3; /* 2:0 */ + u32 dBuffer : 1; /* 3 */ + u32 dummy : 5; /* 8:4 */ + u32 cmdSign : 8; /* 16:9 */ + u32 modeByte : 1; /* 17 */ + u32 rdLatency : 1; /* 18 */ + u32 rdAddrSel : 1; /* 19 */ + u32 rdTransfer : 3; /* 22:20 */ + u32 rdThrough : 1; /* 23 */ + u32 rdCmd : 8; /* 31:24 */ + } val; + } FQSpi_RdCfgReg_t; + + /*QSPI_WR_CFG*/ + typedef union + { + u32 data; + struct + { + u32 wrSckSel : 3; /* 2:0 */ + u32 wrMode : 1; /* 3 */ + u32 wrAddrsel : 1; /* 4 */ + u32 wrTransfer : 3; /* 7:5 */ + u32 wrThrough : 1; /* 8 */ + u32 wrWait : 1; /* 9 */ + u32 wrRes : 14; /* 23:10 */ + u32 wrCmd : 8; /* 31:24 */ + } val; + } FQSpi_WrCfgReg_t; + + /*QSPI_CMD_PORT*/ + typedef union + { + u32 data; + struct + { + u32 sckSel : 3; /* 2:0 */ + u32 rwMum : 3; /* 5:3 */ + u32 pBuffer : 1; /* 6 */ + u32 dummy : 5; /* 11:7 */ + u32 addrSel : 1; /* 12 */ + u32 dataTransfer : 1; /* 13 */ + u32 latency : 1; /* 14 */ + u32 cmdAddr : 1; /* 15 */ + u32 transfer : 3; /* 18:16 */ + u32 cs : 2; /* 20:19 */ + u32 through : 1; /* 21 */ + u32 wait : 1; /* 22 */ + u32 res : 1; /* 23 */ + u32 cmd : 8; /* 31:24 */ + } val; + } FQSpi_CmdPortReg_t; + + /** + * @name: FQSpi_Reset + * @msg: This routine performs the QSPI controller initialization. + * @in param: pQspi + * @return {*} + */ + void FQSpi_Reset(FQSpi_t *pQspi); + +#ifdef __cplusplus +} +#endif + +#endif // ! diff --git a/bsp/ft2004/libraries/bsp/ft_qspi/qspi_sinit.c b/bsp/ft2004/libraries/bsp/ft_qspi/qspi_sinit.c new file mode 100644 index 0000000000000000000000000000000000000000..79a30bae59e6c1c84ade99e690e45a8c7b1b58e2 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_qspi/qspi_sinit.c @@ -0,0 +1,58 @@ +/* + * @[H]: Copyright (C) 2014-2021 Tianjin Phytium Technology.  All rights reserved. + * + *  Permission is hereby granted, free of charge, to any person obtaining a copy + *  of this software and associated documentation files (the "Software"), to deal + *  in the Software without restriction, including without limitation the rights + *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + *  copies of the Software, and to permit persons to whom the Software is + *  furnished to do so, subject to the following conditions: + * + *  The above copyright notice and this permission notice shall be included in + *  all copies or substantial portions of the Software. + * + *  Use of the Software is limited solely to applications: + *  (a) running on a Phytium device, or + *  (b) that interact with a Phytium device through a bus or interconnect. + * + *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + *  PHYTIUM  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + *  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + *  SOFTWARE. + * + *  Except as contained in this notice, the name of the Phytium shall not be used + *  in advertising or otherwise to promote the sale, use or other dealings in + *  this Software without prior written authorization from Phytium.  + * + * @Date: 2021-04-07 13:22:01 + * @LastEditTime: 2021-04-07 13:22:01 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + */ + +#include "ft_qspi.h" +#include "ft_parameters.h" + +extern FQSpi_Config_t FqSpi_ConfigTable[FT_QSPI_NUM]; + +FQSpi_Config_t *FQSpi_LookupConfig(u32 instanceId) +{ + FQSpi_Config_t *pFQSpi_Config_t = NULL; + + u32 Index; + for (Index = 0; Index < (u32)FT_GMAC_INSTANCES_NUM; Index++) + { + if (FqSpi_ConfigTable[Index].instanceId == instanceId) + { + pFQSpi_Config_t = &FqSpi_ConfigTable[Index]; + break; + } + } + + return pFQSpi_Config_t; +} diff --git a/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl.c b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl.c new file mode 100644 index 0000000000000000000000000000000000000000..d1f8b5c43d2124cfcd49258b34a57f7ba1e0fe72 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl.c @@ -0,0 +1,718 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology(TianJin), Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-03-31 14:59:20 + * @LastEditTime: 2021-04-15 13:57:52 + * @Description:  This files is for implemenation of sd ctrl + * + * @Modify History: * * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_parameters.h" +#include "ft_assert.h" +#include "ft_io.h" +#include "ft_sdctrl.h" +#include "ft_sdctrl_hw.h" +#include "ft_debug.h" +#include "ft_printf.h" +#include "ft_trace.h" +#include "ft_cache.h" +#define FT_SD_CTRL_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FT_SD_CTRL_DEBUG_TAG, format, ##__VA_ARGS__) +#define FT_SD_CTRL_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(FT_SD_CTRL_DEBUG_TAG, format, ##__VA_ARGS__) +#define FT_SD_CTRL_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FT_SD_CTRL_DEBUG_TAG, format, ##__VA_ARGS__) + +/** + * @Description: setup sd ctrl clk freq + * @Date: 2021-04-01 09:28:28 + * @Param: + * @return {*} + * @param {FT_INOUT FtsdCtrl_t} *pFtsdCtrl + * @param {FT_IN u32} sdClk, clk from SD + */ +void FSdCtrl_ClkFreqSetup(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN u32 sdClk) +{ + FSdCtrl_Config_t *pConfig; + u32 clkDiv; + u32 inputClk; + u32 tmpSdFreq; + u32 workSpeed; + + Ft_assertVoid(FT_NULL != pFtsdCtrl); + pConfig = &pFtsdCtrl->config; + inputClk = pConfig->inputClockHz; + + /* sd work speed is limit to 25MHz */ + workSpeed = (sdClk < SD_CLK_FREQ_25MHZ) ? sdClk : SD_CLK_FREQ_25MHZ; + + /* if sd clk freq is valid and is two times greater than io input clk */ + if ((SD_CLK_FREQ_400KHZ < workSpeed) && (inputClk > (2 * workSpeed))) + { + clkDiv = (u32)(inputClk / (2 * workSpeed)) - 1; + + /* calculte sd freq one more time base on divsor */ + tmpSdFreq = (u32)inputClk / (2 * (clkDiv + 1)); + + /* if calculated sd freq is greater than the real val */ + if (tmpSdFreq > workSpeed) + { + clkDiv += 1; + } + } + else + { + clkDiv = SD_FRRQ_DIV_DEFAULT; + } + + Ft_out32(pConfig->baseAddress + CLOCK_DIV_REG_OFFSET, clkDiv); + + return; +} + +/** + * @name: FsdCtrl_Init + * @msg: init sd ctrl + * @in param: + * @inout param: + * @out param: + * @return {*} + * @param {FT_INOUT FtsdCtrl_t} *pFtsdCtrl + */ +ft_error_t FsdCtrl_Init(FT_INOUT FtsdCtrl_t *pFtsdCtrl) +{ + FSdCtrl_Config_t *pConfig; + Ft_assertNonvoid(FT_NULL != pFtsdCtrl); + pConfig = &pFtsdCtrl->config; + + /* Disable card detection */ + Ft_out32(pConfig->baseAddress + SD_SEN_REG_OFFSET, 0); + + /* Disable all interrupts */ + Ft_out32(pConfig->baseAddress + NORMAL_INT_EN_REG_OFFSET, 0); + Ft_out32(pConfig->baseAddress + ERROR_INT_EN_REG_OFFSET, 0); + Ft_out32(pConfig->baseAddress + BD_ISR_EN_REG_OFFSET, 0); + // Ft_out32(pConfig->baseAddress + NORMAL_INT_EN_REG_OFFSET, NORMAL_INT_EN_ECCRCE); + + /* Clear status register */ + Ft_out32(pConfig->baseAddress + NORMAL_INT_STATUS_REG, 0); + Ft_out32(pConfig->baseAddress + ERROR_INT_STATUS_REG, 0); + Ft_out32(pConfig->baseAddress + BD_ISR_REG, 0); + + /* Set default ctrl register */ + Ft_out32(pConfig->baseAddress + CONTROLL_SETTING_REG_OFFSET, 0x0f00); + + /* Set default drive and sampling register */ + Ft_out32(pConfig->baseAddress + SD_DRV_REG_OFFSET, 0); + Ft_out32(pConfig->baseAddress + SD_SAMP_REG_OFFSET, 0); + + /* Configure to default cmd data timeout */ + Ft_out32(pConfig->baseAddress + TIMEOUT_CMD_REG_OFFSET, 0xFFFFFFFF); + //FSdCtrl_ClkFreqSetup(pFtsdCtrl, 1); + + Ft_out32(pConfig->baseAddress + CLOCK_DIV_REG_OFFSET, SD_FRRQ_DIV_DEFAULT); + Ft_out32(pConfig->baseAddress + SD_SAMP_REG_OFFSET, SD_SAMP_DEFAULT); + + pFtsdCtrl->isReady = FT_COMPONENT_IS_READLY; + + return FTSDC_SUCCESS; +} + +/** + * @name: FSdCtrl_CardDetect + * @msg: + * @in param {FtsdCtrl_t} *pFtsdCtrl + * @inout param: + * @out param: + * @return {*} + */ +bool_t FSdCtrl_CardDetect(FT_INOUT FtsdCtrl_t *pFtsdCtrl) +{ + FSdCtrl_Config_t *pConfig; + u32 status; + + Ft_assertBool(FT_NULL != pFtsdCtrl); + pConfig = &pFtsdCtrl->config; + status = Ft_in32(pConfig->baseAddress + STATUS_REG); + + /* check card-detection signal */ + if (((status)&STATUS_REG_CDSL) == STATUS_REG_CDSL) + { + pConfig->cardDetect = 0; + } + else + { + pConfig->cardDetect = 1; + } + + return pConfig->cardDetect; +} + +/** + * @name: + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + * @param {FT_INOUT FtsdCtrl_t} *pFtsdCtrl + */ +void FSdCtrl_ResetDma(FT_INOUT FtsdCtrl_t *pFtsdCtrl) +{ + FSdCtrl_Config_t *pConfig; + Ft_assertVoid(FT_NULL != pFtsdCtrl); + pConfig = &pFtsdCtrl->config; + + Ft_setBit32((UINTPTR)(pConfig->baseAddress + SOFTWARE_RESET_REG_OFFSET), SOFTWARE_RESET_BDRST); + Ft_clearBit32((UINTPTR)(pConfig->baseAddress + SOFTWARE_RESET_REG_OFFSET), SOFTWARE_RESET_BDRST); +} + +/** + * @name: + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + * @param {FT_INFtsdCtrl_t} *pFtsdCtrl + * @param {FT_INu32} cmdIndex + * @param {FT_INu32} rspType + */ +u32 FSdCtrl_PrepareCmdRaw(FT_IN u32 cmdIndex, FT_IN u32 rspType) +{ + u32 rawCmd = 0; + + rawCmd |= CMD_SETTING_CMDI(cmdIndex); + + switch (rspType) + { + case FTSDCTRL_CMD_RES_NONE: + rawCmd |= CMD_SETTING_RTS(0); + break; + case FTSDCTRL_CMD_RES_LONG: + rawCmd |= CMD_SETTING_RTS(1); + break; + case FTSDCTRL_CMD_RES_SHORT: + rawCmd |= CMD_SETTING_RTS(2); + break; + default: + rawCmd |= CMD_SETTING_RTS(0); + break; + } + + return rawCmd; +} + +/** + * Description: sd ctrl write data + * Date: 2021-03-31 11:12:09 + * Param: + * return {*} + * param {FT_INOUT FtsdCtrl_t} *pFtsdCtrl + * param {FT_IN UINTPTR} dataAddr, src addr + * param {FT_IN UINTPTR} cardAddr, dst addr + * param {FT_IN u32} blkNum, num of blks to write + */ +void FSdCtrl_WriteData(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN UINTPTR dataAddr, + FT_IN UINTPTR cardAddr, FT_IN u32 blkNum) +{ + + FSdCtrl_Config_t *pConfig; + Ft_assertVoid(FT_NULL != pFtsdCtrl); + pConfig = &pFtsdCtrl->config; + + /* write 1 to clear data status register and command status register */ + Ft_out32(pConfig->baseAddress + BD_ISR_REG, BD_ISR_REG_TRS); + Ft_out32(pConfig->baseAddress + NORMAL_INT_STATUS_REG, NORMAL_INT_STATUS_CC); + + /* set DMA BD */ + Ft_setBit32((UINTPTR)(pConfig->baseAddress + SOFTWARE_RESET_REG_OFFSET), SOFTWARE_RESET_BDRST); + Ft_clearBit32((UINTPTR)(pConfig->baseAddress + SOFTWARE_RESET_REG_OFFSET), SOFTWARE_RESET_BDRST); + + /* set transfer lenth */ + Ft_out32(pConfig->baseAddress + BLK_CNT_REG, blkNum); + + /* set DMA discriptor data low address,data high address,card low address,card high address*/ + Ft_out32(pConfig->baseAddress + DAT_IN_M_TX_BD, dataAddr); + Ft_out32(pConfig->baseAddress + DAT_IN_M_TX_BD, 0); + Ft_out32(pConfig->baseAddress + DAT_IN_M_TX_BD, cardAddr); + Ft_out32(pConfig->baseAddress + DAT_IN_M_TX_BD, 0); +} + +/** + * @name: + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + */ +void FSdCtrl_ReadData(FT_INOUT FtsdCtrl_t *pFtsdCtrl, + FT_IN UINTPTR dataAddr, + FT_IN UINTPTR cardAddr, + FT_IN u32 blkNum) +{ + FSdCtrl_Config_t *pConfig; + Ft_assertVoid(FT_NULL != pFtsdCtrl); + pConfig = &pFtsdCtrl->config; + + /* clear data status register and command status register */ + Ft_out32(pConfig->baseAddress + BD_ISR_REG, BD_ISR_EN_ETRS); + Ft_out32(pConfig->baseAddress + NORMAL_INT_STATUS_REG, NORMAL_INT_EN_ECC); + + /* set DMA BD */ + Ft_setBit32((UINTPTR)(pConfig->baseAddress + SOFTWARE_RESET_REG_OFFSET), SOFTWARE_RESET_BDRST); + Ft_clearBit32((UINTPTR)(pConfig->baseAddress + SOFTWARE_RESET_REG_OFFSET), SOFTWARE_RESET_BDRST); + + /* set transfer lenth */ + Ft_out32(pConfig->baseAddress + BLK_CNT_REG, blkNum); + + /* set DMA discriptor data low address,data high address,card low address,card high address*/ + + Ft_out32(pConfig->baseAddress + DAT_IN_M_RX_BD, dataAddr); + Ft_out32(pConfig->baseAddress + DAT_IN_M_RX_BD, 0); + Ft_out32(pConfig->baseAddress + DAT_IN_M_RX_BD, cardAddr); + Ft_out32(pConfig->baseAddress + DAT_IN_M_RX_BD, 0); +} + +/** + * Description: send ctrl cmd + * Date: 2021-03-31 10:51:33 + * Param: + * return {*} + * param {FT_INOUT FtsdCtrl_t} *pFtsdCtrl + * param {FT_IN pFtsdCtrl_delayTimer_t} pDelayTimer_fun + * param {FT_IN u32} cmd + * param {FT_IN u32} respType + * param {FT_IN u32} arg + */ +static ft_error_t FsdCtrl_privateSendCmd(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN pFtsdCtrl_delayTimer_t pDelayTimer_fun, FT_IN u32 cmd, FT_IN u32 respType, FT_IN u32 arg) +{ + u32 temp; + u32 sd_cmd; + u32 sd_arg; + FSdCtrl_Config_t *pConfig; + Ft_assertNonvoid(FT_NULL != pFtsdCtrl); + pConfig = &pFtsdCtrl->config; + + /* enable cmd finished irq */ + Ft_out32(pConfig->baseAddress + NORMAL_INT_STATUS_REG, NORMAL_INT_EN_ECC); + Ft_out32(pConfig->baseAddress + NORMAL_INT_STATUS_REG, 0); + + Ft_out32(pConfig->baseAddress + ERROR_INT_STATUS_REG, BD_ISR_EN_ETRS); + Ft_out32(pConfig->baseAddress + ERROR_INT_STATUS_REG, 0); + + /* prepare cmd msg, along with arg */ + sd_cmd = FSdCtrl_PrepareCmdRaw(cmd, respType); + sd_arg = arg; + + /* send cmd and arg */ + Ft_out32(pConfig->baseAddress + CMD_SETTING_REG_OFFSET, sd_cmd); + Ft_out32(pConfig->baseAddress + ARGUMENT_REG_OFFSET, sd_arg); + + if (pConfig->workMode & FTSDCTRL_CMD_IRQ_MASK) + { + if (pFtsdCtrl->cmdWaitCallback) + { + /* if irq is enabled and call back registered, enter call back procedure */ + return pFtsdCtrl->cmdWaitCallback(pFtsdCtrl); + } + else + { + return FTSDC_INVALID_PARAM; + } + } + else + { + temp = Ft_in32(pConfig->baseAddress + NORMAL_INT_STATUS_REG); + /* polling wait for cmd-finished response */ + while (NORMAL_INT_STATUS_CC != (temp & NORMAL_INT_STATUS_CC)) + { + temp = Ft_in32(pConfig->baseAddress + NORMAL_INT_STATUS_REG); + pDelayTimer_fun(1); + } + } + + return FTSDC_SUCCESS; +} + +/** + * Description: wait data write procedure to end + * Date: 2021-03-31 11:28:41 + * Param: + * return {*} + */ +ft_error_t FSdCtrl_WaitWriteDataEnd(FT_INOUT FtsdCtrl_t *pFtsdCtrl, + FT_IN pFtsdCtrl_delayTimer_t pDelayTimer_fun, + FT_IN u32 blkNum) +{ + u32 status; + u32 statusMask; + ft_error_t ret; + s32 timeout = 1000; + FSdCtrl_Config_t *pConfig; + + Ft_assertNonvoid(FT_NULL != pFtsdCtrl); + pConfig = &pFtsdCtrl->config; + + if (pConfig->workMode & FTSDCTRL_DATA_WRITE_IRQ_MASK) + { + /* enter irq mode */ + if (NULL == pFtsdCtrl->writeWaitCallback) + { + return FTSDC_INVALID_PARAM; + } + + ret = pFtsdCtrl->writeWaitCallback(pFtsdCtrl); + if (FTSDC_SUCCESS != ret) + { + return FTSDC_EILSEQ; + } + } + else + { + /* wait for DMA-error or DMA-finished status */ + statusMask = BD_ISR_REG_DAIS | BD_ISR_REG_TRS; + do + { + status = (Ft_in32(pConfig->baseAddress + BD_ISR_REG) & statusMask); + pDelayTimer_fun(1); + timeout--; + } while ((!status) && timeout); + + if (status & BD_ISR_REG_DAIS) + { + if (status & (BD_ISR_REG_TRE | BD_ISR_REG_NRCRC | BD_ISR_REG_CMDE)) + { + return FTSDC_EILSEQ; + } + else if (!timeout) + { + return FTSDC_TIMEOUT; + } + } + } + + /* multi block needs MMC_STOP_TRANSMISSION to stop process*/ + if (blkNum > 1) + { + return FsdCtrl_privateSendCmd(pFtsdCtrl, pDelayTimer_fun, 12, CMD_SETTING_RTS(2), 0); + } + + return FTSDC_SUCCESS; +} + +/** + * Description: wait for read data procedure end + * Date: 2021-03-31 11:25:25 + * Param: + * return {*} + */ +ft_error_t FSdCtrl_WaitReadDataEnd(FT_INOUT FtsdCtrl_t *pFtsdCtrl, + FT_IN pFtsdCtrl_delayTimer_t pDelayTimer_fun, + FT_IN u32 blkNum) +{ + u32 status; + u32 statusMask; + ft_error_t ret; + s32 timeout = 1000; + FSdCtrl_Config_t *pConfig; + + Ft_assertNonvoid(FT_NULL != pFtsdCtrl); + pConfig = &pFtsdCtrl->config; + + if (pConfig->workMode & FTSDCTRL_DATA_READ_IRQ_MASK) + { + if (pFtsdCtrl->readWaitCallback) + { + ret = pFtsdCtrl->readWaitCallback(pFtsdCtrl); + if (FTSDC_SUCCESS != ret) + { + return FTSDC_EILSEQ; + } + } + else + { + return FTSDC_INVALID_PARAM; + } + } + else + { + /* wait for DMA-error or Read-finish status */ + statusMask = BD_ISR_REG_DAIS | BD_ISR_REG_RESPE; + do + { + status = (Ft_in32(pConfig->baseAddress + BD_ISR_REG) & statusMask); + pDelayTimer_fun(1); + timeout--; + } while ((!status) && timeout); + + if (status & BD_ISR_REG_DAIS) + { + /* error handle */ + if (status & (BD_ISR_REG_TRE | BD_ISR_REG_NRCRC | BD_ISR_REG_CMDE)) + { + return FTSDC_EILSEQ; + } + else if (!timeout) + { + return FTSDC_TIMEOUT; + } + } + } + + // /* multi block needs MMC_STOP_TRANSMISSION to stop process*/ + if (blkNum > 1) + { + return FsdCtrl_privateSendCmd(pFtsdCtrl, pDelayTimer_fun, 12, CMD_SETTING_RTS(2), 0); + } + + return FTSDC_SUCCESS; +} + +/** + * Description: wait for cmd response + * Date: 2021-03-31 11:18:57 + * Param: + * return {*} + */ +ft_error_t FSdCtrl_WaitCmdEnd(FT_OUT FtsdCtrl_t *pFtsdCtrl, + FT_IN pFtsdCtrl_delayTimer_t pDelayTimer_fun, + FT_IN u32 rspType, + FT_OUT u32 *cmdRsp) +{ + u32 status; + u32 statusMask; + s32 timeout = 1000; + const FSdCtrl_Config_t *pConfig; + ft_error_t result = FST_SUCCESS; + + Ft_assertNonvoid(FT_NULL != pFtsdCtrl); + pConfig = &pFtsdCtrl->config; + + if (pConfig->workMode & FTSDCTRL_CMD_IRQ_MASK) + { + if (pFtsdCtrl->cmdWaitCallback) + { + result = pFtsdCtrl->cmdWaitCallback(pFtsdCtrl); + } + else + { + return FTSDC_INVALID_PARAM; + } + status = Ft_in32(pConfig->baseAddress + NORMAL_INT_STATUS_REG); + } + else + { + /* wait for cmd-error or cmd-finish respones */ + statusMask = NORMAL_INT_STATUS_EI | NORMAL_INT_STATUS_CC; + + do + { + status = (Ft_in32(pConfig->baseAddress + NORMAL_INT_STATUS_REG) & statusMask); + pDelayTimer_fun(1); + timeout--; + + } while ((!status) && timeout); + } + + if (status & NORMAL_INT_STATUS_EI) + { + /* error handle */ + status = Ft_in32(pConfig->baseAddress + ERROR_INT_STATUS_REG); + + if (!timeout) + { + return FTSDC_TIMEOUT; + } + else if ((status & NORMAL_INT_EN_ECCRCE)) + { + return FTSDC_EILSEQ; + } + } + + if (rspType != FTSDCTRL_CMD_RES_NONE) + { + /* get cmd respones */ + if (rspType == FTSDCTRL_CMD_RES_LONG) + { + cmdRsp[0] = Ft_in32(pConfig->baseAddress + CMD_RESP_1); + cmdRsp[1] = Ft_in32(pConfig->baseAddress + CMD_RESP_2); + cmdRsp[2] = Ft_in32(pConfig->baseAddress + CMD_RESP_3); + cmdRsp[3] = Ft_in32(pConfig->baseAddress + CMD_RESP_4); + } + else + { + cmdRsp[0] = Ft_in32(pConfig->baseAddress + CMD_RESP_1); + cmdRsp[1] = 0; + cmdRsp[2] = 0; + cmdRsp[3] = 0; + } + } + + return result; +} + +/** + * @name: + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + */ +void FSdCtrl_DoCmd(FT_INOUT FtsdCtrl_t *pFtsdCtrl, + FT_IN u32 cmdIndex, + FT_IN u32 rspType, + u32 arg) +{ + u32 cmd; + + FSdCtrl_Config_t *pConfig; + Ft_assertVoid(FT_NULL != pFtsdCtrl); + pConfig = &pFtsdCtrl->config; + + /* clear normal interrupt status */ + Ft_out32(pConfig->baseAddress + NORMAL_INT_STATUS_REG, NORMAL_INT_STATUS_EI); + + /* set command*/ + cmd = FSdCtrl_PrepareCmdRaw(cmdIndex, rspType); + Ft_out32(pConfig->baseAddress + CMD_SETTING_REG_OFFSET, cmd); + + if (cmdIndex == 41) + { + arg = 0x40ff8000; + } + + Ft_out32(pConfig->baseAddress + ARGUMENT_REG_OFFSET, arg); +} + +/** + * @name: + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + */ +void FSdCtrl_DoACmd(FT_INOUT FtsdCtrl_t *pFtsdCtrl, + FT_IN u32 cmdIndex, + FT_IN u32 rspType, + u32 arg) +{ + u32 cmd; + + FSdCtrl_Config_t *pConfig; + Ft_assertVoid(FT_NULL != pFtsdCtrl); + pConfig = &pFtsdCtrl->config; + + /* clear normal interrupt status */ + Ft_out32(pConfig->baseAddress + NORMAL_INT_STATUS_REG, NORMAL_INT_EN_ECC); + /* set command*/ + cmd = FSdCtrl_PrepareCmdRaw(cmdIndex, rspType); + cmd |= CMD_SETTING_TRTY(2); + Ft_out32(pConfig->baseAddress + CMD_SETTING_REG_OFFSET, cmd); +} + +/** + * @name: + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + * @param {FT_INOUT FtsdCtrl_t} *pFtsdCtrl + * @param {FT_IN pFtsdCtrl_irqWaitCallback_t} callBack + */ +void FSdCtrl_WriteWaitRegister(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN pFtsdCtrl_irqWaitCallback_t callBack) +{ + Ft_assertVoid(FT_NULL != pFtsdCtrl); + pFtsdCtrl->writeWaitCallback = callBack; +} + +/** + * @name: + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + * @param {FT_INOUT FtsdCtrl_t} *pFtsdCtrl + * @param {FT_IN pFtsdCtrl_irqWaitCallback_t} callBack + */ +void FSdCtrl_ReadWaitRegister(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN pFtsdCtrl_irqWaitCallback_t callBack) +{ + Ft_assertVoid(FT_NULL != pFtsdCtrl); + pFtsdCtrl->readWaitCallback = callBack; +} + +/** + * @name: + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + * @param {FT_INOUT FtsdCtrl_t} *pFtsdCtrl + * @param {FT_IN pFtsdCtrl_irqWaitCallback_t} callBack + */ +void FSdCtrl_CmdWaitRegister(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN pFtsdCtrl_irqWaitCallback_t callBack) +{ + Ft_assertVoid(FT_NULL != pFtsdCtrl); + pFtsdCtrl->cmdWaitCallback = callBack; +} + +/** + * @name: + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + * @param {FT_INOUT FtsdCtrl_t} *pFtsdCtrl + */ +u32 FSdCtrl_GetNormalIrqStatus(FT_INOUT FtsdCtrl_t *pFtsdCtrl) +{ + Ft_assertNonvoid(FT_NULL != pFtsdCtrl); + FSdCtrl_Config_t *pConfig; + pConfig = &pFtsdCtrl->config; + // rt_kprintf("FSdCtrl_GetNormalIrqStatus is in \r\n"); + return Ft_in32(pConfig->baseAddress + NORMAL_INT_STATUS_REG); +} + +/** + * @name: + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + * @param {FT_INOUT FtsdCtrl_t} *pFtsdCtrl + */ +u32 FSdCtrl_GetDataIrqStatus(FT_INOUT FtsdCtrl_t *pFtsdCtrl) +{ + Ft_assertNonvoid(FT_NULL != pFtsdCtrl); + FSdCtrl_Config_t *pConfig; + pConfig = &pFtsdCtrl->config; + + return Ft_in32(pConfig->baseAddress + BD_ISR_REG); +} + +/** + * @name: + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + * @param {FT_INOUT FtsdCtrl_t} *pFtsdCtrl + */ +u32 FSdCtrl_GetErrorIrqStatus(FT_INOUT FtsdCtrl_t *pFtsdCtrl) +{ + Ft_assertNonvoid(FT_NULL != pFtsdCtrl); + FSdCtrl_Config_t *pConfig; + pConfig = &pFtsdCtrl->config; + + return Ft_in32(pConfig->baseAddress + ERROR_INT_STATUS_REG); +} \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl.h b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl.h new file mode 100644 index 0000000000000000000000000000000000000000..1951645547deb9639178cf1344db6a7931afd014 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl.h @@ -0,0 +1,235 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology(TianJin), Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-03-31 14:59:20 + * @LastEditTime: 2021-04-19 17:04:44 + * @Description:  This files is for implementation of sd ctrl + * + * @Modify History: * * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef FTSDCTRL_H +#define FTSDCTRL_H +#include "ft_types.h" +#include "ft_error_code.h" + +/* sd ctrl module debug tag */ +#define FT_SD_CTRL_DEBUG_TAG "FT_SD_CTRL" + +/* definition of errcode for sd module */ +#define FTSDC_SUCCESS FST_SUCCESS /* 成功 */ +#define FTSDC_FAILURE FT_MAKE_ERRCODE(errModeSdCtrl, errBspGeneral, FST_FAILURE) /* Normal */ +#define FTSDC_TIMEOUT FT_MAKE_ERRCODE(errModeSdCtrl, errBspGeneral, FST_TIMEOUT) /* Timeout */ +#define FTSDC_EILSEQ FT_MAKE_ERRCODE(errModeSdCtrl, errBspGeneral, FST_EILSEQ) /* Illegal byte sequence. */ +#define FTSDC_INVALID_PARAM FT_MAKE_ERRCODE(errModeSdCtrl, errBspGeneral, FST_INVALID_PARAM) /* Illegal byte sequence. */ + +/* type of response to sd cmds */ +#define FTSDCTRL_CMD_RES_NONE 0 /* No response */ +#define FTSDCTRL_CMD_RES_LONG 1 /* The response length is long, code length is 128 */ +#define FTSDCTRL_CMD_RES_SHORT 2 /* The response length is short, code length is 32 */ + +/* irq enable bits */ +#define FTSDCTRL_DATA_WRITE_IRQ_MASK 0x1 +#define FTSDCTRL_DATA_READ_IRQ_MASK 0x2 +#define FTSDCTRL_CMD_IRQ_MASK 0x4 + +/* type of irq callback */ +typedef enum +{ + FTSDCTRL_DMADATAIRQID = 0x1U, /* Select dma interrupt */ + FTSDCTRL_CMDIRQID = 0x2U, /* Select cmd interrupt */ + FTSDCTRL_ERRORIRQID = 0x3U, /* Select error interrupt */ +} FSdCtrl_IrqCallbackSelect_t; + +/* normal irq enable bits for NORMAL_INT_EN_REG_OFFSET */ +typedef enum +{ + NORMAL_IRQ_CC = 1, /* Command completion interrupt */ + NORMAL_IRQ_CR = 2, /* Card removal interrupt */ + NORMAL_IRQ_EI = 4 /* Command error interrupt */ +} FSdCtrl_NormalIrqSelect_t; + +/* error irq enable bits for ERROR_INT_EN_REG_OFFSET */ +typedef enum +{ + ERROR_IRQ_CTE = 1, /* Command timeout error interrupted */ + ERROR_IRQ_CCRCE = 2, /* Command CRC error interrupt */ + ERROR_IRQ_CIR = 4, /* Command index error interrupt */ + ERROR_IRQ_CNR = 8 /* Command response error interrupted */ +} FSdCtrl_ErrorIrqSelect_t; + +/* data trans irq bits for BD_ISR_EN_REG_OFFSET */ +typedef enum +{ + BD_IRQ_TRS = 1, /* DMA transmission has been interrupted */ + BD_IRQ_DTE = 2, /* Timeout interrupt */ + BD_IRQ_CMDE = 4, /* Command response error interrupted */ + BD_IRQ_TRE = 8, /* Command response error interrupt CRC response error interrupt */ + BD_IRQ_NRCRC = 0x10, /* No CRC response interruption */ + BD_IRQ_DATFRAX = 0x20, /* AXI bus forces to release interrupts */ + BD_IRQ_RESPE = 0x40, /* Read SD card operation, AXI BR channel complete interrupt */ + BD_IRQ_DAIS = 0x80, /* DMA error interrupt */ +} FSdCtrl_BdIrqSelect; + +/* types of irq */ +typedef enum +{ + FTSDC_NORMAL_ISR = 0U, + FTSDC_BD_ISR, + FTSDC_ERROR_ISR +} FSdCtrl_IsrCallbackSelect_t; + +/* voltage supply range type of SD Card follow POWER_CONTROLL_REG +*/ +typedef enum +{ + FSDC_HIGH_V = 0, /* SD card operate within the voltage range of 2.7-3.6 V */ + FSDC_DUAL_V, /* SD card operate within the Low Voltage Range (T.B.D) and 2.7-3.6 V */ + + MAX_FSDC_VOLTAGE_TYPE +} FSdCtrl_VRangeType_t; + +/* read-write property of SD Card */ +typedef enum +{ + FSDC_RW_CARD = 0, + FSDC_RO_CARD, + + MAX_FSDC_WR_CARD_TYPE +} FSdCtrl_WRType_t; + +/* capacity type of SD Card */ +typedef enum +{ + FSDC_SD_CARD = 0, + FSDC_SDHC_CARD, + FSDC_SDXC_CARD, + + MAX_FSDC_CARD_CAPACITY_TYPE +} FSdCtrl_CapacityType_t; + +/* speed class of SD Card */ +typedef enum +{ + FSDC_CLASS0 = 0, + FSDC_CLASS2, + FSDC_CLASS4, + FSDC_CLASS6, + + MAX_FSDC_CLASS_TYPE +} FSdCtrl_ClassType_t; + +/** + * This typedef contains configuration information for the sd device. + */ +typedef struct +{ + u32 instanceId; /* Unique ID of device */ + u32 baseAddress; /* Base address of the device */ + u32 inputClockHz; /* Input clock frequency */ + u32 cardDetect; /* Card Detect */ + u32 writeProtect; /* Write Protect */ + u32 busWidth; /* Bus Width */ + u32 dmaIrqNum; /* dma irq number */ + u32 normalIrqNum; /* normal irq number */ + u32 errIrqNum; /* error irq number */ + u8 workMode; /* Work mode for data transfers , + If the mask bit is 0, polling is used , + follow irq enable bits*/ +} FSdCtrl_Config_t; + +typedef void (*FtsdCtrl_irqCallback_t)(void *args); + +/* irq callback and iput args */ +typedef struct +{ + FtsdCtrl_irqCallback_t pDmaDataCallback; /* DMA data interrupt function pointer */ + void *pDmaDataArgs; + + FtsdCtrl_irqCallback_t pCmdCallback; /* Commond interrupt function pointer */ + void *pCmdArgs; + + FtsdCtrl_irqCallback_t pErrorCallback; /* Error interrupt function pointer */ + void *pErrorArgs; +} FSdCtrl_IrqConfig_t; + +typedef struct FtsdCtrl FtsdCtrl_t; +typedef void (*pFtsdCtrl_delayTimer_t)(ft_base_t delayUs); +typedef ft_error_t (*pFtsdCtrl_irqWaitCallback_t)(FtsdCtrl_t *FtsdCtrl); + +/* ctrl instance of sd */ +struct FtsdCtrl +{ + FSdCtrl_Config_t config; + u32 isReady; /* Device is initialized and ready */ + /*************reserved**************/ + FSdCtrl_VRangeType_t voltageType; + FSdCtrl_WRType_t writeReadType; + FSdCtrl_CapacityType_t capacityType; + FSdCtrl_ClassType_t speedClassType; + /*************reserved**************/ + FSdCtrl_IrqConfig_t irqConfig; + pFtsdCtrl_irqWaitCallback_t writeWaitCallback; /* function pointer .Used to determine whether the data transmission is complete*/ + pFtsdCtrl_irqWaitCallback_t readWaitCallback; /* function pointer .Used to determine whether the data received is complete*/ + pFtsdCtrl_irqWaitCallback_t cmdWaitCallback; /* function pointer . Used to determine whether the command is complete */ +}; + +u32 FSdCtrl_PrepareCmdRaw(FT_IN u32 cmdIndex, FT_IN u32 rspType); +void FSdCtrl_WriteData(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN UINTPTR dataAddr, FT_IN UINTPTR cmdArg, FT_IN u32 blkNum); +void FSdCtrl_ReadData(FT_INOUT FtsdCtrl_t *pFtsdCtrl, + FT_IN UINTPTR dataAddr, + FT_IN UINTPTR cardAddr, + FT_IN u32 blkNum); +ft_error_t FSdCtrl_WaitCmdEnd(FT_OUT FtsdCtrl_t *pFtsdCtrl, + FT_IN pFtsdCtrl_delayTimer_t pDelayTimer_fun, + FT_IN u32 rspType, + FT_OUT u32 *cmdRsp); +ft_error_t FSdCtrl_WaitReadDataEnd(FT_INOUT FtsdCtrl_t *pFtsdCtrl, + FT_IN pFtsdCtrl_delayTimer_t pDelayTimer_fun, + FT_IN u32 blkNum); +ft_error_t FSdCtrl_WaitWriteDataEnd(FT_INOUT FtsdCtrl_t *pFtsdCtrl, + FT_IN pFtsdCtrl_delayTimer_t pDelayTimer_fun, + FT_IN u32 blkNum); + +void FSdCtrl_DoCmd(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN u32 cmdIndex, FT_IN u32 rspType, u32 arg); +void FSdCtrl_DoACmd(FT_INOUT FtsdCtrl_t *pFtsdCtrl, + FT_IN u32 cmdIndex, + FT_IN u32 rspType, + u32 arg); +void FSdCtrl_NormalIrq(FT_INOUT FtsdCtrl_t *pFtsdCtrl); +void FSdCtrl_DmaIrq(FT_INOUT FtsdCtrl_t *pFtsdCtrl); +void FSdCtrl_ErrIrq(FT_INOUT FtsdCtrl_t *pFtsdCtrl); +bool_t FSdCtrl_CardDetect(FT_INOUT FtsdCtrl_t *pFtsdCtrl); + +FSdCtrl_Config_t *FSdCtrl_LookupConfig(u32 instanceId); +/* This routine performs per device specific initialization of Phytium SDHC.*/ +ft_error_t FsdCtrl_Init(FT_INOUT FtsdCtrl_t *pFtsdCtrl); +void FSdCtrl_ClkFreqSetup(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN u32 sdClk); +void FSdCtrl_ResetDma(FT_INOUT FtsdCtrl_t *pFtsdCtrl); +/* reset sd ctrl during init */ +void FSdCtrl_Reset(FT_INOUT FtsdCtrl_t *pFtsdCtrl, pFtsdCtrl_delayTimer_t fDelayTimer); + +/* set irq call backs */ +ft_error_t FSdCtrl_SetHandler(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN FSdCtrl_IrqCallbackSelect_t selectIndex, + void *FuncPtr, + void *Args); + +/* register call-backs to determinate wheather write、read and cmd is complete */ +void FSdCtrl_WriteWaitRegister(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN pFtsdCtrl_irqWaitCallback_t callBack); +void FSdCtrl_ReadWaitRegister(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN pFtsdCtrl_irqWaitCallback_t callBack); +void FSdCtrl_CmdWaitRegister(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN pFtsdCtrl_irqWaitCallback_t callBack); +void FSdCtrl_ErrWaitRegister(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN pFtsdCtrl_irqWaitCallback_t callBack); + +/* get irq status */ +u32 FSdCtrl_GetNormalIrqStatus(FT_INOUT FtsdCtrl_t *pFtsdCtrl); +u32 FSdCtrl_GetDataIrqStatus(FT_INOUT FtsdCtrl_t *pFtsdCtrl); +u32 FSdCtrl_GetErrorIrqStatus(FT_INOUT FtsdCtrl_t *pFtsdCtrl); + +/* enable selected normal irq */ +void FSdCtrl_NormalIrqSet(FtsdCtrl_t *pFtsdCtrl, FT_IN FSdCtrl_NormalIrqSelect_t flgs); +void FSdCtrl_BdIrqSet(FtsdCtrl_t *pFtsdCtrl, FT_IN FSdCtrl_BdIrqSelect flgs); + +#endif // \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_g.c b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_g.c new file mode 100644 index 0000000000000000000000000000000000000000..a8a388e22749e7eab3d030bb7f8299050af4de98 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_g.c @@ -0,0 +1,31 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology(TianJin), Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-03-31 14:59:20 + * @LastEditTime: 2021-04-12 10:03:52 + * @Description:  This files is for sd ctrl config definition + * + * @Modify History: * * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_sdctrl.h" +#include "ft_parameters.h" + +/* configs of sd ctrl */ +FSdCtrl_Config_t FSdCtrl_Config[FT_SDC_NUM] = + { + { + .instanceId = FT_SDC_INSTANCE, + .baseAddress = FT_SDC_BASEADDR, + .inputClockHz = FT_SDC_FREQ, + .cardDetect = 1, + .writeProtect = 0, + .busWidth = 1, + .dmaIrqNum = 52, + .normalIrqNum = 53, + .errIrqNum = 54, + .workMode = 0 /*FTSDCTRL_CMD_IRQ_MASK | FTSDCTRL_DATA_WRITE_IRQ_MASK | FTSDCTRL_DATA_READ_IRQ_MASK*/ + }}; diff --git a/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_hw.c b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_hw.c new file mode 100644 index 0000000000000000000000000000000000000000..c06dc28e22bc6d13d1e8c675c6da982ed72bf016 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_hw.c @@ -0,0 +1,51 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology(TianJin), Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-03-31 14:59:20 + * @LastEditTime: 2021-04-07 13:40:04 + * @Description:  This files is for sd ctrl register-related implementations + * + * @Modify History: * * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_sdctrl_hw.h" +#include "ft_sdctrl.h" + +#include "ft_io.h" +#include "ft_types.h" +#include "ft_assert.h" +#include "ft_generic_timer.h" + +/** + * @name: + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + * @param {FT_INOUT FtsdCtrl_t} *pFtsdCtrl + * @param {pFtsdCtrl_delayTimer_t} fDelayTimer + */ +void FSdCtrl_Reset(FT_INOUT FtsdCtrl_t *pFtsdCtrl, pFtsdCtrl_delayTimer_t fDelayTimer) +{ + FSdCtrl_Config_t *pConfig; + Ft_assertVoid(FT_NULL != pFtsdCtrl); + + pConfig = &pFtsdCtrl->config; + /* trigger software reset for 1us */ + Ft_setBit32(pConfig->baseAddress + SOFTWARE_RESET_REG_OFFSET, SOFTWARE_RESET_SRST); + /* Wait for reset is ok */ + Ft_GenericTimer_UsDelay(1); + Ft_clearBit32(pConfig->baseAddress + SOFTWARE_RESET_REG_OFFSET, SOFTWARE_RESET_SRST); + + /* wait dat[0] to be high-lev */ + while ((!(Ft_in32(pConfig->baseAddress + STATUS_REG) & STATUS_REG_DLSL(1)))) + { + fDelayTimer(1); + } + + return; +} diff --git a/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_hw.h b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_hw.h new file mode 100644 index 0000000000000000000000000000000000000000..f5e9014e522f8505fab19c283a7af844f5408d9b --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_hw.h @@ -0,0 +1,210 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology(TianJin), Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-03-31 14:59:20 + * @LastEditTime: 2021-04-19 16:17:39 + * @Description:  This files is for sd ctrl register + * + * @Modify History: * * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef _SDCTRL_HW_H +#define _SDCTRL_HW_H + +#include "ft_sdctrl.h" + +/* Register Offset */ + +#define CONTROLL_SETTING_REG_OFFSET 0x00 /* Controller configuration register */ +#define ARGUMENT_REG_OFFSET 0x04 /* Parameter register */ +#define CMD_SETTING_REG_OFFSET 0x08 /* Command register */ +#define CLOCK_DIV_REG_OFFSET 0x0C /* Clock division register */ +#define SOFTWARE_RESET_REG_OFFSET 0x10 /* Reset control register */ +#define POWER_CONTROLL_REG_OFFSET 0x14 /* Power control register */ +#define TIMEOUT_CMD_REG_OFFSET 0x18 /* cmd Timeout setting register */ +#define TIMEOUT_DATA_REG_OFFSET 0x1C /* Data timeout setting register */ +#define NORMAL_INT_EN_REG_OFFSET 0x20 /* Interrupt Enable Register */ +#define ERROR_INT_EN_REG_OFFSET 0x24 /* error Interrupt Enable Register */ +#define BD_ISR_EN_REG_OFFSET 0x28 /* Data Transfer Interrupt Enable Register */ +#define CAPABILIES_REG_OFFSET 0x2c /* capabilies register */ +#define SD_DRV_REG_OFFSET 0x30 /* SD card driver phase register */ +#define SD_SAMP_REG_OFFSET 0x34 /* SD card sampling phase register */ +#define SD_SEN_REG_OFFSET 0x38 /* Card detection controller */ +#define HDS_AXI_REG_CONF1_OFFSET 0x3c /* AXI boundary configuration register 1 */ +#define DAT_IN_M_RX_BD 0x40 /* SD BD RX address register */ +#define DAT_IN_M_TX_BD 0x60 /* SD BD TX address register */ +#define BLK_CNT_REG 0x80 /* Block reads and writes configuration registers */ +#define HDS_AXI_REG_CONF2 0xa8 /* AXI boundary configuration register 2 */ +#define NORMAL_INT_STATUS_REG 0xc0 /* Interrupt status register */ +#define ERROR_INT_STATUS_REG 0xc4 /* ERROR interrupt register */ +#define BD_ISR_REG 0xc8 /* Data Transfer Interrupt Status Register */ +#define BD_STATUS 0xcc /* BD descriptor register */ +#define STATUS_REG 0xd0 /* state register */ +#define BLOCK 0xd4 /* Block length register */ +#define CMD_RESP_1 0xe0 /* Command response register 1 */ +#define CMD_RESP_2 0xe4 /* Command response register 2 */ +#define CMD_RESP_3 0xe8 /* Command response register 3 */ +#define CMD_RESP_4 0xec /* Command response register 4 */ + +/* Controller configuration register */ +#define CONTROLL_SETTING_PERMDR(x) ((x & 3) << 8) /* Read operation corresponding to the size of the end selection: 00: small end alignment,01: large end alignment,10: SD protocol mode */ +#define CONTROLL_SETTING_PERMDW(x) ((x & 3) << 10) /* Write operation corresponding to the size of the endian selection: 00: small endian alignment 01: large endian alignment 10: SD protocol mode*/ + +/* Parameter register */ +#define ARGUMENT_REG(x) (x & 0xffffffff) + +/* Command register */ +#define CMD_SETTING_RTS(x) ((x & 3) << 0) /* 0: No response 01: Response byte length 136 10: Response byte length 48 11: Response byte length 48 */ +#define CMD_SETTING_CRCE (1U << 3) /* 0: CRC check is not performed on CMD response 1: CRC check is performed on CMD response */ +#define CMD_SETTING_CICE (1U << 4) /* 0:CMD 响应时,不执行索引检查 1:CMD 响应时,执行索引检查 */ +#define CMD_SETTING_CMDW(x) ((x & 3) << 6) +#define CMD_SETTING_CMDI(x) ((x & 0x3f) << 8) /* 命令索引 */ +#define CMD_SETTING_TRTY(x) ((x & 3) << 14) /* 10: adtc 指令 ,其它: 读写操作 */ + +/* 时钟分频寄存器 */ +#define CLOCK_DIV_RE(x) (x & 0xffffffff) /* CLKD-时钟分频系数 SD_frequency= 600M/ (2*(clock_d+1)) */ + +/* 复位控制寄存器 */ +#define SOFTWARE_RESET_SRST (1U) /* 控制器软复位 */ +#define SOFTWARE_RESET_BDRST (4U) /* DMA BD 清 0 */ +#define SOFTWARE_RESET_CFCLF (8U) /* 卡插入拔出状态触发标志清 0 */ + +/* cmd 超时设置寄存器 */ +#define TIMEOUT_CMD_REG(x) (x & 0xffffffff) /* command 超时参数 */ + +/* 数据超时设置寄存器 */ +#define TIMEOUT_DATA_REG(x) (x & 0xffffffff) /* data 超时参数 */ + +/* 中断使能寄存器 */ +#define NORMAL_INT_EN_ECC 1U /* 命令完成中断使能 */ +#define NORMAL_INT_EN_ECCRCE 2U /* 卡拔出中断使能 */ +#define NORMAL_INT_EN_ECIE (1U << 15) /* 错误中断使能 */ + +/* error 中断使能寄存器 */ +#define ERROR_INT_EN_CNR (1U << 4) /* Command response error interrupted */ +#define ERROR_INT_EN_CIR (1U << 3) /* 命令索引错误中断使能 */ +#define ERROR_INT_EN_CCRCE (1U << 1) /* 命令 CRC 错误中断使能 */ +#define ERROR_INT_EN_CTE (1U << 0) /* 命令超时中断使能 */ + +/* 数据传输中断使能寄存器 */ +#define BD_ISR_EN_ETRS (1U << 0) /* DMA 传输完成中断使能 */ +#define BD_ISR_EN_EDTE (1U << 3) /* 数据超时中断使能 */ +#define BD_ISR_EN_ECMDE (1U << 4) /* 命令响应错误中断使能 */ +#define BD_ISR_EN_ETRE (1U << 5) /* 传输错误中断使能 */ +#define BD_ISR_EN_ENRCRCE (1U << 6) /* CRC 校验错误中断使能 */ +#define BD_ISR_EN_EDATFRAXE (1U << 7) /* AXI 总线错误中断使能 */ +#define BD_ISR_EN_RESPE (1U << 8) /* 读 SD 卡操作,AXI BR 通道完成中断 */ +#define BD_ISR_EN_EDAISE (1U << 15) /* DMA 错误中断使能 */ +#define BD_ISR_ALL_MASK (BD_ISR_EN_ETRS | BD_ISR_EN_EDTE | \ + BD_ISR_EN_ECMDE | BD_ISR_EN_ETRE | \ + BD_ISR_EN_ENRCRCE | BD_ISR_EN_EDATFRAXE | \ + BD_ISR_EN_RESPE | BD_ISR_EN_EDAISE) + +/* 状态寄存器 */ +#define CAPABILIES_REG(x) (x & 0xffffffff) + +/* SD 卡驱动相位寄存器 */ +#define SD_DRV_REG(x) (x & 0xffffffff) /* 卡驱动相位配置参数 */ + +/* SD 卡采样相位寄存器 */ +#define SD_SAMP_REG(x) (x & 0xffffffff) /* 卡采样相位配置参数 */ +#define SD_SAMP_DEFAULT 11 /* when SD card work in high-speed mode, \ + the best sampling pharse is needed to \ + get the correct data */ +#define SD_FRRQ_DIV_DEFAULT 5 /* default freq div */ +#define SD_CLK_FREQ_400KHZ 400000 +#define SD_CLK_FREQ_25MHZ 25000000 + +/* 卡检测控制器 */ +#define SD_SEN_REG_CREFR (1U << 1) /* 卡拔出时自动释放 AXI 总线选择 */ +#define SD_SEN_REG_CRES (1U << 2) /* CARD 在位状态标志选择 0: 卡在位-0,不在位-1 1: 卡在位-1,不在位-0 */ +#define SD_SEN_REG_DEBNCE(x) ((x & 0xffffff) << 8) /* 去抖时钟分频参数 */ + +/* AXI 边界配置寄存器 1 */ +#define HDS_AXI_REG_CONF1_AWDOMAIN_HDS_M(x) ((x & 0x3) << 0) +#define HDS_AXI_REG_CONF1_AWBAR_HDS_M(x) ((x & 0x3) << 2) +#define HDS_AXI_REG_CONF1_ARSNOOP_HDS_M(x) ((x & 0xf) << 4) +#define HDS_AXI_REG_CONF1_ARREGION_HDS_M(x) ((x & 0xf) << 8) +#define HDS_AXI_REG_CONF1_ARDOMAIN_HDS_M(x) ((x & 0x3) << 12) +#define HDS_AXI_REG_CONF1_ARBAR_HDS_M(x) ((x & 0x3) << 14) +#define HDS_AXI_REG_CONF1_AWSNOOP_HDS_M(x) ((x & 0x7) << 16) +#define HDS_AXI_REG_CONF1_AWREGION_HDS_M(x) ((x & 0xF) << 19) + +/* SD BD RX 地址寄存器 */ +#define DAT_IN_M_RX_BD_MASK(x) (x & 0xffffffff) /* dma 读卡地址配置:4 个 cycle ,系统低 4B-系统高 4B-SD 低 4B- SD 高 4B */ + +/* SD BD TX 地址寄存器 */ +#define DAT_IN_M_TX_BD_MASK(x) (x & 0xffffffff) /* dma 写卡地址配置:4 个 cycle ,系统低 4B-系统高 4B-SD 低 4B- SD 高 4B */ + +/* 块读写配置寄存器 */ +#define BLK_CNT(x) (x & 0xffffffff) /* dma block num setting */ + +/* AXI 边界配置寄存器 2 */ +#define HDS_AXI_REG_CONF2_D_ARPROT(x) ((x & 0x7) << 27) +#define HDS_AXI_REG_CONF2_SD_AWPROT(x) ((x & 0x7) << 24) +#define HDS_AXI_REG_CONF2_SD_ARCACHE_M(x) ((x & 0xf) << 20) +#define HDS_AXI_REG_CONF2_SD_AWCACHE_M(x) ((x & 0xf) << 16) +#define HDS_AXI_REG_CONF2_RESERVED(x) ((x & 0x3) << 14) +#define HDS_AXI_REG_CONF2_HDA_ARPRO(x) ((x & 0x7) << 11) +#define HDS_AXI_REG_CONF2_HDA_AWPROT(x) ((x & 0x7) << 8) +#define HDS_AXI_REG_CONF2_HDA_ARCACHE_M(x) ((x & 0xf) << 4) +#define HDS_AXI_REG_CONF2_HDA_AWCACHE_M(x) ((x & 0xf) << 0) + +/* 中断状态寄存器 */ +#define NORMAL_INT_STATUS_EI (1U << 15) /* 命令错误中断 */ +#define NORMAL_INT_STATUS_CR (1U << 1) /* 卡移除中断 */ +#define NORMAL_INT_STATUS_CC 1U /* 命令完成中断 */ +#define NORMAL_INT_STATUS_ALL_MASK (NORMAL_INT_STATUS_EI | NORMAL_INT_STATUS_CR | NORMAL_INT_STATUS_CC) + +/* error 中断寄存器 */ +#define ERROR_INT_STATUS_CNR (1U << 4) /* 命令响应错误中断 */ +#define ERROR_INT_STATUS_CIR (1U << 3) /* 命令索引错误中断 */ +#define ERROR_INT_STATUS_CCRCE (1U << 1) /* 命令 CRC 错误中断 */ +#define ERROR_INT_STATUS_CTE 1U /* 命令超时错误中断 */ +#define ERROR_INT_STATUS_ALL_MASK (ERROR_INT_STATUS_CNR | ERROR_INT_STATUS_CIR | ERROR_INT_STATUS_CCRCE | ERROR_INT_STATUS_CTE) + +/* 数据传输中断状态寄存器 */ +#define BD_ISR_REG_DAIS (1U << 15) /* DMA 错误中断*/ +#define BD_ISR_REG_RESPE (1U << 8) /* 读 SD 卡操作,AXI BR 通道完成中断*/ +#define BD_ISR_REG_DATFRAX (1U << 7) /* axi 总线强制释放中断*/ +#define BD_ISR_REG_NRCRC (1U << 6) /* 无 CRC 响应中断*/ +#define BD_ISR_REG_TRE (1U << 5) /* CRC 响应错误中断*/ +#define BD_ISR_REG_CMDE (1U << 4) /* 命令响应错误中断*/ +#define BD_ISR_REG_DTE (1U << 3) /* 超时中断*/ +#define BD_ISR_REG_TRS (1U << 0) /* DMA 传输完成中断*/ + +/* bd 描述符寄存器 */ +#define BD_STATUS_REG(x) (x & 0xffffffff) /* bd 描述符寄存器 */ + +/* 状态寄存器 */ +#define STATUS_REG_DATMAST(x) ((x & 0xf) << 27) /* data_master 状态机 */ +#define STATUS_REG_CDIF (1U << 26) /* 卡在位标志 */ +#define STATUS_REG_CDRF (1U << 25) /* 卡不在位标志 */ +#define STATUS_REG_CLSL (1U << 24) /* 命令闲信号 */ +#define STATUS_REG_DLSL(x) ((x & 0xf) << 20) /* 线信号 */ +#define STATUS_REG_CDSL (1U << 19) /* 卡检测管脚信号 */ +#define STATUS_REG_CST(x) ((x & 0xf) << 12) /* cmd_host state 状态机 */ +#define STATUS_REG_CSM(x) ((x & 0X1F) << 7) +#define STATUS_REG_DAT_AVA (1 << 6) /* DAT_AVA 当前命令状态流程运转完 */ +#define STATUS_REG_CRC_VALID (1 << 5) +#define STATUS_REG_CICMD 1U /* RO 0x0 CMD 总线状态 */ + +/* 块长度寄存器 */ +#define BLOCK_RGE(x) (x & 0xffffffff) /* 块长度寄存器 */ + +/* 命令响应寄存器 1 */ +#define CMD_RESP_1_REG(x) (x & 0xffffffff) + +/* 命令响应寄存器 2 */ +#define CMD_RESP_2_REG(x) (x & 0xffffffff) + +/* 命令响应寄存器 3 */ +#define CMD_RESP_3_REG(x) (x & 0xffffffff) + +/* 命令响应寄存器 4 */ +#define CMD_RESP_4_REG(x) (x & 0xffffffff) + +#endif // ! \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_intr.c b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_intr.c new file mode 100644 index 0000000000000000000000000000000000000000..09a35d3d8f02b406aede4fe8043a86e56ab20f18 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_intr.c @@ -0,0 +1,143 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology(TianJin), Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-03-31 14:59:20 + * @LastEditTime: 2021-04-07 13:40:20 + * @Description:  This files is for sd ctrl irq handling + * + * @Modify History: * * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_sdctrl.h" +#include "ft_sdctrl_hw.h" +#include "ft_assert.h" +#include "ft_types.h" +#include "ft_io.h" +#include "ft_printf.h" +#include "ft_debug.h" + +#ifndef LOG_LOCAL_LEVEL +#define LOG_LOCAL_LEVEL FT_LOG_NONE +#endif +#define FT_SD_CTRL_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FT_SD_CTRL_DEBUG_TAG, format, ##__VA_ARGS__) +#define FT_SD_CTRL_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(FT_SD_CTRL_DEBUG_TAG, format, ##__VA_ARGS__) +#define FT_SD_CTRL_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FT_SD_CTRL_DEBUG_TAG, format, ##__VA_ARGS__) + +/** + * Description: normal irq for sd ctrl + * Date: 2021-03-31 10:46:55 + * Param: + * return {*} + * param {FT_INOUT FtsdCtrl_t} *pFtsdCtrl + */ +void FSdCtrl_NormalIrq(FT_INOUT FtsdCtrl_t *pFtsdCtrl) +{ + FSdCtrl_Config_t *pConfig; + FSdCtrl_IrqConfig_t *irqConfig; + Ft_assertVoid(FT_NULL != pFtsdCtrl); + pConfig = &pFtsdCtrl->config; + irqConfig = &pFtsdCtrl->irqConfig; + + //FT_SD_CTRL_DEBUG_I("enter cmd irq procedure\r\n"); + if (irqConfig->pCmdCallback) + { + irqConfig->pCmdCallback(irqConfig->pCmdArgs); + } + + /* clear interrupts */ + Ft_out32(pConfig->baseAddress + NORMAL_INT_STATUS_REG, NORMAL_INT_STATUS_ALL_MASK); + Ft_out32(pConfig->baseAddress + NORMAL_INT_STATUS_REG, 0); +} + +/** + * @name: + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + * @param {FT_INOUT FtsdCtrl_t} *pFtsdCtrl + */ +void FSdCtrl_DmaIrq(FT_INOUT FtsdCtrl_t *pFtsdCtrl) +{ + FSdCtrl_Config_t *pConfig; + FSdCtrl_IrqConfig_t *irqConfig; + Ft_assertVoid(FT_NULL != pFtsdCtrl); + pConfig = &pFtsdCtrl->config; + irqConfig = &pFtsdCtrl->irqConfig; + + if (irqConfig->pDmaDataCallback) + { + irqConfig->pDmaDataCallback(irqConfig->pDmaDataArgs); + } + + /* clear interrupts */ + Ft_out32(pConfig->baseAddress + BD_ISR_REG, BD_ISR_ALL_MASK); + Ft_out32(pConfig->baseAddress + BD_ISR_REG, 0); +} + +/** + * @name: + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + * @param {FT_INOUT FtsdCtrl_t} *pFtsdCtrl + */ +void FSdCtrl_ErrIrq(FT_INOUT FtsdCtrl_t *pFtsdCtrl) +{ + FSdCtrl_Config_t *pConfig; + FSdCtrl_IrqConfig_t *irqConfig; + Ft_assertVoid(FT_NULL != pFtsdCtrl); + pConfig = &pFtsdCtrl->config; + irqConfig = &pFtsdCtrl->irqConfig; + + if (irqConfig->pErrorCallback) + { + irqConfig->pErrorCallback(irqConfig->pErrorArgs); + } + + /* clear interrupts */ + Ft_out32(pConfig->baseAddress + ERROR_INT_STATUS_REG, ERROR_INT_STATUS_ALL_MASK); + Ft_out32(pConfig->baseAddress + ERROR_INT_STATUS_REG, 0); +} + +/** + * @name: + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + */ +ft_error_t FSdCtrl_SetHandler(FT_INOUT FtsdCtrl_t *pFtsdCtrl, FT_IN FSdCtrl_IrqCallbackSelect_t selectIndex, + void *FuncPtr, void *Args) +{ + Ft_assertNonvoid(pFtsdCtrl != NULL); + Ft_assertNonvoid(FuncPtr != NULL); + Ft_assertNonvoid(pFtsdCtrl->isReady == FT_COMPONENT_IS_READLY); + + switch (selectIndex) + { + case FTSDCTRL_DMADATAIRQID: + pFtsdCtrl->irqConfig.pDmaDataCallback = FuncPtr; + pFtsdCtrl->irqConfig.pDmaDataArgs = Args; + break; + case FTSDCTRL_CMDIRQID: + pFtsdCtrl->irqConfig.pCmdCallback = FuncPtr; + pFtsdCtrl->irqConfig.pCmdArgs = Args; + break; + case FTSDCTRL_ERRORIRQID: + pFtsdCtrl->irqConfig.pErrorCallback = FuncPtr; + pFtsdCtrl->irqConfig.pErrorArgs = Args; + break; + default: + return FTSDC_FAILURE; + } + + return FTSDC_SUCCESS; +} \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_option.c b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_option.c new file mode 100644 index 0000000000000000000000000000000000000000..fdb520753ab6f8018c16665b5c81fae4294d73d9 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_option.c @@ -0,0 +1,91 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology(TianJin), Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-03-31 14:59:20 + * @LastEditTime: 2021-04-07 13:40:38 + * @Description:  This files is for sd ctrl option setting + * + * @Modify History: * * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_sdctrl.h" +#include "ft_sdctrl_hw.h" +#include "ft_types.h" +#include "ft_io.h" +#include "ft_printf.h" +#include "ft_assert.h" + +/** + * @name: + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + * @param {FtsdCtrl_t} *pFtsdCtrl + * @param {FT_IN FSdCtrl_NormalIrqSelect_t} flgs + */ +void FSdCtrl_NormalIrqSet(FtsdCtrl_t *pFtsdCtrl, FT_IN FSdCtrl_NormalIrqSelect_t flgs) +{ + FSdCtrl_Config_t *pConfig; + u32 regValue; + Ft_assertVoid(FT_NULL != pFtsdCtrl); + pConfig = &pFtsdCtrl->config; + + /* */ + regValue = ((flgs & NORMAL_IRQ_CC) ? NORMAL_INT_EN_ECC : 0) | ((flgs & NORMAL_IRQ_CR) ? NORMAL_INT_EN_ECCRCE : 0) | + ((flgs & NORMAL_IRQ_EI) ? NORMAL_INT_EN_ECIE : 0); + + Ft_out32(pConfig->baseAddress + NORMAL_INT_EN_REG_OFFSET, regValue); +} + +/** + * @name: + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + * @param {FtsdCtrl_t} *pFtsdCtrl + * @param {FT_IN FSdCtrl_ErrorIrqSelect_t} flgs + */ +void FsdCtrl_errorIrqSet(FtsdCtrl_t *pFtsdCtrl, FT_IN FSdCtrl_ErrorIrqSelect_t flgs) +{ + FSdCtrl_Config_t *pConfig; + u32 regValue; + Ft_assertVoid(FT_NULL != pFtsdCtrl); + pConfig = &pFtsdCtrl->config; + + regValue = ((flgs & ERROR_IRQ_CTE) ? ERROR_INT_EN_CTE : 0) | ((flgs & ERROR_IRQ_CCRCE) ? ERROR_INT_EN_CCRCE : 0) | + ((flgs & ERROR_IRQ_CIR) ? ERROR_INT_EN_CIR : 0) | ((flgs & ERROR_IRQ_CNR) ? ERROR_INT_EN_CNR : 0); + + Ft_out32(pConfig->baseAddress + ERROR_INT_EN_REG_OFFSET, regValue); +} + +/** + * @name: + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + * @param {FtsdCtrl_t} *pFtsdCtrl + * @param {FT_IN FSdCtrl_BdIrqSelect} flgs + */ +void FSdCtrl_BdIrqSet(FtsdCtrl_t *pFtsdCtrl, FT_IN FSdCtrl_BdIrqSelect flgs) +{ + FSdCtrl_Config_t *pConfig; + u32 regValue; + Ft_assertVoid(FT_NULL != pFtsdCtrl); + pConfig = &pFtsdCtrl->config; + + regValue = ((flgs & BD_IRQ_TRS) ? BD_ISR_EN_ETRS : 0) | ((flgs & BD_IRQ_DTE) ? BD_ISR_EN_EDTE : 0) | + ((flgs & BD_IRQ_CMDE) ? BD_ISR_EN_ECMDE : 0) | ((flgs & BD_IRQ_TRE) ? BD_ISR_EN_ETRE : 0) | + ((flgs & BD_IRQ_NRCRC) ? BD_ISR_EN_ENRCRCE : 0) | ((flgs & BD_IRQ_DATFRAX) ? BD_ISR_EN_EDATFRAXE : 0) | + ((flgs & BD_IRQ_RESPE) ? BD_ISR_EN_RESPE : 0) | ((flgs & BD_IRQ_DAIS) ? BD_ISR_EN_EDAISE : 0); + + Ft_out32(pConfig->baseAddress + BD_ISR_EN_REG_OFFSET, regValue); +} diff --git a/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_sinit.c b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_sinit.c new file mode 100644 index 0000000000000000000000000000000000000000..ad31af76ffb70ce565aff62dfb53a4b87d8861b9 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_sd/ft_sdctrl_sinit.c @@ -0,0 +1,42 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology(TianJin), Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-03-31 14:59:20 + * @LastEditTime: 2021-04-19 17:05:14 + * @Description:  This files is for sd ctrl static initialization + * + * @Modify History: * * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_sdctrl.h" +#include "ft_parameters.h" + +extern FSdCtrl_Config_t FSdCtrl_Config[FT_SDC_NUM]; + +/** + * @name: + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + * @param {u32} instanceId + */ +FSdCtrl_Config_t *FSdCtrl_LookupConfig(u32 instanceId) +{ + FSdCtrl_Config_t *CfgPtr = NULL; + u32 Index; + for (Index = 0; Index < (u32)FT_GMAC_INSTANCES_NUM; Index++) + { + if (FSdCtrl_Config[Index].instanceId == instanceId) + { + CfgPtr = &FSdCtrl_Config[Index]; + break; + } + } + + return (FSdCtrl_Config_t *)CfgPtr; +} diff --git a/bsp/ft2004/libraries/bsp/ft_spi/ft_spi.c b/bsp/ft2004/libraries/bsp/ft_spi/ft_spi.c new file mode 100644 index 0000000000000000000000000000000000000000..bd0e3349edcb2215ce904995e39f508eba8e0cbe --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_spi/ft_spi.c @@ -0,0 +1,192 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-25 14:00:25 + * @LastEditTime: 2021-04-30 16:11:38 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_assert.h" +#include "ft_spi.h" +#include "ft_spi_hw.h" +#include "ft_generic_timer.h" +#include "ft_gpio.h" + +void FSpi_DumpAllStatus(FT_IN FSpi_Ctrl_t *pCtrl, FT_IN char *tag) +{ + FT_SPI_DEBUG_I("***%s status******\r\n", tag); + FT_SPI_DEBUG_I("busy: %d", SPI_STATUS_REG(pCtrl)->val.Busy); + FT_SPI_DEBUG_I("tx fifo not empty: %d", SPI_STATUS_REG(pCtrl)->val.Tfnf); + FT_SPI_DEBUG_I("tx fifo empty: %d", SPI_STATUS_REG(pCtrl)->val.Tfe); + FT_SPI_DEBUG_I("rx fifo not empty: %d", SPI_STATUS_REG(pCtrl)->val.Rfne); + FT_SPI_DEBUG_I("rx fifo full: %d", SPI_STATUS_REG(pCtrl)->val.Rff); + FT_SPI_DEBUG_I("trans error: %d", SPI_STATUS_REG(pCtrl)->val.Txe); + FT_SPI_DEBUG_I("trans conflict error: %d", SPI_STATUS_REG(pCtrl)->val.Dcol); +} + +u32 FSpi_ReadWriteByte(FT_INOUT FSpi_Ctrl_t *pCtrl, FT_IN u8 TxData, + FT_OUT u8 *pRxData) +{ + u32 Retry = 0; + u32 Ret = ERR_SPI_OK; + u16 RxData; + + if (!pCtrl->IsReady) + { + return ERR_SPI_NOT_READY; + } + + while (FSPI_TX_FIFO_NOT_EMPTY(pCtrl)) + { + //Ft_GenericTimer_UsDelay(2); + if ((Retry++) > SPI_TIMEOUT) + { + Ret = ERR_SPI_TX_TIMEOUT; + goto __EXIT; + } + } + FSPI_WRITE_DATA(pCtrl, (u16)TxData); + + Retry = 0; + + while (FSPI_RX_FIFO_EMPTY(pCtrl)) + { + //Ft_GenericTimer_UsDelay(2); + if ((Retry++) > SPI_TIMEOUT) + { + Ret = ERR_SPI_RX_TIMEOUT; + goto __EXIT; + } + } + RxData = FSPI_READ_DATA(pCtrl); + + if (pRxData) + { + *pRxData = (u8)RxData; + } + +__EXIT: + return Ret; +} + +u32 FSpi_Init(FT_INOUT FSpi_Ctrl_t *pCtrl) +{ + u32 Ret = ERR_SPI_OK; + + FSPI_DISABLE(pCtrl); + + /* config spi ctrl register */ + SPI_CTRL0_REG(pCtrl)->val.Dfs = SPI_DFS_DEFAULT; + SPI_CTRL0_REG(pCtrl)->val.Frf = SPI_FRF_DEFAULT; + + if (SPI_CTRL_CPHA_1EDGE == pCtrl->Config.Cpha) + { + SPI_CTRL0_REG(pCtrl)->val.Scph = SPI_SCPH_SW_CLK_AT_DATA_BEG; + } + else if (SPI_CTRL_CPHA_2EDGE == pCtrl->Config.Cpha) + { + SPI_CTRL0_REG(pCtrl)->val.Scph = SPI_SCPH_SW_CLK_AT_DATA_MID; + } + else + { + Ft_assertNoneReturn(0); + } + + if (SPI_CTRL_CPOL_LOW == pCtrl->Config.Cpol) + { + SPI_CTRL0_REG(pCtrl)->val.Scpol = SPI_SCPOL_NOT_ACT_LOW; + } + else if (SPI_CTRL_CPOL_HIGH == pCtrl->Config.Cpol) + { + SPI_CTRL0_REG(pCtrl)->val.Scpol = SPI_SCPOL_NOT_ACT_HIGH; + } + else + { + Ft_assertNoneReturn(0); + } + + SPI_CTRL0_REG(pCtrl)->val.Tmod = SPI_TMOD_TX_RX_MODE; + SPI_CTRL0_REG(pCtrl)->val.SlvOE = SPI_SLV_OE_DISABLE; + SPI_CTRL0_REG(pCtrl)->val.Srl = SPI_SRL_NORMAL_MODE; + SPI_CTRL0_REG(pCtrl)->val.Cfs = SPI_CFS_DEFAULT; + + /* config spi clock */ + FSPI_SET_BAUDR(pCtrl, pCtrl->Config.BaudRDiv); + + /* config rx and tx fifo, fifo depth to trigger intr */ + SPI_TXFTL_REG(pCtrl)->val.Tft = 0; + SPI_RXFTL_REG(pCtrl)->val.Rft = 0; + SPI_TXFL_REG(pCtrl)->val.Txtfl = 0; + SPI_RXFL_REG(pCtrl)->val.Rxtfl = 0; + + SPI_RXSAMPLE_DLY_REG(pCtrl)->val.Rsd = SPI_DEFAULT_RSD; + + FSPI_ENABLE(pCtrl); + + /* set spi ready flag */ + if (ERR_SPI_OK == Ret) + { + pCtrl->IsReady = TRUE; + } + + return Ret; +} + +static void FSpi_ToggleCSPin(FT_INOUT FSpi_Ctrl_t *pCtrl, FT_IN FSpi_DevId_t DevId, + FT_IN bool_t select) +{ + u32 setVal = ((TRUE == select) ? GPIO_OFF : GPIO_ON); + + Ft_assertNoneReturn(NULL != pCtrl); + + if (FGpio_ReadPinA(GPIO_CTRL_ID_1, pCtrl->CsPin) != setVal) + { + FGpio_WritePinA(GPIO_CTRL_ID_1, pCtrl->CsPin, setVal); + } + + Ft_GenericTimer_UsDelay(10); + return; +} + +void FSpi_SelectSlave(FT_INOUT FSpi_Ctrl_t *pCtrl, FT_IN FSpi_DevId_t DevId, + FT_IN bool_t select) +{ + FSpi_SeReg_t *pSelReg; + u32 setVal = ((TRUE == select) ? SPI_SE_SELECTED : SPI_SE_UNSELECTED); + + FSPI_DISABLE(pCtrl); + /* enable or disable specific spi slave device */ + pSelReg = SPI_SE_REG(pCtrl); + switch(DevId) + { + case SPI_DEV_ID_0: + pSelReg->val.SelSlave_0 = setVal; + break; + case SPI_DEV_ID_1: + pSelReg->val.SelSlave_1 = setVal; + Ft_assertNoneReturn(0); + break; + case SPI_DEV_ID_2: + pSelReg->val.SelSlave_2 = setVal; + Ft_assertNoneReturn(0); + break; + case SPI_DEV_ID_3: + pSelReg->val.SelSlave_3 = setVal; + Ft_assertNoneReturn(0); + break; + default: + Ft_assertNoneReturn(0); + break; + } + + FSpi_ToggleCSPin(pCtrl, DevId, select); + FSPI_ENABLE(pCtrl); + + return; +} \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/ft_spi/ft_spi.h b/bsp/ft2004/libraries/bsp/ft_spi/ft_spi.h new file mode 100644 index 0000000000000000000000000000000000000000..3c5190f5620bd0f963ca5cb8f42c4916e5b896d7 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_spi/ft_spi.h @@ -0,0 +1,95 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-25 13:59:05 + * @LastEditTime: 2021-04-30 16:11:46 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef FT_BSP_SPI_H +#define FT_BSP_SPI_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ft_types.h" +#include "ft_spi_hw.h" +#include "ft_error_code.h" +#include "ft_debug.h" + +typedef struct +{ + u8 WorkMode; +#define SPI_CTRL_MASTER_MODE (u8)0x0 +#define SPI_CTRL_SLAVE_MODE (u8)0x1 + u8 DevAddrLen; +#define SPI_3_BYTE_ADDR (u8)0x3 +#define SPI_4_BYTE_ADDR (u8)0x4 + u8 Cpol; +#define SPI_CTRL_CPOL_LOW (u8)0x0 +#define SPI_CTRL_CPOL_HIGH (u8)0x1 + u8 Cpha; +#define SPI_CTRL_CPHA_1EDGE (u8)0x0 +#define SPI_CTRL_CPHA_2EDGE (u8)0x1 + u8 DevAddr[4]; + u32 BaudRDiv; +} FSpi_Conf_t; + +typedef struct +{ + FSpi_Conf_t Config; + FSpi_CtrlId_t CtrlId; + FSpi_DevId_t DevId; /* support only one slave at the moment */ + bool_t IsReady; + u16 CsPin; /* cs pin in gpio group A */ +}FSpi_Ctrl_t; + +/* misc marco */ +#define SPI_TIMEOUT 5000 +#define SPI_DUMMY_TX_DATA 0xFF + +/* ctrl member shortcut */ +#define FSPI_DEV_ADDR_LEN(pCtrl) (pCtrl->Config.DevAddrLen) +#define FSPI_IS_3_BYTE_ADDR(pCtrl) (SPI_3_BYTE_ADDR == FSPI_DEV_ADDR_LEN(pCtrl)) +#define FSPI_DEV_ADDR(pCtrl) (pCtrl->Config.DevAddr) + +/* define error code */ +#define ERR_SPI_OK ERR_SUCCESS +#define ERR_SPI_GENERAL FT_CODE_ERR(ERR_MODE_SPI, 0, 1) +#define ERR_SPI_NOT_READY FT_CODE_ERR(ERR_MODE_SPI, 0, 2) +#define ERR_SPI_TX_TIMEOUT FT_CODE_ERR(ERR_MODE_SPI, 0, 3) +#define ERR_SPI_RX_TIMEOUT FT_CODE_ERR(ERR_MODE_SPI, 0, 4) + +/* spi flash error code */ +#define ERR_SPI_WAIT_TIMEOUT FT_CODE_ERR(ERR_MODE_SPI, 1, 1) + +/* define debug utilities */ +#define FT_SPI_DEBUG_TAG "FT_SPI" +#define FT_SPI_ENABLE_DEBUG +#define FT_SPI_ERROR(format, ...) FT_DEBUG_PRINT_E(FT_SPI_DEBUG_TAG, format, ##__VA_ARGS__) +#ifdef FT_SPI_ENABLE_DEBUG +#define FT_SPI_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FT_SPI_DEBUG_TAG, format, ##__VA_ARGS__) +#define FT_SPI_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FT_SPI_DEBUG_TAG, format, ##__VA_ARGS__) +#else +#define FT_SPI_DEBUG_I(format, ...) +#define FT_SPI_DEBUG_W(format, ...) +#endif + +u32 FSpi_Init(FT_INOUT FSpi_Ctrl_t *pCtrl); +u32 FSpi_ReadWriteByte(FT_INOUT FSpi_Ctrl_t *pCtrl, FT_IN u8 TxData, + FT_OUT u8 *pRxData); +void FSpi_SelectSlave(FT_INOUT FSpi_Ctrl_t *pCtrl, FT_IN FSpi_DevId_t DevId, + FT_IN bool_t select); +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/ft_spi/ft_spi_hw.h b/bsp/ft2004/libraries/bsp/ft_spi/ft_spi_hw.h new file mode 100644 index 0000000000000000000000000000000000000000..53c502f87e2916e8a23d3f8617493c44477c9247 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_spi/ft_spi_hw.h @@ -0,0 +1,331 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-25 13:59:44 + * @LastEditTime: 2021-04-30 15:42:30 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ +#ifndef FT_BSP_SPI_HW_H +#define FT_BSP_SPI_HW_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ft_types.h" + +/* offset map of SPI register */ +#define SPI_CTRL_R0 0x00 //Ctrl register 0 +#define SPI_CTRL_R1 0x04 //Ctrl register 1 +#define SPI_SSI_EN_R 0x08 //SPI enable register +#define SPI_MW_CR 0x0c //Microwire ctrl register +#define SPI_SE_R 0x10 //Slave enable register +#define SPI_BAUD_R 0x14 //Baudrate set register +#define SPI_TXFTL_R 0x18 //Tx threshold register +#define SPI_RXFTL_R 0x1c //Rx threshold register +#define SPI_TXFL_R 0x20 //Tx level register +#define SPI_RXFL_R 0x24 //Rx level register +#define SPI_S_R 0x28 //Status register +#define SPI_IM_R 0x2c //Intr mask register +#define SPI_RIS_R 0x34 //Intr status register +#define SPI_TXOI_CR 0x38 //TX FIFO overflow intr clear register +#define SPI_RXOI_CR 0x3c //RX FIFO overflow intr clear register +#define SPI_RXUI_CR 0x40 //TX FIFO underflow intr clear register +#define SPI_MSTI_CR 0x44 //Multi slave intr clear register +#define SPI_IC_R 0x48 //Intr clear register +#define SPI_DMA_CR 0x4c //DMA ctrl register +#define SPI_DMA_TDL_R 0x50 //DMA TX Data level register +#define SPI_DMA_RDL_R 0x54 //DMA RX Data level register +#define SPI_ID_R 0x58 //Identification register +#define SPI_D_R 0xec //Data register +#define SPI_RX_SAMPLE_DLY 0xfc //RX Data delay register + +typedef enum +{ + SPI_CTRL_ID_0 = 0, + SPI_CTRL_ID_1, + + NUM_OF_SPI_CTRL, +} FSpi_CtrlId_t; + +typedef enum +{ + SPI_DEV_ID_0 = 0, + SPI_DEV_ID_1, + SPI_DEV_ID_2, + SPI_DEV_ID_3, + + NUM_OF_SPI_DEV, +}FSpi_DevId_t; + +/* base address of SPI register */ +const static u32 g_SpiBaseAddr[NUM_OF_SPI_CTRL] = {0x2800c000, 0x28013000}; + +typedef union +{ + u32 data; + struct + { + u32 Dfs : 4; /* 3:0, select data length */ +#define SPI_DFS_DEFAULT 0x7 + u32 Frf : 2; /* 5:4, selcet trans mode */ +#define SPI_FRF_DEFAULT 0x0 + u32 Scph : 1; /* 6, serial clock phase */ +#define SPI_SCPH_SW_CLK_AT_DATA_MID 0x0 /* second edge */ +#define SPI_SCPH_SW_CLK_AT_DATA_BEG 0x1 /* first edge */ + u32 Scpol : 1; /* 7, serial clock Polarity */ +#define SPI_SCPOL_NOT_ACT_LOW 0x0 +#define SPI_SCPOL_NOT_ACT_HIGH 0x1 + u32 Tmod : 2; /* 9:8, ctrl trans mode, indicate if tx rx data is valid */ +#define SPI_TMOD_TX_RX_MODE 0x0 +#define SPI_TMOD_TX_MODE 0x1 +#define SPI_TMOD_RX_MODE 0x2 +#define SPI_TMOD_EEPROM_MODE 0x3 + u32 SlvOE : 1; /* 10, enable slave tx logic */ +#define SPI_SLV_OE_ENABLE 0x0 +#define SPI_SLV_OE_DISABLE 0x1 + u32 Srl : 1; /* 11, shift register loopback */ +#define SPI_SRL_NORMAL_MODE 0x0 +#define SPI_SRL_TEST_MODE 0x1 + u32 Cfs : 4; /* 15:12, ctrl data size, applied in Microwire mode */ +#define SPI_CFS_DEFAULT 0x0 + u32 Reserve : 16; + } val; +}FSpi_CtrlReg0_t; + +typedef union +{ + u32 data; + struct + { + u32 ndf : 16; /* 15:0 valid when TMOD = 10, TMOD = 11 */ +#define SPI_NDF_DEFAULT 16 + u32 Reserve : 16; + } val; +}FSpi_CtrlReg1_t; + +typedef struct +{ + u32 CPOL; + u32 CPHA; +} FSpi_ClockMode_t; + +static const FSpi_ClockMode_t g_FSpi_ClockMode[4] = +{ + {.CPOL = SPI_SCPOL_NOT_ACT_LOW, .CPHA = SPI_SCPH_SW_CLK_AT_DATA_BEG}, /* low level logic, sample at rising edge, shift at falling edge */ + {.CPOL = SPI_SCPOL_NOT_ACT_LOW, .CPHA = SPI_SCPH_SW_CLK_AT_DATA_MID}, /* low level logic, sample at falling edge, shift at rising edge */ + {.CPOL = SPI_SCPOL_NOT_ACT_HIGH, .CPHA = SPI_SCPH_SW_CLK_AT_DATA_MID}, /* high level logic, sample at falling edge, shift at rising edge */ + {.CPOL = SPI_SCPOL_NOT_ACT_HIGH, .CPHA = SPI_SCPH_SW_CLK_AT_DATA_BEG}, /* high level logic, sample at rising edge, shift at falling edge */ +}; + +typedef union +{ + u32 data; + struct + { + u32 SsiEn : 1; /* 0, enable or disable all SPI op */ + u32 Reserve : 31; + }val; +}FSpi_SsiEnReg_t; + + +typedef union +{ + u32 data; + struct + { + u32 MwMod : 1; /* 0 microwire trans mode */ +#define SPI_MWMODE_NO_CONTINUOUES 0 +#define SPI_MWMODE_CONTINUOUES 1 + u32 Mdd : 1; /* 1 microwire ctrl bit */ +#define SPI_MWMDD_RXFROM_EXT_DEV 0 +#define SPI_MWMDD_TXTO_EXT_DEV 1 + u32 Mhs : 1; /* 2 microwire handshake */ +#define SPI_MWMHS_DISABLE 0 +#define SPI_MWMHS_ENABLE 1 + u32 Reserve : 29; + }val; +}FSpi_MwcrReg_t; + +typedef union +{ + u32 data; + struct + { + u32 SelSlave_0 : 1; /* 3:0, select specifc slave device */ + u32 SelSlave_1 : 1; + u32 SelSlave_2 : 1; + u32 SelSlave_3 : 1; +#define SPI_SE_SELECTED 0x1 +#define SPI_SE_UNSELECTED 0x0 + u32 Reserve : 28; + } val; +}FSpi_SeReg_t; + +typedef union +{ + u32 data; + struct + { + u32 Sckdv : 16; /* 15:0, SSI clk divider, must be times of 2 */ +#define SPI_SCKDV_MIN (2) +#define SPI_SCKDV_4 (4) +#define SPI_SCKDV_8 (8) +#define SPI_SCKDV_16 (16) +#define SPI_SCKDV_32 (20) +#define SPI_SCKDV_64 (28) +#define SPI_SCKDV_128 (128) +#define SPI_SCKDV_256 (256) +#define SPI_SCKDV_1024 (1024) +#define SPI_SCKDV_4096 (4096) +#define SPI_SCKDV_12800 (12800) +#define SPI_SCKDV_56800 (56800) +#define SPI_SCKDV_MAX (65534) + u32 Reserve : 16; + }val; +}FSpi_BaudrReg_t; + +typedef union +{ + u32 data; + struct + { + u32 Tft : 8; /* 7:0, TX FIFO threshold */ + u32 Reserve : 24; + }val; + +}FSpi_TxFtlrReg_t; + +typedef union +{ + u32 data; + struct + { + u32 Rft : 8; /* 7:0, RX FIFO threshold */ + u32 Reserve : 24; + }val; + +}FSpi_RxFtlrReg_t; + +typedef union +{ + u32 data; + struct + { + u32 Txtfl : 8; /* 7:0, TX FIFO level, num of valid num */ + u32 Reserve : 24; + }val; + +}FSpi_TxFlrReg_t; + +typedef union +{ + u32 data; + struct + { + u32 Rxtfl : 8; /* 7:0, RX FIFO level, num of valid num */ + u32 Reserve : 24; + }val; + +}FSpi_RxFlrReg_t; + +typedef union +{ + u32 data; + struct + { + u32 Busy : 1; /* 0, SPI bus busy bit */ + u32 Tfnf : 1; /* 1, tx FIFO not empty */ +#define SPI_TX_FIFO_FULL 0x0 +#define SPI_TX_FIFO_NOT_FULL 0x1 + u32 Tfe : 1; /* 2, tx FIFO empty */ +#define SPI_TX_FIFO_NOT_EMPTY 0x0 +#define SPI_TX_FIFO_EMPTY 0x1 + u32 Rfne : 1; /* 3, rx FIFO not emptu */ +#define SPI_RX_FIFO_EMPTY 0x0 +#define SPI_RX_FIFO_NOT_EMPTY 0x1 + u32 Rff : 1; /* 4, rx FIFO full */ +#define SPI_RX_FIFO_NOT_FULL 0x0 +#define SPI_RX_FIFO_FULL 0x1 + u32 Txe : 1; /* 5, trans error */ +#define SPI_TX_NO_ERR 0x0 +#define SPI_TX_ERR 0x1 + u32 Dcol : 1; /* 6, trans conflict error */ +#define SPI_TX_NO_COLERR 0x0 +#define SPI_TX_COLERR 0x1 + u32 Reserve : 25; + }val; +}FSpi_StatusReg_t; /* Read-Only */ + +typedef union +{ + u32 IdCode : 32; +}FSpi_IDReg_t; + +typedef union +{ + u32 data; + struct + { + u32 Dr : 16; /* 15:0, RX and TX fifo */ +#define SPI_8BIT_MASK 0xFF +#define SPI_16BIT_MASK 0xFFFF + u32 Reserve : 16; + } val; +}FSpi_DataReg_t; + +typedef union +{ + u32 data; + struct + { + u32 Rsd : 8; /* 7:0, RX data delay */ +#define SPI_DEFAULT_RSD 0x6 + u32 Reserve : 24; + } val; +}FSpi_RxSampleDlyReg_t; + +#define SPI_CTL_ID(pCtrl) ((pCtrl)->CtrlId) +#define SPI_BASE_ADDR(pCtrl) (g_SpiBaseAddr[SPI_CTL_ID(pCtrl)]) + +/* select slave device */ +#define SPI_SE_REG(pCtrl) ((FSpi_SeReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_SE_R)) +/* set speed */ +#define SPI_BAUDR_REG(pCtrl) ((FSpi_BaudrReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_BAUD_R)) +#define FSPI_SET_BAUDR(pCtrl, div) (SPI_BAUDR_REG(pCtrl)->val.Sckdv = (div)) +#define FSPI_GET_BAUDR(pCtrl) (SPI_BAUDR_REG(pCtrl)->val.Sckdv) +/* check status */ +#define SPI_STATUS_REG(pCtrl) ((FSpi_StatusReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_S_R)) +#define FSPI_TX_FIFO_NOT_EMPTY(pCtrl) (SPI_TX_FIFO_NOT_EMPTY == (SPI_STATUS_REG(pCtrl)->val.Tfe)) +#define FSPI_RX_FIFO_EMPTY(pCtrl) (SPI_RX_FIFO_EMPTY == (SPI_STATUS_REG(pCtrl)->val.Rfne)) +/* enable/disable spi bus */ +#define SPI_SSIEN_REG(pCtrl) ((FSpi_SsiEnReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_SSI_EN_R)) +#define FSPI_ENABLE(pCtrl) (SPI_SSIEN_REG(pCtrl)->val.SsiEn = 1) +#define FSPI_DISABLE(pCtrl) (SPI_SSIEN_REG(pCtrl)->val.SsiEn = 0) +/* shortcut to access register */ +#define SPI_CTRL0_REG(pCtrl) ((FSpi_CtrlReg0_t *)(SPI_BASE_ADDR(pCtrl) + SPI_CTRL_R0)) +#define SPI_CTRL1_REG(pCtrl) ((FSpi_CtrlReg1_t *)(SPI_BASE_ADDR(pCtrl) + SPI_CTRL_R1)) +#define SPI_TXFTL_REG(pCtrl) ((FSpi_TxFtlrReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_TXFTL_R)) +#define SPI_RXFTL_REG(pCtrl) ((FSpi_RxFtlrReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_RXFTL_R)) +#define SPI_TXFL_REG(pCtrl) ((FSpi_TxFlrReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_TXFL_R)) +#define SPI_RXFL_REG(pCtrl) ((FSpi_RxFlrReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_RXFL_R)) +#define SPI_ID_REG(pCtrl) ((FSpi_IDReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_ID_R)) +#define FSPI_GET_ID(pCtrl) (SPI_ID_REG(pCtrl)->IdCode) +#define SPI_DATA_REG(pCtrl) ((FSpi_DataReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_D_R)) +#define FSPI_READ_DATA(pCtrl) (u16)(SPI_DATA_REG(pCtrl)->val.Dr) +#define FSPI_WRITE_DATA(pCtrl, dat) (SPI_DATA_REG(pCtrl)->val.Dr = (u16)(dat)) +#define SPI_RXSAMPLE_DLY_REG(pCtrl) ((FSpi_RxSampleDlyReg_t *)(SPI_BASE_ADDR(pCtrl) + SPI_RX_SAMPLE_DLY)) +#define SPI_MWCTRL_REG(pCtrl) ((FSpi_MwcrReg_t *)SPI_BASE_ADDR(pCtrl) + SPI_MW_CR) + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/ft_spi/ft_spi_irq.c b/bsp/ft2004/libraries/bsp/ft_spi/ft_spi_irq.c new file mode 100644 index 0000000000000000000000000000000000000000..7a53a33589d427830efca09922cad1615c040970 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_spi/ft_spi_irq.c @@ -0,0 +1,13 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-25 14:00:39 + * @LastEditTime: 2021-04-25 14:00:39 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ diff --git a/bsp/ft2004/libraries/bsp/ft_uart/ft_uart.c b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart.c new file mode 100644 index 0000000000000000000000000000000000000000..750b0c83a9bb6095c57395e9029e73a72f33559e --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart.c @@ -0,0 +1,287 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-07 17:49:58 + * @Description:  This files is for uart functions + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +/***************************** Include Files ********************************/ + +#include "ft_status.h" +#include "ft_uart.h" +#include "ft_io.h" + +u32 FUart_SendBuffer(Ft_Uart *UartPtr); +u32 FUart_ReceiveBuffer(Ft_Uart *UartPtr); + +static void FUart_StubHandler(void *Args, u32 Event, + u32 ByteCount); + +/** + * @name: FUart_CfgInitialize + * @msg: initalize uart configure + * @return {*} + * @param {Ft_Uart} *UartPtr + * @param {FUart_Config_t} *Config + */ +s32 FUart_CfgInitialize(Ft_Uart *UartPtr, FUart_Config_t *Config) +{ + u32 RegValue = 0; + + Ft_assertNonvoid(UartPtr != NULL); + Ft_assertNonvoid(Config != NULL); + + UartPtr->Config.InstanceId = Config->InstanceId; + UartPtr->Config.BaseAddress = Config->BaseAddress; + UartPtr->Config.RefClockHz = Config->RefClockHz; + UartPtr->Config.IsrNum = Config->IsrNum; + + UartPtr->Handler = FUart_StubHandler; + + UartPtr->SendBuffer.BytePtr = NULL; + UartPtr->SendBuffer.RequestedBytes = 0; + UartPtr->SendBuffer.RemainingBytes = 0; + + UartPtr->ReceiveBuffer.BytePtr = NULL; + UartPtr->ReceiveBuffer.RequestedBytes = 0; + UartPtr->ReceiveBuffer.RemainingBytes = 0; + UartPtr->rxbs_error = 0; + UartPtr->IsReady = FT_COMPONENT_IS_READLY; + //Config.BaseAddress, UARTLCR_H_OFFSET, RegValue); + + /* Set the RX FIFO trigger at 8 data bytes.Tx FIFO trigger is 8 data bytes*/ + RegValue = (1 << 3) | (1 << 0); + FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTIFLS_OFFSET, RegValue); + + /* Disable all interrupts, polled mode is the default */ + RegValue = 0; + FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET, RegValue); + return FST_SUCCESS; +} + +/** + * @name: FUart_Send + * @msg: + * @param {Ft_Uart} *UartPtr + * @param {u8} *Buffer + * @param {u32} Length + * @return {u32} The Number of bytes actully sent. + */ +u32 FUart_Send(Ft_Uart *UartPtr, u8 *BytePtr, u32 Length) +{ + u32 RegValue = 0; + u32 SentCount = 0; + Ft_assertNonvoid(UartPtr != NULL); + Ft_assertNonvoid(BytePtr != NULL); + Ft_assertNonvoid(UartPtr->IsReady == FT_COMPONENT_IS_READLY); + + /* + * Disable the UART transmit interrupts to allow this call to stop a + * previous operation that may be interrupt driven. + */ + RegValue = FT_UART_ReadReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET); + RegValue &= ~(UARTIMSC_TXIM); + FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET, RegValue); + + UartPtr->SendBuffer.BytePtr = BytePtr; + UartPtr->SendBuffer.RequestedBytes = Length; + UartPtr->SendBuffer.RemainingBytes = Length; + + SentCount = FUart_SendBuffer(UartPtr); + + return SentCount; +} + +/** + * @name: FUart_PutChar + * @msg: send a char through uart + * @return {*} + * @param {Ft_Uart} *UartPtr + * @param {s8} Data + */ +void FUart_PutChar(Ft_Uart *UartPtr, s8 Data) +{ + Ft_assertVoid(UartPtr != NULL); + Ft_assertVoid(UartPtr->IsReady == FT_COMPONENT_IS_READLY); + + while (!FT_UART_IsTransmitFull(UartPtr->Config.BaseAddress)) + { + FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTDR_OFFSET, Data); + break; + } +} + +static void FUart_StubHandler(void *Args, u32 Event, + u32 ByteCount) +{ + (void)Args; + (void)Event; + (void)ByteCount; + + Ft_assertVoidAlways(); +} + +/** + * @name: FUart_SendBuffer + * @msg: send data buffer through uart + * @return {*} + * @param {Ft_Uart} *UartPtr + */ +u32 FUart_SendBuffer(Ft_Uart *UartPtr) +{ + u32 SentCount = 0U; + u32 RegValue; + + /* + * If the TX FIFO is full, send nothing. + * Otherwise put bytes into the TX FIFO unil it is full, or all of the + * data has been put into the FIFO. + */ + while ((!FT_UART_IsTransmitFull(UartPtr->Config.BaseAddress)) && (UartPtr->SendBuffer.RemainingBytes > SentCount)) + { + FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTDR_OFFSET, (u32)UartPtr->SendBuffer.BytePtr[SentCount]); + SentCount++; + } + + /* Update the buffer to reflect the bytes that were sent from it */ + UartPtr->SendBuffer.BytePtr += SentCount; + UartPtr->SendBuffer.RemainingBytes -= SentCount; + + RegValue = FT_UART_ReadReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET); + RegValue |= (UARTIMSC_TXIM); + FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET, RegValue); + + return SentCount; +} + +/** + * @name: FUart_Receive + * @msg: receive data through uart + * @return {*} + * @param {Ft_Uart} *UartPtr + * @param {u8} *BytePtr + * @param {u32} Length + */ +u32 FUart_Receive(Ft_Uart *UartPtr, u8 *BytePtr, u32 Length) +{ + u32 Received; + u32 BackRegValue; + + Ft_assertNonvoid(UartPtr != NULL); + Ft_assertNonvoid(BytePtr != NULL); + Ft_assertNonvoid(UartPtr->IsReady == FT_COMPONENT_IS_READLY); + + /* + * Disable all the interrupts. + * This stops a previous operation that may be interrupt driven + */ + BackRegValue = FT_UART_ReadReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET); + FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET, 0); + + UartPtr->ReceiveBuffer.BytePtr = BytePtr; + UartPtr->ReceiveBuffer.RequestedBytes = Length; + UartPtr->ReceiveBuffer.RemainingBytes = Length; + + Received = FUart_ReceiveBuffer(UartPtr); + FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET, BackRegValue); + + return Received; +} + +/** + * @name: Ft_Uart_ReceiveBuffer + * @msg: handling uart receive buffer + * @return {*} + * @param {Ft_Uart} *UartPtr + */ +u32 FUart_ReceiveBuffer(Ft_Uart *UartPtr) +{ + + u32 ReceivedCount = 0U; + u32 Event; + u32 EventData; + u32 ByteValue; + + while ((ReceivedCount < UartPtr->ReceiveBuffer.RemainingBytes) && !FT_UART_IsReceiveData(UartPtr->Config.BaseAddress)) + { + ByteValue = FT_UART_ReadReg(UartPtr->Config.BaseAddress, UARTDR_OFFSET); + + if (UartPtr->rxbs_error) + { + if ((ByteValue & UARTDR_ALLE) != 0) + { + EventData = ByteValue; + Event = FUART_EVENT_PARE_FRAME_BRKE; + + if (UartPtr->Handler) + { + UartPtr->Handler(UartPtr->Args, Event, EventData); + } + } + } + UartPtr->ReceiveBuffer.BytePtr[ReceivedCount] = (u8)(ByteValue & 0xff); + ReceivedCount++; + } + + UartPtr->rxbs_error = 0; + + if (UartPtr->ReceiveBuffer.BytePtr != NULL) + { + UartPtr->ReceiveBuffer.BytePtr += ReceivedCount; + } + UartPtr->ReceiveBuffer.RemainingBytes -= ReceivedCount; + + return ReceivedCount; +} + +/** + * @name: FUart_BlockSend + * @msg: initiate uart block send + * @return {*} + * @param {Ft_Uart} *UartPtr + * @param {u8} *BytePtr + * @param {u32} Length + */ +void FUart_BlockSend(Ft_Uart *UartPtr, u8 *BytePtr, u32 Length) +{ + u32 index; + + Ft_assertVoid(UartPtr != NULL); + Ft_assertVoid(BytePtr != NULL); + Ft_assertVoid(UartPtr->IsReady == FT_COMPONENT_IS_READLY); + + for (index = 0; index < Length; index++) + { + FUart_SendByte(UartPtr->Config.BaseAddress, BytePtr[index]); + } +} + +/** + * @name: FUart_BlockReceive + * @msg: initiate uart block receive + * @return {*} + * @param {Ft_Uart} *UartPtr + */ +u8 FUart_BlockReceive(Ft_Uart *UartPtr) +{ + Ft_assertNonvoid(UartPtr != NULL); + Ft_assertNonvoid(UartPtr->IsReady == FT_COMPONENT_IS_READLY); + return FUart_RecvByte(UartPtr->Config.BaseAddress); +} \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/ft_uart/ft_uart.h b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart.h new file mode 100644 index 0000000000000000000000000000000000000000..e072fdab7dd6a6e96c86db6317d92a5aae352579 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart.h @@ -0,0 +1,111 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-19 16:30:05 + * @Description:  This files is for uart functions + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef FT_UART_H +#define FT_UART_H + +#include "ft_types.h" +#include "ft_assert.h" +#include "ft_status.h" +#include "ft_uart_hw.h" + +#define FUART_BAUDRATE 115200U + +/* Config options */ +#define FUART_OPTION_UARTEN 0x1U +#define FUART_OPTION_RXEN 0x2U +#define FUART_OPTION_TXEN 0x4U +#define FUART_OPTION_FIFOEN 0x8U + +/* Data format values */ +#define FUART_FORMAT_WORDLENGTH_8BIT 0x3 +#define FUART_FORMAT_WORDLENGTH_7BIT 0x2 +#define FUART_FORMAT_WORDLENGTH_6BIT 0x1 +#define FUART_FORMAT_WORDLENGTH_5BIT 0x0 + +#define FUART_FORMAT_NO_PARITY 0U +#define FUART_FORMAT_MARK_PARITY 1U +#define FUART_FORMAT_SPACE_PARITY 2U +#define FUART_FORMAT_ODD_PARTY 3U +#define FUART_FORMAT_EVEN_PARITY 4U + +#define FUART_FORMAT_2_STOP_BIT 0U +#define FUART_FORMAT_1_STOP_BIT 1U + +/* Callback events */ + +#define FUART_EVENT_RECV_DATA 1U /**< Data receiving done */ +#define FUART_EVENT_RECV_TOUT 2U /**< A receive timeout occurred */ +#define FUART_EVENT_SENT_DATA 3U /**< Data transmission done */ +#define FUART_EVENT_RECV_ERROR 4U /**< A receive error detected */ +#define FUART_EVENT_MODEM 5U /**< Modem status changed */ +#define FUART_EVENT_PARE_FRAME_BRKE 6U /**< A receive parity, frame, break \ + * error detected */ +#define FUART_EVENT_RECV_ORERR 7U /**< A receive overrun error detected */ + +/**************************** Type Definitions ******************************/ +typedef struct +{ + u32 InstanceId; /* Id of device*/ + u32 BaseAddress; + u32 RefClockHz; + u32 IsrNum; +} FUart_Config_t; + +typedef struct +{ + u8 *BytePtr; + u32 RequestedBytes; + u32 RemainingBytes; +} FUart_Buffer_t; + +typedef struct +{ + u32 BaudRate; /**< In bps, ie 1200 */ + u32 DataBits; /**< Number of data bits */ + u32 Parity; /**< Parity */ + u8 StopBits; /**< Number of stop bits */ +} FUart_Format_t; + +typedef void (*FUart_Handler_t)(void *Args, u32 Event, u32 EventData); + +typedef struct +{ + FUart_Config_t Config; /* Configuration data structure */ + u32 InputClockHz; + u32 IsReady; /* Device is ininitialized and ready*/ + u32 BaudRate; + + FUart_Buffer_t SendBuffer; + FUart_Buffer_t ReceiveBuffer; + + FUart_Handler_t Handler; + void *Args; + uint8_t rxbs_error; /* 接收过程中出现错误 ,0 无错误,1 存在错误*/ + +} Ft_Uart; + +void FUart_PutChar(Ft_Uart *UartPtr, s8 Data); +u32 FUart_Send(Ft_Uart *UartPtr, u8 *Buffer, u32 Length); +u32 FUart_Receive(Ft_Uart *UartPtr, u8 *BytePtr, u32 Length); +s32 FUart_CfgInitialize(Ft_Uart *UartPtr, FUart_Config_t *Config); +FUart_Config_t *FUart_LookupConfig(u32 InstanceId); +void FUart_SetOptions(Ft_Uart *UartPtr, u32 Options); +void FUart_SetSpecificOptions(Ft_Uart *UartPtr, u32 Options); +void FUart_ClearSpecificOptions(Ft_Uart *UartPtr, u32 Options); +void FUart_InterruptHandler(Ft_Uart *UartPtr); +void FUart_SetHandler(Ft_Uart *UartPtr, FUart_Handler_t FuncPtr, + void *Args); +void FUart_SetInterruptMask(Ft_Uart *UartPtr, u32 Mask); +#endif // ! \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_g.c b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_g.c new file mode 100644 index 0000000000000000000000000000000000000000..1da9225045cd2ed164dc5cf526f0dba1f2529794 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_g.c @@ -0,0 +1,34 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-07 13:42:30 + * @Description:  This files is for uart config + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_uart.h" +#include "ft_parameters.h" + +FUart_Config_t FUart_Config_tTable[FT_UART_NUM] = { + {FT_UART0_ID, + FT_UART0_BASE_ADDR, + FT_UART0_CLK_FREQ_HZ, + 38}, + {FT_UART1_ID, + FT_UART1_BASE_ADDR, + FT_UART1_CLK_FREQ_HZ, + 39}, + {FT_UART2_ID, + FT_UART2_BASE_ADDR, + FT_UART2_CLK_FREQ_HZ, + 40}, + {FT_UART3_ID, + FT_UART3_BASE_ADDR, + FT_UART3_CLK_FREQ_HZ, + 41}}; diff --git a/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_hw.c b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_hw.c new file mode 100644 index 0000000000000000000000000000000000000000..0f52367ddbd7ef32b8a2444f8b050ffdbf9e9790 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_hw.c @@ -0,0 +1,66 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-07 17:54:21 + * @Description:  This files is for uart register function + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + + +#include "ft_uart_hw.h" + +/** + * @name: FUart_SendByte + * @msg: + * @return {*} + * @param {u32} BaseAddress + * @param {u8} Byte + */ +void FUart_SendByte(u32 BaseAddress, u8 Byte) +{ + while (FT_UART_IsTransmitFull(BaseAddress)) + { + ; + } + FT_UART_WriteReg(BaseAddress, UARTDR_OFFSET, (u32)Byte); +} + +/** + * @name: FUart_RecvByte + * @msg: + * @return {*} + * @param {u32} BaseAddress + */ +u8 FUart_RecvByte(u32 BaseAddress) +{ + u32 RecievedByte; + while (FT_UART_IsReceiveData(BaseAddress)) + { + ; + } + RecievedByte = FT_UART_ReadReg(BaseAddress, UARTDR_OFFSET); + return RecievedByte; +} + +/** + * @name: FUart_GetChar + * @msg: + * @return {*} + * @param {u32} BaseAddress + */ +u8 FUart_GetChar(u32 BaseAddress) +{ + u32 RecievedByte; + if (FT_UART_IsReceiveData(BaseAddress)) + { + return 0xff; + } + RecievedByte = FT_UART_ReadReg(BaseAddress, UARTDR_OFFSET); + return RecievedByte; +} diff --git a/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_hw.h b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_hw.h new file mode 100644 index 0000000000000000000000000000000000000000..2a3ac1c749923b6ee627145f448337f5faa90cd8 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_hw.h @@ -0,0 +1,222 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology(TianJin), Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-03-31 14:59:20 + * @LastEditTime: 2021-04-02 14:14:34 + * @Description:  This files is for definition of uart register + * + * @Modify History: * * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + + +#ifndef FT_UART_HW_H +#define FT_UART_HW_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ft_types.h" +#include "ft_assert.h" +#include "ft_io.h" + +/************************** Constant Definitions *****************************/ + +/** @name Register Map + * + * Register offsets for the UART. + * @{ + */ + +#define UARTDR_OFFSET 0U /* 数据寄存器 */ +#define UARTRSR_OFFSET 4U /* 接收状态寄存器/错误清除寄存器 */ +#define UARTECR_OFFSET UARTRSR_OFFSET +#define UARTFTR_OFFSET 0x18U /* 标志寄存器 */ +#define UARTILPR_OFFSET 0x020U /* 低功耗计数寄存器 */ +#define UARTIBRD_OFFSET 0x024U /* 波特率整数值配置寄存器 */ +#define UARTFBRD_OFFSET 0x028U /* 波特率小数值配置寄存器 */ +#define UARTLCR_H_OFFSET 0x02cU /* 线控寄存器 */ +#define UARTCR_OFFSET 0x030U /* 控制寄存器 */ +#define UARTIFLS_OFFSET 0x034U /* FIFO阈值选择寄存器 */ +#define UARTIMSC_OFFSET 0x038U /* 中断屏蔽选择清除寄存器 */ +#define UARTRIS_OFFSET 0x03cU /* 中断状态寄存器 */ +#define UARTMIS_OFFSET 0x040U /* 中断屏蔽状态寄存器 */ +#define UARTICR_OFFSET 0x044U /* 中断清除寄存器 */ +#define UARTDMACR_OFFSET 0x048U /* DMA控制寄存器 */ + + /* 数据寄存器 RW */ + +#define UARTDR_OE 0x800U /* 如果接收到数据并且接收的 FIFO 已满,该位设置为 1 */ +#define UARTDR_BE 0x400U /* 突发错误 */ +#define UARTDR_PE 0x200U /* 奇偶校验错误。 */ +#define UARTDR_FE 0x100U /* 帧错误。 */ +#define UARTDR_ALLE (UARTDR_OE | UARTDR_BE | UARTDR_PE | UARTDR_FE) +#define UARTDR_DATA 0xffU /* R 接收数据 ,W 传输数据 */ + + /* 接收状态寄存器 RW */ + +#define UARTRSR_OE 0x8U /* 溢出错误。 */ +#define UARTRSR_BE 0x4U /* 突发错误 */ +#define UARTRSR_PE 0x2U /* 奇偶校验错误。 */ +#define UARTRSR_FE 0x1U /* 帧错误 */ + +#define UARTECR_CLE 0xffU /* 清除 */ + +/* 标志寄存器 RO */ +#define UARTFTR_RI 0x100U /* Ring indicator */ +#define UARTFTR_TXFE 0x80U /* Transmit FIFO empty */ +#define UARTFTR_RXFF 0x40U /* Receive FIFO full */ +#define UARTFTR_TXFF 0x20U /* Transmit FIFO full. */ +#define UARTFTR_RXFE 0x10U /* Receive FIFO empty */ +#define UARTFTR_BUSY 0x08U /* UART busy */ +#define UARTFTR_DCD 0x04U /* Data carrier detect. */ +#define UARTFTR_DSR 0x02U /* Data set ready. */ +#define UARTFTR_CTS 0x1U /* Clear to send */ + +/* IrDA 低功耗计数寄存器 RW */ +#define UARTILPR_ILPDVSR 0xffU /* 8-bit low-power divisor value. These bits are cleared to 0 at reset */ + +/* 波特率整数值配置寄存器 RW */ +#define UARTIBRD_BAUD_DIVFRAC 0xffffU /* The fractional baud rate divisor. */ + +/* 波特率小数值配置寄存器 RW */ +#define UARTFBRD_BAUD_DIVFRAC 0x3fU /* The fractional baud rate divisor. */ + +/* 线控寄存器 RW */ +#define UARTLCR_H_SPS 0x80U /* Stick parity select. */ +#define UARTLCR_H_WLEN 0x60U /* Word length. */ +#define UARTLCR_H_FEN 0x10U /* Enable FIFOs. */ +#define UARTLCR_H_STP2 0x08U /* Two stop bits select. */ +#define UARTLCR_H_EPS 0x04U /* Even parity select. */ +#define UARTLCR_H_PEN 0x02U /* Parity enable. */ +#define UARTLCR_H_BRK 0x01U /* send break */ + +/* 控制寄存器 RW */ +#define UARTCR_CTSEN 0x8000U /* CTS hardware flow control enable. */ +#define UARTCR_RTSEN 0x4000U /* RTS hardware flow control enable. */ +#define UARTCR_OUT2 0x2000U /* This bit is the complement of the UART Out2 (nUARTOut2) modem status output. */ +#define UARTCR_Out1 0x1000U /* This bit is the complement of the UART Out1 (nUARTOut1) modem status output. */ +#define UARTCR_RTS 0x0800U /* Request to send. */ +#define UARTCR_DTR 0x0400U /* Data transmit ready */ +#define UARTCR_RXE 0x0200U /* Receive enable. */ +#define UARTCR_TXE 0x0100U /* Transmit enable. */ +#define UARTCR_LBE 0x0080U /* Loop back enable.*/ +#define UARTCR_SIRLP 0x4U /* IrDA SIR low power mode. */ +#define UARTCR_SIREN 0x2U /* SIR enable. */ +#define UARTCR_UARTEN 0x1U /* UART enable. */ + +/* FIFO阈值选择寄存器 RW */ +#define UARTIFLS_RXIFLSEL 0x38U /* Receive interrupt FIFO level select. */ +#define UARTIFLS_TXIFLSEL 0x7U /* Transmit interrupt FIFO level select. */ + +/* 中断屏蔽选择清除寄存器 RW */ +#define UARTIMSC_OEIM 0x400U /* Overrun error interrupt mask. */ +#define UARTIMSC_BEIM 0x200U /* Break error interrupt mask */ +#define UARTIMSC_PEIM 0x100U /* Parity error interrupt mask. */ +#define UARTIMSC_FEIM 0x80U /* Framing error interrupt mask. */ +#define UARTIMSC_RTIM 0x40U /* Receive timeout interrupt mask. */ +#define UARTIMSC_TXIM 0x20U /* Transmit interrupt mask. */ +#define UARTIMSC_RXIM 0x10U /* Receive interrupt mask. */ +#define UARTIMSC_DSRMIM 0x8U /* nUARTDSR modem interrupt mask. */ +#define UARTIMSC_DCDMIM 0x4U /* nUARTDCD modem interrupt mask. */ +#define UARTIMSC_CTSMIM 0x2U /* nUARTCTS modem interrupt mask. */ +#define UARTIMSC_RIMIM 0x1U /* nUARTRI modem interrupt mask. */ +#define UARTIMSC_ALLM 0x3ffU /* all interrupt mask */ + + /* 中断状态寄存器 RO */ + +#define UARTRIS_OEIS 0x400U /* Overrun error interrupt mask. */ +#define UARTRIS_BEIS 0x200U /* Break error interrupt mask */ +#define UARTRIS_PEIS 0x100U /* Parity error interrupt mask. */ +#define UARTRIS_FEIS 0x80U /* Framing error interrupt mask. */ +#define UARTRIS_RTIS 0x40U /* Receive timeout interrupt mask. */ +#define UARTRIS_TXIS 0x20U /* Transmit interrupt mask. */ +#define UARTRIS_RXIS 0x10U /* Receive interrupt mask. */ +#define UARTRIS_DSRMIS 0x8U /* nUARTDSR modem interrupt mask. */ +#define UARTRIS_DCDMIS 0x4U /* nUARTDCD modem interrupt mask. */ +#define UARTRIS_CTSMIS 0x2U /* nUARTCTS modem interrupt mask. */ +#define UARTRIS_RIMIS 0x1U /* nUARTRI modem interrupt mask. */ + + /* 中断屏蔽状态寄存器 R0 */ + +#define UARTMIS_OEMIS 0x400U /* Overrun error interrupt mask. */ +#define UARTMIS_BEMIS 0x200U /* Break error interrupt mask */ +#define UARTMIS_PEMIS 0x100U /* Parity error interrupt mask. */ +#define UARTMIS_FEMIS 0x80U /* Framing error interrupt mask. */ +#define UARTMIS_RTMIS 0x40U /* Receive timeout interrupt mask. */ +#define UARTMIS_TXMIS 0x20U /* Transmit interrupt mask. */ +#define UARTMIS_RXMIS 0x10U /* Receive interrupt mask. */ +#define UARTMIS_DSRMMIS 0x8U /* nUARTDSR modem interrupt mask. */ +#define UARTMIS_DCDMMIS 0x4U /* nUARTDCD modem interrupt mask. */ +#define UARTMIS_CTSMMIS 0x2U /* nUARTCTS modem interrupt mask. */ +#define UARTMIS_RIMMIS 0x1U /* nUARTRI modem interrupt mask. */ + +/* 中断清除寄存器 WO */ +#define UARTICR_OEIC 0x400U /* Overrun error interrupt mask. */ +#define UARTICR_BEIC 0x200U /* Break error interrupt mask */ +#define UARTICR_PEIC 0x100U /* Parity error interrupt mask. */ +#define UARTICR_FEIC 0x80U /* Framing error interrupt mask. */ +#define UARTICR_RTIC 0x40U /* Receive timeout interrupt mask. */ +#define UARTICR_TXIC 0x20U /* Transmit interrupt mask. */ +#define UARTICR_RXIC 0x10U /* Receive interrupt mask. */ +#define UARTICR_DSRMIC 0x8U /* nUARTDSR modem interrupt mask. */ +#define UARTICR_DCDMIC 0x4U /* nUARTDCD modem interrupt mask. */ +#define UARTICR_CTSMIC 0x2U /* nUARTCTS modem interrupt mask. */ +#define UARTICR_RIMIC 0x1U /* nUARTRI modem interrupt mask. */ + +/* DMA控制寄存器 RW */ +#define UARTDMACR_DMAONERR 0x4U /* DMA on error. */ +#define UARTDMACR_TXDMAE 0x2U /* Transmit DMA enable. */ +#define UARTDMACR_RXDMAE 0x1U /* Receive DMA enable. */ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/** + * @name: FT_UART_ReadReg + * @msg: 读取串口寄存器 + * @param {u32} BaseAddress 串口的基地址 + * @param {u32} RegOffset 串口的寄存器的偏移 + * @return {u32} 寄存器参数 + */ +#define FT_UART_ReadReg(BaseAddress, RegOffset) Ft_in32(BaseAddress + (u32)RegOffset) + +/** + * @name: FT_UART_WriteReg + * @msg: 写入串口寄存器 + * @param {u32} BaseAddress 串口的基地址 + * @param {u32} RegOffset 串口的寄存器的偏移 + * @param {u32} RegisterValue 写入寄存器参数 + * @return {void} + */ +#define FT_UART_WriteReg(BaseAddress, RegOffset, RegisterValue) Ft_out32(BaseAddress + (u32)RegOffset, (u32)RegisterValue) + +/** + * @name: FT_UART_ISRECEIVEDATA + * @msg: 用于确认是否接收到数据 + * @param {u32} BaseAddress 串口的基地址 + * @return {bool} true 是存在数据 , false 是不存在数据 + * + */ +#define FT_UART_IsReceiveData(BaseAddress) (Ft_in32(BaseAddress + UARTFTR_OFFSET) & UARTFTR_RXFE) + +/** + * @name: FT_UART_ISTRANSMITFULL + * @msg: 用于确认是否能够发送数据 + * @param {u32} BaseAddress 串口的基地址 + * @return {bool} true 是数据已满 , false 可以发送数据 + */ +#define FT_UART_IsTransmitFull(BaseAddress) ((Ft_in32(BaseAddress + UARTFTR_OFFSET) & (u32)UARTFTR_TXFF) == UARTFTR_TXFF) + + void FUart_SendByte(u32 BaseAddress, u8 Byte); + u8 FUart_RecvByte(u32 BaseAddress); + u8 FUart_GetChar(u32 BaseAddress); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_intr.c b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_intr.c new file mode 100644 index 0000000000000000000000000000000000000000..fc6dd5402acb803803c386c83af5505b398ff2cd --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_intr.c @@ -0,0 +1,209 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-07 17:52:02 + * @Description:  This files is for uart irq functions + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_uart.h" + +extern u32 FUart_SendBuffer(Ft_Uart *UartPtr); +extern u32 FUart_ReceiveBuffer(Ft_Uart *UartPtr); + +static void FUart_receiveErrorHandler(Ft_Uart *UartPtr, u32 InterruptStatus); +static void FUart_receiveDataHandler(Ft_Uart *UartPtr); +static void FUart_receiveTimeoutHandler(Ft_Uart *UartPtr); +static void FUart_sendDataHandler(Ft_Uart *UartPtr, u32 InterruptStatus); + +/** + * @name: FUart_GetInterruptMask + * @msg: 此函数获取所有串口中断的mask。 + * @param {Ft_Uart} *UartPtr + * @return {u32} mask + */ +u32 FUart_GetInterruptMask(Ft_Uart *UartPtr) +{ + Ft_assertNonvoid(UartPtr != NULL); + + return FT_UART_ReadReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET); +} + +/** + * @name: + * @msg: + * @param {Ft_Uart} *UartPtr + * @param {u32} Mask + * @return {*} + */ +void FUart_SetInterruptMask(Ft_Uart *UartPtr, u32 Mask) +{ + u32 TempMask = Mask; + Ft_assertVoid(UartPtr != NULL); + + TempMask &= UARTIMSC_ALLM; + + FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET, TempMask); +} + +/** + * @name: FUart_SetHandler + * @msg: 设置中断回调函数 + * @param {*} + * @return {*} + */ +void FUart_SetHandler(Ft_Uart *UartPtr, FUart_Handler_t FuncPtr, + void *Args) +{ + Ft_assertVoid(UartPtr != NULL); + Ft_assertVoid(FuncPtr != NULL); + Ft_assertVoid(UartPtr->IsReady == FT_COMPONENT_IS_READLY); + + UartPtr->Handler = FuncPtr; + UartPtr->Args = Args; +} + +/** + * @name: FUart_InterruptHandler + * @msg: 串口中断函数入口 + * @param {Ft_Uart} *UartPtr + * @return {*} + */ +void FUart_InterruptHandler(Ft_Uart *UartPtr) +{ + u32 RegValue = 0; + Ft_assertVoid(UartPtr != NULL); + Ft_assertVoid(UartPtr->IsReady == FT_COMPONENT_IS_READLY); + //Ft_printf("FUart_InterruptHandler %x\r\n", UartPtr); + RegValue = FT_UART_ReadReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET); + + RegValue &= FT_UART_ReadReg(UartPtr->Config.BaseAddress, UARTMIS_OFFSET); + + if ((RegValue & ((u32)UARTMIS_RXMIS)) != (u32)0) + { + /* Received data interrupt */ + FUart_receiveDataHandler(UartPtr); + } + + if ((RegValue & ((u32)UARTMIS_TXMIS)) != (u32)0) + { + /* Transmit data interrupt */ + FUart_sendDataHandler(UartPtr, RegValue); + } + + if (((RegValue) & ((u32)UARTMIS_OEMIS | (u32)UARTMIS_BEMIS | (u32)UARTMIS_PEMIS | (u32)UARTMIS_FEMIS)) != (u32)0) + { + /* Received Error Status interrupt */ + FUart_receiveErrorHandler(UartPtr, RegValue); + } + + if ((RegValue & ((u32)UARTMIS_RTMIS)) != (u32)0) + { + /* Received Timeout interrupt */ + FUart_receiveTimeoutHandler(UartPtr); + } + + if (((RegValue) & ((u32)UARTMIS_DSRMMIS | (u32)UARTMIS_DCDMMIS | (u32)UARTMIS_CTSMMIS | (u32)UARTMIS_RIMMIS)) != (u32)0) + { + /* Modem status interrupt */ + } + + /* Clear the interrupt status. */ + FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTICR_OFFSET, + RegValue); +} + +static void FUart_receiveErrorHandler(Ft_Uart *UartPtr, u32 InterruptStatus) +{ + UartPtr->rxbs_error = 0; + + if (((InterruptStatus) & ((u32)UARTMIS_OEMIS | (u32)UARTMIS_BEMIS | (u32)UARTMIS_PEMIS | (u32)UARTMIS_FEMIS)) != 0) + { + UartPtr->rxbs_error = 1; + } + + (void)FUart_ReceiveBuffer(UartPtr); + + if (0 == UartPtr->rxbs_error) + { + if (UartPtr->Handler) + { + UartPtr->Handler(UartPtr->Args, FUART_EVENT_RECV_ERROR, UartPtr->ReceiveBuffer.RequestedBytes - UartPtr->ReceiveBuffer.RemainingBytes); + } + } +} + +/** + * @name: FUart_receiveDataHandler + * @msg: + * @param {*} + * @return {*} + */ +static void FUart_receiveDataHandler(Ft_Uart *UartPtr) +{ + if ((u32)0 != UartPtr->ReceiveBuffer.RemainingBytes) + { + (void)FUart_ReceiveBuffer(UartPtr); + } + + if ((u32)0 == UartPtr->ReceiveBuffer.RemainingBytes) + { + if (UartPtr->Handler) + { + UartPtr->Handler(UartPtr->Args, FUART_EVENT_RECV_DATA, UartPtr->ReceiveBuffer.RequestedBytes - UartPtr->ReceiveBuffer.RemainingBytes); + } + } +} + +static void FUart_receiveTimeoutHandler(Ft_Uart *UartPtr) +{ + u32 Event; + + if ((u32)0 != UartPtr->ReceiveBuffer.RemainingBytes) + { + (void)FUart_ReceiveBuffer(UartPtr); + } + + if ((u32)0 == UartPtr->ReceiveBuffer.RemainingBytes) + { + Event = FUART_EVENT_RECV_TOUT; + } + else + { + Event = FUART_EVENT_RECV_DATA; + } + + if (UartPtr->Handler) + { + UartPtr->Handler(UartPtr->Args, Event, UartPtr->ReceiveBuffer.RequestedBytes - UartPtr->ReceiveBuffer.RemainingBytes); + } +} + +static void FUart_sendDataHandler(Ft_Uart *UartPtr, u32 InterruptStatus) +{ + u32 RegValue; + if (UartPtr->SendBuffer.RemainingBytes == (u32)0) + { + //Config.BaseAddress, UARTIMSC_OFFSET); + RegValue &= ~UARTIMSC_TXIM; + FT_UART_WriteReg(UartPtr->Config.BaseAddress, UARTIMSC_OFFSET, RegValue); + if (UartPtr->Handler) + { + UartPtr->Handler(UartPtr->Args, FUART_EVENT_RECV_DATA, UartPtr->ReceiveBuffer.RequestedBytes - UartPtr->ReceiveBuffer.RemainingBytes); + } + } + else if (InterruptStatus & UARTMIS_TXMIS) + { + FUart_SendBuffer(UartPtr); + } + else + { + } +} diff --git a/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_options.c b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_options.c new file mode 100644 index 0000000000000000000000000000000000000000..58b5bea59a932a266611fd402c8d25beb18d275e --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_options.c @@ -0,0 +1,60 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-19 16:28:05 + * @Description:  This files is for uart option setting + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_uart.h" +#include "ft_uart_hw.h" +#include "ft_types.h" +/************************** Variable Definitions ****************************/ +/* + * The following data type is a map from an option to the offset in the + * register to which it belongs as well as its bit mask in that register. + */ +typedef struct +{ + u32 Option; + u32 RegisterOffset; + u32 Mask; +} Mapping; + +static Mapping OptionTable[] = { + {FUART_OPTION_UARTEN, UARTCR_OFFSET, UARTCR_UARTEN}, + {FUART_OPTION_RXEN, UARTCR_OFFSET, UARTCR_RXE}, + {FUART_OPTION_TXEN, UARTCR_OFFSET, UARTCR_TXE}, + {FUART_OPTION_FIFOEN, UARTLCR_H_OFFSET, UARTLCR_H_FEN}}; + +#define FT_UART_NUM_OPITIONS (sizeof(OptionTable) / sizeof(Mapping)) + +void FUart_SetOptions(Ft_Uart *UartPtr, u32 Options) +{ + u32 Index; + u32 RegValue; + Ft_assertVoid(UartPtr != NULL); + Ft_assertVoid(UartPtr->IsReady == FT_COMPONENT_IS_READLY); + + for (Index = 0; Index < FT_UART_NUM_OPITIONS; Index++) + { + RegValue = FT_UART_ReadReg(UartPtr->Config.BaseAddress, OptionTable[Index].RegisterOffset); + + if ((Options & OptionTable[Index].Option) != (u32)(0)) + { + RegValue |= OptionTable[Index].Mask; + } + else + { + RegValue &= ~OptionTable[Index].Mask; + } + + FT_UART_WriteReg(UartPtr->Config.BaseAddress, OptionTable[Index].RegisterOffset, RegValue); + } +} diff --git a/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_selftest.c b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_selftest.c new file mode 100644 index 0000000000000000000000000000000000000000..0feffa0990927bd41fd5425ffaa2eba2fe5f499e --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_selftest.c @@ -0,0 +1,13 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-07 13:44:41 + * @Description:  This files is for uart test cases + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ diff --git a/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_sinit.c b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_sinit.c new file mode 100644 index 0000000000000000000000000000000000000000..da4f856b58820a5a4459c98eabf6d4e56d1d5dc6 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/ft_uart/ft_uart_sinit.c @@ -0,0 +1,41 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-07 13:44:56 + * @Description:  This files is for uart static init + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_uart.h" +#include "ft_parameters.h" + +extern FUart_Config_t FUart_Config_tTable[FT_UART_NUM]; + +/** + * @name: Ft_Uart_LookupConfig + * @msg: 获取串口的基本配置 + * @param {u16} InstanceId FT_UARTX_ID + * @return {*} + */ +FUart_Config_t *FUart_LookupConfig(u32 InstanceId) +{ + FUart_Config_t *CfgPtr = NULL; + u32 Index; + + for (Index = 0; Index < (u32)FT_UART_NUM; Index++) + { + if (FUart_Config_tTable[Index].InstanceId == InstanceId) + { + CfgPtr = &FUart_Config_tTable[Index]; + break; + } + } + + return (FUart_Config_t *)CfgPtr; +} \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/include/ft_parameters.h b/bsp/ft2004/libraries/bsp/include/ft_parameters.h new file mode 100644 index 0000000000000000000000000000000000000000..60612d98a32deb2a9dad043a98c9f1ff89509839 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/include/ft_parameters.h @@ -0,0 +1,204 @@ +/* + * [H]: Copyright (C) 2014-2021 Tianjin Phytium Technology.  All rights reserved. + * + *  Permission is hereby granted, free of charge, to any person obtaining a copy + *  of this software and associated documentation files (the "Software"), to deal + *  in the Software without restriction, including without limitation the rights + *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + *  copies of the Software, and to permit persons to whom the Software is + *  furnished to do so, subject to the following conditions: + * + *  The above copyright notice and this permission notice shall be included in + *  all copies or substantial portions of the Software. + * + *  Use of the Software is limited solely to applications: + *  (a) running on a Phytium device, or + *  (b) that interact with a Phytium device through a bus or interconnect. + * + *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + *  PHYTIUM  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + *  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + *  SOFTWARE. + * + *  Except as contained in this notice, the name of the Phytium shall not be used + *  in advertising or otherwise to promote the sale, use or other dealings in + *  this Software without prior written authorization from Phytium.  + * + * Date: 2021-03-30 14:57:03 + * LastEditTime: 2021-03-30 15:05:12 + * Description:  definitions of BSP parameters + * Modify History: + * * * Ver Who Date Changes + * * ----- ------ -------- ---------------------------------------------- + * 1.00 Huanghe 2021/3/1 init + */ + +#ifndef FT_PARAMETERS_H +#define FT_PARAMETERS_H + +/* Device register address */ +#define FT_DEV_BASE_ADDR 0x28000000 +#define FT_DEV_END_ADDR 0x2FFFFFFF + +/******** UART ************/ + +#define FT_UART_NUM 4 +#define FT_UART_REG_LENGTH 0x18000 + +#define FT_UART0_ID 0 +#define FT_UART0_BASE_ADDR 0x28000000 +#define FT_UART0_CLK_FREQ_HZ 48000000 + +#define FT_UART1_ID 1 +#define FT_UART1_BASE_ADDR 0x28001000 +#define FT_UART1_CLK_FREQ_HZ 48000000 + +#define FT_UART2_ID 2 +#define FT_UART2_BASE_ADDR 0x28002000 +#define FT_UART2_CLK_FREQ_HZ 48000000 + +#define FT_UART3_BASE_ADDR 0x28003000 +#define FT_UART3_ID 3 +#define FT_UART3_CLK_FREQ_HZ 48000000 + +#define FT_STDOUT_BASEADDRESS FT_UART1_BASE_ADDR +#define FT_STDIN_BASEADDRESS FT_UART1_BASE_ADDR + +/****** GIC v3 *****/ +#define FT_GICV3_INSTANCES_NUM 1U +#define GICV3_REG_LENGTH 0x00009000 + +/* + * The maximum priority value that can be used in the GIC. + */ +#define GICV3_MAX_INTR_PRIO_VAL 240U +#define GICV3_INTR_PRIO_MASK 0x000000f0U + +#define ARM_GIC_IPI_COUNT 16 /* MPCore IPI count */ +#define SGI_INT_MAX 16 +#define SPI_START_INT_NUM 32 /* SPI start at ID32 */ +#define PPI_START_INT_NUM 16 /* PPI start at ID16 */ +#define GIC_INT_MAX_NUM 1020 /* GIC max interrupts count */ + +#define FT_GICV3_BASEADDRESS 0x29900000U +#define FT_GICV3_DISTRIBUTOR_BASEADDRESS (FT_GICV3_BASEADDRESS + 0) +#define FT_GICV3_RD_BASEADDRESS (FT_GICV3_BASEADDRESS + 0x80000U) +#define FT_GICV3_SGI_BASEADDRESS (FT_GICV3_RD_BASEADDRESS + (1U << 16)) + +#define FT_GICV3_VECTORTABLE_NUM GIC_INT_MAX_NUM + +/** Gmac **/ +#define FT_GMAC_INSTANCES_NUM 2U +#define FT_GMAC_REG_LENGTH 0x00009000 + +#define FT_GMAC_COMMON_ADDR 0x2820B000U + +#define FT_GMAC0_ID 0 +#define FT_GMAC0_BASEADDR 0x2820C000U +#define FT_GMAC0_DEFAULT_ADDR \ + { \ + 0x11, 0x1c, 0x2c, 0x5c, 0x66, 0x88 \ + } + +#define FT_GMAC1_ID 1 +#define FT_GMAC1_BASEADDR 0x28210000U + +/** @defgroup ENET_Buffers_setting + * @{ + */ +#define GMAC_MAX_PACKET_SIZE 1600 /* GMAC_HEADER + GMAC_EXTRA + VLAN_TAG + MAX_GMAC_PAYLOAD + GMAC_CRC */ +#define GMAC_HEADER 14 /* 6 byte Dest addr, 6 byte Src addr, 2 byte length/type */ +#define GMAC_CRC 4 /* Gmac CRC */ +#define GMAC_EXTRA 2 /* Extra bytes in some cases */ +#define VLAN_TAG 4 /* optional 802.1q VLAN Tag */ +#define MIN_GMAC_PAYLOAD 46 /* Minimum Gmac payload size */ +#define MAX_GMAC_PAYLOAD 1500 /* Maximum Gmac payload size */ +#define JUMBO_FRAME_PAYLOAD 9000 /* Jumbo frame payload size */ +#define RX_DESCNUM 1024U /* Rx buffers of size GMAC_MAX_PACKET_SIZE */ +#define TX_DESCNUM 1024U /* Tx buffers of size GMAC_MAX_PACKET_SIZE */ + +#define PHY_USING_AR8035 + +#define GMAC0_ISRNUM 81 +#define GMAC0_ISRPRIORITY 0 + +#define GMAC1_ISRNUM 82 +#define GMAC1_ISRPRIORITY 0 + +/* SDC */ +#define FT_SDC_NUM 1 +#define FT_SDC_INSTANCE 0 +#define FT_SDC_BASEADDR 0x28207C00U +#define FT_SDC_REG_LENGTH 0x4000 +#define FT_SDC_FREQ 600000000 + +/* pin MUX/DEMUX */ + +#define FT_PIN_MUX_BASEADDR 0x28180000 +#define FT_PIN_MUX_REG_LENGTH 0x10000 + +/* CAN */ + +#define FT_CAN_NUM 3 +#define FT_CAN_REG_LENGTH 0x1000 +#define FT_CAN0_BASEADDR 0x28207000 +#define FT_CAN1_BASEADDR 0x28207400 +#define FT_CAN2_BASEADDR 0x28207800 +#define FT_CAN0_IRQNUM 119 +#define FT_CAN1_IRQNUM 123 +#define FT_CAN2_IRQNUM 124 +#define FT_CAN_BAUDRATE 1000000 /* 1M */ +#define FT_CAN_CLK 600000000 + +/* pci */ + +#define FT_PCI_CONFIG_BASEADDR 0x40000000 +#define FT_PCI_CONFIG_REG_LENGTH 0x10000000 + +#define FT_PCI_IO_CONFIG_BASEADDR 0x50000000 +#define FT_PCI_IO_CONFIG_REG_LENGTH 0x08000000 + +#define FT_PCI_MEM32_BASEADDR 0x58000000 +#define FT_PCI_MEM32_REG_LENGTH 0x27000000 + +/* qspi */ +#define FT_QSPI_NUM 1U +#define FT_QSPI_INSTANCE 0 +#define FT_QSPI_MAX_CS_NUM 4 +#define FT_QSPI_BASEADDR 0x28014000 + +#define FT_QSPI_FLASH_CAP_4MB 0 +#define FT_QSPI_FLASH_CAP_8MB 1 +#define FT_QSPI_FLASH_CAP_16MB 2 +#define FT_QSPI_FLASH_CAP_32MB 3 +#define FT_QSPI_FLASH_CAP_64MB 4 +#define FT_QSPI_FLASH_CAP_128MB 5 +#define FT_QSPI_FLASH_CAP_256MB 6 + +#define FT_QSPI_ADDR_SEL_3 0 +#define FT_QSPI_ADDR_SEL_4 1 + +#define FT_QSPI_SCK_DIV_128 0 +#define FT_QSPI_SCK_DIV_2 1 +#define FT_QSPI_SCK_DIV_4 2 +#define FT_QSPI_SCK_DIV_8 3 +#define FT_QSPI_SCK_DIV_16 4 +#define FT_QSPI_SCK_DIV_32 5 +#define FT_QSPI_SCK_DIV_64 6 + +#define FT_QSPI_TRANSFER_1_1_1 0 +#define FT_QSPI_TRANSFER_1_1_2 1 +#define FT_QSPI_TRANSFER_1_1_4 2 +#define FT_QSPI_TRANSFER_1_2_2 3 +#define FT_QSPI_TRANSFER_1_4_4 4 +#define FT_QSPI_TRANSFER_2_2_2 5 +#define FT_QSPI_TRANSFER_4_4_4 6 + +/* smp */ + +#define FT_SMP_EN + +#endif // ! \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_assert.c b/bsp/ft2004/libraries/bsp/standlone/ft_assert.c new file mode 100644 index 0000000000000000000000000000000000000000..a37c9ab5fd3ea596e306f14bac75706ffae84fad --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_assert.c @@ -0,0 +1,43 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-05-18 13:43:09 + * @Description:  This files is for type definition + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_types.h" +#include "ft_assert.h" + +/************* 全局变量 用于判断驱动是否出现断言 *****************/ +u32 Ft_assertStatus; + +/************** 断言是否需要无限等待,1 等待,0不等待 ******************/ +s32 Ft_assertWait = 1; + +/* 当断言发生时,将会调用此函数 */ +static Ft_assertCallback Ft_assertCallbackRoutine = NULL; + +/************************** Function Prototypes ******************************/ +void Ft_assert(FT_IN char *File, s32 Line) +{ + if (Ft_assertCallbackRoutine != NULL) + { + Ft_assertCallbackRoutine(File, Line); + } + + while (Ft_assertWait != 0) + { + } +} + +void Ft_assertSetCallBack(Ft_assertCallback Routine) +{ + Ft_assertCallbackRoutine = Routine; +} diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_assert.h b/bsp/ft2004/libraries/bsp/standlone/ft_assert.h new file mode 100644 index 0000000000000000000000000000000000000000..03dd543e152952d15290f5f40cc149d1cf3502a9 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_assert.h @@ -0,0 +1,154 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-05-18 13:43:19 + * @Description:  This files is for assert function + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef Ft_assert_H +#define Ft_assert_H + +#include "ft_types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define Fassert_NONE 0U +#define Fassert_OCCURRED 1U + + extern u32 Ft_assertStatus; + extern s32 Ft_assertWait; + extern void Ft_assert(FT_IN char *File, s32 Line); + + typedef void (*Ft_assertCallback)(FT_IN char *File, s32 Line); + +/** + * @name: Ft_assertVoid + * @msg: 断言函数不带返回值 + * @param {*} + * @return {*} + */ +#define Ft_assertVoid(Expression) \ + { \ + if (Expression) \ + { \ + Ft_assertStatus = Fassert_NONE; \ + } \ + else \ + { \ + Ft_assert(__FILE__, __LINE__); \ + Ft_assertStatus = Fassert_OCCURRED; \ + return; \ + } \ + } + +/** + * @name: + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + */ +#define Ft_assertBool(Expression) \ + { \ + if (Expression) \ + { \ + Ft_assertStatus = Fassert_NONE; \ + } \ + else \ + { \ + Ft_assert(__FILE__, __LINE__); \ + Ft_assertStatus = Fassert_OCCURRED; \ + return FALSE; \ + } \ + } + +/** + * @name: Ft_assertZeroNum + * @msg: 断言函数带返回值0 + * @param {*} + * @return {*} + */ +#define Ft_assertZeroNum(Expression) \ + { \ + if (Expression) \ + { \ + Ft_assertStatus = Fassert_NONE; \ + } \ + else \ + { \ + Ft_assert(__FILE__, __LINE__); \ + Ft_assertStatus = Fassert_OCCURRED; \ + return FST_ASSERT_RETURN; \ + } \ + } + +/** + * @name: Ft_assertNonvoid + * @msg: 断言函数带返回值FST_ASSERT_RETURN + * @param {*} + * @return {*} + */ +#define Ft_assertNonvoid(Expression) \ + { \ + if (Expression) \ + { \ + Ft_assertStatus = Fassert_NONE; \ + } \ + else \ + { \ + Ft_assert(__FILE__, __LINE__); \ + Ft_assertStatus = Fassert_OCCURRED; \ + return FST_ASSERT_RETURN; \ + } \ + } + +/** + * @name: Ft_assertNoneReturn + * @msg: 断言函数不返回 + * @param {*} + * @return {*} + */ +#define Ft_assertNoneReturn(Expression) \ + { \ + if (Expression) \ + { \ + Ft_assertStatus = Fassert_NONE; \ + } \ + else \ + { \ + Ft_assert(__FILE__, __LINE__); \ + Ft_assertStatus = Fassert_OCCURRED; \ + } \ + } + +#define Ft_assertVoidAlways() \ + { \ + Ft_assert(__FILE__, __LINE__); \ + Ft_assertStatus = Fassert_OCCURRED; \ + return; \ + } + +#define Ft_assertNonvoidAlways() \ + { \ + Ft_assert(__FILE__, __LINE__); \ + Ft_assertStatus = Fassert_OCCURRED; \ + return FST_ASSERT_RETURN; \ + } + + void Ft_assertSetCallBack(Ft_assertCallback routine); +#ifdef __cplusplus +} +#endif + +#endif // ! diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_cache.c b/bsp/ft2004/libraries/bsp/standlone/ft_cache.c new file mode 100644 index 0000000000000000000000000000000000000000..f21a20cbcb30844565fa85f3bbffa5f4eba47429 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_cache.c @@ -0,0 +1,87 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-16 14:00:59 + * @LastEditTime: 2021-04-16 16:07:27 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + + +#include "ft_cache.h" + +__STATIC_INLINE u32 FCache_cacheLineSize(void) +{ + u32 ctr; + asm volatile("mrc p15, 0, %0, c0, c0, 1" + : "=r"(ctr)); + return 4 << ((ctr >> 16) & 0xF); +} + +void FCache_cpuDcacheInvalidate(void *addr, ft_base_t size) +{ + u32 lineSize = FCache_cacheLineSize(); + u32 startAddr = (u32)addr; + u32 endAddr = (u32)addr + size + lineSize - 1; + + asm volatile("dmb" :: + : "memory"); + + startAddr &= ~(lineSize - 1); + endAddr &= ~(lineSize - 1); + + while (startAddr < endAddr) + { + asm volatile("mcr p15, 0, %0, c7, c6, 1" ::"r"(startAddr)); /* dcimvac */ + startAddr += lineSize; + } + + asm volatile("dsb" :: + : "memory"); +} + +void FCache_cpuDcacheClean(void *addr, ft_base_t size) +{ + u32 lineSize = FCache_cacheLineSize(); + u32 startAddr = (u32)addr; + u32 endAddr = (u32)addr + size + lineSize - 1; + + asm volatile("dmb" :: + : "memory"); + + startAddr &= ~(lineSize - 1); + endAddr &= ~(lineSize - 1); + + while (startAddr < endAddr) + { + asm volatile("mcr p15, 0, %0, c7, c10, 1" ::"r"(startAddr)); /* dccmvac */ + startAddr += lineSize; + } + + asm volatile("dsb" :: + : "memory"); +} + +void FCache_cpuIcacheInvalidate(void *addr, ft_base_t size) +{ + u32 lineSize = FCache_cacheLineSize(); + u32 startAddr = (u32)addr; + u32 endAddr = (u32)addr + size + lineSize - 1; + + asm volatile("dmb" :: + : "memory"); + startAddr &= ~(lineSize - 1); + endAddr &= ~(lineSize - 1); + while (startAddr < endAddr) + { + asm volatile("mcr p15, 0, %0, c7, c5, 1" ::"r"(startAddr)); /* icimvau */ + startAddr += lineSize; + } + asm volatile("dsb\n\tisb" :: + : "memory"); +} diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_cache.h b/bsp/ft2004/libraries/bsp/standlone/ft_cache.h new file mode 100644 index 0000000000000000000000000000000000000000..5132138636e8ea6633b42d318034051a303748f2 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_cache.h @@ -0,0 +1,56 @@ +/* + * @[H]: Copyright (C) 2014-2021 Phytium Technology.  All rights reserved. + * + *  Permission is hereby granted, free of charge, to any person obtaining a copy + *  of this software and associated documentation files (the "Software"), to deal + *  in the Software without restriction, including without limitation the rights + *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + *  copies of the Software, and to permit persons to whom the Software is + *  furnished to do so, subject to the following conditions: + * + *  The above copyright notice and this permission notice shall be included in + *  all copies or substantial portions of the Software. + * + *  Use of the Software is limited solely to applications: + *  (a) running on a Phytium device, or + *  (b) that interact with a Phytium device through a bus or interconnect. + * + *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + *  PHYTIUM  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + *  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + *  SOFTWARE. + * + *  Except as contained in this notice, the name of the Phytium shall not be used + *  in advertising or otherwise to promote the sale, use or other dealings in + *  this Software without prior written authorization from Phytium.  + * + * @Date: 2021-04-13 21:52:20 + * @LastEditTime: 2021-04-13 21:52:20 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + */ + +#ifndef FT_CACHE_H +#define FT_CACHE_H + +#include "ft_types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + void FCache_cpuDcacheInvalidate(void *addr, ft_base_t size); + void FCache_cpuDcacheClean(void *addr, ft_base_t size); + void FCache_cpuIcacheInvalidate(void *addr, ft_base_t size); + +#ifdef __cplusplus +} +#endif + +#endif // !FT_CACHE_H \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_cpu.c b/bsp/ft2004/libraries/bsp/standlone/ft_cpu.c new file mode 100644 index 0000000000000000000000000000000000000000..affa0c196a603bc8cfa3b3acfca2581c1d886c3b --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_cpu.c @@ -0,0 +1,170 @@ +/* + * @[H]: Copyright (C) 2014-2021 Phytium Technology.  All rights reserved. + * + *  Permission is hereby granted, free of charge, to any person obtaining a copy + *  of this software and associated documentation files (the "Software"), to deal + *  in the Software without restriction, including without limitation the rights + *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + *  copies of the Software, and to permit persons to whom the Software is + *  furnished to do so, subject to the following conditions: + * + *  The above copyright notice and this permission notice shall be included in + *  all copies or substantial portions of the Software. + * + *  Use of the Software is limited solely to applications: + *  (a) running on a Phytium device, or + *  (b) that interact with a Phytium device through a bus or interconnect. + * + *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + *  PHYTIUM  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + *  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + *  SOFTWARE. + * + *  Except as contained in this notice, the name of the Phytium shall not be used + *  in advertising or otherwise to promote the sale, use or other dealings in + *  this Software without prior written authorization from Phytium.  + * + * @Date: 2021-04-20 11:32:32 + * @LastEditTime: 2021-04-20 11:32:32 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + */ + +#include "ft_parameters.h" +#include "ft_cpu.h" +#include "ft_assert.h" +#include "ft_printf.h" + +#ifdef FT_SMP_EN + +typedef union +{ + u32 Slock; + struct ArchTicket + { + u16 owner; + u16 next; + } Tickets; +} FCpu_Lock_t; + +struct FCpu +{ + u32 IsReady; + FCpu_Lock_t Clock; +}; + +struct FCpu FCpu_Lock = {0}; + +const u32 SoftAffiTable[4] = {0, 1, 0x100, 0x101}; + +/** + * @name: FCpu_IdGet + * @msg: In a multiprocessor system, provides an additional PE identification mechanism for scheduling + purposes. + * @return {Aff0} Affinity level 0. The most significant affinity level field, for this PE in the system. + */ +s32 FCpu_IdGet(void) +{ + s32 cpu_id; + __asm__ volatile( + "mrc p15, 0, %0, c0, c0, 5" + : "=r"(cpu_id)); + // Ft_printf("error cpu_id %x \r\n", cpu_id); + // cpu_id &= 0xf; + + switch ((cpu_id & 0xfff)) + { + case 1: + return 1; + case 0x100: + return 2; + case 0x101: + return 3; + default: + return (cpu_id & 0xf); + } +} + +s32 FCpu_AffinityGet(void) +{ + s32 AffinityId; + __asm__ volatile( + "mrc p15, 0, %0, c0, c0, 5" + : "=r"(AffinityId)); + // Ft_printf("error cpu_id %x \r\n", cpu_id); + // cpu_id &= 0xf; + return AffinityId & 0xfff; +} + +void FCpu_SpinLockInit(void) +{ + FCpu_Lock.Clock.Slock = 0; + FCpu_Lock.IsReady = FT_COMPONENT_IS_READLY; +} + +void FCpu_SpinLock(void) +{ + u32 Tmp; + u32 Newval; + FCpu_Lock_t LockVal; + Ft_assertVoid(FCpu_Lock.IsReady == FT_COMPONENT_IS_READLY); + + __asm__ __volatile__( + "pld [%0]" ::"r"(&FCpu_Lock.Clock.Slock)); + + __asm__ __volatile__( + "1: ldrex %0, [%3]\n" + " add %1, %0, %4\n" + " strex %2, %1, [%3]\n" + " teq %2, #0\n" + " bne 1b" + : "=&r"(LockVal), "=&r"(Newval), "=&r"(Tmp) + : "r"(&FCpu_Lock.Clock.Slock), "I"(1 << 16) + : "cc"); + + while (LockVal.Tickets.next != LockVal.Tickets.owner) + { + __asm__ __volatile__("wfe" :: + : "memory"); + LockVal.Tickets.owner = *(volatile unsigned short *)(&FCpu_Lock.Clock.Tickets.owner); + } + + __asm__ volatile("dmb" :: + : "memory"); +} + +void FCpu_SpinUnlock(void) +{ + Ft_assertVoid(FCpu_Lock.IsReady == FT_COMPONENT_IS_READLY); + __asm__ volatile("dmb" :: + : "memory"); + FCpu_Lock.Clock.Tickets.owner++; + __asm__ volatile("dsb ishst\nsev" :: + : "memory"); +} + +#else /*RT_USING_SMP*/ + +s32 FCpu_IdGet(void) +{ + return 0; +} +void FCpu_SpinLockInit(void) +{ + return; +} +void FCpu_SpinLock(void) +{ + return; +} +void FCpu_SpinUnlock(void) +{ + return; +} + +#endif \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_cpu.h b/bsp/ft2004/libraries/bsp/standlone/ft_cpu.h new file mode 100644 index 0000000000000000000000000000000000000000..4dd32dbbbf542c5dad82a9ce253630bad3373d1d --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_cpu.h @@ -0,0 +1,50 @@ +/* + * @[H]: Copyright (C) 2014-2021 Phytium Technology.  All rights reserved. + * + *  Permission is hereby granted, free of charge, to any person obtaining a copy + *  of this software and associated documentation files (the "Software"), to deal + *  in the Software without restriction, including without limitation the rights + *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + *  copies of the Software, and to permit persons to whom the Software is + *  furnished to do so, subject to the following conditions: + * + *  The above copyright notice and this permission notice shall be included in + *  all copies or substantial portions of the Software. + * + *  Use of the Software is limited solely to applications: + *  (a) running on a Phytium device, or + *  (b) that interact with a Phytium device through a bus or interconnect. + * + *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + *  PHYTIUM  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + *  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + *  SOFTWARE. + * + *  Except as contained in this notice, the name of the Phytium shall not be used + *  in advertising or otherwise to promote the sale, use or other dealings in + *  this Software without prior written authorization from Phytium.  + * + * @Date: 2021-04-20 11:33:54 + * @LastEditTime: 2021-04-20 11:33:55 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + */ + +#ifndef FT_CPU_H +#define FT_CPU_H + +#include "ft_types.h" +#include "ft_error_code.h" +extern const u32 SoftAffiTable[4]; +s32 FCpu_IdGet(void); +void FCpu_SpinLockInit(void); +void FCpu_SpinLock(void); +void FCpu_SpinUnlock(void); +s32 FCpu_AffinityGet(void); + +#endif // !FT_SPIN_H diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_debug.c b/bsp/ft2004/libraries/bsp/standlone/ft_debug.c new file mode 100644 index 0000000000000000000000000000000000000000..fcfd9fcd73c0c289e7a17d42bb4e9d535f1a0ac3 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_debug.c @@ -0,0 +1,91 @@ +/* + * @[H]: Copyright (C) 2014-2021 Phytium Technology.  All rights reserved. + * + *  Permission is hereby granted, free of charge, to any person obtaining a copy + *  of this software and associated documentation files (the "Software"), to deal + *  in the Software without restriction, including without limitation the rights + *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + *  copies of the Software, and to permit persons to whom the Software is + *  furnished to do so, subject to the following conditions: + * + *  The above copyright notice and this permission notice shall be included in + *  all copies or substantial portions of the Software. + * + *  Use of the Software is limited solely to applications: + *  (a) running on a Phytium device, or + *  (b) that interact with a Phytium device through a bus or interconnect. + * + *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + *  PHYTIUM  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + *  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + *  SOFTWARE. + * + *  Except as contained in this notice, the name of the Phytium shall not be used + *  in advertising or otherwise to promote the sale, use or other dealings in + *  this Software without prior written authorization from Phytium.  + * + * @Date: 2021-04-25 16:44:23 + * @LastEditTime: 2021-04-25 16:44:23 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + */ +#include "ft_debug.h" + +#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ') +void Ft_DumpHexByte(const u8 *ptr, ft_base_t buflen) +{ + unsigned char *buf = (unsigned char *)ptr; + int i, j; + + for (i = 0; i < buflen; i += 16) + { + Ft_printf("0x%08X: ", ptr + i); + + for (j = 0; j < 16; j++) + if (i + j < buflen) + Ft_printf("%02X ", buf[i + j]); + else + Ft_printf(" "); + Ft_printf(" "); + + for (j = 0; j < 16; j++) + if (i + j < buflen) + Ft_printf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.'); + Ft_printf("\r\n"); + } +} + +void Ft_DumpHexWord(const u32 *ptr, ft_base_t buflen) +{ + u32 *buf = (u32 *)ptr; + int i, j; + buflen = buflen / 4; + for (i = 0; i < buflen; i += 4) + { + Ft_printf("0x%08X: ", ptr + i); + + for (j = 0; j < 4; j++) + { + if (i + j < buflen) + { + Ft_printf("%08X ", buf[i + j]); + } + else + { + Ft_printf(" "); + } + } + + Ft_printf(" "); + + for (j = 0; j < 16; j++) + if (i + j < buflen) + Ft_printf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.'); + Ft_printf("\r\n"); + } +} \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_debug.h b/bsp/ft2004/libraries/bsp/standlone/ft_debug.h new file mode 100644 index 0000000000000000000000000000000000000000..6ea77713f1d9c14ed72251fe1a4b80343b3f19aa --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_debug.h @@ -0,0 +1,78 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-25 17:19:03 + * @Description:  This files is for debug functions + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef FT_DEBUG_H +#define FT_DEBUG_H + +#include "ft_printf.h" + +typedef enum +{ + FT_LOG_NONE, /*!< No log output */ + FT_LOG_ERROR, /*!< Critical errors, software module can not recover on its own */ + FT_LOG_WARN, /*!< Error conditions from which recovery measures have been taken */ + FT_LOG_INFO, /*!< Information messages which describe normal flow of events */ + FT_LOG_DEBUG, /*!< Extra information which is not necessary for normal use (values, pointers, sizes, etc). */ + FT_LOG_VERBOSE /*!< Bigger chunks of debugging information, or frequent messages which can potentially flood the output. */ +} ft_log_level_t; + +#define LOG_COLOR_BLACK "30" +#define LOG_COLOR_RED "31" +#define LOG_COLOR_GREEN "32" +#define LOG_COLOR_BROWN "33" +#define LOG_COLOR_BLUE "34" +#define LOG_COLOR_PURPLE "35" +#define LOG_COLOR_CYAN "36" +#define LOG_COLOR(COLOR) "\033[0;" COLOR "m" +#define LOG_BOLD(COLOR) "\033[1;" COLOR "m" +#define LOG_RESET_COLOR "\033[0m" +#define LOG_COLOR_E LOG_COLOR(LOG_COLOR_RED) +#define LOG_COLOR_W LOG_COLOR(LOG_COLOR_BROWN) +#define LOG_COLOR_I LOG_COLOR(LOG_COLOR_GREEN) +#define LOG_COLOR_D +#define LOG_COLOR_V + +#ifndef LOG_LOCAL_LEVEL +#define LOG_LOCAL_LEVEL FT_LOG_VERBOSE +#endif + +#define LOG_FORMAT(letter, format) LOG_COLOR_##letter " %s: " format LOG_RESET_COLOR "\r\n" + +#define PORT_KPRINTF Ft_printf + +#define LOG_EARLY_IMPL(tag, format, log_level, log_tag_letter, ...) \ + do \ + { \ + if (LOG_LOCAL_LEVEL < log_level) \ + break; \ + PORT_KPRINTF(LOG_FORMAT(log_tag_letter, format), tag, ##__VA_ARGS__); \ + } while (0) + +#define EARLY_LOGE(tag, format, ...) LOG_EARLY_IMPL(tag, format, FT_LOG_ERROR, E, ##__VA_ARGS__) +#define EARLY_LOGI(tag, format, ...) LOG_EARLY_IMPL(tag, format, FT_LOG_INFO, I, ##__VA_ARGS__) +#define EARLY_LOGD(tag, format, ...) LOG_EARLY_IMPL(tag, format, FT_LOG_DEBUG, D, ##__VA_ARGS__) +#define EARLY_LOGW(tag, format, ...) LOG_EARLY_IMPL(tag, format, FT_LOG_WARN, W, ##__VA_ARGS__) +#define EARLY_LOGV(tag, format, ...) LOG_EARLY_IMPL(tag, format, FT_LOG_VERBOSE, W, ##__VA_ARGS__) + +#define FT_DEBUG_PRINT_I(TAG, format, ...) EARLY_LOGI(TAG, format, ##__VA_ARGS__) +#define FT_DEBUG_PRINT_E(TAG, format, ...) EARLY_LOGE(TAG, format, ##__VA_ARGS__) +#define FT_DEBUG_PRINT_D(TAG, format, ...) EARLY_LOGD(TAG, format, ##__VA_ARGS__) +#define FT_DEBUG_PRINT_W(TAG, format, ...) EARLY_LOGW(TAG, format, ##__VA_ARGS__) +#define FT_DEBUG_PRINT_V(TAG, format, ...) EARLY_LOGV(TAG, format, ##__VA_ARGS__) + +#define FT_RAW_PRINTF(format, ...) PORT_KPRINTF(format, ##__VA_ARGS__) + +void Ft_DumpHexWord(const u32 *ptr, ft_base_t buflen); +void Ft_DumpHexByte(const u8 *ptr, ft_base_t buflen); +#endif // ! \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_error_code.h b/bsp/ft2004/libraries/bsp/standlone/ft_error_code.h new file mode 100644 index 0000000000000000000000000000000000000000..4ac36067353149ef61ba768d3b1d362c3cdf9fe8 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_error_code.h @@ -0,0 +1,72 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:30 + * @LastEditTime: 2021-04-25 17:07:09 + * @Description:  This files is for error code functions + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef _FT_ERROR_CODE_H +#define _FT_ERROR_CODE_H + +#include "ft_status.h" +#include "ft_types.h" + +typedef ft_base_t ft_error_t; + +/* 系统错误码模块定义 */ +typedef enum _ft_errcode_module_mask +{ + errModGeneral = 0, + errModBsp, + errModeUart, + errModeI2c, + errModeGmac, + errModeSdCtrl, + errCan, + errGicV3, + errQspi, + ERR_MODE_SD_MMC, + ERR_MODE_SPI, + + errModMaxMask = 255, +} ft_errcode_module_mask_t; + +/* BSP模块的错误子模块定义 */ +typedef enum _ft_errcode_bsp_mask +{ + errBspGeneral = 0, + errBspClk, + errBspRtc, + errPort, + errBspModMaxMask = 255 +} ft_errcode_bsp_mask_t; + +#define FT_ERRCODE_SYS_MODULE_OFFSET 24 +#define FT_ERRCODE_SUB_MODULE_OFFSET 16 + +#define FT_ERRCODE_SYS_MODULE_MASK (0xff << FT_ERRCODE_SYS_MODULE_OFFSET) /* bit 24 .. 31 */ +#define FT_ERRCODE_SUB_MODULE_MASK (0xff << FT_ERRCODE_SUB_MODULE_OFFSET) /* bit 16 .. 23 */ +#define FT_ERRCODE_TAIL_VALUE_MASK (0xffff) /* bit 1 .. 15 */ + +/* Offset error code */ +#define FT_ERRCODE_OFFSET(code, offset, mask) \ + (((code) << offset) & mask) + +/* Assembly error code */ +#define FT_MAKE_ERRCODE(sys_mode, sub_mode, tail) \ + ((FT_ERRCODE_OFFSET(sys_mode, FT_ERRCODE_SYS_MODULE_OFFSET, FT_ERRCODE_SYS_MODULE_MASK)) | \ + (FT_ERRCODE_OFFSET(sub_mode, FT_ERRCODE_SUB_MODULE_OFFSET, FT_ERRCODE_SUB_MODULE_MASK)) | \ + (tail & FT_ERRCODE_TAIL_VALUE_MASK)) +#define FT_CODE_ERR FT_MAKE_ERRCODE + +#define ERR_SUCCESS FT_MAKE_ERRCODE(errModGeneral, errBspGeneral, FST_SUCCESS) /* 成功 */ +#define ERR_GENERAL FT_MAKE_ERRCODE(errModGeneral, errBspGeneral, FST_FAILURE) /* 一般错误 */ + +#endif diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_generic_timer.c b/bsp/ft2004/libraries/bsp/standlone/ft_generic_timer.c new file mode 100644 index 0000000000000000000000000000000000000000..4116f1c69496830118bb0ae96a878e5324a6ee5d --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_generic_timer.c @@ -0,0 +1,328 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-26 11:25:56 + * @Description:  This files is for generic timer functions + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_status.h" +#include "ft_types.h" +#include "ft_generic_timer.h" +#include "ft_printf.h" +#include "ft_assert.h" +#include "ft_aarch32_asm.h" +#include "ft_cpu.h" + +#define GENERICTIMER_ASM(x) __asm__ volatile(x) +#define USEVIRTUAL 0 +#define USE_ISRNUM GEN_TIMER_PHYSICAL_NOSECURE_IRQN + +static volatile u32 _TickCnt; +static volatile u32 _Tickms; + +typedef struct ft_Generictimer +{ + u64 Frequency; + u64 MaxCount; + u64 TicksPerUs; + u32 Isr_PeriodMsec; + u32 Isr_PeriodCnt; //member))) + +#endif // ! FT_LIST_H diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_math.c b/bsp/ft2004/libraries/bsp/standlone/ft_math.c new file mode 100644 index 0000000000000000000000000000000000000000..0195649874feda427b4912fd9ab5232cdb5f58fb --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_math.c @@ -0,0 +1,43 @@ +/* + * @[H]: Copyright (C) 2014-2021 Phytium Technology.  All rights reserved. + * + *  Permission is hereby granted, free of charge, to any person obtaining a copy + *  of this software and associated documentation files (the "Software"), to deal + *  in the Software without restriction, including without limitation the rights + *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + *  copies of the Software, and to permit persons to whom the Software is + *  furnished to do so, subject to the following conditions: + * + *  The above copyright notice and this permission notice shall be included in + *  all copies or substantial portions of the Software. + * + *  Use of the Software is limited solely to applications: + *  (a) running on a Phytium device, or + *  (b) that interact with a Phytium device through a bus or interconnect. + * + *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + *  PHYTIUM  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + *  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + *  SOFTWARE. + * + *  Except as contained in this notice, the name of the Phytium shall not be used + *  in advertising or otherwise to promote the sale, use or other dealings in + *  this Software without prior written authorization from Phytium.  + * + * @Date: 2021-04-28 22:15:48 + * @LastEditTime: 2021-04-28 22:15:48 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + */ + +#include "ft_math.h" + +u32 Ft_Abs(s32 num) +{ + return (num >= 0 ? num : -num); +} diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_math.h b/bsp/ft2004/libraries/bsp/standlone/ft_math.h new file mode 100644 index 0000000000000000000000000000000000000000..792d9a073cb7aa24c57674c7bda16b37b428991d --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_math.h @@ -0,0 +1,48 @@ +/* + * @[H]: Copyright (C) 2014-2021 Phytium Technology.  All rights reserved. + * + *  Permission is hereby granted, free of charge, to any person obtaining a copy + *  of this software and associated documentation files (the "Software"), to deal + *  in the Software without restriction, including without limitation the rights + *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + *  copies of the Software, and to permit persons to whom the Software is + *  furnished to do so, subject to the following conditions: + * + *  The above copyright notice and this permission notice shall be included in + *  all copies or substantial portions of the Software. + * + *  Use of the Software is limited solely to applications: + *  (a) running on a Phytium device, or + *  (b) that interact with a Phytium device through a bus or interconnect. + * + *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + *  PHYTIUM  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + *  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + *  SOFTWARE. + * + *  Except as contained in this notice, the name of the Phytium shall not be used + *  in advertising or otherwise to promote the sale, use or other dealings in + *  this Software without prior written authorization from Phytium.  + * + * @Date: 2021-04-28 22:15:19 + * @LastEditTime: 2021-04-28 22:15:19 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + */ + +#ifndef FT_MATH_H +#define FT_MATH_H + +#include "ft_types.h" + +#define FT_INT_MAX 2147483647 +#define FT_UINT_MAX (FT_INT_MAX * 2U + 1) + +u32 Ft_Abs(s32 num); + +#endif // !FT_MATH_H \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_mux.c b/bsp/ft2004/libraries/bsp/standlone/ft_mux.c new file mode 100644 index 0000000000000000000000000000000000000000..07a4e10d2f3d42bbf3f23ea293cf33316596fb2d --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_mux.c @@ -0,0 +1,96 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-27 17:28:42 + * @Description:  This files is for pin mux + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + + +#include "ft_mux.h" +#include "ft_io.h" +#include "ft_assert.h" +#include "ft_printf.h" + +/** + * Description: enable i2c 1 ~ 3 pin pad mux + * Date: 2021-03-24 13:34:06 + * Param: + * return {*} + * param {FT_IN u32} I2cId, i2c 0 ~ 3 + */ +void Ft_setI2cMux(FT_IN u32 I2cId) +{ + u32 RegValue; + + switch (I2cId) + { + case I2C0_ID: + /* i2c0 is by default enabled */ + break; + case I2C1_ID: + /* select i2c1 SCL, SDA mux */ + RegValue = Ft_in32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG200_OFFSET); + RegValue |= (I2C1_SCL_PIN_REG200_BIT | I2C1_SDA_PIN_REG200_BIT); + Ft_out32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG200_OFFSET, RegValue); + break; + case I2C2_ID: + Ft_assertNoneReturn(0); + break; + case I2C3_ID: + Ft_assertNoneReturn(0); + break; + default: + Ft_assertNoneReturn(0); + break; + } + + return; +} + +void Ft_setSpiMux(FT_IN u32 SpiId) +{ + u32 RegValue; + + switch (SpiId) + { + case SPI0_ID: + /* spi0 is by default enabled */ + RegValue = Ft_in32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG208_OFFSET); + /* clear specific bits to choose Func 0 */ + RegValue |= SPI1_PORTA5_PIN_REG208_BIT; + Ft_out32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG208_OFFSET, RegValue); + Ft_printf("bef reg 208 0x%x\r\n", Ft_in32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG208_OFFSET)); + + // RegValue &= SPI0_CSN0_PIN_REG208_BIT; + // RegValue &= SPI0_SCK_PIN_REG208_BIT; + // RegValue &= SPI0_SO_PIN_REG208_BIT; + // RegValue &= SPI0_SI_PIN_REG208_BIT; + // Ft_out32(FT_PIN_DEMUX_BASE + SPI0_SI_PIN_REG208_BIT, RegValue); + break; + case SPI1_ID: + /* select spi cs, sck, so, si pin mux */ + Ft_printf("bef reg 210 0x%x\r\n", Ft_in32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG210_OFFSET)); + RegValue = Ft_in32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG210_OFFSET); + RegValue |= SPI1_CSN0_PIN_REG210_BIT; + Ft_out32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG210_OFFSET, RegValue); + Ft_printf("aft reg 210 0x%x\r\n", Ft_in32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG210_OFFSET)); + + Ft_printf("bef reg 214 0x%x\r\n", Ft_in32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG214_OFFSET)); + RegValue = Ft_in32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG214_OFFSET); + RegValue |= SPI1_SCK_PIN_REG214_BIT | SPI1_SO_PIN_REG214_BIT | SPI1_SI_PIN_REG214_BIT; + Ft_out32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG214_OFFSET, RegValue); + Ft_printf("aft reg 214 0x%x\r\n", Ft_in32(FT_PIN_DEMUX_BASE + FT_PIN_DEMUX_REG214_OFFSET)); + break; + default: + break; + } + + return; +} \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_mux.h b/bsp/ft2004/libraries/bsp/standlone/ft_mux.h new file mode 100644 index 0000000000000000000000000000000000000000..7d820b1b98b4a60262d419cfe67d51349bca49be --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_mux.h @@ -0,0 +1,87 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-27 17:27:41 + * @Description:  This files is for pin mux + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + + +#ifndef FT_BSP_MUX_H +#define FT_BSP_MUX_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ft_types.h" + +/* pad pin multi-function demu */ +#define FT_PIN_DEMUX_BASE 0x28180000 +#define FT_PIN_DEMUX_REG200_OFFSET 0x200 +#define FT_PIN_DEMUX_REG204_OFFSET 0x204 +#define FT_PIN_DEMUX_REG208_OFFSET 0x208 +#define FT_PIN_DEMUX_REG210_OFFSET 0x210 +#define FT_PIN_DEMUX_REG214_OFFSET 0x214 + +/* i2c mux function option */ +#define I2C1_SCL_PIN_REG200_MASK ((u32)0x3 << 28) /* all_pll_lock_pad [29:28] */ +#define I2C1_SCL_PIN_REG200_BIT ((u32)0x2 << 28) +#define I2C1_SDA_PIN_REG200_MASK ((u32)0x3 << 24) /* cru_clk_obv_pad [25:24] */ +#define I2C1_SDA_PIN_REG200_BIT ((u32)0x2 << 24) +#define I2C2_SCL_PIN_REG204_MASK ((u32)0x3 << 8) /* swdo_swj_pad [9: 8] */ +#define I2C2_SCL_PIN_REG204_BIT ((u32)0x2 << 8) +#define I2C2_SDA_PIN_REG204_MASK ((u32)0x3 << 6) /* tdo_swj_pad [7: 6] */ +#define I2C2_SDA_PIN_REG204_BIT ((u32)0x2 << 6) +#define I2C3_SCL_PIN_REG204_MASK ((u32)0x3 << 0) /* hdt_mb_done_state_pad [1 : 0] */ +#define I2C3_SCL_PIN_REG204_BIT ((u32)0x2 << 0) +#define I2C3_SDA_PIN_REG208_MASK ((u32)0x3 << 30) /* hdt_mb_fail_state_pad [31 : 30] */ +#define I2C3_SDA_PIN_REG208_BIT ((u32)0x2 << 30) + +//#define SPI0_CSN0_PIN_REG208_BIT ((u32)~(0x3 << 16)) +#define SPI1_PORTA5_PIN_REG208_BIT ((u32)0x1 << 16) +// #define SPI0_SCK_PIN_REG208_BIT ((u32)~(0x3 << 12)) +// #define SPI0_SO_PIN_REG208_BIT ((u32)~(0x3 << 8)) +// #define SPI0_SI_PIN_REG208_BIT ((u32)~(0x3 << 4)) + +#define SPI1_CSN0_PIN_REG210_MASK ((u32)0x3 << 0) /* uart_2_rxd_pad [1 : 0] */ +#define SPI1_CSN0_PIN_REG210_BIT ((u32)0x1 << 0) +#define SPI1_SCK_PIN_REG214_MASK ((u32)0x3 << 28) /* uart_2_txd_pad [29 : 28] */ +#define SPI1_SCK_PIN_REG214_BIT ((u32)0x1 << 28) +#define SPI1_SO_PIN_REG214_MASK ((u32)0x3 << 24) /* uart_3_rxd_pad [25 : 24] */ +#define SPI1_SO_PIN_REG214_BIT ((u32)0x1 << 24) +#define SPI1_SI_PIN_REG214_MASK ((u32)0x3 << 20) /* uart_3_txd_pad [21 : 20] */ +#define SPI1_SI_PIN_REG214_BIT ((u32)0x1 << 20) + +/* i2c ctrl instance */ +#define I2C0_ID 0 +#define I2C1_ID 1 +#define I2C2_ID 2 +#define I2C3_ID 3 + +/* spi ctrl instance */ +#define SPI0_ID 0 +#define SPI1_ID 1 + +/** + * Description: enable mux of certain i2c bus + * Date: 2021-03-30 13:58:45 + * Param: + * return {*} + * param {FT_IN u32} I2cId + */ +void Ft_setI2cMux(FT_IN u32 I2cId); +void Ft_setSpiMux(FT_IN u32 SpiId); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_printf.c b/bsp/ft2004/libraries/bsp/standlone/ft_printf.c new file mode 100644 index 0000000000000000000000000000000000000000..0b3de4bdf51e0516699674445b76e8a6f29cf3fc --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_printf.c @@ -0,0 +1,97 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-07 15:29:54 + * @Description:  This files is for printf function + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + + +#include "ft_printf.h" +#include "stdio.h" +#include "ft_aarch32_asm.h" + +static char print_buffer[PRINTF_BUFFER_LENGTH]; + +extern void outbyte(char byte); + +vsprintf_p Vsprintf_pFun = (vsprintf_p)vsprintf; + +void Ft_vsprintfRegister(vsprintf_p f) +{ + Vsprintf_pFun = f; +} + +void Ft_printf(const char *fmt, ...) +{ + va_list args; + size_t i; + size_t length; +#ifdef NEED_CLOSE_ISR + IRQ_DISABLE(); +#endif + va_start(args, fmt); + + length = Vsprintf_pFun(print_buffer, fmt, args); + va_end(args); + for (i = 0; i < length; i++) + { + outbyte(print_buffer[i]); + } + +#ifdef NEED_CLOSE_ISR + IRQ_ENABLE(); +#endif +} + +char *Ft_itoa(int num, char *str, int radix) +{ + char index[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + unsigned unum; + int i = 0; + int j; + int k; + char temp; + + if (radix == 10 && num < 0) + { + unum = (unsigned)-num; + str[i++] = '-'; + } + else + { + unum = (unsigned)num; + } + + do + { + str[i++] = index[unum % (unsigned)radix]; + unum /= radix; + } while (unum); + + str[i] = '\0'; + + if (str[0] == '-') + { + k = 1; + } + else + { + k = 0; + } + + for (j = k; j <= (i - 1) / 2; j++) + { + temp = str[j]; + str[j] = str[i - 1 + k - j]; + str[i - 1 + k - j] = temp; + } + + return str; +} \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_printf.h b/bsp/ft2004/libraries/bsp/standlone/ft_printf.h new file mode 100644 index 0000000000000000000000000000000000000000..96d3a45fd706ca25c20457f9c300f718e907bec2 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_printf.h @@ -0,0 +1,31 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-07 15:30:52 + * @Description:  This files is for printf functions + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + + +#ifndef Ft_printf_H +#define Ft_printf_H + +#include +#include "ft_types.h" + +// #define NEED_CLOSE_ISR +#define PRINTF_BUFFER_LENGTH 4096 + +typedef s32 (*vsprintf_p)(char *buf, const char *format, va_list arg_ptr); + +void Ft_vsprintfRegister(vsprintf_p f); +void Ft_printf(const char *fmt, ...); +char *Ft_itoa(int num, char *str, int radix); + +#endif // ! \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_psci.c b/bsp/ft2004/libraries/bsp/standlone/ft_psci.c new file mode 100644 index 0000000000000000000000000000000000000000..003385fc6ec65d92ce763f0d0056313079c3eb2b --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_psci.c @@ -0,0 +1,102 @@ +/* + * @[H]: Copyright (C) 2014-2021 Phytium Technology.  All rights reserved. + * + *  Permission is hereby granted, free of charge, to any person obtaining a copy + *  of this software and associated documentation files (the "Software"), to deal + *  in the Software without restriction, including without limitation the rights + *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + *  copies of the Software, and to permit persons to whom the Software is + *  furnished to do so, subject to the following conditions: + * + *  The above copyright notice and this permission notice shall be included in + *  all copies or substantial portions of the Software. + * + *  Use of the Software is limited solely to applications: + *  (a) running on a Phytium device, or + *  (b) that interact with a Phytium device through a bus or interconnect. + * + *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + *  PHYTIUM  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + *  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + *  SOFTWARE. + * + *  Except as contained in this notice, the name of the Phytium shall not be used + *  in advertising or otherwise to promote the sale, use or other dealings in + *  this Software without prior written authorization from Phytium.  + * + * @Date: 2021-04-21 10:43:52 + * @LastEditTime: 2021-04-21 10:43:53 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + */ + +#include "ft_psci.h" +#include "ft_smc.h" +#include "ft_cpu.h" +#include "ft_printf.h" + +#define PSCI_CPUON_NUM 0x84000003 +#define PSCI_RESET_NUM 0x84000009 + +/** + * @name: FPsci_CpuOn + * @msg: Power up a core + * @in param CpuList: Bits[24:31]: Must be zero. + * Bits[16:23] Aff2: Match Aff2 of target core MPIDR + * Bits[8:15] Aff1: Match Aff1 of target core MPIDR + * Bits[0:7] Aff0: Match Aff0 of target core MPIDR + * @in param BootAddr: a 32-bit entry point physical address (or IPA). + * @return {None} + */ +void FPsci_CpuOn(s32 CpuIdMask, u32 BootAddr) +{ + + FSmc_Data_t Input = {0}; + FSmc_Data_t Output = {0}; + Input.FunctionIdentifier = PSCI_CPUON_NUM; + + if ((1 << 0) == CpuIdMask) + { + Input.a1 = SoftAffiTable[0]; + } + else if ((1 << 1) == CpuIdMask) + { + Input.a1 = SoftAffiTable[1]; + } + else if ((1 << 2) == CpuIdMask) + { + Input.a1 = SoftAffiTable[2]; + } + else if ((1 << 3) == CpuIdMask) + { + Input.a1 = SoftAffiTable[3]; + } + else + { + return; + } + + /*input.a2 = (u32)(BootAddr >> 32);*/ + Input.a2 = (u32)(BootAddr & 0xFFFFFFFF); + FSmc_Call(&Input, &Output); + __asm__ volatile("NOP"); +} + +void FPsci_Reset(void) +{ + + FSmc_Data_t Input = {0}; + FSmc_Data_t Output = {0}; + + Input.FunctionIdentifier = PSCI_RESET_NUM; + FSmc_Call(&Input, &Output); + + __asm__ volatile("NOP"); + while (1) + ; +} diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_psci.h b/bsp/ft2004/libraries/bsp/standlone/ft_psci.h new file mode 100644 index 0000000000000000000000000000000000000000..ebb8ccbff2b35724a2472cf60fcc8bf0302baeaa --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_psci.h @@ -0,0 +1,55 @@ +/* + * @[H]: Copyright (C) 2014-2021 Phytium Technology.  All rights reserved. + * + *  Permission is hereby granted, free of charge, to any person obtaining a copy + *  of this software and associated documentation files (the "Software"), to deal + *  in the Software without restriction, including without limitation the rights + *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + *  copies of the Software, and to permit persons to whom the Software is + *  furnished to do so, subject to the following conditions: + * + *  The above copyright notice and this permission notice shall be included in + *  all copies or substantial portions of the Software. + * + *  Use of the Software is limited solely to applications: + *  (a) running on a Phytium device, or + *  (b) that interact with a Phytium device through a bus or interconnect. + * + *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + *  PHYTIUM  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + *  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + *  SOFTWARE. + * + *  Except as contained in this notice, the name of the Phytium shall not be used + *  in advertising or otherwise to promote the sale, use or other dealings in + *  this Software without prior written authorization from Phytium.  + * + * @Date: 2021-04-21 10:43:59 + * @LastEditTime: 2021-04-21 10:44:00 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + */ + +#ifndef FT_PSCI_H +#define FT_PSCI_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ft_types.h" + + void FPsci_CpuOn(s32 CpuIdMask, u32 BootAddr); + void FPsci_Reset(void); + +#ifdef __cplusplus +} +#endif + +#endif // ! \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_smc.S b/bsp/ft2004/libraries/bsp/standlone/ft_smc.S new file mode 100644 index 0000000000000000000000000000000000000000..c610350eb5243a227efef6e6fe8aa2861b662426 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_smc.S @@ -0,0 +1,36 @@ + + +/******************************************************************************* +* +* FSmc_Call - initiate SMC call +* +* This routine initiates SMC call which traps the processor into Monitor Mode. +* The ARM SMC Call Convetion defines that up to eight registers can be exchanged +* during an SMC call. The input parameter contains eight INT32 valeus which are +* to be passed in the SMC call; similarily the output parameter also contains +* eight INT32 values which are returned from the SMC call. +* +* \NOMANUAL +* +* RETURNS: OK +* +* void FSmc_Call +* ( +* FSmc_Data_t * input, /@ r0 - input register values @/ +* FSmc_Data_t * output /@ r1 - output register values @/ +* ) +*/ + +.arm +.align 4 +.globl FSmc_Call +FSmc_Call: + STMDB sp!, {r0-r7} /* save clobbered registers to stack */ + ldr r12, [sp, #(4 * 0)] /* get 1st argument (ptr to input struct) */ + ldmia r12, {r0-r7} /* save input argument to r0-r7 */ + smc #0 + ldr r12, [sp, #(4 * 1)] /* get 2th argument (ptr to output result) */ + stmia r12, {r0-r7} /* get output argument from r0-r7 */ + ldmfd sp!, {r0-r7} /* restore clobbered registers from stack */ + bx lr +.size FSmc_Call, .- FSmc_Call diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_smc.h b/bsp/ft2004/libraries/bsp/standlone/ft_smc.h new file mode 100644 index 0000000000000000000000000000000000000000..aa83d5124ab07b19b98cc5abed3b38a2b587adf7 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_smc.h @@ -0,0 +1,67 @@ +/* + * @[H]: Copyright (C) 2014-2021 Phytium Technology.  All rights reserved. + * + *  Permission is hereby granted, free of charge, to any person obtaining a copy + *  of this software and associated documentation files (the "Software"), to deal + *  in the Software without restriction, including without limitation the rights + *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + *  copies of the Software, and to permit persons to whom the Software is + *  furnished to do so, subject to the following conditions: + * + *  The above copyright notice and this permission notice shall be included in + *  all copies or substantial portions of the Software. + * + *  Use of the Software is limited solely to applications: + *  (a) running on a Phytium device, or + *  (b) that interact with a Phytium device through a bus or interconnect. + * + *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + *  PHYTIUM  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + *  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + *  SOFTWARE. + * + *  Except as contained in this notice, the name of the Phytium shall not be used + *  in advertising or otherwise to promote the sale, use or other dealings in + *  this Software without prior written authorization from Phytium.  + * + * @Date: 2021-04-21 11:53:38 + * @LastEditTime: 2021-04-21 11:53:38 + * @Description:  Description of file + * @Modify History: + * * * Ver   Who        Date         Changes + * * ----- ------     --------    -------------------------------------- + */ + +#ifndef FT_SMC_H +#define FT_SMC_H + +#include "ft_types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + typedef struct + { + /* data */ + u32 FunctionIdentifier; + u32 a1; + u32 a2; + u32 a3; + u32 a4; + u32 a5; + u32 a6; + + } FSmc_Data_t; + + void FSmc_Call(FSmc_Data_t *Input, FSmc_Data_t *Output); + +#ifdef __cplusplus +} +#endif + +#endif // !FT_SMC_H \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_status.h b/bsp/ft2004/libraries/bsp/standlone/ft_status.h new file mode 100644 index 0000000000000000000000000000000000000000..c56c6a03db7e5906e33f2968707f589b4c8418bb --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_status.h @@ -0,0 +1,82 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-07 15:31:10 + * @Description:  This files is for definition of status + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef FT_STATUS_H +#define FT_STATUS_H + +/** +@name Common Status Codes +*/ + +typedef enum +{ + FST_SUCCESS = 0L, + FST_FAILURE = 1L, + FST_INSTANCE_NOT_FOUND = 2L, + FST_DEVICE_BLOCK_NOT_FOUND = 3L, + FST_INVALID_VERSION = 4L, + FST_DEVICE_IS_STARTED = 5L, + FST_DEVICE_IS_STOPPED = 6L, + FST_FIFO_ERROR = 7L, /* An error occurred during an \ + operation with a FIFO such as \ + an underrun or overrun, this \ + error requires the device to \ + be reset */ + FST_RESET_ERROR = 8L, /* An error occurred which requires \ + the device to be reset */ + FST_DMA_ERROR = 9L, /* A DMA error occurred, this error \ + typically requires the device \ + using the DMA to be reset */ + FST_NOT_POLLED = 10L, /* The device is not configured for \ + polled mode operation */ + FST_FIFO_NO_ROOM = 11L, /* A FIFO did not have room to put \ + the specified data into */ + FST_BUFFER_TOO_SMALL = 12L, /* The buffer is not large enough \ + to hold the expected data */ + FST_NO_DATA = 13L, /* There was no data available */ + FST_REGISTER_ERROR = 14L, /* A register did not contain the \ + expected value */ + FST_INVALID_PARAM = 15L, /* An invalid parameter was passed \ + into the function */ + FST_NOT_SGDMA = 16L, /* The device is not configured for \ + scatter-gather DMA operation */ + FST_LOOPBACK_ERROR = 17L, /* A loopback test failed */ + FST_NO_CALLBACK = 18L, /* A callback has not yet been \ + registered */ + FST_NO_FEATURE = 19L, /* Device is not configured with \ + the requested feature */ + FST_NOT_INTERRUPT = 20L, /* Device is not configured for \ + interrupt mode operation */ + FST_DEVICE_BUSY = 21L, /* Device is busy */ + FST_ERROR_COUNT_MAX = 22L, /* The error counters of a device \ + have maxed out */ + FST_IS_STARTED = 23L, /* Used when part of device is \ + already started i.e. \ + sub channel */ + FST_IS_STOPPED = 24L, /* Used when part of device is \ + already stopped i.e. \ + sub channel */ + FST_DATA_LOST = 26L, /* Driver defined error */ + FST_RECV_ERROR = 27L, /* Generic receive error */ + FST_SEND_ERROR = 28L, /* Generic transmit error */ + FST_NOT_ENABLED = 29L, /* A requested service is not \ + available because it has not \ + been enabled */ + FST_ASSERT_RETURN = 30L, /* Assert occurs defined error */ + FST_TIMEOUT = 31L, + FST_EILSEQ = 32L, /* Illegal byte sequence. */ + FST_STATUS_MAX_VALUE = 0xffff /* Status max value */ +} Common_status; + +#endif // !FT_STATUS_H \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_trace.c b/bsp/ft2004/libraries/bsp/standlone/ft_trace.c new file mode 100644 index 0000000000000000000000000000000000000000..365fc32db0cd56d90912c602975539429f8f7576 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_trace.c @@ -0,0 +1,68 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-15 11:27:24 + * @LastEditTime: 2021-04-26 17:24:53 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +//#include "FreeRTOS.h" +//#include "task.h" +#include "ft_trace.h" +#include "ft_printf.h" + +// typedef struct MEMBLOCK_LINK +// { +// struct MEMBLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the list. */ +// size_t xBlockSize; /*<< The size of the free block. */ +// } MEMBlockLink_t; +void Sdmmc_TraceHeapAlloc(const char *tag) +{ +// #ifdef FT_MEM_TRACE_ENABLED +// MEMBlockLink_t *pNextBlk = pvHeapAllocAddr(); +// FT_MEM_TRACE("<%s> next blk to alloc 0x%p, next next blk to alloc 0x%p", +// tag, +// pNextBlk, +// pNextBlk->pxNextFreeBlock); +// #endif +} + +void dump_hex(const u8 *ptr, u32 buflen, const char *tag) +{ + unsigned char *buf = (unsigned char *)ptr; + u32 i, j; + + Ft_printf("dump hex for %s\r\n", tag); + for (i = 0; i < buflen; i += 16) + { + Ft_printf("%08X: ", ptr + i); + + for (j = 0; j < 16; j++) + { + if (i + j < buflen) + { + Ft_printf("%02X ", buf[i + j]); + } + else + { + Ft_printf(" "); + } + } + Ft_printf(" "); + + for (j = 0; j < 16; j++) + { + if (i + j < buflen) + { + Ft_printf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.'); + } + } + Ft_printf("\r\n"); + } +} diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_trace.h b/bsp/ft2004/libraries/bsp/standlone/ft_trace.h new file mode 100644 index 0000000000000000000000000000000000000000..e562d3801ba2bd2855d03eb41543b202edc117bb --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_trace.h @@ -0,0 +1,53 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-15 11:27:14 + * @LastEditTime: 2021-04-16 13:40:55 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef _FT_TRACE_H_ +#define _FT_TRACE_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ft_debug.h" + +/* define debug log function */ +#define FT_MEM_TRACE_ENABLED +#define FT_MEM_TRACE_TAG "FT_MEM" +#ifdef FT_MEM_TRACE_ENABLED +#define FT_MEM_TRACE(format, ...) FT_DEBUG_PRINT_I(FT_MEM_TRACE_TAG, format, ##__VA_ARGS__) +#else +#define FT_MEM_TRACE(format, ...) +#endif + +#define FT_LOGIC_TRACE_ENABLED +#define FT_LOGIC_TRACE_TAG "FT_LOGIC" +#ifdef FT_LOGIC_TRACE_ENABLED +#define FT_LOGIC_TRACE(format, ...) FT_DEBUG_PRINT_I(FT_LOGIC_TRACE_TAG, format, ##__VA_ARGS__) +#define FT_MEM_TRACE_DUMP(buf, buflen, tag) dump_hex((buf), (buflen), (tag)) +#else +#define FT_LOGIC_TRACE(format, ...) +#define FT_MEM_TRACE_DUMP(buf, buflen, tag) +#endif + +#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ') +void dump_hex(const u8 *ptr, u32 buflen, const char *tag); +void Sdmmc_TraceHeapAlloc(const char *tag); + + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/standlone/ft_types.h b/bsp/ft2004/libraries/bsp/standlone/ft_types.h new file mode 100644 index 0000000000000000000000000000000000000000..bd5a699b8731bea37756d93cfb9e307a0a3ffdbf --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/ft_types.h @@ -0,0 +1,75 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-05-11 10:18:14 + * @Description:  This files is for definition of system-level types + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef FT_TYPES_H +#define FT_TYPES_H +#include +#include + +/* Constant Definitions */ + +#ifndef TRUE +#define TRUE 1U +#endif + +#ifndef FALSE +#define FALSE 0U +#endif + +#ifndef NULL +#define NULL 0U +#endif + +#define FT_NULL NULL + +#define FT_COMPONENT_IS_READLY 0x11111111U +#define FT_COMPONENT_IS_STARTED 0x22222222U + +#define __STATIC_INLINE static inline + +#define FT_OUT /* 表示输出参数,指针指向的值会修改,且不会读 */ +#define FT_IN /* 表示输入参数,指针指向的值不会修改 */ +#define FT_INOUT /* 表示输入输出参数,指针指向的值会修改,且会读取 */ +#define FT_IO volatile + +typedef char s8; +typedef unsigned char u8; +typedef short s16; +typedef unsigned short u16; +typedef int s32; +typedef unsigned int u32; +typedef unsigned long long u64; +typedef long long s64; +typedef int ft_base_t; +typedef ft_base_t bool_t; + +typedef intptr_t INTPTR; +typedef uintptr_t UINTPTR; +typedef ptrdiff_t PTRDIFF; + +#define __STATIC_INLINE static inline +#define LOCAL static + +#define LLSB(x) ((x)&0xff) /* 32bit word byte/word swap macros */ +#define LNLSB(x) (((x) >> 8) & 0xff) +#define LNMSB(x) (((x) >> 16) & 0xff) +#define LMSB(x) (((x) >> 24) & 0xff) +#define U32SWAP(x) ((LLSB(x) << 24) | \ + (LNLSB(x) << 16) | \ + (LNMSB(x) << 8) | \ + (LMSB(x))) + +#define FT_SWAP32(x) U32SWAP((u32)x) + +#endif // diff --git a/bsp/ft2004/libraries/bsp/standlone/inbyte.c b/bsp/ft2004/libraries/bsp/standlone/inbyte.c new file mode 100644 index 0000000000000000000000000000000000000000..4f49daf6cc447eace570377a0b8596e395b6bded --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/inbyte.c @@ -0,0 +1,22 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-07 15:31:34 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + + +#include "ft_parameters.h" +#include "ft_uart_hw.h" + +u8 inbyte(void) +{ + return FUart_RecvByte(FT_STDIN_BASEADDRESS); +} \ No newline at end of file diff --git a/bsp/ft2004/libraries/bsp/standlone/outbyte.c b/bsp/ft2004/libraries/bsp/standlone/outbyte.c new file mode 100644 index 0000000000000000000000000000000000000000..e532ec9ed9f1c1b35d5af4c40451279d1a2c3c28 --- /dev/null +++ b/bsp/ft2004/libraries/bsp/standlone/outbyte.c @@ -0,0 +1,21 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-07 17:54:32 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_parameters.h" +#include "ft_uart_hw.h" + +void outbyte(char byte) +{ + FUart_SendByte(FT_STDOUT_BASEADDRESS, byte); +} diff --git a/bsp/ft2004/libraries/component/component.mk b/bsp/ft2004/libraries/component/component.mk new file mode 100644 index 0000000000000000000000000000000000000000..dcd981c6ec6190e9d8532d72500b1f454405991e --- /dev/null +++ b/bsp/ft2004/libraries/component/component.mk @@ -0,0 +1,4 @@ +INCDIRS += $(DEVICE_PATH)/component/sdmmc + + +SRCDIRS += $(DEVICE_PATH)/component/sdmmc diff --git a/bsp/ft2004/libraries/component/sdmmc/diskio_sdmmc.c b/bsp/ft2004/libraries/component/sdmmc/diskio_sdmmc.c new file mode 100644 index 0000000000000000000000000000000000000000..b0f02116ee1d5751c3a742fec768745653a76a5e --- /dev/null +++ b/bsp/ft2004/libraries/component/sdmmc/diskio_sdmmc.c @@ -0,0 +1,426 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-08 16:57:05 + * @LastEditTime: 2021-04-16 13:38:21 + * @Description:  This files is for free-rtos sdmmc porting + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include +#include +#include "ft_assert.h" +#include "ft_parameters.h" +#include "ft_sdctrl.h" +#include "ft_sdmmc.h" +#include "ft_sdmmc_common.h" +#include "ft_sdmmc_cmd.h" +#include "diskio_sdmmc.h" + +#define SDCTR_BUFF_SIZE (512 * 2) +#define SDCTR_ALIGN_MASK 0x1f +static u8 g_DMABuf[SDCTR_BUFF_SIZE] __attribute__((aligned(SDCTR_ALIGN_MASK + 1))); + +typedef struct +{ + FtsdCtrl_t *pSdmmcReg; + Sdmmc_Host_t *pSdmmcHost; + Sdmmc_Card_t *pSdmmcCard; + bool_t isReady; +} FSdmmc_Ctrl; + +FSdmmc_Ctrl *FSdmmc_GetSdmmcCtrl(); +ft_error_t FSdmmc_InitHost(); +ft_error_t FSdmmc_SetBusWidth(int slot, size_t width); +size_t FSdmmc_GetSlotWidth(int slot); +ft_error_t FSdmmc_SetBusDdrMode(int slot, bool_t ddr_enabled); +ft_error_t FSdmmc_SetCardClk(int slot, u32 freq_khz); +ft_error_t FSdmmc_DoTransaction(int slot, Sdmmc_Cmd_t *cmdinfo); +ft_error_t FSdmmc_DeInit(void); +ft_error_t FSdmmc_IoIntEnable(int slot); +ft_error_t FSdmmc_IoIntWait(int slot, u32 timeout_ticks); + +#define SDMMC_SLOT_NO_CD GPIO_NUM_NC ///< indicates that card detect line is not used +#define SDMMC_SLOT_NO_WP GPIO_NUM_NC ///< indicates that write protect line is not used +#define SDMMC_SLOT_WIDTH_DEFAULT 0 ///< use the default width for the slot (8 for slot 0, 4 for slot 1) + +static FSdmmc_Ctrl g_SdmmcCtrl = { + .pSdmmcReg = NULL, + .pSdmmcHost = NULL, + .pSdmmcCard = NULL, + .isReady = FALSE}; + +static FtsdCtrl_t *FSdmmc_GetHWCtrl() +{ + if (NULL == g_SdmmcCtrl.pSdmmcReg) + { + g_SdmmcCtrl.pSdmmcReg = Sdmmc_HeapMalloc(sizeof(FtsdCtrl_t)); + Ft_assertNoneReturn(g_SdmmcCtrl.pSdmmcReg); + } + + return g_SdmmcCtrl.pSdmmcReg; +} + +static Sdmmc_Host_t *FSdmmc_GetHostCtrl() +{ + if (NULL == g_SdmmcCtrl.pSdmmcHost) + { + g_SdmmcCtrl.pSdmmcHost = Sdmmc_HeapMalloc(sizeof(Sdmmc_Host_t)); + Ft_assertNoneReturn(g_SdmmcCtrl.pSdmmcHost); + + g_SdmmcCtrl.pSdmmcHost->flags = SDMMC_HOST_FLAG_1BIT; + g_SdmmcCtrl.pSdmmcHost->flags &= ~SDMMC_HOST_FLAG_DDR; + g_SdmmcCtrl.pSdmmcHost->slot = FATFS_HOST_SLOT_0; + g_SdmmcCtrl.pSdmmcHost->max_freq_khz = SDMMC_FREQ_PROBING; + g_SdmmcCtrl.pSdmmcHost->io_voltage = 3.3f; + g_SdmmcCtrl.pSdmmcHost->init = &FSdmmc_InitHost; + g_SdmmcCtrl.pSdmmcHost->set_bus_width = &FSdmmc_SetBusWidth; + g_SdmmcCtrl.pSdmmcHost->get_bus_width = &FSdmmc_GetSlotWidth; + g_SdmmcCtrl.pSdmmcHost->set_bus_ddr_mode = &FSdmmc_SetBusDdrMode; + g_SdmmcCtrl.pSdmmcHost->set_card_clk = &FSdmmc_SetCardClk; + g_SdmmcCtrl.pSdmmcHost->do_transaction = &FSdmmc_DoTransaction; + g_SdmmcCtrl.pSdmmcHost->deinit = &FSdmmc_DeInit; + g_SdmmcCtrl.pSdmmcHost->io_int_enable = FSdmmc_IoIntEnable; + g_SdmmcCtrl.pSdmmcHost->io_int_wait = FSdmmc_IoIntWait; + g_SdmmcCtrl.pSdmmcHost->command_timeout_ms = 0; + } + + return g_SdmmcCtrl.pSdmmcHost; +} + +static Sdmmc_Card_t *FSdmmc_GetCardCtrl() +{ + if (NULL == g_SdmmcCtrl.pSdmmcCard) + { + g_SdmmcCtrl.pSdmmcCard = Sdmmc_HeapMalloc(sizeof(Sdmmc_Card_t)); + Ft_assertNoneReturn(g_SdmmcCtrl.pSdmmcCard); + } + + return g_SdmmcCtrl.pSdmmcCard; +} + +bool_t FSdmmc_IsSdmmcReady() +{ + return g_SdmmcCtrl.isReady; +} + +static void FSdmmc_SetSdmmcReady(bool_t status) +{ + g_SdmmcCtrl.isReady = status; +} + +/******************SD MMC for FreeRTOS*************************/ +ft_error_t FSdmmc_InitHost() +{ + FtsdCtrl_t *pRegCtrl = FSdmmc_GetHWCtrl(); + ft_error_t ret = ERR_SDMMC_OK; + + pRegCtrl->config = *(FSdCtrl_Config_t *)FSdCtrl_LookupConfig(0); + FSdCtrl_Reset(pRegCtrl, (pFtsdCtrl_delayTimer_t)Sdmmc_Delay); + FATFS_ERROR_HANDLE_RET(ret, FsdCtrl_Init(pRegCtrl), "init host"); + + FSdCtrl_ClkFreqSetup(pRegCtrl, SDMMC_FREQ_PROBING); + + return ret; +} + +ft_error_t FSdmmc_InitCard() +{ + return Sdmmc_CardInit(FSdmmc_GetHostCtrl(), FSdmmc_GetCardCtrl()); +} + +bool_t FSdmmc_CardExist() +{ + return FSdCtrl_CardDetect(FSdmmc_GetHWCtrl()); +} + +ft_error_t FSdmmc_SetBusWidth(int slot, size_t width) +{ + ft_error_t ret = ERR_SDMMC_OK; + + return ret; +} + +size_t FSdmmc_GetSlotWidth(int slot) +{ + return 1; +} + +ft_error_t FSdmmc_SetBusDdrMode(int slot, bool_t ddr_enabled) +{ + ft_error_t ret = ERR_SDMMC_OK; + + return ret; +} + +ft_error_t FSdmmc_SetCardClk(int slot, u32 freq_khz) +{ + ft_error_t ret = ERR_SDMMC_OK; + FSdCtrl_ClkFreqSetup(FSdmmc_GetHWCtrl(), SDMMC_FREQ_DEFAULT); + return ret; +} + +static u32 FSdmmc_resp2CmdType(u32 cmdFlag) +{ + u32 cmdType = FTSDCTRL_CMD_RES_SHORT; + + switch (cmdFlag) + { + case SCT_RESP_NONE: + cmdType = FTSDCTRL_CMD_RES_NONE; + break; + case SCT_RESP_LONG: + cmdType = FTSDCTRL_CMD_RES_LONG; + break; + case SCT_RESP_SHORT: + cmdType = FTSDCTRL_CMD_RES_SHORT; + break; + default: + Ft_assertNoneReturn(0); + break; + } + + return cmdType; +} + +static ft_error_t FSdmmc_transferByDMA(FtsdCtrl_t *pRegCtrl, Sdmmc_Cmd_t *cmdInfo) +{ + u32 cmdType; + u32 *pBuf; + u32 ret = ERR_SDMMC_OK; + + Ft_assertNoneReturn((NULL != pRegCtrl) && (NULL != cmdInfo)); + + /* get respones type from command info */ + Sdmmc_TraceHeapAlloc("BEF-CMD-TYPE"); + cmdType = FSdmmc_resp2CmdType(cmdInfo->cmd_resp_type); + pBuf = cmdInfo->data; + + if (cmdInfo->flags & SCF_CMD_READ) + { + //FT_FATFS_DEBUG_I("read cmd"); + + /* read mode */ + if ((cmdInfo->flags & SCF_CMD_ADTC) && (512 > cmdInfo->blklen)) + { + Sdmmc_TraceHeapAlloc("BEF-DO-ACMD"); + FSdCtrl_DoACmd(pRegCtrl, cmdInfo->opcode, cmdType, cmdInfo->arg); + Sdmmc_Delay(10); + } + + Sdmmc_TraceHeapAlloc("BEF-READ-DATA"); + FSdCtrl_ReadData(pRegCtrl, (UINTPTR)cmdInfo->data, cmdInfo->arg, 1); + Sdmmc_TraceHeapAlloc("AFT-READ-DATA"); + //Ft_printf("0x%p %x\r\n", &cmdInfo->error, cmdInfo->error); + cmdInfo->error = FSdCtrl_WaitCmdEnd(pRegCtrl, (pFtsdCtrl_delayTimer_t)Sdmmc_Delay, cmdType, (u32 *)cmdInfo->response); + Sdmmc_TraceHeapAlloc("AFT-READ-WAIT"); + + ret = FSdCtrl_WaitReadDataEnd(pRegCtrl, (pFtsdCtrl_delayTimer_t)Sdmmc_Delay, 1); + Sdmmc_TraceHeapAlloc("AFT-READ-WAIT-END"); + } + else + { + /* write mode */ + //FT_FATFS_DEBUG_I("write cmd"); + + FSdCtrl_WriteData(pRegCtrl, (UINTPTR)cmdInfo->data, cmdInfo->arg, 1); + cmdInfo->error = FSdCtrl_WaitCmdEnd(pRegCtrl, (pFtsdCtrl_delayTimer_t)Sdmmc_Delay, cmdType, (u32 *)cmdInfo->response); + + ret = FSdCtrl_WaitWriteDataEnd(pRegCtrl, (pFtsdCtrl_delayTimer_t)Sdmmc_Delay, 1); + } + + return ret; +} + +static ft_error_t FSdmmc_doCommand(FtsdCtrl_t *pRegCtrl, Sdmmc_Cmd_t *cmdInfo) +{ + u32 cmdType; + u32 *pBuf; + u32 ret = ERR_SDMMC_OK; + + Ft_assertNoneReturn((NULL != pRegCtrl) && (NULL != cmdInfo)); + + cmdType = FSdmmc_resp2CmdType(cmdInfo->cmd_resp_type); + Sdmmc_Delay(10); + + //FT_FATFS_DEBUG_I("do cmd: type: %d, resp: 0x%x", cmdType, cmdInfo->response); + FSdCtrl_DoCmd(pRegCtrl, cmdInfo->opcode, cmdType, cmdInfo->arg); + cmdInfo->error = FSdCtrl_WaitCmdEnd(pRegCtrl, (pFtsdCtrl_delayTimer_t)Sdmmc_Delay, cmdType, (u32 *)cmdInfo->response); + ret = cmdInfo->error; + + return ret; +} + +static ft_error_t FSdmmc_sendCommand(FtsdCtrl_t *pRegCtrl, Sdmmc_Cmd_t *cmdInfo) +{ + ft_error_t ret = ERR_SDMMC_OK; + + Ft_assertNoneReturn((NULL != pRegCtrl) && (NULL != cmdInfo)); + + /* read one block */ + if (NULL != cmdInfo->data) + { + //FT_FATFS_DEBUG_I("CMD %d ,data transfer", cmdInfo->opcode); + Sdmmc_TraceHeapAlloc("BEF-DMA"); + ret = FSdmmc_transferByDMA(pRegCtrl, cmdInfo); + } + else + { + //FT_FATFS_DEBUG_I("CMD %d ,cmd transfer", cmdInfo->opcode); + Sdmmc_TraceHeapAlloc("BEF-DO-CMD"); + ret = FSdmmc_doCommand(pRegCtrl, cmdInfo); + } + + Sdmmc_TraceHeapAlloc("AFT-DO-CMD"); + return ret; +} + +static bool_t FSdmmc_cmdNeedsAutoStop(const Sdmmc_Cmd_t *cmd) +{ + /* SDMMC host needs an "auto stop" flag for the following commands: */ + return cmd->datalen > 0 && + (cmd->opcode == MMC_WRITE_BLOCK_MULTIPLE || + cmd->opcode == MMC_READ_BLOCK_MULTIPLE || + cmd->opcode == MMC_WRITE_DAT_UNTIL_STOP || + cmd->opcode == MMC_READ_DAT_UNTIL_STOP); +} + +static void FSdmmc_dumpCmdInfo(Sdmmc_Cmd_t *cmdInfo) +{ + Ft_assertNoneReturn(NULL != cmdInfo); + return; +} + +static void FSdmmc_dumpCardInfo(Sdmmc_Card_t *pCard) +{ + Ft_assertNoneReturn(NULL != pCard); + + // FT_FATFS_DEBUG_I("HOST:0x%x 0x%x, RCA:0x%x, Freq: %d, MEM: %d, SPI: %d, SDIO: %d, MMC: %d, BUS Width: %d. DDR: %d", + // pCard->host, FSdmmc_GetSdmmcCtrl(), pCard->rca, pCard->max_freq_khz, + // pCard->is_mem, Sdmmc_IsHostSpi(pCard), pCard->is_sdio, pCard->is_mmc, + // pCard->log_bus_width, pCard->is_ddr); + + return; +} + +ft_error_t FSdmmc_DoTransaction(int slot, Sdmmc_Cmd_t *cmdInfo) +{ + ft_error_t ret = ERR_SDMMC_OK; + FtsdCtrl_t *pRegCtrl = FSdmmc_GetHWCtrl(); + size_t inputBufSize; + u8 *pDataBuf = cmdInfo->data; + + Sdmmc_TraceHeapAlloc("BEF-DUMP"); + FSdmmc_dumpCmdInfo(cmdInfo); + + /* use DMA buf to transfer data */ + if ((NULL != cmdInfo->data)) + { + Ft_assertNoneReturn(cmdInfo->datalen <= SDCTR_BUFF_SIZE); + memset(g_DMABuf, 0, sizeof(g_DMABuf)); + memcpy(g_DMABuf, cmdInfo->data, cmdInfo->datalen); + cmdInfo->data = g_DMABuf; /* use dma buffer to read and write data */ + } + + ret = FSdmmc_sendCommand(pRegCtrl, cmdInfo); + + if ((NULL != cmdInfo->data) && (ERR_SDMMC_OK == ret)) + { + /* copy back data from DMA buf to the original data buf */ + //dump_hex(g_DMABuf, 512, "DMA buf"); + memcpy(pDataBuf, g_DMABuf, cmdInfo->datalen); + } + + if (FSdmmc_cmdNeedsAutoStop(cmdInfo)) + { + Ft_assertNoneReturn(0); + } + + return ret; +} + +ft_error_t FSdmmc_DeInit(void) +{ + ft_error_t ret = ERR_SDMMC_OK; + + FSdmmc_SetSdmmcReady(FALSE); + + return ret; +} + +ft_error_t FSdmmc_IoIntEnable(int slot) +{ + ft_error_t ret = ERR_SDMMC_OK; + + return ret; +} + +ft_error_t FSdmmc_IoIntWait(int slot, u32 timeout_ticks) +{ + ft_error_t ret = ERR_SDMMC_OK; + + return ret; +} + +ft_error_t FSdmmc_InitSd() +{ + ft_error_t ret = ERR_SDMMC_OK; + + if (FSdmmc_IsSdmmcReady()) + { + FT_SDMMC_DEBUG_E("try to re-init"); + return ret; + } + + FATFS_ERROR_HANDLE_RET(ret, FSdmmc_InitHost(), "init host"); + FATFS_ERROR_HANDLE_RET(ret, FSdmmc_InitCard(), "init card"); + + if (FSdmmc_CardExist()) + { + FSdmmc_SetSdmmcReady(TRUE); + } + else + { + ret = ERR_SDMMC_CARD_NOFOUND; + } + + return ret; +} + +ft_error_t FSdmmc_ReadSector(u32 startSector, u32 numSector, void *pBuf) +{ + ft_error_t ret = ERR_SDMMC_OK; + //FT_FATFS_DEBUG_I("before get ctrl"); + Sdmmc_Card_t *pCard = FSdmmc_GetCardCtrl(); + + //FT_FATFS_DEBUG_I("before check ready"); + if (!FSdmmc_IsSdmmcReady()) + { + return ERR_SDMMC_NOTYET_INIT; + } + + FATFS_ERROR_HANDLE_RET(ret, Sdmmc_ReadSectors(pCard, pBuf, startSector, numSector), "read sector"); + return ret; +} + +ft_error_t FSdmmc_WriteSector(u32 startSector, u32 numSector, void *pBuf) +{ + ft_error_t ret = ERR_SDMMC_OK; + //FT_FATFS_DEBUG_I("before get ctrl"); + Sdmmc_Card_t *pCard = FSdmmc_GetCardCtrl(); + + //FT_FATFS_DEBUG_I("before check ready"); + if (!FSdmmc_IsSdmmcReady()) + { + return ERR_SDMMC_NOTYET_INIT; + } + + FATFS_ERROR_HANDLE_RET(ret, Sdmmc_WriteSectors(pCard, pBuf, startSector, numSector), "write sector"); + //FT_FATFS_DEBUG_I("sector write finished! ret %x", ret); + return ret; +} \ No newline at end of file diff --git a/bsp/ft2004/libraries/component/sdmmc/diskio_sdmmc.h b/bsp/ft2004/libraries/component/sdmmc/diskio_sdmmc.h new file mode 100644 index 0000000000000000000000000000000000000000..d00d7df32e1548a4c5abee8ab6809a40efa16ee9 --- /dev/null +++ b/bsp/ft2004/libraries/component/sdmmc/diskio_sdmmc.h @@ -0,0 +1,102 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-14 15:03:12 + * @LastEditTime: 2021-04-16 10:39:54 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef _FT_DISKIO_FATFS_H_ +#define _FT_DISKIO_FATFS_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ft_sdctrl.h" +#include "ft_types.h" +#include "ft_error_code.h" +#include "ft_sdmmc_defs.h" +#include "ft_sdmmc_common.h" +#include "ft_sdmmc.h" +#include "ft_debug.h" + +#define FATFS_HOST_SLOT_0 0 ///< FATFS slot 0 + +#define FATFS_ERROR_HANDLE_RET(result, expression, msg) \ + { \ + if (ERR_SDMMC_OK == (result)) { \ + result = expression; \ + if (result != ERR_SDMMC_OK) { \ + FT_FATFS_DEBUG_E("sd mmc process failed when %s err 0x%x at %s", msg, result, __func__); \ + return result; \ + } \ + } \ + } + +#define FATFS_ERROR_HANDLE_GOTO(result, expression, label, msg) \ + { \ + if (ERR_SDMMC_OK == (result)) { \ + result = expression; \ + if (result != ERR_SDMMC_OK) { \ + FT_FATFS_DEBUG_E("sd mmc process failed when %s err 0x%x at %s", msg, result, __func__); \ + goto label; \ + } \ + } \ + } + +#define FATFS_ALLOC_HANDLE_RET(result, ptr) \ + { \ + if (NULL == (ptr)) \ + { \ + result = ERR_FATFS_NO_MEM; \ + FT_FATFS_DEBUG_E("sd mmc memory allocate failed err %d at %s", result, __func__); \ + return result; \ + }\ + } + +#define FATFS_ALLOC_HANDLE_GOTO(result, ptr, label) \ + { \ + if (NULL == (ptr)) \ + { \ + result = ERR_FATFS_NO_MEM; \ + FT_FATFS_DEBUG_E("sd mmc memory allocate failed err %d at %s", result, __func__); \ + goto label; \ + }\ + } + +ft_error_t FSdmmc_ProbeSd(int slot, int width, int freq_khz, bool_t ddr); +ft_error_t FSdmmc_InitSd(); +ft_error_t FSdmmc_ReadSector(u32 startSector, u32 numSector, void *pBuf); +ft_error_t FSdmmc_WriteSector(u32 startSector, u32 numSector, void *pBuf); +bool_t FSdmmc_CardExist(); +bool_t FSdmmc_IsSdmmcReady(); + +#define FT_FATFS_DEBUG_ENABLED +#define FT_FATFS_DEBUG_TAG "FT_FATFS" +#ifdef FT_FATFS_DEBUG_ENABLED +#define FT_FATFS_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FT_FATFS_DEBUG_TAG, format, ##__VA_ARGS__) +#define FT_FATFS_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(FT_FATFS_DEBUG_TAG, format, ##__VA_ARGS__) +#define FT_FATFS_DEBUG_D(format, ...) FT_DEBUG_PRINT_D(FT_FATFS_DEBUG_TAG, format, ##__VA_ARGS__) +#define FT_FATFS_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FT_FATFS_DEBUG_TAG, format, ##__VA_ARGS__) +#define FT_FATFS_DEBUG_V(format, ...) FT_DEBUG_PRINT_V(FT_FATFS_DEBUG_TAG, format, ##__VA_ARGS__) +#else +#define FT_FATFS_DEBUG_I(format, ...) +#define FT_FATFS_DEBUG_E(format, ...) +#define FT_FATFS_DEBUG_D(format, ...) +#define FT_FATFS_DEBUG_W(format, ...) +#define FT_FATFS_DEBUG_V(format, ...) +#endif + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc.h b/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc.h new file mode 100644 index 0000000000000000000000000000000000000000..b46756de8f94df54ae2f760d40ae90a2b8821b86 --- /dev/null +++ b/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc.h @@ -0,0 +1,239 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-08 11:50:53 + * @LastEditTime: 2021-04-16 13:29:24 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef _FT_SDMMC_H_ +#define _FT_SDMMC_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ft_types.h" +#include "ft_trace.h" +#include "ft_error_code.h" +#include "ft_sdmmc_defs.h" + +/** + * Decoded values from SD card Card Specific Data register + */ +typedef struct { + int csdVer; /*!< CSD structure format */ + int mmcVer; /*!< MMC version (for CID format) */ + int capacity; /*!< total number of sectors */ + int sectorSize; /*!< sector size in bytes */ + int readBlkLen; /*!< block length for reads */ + int cardCmdClass; /*!< Card Command Class for SD */ + int transSpeed; /*!< Max transfer speed */ +} Sdmmc_CSD_t; + +/** + * Decoded values from SD card Card IDentification register + */ +typedef struct { + int mfgId; /*!< manufacturer identification number */ + int oemId; /*!< OEM/product identification number */ + char name[8]; /*!< product name (MMC v1 has the longest) */ + int revision; /*!< product revision */ + int serial; /*!< product serial number */ + int date; /*!< manufacturing date */ +} Sdmmc_CID_t; + +/** + * Decoded values from SD Configuration Register + */ +typedef struct { + int sdSpec; /*!< SD Physical layer specification version, reported by card */ + int bus_width; /*!< bus widths supported by card: BIT(0) — 1-bit bus, BIT(2) — 4-bit bus */ +} Sdmmc_SCR_t; + +/** + * Decoded values of Extended Card Specific Data + */ +typedef struct { + u8 power_class; /*!< Power class used by the card */ +} Sdmmc_ExtCSD_t; + +/** + * SD/MMC command response buffer + */ +typedef u32 Sdmmc_Resp_t[4]; + +/** + * SD SWITCH_FUNC response buffer + */ +typedef struct { + u32 data[512 / 8 / sizeof(u32)]; /*!< response data */ +} Sdmmc_SwitchFuncRsp_t; + +/** + * SD/MMC command information + */ +typedef struct { + u32 opcode; /*!< SD or MMC command index */ + u32 arg; /*!< SD/MMC command argument */ + Sdmmc_Resp_t response; /*!< response buffer */ + //u32 response[4]; + void* data; /*!< buffer to send or read into */ + size_t datalen; /*!< length of data buffer */ + size_t blklen; /*!< block length */ + int flags; /*!< see below */ +/** @cond */ +#define SCF_ITSDONE 0x0001 /*!< command is complete */ +#define SCF_CMD(flags) ((flags) & 0x00f0) +#define SCF_CMD_AC 0x0000 +#define SCF_CMD_ADTC 0x0010 +#define SCF_CMD_BC 0x0020 +#define SCF_CMD_BCR 0x0030 +#define SCF_CMD_READ 0x0040 /*!< read command (data expected) */ +#define SCF_RSP_BSY 0x0100 +#define SCF_RSP_136 0x0200 +#define SCF_RSP_CRC 0x0400 +#define SCF_RSP_IDX 0x0800 +#define SCF_RSP_PRESENT 0x1000 +/* response types */ +#define SCF_RSP_R0 0 /*!< none */ +#define SCF_RSP_R1 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX) +#define SCF_RSP_R1B (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX|SCF_RSP_BSY) +#define SCF_RSP_R2 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_136) +#define SCF_RSP_R3 (SCF_RSP_PRESENT) +#define SCF_RSP_R4 (SCF_RSP_PRESENT) +#define SCF_RSP_R5 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX) +#define SCF_RSP_R5B (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX|SCF_RSP_BSY) +#define SCF_RSP_R6 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX) +#define SCF_RSP_R7 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX) +/* special flags */ +#define SCF_WAIT_BUSY 0x2000 /*!< Wait for completion of card busy signal before returning */ +/** @endcond */ + u32 cmd_resp_type; /*!< command respones type */ +#define SCT_RESP_NONE 0x01 +#define SCT_RESP_LONG 0x02 +#define SCT_RESP_SHORT 0x04 + ft_error_t error; /*!< error returned from transfer */ + int timeout_ms; /*!< response timeout, in milliseconds */ +} Sdmmc_Cmd_t; + +/** + * SD/MMC Host description + * + * This structure defines properties of SD/MMC host and functions + * of SD/MMC host which can be used by upper layers. + */ +typedef struct { + u32 flags; /*!< flags defining host properties */ +#define SDMMC_HOST_FLAG_1BIT BIT(0) /*!< host supports 1-line SD and MMC protocol */ +#define SDMMC_HOST_FLAG_4BIT BIT(1) /*!< host supports 4-line SD and MMC protocol */ +#define SDMMC_HOST_FLAG_8BIT BIT(2) /*!< host supports 8-line MMC protocol */ +#define SDMMC_HOST_FLAG_SPI BIT(3) /*!< host supports SPI protocol */ +#define SDMMC_HOST_FLAG_DDR BIT(4) /*!< host supports DDR mode for SD/MMC */ + int slot; /*!< slot number, to be passed to host functions */ + int max_freq_khz; /*!< max frequency supported by the host */ +#define SDMMC_FREQ_DEFAULT 20000 /*!< SD/MMC Default speed (limited by clock divider) */ +#define SDMMC_FREQ_HIGHSPEED 40000 /*!< SD High speed (limited by clock divider) */ +#define SDMMC_FREQ_PROBING 400 /*!< SD/MMC probing speed */ +#define SDMMC_FREQ_52M 52000 /*!< MMC 52MHz speed */ +#define SDMMC_FREQ_26M 26000 /*!< MMC 26MHz speed */ + float io_voltage; /*!< I/O voltage used by the controller (voltage switching is not supported) */ + ft_error_t (*init)(void); /*!< Host function to initialize the driver */ + ft_error_t (*set_bus_width)(int slot, size_t width); /*!< host function to set bus width */ + size_t (*get_bus_width)(int slot); /*!< host function to get bus width */ + ft_error_t (*set_bus_ddr_mode)(int slot, bool_t ddr_enable); /*!< host function to set DDR mode */ + ft_error_t (*set_card_clk)(int slot, u32 freq_khz); /*!< host function to set card clock frequency */ + ft_error_t (*do_transaction)(int slot, Sdmmc_Cmd_t* cmdinfo); /*!< host function to do a transaction */ + ft_error_t (*deinit)(void); /*!< host function to deinitialize the driver */ + ft_error_t (*io_int_enable)(int slot); /*!< Host function to enable SDIO interrupt line */ + ft_error_t (*io_int_wait)(int slot, u32 timeout_ticks); /*!< Host function to wait for SDIO interrupt line to be active */ + int command_timeout_ms; /*!< timeout, in milliseconds, of a single command. Set to 0 to use the default value. */ +} Sdmmc_Host_t; + +/** + * SD/MMC card information structure + */ +typedef struct { + Sdmmc_Host_t host; /*!< Host with which the card is associated */ + u32 ocr; /*!< OCR (Operation Conditions Register) value */ + union { + Sdmmc_CID_t cid; /*!< decoded CID (Card IDentification) register value */ + Sdmmc_Resp_t raw_cid; /*!< raw CID of MMC card to be decoded + after the CSD is fetched in the data transfer mode*/ + }; + Sdmmc_CSD_t csd; /*!< decoded CSD (Card-Specific Data) register value */ + Sdmmc_SCR_t scr; /*!< decoded SCR (SD card Configuration Register) value */ + Sdmmc_ExtCSD_t ext_csd; /*!< decoded EXT_CSD (Extended Card Specific Data) register value */ + u16 rca; /*!< RCA (Relative Card Address) */ + u16 max_freq_khz; /*!< Maximum frequency, in kHz, supported by the card */ + u32 is_mem : 1; /*!< Bit indicates if the card is a memory card */ + u32 is_sdio : 1; /*!< Bit indicates if the card is an IO card */ + u32 is_mmc : 1; /*!< Bit indicates if the card is MMC */ + u32 num_io_functions : 3; /*!< If is_sdio is 1, contains the number of IO functions on the card */ + u32 log_bus_width : 2; /*!< log2(bus width supported by card) */ + u32 is_ddr : 1; /*!< Card supports DDR mode */ + u32 reserved : 23; /*!< Reserved for future expansion */ +} Sdmmc_Card_t; + +/* +* Platform configuration for SDMMC +*/ +typedef struct +{ + void (*task_delay)(u32 ticks_to_delay); /* os-depends tick time delay method */ + void *(*heap_alloc)(size_t size); /* os-depends heap allocate method */ + void (*heap_free)(void *ptr); /* os-depends heap free method */ + bool_t (*check_dma_capable)(const void *ptr); /* os-depends memory allign check before dma */ + void (*printf)(const char *fmt, ...); /* os-depends printf method */ + u32 tick_period; /* os-depends tick time period */ + void *event_queue; /* os-depends event queue */ + void *io_intr_event; /* os-depends event semphere */ +} Sdmmc_OSImpl_t; +const Sdmmc_OSImpl_t *get_sdmmc_os_impl(); +static inline void Sdmmc_Printf(const char *fmt, ...) +{ + get_sdmmc_os_impl()->printf(fmt); +} + +static inline void *Sdmmc_HeapMalloc(size_t size) +{ + //FT_MEM_TRACE("size %d", size); + Sdmmc_TraceHeapAlloc("BEF-MALLOC"); + void *pMen = get_sdmmc_os_impl()->heap_alloc(size); + //FT_MEM_TRACE("malloc 0x%p size %d", pMen); + return pMen; +} + +static inline void Sdmmc_HeapFree(void *ptr) +{ + if (NULL != ptr) + { + //FT_MEM_TRACE("free 0x%p", ptr); + Sdmmc_TraceHeapAlloc("BEF-FREE"); + get_sdmmc_os_impl()->heap_free(ptr); + } + return; +} + +static inline void Sdmmc_Delay(u32 tick) +{ + get_sdmmc_os_impl()->task_delay(tick); +} + +static inline bool_t Sdmmc_DMACapable(const void *ptr) +{ + get_sdmmc_os_impl()->check_dma_capable(ptr); +} + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc_cmd.c b/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc_cmd.c new file mode 100644 index 0000000000000000000000000000000000000000..7236ae5f9f2cf3ba41bf125bdd3dc13d54f0aab0 --- /dev/null +++ b/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc_cmd.c @@ -0,0 +1,610 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-08 11:51:03 + * @LastEditTime: 2021-04-15 13:39:44 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include +#include "ft_sdmmc_defs.h" +#include "ft_sdmmc_cmd.h" +#include "ft_sdmmc_common.h" + +static const char* TAG = "sdmmc_cmd"; + +ft_error_t Sdmmc_SendCmd(Sdmmc_Card_t* card, Sdmmc_Cmd_t* cmd) +{ + if (card->host.command_timeout_ms != 0) { + cmd->timeout_ms = card->host.command_timeout_ms; + } else if (cmd->timeout_ms == 0) { + cmd->timeout_ms = SDMMC_DEFAULT_CMD_TIMEOUT_MS; + } + + int slot = card->host.slot; + Sdmmc_TraceHeapAlloc("BEF-TRANS"); + FT_SDMMC_DEBUG_V( "sending cmd slot=%d op=%d arg=%x flags=%x data=%p blklen=%d datalen=%d timeout=%d", + slot, cmd->opcode, cmd->arg, cmd->flags, cmd->data, cmd->blklen, cmd->datalen, cmd->timeout_ms); + //FT_SDMMC_DEBUG_I("transaction handler %x", (*card->host.do_transaction)); + ft_error_t err = (*card->host.do_transaction)(slot, cmd); + if (err != 0) { + FT_SDMMC_DEBUG_E("cmd=%d, sdmmc_req_run returned 0x%x", cmd->opcode, err); + return err; + } + Sdmmc_TraceHeapAlloc("AFT-TRANS"); + int state = MMC_R1_CURRENT_STATE(cmd->response); + FT_SDMMC_DEBUG_V( "CMD %d type %d arg 0x%x \r\n response--------- \r\n %08x \r\n %08x \r\n %08x \r\n %08x \r\n err=0x%x state=%d \r\n ---------", + cmd->opcode, cmd->cmd_resp_type, cmd->arg, + cmd->response[0], + cmd->response[1], + cmd->response[2], + cmd->response[3], + cmd->error, + state); + return cmd->error; +} + +ft_error_t Sdmmc_sendAppCmd(Sdmmc_Card_t* card, Sdmmc_Cmd_t* cmd) +{ + Sdmmc_Cmd_t app_cmd = { + .opcode = MMC_APP_CMD, + .flags = SCF_CMD_AC | SCF_RSP_R1, + .cmd_resp_type = SCT_RESP_SHORT, + .arg = MMC_ARG_RCA(card->rca) + }; + Sdmmc_TraceHeapAlloc("BEF-SEND"); + ft_error_t err = Sdmmc_SendCmd(card, &app_cmd); + if (err != ERR_SDMMC_OK) { + return err; + } + // Check APP_CMD status bit (only in SD mode) + Sdmmc_TraceHeapAlloc("AFT-SEND"); + if (!Sdmmc_IsHostSpi(card) && !(MMC_R1(app_cmd.response) & MMC_R1_APP_CMD)) { + FT_SDMMC_DEBUG_E("card doesn't support APP_CMD"); + return ERR_SDMMC_NOT_SUPPORTED; + } + return Sdmmc_SendCmd(card, cmd); +} + + +ft_error_t Sdmmc_SendCmdGoIdleState(Sdmmc_Card_t* card) +{ + Sdmmc_Cmd_t cmd = { + .opcode = MMC_GO_IDLE_STATE, + .flags = SCF_CMD_BC | SCF_RSP_R0, + .cmd_resp_type = SCT_RESP_NONE + }; + ft_error_t err = Sdmmc_SendCmd(card, &cmd); + if (Sdmmc_IsHostSpi(card)) { + /* To enter SPI mode, CMD0 needs to be sent twice (see figure 4-1 in + * SD Simplified spec v4.10). Some cards enter SD mode on first CMD0, + * so don't expect the above command to succeed. + * SCF_RSP_R1 flag below tells the lower layer to expect correct R1 + * response (in SPI mode). + */ + (void) err; + Sdmmc_Delay(SDMMC_GO_IDLE_DELAY_MS / get_sdmmc_os_impl()->tick_period); + + cmd.flags |= SCF_RSP_R1; + err = Sdmmc_SendCmd(card, &cmd); + } + if (err == ERR_SDMMC_OK) { + Sdmmc_Delay(SDMMC_GO_IDLE_DELAY_MS / get_sdmmc_os_impl()->tick_period); + } + return err; +} + + +ft_error_t Sdmmc_SendCmdSendIfCond(Sdmmc_Card_t* card, u32 ocr) +{ + const u8 pattern = 0xaa; /* any pattern will do here */ + Sdmmc_Cmd_t cmd = { + .opcode = SD_SEND_IF_COND, + .arg = (((ocr & SD_OCR_VOL_MASK) != 0) << 8) | pattern, + .flags = SCF_CMD_BCR | SCF_RSP_R7, + .cmd_resp_type = SCT_RESP_SHORT, + }; + ft_error_t err = Sdmmc_SendCmd(card, &cmd); + if (err != ERR_SDMMC_OK) { + return err; + } + u8 response = cmd.response[0] & 0xff; + if (response != pattern) { + FT_SDMMC_DEBUG_E("%s: received=0x%x expected=0x%x", __func__, response, pattern); + return ERR_SDMMC_INVALID_RESPONSE; + } + return ERR_SDMMC_OK; +} + +ft_error_t Sdmmc_SendCmdSendOpCond(Sdmmc_Card_t* card, u32 ocr, u32 *ocrp) +{ + ft_error_t err; + + Sdmmc_Cmd_t cmd = { + .arg = ocr, + .flags = SCF_CMD_BCR | SCF_RSP_R3, + .cmd_resp_type = SCT_RESP_SHORT, + .opcode = SD_APP_OP_COND + }; + int nretries = SDMMC_SEND_OP_COND_MAX_RETRIES; + int err_cnt = SDMMC_SEND_OP_COND_MAX_ERRORS; + for (; nretries != 0; --nretries) { + bzero(&cmd, sizeof cmd); + cmd.arg = ocr; + cmd.flags = SCF_CMD_BCR | SCF_RSP_R3; + if (!card->is_mmc) { /* SD mode */ + cmd.opcode = SD_APP_OP_COND; + cmd.cmd_resp_type = SCT_RESP_SHORT; + err = Sdmmc_sendAppCmd(card, &cmd); + } else { /* MMC mode */ + cmd.arg &= ~MMC_OCR_ACCESS_MODE_MASK; + cmd.arg |= MMC_OCR_SECTOR_MODE; + cmd.opcode = MMC_SEND_OP_COND; + cmd.cmd_resp_type = SCT_RESP_SHORT; + err = Sdmmc_SendCmd(card, &cmd); + } + + if (err != ERR_SDMMC_OK) { + if (--err_cnt == 0) { + FT_SDMMC_DEBUG_E("%s: Sdmmc_sendAppCmd err=0x%x", __func__, err); + return err; + } else { + FT_SDMMC_DEBUG_V( "%s: ignoring err=0x%x", __func__, err); + continue; + } + } + // In SD protocol, card sets MEM_READY bit in OCR when it is ready. + // In SPI protocol, card clears IDLE_STATE bit in R1 response. + if (!Sdmmc_IsHostSpi(card)) { + if ((MMC_R3(cmd.response) & MMC_OCR_MEM_READY) || + ocr == 0) { + break; + } + } else { + if ((SD_SPI_R1(cmd.response) & SD_SPI_R1_IDLE_STATE) == 0) { + break; + } + } + Sdmmc_Delay(10 / get_sdmmc_os_impl()->tick_period); + } + if (nretries == 0) { + return ERR_SDMMC_TIMEOUT; + } + if (ocrp) { + *ocrp = MMC_R3(cmd.response); + } + return ERR_SDMMC_OK; +} + +ft_error_t Sdmmc_SendCmdReadOCR(Sdmmc_Card_t *card, u32 *ocrp) +{ + assert(ocrp); + Sdmmc_Cmd_t cmd = { + .opcode = SD_READ_OCR, + .flags = SCF_CMD_BCR | SCF_RSP_R2, + .cmd_resp_type = SCT_RESP_LONG + }; + ft_error_t err = Sdmmc_SendCmd(card, &cmd); + if (err != ERR_SDMMC_OK) { + return err; + } + *ocrp = SD_SPI_R3(cmd.response); + return ERR_SDMMC_OK; +} + + +ft_error_t Sdmmc_SendCmdAllSendCID(Sdmmc_Card_t* card, Sdmmc_Resp_t* out_raw_cid) +{ + assert(out_raw_cid); + Sdmmc_Cmd_t cmd = { + .opcode = MMC_ALL_SEND_CID, + .flags = SCF_CMD_BCR | SCF_RSP_R2, + .cmd_resp_type = SCT_RESP_LONG + }; + ft_error_t err = Sdmmc_SendCmd(card, &cmd); + if (err != ERR_SDMMC_OK) { + return err; + } + memcpy(out_raw_cid, &cmd.response, sizeof(Sdmmc_Resp_t)); + return ERR_SDMMC_OK; +} + +ft_error_t Sdmmc_SendCmdSendCID(Sdmmc_Card_t *card, Sdmmc_CID_t *out_cid) +{ + assert(out_cid); + assert(Sdmmc_IsHostSpi(card) && "SEND_CID should only be used in SPI mode"); + assert(!card->is_mmc && "MMC cards are not supported in SPI mode"); + Sdmmc_Resp_t buf; + Sdmmc_Cmd_t cmd = { + .opcode = MMC_SEND_CID, + .flags = SCF_CMD_READ | SCF_CMD_ADTC, + .cmd_resp_type = SCT_RESP_LONG, + .arg = 0, + .data = &buf[0], + .datalen = sizeof(buf) + }; + ft_error_t err = Sdmmc_SendCmd(card, &cmd); + if (err != ERR_SDMMC_OK) { + return err; + } + Sdmmc_FilpByteOrder(buf, sizeof(buf)); + return Sdmmc_DecodeCID(buf, out_cid); +} + + +ft_error_t Sdmmc_SendCmdSetRelativeAddr(Sdmmc_Card_t* card, uint16_t* out_rca) +{ + assert(out_rca); + Sdmmc_Cmd_t cmd = { + .opcode = SD_SEND_RELATIVE_ADDR, + .flags = SCF_CMD_BCR | SCF_RSP_R6, + .cmd_resp_type = SCT_RESP_SHORT + }; + + /* MMC cards expect us to set the RCA. + * Set RCA to 1 since we don't support multiple cards on the same bus, for now. + */ + uint16_t mmc_rca = 1; + if (card->is_mmc) { + cmd.arg = MMC_ARG_RCA(mmc_rca); + } + + ft_error_t err = Sdmmc_SendCmd(card, &cmd); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E("send CMD RCA failed!!"); + return err; + } + + *out_rca = (card->is_mmc) ? mmc_rca : SD_R6_RCA(cmd.response); + return ERR_SDMMC_OK; +} + +ft_error_t Sdmmc_SendCmdSetBlkLen(Sdmmc_Card_t* card, Sdmmc_CSD_t* csd) +{ + Sdmmc_Cmd_t cmd = { + .opcode = MMC_SET_BLOCKLEN, + .arg = csd->sectorSize, + .flags = SCF_CMD_AC | SCF_RSP_R1, + .cmd_resp_type = SCT_RESP_SHORT + }; + return Sdmmc_SendCmd(card, &cmd); +} + +ft_error_t Sdmmc_SendCmdSendCSD(Sdmmc_Card_t* card, Sdmmc_CSD_t* out_csd) +{ + /* The trick with SEND_CSD is that in SPI mode, it acts as a data read + * command, while in SD mode it is an AC command with R2 response. + */ + Sdmmc_Resp_t spi_buf; + const bool_t is_spi = Sdmmc_IsHostSpi(card); + Sdmmc_Cmd_t cmd = { + .opcode = MMC_SEND_CSD, + .arg = is_spi ? 0 : MMC_ARG_RCA(card->rca), + .flags = is_spi ? (SCF_CMD_READ | SCF_CMD_ADTC | SCF_RSP_R1) : + (SCF_CMD_AC | SCF_RSP_R2), + .cmd_resp_type = SCT_RESP_LONG, + .data = is_spi ? &spi_buf[0] : 0, + .datalen = is_spi ? sizeof(spi_buf) : 0, + }; + ft_error_t err = Sdmmc_SendCmd(card, &cmd); + if (err != ERR_SDMMC_OK) { + return err; + } + u32* ptr = cmd.response; + if (is_spi) { + Sdmmc_FilpByteOrder(spi_buf, sizeof(spi_buf)); + ptr = spi_buf; + } + if (card->is_mmc) { + err = Sdmmc_MMCDecodeCSD(cmd.response, out_csd); + } else { + err = Sdmmc_DecodeCSD(ptr, out_csd); + } + return err; +} + +ft_error_t Sdmmc_SendCmdSelectCard(Sdmmc_Card_t* card, u32 rca) +{ + /* Don't expect to see a response when de-selecting a card */ + u32 response = (rca == 0) ? 0 : SCF_RSP_R1; + Sdmmc_Cmd_t cmd = { + .opcode = MMC_SELECT_CARD, + .arg = MMC_ARG_RCA(rca), + .flags = SCF_CMD_AC | response, + .cmd_resp_type = SCT_RESP_SHORT + }; + return Sdmmc_SendCmd(card, &cmd); +} + +ft_error_t Sdmmc_SendCmdSendSCR(Sdmmc_Card_t* card, Sdmmc_SCR_t *out_scr) +{ + size_t datalen = 8; + u32* buf = (u32*) Sdmmc_HeapMalloc(datalen); + if (buf == NULL) { + return ERR_SDMMC_NO_MEM; + } + Sdmmc_Cmd_t cmd = { + .data = buf, + .datalen = datalen, + .blklen = datalen, + .flags = SCF_CMD_ADTC | SCF_CMD_READ | SCF_RSP_R1, + .cmd_resp_type = SCT_RESP_SHORT, + .opcode = SD_APP_SEND_SCR + }; + Sdmmc_TraceHeapAlloc("BEF-APP-CMD"); + ft_error_t err = Sdmmc_sendAppCmd(card, &cmd); + Sdmmc_TraceHeapAlloc("AFT-APP-CMD"); + if (err == ERR_SDMMC_OK) { + err = Sdmmc_DecodeSCR(buf, out_scr); + + // if (ERR_SDMMC_OK != err){ + // //dump_hex((u8*)buf, datalen * sizeof(u32)); + // } + + Sdmmc_TraceHeapAlloc("AFT-DECODE-SCR"); + FT_SDMMC_DEBUG_E("result: %x, bus width: %d, sd spec: %d", err, + out_scr->bus_width, out_scr->sdSpec); + } + Sdmmc_HeapFree(buf); + return err; +} + +ft_error_t Sdmmc_SendCmdSetBusWidth(Sdmmc_Card_t* card, int width) +{ + Sdmmc_Cmd_t cmd = { + .opcode = SD_APP_SET_BUS_WIDTH, + .flags = SCF_RSP_R1 | SCF_CMD_AC, + .cmd_resp_type = SCT_RESP_SHORT, + .arg = (width == 4) ? SD_ARG_BUS_WIDTH_4 : SD_ARG_BUS_WIDTH_1, + }; + + return Sdmmc_sendAppCmd(card, &cmd); +} + +ft_error_t Sdmmc_SendCmdCrcOnOff(Sdmmc_Card_t* card, bool_t crc_enable) +{ + assert(Sdmmc_IsHostSpi(card) && "CRC_ON_OFF can only be used in SPI mode"); + Sdmmc_Cmd_t cmd = { + .opcode = SD_CRC_ON_OFF, + .arg = crc_enable ? 1 : 0, + .flags = SCF_CMD_AC | SCF_RSP_R1, + .cmd_resp_type = SCT_RESP_SHORT + }; + return Sdmmc_SendCmd(card, &cmd); +} + +ft_error_t Sdmmc_SendCmdSendStatus(Sdmmc_Card_t* card, u32* out_status) +{ + Sdmmc_Cmd_t cmd = { + .opcode = MMC_SEND_STATUS, + .arg = MMC_ARG_RCA(card->rca), + .flags = SCF_CMD_AC | SCF_RSP_R1, + .cmd_resp_type = SCT_RESP_SHORT + }; + ft_error_t err = Sdmmc_SendCmd(card, &cmd); + if (err != ERR_SDMMC_OK) { + return err; + } + if (out_status) { + *out_status = MMC_R1(cmd.response); + } + return ERR_SDMMC_OK; +} + +ft_error_t Sdmmc_SendCmdSwitch(Sdmmc_Card_t* card) +{ + size_t datalen = 64; + ft_error_t err; + u32* buf = (u32*) Sdmmc_HeapMalloc(datalen); + if (buf == NULL) { + return ERR_SDMMC_NO_MEM; + } + //memset(buf, 0, sizeof(u32) * datalen); + // Sdmmc_Cmd_t cmd = { + // .opcode = MMC_SWITCH, + // .arg = 0x00FFFFF1, + // .flags = SCF_CMD_ADTC | SCF_RSP_R1, + // .cmd_resp_type = SCT_RESP_SHORT, + // .data = buf, + // .datalen = datalen, + // .blklen = datalen + // }; + // ft_error_t err = Sdmmc_SendCmd(card, &cmd); + // if (ERR_SDMMC_OK != err){ + // goto _EXIT; + // } + + // memset(buf, 0, sizeof(u32) * datalen); + // Sdmmc_Cmd_t cmd2 = { + // .opcode = MMC_SWITCH, + // .arg = 0x80FFFFF1, + // .flags = SCF_CMD_ADTC | SCF_RSP_R1, + // .cmd_resp_type = SCT_RESP_SHORT, + // .data = buf, + // .datalen = datalen, + // .blklen = datalen + // }; + // err = Sdmmc_SendCmd(card, &cmd2); + // if (ERR_SDMMC_OK != err){ + // goto _EXIT; + // } + + memset(buf, 0, datalen); + Sdmmc_Cmd_t cmd3 = { + .opcode = MMC_SWITCH, + .arg = 0x00000002, + .flags = SCF_CMD_ADTC | SCF_RSP_R1, + .cmd_resp_type = SCT_RESP_SHORT, + //.data = buf, + //.datalen = datalen, + //.blklen = datalen + }; + err = Sdmmc_sendAppCmd(card, &cmd3); + +_EXIT: + Sdmmc_HeapFree(buf); + return err; +} + +ft_error_t Sdmmc_WriteSectors(Sdmmc_Card_t* card, const void* src, + size_t start_block, size_t block_count) +{ + ft_error_t err = ERR_SDMMC_OK; + size_t block_size = card->csd.sectorSize; + if ((Sdmmc_DMACapable(src)) && ((intptr_t)src % 4 == 0)) { + err = Sdmmc_WriteSectorsDMA(card, src, start_block, block_count); + } else { + // SDMMC peripheral needs DMA-capable buffers. Split the write into + // separate single block writes, if needed, and allocate a temporary + // DMA-capable buffer. + void* tmp_buf = Sdmmc_HeapMalloc(block_size); + if (tmp_buf == NULL) { + return ERR_SDMMC_NO_MEM; + } + const u8* cur_src = (const u8*) src; + for (size_t i = 0; i < block_count; ++i) { + memcpy(tmp_buf, cur_src, block_size); + cur_src += block_size; + err = Sdmmc_WriteSectorsDMA(card, tmp_buf, start_block + i, 1); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_D("%s: error 0x%x writing block %d+%d", + __func__, err, start_block, i); + break; + } + } + FT_SDMMC_DEBUG_D("before free"); + Sdmmc_HeapFree(tmp_buf); + } + + return err; +} + +ft_error_t Sdmmc_WriteSectorsDMA(Sdmmc_Card_t* card, const void* src, + size_t start_block, size_t block_count) +{ + if (start_block + block_count > (size_t)card->csd.capacity) { + return ERR_SDMMC_INVALID_SIZE; + } + size_t block_size = card->csd.sectorSize; + Sdmmc_Cmd_t cmd = { + .flags = SCF_CMD_ADTC | SCF_RSP_R1, + .cmd_resp_type = SCT_RESP_SHORT, + .blklen = block_size, + .data = (void*) src, + .datalen = block_count * block_size, + .timeout_ms = SDMMC_WRITE_CMD_TIMEOUT_MS + }; + if (block_count == 1) { + cmd.opcode = MMC_WRITE_BLOCK_SINGLE; + } else { + cmd.opcode = MMC_WRITE_BLOCK_MULTIPLE; + } + if (card->ocr & SD_OCR_SDHC_CAP) { + cmd.arg = start_block; + } else { + cmd.arg = start_block * block_size; + } + ft_error_t err = Sdmmc_SendCmd(card, &cmd); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E("%s: Sdmmc_SendCmd returned 0x%x", __func__, err); + return err; + } + u32 status = 0; + size_t count = 0; + while (!Sdmmc_IsHostSpi(card) && !(status & MMC_R1_READY_FOR_DATA)) { + // TODO: add some timeout here + err = Sdmmc_SendCmdSendStatus(card, &status); + if (err != ERR_SDMMC_OK) { + return err; + } + if (++count % 10 == 0) { + FT_SDMMC_DEBUG_V( "waiting for card to become ready (%d)", count); + } + } + return ERR_SDMMC_OK; +} + +ft_error_t Sdmmc_ReadSectors(Sdmmc_Card_t* card, void* dst, + size_t start_block, size_t block_count) +{ + ft_error_t err = ERR_SDMMC_OK; + size_t block_size = card->csd.sectorSize; + FT_SDMMC_DEBUG_I("Sdmmc_ReadSectors dst 0x%x", dst); + if (Sdmmc_DMACapable(dst) && (intptr_t)dst % 4 == 0) { + FT_SDMMC_DEBUG_I("1"); + err = Sdmmc_ReadSectorsDMA(card, dst, start_block, block_count); + } else { + // SDMMC peripheral needs DMA-capable buffers. Split the read into + // separate single block reads, if needed, and allocate a temporary + // DMA-capable buffer. + FT_SDMMC_DEBUG_I("2"); + void* tmp_buf = Sdmmc_HeapMalloc(block_size); + if (tmp_buf == NULL) { + return ERR_SDMMC_NO_MEM; + } + u8* cur_dst = (u8*) dst; + for (size_t i = 0; i < block_count; ++i) { + err = Sdmmc_ReadSectorsDMA(card, tmp_buf, start_block + i, 1); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_D("%s: error 0x%x writing block %d+%d", + __func__, err, start_block, i); + break; + } + memcpy(cur_dst, tmp_buf, block_size); + cur_dst += block_size; + } + Sdmmc_HeapFree(tmp_buf); + } + return err; +} + +ft_error_t Sdmmc_ReadSectorsDMA(Sdmmc_Card_t* card, void* dst, + size_t start_block, size_t block_count) +{ + if (start_block + block_count > (size_t)card->csd.capacity) { + return ERR_SDMMC_INVALID_SIZE; + } + size_t block_size = card->csd.sectorSize; + Sdmmc_Cmd_t cmd = { + .flags = SCF_CMD_ADTC | SCF_CMD_READ | SCF_RSP_R1, + .cmd_resp_type = SCT_RESP_SHORT, + .blklen = block_size, + .data = (void*) dst, + .datalen = block_count * block_size + }; + if (block_count == 1) { + cmd.opcode = MMC_READ_BLOCK_SINGLE; + } else { + cmd.opcode = MMC_READ_BLOCK_MULTIPLE; + } + if (card->ocr & SD_OCR_SDHC_CAP) { + cmd.arg = start_block; + } else { + cmd.arg = start_block * block_size; + } + ft_error_t err = Sdmmc_SendCmd(card, &cmd); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E("%s: Sdmmc_SendCmd returned 0x%x", __func__, err); + return err; + } + u32 status = 0; + size_t count = 0; + while (!Sdmmc_IsHostSpi(card) && !(status & MMC_R1_READY_FOR_DATA)) { + // TODO: add some timeout here + err = Sdmmc_SendCmdSendStatus(card, &status); + if (err != ERR_SDMMC_OK) { + return err; + } + if (++count % 10 == 0) { + FT_SDMMC_DEBUG_V( "waiting for card to become ready (%d)", count); + } + } + return ERR_SDMMC_OK; +} + diff --git a/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc_cmd.h b/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc_cmd.h new file mode 100644 index 0000000000000000000000000000000000000000..d725b02b6f779c791ac6b3d58463cabf2485e502 --- /dev/null +++ b/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc_cmd.h @@ -0,0 +1,88 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-08 13:27:51 + * @LastEditTime: 2021-04-14 10:44:46 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef _FT_SDMMC_CMD_H_ +#define _FT_SDMMC_CMD_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ft_error_code.h" +#include "ft_sdmmc_defs.h" +#include "ft_sdmmc.h" + +#define FILE void + +/** + * Probe and initialize SD/MMC card using given host + * + * @note Only SD cards (SDSC and SDHC/SDXC) are supported now. + * Support for MMC/eMMC cards will be added later. + * + * @param host pointer to structure defining host controller + * @param out_card pointer to structure which will receive information + * about the card when the function completes + * @return + * - ESP_OK on success + * - One of the error codes from SDMMC host controller + */ +ft_error_t Sdmmc_CardInit(const Sdmmc_Host_t* host, + Sdmmc_Card_t* out_card); + +/** + * @brief Print information about the card to a stream + * @param stream stream obtained using fopen or fdopen + * @param card card information structure initialized using Sdmmc_CardInit + */ +void Sdmmc_CardPrintInfo(FILE* stream, const Sdmmc_Card_t* card); + +/** + * Write given number of sectors to SD/MMC card + * + * @param card pointer to card information structure previously initialized + * using Sdmmc_CardInit + * @param src pointer to data buffer to read data from; data size must be + * equal to sector_count * card->csd.sectorSize + * @param start_sector sector where to start writing + * @param sector_count number of sectors to write + * @return + * - ESP_OK on success + * - One of the error codes from SDMMC host controller + */ +ft_error_t Sdmmc_WriteSectors(Sdmmc_Card_t* card, const void* src, + size_t start_sector, size_t sector_count); + +/** + * Write given number of sectors to SD/MMC card + * + * @param card pointer to card information structure previously initialized + * using Sdmmc_CardInit + * @param dst pointer to data buffer to write into; buffer size must be + * at least sector_count * card->csd.sectorSize + * @param start_sector sector where to start reading + * @param sector_count number of sectors to read + * @return + * - ESP_OK on success + * - One of the error codes from SDMMC host controller + */ +ft_error_t Sdmmc_ReadSectors(Sdmmc_Card_t* card, void* dst, + size_t start_sector, size_t sector_count); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc_common.c b/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc_common.c new file mode 100644 index 0000000000000000000000000000000000000000..983102efde027554eb5e6b6133aedd9a04264c7d --- /dev/null +++ b/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc_common.c @@ -0,0 +1,318 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-08 13:45:15 + * @LastEditTime: 2021-04-14 15:49:41 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include +#include +#include +#include "ft_sdmmc_common.h" +#include "ft_sdmmc_cmd.h" +#include "ft_sdmmc.h" + +static const char* TAG = "sdmmc_common"; + +ft_error_t Sdmmc_InitOCR(Sdmmc_Card_t* card) +{ + ft_error_t err; + /* In SPI mode, READ_OCR (CMD58) command is used to figure out which voltage + * ranges the card can support. This step is skipped since 1.8V isn't + * supported on the ESP32. + */ + + u32 host_ocr = Sdmmc_GetHostOCR(card->host.io_voltage); + if ((card->ocr & SD_OCR_SDHC_CAP) != 0) { + host_ocr |= SD_OCR_SDHC_CAP; + } + /* Send SEND_OP_COND (ACMD41) command to the card until it becomes ready. */ + err = Sdmmc_SendCmdSendOpCond(card, host_ocr, &card->ocr); + + /* If time-out, re-try send_op_cond as MMC */ + if (err == ERR_SDMMC_TIMEOUT && !Sdmmc_IsHostSpi(card)) { + FT_SDMMC_DEBUG_D("send_op_cond timeout, trying MMC"); + card->is_mmc = 1; + err = Sdmmc_SendCmdSendOpCond(card, host_ocr, &card->ocr); + } + + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E("%s: send_op_cond (1) returned 0x%x", __func__, err); + return err; + } + if (Sdmmc_IsHostSpi(card)) { + err = Sdmmc_SendCmdReadOCR(card, &card->ocr); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E("%s: read_ocr returned 0x%x", __func__, err); + return err; + } + } + FT_SDMMC_DEBUG_D("host_ocr=0x%x card_ocr=0x%x", host_ocr, card->ocr); + + /* Clear all voltage bits in host's OCR which the card doesn't support. + * Don't touch CCS bit because in SPI mode cards don't report CCS in ACMD41 + * response. + */ + host_ocr &= (card->ocr | (~SD_OCR_VOL_MASK)); + FT_SDMMC_DEBUG_D("Sdmmc_CardInit: host_ocr=%08x, card_ocr=%08x", host_ocr, card->ocr); + return ERR_SDMMC_OK; +} + +ft_error_t Sdmmc_InitCID(Sdmmc_Card_t* card) +{ + ft_error_t err; + Sdmmc_Resp_t raw_cid; + if (!Sdmmc_IsHostSpi(card)) { + err = Sdmmc_SendCmdAllSendCID(card, &raw_cid); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E("%s: all_send_cid returned 0x%x", __func__, err); + return err; + } + if (!card->is_mmc) { + err = Sdmmc_DecodeCID(raw_cid, &card->cid); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E("%s: decoding CID failed (0x%x)", __func__, err); + return err; + } + } else { + /* For MMC, need to know CSD to decode CID. But CSD can only be read + * in data transfer mode, and it is not possible to read CID in data + * transfer mode. We temporiliy store the raw cid and do the + * decoding after the RCA is set and the card is in data transfer + * mode. + */ + memcpy(card->raw_cid, raw_cid, sizeof(Sdmmc_Resp_t)); + } + } else { + err = Sdmmc_SendCmdSendCID(card, &card->cid); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E("%s: send_cid returned 0x%x", __func__, err); + return err; + } + } + return ERR_SDMMC_OK; +} + +ft_error_t Sdmmc_InitRCA(Sdmmc_Card_t* card) +{ + ft_error_t err; + err = Sdmmc_SendCmdSetRelativeAddr(card, &card->rca); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E("%s: set_relative_addr returned 0x%x", __func__, err); + return err; + } + return ERR_SDMMC_OK; +} + +ft_error_t Sdmmc_InitMMCDecodeCID(Sdmmc_Card_t* card) +{ + ft_error_t err; + Sdmmc_Resp_t raw_cid; + memcpy(raw_cid, card->raw_cid, sizeof(raw_cid)); + err = Sdmmc_MMCDecodeCID(card->csd.mmcVer, raw_cid, &card->cid); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E("%s: decoding CID failed (0x%x)", __func__, err); + return err; + } + return ERR_SDMMC_OK; +} + +ft_error_t Sdmmc_InitCSD(Sdmmc_Card_t* card) +{ + //FT_SDMMC_DEBUG_I("is mem: %d", card->is_mem); + assert(card->is_mem == 1); + /* Get and decode the contents of CSD register. Determine card capacity. */ + ft_error_t err = Sdmmc_SendCmdSendCSD(card, &card->csd); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E("%s: send_csd returned 0x%x", __func__, err); + return err; + } + const size_t max_sdsc_capacity = UINT32_MAX / card->csd.sectorSize + 1; + if (!(card->ocr & SD_OCR_SDHC_CAP) && + card->csd.capacity > (int)max_sdsc_capacity) { + FT_SDMMC_DEBUG_W("%s: SDSC card reports capacity=%u. Limiting to %u.", + __func__, card->csd.capacity, max_sdsc_capacity); + card->csd.capacity = max_sdsc_capacity; + } + return ERR_SDMMC_OK; +} + +ft_error_t Sdmmc_InitSelectCard(Sdmmc_Card_t* card) +{ + assert(!Sdmmc_IsHostSpi(card)); + ft_error_t err = Sdmmc_SendCmdSelectCard(card, card->rca); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E("%s: select_card returned 0x%x", __func__, err); + return err; + } + return ERR_SDMMC_OK; +} + +ft_error_t Sdmmc_InitCardHsMode(Sdmmc_Card_t* card) +{ + ft_error_t err = ERR_SDMMC_NOT_SUPPORTED; + if (card->is_mem && !card->is_mmc) { + err = Sdmmc_EnableHsModeAndCheck(card); + } /*else if (card->is_sdio) { + err = sdmmc_io_enable_hs_mode(card); + } */else if (card->is_mmc){ + err = Sdmmc_MMCEnableHsMode(card); + } + if (err == ERR_SDMMC_NOT_SUPPORTED) { + FT_SDMMC_DEBUG_D("%s: host supports HS mode, but card doesn't", __func__); + card->max_freq_khz = SDMMC_FREQ_DEFAULT; + } else if (err != ERR_SDMMC_OK) { + return err; + } + return ERR_SDMMC_OK; +} + +ft_error_t Sdmmc_InitHostBusWidth(Sdmmc_Card_t* card) +{ + int bus_width = 1; + + if ((card->host.flags & SDMMC_HOST_FLAG_4BIT) && + (card->log_bus_width == 2)) { + bus_width = 4; + } else if ((card->host.flags & SDMMC_HOST_FLAG_8BIT) && + (card->log_bus_width == 3)) { + bus_width = 8; + } + FT_SDMMC_DEBUG_D("%s: using %d-bit bus", __func__, bus_width); + if (bus_width > 1) { + ft_error_t err = (*card->host.set_bus_width)(card->host.slot, bus_width); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E("host.set_bus_width failed (0x%x)", err); + return err; + } + } + return ERR_SDMMC_OK; +} + +ft_error_t Sdmmc_InitHostFreq(Sdmmc_Card_t* card) +{ + assert(card->max_freq_khz <= card->host.max_freq_khz); + + /* Find highest frequency in the following list, + * which is below card->max_freq_khz. + */ + const u32 freq_values[] = { + SDMMC_FREQ_52M, + SDMMC_FREQ_HIGHSPEED, + SDMMC_FREQ_26M, + SDMMC_FREQ_DEFAULT + //NOTE: in sdspi mode, 20MHz may not work. in that case, add 10MHz here. + }; + const int n_freq_values = sizeof(freq_values) / sizeof(freq_values[0]); + + u32 selected_freq = SDMMC_FREQ_PROBING; + for (int i = 0; i < n_freq_values; ++i) { + u32 freq = freq_values[i]; + if (card->max_freq_khz >= freq) { + selected_freq = freq; + break; + } + } + + FT_SDMMC_DEBUG_D("%s: using %d kHz bus frequency", __func__, selected_freq); + if (selected_freq > SDMMC_FREQ_PROBING) { + ft_error_t err = (*card->host.set_card_clk)(card->host.slot, selected_freq); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E("failed to switch bus frequency (0x%x)", err); + return err; + } + } + + if (card->is_ddr) { + if (card->host.set_bus_ddr_mode == NULL) { + FT_SDMMC_DEBUG_E("host doesn't support DDR mode or voltage switching"); + return ERR_SDMMC_NOT_SUPPORTED; + } + ft_error_t err = (*card->host.set_bus_ddr_mode)(card->host.slot, TRUE); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E("failed to switch bus to DDR mode (0x%x)", err); + return err; + } + } + return ERR_SDMMC_OK; +} + +void Sdmmc_FilpByteOrder(u32* response, size_t size) +{ + assert(size % (2 * sizeof(u32)) == 0); + const size_t n_words = size / sizeof(u32); + for (int i = 0; i < (int)n_words / 2; ++i) { + u32 left = __builtin_bswap32(response[i]); + u32 right = __builtin_bswap32(response[n_words - i - 1]); + response[i] = right; + response[n_words - i - 1] = left; + } +} + +void Sdmmc_CardPrintInfo(FILE* stream, const Sdmmc_Card_t* card) +{ + bool_t print_scr = FALSE; + bool_t print_csd = FALSE; + const char* type; + Sdmmc_Printf("Name: %s\n", card->cid.name); + if (card->is_sdio) { + type = "SDIO"; + print_scr = TRUE; + print_csd = TRUE; + } else if (card->is_mmc) { + type = "MMC"; + print_csd = TRUE; + } else { + type = (card->ocr & SD_OCR_SDHC_CAP) ? "SDHC/SDXC" : "SDSC"; + } + Sdmmc_Printf("Type: %s\n", type); + if (card->max_freq_khz < 1000) { + Sdmmc_Printf("Speed: %d kHz\n", card->max_freq_khz); + } else { + Sdmmc_Printf("Speed: %d MHz%s\n", card->max_freq_khz / 1000, + card->is_ddr ? ", DDR" : ""); + } + Sdmmc_Printf("Size: %lluMB\n", ((uint64_t) card->csd.capacity) * card->csd.sectorSize / (1024 * 1024)); + + if (print_csd) { + Sdmmc_Printf("CSD: ver=%d, sectorSize=%d, capacity=%d read_bl_len=%d\n", + card->csd.csdVer, + card->csd.sectorSize, card->csd.capacity, card->csd.readBlkLen); + } + if (print_scr) { + Sdmmc_Printf("SCR: sdSpec=%d, bus_width=%d\n", card->scr.sdSpec, card->scr.bus_width); + } +} + +ft_error_t Sdmmc_FixHostFlags(Sdmmc_Card_t* card) +{ + const u32 width_1bit = SDMMC_HOST_FLAG_1BIT; + const u32 width_4bit = SDMMC_HOST_FLAG_4BIT; + const u32 width_8bit = SDMMC_HOST_FLAG_8BIT; + const u32 width_mask = width_1bit | width_4bit | width_8bit; + + int slot_bit_width = card->host.get_bus_width(card->host.slot); + if (slot_bit_width == 1 && + (card->host.flags & (width_4bit | width_8bit))) { + card->host.flags &= ~width_mask; + card->host.flags |= width_1bit; + } else if (slot_bit_width == 4 && (card->host.flags & width_8bit)) { + if ((card->host.flags & width_4bit) == 0) { + FT_SDMMC_DEBUG_W("slot width set to 4, but host flags don't have 4 line mode enabled; using 1 line mode"); + card->host.flags &= ~width_mask; + card->host.flags |= width_1bit; + } else { + card->host.flags &= ~width_mask; + card->host.flags |= width_4bit; + } + } + + return ERR_SDMMC_OK; +} diff --git a/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc_common.h b/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc_common.h new file mode 100644 index 0000000000000000000000000000000000000000..d81bcb9565fefb2e30ce6b29b4278f4059b624cf --- /dev/null +++ b/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc_common.h @@ -0,0 +1,178 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-08 13:45:05 + * @LastEditTime: 2021-04-15 15:12:03 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef _FT_SDMMC_COMMON_H_ +#define _FT_SDMMC_COMMON_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ft_types.h" +#include "ft_debug.h" +#include "ft_error_code.h" +#include "ft_sdmmc.h" + +#define SDMMC_GO_IDLE_DELAY_MS 20 +#define SDMMC_IO_SEND_OP_COND_DELAY_MS 10 + +/* These delay values are mostly useful for cases when CD pin is not used, and + * the card is removed. In this case, SDMMC peripheral may not always return + * CMD_DONE / DATA_DONE interrupts after signaling the error. These timeouts work + * as a safety net in such cases. + */ +#define SDMMC_DEFAULT_CMD_TIMEOUT_MS 1000 // Max timeout of ordinary commands +#define SDMMC_WRITE_CMD_TIMEOUT_MS 5000 // Max timeout of write commands + +/* Maximum retry/error count for SEND_OP_COND (CMD1). + * These are somewhat arbitrary, values originate from OpenBSD driver. + */ +#define SDMMC_SEND_OP_COND_MAX_RETRIES 100 +#define SDMMC_SEND_OP_COND_MAX_ERRORS 3 + +/* Functions to send individual commands */ +ft_error_t Sdmmc_SendCmd(Sdmmc_Card_t* card, Sdmmc_Cmd_t* cmd); +ft_error_t Sdmmc_SendAppCmd(Sdmmc_Card_t* card, Sdmmc_Cmd_t* cmd); +ft_error_t Sdmmc_SendCmdGoIdleState(Sdmmc_Card_t* card); +ft_error_t Sdmmc_SendCmdSendIfCond(Sdmmc_Card_t* card, u32 ocr); +ft_error_t Sdmmc_SendCmdSendOpCond(Sdmmc_Card_t* card, u32 ocr, u32 *ocrp); +ft_error_t Sdmmc_SendCmdReadOCR(Sdmmc_Card_t *card, u32 *ocrp); +ft_error_t Sdmmc_SendCmdSendCID(Sdmmc_Card_t *card, Sdmmc_CID_t *out_cid); +ft_error_t Sdmmc_SendCmdAllSendCID(Sdmmc_Card_t* card, Sdmmc_Resp_t* out_raw_cid); +ft_error_t Sdmmc_SendCmdSetRelativeAddr(Sdmmc_Card_t* card, u16* out_rca); +ft_error_t Sdmmc_SendCmdSetBlkLen(Sdmmc_Card_t* card, Sdmmc_CSD_t* csd); +ft_error_t Sdmmc_SendCmdSwitchFunc(Sdmmc_Card_t* card, + u32 mode, u32 group, u32 function, + Sdmmc_SwitchFuncRsp_t* resp); +ft_error_t Sdmmc_SendCmdSendCSD(Sdmmc_Card_t* card, Sdmmc_CSD_t* out_csd); +ft_error_t Sdmmc_SendCmdSelectCard(Sdmmc_Card_t* card, u32 rca); +ft_error_t Sdmmc_SendCmdSendSCR(Sdmmc_Card_t* card, Sdmmc_SCR_t *out_scr); +ft_error_t Sdmmc_SendCmdSwitch(Sdmmc_Card_t *card); +ft_error_t Sdmmc_SendCmdSetBusWidth(Sdmmc_Card_t* card, int width); +ft_error_t Sdmmc_SendCmdSendStatus(Sdmmc_Card_t* card, u32* out_status); +ft_error_t Sdmmc_SendCmdCrcOnOff(Sdmmc_Card_t* card, bool_t crc_enable); + +/* Higher level functions */ +ft_error_t Sdmmc_EnableHsMode(Sdmmc_Card_t* card); +ft_error_t Sdmmc_EnableHsModeAndCheck(Sdmmc_Card_t* card); +ft_error_t Sdmmc_WriteSectorsDMA(Sdmmc_Card_t* card, const void* src, + size_t start_block, size_t block_count); +ft_error_t Sdmmc_ReadSectorsDMA(Sdmmc_Card_t* card, void* dst, + size_t start_block, size_t block_count); + +/* SD specific */ +ft_error_t Sdmmc_CheckSCR(Sdmmc_Card_t* card); +ft_error_t Sdmmc_DecodeCID(Sdmmc_Resp_t resp, Sdmmc_CID_t* out_cid); +ft_error_t Sdmmc_DecodeCSD(Sdmmc_Resp_t response, Sdmmc_CSD_t* out_csd); +ft_error_t Sdmmc_DecodeSCR(u32 *raw_scr, Sdmmc_SCR_t* out_scr); + +/* MMC specific */ +ft_error_t Sdmmc_MMCSendExtCSDData(Sdmmc_Card_t* card, void *out_data, size_t datalen); +ft_error_t Sdmmc_MMCSwitch(Sdmmc_Card_t* card, u8 set, u8 index, u8 value); +ft_error_t Sdmmc_MMCDecodeCID(int mmcVer, Sdmmc_Resp_t resp, Sdmmc_CID_t* out_cid); +ft_error_t Sdmmc_MMCDecodeCSD(Sdmmc_Resp_t response, Sdmmc_CSD_t* out_csd); +ft_error_t Sdmmc_MMCEnableHsMode(Sdmmc_Card_t* card); + +/* Parts of card initialization flow */ +ft_error_t Sdmmc_InitSdIfCond(Sdmmc_Card_t* card); +ft_error_t Sdmmc_InitSelectCard(Sdmmc_Card_t* card); +ft_error_t Sdmmc_InitCSD(Sdmmc_Card_t* card); +ft_error_t Sdmmc_InitCID(Sdmmc_Card_t* card); +ft_error_t Sdmmc_InitRCA(Sdmmc_Card_t* card); +ft_error_t Sdmmc_InitMMCDecodeCID(Sdmmc_Card_t* card); +ft_error_t Sdmmc_InitOCR(Sdmmc_Card_t* card); +ft_error_t Sdmmc_InitSpiCrc(Sdmmc_Card_t* card); +//ft_error_t sdmmc_init_io(Sdmmc_Card_t* card); +ft_error_t Sdmmc_InitSdBlkLen(Sdmmc_Card_t* card); +ft_error_t Sdmmc_InitSdSCR(Sdmmc_Card_t* card); +ft_error_t Sdmmc_InitSwitchHs(Sdmmc_Card_t *card); +ft_error_t Sdmmc_InitSdWaitDataReady(Sdmmc_Card_t* card); +ft_error_t Sdmmc_InitMMCReadExtCSD(Sdmmc_Card_t* card); +ft_error_t Sdmmc_InitMMCReadCID(Sdmmc_Card_t* card); +ft_error_t Sdmmc_InitHostBusWidth(Sdmmc_Card_t* card); +ft_error_t Sdmmc_InitSdBusWidth(Sdmmc_Card_t* card); +//ft_error_t sdmmc_init_io_bus_width(Sdmmc_Card_t* card); +ft_error_t Sdmmc_InitMMCBusWidth(Sdmmc_Card_t* card); +ft_error_t Sdmmc_InitCardHsMode(Sdmmc_Card_t* card); +ft_error_t Sdmmc_InitHostFreq(Sdmmc_Card_t* card); +ft_error_t Sdmmc_InitMMCCheckCSD(Sdmmc_Card_t* card); + +/* Various helper functions */ +static inline bool_t Sdmmc_IsHostSpi(const Sdmmc_Card_t* card) +{ + return (card->host.flags & SDMMC_HOST_FLAG_SPI) != 0; +} + +static inline u32 Sdmmc_GetHostOCR(float voltage) +{ + // TODO: report exact voltage to the card + // For now tell that the host has 2.8-3.6V voltage range + (void) voltage; + return SD_OCR_VOL_MASK; +} + +void Sdmmc_FilpByteOrder(u32* response, size_t size); + +ft_error_t Sdmmc_FixHostFlags(Sdmmc_Card_t* card); + +/* define debug log function */ +//#define FT_SDMMC_DEBUG_ENABLED +#define FT_SDMMC_DEBUG_TAG "FT_SDMMC" +#define FT_SDMMC_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(FT_SDMMC_DEBUG_TAG, format, ##__VA_ARGS__) +#ifdef FT_SDMMC_DEBUG_ENABLED +#define FT_SDMMC_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FT_SDMMC_DEBUG_TAG, format, ##__VA_ARGS__) +#define FT_SDMMC_DEBUG_D(format, ...) FT_DEBUG_PRINT_D(FT_SDMMC_DEBUG_TAG, format, ##__VA_ARGS__) +#define FT_SDMMC_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FT_SDMMC_DEBUG_TAG, format, ##__VA_ARGS__) +#define FT_SDMMC_DEBUG_V(format, ...) FT_DEBUG_PRINT_V(FT_SDMMC_DEBUG_TAG, format, ##__VA_ARGS__) +#else +#define FT_SDMMC_DEBUG_I(format, ...) +#define FT_SDMMC_DEBUG_D(format, ...) +#define FT_SDMMC_DEBUG_W(format, ...) +#define FT_SDMMC_DEBUG_V(format, ...) +#endif + +/* define SD MMC error code */ +typedef enum +{ + ERR_SUB_MODE_SDMMC_GENERAL = 0 +}FT_SDMMC_ERR_SUB_MODE; + + +#define ERR_SDMMC_NO_MEM FT_CODE_ERR(ERR_MODE_SD_MMC, ERR_SUB_MODE_SDMMC_GENERAL, 0x1) /*!< Out of memory */ +#define ERR_SDMMC_INVALID_ARG FT_CODE_ERR(ERR_MODE_SD_MMC, ERR_SUB_MODE_SDMMC_GENERAL, 0x2) +#define ERR_SDMMC_INVALID_STATE FT_CODE_ERR(ERR_MODE_SD_MMC, ERR_SUB_MODE_SDMMC_GENERAL, 0x3) /*!< Invalid state */ +#define ERR_SDMMC_INVALID_SIZE FT_CODE_ERR(ERR_MODE_SD_MMC, ERR_SUB_MODE_SDMMC_GENERAL, 0x4) /*!< Invalid size */ +#define ERR_SDMMC_NOT_FOUND FT_CODE_ERR(ERR_MODE_SD_MMC, ERR_SUB_MODE_SDMMC_GENERAL, 0x5) /*!< Requested resource not found */ +#define ERR_SDMMC_NOT_SUPPORTED FT_CODE_ERR(ERR_MODE_SD_MMC, ERR_SUB_MODE_SDMMC_GENERAL, 0x6) /*!< Operation or feature not supported */ +#define ERR_SDMMC_TIMEOUT FT_CODE_ERR(ERR_MODE_SD_MMC, ERR_SUB_MODE_SDMMC_GENERAL, 0x7) /*!< Operation timed out */ +#define ERR_SDMMC_INVALID_RESPONSE FT_CODE_ERR(ERR_MODE_SD_MMC, ERR_SUB_MODE_SDMMC_GENERAL, 0x8) /*!< Received response was invalid */ +#define ERR_SDMMC_INVALID_CRC FT_CODE_ERR(ERR_MODE_SD_MMC, ERR_SUB_MODE_SDMMC_GENERAL, 0x9) /*!< CRC or checksum was invalid */ +#define ERR_SDMMC_INVALID_VERSION FT_CODE_ERR(ERR_MODE_SD_MMC, ERR_SUB_MODE_SDMMC_GENERAL, 0xa) /*!< Version was invalid */ +#define ERR_SDMMC_INVALID_MAC FT_CODE_ERR(ERR_MODE_SD_MMC, ERR_SUB_MODE_SDMMC_GENERAL, 0xb) /*!< MAC address was invalid */ +#define ERR_SDMMC_CARD_NOFOUND FT_CODE_ERR(ERR_MODE_SD_MMC, ERR_SUB_MODE_SDMMC_GENERAL, 0x10) /*!< SDMMC card not found */ + +#define ERR_SDMMC_WIFI_BASE FT_CODE_ERR(ERR_MODE_SD_MMC, ERR_SUB_MODE_SDMMC_GENERAL, 0xc) /*!< Starting number of WiFi error codes */ +#define ERR_SDMMC_MESH_BASE FT_CODE_ERR(ERR_MODE_SD_MMC, ERR_SUB_MODE_SDMMC_GENERAL, 0xd) /*!< Starting number of MESH error codes */ +#define ERR_SDMMC_FLASH_BASE FT_CODE_ERR(ERR_MODE_SD_MMC, ERR_SUB_MODE_SDMMC_GENERAL, 0xe) /*!< Starting number of flash error codes */ +#define ERR_SDMMC_NOTYET_INIT FT_CODE_ERR(ERR_MODE_SD_MMC, ERR_SUB_MODE_SDMMC_GENERAL, 0xf) /*!< Starting number of flash error codes */ + +#define ERR_SDMMC_OK ERR_SUCCESS + + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc_defs.h b/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc_defs.h new file mode 100644 index 0000000000000000000000000000000000000000..c247fe46fa2a82b597b6a218e1d7c06cb9bdd5dd --- /dev/null +++ b/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc_defs.h @@ -0,0 +1,501 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-08 11:50:06 + * @LastEditTime: 2021-04-13 10:50:52 + * @Description:  This files is for sdmmc cmd definition + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + * 0.2.0 Zhu Gengyu 2021/4/8 init + */ + +#ifndef _FT_SDMMC_DEFS_H_ +#define _FT_SDMMC_DEFS_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include "ft_types.h" + +#define BIT(nr) (1UL << (nr)) +#define BIT64(nr) (1ULL << (nr)) + +/* MMC commands */ /* response type */ +#define MMC_GO_IDLE_STATE 0 /* R0 */ +#define MMC_SEND_OP_COND 1 /* R3 */ +#define MMC_ALL_SEND_CID 2 /* R2 */ +#define MMC_SET_RELATIVE_ADDR 3 /* R1 */ +#define MMC_SWITCH 6 /* R1B */ +#define MMC_SELECT_CARD 7 /* R1 */ +#define MMC_SEND_EXT_CSD 8 /* R1 */ +#define MMC_SEND_CSD 9 /* R2 */ +#define MMC_SEND_CID 10 /* R1 */ +#define MMC_READ_DAT_UNTIL_STOP 11 /* R1 */ +#define MMC_STOP_TRANSMISSION 12 /* R1B */ +#define MMC_SEND_STATUS 13 /* R1 */ +#define MMC_SET_BLOCKLEN 16 /* R1 */ +#define MMC_READ_BLOCK_SINGLE 17 /* R1 */ +#define MMC_READ_BLOCK_MULTIPLE 18 /* R1 */ +#define MMC_WRITE_DAT_UNTIL_STOP 20 /* R1 */ +#define MMC_SET_BLOCK_COUNT 23 /* R1 */ +#define MMC_WRITE_BLOCK_SINGLE 24 /* R1 */ +#define MMC_WRITE_BLOCK_MULTIPLE 25 /* R1 */ +#define MMC_APP_CMD 55 /* R1 */ + +/* SD commands */ /* response type */ +#define SD_SEND_RELATIVE_ADDR 3 /* R6 */ +#define SD_SEND_SWITCH_FUNC 6 /* R1 */ +#define SD_SEND_IF_COND 8 /* R7 */ +#define SD_READ_OCR 58 /* R3 */ +#define SD_CRC_ON_OFF 59 /* R1 */ + +/* SD application commands */ /* response type */ +#define SD_APP_SET_BUS_WIDTH 6 /* R1 */ +#define SD_APP_SD_STATUS 13 /* R2 */ +#define SD_APP_OP_COND 41 /* R3 */ +#define SD_APP_SEND_SCR 51 /* R1 */ + +/* SD IO commands */ +#define SD_IO_SEND_OP_COND 5 /* R4 */ +#define SD_IO_RW_DIRECT 52 /* R5 */ +#define SD_IO_RW_EXTENDED 53 /* R5 */ + + +/* OCR bits */ +#define MMC_OCR_MEM_READY (1<<31) /* memory power-up status bit */ +#define MMC_OCR_ACCESS_MODE_MASK 0x60000000 /* bits 30:29 */ +#define MMC_OCR_SECTOR_MODE (1<<30) +#define MMC_OCR_BYTE_MODE (1<<29) +#define MMC_OCR_3_5V_3_6V (1<<23) +#define MMC_OCR_3_4V_3_5V (1<<22) +#define MMC_OCR_3_3V_3_4V (1<<21) +#define MMC_OCR_3_2V_3_3V (1<<20) +#define MMC_OCR_3_1V_3_2V (1<<19) +#define MMC_OCR_3_0V_3_1V (1<<18) +#define MMC_OCR_2_9V_3_0V (1<<17) +#define MMC_OCR_2_8V_2_9V (1<<16) +#define MMC_OCR_2_7V_2_8V (1<<15) +#define MMC_OCR_2_6V_2_7V (1<<14) +#define MMC_OCR_2_5V_2_6V (1<<13) +#define MMC_OCR_2_4V_2_5V (1<<12) +#define MMC_OCR_2_3V_2_4V (1<<11) +#define MMC_OCR_2_2V_2_3V (1<<10) +#define MMC_OCR_2_1V_2_2V (1<<9) +#define MMC_OCR_2_0V_2_1V (1<<8) +#define MMC_OCR_1_65V_1_95V (1<<7) + +#define SD_OCR_SDHC_CAP (1<<30) +#define SD_OCR_VOL_MASK 0xFF8000 /* bits 23:15 */ + +/* SD mode R1 response type bits */ +#define MMC_R1_READY_FOR_DATA (1<<8) /* ready for next transfer */ +#define MMC_R1_APP_CMD (1<<5) /* app. commands supported */ +#define MMC_R1_SWITCH_ERROR (1<<7) /* switch command did not succeed */ + +/* SPI mode R1 response type bits */ +#define SD_SPI_R1_IDLE_STATE (1<<0) +#define SD_SPI_R1_ERASE_RST (1<<1) +#define SD_SPI_R1_ILLEGAL_CMD (1<<2) +#define SD_SPI_R1_CMD_CRC_ERR (1<<3) +#define SD_SPI_R1_ERASE_SEQ_ERR (1<<4) +#define SD_SPI_R1_ADDR_ERR (1<<5) +#define SD_SPI_R1_PARAM_ERR (1<<6) +#define SD_SPI_R1_NO_RESPONSE (1<<7) + +#define SDIO_R1_FUNC_NUM_ERR (1<<4) + +/* 48-bit response decoding (32 bits w/o CRC) */ +#define MMC_R1(resp) ((resp)[0]) +#define MMC_R3(resp) ((resp)[0]) +#define MMC_R4(resp) ((resp)[0]) +#define MMC_R5(resp) ((resp)[0]) +#define SD_R6(resp) ((resp)[0]) +#define MMC_R1_CURRENT_STATE(resp) (((resp)[0] >> 9) & 0xf) + +/* SPI mode response decoding */ +#define SD_SPI_R1(resp) ((resp)[0] & 0xff) +#define SD_SPI_R2(resp) ((resp)[0] & 0xffff) +#define SD_SPI_R3(resp) ((resp)[0]) +#define SD_SPI_R7(resp) ((resp)[0]) + +/* SPI mode data response decoding */ +#define SD_SPI_DATA_RSP_VALID(resp_byte) (((resp_byte)&0x11)==0x1) +#define SD_SPI_DATA_RSP(resp_byte) (((resp_byte)>>1)&0x7) +#define SD_SPI_DATA_ACCEPTED 0x2 +#define SD_SPI_DATA_CRC_ERROR 0x5 +#define SD_SPI_DATA_WR_ERROR 0x6 + +/* RCA argument and response */ +#define MMC_ARG_RCA(rca) ((rca) << 16) +#define SD_R6_RCA(resp) (SD_R6((resp)) >> 16) + +/* bus width argument */ +#define SD_ARG_BUS_WIDTH_1 0 +#define SD_ARG_BUS_WIDTH_4 2 + +/* EXT_CSD fields */ +#define EXT_CSD_BUS_WIDTH 183 /* WO */ +#define EXT_CSD_HS_TIMING 185 /* R/W */ +#define EXT_CSD_REV 192 /* RO */ +#define EXT_CSD_STRUCTURE 194 /* RO */ +#define EXT_CSD_CARD_TYPE 196 /* RO */ +#define EXT_CSD_SEC_COUNT 212 /* RO */ +#define EXT_CSD_PWR_CL_26_360 203 /* RO */ +#define EXT_CSD_PWR_CL_52_360 202 /* RO */ +#define EXT_CSD_PWR_CL_26_195 201 /* RO */ +#define EXT_CSD_PWR_CL_52_195 200 /* RO */ +#define EXT_CSD_POWER_CLASS 187 /* R/W */ +#define EXT_CSD_CMD_SET 191 /* R/W */ +#define EXT_CSD_S_CMD_SET 504 /* RO */ + +/* EXT_CSD field definitions */ +#define EXT_CSD_CMD_SET_NORMAL (1U << 0) +#define EXT_CSD_CMD_SET_SECURE (1U << 1) +#define EXT_CSD_CMD_SET_CPSECURE (1U << 2) + +/* EXT_CSD_HS_TIMING */ +#define EXT_CSD_HS_TIMING_BC 0 +#define EXT_CSD_HS_TIMING_HS 1 +#define EXT_CSD_HS_TIMING_HS200 2 +#define EXT_CSD_HS_TIMING_HS400 3 + +/* EXT_CSD_BUS_WIDTH */ +#define EXT_CSD_BUS_WIDTH_1 0 +#define EXT_CSD_BUS_WIDTH_4 1 +#define EXT_CSD_BUS_WIDTH_8 2 +#define EXT_CSD_BUS_WIDTH_4_DDR 5 +#define EXT_CSD_BUS_WIDTH_8_DDR 6 + +/* EXT_CSD_CARD_TYPE */ +/* The only currently valid values for this field are 0x01, 0x03, 0x07, + * 0x0B and 0x0F. */ +#define EXT_CSD_CARD_TYPE_F_26M (1 << 0) /* SDR at "rated voltages */ +#define EXT_CSD_CARD_TYPE_F_52M (1 << 1) /* SDR at "rated voltages */ +#define EXT_CSD_CARD_TYPE_F_52M_1_8V (1 << 2) /* DDR, 1.8V or 3.3V I/O */ +#define EXT_CSD_CARD_TYPE_F_52M_1_2V (1 << 3) /* DDR, 1.2V I/O */ +#define EXT_CSD_CARD_TYPE_26M 0x01 +#define EXT_CSD_CARD_TYPE_52M 0x03 +#define EXT_CSD_CARD_TYPE_52M_V18 0x07 +#define EXT_CSD_CARD_TYPE_52M_V12 0x0b +#define EXT_CSD_CARD_TYPE_52M_V12_18 0x0f + +/* EXT_CSD MMC */ +#define EXT_CSD_MMC_SIZE 512 + +/* MMC_SWITCH access mode */ +#define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */ +#define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits in value */ +#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits in value */ +#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */ + +/* MMC R2 response (CSD) */ +#define MMC_CSD_CSDVER(resp) MMC_RSP_BITS((resp), 126, 2) +#define MMC_CSD_CSDVER_1_0 1 +#define MMC_CSD_CSDVER_2_0 2 +#define MMC_CSD_CSDVER_EXT_CSD 3 +#define MMC_CSD_MMCVER(resp) MMC_RSP_BITS((resp), 122, 4) +#define MMC_CSD_MMCVER_1_0 0 /* MMC 1.0 - 1.2 */ +#define MMC_CSD_MMCVER_1_4 1 /* MMC 1.4 */ +#define MMC_CSD_MMCVER_2_0 2 /* MMC 2.0 - 2.2 */ +#define MMC_CSD_MMCVER_3_1 3 /* MMC 3.1 - 3.3 */ +#define MMC_CSD_MMCVER_4_0 4 /* MMC 4 */ +#define MMC_CSD_READ_BL_LEN(resp) MMC_RSP_BITS((resp), 80, 4) +#define MMC_CSD_C_SIZE(resp) MMC_RSP_BITS((resp), 62, 12) +#define MMC_CSD_CAPACITY(resp) ((MMC_CSD_C_SIZE((resp))+1) << \ + (MMC_CSD_C_SIZE_MULT((resp))+2)) +#define MMC_CSD_C_SIZE_MULT(resp) MMC_RSP_BITS((resp), 47, 3) + +/* MMC v1 R2 response (CID) */ +#define MMC_CID_MID_V1(resp) MMC_RSP_BITS((resp), 104, 24) +#define MMC_CID_PNM_V1_CPY(resp, pnm) \ + do { \ + (pnm)[0] = MMC_RSP_BITS((resp), 96, 8); \ + (pnm)[1] = MMC_RSP_BITS((resp), 88, 8); \ + (pnm)[2] = MMC_RSP_BITS((resp), 80, 8); \ + (pnm)[3] = MMC_RSP_BITS((resp), 72, 8); \ + (pnm)[4] = MMC_RSP_BITS((resp), 64, 8); \ + (pnm)[5] = MMC_RSP_BITS((resp), 56, 8); \ + (pnm)[6] = MMC_RSP_BITS((resp), 48, 8); \ + (pnm)[7] = '\0'; \ + } while (0) +#define MMC_CID_REV_V1(resp) MMC_RSP_BITS((resp), 40, 8) +#define MMC_CID_PSN_V1(resp) MMC_RSP_BITS((resp), 16, 24) +#define MMC_CID_MDT_V1(resp) MMC_RSP_BITS((resp), 8, 8) + +/* MMC v2 R2 response (CID) */ +#define MMC_CID_MID_V2(resp) MMC_RSP_BITS((resp), 120, 8) +#define MMC_CID_OID_V2(resp) MMC_RSP_BITS((resp), 104, 16) +#define MMC_CID_PNM_V2_CPY(resp, pnm) \ + do { \ + (pnm)[0] = MMC_RSP_BITS((resp), 96, 8); \ + (pnm)[1] = MMC_RSP_BITS((resp), 88, 8); \ + (pnm)[2] = MMC_RSP_BITS((resp), 80, 8); \ + (pnm)[3] = MMC_RSP_BITS((resp), 72, 8); \ + (pnm)[4] = MMC_RSP_BITS((resp), 64, 8); \ + (pnm)[5] = MMC_RSP_BITS((resp), 56, 8); \ + (pnm)[6] = '\0'; \ + } while (0) +#define MMC_CID_PSN_V2(resp) MMC_RSP_BITS((resp), 16, 32) + +/* SD R2 response (CSD) */ +#define SD_CSD_CSDVER(resp) MMC_RSP_BITS((resp), 126, 2) +#define SD_CSD_CSDVER_1_0 0 +#define SD_CSD_CSDVER_2_0 1 +#define SD_CSD_TAAC(resp) MMC_RSP_BITS((resp), 112, 8) +#define SD_CSD_TAAC_1_5_MSEC 0x26 +#define SD_CSD_NSAC(resp) MMC_RSP_BITS((resp), 104, 8) +#define SD_CSD_SPEED(resp) MMC_RSP_BITS((resp), 96, 8) +#define SD_CSD_SPEED_25_MHZ 0x32 +#define SD_CSD_SPEED_50_MHZ 0x5a +#define SD_CSD_CCC(resp) MMC_RSP_BITS((resp), 84, 12) +#define SD_CSD_CCC_BASIC (1 << 0) /* basic */ +#define SD_CSD_CCC_BR (1 << 2) /* block read */ +#define SD_CSD_CCC_BW (1 << 4) /* block write */ +#define SD_CSD_CCC_ERASE (1 << 5) /* erase */ +#define SD_CSD_CCC_WP (1 << 6) /* write protection */ +#define SD_CSD_CCC_LC (1 << 7) /* lock card */ +#define SD_CSD_CCC_AS (1 << 8) /*application specific*/ +#define SD_CSD_CCC_IOM (1 << 9) /* I/O mode */ +#define SD_CSD_CCC_SWITCH (1 << 10) /* switch */ +#define SD_CSD_READ_BL_LEN(resp) MMC_RSP_BITS((resp), 80, 4) +#define SD_CSD_READ_BL_PARTIAL(resp) MMC_RSP_BITS((resp), 79, 1) +#define SD_CSD_WRITE_BLK_MISALIGN(resp) MMC_RSP_BITS((resp), 78, 1) +#define SD_CSD_READ_BLK_MISALIGN(resp) MMC_RSP_BITS((resp), 77, 1) +#define SD_CSD_DSR_IMP(resp) MMC_RSP_BITS((resp), 76, 1) +#define SD_CSD_C_SIZE(resp) MMC_RSP_BITS((resp), 62, 12) +#define SD_CSD_CAPACITY(resp) ((SD_CSD_C_SIZE((resp))+1) << \ + (SD_CSD_C_SIZE_MULT((resp))+2)) +#define SD_CSD_V2_C_SIZE(resp) MMC_RSP_BITS((resp), 48, 22) +#define SD_CSD_V2_CAPACITY(resp) ((SD_CSD_V2_C_SIZE((resp))+1) << 10) +#define SD_CSD_V2_BL_LEN 0x9 /* 512 */ +#define SD_CSD_VDD_R_CURR_MIN(resp) MMC_RSP_BITS((resp), 59, 3) +#define SD_CSD_VDD_R_CURR_MAX(resp) MMC_RSP_BITS((resp), 56, 3) +#define SD_CSD_VDD_W_CURR_MIN(resp) MMC_RSP_BITS((resp), 53, 3) +#define SD_CSD_VDD_W_CURR_MAX(resp) MMC_RSP_BITS((resp), 50, 3) +#define SD_CSD_VDD_RW_CURR_100mA 0x7 +#define SD_CSD_VDD_RW_CURR_80mA 0x6 +#define SD_CSD_C_SIZE_MULT(resp) MMC_RSP_BITS((resp), 47, 3) +#define SD_CSD_ERASE_BLK_EN(resp) MMC_RSP_BITS((resp), 46, 1) +#define SD_CSD_SECTOR_SIZE(resp) MMC_RSP_BITS((resp), 39, 7) /* +1 */ +#define SD_CSD_WP_GRP_SIZE(resp) MMC_RSP_BITS((resp), 32, 7) /* +1 */ +#define SD_CSD_WP_GRP_ENABLE(resp) MMC_RSP_BITS((resp), 31, 1) +#define SD_CSD_R2W_FACTOR(resp) MMC_RSP_BITS((resp), 26, 3) +#define SD_CSD_WRITE_BL_LEN(resp) MMC_RSP_BITS((resp), 22, 4) +#define SD_CSD_RW_BL_LEN_2G 0xa +#define SD_CSD_RW_BL_LEN_1G 0x9 +#define SD_CSD_WRITE_BL_PARTIAL(resp) MMC_RSP_BITS((resp), 21, 1) +#define SD_CSD_FILE_FORMAT_GRP(resp) MMC_RSP_BITS((resp), 15, 1) +#define SD_CSD_COPY(resp) MMC_RSP_BITS((resp), 14, 1) +#define SD_CSD_PERM_WRITE_PROTECT(resp) MMC_RSP_BITS((resp), 13, 1) +#define SD_CSD_TMP_WRITE_PROTECT(resp) MMC_RSP_BITS((resp), 12, 1) +#define SD_CSD_FILE_FORMAT(resp) MMC_RSP_BITS((resp), 10, 2) + +/* SD R2 response (CID) */ +#define SD_CID_MID(resp) MMC_RSP_BITS((resp), 120, 8) +#define SD_CID_OID(resp) MMC_RSP_BITS((resp), 104, 16) +#define SD_CID_PNM_CPY(resp, pnm) \ + do { \ + (pnm)[0] = MMC_RSP_BITS((resp), 96, 8); \ + (pnm)[1] = MMC_RSP_BITS((resp), 88, 8); \ + (pnm)[2] = MMC_RSP_BITS((resp), 80, 8); \ + (pnm)[3] = MMC_RSP_BITS((resp), 72, 8); \ + (pnm)[4] = MMC_RSP_BITS((resp), 64, 8); \ + (pnm)[5] = '\0'; \ + } while (0) +#define SD_CID_REV(resp) MMC_RSP_BITS((resp), 56, 8) +#define SD_CID_PSN(resp) MMC_RSP_BITS((resp), 24, 32) +#define SD_CID_MDT(resp) MMC_RSP_BITS((resp), 8, 12) + +/* SCR (SD Configuration Register) */ +#define SCR_STRUCTURE(scr) MMC_RSP_BITS((scr), 60, 4) +#define SCR_STRUCTURE_VER_1_0 0 /* Version 1.0 */ +#define SCR_SD_SPEC(scr) MMC_RSP_BITS((scr), 56, 4) +#define SCR_SD_SPEC_VER_1_0 0 /* Version 1.0 and 1.01 */ +#define SCR_SD_SPEC_VER_1_10 1 /* Version 1.10 */ +#define SCR_SD_SPEC_VER_2 2 /* Version 2.00 or Version 3.0X */ +#define SCR_DATA_STAT_AFTER_ERASE(scr) MMC_RSP_BITS((scr), 55, 1) +#define SCR_SD_SECURITY(scr) MMC_RSP_BITS((scr), 52, 3) +#define SCR_SD_SECURITY_NONE 0 /* no security */ +#define SCR_SD_SECURITY_1_0 1 /* security protocol 1.0 */ +#define SCR_SD_SECURITY_1_0_2 2 /* security protocol 1.0 */ +#define SCR_SD_BUS_WIDTHS(scr) MMC_RSP_BITS((scr), 48, 4) +#define SCR_SD_BUS_WIDTHS_1BIT (1 << 0) /* 1bit (DAT0) */ +#define SCR_SD_BUS_WIDTHS_4BIT (1 << 2) /* 4bit (DAT0-3) */ +#define SCR_SD_SPEC3(scr) MMC_RSP_BITS((scr), 47, 1) +#define SCR_EX_SECURITY(scr) MMC_RSP_BITS((scr), 43, 4) +#define SCR_SD_SPEC4(scr) MMC_RSP_BITS((scr), 42, 1) +#define SCR_RESERVED(scr) MMC_RSP_BITS((scr), 34, 8) +#define SCR_CMD_SUPPORT_CMD23(scr) MMC_RSP_BITS((scr), 33, 1) +#define SCR_CMD_SUPPORT_CMD20(scr) MMC_RSP_BITS((scr), 32, 1) +#define SCR_RESERVED2(scr) MMC_RSP_BITS((scr), 0, 32) + +/* Max supply current in SWITCH_FUNC response (in mA) */ +#define SD_SFUNC_I_MAX(status) (MMC_RSP_BITS((u32 *)(status), 496, 16)) + +/* Supported flags in SWITCH_FUNC response */ +#define SD_SFUNC_SUPPORTED(status, group) \ + (MMC_RSP_BITS((u32 *)(status), 400 + (group - 1) * 16, 16)) + +/* Selected function in SWITCH_FUNC response */ +#define SD_SFUNC_SELECTED(status, group) \ + (MMC_RSP_BITS((u32 *)(status), 376 + (group - 1) * 4, 4)) + +/* Busy flags in SWITCH_FUNC response */ +#define SD_SFUNC_BUSY(status, group) \ + (MMC_RSP_BITS((u32 *)(status), 272 + (group - 1) * 16, 16)) + +/* Version of SWITCH_FUNC response */ +#define SD_SFUNC_VER(status) (MMC_RSP_BITS((u32 *)(status), 368, 8)) + +#define SD_SFUNC_GROUP_MAX 6 +#define SD_SFUNC_FUNC_MAX 15 + +#define SD_ACCESS_MODE 1 /* Function group 1, Access Mode */ + +#define SD_ACCESS_MODE_SDR12 0 /* 25 MHz clock */ +#define SD_ACCESS_MODE_SDR25 1 /* 50 MHz clock */ +#define SD_ACCESS_MODE_SDR50 2 /* UHS-I, 100 MHz clock */ +#define SD_ACCESS_MODE_SDR104 3 /* UHS-I, 208 MHz clock */ +#define SD_ACCESS_MODE_DDR50 4 /* UHS-I, 50 MHz clock, DDR */ + +/** + * @brief Extract up to 32 sequential bits from an array of 32-bit words + * + * Bits within the word are numbered in the increasing order from LSB to MSB. + * + * As an example, consider 2 32-bit words: + * + * 0x01234567 0x89abcdef + * + * On a little-endian system, the bytes are stored in memory as follows: + * + * 67 45 23 01 ef cd ab 89 + * + * MMC_RSP_BITS will extact bits as follows: + * + * start=0 len=4 -> result=0x00000007 + * start=0 len=12 -> result=0x00000567 + * start=28 len=8 -> result=0x000000f0 + * start=59 len=5 -> result=0x00000011 + * + * @param src array of words to extract bits from + * @param start index of the first bit to extract + * @param len number of bits to extract, 1 to 32 + * @return 32-bit word where requested bits start from LSB + */ +static inline u32 MMC_RSP_BITS(u32 *src, int start, int len) +{ + u32 mask = (len % 32 == 0) ? UINT_MAX : UINT_MAX >> (32 - (len % 32)); + size_t word = start / 32; + size_t shift = start % 32; + u32 right = src[word] >> shift; + u32 left = (len + shift <= 32) ? 0 : src[word + 1] << ((32 - shift) % 32); + return (left | right) & mask; +} + +/* SD R4 response (IO OCR) */ +#define SD_IO_OCR_MEM_READY (1<<31) +#define SD_IO_OCR_NUM_FUNCTIONS(ocr) (((ocr) >> 28) & 0x7) +#define SD_IO_OCR_MEM_PRESENT (1<<27) +#define SD_IO_OCR_MASK 0x00fffff0 + +/* CMD52 arguments */ +#define SD_ARG_CMD52_READ (0<<31) +#define SD_ARG_CMD52_WRITE (1<<31) +#define SD_ARG_CMD52_FUNC_SHIFT 28 +#define SD_ARG_CMD52_FUNC_MASK 0x7 +#define SD_ARG_CMD52_EXCHANGE (1<<27) +#define SD_ARG_CMD52_REG_SHIFT 9 +#define SD_ARG_CMD52_REG_MASK 0x1ffff +#define SD_ARG_CMD52_DATA_SHIFT 0 +#define SD_ARG_CMD52_DATA_MASK 0xff +#define SD_R5_DATA(resp) ((resp)[0] & 0xff) + +/* CMD53 arguments */ +#define SD_ARG_CMD53_READ (0<<31) +#define SD_ARG_CMD53_WRITE (1<<31) +#define SD_ARG_CMD53_FUNC_SHIFT 28 +#define SD_ARG_CMD53_FUNC_MASK 0x7 +#define SD_ARG_CMD53_BLOCK_MODE (1<<27) +#define SD_ARG_CMD53_INCREMENT (1<<26) +#define SD_ARG_CMD53_REG_SHIFT 9 +#define SD_ARG_CMD53_REG_MASK 0x1ffff +#define SD_ARG_CMD53_LENGTH_SHIFT 0 +#define SD_ARG_CMD53_LENGTH_MASK 0x1ff +#define SD_ARG_CMD53_LENGTH_MAX 512 + +/* Card Common Control Registers (CCCR) */ +#define SD_IO_CCCR_START 0x00000 +#define SD_IO_CCCR_SIZE 0x100 +#define SD_IO_CCCR_FN_ENABLE 0x02 +#define SD_IO_CCCR_FN_READY 0x03 +#define SD_IO_CCCR_INT_ENABLE 0x04 +#define SD_IO_CCCR_INT_PENDING 0x05 +#define SD_IO_CCCR_CTL 0x06 +#define CCCR_CTL_RES (1<<3) +#define SD_IO_CCCR_BUS_WIDTH 0x07 +#define CCCR_BUS_WIDTH_1 (0<<0) +#define CCCR_BUS_WIDTH_4 (2<<0) +#define CCCR_BUS_WIDTH_8 (3<<0) +#define CCCR_BUS_WIDTH_ECSI (1<<5) +#define SD_IO_CCCR_CARD_CAP 0x08 +#define CCCR_CARD_CAP_LSC BIT(6) +#define CCCR_CARD_CAP_4BLS BIT(7) +#define SD_IO_CCCR_CISPTR 0x09 +#define SD_IO_CCCR_BLKSIZEL 0x10 +#define SD_IO_CCCR_BLKSIZEH 0x11 +#define SD_IO_CCCR_HIGHSPEED 0x13 +#define CCCR_HIGHSPEED_SUPPORT BIT(0) +#define CCCR_HIGHSPEED_ENABLE BIT(1) + +/* Function Basic Registers (FBR) */ +#define SD_IO_FBR_START 0x00100 +#define SD_IO_FBR_SIZE 0x00700 + +/* Card Information Structure (CIS) */ +#define SD_IO_CIS_START 0x01000 +#define SD_IO_CIS_SIZE 0x17000 + +/* CIS tuple codes (based on PC Card 16) */ +#define CISTPL_CODE_NULL 0x00 +#define CISTPL_CODE_DEVICE 0x01 +#define CISTPL_CODE_CHKSUM 0x10 +#define CISTPL_CODE_VERS1 0x15 +#define CISTPL_CODE_ALTSTR 0x16 +#define CISTPL_CODE_CONFIG 0x1A +#define CISTPL_CODE_CFTABLE_ENTRY 0x1B +#define CISTPL_CODE_MANFID 0x20 +#define CISTPL_CODE_FUNCID 0x21 +#define TPLFID_FUNCTION_SDIO 0x0c +#define CISTPL_CODE_FUNCE 0x22 +#define CISTPL_CODE_VENDER_BEGIN 0x80 +#define CISTPL_CODE_VENDER_END 0x8F +#define CISTPL_CODE_SDIO_STD 0x91 +#define CISTPL_CODE_SDIO_EXT 0x92 +#define CISTPL_CODE_END 0xFF + + +/* Timing */ +#define SDMMC_TIMING_LEGACY 0 +#define SDMMC_TIMING_HIGHSPEED 1 +#define SDMMC_TIMING_MMC_DDR52 2 + +/* Architecture specifics. */ +//#define CONFIG_FREERTOS_HZ 100 /* NOT SURE ABOUT THE VALUE */ +//#define configTICK_RATE_HZ ( CONFIG_FREERTOS_HZ ) +//#define portTICK_PERIOD_MS ( ( u32 ) 1000 / configTICK_RATE_HZ ) +//#define MALLOC_CAP_DMA (1<<3) ///< Memory must be able to accessed by DMA +#define MIN(A,B) ((A) < (B) ? (A):(B)) + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc_init.c b/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc_init.c new file mode 100644 index 0000000000000000000000000000000000000000..b5e584134944dc8edc16fe7deb7a753d8ef20e40 --- /dev/null +++ b/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc_init.c @@ -0,0 +1,147 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-08 11:51:14 + * @LastEditTime: 2021-04-14 15:49:12 + * @Description:  This files is for sdmmc init process + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include +#include "ft_assert.h" +#include "ft_sdmmc.h" +#include "ft_sdmmc_defs.h" +#include "ft_sdmmc_common.h" + +#define SDMMC_INIT_STEP(condition, function) \ + do { \ + if ((condition)) { \ + ft_error_t err = (function)(card); \ + if (err != ERR_SDMMC_OK) { \ + FT_SDMMC_DEBUG_E("init failed at %s %d: returned 0x%x", #function, __LINE__, err); \ + return err; \ + } \ + } \ + } while(0); + +void Sdmmc_cardSetSDMem(Sdmmc_Card_t* card) +{ + card->is_ddr = FALSE; + card->is_mem = TRUE; + card->is_mmc = FALSE; + card->is_sdio = FALSE; + card->log_bus_width = 2; +} + +ft_error_t Sdmmc_CardInit(const Sdmmc_Host_t* config, Sdmmc_Card_t* card) +{ + memset(card, 0, sizeof(*card)); + memcpy(&card->host, config, sizeof(*config)); + const bool_t is_spi = FALSE/*Sdmmc_IsHostSpi(card)*/; + const bool_t always = TRUE; + const bool_t io_supported = FALSE; + const bool_t is_mmc = FALSE; + const bool_t is_sdmem = TRUE; + const bool_t is_mem = TRUE; + const bool_t is_sdio = FALSE; + + Sdmmc_cardSetSDMem(card); + + /* Check if host flags are compatible with slot configuration. */ + //SDMMC_INIT_STEP(!is_spi, Sdmmc_FixHostFlags); + SDMMC_INIT_STEP(always, Sdmmc_FixHostFlags); + + /* Reset SDIO (CMD52, RES) before re-initializing IO (CMD5). */ + //SDMMC_INIT_STEP(io_supported, sdmmc_io_reset); + + /* GO_IDLE_STATE (CMD0) command resets the card */ + SDMMC_INIT_STEP(always, Sdmmc_SendCmdGoIdleState); + + /* SEND_IF_COND (CMD8) command is used to identify SDHC/SDXC cards. */ + SDMMC_INIT_STEP(always, Sdmmc_InitSdIfCond); + + /* IO_SEND_OP_COND(CMD5), Determine if the card is an IO card. */ + //SDMMC_INIT_STEP(io_supported, sdmmc_init_io); + + // const bool_t is_mem = card->is_mem; + // const bool_t is_sdio = !is_mem; + + /* Enable CRC16 checks for data transfers in SPI mode */ + SDMMC_INIT_STEP(is_spi, Sdmmc_InitSpiCrc); + + /* Use SEND_OP_COND to set up card OCR */ + SDMMC_INIT_STEP(is_mem, Sdmmc_InitOCR); + + // const bool_t is_mmc = is_mem && card->is_mmc; + // const bool_t is_sdmem = is_mem && !is_mmc; + + // FT_SDMMC_DEBUG_D("%s: card type is %s", __func__, + // is_sdio ? "SDIO" : is_mmc ? "MMC" : "SD"); + + /* Read the contents of CID register*/ + SDMMC_INIT_STEP(is_mem, Sdmmc_InitCID); + + /* Assign RCA */ + SDMMC_INIT_STEP(!is_spi, Sdmmc_InitRCA); + FT_SDMMC_DEBUG_D("finish assign rca!!"); + + /* Read and decode the contents of CSD register */ + SDMMC_INIT_STEP(is_mem, Sdmmc_InitCSD); + + /* Decode the contents of mmc CID register */ + SDMMC_INIT_STEP(is_mmc && !is_spi, Sdmmc_InitMMCDecodeCID); + + /* Switch the card from stand-by mode to data transfer mode (not needed if + * SPI interface is used). This is needed to issue SET_BLOCKLEN and + * SEND_SCR commands. + */ + SDMMC_INIT_STEP(!is_spi, Sdmmc_InitSelectCard); + + /* SD memory cards: + * Set block len for SDSC cards to 512 bytes (same as SDHC) + * Read SCR + * Wait to enter data transfer state + */ + SDMMC_INIT_STEP(is_sdmem, Sdmmc_InitSdBlkLen); + + /* Switch to high speed before one need to fetch data from SD Card */ + SDMMC_INIT_STEP(is_sdmem, Sdmmc_InitSwitchHs); + + SDMMC_INIT_STEP(is_sdmem, Sdmmc_InitSdSCR); + //SDMMC_INIT_STEP(is_sdmem, Sdmmc_InitSdWaitDataReady); + + // /* MMC cards: read CXD */ + // SDMMC_INIT_STEP(is_mmc, Sdmmc_InitMMCReadExtCSD); + + // /* Try to switch card to HS mode if the card supports it. + // * Set card->max_freq_khz value accordingly. + // */ + SDMMC_INIT_STEP(always, Sdmmc_InitCardHsMode); + + // /* Set bus width. One call for every kind of card, then one for the host */ + if (!is_spi) { + //SDMMC_INIT_STEP(is_sdmem, Sdmmc_InitSdBusWidth); + //SDMMC_INIT_STEP(is_sdio, sdmmc_init_io_bus_width); + //SDMMC_INIT_STEP(is_mmc, Sdmmc_InitMMCBusWidth); + //SDMMC_INIT_STEP(always, Sdmmc_InitHostBusWidth); + } + + // /* Switch to the host to use card->max_freq_khz frequency. */ + //SDMMC_INIT_STEP(always, Sdmmc_InitHostFreq); + + // /* Sanity check after switching the bus mode and frequency */ + // FT_SDMMC_DEBUG_D("before check sd scr"); + // SDMMC_INIT_STEP(is_sdmem, Sdmmc_CheckSCR); + // FT_SDMMC_DEBUG_D("after check sd scr"); + // /* TODO: this is CMD line only, add data checks for eMMC */ + // //SDMMC_INIT_STEP(is_mmc, Sdmmc_InitMMCCheckCSD); + // /* TODO: add similar checks for SDIO */ + + return ERR_SDMMC_OK; +} + diff --git a/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc_mmc.c b/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc_mmc.c new file mode 100644 index 0000000000000000000000000000000000000000..e80a9045fc8fa278a0a10c2e789d0a6d57d4afd6 --- /dev/null +++ b/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc_mmc.c @@ -0,0 +1,261 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-08 16:03:05 + * @LastEditTime: 2021-04-14 11:55:03 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include +#include +#include "ft_sdmmc_defs.h" +#include "ft_sdmmc_common.h" + +ft_error_t Sdmmc_InitMMCReadExtCSD(Sdmmc_Card_t* card) +{ + int card_type; + ft_error_t err = ERR_SDMMC_OK; + + u8* ext_csd = Sdmmc_HeapMalloc(EXT_CSD_MMC_SIZE); + if (!ext_csd) { + FT_SDMMC_DEBUG_E("%s: could not allocate ext_csd", __func__); + return ERR_SDMMC_NO_MEM; + } + + uint32_t sectors = 0; + + FT_SDMMC_DEBUG_D("MMC version: %d", card->csd.mmcVer); + if (card->csd.mmcVer < MMC_CSD_MMCVER_4_0) { + err = ERR_SDMMC_NOT_SUPPORTED; + goto out; + } + + /* read EXT_CSD */ + err = Sdmmc_MMCSendExtCSDData(card, ext_csd, EXT_CSD_MMC_SIZE); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E("%s: send_ext_csd_data error 0x%x", __func__, err); + goto out; + } + card_type = ext_csd[EXT_CSD_CARD_TYPE]; + + card->is_ddr = 0; + if (card_type & EXT_CSD_CARD_TYPE_F_52M_1_8V) { + card->max_freq_khz = SDMMC_FREQ_52M; + if ((card->host.flags & SDMMC_HOST_FLAG_DDR) && + card->host.max_freq_khz >= SDMMC_FREQ_26M && + card->host.get_bus_width(card->host.slot) == 4) { + FT_SDMMC_DEBUG_D("card and host support DDR mode"); + card->is_ddr = 1; + } + } else if (card_type & EXT_CSD_CARD_TYPE_F_52M) { + card->max_freq_khz = SDMMC_FREQ_52M; + } else if (card_type & EXT_CSD_CARD_TYPE_F_26M) { + card->max_freq_khz = SDMMC_FREQ_26M; + } else { + FT_SDMMC_DEBUG_W("%s: unknown CARD_TYPE 0x%x", __func__, card_type); + } + /* For MMC cards, use speed value from EXT_CSD */ + card->csd.transSpeed = card->max_freq_khz * 1000; + FT_SDMMC_DEBUG_D("MMC card type %d, max_freq_khz=%d, is_ddr=%d", card_type, card->max_freq_khz, card->is_ddr); + card->max_freq_khz = MIN(card->max_freq_khz, card->host.max_freq_khz); + + if (card->host.flags & SDMMC_HOST_FLAG_8BIT) { + card->ext_csd.power_class = ext_csd[(card->max_freq_khz > SDMMC_FREQ_26M) ? + EXT_CSD_PWR_CL_52_360 : EXT_CSD_PWR_CL_26_360] >> 4; + card->log_bus_width = 3; + } else if (card->host.flags & SDMMC_HOST_FLAG_4BIT) { + card->ext_csd.power_class = ext_csd[(card->max_freq_khz > SDMMC_FREQ_26M) ? + EXT_CSD_PWR_CL_52_360 : EXT_CSD_PWR_CL_26_360] & 0x0f; + card->log_bus_width = 2; + } else { + card->ext_csd.power_class = 0; //card must be able to do full rate at powerclass 0 in 1-bit mode + card->log_bus_width = 0; + } + + sectors = ( ext_csd[EXT_CSD_SEC_COUNT + 0] << 0 ) + | ( ext_csd[EXT_CSD_SEC_COUNT + 1] << 8 ) + | ( ext_csd[EXT_CSD_SEC_COUNT + 2] << 16 ) + | ( ext_csd[EXT_CSD_SEC_COUNT + 3] << 24 ); + + if (sectors > (2u * 1024 * 1024 * 1024) / 512) { + card->csd.capacity = sectors; + } + +out: + Sdmmc_HeapFree(ext_csd); + return err; +} + +ft_error_t Sdmmc_InitMMCBusWidth(Sdmmc_Card_t* card) +{ + ft_error_t err; + if (card->ext_csd.power_class != 0) { + err = Sdmmc_MMCSwitch(card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_POWER_CLASS, card->ext_csd.power_class); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E("%s: can't change power class (%d bit), 0x%x" + , __func__, card->ext_csd.power_class, err); + return err; + } + } + + if (card->log_bus_width > 0) { + int csd_bus_width_value = EXT_CSD_BUS_WIDTH_1; + int bus_width = 1; + if (card->log_bus_width == 2) { + if (card->is_ddr) { + csd_bus_width_value = EXT_CSD_BUS_WIDTH_4_DDR; + } else { + csd_bus_width_value = EXT_CSD_BUS_WIDTH_4; + } + bus_width = 4; + } else if (card->log_bus_width == 3) { + if (card->is_ddr) { + csd_bus_width_value = EXT_CSD_BUS_WIDTH_8_DDR; + } else { + csd_bus_width_value = EXT_CSD_BUS_WIDTH_8; + } + bus_width = 8; + } + err = Sdmmc_MMCSwitch(card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_BUS_WIDTH, csd_bus_width_value); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E("%s: can't change bus width (%d bit), 0x%x", + __func__, bus_width, err); + return err; + } + } + return ERR_SDMMC_OK; +} + +ft_error_t Sdmmc_MMCEnableHsMode(Sdmmc_Card_t* card) +{ + ft_error_t err; + if (card->max_freq_khz > SDMMC_FREQ_26M) { + /* switch to high speed timing */ + err = Sdmmc_MMCSwitch(card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_HS_TIMING, EXT_CSD_HS_TIMING_HS); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E("%s: mmc_switch EXT_CSD_HS_TIMING_HS error 0x%x", + __func__, err); + return err; + } + } + return ERR_SDMMC_OK; +} + +ft_error_t Sdmmc_MMCDecodeCID(int mmcVer, Sdmmc_Resp_t resp, Sdmmc_CID_t* out_cid) +{ + if (mmcVer == MMC_CSD_MMCVER_1_0 || + mmcVer == MMC_CSD_MMCVER_1_4) { + out_cid->mfgId = MMC_CID_MID_V1(resp); + out_cid->oemId = 0; + MMC_CID_PNM_V1_CPY(resp, out_cid->name); + out_cid->revision = MMC_CID_REV_V1(resp); + out_cid->serial = MMC_CID_PSN_V1(resp); + out_cid->date = MMC_CID_MDT_V1(resp); + } else if (mmcVer == MMC_CSD_MMCVER_2_0 || + mmcVer == MMC_CSD_MMCVER_3_1 || + mmcVer == MMC_CSD_MMCVER_4_0) { + out_cid->mfgId = MMC_CID_MID_V2(resp); + out_cid->oemId = MMC_CID_OID_V2(resp); + MMC_CID_PNM_V1_CPY(resp, out_cid->name); + out_cid->revision = 0; + out_cid->serial = MMC_CID_PSN_V1(resp); + out_cid->date = 0; + } + return ERR_SDMMC_OK; +} + +ft_error_t Sdmmc_MMCDecodeCSD(Sdmmc_Resp_t response, Sdmmc_CSD_t* out_csd) +{ + out_csd->csdVer = MMC_CSD_CSDVER(response); + if (out_csd->csdVer == MMC_CSD_CSDVER_1_0 || + out_csd->csdVer == MMC_CSD_CSDVER_2_0 || + out_csd->csdVer == MMC_CSD_CSDVER_EXT_CSD) { + out_csd->mmcVer = MMC_CSD_MMCVER(response); + out_csd->capacity = MMC_CSD_CAPACITY(response); + out_csd->readBlkLen = MMC_CSD_READ_BL_LEN(response); + } else { + FT_SDMMC_DEBUG_E("unknown MMC CSD structure version 0x%x\n", out_csd->csdVer); + return 1; + } + int read_bl_size = 1 << out_csd->readBlkLen; + out_csd->sectorSize = MIN(read_bl_size, 512); + if (out_csd->sectorSize < read_bl_size) { + out_csd->capacity *= read_bl_size / out_csd->sectorSize; + } + /* transSpeed will be determined when reading CXD */ + out_csd->transSpeed = 0; + return ERR_SDMMC_OK; +} + +ft_error_t Sdmmc_MMCSendExtCSDData(Sdmmc_Card_t* card, void *out_data, size_t datalen) +{ + assert(Sdmmc_DMACapable(out_data)); + Sdmmc_Cmd_t cmd = { + .data = out_data, + .datalen = datalen, + .blklen = datalen, + .opcode = MMC_SEND_EXT_CSD, + .arg = 0, + .flags = SCF_CMD_ADTC | SCF_RSP_R1 | SCF_CMD_READ, + .cmd_resp_type = SCT_RESP_SHORT + }; + return Sdmmc_SendCmd(card, &cmd); +} + +ft_error_t Sdmmc_MMCSwitch(Sdmmc_Card_t* card, u8 set, u8 index, u8 value) +{ + Sdmmc_Cmd_t cmd = { + .opcode = MMC_SWITCH, + .arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | (index << 16) | (value << 8) | set, + .flags = SCF_RSP_R1B | SCF_CMD_AC | SCF_WAIT_BUSY, + .cmd_resp_type = SCT_RESP_SHORT + }; + ft_error_t err = Sdmmc_SendCmd(card, &cmd); + if (err == ERR_SDMMC_OK) { + //check response bit to see that switch was accepted + if (MMC_R1(cmd.response) & MMC_R1_SWITCH_ERROR) + err = ERR_SDMMC_INVALID_RESPONSE; + } + + return err; +} + +ft_error_t Sdmmc_InitMMCCheckCSD(Sdmmc_Card_t* card) +{ + ft_error_t err; + assert(card->is_mem == 1); + assert(card->rca != 0); + //The card will not respond to send_csd command in the transfer state. + //Deselect it first. + err = Sdmmc_SendCmdSelectCard(card, 0); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E("%s: select_card returned 0x%x", __func__, err); + return err; + } + + Sdmmc_CSD_t csd; + /* Get the contents of CSD register to verify the communication over CMD line + is OK. */ + err = Sdmmc_SendCmdSendCSD(card, &csd); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E("%s: send_csd returned 0x%x", __func__, err); + return err; + } + + //Select the card again + err = Sdmmc_SendCmdSelectCard(card, card->rca); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E("%s: select_card returned 0x%x", __func__, err); + return err; + } + return ERR_SDMMC_OK; +} diff --git a/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc_port.c b/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc_port.c new file mode 100644 index 0000000000000000000000000000000000000000..c0f1645bf3dc6d08e1140ac4650bfe1fc34e0c2a --- /dev/null +++ b/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc_port.c @@ -0,0 +1,64 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-08 16:52:05 + * @LastEditTime: 2021-04-15 13:51:10 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_printf.h" +#include "ft_generic_timer.h" +#include "ft_assert.h" +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" +#include "ft_sdmmc.h" +#include "ft_sdmmc_common.h" + +static void freertos_task_delay(u32 delay_tick) +{ + (void)vTaskDelay(delay_tick); +} + +static void *freertos_heap_alloc(size_t size) +{ + void *ptr = pvPortMalloc(size); + FT_SDMMC_DEBUG_D("allocate %x size %d", ptr, size); + return ptr; +} + +static void freertos_heap_free(void *ptr) +{ + Ft_assertNoneReturn(NULL != ptr); + FT_SDMMC_DEBUG_D("do free %x", ptr); + vPortFree(ptr); +} + +static bool_t freertos_dma_capable(const void *ptr) +{ + /* no check implemented */ + return TRUE; +} + +/* specify cpu or os depended implementation */ +static const Sdmmc_OSImpl_t sdmmc_os_impl = { + .task_delay = freertos_task_delay, /* freeRTOS delay */ + .heap_alloc = freertos_heap_alloc, /* freeRTOS heap memory allocator */ + .heap_free = freertos_heap_free, /* freeRTOS heap free */ + .check_dma_capable = freertos_dma_capable, /* freeRTOS mem allign check */ + .printf = Ft_printf, /* freeRTOS printf */ + .tick_period = portTICK_PERIOD_MS, /* freeRTOS tick period */ + .event_queue = NULL, /* freeRTOS follow type QueueHandle_t */ + .io_intr_event = NULL, /* freeRTOS follow type SemaphoreHandle_t */ +}; + +const Sdmmc_OSImpl_t *get_sdmmc_os_impl() +{ + return &sdmmc_os_impl; +} diff --git a/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc_sd.c b/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc_sd.c new file mode 100644 index 0000000000000000000000000000000000000000..47ca2c068c61e067476160e09c3f49046526fb60 --- /dev/null +++ b/bsp/ft2004/libraries/component/sdmmc/ft_sdmmc_sd.c @@ -0,0 +1,376 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-08 11:51:42 + * @LastEditTime: 2021-04-14 11:55:34 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ +#include +#include +#include "ft_sdmmc_defs.h" +#include "ft_sdmmc.h" +#include "ft_sdmmc_common.h" + +ft_error_t Sdmmc_InitSdIfCond(Sdmmc_Card_t* card) +{ + /* SEND_IF_COND (CMD8) command is used to identify SDHC/SDXC cards. + * SD v1 and non-SD cards will not respond to this command. + */ + u32 host_ocr = Sdmmc_GetHostOCR(card->host.io_voltage); + ft_error_t err = Sdmmc_SendCmdSendIfCond(card, host_ocr); + if (err == ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_D( "SDHC/SDXC card"); + host_ocr |= SD_OCR_SDHC_CAP; + } else if (err == ERR_SDMMC_TIMEOUT) { + FT_SDMMC_DEBUG_D( "CMD8 timeout; not an SD v2.00 card"); + } else if (Sdmmc_IsHostSpi(card) && err == ERR_SDMMC_NOT_SUPPORTED) { + FT_SDMMC_DEBUG_D( "CMD8 rejected; not an SD v2.00 card"); + } else { + FT_SDMMC_DEBUG_E( "%s: send_if_cond (1) returned 0x%x", __func__, err); + return err; + } + card->ocr = host_ocr; + return ERR_SDMMC_OK; +} + +ft_error_t Sdmmc_InitSdBlkLen(Sdmmc_Card_t* card) +{ + /* SDSC cards support configurable data block lengths. + * We don't use this feature and set the block length to 512 bytes, + * same as the block length for SDHC cards. + */ + if ((card->ocr & SD_OCR_SDHC_CAP) == 0) { + ft_error_t err = Sdmmc_SendCmdSetBlkLen(card, &card->csd); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E( "%s: set_blocklen returned 0x%x", __func__, err); + return err; + } + } + return ERR_SDMMC_OK; +} + +ft_error_t Sdmmc_InitSdSCR(Sdmmc_Card_t* card) +{ + ft_error_t err; + /* Get the contents of SCR register: bus width and the version of SD spec + * supported by the card. + * In SD mode, this is the first command which uses D0 line. Errors at + * this step usually indicate connection issue or lack of pull-up resistor. + */ + err = Sdmmc_SendCmdSendSCR(card, &card->scr); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E( "%s: send_scr (1) returned 0x%x", __func__, err); + return err; + } + + if ((card->scr.bus_width & SCR_SD_BUS_WIDTHS_4BIT) + && (card->host.flags & SDMMC_HOST_FLAG_4BIT)) { + card->log_bus_width = 2; + } else { + card->log_bus_width = 0; + } + return ERR_SDMMC_OK; +} + +ft_error_t Sdmmc_InitSwitchHs(Sdmmc_Card_t* card) +{ + ft_error_t err; + + err = Sdmmc_SendCmdSwitch(card); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E("switch card to high speed failed !!"); + return err; + } + + return err; +} + +ft_error_t Sdmmc_InitSdBusWidth(Sdmmc_Card_t* card) +{ + int width = 1; + if (card->log_bus_width == 2) { + width = 4; + } else if (card->log_bus_width == 3) { + width = 8; + } + ft_error_t err = Sdmmc_SendCmdSetBusWidth(card, width); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E( "set_bus_width failed (0x%x)", err); + return err; + } + return ERR_SDMMC_OK; +} + +ft_error_t Sdmmc_InitSdWaitDataReady(Sdmmc_Card_t* card) +{ + /* Wait for the card to be ready for data transfers */ + u32 status = 0; + u32 count = 0; + while (!Sdmmc_IsHostSpi(card) && !(status & MMC_R1_READY_FOR_DATA)) { + // TODO: add some timeout here + ft_error_t err = Sdmmc_SendCmdSendStatus(card, &status); + if (err != ERR_SDMMC_OK) { + return err; + } + if (++count % 16 == 0) { + FT_SDMMC_DEBUG_V("waiting for card to become ready (%d)", count); + } + } + return ERR_SDMMC_OK; +} + +ft_error_t Sdmmc_SendCmdSwitchFunc(Sdmmc_Card_t* card, + u32 mode, u32 group, u32 function, + Sdmmc_SwitchFuncRsp_t* resp) +{ + if (card->scr.sdSpec < SCR_SD_SPEC_VER_1_10 || + ((card->csd.cardCmdClass & SD_CSD_CCC_SWITCH) == 0)) { + return ERR_SDMMC_NOT_SUPPORTED; + } + + if (group == 0 || + group > SD_SFUNC_GROUP_MAX || + function > SD_SFUNC_FUNC_MAX) { + return ERR_SDMMC_INVALID_ARG; + } + + if (mode > 1) { + return ERR_SDMMC_INVALID_ARG; + } + + u32 group_shift = (group - 1) << 2; + /* all functions which should not be affected are set to 0xf (no change) */ + u32 other_func_mask = (0x00ffffff & ~(0xf << group_shift)); + u32 func_val = (function << group_shift) | other_func_mask; + + Sdmmc_Cmd_t cmd = { + .opcode = MMC_SWITCH, + .flags = SCF_CMD_ADTC | SCF_CMD_READ | SCF_RSP_R1, + .cmd_resp_type = SCT_RESP_SHORT, + .blklen = sizeof(Sdmmc_SwitchFuncRsp_t), + .data = resp->data, + .datalen = sizeof(Sdmmc_SwitchFuncRsp_t), + .arg = (!!mode << 31) | func_val + }; + + ft_error_t err = Sdmmc_SendCmd(card, &cmd); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E( "%s: Sdmmc_SendCmd returned 0x%x", __func__, err); + return err; + } + Sdmmc_FilpByteOrder(resp->data, sizeof(Sdmmc_SwitchFuncRsp_t)); + u32 resp_ver = SD_SFUNC_VER(resp->data); + if (resp_ver == 0) { + /* busy response is never sent */ + } else if (resp_ver == 1) { + if (SD_SFUNC_BUSY(resp->data, group) & (1 << function)) { + FT_SDMMC_DEBUG_D( "%s: response indicates function %d:%d is busy", + __func__, group, function); + return ERR_SDMMC_INVALID_STATE; + } + } else { + FT_SDMMC_DEBUG_D( "%s: got an invalid version of SWITCH_FUNC response: 0x%02x", + __func__, resp_ver); + return ERR_SDMMC_INVALID_RESPONSE; + } + return ERR_SDMMC_OK; +} + +ft_error_t Sdmmc_EnableHsMode(Sdmmc_Card_t* card) +{ + /* This will determine if the card supports SWITCH_FUNC command, + * and high speed mode. If the cards supports both, this will enable + * high speed mode at the card side. + */ + if (card->scr.sdSpec < SCR_SD_SPEC_VER_1_10 || + ((card->csd.cardCmdClass & SD_CSD_CCC_SWITCH) == 0)) { + return ERR_SDMMC_NOT_SUPPORTED; + } + Sdmmc_SwitchFuncRsp_t* response = (Sdmmc_SwitchFuncRsp_t*) + Sdmmc_HeapMalloc(sizeof(*response)); + if (response == NULL) { + return ERR_SDMMC_NO_MEM; + } + + ft_error_t err = Sdmmc_SendCmdSwitchFunc(card, 0, SD_ACCESS_MODE, 0, response); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_D( "%s: Sdmmc_SendCmdSwitchFunc (1) returned 0x%x", __func__, err); + goto out; + } + u32 supported_mask = SD_SFUNC_SUPPORTED(response->data, 1); + if ((supported_mask & BIT(SD_ACCESS_MODE_SDR25)) == 0) { + err = ERR_SDMMC_NOT_SUPPORTED; + goto out; + } + err = Sdmmc_SendCmdSwitchFunc(card, 1, SD_ACCESS_MODE, SD_ACCESS_MODE_SDR25, response); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_D( "%s: Sdmmc_SendCmdSwitchFunc (2) returned 0x%x", __func__, err); + goto out; + } + +out: + Sdmmc_HeapFree(response); + return err; +} + +ft_error_t Sdmmc_EnableHsModeAndCheck(Sdmmc_Card_t* card) +{ + /* All cards should support at least default speed */ + card->max_freq_khz = SDMMC_FREQ_DEFAULT; + if (card->host.max_freq_khz <= card->max_freq_khz) { + /* Host is configured to use low frequency, don't attempt to switch */ + card->max_freq_khz = card->host.max_freq_khz; + return ERR_SDMMC_OK; + } + + /* Try to enabled HS mode */ + ft_error_t err = Sdmmc_EnableHsMode(card); + if (err != ERR_SDMMC_OK) { + return err; + } + /* HS mode has been enabled on the card. + * Read CSD again, it should now indicate that the card supports + * 50MHz clock. + * Since SEND_CSD is allowed only in standby mode, and the card is currently in data transfer + * mode, deselect the card first, then get the CSD, then select the card again. This step is + * not required in SPI mode, since CMD7 (select_card) is not supported. + */ + const bool_t is_spi = Sdmmc_IsHostSpi(card); + if (!is_spi) { + err = Sdmmc_SendCmdSelectCard(card, 0); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E( "%s: select_card (1) returned 0x%x", __func__, err); + return err; + } + } + err = Sdmmc_SendCmdSendCSD(card, &card->csd); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E( "%s: send_csd returned 0x%x", __func__, err); + return err; + } + if (!is_spi) { + err = Sdmmc_SendCmdSelectCard(card, card->rca); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E( "%s: select_card (2) returned 0x%x", __func__, err); + return err; + } + } + + if (card->csd.transSpeed != 50000000) { + FT_SDMMC_DEBUG_W("unexpected: after enabling HS mode, transSpeed=%d", card->csd.transSpeed); + return ERR_SDMMC_NOT_SUPPORTED; + } + + card->max_freq_khz = SDMMC_FREQ_HIGHSPEED; + return ERR_SDMMC_OK; +} + +ft_error_t Sdmmc_CheckSCR(Sdmmc_Card_t* card) +{ + /* If frequency switch has been performed, read SCR register one more time + * and compare the result with the previous one. Use this simple check as + * an indicator of potential signal integrity issues. + */ + Sdmmc_SCR_t scr_tmp; + ft_error_t err = Sdmmc_SendCmdSendSCR(card, &scr_tmp); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E( "%s: send_scr returned 0x%x", __func__, err); + return err; + } + if (memcmp(&card->scr, &scr_tmp, sizeof(scr_tmp)) != 0) { + FT_SDMMC_DEBUG_E( "got corrupted data after increasing clock frequency"); + return ERR_SDMMC_INVALID_RESPONSE; + } + return ERR_SDMMC_OK; +} + +ft_error_t Sdmmc_InitSpiCrc(Sdmmc_Card_t* card) +{ + /* In SD mode, CRC checks of data transfers are mandatory and performed + * by the hardware. In SPI mode, CRC16 of data transfers is optional and + * needs to be enabled. + */ + assert(Sdmmc_IsHostSpi(card)); + ft_error_t err = Sdmmc_SendCmdCrcOnOff(card, TRUE); + if (err != ERR_SDMMC_OK) { + FT_SDMMC_DEBUG_E( "%s: Sdmmc_SendCmdCrcOnOff returned 0x%x", __func__, err); + return err; + } + return ERR_SDMMC_OK; +} + +ft_error_t Sdmmc_DecodeCID(Sdmmc_Resp_t resp, Sdmmc_CID_t* out_cid) +{ + out_cid->mfgId = SD_CID_MID(resp); + out_cid->oemId = SD_CID_OID(resp); + SD_CID_PNM_CPY(resp, out_cid->name); + out_cid->revision = SD_CID_REV(resp); + out_cid->serial = SD_CID_PSN(resp); + out_cid->date = SD_CID_MDT(resp); + return ERR_SDMMC_OK; +} + +ft_error_t Sdmmc_DecodeCSD(Sdmmc_Resp_t response, Sdmmc_CSD_t* out_csd) +{ + out_csd->csdVer = SD_CSD_CSDVER(response); + FT_SDMMC_DEBUG_I("is sd v%d.0", out_csd->csdVer + 1); + switch (out_csd->csdVer) { + case SD_CSD_CSDVER_2_0: + out_csd->capacity = SD_CSD_V2_CAPACITY(response); + out_csd->readBlkLen = SD_CSD_V2_BL_LEN; + break; + case SD_CSD_CSDVER_1_0: + out_csd->capacity = SD_CSD_CAPACITY(response); + out_csd->readBlkLen = SD_CSD_READ_BL_LEN(response); + break; + default: + FT_SDMMC_DEBUG_E( "unknown SD CSD structure version 0x%x", out_csd->csdVer); + return ERR_SDMMC_NOT_SUPPORTED; + } + + out_csd->cardCmdClass = SD_CSD_CCC(response); + int read_bl_size = 1 << out_csd->readBlkLen; + out_csd->sectorSize = MIN(read_bl_size, 512); + if (out_csd->sectorSize < read_bl_size) { + out_csd->capacity *= read_bl_size / out_csd->sectorSize; + } + int speed = SD_CSD_SPEED(response); + if (speed == SD_CSD_SPEED_50_MHZ) { + out_csd->transSpeed = 50000000; + } else { + out_csd->transSpeed = 25000000; + } + + FT_SDMMC_DEBUG_I("sd capacity is %dMB", ((out_csd->capacity / 1000) * out_csd->sectorSize)/1000); + return ERR_SDMMC_OK; +} + +#define be32_to_cpu(x) ((u32)( \ + (((u32)(x) & (u32)0x000000ffUL) << 24) | \ + (((u32)(x) & (u32)0x0000ff00UL) << 8) | \ + (((u32)(x) & (u32)0x00ff0000UL) >> 8) | \ + (((u32)(x) & (u32)0xff000000UL) >> 24))) + +ft_error_t Sdmmc_DecodeSCR(u32 *raw_scr, Sdmmc_SCR_t* out_scr) +{ + Sdmmc_Resp_t resp = { 0 }; + FT_SDMMC_DEBUG_D("raw scr 0x%x 0x%x", raw_scr[0], raw_scr[1]); + resp[1] = be32_to_cpu(raw_scr[0]); + resp[0] = be32_to_cpu(raw_scr[1]); + FT_SDMMC_DEBUG_D("resp 0x%x 0x%x", resp[0], resp[1]); + int ver = SCR_STRUCTURE(resp); + if (ver != 0) { + FT_SDMMC_DEBUG_E("not support!! scr version is %d", ver); + return ERR_SDMMC_NOT_SUPPORTED; + } + out_scr->sdSpec = SCR_SD_SPEC(resp); + out_scr->bus_width = SCR_SD_BUS_WIDTHS(resp); + return ERR_SDMMC_OK; +} + diff --git a/bsp/ft2004/libraries/cpu/ft_aarch32_asm.h b/bsp/ft2004/libraries/cpu/ft_aarch32_asm.h new file mode 100644 index 0000000000000000000000000000000000000000..82a30ce06a877a8972e2014eb15959cfab397a47 --- /dev/null +++ b/bsp/ft2004/libraries/cpu/ft_aarch32_asm.h @@ -0,0 +1,316 @@ +/* + * @Author: your name + * @Date: 2021-01-22 16:30:56 + * @LastEditTime: 2021-04-23 15:16:10 + * @LastEditors: Please set LastEditors + * @Description: In User Settings Edit + * @FilePath: \project_freertos\devices\ft2004\bsp\core\ft_asm.h + */ + +#ifndef FT_AARCH32_ASM_H +#define FT_AARCH32_ASM_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ft_types.h" + +#define __ASM __asm +#define __STRINGIFY(x) #x +/* C语言实现MCR指令 */ +#define __MCR(coproc, opcode_1, src, CRn, CRm, opcode_2) \ + __ASM volatile("MCR " __STRINGIFY(p##coproc) ", " __STRINGIFY(opcode_1) ", " \ + "%0, " __STRINGIFY(c##CRn) ", " __STRINGIFY(c##CRm) ", " __STRINGIFY(opcode_2) \ + : \ + : "r"(src) \ + : "memory"); + +/* C语言实现MRC指令 */ +#define __MRC(coproc, opcode_1, CRn, CRm, opcode_2) \ + ({ \ + u32 __dst; \ + __ASM volatile("MRC " __STRINGIFY(p##coproc) ", " __STRINGIFY(opcode_1) ", " \ + "%0, " __STRINGIFY(c##CRn) ", " __STRINGIFY(c##CRm) ", " __STRINGIFY(opcode_2) \ + : "=r"(__dst)::"memory"); \ + __dst; \ + }) + + __attribute__((always_inline)) __STATIC_INLINE u32 __get_VBAR(void) + { + return __MRC(15, 0, 12, 0, 0); + } + + __attribute__((always_inline)) __STATIC_INLINE void __set_VBAR(u32 vbar) + { + __MCR(15, 0, vbar, 12, 0, 0); + } + + __attribute__((always_inline)) __STATIC_INLINE void sys_icc_igrpen0_set(u32 value) + { + __MCR(15, 0, value, 12, 12, 6); + } + + __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_igrpen0_get(void) + { + return __MRC(15, 0, 12, 12, 6); + } + + __attribute__((always_inline)) __STATIC_INLINE void sys_icc_igrpen1_set(u32 value) + { + __MCR(15, 0, value, 12, 12, 7); + } + + __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_igrpen1_get(void) + { + return __MRC(15, 0, 12, 12, 7); + } + + __attribute__((always_inline)) __STATIC_INLINE void sys_icc_ctlr_set(u32 value) + { + __MCR(15, 0, value, 12, 12, 4); + } + + __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_ctlr_get(void) + { + return __MRC(15, 0, 12, 12, 4); + } + + __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_hppir0_get(void) + { + return __MRC(15, 0, 12, 8, 2); + } + + __attribute__((always_inline)) __STATIC_INLINE void sys_icc_bpr_set(u32 value) + { + __MCR(15, 0, value, 12, 12, 3); + } + + __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_bpr_get(void) + { + return __MRC(15, 0, 12, 12, 3); + } + + __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_hppir1_get(void) + { + return __MRC(15, 0, 12, 12, 2); + } + + __attribute__((always_inline)) __STATIC_INLINE void sys_icc_eoir0_set(u32 value) + { + __MCR(15, 0, value, 12, 8, 1); + } + + __attribute__((always_inline)) __STATIC_INLINE void sys_icc_eoir1_set(u32 value) + { + __MCR(15, 0, value, 12, 12, 1); + } + + __attribute__((always_inline)) __STATIC_INLINE void sys_icc_pmr_set(u32 value) + { + __MCR(15, 0, value, 4, 6, 0); + } + + __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_pmr_get(void) + { + return __MRC(15, 0, 4, 6, 0); + } + + __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_iar1_get(void) + { + return __MRC(15, 0, 12, 12, 0); + } + + __attribute__((always_inline)) __STATIC_INLINE void sys_icc_sre_set(u32 value) + { + __MCR(15, 0, value, 12, 12, 5); + } + + __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_sre_get(void) + { + return __MRC(15, 0, 12, 12, 5); + } + + __attribute__((always_inline)) __STATIC_INLINE u32 sys_icc_rpr_get(void) + { + return __MRC(15, 0, 12, 11, 3); + } + + /* Generic Timer registers */ + /** + * @name: arm_aarch32_cntfrq_get + * @msg: This register is provided so that software can discover the frequency of the system counter. + * @return {__STATIC_INLINEu32}: frequency of the system counter + */ + __attribute__((always_inline)) __STATIC_INLINE u32 arm_aarch32_cntfrq_get(void) + { + return __MRC(15, 0, 14, 0, 0); + } + + /** + * @name: arm_aarch32_cnthv_tval_get + * @msg: Provides AArch32 access to the timer value for the EL2 virtual timer. + * @return {__STATIC_INLINEu32}: EL2 virtual timer Cnt. + */ + __attribute__((always_inline)) __STATIC_INLINE u32 arm_aarch32_cnthv_tval_get(void) + { + return __MRC(15, 0, 14, 3, 0); + } + + /** + * @name: arm_aarch32_cnthv_ctl_set + * @msg: Provides AArch32 access to the control register for the EL2 virtual timer. + * @in param {u32}: RegValue;ENABLE: bit [0] 0 Timer disabled,1 Timer enabled. + * IMASK,bit [1]: 0 Timer interrupt is not masked by the IMASK bit. 1 Timer interrupt is masked by the IMASK bit. + * ISTATUS, bit [2]: 0 Timer condition is not met. 1 Timer condition is met. rea-only + */ + __attribute__((always_inline)) __STATIC_INLINE void arm_aarch32_cnthv_ctl_set(u32 RegValue) + { + __MCR(15, 0, RegValue, 14, 3, 1); + } + + /** + * @name: arm_aarch32_cnthv_ctl_get + * @msg: Provides AArch32 access to the control register for the EL2 virtual timer. + * @return {__STATIC_INLINEu32}: RegValue;ENABLE: bit [0] 0 Timer disabled,1 Timer enabled. + * IMASK,bit [1]: 0 Timer interrupt is not masked by the IMASK bit. 1 Timer interrupt is masked by the IMASK bit. + * ISTATUS, bit [2]: 0 Timer condition is not met. 1 Timer condition is met. read-only + */ + __attribute__((always_inline)) __STATIC_INLINE u32 arm_aarch32_cnthv_ctl_get(void) + { + return __MRC(15, 0, 14, 3, 1); + } + + /** + * @name: arm_aarch32_cnthv_tval_set + * @msg: Provides AArch32 access to the timer value for the EL2 virtual timer. + * @in param {u32}: TimerValue, bits [31:0] The TimerValue view of the EL2 virtual timer. + */ + __attribute__((always_inline)) __STATIC_INLINE void arm_aarch32_cnthv_tval_set(u32 RegValue) + { + __MCR(15, 0, RegValue, 14, 3, 0); + } + + /** + * @name: arm_aarch32_cntvct_get + * @msg: Read the register that holds the 64-bit virtual count value. The virtual count value is equal to the physical count value visible in CNTPCT minus the virtual offset visible in CNTVOFF. + * @return {__STATIC_INLINEu64}Bits [63:0] Virtual count value. + */ + __attribute__((always_inline)) __STATIC_INLINE u64 arm_aarch32_cntvct_get(void) + { + /* "r0" --- low, + "r1" --- hi + */ + u32 low; + u32 hi; + __asm__ volatile( + ".word 0xec510f1e \n" /* mrrc p15, 1, r0, r1, c14 */ + "mov %0, r0 \n" + "mov %1, r1 \n" + : "=&r"(low), "=&r"(hi)); + return (((u64)hi) << 32) | low; + } + + /* physical */ + + /** + * @name: arm_aarch32_cntp_tval_get + * @msg: Read the register that holds the timer value for the EL1 physical timer. + * @return {__STATIC_INLINEu32}: TimerValue, bits [31:0] The TimerValue view of the EL1 physical timer. + */ + __attribute__((always_inline)) __STATIC_INLINE u32 arm_aarch32_cntp_tval_get(void) + { + return __MRC(15, 0, 14, 2, 0); + } + + /** + * @name: arm_aarch32_cntp_tval_set + * @msg: write the register that control register for the EL1 physical timer. + * @in param {u32}: TimerValue, bits [31:0] The TimerValue view of the EL1 physical timer. + */ + __attribute__((always_inline)) __STATIC_INLINE void arm_aarch32_cntp_tval_set(u32 RegValue) + { + __MCR(15, 0, RegValue, 14, 2, 0); + } + + /** + * @name: arm_aarch32_cntp_ctl_set + * @msg: write the register that control register for the EL1 physical timer. + * @in param {u32}: ENABLE, bit[0] Enables the timer ; IMASK, bit [1] Timer interrupt mask bit; ISTATUS, bit [2] The status of the timer. + */ + __attribute__((always_inline)) __STATIC_INLINE void arm_aarch32_cntp_ctl_set(u32 RegValue) + { + __MCR(15, 0, RegValue, 14, 2, 1); + } + + /** + * @name: arm_aarch32_cntp_ctl_get + * @msg: Read the register that control register for the EL1 physical timer. + * @return {__STATIC_INLINEu32}: ENABLE, bit[0] Enables the timer ; IMASK, bit [1] Timer interrupt mask bit; ISTATUS, bit [2] The status of the timer. + */ + __attribute__((always_inline)) __STATIC_INLINE u32 arm_aarch32_cntp_ctl_get(void) + { + return __MRC(15, 0, 14, 2, 1); + } + + /** + * @name: arm_aarch32_cntpct_get + * @msg: Read the register that holds the 64-bit physical count value. + * @return {__STATIC_INLINEu64} CompareValue, bits [63:0] Physical count value. + */ + __attribute__((always_inline)) __STATIC_INLINE u64 arm_aarch32_cntpct_get(void) + { + /* "r0" --- low, + "r1" --- hi + */ + u32 low; + u32 hi; + __asm__ volatile( + + ".word 0xec510f0e \n" /* mrrc p15, 0, r0, r1, c14 */ + "mov %0, r0 \n" + "mov %1, r1 \n" + : "=&r"(low), "=&r"(hi)); + return (((u64)hi) << 32) | low; + } + +#define IRQ_DISABLE() \ + __asm volatile("CPSID i" :: \ + : "memory"); \ + __asm volatile("DSB"); \ + __asm volatile("ISB"); + +#define IRQ_ENABLE() \ + __asm volatile("CPSIE i" :: \ + : "memory"); \ + __asm volatile("DSB"); \ + __asm volatile("ISB"); + + /* the exception stack without VFP registers */ + struct ft_hw_exp_stack + { + u32 r0; + u32 r1; + u32 r2; + u32 r3; + u32 r4; + u32 r5; + u32 r6; + u32 r7; + u32 r8; + u32 r9; + u32 r10; + u32 fp; + u32 ip; + u32 sp; + u32 lr; + u32 pc; + u32 cpsr; + }; + +#ifdef __cplusplus +} +#endif + +#endif // ! \ No newline at end of file diff --git a/bsp/ft2004/libraries/device.mk b/bsp/ft2004/libraries/device.mk new file mode 100644 index 0000000000000000000000000000000000000000..73704392823037b01f5a770e758e082e310be718 --- /dev/null +++ b/bsp/ft2004/libraries/device.mk @@ -0,0 +1,12 @@ + + +include $(DEVICE_PATH)/bsp/bsp.mk +include $(DEVICE_PATH)/drivers/drivers.mk +include $(DEVICE_PATH)/component/component.mk + +INCDIRS += $(DEVICE_PATH)/include \ + $(DEVICE_PATH)/cpu +SRCDIRS += $(DEVICE_PATH)/gcc + +# EXCLOUDLE_CFILES += $(DEVICE_PATH)/utilities/test_print.c + diff --git a/bsp/ft2004/libraries/doc/ChangeLog.md b/bsp/ft2004/libraries/doc/ChangeLog.md new file mode 100644 index 0000000000000000000000000000000000000000..b0d6bd9d112281e38a8f45e068e1355f68b5aee4 --- /dev/null +++ b/bsp/ft2004/libraries/doc/ChangeLog.md @@ -0,0 +1,90 @@ +# FT2004-driver ChangeLog + +Change log since v0.1.0 + +# FT2004-driver V0.4.2 Change Log + +## bsp/ft_can + +1. support can controller + +## drivers/rtthread + +1. adapt can drivers to rt-thread + +# FT2004-driver V0.4.2 Change Log + +## bsp/ft_spi + +1. support spi ctrl to read and write spi flash in rt-thread +2. notes that spi chip select pin is ctrl in the way of gpio + +## bsp/ft_gpio + +1. support group A gpio ctrl, include w/r status, change direction + +## component/s25fsxx + +1. support s24fs serial spi flash operations + +## drivers/rtthread + +1. adapt spi drivers to rt-thread SFUD flash support component + +# FT2004-driver V0.4.1 Change Log + +## bsp/ft_i2c + +1. support irq read and write for i2c +2. delete unused rtc and eeprom component + +# FT2004-driver V0.4.0 Change Log + +## component/sdmmc + +1. add sd2.0 comand support +2. modify function and variable name by code convention + +# FT2004-driver V0.3.2 Change Log + +## Docs + +1. add ChangeLog.md + +## bsp/standlone + +1. Added ft_cache.c ft_cache.h + +## bsp/ft_gmac + +1. Added descriptor cache handling + +## drivers/rtthread + +1. Modify the bug for drv_qspi + +1. Added cache to drv_sdctrl + +# FT2004-driver V0.3.1 Change Log + +## Docs + +1. add ChangeLog.md + +## bsp/ft_qspi + +1. Complete the writing of QSPI driver + +2. Test bsp api in rtthread + +## drivers/rtthread + +1. add drv_qspi.c + +2. Access to the SUFD framework + +3. Test functions through the rtthread device management framework + +## exhibition + +![](./figures/v0.3.0_add.png) diff --git a/bsp/ft2004/libraries/doc/figures/v0.3.0_add.png b/bsp/ft2004/libraries/doc/figures/v0.3.0_add.png new file mode 100644 index 0000000000000000000000000000000000000000..d7e6b398490234df5adbf4ceffc91586da1621f5 Binary files /dev/null and b/bsp/ft2004/libraries/doc/figures/v0.3.0_add.png differ diff --git a/bsp/ft2004/libraries/drivers/drivers.mk b/bsp/ft2004/libraries/drivers/drivers.mk new file mode 100644 index 0000000000000000000000000000000000000000..cf1b66f990914a8f31072dd1984a733e927ac55e --- /dev/null +++ b/bsp/ft2004/libraries/drivers/drivers.mk @@ -0,0 +1,13 @@ + + + + +INCDIRS += $(DEVICE_PATH)/drivers\ + $(DEVICE_PATH)/drivers/freertos \ + $(DEVICE_PATH)/drivers/freertos/lwip \ + $(DEVICE_PATH)/drivers/freertos/lwip/system/arch + + +SRCDIRS +=$(DEVICE_PATH)/drivers \ + $(DEVICE_PATH)/drivers/freertos \ + $(DEVICE_PATH)/drivers/freertos/lwip \ No newline at end of file diff --git a/bsp/ft2004/libraries/drivers/freertos/FreeRTOSConfig.h b/bsp/ft2004/libraries/drivers/freertos/FreeRTOSConfig.h new file mode 100644 index 0000000000000000000000000000000000000000..ae47a6bdd4e4131257863f6f7a7c676571bd8cf2 --- /dev/null +++ b/bsp/ft2004/libraries/drivers/freertos/FreeRTOSConfig.h @@ -0,0 +1,235 @@ +/* + * FreeRTOS V202011.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html + *----------------------------------------------------------*/ + +/* + * The FreeRTOS Cortex-A port implements a full interrupt nesting model. + * + * Interrupts that are assigned a priority at or below + * configMAX_API_CALL_INTERRUPT_PRIORITY (which counter-intuitively in the ARM + * generic interrupt controller [GIC] means a priority that has a numerical + * value above configMAX_API_CALL_INTERRUPT_PRIORITY) can call FreeRTOS safe API + * functions and will nest. + * + * Interrupts that are assigned a priority above + * configMAX_API_CALL_INTERRUPT_PRIORITY (which in the GIC means a numerical + * value below configMAX_API_CALL_INTERRUPT_PRIORITY) cannot call any FreeRTOS + * API functions, will nest, and will not be masked by FreeRTOS critical + * sections (although it is necessary for interrupts to be globally disabled + * extremely briefly as the interrupt mask is updated in the GIC). + * + * FreeRTOS functions that can be called from an interrupt are those that end in + * "FromISR". FreeRTOS maintains a separate interrupt safe API to enable + * interrupt entry to be shorter, faster, simpler and smaller. + * + */ +#define configMAX_API_CALL_INTERRUPT_PRIORITY (16 - 1) + +#define configCPU_CLOCK_HZ 100000000UL +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#define configUSE_TICKLESS_IDLE 0 +#define configTICK_RATE_HZ ((TickType_t)100) +#define configUSE_PREEMPTION 1 +#define configUSE_IDLE_HOOK 1 +#define configUSE_TICK_HOOK 1 +#define configMAX_PRIORITIES (7) +#define configMINIMAL_STACK_SIZE ((unsigned short)256) +#define configTOTAL_HEAP_SIZE (4096 * 1024) +#define configMAX_TASK_NAME_LEN (20) +#define configUSE_TRACE_FACILITY 1 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 8 +#define configCHECK_FOR_STACK_OVERFLOW 0 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_MALLOC_FAILED_HOOK 1 +#define configUSE_APPLICATION_TASK_TAG 0 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configUSE_QUEUE_SETS 1 +#define configSUPPORT_STATIC_ALLOCATION 0 +#define configSUPPORT_DYNAMIC_ALLOCATION 1 + +/* Include the query-heap CLI command to query the free heap space. */ +#define configINCLUDE_QUERY_HEAP_COMMAND 1 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES (2) + +/* Software timer definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1) +#define configTIMER_QUEUE_LENGTH 5 +#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 2) + +/* If configUSE_TASK_FPU_SUPPORT is set to 1 (or undefined) then each task will +be created without an FPU context, and a task must call vTaskUsesFPU() before +making use of any FPU registers. If configUSE_TASK_FPU_SUPPORT is set to 2 then +tasks are created with an FPU context by default, and calling vTaskUsesFPU() has +no effect. */ +#define configUSE_TASK_FPU_SUPPORT 1 + +/* Set the following definitions to 1 to include the API function, or zero +to exclude the API function. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 1 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTimerPendFunctionCall 1 +#define INCLUDE_eTaskGetState 1 +#define INCLUDE_xTaskAbortDelay 1 +#define INCLUDE_xTaskGetTaskHandle 1 +#define INCLUDE_xTaskGetHandle 1 +#define INCLUDE_xSemaphoreGetMutexHolder 1 + +/* This demo makes use of one or more example stats formatting functions. These +format the raw data provided by the uxTaskGetSystemState() function in to human +readable ASCII form. See the notes in the implementation of vTaskList() within +FreeRTOS/Source/tasks.c for limitations. */ +#define configUSE_STATS_FORMATTING_FUNCTIONS 1 + +/* Run time stats are not generated. portCONFIGURE_TIMER_FOR_RUN_TIME_STATS and +portGET_RUN_TIME_COUNTER_VALUE must be defined if configGENERATE_RUN_TIME_STATS +is set to 1. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() +#define portGET_RUN_TIME_COUNTER_VALUE() + +/* The size of the global output buffer that is available for use when there +are multiple command interpreters running at once (for example, one on a UART +and one on TCP/IP). This is done to prevent an output buffer being defined by +each implementation - which would waste RAM. In this case, there is only one +command interpreter running. */ +#define configCOMMAND_INT_MAX_OUTPUT_SIZE 2096 + +/* Normal assert() semantics without relying on the provision of an assert.h +header file. */ +// void vAssertCalled(const char *pcFile, unsigned long ulLine); +// #define configASSERT(x) +// if ((x) == 0) +// vAssertCalled(__FILE__, __LINE__); + +#define configASSERT(x) \ + if ((x) == 0) \ + { \ + extern void Ft_printf(const char *fmt, ...); \ + Ft_printf("configASSERT is %s : %d \r\n", __FILE__, __LINE__); \ + taskDISABLE_INTERRUPTS(); \ + for (;;) \ + ; \ + } + +/* If configTASK_RETURN_ADDRESS is not defined then a task that attempts to +return from its implementing function will end up in a "task exit error" +function - which contains a call to configASSERT(). However this can give GCC +some problems when it tries to unwind the stack, as the exit error function has +nothing to return to. To avoid this define configTASK_RETURN_ADDRESS to 0. */ +#define configTASK_RETURN_ADDRESS NULL + +/****** Hardware specific settings. *******************************************/ + +/* + * The application must provide a function that configures a peripheral to + * create the FreeRTOS tick interrupt, then define configSETUP_TICK_INTERRUPT() + * in FreeRTOSConfig.h to call the function. FreeRTOS_Tick_Handler() must + * be installed as the peripheral's interrupt handler. + */ + +#define configSETUP_TICK_INTERRUPT() \ + do \ + { \ + void SystemSetupSystick(u32 tickRateHz, void *tickHandler, u32 intPriority); \ + /* Setup systick with lowest priority */ \ + SystemSetupSystick(configTICK_RATE_HZ, (void *)FreeRTOS_Tick_Handler, (configUNIQUE_INTERRUPT_PRIORITIES - 2) << portPRIORITY_SHIFT); \ + } while (0) + +#define configCLEAR_TICK_INTERRUPT() \ + do \ + { \ + } while (0) + +#define FreeRTOS_IRQ_Handler IRQ_Handler +#define FreeRTOS_SWI_Handler SVC_Handler + +#define configINTERRUPT_CONTROLLER_BASE_ADDRESS (0x71800000) +#define configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET (0x2000UL) +#define configUNIQUE_INTERRUPT_PRIORITIES 16 + +/****** Network configuration settings - only used when the lwIP example is +built. See the page that documents this demo on the http://www.FreeRTOS.org +website for more information. ***********************************************/ + +/* The priority for the task that unblocked by the MAC interrupt to process +received packets. */ +#define configMAC_INPUT_TASK_PRIORITY (configMAX_PRIORITIES - 1) + +/* The priority of the task that runs the lwIP stack. */ +#define configLWIP_TASK_PRIORITY (configMAX_PRIORITIES - 2) + +/* The priority of the task that uses lwIP sockets to provide a simple command +line interface. */ +#define configCLI_TASK_PRIORITY (tskIDLE_PRIORITY) + +/* MAC address configuration. */ +#define configMAC_ADDR0 0x00 +#define configMAC_ADDR1 0x13 +#define configMAC_ADDR2 0x14 +#define configMAC_ADDR3 0x15 +#define configMAC_ADDR4 0x15 +#define configMAC_ADDR5 0x16 + +/* IP address configuration. */ +#define configIP_ADDR0 172 +#define configIP_ADDR1 25 +#define configIP_ADDR2 218 +#define configIP_ADDR3 200 + +/* Netmask configuration. */ +#define configNET_MASK0 255 +#define configNET_MASK1 255 +#define configNET_MASK2 255 +#define configNET_MASK3 0 + +#endif /* FREERTOS_CONFIG_H */ diff --git a/bsp/ft2004/libraries/drivers/freertos/ft_os_gmac.c b/bsp/ft2004/libraries/drivers/freertos/ft_os_gmac.c new file mode 100644 index 0000000000000000000000000000000000000000..c0e2504cbfe5a6ffaab5317cee9239d4988e572c --- /dev/null +++ b/bsp/ft2004/libraries/drivers/freertos/ft_os_gmac.c @@ -0,0 +1,186 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-07 15:00:19 + * @Description:  This files is for freertos gmac ports + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_os_gmac.h" +#include "ft_gmac.h" +#include "ft_assert.h" +#include "ft_io.h" +#include "system_gic.h" +#include "ft_list.h" +#include "ft_debug.h" + +#include +#include +#include + +#include + +#define OS_MAC_DEBUG_TAG "OS_MAC" + +#define OS_MAC_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(OS_MAC_DEBUG_TAG, format, ##__VA_ARGS__) +#define OS_MAC_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(OS_MAC_DEBUG_TAG, format, ##__VA_ARGS__) +#define OS_MAC_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(OS_MAC_DEBUG_TAG, format, ##__VA_ARGS__) + +#define FT_OS_GMACOBJECT_READLY 0x58 + +/** + * @name: Ft_Os_GmacMem_Create + * @msg: Initialize the Gmac TX/Rx Describe Memory 。 + * @param {*} + * @return {*} + */ +static void Ft_Os_GmacMem_Create(Ft_Os_Gmac *Os_Gmac) +{ + Os_Gmac->Rxbuffer = pvPortMalloc(RX_DESCNUM * GMAC_MAX_PACKET_SIZE); + if (Os_Gmac->Rxbuffer == NULL) + { + OS_MAC_DEBUG_E("Rxbuffer Malloc is error "); + Ft_assertVoidAlways(); + } + + Os_Gmac->Txbuffer = pvPortMalloc(TX_DESCNUM * GMAC_MAX_PACKET_SIZE); + if (Os_Gmac->Txbuffer == NULL) + { + OS_MAC_DEBUG_E("Txbuffer Malloc is error "); + Ft_assertVoidAlways(); + } + + Os_Gmac->Gmac.TxDesc = pvPortMalloc(TX_DESCNUM * sizeof(FGmac_DmaDesc_t)); + if (Os_Gmac->Gmac.TxDesc == NULL) + { + OS_MAC_DEBUG_E("TxDesc Malloc is error "); + Ft_assertVoidAlways(); + } + + Os_Gmac->Gmac.RxDesc = pvPortMalloc(RX_DESCNUM * sizeof(FGmac_DmaDesc_t) + 128); + if (Os_Gmac->Gmac.RxDesc == NULL) + { + OS_MAC_DEBUG_E("RxDesc Malloc is error "); + Ft_assertVoidAlways(); + } + + OS_MAC_DEBUG_E("RxDesc fit before addr %x ", Os_Gmac->Gmac.RxDesc); + +#define ROUND_UP(x, align) (((long)(x) + ((long)align - 1)) & \ + ~((long)align - 1)) + + Os_Gmac->Gmac.RxDesc = (FGmac_DmaDesc_t *)ROUND_UP(Os_Gmac->Gmac.RxDesc, 128); + OS_MAC_DEBUG_E("RxDesc fit after addr %x ", Os_Gmac->Gmac.RxDesc); +} + +static void Ft_Os_GmacMem_Free(Ft_Os_Gmac *Os_Gmac) +{ + if (Os_Gmac->Rxbuffer) + { + vPortFree(Os_Gmac->Rxbuffer); + } + + if (Os_Gmac->Txbuffer) + { + vPortFree(Os_Gmac->Txbuffer); + } + + if (Os_Gmac->Gmac.RxDesc) + { + vPortFree(Os_Gmac->Gmac.RxDesc); + } + + if (Os_Gmac->Gmac.TxDesc) + { + vPortFree(Os_Gmac->Gmac.TxDesc); + } +} + +/** + * @name: Ft_Os_GmacObject_Init + * @msg: + * @param {Ft_Os_Gmac} *Os_Gmac + * @param {Ft_Os_Gmac_Config} *Config + * @return {*} + */ +void Ft_Os_GmacObject_Init(Ft_Os_Gmac *Os_Gmac, Ft_Os_Gmac_Config *Config) +{ + Ft_assertVoid(Os_Gmac != NULL); + Ft_assertVoid(Os_Gmac->IsReady != FT_OS_GMACOBJECT_READLY); + memset(Os_Gmac, 0, sizeof(Ft_Os_Gmac)); + Os_Gmac->Config = *Config; + Os_Gmac->IsReady = FT_OS_GMACOBJECT_READLY; +} + +/** + * @name: Ft_Os_Gmac_Init + * @msg: + * @param {Ft_Os_Gmac} *Os_Gmac + * @param {u32} InstanceId + * @return {*} + */ +void Ft_Os_Gmac_Init(Ft_Os_Gmac *Os_Gmac) +{ + Ft_Gmac_t *Gmac; + Ft_assertVoid(Os_Gmac != NULL); + Ft_assertVoid((Os_Gmac->IsReady == FT_OS_GMACOBJECT_READLY)); + Gmac = &Os_Gmac->Gmac; + Ft_Os_GmacMem_Free(Os_Gmac); + Ft_assertVoid(Ft_GmacCfgInitialize(Gmac, Ft_Gmac_LookupConfig(Os_Gmac->Config.Gmac_Instance)) == FST_SUCCESS); + Ft_Os_GmacMem_Create(Os_Gmac); + + /* Create a binary semaphore used for informing ethernetif of frame reception */ + Ft_assertVoid((Os_Gmac->s_xSemaphore = xSemaphoreCreateBinary()) != NULL); + /* Create a event group used for ethernetif of status change */ + Ft_assertVoid((Os_Gmac->s_xStatusEvent = xEventGroupCreate()) != NULL); +} + +/** + * @name: Ft_Os_Gmac_Start + * @msg: + * @param {Ft_Os_Gmac} *Os_Gmac + * @return {*} + */ +void Ft_Os_Gmac_Start(Ft_Os_Gmac *Os_Gmac) +{ + Ft_Gmac_t *Gmac; + Ft_assertVoid(Os_Gmac != NULL); + Ft_assertVoid((Os_Gmac->IsReady == FT_OS_GMACOBJECT_READLY)); + Gmac = &Os_Gmac->Gmac; + u32 ret; + + ret = Ft_Gmac_HwInitialize(Gmac); + if (FST_SUCCESS != ret) + { + OS_MAC_DEBUG_E("Gmac return err code %d\r\n", ret); + Ft_assertVoid(FST_SUCCESS == ret); + } + + /* Initialize Rx Description list : ring Mode */ + FGmac_DmaRxDescRingInit(Gmac, Gmac->RxDesc, Os_Gmac->Rxbuffer, GMAC_MAX_PACKET_SIZE, RX_DESCNUM); + + /* Initialize Tx Description list : ring Mode */ + FGmac_DmaTxDescRingInit(Gmac, Gmac->TxDesc, Os_Gmac->Txbuffer, GMAC_MAX_PACKET_SIZE, TX_DESCNUM); + + Ft_Gmac_Start(Gmac); + /* Gmac interrupt init */ + System_Gic_Enable(Gmac->Config.IRQ_NUM, (FGicv3_InterruptHandler_t)FGmac_IntrHandler, Gmac->Config.IRQPriority, Gmac); + + return; +} + +void Ft_Os_Gmac_Stop(Ft_Os_Gmac *Os_Gmac) +{ + Ft_Gmac_t *Gmac; + + Ft_assertVoid(Os_Gmac != NULL); + Ft_assertVoid((Os_Gmac->IsReady == FT_OS_GMACOBJECT_READLY)); + Gmac = &Os_Gmac->Gmac; + Ft_Gmac_Stop(Gmac); +} \ No newline at end of file diff --git a/bsp/ft2004/libraries/drivers/freertos/ft_os_gmac.h b/bsp/ft2004/libraries/drivers/freertos/ft_os_gmac.h new file mode 100644 index 0000000000000000000000000000000000000000..3f91bb6d7e3ec9646c55ab68d003935778fb8e7b --- /dev/null +++ b/bsp/ft2004/libraries/drivers/freertos/ft_os_gmac.h @@ -0,0 +1,84 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-20 09:51:46 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef FT_OS_GMAC_H +#define FT_OS_GMAC_H +#include "ft_gmac.h" +#include "ft_parameters.h" + +#include +#include +#include + +#include "lwip/netif.h" + +#define FT_OS_GMAC0_ID FT_GMAC0_ID +#define FT_OS_GMAC1_ID FT_GMAC1_ID + +#ifdef PHY_USING_AR8035 +#define USE_LWIP +#endif + +#define FT_NETIF_LINKUP 0x1U +#define FT_NETIF_DOWN 0x2U + +struct Ipv4Address +{ + u8 Ip_Address[4]; + u8 Netmask_Address[4]; + u8 GateWay_Address[4]; +}; + +struct GmacThread +{ + const char *Thread_Name; + u16 StackDepth; /* The number of words the stack */ + u32 Priority; /* Defines the priority at which the task will execute. */ + TaskHandle_t Thread_Handle; +}; + +typedef struct +{ + u32 Gmac_Instance; /* select Gmac global object */ + u32 Isr_Priority; /* irq Priority */ + struct Ipv4Address Address; + + /* Gmac input thread */ + struct GmacThread MacInputThread; + struct GmacThread MacStatusThread; + +} Ft_Os_Gmac_Config; + +typedef struct +{ + Ft_Gmac_t Gmac; + struct netif Netif_Object; + Ft_Os_Gmac_Config Config; + u8 *Rxbuffer; /* Buffer for RxDesc */ + u8 *Txbuffer; /* Buffer for TxDesc */ + u8 IsReady; /* Ft_Os_Gmac Object first need Init use Ft_Os_GmacObjec_Init */ + + SemaphoreHandle_t s_xSemaphore; /* Semaphore to signal incoming packets */ + EventGroupHandle_t s_xStatusEvent; /* Event Group to show netif's status ,follow FT_NETIF_XX*/ +} Ft_Os_Gmac; +void Ft_Os_GmacObject_Init(Ft_Os_Gmac *Os_Gmac, Ft_Os_Gmac_Config *Config); +void Ft_Os_Gmac_Init(Ft_Os_Gmac *Ft_Os_Gmac); +void Ft_Os_Gmac_Start(Ft_Os_Gmac *Os_Gmac); +void Ft_Os_Gmac_Stop(Ft_Os_Gmac *Os_Gmac); + +#ifdef USE_LWIP + +#endif + +#endif // ! FT_OS_GMAC_H \ No newline at end of file diff --git a/bsp/ft2004/libraries/drivers/freertos/ft_os_i2c.c b/bsp/ft2004/libraries/drivers/freertos/ft_os_i2c.c new file mode 100644 index 0000000000000000000000000000000000000000..f6a2efc38953a324ffe9e4f648b03fdcf5533b86 --- /dev/null +++ b/bsp/ft2004/libraries/drivers/freertos/ft_os_i2c.c @@ -0,0 +1,232 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-21 09:29:56 + * @LastEditTime: 2021-04-23 10:11:00 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include +#include +#include +#include +#include "ft_os_i2c.h" +#include "ft_i2c.h" +#include "system_gic.h" + +static FI2C_t g_I2cCtrl[MAX_I2C_CTRL_ID]; + +inline static FI2C_t *FOS_getI2cCtrl(FI2C_Instance_t id) +{ + return &g_I2cCtrl[id]; +} + +static void FOS_waitI2cCallback(const u32 IrqType, + void *pArg) +{ + FI2C_t *pDev = (FI2C_t *)pArg; + u32 irqMask; + + /* wait for TX over signal */ + EventBits_t ev = 0; + + Ft_assertNoneReturn(NULL != pDev); + + irqMask = FI2C_getIrqMask(pDev); + FI2C_setIrqMask(pDev, irqMask); + + FT_I2C_DEBUG_I("%d wait for event mask 0x%x", IrqType, FI2C_getIrqMask(pDev)); + switch (IrqType) + { + case I2C_IRQ_TYPE_TX_COMPLETE: + ev = xEventGroupWaitBits(pDev->pTxEvent, + FOS_I2C_TX_OVER_EVT, + pdTRUE, pdFALSE, I2C_TIMEOUT); + break; + case I2C_IRQ_TYPE_RX_COMPLETE: + ev = xEventGroupWaitBits(pDev->pRxEvent, + FOS_I2C_RX_OVER_EVT, + pdTRUE, pdFALSE, I2C_TIMEOUT); + break; + default: + Ft_assertNoneReturn(0); + break; + } + + if (ev & FOS_I2C_TX_OVER_EVT) + { + FT_I2C_DEBUG_I("recev tx over event"); + } + else if (ev & FOS_I2C_RX_OVER_EVT) + { + FT_I2C_DEBUG_I("recev rx over event"); + } + else + { + FT_I2C_ERROR("wait evt timeout"); + pDev->LastIrqErr = ERR_I2C_EVT_TIMEOUT; + } + + return; +} + +static void FOS_irqI2cCallback(const u32 IrqType, + void *pArg, + void *pData) +{ + FI2C_t *pDev = (FI2C_t *)pArg; + + /* send RX over signal */ + BaseType_t xResult = pdFALSE; + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + + Ft_assertNoneReturn((NULL != pDev)); + + switch (IrqType) + { + case I2C_IRQ_TYPE_TX_COMPLETE: + xResult = xEventGroupSetBitsFromISR(pDev->pTxEvent, + FOS_I2C_TX_OVER_EVT, + &xHigherPriorityTaskWoken); + break; + case I2C_IRQ_TYPE_RX_COMPLETE: + xResult = xEventGroupSetBitsFromISR(pDev->pRxEvent, + FOS_I2C_RX_OVER_EVT, + &xHigherPriorityTaskWoken); + break; + default: + Ft_assertNoneReturn(0); + break; + } + FT_I2C_DEBUG_I("send signal %d, result %d", IrqType, xResult); + + if (pdFAIL != xResult) + { + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + } + + return; +} + +void FOS_deInitI2cCtrl(FI2C_Instance_t Id) +{ + FI2C_deInitMaster(FOS_getI2cCtrl(Id)); +} + +u32 FOS_initI2cCtrl(FOS_I2cConfig_t *pConf) +{ + u32 ret = ERR_I2C_OK; + u32 irqMask; + u32 txBufSize; + u32 rxBufSize; + FI2C_t *pCtrl = FOS_getI2cCtrl(pConf->Id); + if (I2C_MASTER_DEV == pConf->DevType) + { + FI2C_initMaster(pConf->Id, pConf->WorkMode,pConf->SlaveAddr, + pConf->UseWRFIFO, + pConf->PageSize, pCtrl); + } + else + { + return ERR_I2C_NOT_SUPPORT; + } + + if (ERR_I2C_OK != ret) + { + return ret; + } + + if (I2C_IRQ_MODE == pConf->WorkMode) + { + /* enable some irq */ + irqMask = I2C_IRQ_TX_ABRT | I2C_IRQ_STOP_DET | + I2C_IRQ_START_DET | I2C_IRQ_RX_OVER | I2C_IRQ_RX_FULL | + I2C_IRQ_TX_OVER | I2C_IRQ_TX_EMPTY; + + //I2C_IRQ_DEFAULT_MASK; //I2C_IRQ_RX_OVER | I2C_IRQ_TX_OVER; + FI2C_setIrqMask(pCtrl, irqMask); + //FT_I2C_DEBUG_I("set irq mask 0x%x", FI2C_getIrqMask(pCtrl)); + + /* register irq handler */ + pCtrl->pIrqCallBack = FOS_irqI2cCallback; + pCtrl->pWaitCallBack = FOS_waitI2cCallback; + + /* create sync event */ + pCtrl->pRxEvent = xEventGroupCreate(); + pCtrl->pTxEvent = xEventGroupCreate(); + if (!pCtrl->pRxEvent || !pCtrl->pTxEvent) + { + FT_I2C_ERROR("alloc event failed!!!"); + ret = ERR_I2C_INVALID_NO_MEM; + goto EXIT; + } + + /* register i2c irq to gic */ + if (pConf->UseWRFIFO) + { + System_Gic_Enable(g_FI2cIrqNum[pConf->Id], + (FGicv3_interruptHandler)FI2C_irqHandler4Fifo, + I2C_DEFAULT_IRQ_PRIORITY, + pCtrl); + } + else + { + System_Gic_Enable(g_FI2cIrqNum[pConf->Id], + (FGicv3_interruptHandler)FI2C_irqHandler, + I2C_DEFAULT_IRQ_PRIORITY, + pCtrl); + } + } + +EXIT: + return ret; +} + +u32 FOS_i2cRead(FOS_I2cConfig_t *pConf) +{ + FI2C_t *pDev = FOS_getI2cCtrl(pConf->Id); + FI2C_Buffer_t *pBuf = &pDev->RxBuf; + u32 ret; + if (pConf->UseWRFIFO) + { + pBuf->BytePtr = pConf->pRxBuf; + pBuf->DataLength = pConf->RxBufSize ; + pBuf->CurIndex = 0; + ret = FI2C_readByFifo(pConf->PageAddr, pDev); + } + else + { + ret = FI2C_readByByte(pConf->RxBufSize, pConf->pRxBuf, + pConf->PageAddr, pDev); + } + + return ret; +} + +u32 FOS_i2cWrite(FOS_I2cConfig_t *pConf) +{ + FI2C_t *pDev = FOS_getI2cCtrl(pConf->Id); + FI2C_Buffer_t *pBuf = &pDev->TxBuf; + u32 ret = ERR_I2C_OK; + if (pConf->UseWRFIFO) + { + pBuf->BytePtr = pConf->pTxBuf; + pBuf->DataLength = pConf->TxBufSize; + pBuf->CurIndex = 0; + + ret = FI2C_writeByFifo(pConf->PageAddr, pDev); + } + else + { + ret = FI2C_writeByByte(pConf->TxBufSize, pConf->pTxBuf, + pConf->PageAddr, pDev); + } + + return ret; +} \ No newline at end of file diff --git a/bsp/ft2004/libraries/drivers/freertos/ft_os_i2c.h b/bsp/ft2004/libraries/drivers/freertos/ft_os_i2c.h new file mode 100644 index 0000000000000000000000000000000000000000..e0b99adfb760d5b92c31632f02cc7759c2aecb2e --- /dev/null +++ b/bsp/ft2004/libraries/drivers/freertos/ft_os_i2c.h @@ -0,0 +1,55 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-21 09:29:48 + * @LastEditTime: 2021-04-23 09:24:59 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef FT_FREERTOS_I2C_H +#define FT_FREERTOS_I2C_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ft_i2c.h" + +/* RX event */ +#define FOS_I2C_RX_OVER_EVT (0x01 << 0) + +/* TX event */ +#define FOS_I2C_TX_OVER_EVT (0x01 << 0) + +typedef struct +{ + FI2C_Instance_t Id; + FI2C_DevType_t DevType; + FI2C_WorkMode_t WorkMode; + u32 SlaveAddr; + u32 PageAddr; + u32 PageSize; + u8 *pTxBuf; + u32 TxBufSize; + u8 *pRxBuf; + u32 RxBufSize; + bool_t UseWRFIFO; +}FOS_I2cConfig_t; + +u32 FOS_initI2cCtrl(FOS_I2cConfig_t *config); +void FOS_deInitI2cCtrl(FI2C_Instance_t Id); +u32 FOS_i2cRead(FOS_I2cConfig_t *config); +u32 FOS_i2cWrite(FOS_I2cConfig_t *config); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/bsp/ft2004/libraries/drivers/freertos/ft_os_uart.c b/bsp/ft2004/libraries/drivers/freertos/ft_os_uart.c new file mode 100644 index 0000000000000000000000000000000000000000..fb08cba36809e2fcda839ce6864c3e9e1885dc2a --- /dev/null +++ b/bsp/ft2004/libraries/drivers/freertos/ft_os_uart.c @@ -0,0 +1,229 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-07 15:40:07 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_os_uart.h" +#include "ft_uart.h" +#include "ft_printf.h" +#include "system_gic.h" +#include "ft_types.h" +#include "ft_status.h" + +extern u32 FUart_GetInterruptMask(Ft_Uart *UartPtr); +extern void FUart_SetInterruptMask(Ft_Uart *UartPtr, u32 Mask); + +/* Callback events */ + +static void Ft_Os_Uart_Callback(void *Args, u32 Event, u32 EventData) +{ + Ft_Os_Uart *OsUartPtr = (Ft_Os_Uart *)Args; + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + BaseType_t xResult = pdFALSE; + u32 RegTemp; + if (FUART_EVENT_RECV_DATA == Event || FUART_EVENT_RECV_TOUT == Event) + { + xResult = xEventGroupSetBitsFromISR(OsUartPtr->rxEvent, RTOS_UART_COMPLETE, &xHigherPriorityTaskWoken); + } + else if (FUART_EVENT_RECV_ERROR == Event) + { + xResult = xEventGroupSetBitsFromISR(OsUartPtr->rxEvent, RTOS_UART_RECV_ERROR, &xHigherPriorityTaskWoken); + } + else if (FUART_EVENT_SENT_DATA == Event) + { + + xResult = xEventGroupSetBitsFromISR(OsUartPtr->txEvent, RTOS_UART_RECV_ERROR, &xHigherPriorityTaskWoken); + } + else if (FUART_EVENT_PARE_FRAME_BRKE == Event) + { + xResult = xEventGroupSetBitsFromISR(OsUartPtr->rxEvent, RTOS_UART_RECV_ERROR, &xHigherPriorityTaskWoken); + } + else if (FUART_EVENT_RECV_ORERR == Event) + { + } + + if (FUART_EVENT_SENT_DATA == Event) + { + } + else + { + //UartObj); + RegTemp &= ~UARTMIS_RTMIS; + FUart_SetInterruptMask(&OsUartPtr->UartObj, RegTemp); + } + + if (xResult != pdFAIL) + { + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + } +} + +void Ft_Os_UartInit(Ft_Os_Uart *OsUartPtr, Ft_Os_Uart_Config *Config) +{ + Ft_Uart *UartPtr = NULL; + Ft_assertVoid(OsUartPtr != NULL); + Ft_assertVoid(Config != NULL); + UartPtr = &OsUartPtr->UartObj; + Ft_printf("OsUartPtr %x", OsUartPtr); + Ft_assertVoid(FUart_CfgInitialize(UartPtr, FUart_LookupConfig(Config->Uart_Instance)) == FST_SUCCESS); + FUart_SetHandler(UartPtr, Ft_Os_Uart_Callback, OsUartPtr); + Ft_assertVoid((OsUartPtr->rxSemaphore = xSemaphoreCreateMutex()) != NULL); + Ft_assertVoid((OsUartPtr->txSemaphore = xSemaphoreCreateMutex()) != NULL); + Ft_assertVoid((OsUartPtr->txEvent = xEventGroupCreate()) != NULL); + Ft_assertVoid((OsUartPtr->rxEvent = xEventGroupCreate()) != NULL); + System_Gic_Enable(OsUartPtr->UartObj.Config.IsrNum, (FGicv3_InterruptHandler_t)FUart_InterruptHandler, Config->Isr_Priority, UartPtr); + FUart_SetOptions(UartPtr, FUART_OPTION_UARTEN | FUART_OPTION_RXEN | FUART_OPTION_TXEN | FUART_OPTION_FIFOEN); +} + +/** + * @name: Ft_Os_ReceiveBuffer + * @msg: + * @param {Ft_Os_Uart} *OsUartPtr + * @param {u8} *buffer + * @param {u32} length + * @param {u32} *Received + * @return {*} + */ +s32 Ft_Os_UartReceiveBuffer(Ft_Os_Uart *OsUartPtr, u8 *buffer, u32 length, u32 *Received) +{ + u32 GetLength; + Ft_Uart *UartPtr; + EventBits_t ev; + s32 ret; + if (NULL == OsUartPtr) + { + return FST_INSTANCE_NOT_FOUND; + } + + if (NULL == buffer) + { + return FST_FAILURE; + } + + if (NULL == Received) + { + return FST_FAILURE; + } + + if (0 == length) + { + *Received = 0; + return FST_SUCCESS; + } + + UartPtr = &OsUartPtr->UartObj; + + /* New transfer can be performed only after current one is finished */ + if (pdFALSE == xSemaphoreTake(OsUartPtr->rxSemaphore, portMAX_DELAY)) + { + /* We could not take the semaphore, exit with 0 data received */ + ret = FST_FAILURE; + } + + GetLength = FUart_Receive(UartPtr, buffer, length); + if (GetLength > 0) + { + *Received = GetLength; + ret = FST_SUCCESS; + } + else + { + u32 RegTemp; + + RegTemp = FUart_GetInterruptMask(UartPtr); + RegTemp |= UARTMIS_RTMIS; + FUart_SetInterruptMask(UartPtr, RegTemp); + + ev = xEventGroupWaitBits(OsUartPtr->rxEvent, + RTOS_UART_COMPLETE | RTOS_UART_HARDWARE_BUFFER_OVERRUN | RTOS_UART_RECV_ERROR, + pdTRUE, pdFALSE, portMAX_DELAY); + + if (ev & RTOS_UART_HARDWARE_BUFFER_OVERRUN) + { + ret = FST_FIFO_ERROR; + *Received = 0; + } + else if (ev & RTOS_UART_COMPLETE) + { + ret = FST_SUCCESS; + *Received = UartPtr->ReceiveBuffer.RequestedBytes - UartPtr->ReceiveBuffer.RemainingBytes; + } + else if (ev & RTOS_UART_RECV_ERROR) + { + ret = FST_RECV_ERROR; + *Received = 0; + } + else + { + ret = FST_INVALID_PARAM; + *Received = 0; + } + } + + /* Enable next transfer. Current one is finished */ + if (pdFALSE == xSemaphoreGive(OsUartPtr->rxSemaphore)) + { + /* We could not post the semaphore, exit with error */ + Ft_printf("FST_FAILURE xSemaphoreGive \r\n"); + ret = FST_FAILURE; + } + + return ret; +} + +/** + * @name: + * @msg: + * @param {Ft_Os_Uart} *OsUartPtr + * @param {u8} *buffer + * @param {u32} length + * @return {*} + */ +s32 Ft_Os_UartBlockingSend(Ft_Os_Uart *OsUartPtr, u8 *buffer, u32 length) +{ + s32 ret = FST_SUCCESS; + Ft_Uart *UartPtr; + EventBits_t ev; + if (NULL == OsUartPtr) + { + return FST_INSTANCE_NOT_FOUND; + } + + if (NULL == buffer) + { + return FST_FAILURE; + } + + UartPtr = &OsUartPtr->UartObj; + + if (pdFALSE == xSemaphoreTake(OsUartPtr->txSemaphore, portMAX_DELAY)) + { + return FST_FAILURE; + } + + FUart_Send(UartPtr, buffer, length); + + ev = xEventGroupWaitBits(OsUartPtr->txEvent, RTOS_UART_COMPLETE, pdTRUE, pdFALSE, portMAX_DELAY); + if (!(ev & RTOS_UART_COMPLETE)) + { + ret = FST_FAILURE; + } + + if (pdFALSE == xSemaphoreGive(OsUartPtr->txSemaphore)) + { + /* We could not post the semaphore, exit with error */ + ret = FST_FAILURE; + } + + return ret; +} \ No newline at end of file diff --git a/bsp/ft2004/libraries/drivers/freertos/ft_os_uart.h b/bsp/ft2004/libraries/drivers/freertos/ft_os_uart.h new file mode 100644 index 0000000000000000000000000000000000000000..1b0ae3c13fb4b3cb0c9ac0187a43acccdd738212 --- /dev/null +++ b/bsp/ft2004/libraries/drivers/freertos/ft_os_uart.h @@ -0,0 +1,67 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-07 15:40:12 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + + +#ifndef FT_OS_UART_H +#define FT_OS_UART_H + +#include "ft_uart.h" +#include "ft_parameters.h" +#include +#include +#include + +#include "ft_types.h" + +#define UART0_ID FT_UART0_ID +#define UART1_ID FT_UART1_ID +#define UART2_ID FT_UART2_ID +#define UART3_ID FT_UART3_ID + +/*! +* @cond RTOS_PRIVATE +* @name UART FreeRTOS handler +* +* These are the only valid states for txEvent and rxEvent +*/ +/*@{*/ +/*! @brief Event flag - transfer complete. */ +#define RTOS_UART_COMPLETE 0x1 +/*! @brief Event flag - hardware buffer overrun. */ +#define RTOS_UART_HARDWARE_BUFFER_OVERRUN 0x2 +/*! @brief Event flag Receive is error */ +#define RTOS_UART_RECV_ERROR 0x4 + +/*@}*/ + +typedef struct +{ + u32 Uart_Instance; /* select uart global object */ + u32 Isr_Priority; /* irq Priority */ +} Ft_Os_Uart_Config; + +typedef struct +{ + Ft_Uart UartObj; /* Uart Object */ + SemaphoreHandle_t rxSemaphore; /*!< RX semaphore for resource sharing */ + SemaphoreHandle_t txSemaphore; /*!< TX semaphore for resource sharing */ + EventGroupHandle_t rxEvent; /*!< RX completion event */ + EventGroupHandle_t txEvent; /*!< TX completion event */ +} Ft_Os_Uart; + +void Ft_Os_UartInit(Ft_Os_Uart *OsUartPtr, Ft_Os_Uart_Config *Config); +s32 Ft_Os_UartBlockingSend(Ft_Os_Uart *OsUartPtr, u8 *buffer, u32 length); +s32 Ft_Os_UartReceiveBuffer(Ft_Os_Uart *OsUartPtr, u8 *buffer, u32 length, u32 *Received); + +#endif // ! diff --git a/bsp/ft2004/libraries/drivers/freertos/system_ft2004.c b/bsp/ft2004/libraries/drivers/freertos/system_ft2004.c new file mode 100644 index 0000000000000000000000000000000000000000..459ae1ae9e54b81cd080de9bf2b864444fd3545c --- /dev/null +++ b/bsp/ft2004/libraries/drivers/freertos/system_ft2004.c @@ -0,0 +1,88 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-07 15:40:19 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_assert.h" +#include "ft_printf.h" +#include "system_gic.h" +#include "ft_generic_timer.h" +#include "ft_aarch32_asm.h" + +static void AssertCallback(FT_IN s8 *File, s32 Line) +{ + Ft_printf("Assert Error is %s : %d \r\n", File, Line); +} + +void SystemInit(void) +{ + // + +#ifdef BSP_USE_CAN + +#define LOG_TAG "drv_can" +#include + +#define _CAN0_NAME "can0" +#define _CAN1_NAME "can1" + +#define RTHW_CAN_WAIT(_can) rt_sem_take(&_can->recv_semaphore, RT_WAITING_FOREVER); +#define RTHW_CAN_SEND(_can) rt_sem_release(&_can->recv_semaphore); + +#ifdef BSP_USING_CAN0 +struct ft2004_can drv_can0 = + { + .name = _CAN0_NAME, + .can_handle.Config.InstanceId = 0}; +#endif + +#ifdef BSP_USING_CAN1 +struct ft2004_can drv_can1 = + { + .name = _CAN1_NAME, + .can_handle.Config.InstanceId = 1}; +#endif + +static void _can_recv_irq(void *args) +{ + struct ft2004_can *drv_can = (struct ft2004_can *)args; + RTHW_CAN_SEND(drv_can); +} + +static void rt_hw_inner_can_isr(int irqno, void *param) +{ + FCan_IntrHandler(param); +} + +static rt_err_t _can_config(struct rt_can_device *can, struct can_configure *cfg) +{ + struct FCan_Bittiming bit_timing = {0}; + struct ft2004_can *drv_can; + RT_ASSERT(can); + RT_ASSERT(cfg); + drv_can = (struct ft2004_can *)can->parent.user_data; + RT_ASSERT(drv_can); + + FCan_CfgInitialize(&drv_can->can_handle, FCan_LookupConfig(drv_can->can_handle.Config.InstanceId)); + + FCan_SetHandler(&drv_can->can_handle, FCAN_HANDLER_RECV, _can_recv_irq, drv_can); + + bit_timing.bitrate = cfg->baud_rate; + + if (FCan_CalcBittiming(&bit_timing) != FCAN_SUCCESS) + { + LOG_E("Setting baud rate %x is not valid \r\n", bit_timing.bitrate); + return -RT_ERROR; + } + + FCan_SetTiming(&drv_can->can_handle, &bit_timing); + + rt_hw_interrupt_set_priority(drv_can->can_handle.Config.IrqNum, 16); + rt_hw_interrupt_install(drv_can->can_handle.Config.IrqNum, rt_hw_inner_can_isr, &drv_can->can_handle, drv_can->name); + rt_hw_interrupt_umask(drv_can->can_handle.Config.IrqNum); + + FCan_Enable(&drv_can->can_handle); + + return RT_EOK; +} + +static rt_err_t _can_control(struct rt_can_device *can, int cmd, void *arg) +{ + return RT_EOK; +} + +static int _can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t box_num) +{ + struct ft2004_can *drv_can; + struct rt_can_msg *pmsg = (struct rt_can_msg *)buf; + struct FCan_Frame can_frame = {0}; + RT_ASSERT(can); + drv_can = (struct ft2004_can *)can->parent.user_data; + RT_ASSERT(drv_can); + + /* Check the parameters */ + RT_ASSERT(pmsg->len <= 8U); + + if (RT_CAN_STDID == pmsg->ide) + { + can_frame.CanId = pmsg->id; + } + else + { + can_frame.CanId = pmsg->id; + can_frame.CanId |= CAN_EFF_FLAG; + } + + if (RT_CAN_DTR == pmsg->rtr) + { + } + else + { + can_frame.CanId |= CAN_RTR_FLAG; + } + + can_frame.CanDlc = pmsg->len & 0x0FU; + memcpy(can_frame.data, pmsg->data, 8); + + return (FCan_SendByIrq(&drv_can->can_handle, &can_frame, 1, RT_NULL) == 1) ? RT_EOK : -RT_ERROR; +} + +static int _can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t fifo) +{ + struct ft2004_can *drv_can; + struct rt_can_msg *pmsg = (struct rt_can_msg *)buf; + RT_ASSERT(can); + struct FCan_Frame recv_frame = {0}; + drv_can = (struct ft2004_can *)can->parent.user_data; + RT_ASSERT(drv_can); + + RTHW_CAN_WAIT(drv_can); + + if (FCan_RecvByIrq(&drv_can->can_handle, &recv_frame, 1) == 0) + { + LOG_E("rx msg is error"); + return -RT_ERROR; + } + + if (CAN_EFF_FLAG & recv_frame.CanId) + { + pmsg->ide = RT_CAN_EXTID; + pmsg->id = (recv_frame.CanId & ~(RT_CAN_EXTID)); + } + else + { + pmsg->ide = RT_CAN_STDID; + pmsg->id = recv_frame.CanId; + } + + if (CAN_RTR_FLAG & recv_frame.CanId) + { + pmsg->id &= ~CAN_RTR_FLAG; + pmsg->rtr = RT_CAN_RTR; + } + else + { + pmsg->rtr = RT_CAN_DTR; + } + + /* get len */ + pmsg->len = recv_frame.CanDlc; + return RT_EOK; +} + +static const struct rt_can_ops _can_ops = + { + _can_config, + _can_control, + _can_sendmsg, + _can_recvmsg, +}; + +int rt_hw_can_init(void) +{ +#ifdef BSP_USING_CAN0 + drv_can0.can_handle.Config.InstanceId = 0; + rt_sem_init(&drv_can0.recv_semaphore, "can0_recv", 0, RT_IPC_FLAG_FIFO); + drv_can0.device.config.ticks = 20000; + drv_can0.device.config.baud_rate = 1000000; + rt_hw_can_register(&drv_can0.device, + drv_can0.name, + &_can_ops, + &drv_can0); + +#endif + +#ifdef BSP_USING_CAN1 + drv_can1.can_handle.Config.InstanceId = 1; + drv_can0.device.config.baud_rate = 1000000; + rt_sem_init(&drv_can1.recv_semaphore, "can1_recv", 0, RT_IPC_FLAG_FIFO); + rt_hw_can_register(&drv_can1.device, + drv_can1.name, + &_can_ops, + &drv_can1); + +#endif + return 0; +} + +INIT_BOARD_EXPORT(rt_hw_can_init); + +#ifdef BSP_USING_CAN0_DEBUG + +struct can_test_struct +{ + const char *name; + struct rt_can_filter_config *filter; + rt_device_t candev; + struct rt_semaphore _sem; +}; + +static struct can_test_struct can0_test_obj = { + .name = _CAN0_NAME}; + +void can_recv_irq(void *param) +{ + struct can_test_struct *_can_obj = (struct can_test_struct *)param; + rt_kprintf("can_recv_iqr \r\n"); + rt_sem_release(&_can_obj->_sem); +} + +static void rt_can_test_loopback_thread_entry(void *param) +{ + struct can_test_struct *_can_obj = (struct can_test_struct *)param; + struct FCan_Frame recv_frame; + struct ft2004_can *drv_can; + rt_uint32_t i; + _can_obj->candev = rt_device_find(_can_obj->name); + RT_ASSERT(_can_obj->candev); + drv_can = (struct ft2004_can *)_can_obj->candev->user_data; + rt_sem_init(&_can_obj->_sem, "canrx_wait", 0, RT_IPC_FLAG_FIFO); + rt_device_open(_can_obj->candev, RT_DEVICE_OFLAG_RDWR); + + while (1) + { + rt_kprintf(" start to wait loopback \r\n"); + RTHW_CAN_WAIT(drv_can); + while (0 != FCan_RecvByIrq(&drv_can->can_handle, &recv_frame, 1)) + { + rt_kprintf("CanId %x \r\n", recv_frame.CanId); + rt_kprintf("CanDlc %x \r\n", recv_frame.CanDlc); + for (i = 0; i < recv_frame.CanDlc; i++) + { + rt_kprintf("data [%d] %x \r\n", i, recv_frame.data[i]); + } + FCan_SendByIrq(&drv_can->can_handle, &recv_frame, 1, RT_NULL); + } + } +} + +int rt_can0_test(void) +{ + rt_thread_t tid; + + tid = rt_thread_create("can0_loopback", + rt_can_test_loopback_thread_entry, &can0_test_obj, + 1024, 16, 20); + if (tid != RT_NULL) + rt_thread_startup(tid); + + return 0; +} + +INIT_APP_EXPORT(rt_can0_test); + +#endif + +#endif diff --git a/bsp/ft2004/libraries/drivers/rtthread/drv_can.h b/bsp/ft2004/libraries/drivers/rtthread/drv_can.h new file mode 100644 index 0000000000000000000000000000000000000000..1c91f09ca1296296338745e0b1149b118c77700d --- /dev/null +++ b/bsp/ft2004/libraries/drivers/rtthread/drv_can.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-05-11 Carl the first version + */ + +#ifndef __DRV_CAN_H__ +#define __DRV_CAN_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include +#include +#include "ft_can.h" + + struct ft2004_can + { + const char *name; + FCan_t can_handle; + struct rt_semaphore recv_semaphore; + struct rt_can_device device; /* inherit from can device */ + }; + + int rt_hw_can_init(void); + +#ifdef __cplusplus +} +#endif + +#endif // ! diff --git a/bsp/ft2004/libraries/drivers/rtthread/drv_eth.c b/bsp/ft2004/libraries/drivers/rtthread/drv_eth.c new file mode 100644 index 0000000000000000000000000000000000000000..97cf46c1cfb484cf7f9b6d410ab54509b0e5e8e0 --- /dev/null +++ b/bsp/ft2004/libraries/drivers/rtthread/drv_eth.c @@ -0,0 +1,709 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-03-09 Carl the first version + */ + +#include "board.h" +#include +#include "lwipopts.h" +#include "ft_parameters.h" +#include "ft_gmac.h" +#include "ft_cache.h" +#include "ft_gmac_hw.h" +#include "ft_status.h" +#include "ft_io.h" +#include "drv_eth.h" +#include "system_gic.h" + +#ifdef BSP_USING_GMAC + +#define LOG_TAG "drv.gmac" +#include + +#define MAX_ADDR_LEN 6 + +#define LINK_THREAD_STACK_LENGTH 0x400 + +struct drv_gmac +{ + struct eth_device parent; /* inherit from ethernet device */ + Ft_Gmac_t Gmac; /* Gmac driver */ +#ifndef PHY_USING_INTERRUPT_MODE + rt_timer_t poll_link_timer; +#endif + rt_uint8_t *rx_buffer; /* Buffer for RxDesc */ + rt_uint8_t *tx_buffer; /* Buffer for TxDesc */ + uint32_t eth_speed; /* eth_speed */ + uint32_t eth_mode; /* ETH_Duplex_Mode */ + rt_uint8_t dev_addr[MAX_ADDR_LEN]; /* MAC address */ + struct rt_event link_event; + + struct rt_thread _link_thread; + rt_uint8_t _link_thread_stack[LINK_THREAD_STACK_LENGTH]; + + rt_thread_t _debug_tid; +}; + +static void rt_ft2004_status_check(void *Args, u32 MacPhyStatus); + +// +#if defined(RAW_DATA_PRINT) +#if defined(ETH_RX_DUMP) || defined(ETH_TX_DUMP) +#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ') +static void dump_hex(const rt_uint8_t *ptr, rt_size_t buflen) +{ + unsigned char *buf = (unsigned char *)ptr; + int i, j; + + for (i = 0; i < buflen; i += 16) + { + rt_kprintf("%08X: ", i); + + for (j = 0; j < 16; j++) + if (i + j < buflen) + rt_kprintf("%02X ", buf[i + j]); + else + rt_kprintf(" "); + rt_kprintf(" "); + + for (j = 0; j < 16; j++) + if (i + j < buflen) + rt_kprintf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.'); + rt_kprintf("\n"); + } +} +#endif +#endif + +/** + * @name: rt_gmacmem_create + * @msg: Initialize the Gmac TX/Rx Describe Memory 。 + * @param {*} + * @return {*} + */ +static void rt_gmacmem_create(struct drv_gmac *pOsGmac) +{ + pOsGmac->rx_buffer = rt_calloc(1, RX_DESCNUM * GMAC_MAX_PACKET_SIZE); + if (pOsGmac->rx_buffer == NULL) + { + LOG_E("rx_buffer Malloc is error "); + RT_ASSERT(0) + } + + pOsGmac->tx_buffer = rt_calloc(1, TX_DESCNUM * GMAC_MAX_PACKET_SIZE); + if (pOsGmac->tx_buffer == NULL) + { + LOG_E("tx_buffer Malloc is error "); + RT_ASSERT(0) + } + + pOsGmac->Gmac.TxDesc = rt_calloc(1, TX_DESCNUM * sizeof(FGmac_DmaDesc_t)); + if (pOsGmac->Gmac.TxDesc == NULL) + { + LOG_E("TxDesc Malloc is error "); + RT_ASSERT(0) + } + + pOsGmac->Gmac.RxDesc = rt_calloc(1, RX_DESCNUM * sizeof(FGmac_DmaDesc_t) + 128); + if (pOsGmac->Gmac.RxDesc == NULL) + { + LOG_E("RxDesc Malloc is error "); + RT_ASSERT(0) + } + +#define ROUND_UP(x, align) (((long)(x) + ((long)align - 1)) & \ + ~((long)align - 1)) + + pOsGmac->Gmac.RxDesc = (FGmac_DmaDesc_t *)ROUND_UP(pOsGmac->Gmac.RxDesc, 128); + LOG_D("RxDesc fit after addr %x ", pOsGmac->Gmac.RxDesc); +} + +static void rt_gmacmem_free(struct drv_gmac *pOsGmac) +{ + if (pOsGmac->rx_buffer) + { + rt_free(pOsGmac->rx_buffer); + } + + if (pOsGmac->tx_buffer) + { + rt_free(pOsGmac->tx_buffer); + } + + if (pOsGmac->Gmac.RxDesc) + { + rt_free(pOsGmac->Gmac.RxDesc); + } + + if (pOsGmac->Gmac.TxDesc) + { + rt_free(pOsGmac->Gmac.TxDesc); + } +} + +static void rt_hw_gmac_isr(int irqno, void *param) +{ + FGmac_IntrHandler(param); +} + +static void rt_hw_gmac_recv_isr(void *Args) +{ + struct drv_gmac *pOsMac; + rt_err_t result = 0; + + if (RT_NULL == Args) + { + LOG_E("Args is NULL"); + return; + } + + pOsMac = (struct drv_gmac *)Args; + result = eth_device_ready(&(pOsMac->parent)); + if (result != RT_EOK) + { + LOG_I("RxCpltCallback err = %d", result); + } +} + +/** + * @name: Ft_Os_Gmac_Start + * @msg: + * @param {Ft_Os_Gmac} *Os_Gmac + * @return {*} + */ +static rt_err_t +rt_ft2004_gmac_start(struct drv_gmac *pOsMac) +{ + Ft_Gmac_t *pGmac; + pGmac = &pOsMac->Gmac; + + if (FST_SUCCESS != Ft_Gmac_HwInitialize(pGmac)) + { + return -RT_ERROR; + } + + FGmac_SetHandler(pGmac, FT_GMAC_RX_COMPLETE_CB_ID, rt_hw_gmac_recv_isr, pOsMac); + FGmac_SetHandler(pGmac, FT_GMAC_MAC_PHY_STATUS_CB_ID, rt_ft2004_status_check, pOsMac); + + /* Initialize Rx Description list : ring Mode */ + FGmac_DmaRxDescRingInit(pGmac, pGmac->RxDesc, pOsMac->rx_buffer, GMAC_MAX_PACKET_SIZE, RX_DESCNUM); + + /* Initialize Tx Description list : ring Mode */ + FGmac_DmaTxDescRingInit(pGmac, pGmac->TxDesc, pOsMac->tx_buffer, GMAC_MAX_PACKET_SIZE, TX_DESCNUM); + + Ft_Gmac_Start(pGmac); + /* Gmac interrupt init */ + rt_hw_interrupt_install(pGmac->Config.IRQ_NUM, rt_hw_gmac_isr, pGmac, "Gmac"); + rt_hw_interrupt_umask(pGmac->Config.IRQ_NUM); + return RT_EOK; +} + +void rt_ft2004_gmac_stop(struct drv_gmac *pOsMac) +{ + Ft_Gmac_t *pGmac; + pGmac = &pOsMac->Gmac; + Ft_Gmac_Stop(pGmac); +} + +/* GMAC initialization function */ +static rt_err_t rt_ft2004_gmac_init(rt_device_t dev) +{ + struct drv_gmac *pOsMac; + struct eth_device *pGmacParent; + FGmac_Config_t *pConfig; + + pGmacParent = rt_container_of(dev, struct eth_device, parent); + if (NULL == pGmacParent) + { + return -RT_ENOMEM; + } + + pOsMac = rt_container_of(pGmacParent, struct drv_gmac, parent); + if (NULL == pOsMac) + { + return -RT_ENOMEM; + } + + pConfig = Ft_Gmac_LookupConfig(pOsMac->Gmac.Config.InstanceId); + if (NULL == pConfig) + { + return -RT_ENOMEM; + } + + Ft_Gmac_UseDefaultMacAddr(&pOsMac->Gmac, pOsMac->Gmac.Config.MacAddr); + + if (FST_SUCCESS != Ft_GmacCfgInitialize(&pOsMac->Gmac, pConfig)) + { + return -RT_ERROR; + } + + return rt_ft2004_gmac_start(pOsMac); +} + +static rt_err_t rt_ft2004_gmac_open(rt_device_t dev, rt_uint16_t oflag) +{ + LOG_D("gmac open"); + return RT_EOK; +} + +static rt_err_t rt_ft2004_gmac_close(rt_device_t dev) +{ + LOG_D("gmac close"); + return RT_EOK; +} + +static rt_size_t rt_ft2004_gmac_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + LOG_D("gmac read"); + rt_set_errno(-RT_ENOSYS); + return 0; +} + +static rt_size_t rt_ft2004_gmac_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +{ + LOG_D("gmac write"); + rt_set_errno(-RT_ENOSYS); + return 0; +} + +static rt_err_t rt_ft2004_gmac_control(rt_device_t dev, int cmd, void *args) +{ + + struct drv_gmac *pOsMac; + struct eth_device *pGmacParent; + + pGmacParent = rt_container_of(dev, struct eth_device, parent); + if (NULL == pGmacParent) + { + return -RT_ENOMEM; + } + + pOsMac = rt_container_of(pGmacParent, struct drv_gmac, parent); + if (NULL == pOsMac) + { + return -RT_ENOMEM; + } + + switch (cmd) + { + case NIOCTL_GADDR: + /* get mac address */ + if (args) + rt_memcpy(args, pOsMac->dev_addr, 6); + else + return -RT_ERROR; + break; + + default: + break; + } + + return RT_EOK; +} + +/** + * @name: rt_ft2004_gmac_tx + * @msg: + * @in param{rt_device_t}: + * @return {*} + * @param {rt_device_t} dev + * @param {structpbuf} *p + */ +rt_err_t rt_ft2004_gmac_tx(rt_device_t dev, struct pbuf *p) +{ + struct drv_gmac *pOsMac; + Ft_Gmac_t *pGmac; + struct eth_device *pGmacParent; + + err_t errval; + struct pbuf *q; + u8 *Buffer = NULL; + volatile FGmac_DmaDesc_t *DmaTxDesc; + + u32 FrameLength = 0; + u32 BufferOffset = 0; + u32 BytesLeftToCopy = 0; + u32 PayLoadOffset = 0; + + pGmacParent = rt_container_of(dev, struct eth_device, parent); + if (NULL == pGmacParent) + { + return -RT_ENOMEM; + } + + pOsMac = rt_container_of(pGmacParent, struct drv_gmac, parent); + if (NULL == pOsMac) + { + return -RT_ENOMEM; + } + + pGmac = &pOsMac->Gmac; + DmaTxDesc = &pGmac->TxDesc[pGmac->TxDescRingData.DescBufIndex]; + Buffer = (u8 *)DmaTxDesc->Buffer1Addr; + + if (Buffer == NULL) + { + LOG_E("Buffer is NULL \r\n"); + RT_ASSERT(0) + } + +#if RT_LWIP_ETH_PAD_SIZE + pbuf_header(p, -RT_LWIP_ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + + for (q = p; q != NULL; q = q->next) + { + /* Is this buffer available? If not, goto error */ + if ((DmaTxDesc->Status & DMA_TDES0_OWN) != 0) + { + errval = ERR_USE; + LOG_E("error errval = ERR_USE; \r\n"); + goto error; + } + + /* Get bytes in current lwIP buffer */ + BytesLeftToCopy = q->len; + PayLoadOffset = 0; + /* Check if the length of data to copy is bigger than Tx buffer size*/ + while ((BytesLeftToCopy + BufferOffset) > GMAC_MAX_PACKET_SIZE) + { + /* Copy data to Tx buffer*/ + memcpy((u8 *)((u8 *)Buffer + BufferOffset), (u8 *)((u8 *)q->payload + PayLoadOffset), (GMAC_MAX_PACKET_SIZE - BufferOffset)); + FCache_cpuDcacheClean((rt_uint32_t *)DmaTxDesc->Buffer1Addr, GMAC_MAX_PACKET_SIZE); + GMAC_INC_DESC(pGmac->TxDescRingData.DescBufIndex, pGmac->TxDescRingData.DescMaxNumber); + /* Point to next descriptor */ + DmaTxDesc = &pGmac->TxDesc[pGmac->TxDescRingData.DescBufIndex]; + + /* Check if the Bufferis available */ + if ((DmaTxDesc->Status & DMA_TDES0_OWN) != (u32)0) + { + errval = ERR_USE; + LOG_E("Check if the Bufferis available \r\n"); + goto error; + } + + Buffer = (u8 *)(DmaTxDesc->Buffer1Addr); + BytesLeftToCopy = BytesLeftToCopy - (GMAC_MAX_PACKET_SIZE - BufferOffset); + PayLoadOffset = PayLoadOffset + (GMAC_MAX_PACKET_SIZE - BufferOffset); + FrameLength = FrameLength + (GMAC_MAX_PACKET_SIZE - BufferOffset); + BufferOffset = 0; + + if (Buffer == NULL) + { + LOG_E(" error Buffer is 0 \r\n"); + RT_ASSERT(0) + } + } + + /* Copy the remaining bytes */ + memcpy((u8 *)((u8 *)Buffer + BufferOffset), (u8 *)((u8 *)q->payload + PayLoadOffset), BytesLeftToCopy); + BufferOffset = BufferOffset + BytesLeftToCopy; + FrameLength = FrameLength + BytesLeftToCopy; + } + /* 指向下一个位置 */ + FCache_cpuDcacheClean((rt_uint32_t *)DmaTxDesc->Buffer1Addr, GMAC_MAX_PACKET_SIZE); + GMAC_INC_DESC(pGmac->TxDescRingData.DescBufIndex, pGmac->TxDescRingData.DescMaxNumber); +#if RT_LWIP_ETH_PAD_SIZE + pbuf_header(p, RT_LWIP_ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + +#ifdef ETH_TX_DUMP + dump_hex(Buffer, p->tot_len); +#endif + + FGmac_TransmitframeRingPoll(pGmac, FrameLength); +error: + FGmac_SetTransmitUnderflow(pGmac); + return errval; +} + +struct pbuf *rt_ft2004_gmac_rx(rt_device_t dev) +{ + struct drv_gmac *pOsMac; + Ft_Gmac_t *pGmac; + struct eth_device *pGmacParent; + + struct pbuf *p = NULL; + struct pbuf *q = NULL; + u16 Length = 0; + u8 *Buffer; + volatile FGmac_DmaDesc_t *DmaRxDesc; + u32 BufferOffset = 0; + u32 PayLoadOffset = 0; + u32 BytesLeftToCopy = 0; + u32 DescBufIndex; /* For Current Desc buffer buf position */ + + pGmacParent = rt_container_of(dev, struct eth_device, parent); + if (NULL == pGmacParent) + { + return RT_NULL; + } + + pOsMac = rt_container_of(pGmacParent, struct drv_gmac, parent); + if (NULL == pOsMac) + { + return RT_NULL; + } + + pGmac = &pOsMac->Gmac; + + /* get received frame */ + if (FST_SUCCESS != FGmac_RingGetReceivedFrame_IT(pGmac)) + { + return NULL; + } + + DescBufIndex = pGmac->RxDescRingData.DescBufIndex; + Length = (pGmac->RxDesc[DescBufIndex].Status & DMA_RDES0_FRAME_LEN_MASK) >> DMA_RDES0_FRAME_LEN_SHIFT; + Buffer = (u8 *)pGmac->RxDesc[DescBufIndex].Buffer1Addr; + +#if RT_LWIP_ETH_PAD_SIZE + Length += RT_LWIP_ETH_PAD_SIZE; /* allow room for Ethernet padding */ +#endif + + if (Length > 0) + { + /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */ + p = pbuf_alloc(PBUF_RAW, Length, PBUF_POOL); + } + +#ifdef ETH_RX_DUMP + dump_hex(Buffer, (u32)Length); +#endif + + if (p != NULL) + { +#if RT_LWIP_ETH_PAD_SIZE + pbuf_header(p, -RT_LWIP_ETH_PAD_SIZE); /* drop the padding word */ +#endif + DmaRxDesc = &pGmac->RxDesc[DescBufIndex]; + BufferOffset = 0; + for (q = p; q != NULL; q = q->next) + { + BytesLeftToCopy = q->len; + PayLoadOffset = 0; + /* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size*/ + while ((BytesLeftToCopy + BufferOffset) > GMAC_MAX_PACKET_SIZE) + { + /* Copy data to pbuf */ + memcpy((u8 *)((u8 *)q->payload + PayLoadOffset), (u8 *)((u8 *)Buffer + BufferOffset), (GMAC_MAX_PACKET_SIZE - BufferOffset)); + + /* Point to next descriptor */ + GMAC_INC_DESC(DescBufIndex, pGmac->RxDescRingData.DescMaxNumber); + if (DescBufIndex == pGmac->RxDescRingData.DescIndex) + { + break; + } + + DmaRxDesc = &pGmac->RxDesc[DescBufIndex]; + Buffer = (u8 *)(DmaRxDesc->Buffer1Addr); + + BytesLeftToCopy = BytesLeftToCopy - (GMAC_MAX_PACKET_SIZE - BufferOffset); + PayLoadOffset = PayLoadOffset + (GMAC_MAX_PACKET_SIZE - BufferOffset); + BufferOffset = 0; + } + /* Copy remaining data in pbuf */ + memcpy((u8 *)((u8 *)q->payload + PayLoadOffset), (u8 *)((u8 *)Buffer + BufferOffset), BytesLeftToCopy); + BufferOffset = BufferOffset + BytesLeftToCopy; + } + +#if RT_LWIP_ETH_PAD_SIZE + pbuf_header(p, RT_LWIP_ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + } + + /* Release descriptors to DMA */ + /* Point to first descriptor */ + DmaRxDesc = &pGmac->RxDesc[DescBufIndex]; + /* Set Own bit in Rx descriptors: gives the buffers back to DMA */ + for (DescBufIndex = pGmac->RxDescRingData.DescBufIndex; DescBufIndex != pGmac->RxDescRingData.DescIndex; GMAC_INC_DESC(DescBufIndex, pGmac->RxDescRingData.DescMaxNumber)) + { + FCache_cpuDcacheInvalidate((rt_uint32_t *)pGmac->RxDesc[DescBufIndex].Buffer1Addr, GMAC_MAX_PACKET_SIZE); + DmaRxDesc->Status |= DMA_RDES0_OWN; + DmaRxDesc = &pGmac->RxDesc[DescBufIndex]; + } + + /* Sync index */ + pGmac->RxDescRingData.DescBufIndex = pGmac->RxDescRingData.DescIndex; + FGmac_ResumeTransmissionReception(pGmac); + + return p; +} + +static void rt_ft2004_status_check(void *Args, u32 MacPhyStatus) +{ + struct drv_gmac *pOsMac; + + pOsMac = (struct drv_gmac *)Args; + + if (MacPhyStatus & 0x8) + { + LOG_I("netif_set_link_up %x \r\n", rt_event_send(&pOsMac->link_event, FT_NETIF_LINKUP)); + } + else + { + LOG_I("netif_set_link_down %x\r\n", rt_event_send(&pOsMac->link_event, FT_NETIF_DOWN)); + } +} + +static void ethernet_link_thread(void *Args) +{ + struct drv_gmac *pOsMac; + rt_uint32_t status; + u32 LastStatus = FT_NETIF_DOWN; + u32 Flg; + if (RT_NULL == Args) + { + return; + } + + pOsMac = (struct drv_gmac *)Args; + + while (1) + { + status = 0; + if (rt_event_recv(&pOsMac->link_event, FT_NETIF_LINKUP | FT_NETIF_DOWN, RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_OR, + RT_WAITING_FOREVER, &status) != RT_EOK) + { + LOG_E("wait completed timeout"); + continue; + } + + if (status & FT_NETIF_DOWN) + { + eth_device_linkchange(&pOsMac->parent, RT_FALSE); + LastStatus = FT_NETIF_DOWN; + } + else if (status & FT_NETIF_LINKUP) + { + Flg = (LastStatus == FT_NETIF_LINKUP) ? 0 : 1; + LastStatus = FT_NETIF_LINKUP; + } + else + { + LOG_I(" EventGroup is error \r\n"); + RT_ASSERT(0) + } + + if (Flg) + { + Flg = 0; + // eth_device_linkchange(&pOsMac->parent, RT_FALSE); + LOG_I(" Start Linkup \r\n"); + rt_ft2004_gmac_stop(pOsMac); + rt_ft2004_gmac_start(pOsMac); + LOG_I(" HardWare is ok \r\n"); + if (LastStatus == FT_NETIF_LINKUP) + { + rt_thread_mdelay(5000); + eth_device_linkchange(&pOsMac->parent, RT_TRUE); + } + } + } +} + +#ifdef BSP_USING_GMAC0 +struct drv_gmac os_drv_gmac0; +static char *os_drv_gmac0_name = "gmac0"; +#endif + +#ifdef BSP_USING_GMAC1 +struct drv_gmac os_drv_gmac1; +static char *os_drv_gmac1_name = "gmac1"; + +#endif + +static int rt_hw_gmac_init(struct drv_gmac *pOsMac, const char *name) +{ + rt_err_t state = RT_EOK; + // rt_thread_t tid; + rt_gmacmem_free(pOsMac); + rt_gmacmem_create(pOsMac); + + pOsMac->eth_speed = GMAC_SPEED_1000M; + pOsMac->eth_mode = GMAC_MODE_FULLDUPLEX; + + pOsMac->parent.parent.init = rt_ft2004_gmac_init; + pOsMac->parent.parent.open = rt_ft2004_gmac_open; + pOsMac->parent.parent.close = rt_ft2004_gmac_close; + pOsMac->parent.parent.read = rt_ft2004_gmac_read; + pOsMac->parent.parent.write = rt_ft2004_gmac_write; + pOsMac->parent.parent.control = rt_ft2004_gmac_control; + pOsMac->parent.parent.user_data = RT_NULL; + + pOsMac->parent.eth_rx = rt_ft2004_gmac_rx; + pOsMac->parent.eth_tx = rt_ft2004_gmac_tx; + Ft_Gmac_UseDefaultMacAddr(&pOsMac->Gmac, pOsMac->dev_addr); + state = rt_event_init(&pOsMac->link_event, name, RT_IPC_FLAG_FIFO); + LOG_I("rt_event_init is ok \r\n"); + if (RT_EOK != state) + { + rt_kprintf("init gmac0 event failed.\n"); + return -RT_ERROR; + } + + /* register eth device */ + state = eth_device_init(&(pOsMac->parent), name); + if (RT_EOK != state) + { + LOG_E("gmac device init faild: %d", state); + return -RT_ERROR; + } + + state = rt_thread_init(&pOsMac->_link_thread, + name, + ethernet_link_thread, + pOsMac, + &pOsMac->_link_thread_stack[0], + sizeof(pOsMac->_link_thread_stack), + 10, 2); + + if (RT_EOK == state) + { + rt_thread_startup(&pOsMac->_link_thread); + } + else + { + LOG_E("rt_thread_init is error"); + return -RT_ERROR; + } + + // pOsMac->_debug_tid = rt_thread_create(name, rt_hw_gmac_test, pOsMac, 512, 1, 2); + // rt_thread_startup(pOsMac->_debug_tid); + return RT_EOK; +} + +static int rt_hw_ft2004_eth_init(void) +{ + rt_err_t state = RT_EOK; + +#ifdef BSP_USING_GMAC0 + os_drv_gmac0.Gmac.Config.InstanceId = 0; + state = rt_hw_gmac_init(&os_drv_gmac0, os_drv_gmac0_name); + if (RT_EOK != state) + { + goto __exit; + } +#endif + +#ifdef BSP_USING_GMAC1 + os_drv_gmac1.Gmac.Config.InstanceId = 1; + state = rt_hw_gmac_init(&os_drv_gmac1, os_drv_gmac1_name); + if (RT_EOK != state) + { + goto __exit; + } +#endif + +__exit: + return state; +} + +INIT_DEVICE_EXPORT(rt_hw_ft2004_eth_init); + +#endif diff --git a/bsp/ft2004/libraries/drivers/rtthread/drv_eth.h b/bsp/ft2004/libraries/drivers/rtthread/drv_eth.h new file mode 100644 index 0000000000000000000000000000000000000000..8eaebdff2d799bcf9592d224d1902691bdddc3e1 --- /dev/null +++ b/bsp/ft2004/libraries/drivers/rtthread/drv_eth.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-03-09 Carl the first version + */ +#ifndef __DRV_ETH_H__ +#define __DRV_ETH_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define FT_NETIF_LINKUP 0x1U +#define FT_NETIF_DOWN 0x2U + +#ifdef __cplusplus +} +#endif + +#endif // ! \ No newline at end of file diff --git a/bsp/ft2004/libraries/drivers/rtthread/drv_log.h b/bsp/ft2004/libraries/drivers/rtthread/drv_log.h new file mode 100644 index 0000000000000000000000000000000000000000..7e0bfee5b4b77b2cdb5d2bcfc5ad9c1e78b1fe05 --- /dev/null +++ b/bsp/ft2004/libraries/drivers/rtthread/drv_log.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-11-15 SummerGift first version + */ + +/* + * NOTE: DO NOT include this file on the header file. + */ + +#ifndef LOG_TAG +#define DBG_TAG "drv" +#else +#define DBG_TAG LOG_TAG +#endif /* LOG_TAG */ + +#ifdef DRV_DEBUG +#define DBG_LVL DBG_LOG +#else +#define DBG_LVL DBG_INFO +#endif /* DRV_DEBUG */ + +#include diff --git a/bsp/ft2004/libraries/drivers/rtthread/drv_qspi.c b/bsp/ft2004/libraries/drivers/rtthread/drv_qspi.c new file mode 100644 index 0000000000000000000000000000000000000000..dafed45baa1e450f76c9aec5e367429c48c38db1 --- /dev/null +++ b/bsp/ft2004/libraries/drivers/rtthread/drv_qspi.c @@ -0,0 +1,424 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-04-11 Carl the first version + */ + +#include "drv_qspi.h" +#include +#include "rtdevice.h" +#include "ft_qspi.h" +#include "ft_parameters.h" + +#ifdef BSP_USE_QSPI + +#define DRV_DEBUG +#define LOG_TAG "drv.qspi" +#include + +struct ft2004_qspi_bus +{ + FQSpi_t fqspi; + char *name; + rt_uint32_t init; /* 1 is init already */ +}; + +static struct rt_spi_bus _qspi_bus; +static struct ft2004_qspi_bus _ft2004_qspi_bus; + +static int ft2004_qspi_init(struct rt_qspi_device *device, struct rt_qspi_configuration *qspi_cfg) +{ + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(qspi_cfg != RT_NULL); + + // struct rt_spi_configuration *cfg = &qspi_cfg->parent; + struct ft2004_qspi_bus *qspi_bus_p = device->parent.bus->parent.user_data; + + if (qspi_bus_p->init == 0) + { + qspi_bus_p->init = 1; + FQSpi_CfgInitialize(&qspi_bus_p->fqspi, FQSpi_LookupConfig(0)); + } + + return RT_EOK; +} + +static rt_err_t ft2004_cmdOperation(struct ft2004_qspi_bus *qspi_bus_p, struct rt_spi_message *message) +{ + struct rt_qspi_message *qspi_message = (struct rt_qspi_message *)message; + const rt_uint8_t *sndb = message->send_buf; + rt_uint8_t *rcvb = message->recv_buf; + ft_error_t ret; + RT_ASSERT(qspi_bus_p != RT_NULL); + RT_ASSERT(message != RT_NULL); + + struct FQSpi_CmdPack cmd_pack = {0}; + + if (qspi_message->instruction.qspi_lines == 0) + { + LOG_E("instruction is not valid"); + return RT_ERROR; + } + + cmd_pack.cmd = qspi_message->instruction.content; + + if (qspi_message->address.qspi_lines != 0) + { + cmd_pack.flags |= FQSPI_CMD_NEED_ADDR_MASK; + cmd_pack.addr = qspi_message->address.content; + } + + if (qspi_message->address.size == 24) + { + cmd_pack.flags |= FQSPI_CMD_ADDRESS_3BYTE_MASK; + } + else if (qspi_message->address.size == 32) + { + cmd_pack.flags |= FQSPI_CMD_ADDRESS_4BYTE_MASK; + } + + if (qspi_message->qspi_data_lines != 0) + { + if (sndb && (message->length > 0)) + { + cmd_pack.flags |= FQSPI_CMD_NEED_SET_MASK; + cmd_pack.txBuf = sndb; + cmd_pack.length = message->length; + } + else if (rcvb && (message->length > 0)) + { + cmd_pack.flags |= FQSPI_CMD_NEED_GET_MASK; + cmd_pack.rxBuf = rcvb; + cmd_pack.length = message->length; + } + else + { + cmd_pack.flags &= ~(FQSPI_CMD_NEED_GET_MASK | FQSPI_CMD_NEED_SET_MASK); + } + } + + if (qspi_message->dummy_cycles) + { + cmd_pack.flags |= FQSPI_CMD_NEED_DUMMY_MASK; + cmd_pack.dummyCycle = qspi_message->dummy_cycles; + } + + if (cmd_pack.cmd == 0x20) + { + if (qspi_message->address.size == 32) + { + cmd_pack.cmd = 0xdc; + } + } + +#ifdef BSP_QSPI_DEBUG + LOG_I("flags %x", cmd_pack.flags); +#endif + + ret = FQSpi_CmdOperation(&qspi_bus_p->fqspi, &cmd_pack); + +#ifdef BSP_QSPI_DEBUG + if (ret == FQSPI_SUCCESS) + if (cmd_pack.cmd == 5) + { + LOG_I("cmd05 0x%x", cmd_pack.rxBuf[0]); + } +#endif + + return (ret == FQSPI_SUCCESS) ? RT_EOK : RT_ERROR; +} + +static rt_uint32_t ft2004_qspi_xfer(struct ft2004_qspi_bus *qspi_bus_p, struct rt_spi_message *message) +{ + struct rt_qspi_message *qspi_message = (struct rt_qspi_message *)message; + rt_uint32_t ret_length = 0; + const rt_uint8_t *sndb = message->send_buf; + rt_uint8_t *rcvb = message->recv_buf; + rt_int32_t length = message->length; + rt_uint32_t cmd; + rt_uint32_t addr; + FQSpi_t *qspi_p; + FQSpi_Config_t *qspi_config_p; + struct FQSpi_DataPack data_pack = {0}; + qspi_p = &qspi_bus_p->fqspi; + qspi_config_p = &qspi_bus_p->fqspi.config; + + cmd = qspi_message->instruction.content; + addr = qspi_message->address.content; + +#ifdef BSP_QSPI_DEBUG + LOG_I("cmd is %x ", cmd); + LOG_I("length %d , rcvb %x sndb %x addr %x dummy_cycles %x ", length, rcvb, sndb, addr, qspi_message->dummy_cycles); +#endif + + if (qspi_config_p->channel >= FT_QSPI_MAX_CS_NUM) + { + LOG_E("invalid channel[%x] ", qspi_config_p->channel); + return RT_ERROR; + } + switch (cmd) + { + case FQSPI_FLASH_CMD_PP: + { + if (RT_NULL != sndb) + { + data_pack.cmd = cmd; + data_pack.addr = addr; + if (qspi_message->address.size == 24) + { + data_pack.flags |= FQSPI_DATA_ADDRESS_3BYTE_MASK; + } + else + { + data_pack.flags |= FQSPI_DATA_ADDRESS_4BYTE_MASK; + } + + LOG_E("write flags %x ", data_pack.flags); + data_pack.txBuf = sndb; + data_pack.length = length; + ret_length = ((FQSpi_Write(qspi_p, &data_pack) == FQSPI_SUCCESS) ? length : 0); + } + else + { + LOG_E("pp cmd %x sndb is null", cmd); + ret_length = 0; + } + } + break; + case FQSPI_FLASH_CMD_WRDI: /* for sufd qspi fast read */ + FQSpi_FlashRegSet(qspi_p, cmd, RT_NULL, 0); + case FQSPI_FLASH_CMD_READ: + { + if (RT_NULL != rcvb) + { + data_pack.cmd = FQSPI_FLASH_CMD_READ; + data_pack.addr = addr; + if (qspi_message->address.size == 24) + { + data_pack.flags |= FQSPI_DATA_ADDRESS_3BYTE_MASK; + } + else + { + data_pack.flags |= FQSPI_DATA_ADDRESS_4BYTE_MASK; + } + + if (qspi_message->dummy_cycles) + { + data_pack.flags |= FQSPI_DATA_NEED_DUMMY_MASK; + data_pack.dummyCycle = qspi_message->dummy_cycles; + } + data_pack.rxBuf = rcvb; + data_pack.length = length; + + ret_length = ((FQSpi_Read(qspi_p, &data_pack) == FQSPI_SUCCESS) ? length : 0); + } + else + { + // LOG_E("read cmd %x rcvb is null", cmd); + ret_length = 0; + } + } + break; + + default: + { + if (ft2004_cmdOperation(qspi_bus_p, message) == RT_EOK) + { + ret_length = 1; + } + else + { + LOG_E("ft2004_cmdOperation error"); + ret_length = 0; + } + } + } + + return ret_length; +} + +static rt_uint32_t qspixfer(struct rt_spi_device *device, struct rt_spi_message *message) +{ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(device->bus != RT_NULL); + struct ft2004_qspi_bus *qspi_bus_p = device->bus->parent.user_data; + + return ft2004_qspi_xfer(qspi_bus_p, message); +} + +static rt_err_t qspi_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration) +{ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(configuration != RT_NULL); + + struct rt_qspi_device *qspi_device = (struct rt_qspi_device *)device; + return ft2004_qspi_init(qspi_device, &qspi_device->config); +} + +static const struct rt_spi_ops ft2004_qspi_ops = + { + .configure = qspi_configure, + .xfer = qspixfer, +}; + +static int ft2004_qspi_register_bus(struct ft2004_qspi_bus *qspi_bus, const char *name) +{ + RT_ASSERT(qspi_bus != RT_NULL); + RT_ASSERT(name != RT_NULL); + + _qspi_bus.parent.user_data = qspi_bus; + return rt_qspi_bus_register(&_qspi_bus, name, &ft2004_qspi_ops); +} + +rt_err_t ft2004_qspi_bus_attach_device(const char *bus_name, const char *device_name, rt_uint8_t data_line_width, void (*enter_qspi_mode)(), void (*exit_qspi_mode)()) +{ + struct rt_qspi_device *qspi_device = RT_NULL; + rt_err_t result = RT_EOK; + + RT_ASSERT(bus_name != RT_NULL); + RT_ASSERT(device_name != RT_NULL); + RT_ASSERT(data_line_width == 1 || data_line_width == 2 || data_line_width == 4); + + qspi_device = (struct rt_qspi_device *)rt_malloc(sizeof(struct rt_qspi_device)); + if (qspi_device == RT_NULL) + { + LOG_E("no memory, qspi bus attach device failed!"); + result = RT_ENOMEM; + goto __exit; + } + + qspi_device->enter_qspi_mode = enter_qspi_mode; + qspi_device->exit_qspi_mode = exit_qspi_mode; + qspi_device->config.qspi_dl_width = data_line_width; + + result = rt_spi_bus_attach_device(&qspi_device->parent, device_name, bus_name, RT_NULL); + +__exit: + if (result != RT_EOK) + { + if (qspi_device) + { + rt_free(qspi_device); + } + } + + return result; +} + +static int rt_hw_qspi_bus_init(void) +{ + return ft2004_qspi_register_bus(&_ft2004_qspi_bus, FT2004_QSPI_NAME); +} +INIT_BOARD_EXPORT(rt_hw_qspi_bus_init); +#ifdef BSP_QSPI_DEBUG +static void cmd05_check(void) +{ + struct FQSpi_CmdPack cmd_pack = {0}; + u8 rx_buffer[1]; + + cmd_pack.cmd = 0x6; + FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack); + + rt_memset(&cmd_pack, 0, sizeof(&cmd_pack)); + cmd_pack.cmd = 0x5; + cmd_pack.flags = FQSPI_CMD_NEED_GET_MASK; + cmd_pack.rxBuf = rx_buffer; + cmd_pack.length = sizeof(rx_buffer); + + FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack); + + for (u32 i = 0; i < cmd_pack.length; i++) + { + LOG_I("cnt %d, 0x%x ", i, rx_buffer[i]); + } + + rt_memset(&cmd_pack, 0, sizeof(&cmd_pack)); + cmd_pack.cmd = 0x4; + FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack); + + rt_memset(&cmd_pack, 0, sizeof(&cmd_pack)); + cmd_pack.cmd = 0x5; + cmd_pack.flags = FQSPI_CMD_NEED_GET_MASK; + cmd_pack.rxBuf = rx_buffer; + cmd_pack.length = sizeof(rx_buffer); + + FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack); + + for (u32 i = 0; i < cmd_pack.length; i++) + { + LOG_I("cnt %d, 0x%x ", i, rx_buffer[i]); + } +} +MSH_CMD_EXPORT_ALIAS(cmd05_check, cmd05_check, cmd05_check); +#endif + +#ifdef BSP_QSPI_DEBUG +static void cmd35_check(void) +{ + struct FQSpi_CmdPack cmd_pack = {0}; + u8 rx_buffer[1]; + + cmd_pack.cmd = 0x6; + FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack); + + rt_memset(&cmd_pack, 0, sizeof(&cmd_pack)); + cmd_pack.cmd = 0x5; + cmd_pack.flags = FQSPI_CMD_NEED_GET_MASK; + cmd_pack.rxBuf = rx_buffer; + cmd_pack.length = sizeof(rx_buffer); + + FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack); + + for (u32 i = 0; i < cmd_pack.length; i++) + { + LOG_I("cnt %d, 0x%x ", i, rx_buffer[i]); + } + + cmd_pack.cmd = 0xB7; + FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack); + + rt_memset(&cmd_pack, 0, sizeof(&cmd_pack)); + cmd_pack.cmd = 0x35; + cmd_pack.flags = FQSPI_CMD_NEED_GET_MASK; + cmd_pack.rxBuf = rx_buffer; + cmd_pack.length = sizeof(rx_buffer); + + FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack); + + for (u32 i = 0; i < cmd_pack.length; i++) + { + LOG_I("cnt %d, 0x%x ", i, rx_buffer[i]); + } +} +MSH_CMD_EXPORT_ALIAS(cmd35_check, cmd35_check, cmd35_check); +#endif +#ifdef BSP_QSPI_DEBUG +static void cmd15_check(void) +{ + struct FQSpi_CmdPack cmd_pack = {0}; + u8 rx_buffer[1]; + + // cmd_pack.cmd = 0xB7; + // FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack); + + rt_memset(&cmd_pack, 0, sizeof(&cmd_pack)); + cmd_pack.cmd = 0x15; + cmd_pack.flags = FQSPI_CMD_NEED_GET_MASK; + cmd_pack.rxBuf = rx_buffer; + cmd_pack.length = sizeof(rx_buffer); + + FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack); + + for (u32 i = 0; i < cmd_pack.length; i++) + { + LOG_I("cnt %d, 0x%x ", i, rx_buffer[i]); + } +} +MSH_CMD_EXPORT_ALIAS(cmd15_check, cmd15_check, cmd15_check); +#endif +#endif \ No newline at end of file diff --git a/bsp/ft2004/libraries/drivers/rtthread/drv_qspi.h b/bsp/ft2004/libraries/drivers/rtthread/drv_qspi.h new file mode 100644 index 0000000000000000000000000000000000000000..54b0724b9e635a8bcf641063f842b095fd86ccd5 --- /dev/null +++ b/bsp/ft2004/libraries/drivers/rtthread/drv_qspi.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-04-11 Carl the first version + */ + +#ifndef __DRT_QSPI_H__ +#define __DRT_QSPI_H__ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define FT2004_QSPI_NAME "qspi" + + rt_err_t ft2004_qspi_bus_attach_device(const char *bus_name, const char *device_name, rt_uint8_t data_line_width, void (*enter_qspi_mode)(), void (*exit_qspi_mode)()); + +#ifdef __cplusplus +} +#endif + +#endif // !DRT_QSPI_H \ No newline at end of file diff --git a/bsp/ft2004/libraries/drivers/rtthread/drv_sdcard.c b/bsp/ft2004/libraries/drivers/rtthread/drv_sdcard.c new file mode 100644 index 0000000000000000000000000000000000000000..e8b0ae2b6cf59dec8641f28dcbee18f4021ad4f6 --- /dev/null +++ b/bsp/ft2004/libraries/drivers/rtthread/drv_sdcard.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-03-18 Carl the first version + */ + +#include + +#define BSP_USING_SDC +#ifdef BSP_USING_SDC + +#include +#include +#include +#include "drv_sdctrl.h" + +#define DBG_TAG "app.card" +#define DBG_LVL DBG_INFO +#include + +static rt_err_t _sdcard_mount(void) +{ + rt_device_t device; + + device = rt_device_find("sd0"); + rt_kprintf("rt_device_find %x \r\n", device); + if (device == NULL) + { + mmcsd_wait_cd_changed(0); + ft2004_mmcsd_change(); + if (mmcsd_wait_cd_changed(rt_tick_from_millisecond(5000)) == -RT_ETIMEOUT) + { + rt_kprintf("timeout \r\n"); + return RT_ERROR; + } + device = rt_device_find("sd0"); + } + + rt_thread_mdelay(1000); + LOG_I("dfs_mount \r\n"); + if (device != RT_NULL) + { + if (dfs_mount("sd0", "/", "elm", 0, 0) == RT_EOK) + { + LOG_I("sd card mount to '/'"); + } + else + { + LOG_W("sd card mount to '/' failed!"); + return RT_ERROR; + } + } + + return RT_EOK; +} + +static void _sdcard_unmount(void) +{ + rt_thread_mdelay(200); + dfs_unmount("/"); + LOG_I("Unmount \"/\""); + + mmcsd_wait_cd_changed(0); + ft2004_mmcsd_change(); + mmcsd_wait_cd_changed(rt_tick_from_millisecond(5000)); + LOG_I("Unmount is over \r\n"); +} + +static void sd_mount(void *parameter) +{ + rt_uint8_t state = 0; /* 1. is valid card ,0 is removal */ +#ifdef BSP_SDC_IRQ_CARD_REMOVE + rt_uint32_t status; +#endif + while (1) + { + switch (state) + { + case 0: + if (ft2004_card_status() == 1) + { +#ifdef BSP_SDC_IRQ_CARD_REMOVE + ft2004_card_remove_check(0, RT_NULL); /* Clear removal flag bit */ +#endif + if (_sdcard_mount() == RT_EOK) + { + state = 1; + } + else + { + /* For the critical case of frequent plug */ + rt_kprintf("dfs_unmount \r\n"); + _sdcard_unmount(); + ft2004_sdctrl_reset(); + } + } + else + { + rt_thread_mdelay(100); + } + break; + case 1: + +#ifdef BSP_SDC_IRQ_CARD_REMOVE + if (ft2004_card_remove_check(RT_WAITING_FOREVER, &status) == RT_EOK) + { + if (status & SDCTR_CARD_REMOVE_FLG) + { + state = 0; + _sdcard_unmount(); + } + } +#else + if (ft2004_card_status() == 0) + { + state = 0; + _sdcard_unmount(); + } +#endif + else + { + rt_thread_mdelay(100); + } + break; + default: + state = 0; + break; + } + } +} + +int ft2004_sdcard_mount(void) +{ + rt_thread_t tid; + + tid = rt_thread_create("sd_mount", sd_mount, RT_NULL, + 8192, 2, 20); + + if (tid != RT_NULL) + { + rt_thread_startup(tid); + } + else + { + LOG_E("create sd_mount thread err!"); + } + return RT_EOK; +} +INIT_APP_EXPORT(ft2004_sdcard_mount); + +#endif /* BSP_USING_SDCARD */ diff --git a/bsp/ft2004/libraries/drivers/rtthread/drv_sdctrl.c b/bsp/ft2004/libraries/drivers/rtthread/drv_sdctrl.c new file mode 100644 index 0000000000000000000000000000000000000000..85b1a34277ed242a5e02b2e73e46f0be11f3bf9d --- /dev/null +++ b/bsp/ft2004/libraries/drivers/rtthread/drv_sdctrl.c @@ -0,0 +1,693 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-03-18 Carl the first version + */ + +#include "drv_sdctrl.h" +#include "ft_sdctrl_hw.h" +#include "ft_sdctrl.h" +#include "ft_debug.h" +#include "ft_types.h" +#include "ft_generic_timer.h" +#include +#include "interrupt.h" +#include "rtconfig.h" +#include "ft_cache.h" + +#ifdef BSP_USING_SDC + +#define LOG_TAG "drv.sdmmc" +#include + +#define RTHW_SDCTRL_LOCK(_sdctrl) rt_mutex_take(&_sdctrl->mutex, RT_WAITING_FOREVER) +#define RTHW_SDCTRL_UNLOCK(_sdctrl) rt_mutex_release(&_sdctrl->mutex); + +struct mmcsd_pkg +{ + struct rt_mmcsd_cmd *cmd; + void *buff; + rt_uint32_t flag; +}; + +typedef struct +{ + FtsdCtrl_t ft_sdctrl; + struct rt_mmcsd_host *host; + struct rt_event event; + struct rt_mutex mutex; + struct mmcsd_pkg *pkg; +} ft_sdctrl_class_t; + +ft_sdctrl_class_t sdctrl_class; + +ALIGN(SDCTR_ALIGN_LEN) +static rt_uint8_t cache_buf[SDCTR_BUFF_SIZE]; + +static void rthw_sdctrl_send_command(ft_sdctrl_class_t *class_p, struct mmcsd_pkg *pkg); + +static void demo_dump_sdc(void) +{ + Ft_DumpHexWord((const rt_uint32_t *)(0x28207C00), 256); +} +MSH_CMD_EXPORT_ALIAS(demo_dump_sdc, dump_sdc, output all dump_sdc); + +static void rthw_sdctrl_delay(u32 delayCnt) +{ + Ft_GenericTimer_UsDelay(delayCnt); +} + +static u32 rthw_sdctrl_rasp2type(u32 rasp) +{ + + switch (rasp) + { + case RESP_NONE: + return FTSDCTRL_CMD_RES_NONE; + case RESP_R2: + return FTSDCTRL_CMD_RES_LONG; + default: + return FTSDCTRL_CMD_RES_SHORT; + } + + return FTSDCTRL_CMD_RES_SHORT; +} + +static void rthw_sdctrl_transfer_by_dma(ft_sdctrl_class_t *class_p, struct mmcsd_pkg *pkg) +{ + struct rt_mmcsd_data *data; + struct rt_mmcsd_cmd *cmd; + u32 rasp; + u32 *buff; + FtsdCtrl_t *ft_sdctrl_p; + + if ((RT_NULL == class_p)) + { + LOG_E("rthw_sdctrl_transfer_by_dma invalid class_p"); + return; + } + ft_sdctrl_p = &class_p->ft_sdctrl; + + if ((RT_NULL == pkg)) + { + LOG_E("rthw_sdctrl_transfer_by_dma invalid args"); + return; + } + + data = pkg->cmd->data; + if (RT_NULL == data) + { + LOG_E("rthw_sdctrl_transfer_by_dma invalid args"); + return; + } + + buff = pkg->buff; + if (RT_NULL == buff) + { + LOG_E("rthw_sdctrl_transfer_by_dma invalid args"); + return; + } + + cmd = pkg->cmd; + rasp = resp_type(pkg->cmd); + rasp = rthw_sdctrl_rasp2type(rasp); + + if (data->flags & DATA_DIR_WRITE) + { +#ifdef BSP_SDC_DEBUG_PRINT + rt_kprintf("DATA_DIR_WRITE %x \r\n", cmd->arg); +#endif + FCache_cpuDcacheClean(buff, data->blks * data->blksize); + + /* data, card, blk: card : data + blk */ + FSdCtrl_WriteData(ft_sdctrl_p, (UINTPTR)buff, cmd->arg, data->blks); + cmd->err = FSdCtrl_WaitCmdEnd(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay, rasp, cmd->resp); + +#ifdef BSP_SDC_DEBUG_PRINT + for (int i = 0; i < 4; i++) + { + rt_kprintf("cmdRsp[%d] %x \r\n", i, cmd->resp[i]); + } + Ft_DumpHexWord(buff, 256); +#endif + FSdCtrl_WaitWriteDataEnd(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay, data->blks); + FCache_cpuDcacheInvalidate(buff, data->blks * data->blksize); + } + else if (data->flags & DATA_DIR_READ) + { +#ifdef BSP_SDC_DEBUG_PRINT + rt_kprintf("DATA_DIR_READ %x \r\n", cmd->arg); +#endif + if ((cmd->flags & CMD_ADTC) && (data->blksize < 512)) + { +#ifdef BSP_SDC_DEBUG_PRINT + LOG_E("CMD_ADTC \r\n"); +#endif + FSdCtrl_DoACmd(ft_sdctrl_p, cmd->cmd_code, rasp, cmd->arg); + rt_thread_mdelay(10); + } + + FCache_cpuDcacheInvalidate(buff, data->blks * data->blksize); + FSdCtrl_ReadData(ft_sdctrl_p, (UINTPTR)buff, cmd->arg, data->blks); + cmd->err = FSdCtrl_WaitCmdEnd(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay, rasp, cmd->resp); +#ifdef BSP_SDC_DEBUG_PRINT + for (int i = 0; i < 4; i++) + { + rt_kprintf("cmdRsp[%d] %x \r\n", i, cmd->resp[i]); + } +#endif + FSdCtrl_WaitReadDataEnd(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay, data->blks); + FCache_cpuDcacheClean(buff, data->blks * data->blksize); +#ifdef BSP_SDC_DEBUG_PRINT + Ft_DumpHexWord(buff, data->blks * data->blksize); +#endif + } +} + +static void rthw_sdctrl_docmd(ft_sdctrl_class_t *class_p, struct mmcsd_pkg *pkg) +{ + struct rt_mmcsd_cmd *cmd; + u32 rasp; + FtsdCtrl_t *ft_sdctrl_p; + + if ((RT_NULL == class_p)) + { + LOG_E("rthw_sdctrl_docmd invalid class_p"); + return; + } + + ft_sdctrl_p = &class_p->ft_sdctrl; + + if ((RT_NULL == pkg)) + { + LOG_E("rthw_sdctrl_docmd invalid args"); + return; + } + + cmd = pkg->cmd; + rasp = resp_type(pkg->cmd); + rasp = rthw_sdctrl_rasp2type(rasp); + FSdCtrl_DoCmd(ft_sdctrl_p, pkg->cmd->cmd_code, rasp, cmd->arg); + cmd->err = FSdCtrl_WaitCmdEnd(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay, rasp, cmd->resp); + +#ifdef BSP_SDC_DEBUG_PRINT + for (int i = 0; i < 4; i++) + { + rt_kprintf("cmdRsp[%d] %x \r\n", i, cmd->resp[i]); + } +#endif +} + +static void rthw_sdctrl_send_command(ft_sdctrl_class_t *class_p, struct mmcsd_pkg *pkg) +{ + struct rt_mmcsd_cmd *cmd = pkg->cmd; + struct rt_mmcsd_data *data = cmd->data; + /* save pkg */ + class_p->pkg = pkg; + + /* config data reg */ + if (data != RT_NULL && data->blks) + { + /* transfer config */ + rthw_sdctrl_transfer_by_dma(class_p, pkg); + } + else + { + rthw_sdctrl_docmd(class_p, pkg); + } +} + +/** + * @brief This function send sdio request. + * @param host rt_mmcsd_host + * @param req request + * @retval None + */ +static void rthw_sdctrl_request(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req) +{ + struct mmcsd_pkg pkg; + ft_sdctrl_class_t *class_p = host->private_data; + struct rt_mmcsd_data *data; + + RTHW_SDCTRL_LOCK(class_p); + if (req->cmd != RT_NULL) + { + rt_memset(&pkg, 0, sizeof(pkg)); + data = req->cmd->data; + pkg.cmd = req->cmd; + + if (pkg.cmd->cmd_code == 5 || pkg.cmd->cmd_code == 1) + { + rt_kprintf("cmd_code is not vaild %x \r\n", pkg.cmd->cmd_code); + pkg.cmd->err = RT_EINVAL; + goto _exit; + } + +#ifdef BSP_SDC_DEBUG_PRINT + struct rt_mmcsd_cmd *cmd; + cmd = req->cmd; + LOG_E("CMD:%d ARG:0x%08x RES:%s%s%s%s%s%s%s%s%s rw:%c len:%d blksize:%d", + cmd->cmd_code, + cmd->arg, + resp_type(cmd) == RESP_NONE ? "NONE" : "", + resp_type(cmd) == RESP_R1 ? "R1" : "", + resp_type(cmd) == RESP_R1B ? "R1B" : "", + resp_type(cmd) == RESP_R2 ? "R2" : "", + resp_type(cmd) == RESP_R3 ? "R3" : "", + resp_type(cmd) == RESP_R4 ? "R4" : "", + resp_type(cmd) == RESP_R5 ? "R5" : "", + resp_type(cmd) == RESP_R6 ? "R6" : "", + resp_type(cmd) == RESP_R7 ? "R7" : "", + data ? (data->flags & DATA_DIR_WRITE ? 'w' : 'r') : '-', + data ? data->blks * data->blksize : 0, + data ? data->blksize : 0); +#endif + + if (data != RT_NULL) + { + rt_uint32_t size = data->blks * data->blksize; + + RT_ASSERT(size <= SDCTR_BUFF_SIZE); + pkg.buff = data->buf; + if ((rt_uint32_t)data->buf & (SDCTR_ALIGN_LEN - 1)) + { + pkg.buff = cache_buf; + if (data->flags & DATA_DIR_WRITE) + { + rt_memcpy(cache_buf, data->buf, size); + } + } + } + + rthw_sdctrl_send_command(class_p, &pkg); + + if ((data != RT_NULL) && (data->flags & DATA_DIR_READ) && ((rt_uint32_t)data->buf & (SDCTR_ALIGN_LEN - 1))) + { + rt_memcpy(data->buf, cache_buf, data->blksize * data->blks); + } + } + + if (req->stop != RT_NULL) + { + rt_memset(&pkg, 0, sizeof(pkg)); + pkg.cmd = req->stop; + rthw_sdctrl_send_command(class_p, &pkg); + } + +_exit: + + RTHW_SDCTRL_UNLOCK(class_p); + mmcsd_req_complete(class_p->host); +} + +static void rthw_sdctrl_clk_divider(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg) +{ + ft_sdctrl_class_t *class_p = host->private_data; + FtsdCtrl_t *sd_ctrl = &(class_p->ft_sdctrl); + + /* bus mode is pull push */ + FSdCtrl_ClkFreqSetup(sd_ctrl, io_cfg->clock); + return; +} + +static void rthw_sdctrl_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg) +{ + ft_sdctrl_class_t *class_p = host->private_data; + RTHW_SDCTRL_LOCK(class_p); + + /* calculate and set clk divider */ + rthw_sdctrl_clk_divider(host, io_cfg); + + RTHW_SDCTRL_UNLOCK(class_p); +} + +rt_int32_t rthw_sdctrl_detect(struct rt_mmcsd_host *host) +{ + ft_sdctrl_class_t *class_p = host->private_data; + + return FSdCtrl_CardDetect(&class_p->ft_sdctrl); +} + +static const struct rt_mmcsd_host_ops ops = + { + rthw_sdctrl_request, + rthw_sdctrl_iocfg, + rthw_sdctrl_detect, + RT_NULL, +}; + +/** + * @name: rthw_sdctrl_nomarl_callback + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + * @param {void} *args + */ +void rthw_sdctrl_nomarl_callback(void *args) +{ + FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)args; + rt_uint32_t status; + ft_sdctrl_class_t *class_p; + if (RT_NULL == pFtsdCtrl) + { + return; + } + + class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl); + + status = FSdCtrl_GetNormalIrqStatus(pFtsdCtrl); + + if (status & NORMAL_INT_STATUS_CR) + { + rt_event_send(&class_p->event, SDCTR_CARD_REMOVE_FLG); + } + else if (status & NORMAL_INT_STATUS_CC) + { + rt_event_send(&class_p->event, SDCTR_CMD_IS_COMPLETE_FLG); + } + else if (status & NORMAL_INT_STATUS_EI) + { + rt_event_send(&class_p->event, SDCTR_CMD_IS_ERROR_FLG); + } + + return; +} + +/** + * @name: + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + * @param {void} *args + */ +void rthw_sdctrl_dma_callback(void *args) +{ + FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)args; + rt_uint32_t status; + ft_sdctrl_class_t *class_p; + + if (RT_NULL == pFtsdCtrl) + { + return; + } + + class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl); + + status = FSdCtrl_GetDataIrqStatus(pFtsdCtrl); + + if (status & BD_ISR_REG_TRS) + { + /* send write complete event */ + rt_event_send(&class_p->event, SDCTR_WRITE_IS_COMPLETE_FLG); + } + + if (status & BD_ISR_REG_RESPE) + { + /* send read complete event */ + rt_event_send(&class_p->event, SDCTR_READ_IS_COMPLETE_FLG); + } + + if (status & BD_ISR_REG_DAIS) + { + /* send dma errror event */ + rt_event_send(&class_p->event, SDCTR_DMA_IS_ERROR_FLG); + } +} + +/** + * @name: + * @msg: + * @in param: + * @inout param: + * @out param: + * @return {*} + * @param {void} *args + */ +void rthw_sdctrl_error_callback(void *args) +{ + FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)args; + rt_uint32_t status; + ft_sdctrl_class_t *class_p; + + if (RT_NULL == pFtsdCtrl) + { + return; + } + + class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl); + + status = FSdCtrl_GetErrorIrqStatus(pFtsdCtrl); + + if (status & SDCTR_CMD_TIMEOUT_FLG) + { + rt_event_send(&class_p->event, SDCTR_CMD_TIMEOUT_FLG); + } + + if (status & ERROR_INT_EN_CNR) + { + rt_event_send(&class_p->event, SDCTR_CMD_RECEIVE_IS_ERROR_FLG); + } + + if (status & ERROR_INT_EN_CCRCE) + { + rt_event_send(&class_p->event, SDCTR_CMD_CRC_IS_ERROR_FLG); + } +} + +void rthw_sdctrl_normal_irq(int vector, void *param) +{ + FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)param; + FSdCtrl_NormalIrq(pFtsdCtrl); +} + +void rthw_sdctrl_dma_irq(int vector, void *param) +{ + FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)param; + FSdCtrl_DmaIrq(pFtsdCtrl); +} + +void rthw_sdctrl_err_irq(int vector, void *param) +{ + FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)param; + FSdCtrl_ErrIrq(pFtsdCtrl); +} + +ft_error_t rthw_sdctrl_cmd_wait(FtsdCtrl_t *pFtsdCtrl) +{ + rt_uint32_t status; + ft_sdctrl_class_t *class_p; + + if (RT_NULL == pFtsdCtrl) + { + return FTSDC_INVALID_PARAM; + } + + class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl); + + if (rt_event_recv(&class_p->event, SDCTR_CMD_IS_COMPLETE_FLG | SDCTR_CMD_IS_ERROR_FLG | SDCTR_CMD_CRC_IS_ERROR_FLG, RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_OR, + rt_tick_from_millisecond(50000), &status) != RT_EOK) + { + /* wait cmd completed timeout */ + LOG_E("wait cmd completed timeout"); + return FTSDC_TIMEOUT; + } + + if (SDCTR_CMD_IS_COMPLETE_FLG == (status & SDCTR_CMD_IS_COMPLETE_FLG)) + { + return FTSDC_SUCCESS; + } + else + { + LOG_E("wait cmd is error %x ", status); + return FTSDC_FAILURE; + } +} + +ft_error_t rthw_sdctrl_read_wait(FtsdCtrl_t *pFtsdCtrl) +{ + rt_uint32_t status; + ft_sdctrl_class_t *class_p; + + if (RT_NULL == pFtsdCtrl) + { + return FTSDC_INVALID_PARAM; + } + + class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl); + + if (rt_event_recv(&class_p->event, SDCTR_READ_IS_COMPLETE_FLG | SDCTR_CMD_RECEIVE_IS_ERROR_FLG, + RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_OR, + rt_tick_from_millisecond(50000), &status) != RT_EOK) + { + /* wait read completed timeout */ + LOG_E("wait read completed timeout"); + return FTSDC_TIMEOUT; + } + + if (SDCTR_READ_IS_COMPLETE_FLG == (status & SDCTR_READ_IS_COMPLETE_FLG)) + { + return FTSDC_SUCCESS; + } + else + { + LOG_E("wait read is error %x ", status); + return FTSDC_FAILURE; + } +} + +ft_error_t rthw_sdctrl_write_wait(FtsdCtrl_t *pFtsdCtrl) +{ + rt_uint32_t status; + ft_sdctrl_class_t *class_p; + + if (RT_NULL == pFtsdCtrl) + { + return FTSDC_INVALID_PARAM; + } + + class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl); + + if (rt_event_recv(&class_p->event, SDCTR_WRITE_IS_COMPLETE_FLG, RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_OR, + rt_tick_from_millisecond(50000), &status) != RT_EOK) + { + /* wait write completed timeout */ + LOG_E("wait write completed timeout"); + return FTSDC_TIMEOUT; + } + + if (SDCTR_WRITE_IS_COMPLETE_FLG == (status & SDCTR_WRITE_IS_COMPLETE_FLG)) + { + return FTSDC_SUCCESS; + } + else + { + LOG_E("wait write is error %x ", status); + return FTSDC_FAILURE; + } +} + +/** + * Description: create sd ctrl instance + * Date: 2021-03-31 10:10:40 + * Param: + * return {*} + * param {ft_sdctrl_class_t} *class_p + */ +static rt_err_t rthw_sdctrl_create(ft_sdctrl_class_t *class_p) +{ + struct rt_mmcsd_host *host; + + host = mmcsd_alloc_host(); + if (host == RT_NULL) + { + LOG_E("L:%d F:%s mmcsd alloc host fail"); + return RT_ENOMEM; + } + + class_p->ft_sdctrl.config = *(FSdCtrl_Config_t *)FSdCtrl_LookupConfig(0); + rt_event_init(&class_p->event, "sdctrl", RT_IPC_FLAG_FIFO); + rt_mutex_init(&class_p->mutex, "sdctrl", RT_IPC_FLAG_FIFO); + + class_p->host = host; + host->ops = &ops; + /* range of sd work speed */ + host->freq_min = 400 * 1000; + host->freq_max = 48 * 1000000; + host->valid_ocr = 0X00FFFF80; /* The voltage range supported is 1.65v-3.6v */ + host->flags = MMCSD_BUSWIDTH_4; + host->private_data = class_p; + /* ready to change */ + + return RT_EOK; +} + +int rthw_sdctrl_init(void) +{ + + FtsdCtrl_t *ft_sdctrl_p; +#ifdef BSP_SDC_USE_IRQ + FSdCtrl_Config_t *config_p; + FSdCtrl_NormalIrqSelect_t normalIrqFlgs = 0; +#endif + + rt_kprintf("rthw_sdctrl_init \r\n"); + RT_ASSERT(rthw_sdctrl_create(&sdctrl_class) == RT_EOK); + ft_sdctrl_p = &sdctrl_class.ft_sdctrl; + + FSdCtrl_Reset(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay); + FsdCtrl_Init(ft_sdctrl_p); + +#ifdef BSP_SDC_USE_IRQ + config_p = &ft_sdctrl_p->config; +#ifdef BSP_SDC_IRQ_CARD_REMOVE + normalIrqFlgs |= NORMAL_IRQ_CR; + +#endif + normalIrqFlgs |= NORMAL_IRQ_CC; + /* register handler、irq enable bit and wait callback */ + FSdCtrl_SetHandler(ft_sdctrl_p, FTSDCTRL_CMDIRQID, rthw_sdctrl_nomarl_callback, ft_sdctrl_p); + FSdCtrl_NormalIrqSet(ft_sdctrl_p, normalIrqFlgs); + FSdCtrl_CmdWaitRegister(ft_sdctrl_p, rthw_sdctrl_cmd_wait); + + FSdCtrl_SetHandler(ft_sdctrl_p, FTSDCTRL_DMADATAIRQID, rthw_sdctrl_dma_callback, ft_sdctrl_p); + FSdCtrl_BdIrqSet(ft_sdctrl_p, BD_IRQ_TRS | BD_IRQ_RESPE); + FSdCtrl_WriteWaitRegister(ft_sdctrl_p, rthw_sdctrl_write_wait); + FSdCtrl_ReadWaitRegister(ft_sdctrl_p, rthw_sdctrl_read_wait); + + config_p->workMode = FTSDCTRL_CMD_IRQ_MASK | FTSDCTRL_DATA_WRITE_IRQ_MASK | FTSDCTRL_DATA_READ_IRQ_MASK; + +#else + +#endif + + /* install normal irq */ + + rt_hw_interrupt_install(ft_sdctrl_p->config.normalIrqNum, rthw_sdctrl_normal_irq, + &sdctrl_class.ft_sdctrl, "normalIrq"); + rt_hw_interrupt_umask(ft_sdctrl_p->config.normalIrqNum); + + rt_hw_interrupt_install(ft_sdctrl_p->config.dmaIrqNum, rthw_sdctrl_dma_irq, + &sdctrl_class.ft_sdctrl, "dmaIrq"); + rt_hw_interrupt_umask(ft_sdctrl_p->config.dmaIrqNum); + + return 0; +} + +INIT_DEVICE_EXPORT(rthw_sdctrl_init); + +void ft2004_mmcsd_change(void) +{ + mmcsd_change(sdctrl_class.host); +} + +rt_bool_t ft2004_card_status(void) +{ + return FSdCtrl_CardDetect(&sdctrl_class.ft_sdctrl); +} + +rt_err_t ft2004_card_remove_check(rt_int32_t timeout, rt_uint32_t *status) +{ + return rt_event_recv(&sdctrl_class.event, SDCTR_CARD_REMOVE_FLG, RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_OR, + timeout, status); +} + +void ft2004_sdctrl_reset(void) +{ + FSdCtrl_Reset(&sdctrl_class.ft_sdctrl, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay); + FsdCtrl_Init(&sdctrl_class.ft_sdctrl); + +#ifdef BSP_SDC_USE_IRQ + FSdCtrl_NormalIrqSet(&sdctrl_class.ft_sdctrl, NORMAL_IRQ_CC | NORMAL_IRQ_CR | NORMAL_IRQ_EI); + FSdCtrl_BdIrqSet(&sdctrl_class.ft_sdctrl, BD_IRQ_TRS | BD_IRQ_RESPE); +#endif +} + +#endif diff --git a/bsp/ft2004/libraries/drivers/rtthread/drv_sdctrl.h b/bsp/ft2004/libraries/drivers/rtthread/drv_sdctrl.h new file mode 100644 index 0000000000000000000000000000000000000000..dba34f252525dec74218ff6d10d6f428ef96de45 --- /dev/null +++ b/bsp/ft2004/libraries/drivers/rtthread/drv_sdctrl.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-03-18 Carl the first version + */ + +#ifndef __DRV_SDCTRL_H__ +#define __DRV_SDCTRL_H__ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define SDCTR_CMD_IS_COMPLETE_FLG 0x1UL /* Command is complete */ +#define SDCTR_WRITE_IS_COMPLETE_FLG 0x2UL +#define SDCTR_READ_IS_COMPLETE_FLG 0x4UL +#define SDCTR_CMD_IS_ERROR_FLG 0x8UL +#define SDCTR_CMD_CRC_IS_ERROR_FLG 0x10UL /* Command CRC error */ +#define SDCTR_DMA_IS_ERROR_FLG 0x20UL /* */ +#define SDCTR_CARD_REMOVE_FLG 0x40UL /* Card remove */ +#define SDCTR_CMD_TIMEOUT_FLG 0x70UL /* command timeout */ +#define SDCTR_CMD_RECEIVE_IS_ERROR_FLG 0x80UL /* CMD receive is error */ + +#ifndef SDCTR_BUFF_SIZE +#define SDCTR_BUFF_SIZE (512 * 128) +#endif + +#ifndef SDCTR_ALIGN_LEN +#define SDCTR_ALIGN_LEN (32) +#endif + + void ft2004_mmcsd_change(void); + rt_bool_t ft2004_card_status(void); + rt_err_t ft2004_card_remove_check(rt_int32_t timeout, rt_uint32_t *status); + void ft2004_sdctrl_reset(void); +#ifdef __cplusplus +} +#endif + +#endif // ! diff --git a/bsp/ft2004/libraries/drivers/rtthread/drv_spi.c b/bsp/ft2004/libraries/drivers/rtthread/drv_spi.c new file mode 100644 index 0000000000000000000000000000000000000000..1ed51420b52fd9a47f9d1e3e1282f4256a6d5656 --- /dev/null +++ b/bsp/ft2004/libraries/drivers/rtthread/drv_spi.c @@ -0,0 +1,447 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-25 14:01:29 + * @LastEditTime: 2021-04-30 16:11:25 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "drv_spi.h" +#include +#include +#include +#include "ft_spi.h" +#include "ft_mux.h" +#include "ft_trace.h" +#include "ft_generic_timer.h" + +#define DRV_DEBUG +#define LOG_TAG "drv.spi" +#include + +typedef void (*spi_cs_handler_t)(const rt_bool_t select); +typedef struct +{ + FSpi_Ctrl_t spi_ctrl; + struct rt_spi_bus spi_bus; + uint16_t spi_cs_pin; + spi_cs_handler_t spi_cs_handler; +}ft2004_spi_class; + +void ft2004_spi_cs(const rt_bool_t select); +static ft2004_spi_class spi_obj = { + .spi_cs_handler = ft2004_spi_cs, + .spi_ctrl = { + .CtrlId = SPI_CTRL_ID_0, + .DevId = SPI_DEV_ID_0, + .IsReady = FALSE, + .CsPin = 5, /* use pin 5 in gpio group a as cs signal pin */ + }, +}; +static const FSpi_Conf_t spi_conf[NUM_OF_SPI_CTRL] = +{ + { + .DevAddr = {0x00, 0x00, 0x00, 0x00}, + .DevAddrLen = SPI_4_BYTE_ADDR, + .WorkMode = SPI_CTRL_MASTER_MODE, + /* mode 2 CPOL = 1, CPHA = 0 */ + .Cpol = SPI_CTRL_CPOL_HIGH, + .Cpha = SPI_CTRL_CPHA_1EDGE, + .BaudRDiv = SPI_SCKDV_4, + }, + { + .DevAddr = {0x00, 0x00, 0x00, 0x00}, + .DevAddrLen = SPI_4_BYTE_ADDR, + .WorkMode = SPI_CTRL_MASTER_MODE, + .Cpol = SPI_CTRL_CPOL_HIGH, + .Cpha = SPI_CTRL_CPHA_1EDGE, + .BaudRDiv = SPI_SCKDV_MAX, + } +}; + +inline static ft2004_spi_class *ft2004_spi_get_class() +{ + return &spi_obj; +} + +inline static FSpi_Ctrl_t *ft2004_spi_get_ctrl() +{ + return &(ft2004_spi_get_class()->spi_ctrl); +} + +static const FSpi_Conf_t *ft2004_lookup_conf(FT_IN FSpi_CtrlId_t CtrlId) +{ + return &spi_conf[CtrlId]; +} + +void ft2004_spi_cs(const rt_bool_t select) +{ + FSpi_Ctrl_t *ctrl_p = ft2004_spi_get_ctrl(); + FSpi_SelectSlave(ctrl_p, ctrl_p->DevId, (bool_t)select); +} + +/**spi flash operations***/ +u32 ft2004_spi_transcation(const u8 tx_data, u8 *rx_data_p) +{ + FSpi_Ctrl_t *ctrl_p = ft2004_spi_get_ctrl(); + u32 ret = ERR_SPI_OK; + + ret = FSpi_ReadWriteByte(ctrl_p, tx_data, rx_data_p); + return ret; +} +/**spi flash operations***/ + +static rt_err_t ft2004_spi_init(struct rt_spi_configuration *cfg) +{ + FSpi_Ctrl_t *ctrl_p = ft2004_spi_get_ctrl(); + FSpi_DevId_t dev_id; + u32 ret = ERR_SPI_OK; + + //RT_ASSERT(cfg != RT_NULL); + RT_ASSERT(ctrl_p != RT_NULL); + dev_id = ctrl_p->DevId; + + /* get spi flash default config */ + ctrl_p->Config = *(ft2004_lookup_conf(dev_id)); + + /* change config according to inputs, cfg could be RT_NULL */ + + /* reset ctrl block */ + ctrl_p->IsReady = FALSE; + + /* set spi pin mux */ + Ft_setSpiMux(ctrl_p->CtrlId); + + /* init spi ctrl */ + ret = FSpi_Init(ctrl_p); + + if (ERR_SPI_OK == ret) + { + return RT_EOK; + } + else + { + return -RT_ERROR; + } +} + +static rt_uint32_t spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message) +{ + rt_size_t message_length, loop; + rt_uint8_t *recv_buf; + const rt_uint8_t *send_buf; + u32 tx_rx_result = ERR_SPI_OK; + spi_cs_handler_t cs_handler = ft2004_spi_get_class()->spi_cs_handler; + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(device->bus != RT_NULL); + RT_ASSERT(device->bus->parent.user_data != RT_NULL); + RT_ASSERT(message != RT_NULL); + + if (message->cs_take && cs_handler) + { + cs_handler(TRUE); + } + + message_length = message->length; + recv_buf = message->recv_buf; + send_buf = message->send_buf; + + /* handle msg */ + for (loop = 0; loop < message_length; loop++) + { + /* start data exchange */ + if ((message->recv_buf) && (message->send_buf)) + { + /* need tx and rx */ + tx_rx_result |= ft2004_spi_transcation(*send_buf, recv_buf); + send_buf++; + recv_buf++; + } + else if (message->send_buf) + { + /* tx only */ + tx_rx_result |= ft2004_spi_transcation(*send_buf, RT_NULL); + send_buf++; + } + else + { + /* rx only */ + tx_rx_result |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, recv_buf); + recv_buf++; + } + } + + if (ERR_SPI_OK != tx_rx_result) + { + LOG_E("spi transfer error : 0x%x", tx_rx_result); + message->length = 0; + } + else + { + //LOG_D("transfer done"); + } + + if (message->cs_release && cs_handler) + { + cs_handler(FALSE); + } + + return message->length; +} + +static rt_err_t spi_configure(struct rt_spi_device *device, + struct rt_spi_configuration *configuration) +{ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(configuration != RT_NULL); + + return ft2004_spi_init(configuration); +} + +static const struct rt_spi_ops ft2004_spi_ops = +{ + .configure = spi_configure, + .xfer = spi_xfer, +}; + +/** + * Attach the spi device to SPI bus, this function must be used after initialization. + */ +rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, uint16_t cs_gpio_pin) +{ + rt_err_t result; + struct rt_spi_device *spi_device; + ft2004_spi_class *spi_class = ft2004_spi_get_class(); + + RT_ASSERT(spi_class != RT_NULL); + + spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device)); + RT_ASSERT(spi_device != RT_NULL); + + result = rt_spi_bus_attach_device(spi_device, device_name, bus_name, RT_NULL); + + LOG_I("attach result 0x%x", result); + + if (result != RT_EOK) + { + if (spi_device) + { + rt_free(spi_device); + } + } + return result; +} + +static int rt_hw_spi_bus_init(void) +{ + rt_err_t result; + ft2004_spi_class *spi_class = ft2004_spi_get_class(); + + LOG_I("init spi ctrl"); + spi_class->spi_bus.parent.user_data = &spi_class->spi_bus; + result = rt_spi_bus_register(&spi_class->spi_bus, SPI_BUS_NAME, &ft2004_spi_ops); + return result; +} + +int rt_hw_spi_init(void) +{ + return rt_hw_spi_bus_init(); +} +INIT_BOARD_EXPORT(rt_hw_spi_init); + +static void rthw_spi_delay(u32 delayCnt) +{ + Ft_GenericTimer_UsDelay(delayCnt); +} + +/************spi flash operatiosn implemented for sample test****************/ +/* definition of s25fs maunfactor id */ +typedef struct +{ + u8 Mid; + u8 MemoryType; + u8 Density; + u8 RemainBytes; + u8 PhySectArch; + u8 FamilyID; +}ft2004_manuid_t; + +/* definition of cmd for s25fs */ +#define S25FS_ENABLE_WR 0x06 +#define S25FS_DISABLE_WR 0x04 +#define S25FS_READ_ID 0x9F +#define S25FS_READ_4BYTE_ADD 0x13 +#define S25FS_ERASE_4BYTE_ADD 0x21 +#define S25FS_READ_STATUS_1 0x05 +#define S25FS_READ_FLASH_PARAM 0x5A + +static void ft2004_dump_manuid(const ft2004_manuid_t *pId) +{ + rt_kprintf("0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\r\n", + pId->Mid, pId->MemoryType, pId->Density, pId->RemainBytes, + pId->PhySectArch, pId->FamilyID); +} + +static u32 ft2004_read_in_4byte_addr(const u32 ReadAddr, const u32 BytesToRead, u8 *pBuf) +{ + u32 ret = ERR_SPI_OK; + u32 loop; + + RT_ASSERT(RT_NULL != pBuf); + + ft2004_spi_cs(TRUE); + ret |= ft2004_spi_transcation(S25FS_READ_4BYTE_ADD, RT_NULL); + /* only 4-bytes address, MSB first */ + ret |= ft2004_spi_transcation((u8)(ReadAddr >> 24), RT_NULL); + ret |= ft2004_spi_transcation((u8)(ReadAddr >> 16), RT_NULL); + ret |= ft2004_spi_transcation((u8)(ReadAddr >> 8), RT_NULL); + ret |= ft2004_spi_transcation((u8)ReadAddr, RT_NULL); + /* read out data */ + for (loop = 0; loop < BytesToRead; loop++) + { + ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, pBuf + loop); + if (ERR_SPI_OK != ret) + { + break; + } + } + ft2004_spi_cs(FALSE); + return ret; +} + +u32 ft2004_spi_enable_wr(const bool_t enable) +{ + u32 ret = ERR_SPI_OK; + ft2004_spi_cs(TRUE); + if (enable) + { + ret |= ft2004_spi_transcation(S25FS_ENABLE_WR, RT_NULL); + } + else + { + ret |= ft2004_spi_transcation(S25FS_DISABLE_WR, RT_NULL); + } + ft2004_spi_cs(FALSE); + return ret; +} + +u32 ft2004_erase_sector_in_4byte_addr(const u32 sector_addr) +{ + u32 Ret = ERR_SPI_OK; + + ft2004_spi_enable_wr(TRUE); + LOG_I("erase sector 0x%x", Ret); + if (ERR_SPI_OK != Ret) + { + return Ret; + } + + ft2004_spi_cs(TRUE); + Ret |= ft2004_spi_transcation(S25FS_ERASE_4BYTE_ADD, RT_NULL); + Ret |= ft2004_spi_transcation((u8)(sector_addr >> 24), RT_NULL); + Ret |= ft2004_spi_transcation((u8)(sector_addr >> 16), RT_NULL); + Ret |= ft2004_spi_transcation((u8)(sector_addr >> 8), RT_NULL); + Ret |= ft2004_spi_transcation((u8)(sector_addr), RT_NULL); + ft2004_spi_cs(FALSE); + + return Ret; +} + +u32 ft2004_spi_read_params(const u32 Addr) +{ + u32 Ret = ERR_SPI_OK; + u8 dat[8] = {0}; + u32 loop; + + ft2004_spi_cs(TRUE); + Ret |= ft2004_spi_transcation(S25FS_READ_FLASH_PARAM, RT_NULL); + Ret |= ft2004_spi_transcation((u8)(Addr >> 16), RT_NULL); + Ret |= ft2004_spi_transcation((u8)(Addr >> 8), RT_NULL); + Ret |= ft2004_spi_transcation((u8)(Addr), RT_NULL); + for (loop = 0; loop < 8; loop++) + { + Ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, dat + loop); + rt_kprintf("%d: 0x%x", loop, *(dat + loop)); + } + + ft2004_spi_cs(FALSE); + return Ret; +} + +static u32 ft2004_spi_readid_for_test( ft2004_manuid_t *pId) +{ + FSpi_Ctrl_t *ctrl_p = ft2004_spi_get_ctrl(); + u32 ret = ERR_SPI_OK; + + if (!ctrl_p->IsReady) + { + return ERR_SPI_NOT_READY; + } + + RT_ASSERT(RT_NULL != pId); + + ft2004_spi_cs(TRUE); + + /* shifting the command code “90H” followed by a 24-bit address */ + ret |= ft2004_spi_transcation(S25FS_READ_ID, RT_NULL); + + /* Manufacturer ID and the Device ID are shifted out */ + ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->Mid); + ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->MemoryType); + ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->Density); + ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->RemainBytes); + ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->PhySectArch); + ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->FamilyID); + ft2004_spi_cs(FALSE); + + if (ERR_SPI_OK == ret) + { + ft2004_dump_manuid(pId); + } + + return ret; +} + +static void spi_9f_s25fs_sample(int argc, char *argv[]) +{ + ft2004_manuid_t dev_id; + u32 ret = ERR_SPI_OK; + u32 delay = SPI_TIMEOUT * 10; + + rt_kprintf("test s25fs spi flash\r\n"); + ret |= ft2004_spi_init(RT_NULL); + ret |= ft2004_spi_readid_for_test(&dev_id); + + rt_kprintf("result is: 0x%x \r\n", ret); + while (--delay) + { + rthw_spi_delay(10); + } +} +MSH_CMD_EXPORT(spi_9f_s25fs_sample, "spi s25fs cmd 9fH sample"); + +static u8 read_buf[256]; +static void spi_5a_s25fs_sample(int argc, char *argv[]) +{ + u32 ret = ERR_SPI_OK; + u32 delay = SPI_TIMEOUT * 10; + u32 read_addr = 0x0000; + + rt_kprintf("test s25fs spi flash\r\n"); + ret |= ft2004_spi_init(RT_NULL); + ret |= ft2004_spi_read_params(read_addr); + ret |= ft2004_read_in_4byte_addr(read_addr, 256, read_buf); + rt_kprintf("result is: 0x%x \r\n", ret); + while (--delay) + { + rthw_spi_delay(10); + } +} +MSH_CMD_EXPORT(spi_5a_s25fs_sample, "spi s25fs cmd 5aH sample"); \ No newline at end of file diff --git a/bsp/ft2004/libraries/drivers/rtthread/drv_spi.h b/bsp/ft2004/libraries/drivers/rtthread/drv_spi.h new file mode 100644 index 0000000000000000000000000000000000000000..0d9ae1d9e6f155e309c012d4e1fecc3bdba591d1 --- /dev/null +++ b/bsp/ft2004/libraries/drivers/rtthread/drv_spi.h @@ -0,0 +1,29 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-25 14:01:39 + * @LastEditTime: 2021-04-29 09:40:13 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ +#ifndef FT_DRIVERS_RTT_SPI_H +#define FT_DRIVERS_RTT_SPI_H + +#include + +#define SPI_BUS_NAME "spi0" +#define SPI_DEV_NAME "S25FS256" + +rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, uint16_t cs_gpio_pin); + +#ifdef __cplusplus +extern "C" +{ +#endif + +#endif \ No newline at end of file diff --git a/bsp/ft2004/libraries/drivers/rtthread/drv_usart.c b/bsp/ft2004/libraries/drivers/rtthread/drv_usart.c new file mode 100644 index 0000000000000000000000000000000000000000..ada3178e192ec885cd99da6a3fea5d0ced94db7d --- /dev/null +++ b/bsp/ft2004/libraries/drivers/rtthread/drv_usart.c @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-03-04 Carl the first version + */ + +#include "board.h" +#include "drv_usart.h" +#include "interrupt.h" +#include "serial.h" +#include "rtconfig.h" + +#ifdef RT_USING_SERIAL + +extern u32 FUart_GetInterruptMask(Ft_Uart *uart_ptr); + +static void Ft_Os_Uart_Callback(void *Args, u32 Event, u32 EventData); + +static void rt_hw_uart_isr(int irqno, void *param) +{ + Ft_Uart *uart_ptr = (Ft_Uart *)param; + FUart_InterruptHandler(uart_ptr); +} + +static rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) +{ + struct drv_usart *uart; + Ft_Uart *uart_ptr; + u32 RegTemp; + RT_ASSERT(serial != RT_NULL); + RT_ASSERT(cfg != RT_NULL); + uart = rt_container_of(serial, struct drv_usart, serial); + uart_ptr = uart->handle; + + RT_ASSERT(FUart_CfgInitialize(uart_ptr, FUart_LookupConfig(uart_ptr->Config.InstanceId)) == FST_SUCCESS); + FUart_SetHandler(uart_ptr, Ft_Os_Uart_Callback, serial); + rt_hw_interrupt_install(uart_ptr->Config.IsrNum, rt_hw_uart_isr, uart_ptr, "uart"); + rt_hw_interrupt_umask(uart_ptr->Config.IsrNum); + + //handle; + + switch (cmd) + { + case RT_DEVICE_CTRL_CLR_INT: + /* disable rx irq */ + rt_hw_interrupt_mask(uart_ptr->Config.IsrNum); + break; + + case RT_DEVICE_CTRL_SET_INT: + /* enable rx irq */ + rt_hw_interrupt_umask(uart_ptr->Config.IsrNum); + break; + } + + return RT_EOK; +} + +static void Ft_Os_Uart_Callback(void *Args, u32 Event, u32 EventData) +{ + struct rt_serial_device *serial = (struct rt_serial_device *)Args; + + if (FUART_EVENT_RECV_DATA == Event || FUART_EVENT_RECV_TOUT == Event) + { + rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); + } + else if (FUART_EVENT_RECV_ERROR == Event) + { + } + else if (FUART_EVENT_SENT_DATA == Event) + { + } + else if (FUART_EVENT_PARE_FRAME_BRKE == Event) + { + } + else if (FUART_EVENT_RECV_ORERR == Event) + { + } + + if (FUART_EVENT_SENT_DATA == Event) + { + } + else + { + // u32 RegTemp; + // //UartObj); + // RegTemp &= ~UARTMIS_RTMIS; + // FUart_SetInterruptMask(&Osuart_ptr->UartObj, RegTemp); + } +} + +static int uart_putc(struct rt_serial_device *serial, char c) +{ + struct drv_usart *uart; + Ft_Uart *uart_ptr; + RT_ASSERT(serial != RT_NULL); + + uart = rt_container_of(serial, struct drv_usart, serial); + uart_ptr = uart->handle; + + FUart_SendByte(uart_ptr->Config.BaseAddress, c); + + return 1; +} + +static int uart_getc(struct rt_serial_device *serial) +{ + int ch; + struct drv_usart *uart; + Ft_Uart *uart_ptr; + RT_ASSERT(serial != RT_NULL); + + uart = rt_container_of(serial, struct drv_usart, serial); + uart_ptr = uart->handle; + + ch = FUart_GetChar(uart_ptr->Config.BaseAddress); + if (ch == 0xff) + ch = -1; + + return ch; +} + +static const struct rt_uart_ops _uart_ops = + { + uart_configure, + uart_control, + uart_putc, + uart_getc, +}; + +#ifdef RT_USING_UART0 +static Ft_Uart Ft_Uart0; +static struct drv_usart _RtUart0; +#endif + +#ifdef RT_USING_UART1 +static Ft_Uart Ft_Uart1; +static struct drv_usart _RtUart1; +#endif + +int rt_hw_uart_init(void) +{ + + struct serial_configure config; + +#ifdef RT_USING_UART0 + config.bufsz = RT_SERIAL_RB_BUFSZ; + _RtUart0.serial.ops = &_uart_ops; + _RtUart0.serial.config = config; + Ft_Uart0.Config.InstanceId = FT_UART0_ID; + _RtUart0.Handle = &Ft_Uart0; + + rt_hw_serial_register(&_RtUart0.serial, "uart0", + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, + &_RtUart0); +#endif + +#ifdef RT_USING_UART1 + config.bufsz = RT_SERIAL_RB_BUFSZ; + // Ft_printf("RT_USING_UART1 serial is %x \r\n", &_RtUart1.serial); + _RtUart1.serial.ops = &_uart_ops; + _RtUart1.serial.config = config; + Ft_Uart1.Config.InstanceId = FT_UART1_ID; + _RtUart1.handle = &Ft_Uart1; + rt_hw_serial_register(&_RtUart1.serial, "uart1", + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, + &_RtUart1); +#endif + + return 0; +} +INIT_BOARD_EXPORT(rt_hw_uart_init); + +#endif /* RT_USING_SERIAL */ diff --git a/bsp/ft2004/libraries/drivers/rtthread/drv_usart.h b/bsp/ft2004/libraries/drivers/rtthread/drv_usart.h new file mode 100644 index 0000000000000000000000000000000000000000..abd265a259529cd9c00f6d1fa5951426f542dd6e --- /dev/null +++ b/bsp/ft2004/libraries/drivers/rtthread/drv_usart.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-03-04 Carl the first version + */ + +#ifndef __DRV_USART_H__ +#define __DRV_USART_H__ + +#include +#include "rtdevice.h" +#include "ft_uart.h" + +struct drv_usart +{ + Ft_Uart *handle; + + /* data */ + struct rt_serial_device serial; +}; + +#endif // ! \ No newline at end of file diff --git a/bsp/ft2004/libraries/drivers/rtthread/ports/drv_qspi_flash.c b/bsp/ft2004/libraries/drivers/rtthread/ports/drv_qspi_flash.c new file mode 100644 index 0000000000000000000000000000000000000000..102cd5fc5b5226ffa2de0dbb3cbc4b7da997dd09 --- /dev/null +++ b/bsp/ft2004/libraries/drivers/rtthread/ports/drv_qspi_flash.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-04-08 Carl the first version + */ + +#include +#include +#include +#include +#include + +#ifdef BSP_USE_QSPI + +#include "spi_flash.h" +#include "spi_flash_sfud.h" +#define _QSPI_DEVICE_NAME "qspiflash" + +static int +rt_hw_qspi_flash_with_sfud_init(void) +{ + ft2004_qspi_bus_attach_device(FT2004_QSPI_NAME, _QSPI_DEVICE_NAME, 1, RT_NULL, RT_NULL); + + /* init gd */ + rt_kprintf("start rt_sfud_flash_probe \r\n"); + if (RT_NULL == rt_sfud_flash_probe("GD25LQ256D", _QSPI_DEVICE_NAME)) + { + return -RT_ERROR; + } + + return RT_EOK; +} +INIT_COMPONENT_EXPORT(rt_hw_qspi_flash_with_sfud_init); + +#endif /* BSP_USING_QSPI_FLASH */ diff --git a/bsp/ft2004/libraries/drivers/rtthread/ports/drv_spi_flash.c b/bsp/ft2004/libraries/drivers/rtthread/ports/drv_spi_flash.c new file mode 100644 index 0000000000000000000000000000000000000000..6189a81da4defe4992ba24a8e657ec9315042baf --- /dev/null +++ b/bsp/ft2004/libraries/drivers/rtthread/ports/drv_spi_flash.c @@ -0,0 +1,43 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-25 14:01:16 + * @LastEditTime: 2021-04-30 14:43:12 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include +#include +#include +#include +#include +#include "ft_spi.h" + +#ifdef BSP_USE_SPI + +#include "spi_flash.h" +#include "spi_flash_sfud.h" + +static int rt_hw_spi_flash_init(void) +{ + uint16_t cs_pin = 5; + rt_hw_spi_device_attach(SPI_BUS_NAME, SPI_DEV_NAME, cs_pin); + + rt_kprintf("attach spi flash\r\n"); + /* lookup flah */ + if (RT_NULL == rt_sfud_flash_probe("S25FS256S", SPI_DEV_NAME)) + { + rt_kprintf("attach spi flash failed\r\n"); + return -RT_ERROR; + } + + return RT_EOK; +} +INIT_COMPONENT_EXPORT(rt_hw_spi_flash_init); +#endif \ No newline at end of file diff --git a/bsp/ft2004/libraries/drivers/system_gic.c b/bsp/ft2004/libraries/drivers/system_gic.c new file mode 100644 index 0000000000000000000000000000000000000000..427b1a5a32107c5a56ea37fe5a33d1563da3b293 --- /dev/null +++ b/bsp/ft2004/libraries/drivers/system_gic.c @@ -0,0 +1,120 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-28 15:05:59 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#include "ft_gicv3.h" +#include "ft_gicv3_hw.h" +#include "ft_io.h" +#include "ft_printf.h" +#include "ft_cpu.h" +#include "ft_types.h" +#include "ft_assert.h" +#include "ft_aarch32_asm.h" +#include "system_gic.h" + +#include "ft_debug.h" +#define SYSTEM_GIC_DEBUG_TAG "SYSTEM_GIC" + +#define SYSTEM_GIC_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(SYSTEM_GIC_DEBUG_TAG, format, ##__VA_ARGS__) +#define SYSTEM_GIC_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(SYSTEM_GIC_DEBUG_TAG, format, ##__VA_ARGS__) +#define SYSTEM_GIC_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(SYSTEM_GIC_DEBUG_TAG, format, ##__VA_ARGS__) + +FGicv3 gicv3_object = {0}; + +void System_Gic_Init(void) +{ + Ft_assertVoid((FGicv3_Config_tInitalize(&gicv3_object, FGicv3_LookupConfig(0)) == FST_SUCCESS)); +} + +void System_Gic_Enable(u32 InterruptID, FGicv3_InterruptHandler_t InterruptHandler, u32 Priority, void *Args) +{ + Ft_assertVoid((FGicV3_Connect(&gicv3_object, InterruptID, InterruptHandler, Priority, Args) == FST_SUCCESS)); + FGicV3_Enable(&gicv3_object, InterruptID); +} + +void System_Gic_Disable(u32 InterruptID) +{ + FGicV3_Disconnect(&gicv3_object, InterruptID); + FGicV3_Disable(&gicv3_object, InterruptID); +} + +void System_GicMask(u32 InterruptID) +{ + FGicV3_Enable(&gicv3_object, InterruptID); +} + +void System_GicUnMask(u32 InterruptID) +{ + FGicV3_Enable(&gicv3_object, InterruptID); +} + +void System_GicSetPriority(u32 InterruptID, u32 Priority) +{ + FGicV3_SetPriority(&gicv3_object, InterruptID, Priority); +} + +s32 System_GicGetActiveIrq(void) +{ + return __MRC(15, 0, 12, 12, 0); +} + +void System_GicAck(s32 InterruptID) +{ + sys_icc_eoir1_set((u32)InterruptID); +} + +__STATIC_INLINE void System_SoftIrqSend(u32 ValLow, u32 ValHigh) +{ + __asm__ __volatile__("MCRR p15,0,%0,%1,c12" + : + : "r"(ValLow), "r"(ValHigh)); +} + +ft_error_t System_IpiGen(s32 InterruptID, s32 CpuIdMask) +{ + u32 cnt = 0; + u8 aff1 = 0, + aff2 = 0, CpuList = 0; + volatile u32 LowWord = 0, HighWord = 0; + + for (cnt = 0; cnt < 32; cnt++) + { + /* code */ + if ((CpuIdMask >> cnt) & 0x1) + { + if (cnt < sizeof(SoftAffiTable) / sizeof(u32)) + { + CpuList = (u8)(SoftAffiTable[cnt] & 0xff); + aff1 = (u8)((SoftAffiTable[cnt] >> 8) & 0xff); + aff2 = (u8)((SoftAffiTable[cnt] >> 16) & 0xff); + CpuList = 1 << CpuList; + LowWord |= CpuList; + LowWord |= (InterruptID & 0xffff) << 24; + LowWord |= aff1 << 16; + HighWord |= aff2; + rt_kprintf("HighWord %x \r\n", HighWord); + rt_kprintf("LowWord %x \r\n", LowWord); + System_SoftIrqSend(LowWord, HighWord); + + // SYSTEM_GIC_DEBUG_E("System_IpiGen IS OK cnt is %x low %x, High %x \r\n", cnt, LowWord, HighWord); + } + else + { + SYSTEM_GIC_DEBUG_E("CpuId is over max size %x \r\n", CpuIdMask); + return SYSGIC_FAILURE; + } + } + } + + return SYSGIC_SUCCESS; +} \ No newline at end of file diff --git a/bsp/ft2004/libraries/drivers/system_gic.h b/bsp/ft2004/libraries/drivers/system_gic.h new file mode 100644 index 0000000000000000000000000000000000000000..974a667c97fd2cf451d8f7005f67a1c2e32650d0 --- /dev/null +++ b/bsp/ft2004/libraries/drivers/system_gic.h @@ -0,0 +1,47 @@ +/* + * @ : Copyright (c) 2020 Phytium Information Technology, Inc. + * The right to copy, distribute, modify, or otherwise make use + * of this software may be licensed only pursuant to the terms + * of an applicable Phytium license agreement. + * @Date: 2021-04-07 09:53:07 + * @LastEditTime: 2021-04-27 16:02:36 + * @Description:  This files is for + * + * @Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + */ + +#ifndef SYSTEM_GIC_H +#define SYSTEM_GIC_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ft_types.h" +#include "ft_gicv3.h" +#include "ft_error_code.h" + +#define SYSGIC_SUCCESS FST_SUCCESS /* SUCCESS */ +#define SYSGIC_FAILURE FT_MAKE_ERRCODE(errGicV3, errPort, FST_FAILURE) /* Normal */ +#define SYSGIC_TIMEOUT FT_MAKE_ERRCODE(errGicV3, errPort, FST_TIMEOUT) /* Timeout */ +#define SYSGIC_EILSEQ FT_MAKE_ERRCODE(errGicV3, errPort, FST_EILSEQ) /* Illegal byte sequence. */ +#define SYSGIC_INVALID_PARAM FT_MAKE_ERRCODE(errGicV3, errPort, FST_INVALID_PARAM) /* Invalid param. */ + + void System_Gic_Init(void); + void System_Gic_Enable(u32 InterruptID, FGicv3_InterruptHandler_t InterruptHandler, u32 Priority, void *Args); + void System_Gic_Disable(u32 InterruptID); + void System_GicMask(u32 InterruptID); + void System_GicUnMask(u32 InterruptID); + void System_GicAck(s32 InterruptID); + void System_GicSetPriority(u32 InterruptID, u32 Priority); + s32 System_GicGetActiveIrq(void); + ft_error_t System_IpiGen(s32 InterruptID, s32 CpuId); + +#ifdef __cplusplus +} +#endif + +#endif // ! \ No newline at end of file diff --git a/bsp/ft2004/libraries/gcc/assembly_functions.olsd b/bsp/ft2004/libraries/gcc/assembly_functions.olsd new file mode 100644 index 0000000000000000000000000000000000000000..68e58e48a36e148ec01a7f981c6034bec22588d6 --- /dev/null +++ b/bsp/ft2004/libraries/gcc/assembly_functions.olsd @@ -0,0 +1,178 @@ + +#include "asmArm.h" + + + .globl FUNC(sys_icc_igrpen0_set) + .globl FUNC(sys_icc_igrpen0_get) + .globl FUNC(sys_icc_igrpen1_set) + .globl FUNC(sys_icc_igrpen1_get) + .globl FUNC(sys_icc_ctlr_set) + .globl FUNC(sys_icc_bpr_set) + .globl FUNC(sys_icc_hppir0_get) + .globl FUNC(sys_icc_hppir1_get) + .globl FUNC(sys_icc_eoir0_set) + .globl FUNC(sys_icc_eoir1_set) + .globl FUNC(sys_icc_pmr_set) + .globl FUNC(sys_icc_iar1_get) + .globl FUNC(sys_icc_sgi1r_set) + .globl FUNC(sys_icc_sgi0r_set) + .globl FUNC(sys_icc_sre_set) + .globl FUNC(sys_icc_sre_get) + .globl FUNC(vxMpidrGet) + .globl FUNC(armSmcCall) + .globl FUNC(sys_cntkctl_get) + .globl FUNC(sys_dfar_get) + .globl FUNC(sys_dfsr_get) + .globl FUNC(sys_ifar_get) + .globl FUNC(sys_ifsr_get) + .text + .balign 4 + +/* void sys_icc_igrpen0_set(unsigned int) */ +FUNC_BEGIN(sys_icc_igrpen0_set) + mcr p15, 0, r0, c12, c12, 6 + isb + mov pc, lr + +/* unsigned int sys_icc_igrpen0_get(void) */ +FUNC_BEGIN(sys_icc_igrpen0_get) + mrc p15, 0, r0, c12, c12, 6 + mov pc, lr + +/* void sys_icc_igrpen1_set(unsigned int) */ +FUNC_BEGIN(sys_icc_igrpen1_set) + mcr p15, 0, r0, c12, c12, 7 + isb + mov pc, lr + +/* void sys_icc_igrpen1_get(unsigned int) */ +FUNC_BEGIN(sys_icc_igrpen1_get) + mrc p15, 0, r0, c12, c12, 7 + isb + mov pc, lr + +/* void sys_icc_ctlr_set(unsigned int) */ +FUNC_BEGIN(sys_icc_ctlr_set) + mcr p15, 0, r0, c12, c12, 4 + mov pc, lr + +/* unsigned int sys_icc_hppir0_get(void) */ +FUNC_BEGIN(sys_icc_hppir0_get) + mrc p15, 0, r0, c12, c8, 2 + isb + mov pc, lr + +/* unsigned int sys_icc_hppir1_get(void) */ +FUNC_BEGIN(sys_icc_hppir1_get) + mrc p15, 0, r0, c12, c12, 2 + isb + mov pc, lr + +/* void sys_icc_bpr_set(unsigned int) */ +FUNC_BEGIN(sys_icc_bpr_set) + mcr p15, 0, r0, c12, c8, 3 + isb + mov pc, lr + + + +/* void sys_icc_eoir0_set(unsigned int) */ +FUNC_BEGIN(sys_icc_eoir0_set) + mcr p15, 0, r0, c12, c8, 1 + isb + mov pc, lr + + +/* void sys_icc_eoir1_set(unsigned int) */ +FUNC_BEGIN(sys_icc_eoir1_set) + mcr p15, 0, r0, c12, c12, 1 + isb + mov pc, lr + +/* void sys_icc_pmr_set(unsigned int) */ +FUNC_BEGIN(sys_icc_pmr_set) + mcr p15, 0, r0, c4, c6, 0 + isb + mov pc, lr + +/* unsigned int sys_icc_iar1_get(void) */ +FUNC_BEGIN(sys_icc_iar1_get) + mrc p15, 0, r0, c12, c12, 0 + isb + mov pc, lr +#if 0 +/* void sys_icc_igrpen1_set(unsigned int) */ +FUNC_BEGIN(sys_icc_sgi1r_set) + mcrr p15, 0, r0, r1, c12 + isb + mov pc, lr + +FUNC_BEGIN(sys_icc_sgi0r_set) + mcrr p15, 2, r0, r1, c12 + isb + mov pc, lr +#endif +/* void sys_icc_sre_set(unsigned int) */ +FUNC_BEGIN(sys_icc_sre_set) + mcr p15, 0, r0, c12, c12, 5 + isb + mov pc, lr + +/* unsigned int sys_icc_sre_get(void) */ +FUNC_BEGIN(sys_icc_sre_get) + mrc p15, 0, r0, c12, c12, 5 + isb + mov pc, lr + + /* unsigned int sys_icc_sre_get(void) */ +FUNC_BEGIN(sys_cntkctl_get) + mcr p15, 0, r0, c14, c1, 0 + isb + mov pc, lr + +FUNC_BEGIN(sys_dfar_get) + MRC p15,0,r0,c6,c0,0 + isb + mov pc, lr + +FUNC_BEGIN(sys_dfsr_get) + MRC p15,0,r0,c5,c0,0 + isb + mov pc, lr + +FUNC_BEGIN(sys_ifar_get) + MRC p15,0,r0,c6,c0,2 + isb + mov pc, lr + +FUNC_BEGIN(sys_ifsr_get) + MRC p15,0,r0,c5,c0,1 + isb + mov pc, lr + +#if 0 +FUNC_BEGIN(vxCpsrGet) + MRS r0, cpsr + isb + mov pc, lr + +#endif +FUNC_BEGIN(vxMpidrGet) + MRC p15, 0, r0, c0, c0, 5 + MOV pc, lr + + + + + + + + + + + + + + + + diff --git a/bsp/ft2004/libraries/gcc/lib_test.c b/bsp/ft2004/libraries/gcc/lib_test.c new file mode 100644 index 0000000000000000000000000000000000000000..20f037ab0390ddfb79bf3f26df9c013ba54f478c --- /dev/null +++ b/bsp/ft2004/libraries/gcc/lib_test.c @@ -0,0 +1,134 @@ +/* + * @Author: hh + * @Date: 2020-12-29 17:07:06 + * @LastEditTime: 2021-03-01 11:11:24 + * @LastEditors: Please set LastEditors + * @Description: In User Settings Edit + * @FilePath: \ft\project_freertos\devices\ft2000ahk\gcc\main.c + */ + +// #include +// #include + +// int main(void) +// { +// volatile char *data = 0; +// data = malloc(1); +// memcpy(data, data, 1); +// free((void *)data); +// return data; +// } + +#include +#include +#include +#include +#include "ft_types.h" +#include "ft_printf.h" + +// int main(void) +// { +// volatile char *data = 0; +// Ft_printf("233333"); +// data = malloc(1024); +// return (int)data; +// } + +void user_fun_def(void) +{ + Ft_printf("user_fun_def \r\n"); + while (1) + { + } +} + +void frq_debug(u32 r0, u32 r1) +{ + Ft_printf("test frq current %x ,last %x\r\n", r0, r1); + while (1) + { + } +} + +void irq_debug(u32 r0, u32 r1) +{ + Ft_printf("test irq current %x ,last %x\r\n", r0, r1); + while (1) + { + } +} + +void PrefAbort_debug(void) +{ + Ft_printf("PrefAbort_debug\r\n"); + while (1) + { + } +} + +void Svc_debug(void) +{ + Ft_printf("Svc_debug\r\n"); + while (1) + { + } +} + +void Undefine_debug(void) +{ + Ft_printf("Undefine_debug\r\n"); + while (1) + { + } +} + +void data_abort_debug(void) +{ + Ft_printf("data abort\r\n"); + while (1) + { + } +} + +int _close(int file) { return -1; } + +int _fstat(int file, struct stat *st) +{ + // st->st_mode = S_IFCHR; + return 0; +} + +int _isatty(int file) { return 1; } + +int _lseek(int file, int ptr, int dir) { return 0; } + +int _open(const char *name, int flags, int mode) { return -1; } + +int _read(int file, char *ptr, int len) +{ + int todo = 0; + // if (len == 0) + // return 0; + // while (UART_FR(UART0_ADDR) & UART_FR_RXFE) + // ; + // *ptr++ = UART_DR(UART0_ADDR); + // for (todo = 1; todo < len; todo++) + // { + // if (UART_FR(UART0_ADDR) & UART_FR_RXFE) + // { + // break; + // } + // *ptr++ = UART_DR(UART0_ADDR); + // } + return todo; +} +int _write(int file, char *ptr, int len) +{ + // int todo; + + // for (todo = 0; todo < len; todo++) + // { + // UART_DR(UART0_ADDR) = *ptr++; + // } + return 0; +} diff --git a/bsp/ft2004/libraries/gcc/ram_ft_aarch32.lds b/bsp/ft2004/libraries/gcc/ram_ft_aarch32.lds new file mode 100644 index 0000000000000000000000000000000000000000..50bbd06b061d8a480ea0c3be14d7c21ebac6ccc7 --- /dev/null +++ b/bsp/ft2004/libraries/gcc/ram_ft_aarch32.lds @@ -0,0 +1,86 @@ + + +ENTRY(Startup_Aarch32) + +HEAP_SIZE = DEFINED(__heap_size__) ? __heap_size__ : 0x0400; +ISTACK_SIZE = DEFINED(__irq_stack_size__) ? __irq_stack_size__ : 0x0800; +CSTACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x0800; +USTACK_SIZE = DEFINED(__user_stack_size__) ? __user_stack_size__ : 0x0800; + + + +/* Specify the memory areas */ +MEMORY +{ + m_mode_transform (RX) : ORIGIN = 0x80100000, LENGTH = 0x00000200 + m_interrupts (RX) : ORIGIN = 0x80100200, LENGTH = 0x00000040 + m_text (RX) : ORIGIN = 0x80100240, LENGTH = 0x003ffdc0 + m_data (RW) : ORIGIN = 0x80400000, LENGTH = 0x00800000 + m_stack (RW) : ORIGIN = 0x80c00000, LENGTH = 0x00400000 +} + + +/* Define output sections */ +SECTIONS +{ + . = 0x80100000 ; + .mode_transform : + { + . = ALIGN(4); + KEEP(*(.Startup_Aarch32)) /* Startup code */ + . = ALIGN(4); + } > m_mode_transform + + .interrupts : + { + __VECTOR_TABLE = .; + . = ALIGN(4); + KEEP(*(.Startup_Ft_Aarch32)) /* Startup code */ + . = ALIGN(4); + } > m_interrupts + + /* The program code and other data goes into DDR RAM */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + KEEP (*(.init)) + KEEP (*(.fini)) + _exit = .; + . = ALIGN(4); + } > m_text + + .heap : + { + . = ALIGN(8); + __end__ = .; + PROVIDE(end = .); + __HeapBase = .; + . += HEAP_SIZE; + __HeapLimit = .; + __heap_limit = .; /* Add for _sbrk */ + } > m_data + + /* Initializes stack on the end of block */ + .stack : + { + __IStackTop = .; + __IStackLimit = __IStackTop - ISTACK_SIZE; + __CStackTop = __IStackLimit; + __CStackLimit = __CStackTop - CSTACK_SIZE; + __UStackTop = __CStackLimit; + __UStackLimit = __UStackTop - USTACK_SIZE; + PROVIDE(__stack = __CStackTop); + } > m_stack + + + .rodata ALIGN(4) : {*(.rodata*)} >m_data + .data ALIGN(4) : { *(.data) } >m_data +} + diff --git a/bsp/ft2004/libraries/gcc/startup_aarch32.S b/bsp/ft2004/libraries/gcc/startup_aarch32.S new file mode 100644 index 0000000000000000000000000000000000000000..b08dcbb6ad8257d57e251fa8d5aa7f086e945432 --- /dev/null +++ b/bsp/ft2004/libraries/gcc/startup_aarch32.S @@ -0,0 +1,244 @@ + + +.equ Mode_USR, 0x10 +.equ Mode_FIQ, 0x11 +.equ Mode_IRQ, 0x12 +.equ Mode_SVC, 0x13 +.equ Mode_ABT, 0x17 +.equ Mode_UND, 0x1B +.equ Mode_SYS, 0x1F + +.section .Startup_Aarch32, "a" +.global Startup_Aarch32 /* 全局标号 */ + +Startup_Aarch32: + + + + MRS r1, cpsr + BIC r1, r1, #0x0000001F + ORR r1, r1, #0x13 | (1<<7) | (1<<6) + MSR cpsr, r1 + + /* + * SPSR does not have pre-defined reset value. + * Here correct endianess (BE bit) in SPSR + */ + + MRS r0, spsr + BIC r0, r0, #(0x1 << 9) /* Little Endian */ + MSR spsr_x, r0 + + + b Startup_Ft_Aarch32 + + .size Startup_Aarch32, . - Startup_Aarch32 + .text + .arm + + +.syntax unified +.arch armv8-a + +.section .Startup_Ft_Aarch32, "a" +.align 2 +.global Startup_Ft_Aarch32 /* 全局标号 */ + +Startup_Ft_Aarch32: + + ldr pc, =Reset_Handler /* Reset */ + ldr pc, =Undefined_Handler /* Undefined instructions */ + ldr pc, =SVC_Handler /* Supervisor Call */ + ldr pc, =PrefAbort_Handler /* Prefetch abort */ + /* ldr pc, =DataAbort_Handler Data abort */ + ldr pc, =DataAbort_Handler + .word 0 /* RESERVED */ + ldr pc, =IRQ_Handler /* IRQ interrupt */ + ldr pc, =FIQ_Handler /* FIQ interrupt */ + + .size Startup_Ft_Aarch32, . - Startup_Ft_Aarch32 + .text + .arm + + + + .arm + .align 2 + .globl Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + cpsid i /* Mask interrupts */ + + + /* 关闭I,DCache和MMU + * 采取读-改-写的方式。 + */ + mrc p15, 0, r0, c1, c0, 0 /* 读取CP15的C1寄存器到R0中 */ + bic r0, r0, #(0x1 << 12) /* 清除C1寄存器的bit12位(I位),关闭I Cache */ + bic r0, r0, #(0x1 << 2) /* 清除C1寄存器的bit2(C位),关闭D Cache */ + bic r0, r0, #0x2 /* 清除C1寄存器的bit1(A位),关闭对齐 */ + bic r0, r0, #(0x1 << 11) /* 清除C1寄存器的bit11(Z位),关闭分支预测 */ + bic r0, r0, #0x1 /* 清除C1寄存器的bit0(M位),关闭MMU */ + mcr p15, 0, r0, c1, c0, 0 /* 将r0寄存器中的值写入到CP15的C1寄存器中 */ + + + /* 设置用户堆栈 */ + /* Set up stack for IRQ, System/User and Supervisor Modes */ + /* 进入IRQ模式 */ + mrs r0, cpsr + bic r0, r0, #0x1f /* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4 */ + orr r0, r0, #0x12 /* r0或上0x13,表示使用IRQ模式 */ + msr cpsr, r0 /* 将r0 的数据写入到cpsr_c中 */ + ldr sp, =__IStackTop + + /* 进入SYS模式 */ + mrs r0, cpsr + bic r0, r0, #0x1f /* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4 */ + orr r0, r0, #0x1f /* r0或上0x13,表示使用SYS模式 */ + msr cpsr, r0 /* 将r0 的数据写入到cpsr_c中 */ + ldr sp, =__CStackTop + + /* 进入SVC模式 */ + mrs r0, cpsr + bic r0, r0, #0x1f /* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4 */ + orr r0, r0, #0x13 /* r0或上0x13,表示使用SVC模式 */ + msr cpsr, r0 /* 将r0 的数据写入到cpsr_c中 */ + ldr sp, =__CStackTop + + + + +#ifndef NO_RTOS + ldr r0,=SystemInit + blx r0 + + MOV R0, #(0xF << 20) // Enable CP10 & CP11 function + MCR P15, 0, R0, C1, C0, 2 // Write the Coprocessor Access Control + ISB // Register (CPACR). + // Switch on the FP and NEON hardware. + MOV R1, #(0x1 << 30) + VMSR FPEXC, R1 + +#endif + + cpsie i /* 打开全局中断 */ + + /* b main 跳转到main函数 */ + b main + + + +.macro push_svc_reg + sub sp, sp, #17 * 4 @/* Sizeof(struct ft_hw_exp_stack) */ + stmia sp, {r0 - r12} @/* Calling r0-r12 */ + mov r0, sp + mrs r6, spsr @/* Save CPSR */ + str lr, [r0, #15*4] @/* Push PC */ + str r6, [r0, #16*4] @/* Push CPSR */ + cps #Mode_SVC + str sp, [r0, #13*4] @/* Save calling SP */ + str lr, [r0, #14*4] @/* Save calling PC */ +.endm + + + +/* Undefined_Handler */ + .align 2 + .arm + .weak Undefined_Handler + .type Undefined_Handler, %function +Undefined_Handler: + b Undefine_debug + b Undefined_Handler + .size Undefined_Handler, . - Undefined_Handler + + + .align 2 + .arm + .weak SVC_Handler + .type SVC_Handler, %function +SVC_Handler: + b Svc_debug + ldr r0,=SVC_Handler + bx r0 + .size SVC_Handler, . - SVC_Handler + + .align 2 + .arm + .weak PrefAbort_Handler + .type PrefAbort_Handler, %function +PrefAbort_Handler: + b PrefAbort_debug + ldr r0,=PrefAbort_Handler + bx r0 + .size PrefAbort_Handler, . - PrefAbort_Handler + + + .align 5 + .arm + .weak DataAbort_Handler + .type DataAbort_Handler, %function +DataAbort_Handler: + push_svc_reg + bl Ft_Arrch32_trap_dabt + b . + + .align 4 + .arm + .weak IRQ_Handler + .type IRQ_Handler, %function +IRQ_Handler: + push {lr} /* Save return address+4 */ + push {r0-r3, r12} /* Push caller save registers */ + + MRS r0, spsr /* Save SPRS to allow interrupt reentry */ + push {r0} + + /* Get GIC base address MRC P15, 4, r1, C15, C0, 0 */ + + //r0, Regs->r1, Regs->r2, Regs->r3); + TRAPS_DEBUG_E("r04:0x%08x r05:0x%08x r06:0x%08x r07:0x%08x\n", Regs->r4, Regs->r5, Regs->r6, Regs->r7); + TRAPS_DEBUG_E("r08:0x%08x r09:0x%08x r10:0x%08x\n", Regs->r8, Regs->r9, Regs->r10); + TRAPS_DEBUG_E("fp :0x%08x ip :0x%08x\n", Regs->fp, Regs->ip); + TRAPS_DEBUG_E("sp :0x%08x lr :0x%08x pc :0x%08x\n", Regs->sp, Regs->lr, Regs->pc); + TRAPS_DEBUG_E("cpsr:0x%08x\n", Regs->cpsr); +} + +void Ft_Arrch32_trap_dabt(struct ft_hw_exp_stack *Regs) +{ + TRAPS_DEBUG_E("data abort:"); + Ft_Arrch32_Registers(Regs); + while (1) + ; +} diff --git a/bsp/ft2004/libraries/include/asmArm.h b/bsp/ft2004/libraries/include/asmArm.h new file mode 100644 index 0000000000000000000000000000000000000000..8a2766353005f9ae2bb0be8a03b1f450cdc48f63 --- /dev/null +++ b/bsp/ft2004/libraries/include/asmArm.h @@ -0,0 +1,34 @@ +/* + * @Author: your name + * @Date: 2021-01-20 10:07:04 + * @LastEditTime: 2021-04-22 16:32:31 + * @LastEditors: Please set LastEditors + * @Description: In User Settings Edit + * @FilePath: \project_freertos\devices\ft2004\gcc\asmArm.h + */ +#ifndef ASMARM_H +#define ASMARM_H + +#define FUNC_LABEL(func) \ + func: + +#if (defined __GNUC__) +#define FUNC_BEGIN(func) \ + .thumb; \ + .thumb_func; \ + .balign 4; \ + FUNC_LABEL(func) +#else /* !__GNUC__ */ +#define FUNC_BEGIN(func) \ + .thumb; \ + .balign 4; \ + FUNC_LABEL(func) +#endif /* __GNUC__ */ + +#define FUNC(sym) sym +#define FUNC_END(func) .size FUNC(func), .- FUNC(func) + +#define Swap64(var64) var64 +#define Swap32(var32) var32 + +#endif // !ASMARM_H \ No newline at end of file diff --git a/bsp/ft2004/libraries/readme.md b/bsp/ft2004/libraries/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..c8d372b5f2d2d4b002e4bb6be683e4fe6b6dd3bd --- /dev/null +++ b/bsp/ft2004/libraries/readme.md @@ -0,0 +1,69 @@ +# README + +- FT2004 rtos 驱动介绍 + +## 1. 当前版本 + +- V0.4.2 + +## 2. 关于此文档 + +- 本文档提供此项目框架性和基本功能介绍 + +- 详细的硬件 bsp 介绍请阅读 doc 文件中模块子文档。 + +## 3. 编译器版本 + +- gcc-arm-none-eabi-10-2020-q4-major + +## 4. 文件结构介绍 + +| 目录名 | 内容 | +| --------- | ---------------------------------------- | +| bsp | 存放芯片上的外设,例如网卡,i2c 和串口等 | +| component | 板载外设驱动 ,rtc、eeprom、sdmmc 等 | +| cpu | cpu 架构方面指令 | +| doc | 具体外设文档 | +| drivers | 与不同 rtos 进行耦合的驱动 | +| gcc | gcc 编译环境下的启动、链接文件 | +| include | 平台相关的包含 | + +## 5. 支持外设 + +| 外设名 | 备注 | +| -------- | ---------------------- | +| ft_gicv3 | gicv3 中断控制器 | +| ft_gmac | ft gmac 千兆网卡控制器 | +| ft_i2c | FT I2C | +| ft_qspi | FT qspi 控制器 | +| ft_sd | FT mmcsd 控制器 | +| ft_uart | PrimeCell PL011 | +| ft_spi | FT spi 控制器 | +| ft_gpio | FT gpio 控制器 | +| ft_can | FT can 控制器 | + +## 6. 使用实例 + +[freertos](https://gitee.com/phytium_embedded/ft2004-freertos) + +## 7. 参考资源 + +armv8 Architecture Reference Manual + +FT-2000/4 软件编程手册-V1.4 + +FT-2000/4 硬件设计指导手册 + +FT-2000 四核处理器数据手册 V1.6 + +## 8. 贡献方法 + +请联系飞腾嵌入式软件部 + +huanghe@phytium.com.cn + +zhugengyu@phytium.com.cn + +## 9. 许可协议 + +Apache License. diff --git a/bsp/ft2004/make.sh b/bsp/ft2004/make.sh new file mode 100644 index 0000000000000000000000000000000000000000..4fd5c685e07e5d1ca8e087166eabedcb01e36d66 --- /dev/null +++ b/bsp/ft2004/make.sh @@ -0,0 +1,16 @@ +### + # @Author: hh + # @Date: 2020-12-23 13:53:50 + # @LastEditTime: 2021-05-18 16:48:25 + # @LastEditors: Please set LastEditors + # @Description: In User Settings Edit + # @FilePath: \ft\bare\2_base\factory.sh +### +#/bin/sh +# scons --clean +# ./update.sh +scons -j8 +rm /mnt/d/project/tftp/rtthread.bin +cp ./rtthread.bin /mnt/d/project/tftp/ + +# arm-none-eabi-objdump -D -m arm ft2004.elf > rtt.dis \ No newline at end of file diff --git a/bsp/ft2004/rtconfig.h b/bsp/ft2004/rtconfig.h new file mode 100644 index 0000000000000000000000000000000000000000..a717e5b082a4abc72922c991d38e86624792a1c8 --- /dev/null +++ b/bsp/ft2004/rtconfig.h @@ -0,0 +1,270 @@ +#ifndef RT_CONFIG_H__ +#define RT_CONFIG_H__ + +/* Automatically generated file; DO NOT EDIT. */ +/* RT-Thread Project Configuration */ + +/* RT-Thread Kernel */ + +#define RT_NAME_MAX 32 +#define RT_USING_SMP +#define RT_CPUS_NR 4 +#define RT_ALIGN_SIZE 128 +#define RT_THREAD_PRIORITY_32 +#define RT_THREAD_PRIORITY_MAX 32 +#define RT_TICK_PER_SECOND 100 +#define RT_USING_OVERFLOW_CHECK +#define RT_USING_HOOK +#define RT_USING_IDLE_HOOK +#define RT_IDLE_HOOK_LIST_SIZE 4 +#define IDLE_THREAD_STACK_SIZE 4096 +#define RT_USING_TIMER_SOFT +#define RT_TIMER_THREAD_PRIO 4 +#define RT_TIMER_THREAD_STACK_SIZE 512 + +/* kservice optimization */ + +#define RT_DEBUG +#define RT_DEBUG_COLOR + +/* Inter-Thread communication */ + +#define RT_USING_SEMAPHORE +#define RT_USING_MUTEX +#define RT_USING_EVENT +#define RT_USING_MAILBOX +#define RT_USING_MESSAGEQUEUE + +/* Memory Management */ + +#define RT_USING_MEMHEAP +#define RT_USING_SLAB +#define RT_USING_HEAP + +/* Kernel Device Object */ + +#define RT_USING_DEVICE +#define RT_USING_INTERRUPT_INFO +#define RT_USING_CONSOLE +#define RT_CONSOLEBUF_SIZE 4096 +#define RT_CONSOLE_DEVICE_NAME "uart1" +#define RT_VER_NUM 0x40004 +#define ARCH_ARM +#define ARCH_ARM_CORTEX_A +#define RT_USING_GIC_V3 + +/* RT-Thread Components */ + +#define RT_USING_COMPONENTS_INIT +#define RT_USING_USER_MAIN +#define RT_MAIN_THREAD_STACK_SIZE 2048 +#define RT_MAIN_THREAD_PRIORITY 10 + +/* C++ features */ + + +/* Command shell */ + +#define RT_USING_FINSH +#define FINSH_THREAD_NAME "tshell" +#define FINSH_USING_HISTORY +#define FINSH_HISTORY_LINES 5 +#define FINSH_USING_SYMTAB +#define FINSH_USING_DESCRIPTION +#define FINSH_THREAD_PRIORITY 20 +#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_CMD_SIZE 128 +#define FINSH_USING_MSH +#define FINSH_USING_MSH_DEFAULT +#define FINSH_ARG_MAX 10 + +/* Device virtual file system */ + +#define RT_USING_DFS +#define DFS_USING_WORKDIR +#define DFS_FILESYSTEMS_MAX 2 +#define DFS_FILESYSTEM_TYPES_MAX 2 +#define DFS_FD_MAX 16 +#define RT_USING_DFS_ELMFAT + +/* elm-chan's FatFs, Generic FAT Filesystem Module */ + +#define RT_DFS_ELM_CODE_PAGE 437 +#define RT_DFS_ELM_WORD_ACCESS +#define RT_DFS_ELM_USE_LFN_3 +#define RT_DFS_ELM_USE_LFN 3 +#define RT_DFS_ELM_LFN_UNICODE_0 +#define RT_DFS_ELM_LFN_UNICODE 0 +#define RT_DFS_ELM_MAX_LFN 255 +#define RT_DFS_ELM_DRIVES 2 +#define RT_DFS_ELM_MAX_SECTOR_SIZE 512 +#define RT_DFS_ELM_REENTRANT +#define RT_USING_DFS_DEVFS + +/* Device Drivers */ + +#define RT_USING_DEVICE_IPC +#define RT_PIPE_BUFSZ 512 +#define RT_USING_SERIAL +#define RT_SERIAL_USING_DMA +#define RT_SERIAL_RB_BUFSZ 256 +#define RT_USING_CAN +#define RT_USING_SDIO +#define RT_SDIO_STACK_SIZE 512 +#define RT_SDIO_THREAD_PRIORITY 15 +#define RT_MMCSD_STACK_SIZE 1024 +#define RT_MMCSD_THREAD_PREORITY 22 +#define RT_MMCSD_MAX_PARTITION 16 +#define RT_USING_SPI +#define RT_USING_QSPI +#define RT_USING_SFUD +#define RT_SFUD_USING_SFDP +#define RT_SFUD_USING_FLASH_INFO_TABLE +#define RT_SFUD_USING_QSPI +#define RT_SFUD_SPI_MAX_HZ 50000000 + +/* Using USB */ + + +/* POSIX layer and C standard library */ + +#define RT_LIBC_USING_TIME +#define RT_LIBC_FIXED_TIMEZONE 8 + +/* Network */ + +/* Socket abstraction layer */ + + +/* Network interface device */ + +#define RT_USING_NETDEV +#define NETDEV_USING_IFCONFIG +#define NETDEV_USING_PING +#define NETDEV_USING_NETSTAT +#define NETDEV_USING_AUTO_DEFAULT +#define NETDEV_IPV4 1 +#define NETDEV_IPV6 0 + +/* light weight TCP/IP stack */ + +#define RT_USING_LWIP +#define RT_USING_LWIP212 +#define RT_LWIP_MEM_ALIGNMENT 4 +#define RT_LWIP_IGMP +#define RT_LWIP_ICMP +#define RT_LWIP_DNS + +/* Static IPv4 Address */ + +#define RT_LWIP_IPADDR "192.168.3.20" +#define RT_LWIP_GWADDR "192.168.3.1" +#define RT_LWIP_MSKADDR "255.255.255.0" +#define RT_LWIP_UDP +#define RT_LWIP_TCP +#define RT_LWIP_RAW +#define RT_MEMP_NUM_NETCONN 8 +#define RT_LWIP_PBUF_NUM 16 +#define RT_LWIP_RAW_PCB_NUM 4 +#define RT_LWIP_UDP_PCB_NUM 4 +#define RT_LWIP_TCP_PCB_NUM 4 +#define RT_LWIP_TCP_SEG_NUM 40 +#define RT_LWIP_TCP_SND_BUF 8196 +#define RT_LWIP_TCP_WND 8196 +#define RT_LWIP_TCPTHREAD_PRIORITY 10 +#define RT_LWIP_TCPTHREAD_MBOX_SIZE 8 +#define RT_LWIP_TCPTHREAD_STACKSIZE 1024 +#define RT_LWIP_ETHTHREAD_PRIORITY 12 +#define RT_LWIP_ETHTHREAD_STACKSIZE 1024 +#define RT_LWIP_ETHTHREAD_MBOX_SIZE 8 +#define LWIP_NETIF_STATUS_CALLBACK 1 +#define LWIP_NETIF_LINK_CALLBACK 1 +#define SO_REUSE 1 +#define LWIP_SO_RCVTIMEO 1 +#define LWIP_SO_SNDTIMEO 1 +#define LWIP_SO_RCVBUF 1 +#define LWIP_SO_LINGER 0 +#define LWIP_NETIF_LOOPBACK 0 +#define RT_LWIP_USING_PING + +/* AT commands */ + + +/* VBUS(Virtual Software BUS) */ + + +/* Utilities */ + + +/* RT-Thread Utestcases */ + + +/* RT-Thread online packages */ + +/* IoT - internet of things */ + + +/* Wi-Fi */ + +/* Marvell WiFi */ + + +/* Wiced WiFi */ + + +/* IoT Cloud */ + + +/* security packages */ + + +/* language packages */ + + +/* multimedia packages */ + + +/* tools packages */ + + +/* system packages */ + + +/* Micrium: Micrium software products porting for RT-Thread */ + + +/* peripheral libraries and drivers */ + + +/* AI packages */ + + +/* miscellaneous packages */ + + +/* samples: kernel and components samples */ + + +/* entertainment: terminal games and other interesting software packages */ + +#define FT2004 + +/* Hardware Drivers Config */ + +/* On-chip Peripheral Drivers */ + +#define BSP_USING_UART +#define RT_USING_UART1 +#define BSP_USING_SDC +#define BSP_USING_GMAC +#define BSP_USING_GMAC1 +#define RT_LWIP_ETH_PAD_SIZE 2 +#define BSP_USE_SPI +#define BSP_USE_GPIO +#define BSP_USE_CAN +#define BSP_USING_CAN0 + +/* Board extended module Drivers */ + + +#endif diff --git a/bsp/ft2004/rtconfig.py b/bsp/ft2004/rtconfig.py new file mode 100644 index 0000000000000000000000000000000000000000..b8f889771661ece49ade23687764043ebd4738b9 --- /dev/null +++ b/bsp/ft2004/rtconfig.py @@ -0,0 +1,82 @@ +''' +Author: your name +Date: 2021-03-01 18:57:53 +LastEditTime: 2021-05-18 18:51:53 +LastEditors: Please set LastEditors +Description: In User Settings Edit +FilePath: \rtthread\bsp\ft2004\rtconfig.py +''' +import os + +# header = ''' +# #ifndef __MAC_AUTO_GENERATE_H__ +# #define __MAC_AUTO_GENERATE_H__ + +# /* Automatically generated file; DO NOT EDIT. */ +# /* mac configure file for RT-Thread qemu */ + +# #define AUTOMAC0 0x52 +# #define AUTOMAC1 0x54 +# #define AUTOMAC2 0x00 +# #define AUTOMAC''' + +# end = ''' +# #endif +# ''' + +# toolchains options +ARCH='arm' +CPU='cortex-a' +CROSS_TOOL='gcc' + +if os.getenv('RTT_CC'): + CROSS_TOOL = os.getenv('RTT_CC') + +# only support GNU GCC compiler. +PLATFORM = 'gcc' +EXEC_PATH = '/usr/lib/arm-none-eabi/bin' +if os.getenv('RTT_EXEC_PATH'): + EXEC_PATH = os.getenv('RTT_EXEC_PATH') + +BUILD = 'debug' + +LIBPATH = '/usr/lib/arm-none-eabi/lib' + + +if PLATFORM == 'gcc': + # toolchains + PREFIX = 'arm-none-eabi-' + CC = PREFIX + 'gcc' + CXX = PREFIX + 'g++' + AS = PREFIX + 'gcc' + AR = PREFIX + 'ar' + LINK = PREFIX + 'gcc' + TARGET_EXT = 'elf' + SIZE = PREFIX + 'size' + OBJDUMP = PREFIX + 'objdump' + OBJCPY = PREFIX + 'objcopy' + STRIP = PREFIX + 'strip' + + + DEVICE = ' -march=armv8-a -mfpu=vfpv4-d16 -ftree-vectorize -ffast-math -mfloat-abi=soft --specs=nano.specs --specs=nosys.specs -fno-builtin ' + # DEVICE = ' -march=armv7-a -mfpu=vfpv3-d16 -ftree-vectorize -ffast-math -mfloat-abi=hard' + CFLAGS = DEVICE + ' -Wall' + AFLAGS = ' -c'+ DEVICE + ' -fsingle-precision-constant -fno-builtin -x assembler-with-cpp -D__ASSEMBLY__' + LINK_SCRIPT = 'ft_aarch32.lds' + LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,system_vectors'+\ + ' -T %s' % LINK_SCRIPT + + CPATH = '' + LPATH = LIBPATH + + # generate debug info in all cases + AFLAGS += ' -gdwarf-2' + CFLAGS += ' -g -gdwarf-2' + + if BUILD == 'debug': + CFLAGS += ' -O0' + else: + CFLAGS += ' -O2' + + POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' +\ + SIZE + ' $TARGET \n'