summaryrefslogtreecommitdiff
path: root/bsp/ls2kdev
diff options
context:
space:
mode:
authorcliff-cmc <[email protected]>2021-02-26 11:09:27 +0800
committerCliff Chen <[email protected]>2021-02-26 11:45:19 +0800
commiteea0c3d74a40f73235da45c6f77e8b411ac94cf2 (patch)
treea6906f1aed7118ab53dbe18f2ee4727a754583af /bsp/ls2kdev
parent1a9ecf27f31277750d92c921b62503f75275e122 (diff)
parentfae0fa8eea4c0e797940bf1eddc8ee6c1711734a (diff)
Add memtrace command for memheap.c
Diffstat (limited to 'bsp/ls2kdev')
-rw-r--r--bsp/ls2kdev/.config255
-rw-r--r--bsp/ls2kdev/Kconfig11
-rw-r--r--bsp/ls2kdev/README.md58
-rw-r--r--bsp/ls2kdev/SConstruct4
-rw-r--r--bsp/ls2kdev/applications/main.c4
-rw-r--r--bsp/ls2kdev/applications/mnt.c47
-rw-r--r--bsp/ls2kdev/drivers/SConscript10
-rw-r--r--bsp/ls2kdev/drivers/ata/SConscript14
-rw-r--r--bsp/ls2kdev/drivers/ata/ahci.h281
-rw-r--r--bsp/ls2kdev/drivers/ata/ata_debug.h20
-rw-r--r--bsp/ls2kdev/drivers/ata/ata_interface.h101
-rw-r--r--bsp/ls2kdev/drivers/ata/blk_device.c127
-rw-r--r--bsp/ls2kdev/drivers/ata/blk_device.h48
-rw-r--r--bsp/ls2kdev/drivers/ata/dwc_ahsata.c1234
-rw-r--r--bsp/ls2kdev/drivers/ata/dwc_ahsata.h25
-rw-r--r--bsp/ls2kdev/drivers/ata/dwc_ahsata_priv.h323
-rw-r--r--bsp/ls2kdev/drivers/ata/fis.h152
-rw-r--r--bsp/ls2kdev/drivers/ata/libata.c150
-rw-r--r--bsp/ls2kdev/drivers/ata/libata.h653
-rw-r--r--bsp/ls2kdev/drivers/board.c19
-rw-r--r--bsp/ls2kdev/drivers/board.h4
-rw-r--r--bsp/ls2kdev/drivers/clk.c100
-rw-r--r--bsp/ls2kdev/drivers/clk.h23
-rw-r--r--bsp/ls2kdev/drivers/drv_gpio.c163
-rw-r--r--bsp/ls2kdev/drivers/drv_gpio.h23
-rw-r--r--bsp/ls2kdev/drivers/drv_pwm.c141
-rw-r--r--bsp/ls2kdev/drivers/drv_rtc.c186
-rw-r--r--bsp/ls2kdev/drivers/drv_spi.c231
-rw-r--r--bsp/ls2kdev/drivers/drv_spi.h46
-rw-r--r--bsp/ls2kdev/drivers/drv_uart.c127
-rw-r--r--bsp/ls2kdev/drivers/drv_uart.h151
-rw-r--r--bsp/ls2kdev/drivers/interrupt.c180
-rw-r--r--bsp/ls2kdev/drivers/interrupt.h85
-rw-r--r--bsp/ls2kdev/drivers/ls2k1000.h46
-rw-r--r--bsp/ls2kdev/drivers/net/SConscript16
-rw-r--r--bsp/ls2kdev/drivers/net/mii.c140
-rw-r--r--bsp/ls2kdev/drivers/net/mii.h229
-rw-r--r--bsp/ls2kdev/drivers/net/synopGMAC.c988
-rw-r--r--bsp/ls2kdev/drivers/net/synopGMAC.h23
-rw-r--r--bsp/ls2kdev/drivers/net/synopGMAC_Dev.c3750
-rw-r--r--bsp/ls2kdev/drivers/net/synopGMAC_Dev.h1717
-rw-r--r--bsp/ls2kdev/drivers/net/synopGMAC_Host.h60
-rw-r--r--bsp/ls2kdev/drivers/net/synopGMAC_debug.h22
-rw-r--r--bsp/ls2kdev/drivers/net/synopGMAC_network_interface.h65
-rw-r--r--bsp/ls2kdev/drivers/net/synopGMAC_plat.c133
-rw-r--r--bsp/ls2kdev/drivers/net/synopGMAC_plat.h242
-rw-r--r--bsp/ls2kdev/drivers/net/synopGMAC_types.h23
-rw-r--r--bsp/ls2kdev/drivers/pci/SConscript10
-rw-r--r--bsp/ls2kdev/drivers/pci/pci.c20
-rw-r--r--bsp/ls2kdev/drivers/pci/pci.h42
-rw-r--r--bsp/ls2kdev/ls2k_ram.lds17
-rw-r--r--bsp/ls2kdev/rtconfig.h106
-rw-r--r--bsp/ls2kdev/rtconfig.py3
53 files changed, 12401 insertions, 247 deletions
diff --git a/bsp/ls2kdev/.config b/bsp/ls2kdev/.config
index d8a97b46b0..2d89bcb80b 100644
--- a/bsp/ls2kdev/.config
+++ b/bsp/ls2kdev/.config
@@ -6,20 +6,20 @@
#
# RT-Thread Kernel
#
-CONFIG_RT_NAME_MAX=8
+CONFIG_RT_NAME_MAX=30
# CONFIG_RT_USING_ARCH_DATA_TYPE is not set
# CONFIG_RT_USING_SMP is not set
-CONFIG_RT_ALIGN_SIZE=4
+CONFIG_RT_ALIGN_SIZE=8
# 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_TICK_PER_SECOND=1000
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=2048
+CONFIG_IDLE_THREAD_STACK_SIZE=16384
# CONFIG_RT_USING_TIMER_SOFT is not set
CONFIG_RT_DEBUG=y
# CONFIG_RT_DEBUG_COLOR is not set
@@ -52,6 +52,7 @@ CONFIG_RT_USING_MEMPOOL=y
# CONFIG_RT_USING_NOHEAP is not set
CONFIG_RT_USING_SMALL_MEM=y
# CONFIG_RT_USING_SLAB is not set
+# CONFIG_RT_USING_USERHEAP is not set
# CONFIG_RT_USING_MEMTRACE is not set
CONFIG_RT_USING_HEAP=y
@@ -65,6 +66,7 @@ CONFIG_RT_USING_CONSOLE=y
CONFIG_RT_CONSOLEBUF_SIZE=256
CONFIG_RT_CONSOLE_DEVICE_NAME="uart"
CONFIG_RT_VER_NUM=0x40003
+CONFIG_ARCH_CPU_64BIT=y
# CONFIG_RT_USING_CPU_FFS is not set
CONFIG_ARCH_MIPS64=y
# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set
@@ -74,7 +76,7 @@ CONFIG_ARCH_MIPS64=y
#
CONFIG_RT_USING_COMPONENTS_INIT=y
CONFIG_RT_USING_USER_MAIN=y
-CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048
+CONFIG_RT_MAIN_THREAD_STACK_SIZE=16384
CONFIG_RT_MAIN_THREAD_PRIORITY=10
#
@@ -93,7 +95,7 @@ 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_THREAD_STACK_SIZE=16384
CONFIG_FINSH_CMD_SIZE=80
# CONFIG_FINSH_USING_AUTH is not set
CONFIG_FINSH_USING_MSH=y
@@ -104,14 +106,44 @@ CONFIG_FINSH_ARG_MAX=10
#
# Device virtual file system
#
-# CONFIG_RT_USING_DFS is not set
+CONFIG_RT_USING_DFS=y
+CONFIG_DFS_USING_WORKDIR=y
+CONFIG_DFS_FILESYSTEMS_MAX=10
+CONFIG_DFS_FILESYSTEM_TYPES_MAX=10
+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=936
+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_MAX_LFN=255
+CONFIG_RT_DFS_ELM_DRIVES=9
+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_UFFS is not set
+# CONFIG_RT_USING_DFS_JFFS2 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_SYSTEM_WORKQUEUE=y
+CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=16384
+CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=5
CONFIG_RT_USING_SERIAL=y
CONFIG_RT_SERIAL_USING_DMA=y
CONFIG_RT_SERIAL_RB_BUFSZ=64
@@ -119,15 +151,22 @@ CONFIG_RT_SERIAL_RB_BUFSZ=64
# CONFIG_RT_USING_HWTIMER is not set
# CONFIG_RT_USING_CPUTIME is not set
# CONFIG_RT_USING_I2C is not set
+# CONFIG_RT_USING_PHY is not set
CONFIG_RT_USING_PIN=y
# CONFIG_RT_USING_ADC is not set
+# CONFIG_RT_USING_DAC is not set
# CONFIG_RT_USING_PWM is not set
# CONFIG_RT_USING_MTD_NOR is not set
# CONFIG_RT_USING_MTD_NAND is not set
# CONFIG_RT_USING_PM is not set
# CONFIG_RT_USING_RTC is not set
# CONFIG_RT_USING_SDIO is not set
-# CONFIG_RT_USING_SPI is not set
+CONFIG_RT_USING_SPI=y
+# CONFIG_RT_USING_QSPI is not set
+# CONFIG_RT_USING_SPI_MSD is not set
+# CONFIG_RT_USING_SFUD is not set
+# CONFIG_RT_USING_ENC28J60 is not set
+# CONFIG_RT_USING_SPI_WIFI is not set
# CONFIG_RT_USING_WDT is not set
# CONFIG_RT_USING_AUDIO is not set
# CONFIG_RT_USING_SENSOR is not set
@@ -148,6 +187,11 @@ CONFIG_RT_USING_PIN=y
#
CONFIG_RT_USING_LIBC=y
# CONFIG_RT_USING_PTHREADS is not set
+CONFIG_RT_USING_POSIX=y
+# CONFIG_RT_USING_POSIX_MMAP is not set
+# CONFIG_RT_USING_POSIX_TERMIOS is not set
+# CONFIG_RT_USING_POSIX_GETLINE is not set
+# CONFIG_RT_USING_POSIX_AIO is not set
# CONFIG_RT_USING_MODULE is not set
#
@@ -157,22 +201,91 @@ CONFIG_RT_USING_LIBC=y
#
# Socket abstraction layer
#
-# CONFIG_RT_USING_SAL is not set
+CONFIG_RT_USING_SAL=y
+
+#
+# protocol stack implement
+#
+CONFIG_SAL_USING_LWIP=y
+# CONFIG_SAL_USING_POSIX is not set
+CONFIG_SAL_SOCKETS_NUM=16
#
# Network interface device
#
-# CONFIG_RT_USING_NETDEV is not set
+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 is not set
+CONFIG_RT_USING_LWIP=y
+# CONFIG_RT_USING_LWIP141 is not set
+CONFIG_RT_USING_LWIP202=y
+# CONFIG_RT_USING_LWIP212 is not set
+# CONFIG_RT_USING_LWIP_IPV6 is not set
+CONFIG_RT_LWIP_MEM_ALIGNMENT=8
+CONFIG_RT_LWIP_IGMP=y
+CONFIG_RT_LWIP_ICMP=y
+CONFIG_RT_LWIP_SNMP=y
+CONFIG_RT_LWIP_DNS=y
+CONFIG_RT_LWIP_DHCP=y
+CONFIG_IP_SOF_BROADCAST=1
+CONFIG_IP_SOF_BROADCAST_RECV=1
+
+#
+# Static IPv4 Address
+#
+CONFIG_RT_LWIP_IPADDR="192.168.1.30"
+CONFIG_RT_LWIP_GWADDR="192.168.1.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=5
+CONFIG_RT_LWIP_TCPTHREAD_MBOX_SIZE=32
+CONFIG_RT_LWIP_TCPTHREAD_STACKSIZE=16384
+# CONFIG_LWIP_NO_RX_THREAD is not set
+# CONFIG_LWIP_NO_TX_THREAD is not set
+CONFIG_RT_LWIP_ETHTHREAD_PRIORITY=5
+CONFIG_RT_LWIP_ETHTHREAD_STACKSIZE=16384
+CONFIG_RT_LWIP_ETHTHREAD_MBOX_SIZE=32
+CONFIG_RT_LWIP_REASSEMBLY_FRAG=y
+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=y
+# 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)
@@ -198,11 +311,15 @@ CONFIG_RT_USING_LIBC=y
#
# 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
@@ -229,6 +346,7 @@ CONFIG_RT_USING_LIBC=y
# 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
@@ -241,8 +359,10 @@ CONFIG_RT_USING_LIBC=y
# 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_IOTHUB 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
@@ -257,6 +377,16 @@ CONFIG_RT_USING_LIBC=y
# 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
#
# security packages
@@ -264,6 +394,8 @@ CONFIG_RT_USING_LIBC=y
# 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
@@ -280,6 +412,9 @@ CONFIG_RT_USING_LIBC=y
# CONFIG_PKG_USING_STEMWIN is not set
# CONFIG_PKG_USING_WAVPLAYER is not set
# CONFIG_PKG_USING_TJPGD 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
@@ -294,10 +429,18 @@ CONFIG_RT_USING_LIBC=y
# 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
#
# system packages
@@ -306,8 +449,11 @@ CONFIG_RT_USING_LIBC=y
# CONFIG_PKG_USING_CAIRO is not set
# CONFIG_PKG_USING_PIXMAN is not set
# CONFIG_PKG_USING_LWEXT4 is not set
+# CONFIG_PKG_USING_LWEXT4_LATEST_VERSION is not set
+# CONFIG_PKG_USING_LWEXT4_V100 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
@@ -317,6 +463,24 @@ CONFIG_RT_USING_LIBC=y
# 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
#
# peripheral libraries and drivers
@@ -333,6 +497,10 @@ CONFIG_RT_USING_LIBC=y
# 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
@@ -349,6 +517,30 @@ CONFIG_RT_USING_LIBC=y
# 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
#
# miscellaneous packages
@@ -358,6 +550,7 @@ CONFIG_RT_USING_LIBC=y
# 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
@@ -378,6 +571,7 @@ CONFIG_RT_USING_LIBC=y
# 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_NNOM is not set
# CONFIG_PKG_USING_LIBANN is not set
# CONFIG_PKG_USING_ELAPACK is not set
@@ -385,34 +579,15 @@ CONFIG_RT_USING_LIBC=y
# CONFIG_PKG_USING_VT100 is not set
# CONFIG_PKG_USING_ULAPACK is not set
# CONFIG_PKG_USING_UKAL is not set
+# CONFIG_PKG_USING_CRCLIB is not set
#
-# Privated Packages of RealThread
+# games: games run on RT-Thread console
#
-# CONFIG_PKG_USING_CODEC is not set
-# CONFIG_PKG_USING_PLAYER is not set
-# CONFIG_PKG_USING_MPLAYER is not set
-# CONFIG_PKG_USING_PERSIMMON_SRC is not set
-# CONFIG_PKG_USING_JS_PERSIMMON is not set
-# CONFIG_PKG_USING_JERRYSCRIPT_WIN32 is not set
-
-#
-# Network Utilities
-#
-# CONFIG_PKG_USING_WICED is not set
-# CONFIG_PKG_USING_CLOUDSDK is not set
-# CONFIG_PKG_USING_POWER_MANAGER is not set
-# CONFIG_PKG_USING_RT_OTA is not set
-# CONFIG_PKG_USING_RDBD_SRC is not set
-# CONFIG_PKG_USING_RTINSIGHT is not set
-# CONFIG_PKG_USING_SMARTCONFIG is not set
-# CONFIG_PKG_USING_RTX is not set
-# CONFIG_RT_USING_TESTCASE is not set
-# CONFIG_PKG_USING_NGHTTP2 is not set
-# CONFIG_PKG_USING_AVS is not set
-# CONFIG_PKG_USING_JOYLINK is not set
-# CONFIG_PKG_USING_STS is not set
-# CONFIG_PKG_USING_DLMS is not set
-# CONFIG_PKG_USING_AUDIO_FRAMEWORK is not set
-# CONFIG_PKG_USING_ZBAR is not set
+# CONFIG_PKG_USING_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_LWGPS is not set
+# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set
CONFIG_SOC_LS2K1000=y
diff --git a/bsp/ls2kdev/Kconfig b/bsp/ls2kdev/Kconfig
index 5cfb6892ff..fc2dfe1328 100644
--- a/bsp/ls2kdev/Kconfig
+++ b/bsp/ls2kdev/Kconfig
@@ -29,4 +29,13 @@ config SOC_LS2K1000
select RT_USING_USER_MAIN
select RT_USING_DEVICE
default y
- \ No newline at end of file
+
+if RT_USING_SERIAL
+config RT_USING_UART0
+ bool "Using RT_USING_UART0"
+ default y
+
+config RT_USING_UART4
+ bool "Using RT_USING_UART4"
+ default y
+endif
diff --git a/bsp/ls2kdev/README.md b/bsp/ls2kdev/README.md
index 783f4b2d41..08a7dec063 100644
--- a/bsp/ls2kdev/README.md
+++ b/bsp/ls2kdev/README.md
@@ -84,17 +84,67 @@ Hi, this is RT-Thread!!
msh >
```
-## 4. 支持情况
+## 4.开机自动启动
+
+在调试阶段,可以利用脚本,在pmon阶段从TFTP服务器上获取固件,然后引导启动。这样可以节省开发配置的时间。具体的步骤如下:
+
+**第一步:**
+设置开发板的IP地址,在进入pmon的控制台后,输入`set ifconfig syn0:10.1.1.100`。其中`syn0`后面的ip地址为开发板的ip地址,与存放rt-thread固件的TFTP的服务器IP地址在**同一网段**。
+
+**第二步:**
+
+进入龙芯的Debian系统,用管理员权限进入,输入用户名`root`,密码`loongson`。并且修改boot分区下的boot.cfg文件。增加如下:
+
+```
+title TFTPBOOT
+ kernel tftp://10.1.1.118/rtthread.elf
+ args console=tty root=/dev/sda2
+ initrd (wd0,0)/initrd.img
+```
+
+其中`tftp://10.1.1.118/rtthread.elf`中的`10.1.1.118`为tftp服务器的ip地址。
+
+**第三步:**
+
+电脑开启TFTP服务器,将路径指向存放有ls2k的rt-thread固件的目录下。
+
+以上三步完成之后,重启系统,就可以省略每次都需要进入pmon的输入命令的麻烦,板子上电后,可以自动从系统TFTP服务器中获取固件,然后启动,大大提高调试代码效率。
+
+## 5.SATA接口的SSD文件系统支持
+
+当前已经支持SATA接口的SSD文件系统驱动,需要通过menuconfig
+
+```
+RT-Thread online packages --->
+ system packages --->
+ lwext4: an excellent choice of ext2/3/4 filesystem for microcontrollers
+```
+
+然后输入下面的命令更新软件包
+
+```
+pkgs --update
+```
+
+输入`scons`编译代码即可使用SATA接口的SSD文件系统。
+
+## 6. 支持情况
| 驱动 | 支持情况 | 备注 |
| ------ | ---- | :------: |
-| UART | 支持 | UART0|
+| UART | 支持 | UART0\UART4,波特率可调 |
+| GPIO | 支持 | - |
+| PWM | 支持 | - |
+| GMAC | 支持 | 网卡驱动 |
+| RTC | 支持 | - |
+| SPI | 支持 | - |
+| SATA SSD | 支持 | 需要打开lwext4软件包 |
-## 5. 联系人信息
+## 7. 联系人信息
维护人:[bernard][4]
[1]: http://ftp.loongnix.org/loongsonpi/pi_2/doc
[2]: https://pan.baidu.com/s/17dbdOE4NAJ-qEW7drVRq2w
[3]: http://ftp.loongnix.org/embedd/ls2k/
-[4]: https://github.com/BernardXiong
+[4]: https://github.com/BernardXiong \ No newline at end of file
diff --git a/bsp/ls2kdev/SConstruct b/bsp/ls2kdev/SConstruct
index 69373ed71f..66b5ae8603 100644
--- a/bsp/ls2kdev/SConstruct
+++ b/bsp/ls2kdev/SConstruct
@@ -9,15 +9,15 @@ from building import *
TARGET = 'rtthread.' + rtconfig.TARGET_EXT
-rtconfig.AFLAGS += ' -I' + str(Dir('#')) + ' -I ' + RTT_ROOT + '/libcpu/mips/common/'
-
DefaultEnvironment(tools=[])
env = Environment(tools = ['mingw'],
AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS,
+ CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS,
AR = rtconfig.AR, ARFLAGS = '-rc',
LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS)
env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
+env['ASCOM'] = env['ASPPCOM']
Export('RTT_ROOT')
Export('rtconfig')
diff --git a/bsp/ls2kdev/applications/main.c b/bsp/ls2kdev/applications/main.c
index bd975f4825..053e741bfa 100644
--- a/bsp/ls2kdev/applications/main.c
+++ b/bsp/ls2kdev/applications/main.c
@@ -10,8 +10,8 @@
#include <rtthread.h>
-int main(int argc, char** argv)
-{
+int main(int argc, char **argv)
+{
rt_kprintf("Hi, this is RT-Thread!!\n");
return 0;
}
diff --git a/bsp/ls2kdev/applications/mnt.c b/bsp/ls2kdev/applications/mnt.c
new file mode 100644
index 0000000000..1c9b9b047a
--- /dev/null
+++ b/bsp/ls2kdev/applications/mnt.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2020-12-29 bigmagic first version
+ */
+#include <rthw.h>
+#include <rtthread.h>
+
+#ifdef PKG_USING_LWEXT4
+
+#include <dfs.h>
+#include <dfs_fs.h>
+#include <dfs_file.h>
+#include <ext4.h>
+#include <ext4_debug.h>
+#include <blk_device.h>
+#include <stdint.h>
+#include <pci.h>
+
+#define EXT4_DEBUG_ALL (0xFFFFFFFF)
+#define EXT4_DEBUG_NO (0)
+
+int mount_ssd(void)
+{
+ struct blk_device *blkdev = (struct blk_device *)rt_device_find("dwc_ahsata_blk");
+
+ if(blkdev == RT_NULL)
+ {
+ rt_kprintf("dwc_ahsata_blk not found!\n");
+ return;
+ }
+
+ ext4_dmask_set(EXT4_DEBUG_NO);
+ blk_device_init(blkdev);
+ dfs_mount("dwc_ahsata_blk","/","ext",0,(void *)1);
+ dfs_mount("dwc_ahsata_blk","/boot","ext",0,(void *)0);
+
+ return 0;
+}
+
+INIT_ENV_EXPORT(mount_ssd);
+
+#endif
diff --git a/bsp/ls2kdev/drivers/SConscript b/bsp/ls2kdev/drivers/SConscript
index d5542b768f..33310b6d7e 100644
--- a/bsp/ls2kdev/drivers/SConscript
+++ b/bsp/ls2kdev/drivers/SConscript
@@ -7,4 +7,14 @@ CPPPATH = [cwd]
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
+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'))
+
+group = group + objs
+
Return('group')
diff --git a/bsp/ls2kdev/drivers/ata/SConscript b/bsp/ls2kdev/drivers/ata/SConscript
new file mode 100644
index 0000000000..164023bd1f
--- /dev/null
+++ b/bsp/ls2kdev/drivers/ata/SConscript
@@ -0,0 +1,14 @@
+from building import *
+
+cwd = GetCurrentDir()
+src = Glob('*.c')
+
+CPPPATH = [cwd]
+
+if GetDepend('RT_USING_DFS_ELMFAT') == False:
+ SrcRemove(src, 'dwc_ahsata.c')
+ SrcRemove(src, 'libata.c')
+
+group = DefineGroup('Drivers', src, depend = ['PKG_USING_LWEXT4'], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/ls2kdev/drivers/ata/ahci.h b/bsp/ls2kdev/drivers/ata/ahci.h
new file mode 100644
index 0000000000..bccec2c379
--- /dev/null
+++ b/bsp/ls2kdev/drivers/ata/ahci.h
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2020-08-19 lizhirui porting to ls2k
+ */
+
+#ifndef _AHCI_H_
+#define _AHCI_H_
+
+#define AHCI_PCI_BAR 0x24
+#define AHCI_MAX_SG 56 /* hardware max is 64K */
+#define AHCI_CMD_SLOT_SZ 32
+#define AHCI_MAX_CMD_SLOT 32
+#define AHCI_RX_FIS_SZ 256
+#define AHCI_CMD_TBL_HDR 0x80
+#define AHCI_CMD_TBL_CDB 0x40
+#define AHCI_CMD_TBL_SZ AHCI_CMD_TBL_HDR + (AHCI_MAX_SG * 16)
+#define AHCI_PORT_PRIV_DMA_SZ (AHCI_CMD_SLOT_SZ * AHCI_MAX_CMD_SLOT + \
+ AHCI_CMD_TBL_SZ + AHCI_RX_FIS_SZ)
+#define AHCI_CMD_ATAPI (1 << 5)
+#define AHCI_CMD_WRITE (1 << 6)
+#define AHCI_CMD_PREFETCH (1 << 7)
+#define AHCI_CMD_RESET (1 << 8)
+#define AHCI_CMD_CLR_BUSY (1 << 10)
+
+#define RX_FIS_D2H_REG 0x40 /* offset of D2H Register FIS data */
+
+/* Global controller registers */
+#define HOST_CAP 0x00 /* host capabilities */
+#define HOST_CTL 0x04 /* global host control */
+#define HOST_IRQ_STAT 0x08 /* interrupt status */
+#define HOST_PORTS_IMPL 0x0c /* bitmap of implemented ports */
+#define HOST_VERSION 0x10 /* AHCI spec. version compliancy */
+#define HOST_CAP2 0x24 /* host capabilities, extended */
+
+/* HOST_CTL bits */
+#define HOST_RESET (1 << 0) /* reset controller; self-clear */
+#define HOST_IRQ_EN (1 << 1) /* global IRQ enable */
+#define HOST_AHCI_EN (1 << 31) /* AHCI enabled */
+
+/* Registers for each SATA port */
+#define PORT_LST_ADDR 0x00 /* command list DMA addr */
+#define PORT_LST_ADDR_HI 0x04 /* command list DMA addr hi */
+#define PORT_FIS_ADDR 0x08 /* FIS rx buf addr */
+#define PORT_FIS_ADDR_HI 0x0c /* FIS rx buf addr hi */
+#define PORT_IRQ_STAT 0x10 /* interrupt status */
+#define PORT_IRQ_MASK 0x14 /* interrupt enable/disable mask */
+#define PORT_CMD 0x18 /* port command */
+#define PORT_TFDATA 0x20 /* taskfile data */
+#define PORT_SIG 0x24 /* device TF signature */
+#define PORT_CMD_ISSUE 0x38 /* command issue */
+#define PORT_SCR 0x28 /* SATA phy register block */
+#define PORT_SCR_STAT 0x28 /* SATA phy register: SStatus */
+#define PORT_SCR_CTL 0x2c /* SATA phy register: SControl */
+#define PORT_SCR_ERR 0x30 /* SATA phy register: SError */
+#define PORT_SCR_ACT 0x34 /* SATA phy register: SActive */
+
+#ifdef CONFIG_SUNXI_AHCI
+#define PORT_P0DMACR 0x70 /* SUNXI specific "DMA register" */
+#endif
+
+/* PORT_IRQ_{STAT,MASK} bits */
+#define PORT_IRQ_COLD_PRES (1 << 31) /* cold presence detect */
+#define PORT_IRQ_TF_ERR (1 << 30) /* task file error */
+#define PORT_IRQ_HBUS_ERR (1 << 29) /* host bus fatal error */
+#define PORT_IRQ_HBUS_DATA_ERR (1 << 28) /* host bus data error */
+#define PORT_IRQ_IF_ERR (1 << 27) /* interface fatal error */
+#define PORT_IRQ_IF_NONFATAL (1 << 26) /* interface non-fatal error */
+#define PORT_IRQ_OVERFLOW (1 << 24) /* xfer exhausted available S/G */
+#define PORT_IRQ_BAD_PMP (1 << 23) /* incorrect port multiplier */
+
+#define PORT_IRQ_PHYRDY (1 << 22) /* PhyRdy changed */
+#define PORT_IRQ_DEV_ILCK (1 << 7) /* device interlock */
+#define PORT_IRQ_CONNECT (1 << 6) /* port connect change status */
+#define PORT_IRQ_SG_DONE (1 << 5) /* descriptor processed */
+#define PORT_IRQ_UNK_FIS (1 << 4) /* unknown FIS rx'd */
+#define PORT_IRQ_SDB_FIS (1 << 3) /* Set Device Bits FIS rx'd */
+#define PORT_IRQ_DMAS_FIS (1 << 2) /* DMA Setup FIS rx'd */
+#define PORT_IRQ_PIOS_FIS (1 << 1) /* PIO Setup FIS rx'd */
+#define PORT_IRQ_D2H_REG_FIS (1 << 0) /* D2H Register FIS rx'd */
+
+#define PORT_IRQ_FATAL PORT_IRQ_TF_ERR | PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR | PORT_IRQ_IF_ERR
+
+#define DEF_PORT_IRQ PORT_IRQ_FATAL | PORT_IRQ_PHYRDY | PORT_IRQ_CONNECT | PORT_IRQ_SG_DONE | PORT_IRQ_UNK_FIS | PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS | PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS
+
+/* PORT_SCR_STAT bits */
+#define PORT_SCR_STAT_DET_MASK 0x3
+#define PORT_SCR_STAT_DET_COMINIT 0x1
+#define PORT_SCR_STAT_DET_PHYRDY 0x3
+
+/* PORT_CMD bits */
+#define PORT_CMD_ATAPI (1 << 24) /* Device is ATAPI */
+#define PORT_CMD_LIST_ON (1 << 15) /* cmd list DMA engine running */
+#define PORT_CMD_FIS_ON (1 << 14) /* FIS DMA engine running */
+#define PORT_CMD_FIS_RX (1 << 4) /* Enable FIS receive DMA engine */
+#define PORT_CMD_CLO (1 << 3) /* Command list override */
+#define PORT_CMD_POWER_ON (1 << 2) /* Power up device */
+#define PORT_CMD_SPIN_UP (1 << 1) /* Spin up device */
+#define PORT_CMD_START (1 << 0) /* Enable port DMA engine */
+
+#define PORT_CMD_ICC_ACTIVE (0x1 << 28) /* Put i/f in active state */
+#define PORT_CMD_ICC_PARTIAL (0x2 << 28) /* Put i/f in partial state */
+#define PORT_CMD_ICC_SLUMBER (0x6 << 28) /* Put i/f in slumber state */
+
+#define AHCI_MAX_PORTS 32
+
+#define ATA_FLAG_SATA (1 << 3)
+#define ATA_FLAG_NO_LEGACY (1 << 4) /* no legacy mode check */
+#define ATA_FLAG_MMIO (1 << 6) /* use MMIO, not PIO */
+#define ATA_FLAG_SATA_RESET (1 << 7) /* (obsolete) use COMRESET */
+#define ATA_FLAG_PIO_DMA (1 << 8) /* PIO cmds via DMA */
+#define ATA_FLAG_NO_ATAPI (1 << 11) /* No ATAPI support */
+
+struct ahci_cmd_hdr
+{
+ u32 opts;
+ u32 status;
+ u64 tbl_addr;
+ //u32 tbl_addr_hi;
+ u32 reserved[4];
+};
+
+struct ahci_sg
+{
+ u64 addr;
+ //u32 addr_hi;
+ u32 reserved;
+ u32 flags_size;
+};
+
+struct ahci_ioports
+{
+ void __iomem *port_mmio;
+ struct ahci_cmd_hdr *cmd_slot;
+ struct ahci_sg *cmd_tbl_sg;
+ ulong cmd_tbl;
+ u32 rx_fis;
+};
+
+/**
+ * struct ahci_uc_priv - information about an AHCI controller
+ *
+ * When driver model is used, this is accessible using dev_get_uclass_priv(dev)
+ * where dev is the controller (although at present it sometimes stands alone).
+ */
+struct ahci_uc_priv
+{
+ struct rt_device parent;
+ struct ahci_ioports port[AHCI_MAX_PORTS];
+ u16 *ataid[AHCI_MAX_PORTS];
+ u32 n_ports;
+ u32 hard_port_no;
+ u32 host_flags;
+ u32 host_set_flags;
+ void *mmio_base;
+ u32 pio_mask;
+ u32 udma_mask;
+ u32 flags;
+ u32 cap; /* cache of HOST_CAP register */
+ u32 port_map; /* cache of HOST_PORTS_IMPL reg */
+ u32 link_port_map; /*linkup port map*/
+};
+
+struct ahci_ops
+{
+ /**
+ * reset() - reset the controller
+ *
+ * @dev: Controller to reset
+ * @return 0 if OK, -ve on error
+ */
+ int (*reset)(struct rt_device *dev);
+
+ /**
+ * port_status() - get the status of a SATA port
+ *
+ * @dev: Controller to reset
+ * @port: Port number to check (0 for first)
+ * @return 0 if detected, -ENXIO if nothing on port, other -ve on error
+ */
+ int (*port_status)(struct rt_device *dev, int port);
+
+ /**
+ * scan() - scan SATA ports
+ *
+ * @dev: Controller to scan
+ * @return 0 if OK, -ve on error
+ */
+ int (*scan)(struct rt_device *dev);
+};
+
+#define ahci_get_ops(dev) ((struct ahci_ops *)(dev)->driver->ops)
+
+/**
+ * sata_reset() - reset the controller
+ *
+ * @dev: Controller to reset
+ * @return 0 if OK, -ve on error
+ */
+int sata_reset(struct rt_device *dev);
+
+/**
+ * sata_port_status() - get the status of a SATA port
+ *
+ * @dev: Controller to reset
+ * @port: Port number to check (0 for first)
+ * @return 0 if detected, -ENXIO if nothin on port, other -ve on error
+ */
+int sata_dm_port_status(struct rt_device *dev, int port);
+
+/**
+ * sata_scan() - scan SATA ports
+ *
+ * @dev: Controller to scan
+ * @return 0 if OK, -ve on error
+ */
+int sata_scan(struct rt_device *dev);
+
+int ahci_init(void __iomem *base);
+int ahci_reset(void __iomem *base);
+
+/**
+ * ahci_init_one_dm() - set up a single AHCI port
+ *
+ * @dev: Controller to init
+ */
+int ahci_init_one_dm(struct rt_device *dev);
+
+/**
+ * ahci_start_ports_dm() - start all AHCI ports for a controller
+ *
+ * @dev: Controller containing ports to start
+ */
+int ahci_start_ports_dm(struct rt_device *dev);
+
+/**
+ * ahci_init_dm() - init AHCI for a controller, finding all ports
+ *
+ * @dev: Device to init
+ */
+int ahci_init_dm(struct rt_device *dev, void __iomem *base);
+
+/**
+ * ahci_bind_scsi() - bind a new SCSI bus as a child
+ *
+ * Note that the SCSI bus device will itself bind block devices
+ *
+ * @ahci_dev: AHCI parent device
+ * @devp: Returns new SCSI bus device
+ * @return 0 if OK, -ve on error
+ */
+int ahci_bind_scsi(struct rt_device *ahci_dev, struct rt_device **devp);
+
+/**
+ * ahci_probe_scsi() - probe and scan the attached SCSI bus
+ *
+ * Note that the SCSI device will itself bind block devices for any storage
+ * devices it finds.
+ *
+ * @ahci_dev: AHCI parent device
+ * @base: Base address of AHCI port
+ * @return 0 if OK, -ve on error
+ */
+int ahci_probe_scsi(struct rt_device *ahci_dev, ulong base);
+
+/**
+ * ahci_probe_scsi_pci() - probe and scan the attached SCSI bus on PCI
+ *
+ * Note that the SCSI device will itself bind block devices for any storage
+ * devices it finds.
+ *
+ * @ahci_dev: AHCI parent device
+ * @return 0 if OK, -ve on error
+ */
+int ahci_probe_scsi_pci(struct rt_device *ahci_dev);
+
+#endif
diff --git a/bsp/ls2kdev/drivers/ata/ata_debug.h b/bsp/ls2kdev/drivers/ata/ata_debug.h
new file mode 100644
index 0000000000..cf628d73ea
--- /dev/null
+++ b/bsp/ls2kdev/drivers/ata/ata_debug.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2020-08-19 lizhirui first version
+ */
+
+#ifndef __ATA_DEBUG_H__
+#define __ATA_DEBUG_H__
+//#define ATA_DEBUG
+#include <rtthread.h>
+#ifdef ATA_DEBUG
+#define debug rt_kprintf
+#else
+#define debug(...)
+#endif
+#endif
diff --git a/bsp/ls2kdev/drivers/ata/ata_interface.h b/bsp/ls2kdev/drivers/ata/ata_interface.h
new file mode 100644
index 0000000000..fc7fb5cbe6
--- /dev/null
+++ b/bsp/ls2kdev/drivers/ata/ata_interface.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2020-08-19 lizhirui first version
+ */
+
+#ifndef __ATA_INTERFACE_H__
+#define __ATA_INTERFACE_H__
+
+typedef rt_uint8_t u8;
+typedef rt_uint16_t u16;
+typedef rt_uint32_t u32;
+typedef rt_uint64_t u64;
+typedef rt_uint64_t ulong;
+
+typedef rt_int8_t s8;
+typedef rt_int16_t s16;
+typedef rt_int32_t s32;
+typedef rt_int64_t s64;
+
+typedef rt_size_t lbaint_t;
+
+#define __iomem
+#define mdelay rt_thread_mdelay
+#define udelay(...) rt_thread_mdelay(1)
+
+#define cpu_to_le32
+#define cpu_to_le16
+#define le32_to_cpu
+#define le16_to_cpu
+
+#define flush_cache(...)
+#define invalidate_dcache_range(...)
+
+#define ARCH_DMA_MINALIGN 1024
+
+#define CONFIG_IS_ENABLED
+#define AHCI 1
+
+#define VADDR_TO_PHY(vaddr) (((u64)vaddr) - KSEG0BASE)
+#define LOW_PHY(vaddr) ((u32)VADDR_TO_PHY(vaddr))
+#define HIGH_PHY(vaddr) ((u32)((VADDR_TO_PHY(vaddr)) >> 32))
+
+#define ALIGN_1(x, a) __ALIGN_MASK((x), (typeof(x))(a)-1)
+#define ALIGN_DOWN(x, a) ALIGN_1((x) - ((a)-1), (a))
+#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
+#define PTR_ALIGN(p, a) ((typeof(p))ALIGN((unsigned long)(p), (a)))
+#define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a)-1)) == 0)
+
+#define ROUND(a, b) (((a) + (b)-1) & ~((b)-1))
+
+#define PAD_COUNT(s, pad) (((s)-1) / (pad) + 1)
+#define PAD_SIZE(s, pad) (PAD_COUNT(s, pad) * pad)
+#define ALLOC_ALIGN_BUFFER_PAD(type, name, size, align, pad) \
+ char __##name[ROUND(PAD_SIZE((size) * sizeof(type), pad), align) + (align - 1)]; \
+ \
+ type *name = (type *)ALIGN_1((rt_ubase_t)__##name, align)
+#define ALLOC_ALIGN_BUFFER(type, name, size, align) \
+ ALLOC_ALIGN_BUFFER_PAD(type, name, size, align, 1)
+#define ALLOC_CACHE_ALIGN_BUFFER_PAD(type, name, size, pad) \
+ ALLOC_ALIGN_BUFFER_PAD(type, name, size, ARCH_DMA_MINALIGN, pad)
+#define ALLOC_CACHE_ALIGN_BUFFER(type, name, size) \
+ ALLOC_ALIGN_BUFFER(type, name, size, ARCH_DMA_MINALIGN)
+
+static inline u32 readl(void *addr)
+{
+ return *((u32 *)addr);
+}
+
+static inline void writel(u32 data, void *addr)
+{
+ *((u32 *)addr) = data;
+}
+
+static inline int ffs(int word)
+{
+ int r;
+
+ if (word == 0)
+ {
+ return 0;
+ }
+
+ word &= (-word);
+
+ __asm__("clz %0, %1"
+ : "=r"(r)
+ : "r"(word));
+ return 32 - r;
+}
+
+static inline void setbits_le32(u32 *addr, u32 value)
+{
+ *addr = value;
+}
+
+#endif
diff --git a/bsp/ls2kdev/drivers/ata/blk_device.c b/bsp/ls2kdev/drivers/ata/blk_device.c
new file mode 100644
index 0000000000..c6ed880988
--- /dev/null
+++ b/bsp/ls2kdev/drivers/ata/blk_device.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2020-08-19 lizhirui first version
+ */
+
+#include <rtthread.h>
+#include <rtdef.h>
+#include <dfs.h>
+#include <dfs_fs.h>
+#include <dfs_file.h>
+#include <ext4.h>
+#include <ext4_debug.h>
+#include <blk_device.h>
+#include <stdint.h>
+
+static struct blk_device *blkdev;
+static rt_uint32_t disk_sector_size;
+
+static int blockdev_open(struct ext4_blockdev *bdev)
+{
+ int r;
+ uint32_t size;
+ rt_device_t device = (rt_device_t)blkdev;
+ struct rt_device_blk_geometry geometry;
+
+ RT_ASSERT(device);
+
+ r = rt_device_open((rt_device_t)blkdev, RT_DEVICE_OFLAG_RDWR);
+
+ if (r != RT_EOK)
+ {
+ return r;
+ }
+
+ r = rt_device_control(device, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry);
+
+ if (RT_EOK == r)
+ {
+ bdev->part_offset = 0;
+ bdev->part_size = geometry.sector_count * geometry.bytes_per_sector;
+ disk_sector_size = geometry.bytes_per_sector;
+ bdev->bdif->ph_bcnt = bdev->part_size / bdev->bdif->ph_bsize;
+ }
+
+ return r;
+}
+
+static int blockdev_bread(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id,
+ uint32_t blk_cnt)
+{
+ int result;
+ rt_device_t device = (rt_device_t)blkdev;
+ struct blk_device *blk = (struct blk_device *)device;
+ RT_ASSERT(device);
+
+ result = rt_device_read(device, blk_id * (bdev->bdif->ph_bsize / disk_sector_size),
+ buf, blk_cnt * (bdev->bdif->ph_bsize / disk_sector_size));
+
+ if ((blk_cnt * (bdev->bdif->ph_bsize / disk_sector_size)) == result)
+ {
+ result = 0;
+ }
+ else
+ {
+ result = -EIO;
+ }
+
+ return result;
+}
+
+static int blockdev_bwrite(struct ext4_blockdev *bdev, const void *buf,
+ uint64_t blk_id, uint32_t blk_cnt)
+{
+ int result;
+ rt_device_t device = (rt_device_t)blkdev;
+
+ RT_ASSERT(device);
+
+ result = rt_device_write(device, blk_id * (bdev->bdif->ph_bsize / disk_sector_size),
+ buf, blk_cnt * (bdev->bdif->ph_bsize / disk_sector_size));
+
+ if ((blk_cnt * (bdev->bdif->ph_bsize / disk_sector_size)) == result)
+ {
+ result = 0;
+ }
+ else
+ {
+ result = -EIO;
+ }
+
+ return result;
+}
+
+static int blockdev_close(struct ext4_blockdev *bdev)
+{
+ return rt_device_close((rt_device_t)blkdev);
+}
+
+static int blockdev_lock(struct ext4_blockdev *bdev)
+{
+ return 0;
+}
+
+static int blockdev_unlock(struct ext4_blockdev *bdev)
+{
+ return 0;
+}
+
+EXT4_BLOCKDEV_STATIC_INSTANCE(bdev, 4096, 0, blockdev_open,
+ blockdev_bread, blockdev_bwrite, blockdev_close,
+ blockdev_lock, blockdev_unlock);
+
+void blk_device_init(struct blk_device *blk_devices)
+{
+ blkdev = blk_devices;
+
+ if (ext4_mbr_scan(&bdev, &(blkdev->ext4_partition)) != EOK)
+ {
+ rt_kprintf("MBR scan failed!\n");
+ return;
+ }
+}
diff --git a/bsp/ls2kdev/drivers/ata/blk_device.h b/bsp/ls2kdev/drivers/ata/blk_device.h
new file mode 100644
index 0000000000..8401e8aac6
--- /dev/null
+++ b/bsp/ls2kdev/drivers/ata/blk_device.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2020-08-19 lizhirui first version
+ */
+
+#ifndef __BLK_DEVICE_H__
+#define __BLK_DEVICE_H__
+
+#include <rtconfig.h>
+#include <ext4_mbr.h>
+
+#define DEV_TYPE_UNKNOWN 0xff /* not connected */
+#define DEV_TYPE_HARDDISK 0x00 /* harddisk */
+#define DEV_TYPE_TAPE 0x01 /* Tape */
+#define DEV_TYPE_CDROM 0x05 /* CD-ROM */
+#define DEV_TYPE_OPDISK 0x07 /* optical disk */
+
+struct blk_device
+{
+ struct rt_device parent;
+ struct ahci_uc_priv *ahci_device;
+
+ rt_uint8_t target;
+ rt_uint8_t lun;
+ rt_uint8_t type;
+
+#ifdef RT_USING_DFS_LWEXT4
+ struct ext4_mbr_bdevs ext4_partition;
+#endif
+
+ rt_bool_t lba48;
+ rt_uint64_t lba;
+ rt_uint64_t blksz;
+ rt_int32_t log2blksz;
+
+ char product[21];
+ char revision[9];
+ char vendor[41];
+};
+
+void blk_device_init(struct blk_device *blk_devices);
+
+#endif
diff --git a/bsp/ls2kdev/drivers/ata/dwc_ahsata.c b/bsp/ls2kdev/drivers/ata/dwc_ahsata.c
new file mode 100644
index 0000000000..bf76636e06
--- /dev/null
+++ b/bsp/ls2kdev/drivers/ata/dwc_ahsata.c
@@ -0,0 +1,1234 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2020-08-19 lizhirui porting to ls2k
+ */
+
+#include <rtthread.h>
+#include <rtdef.h>
+#include <mips_addrspace.h>
+#include <ata_interface.h>
+#include <ahci.h>
+#include <dwc_ahsata.h>
+#include <fis.h>
+#include <libata.h>
+#include <ata_debug.h>
+#include <blk_device.h>
+#include "dwc_ahsata_priv.h"
+
+struct sata_port_regs
+{
+ u32 clb;
+ u32 clbu;
+ u32 fb;
+ u32 fbu;
+ u32 is;
+ u32 ie;
+ u32 cmd;
+ u32 res1[1];
+ u32 tfd;
+ u32 sig;
+ u32 ssts;
+ u32 sctl;
+ u32 serr;
+ u32 sact;
+ u32 ci;
+ u32 sntf;
+ u32 res2[1];
+ u32 dmacr;
+ u32 res3[1];
+ u32 phycr;
+ u32 physr;
+};
+
+struct sata_host_regs
+{
+ u32 cap;
+ u32 ghc;
+ u32 is;
+ u32 pi;
+ u32 vs;
+ u32 ccc_ctl;
+ u32 ccc_ports;
+ u32 res1[2];
+ u32 cap2;
+ u32 res2[30];
+ u32 bistafr;
+ u32 bistcr;
+ u32 bistfctr;
+ u32 bistsr;
+ u32 bistdecr;
+ u32 res3[2];
+ u32 oobr;
+ u32 res4[8];
+ u32 timer1ms;
+ u32 res5[1];
+ u32 gparam1r;
+ u32 gparam2r;
+ u32 pparamr;
+ u32 testr;
+ u32 versionr;
+ u32 idr;
+};
+
+#define MAX_DATA_BYTES_PER_SG (4 * 1024 * 1024)
+#define MAX_BYTES_PER_TRANS (AHCI_MAX_SG * MAX_DATA_BYTES_PER_SG)
+
+#define writel_with_flush(a, b) \
+ do \
+ { \
+ writel(a, b); \
+ readl(b); \
+ } while (0)
+
+static inline void __iomem *ahci_port_base(void __iomem *base, u32 port)
+{
+ return base + 0x100 + (port * 0x80);
+}
+
+static int waiting_for_cmd_completed(u8 *offset, int timeout_msec, u32 sign)
+{
+ int i;
+ u32 status;
+
+ for (i = 0; ((status = readl(offset)) & sign) && i < timeout_msec; i++)
+ {
+ mdelay(1);
+ }
+
+ return (i < timeout_msec) ? 0 : -1;
+}
+
+static int ahci_setup_oobr(struct ahci_uc_priv *uc_priv, int clk)
+{
+ struct sata_host_regs *host_mmio = uc_priv->mmio_base;
+
+ writel(SATA_HOST_OOBR_WE, &host_mmio->oobr);
+ writel(0x02060b14, &host_mmio->oobr);
+
+ return 0;
+}
+
+int ahci_host_init(struct ahci_uc_priv *uc_priv)
+{
+ u32 tmp, cap_save, num_ports;
+ int i, j, timeout = 1000;
+ struct sata_port_regs *port_mmio = NULL;
+ struct sata_host_regs *host_mmio = uc_priv->mmio_base;
+
+ //prepare to enable staggered spin-up
+ cap_save = readl(&host_mmio->cap);
+ cap_save |= SATA_HOST_CAP_SSS;
+
+ /* global controller reset */
+ tmp = readl(&host_mmio->ghc);
+
+ //ahsata controller reset
+ if ((tmp & SATA_HOST_GHC_HR) == 0)
+ {
+ writel_with_flush(tmp | SATA_HOST_GHC_HR, &host_mmio->ghc);
+ }
+
+ //wait for reset finishing
+ while ((readl(&host_mmio->ghc) & SATA_HOST_GHC_HR) && --timeout)
+ ;
+
+ //reset timeout
+ if (timeout <= 0)
+ {
+ debug("controller reset failed (0x%x)\n", tmp);
+ return -1;
+ }
+
+ /* Set timer 1ms @ 100MHz*/
+ writel(100000000 / 1000, &host_mmio->timer1ms);
+
+ ahci_setup_oobr(uc_priv, 0);
+
+ //enable ahci
+ writel_with_flush(SATA_HOST_GHC_AE, &host_mmio->ghc);
+
+ //enable staggered spin-up
+ writel(cap_save, &host_mmio->cap);
+
+ //get sata port number
+ num_ports = (cap_save & SATA_HOST_CAP_NP_MASK) + 1;
+
+ //initialize pi register to set correct port number
+ writel_with_flush((1 << num_ports) - 1, &host_mmio->pi);
+
+ /*
+ * Determine which Ports are implemented by the DWC_ahsata,
+ * by reading the PI register. This bit map value aids the
+ * software to determine how many Ports are available and
+ * which Port registers need to be initialized.
+ */
+ uc_priv->cap = readl(&host_mmio->cap);
+ uc_priv->port_map = readl(&host_mmio->pi);
+
+ /* Determine how many command slots the HBA supports */
+ uc_priv->n_ports = (uc_priv->cap & SATA_HOST_CAP_NP_MASK) + 1;
+
+ debug("cap 0x%x port_map 0x%x n_ports %d\n",
+ uc_priv->cap, uc_priv->port_map, uc_priv->n_ports);
+
+ for (i = 0; i < uc_priv->n_ports; i++)
+ {
+ uc_priv->port[i].port_mmio = ahci_port_base(host_mmio, i);
+ port_mmio = uc_priv->port[i].port_mmio;
+
+ /* Ensure that the DWC_ahsata is in idle state */
+ tmp = readl(&port_mmio->cmd);
+
+ /*
+ * When P#CMD.ST, P#CMD.CR, P#CMD.FRE and P#CMD.FR
+ * are all cleared, the Port is in an idle state.
+ */
+ if (tmp & (SATA_PORT_CMD_CR | SATA_PORT_CMD_FR |
+ SATA_PORT_CMD_FRE | SATA_PORT_CMD_ST))
+ {
+
+ /*
+ * System software places a Port into the idle state by
+ * clearing P#CMD.ST and waiting for P#CMD.CR to return
+ * 0 when read.
+ */
+ tmp &= ~SATA_PORT_CMD_ST;
+ writel_with_flush(tmp, &port_mmio->cmd);
+
+ /*
+ * spec says 500 msecs for each bit, so
+ * this is slightly incorrect.
+ */
+ mdelay(500);
+
+ timeout = 1000;
+ while ((readl(&port_mmio->cmd) & SATA_PORT_CMD_CR) && --timeout)
+ ;
+
+ if (timeout <= 0)
+ {
+ debug("port reset failed (0x%x)\n", tmp);
+ return -1;
+ }
+ }
+
+ /* Spin-up device */
+ tmp = readl(&port_mmio->cmd);
+ writel((tmp | SATA_PORT_CMD_SUD), &port_mmio->cmd);
+
+ /* Wait for spin-up to finish */
+ timeout = 1000;
+ while (!(readl(&port_mmio->cmd) | SATA_PORT_CMD_SUD) && --timeout)
+ ;
+
+ if (timeout <= 0)
+ {
+ debug("Spin-Up can't finish!\n");
+ return -1;
+ }
+
+ for (j = 0; j < 100; ++j)
+ {
+ mdelay(10);
+ tmp = readl(&port_mmio->ssts);
+ if (((tmp & SATA_PORT_SSTS_DET_MASK) == 0x3) ||
+ ((tmp & SATA_PORT_SSTS_DET_MASK) == 0x1))
+ {
+ break;
+ }
+ }
+
+ /* Wait for COMINIT bit 26 (DIAG_X) in SERR */
+ timeout = 1000;
+ while (!(readl(&port_mmio->serr) & SATA_PORT_SERR_DIAG_X) && --timeout)
+ ;
+
+ if (timeout <= 0)
+ {
+ debug("Can't find DIAG_X set!\n");
+ return -1;
+ }
+
+ /*
+ * For each implemented Port, clear the P#SERR
+ * register, by writing ones to each implemented\
+ * bit location.
+ */
+ tmp = readl(&port_mmio->serr);
+ debug("P#SERR 0x%x\n",
+ tmp);
+ writel(tmp, &port_mmio->serr);
+
+ /* Ack any pending irq events for this port */
+ tmp = readl(&host_mmio->is);
+ debug("IS 0x%x\n", tmp);
+ if (tmp)
+ {
+ writel(tmp, &host_mmio->is);
+ }
+
+ writel(1 << i, &host_mmio->is);
+
+ /* set irq mask (enables interrupts) */
+ writel(DEF_PORT_IRQ, &port_mmio->ie);
+
+ /* register linkup ports */
+ tmp = readl(&port_mmio->ssts);
+ debug("Port %d status: 0x%x\n", i, tmp);
+ if ((tmp & SATA_PORT_SSTS_DET_MASK) == 0x03)
+ {
+ uc_priv->link_port_map |= (0x01 << i);
+ }
+ }
+
+ tmp = readl(&host_mmio->ghc);
+ debug("GHC 0x%x\n", tmp);
+ //Interrupt Enable
+ writel(tmp | SATA_HOST_GHC_IE, &host_mmio->ghc);
+ tmp = readl(&host_mmio->ghc);
+ debug("GHC 0x%x\n", tmp);
+
+ return 0;
+}
+
+int rt_hw_ahci_host_init()
+{
+ struct ahci_uc_priv *ahci_device;
+ ahci_device = (struct ahci_uc_priv *)rt_device_create(RT_Device_Class_Miscellaneous, sizeof(struct ahci_uc_priv) - sizeof(struct rt_device));
+
+ ahci_device->mmio_base = (void *)DWCAHSATA_BASE;
+ ahci_device->parent.init = NULL;
+ ahci_device->parent.open = NULL;
+ ahci_device->parent.close = NULL;
+ ahci_device->parent.read = NULL;
+ ahci_device->parent.write = NULL;
+ ahci_device->parent.control = NULL;
+
+ if (rt_device_register((rt_device_t)ahci_device, "dwc_ahsata_ahci", 0) != RT_EOK)
+ {
+ rt_kprintf("dwc_ahsata_ahci device register failed!\n");
+ return -RT_ERROR;
+ }
+
+ if (dwc_ahsata_probe((rt_device_t)ahci_device) != 0)
+ {
+ rt_kprintf("ahci probe failed!\n");
+ return -RT_ERROR;
+ }
+
+ if (dwc_ahsata_scan((rt_device_t)ahci_device) != 0)
+ {
+ rt_kprintf("ahci host sata device scan failed!\n");
+ return -RT_ERROR;
+ }
+
+ return RT_EOK;
+}
+INIT_COMPONENT_EXPORT(rt_hw_ahci_host_init);
+
+static void ahci_print_info(struct ahci_uc_priv *uc_priv)
+{
+ struct sata_host_regs *host_mmio = uc_priv->mmio_base;
+ u32 vers, cap, impl, speed;
+ const char *speed_s;
+ const char *scc_s;
+
+ vers = readl(&host_mmio->vs);
+ cap = uc_priv->cap;
+ impl = uc_priv->port_map;
+
+ speed = (cap & SATA_HOST_CAP_ISS_MASK) >> SATA_HOST_CAP_ISS_OFFSET;
+
+ if (speed == 1)
+ {
+ speed_s = "1.5";
+ }
+ else if (speed == 2)
+ {
+ speed_s = "3";
+ }
+ else
+ {
+ speed_s = "?";
+ }
+
+ scc_s = "SATA";
+
+ rt_kprintf("AHCI %02x%02x.%02x%02x "
+ "%u slots %u ports %s Gbps 0x%x impl %s mode\n",
+ (vers >> 24) & 0xff,
+ (vers >> 16) & 0xff,
+ (vers >> 8) & 0xff,
+ vers & 0xff,
+ ((cap >> 8) & 0x1f) + 1,
+ (cap & 0x1f) + 1,
+ speed_s,
+ impl,
+ scc_s);
+
+ rt_kprintf("flags: "
+ "%s%s%s%s%s%s"
+ "%s%s%s%s%s%s%s\n",
+ cap & (1 << 31) ? "64bit " : "",
+ cap & (1 << 30) ? "ncq " : "",
+ cap & (1 << 28) ? "ilck " : "",
+ cap & (1 << 27) ? "stag " : "",
+ cap & (1 << 26) ? "pm " : "",
+ cap & (1 << 25) ? "led " : "",
+ cap & (1 << 24) ? "clo " : "",
+ cap & (1 << 19) ? "nz " : "",
+ cap & (1 << 18) ? "only " : "",
+ cap & (1 << 17) ? "pmp " : "",
+ cap & (1 << 15) ? "pio " : "",
+ cap & (1 << 14) ? "slum " : "",
+ cap & (1 << 13) ? "part " : "");
+
+ rt_kprintf("version = %08x\n", ((struct sata_host_regs *)(uc_priv->mmio_base))->versionr);
+}
+
+static int ahci_fill_sg(struct ahci_uc_priv *uc_priv, u8 port,
+ unsigned char *buf, int buf_len)
+{
+ struct ahci_ioports *pp = &uc_priv->port[port];
+ struct ahci_sg *ahci_sg = pp->cmd_tbl_sg;
+ u32 sg_count, max_bytes;
+ int i;
+
+ max_bytes = MAX_DATA_BYTES_PER_SG;
+ sg_count = ((buf_len - 1) / max_bytes) + 1;
+
+ if (sg_count > AHCI_MAX_SG)
+ {
+ rt_kprintf("Error:Too much sg!\n");
+ return -1;
+ }
+
+ for (i = 0; i < sg_count; i++)
+ {
+ ahci_sg->addr = VADDR_TO_PHY(buf + i * max_bytes);
+ //ahci_sg->addr_hi = 0;
+ ahci_sg->flags_size = cpu_to_le32(0x3fffff &
+ (buf_len < max_bytes
+ ? (buf_len - 1)
+ : (max_bytes - 1)));
+ ahci_sg++;
+ buf_len -= max_bytes;
+ }
+
+ return sg_count;
+}
+
+static void ahci_fill_cmd_slot(struct ahci_ioports *pp, u32 cmd_slot, u32 opts)
+{
+ struct ahci_cmd_hdr *cmd_hdr = (struct ahci_cmd_hdr *)(pp->cmd_slot +
+ AHCI_CMD_SLOT_SZ * cmd_slot);
+
+ memset(cmd_hdr, 0, AHCI_CMD_SLOT_SZ);
+ cmd_hdr->opts = cpu_to_le32(opts);
+ cmd_hdr->status = 0;
+ pp->cmd_slot->tbl_addr = VADDR_TO_PHY(pp->cmd_tbl);
+ /*#ifdef CONFIG_PHYS_64BIT
+ pp->cmd_slot->tbl_addr_hi =
+ cpu_to_le32((u32)(((pp->cmd_tbl) >> 16) >> 16));
+#endif*/
+}
+
+#define AHCI_GET_CMD_SLOT(c) ((c) ? ffs(c) : 0)
+
+static int ahci_exec_ata_cmd(struct ahci_uc_priv *uc_priv, u8 port,
+ struct sata_fis_h2d *cfis, u8 *buf, u32 buf_len,
+ s32 is_write)
+{
+ struct ahci_ioports *pp = &uc_priv->port[port];
+ struct sata_port_regs *port_mmio = pp->port_mmio;
+ u32 opts;
+ int sg_count = 0, cmd_slot = 0;
+
+ cmd_slot = AHCI_GET_CMD_SLOT(readl(&port_mmio->ci));
+
+ if (32 == cmd_slot)
+ {
+ rt_kprintf("Can't find empty command slot!\n");
+ return 0;
+ }
+
+ /* Check xfer length */
+ if (buf_len > MAX_BYTES_PER_TRANS)
+ {
+ rt_kprintf("Max transfer length is %dB\n\r",
+ MAX_BYTES_PER_TRANS);
+ return 0;
+ }
+
+ memcpy((u8 *)(pp->cmd_tbl), cfis, sizeof(struct sata_fis_h2d));
+
+ if (buf && buf_len)
+ {
+ sg_count = ahci_fill_sg(uc_priv, port, buf, buf_len);
+ }
+
+ opts = (sizeof(struct sata_fis_h2d) >> 2) | (sg_count << 16);
+
+ if (is_write)
+ {
+ opts |= 0x40;
+ flush_cache((ulong)buf, buf_len);
+ }
+
+ ahci_fill_cmd_slot(pp, cmd_slot, opts);
+
+ flush_cache((int)(pp->cmd_slot), AHCI_PORT_PRIV_DMA_SZ);
+ writel_with_flush(1 << cmd_slot, &port_mmio->ci);
+
+ if (waiting_for_cmd_completed((u8 *)&port_mmio->ci, 10000,
+ 0x1 << cmd_slot))
+ {
+ rt_kprintf("timeout exit!\n");
+ return -1;
+ }
+
+ invalidate_dcache_range((int)(pp->cmd_slot),
+ (int)(pp->cmd_slot) + AHCI_PORT_PRIV_DMA_SZ);
+
+ debug("ahci_exec_ata_cmd: %d byte transferred.\n",
+ pp->cmd_slot->status);
+
+ if (!is_write)
+ {
+ invalidate_dcache_range((ulong)buf, (ulong)buf + buf_len);
+ }
+
+ return buf_len;
+}
+
+static void ahci_set_feature(struct ahci_uc_priv *uc_priv, u8 port)
+{
+ struct sata_fis_h2d h2d __aligned(ARCH_DMA_MINALIGN);
+ struct sata_fis_h2d *cfis = &h2d;
+
+ memset(cfis, 0, sizeof(struct sata_fis_h2d));
+ cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
+ cfis->pm_port_c = 1 << 7;
+ cfis->command = ATA_CMD_SET_FEATURES;
+ cfis->features = SETFEATURES_XFER;
+ cfis->sector_count = ffs(uc_priv->udma_mask + 1) + 0x3e;
+
+ ahci_exec_ata_cmd(uc_priv, port, cfis, NULL, 0, READ_CMD);
+}
+
+static int ahci_port_start(struct ahci_uc_priv *uc_priv, u8 port)
+{
+ struct ahci_ioports *pp = &uc_priv->port[port];
+ struct sata_port_regs *port_mmio = pp->port_mmio;
+ u32 port_status;
+ u64 mem;
+ int timeout = 10000000;
+
+ debug("Enter start port: %d\n", port);
+ port_status = readl(&port_mmio->ssts);
+ debug("Port %d status: %x\n", port, port_status);
+
+ if ((port_status & 0xf) != 0x03)
+ {
+ rt_kprintf("No Link on this port!\n");
+ return -1;
+ }
+
+ mem = (u64)malloc(AHCI_PORT_PRIV_DMA_SZ + 1024);
+
+ if (!mem)
+ {
+ rt_kprintf("No mem for table!\n");
+ return -ENOMEM;
+ }
+
+ mem = (mem + 0x400) & (~0x3ff); /* Aligned to 1024-bytes */
+ memset((u8 *)mem, 0, AHCI_PORT_PRIV_DMA_SZ);
+
+ /*
+ * First item in chunk of DMA memory: 32-slot command table,
+ * 32 bytes each in size
+ */
+ pp->cmd_slot = (struct ahci_cmd_hdr *)mem;
+ debug("cmd_slot = 0x%p\n", pp->cmd_slot);
+ mem += (AHCI_CMD_SLOT_SZ * DWC_AHSATA_MAX_CMD_SLOTS);
+
+ /*
+ * Second item: Received-FIS area, 256-Byte aligned
+ */
+ pp->rx_fis = mem;
+ mem += AHCI_RX_FIS_SZ;
+
+ /*
+ * Third item: data area for storing a single command
+ * and its scatter-gather table
+ */
+ pp->cmd_tbl = mem;
+ debug("cmd_tbl_dma = 0x%lx\n", pp->cmd_tbl);
+
+ mem += AHCI_CMD_TBL_HDR;
+
+ writel_with_flush(0x00004444, &port_mmio->dmacr);
+ pp->cmd_tbl_sg = (struct ahci_sg *)mem;
+ writel_with_flush(LOW_PHY(pp->cmd_slot), &port_mmio->clb);
+ writel_with_flush(HIGH_PHY(pp->cmd_slot), &port_mmio->clbu);
+ writel_with_flush(LOW_PHY(pp->rx_fis), &port_mmio->fb);
+ writel_with_flush(HIGH_PHY(pp->rx_fis), &port_mmio->fbu);
+
+ /* Enable FRE */
+ writel_with_flush((SATA_PORT_CMD_FRE | readl(&port_mmio->cmd)),
+ &port_mmio->cmd);
+
+ /* Wait device ready */
+ while ((readl(&port_mmio->tfd) & (SATA_PORT_TFD_STS_ERR |
+ SATA_PORT_TFD_STS_DRQ | SATA_PORT_TFD_STS_BSY)) &&
+ --timeout)
+ ;
+ if (timeout <= 0)
+ {
+ debug("Device not ready for BSY, DRQ and"
+ "ERR in TFD!\n");
+ return -1;
+ }
+
+ writel_with_flush(PORT_CMD_ICC_ACTIVE | PORT_CMD_FIS_RX |
+ PORT_CMD_POWER_ON | PORT_CMD_SPIN_UP |
+ PORT_CMD_START,
+ &port_mmio->cmd);
+
+ debug("Exit start port %d\n", port);
+
+ return 0;
+}
+
+static void dwc_ahsata_print_info(struct blk_device *pdev)
+{
+ rt_kprintf("SATA Device Info:\n\r");
+ rt_kprintf("S/N: %s\n\rProduct model number: %s\n\r"
+ "Firmware version: %s\n\rCapacity: %lu sectors\n\r",
+ pdev->product, pdev->vendor, pdev->revision, pdev->lba);
+}
+
+static void dwc_ahsata_identify(struct ahci_uc_priv *uc_priv, u16 *id)
+{
+ struct sata_fis_h2d h2d __aligned(ARCH_DMA_MINALIGN);
+ struct sata_fis_h2d *cfis = &h2d;
+ u8 port = uc_priv->hard_port_no;
+
+ memset(cfis, 0, sizeof(struct sata_fis_h2d));
+
+ cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
+ cfis->pm_port_c = 0x80; /* is command */
+ cfis->command = ATA_CMD_ID_ATA;
+
+ ahci_exec_ata_cmd(uc_priv, port, cfis, (u8 *)id, ATA_ID_WORDS * 2,
+ READ_CMD);
+ ata_swap_buf_le16(id, ATA_ID_WORDS);
+}
+
+static void dwc_ahsata_xfer_mode(struct ahci_uc_priv *uc_priv, u16 *id)
+{
+ uc_priv->pio_mask = id[ATA_ID_PIO_MODES];
+ uc_priv->udma_mask = id[ATA_ID_UDMA_MODES];
+ debug("pio %04x, udma %04x\n\r", uc_priv->pio_mask, uc_priv->udma_mask);
+}
+
+static u32 dwc_ahsata_rw_cmd(struct ahci_uc_priv *uc_priv, u32 start,
+ u32 blkcnt, u8 *buffer, int is_write)
+{
+ struct sata_fis_h2d h2d __aligned(ARCH_DMA_MINALIGN);
+ struct sata_fis_h2d *cfis = &h2d;
+ u8 port = uc_priv->hard_port_no;
+ u32 block;
+
+ block = start;
+
+ memset(cfis, 0, sizeof(struct sata_fis_h2d));
+
+ cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
+ cfis->pm_port_c = 0x80; /* is command */
+ cfis->command = (is_write) ? ATA_CMD_WRITE : ATA_CMD_READ;
+ cfis->device = ATA_LBA;
+
+ cfis->device |= (block >> 24) & 0xf;
+ cfis->lba_high = (block >> 16) & 0xff;
+ cfis->lba_mid = (block >> 8) & 0xff;
+ cfis->lba_low = block & 0xff;
+ cfis->sector_count = (u8)(blkcnt & 0xff);
+
+ if (ahci_exec_ata_cmd(uc_priv, port, cfis, buffer,
+ ATA_SECT_SIZE * blkcnt, is_write) > 0)
+ return blkcnt;
+ else
+ return 0;
+}
+
+static void dwc_ahsata_flush_cache(struct ahci_uc_priv *uc_priv)
+{
+ struct sata_fis_h2d h2d __aligned(ARCH_DMA_MINALIGN);
+ struct sata_fis_h2d *cfis = &h2d;
+ u8 port = uc_priv->hard_port_no;
+
+ memset(cfis, 0, sizeof(struct sata_fis_h2d));
+
+ cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
+ cfis->pm_port_c = 0x80; /* is command */
+ cfis->command = ATA_CMD_FLUSH;
+
+ ahci_exec_ata_cmd(uc_priv, port, cfis, NULL, 0, 0);
+}
+
+static u32 dwc_ahsata_rw_cmd_ext(struct ahci_uc_priv *uc_priv, u32 start,
+ lbaint_t blkcnt, u8 *buffer, int is_write)
+{
+ struct sata_fis_h2d h2d __aligned(ARCH_DMA_MINALIGN);
+ struct sata_fis_h2d *cfis = &h2d;
+ u8 port = uc_priv->hard_port_no;
+ u64 block;
+
+ block = (u64)start;
+
+ memset(cfis, 0, sizeof(struct sata_fis_h2d));
+
+ cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
+ cfis->pm_port_c = 0x80; /* is command */
+
+ cfis->command = (is_write) ? ATA_CMD_WRITE_EXT
+ : ATA_CMD_READ_EXT;
+
+ cfis->lba_high_exp = (block >> 40) & 0xff;
+ cfis->lba_mid_exp = (block >> 32) & 0xff;
+ cfis->lba_low_exp = (block >> 24) & 0xff;
+ cfis->lba_high = (block >> 16) & 0xff;
+ cfis->lba_mid = (block >> 8) & 0xff;
+ cfis->lba_low = block & 0xff;
+ cfis->device = ATA_LBA;
+ cfis->sector_count_exp = (blkcnt >> 8) & 0xff;
+ cfis->sector_count = blkcnt & 0xff;
+
+ if (ahci_exec_ata_cmd(uc_priv, port, cfis, buffer,
+ ATA_SECT_SIZE * blkcnt, is_write) > 0)
+ return blkcnt;
+ else
+ return 0;
+}
+
+static void dwc_ahsata_flush_cache_ext(struct ahci_uc_priv *uc_priv)
+{
+ struct sata_fis_h2d h2d __aligned(ARCH_DMA_MINALIGN);
+ struct sata_fis_h2d *cfis = &h2d;
+ u8 port = uc_priv->hard_port_no;
+
+ memset(cfis, 0, sizeof(struct sata_fis_h2d));
+
+ cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
+ cfis->pm_port_c = 0x80; /* is command */
+ cfis->command = ATA_CMD_FLUSH_EXT;
+
+ ahci_exec_ata_cmd(uc_priv, port, cfis, NULL, 0, 0);
+}
+
+static void dwc_ahsata_init_wcache(struct ahci_uc_priv *uc_priv, u16 *id)
+{
+ if (ata_id_has_wcache(id) && ata_id_wcache_enabled(id))
+ uc_priv->flags |= SATA_FLAG_WCACHE;
+ if (ata_id_has_flush(id))
+ uc_priv->flags |= SATA_FLAG_FLUSH;
+ if (ata_id_has_flush_ext(id))
+ uc_priv->flags |= SATA_FLAG_FLUSH_EXT;
+}
+
+static u32 ata_low_level_rw_lba48(struct ahci_uc_priv *uc_priv, u32 blknr,
+ lbaint_t blkcnt, const void *buffer,
+ int is_write)
+{
+ u32 start, blks;
+ u8 *addr;
+ int max_blks;
+
+ start = blknr;
+ blks = blkcnt;
+ addr = (u8 *)buffer;
+
+ max_blks = ATA_MAX_SECTORS_LBA48;
+
+ do
+ {
+ if (blks > max_blks)
+ {
+ if (max_blks != dwc_ahsata_rw_cmd_ext(uc_priv, start,
+ max_blks, addr,
+ is_write))
+ return 0;
+ start += max_blks;
+ blks -= max_blks;
+ addr += ATA_SECT_SIZE * max_blks;
+ }
+ else
+ {
+ if (blks != dwc_ahsata_rw_cmd_ext(uc_priv, start, blks,
+ addr, is_write))
+ return 0;
+ start += blks;
+ blks = 0;
+ addr += ATA_SECT_SIZE * blks;
+ }
+ } while (blks != 0);
+
+ return blkcnt;
+}
+
+static u32 ata_low_level_rw_lba28(struct ahci_uc_priv *uc_priv, u32 blknr,
+ lbaint_t blkcnt, const void *buffer,
+ int is_write)
+{
+ u32 start, blks;
+ u8 *addr;
+ int max_blks;
+
+ start = blknr;
+ blks = blkcnt;
+ addr = (u8 *)buffer;
+
+ max_blks = ATA_MAX_SECTORS;
+ do
+ {
+ if (blks > max_blks)
+ {
+ if (max_blks != dwc_ahsata_rw_cmd(uc_priv, start,
+ max_blks, addr,
+ is_write))
+ return 0;
+ start += max_blks;
+ blks -= max_blks;
+ addr += ATA_SECT_SIZE * max_blks;
+ }
+ else
+ {
+ if (blks != dwc_ahsata_rw_cmd(uc_priv, start, blks,
+ addr, is_write))
+ return 0;
+ start += blks;
+ blks = 0;
+ addr += ATA_SECT_SIZE * blks;
+ }
+ } while (blks != 0);
+
+ return blkcnt;
+}
+
+static int dwc_ahci_start_ports(struct ahci_uc_priv *uc_priv)
+{
+ u32 linkmap;
+ int i;
+
+ linkmap = uc_priv->link_port_map;
+
+ if (0 == linkmap)
+ {
+ rt_kprintf("No port device detected!\n");
+ return -ENXIO;
+ }
+
+ for (i = 0; i < uc_priv->n_ports; i++)
+ {
+ if ((linkmap >> i) && ((linkmap >> i) & 0x01))
+ {
+ if (ahci_port_start(uc_priv, (u8)i))
+ {
+ rt_kprintf("Can not start port %d\n", i);
+ return 1;
+ }
+
+ uc_priv->hard_port_no = i;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+unsigned char sector_data[512];
+
+void dump_pbuf(void *p, int len)
+{
+ rt_kprintf("----dump_pbuf----\n");
+ rt_kprintf("pbuf = 0x%p,len = %d\n", p, len);
+ u32 i;
+ u8 *q = p;
+ rt_kprintf("%p", q);
+
+ for (i = 0; i < 16; i++)
+ {
+ rt_kprintf(" %02x", i);
+ }
+
+ rt_kprintf("\n");
+
+ for (i = 0; i < len; i++)
+ {
+ if (!(i & 0xF))
+ {
+ rt_kprintf("%p", &q[i]);
+ }
+
+ rt_kprintf(" %02x", q[i]);
+
+ if ((i & 0xF) == 0xF)
+ {
+ rt_kprintf("\n");
+ }
+ }
+
+ rt_kprintf("\n-----------------\n");
+}
+
+static int dwc_ahsata_scan_common(struct ahci_uc_priv *uc_priv,
+ struct blk_device *pdev)
+{
+ u8 serial[ATA_ID_SERNO_LEN + 1] = {0};
+ u8 firmware[ATA_ID_FW_REV_LEN + 1] = {0};
+ u8 product[ATA_ID_PROD_LEN + 1] = {0};
+ u8 port = uc_priv->hard_port_no;
+ ALLOC_CACHE_ALIGN_BUFFER(u16, id, ATA_ID_WORDS);
+
+ /* Identify device to get information */
+ dwc_ahsata_identify(uc_priv, id);
+
+ /* Serial number */
+ ata_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial));
+ memcpy(pdev->product, serial, sizeof(serial));
+
+ /* Firmware version */
+ ata_id_c_string(id, firmware, ATA_ID_FW_REV, sizeof(firmware));
+ memcpy(pdev->revision, firmware, sizeof(firmware));
+
+ /* Product model */
+ ata_id_c_string(id, product, ATA_ID_PROD, sizeof(product));
+ memcpy(pdev->vendor, product, sizeof(product));
+
+ /* Total sectors */
+ pdev->lba = ata_id_n_sectors(id);
+
+ pdev->type = DEV_TYPE_HARDDISK;
+ pdev->blksz = ATA_SECT_SIZE;
+ pdev->lun = 0;
+
+ /* Check if support LBA48 */
+ if (ata_id_has_lba48(id))
+ {
+ pdev->lba48 = 1;
+ debug("Device support LBA48\n\r");
+ }
+
+ /* Get the NCQ queue depth from device */
+ uc_priv->flags &= (~SATA_FLAG_Q_DEP_MASK);
+ uc_priv->flags |= ata_id_queue_depth(id);
+
+ /* Get the xfer mode from device */
+ dwc_ahsata_xfer_mode(uc_priv, id);
+
+ /* Get the write cache status from device */
+ dwc_ahsata_init_wcache(uc_priv, id);
+
+ /* Set the xfer mode to highest speed */
+ ahci_set_feature(uc_priv, port);
+ dwc_ahsata_read((rt_device_t)pdev, 0, sector_data, 1);
+ //dump_pbuf(sector_data, 512);
+ dwc_ahsata_print_info(pdev);
+
+ return 0;
+}
+
+/*
+ * SATA interface between low level driver and command layer
+ */
+static ulong sata_read_common(struct ahci_uc_priv *uc_priv,
+ struct blk_device *desc, ulong blknr,
+ lbaint_t blkcnt, void *buffer)
+{
+ u32 rc;
+
+ if (desc->lba48)
+ rc = ata_low_level_rw_lba48(uc_priv, blknr, blkcnt, buffer,
+ READ_CMD);
+ else
+ rc = ata_low_level_rw_lba28(uc_priv, blknr, blkcnt, buffer,
+ READ_CMD);
+
+ return rc;
+}
+
+static ulong sata_write_common(struct ahci_uc_priv *uc_priv,
+ struct blk_device *desc, ulong blknr,
+ lbaint_t blkcnt, const void *buffer)
+{
+ u32 rc;
+ u32 flags = uc_priv->flags;
+
+ if (desc->lba48)
+ {
+ rc = ata_low_level_rw_lba48(uc_priv, blknr, blkcnt, buffer,
+ WRITE_CMD);
+ if ((flags & SATA_FLAG_WCACHE) && (flags & SATA_FLAG_FLUSH_EXT))
+ dwc_ahsata_flush_cache_ext(uc_priv);
+ }
+ else
+ {
+ rc = ata_low_level_rw_lba28(uc_priv, blknr, blkcnt, buffer,
+ WRITE_CMD);
+ if ((flags & SATA_FLAG_WCACHE) && (flags & SATA_FLAG_FLUSH))
+ dwc_ahsata_flush_cache(uc_priv);
+ }
+
+ return rc;
+}
+
+#if !CONFIG_IS_ENABLED(AHCI)
+static int ahci_init_one(int pdev)
+{
+ int rc;
+ struct ahci_uc_priv *uc_priv = NULL;
+
+ uc_priv = malloc(sizeof(struct ahci_uc_priv));
+ if (!uc_priv)
+ return -ENOMEM;
+
+ memset(uc_priv, 0, sizeof(struct ahci_uc_priv));
+ uc_priv->dev = pdev;
+
+ uc_priv->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | ATA_FLAG_NO_ATAPI;
+
+ uc_priv->mmio_base = (void __iomem *)CONFIG_DWC_AHSATA_BASE_ADDR;
+
+ /* initialize adapter */
+ rc = ahci_host_init(uc_priv);
+ if (rc)
+ goto err_out;
+
+ ahci_print_info(uc_priv);
+
+ /* Save the uc_private struct to block device struct */
+ sata_dev_desc[pdev].priv = uc_priv;
+
+ return 0;
+
+err_out:
+ if (uc_priv)
+ free(uc_priv);
+ return rc;
+}
+
+int init_sata(int dev)
+{
+ struct ahci_uc_priv *uc_priv = NULL;
+
+#if defined(CONFIG_MX6)
+ if (!is_mx6dq() && !is_mx6dqp())
+ return 1;
+#endif
+ if (dev < 0 || dev > (CONFIG_SYS_SATA_MAX_DEVICE - 1))
+ {
+ rt_kprintf("The sata index %d is out of ranges\n\r", dev);
+ return -1;
+ }
+
+ ahci_init_one(dev);
+
+ uc_priv = sata_dev_desc[dev].priv;
+
+ return dwc_ahci_start_ports(uc_priv) ? 1 : 0;
+}
+
+int reset_sata(int dev)
+{
+ struct ahci_uc_priv *uc_priv;
+ struct sata_host_regs *host_mmio;
+
+ if (dev < 0 || dev > (CONFIG_SYS_SATA_MAX_DEVICE - 1))
+ {
+ rt_kprintf("The sata index %d is out of ranges\n\r", dev);
+ return -1;
+ }
+
+ uc_priv = sata_dev_desc[dev].priv;
+ if (NULL == uc_priv)
+ /* not initialized, so nothing to reset */
+ return 0;
+
+ host_mmio = uc_priv->mmio_base;
+ setbits_le32(&host_mmio->ghc, SATA_HOST_GHC_HR);
+ while (readl(&host_mmio->ghc) & SATA_HOST_GHC_HR)
+ udelay(100);
+
+ free(uc_priv);
+ memset(&sata_dev_desc[dev], 0, sizeof(struct blk_desc));
+
+ return 0;
+}
+
+int sata_port_status(int dev, int port)
+{
+ struct sata_port_regs *port_mmio;
+ struct ahci_uc_priv *uc_priv = NULL;
+
+ if (dev < 0 || dev > (CONFIG_SYS_SATA_MAX_DEVICE - 1))
+ return -EINVAL;
+
+ if (sata_dev_desc[dev].priv == NULL)
+ return -ENODEV;
+
+ uc_priv = sata_dev_desc[dev].priv;
+ port_mmio = uc_priv->port[port].port_mmio;
+
+ return readl(&port_mmio->ssts) & SATA_PORT_SSTS_DET_MASK;
+}
+
+/*
+ * SATA interface between low level driver and command layer
+ */
+ulong sata_read(int dev, ulong blknr, lbaint_t blkcnt, void *buffer)
+{
+ struct ahci_uc_priv *uc_priv = sata_dev_desc[dev].priv;
+
+ return sata_read_common(uc_priv, &sata_dev_desc[dev], blknr, blkcnt,
+ buffer);
+}
+
+ulong sata_write(int dev, ulong blknr, lbaint_t blkcnt, const void *buffer)
+{
+ struct ahci_uc_priv *uc_priv = sata_dev_desc[dev].priv;
+
+ return sata_write_common(uc_priv, &sata_dev_desc[dev], blknr, blkcnt,
+ buffer);
+}
+
+int scan_sata(int dev)
+{
+ struct ahci_uc_priv *uc_priv = sata_dev_desc[dev].priv;
+ struct blk_desc *pdev = &sata_dev_desc[dev];
+
+ return dwc_ahsata_scan_common(uc_priv, pdev);
+}
+#endif /* CONFIG_IS_ENABLED(AHCI) */
+
+#if CONFIG_IS_ENABLED(AHCI)
+
+int dwc_ahsata_port_status(struct rt_device *dev, int port)
+{
+ struct ahci_uc_priv *uc_priv = (struct ahci_uc_priv *)dev;
+ struct sata_port_regs *port_mmio;
+
+ port_mmio = uc_priv->port[port].port_mmio;
+ return readl(&port_mmio->ssts) & SATA_PORT_SSTS_DET_MASK ? 0 : -ENXIO;
+}
+
+int dwc_ahsata_bus_reset(struct rt_device *dev)
+{
+ struct ahci_uc_priv *uc_priv = (struct ahci_uc_priv *)dev;
+ struct sata_host_regs *host_mmio = uc_priv->mmio_base;
+
+ setbits_le32(&host_mmio->ghc, SATA_HOST_GHC_HR);
+
+ while (readl(&host_mmio->ghc) & SATA_HOST_GHC_HR)
+ {
+ udelay(100);
+ }
+
+ return 0;
+}
+
+int dwc_ahsata_scan(struct rt_device *dev)
+{
+ struct ahci_uc_priv *uc_priv = (struct ahci_uc_priv *)dev;
+ struct blk_device *blk;
+ rt_err_t ret;
+
+ blk = (struct blk_device *)rt_device_create(RT_Device_Class_Block, sizeof(struct blk_device) - sizeof(struct rt_device));
+ blk->parent.init = NULL;
+ blk->parent.open = NULL;
+ blk->parent.close = NULL;
+ blk->parent.control = dwc_ahsata_control;
+ blk->parent.read = dwc_ahsata_read;
+ blk->parent.write = dwc_ahsata_write;
+ blk->ahci_device = uc_priv;
+ blk->blksz = 512;
+ blk->log2blksz = 9;
+ blk->lba = 0;
+ ret = rt_device_register((rt_device_t)blk, "dwc_ahsata_blk", RT_DEVICE_FLAG_RDWR);
+
+ if (ret != RT_EOK)
+ {
+ debug("Can't create device\n");
+ return ret;
+ }
+
+ ret = dwc_ahsata_scan_common(uc_priv, blk);
+
+ if (ret)
+ {
+ debug("%s: Failed to scan bus\n", __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+int dwc_ahsata_probe(struct rt_device *dev)
+{
+ struct ahci_uc_priv *uc_priv = (struct ahci_uc_priv *)dev;
+ int ret;
+
+ uc_priv->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | ATA_FLAG_NO_ATAPI;
+
+ /* initialize adapter */
+ ret = ahci_host_init(uc_priv);
+ if (ret)
+ return ret;
+
+ ahci_print_info(uc_priv);
+
+ return dwc_ahci_start_ports(uc_priv);
+}
+
+rt_size_t dwc_ahsata_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
+{
+ struct blk_device *blk = (struct blk_device *)dev;
+ return sata_read_common(blk->ahci_device, blk, pos, size, buffer);
+}
+
+rt_size_t dwc_ahsata_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
+{
+ struct blk_device *blk = (struct blk_device *)dev;
+ return sata_write_common(blk->ahci_device, blk, pos, size, buffer);
+}
+
+rt_err_t dwc_ahsata_control(rt_device_t dev, int cmd, void *args)
+{
+ struct blk_device *blk = (struct blk_device *)dev;
+
+ switch (cmd)
+ {
+ case RT_DEVICE_CTRL_BLK_GETGEOME:
+
+ if (args != NULL)
+ {
+ struct rt_device_blk_geometry *info = (struct rt_device_blk_geometry *)args;
+ info->sector_count = blk->lba;
+ info->bytes_per_sector = blk->blksz;
+ info->block_size = 0;
+ }
+
+ break;
+ }
+
+ return RT_EOK;
+}
+
+#endif
diff --git a/bsp/ls2kdev/drivers/ata/dwc_ahsata.h b/bsp/ls2kdev/drivers/ata/dwc_ahsata.h
new file mode 100644
index 0000000000..44e993d03e
--- /dev/null
+++ b/bsp/ls2kdev/drivers/ata/dwc_ahsata.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2020-08-19 lizhirui porting to ls2k
+ */
+
+
+#ifndef __DWC_AHSATA_H__
+#define __DWC_AHSATA_H__
+
+#define DWCAHSATA_BASE (0x9000000000000000 | 0x400e0000)
+
+int dwc_ahsata_bus_reset(struct rt_device *dev);
+int dwc_ahsata_probe(struct rt_device *dev);
+int dwc_ahsata_scan(struct rt_device *dev);
+int dwc_ahsata_port_status(struct rt_device *dev, int port);
+rt_size_t dwc_ahsata_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);
+rt_size_t dwc_ahsata_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);
+rt_err_t dwc_ahsata_control(rt_device_t dev, int cmd, void *args);
+
+#endif
diff --git a/bsp/ls2kdev/drivers/ata/dwc_ahsata_priv.h b/bsp/ls2kdev/drivers/ata/dwc_ahsata_priv.h
new file mode 100644
index 0000000000..03e64808b9
--- /dev/null
+++ b/bsp/ls2kdev/drivers/ata/dwc_ahsata_priv.h
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2020-08-19 lizhirui porting to ls2k
+ */
+
+#ifndef __DWC_AHSATA_PRIV_H__
+#define __DWC_AHSATA_PRIV_H__
+
+#define DWC_AHSATA_MAX_CMD_SLOTS 32
+
+/* Max host controller numbers */
+#define SATA_HC_MAX_NUM 4
+/* Max command queue depth per host controller */
+#define DWC_AHSATA_HC_MAX_CMD 32
+/* Max port number per host controller */
+#define SATA_HC_MAX_PORT 16
+
+/* Generic Host Register */
+
+/* HBA Capabilities Register */
+#define SATA_HOST_CAP_S64A 0x80000000
+#define SATA_HOST_CAP_SNCQ 0x40000000
+#define SATA_HOST_CAP_SSNTF 0x20000000
+#define SATA_HOST_CAP_SMPS 0x10000000
+#define SATA_HOST_CAP_SSS 0x08000000
+#define SATA_HOST_CAP_SALP 0x04000000
+#define SATA_HOST_CAP_SAL 0x02000000
+#define SATA_HOST_CAP_SCLO 0x01000000
+#define SATA_HOST_CAP_ISS_MASK 0x00f00000
+#define SATA_HOST_CAP_ISS_OFFSET 20
+#define SATA_HOST_CAP_SNZO 0x00080000
+#define SATA_HOST_CAP_SAM 0x00040000
+#define SATA_HOST_CAP_SPM 0x00020000
+#define SATA_HOST_CAP_PMD 0x00008000
+#define SATA_HOST_CAP_SSC 0x00004000
+#define SATA_HOST_CAP_PSC 0x00002000
+#define SATA_HOST_CAP_NCS 0x00001f00
+#define SATA_HOST_CAP_CCCS 0x00000080
+#define SATA_HOST_CAP_EMS 0x00000040
+#define SATA_HOST_CAP_SXS 0x00000020
+#define SATA_HOST_CAP_NP_MASK 0x0000001f
+
+/* Global HBA Control Register */
+#define SATA_HOST_GHC_AE 0x80000000
+#define SATA_HOST_GHC_IE 0x00000002
+#define SATA_HOST_GHC_HR 0x00000001
+
+/* Interrupt Status Register */
+
+/* Ports Implemented Register */
+
+/* AHCI Version Register */
+#define SATA_HOST_VS_MJR_MASK 0xffff0000
+#define SATA_HOST_VS_MJR_OFFSET 16
+#define SATA_HOST_VS_MJR_MNR 0x0000ffff
+
+/* Command Completion Coalescing Control */
+#define SATA_HOST_CCC_CTL_TV_MASK 0xffff0000
+#define SATA_HOST_CCC_CTL_TV_OFFSET 16
+#define SATA_HOST_CCC_CTL_CC_MASK 0x0000ff00
+#define SATA_HOST_CCC_CTL_CC_OFFSET 8
+#define SATA_HOST_CCC_CTL_INT_MASK 0x000000f8
+#define SATA_HOST_CCC_CTL_INT_OFFSET 3
+#define SATA_HOST_CCC_CTL_EN 0x00000001
+
+/* Command Completion Coalescing Ports */
+
+/* HBA Capabilities Extended Register */
+#define SATA_HOST_CAP2_APST 0x00000004
+
+/* BIST Activate FIS Register */
+#define SATA_HOST_BISTAFR_NCP_MASK 0x0000ff00
+#define SATA_HOST_BISTAFR_NCP_OFFSET 8
+#define SATA_HOST_BISTAFR_PD_MASK 0x000000ff
+#define SATA_HOST_BISTAFR_PD_OFFSET 0
+
+/* BIST Control Register */
+#define SATA_HOST_BISTCR_FERLB 0x00100000
+#define SATA_HOST_BISTCR_TXO 0x00040000
+#define SATA_HOST_BISTCR_CNTCLR 0x00020000
+#define SATA_HOST_BISTCR_NEALB 0x00010000
+#define SATA_HOST_BISTCR_LLC_MASK 0x00000700
+#define SATA_HOST_BISTCR_LLC_OFFSET 8
+#define SATA_HOST_BISTCR_ERREN 0x00000040
+#define SATA_HOST_BISTCR_FLIP 0x00000020
+#define SATA_HOST_BISTCR_PV 0x00000010
+#define SATA_HOST_BISTCR_PATTERN_MASK 0x0000000f
+#define SATA_HOST_BISTCR_PATTERN_OFFSET 0
+
+/* BIST FIS Count Register */
+
+/* BIST Status Register */
+#define SATA_HOST_BISTSR_FRAMERR_MASK 0x0000ffff
+#define SATA_HOST_BISTSR_FRAMERR_OFFSET 0
+#define SATA_HOST_BISTSR_BRSTERR_MASK 0x00ff0000
+#define SATA_HOST_BISTSR_BRSTERR_OFFSET 16
+
+/* BIST DWORD Error Count Register */
+
+/* OOB Register*/
+#define SATA_HOST_OOBR_WE 0x80000000
+#define SATA_HOST_OOBR_cwMin_MASK 0x7f000000
+#define SATA_HOST_OOBR_cwMAX_MASK 0x00ff0000
+#define SATA_HOST_OOBR_ciMin_MASK 0x0000ff00
+#define SATA_HOST_OOBR_ciMax_MASK 0x000000ff
+
+/* Timer 1-ms Register */
+
+/* Global Parameter 1 Register */
+#define SATA_HOST_GPARAM1R_ALIGN_M 0x80000000
+#define SATA_HOST_GPARAM1R_RX_BUFFER 0x40000000
+#define SATA_HOST_GPARAM1R_PHY_DATA_MASK 0x30000000
+#define SATA_HOST_GPARAM1R_PHY_RST 0x08000000
+#define SATA_HOST_GPARAM1R_PHY_CTRL_MASK 0x07e00000
+#define SATA_HOST_GPARAM1R_PHY_STAT_MASK 0x001f8000
+#define SATA_HOST_GPARAM1R_LATCH_M 0x00004000
+#define SATA_HOST_GPARAM1R_BIST_M 0x00002000
+#define SATA_HOST_GPARAM1R_PHY_TYPE 0x00001000
+#define SATA_HOST_GPARAM1R_RETURN_ERR 0x00000400
+#define SATA_HOST_GPARAM1R_AHB_ENDIAN_MASK 0x00000300
+#define SATA_HOST_GPARAM1R_S_HADDR 0X00000080
+#define SATA_HOST_GPARAM1R_M_HADDR 0X00000040
+
+/* Global Parameter 2 Register */
+#define SATA_HOST_GPARAM2R_DEV_CP 0x00004000
+#define SATA_HOST_GPARAM2R_DEV_MP 0x00002000
+#define SATA_HOST_GPARAM2R_DEV_ENCODE_M 0x00001000
+#define SATA_HOST_GPARAM2R_RXOOB_CLK_M 0x00000800
+#define SATA_HOST_GPARAM2R_RXOOB_M 0x00000400
+#define SATA_HOST_GPARAM2R_TX_OOB_M 0x00000200
+#define SATA_HOST_GPARAM2R_RXOOB_CLK_MASK 0x000001ff
+
+/* Port Parameter Register */
+#define SATA_HOST_PPARAMR_TX_MEM_M 0x00000200
+#define SATA_HOST_PPARAMR_TX_MEM_S 0x00000100
+#define SATA_HOST_PPARAMR_RX_MEM_M 0x00000080
+#define SATA_HOST_PPARAMR_RX_MEM_S 0x00000040
+#define SATA_HOST_PPARAMR_TXFIFO_DEPTH_MASK 0x00000038
+#define SATA_HOST_PPARAMR_RXFIFO_DEPTH_MASK 0x00000007
+
+/* Test Register */
+#define SATA_HOST_TESTR_PSEL_MASK 0x00070000
+#define SATA_HOST_TESTR_TEST_IF 0x00000001
+
+/* Port Register Descriptions */
+/* Port# Command List Base Address Register */
+#define SATA_PORT_CLB_CLB_MASK 0xfffffc00
+
+/* Port# Command List Base Address Upper 32-Bits Register */
+
+/* Port# FIS Base Address Register */
+#define SATA_PORT_FB_FB_MASK 0xfffffff0
+
+/* Port# FIS Base Address Upper 32-Bits Register */
+
+/* Port# Interrupt Status Register */
+#define SATA_PORT_IS_CPDS 0x80000000
+#define SATA_PORT_IS_TFES 0x40000000
+#define SATA_PORT_IS_HBFS 0x20000000
+#define SATA_PORT_IS_HBDS 0x10000000
+#define SATA_PORT_IS_IFS 0x08000000
+#define SATA_PORT_IS_INFS 0x04000000
+#define SATA_PORT_IS_OFS 0x01000000
+#define SATA_PORT_IS_IPMS 0x00800000
+#define SATA_PORT_IS_PRCS 0x00400000
+#define SATA_PORT_IS_DMPS 0x00000080
+#define SATA_PORT_IS_PCS 0x00000040
+#define SATA_PORT_IS_DPS 0x00000020
+#define SATA_PORT_IS_UFS 0x00000010
+#define SATA_PORT_IS_SDBS 0x00000008
+#define SATA_PORT_IS_DSS 0x00000004
+#define SATA_PORT_IS_PSS 0x00000002
+#define SATA_PORT_IS_DHRS 0x00000001
+
+/* Port# Interrupt Enable Register */
+#define SATA_PORT_IE_CPDE 0x80000000
+#define SATA_PORT_IE_TFEE 0x40000000
+#define SATA_PORT_IE_HBFE 0x20000000
+#define SATA_PORT_IE_HBDE 0x10000000
+#define SATA_PORT_IE_IFE 0x08000000
+#define SATA_PORT_IE_INFE 0x04000000
+#define SATA_PORT_IE_OFE 0x01000000
+#define SATA_PORT_IE_IPME 0x00800000
+#define SATA_PORT_IE_PRCE 0x00400000
+#define SATA_PORT_IE_DMPE 0x00000080
+#define SATA_PORT_IE_PCE 0x00000040
+#define SATA_PORT_IE_DPE 0x00000020
+#define SATA_PORT_IE_UFE 0x00000010
+#define SATA_PORT_IE_SDBE 0x00000008
+#define SATA_PORT_IE_DSE 0x00000004
+#define SATA_PORT_IE_PSE 0x00000002
+#define SATA_PORT_IE_DHRE 0x00000001
+
+/* Port# Command Register */
+#define SATA_PORT_CMD_ICC_MASK 0xf0000000
+#define SATA_PORT_CMD_ASP 0x08000000
+#define SATA_PORT_CMD_ALPE 0x04000000
+#define SATA_PORT_CMD_DLAE 0x02000000
+#define SATA_PORT_CMD_ATAPI 0x01000000
+#define SATA_PORT_CMD_APSTE 0x00800000
+#define SATA_PORT_CMD_ESP 0x00200000
+#define SATA_PORT_CMD_CPD 0x00100000
+#define SATA_PORT_CMD_MPSP 0x00080000
+#define SATA_PORT_CMD_HPCP 0x00040000
+#define SATA_PORT_CMD_PMA 0x00020000
+#define SATA_PORT_CMD_CPS 0x00010000
+#define SATA_PORT_CMD_CR 0x00008000
+#define SATA_PORT_CMD_FR 0x00004000
+#define SATA_PORT_CMD_MPSS 0x00002000
+#define SATA_PORT_CMD_CCS_MASK 0x00001f00
+#define SATA_PORT_CMD_FRE 0x00000010
+#define SATA_PORT_CMD_CLO 0x00000008
+#define SATA_PORT_CMD_POD 0x00000004
+#define SATA_PORT_CMD_SUD 0x00000002
+#define SATA_PORT_CMD_ST 0x00000001
+
+/* Port# Task File Data Register */
+#define SATA_PORT_TFD_ERR_MASK 0x0000ff00
+#define SATA_PORT_TFD_STS_MASK 0x000000ff
+#define SATA_PORT_TFD_STS_ERR 0x00000001
+#define SATA_PORT_TFD_STS_DRQ 0x00000008
+#define SATA_PORT_TFD_STS_BSY 0x00000080
+
+/* Port# Signature Register */
+
+/* Port# Serial ATA Status {SStatus} Register */
+#define SATA_PORT_SSTS_IPM_MASK 0x00000f00
+#define SATA_PORT_SSTS_SPD_MASK 0x000000f0
+#define SATA_PORT_SSTS_DET_MASK 0x0000000f
+
+/* Port# Serial ATA Control {SControl} Register */
+#define SATA_PORT_SCTL_IPM_MASK 0x00000f00
+#define SATA_PORT_SCTL_SPD_MASK 0x000000f0
+#define SATA_PORT_SCTL_DET_MASK 0x0000000f
+
+/* Port# Serial ATA Error {SError} Register */
+#define SATA_PORT_SERR_DIAG_X 0x04000000
+#define SATA_PORT_SERR_DIAG_F 0x02000000
+#define SATA_PORT_SERR_DIAG_T 0x01000000
+#define SATA_PORT_SERR_DIAG_S 0x00800000
+#define SATA_PORT_SERR_DIAG_H 0x00400000
+#define SATA_PORT_SERR_DIAG_C 0x00200000
+#define SATA_PORT_SERR_DIAG_D 0x00100000
+#define SATA_PORT_SERR_DIAG_B 0x00080000
+#define SATA_PORT_SERR_DIAG_W 0x00040000
+#define SATA_PORT_SERR_DIAG_I 0x00020000
+#define SATA_PORT_SERR_DIAG_N 0x00010000
+#define SATA_PORT_SERR_ERR_E 0x00000800
+#define SATA_PORT_SERR_ERR_P 0x00000400
+#define SATA_PORT_SERR_ERR_C 0x00000200
+#define SATA_PORT_SERR_ERR_T 0x00000100
+#define SATA_PORT_SERR_ERR_M 0x00000002
+#define SATA_PORT_SERR_ERR_I 0x00000001
+
+/* Port# Serial ATA Active {SActive} Register */
+
+/* Port# Command Issue Register */
+
+/* Port# Serial ATA Notification Register */
+
+/* Port# DMA Control Register */
+#define SATA_PORT_DMACR_RXABL_MASK 0x0000f000
+#define SATA_PORT_DMACR_TXABL_MASK 0x00000f00
+#define SATA_PORT_DMACR_RXTS_MASK 0x000000f0
+#define SATA_PORT_DMACR_TXTS_MASK 0x0000000f
+
+/* Port# PHY Control Register */
+
+/* Port# PHY Status Register */
+
+#define SATA_HC_CMD_HDR_ENTRY_SIZE sizeof(struct cmd_hdr_entry)
+
+/* DW0
+*/
+#define CMD_HDR_DI_CFL_MASK 0x0000001f
+#define CMD_HDR_DI_CFL_OFFSET 0
+#define CMD_HDR_DI_A 0x00000020
+#define CMD_HDR_DI_W 0x00000040
+#define CMD_HDR_DI_P 0x00000080
+#define CMD_HDR_DI_R 0x00000100
+#define CMD_HDR_DI_B 0x00000200
+#define CMD_HDR_DI_C 0x00000400
+#define CMD_HDR_DI_PMP_MASK 0x0000f000
+#define CMD_HDR_DI_PMP_OFFSET 12
+#define CMD_HDR_DI_PRDTL 0xffff0000
+#define CMD_HDR_DI_PRDTL_OFFSET 16
+
+/* prde_fis_len
+*/
+#define CMD_HDR_PRD_ENTRY_SHIFT 16
+#define CMD_HDR_PRD_ENTRY_MASK 0x003f0000
+#define CMD_HDR_FIS_LEN_SHIFT 2
+
+/* attribute
+*/
+#define CMD_HDR_ATTR_RES 0x00000800 /* Reserved bit, should be 1 */
+#define CMD_HDR_ATTR_VBIST 0x00000400 /* Vendor BIST */
+/* Snoop enable for all descriptor */
+#define CMD_HDR_ATTR_SNOOP 0x00000200
+#define CMD_HDR_ATTR_FPDMA 0x00000100 /* FPDMA queued command */
+#define CMD_HDR_ATTR_RESET 0x00000080 /* Reset - a SRST or device reset */
+/* BIST - require the host to enter BIST mode */
+#define CMD_HDR_ATTR_BIST 0x00000040
+#define CMD_HDR_ATTR_ATAPI 0x00000020 /* ATAPI command */
+#define CMD_HDR_ATTR_TAG 0x0000001f /* TAG mask */
+
+#define FLAGS_DMA 0x00000000
+#define FLAGS_FPDMA 0x00000001
+
+#define SATA_FLAG_Q_DEP_MASK 0x0000000f
+#define SATA_FLAG_WCACHE 0x00000100
+#define SATA_FLAG_FLUSH 0x00000200
+#define SATA_FLAG_FLUSH_EXT 0x00000400
+
+#define READ_CMD 0
+#define WRITE_CMD 1
+
+#endif /* __DWC_AHSATA_H__ */
diff --git a/bsp/ls2kdev/drivers/ata/fis.h b/bsp/ls2kdev/drivers/ata/fis.h
new file mode 100644
index 0000000000..c4c6557b8f
--- /dev/null
+++ b/bsp/ls2kdev/drivers/ata/fis.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2020-08-19 lizhirui porting to ls2k
+ */
+
+#ifndef __FIS_H__
+#define __FIS_H__
+/*
+* Register - Host to Device FIS
+*/
+typedef struct sata_fis_h2d
+{
+ u8 fis_type;
+ u8 pm_port_c;
+ u8 command;
+ u8 features;
+ u8 lba_low;
+ u8 lba_mid;
+ u8 lba_high;
+ u8 device;
+ u8 lba_low_exp;
+ u8 lba_mid_exp;
+ u8 lba_high_exp;
+ u8 features_exp;
+ u8 sector_count;
+ u8 sector_count_exp;
+ u8 res1;
+ u8 control;
+ u8 res2[4];
+} __attribute__((packed)) sata_fis_h2d_t;
+
+/*
+* Register - Host to Device FIS for read/write FPDMA queued
+*/
+typedef struct sata_fis_h2d_ncq
+{
+ u8 fis_type;
+ u8 pm_port_c;
+ u8 command;
+ u8 sector_count_low;
+ u8 lba_low;
+ u8 lba_mid;
+ u8 lba_high;
+ u8 device;
+ u8 lba_low_exp;
+ u8 lba_mid_exp;
+ u8 lba_high_exp;
+ u8 sector_count_high;
+ u8 tag;
+ u8 res1;
+ u8 res2;
+ u8 control;
+ u8 res3[4];
+} __attribute__((packed)) sata_fis_h2d_ncq_t;
+
+/*
+* Register - Device to Host FIS
+*/
+typedef struct sata_fis_d2h
+{
+ u8 fis_type;
+ u8 pm_port_i;
+ u8 status;
+ u8 error;
+ u8 lba_low;
+ u8 lba_mid;
+ u8 lba_high;
+ u8 device;
+ u8 lba_low_exp;
+ u8 lba_mid_exp;
+ u8 lba_high_exp;
+ u8 res1;
+ u8 sector_count;
+ u8 sector_count_exp;
+ u8 res2[2];
+ u8 res3[4];
+} __attribute__((packed)) sata_fis_d2h_t;
+
+/*
+* DMA Setup - Device to Host or Host to Device FIS
+*/
+typedef struct sata_fis_dma_setup
+{
+ u8 fis_type;
+ u8 pm_port_dir_int_act;
+ u8 res1;
+ u8 res2;
+ u32 dma_buffer_id_low;
+ u32 dma_buffer_id_high;
+ u32 res3;
+ u32 dma_buffer_offset;
+ u32 dma_transfer_count;
+ u32 res4;
+} __attribute__((packed)) sata_fis_dma_setup_t;
+
+/*
+* PIO Setup - Device to Host FIS
+*/
+typedef struct sata_fis_pio_setup
+{
+ u8 fis_type;
+ u8 pm_port_dir_int;
+ u8 status;
+ u8 error;
+ u8 lba_low;
+ u8 lba_mid;
+ u8 lba_high;
+ u8 res1;
+ u8 lba_low_exp;
+ u8 lba_mid_exp;
+ u8 lba_high_exp;
+ u8 res2;
+ u8 sector_count;
+ u8 sector_count_exp;
+ u8 res3;
+ u8 e_status;
+ u16 transfer_count;
+ u16 res4;
+} __attribute__((packed)) sata_fis_pio_setup_t;
+
+/*
+* Data - Host to Device or Device to Host FIS
+*/
+typedef struct sata_fis_data
+{
+ u8 fis_type;
+ u8 pm_port;
+ u8 res1;
+ u8 res2;
+ u32 data[2048];
+} __attribute__((packed)) sata_fis_data_t;
+
+/* fis_type - SATA FIS type
+ */
+enum sata_fis_type
+{
+ SATA_FIS_TYPE_REGISTER_H2D = 0x27,
+ SATA_FIS_TYPE_REGISTER_D2H = 0x34,
+ SATA_FIS_TYPE_DMA_ACT_D2H = 0x39,
+ SATA_FIS_TYPE_DMA_SETUP_BI = 0x41,
+ SATA_FIS_TYPE_DATA_BI = 0x46,
+ SATA_FIS_TYPE_BIST_ACT_BI = 0x58,
+ SATA_FIS_TYPE_PIO_SETUP_D2H = 0x5F,
+ SATA_FIS_TYPE_SET_DEVICE_BITS_D2H = 0xA1,
+};
+
+#endif /* __FIS_H__ */
diff --git a/bsp/ls2kdev/drivers/ata/libata.c b/bsp/ls2kdev/drivers/ata/libata.c
new file mode 100644
index 0000000000..980fc071fc
--- /dev/null
+++ b/bsp/ls2kdev/drivers/ata/libata.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2020-08-19 lizhirui porting to ls2k
+ */
+
+#include <rtthread.h>
+#include <ata_interface.h>
+#include <libata.h>
+
+u64 ata_id_n_sectors(u16 *id)
+{
+ if (ata_id_has_lba(id)) {
+ if (ata_id_has_lba48(id))
+ return ata_id_u64(id, ATA_ID_LBA48_SECTORS);
+ else
+ return ata_id_u32(id, ATA_ID_LBA_SECTORS);
+ } else {
+ return 0;
+ }
+}
+
+u32 ata_dev_classify(u32 sig)
+{
+ u8 lbam, lbah;
+
+ lbam = (sig >> 16) & 0xff;
+ lbah = (sig >> 24) & 0xff;
+
+ if (((lbam == 0) && (lbah == 0)) ||
+ ((lbam == 0x3c) && (lbah == 0xc3)))
+ return ATA_DEV_ATA;
+
+ if ((lbam == 0x14) && (lbah == 0xeb))
+ return ATA_DEV_ATAPI;
+
+ if ((lbam == 0x69) && (lbah == 0x96))
+ return ATA_DEV_PMP;
+
+ return ATA_DEV_UNKNOWN;
+}
+
+static void ata_id_string(const u16 *id, unsigned char *s,
+ unsigned int ofs, unsigned int len)
+{
+ unsigned int c;
+
+ while (len > 0) {
+ c = id[ofs] >> 8;
+ *s = c;
+ s++;
+
+ c = id[ofs] & 0xff;
+ *s = c;
+ s++;
+
+ ofs++;
+ len -= 2;
+ }
+}
+
+void ata_id_c_string(const u16 *id, unsigned char *s,
+ unsigned int ofs, unsigned int len)
+{
+ unsigned char *p;
+
+ ata_id_string(id, s, ofs, len - 1);
+
+ p = s + strnlen((char *)s, len - 1);
+ while (p > s && p[-1] == ' ')
+ p--;
+ *p = '\0';
+}
+
+void ata_dump_id(u16 *id)
+{
+ unsigned char serial[ATA_ID_SERNO_LEN + 1];
+ unsigned char firmware[ATA_ID_FW_REV_LEN + 1];
+ unsigned char product[ATA_ID_PROD_LEN + 1];
+ u64 n_sectors;
+
+ /* Serial number */
+ ata_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial));
+ printf("S/N: %s\n\r", serial);
+
+ /* Firmware version */
+ ata_id_c_string(id, firmware, ATA_ID_FW_REV, sizeof(firmware));
+ printf("Firmware version: %s\n\r", firmware);
+
+ /* Product model */
+ ata_id_c_string(id, product, ATA_ID_PROD, sizeof(product));
+ printf("Product model number: %s\n\r", product);
+
+ /* Total sectors of device */
+ n_sectors = ata_id_n_sectors(id);
+ printf("Capablity: %lld sectors\n\r", n_sectors);
+
+ printf ("id[49]: capabilities = 0x%04x\n"
+ "id[53]: field valid = 0x%04x\n"
+ "id[63]: mwdma = 0x%04x\n"
+ "id[64]: pio = 0x%04x\n"
+ "id[75]: queue depth = 0x%04x\n",
+ id[49],
+ id[53],
+ id[63],
+ id[64],
+ id[75]);
+
+ printf ("id[76]: sata capablity = 0x%04x\n"
+ "id[78]: sata features supported = 0x%04x\n"
+ "id[79]: sata features enable = 0x%04x\n",
+ id[76],
+ id[78],
+ id[79]);
+
+ printf ("id[80]: major version = 0x%04x\n"
+ "id[81]: minor version = 0x%04x\n"
+ "id[82]: command set supported 1 = 0x%04x\n"
+ "id[83]: command set supported 2 = 0x%04x\n"
+ "id[84]: command set extension = 0x%04x\n",
+ id[80],
+ id[81],
+ id[82],
+ id[83],
+ id[84]);
+ printf ("id[85]: command set enable 1 = 0x%04x\n"
+ "id[86]: command set enable 2 = 0x%04x\n"
+ "id[87]: command set default = 0x%04x\n"
+ "id[88]: udma = 0x%04x\n"
+ "id[93]: hardware reset result = 0x%04x\n",
+ id[85],
+ id[86],
+ id[87],
+ id[88],
+ id[93]);
+}
+
+void ata_swap_buf_le16(u16 *buf, unsigned int buf_words)
+{
+ unsigned int i;
+
+ for (i = 0; i < buf_words; i++)
+ {
+ buf[i] = le16_to_cpu(buf[i]);
+ }
+}
diff --git a/bsp/ls2kdev/drivers/ata/libata.h b/bsp/ls2kdev/drivers/ata/libata.h
new file mode 100644
index 0000000000..ae00c68446
--- /dev/null
+++ b/bsp/ls2kdev/drivers/ata/libata.h
@@ -0,0 +1,653 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2020-08-19 lizhirui porting to ls2k
+ */
+
+#ifndef __LIBATA_H__
+#define __LIBATA_H__
+
+enum {
+ /* various global constants */
+ ATA_MAX_DEVICES = 2, /* per bus/port */
+ ATA_MAX_PRD = 256, /* we could make these 256/256 */
+ ATA_SECT_SIZE = 512,
+ ATA_MAX_SECTORS_128 = 128,
+ ATA_MAX_SECTORS = 256,
+ ATA_MAX_SECTORS_LBA48 = 65535,
+ ATA_MAX_SECTORS_TAPE = 65535,
+
+ ATA_ID_WORDS = 256,
+ ATA_ID_SERNO = 10,
+ ATA_ID_FW_REV = 23,
+ ATA_ID_PROD = 27,
+ ATA_ID_OLD_PIO_MODES = 51,
+ ATA_ID_FIELD_VALID = 53,
+ ATA_ID_LBA_SECTORS = 60,
+ ATA_ID_MWDMA_MODES = 63,
+ ATA_ID_PIO_MODES = 64,
+ ATA_ID_EIDE_DMA_MIN = 65,
+ ATA_ID_EIDE_PIO = 67,
+ ATA_ID_EIDE_PIO_IORDY = 68,
+ ATA_ID_PIO4 = (1 << 1),
+ ATA_ID_QUEUE_DEPTH = 75,
+ ATA_ID_SATA_CAP = 76,
+ ATA_ID_SATA_FEATURES = 78,
+ ATA_ID_SATA_FEATURES_EN = 79,
+ ATA_ID_MAJOR_VER = 80,
+ ATA_ID_MINOR_VER = 81,
+ ATA_ID_UDMA_MODES = 88,
+ ATA_ID_LBA48_SECTORS = 100,
+
+ ATA_ID_SERNO_LEN = 20,
+ ATA_ID_FW_REV_LEN = 8,
+ ATA_ID_PROD_LEN = 40,
+
+ ATA_PCI_CTL_OFS = 2,
+
+ ATA_PIO0 = (1 << 0),
+ ATA_PIO1 = ATA_PIO0 | (1 << 1),
+ ATA_PIO2 = ATA_PIO1 | (1 << 2),
+ ATA_PIO3 = ATA_PIO2 | (1 << 3),
+ ATA_PIO4 = ATA_PIO3 | (1 << 4),
+ ATA_PIO5 = ATA_PIO4 | (1 << 5),
+ ATA_PIO6 = ATA_PIO5 | (1 << 6),
+
+ ATA_SWDMA0 = (1 << 0),
+ ATA_SWDMA1 = ATA_SWDMA0 | (1 << 1),
+ ATA_SWDMA2 = ATA_SWDMA1 | (1 << 2),
+
+ ATA_SWDMA2_ONLY = (1 << 2),
+
+ ATA_MWDMA0 = (1 << 0),
+ ATA_MWDMA1 = ATA_MWDMA0 | (1 << 1),
+ ATA_MWDMA2 = ATA_MWDMA1 | (1 << 2),
+
+ ATA_MWDMA12_ONLY = (1 << 1) | (1 << 2),
+ ATA_MWDMA2_ONLY = (1 << 2),
+
+ ATA_UDMA0 = (1 << 0),
+ ATA_UDMA1 = ATA_UDMA0 | (1 << 1),
+ ATA_UDMA2 = ATA_UDMA1 | (1 << 2),
+ ATA_UDMA3 = ATA_UDMA2 | (1 << 3),
+ ATA_UDMA4 = ATA_UDMA3 | (1 << 4),
+ ATA_UDMA5 = ATA_UDMA4 | (1 << 5),
+ ATA_UDMA6 = ATA_UDMA5 | (1 << 6),
+ ATA_UDMA7 = ATA_UDMA6 | (1 << 7),
+ /* ATA_UDMA7 is just for completeness... doesn't exist (yet?). */
+
+ ATA_UDMA_MASK_40C = ATA_UDMA2, /* udma0-2 */
+
+ /* DMA-related */
+ ATA_PRD_SZ = 8,
+ ATA_PRD_TBL_SZ = (ATA_MAX_PRD * ATA_PRD_SZ),
+ ATA_PRD_EOT = (1 << 31), /* end-of-table flag */
+
+ ATA_DMA_TABLE_OFS = 4,
+ ATA_DMA_STATUS = 2,
+ ATA_DMA_CMD = 0,
+ ATA_DMA_WR = (1 << 3),
+ ATA_DMA_START = (1 << 0),
+ ATA_DMA_INTR = (1 << 2),
+ ATA_DMA_ERR = (1 << 1),
+ ATA_DMA_ACTIVE = (1 << 0),
+
+ /* bits in ATA command block registers */
+ ATA_HOB = (1 << 7), /* LBA48 selector */
+ ATA_NIEN = (1 << 1), /* disable-irq flag */
+ ATA_LBA = (1 << 6), /* LBA28 selector */
+ ATA_DEV1 = (1 << 4), /* Select Device 1 (slave) */
+ ATA_DEVICE_OBS = (1 << 7) | (1 << 5), /* obs bits in dev reg */
+ ATA_DEVCTL_OBS = (1 << 3), /* obsolete bit in devctl reg */
+ ATA_BUSY = (1 << 7), /* BSY status bit */
+ ATA_DRDY = (1 << 6), /* device ready */
+ ATA_DF = (1 << 5), /* device fault */
+ ATA_DRQ = (1 << 3), /* data request i/o */
+ ATA_ERR = (1 << 0), /* have an error */
+ ATA_SRST = (1 << 2), /* software reset */
+ ATA_ICRC = (1 << 7), /* interface CRC error */
+ ATA_UNC = (1 << 6), /* uncorrectable media error */
+ ATA_IDNF = (1 << 4), /* ID not found */
+ ATA_ABORTED = (1 << 2), /* command aborted */
+
+ /* ATA command block registers */
+ ATA_REG_DATA = 0x00,
+ ATA_REG_ERR = 0x01,
+ ATA_REG_NSECT = 0x02,
+ ATA_REG_LBAL = 0x03,
+ ATA_REG_LBAM = 0x04,
+ ATA_REG_LBAH = 0x05,
+ ATA_REG_DEVICE = 0x06,
+ ATA_REG_STATUS = 0x07,
+
+ ATA_REG_FEATURE = ATA_REG_ERR, /* and their aliases */
+ ATA_REG_CMD = ATA_REG_STATUS,
+ ATA_REG_BYTEL = ATA_REG_LBAM,
+ ATA_REG_BYTEH = ATA_REG_LBAH,
+ ATA_REG_DEVSEL = ATA_REG_DEVICE,
+ ATA_REG_IRQ = ATA_REG_NSECT,
+
+ /* ATA device commands */
+ ATA_CMD_DEV_RESET = 0x08, /* ATAPI device reset */
+ ATA_CMD_PIO_READ = 0x20, /* Read sectors with retry */
+ ATA_CMD_PIO_READ_EXT = 0x24,
+ ATA_CMD_READ_EXT = 0x25,
+ ATA_CMD_READ_NATIVE_MAX_EXT = 0x27,
+ ATA_CMD_READ_MULTI_EXT = 0x29,
+ ATA_CMD_READ_LOG_EXT = 0x2f,
+ ATA_CMD_PIO_WRITE = 0x30, /* write sectors with retry */
+ ATA_CMD_PIO_WRITE_EXT = 0x34,
+ ATA_CMD_WRITE_EXT = 0x35,
+ ATA_CMD_SET_MAX_EXT = 0x37,
+ ATA_CMD_WRITE_MULTI_EXT = 0x39,
+ ATA_CMD_WRITE_FUA_EXT = 0x3D,
+ ATA_CMD_VERIFY = 0x40, /* read verify sectors with retry */
+ ATA_CMD_VERIFY_EXT = 0x42,
+ ATA_CMD_FPDMA_READ = 0x60,
+ ATA_CMD_FPDMA_WRITE = 0x61,
+ ATA_CMD_EDD = 0x90, /* execute device diagnostic */
+ ATA_CMD_INIT_DEV_PARAMS = 0x91, /* initialize device parameters */
+ ATA_CMD_PACKET = 0xA0, /* ATAPI packet */
+ ATA_CMD_ID_ATAPI = 0xA1, /* ATAPI identify device */
+ ATA_CMD_CONF_OVERLAY = 0xB1,
+ ATA_CMD_READ_MULTI = 0xC4, /* read multiple */
+ ATA_CMD_WRITE_MULTI = 0xC5, /* write multiple */
+ ATA_CMD_SET_MULTI = 0xC6, /* set multiple mode */
+ ATA_CMD_READ = 0xC8, /* read DMA with retry */
+ ATA_CMD_WRITE = 0xCA, /* write DMA with retry */
+ ATA_CMD_WRITE_MULTI_FUA_EXT = 0xCE,
+ ATA_CMD_STANDBYNOW1 = 0xE0, /* standby immediate */
+ ATA_CMD_IDLEIMMEDIATE = 0xE1, /* idle immediate */
+ ATA_CMD_STANDBY = 0xE2, /* place in standby power mode */
+ ATA_CMD_IDLE = 0xE3, /* place in idle power mode */
+ ATA_CMD_PMP_READ = 0xE4, /* read buffer */
+ ATA_CMD_CHK_POWER = 0xE5, /* check power mode */
+ ATA_CMD_SLEEP = 0xE6, /* sleep */
+ ATA_CMD_FLUSH = 0xE7,
+ ATA_CMD_PMP_WRITE = 0xE8, /* write buffer */
+ ATA_CMD_FLUSH_EXT = 0xEA,
+ ATA_CMD_ID_ATA = 0xEC, /* identify device */
+ ATA_CMD_SET_FEATURES = 0xEF, /* set features */
+ ATA_CMD_SEC_FREEZE_LOCK = 0xF5, /* security freeze */
+ ATA_CMD_READ_NATIVE_MAX = 0xF8,
+ ATA_CMD_SET_MAX = 0xF9,
+
+ /* READ_LOG_EXT pages */
+ ATA_LOG_SATA_NCQ = 0x10,
+
+ /* READ/WRITE LONG (obsolete) */
+ ATA_CMD_READ_LONG = 0x22,
+ ATA_CMD_READ_LONG_ONCE = 0x23,
+ ATA_CMD_WRITE_LONG = 0x32,
+ ATA_CMD_WRITE_LONG_ONCE = 0x33,
+
+ /* SETFEATURES stuff */
+ SETFEATURES_XFER = 0x03,
+ XFER_UDMA_7 = 0x47,
+ XFER_UDMA_6 = 0x46,
+ XFER_UDMA_5 = 0x45,
+ XFER_UDMA_4 = 0x44,
+ XFER_UDMA_3 = 0x43,
+ XFER_UDMA_2 = 0x42,
+ XFER_UDMA_1 = 0x41,
+ XFER_UDMA_0 = 0x40,
+ XFER_MW_DMA_4 = 0x24, /* CFA only */
+ XFER_MW_DMA_3 = 0x23, /* CFA only */
+ XFER_MW_DMA_2 = 0x22,
+ XFER_MW_DMA_1 = 0x21,
+ XFER_MW_DMA_0 = 0x20,
+ XFER_SW_DMA_2 = 0x12,
+ XFER_SW_DMA_1 = 0x11,
+ XFER_SW_DMA_0 = 0x10,
+ XFER_PIO_6 = 0x0E, /* CFA only */
+ XFER_PIO_5 = 0x0D, /* CFA only */
+ XFER_PIO_4 = 0x0C,
+ XFER_PIO_3 = 0x0B,
+ XFER_PIO_2 = 0x0A,
+ XFER_PIO_1 = 0x09,
+ XFER_PIO_0 = 0x08,
+ XFER_PIO_SLOW = 0x00,
+
+ SETFEATURES_WC_ON = 0x02, /* Enable write cache */
+ SETFEATURES_WC_OFF = 0x82, /* Disable write cache */
+
+ SETFEATURES_SPINUP = 0x07, /* Spin-up drive */
+
+ SETFEATURES_SATA_ENABLE = 0x10, /* Enable use of SATA feature */
+ SETFEATURES_SATA_DISABLE = 0x90, /* Disable use of SATA feature */
+
+ /* SETFEATURE Sector counts for SATA features */
+ SATA_AN = 0x05, /* Asynchronous Notification */
+ SATA_DIPM = 0x03, /* Device Initiated Power Management */
+
+ /* feature values for SET_MAX */
+ ATA_SET_MAX_ADDR = 0x00,
+ ATA_SET_MAX_PASSWD = 0x01,
+ ATA_SET_MAX_LOCK = 0x02,
+ ATA_SET_MAX_UNLOCK = 0x03,
+ ATA_SET_MAX_FREEZE_LOCK = 0x04,
+
+ /* feature values for DEVICE CONFIGURATION OVERLAY */
+ ATA_DCO_RESTORE = 0xC0,
+ ATA_DCO_FREEZE_LOCK = 0xC1,
+ ATA_DCO_IDENTIFY = 0xC2,
+ ATA_DCO_SET = 0xC3,
+
+ /* ATAPI stuff */
+ ATAPI_PKT_DMA = (1 << 0),
+ ATAPI_DMADIR = (1 << 2), /* ATAPI data dir:
+ 0=to device, 1=to host */
+ ATAPI_CDB_LEN = 16,
+
+ /* PMP stuff */
+ SATA_PMP_MAX_PORTS = 15,
+ SATA_PMP_CTRL_PORT = 15,
+
+ SATA_PMP_GSCR_DWORDS = 128,
+ SATA_PMP_GSCR_PROD_ID = 0,
+ SATA_PMP_GSCR_REV = 1,
+ SATA_PMP_GSCR_PORT_INFO = 2,
+ SATA_PMP_GSCR_ERROR = 32,
+ SATA_PMP_GSCR_ERROR_EN = 33,
+ SATA_PMP_GSCR_FEAT = 64,
+ SATA_PMP_GSCR_FEAT_EN = 96,
+
+ SATA_PMP_PSCR_STATUS = 0,
+ SATA_PMP_PSCR_ERROR = 1,
+ SATA_PMP_PSCR_CONTROL = 2,
+
+ SATA_PMP_FEAT_BIST = (1 << 0),
+ SATA_PMP_FEAT_PMREQ = (1 << 1),
+ SATA_PMP_FEAT_DYNSSC = (1 << 2),
+ SATA_PMP_FEAT_NOTIFY = (1 << 3),
+
+ /* cable types */
+ ATA_CBL_NONE = 0,
+ ATA_CBL_PATA40 = 1,
+ ATA_CBL_PATA80 = 2,
+ ATA_CBL_PATA40_SHORT = 3, /* 40 wire cable to high UDMA spec */
+ ATA_CBL_PATA_UNK = 4, /* don't know, maybe 80c? */
+ ATA_CBL_PATA_IGN = 5, /* don't know, ignore cable handling */
+ ATA_CBL_SATA = 6,
+
+ /* SATA Status and Control Registers */
+ SCR_STATUS = 0,
+ SCR_ERROR = 1,
+ SCR_CONTROL = 2,
+ SCR_ACTIVE = 3,
+ SCR_NOTIFICATION = 4,
+
+ /* SError bits */
+ SERR_DATA_RECOVERED = (1 << 0), /* recovered data error */
+ SERR_COMM_RECOVERED = (1 << 1), /* recovered comm failure */
+ SERR_DATA = (1 << 8), /* unrecovered data error */
+ SERR_PERSISTENT = (1 << 9), /* persistent data/comm error */
+ SERR_PROTOCOL = (1 << 10), /* protocol violation */
+ SERR_INTERNAL = (1 << 11), /* host internal error */
+ SERR_PHYRDY_CHG = (1 << 16), /* PHY RDY changed */
+ SERR_PHY_INT_ERR = (1 << 17), /* PHY internal error */
+ SERR_COMM_WAKE = (1 << 18), /* Comm wake */
+ SERR_10B_8B_ERR = (1 << 19), /* 10b to 8b decode error */
+ SERR_DISPARITY = (1 << 20), /* Disparity */
+ SERR_CRC = (1 << 21), /* CRC error */
+ SERR_HANDSHAKE = (1 << 22), /* Handshake error */
+ SERR_LINK_SEQ_ERR = (1 << 23), /* Link sequence error */
+ SERR_TRANS_ST_ERROR = (1 << 24), /* Transport state trans. error */
+ SERR_UNRECOG_FIS = (1 << 25), /* Unrecognized FIS */
+ SERR_DEV_XCHG = (1 << 26), /* device exchanged */
+
+ /* struct ata_taskfile flags */
+ ATA_TFLAG_LBA48 = (1 << 0), /* enable 48-bit LBA and "HOB" */
+ ATA_TFLAG_ISADDR = (1 << 1), /* enable r/w to nsect/lba regs */
+ ATA_TFLAG_DEVICE = (1 << 2), /* enable r/w to device reg */
+ ATA_TFLAG_WRITE = (1 << 3), /* data dir: host->dev==1 (write) */
+ ATA_TFLAG_LBA = (1 << 4), /* enable LBA */
+ ATA_TFLAG_FUA = (1 << 5), /* enable FUA */
+ ATA_TFLAG_POLLING = (1 << 6), /* set nIEN to 1 and use polling */
+
+ /* protocol flags */
+ ATA_PROT_FLAG_PIO = (1 << 0), /* is PIO */
+ ATA_PROT_FLAG_DMA = (1 << 1), /* is DMA */
+ ATA_PROT_FLAG_DATA = ATA_PROT_FLAG_PIO | ATA_PROT_FLAG_DMA,
+ ATA_PROT_FLAG_NCQ = (1 << 2), /* is NCQ */
+ ATA_PROT_FLAG_ATAPI = (1 << 3), /* is ATAPI */
+};
+
+enum ata_tf_protocols {
+ /* ATA taskfile protocols */
+ ATA_PROT_UNKNOWN, /* unknown/invalid */
+ ATA_PROT_NODATA, /* no data */
+ ATA_PROT_PIO, /* PIO data xfer */
+ ATA_PROT_DMA, /* DMA */
+ ATA_PROT_NCQ, /* NCQ */
+ ATAPI_PROT_NODATA, /* packet command, no data */
+ ATAPI_PROT_PIO, /* packet command, PIO data xfer*/
+ ATAPI_PROT_DMA, /* packet command with special DMA sauce */
+};
+
+enum ata_ioctls {
+ ATA_IOC_GET_IO32 = 0x309,
+ ATA_IOC_SET_IO32 = 0x324,
+};
+
+enum ata_dev_typed {
+ ATA_DEV_ATA, /* ATA device */
+ ATA_DEV_ATAPI, /* ATAPI device */
+ ATA_DEV_PMP, /* Port Multiplier Port */
+ ATA_DEV_UNKNOWN, /* unknown */
+};
+
+struct ata_taskfile {
+ unsigned long flags; /* ATA_TFLAG_xxx */
+ u8 protocol; /* ATA_PROT_xxx */
+
+ u8 ctl; /* control reg */
+
+ u8 hob_feature; /* additional data */
+ u8 hob_nsect; /* to support LBA48 */
+ u8 hob_lbal;
+ u8 hob_lbam;
+ u8 hob_lbah;
+
+ u8 feature;
+ u8 nsect;
+ u8 lbal;
+ u8 lbam;
+ u8 lbah;
+
+ u8 device;
+
+ u8 command; /* IO operation */
+};
+
+/*
+ * protocol tests
+ */
+static inline unsigned int ata_prot_flags(u8 prot)
+{
+ switch (prot) {
+ case ATA_PROT_NODATA:
+ return 0;
+ case ATA_PROT_PIO:
+ return ATA_PROT_FLAG_PIO;
+ case ATA_PROT_DMA:
+ return ATA_PROT_FLAG_DMA;
+ case ATA_PROT_NCQ:
+ return ATA_PROT_FLAG_DMA | ATA_PROT_FLAG_NCQ;
+ case ATAPI_PROT_NODATA:
+ return ATA_PROT_FLAG_ATAPI;
+ case ATAPI_PROT_PIO:
+ return ATA_PROT_FLAG_ATAPI | ATA_PROT_FLAG_PIO;
+ case ATAPI_PROT_DMA:
+ return ATA_PROT_FLAG_ATAPI | ATA_PROT_FLAG_DMA;
+ }
+ return 0;
+}
+
+static inline int ata_is_atapi(u8 prot)
+{
+ return ata_prot_flags(prot) & ATA_PROT_FLAG_ATAPI;
+}
+
+static inline int ata_is_nodata(u8 prot)
+{
+ return !(ata_prot_flags(prot) & ATA_PROT_FLAG_DATA);
+}
+
+static inline int ata_is_pio(u8 prot)
+{
+ return ata_prot_flags(prot) & ATA_PROT_FLAG_PIO;
+}
+
+static inline int ata_is_dma(u8 prot)
+{
+ return ata_prot_flags(prot) & ATA_PROT_FLAG_DMA;
+}
+
+static inline int ata_is_ncq(u8 prot)
+{
+ return ata_prot_flags(prot) & ATA_PROT_FLAG_NCQ;
+}
+
+static inline int ata_is_data(u8 prot)
+{
+ return ata_prot_flags(prot) & ATA_PROT_FLAG_DATA;
+}
+
+/*
+ * id tests
+ */
+#define ata_id_is_ata(id) (((id)[0] & (1 << 15)) == 0)
+#define ata_id_has_lba(id) ((id)[49] & (1 << 9))
+#define ata_id_has_dma(id) ((id)[49] & (1 << 8))
+#define ata_id_has_ncq(id) ((id)[76] & (1 << 8))
+#define ata_id_queue_depth(id) (((id)[75] & 0x1f) + 1)
+#define ata_id_removeable(id) ((id)[0] & (1 << 7))
+#define ata_id_iordy_disable(id) ((id)[49] & (1 << 10))
+#define ata_id_has_iordy(id) ((id)[49] & (1 << 11))
+
+#define ata_id_u32(id,n) \
+ (((u32) (id)[(n) + 1] << 16) | ((u32) (id)[(n)]))
+#define ata_id_u64(id,n) \
+ ( ((u64) (id)[(n) + 3] << 48) | \
+ ((u64) (id)[(n) + 2] << 32) | \
+ ((u64) (id)[(n) + 1] << 16) | \
+ ((u64) (id)[(n) + 0]) )
+
+#define ata_id_cdb_intr(id) (((id)[0] & 0x60) == 0x20)
+
+static inline int ata_id_has_fua(const u16 *id)
+{
+ if ((id[84] & 0xC000) != 0x4000)
+ return 0;
+ return id[84] & (1 << 6);
+}
+
+static inline int ata_id_has_flush(const u16 *id)
+{
+ if ((id[83] & 0xC000) != 0x4000)
+ return 0;
+ return id[83] & (1 << 12);
+}
+
+static inline int ata_id_has_flush_ext(const u16 *id)
+{
+ if ((id[83] & 0xC000) != 0x4000)
+ return 0;
+ return id[83] & (1 << 13);
+}
+
+static inline int ata_id_has_lba48(const u16 *id)
+{
+ if ((id[83] & 0xC000) != 0x4000)
+ return 0;
+ if (!ata_id_u64(id, 100))
+ return 0;
+ return id[83] & (1 << 10);
+}
+
+static inline int ata_id_hpa_enabled(const u16 *id)
+{
+ /* Yes children, word 83 valid bits cover word 82 data */
+ if ((id[83] & 0xC000) != 0x4000)
+ return 0;
+ /* And 87 covers 85-87 */
+ if ((id[87] & 0xC000) != 0x4000)
+ return 0;
+ /* Check command sets enabled as well as supported */
+ if ((id[85] & ( 1 << 10)) == 0)
+ return 0;
+ return id[82] & (1 << 10);
+}
+
+static inline int ata_id_has_wcache(const u16 *id)
+{
+ /* Yes children, word 83 valid bits cover word 82 data */
+ if ((id[83] & 0xC000) != 0x4000)
+ return 0;
+ return id[82] & (1 << 5);
+}
+
+static inline int ata_id_has_pm(const u16 *id)
+{
+ if ((id[83] & 0xC000) != 0x4000)
+ return 0;
+ return id[82] & (1 << 3);
+}
+
+static inline int ata_id_rahead_enabled(const u16 *id)
+{
+ if ((id[87] & 0xC000) != 0x4000)
+ return 0;
+ return id[85] & (1 << 6);
+}
+
+static inline int ata_id_wcache_enabled(const u16 *id)
+{
+ if ((id[87] & 0xC000) != 0x4000)
+ return 0;
+ return id[85] & (1 << 5);
+}
+
+static inline unsigned int ata_id_major_version(const u16 *id)
+{
+ unsigned int mver;
+
+ if (id[ATA_ID_MAJOR_VER] == 0xFFFF)
+ return 0;
+
+ for (mver = 14; mver >= 1; mver--)
+ if (id[ATA_ID_MAJOR_VER] & (1 << mver))
+ break;
+ return mver;
+}
+
+static inline int ata_id_is_sata(const u16 *id)
+{
+ return ata_id_major_version(id) >= 5 && id[93] == 0;
+}
+
+static inline int ata_id_has_tpm(const u16 *id)
+{
+ /* The TPM bits are only valid on ATA8 */
+ if (ata_id_major_version(id) < 8)
+ return 0;
+ if ((id[48] & 0xC000) != 0x4000)
+ return 0;
+ return id[48] & (1 << 0);
+}
+
+static inline int ata_id_has_dword_io(const u16 *id)
+{
+ /* ATA 8 reuses this flag for "trusted" computing */
+ if (ata_id_major_version(id) > 7)
+ return 0;
+ if (id[48] & (1 << 0))
+ return 1;
+ return 0;
+}
+
+static inline int ata_id_current_chs_valid(const u16 *id)
+{
+ /* For ATA-1 devices, if the INITIALIZE DEVICE PARAMETERS command
+ has not been issued to the device then the values of
+ id[54] to id[56] are vendor specific. */
+ return (id[53] & 0x01) && /* Current translation valid */
+ id[54] && /* cylinders in current translation */
+ id[55] && /* heads in current translation */
+ id[55] <= 16 &&
+ id[56]; /* sectors in current translation */
+}
+
+static inline int ata_id_is_cfa(const u16 *id)
+{
+ u16 v = id[0];
+ if (v == 0x848A) /* Standard CF */
+ return 1;
+ /* Could be CF hiding as standard ATA */
+ if (ata_id_major_version(id) >= 3 && id[82] != 0xFFFF &&
+ (id[82] & ( 1 << 2)))
+ return 1;
+ return 0;
+}
+
+static inline int ata_drive_40wire(const u16 *dev_id)
+{
+ if (ata_id_is_sata(dev_id))
+ return 0; /* SATA */
+ if ((dev_id[93] & 0xE000) == 0x6000)
+ return 0; /* 80 wire */
+ return 1;
+}
+
+static inline int ata_drive_40wire_relaxed(const u16 *dev_id)
+{
+ if ((dev_id[93] & 0x2000) == 0x2000)
+ return 0; /* 80 wire */
+ return 1;
+}
+
+static inline int atapi_cdb_len(const u16 *dev_id)
+{
+ u16 tmp = dev_id[0] & 0x3;
+ switch (tmp) {
+ case 0: return 12;
+ case 1: return 16;
+ default: return -1;
+ }
+}
+
+static inline int atapi_command_packet_set(const u16 *dev_id)
+{
+ return (dev_id[0] >> 8) & 0x1f;
+}
+
+static inline int atapi_id_dmadir(const u16 *dev_id)
+{
+ return ata_id_major_version(dev_id) >= 7 && (dev_id[62] & 0x8000);
+}
+
+static inline int is_multi_taskfile(struct ata_taskfile *tf)
+{
+ return (tf->command == ATA_CMD_READ_MULTI) ||
+ (tf->command == ATA_CMD_WRITE_MULTI) ||
+ (tf->command == ATA_CMD_READ_MULTI_EXT) ||
+ (tf->command == ATA_CMD_WRITE_MULTI_EXT) ||
+ (tf->command == ATA_CMD_WRITE_MULTI_FUA_EXT);
+}
+
+static inline int ata_ok(u8 status)
+{
+ return ((status & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | ATA_ERR))
+ == ATA_DRDY);
+}
+
+static inline int lba_28_ok(u64 block, u32 n_block)
+{
+ /* check the ending block number */
+ return ((block + n_block - 1) < ((u64)1 << 28)) && (n_block <= 256);
+}
+
+static inline int lba_48_ok(u64 block, u32 n_block)
+{
+ /* check the ending block number */
+ return ((block + n_block - 1) < ((u64)1 << 48)) && (n_block <= 65536);
+}
+
+#define sata_pmp_gscr_vendor(gscr) ((gscr)[SATA_PMP_GSCR_PROD_ID] & 0xffff)
+#define sata_pmp_gscr_devid(gscr) ((gscr)[SATA_PMP_GSCR_PROD_ID] >> 16)
+#define sata_pmp_gscr_rev(gscr) (((gscr)[SATA_PMP_GSCR_REV] >> 8) & 0xff)
+#define sata_pmp_gscr_ports(gscr) ((gscr)[SATA_PMP_GSCR_PORT_INFO] & 0xf)
+
+u64 ata_id_n_sectors(u16 *id);
+u32 ata_dev_classify(u32 sig);
+void ata_id_c_string(const u16 *id, unsigned char *s,
+ unsigned int ofs, unsigned int len);
+void ata_dump_id(u16 *id);
+void ata_swap_buf_le16(u16 *buf, unsigned int buf_words);
+
+#endif /* __LIBATA_H__ */
diff --git a/bsp/ls2kdev/drivers/board.c b/bsp/ls2kdev/drivers/board.c
index 20b7a84516..9b79902c41 100644
--- a/bsp/ls2kdev/drivers/board.c
+++ b/bsp/ls2kdev/drivers/board.c
@@ -12,18 +12,26 @@
#include <rthw.h>
#include "mips_regs.h"
+#include "mips_fpu.h"
#include "exception.h"
#include "drv_uart.h"
#include "board.h"
+#include "ls2k1000.h"
+
/**
* this function will reset CPU
*
*/
void rt_hw_cpu_reset(void)
{
+ WDT_EN = 0x01;
+ WDT_TIMER = 0x01;
+ WDT_SET = 0x01;
rt_kprintf("reboot system...\n");
while (1);
}
+MSH_CMD_EXPORT_ALIAS(rt_hw_cpu_reset, reboot, reset cpu);
+
/**
* this function will shutdown CPU
@@ -31,10 +39,13 @@ void rt_hw_cpu_reset(void)
*/
void rt_hw_cpu_shutdown(void)
{
+ PM1_STS &= 0xffffffff;
+ PM1_CNT = 0x3c00;
rt_kprintf("shutdown...\n");
while (1);
}
+MSH_CMD_EXPORT_ALIAS(rt_hw_cpu_shutdown, poweroff, shutdown cpu);
/**
@@ -56,7 +67,7 @@ void rt_hw_timer_handler(void)
*/
void rt_hw_timer_init(void)
{
- write_c0_compare(CPU_HZ/2/RT_TICK_PER_SECOND);
+ write_c0_compare(CPU_HZ / 2 / RT_TICK_PER_SECOND);
write_c0_count(0);
mips_unmask_cpu_irq(7);
}
@@ -79,16 +90,16 @@ void rt_hw_board_init(void)
/* init hardware UART device */
rt_hw_uart_init();
/* set console device */
- rt_console_set_device("uart");
+ rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
#endif
#ifdef RT_USING_HEAP
- rt_system_heap_init((void*)RT_HW_HEAP_BEGIN, (void*)RT_HW_HEAP_END);
+ rt_system_heap_init((void *)RT_HW_HEAP_BEGIN, (void *)RT_HW_HEAP_END);
#endif
/* init operating system timer */
rt_hw_timer_init();
-
+
#ifdef RT_USING_COMPONENTS_INIT
rt_components_board_init();
#endif
diff --git a/bsp/ls2kdev/drivers/board.h b/bsp/ls2kdev/drivers/board.h
index 6e2f85ec74..ca57ebf3f2 100644
--- a/bsp/ls2kdev/drivers/board.h
+++ b/bsp/ls2kdev/drivers/board.h
@@ -15,8 +15,8 @@
extern unsigned char __bss_end;
-#define CPU_HZ (100 * 1000 * 1000)
-#define RT_HW_HEAP_BEGIN KSEG1BASE//(void*)&__bss_end
+#define CPU_HZ (1000 * 1000 * 1000) //QEMU 200*1000*1000
+#define RT_HW_HEAP_BEGIN (void*)&__bss_end
#define RT_HW_HEAP_END (void*)(RT_HW_HEAP_BEGIN + 64 * 1024 * 1024)
void rt_hw_board_init(void);
diff --git a/bsp/ls2kdev/drivers/clk.c b/bsp/ls2kdev/drivers/clk.c
new file mode 100644
index 0000000000..b919713490
--- /dev/null
+++ b/bsp/ls2kdev/drivers/clk.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2017-09-06 勤为本 first version
+ *
+ * Copyright (c) 2020, duhuanpeng<[email protected]>
+ * legacy driver APIs from loongson 1C BSP.
+ */
+
+#include <rtthread.h>
+#include "ls2k1000.h"
+
+struct loongson_pll
+{
+ rt_uint64_t PLL_SYS_0;
+ rt_uint64_t PLL_SYS_1;
+ rt_uint64_t PLL_DDR_0;
+ rt_uint64_t PLL_DDR_1;
+ rt_uint64_t PLL_DC_0;
+ rt_uint64_t PLL_DC_1;
+ rt_uint64_t PLL_PIX0_0;
+ rt_uint64_t PLL_PIX0_1;
+ rt_uint64_t PLL_PIX1_0;
+ rt_uint64_t PLL_PIX1_1;
+ rt_uint64_t FREQSCALE;
+};
+
+/* See the Schematic */
+#define SYS_CLKSEL1 1
+#define SYS_CLKSEL0 0
+
+/* bit field helpers. */
+#define __M(n) (~(~0<<(n)))
+#define __RBF(number, n) ((number)&__M(n))
+#define __BF(number, n, m) __RBF((number>>m), (n-m+1))
+#define BF(number, n, m) (m<n ? __BF(number, n, m) : __BF(number, m, n))
+
+int refclk = 100;
+int gmac_clock = 125;
+
+volatile struct loongson_pll *pll = (void *)PLL_SYS_BASE;
+
+
+unsigned long clk_get_pll_rate(void)
+{
+ return -RT_ENOSYS;
+
+}
+
+unsigned long clk_get_cpu_rate(void)
+{
+ unsigned long node_clock;
+ int l1_div_ref;
+ int l1_div_loopc;
+ int l2_div_out_node;
+
+ l1_div_ref = BF(pll->PLL_SYS_0, 26, 31);
+ l1_div_loopc = BF(pll->PLL_SYS_0, 32, 41);
+ l2_div_out_node = BF(pll->PLL_SYS_1, 5, 0);
+
+ node_clock = refclk / l1_div_ref * l1_div_loopc / l2_div_out_node;
+ return node_clock;
+}
+
+unsigned long clk_get_ddr_rate(void)
+{
+ unsigned long ddr_clock;
+ int l1_div_ref;
+ int l1_div_loopc;
+ int l2_div_out_ddr;
+
+ l1_div_ref = BF(pll->PLL_DDR_0, 26, 31);
+ l1_div_loopc = BF(pll->PLL_DDR_0, 32, 41);
+ l2_div_out_ddr = BF(pll->PLL_DDR_1, 0, 5);
+
+ ddr_clock = refclk / l1_div_ref * l1_div_loopc / l2_div_out_ddr;
+ return ddr_clock;
+}
+
+unsigned long clk_get_apb_rate(void)
+{
+ unsigned long apb_clock;
+ int apb_freqscale;
+
+ apb_freqscale = BF(pll->FREQSCALE, 22, 20);
+
+ /* gmac clock is fixed 125MHz */
+ apb_clock = gmac_clock * (apb_freqscale + 1) / 8;
+ return apb_clock;
+
+}
+
+unsigned long clk_get_dc_rate(void)
+{
+ return -RT_ENOSYS;
+}
diff --git a/bsp/ls2kdev/drivers/clk.h b/bsp/ls2kdev/drivers/clk.h
new file mode 100644
index 0000000000..3a73da861c
--- /dev/null
+++ b/bsp/ls2kdev/drivers/clk.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2017-09-06 勤为本 first version
+ *
+ * Copyright (c) 2020, Du Huanpeng <[email protected]>
+ * base on bsp/ls1cdev/libraries/ls1c_clock.h
+ */
+
+#ifndef __LOONGSON_CLK_H__
+#define __LOONGSON_CLK_H__
+
+unsigned long clk_get_pll_rate(void);
+unsigned long clk_get_cpu_rate(void);
+unsigned long clk_get_ddr_rate(void);
+unsigned long clk_get_apb_rate(void);
+unsigned long clk_get_dc_rate(void);
+
+#endif
diff --git a/bsp/ls2kdev/drivers/drv_gpio.c b/bsp/ls2kdev/drivers/drv_gpio.c
index bcbecd9e2c..73a806afb2 100644
--- a/bsp/ls2kdev/drivers/drv_gpio.c
+++ b/bsp/ls2kdev/drivers/drv_gpio.c
@@ -5,28 +5,17 @@
* Change Logs:
* Date Author Notes
* 2015-01-20 Bernard the first version
- * 2017-10-20 ZYH add mode open drain and input pull down
- * 2020-06-01 Du Huanpeng GPIO driver based on <components/drivers/include/drivers/pin.h>
+ * 2017-10-20 ZYH add mode open drain and input pull down
+ * 2020-06-01 Du Huanpeng GPIO driver based on <components/drivers/include/drivers/pin.h>
*/
-
-
#include <rtthread.h>
#include <drivers/pin.h>
-#include <rthw.h>
#include <ls2k1000.h>
-
-struct loongson_gpio {
- rt_uint64_t GPIO0_OEN;
- rt_uint64_t GPIO1_OEN; /* Reserved */
- rt_uint64_t GPIO0_O;
- rt_uint64_t GPIO1_O; /* Reserved */
- rt_uint64_t GPIO0_I;
- rt_uint64_t GPIO1_I; /* Reserved */
- rt_uint64_t GPIO0_INTEN;
- rt_uint64_t GPIO1_INTEN; /* Reserved */
-};
+#include "drv_gpio.h"
#ifdef RT_USING_PIN
+#define GPIO_IRQ_NUM (64)
+static struct gpio_irq_def _g_gpio_irq_tbl[GPIO_IRQ_NUM];
static void loongson_pin_mode(struct rt_device *device, rt_base_t pin, rt_base_t mode)
{
@@ -36,7 +25,8 @@ static void loongson_pin_mode(struct rt_device *device, rt_base_t pin, rt_base_t
gpio = (void *)device->user_data;
m = (rt_uint64_t)1 << pin;
- switch (mode) {
+ switch (mode)
+ {
case PIN_MODE_OUTPUT:
gpio->GPIO0_OEN &= ~m;
break;
@@ -63,7 +53,8 @@ static void loongson_pin_write(struct rt_device *device, rt_base_t pin, rt_base_
struct loongson_gpio *gpio;
rt_uint64_t m;
- if (pin < 0 || pin >= 60) {
+ if (pin < 0 || pin >= 60)
+ {
rt_kprintf("error\n");
return;
}
@@ -84,7 +75,7 @@ static int loongson_pin_read(struct rt_device *device, rt_base_t pin)
gpio = (void *)device->user_data;
rt_uint64_t m;
- m = gpio->GPIO1_I;
+ m = gpio->GPIO0_I;
m &= (rt_uint64_t)1 << pin;
rc = !!m;
@@ -92,13 +83,36 @@ static int loongson_pin_read(struct rt_device *device, rt_base_t pin)
return rc;
}
- /* TODO: add GPIO interrupt */
+/* TODO: add GPIO interrupt */
static rt_err_t loongson_pin_attach_irq(struct rt_device *device, rt_int32_t pin, rt_uint32_t mode, void (*hdr)(void *args), void *args)
{
+ rt_uint8_t index;
+ rt_uint64_t m;
struct loongson_gpio *gpio;
gpio = (void *)device->user_data;
+ if (pin < 4)
+ {
+ index = pin;
+ }
+ else if (pin < 32)
+ {
+ index = 5;
+ }
+ else
+ {
+ index = 6;
+ }
+
+ _g_gpio_irq_tbl[index].irq_cb[pin] = hdr;
+ _g_gpio_irq_tbl[index].irq_arg[pin] = args;
+ _g_gpio_irq_tbl[index].irq_type[pin] = mode;
+
+ liointc_set_irq_mode(index, mode);
+ m = (rt_uint64_t)1 << pin;
+ gpio->GPIO0_INTEN |= m;
+
return RT_EOK;
}
static rt_err_t loongson_pin_detach_irq(struct rt_device *device, rt_int32_t pin)
@@ -107,6 +121,24 @@ static rt_err_t loongson_pin_detach_irq(struct rt_device *device, rt_int32_t pin
gpio = (void *)device->user_data;
+ rt_uint8_t index;
+ if (pin < 4)
+ {
+ index = pin;
+ }
+ else if (pin < 32)
+ {
+ index = 5;
+ }
+ else
+ {
+ index = 6;
+ }
+ _g_gpio_irq_tbl[index].irq_cb[pin] = RT_NULL;
+ _g_gpio_irq_tbl[index].irq_arg[pin] = RT_NULL;
+ _g_gpio_irq_tbl[index].irq_type[pin] = RT_NULL;
+ _g_gpio_irq_tbl[index].state[pin] = RT_NULL;
+
return RT_EOK;
}
static rt_err_t loongson_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled)
@@ -115,11 +147,75 @@ static rt_err_t loongson_pin_irq_enable(struct rt_device *device, rt_base_t pin,
gpio = (void *)device->user_data;
+ rt_uint8_t index;
+ if (pin < 4)
+ {
+ index = pin;
+ }
+ else if (pin < 32)
+ {
+ index = 5;
+ }
+ else
+ {
+ index = 6;
+ }
+
+ if (enabled)
+ _g_gpio_irq_tbl[index].state[pin] = 1;
+ else
+ _g_gpio_irq_tbl[index].state[pin] = 0;
return RT_EOK;
}
+static void gpio_irq_handler(int irq, void *param)
+{
+ struct gpio_irq_def *irq_def = (struct gpio_irq_def *)param;
+ rt_uint32_t pin;
+ rt_uint32_t value;
+ rt_uint32_t tmpvalue;
+
+ if (irq == LS2K_GPIO0_INT_IRQ)
+ {
+ pin = 0;
+ }
+ else if (irq == LS2K_GPIO1_INT_IRQ)
+ {
+ pin = 1;
+ }
+ else if (irq == LS2K_GPIO2_INT_IRQ)
+ {
+ pin = 2;
+ }
+ else if (irq == LS2K_GPIO3_INT_IRQ)
+ {
+ pin = 3;
+ }
+ else if (irq == LS2K_GPIO_INTLO_IRQ)
+ {
+ pin = 4;
+ }
+ else
+ {
+ pin = 32;
+ }
+
+ while (value)
+ {
+ if ((value & 0x1) && (irq_def->irq_cb[pin] != RT_NULL))
+ {
+ if (irq_def->state[pin])
+ {
+ irq_def->irq_cb[pin](irq_def->irq_arg[pin]);
+ }
+ }
+ pin++;
+ value = value >> 1;
+ }
+}
-static struct rt_pin_ops loongson_pin_ops = {
+static struct rt_pin_ops loongson_pin_ops =
+{
.pin_mode = loongson_pin_mode,
.pin_write = loongson_pin_write,
.pin_read = loongson_pin_read,
@@ -128,6 +224,7 @@ static struct rt_pin_ops loongson_pin_ops = {
.pin_attach_irq = loongson_pin_attach_irq,
.pin_detach_irq = loongson_pin_detach_irq,
.pin_irq_enable = loongson_pin_irq_enable,
+ .pin_get = RT_NULL,
};
@@ -139,6 +236,30 @@ int loongson_pin_init(void)
loongson_gpio_priv = (void *)GPIO_BASE;
rc = rt_device_pin_register("pin", &loongson_pin_ops, loongson_gpio_priv);
+ //gpio0
+ rt_hw_interrupt_install(LS2K_GPIO0_INT_IRQ, gpio_irq_handler, &_g_gpio_irq_tbl[0], "gpio0_irq");
+ rt_hw_interrupt_umask(LS2K_GPIO0_INT_IRQ);
+
+ //gpio1
+ rt_hw_interrupt_install(LS2K_GPIO1_INT_IRQ, gpio_irq_handler, &_g_gpio_irq_tbl[1], "gpio1_irq");
+ rt_hw_interrupt_umask(LS2K_GPIO1_INT_IRQ);
+
+ //gpio2
+ rt_hw_interrupt_install(LS2K_GPIO2_INT_IRQ, gpio_irq_handler, &_g_gpio_irq_tbl[2], "gpio2_irq");
+ rt_hw_interrupt_umask(LS2K_GPIO2_INT_IRQ);
+
+ //gpio3
+ rt_hw_interrupt_install(LS2K_GPIO3_INT_IRQ, gpio_irq_handler, &_g_gpio_irq_tbl[3], "gpio3_irq");
+ rt_hw_interrupt_umask(LS2K_GPIO3_INT_IRQ);
+
+ //gpio4~gpio31
+ rt_hw_interrupt_install(LS2K_GPIO_INTLO_IRQ, gpio_irq_handler, &_g_gpio_irq_tbl[4], "gpio4_irq");
+ rt_hw_interrupt_umask(LS2K_GPIO_INTLO_IRQ);
+
+ //gpio32~gpio63
+ rt_hw_interrupt_install(LS2K_GPIO_INTHI_IRQ, gpio_irq_handler, &_g_gpio_irq_tbl[5], "gpio5_irq");
+ rt_hw_interrupt_umask(LS2K_GPIO_INTHI_IRQ);
+
return rc;
}
INIT_BOARD_EXPORT(loongson_pin_init);
diff --git a/bsp/ls2kdev/drivers/drv_gpio.h b/bsp/ls2kdev/drivers/drv_gpio.h
index 6d505c1294..4bf1ba80f5 100644
--- a/bsp/ls2kdev/drivers/drv_gpio.h
+++ b/bsp/ls2kdev/drivers/drv_gpio.h
@@ -6,16 +6,35 @@
*
* Change Logs:
* Date Author Notes
- * 2017-11-24 勤为本 first version
+ * 2017-11-24 勤为本 first version
* 2018-05-11 zhuangwei add gpio interrupt ops
*/
#ifndef __DRV_GPIO_H__
#define __DRV_GPIO_H__
+#include <rthw.h>
-int loongson_pin_init(void);
+struct gpio_irq_def
+{
+ void *irq_arg[32];
+ void (*irq_cb[32])(void *param);
+ rt_uint8_t irq_type[32];
+ rt_uint8_t state[32];
+};
+
+struct loongson_gpio {
+ rt_uint64_t GPIO0_OEN;
+ rt_uint64_t GPIO1_OEN; /* Reserved */
+ rt_uint64_t GPIO0_O;
+ rt_uint64_t GPIO1_O; /* Reserved */
+ rt_uint64_t GPIO0_I;
+ rt_uint64_t GPIO1_I; /* Reserved */
+ rt_uint64_t GPIO0_INTEN;
+ rt_uint64_t GPIO1_INTEN; /* Reserved */
+};
+int loongson_pin_init(void);
#endif
diff --git a/bsp/ls2kdev/drivers/drv_pwm.c b/bsp/ls2kdev/drivers/drv_pwm.c
new file mode 100644
index 0000000000..1b5c98755d
--- /dev/null
+++ b/bsp/ls2kdev/drivers/drv_pwm.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Copyright(c) 2020, Du Huanpeng<[email protected]>
+ *
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <ls2k1000.h>
+
+#ifdef RT_USING_PWM
+
+#define PWM0_BASE (0xFFFFFFFFBFe02000)
+#define PWM1_BASE (0xFFFFFFFFBFe02010)
+#define PWM2_BASE (0xFFFFFFFFBFe02020)
+#define PWM3_BASE (0xFFFFFFFFBFe02030)
+
+#define CTRL_EN (1UL<<0)
+#define CTRL_OE (1UL<<3)
+#define CTRL_SINGL (1UL<<4)
+#define CTRL_INTE (1UL<<5)
+#define CTRL_INT (1UL<<6)
+#define CTRL_RST (1UL<<7)
+#define CTRL_CAPTE (1UL<<8)
+#define CTRL_INVERT (1UL<<9)
+#define CTRL_DZONE (1UL<<10)
+
+struct loongson_pwm
+{
+ rt_uint32_t __PAD0;
+ rt_uint32_t low_buffer;
+ rt_uint32_t full_buffer;
+ rt_uint32_t ctrl;
+};
+
+rt_err_t loongson_pwm_enable(struct rt_device_pwm *device, int channel)
+{
+ int **priv;
+ struct loongson_pwm *chip;
+ volatile rt_uint64_t *config0;
+ rt_uint64_t m;
+
+ channel %= 4;
+
+ config0 = (void *)GEN_CONFIG0_REG;
+ m = 1ULL << 12 << channel;
+ *config0 |= m;
+
+ priv = device->parent.user_data;
+ chip = (void *)priv[channel];
+ chip->ctrl = CTRL_EN;
+
+ return RT_EOK;
+}
+
+rt_err_t loongson_pwm_disable(struct rt_device_pwm *device, int channel)
+{
+ struct loongson_pwm **chip;
+ rt_uint64_t m;
+
+ chip = device->parent.user_data;
+ channel %= 4;
+ chip[channel]->ctrl &= ~CTRL_EN;
+
+ return RT_EOK;
+}
+
+rt_err_t loongson_pwm_set(struct rt_device_pwm *device, int channel, rt_uint32_t period, rt_uint32_t pulse)
+{
+ struct loongson_pwm *chip;
+ rt_uint32_t **priv;
+
+ priv = device->parent.user_data;
+ channel %= 4;
+ chip = (void *)priv[channel];
+
+ chip->ctrl &= ~CTRL_EN;
+ chip->full_buffer = period;
+ chip->low_buffer = pulse;
+ chip->ctrl |= CTRL_EN;
+
+ return RT_EOK;
+}
+
+static rt_err_t loongson_pwm_ioctl(struct rt_device_pwm *device, int cmd, void *arg)
+{
+ rt_err_t rc;
+ struct rt_pwm_configuration *cfg;
+
+ cfg = (void *)arg;
+
+ switch (cmd)
+ {
+ case PWM_CMD_ENABLE:
+ rc = loongson_pwm_enable(device, cfg->channel);
+ break;
+ case PWM_CMD_DISABLE:
+ rc = loongson_pwm_disable(device, cfg->channel);
+ break;
+ case PWM_CMD_SET:
+ rc = loongson_pwm_set(device, cfg->channel, cfg->period, cfg->pulse);
+ break;
+ case PWM_CMD_GET:
+ rc = RT_ENOSYS;
+ break;
+ default:
+ rc = RT_EINVAL;
+ break;
+ }
+ return rc;
+}
+
+struct rt_pwm_ops loongson_pwm_ops =
+{
+ .control = loongson_pwm_ioctl,
+};
+
+struct rt_device_pwm loongson_pwm =
+{
+ .ops = &loongson_pwm_ops,
+};
+
+int loongson_pwm_init(void)
+{
+ int rc = RT_EOK;
+ static rt_uint32_t *priv[] =
+ {
+ (void *)PWM0_BASE,
+ (void *)PWM1_BASE,
+ (void *)PWM2_BASE,
+ (void *)PWM3_BASE
+ };
+ rc = rt_device_pwm_register(&loongson_pwm, "pwm0", &loongson_pwm_ops, &priv);
+ return rc;
+}
+INIT_DEVICE_EXPORT(loongson_pwm_init);
+
+#endif /*RT_USING_PWM*/
diff --git a/bsp/ls2kdev/drivers/drv_rtc.c b/bsp/ls2kdev/drivers/drv_rtc.c
new file mode 100644
index 0000000000..3cea0288be
--- /dev/null
+++ b/bsp/ls2kdev/drivers/drv_rtc.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ * Copyright (c) 2020, Du Huanpeng <[email protected]>
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2018-01-30 armink the first version
+ * 2020-06-23 Du Huanpeng based on components/drivers/rtc/soft_rtc.c
+ */
+
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <sys/time.h>
+#include "ls2k1000.h"
+
+#ifdef RT_USING_RTC
+
+struct loongson_rtc
+{
+ rt_uint32_t sys_toytrim;
+ rt_uint32_t sys_toywrite0;
+ rt_uint32_t sys_toywrite1;
+ rt_uint32_t sys_toyread0;
+ rt_uint32_t sys_toyread1;
+ rt_uint32_t sys_toymatch0;
+ rt_uint32_t sys_toymatch1;
+ rt_uint32_t sys_toymatch2;
+ rt_uint32_t sys_rtcctrl;
+ rt_uint32_t __pad4[3];
+ rt_uint32_t __pad5[4];
+ rt_uint32_t sys_rtctrim;
+ rt_uint32_t sys_rtcwrite0;
+ rt_uint32_t sys_rtcread0;
+ rt_uint32_t sys_rtcmatch0;
+ rt_uint32_t sys_rtcmatch1;
+ rt_uint32_t sys_rtcmatch2;
+};
+
+/* bit field helpers. */
+#define __M(n) (~(~0<<(n)))
+#define __RBF(number, n) ((number)&__M(n))
+#define __BF(number, n, m) __RBF((number>>m), (n-m+1))
+#define BF(number, n, m) (m<n ? __BF(number, n, m) : __BF(number, m, n))
+
+struct rtctime
+{
+ rt_uint32_t sys_toyread0;
+ rt_uint32_t sys_toyread1;
+ rt_uint32_t sys_rtcread0;
+};
+typedef struct rtctime rtctime_t;
+
+struct tm *localrtctime(const rtctime_t *rtctp)
+{
+ static struct tm time;
+ int msec;
+
+ msec = BF(rtctp->sys_toyread0, 3, 0);
+ msec *= 100;
+
+ time.tm_sec = BF(rtctp->sys_toyread0, 9, 4);
+ time.tm_min = BF(rtctp->sys_toyread0, 15, 10);
+ time.tm_hour = BF(rtctp->sys_toyread0, 20, 16);
+ time.tm_mday = BF(rtctp->sys_toyread0, 21, 25);
+ time.tm_mon = BF(rtctp->sys_toyread0, 26, 31);
+ /* struct tm has three more members:
+ time.tm_isdst
+ time.tm_wday
+ time.tm_yday
+ */
+ time.tm_mon -= 1;
+ time.tm_year = rtctp->sys_toyread1;
+ return &time;
+}
+
+rtctime_t mkrtctime(struct tm *tm)
+{
+ rtctime_t rtctm;
+ struct tm tmptime;
+
+ rtctm.sys_toyread0 <<= 31 - 26 + 1;
+ rtctm.sys_toyread0 |= tm->tm_mon + 1;
+ rtctm.sys_toyread0 <<= 25 - 21 + 1;
+ rtctm.sys_toyread0 |= tm->tm_mday;
+ rtctm.sys_toyread0 <<= 20 - 16 + 1;
+ rtctm.sys_toyread0 |= tm->tm_hour;
+ rtctm.sys_toyread0 <<= 15 - 10 + 1;
+ rtctm.sys_toyread0 |= tm->tm_min;
+ rtctm.sys_toyread0 <<= 9 - 4 + 1;
+ rtctm.sys_toyread0 |= tm->tm_sec;
+ /* Fixme: 0.1 second */
+ rtctm.sys_toyread0 <<= 3 - 0 + 1;
+ rtctm.sys_toyread0 |= 0;
+
+ rtctm.sys_toyread1 = tm->tm_year;
+
+ tmptime = *localrtctime(&rtctm);
+
+ return rtctm;
+}
+
+static rt_err_t rt_rtc_open(rt_device_t dev, rt_uint16_t oflag)
+{
+ return RT_EOK;
+}
+
+static rt_size_t rt_rtc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
+{
+ return 0;
+}
+
+static rt_err_t rt_rtc_ioctl(rt_device_t dev, int cmd, void *args)
+{
+ rt_err_t err = RT_ENOSYS;
+
+ static int count = 0;
+
+ struct loongson_rtc *hw_rtc;
+ rtctime_t rtctm;
+ struct tm time;
+ struct tm tmptime;
+ time_t *t;
+
+ hw_rtc = dev->user_data;
+
+ t = (time_t *)args;
+ time = *gmtime(t);
+
+ rtctm.sys_toyread0 = hw_rtc->sys_toyread0;
+ rtctm.sys_toyread1 = hw_rtc->sys_toyread1;
+ rtctm.sys_rtcread0 = hw_rtc->sys_rtcread0;
+ tmptime = *localrtctime(&rtctm);
+
+ switch (cmd)
+ {
+ case RT_DEVICE_CTRL_RTC_GET_TIME:
+ *t = timegm(&tmptime);
+ break;
+ case RT_DEVICE_CTRL_RTC_SET_TIME:
+ tmptime.tm_hour = time.tm_hour;
+ tmptime.tm_min = time.tm_min;
+ tmptime.tm_sec = time.tm_sec;
+
+ tmptime.tm_year = time.tm_year;
+ tmptime.tm_mon = time.tm_mon;
+ tmptime.tm_mday = time.tm_mday;
+
+ rtctm = mkrtctime(&tmptime);
+ /* write to hw RTC */
+ hw_rtc->sys_toywrite0 = rtctm.sys_toyread0;
+ hw_rtc->sys_toywrite1 = rtctm.sys_toyread1;
+ break;
+ case RT_DEVICE_CTRL_RTC_GET_ALARM:
+ break;
+ case RT_DEVICE_CTRL_RTC_SET_ALARM:
+ break;
+ default:
+ break;
+ }
+
+ return RT_EOK;
+}
+
+int rt_hw_rtc_init(void)
+{
+ static struct rt_device rtc =
+ {
+ .type = RT_Device_Class_RTC,
+ .init = RT_NULL,
+ .open = rt_rtc_open,
+ .close = RT_NULL,
+ .read = rt_rtc_read,
+ .write = RT_NULL,
+ .control = rt_rtc_ioctl,
+ .user_data = (void *)RTC_BASE,
+ };
+ rt_device_register(&rtc, "rtc", RT_DEVICE_FLAG_RDWR);
+}
+
+INIT_DEVICE_EXPORT(rt_hw_rtc_init);
+
+#endif /*RT_USING_RTC*/
diff --git a/bsp/ls2kdev/drivers/drv_spi.c b/bsp/ls2kdev/drivers/drv_spi.c
new file mode 100644
index 0000000000..5a42acbee8
--- /dev/null
+++ b/bsp/ls2kdev/drivers/drv_spi.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2020-10-28 0xcccccccccccc Initial Version
+ * 2021-01-17 0xcccccccccccc Bug Fixed : clock division cannot been adjusted as expected due to wrong register configuration.
+ */
+/**
+ * @addtogroup ls2k
+ */
+/*@{*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <rtthread.h>
+#include <drivers/spi.h>
+#include "drv_spi.h"
+
+#ifdef RT_USING_SPI
+static void spi_init(uint8_t spre_spr, uint8_t copl, uint8_t cpha)
+{
+ SET_SPI(SPSR, 0xc0);
+ SET_SPI(PARAM, 0x40);
+ SET_SPI(PARAM2, 0x01);
+ SET_SPI(SPER, (spre_spr & 0b00001100) >> 2);
+ SET_SPI(SPCR, 0x50 | copl << 3 | cpha << 2 | (spre_spr & 0b00000011));
+ SET_SPI(SOFTCS, 0xff);
+}
+
+static void spi_set_csn(uint8_t val)
+{
+ SET_SPI(SOFTCS, val);
+}
+
+#ifdef RT_USING_SPI_GPIOCS
+ #include <drivers/pin.h>
+#endif
+static void spi_set_cs(unsigned char cs, int new_status)
+{
+ if (cs < 4)
+ {
+ unsigned char val = 0;
+ val = GET_SPI(SOFTCS);
+ val |= 0x01 << cs ; // csen=1
+ if (new_status) // cs = 1
+ {
+ val |= (0x10 << cs); // csn=1
+ }
+ else // cs = 0
+ {
+ val &= ~(0x10 << cs); // csn=0
+ }
+ SET_SPI(SOFTCS, val);
+ return ;
+ }
+#ifdef RT_USING_SPI_GPIOCS
+ else
+ {
+ rt_pin_mode(cs, PIN_MODE_OUTPUT); // with RT_USING_SPI_GPIOCS feature enabled, gpio will be used as csn pin.
+ rt_pin_write(cs, new_status);
+ }
+#endif
+}
+static uint8_t spi_write_for_response(uint8_t data)
+{
+ uint8_t val;
+ SET_SPI(TXFIFO, data);
+ while ((GET_SPI(SPSR))&RFEMPTY); //wait for echo
+ val = GET_SPI(RXFIFO);
+ return val;
+}
+
+static int cmd_spi_init(int argc, char *argv[])
+{
+ uint8_t spre_spr, cpol, cpha;
+ switch (argc)
+ {
+ case 2:
+ spre_spr = strtoul(argv[1], NULL, 0);
+ spi_init(spre_spr, 0, 0);
+ break;
+ case 4:
+ spre_spr = strtoul(argv[1], NULL, 0);
+ cpol = strtoul(argv[2], NULL, 0);
+ cpha = strtoul(argv[3], NULL, 0);
+ spi_init(spre_spr, 0, 0);
+ break;
+ default:
+ printf("\nusage : cmd_spi_init spre_spr <cpol> <cpha>\n(cmd_spi_init 0x4 0x0 0x0)\n0x4:div8 0xb:div4096\n");
+ break;
+ }
+}
+MSH_CMD_EXPORT(cmd_spi_init, cmd_spi_init);
+static int cmd_spi_set_csn(int argc, char *argv[])
+{
+ uint8_t val, csn;
+ switch (argc)
+ {
+ case 3:
+ csn = strtoul(argv[1], NULL, 0);
+ val = strtoul(argv[2], NULL, 0);
+ spi_set_cs(csn, val);
+ break;
+ default:
+ printf("usage:cmd_spi_set_csn csn val\n(0xbf for csn1 enable,0xff for csn1 disable)\n");
+ break;
+ }
+}
+MSH_CMD_EXPORT(cmd_spi_set_csn, cmd_spi_set_csn);
+static int cmd_spi_write(int argc, char *argv[])
+{
+ uint8_t data, resp;
+ switch (argc)
+ {
+ case 2:
+ data = strtoul(argv[1], NULL, 0);
+ resp = spi_write_for_response(data);
+ printf("resp:%2X\n", resp);
+ break;
+ default:
+ printf("usage:cmd_spi_write data\n");
+ break;
+ }
+}
+MSH_CMD_EXPORT(cmd_spi_write, cmd_spi_write);
+
+static rt_err_t configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration);
+static rt_uint32_t xfer(struct rt_spi_device *device, struct rt_spi_message *message);
+const static unsigned char SPI_DIV_TABLE[] = {0b0000, 0b0001, 0b0100, 0b0010, 0b0011, 0b0101, 0b0110, 0b0111, 0b1000, 0b1001, 0b1010, 0b1011};
+// 2 4 8 16 32 64 128 256 512 1024 2048 4096
+static rt_err_t configure(struct rt_spi_device *device,
+ struct rt_spi_configuration *configuration)
+{
+
+ unsigned char cpol = 0;
+ unsigned char cpha = 0;
+
+ RT_ASSERT(NULL != device);
+ RT_ASSERT(NULL != configuration);
+
+ // baudrate
+ if (configuration->mode & RT_SPI_CPOL) // cpol
+ {
+ cpol = 1;
+ }
+ else
+ {
+ cpol = 0;
+ }
+ if (configuration->mode & RT_SPI_CPHA) // cpha
+ {
+ cpha = 1;
+ }
+ else
+ {
+ cpha = 0;
+ }
+
+ float spi_max_speed = ((float)APB_MAX_SPEED) / (8.0 / (float)APB_FREQSCALE);
+ uint64_t div = (uint64_t)(spi_max_speed / (float)configuration->max_hz);
+ int ctr = 0;
+ while (div != 1 && ctr < 12)
+ {
+ ctr++;
+ div = div >> 1;
+ }
+ spi_init(SPI_DIV_TABLE[ctr], cpol, cpha);
+
+ return RT_EOK;
+}
+static rt_uint32_t xfer(struct rt_spi_device *device,
+ struct rt_spi_message *message)
+{
+
+ unsigned char cs = 0;
+ rt_uint32_t size = 0;
+ const rt_uint8_t *send_ptr = NULL;
+ rt_uint8_t *recv_ptr = NULL;
+ rt_uint8_t data = 0;
+ RT_ASSERT(NULL != device);
+ RT_ASSERT(NULL != message);
+ cs = (unsigned char)(device->parent.user_data);
+ size = message->length;
+ if (message->cs_take)
+ {
+ spi_set_cs(cs, 0);
+ }
+ // send data
+ send_ptr = message->send_buf;
+ recv_ptr = message->recv_buf;
+ while (size--)
+ {
+ data = 0xFF;
+ if (NULL != send_ptr)
+ {
+ data = *send_ptr++;
+ }
+ if (NULL != recv_ptr)
+ {
+ *recv_ptr++ = spi_write_for_response(data);
+ }
+ else
+ {
+ spi_write_for_response(data);
+ }
+ }
+ // release cs
+ if (message->cs_release)
+ {
+ spi_set_cs(cs, 1);
+ }
+ return message->length;
+}
+static struct rt_spi_ops loongson_spi_ops =
+{
+ .configure = configure,
+ .xfer = xfer
+};
+static struct rt_spi_bus loongson_spi;
+static int loongson_spi_init()
+{
+ //rt_kprintf("spi_init\n");
+ return rt_spi_bus_register(&loongson_spi, "spi", &loongson_spi_ops);
+}
+INIT_BOARD_EXPORT(loongson_spi_init);
+
+#endif
+/*@}*/
diff --git a/bsp/ls2kdev/drivers/drv_spi.h b/bsp/ls2kdev/drivers/drv_spi.h
new file mode 100644
index 0000000000..0b254d4fc2
--- /dev/null
+++ b/bsp/ls2kdev/drivers/drv_spi.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2020-10-28 0xcccccccccccc Initial Version
+ */
+/**
+ * @addtogroup ls2k
+ */
+/*@{*/
+#ifndef LS2K_DRV_SPI_H
+#define LS2K_DRV_SPI_H
+
+#include <rtthread.h>
+#include <rthw.h>
+
+// kseg1 byte operation
+#define KSEG1_STORE8(addr,val) *(volatile char *)(0xffffffffa0000000 | addr) = val
+#define KSEG1_LOAD8(addr) *(volatile char *)(0xffffffffa0000000 | addr)
+// clock configurations
+#define APB_MAX_SPEED 125000000U
+#define APB_FREQSCALE (((KSEG1_LOAD8(0xffffffffbfe104d2)>>4)&0x7)+1)
+// base addrs
+#define SPI_BASE 0x1fff0220
+#define PMON_ADDR 0xa1000000
+#define FLASH_ADDR 0x000000
+// bit bias
+#define SPCR 0x0
+#define SPSR 0x1
+#define FIFO 0x2
+#define TXFIFO 0x2
+#define RXFIFO 0x2
+#define SPER 0x3
+#define PARAM 0x4
+#define SOFTCS 0x5
+#define PARAM2 0x6
+#define RFEMPTY 1
+// SPI controller operaion macros
+#define SET_SPI(addr,val) KSEG1_STORE8(SPI_BASE+addr,val)
+#define GET_SPI(addr) KSEG1_LOAD8(SPI_BASE+addr)
+
+#endif
+/*@}*/
diff --git a/bsp/ls2kdev/drivers/drv_uart.c b/bsp/ls2kdev/drivers/drv_uart.c
index 428393dcc4..5b5c39c595 100644
--- a/bsp/ls2kdev/drivers/drv_uart.c
+++ b/bsp/ls2kdev/drivers/drv_uart.c
@@ -6,37 +6,57 @@
* Change Logs:
* Date Author Notes
* 2020-04-05 bigmagic Initial version
+ * 2020-10-28 ma Buadrate & Multi-Port support
*/
-
/**
* @addtogroup ls2k
*/
-
/*@{*/
-
#include <rtthread.h>
#include <rtdevice.h>
#include <rthw.h>
#include "drv_uart.h"
-
#define TRUE 1
#define FALSE 0
-
+const struct serial_configure config_uart0 = {
+ BAUD_RATE_115200, /* 921600 bits/s */
+ DATA_BITS_8, /* 8 databits */
+ STOP_BITS_1, /* 1 stopbit */
+ PARITY_NONE, /* No parity */
+ BIT_ORDER_LSB, /* LSB first sent */
+ NRZ_NORMAL, /* Normal mode */
+ RT_SERIAL_RB_BUFSZ, /* Buffer size */
+ 0
+};
struct rt_uart_ls2k
{
void *base;
rt_uint32_t IRQ;
};
-
-static rt_err_t mipssim_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
+static rt_err_t ls2k_uart_set_buad(struct rt_serial_device *serial, struct serial_configure *cfg)
{
struct rt_uart_ls2k *uart_dev = RT_NULL;
-
+ rt_err_t ret = RT_EOK;
RT_ASSERT(serial != RT_NULL);
RT_ASSERT(cfg != RT_NULL);
-
uart_dev = (struct rt_uart_ls2k *)serial->parent.user_data;
-
+ uint64_t brtc = (125000000U) / (16 * (cfg->baud_rate));
+ UART_LCR(uart_dev->base) = 0x80; // Activate buadcfg
+ UART_LSB(uart_dev->base) = brtc & 0xff;
+ UART_MSB(uart_dev->base) = brtc >> 8;
+ if (((((short)UART_MSB(uart_dev->base)) << 8) | UART_LSB(uart_dev->base)) != brtc) ret = RT_ERROR;
+ UART_LCR(uart_dev->base) = CFCR_8BITS; // Back to normal
+ UART_MCR(uart_dev->base) = MCR_IENABLE/* | MCR_DTR | MCR_RTS*/;
+ UART_IER(uart_dev->base) = 0;
+}
+static rt_err_t ls2k_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
+{
+ struct rt_uart_ls2k *uart_dev = RT_NULL;
+ RT_ASSERT(serial != RT_NULL);
+ RT_ASSERT(cfg != RT_NULL);
+ ls2k_uart_set_buad(serial, cfg);
+ uart_dev = (struct rt_uart_ls2k *)serial->parent.user_data;
+ HWREG8(0xffffffffbfe10428) = 0x1f; // Enable Multi-Port Support, by default it's 0x11 ,which means UART0 & UART4 Controller is in single port mode.
UART_IER(uart_dev->base) = 0; /* clear interrupt */
UART_FCR(uart_dev->base) = 0xc1; /* reset UART Rx/Tx */
/* set databits, stopbits and parity. (8-bit data, 1 stopbit, no parity) */
@@ -44,40 +64,30 @@ static rt_err_t mipssim_uart_configure(struct rt_serial_device *serial, struct s
UART_MCR(uart_dev->base) = 0x3;
UART_LSR(uart_dev->base) = 0x60;
UART_MSR(uart_dev->base) = 0xb0;
-
return RT_EOK;
}
-
-static rt_err_t mipssim_uart_control(struct rt_serial_device *serial, int cmd, void *arg)
+static rt_err_t ls2k_uart_control(struct rt_serial_device *serial, int cmd, void *arg)
{
struct rt_uart_ls2k *uart_dev = RT_NULL;
-
RT_ASSERT(serial != RT_NULL);
uart_dev = (struct rt_uart_ls2k *)serial->parent.user_data;
-
switch (cmd)
{
case RT_DEVICE_CTRL_CLR_INT: /* Disable RX IRQ */
rt_hw_interrupt_mask(uart_dev->IRQ);
break;
-
case RT_DEVICE_CTRL_SET_INT: /* Enable RX IRQ */
rt_hw_interrupt_umask(uart_dev->IRQ);
- UART_IER(uart_dev->base) |= (IER_IRxE|IER_ILE);
+ UART_IER(uart_dev->base) |= (IER_IRxE | IER_ILE);
break;
-
default:
break;
}
-
return RT_EOK;
-
}
-
static rt_bool_t uart_is_transmit_empty(struct rt_uart_ls2k *uart_dev)
{
unsigned char status = UART_LSR(uart_dev->base);
-
if (status & (UARTLSR_TE | UARTLSR_TFE))
{
return TRUE;
@@ -87,50 +97,35 @@ static rt_bool_t uart_is_transmit_empty(struct rt_uart_ls2k *uart_dev)
return FALSE;
}
}
-
-static int mipssim_uart_putc(struct rt_serial_device *serial, char c)
+static int ls2k_uart_putc(struct rt_serial_device *serial, char c)
{
struct rt_uart_ls2k *uart_dev = RT_NULL;
-
RT_ASSERT(serial != RT_NULL);
-
uart_dev = (struct rt_uart_ls2k *)serial->parent.user_data;
-
while (FALSE == uart_is_transmit_empty(uart_dev))
;
-
UART_DAT(uart_dev->base) = c;
-
return 1;
}
-
-static int mipssim_uart_getc(struct rt_serial_device *serial)
+static int ls2k_uart_getc(struct rt_serial_device *serial)
{
struct rt_uart_ls2k *uart_dev = RT_NULL;
-
RT_ASSERT(serial != RT_NULL);
-
uart_dev = (struct rt_uart_ls2k *)serial->parent.user_data;
-
if (LSR_RXRDY & UART_LSR(uart_dev->base))
{
return UART_DAT(uart_dev->base);
}
-
return -1;
}
-
/* UART interrupt handler */
static void uart_irq_handler(int vector, void *param)
{
struct rt_serial_device *serial = (struct rt_serial_device *)param;
struct rt_uart_ls2k *uart_dev = RT_NULL;
-
RT_ASSERT(serial != RT_NULL);
-
uart_dev = (struct rt_uart_ls2k *)serial->parent.user_data;
unsigned char iir = UART_IIR(uart_dev->base);
-
/* Find out interrupt reason */
if ((IIR_RXTOUT & iir) || (IIR_RXRDY & iir))
{
@@ -138,41 +133,55 @@ static void uart_irq_handler(int vector, void *param)
rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
rt_interrupt_leave();
}
-
}
-
-static const struct rt_uart_ops mipssim_uart_ops =
+static const struct rt_uart_ops ls2k_uart_ops =
{
- mipssim_uart_configure,
- mipssim_uart_control,
- mipssim_uart_putc,
- mipssim_uart_getc,
+ ls2k_uart_configure,
+ ls2k_uart_control,
+ ls2k_uart_putc,
+ ls2k_uart_getc,
};
-
struct rt_uart_ls2k uart_dev0 =
{
- (void *)UART0_BASE,
- 4,
+ (void *)UARTx_BASE(0),
+ LS2K_UART_0_1_2_3_IRQ,
+};
+struct rt_uart_ls2k uart_dev4 =
+{
+ (void *)UARTx_BASE(4),
+ LS2K_UART_4_5_6_7_IRQ,
};
-struct rt_serial_device serial;
+struct rt_serial_device serial, serial4;
void rt_hw_uart_init(void)
{
- struct rt_uart_ls2k *uart;
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
- uart = &uart_dev0;
-
- serial.ops = &mipssim_uart_ops;
- serial.config = config;
-
- rt_hw_interrupt_install(uart->IRQ, uart_irq_handler, &serial, "UART");
+#ifdef RT_USING_UART0
+ struct rt_uart_ls2k *uart0;
+ uart0 = &uart_dev0;
+ serial.ops = &ls2k_uart_ops;
+ serial.config = config_uart0;
+ rt_hw_interrupt_install(uart0->IRQ, uart_irq_handler, &serial, "UART0");
/* register UART device */
rt_hw_serial_register(&serial,
- "uart",
+ "uart0",
+ RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
+ uart0);
+#endif
+
+#ifdef RT_USING_UART4
+ struct rt_uart_ls2k *uart4;
+ uart4 = &uart_dev4;
+ serial4.ops = &ls2k_uart_ops;
+ serial4.config = config;
+ rt_hw_interrupt_install(uart4->IRQ, uart_irq_handler, &serial4, "UART4");
+ rt_hw_serial_register(&serial4,
+ "uart4",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
- uart);
+ &uart_dev4);
+#endif
}
/*@}*/
diff --git a/bsp/ls2kdev/drivers/drv_uart.h b/bsp/ls2kdev/drivers/drv_uart.h
index 95c69a0442..ca3e856d06 100644
--- a/bsp/ls2kdev/drivers/drv_uart.h
+++ b/bsp/ls2kdev/drivers/drv_uart.h
@@ -5,7 +5,7 @@
*
* Change Logs:
* Date Author Notes
- * 2019-04-05 bigmagic Initial version
+ * 2020-04-05 bigmagic Initial version
*/
#ifndef _DRV_UART_H__
@@ -15,100 +15,99 @@
#include <rthw.h>
/* UART registers */
-#define UART_DAT(base) HWREG8(base + 0x00)
-#define UART_IER(base) HWREG8(base + 0x01)
-#define UART_IIR(base) HWREG8(base + 0x02)
-#define UART_FCR(base) HWREG8(base + 0x02)
-#define UART_LCR(base) HWREG8(base + 0x03)
-#define UART_MCR(base) HWREG8(base + 0x04)
-#define UART_LSR(base) HWREG8(base + 0x05)
-#define UART_MSR(base) HWREG8(base + 0x06)
+#define UART_DAT(base) HWREG8(base + 0x00)
+#define UART_IER(base) HWREG8(base + 0x01)
+#define UART_IIR(base) HWREG8(base + 0x02)
+#define UART_FCR(base) HWREG8(base + 0x02)
+#define UART_LCR(base) HWREG8(base + 0x03)
+#define UART_MCR(base) HWREG8(base + 0x04)
+#define UART_LSR(base) HWREG8(base + 0x05)
+#define UART_MSR(base) HWREG8(base + 0x06)
-#define UART_LSB(base) HWREG8(base + 0x00)
-#define UART_MSB(base) HWREG8(base + 0x01)
+#define UART_LSB(base) HWREG8(base + 0x00)
+#define UART_MSB(base) HWREG8(base + 0x01)
/* interrupt enable register */
-#define IER_IRxE 0x1
-#define IER_ITxE 0x2
-#define IER_ILE 0x4
-#define IER_IME 0x8
+#define IER_IRxE 0x1
+#define IER_ITxE 0x2
+#define IER_ILE 0x4
+#define IER_IME 0x8
/* interrupt identification register */
-#define IIR_IMASK 0xf /* mask */
-#define IIR_RXTOUT 0xc /* receive timeout */
-#define IIR_RLS 0x6 /* receive line status */
-#define IIR_RXRDY 0x4 /* receive ready */
-#define IIR_TXRDY 0x2 /* transmit ready */
-#define IIR_NOPEND 0x1 /* nothing */
-#define IIR_MLSC 0x0 /* modem status */
-#define IIR_FIFO_MASK 0xc0 /* set if FIFOs are enabled */
+#define IIR_IMASK 0xf /* mask */
+#define IIR_RXTOUT 0xc /* receive timeout */
+#define IIR_RLS 0x6 /* receive line status */
+#define IIR_RXRDY 0x4 /* receive ready */
+#define IIR_TXRDY 0x2 /* transmit ready */
+#define IIR_NOPEND 0x1 /* nothing */
+#define IIR_MLSC 0x0 /* modem status */
+#define IIR_FIFO_MASK 0xc0 /* set if FIFOs are enabled */
/* fifo control register */
-#define FIFO_ENABLE 0x01 /* enable fifo */
-#define FIFO_RCV_RST 0x02 /* reset receive fifo */
-#define FIFO_XMT_RST 0x04 /* reset transmit fifo */
-#define FIFO_DMA_MODE 0x08 /* enable dma mode */
-#define FIFO_TRIGGER_1 0x00 /* trigger at 1 char */
-#define FIFO_TRIGGER_4 0x40 /* trigger at 4 chars */
-#define FIFO_TRIGGER_8 0x80 /* trigger at 8 chars */
-#define FIFO_TRIGGER_14 0xc0 /* trigger at 14 chars */
+#define FIFO_ENABLE 0x01 /* enable fifo */
+#define FIFO_RCV_RST 0x02 /* reset receive fifo */
+#define FIFO_XMT_RST 0x04 /* reset transmit fifo */
+#define FIFO_DMA_MODE 0x08 /* enable dma mode */
+#define FIFO_TRIGGER_1 0x00 /* trigger at 1 char */
+#define FIFO_TRIGGER_4 0x40 /* trigger at 4 chars */
+#define FIFO_TRIGGER_8 0x80 /* trigger at 8 chars */
+#define FIFO_TRIGGER_14 0xc0 /* trigger at 14 chars */
-// 线路控制寄存器
/* character format control register */
-#define CFCR_DLAB 0x80 /* divisor latch */
-#define CFCR_SBREAK 0x40 /* send break */
-#define CFCR_PZERO 0x30 /* zero parity */
-#define CFCR_PONE 0x20 /* one parity */
-#define CFCR_PEVEN 0x10 /* even parity */
-#define CFCR_PODD 0x00 /* odd parity */
-#define CFCR_PENAB 0x08 /* parity enable */
-#define CFCR_STOPB 0x04 /* 2 stop bits */
-#define CFCR_8BITS 0x03 /* 8 data bits */
-#define CFCR_7BITS 0x02 /* 7 data bits */
-#define CFCR_6BITS 0x01 /* 6 data bits */
-#define CFCR_5BITS 0x00 /* 5 data bits */
+#define CFCR_DLAB 0x80 /* divisor latch */
+#define CFCR_SBREAK 0x40 /* send break */
+#define CFCR_PZERO 0x30 /* zero parity */
+#define CFCR_PONE 0x20 /* one parity */
+#define CFCR_PEVEN 0x10 /* even parity */
+#define CFCR_PODD 0x00 /* odd parity */
+#define CFCR_PENAB 0x08 /* parity enable */
+#define CFCR_STOPB 0x04 /* 2 stop bits */
+#define CFCR_8BITS 0x03 /* 8 data bits */
+#define CFCR_7BITS 0x02 /* 7 data bits */
+#define CFCR_6BITS 0x01 /* 6 data bits */
+#define CFCR_5BITS 0x00 /* 5 data bits */
/* modem control register */
-#define MCR_LOOPBACK 0x10 /* loopback */
-#define MCR_IENABLE 0x08 /* output 2 = int enable */
-#define MCR_DRS 0x04 /* output 1 = xxx */
-#define MCR_RTS 0x02 /* enable RTS */
-#define MCR_DTR 0x01 /* enable DTR */
+#define MCR_LOOPBACK 0x10 /* loopback */
+#define MCR_IENABLE 0x08 /* output 2 = int enable */
+#define MCR_DRS 0x04 /* output 1 = xxx */
+#define MCR_RTS 0x02 /* enable RTS */
+#define MCR_DTR 0x01 /* enable DTR */
/* line status register */
-#define LSR_RCV_FIFO 0x80 /* error in receive fifo */
-#define LSR_TSRE 0x40 /* transmitter empty */
-#define LSR_TXRDY 0x20 /* transmitter ready */
-#define LSR_BI 0x10 /* break detected */
-#define LSR_FE 0x08 /* framing error */
-#define LSR_PE 0x04 /* parity error */
-#define LSR_OE 0x02 /* overrun error */
-#define LSR_RXRDY 0x01 /* receiver ready */
-#define LSR_RCV_MASK 0x1f
+#define LSR_RCV_FIFO 0x80 /* error in receive fifo */
+#define LSR_TSRE 0x40 /* transmitter empty */
+#define LSR_TXRDY 0x20 /* transmitter ready */
+#define LSR_BI 0x10 /* break detected */
+#define LSR_FE 0x08 /* framing error */
+#define LSR_PE 0x04 /* parity error */
+#define LSR_OE 0x02 /* overrun error */
+#define LSR_RXRDY 0x01 /* receiver ready */
+#define LSR_RCV_MASK 0x1f
/* UART interrupt enable register value */
-#define UARTIER_IME (1 << 3)
-#define UARTIER_ILE (1 << 2)
-#define UARTIER_ITXE (1 << 1)
-#define UARTIER_IRXE (1 << 0)
+#define UARTIER_IME (1 << 3)
+#define UARTIER_ILE (1 << 2)
+#define UARTIER_ITXE (1 << 1)
+#define UARTIER_IRXE (1 << 0)
/* UART line control register value */
-#define UARTLCR_DLAB (1 << 7)
-#define UARTLCR_BCB (1 << 6)
-#define UARTLCR_SPB (1 << 5)
-#define UARTLCR_EPS (1 << 4)
-#define UARTLCR_PE (1 << 3)
-#define UARTLCR_SB (1 << 2)
+#define UARTLCR_DLAB (1 << 7)
+#define UARTLCR_BCB (1 << 6)
+#define UARTLCR_SPB (1 << 5)
+#define UARTLCR_EPS (1 << 4)
+#define UARTLCR_PE (1 << 3)
+#define UARTLCR_SB (1 << 2)
/* UART line status register value */
-#define UARTLSR_ERROR (1 << 7)
-#define UARTLSR_TE (1 << 6)
-#define UARTLSR_TFE (1 << 5)
-#define UARTLSR_BI (1 << 4)
-#define UARTLSR_FE (1 << 3)
-#define UARTLSR_PE (1 << 2)
-#define UARTLSR_OE (1 << 1)
-#define UARTLSR_DR (1 << 0)
+#define UARTLSR_ERROR (1 << 7)
+#define UARTLSR_TE (1 << 6)
+#define UARTLSR_TFE (1 << 5)
+#define UARTLSR_BI (1 << 4)
+#define UARTLSR_FE (1 << 3)
+#define UARTLSR_PE (1 << 2)
+#define UARTLSR_OE (1 << 1)
+#define UARTLSR_DR (1 << 0)
#endif
diff --git a/bsp/ls2kdev/drivers/interrupt.c b/bsp/ls2kdev/drivers/interrupt.c
index 6473e5aa94..9e9c210aa0 100644
--- a/bsp/ls2kdev/drivers/interrupt.c
+++ b/bsp/ls2kdev/drivers/interrupt.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006-2019, RT-Thread Development Team
+ * Copyright (c) 2006-2020, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@@ -17,8 +17,9 @@
#include <rtthread.h>
#include <rthw.h>
#include <exception.h>
-
-#define MAX_INTR 32
+#include <drivers/pin.h>
+#include "ls2k1000.h"
+#include "interrupt.h"
static struct rt_irq_desc irq_handle_table[MAX_INTR];
@@ -27,21 +28,145 @@ static void rt_hw_interrupt_handler(int vector, void *param)
rt_kprintf("Unhandled interrupt %d occured!!!\n", vector);
}
+static void liointc_init(void)
+{
+ int i;
+ /* Router for LIOINTC0, to Core 0, INT0 (CPU IP2) */
+ for (i = 0; i < 32; i ++)
+ {
+ HWREG8(LIOINTC0_BASE + i) = LIOINTC_COREx_INTy(0, 0);
+ }
+
+ /* Router for LIOINTC1, to Core 0, INT1 (CPU IP3) */
+ for (i = 0; i < 32; i ++)
+ {
+ HWREG8(LIOINTC1_BASE + i) = LIOINTC_COREx_INTy(0, 1);
+ }
+
+ /* Disable all IRQs */
+ HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_DISABLE) = 0xffffffff;
+ HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_DISABLE) = 0xffffffff;
+
+ /* Set all IRQs to low level triggered (Default?) */
+ HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_POL) = 0x0;
+ HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_EDGE) = 0x0;
+
+ HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_POL) = 0x0;
+ HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_EDGE) = 0x0;
+}
+
+//set irq mode
+void liointc_set_irq_mode(int irq, int mode)
+{
+ if (irq < 32)
+ {
+ if (mode == PIN_IRQ_MODE_RISING)
+ {
+ HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_POL) |= (0x0 << (irq));
+ HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_EDGE) |= (0x1 << (irq));
+ }
+ else if (mode == PIN_IRQ_MODE_FALLING)
+ {
+ HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_POL) |= (0x1 << (irq));
+ HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_EDGE) |= (0x1 << (irq));
+ }
+ else if (mode == PIN_IRQ_MODE_HIGH_LEVEL)
+ {
+ HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_POL) |= (0x1 << (irq));
+ HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_EDGE) |= (0x0 << (irq));
+ }
+ else if (mode == PIN_IRQ_MODE_LOW_LEVEL)
+ {
+ HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_POL) |= (0x0 << (irq));
+ HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_EDGE) |= (0x0 << (irq));
+ }
+ else
+ {
+ HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_POL) |= (0x1 << (irq));
+ HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_EDGE) |= (0x1 << (irq));
+ }
+ }
+ else
+ {
+ if (mode == PIN_IRQ_MODE_RISING)
+ {
+ HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_POL) |= (0x0 << (irq - 32));
+ HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_EDGE) |= (0x1 << (irq - 32));
+ }
+ else if (mode == PIN_IRQ_MODE_FALLING)
+ {
+ HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_POL) |= (0x1 << (irq - 32));
+ HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_EDGE) |= (0x1 << (irq - 32));
+ }
+ else if (mode == PIN_IRQ_MODE_HIGH_LEVEL)
+ {
+ HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_POL) |= (0x1 << (irq - 32));
+ HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_EDGE) |= (0x0 << (irq - 32));
+ }
+ else if (mode == PIN_IRQ_MODE_LOW_LEVEL)
+ {
+ HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_POL) |= (0x0 << (irq - 32));
+ HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_EDGE) |= (0x0 << (irq - 32));
+ }
+ else
+ {
+ HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_POL) |= (0x1 << (irq - 32));
+ HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_EDGE) |= (0x1 << (irq - 32));
+ }
+ }
+}
+
+static void liointc_isr(rt_ubase_t reg_base, rt_ubase_t isr_base,
+ int irq_base)
+{
+ rt_uint32_t isr, tmp;
+ int intx;
+ /* Mask to clear ISR */
+ isr = HWREG32(isr_base);
+
+ tmp = isr;
+ /* Handle each of them */
+ while (tmp)
+ {
+ rt_isr_handler_t irq_func;
+ void *param;
+ int irq;
+
+ intx = __rt_ffs(isr) - 1;
+ tmp &= ~(1 << intx);
+
+ irq = intx + irq_base;
+
+ irq_func = irq_handle_table[irq].handler;
+ param = irq_handle_table[irq].param;
+ irq_func(irq, param);
+#ifdef RT_USING_INTERRUPT_INFO
+ irq_handle_table[irq].counter++;
+#endif
+ }
+
+ /* Enable them again */
+ HWREG32(reg_base + LIOINTC_REG_INTC_ENABLE) = isr;
+}
+
/**
* This function will initialize hardware interrupt
*/
void rt_hw_interrupt_init(void)
{
rt_uint32_t idx;
+
rt_memset(irq_handle_table, 0x00, sizeof(irq_handle_table));
for (idx = 0; idx < MAX_INTR; idx ++)
{
irq_handle_table[idx].handler = rt_hw_interrupt_handler;
}
+
+ liointc_init();
}
rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
- void *param, const char *name)
+ void *param, const char *name)
{
rt_isr_handler_t old_handler = RT_NULL;
@@ -56,34 +181,57 @@ rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
irq_handle_table[vector].param = param;
}
+ if (vector <= 32)
+ {
+ mips_unmask_cpu_irq(2);
+ }
+ else
+ {
+ mips_unmask_cpu_irq(3);
+ }
+
return old_handler;
}
-void rt_hw_timer_handler(void);
-
void rt_do_mips_cpu_irq(rt_uint32_t ip)
{
void *param;
rt_isr_handler_t irq_func;
-
- if (ip == 7) {
+ if (ip == 7)
+ {
rt_hw_timer_handler();
- } else {
- irq_func = irq_handle_table[ip].handler;
- param = irq_handle_table[ip].param;
-
- /* do interrupt */
- irq_func(ip, param);
+ }
+ else if (ip == 2)
+ {
+ liointc_isr(LIOINTC0_BASE, CORE0_INTISR0, LIOINTC0_IRQBASE);
+ }
+ else if (ip == 3)
+ {
+ liointc_isr(LIOINTC1_BASE, CORE0_INTISR1, LIOINTC1_IRQBASE);
}
}
void rt_hw_interrupt_umask(int irq)
{
- mips_unmask_cpu_irq(irq);
+ if (irq < LIOINTC0_IRQBASE + 32)
+ {
+ HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_ENABLE) = (1 << irq);
+ }
+ else if (irq < LIOINTC1_IRQBASE + 32)
+ {
+ HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_ENABLE) = (1 << (irq - 32));
+ }
}
void rt_hw_interrupt_mask(int irq)
{
- mips_mask_cpu_irq(irq);
+ if (irq < LIOINTC0_IRQBASE + 32)
+ {
+ HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_DISABLE) = (1 << irq);
+ }
+ else if (irq < LIOINTC1_IRQBASE + 32)
+ {
+ HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_DISABLE) = (1 << (irq - 32));
+ }
}
/*@}*/
diff --git a/bsp/ls2kdev/drivers/interrupt.h b/bsp/ls2kdev/drivers/interrupt.h
new file mode 100644
index 0000000000..df55437cf9
--- /dev/null
+++ b/bsp/ls2kdev/drivers/interrupt.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2020-06-21 bigmagic Initial version
+ */
+
+#ifndef _DRV_INTERRUPT_H__
+#define _DRV_INTERRUPT_H__
+
+#define LS2K_UART_0_1_2_3_IRQ (0)
+#define LS2K_UART_4_5_6_7_IRQ (1)
+#define LS2K_UART_8_9_10_11_IRQ (2)
+#define LS2K_EL_IRQ (3)
+#define LS2K_HDA_IRQ (4)
+#define LS2K_I2S_IRQ (5)
+#define LS2K_RESERVED1_IRQ (6)
+#define LS2K_THSENS_IRQ (7)
+#define LS2K_TOY_TICK_IRQ (8)
+#define LS2K_RTC_TICK_IRQ (9)
+#define LS2K_CAM_TICK_IRQ (10)
+#define LS2K_RESERVED2_IRQ (11)
+#define LS2K_GMAC0_SBD_IRQ (12)
+#define LS2K_GMAC0_PMT_IRQ (13)
+#define LS2K_GMAC1_SBD_IRQ (14)
+#define LS2K_GMAC1_PMT_IRQ (15)
+#define LS2K_CANO_IRQ (16)
+#define LS2K_CAN1_IRQ (17)
+#define LS2K_BOOT_IRQ (18)
+#define LS2K_SATA_IRQ (19)
+#define LS2K_NAND_IRQ (20)
+#define LS2K_HPET_IRQ (21)
+#define LS2K_I2C0_IRQ (21)
+#define LS2K_I2C1_IRQ (22)
+#define LS2K_I2C2_IRQ (23)
+#define LS2K_PWM0_IRQ (24)
+#define LS2K_PWM1_IRQ (25)
+#define LS2K_PWM2_IRQ (26)
+#define LS2K_PWM3_IRQ (27)
+#define LS2K_DC_IRQ (28)
+#define LS2K_GPU_IRQ (29)
+#define LS2K_VPU_IRQ (30)
+#define LS2K_SDIO_IRQ (31)
+//#define LS2K_PCIE0_IRQ (32~35)
+//#define LS2K_PCIE1_IRQ (36~37)
+#define LS2K_HPET1_IRQ (38)
+#define LS2K_HPET2_IRQ (39)
+//#define LS2K_TOY_IRQ (40~43)
+//#define LS2K_DMA_IRQ (44~48)
+#define LS2K_OTG_IRQ (49)
+#define LS2K_EHCI_IRQ (50)
+#define LS2K_OHCI_IRQ (51)
+//#define LS2K_RTC_IRQ (52~54)
+#define LS2K_RSA_IRQ (55)
+#define LS2K_AES_IRQ (56)
+#define LS2K_DES_IRQ (57)
+#define LS2K_GPIO_INTLO_IRQ (58)
+#define LS2K_GPIO_INTHI_IRQ (59)
+#define LS2K_GPIO0_INT_IRQ (60)
+#define LS2K_GPIO1_INT_IRQ (61)
+#define LS2K_GPIO2_INT_IRQ (62)
+#define LS2K_GPIO3_INT_IRQ (63)
+
+#define MAX_INTR (64)
+#define LIOINTC0_IRQBASE (0)
+#define LIOINTC1_IRQBASE (32)
+
+#define LIOINTC_SHIFT_INTx (4)
+#define LIOINTC_COREx_INTy(x, y) ((1 << x) | (1 << (y + LIOINTC_SHIFT_INTx)))
+
+#define LIOINTC_INTC_CHIP_START 0x20
+
+#define LIOINTC_REG_INTC_STATUS (LIOINTC_INTC_CHIP_START + 0x00)
+#define LIOINTC_REG_INTC_EN_STATUS (LIOINTC_INTC_CHIP_START + 0x04)
+#define LIOINTC_REG_INTC_ENABLE (LIOINTC_INTC_CHIP_START + 0x08)
+#define LIOINTC_REG_INTC_DISABLE (LIOINTC_INTC_CHIP_START + 0x0c)
+#define LIOINTC_REG_INTC_POL (LIOINTC_INTC_CHIP_START + 0x10)
+#define LIOINTC_REG_INTC_EDGE (LIOINTC_INTC_CHIP_START + 0x14)
+
+void liointc_set_irq_mode(int irq, int mode);
+
+#endif
diff --git a/bsp/ls2kdev/drivers/ls2k1000.h b/bsp/ls2kdev/drivers/ls2k1000.h
index 471ab80323..668d484d9c 100644
--- a/bsp/ls2kdev/drivers/ls2k1000.h
+++ b/bsp/ls2kdev/drivers/ls2k1000.h
@@ -2,12 +2,50 @@
#define _LS2K1000_H__
#include <mips.h>
+#include "interrupt.h"
+#include <rthw.h>
-#define UART0_BASE_ADDR 0xbfe00000
-#define UART0_OFF 0x0
-#define UART0_BASE CKSEG1ADDR(UART0_BASE_ADDR + UART0_OFF)
+#define APB_BASE CKSEG1ADDR(0xbfe00000)
-#define GPIO_BASE 0xFFFFFFFFBFE10500
+#define UART0_BASE_ADDR (0xbfe00000)
+#define UART0_OFF (0x0)
+#define UART0_BASE CKSEG1ADDR(UART0_BASE_ADDR + UART0_OFF)
+
+#define UARTx_BASE(x) ((APB_BASE | (0x0 << 12) | (x << 8)))
+
+#define LIOINTC0_BASE CKSEG1ADDR(0x1fe11400)
+#define CORE0_INTISR0 CKSEG1ADDR(0x1fe11040)
+
+#define LIOINTC1_BASE CKSEG1ADDR(0x1fe11440)
+#define CORE0_INTISR1 CKSEG1ADDR(0x1fe11048)
+
+#define GPIO_BASE (0xFFFFFFFFBFE10500)
+#define PLL_SYS_BASE (0xFFFFFFFFBFE10480)
+#define RTC_BASE (0xFFFFFFFFBFE07820)
+
+#define GEN_CONFIG0_REG (0xFFFFFFFFBfe10420)
+
+
+/*
+ * General PM Configuration Register
+ */
+#define PMCON_BASE (APB_BASE | (0x7 << 12))
+
+/*
+ * Power Management1 Configuration Registers
+ */
+#define PM1_BASE (PMCON_BASE + 0x0C)
+#define PM1_STS HWREG32(PM1_BASE)
+#define PM1_EN HWREG32(PM1_BASE + 0x04)
+#define PM1_CNT HWREG32(PM1_BASE + 0x08)
+
+/*
+ * Watch Dog Configuration Registers
+ */
+#define WDT_BASE (PMCON_BASE + 0x30)
+#define WDT_EN HWREG32(WDT_BASE)
+#define WDT_SET HWREG32(WDT_BASE + 0x04)
+#define WDT_TIMER HWREG32(WDT_BASE + 0x08)
void rt_hw_timer_handler(void);
void rt_hw_uart_init(void);
diff --git a/bsp/ls2kdev/drivers/net/SConscript b/bsp/ls2kdev/drivers/net/SConscript
new file mode 100644
index 0000000000..841d177c42
--- /dev/null
+++ b/bsp/ls2kdev/drivers/net/SConscript
@@ -0,0 +1,16 @@
+from building import *
+
+cwd = GetCurrentDir()
+src = Glob('*.c')
+
+CPPPATH = [cwd]
+
+if GetDepend('RT_USING_LWIP') == False:
+ SrcRemove(src, 'mii.c')
+ SrcRemove(src, 'synopGMAC.c')
+ SrcRemove(src, 'synopGMAC_Dev.c')
+ SrcRemove(src, 'synopGMAC_plat.c')
+
+group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/ls2kdev/drivers/net/mii.c b/bsp/ls2kdev/drivers/net/mii.c
new file mode 100644
index 0000000000..d83caef6de
--- /dev/null
+++ b/bsp/ls2kdev/drivers/net/mii.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2017-08-24 chinesebear first version
+ */
+#include "mii.h"
+
+static inline unsigned int mii_nway_result(unsigned int negotiated)
+{
+ unsigned int ret;
+
+ if (negotiated & LPA_100FULL)
+ ret = LPA_100FULL;
+ else if (negotiated & LPA_100BASE4)
+ ret = LPA_100BASE4;
+ else if (negotiated & LPA_100HALF)
+ ret = LPA_100HALF;
+ else if (negotiated & LPA_10FULL)
+ ret = LPA_10FULL;
+ else
+ ret = LPA_10HALF;
+
+ return ret;
+}
+
+static int mii_check_gmii_support(struct mii_if_info *mii)
+{
+ int reg;
+
+ reg = mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
+ if (reg & BMSR_ESTATEN)
+ {
+ reg = mii->mdio_read(mii->dev, mii->phy_id, MII_ESTATUS);
+ if (reg & (ESTATUS_1000_TFULL | ESTATUS_1000_THALF))
+ return 1;
+ }
+
+ return 0;
+}
+
+static int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
+{
+ struct synopGMACNetworkAdapter *dev = mii->dev;
+ u32 advert, bmcr, lpa, nego;
+ u32 advert2 = 0, bmcr2 = 0, lpa2 = 0;
+
+ ecmd->supported =
+ (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
+ SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII);
+ if (mii->supports_gmii)
+ ecmd->supported |= SUPPORTED_1000baseT_Half |
+ SUPPORTED_1000baseT_Full;
+
+ /* only supports twisted-pair */
+ ecmd->port = PORT_MII;
+
+ /* only supports internal transceiver */
+ ecmd->transceiver = XCVR_INTERNAL;
+
+ /* this isn't fully supported at higher layers */
+ ecmd->phy_address = mii->phy_id;
+
+ ecmd->advertising = ADVERTISED_TP | ADVERTISED_MII;
+ advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE);
+ if (mii->supports_gmii)
+ advert2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000);
+
+ if (advert & ADVERTISE_10HALF)
+ ecmd->advertising |= ADVERTISED_10baseT_Half;
+ if (advert & ADVERTISE_10FULL)
+ ecmd->advertising |= ADVERTISED_10baseT_Full;
+ if (advert & ADVERTISE_100HALF)
+ ecmd->advertising |= ADVERTISED_100baseT_Half;
+ if (advert & ADVERTISE_100FULL)
+ ecmd->advertising |= ADVERTISED_100baseT_Full;
+ if (advert2 & ADVERTISE_1000HALF)
+ ecmd->advertising |= ADVERTISED_1000baseT_Half;
+ if (advert2 & ADVERTISE_1000FULL)
+ ecmd->advertising |= ADVERTISED_1000baseT_Full;
+
+ bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
+ lpa = mii->mdio_read(dev, mii->phy_id, MII_LPA);
+ if (mii->supports_gmii)
+ {
+ bmcr2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000);
+ lpa2 = mii->mdio_read(dev, mii->phy_id, MII_STAT1000);
+ }
+ if (bmcr & BMCR_ANENABLE)
+ {
+ ecmd->advertising |= ADVERTISED_Autoneg;
+ ecmd->autoneg = AUTONEG_ENABLE;
+
+ nego = mii_nway_result(advert & lpa);
+ if ((bmcr2 & (ADVERTISE_1000HALF | ADVERTISE_1000FULL)) &
+ (lpa2 >> 2))
+ ecmd->speed = SPEED_1000;
+ else if (nego == LPA_100FULL || nego == LPA_100HALF)
+ ecmd->speed = SPEED_100;
+ else
+ ecmd->speed = SPEED_10;
+ if ((lpa2 & LPA_1000FULL) || nego == LPA_100FULL ||
+ nego == LPA_10FULL)
+ {
+ ecmd->duplex = DUPLEX_FULL;
+ mii->full_duplex = 1;
+ }
+ else
+ {
+ ecmd->duplex = DUPLEX_HALF;
+ mii->full_duplex = 0;
+ }
+ }
+ else
+ {
+ ecmd->autoneg = AUTONEG_DISABLE;
+
+ ecmd->speed = ((bmcr & BMCR_SPEED1000 &&
+ (bmcr & BMCR_SPEED100) == 0) ? SPEED_1000 :
+ (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10);
+ ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
+ }
+
+ /* ignore maxtxpkt, maxrxpkt for now */
+
+ return 0;
+}
+
+static int mii_link_ok(struct mii_if_info *mii)
+{
+ /* first, a dummy read, needed to latch some MII phys */
+ mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
+ if (mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR) & BMSR_LSTATUS)
+ return 1;
+ return 0;
+}
diff --git a/bsp/ls2kdev/drivers/net/mii.h b/bsp/ls2kdev/drivers/net/mii.h
new file mode 100644
index 0000000000..bc6d6c7a0c
--- /dev/null
+++ b/bsp/ls2kdev/drivers/net/mii.h
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2017-08-24 chinesebear first version
+ */
+#ifndef __MII_H__
+#define __MII_H__
+/* Generic MII registers. */
+
+#include "synopGMAC_types.h"
+
+#define MII_BMCR 0x00 /* Basic mode control register */
+#define MII_BMSR 0x01 /* Basic mode status register */
+#define MII_PHYSID1 0x02 /* PHYS ID 1 */
+#define MII_PHYSID2 0x03 /* PHYS ID 2 */
+#define MII_ADVERTISE 0x04 /* Advertisement control reg */
+#define MII_LPA 0x05 /* Link partner ability reg */
+#define MII_EXPANSION 0x06 /* Expansion register */
+#define MII_CTRL1000 0x09 /* 1000BASE-T control */
+#define MII_STAT1000 0x0a /* 1000BASE-T status */
+#define MII_ESTATUS 0x0f /* Extended Status */
+#define MII_DCOUNTER 0x12 /* Disconnect counter */
+#define MII_FCSCOUNTER 0x13 /* False carrier counter */
+#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */
+#define MII_RERRCOUNTER 0x15 /* Receive error counter */
+#define MII_SREVISION 0x16 /* Silicon revision */
+#define MII_RESV1 0x17 /* Reserved... */
+#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */
+#define MII_PHYADDR 0x19 /* PHY address */
+#define MII_RESV2 0x1a /* Reserved... */
+#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */
+#define MII_NCONFIG 0x1c /* Network interface config */
+
+/* Basic mode control register. */
+#define BMCR_RESV 0x003f /* Unused... */
+#define BMCR_SPEED1000 0x0040 /* MSB of Speed (1000) */
+#define BMCR_CTST 0x0080 /* Collision test */
+#define BMCR_FULLDPLX 0x0100 /* Full duplex */
+#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */
+#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */
+#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */
+#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */
+#define BMCR_SPEED100 0x2000 /* Select 100Mbps */
+#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */
+#define BMCR_RESET 0x8000 /* Reset the DP83840 */
+
+/* Basic mode status register. */
+#define BMSR_ERCAP 0x0001 /* Ext-reg capability */
+#define BMSR_JCD 0x0002 /* Jabber detected */
+#define BMSR_LSTATUS 0x0004 /* Link status */
+#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */
+#define BMSR_RFAULT 0x0010 /* Remote fault detected */
+#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */
+#define BMSR_RESV 0x00c0 /* Unused... */
+#define BMSR_ESTATEN 0x0100 /* Extended Status in R15 */
+#define BMSR_100FULL2 0x0200 /* Can do 100BASE-T2 HDX */
+#define BMSR_100HALF2 0x0400 /* Can do 100BASE-T2 FDX */
+#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */
+#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */
+#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */
+#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */
+#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */
+
+/* Advertisement control register. */
+#define ADVERTISE_SLCT 0x001f /* Selector bits */
+#define ADVERTISE_CSMA 0x0001 /* Only selector supported */
+#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
+#define ADVERTISE_1000XFULL 0x0020 /* Try for 1000BASE-X full-duplex */
+#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
+#define ADVERTISE_1000XHALF 0x0040 /* Try for 1000BASE-X half-duplex */
+#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
+#define ADVERTISE_1000XPAUSE 0x0080 /* Try for 1000BASE-X pause */
+#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
+#define ADVERTISE_1000XPSE_ASYM 0x0100 /* Try for 1000BASE-X asym pause */
+#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */
+#define ADVERTISE_PAUSE_CAP 0x0400 /* Try for pause */
+#define ADVERTISE_PAUSE_ASYM 0x0800 /* Try for asymetric pause */
+#define ADVERTISE_RESV 0x1000 /* Unused... */
+#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */
+#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */
+#define ADVERTISE_NPAGE 0x8000 /* Next page bit */
+
+#define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \
+ ADVERTISE_CSMA)
+#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \
+ ADVERTISE_100HALF | ADVERTISE_100FULL)
+
+/* Indicates what features are advertised by the interface. */
+#define ADVERTISED_10baseT_Half (1 << 0)
+#define ADVERTISED_10baseT_Full (1 << 1)
+#define ADVERTISED_100baseT_Half (1 << 2)
+#define ADVERTISED_100baseT_Full (1 << 3)
+#define ADVERTISED_1000baseT_Half (1 << 4)
+#define ADVERTISED_1000baseT_Full (1 << 5)
+#define ADVERTISED_Autoneg (1 << 6)
+#define ADVERTISED_TP (1 << 7)
+#define ADVERTISED_AUI (1 << 8)
+#define ADVERTISED_MII (1 << 9)
+#define ADVERTISED_FIBRE (1 << 10)
+#define ADVERTISED_BNC (1 << 11)
+#define ADVERTISED_10000baseT_Full (1 << 12)
+#define ADVERTISED_Pause (1 << 13)
+#define ADVERTISED_Asym_Pause (1 << 14)
+
+/* Link partner ability register. */
+#define LPA_SLCT 0x001f /* Same as advertise selector */
+#define LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */
+#define LPA_1000XFULL 0x0020 /* Can do 1000BASE-X full-duplex */
+#define LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */
+#define LPA_1000XHALF 0x0040 /* Can do 1000BASE-X half-duplex */
+#define LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */
+#define LPA_1000XPAUSE 0x0080 /* Can do 1000BASE-X pause */
+#define LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */
+#define LPA_1000XPAUSE_ASYM 0x0100 /* Can do 1000BASE-X pause asym*/
+#define LPA_100BASE4 0x0200 /* Can do 100mbps 4k packets */
+#define LPA_PAUSE_CAP 0x0400 /* Can pause */
+#define LPA_PAUSE_ASYM 0x0800 /* Can pause asymetrically */
+#define LPA_RESV 0x1000 /* Unused... */
+#define LPA_RFAULT 0x2000 /* Link partner faulted */
+#define LPA_LPACK 0x4000 /* Link partner acked us */
+#define LPA_NPAGE 0x8000 /* Next page bit */
+
+#define LPA_DUPLEX (LPA_10FULL | LPA_100FULL)
+#define LPA_100 (LPA_100FULL | LPA_100HALF | LPA_100BASE4)
+
+/* Expansion register for auto-negotiation. */
+#define EXPANSION_NWAY 0x0001 /* Can do N-way auto-nego */
+#define EXPANSION_LCWP 0x0002 /* Got new RX page code word */
+#define EXPANSION_ENABLENPAGE 0x0004 /* This enables npage words */
+#define EXPANSION_NPCAPABLE 0x0008 /* Link partner supports npage */
+#define EXPANSION_MFAULTS 0x0010 /* Multiple faults detected */
+#define EXPANSION_RESV 0xffe0 /* Unused... */
+
+#define ESTATUS_1000_TFULL 0x2000 /* Can do 1000BT Full */
+#define ESTATUS_1000_THALF 0x1000 /* Can do 1000BT Half */
+
+/* N-way test register. */
+#define NWAYTEST_RESV1 0x00ff /* Unused... */
+#define NWAYTEST_LOOPBACK 0x0100 /* Enable loopback for N-way */
+#define NWAYTEST_RESV2 0xfe00 /* Unused... */
+
+/* 1000BASE-T Control register */
+#define ADVERTISE_1000FULL 0x0200 /* Advertise 1000BASE-T full duplex */
+#define ADVERTISE_1000HALF 0x0100 /* Advertise 1000BASE-T half duplex */
+
+/* 1000BASE-T Status register */
+#define LPA_1000LOCALRXOK 0x2000 /* Link partner local receiver status */
+#define LPA_1000REMRXOK 0x1000 /* Link partner remote receiver status */
+#define LPA_1000FULL 0x0800 /* Link partner 1000BASE-T full duplex */
+
+#define SUPPORTED_10baseT_Half (1 << 0)
+#define SUPPORTED_10baseT_Full (1 << 1)
+#define SUPPORTED_100baseT_Half (1 << 2)
+#define SUPPORTED_100baseT_Full (1 << 3)
+#define SUPPORTED_1000baseT_Half (1 << 4)
+#define SUPPORTED_1000baseT_Full (1 << 5)
+#define SUPPORTED_Autoneg (1 << 6)
+#define SUPPORTED_TP (1 << 7)
+#define SUPPORTED_AUI (1 << 8)
+#define SUPPORTED_MII (1 << 9)
+#define SUPPORTED_FIBRE (1 << 10)
+#define SUPPORTED_BNC (1 << 11)
+#define SUPPORTED_10000baseT_Full (1 << 12)
+#define SUPPORTED_Pause (1 << 13)
+#define SUPPORTED_Asym_Pause (1 << 14)
+
+
+/* Which connector port. */
+#define PORT_TP 0x00
+#define PORT_AUI 0x01
+#define PORT_MII 0x02
+#define PORT_FIBRE 0x03
+#define PORT_BNC 0x04
+
+/* Which transceiver to use. */
+#define XCVR_INTERNAL 0x00
+#define XCVR_EXTERNAL 0x01
+#define XCVR_DUMMY1 0x02
+#define XCVR_DUMMY2 0x03
+#define XCVR_DUMMY3 0x04
+
+#define AUTONEG_DISABLE 0x00
+#define AUTONEG_ENABLE 0x01
+
+
+#define SPEED_10 10
+#define SPEED_100 100
+#define SPEED_1000 1000
+#define SPEED_2500 2500
+#define SPEED_10000 10000
+
+#define DUPLEX_HALF 0x00
+#define DUPLEX_FULL 0x01
+
+struct ethtool_cmd {
+ u32 cmd;
+ u32 supported; /* Features this interface supports */
+ u32 advertising; /* Features this interface advertises */
+ u16 speed; /* The forced speed, 10Mb, 100Mb, gigabit */
+ u8 duplex; /* Duplex, half or full */
+ u8 port; /* Which connector port */
+ u8 phy_address;
+ u8 transceiver; /* Which transceiver to use */
+ u8 autoneg; /* Enable or disable autonegotiation */
+ u32 maxtxpkt; /* Tx pkts before generating tx int */
+ u32 maxrxpkt; /* Rx pkts before generating rx int */
+ u32 reserved[4];
+};
+
+struct mii_if_info {
+ int phy_id;
+ int advertising;
+ int phy_id_mask;
+ int reg_num_mask;
+
+ unsigned int full_duplex : 1; /* is full duplex? */
+ unsigned int force_media : 1; /* is autoneg. disabled? */
+ unsigned int supports_gmii : 1; /* are GMII registers supported? */
+
+ struct synopGMACNetworkAdapter *dev;
+ int (*mdio_read) (struct synopGMACNetworkAdapter *dev, int phy_id, int location);
+ void (*mdio_write) (struct synopGMACNetworkAdapter *dev, int phy_id, int location, int val);
+};
+
+#endif
diff --git a/bsp/ls2kdev/drivers/net/synopGMAC.c b/bsp/ls2kdev/drivers/net/synopGMAC.c
new file mode 100644
index 0000000000..22e51de712
--- /dev/null
+++ b/bsp/ls2kdev/drivers/net/synopGMAC.c
@@ -0,0 +1,988 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2017-08-24 chinesebear first version
+ * 2020-08-10 lizhirui porting to ls2k
+ */
+
+#include <rtthread.h>
+#include <rtdef.h>
+//#include <lwip/pbuf.h>
+
+#include "synopGMAC.h"
+#include "mii.c"
+#include "synopGMAC_debug.h"
+
+#define RMII
+
+#define PCI_BASE (0xFE00001800)
+#define Buffer_Size 2048
+#define MAX_ADDR_LEN 6
+#define NAMESIZE 16
+
+#define LS1B_GMAC0_IRQ 34
+#define BUS_SIZE_ALIGN(x) ((x+15)&~15)
+
+#define DEFAULT_MAC_ADDRESS {0x00, 0x55, 0x7B, 0xB5, 0x7D, 0xF7}
+
+u64 gmac_base = 0;
+static u32 GMAC_Power_down;
+extern void *plat_alloc_consistent_dmaable_memory(synopGMACdevice *pcidev, u32 size, u32 *addr) ;
+extern s32 synopGMAC_check_phy_init(synopGMACPciNetworkAdapter *adapter) ;
+extern int init_phy(synopGMACdevice *gmacdev);
+dma_addr_t plat_dma_map_single(void *hwdev, void *ptr, u32 size);
+
+void eth_rx_irq(int irqno, void *param);
+static char Rx_Buffer[Buffer_Size];
+static char Tx_Buffer[Buffer_Size];
+
+struct pci_header
+{
+ uint16_t VendorID;
+ uint16_t DeviceID;
+ uint16_t Command;
+ uint16_t Status;
+ uint32_t RevisionID : 8;
+ uint32_t ClassCode : 24;
+ uint8_t CachelineSize;
+ uint8_t LatencyTimer;
+ uint8_t HeaderType;
+ uint8_t BIST;
+ uint32_t BaseAddressRegister[6];
+ uint32_t CardbusCISPointer;
+ uint16_t SubsystemVendorID;
+ uint16_t SubsystemID;
+ uint32_t ExpansionROMBaseAddress;
+ uint32_t CapabilitiesPointer : 8;
+ uint32_t resv1 : 24;
+ uint32_t resv2;
+ uint8_t InterruptLine;
+ uint8_t InterruptPin;
+ uint8_t Min_Gnt;
+ uint8_t Max_Lat;
+};
+
+struct rt_eth_dev
+{
+ struct eth_device parent;
+ rt_uint8_t dev_addr[MAX_ADDR_LEN];
+ char *name;
+ int iobase;
+ int state;
+ int index;
+ struct rt_timer link_timer;
+ struct rt_timer rx_poll_timer;
+ void *priv;
+};
+static struct rt_eth_dev eth_dev;
+static struct rt_semaphore sem_ack, sem_lock;
+
+/**
+ * This sets up the transmit Descriptor queue in ring or chain mode.
+ * This function is tightly coupled to the platform and operating system
+ * Device is interested only after the descriptors are setup. Therefore this function
+ * is not included in the device driver API. This function should be treated as an
+ * example code to design the descriptor structures for ring mode or chain mode.
+ * This function depends on the pcidev structure for allocation consistent dma-able memory in case
+ * of linux.
+ * This limitation is due to the fact that linux uses pci structure to allocate a dmable memory
+ * - Allocates the memory for the descriptors.
+ * - Initialize the Busy and Next descriptors indices to 0(Indicating first descriptor).
+ * - Initialize the Busy and Next descriptors to first descriptor address.
+ * - Initialize the last descriptor with the endof ring in case of ring mode.
+ * - Initialize the descriptors in chain mode.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] pointer to pci_device structure.
+ * @param[in] number of descriptor expected in tx descriptor queue.
+ * @param[in] whether descriptors to be created in RING mode or CHAIN mode.
+ * \return 0 upon success. Error code upon failure.
+ * \note This function fails if allocation fails for required number of descriptors in Ring mode,
+ * but in chain mode
+ * function returns -ESYNOPGMACNOMEM in the process of descriptor chain creation. once returned from
+ * this function
+ * user should for gmacdev->TxDescCount to see how many descriptors are there in the chain. Should
+ * continue further
+ * only if the number of descriptors in the chain meets the requirements
+ */
+s32 synopGMAC_setup_tx_desc_queue(synopGMACdevice *gmacdev, u32 no_of_desc, u32 desc_mode)
+{
+ s32 i;
+ DmaDesc *bf1;
+
+ DmaDesc *first_desc = NULL;
+
+ dma_addr_t dma_addr;
+ gmacdev->TxDescCount = 0;
+
+ first_desc = (DmaDesc *)plat_alloc_consistent_dmaable_memory(gmacdev, sizeof(DmaDesc) * (no_of_desc), &dma_addr);
+
+ if (first_desc == NULL)
+ {
+ rt_kprintf("Error in Tx Descriptors memory allocation\n");
+ return -ESYNOPGMACNOMEM;
+ }
+
+ DEBUG_MES("tx_first_desc_addr = %p\n", first_desc);
+ DEBUG_MES("dmaadr = %p\n", dma_addr);
+ gmacdev->TxDescCount = no_of_desc;
+ gmacdev->TxDesc = first_desc;
+ gmacdev->TxDescDma = dma_addr;
+
+ for (i = 0; i < gmacdev->TxDescCount; i++)
+ {
+ synopGMAC_tx_desc_init_ring(gmacdev->TxDesc + i, i == gmacdev->TxDescCount - 1);
+
+#if SYNOP_TOP_DEBUG
+ rt_kprintf("\n%02d %08x \n", i, (unsigned int)(gmacdev->TxDesc + i));
+ rt_kprintf("%08x ", (unsigned int)((gmacdev->TxDesc + i))->status);
+ rt_kprintf("%08x ", (unsigned int)((gmacdev->TxDesc + i)->length));
+ rt_kprintf("%08x ", (unsigned int)((gmacdev->TxDesc + i)->buffer1));
+ rt_kprintf("%08x ", (unsigned int)((gmacdev->TxDesc + i)->buffer2));
+ rt_kprintf("%08x ", (unsigned int)((gmacdev->TxDesc + i)->data1));
+ rt_kprintf("%08x ", (unsigned int)((gmacdev->TxDesc + i)->data2));
+ rt_kprintf("%08x ", (unsigned int)((gmacdev->TxDesc + i)->dummy1));
+ rt_kprintf("%08x ", (unsigned int)((gmacdev->TxDesc + i)->dummy2));
+#endif
+ }
+
+ gmacdev->TxNext = 0;
+ gmacdev->TxBusy = 0;
+ gmacdev->TxNextDesc = gmacdev->TxDesc;
+ gmacdev->TxBusyDesc = gmacdev->TxDesc;
+ gmacdev->BusyTxDesc = 0;
+
+ return -ESYNOPGMACNOERR;
+}
+
+/**
+ * This sets up the receive Descriptor queue in ring or chain mode.
+ * This function is tightly coupled to the platform and operating system
+ * Device is interested only after the descriptors are setup. Therefore this function
+ * is not included in the device driver API. This function should be treated as an
+ * example code to design the descriptor structures in ring mode or chain mode.
+ * This function depends on the pcidev structure for allocation of consistent dma-able memory in
+ * case of linux.
+ * This limitation is due to the fact that linux uses pci structure to allocate a dmable memory
+ * - Allocates the memory for the descriptors.
+ * - Initialize the Busy and Next descriptors indices to 0(Indicating first descriptor).
+ * - Initialize the Busy and Next descriptors to first descriptor address.
+ * - Initialize the last descriptor with the endof ring in case of ring mode.
+ * - Initialize the descriptors in chain mode.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] pointer to pci_device structure.
+ * @param[in] number of descriptor expected in rx descriptor queue.
+ * @param[in] whether descriptors to be created in RING mode or CHAIN mode.
+ * \return 0 upon success. Error code upon failure.
+ * \note This function fails if allocation fails for required number of descriptors in Ring mode,
+ * but in chain mode
+ * function returns -ESYNOPGMACNOMEM in the process of descriptor chain creation. once returned from
+ * this function
+ * user should for gmacdev->RxDescCount to see how many descriptors are there in the chain. Should
+ * continue further
+ * only if the number of descriptors in the chain meets the requirements
+ */
+s32 synopGMAC_setup_rx_desc_queue(synopGMACdevice *gmacdev, u32 no_of_desc, u32 desc_mode)
+{
+ s32 i;
+ DmaDesc *bf1;
+ DmaDesc *first_desc = NULL;
+
+ dma_addr_t dma_addr;
+
+ gmacdev->RxDescCount = 0;
+ first_desc = (DmaDesc *)plat_alloc_consistent_dmaable_memory(gmacdev, sizeof(DmaDesc) * no_of_desc, &dma_addr);
+ if (first_desc == NULL)
+ {
+ rt_kprintf("Error in Rx Descriptor Memory allocation in Ring mode\n");
+ return -ESYNOPGMACNOMEM;
+ }
+
+ DEBUG_MES("rx_first_desc_addr = %p\n", first_desc);
+ DEBUG_MES("dmaadr = %p\n", dma_addr);
+ gmacdev->RxDescCount = no_of_desc;
+ gmacdev->RxDesc = (DmaDesc *)first_desc;
+ gmacdev->RxDescDma = dma_addr;
+
+ for (i = 0; i < gmacdev->RxDescCount; i++)
+ {
+ synopGMAC_rx_desc_init_ring(gmacdev->RxDesc + i, i == gmacdev->RxDescCount - 1);
+ }
+
+ gmacdev->RxNext = 0;
+ gmacdev->RxBusy = 0;
+ gmacdev->RxNextDesc = gmacdev->RxDesc;
+ gmacdev->RxBusyDesc = gmacdev->RxDesc;
+
+ gmacdev->BusyRxDesc = 0;
+
+ return -ESYNOPGMACNOERR;
+}
+
+void synopGMAC_linux_cable_unplug_function(void *adaptr)
+{
+ s32 data;
+ synopGMACPciNetworkAdapter *adapter = (synopGMACPciNetworkAdapter *)adaptr;
+ synopGMACdevice *gmacdev = adapter->synopGMACdev;
+ struct ethtool_cmd cmd;
+
+ if (!mii_link_ok(&adapter->mii))
+ {
+ if (gmacdev->LinkState)
+ rt_kprintf("\r\nNo Link\r\n");
+ gmacdev->DuplexMode = 0;
+ gmacdev->Speed = 0;
+ gmacdev->LoopBackMode = 0;
+ gmacdev->LinkState = 0;
+ }
+ else
+ {
+ data = synopGMAC_check_phy_init(adapter);
+
+ if (gmacdev->LinkState != data)
+ {
+ gmacdev->LinkState = data;
+ synopGMAC_mac_init(gmacdev);
+ rt_kprintf("Link is up in %s mode\n", (gmacdev->DuplexMode == FULLDUPLEX) ? "FULL DUPLEX" : "HALF DUPLEX");
+ if (gmacdev->Speed == SPEED1000)
+ rt_kprintf("Link is with 1000M Speed \r\n");
+ if (gmacdev->Speed == SPEED100)
+ rt_kprintf("Link is with 100M Speed \n");
+ if (gmacdev->Speed == SPEED10)
+ rt_kprintf("Link is with 10M Speed \n");
+ }
+ }
+}
+
+s32 synopGMAC_check_phy_init(synopGMACPciNetworkAdapter *adapter)
+{
+ struct ethtool_cmd cmd;
+ synopGMACdevice *gmacdev = adapter->synopGMACdev;
+
+ if (!mii_link_ok(&adapter->mii))
+ {
+ gmacdev->DuplexMode = FULLDUPLEX;
+ gmacdev->Speed = SPEED100;
+
+ return 0;
+ }
+ else
+ {
+ mii_ethtool_gset(&adapter->mii, &cmd);
+
+ gmacdev->DuplexMode = (cmd.duplex == DUPLEX_FULL) ? FULLDUPLEX : HALFDUPLEX ;
+ if (cmd.speed == SPEED_1000)
+ gmacdev->Speed = SPEED1000;
+ else if (cmd.speed == SPEED_100)
+ gmacdev->Speed = SPEED100;
+ else
+ gmacdev->Speed = SPEED10;
+ }
+
+ return gmacdev->Speed | (gmacdev->DuplexMode << 4);
+}
+
+static int Mac_change_check(u8 *macaddr0, u8 *macaddr1)
+{
+ int i;
+ for (i = 0; i < 6; i++)
+ {
+ if (macaddr0[i] != macaddr1[i])
+ return 1;
+ }
+ return 0;
+}
+
+static rt_err_t eth_init(rt_device_t device)
+{
+ struct eth_device *eth_device = (struct eth_device *)device;
+ RT_ASSERT(eth_device != RT_NULL);
+
+ s32 ijk;
+ s32 status = 0;
+ u64 dma_addr;
+ u32 Mac_changed = 0;
+ struct pbuf *pbuf;
+ u8 macaddr[6] = DEFAULT_MAC_ADDRESS;
+ struct rt_eth_dev *dev = &eth_dev;
+ struct synopGMACNetworkAdapter *adapter = dev->priv;
+ synopGMACdevice *gmacdev = (synopGMACdevice *)adapter->synopGMACdev;
+
+ synopGMAC_reset(gmacdev);
+ synopGMAC_attach(gmacdev, (gmac_base + MACBASE), (gmac_base + DMABASE), DEFAULT_PHY_BASE, macaddr);
+
+ synopGMAC_read_version(gmacdev);
+
+ synopGMAC_set_mdc_clk_div(gmacdev, GmiiCsrClk3);
+ gmacdev->ClockDivMdc = synopGMAC_get_mdc_clk_div(gmacdev);
+
+ init_phy(adapter->synopGMACdev);
+
+ DEBUG_MES("tx desc_queue\n");
+ synopGMAC_setup_tx_desc_queue(gmacdev, TRANSMIT_DESC_SIZE, RINGMODE);
+ synopGMAC_init_tx_desc_base(gmacdev);
+
+ DEBUG_MES("rx desc_queue\n");
+ synopGMAC_setup_rx_desc_queue(gmacdev, RECEIVE_DESC_SIZE, RINGMODE);
+ synopGMAC_init_rx_desc_base(gmacdev);
+ DEBUG_MES("DmaRxBaseAddr = %08x\n", synopGMACReadReg(gmacdev->DmaBase, DmaRxBaseAddr));
+
+// u32 dmaRx_Base_addr = synopGMACReadReg(gmacdev->DmaBase,DmaRxBaseAddr);
+// rt_kprintf("first_desc_addr = 0x%x\n", dmaRx_Base_addr);
+
+#ifdef ENH_DESC_8W
+ synopGMAC_dma_bus_mode_init(gmacdev, DmaBurstLength32 | DmaDescriptorSkip2 | DmaDescriptor8Words);
+#else
+ synopGMAC_dma_bus_mode_init(gmacdev, DmaBurstLength4 | DmaDescriptorSkip1);
+ //synopGMAC_dma_bus_mode_init(gmacdev, DmaBurstLength4 | DmaDescriptorSkip2);
+#endif
+ synopGMAC_dma_control_init(gmacdev, DmaStoreAndForward | DmaTxSecondFrame | DmaRxThreshCtrl128);
+
+ status = synopGMAC_check_phy_init(adapter);
+ synopGMAC_mac_init(gmacdev);
+
+ synopGMAC_pause_control(gmacdev);
+
+#ifdef IPC_OFFLOAD
+ synopGMAC_enable_rx_chksum_offload(gmacdev);
+ synopGMAC_rx_tcpip_chksum_drop_enable(gmacdev);
+#endif
+
+ u64 skb;
+ do
+ {
+ skb = (u64)plat_alloc_memory(RX_BUF_SIZE); //should skb aligned here?
+ if (skb == RT_NULL)
+ {
+ rt_kprintf("ERROR in skb buffer allocation\n");
+ break;
+ }
+
+ dma_addr = plat_dma_map_single(gmacdev, (void *)skb, RX_BUF_SIZE); //获取 skb 的 dma 地址
+
+ status = synopGMAC_set_rx_qptr(gmacdev, dma_addr, RX_BUF_SIZE, (u64)skb, 0, 0, 0);
+ if (status < 0)
+ {
+ rt_kprintf("status < 0!!\n");
+ plat_free_memory((void *)skb);
+ }
+ }
+ while (status >= 0 && (status < (RECEIVE_DESC_SIZE - 1)));
+ synopGMAC_clear_interrupt(gmacdev);
+
+ synopGMAC_disable_mmc_tx_interrupt(gmacdev, 0xFFFFFFFF);
+ synopGMAC_disable_mmc_rx_interrupt(gmacdev, 0xFFFFFFFF);
+ synopGMAC_disable_mmc_ipc_rx_interrupt(gmacdev, 0xFFFFFFFF);
+
+// synopGMAC_disable_interrupt_all(gmacdev);
+ synopGMAC_enable_interrupt(gmacdev, DmaIntEnable);
+ synopGMAC_enable_dma_rx(gmacdev);
+ synopGMAC_enable_dma_tx(gmacdev);
+
+ plat_delay(DEFAULT_LOOP_VARIABLE);
+ synopGMAC_check_phy_init(adapter);
+ synopGMAC_mac_init(gmacdev);
+
+ rt_timer_init(&dev->link_timer, "link_timer",
+ synopGMAC_linux_cable_unplug_function,
+ (void *)adapter,
+ RT_TICK_PER_SECOND,
+ RT_TIMER_FLAG_PERIODIC);
+
+ rt_timer_start(&dev->link_timer);
+#ifdef RT_USING_GMAC_INT_MODE
+ /* installl isr */
+ DEBUG_MES("%s\n", __FUNCTION__);
+ rt_hw_interrupt_install(LS1C_MAC_IRQ, eth_rx_irq, RT_NULL, "e0_isr");
+ rt_hw_interrupt_umask(LS1C_MAC_IRQ);
+#else
+ rt_timer_init(&dev->rx_poll_timer, "rx_poll_timer",
+ eth_rx_irq,
+ (void *)adapter,
+ 1,
+ RT_TIMER_FLAG_PERIODIC);
+
+ rt_timer_start(&dev->rx_poll_timer);
+#endif /*RT_USING_GMAC_INT_MODE*/
+
+ return RT_EOK;
+}
+
+static rt_err_t eth_open(rt_device_t dev, rt_uint16_t oflag)
+{
+ rt_kprintf("eth_open!!\n");
+
+ return RT_EOK;
+}
+
+static rt_err_t eth_close(rt_device_t dev)
+{
+ return RT_EOK;
+}
+
+static rt_size_t eth_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
+{
+ rt_set_errno(-RT_ENOSYS);
+ return 0;
+}
+
+static rt_size_t eth_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
+{
+ rt_set_errno(-RT_ENOSYS);
+ return 0;
+}
+
+static rt_err_t eth_control(rt_device_t dev, int cmd, void *args)
+{
+ switch (cmd)
+ {
+ case NIOCTL_GADDR:
+ if (args) rt_memcpy(args, eth_dev.dev_addr, 6);
+ else return -RT_ERROR;
+ break;
+
+ default :
+ break;
+ }
+ return RT_EOK;
+}
+
+rt_err_t rt_eth_tx(rt_device_t device, struct pbuf *p)
+{
+ /* lock eth device */
+ rt_sem_take(&sem_lock, RT_WAITING_FOREVER);
+
+ DEBUG_MES("in %s\n", __FUNCTION__);
+
+ s32 status;
+ u64 pbuf;
+ u64 dma_addr;
+ u32 offload_needed = 0;
+ u32 index;
+ DmaDesc *dpr;
+ struct rt_eth_dev *dev = (struct rt_eth_dev *) device;
+ struct synopGMACNetworkAdapter *adapter;
+ synopGMACdevice *gmacdev;
+ adapter = (struct synopGMACNetworkAdapter *) dev->priv;
+ if (adapter == NULL)
+ return -1;
+
+ gmacdev = (synopGMACdevice *) adapter->synopGMACdev;
+ if (gmacdev == NULL)
+ return -1;
+
+ if (!synopGMAC_is_desc_owned_by_dma(gmacdev->TxNextDesc))
+ {
+
+ pbuf = (u64)plat_alloc_memory(p->tot_len);
+ //pbuf = (u32)pbuf_alloc(PBUF_LINK, p->len, PBUF_RAM);
+ if (pbuf == 0)
+ {
+ rt_kprintf("===error in alloc bf1\n");
+ return -1;
+ }
+
+ DEBUG_MES("p->len = %d\n", p->len);
+ pbuf_copy_partial(p, (void *)pbuf, p->tot_len, 0);
+ dma_addr = plat_dma_map_single(gmacdev, (void *)pbuf, p->tot_len);
+
+ status = synopGMAC_set_tx_qptr(gmacdev, dma_addr, p->tot_len, pbuf, 0, 0, 0, offload_needed, &index, dpr);
+
+ if (status < 0)
+ {
+ rt_kprintf("%s No More Free Tx Descriptors\n", __FUNCTION__);
+
+ plat_free_memory((void *)pbuf);
+ return -16;
+ }
+ }
+
+ synopGMAC_resume_dma_tx(gmacdev);
+
+
+ s32 desc_index;
+ u64 data1, data2;
+ u32 dma_addr1, dma_addr2;
+ u32 length1, length2;
+#ifdef ENH_DESC_8W
+ u32 ext_status;
+ u16 time_stamp_higher;
+ u32 time_stamp_high;
+ u32 time_stamp_low;
+#endif
+ do
+ {
+#ifdef ENH_DESC_8W
+ desc_index = synopGMAC_get_tx_qptr(gmacdev, &status, &dma_addr1, &length1, &data1, &dma_addr2, &length2, &data2, &ext_status, &time_stamp_high, &time_stamp_low);
+ synopGMAC_TS_read_timestamp_higher_val(gmacdev, &time_stamp_higher);
+#else
+ desc_index = synopGMAC_get_tx_qptr(gmacdev, &status, &dma_addr1, &length1, &data1, &dma_addr2, &length2, &data2);
+#endif
+ if (desc_index >= 0 && data1 != 0)
+ {
+#ifdef IPC_OFFLOAD
+ if (synopGMAC_is_tx_ipv4header_checksum_error(gmacdev, status))
+ {
+ rt_kprintf("Harware Failed to Insert IPV4 Header Checksum\n");
+ }
+ if (synopGMAC_is_tx_payload_checksum_error(gmacdev, status))
+ {
+ rt_kprintf("Harware Failed to Insert Payload Checksum\n");
+ }
+#endif
+
+ plat_free_memory((void *)(data1)); //sw: data1 = buffer1
+
+ if (synopGMAC_is_desc_valid(status))
+ {
+ adapter->synopGMACNetStats.tx_bytes += length1;
+ adapter->synopGMACNetStats.tx_packets++;
+ }
+ else
+ {
+ adapter->synopGMACNetStats.tx_errors++;
+ adapter->synopGMACNetStats.tx_aborted_errors += synopGMAC_is_tx_aborted(status);
+ adapter->synopGMACNetStats.tx_carrier_errors += synopGMAC_is_tx_carrier_error(status);
+ }
+ }
+
+ adapter->synopGMACNetStats.collisions += synopGMAC_get_tx_collision_count(status);
+ }
+ while (desc_index >= 0);
+
+ /* unlock eth device */
+ rt_sem_release(&sem_lock);
+// rt_kprintf("output %d bytes\n", p->len);
+ u32 test_data;
+ test_data = synopGMACReadReg(gmacdev->DmaBase, DmaStatus);
+ //rt_kprintf("dma_status = 0x%08x\n",test_data);
+
+ return RT_EOK;
+}
+
+struct pbuf *rt_eth_rx(rt_device_t device)
+{
+ DEBUG_MES("%s : \n", __FUNCTION__);
+ struct rt_eth_dev *dev = &eth_dev;
+ struct synopGMACNetworkAdapter *adapter;
+ synopGMACdevice *gmacdev;
+// struct PmonInet * pinetdev;
+ s32 desc_index;
+ int i;
+ char *ptr;
+ u32 bf1;
+ u64 data1;
+ u64 data2;
+ u32 len;
+ u32 status;
+ u32 dma_addr1;
+ u32 dma_addr2;
+ struct pbuf *pbuf = RT_NULL;
+ rt_sem_take(&sem_lock, RT_WAITING_FOREVER);
+
+ adapter = (struct synopGMACNetworkAdapter *) dev->priv;
+ if (adapter == NULL)
+ {
+ rt_kprintf("%S : Unknown Device !!\n", __FUNCTION__);
+ return NULL;
+ }
+
+ gmacdev = (synopGMACdevice *) adapter->synopGMACdev;
+ if (gmacdev == NULL)
+ {
+ rt_kprintf("%s : GMAC device structure is missing\n", __FUNCTION__);
+ return NULL;
+ }
+
+ /*Handle the Receive Descriptors*/
+ desc_index = synopGMAC_get_rx_qptr(gmacdev, &status, &dma_addr1, NULL, &data1, &dma_addr2, NULL, &data2);
+
+ if (((u32)desc_index >= RECEIVE_DESC_SIZE) && (desc_index != -1))
+ {
+ rt_kprintf("host receive descriptor address pointer = 0x%08x\n", synopGMACReadReg(gmacdev->DmaBase, DmaRxCurrDesc));
+ rt_kprintf("host receive buffer = 0x%08x\n", synopGMACReadReg(gmacdev->DmaBase, DmaRxCurrAddr));
+ rt_kprintf("desc_index error!!!!,tick = %d\n", rt_tick_get());
+ while (1);
+ }
+
+ if (desc_index >= 0 && data1 != 0)
+ {
+ DEBUG_MES("Received Data at Rx Descriptor %d for skb 0x%08x whose status is %08x\n", desc_index, dma_addr1, status);
+
+ if (synopGMAC_is_rx_desc_valid(status) || SYNOP_PHY_LOOPBACK)
+ {
+ dma_addr1 = plat_dma_map_single(gmacdev, (void *)data1, RX_BUF_SIZE);
+ len = synopGMAC_get_rx_desc_frame_length(status) - 4; //Not interested in Ethernet CRC bytes
+ pbuf = pbuf_alloc(PBUF_LINK, len, PBUF_RAM);
+ if (pbuf == 0) rt_kprintf("===error in pbuf_alloc\n");
+ rt_memcpy(pbuf->payload, (char *)data1, len);
+ DEBUG_MES("==get pkg len: %d\n", len);
+ }
+ else
+ {
+ rt_kprintf("s: %08x\n", status);
+ adapter->synopGMACNetStats.rx_errors++;
+ adapter->synopGMACNetStats.collisions += synopGMAC_is_rx_frame_collision(status);
+ adapter->synopGMACNetStats.rx_crc_errors += synopGMAC_is_rx_crc(status);
+ adapter->synopGMACNetStats.rx_frame_errors += synopGMAC_is_frame_dribbling_errors(status);
+ adapter->synopGMACNetStats.rx_length_errors += synopGMAC_is_rx_frame_length_errors(status);
+ }
+ desc_index = synopGMAC_set_rx_qptr(gmacdev, dma_addr1, RX_BUF_SIZE, (u64)data1, 0, 0, 0);
+ if (desc_index < 0)
+ {
+#if SYNOP_RX_DEBUG
+ rt_kprintf("Cannot set Rx Descriptor for data1 %08x\n", (u32)data1);
+#endif
+
+ plat_free_memory((void *)data1);
+ }
+ }
+ rt_sem_release(&sem_lock);
+ DEBUG_MES("%s : before return \n", __FUNCTION__);
+ return pbuf;
+}
+
+static int rtl88e1111_config_init(synopGMACdevice *gmacdev)
+{
+ int retval, err;
+ u16 data;
+
+ DEBUG_MES("in %s\n", __FUNCTION__);
+ synopGMAC_read_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x14, &data);
+ data = data | 0x82;
+ err = synopGMAC_write_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x14, data);
+ synopGMAC_read_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x00, &data);
+ data = data | 0x8000;
+ err = synopGMAC_write_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x00, data);
+#if SYNOP_PHY_LOOPBACK
+ synopGMAC_read_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x14, &data);
+ data = data | 0x70;
+ data = data & 0xffdf;
+ err = synopGMAC_write_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x14, data);
+ data = 0x8000;
+ err = synopGMAC_write_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x00, data);
+ data = 0x5140;
+ err = synopGMAC_write_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x00, data);
+#endif
+ if (err < 0)
+ return err;
+ return 0;
+}
+
+int init_phy(synopGMACdevice *gmacdev)
+{
+ u16 data;
+
+ synopGMAC_read_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 2, &data);
+ /*set 88e1111 clock phase delay*/
+ if (data == 0x141)
+ rtl88e1111_config_init(gmacdev);
+#if defined (RMII)
+ else if (data == 0x8201)
+ {
+ //RTL8201
+ data = 0x400; // set RMII mode
+ synopGMAC_write_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x19, data);
+ synopGMAC_read_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x19, &data);
+ TR("phy reg25 is %0x \n", data);
+
+ data = 0x3100; //set 100M speed
+ synopGMAC_write_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x0, data);
+ }
+ else if (data == 0x0180 || data == 0x0181)
+ {
+ //DM9161
+ synopGMAC_read_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x10, &data);
+ data |= (1 << 8); //set RMII mode
+ synopGMAC_write_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x10, data); //set RMII mode
+ synopGMAC_read_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x10, &data);
+ TR("phy reg16 is 0x%0x \n", data);
+
+ // synopGMAC_read_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0x0,&data);
+ // data &= ~(1<<10);
+ data = 0x3100; //set auto-
+ //data = 0x0100; //set 10M speed
+ synopGMAC_write_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x0, data);
+ }
+#endif
+
+ return 0;
+}
+
+u32 synopGMAC_wakeup_filter_config3[] =
+{
+ 0x00000000,
+ 0x000000FF,
+ 0x00000000,
+ 0x00000000,
+ 0x00000100,
+ 0x00003200,
+ 0x7eED0000,
+ 0x00000000
+};
+
+static void synopGMAC_linux_powerdown_mac(synopGMACdevice *gmacdev)
+{
+ rt_kprintf("Put the GMAC to power down mode..\n");
+
+ GMAC_Power_down = 1;
+
+ synopGMAC_disable_dma_tx(gmacdev);
+ plat_delay(10000);
+
+ synopGMAC_tx_disable(gmacdev);
+ synopGMAC_rx_disable(gmacdev);
+ plat_delay(10000);
+
+ synopGMAC_disable_dma_rx(gmacdev);
+
+ synopGMAC_magic_packet_enable(gmacdev);
+ synopGMAC_write_wakeup_frame_register(gmacdev, synopGMAC_wakeup_filter_config3);
+
+ synopGMAC_wakeup_frame_enable(gmacdev);
+
+ synopGMAC_rx_enable(gmacdev);
+
+ synopGMAC_pmt_int_enable(gmacdev);
+
+ synopGMAC_power_down_enable(gmacdev);
+ return;
+}
+
+static void synopGMAC_linux_powerup_mac(synopGMACdevice *gmacdev)
+{
+ GMAC_Power_down = 0;
+ if (synopGMAC_is_magic_packet_received(gmacdev))
+ rt_kprintf("GMAC wokeup due to Magic Pkt Received\n");
+ if (synopGMAC_is_wakeup_frame_received(gmacdev))
+ rt_kprintf("GMAC wokeup due to Wakeup Frame Received\n");
+
+ synopGMAC_pmt_int_disable(gmacdev);
+
+ synopGMAC_rx_enable(gmacdev);
+ synopGMAC_enable_dma_rx(gmacdev);
+
+ synopGMAC_tx_enable(gmacdev);
+ synopGMAC_enable_dma_tx(gmacdev);
+ return;
+}
+
+
+static int mdio_read(synopGMACPciNetworkAdapter *adapter, int addr, int reg)
+{
+ synopGMACdevice *gmacdev;
+ u16 data;
+ gmacdev = adapter->synopGMACdev;
+
+ synopGMAC_read_phy_reg(gmacdev->MacBase, addr, reg, &data);
+ return data;
+}
+
+static void mdio_write(synopGMACPciNetworkAdapter *adapter, int addr, int reg, int data)
+{
+ synopGMACdevice *gmacdev;
+ gmacdev = adapter->synopGMACdev;
+ synopGMAC_write_phy_reg(gmacdev->MacBase, addr, reg, data);
+}
+
+void eth_rx_irq(int irqno, void *param)
+{
+ struct rt_eth_dev *dev = &eth_dev;
+ struct synopGMACNetworkAdapter *adapter = dev->priv;
+ //DEBUG_MES("in irq!!\n");
+#ifdef RT_USING_GMAC_INT_MODE
+ int i ;
+ for (i = 0; i < 7200; i++)
+ ;
+#endif /*RT_USING_GMAC_INT_MODE*/
+ synopGMACdevice *gmacdev = (synopGMACdevice *)adapter->synopGMACdev;
+
+ u32 interrupt, dma_status_reg;
+ s32 status;
+ u32 dma_addr;
+
+ //rt_kprintf("irq i = %d\n", i++);
+ dma_status_reg = synopGMACReadReg(gmacdev->DmaBase, DmaStatus);
+ if (dma_status_reg == 0)
+ {
+ rt_kprintf("dma_status ==0 \n");
+ return;
+ }
+
+ //rt_kprintf("dma_status_reg is 0x%x\n", dma_status_reg);
+ u32 gmacstatus;
+ synopGMAC_disable_interrupt_all(gmacdev);
+ gmacstatus = synopGMACReadReg(gmacdev->MacBase, GmacStatus);
+
+ if (dma_status_reg & GmacPmtIntr)
+ {
+ rt_kprintf("%s:: Interrupt due to PMT module\n", __FUNCTION__);
+ //synopGMAC_linux_powerup_mac(gmacdev);
+ }
+ if (dma_status_reg & GmacMmcIntr)
+ {
+ rt_kprintf("%s:: Interrupt due to MMC module\n", __FUNCTION__);
+ DEBUG_MES("%s:: synopGMAC_rx_int_status = %08x\n", __FUNCTION__, synopGMAC_read_mmc_rx_int_status(gmacdev));
+ DEBUG_MES("%s:: synopGMAC_tx_int_status = %08x\n", __FUNCTION__, synopGMAC_read_mmc_tx_int_status(gmacdev));
+ }
+
+ if (dma_status_reg & GmacLineIntfIntr)
+ {
+ //rt_kprintf("%s:: Interrupt due to GMAC LINE module\n", __FUNCTION__);
+ }
+
+ interrupt = synopGMAC_get_interrupt_type(gmacdev);
+ //rt_kprintf("%s:Interrupts to be handled: 0x%08x\n",__FUNCTION__,interrupt);
+ if (interrupt & synopGMACDmaError)
+ {
+ u8 mac_addr0[6];
+ rt_kprintf("%s::Fatal Bus Error Inetrrupt Seen\n", __FUNCTION__);
+
+ memcpy(mac_addr0, dev->dev_addr, 6);
+ synopGMAC_disable_dma_tx(gmacdev);
+ synopGMAC_disable_dma_rx(gmacdev);
+
+ synopGMAC_take_desc_ownership_tx(gmacdev);
+ synopGMAC_take_desc_ownership_rx(gmacdev);
+
+ synopGMAC_init_tx_rx_desc_queue(gmacdev);
+
+ synopGMAC_reset(gmacdev);
+
+ synopGMAC_set_mac_addr(gmacdev, GmacAddr0High, GmacAddr0Low, mac_addr0);
+ synopGMAC_dma_bus_mode_init(gmacdev, DmaFixedBurstEnable | DmaBurstLength8 | DmaDescriptorSkip1);
+ synopGMAC_dma_control_init(gmacdev, DmaStoreAndForward);
+ synopGMAC_init_rx_desc_base(gmacdev);
+ synopGMAC_init_tx_desc_base(gmacdev);
+ synopGMAC_mac_init(gmacdev);
+ synopGMAC_enable_dma_rx(gmacdev);
+ synopGMAC_enable_dma_tx(gmacdev);
+
+ }
+ if (interrupt & synopGMACDmaRxNormal)
+ {
+ //DEBUG_MES("%s:: Rx Normal \n", __FUNCTION__);
+ //synop_handle_received_data(netdev);
+ eth_device_ready(&eth_dev.parent);
+ }
+ if (interrupt & synopGMACDmaRxAbnormal)
+ {
+ //rt_kprintf("%s::Abnormal Rx Interrupt Seen\n",__FUNCTION__);
+ if (GMAC_Power_down == 0)
+ {
+ adapter->synopGMACNetStats.rx_over_errors++;
+ synopGMACWriteReg(gmacdev->DmaBase, DmaStatus, 0x80);
+ synopGMAC_resume_dma_rx(gmacdev);
+ }
+ }
+ if (interrupt & synopGMACDmaRxStopped)
+ {
+ rt_kprintf("%s::Receiver stopped seeing Rx interrupts\n", __FUNCTION__); //Receiver gone in to stopped state
+ }
+
+ if (interrupt & synopGMACDmaTxNormal)
+ {
+ DEBUG_MES("%s::Finished Normal Transmission \n", __FUNCTION__);
+ // synop_handle_transmit_over(netdev);
+ }
+
+ if (interrupt & synopGMACDmaTxAbnormal)
+ {
+ rt_kprintf("%s::Abnormal Tx Interrupt Seen\n", __FUNCTION__);
+ }
+ if (interrupt & synopGMACDmaTxStopped)
+ {
+ TR("%s::Transmitter stopped sending the packets\n", __FUNCTION__);
+ if (GMAC_Power_down == 0) // If Mac is not in powerdown
+ {
+ synopGMAC_disable_dma_tx(gmacdev);
+ synopGMAC_take_desc_ownership_tx(gmacdev);
+
+ synopGMAC_enable_dma_tx(gmacdev);
+ // netif_wake_queue(netdev);
+ TR("%s::Transmission Resumed\n", __FUNCTION__);
+ }
+ }
+ /* Enable the interrrupt before returning from ISR*/
+ synopGMAC_enable_interrupt(gmacdev, DmaIntEnable);
+
+ return;
+}
+
+int rt_hw_eth_init(void)
+{
+ struct pci_header *p = (struct pci_header *)(0x9000000000000000 | PCI_BASE);
+ gmac_base = (0x9000000000000000 | ((p->BaseAddressRegister[0]) & 0xffffff00));
+
+ struct synopGMACNetworkAdapter *synopGMACadapter;
+ static u8 mac_addr0[6] = DEFAULT_MAC_ADDRESS;
+ int index;
+ rt_sem_init(&sem_ack, "tx_ack", 1, RT_IPC_FLAG_FIFO);
+ rt_sem_init(&sem_lock, "eth_lock", 1, RT_IPC_FLAG_FIFO);
+
+ memset(&eth_dev, 0, sizeof(eth_dev));
+ synopGMACadapter = (struct synopGMACNetworkAdapter *)plat_alloc_memory(sizeof(struct synopGMACNetworkAdapter));
+ if (!synopGMACadapter)
+ {
+ rt_kprintf("Error in Memory Allocataion, Founction : %s \n", __FUNCTION__);
+ }
+ memset((char *)synopGMACadapter, 0, sizeof(struct synopGMACNetworkAdapter));
+
+ synopGMACadapter->synopGMACdev = NULL;
+
+ synopGMACadapter->synopGMACdev = (synopGMACdevice *) plat_alloc_memory(sizeof(synopGMACdevice));
+ if (!synopGMACadapter->synopGMACdev)
+ {
+ rt_kprintf("Error in Memory Allocataion, Founction : %s \n", __FUNCTION__);
+ }
+
+ memset((char *)synopGMACadapter->synopGMACdev, 0, sizeof(synopGMACdevice));
+
+ /*
+ * Attach the device to MAC struct This will configure all the required base addresses
+ * such as Mac base, configuration base, phy base address(out of 32 possible phys)
+ * */
+ synopGMAC_attach(synopGMACadapter->synopGMACdev, (gmac_base + MACBASE), gmac_base + DMABASE, DEFAULT_PHY_BASE, mac_addr0);
+
+ init_phy(synopGMACadapter->synopGMACdev);
+ synopGMAC_reset(synopGMACadapter->synopGMACdev);
+
+ /* MII setup */
+ synopGMACadapter->mii.phy_id_mask = 0x1F;
+ synopGMACadapter->mii.reg_num_mask = 0x1F;
+ synopGMACadapter->mii.dev = synopGMACadapter;
+ synopGMACadapter->mii.mdio_read = mdio_read;
+ synopGMACadapter->mii.mdio_write = mdio_write;
+ synopGMACadapter->mii.phy_id = synopGMACadapter->synopGMACdev->PhyBase;
+ synopGMACadapter->mii.supports_gmii = mii_check_gmii_support(&synopGMACadapter->mii);
+
+ eth_dev.iobase = gmac_base;
+ eth_dev.name = "e0";
+ eth_dev.priv = synopGMACadapter;
+ eth_dev.dev_addr[0] = mac_addr0[0];
+ eth_dev.dev_addr[1] = mac_addr0[1];
+ eth_dev.dev_addr[2] = mac_addr0[2];
+ eth_dev.dev_addr[3] = mac_addr0[3];
+ eth_dev.dev_addr[4] = mac_addr0[4];
+ eth_dev.dev_addr[5] = mac_addr0[5];
+
+ eth_dev.parent.parent.type = RT_Device_Class_NetIf;
+ eth_dev.parent.parent.init = eth_init;
+ eth_dev.parent.parent.open = eth_open;
+ eth_dev.parent.parent.close = eth_close;
+ eth_dev.parent.parent.read = eth_read;
+ eth_dev.parent.parent.write = eth_write;
+ eth_dev.parent.parent.control = eth_control;
+ eth_dev.parent.parent.user_data = RT_NULL;
+
+ eth_dev.parent.eth_tx = rt_eth_tx;
+ eth_dev.parent.eth_rx = rt_eth_rx;
+
+ eth_device_init(&(eth_dev.parent), "e0");
+ eth_device_linkchange(&eth_dev.parent, RT_TRUE); //linkup the e0 for lwip to check
+ return 0;
+}
+INIT_COMPONENT_EXPORT(rt_hw_eth_init);
diff --git a/bsp/ls2kdev/drivers/net/synopGMAC.h b/bsp/ls2kdev/drivers/net/synopGMAC.h
new file mode 100644
index 0000000000..a1369ae00f
--- /dev/null
+++ b/bsp/ls2kdev/drivers/net/synopGMAC.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2017-08-24 chinesebear first version
+ */
+
+#ifndef __SYNOPGMAC__H
+#define __SYNOPGMAC__H
+
+#include "synopGMAC_network_interface.h"
+#include "synopGMAC_Host.h"
+#include "synopGMAC_Dev.h"
+#include "synopGMAC_plat.h"
+#include "mii.h"
+#include "synopGMAC_types.h"
+
+int rt_hw_eth_init(void);
+
+#endif /*__SYNOPGMAC__H*/
diff --git a/bsp/ls2kdev/drivers/net/synopGMAC_Dev.c b/bsp/ls2kdev/drivers/net/synopGMAC_Dev.c
new file mode 100644
index 0000000000..e6fea9f2ec
--- /dev/null
+++ b/bsp/ls2kdev/drivers/net/synopGMAC_Dev.c
@@ -0,0 +1,3750 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2017-08-24 chinesebear first version
+ * 2020-08-10 lizhirui porting to ls2k
+ */
+
+#include "synopGMAC_Dev.h"
+#include <rthw.h>
+#include <rtthread.h>
+
+#define UNUSED 1
+
+/**
+ * Function to set the MDC clock for mdio transactiona
+ *
+ * @param[in] pointer to device structure.
+ * @param[in] clk divider value.
+ * \return Reuturns 0 on success else return the error value.
+ */
+s32 synopGMAC_set_mdc_clk_div(synopGMACdevice *gmacdev, u32 clk_div_val)
+{
+ u32 orig_data;
+ orig_data = synopGMACReadReg(gmacdev -> MacBase, GmacGmiiAddr); //set the mdc clock to the user defined value
+ orig_data &= (~GmiiCsrClkMask);
+ orig_data |= clk_div_val;
+ synopGMACWriteReg(gmacdev -> MacBase, GmacGmiiAddr, orig_data);
+ return 0;
+}
+
+/**
+ * Returns the current MDC divider value programmed in the ip.
+ *
+ * @param[in] pointer to device structure.
+ * @param[in] clk divider value.
+ * \return Returns the MDC divider value read.
+ */
+u32 synopGMAC_get_mdc_clk_div(synopGMACdevice *gmacdev)
+{
+ u32 data;
+ data = synopGMACReadReg(gmacdev->MacBase, GmacGmiiAddr);
+ data &= GmiiCsrClkMask;
+ return data;
+}
+
+
+/**
+ * Function to read the Phy register. The access to phy register
+ * is a slow process as the data is moved accross MDI/MDO interface
+ * @param[in] pointer to Register Base (It is the mac base in our case) .
+ * @param[in] PhyBase register is the index of one of supported 32 PHY devices.
+ * @param[in] Register offset is the index of one of the 32 phy register.
+ * @param[out] u16 data read from the respective phy register (only valid iff return value is 0).
+ * \return Returns 0 on success else return the error status.
+ */
+s32 synopGMAC_read_phy_reg(u64 RegBase, u32 PhyBase, u32 RegOffset, u16 *data)
+{
+ u64 addr;
+ u32 loop_variable;
+ addr = ((PhyBase << GmiiDevShift) & GmiiDevMask) | ((RegOffset << GmiiRegShift) & GmiiRegMask)
+ | GmiiCsrClk3; //sw: add GmiiCsrClk
+ addr = addr | GmiiBusy ; //Gmii busy bit
+
+ synopGMACWriteReg(RegBase, GmacGmiiAddr, addr);
+ //write the address from where the data to be read in GmiiGmiiAddr register of synopGMAC ip
+
+ for (loop_variable = 0; loop_variable < DEFAULT_LOOP_VARIABLE; loop_variable++)
+ {
+ //Wait till the busy bit gets cleared within a certain amount of time
+ if (!(synopGMACReadReg(RegBase, GmacGmiiAddr) & GmiiBusy))
+ {
+ break;
+ }
+
+ plat_delay(DEFAULT_DELAY_VARIABLE);
+ }
+
+ if (loop_variable < DEFAULT_LOOP_VARIABLE)
+ {
+ *data = (u16)(synopGMACReadReg(RegBase, GmacGmiiData) & 0xFFFF);
+ }
+ else
+ {
+ TR("Error::: PHY not responding Busy bit didnot get cleared !!!!!!\n");
+ return -ESYNOPGMACPHYERR;
+ }
+ //sw
+#if SYNOP_REG_DEBUG
+ printf("read phy reg: offset = 0x%x\tdata = 0x%x\n", RegOffset, *data);
+#endif
+
+ return -ESYNOPGMACNOERR;
+}
+
+/**
+ * Function to write to the Phy register. The access to phy register
+ * is a slow process as the data is moved accross MDI/MDO interface
+ * @param[in] pointer to Register Base (It is the mac base in our case) .
+ * @param[in] PhyBase register is the index of one of supported 32 PHY devices.
+ * @param[in] Register offset is the index of one of the 32 phy register.
+ * @param[in] data to be written to the respective phy register.
+ * \return Returns 0 on success else return the error status.
+ */
+s32 synopGMAC_write_phy_reg(u64 RegBase, u32 PhyBase, u32 RegOffset, u16 data)
+{
+ u32 addr;
+ u32 loop_variable;
+
+ synopGMACWriteReg(RegBase, GmacGmiiData, data); // write the data in to GmacGmiiData register of synopGMAC ip
+
+ addr = ((PhyBase << GmiiDevShift) & GmiiDevMask) | ((RegOffset << GmiiRegShift) & GmiiRegMask) | GmiiWrite | GmiiCsrClk3; //sw: add GmiiCsrclk
+
+ addr = addr | GmiiBusy ; //set Gmii clk to 20-35 Mhz and Gmii busy bit
+
+ synopGMACWriteReg(RegBase, GmacGmiiAddr, addr);
+ for (loop_variable = 0; loop_variable < DEFAULT_LOOP_VARIABLE; loop_variable++)
+ {
+ if (!(synopGMACReadReg(RegBase, GmacGmiiAddr) & GmiiBusy))
+ {
+ break;
+ }
+
+ plat_delay(DEFAULT_DELAY_VARIABLE);
+ }
+
+ if (loop_variable < DEFAULT_LOOP_VARIABLE)
+ {
+ return -ESYNOPGMACNOERR;
+ }
+ else
+ {
+ TR("Error::: PHY not responding Busy bit didnot get cleared !!!!!!\n");
+ return -ESYNOPGMACPHYERR;
+ }
+#if SYNOP_REG_DEBUG
+ printf("write phy reg: offset = 0x%x\tdata = 0x%x", RegOffset, data);
+#endif
+}
+
+/**
+ * Function to configure the phy in loopback mode.
+ *
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] enable or disable the loopback.
+ * \return 0 on success else return the error status.
+ * \note Don't get confused with mac loop-back synopGMAC_loopback_on(synopGMACdevice *)
+ * and synopGMAC_loopback_off(synopGMACdevice *) functions.
+ */
+#if UNUSED
+s32 synopGMAC_phy_loopback(synopGMACdevice *gmacdev, bool loopback)
+{
+ s32 status = -ESYNOPGMACNOERR;
+ u16 temp;
+
+ status = synopGMAC_read_phy_reg(gmacdev -> MacBase, gmacdev -> PhyBase, PHY_CONTROL_REG, &temp);
+
+ if (loopback)
+ {
+ temp |= 0x4000;
+ }
+ else
+ {
+ temp = temp;
+ }
+
+ status = synopGMAC_write_phy_reg(gmacdev -> MacBase, gmacdev -> PhyBase, PHY_CONTROL_REG, temp);
+ return status;
+}
+
+#endif
+
+/**
+ * Function to read the GMAC IP Version and populates the same in device data structure.
+ * @param[in] pointer to synopGMACdevice.
+ * \return Always return 0.
+ */
+
+s32 synopGMAC_read_version(synopGMACdevice *gmacdev)
+{
+ u32 data = 0;
+ data = synopGMACReadReg(gmacdev -> MacBase, GmacVersion);
+ gmacdev -> Version = data;
+ return 0;
+}
+
+
+/**
+ * Function to reset the GMAC core.
+ * This reests the DMA and GMAC core. After reset all the registers holds their respective reset value
+ * @param[in] pointer to synopGMACdevice.
+ * \return 0 on success else return the error status.
+ */
+s32 synopGMAC_reset(synopGMACdevice *gmacdev)
+{
+ u32 data = 0;
+ synopGMACWriteReg(gmacdev -> DmaBase, DmaBusMode, DmaResetOn);
+ plat_delay(DEFAULT_LOOP_VARIABLE);
+ data = synopGMACReadReg(gmacdev -> DmaBase, DmaBusMode);
+ TR("DATA after Reset = %08x\n", data);
+
+ return 0;
+}
+
+
+/**
+ * Function to program DMA bus mode register.
+ *
+ * The Bus Mode register is programmed with the value given. The bits to be set are
+ * bit wise or'ed and sent as the second argument to this function.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] the data to be programmed.
+ * \return 0 on success else return the error status.
+ */
+s32 synopGMAC_dma_bus_mode_init(synopGMACdevice *gmacdev, u32 init_value)
+{
+ synopGMACWriteReg(gmacdev -> DmaBase, DmaBusMode, init_value);
+ return 0;
+}
+
+/**
+ * Function to program DMA Control register(Operation Mode Register 0x18).
+ *
+ * The Dma Control register is programmed with the value given. The bits to be set are
+ * bit wise or'ed and sent as the second argument to this function.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] the data to be programmed.
+ * \return 0 on success else return the error status.
+ */
+s32 synopGMAC_dma_control_init(synopGMACdevice *gmacdev, u32 init_value)
+{
+ synopGMACWriteReg(gmacdev -> DmaBase, DmaControl, init_value);
+ return 0;
+}
+
+
+/*Gmac configuration functions*/
+
+/**
+ * Enable the watchdog timer on the receiver.
+ * When enabled, Gmac enables Watchdog timer, and GMAC allows no more than
+ * 2048 bytes of data (10,240 if Jumbo frame enabled).
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_wd_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev -> MacBase, GmacConfig, GmacWatchdog);
+ return;
+}
+/**
+ * Disable the watchdog timer on the receiver.
+ * When disabled, Gmac disabled watchdog timer, and can receive frames up to
+ * 16,384 bytes.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+
+void synopGMAC_wd_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacWatchdog);
+ return;
+}
+
+/**
+ * Enables the Jabber frame support.
+ * When enabled, GMAC disabled the jabber timer, and can transfer 16,384 byte frames.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_jab_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev -> MacBase, GmacConfig, GmacJabber);
+ return;
+}
+/**
+ * Disables the Jabber frame support.
+ * When disabled, GMAC enables jabber timer. It cuts of transmitter if application
+ * sends more than 2048 bytes of data (10240 if Jumbo frame enabled).
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+#if UNUSED
+void synopGMAC_jab_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacJabber);
+ return;
+}
+#endif
+
+/**
+ * Enables Frame bursting (Only in Half Duplex Mode).
+ * When enabled, GMAC allows frame bursting in GMII Half Duplex mode.
+ * Reserved in 10/100 and Full-Duplex configurations.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_frame_burst_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacFrameBurst);
+ return;
+}
+/**
+ * Disables Frame bursting.
+ * When Disabled, frame bursting is not supported.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+#if UNUSED
+void synopGMAC_frame_burst_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev -> MacBase, GmacConfig, GmacFrameBurst);
+ return;
+}
+#endif
+
+/**
+ * Enable Jumbo frame support.
+ * When Enabled GMAC supports jumbo frames of 9018/9022(VLAN tagged).
+ * Giant frame error is not reported in receive frame status.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+#if UNUSED
+void synopGMAC_jumbo_frame_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacJumboFrame);
+ return;
+}
+#endif
+/**
+ * Disable Jumbo frame support.
+ * When Disabled GMAC does not supports jumbo frames.
+ * Giant frame error is reported in receive frame status.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_jumbo_frame_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev -> MacBase, GmacConfig, GmacJumboFrame);
+ return;
+}
+
+/**
+ * Disable Carrier sense.
+ * When Disabled GMAC ignores CRS signal during frame transmission
+ * in half duplex mode.
+ * @param[in] pointer to synopGMACdevice.
+ * \return void.
+ */
+
+#if UNUSED
+void synopGMAC_disable_crs(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacDisableCrs);
+ return;
+}
+#endif
+
+
+
+/**
+ * Selects the GMII port.
+ * When called GMII (1000Mbps) port is selected (programmable only in 10/100/1000 Mbps configuration).
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_select_gmii(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev -> MacBase, GmacConfig, GmacMiiGmii);
+ return;
+}
+/**
+ * Selects the MII port.
+ * When called MII (10/100Mbps) port is selected (programmable only in 10/100/1000 Mbps configuration).
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_select_mii(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacMiiGmii);
+ return;
+}
+
+/**
+ * Enables Receive Own bit (Only in Half Duplex Mode).
+ * When enaled GMAC receives all the packets given by phy while transmitting.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_rx_own_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev -> MacBase, GmacConfig, GmacRxOwn);
+ return;
+}
+/**
+ * Disables Receive Own bit (Only in Half Duplex Mode).
+ * When enaled GMAC disables the reception of frames when gmii_txen_o is asserted.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+#if UNUSED
+void synopGMAC_rx_own_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacRxOwn);
+ return;
+}
+#endif
+
+/**
+ * Sets the GMAC in loopback mode.
+ * When on GMAC operates in loop-back mode at GMII/MII.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ * \note (G)MII Receive clock is required for loopback to work properly, as transmit clock is
+ * not looped back internally.
+ */
+void synopGMAC_loopback_on(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacLoopback);
+ return;
+}
+/**
+ * Sets the GMAC in Normal mode.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_loopback_off(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev -> MacBase, GmacConfig, GmacLoopback);
+ return;
+}
+
+/**
+ * Sets the GMAC core in Full-Duplex mode.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_set_full_duplex(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacDuplex);
+ return;
+}
+/**
+ * Sets the GMAC core in Half-Duplex mode.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_set_half_duplex(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev -> MacBase, GmacConfig, GmacDuplex);
+ return;
+}
+
+/**
+ * GMAC tries retransmission (Only in Half Duplex mode).
+ * If collision occurs on the GMII/MII, GMAC attempt retries based on the
+ * back off limit configured.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ * \note This function is tightly coupled with synopGMAC_back_off_limit(synopGMACdev *, u32).
+ */
+void synopGMAC_retry_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev -> MacBase, GmacConfig, GmacRetry);
+ return;
+}
+/**
+ * GMAC tries only one transmission (Only in Half Duplex mode).
+ * If collision occurs on the GMII/MII, GMAC will ignore the current frami
+ * transmission and report a frame abort with excessive collision in tranmit frame status.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+#if UNUSED
+void synopGMAC_retry_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacRetry);
+ return;
+}
+#endif
+
+/**
+ * GMAC strips the Pad/FCS field of incoming frames.
+ * This is true only if the length field value is less than or equal to
+ * 1500 bytes. All received frames with length field greater than or equal to
+ * 1501 bytes are passed to the application without stripping the Pad/FCS field.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+#if UNUSED
+void synopGMAC_pad_crc_strip_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacPadCrcStrip);
+ return;
+}
+#endif
+/**
+ * GMAC doesnot strips the Pad/FCS field of incoming frames.
+ * GMAC will pass all the incoming frames to Host unmodified.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_pad_crc_strip_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev -> MacBase, GmacConfig, GmacPadCrcStrip);
+ u32 status = synopGMACReadReg(gmacdev -> MacBase, GmacConfig);
+ DEBUG_MES("strips status : %u\n", status & GmacPadCrcStrip);
+ return;
+}
+/**
+ * GMAC programmed with the back off limit value.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ * \note This function is tightly coupled with synopGMAC_retry_enable(synopGMACdevice * gmacdev)
+ */
+void synopGMAC_back_off_limit(synopGMACdevice *gmacdev, u32 value)
+{
+ u32 data;
+ data = synopGMACReadReg(gmacdev -> MacBase, GmacConfig);
+ data &= (~GmacBackoffLimit);
+ data |= value;
+ synopGMACWriteReg(gmacdev -> MacBase, GmacConfig, data);
+ return;
+}
+
+/**
+ * Enables the Deferral check in GMAC (Only in Half Duplex mode)
+ * GMAC issues a Frame Abort Status, along with the excessive deferral error bit set in the
+ * transmit frame status when transmit state machine is deferred for more than
+ * - 24,288 bit times in 10/100Mbps mode
+ * - 155,680 bit times in 1000Mbps mode or Jumbo frame mode in 10/100Mbps operation.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ * \note Deferral begins when transmitter is ready to transmit, but is prevented because of
+ * an active CRS (carrier sense)
+ */
+#if UNUSED
+void synopGMAC_deferral_check_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacDeferralCheck);
+ return;
+}
+#endif
+/**
+ * Disables the Deferral check in GMAC (Only in Half Duplex mode).
+ * GMAC defers until the CRS signal goes inactive.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_deferral_check_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev -> MacBase, GmacConfig, GmacDeferralCheck);
+ return;
+}
+/**
+ * Enable the reception of frames on GMII/MII.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_rx_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacRx);
+ return;
+}
+/**
+ * Disable the reception of frames on GMII/MII.
+ * GMAC receive state machine is disabled after completion of reception of current frame.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+#if UNUSED
+void synopGMAC_rx_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev -> MacBase, GmacConfig, GmacRx);
+ return;
+}
+#endif
+/**
+ * Enable the transmission of frames on GMII/MII.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_tx_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacTx);
+ return;
+}
+/**
+ * Disable the transmission of frames on GMII/MII.
+ * GMAC transmit state machine is disabled after completion of transmission of current frame.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+#if UNUSED
+void synopGMAC_tx_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev -> MacBase, GmacConfig, GmacTx);
+ return;
+}
+#endif
+
+
+/*Receive frame filter configuration functions*/
+
+/**
+ * Disables reception of all the frames to application.
+ * GMAC passes only those received frames to application which
+ * pass SA/DA address filtering.
+ * @param[in] pointer to synopGMACdevice.
+ * \return void.
+ */
+void synopGMAC_frame_filter_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev -> MacBase, GmacFrameFilter, GmacFilter);
+ return;
+}
+
+/**
+ * Enables reception of all the frames to application.
+ * GMAC passes all the frames received to application irrespective of whether they
+ * pass SA/DA address filtering or not.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_frame_filter_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev -> MacBase, GmacFrameFilter, GmacFilter);
+ return;
+}
+
+/**
+ * Populates the Hash High register with the data supplied.
+ * This function is called when the Hash filtering is to be enabled.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] data to be written to hash table high register.
+ * \return void.
+ */
+#if UNUSED
+void synopGMAC_write_hash_table_high(synopGMACdevice *gmacdev, u32 data)
+{
+ synopGMACWriteReg(gmacdev -> MacBase, GmacHashHigh, data);
+ return;
+}
+#endif
+
+/**
+ * Populates the Hash Low register with the data supplied.
+ * This function is called when the Hash filtering is to be enabled.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] data to be written to hash table low register.
+ * \return void.
+ */
+#if UNUSED
+void synopGMAC_write_hash_table_low(synopGMACdevice *gmacdev, u32 data)
+{
+ synopGMACWriteReg(gmacdev -> MacBase, GmacHashLow, data);
+ return;
+}
+#endif
+
+/**
+ * Enables Hash or Perfect filter (only if Hash filter is enabled in H/W).
+ * Only frames matching either perfect filtering or Hash Filtering as per HMC and HUC
+ * configuration are sent to application.
+ * @param[in] pointer to synopGMACdevice.
+ * \return void.
+ */
+#if UNUSED
+void synopGMAC_hash_perfect_filter_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev -> MacBase, GmacFrameFilter, GmacHashPerfectFilter);
+ return;
+}
+#endif
+
+/**
+ * Enables only Hash(only if Hash filter is enabled in H/W).
+ * Only frames matching Hash Filtering as per HMC and HUC
+ * configuration are sent to application.
+ * @param[in] pointer to synopGMACdevice.
+ * \return void.
+ */
+#if UNUSED
+void synopGMAC_Hash_filter_only_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev -> MacBase, GmacFrameFilter, GmacHashPerfectFilter);
+ return;
+}
+#endif
+
+/**
+ * Enables Source address filtering.
+ * When enabled source address filtering is performed. Only frames matching SA filtering are passed to application with
+ * SAMatch bit of RxStatus is set. GMAC drops failed frames.
+ * @param[in] pointer to synopGMACdevice.
+ * \return void.
+ * \note This function is overriden by synopGMAC_frame_filter_disable(synopGMACdevice *)
+ */
+#if UNUSED
+void synopGMAC_src_addr_filter_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev -> MacBase, GmacFrameFilter, GmacSrcAddrFilter);
+ return;
+}
+#endif
+/**
+ * Disables Source address filtering.
+ * When disabled GMAC forwards the received frames with updated SAMatch bit in RxStatus.
+ * @param[in] pointer to synopGMACdevice.
+ * \return void.
+ */
+void synopGMAC_src_addr_filter_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev -> MacBase, GmacFrameFilter, GmacSrcAddrFilter);
+ return;
+}
+/**
+ * Enables Inverse Destination address filtering.
+ * @param[in] pointer to synopGMACdevice.
+ * \return void.
+ */
+#if UNUSED
+void synopGMAC_dst_addr_filter_inverse(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev -> MacBase, GmacFrameFilter, GmacDestAddrFilterInv);
+ return;
+}
+#endif
+/**
+ * Enables the normal Destination address filtering.
+ * @param[in] pointer to synopGMACdevice.
+ * \return void.
+ */
+void synopGMAC_dst_addr_filter_normal(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev -> MacBase, GmacFrameFilter, GmacDestAddrFilterInv);
+ return;
+}
+
+/**
+ * Enables forwarding of control frames.
+ * When set forwards all the control frames (incl. unicast and multicast PAUSE frames).
+ * @param[in] pointer to synopGMACdevice.
+ * \return void.
+ * \note Depends on RFE of FlowControlRegister[2]
+ */
+void synopGMAC_set_pass_control(synopGMACdevice *gmacdev, u32 passcontrol)
+{
+ u32 data;
+ data = synopGMACReadReg(gmacdev -> MacBase, GmacFrameFilter);
+ data &= (~GmacPassControl);
+ data |= passcontrol;
+ synopGMACWriteReg(gmacdev -> MacBase, GmacFrameFilter, data);
+ return;
+}
+
+/**
+ * Enables Broadcast frames.
+ * When enabled Address filtering module passes all incoming broadcast frames.
+ * @param[in] pointer to synopGMACdevice.
+ * \return void.
+ */
+void synopGMAC_broadcast_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev -> MacBase, GmacFrameFilter, GmacBroadcast);
+ return;
+}
+/**
+ * Disable Broadcast frames.
+ * When disabled Address filtering module filters all incoming broadcast frames.
+ * @param[in] pointer to synopGMACdevice.
+ * \return void.
+ */
+#if UNUSED
+void synopGMAC_broadcast_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev->MacBase, GmacFrameFilter, GmacBroadcast);
+ return;
+}
+#endif
+
+/**
+ * Enables Multicast frames.
+ * When enabled all multicast frames are passed.
+ * @param[in] pointer to synopGMACdevice.
+ * \return void.
+ */
+#if UNUSED
+void synopGMAC_multicast_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev -> MacBase, GmacFrameFilter, GmacMulticastFilter);
+ return;
+}
+#endif
+/**
+ * Disable Multicast frames.
+ * When disabled multicast frame filtering depends on HMC bit.
+ * @param[in] pointer to synopGMACdevice.
+ * \return void.
+ */
+void synopGMAC_multicast_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev -> MacBase, GmacFrameFilter, GmacMulticastFilter);
+ return;
+}
+
+/**
+ * Enables multicast hash filtering.
+ * When enabled GMAC performs teh destination address filtering according to the hash table.
+ * @param[in] pointer to synopGMACdevice.
+ * \return void.
+ */
+#if UNUSED
+void synopGMAC_multicast_hash_filter_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev -> MacBase, GmacFrameFilter, GmacMcastHashFilter);
+ return;
+}
+#endif
+/**
+ * Disables multicast hash filtering.
+ * When disabled GMAC performs perfect destination address filtering for multicast frames, it compares
+ * DA field with the value programmed in DA register.
+ * @param[in] pointer to synopGMACdevice.
+ * \return void.
+ */
+void synopGMAC_multicast_hash_filter_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev -> MacBase, GmacFrameFilter, GmacMcastHashFilter);
+ return;
+}
+
+/**
+ * Enables promiscous mode.
+ * When enabled Address filter modules pass all incoming frames regardless of their Destination
+ * and source addresses.
+ * @param[in] pointer to synopGMACdevice.
+ * \return void.
+ */
+#if UNUSED
+void synopGMAC_promisc_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev -> MacBase, GmacFrameFilter, GmacPromiscuousMode);
+ return;
+}
+#endif
+/**
+ * Clears promiscous mode.
+ * When called the GMAC falls back to normal operation from promiscous mode.
+ * @param[in] pointer to synopGMACdevice.
+ * \return void.
+ */
+void synopGMAC_promisc_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev -> MacBase, GmacFrameFilter, GmacPromiscuousMode);
+ return;
+}
+
+/**
+ * Enables unicast hash filtering.
+ * When enabled GMAC performs the destination address filtering of unicast frames according to the hash table.
+ * @param[in] pointer to synopGMACdevice.
+ * \return void.
+ */
+#if UNUSED
+void synopGMAC_unicast_hash_filter_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev -> MacBase, GmacFrameFilter, GmacUcastHashFilter);
+ return;
+}
+#endif
+/**
+ * Disables multicast hash filtering.
+ * When disabled GMAC performs perfect destination address filtering for unicast frames, it compares
+ * DA field with the value programmed in DA register.
+ * @param[in] pointer to synopGMACdevice.
+ * \return void.
+ */
+void synopGMAC_unicast_hash_filter_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev -> MacBase, GmacFrameFilter, GmacUcastHashFilter);
+ return;
+}
+
+/*Flow control configuration functions*/
+
+/**
+ * Enables detection of pause frames with stations unicast address.
+ * When enabled GMAC detects the pause frames with stations unicast address in addition to the
+ * detection of pause frames with unique multicast address.
+ * @param[in] pointer to synopGMACdevice.
+ * \return void.
+ */
+#if UNUSED
+void synopGMAC_unicast_pause_frame_detect_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev -> MacBase, GmacFlowControl, GmacUnicastPauseFrame);
+ return;
+}
+#endif
+/**
+ * Disables detection of pause frames with stations unicast address.
+ * When disabled GMAC only detects with the unique multicast address (802.3x).
+ * @param[in] pointer to synopGMACdevice.
+ * \return void.
+ */
+void synopGMAC_unicast_pause_frame_detect_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev -> MacBase, GmacFlowControl, GmacUnicastPauseFrame);
+ return;
+}
+/**
+ * Rx flow control enable.
+ * When Enabled GMAC will decode the rx pause frame and disable the tx for a specified time.
+ * @param[in] pointer to synopGMACdevice.
+ * \return void.
+ */
+void synopGMAC_rx_flow_control_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev -> MacBase, GmacFlowControl, GmacRxFlowControl);
+ return;
+}
+/**
+ * Rx flow control disable.
+ * When disabled GMAC will not decode pause frame.
+ * @param[in] pointer to synopGMACdevice.
+ * \return void.
+ */
+void synopGMAC_rx_flow_control_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev -> MacBase, GmacFlowControl, GmacRxFlowControl);
+ return;
+}
+/**
+ * Tx flow control enable.
+ * When Enabled
+ * - In full duplex GMAC enables flow control operation to transmit pause frames.
+ * - In Half duplex GMAC enables the back pressure operation
+ * @param[in] pointer to synopGMACdevice.
+ * \return void.
+ */
+void synopGMAC_tx_flow_control_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev -> MacBase, GmacFlowControl, GmacTxFlowControl);
+ return;
+}
+
+/**
+ * Tx flow control disable.
+ * When Disabled
+ * - In full duplex GMAC will not transmit any pause frames.
+ * - In Half duplex GMAC disables the back pressure feature.
+ * @param[in] pointer to synopGMACdevice.
+ * \return void.
+ */
+void synopGMAC_tx_flow_control_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev -> MacBase, GmacFlowControl, GmacTxFlowControl);
+ return;
+}
+
+/**
+ * Initiate Flowcontrol operation.
+ * When Set
+ * - In full duplex GMAC initiates pause control frame.
+ * - In Half duplex GMAC initiates back pressure function.
+ * @param[in] pointer to synopGMACdevice.
+ * \return void.
+ */
+#if UNUSED
+void synopGMAC_tx_activate_flow_control(synopGMACdevice *gmacdev)
+{
+ //In case of full duplex check for this bit to b'0. if it is read as b'1 indicates that
+ //control frame transmission is in progress.
+ if (gmacdev -> Speed == FULLDUPLEX)
+ {
+ if (!synopGMACCheckBits(gmacdev -> MacBase, GmacFlowControl, GmacFlowControlBackPressure))
+ {
+ synopGMACSetBits(gmacdev -> MacBase, GmacFlowControl, GmacFlowControlBackPressure);
+ }
+ }
+ else//if half duplex mode
+ {
+
+ synopGMACSetBits(gmacdev -> MacBase, GmacFlowControl, GmacFlowControlBackPressure);
+ }
+
+ return;
+}
+#endif
+
+/**
+ * stops Flowcontrol operation.
+ * @param[in] pointer to synopGMACdevice.
+ * \return void.
+ */
+#if UNUSED
+void synopGMAC_tx_deactivate_flow_control(synopGMACdevice *gmacdev)
+{
+ //In full duplex this bit is automatically cleared after transmitting a pause control frame.
+ if (gmacdev->Speed == HALFDUPLEX)
+ {
+ synopGMACSetBits(gmacdev -> MacBase, GmacFlowControl, GmacFlowControlBackPressure);
+ }
+
+ return;
+}
+#endif
+
+/**
+ * This enables the pause frame generation after programming the appropriate registers.
+ * presently activation is set at 3k and deactivation set at 4k. These may have to tweaked
+ * if found any issues
+ * @param[in] pointer to synopGMACdevice.
+ * \return void.
+ */
+void synopGMAC_pause_control(synopGMACdevice *gmacdev)
+{
+ u32 omr_reg;
+ u32 mac_flow_control_reg;
+ omr_reg = synopGMACReadReg(gmacdev -> DmaBase, DmaControl);
+ omr_reg |= DmaRxFlowCtrlAct4K | DmaRxFlowCtrlDeact5K | DmaEnHwFlowCtrl;
+ synopGMACWriteReg(gmacdev -> DmaBase, DmaControl, omr_reg);
+
+ mac_flow_control_reg = synopGMACReadReg(gmacdev -> MacBase, GmacFlowControl);
+ mac_flow_control_reg |= GmacRxFlowControl | GmacTxFlowControl | 0xFFFF0000;
+ synopGMACWriteReg(gmacdev -> MacBase, GmacFlowControl, mac_flow_control_reg);
+
+ return;
+}
+
+/**
+ * Example mac initialization sequence.
+ * This function calls the initialization routines to initialize the GMAC register.
+ * One can change the functions invoked here to have different configuration as per the requirement
+ * @param[in] pointer to synopGMACdevice.
+ * \return Returns 0 on success.
+ */
+s32 synopGMAC_mac_init(synopGMACdevice *gmacdev)
+{
+ u32 PHYreg;
+
+ if (gmacdev->DuplexMode == FULLDUPLEX)
+ {
+ TR("\n===phy FULLDUPLEX MODE\n"); //sw: debug
+ synopGMAC_wd_enable(gmacdev);
+ synopGMAC_jab_enable(gmacdev);
+ synopGMAC_frame_burst_enable(gmacdev);
+ synopGMAC_jumbo_frame_disable(gmacdev);
+ synopGMAC_rx_own_enable(gmacdev);
+#if SYNOP_LOOPBACK_MODE
+ synopGMAC_loopback_on(gmacdev);
+#else
+ synopGMAC_loopback_off(gmacdev);
+#endif
+ synopGMAC_set_full_duplex(gmacdev); //1
+ synopGMAC_retry_enable(gmacdev);
+ synopGMAC_pad_crc_strip_disable(gmacdev);
+ synopGMAC_back_off_limit(gmacdev, GmacBackoffLimit0);
+ synopGMAC_deferral_check_disable(gmacdev);
+
+ synopGMAC_tx_enable(gmacdev); //according to Tang Dan's commitment
+ synopGMAC_rx_enable(gmacdev);
+
+ synopGMACSetBits(gmacdev -> DmaBase, DmaControl, DmaStoreAndForward); //3
+ synopGMACSetBits(gmacdev -> DmaBase, DmaControl, DmaFwdErrorFrames);
+
+ if (gmacdev -> Speed == SPEED1000)
+ {
+ synopGMAC_select_gmii(gmacdev);
+ }
+ else
+ {
+ synopGMAC_select_mii(gmacdev);
+
+ if (gmacdev -> Speed == SPEED100)
+ {
+ synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacFESpeed100);
+ }
+ else
+ {
+ synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacFESpeed10);
+ }
+ }
+
+
+ /*Frame Filter Configuration*/
+ //synopGMAC_frame_filter_enable(gmacdev); //2
+ synopGMAC_frame_filter_disable(gmacdev); //2
+ synopGMAC_set_pass_control(gmacdev, GmacPassControl0);
+ synopGMAC_broadcast_enable(gmacdev);
+ synopGMAC_src_addr_filter_disable(gmacdev);
+ synopGMAC_multicast_disable(gmacdev);
+ synopGMAC_dst_addr_filter_normal(gmacdev); //scl
+ //synopGMAC_dst_addr_filter_inverse(gmacdev);
+ synopGMAC_multicast_hash_filter_disable(gmacdev);
+ synopGMAC_promisc_disable(gmacdev);
+ synopGMAC_unicast_hash_filter_disable(gmacdev);
+
+ /*Flow Control Configuration*/
+ synopGMAC_unicast_pause_frame_detect_disable(gmacdev);
+ synopGMAC_rx_flow_control_enable(gmacdev);
+ synopGMAC_tx_flow_control_enable(gmacdev);
+ }
+ else//for Half Duplex configuration
+ {
+
+ TR("\n===phy HALFDUPLEX MODE\n"); //sw: debug
+ synopGMAC_wd_enable(gmacdev);
+ synopGMAC_jab_enable(gmacdev);
+ synopGMAC_frame_burst_enable(gmacdev);
+ synopGMAC_jumbo_frame_disable(gmacdev);
+ synopGMAC_rx_own_enable(gmacdev);
+#if SYNOP_LOOPBACK_MODE
+ synopGMAC_loopback_on(gmacdev);
+#else
+ synopGMAC_loopback_off(gmacdev);
+#endif
+ synopGMAC_set_half_duplex(gmacdev);
+ synopGMAC_retry_enable(gmacdev);
+ synopGMAC_pad_crc_strip_disable(gmacdev);
+ synopGMAC_back_off_limit(gmacdev, GmacBackoffLimit0);
+ synopGMAC_deferral_check_disable(gmacdev);
+
+//sw: set efe & tsf
+ synopGMACSetBits(gmacdev -> DmaBase, DmaControl, DmaStoreAndForward);
+ synopGMACSetBits(gmacdev -> DmaBase, DmaControl, DmaFwdErrorFrames);
+//sw: put it in the end
+ synopGMAC_tx_enable(gmacdev);
+ synopGMAC_rx_enable(gmacdev);
+
+
+ if (gmacdev -> Speed == SPEED1000)
+ synopGMAC_select_gmii(gmacdev);
+ else
+ {
+ synopGMAC_select_mii(gmacdev);
+
+ if (gmacdev -> Speed == SPEED100)
+ {
+ synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacFESpeed100);
+ }
+ else
+ {
+ synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacFESpeed10);
+ }
+ }
+
+// synopGMACSetBits(gmacdev->MacBase, GmacConfig, GmacDisableCrs);
+// synopGMAC_select_gmii(gmacdev);
+
+ /*Frame Filter Configuration*/
+ synopGMAC_frame_filter_enable(gmacdev);
+// synopGMAC_frame_filter_disable(gmacdev);
+
+ synopGMAC_set_pass_control(gmacdev, GmacPassControl0);
+ synopGMAC_broadcast_enable(gmacdev);
+ synopGMAC_src_addr_filter_disable(gmacdev);
+ synopGMAC_multicast_disable(gmacdev);
+ synopGMAC_dst_addr_filter_normal(gmacdev);
+ synopGMAC_multicast_hash_filter_disable(gmacdev);
+
+ synopGMAC_promisc_disable(gmacdev);
+// synopGMAC_promisc_enable(gmacdev);
+ synopGMAC_unicast_hash_filter_disable(gmacdev);
+
+//sw: loopback mode
+// synopGMAC_loopback_on(gmacdev);
+
+ /*Flow Control Configuration*/
+ synopGMAC_unicast_pause_frame_detect_disable(gmacdev);
+ synopGMAC_rx_flow_control_disable(gmacdev);
+ synopGMAC_tx_flow_control_disable(gmacdev);
+
+ /*To set PHY register to enable CRS on Transmit*/
+ }
+ return 0;
+}
+
+
+/**
+ * Sets the Mac address in to GMAC register.
+ * This function sets the MAC address to the MAC register in question.
+ * @param[in] pointer to synopGMACdevice to populate mac dma and phy addresses.
+ * @param[in] Register offset for Mac address high
+ * @param[in] Register offset for Mac address low
+ * @param[in] buffer containing mac address to be programmed.
+ * \return 0 upon success. Error code upon failure.
+ */
+s32 synopGMAC_set_mac_addr(synopGMACdevice *gmacdev, u32 MacHigh, u32 MacLow, u8 *MacAddr)
+{
+ u32 data;
+
+ data = (MacAddr[5] << 8) | MacAddr[4];
+ synopGMACWriteReg(gmacdev -> MacBase, MacHigh, data);
+ data = (MacAddr[3] << 24) | (MacAddr[2] << 16) | (MacAddr[1] << 8) | MacAddr[0];
+ synopGMACWriteReg(gmacdev -> MacBase, MacLow, data);
+
+ return 0;
+}
+
+
+/**
+ * Get the Mac address in to the address specified.
+ * The mac register contents are read and written to buffer passed.
+ * @param[in] pointer to synopGMACdevice to populate mac dma and phy addresses.
+ * @param[in] Register offset for Mac address high
+ * @param[in] Register offset for Mac address low
+ * @param[out] buffer containing the device mac address.
+ * \return 0 upon success. Error code upon failure.
+ */
+s32 synopGMAC_get_mac_addr(synopGMACdevice *gmacdev, u32 MacHigh, u32 MacLow, u8 *MacAddr)
+{
+ u32 data;
+
+ data = synopGMACReadReg(gmacdev -> MacBase, MacHigh);
+ MacAddr[5] = (data >> 8) & 0xff;
+ MacAddr[4] = (data) & 0xff;
+
+ data = synopGMACReadReg(gmacdev -> MacBase, MacLow);
+ MacAddr[3] = (data >> 24) & 0xff;
+ MacAddr[2] = (data >> 16) & 0xff;
+ MacAddr[1] = (data >> 8) & 0xff;
+ MacAddr[0] = (data) & 0xff;
+
+// rt_kprintf("MacAddr = 0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\n",MacAddr[0],MacAddr[1],MacAddr[2],MacAddr[3],MacAddr[4],MacAddr[5]);
+
+ return 0;
+}
+
+
+/**
+ * Attaches the synopGMAC device structure to the hardware.
+ * Device structure is populated with MAC/DMA and PHY base addresses.
+ * @param[in] pointer to synopGMACdevice to populate mac dma and phy addresses.
+ * @param[in] GMAC IP mac base address.
+ * @param[in] GMAC IP dma base address.
+ * @param[in] GMAC IP phy base address.
+ * \return 0 upon success. Error code upon failure.
+ * \note This is important function. No kernel api provided by Synopsys
+ */
+
+s32 synopGMAC_attach(synopGMACdevice *gmacdev, u64 macBase, u64 dmaBase, u64 phyBase, u8 *mac_addr)
+{
+ /*Make sure the Device data strucure is cleared before we proceed further*/
+ rt_memset((void *)gmacdev, 0, sizeof(synopGMACdevice));
+ /*Populate the mac and dma base addresses*/
+ gmacdev -> MacBase = macBase;
+ gmacdev -> DmaBase = dmaBase;
+ gmacdev -> PhyBase = phyBase;
+// rt_kprintf("gmacdev->DmaBase = 0x%x\n", gmacdev->DmaBase);
+// rt_kprintf("dmaBase = 0x%x\n", dmaBase);
+ {
+ int i, j;
+ u16 data;
+
+ for (i = phyBase, j = 0; j < 32; i = (i + 1) & 0x1f, j++)
+ {
+ synopGMAC_read_phy_reg(gmacdev -> MacBase, i, 2, &data);
+
+ if (data != 0 && data != 0xffff)
+ {
+ break;
+ }
+
+ synopGMAC_read_phy_reg(gmacdev -> MacBase, i, 3, &data);
+
+ if (data != 0 && data != 0xffff)
+ {
+ break;
+ }
+ }
+
+ if (j == 32)
+ {
+ rt_kprintf("phy_detect: can't find PHY!\n");
+ }
+
+ gmacdev -> PhyBase = i;
+ }
+
+// synopGMAC_get_mac_addr(gmacdev, GmacAddr0High, GmacAddr0Low, mac_addr);
+
+ /* Program/flash in the station/IP's Mac address */
+ synopGMAC_set_mac_addr(gmacdev, GmacAddr0High, GmacAddr0Low, mac_addr);
+
+ return 0;
+}
+
+
+
+
+/**
+ * Initialize the rx descriptors for ring or chain mode operation.
+ * - Status field is initialized to 0.
+ * - EndOfRing set for the last descriptor.
+ * - buffer1 and buffer2 set to 0 for ring mode of operation. (note)
+ * - data1 and data2 set to 0. (note)
+ * @param[in] pointer to DmaDesc structure.
+ * @param[in] whether end of ring
+ * \return void.
+ * \note Initialization of the buffer1, buffer2, data1,data2 and status are not done here. This only initializes whether one wants to use this descriptor
+ * in chain mode or ring mode. For chain mode of operation the buffer2 and data2 are programmed before calling this function.
+ */
+void synopGMAC_rx_desc_init_ring(DmaDesc *desc, bool last_ring_desc)
+{
+ desc -> length = last_ring_desc ? RxDescEndOfRing : 0;
+ desc -> status = 0;
+ desc -> buffer1 = 0;
+ desc -> buffer2 = 0;
+ desc -> data1 = 0;
+ desc -> data2 = 0;
+ //desc -> dummy1 = 0;
+ //desc -> dummy2 = 0;
+
+ return;
+}
+void synopGMAC_rx_desc_recycle(DmaDesc *desc, bool last_ring_desc)
+{
+ desc -> status = DescOwnByDma;
+ desc -> length = last_ring_desc ? RxDescEndOfRing : 0;
+ //desc->buffer1 = 0;
+ //desc->buffer2 = 0;
+ //desc->data1 = 0;
+ //desc->data2 = 0;
+ //desc -> dummy1 = 0;
+ //desc -> dummy2 = 0;
+
+ return;
+}
+/**
+ * Initialize the tx descriptors for ring or chain mode operation.
+ * - Status field is initialized to 0.
+ * - EndOfRing set for the last descriptor.
+ * - buffer1 and buffer2 set to 0 for ring mode of operation. (note)
+ * - data1 and data2 set to 0. (note)
+ * @param[in] pointer to DmaDesc structure.
+ * @param[in] whether end of ring
+ * \return void.
+ * \note Initialization of the buffer1, buffer2, data1,data2 and status are not done here. This only initializes whether one wants to use this descriptor
+ * in chain mode or ring mode. For chain mode of operation the buffer2 and data2 are programmed before calling this function.
+ */
+void synopGMAC_tx_desc_init_ring(DmaDesc *desc, bool last_ring_desc)
+{
+#ifdef ENH_DESC
+ desc -> status = last_ring_desc ? TxDescEndOfRing : 0;
+ desc -> length = 0;
+#else
+ desc -> length = last_ring_desc ? TxDescEndOfRing : 0;
+ desc -> status = 0;
+#endif
+//sw
+ desc -> buffer1 = 0;
+ desc -> buffer2 = 0;
+ desc -> data1 = 0;
+ desc -> data2 = 0;
+ //desc -> dummy1 = 0;
+ //desc -> dummy2 = 0;
+ return;
+}
+
+/**
+ * Initialize the rx descriptors for chain mode of operation.
+ * - Status field is initialized to 0.
+ * - EndOfRing set for the last descriptor.
+ * - buffer1 and buffer2 set to 0.
+ * - data1 and data2 set to 0.
+ * @param[in] pointer to DmaDesc structure.
+ * @param[in] whether end of ring
+ * \return void.
+ */
+
+void synopGMAC_rx_desc_init_chain(DmaDesc *desc)
+{
+ desc -> status = 0;
+ desc -> length = RxDescChain;
+ desc -> buffer1 = 0;
+ desc -> data1 = 0;
+ return;
+}
+/**
+ * Initialize the rx descriptors for chain mode of operation.
+ * - Status field is initialized to 0.
+ * - EndOfRing set for the last descriptor.
+ * - buffer1 and buffer2 set to 0.
+ * - data1 and data2 set to 0.
+ * @param[in] pointer to DmaDesc structure.
+ * @param[in] whether end of ring
+ * \return void.
+ */
+void synopGMAC_tx_desc_init_chain(DmaDesc *desc)
+{
+#ifdef ENH_DESC
+ desc -> status = TxDescChain;
+ desc -> length = 0;
+#else
+ desc -> length = TxDescChain;
+#endif
+ desc -> buffer1 = 0;
+ desc -> data1 = 0;
+ return;
+}
+
+s32 synopGMAC_init_tx_rx_desc_queue(synopGMACdevice *gmacdev)
+{
+ s32 i;
+
+ for (i = 0; i < gmacdev -> TxDescCount; i++)
+ {
+ synopGMAC_tx_desc_init_ring(gmacdev -> TxDesc + i, i == gmacdev -> TxDescCount - 1);
+ }
+
+ TR("At line %d\n", __LINE__);
+
+ for (i = 0; i < gmacdev -> RxDescCount; i++)
+ {
+ synopGMAC_rx_desc_init_ring(gmacdev -> RxDesc + i, i == gmacdev -> RxDescCount - 1);
+ }
+
+ gmacdev -> TxNext = 0;
+ gmacdev -> TxBusy = 0;
+ gmacdev -> RxNext = 0;
+ gmacdev -> RxBusy = 0;
+
+ return -ESYNOPGMACNOERR;
+}
+/**
+ * Programs the DmaRxBaseAddress with the Rx descriptor base address.
+ * Rx Descriptor's base address is available in the gmacdev structure. This function progrms the
+ * Dma Rx Base address with the starting address of the descriptor ring or chain.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_init_rx_desc_base(synopGMACdevice *gmacdev)
+{
+ DEBUG_MES("gmacdev->RxDescDma = %08x\n", gmacdev -> RxDescDma);
+ synopGMACWriteReg(gmacdev -> DmaBase, DmaRxBaseAddr, (u32)gmacdev -> RxDescDma);
+ return;
+}
+
+/**
+ * Programs the DmaTxBaseAddress with the Tx descriptor base address.
+ * Tx Descriptor's base address is available in the gmacdev structure. This function progrms the
+ * Dma Tx Base address with the starting address of the descriptor ring or chain.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_init_tx_desc_base(synopGMACdevice *gmacdev)
+{
+ synopGMACWriteReg(gmacdev -> DmaBase, DmaTxBaseAddr, (u32)gmacdev -> TxDescDma);
+ return;
+}
+
+
+/**
+ * Makes the Dma as owner for this descriptor.
+ * This function sets the own bit of status field of the DMA descriptor,
+ * indicating the DMA is the owner for this descriptor.
+ * @param[in] pointer to DmaDesc structure.
+ * \return returns void.
+ */
+void synopGMAC_set_owner_dma(DmaDesc *desc)
+{
+ desc -> status |= DescOwnByDma;
+}
+
+/**
+ * set tx descriptor to indicate SOF.
+ * This Descriptor contains the start of ethernet frame.
+ * @param[in] pointer to DmaDesc structure.
+ * \return returns void.
+ */
+void synopGMAC_set_desc_sof(DmaDesc *desc)
+{
+#ifdef ENH_DESC
+ desc -> status |= DescTxFirst;//ENH_DESC
+#else
+ desc -> length |= DescTxFirst;
+#endif
+}
+
+/**
+ * set tx descriptor to indicate EOF.
+ * This descriptor contains the End of ethernet frame.
+ * @param[in] pointer to DmaDesc structure.
+ * \return returns void.
+ */
+void synopGMAC_set_desc_eof(DmaDesc *desc)
+{
+#ifdef ENH_DESC
+ desc -> status |= DescTxLast;//ENH_DESC
+#else
+ desc -> length |= DescTxLast;
+#endif
+}
+
+
+/**
+ * checks whether this descriptor contains start of frame.
+ * This function is to check whether the descriptor's data buffer
+ * contains a fresh ethernet frame?
+ * @param[in] pointer to DmaDesc structure.
+ * \return returns true if SOF in current descriptor, else returns fail.
+ */
+bool synopGMAC_is_sof_in_rx_desc(DmaDesc *desc)
+{
+ return ((desc -> status & DescRxFirst) == DescRxFirst);
+}
+
+/**
+ * checks whether this descriptor contains end of frame.
+ * This function is to check whether the descriptor's data buffer
+ * contains end of ethernet frame?
+ * @param[in] pointer to DmaDesc structure.
+ * \return returns true if SOF in current descriptor, else returns fail.
+ */
+bool synopGMAC_is_eof_in_rx_desc(DmaDesc *desc)
+{
+ return ((desc -> status & DescRxLast) == DescRxLast);
+}
+
+/**
+ * checks whether destination address filter failed in the rx frame.
+ * @param[in] pointer to DmaDesc structure.
+ * \return returns true if Failed, false if not.
+ */
+bool synopGMAC_is_da_filter_failed(DmaDesc *desc)
+{
+ return ((desc -> status & DescDAFilterFail) == DescDAFilterFail);
+}
+
+/**
+ * checks whether source address filter failed in the rx frame.
+ * @param[in] pointer to DmaDesc structure.
+ * \return returns true if Failed, false if not.
+ */
+bool synopGMAC_is_sa_filter_failed(DmaDesc *desc)
+{
+ return ((desc -> status & DescSAFilterFail) == DescSAFilterFail);
+}
+
+/**
+ * Checks whether the descriptor is owned by DMA.
+ * If descriptor is owned by DMA then the OWN bit is set to 1. This API is same for both ring and chain mode.
+ * @param[in] pointer to DmaDesc structure.
+ * \return returns true if Dma owns descriptor and false if not.
+ */
+bool synopGMAC_is_desc_owned_by_dma(DmaDesc *desc)
+{
+ return ((desc -> status & DescOwnByDma) == DescOwnByDma);
+}
+
+/**
+ * returns the byte length of received frame including CRC.
+ * This returns the no of bytes received in the received ethernet frame including CRC(FCS).
+ * @param[in] pointer to DmaDesc structure.
+ * \return returns the length of received frame lengths in bytes.
+ */
+u32 synopGMAC_get_rx_desc_frame_length(u32 status)
+{
+ return ((status & DescFrameLengthMask) >> DescFrameLengthShift);
+}
+
+/**
+ * Checks whether the descriptor is valid
+ * if no errors such as CRC/Receive Error/Watchdog Timeout/Late collision/Giant Frame/Overflow/Descriptor
+ * error the descritpor is said to be a valid descriptor.
+ * @param[in] pointer to DmaDesc structure.
+ * \return True if desc valid. false if error.
+ */
+bool synopGMAC_is_desc_valid(u32 status)
+{
+ return ((status & DescError) == 0);
+}
+
+/**
+ * Checks whether the descriptor is empty.
+ * If the buffer1 and buffer2 lengths are zero in ring mode descriptor is empty.
+ * In chain mode buffer2 length is 0 but buffer2 itself contains the next descriptor address.
+ * @param[in] pointer to DmaDesc structure.
+ * \return returns true if descriptor is empty, false if not empty.
+ */
+bool synopGMAC_is_desc_empty(DmaDesc *desc)
+{
+ //if both the buffer1 length and buffer2 length are zero desc is empty
+ return (((desc -> length & DescSize1Mask) == 0) && ((desc -> length & DescSize2Mask) == 0));
+}
+
+
+/**
+ * Checks whether the rx descriptor is valid.
+ * if rx descripor is not in error and complete frame is available in the same descriptor
+ * @param[in] pointer to DmaDesc structure.
+ * \return returns true if no error and first and last desc bits are set, otherwise it returns false.
+ */
+bool synopGMAC_is_rx_desc_valid(u32 status)
+{
+ return ((status & DescError) == 0) && ((status & DescRxFirst) == DescRxFirst) && ((status & DescRxLast) == DescRxLast);
+}
+
+/**
+ * Checks whether the tx is aborted due to collisions.
+ * @param[in] pointer to DmaDesc structure.
+ * \return returns true if collisions, else returns false.
+ */
+bool synopGMAC_is_tx_aborted(u32 status)
+{
+ return (((status & DescTxLateCollision) == DescTxLateCollision) | ((status & DescTxExcCollisions) == DescTxExcCollisions));
+
+}
+
+/**
+ * Checks whether the tx carrier error.
+ * @param[in] pointer to DmaDesc structure.
+ * \return returns true if carrier error occured, else returns falser.
+ */
+bool synopGMAC_is_tx_carrier_error(u32 status)
+{
+ return (((status & DescTxLostCarrier) == DescTxLostCarrier) | ((status & DescTxNoCarrier) == DescTxNoCarrier));
+}
+
+
+/**
+ * Gives the transmission collision count.
+ * returns the transmission collision count indicating number of collisions occured before the frame was transmitted.
+ * Make sure to check excessive collision didnot happen to ensure the count is valid.
+ * @param[in] pointer to DmaDesc structure.
+ * \return returns the count value of collision.
+ */
+u32 synopGMAC_get_tx_collision_count(u32 status)
+{
+ return ((status & DescTxCollMask) >> DescTxCollShift);
+}
+u32 synopGMAC_is_exc_tx_collisions(u32 status)
+{
+ return ((status & DescTxExcCollisions) == DescTxExcCollisions);
+}
+
+
+/**
+ * Check for damaged frame due to overflow or collision.
+ * Retruns true if rx frame was damaged due to buffer overflow in MTL or late collision in half duplex mode.
+ * @param[in] pointer to DmaDesc structure.
+ * \return returns true if error else returns false.
+ */
+bool synopGMAC_is_rx_frame_damaged(u32 status)
+{
+//bool synopGMAC_dma_rx_collisions(u32 status)
+ return (((status & DescRxDamaged) == DescRxDamaged) | ((status & DescRxCollision) == DescRxCollision));
+}
+
+/**
+ * Check for damaged frame due to collision.
+ * Retruns true if rx frame was damaged due to late collision in half duplex mode.
+ * @param[in] pointer to DmaDesc structure.
+ * \return returns true if error else returns false.
+ */
+bool synopGMAC_is_rx_frame_collision(u32 status)
+{
+//bool synopGMAC_dma_rx_collisions(u32 status)
+ return ((status & DescRxCollision) == DescRxCollision);
+}
+
+/**
+ * Check for receive CRC error.
+ * Retruns true if rx frame CRC error occured.
+ * @param[in] pointer to DmaDesc structure.
+ * \return returns true if error else returns false.
+ */
+bool synopGMAC_is_rx_crc(u32 status)
+{
+//u32 synopGMAC_dma_rx_crc(u32 status)
+ return ((status & DescRxCrc) == DescRxCrc);
+}
+
+/**
+ * Indicates rx frame has non integer multiple of bytes. (odd nibbles).
+ * Retruns true if dribbling error in rx frame.
+ * @param[in] pointer to DmaDesc structure.
+ * \return returns true if error else returns false.
+ */
+bool synopGMAC_is_frame_dribbling_errors(u32 status)
+{
+//u32 synopGMAC_dma_rx_frame_errors(u32 status)
+ return ((status & DescRxDribbling) == DescRxDribbling);
+}
+
+/**
+ * Indicates error in rx frame length.
+ * Retruns true if received frame length doesnot match with the length field
+ * @param[in] pointer to DmaDesc structure.
+ * \return returns true if error else returns false.
+ */
+bool synopGMAC_is_rx_frame_length_errors(u32 status)
+{
+//u32 synopGMAC_dma_rx_length_errors(u32 status)
+ return ((status & DescRxLengthError) == DescRxLengthError);
+}
+
+/**
+ * Checks whether this rx descriptor is last rx descriptor.
+ * This returns true if it is last descriptor either in ring mode or in chain mode.
+ * @param[in] pointer to devic structure.
+ * @param[in] pointer to DmaDesc structure.
+ * \return returns true if it is last descriptor, false if not.
+ * \note This function should not be called before initializing the descriptor using synopGMAC_desc_init().
+ */
+bool synopGMAC_is_last_rx_desc(synopGMACdevice *gmacdev, DmaDesc *desc)
+{
+//bool synopGMAC_is_last_desc(DmaDesc *desc)
+ return (((desc -> length & RxDescEndOfRing) == RxDescEndOfRing) || ((u64)gmacdev -> RxDesc == desc -> data2));
+}
+
+/**
+ * Checks whether this tx descriptor is last tx descriptor.
+ * This returns true if it is last descriptor either in ring mode or in chain mode.
+ * @param[in] pointer to devic structure.
+ * @param[in] pointer to DmaDesc structure.
+ * \return returns true if it is last descriptor, false if not.
+ * \note This function should not be called before initializing the descriptor using synopGMAC_desc_init().
+ */
+bool synopGMAC_is_last_tx_desc(synopGMACdevice *gmacdev, DmaDesc *desc)
+{
+//bool synopGMAC_is_last_desc(DmaDesc *desc)
+#ifdef ENH_DESC
+ return (((desc->status & TxDescEndOfRing) == TxDescEndOfRing) || ((u64)gmacdev -> TxDesc == desc -> data2));
+#else
+ return (((desc->length & TxDescEndOfRing) == TxDescEndOfRing) || ((u64)gmacdev -> TxDesc == desc -> data2));
+#endif
+}
+
+/**
+ * Checks whether this rx descriptor is in chain mode.
+ * This returns true if it is this descriptor is in chain mode.
+ * @param[in] pointer to DmaDesc structure.
+ * \return returns true if chain mode is set, false if not.
+ */
+bool synopGMAC_is_rx_desc_chained(DmaDesc *desc)
+{
+ return ((desc -> length & RxDescChain) == RxDescChain);
+}
+
+/**
+ * Checks whether this tx descriptor is in chain mode.
+ * This returns true if it is this descriptor is in chain mode.
+ * @param[in] pointer to DmaDesc structure.
+ * \return returns true if chain mode is set, false if not.
+ */
+bool synopGMAC_is_tx_desc_chained(DmaDesc *desc)
+{
+#ifdef ENH_DESC
+ return ((desc -> status & TxDescChain) == TxDescChain);
+#else
+ return ((desc -> length & TxDescChain) == TxDescChain);
+#endif
+}
+
+/**
+ * Driver Api to get the descriptor field information.
+ * This returns the status, dma-able address of buffer1, the length of buffer1, virtual address of buffer1
+ * dma-able address of buffer2, length of buffer2, virtural adddress of buffer2.
+ * @param[in] pointer to DmaDesc structure.
+ * @param[out] pointer to status field fo descriptor.
+ * @param[out] dma-able address of buffer1.
+ * @param[out] length of buffer1.
+ * @param[out] virtual address of buffer1.
+ * @param[out] dma-able address of buffer2.
+ * @param[out] length of buffer2.
+ * @param[out] virtual address of buffer2.
+ * \return returns void.
+ */
+void synopGMAC_get_desc_data(DmaDesc *desc, u32 *Status, u32 *Buffer1, u32 *Length1, u64 *Data1, u32 *Buffer2, u32 *Length2, u64 *Data2)
+{
+
+ if (Status != 0)
+ {
+ *Status = desc -> status;
+ }
+
+ if (Buffer1 != 0)
+ {
+ *Buffer1 = desc -> buffer1;
+ }
+
+ if (Length1 != 0)
+ {
+ *Length1 = (desc -> length & DescSize1Mask) >> DescSize1Shift;
+ }
+
+ if (Data1 != 0)
+ {
+ *Data1 = desc -> data1;
+ }
+
+ if (Buffer2 != 0)
+ {
+ *Buffer2 = desc -> buffer2;
+ }
+
+ if (Length2 != 0)
+ {
+ *Length2 = (desc -> length & DescSize2Mask) >> DescSize2Shift;
+ }
+
+ if (Data2 != 0)
+ {
+ *Data2 = desc -> data2;
+ }
+
+ return;
+}
+
+#ifdef ENH_DESC_8W
+/**
+ * This function is defined two times. Once when the code is compiled for ENHANCED DESCRIPTOR SUPPORT and Once for Normal descriptor
+ * Get the index and address of Tx desc.
+ * This api is same for both ring mode and chain mode.
+ * This function tracks the tx descriptor the DMA just closed after the transmission of data from this descriptor is
+ * over. This returns the descriptor fields to the caller.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[out] status field of the descriptor.
+ * @param[out] Dma-able buffer1 pointer.
+ * @param[out] length of buffer1 (Max is 2048).
+ * @param[out] virtual pointer for buffer1.
+ * @param[out] Dma-able buffer2 pointer.
+ * @param[out] length of buffer2 (Max is 2048).
+ * @param[out] virtual pointer for buffer2.
+ * @param[out] u32 data indicating whether the descriptor is in ring mode or chain mode.
+ * \return returns present tx descriptor index on success. Negative value if error.
+ */
+s32 synopGMAC_get_tx_qptr(synopGMACdevice *gmacdev, u32 *Status, u32 *Buffer1, u32 *Length1, u64 *Data1, u32 *Buffer2, u32 *Length2, u64 *Data2,
+ u32 *Ext_Status, u32 *Time_Stamp_High, u32 *Time_Stamp_Low)
+{
+ u32 txover = gmacdev->TxBusy;
+ DmaDesc *txdesc = gmacdev->TxBusyDesc;
+
+ if (synopGMAC_is_desc_owned_by_dma(txdesc))
+ return -1;
+ if (synopGMAC_is_desc_empty(txdesc))
+ return -1;
+
+ (gmacdev->BusyTxDesc)--; //busy tx descriptor is reduced by one as it will be handed over to Processor now
+
+ if (Status != 0)
+ *Status = txdesc->status;
+
+ if (Ext_Status != 0)
+ *Ext_Status = txdesc->extstatus;
+ if (Time_Stamp_High != 0)
+ *Time_Stamp_High = txdesc->timestamphigh;
+ if (Time_Stamp_Low != 0)
+ *Time_Stamp_High = txdesc->timestamplow;
+
+ if (Buffer1 != 0)
+ *Buffer1 = txdesc->buffer1;
+ if (Length1 != 0)
+ *Length1 = (txdesc->length & DescSize1Mask) >> DescSize1Shift;
+ if (Data1 != 0)
+ *Data1 = txdesc->data1;
+
+ if (Buffer2 != 0)
+ *Buffer2 = txdesc->buffer2;
+ if (Length2 != 0)
+ *Length2 = (txdesc->length & DescSize2Mask) >> DescSize2Shift;
+ if (Data1 != 0)
+ *Data2 = txdesc->data2;
+
+ gmacdev->TxBusy = synopGMAC_is_last_tx_desc(gmacdev, txdesc) ? 0 : txover + 1;
+
+ if (synopGMAC_is_tx_desc_chained(txdesc))
+ {
+ gmacdev->TxBusyDesc = (DmaDesc *)txdesc->data2;
+ synopGMAC_tx_desc_init_chain(txdesc);
+ }
+ else
+ {
+ gmacdev->TxBusyDesc = synopGMAC_is_last_tx_desc(gmacdev, txdesc) ? gmacdev->TxDesc : (txdesc + 1);
+ synopGMAC_tx_desc_init_ring(txdesc, synopGMAC_is_last_tx_desc(gmacdev, txdesc));
+ }
+ TR("%02d %08x %08x %08x %08x %08x %08x %08x\n", txover, (u32)txdesc, txdesc->status, txdesc->length, txdesc->buffer1, txdesc->buffer2, txdesc->data1, txdesc->data2);
+
+ return txover;
+}
+#else
+
+/**
+ * Get the index and address of Tx desc.
+ * This api is same for both ring mode and chain mode.
+ * This function tracks the tx descriptor the DMA just closed after the transmission of data from this descriptor is
+ * over. This returns the descriptor fields to the caller.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[out] status field of the descriptor.
+ * @param[out] Dma-able buffer1 pointer.
+ * @param[out] length of buffer1 (Max is 2048).
+ * @param[out] virtual pointer for buffer1.
+ * @param[out] Dma-able buffer2 pointer.
+ * @param[out] length of buffer2 (Max is 2048).
+ * @param[out] virtual pointer for buffer2.
+ * @param[out] u32 data indicating whether the descriptor is in ring mode or chain mode.
+ * \return returns present tx descriptor index on success. Negative value if error.
+ */
+s32 synopGMAC_get_tx_qptr(synopGMACdevice *gmacdev, u32 *Status, u32 *Buffer1, u32 *Length1, u64 *Data1, u32 *Buffer2, u32 *Length2, u64 *Data2)
+{
+ u32 txover = gmacdev->TxBusy;
+ DmaDesc *txdesc = gmacdev->TxBusyDesc;
+ int i;
+//sw: dbg
+ //pci_sync_cache(0, (vm_offset_t)txdesc, 64, SYNC_R);
+ //pci_sync_cache(0, (vm_offset_t)txdesc, 64, SYNC_W);
+#if SYNOP_TX_DEBUG
+ printf("Cache sync before get a used tx dma desc!\n");
+ printf("\n==%02d %08x %08x %08x %08x %08x %08x %08x\n", txover, (u32)txdesc, txdesc->status, txdesc->length, txdesc->buffer1, txdesc->buffer2, txdesc->data1, txdesc->data2);
+#endif
+ if (synopGMAC_is_desc_owned_by_dma(txdesc))
+ {
+ return -1;
+ }
+// gmacdev->TxBusy = synopGMAC_is_last_tx_desc(gmacdev,txdesc) ? 0 : txover + 1;
+// gmacdev->TxBusyDesc = synopGMAC_is_last_tx_desc(gmacdev,txdesc) ? gmacdev->TxDesc : (txdesc + 1);
+ if (synopGMAC_is_desc_empty(txdesc))
+ {
+ return -1;
+ }
+ (gmacdev->BusyTxDesc)--; //busy tx descriptor is reduced by one as it will be handed over to Processor now
+
+ if (Status != 0)
+ *Status = txdesc->status;
+
+ if (Buffer1 != 0)
+ *Buffer1 = txdesc->buffer1;
+ if (Length1 != 0)
+ *Length1 = (txdesc->length & DescSize1Mask) >> DescSize1Shift;
+ if (Data1 != 0)
+ *Data1 = txdesc->data1;
+
+ if (Buffer2 != 0)
+ *Buffer2 = txdesc->buffer2;
+ if (Length2 != 0)
+ *Length2 = (txdesc->length & DescSize2Mask) >> DescSize2Shift;
+ if (Data1 != 0)
+ *Data2 = txdesc->data2;
+
+ gmacdev->TxBusy = synopGMAC_is_last_tx_desc(gmacdev, txdesc) ? 0 : txover + 1;
+
+ if (synopGMAC_is_tx_desc_chained(txdesc))
+ {
+ gmacdev->TxBusyDesc = (DmaDesc *)txdesc->data2;
+ synopGMAC_tx_desc_init_chain(txdesc);
+ }
+ else
+ {
+ gmacdev->TxBusyDesc = synopGMAC_is_last_tx_desc(gmacdev, txdesc) ? gmacdev->TxDesc : (txdesc + 1);
+ synopGMAC_tx_desc_init_ring(txdesc, synopGMAC_is_last_tx_desc(gmacdev, txdesc));
+ }
+ //printf("%02d %08x %08x %08x %08x %08x %08x %08x\n",txover,(u32)txdesc,txdesc->status,txdesc->length,txdesc->buffer1,txdesc->buffer2,txdesc->data1,txdesc->data2);
+ //pci_sync_cache(0, (vm_offset_t)txdesc, 64, SYNC_W);
+#if SYNOP_TX_DEBUG
+ printf("Cache sync after re-init a tx dma desc!\n");
+#endif
+
+ return txover;
+}
+
+#endif
+/**
+ * Populate the tx desc structure with the buffer address.
+ * Once the driver has a packet ready to be transmitted, this function is called with the
+ * valid dma-able buffer addresses and their lengths. This function populates the descriptor
+ * and make the DMA the owner for the descriptor. This function also controls whether Checksum
+ * offloading to be done in hardware or not.
+ * This api is same for both ring mode and chain mode.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] Dma-able buffer1 pointer.
+ * @param[in] length of buffer1 (Max is 2048).
+ * @param[in] virtual pointer for buffer1.
+ * @param[in] Dma-able buffer2 pointer.
+ * @param[in] length of buffer2 (Max is 2048).
+ * @param[in] virtual pointer for buffer2.
+ * @param[in] u32 data indicating whether the descriptor is in ring mode or chain mode.
+ * @param[in] u32 indicating whether the checksum offloading in HW/SW.
+ * \return returns present tx descriptor index on success. Negative value if error.
+ */
+u32 len;
+s32 synopGMAC_set_tx_qptr(synopGMACdevice *gmacdev, u32 Buffer1, u32 Length1, u64 Data1, u32 Buffer2, u32 Length2, u64 Data2, u32 offload_needed, u32 *index, DmaDesc *Dpr)
+{
+ u32 txnext = gmacdev->TxNext;
+ DmaDesc *txdesc = gmacdev->TxNextDesc;
+
+ *index = txnext;
+ Dpr = txdesc;
+
+ if (!synopGMAC_is_desc_empty(txdesc))
+ {
+ TR("set tx qptr: desc empty!\n");
+ return -1;
+ }
+
+ (gmacdev->BusyTxDesc)++; //busy tx descriptor is reduced by one as it will be handed over to Processor now
+
+ if (synopGMAC_is_tx_desc_chained(txdesc))
+ {
+ txdesc->length |= ((Length1 << DescSize1Shift) & DescSize1Mask);
+#ifdef ENH_DESC
+ txdesc->status |= (DescTxFirst | DescTxLast | DescTxIntEnable); //ENH_DESC
+#else
+ txdesc->length |= (DescTxFirst | DescTxLast | DescTxIntEnable); //Its always assumed that complete data will fit in to one descriptor
+#endif
+
+ txdesc->buffer1 = Buffer1;
+ txdesc->data1 = Data1;
+
+ if (offload_needed)
+ {
+ /*
+ Make sure that the OS you are running supports the IP and TCP checkusm offloaidng,
+ before calling any of the functions given below.
+ */
+ synopGMAC_tx_checksum_offload_ipv4hdr(gmacdev, txdesc);
+ synopGMAC_tx_checksum_offload_tcponly(gmacdev, txdesc);
+// synopGMAC_tx_checksum_offload_tcp_pseudo(gmacdev, txdesc);
+ }
+#ifdef ENH_DESC
+ txdesc->status |= DescOwnByDma;//ENH_DESC
+#else
+ txdesc->status = DescOwnByDma;
+#endif
+
+ gmacdev->TxNext = synopGMAC_is_last_tx_desc(gmacdev, txdesc) ? 0 : txnext + 1;
+ gmacdev->TxNextDesc = (DmaDesc *)txdesc->data2;
+ }
+ else
+ {
+// printf("synopGMAC_set_tx_qptr:in ring mode\n");
+ txdesc->length |= (((Length1 << DescSize1Shift) & DescSize1Mask) | ((Length2 << DescSize2Shift) & DescSize2Mask));
+#ifdef ENH_DESC
+ txdesc->status |= (DescTxFirst | DescTxLast | DescTxIntEnable); //ENH_DESC
+#else
+ txdesc->length |= (DescTxFirst | DescTxLast | DescTxIntEnable); //Its always assumed that complete data will fit in to one descriptor
+#endif
+
+ txdesc->buffer1 = Buffer1;
+ txdesc->data1 = Data1;
+
+ txdesc->buffer2 = Buffer2;
+ txdesc->data2 = Data2;
+
+ if (offload_needed)
+ {
+ /*
+ Make sure that the OS you are running supports the IP and TCP checkusm offloaidng,
+ before calling any of the functions given below.
+ */
+//sw: i am not sure about the checksum.so i omit it in the outside
+ synopGMAC_tx_checksum_offload_ipv4hdr(gmacdev, txdesc);
+ synopGMAC_tx_checksum_offload_tcponly(gmacdev, txdesc);
+// synopGMAC_tx_checksum_offload_tcp_pseudo(gmacdev, txdesc);
+ }
+#ifdef ENH_DESC
+ txdesc->status |= DescOwnByDma;//ENH_DESC
+#else
+// printf("synopGMAC_set_tx_qptr:give the tx descroptor to dma\n");
+ txdesc->status = DescOwnByDma;
+#endif
+
+ gmacdev->TxNext = synopGMAC_is_last_tx_desc(gmacdev, txdesc) ? 0 : txnext + 1;
+ gmacdev->TxNextDesc = synopGMAC_is_last_tx_desc(gmacdev, txdesc) ? gmacdev->TxDesc : (txdesc + 1);
+ }
+
+
+#if SYNOP_TX_DEBUG
+ printf("%02d %08x %08x %08x %08x %08x %08x %08x\n", txnext, (u32)txdesc, txdesc->status, txdesc->length, txdesc->buffer1, txdesc->buffer2, txdesc->data1, txdesc->data2);
+#endif
+ //pci_sync_cache(0, (vm_offset_t)txdesc, 64, SYNC_W);
+#if SYNOP_TX_DEBUG
+ printf("Cache sync to set a tx desc!\n");
+#endif
+ //pci_sync_cache(0, (vm_offset_t)(txdesc->data1), 32, SYNC_W);
+#if SYNOP_TX_DEBUG
+ //printf("Cache sync for data in the buf of the tx desc!\n");
+#endif
+ return txnext;
+}
+#ifdef ENH_DESC_8W
+/**
+ * Prepares the descriptor to receive packets.
+ * The descriptor is allocated with the valid buffer addresses (sk_buff address) and the length fields
+ * and handed over to DMA by setting the ownership. After successful return from this function the
+ * descriptor is added to the receive descriptor pool/queue.
+ * This api is same for both ring mode and chain mode.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] Dma-able buffer1 pointer.
+ * @param[in] length of buffer1 (Max is 2048).
+ * @param[in] Dma-able buffer2 pointer.
+ * @param[in] length of buffer2 (Max is 2048).
+ * @param[in] u32 data indicating whether the descriptor is in ring mode or chain mode.
+ * \return returns present rx descriptor index on success. Negative value if error.
+ */
+// dma_addr RX_BUF_SIZE skb
+s32 synopGMAC_set_rx_qptr(synopGMACdevice *gmacdev, u32 Buffer1, u32 Length1, u64 Data1, u32 Buffer2, u32 Length2, u64 Data2)
+{
+ u32 rxnext = gmacdev->RxNext;
+ DmaDesc *rxdesc = gmacdev->RxNextDesc;
+
+ if (!synopGMAC_is_desc_empty(rxdesc))
+ return -1;
+
+ if (synopGMAC_is_rx_desc_chained(rxdesc))
+ {
+ rxdesc->length |= ((Length1 << DescSize1Shift) & DescSize1Mask);
+
+ rxdesc->buffer1 = Buffer1;
+ rxdesc->data1 = Data1;
+
+ rxdesc->extstatus = 0;
+ rxdesc->reserved1 = 0;
+ rxdesc->timestamplow = 0;
+ rxdesc->timestamphigh = 0;
+
+ if ((rxnext % MODULO_INTERRUPT) != 0)
+ rxdesc->length |= RxDisIntCompl;
+
+ rxdesc->status = DescOwnByDma;
+
+ gmacdev->RxNext = synopGMAC_is_last_rx_desc(gmacdev, rxdesc) ? 0 : rxnext + 1;
+ gmacdev->RxNextDesc = (DmaDesc *)rxdesc->data2;
+ }
+ else
+ {
+ rxdesc->length |= (((Length1 << DescSize1Shift) & DescSize1Mask) | ((Length2 << DescSize2Shift) & DescSize2Mask));
+
+ rxdesc->buffer1 = Buffer1;
+ rxdesc->data1 = Data1;
+
+ rxdesc->extstatus = 0;
+ rxdesc->reserved1 = 0;
+ rxdesc->timestamplow = 0;
+ rxdesc->timestamphigh = 0;
+
+ rxdesc->buffer2 = Buffer2;
+ rxdesc->data2 = Data2;
+
+ if ((rxnext % MODULO_INTERRUPT) != 0)
+ rxdesc->length |= RxDisIntCompl;
+
+ rxdesc->status = DescOwnByDma;
+ gmacdev->RxNext = synopGMAC_is_last_rx_desc(gmacdev, rxdesc) ? 0 : rxnext + 1;
+ gmacdev->RxNextDesc = synopGMAC_is_last_rx_desc(gmacdev, rxdesc) ? gmacdev->RxDesc : (rxdesc + 1);
+ }
+#if SYNOP_RX_DEBUG
+ TR("%02d %08x %08x %08x %08x %08x %08x %08x %08x %08x\n", rxnext, (u32)rxdesc, rxdesc->status, rxdesc->length, rxdesc->buffer1, rxdesc->buffer2, rxdesc->data1, rxdesc->data2, rxdesc->dummy1, rxdesc->dummy2);
+#endif
+
+ (gmacdev->BusyRxDesc)++; //One descriptor will be given to Hardware. So busy count incremented by one
+ //pci_sync_cache(0, (vm_offset_t)rxdesc,64, SYNC_W);
+ return rxnext;
+}
+
+#else
+/**
+ * Prepares the descriptor to receive packets.
+ * The descriptor is allocated with the valid buffer addresses (sk_buff address) and the length fields
+ * and handed over to DMA by setting the ownership. After successful return from this function the
+ * descriptor is added to the receive descriptor pool/queue.
+ * This api is same for both ring mode and chain mode.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] Dma-able buffer1 pointer.
+ * @param[in] length of buffer1 (Max is 2048).
+ * @param[in] Dma-able buffer2 pointer.
+ * @param[in] length of buffer2 (Max is 2048).
+ * @param[in] u32 data indicating whether the descriptor is in ring mode or chain mode.
+ * \return returns present rx descriptor index on success. Negative value if error.
+ */
+s32 synopGMAC_set_rx_qptr(synopGMACdevice *gmacdev, u32 Buffer1, u32 Length1, u64 Data1, u32 Buffer2, u32 Length2, u64 Data2)
+{
+ u32 rxnext = gmacdev->RxNext;
+ DmaDesc *rxdesc = gmacdev->RxNextDesc;
+
+ if (!synopGMAC_is_desc_empty(rxdesc))
+ return -1;
+
+ if (synopGMAC_is_rx_desc_chained(rxdesc))
+ {
+ rxdesc->length |= ((Length1 << DescSize1Shift) & DescSize1Mask);
+
+ rxdesc->buffer1 = Buffer1;
+ rxdesc->data1 = Data1;
+
+ if ((rxnext % MODULO_INTERRUPT) != 0)
+ rxdesc->length |= RxDisIntCompl;
+
+ rxdesc->status = DescOwnByDma;
+
+ gmacdev->RxNext = synopGMAC_is_last_rx_desc(gmacdev, rxdesc) ? 0 : rxnext + 1;
+ gmacdev->RxNextDesc = (DmaDesc *)rxdesc->data2;
+ }
+ else
+ {
+ rxdesc->length |= (((Length1 << DescSize1Shift) & DescSize1Mask) | ((Length2 << DescSize2Shift) & DescSize2Mask));
+
+ rxdesc->buffer1 = Buffer1;
+ rxdesc->data1 = Data1;
+
+ rxdesc->buffer2 = Buffer2;
+ rxdesc->data2 = Data2;
+
+ if ((rxnext % MODULO_INTERRUPT) != 0)
+ rxdesc->length |= RxDisIntCompl;
+
+ rxdesc->status = DescOwnByDma;
+
+ gmacdev->RxNext = synopGMAC_is_last_rx_desc(gmacdev, rxdesc) ? 0 : rxnext + 1;
+ gmacdev->RxNextDesc = synopGMAC_is_last_rx_desc(gmacdev, rxdesc) ? gmacdev->RxDesc : (rxdesc + 1);
+ }
+#if SYNOP_RX_DEBUG
+ TR("%02d %08x %08x %08x %08x %08x %08x %08x\n", rxnext, (u32)rxdesc, rxdesc->status, rxdesc->length, rxdesc->buffer1, rxdesc->buffer2, rxdesc->data1, rxdesc->data2);
+#endif
+ (gmacdev->BusyRxDesc)++; //One descriptor will be given to Hardware. So busy count incremented by one
+
+ return rxnext;
+}
+
+s32 synopGMAC_set_rx_qptr_init(synopGMACdevice *gmacdev, u32 Buffer1, u32 Length1, u64 Data1, u32 Buffer2, u32 Length2, u64 Data2)
+{
+ u32 rxnext = gmacdev->RxNext;
+ DmaDesc *rxdesc = gmacdev->RxNextDesc;
+
+ /* sw
+ if(synopGMAC_is_desc_owned_by_dma(rxdesc))
+ return -1;
+ */
+
+ if (!synopGMAC_is_desc_empty(rxdesc))
+ return -1;
+
+ if (synopGMAC_is_rx_desc_chained(rxdesc))
+ {
+ rxdesc->length |= ((Length1 << DescSize1Shift) & DescSize1Mask);
+
+ rxdesc->buffer1 = Buffer1;
+ rxdesc->data1 = Data1;
+
+ if ((rxnext % MODULO_INTERRUPT) != 0)
+ rxdesc->length |= RxDisIntCompl;
+
+ rxdesc->status = DescOwnByDma;
+ rxdesc->status = 0;
+
+ gmacdev->RxNext = synopGMAC_is_last_rx_desc(gmacdev, rxdesc) ? 0 : rxnext + 1;
+ gmacdev->RxNextDesc = (DmaDesc *)rxdesc->data2;
+ }
+ else
+ {
+ rxdesc->length |= (((Length1 << DescSize1Shift) & DescSize1Mask) | ((Length2 << DescSize2Shift) & DescSize2Mask));
+
+ rxdesc->buffer1 = Buffer1;
+ rxdesc->data1 = Data1;
+
+ rxdesc->buffer2 = Buffer2;
+ rxdesc->data2 = Data2;
+
+ if ((rxnext % MODULO_INTERRUPT) != 0)
+ rxdesc->length |= RxDisIntCompl;
+
+ rxdesc->status = DescOwnByDma;
+ rxdesc->status = 0;
+
+ gmacdev->RxNext = synopGMAC_is_last_rx_desc(gmacdev, rxdesc) ? 0 : rxnext + 1;
+ gmacdev->RxNextDesc = synopGMAC_is_last_rx_desc(gmacdev, rxdesc) ? gmacdev->RxDesc : (rxdesc + 1);
+ }
+ TR("%02d %08x %08x %08x %08x %08x %08x %08x\n", rxnext, (u32)rxdesc, rxdesc->status, rxdesc->length, rxdesc->buffer1, rxdesc->buffer2, rxdesc->data1, rxdesc->data2);
+ (gmacdev->BusyRxDesc)++; //One descriptor will be given to Hardware. So busy count incremented by one
+ return rxnext;
+}
+#endif
+#ifdef ENH_DESC_8W
+/**
+ * This function is defined two times. Once when the code is compiled for ENHANCED DESCRIPTOR SUPPORT and Once for Normal descriptor
+ * Get back the descriptor from DMA after data has been received.
+ * When the DMA indicates that the data is received (interrupt is generated), this function should be
+ * called to get the descriptor and hence the data buffers received. With successful return from this
+ * function caller gets the descriptor fields for processing. check the parameters to understand the
+ * fields returned.`
+ * @param[in] pointer to synopGMACdevice.
+ * @param[out] pointer to hold the status of DMA.
+ * @param[out] Dma-able buffer1 pointer.
+ * @param[out] pointer to hold length of buffer1 (Max is 2048).
+ * @param[out] virtual pointer for buffer1.
+ * @param[out] Dma-able buffer2 pointer.
+ * @param[out] pointer to hold length of buffer2 (Max is 2048).
+ * @param[out] virtual pointer for buffer2.
+ * \return returns present rx descriptor index on success. Negative value if error.
+ */
+s32 synopGMAC_get_rx_qptr(synopGMACdevice *gmacdev, u32 *Status, u32 *Buffer1, u32 *Length1, u64 *Data1, u32 *Buffer2, u32 *Length2, u64 *Data2,
+ u32 *Ext_Status, u32 *Time_Stamp_High, u32 *Time_Stamp_Low)
+{
+ u32 rxnext = gmacdev->RxBusy; // index of descriptor the DMA just completed. May be useful when data
+ //is spread over multiple buffers/descriptors
+ DmaDesc *rxdesc = gmacdev->RxBusyDesc;
+ if (synopGMAC_is_desc_owned_by_dma(rxdesc))
+ return -1;
+ if (synopGMAC_is_desc_empty(rxdesc))
+ return -1;
+
+
+ if (Status != 0)
+ *Status = rxdesc->status;// send the status of this descriptor
+
+ if (Ext_Status != 0)
+ *Ext_Status = rxdesc->extstatus;
+ if (Time_Stamp_High != 0)
+ *Time_Stamp_High = rxdesc->timestamphigh;
+ if (Time_Stamp_Low != 0)
+ *Time_Stamp_Low = rxdesc->timestamplow;
+
+ if (Length1 != 0)
+ *Length1 = (rxdesc->length & DescSize1Mask) >> DescSize1Shift;
+ if (Buffer1 != 0)
+ *Buffer1 = rxdesc->buffer1;
+ if (Data1 != 0)
+ *Data1 = rxdesc->data1;
+
+ if (Length2 != 0)
+ *Length2 = (rxdesc->length & DescSize2Mask) >> DescSize2Shift;
+ if (Buffer2 != 0)
+ *Buffer2 = rxdesc->buffer2;
+ if (Data1 != 0)
+ *Data2 = rxdesc->data2;
+
+ gmacdev->RxBusy = synopGMAC_is_last_rx_desc(gmacdev, rxdesc) ? 0 : rxnext + 1;
+
+ if (synopGMAC_is_rx_desc_chained(rxdesc))
+ {
+ gmacdev->RxBusyDesc = (DmaDesc *)rxdesc->data2;
+ synopGMAC_rx_desc_init_chain(rxdesc);
+ //synopGMAC_desc_init_chain(rxdesc, synopGMAC_is_last_rx_desc(gmacdev,rxdesc),0,0);
+ }
+ else
+ {
+ gmacdev->RxBusyDesc = synopGMAC_is_last_rx_desc(gmacdev, rxdesc) ? gmacdev->RxDesc : (rxdesc + 1);
+ synopGMAC_rx_desc_init_ring(rxdesc, synopGMAC_is_last_rx_desc(gmacdev, rxdesc));
+ }
+ TR("%02d %08x %08x %08x %08x %08x %08x %08x\n", rxnext, (u32)rxdesc, rxdesc->status, rxdesc->length, rxdesc->buffer1, rxdesc->buffer2, rxdesc->data1, rxdesc->data2);
+ (gmacdev->BusyRxDesc)--; //busy tx descriptor is reduced by one as it will be handed over to Processor now
+ return (rxnext);
+
+}
+#else
+
+/**
+ * Get back the descriptor from DMA after data has been received.
+ * When the DMA indicates that the data is received (interrupt is generated), this function should be
+ * called to get the descriptor and hence the data buffers received. With successful return from this
+ * function caller gets the descriptor fields for processing. check the parameters to understand the
+ * fields returned.`
+ * @param[in] pointer to synopGMACdevice.
+ * @param[out] pointer to hold the status of DMA.
+ * @param[out] Dma-able buffer1 pointer.
+ * @param[out] pointer to hold length of buffer1 (Max is 2048).
+ * @param[out] virtual pointer for buffer1.
+ * @param[out] Dma-able buffer2 pointer.
+ * @param[out] pointer to hold length of buffer2 (Max is 2048).
+ * @param[out] virtual pointer for buffer2.
+ * \return returns present rx descriptor index on success. Negative value if error.
+ */
+s32 synopGMAC_get_rx_qptr(synopGMACdevice *gmacdev, u32 *Status, u32 *Buffer1, u32 *Length1, u64 *Data1, u32 *Buffer2, u32 *Length2, u64 *Data2)
+{
+ u32 rxnext = gmacdev->RxBusy; // index of descriptor the DMA just completed. May be useful when data
+ //is spread over multiple buffers/descriptors
+ DmaDesc *rxdesc = gmacdev->RxBusyDesc;
+ u32 len;
+ if (synopGMAC_is_desc_owned_by_dma(rxdesc))
+ {
+ DEBUG_MES("synopGMAC_get_rx_qptr:DMA descriptor is owned by GMAC!\n");
+ return -1;
+ }
+
+ if (synopGMAC_is_desc_empty(rxdesc))
+ {
+ DEBUG_MES("synopGMAC_get_rx_qptr:rx desc is empty!\n");
+ return -1;
+ }
+
+ if (Status != 0)
+ *Status = rxdesc->status;// send the status of this descriptor
+
+ if (Length1 != 0)
+ *Length1 = (rxdesc->length & DescSize1Mask) >> DescSize1Shift;
+ if (Buffer1 != 0)
+ *Buffer1 = rxdesc->buffer1;
+ if (Data1 != 0)
+ *Data1 = rxdesc->data1;
+ if (Length2 != 0)
+ *Length2 = (rxdesc->length & DescSize2Mask) >> DescSize2Shift;
+ if (Buffer2 != 0)
+ *Buffer2 = rxdesc->buffer2;
+ if (Data1 != 0)
+ *Data2 = rxdesc->data2;
+
+ len = synopGMAC_get_rx_desc_frame_length(*Status);
+ DEBUG_MES("Cache sync for data buffer in rx dma desc: length = 0x%x\n", len);
+ gmacdev->RxBusy = synopGMAC_is_last_rx_desc(gmacdev, rxdesc) ? 0 : rxnext + 1;
+ if (synopGMAC_is_rx_desc_chained(rxdesc))
+ {
+ gmacdev->RxBusyDesc = (DmaDesc *)rxdesc->data2;
+ synopGMAC_rx_desc_init_chain(rxdesc);
+ }
+ else
+ {
+ gmacdev->RxBusyDesc = synopGMAC_is_last_rx_desc(gmacdev, rxdesc) ? gmacdev->RxDesc : (rxdesc + 1);
+//sw: raw data
+#if SYNOP_RX_DEBUG
+ DEBUG_MES("%02d %08x %08x %08x %08x %08x %08x %08x\n", rxnext, (u32)rxdesc, rxdesc->status, rxdesc->length, rxdesc->buffer1, rxdesc->buffer2, rxdesc->data1, rxdesc->data2);
+#endif
+ synopGMAC_rx_desc_init_ring(rxdesc, synopGMAC_is_last_rx_desc(gmacdev, rxdesc));
+ }
+#if SYNOP_RX_DEBUG
+ DEBUG_MES("%02d %08x %08x %08x %08x %08x %08x %08x\n", rxnext, (u32)rxdesc, rxdesc->status, rxdesc->length, rxdesc->buffer1, rxdesc->buffer2, rxdesc->data1, rxdesc->data2);
+#endif
+
+ (gmacdev->BusyRxDesc)--; //This returns one descriptor to processor. So busy count will be decremented by one
+ return (rxnext);
+
+}
+
+#endif
+
+/**
+ * Clears all the pending interrupts.
+ * If the Dma status register is read then all the interrupts gets cleared
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_clear_interrupt(synopGMACdevice *gmacdev)
+{
+ u32 data;
+ data = synopGMACReadReg(gmacdev->DmaBase, DmaStatus);
+ TR("DMA status reg = 0x%x before cleared!\n", data);
+ synopGMACWriteReg(gmacdev->DmaBase, DmaStatus, data);
+ // plat_delay(DEFAULT_LOOP_VARIABLE);
+// data = synopGMACReadReg(gmacdev->DmaBase, DmaStatus);
+ TR("DMA status reg = 0x%x after cleared!\n", data);
+}
+
+/**
+ * Returns the all unmasked interrupt status after reading the DmaStatus register.
+ * @param[in] pointer to synopGMACdevice.
+ * \return 0 upon success. Error code upon failure.
+ */
+u32 synopGMAC_get_interrupt_type(synopGMACdevice *gmacdev)
+{
+ u32 data;
+ u32 interrupts = 0;
+ data = synopGMACReadReg(gmacdev->DmaBase, DmaStatus);
+
+ //data = data & ~0x84; //sw: some bits shoud not be cleaned
+ synopGMACWriteReg(gmacdev->DmaBase, DmaStatus, data); //manju: I think this is the appropriate location to clear the interrupts
+ plat_delay(DEFAULT_LOOP_VARIABLE);
+ if (data & DmaIntErrorMask) interrupts |= synopGMACDmaError;
+ if (data & DmaIntRxNormMask) interrupts |= synopGMACDmaRxNormal;
+ if (data & DmaIntRxAbnMask) interrupts |= synopGMACDmaRxAbnormal;
+ if (data & DmaIntRxStoppedMask) interrupts |= synopGMACDmaRxStopped;
+ if (data & DmaIntTxNormMask) interrupts |= synopGMACDmaTxNormal;
+ if (data & DmaIntTxAbnMask) interrupts |= synopGMACDmaTxAbnormal;
+ if (data & DmaIntTxStoppedMask) interrupts |= synopGMACDmaTxStopped;
+
+ return interrupts;
+}
+
+/**
+ * Returns the interrupt mask.
+ * @param[in] pointer to synopGMACdevice.
+ * \return 0 upon success. Error code upon failure.
+ */
+#if UNUSED
+u32 synopGMAC_get_interrupt_mask(synopGMACdevice *gmacdev)
+{
+ return (synopGMACReadReg(gmacdev->DmaBase, DmaInterrupt));
+}
+#endif
+
+/**
+ * Enable all the interrupts.
+ * Enables the DMA interrupt as specified by the bit mask.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] bit mask of interrupts to be enabled.
+ * \return returns void.
+ */
+#if UNUSED
+void synopGMAC_enable_interrupt(synopGMACdevice *gmacdev, u32 interrupts)
+{
+ synopGMACWriteReg(gmacdev->DmaBase, DmaInterrupt, interrupts);
+ return;
+}
+#endif
+
+
+/**
+ * Disable all the interrupts.
+ * Disables all DMA interrupts.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ * \note This function disabled all the interrupts, if you want to disable a particular interrupt then
+ * use synopGMAC_disable_interrupt().
+ */
+void synopGMAC_disable_interrupt_all(synopGMACdevice *gmacdev)
+{
+// rt_kprintf("dmabase = 0x%x\n",gmacdev->DmaBase);
+ synopGMACWriteReg(gmacdev->DmaBase, DmaInterrupt, DmaIntDisable);
+// synopGMACReadReg(gmacdev->DmaBase, DmaInterrupt);
+ return;
+}
+
+/**
+ * Disable interrupt according to the bitfield supplied.
+ * Disables only those interrupts specified in the bit mask in second argument.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] bit mask for interrupts to be disabled.
+ * \return returns void.
+ */
+#if UNUSED
+void synopGMAC_disable_interrupt(synopGMACdevice *gmacdev, u32 interrupts)
+{
+ synopGMACClearBits(gmacdev->DmaBase, DmaInterrupt, interrupts);
+ return;
+}
+#endif
+/**
+ * Enable the DMA Reception.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_enable_dma_rx(synopGMACdevice *gmacdev)
+{
+// synopGMACSetBits(gmacdev->DmaBase, DmaControl, DmaRxStart);
+ u32 data;
+ data = synopGMACReadReg(gmacdev->DmaBase, DmaControl);
+ data |= DmaRxStart;
+ TR0(" ===33334\n");
+ synopGMACWriteReg(gmacdev->DmaBase, DmaControl, data);
+ TR0(" ===33344\n");
+}
+
+/**
+ * Enable the DMA Transmission.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_enable_dma_tx(synopGMACdevice *gmacdev)
+{
+// synopGMACSetBits(gmacdev->DmaBase, DmaControl, DmaTxStart);
+ u32 data;
+ data = synopGMACReadReg(gmacdev->DmaBase, DmaControl);
+ data |= DmaTxStart;
+ synopGMACWriteReg(gmacdev->DmaBase, DmaControl, data);
+
+}
+
+/**
+ * Resumes the DMA Transmission.
+ * the DmaTxPollDemand is written. (the data writeen could be anything).
+ * This forces the DMA to resume transmission.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_resume_dma_tx(synopGMACdevice *gmacdev)
+{
+ synopGMACWriteReg(gmacdev->DmaBase, DmaTxPollDemand, 1);
+
+}
+/**
+ * Resumes the DMA Reception.
+ * the DmaRxPollDemand is written. (the data writeen could be anything).
+ * This forces the DMA to resume reception.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_resume_dma_rx(synopGMACdevice *gmacdev)
+{
+ synopGMACWriteReg(gmacdev->DmaBase, DmaRxPollDemand, 0);
+
+}
+/**
+ * Take ownership of this Descriptor.
+ * The function is same for both the ring mode and the chain mode DMA structures.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_take_desc_ownership(DmaDesc *desc)
+{
+ if (desc)
+ {
+ desc->status &= ~DescOwnByDma; //Clear the DMA own bit
+// desc->status |= DescError; // Set the error to indicate this descriptor is bad
+ }
+}
+
+/**
+ * Take ownership of all the rx Descriptors.
+ * This function is called when there is fatal error in DMA transmission.
+ * When called it takes the ownership of all the rx descriptor in rx descriptor pool/queue from DMA.
+ * The function is same for both the ring mode and the chain mode DMA structures.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ * \note Make sure to disable the transmission before calling this function, otherwise may result in racing situation.
+ */
+void synopGMAC_take_desc_ownership_rx(synopGMACdevice *gmacdev)
+{
+ s32 i;
+ DmaDesc *desc;
+ desc = gmacdev->RxDesc;
+ for (i = 0; i < gmacdev->RxDescCount; i++)
+ {
+ if (synopGMAC_is_rx_desc_chained(desc)) //This descriptor is in chain mode
+ {
+
+ synopGMAC_take_desc_ownership(desc);
+ desc = (DmaDesc *)desc->data2;
+ }
+ else
+ {
+ synopGMAC_take_desc_ownership(desc + i);
+ }
+ }
+}
+
+/**
+ * Take ownership of all the rx Descriptors.
+ * This function is called when there is fatal error in DMA transmission.
+ * When called it takes the ownership of all the tx descriptor in tx descriptor pool/queue from DMA.
+ * The function is same for both the ring mode and the chain mode DMA structures.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ * \note Make sure to disable the transmission before calling this function, otherwise may result in racing situation.
+ */
+void synopGMAC_take_desc_ownership_tx(synopGMACdevice *gmacdev)
+{
+ s32 i;
+ DmaDesc *desc;
+ desc = gmacdev->TxDesc;
+ for (i = 0; i < gmacdev->TxDescCount; i++)
+ {
+ if (synopGMAC_is_tx_desc_chained(desc)) //This descriptor is in chain mode
+ {
+ synopGMAC_take_desc_ownership(desc);
+ desc = (DmaDesc *)desc->data2;
+ }
+ else
+ {
+ synopGMAC_take_desc_ownership(desc + i);
+ }
+ }
+}
+
+/**
+ * Disable the DMA for Transmission.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+
+void synopGMAC_disable_dma_tx(synopGMACdevice *gmacdev)
+{
+// synopGMACClearBits(gmacdev->DmaBase, DmaControl, DmaTxStart);
+ u32 data;
+ data = synopGMACReadReg(gmacdev->DmaBase, DmaControl);
+ data &= (~DmaTxStart);
+ synopGMACWriteReg(gmacdev->DmaBase, DmaControl, data);
+}
+/**
+ * Disable the DMA for Reception.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_disable_dma_rx(synopGMACdevice *gmacdev)
+{
+// synopGMACClearBits(gmacdev->DmaBase, DmaControl, DmaRxStart);
+ u32 data;
+ data = synopGMACReadReg(gmacdev->DmaBase, DmaControl);
+ data &= (~DmaRxStart);
+ synopGMACWriteReg(gmacdev->DmaBase, DmaControl, data);
+}
+/*******************PMT APIs***************************************/
+/**
+ * Enables the assertion of PMT interrupt.
+ * This enables the assertion of PMT interrupt due to Magic Pkt or Wakeup frame
+ * reception.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+#if UNUSED
+void synopGMAC_pmt_int_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev->MacBase, GmacInterruptMask, GmacPmtIntMask);
+ return;
+}
+#endif
+/**
+ * Disables the assertion of PMT interrupt.
+ * This disables the assertion of PMT interrupt due to Magic Pkt or Wakeup frame
+ * reception.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_pmt_int_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev->MacBase, GmacInterruptMask, GmacPmtIntMask);
+ return;
+}
+/**
+ * Enables the power down mode of GMAC.
+ * This function puts the Gmac in power down mode.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+#if UNUSED
+void synopGMAC_power_down_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev->MacBase, GmacPmtCtrlStatus, GmacPmtPowerDown);
+ return;
+}
+#endif
+/**
+ * Disables the powerd down setting of GMAC.
+ * If the driver wants to bring up the GMAC from powerdown mode, even though the magic packet or the
+ * wake up frames received from the network, this function should be called.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+#if UNUSED
+void synopGMAC_power_down_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev->MacBase, GmacPmtCtrlStatus, GmacPmtPowerDown);
+ return;
+}
+#endif
+/**
+ * Enables the pmt interrupt generation in powerdown mode.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+#if UNUSED
+void synopGMAC_enable_pmt_interrupt(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev->MacBase, GmacInterruptMask, GmacPmtIntMask);
+}
+#endif
+/**
+ * Disables the pmt interrupt generation in powerdown mode.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+#if UNUSED
+void synopGMAC_disable_pmt_interrupt(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev->MacBase, GmacInterruptMask, GmacPmtIntMask);
+}
+#endif
+/**
+ * Enables GMAC to look for Magic packet.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+#if UNUSED
+void synopGMAC_magic_packet_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev->MacBase, GmacPmtCtrlStatus, GmacPmtMagicPktEnable);
+ return;
+}
+#endif
+
+/**
+ * Enables GMAC to look for wake up frame.
+ * Wake up frame is defined by the user.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+#if UNUSED
+void synopGMAC_wakeup_frame_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev->MacBase, GmacPmtCtrlStatus, GmacPmtWakeupFrameEnable);
+ return;
+}
+#endif
+
+/**
+ * Enables wake-up frame filter to handle unicast packets.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+#if UNUSED
+void synopGMAC_pmt_unicast_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev->MacBase, GmacPmtCtrlStatus, GmacPmtGlobalUnicast);
+ return;
+}
+#endif
+/**
+ * Checks whether the packet received is a magic packet?.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns True if magic packet received else returns false.
+ */
+bool synopGMAC_is_magic_packet_received(synopGMACdevice *gmacdev)
+{
+ u32 data;
+ data = synopGMACReadReg(gmacdev->MacBase, GmacPmtCtrlStatus);
+ return ((data & GmacPmtMagicPktReceived) == GmacPmtMagicPktReceived);
+}
+/**
+ * Checks whether the packet received is a wakeup frame?.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns true if wakeup frame received else returns false.
+ */
+bool synopGMAC_is_wakeup_frame_received(synopGMACdevice *gmacdev)
+{
+ u32 data;
+ data = synopGMACReadReg(gmacdev->MacBase, GmacPmtCtrlStatus);
+ return ((data & GmacPmtWakeupFrameReceived) == GmacPmtWakeupFrameReceived);
+}
+
+/**
+ * Populates the remote wakeup frame registers.
+ * Consecutive 8 writes to GmacWakeupAddr writes the wakeup frame filter registers.
+ * Before commensing a new write, frame filter pointer is reset to 0x0000.
+ * A small delay is introduced to allow frame filter pointer reset operation.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] pointer to frame filter contents array.
+ * \return returns void.
+ */
+#if UNUSED
+void synopGMAC_write_wakeup_frame_register(synopGMACdevice *gmacdev, u32 *filter_contents)
+{
+ s32 i;
+ synopGMACSetBits(gmacdev->MacBase, GmacPmtCtrlStatus, GmacPmtFrmFilterPtrReset);
+ plat_delay(10);
+ for (i = 0; i < WAKEUP_REG_LENGTH; i++)
+ synopGMACWriteReg(gmacdev->MacBase, GmacWakeupAddr, *(filter_contents + i));
+ return;
+
+}
+#endif
+
+/*******************PMT APIs***************************************/
+/*******************MMC APIs***************************************/
+/**
+ * Freezes the MMC counters.
+ * This function call freezes the MMC counters. None of the MMC counters are updated
+ * due to any tx or rx frames until synopGMAC_mmc_counters_resume is called.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+#if UNUSED
+void synopGMAC_mmc_counters_stop(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev->MacBase, GmacMmcCntrl, GmacMmcCounterFreeze);
+ return;
+}
+#endif
+/**
+ * Resumes the MMC counter updation.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+#if UNUSED
+void synopGMAC_mmc_counters_resume(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev->MacBase, GmacMmcCntrl, GmacMmcCounterFreeze);
+ return;
+}
+#endif
+/**
+ * Configures the MMC in Self clearing mode.
+ * Programs MMC interface so that counters are cleared when the counters are read.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+#if UNUSED
+void synopGMAC_mmc_counters_set_selfclear(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev->MacBase, GmacMmcCntrl, GmacMmcCounterResetOnRead);
+ return;
+}
+#endif
+/**
+ * Configures the MMC in non-Self clearing mode.
+ * Programs MMC interface so that counters are cleared when the counters are read.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+#if UNUSED
+void synopGMAC_mmc_counters_reset_selfclear(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev->MacBase, GmacMmcCntrl, GmacMmcCounterResetOnRead);
+ return;
+}
+#endif
+/**
+ * Configures the MMC to stop rollover.
+ * Programs MMC interface so that counters will not rollover after reaching maximum value.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+#if UNUSED
+void synopGMAC_mmc_counters_disable_rollover(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev->MacBase, GmacMmcCntrl, GmacMmcCounterStopRollover);
+ return;
+}
+/**
+ * Configures the MMC to rollover.
+ * Programs MMC interface so that counters will rollover after reaching maximum value.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_mmc_counters_enable_rollover(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev->MacBase, GmacMmcCntrl, GmacMmcCounterStopRollover);
+ return;
+}
+
+/**
+ * Read the MMC Counter.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] the counter to be read.
+ * \return returns the read count value.
+ */
+u32 synopGMAC_read_mmc_counter(synopGMACdevice *gmacdev, u32 counter)
+{
+ return (synopGMACReadReg(gmacdev->MacBase, counter));
+}
+#endif
+/**
+ * Read the MMC Rx interrupt status.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns the Rx interrupt status.
+ */
+u32 synopGMAC_read_mmc_rx_int_status(synopGMACdevice *gmacdev)
+{
+ return (synopGMACReadReg(gmacdev->MacBase, GmacMmcIntrRx));
+}
+/**
+ * Read the MMC Tx interrupt status.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns the Tx interrupt status.
+ */
+u32 synopGMAC_read_mmc_tx_int_status(synopGMACdevice *gmacdev)
+{
+ return (synopGMACReadReg(gmacdev->MacBase, GmacMmcIntrTx));
+}
+/**
+ * Disable the MMC Tx interrupt.
+ * The MMC tx interrupts are masked out as per the mask specified.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] tx interrupt bit mask for which interrupts needs to be disabled.
+ * \return returns void.
+ */
+void synopGMAC_disable_mmc_tx_interrupt(synopGMACdevice *gmacdev, u32 mask)
+{
+ synopGMACSetBits(gmacdev->MacBase, GmacMmcIntrMaskTx, mask);
+ return;
+}
+/**
+ * Enable the MMC Tx interrupt.
+ * The MMC tx interrupts are enabled as per the mask specified.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] tx interrupt bit mask for which interrupts needs to be enabled.
+ * \return returns void.
+ */
+#if UNUSED
+void synopGMAC_enable_mmc_tx_interrupt(synopGMACdevice *gmacdev, u32 mask)
+{
+ synopGMACClearBits(gmacdev->MacBase, GmacMmcIntrMaskTx, mask);
+}
+#endif
+/**
+ * Disable the MMC Rx interrupt.
+ * The MMC rx interrupts are masked out as per the mask specified.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] rx interrupt bit mask for which interrupts needs to be disabled.
+ * \return returns void.
+ */
+void synopGMAC_disable_mmc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask)
+{
+ synopGMACSetBits(gmacdev->MacBase, GmacMmcIntrMaskRx, mask);
+ return;
+}
+/**
+ * Enable the MMC Rx interrupt.
+ * The MMC rx interrupts are enabled as per the mask specified.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] rx interrupt bit mask for which interrupts needs to be enabled.
+ * \return returns void.
+ */
+#if UNUSED
+void synopGMAC_enable_mmc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask)
+{
+ synopGMACClearBits(gmacdev->MacBase, GmacMmcIntrMaskRx, mask);
+ return;
+}
+#endif
+/**
+ * Disable the MMC ipc rx checksum offload interrupt.
+ * The MMC ipc rx checksum offload interrupts are masked out as per the mask specified.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] rx interrupt bit mask for which interrupts needs to be disabled.
+ * \return returns void.
+ */
+void synopGMAC_disable_mmc_ipc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask)
+{
+ synopGMACSetBits(gmacdev->MacBase, GmacMmcRxIpcIntrMask, mask);
+ return;
+}
+/**
+ * Enable the MMC ipc rx checksum offload interrupt.
+ * The MMC ipc rx checksum offload interrupts are enabled as per the mask specified.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] rx interrupt bit mask for which interrupts needs to be enabled.
+ * \return returns void.
+ */
+#if UNUSED
+void synopGMAC_enable_mmc_ipc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask)
+{
+ synopGMACClearBits(gmacdev->MacBase, GmacMmcRxIpcIntrMask, mask);
+ return;
+}
+#endif
+/*******************MMC APIs***************************************/
+/*******************Ip checksum offloading APIs***************************************/
+
+/**
+ * Enables the ip checksum offloading in receive path.
+ * When set GMAC calculates 16 bit 1's complement of all received ethernet frame payload.
+ * It also checks IPv4 Header checksum is correct. GMAC core appends the 16 bit checksum calculated
+ * for payload of IP datagram and appends it to Ethernet frame transferred to the application.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+#if UNUSED
+void synopGMAC_enable_rx_chksum_offload(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev->MacBase, GmacConfig, GmacRxIpcOffload);
+ return;
+}
+/**
+ * Disable the ip checksum offloading in receive path.
+ * Ip checksum offloading is disabled in the receive path.
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_disable_rx_Ipchecksum_offload(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev->MacBase, GmacConfig, GmacRxIpcOffload);
+}
+/**
+ * Instruct the DMA to drop the packets fails tcp ip checksum.
+ * This is to instruct the receive DMA engine to drop the recevied packet if they
+ * fails the tcp/ip checksum in hardware. Valid only when full checksum offloading is enabled(type-2).
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_rx_tcpip_chksum_drop_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev->DmaBase, DmaControl, DmaDisableDropTcpCs);
+ return;
+}
+/**
+ * Instruct the DMA not to drop the packets even if it fails tcp ip checksum.
+ * This is to instruct the receive DMA engine to allow the packets even if recevied packet
+ * fails the tcp/ip checksum in hardware. Valid only when full checksum offloading is enabled(type-2).
+ * @param[in] pointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_rx_tcpip_chksum_drop_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev->DmaBase, DmaControl, DmaDisableDropTcpCs);
+ return;
+}
+#endif
+
+/**
+ * When the Enhanced Descriptor is enabled then the bit 0 of RDES0 indicates whether the
+ * Extended Status is available (RDES4). Time Stamp feature and the Checksum Offload Engine2
+ * makes use of this extended status to provide the status of the received packet.
+ * @param[in] pointer to synopGMACdevice
+ * \return returns TRUE or FALSE
+ */
+#ifdef ENH_DESC_8W
+/**
+ * This function indicates whether extended status is available in the RDES0.
+ * Any function which accesses the fields of extended status register must ensure a check on this has been made
+ * This is valid only for Enhanced Descriptor.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] u32 status field of the corresponding descriptor.
+ * \return returns TRUE or FALSE.
+ */
+bool synopGMAC_is_ext_status(synopGMACdevice *gmacdev, u32 status) // extended status present indicates that the RDES4 need to be probed
+{
+ return ((status & DescRxEXTsts) != 0); // if extstatus set then it returns 1
+}
+/**
+ * This function returns true if the IP header checksum bit is set in the extended status.
+ * Valid only when enhaced status available is set in RDES0 bit 0.
+ * This is valid only for Enhanced Descriptor.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] u32 status field of the corresponding descriptor.
+ * \return returns TRUE or FALSE.
+ */
+bool synopGMAC_ES_is_IP_header_error(synopGMACdevice *gmacdev, u32 ext_status) // IP header (IPV4) checksum error
+{
+ return ((ext_status & DescRxIpHeaderError) != 0); // if IPV4 header error return 1
+}
+/**
+ * This function returns true if the Checksum is bypassed in the hardware.
+ * Valid only when enhaced status available is set in RDES0 bit 0.
+ * This is valid only for Enhanced Descriptor.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] u32 status field of the corresponding descriptor.
+ * \return returns TRUE or FALSE.
+ */
+bool synopGMAC_ES_is_rx_checksum_bypassed(synopGMACdevice *gmacdev, u32 ext_status) // Hardware engine bypassed the checksum computation/checking
+{
+ return ((ext_status & DescRxChkSumBypass) != 0); // if checksum offloading bypassed return 1
+}
+/**
+ * This function returns true if payload checksum error is set in the extended status.
+ * Valid only when enhaced status available is set in RDES0 bit 0.
+ * This is valid only for Enhanced Descriptor.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] u32 status field of the corresponding descriptor.
+ * \return returns TRUE or FALSE.
+ */
+bool synopGMAC_ES_is_IP_payload_error(synopGMACdevice *gmacdev, u32 ext_status) // IP payload checksum is in error (UDP/TCP/ICMP checksum error)
+{
+ return ((ext_status & DescRxIpPayloadError) != 0); // if IP payload error return 1
+}
+#endif
+
+/**
+ * Decodes the Rx Descriptor status to various checksum error conditions.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] u32 status field of the corresponding descriptor.
+ * \return returns decoded enum (u32) indicating the status.
+ */
+u32 synopGMAC_is_rx_checksum_error(synopGMACdevice *gmacdev, u32 status)
+{
+ if (((status & DescRxChkBit5) == 0) && ((status & DescRxChkBit7) == 0) && ((status & DescRxChkBit0) == 0))
+ return RxLenLT600;
+ else if (((status & DescRxChkBit5) == 0) && ((status & DescRxChkBit7) == 0) && ((status & DescRxChkBit0) != 0))
+ return RxIpHdrPayLoadChkBypass;
+ else if (((status & DescRxChkBit5) == 0) && ((status & DescRxChkBit7) != 0) && ((status & DescRxChkBit0) != 0))
+ return RxChkBypass;
+ else if (((status & DescRxChkBit5) != 0) && ((status & DescRxChkBit7) == 0) && ((status & DescRxChkBit0) == 0))
+ return RxNoChkError;
+ else if (((status & DescRxChkBit5) != 0) && ((status & DescRxChkBit7) == 0) && ((status & DescRxChkBit0) != 0))
+ return RxPayLoadChkError;
+ else if (((status & DescRxChkBit5) != 0) && ((status & DescRxChkBit7) != 0) && ((status & DescRxChkBit0) == 0))
+ return RxIpHdrChkError;
+ else if (((status & DescRxChkBit5) != 0) && ((status & DescRxChkBit7) != 0) && ((status & DescRxChkBit0) != 0))
+ return RxIpHdrPayLoadChkError;
+ else
+ return RxIpHdrPayLoadRes;
+}
+/**
+ * Checks if any Ipv4 header checksum error in the frame just transmitted.
+ * This serves as indication that error occureed in the IPv4 header checksum insertion.
+ * The sent out frame doesnot carry any ipv4 header checksum inserted by the hardware.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] u32 status field of the corresponding descriptor.
+ * \return returns true if error in ipv4 header checksum, else returns false.
+ */
+bool synopGMAC_is_tx_ipv4header_checksum_error(synopGMACdevice *gmacdev, u32 status)
+{
+ return ((status & DescTxIpv4ChkError) == DescTxIpv4ChkError);
+}
+
+/**
+ * Checks if any payload checksum error in the frame just transmitted.
+ * This serves as indication that error occureed in the payload checksum insertion.
+ * The sent out frame doesnot carry any payload checksum inserted by the hardware.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] u32 status field of the corresponding descriptor.
+ * \return returns true if error in ipv4 header checksum, else returns false.
+ */
+bool synopGMAC_is_tx_payload_checksum_error(synopGMACdevice *gmacdev, u32 status)
+{
+ return ((status & DescTxPayChkError) == DescTxPayChkError);
+}
+/**
+ * The check summ offload engine is bypassed in the tx path.
+ * Checksum is not computed in the Hardware.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] Pointer to tx descriptor for which ointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_tx_checksum_offload_bypass(synopGMACdevice *gmacdev, DmaDesc *desc)
+{
+#ifdef ENH_DESC
+ desc->status = (desc->length & (~DescTxCisMask));//ENH_DESC
+#else
+ desc->length = (desc->length & (~DescTxCisMask));
+#endif
+}
+/**
+ * The check summ offload engine is enabled to do only IPV4 header checksum.
+ * IPV4 header Checksum is computed in the Hardware.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] Pointer to tx descriptor for which ointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_tx_checksum_offload_ipv4hdr(synopGMACdevice *gmacdev, DmaDesc *desc)
+{
+#ifdef ENH_DESC
+ desc->status = ((desc->status & (~DescTxCisMask)) | DescTxCisIpv4HdrCs);//ENH_DESC
+#else
+ desc->length = ((desc->length & (~DescTxCisMask)) | DescTxCisIpv4HdrCs);
+#endif
+}
+
+/**
+ * The check summ offload engine is enabled to do TCPIP checsum assuming Pseudo header is available.
+ * Hardware computes the tcp ip checksum assuming pseudo header checksum is computed in software.
+ * Ipv4 header checksum is also inserted.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] Pointer to tx descriptor for which ointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_tx_checksum_offload_tcponly(synopGMACdevice *gmacdev, DmaDesc *desc)
+{
+#ifdef ENH_DESC
+ desc->status = ((desc->status & (~DescTxCisMask)) | DescTxCisTcpOnlyCs);//ENH_DESC
+#else
+ desc->length = ((desc->length & (~DescTxCisMask)) | DescTxCisTcpOnlyCs);
+#endif
+}
+/**
+ * The check summ offload engine is enabled to do complete checksum computation.
+ * Hardware computes the tcp ip checksum including the pseudo header checksum.
+ * Here the tcp payload checksum field should be set to 0000.
+ * Ipv4 header checksum is also inserted.
+ * @param[in] pointer to synopGMACdevice.
+ * @param[in] Pointer to tx descriptor for which ointer to synopGMACdevice.
+ * \return returns void.
+ */
+void synopGMAC_tx_checksum_offload_tcp_pseudo(synopGMACdevice *gmacdev, DmaDesc *desc)
+{
+#ifdef ENH_DESC
+ desc->status = ((desc->length & (~DescTxCisMask)) | DescTxCisTcpPseudoCs);
+#else
+ desc->length = ((desc->length & (~DescTxCisMask)) | DescTxCisTcpPseudoCs);
+#endif
+
+}
+/*******************Ip checksum offloading APIs***************************************/
+/*******************IEEE 1588 Timestamping API***************************************/
+/*
+ * At this time the driver supports the IEEE time stamping feature when the Enhanced Descriptors are enabled.
+ * For normal descriptor and the IEEE time stamp (version 1), driver support is not proviced
+ * Please make sure you have enabled the Advanced timestamp feature in the hardware and the driver should
+ * be compiled with the ADV_TME_STAMP feature.
+ * Some of the APIs provided here may not be valid for all configurations. Please make sure you call the
+ * API with due care.
+ */
+
+/**
+ * This function enables the timestamping. This enables the timestamping for transmit and receive frames.
+ * When disabled timestamp is not added to tx and receive frames and timestamp generator is suspended.
+ * @param[in] pointer to synopGMACdevice
+ * \return returns void
+ */
+#if UNUSED
+void synopGMAC_TS_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev->MacBase, GmacTSControl, GmacTSENA);
+ return;
+}
+/**
+ * This function disables the timestamping.
+ * When disabled timestamp is not added to tx and receive frames and timestamp generator is suspended.
+ * @param[in] pointer to synopGMACdevice
+ * \return returns void
+ */
+void synopGMAC_TS_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev->MacBase, GmacInterruptMask, GmacTSIntMask);
+ return;
+}
+
+/**
+ * Enable the interrupt to get timestamping interrupt.
+ * This enables the host to get the interrupt when (1) system time is greater or equal to the
+ * target time high and low register or (2) there is a overflow in th esecond register.
+ * @param[in] pointer to synopGMACdevice
+ * \return returns void
+ */
+void synopGMAC_TS_int_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev->MacBase, GmacInterruptMask, GmacPmtIntMask);
+ return;
+}
+
+/**
+ * Disable the interrupt to get timestamping interrupt.
+ * @param[in] pointer to synopGMACdevice
+ * \return returns void
+ */
+void synopGMAC_TS_int_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev->MacBase, GmacInterruptMask, GmacPmtIntMask);
+ return;
+}
+
+/**
+ * Enable MAC address for PTP frame filtering.
+ * When enabled, uses MAC address (apart from MAC address 0) to filter the PTP frames when
+ * PTP is sent directly over Ethernet.
+ * @param[in] pointer to synopGMACdevice
+ * \return returns void
+ */
+void synopGMAC_TS_mac_addr_filt_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev->MacBase, GmacTSControl, GmacTSENMACADDR);
+ return;
+}
+
+/**
+ * Disables MAC address for PTP frame filtering.
+ * @param[in] pointer to synopGMACdevice
+ * \return returns void
+ */
+void synopGMAC_TS_mac_addr_filt_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev->MacBase, GmacTSControl, GmacTSENMACADDR);
+ return;
+}
+
+/**
+ * Selet the type of clock mode for PTP.
+ * Please note to use one of the follwoing as the clk_type argument.
+ * GmacTSOrdClk = 0x00000000, 00=> Ordinary clock
+ * GmacTSBouClk = 0x00010000, 01=> Boundary clock
+ * GmacTSEtoEClk = 0x00020000, 10=> End-to-End transparent clock
+ * GmacTSPtoPClk = 0x00030000, 11=> P-to-P transparent clock
+ * @param[in] pointer to synopGMACdevice
+ * @param[in] u32 value representing one of the above clk value
+ * \return returns void
+ */
+void synopGMAC_TS_set_clk_type(synopGMACdevice *gmacdev, u32 clk_type)
+{
+ u32 clkval;
+ clkval = synopGMACReadReg(gmacdev->MacBase, GmacTSControl); //set the mdc clock to the user defined value
+ clkval = clkval | clk_type;
+ synopGMACWriteReg(gmacdev->MacBase, GmacTSControl, clkval);
+ return;
+}
+
+/**
+ * Enable Snapshot for messages relevant to Master.
+ * When enabled, snapshot is taken for messages relevant to master mode only, else snapshot is taken for messages relevant
+ * to slave node.
+ * Valid only for Ordinary clock and Boundary clock
+ * Reserved when "Advanced Time Stamp" is not selected
+ * @param[in] pointer to synopGMACdevice
+ * \return returns void
+ */
+void synopGMAC_TS_master_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev->MacBase, GmacTSControl, GmacTSMSTRENA);
+ return;
+}
+/**
+ * Disable Snapshot for messages relevant to Master.
+ * When disabled, snapshot is taken for messages relevant
+ * to slave node.
+ * Valid only for Ordinary clock and Boundary clock
+ * Reserved when "Advanced Time Stamp" is not selected
+ * @param[in] pointer to synopGMACdevice
+ * \return returns void
+ */
+void synopGMAC_TS_master_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev->MacBase, GmacTSControl, GmacTSMSTRENA);
+ return;
+}
+/**
+ * Enable Snapshot for Event messages.
+ * When enabled, snapshot is taken for event messages only (SYNC, Delay_Req, Pdelay_Req or Pdelay_Resp)
+ * When disabled, snapshot is taken for all messages except Announce, Management and Signaling.
+ * Reserved when "Advanced Time Stamp" is not selected
+ * @param[in] pointer to synopGMACdevice
+ * \return returns void
+ */
+void synopGMAC_TS_event_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev->MacBase, GmacTSControl, GmacTSEVNTENA);
+ return;
+}
+/**
+ * Disable Snapshot for Event messages.
+ * When disabled, snapshot is taken for all messages except Announce, Management and Signaling.
+ * Reserved when "Advanced Time Stamp" is not selected
+ * @param[in] pointer to synopGMACdevice
+ * \return returns void
+ */
+void synopGMAC_TS_event_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev->MacBase, GmacTSControl, GmacTSEVNTENA);
+ return;
+}
+
+/**
+ * Enable time stamp snapshot for IPV4 frames.
+ * When enabled, time stamp snapshot is taken for IPV4 frames
+ * Reserved when "Advanced Time Stamp" is not selected
+ * @param[in] pointer to synopGMACdevice
+ * \return returns void
+ */
+void synopGMAC_TS_IPV4_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev->MacBase, GmacTSControl, GmacTSIPV4ENA);
+ return;
+}
+/**
+ * Disable time stamp snapshot for IPV4 frames.
+ * When disabled, time stamp snapshot is not taken for IPV4 frames
+ * Reserved when "Advanced Time Stamp" is not selected
+ * @param[in] pointer to synopGMACdevice
+ * \return returns void
+ */
+void synopGMAC_TS_IPV4_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev->MacBase, GmacTSControl, GmacTSIPV4ENA);
+ return;
+} // Only for "Advanced Time Stamp"
+/**
+ * Enable time stamp snapshot for IPV6 frames.
+ * When enabled, time stamp snapshot is taken for IPV6 frames
+ * Reserved when "Advanced Time Stamp" is not selected
+ * @param[in] pointer to synopGMACdevice
+ * \return returns void
+ */
+void synopGMAC_TS_IPV6_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev->MacBase, GmacTSControl, GmacTSIPV6ENA);
+ return;
+}
+/**
+ * Disable time stamp snapshot for IPV6 frames.
+ * When disabled, time stamp snapshot is not taken for IPV6 frames
+ * Reserved when "Advanced Time Stamp" is not selected
+ * @param[in] pointer to synopGMACdevice
+ * \return returns void
+ */
+void synopGMAC_TS_IPV6_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev->MacBase, GmacTSControl, GmacTSIPV6ENA);
+ return;
+}
+
+/**
+ * Enable time stamp snapshot for PTP over Ethernet frames.
+ * When enabled, time stamp snapshot is taken for PTP over Ethernet frames
+ * Reserved when "Advanced Time Stamp" is not selected
+ * @param[in] pointer to synopGMACdevice
+ * \return returns void
+ */
+void synopGMAC_TS_ptp_over_ethernet_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev->MacBase, GmacTSControl, GmacTSIPENA);
+ return;
+}
+/**
+ * Disable time stamp snapshot for PTP over Ethernet frames.
+ * When disabled, time stamp snapshot is not taken for PTP over Ethernet frames
+ * Reserved when "Advanced Time Stamp" is not selected
+ * @param[in] pointer to synopGMACdevice
+ * \return returns void
+ */
+void synopGMAC_TS_ptp_over_ethernet_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev->MacBase, GmacTSControl, GmacTSIPENA);
+ return;
+}
+
+/**
+ * Snoop PTP packet for version 2 format
+ * When set the PTP packets are snooped using the version 2 format.
+ * @param[in] pointer to synopGMACdevice
+ * \return returns void
+ */
+void synopGMAC_TS_pkt_snoop_ver2(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev->MacBase, GmacTSControl, GmacTSVER2ENA);
+ return;
+}
+/**
+ * Snoop PTP packet for version 2 format
+ * When set the PTP packets are snooped using the version 2 format.
+ * @param[in] pointer to synopGMACdevice
+ * \return returns void
+ */
+void synopGMAC_TS_pkt_snoop_ver1(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev->MacBase, GmacTSControl, GmacTSVER2ENA);
+ return;
+}
+
+/**
+ * Timestamp digital rollover
+ * When set the timestamp low register rolls over after 0x3B9A_C9FF value.
+ * @param[in] pointer to synopGMACdevice
+ * \return returns void
+ */
+void synopGMAC_TS_digital_rollover_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev->MacBase, GmacTSControl, GmacTSCTRLSSR);
+ return;
+}
+/**
+ * Timestamp binary rollover
+ * When set the timestamp low register rolls over after 0x7FFF_FFFF value.
+ * @param[in] pointer to synopGMACdevice
+ * \return returns void
+ */
+void synopGMAC_TS_binary_rollover_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev->MacBase, GmacTSControl, GmacTSCTRLSSR);
+ return;
+}
+/**
+ * Enable Time Stamp for All frames
+ * When set the timestamp snap shot is enabled for all frames received by the core.
+ * Reserved when "Advanced Time Stamp" is not selected
+ * @param[in] pointer to synopGMACdevice
+ * \return returns void
+ */
+void synopGMAC_TS_all_frames_enable(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev->MacBase, GmacTSControl, GmacTSENALL);
+ return;
+}
+/**
+ * Disable Time Stamp for All frames
+ * When reset the timestamp snap shot is not enabled for all frames received by the core.
+ * Reserved when "Advanced Time Stamp" is not selected
+ * @param[in] pointer to synopGMACdevice
+ * \return returns void
+ */
+void synopGMAC_TS_all_frames_disable(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev->MacBase, GmacTSControl, GmacTSENALL);
+ return;
+}
+/**
+ * Addend Register Update
+ * This function loads the contents of Time stamp addend register with the supplied 32 value.
+ * This is reserved function when only coarse correction option is selected
+ * @param[in] pointer to synopGMACdevice
+ * @param[in] 32 bit addend value
+ * \return returns 0 for Success or else Failure
+ */
+s32 synopGMAC_TS_addend_update(synopGMACdevice *gmacdev, u32 addend_value)
+{
+ u32 loop_variable;
+ synopGMACWriteReg(gmacdev->MacBase, GmacTSAddend, addend_value); // Load the addend_value in to Addend register
+ for (loop_variable = 0; loop_variable < DEFAULT_LOOP_VARIABLE; loop_variable++) //Wait till the busy bit gets cleared with in a certain amount of time
+ {
+ if (!((synopGMACReadReg(gmacdev->MacBase, GmacTSControl)) & GmacTSADDREG)) // if it is cleared then break
+ {
+ break;
+ }
+ plat_delay(DEFAULT_DELAY_VARIABLE);
+ }
+ if (loop_variable < DEFAULT_LOOP_VARIABLE)
+ synopGMACSetBits(gmacdev->MacBase, GmacTSControl, GmacTSADDREG);
+ else
+ {
+ TR("Error::: The TSADDREG bit is not getting cleared !!!!!!\n");
+ return -ESYNOPGMACPHYERR;
+ }
+ return -ESYNOPGMACNOERR;
+}
+/**
+ * time stamp Update
+ * This function updates (adds/subtracts) with the value specified in the Timestamp High Update and
+ * Timestamp Low Update register.
+ * @param[in] pointer to synopGMACdevice
+ * @param[in] Timestamp High Update value
+ * @param[in] Timestamp Low Update value
+ * \return returns 0 for Success or else Failure
+ */
+s32 synopGMAC_TS_timestamp_update(synopGMACdevice *gmacdev, u32 high_value, u32 low_value)
+{
+ u32 loop_variable;
+ synopGMACWriteReg(gmacdev->MacBase, GmacTSHighUpdate, high_value); // Load the high value to Timestamp High register
+ synopGMACWriteReg(gmacdev->MacBase, GmacTSLowUpdate, low_value); // Load the high value to Timestamp High register
+ for (loop_variable = 0; loop_variable < DEFAULT_LOOP_VARIABLE; loop_variable++) //Wait till the busy bit gets cleared with in a certain amount of time
+ {
+ if (!((synopGMACReadReg(gmacdev->MacBase, GmacTSControl)) & GmacTSUPDT)) // if it is cleared then break
+ {
+ break;
+ }
+ plat_delay(DEFAULT_DELAY_VARIABLE);
+ }
+ if (loop_variable < DEFAULT_LOOP_VARIABLE)
+ synopGMACSetBits(gmacdev->MacBase, GmacTSControl, GmacTSUPDT);
+ else
+ {
+ TR("Error::: The TSADDREG bit is not getting cleared !!!!!!\n");
+ return -ESYNOPGMACPHYERR;
+ }
+ return -ESYNOPGMACNOERR;
+}
+
+/**
+ * time stamp Initialize
+ * This function Loads/Initializes h the value specified in the Timestamp High Update and
+ * Timestamp Low Update register.
+ * @param[in] pointer to synopGMACdevice
+ * @param[in] Timestamp High Load value
+ * @param[in] Timestamp Low Load value
+ * \return returns 0 for Success or else Failure
+ */
+s32 synopGMAC_TS_timestamp_init(synopGMACdevice *gmacdev, u32 high_value, u32 low_value)
+{
+ u32 loop_variable;
+ synopGMACWriteReg(gmacdev->MacBase, GmacTSHighUpdate, high_value); // Load the high value to Timestamp High register
+ synopGMACWriteReg(gmacdev->MacBase, GmacTSLowUpdate, low_value); // Load the high value to Timestamp High register
+ for (loop_variable = 0; loop_variable < DEFAULT_LOOP_VARIABLE; loop_variable++) //Wait till the busy bit gets cleared with in a certain amount of time
+ {
+ if (!((synopGMACReadReg(gmacdev->MacBase, GmacTSControl)) & GmacTSINT)) // if it is cleared then break
+ {
+ break;
+ }
+ plat_delay(DEFAULT_DELAY_VARIABLE);
+ }
+ if (loop_variable < DEFAULT_LOOP_VARIABLE)
+ synopGMACSetBits(gmacdev->MacBase, GmacTSControl, GmacTSINT);
+ else
+ {
+ TR("Error::: The TSADDREG bit is not getting cleared !!!!!!\n");
+ return -ESYNOPGMACPHYERR;
+ }
+ return -ESYNOPGMACNOERR;
+}
+
+/**
+ * Time Stamp Update Coarse
+ * When reset the timestamp update is done using coarse method.
+ * @param[in] pointer to synopGMACdevice
+ * \return returns void
+ */
+void synopGMAC_TS_coarse_update(synopGMACdevice *gmacdev)
+{
+ synopGMACClearBits(gmacdev->MacBase, GmacTSControl, GmacTSCFUPDT);
+ return;
+}
+/**
+ * Time Stamp Update Fine
+ * When reset the timestamp update is done using Fine method.
+ * @param[in] pointer to synopGMACdevice
+ * \return returns void
+ */
+void synopGMAC_TS_fine_update(synopGMACdevice *gmacdev)
+{
+ synopGMACSetBits(gmacdev->MacBase, GmacTSControl, GmacTSCFUPDT);
+ return;
+}
+
+/**
+ * Load the Sub Second Increment value in to Sub Second increment register
+ * @param[in] pointer to synopGMACdevice
+ * \return returns void
+ */
+void synopGMAC_TS_subsecond_init(synopGMACdevice *gmacdev, u32 sub_sec_inc_value)
+{
+ synopGMACWriteReg(gmacdev->MacBase, GmacTSSubSecIncr, (sub_sec_inc_value & GmacSSINCMsk));
+ return;
+}
+/**
+ * Reads the time stamp contents in to the respective pointers
+ * These registers are readonly.
+ * This function returns the 48 bit time stamp assuming Version 2 timestamp with higher word is selected.
+ * @param[in] pointer to synopGMACdevice
+ * @param[in] pointer to hold 16 higher bit second register contents
+ * @param[in] pointer to hold 32 bit second register contents
+ * @param[in] pointer to hold 32 bit subnanosecond register contents
+ * \return returns void
+ * \note Please note that since the atomic access to the timestamp registers is not possible,
+ * the contents read may be different from the actual time stamp.
+ */
+void synopGMAC_TS_read_timestamp(synopGMACdevice *gmacdev, u16 *higher_sec_val, u32 *sec_val, u32 *sub_sec_val)
+{
+ * higher_sec_val = (u16)(synopGMACReadReg(gmacdev->MacBase, GmacTSHighWord) & GmacTSHighWordMask);
+ * sec_val = synopGMACReadReg(gmacdev->MacBase, GmacTSHigh);
+ * sub_sec_val = synopGMACReadReg(gmacdev->MacBase, GmacTSLow);
+ return;
+}
+/**
+ * Loads the time stamp higher sec value from the value supplied
+ * @param[in] pointer to synopGMACdevice
+ * @param[in] 16 higher bit second register contents passed as 32 bit value
+ * \return returns void
+ */
+void synopGMAC_TS_load_timestamp_higher_val(synopGMACdevice *gmacdev, u32 higher_sec_val)
+{
+ synopGMACWriteReg(gmacdev->MacBase, GmacTSHighWord, (higher_sec_val & GmacTSHighWordMask));
+ return;
+}
+/**
+ * Reads the time stamp higher sec value to respective pointers
+ * @param[in] pointer to synopGMACdevice
+ * @param[in] pointer to hold 16 higher bit second register contents
+ * \return returns void
+ */
+void synopGMAC_TS_read_timestamp_higher_val(synopGMACdevice *gmacdev, u16 *higher_sec_val)
+{
+ * higher_sec_val = (u16)(synopGMACReadReg(gmacdev->MacBase, GmacTSHighWord) & GmacTSHighWordMask);
+ return;
+}
+/**
+ * Load the Target time stamp registers
+ * This function Loads the target time stamp registers with the values proviced
+ * @param[in] pointer to synopGMACdevice
+ * @param[in] target Timestamp High value
+ * @param[in] target Timestamp Low value
+ * \return returns 0 for Success or else Failure
+ */
+void synopGMAC_TS_load_target_timestamp(synopGMACdevice *gmacdev, u32 sec_val, u32 sub_sec_val)
+{
+ synopGMACWriteReg(gmacdev->MacBase, GmacTSTargetTimeHigh, sec_val);
+ synopGMACWriteReg(gmacdev->MacBase, GmacTSTargetTimeLow, sub_sec_val);
+ return;
+}
+/**
+ * Reads the Target time stamp registers
+ * This function Loads the target time stamp registers with the values proviced
+ * @param[in] pointer to synopGMACdevice
+ * @param[in] pointer to hold target Timestamp High value
+ * @param[in] pointer to hold target Timestamp Low value
+ * \return returns 0 for Success or else Failure
+ */
+void synopGMAC_TS_read_target_timestamp(synopGMACdevice *gmacdev, u32 *sec_val, u32 *sub_sec_val)
+{
+ * sec_val = synopGMACReadReg(gmacdev->MacBase, GmacTSTargetTimeHigh);
+ * sub_sec_val = synopGMACReadReg(gmacdev->MacBase, GmacTSTargetTimeLow);
+ return;
+}
+#endif
diff --git a/bsp/ls2kdev/drivers/net/synopGMAC_Dev.h b/bsp/ls2kdev/drivers/net/synopGMAC_Dev.h
new file mode 100644
index 0000000000..f47046d5ba
--- /dev/null
+++ b/bsp/ls2kdev/drivers/net/synopGMAC_Dev.h
@@ -0,0 +1,1717 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2017-08-24 chinesebear first version
+ * 2020-08-10 lizhirui porting to ls2k
+ */
+
+#define UNUSED 1
+
+#ifndef SYNOP_GMAC_DEV_H
+#define SYNOP_GMAC_DEV_H 1
+
+/*******************************************************************/
+#define SYNOP_LOOPBACK_MODE (0)
+#define SYNOP_LOOPBACK_DEBUG (0)
+#define SYNOP_PHY_LOOPBACK (0)
+
+#define SYNOP_TX_TEST (0)
+#define SYNOP_RX_TEST (0)
+
+#define SYNOP_TOP_DEBUG (0)
+#define SYNOP_REG_DEBUG (0)
+#define SYNOP_RX_DEBUG (0)
+#define SYNOP_TX_DEBUG (0)
+
+#define ENH_DESC
+/*******************************************************************/
+
+#include "synopGMAC_plat.h"
+#include "synopGMAC_types.h"
+
+//sw: typedef are included in synopGMAC_plat.h
+// it is strange that we should add it here again!!
+
+/*SynopGMAC can support up to 32 phys*/
+#define GMAC_PHY_BASE 1
+#ifdef GMAC_PHY_BASE
+#define DEFAULT_PHY_BASE GMAC_PHY_BASE
+#else
+#define DEFAULT_PHY_BASE PHY16 //We use First Phy
+#endif
+#define MACBASE 0x0000 // The Mac Base address offset is 0x0000
+#define DMABASE 0x1000 // Dma base address starts with an offset 0x1000
+
+
+enum GMACPhyBase
+{
+ PHY0 = 0, //The device can support 32 phys, but we use first phy only
+ PHY1 = 1,
+ PHY16 = 16,
+ PHY31 = 31,
+};
+
+
+//#define TRANSMIT_DESC_SIZE 256 //Tx Descriptors needed in the Descriptor pool/queue
+//#define RECEIVE_DESC_SIZE 256 //Rx Descriptors needed in the Descriptor pool/queue
+//#define TRANSMIT_DESC_SIZE 13//256 //Tx Descriptors needed in the Descriptor pool/queue
+#define TRANSMIT_DESC_SIZE 36 //48 //Tx Descriptors needed in the Descriptor pool/queue
+#define RECEIVE_DESC_SIZE 36 //96 //Rx Descriptors needed in the Descriptor pool/queue
+
+#define ETHERNET_HEADER 14 //6 byte Dest addr, 6 byte Src addr, 2 byte length/type
+#define ETHERNET_CRC 4 //Ethernet CRC
+#define ETHERNET_EXTRA 2 //Only God knows about this?????
+#define ETHERNET_PACKET_COPY 250 // Maximum length when received data is copied on to a new skb
+#define ETHERNET_PACKET_EXTRA 18 // Preallocated length for the rx packets is MTU + ETHERNET_PACKET_EXTRA
+#define VLAN_TAG 4 //optional 802.1q VLAN Tag
+#define MIN_ETHERNET_PAYLOAD 46 //Minimum Ethernet payload size
+#define MAX_ETHERNET_PAYLOAD 1500 //Maximum Ethernet payload size
+#define JUMBO_FRAME_PAYLOAD 9000 //Jumbo frame payload size
+
+#define TX_BUF_SIZE ETHERNET_HEADER + ETHERNET_CRC + MAX_ETHERNET_PAYLOAD + VLAN_TAG + 1000
+#define RX_BUF_SIZE ETHERNET_HEADER + ETHERNET_CRC + MAX_ETHERNET_PAYLOAD + VLAN_TAG + 1000
+
+
+// This is the IP's phy address. This is unique address for every MAC in the universe
+#define DEFAULT_MAC_ADDRESS {0x00, 0x55, 0x7B, 0xB5, 0x7D, 0xF7}
+
+/*
+DMA Descriptor Structure
+The structure is common for both receive and transmit descriptors
+The descriptor is of 4 words, but our structrue contains 6 words where
+last two words are to hold the virtual address of the network buffer pointers
+for driver's use
+From the GMAC core release 3.50a onwards, the Enhanced Descriptor structure got changed.
+The descriptor (both transmit and receive) are of 8 words each rather the 4 words of normal
+descriptor structure.
+Whenever IEEE 1588 Timestamping is enabled TX/RX DESC6 provides the lower 32 bits of Timestamp value and
+ TX/RX DESC7 provides the upper 32 bits of Timestamp value
+In addition to this whenever extended status bit is set (RX DESC0 bit 0), RX DESC4 contains the extended status information
+*/
+
+#define MODULO_INTERRUPT 1 // if it is set to 1, interrupt is available for all the descriptors or else interrupt is available only for
+ // descriptor whose index%MODULO_INTERRUPT is zero
+#ifdef ENH_DESC_8W
+typedef struct DmaDescStruct
+{
+ u32 status; /* Status */
+ u32 length; /* Buffer 1 and Buffer 2 length */
+ u32 buffer1; /* Network Buffer 1 pointer (Dma-able) */
+ u32 buffer2; /* Network Buffer 2 pointer or next descriptor pointer (Dma-able)in chain structure */
+ /* This data below is used only by driver */
+ u32 extstatus; /* Extended status of a Rx Descriptor */
+ u32 reserved1; /* Reserved word */
+ u32 timestamplow; /* Lower 32 bits of the 64 bit timestamp value */
+ u32 timestamphigh; /* Higher 32 bits of the 64 bit timestamp value */
+ u64 data1; /* This holds virtual address of buffer1, not used by DMA */
+ u64 data2; /* This holds virtual address of buffer2, not used by DMA */
+} DmaDesc;
+#else
+typedef struct DmaDescStruct
+{
+ u32 status; /* Status */
+ u32 length; /* Buffer 1 and Buffer 2 length */
+ u32 buffer1; /* Network Buffer 1 pointer (Dma-able) */
+ u32 buffer2; /* Network Buffer 2 pointer or next descriptor pointer (Dma-able)in chain structure */
+ /* This data below is used only by driver */
+ u64 data1; /* This holds virtual address of buffer1, not used by DMA */
+ u64 data2; /* This holds virtual address of buffer2, not used by DMA */
+
+ //u32 dummy1; //sw: for addr align
+ //u32 dummy2; //
+
+} DmaDesc;
+#endif
+
+enum DescMode
+{
+ RINGMODE = 0x00000001,
+ CHAINMODE = 0x00000002,
+};
+
+enum BufferMode
+{
+ SINGLEBUF = 0x00000001,
+ DUALBUF = 0x00000002,
+};
+
+/* synopGMAC device data */
+
+typedef struct synopGMACDeviceStruct
+{
+ u64 MacBase; /* base address of MAC registers */
+ u64 DmaBase; /* base address of DMA registers */
+ u64 PhyBase; /* PHY device address on MII interface */
+ u32 Version; /* Gmac Revision version */
+
+ dma_addr_t TxDescDma; /* Dma-able address of first tx descriptor either in ring or chain mode, this is used by the GMAC device*/
+ dma_addr_t RxDescDma; /* Dma-able address of first rx descriptor either in ring or chain mode, this is used by the GMAC device*/
+ DmaDesc *TxDesc; /* start address of TX descriptors ring or chain, this is used by the driver */
+ DmaDesc *RxDesc; /* start address of RX descriptors ring or chain, this is used by the driver */
+
+ u32 BusyTxDesc; /* Number of Tx Descriptors owned by DMA at any given time*/
+ u32 BusyRxDesc; /* Number of Rx Descriptors owned by DMA at any given time*/
+
+ u32 RxDescCount; /* number of rx descriptors in the tx descriptor queue/pool */
+ u32 TxDescCount; /* number of tx descriptors in the rx descriptor queue/pool */
+
+ u32 TxBusy; /* index of the tx descriptor owned by DMA, is obtained by synopGMAC_get_tx_qptr() */
+ u32 TxNext; /* index of the tx descriptor next available with driver, given to DMA by synopGMAC_set_tx_qptr() */
+ u32 RxBusy; /* index of the rx descriptor owned by DMA, obtained by synopGMAC_get_rx_qptr() */
+ u32 RxNext; /* index of the rx descriptor next available with driver, given to DMA by synopGMAC_set_rx_qptr() */
+
+ DmaDesc * TxBusyDesc; /* Tx Descriptor address corresponding to the index TxBusy */
+ DmaDesc * TxNextDesc; /* Tx Descriptor address corresponding to the index TxNext */
+ DmaDesc * RxBusyDesc; /* Rx Descriptor address corresponding to the index TxBusy */
+ DmaDesc * RxNextDesc; /* Rx Descriptor address corresponding to the index RxNext */
+
+ /*Phy related stuff*/
+ u32 ClockDivMdc; /* Clock divider value programmed in the hardware */
+ /* The status of the link */
+ u32 LinkState0; /* Link status as reported by the Marvel Phy */
+ u32 LinkState; /* Link status as reported by the Marvel Phy */
+ u32 DuplexMode; /* Duplex mode of the Phy */
+ u32 Speed; /* Speed of the Phy */
+ u32 LoopBackMode; /* Loopback status of the Phy */
+// void * FirstTxDesc;
+// void * FirstRxDesc;
+// u32 skb_array[RECEIVE_DESC_SIZE];
+} synopGMACdevice;
+
+/* Below is "88E1011/88E1011S Integrated 10/100/1000 Gigabit Ethernet Transceiver"
+ * Register and their layouts. This Phy has been used in the Dot Aster GMAC Phy daughter.
+ * Since the Phy register map is standard, this map hardly changes to a different Ppy
+ */
+enum MiiRegisters
+{
+ PHY_CONTROL_REG = 0x0000, /*Control Register*/
+ PHY_STATUS_REG = 0x0001, /*Status Register */
+ PHY_ID_HI_REG = 0x0002, /*PHY Identifier High Register*/
+ PHY_ID_LOW_REG = 0x0003, /*PHY Identifier High Register*/
+ PHY_AN_ADV_REG = 0x0004, /*Auto-Negotiation Advertisement Register*/
+ PHY_LNK_PART_ABl_REG = 0x0005, /*Link Partner Ability Register (Base Page)*/
+ PHY_AN_EXP_REG = 0x0006, /*Auto-Negotiation Expansion Register*/
+ PHY_AN_NXT_PAGE_TX_REG = 0x0007, /*Next Page Transmit Register*/
+ PHY_LNK_PART_NXT_PAGE_REG = 0x0008, /*Link Partner Next Page Register*/
+ PHY_1000BT_CTRL_REG = 0x0009, /*1000BASE-T Control Register*/
+ PHY_1000BT_STATUS_REG = 0x000a, /*1000BASE-T Status Register*/
+ PHY_SPECIFIC_CTRL_REG = 0x0010, /*Phy specific control register*/
+ PHY_SPECIFIC_STATUS_REG = 0x0011, /*Phy specific status register*/
+ PHY_INTERRUPT_ENABLE_REG = 0x0012, /*Phy interrupt enable register*/
+ PHY_INTERRUPT_STATUS_REG = 0x0013, /*Phy interrupt status register*/
+ PHY_EXT_PHY_SPC_CTRL = 0x0014, /*Extended Phy specific control*/
+ PHY_RX_ERR_COUNTER = 0x0015, /*Receive Error Counter*/
+ PHY_EXT_ADDR_CBL_DIAG = 0x0016, /*Extended address for cable diagnostic register*/
+ PHY_LED_CONTROL = 0x0018, /*LED Control*/
+ PHY_MAN_LED_OVERIDE = 0x0019, /*Manual LED override register*/
+ PHY_EXT_PHY_SPC_CTRL2 = 0x001a, /*Extended Phy specific control 2*/
+ PHY_EXT_PHY_SPC_STATUS = 0x001b, /*Extended Phy specific status*/
+ PHY_CBL_DIAG_REG = 0x001c, /*Cable diagnostic registers*/
+};
+
+/* This is Control register layout. Control register is of 16 bit wide.
+*/
+enum Mii_GEN_CTRL
+{ /* Description bits R/W default value */
+ Mii_reset = 0x8000,
+ Mii_Speed_10 = 0x0000, /* 10 Mbps 6:13 RW */
+ Mii_Speed_100 = 0x2000, /* 100 Mbps 6:13 RW */
+ Mii_Speed_1000 = 0x0040, /* 1000 Mbit/s 6:13 RW */
+
+ Mii_Duplex = 0x0100, /* Full Duplex mode 8 RW */
+
+ Mii_Manual_Master_Config = 0x0800, /* Manual Master Config 11 RW */
+
+ Mii_Loopback = 0x4000, /* Enable Loop back 14 RW */
+ Mii_NoLoopback = 0x0000, /* Enable Loop back 14 RW */
+};
+
+enum Mii_Phy_Status
+{
+ Mii_phy_status_speed_10 = 0x0000,
+ Mii_phy_status_speed_100 = 0x4000,
+ Mii_phy_status_speed_1000 = 0x8000,
+
+ Mii_phy_status_full_duplex = 0x2000,
+ Mii_phy_status_half_duplex = 0x0000,
+
+ Mii_phy_status_link_up = 0x0400, //lyf:rtl 8211 phy
+// Mii_phy_status_link_up = 0x0100, //sw: broadcom BCM5461 PHY
+};
+/* This is Status register layout. Status register is of 16 bit wide.
+*/
+enum Mii_GEN_STATUS
+{
+ Mii_AutoNegCmplt = 0x0020, /* Autonegotiation completed 5 RW */
+ Mii_Link = 0x0004, /* Link status 2 RW */
+};
+
+enum Mii_Link_Status
+{
+ LINKDOWN = 0,
+ LINKUP = 1,
+};
+
+enum Mii_Duplex_Mode
+{
+ HALFDUPLEX = 1,
+ FULLDUPLEX = 2,
+};
+enum Mii_Link_Speed
+{
+ SPEED10 = 1,
+ SPEED100 = 2,
+ SPEED1000 = 3,
+};
+
+enum Mii_Loop_Back
+{
+ NOLOOPBACK = 0,
+ LOOPBACK = 1,
+};
+
+/**********************************************************
+ * GMAC registers Map
+ * For Pci based system address is BARx + GmacRegisterBase
+ * For any other system translation is done accordingly
+ **********************************************************/
+enum GmacRegisters
+{
+ GmacConfig = 0x0000, /* Mac config Register */
+ GmacFrameFilter = 0x0004, /* Mac frame filtering controls */
+ GmacHashHigh = 0x0008, /* Multi-cast hash table high */
+ GmacHashLow = 0x000C, /* Multi-cast hash table low */
+ GmacGmiiAddr = 0x0010, /* GMII address Register(ext. Phy) */
+ GmacGmiiData = 0x0014, /* GMII data Register(ext. Phy) */
+ GmacFlowControl = 0x0018, /* Flow control Register */
+ GmacVlan = 0x001C, /* VLAN tag Register (IEEE 802.1Q) */
+
+ GmacVersion = 0x0020, /* GMAC Core Version Register */
+ GmacWakeupAddr = 0x0028, /* GMAC wake-up frame filter adrress reg */
+ GmacPmtCtrlStatus = 0x002C, /* PMT control and status register */
+
+ GmacInterruptStatus = 0x0038, /* Mac Interrupt ststus register */
+ GmacInterruptMask = 0x003C, /* Mac Interrupt Mask register */
+
+ GmacAddr0High = 0x0040, /* Mac address0 high Register */
+ GmacAddr0Low = 0x0044, /* Mac address0 low Register */
+ GmacAddr1High = 0x0048, /* Mac address1 high Register */
+ GmacAddr1Low = 0x004C, /* Mac address1 low Register */
+ GmacAddr2High = 0x0050, /* Mac address2 high Register */
+ GmacAddr2Low = 0x0054, /* Mac address2 low Register */
+ GmacAddr3High = 0x0058, /* Mac address3 high Register */
+ GmacAddr3Low = 0x005C, /* Mac address3 low Register */
+ GmacAddr4High = 0x0060, /* Mac address4 high Register */
+ GmacAddr4Low = 0x0064, /* Mac address4 low Register */
+ GmacAddr5High = 0x0068, /* Mac address5 high Register */
+ GmacAddr5Low = 0x006C, /* Mac address5 low Register */
+ GmacAddr6High = 0x0070, /* Mac address6 high Register */
+ GmacAddr6Low = 0x0074, /* Mac address6 low Register */
+ GmacAddr7High = 0x0078, /* Mac address7 high Register */
+ GmacAddr7Low = 0x007C, /* Mac address7 low Register */
+ GmacAddr8High = 0x0080, /* Mac address8 high Register */
+ GmacAddr8Low = 0x0084, /* Mac address8 low Register */
+ GmacAddr9High = 0x0088, /* Mac address9 high Register */
+ GmacAddr9Low = 0x008C, /* Mac address9 low Register */
+ GmacAddr10High = 0x0090, /* Mac address10 high Register */
+ GmacAddr10Low = 0x0094, /* Mac address10 low Register */
+ GmacAddr11High = 0x0098, /* Mac address11 high Register */
+ GmacAddr11Low = 0x009C, /* Mac address11 low Register */
+ GmacAddr12High = 0x00A0, /* Mac address12 high Register */
+ GmacAddr12Low = 0x00A4, /* Mac address12 low Register */
+ GmacAddr13High = 0x00A8, /* Mac address13 high Register */
+ GmacAddr13Low = 0x00AC, /* Mac address13 low Register */
+ GmacAddr14High = 0x00B0, /* Mac address14 high Register */
+ GmacAddr14Low = 0x00B4, /* Mac address14 low Register */
+ GmacAddr15High = 0x00B8, /* Mac address15 high Register */
+ GmacAddr15Low = 0x00BC, /* Mac address15 low Register */
+ GmacStatus = 0x00d8, /* MAC status */
+
+ /*Time Stamp Register Map*/
+ GmacTSControl = 0x0700, /* Controls the Timestamp update logic : only when IEEE 1588 time stamping is enabled in corekit */
+
+ GmacTSSubSecIncr = 0x0704, /* 8 bit value by which sub second register is incremented : only when IEEE 1588 time stamping without external timestamp input */
+
+ GmacTSHigh = 0x0708, /* 32 bit seconds(MS) : only when IEEE 1588 time stamping without external timestamp input */
+ GmacTSLow = 0x070C, /* 32 bit nano seconds(MS) : only when IEEE 1588 time stamping without external timestamp input */
+
+ GmacTSHighUpdate = 0x0710, /* 32 bit seconds(MS) to be written/added/subtracted : only when IEEE 1588 time stamping without external timestamp input */
+ GmacTSLowUpdate = 0x0714, /* 32 bit nano seconds(MS) to be writeen/added/subtracted : only when IEEE 1588 time stamping without external timestamp input */
+
+ GmacTSAddend = 0x0718, /* Used by Software to readjust the clock frequency linearly : only when IEEE 1588 time stamping without external timestamp input */
+
+ GmacTSTargetTimeHigh = 0x071C, /* 32 bit seconds(MS) to be compared with system time : only when IEEE 1588 time stamping without external timestamp input */
+ GmacTSTargetTimeLow = 0x0720, /* 32 bit nano seconds(MS) to be compared with system time : only when IEEE 1588 time stamping without external timestamp input */
+
+ GmacTSHighWord = 0x0724, /* Time Stamp Higher Word Register (Version 2 only); only lower 16 bits are valid */
+//GmacTSHighWordUpdate = 0x072C, /* Time Stamp Higher Word Update Register (Version 2 only); only lower 16 bits are valid */
+
+ GmacTSStatus = 0x0728, /* Time Stamp Status Register */
+};
+
+/**********************************************************
+ * GMAC Network interface registers
+ * This explains the Register's Layout
+
+ * FES is Read only by default and is enabled only when Tx
+ * Config Parameter is enabled for RGMII/SGMII interface
+ * during CoreKit Config.
+
+ * DM is Read only with value 1'b1 in Full duplex only Config
+ **********************************************************/
+
+/* GmacConfig = 0x0000, Mac config Register Layout */
+enum GmacConfigReg
+{
+ /* Bit description Bits R/W Reset value */
+ GmacWatchdog = 0x00800000,
+ GmacWatchdogDisable = 0x00800000, /* (WD)Disable watchdog timer on Rx 23 RW */
+ GmacWatchdogEnable = 0x00000000, /* Enable watchdog timer 0 */
+
+ GmacJabber = 0x00400000,
+ GmacJabberDisable = 0x00400000, /* (JD)Disable jabber timer on Tx 22 RW */
+ GmacJabberEnable = 0x00000000, /* Enable jabber timer 0 */
+
+ GmacFrameBurst = 0x00200000,
+ GmacFrameBurstEnable = 0x00200000, /* (BE)Enable frame bursting during Tx 21 RW */
+ GmacFrameBurstDisable = 0x00000000, /* Disable frame bursting 0 */
+
+ GmacJumboFrame = 0x00100000,
+ GmacJumboFrameEnable = 0x00100000, /* (JE)Enable jumbo frame for Tx 20 RW */
+ GmacJumboFrameDisable = 0x00000000, /* Disable jumbo frame 0 */
+
+ GmacInterFrameGap7 = 0x000E0000, /* (IFG) Config7 - 40 bit times 19:17 RW */
+ GmacInterFrameGap6 = 0x000C0000, /* (IFG) Config6 - 48 bit times */
+ GmacInterFrameGap5 = 0x000A0000, /* (IFG) Config5 - 56 bit times */
+ GmacInterFrameGap4 = 0x00080000, /* (IFG) Config4 - 64 bit times */
+ GmacInterFrameGap3 = 0x00040000, /* (IFG) Config3 - 72 bit times */
+ GmacInterFrameGap2 = 0x00020000, /* (IFG) Config2 - 80 bit times */
+ GmacInterFrameGap1 = 0x00010000, /* (IFG) Config1 - 88 bit times */
+ GmacInterFrameGap0 = 0x00000000, /* (IFG) Config0 - 96 bit times 000 */
+
+ GmacDisableCrs = 0x00010000,
+ GmacMiiGmii = 0x00008000,
+ GmacSelectMii = 0x00008000, /* (PS)Port Select-MII mode 15 RW */
+ GmacSelectGmii = 0x00000000, /* GMII mode 0 */
+
+ GmacFESpeed100 = 0x00004000, /*(FES)Fast Ethernet speed 100Mbps 14 RW */
+ GmacFESpeed10 = 0x00000000, /* 10Mbps 0 */
+
+ GmacRxOwn = 0x00002000,
+ GmacDisableRxOwn = 0x00002000, /* (DO)Disable receive own packets 13 RW */
+ GmacEnableRxOwn = 0x00000000, /* Enable receive own packets 0 */
+
+ GmacLoopback = 0x00001000,
+ GmacLoopbackOn = 0x00001000, /* (LM)Loopback mode for GMII/MII 12 RW */
+ GmacLoopbackOff = 0x00000000, /* Normal mode 0 */
+
+ GmacDuplex = 0x00000800,
+ GmacFullDuplex = 0x00000800, /* (DM)Full duplex mode 11 RW */
+ GmacHalfDuplex = 0x00000000, /* Half duplex mode 0 */
+
+ GmacRxIpcOffload = 0x00000400, /* IPC checksum offload 10 RW 0 */
+
+ GmacRetry = 0x00000200,
+ GmacRetryDisable = 0x00000200, /* (DR)Disable Retry 9 RW */
+ GmacRetryEnable = 0x00000000, /* Enable retransmission as per BL 0 */
+
+ GmacLinkUp = 0x00000100, /* (LUD)Link UP 8 RW */
+ GmacLinkDown = 0x00000100, /* Link Down 0 */
+
+ GmacPadCrcStrip = 0x00000080,
+ GmacPadCrcStripEnable = 0x00000080, /* (ACS) Automatic Pad/Crc strip enable 7 RW */
+ GmacPadCrcStripDisable = 0x00000000, /* Automatic Pad/Crc stripping disable 0 */
+
+ GmacBackoffLimit = 0x00000060,
+ GmacBackoffLimit3 = 0x00000060, /* (BL)Back-off limit in HD mode 6:5 RW */
+ GmacBackoffLimit2 = 0x00000040, /* */
+ GmacBackoffLimit1 = 0x00000020, /* */
+ GmacBackoffLimit0 = 0x00000000, /* 00 */
+
+ GmacDeferralCheck = 0x00000010,
+ GmacDeferralCheckEnable = 0x00000010, /* (DC)Deferral check enable in HD mode 4 RW */
+ GmacDeferralCheckDisable = 0x00000000, /* Deferral check disable 0 */
+
+ GmacTx = 0x00000008,
+ GmacTxEnable = 0x00000008, /* (TE)Transmitter enable 3 RW */
+ GmacTxDisable = 0x00000000, /* Transmitter disable 0 */
+
+ GmacRx = 0x00000004,
+ GmacRxEnable = 0x00000004, /* (RE)Receiver enable 2 RW */
+ GmacRxDisable = 0x00000000, /* Receiver disable 0 */
+};
+
+/* GmacFrameFilter = 0x0004, Mac frame filtering controls Register Layout*/
+enum GmacFrameFilterReg
+{
+ GmacFilter = 0x80000000,
+ GmacFilterOff = 0x80000000, /* (RA)Receive all incoming packets 31 RW */
+ GmacFilterOn = 0x00000000, /* Receive filtered packets only 0 */
+
+ GmacHashPerfectFilter = 0x00000400, /*Hash or Perfect Filter enable 10 RW 0 */
+
+ GmacSrcAddrFilter = 0x00000200,
+ GmacSrcAddrFilterEnable = 0x00000200, /* (SAF)Source Address Filter enable 9 RW */
+ GmacSrcAddrFilterDisable = 0x00000000, /* 0 */
+
+ GmacSrcInvaAddrFilter = 0x00000100,
+ GmacSrcInvAddrFilterEn = 0x00000100, /* (SAIF)Inv Src Addr Filter enable 8 RW */
+ GmacSrcInvAddrFilterDis = 0x00000000, /* 0 */
+
+ GmacPassControl = 0x000000C0,
+ GmacPassControl3 = 0x000000C0, /* (PCS)Forwards ctrl frms that pass AF 7:6 RW */
+ GmacPassControl2 = 0x00000080, /* Forwards all control frames */
+ GmacPassControl1 = 0x00000040, /* Does not pass control frames */
+ GmacPassControl0 = 0x00000000, /* Does not pass control frames 00 */
+
+ GmacBroadcast = 0x00000020,
+ GmacBroadcastDisable = 0x00000020, /* (DBF)Disable Rx of broadcast frames 5 RW */
+ GmacBroadcastEnable = 0x00000000, /* Enable broadcast frames 0 */
+
+ GmacMulticastFilter = 0x00000010,
+ GmacMulticastFilterOff = 0x00000010, /* (PM) Pass all multicast packets 4 RW */
+ GmacMulticastFilterOn = 0x00000000, /* Pass filtered multicast packets 0 */
+
+ GmacDestAddrFilter = 0x00000008,
+ GmacDestAddrFilterInv = 0x00000008, /* (DAIF)Inverse filtering for DA 3 RW */
+ GmacDestAddrFilterNor = 0x00000000, /* Normal filtering for DA 0 */
+
+ GmacMcastHashFilter = 0x00000004,
+ GmacMcastHashFilterOn = 0x00000004, /* (HMC)perfom multicast hash filtering 2 RW */
+ GmacMcastHashFilterOff = 0x00000000, /* perfect filtering only 0 */
+
+ GmacUcastHashFilter = 0x00000002,
+ GmacUcastHashFilterOn = 0x00000002, /* (HUC)Unicast Hash filtering only 1 RW */
+ GmacUcastHashFilterOff = 0x00000000, /* perfect filtering only 0 */
+
+ GmacPromiscuousMode = 0x00000001,
+ GmacPromiscuousModeOn = 0x00000001, /* Receive all frames 0 RW */
+ GmacPromiscuousModeOff = 0x00000000, /* Receive filtered packets only 0 */
+};
+
+/*GmacGmiiAddr = 0x0010, GMII address Register(ext. Phy) Layout */
+enum GmacGmiiAddrReg
+{
+ GmiiDevMask = 0x0000F800, /* (PA)GMII device address 15:11 RW 0x00 */
+ GmiiDevShift = 11,
+
+ GmiiRegMask = 0x000007C0, /* (GR)GMII register in selected Phy 10:6 RW 0x00 */
+ GmiiRegShift = 6,
+
+ GmiiCsrClkMask = 0x0000001C, /* CSR Clock bit Mask 4:2 */
+ GmiiCsrClk5 = 0x00000014, /* (CR)CSR Clock Range 250-300 MHz 4:2 RW 000 */
+ GmiiCsrClk4 = 0x00000010, /* 150-250 MHz */
+ GmiiCsrClk3 = 0x0000000C, /* 35-60 MHz */
+ GmiiCsrClk2 = 0x00000008, /* 20-35 MHz */
+ GmiiCsrClk1 = 0x00000004, /* 100-150 MHz */
+ GmiiCsrClk0 = 0x00000000, /* 60-100 MHz */
+
+ GmiiWrite = 0x00000002, /* (GW)Write to register 1 RW */
+ GmiiRead = 0x00000000, /* Read from register 0 */
+
+ GmiiBusy = 0x00000001, /* (GB)GMII interface is busy 0 RW 0 */
+};
+
+/* GmacGmiiData = 0x0014, GMII data Register(ext. Phy) Layout */
+enum GmacGmiiDataReg
+{
+ GmiiDataMask = 0x0000FFFF, /* (GD)GMII Data 15:0 RW 0x0000 */
+};
+
+/*GmacFlowControl = 0x0018, Flow control Register Layout */
+enum GmacFlowControlReg
+{
+ GmacPauseTimeMask = 0xFFFF0000, /* (PT) PAUSE TIME field in the control frame 31:16 RW 0x0000 */
+ GmacPauseTimeShift = 16,
+
+ GmacPauseLowThresh = 0x00000030,
+ GmacPauseLowThresh3 = 0x00000030, /* (PLT)thresh for pause tmr 256 slot time 5:4 RW */
+ GmacPauseLowThresh2 = 0x00000020, /* 144 slot time */
+ GmacPauseLowThresh1 = 0x00000010, /* 28 slot time */
+ GmacPauseLowThresh0 = 0x00000000, /* 4 slot time 000 */
+
+ GmacUnicastPauseFrame = 0x00000008,
+ GmacUnicastPauseFrameOn = 0x00000008, /* (UP)Detect pause frame with unicast addr. 3 RW */
+ GmacUnicastPauseFrameOff = 0x00000000, /* Detect only pause frame with multicast addr. 0 */
+
+ GmacRxFlowControl = 0x00000004,
+ GmacRxFlowControlEnable = 0x00000004, /* (RFE)Enable Rx flow control 2 RW */
+ GmacRxFlowControlDisable = 0x00000000, /* Disable Rx flow control 0 */
+
+ GmacTxFlowControl = 0x00000002,
+ GmacTxFlowControlEnable = 0x00000002, /* (TFE)Enable Tx flow control 1 RW */
+ GmacTxFlowControlDisable = 0x00000000, /* Disable flow control 0 */
+
+ GmacFlowControlBackPressure= 0x00000001,
+ GmacSendPauseFrame = 0x00000001, /* (FCB/PBA)send pause frm/Apply back pressure 0 RW 0 */
+};
+
+/* GmacInterruptStatus = 0x0038, Mac Interrupt ststus register */
+enum GmacInterruptStatusBitDefinition
+{
+ GmacTSIntSts = 0x00000200, /* set if int generated due to TS (Read Time Stamp Status Register to know details)*/
+ GmacMmcRxChksumOffload = 0x00000080, /* set if int generated in MMC RX CHECKSUM OFFLOAD int register */
+ GmacMmcTxIntSts = 0x00000040, /* set if int generated in MMC TX Int register */
+ GmacMmcRxIntSts = 0x00000020, /* set if int generated in MMC RX Int register */
+ GmacMmcIntSts = 0x00000010, /* set if any of the above bit [7:5] is set */
+ GmacPmtIntSts = 0x00000008, /* set whenver magic pkt/wake-on-lan frame is received */
+ GmacPcsAnComplete = 0x00000004, /* set when AN is complete in TBI/RTBI/SGMIII phy interface */
+ GmacPcsLnkStsChange = 0x00000002, /* set if any lnk status change in TBI/RTBI/SGMII interface */
+ GmacRgmiiIntSts = 0x00000001, /* set if any change in lnk status of RGMII interface */
+};
+
+/* GmacInterruptMask = 0x003C, Mac Interrupt Mask register */
+enum GmacInterruptMaskBitDefinition
+{
+ GmacTSIntMask = 0x00000200, /* when set disables the time stamp interrupt generation */
+ GmacPmtIntMask = 0x00000008, /* when set Disables the assertion of PMT interrupt */
+ GmacPcsAnIntMask = 0x00000004, /* When set disables the assertion of PCS AN complete interrupt */
+ GmacPcsLnkStsIntMask = 0x00000002, /* when set disables the assertion of PCS lnk status change interrupt */
+ GmacRgmiiIntMask = 0x00000001, /* when set disables the assertion of RGMII int */
+};
+
+/**********************************************************
+ * GMAC DMA registers
+ * For Pci based system address is BARx + GmaDmaBase
+ * For any other system translation is done accordingly
+ **********************************************************/
+enum DmaRegisters
+{
+ DmaBusMode = 0x0000, /* CSR0 - Bus Mode Register */
+ DmaTxPollDemand = 0x0004, /* CSR1 - Transmit Poll Demand Register */
+ DmaRxPollDemand = 0x0008, /* CSR2 - Receive Poll Demand Register */
+ DmaRxBaseAddr = 0x000C, /* CSR3 - Receive Descriptor list base address */
+ DmaTxBaseAddr = 0x0010, /* CSR4 - Transmit Descriptor list base address */
+ DmaStatus = 0x0014, /* CSR5 - Dma status Register */
+ DmaControl = 0x0018, /* CSR6 - Dma Operation Mode Register */
+ DmaInterrupt = 0x001C, /* CSR7 - Interrupt enable */
+ DmaMissedFr = 0x0020, /* CSR8 - Missed Frame & Buffer overflow Counter */
+ DmaTxCurrDesc = 0x0048, /* - Current host Tx Desc Register */
+ DmaRxCurrDesc = 0x004C, /* - Current host Rx Desc Register */
+ DmaTxCurrAddr = 0x0050, /* CSR20 - Current host transmit buffer address */
+ DmaRxCurrAddr = 0x0054, /* CSR21 - Current host receive buffer address */
+};
+
+/**********************************************************
+ * DMA Engine registers Layout
+ **********************************************************/
+
+/*DmaBusMode = 0x0000, CSR0 - Bus Mode */
+enum DmaBusModeReg
+{ /* Bit description Bits R/W Reset value */
+ DmaFixedBurstEnable = 0x00010000, /* (FB)Fixed Burst SINGLE, INCR4, INCR8 or INCR16 16 RW */
+ DmaFixedBurstDisable = 0x00000000, /* SINGLE, INCR 0 */
+
+ DmaTxPriorityRatio11 = 0x00000000, /* (PR)TX:RX DMA priority ratio 1:1 15:14 RW 00 */
+ DmaTxPriorityRatio21 = 0x00004000, /* (PR)TX:RX DMA priority ratio 2:1 */
+ DmaTxPriorityRatio31 = 0x00008000, /* (PR)TX:RX DMA priority ratio 3:1 */
+ DmaTxPriorityRatio41 = 0x0000C000, /* (PR)TX:RX DMA priority ratio 4:1 */
+
+ DmaBurstLengthx8 = 0x01000000, /* When set mutiplies the PBL by 8 24 RW 0 */
+
+ DmaBurstLength256 = 0x01002000, /*(DmaBurstLengthx8 | DmaBurstLength32) = 256 [24]:13:8 */
+ DmaBurstLength128 = 0x01001000, /*(DmaBurstLengthx8 | DmaBurstLength16) = 128 [24]:13:8 */
+ DmaBurstLength64 = 0x01000800, /*(DmaBurstLengthx8 | DmaBurstLength8) = 64 [24]:13:8 */
+ DmaBurstLength32 = 0x00002000, /* (PBL) programmable Dma burst length = 32 13:8 RW */
+ DmaBurstLength16 = 0x00001000, /* Dma burst length = 16 */
+ DmaBurstLength8 = 0x00000800, /* Dma burst length = 8 */
+ DmaBurstLength4 = 0x00000400, /* Dma burst length = 4 */
+ DmaBurstLength2 = 0x00000200, /* Dma burst length = 2 */
+ DmaBurstLength1 = 0x00000100, /* Dma burst length = 1 */
+ DmaBurstLength0 = 0x00000000, /* Dma burst length = 0 0x00 */
+
+ DmaDescriptor8Words = 0x00000080, /* Enh Descriptor works 1=> 8 word descriptor 7 0 */
+ DmaDescriptor4Words = 0x00000000, /* Enh Descriptor works 0=> 4 word descriptor 7 0 */
+
+ DmaDescriptorSkip16 = 0x00000040, /* (DSL)Descriptor skip length (no.of dwords) 6:2 RW */
+ DmaDescriptorSkip8 = 0x00000020, /* between two unchained descriptors */
+ DmaDescriptorSkip4 = 0x00000010, /* */
+ DmaDescriptorSkip2 = 0x00000008, /* */
+ DmaDescriptorSkip1 = 0x00000004, /* */
+ DmaDescriptorSkip0 = 0x00000000, /* 0x00 */
+
+ DmaArbitRr = 0x00000000, /* (DA) DMA RR arbitration 1 RW 0 */
+ DmaArbitPr = 0x00000002, /* Rx has priority over Tx */
+
+ DmaResetOn = 0x00000001, /* (SWR)Software Reset DMA engine 0 RW */
+ DmaResetOff = 0x00000000, /* 0 */
+};
+
+/*DmaStatus = 0x0014, CSR5 - Dma status Register */
+enum DmaStatusReg
+{
+ /*Bit 28 27 and 26 indicate whether the interrupt due to PMT GMACMMC or GMAC LINE Remaining bits are DMA interrupts*/
+ GmacPmtIntr = 0x10000000, /* (GPI)Gmac subsystem interrupt 28 RO 0 */
+ GmacMmcIntr = 0x08000000, /* (GMI)Gmac MMC subsystem interrupt 27 RO 0 */
+ GmacLineIntfIntr = 0x04000000, /* Line interface interrupt 26 RO 0 */
+
+ DmaErrorBit2 = 0x02000000, /* (EB)Error bits 0-data buffer, 1-desc. access 25 RO 0 */
+ DmaErrorBit1 = 0x01000000, /* (EB)Error bits 0-write trnsf, 1-read transfr 24 RO 0 */
+ DmaErrorBit0 = 0x00800000, /* (EB)Error bits 0-Rx DMA, 1-Tx DMA 23 RO 0 */
+
+ DmaTxState = 0x00700000, /* (TS)Transmit process state 22:20 RO */
+ DmaTxStopped = 0x00000000, /* Stopped - Reset or Stop Tx Command issued 000 */
+ DmaTxFetching = 0x00100000, /* Running - fetching the Tx descriptor */
+ DmaTxWaiting = 0x00200000, /* Running - waiting for status */
+ DmaTxReading = 0x00300000, /* Running - reading the data from host memory */
+ DmaTxSuspended = 0x00600000, /* Suspended - Tx Descriptor unavailabe */
+ DmaTxClosing = 0x00700000, /* Running - closing Rx descriptor */
+
+ DmaRxState = 0x000E0000, /* (RS)Receive process state 19:17 RO */
+ DmaRxStopped = 0x00000000, /* Stopped - Reset or Stop Rx Command issued 000 */
+ DmaRxFetching = 0x00020000, /* Running - fetching the Rx descriptor */
+ DmaRxWaiting = 0x00060000, /* Running - waiting for packet */
+ DmaRxSuspended = 0x00080000, /* Suspended - Rx Descriptor unavailable */
+ DmaRxClosing = 0x000A0000, /* Running - closing descriptor */
+ DmaRxQueuing = 0x000E0000, /* Running - queuing the recieve frame into host memory */
+
+ DmaIntNormal = 0x00010000, /* (NIS)Normal interrupt summary 16 RW 0 */
+ DmaIntAbnormal = 0x00008000, /* (AIS)Abnormal interrupt summary 15 RW 0 */
+
+ DmaIntEarlyRx = 0x00004000, /* Early receive interrupt (Normal) RW 0 */
+ DmaIntBusError = 0x00002000, /* Fatal bus error (Abnormal) RW 0 */
+ DmaIntEarlyTx = 0x00000400, /* Early transmit interrupt (Abnormal) RW 0 */
+ DmaIntRxWdogTO = 0x00000200, /* Receive Watchdog Timeout (Abnormal) RW 0 */
+ DmaIntRxStopped = 0x00000100, /* Receive process stopped (Abnormal) RW 0 */
+ DmaIntRxNoBuffer = 0x00000080, /* Receive buffer unavailable (Abnormal) RW 0 */
+ DmaIntRxCompleted = 0x00000040, /* Completion of frame reception (Normal) RW 0 */
+ DmaIntTxUnderflow = 0x00000020, /* Transmit underflow (Abnormal) RW 0 */
+ DmaIntRcvOverflow = 0x00000010, /* Receive Buffer overflow interrupt RW 0 */
+ DmaIntTxJabberTO = 0x00000008, /* Transmit Jabber Timeout (Abnormal) RW 0 */
+ DmaIntTxNoBuffer = 0x00000004, /* Transmit buffer unavailable (Normal) RW 0 */
+ DmaIntTxStopped = 0x00000002, /* Transmit process stopped (Abnormal) RW 0 */
+ DmaIntTxCompleted = 0x00000001, /* Transmit completed (Normal) RW 0 */
+};
+
+/*DmaControl = 0x0018, CSR6 - Dma Operation Mode Register */
+enum DmaControlReg
+{
+ DmaDisableDropTcpCs = 0x04000000, /* (DT) Dis. drop. of tcp/ip CS error frames 26 RW 0 */
+
+ DmaStoreAndForward = 0x02200000, /* (SF)Store and forward 21 RW 0 */
+ DmaFlushTxFifo = 0x00100000, /* (FTF)Tx FIFO controller is reset to default 20 RW 0 */
+
+ DmaTxThreshCtrl = 0x0001C000, /* (TTC)Controls thre Threh of MTL tx Fifo 16:14 RW */
+ DmaTxThreshCtrl16 = 0x0001C000, /* (TTC)Controls thre Threh of MTL tx Fifo 16 16:14 RW */
+ DmaTxThreshCtrl24 = 0x00018000, /* (TTC)Controls thre Threh of MTL tx Fifo 24 16:14 RW */
+ DmaTxThreshCtrl32 = 0x00014000, /* (TTC)Controls thre Threh of MTL tx Fifo 32 16:14 RW */
+ DmaTxThreshCtrl40 = 0x00010000, /* (TTC)Controls thre Threh of MTL tx Fifo 40 16:14 RW */
+ DmaTxThreshCtrl256 = 0x0000c000, /* (TTC)Controls thre Threh of MTL tx Fifo 256 16:14 RW */
+ DmaTxThreshCtrl192 = 0x00008000, /* (TTC)Controls thre Threh of MTL tx Fifo 192 16:14 RW */
+ DmaTxThreshCtrl128 = 0x00004000, /* (TTC)Controls thre Threh of MTL tx Fifo 128 16:14 RW */
+ DmaTxThreshCtrl64 = 0x00000000, /* (TTC)Controls thre Threh of MTL tx Fifo 64 16:14 RW 000 */
+
+ DmaTxStart = 0x00002000, /* (ST)Start/Stop transmission 13 RW 0 */
+
+ DmaRxFlowCtrlDeact = 0x00401800, /* (RFD)Rx flow control deact. threhold [22]:12:11 RW */
+ DmaRxFlowCtrlDeact1K = 0x00000000, /* (RFD)Rx flow control deact. threhold (1kbytes) [22]:12:11 RW 00 */
+ DmaRxFlowCtrlDeact2K = 0x00000800, /* (RFD)Rx flow control deact. threhold (2kbytes) [22]:12:11 RW */
+ DmaRxFlowCtrlDeact3K = 0x00001000, /* (RFD)Rx flow control deact. threhold (3kbytes) [22]:12:11 RW */
+ DmaRxFlowCtrlDeact4K = 0x00001800, /* (RFD)Rx flow control deact. threhold (4kbytes) [22]:12:11 RW */
+ DmaRxFlowCtrlDeact5K = 0x00400000, /* (RFD)Rx flow control deact. threhold (4kbytes) [22]:12:11 RW */
+ DmaRxFlowCtrlDeact6K = 0x00400800, /* (RFD)Rx flow control deact. threhold (4kbytes) [22]:12:11 RW */
+ DmaRxFlowCtrlDeact7K = 0x00401000, /* (RFD)Rx flow control deact. threhold (4kbytes) [22]:12:11 RW */
+
+ DmaRxFlowCtrlAct = 0x00800600, /* (RFA)Rx flow control Act. threhold [23]:10:09 RW */
+ DmaRxFlowCtrlAct1K = 0x00000000, /* (RFA)Rx flow control Act. threhold (1kbytes) [23]:10:09 RW 00 */
+ DmaRxFlowCtrlAct2K = 0x00000200, /* (RFA)Rx flow control Act. threhold (2kbytes) [23]:10:09 RW */
+ DmaRxFlowCtrlAct3K = 0x00000400, /* (RFA)Rx flow control Act. threhold (3kbytes) [23]:10:09 RW */
+ DmaRxFlowCtrlAct4K = 0x00000600, /* (RFA)Rx flow control Act. threhold (4kbytes) [23]:10:09 RW */
+ DmaRxFlowCtrlAct5K = 0x00800000, /* (RFA)Rx flow control Act. threhold (5kbytes) [23]:10:09 RW */
+ DmaRxFlowCtrlAct6K = 0x00800200, /* (RFA)Rx flow control Act. threhold (6kbytes) [23]:10:09 RW */
+ DmaRxFlowCtrlAct7K = 0x00800400, /* (RFA)Rx flow control Act. threhold (7kbytes) [23]:10:09 RW */
+
+ DmaRxThreshCtrl = 0x00000018, /* (RTC)Controls thre Threh of MTL rx Fifo 4:3 RW */
+ DmaRxThreshCtrl64 = 0x00000000, /* (RTC)Controls thre Threh of MTL tx Fifo 64 4:3 RW */
+ DmaRxThreshCtrl32 = 0x00000008, /* (RTC)Controls thre Threh of MTL tx Fifo 32 4:3 RW */
+ DmaRxThreshCtrl96 = 0x00000010, /* (RTC)Controls thre Threh of MTL tx Fifo 96 4:3 RW */
+ DmaRxThreshCtrl128 = 0x00000018, /* (RTC)Controls thre Threh of MTL tx Fifo 128 4:3 RW */
+
+ DmaEnHwFlowCtrl = 0x00000100, /* (EFC)Enable HW flow control 8 RW */
+ DmaDisHwFlowCtrl = 0x00000000, /* Disable HW flow control 0 */
+
+ DmaFwdErrorFrames = 0x00000080, /* (FEF)Forward error frames 7 RW 0 */
+ DmaFwdUnderSzFrames = 0x00000040, /* (FUF)Forward undersize frames 6 RW 0 */
+ DmaTxSecondFrame = 0x00000004, /* (OSF)Operate on second frame 4 RW 0 */
+ DmaRxStart = 0x00000002, /* (SR)Start/Stop reception 1 RW 0 */
+};
+
+
+/*DmaInterrupt = 0x001C, CSR7 - Interrupt enable Register Layout */
+enum DmaInterruptReg
+{
+ DmaIeNormal = DmaIntNormal , /* Normal interrupt enable RW 0 */
+ DmaIeAbnormal = DmaIntAbnormal , /* Abnormal interrupt enable RW 0 */
+
+ DmaIeEarlyRx = DmaIntEarlyRx , /* Early receive interrupt enable RW 0 */
+ DmaIeBusError = DmaIntBusError , /* Fatal bus error enable RW 0 */
+ DmaIeEarlyTx = DmaIntEarlyTx , /* Early transmit interrupt enable RW 0 */
+ DmaIeRxWdogTO = DmaIntRxWdogTO , /* Receive Watchdog Timeout enable RW 0 */
+ DmaIeRxStopped = DmaIntRxStopped , /* Receive process stopped enable RW 0 */
+ DmaIeRxNoBuffer = DmaIntRxNoBuffer , /* Receive buffer unavailable enable RW 0 */
+ DmaIeRxCompleted = DmaIntRxCompleted, /* Completion of frame reception enable RW 0 */
+ DmaIeTxUnderflow = DmaIntTxUnderflow, /* Transmit underflow enable RW 0 */
+
+ DmaIeRxOverflow = DmaIntRcvOverflow, /* Receive Buffer overflow interrupt RW 0 */
+ DmaIeTxJabberTO = DmaIntTxJabberTO , /* Transmit Jabber Timeout enable RW 0 */
+ DmaIeTxNoBuffer = DmaIntTxNoBuffer , /* Transmit buffer unavailable enable RW 0 */
+ DmaIeTxStopped = DmaIntTxStopped , /* Transmit process stopped enable RW 0 */
+ DmaIeTxCompleted = DmaIntTxCompleted, /* Transmit completed enable RW 0 */
+};
+
+
+
+/**********************************************************
+ * DMA Engine descriptors
+ **********************************************************/
+#ifdef ENH_DESC
+/*
+**********Enhanced Descritpor structure to support 8K buffer per buffer ****************************
+
+DmaRxBaseAddr = 0x000C, CSR3 - Receive Descriptor list base address
+DmaRxBaseAddr is the pointer to the first Rx Descriptors. the Descriptor format in Little endian with a
+32 bit Data bus is as shown below
+
+Similarly
+DmaTxBaseAddr = 0x0010, CSR4 - Transmit Descriptor list base address
+DmaTxBaseAddr is the pointer to the first Rx Descriptors. the Descriptor format in Little endian with a
+32 bit Data bus is as shown below
+ --------------------------------------------------------------------------
+ RDES0 |OWN (31)| Status |
+ --------------------------------------------------------------------------
+ RDES1 | Ctrl | Res | Byte Count Buffer 2 | Ctrl | Res | Byte Count Buffer 1 |
+ --------------------------------------------------------------------------
+ RDES2 | Buffer 1 Address |
+ --------------------------------------------------------------------------
+ RDES3 | Buffer 2 Address / Next Descriptor Address |
+ --------------------------------------------------------------------------
+
+ --------------------------------------------------------------------------
+ TDES0 |OWN (31)| Ctrl | Res | Ctrl | Res | Status |
+ --------------------------------------------------------------------------
+ TDES1 | Res | Byte Count Buffer 2 | Res | Byte Count Buffer 1 |
+ --------------------------------------------------------------------------
+ TDES2 | Buffer 1 Address |
+ --------------------------------------------------------------------------
+ TDES3 | Buffer 2 Address / Next Descriptor Address |
+ --------------------------------------------------------------------------
+
+*/
+
+enum DmaDescriptorStatus /* status word of DMA descriptor */
+{
+ DescOwnByDma = 0x80000000, /* (OWN)Descriptor is owned by DMA engine 31 RW */
+
+ DescDAFilterFail = 0x40000000, /* (AFM)Rx - DA Filter Fail for the rx frame 30 */
+
+ DescFrameLengthMask = 0x3FFF0000, /* (FL)Receive descriptor frame length 29:16 */
+ DescFrameLengthShift = 16,
+
+ DescError = 0x00008000, /* (ES)Error summary bit - OR of the follo. bits: 15 */
+ /* DE || OE || IPC || LC || RWT || RE || CE */
+ DescRxTruncated = 0x00004000, /* (DE)Rx - no more descriptors for receive frame 14 */
+ DescSAFilterFail = 0x00002000, /* (SAF)Rx - SA Filter Fail for the received frame 13 */
+ DescRxLengthError = 0x00001000, /* (LE)Rx - frm size not matching with len field 12 */
+ DescRxDamaged = 0x00000800, /* (OE)Rx - frm was damaged due to buffer overflow 11 */
+ DescRxVLANTag = 0x00000400, /* (VLAN)Rx - received frame is a VLAN frame 10 */
+ DescRxFirst = 0x00000200, /* (FS)Rx - first descriptor of the frame 9 */
+ DescRxLast = 0x00000100, /* (LS)Rx - last descriptor of the frame 8 */
+ DescRxLongFrame = 0x00000080, /* (Giant Frame)Rx - frame is longer than 1518/1522 7 */
+ DescRxCollision = 0x00000040, /* (LC)Rx - late collision occurred during reception 6 */
+ DescRxFrameEther = 0x00000020, /* (FT)Rx - Frame type - Ethernet, otherwise 802.3 5 */
+ DescRxWatchdog = 0x00000010, /* (RWT)Rx - watchdog timer expired during reception 4 */
+ DescRxMiiError = 0x00000008, /* (RE)Rx - error reported by MII interface 3 */
+ DescRxDribbling = 0x00000004, /* (DE)Rx - frame contains non int multiple of 8 bits 2 */
+ DescRxCrc = 0x00000002, /* (CE)Rx - CRC error 1 */
+// DescRxMacMatch = 0x00000001, /* (RX MAC Address) Rx mac address reg(1 to 15)match 0 */
+
+ DescRxEXTsts = 0x00000001, /* Extended Status Available (RDES4) 0 */
+
+ DescTxIntEnable = 0x40000000, /* (IC)Tx - interrupt on completion 30 */
+ DescTxLast = 0x20000000, /* (LS)Tx - Last segment of the frame 29 */
+ DescTxFirst = 0x10000000, /* (FS)Tx - First segment of the frame 28 */
+ DescTxDisableCrc = 0x08000000, /* (DC)Tx - Add CRC disabled (first segment only) 27 */
+ DescTxDisablePadd = 0x04000000, /* (DP)disable padding, added by - reyaz 26 */
+
+ DescTxCisMask = 0x00c00000, /* Tx checksum offloading control mask 23:22 */
+ DescTxCisBypass = 0x00000000, /* Checksum bypass */
+ DescTxCisIpv4HdrCs = 0x00400000, /* IPv4 header checksum */
+ DescTxCisTcpOnlyCs = 0x00800000, /* TCP/UDP/ICMP checksum. Pseudo header checksum is assumed to be present */
+ DescTxCisTcpPseudoCs = 0x00c00000, /* TCP/UDP/ICMP checksum fully in hardware including pseudo header */
+
+ TxDescEndOfRing = 0x00200000, /* (TER)End of descriptors ring 21 */
+ TxDescChain = 0x00100000, /* (TCH)Second buffer address is chain address 20 */
+
+ DescRxChkBit0 = 0x00000001, /*() Rx - Rx Payload Checksum Error 0 */
+ DescRxChkBit7 = 0x00000080, /* (IPC CS ERROR)Rx - Ipv4 header checksum error 7 */
+ DescRxChkBit5 = 0x00000020, /* (FT)Rx - Frame type - Ethernet, otherwise 802.3 5 */
+
+ DescRxTSavail = 0x00000080, /* Time stamp available 7 */
+ DescRxFrameType = 0x00000020, /* (FT)Rx - Frame type - Ethernet, otherwise 802.3 5 */
+
+ DescTxIpv4ChkError = 0x00010000, /* (IHE) Tx Ip header error 16 */
+ DescTxTimeout = 0x00004000, /* (JT)Tx - Transmit jabber timeout 14 */
+ DescTxFrameFlushed = 0x00002000, /* (FF)Tx - DMA/MTL flushed the frame due to SW flush 13 */
+ DescTxPayChkError = 0x00001000, /* (PCE) Tx Payload checksum Error 12 */
+ DescTxLostCarrier = 0x00000800, /* (LC)Tx - carrier lost during tramsmission 11 */
+ DescTxNoCarrier = 0x00000400, /* (NC)Tx - no carrier signal from the tranceiver 10 */
+ DescTxLateCollision = 0x00000200, /* (LC)Tx - transmission aborted due to collision 9 */
+ DescTxExcCollisions = 0x00000100, /* (EC)Tx - transmission aborted after 16 collisions 8 */
+ DescTxVLANFrame = 0x00000080, /* (VF)Tx - VLAN-type frame 7 */
+
+ DescTxCollMask = 0x00000078, /* (CC)Tx - Collision count 6:3 */
+ DescTxCollShift = 3,
+
+ DescTxExcDeferral = 0x00000004, /* (ED)Tx - excessive deferral 2 */
+ DescTxUnderflow = 0x00000002, /* (UF)Tx - late data arrival from the memory 1 */
+ DescTxDeferred = 0x00000001, /* (DB)Tx - frame transmision deferred 0 */
+ /*
+ This explains the RDES1/TDES1 bits layout
+ --------------------------------------------------------------------
+ RDES1/TDES1 | Control Bits | Byte Count Buffer 2 | Byte Count Buffer 1 |
+ --------------------------------------------------------------------
+ */
+// DmaDescriptorLength length word of DMA descriptor
+ RxDisIntCompl = 0x80000000, /* (Disable Rx int on completion) 31 */
+ RxDescEndOfRing = 0x00008000, /* (TER)End of descriptors ring 15 */
+ RxDescChain = 0x00004000, /* (TCH)Second buffer address is chain address 14 */
+
+ DescSize2Mask = 0x1FFF0000, /* (TBS2) Buffer 2 size 28:16 */
+ DescSize2Shift = 16,
+ DescSize1Mask = 0x00001FFF, /* (TBS1) Buffer 1 size 12:0 */
+ DescSize1Shift = 0,
+ /*
+ This explains the RDES4 Extended Status bits layout
+ --------------------------------------------------------------------
+ RDES4 | Extended Status |
+ --------------------------------------------------------------------
+ */
+ DescRxPtpAvail = 0x00004000, /* PTP snapshot available 14 */
+ DescRxPtpVer = 0x00002000, /* When set indicates IEEE1584 Version 2 (else Ver1) 13 */
+ DescRxPtpFrameType = 0x00001000, /* PTP frame type Indicates PTP sent over ethernet 12 */
+ DescRxPtpMessageType = 0x00000F00, /* Message Type 11:8 */
+ DescRxPtpNo = 0x00000000, /* 0000 => No PTP message received */
+ DescRxPtpSync = 0x00000100, /* 0001 => Sync (all clock types) received */
+ DescRxPtpFollowUp = 0x00000200, /* 0010 => Follow_Up (all clock types) received */
+ DescRxPtpDelayReq = 0x00000300, /* 0011 => Delay_Req (all clock types) received */
+ DescRxPtpDelayResp = 0x00000400, /* 0100 => Delay_Resp (all clock types) received */
+ DescRxPtpPdelayReq = 0x00000500, /* 0101 => Pdelay_Req (in P to P tras clk) or Announce in Ord and Bound clk */
+ DescRxPtpPdelayResp = 0x00000600, /* 0110 => Pdealy_Resp(in P to P trans clk) or Management in Ord and Bound clk */
+ DescRxPtpPdelayRespFP = 0x00000700, /* 0111 => Pdealy_Resp_Follow_Up (in P to P trans clk) or Signaling in Ord and Bound clk */
+ DescRxPtpIPV6 = 0x00000080, /* Received Packet is in IPV6 Packet 7 */
+ DescRxPtpIPV4 = 0x00000040, /* Received Packet is in IPV4 Packet 6 */
+
+ DescRxChkSumBypass = 0x00000020, /* When set indicates checksum offload engine 5
+ is bypassed */
+ DescRxIpPayloadError = 0x00000010, /* When set indicates 16bit IP payload CS is in error 4 */
+ DescRxIpHeaderError = 0x00000008, /* When set indicates 16bit IPV4 header CS is in 3
+ error or IP datagram version is not consistent
+ with Ethernet type value */
+ DescRxIpPayloadType = 0x00000007, /* Indicate the type of payload encapsulated 2:0
+ in IPdatagram processed by COE (Rx) */
+ DescRxIpPayloadUnknown= 0x00000000, /* Unknown or didnot process IP payload */
+ DescRxIpPayloadUDP = 0x00000001, /* UDP */
+ DescRxIpPayloadTCP = 0x00000002, /* TCP */
+ DescRxIpPayloadICMP = 0x00000003, /* ICMP */
+
+};
+
+#else
+/*
+
+********** Default Descritpor structure ****************************
+DmaRxBaseAddr = 0x000C, CSR3 - Receive Descriptor list base address
+DmaRxBaseAddr is the pointer to the first Rx Descriptors. the Descriptor format in Little endian with a
+32 bit Data bus is as shown below
+
+Similarly
+DmaTxBaseAddr = 0x0010, CSR4 - Transmit Descriptor list base address
+DmaTxBaseAddr is the pointer to the first Rx Descriptors. the Descriptor format in Little endian with a
+32 bit Data bus is as shown below
+ --------------------------------------------------------------------
+ RDES0/TDES0 |OWN (31)| Status |
+ --------------------------------------------------------------------
+ RDES1/TDES1 | Control Bits | Byte Count Buffer 2 | Byte Count Buffer 1 |
+ --------------------------------------------------------------------
+ RDES2/TDES2 | Buffer 1 Address |
+ --------------------------------------------------------------------
+ RDES3/TDES3 | Buffer 2 Address / Next Descriptor Address |
+ --------------------------------------------------------------------
+*/
+enum DmaDescriptorStatus /* status word of DMA descriptor */
+{
+ DescOwnByDma = 0x80000000, /* (OWN)Descriptor is owned by DMA engine 31 RW */
+
+ DescDAFilterFail = 0x40000000, /* (AFM)Rx - DA Filter Fail for the rx frame 30 */
+
+ DescFrameLengthMask = 0x3FFF0000, /* (FL)Receive descriptor frame length 29:16 */
+ DescFrameLengthShift = 16,
+
+ DescError = 0x00008000, /* (ES)Error summary bit - OR of the follo. bits: 15 */
+ /* DE || OE || IPC || LC || RWT || RE || CE */
+ DescRxTruncated = 0x00004000, /* (DE)Rx - no more descriptors for receive frame 14 */
+ DescSAFilterFail = 0x00002000, /* (SAF)Rx - SA Filter Fail for the received frame 13 */
+ DescRxLengthError = 0x00001000, /* (LE)Rx - frm size not matching with len field 12 */
+ DescRxDamaged = 0x00000800, /* (OE)Rx - frm was damaged due to buffer overflow 11 */
+ DescRxVLANTag = 0x00000400, /* (VLAN)Rx - received frame is a VLAN frame 10 */
+ DescRxFirst = 0x00000200, /* (FS)Rx - first descriptor of the frame 9 */
+ DescRxLast = 0x00000100, /* (LS)Rx - last descriptor of the frame 8 */
+ DescRxLongFrame = 0x00000080, /* (Giant Frame)Rx - frame is longer than 1518/1522 7 */
+ DescRxCollision = 0x00000040, /* (LC)Rx - late collision occurred during reception 6 */
+ DescRxFrameEther = 0x00000020, /* (FT)Rx - Frame type - Ethernet, otherwise 802.3 5 */
+ DescRxWatchdog = 0x00000010, /* (RWT)Rx - watchdog timer expired during reception 4 */
+ DescRxMiiError = 0x00000008, /* (RE)Rx - error reported by MII interface 3 */
+ DescRxDribbling = 0x00000004, /* (DE)Rx - frame contains non int multiple of 8 bits 2 */
+ DescRxCrc = 0x00000002, /* (CE)Rx - CRC error 1 */
+ DescRxMacMatch = 0x00000001, /* (RX MAC Address) Rx mac address reg(1 to 15)match 0 */
+
+//Rx Descriptor Checksum Offload engine (type 2) encoding
+//DescRxPayChkError = 0x00000001, /* () Rx - Rx Payload Checksum Error 0 */
+//DescRxIpv4ChkError = 0x00000080, /* (IPC CS ERROR)Rx - Ipv4 header checksum error 7 */
+
+ DescRxChkBit0 = 0x00000001, /*() Rx - Rx Payload Checksum Error 0 */
+ DescRxChkBit7 = 0x00000080, /* (IPC CS ERROR)Rx - Ipv4 header checksum error 7 */
+ DescRxChkBit5 = 0x00000020, /* (FT)Rx - Frame type - Ethernet, otherwise 802.3 5 */
+
+ DescTxIpv4ChkError = 0x00010000, /* (IHE) Tx Ip header error 16 */
+ DescTxTimeout = 0x00004000, /* (JT)Tx - Transmit jabber timeout 14 */
+ DescTxFrameFlushed = 0x00002000, /* (FF)Tx - DMA/MTL flushed the frame due to SW flush 13 */
+ DescTxPayChkError = 0x00001000, /* (PCE) Tx Payload checksum Error 12 */
+ DescTxLostCarrier = 0x00000800, /* (LC)Tx - carrier lost during tramsmission 11 */
+ DescTxNoCarrier = 0x00000400, /* (NC)Tx - no carrier signal from the tranceiver 10 */
+ DescTxLateCollision = 0x00000200, /* (LC)Tx - transmission aborted due to collision 9 */
+ DescTxExcCollisions = 0x00000100, /* (EC)Tx - transmission aborted after 16 collisions 8 */
+ DescTxVLANFrame = 0x00000080, /* (VF)Tx - VLAN-type frame 7 */
+
+ DescTxCollMask = 0x00000078, /* (CC)Tx - Collision count 6:3 */
+ DescTxCollShift = 3,
+
+ DescTxExcDeferral = 0x00000004, /* (ED)Tx - excessive deferral 2 */
+ DescTxUnderflow = 0x00000002, /* (UF)Tx - late data arrival from the memory 1 */
+ DescTxDeferred = 0x00000001, /* (DB)Tx - frame transmision deferred 0 */
+
+ /*
+ This explains the RDES1/TDES1 bits layout
+ --------------------------------------------------------------------
+ RDES1/TDES1 | Control Bits | Byte Count Buffer 2 | Byte Count Buffer 1 |
+ --------------------------------------------------------------------
+
+ */
+//DmaDescriptorLength length word of DMA descriptor
+ DescTxIntEnable = 0x80000000, /* (IC)Tx - interrupt on completion 31 */
+ DescTxLast = 0x40000000, /* (LS)Tx - Last segment of the frame 30 */
+ DescTxFirst = 0x20000000, /* (FS)Tx - First segment of the frame 29 */
+ DescTxDisableCrc = 0x04000000, /* (DC)Tx - Add CRC disabled (first segment only) 26 */
+
+ RxDisIntCompl = 0x80000000, /* (Disable Rx int on completion) 31 */
+ RxDescEndOfRing = 0x02000000, /* (TER)End of descriptors ring */
+ RxDescChain = 0x01000000, /* (TCH)Second buffer address is chain address 24 */
+
+ DescTxDisablePadd = 0x00800000, /* (DP)disable padding, added by - reyaz 23 */
+
+ TxDescEndOfRing = 0x02000000, /* (TER)End of descriptors ring */
+ TxDescChain = 0x01000000, /* (TCH)Second buffer address is chain address 24 */
+
+ DescSize2Mask = 0x003FF800, /* (TBS2) Buffer 2 size 21:11 */
+ DescSize2Shift = 11,
+ DescSize1Mask = 0x000007FF, /* (TBS1) Buffer 1 size 10:0 */
+ DescSize1Shift = 0,
+
+ DescTxCisMask = 0x18000000, /* Tx checksum offloading control mask 28:27 */
+ DescTxCisBypass = 0x00000000, /* Checksum bypass */
+ DescTxCisIpv4HdrCs = 0x08000000, /* IPv4 header checksum */
+ DescTxCisTcpOnlyCs = 0x10000000, /* TCP/UDP/ICMP checksum. Pseudo header checksum is assumed to be present */
+ DescTxCisTcpPseudoCs = 0x18000000, /* TCP/UDP/ICMP checksum fully in hardware including pseudo header */
+};
+#endif
+
+// Rx Descriptor COE type2 encoding
+enum RxDescCOEEncode
+{
+ RxLenLT600 = 0, /* Bit(5:7:0)=>0 IEEE 802.3 type frame Length field is Lessthan 0x0600 */
+ RxIpHdrPayLoadChkBypass = 1, /* Bit(5:7:0)=>1 Payload & Ip header checksum bypassed (unsuppported payload) */
+ RxIpHdrPayLoadRes = 2, /* Bit(5:7:0)=>2 Reserved */
+ RxChkBypass = 3, /* Bit(5:7:0)=>3 Neither IPv4 nor IPV6. So checksum bypassed */
+ RxNoChkError = 4, /* Bit(5:7:0)=>4 No IPv4/IPv6 Checksum error detected */
+ RxPayLoadChkError = 5, /* Bit(5:7:0)=>5 Payload checksum error detected for Ipv4/Ipv6 frames */
+ RxIpHdrChkError = 6, /* Bit(5:7:0)=>6 Ip header checksum error detected for Ipv4 frames */
+ RxIpHdrPayLoadChkError = 7, /* Bit(5:7:0)=>7 Payload & Ip header checksum error detected for Ipv4/Ipv6 frames */
+};
+
+/**********************************************************
+ * DMA engine interrupt handling functions
+ **********************************************************/
+
+ enum synopGMACDmaIntEnum /* Intrerrupt types */
+{
+ synopGMACDmaRxNormal = 0x01, /* normal receiver interrupt */
+ synopGMACDmaRxAbnormal = 0x02, /* abnormal receiver interrupt */
+ synopGMACDmaRxStopped = 0x04, /* receiver stopped */
+ synopGMACDmaTxNormal = 0x08, /* normal transmitter interrupt */
+ synopGMACDmaTxAbnormal = 0x10, /* abnormal transmitter interrupt */
+ synopGMACDmaTxStopped = 0x20, /* transmitter stopped */
+ synopGMACDmaError = 0x80, /* Dma engine error */
+};
+
+
+/**********************************************************
+ * Initial register values
+ **********************************************************/
+enum InitialRegisters
+{
+ /* Full-duplex mode with perfect filter on */
+ GmacConfigInitFdx1000 = GmacWatchdogEnable | GmacJabberEnable | GmacFrameBurstEnable | GmacJumboFrameDisable
+ | GmacSelectGmii | GmacEnableRxOwn | GmacLoopbackOff
+ | GmacFullDuplex | GmacRetryEnable | GmacPadCrcStripDisable
+ | GmacBackoffLimit0 | GmacDeferralCheckDisable | GmacTxEnable | GmacRxEnable,
+
+ /* Full-duplex mode with perfect filter on */
+ GmacConfigInitFdx110 = GmacWatchdogEnable | GmacJabberEnable | GmacFrameBurstEnable | GmacJumboFrameDisable
+ | GmacSelectMii | GmacEnableRxOwn | GmacLoopbackOff
+ | GmacFullDuplex | GmacRetryEnable | GmacPadCrcStripDisable
+ | GmacBackoffLimit0 | GmacDeferralCheckDisable | GmacTxEnable | GmacRxEnable,
+
+ /* Full-duplex mode */
+ // CHANGED: Pass control config, dest addr filter normal, added source address filter, multicast & unicast
+ // Hash filter.
+ /* = GmacFilterOff | GmacPassControlOff | GmacBroadcastEnable */
+ GmacFrameFilterInitFdx = GmacFilterOn | GmacPassControl0 | GmacBroadcastEnable | GmacSrcAddrFilterDisable
+ | GmacMulticastFilterOn | GmacDestAddrFilterNor | GmacMcastHashFilterOff
+ | GmacPromiscuousModeOff | GmacUcastHashFilterOff,
+
+ /* Full-duplex mode */
+ GmacFlowControlInitFdx = GmacUnicastPauseFrameOff | GmacRxFlowControlEnable | GmacTxFlowControlEnable,
+
+ /* Full-duplex mode */
+ GmacGmiiAddrInitFdx = GmiiCsrClk2,
+
+
+ /* Half-duplex mode with perfect filter on */
+ // CHANGED: Removed Endian configuration, added single bit config for PAD/CRC strip,
+ /*| GmacSelectMii | GmacLittleEndian | GmacDisableRxOwn | GmacLoopbackOff*/
+ GmacConfigInitHdx1000 = GmacWatchdogEnable | GmacJabberEnable | GmacFrameBurstEnable | GmacJumboFrameDisable
+ | GmacSelectGmii | GmacDisableRxOwn | GmacLoopbackOff
+ | GmacHalfDuplex | GmacRetryEnable | GmacPadCrcStripDisable
+ | GmacBackoffLimit0 | GmacDeferralCheckDisable | GmacTxEnable | GmacRxEnable,
+
+ /* Half-duplex mode with perfect filter on */
+ GmacConfigInitHdx110 = GmacWatchdogEnable | GmacJabberEnable | GmacFrameBurstEnable | GmacJumboFrameDisable
+ | GmacSelectMii | GmacDisableRxOwn | GmacLoopbackOff
+ | GmacHalfDuplex | GmacRetryEnable | GmacPadCrcStripDisable
+ | GmacBackoffLimit0 | GmacDeferralCheckDisable | GmacTxEnable | GmacRxEnable,
+
+ /* Half-duplex mode */
+ GmacFrameFilterInitHdx = GmacFilterOn | GmacPassControl0 | GmacBroadcastEnable | GmacSrcAddrFilterDisable
+ | GmacMulticastFilterOn | GmacDestAddrFilterNor | GmacMcastHashFilterOff
+ | GmacUcastHashFilterOff| GmacPromiscuousModeOff,
+
+ /* Half-duplex mode */
+ GmacFlowControlInitHdx = GmacUnicastPauseFrameOff | GmacRxFlowControlDisable | GmacTxFlowControlDisable,
+
+ /* Half-duplex mode */
+ GmacGmiiAddrInitHdx = GmiiCsrClk2,
+
+ /**********************************************
+ *DMA configurations
+ **********************************************/
+
+ DmaBusModeInit = DmaFixedBurstEnable | DmaBurstLength8 | DmaDescriptorSkip1 | DmaResetOff,
+// DmaBusModeInit = DmaFixedBurstEnable | DmaBurstLength8 | DmaDescriptorSkip4 | DmaResetOff,
+
+ /* 1000 Mb/s mode */
+ DmaControlInit1000 = DmaStoreAndForward,// | DmaTxSecondFrame ,
+
+ /* 100 Mb/s mode */
+ DmaControlInit100 = DmaStoreAndForward,
+
+ /* 10 Mb/s mode */
+ DmaControlInit10 = DmaStoreAndForward,
+
+ /* Interrupt groups */
+ DmaIntErrorMask = DmaIntBusError, /* Error */
+ DmaIntRxAbnMask = DmaIntRxNoBuffer, /* receiver abnormal interrupt */
+ DmaIntRxNormMask = DmaIntRxCompleted, /* receiver normal interrupt */
+ DmaIntRxStoppedMask = DmaIntRxStopped, /* receiver stopped */
+ DmaIntTxAbnMask = DmaIntTxUnderflow, /* transmitter abnormal interrupt */
+ DmaIntTxNormMask = DmaIntTxCompleted, /* transmitter normal interrupt */
+ DmaIntTxStoppedMask = DmaIntTxStopped, /* transmitter stopped */
+
+ DmaIntEnable = DmaIeNormal | DmaIeAbnormal | DmaIntErrorMask
+//DmaIntEnable = DmaIeNormal | DmaIntErrorMask
+ | DmaIntRxAbnMask | DmaIntRxNormMask | DmaIntRxStoppedMask
+// | DmaIntRxNormMask | DmaIntRxStoppedMask
+ | DmaIntTxAbnMask | DmaIntTxNormMask | DmaIntTxStoppedMask,
+ DmaIntDisable = 0,
+};
+
+
+/**********************************************************
+ * Mac Management Counters (MMC)
+ **********************************************************/
+
+enum MMC_ENABLE
+{
+ GmacMmcCntrl = 0x0100, /* mmc control for operating mode of MMC */
+ GmacMmcIntrRx = 0x0104, /* maintains interrupts generated by rx counters */
+ GmacMmcIntrTx = 0x0108, /* maintains interrupts generated by tx counters */
+ GmacMmcIntrMaskRx = 0x010C, /* mask for interrupts generated from rx counters */
+ GmacMmcIntrMaskTx = 0x0110, /* mask for interrupts generated from tx counters */
+};
+enum MMC_TX
+{
+ GmacMmcTxOctetCountGb = 0x0114, /*Bytes Tx excl. of preamble and retried bytes (Good or Bad) */
+ GmacMmcTxFrameCountGb = 0x0118, /*Frames Tx excl. of retried frames (Good or Bad) */
+ GmacMmcTxBcFramesG = 0x011C, /*Broadcast Frames Tx (Good) */
+ GmacMmcTxMcFramesG = 0x0120, /*Multicast Frames Tx (Good) */
+
+ GmacMmcTx64OctetsGb = 0x0124, /*Tx with len 64 bytes excl. of pre and retried (Good or Bad) */
+ GmacMmcTx65To127OctetsGb = 0x0128, /*Tx with len >64 bytes <=127 excl. of pre and retried (Good or Bad) */
+ GmacMmcTx128To255OctetsGb = 0x012C, /*Tx with len >128 bytes <=255 excl. of pre and retried (Good or Bad) */
+ GmacMmcTx256To511OctetsGb = 0x0130, /*Tx with len >256 bytes <=511 excl. of pre and retried (Good or Bad) */
+ GmacMmcTx512To1023OctetsGb = 0x0134, /*Tx with len >512 bytes <=1023 excl. of pre and retried (Good or Bad) */
+ GmacMmcTx1024ToMaxOctetsGb = 0x0138, /*Tx with len >1024 bytes <=MaxSize excl. of pre and retried (Good or Bad) */
+
+ GmacMmcTxUcFramesGb = 0x013C, /*Unicast Frames Tx (Good or Bad) */
+ GmacMmcTxMcFramesGb = 0x0140, /*Multicast Frames Tx (Good and Bad) */
+ GmacMmcTxBcFramesGb = 0x0144, /*Broadcast Frames Tx (Good and Bad) */
+ GmacMmcTxUnderFlowError = 0x0148, /*Frames aborted due to Underflow error */
+ GmacMmcTxSingleColG = 0x014C, /*Successfully Tx Frames after singel collision in Half duplex mode */
+ GmacMmcTxMultiColG = 0x0150, /*Successfully Tx Frames after more than singel collision in Half duplex mode */
+ GmacMmcTxDeferred = 0x0154, /*Successfully Tx Frames after a deferral in Half duplex mode */
+ GmacMmcTxLateCol = 0x0158, /*Frames aborted due to late collision error */
+ GmacMmcTxExessCol = 0x015C, /*Frames aborted due to excessive (16) collision errors */
+ GmacMmcTxCarrierError = 0x0160, /*Frames aborted due to carrier sense error (No carrier or Loss of carrier) */
+ GmacMmcTxOctetCountG = 0x0164, /*Bytes Tx excl. of preamble and retried bytes (Good) */
+ GmacMmcTxFrameCountG = 0x0168, /*Frames Tx (Good) */
+ GmacMmcTxExessDef = 0x016C, /*Frames aborted due to excessive deferral errors (deferred for more than 2 max-sized frame times)*/
+
+ GmacMmcTxPauseFrames = 0x0170, /*Number of good pause frames Tx. */
+ GmacMmcTxVlanFramesG = 0x0174, /*Number of good Vlan frames Tx excl. retried frames */
+};
+enum MMC_RX
+{
+ GmacMmcRxFrameCountGb = 0x0180, /*Frames Rx (Good or Bad) */
+ GmacMmcRxOctetCountGb = 0x0184, /*Bytes Rx excl. of preamble and retried bytes (Good or Bad) */
+ GmacMmcRxOctetCountG = 0x0188, /*Bytes Rx excl. of preamble and retried bytes (Good) */
+ GmacMmcRxBcFramesG = 0x018C, /*Broadcast Frames Rx (Good) */
+ GmacMmcRxMcFramesG = 0x0190, /*Multicast Frames Rx (Good) */
+
+ GmacMmcRxCrcError = 0x0194, /*Number of frames received with CRC error */
+ GmacMmcRxAlignError = 0x0198, /*Number of frames received with alignment (dribble) error. Only in 10/100mode */
+ GmacMmcRxRuntError = 0x019C, /*Number of frames received with runt (<64 bytes and CRC error) error */
+ GmacMmcRxJabberError = 0x01A0, /*Number of frames rx with jabber (>1518/1522 or >9018/9022 and CRC) */
+ GmacMmcRxUnderSizeG = 0x01A4, /*Number of frames received with <64 bytes without any error */
+ GmacMmcRxOverSizeG = 0x01A8, /*Number of frames received with >1518/1522 bytes without any error */
+
+ GmacMmcRx64OctetsGb = 0x01AC, /*Rx with len 64 bytes excl. of pre and retried (Good or Bad) */
+ GmacMmcRx65To127OctetsGb = 0x01B0, /*Rx with len >64 bytes <=127 excl. of pre and retried (Good or Bad) */
+ GmacMmcRx128To255OctetsGb = 0x01B4, /*Rx with len >128 bytes <=255 excl. of pre and retried (Good or Bad) */
+ GmacMmcRx256To511OctetsGb = 0x01B8, /*Rx with len >256 bytes <=511 excl. of pre and retried (Good or Bad) */
+ GmacMmcRx512To1023OctetsGb = 0x01BC, /*Rx with len >512 bytes <=1023 excl. of pre and retried (Good or Bad) */
+ GmacMmcRx1024ToMaxOctetsGb = 0x01C0, /*Rx with len >1024 bytes <=MaxSize excl. of pre and retried (Good or Bad) */
+
+ GmacMmcRxUcFramesG = 0x01C4, /*Unicast Frames Rx (Good) */
+ GmacMmcRxLengthError = 0x01C8, /*Number of frames received with Length type field != frame size */
+ GmacMmcRxOutOfRangeType = 0x01CC, /*Number of frames received with length field != valid frame size */
+
+ GmacMmcRxPauseFrames = 0x01D0, /*Number of good pause frames Rx. */
+ GmacMmcRxFifoOverFlow = 0x01D4, /*Number of missed rx frames due to FIFO overflow */
+ GmacMmcRxVlanFramesGb = 0x01D8, /*Number of good Vlan frames Rx */
+
+ GmacMmcRxWatchdobError = 0x01DC, /*Number of frames rx with error due to watchdog timeout error */
+};
+
+enum MMC_IP_RELATED
+{
+ GmacMmcRxIpcIntrMask = 0x0200, /*Maintains the mask for interrupt generated from rx IPC statistic counters */
+ GmacMmcRxIpcIntr = 0x0208, /*Maintains the interrupt that rx IPC statistic counters generate */
+
+ GmacMmcRxIpV4FramesG = 0x0210, /*Good IPV4 datagrams received */
+ GmacMmcRxIpV4HdrErrFrames = 0x0214, /*Number of IPV4 datagrams received with header errors */
+ GmacMmcRxIpV4NoPayFrames = 0x0218, /*Number of IPV4 datagrams received which didnot have TCP/UDP/ICMP payload */
+ GmacMmcRxIpV4FragFrames = 0x021C, /*Number of IPV4 datagrams received with fragmentation */
+ GmacMmcRxIpV4UdpChkDsblFrames = 0x0220, /*Number of IPV4 datagrams received that had a UDP payload checksum disabled */
+
+ GmacMmcRxIpV6FramesG = 0x0224, /*Good IPV6 datagrams received */
+ GmacMmcRxIpV6HdrErrFrames = 0x0228, /*Number of IPV6 datagrams received with header errors */
+ GmacMmcRxIpV6NoPayFrames = 0x022C, /*Number of IPV6 datagrams received which didnot have TCP/UDP/ICMP payload */
+
+ GmacMmcRxUdpFramesG = 0x0230, /*Number of good IP datagrams with good UDP payload */
+ GmacMmcRxUdpErrorFrames = 0x0234, /*Number of good IP datagrams with UDP payload having checksum error */
+
+ GmacMmcRxTcpFramesG = 0x0238, /*Number of good IP datagrams with good TDP payload */
+ GmacMmcRxTcpErrorFrames = 0x023C, /*Number of good IP datagrams with TCP payload having checksum error */
+
+ GmacMmcRxIcmpFramesG = 0x0240, /*Number of good IP datagrams with good Icmp payload */
+ GmacMmcRxIcmpErrorFrames = 0x0244, /*Number of good IP datagrams with Icmp payload having checksum error */
+
+ GmacMmcRxIpV4OctetsG = 0x0250, /*Good IPV4 datagrams received excl. Ethernet hdr,FCS,Pad,Ip Pad bytes */
+ GmacMmcRxIpV4HdrErrorOctets = 0x0254, /*Number of bytes in IPV4 datagram with header errors */
+ GmacMmcRxIpV4NoPayOctets = 0x0258, /*Number of bytes in IPV4 datagram with no TCP/UDP/ICMP payload */
+ GmacMmcRxIpV4FragOctets = 0x025C, /*Number of bytes received in fragmented IPV4 datagrams */
+ GmacMmcRxIpV4UdpChkDsblOctets = 0x0260, /*Number of bytes received in UDP segment that had UDP checksum disabled */
+
+ GmacMmcRxIpV6OctetsG = 0x0264, /*Good IPV6 datagrams received excl. Ethernet hdr,FCS,Pad,Ip Pad bytes */
+ GmacMmcRxIpV6HdrErrorOctets = 0x0268, /*Number of bytes in IPV6 datagram with header errors */
+ GmacMmcRxIpV6NoPayOctets = 0x026C, /*Number of bytes in IPV6 datagram with no TCP/UDP/ICMP payload */
+
+ GmacMmcRxUdpOctetsG = 0x0270, /*Number of bytes in IP datagrams with good UDP payload */
+ GmacMmcRxUdpErrorOctets = 0x0274, /*Number of bytes in IP datagrams with UDP payload having checksum error */
+
+ GmacMmcRxTcpOctetsG = 0x0278, /*Number of bytes in IP datagrams with good TDP payload */
+ GmacMmcRxTcpErrorOctets = 0x027C, /*Number of bytes in IP datagrams with TCP payload having checksum error */
+
+ GmacMmcRxIcmpOctetsG = 0x0280, /*Number of bytes in IP datagrams with good Icmp payload */
+ GmacMmcRxIcmpErrorOctets = 0x0284, /*Number of bytes in IP datagrams with Icmp payload having checksum error */
+};
+
+
+enum MMC_CNTRL_REG_BIT_DESCRIPTIONS
+{
+ GmacMmcCounterFreeze = 0x00000008, /* when set MMC counters freeze to current value */
+ GmacMmcCounterResetOnRead = 0x00000004, /* when set MMC counters will be reset to 0 after read */
+ GmacMmcCounterStopRollover = 0x00000002, /* when set counters will not rollover after max value */
+ GmacMmcCounterReset = 0x00000001, /* when set all counters wil be reset (automatically cleared after 1 clk) */
+};
+
+enum MMC_RX_INTR_MASK_AND_STATUS_BIT_DESCRIPTIONS
+{
+ GmacMmcRxWDInt = 0x00800000, /* set when rxwatchdog error reaches half of max value */
+ GmacMmcRxVlanInt = 0x00400000, /* set when GmacMmcRxVlanFramesGb counter reaches half of max value */
+ GmacMmcRxFifoOverFlowInt = 0x00200000, /* set when GmacMmcRxFifoOverFlow counter reaches half of max value */
+ GmacMmcRxPauseFrameInt = 0x00100000, /* set when GmacMmcRxPauseFrames counter reaches half of max value */
+ GmacMmcRxOutOfRangeInt = 0x00080000, /* set when GmacMmcRxOutOfRangeType counter reaches half of max value */
+ GmacMmcRxLengthErrorInt = 0x00040000, /* set when GmacMmcRxLengthError counter reaches half of max value */
+ GmacMmcRxUcFramesInt = 0x00020000, /* set when GmacMmcRxUcFramesG counter reaches half of max value */
+ GmacMmcRx1024OctInt = 0x00010000, /* set when GmacMmcRx1024ToMaxOctetsGb counter reaches half of max value */
+ GmacMmcRx512OctInt = 0x00008000, /* set when GmacMmcRx512To1023OctetsGb counter reaches half of max value */
+ GmacMmcRx256OctInt = 0x00004000, /* set when GmacMmcRx256To511OctetsGb counter reaches half of max value */
+ GmacMmcRx128OctInt = 0x00002000, /* set when GmacMmcRx128To255OctetsGb counter reaches half of max value */
+ GmacMmcRx65OctInt = 0x00001000, /* set when GmacMmcRx65To127OctetsG counter reaches half of max value */
+ GmacMmcRx64OctInt = 0x00000800, /* set when GmacMmcRx64OctetsGb counter reaches half of max value */
+ GmacMmcRxOverSizeInt = 0x00000400, /* set when GmacMmcRxOverSizeG counter reaches half of max value */
+ GmacMmcRxUnderSizeInt = 0x00000200, /* set when GmacMmcRxUnderSizeG counter reaches half of max value */
+ GmacMmcRxJabberErrorInt = 0x00000100, /* set when GmacMmcRxJabberError counter reaches half of max value */
+ GmacMmcRxRuntErrorInt = 0x00000080, /* set when GmacMmcRxRuntError counter reaches half of max value */
+ GmacMmcRxAlignErrorInt = 0x00000040, /* set when GmacMmcRxAlignError counter reaches half of max value */
+ GmacMmcRxCrcErrorInt = 0x00000020, /* set when GmacMmcRxCrcError counter reaches half of max value */
+ GmacMmcRxMcFramesInt = 0x00000010, /* set when GmacMmcRxMcFramesG counter reaches half of max value */
+ GmacMmcRxBcFramesInt = 0x00000008, /* set when GmacMmcRxBcFramesG counter reaches half of max value */
+ GmacMmcRxOctetGInt = 0x00000004, /* set when GmacMmcRxOctetCountG counter reaches half of max value */
+ GmacMmcRxOctetGbInt = 0x00000002, /* set when GmacMmcRxOctetCountGb counter reaches half of max value */
+ GmacMmcRxFrameInt = 0x00000001, /* set when GmacMmcRxFrameCountGb counter reaches half of max value */
+};
+
+enum MMC_TX_INTR_MASK_AND_STATUS_BIT_DESCRIPTIONS
+{
+
+ GmacMmcTxVlanInt = 0x01000000, /* set when GmacMmcTxVlanFramesG counter reaches half of max value */
+ GmacMmcTxPauseFrameInt = 0x00800000, /* set when GmacMmcTxPauseFrames counter reaches half of max value */
+ GmacMmcTxExessDefInt = 0x00400000, /* set when GmacMmcTxExessDef counter reaches half of max value */
+ GmacMmcTxFrameInt = 0x00200000, /* set when GmacMmcTxFrameCount counter reaches half of max value */
+ GmacMmcTxOctetInt = 0x00100000, /* set when GmacMmcTxOctetCountG counter reaches half of max value */
+ GmacMmcTxCarrierErrorInt = 0x00080000, /* set when GmacMmcTxCarrierError counter reaches half of max value */
+ GmacMmcTxExessColInt = 0x00040000, /* set when GmacMmcTxExessCol counter reaches half of max value */
+ GmacMmcTxLateColInt = 0x00020000, /* set when GmacMmcTxLateCol counter reaches half of max value */
+ GmacMmcTxDeferredInt = 0x00010000, /* set when GmacMmcTxDeferred counter reaches half of max value */
+ GmacMmcTxMultiColInt = 0x00008000, /* set when GmacMmcTxMultiColG counter reaches half of max value */
+ GmacMmcTxSingleCol = 0x00004000, /* set when GmacMmcTxSingleColG counter reaches half of max value */
+ GmacMmcTxUnderFlowErrorInt = 0x00002000, /* set when GmacMmcTxUnderFlowError counter reaches half of max value */
+ GmacMmcTxBcFramesGbInt = 0x00001000, /* set when GmacMmcTxBcFramesGb counter reaches half of max value */
+ GmacMmcTxMcFramesGbInt = 0x00000800, /* set when GmacMmcTxMcFramesGb counter reaches half of max value */
+ GmacMmcTxUcFramesInt = 0x00000400, /* set when GmacMmcTxUcFramesGb counter reaches half of max value */
+ GmacMmcTx1024OctInt = 0x00000200, /* set when GmacMmcTx1024ToMaxOctetsGb counter reaches half of max value */
+ GmacMmcTx512OctInt = 0x00000100, /* set when GmacMmcTx512To1023OctetsGb counter reaches half of max value */
+ GmacMmcTx256OctInt = 0x00000080, /* set when GmacMmcTx256To511OctetsGb counter reaches half of max value */
+ GmacMmcTx128OctInt = 0x00000040, /* set when GmacMmcTx128To255OctetsGb counter reaches half of max value */
+ GmacMmcTx65OctInt = 0x00000020, /* set when GmacMmcTx65To127OctetsGb counter reaches half of max value */
+ GmacMmcTx64OctInt = 0x00000010, /* set when GmacMmcTx64OctetsGb counter reaches half of max value */
+ GmacMmcTxMcFramesInt = 0x00000008, /* set when GmacMmcTxMcFramesG counter reaches half of max value */
+ GmacMmcTxBcFramesInt = 0x00000004, /* set when GmacMmcTxBcFramesG counter reaches half of max value */
+ GmacMmcTxFrameGbInt = 0x00000002, /* set when GmacMmcTxFrameCountGb counter reaches half of max value */
+ GmacMmcTxOctetGbInt = 0x00000001, /* set when GmacMmcTxOctetCountGb counter reaches half of max value */
+};
+
+
+/**********************************************************
+ * Power Management (PMT) Block
+ **********************************************************/
+
+/**
+ * PMT supports the reception of network (remote) wake-up frames and Magic packet frames.
+ * It generates interrupts for wake-up frames and Magic packets received by GMAC.
+ * PMT sits in Rx path and is enabled with remote wake-up frame enable and Magic packet enable.
+ * These enable are in PMT control and Status register and are programmed by apllication.
+ *
+ * When power down mode is enabled in PMT, all rx frames are dropped by the core. Core comes
+ * out of power down mode only when either Magic packe tor a Remote wake-up frame is received
+ * and the corresponding detection is enabled.
+ *
+ * Driver need not be modified to support this feature. Only Api to put the device in to power
+ * down mode is sufficient
+ */
+
+#define WAKEUP_REG_LENGTH 8 /*This is the reg length for wake up register configuration*/
+
+enum GmacPmtCtrlStatusBitDefinition
+{
+ GmacPmtFrmFilterPtrReset = 0x80000000, /* when set remote wake-up frame filter register pointer to 3'b000 */
+ GmacPmtGlobalUnicast = 0x00000200, /* When set enables any unicast packet to be a wake-up frame */
+ GmacPmtWakeupFrameReceived = 0x00000040, /* Wake up frame received */
+ GmacPmtMagicPktReceived = 0x00000020, /* Magic Packet received */
+ GmacPmtWakeupFrameEnable = 0x00000004, /* Wake-up frame enable */
+ GmacPmtMagicPktEnable = 0x00000002, /* Magic packet enable */
+ GmacPmtPowerDown = 0x00000001, /* Power Down */
+};
+
+/**********************************************************
+ * IEEE 1588-2008 Precision Time Protocol (PTP) Support
+ **********************************************************/
+enum PTPMessageType
+{
+ SYNC = 0x0,
+ Delay_Req = 0x1,
+ Pdelay_Req = 0x2,
+ Pdelay_Resp = 0x3,
+ Follow_up = 0x8,
+ Delay_Resp = 0x9,
+ Pdelay_Resp_Follow_Up = 0xA,
+ Announce = 0xB,
+ Signaling = 0xC,
+ Management = 0xD,
+};
+
+typedef struct TimeStampStruct
+{
+ u32 TSversion; /* PTP Version 1 or PTP version2 */
+ u32 TSmessagetype; /* Message type associated with this time stamp */
+
+ u16 TShighest16; /* Highest 16 bit time stamp value, Valid onley when ADV_TIME_HIGH_WORD configured in corekit */
+ u32 TSupper32; /* Most significant 32 bit time stamp value */
+ u32 TSlower32; /* Least Significat 32 bit time stamp value */
+
+} TimeStamp;
+
+
+/**
+ * IEEE 1588-2008 is the optional module to support Ethernet frame time stamping.
+ * Sixty four (+16) bit time stamps are given in each frames transmit and receive status.
+ * The driver assumes the following
+ * 1. "IEEE 1588 Time Stamping" "TIME_STAMPING"is ENABLED in corekit
+ * 2. "IEEE 1588 External Time Stamp Input Enable" "EXT_TIME_STAMPING" is DISABLED in corekit
+ * 3. "IEEE 1588 Advanced Time Stamp support" "ADV_TIME_STAMPING" is ENABLED in corekit
+ * 4. "IEEE 1588 Higher Word Register Enable" "ADV_TIME_HIGH_WORD" is ENABLED in corekit
+ */
+
+/* GmacTSControl = 0x0700, Controls the Timestamp update logic : only when IEEE 1588 time stamping is enabled in corekit */
+enum GmacTSControlReg
+{
+ GmacTSENMACADDR = 0x00040000, /* Enable Mac Addr for PTP filtering 18 RW 0 */
+
+ GmacTSCLKTYPE = 0x00030000, /* Select the type of clock node 17:16 RW 00 */
+ /*
+ TSCLKTYPE TSMSTRENA TSEVNTENA Messages for wihich TS snapshot is taken
+ 00/01 X 0 SYNC, FOLLOW_UP, DELAY_REQ, DELAY_RESP
+ 00/01 1 0 DELAY_REQ
+ 00/01 0 1 SYNC
+ 10 NA 0 SYNC, FOLLOW_UP, DELAY_REQ, DELAY_RESP
+ 10 NA 1 SYNC, FOLLOW_UP
+ 11 NA 0 SYNC, FOLLOW_UP, DELAY_REQ, DELAY_RESP, PDELAY_REQ, PDELAY_RESP
+ 11 NA 1 SYNC, PDELAY_REQ, PDELAY_RESP
+ */
+ GmacTSOrdClk = 0x00000000, /* 00=> Ordinary clock*/
+ GmacTSBouClk = 0x00010000, /* 01=> Boundary clock*/
+ GmacTSEtoEClk = 0x00020000, /* 10=> End-to-End transparent clock*/
+ GmacTSPtoPClk = 0x00030000, /* 11=> P-to-P transparent clock*/
+
+ GmacTSMSTRENA = 0x00008000, /* Ena TS Snapshot for Master Messages 15 RW 0 */
+ GmacTSEVNTENA = 0x00004000, /* Ena TS Snapshot for Event Messages 14 RW 0 */
+ GmacTSIPV4ENA = 0x00002000, /* Ena TS snapshot for IPv4 13 RW 1 */
+ GmacTSIPV6ENA = 0x00001000, /* Ena TS snapshot for IPv6 12 RW 0 */
+ GmacTSIPENA = 0x00000800, /* Ena TS snapshot for PTP over E'net 11 RW 0 */
+ GmacTSVER2ENA = 0x00000400, /* Ena PTP snooping for version 2 10 RW 0 */
+
+ GmacTSCTRLSSR = 0x00000200, /* Digital or Binary Rollover 9 RW 0 */
+
+ GmacTSENALL = 0x00000100, /* Enable TS fro all frames (Ver2 only) 8 RW 0 */
+
+ GmacTSADDREG = 0x00000020, /* Addend Register Update 5 RW_SC 0 */
+ GmacTSUPDT = 0x00000008, /* Time Stamp Update 3 RW_SC 0 */
+ GmacTSINT = 0x00000004, /* Time Atamp Initialize 2 RW_SC 0 */
+
+ GmacTSTRIG = 0x00000010, /* Time stamp interrupt Trigger Enable 4 RW_SC 0 */
+
+ GmacTSCFUPDT = 0x00000002, /* Time Stamp Fine/Coarse 1 RW 0 */
+ GmacTSCUPDTCoarse = 0x00000000, /* 0=> Time Stamp update method is coarse */
+ GmacTSCUPDTFine = 0x00000002, /* 1=> Time Stamp update method is fine */
+
+ GmacTSENA = 0x00000001, /* Time Stamp Enable 0 RW 0 */
+};
+
+
+/* GmacTSSubSecIncr = 0x0704, 8 bit value by which sub second register is incremented : only when IEEE 1588 time stamping without external timestamp input */
+enum GmacTSSubSecIncrReg
+{
+ GmacSSINCMsk = 0x000000FF, /* Only Lower 8 bits are valid bits 7:0 RW 00 */
+};
+
+/* GmacTSLow = 0x070C, Indicates whether the timestamp low count is positive or negative; for Adv timestamp it is always zero */
+enum GmacTSSign
+{
+ GmacTSSign = 0x80000000, /* PSNT 31 RW 0 */
+ GmacTSPositive = 0x00000000,
+ GmacTSNegative = 0x80000000,
+};
+
+/*GmacTargetTimeLow = 0x0718, 32 bit nano seconds(MS) to be compared with system time : only when IEEE 1588 time stamping without external timestamp input */
+enum GmacTSLowReg
+{
+ GmacTSDecThr = 0x3B9AC9FF, /*when TSCTRLSSR is set the max value for GmacTargetTimeLowReg and GmacTimeStampLow register is 0x3B9AC9FF at 1ns precision */
+};
+
+/* GmacTSHighWord = 0x0724, Time Stamp Higher Word Register (Version 2 only); only lower 16 bits are valid */
+enum GmacTSHighWordReg
+{
+ GmacTSHighWordMask = 0x0000FFFF, /* Time Stamp Higher work register has only lower 16 bits valid */
+};
+/*GmacTSStatus = 0x0728, Time Stamp Status Register */
+enum GmacTSStatusReg
+{
+ GmacTSTargTimeReached = 0x00000002, /* Time Stamp Target Time Reached 1 RO 0 */
+ GmacTSSecondsOverflow = 0x00000001, /* Time Stamp Seconds Overflow 0 RO 0 */
+};
+
+/**********************************************************
+ * Time stamp related functions
+ **********************************************************/
+void synopGMAC_TS_enable(synopGMACdevice *gmacdev);
+void synopGMAC_TS_disable(synopGMACdevice *gmacdev);
+
+void synopGMAC_TS_int_enable(synopGMACdevice *gmacdev);
+void synopGMAC_TS_int_disable(synopGMACdevice *gmacdev);
+
+void synopGMAC_TS_mac_addr_filt_enable(synopGMACdevice *gmacdev);
+void synopGMAC_TS_mac_addr_filt_disable(synopGMACdevice *gmacdev);
+void synopGMAC_TS_set_clk_type(synopGMACdevice *gmacdev, u32 clk_type);
+void synopGMAC_TS_master_enable(synopGMACdevice *gmacdev); // Only for Ordinary clock and Boundary clock and "Advanced Time Stamp"
+void synopGMAC_TS_master_disable(synopGMACdevice *gmacdev); // Only for Ordinary clock and Boundary clock and "Advanced Time Stamp"
+void synopGMAC_TS_event_enable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp"
+void synopGMAC_TS_event_disable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp"
+void synopGMAC_TS_IPV4_enable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp"
+void synopGMAC_TS_IPV4_disable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp"
+void synopGMAC_TS_IPV6_enable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp"
+void synopGMAC_TS_IPV6_disable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp"
+void synopGMAC_TS_ptp_over_ethernet_enable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp"
+void synopGMAC_TS_ptp_over_ethernet_disable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp"
+void synopGMAC_TS_pkt_snoop_ver2(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp"
+void synopGMAC_TS_pkt_snoop_ver1(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp"
+
+void synopGMAC_TS_digital_rollover_enable(synopGMACdevice *gmacdev);
+void synopGMAC_TS_binary_rollover_enable(synopGMACdevice *gmacdev);
+void synopGMAC_TS_all_frames_enable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp"
+void synopGMAC_TS_all_frames_disable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp"
+
+s32 synopGMAC_TS_addend_update(synopGMACdevice *gmacdev, u32 addend_value);
+s32 synopGMAC_TS_timestamp_update(synopGMACdevice *gmacdev, u32 high_value, u32 low_value);
+s32 synopGMAC_TS_timestamp_init(synopGMACdevice *gmacdev, u32 high_value, u32 low_value);
+
+void synopGMAC_TS_coarse_update(synopGMACdevice *gmacdev); // Only if "fine correction" enabled
+void synopGMAC_TS_fine_update(synopGMACdevice *gmacdev); // Only if "fine correction" enabled
+
+void synopGMAC_TS_subsecond_init(synopGMACdevice *gmacdev, u32 sub_sec_inc_val); // Update should happen making use of subsecond mask
+void synopGMAC_TS_read_timestamp(synopGMACdevice *gmacdev, u16 * higher_sec_val,
+ u32 * sec_val, u32 * sub_sec_val); // Reads the timestamp low,high and higher(Ver2) registers in the the struct pointer; readonly contents
+void synopGMAC_TS_load_target_timestamp(synopGMACdevice *gmacdev, u32 sec_val, u32 sub_sec_val); //Loads the timestamp target register with the values provided
+
+void synopGMAC_TS_load_timestamp_higher_val(synopGMACdevice *gmacdev, u32 higher_sec_val);
+void synopGMAC_TS_read_timestamp_higher_val(synopGMACdevice *gmacdev, u16 * higher_sec_val);
+void synopGMAC_TS_read_target_timestamp(synopGMACdevice *gmacdev, u32 * sec_val, u32 * sub_sec_val); //Read the target time stamp register contents
+
+
+/**********************************************************
+ * Common functions
+ **********************************************************/
+s32 synopGMAC_set_mdc_clk_div(synopGMACdevice *gmacdev,u32 clk_div_val );
+u32 synopGMAC_get_mdc_clk_div(synopGMACdevice *gmacdev);
+s32 synopGMAC_read_phy_reg(u64 RegBase,u32 PhyBase, u32 RegOffset, u16 * data);
+s32 synopGMAC_write_phy_reg(u64 RegBase, u32 PhyBase, u32 RegOffset, u16 data);
+s32 synopGMAC_phy_loopback(synopGMACdevice *gmacdev, bool loopback);
+s32 synopGMAC_read_version (synopGMACdevice * gmacdev) ;
+s32 synopGMAC_reset (synopGMACdevice * gmacdev );
+s32 synopGMAC_dma_bus_mode_init(synopGMACdevice * gmacdev, u32 init_value );
+s32 synopGMAC_dma_control_init(synopGMACdevice * gmacdev, u32 init_value );
+void synopGMAC_wd_enable(synopGMACdevice * gmacdev);
+void synopGMAC_wd_disable(synopGMACdevice * gmacdev);
+void synopGMAC_jab_enable(synopGMACdevice * gmacdev);
+void synopGMAC_jab_disable(synopGMACdevice * gmacdev);
+void synopGMAC_frame_burst_enable(synopGMACdevice * gmacdev);
+void synopGMAC_frame_burst_disable(synopGMACdevice * gmacdev);
+void synopGMAC_jumbo_frame_enable(synopGMACdevice * gmacdev);
+void synopGMAC_jumbo_frame_disable(synopGMACdevice * gmacdev);
+void synopGMAC_select_gmii(synopGMACdevice * gmacdev);
+void synopGMAC_select_mii(synopGMACdevice * gmacdev);
+void synopGMAC_rx_own_enable(synopGMACdevice * gmacdev);
+void synopGMAC_rx_own_disable(synopGMACdevice * gmacdev);
+void synopGMAC_loopback_on(synopGMACdevice * gmacdev);
+void synopGMAC_loopback_off(synopGMACdevice * gmacdev);
+void synopGMAC_set_full_duplex(synopGMACdevice * gmacdev);
+void synopGMAC_set_half_duplex(synopGMACdevice * gmacdev);
+void synopGMAC_retry_enable(synopGMACdevice * gmacdev);
+void synopGMAC_retry_disable(synopGMACdevice * gmacdev);
+void synopGMAC_pad_crc_strip_enable(synopGMACdevice * gmacdev);
+void synopGMAC_pad_crc_strip_disable(synopGMACdevice * gmacdev);
+void synopGMAC_back_off_limit(synopGMACdevice * gmacdev, u32 value);
+void synopGMAC_deferral_check_enable(synopGMACdevice * gmacdev);
+void synopGMAC_deferral_check_disable(synopGMACdevice * gmacdev);
+void synopGMAC_rx_enable(synopGMACdevice * gmacdev);
+void synopGMAC_rx_disable(synopGMACdevice * gmacdev);
+void synopGMAC_tx_enable(synopGMACdevice * gmacdev);
+void synopGMAC_tx_disable(synopGMACdevice * gmacdev);
+void synopGMAC_frame_filter_enable(synopGMACdevice * gmacdev);
+void synopGMAC_frame_filter_disable(synopGMACdevice * gmacdev);
+void synopGMAC_write_hash_table_high(synopGMACdevice * gmacdev, u32 data);
+void synopGMAC_write_hash_table_low(synopGMACdevice * gmacdev, u32 data);
+void synopGMAC_hash_perfect_filter_enable(synopGMACdevice * gmacdev);
+void synopGMAC_Hash_filter_only_enable(synopGMACdevice * gmacdev);
+void synopGMAC_src_addr_filter_enable(synopGMACdevice * gmacdev);
+void synopGMAC_src_addr_filter_disable(synopGMACdevice * gmacdev);
+void synopGMAC_dst_addr_filter_inverse(synopGMACdevice * gmacdev);
+void synopGMAC_dst_addr_filter_normal(synopGMACdevice * gmacdev);
+void synopGMAC_set_pass_control(synopGMACdevice * gmacdev,u32 passcontrol);
+void synopGMAC_broadcast_enable(synopGMACdevice * gmacdev);
+void synopGMAC_broadcast_disable(synopGMACdevice * gmacdev);
+void synopGMAC_multicast_enable(synopGMACdevice * gmacdev);
+void synopGMAC_multicast_disable(synopGMACdevice * gmacdev);
+void synopGMAC_multicast_hash_filter_enable(synopGMACdevice * gmacdev);
+void synopGMAC_multicast_hash_filter_disable(synopGMACdevice * gmacdev);
+void synopGMAC_promisc_enable(synopGMACdevice * gmacdev);
+void synopGMAC_promisc_disable(synopGMACdevice * gmacdev);
+void synopGMAC_unicast_hash_filter_enable(synopGMACdevice * gmacdev);
+void synopGMAC_unicast_hash_filter_disable(synopGMACdevice * gmacdev);
+void synopGMAC_unicast_pause_frame_detect_enable(synopGMACdevice * gmacdev);
+void synopGMAC_unicast_pause_frame_detect_disable(synopGMACdevice * gmacdev);
+void synopGMAC_rx_flow_control_enable(synopGMACdevice * gmacdev);
+void synopGMAC_rx_flow_control_disable(synopGMACdevice * gmacdev);
+void synopGMAC_tx_flow_control_enable(synopGMACdevice * gmacdev);
+void synopGMAC_tx_flow_control_disable(synopGMACdevice * gmacdev);
+void synopGMAC_tx_activate_flow_control(synopGMACdevice * gmacdev);
+void synopGMAC_tx_deactivate_flow_control(synopGMACdevice * gmacdev);
+void synopGMAC_pause_control(synopGMACdevice *gmacdev);
+s32 synopGMAC_mac_init(synopGMACdevice * gmacdev);
+s32 synopGMAC_set_mac_addr(synopGMACdevice *gmacdev, u32 MacHigh, u32 MacLow, u8 *MacAddr );
+s32 synopGMAC_get_mac_addr(synopGMACdevice *gmacdev, u32 MacHigh, u32 MacLow, u8 *MacAddr );
+s32 synopGMAC_attach (synopGMACdevice * gmacdev, u64 macBase, u64 dmaBase, u64 phyBase,u8 *mac_addr);
+void synopGMAC_rx_desc_init_ring(DmaDesc *desc, bool last_ring_desc);
+void synopGMAC_tx_desc_init_ring(DmaDesc *desc, bool last_ring_desc);
+void synopGMAC_rx_desc_init_chain(DmaDesc * desc);
+void synopGMAC_tx_desc_init_chain(DmaDesc * desc);
+s32 synopGMAC_init_tx_rx_desc_queue(synopGMACdevice *gmacdev);
+void synopGMAC_init_rx_desc_base(synopGMACdevice *gmacdev);
+void synopGMAC_init_tx_desc_base(synopGMACdevice *gmacdev);
+void synopGMAC_set_owner_dma(DmaDesc *desc);
+void synopGMAC_set_desc_sof(DmaDesc *desc);
+void synopGMAC_set_desc_eof(DmaDesc *desc);
+bool synopGMAC_is_sof_in_rx_desc(DmaDesc *desc);
+bool synopGMAC_is_eof_in_rx_desc(DmaDesc *desc);
+bool synopGMAC_is_da_filter_failed(DmaDesc *desc);
+bool synopGMAC_is_sa_filter_failed(DmaDesc *desc);
+bool synopGMAC_is_desc_owned_by_dma(DmaDesc *desc);
+u32 synopGMAC_get_rx_desc_frame_length(u32 status);
+bool synopGMAC_is_desc_valid(u32 status);
+bool synopGMAC_is_desc_empty(DmaDesc *desc);
+bool synopGMAC_is_rx_desc_valid(u32 status);
+bool synopGMAC_is_tx_aborted(u32 status);
+bool synopGMAC_is_tx_carrier_error(u32 status);
+u32 synopGMAC_get_tx_collision_count(u32 status);
+u32 synopGMAC_is_exc_tx_collisions(u32 status);
+bool synopGMAC_is_rx_frame_damaged(u32 status);
+bool synopGMAC_is_rx_frame_collision(u32 status);
+bool synopGMAC_is_rx_crc(u32 status);
+bool synopGMAC_is_frame_dribbling_errors(u32 status);
+bool synopGMAC_is_rx_frame_length_errors(u32 status);
+bool synopGMAC_is_last_rx_desc(synopGMACdevice * gmacdev,DmaDesc *desc);
+bool synopGMAC_is_last_tx_desc(synopGMACdevice * gmacdev,DmaDesc *desc);
+bool synopGMAC_is_rx_desc_chained(DmaDesc * desc);
+bool synopGMAC_is_tx_desc_chained(DmaDesc * desc);
+void synopGMAC_get_desc_data(DmaDesc * desc, u32 * Status, u32 * Buffer1, u32 * Length1, u64 * Data1, u32 * Buffer2, u32 * Length2, u64 * Data2);
+#ifdef ENH_DESC_8W
+s32 synopGMAC_get_tx_qptr(synopGMACdevice * gmacdev, u32 * Status, u32 * Buffer1, u32 * Length1, u64 * Data1, u32 * Buffer2, u32 * Length2, u64 * Data2,
+ u32 * Ext_Status, u32 * Time_Stamp_High, u32 * Time_Stamp_low);
+#else
+s32 synopGMAC_get_tx_qptr(synopGMACdevice * gmacdev, u32 * Status, u32 * Buffer1, u32 * Length1, u64 * Data1, u32 * Buffer2, u32 * Length2, u64 * Data2 );
+#endif
+s32 synopGMAC_set_tx_qptr(synopGMACdevice * gmacdev, u32 Buffer1, u32 Length1, u64 Data1, u32 Buffer2, u32 Length2, u64 Data2,u32 offload_needed,u32 * index,DmaDesc *Dpr);
+s32 synopGMAC_set_rx_qptr(synopGMACdevice * gmacdev, u32 Buffer1, u32 Length1, u64 Data1, u32 Buffer2, u32 Length2, u64 Data2);
+#ifdef ENH_DESC_8W
+s32 synopGMAC_get_rx_qptr(synopGMACdevice * gmacdev, u32 * Status, u32 * Buffer1, u32 * Length1, u64 * Data1, u32 * Buffer2, u32 * Length2, u64 * Data2,
+ u32 * Ext_Status, u32 * Time_Stamp_High, u32 * Time_Stamp_low);
+#else
+s32 synopGMAC_get_rx_qptr(synopGMACdevice * gmacdev, u32 * Status, u32 * Buffer1, u32 * Length1, u64 * Data1, u32 * Buffer2, u32 * Length2, u64 * Data2);
+#endif
+void synopGMAC_clear_interrupt(synopGMACdevice *gmacdev);
+u32 synopGMAC_get_interrupt_type(synopGMACdevice *gmacdev);
+u32 synopGMAC_get_interrupt_mask(synopGMACdevice *gmacdev);
+void synopGMAC_enable_interrupt(synopGMACdevice *gmacdev, u32 interrupts);
+void synopGMAC_disable_interrupt_all(synopGMACdevice *gmacdev);
+void synopGMAC_disable_interrupt(synopGMACdevice *gmacdev, u32 interrupts);
+void synopGMAC_enable_dma_rx(synopGMACdevice * gmacdev);
+void synopGMAC_enable_dma_tx(synopGMACdevice * gmacdev);
+void synopGMAC_resume_dma_tx(synopGMACdevice * gmacdev);
+void synopGMAC_resume_dma_rx(synopGMACdevice * gmacdev);
+void synopGMAC_take_desc_ownership(DmaDesc * desc);
+void synopGMAC_take_desc_ownership_rx(synopGMACdevice * gmacdev);
+void synopGMAC_take_desc_ownership_tx(synopGMACdevice * gmacdev);
+void synopGMAC_disable_dma_tx(synopGMACdevice * gmacdev);
+void synopGMAC_disable_dma_rx(synopGMACdevice * gmacdev);
+/******Following APIs are valid only for Enhanced Descriptor from 3.50a release onwards*******/
+bool synopGMAC_is_ext_status(synopGMACdevice *gmacdev,u32 status);
+bool synopGMAC_ES_is_IP_header_error(synopGMACdevice *gmacdev,u32 ext_status);
+bool synopGMAC_ES_is_rx_checksum_bypassed(synopGMACdevice *gmacdev,u32 ext_status);
+bool synopGMAC_ES_is_IP_payload_error(synopGMACdevice *gmacdev,u32 ext_status);
+/*******************PMT APIs***************************************/
+void synopGMAC_pmt_int_enable(synopGMACdevice *gmacdev);
+void synopGMAC_pmt_int_disable(synopGMACdevice *gmacdev);
+void synopGMAC_power_down_enable(synopGMACdevice *gmacdev);
+void synopGMAC_power_down_disable(synopGMACdevice *gmacdev);
+void synopGMAC_enable_pmt_interrupt(synopGMACdevice *gmacdev);
+void synopGMAC_disable_pmt_interrupt(synopGMACdevice *gmacdev);
+void synopGMAC_magic_packet_enable(synopGMACdevice *gmacdev);
+void synopGMAC_wakeup_frame_enable(synopGMACdevice *gmacdev);
+void synopGMAC_pmt_unicast_enable(synopGMACdevice *gmacdev);
+bool synopGMAC_is_magic_packet_received(synopGMACdevice *gmacdev);
+bool synopGMAC_is_wakeup_frame_received(synopGMACdevice *gmacdev);
+void synopGMAC_write_wakeup_frame_register(synopGMACdevice *gmacdev, u32 * filter_contents);
+/*******************MMC APIs***************************************/
+void synopGMAC_mmc_counters_stop(synopGMACdevice *gmacdev);
+void synopGMAC_mmc_counters_resume(synopGMACdevice *gmacdev);
+void synopGMAC_mmc_counters_set_selfclear(synopGMACdevice *gmacdev);
+void synopGMAC_mmc_counters_reset_selfclear(synopGMACdevice *gmacdev);
+void synopGMAC_mmc_counters_disable_rollover(synopGMACdevice *gmacdev);
+void synopGMAC_mmc_counters_enable_rollover(synopGMACdevice *gmacdev);
+u32 synopGMAC_read_mmc_counter(synopGMACdevice *gmacdev, u32 counter);
+u32 synopGMAC_read_mmc_rx_int_status(synopGMACdevice *gmacdev);
+u32 synopGMAC_read_mmc_tx_int_status(synopGMACdevice *gmacdev);
+void synopGMAC_disable_mmc_tx_interrupt(synopGMACdevice *gmacdev, u32 mask);
+void synopGMAC_enable_mmc_tx_interrupt(synopGMACdevice *gmacdev, u32 mask);
+void synopGMAC_disable_mmc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask);
+void synopGMAC_enable_mmc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask);
+void synopGMAC_enable_mmc_ipc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask);
+void synopGMAC_disable_mmc_ipc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask);
+/*******************Ip checksum offloading APIs***************************************/
+void synopGMAC_enable_rx_chksum_offload(synopGMACdevice *gmacdev);
+void synopGMAC_disable_rx_Ipchecksum_offload(synopGMACdevice *gmacdev);
+void synopGMAC_rx_tcpip_chksum_drop_enable(synopGMACdevice *gmacdev);
+void synopGMAC_rx_tcpip_chksum_drop_disable(synopGMACdevice *gmacdev);
+u32 synopGMAC_is_rx_checksum_error(synopGMACdevice *gmacdev, u32 status);
+bool synopGMAC_is_tx_ipv4header_checksum_error(synopGMACdevice *gmacdev, u32 status);
+bool synopGMAC_is_tx_payload_checksum_error(synopGMACdevice *gmacdev, u32 status);
+void synopGMAC_tx_checksum_offload_bypass(synopGMACdevice *gmacdev, DmaDesc *desc);
+void synopGMAC_tx_checksum_offload_ipv4hdr(synopGMACdevice *gmacdev, DmaDesc *desc);
+void synopGMAC_tx_checksum_offload_tcponly(synopGMACdevice *gmacdev, DmaDesc *desc);
+void synopGMAC_tx_checksum_offload_tcp_pseudo(synopGMACdevice *gmacdev, DmaDesc *desc);
+
+#endif /* End of file */
diff --git a/bsp/ls2kdev/drivers/net/synopGMAC_Host.h b/bsp/ls2kdev/drivers/net/synopGMAC_Host.h
new file mode 100644
index 0000000000..b81b0c29f0
--- /dev/null
+++ b/bsp/ls2kdev/drivers/net/synopGMAC_Host.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2017-08-24 chinesebear first version
+ */
+
+#ifndef SYNOP_GMAC_HOST_H
+#define SYNOP_GMAC_HOST_H 1
+
+#include "synopGMAC_plat.h"
+#include "synopGMAC_Dev.h"
+#include "mii.h"
+
+struct net_device_stats
+{
+ unsigned long rx_packets; /* total packets received */
+ unsigned long tx_packets; /* total packets transmitted */
+ unsigned long rx_bytes; /* total bytes received */
+ unsigned long tx_bytes; /* total bytes transmitted */
+ unsigned long rx_errors; /* bad packets received */
+ unsigned long tx_errors; /* packet transmit problems */
+ unsigned long rx_dropped; /* no space in linux buffers */
+ unsigned long tx_dropped; /* no space available in linux */
+ unsigned long multicast; /* multicast packets received */
+ unsigned long collisions;
+
+ /* detailed rx_errors: */
+ unsigned long rx_length_errors;
+ unsigned long rx_over_errors; /* receiver ring buff overflow */
+ unsigned long rx_crc_errors; /* recved pkt with crc error */
+ unsigned long rx_frame_errors; /* recv'd frame alignment error */
+ unsigned long rx_fifo_errors; /* recv'r fifo overrun */
+ unsigned long rx_missed_errors; /* receiver missed packet */
+
+ /* detailed tx_errors */
+ unsigned long tx_aborted_errors;
+ unsigned long tx_carrier_errors;
+ unsigned long tx_fifo_errors;
+ unsigned long tx_heartbeat_errors;
+ unsigned long tx_window_errors;
+
+ /* for cslip etc */
+ unsigned long rx_compressed;
+ unsigned long tx_compressed;
+};
+
+typedef struct synopGMACNetworkAdapter{
+/*Device Dependent Data structur*/
+synopGMACdevice * synopGMACdev;
+
+struct net_device_stats synopGMACNetStats;
+
+struct mii_if_info mii;
+} synopGMACPciNetworkAdapter;
+
+#endif
diff --git a/bsp/ls2kdev/drivers/net/synopGMAC_debug.h b/bsp/ls2kdev/drivers/net/synopGMAC_debug.h
new file mode 100644
index 0000000000..c5387d00d8
--- /dev/null
+++ b/bsp/ls2kdev/drivers/net/synopGMAC_debug.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2017-08-24 chinesebear first version
+ */
+
+#ifndef __DEBUG_H__
+#define __DEBUG_H__
+
+//#define GMAC_DEBUG
+#include <rtthread.h>
+#ifdef GMAC_DEBUG
+#define DEBUG_MES rt_kprintf
+#else
+#define DEBUG_MES(...)
+#endif
+
+#endif /*__DEBUG_H__*/
diff --git a/bsp/ls2kdev/drivers/net/synopGMAC_network_interface.h b/bsp/ls2kdev/drivers/net/synopGMAC_network_interface.h
new file mode 100644
index 0000000000..5cb0c6d6d3
--- /dev/null
+++ b/bsp/ls2kdev/drivers/net/synopGMAC_network_interface.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2017-08-24 chinesebear first version
+ */
+
+#ifndef SYNOP_GMAC_NETWORK_INTERFACE_H
+#define SYNOP_GMAC_NETWORK_INTERFACE_H 1
+
+#include <lwip/sys.h>
+#include <netif/ethernetif.h>
+#include "synopGMAC_plat.h"
+#include "synopGMAC_Host.h"
+#include "synopGMAC_Dev.h"
+
+#define NET_IF_TIMEOUT (10*HZ)
+#define CHECK_TIME (HZ)
+
+s32 synopGMAC_init_network_interface(char* xname,u64 synopGMACMappedAddr);
+void synopGMAC_exit_network_interface(void);
+
+s32 synopGMAC_linux_open(struct eth_device *);
+s32 synopGMAC_linux_close(struct eth_device *);
+struct net_device_stats * synopGMAC_linux_get_stats(struct synopGMACNetworkAdapter *);
+
+s32 synopGMAC_test(synopGMACdevice * gmacdev_0,synopGMACdevice * gmacdev_1);
+
+void dumpreg(u64 );
+void dumpphyreg();
+
+/*
+ * gethex(vp,p,n)
+ * convert n hex digits from p to binary, result in vp,
+ * rtn 1 on success
+ */
+static int gethex(u8 *vp, char *p, int n)
+{
+ u8 v;
+ int digit;
+
+ for (v = 0; n > 0; n--) {
+ if (*p == 0)
+ return (0);
+ if (*p >= '0' && *p <= '9')
+ digit = *p - '0';
+ else if (*p >= 'a' && *p <= 'f')
+ digit = *p - 'a' + 10;
+ else if (*p >= 'A' && *p <= 'F')
+ digit = *p - 'A' + 10;
+ else
+ return (0);
+
+ v <<= 4;
+ v |= digit;
+ p++;
+ }
+ *vp = v;
+ return (1);
+}
+
+#endif /* End of file */
diff --git a/bsp/ls2kdev/drivers/net/synopGMAC_plat.c b/bsp/ls2kdev/drivers/net/synopGMAC_plat.c
new file mode 100644
index 0000000000..0c938e9949
--- /dev/null
+++ b/bsp/ls2kdev/drivers/net/synopGMAC_plat.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2017-08-24 chinesebear first version
+ * 2020-08-10 lizhirui porting to ls2k
+ */
+#include "synopGMAC_plat.h"
+#include "synopGMAC_Dev.h"
+#include <rthw.h>
+#include <rtthread.h>
+
+void flush_cache(unsigned long start_addr, unsigned long size)
+{
+ /*r4k_dcache_wback_inv(start_addr,size);
+
+ //rt_kprintf("flush_cache:start_addr = 0x%p,size = 0x%p",start_addr,size);
+ unsigned long new_addr = start_addr - CACHED_MEMORY_ADDR + UNCACHED_MEMORY_ADDR;
+ rt_memcpy(new_addr,start_addr,size);
+
+ if(rt_memcmp(start_addr,new_addr,size) != 0)
+ {
+ rt_kprintf("flush_cache:data isn't matched!\n");
+ while(1);
+ }
+ else
+ {
+ //rt_kprintf("flush_cache:data is matched!\n");
+ }*/
+}
+
+//convert virtual address to physical address
+dma_addr_t __attribute__((weak)) gmac_dmamap(unsigned long va, u32 size)
+{
+ return VA_TO_PA(va);
+ //return UNCACHED_TO_PHYS(va);
+}
+
+/**
+ * This is a wrapper function for Memory allocation routine. In linux Kernel
+ * it it kmalloc function
+ * @param[in] bytes in bytes to allocate
+ */
+
+void *plat_alloc_memory(u32 bytes)
+{
+//return (void*)malloc((size_t)bytes, M_DEVBUF, M_DONTWAIT);
+ void *buf = (void *)rt_malloc((u32)bytes);
+ flush_cache((unsigned long)buf, bytes);
+ return buf;
+}
+
+/**
+ * This is a wrapper function for consistent dma-able Memory allocation routine.
+ * In linux Kernel, it depends on pci dev structure
+ * @param[in] bytes in bytes to allocate
+ */
+
+//allocate a space aligned to 16-byte boundary without cache
+void *plat_alloc_consistent_dmaable_memory(synopGMACdevice *pcidev, u32 size, u32 *addr)
+{
+ void *buf;
+ buf = (void *)rt_malloc((u32)(size + 16));
+ //CPU_IOFlushDCache( buf,size, SYNC_W);
+ unsigned long i = (unsigned long)buf;
+// rt_kprintf("size = %d\n", size);
+// rt_kprintf("bufaddr = %p\n", buf);
+// rt_kprintf("i%%16 == %d\n", i%16);
+ if (i % 16 == 8)
+ {
+ i += 8;
+ }
+ else if (i % 16 == 4)
+ {
+ i += 12;
+ }
+ else if (i % 16 == 12)
+ {
+ i += 4;
+ }
+
+ flush_cache(i, size);
+ *addr = gmac_dmamap(i, size);
+ buf = (unsigned char *)CACHED_TO_UNCACHED(i);
+ //rt_kprintf("bufaddr = %p\n", buf);
+ return buf;
+}
+
+/**
+ * This is a wrapper function for freeing consistent dma-able Memory.
+ * In linux Kernel, it depends on pci dev structure
+ * @param[in] bytes in bytes to allocate
+ */
+//void plat_free_consistent_dmaable_memory(void * addr)
+void plat_free_consistent_dmaable_memory(synopGMACdevice *pcidev, u32 size, void *addr, u64 dma_addr)
+{
+ rt_free((void *)PHYS_TO_CACHED(UNCACHED_TO_PHYS(addr)));
+ return;
+}
+
+/**
+ * This is a wrapper function for Memory free routine. In linux Kernel
+ * it it kfree function
+ * @param[in] buffer pointer to be freed
+ */
+void plat_free_memory(void *buffer)
+{
+ rt_free(buffer);
+ return ;
+}
+
+//convert virtual address to physical address and flush cache
+dma_addr_t plat_dma_map_single(void *hwdev, void *ptr, u32 size)
+{
+ unsigned long addr = (unsigned long) ptr;
+ //CPU_IOFlushDCache(addr,size, direction);
+ flush_cache(addr, size);
+ return gmac_dmamap(addr, size);
+}
+
+/**
+ * This is a wrapper function for platform dependent delay
+ * Take care while passing the argument to this function
+ * @param[in] buffer pointer to be freed
+ */
+void plat_delay(u32 delay)
+{
+ while (delay--);
+ return;
+}
diff --git a/bsp/ls2kdev/drivers/net/synopGMAC_plat.h b/bsp/ls2kdev/drivers/net/synopGMAC_plat.h
new file mode 100644
index 0000000000..3b6eaca197
--- /dev/null
+++ b/bsp/ls2kdev/drivers/net/synopGMAC_plat.h
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2017-08-24 chinesebear first version
+ * 2020-08-10 lizhirui porting to ls2k
+ */
+
+#ifndef SYNOP_GMAC_PLAT_H
+#define SYNOP_GMAC_PLAT_H 1
+
+/* sw
+#include <linux/kernel.h>
+#include <asm/io.h>
+#include <linux/gfp.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+*/
+#include "synopGMAC_types.h"
+#include "synopGMAC_debug.h"
+//#include "mii.h"
+//#include "GMAC_Pmon.h"
+//#include "synopGMAC_Host.h"
+#include <rtthread.h>
+#include <stdint.h>
+#include "mips_addrspace.h"
+//sw: copy the type define into here
+#define IOCTL_READ_REGISTER SIOCDEVPRIVATE+1
+#define IOCTL_WRITE_REGISTER SIOCDEVPRIVATE+2
+#define IOCTL_READ_IPSTRUCT SIOCDEVPRIVATE+3
+#define IOCTL_READ_RXDESC SIOCDEVPRIVATE+4
+#define IOCTL_READ_TXDESC SIOCDEVPRIVATE+5
+#define IOCTL_POWER_DOWN SIOCDEVPRIVATE+6
+
+#define SYNOP_GMAC0 1
+
+typedef int bool;
+//typedef unsigned long dma_addr_t;
+
+#define KUSEG_ADDR 0x0
+#define CACHED_MEMORY_ADDR KSEG0BASE
+#define UNCACHED_MEMORY_ADDR KSEG0BASE
+#define KSEG2_ADDR KSEG2BASE
+#define MAX_MEM_ADDR KSEG3BASE
+#define RESERVED_ADDR KSEG3BASE
+
+#define CACHED_TO_PHYS(x) ((uint64_t)(x) - CACHED_MEMORY_ADDR)
+#define PHYS_TO_CACHED(x) ((uint64_t)(x) + CACHED_MEMORY_ADDR)
+#define UNCACHED_TO_PHYS(x) ((uint64_t)(x) - UNCACHED_MEMORY_ADDR)
+#define PHYS_TO_UNCACHED(x) ((uint64_t)(x) + UNCACHED_MEMORY_ADDR)
+#define VA_TO_CINDEX(x) (PHYS_TO_CACHED(UNCACHED_TO_PHYS(x)))
+#define CACHED_TO_UNCACHED(x) (PHYS_TO_UNCACHED(CACHED_TO_PHYS(x)))
+
+#define VA_TO_PA(x) CACHED_TO_PHYS(x)
+
+/* sw
+#define TR0(fmt, args...) printk(KERN_CRIT "SynopGMAC: " fmt, ##args)
+
+#ifdef DEBUG
+#undef TR
+# define TR(fmt, args...) printk(KERN_CRIT "SynopGMAC: " fmt, ##args)
+#else
+# define TR(fmt, args...) // not debugging: nothing
+#endif
+*/
+/*
+#define TR0(fmt, args...) printf("SynopGMAC: " fmt, ##args)
+*/
+
+/*
+#ifdef DEBUG
+#undef TR
+# define TR(fmt, args...) printf("SynopGMAC: " fmt, ##args)
+#else
+//# define TR(fmt, args...) // not debugging: nothing
+#define TR(fmt, args...) printf("SynopGMAC: " fmt, ##args)
+#endif
+*/
+
+//sw: nothing to display
+#define TR0(fmt, args...) //rt_kprintf(fmt, ##args)
+#define TR(fmt, args...) //rt_kprintf(fmt, ##args)
+
+//typedef int bool;
+enum synopGMAC_boolean
+ {
+ false = 0,
+ true = 1
+ };
+
+#define DEFAULT_DELAY_VARIABLE 10
+#define DEFAULT_LOOP_VARIABLE 10000
+
+/* There are platform related endian conversions
+ *
+ */
+#define LE32_TO_CPU __le32_to_cpu
+#define BE32_TO_CPU __be32_to_cpu
+#define CPU_TO_LE32 __cpu_to_le32
+
+/* Error Codes */
+#define ESYNOPGMACNOERR 0
+#define ESYNOPGMACNOMEM 1
+#define ESYNOPGMACPHYERR 2
+#define ESYNOPGMACBUSY 3
+
+struct Network_interface_data
+{
+ u32 unit;
+ u64 addr;
+ u32 data;
+};
+
+
+/**
+ * These are the wrapper function prototypes for OS/platform related routines
+ */
+void * plat_alloc_memory(u32 );
+void plat_free_memory(void *);
+
+//void * plat_alloc_consistent_dmaable_memory(struct pci_dev *, u32, u32 *);
+//void plat_free_consistent_dmaable_memory (struct pci_dev *, u32, void *, u32);
+void plat_delay(u32);
+
+
+/**
+ * The Low level function to read register contents from Hardware.
+ *
+ * @param[in] pointer to the base of register map
+ * @param[in] Offset from the base
+ * \return Returns the register contents
+ */
+static u32 synopGMACReadReg(u64 RegBase, u32 RegOffset)
+{
+ u64 addr;
+ u32 data;
+
+ addr = RegBase + (u32)RegOffset;
+ data = *(volatile u32 *)addr;
+
+#if SYNOP_REG_DEBUG
+ TR("%s RegBase = 0x%08x RegOffset = 0x%08x RegData = 0x%08x\n", __FUNCTION__, (u32)RegBase, RegOffset, data );
+#endif
+ // rt_kprintf("%s RegBase = 0x%08x RegOffset = 0x%08x RegData = 0x%08x\n", __FUNCTION__, (u32)RegBase, RegOffset, data );
+ return data;
+
+}
+
+/**
+ * The Low level function to write to a register in Hardware.
+ *
+ * @param[in] pointer to the base of register map
+ * @param[in] Offset from the base
+ * @param[in] Data to be written
+ * \return void
+ */
+static void synopGMACWriteReg(u64 RegBase, u32 RegOffset, u32 RegData )
+{
+ u64 addr;
+ addr = RegBase + (u32)RegOffset;
+// rt_kprintf("%s RegBase = 0x%08x RegOffset = 0x%08x RegData = 0x%08x\n", __FUNCTION__,(u32) RegBase, RegOffset, RegData );
+#if SYNOP_REG_DEBUG
+ TR("%s RegBase = 0x%p RegOffset = 0x%08x RegData = 0x%08x\n", __FUNCTION__,(u32) RegBase, RegOffset, RegData );
+#endif
+ *(volatile u32 *)addr = RegData;
+ /*if(addr == 0xbfe1100c)
+ DEBUG_MES("regdata = %08x\n", RegData);*/
+ return;
+}
+
+/**
+ * The Low level function to set bits of a register in Hardware.
+ *
+ * @param[in] pointer to the base of register map
+ * @param[in] Offset from the base
+ * @param[in] Bit mask to set bits to logical 1
+ * \return void
+ */
+static void synopGMACSetBits(u64 RegBase, u32 RegOffset, u32 BitPos)
+{
+ //u64 addr = (u64)RegBase + (u64)RegOffset;
+ u32 data;
+ data = synopGMACReadReg(RegBase, RegOffset);
+ data |= BitPos;
+ synopGMACWriteReg(RegBase, RegOffset, data);
+ // writel(data,(void *)addr);
+ #if SYNOP_REG_DEBUG
+ TR("%s !!!!!!!!!!!!! RegOffset = 0x%08x RegData = 0x%08x\n", __FUNCTION__, RegOffset, data );
+ #endif
+ return;
+}
+
+
+/**
+ * The Low level function to clear bits of a register in Hardware.
+ *
+ * @param[in] pointer to the base of register map
+ * @param[in] Offset from the base
+ * @param[in] Bit mask to clear bits to logical 0
+ * \return void
+ */
+static void synopGMACClearBits(u64 RegBase, u32 RegOffset, u32 BitPos)
+{
+ u32 data;
+ data = synopGMACReadReg(RegBase, RegOffset);
+ data &= (~BitPos);
+ synopGMACWriteReg(RegBase, RegOffset, data);
+ #if SYNOP_REG_DEBUG
+ TR("%s !!!!!!!!!!!!! RegOffset = 0x%08x RegData = 0x%08x\n", __FUNCTION__, RegOffset, data );
+ #endif
+ return;
+}
+
+/**
+ * The Low level function to Check the setting of the bits.
+ *
+ * @param[in] pointer to the base of register map
+ * @param[in] Offset from the base
+ * @param[in] Bit mask to set bits to logical 1
+ * \return returns TRUE if set to '1' returns FALSE if set to '0'. Result undefined there are no bit set in the BitPos argument.
+ *
+ */
+static bool synopGMACCheckBits(u64 RegBase, u32 RegOffset, u32 BitPos)
+{
+ u32 data;
+ data = synopGMACReadReg(RegBase, RegOffset);
+ data &= BitPos;
+
+ if(data)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+#endif
diff --git a/bsp/ls2kdev/drivers/net/synopGMAC_types.h b/bsp/ls2kdev/drivers/net/synopGMAC_types.h
new file mode 100644
index 0000000000..52c7870905
--- /dev/null
+++ b/bsp/ls2kdev/drivers/net/synopGMAC_types.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2017-08-24 chinesebear first version
+ */
+
+#ifndef __TYPES__H
+#define __TYPES__H
+
+typedef unsigned char uint8_t;
+typedef unsigned long long u64;
+typedef unsigned int u32;
+typedef unsigned short u16;
+typedef unsigned char u8;
+typedef signed int s32;
+
+typedef u32 dma_addr_t;
+
+#endif /*__TYPES__H*/
diff --git a/bsp/ls2kdev/drivers/pci/SConscript b/bsp/ls2kdev/drivers/pci/SConscript
new file mode 100644
index 0000000000..6c6d2c7adb
--- /dev/null
+++ b/bsp/ls2kdev/drivers/pci/SConscript
@@ -0,0 +1,10 @@
+from building import *
+
+cwd = GetCurrentDir()
+src = Glob('*.c')
+
+CPPPATH = [cwd]
+
+group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/ls2kdev/drivers/pci/pci.c b/bsp/ls2kdev/drivers/pci/pci.c
new file mode 100644
index 0000000000..7f62e88dc7
--- /dev/null
+++ b/bsp/ls2kdev/drivers/pci/pci.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2020-12-28 lizhirui first version
+ */
+
+#include <rtthread.h>
+#include <pci.h>
+
+rt_uint64_t pci_get_device_map_addr(rt_uint64_t bus,rt_uint64_t device,rt_uint64_t function,rt_uint32_t index)
+{
+
+ rt_uint64_t device_addr = 0xFE00000000 | (bus << 16) | ((device & 0x1f) << 11) | ((function & 0x07) << 8);
+ struct pci_header *p = (struct pci_header *)(0x9000000000000000UL | device_addr);
+ return 0x9000000000000000UL | ((rt_uint64_t)(p -> BaseAddressRegister[index] & 0xFFFFFFF0));
+}
diff --git a/bsp/ls2kdev/drivers/pci/pci.h b/bsp/ls2kdev/drivers/pci/pci.h
new file mode 100644
index 0000000000..db4b3a0185
--- /dev/null
+++ b/bsp/ls2kdev/drivers/pci/pci.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2020-12-28 lizhirui first version
+ */
+
+#ifndef __PCI_H__
+#define __PCI_H__
+
+ struct pci_header
+ {
+ rt_uint16_t VendorID;
+ rt_uint16_t DeviceID;
+ rt_uint16_t Command;
+ rt_uint16_t Status;
+ rt_uint32_t RevisionID : 8;
+ rt_uint32_t ClassCode : 24;
+ rt_uint8_t CachelineSize;
+ rt_uint8_t LatencyTimer;
+ rt_uint8_t HeaderType;
+ rt_uint8_t BIST;
+ rt_uint32_t BaseAddressRegister[6];
+ rt_uint32_t CardbusCISPointer;
+ rt_uint16_t SubsystemVendorID;
+ rt_uint16_t SubsystemID;
+ rt_uint32_t ExpansionROMBaseAddress;
+ rt_uint32_t CapabilitiesPointer : 8;
+ rt_uint32_t resv1 : 24;
+ rt_uint32_t resv2;
+ rt_uint8_t InterruptLine;
+ rt_uint8_t InterruptPin;
+ rt_uint8_t Min_Gnt;
+ rt_uint8_t Max_Lat;
+ };
+
+ rt_uint64_t pci_get_device_map_addr(rt_uint64_t bus,rt_uint64_t device,rt_uint64_t function,rt_uint32_t index);
+
+#endif
diff --git a/bsp/ls2kdev/ls2k_ram.lds b/bsp/ls2kdev/ls2k_ram.lds
index 8bec1e855b..313a52969c 100644
--- a/bsp/ls2kdev/ls2k_ram.lds
+++ b/bsp/ls2kdev/ls2k_ram.lds
@@ -78,6 +78,23 @@ SECTIONS
*(.sdata.*)
}
+ . = 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__ = .);
+ }
+
.stack :
{
. = ALIGN(8);
diff --git a/bsp/ls2kdev/rtconfig.h b/bsp/ls2kdev/rtconfig.h
index aaeed71df5..4fd46f8874 100644
--- a/bsp/ls2kdev/rtconfig.h
+++ b/bsp/ls2kdev/rtconfig.h
@@ -6,16 +6,16 @@
/* RT-Thread Kernel */
-#define RT_NAME_MAX 8
-#define RT_ALIGN_SIZE 4
+#define RT_NAME_MAX 30
+#define RT_ALIGN_SIZE 8
#define RT_THREAD_PRIORITY_32
#define RT_THREAD_PRIORITY_MAX 32
-#define RT_TICK_PER_SECOND 100
+#define RT_TICK_PER_SECOND 1000
#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 2048
+#define IDLE_THREAD_STACK_SIZE 16384
#define RT_DEBUG
/* Inter-Thread communication */
@@ -37,15 +37,16 @@
#define RT_USING_DEVICE
#define RT_USING_CONSOLE
#define RT_CONSOLEBUF_SIZE 256
-#define RT_CONSOLE_DEVICE_NAME "uart"
+#define RT_CONSOLE_DEVICE_NAME "uart0"
#define RT_VER_NUM 0x40003
+#define ARCH_CPU_64BIT
#define ARCH_MIPS64
/* RT-Thread Components */
#define RT_USING_COMPONENTS_INIT
#define RT_USING_USER_MAIN
-#define RT_MAIN_THREAD_STACK_SIZE 2048
+#define RT_MAIN_THREAD_STACK_SIZE 16384
#define RT_MAIN_THREAD_PRIORITY 10
/* C++ features */
@@ -60,7 +61,7 @@
#define FINSH_USING_SYMTAB
#define FINSH_USING_DESCRIPTION
#define FINSH_THREAD_PRIORITY 20
-#define FINSH_THREAD_STACK_SIZE 4096
+#define FINSH_THREAD_STACK_SIZE 16384
#define FINSH_CMD_SIZE 80
#define FINSH_USING_MSH
#define FINSH_USING_MSH_DEFAULT
@@ -68,15 +69,39 @@
/* Device virtual file system */
+#define RT_USING_DFS
+#define DFS_USING_WORKDIR
+#define DFS_FILESYSTEMS_MAX 10
+#define DFS_FILESYSTEM_TYPES_MAX 10
+#define DFS_FD_MAX 16
+#define RT_USING_DFS_ELMFAT
+
+/* elm-chan's FatFs, Generic FAT Filesystem Module */
+
+#define RT_DFS_ELM_CODE_PAGE 936
+#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 9
+#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_SYSTEM_WORKQUEUE
+#define RT_SYSTEM_WORKQUEUE_STACKSIZE 16384
+#define RT_SYSTEM_WORKQUEUE_PRIORITY 5
#define RT_USING_SERIAL
#define RT_SERIAL_USING_DMA
#define RT_SERIAL_RB_BUFSZ 64
#define RT_USING_PIN
+#define RT_USING_SPI
/* Using USB */
@@ -84,17 +109,76 @@
/* POSIX layer and C standard library */
#define RT_USING_LIBC
+#define RT_USING_POSIX
/* Network */
/* Socket abstraction layer */
+#define RT_USING_SAL
+#define SAL_INTERNET_CHECK
+
+/* protocol stack implement */
+
+#define SAL_USING_LWIP
+#define SAL_SOCKETS_NUM 16
/* 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_LWIP202
+#define RT_LWIP_MEM_ALIGNMENT 8
+#define RT_LWIP_IGMP
+#define RT_LWIP_ICMP
+#define RT_LWIP_SNMP
+#define RT_LWIP_DNS
+#define RT_LWIP_DHCP
+#define IP_SOF_BROADCAST 1
+#define IP_SOF_BROADCAST_RECV 1
+
+/* Static IPv4 Address */
+
+#define RT_LWIP_IPADDR "192.168.1.30"
+#define RT_LWIP_GWADDR "192.168.1.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 5
+#define RT_LWIP_TCPTHREAD_MBOX_SIZE 32
+#define RT_LWIP_TCPTHREAD_STACKSIZE 16384
+#define RT_LWIP_ETHTHREAD_PRIORITY 5
+#define RT_LWIP_ETHTHREAD_STACKSIZE 16384
+#define RT_LWIP_ETHTHREAD_MBOX_SIZE 32
+#define RT_LWIP_REASSEMBLY_FRAG
+#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_STATS
+#define RT_LWIP_USING_PING
/* AT commands */
@@ -147,12 +231,8 @@
/* samples: kernel and components samples */
-
-/* Privated Packages of RealThread */
-
-
-/* Network Utilities */
-
#define SOC_LS2K1000
+#define RT_USING_UART0
+#define RT_USING_UART4
#endif
diff --git a/bsp/ls2kdev/rtconfig.py b/bsp/ls2kdev/rtconfig.py
index c8490a382f..0988198426 100644
--- a/bsp/ls2kdev/rtconfig.py
+++ b/bsp/ls2kdev/rtconfig.py
@@ -31,6 +31,7 @@ BUILD = 'debug'
PREFIX = 'mips-sde-elf-'
CC = PREFIX + 'gcc'
+CXX = PREFIX + 'g++'
AS = PREFIX + 'gcc'
AR = PREFIX + 'ar'
LINK = PREFIX + 'gcc'
@@ -40,7 +41,7 @@ OBJDUMP = PREFIX + 'objdump'
OBJCPY = PREFIX + 'objcopy'
READELF = PREFIX + 'readelf'
-DEVICE = ' -march=mips64r2 -mabi=64 -msoft-float -EL'
+DEVICE = ' -march=mips64r2 -mabi=64 -msoft-float -EL -mno-gpopt'
CFLAGS = DEVICE + ' -G0 -mno-abicalls -fno-pic -fno-builtin -fno-exceptions -ffunction-sections -fomit-frame-pointer'
AFLAGS = ' -c' + DEVICE + ' -fno-pic -fno-builtin -mno-abicalls -x assembler-with-cpp'
LFLAGS = DEVICE + ' -nostartfiles -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,Reset_Handler -T ls2k_ram.lds'