浏览代码

Merge pull request #4683 from Wang-Huachen/master

add ethernet driver for zynqmp-r5-axu4ev
Bernard Xiong 4 年之前
父节点
当前提交
a0175e3d15
共有 70 个文件被更改,包括 15079 次插入3625 次删除
  1. 186 23
      bsp/zynqmp-r5-axu4ev/.config
  2. 19 1
      bsp/zynqmp-r5-axu4ev/README.md
  3. 8 1
      bsp/zynqmp-r5-axu4ev/README_zh.md
  4. 1 1
      bsp/zynqmp-r5-axu4ev/applications/SConscript
  5. 13 0
      bsp/zynqmp-r5-axu4ev/drivers/Kconfig
  6. 3 0
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/SConscript
  7. 15 0
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/SConscript
  8. 480 0
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps.c
  9. 836 0
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps.h
  10. 762 0
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bd.h
  11. 1076 0
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bdring.c
  12. 215 0
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bdring.h
  13. 1133 0
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_control.c
  14. 32 0
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_g.c
  15. 97 0
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.c
  16. 646 0
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.h
  17. 242 0
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_intr.c
  18. 71 0
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_sinit.c
  19. 340 340
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops.c
  20. 64 64
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops.h
  21. 6 6
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_g.c
  22. 7 7
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_hw.c
  23. 28 28
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_hw.h
  24. 361 361
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_intr.c
  25. 49 49
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_selftest.c
  26. 14 14
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_sinit.c
  27. 207 207
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps.c
  28. 80 80
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps.h
  29. 438 438
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_card.c
  30. 24 24
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_g.c
  31. 442 442
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_host.c
  32. 525 525
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_hw.h
  33. 401 401
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_options.c
  34. 12 12
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_sinit.c
  35. 5 5
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sleep.h
  36. 15 0
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/SConscript
  37. 90 0
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xadapter.h
  38. 163 0
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xemacpsif.h
  39. 54 0
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xpqueue.h
  40. 58 0
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xtopology.h
  41. 409 0
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xadapter.c
  42. 101 0
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemac_ieee_reg.h
  43. 756 0
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif.c
  44. 869 0
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_dma.c
  45. 276 0
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_hw.c
  46. 49 0
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_hw.h
  47. 1152 0
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_physpeed.c
  48. 44 0
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xlwipconfig.h
  49. 93 0
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xpqueue.c
  50. 15 0
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xtopology_g.c
  51. 34 34
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_io.h
  52. 1 1
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_printf.h
  53. 16 13
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_types.h
  54. 9 9
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xparameters.h
  55. 208 208
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xparameters_ps.h
  56. 9 9
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xplatform_info.h
  57. 265 265
      bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xstatus.h
  58. 349 0
      bsp/zynqmp-r5-axu4ev/drivers/drv_eth.c
  59. 13 0
      bsp/zynqmp-r5-axu4ev/drivers/drv_eth.h
  60. 8 8
      bsp/zynqmp-r5-axu4ev/drivers/drv_sdcard.c
  61. 2 2
      bsp/zynqmp-r5-axu4ev/drivers/drv_timer.c
  62. 7 7
      bsp/zynqmp-r5-axu4ev/drivers/drv_uart.c
  63. 5 5
      bsp/zynqmp-r5-axu4ev/drivers/zynqmp-r5.h
  64. 82 5
      bsp/zynqmp-r5-axu4ev/rtconfig.h
  65. 2 2
      bsp/zynqmp-r5-axu4ev/rtconfig.py
  66. 263 28
      libcpu/arm/zynqmp-r5/cache.c
  67. 4 0
      libcpu/arm/zynqmp-r5/start_gcc.S
  68. 54 0
      libcpu/arm/zynqmp-r5/xil_mmu.h
  69. 637 0
      libcpu/arm/zynqmp-r5/xil_mpu.c
  70. 129 0
      libcpu/arm/zynqmp-r5/xil_mpu.h

+ 186 - 23
bsp/zynqmp-r5-axu4ev/.config

@@ -23,6 +23,12 @@ CONFIG_IDLE_THREAD_STACK_SIZE=512
 CONFIG_RT_USING_TIMER_SOFT=y
 CONFIG_RT_TIMER_THREAD_PRIO=4
 CONFIG_RT_TIMER_THREAD_STACK_SIZE=512
+
+#
+# kservice optimization
+#
+# CONFIG_RT_KSERVICE_USING_STDLIB is not set
+# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set
 CONFIG_RT_DEBUG=y
 # CONFIG_RT_DEBUG_COLOR is not set
 # CONFIG_RT_DEBUG_INIT_CONFIG is not set
@@ -52,8 +58,9 @@ CONFIG_RT_USING_MESSAGEQUEUE=y
 CONFIG_RT_USING_MEMPOOL=y
 # CONFIG_RT_USING_MEMHEAP is not set
 # CONFIG_RT_USING_NOHEAP is not set
-CONFIG_RT_USING_SMALL_MEM=y
-# CONFIG_RT_USING_SLAB is not set
+# CONFIG_RT_USING_SMALL_MEM is not set
+CONFIG_RT_USING_SLAB=y
+# CONFIG_RT_USING_USERHEAP is not set
 # CONFIG_RT_USING_MEMTRACE is not set
 CONFIG_RT_USING_HEAP=y
 
@@ -66,7 +73,7 @@ CONFIG_RT_USING_DEVICE=y
 CONFIG_RT_USING_CONSOLE=y
 CONFIG_RT_CONSOLEBUF_SIZE=128
 CONFIG_RT_CONSOLE_DEVICE_NAME="uart0"
-CONFIG_RT_VER_NUM=0x40003
+CONFIG_RT_VER_NUM=0x40004
 # CONFIG_RT_USING_CPU_FFS is not set
 # CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set
 
@@ -123,6 +130,11 @@ CONFIG_RT_DFS_ELM_WORD_ACCESS=y
 # CONFIG_RT_DFS_ELM_USE_LFN_2 is not set
 CONFIG_RT_DFS_ELM_USE_LFN_3=y
 CONFIG_RT_DFS_ELM_USE_LFN=3
+CONFIG_RT_DFS_ELM_LFN_UNICODE_0=y
+# CONFIG_RT_DFS_ELM_LFN_UNICODE_1 is not set
+# CONFIG_RT_DFS_ELM_LFN_UNICODE_2 is not set
+# CONFIG_RT_DFS_ELM_LFN_UNICODE_3 is not set
+CONFIG_RT_DFS_ELM_LFN_UNICODE=0
 CONFIG_RT_DFS_ELM_MAX_LFN=255
 CONFIG_RT_DFS_ELM_DRIVES=2
 CONFIG_RT_DFS_ELM_MAX_SECTOR_SIZE=512
@@ -131,15 +143,16 @@ 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=2048
+CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23
 CONFIG_RT_USING_SERIAL=y
 CONFIG_RT_SERIAL_USING_DMA=y
 CONFIG_RT_SERIAL_RB_BUFSZ=64
@@ -147,6 +160,7 @@ 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
@@ -172,11 +186,6 @@ CONFIG_RT_USING_PIN=y
 # CONFIG_RT_USING_USB_HOST is not set
 # CONFIG_RT_USING_USB_DEVICE is not set
 
-#
-# Using RapidIO
-#
-# CONFIG_RT_USING_RAPIDIO is not set
-
 #
 # POSIX layer and C standard library
 #
@@ -188,6 +197,7 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_RT_USING_POSIX_GETLINE is not set
 # CONFIG_RT_USING_POSIX_AIO is not set
 # CONFIG_RT_USING_MODULE is not set
+CONFIG_RT_LIBC_FIXED_TIMEZONE=8
 
 #
 # Network
@@ -196,22 +206,91 @@ CONFIG_RT_USING_POSIX=y
 #
 # Socket abstraction layer
 #
-# CONFIG_RT_USING_SAL is not set
+CONFIG_RT_USING_SAL=y
+CONFIG_SAL_INTERNET_CHECK=y
+
+#
+# protocol stack implement
+#
+CONFIG_SAL_USING_LWIP=y
+CONFIG_SAL_USING_POSIX=y
 
 #
 # 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=32
+CONFIG_RT_LWIP_IGMP=y
+CONFIG_RT_LWIP_ICMP=y
+# CONFIG_RT_LWIP_SNMP is not set
+CONFIG_RT_LWIP_DNS=y
+CONFIG_RT_LWIP_DHCP=y
+CONFIG_IP_SOF_BROADCAST=1
+CONFIG_IP_SOF_BROADCAST_RECV=1
+
+#
+# Static IPv4 Address
+#
+CONFIG_RT_LWIP_IPADDR="192.168.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=256
+CONFIG_RT_LWIP_RAW_PCB_NUM=4
+CONFIG_RT_LWIP_UDP_PCB_NUM=4
+CONFIG_RT_LWIP_TCP_PCB_NUM=4
+CONFIG_RT_LWIP_TCP_SEG_NUM=40
+CONFIG_RT_LWIP_TCP_SND_BUF=8196
+CONFIG_RT_LWIP_TCP_WND=8196
+CONFIG_RT_LWIP_TCPTHREAD_PRIORITY=10
+CONFIG_RT_LWIP_TCPTHREAD_MBOX_SIZE=8
+CONFIG_RT_LWIP_TCPTHREAD_STACKSIZE=2048
+# CONFIG_LWIP_NO_RX_THREAD is not set
+# CONFIG_LWIP_NO_TX_THREAD is not set
+CONFIG_RT_LWIP_ETHTHREAD_PRIORITY=12
+CONFIG_RT_LWIP_ETHTHREAD_STACKSIZE=1024
+CONFIG_RT_LWIP_ETHTHREAD_MBOX_SIZE=8
+# CONFIG_RT_LWIP_REASSEMBLY_FRAG is not set
+CONFIG_LWIP_NETIF_STATUS_CALLBACK=1
+CONFIG_LWIP_NETIF_LINK_CALLBACK=1
+CONFIG_SO_REUSE=1
+CONFIG_LWIP_SO_RCVTIMEO=1
+CONFIG_LWIP_SO_SNDTIMEO=1
+CONFIG_LWIP_SO_RCVBUF=1
+CONFIG_LWIP_SO_LINGER=0
+# CONFIG_RT_LWIP_NETIF_LOOPBACK is not set
+CONFIG_LWIP_NETIF_LOOPBACK=0
+# CONFIG_RT_LWIP_STATS is not set
+# CONFIG_RT_LWIP_USING_HW_CHECKSUM is not set
+CONFIG_RT_LWIP_USING_PING=y
+# CONFIG_RT_LWIP_DEBUG is not set
 
 #
 # AT commands
 #
 # CONFIG_RT_USING_AT is not set
+# CONFIG_LWIP_USING_DHCPD is not set
 
 #
 # VBUS(Virtual Software BUS)
@@ -225,6 +304,11 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_RT_USING_ULOG is not set
 # CONFIG_RT_USING_UTEST is not set
 
+#
+# RT-Thread Utestcases
+#
+# CONFIG_RT_USING_UTESTCASES is not set
+
 #
 # RT-Thread online packages
 #
@@ -292,8 +376,6 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_LIBRWS is not set
 # CONFIG_PKG_USING_TCPSERVER is not set
 # CONFIG_PKG_USING_PROTOBUF_C is not set
-# CONFIG_PKG_USING_ONNX_PARSER is not set
-# CONFIG_PKG_USING_ONNX_BACKEND is not set
 # CONFIG_PKG_USING_DLT645 is not set
 # CONFIG_PKG_USING_QXWZ is not set
 # CONFIG_PKG_USING_SMTP_CLIENT is not set
@@ -307,6 +389,13 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_PDULIB is not set
 # CONFIG_PKG_USING_BTSTACK is not set
 # CONFIG_PKG_USING_LORAWAN_ED_STACK is not set
+# CONFIG_PKG_USING_WAYZ_IOTKIT is not set
+# CONFIG_PKG_USING_MAVLINK is not set
+# CONFIG_PKG_USING_RAPIDJSON is not set
+# CONFIG_PKG_USING_BSAL is not set
+# CONFIG_PKG_USING_AGILE_MODBUS is not set
+# CONFIG_PKG_USING_AGILE_FTP is not set
+# CONFIG_PKG_USING_EMBEDDEDPROTO is not set
 
 #
 # security packages
@@ -332,8 +421,11 @@ CONFIG_RT_USING_POSIX=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_PDFGEN is not set
 # CONFIG_PKG_USING_HELIX is not set
 # CONFIG_PKG_USING_AZUREGUIX is not set
+# CONFIG_PKG_USING_TOUCHGFX2RTT is not set
+# CONFIG_PKG_USING_NUEMWIN is not set
 
 #
 # tools packages
@@ -345,6 +437,8 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_RDB is not set
 # CONFIG_PKG_USING_QRCODE is not set
 # CONFIG_PKG_USING_ULOG_EASYFLASH is not set
+# CONFIG_PKG_USING_ULOG_FILE is not set
+# CONFIG_PKG_USING_LOGMGR is not set
 # CONFIG_PKG_USING_ADBD is not set
 # CONFIG_PKG_USING_COREMARK is not set
 # CONFIG_PKG_USING_DHRYSTONE is not set
@@ -357,6 +451,22 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_URLENCODE is not set
 # CONFIG_PKG_USING_UMCN is not set
 # CONFIG_PKG_USING_LWRB2RTT is not set
+# CONFIG_PKG_USING_CPU_USAGE is not set
+# CONFIG_PKG_USING_GBK2UTF8 is not set
+# CONFIG_PKG_USING_VCONSOLE is not set
+# CONFIG_PKG_USING_KDB is not set
+# CONFIG_PKG_USING_WAMR is not set
+# CONFIG_PKG_USING_MICRO_XRCE_DDS_CLIENT is not set
+# CONFIG_PKG_USING_LWLOG is not set
+# CONFIG_PKG_USING_ANV_TRACE is not set
+# CONFIG_PKG_USING_ANV_MEMLEAK is not set
+# CONFIG_PKG_USING_ANV_TESTSUIT is not set
+# CONFIG_PKG_USING_ANV_BENCH is not set
+# CONFIG_PKG_USING_DEVMEM is not set
+# CONFIG_PKG_USING_REGEX is not set
+# CONFIG_PKG_USING_MEM_SANDBOX is not set
+# CONFIG_PKG_USING_SOLAR_TERMS is not set
+# CONFIG_PKG_USING_GAN_ZHI is not set
 
 #
 # system packages
@@ -364,7 +474,6 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_GUIENGINE is not set
 # CONFIG_PKG_USING_CAIRO is not set
 # CONFIG_PKG_USING_PIXMAN is not set
-# CONFIG_PKG_USING_LWEXT4 is not set
 # CONFIG_PKG_USING_PARTITION is not set
 # CONFIG_PKG_USING_FAL is not set
 # CONFIG_PKG_USING_FLASHDB is not set
@@ -374,6 +483,9 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_CMSIS is not set
 # CONFIG_PKG_USING_DFS_YAFFS is not set
 # CONFIG_PKG_USING_LITTLEFS is not set
+# CONFIG_PKG_USING_DFS_JFFS2 is not set
+# CONFIG_PKG_USING_DFS_UFFS is not set
+# CONFIG_PKG_USING_LWEXT4 is not set
 # CONFIG_PKG_USING_THREAD_POOL is not set
 # CONFIG_PKG_USING_ROBOTS is not set
 # CONFIG_PKG_USING_EV is not set
@@ -388,11 +500,21 @@ CONFIG_RT_USING_POSIX=y
 # Micrium: Micrium software products porting for RT-Thread
 #
 # CONFIG_PKG_USING_UCOSIII_WRAPPER is not set
+# CONFIG_PKG_USING_UCOSII_WRAPPER is not set
 # CONFIG_PKG_USING_UC_CRC is not set
 # CONFIG_PKG_USING_UC_CLK is not set
 # CONFIG_PKG_USING_UC_COMMON is not set
 # CONFIG_PKG_USING_UC_MODBUS is not set
 # CONFIG_PKG_USING_PPOOL is not set
+# CONFIG_PKG_USING_OPENAMP is not set
+# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set
+# CONFIG_PKG_USING_RT_MEMCPY_CM is not set
+# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set
+# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set
+# CONFIG_PKG_USING_QFPLIB_M3 is not set
+# CONFIG_PKG_USING_LPM is not set
+# CONFIG_PKG_USING_TLSF is not set
+# CONFIG_PKG_USING_EVENT_RECORDER is not set
 
 #
 # peripheral libraries and drivers
@@ -401,6 +523,7 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_REALTEK_AMEBA is not set
 # CONFIG_PKG_USING_SHT2X is not set
 # CONFIG_PKG_USING_SHT3X is not set
+# CONFIG_PKG_USING_AS7341 is not set
 # CONFIG_PKG_USING_STM32_SDIO is not set
 # CONFIG_PKG_USING_ICM20608 is not set
 # CONFIG_PKG_USING_U8G2 is not set
@@ -449,6 +572,30 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_DM9051 is not set
 # CONFIG_PKG_USING_SSD1306 is not set
 # CONFIG_PKG_USING_QKEY is not set
+# CONFIG_PKG_USING_RS485 is not set
+# CONFIG_PKG_USING_NES is not set
+# CONFIG_PKG_USING_VIRTUAL_SENSOR is not set
+# CONFIG_PKG_USING_VDEVICE is not set
+# CONFIG_PKG_USING_SGM706 is not set
+# CONFIG_PKG_USING_STM32WB55_SDK is not set
+# CONFIG_PKG_USING_RDA58XX is not set
+# CONFIG_PKG_USING_LIBNFC is not set
+# CONFIG_PKG_USING_MFOC is not set
+# CONFIG_PKG_USING_TMC51XX is not set
+# CONFIG_PKG_USING_TCA9534 is not set
+
+#
+# AI packages
+#
+# CONFIG_PKG_USING_LIBANN is not set
+# CONFIG_PKG_USING_NNOM is not set
+# CONFIG_PKG_USING_ONNX_BACKEND is not set
+# CONFIG_PKG_USING_ONNX_PARSER is not set
+# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set
+# CONFIG_PKG_USING_ELAPACK is not set
+# CONFIG_PKG_USING_ULAPACK is not set
+# CONFIG_PKG_USING_QUEST is not set
+# CONFIG_PKG_USING_NAXOS is not set
 
 #
 # miscellaneous packages
@@ -458,6 +605,7 @@ CONFIG_RT_USING_POSIX=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
@@ -479,19 +627,24 @@ CONFIG_RT_USING_POSIX=y
 # 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
 # CONFIG_PKG_USING_ARMv7M_DWT is not set
 # CONFIG_PKG_USING_VT100 is not set
-# CONFIG_PKG_USING_TETRIS is not set
-# CONFIG_PKG_USING_ULAPACK is not set
 # CONFIG_PKG_USING_UKAL is not set
 # CONFIG_PKG_USING_CRCLIB is not set
+
+#
+# entertainment: terminal games and other interesting software packages
+#
 # CONFIG_PKG_USING_THREES is not set
 # CONFIG_PKG_USING_2048 is not set
+# CONFIG_PKG_USING_SNAKE is not set
+# CONFIG_PKG_USING_TETRIS is not set
+# CONFIG_PKG_USING_DONUT is not set
+# CONFIG_PKG_USING_ACLOCK is not set
 # CONFIG_PKG_USING_LWGPS is not set
-# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set
+# CONFIG_PKG_USING_STATE_MACHINE is not set
+# CONFIG_PKG_USING_MCURSES is not set
+# CONFIG_PKG_USING_COWSAY is not set
 CONFIG_SOC_ZYNQMP_R5=y
 
 #
@@ -510,6 +663,16 @@ CONFIG_BSP_USING_UART0=y
 CONFIG_BSP_USING_SDIO=y
 CONFIG_BSP_USING_SD0=y
 
+#
+# Please set RT_LWIP_PBUF_NUM is at least 256 if Enable Ethernet!
+#
+
+#
+# Please set RT_LWIP_MEM_ALIGNMENT is at 32 if Enable Ethernet!
+#
+CONFIG_BSP_USING_ETH=y
+CONFIG_RT_LWIP_PBUF_POOL_BUFSIZE=1700
+
 #
 # Board extended module Drivers
 #

+ 19 - 1
bsp/zynqmp-r5-axu4ev/README.md

@@ -35,6 +35,7 @@ Each peripheral supporting condition for this BSP is as follows:
 | UART              |     Support     | UART0                            |
 | TIMER     |     Support     |     TTC0 provides system clock         |
 | EMMC | Support | SD0 Controller |
+| EMAC | Support | e0 Net Interface |
 
 ## Execution Instruction
 
@@ -99,14 +100,31 @@ msh />
 
 This BSP enables EMMC driver and DFS file system by default. If you need to use a file system, you can format and mount it by yourself.
 
+This BSP is enabled and configured with net interface driver and LwIP protocol stack by default, and note the following configuration:
+
+1. Note that `RT_LWIP_PBUF_NUM` is set to at least 256
+
+2. Note that `RT_ LWIP_ MEM_ Alignment` is set to 32. If the version other than lwip 2.0.2 in RTT is used, the `MEM_ALIGNMENT` in `lwipopts.h` needs to be modified manually because the macro is not used in other versions.
+
 ## BSP Migration
 
 If you need to ported the BSP to another development board of Xilinx Zynq UltraScale+ MPSOC development platform, it is also convenient. The main modifications are as follows:
 
-1. Memory: `psu_r5_ddr_0_MEM_0` in `zynqmp-r5.ld` (if DDR memory is less than 2G)
+1. Memory: `psu_r5_ddr_0_MEM_0` in `zynqmp-r5.ld`  and `HEAP_END` in `board.h ` (if DDR memory is less than 2G) 
 2. Main Frequency: `XPAR_CPU_CORTEXR5_0_CPU_CLK_FREQ_HZ` in `zynqmp-r5.h`
 3. Pin and Frequency of Serial Port: `rxmio`, `txmio` and `XPAR_PSU_UART_0_UART_CLK_FREQ_HZ` in `drv_uart.c`
 4. Timer Frequency: `XPAR_PSU_TTC_0_TTC_CLK_FREQ_HZ` in `drv_timer.c`
 5. SD Controller: Block device driver initialization in `drv_sdcard.c`
+6. Net interface: If the PHY chip used is not in the range of driver support, it may be necessary to realize the rate identification function of the corresponding chip in `xemacpsif_physpeed.c`. You can refer to the corresponding tutorial of Alinx.
 
 The parameter macro definition in `xparameters.h` does not need to be modified manually. You can directly copy the `xparameters.h` file of the development board generated in Xilinx Vitis.
+
+## Attention
+
+-None
+
+## Contact
+
+Maintainer:
+
+-  [Wang Huachen](https://github.com/Wang-Huachen/)

+ 8 - 1
bsp/zynqmp-r5-axu4ev/README_zh.md

@@ -32,6 +32,7 @@ AXU4EV-E 开发板是 芯驿电子科技(上海)有限公司 推出的一款
 | UART              |     支持     | UART0                            |
 | TIMER     |     支持     |     TTC0提供系统时钟         |
 | EMMC | 支持 | SD0控制器 |
+| EMAC | 支持 | e0网卡 |
 
 ## 使用说明
 
@@ -107,16 +108,22 @@ msh />
 
 此 BSP 默认开启了 EMMC 驱动和 DFS 文件系统,如果需要使用文件系统可以自行格式化并挂载。
 
+此 BSP 默认开启并配置了网卡驱动及lwip协议栈,相关配置需要注意如下几点:
+
+1. 注意将`RT_LWIP_PBUF_NUM`至少设置为256
+2. 注意将`RT_LWIP_MEM_ALIGNMENT`设置为32。若使用RTT中lwip 2.0.2以外的版本时,由于其他版本未使用该宏,需要手动修改`lwipopts.h`中的`MEM_ALIGNMENT`宏。
+
 
 ## 板级移植
 
 如果需要将BSP移植到其他 XILINX Zynq UltraScale+ MPSoCs 开发平台的开发板上也比较方便,主要修改的地方有以下几点:
 
-1. 内存: 如果 DDR memory 小于 2G,需要修改`zynqmp-r5.ld`链接文件中的`psu_r5_ddr_0_MEM_0` 
+1. 内存: 如果 DDR memory 小于 2G,需要修改`zynqmp-r5.ld`链接文件中的`psu_r5_ddr_0_MEM_0` 以及`board.h`中的`HEAP_END`
 2. 主频: `xparameters.h`中的`XPAR_CPU_CORTEXR5_0_CPU_CLK_FREQ_HZ`
 3. 串口引脚和频率:`drv_uart.c`中的`rxmio`, `txmio` 和`xparameters.h`中的`XPAR_PSU_UART_0_UART_CLK_FREQ_HZ`
 4. 定时器频率:`xparameters.h`中的`XPAR_PSU_TTC_0_TTC_CLK_FREQ_HZ` 
 5. SD控制器:`drv_sdcard.c`中的块设备驱动初始化
+6. 网卡驱动:若使用的PHY芯片不在驱动支持范围内,可能需要在`xemacpsif_physpeed.c`中实现相应芯片的速率识别函数,可参考ALINX的相应教程。
 
 以上需要修改的`xparameters.h`中的参数宏定义不需要手动修改,可以直接将Xilinx Vitis中产生的开发板的`xparameters.h`文件复制过来即可。
 

+ 1 - 1
bsp/zynqmp-r5-axu4ev/applications/SConscript

@@ -3,7 +3,7 @@ Import('rtconfig')
 from building import *
 
 cwd     = os.path.join(str(Dir('#')), 'applications')
-src	= Glob('*.c')
+src    = Glob('*.c')
 CPPPATH = [cwd, str(Dir('#'))]
 
 group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)

+ 13 - 0
bsp/zynqmp-r5-axu4ev/drivers/Kconfig

@@ -24,6 +24,19 @@ menu "Hardware Drivers Config"
                 bool "Enable SD0 EMMC"
                 default y
         endif
+    comment "Please set RT_LWIP_PBUF_NUM is at least 256 if Enable Ethernet!"
+    comment "Please set RT_LWIP_MEM_ALIGNMENT is at 32 if Enable Ethernet!"
+    menuconfig BSP_USING_ETH
+        bool "Enable Ethernet"
+        default n
+        select RT_USING_NETDEV
+        select RT_USING_LWIP
+        if BSP_USING_ETH
+            config RT_LWIP_PBUF_POOL_BUFSIZE
+                int "The size of each pbuf in the pbuf pool"
+                range 1500 2000
+                default 1700
+        endif
 
     endmenu
 

+ 3 - 0
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/SConscript

@@ -11,6 +11,9 @@ if GetDepend('BSP_USING_SDIO'):
     objs = objs + SConscript('sdps_v3_9/SConscript')
 if GetDepend('RT_USING_PIN'):
     objs = objs + SConscript('gpiops_v3_7/SConscript')
+if GetDepend('BSP_USING_ETH'):
+    objs = objs + SConscript('emacps_v3_11/SConscript')
+    objs = objs + SConscript('xemacpsif/SConscript')
 
 objs = objs + group
 

+ 15 - 0
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/SConscript

@@ -0,0 +1,15 @@
+import rtconfig
+from building import *
+
+# get current directory
+cwd = GetCurrentDir()
+CPPPATH = [cwd]
+
+# The set of source files associated with this SConscript file.
+
+src = Glob('*.c')
+path = cwd
+
+group = DefineGroup('ZYNQMP_HAL', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')

+ 480 - 0
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps.c

@@ -0,0 +1,480 @@
+/******************************************************************************
+* Copyright (C) 2010 - 2020 Xilinx, Inc.  All rights reserved.
+* SPDX-License-Identifier: MIT
+******************************************************************************/
+
+/*****************************************************************************/
+/**
+*
+* @file xemacps.c
+* @addtogroup emacps_v3_11
+* @{
+*
+* The XEmacPs driver. Functions in this file are the minimum required functions
+* for this driver. See xemacps.h for a detailed description of the driver.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a wsy  01/10/10 First release
+* 2.1  srt  07/15/14 Add support for Zynq Ultrascale Mp GEM specification and
+*              64-bit changes.
+* 3.00 kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.0  hk   02/20/15 Added support for jumbo frames. Increase AHB burst.
+*                    Disable extended mode. Perform all 64 bit changes under
+*                    check for arch64.
+* 3.1  hk   08/10/15 Update upper 32 bit tx and rx queue ptr registers
+* 3.5  hk   08/14/17 Update cache coherency information of the interface in
+*                    its config structure.
+* 3.8  hk   09/17/18 Cleanup stale comments.
+* 3.8  mus  11/05/18 Support 64 bit DMA addresses for Microblaze-X platform.
+* 3.10 hk   05/16/19 Clear status registers properly in reset
+* 3.11 sd   02/14/20 Add clock support
+*
+* </pre>
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xemacps.h"
+
+/************************** Constant Definitions *****************************/
+
+
+/**************************** Type Definitions *******************************/
+
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+
+/************************** Function Prototypes ******************************/
+
+void XEmacPs_StubHandler(void);    /* Default handler routine */
+
+/************************** Variable Definitions *****************************/
+
+
+/*****************************************************************************/
+/**
+* Initialize a specific XEmacPs instance/driver. The initialization entails:
+* - Initialize fields of the XEmacPs instance structure
+* - Reset hardware and apply default options
+* - Configure the DMA channels
+*
+* The PHY is setup independently from the device. Use the MII or whatever other
+* interface may be present for setup.
+*
+* @param InstancePtr is a pointer to the instance to be worked on.
+* @param CfgPtr is the device configuration structure containing required
+*        hardware build data.
+* @param EffectiveAddress is the base address of the device. If address
+*        translation is not utilized, this parameter can be passed in using
+*        CfgPtr->Config.BaseAddress to specify the physical base address.
+*
+* @return
+* - XST_SUCCESS if initialization was successful
+*
+******************************************************************************/
+LONG XEmacPs_CfgInitialize(XEmacPs *InstancePtr, XEmacPs_Config * CfgPtr,
+               UINTPTR EffectiveAddress)
+{
+    /* Verify arguments */
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(CfgPtr != NULL);
+
+    /* Set device base address and ID */
+    InstancePtr->Config.DeviceId = CfgPtr->DeviceId;
+    InstancePtr->Config.BaseAddress = EffectiveAddress;
+    InstancePtr->Config.IsCacheCoherent = CfgPtr->IsCacheCoherent;
+#if defined  (XCLOCKING)
+    InstancePtr->Config.RefClk = CfgPtr->RefClk;
+#endif
+
+    /* Set callbacks to an initial stub routine */
+    InstancePtr->SendHandler = ((XEmacPs_Handler)((void*)XEmacPs_StubHandler));
+    InstancePtr->RecvHandler = ((XEmacPs_Handler)(void*)XEmacPs_StubHandler);
+    InstancePtr->ErrorHandler = ((XEmacPs_ErrHandler)(void*)XEmacPs_StubHandler);
+
+    /* Reset the hardware and set default options */
+    InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
+    XEmacPs_Reset(InstancePtr);
+
+    return (LONG)(XST_SUCCESS);
+}
+
+
+/*****************************************************************************/
+/**
+* Start the Ethernet controller as follows:
+*   - Enable transmitter if XTE_TRANSMIT_ENABLE_OPTION is set
+*   - Enable receiver if XTE_RECEIVER_ENABLE_OPTION is set
+*   - Start the SG DMA send and receive channels and enable the device
+*     interrupt
+*
+* @param InstancePtr is a pointer to the instance to be worked on.
+*
+* @return N/A
+*
+* @note
+* Hardware is configured with scatter-gather DMA, the driver expects to start
+* the scatter-gather channels and expects that the user has previously set up
+* the buffer descriptor lists.
+*
+* This function makes use of internal resources that are shared between the
+* Start, Stop, and Set/ClearOptions functions. So if one task might be setting
+* device options while another is trying to start the device, the user is
+* required to provide protection of this shared data (typically using a
+* semaphore).
+*
+* This function must not be preempted by an interrupt that may service the
+* device.
+*
+******************************************************************************/
+void XEmacPs_Start(XEmacPs *InstancePtr)
+{
+    u32 Reg;
+
+    /* Assert bad arguments and conditions */
+    Xil_AssertVoid(InstancePtr != NULL);
+    Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
+
+#if defined  (XCLOCKING)
+    if (InstancePtr->IsStarted != (u32)XIL_COMPONENT_IS_STARTED) {
+        Xil_ClockEnable(InstancePtr->Config.RefClk);
+    }
+#endif
+
+    /* Start DMA */
+    /* When starting the DMA channels, both transmit and receive sides
+     * need an initialized BD list.
+     */
+    if (InstancePtr->Version == 2) {
+        Xil_AssertVoid(InstancePtr->RxBdRing.BaseBdAddr != 0);
+        Xil_AssertVoid(InstancePtr->TxBdRing.BaseBdAddr != 0);
+    XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+               XEMACPS_RXQBASE_OFFSET,
+               InstancePtr->RxBdRing.BaseBdAddr);
+
+    XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+               XEMACPS_TXQBASE_OFFSET,
+               InstancePtr->TxBdRing.BaseBdAddr);
+    }
+
+    /* clear any existed int status */
+    XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET,
+               XEMACPS_IXR_ALL_MASK);
+
+    /* Enable transmitter if not already enabled */
+    if ((InstancePtr->Options & (u32)XEMACPS_TRANSMITTER_ENABLE_OPTION)!=0x00000000U) {
+        Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                    XEMACPS_NWCTRL_OFFSET);
+        if ((!(Reg & XEMACPS_NWCTRL_TXEN_MASK))==TRUE) {
+            XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                       XEMACPS_NWCTRL_OFFSET,
+                   Reg | (u32)XEMACPS_NWCTRL_TXEN_MASK);
+        }
+    }
+
+    /* Enable receiver if not already enabled */
+    if ((InstancePtr->Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) {
+        Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                    XEMACPS_NWCTRL_OFFSET);
+        if ((!(Reg & XEMACPS_NWCTRL_RXEN_MASK))==TRUE) {
+            XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                       XEMACPS_NWCTRL_OFFSET,
+                   Reg | (u32)XEMACPS_NWCTRL_RXEN_MASK);
+        }
+    }
+
+        /* Enable TX and RX interrupts */
+        XEmacPs_IntEnable(InstancePtr, (XEMACPS_IXR_TX_ERR_MASK |
+    XEMACPS_IXR_RX_ERR_MASK | (u32)XEMACPS_IXR_FRAMERX_MASK |
+    (u32)XEMACPS_IXR_TXCOMPL_MASK));
+
+    /* Enable TX Q1 Interrupts */
+    if (InstancePtr->Version > 2)
+        XEmacPs_IntQ1Enable(InstancePtr, XEMACPS_INTQ1_IXR_ALL_MASK);
+
+    /* Mark as started */
+    InstancePtr->IsStarted = XIL_COMPONENT_IS_STARTED;
+
+    return;
+}
+
+
+/*****************************************************************************/
+/**
+* Gracefully stop the Ethernet MAC as follows:
+*   - Disable all interrupts from this device
+*   - Stop DMA channels
+*   - Disable the tansmitter and receiver
+*
+* Device options currently in effect are not changed.
+*
+* This function will disable all interrupts. Default interrupts settings that
+* had been enabled will be restored when XEmacPs_Start() is called.
+*
+* @param InstancePtr is a pointer to the instance to be worked on.
+*
+* @note
+* This function makes use of internal resources that are shared between the
+* Start, Stop, SetOptions, and ClearOptions functions. So if one task might be
+* setting device options while another is trying to start the device, the user
+* is required to provide protection of this shared data (typically using a
+* semaphore).
+*
+* Stopping the DMA channels causes this function to block until the DMA
+* operation is complete.
+*
+******************************************************************************/
+void XEmacPs_Stop(XEmacPs *InstancePtr)
+{
+    u32 Reg;
+
+    Xil_AssertVoid(InstancePtr != NULL);
+    Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
+
+    /* Disable all interrupts */
+    XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_IDR_OFFSET,
+               XEMACPS_IXR_ALL_MASK);
+
+    /* Disable the receiver & transmitter */
+    Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                XEMACPS_NWCTRL_OFFSET);
+    Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK);
+    Reg &= (u32)(~XEMACPS_NWCTRL_TXEN_MASK);
+    XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+               XEMACPS_NWCTRL_OFFSET, Reg);
+
+    /* Mark as stopped */
+    InstancePtr->IsStarted = 0U;
+#if defined  (XCLOCKING)
+    Xil_ClockDisable(InstancePtr->Config.RefClk);
+#endif
+}
+
+
+/*****************************************************************************/
+/**
+* Perform a graceful reset of the Ethernet MAC. Resets the DMA channels, the
+* transmitter, and the receiver.
+*
+* Steps to reset
+* - Stops transmit and receive channels
+* - Stops DMA
+* - Configure transmit and receive buffer size to default
+* - Clear transmit and receive status register and counters
+* - Clear all interrupt sources
+* - Clear phy (if there is any previously detected) address
+* - Clear MAC addresses (1-4) as well as Type IDs and hash value
+*
+* All options are placed in their default state. Any frames in the
+* descriptor lists will remain in the lists. The side effect of doing
+* this is that after a reset and following a restart of the device, frames
+* were in the list before the reset may be transmitted or received.
+*
+* The upper layer software is responsible for re-configuring (if necessary)
+* and restarting the MAC after the reset. Note also that driver statistics
+* are not cleared on reset. It is up to the upper layer software to clear the
+* statistics if needed.
+*
+* When a reset is required, the driver notifies the upper layer software of
+* this need through the ErrorHandler callback and specific status codes.
+* The upper layer software is responsible for calling this Reset function
+* and then re-configuring the device.
+*
+* @param InstancePtr is a pointer to the instance to be worked on.
+*
+******************************************************************************/
+void XEmacPs_Reset(XEmacPs *InstancePtr)
+{
+    u32 Reg;
+    u8 i;
+    s8 EmacPs_zero_MAC[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
+
+    Xil_AssertVoid(InstancePtr != NULL);
+    Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
+
+    /* Stop the device and reset hardware */
+    XEmacPs_Stop(InstancePtr);
+    InstancePtr->Options = XEMACPS_DEFAULT_OPTIONS;
+
+    InstancePtr->Version = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, 0xFC);
+
+    InstancePtr->Version = (InstancePtr->Version >> 16) & 0xFFF;
+
+    InstancePtr->MaxMtuSize = XEMACPS_MTU;
+    InstancePtr->MaxFrameSize = XEMACPS_MTU + XEMACPS_HDR_SIZE +
+                    XEMACPS_TRL_SIZE;
+    InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize +
+                    XEMACPS_HDR_VLAN_SIZE;
+    InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_MASK;
+
+    /* Setup hardware with default values */
+    XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+            XEMACPS_NWCTRL_OFFSET,
+            (XEMACPS_NWCTRL_STATCLR_MASK |
+            XEMACPS_NWCTRL_MDEN_MASK) &
+            (u32)(~XEMACPS_NWCTRL_LOOPEN_MASK));
+
+    Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+            XEMACPS_NWCFG_OFFSET);
+    Reg &= XEMACPS_NWCFG_MDCCLKDIV_MASK;
+
+    Reg = Reg | (u32)XEMACPS_NWCFG_100_MASK |
+            (u32)XEMACPS_NWCFG_FDEN_MASK |
+            (u32)XEMACPS_NWCFG_UCASTHASHEN_MASK;
+
+    XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                    XEMACPS_NWCFG_OFFSET, Reg);
+    if (InstancePtr->Version > 2) {
+        XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCFG_OFFSET,
+            (XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCFG_OFFSET) |
+                XEMACPS_NWCFG_DWIDTH_64_MASK));
+    }
+
+    XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+            XEMACPS_DMACR_OFFSET,
+            (((((u32)XEMACPS_RX_BUF_SIZE / (u32)XEMACPS_RX_BUF_UNIT) +
+                (((((u32)XEMACPS_RX_BUF_SIZE %
+                (u32)XEMACPS_RX_BUF_UNIT))!=(u32)0) ? 1U : 0U)) <<
+                (u32)(XEMACPS_DMACR_RXBUF_SHIFT)) &
+                (u32)(XEMACPS_DMACR_RXBUF_MASK)) |
+                (u32)XEMACPS_DMACR_RXSIZE_MASK |
+                (u32)XEMACPS_DMACR_TXSIZE_MASK);
+
+
+    if (InstancePtr->Version > 2) {
+        XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET,
+            (XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET) |
+#if defined(__aarch64__) || defined(__arch64__)
+            (u32)XEMACPS_DMACR_ADDR_WIDTH_64 |
+#endif
+            (u32)XEMACPS_DMACR_INCR16_AHB_BURST));
+    }
+
+    XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+               XEMACPS_TXSR_OFFSET, XEMACPS_SR_ALL_MASK);
+
+    XEmacPs_SetQueuePtr(InstancePtr, 0, 0x00U, (u16)XEMACPS_SEND);
+    if (InstancePtr->Version > 2)
+        XEmacPs_SetQueuePtr(InstancePtr, 0, 0x01U, (u16)XEMACPS_SEND);
+    XEmacPs_SetQueuePtr(InstancePtr, 0, 0x00U, (u16)XEMACPS_RECV);
+
+    XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+               XEMACPS_RXSR_OFFSET, XEMACPS_SR_ALL_MASK);
+
+    XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_IDR_OFFSET,
+               XEMACPS_IXR_ALL_MASK);
+
+    Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                XEMACPS_ISR_OFFSET);
+    XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET,
+               Reg);
+
+    XEmacPs_ClearHash(InstancePtr);
+
+    for (i = 1U; i < 5U; i++) {
+        (void)XEmacPs_SetMacAddress(InstancePtr, EmacPs_zero_MAC, i);
+        (void)XEmacPs_SetTypeIdCheck(InstancePtr, 0x00000000U, i);
+    }
+
+    /* clear all counters */
+    for (i = 0U; i < (u8)((XEMACPS_LAST_OFFSET - XEMACPS_OCTTXL_OFFSET) / 4U);
+         i++) {
+        (void)XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                                   XEMACPS_OCTTXL_OFFSET + (u32)(((u32)i) * ((u32)4)));
+    }
+
+    /* Disable the receiver */
+    Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                XEMACPS_NWCTRL_OFFSET);
+    Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK);
+    XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+               XEMACPS_NWCTRL_OFFSET, Reg);
+
+    /* Sync default options with hardware but leave receiver and
+         * transmitter disabled. They get enabled with XEmacPs_Start() if
+     * XEMACPS_TRANSMITTER_ENABLE_OPTION and
+         * XEMACPS_RECEIVER_ENABLE_OPTION are set.
+     */
+    (void)XEmacPs_SetOptions(InstancePtr, InstancePtr->Options &
+                ~((u32)XEMACPS_TRANSMITTER_ENABLE_OPTION |
+                  (u32)XEMACPS_RECEIVER_ENABLE_OPTION));
+
+    (void)XEmacPs_ClearOptions(InstancePtr, ~InstancePtr->Options);
+}
+
+
+/******************************************************************************/
+/**
+ * This is a stub for the asynchronous callbacks. The stub is here in case the
+ * upper layer forgot to set the handler(s). On initialization, all handlers are
+ * set to this callback. It is considered an error for this handler to be
+ * invoked.
+ *
+ ******************************************************************************/
+void XEmacPs_StubHandler(void)
+{
+    Xil_AssertVoidAlways();
+}
+
+/*****************************************************************************/
+/**
+* This function sets the start address of the transmit/receive buffer queue.
+*
+* @param    InstancePtr is a pointer to the instance to be worked on.
+* @param    QPtr is the address of the Queue to be written
+* @param    QueueNum is the Buffer Queue Index
+* @param    Direction indicates Transmit/Receive
+*
+* @note
+* The buffer queue addresses has to be set before starting the transfer, so
+* this function has to be called in prior to XEmacPs_Start()
+*
+******************************************************************************/
+void XEmacPs_SetQueuePtr(XEmacPs *InstancePtr, UINTPTR QPtr, u8 QueueNum,
+             u16 Direction)
+{
+    /* Assert bad arguments and conditions */
+    Xil_AssertVoid(InstancePtr != NULL);
+    Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
+
+        /* If already started, then there is nothing to do */
+        if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
+                return;
+        }
+
+    if (QueueNum == 0x00U) {
+        if (Direction == XEMACPS_SEND) {
+            XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                XEMACPS_TXQBASE_OFFSET,
+                (QPtr & ULONG64_LO_MASK));
+        } else {
+            XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                XEMACPS_RXQBASE_OFFSET,
+                (QPtr & ULONG64_LO_MASK));
+        }
+    }
+     else {
+        XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+            XEMACPS_TXQ1BASE_OFFSET,
+            (QPtr & ULONG64_LO_MASK));
+    }
+#ifdef __aarch64__
+    if (Direction == XEMACPS_SEND) {
+        /* Set the MSB of TX Queue start address */
+        XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                XEMACPS_MSBBUF_TXQBASE_OFFSET,
+                (u32)((QPtr & ULONG64_HI_MASK) >> 32U));
+    } else {
+        /* Set the MSB of RX Queue start address */
+        XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                XEMACPS_MSBBUF_RXQBASE_OFFSET,
+                (u32)((QPtr & ULONG64_HI_MASK) >> 32U));
+    }
+#endif
+}
+/** @} */

+ 836 - 0
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps.h

@@ -0,0 +1,836 @@
+/******************************************************************************
+* Copyright (C) 2010 - 2020 Xilinx, Inc.  All rights reserved.
+* SPDX-License-Identifier: MIT
+******************************************************************************/
+
+/****************************************************************************/
+/**
+ *
+ * @file xemacps.h
+* @addtogroup emacps_v3_11
+* @{
+* @details
+ *
+ * The Xilinx Embedded Processor Block Ethernet driver.
+ *
+ * For a full description of XEMACPS features, please see the hardware spec.
+ * This driver supports the following features:
+ *   - Memory mapped access to host interface registers
+ *   - Statistics counter registers for RMON/MIB
+ *   - API for interrupt driven frame transfers for hardware configured DMA
+ *   - Virtual memory support
+ *   - Unicast, broadcast, and multicast receive address filtering
+ *   - Full and half duplex operation
+ *   - Automatic PAD & FCS insertion and stripping
+ *   - Flow control
+ *   - Support up to four 48bit addresses
+ *   - Address checking for four specific 48bit addresses
+ *   - VLAN frame support
+ *   - Pause frame support
+ *   - Large frame support up to 1536 bytes
+ *   - Checksum offload
+ *
+ * <b>Driver Description</b>
+ *
+ * The device driver enables higher layer software (e.g., an application) to
+ * communicate to the XEmacPs. The driver handles transmission and reception
+ * of Ethernet frames, as well as configuration and control. No pre or post
+ * processing of frame data is performed. The driver does not validate the
+ * contents of an incoming frame in addition to what has already occurred in
+ * hardware.
+ * A single device driver can support multiple devices even when those devices
+ * have significantly different configurations.
+ *
+ * <b>Initialization & Configuration</b>
+ *
+ * The XEmacPs_Config structure is used by the driver to configure itself.
+ * This configuration structure is typically created by the tool-chain based
+ * on hardware build properties.
+ *
+ * The driver instance can be initialized in
+ *
+ *   - XEmacPs_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddress):  Uses a
+ *     configuration structure provided by the caller. If running in a system
+ *     with address translation, the provided virtual memory base address
+ *     replaces the physical address present in the configuration structure.
+ *
+ * The device supports DMA only as current development plan. No FIFO mode is
+ * supported. The driver expects to start the DMA channels and expects that
+ * the user has set up the buffer descriptor lists.
+ *
+ * <b>Interrupts and Asynchronous Callbacks</b>
+ *
+ * The driver has no dependencies on the interrupt controller. When an
+ * interrupt occurs, the handler will perform a small amount of
+ * housekeeping work, determine the source of the interrupt, and call the
+ * appropriate callback function. All callbacks are registered by the user
+ * level application.
+ *
+ * <b>Virtual Memory</b>
+ *
+ * All virtual to physical memory mappings must occur prior to accessing the
+ * driver API.
+ *
+ * For DMA transactions, user buffers supplied to the driver must be in terms
+ * of their physical address.
+ *
+ * <b>DMA</b>
+ *
+ * The DMA engine uses buffer descriptors (BDs) to describe Ethernet frames.
+ * These BDs are typically chained together into a list the hardware follows
+ * when transferring data in and out of the packet buffers. Each BD describes
+ * a memory region containing either a full or partial Ethernet packet.
+ *
+ * Interrupt coalescing is not supported from this built-in DMA engine.
+ *
+ * This API requires the user to understand how the DMA operates. The
+ * following paragraphs provide some explanation, but the user is encouraged
+ * to read documentation in xemacps_bdring.h as well as study example code
+ * that accompanies this driver.
+ *
+ * The API is designed to get BDs to and from the DMA engine in the most
+ * efficient means possible. The first step is to establish a  memory region
+ * to contain all BDs for a specific channel. This is done with
+ * XEmacPs_BdRingCreate(). This function sets up a BD ring that hardware will
+ * follow as BDs are processed. The ring will consist of a user defined number
+ * of BDs which will all be partially initialized. For example on the transmit
+ * channel, the driver will initialize all BDs' so that they are configured
+ * for transmit. The more fields that can be permanently setup at
+ * initialization, then the fewer accesses will be needed to each BD while
+ * the DMA engine is in operation resulting in better throughput and CPU
+ * utilization. The best case initialization would require the user to set
+ * only a frame buffer address and length prior to submitting the BD to the
+ * engine.
+ *
+ * BDs move through the engine with the help of functions
+ * XEmacPs_BdRingAlloc(), XEmacPs_BdRingToHw(), XEmacPs_BdRingFromHw(),
+ * and XEmacPs_BdRingFree().
+ * All these functions handle BDs that are in place. That is, there are no
+ * copies of BDs kept anywhere and any BD the user interacts with is an actual
+ * BD from the same ring hardware accesses.
+ *
+ * BDs in the ring go through a series of states as follows:
+ *   1. Idle. The driver controls BDs in this state.
+ *   2. The user has data to transfer. XEmacPs_BdRingAlloc() is called to
+ *      reserve BD(s). Once allocated, the user may setup the BD(s) with
+ *      frame buffer address, length, and other attributes. The user controls
+ *      BDs in this state.
+ *   3. The user submits BDs to the DMA engine with XEmacPs_BdRingToHw. BDs
+ *      in this state are either waiting to be processed by hardware, are in
+ *      process, or have been processed. The DMA engine controls BDs in this
+ *      state.
+ *   4. Processed BDs are retrieved with XEmacEpv_BdRingFromHw() by the
+ *      user. Once retrieved, the user can examine each BD for the outcome of
+ *      the DMA transfer. The user controls BDs in this state. After examining
+ *      the BDs the user calls XEmacPs_BdRingFree() which places the BDs back
+ *      into state 1.
+ *
+ * Each of the four BD accessor functions operate on a set of BDs. A set is
+ * defined as a segment of the BD ring consisting of one or more BDs. The user
+ * views the set as a pointer to the first BD along with the number of BDs for
+ * that set. The set can be navigated by using macros XEmacPs_BdNext(). The
+ * user must exercise extreme caution when changing BDs in a set as there is
+ * nothing to prevent doing a mBdNext past the end of the set and modifying a
+ * BD out of bounds.
+ *
+ * XEmacPs_BdRingAlloc() + XEmacPs_BdRingToHw(), as well as
+ * XEmacPs_BdRingFromHw() + XEmacPs_BdRingFree() are designed to be used in
+ * tandem. The same BD set retrieved with BdRingAlloc should be the same one
+ * provided to hardware with BdRingToHw. Same goes with BdRingFromHw and
+ * BdRIngFree.
+ *
+ * <b>Alignment & Data Cache Restrictions</b>
+ *
+ * Due to the design of the hardware, all RX buffers, BDs need to be 4-byte
+ * aligned. Please reference xemacps_bd.h for cache related macros.
+ *
+ * DMA Tx:
+ *
+ *   - If frame buffers exist in cached memory, then they must be flushed
+ *     prior to committing them to hardware.
+ *
+ * DMA Rx:
+ *
+ *   - If frame buffers exist in cached memory, then the cache must be
+ *     invalidated for the memory region containing the frame prior to data
+ *     access
+ *
+ * Both cache invalidate/flush are taken care of in driver code.
+ *
+ * <b>Buffer Copying</b>
+ *
+ * The driver is designed for a zero-copy buffer scheme. That is, the driver
+ * will not copy buffers. This avoids potential throughput bottlenecks within
+ * the driver. If byte copying is required, then the transfer will take longer
+ * to complete.
+ *
+ * <b>Checksum Offloading</b>
+ *
+ * The Embedded Processor Block Ethernet can be configured to perform IP, TCP
+ * and UDP checksum offloading in both receive and transmit directions.
+ *
+ * IP packets contain a 16-bit checksum field, which is the 16-bit 1s
+ * complement of the 1s complement sum of all 16-bit words in the header.
+ * TCP and UDP packets contain a 16-bit checksum field, which is the 16-bit
+ * 1s complement of the 1s complement sum of all 16-bit words in the header,
+ * the data and a conceptual pseudo header.
+ *
+ * To calculate these checksums in software requires each byte of the packet
+ * to be read. For TCP and UDP this can use a large amount of processing power.
+ * Offloading the checksum calculation to hardware can result in significant
+ * performance improvements.
+ *
+ * The transmit checksum offload is only available to use DMA in packet buffer
+ * mode. This is because the complete frame to be transmitted must be read
+ * into the packet buffer memory before the checksum can be calculated and
+ * written to the header at the beginning of the frame.
+ *
+ * For IP, TCP or UDP receive checksum offload to be useful, the operating
+ * system containing the protocol stack must be aware that this offload is
+ * available so that it can make use of the fact that the hardware has verified
+ * the checksum.
+ *
+ * When receive checksum offloading is enabled in the hardware, the IP header
+ * checksum is checked, where the packet meets the following criteria:
+ *
+ * 1. If present, the VLAN header must be four octets long and the CFI bit
+ *    must not be set.
+ * 2. Encapsulation must be RFC 894 Ethernet Type Encoding or RFC 1042 SNAP
+ *    encoding.
+ * 3. IP v4 packet.
+ * 4. IP header is of a valid length.
+ * 5. Good IP header checksum.
+ * 6. No IP fragmentation.
+ * 7. TCP or UDP packet.
+ *
+ * When an IP, TCP or UDP frame is received, the receive buffer descriptor
+ * gives an indication if the hardware was able to verify the checksums.
+ * There is also an indication if the frame had SNAP encapsulation. These
+ * indication bits will replace the type ID match indication bits when the
+ * receive checksum offload is enabled.
+ *
+ * If any of the checksums are verified incorrect by the hardware, the packet
+ * is discarded and the appropriate statistics counter incremented.
+ *
+ * <b>PHY Interfaces</b>
+ *
+ * RGMII 1.3 is the only interface supported.
+ *
+ * <b>Asserts</b>
+ *
+ * Asserts are used within all Xilinx drivers to enforce constraints on
+ * parameters. Asserts can be turned off on a system-wide basis by defining,
+ * at compile time, the NDEBUG identifier. By default, asserts are turned on
+ * and it is recommended that users leave asserts on during development. For
+ * deployment use -DNDEBUG compiler switch to remove assert code.
+ *
+ * @note
+ *
+ * Xilinx drivers are typically composed of two parts, one is the driver
+ * and the other is the adapter.  The driver is independent of OS and processor
+ * and is intended to be highly portable.  The adapter is OS-specific and
+ * facilitates communication between the driver and an OS.
+ * This driver is intended to be RTOS and processor independent. Any needs for
+ * dynamic memory management, threads or thread mutual exclusion, or cache
+ * control must be satisfied bythe layer above this driver.
+ *
+ * <pre>
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -------------------------------------------------------
+ * 1.00a wsy  01/10/10 First release
+ * 1.00a asa  11/21/11 The function XEmacPs_BdRingFromHwTx in file
+ *               xemacps_bdring.c is modified. Earlier it was checking for
+ *               "BdLimit"(passed argument) number of BDs for finding out
+ *               which BDs are successfully processed. Now one more check
+ *               is added. It looks for BDs till the current BD pointer
+ *               reaches HwTail. By doing this processing time is saved.
+ * 1.00a asa  01/24/12 The function XEmacPs_BdRingFromHwTx in file
+ *               xemacps_bdring.c is modified. Now start of packet is
+ *               searched for returning the number of BDs processed.
+ * 1.02a asa  11/05/12 Added a new API for deleting an entry from the HASH
+ *               registers. Added a new API to set the bust length.
+ *               Added some new hash-defines.
+ * 1.03a asa  01/23/12 Fix for CR #692702 which updates error handling for
+ *               Rx errors. Under heavy Rx traffic, there will be a large
+ *               number of errors related to receive buffer not available.
+ *               Because of a HW bug (SI #692601), under such heavy errors,
+ *               the Rx data path can become unresponsive. To reduce the
+ *               probabilities for hitting this HW bug, the SW writes to
+ *               bit 18 to flush a packet from Rx DPRAM immediately. The
+ *               changes for it are done in the function
+ *               XEmacPs_IntrHandler.
+ * 1.05a asa  09/23/13 Cache operations on BDs are not required and hence
+ *               removed. It is expected that all BDs are allocated in
+ *               from uncached area.
+ * 1.06a asa  11/02/13 Changed the value for XEMACPS_RXBUF_LEN_MASK from 0x3fff
+ *                to 0x1fff. This fixes the CR#744902.
+ *              Made changes in example file xemacps_example.h to fix compilation
+ *              issues with iarcc compiler.
+ * 2.0   adk  10/12/13 Updated as per the New Tcl API's
+ * 2.1   adk  11/08/14 Fixed the CR#811288. Changes are made in the driver tcl file.
+ * 2.1   bss  09/08/14 Modified driver tcl to fix CR#820349 to export phy
+ *               address in xparameters.h when GMII to RGMII converter
+ *               is present in hw.
+ * 2.1   srt  07/15/14 Add support for Zynq Ultrascale Mp GEM specification and 64-bit
+ *               changes.
+ * 2.2   adk  29/10/14 Fixed CR#827686 when PCS/PMA core is configured with
+ *                    1000BASE-X mode export proper values to the xparameters.h
+ *                    file. Changes are made in the driver tcl file.
+ * 3.0   adk  08/1/15  Don't include gem in peripheral test when gem is
+ *                    configured with PCS/PMA Core. Changes are made in the
+ *               test app tcl(CR:827686).
+ * 3.0   kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+ * 3.0   hk   03/18/15 Added support for jumbo frames. Increase AHB burst.
+ *                     Disable extended mode. Perform all 64 bit changes under
+ *                     check for arch64.
+ *                     Remove "used bit set" from TX error interrupt masks.
+ * 3.1   hk   07/27/15 Do not call error handler with '0' error code when
+ *                     there is no error. CR# 869403
+ *            08/10/15 Update upper 32 bit tx and rx queue ptr registers.
+ * 3.2   hk   02/22/16 Added SGMII support for Zynq Ultrascale+ MPSoC.
+ * 3.4   ms   01/23/17 Modified xil_printf statement in main function for all
+ *                     examples to ensure that "Successfully ran" and "Failed"
+ *                     strings are available in all examples. This is a fix
+ *                     for CR-965028.
+ *       ms   03/17/17 Modified text file in examples folder for doxygen
+ *                     generation.
+ *       ms   04/05/17 Added tabspace for return statements in functions of
+ *                     xemacps_ieee1588_example.c for proper documentation
+ *                     while generating doxygen.
+ * 3.5   hk   08/14/17 Update cache coherency information of the interface in
+ *                     its config structure.
+ * 3.6   rb   09/08/17 HwCnt variable (in XEmacPs_BdRing structure) is
+ *               changed to volatile.
+ *               Add API XEmacPs_BdRingPtrReset() to reset pointers
+ * 3.8   hk   07/19/18 Fixed CPP, GCC and doxygen warnings - CR-1006327
+ *     hk   09/17/18 Fix PTP interrupt masks and cleanup comments.
+ * 3.9   hk   01/23/19 Add RX watermark support
+ * 3.11  sd   02/14/20 Add clock support
+ *
+ * </pre>
+ *
+ ****************************************************************************/
+
+#ifndef XEMACPS_H        /* prevent circular inclusions */
+#define XEMACPS_H        /* by using protection macros */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************** Include Files ********************************/
+
+#include "xil_types.h"
+#include "xil_assert.h"
+#include "xstatus.h"
+#include "xemacps_hw.h"
+#include "xemacps_bd.h"
+#include "xemacps_bdring.h"
+#if defined  (XCLOCKING)
+#include "xil_clocking.h"
+#endif
+
+/************************** Constant Definitions ****************************/
+
+/*
+ * Device information
+ */
+#define XEMACPS_DEVICE_NAME     "xemacps"
+#define XEMACPS_DEVICE_DESC     "Xilinx PS 10/100/1000 MAC"
+
+
+/** @name Configuration options
+ *
+ * Device configuration options. See the XEmacPs_SetOptions(),
+ * XEmacPs_ClearOptions() and XEmacPs_GetOptions() for information on how to
+ * use options.
+ *
+ * The default state of the options are noted and are what the device and
+ * driver will be set to after calling XEmacPs_Reset() or
+ * XEmacPs_Initialize().
+ *
+ * @{
+ */
+
+#define XEMACPS_PROMISC_OPTION               0x00000001U
+/**< Accept all incoming packets.
+ *   This option defaults to disabled (cleared) */
+
+#define XEMACPS_FRAME1536_OPTION             0x00000002U
+/**< Frame larger than 1516 support for Tx & Rx.
+ *   This option defaults to disabled (cleared) */
+
+#define XEMACPS_VLAN_OPTION                  0x00000004U
+/**< VLAN Rx & Tx frame support.
+ *   This option defaults to disabled (cleared) */
+
+#define XEMACPS_FLOW_CONTROL_OPTION          0x00000010U
+/**< Enable recognition of flow control frames on Rx
+ *   This option defaults to enabled (set) */
+
+#define XEMACPS_FCS_STRIP_OPTION             0x00000020U
+/**< Strip FCS and PAD from incoming frames. Note: PAD from VLAN frames is not
+ *   stripped.
+ *   This option defaults to enabled (set) */
+
+#define XEMACPS_FCS_INSERT_OPTION            0x00000040U
+/**< Generate FCS field and add PAD automatically for outgoing frames.
+ *   This option defaults to disabled (cleared) */
+
+#define XEMACPS_LENTYPE_ERR_OPTION           0x00000080U
+/**< Enable Length/Type error checking for incoming frames. When this option is
+ *   set, the MAC will filter frames that have a mismatched type/length field
+ *   and if XEMACPS_REPORT_RXERR_OPTION is set, the user is notified when these
+ *   types of frames are encountered. When this option is cleared, the MAC will
+ *   allow these types of frames to be received.
+ *
+ *   This option defaults to disabled (cleared) */
+
+#define XEMACPS_TRANSMITTER_ENABLE_OPTION    0x00000100U
+/**< Enable the transmitter.
+ *   This option defaults to enabled (set) */
+
+#define XEMACPS_RECEIVER_ENABLE_OPTION       0x00000200U
+/**< Enable the receiver
+ *   This option defaults to enabled (set) */
+
+#define XEMACPS_BROADCAST_OPTION             0x00000400U
+/**< Allow reception of the broadcast address
+ *   This option defaults to enabled (set) */
+
+#define XEMACPS_MULTICAST_OPTION             0x00000800U
+/**< Allows reception of multicast addresses programmed into hash
+ *   This option defaults to disabled (clear) */
+
+#define XEMACPS_RX_CHKSUM_ENABLE_OPTION      0x00001000U
+/**< Enable the RX checksum offload
+ *   This option defaults to enabled (set) */
+
+#define XEMACPS_TX_CHKSUM_ENABLE_OPTION      0x00002000U
+/**< Enable the TX checksum offload
+ *   This option defaults to enabled (set) */
+
+#define XEMACPS_JUMBO_ENABLE_OPTION    0x00004000U
+#define XEMACPS_SGMII_ENABLE_OPTION    0x00008000U
+
+#define XEMACPS_DEFAULT_OPTIONS                     \
+    ((u32)XEMACPS_FLOW_CONTROL_OPTION |                  \
+     (u32)XEMACPS_FCS_INSERT_OPTION |                    \
+     (u32)XEMACPS_FCS_STRIP_OPTION |                     \
+     (u32)XEMACPS_BROADCAST_OPTION |                     \
+     (u32)XEMACPS_LENTYPE_ERR_OPTION |                   \
+     (u32)XEMACPS_TRANSMITTER_ENABLE_OPTION |            \
+     (u32)XEMACPS_RECEIVER_ENABLE_OPTION |               \
+     (u32)XEMACPS_RX_CHKSUM_ENABLE_OPTION |              \
+     (u32)XEMACPS_TX_CHKSUM_ENABLE_OPTION)
+
+/**< Default options set when device is initialized or reset */
+/*@}*/
+
+/** @name Callback identifiers
+ *
+ * These constants are used as parameters to XEmacPs_SetHandler()
+ * @{
+ */
+#define XEMACPS_HANDLER_DMASEND 1U
+#define XEMACPS_HANDLER_DMARECV 2U
+#define XEMACPS_HANDLER_ERROR   3U
+/*@}*/
+
+/* Constants to determine the configuration of the hardware device. They are
+ * used to allow the driver to verify it can operate with the hardware.
+ */
+#define XEMACPS_MDIO_DIV_DFT    MDC_DIV_32 /**< Default MDIO clock divisor */
+
+/* The next few constants help upper layers determine the size of memory
+ * pools used for Ethernet buffers and descriptor lists.
+ */
+#define XEMACPS_MAC_ADDR_SIZE   6U    /* size of Ethernet header */
+
+#define XEMACPS_MTU             1500U    /* max MTU size of Ethernet frame */
+#define XEMACPS_MTU_JUMBO       10240U    /* max MTU size of jumbo frame */
+#define XEMACPS_HDR_SIZE        14U    /* size of Ethernet header */
+#define XEMACPS_HDR_VLAN_SIZE   18U    /* size of Ethernet header with VLAN */
+#define XEMACPS_TRL_SIZE        4U    /* size of Ethernet trailer (FCS) */
+#define XEMACPS_MAX_FRAME_SIZE       (XEMACPS_MTU + XEMACPS_HDR_SIZE + \
+        XEMACPS_TRL_SIZE)
+#define XEMACPS_MAX_VLAN_FRAME_SIZE  (XEMACPS_MTU + XEMACPS_HDR_SIZE + \
+        XEMACPS_HDR_VLAN_SIZE + XEMACPS_TRL_SIZE)
+#define XEMACPS_MAX_VLAN_FRAME_SIZE_JUMBO  (XEMACPS_MTU_JUMBO + XEMACPS_HDR_SIZE + \
+        XEMACPS_HDR_VLAN_SIZE + XEMACPS_TRL_SIZE)
+
+/* DMACR Bust length hash defines */
+
+#define XEMACPS_SINGLE_BURST    0x00000001
+#define XEMACPS_4BYTE_BURST        0x00000004
+#define XEMACPS_8BYTE_BURST        0x00000008
+#define XEMACPS_16BYTE_BURST    0x00000010
+
+
+/**************************** Type Definitions ******************************/
+/** @name Typedefs for callback functions
+ *
+ * These callbacks are invoked in interrupt context.
+ * @{
+ */
+/**
+ * Callback invoked when frame(s) have been sent or received in interrupt
+ * driven DMA mode. To set the send callback, invoke XEmacPs_SetHandler().
+ *
+ * @param CallBackRef is user data assigned when the callback was set.
+ *
+ * @note
+ * See xemacps_hw.h for bitmasks definitions and the device hardware spec for
+ * further information on their meaning.
+ *
+ */
+typedef void (*XEmacPs_Handler) (void *CallBackRef);
+
+/**
+ * Callback when an asynchronous error occurs. To set this callback, invoke
+ * XEmacPs_SetHandler() with XEMACPS_HANDLER_ERROR in the HandlerType
+ * parameter.
+ *
+ * @param CallBackRef is user data assigned when the callback was set.
+ * @param Direction defines either receive or transmit error(s) has occurred.
+ * @param ErrorWord definition varies with Direction
+ *
+ */
+typedef void (*XEmacPs_ErrHandler) (void *CallBackRef, u8 Direction,
+                     u32 ErrorWord);
+
+/*@}*/
+
+/**
+ * This typedef contains configuration information for a device.
+ */
+typedef struct {
+    u16 DeviceId;    /**< Unique ID  of device */
+    UINTPTR BaseAddress;/**< Physical base address of IPIF registers */
+    u8 IsCacheCoherent; /**< Applicable only to A53 in EL1 mode;
+                * describes whether Cache Coherent or not */
+#if defined  (XCLOCKING)
+    u32 RefClk;    /**< Input clock */
+#endif
+} XEmacPs_Config;
+
+
+/**
+ * The XEmacPs driver instance data. The user is required to allocate a
+ * structure of this type for every XEmacPs device in the system. A pointer
+ * to a structure of this type is then passed to the driver API functions.
+ */
+typedef struct XEmacPs_Instance {
+    XEmacPs_Config Config;    /* Hardware configuration */
+    u32 IsStarted;        /* Device is currently started */
+    u32 IsReady;        /* Device is initialized and ready */
+    u32 Options;        /* Current options word */
+
+    XEmacPs_BdRing TxBdRing;    /* Transmit BD ring */
+    XEmacPs_BdRing RxBdRing;    /* Receive BD ring */
+
+    XEmacPs_Handler SendHandler;
+    XEmacPs_Handler RecvHandler;
+    void *SendRef;
+    void *RecvRef;
+
+    XEmacPs_ErrHandler ErrorHandler;
+    void *ErrorRef;
+    u32 Version;
+    u32 RxBufMask;
+    u32 MaxMtuSize;
+    u32 MaxFrameSize;
+    u32 MaxVlanFrameSize;
+
+} XEmacPs;
+
+
+/***************** Macros (Inline Functions) Definitions ********************/
+
+/****************************************************************************/
+/**
+* Retrieve the Tx ring object. This object can be used in the various Ring
+* API functions.
+*
+* @param  InstancePtr is the DMA channel to operate on.
+*
+* @return TxBdRing attribute
+*
+* @note
+* C-style signature:
+*    XEmacPs_BdRing XEmacPs_GetTxRing(XEmacPs *InstancePtr)
+*
+*****************************************************************************/
+#define XEmacPs_GetTxRing(InstancePtr) ((InstancePtr)->TxBdRing)
+
+/****************************************************************************/
+/**
+* Retrieve the Rx ring object. This object can be used in the various Ring
+* API functions.
+*
+* @param  InstancePtr is the DMA channel to operate on.
+*
+* @return RxBdRing attribute
+*
+* @note
+* C-style signature:
+*    XEmacPs_BdRing XEmacPs_GetRxRing(XEmacPs *InstancePtr)
+*
+*****************************************************************************/
+#define XEmacPs_GetRxRing(InstancePtr) ((InstancePtr)->RxBdRing)
+
+/****************************************************************************/
+/**
+*
+* Enable interrupts specified in <i>Mask</i>. The corresponding interrupt for
+* each bit set to 1 in <i>Mask</i>, will be enabled.
+*
+* @param InstancePtr is a pointer to the instance to be worked on.
+* @param Mask contains a bit mask of interrupts to enable. The mask can
+*        be formed using a set of bitwise or'd values.
+*
+* @note
+* The state of the transmitter and receiver are not modified by this function.
+* C-style signature
+*     void XEmacPs_IntEnable(XEmacPs *InstancePtr, u32 Mask)
+*
+*****************************************************************************/
+#define XEmacPs_IntEnable(InstancePtr, Mask)                            \
+    XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress,             \
+        XEMACPS_IER_OFFSET,                                     \
+        ((Mask) & XEMACPS_IXR_ALL_MASK));
+
+/****************************************************************************/
+/**
+*
+* Disable interrupts specified in <i>Mask</i>. The corresponding interrupt for
+* each bit set to 1 in <i>Mask</i>, will be enabled.
+*
+* @param InstancePtr is a pointer to the instance to be worked on.
+* @param Mask contains a bit mask of interrupts to disable. The mask can
+*        be formed using a set of bitwise or'd values.
+*
+* @note
+* The state of the transmitter and receiver are not modified by this function.
+* C-style signature
+*     void XEmacPs_IntDisable(XEmacPs *InstancePtr, u32 Mask)
+*
+*****************************************************************************/
+#define XEmacPs_IntDisable(InstancePtr, Mask)                           \
+    XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress,             \
+        XEMACPS_IDR_OFFSET,                                     \
+        ((Mask) & XEMACPS_IXR_ALL_MASK));
+
+/****************************************************************************/
+/**
+*
+* Enable interrupts specified in <i>Mask</i>. The corresponding interrupt for
+* each bit set to 1 in <i>Mask</i>, will be enabled.
+*
+* @param InstancePtr is a pointer to the instance to be worked on.
+* @param Mask contains a bit mask of interrupts to enable. The mask can
+*        be formed using a set of bitwise or'd values.
+*
+* @note
+* The state of the transmitter and receiver are not modified by this function.
+* C-style signature
+*     void XEmacPs_IntQ1Enable(XEmacPs *InstancePtr, u32 Mask)
+*
+*****************************************************************************/
+#define XEmacPs_IntQ1Enable(InstancePtr, Mask)                            \
+    XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress,             \
+        XEMACPS_INTQ1_IER_OFFSET,                                \
+        ((Mask) & XEMACPS_INTQ1_IXR_ALL_MASK));
+
+/****************************************************************************/
+/**
+*
+* Disable interrupts specified in <i>Mask</i>. The corresponding interrupt for
+* each bit set to 1 in <i>Mask</i>, will be enabled.
+*
+* @param InstancePtr is a pointer to the instance to be worked on.
+* @param Mask contains a bit mask of interrupts to disable. The mask can
+*        be formed using a set of bitwise or'd values.
+*
+* @note
+* The state of the transmitter and receiver are not modified by this function.
+* C-style signature
+*     void XEmacPs_IntDisable(XEmacPs *InstancePtr, u32 Mask)
+*
+*****************************************************************************/
+#define XEmacPs_IntQ1Disable(InstancePtr, Mask)                           \
+    XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress,             \
+        XEMACPS_INTQ1_IDR_OFFSET,                               \
+        ((Mask) & XEMACPS_INTQ1_IXR_ALL_MASK));
+
+/****************************************************************************/
+/**
+*
+* This macro triggers trasmit circuit to send data currently in TX buffer(s).
+*
+* @param InstancePtr is a pointer to the XEmacPs instance to be worked on.
+*
+* @return
+*
+* @note
+*
+* Signature: void XEmacPs_Transmit(XEmacPs *InstancePtr)
+*
+*****************************************************************************/
+#define XEmacPs_Transmit(InstancePtr)                              \
+        XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress,          \
+        XEMACPS_NWCTRL_OFFSET,                                     \
+        (XEmacPs_ReadReg((InstancePtr)->Config.BaseAddress,          \
+        XEMACPS_NWCTRL_OFFSET) | XEMACPS_NWCTRL_STARTTX_MASK))
+
+/****************************************************************************/
+/**
+*
+* This macro determines if the device is configured with checksum offloading
+* on the receive channel
+*
+* @param InstancePtr is a pointer to the XEmacPs instance to be worked on.
+*
+* @return
+*
+* Boolean TRUE if the device is configured with checksum offloading, or
+* FALSE otherwise.
+*
+* @note
+*
+* Signature: u32 XEmacPs_IsRxCsum(XEmacPs *InstancePtr)
+*
+*****************************************************************************/
+#define XEmacPs_IsRxCsum(InstancePtr)                                     \
+        ((XEmacPs_ReadReg((InstancePtr)->Config.BaseAddress,             \
+          XEMACPS_NWCFG_OFFSET) & XEMACPS_NWCFG_RXCHKSUMEN_MASK) != 0U     \
+          ? TRUE : FALSE)
+
+/****************************************************************************/
+/**
+*
+* This macro determines if the device is configured with checksum offloading
+* on the transmit channel
+*
+* @param InstancePtr is a pointer to the XEmacPs instance to be worked on.
+*
+* @return
+*
+* Boolean TRUE if the device is configured with checksum offloading, or
+* FALSE otherwise.
+*
+* @note
+*
+* Signature: u32 XEmacPs_IsTxCsum(XEmacPs *InstancePtr)
+*
+*****************************************************************************/
+#define XEmacPs_IsTxCsum(InstancePtr)                                     \
+        ((XEmacPs_ReadReg((InstancePtr)->Config.BaseAddress,              \
+          XEMACPS_DMACR_OFFSET) & XEMACPS_DMACR_TCPCKSUM_MASK) != 0U       \
+          ? TRUE : FALSE)
+
+/************************** Function Prototypes *****************************/
+
+/****************************************************************************/
+/**
+*
+* This macro sets RX watermark register.
+*
+* @param InstancePtr is a pointer to the XEmacPs instance to be worked on.
+* @param High is the non-zero RX high watermark value. When SRAM fill level
+*     is above this, a pause frame will be sent.
+* @param Low is the non-zero RX low watermark value. When SRAM fill level
+*     is below this, a zero length pause frame will be sent IF the last
+*     pause frame sent was non-zero.
+*
+* @return None
+*
+* @note
+*
+* Signature: void XEmacPs_SetRXWatermark(XEmacPs *InstancePtr, u16 High,
+*                     u16 Low)
+*
+*****************************************************************************/
+#define XEmacPs_SetRXWatermark(InstancePtr, High, Low)                     \
+        XEmacPs_WriteReg((InstancePtr)->Config.BaseAddress,                \
+        XEMACPS_RXWATERMARK_OFFSET,                                        \
+        (High & XEMACPS_RXWM_HIGH_MASK) |  \
+        ((Low << XEMACPS_RXWM_LOW_SHFT_MSK) & XEMACPS_RXWM_LOW_MASK) |)
+
+/****************************************************************************/
+/**
+*
+* This macro gets RX watermark register.
+*
+* @param InstancePtr is a pointer to the XEmacPs instance to be worked on.
+*
+* @return RX watermark register value
+*
+* @note
+*
+* Signature: void XEmacPs_GetRXWatermark(XEmacPs *InstancePtr)
+*
+*****************************************************************************/
+#define XEmacPs_GetRXWatermark(InstancePtr)                     \
+        XEmacPs_ReadReg((InstancePtr)->Config.BaseAddress,                \
+        XEMACPS_RXWATERMARK_OFFSET)
+/*
+ * Initialization functions in xemacps.c
+ */
+LONG XEmacPs_CfgInitialize(XEmacPs *InstancePtr, XEmacPs_Config *CfgPtr,
+               UINTPTR EffectiveAddress);
+void XEmacPs_Start(XEmacPs *InstancePtr);
+void XEmacPs_Stop(XEmacPs *InstancePtr);
+void XEmacPs_Reset(XEmacPs *InstancePtr);
+void XEmacPs_SetQueuePtr(XEmacPs *InstancePtr, UINTPTR QPtr, u8 QueueNum,
+             u16 Direction);
+
+/*
+ * Lookup configuration in xemacps_sinit.c
+ */
+XEmacPs_Config *XEmacPs_LookupConfig(u16 DeviceId);
+
+/*
+ * Interrupt-related functions in xemacps_intr.c
+ * DMA only and FIFO is not supported. This DMA does not support coalescing.
+ */
+LONG XEmacPs_SetHandler(XEmacPs *InstancePtr, u32 HandlerType,
+            void *FuncPointer, void *CallBackRef);
+void XEmacPs_IntrHandler(void *XEmacPsPtr);
+
+/*
+ * MAC configuration/control functions in XEmacPs_control.c
+ */
+LONG XEmacPs_SetOptions(XEmacPs *InstancePtr, u32 Options);
+LONG XEmacPs_ClearOptions(XEmacPs *InstancePtr, u32 Options);
+u32 XEmacPs_GetOptions(XEmacPs *InstancePtr);
+
+LONG XEmacPs_SetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index);
+LONG XEmacPs_DeleteHash(XEmacPs *InstancePtr, void *AddressPtr);
+void XEmacPs_GetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index);
+
+LONG XEmacPs_SetHash(XEmacPs *InstancePtr, void *AddressPtr);
+void XEmacPs_ClearHash(XEmacPs *InstancePtr);
+void XEmacPs_GetHash(XEmacPs *InstancePtr, void *AddressPtr);
+
+void XEmacPs_SetMdioDivisor(XEmacPs *InstancePtr,
+                XEmacPs_MdcDiv Divisor);
+void XEmacPs_SetOperatingSpeed(XEmacPs *InstancePtr, u16 Speed);
+u16 XEmacPs_GetOperatingSpeed(XEmacPs *InstancePtr);
+LONG XEmacPs_PhyRead(XEmacPs *InstancePtr, u32 PhyAddress,
+             u32 RegisterNum, u16 *PhyDataPtr);
+LONG XEmacPs_PhyWrite(XEmacPs *InstancePtr, u32 PhyAddress,
+              u32 RegisterNum, u16 PhyData);
+LONG XEmacPs_SetTypeIdCheck(XEmacPs *InstancePtr, u32 Id_Check, u8 Index);
+
+LONG XEmacPs_SendPausePacket(XEmacPs *InstancePtr);
+void XEmacPs_DMABLengthUpdate(XEmacPs *InstancePtr, s32 BLength);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of protection macro */
+/** @} */

+ 762 - 0
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bd.h

@@ -0,0 +1,762 @@
+/******************************************************************************
+* Copyright (C) 2010 - 2020 Xilinx, Inc.  All rights reserved.
+* SPDX-License-Identifier: MIT
+******************************************************************************/
+
+/*****************************************************************************/
+/**
+ *
+ * @file xemacps_bd.h
+* @addtogroup emacps_v3_11
+* @{
+ *
+ * This header provides operations to manage buffer descriptors in support
+ * of scatter-gather DMA.
+ *
+ * The API exported by this header defines abstracted macros that allow the
+ * user to read/write specific BD fields.
+ *
+ * <b>Buffer Descriptors</b>
+ *
+ * A buffer descriptor (BD) defines a DMA transaction. The macros defined by
+ * this header file allow access to most fields within a BD to tailor a DMA
+ * transaction according to user and hardware requirements.  See the hardware
+ * IP DMA spec for more information on BD fields and how they affect transfers.
+ *
+ * The XEmacPs_Bd structure defines a BD. The organization of this structure
+ * is driven mainly by the hardware for use in scatter-gather DMA transfers.
+ *
+ * <b>Performance</b>
+ *
+ * Limiting I/O to BDs can improve overall performance of the DMA channel.
+ *
+ * <pre>
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -------------------------------------------------------
+ * 1.00a wsy  01/10/10 First release
+ * 2.1   srt  07/15/14 Add support for Zynq Ultrascale MP GEM specification
+ *                     and 64-bit changes.
+ * 3.0   kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+ * 3.0   hk   02/20/15 Added support for jumbo frames.
+ *                     Disable extended mode. Perform all 64 bit changes under
+ *                     check for arch64.
+ * 3.2   hk   11/18/15 Change BD typedef and number of words.
+ * 3.8   hk   08/18/18 Remove duplicate definition of XEmacPs_BdSetLength
+ * 3.8   mus  11/05/18 Support 64 bit DMA addresses for Microblaze-X platform.
+ *
+ * </pre>
+ *
+ * ***************************************************************************
+ */
+
+#ifndef XEMACPS_BD_H        /* prevent circular inclusions */
+#define XEMACPS_BD_H        /* by using protection macros */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************** Include Files *********************************/
+
+#include <string.h>
+#include "xil_types.h"
+#include "xil_assert.h"
+
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+#ifdef __aarch64__
+/* Minimum BD alignment */
+#define XEMACPS_DMABD_MINIMUM_ALIGNMENT  64U
+#define XEMACPS_BD_NUM_WORDS 4U
+#else
+/* Minimum BD alignment */
+#define XEMACPS_DMABD_MINIMUM_ALIGNMENT  4U
+#define XEMACPS_BD_NUM_WORDS 2U
+#endif
+
+/**
+ * The XEmacPs_Bd is the type for buffer descriptors (BDs).
+ */
+typedef u32 XEmacPs_Bd[XEMACPS_BD_NUM_WORDS];
+
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/*****************************************************************************/
+/**
+ * Zero out BD fields
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @return Nothing
+ *
+ * @note
+ * C-style signature:
+ *    void XEmacPs_BdClear(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+#define XEmacPs_BdClear(BdPtr)                                  \
+    memset((BdPtr), 0, sizeof(XEmacPs_Bd))
+
+/****************************************************************************/
+/**
+*
+* Read the given Buffer Descriptor word.
+*
+* @param    BaseAddress is the base address of the BD to read
+* @param    Offset is the word offset to be read
+*
+* @return   The 32-bit value of the field
+*
+* @note
+* C-style signature:
+*    u32 XEmacPs_BdRead(UINTPTR BaseAddress, UINTPTR Offset)
+*
+*****************************************************************************/
+#define XEmacPs_BdRead(BaseAddress, Offset)             \
+    (*(u32 *)((UINTPTR)((void*)(BaseAddress)) + (u32)(Offset)))
+
+/****************************************************************************/
+/**
+*
+* Write the given Buffer Descriptor word.
+*
+* @param    BaseAddress is the base address of the BD to write
+* @param    Offset is the word offset to be written
+* @param    Data is the 32-bit value to write to the field
+*
+* @return   None.
+*
+* @note
+* C-style signature:
+*    void XEmacPs_BdWrite(UINTPTR BaseAddress, UINTPTR Offset, UINTPTR Data)
+*
+*****************************************************************************/
+#define XEmacPs_BdWrite(BaseAddress, Offset, Data)              \
+    (*(u32 *)((UINTPTR)(void*)(BaseAddress) + (u32)(Offset)) = (u32)(Data))
+
+/*****************************************************************************/
+/**
+ * Set the BD's Address field (word 0).
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ * @param  Addr  is the value to write to BD's status field.
+ *
+ * @note :
+ *
+ * C-style signature:
+ *    void XEmacPs_BdSetAddressTx(XEmacPs_Bd* BdPtr, UINTPTR Addr)
+ *
+ *****************************************************************************/
+#if defined(__aarch64__) || defined(__arch64__)
+#define XEmacPs_BdSetAddressTx(BdPtr, Addr)                        \
+    XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET,        \
+            (u32)((Addr) & ULONG64_LO_MASK));        \
+    XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_HI_OFFSET,        \
+    (u32)(((Addr) & ULONG64_HI_MASK) >> 32U));
+#else
+#define XEmacPs_BdSetAddressTx(BdPtr, Addr)                        \
+    XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET, (u32)(Addr))
+#endif
+
+/*****************************************************************************/
+/**
+ * Set the BD's Address field (word 0).
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ * @param  Addr  is the value to write to BD's status field.
+ *
+ * @note : Due to some bits are mixed within receive BD's address field,
+ *         read-modify-write is performed.
+ *
+ * C-style signature:
+ *    void XEmacPs_BdSetAddressRx(XEmacPs_Bd* BdPtr, UINTPTR Addr)
+ *
+ *****************************************************************************/
+#ifdef __aarch64__
+#define XEmacPs_BdSetAddressRx(BdPtr, Addr)                        \
+    XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET,              \
+    ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) &           \
+    ~XEMACPS_RXBUF_ADD_MASK) | ((u32)((Addr) & ULONG64_LO_MASK))));  \
+    XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_HI_OFFSET,     \
+    (u32)(((Addr) & ULONG64_HI_MASK) >> 32U));
+#else
+#define XEmacPs_BdSetAddressRx(BdPtr, Addr)                        \
+    XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET,              \
+    ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) &           \
+    ~XEMACPS_RXBUF_ADD_MASK) | (UINTPTR)(Addr)))
+#endif
+
+/*****************************************************************************/
+/**
+ * Set the BD's Status field (word 1).
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ * @param  Data  is the value to write to BD's status field.
+ *
+ * @note
+ * C-style signature:
+ *    void XEmacPs_BdSetStatus(XEmacPs_Bd* BdPtr, UINTPTR Data)
+ *
+ *****************************************************************************/
+#define XEmacPs_BdSetStatus(BdPtr, Data)                           \
+    XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET,              \
+    XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) | (Data))
+
+
+/*****************************************************************************/
+/**
+ * Retrieve the BD's Packet DMA transfer status word (word 1).
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @return Status word
+ *
+ * @note
+ * C-style signature:
+ *    u32 XEmacPs_BdGetStatus(XEmacPs_Bd* BdPtr)
+ *
+ * Due to the BD bit layout differences in transmit and receive. User's
+ * caution is required.
+ *****************************************************************************/
+#define XEmacPs_BdGetStatus(BdPtr)                                 \
+    XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET)
+
+
+/*****************************************************************************/
+/**
+ * Get the address (bits 0..31) of the BD's buffer address (word 0)
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @note
+ * C-style signature:
+ *    UINTPTR XEmacPs_BdGetBufAddr(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+#if defined(__aarch64__) || defined(__arch64__)
+#define XEmacPs_BdGetBufAddr(BdPtr)                               \
+    (XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) |          \
+    (XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_HI_OFFSET)) << 32U)
+#else
+#define XEmacPs_BdGetBufAddr(BdPtr)                               \
+    (XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET))
+#endif
+
+/*****************************************************************************/
+/**
+ * Set transfer length in bytes for the given BD. The length must be set each
+ * time a BD is submitted to hardware.
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ * @param  LenBytes is the number of bytes to transfer.
+ *
+ * @note
+ * C-style signature:
+ *    void XEmacPs_BdSetLength(XEmacPs_Bd* BdPtr, u32 LenBytes)
+ *
+ *****************************************************************************/
+#define XEmacPs_BdSetLength(BdPtr, LenBytes)                       \
+    XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET,              \
+    ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) &           \
+    ~XEMACPS_TXBUF_LEN_MASK) | (LenBytes)))
+
+
+/*****************************************************************************/
+/**
+ * Retrieve the BD length field.
+ *
+ * For Tx channels, the returned value is the same as that written with
+ * XEmacPs_BdSetLength().
+ *
+ * For Rx channels, the returned value is the size of the received packet.
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @return Length field processed by hardware or set by
+ *         XEmacPs_BdSetLength().
+ *
+ * @note
+ * C-style signature:
+ *    UINTPTR XEmacPs_BdGetLength(XEmacPs_Bd* BdPtr)
+ *    XEAMCPS_RXBUF_LEN_MASK is same as XEMACPS_TXBUF_LEN_MASK.
+ *
+ *****************************************************************************/
+#define XEmacPs_BdGetLength(BdPtr)                                 \
+    (XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) &            \
+    XEMACPS_RXBUF_LEN_MASK)
+
+/*****************************************************************************/
+/**
+ * Retrieve the RX frame size.
+ *
+ * The returned value is the size of the received packet.
+ * This API supports jumbo frame sizes if enabled.
+ *
+ * @param  InstancePtr is the pointer to XEmacps instance
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @return Length field processed by hardware or set by
+ *         XEmacPs_BdSetLength().
+ *
+ * @note
+ * C-style signature:
+ *    UINTPTR XEmacPs_GetRxFrameSize(XEmacPs* InstancePtr, XEmacPs_Bd* BdPtr)
+ *    RxBufMask is dependent on whether jumbo is enabled or not.
+ *
+ *****************************************************************************/
+#define XEmacPs_GetRxFrameSize(InstancePtr, BdPtr)                   \
+    (XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) &            \
+    (InstancePtr)->RxBufMask)
+
+/*****************************************************************************/
+/**
+ * Test whether the given BD has been marked as the last BD of a packet.
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @return TRUE if BD represents the "Last" BD of a packet, FALSE otherwise
+ *
+ * @note
+ * C-style signature:
+ *    UINTPTR XEmacPs_BdIsLast(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+#define XEmacPs_BdIsLast(BdPtr)                                    \
+    ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) &           \
+    XEMACPS_RXBUF_EOF_MASK)!=0U ? TRUE : FALSE)
+
+
+/*****************************************************************************/
+/**
+ * Tell the DMA engine that the given transmit BD marks the end of the current
+ * packet to be processed.
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @note
+ * C-style signature:
+ *    void XEmacPs_BdSetLast(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+#define XEmacPs_BdSetLast(BdPtr)                                   \
+    (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET,             \
+    XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) |             \
+    XEMACPS_TXBUF_LAST_MASK))
+
+
+/*****************************************************************************/
+/**
+ * Tell the DMA engine that the current packet does not end with the given
+ * BD.
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @note
+ * C-style signature:
+ *    void XEmacPs_BdClearLast(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+#define XEmacPs_BdClearLast(BdPtr)                                 \
+    (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET,             \
+    XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) &             \
+    ~XEMACPS_TXBUF_LAST_MASK))
+
+
+/*****************************************************************************/
+/**
+ * Set this bit to mark the last descriptor in the receive buffer descriptor
+ * list.
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @note
+ * C-style signature:
+ *    void XEmacPs_BdSetRxWrap(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+/*#define XEmacPs_BdSetRxWrap(BdPtr)                                 \
+    (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET,             \
+    XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) |             \
+    XEMACPS_RXBUF_WRAP_MASK))
+*/
+
+/*****************************************************************************/
+/**
+ * Determine the wrap bit of the receive BD which indicates end of the
+ * BD list.
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @note
+ * C-style signature:
+ *    u8 XEmacPs_BdIsRxWrap(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+#define XEmacPs_BdIsRxWrap(BdPtr)                                  \
+    ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) &           \
+    XEMACPS_RXBUF_WRAP_MASK)!=0U ? TRUE : FALSE)
+
+
+/*****************************************************************************/
+/**
+ * Sets this bit to mark the last descriptor in the transmit buffer
+ * descriptor list.
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @note
+ * C-style signature:
+ *    void XEmacPs_BdSetTxWrap(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+/*#define XEmacPs_BdSetTxWrap(BdPtr)                                 \
+    (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET,             \
+    XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) |             \
+    XEMACPS_TXBUF_WRAP_MASK))
+*/
+
+/*****************************************************************************/
+/**
+ * Determine the wrap bit of the transmit BD which indicates end of the
+ * BD list.
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @note
+ * C-style signature:
+ *    u8 XEmacPs_BdGetTxWrap(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+#define XEmacPs_BdIsTxWrap(BdPtr)                                  \
+    ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) &           \
+    XEMACPS_TXBUF_WRAP_MASK)!=0U ? TRUE : FALSE)
+
+
+/*****************************************************************************/
+/*
+ * Must clear this bit to enable the MAC to write data to the receive
+ * buffer. Hardware sets this bit once it has successfully written a frame to
+ * memory. Once set, software has to clear the bit before the buffer can be
+ * used again. This macro clear the new bit of the receive BD.
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @note
+ * C-style signature:
+ *    void XEmacPs_BdClearRxNew(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+#define XEmacPs_BdClearRxNew(BdPtr)                                \
+    (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_ADDR_OFFSET,             \
+    XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) &             \
+    ~XEMACPS_RXBUF_NEW_MASK))
+
+
+/*****************************************************************************/
+/**
+ * Determine the new bit of the receive BD.
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @note
+ * C-style signature:
+ *    UINTPTR XEmacPs_BdIsRxNew(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+#define XEmacPs_BdIsRxNew(BdPtr)                                   \
+    ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_ADDR_OFFSET) &           \
+    XEMACPS_RXBUF_NEW_MASK)!=0U ? TRUE : FALSE)
+
+
+/*****************************************************************************/
+/**
+ * Software sets this bit to disable the buffer to be read by the hardware.
+ * Hardware sets this bit for the first buffer of a frame once it has been
+ * successfully transmitted. This macro sets this bit of transmit BD to avoid
+ * confusion.
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @note
+ * C-style signature:
+ *    void XEmacPs_BdSetTxUsed(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+#define XEmacPs_BdSetTxUsed(BdPtr)                                 \
+    (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET,             \
+    XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) |             \
+    XEMACPS_TXBUF_USED_MASK))
+
+
+/*****************************************************************************/
+/**
+ * Software clears this bit to enable the buffer to be read by the hardware.
+ * Hardware sets this bit for the first buffer of a frame once it has been
+ * successfully transmitted. This macro clears this bit of transmit BD.
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @note
+ * C-style signature:
+ *    void XEmacPs_BdClearTxUsed(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+#define XEmacPs_BdClearTxUsed(BdPtr)                               \
+    (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET,             \
+    XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) &             \
+    ~XEMACPS_TXBUF_USED_MASK))
+
+
+/*****************************************************************************/
+/**
+ * Determine the used bit of the transmit BD.
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @note
+ * C-style signature:
+ *    UINTPTR XEmacPs_BdIsTxUsed(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+#define XEmacPs_BdIsTxUsed(BdPtr)                                  \
+    ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) &           \
+    XEMACPS_TXBUF_USED_MASK)!=0U ? TRUE : FALSE)
+
+
+/*****************************************************************************/
+/**
+ * Determine if a frame fails to be transmitted due to too many retries.
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @note
+ * C-style signature:
+ *    UINTPTR XEmacPs_BdIsTxRetry(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+#define XEmacPs_BdIsTxRetry(BdPtr)                                 \
+    ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) &           \
+    XEMACPS_TXBUF_RETRY_MASK)!=0U ? TRUE : FALSE)
+
+
+/*****************************************************************************/
+/**
+ * Determine if a frame fails to be transmitted due to data can not be
+ * feteched in time or buffers are exhausted.
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @note
+ * C-style signature:
+ *    UINTPTR XEmacPs_BdIsTxUrun(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+#define XEmacPs_BdIsTxUrun(BdPtr)                                  \
+    ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) &           \
+    XEMACPS_TXBUF_URUN_MASK)!=0U ? TRUE : FALSE)
+
+
+/*****************************************************************************/
+/**
+ * Determine if a frame fails to be transmitted due to buffer is exhausted
+ * mid-frame.
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @note
+ * C-style signature:
+ *    UINTPTR XEmacPs_BdIsTxExh(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+#define XEmacPs_BdIsTxExh(BdPtr)                                   \
+    ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) &           \
+    XEMACPS_TXBUF_EXH_MASK)!=0U ? TRUE : FALSE)
+
+
+/*****************************************************************************/
+/**
+ * Sets this bit, no CRC will be appended to the current frame. This control
+ * bit must be set for the first buffer in a frame and will be ignored for
+ * the subsequent buffers of a frame.
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @note
+ * This bit must be clear when using the transmit checksum generation offload,
+ * otherwise checksum generation and substitution will not occur.
+ *
+ * C-style signature:
+ *    UINTPTR XEmacPs_BdSetTxNoCRC(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+#define XEmacPs_BdSetTxNoCRC(BdPtr)                                \
+    (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET,             \
+    XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) |             \
+    XEMACPS_TXBUF_NOCRC_MASK))
+
+
+/*****************************************************************************/
+/**
+ * Clear this bit, CRC will be appended to the current frame. This control
+ * bit must be set for the first buffer in a frame and will be ignored for
+ * the subsequent buffers of a frame.
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @note
+ * This bit must be clear when using the transmit checksum generation offload,
+ * otherwise checksum generation and substitution will not occur.
+ *
+ * C-style signature:
+ *    UINTPTR XEmacPs_BdClearTxNoCRC(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+#define XEmacPs_BdClearTxNoCRC(BdPtr)                              \
+    (XEmacPs_BdWrite((BdPtr), XEMACPS_BD_STAT_OFFSET,             \
+    XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) &             \
+    ~XEMACPS_TXBUF_NOCRC_MASK))
+
+
+/*****************************************************************************/
+/**
+ * Determine the broadcast bit of the receive BD.
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @note
+ * C-style signature:
+ *    UINTPTR XEmacPs_BdIsRxBcast(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+#define XEmacPs_BdIsRxBcast(BdPtr)                                 \
+    ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) &           \
+    XEMACPS_RXBUF_BCAST_MASK)!=0U ? TRUE : FALSE)
+
+
+/*****************************************************************************/
+/**
+ * Determine the multicast hash bit of the receive BD.
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @note
+ * C-style signature:
+ *    UINTPTR XEmacPs_BdIsRxMultiHash(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+#define XEmacPs_BdIsRxMultiHash(BdPtr)                             \
+    ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) &           \
+    XEMACPS_RXBUF_MULTIHASH_MASK)!=0U ? TRUE : FALSE)
+
+
+/*****************************************************************************/
+/**
+ * Determine the unicast hash bit of the receive BD.
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @note
+ * C-style signature:
+ *    UINTPTR XEmacPs_BdIsRxUniHash(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+#define XEmacPs_BdIsRxUniHash(BdPtr)                               \
+    ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) &           \
+    XEMACPS_RXBUF_UNIHASH_MASK)!=0U ? TRUE : FALSE)
+
+
+/*****************************************************************************/
+/**
+ * Determine if the received frame is a VLAN Tagged frame.
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @note
+ * C-style signature:
+ *    UINTPTR XEmacPs_BdIsRxVlan(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+#define XEmacPs_BdIsRxVlan(BdPtr)                                  \
+    ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) &           \
+    XEMACPS_RXBUF_VLAN_MASK)!=0U ? TRUE : FALSE)
+
+
+/*****************************************************************************/
+/**
+ * Determine if the received frame has Type ID of 8100h and null VLAN
+ * identifier(Priority tag).
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @note
+ * C-style signature:
+ *    UINTPTR XEmacPs_BdIsRxPri(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+#define XEmacPs_BdIsRxPri(BdPtr)                                   \
+    ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) &           \
+    XEMACPS_RXBUF_PRI_MASK)!=0U ? TRUE : FALSE)
+
+
+/*****************************************************************************/
+/**
+ * Determine if the received frame's Concatenation Format Indicator (CFI) of
+ * the frames VLANTCI field was set.
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @note
+ * C-style signature:
+ *    UINTPTR XEmacPs_BdIsRxCFI(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+#define XEmacPs_BdIsRxCFI(BdPtr)                                   \
+    ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) &           \
+    XEMACPS_RXBUF_CFI_MASK)!=0U ? TRUE : FALSE)
+
+
+/*****************************************************************************/
+/**
+ * Determine the End Of Frame (EOF) bit of the receive BD.
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @note
+ * C-style signature:
+ *    UINTPTR XEmacPs_BdGetRxEOF(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+#define XEmacPs_BdIsRxEOF(BdPtr)                                   \
+    ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) &           \
+    XEMACPS_RXBUF_EOF_MASK)!=0U ? TRUE : FALSE)
+
+
+/*****************************************************************************/
+/**
+ * Determine the Start Of Frame (SOF) bit of the receive BD.
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @note
+ * C-style signature:
+ *    UINTPTR XEmacPs_BdGetRxSOF(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+#define XEmacPs_BdIsRxSOF(BdPtr)                                   \
+    ((XEmacPs_BdRead((BdPtr), XEMACPS_BD_STAT_OFFSET) &           \
+    XEMACPS_RXBUF_SOF_MASK)!=0U ? TRUE : FALSE)
+
+
+/************************** Function Prototypes ******************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of protection macro */
+/** @} */

+ 1076 - 0
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bdring.c

@@ -0,0 +1,1076 @@
+/******************************************************************************
+* Copyright (C) 2010 - 2020 Xilinx, Inc.  All rights reserved.
+* SPDX-License-Identifier: MIT
+******************************************************************************/
+
+/*****************************************************************************/
+/**
+*
+* @file xemacps_bdring.c
+* @addtogroup emacps_v3_11
+* @{
+*
+* This file implements buffer descriptor ring related functions.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a wsy  01/10/10 First release
+* 1.00a asa  11/21/11 The function XEmacPs_BdRingFromHwTx is modified.
+*              Earlier it used to search in "BdLimit" number of BDs to
+*              know which BDs are processed. Now one more check is
+*              added. It looks for BDs till the current BD pointer
+*              reaches HwTail. By doing this processing time is saved.
+* 1.00a asa  01/24/12 The function XEmacPs_BdRingFromHwTx in file
+*              xemacps_bdring.c is modified. Now start of packet is
+*              searched for returning the number of BDs processed.
+* 1.05a asa  09/23/13 Cache operations on BDs are not required and hence
+*              removed. It is expected that all BDs are allocated in
+*              from uncached area. Fix for CR #663885.
+* 2.1   srt  07/15/14 Add support for Zynq Ultrascale Mp architecture.
+* 3.0   kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.6   rb   09/08/17 Add XEmacPs_BdRingPtrReset() API to reset BD ring
+*               pointers
+*
+* </pre>
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xstatus.h"
+#include "xil_cache.h"
+#include "xemacps_hw.h"
+#include "xemacps_bd.h"
+#include "xemacps_bdring.h"
+
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/****************************************************************************
+ * Compute the virtual address of a descriptor from its physical address
+ *
+ * @param BdPtr is the physical address of the BD
+ *
+ * @returns Virtual address of BdPtr
+ *
+ * @note Assume BdPtr is always a valid BD in the ring
+ ****************************************************************************/
+#define XEMACPS_PHYS_TO_VIRT(BdPtr) \
+    ((UINTPTR)(BdPtr) + (RingPtr->BaseBdAddr - RingPtr->PhysBaseAddr))
+
+/****************************************************************************
+ * Compute the physical address of a descriptor from its virtual address
+ *
+ * @param BdPtr is the physical address of the BD
+ *
+ * @returns Physical address of BdPtr
+ *
+ * @note Assume BdPtr is always a valid BD in the ring
+ ****************************************************************************/
+#define XEMACPS_VIRT_TO_PHYS(BdPtr) \
+    ((UINTPTR)(BdPtr) - (RingPtr->BaseBdAddr - RingPtr->PhysBaseAddr))
+
+/****************************************************************************
+ * Move the BdPtr argument ahead an arbitrary number of BDs wrapping around
+ * to the beginning of the ring if needed.
+ *
+ * We know if a wrapaound should occur if the new BdPtr is greater than
+ * the high address in the ring OR if the new BdPtr crosses over the
+ * 0xFFFFFFFF to 0 boundary. The latter test is a valid one since we do not
+ * allow a BD space to span this boundary.
+ *
+ * @param RingPtr is the ring BdPtr appears in
+ * @param BdPtr on input is the starting BD position and on output is the
+ *        final BD position
+ * @param NumBd is the number of BD spaces to increment
+ *
+ ****************************************************************************/
+#define XEMACPS_RING_SEEKAHEAD(RingPtr, BdPtr, NumBd)                  \
+    {                                                                   \
+        UINTPTR Addr = (UINTPTR)(void *)(BdPtr);                        \
+                                                                        \
+        Addr += ((RingPtr)->Separation * (NumBd));                        \
+        if ((Addr > (RingPtr)->HighBdAddr) || ((UINTPTR)(void *)(BdPtr) > Addr))  \
+        {                                                               \
+            Addr -= (RingPtr)->Length;                                  \
+        }                                                               \
+                                                                        \
+        (BdPtr) = (XEmacPs_Bd*)(void *)Addr;                                     \
+    }
+
+/****************************************************************************
+ * Move the BdPtr argument backwards an arbitrary number of BDs wrapping
+ * around to the end of the ring if needed.
+ *
+ * We know if a wrapaound should occur if the new BdPtr is less than
+ * the base address in the ring OR if the new BdPtr crosses over the
+ * 0xFFFFFFFF to 0 boundary. The latter test is a valid one since we do not
+ * allow a BD space to span this boundary.
+ *
+ * @param RingPtr is the ring BdPtr appears in
+ * @param BdPtr on input is the starting BD position and on output is the
+ *        final BD position
+ * @param NumBd is the number of BD spaces to increment
+ *
+ ****************************************************************************/
+#define XEMACPS_RING_SEEKBACK(RingPtr, BdPtr, NumBd)                   \
+    {                                                                   \
+        UINTPTR Addr = (UINTPTR)(void *)(BdPtr);                                  \
+                                                                        \
+        Addr -= ((RingPtr)->Separation * (NumBd));                        \
+        if ((Addr < (RingPtr)->BaseBdAddr) || ((UINTPTR)(void*)(BdPtr) < Addr))  \
+        {                                                               \
+            Addr += (RingPtr)->Length;                                  \
+        }                                                               \
+                                                                        \
+        (BdPtr) = (XEmacPs_Bd*)(void*)Addr;                                     \
+    }
+
+
+/************************** Function Prototypes ******************************/
+
+static void XEmacPs_BdSetRxWrap(UINTPTR BdPtr);
+static void XEmacPs_BdSetTxWrap(UINTPTR BdPtr);
+
+/************************** Variable Definitions *****************************/
+
+/*****************************************************************************/
+/**
+ * Using a memory segment allocated by the caller, create and setup the BD list
+ * for the given DMA channel.
+ *
+ * @param RingPtr is the instance to be worked on.
+ * @param PhysAddr is the physical base address of user memory region.
+ * @param VirtAddr is the virtual base address of the user memory region. If
+ *        address translation is not being utilized, then VirtAddr should be
+ *        equivalent to PhysAddr.
+ * @param Alignment governs the byte alignment of individual BDs. This function
+ *        will enforce a minimum alignment of 4 bytes with no maximum as long
+ *        as it is specified as a power of 2.
+ * @param BdCount is the number of BDs to setup in the user memory region. It
+ *        is assumed the region is large enough to contain the BDs.
+ *
+ * @return
+ *
+ * - XST_SUCCESS if initialization was successful
+ * - XST_NO_FEATURE if the provided instance is a non DMA type
+ *   channel.
+ * - XST_INVALID_PARAM under any of the following conditions:
+ *   1) PhysAddr and/or VirtAddr are not aligned to the given Alignment
+ *      parameter.
+ *   2) Alignment parameter does not meet minimum requirements or is not a
+ *      power of 2 value.
+ *   3) BdCount is 0.
+ * - XST_DMA_SG_LIST_ERROR if the memory segment containing the list spans
+ *   over address 0x00000000 in virtual address space.
+ *
+ * @note
+ * Make sure to pass in the right alignment value.
+ *****************************************************************************/
+LONG XEmacPs_BdRingCreate(XEmacPs_BdRing * RingPtr, UINTPTR PhysAddr,
+              UINTPTR VirtAddr, u32 Alignment, u32 BdCount)
+{
+    u32 i;
+    UINTPTR BdVirtAddr;
+    UINTPTR BdPhyAddr;
+    UINTPTR VirtAddrLoc = VirtAddr;
+
+    /* In case there is a failure prior to creating list, make sure the
+     * following attributes are 0 to prevent calls to other functions
+     * from doing anything.
+     */
+    RingPtr->AllCnt = 0U;
+    RingPtr->FreeCnt = 0U;
+    RingPtr->HwCnt = 0U;
+    RingPtr->PreCnt = 0U;
+    RingPtr->PostCnt = 0U;
+
+    /* Make sure Alignment parameter meets minimum requirements */
+    if (Alignment < (u32)XEMACPS_DMABD_MINIMUM_ALIGNMENT) {
+        return (LONG)(XST_INVALID_PARAM);
+    }
+
+    /* Make sure Alignment is a power of 2 */
+    if (((Alignment - 0x00000001U) & Alignment)!=0x00000000U) {
+        return (LONG)(XST_INVALID_PARAM);
+    }
+
+    /* Make sure PhysAddr and VirtAddr are on same Alignment */
+    if (((PhysAddr % Alignment)!=(u32)0) || ((VirtAddrLoc % Alignment)!=(u32)0)) {
+        return (LONG)(XST_INVALID_PARAM);
+    }
+
+    /* Is BdCount reasonable? */
+    if (BdCount == 0x00000000U) {
+        return (LONG)(XST_INVALID_PARAM);
+    }
+
+    /* Figure out how many bytes will be between the start of adjacent BDs */
+    RingPtr->Separation = ((u32)sizeof(XEmacPs_Bd));
+
+    /* Must make sure the ring doesn't span address 0x00000000. If it does,
+     * then the next/prev BD traversal macros will fail.
+     */
+    if (VirtAddrLoc > ((VirtAddrLoc + (RingPtr->Separation * BdCount)) - (u32)1)) {
+        return (LONG)(XST_DMA_SG_LIST_ERROR);
+    }
+
+    /* Initial ring setup:
+     *  - Clear the entire space
+     *  - Setup each BD's BDA field with the physical address of the next BD
+     */
+    (void)memset((void *) VirtAddrLoc, 0, (RingPtr->Separation * BdCount));
+
+    BdVirtAddr = VirtAddrLoc;
+    BdPhyAddr = PhysAddr + RingPtr->Separation;
+    for (i = 1U; i < BdCount; i++) {
+        BdVirtAddr += RingPtr->Separation;
+        BdPhyAddr += RingPtr->Separation;
+    }
+
+    /* Setup and initialize pointers and counters */
+    RingPtr->RunState = (u32)(XST_DMA_SG_IS_STOPPED);
+    RingPtr->BaseBdAddr = VirtAddrLoc;
+    RingPtr->PhysBaseAddr = PhysAddr;
+    RingPtr->HighBdAddr = BdVirtAddr;
+    RingPtr->Length =
+        ((RingPtr->HighBdAddr - RingPtr->BaseBdAddr) + RingPtr->Separation);
+    RingPtr->AllCnt = (u32)BdCount;
+    RingPtr->FreeCnt = (u32)BdCount;
+    RingPtr->FreeHead = (XEmacPs_Bd *)(void *)VirtAddrLoc;
+    RingPtr->PreHead = (XEmacPs_Bd *)VirtAddrLoc;
+    RingPtr->HwHead = (XEmacPs_Bd *)VirtAddrLoc;
+    RingPtr->HwTail = (XEmacPs_Bd *)VirtAddrLoc;
+    RingPtr->PostHead = (XEmacPs_Bd *)VirtAddrLoc;
+    RingPtr->BdaRestart = (XEmacPs_Bd *)(void *)PhysAddr;
+
+    return (LONG)(XST_SUCCESS);
+}
+
+
+/*****************************************************************************/
+/**
+ * Clone the given BD into every BD in the list.
+ * every field of the source BD is replicated in every BD of the list.
+ *
+ * This function can be called only when all BDs are in the free group such as
+ * they are immediately after initialization with XEmacPs_BdRingCreate().
+ * This prevents modification of BDs while they are in use by hardware or the
+ * user.
+ *
+ * @param RingPtr is the pointer of BD ring instance to be worked on.
+ * @param SrcBdPtr is the source BD template to be cloned into the list. This
+ *        BD will be modified.
+ * @param Direction is either XEMACPS_SEND or XEMACPS_RECV that indicates
+ *        which direction.
+ *
+ * @return
+ *   - XST_SUCCESS if the list was modified.
+ *   - XST_DMA_SG_NO_LIST if a list has not been created.
+ *   - XST_DMA_SG_LIST_ERROR if some of the BDs in this channel are under
+ *     hardware or user control.
+ *   - XST_DEVICE_IS_STARTED if the DMA channel has not been stopped.
+ *
+ *****************************************************************************/
+LONG XEmacPs_BdRingClone(XEmacPs_BdRing * RingPtr, XEmacPs_Bd * SrcBdPtr,
+             u8 Direction)
+{
+    u32 i;
+    UINTPTR CurBd;
+
+    /* Can't do this function if there isn't a ring */
+    if (RingPtr->AllCnt == 0x00000000U) {
+        return (LONG)(XST_DMA_SG_NO_LIST);
+    }
+
+    /* Can't do this function with the channel running */
+    if (RingPtr->RunState == (u32)XST_DMA_SG_IS_STARTED) {
+        return (LONG)(XST_DEVICE_IS_STARTED);
+    }
+
+    /* Can't do this function with some of the BDs in use */
+    if (RingPtr->FreeCnt != RingPtr->AllCnt) {
+        return (LONG)(XST_DMA_SG_LIST_ERROR);
+    }
+
+    if ((Direction != (u8)XEMACPS_SEND) && (Direction != (u8)XEMACPS_RECV)) {
+        return (LONG)(XST_INVALID_PARAM);
+    }
+
+    /* Starting from the top of the ring, save BD.Next, overwrite the entire
+     * BD with the template, then restore BD.Next
+     */
+    CurBd = RingPtr->BaseBdAddr;
+    for (i = 0U; i < RingPtr->AllCnt; i++) {
+        memcpy((void *)CurBd, SrcBdPtr, sizeof(XEmacPs_Bd));
+    CurBd += RingPtr->Separation;
+    }
+
+    CurBd -= RingPtr->Separation;
+
+    if (Direction == XEMACPS_RECV) {
+        XEmacPs_BdSetRxWrap(CurBd);
+    }
+    else {
+        XEmacPs_BdSetTxWrap(CurBd);
+    }
+
+    return (LONG)(XST_SUCCESS);
+}
+
+
+/*****************************************************************************/
+/**
+ * Reserve locations in the BD list. The set of returned BDs may be modified
+ * in preparation for future DMA transaction(s). Once the BDs are ready to be
+ * submitted to hardware, the user must call XEmacPs_BdRingToHw() in the same
+ * order which they were allocated here. Example:
+ *
+ * <pre>
+ *        NumBd = 2,
+ *        Status = XEmacPs_BdRingAlloc(MyRingPtr, NumBd, &MyBdSet),
+ *
+ *        if (Status != XST_SUCCESS)
+ *        {
+ *            *Not enough BDs available for the request*
+ *        }
+ *
+ *        CurBd = MyBdSet,
+ *        for (i=0; i<NumBd; i++)
+ *        {
+ *            * Prepare CurBd *.....
+ *
+ *            * Onto next BD *
+ *            CurBd = XEmacPs_BdRingNext(MyRingPtr, CurBd),
+ *        }
+ *
+ *        * Give list to hardware *
+ *        Status = XEmacPs_BdRingToHw(MyRingPtr, NumBd, MyBdSet),
+ * </pre>
+ *
+ * A more advanced use of this function may allocate multiple sets of BDs.
+ * They must be allocated and given to hardware in the correct sequence:
+ * <pre>
+ *        * Legal *
+ *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd1, &MySet1),
+ *        XEmacPs_BdRingToHw(MyRingPtr, NumBd1, MySet1),
+ *
+ *        * Legal *
+ *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd1, &MySet1),
+ *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd2, &MySet2),
+ *        XEmacPs_BdRingToHw(MyRingPtr, NumBd1, MySet1),
+ *        XEmacPs_BdRingToHw(MyRingPtr, NumBd2, MySet2),
+ *
+ *        * Not legal *
+ *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd1, &MySet1),
+ *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd2, &MySet2),
+ *        XEmacPs_BdRingToHw(MyRingPtr, NumBd2, MySet2),
+ *        XEmacPs_BdRingToHw(MyRingPtr, NumBd1, MySet1),
+ * </pre>
+ *
+ * Use the API defined in xemacps_bd.h to modify individual BDs. Traversal
+ * of the BD set can be done using XEmacPs_BdRingNext() and
+ * XEmacPs_BdRingPrev().
+ *
+ * @param RingPtr is a pointer to the BD ring instance to be worked on.
+ * @param NumBd is the number of BDs to allocate
+ * @param BdSetPtr is an output parameter, it points to the first BD available
+ *        for modification.
+ *
+ * @return
+ *   - XST_SUCCESS if the requested number of BDs was returned in the BdSetPtr
+ *     parameter.
+ *   - XST_FAILURE if there were not enough free BDs to satisfy the request.
+ *
+ * @note This function should not be preempted by another XEmacPs_Bd function
+ *       call that modifies the BD space. It is the caller's responsibility to
+ *       provide a mutual exclusion mechanism.
+ *
+ * @note Do not modify more BDs than the number requested with the NumBd
+ *       parameter. Doing so will lead to data corruption and system
+ *       instability.
+ *
+ *****************************************************************************/
+LONG XEmacPs_BdRingAlloc(XEmacPs_BdRing * RingPtr, u32 NumBd,
+             XEmacPs_Bd ** BdSetPtr)
+{
+    LONG Status;
+    /* Enough free BDs available for the request? */
+    if (RingPtr->FreeCnt < NumBd) {
+        Status = (LONG)(XST_FAILURE);
+    } else {
+    /* Set the return argument and move FreeHead forward */
+    *BdSetPtr = RingPtr->FreeHead;
+    XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->FreeHead, NumBd);
+    RingPtr->FreeCnt -= NumBd;
+    RingPtr->PreCnt += NumBd;
+        Status = (LONG)(XST_SUCCESS);
+    }
+    return Status;
+}
+
+/*****************************************************************************/
+/**
+ * Fully or partially undo an XEmacPs_BdRingAlloc() operation. Use this
+ * function if all the BDs allocated by XEmacPs_BdRingAlloc() could not be
+ * transferred to hardware with XEmacPs_BdRingToHw().
+ *
+ * This function helps out in situations when an unrelated error occurs after
+ * BDs have been allocated but before they have been given to hardware.
+ * An example of this type of error would be an OS running out of resources.
+ *
+ * This function is not the same as XEmacPs_BdRingFree(). The Free function
+ * returns BDs to the free list after they have been processed by hardware,
+ * while UnAlloc returns them before being processed by hardware.
+ *
+ * There are two scenarios where this function can be used. Full UnAlloc or
+ * Partial UnAlloc. A Full UnAlloc means all the BDs Alloc'd will be returned:
+ *
+ * <pre>
+ *    Status = XEmacPs_BdRingAlloc(MyRingPtr, 10, &BdPtr),
+ *        ...
+ *    if (Error)
+ *    {
+ *        Status = XEmacPs_BdRingUnAlloc(MyRingPtr, 10, &BdPtr),
+ *    }
+ * </pre>
+ *
+ * A partial UnAlloc means some of the BDs Alloc'd will be returned:
+ *
+ * <pre>
+ *    Status = XEmacPs_BdRingAlloc(MyRingPtr, 10, &BdPtr),
+ *    BdsLeft = 10,
+ *    CurBdPtr = BdPtr,
+ *
+ *    while (BdsLeft)
+ *    {
+ *       if (Error)
+ *       {
+ *          Status = XEmacPs_BdRingUnAlloc(MyRingPtr, BdsLeft, CurBdPtr),
+ *       }
+ *
+ *       CurBdPtr = XEmacPs_BdRingNext(MyRingPtr, CurBdPtr),
+ *       BdsLeft--,
+ *    }
+ * </pre>
+ *
+ * A partial UnAlloc must include the last BD in the list that was Alloc'd.
+ *
+ * @param RingPtr is a pointer to the instance to be worked on.
+ * @param NumBd is the number of BDs to allocate
+ * @param BdSetPtr is an output parameter, it points to the first BD available
+ *        for modification.
+ *
+ * @return
+ *   - XST_SUCCESS if the BDs were unallocated.
+ *   - XST_FAILURE if NumBd parameter was greater that the number of BDs in
+ *     the preprocessing state.
+ *
+ * @note This function should not be preempted by another XEmacPs_Bd function
+ *       call that modifies the BD space. It is the caller's responsibility to
+ *       provide a mutual exclusion mechanism.
+ *
+ *****************************************************************************/
+LONG XEmacPs_BdRingUnAlloc(XEmacPs_BdRing * RingPtr, u32 NumBd,
+               XEmacPs_Bd * BdSetPtr)
+{
+    LONG Status;
+    (void) BdSetPtr;
+    Xil_AssertNonvoid(RingPtr != NULL);
+    Xil_AssertNonvoid(BdSetPtr != NULL);
+
+    /* Enough BDs in the free state for the request? */
+    if (RingPtr->PreCnt < NumBd) {
+        Status = (LONG)(XST_FAILURE);
+    } else {
+    /* Set the return argument and move FreeHead backward */
+        XEMACPS_RING_SEEKBACK(RingPtr, (RingPtr->FreeHead), NumBd);
+    RingPtr->FreeCnt += NumBd;
+    RingPtr->PreCnt -= NumBd;
+        Status = (LONG)(XST_SUCCESS);
+    }
+    return Status;
+}
+
+
+/*****************************************************************************/
+/**
+ * Enqueue a set of BDs to hardware that were previously allocated by
+ * XEmacPs_BdRingAlloc(). Once this function returns, the argument BD set goes
+ * under hardware control. Any changes made to these BDs after this point will
+ * corrupt the BD list leading to data corruption and system instability.
+ *
+ * The set will be rejected if the last BD of the set does not mark the end of
+ * a packet (see XEmacPs_BdSetLast()).
+ *
+ * @param RingPtr is a pointer to the instance to be worked on.
+ * @param NumBd is the number of BDs in the set.
+ * @param BdSetPtr is the first BD of the set to commit to hardware.
+ *
+ * @return
+ *   - XST_SUCCESS if the set of BDs was accepted and enqueued to hardware.
+ *   - XST_FAILURE if the set of BDs was rejected because the last BD of the set
+ *     did not have its "last" bit set.
+ *   - XST_DMA_SG_LIST_ERROR if this function was called out of sequence with
+ *     XEmacPs_BdRingAlloc().
+ *
+ * @note This function should not be preempted by another XEmacPs_Bd function
+ *       call that modifies the BD space. It is the caller's responsibility to
+ *       provide a mutual exclusion mechanism.
+ *
+ *****************************************************************************/
+LONG XEmacPs_BdRingToHw(XEmacPs_BdRing * RingPtr, u32 NumBd,
+            XEmacPs_Bd * BdSetPtr)
+{
+    XEmacPs_Bd *CurBdPtr;
+    u32 i;
+    LONG Status;
+    /* if no bds to process, simply return. */
+    if (0U == NumBd){
+        Status = (LONG)(XST_SUCCESS);
+    } else {
+    /* Make sure we are in sync with XEmacPs_BdRingAlloc() */
+    if ((RingPtr->PreCnt < NumBd) || (RingPtr->PreHead != BdSetPtr)) {
+            Status = (LONG)(XST_DMA_SG_LIST_ERROR);
+        } else {
+    CurBdPtr = BdSetPtr;
+            for (i = 0U; i < NumBd; i++) {
+                CurBdPtr = (XEmacPs_Bd *)((void *)XEmacPs_BdRingNext(RingPtr, CurBdPtr));
+    }
+    /* Adjust ring pointers & counters */
+    XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->PreHead, NumBd);
+    RingPtr->PreCnt -= NumBd;
+    RingPtr->HwTail = CurBdPtr;
+    RingPtr->HwCnt += NumBd;
+
+            Status = (LONG)(XST_SUCCESS);
+        }
+    }
+    return Status;
+}
+
+
+/*****************************************************************************/
+/**
+ * Returns a set of BD(s) that have been processed by hardware. The returned
+ * BDs may be examined to determine the outcome of the DMA transaction(s).
+ * Once the BDs have been examined, the user must call XEmacPs_BdRingFree()
+ * in the same order which they were retrieved here. Example:
+ *
+ * <pre>
+ *        NumBd = XEmacPs_BdRingFromHwTx(MyRingPtr, MaxBd, &MyBdSet),
+ *        if (NumBd == 0)
+ *        {
+ *           * hardware has nothing ready for us yet*
+ *        }
+ *
+ *        CurBd = MyBdSet,
+ *        for (i=0; i<NumBd; i++)
+ *        {
+ *           * Examine CurBd for post processing *.....
+ *
+ *           * Onto next BD *
+ *           CurBd = XEmacPs_BdRingNext(MyRingPtr, CurBd),
+ *           }
+ *
+ *           XEmacPs_BdRingFree(MyRingPtr, NumBd, MyBdSet),  *Return list*
+ *        }
+ * </pre>
+ *
+ * A more advanced use of this function may allocate multiple sets of BDs.
+ * They must be retrieved from hardware and freed in the correct sequence:
+ * <pre>
+ *        * Legal *
+ *        XEmacPs_BdRingFromHwTx(MyRingPtr, NumBd1, &MySet1),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1),
+ *
+ *        * Legal *
+ *        XEmacPs_BdRingFromHwTx(MyRingPtr, NumBd1, &MySet1),
+ *        XEmacPs_BdRingFromHwTx(MyRingPtr, NumBd2, &MySet2),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd2, MySet2),
+ *
+ *        * Not legal *
+ *        XEmacPs_BdRingFromHwTx(MyRingPtr, NumBd1, &MySet1),
+ *        XEmacPs_BdRingFromHwTx(MyRingPtr, NumBd2, &MySet2),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd2, MySet2),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1),
+ * </pre>
+ *
+ * If hardware has only partially completed a packet spanning multiple BDs,
+ * then none of the BDs for that packet will be included in the results.
+ *
+ * @param RingPtr is a pointer to the instance to be worked on.
+ * @param BdLimit is the maximum number of BDs to return in the set.
+ * @param BdSetPtr is an output parameter, it points to the first BD available
+ *        for examination.
+ *
+ * @return
+ *   The number of BDs processed by hardware. A value of 0 indicates that no
+ *   data is available. No more than BdLimit BDs will be returned.
+ *
+ * @note Treat BDs returned by this function as read-only.
+ *
+ * @note This function should not be preempted by another XEmacPs_Bd function
+ *       call that modifies the BD space. It is the caller's responsibility to
+ *       provide a mutual exclusion mechanism.
+ *
+ *****************************************************************************/
+u32 XEmacPs_BdRingFromHwTx(XEmacPs_BdRing * RingPtr, u32 BdLimit,
+                 XEmacPs_Bd ** BdSetPtr)
+{
+    XEmacPs_Bd *CurBdPtr;
+    u32 BdStr = 0U;
+    u32 BdCount;
+    u32 BdPartialCount;
+    u32 Sop = 0U;
+    u32 Status;
+    u32 BdLimitLoc = BdLimit;
+    CurBdPtr = RingPtr->HwHead;
+    BdCount = 0U;
+    BdPartialCount = 0U;
+
+    /* If no BDs in work group, then there's nothing to search */
+    if (RingPtr->HwCnt == 0x00000000U) {
+        *BdSetPtr = NULL;
+        Status = 0U;
+    } else {
+
+        if (BdLimitLoc > RingPtr->HwCnt){
+            BdLimitLoc = RingPtr->HwCnt;
+    }
+    /* Starting at HwHead, keep moving forward in the list until:
+     *  - A BD is encountered with its new/used bit set which means
+     *    hardware has not completed processing of that BD.
+     *  - RingPtr->HwTail is reached and RingPtr->HwCnt is reached.
+     *  - The number of requested BDs has been processed
+     */
+        while (BdCount < BdLimitLoc) {
+        /* Read the status */
+            if(CurBdPtr != NULL){
+        BdStr = XEmacPs_BdRead(CurBdPtr, XEMACPS_BD_STAT_OFFSET);
+            }
+
+            if ((Sop == 0x00000000U) && ((BdStr & XEMACPS_TXBUF_USED_MASK)!=0x00000000U)){
+                Sop = 1U;
+            }
+            if (Sop == 0x00000001U) {
+            BdCount++;
+            BdPartialCount++;
+        }
+
+        /* hardware has processed this BD so check the "last" bit.
+         * If it is clear, then there are more BDs for the current
+         * packet. Keep a count of these partial packet BDs.
+         */
+            if ((Sop == 0x00000001U) && ((BdStr & XEMACPS_TXBUF_LAST_MASK)!=0x00000000U)) {
+                Sop = 0U;
+                BdPartialCount = 0U;
+        }
+
+        /* Move on to next BD in work group */
+        CurBdPtr = XEmacPs_BdRingNext(RingPtr, CurBdPtr);
+    }
+
+    /* Subtract off any partial packet BDs found */
+        BdCount -= BdPartialCount;
+
+    /* If BdCount is non-zero then BDs were found to return. Set return
+     * parameters, update pointers and counters, return success
+     */
+        if (BdCount > 0x00000000U) {
+        *BdSetPtr = RingPtr->HwHead;
+        RingPtr->HwCnt -= BdCount;
+        RingPtr->PostCnt += BdCount;
+        XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->HwHead, BdCount);
+            Status = (BdCount);
+        } else {
+            *BdSetPtr = NULL;
+            Status = 0U;
+    }
+    }
+    return Status;
+}
+
+
+/*****************************************************************************/
+/**
+ * Returns a set of BD(s) that have been processed by hardware. The returned
+ * BDs may be examined to determine the outcome of the DMA transaction(s).
+ * Once the BDs have been examined, the user must call XEmacPs_BdRingFree()
+ * in the same order which they were retrieved here. Example:
+ *
+ * <pre>
+ *        NumBd = XEmacPs_BdRingFromHwRx(MyRingPtr, MaxBd, &MyBdSet),
+ *
+ *        if (NumBd == 0)
+ *        {
+ *           *hardware has nothing ready for us yet*
+ *        }
+ *
+ *        CurBd = MyBdSet,
+ *        for (i=0; i<NumBd; i++)
+ *        {
+ *           * Examine CurBd for post processing *.....
+ *
+ *           * Onto next BD *
+ *           CurBd = XEmacPs_BdRingNext(MyRingPtr, CurBd),
+ *           }
+ *
+ *           XEmacPs_BdRingFree(MyRingPtr, NumBd, MyBdSet),  * Return list *
+ *        }
+ * </pre>
+ *
+ * A more advanced use of this function may allocate multiple sets of BDs.
+ * They must be retrieved from hardware and freed in the correct sequence:
+ * <pre>
+ *        * Legal *
+ *        XEmacPs_BdRingFromHwRx(MyRingPtr, NumBd1, &MySet1),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1),
+ *
+ *        * Legal *
+ *        XEmacPs_BdRingFromHwRx(MyRingPtr, NumBd1, &MySet1),
+ *        XEmacPs_BdRingFromHwRx(MyRingPtr, NumBd2, &MySet2),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd2, MySet2),
+ *
+ *        * Not legal *
+ *        XEmacPs_BdRingFromHwRx(MyRingPtr, NumBd1, &MySet1),
+ *        XEmacPs_BdRingFromHwRx(MyRingPtr, NumBd2, &MySet2),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd2, MySet2),
+ *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1),
+ * </pre>
+ *
+ * If hardware has only partially completed a packet spanning multiple BDs,
+ * then none of the BDs for that packet will be included in the results.
+ *
+ * @param RingPtr is a pointer to the instance to be worked on.
+ * @param BdLimit is the maximum number of BDs to return in the set.
+ * @param BdSetPtr is an output parameter, it points to the first BD available
+ *        for examination.
+ *
+ * @return
+ *   The number of BDs processed by hardware. A value of 0 indicates that no
+ *   data is available. No more than BdLimit BDs will be returned.
+ *
+ * @note Treat BDs returned by this function as read-only.
+ *
+ * @note This function should not be preempted by another XEmacPs_Bd function
+ *       call that modifies the BD space. It is the caller's responsibility to
+ *       provide a mutual exclusion mechanism.
+ *
+ *****************************************************************************/
+u32 XEmacPs_BdRingFromHwRx(XEmacPs_BdRing * RingPtr, u32 BdLimit,
+                 XEmacPs_Bd ** BdSetPtr)
+{
+    XEmacPs_Bd *CurBdPtr;
+    u32 BdStr = 0U;
+    u32 BdCount;
+    u32 BdPartialCount;
+    u32 Status;
+
+    CurBdPtr = RingPtr->HwHead;
+    BdCount = 0U;
+    BdPartialCount = 0U;
+
+    /* If no BDs in work group, then there's nothing to search */
+    if (RingPtr->HwCnt == 0x00000000U) {
+        *BdSetPtr = NULL;
+        Status = 0U;
+    } else {
+
+    /* Starting at HwHead, keep moving forward in the list until:
+     *  - A BD is encountered with its new/used bit set which means
+     *    hardware has completed processing of that BD.
+     *  - RingPtr->HwTail is reached and RingPtr->HwCnt is reached.
+     *  - The number of requested BDs has been processed
+     */
+    while (BdCount < BdLimit) {
+
+        /* Read the status */
+            if(CurBdPtr!=NULL){
+        BdStr = XEmacPs_BdRead(CurBdPtr, XEMACPS_BD_STAT_OFFSET);
+            }
+            if ((!(XEmacPs_BdIsRxNew(CurBdPtr)))==TRUE) {
+            break;
+        }
+
+        BdCount++;
+
+        /* hardware has processed this BD so check the "last" bit. If
+                 * it is clear, then there are more BDs for the current packet.
+                 * Keep a count of these partial packet BDs.
+         */
+            if ((BdStr & XEMACPS_RXBUF_EOF_MASK)!=0x00000000U) {
+                BdPartialCount = 0U;
+            } else {
+            BdPartialCount++;
+        }
+
+        /* Move on to next BD in work group */
+        CurBdPtr = XEmacPs_BdRingNext(RingPtr, CurBdPtr);
+    }
+
+    /* Subtract off any partial packet BDs found */
+    BdCount -= BdPartialCount;
+
+    /* If BdCount is non-zero then BDs were found to return. Set return
+     * parameters, update pointers and counters, return success
+     */
+        if (BdCount > 0x00000000U) {
+        *BdSetPtr = RingPtr->HwHead;
+        RingPtr->HwCnt -= BdCount;
+        RingPtr->PostCnt += BdCount;
+        XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->HwHead, BdCount);
+            Status = (BdCount);
+    }
+    else {
+        *BdSetPtr = NULL;
+            Status = 0U;
+    }
+}
+    return Status;
+}
+
+
+/*****************************************************************************/
+/**
+ * Frees a set of BDs that had been previously retrieved with
+ * XEmacPs_BdRingFromHw().
+ *
+ * @param RingPtr is a pointer to the instance to be worked on.
+ * @param NumBd is the number of BDs to free.
+ * @param BdSetPtr is the head of a list of BDs returned by
+ * XEmacPs_BdRingFromHw().
+ *
+ * @return
+ *   - XST_SUCCESS if the set of BDs was freed.
+ *   - XST_DMA_SG_LIST_ERROR if this function was called out of sequence with
+ *     XEmacPs_BdRingFromHw().
+ *
+ * @note This function should not be preempted by another XEmacPs_Bd function
+ *       call that modifies the BD space. It is the caller's responsibility to
+ *       provide a mutual exclusion mechanism.
+ *
+ *****************************************************************************/
+LONG XEmacPs_BdRingFree(XEmacPs_BdRing * RingPtr, u32 NumBd,
+            XEmacPs_Bd * BdSetPtr)
+{
+    LONG Status;
+    /* if no bds to process, simply return. */
+    if (0x00000000U == NumBd){
+        Status = (LONG)(XST_SUCCESS);
+    } else {
+    /* Make sure we are in sync with XEmacPs_BdRingFromHw() */
+    if ((RingPtr->PostCnt < NumBd) || (RingPtr->PostHead != BdSetPtr)) {
+            Status = (LONG)(XST_DMA_SG_LIST_ERROR);
+        } else {
+    /* Update pointers and counters */
+    RingPtr->FreeCnt += NumBd;
+    RingPtr->PostCnt -= NumBd;
+    XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->PostHead, NumBd);
+            Status = (LONG)(XST_SUCCESS);
+        }
+    }
+    return Status;
+}
+
+
+/*****************************************************************************/
+/**
+ * Check the internal data structures of the BD ring for the provided channel.
+ * The following checks are made:
+ *
+ *   - Is the BD ring linked correctly in physical address space.
+ *   - Do the internal pointers point to BDs in the ring.
+ *   - Do the internal counters add up.
+ *
+ * The channel should be stopped prior to calling this function.
+ *
+ * @param RingPtr is a pointer to the instance to be worked on.
+ * @param Direction is either XEMACPS_SEND or XEMACPS_RECV that indicates
+ *        which direction.
+ *
+ * @return
+ *   - XST_SUCCESS if the set of BDs was freed.
+ *   - XST_DMA_SG_NO_LIST if the list has not been created.
+ *   - XST_IS_STARTED if the channel is not stopped.
+ *   - XST_DMA_SG_LIST_ERROR if a problem is found with the internal data
+ *     structures. If this value is returned, the channel should be reset to
+ *     avoid data corruption or system instability.
+ *
+ * @note This function should not be preempted by another XEmacPs_Bd function
+ *       call that modifies the BD space. It is the caller's responsibility to
+ *       provide a mutual exclusion mechanism.
+ *
+ *****************************************************************************/
+LONG XEmacPs_BdRingCheck(XEmacPs_BdRing * RingPtr, u8 Direction)
+{
+    UINTPTR AddrV, AddrP;
+    u32 i;
+
+    if ((Direction != (u8)XEMACPS_SEND) && (Direction != (u8)XEMACPS_RECV)) {
+        return (LONG)(XST_INVALID_PARAM);
+    }
+
+    /* Is the list created */
+    if (RingPtr->AllCnt == 0x00000000U) {
+        return (LONG)(XST_DMA_SG_NO_LIST);
+    }
+
+    /* Can't check if channel is running */
+    if (RingPtr->RunState == (u32)XST_DMA_SG_IS_STARTED) {
+        return (LONG)(XST_IS_STARTED);
+    }
+
+    /* RunState doesn't make sense */
+    if (RingPtr->RunState != (u32)XST_DMA_SG_IS_STOPPED) {
+        return (LONG)(XST_DMA_SG_LIST_ERROR);
+    }
+
+    /* Verify internal pointers point to correct memory space */
+    AddrV = (UINTPTR) RingPtr->FreeHead;
+    if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) {
+        return (LONG)(XST_DMA_SG_LIST_ERROR);
+    }
+
+    AddrV = (UINTPTR) RingPtr->PreHead;
+    if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) {
+        return (LONG)(XST_DMA_SG_LIST_ERROR);
+    }
+
+    AddrV = (UINTPTR) RingPtr->HwHead;
+    if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) {
+        return (LONG)(XST_DMA_SG_LIST_ERROR);
+    }
+
+    AddrV = (UINTPTR) RingPtr->HwTail;
+    if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) {
+        return (LONG)(XST_DMA_SG_LIST_ERROR);
+    }
+
+    AddrV = (UINTPTR) RingPtr->PostHead;
+    if ((AddrV < RingPtr->BaseBdAddr) || (AddrV > RingPtr->HighBdAddr)) {
+        return (LONG)(XST_DMA_SG_LIST_ERROR);
+    }
+
+    /* Verify internal counters add up */
+    if ((RingPtr->HwCnt + RingPtr->PreCnt + RingPtr->FreeCnt +
+         RingPtr->PostCnt) != RingPtr->AllCnt) {
+        return (LONG)(XST_DMA_SG_LIST_ERROR);
+    }
+
+    /* Verify BDs are linked correctly */
+    AddrV = RingPtr->BaseBdAddr;
+    AddrP = RingPtr->PhysBaseAddr + RingPtr->Separation;
+
+    for (i = 1U; i < RingPtr->AllCnt; i++) {
+        /* Check BDA for this BD. It should point to next physical addr */
+        if (XEmacPs_BdRead(AddrV, XEMACPS_BD_ADDR_OFFSET) != AddrP) {
+            return (LONG)(XST_DMA_SG_LIST_ERROR);
+        }
+
+        /* Move on to next BD */
+        AddrV += RingPtr->Separation;
+        AddrP += RingPtr->Separation;
+    }
+
+    /* Last BD should have wrap bit set */
+    if (XEMACPS_SEND == Direction) {
+        if ((!XEmacPs_BdIsTxWrap(AddrV))==TRUE) {
+            return (LONG)(XST_DMA_SG_LIST_ERROR);
+        }
+    }
+    else {            /* XEMACPS_RECV */
+        if ((!XEmacPs_BdIsRxWrap(AddrV))==TRUE) {
+            return (LONG)(XST_DMA_SG_LIST_ERROR);
+        }
+    }
+
+    /* No problems found */
+    return (LONG)(XST_SUCCESS);
+}
+
+/*****************************************************************************/
+/**
+ * Set this bit to mark the last descriptor in the receive buffer descriptor
+ * list.
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @note
+ * C-style signature:
+ *    void XEmacPs_BdSetRxWrap(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+static void XEmacPs_BdSetRxWrap(UINTPTR BdPtr)
+{
+    u32 DataValueRx;
+    u32 *TempPtr;
+
+    BdPtr += (u32)(XEMACPS_BD_ADDR_OFFSET);
+    TempPtr = (u32 *)BdPtr;
+    if(TempPtr != NULL) {
+        DataValueRx = *TempPtr;
+        DataValueRx |= XEMACPS_RXBUF_WRAP_MASK;
+        *TempPtr = DataValueRx;
+    }
+}
+
+/*****************************************************************************/
+/**
+ * Sets this bit to mark the last descriptor in the transmit buffer
+ * descriptor list.
+ *
+ * @param  BdPtr is the BD pointer to operate on
+ *
+ * @note
+ * C-style signature:
+ *    void XEmacPs_BdSetTxWrap(XEmacPs_Bd* BdPtr)
+ *
+ *****************************************************************************/
+static void XEmacPs_BdSetTxWrap(UINTPTR BdPtr)
+{
+    u32 DataValueTx;
+    u32 *TempPtr;
+
+    BdPtr += (u32)(XEMACPS_BD_STAT_OFFSET);
+    TempPtr = (u32 *)BdPtr;
+    if(TempPtr != NULL) {
+        DataValueTx = *TempPtr;
+        DataValueTx |= XEMACPS_TXBUF_WRAP_MASK;
+        *TempPtr = DataValueTx;
+    }
+}
+
+/*****************************************************************************/
+/**
+ * Reset BD ring head and tail pointers.
+ *
+ * @param RingPtr is the instance to be worked on.
+ * @param virtaddrloc is the virtual base address of the user memory region.
+ *
+ * @note
+ * Should be called after XEmacPs_Stop()
+ *
+ * @note
+ * C-style signature:
+ *    void XEmacPs_BdRingPtrReset(XEmacPs_BdRing * RingPtr, void *virtaddrloc)
+ *
+ *****************************************************************************/
+void XEmacPs_BdRingPtrReset(XEmacPs_BdRing * RingPtr, void *virtaddrloc)
+{
+    RingPtr->FreeHead = virtaddrloc;
+    RingPtr->PreHead = virtaddrloc;
+    RingPtr->HwHead = virtaddrloc;
+    RingPtr->HwTail = virtaddrloc;
+    RingPtr->PostHead = virtaddrloc;
+}
+
+/** @} */

+ 215 - 0
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_bdring.h

@@ -0,0 +1,215 @@
+/******************************************************************************
+* Copyright (C) 2010 - 2020 Xilinx, Inc.  All rights reserved.
+* SPDX-License-Identifier: MIT
+******************************************************************************/
+
+/*****************************************************************************/
+/**
+*
+* @file xemacps_bdring.h
+* @addtogroup emacps_v3_11
+* @{
+*
+* The Xiline EmacPs Buffer Descriptor ring driver. This is part of EmacPs
+* DMA functionalities.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a wsy  01/10/10 First release
+* 2.1   srt  07/15/14 Add support for Zynq Ultrascale Mp architecture.
+* 3.0   kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.6   rb   09/08/17 HwCnt variable (in XEmacPs_BdRing structure) is
+*              changed to volatile.
+*
+* </pre>
+*
+******************************************************************************/
+
+#ifndef XEMACPS_BDRING_H    /* prevent curcular inclusions */
+#define XEMACPS_BDRING_H    /* by using protection macros */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**************************** Type Definitions *******************************/
+
+/** This is an internal structure used to maintain the DMA list */
+typedef struct {
+    UINTPTR PhysBaseAddr;/**< Physical address of 1st BD in list */
+    UINTPTR BaseBdAddr;     /**< Virtual address of 1st BD in list */
+    UINTPTR HighBdAddr;     /**< Virtual address of last BD in the list */
+    u32 Length;     /**< Total size of ring in bytes */
+    u32 RunState;     /**< Flag to indicate DMA is started */
+    u32 Separation;     /**< Number of bytes between the starting address
+                                  of adjacent BDs */
+    XEmacPs_Bd *FreeHead;
+                 /**< First BD in the free group */
+    XEmacPs_Bd *PreHead;/**< First BD in the pre-work group */
+    XEmacPs_Bd *HwHead; /**< First BD in the work group */
+    XEmacPs_Bd *HwTail; /**< Last BD in the work group */
+    XEmacPs_Bd *PostHead;
+                 /**< First BD in the post-work group */
+    XEmacPs_Bd *BdaRestart;
+                 /**< BDA to load when channel is started */
+
+    volatile u32 HwCnt;    /**< Number of BDs in work group */
+    u32 PreCnt;     /**< Number of BDs in pre-work group */
+    u32 FreeCnt;    /**< Number of allocatable BDs in the free group */
+    u32 PostCnt;    /**< Number of BDs in post-work group */
+    u32 AllCnt;     /**< Total Number of BDs for channel */
+} XEmacPs_BdRing;
+
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/*****************************************************************************/
+/**
+* Use this macro at initialization time to determine how many BDs will fit
+* in a BD list within the given memory constraints.
+*
+* The results of this macro can be provided to XEmacPs_BdRingCreate().
+*
+* @param Alignment specifies what byte alignment the BDs must fall on and
+*        must be a power of 2 to get an accurate calculation (32, 64, 128,...)
+* @param Bytes is the number of bytes to be used to store BDs.
+*
+* @return Number of BDs that can fit in the given memory area
+*
+* @note
+* C-style signature:
+*    u32 XEmacPs_BdRingCntCalc(u32 Alignment, u32 Bytes)
+*
+******************************************************************************/
+#define XEmacPs_BdRingCntCalc(Alignment, Bytes)                    \
+    (u32)((Bytes) / (sizeof(XEmacPs_Bd)))
+
+/*****************************************************************************/
+/**
+* Use this macro at initialization time to determine how many bytes of memory
+* is required to contain a given number of BDs at a given alignment.
+*
+* @param Alignment specifies what byte alignment the BDs must fall on. This
+*        parameter must be a power of 2 to get an accurate calculation (32, 64,
+*        128,...)
+* @param NumBd is the number of BDs to calculate memory size requirements for
+*
+* @return The number of bytes of memory required to create a BD list with the
+*         given memory constraints.
+*
+* @note
+* C-style signature:
+*    u32 XEmacPs_BdRingMemCalc(u32 Alignment, u32 NumBd)
+*
+******************************************************************************/
+#define XEmacPs_BdRingMemCalc(Alignment, NumBd)                    \
+    (u32)(sizeof(XEmacPs_Bd) * (NumBd))
+
+/****************************************************************************/
+/**
+* Return the total number of BDs allocated by this channel with
+* XEmacPs_BdRingCreate().
+*
+* @param  RingPtr is the DMA channel to operate on.
+*
+* @return The total number of BDs allocated for this channel.
+*
+* @note
+* C-style signature:
+*    u32 XEmacPs_BdRingGetCnt(XEmacPs_BdRing* RingPtr)
+*
+*****************************************************************************/
+#define XEmacPs_BdRingGetCnt(RingPtr) ((RingPtr)->AllCnt)
+
+/****************************************************************************/
+/**
+* Return the number of BDs allocatable with XEmacPs_BdRingAlloc() for pre-
+* processing.
+*
+* @param  RingPtr is the DMA channel to operate on.
+*
+* @return The number of BDs currently allocatable.
+*
+* @note
+* C-style signature:
+*    u32 XEmacPs_BdRingGetFreeCnt(XEmacPs_BdRing* RingPtr)
+*
+*****************************************************************************/
+#define XEmacPs_BdRingGetFreeCnt(RingPtr)   ((RingPtr)->FreeCnt)
+
+/****************************************************************************/
+/**
+* Return the next BD from BdPtr in a list.
+*
+* @param  RingPtr is the DMA channel to operate on.
+* @param  BdPtr is the BD to operate on.
+*
+* @return The next BD in the list relative to the BdPtr parameter.
+*
+* @note
+* C-style signature:
+*    XEmacPs_Bd *XEmacPs_BdRingNext(XEmacPs_BdRing* RingPtr,
+*                                      XEmacPs_Bd *BdPtr)
+*
+*****************************************************************************/
+#define XEmacPs_BdRingNext(RingPtr, BdPtr)                           \
+    (((UINTPTR)((void *)(BdPtr)) >= (RingPtr)->HighBdAddr) ?                     \
+    (XEmacPs_Bd*)((void*)(RingPtr)->BaseBdAddr) :                              \
+    (XEmacPs_Bd*)((UINTPTR)((void *)(BdPtr)) + (RingPtr)->Separation))
+
+/****************************************************************************/
+/**
+* Return the previous BD from BdPtr in the list.
+*
+* @param  RingPtr is the DMA channel to operate on.
+* @param  BdPtr is the BD to operate on
+*
+* @return The previous BD in the list relative to the BdPtr parameter.
+*
+* @note
+* C-style signature:
+*    XEmacPs_Bd *XEmacPs_BdRingPrev(XEmacPs_BdRing* RingPtr,
+*                                      XEmacPs_Bd *BdPtr)
+*
+*****************************************************************************/
+#define XEmacPs_BdRingPrev(RingPtr, BdPtr)                           \
+    (((UINTPTR)(BdPtr) <= (RingPtr)->BaseBdAddr) ?                     \
+    (XEmacPs_Bd*)(RingPtr)->HighBdAddr :                              \
+    (XEmacPs_Bd*)((UINTPTR)(BdPtr) - (RingPtr)->Separation))
+
+/************************** Function Prototypes ******************************/
+
+/*
+ * Scatter gather DMA related functions in xemacps_bdring.c
+ */
+LONG XEmacPs_BdRingCreate(XEmacPs_BdRing * RingPtr, UINTPTR PhysAddr,
+              UINTPTR VirtAddr, u32 Alignment, u32 BdCount);
+LONG XEmacPs_BdRingClone(XEmacPs_BdRing * RingPtr, XEmacPs_Bd * SrcBdPtr,
+             u8 Direction);
+LONG XEmacPs_BdRingAlloc(XEmacPs_BdRing * RingPtr, u32 NumBd,
+             XEmacPs_Bd ** BdSetPtr);
+LONG XEmacPs_BdRingUnAlloc(XEmacPs_BdRing * RingPtr, u32 NumBd,
+               XEmacPs_Bd * BdSetPtr);
+LONG XEmacPs_BdRingToHw(XEmacPs_BdRing * RingPtr, u32 NumBd,
+            XEmacPs_Bd * BdSetPtr);
+LONG XEmacPs_BdRingFree(XEmacPs_BdRing * RingPtr, u32 NumBd,
+            XEmacPs_Bd * BdSetPtr);
+u32 XEmacPs_BdRingFromHwTx(XEmacPs_BdRing * RingPtr, u32 BdLimit,
+                 XEmacPs_Bd ** BdSetPtr);
+u32 XEmacPs_BdRingFromHwRx(XEmacPs_BdRing * RingPtr, u32 BdLimit,
+                 XEmacPs_Bd ** BdSetPtr);
+LONG XEmacPs_BdRingCheck(XEmacPs_BdRing * RingPtr, u8 Direction);
+
+void XEmacPs_BdRingPtrReset(XEmacPs_BdRing * RingPtr, void *virtaddrloc);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* end of protection macros */
+/** @} */

+ 1133 - 0
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_control.c

@@ -0,0 +1,1133 @@
+/******************************************************************************
+* Copyright (C) 2009 - 2020 Xilinx, Inc.  All rights reserved.
+* SPDX-License-Identifier: MIT
+******************************************************************************/
+
+/*****************************************************************************/
+/**
+ *
+ * @file xemacps_control.c
+* @addtogroup emacps_v3_11
+* @{
+ *
+ * Functions in this file implement general purpose command and control related
+ * functionality. See xemacps.h for a detailed description of the driver.
+ *
+ * <pre>
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -------------------------------------------------------
+ * 1.00a wsy  01/10/10 First release
+ * 1.02a asa  11/05/12 Added a new API for deleting an entry from the HASH
+ *                       register. Added a new API for setting the BURST length
+ *                       in DMACR register.
+ * 2.1   srt  07/15/14 Add support for Zynq Ultrascale Mp architecture.
+ * 3.0   kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+ * 3.0   hk   02/20/15 Added support for jumbo frames.
+ * 3.2   hk   02/22/16 Added SGMII support for Zynq Ultrascale+ MPSoC.
+ * </pre>
+ *****************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xemacps.h"
+
+/************************** Constant Definitions *****************************/
+
+
+/**************************** Type Definitions *******************************/
+
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+
+/************************** Function Prototypes ******************************/
+
+
+/************************** Variable Definitions *****************************/
+
+
+/*****************************************************************************/
+/**
+ * Set the MAC address for this driver/device.  The address is a 48-bit value.
+ * The device must be stopped before calling this function.
+ *
+ * @param InstancePtr is a pointer to the instance to be worked on.
+ * @param AddressPtr is a pointer to a 6-byte MAC address.
+ * @param Index is a index to which MAC (1-4) address.
+ *
+ * @return
+ * - XST_SUCCESS if the MAC address was set successfully
+ * - XST_DEVICE_IS_STARTED if the device has not yet been stopped
+ *
+ *****************************************************************************/
+LONG XEmacPs_SetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index)
+{
+    u32 MacAddr;
+    u8 *Aptr = (u8 *)(void *)AddressPtr;
+    u8 IndexLoc = Index;
+    LONG Status;
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(Aptr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid((IndexLoc <= (u8)XEMACPS_MAX_MAC_ADDR) && (IndexLoc > 0x00U));
+
+    /* Be sure device has been stopped */
+    if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
+        Status = (LONG)(XST_DEVICE_IS_STARTED);
+    }
+    else{
+    /* Index ranges 1 to 4, for offset calculation is 0 to 3. */
+        IndexLoc--;
+
+    /* Set the MAC bits [31:0] in BOT */
+        MacAddr = *(Aptr);
+        MacAddr |= ((u32)(*(Aptr+1)) << 8U);
+        MacAddr |= ((u32)(*(Aptr+2)) << 16U);
+        MacAddr |= ((u32)(*(Aptr+3)) << 24U);
+    XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                ((u32)XEMACPS_LADDR1L_OFFSET + ((u32)IndexLoc * (u32)8)), MacAddr);
+
+    /* There are reserved bits in TOP so don't affect them */
+    MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                    ((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8)));
+
+        MacAddr &= (u32)(~XEMACPS_LADDR_MACH_MASK);
+
+    /* Set MAC bits [47:32] in TOP */
+        MacAddr |= (u32)(*(Aptr+4));
+        MacAddr |= (u32)(*(Aptr+5)) << 8U;
+
+    XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                ((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8)), MacAddr);
+
+        Status = (LONG)(XST_SUCCESS);
+    }
+    return Status;
+}
+
+
+/*****************************************************************************/
+/**
+ * Get the MAC address for this driver/device.
+ *
+ * @param InstancePtr is a pointer to the instance to be worked on.
+ * @param AddressPtr is an output parameter, and is a pointer to a buffer into
+ *        which the current MAC address will be copied.
+ * @param Index is a index to which MAC (1-4) address.
+ *
+ *****************************************************************************/
+void XEmacPs_GetMacAddress(XEmacPs *InstancePtr, void *AddressPtr, u8 Index)
+{
+    u32 MacAddr;
+    u8 *Aptr = (u8 *)(void *)AddressPtr;
+    u8 IndexLoc = Index;
+    Xil_AssertVoid(InstancePtr != NULL);
+    Xil_AssertVoid(Aptr != NULL);
+    Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
+    Xil_AssertVoid((IndexLoc <= (u8)XEMACPS_MAX_MAC_ADDR) && (IndexLoc > 0x00U));
+
+    /* Index ranges 1 to 4, for offset calculation is 0 to 3. */
+    IndexLoc--;
+
+    MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                    ((u32)XEMACPS_LADDR1L_OFFSET + ((u32)IndexLoc * (u32)8)));
+    *Aptr = (u8) MacAddr;
+    *(Aptr+1) = (u8) (MacAddr >> 8U);
+    *(Aptr+2) = (u8) (MacAddr >> 16U);
+    *(Aptr+3) = (u8) (MacAddr >> 24U);
+
+    /* Read MAC bits [47:32] in TOP */
+    MacAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                    ((u32)XEMACPS_LADDR1H_OFFSET + ((u32)IndexLoc * (u32)8)));
+    *(Aptr+4) = (u8) MacAddr;
+    *(Aptr+5) = (u8) (MacAddr >> 8U);
+}
+
+
+/*****************************************************************************/
+/**
+ * Set 48-bit MAC addresses in hash table.
+ * The device must be stopped before calling this function.
+ *
+ * The hash address register is 64 bits long and takes up two locations in
+ * the memory map. The least significant bits are stored in hash register
+ * bottom and the most significant bits in hash register top.
+ *
+ * The unicast hash enable and the multicast hash enable bits in the network
+ * configuration register enable the reception of hash matched frames. The
+ * destination address is reduced to a 6 bit index into the 64 bit hash
+ * register using the following hash function. The hash function is an XOR
+ * of every sixth bit of the destination address.
+ *
+ * <pre>
+ * hash_index[05] = da[05]^da[11]^da[17]^da[23]^da[29]^da[35]^da[41]^da[47]
+ * hash_index[04] = da[04]^da[10]^da[16]^da[22]^da[28]^da[34]^da[40]^da[46]
+ * hash_index[03] = da[03]^da[09]^da[15]^da[21]^da[27]^da[33]^da[39]^da[45]
+ * hash_index[02] = da[02]^da[08]^da[14]^da[20]^da[26]^da[32]^da[38]^da[44]
+ * hash_index[01] = da[01]^da[07]^da[13]^da[19]^da[25]^da[31]^da[37]^da[43]
+ * hash_index[00] = da[00]^da[06]^da[12]^da[18]^da[24]^da[30]^da[36]^da[42]
+ * </pre>
+ *
+ * da[0] represents the least significant bit of the first byte received,
+ * that is, the multicast/unicast indicator, and da[47] represents the most
+ * significant bit of the last byte received.
+ *
+ * If the hash index points to a bit that is set in the hash register then
+ * the frame will be matched according to whether the frame is multicast
+ * or unicast.
+ *
+ * A multicast match will be signaled if the multicast hash enable bit is
+ * set, da[0] is logic 1 and the hash index points to a bit set in the hash
+ * register.
+ *
+ * A unicast match will be signaled if the unicast hash enable bit is set,
+ * da[0] is logic 0 and the hash index points to a bit set in the hash
+ * register.
+ *
+ * To receive all multicast frames, the hash register should be set with
+ * all ones and the multicast hash enable bit should be set in the network
+ * configuration register.
+ *
+ *
+ * @param InstancePtr is a pointer to the instance to be worked on.
+ * @param AddressPtr is a pointer to a 6-byte MAC address.
+ *
+ * @return
+ * - XST_SUCCESS if the HASH MAC address was set successfully
+ * - XST_DEVICE_IS_STARTED if the device has not yet been stopped
+ * - XST_INVALID_PARAM if the HASH MAC address passed in does not meet
+ *   requirement after calculation
+ *
+ * @note
+ * Having Aptr be unsigned type prevents the following operations from sign
+ * extending.
+ *****************************************************************************/
+LONG XEmacPs_SetHash(XEmacPs *InstancePtr, void *AddressPtr)
+{
+    u32 HashAddr;
+    u8 *Aptr = (u8 *)(void *)AddressPtr;
+    u8 Temp1, Temp2, Temp3, Temp4, Temp5, Temp6, Temp7, Temp8;
+    u32 Result;
+    LONG Status;
+
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(AddressPtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
+
+    /* Be sure device has been stopped */
+    if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
+        Status = (LONG)(XST_DEVICE_IS_STARTED);
+    } else {
+        Temp1 = (*(Aptr+0)) & 0x3FU;
+        Temp2 = ((*(Aptr+0) >> 6U) & 0x03U) | ((*(Aptr+1) & 0x0FU) << 2U);
+
+        Temp3 = ((*(Aptr+1) >> 4U) & 0x0FU) | ((*(Aptr+2) & 0x3U) << 4U);
+        Temp4 = ((*(Aptr+2) >> 2U) & 0x3FU);
+        Temp5 =   (*(Aptr+3)) & 0x3FU;
+        Temp6 = ((*(Aptr+3) >> 6U) & 0x03U) | ((*(Aptr+4) & 0x0FU) << 2U);
+        Temp7 = ((*(Aptr+4) >> 4U) & 0x0FU) | ((*(Aptr+5) & 0x03U) << 4U);
+        Temp8 = ((*(Aptr+5) >> 2U) & 0x3FU);
+
+        Result = (u32)((u32)Temp1 ^ (u32)Temp2 ^ (u32)Temp3 ^ (u32)Temp4 ^
+                (u32)Temp5 ^ (u32)Temp6 ^ (u32)Temp7 ^ (u32)Temp8);
+
+        if (Result >= (u32)XEMACPS_MAX_HASH_BITS) {
+            Status = (LONG)(XST_INVALID_PARAM);
+        } else {
+
+            if (Result < (u32)32) {
+        HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                XEMACPS_HASHL_OFFSET);
+                HashAddr |= (u32)(0x00000001U << Result);
+        XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+            XEMACPS_HASHL_OFFSET, HashAddr);
+    } else {
+        HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                XEMACPS_HASHH_OFFSET);
+                HashAddr |= (u32)(0x00000001U << (u32)(Result - (u32)32));
+        XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+            XEMACPS_HASHH_OFFSET, HashAddr);
+    }
+            Status = (LONG)(XST_SUCCESS);
+        }
+    }
+    return Status;
+}
+
+/*****************************************************************************/
+/**
+ * Delete 48-bit MAC addresses in hash table.
+ * The device must be stopped before calling this function.
+ *
+ * @param InstancePtr is a pointer to the instance to be worked on.
+ * @param AddressPtr is a pointer to a 6-byte MAC address.
+ *
+ * @return
+ * - XST_SUCCESS if the HASH MAC address was deleted successfully
+ * - XST_DEVICE_IS_STARTED if the device has not yet been stopped
+ * - XST_INVALID_PARAM if the HASH MAC address passed in does not meet
+ *   requirement after calculation
+ *
+ * @note
+ * Having Aptr be unsigned type prevents the following operations from sign
+ * extending.
+ *****************************************************************************/
+LONG XEmacPs_DeleteHash(XEmacPs *InstancePtr, void *AddressPtr)
+{
+    u32 HashAddr;
+    u8 *Aptr = (u8 *)(void *)AddressPtr;
+    u8 Temp1, Temp2, Temp3, Temp4, Temp5, Temp6, Temp7, Temp8;
+    u32 Result;
+    LONG Status;
+
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(Aptr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
+
+    /* Be sure device has been stopped */
+    if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
+        Status = (LONG)(XST_DEVICE_IS_STARTED);
+    } else {
+        Temp1 = (*(Aptr+0)) & 0x3FU;
+        Temp2 = ((*(Aptr+0) >> 6U) & 0x03U) | ((*(Aptr+1) & 0x0FU) << 2U);
+        Temp3 = ((*(Aptr+1) >> 4U) & 0x0FU) | ((*(Aptr+2) & 0x03U) << 4U);
+        Temp4 = ((*(Aptr+2) >> 2U) & 0x3FU);
+        Temp5 =   (*(Aptr+3)) & 0x3FU;
+        Temp6 = ((*(Aptr+3) >> 6U) & 0x03U) | ((*(Aptr+4) & 0x0FU) << 2U);
+        Temp7 = ((*(Aptr+4) >> 4U) & 0x0FU) | ((*(Aptr+5) & 0x03U) << 4U);
+        Temp8 = ((*(Aptr+5) >> 2U) & 0x3FU);
+
+        Result = (u32)((u32)Temp1 ^ (u32)Temp2 ^ (u32)Temp3 ^ (u32)Temp4 ^
+                    (u32)Temp5 ^ (u32)Temp6 ^ (u32)Temp7 ^ (u32)Temp8);
+
+        if (Result >= (u32)(XEMACPS_MAX_HASH_BITS)) {
+            Status =  (LONG)(XST_INVALID_PARAM);
+        } else {
+            if (Result < (u32)32) {
+        HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                XEMACPS_HASHL_OFFSET);
+                HashAddr &= (u32)(~(0x00000001U << Result));
+        XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                XEMACPS_HASHL_OFFSET, HashAddr);
+    } else {
+        HashAddr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                XEMACPS_HASHH_OFFSET);
+                HashAddr &= (u32)(~(0x00000001U << (u32)(Result - (u32)32)));
+        XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+            XEMACPS_HASHH_OFFSET, HashAddr);
+    }
+            Status = (LONG)(XST_SUCCESS);
+        }
+    }
+    return Status;
+}
+/*****************************************************************************/
+/**
+ * Clear the Hash registers for the mac address pointed by AddressPtr.
+ *
+ * @param InstancePtr is a pointer to the instance to be worked on.
+ *
+ *****************************************************************************/
+void XEmacPs_ClearHash(XEmacPs *InstancePtr)
+{
+    Xil_AssertVoid(InstancePtr != NULL);
+    Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
+
+    XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                    XEMACPS_HASHL_OFFSET, 0x0U);
+
+    /* write bits [63:32] in TOP */
+    XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                    XEMACPS_HASHH_OFFSET, 0x0U);
+}
+
+
+/*****************************************************************************/
+/**
+ * Get the Hash address for this driver/device.
+ *
+ * @param InstancePtr is a pointer to the instance to be worked on.
+ * @param AddressPtr is an output parameter, and is a pointer to a buffer into
+ *        which the current HASH MAC address will be copied.
+ *
+ *****************************************************************************/
+void XEmacPs_GetHash(XEmacPs *InstancePtr, void *AddressPtr)
+{
+    u32 *Aptr = (u32 *)(void *)AddressPtr;
+
+    Xil_AssertVoid(InstancePtr != NULL);
+    Xil_AssertVoid(AddressPtr != NULL);
+    Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
+
+    *(Aptr+0) = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                    XEMACPS_HASHL_OFFSET);
+
+    /* Read Hash bits [63:32] in TOP */
+    *(Aptr+1) = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                    XEMACPS_HASHH_OFFSET);
+}
+
+
+/*****************************************************************************/
+/**
+ * Set the Type ID match for this driver/device.  The register is a 32-bit
+ * value. The device must be stopped before calling this function.
+ *
+ * @param InstancePtr is a pointer to the instance to be worked on.
+ * @param Id_Check is type ID to be configured.
+ * @param Index is a index to which Type ID (1-4).
+ *
+ * @return
+ * - XST_SUCCESS if the MAC address was set successfully
+ * - XST_DEVICE_IS_STARTED if the device has not yet been stopped
+ *
+ *****************************************************************************/
+LONG XEmacPs_SetTypeIdCheck(XEmacPs *InstancePtr, u32 Id_Check, u8 Index)
+{
+    u8 IndexLoc = Index;
+    LONG Status;
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid((IndexLoc <= (u8)XEMACPS_MAX_TYPE_ID) && (IndexLoc > 0x00U));
+
+    /* Be sure device has been stopped */
+    if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
+        Status = (LONG)(XST_DEVICE_IS_STARTED);
+    } else {
+
+    /* Index ranges 1 to 4, for offset calculation is 0 to 3. */
+        IndexLoc--;
+
+    /* Set the ID bits in MATCHx register */
+    XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                   ((u32)XEMACPS_MATCH1_OFFSET + ((u32)IndexLoc * (u32)4)), Id_Check);
+
+        Status = (LONG)(XST_SUCCESS);
+    }
+    return Status;
+}
+
+/*****************************************************************************/
+/**
+ * Set options for the driver/device. The driver should be stopped with
+ * XEmacPs_Stop() before changing options.
+ *
+ * @param InstancePtr is a pointer to the instance to be worked on.
+ * @param Options are the options to set. Multiple options can be set by OR'ing
+ *        XTE_*_OPTIONS constants together. Options not specified are not
+ *        affected.
+ *
+ * @return
+ * - XST_SUCCESS if the options were set successfully
+ * - XST_DEVICE_IS_STARTED if the device has not yet been stopped
+ *
+ * @note
+ * See xemacps.h for a description of the available options.
+ *
+ *****************************************************************************/
+LONG XEmacPs_SetOptions(XEmacPs *InstancePtr, u32 Options)
+{
+    u32 Reg;        /* Generic register contents */
+    u32 RegNetCfg;        /* Reflects original contents of NET_CONFIG */
+    u32 RegNewNetCfg;    /* Reflects new contents of NET_CONFIG */
+    LONG Status;
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
+
+    /* Be sure device has been stopped */
+    if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
+        Status = (LONG)(XST_DEVICE_IS_STARTED);
+    } else {
+
+    /* Many of these options will change the NET_CONFIG registers.
+     * To reduce the amount of IO to the device, group these options here
+     * and change them all at once.
+     */
+
+    /* Grab current register contents */
+    RegNetCfg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                      XEMACPS_NWCFG_OFFSET);
+    RegNewNetCfg = RegNetCfg;
+
+    /*
+     * It is configured to max 1536.
+     */
+        if ((Options & XEMACPS_FRAME1536_OPTION) != 0x00000000U) {
+        RegNewNetCfg |= (XEMACPS_NWCFG_1536RXEN_MASK);
+    }
+
+    /* Turn on VLAN packet only, only VLAN tagged will be accepted */
+        if ((Options & XEMACPS_VLAN_OPTION) != 0x00000000U) {
+        RegNewNetCfg |= XEMACPS_NWCFG_NVLANDISC_MASK;
+    }
+
+    /* Turn on FCS stripping on receive packets */
+        if ((Options & XEMACPS_FCS_STRIP_OPTION) != 0x00000000U) {
+        RegNewNetCfg |= XEMACPS_NWCFG_FCSREM_MASK;
+    }
+
+    /* Turn on length/type field checking on receive packets */
+        if ((Options & XEMACPS_LENTYPE_ERR_OPTION) != 0x00000000U) {
+            RegNewNetCfg |= XEMACPS_NWCFG_LENERRDSCRD_MASK;
+    }
+
+    /* Turn on flow control */
+        if ((Options & XEMACPS_FLOW_CONTROL_OPTION) != 0x00000000U) {
+        RegNewNetCfg |= XEMACPS_NWCFG_PAUSEEN_MASK;
+    }
+
+    /* Turn on promiscuous frame filtering (all frames are received) */
+        if ((Options & XEMACPS_PROMISC_OPTION) != 0x00000000U) {
+        RegNewNetCfg |= XEMACPS_NWCFG_COPYALLEN_MASK;
+    }
+
+    /* Allow broadcast address reception */
+        if ((Options & XEMACPS_BROADCAST_OPTION) != 0x00000000U) {
+            RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_BCASTDI_MASK);
+    }
+
+    /* Allow multicast address filtering */
+        if ((Options & XEMACPS_MULTICAST_OPTION) != 0x00000000U) {
+        RegNewNetCfg |= XEMACPS_NWCFG_MCASTHASHEN_MASK;
+    }
+
+    /* enable RX checksum offload */
+        if ((Options & XEMACPS_RX_CHKSUM_ENABLE_OPTION) != 0x00000000U) {
+        RegNewNetCfg |= XEMACPS_NWCFG_RXCHKSUMEN_MASK;
+    }
+
+    /* Enable jumbo frames */
+    if (((Options & XEMACPS_JUMBO_ENABLE_OPTION) != 0x00000000U) &&
+        (InstancePtr->Version > 2)) {
+        RegNewNetCfg |= XEMACPS_NWCFG_JUMBO_MASK;
+        XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+            XEMACPS_JUMBOMAXLEN_OFFSET, XEMACPS_RX_BUF_SIZE_JUMBO);
+        Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                      XEMACPS_DMACR_OFFSET);
+        Reg &= ~XEMACPS_DMACR_RXBUF_MASK;
+        Reg |= (((((u32)XEMACPS_RX_BUF_SIZE_JUMBO / (u32)XEMACPS_RX_BUF_UNIT) +
+            (((((u32)XEMACPS_RX_BUF_SIZE_JUMBO %
+            (u32)XEMACPS_RX_BUF_UNIT))!=(u32)0) ? 1U : 0U)) <<
+            (u32)(XEMACPS_DMACR_RXBUF_SHIFT)) &
+            (u32)(XEMACPS_DMACR_RXBUF_MASK));
+        XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+            XEMACPS_DMACR_OFFSET, Reg);
+        InstancePtr->MaxMtuSize = XEMACPS_MTU_JUMBO;
+        InstancePtr->MaxFrameSize = XEMACPS_MTU_JUMBO +
+                    XEMACPS_HDR_SIZE + XEMACPS_TRL_SIZE;
+        InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize +
+                    XEMACPS_HDR_VLAN_SIZE;
+        InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_JUMBO_MASK;
+    }
+
+    if (((Options & XEMACPS_SGMII_ENABLE_OPTION) != 0x00000000U) &&
+        (InstancePtr->Version > 2)) {
+        RegNewNetCfg |= (XEMACPS_NWCFG_SGMIIEN_MASK |
+                        XEMACPS_NWCFG_PCSSEL_MASK);
+    }
+
+    /* Officially change the NET_CONFIG registers if it needs to be
+     * modified.
+     */
+    if (RegNetCfg != RegNewNetCfg) {
+        XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                   XEMACPS_NWCFG_OFFSET, RegNewNetCfg);
+    }
+
+    /* Enable TX checksum offload */
+        if ((Options & XEMACPS_TX_CHKSUM_ENABLE_OPTION) != 0x00000000U) {
+        Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                    XEMACPS_DMACR_OFFSET);
+        Reg |= XEMACPS_DMACR_TCPCKSUM_MASK;
+        XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                     XEMACPS_DMACR_OFFSET, Reg);
+    }
+
+    /* Enable transmitter */
+        if ((Options & XEMACPS_TRANSMITTER_ENABLE_OPTION) != 0x00000000U) {
+        Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                    XEMACPS_NWCTRL_OFFSET);
+        Reg |= XEMACPS_NWCTRL_TXEN_MASK;
+        XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                   XEMACPS_NWCTRL_OFFSET, Reg);
+    }
+
+    /* Enable receiver */
+        if ((Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) {
+        Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                    XEMACPS_NWCTRL_OFFSET);
+        Reg |= XEMACPS_NWCTRL_RXEN_MASK;
+        XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                   XEMACPS_NWCTRL_OFFSET, Reg);
+    }
+
+    /* The remaining options not handled here are managed elsewhere in the
+     * driver. No register modifications are needed at this time. Reflecting
+     * the option in InstancePtr->Options is good enough for now.
+     */
+
+    /* Set options word to its new value */
+    InstancePtr->Options |= Options;
+
+        Status = (LONG)(XST_SUCCESS);
+    }
+    return Status;
+}
+
+
+/*****************************************************************************/
+/**
+ * Clear options for the driver/device
+ *
+ * @param InstancePtr is a pointer to the instance to be worked on.
+ * @param Options are the options to clear. Multiple options can be cleared by
+ *        OR'ing XEMACPS_*_OPTIONS constants together. Options not specified
+ *        are not affected.
+ *
+ * @return
+ * - XST_SUCCESS if the options were set successfully
+ * - XST_DEVICE_IS_STARTED if the device has not yet been stopped
+ *
+ * @note
+ * See xemacps.h for a description of the available options.
+ *
+ *****************************************************************************/
+LONG XEmacPs_ClearOptions(XEmacPs *InstancePtr, u32 Options)
+{
+    u32 Reg;        /* Generic */
+    u32 RegNetCfg;        /* Reflects original contents of NET_CONFIG */
+    u32 RegNewNetCfg;    /* Reflects new contents of NET_CONFIG */
+    LONG Status;
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
+
+    /* Be sure device has been stopped */
+    if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
+        Status = (LONG)(XST_DEVICE_IS_STARTED);
+    } else {
+
+    /* Many of these options will change the NET_CONFIG registers.
+     * To reduce the amount of IO to the device, group these options here
+     * and change them all at once.
+     */
+
+    /* Grab current register contents */
+    RegNetCfg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                      XEMACPS_NWCFG_OFFSET);
+    RegNewNetCfg = RegNetCfg;
+
+    /* There is only RX configuration!?
+     * It is configured in two different length, up to 1536 and 10240 bytes
+     */
+        if ((Options & XEMACPS_FRAME1536_OPTION) != 0x00000000U) {
+            RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_1536RXEN_MASK);
+    }
+
+    /* Turn off VLAN packet only */
+        if ((Options & XEMACPS_VLAN_OPTION) != 0x00000000U) {
+            RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_NVLANDISC_MASK);
+    }
+
+    /* Turn off FCS stripping on receive packets */
+        if ((Options & XEMACPS_FCS_STRIP_OPTION) != 0x00000000U) {
+            RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_FCSREM_MASK);
+    }
+
+    /* Turn off length/type field checking on receive packets */
+        if ((Options & XEMACPS_LENTYPE_ERR_OPTION) != 0x00000000U) {
+            RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_LENERRDSCRD_MASK);
+    }
+
+    /* Turn off flow control */
+        if ((Options & XEMACPS_FLOW_CONTROL_OPTION) != 0x00000000U) {
+            RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_PAUSEEN_MASK);
+    }
+
+    /* Turn off promiscuous frame filtering (all frames are received) */
+        if ((Options & XEMACPS_PROMISC_OPTION) != 0x00000000U) {
+            RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_COPYALLEN_MASK);
+    }
+
+    /* Disallow broadcast address filtering => broadcast reception */
+        if ((Options & XEMACPS_BROADCAST_OPTION) != 0x00000000U) {
+        RegNewNetCfg |= XEMACPS_NWCFG_BCASTDI_MASK;
+    }
+
+    /* Disallow multicast address filtering */
+        if ((Options & XEMACPS_MULTICAST_OPTION) != 0x00000000U) {
+            RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_MCASTHASHEN_MASK);
+    }
+
+    /* Disable RX checksum offload */
+        if ((Options & XEMACPS_RX_CHKSUM_ENABLE_OPTION) != 0x00000000U) {
+            RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_RXCHKSUMEN_MASK);
+    }
+
+    /* Disable jumbo frames */
+    if (((Options & XEMACPS_JUMBO_ENABLE_OPTION) != 0x00000000U) &&
+        (InstancePtr->Version > 2)) {
+        RegNewNetCfg &= (u32)(~XEMACPS_NWCFG_JUMBO_MASK);
+        Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                      XEMACPS_DMACR_OFFSET);
+        Reg &= ~XEMACPS_DMACR_RXBUF_MASK;
+        Reg |= (((((u32)XEMACPS_RX_BUF_SIZE / (u32)XEMACPS_RX_BUF_UNIT) +
+            (((((u32)XEMACPS_RX_BUF_SIZE %
+            (u32)XEMACPS_RX_BUF_UNIT))!=(u32)0) ? 1U : 0U)) <<
+            (u32)(XEMACPS_DMACR_RXBUF_SHIFT)) &
+            (u32)(XEMACPS_DMACR_RXBUF_MASK));
+        XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+            XEMACPS_DMACR_OFFSET, Reg);
+        InstancePtr->MaxMtuSize = XEMACPS_MTU;
+        InstancePtr->MaxFrameSize = XEMACPS_MTU +
+                    XEMACPS_HDR_SIZE + XEMACPS_TRL_SIZE;
+        InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize +
+                    XEMACPS_HDR_VLAN_SIZE;
+        InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_MASK;
+    }
+
+    if (((Options & XEMACPS_SGMII_ENABLE_OPTION) != 0x00000000U) &&
+        (InstancePtr->Version > 2)) {
+        RegNewNetCfg &= (u32)(~(XEMACPS_NWCFG_SGMIIEN_MASK |
+                        XEMACPS_NWCFG_PCSSEL_MASK));
+    }
+
+    /* Officially change the NET_CONFIG registers if it needs to be
+     * modified.
+     */
+    if (RegNetCfg != RegNewNetCfg) {
+        XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                   XEMACPS_NWCFG_OFFSET, RegNewNetCfg);
+    }
+
+    /* Disable TX checksum offload */
+        if ((Options & XEMACPS_TX_CHKSUM_ENABLE_OPTION) != 0x00000000U) {
+        Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                    XEMACPS_DMACR_OFFSET);
+            Reg &= (u32)(~XEMACPS_DMACR_TCPCKSUM_MASK);
+        XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                     XEMACPS_DMACR_OFFSET, Reg);
+    }
+
+    /* Disable transmitter */
+        if ((Options & XEMACPS_TRANSMITTER_ENABLE_OPTION) != 0x00000000U) {
+        Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                    XEMACPS_NWCTRL_OFFSET);
+            Reg &= (u32)(~XEMACPS_NWCTRL_TXEN_MASK);
+        XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                   XEMACPS_NWCTRL_OFFSET, Reg);
+    }
+
+    /* Disable receiver */
+        if ((Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) {
+        Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                    XEMACPS_NWCTRL_OFFSET);
+            Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK);
+        XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                   XEMACPS_NWCTRL_OFFSET, Reg);
+    }
+
+    /* The remaining options not handled here are managed elsewhere in the
+     * driver. No register modifications are needed at this time. Reflecting
+     * option in InstancePtr->Options is good enough for now.
+     */
+
+    /* Set options word to its new value */
+    InstancePtr->Options &= ~Options;
+
+        Status = (LONG)(XST_SUCCESS);
+    }
+    return Status;
+}
+
+
+/*****************************************************************************/
+/**
+ * Get current option settings
+ *
+ * @param InstancePtr is a pointer to the instance to be worked on.
+ *
+ * @return
+ * A bitmask of XTE_*_OPTION constants. Any bit set to 1 is to be interpreted
+ * as a set option.
+ *
+ * @note
+ * See xemacps.h for a description of the available options.
+ *
+ *****************************************************************************/
+u32 XEmacPs_GetOptions(XEmacPs *InstancePtr)
+{
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
+
+    return (InstancePtr->Options);
+}
+
+
+/*****************************************************************************/
+/**
+ * Send a pause packet
+ *
+ * @param InstancePtr is a pointer to the instance to be worked on.
+ *
+ * @return
+ * - XST_SUCCESS if pause frame transmission was initiated
+ * - XST_DEVICE_IS_STOPPED if the device has not been started.
+ *
+ *****************************************************************************/
+LONG XEmacPs_SendPausePacket(XEmacPs *InstancePtr)
+{
+    u32 Reg;
+    LONG Status;
+
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
+
+    /* Make sure device is ready for this operation */
+    if (InstancePtr->IsStarted != (u32)XIL_COMPONENT_IS_STARTED) {
+        Status = (LONG)(XST_DEVICE_IS_STOPPED);
+    } else {
+    /* Send flow control frame */
+    Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                XEMACPS_NWCTRL_OFFSET);
+    Reg |= XEMACPS_NWCTRL_PAUSETX_MASK;
+    XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+               XEMACPS_NWCTRL_OFFSET, Reg);
+        Status = (LONG)(XST_SUCCESS);
+    }
+    return Status;
+}
+
+/*****************************************************************************/
+/**
+ * XEmacPs_GetOperatingSpeed gets the current operating link speed. This may
+ * be the value set by XEmacPs_SetOperatingSpeed() or a hardware default.
+ *
+ * @param InstancePtr references the TEMAC channel on which to operate.
+ *
+ * @return XEmacPs_GetOperatingSpeed returns the link speed in units of
+ *         megabits per second.
+ *
+ * @note
+ *
+ *****************************************************************************/
+u16 XEmacPs_GetOperatingSpeed(XEmacPs *InstancePtr)
+{
+    u32 Reg;
+    u16 Status;
+
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
+
+    Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+            XEMACPS_NWCFG_OFFSET);
+
+    if ((Reg & XEMACPS_NWCFG_1000_MASK) != 0x00000000U) {
+        Status = (u16)(1000);
+    } else {
+        if ((Reg & XEMACPS_NWCFG_100_MASK) != 0x00000000U) {
+            Status = (u16)(100);
+        } else {
+            Status = (u16)(10);
+        }
+    }
+    return Status;
+}
+
+
+/*****************************************************************************/
+/**
+ * XEmacPs_SetOperatingSpeed sets the current operating link speed. For any
+ * traffic to be passed, this speed must match the current MII/GMII/SGMII/RGMII
+ * link speed.
+ *
+ * @param InstancePtr references the TEMAC channel on which to operate.
+ * @param Speed is the speed to set in units of Mbps. Valid values are 10, 100,
+ *        or 1000. XEmacPs_SetOperatingSpeed ignores invalid values.
+ *
+ * @note
+ *
+ *****************************************************************************/
+void XEmacPs_SetOperatingSpeed(XEmacPs *InstancePtr, u16 Speed)
+{
+        u32 Reg;
+        Xil_AssertVoid(InstancePtr != NULL);
+    Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
+    Xil_AssertVoid((Speed == (u16)10) || (Speed == (u16)100) || (Speed == (u16)1000));
+
+        Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+            XEMACPS_NWCFG_OFFSET);
+    Reg &= (u32)(~(XEMACPS_NWCFG_1000_MASK | XEMACPS_NWCFG_100_MASK));
+
+    switch (Speed) {
+        case (u16)10:
+                break;
+
+        case (u16)100:
+                Reg |= XEMACPS_NWCFG_100_MASK;
+                break;
+
+        case (u16)1000:
+                Reg |= XEMACPS_NWCFG_1000_MASK;
+                break;
+    }
+
+        /* Set register and return */
+        XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                XEMACPS_NWCFG_OFFSET, Reg);
+}
+
+
+/*****************************************************************************/
+/**
+ * Set the MDIO clock divisor.
+ *
+ * Calculating the divisor:
+ *
+ * <pre>
+ *              f[HOSTCLK]
+ *   f[MDC] = -----------------
+ *            (1 + Divisor) * 2
+ * </pre>
+ *
+ * where f[HOSTCLK] is the bus clock frequency in MHz, and f[MDC] is the
+ * MDIO clock frequency in MHz to the PHY. Typically, f[MDC] should not
+ * exceed 2.5 MHz. Some PHYs can tolerate faster speeds which means faster
+ * access. Here is the table to show values to generate MDC,
+ *
+ * <pre>
+ * 000 : divide pclk by   8 (pclk up to  20 MHz)
+ * 001 : divide pclk by  16 (pclk up to  40 MHz)
+ * 010 : divide pclk by  32 (pclk up to  80 MHz)
+ * 011 : divide pclk by  48 (pclk up to 120 MHz)
+ * 100 : divide pclk by  64 (pclk up to 160 MHz)
+ * 101 : divide pclk by  96 (pclk up to 240 MHz)
+ * 110 : divide pclk by 128 (pclk up to 320 MHz)
+ * 111 : divide pclk by 224 (pclk up to 540 MHz)
+ * </pre>
+ *
+ * @param InstancePtr is a pointer to the instance to be worked on.
+ * @param Divisor is the divisor to set. Range is 0b000 to 0b111.
+ *
+ *****************************************************************************/
+void XEmacPs_SetMdioDivisor(XEmacPs *InstancePtr, XEmacPs_MdcDiv Divisor)
+{
+    u32 Reg;
+    Xil_AssertVoid(InstancePtr != NULL);
+    Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
+    Xil_AssertVoid(Divisor <= (XEmacPs_MdcDiv)0x7); /* only last three bits are valid */
+
+    Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                XEMACPS_NWCFG_OFFSET);
+    /* clear these three bits, could be done with mask */
+    Reg &= (u32)(~XEMACPS_NWCFG_MDCCLKDIV_MASK);
+
+    Reg |= ((u32)Divisor << XEMACPS_NWCFG_MDC_SHIFT_MASK);
+
+    XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+               XEMACPS_NWCFG_OFFSET, Reg);
+}
+
+
+/*****************************************************************************/
+/**
+* Read the current value of the PHY register indicated by the PhyAddress and
+* the RegisterNum parameters. The MAC provides the driver with the ability to
+* talk to a PHY that adheres to the Media Independent Interface (MII) as
+* defined in the IEEE 802.3 standard.
+*
+* Prior to PHY access with this function, the user should have setup the MDIO
+* clock with XEmacPs_SetMdioDivisor().
+*
+* @param InstancePtr is a pointer to the XEmacPs instance to be worked on.
+* @param PhyAddress is the address of the PHY to be read (supports multiple
+*        PHYs)
+* @param RegisterNum is the register number, 0-31, of the specific PHY register
+*        to read
+* @param PhyDataPtr is an output parameter, and points to a 16-bit buffer into
+*        which the current value of the register will be copied.
+*
+* @return
+*
+* - XST_SUCCESS if the PHY was read from successfully
+* - XST_EMAC_MII_BUSY if there is another PHY operation in progress
+*
+* @note
+*
+* This function is not thread-safe. The user must provide mutually exclusive
+* access to this function if there are to be multiple threads that can call it.
+*
+* There is the possibility that this function will not return if the hardware
+* is broken (i.e., it never sets the status bit indicating that the read is
+* done). If this is of concern to the user, the user should provide a mechanism
+* suitable to their needs for recovery.
+*
+* For the duration of this function, all host interface reads and writes are
+* blocked to the current XEmacPs instance.
+*
+******************************************************************************/
+LONG XEmacPs_PhyRead(XEmacPs *InstancePtr, u32 PhyAddress,
+             u32 RegisterNum, u16 *PhyDataPtr)
+{
+    u32 Mgtcr;
+    volatile u32 Ipisr;
+    u32 IpReadTemp;
+    LONG Status;
+
+    Xil_AssertNonvoid(InstancePtr != NULL);
+
+    /* Make sure no other PHY operation is currently in progress */
+    if ((!(XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                XEMACPS_NWSR_OFFSET) &
+          XEMACPS_NWSR_MDIOIDLE_MASK))==TRUE) {
+        Status = (LONG)(XST_EMAC_MII_BUSY);
+    } else {
+
+    /* Construct Mgtcr mask for the operation */
+    Mgtcr = XEMACPS_PHYMNTNC_OP_MASK | XEMACPS_PHYMNTNC_OP_R_MASK |
+            (PhyAddress << XEMACPS_PHYMNTNC_PHAD_SHFT_MSK) |
+            (RegisterNum << XEMACPS_PHYMNTNC_PREG_SHFT_MSK);
+
+    /* Write Mgtcr and wait for completion */
+    XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+               XEMACPS_PHYMNTNC_OFFSET, Mgtcr);
+
+    do {
+        Ipisr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                      XEMACPS_NWSR_OFFSET);
+            IpReadTemp = Ipisr;
+        } while ((IpReadTemp & XEMACPS_NWSR_MDIOIDLE_MASK) == 0x00000000U);
+
+    /* Read data */
+        *PhyDataPtr = (u16)XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                    XEMACPS_PHYMNTNC_OFFSET);
+        Status = (LONG)(XST_SUCCESS);
+    }
+    return Status;
+}
+
+
+/*****************************************************************************/
+/**
+* Write data to the specified PHY register. The Ethernet driver does not
+* require the device to be stopped before writing to the PHY.  Although it is
+* probably a good idea to stop the device, it is the responsibility of the
+* application to deem this necessary. The MAC provides the driver with the
+* ability to talk to a PHY that adheres to the Media Independent Interface
+* (MII) as defined in the IEEE 802.3 standard.
+*
+* Prior to PHY access with this function, the user should have setup the MDIO
+* clock with XEmacPs_SetMdioDivisor().
+*
+* @param InstancePtr is a pointer to the XEmacPs instance to be worked on.
+* @param PhyAddress is the address of the PHY to be written (supports multiple
+*        PHYs)
+* @param RegisterNum is the register number, 0-31, of the specific PHY register
+*        to write
+* @param PhyData is the 16-bit value that will be written to the register
+*
+* @return
+*
+* - XST_SUCCESS if the PHY was written to successfully. Since there is no error
+*   status from the MAC on a write, the user should read the PHY to verify the
+*   write was successful.
+* - XST_EMAC_MII_BUSY if there is another PHY operation in progress
+*
+* @note
+*
+* This function is not thread-safe. The user must provide mutually exclusive
+* access to this function if there are to be multiple threads that can call it.
+*
+* There is the possibility that this function will not return if the hardware
+* is broken (i.e., it never sets the status bit indicating that the write is
+* done). If this is of concern to the user, the user should provide a mechanism
+* suitable to their needs for recovery.
+*
+* For the duration of this function, all host interface reads and writes are
+* blocked to the current XEmacPs instance.
+*
+******************************************************************************/
+LONG XEmacPs_PhyWrite(XEmacPs *InstancePtr, u32 PhyAddress,
+              u32 RegisterNum, u16 PhyData)
+{
+    u32 Mgtcr;
+    volatile u32 Ipisr;
+    u32 IpWriteTemp;
+    LONG Status;
+
+    Xil_AssertNonvoid(InstancePtr != NULL);
+
+    /* Make sure no other PHY operation is currently in progress */
+    if ((!(XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                XEMACPS_NWSR_OFFSET) &
+          XEMACPS_NWSR_MDIOIDLE_MASK))==TRUE) {
+        Status = (LONG)(XST_EMAC_MII_BUSY);
+    } else {
+    /* Construct Mgtcr mask for the operation */
+    Mgtcr = XEMACPS_PHYMNTNC_OP_MASK | XEMACPS_PHYMNTNC_OP_W_MASK |
+            (PhyAddress << XEMACPS_PHYMNTNC_PHAD_SHFT_MSK) |
+            (RegisterNum << XEMACPS_PHYMNTNC_PREG_SHFT_MSK) | (u32)PhyData;
+
+    /* Write Mgtcr and wait for completion */
+    XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+               XEMACPS_PHYMNTNC_OFFSET, Mgtcr);
+
+    do {
+        Ipisr = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                      XEMACPS_NWSR_OFFSET);
+                IpWriteTemp = Ipisr;
+        } while ((IpWriteTemp & XEMACPS_NWSR_MDIOIDLE_MASK) == 0x00000000U);
+
+        Status = (LONG)(XST_SUCCESS);
+    }
+    return Status;
+}
+
+/*****************************************************************************/
+/**
+* API to update the Burst length in the DMACR register.
+*
+* @param InstancePtr is a pointer to the XEmacPs instance to be worked on.
+* @param BLength is the length in bytes for the dma burst.
+*
+* @return None
+*
+******************************************************************************/
+void XEmacPs_DMABLengthUpdate(XEmacPs *InstancePtr, s32 BLength)
+{
+    u32 Reg;
+    u32 RegUpdateVal = 0;
+
+    Xil_AssertVoid(InstancePtr != NULL);
+    Xil_AssertVoid((BLength == XEMACPS_SINGLE_BURST) ||
+                    (BLength == XEMACPS_4BYTE_BURST) ||
+                    (BLength == XEMACPS_8BYTE_BURST) ||
+                    (BLength == XEMACPS_16BYTE_BURST));
+
+    switch (BLength) {
+        case XEMACPS_SINGLE_BURST:
+            RegUpdateVal = XEMACPS_DMACR_SINGLE_AHB_BURST;
+            break;
+
+        case XEMACPS_4BYTE_BURST:
+            RegUpdateVal = XEMACPS_DMACR_INCR4_AHB_BURST;
+            break;
+
+        case XEMACPS_8BYTE_BURST:
+            RegUpdateVal = XEMACPS_DMACR_INCR8_AHB_BURST;
+            break;
+
+        case XEMACPS_16BYTE_BURST:
+            RegUpdateVal = XEMACPS_DMACR_INCR16_AHB_BURST;
+            break;
+    }
+    Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                        XEMACPS_DMACR_OFFSET);
+
+    Reg &= (u32)(~XEMACPS_DMACR_BLENGTH_MASK);
+    Reg |= RegUpdateVal;
+    XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET,
+                                                                    Reg);
+}
+/** @} */

+ 32 - 0
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_g.c

@@ -0,0 +1,32 @@
+
+/*******************************************************************
+*
+* CAUTION: This file is automatically generated by HSI.
+* Version: 2020.1
+* DO NOT EDIT.
+*
+* Copyright (C) 2010-2021 Xilinx, Inc. All Rights Reserved.
+* SPDX-License-Identifier: MIT
+
+*
+* Description: Driver configuration
+*
+*******************************************************************/
+
+#include "xparameters.h"
+#include "xemacps.h"
+
+/*
+* The configuration table for devices
+*/
+
+XEmacPs_Config XEmacPs_ConfigTable[XPAR_XEMACPS_NUM_INSTANCES] =
+{
+    {
+        XPAR_PSU_ETHERNET_3_DEVICE_ID,
+        XPAR_PSU_ETHERNET_3_BASEADDR,
+        XPAR_PSU_ETHERNET_3_IS_CACHE_COHERENT
+    }
+};
+
+

+ 97 - 0
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.c

@@ -0,0 +1,97 @@
+/******************************************************************************
+* Copyright (C) 2010 - 2020 Xilinx, Inc.  All rights reserved.
+* SPDX-License-Identifier: MIT
+******************************************************************************/
+
+/*****************************************************************************/
+/**
+*
+* @file xemacps_hw.c
+* @addtogroup emacps_v3_11
+* @{
+*
+* This file contains the implementation of the ethernet interface reset sequence
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.05a kpc  28/06/13 First release
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* </pre>
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xemacps_hw.h"
+#include "xparameters.h"
+
+/************************** Constant Definitions *****************************/
+
+
+/**************************** Type Definitions *******************************/
+
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+
+/************************** Function Prototypes ******************************/
+
+/*****************************************************************************/
+/**
+* This function perform the reset sequence to the given emacps interface by
+* configuring the appropriate control bits in the emacps specific registers.
+* the emacps reset sequence involves the following steps
+*    Disable all the interuupts
+*    Clear the status registers
+*    Disable Rx and Tx engines
+*    Update the Tx and Rx descriptor queue registers with reset values
+*    Update the other relevant control registers with reset value
+*
+* @param   BaseAddr of the interface
+*
+* @return N/A
+*
+* @note
+* This function will not modify the slcr registers that are relevant for
+* emacps controller
+******************************************************************************/
+void XEmacPs_ResetHw(u32 BaseAddr)
+{
+    u32 RegVal;
+
+    /* Disable the interrupts  */
+    XEmacPs_WriteReg(BaseAddr,XEMACPS_IDR_OFFSET,0x0U);
+
+    /* Stop transmission,disable loopback and Stop tx and Rx engines */
+    RegVal = XEmacPs_ReadReg(BaseAddr,XEMACPS_NWCTRL_OFFSET);
+    RegVal &= ~((u32)XEMACPS_NWCTRL_TXEN_MASK|
+                (u32)XEMACPS_NWCTRL_RXEN_MASK|
+                (u32)XEMACPS_NWCTRL_HALTTX_MASK|
+                (u32)XEMACPS_NWCTRL_LOOPEN_MASK);
+    /* Clear the statistic registers, flush the packets in DPRAM*/
+    RegVal |= (XEMACPS_NWCTRL_STATCLR_MASK|
+                XEMACPS_NWCTRL_FLUSH_DPRAM_MASK);
+    XEmacPs_WriteReg(BaseAddr,XEMACPS_NWCTRL_OFFSET,RegVal);
+    /* Clear the interrupt status */
+    XEmacPs_WriteReg(BaseAddr,XEMACPS_ISR_OFFSET,XEMACPS_IXR_ALL_MASK);
+    /* Clear the tx status */
+    XEmacPs_WriteReg(BaseAddr,XEMACPS_TXSR_OFFSET,(XEMACPS_TXSR_ERROR_MASK|
+                                    (u32)XEMACPS_TXSR_TXCOMPL_MASK|
+                                    (u32)XEMACPS_TXSR_TXGO_MASK));
+    /* Clear the rx status */
+    XEmacPs_WriteReg(BaseAddr,XEMACPS_RXSR_OFFSET,
+                                XEMACPS_RXSR_FRAMERX_MASK);
+    /* Clear the tx base address */
+    XEmacPs_WriteReg(BaseAddr,XEMACPS_TXQBASE_OFFSET,0x0U);
+    /* Clear the rx base address */
+    XEmacPs_WriteReg(BaseAddr,XEMACPS_RXQBASE_OFFSET,0x0U);
+    /* Update the network config register with reset value */
+    XEmacPs_WriteReg(BaseAddr,XEMACPS_NWCFG_OFFSET,XEMACPS_NWCFG_RESET_MASK);
+    /* Update the hash address registers with reset value */
+    XEmacPs_WriteReg(BaseAddr,XEMACPS_HASHL_OFFSET,0x0U);
+    XEmacPs_WriteReg(BaseAddr,XEMACPS_HASHH_OFFSET,0x0U);
+}
+/** @} */

+ 646 - 0
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_hw.h

@@ -0,0 +1,646 @@
+/******************************************************************************
+* Copyright (C) 2010 - 2020 Xilinx, Inc.  All rights reserved.
+* SPDX-License-Identifier: MIT
+******************************************************************************/
+
+/*****************************************************************************/
+/**
+*
+* @file xemacps_hw.h
+* @addtogroup emacps_v3_11
+* @{
+*
+* This header file contains identifiers and low-level driver functions (or
+* macros) that can be used to access the PS Ethernet MAC (XEmacPs) device.
+* High-level driver functions are defined in xemacps.h.
+*
+* @note
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a wsy  01/10/10 First release.
+* 1.02a asa  11/05/12 Added hash defines for DMACR burst length configuration.
+* 1.05a kpc  28/06/13 Added XEmacPs_ResetHw function prototype
+* 1.06a asa  11/02/13 Changed the value for XEMACPS_RXBUF_LEN_MASK from 0x3fff
+*                      to 0x1fff. This fixes the CR#744902.
+* 2.1   srt  07/15/14 Add support for Zynq Ultrascale Mp GEM specification.
+* 3.0   kvn  12/16/14 Changed name of XEMACPS_NWCFG_LENGTHERRDSCRD_MASK to
+*                      XEMACPS_NWCFG_LENERRDSCRD_MASK as it exceeds 31 characters.
+* 3.0  kpc   1/23/15  Corrected the extended descriptor macro values.
+* 3.0  kvn   02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.0  hk   03/18/15 Added support for jumbo frames.
+*                    Remove "used bit set" from TX error interrupt masks.
+* 3.1  hk   08/10/15 Update upper 32 bit tx and rx queue ptr register offsets.
+* 3.2   hk   02/22/16 Added SGMII support for Zynq Ultrascale+ MPSoC.
+* 3.8  hk   09/17/18 Fix PTP interrupt masks.
+* 3.9  hk   01/23/19 Add RX watermark support
+* 3.10 hk   05/16/19 Clear status registers properly in reset
+* </pre>
+*
+******************************************************************************/
+
+#ifndef XEMACPS_HW_H        /* prevent circular inclusions */
+#define XEMACPS_HW_H        /* by using protection macros */
+
+/***************************** Include Files *********************************/
+
+#include "xil_types.h"
+#include "xil_assert.h"
+#include "xil_io.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/************************** Constant Definitions *****************************/
+
+#define XEMACPS_MAX_MAC_ADDR     4U   /**< Maxmum number of mac address
+                                           supported */
+#define XEMACPS_MAX_TYPE_ID      4U   /**< Maxmum number of type id supported */
+
+#ifdef __aarch64__
+#define XEMACPS_BD_ALIGNMENT     64U   /**< Minimum buffer descriptor alignment
+                                           on the local bus */
+#else
+
+#define XEMACPS_BD_ALIGNMENT     4U   /**< Minimum buffer descriptor alignment
+                                           on the local bus */
+#endif
+#define XEMACPS_RX_BUF_ALIGNMENT 4U   /**< Minimum buffer alignment when using
+                                           options that impose alignment
+                                           restrictions on the buffer data on
+                                           the local bus */
+
+/** @name Direction identifiers
+ *
+ *  These are used by several functions and callbacks that need
+ *  to specify whether an operation specifies a send or receive channel.
+ * @{
+ */
+#define XEMACPS_SEND        1U          /**< send direction */
+#define XEMACPS_RECV        2U          /**< receive direction */
+/*@}*/
+
+/**  @name MDC clock division
+ *  currently supporting 8, 16, 32, 48, 64, 96, 128, 224.
+ * @{
+ */
+typedef enum { MDC_DIV_8 = 0U, MDC_DIV_16, MDC_DIV_32, MDC_DIV_48,
+    MDC_DIV_64, MDC_DIV_96, MDC_DIV_128, MDC_DIV_224
+} XEmacPs_MdcDiv;
+
+/*@}*/
+
+#define XEMACPS_RX_BUF_SIZE 1536U /**< Specify the receive buffer size in
+                                       bytes, 64, 128, ... 10240 */
+#define XEMACPS_RX_BUF_SIZE_JUMBO 10240U
+
+#define XEMACPS_RX_BUF_UNIT   64U /**< Number of receive buffer bytes as a
+                                       unit, this is HW setup */
+
+#define XEMACPS_MAX_RXBD     128U /**< Size of RX buffer descriptor queues */
+#define XEMACPS_MAX_TXBD     128U /**< Size of TX buffer descriptor queues */
+
+#define XEMACPS_MAX_HASH_BITS 64U /**< Maximum value for hash bits. 2**6 */
+
+/* Register offset definitions. Unless otherwise noted, register access is
+ * 32 bit. Names are self explained here.
+ */
+
+#define XEMACPS_NWCTRL_OFFSET        0x00000000U /**< Network Control reg */
+#define XEMACPS_NWCFG_OFFSET         0x00000004U /**< Network Config reg */
+#define XEMACPS_NWSR_OFFSET          0x00000008U /**< Network Status reg */
+
+#define XEMACPS_DMACR_OFFSET         0x00000010U /**< DMA Control reg */
+#define XEMACPS_TXSR_OFFSET          0x00000014U /**< TX Status reg */
+#define XEMACPS_RXQBASE_OFFSET       0x00000018U /**< RX Q Base address reg */
+#define XEMACPS_TXQBASE_OFFSET       0x0000001CU /**< TX Q Base address reg */
+#define XEMACPS_RXSR_OFFSET          0x00000020U /**< RX Status reg */
+
+#define XEMACPS_ISR_OFFSET           0x00000024U /**< Interrupt Status reg */
+#define XEMACPS_IER_OFFSET           0x00000028U /**< Interrupt Enable reg */
+#define XEMACPS_IDR_OFFSET           0x0000002CU /**< Interrupt Disable reg */
+#define XEMACPS_IMR_OFFSET           0x00000030U /**< Interrupt Mask reg */
+
+#define XEMACPS_PHYMNTNC_OFFSET      0x00000034U /**< Phy Maintaince reg */
+#define XEMACPS_RXPAUSE_OFFSET       0x00000038U /**< RX Pause Time reg */
+#define XEMACPS_TXPAUSE_OFFSET       0x0000003CU /**< TX Pause Time reg */
+
+#define XEMACPS_JUMBOMAXLEN_OFFSET   0x00000048U /**< Jumbo max length reg */
+
+#define XEMACPS_RXWATERMARK_OFFSET   0x0000007CU /**< RX watermark reg */
+
+#define XEMACPS_HASHL_OFFSET         0x00000080U /**< Hash Low address reg */
+#define XEMACPS_HASHH_OFFSET         0x00000084U /**< Hash High address reg */
+
+#define XEMACPS_LADDR1L_OFFSET       0x00000088U /**< Specific1 addr low reg */
+#define XEMACPS_LADDR1H_OFFSET       0x0000008CU /**< Specific1 addr high reg */
+#define XEMACPS_LADDR2L_OFFSET       0x00000090U /**< Specific2 addr low reg */
+#define XEMACPS_LADDR2H_OFFSET       0x00000094U /**< Specific2 addr high reg */
+#define XEMACPS_LADDR3L_OFFSET       0x00000098U /**< Specific3 addr low reg */
+#define XEMACPS_LADDR3H_OFFSET       0x0000009CU /**< Specific3 addr high reg */
+#define XEMACPS_LADDR4L_OFFSET       0x000000A0U /**< Specific4 addr low reg */
+#define XEMACPS_LADDR4H_OFFSET       0x000000A4U /**< Specific4 addr high reg */
+
+#define XEMACPS_MATCH1_OFFSET        0x000000A8U /**< Type ID1 Match reg */
+#define XEMACPS_MATCH2_OFFSET        0x000000ACU /**< Type ID2 Match reg */
+#define XEMACPS_MATCH3_OFFSET        0x000000B0U /**< Type ID3 Match reg */
+#define XEMACPS_MATCH4_OFFSET        0x000000B4U /**< Type ID4 Match reg */
+
+#define XEMACPS_STRETCH_OFFSET       0x000000BCU /**< IPG Stretch reg */
+
+#define XEMACPS_OCTTXL_OFFSET        0x00000100U /**< Octects transmitted Low
+                                                      reg */
+#define XEMACPS_OCTTXH_OFFSET        0x00000104U /**< Octects transmitted High
+                                                      reg */
+
+#define XEMACPS_TXCNT_OFFSET         0x00000108U /**< Error-free Frmaes
+                                                      transmitted counter */
+#define XEMACPS_TXBCCNT_OFFSET       0x0000010CU /**< Error-free Broadcast
+                                                      Frames counter*/
+#define XEMACPS_TXMCCNT_OFFSET       0x00000110U /**< Error-free Multicast
+                                                      Frame counter */
+#define XEMACPS_TXPAUSECNT_OFFSET    0x00000114U /**< Pause Frames Transmitted
+                                                      Counter */
+#define XEMACPS_TX64CNT_OFFSET       0x00000118U /**< Error-free 64 byte Frames
+                                                      Transmitted counter */
+#define XEMACPS_TX65CNT_OFFSET       0x0000011CU /**< Error-free 65-127 byte
+                                                      Frames Transmitted
+                                                      counter */
+#define XEMACPS_TX128CNT_OFFSET      0x00000120U /**< Error-free 128-255 byte
+                                                      Frames Transmitted
+                                                      counter*/
+#define XEMACPS_TX256CNT_OFFSET      0x00000124U /**< Error-free 256-511 byte
+                                                      Frames transmitted
+                                                      counter */
+#define XEMACPS_TX512CNT_OFFSET      0x00000128U /**< Error-free 512-1023 byte
+                                                      Frames transmitted
+                                                      counter */
+#define XEMACPS_TX1024CNT_OFFSET     0x0000012CU /**< Error-free 1024-1518 byte
+                                                      Frames transmitted
+                                                      counter */
+#define XEMACPS_TX1519CNT_OFFSET     0x00000130U /**< Error-free larger than
+                                                      1519 byte Frames
+                                                      transmitted counter */
+#define XEMACPS_TXURUNCNT_OFFSET     0x00000134U /**< TX under run error
+                                                      counter */
+
+#define XEMACPS_SNGLCOLLCNT_OFFSET   0x00000138U /**< Single Collision Frame
+                                                      Counter */
+#define XEMACPS_MULTICOLLCNT_OFFSET  0x0000013CU /**< Multiple Collision Frame
+                                                      Counter */
+#define XEMACPS_EXCESSCOLLCNT_OFFSET 0x00000140U /**< Excessive Collision Frame
+                                                      Counter */
+#define XEMACPS_LATECOLLCNT_OFFSET   0x00000144U /**< Late Collision Frame
+                                                      Counter */
+#define XEMACPS_TXDEFERCNT_OFFSET    0x00000148U /**< Deferred Transmission
+                                                      Frame Counter */
+#define XEMACPS_TXCSENSECNT_OFFSET   0x0000014CU /**< Transmit Carrier Sense
+                                                      Error Counter */
+
+#define XEMACPS_OCTRXL_OFFSET        0x00000150U /**< Octects Received register
+                                                      Low */
+#define XEMACPS_OCTRXH_OFFSET        0x00000154U /**< Octects Received register
+                                                      High */
+
+#define XEMACPS_RXCNT_OFFSET         0x00000158U /**< Error-free Frames
+                                                      Received Counter */
+#define XEMACPS_RXBROADCNT_OFFSET    0x0000015CU /**< Error-free Broadcast
+                                                      Frames Received Counter */
+#define XEMACPS_RXMULTICNT_OFFSET    0x00000160U /**< Error-free Multicast
+                                                      Frames Received Counter */
+#define XEMACPS_RXPAUSECNT_OFFSET    0x00000164U /**< Pause Frames
+                                                      Received Counter */
+#define XEMACPS_RX64CNT_OFFSET       0x00000168U /**< Error-free 64 byte Frames
+                                                      Received Counter */
+#define XEMACPS_RX65CNT_OFFSET       0x0000016CU /**< Error-free 65-127 byte
+                                                      Frames Received Counter */
+#define XEMACPS_RX128CNT_OFFSET      0x00000170U /**< Error-free 128-255 byte
+                                                      Frames Received Counter */
+#define XEMACPS_RX256CNT_OFFSET      0x00000174U /**< Error-free 256-512 byte
+                                                      Frames Received Counter */
+#define XEMACPS_RX512CNT_OFFSET      0x00000178U /**< Error-free 512-1023 byte
+                                                      Frames Received Counter */
+#define XEMACPS_RX1024CNT_OFFSET     0x0000017CU /**< Error-free 1024-1518 byte
+                                                      Frames Received Counter */
+#define XEMACPS_RX1519CNT_OFFSET     0x00000180U /**< Error-free 1519-max byte
+                                                      Frames Received Counter */
+#define XEMACPS_RXUNDRCNT_OFFSET     0x00000184U /**< Undersize Frames Received
+                                                      Counter */
+#define XEMACPS_RXOVRCNT_OFFSET      0x00000188U /**< Oversize Frames Received
+                                                      Counter */
+#define XEMACPS_RXJABCNT_OFFSET      0x0000018CU /**< Jabbers Received
+                                                      Counter */
+#define XEMACPS_RXFCSCNT_OFFSET      0x00000190U /**< Frame Check Sequence
+                                                      Error Counter */
+#define XEMACPS_RXLENGTHCNT_OFFSET   0x00000194U /**< Length Field Error
+                                                      Counter */
+#define XEMACPS_RXSYMBCNT_OFFSET     0x00000198U /**< Symbol Error Counter */
+#define XEMACPS_RXALIGNCNT_OFFSET    0x0000019CU /**< Alignment Error Counter */
+#define XEMACPS_RXRESERRCNT_OFFSET   0x000001A0U /**< Receive Resource Error
+                                                      Counter */
+#define XEMACPS_RXORCNT_OFFSET       0x000001A4U /**< Receive Overrun Counter */
+#define XEMACPS_RXIPCCNT_OFFSET      0x000001A8U /**< IP header Checksum Error
+                                                      Counter */
+#define XEMACPS_RXTCPCCNT_OFFSET     0x000001ACU /**< TCP Checksum Error
+                                                      Counter */
+#define XEMACPS_RXUDPCCNT_OFFSET     0x000001B0U /**< UDP Checksum Error
+                                                      Counter */
+#define XEMACPS_LAST_OFFSET          0x000001B4U /**< Last statistic counter
+                              offset, for clearing */
+
+#define XEMACPS_1588_SEC_OFFSET      0x000001D0U /**< 1588 second counter */
+#define XEMACPS_1588_NANOSEC_OFFSET  0x000001D4U /**< 1588 nanosecond counter */
+#define XEMACPS_1588_ADJ_OFFSET      0x000001D8U /**< 1588 nanosecond
+                              adjustment counter */
+#define XEMACPS_1588_INC_OFFSET      0x000001DCU /**< 1588 nanosecond
+                              increment counter */
+#define XEMACPS_PTP_TXSEC_OFFSET     0x000001E0U /**< 1588 PTP transmit second
+                              counter */
+#define XEMACPS_PTP_TXNANOSEC_OFFSET 0x000001E4U /**< 1588 PTP transmit
+                              nanosecond counter */
+#define XEMACPS_PTP_RXSEC_OFFSET     0x000001E8U /**< 1588 PTP receive second
+                              counter */
+#define XEMACPS_PTP_RXNANOSEC_OFFSET 0x000001ECU /**< 1588 PTP receive
+                              nanosecond counter */
+#define XEMACPS_PTPP_TXSEC_OFFSET    0x000001F0U /**< 1588 PTP peer transmit
+                              second counter */
+#define XEMACPS_PTPP_TXNANOSEC_OFFSET 0x000001F4U /**< 1588 PTP peer transmit
+                              nanosecond counter */
+#define XEMACPS_PTPP_RXSEC_OFFSET    0x000001F8U /**< 1588 PTP peer receive
+                              second counter */
+#define XEMACPS_PTPP_RXNANOSEC_OFFSET 0x000001FCU /**< 1588 PTP peer receive
+                              nanosecond counter */
+
+#define XEMACPS_INTQ1_STS_OFFSET     0x00000400U /**< Interrupt Q1 Status
+                            reg */
+#define XEMACPS_TXQ1BASE_OFFSET         0x00000440U /**< TX Q1 Base address
+                            reg */
+#define XEMACPS_RXQ1BASE_OFFSET         0x00000480U /**< RX Q1 Base address
+                            reg */
+#define XEMACPS_MSBBUF_TXQBASE_OFFSET  0x000004C8U /**< MSB Buffer TX Q Base
+                            reg */
+#define XEMACPS_MSBBUF_RXQBASE_OFFSET  0x000004D4U /**< MSB Buffer RX Q Base
+                            reg */
+#define XEMACPS_INTQ1_IER_OFFSET     0x00000600U /**< Interrupt Q1 Enable
+                            reg */
+#define XEMACPS_INTQ1_IDR_OFFSET     0x00000620U /**< Interrupt Q1 Disable
+                            reg */
+#define XEMACPS_INTQ1_IMR_OFFSET     0x00000640U /**< Interrupt Q1 Mask
+                            reg */
+
+/* Define some bit positions for registers. */
+
+/** @name network control register bit definitions
+ * @{
+ */
+#define XEMACPS_NWCTRL_FLUSH_DPRAM_MASK    0x00040000U /**< Flush a packet from
+                            Rx SRAM */
+#define XEMACPS_NWCTRL_ZEROPAUSETX_MASK 0x00000800U /**< Transmit zero quantum
+                                                         pause frame */
+#define XEMACPS_NWCTRL_PAUSETX_MASK     0x00000800U /**< Transmit pause frame */
+#define XEMACPS_NWCTRL_HALTTX_MASK      0x00000400U /**< Halt transmission
+                                                         after current frame */
+#define XEMACPS_NWCTRL_STARTTX_MASK     0x00000200U /**< Start tx (tx_go) */
+
+#define XEMACPS_NWCTRL_STATWEN_MASK     0x00000080U /**< Enable writing to
+                                                         stat counters */
+#define XEMACPS_NWCTRL_STATINC_MASK     0x00000040U /**< Increment statistic
+                                                         registers */
+#define XEMACPS_NWCTRL_STATCLR_MASK     0x00000020U /**< Clear statistic
+                                                         registers */
+#define XEMACPS_NWCTRL_MDEN_MASK        0x00000010U /**< Enable MDIO port */
+#define XEMACPS_NWCTRL_TXEN_MASK        0x00000008U /**< Enable transmit */
+#define XEMACPS_NWCTRL_RXEN_MASK        0x00000004U /**< Enable receive */
+#define XEMACPS_NWCTRL_LOOPEN_MASK      0x00000002U /**< local loopback */
+/*@}*/
+
+/** @name network configuration register bit definitions
+ * @{
+ */
+#define XEMACPS_NWCFG_BADPREAMBEN_MASK 0x20000000U /**< disable rejection of
+                                                        non-standard preamble */
+#define XEMACPS_NWCFG_IPDSTRETCH_MASK  0x10000000U /**< enable transmit IPG */
+#define XEMACPS_NWCFG_SGMIIEN_MASK     0x08000000U /**< SGMII Enable */
+#define XEMACPS_NWCFG_FCSIGNORE_MASK   0x04000000U /**< disable rejection of
+                                                        FCS error */
+#define XEMACPS_NWCFG_HDRXEN_MASK      0x02000000U /**< RX half duplex */
+#define XEMACPS_NWCFG_RXCHKSUMEN_MASK  0x01000000U /**< enable RX checksum
+                                                        offload */
+#define XEMACPS_NWCFG_PAUSECOPYDI_MASK 0x00800000U /**< Do not copy pause
+                                                        Frames to memory */
+#define XEMACPS_NWCFG_DWIDTH_64_MASK   0x00200000U /**< 64 bit Data bus width */
+#define XEMACPS_NWCFG_MDC_SHIFT_MASK   18U       /**< shift bits for MDC */
+#define XEMACPS_NWCFG_MDCCLKDIV_MASK   0x001C0000U /**< MDC Mask PCLK divisor */
+#define XEMACPS_NWCFG_FCSREM_MASK      0x00020000U /**< Discard FCS from
+                                                        received frames */
+#define XEMACPS_NWCFG_LENERRDSCRD_MASK 0x00010000U
+/**< RX length error discard */
+#define XEMACPS_NWCFG_RXOFFS_MASK      0x0000C000U /**< RX buffer offset */
+#define XEMACPS_NWCFG_PAUSEEN_MASK     0x00002000U /**< Enable pause RX */
+#define XEMACPS_NWCFG_RETRYTESTEN_MASK 0x00001000U /**< Retry test */
+#define XEMACPS_NWCFG_XTADDMACHEN_MASK 0x00000200U
+/**< External address match enable */
+#define XEMACPS_NWCFG_PCSSEL_MASK      0x00000800U /**< PCS Select */
+#define XEMACPS_NWCFG_1000_MASK        0x00000400U /**< 1000 Mbps */
+#define XEMACPS_NWCFG_1536RXEN_MASK    0x00000100U /**< Enable 1536 byte
+                                                        frames reception */
+#define XEMACPS_NWCFG_UCASTHASHEN_MASK 0x00000080U /**< Receive unicast hash
+                                                        frames */
+#define XEMACPS_NWCFG_MCASTHASHEN_MASK 0x00000040U /**< Receive multicast hash
+                                                        frames */
+#define XEMACPS_NWCFG_BCASTDI_MASK     0x00000020U /**< Do not receive
+                                                        broadcast frames */
+#define XEMACPS_NWCFG_COPYALLEN_MASK   0x00000010U /**< Copy all frames */
+#define XEMACPS_NWCFG_JUMBO_MASK       0x00000008U /**< Jumbo frames */
+#define XEMACPS_NWCFG_NVLANDISC_MASK   0x00000004U /**< Receive only VLAN
+                                                        frames */
+#define XEMACPS_NWCFG_FDEN_MASK        0x00000002U/**< full duplex */
+#define XEMACPS_NWCFG_100_MASK         0x00000001U /**< 100 Mbps */
+#define XEMACPS_NWCFG_RESET_MASK       0x00080000U/**< reset value */
+/*@}*/
+
+/** @name network status register bit definitaions
+ * @{
+ */
+#define XEMACPS_NWSR_MDIOIDLE_MASK     0x00000004U /**< PHY management idle */
+#define XEMACPS_NWSR_MDIO_MASK         0x00000002U /**< Status of mdio_in */
+/*@}*/
+
+
+/** @name MAC address register word 1 mask
+ * @{
+ */
+#define XEMACPS_LADDR_MACH_MASK        0x0000FFFFU /**< Address bits[47:32]
+                                                      bit[31:0] are in BOTTOM */
+/*@}*/
+
+
+/** @name DMA control register bit definitions
+ * @{
+ */
+#define XEMACPS_DMACR_ADDR_WIDTH_64        0x40000000U /**< 64 bit address bus */
+#define XEMACPS_DMACR_TXEXTEND_MASK        0x20000000U /**< Tx Extended desc mode */
+#define XEMACPS_DMACR_RXEXTEND_MASK        0x10000000U /**< Rx Extended desc mode */
+#define XEMACPS_DMACR_RXBUF_MASK        0x00FF0000U /**< Mask bit for RX buffer
+                                                    size */
+#define XEMACPS_DMACR_RXBUF_SHIFT         16U    /**< Shift bit for RX buffer
+                                                size */
+#define XEMACPS_DMACR_TCPCKSUM_MASK        0x00000800U /**< enable/disable TX
+                                                        checksum offload */
+#define XEMACPS_DMACR_TXSIZE_MASK        0x00000400U /**< TX buffer memory size */
+#define XEMACPS_DMACR_RXSIZE_MASK        0x00000300U /**< RX buffer memory size */
+#define XEMACPS_DMACR_ENDIAN_MASK        0x00000080U /**< endian configuration */
+#define XEMACPS_DMACR_BLENGTH_MASK        0x0000001FU /**< buffer burst length */
+#define XEMACPS_DMACR_SINGLE_AHB_BURST    0x00000001U /**< single AHB bursts */
+#define XEMACPS_DMACR_INCR4_AHB_BURST    0x00000004U /**< 4 bytes AHB bursts */
+#define XEMACPS_DMACR_INCR8_AHB_BURST    0x00000008U /**< 8 bytes AHB bursts */
+#define XEMACPS_DMACR_INCR16_AHB_BURST    0x00000010U /**< 16 bytes AHB bursts */
+/*@}*/
+
+/** @name transmit status register bit definitions
+ * @{
+ */
+#define XEMACPS_TXSR_HRESPNOK_MASK    0x00000100U /**< Transmit hresp not OK */
+#define XEMACPS_TXSR_URUN_MASK        0x00000040U /**< Transmit underrun */
+#define XEMACPS_TXSR_TXCOMPL_MASK     0x00000020U /**< Transmit completed OK */
+#define XEMACPS_TXSR_BUFEXH_MASK      0x00000010U /**< Transmit buffs exhausted
+                                                       mid frame */
+#define XEMACPS_TXSR_TXGO_MASK        0x00000008U /**< Status of go flag */
+#define XEMACPS_TXSR_RXOVR_MASK       0x00000004U /**< Retry limit exceeded */
+#define XEMACPS_TXSR_FRAMERX_MASK     0x00000002U /**< Collision tx frame */
+#define XEMACPS_TXSR_USEDREAD_MASK    0x00000001U /**< TX buffer used bit set */
+
+#define XEMACPS_TXSR_ERROR_MASK      ((u32)XEMACPS_TXSR_HRESPNOK_MASK | \
+                                       (u32)XEMACPS_TXSR_URUN_MASK | \
+                                       (u32)XEMACPS_TXSR_BUFEXH_MASK | \
+                                       (u32)XEMACPS_TXSR_RXOVR_MASK | \
+                                       (u32)XEMACPS_TXSR_FRAMERX_MASK | \
+                                       (u32)XEMACPS_TXSR_USEDREAD_MASK)
+/*@}*/
+
+/**
+ * @name receive status register bit definitions
+ * @{
+ */
+#define XEMACPS_RXSR_HRESPNOK_MASK    0x00000008U /**< Receive hresp not OK */
+#define XEMACPS_RXSR_RXOVR_MASK       0x00000004U /**< Receive overrun */
+#define XEMACPS_RXSR_FRAMERX_MASK     0x00000002U /**< Frame received OK */
+#define XEMACPS_RXSR_BUFFNA_MASK      0x00000001U /**< RX buffer used bit set */
+
+#define XEMACPS_RXSR_ERROR_MASK      ((u32)XEMACPS_RXSR_HRESPNOK_MASK | \
+                                       (u32)XEMACPS_RXSR_RXOVR_MASK | \
+                                       (u32)XEMACPS_RXSR_BUFFNA_MASK)
+
+#define XEMACPS_SR_ALL_MASK    0xFFFFFFFFU /**< Mask for full register */
+
+/*@}*/
+
+/**
+ * @name Interrupt Q1 status register bit definitions
+ * @{
+ */
+#define XEMACPS_INTQ1SR_TXCOMPL_MASK    0x00000080U /**< Transmit completed OK */
+#define XEMACPS_INTQ1SR_TXERR_MASK    0x00000040U /**< Transmit AMBA Error */
+
+#define XEMACPS_INTQ1_IXR_ALL_MASK    ((u32)XEMACPS_INTQ1SR_TXCOMPL_MASK | \
+                     (u32)XEMACPS_INTQ1SR_TXERR_MASK)
+
+/*@}*/
+
+/**
+ * @name interrupts bit definitions
+ * Bits definitions are same in XEMACPS_ISR_OFFSET,
+ * XEMACPS_IER_OFFSET, XEMACPS_IDR_OFFSET, and XEMACPS_IMR_OFFSET
+ * @{
+ */
+#define XEMACPS_IXR_PTPPSTX_MASK    0x02000000U /**< PTP Pdelay_resp TXed */
+#define XEMACPS_IXR_PTPPDRTX_MASK    0x01000000U /**< PTP Pdelay_req TXed */
+#define XEMACPS_IXR_PTPPSRX_MASK    0x00800000U /**< PTP Pdelay_resp RXed */
+#define XEMACPS_IXR_PTPPDRRX_MASK    0x00400000U /**< PTP Pdelay_req RXed */
+
+#define XEMACPS_IXR_PTPSTX_MASK        0x00200000U /**< PTP Sync TXed */
+#define XEMACPS_IXR_PTPDRTX_MASK    0x00100000U /**< PTP Delay_req TXed */
+#define XEMACPS_IXR_PTPSRX_MASK        0x00080000U /**< PTP Sync RXed */
+#define XEMACPS_IXR_PTPDRRX_MASK    0x00040000U /**< PTP Delay_req RXed */
+
+#define XEMACPS_IXR_PAUSETX_MASK    0x00004000U    /**< Pause frame transmitted */
+#define XEMACPS_IXR_PAUSEZERO_MASK  0x00002000U    /**< Pause time has reached
+                                                     zero */
+#define XEMACPS_IXR_PAUSENZERO_MASK 0x00001000U    /**< Pause frame received */
+#define XEMACPS_IXR_HRESPNOK_MASK   0x00000800U    /**< hresp not ok */
+#define XEMACPS_IXR_RXOVR_MASK      0x00000400U    /**< Receive overrun occurred */
+#define XEMACPS_IXR_TXCOMPL_MASK    0x00000080U    /**< Frame transmitted ok */
+#define XEMACPS_IXR_TXEXH_MASK      0x00000040U    /**< Transmit err occurred or
+                                                     no buffers*/
+#define XEMACPS_IXR_RETRY_MASK      0x00000020U    /**< Retry limit exceeded */
+#define XEMACPS_IXR_URUN_MASK       0x00000010U    /**< Transmit underrun */
+#define XEMACPS_IXR_TXUSED_MASK     0x00000008U    /**< Tx buffer used bit read */
+#define XEMACPS_IXR_RXUSED_MASK     0x00000004U    /**< Rx buffer used bit read */
+#define XEMACPS_IXR_FRAMERX_MASK    0x00000002U    /**< Frame received ok */
+#define XEMACPS_IXR_MGMNT_MASK      0x00000001U    /**< PHY management complete */
+#define XEMACPS_IXR_ALL_MASK        0x00007FFFU    /**< Everything! */
+
+#define XEMACPS_IXR_TX_ERR_MASK    ((u32)XEMACPS_IXR_TXEXH_MASK |         \
+                                     (u32)XEMACPS_IXR_RETRY_MASK |         \
+                                     (u32)XEMACPS_IXR_URUN_MASK)
+
+
+#define XEMACPS_IXR_RX_ERR_MASK    ((u32)XEMACPS_IXR_HRESPNOK_MASK |      \
+                                     (u32)XEMACPS_IXR_RXUSED_MASK |        \
+                                     (u32)XEMACPS_IXR_RXOVR_MASK)
+
+/*@}*/
+
+/** @name PHY Maintenance bit definitions
+ * @{
+ */
+#define XEMACPS_PHYMNTNC_OP_MASK    0x40020000U    /**< operation mask bits */
+#define XEMACPS_PHYMNTNC_OP_R_MASK  0x20000000U    /**< read operation */
+#define XEMACPS_PHYMNTNC_OP_W_MASK  0x10000000U    /**< write operation */
+#define XEMACPS_PHYMNTNC_ADDR_MASK  0x0F800000U    /**< Address bits */
+#define XEMACPS_PHYMNTNC_REG_MASK   0x007C0000U    /**< register bits */
+#define XEMACPS_PHYMNTNC_DATA_MASK  0x00000FFFU    /**< data bits */
+#define XEMACPS_PHYMNTNC_PHAD_SHFT_MSK   23U    /**< Shift bits for PHYAD */
+#define XEMACPS_PHYMNTNC_PREG_SHFT_MSK   18U    /**< Shift bits for PHREG */
+/*@}*/
+
+/** @name RX watermark bit definitions
+ * @{
+ */
+#define XEMACPS_RXWM_HIGH_MASK        0x0000FFFFU    /**< RXWM high mask */
+#define XEMACPS_RXWM_LOW_MASK        0xFFFF0000U    /**< RXWM low mask */
+#define XEMACPS_RXWM_LOW_SHFT_MSK    16U    /**< Shift for RXWM low */
+/*@}*/
+
+/* Transmit buffer descriptor status words offset
+ * @{
+ */
+#define XEMACPS_BD_ADDR_OFFSET  0x00000000U /**< word 0/addr of BDs */
+#define XEMACPS_BD_STAT_OFFSET  0x00000004U /**< word 1/status of BDs */
+#define XEMACPS_BD_ADDR_HI_OFFSET  0x00000008U /**< word 2/addr of BDs */
+
+/*
+ * @}
+ */
+
+/* Transmit buffer descriptor status words bit positions.
+ * Transmit buffer descriptor consists of two 32-bit registers,
+ * the first - word0 contains a 32-bit address pointing to the location of
+ * the transmit data.
+ * The following register - word1, consists of various information to control
+ * the XEmacPs transmit process.  After transmit, this is updated with status
+ * information, whether the frame was transmitted OK or why it had failed.
+ * @{
+ */
+#define XEMACPS_TXBUF_USED_MASK  0x80000000U /**< Used bit. */
+#define XEMACPS_TXBUF_WRAP_MASK  0x40000000U /**< Wrap bit, last descriptor */
+#define XEMACPS_TXBUF_RETRY_MASK 0x20000000U /**< Retry limit exceeded */
+#define XEMACPS_TXBUF_URUN_MASK  0x10000000U /**< Transmit underrun occurred */
+#define XEMACPS_TXBUF_EXH_MASK   0x08000000U /**< Buffers exhausted */
+#define XEMACPS_TXBUF_TCP_MASK   0x04000000U /**< Late collision. */
+#define XEMACPS_TXBUF_NOCRC_MASK 0x00010000U /**< No CRC */
+#define XEMACPS_TXBUF_LAST_MASK  0x00008000U /**< Last buffer */
+#define XEMACPS_TXBUF_LEN_MASK   0x00003FFFU /**< Mask for length field */
+/*
+ * @}
+ */
+
+/* Receive buffer descriptor status words bit positions.
+ * Receive buffer descriptor consists of two 32-bit registers,
+ * the first - word0 contains a 32-bit word aligned address pointing to the
+ * address of the buffer. The lower two bits make up the wrap bit indicating
+ * the last descriptor and the ownership bit to indicate it has been used by
+ * the XEmacPs.
+ * The following register - word1, contains status information regarding why
+ * the frame was received (the filter match condition) as well as other
+ * useful info.
+ * @{
+ */
+#define XEMACPS_RXBUF_BCAST_MASK     0x80000000U /**< Broadcast frame */
+#define XEMACPS_RXBUF_MULTIHASH_MASK 0x40000000U /**< Multicast hashed frame */
+#define XEMACPS_RXBUF_UNIHASH_MASK   0x20000000U /**< Unicast hashed frame */
+#define XEMACPS_RXBUF_EXH_MASK       0x08000000U /**< buffer exhausted */
+#define XEMACPS_RXBUF_AMATCH_MASK    0x06000000U /**< Specific address
+                                                      matched */
+#define XEMACPS_RXBUF_IDFOUND_MASK   0x01000000U /**< Type ID matched */
+#define XEMACPS_RXBUF_IDMATCH_MASK   0x00C00000U /**< ID matched mask */
+#define XEMACPS_RXBUF_VLAN_MASK      0x00200000U /**< VLAN tagged */
+#define XEMACPS_RXBUF_PRI_MASK       0x00100000U /**< Priority tagged */
+#define XEMACPS_RXBUF_VPRI_MASK      0x000E0000U /**< Vlan priority */
+#define XEMACPS_RXBUF_CFI_MASK       0x00010000U /**< CFI frame */
+#define XEMACPS_RXBUF_EOF_MASK       0x00008000U /**< End of frame. */
+#define XEMACPS_RXBUF_SOF_MASK       0x00004000U /**< Start of frame. */
+#define XEMACPS_RXBUF_LEN_MASK       0x00001FFFU /**< Mask for length field */
+#define XEMACPS_RXBUF_LEN_JUMBO_MASK 0x00003FFFU /**< Mask for jumbo length */
+
+#define XEMACPS_RXBUF_WRAP_MASK      0x00000002U /**< Wrap bit, last BD */
+#define XEMACPS_RXBUF_NEW_MASK       0x00000001U /**< Used bit.. */
+#define XEMACPS_RXBUF_ADD_MASK       0xFFFFFFFCU /**< Mask for address */
+/*
+ * @}
+ */
+
+/*
+ * Define appropriate I/O access method to memory mapped I/O or other
+ * interface if necessary.
+ */
+
+#define XEmacPs_In32  Xil_In32
+#define XEmacPs_Out32 Xil_Out32
+
+
+/****************************************************************************/
+/**
+*
+* Read the given register.
+*
+* @param    BaseAddress is the base address of the device
+* @param    RegOffset is the register offset to be read
+*
+* @return   The 32-bit value of the register
+*
+* @note
+* C-style signature:
+*    u32 XEmacPs_ReadReg(u32 BaseAddress, u32 RegOffset)
+*
+*****************************************************************************/
+#define XEmacPs_ReadReg(BaseAddress, RegOffset) \
+    XEmacPs_In32((BaseAddress) + (u32)(RegOffset))
+
+
+/****************************************************************************/
+/**
+*
+* Write the given register.
+*
+* @param    BaseAddress is the base address of the device
+* @param    RegOffset is the register offset to be written
+* @param    Data is the 32-bit value to write to the register
+*
+* @return   None.
+*
+* @note
+* C-style signature:
+*    void XEmacPs_WriteReg(u32 BaseAddress, u32 RegOffset,
+*         u32 Data)
+*
+*****************************************************************************/
+#define XEmacPs_WriteReg(BaseAddress, RegOffset, Data) \
+    XEmacPs_Out32((BaseAddress) + (u32)(RegOffset), (u32)(Data))
+
+/************************** Function Prototypes *****************************/
+/*
+ * Perform reset operation to the emacps interface
+ */
+void XEmacPs_ResetHw(u32 BaseAddr);
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* end of protection macro */
+/** @} */

+ 242 - 0
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_intr.c

@@ -0,0 +1,242 @@
+/******************************************************************************
+* Copyright (C) 2010 - 2020 Xilinx, Inc.  All rights reserved.
+* SPDX-License-Identifier: MIT
+******************************************************************************/
+
+/*****************************************************************************/
+/**
+*
+* @file xemacps_intr.c
+* @addtogroup emacps_v3_11
+* @{
+*
+* Functions in this file implement general purpose interrupt processing related
+* functionality. See xemacps.h for a detailed description of the driver.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a wsy  01/10/10 First release
+* 1.03a asa  01/24/13 Fix for CR #692702 which updates error handling for
+*              Rx errors. Under heavy Rx traffic, there will be a large
+*              number of errors related to receive buffer not available.
+*              Because of a HW bug (SI #692601), under such heavy errors,
+*              the Rx data path can become unresponsive. To reduce the
+*              probabilities for hitting this HW bug, the SW writes to
+*              bit 18 to flush a packet from Rx DPRAM immediately. The
+*              changes for it are done in the function
+*              XEmacPs_IntrHandler.
+* 2.1   srt  07/15/14 Add support for Zynq Ultrascale Mp GEM specification
+*               and 64-bit changes.
+* 3.0   kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.1   hk   07/27/15 Do not call error handler with '0' error code when
+*                     there is no error. CR# 869403
+* </pre>
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xemacps.h"
+
+/************************** Constant Definitions *****************************/
+
+
+/**************************** Type Definitions *******************************/
+
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+
+/************************** Function Prototypes ******************************/
+
+
+/************************** Variable Definitions *****************************/
+
+
+/*****************************************************************************/
+/**
+ * Install an asynchronous handler function for the given HandlerType:
+ *
+ * @param InstancePtr is a pointer to the instance to be worked on.
+ * @param HandlerType indicates what interrupt handler type is.
+ *        XEMACPS_HANDLER_DMASEND, XEMACPS_HANDLER_DMARECV and
+ *        XEMACPS_HANDLER_ERROR.
+ * @param FuncPointer is the pointer to the callback function
+ * @param CallBackRef is the upper layer callback reference passed back when
+ *        when the callback function is invoked.
+ *
+ * @return
+ *
+ * None.
+ *
+ * @note
+ * There is no assert on the CallBackRef since the driver doesn't know what
+ * it is.
+ *
+ *****************************************************************************/
+LONG XEmacPs_SetHandler(XEmacPs *InstancePtr, u32 HandlerType,
+            void *FuncPointer, void *CallBackRef)
+{
+    LONG Status;
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(FuncPointer != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
+
+    switch (HandlerType) {
+    case XEMACPS_HANDLER_DMASEND:
+        Status = (LONG)(XST_SUCCESS);
+        InstancePtr->SendHandler = ((XEmacPs_Handler)(void *)FuncPointer);
+        InstancePtr->SendRef = CallBackRef;
+        break;
+    case XEMACPS_HANDLER_DMARECV:
+        Status = (LONG)(XST_SUCCESS);
+        InstancePtr->RecvHandler = ((XEmacPs_Handler)(void *)FuncPointer);
+        InstancePtr->RecvRef = CallBackRef;
+        break;
+    case XEMACPS_HANDLER_ERROR:
+        Status = (LONG)(XST_SUCCESS);
+        InstancePtr->ErrorHandler = ((XEmacPs_ErrHandler)(void *)FuncPointer);
+        InstancePtr->ErrorRef = CallBackRef;
+        break;
+    default:
+        Status = (LONG)(XST_INVALID_PARAM);
+        break;
+    }
+    return Status;
+}
+
+/*****************************************************************************/
+/**
+* Master interrupt handler for EMAC driver. This routine will query the
+* status of the device, bump statistics, and invoke user callbacks.
+*
+* This routine must be connected to an interrupt controller using OS/BSP
+* specific methods.
+*
+* @param XEmacPsPtr is a pointer to the XEMACPS instance that has caused the
+*        interrupt.
+*
+******************************************************************************/
+void XEmacPs_IntrHandler(void *XEmacPsPtr)
+{
+    u32 RegISR;
+    u32 RegSR;
+    u32 RegCtrl;
+    u32 RegQ1ISR = 0U;
+    XEmacPs *InstancePtr = (XEmacPs *) XEmacPsPtr;
+
+    Xil_AssertVoid(InstancePtr != NULL);
+    Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
+
+    /* This ISR will try to handle as many interrupts as it can in a single
+     * call. However, in most of the places where the user's error handler
+         * is called, this ISR exits because it is expected that the user will
+         * reset the device in nearly all instances.
+     */
+    RegISR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                   XEMACPS_ISR_OFFSET);
+
+    /* Read Transmit Q1 ISR */
+
+    if (InstancePtr->Version > 2)
+        RegQ1ISR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                   XEMACPS_INTQ1_STS_OFFSET);
+
+    /* Clear the interrupt status register */
+    XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET,
+               RegISR);
+
+    /* Receive complete interrupt */
+    if ((RegISR & XEMACPS_IXR_FRAMERX_MASK) != 0x00000000U) {
+        /* Clear RX status register RX complete indication but preserve
+         * error bits if there is any */
+        XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                   XEMACPS_RXSR_OFFSET,
+                   ((u32)XEMACPS_RXSR_FRAMERX_MASK |
+                   (u32)XEMACPS_RXSR_BUFFNA_MASK));
+        InstancePtr->RecvHandler(InstancePtr->RecvRef);
+    }
+
+    /* Transmit Q1 complete interrupt */
+    if ((InstancePtr->Version > 2) &&
+            ((RegQ1ISR & XEMACPS_INTQ1SR_TXCOMPL_MASK) != 0x00000000U)) {
+        /* Clear TX status register TX complete indication but preserve
+         * error bits if there is any */
+        XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                   XEMACPS_INTQ1_STS_OFFSET,
+                   XEMACPS_INTQ1SR_TXCOMPL_MASK);
+        XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                   XEMACPS_TXSR_OFFSET,
+                   ((u32)XEMACPS_TXSR_TXCOMPL_MASK |
+                   (u32)XEMACPS_TXSR_USEDREAD_MASK));
+        InstancePtr->SendHandler(InstancePtr->SendRef);
+    }
+
+    /* Transmit complete interrupt */
+    if ((RegISR & XEMACPS_IXR_TXCOMPL_MASK) != 0x00000000U) {
+        /* Clear TX status register TX complete indication but preserve
+         * error bits if there is any */
+        XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                   XEMACPS_TXSR_OFFSET,
+                   ((u32)XEMACPS_TXSR_TXCOMPL_MASK |
+                   (u32)XEMACPS_TXSR_USEDREAD_MASK));
+        InstancePtr->SendHandler(InstancePtr->SendRef);
+    }
+
+    /* Receive error conditions interrupt */
+    if ((RegISR & XEMACPS_IXR_RX_ERR_MASK) != 0x00000000U) {
+        /* Clear RX status register */
+        RegSR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                      XEMACPS_RXSR_OFFSET);
+        XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                   XEMACPS_RXSR_OFFSET, RegSR);
+
+        /* Fix for CR # 692702. Write to bit 18 of net_ctrl
+         * register to flush a packet out of Rx SRAM upon
+         * an error for receive buffer not available. */
+        if ((RegISR & XEMACPS_IXR_RXUSED_MASK) != 0x00000000U) {
+            RegCtrl =
+            XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                        XEMACPS_NWCTRL_OFFSET);
+            RegCtrl |= (u32)XEMACPS_NWCTRL_FLUSH_DPRAM_MASK;
+            XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                    XEMACPS_NWCTRL_OFFSET, RegCtrl);
+        }
+
+        if(RegSR != 0) {
+            InstancePtr->ErrorHandler(InstancePtr->ErrorRef,
+                        XEMACPS_RECV, RegSR);
+        }
+    }
+
+        /* When XEMACPS_IXR_TXCOMPL_MASK is flagged, XEMACPS_IXR_TXUSED_MASK
+         * will be asserted the same time.
+         * Have to distinguish this bit to handle the real error condition.
+         */
+    /* Transmit Q1 error conditions interrupt */
+        if ((InstancePtr->Version > 2) &&
+            ((RegQ1ISR & XEMACPS_INTQ1SR_TXERR_MASK) != 0x00000000U) &&
+            ((RegQ1ISR & XEMACPS_INTQ1SR_TXCOMPL_MASK) != 0x00000000U)) {
+            /* Clear Interrupt Q1 status register */
+            XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                   XEMACPS_INTQ1_STS_OFFSET, RegQ1ISR);
+            InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XEMACPS_SEND,
+                      RegQ1ISR);
+       }
+
+    /* Transmit error conditions interrupt */
+        if (((RegISR & XEMACPS_IXR_TX_ERR_MASK) != 0x00000000U) &&
+            (!(RegISR & XEMACPS_IXR_TXCOMPL_MASK) != 0x00000000U)) {
+        /* Clear TX status register */
+        RegSR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                      XEMACPS_TXSR_OFFSET);
+        XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                   XEMACPS_TXSR_OFFSET, RegSR);
+        InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XEMACPS_SEND,
+                      RegSR);
+    }
+
+}
+/** @} */

+ 71 - 0
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/emacps_v3_11/xemacps_sinit.c

@@ -0,0 +1,71 @@
+/******************************************************************************
+* Copyright (C) 2010 - 2020 Xilinx, Inc.  All rights reserved.
+* SPDX-License-Identifier: MIT
+******************************************************************************/
+
+/*****************************************************************************/
+/**
+*
+* @file xemacps_sinit.c
+* @addtogroup emacps_v3_11
+* @{
+*
+* This file contains lookup method by device ID when success, it returns
+* pointer to config table to be used to initialize the device.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a wsy  01/10/10 New
+* 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* </pre>
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xemacps.h"
+#include "xparameters.h"
+
+/************************** Constant Definitions *****************************/
+
+
+/**************************** Type Definitions *******************************/
+
+/*************************** Variable Definitions *****************************/
+extern XEmacPs_Config XEmacPs_ConfigTable[XPAR_XEMACPS_NUM_INSTANCES];
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+
+/************************** Function Prototypes ******************************/
+
+/*****************************************************************************/
+/**
+* Lookup the device configuration based on the unique device ID.  The table
+* contains the configuration info for each device in the system.
+*
+* @param DeviceId is the unique device ID of the device being looked up.
+*
+* @return
+* A pointer to the configuration table entry corresponding to the given
+* device ID, or NULL if no match is found.
+*
+******************************************************************************/
+XEmacPs_Config *XEmacPs_LookupConfig(u16 DeviceId)
+{
+    XEmacPs_Config *CfgPtr = NULL;
+    u32 i;
+
+    for (i = 0U; i < (u32)XPAR_XEMACPS_NUM_INSTANCES; i++) {
+        if (XEmacPs_ConfigTable[i].DeviceId == DeviceId) {
+            CfgPtr = &XEmacPs_ConfigTable[i];
+            break;
+        }
+    }
+
+    return (XEmacPs_Config *)(CfgPtr);
+}
+/** @} */

+ 340 - 340
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops.c

@@ -21,11 +21,11 @@
 * 1.00a sv   01/15/10 First Release
 * 1.01a sv   04/15/12 Removed the APIs XGpioPs_SetMode, XGpioPs_SetModePin
 *                     XGpioPs_GetMode, XGpioPs_GetModePin as they are not
-*		      relevant to Zynq device. The interrupts are disabled
-*		      for output pins on all banks during initialization.
+*              relevant to Zynq device. The interrupts are disabled
+*              for output pins on all banks during initialization.
 * 2.1   hk   04/29/14 Use Input data register DATA_RO for read. CR# 771667.
 * 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
-* 3.1	kvn  04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980.
+* 3.1    kvn  04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980.
 * 3.1   aru  07/13/18 Resolved doxygen reported warnings. CR# 1006331.
 * 3.4   aru  08/17/18 Resolved MISRA-C mandatory violations. CR# 1007751
 * 3.5   sne  03/01/19 Fixes violations according to MISRAC-2012
@@ -61,51 +61,51 @@ extern void StubHandler(void *CallBackRef, u32 Bank, u32 Status);
 * All members of the XGpioPs instance structure are initialized and
 * StubHandlers are assigned to the Bank Status Handlers.
 *
-* @param	InstancePtr is a pointer to the XGpioPs instance.
-* @param	ConfigPtr points to the XGpioPs device configuration structure.
-* @param	EffectiveAddr is the device base address in the virtual memory
-*		address space. If the address translation is not used then the
-*		physical address should be passed.
-*		Unexpected errors may occur if the address mapping is changed
-*		after this function is invoked.
+* @param    InstancePtr is a pointer to the XGpioPs instance.
+* @param    ConfigPtr points to the XGpioPs device configuration structure.
+* @param    EffectiveAddr is the device base address in the virtual memory
+*        address space. If the address translation is not used then the
+*        physical address should be passed.
+*        Unexpected errors may occur if the address mapping is changed
+*        after this function is invoked.
 *
-* @return	XST_SUCCESS always.
+* @return    XST_SUCCESS always.
 *
-* @note		None.
+* @note        None.
 *
 ******************************************************************************/
 s32 XGpioPs_CfgInitialize(XGpioPs *InstancePtr, const XGpioPs_Config *ConfigPtr,
-				u32 EffectiveAddr)
+                u32 EffectiveAddr)
 {
-	s32 Status = XST_SUCCESS;
-	u8 i;
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(ConfigPtr != NULL);
-	Xil_AssertNonvoid(EffectiveAddr != (u32)0);
-	/*
-	 * Set some default values for instance data, don't indicate the device
-	 * is ready to use until everything has been initialized successfully.
-	 */
-	InstancePtr->IsReady = 0U;
-	InstancePtr->GpioConfig.BaseAddr = EffectiveAddr;
-	InstancePtr->GpioConfig.DeviceId = ConfigPtr->DeviceId;
-	InstancePtr->Handler = (XGpioPs_Handler)StubHandler;
-	InstancePtr->Platform = XGetPlatform_Info();
-
-	/* Initialize the Bank data based on platform */
-	if (InstancePtr->Platform == (u32)XPLAT_ZYNQ_ULTRA_MP) {
-		/*
-		 *	Max pins in the ZynqMP GPIO device
-		 *	0 - 25,  Bank 0
-		 *	26 - 51, Bank 1
-		 *	52 - 77, Bank 2
-		 *	78 - 109, Bank 3
-		 *	110 - 141, Bank 4
-		 *	142 - 173, Bank 5
-		 */
-		InstancePtr->MaxPinNum = (u32)174;
-		InstancePtr->MaxBanks = (u8)6;
-	}
+    s32 Status = XST_SUCCESS;
+    u8 i;
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(ConfigPtr != NULL);
+    Xil_AssertNonvoid(EffectiveAddr != (u32)0);
+    /*
+     * Set some default values for instance data, don't indicate the device
+     * is ready to use until everything has been initialized successfully.
+     */
+    InstancePtr->IsReady = 0U;
+    InstancePtr->GpioConfig.BaseAddr = EffectiveAddr;
+    InstancePtr->GpioConfig.DeviceId = ConfigPtr->DeviceId;
+    InstancePtr->Handler = (XGpioPs_Handler)StubHandler;
+    InstancePtr->Platform = XGetPlatform_Info();
+
+    /* Initialize the Bank data based on platform */
+    if (InstancePtr->Platform == (u32)XPLAT_ZYNQ_ULTRA_MP) {
+        /*
+         *    Max pins in the ZynqMP GPIO device
+         *    0 - 25,  Bank 0
+         *    26 - 51, Bank 1
+         *    52 - 77, Bank 2
+         *    78 - 109, Bank 3
+         *    110 - 141, Bank 4
+         *    142 - 173, Bank 5
+         */
+        InstancePtr->MaxPinNum = (u32)174;
+        InstancePtr->MaxBanks = (u8)6;
+    }
         else if (InstancePtr->Platform == (u32)XPLAT_VERSAL)
         {
                 if(InstancePtr->PmcGpio == (u32)FALSE)
@@ -130,22 +130,22 @@ s32 XGpioPs_CfgInitialize(XGpioPs *InstancePtr, const XGpioPs_Config *ConfigPtr,
                 }
         }
         else {
-		/*
-		 *	Max pins in the GPIO device
-		 *	0 - 31,  Bank 0
-		 *	32 - 53, Bank 1
-		 *	54 - 85, Bank 2
-		 *	86 - 117, Bank 3
-		 */
-		InstancePtr->MaxPinNum = (u32)118;
-		InstancePtr->MaxBanks = (u8)4;
-	}
-
-	/*
-	 * By default, interrupts are not masked in GPIO. Disable
-	 * interrupts for all pins in all the 4 banks.
-	 */
-	for (i=(u8)0U;i<InstancePtr->MaxBanks;i++) {
+        /*
+         *    Max pins in the GPIO device
+         *    0 - 31,  Bank 0
+         *    32 - 53, Bank 1
+         *    54 - 85, Bank 2
+         *    86 - 117, Bank 3
+         */
+        InstancePtr->MaxPinNum = (u32)118;
+        InstancePtr->MaxBanks = (u8)4;
+    }
+
+    /*
+     * By default, interrupts are not masked in GPIO. Disable
+     * interrupts for all pins in all the 4 banks.
+     */
+    for (i=(u8)0U;i<InstancePtr->MaxBanks;i++) {
                 if (InstancePtr->Platform == XPLAT_VERSAL){
                         if(InstancePtr->PmcGpio == (u32)FALSE)
                         {
@@ -171,16 +171,16 @@ s32 XGpioPs_CfgInitialize(XGpioPs *InstancePtr, const XGpioPs_Config *ConfigPtr,
                 }
                 else
                 {
-		XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
-					  ((u32)(i) * XGPIOPS_REG_MASK_OFFSET) +
-					  XGPIOPS_INTDIS_OFFSET, 0xFFFFFFFFU);
+        XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
+                      ((u32)(i) * XGPIOPS_REG_MASK_OFFSET) +
+                      XGPIOPS_INTDIS_OFFSET, 0xFFFFFFFFU);
                 }
-	}
+    }
 
-	/* Indicate the component is now ready to use. */
-	InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
+    /* Indicate the component is now ready to use. */
+    InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
 
-	return Status;
+    return Status;
 }
 
 /****************************************************************************/
@@ -188,20 +188,20 @@ s32 XGpioPs_CfgInitialize(XGpioPs *InstancePtr, const XGpioPs_Config *ConfigPtr,
 *
 * Read the Data register of the specified GPIO bank.
 *
-* @param	InstancePtr is a pointer to the XGpioPs instance.
-* @param	Bank is the bank number of the GPIO to operate on.
-*		Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP.
+* @param    InstancePtr is a pointer to the XGpioPs instance.
+* @param    Bank is the bank number of the GPIO to operate on.
+*        Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP.
 *
-* @return	Current value of the Data register.
+* @return    Current value of the Data register.
 *
-* @note		This function is used for reading the state of all the GPIO pins
-*		of specified bank.
+* @note        This function is used for reading the state of all the GPIO pins
+*        of specified bank.
 *
 *****************************************************************************/
 u32 XGpioPs_Read(const XGpioPs *InstancePtr, u8 Bank)
 {
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
         Xil_AssertNonvoid(Bank < InstancePtr->MaxBanks);
 #ifdef versal
         if(InstancePtr->PmcGpio == TRUE) {
@@ -211,9 +211,9 @@ u32 XGpioPs_Read(const XGpioPs *InstancePtr, u8 Bank)
         }
 #endif
 
-	return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
-				 ((u32)(Bank) * XGPIOPS_DATA_BANK_OFFSET) +
-				 XGPIOPS_DATA_RO_OFFSET);
+    return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
+                 ((u32)(Bank) * XGPIOPS_DATA_BANK_OFFSET) +
+                 XGPIOPS_DATA_RO_OFFSET);
 }
 
 /****************************************************************************/
@@ -221,35 +221,35 @@ u32 XGpioPs_Read(const XGpioPs *InstancePtr, u8 Bank)
 *
 * Read Data from the specified pin.
 *
-* @param	InstancePtr is a pointer to the XGpioPs instance.
-* @param	Pin is the pin number for which the data has to be read.
-*		Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP.
-*		See xgpiops.h for the mapping of the pin numbers in the banks.
+* @param    InstancePtr is a pointer to the XGpioPs instance.
+* @param    Pin is the pin number for which the data has to be read.
+*        Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP.
+*        See xgpiops.h for the mapping of the pin numbers in the banks.
 *
-* @return	Current value of the Pin (0 or 1).
+* @return    Current value of the Pin (0 or 1).
 *
-* @note		This function is used for reading the state of the specified
-*		GPIO pin.
+* @note        This function is used for reading the state of the specified
+*        GPIO pin.
 *
 *****************************************************************************/
 u32 XGpioPs_ReadPin(const XGpioPs *InstancePtr, u32 Pin)
 {
-	u8 Bank;
-	u8 PinNumber;
+    u8 Bank;
+    u8 PinNumber;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
-	Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum);
 
-	/* Get the Bank number and Pin number within the bank. */
+    /* Get the Bank number and Pin number within the bank. */
 #ifdef versal
-	XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber);
+    XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber);
 #else
-	XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);
+    XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);
 #endif
-	return (XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
-				 ((u32)(Bank) * XGPIOPS_DATA_BANK_OFFSET) +
-				 XGPIOPS_DATA_RO_OFFSET) >> (u32)PinNumber) & (u32)1;
+    return (XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
+                 ((u32)(Bank) * XGPIOPS_DATA_BANK_OFFSET) +
+                 XGPIOPS_DATA_RO_OFFSET) >> (u32)PinNumber) & (u32)1;
 
 }
 
@@ -258,21 +258,21 @@ u32 XGpioPs_ReadPin(const XGpioPs *InstancePtr, u32 Pin)
 *
 * Write to the Data register of the specified GPIO bank.
 *
-* @param	InstancePtr is a pointer to the XGpioPs instance.
-* @param	Bank is the bank number of the GPIO to operate on.
-*		Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP.
-* @param	Data is the value to be written to the Data register.
+* @param    InstancePtr is a pointer to the XGpioPs instance.
+* @param    Bank is the bank number of the GPIO to operate on.
+*        Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP.
+* @param    Data is the value to be written to the Data register.
 *
-* @return	None.
+* @return    None.
 *
-* @note		This function is used for writing to all the GPIO pins of
-*		the bank. The previous state of the pins is not maintained.
+* @note        This function is used for writing to all the GPIO pins of
+*        the bank. The previous state of the pins is not maintained.
 *
 *****************************************************************************/
 void XGpioPs_Write(const XGpioPs *InstancePtr, u8 Bank, u32 Data)
 {
-	Xil_AssertVoid(InstancePtr != NULL);
-	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertVoid(InstancePtr != NULL);
+    Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
         Xil_AssertVoid(Bank < InstancePtr->MaxBanks);
 #ifdef versal
         if(InstancePtr->PmcGpio == TRUE) {
@@ -282,9 +282,9 @@ void XGpioPs_Write(const XGpioPs *InstancePtr, u8 Bank, u32 Data)
         }
 #endif
 
-	XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
-			  ((u32)(Bank) * XGPIOPS_DATA_BANK_OFFSET) +
-			  XGPIOPS_DATA_OFFSET, Data);
+    XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
+              ((u32)(Bank) * XGPIOPS_DATA_BANK_OFFSET) +
+              XGPIOPS_DATA_OFFSET, Data);
 }
 
 /****************************************************************************/
@@ -292,54 +292,54 @@ void XGpioPs_Write(const XGpioPs *InstancePtr, u8 Bank, u32 Data)
 *
 * Write data to the specified pin.
 *
-* @param	InstancePtr is a pointer to the XGpioPs instance.
-* @param	Pin is the pin number to which the Data is to be written.
-*		Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP.
-* @param	Data is the data to be written to the specified pin (0 or 1).
+* @param    InstancePtr is a pointer to the XGpioPs instance.
+* @param    Pin is the pin number to which the Data is to be written.
+*        Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP.
+* @param    Data is the data to be written to the specified pin (0 or 1).
 *
-* @return	None.
+* @return    None.
 *
-* @note		This function does a masked write to the specified pin of
-*		the specified GPIO bank. The previous state of other pins
-*		is maintained.
+* @note        This function does a masked write to the specified pin of
+*        the specified GPIO bank. The previous state of other pins
+*        is maintained.
 *
 *****************************************************************************/
 void XGpioPs_WritePin(const XGpioPs *InstancePtr, u32 Pin, u32 Data)
 {
-	u32 RegOffset;
-	u32 Value;
-	u8 Bank;
-	u8 PinNumber;
-	u32 DataVar = Data;
+    u32 RegOffset;
+    u32 Value;
+    u8 Bank;
+    u8 PinNumber;
+    u32 DataVar = Data;
 
-	Xil_AssertVoid(InstancePtr != NULL);
-	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
-	Xil_AssertVoid(Pin < InstancePtr->MaxPinNum);
+    Xil_AssertVoid(InstancePtr != NULL);
+    Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertVoid(Pin < InstancePtr->MaxPinNum);
 
-	/* Get the Bank number and Pin number within the bank. */
+    /* Get the Bank number and Pin number within the bank. */
 #ifdef versal
-	XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber);
+    XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber);
 #else
-	XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);
+    XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);
 #endif
 
-	if (PinNumber > 15U) {
-		/* There are only 16 data bits in bit maskable register. */
-		PinNumber -= (u8)16;
-		RegOffset = XGPIOPS_DATA_MSW_OFFSET;
-	} else {
-		RegOffset = XGPIOPS_DATA_LSW_OFFSET;
-	}
-
-	/*
-	 * Get the 32 bit value to be written to the Mask/Data register where
-	 * the upper 16 bits is the mask and lower 16 bits is the data.
-	 */
-	DataVar &= (u32)0x01;
-	Value = ~((u32)1 << (PinNumber + 16U)) & ((DataVar << PinNumber) | 0xFFFF0000U);
-	XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
-			  ((u32)(Bank) * XGPIOPS_DATA_MASK_OFFSET) +
-			  RegOffset, Value);
+    if (PinNumber > 15U) {
+        /* There are only 16 data bits in bit maskable register. */
+        PinNumber -= (u8)16;
+        RegOffset = XGPIOPS_DATA_MSW_OFFSET;
+    } else {
+        RegOffset = XGPIOPS_DATA_LSW_OFFSET;
+    }
+
+    /*
+     * Get the 32 bit value to be written to the Mask/Data register where
+     * the upper 16 bits is the mask and lower 16 bits is the data.
+     */
+    DataVar &= (u32)0x01;
+    Value = ~((u32)1 << (PinNumber + 16U)) & ((DataVar << PinNumber) | 0xFFFF0000U);
+    XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
+              ((u32)(Bank) * XGPIOPS_DATA_MASK_OFFSET) +
+              RegOffset, Value);
 
 }
 
@@ -350,24 +350,24 @@ void XGpioPs_WritePin(const XGpioPs *InstancePtr, u32 Pin, u32 Data)
 *
 * Set the Direction of the pins of the specified GPIO Bank.
 *
-* @param	InstancePtr is a pointer to the XGpioPs instance.
-* @param	Bank is the bank number of the GPIO to operate on.
-*		Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP.
-* @param	Direction is the 32 bit mask of the Pin direction to be set for
-*		all the pins in the Bank. Bits with 0 are set to Input mode,
-*		bits with 1 are	set to Output Mode.
+* @param    InstancePtr is a pointer to the XGpioPs instance.
+* @param    Bank is the bank number of the GPIO to operate on.
+*        Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP.
+* @param    Direction is the 32 bit mask of the Pin direction to be set for
+*        all the pins in the Bank. Bits with 0 are set to Input mode,
+*        bits with 1 are    set to Output Mode.
 *
-* @return	None.
+* @return    None.
 *
-* @note		This function is used for setting the direction of all the pins
-*		in the specified bank. The previous state of the pins is
-*		not maintained.
+* @note        This function is used for setting the direction of all the pins
+*        in the specified bank. The previous state of the pins is
+*        not maintained.
 *
 *****************************************************************************/
 void XGpioPs_SetDirection(const XGpioPs *InstancePtr, u8 Bank, u32 Direction)
 {
-	Xil_AssertVoid(InstancePtr != NULL);
-	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertVoid(InstancePtr != NULL);
+    Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
         Xil_AssertVoid(Bank < InstancePtr->MaxBanks);
 #ifdef versal
         if(InstancePtr->PmcGpio == TRUE) {
@@ -377,9 +377,9 @@ void XGpioPs_SetDirection(const XGpioPs *InstancePtr, u8 Bank, u32 Direction)
         }
 #endif
 
-	XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
-			  ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
-			  XGPIOPS_DIRM_OFFSET, Direction);
+    XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
+              ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
+              XGPIOPS_DIRM_OFFSET, Direction);
 }
 
 /****************************************************************************/
@@ -387,45 +387,45 @@ void XGpioPs_SetDirection(const XGpioPs *InstancePtr, u8 Bank, u32 Direction)
 *
 * Set the Direction of the specified pin.
 *
-* @param	InstancePtr is a pointer to the XGpioPs instance.
-* @param	Pin is the pin number to which the Data is to be written.
-*		Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP.
-* @param	Direction is the direction to be set for the specified pin.
-*		Valid values are 0 for Input Direction, 1 for Output Direction.
+* @param    InstancePtr is a pointer to the XGpioPs instance.
+* @param    Pin is the pin number to which the Data is to be written.
+*        Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP.
+* @param    Direction is the direction to be set for the specified pin.
+*        Valid values are 0 for Input Direction, 1 for Output Direction.
 *
-* @return	None.
+* @return    None.
 *
 *****************************************************************************/
 void XGpioPs_SetDirectionPin(const XGpioPs *InstancePtr, u32 Pin, u32 Direction)
 {
-	u8 Bank;
-	u8 PinNumber;
-	u32 DirModeReg;
+    u8 Bank;
+    u8 PinNumber;
+    u32 DirModeReg;
 
-	Xil_AssertVoid(InstancePtr != NULL);
-	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
-	Xil_AssertVoid(Pin < InstancePtr->MaxPinNum);
-	Xil_AssertVoid(Direction <= (u32)1);
+    Xil_AssertVoid(InstancePtr != NULL);
+    Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertVoid(Pin < InstancePtr->MaxPinNum);
+    Xil_AssertVoid(Direction <= (u32)1);
 
-	/* Get the Bank number and Pin number within the bank. */
+    /* Get the Bank number and Pin number within the bank. */
 #ifdef versal
-	XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber);
+    XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber);
 #else
-	XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);
+    XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);
 #endif
-	DirModeReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
-				      ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
-				      XGPIOPS_DIRM_OFFSET);
-
-	if (Direction!=(u32)0) { /*  Output Direction */
-		DirModeReg |= ((u32)1 << (u32)PinNumber);
-	} else { /* Input Direction */
-		DirModeReg &= ~ ((u32)1 << (u32)PinNumber);
-	}
-
-	XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
-			 ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
-			 XGPIOPS_DIRM_OFFSET, DirModeReg);
+    DirModeReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
+                      ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
+                      XGPIOPS_DIRM_OFFSET);
+
+    if (Direction!=(u32)0) { /*  Output Direction */
+        DirModeReg |= ((u32)1 << (u32)PinNumber);
+    } else { /* Input Direction */
+        DirModeReg &= ~ ((u32)1 << (u32)PinNumber);
+    }
+
+    XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
+             ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
+             XGPIOPS_DIRM_OFFSET, DirModeReg);
 }
 
 /****************************************************************************/
@@ -433,20 +433,20 @@ void XGpioPs_SetDirectionPin(const XGpioPs *InstancePtr, u32 Pin, u32 Direction)
 *
 * Get the Direction of the pins of the specified GPIO Bank.
 *
-* @param	InstancePtr is a pointer to the XGpioPs instance.
-* @param	Bank is the bank number of the GPIO to operate on.
-*		Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP.
+* @param    InstancePtr is a pointer to the XGpioPs instance.
+* @param    Bank is the bank number of the GPIO to operate on.
+*        Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP.
 *
-* @return	Returns a 32 bit mask of the Direction register. Bits with 0 are
-* 		in Input mode, bits with 1 are in Output Mode.
+* @return    Returns a 32 bit mask of the Direction register. Bits with 0 are
+*         in Input mode, bits with 1 are in Output Mode.
 *
-* @note		None.
+* @note        None.
 *
 *****************************************************************************/
 u32 XGpioPs_GetDirection(const XGpioPs *InstancePtr, u8 Bank)
 {
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
         Xil_AssertNonvoid(Bank < InstancePtr->MaxBanks);
 #ifdef versal
         if(InstancePtr->PmcGpio == TRUE) {
@@ -456,9 +456,9 @@ u32 XGpioPs_GetDirection(const XGpioPs *InstancePtr, u8 Bank)
         }
 #endif
 
-	return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
-				((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
-				XGPIOPS_DIRM_OFFSET);
+    return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
+                ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
+                XGPIOPS_DIRM_OFFSET);
 }
 
 /****************************************************************************/
@@ -466,37 +466,37 @@ u32 XGpioPs_GetDirection(const XGpioPs *InstancePtr, u8 Bank)
 *
 * Get the Direction of the specified pin.
 *
-* @param	InstancePtr is a pointer to the XGpioPs instance.
-* @param	Pin is the pin number for which the Direction is to be
-*		retrieved.
-*		Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP.
+* @param    InstancePtr is a pointer to the XGpioPs instance.
+* @param    Pin is the pin number for which the Direction is to be
+*        retrieved.
+*        Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP.
 *
-* @return	Direction of the specified pin.
-*		- 0 for Input Direction
-*		- 1 for Output Direction
+* @return    Direction of the specified pin.
+*        - 0 for Input Direction
+*        - 1 for Output Direction
 *
-* @note		None.
+* @note        None.
 *
 *****************************************************************************/
 u32 XGpioPs_GetDirectionPin(const XGpioPs *InstancePtr, u32 Pin)
 {
-	u8 Bank;
-	u8 PinNumber;
+    u8 Bank;
+    u8 PinNumber;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
-	Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum);
 
-	/* Get the Bank number and Pin number within the bank. */
+    /* Get the Bank number and Pin number within the bank. */
 #ifdef versal
-	XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber);
+    XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber);
 #else
-	XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);
+    XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);
 #endif
 
-	return (XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
-				 ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
-				 XGPIOPS_DIRM_OFFSET) >> (u32)PinNumber) & (u32)1;
+    return (XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
+                 ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
+                 XGPIOPS_DIRM_OFFSET) >> (u32)PinNumber) & (u32)1;
 }
 
 /****************************************************************************/
@@ -504,24 +504,24 @@ u32 XGpioPs_GetDirectionPin(const XGpioPs *InstancePtr, u32 Pin)
 *
 * Set the Output Enable of the pins of the specified GPIO Bank.
 *
-* @param	InstancePtr is a pointer to the XGpioPs instance.
-* @param	Bank is the bank number of the GPIO to operate on.
-*		Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP.
-* @param	OpEnable is the 32 bit mask of the Output Enables to be set for
-*		all the pins in the Bank. The Output Enable of bits with 0 are
-*		disabled, the Output Enable of bits with 1 are enabled.
+* @param    InstancePtr is a pointer to the XGpioPs instance.
+* @param    Bank is the bank number of the GPIO to operate on.
+*        Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP.
+* @param    OpEnable is the 32 bit mask of the Output Enables to be set for
+*        all the pins in the Bank. The Output Enable of bits with 0 are
+*        disabled, the Output Enable of bits with 1 are enabled.
 *
-* @return	None.
+* @return    None.
 *
-* @note		This function is used for setting the Output Enables of all the
-*		pins in the specified bank. The previous state of the Output
-*		Enables is not maintained.
+* @note        This function is used for setting the Output Enables of all the
+*        pins in the specified bank. The previous state of the Output
+*        Enables is not maintained.
 *
 *****************************************************************************/
 void XGpioPs_SetOutputEnable(const XGpioPs *InstancePtr, u8 Bank, u32 OpEnable)
 {
-	Xil_AssertVoid(InstancePtr != NULL);
-	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertVoid(InstancePtr != NULL);
+    Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
         Xil_AssertVoid(Bank < InstancePtr->MaxBanks);
 #ifdef versal
         if(InstancePtr->PmcGpio == TRUE) {
@@ -531,9 +531,9 @@ void XGpioPs_SetOutputEnable(const XGpioPs *InstancePtr, u8 Bank, u32 OpEnable)
         }
 #endif
 
-	XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
-			  ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
-			  XGPIOPS_OUTEN_OFFSET, OpEnable);
+    XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
+              ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
+              XGPIOPS_OUTEN_OFFSET, OpEnable);
 }
 
 /****************************************************************************/
@@ -541,71 +541,71 @@ void XGpioPs_SetOutputEnable(const XGpioPs *InstancePtr, u8 Bank, u32 OpEnable)
 *
 * Set the Output Enable of the specified pin.
 *
-* @param	InstancePtr is a pointer to the XGpioPs instance.
-* @param	Pin is the pin number to which the Data is to be written.
-*		Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP.
-* @param	OpEnable specifies whether the Output Enable for the specified
-*		pin should be enabled.
-*		Valid values are 0 for Disabling Output Enable,
-*		1 for Enabling Output Enable.
+* @param    InstancePtr is a pointer to the XGpioPs instance.
+* @param    Pin is the pin number to which the Data is to be written.
+*        Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP.
+* @param    OpEnable specifies whether the Output Enable for the specified
+*        pin should be enabled.
+*        Valid values are 0 for Disabling Output Enable,
+*        1 for Enabling Output Enable.
 *
-* @return	None.
+* @return    None.
 *
-* @note		None.
+* @note        None.
 *
 *****************************************************************************/
 void XGpioPs_SetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin, u32 OpEnable)
 {
-	u8 Bank;
-	u8 PinNumber;
-	u32 OpEnableReg;
+    u8 Bank;
+    u8 PinNumber;
+    u32 OpEnableReg;
 
-	Xil_AssertVoid(InstancePtr != NULL);
-	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
-	Xil_AssertVoid(Pin < InstancePtr->MaxPinNum);
-	Xil_AssertVoid(OpEnable <= (u32)1);
+    Xil_AssertVoid(InstancePtr != NULL);
+    Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertVoid(Pin < InstancePtr->MaxPinNum);
+    Xil_AssertVoid(OpEnable <= (u32)1);
 
-	/* Get the Bank number and Pin number within the bank. */
+    /* Get the Bank number and Pin number within the bank. */
 #ifdef versal
-	XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber);
+    XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber);
 #else
-	XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);
+    XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);
 #endif
 
-	OpEnableReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
-				       ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
-				       XGPIOPS_OUTEN_OFFSET);
+    OpEnableReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
+                       ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
+                       XGPIOPS_OUTEN_OFFSET);
 
-	if (OpEnable != (u32)0) { /*  Enable Output Enable */
-		OpEnableReg |= ((u32)1 << (u32)PinNumber);
-	} else { /* Disable Output Enable */
-		OpEnableReg &= ~ ((u32)1 << (u32)PinNumber);
-	}
+    if (OpEnable != (u32)0) { /*  Enable Output Enable */
+        OpEnableReg |= ((u32)1 << (u32)PinNumber);
+    } else { /* Disable Output Enable */
+        OpEnableReg &= ~ ((u32)1 << (u32)PinNumber);
+    }
 
-	XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
-			  ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
-			  XGPIOPS_OUTEN_OFFSET, OpEnableReg);
+    XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
+              ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
+              XGPIOPS_OUTEN_OFFSET, OpEnableReg);
 }
 /****************************************************************************/
 /**
 *
 * Get the Output Enable status of the pins of the specified GPIO Bank.
 *
-* @param	InstancePtr is a pointer to the XGpioPs instance.
-* @param	Bank is the bank number of the GPIO to operate on.
-*		Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP.
+* @param    InstancePtr is a pointer to the XGpioPs instance.
+* @param    Bank is the bank number of the GPIO to operate on.
+*        Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP.
 *
-* @return	Returns a a 32 bit mask of the Output Enable register.
-*		Bits with 0 are in Disabled state, bits with 1 are in
-*		Enabled State.
+* @return    Returns a a 32 bit mask of the Output Enable register.
+*        Bits with 0 are in Disabled state, bits with 1 are in
+*        Enabled State.
 *
-* @note		None.
+* @note        None.
 *
 *****************************************************************************/
 u32 XGpioPs_GetOutputEnable(const XGpioPs *InstancePtr, u8 Bank)
 {
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
         Xil_AssertNonvoid(Bank < InstancePtr->MaxBanks);
 #ifdef versal
         if(InstancePtr->PmcGpio == TRUE) {
@@ -615,9 +615,9 @@ u32 XGpioPs_GetOutputEnable(const XGpioPs *InstancePtr, u8 Bank)
         }
 #endif
 
-	return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
-				((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
-				XGPIOPS_OUTEN_OFFSET);
+    return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
+                ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
+                XGPIOPS_OUTEN_OFFSET);
 }
 
 /****************************************************************************/
@@ -625,37 +625,37 @@ u32 XGpioPs_GetOutputEnable(const XGpioPs *InstancePtr, u8 Bank)
 *
 * Get the Output Enable status of the specified pin.
 *
-* @param	InstancePtr is a pointer to the XGpioPs instance.
-* @param	Pin is the pin number for which the Output Enable status is to
-*		be retrieved.
-*		Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP.
+* @param    InstancePtr is a pointer to the XGpioPs instance.
+* @param    Pin is the pin number for which the Output Enable status is to
+*        be retrieved.
+*        Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP.
 *
-* @return	Output Enable of the specified pin.
-*		- 0 if Output Enable is disabled for this pin
-*		- 1 if Output Enable is enabled for this pin
+* @return    Output Enable of the specified pin.
+*        - 0 if Output Enable is disabled for this pin
+*        - 1 if Output Enable is enabled for this pin
 *
-* @note		None.
+* @note        None.
 *
 *****************************************************************************/
 u32 XGpioPs_GetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin)
 {
-	u8 Bank;
-	u8 PinNumber;
+    u8 Bank;
+    u8 PinNumber;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
-	Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum);
 
-	/* Get the Bank number and Pin number within the bank. */
+    /* Get the Bank number and Pin number within the bank. */
 #ifdef versal
-	XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber);
+    XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber);
 #else
-	XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);
+    XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);
 #endif
 
-	return (XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
-				 ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
-				 XGPIOPS_OUTEN_OFFSET) >> (u32)PinNumber) & (u32)1;
+    return (XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
+                 ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
+                 XGPIOPS_OUTEN_OFFSET) >> (u32)PinNumber) & (u32)1;
 }
 
 /****************************************************************************/
@@ -664,14 +664,14 @@ u32 XGpioPs_GetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin)
 * Get the Bank number and the Pin number in the Bank, for the given PinNumber
 * in the GPIO device.
 *
-* @param	PinNumber is the Pin number in the GPIO device.
-* @param	BankNumber returns the Bank in which this GPIO pin is present.
-*		Valid values are 0 to XGPIOPS_MAX_BANKS - 1.
-* @param	PinNumberInBank returns the Pin Number within the Bank.
+* @param    PinNumber is the Pin number in the GPIO device.
+* @param    BankNumber returns the Bank in which this GPIO pin is present.
+*        Valid values are 0 to XGPIOPS_MAX_BANKS - 1.
+* @param    PinNumberInBank returns the Pin Number within the Bank.
 *
-* @return	None.
+* @return    None.
 *
-* @note		None.
+* @note        None.
 *
 *****************************************************************************/
 #ifdef versal
@@ -680,33 +680,33 @@ void XGpioPs_GetBankPin(const XGpioPs *InstancePtr,u8 PinNumber, u8 *BankNumber,
 void XGpioPs_GetBankPin(u8 PinNumber, u8 *BankNumber, u8 *PinNumberInBank)
 #endif
 {
-	u32 XGpioPsPinTable[6] = {0};
+    u32 XGpioPsPinTable[6] = {0};
 #ifdef versal
         u8 i=(u8)0;
 #endif
-	u32 Platform = XGetPlatform_Info();
-
-	if (Platform == (u32)XPLAT_ZYNQ_ULTRA_MP) {
-		/*
-		 * This structure defines the mapping of the pin numbers to the banks when
-		 * the driver APIs are used for working on the individual pins.
-		 */
-
-		XGpioPsPinTable[0] = (u32)25; /* 0 - 25, Bank 0 */
-		XGpioPsPinTable[1] = (u32)51; /* 26 - 51, Bank 1 */
-		XGpioPsPinTable[2] = (u32)77; /* 52 - 77, Bank 2 */
-		XGpioPsPinTable[3] = (u32)109; /* 78 - 109, Bank 3 */
-		XGpioPsPinTable[4] = (u32)141; /* 110 - 141, Bank 4 */
-		XGpioPsPinTable[5] = (u32)173; /* 142 - 173 Bank 5 */
-
-		*BankNumber = 0U;
-		while (*BankNumber < XGPIOPS_SIX) {
-			if (PinNumber <= XGpioPsPinTable[*BankNumber]) {
-				break;
-			}
-			(*BankNumber)++;
-		}
-	}
+    u32 Platform = XGetPlatform_Info();
+
+    if (Platform == (u32)XPLAT_ZYNQ_ULTRA_MP) {
+        /*
+         * This structure defines the mapping of the pin numbers to the banks when
+         * the driver APIs are used for working on the individual pins.
+         */
+
+        XGpioPsPinTable[0] = (u32)25; /* 0 - 25, Bank 0 */
+        XGpioPsPinTable[1] = (u32)51; /* 26 - 51, Bank 1 */
+        XGpioPsPinTable[2] = (u32)77; /* 52 - 77, Bank 2 */
+        XGpioPsPinTable[3] = (u32)109; /* 78 - 109, Bank 3 */
+        XGpioPsPinTable[4] = (u32)141; /* 110 - 141, Bank 4 */
+        XGpioPsPinTable[5] = (u32)173; /* 142 - 173 Bank 5 */
+
+        *BankNumber = 0U;
+        while (*BankNumber < XGPIOPS_SIX) {
+            if (PinNumber <= XGpioPsPinTable[*BankNumber]) {
+                break;
+            }
+            (*BankNumber)++;
+        }
+    }
 #ifdef versal
         else if(Platform == XPLAT_VERSAL)
         {
@@ -760,22 +760,22 @@ void XGpioPs_GetBankPin(u8 PinNumber, u8 *BankNumber, u8 *PinNumberInBank)
         }
 #endif
         else {
-		XGpioPsPinTable[0] = (u32)31; /* 0 - 31, Bank 0 */
-		XGpioPsPinTable[1] = (u32)53; /* 32 - 53, Bank 1 */
-		XGpioPsPinTable[2] = (u32)85; /* 54 - 85, Bank 2 */
-		XGpioPsPinTable[3] = (u32)117; /* 86 - 117 Bank 3 */
-
-		*BankNumber = 0U;
-		while (*BankNumber < XGPIOPS_FOUR) {
-			if (PinNumber <= XGpioPsPinTable[*BankNumber]) {
-				break;
-			}
-			(*BankNumber)++;
-		}
-	}
-	if (*BankNumber == (u8)0) {
-		*PinNumberInBank = PinNumber;
-	}
+        XGpioPsPinTable[0] = (u32)31; /* 0 - 31, Bank 0 */
+        XGpioPsPinTable[1] = (u32)53; /* 32 - 53, Bank 1 */
+        XGpioPsPinTable[2] = (u32)85; /* 54 - 85, Bank 2 */
+        XGpioPsPinTable[3] = (u32)117; /* 86 - 117 Bank 3 */
+
+        *BankNumber = 0U;
+        while (*BankNumber < XGPIOPS_FOUR) {
+            if (PinNumber <= XGpioPsPinTable[*BankNumber]) {
+                break;
+            }
+            (*BankNumber)++;
+        }
+    }
+    if (*BankNumber == (u8)0) {
+        *PinNumberInBank = PinNumber;
+    }
 
 #ifdef versal
         else if(Platform == XPLAT_VERSAL)
@@ -801,8 +801,8 @@ void XGpioPs_GetBankPin(u8 PinNumber, u8 *BankNumber, u8 *PinNumberInBank)
 #endif
 
         else {
-		*PinNumberInBank = (u8)((u32)PinNumber %
-					(XGpioPsPinTable[*BankNumber - (u8)1] + (u32)1));
+        *PinNumberInBank = (u8)((u32)PinNumber %
+                    (XGpioPsPinTable[*BankNumber - (u8)1] + (u32)1));
         }
 }
 /** @} */

+ 64 - 64
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops.h

@@ -15,10 +15,10 @@
 * Controller.
 *
 * The GPIO Controller supports the following features:
-*	- 4 banks
-*	- Masked writes (There are no masked reads)
-*	- Bypass mode
-*	- Configurable Interrupts (Level/Edge)
+*    - 4 banks
+*    - Masked writes (There are no masked reads)
+*    - Bypass mode
+*    - Configurable Interrupts (Level/Edge)
 *
 * This driver is intended to be RTOS and processor independent. Any needs for
 * dynamic memory management, threads or thread mutual exclusion, virtual
@@ -63,14 +63,14 @@
 * 1.00a sv   01/15/10 First Release
 * 1.01a sv   04/15/12 Removed the APIs XGpioPs_SetMode, XGpioPs_SetModePin
 *                     XGpioPs_GetMode, XGpioPs_GetModePin as they are not
-*		      relevant to Zynq device.The interrupts are disabled
-*		      for output pins on all banks during initialization.
+*              relevant to Zynq device.The interrupts are disabled
+*              for output pins on all banks during initialization.
 * 1.02a hk   08/22/13 Added low level reset API
 * 2.1   hk   04/29/14 Use Input data register DATA_RO for read. CR# 771667.
-* 2.2	sk	 10/13/14 Used Pin number in Bank instead of pin number
-* 					  passed to APIs. CR# 822636
+* 2.2    sk     10/13/14 Used Pin number in Bank instead of pin number
+*                       passed to APIs. CR# 822636
 * 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
-* 3.1	kvn  04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980.
+* 3.1    kvn  04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980.
 *       ms   03/17/17 Added readme.txt file in examples folder for doxygen
 *                     generation.
 *       ms   04/05/17 Added tabspace for return statements in functions of
@@ -89,15 +89,15 @@
 * 3.5   sne  03/14/19 Added Versal support.
 * 3.6   mus  04/05/19 Replaced XPLAT_versal macro with XPLAT_VERSAL, to be in
 *                     sync with standalone BSP
-* 3.6	sne  06/12/19 Fixed IAR compiler warning.
+* 3.6    sne  06/12/19 Fixed IAR compiler warning.
 * 3.6   sne  08/14/19 Added interrupt handler support on versal.
-* 3.7	sne  12/04/19 Reverted versal examples support.
+* 3.7    sne  12/04/19 Reverted versal examples support.
 *
 * </pre>
 *
 ******************************************************************************/
-#ifndef XGPIOPS_H		/* prevent circular inclusions */
-#define XGPIOPS_H		/* by using protection macros */
+#ifndef XGPIOPS_H        /* prevent circular inclusions */
+#define XGPIOPS_H        /* by using protection macros */
 
 #ifdef __cplusplus
 extern "C" {
@@ -116,44 +116,44 @@ extern "C" {
  * The following constants define the interrupt types that can be set for each
  * GPIO pin.
  */
-#define XGPIOPS_IRQ_TYPE_EDGE_RISING	0x00U  /**< Interrupt on Rising edge */
-#define XGPIOPS_IRQ_TYPE_EDGE_FALLING	0x01U  /**< Interrupt Falling edge */
-#define XGPIOPS_IRQ_TYPE_EDGE_BOTH	0x02U  /**< Interrupt on both edges */
-#define XGPIOPS_IRQ_TYPE_LEVEL_HIGH	0x03U  /**< Interrupt on high level */
-#define XGPIOPS_IRQ_TYPE_LEVEL_LOW	0x04U  /**< Interrupt on low level */
+#define XGPIOPS_IRQ_TYPE_EDGE_RISING    0x00U  /**< Interrupt on Rising edge */
+#define XGPIOPS_IRQ_TYPE_EDGE_FALLING    0x01U  /**< Interrupt Falling edge */
+#define XGPIOPS_IRQ_TYPE_EDGE_BOTH    0x02U  /**< Interrupt on both edges */
+#define XGPIOPS_IRQ_TYPE_LEVEL_HIGH    0x03U  /**< Interrupt on high level */
+#define XGPIOPS_IRQ_TYPE_LEVEL_LOW    0x04U  /**< Interrupt on low level */
 /*@}*/
 
-#define XGPIOPS_BANK_MAX_PINS		(u32)32 /**< Max pins in a GPIO bank */
-#define XGPIOPS_BANK0			0x00U  /**< GPIO Bank 0 */
-#define XGPIOPS_BANK1			0x01U  /**< GPIO Bank 1 */
-#define XGPIOPS_BANK2			0x02U  /**< GPIO Bank 2 */
-#define XGPIOPS_BANK3			0x03U  /**< GPIO Bank 3 */
+#define XGPIOPS_BANK_MAX_PINS        (u32)32 /**< Max pins in a GPIO bank */
+#define XGPIOPS_BANK0            0x00U  /**< GPIO Bank 0 */
+#define XGPIOPS_BANK1            0x01U  /**< GPIO Bank 1 */
+#define XGPIOPS_BANK2            0x02U  /**< GPIO Bank 2 */
+#define XGPIOPS_BANK3            0x03U  /**< GPIO Bank 3 */
 
 #ifdef XPAR_PSU_GPIO_0_BASEADDR
-#define XGPIOPS_BANK4			0x04U  /**< GPIO Bank 4 */
-#define XGPIOPS_BANK5			0x05U  /**< GPIO Bank 5 */
+#define XGPIOPS_BANK4            0x04U  /**< GPIO Bank 4 */
+#define XGPIOPS_BANK5            0x05U  /**< GPIO Bank 5 */
 #endif
 
-#define XGPIOPS_MAX_BANKS_ZYNQMP		0x06U  /**< Max banks in a
-										*	Zynq Ultrascale+ MP GPIO device
-										*/
-#define XGPIOPS_MAX_BANKS		0x04U  /**< Max banks in a Zynq GPIO device */
+#define XGPIOPS_MAX_BANKS_ZYNQMP        0x06U  /**< Max banks in a
+                                        *    Zynq Ultrascale+ MP GPIO device
+                                        */
+#define XGPIOPS_MAX_BANKS        0x04U  /**< Max banks in a Zynq GPIO device */
 
-#define XGPIOPS_DEVICE_MAX_PIN_NUM_ZYNQMP	(u32)174 /**< Max pins in the
-						  *	Zynq Ultrascale+ MP GPIO device
-					      * 0 - 25,  Bank 0
-					      * 26 - 51, Bank 1
-					      *	52 - 77, Bank 2
-					      *	78 - 109, Bank 3
-					      *	110 - 141, Bank 4
-					      *	142 - 173, Bank 5
-					      */
-#define XGPIOPS_DEVICE_MAX_PIN_NUM	(u32)118 /**< Max pins in the Zynq GPIO device
-					      * 0 - 31,  Bank 0
-					      * 32 - 53, Bank 1
-					      *	54 - 85, Bank 2
-					      *	86 - 117, Bank 3
-					      */
+#define XGPIOPS_DEVICE_MAX_PIN_NUM_ZYNQMP    (u32)174 /**< Max pins in the
+                          *    Zynq Ultrascale+ MP GPIO device
+                          * 0 - 25,  Bank 0
+                          * 26 - 51, Bank 1
+                          *    52 - 77, Bank 2
+                          *    78 - 109, Bank 3
+                          *    110 - 141, Bank 4
+                          *    142 - 173, Bank 5
+                          */
+#define XGPIOPS_DEVICE_MAX_PIN_NUM    (u32)118 /**< Max pins in the Zynq GPIO device
+                          * 0 - 31,  Bank 0
+                          * 32 - 53, Bank 1
+                          *    54 - 85, Bank 2
+                          *    86 - 117, Bank 3
+                          */
 
 /**************************** Type Definitions *******************************/
 
@@ -165,13 +165,13 @@ extern "C" {
  * driven mode. The handler executes in an interrupt context such that minimal
  * processing should be performed.
  *
- * @param	CallBackRef is a callback reference passed in by the upper layer
- *		when setting the callback functions for a GPIO bank. It is
- *		passed back to the upper layer when the callback is invoked. Its
- *		type is not important to the driver component, so it is a void
- *		pointer.
- * @param	Bank is the bank for which the interrupt status has changed.
- * @param	Status is the Interrupt status of the GPIO bank.
+ * @param    CallBackRef is a callback reference passed in by the upper layer
+ *        when setting the callback functions for a GPIO bank. It is
+ *        passed back to the upper layer when the callback is invoked. Its
+ *        type is not important to the driver component, so it is a void
+ *        pointer.
+ * @param    Bank is the bank for which the interrupt status has changed.
+ * @param    Status is the Interrupt status of the GPIO bank.
  *
  *****************************************************************************/
 typedef void (*XGpioPs_Handler) (void *CallBackRef, u32 Bank, u32 Status);
@@ -180,8 +180,8 @@ typedef void (*XGpioPs_Handler) (void *CallBackRef, u32 Bank, u32 Status);
  * This typedef contains configuration information for a device.
  */
 typedef struct {
-	u16 DeviceId;		/**< Unique ID of device */
-	u32 BaseAddr;		/**< Register base address */
+    u16 DeviceId;        /**< Unique ID of device */
+    u32 BaseAddr;        /**< Register base address */
 } XGpioPs_Config;
 
 /**
@@ -190,13 +190,13 @@ typedef struct {
  * to a variable of this type is then passed to the driver API functions.
  */
 typedef struct {
-	XGpioPs_Config GpioConfig;	/**< Device configuration */
-	u32 IsReady;			/**< Device is initialized and ready */
-	XGpioPs_Handler Handler;	/**< Status handlers for all banks */
-	void *CallBackRef; 		/**< Callback ref for bank handlers */
-	u32 Platform;			/**< Platform data */
-	u32 MaxPinNum;			/**< Max pins in the GPIO device */
-	u8 MaxBanks;			/**< Max banks in a GPIO device */
+    XGpioPs_Config GpioConfig;    /**< Device configuration */
+    u32 IsReady;            /**< Device is initialized and ready */
+    XGpioPs_Handler Handler;    /**< Status handlers for all banks */
+    void *CallBackRef;         /**< Callback ref for bank handlers */
+    u32 Platform;            /**< Platform data */
+    u32 MaxPinNum;            /**< Max pins in the GPIO device */
+    u8 MaxBanks;            /**< Max banks in a GPIO device */
         u32 PmcGpio;                    /**< Flag for accessing PS GPIO for versal*/
 } XGpioPs;
 
@@ -206,7 +206,7 @@ typedef struct {
 
 /* Functions in xgpiops.c */
 s32 XGpioPs_CfgInitialize(XGpioPs *InstancePtr, const XGpioPs_Config *ConfigPtr,
-			   u32 EffectiveAddr);
+               u32 EffectiveAddr);
 
 /* Bank APIs in xgpiops.c */
 u32 XGpioPs_Read(const XGpioPs *InstancePtr, u8 Bank);
@@ -240,11 +240,11 @@ u32 XGpioPs_IntrGetEnabled(const XGpioPs *InstancePtr, u8 Bank);
 u32 XGpioPs_IntrGetStatus(const XGpioPs *InstancePtr, u8 Bank);
 void XGpioPs_IntrClear(const XGpioPs *InstancePtr, u8 Bank, u32 Mask);
 void XGpioPs_SetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 IntrType,
-			  u32 IntrPolarity, u32 IntrOnAny);
+              u32 IntrPolarity, u32 IntrOnAny);
 void XGpioPs_GetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 *IntrType,
-			  u32 *IntrPolarity, u32 *IntrOnAny);
+              u32 *IntrPolarity, u32 *IntrOnAny);
 void XGpioPs_SetCallbackHandler(XGpioPs *InstancePtr, void *CallBackRef,
-			     XGpioPs_Handler FuncPointer);
+                 XGpioPs_Handler FuncPointer);
 void XGpioPs_IntrHandler(const XGpioPs *InstancePtr);
 
 /* Pin APIs in xgpiops_intr.c */

+ 6 - 6
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_g.c

@@ -6,9 +6,9 @@
 * DO NOT EDIT.
 *
 * Copyright (C) 2010-2020 Xilinx, Inc. All Rights Reserved.
-* SPDX-License-Identifier: MIT 
+* SPDX-License-Identifier: MIT
 
-* 
+*
 * Description: Driver configuration
 *
 *******************************************************************/
@@ -22,10 +22,10 @@
 
 XGpioPs_Config XGpioPs_ConfigTable[XPAR_XGPIOPS_NUM_INSTANCES] =
 {
-	{
-		XPAR_PSU_GPIO_0_DEVICE_ID,
-		XPAR_PSU_GPIO_0_BASEADDR
-	}
+    {
+        XPAR_PSU_GPIO_0_DEVICE_ID,
+        XPAR_PSU_GPIO_0_BASEADDR
+    }
 };
 
 

+ 7 - 7
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_hw.c

@@ -19,7 +19,7 @@
 * ----- ---- -------- -----------------------------------------------
 * 1.02a hk   08/22/13 First Release
 * 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
-* 3.1	kvn  04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980.
+* 3.1    kvn  04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980.
 * 3.5   sne  03/01/19 Fixes violations according to MISRAC-2012
 *                     in safety mode and modified the code such as
 *                     Use of mixed mode arithmetic,Declared the pointer param
@@ -52,19 +52,19 @@
 * This function resets the GPIO module by writing reset values to
 * all registers
 *
-* @param	Base address of GPIO module
+* @param    Base address of GPIO module
 *
-* @return	None
+* @return    None
 *
-* @note		None.
+* @note        None.
 *
 ******************************************************************************/
 void XGpioPs_ResetHw(u32 BaseAddress)
 {
-	u32 BankCount;
-	u32 Platform,MaxBanks;
+    u32 BankCount;
+    u32 Platform,MaxBanks;
 
-	Platform = XGetPlatform_Info();
+    Platform = XGetPlatform_Info();
         if (Platform == (u32)XPLAT_ZYNQ_ULTRA_MP) {
                 MaxBanks = (u32)6;
         }

+ 28 - 28
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_hw.h

@@ -23,13 +23,13 @@
 * 1.02a hk   08/22/13 Added low level reset API function prototype and
 *                     related constant definitions
 * 3.00  kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
-* 3.1	kvn  04/13/15 Corrected reset values of banks.
+* 3.1    kvn  04/13/15 Corrected reset values of banks.
 * 3.5   sne  03/14/19 Added versal support.
 * </pre>
 *
 ******************************************************************************/
-#ifndef XGPIOPS_HW_H		/* prevent circular inclusions */
-#define XGPIOPS_HW_H		/* by using protection macros */
+#ifndef XGPIOPS_HW_H        /* prevent circular inclusions */
+#define XGPIOPS_HW_H        /* by using protection macros */
 
 #ifdef __cplusplus
 extern "C" {
@@ -48,17 +48,17 @@ extern "C" {
  */
 #define XGPIOPS_DATA_LSW_OFFSET  0x00000000U  /* Mask and Data Register LSW, WO */
 #define XGPIOPS_DATA_MSW_OFFSET  0x00000004U  /* Mask and Data Register MSW, WO */
-#define XGPIOPS_DATA_OFFSET	 0x00000040U  /* Data Register, RW */
-#define XGPIOPS_DATA_RO_OFFSET	 0x00000060U  /* Data Register - Input, RO */
-#define XGPIOPS_DIRM_OFFSET	 0x00000204U  /* Direction Mode Register, RW */
-#define XGPIOPS_OUTEN_OFFSET	 0x00000208U  /* Output Enable Register, RW */
-#define XGPIOPS_INTMASK_OFFSET	 0x0000020CU  /* Interrupt Mask Register, RO */
-#define XGPIOPS_INTEN_OFFSET	 0x00000210U  /* Interrupt Enable Register, WO */
-#define XGPIOPS_INTDIS_OFFSET	 0x00000214U  /* Interrupt Disable Register, WO*/
-#define XGPIOPS_INTSTS_OFFSET	 0x00000218U  /* Interrupt Status Register, RO */
-#define XGPIOPS_INTTYPE_OFFSET	 0x0000021CU  /* Interrupt Type Register, RW */
-#define XGPIOPS_INTPOL_OFFSET	 0x00000220U  /* Interrupt Polarity Register, RW */
-#define XGPIOPS_INTANY_OFFSET	 0x00000224U  /* Interrupt On Any Register, RW */
+#define XGPIOPS_DATA_OFFSET     0x00000040U  /* Data Register, RW */
+#define XGPIOPS_DATA_RO_OFFSET     0x00000060U  /* Data Register - Input, RO */
+#define XGPIOPS_DIRM_OFFSET     0x00000204U  /* Direction Mode Register, RW */
+#define XGPIOPS_OUTEN_OFFSET     0x00000208U  /* Output Enable Register, RW */
+#define XGPIOPS_INTMASK_OFFSET     0x0000020CU  /* Interrupt Mask Register, RO */
+#define XGPIOPS_INTEN_OFFSET     0x00000210U  /* Interrupt Enable Register, WO */
+#define XGPIOPS_INTDIS_OFFSET     0x00000214U  /* Interrupt Disable Register, WO*/
+#define XGPIOPS_INTSTS_OFFSET     0x00000218U  /* Interrupt Status Register, RO */
+#define XGPIOPS_INTTYPE_OFFSET     0x0000021CU  /* Interrupt Type Register, RW */
+#define XGPIOPS_INTPOL_OFFSET     0x00000220U  /* Interrupt Polarity Register, RW */
+#define XGPIOPS_INTANY_OFFSET     0x00000224U  /* Interrupt On Any Register, RW */
 /* @} */
 
 /** @name Register offsets for each Bank.
@@ -70,7 +70,7 @@ extern "C" {
 /* @} */
 
 /* For backwards compatibility */
-#define XGPIOPS_BYPM_MASK_OFFSET	(u32)0x40
+#define XGPIOPS_BYPM_MASK_OFFSET    (u32)0x40
 
 /** @name Interrupt type reset values for each bank
  *  @{
@@ -106,33 +106,33 @@ extern "C" {
 *
 * This macro reads the given register.
 *
-* @param	BaseAddr is the base address of the device.
-* @param	RegOffset is the register offset to be read.
+* @param    BaseAddr is the base address of the device.
+* @param    RegOffset is the register offset to be read.
 *
-* @return	The 32-bit value of the register
+* @return    The 32-bit value of the register
 *
-* @note		None.
+* @note        None.
 *
 *****************************************************************************/
-#define XGpioPs_ReadReg(BaseAddr, RegOffset)		\
-		Xil_In32((BaseAddr) + (u32)(RegOffset))
+#define XGpioPs_ReadReg(BaseAddr, RegOffset)        \
+        Xil_In32((BaseAddr) + (u32)(RegOffset))
 
 /****************************************************************************/
 /**
 *
 * This macro writes to the given register.
 *
-* @param	BaseAddr is the base address of the device.
-* @param	RegOffset is the offset of the register to be written.
-* @param	Data is the 32-bit value to write to the register.
+* @param    BaseAddr is the base address of the device.
+* @param    RegOffset is the offset of the register to be written.
+* @param    Data is the 32-bit value to write to the register.
 *
-* @return	None.
+* @return    None.
 *
-* @note		None.
+* @note        None.
 *
 *****************************************************************************/
-#define XGpioPs_WriteReg(BaseAddr, RegOffset, Data)	\
-		Xil_Out32((BaseAddr) + (u32)(RegOffset), (u32)(Data))
+#define XGpioPs_WriteReg(BaseAddr, RegOffset, Data)    \
+        Xil_Out32((BaseAddr) + (u32)(RegOffset), (u32)(Data))
 
 /************************** Function Prototypes ******************************/
 

文件差异内容过多而无法显示
+ 361 - 361
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_intr.c


+ 49 - 49
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_selftest.c

@@ -52,61 +52,61 @@
 * This function runs a self-test on the GPIO driver/device. This function
 * does a register read/write test on some of the Interrupt Registers.
 *
-* @param	InstancePtr is a pointer to the XGpioPs instance.
+* @param    InstancePtr is a pointer to the XGpioPs instance.
 *
 * @return
-*		- XST_SUCCESS if the self-test passed.
-* 		- XST_FAILURE otherwise.
+*        - XST_SUCCESS if the self-test passed.
+*         - XST_FAILURE otherwise.
 *
 *
 ******************************************************************************/
 s32 XGpioPs_SelfTest(const XGpioPs *InstancePtr)
 {
-	s32 Status = XST_SUCCESS;
-	u32 IntrEnabled;
-	u32 CurrentIntrType = 0U;
-	u32 CurrentIntrPolarity = 0U;
-	u32 CurrentIntrOnAny = 0U;
-	u32 IntrType = 0U;
-	u32 IntrPolarity = 0U;
-	u32 IntrOnAny = 0U;
-	u32 IntrTestValue = 0x22U;
-
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
-
-	/* Disable the Interrupts for Bank 0 . */
-	IntrEnabled = XGpioPs_IntrGetEnabled(InstancePtr, XGPIOPS_BANK0);
-	XGpioPs_IntrDisable(InstancePtr, XGPIOPS_BANK0, IntrEnabled);
-
-	/*
-	 * Get the Current Interrupt properties for Bank 0.
-	 * Set them to a known value, read it back and compare.
-	 */
-	XGpioPs_GetIntrType(InstancePtr, XGPIOPS_BANK0, &CurrentIntrType,
-			     &CurrentIntrPolarity, &CurrentIntrOnAny);
-
-	XGpioPs_SetIntrType(InstancePtr, XGPIOPS_BANK0, IntrTestValue,
-			     IntrTestValue, IntrTestValue);
-
-	XGpioPs_GetIntrType(InstancePtr, XGPIOPS_BANK0, &IntrType,
-			     &IntrPolarity, &IntrOnAny);
-
-	if ((IntrType != IntrTestValue) && (IntrPolarity != IntrTestValue) &&
-	    (IntrOnAny != IntrTestValue)) {
-
-		Status = XST_FAILURE;
-	}
-
-	/*
-	 * Restore the contents of all the interrupt registers modified in this
-	 * test.
-	 */
-	XGpioPs_SetIntrType(InstancePtr, XGPIOPS_BANK0, CurrentIntrType,
-			     CurrentIntrPolarity, CurrentIntrOnAny);
-
-	XGpioPs_IntrEnable(InstancePtr, XGPIOPS_BANK0, IntrEnabled);
-
-	return Status;
+    s32 Status = XST_SUCCESS;
+    u32 IntrEnabled;
+    u32 CurrentIntrType = 0U;
+    u32 CurrentIntrPolarity = 0U;
+    u32 CurrentIntrOnAny = 0U;
+    u32 IntrType = 0U;
+    u32 IntrPolarity = 0U;
+    u32 IntrOnAny = 0U;
+    u32 IntrTestValue = 0x22U;
+
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+    /* Disable the Interrupts for Bank 0 . */
+    IntrEnabled = XGpioPs_IntrGetEnabled(InstancePtr, XGPIOPS_BANK0);
+    XGpioPs_IntrDisable(InstancePtr, XGPIOPS_BANK0, IntrEnabled);
+
+    /*
+     * Get the Current Interrupt properties for Bank 0.
+     * Set them to a known value, read it back and compare.
+     */
+    XGpioPs_GetIntrType(InstancePtr, XGPIOPS_BANK0, &CurrentIntrType,
+                 &CurrentIntrPolarity, &CurrentIntrOnAny);
+
+    XGpioPs_SetIntrType(InstancePtr, XGPIOPS_BANK0, IntrTestValue,
+                 IntrTestValue, IntrTestValue);
+
+    XGpioPs_GetIntrType(InstancePtr, XGPIOPS_BANK0, &IntrType,
+                 &IntrPolarity, &IntrOnAny);
+
+    if ((IntrType != IntrTestValue) && (IntrPolarity != IntrTestValue) &&
+        (IntrOnAny != IntrTestValue)) {
+
+        Status = XST_FAILURE;
+    }
+
+    /*
+     * Restore the contents of all the interrupt registers modified in this
+     * test.
+     */
+    XGpioPs_SetIntrType(InstancePtr, XGPIOPS_BANK0, CurrentIntrType,
+                 CurrentIntrPolarity, CurrentIntrOnAny);
+
+    XGpioPs_IntrEnable(InstancePtr, XGPIOPS_BANK0, IntrEnabled);
+
+    return Status;
 }
 /** @} */

+ 14 - 14
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/gpiops_v3_7/xgpiops_sinit.c

@@ -13,7 +13,7 @@
 * This file contains the implementation of the XGpioPs driver's static
 * initialization functionality.
 *
-* @note		None.
+* @note        None.
 *
 * <pre>
 *
@@ -50,26 +50,26 @@ extern XGpioPs_Config XGpioPs_ConfigTable[XPAR_XGPIOPS_NUM_INSTANCES];
 * ID. The table XGpioPs_ConfigTable[] contains the configuration information
 * for each device in the system.
 *
-* @param	DeviceId is the unique device ID of the device being looked up.
+* @param    DeviceId is the unique device ID of the device being looked up.
 *
-* @return	A pointer to the configuration table entry corresponding to the
-*		given device ID, or NULL if no match is found.
+* @return    A pointer to the configuration table entry corresponding to the
+*        given device ID, or NULL if no match is found.
 *
-* @note		None.
+* @note        None.
 *
 ******************************************************************************/
 XGpioPs_Config *XGpioPs_LookupConfig(u16 DeviceId)
 {
-	XGpioPs_Config *CfgPtr = NULL;
-	u32 Index;
+    XGpioPs_Config *CfgPtr = NULL;
+    u32 Index;
 
-	for (Index = 0U; Index < (u32)XPAR_XGPIOPS_NUM_INSTANCES; Index++) {
-		if (XGpioPs_ConfigTable[Index].DeviceId == DeviceId) {
-			CfgPtr = &XGpioPs_ConfigTable[Index];
-			break;
-		}
-	}
+    for (Index = 0U; Index < (u32)XPAR_XGPIOPS_NUM_INSTANCES; Index++) {
+        if (XGpioPs_ConfigTable[Index].DeviceId == DeviceId) {
+            CfgPtr = &XGpioPs_ConfigTable[Index];
+            break;
+        }
+    }
 
-	return (XGpioPs_Config *)CfgPtr;
+    return (XGpioPs_Config *)CfgPtr;
 }
 /** @} */

+ 207 - 207
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps.c

@@ -24,14 +24,14 @@
 * 2.2   hk     07/28/14 Make changes to enable use of data cache.
 * 2.3   sk     09/23/14 Send command for relative card address
 *                       when re-initialization is done.CR# 819614.
-*						Use XSdPs_Change_ClkFreq API whenever changing
-*						clock.CR# 816586.
-* 2.4	sk	   12/04/14 Added support for micro SD without
-* 						WP/CD. CR# 810655.
-*						Checked for DAT Inhibit mask instead of CMD
-* 						Inhibit mask in Cmd Transfer API.
-*						Added Support for SD Card v1.0
-* 2.5 	sg	   07/09/15 Added SD 3.0 features
+*                        Use XSdPs_Change_ClkFreq API whenever changing
+*                        clock.CR# 816586.
+* 2.4    sk       12/04/14 Added support for micro SD without
+*                         WP/CD. CR# 810655.
+*                        Checked for DAT Inhibit mask instead of CMD
+*                         Inhibit mask in Cmd Transfer API.
+*                        Added Support for SD Card v1.0
+* 2.5     sg       07/09/15 Added SD 3.0 features
 *       kvn    07/15/15 Modified the code according to MISRAC-2012.
 * 2.6   sk     10/12/15 Added support for SD card v1.0 CR# 840601.
 * 2.7   sk     11/24/15 Considered the slot type befoe checking CD/WP pins.
@@ -102,96 +102,96 @@
 * Initializes a specific XSdPs instance such that the driver is ready to use.
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
-* @param	ConfigPtr is a reference to a structure containing information
-*		about a specific SD device. This function initializes an
-*		InstancePtr object for a specific device specified by the
-*		contents of Config.
-* @param	EffectiveAddr is the device base address in the virtual memory
-*		address space. The caller is responsible for keeping the address
-*		mapping from EffectiveAddr to the device physical base address
-*		unchanged once this function is invoked. Unexpected errors may
-*		occur if the address mapping changes after this function is
-*		called. If address translation is not used, use
-*		ConfigPtr->Config.BaseAddress for this device.
+* @param    InstancePtr is a pointer to the XSdPs instance.
+* @param    ConfigPtr is a reference to a structure containing information
+*        about a specific SD device. This function initializes an
+*        InstancePtr object for a specific device specified by the
+*        contents of Config.
+* @param    EffectiveAddr is the device base address in the virtual memory
+*        address space. The caller is responsible for keeping the address
+*        mapping from EffectiveAddr to the device physical base address
+*        unchanged once this function is invoked. Unexpected errors may
+*        occur if the address mapping changes after this function is
+*        called. If address translation is not used, use
+*        ConfigPtr->Config.BaseAddress for this device.
 *
 * @return
-*		- XST_SUCCESS if successful.
-*		- XST_DEVICE_IS_STARTED if the device is already started.
-*		It must be stopped to re-initialize.
+*        - XST_SUCCESS if successful.
+*        - XST_DEVICE_IS_STARTED if the device is already started.
+*        It must be stopped to re-initialize.
 *
-* @note		This function initializes the host controller.
-*		Initial clock of 400KHz is set.
-*		Voltage of 3.3V is selected as that is supported by host.
-*		Interrupts status is enabled and signal disabled by default.
-*		Default data direction is card to host and
-*		32 bit ADMA2 is selected. Default Block size is 512 bytes.
+* @note        This function initializes the host controller.
+*        Initial clock of 400KHz is set.
+*        Voltage of 3.3V is selected as that is supported by host.
+*        Interrupts status is enabled and signal disabled by default.
+*        Default data direction is card to host and
+*        32 bit ADMA2 is selected. Default Block size is 512 bytes.
 *
 ******************************************************************************/
 s32 XSdPs_CfgInitialize(XSdPs *InstancePtr, XSdPs_Config *ConfigPtr,
-				u32 EffectiveAddr)
+                u32 EffectiveAddr)
 {
-	s32 Status;
+    s32 Status;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(ConfigPtr != NULL);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(ConfigPtr != NULL);
 
 #if defined  (XCLOCKING)
-	InstancePtr->Config.RefClk = ConfigPtr->RefClk;
-	Xil_ClockEnable(InstancePtr->Config.RefClk);
+    InstancePtr->Config.RefClk = ConfigPtr->RefClk;
+    Xil_ClockEnable(InstancePtr->Config.RefClk);
 #endif
-	/* If this API is getting called twice, return value accordingly */
-	if (InstancePtr->IsReady == XIL_COMPONENT_IS_READY) {
-		Status = (s32)XST_DEVICE_IS_STARTED;
-		goto RETURN_PATH ;
-	}
-
-	/* Set some default values. */
-	InstancePtr->Config.DeviceId = ConfigPtr->DeviceId;
-	InstancePtr->Config.BaseAddress = EffectiveAddr;
-	InstancePtr->Config.InputClockHz = ConfigPtr->InputClockHz;
-	InstancePtr->Config.CardDetect =  ConfigPtr->CardDetect;
-	InstancePtr->Config.WriteProtect =  ConfigPtr->WriteProtect;
-	InstancePtr->Config.BusWidth = ConfigPtr->BusWidth;
-	InstancePtr->Config.BankNumber = ConfigPtr->BankNumber;
-	InstancePtr->Config.HasEMIO = ConfigPtr->HasEMIO;
-	InstancePtr->Config.IsCacheCoherent = ConfigPtr->IsCacheCoherent;
-	InstancePtr->SectorCount = 0U;
-	InstancePtr->Mode = XSDPS_DEFAULT_SPEED_MODE;
-	InstancePtr->OTapDelay = 0U;
-	InstancePtr->ITapDelay = 0U;
-	InstancePtr->Dma64BitAddr = 0U;
-	InstancePtr->SlcrBaseAddr = XPS_SYS_CTRL_BASEADDR;
-
-	/* Host Controller version is read. */
-	InstancePtr->HC_Version =
-			(u8)(XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-			XSDPS_HOST_CTRL_VER_OFFSET) & XSDPS_HC_SPEC_VER_MASK);
-
-	/*
-	 * Read capabilities register and update it in Instance pointer.
-	 * It is sufficient to read this once on power on.
-	 */
-	InstancePtr->Host_Caps = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
-						XSDPS_CAPS_OFFSET);
-
-	/* Reset the SD bus lines */
-	Status = XSdPs_ResetConfig(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH ;
-	}
-
-	/* Configure the SD Host Controller */
-	XSdPs_HostConfig(InstancePtr);
-
-	InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
+    /* If this API is getting called twice, return value accordingly */
+    if (InstancePtr->IsReady == XIL_COMPONENT_IS_READY) {
+        Status = (s32)XST_DEVICE_IS_STARTED;
+        goto RETURN_PATH ;
+    }
+
+    /* Set some default values. */
+    InstancePtr->Config.DeviceId = ConfigPtr->DeviceId;
+    InstancePtr->Config.BaseAddress = EffectiveAddr;
+    InstancePtr->Config.InputClockHz = ConfigPtr->InputClockHz;
+    InstancePtr->Config.CardDetect =  ConfigPtr->CardDetect;
+    InstancePtr->Config.WriteProtect =  ConfigPtr->WriteProtect;
+    InstancePtr->Config.BusWidth = ConfigPtr->BusWidth;
+    InstancePtr->Config.BankNumber = ConfigPtr->BankNumber;
+    InstancePtr->Config.HasEMIO = ConfigPtr->HasEMIO;
+    InstancePtr->Config.IsCacheCoherent = ConfigPtr->IsCacheCoherent;
+    InstancePtr->SectorCount = 0U;
+    InstancePtr->Mode = XSDPS_DEFAULT_SPEED_MODE;
+    InstancePtr->OTapDelay = 0U;
+    InstancePtr->ITapDelay = 0U;
+    InstancePtr->Dma64BitAddr = 0U;
+    InstancePtr->SlcrBaseAddr = XPS_SYS_CTRL_BASEADDR;
+
+    /* Host Controller version is read. */
+    InstancePtr->HC_Version =
+            (u8)(XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+            XSDPS_HOST_CTRL_VER_OFFSET) & XSDPS_HC_SPEC_VER_MASK);
+
+    /*
+     * Read capabilities register and update it in Instance pointer.
+     * It is sufficient to read this once on power on.
+     */
+    InstancePtr->Host_Caps = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                        XSDPS_CAPS_OFFSET);
+
+    /* Reset the SD bus lines */
+    Status = XSdPs_ResetConfig(InstancePtr);
+    if (Status != XST_SUCCESS) {
+        Status = XST_FAILURE;
+        goto RETURN_PATH ;
+    }
+
+    /* Configure the SD Host Controller */
+    XSdPs_HostConfig(InstancePtr);
+
+    InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
 
 RETURN_PATH:
 #if defined  (XCLOCKING)
-	Xil_ClockDisable(InstancePtr->Config.RefClk);
+    Xil_ClockDisable(InstancePtr->Config.RefClk);
 #endif
-	return Status;
+    return Status;
 
 }
 
@@ -202,69 +202,69 @@ RETURN_PATH:
 * Initialize Card with Identification mode sequence
 *
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
+* @param    InstancePtr is a pointer to the instance to be worked on.
 *
 * @return
-* 		- XST_SUCCESS if initialization was successful
-* 		- XST_FAILURE if failure - could be because
-* 			a) SD is already initialized
-* 			b) There is no card inserted
-* 			c) One of the steps (commands) in the
-*			   initialization cycle failed
+*         - XST_SUCCESS if initialization was successful
+*         - XST_FAILURE if failure - could be because
+*             a) SD is already initialized
+*             b) There is no card inserted
+*             c) One of the steps (commands) in the
+*               initialization cycle failed
 *
 *
 ******************************************************************************/
 s32 XSdPs_CardInitialize(XSdPs *InstancePtr)
 {
-	s32 Status;
+    s32 Status;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
-	/* Default settings */
-	InstancePtr->BusWidth = XSDPS_1_BIT_WIDTH;
-	InstancePtr->CardType = XSDPS_CARD_SD;
-	InstancePtr->Switch1v8 = 0U;
-	InstancePtr->BusSpeed = XSDPS_CLK_400_KHZ;
+    /* Default settings */
+    InstancePtr->BusWidth = XSDPS_1_BIT_WIDTH;
+    InstancePtr->CardType = XSDPS_CARD_SD;
+    InstancePtr->Switch1v8 = 0U;
+    InstancePtr->BusSpeed = XSDPS_CLK_400_KHZ;
 
 #if defined  (XCLOCKING)
-	Xil_ClockEnable(InstancePtr->Config.RefClk);
+    Xil_ClockEnable(InstancePtr->Config.RefClk);
 #endif
 
-	/* Change the clock frequency to 400 KHz */
-	Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH ;
-	}
-
-	/* Identify the Card whether it is SD, MMC or eMMC */
-	Status = XSdPs_IdentifyCard(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
-	}
-
-	/* Initialize the identified card */
-	if (InstancePtr->CardType == XSDPS_CARD_SD) {
-		Status = XSdPs_SdCardInitialize(InstancePtr);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
-		}
-	} else {
-		Status = XSdPs_MmcCardInitialize(InstancePtr);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
-		}
-	}
+    /* Change the clock frequency to 400 KHz */
+    Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
+    if (Status != XST_SUCCESS) {
+        Status = XST_FAILURE;
+        goto RETURN_PATH ;
+    }
+
+    /* Identify the Card whether it is SD, MMC or eMMC */
+    Status = XSdPs_IdentifyCard(InstancePtr);
+    if (Status != XST_SUCCESS) {
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
+
+    /* Initialize the identified card */
+    if (InstancePtr->CardType == XSDPS_CARD_SD) {
+        Status = XSdPs_SdCardInitialize(InstancePtr);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    } else {
+        Status = XSdPs_MmcCardInitialize(InstancePtr);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    }
 
 RETURN_PATH:
 #if defined  (XCLOCKING)
-	Xil_ClockDisable(InstancePtr->Config.RefClk);
+    Xil_ClockDisable(InstancePtr->Config.RefClk);
 #endif
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -272,48 +272,48 @@ RETURN_PATH:
 * @brief
 * This function performs SD read in polled mode.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
-* @param	Arg is the address passed by the user that is to be sent as
-* 		argument along with the command.
-* @param	BlkCnt - Block count passed by the user.
-* @param	Buff - Pointer to the data buffer for a DMA transfer.
+* @param    InstancePtr is a pointer to the instance to be worked on.
+* @param    Arg is the address passed by the user that is to be sent as
+*         argument along with the command.
+* @param    BlkCnt - Block count passed by the user.
+* @param    Buff - Pointer to the data buffer for a DMA transfer.
 *
 * @return
-* 		- XST_SUCCESS if initialization was successful
-* 		- XST_FAILURE if failure - could be because another transfer
-* 		is in progress or command or data inhibit is set
+*         - XST_SUCCESS if initialization was successful
+*         - XST_FAILURE if failure - could be because another transfer
+*         is in progress or command or data inhibit is set
 *
 ******************************************************************************/
 s32 XSdPs_ReadPolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff)
 {
-	s32 Status;
+    s32 Status;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
 #if defined  (XCLOCKING)
-	Xil_ClockEnable(InstancePtr->Config.RefClk);
+    Xil_ClockEnable(InstancePtr->Config.RefClk);
 #endif
 
-	/* Setup the Read Transfer */
-	Status = XSdPs_SetupTransfer(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
-	}
+    /* Setup the Read Transfer */
+    Status = XSdPs_SetupTransfer(InstancePtr);
+    if (Status != XST_SUCCESS) {
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Read from the card */
-	Status = XSdPs_Read(InstancePtr, Arg, BlkCnt, Buff);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
-	}
+    /* Read from the card */
+    Status = XSdPs_Read(InstancePtr, Arg, BlkCnt, Buff);
+    if (Status != XST_SUCCESS) {
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
 RETURN_PATH:
 #if defined  (XCLOCKING)
-	Xil_ClockDisable(InstancePtr->Config.RefClk);
+    Xil_ClockDisable(InstancePtr->Config.RefClk);
 #endif
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -321,48 +321,48 @@ RETURN_PATH:
 * @brief
 * This function performs SD write in polled mode.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
-* @param	Arg is the address passed by the user that is to be sent as
-* 		argument along with the command.
-* @param	BlkCnt - Block count passed by the user.
-* @param	Buff - Pointer to the data buffer for a DMA transfer.
+* @param    InstancePtr is a pointer to the instance to be worked on.
+* @param    Arg is the address passed by the user that is to be sent as
+*         argument along with the command.
+* @param    BlkCnt - Block count passed by the user.
+* @param    Buff - Pointer to the data buffer for a DMA transfer.
 *
 * @return
-* 		- XST_SUCCESS if initialization was successful
-* 		- XST_FAILURE if failure - could be because another transfer
-* 		is in progress or command or data inhibit is set
+*         - XST_SUCCESS if initialization was successful
+*         - XST_FAILURE if failure - could be because another transfer
+*         is in progress or command or data inhibit is set
 *
 ******************************************************************************/
 s32 XSdPs_WritePolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff)
 {
-	s32 Status;
+    s32 Status;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
 #if defined  (XCLOCKING)
-	Xil_ClockEnable(InstancePtr->Config.RefClk);
+    Xil_ClockEnable(InstancePtr->Config.RefClk);
 #endif
 
-	/* Setup the Write Transfer */
-	Status = XSdPs_SetupTransfer(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
-	}
+    /* Setup the Write Transfer */
+    Status = XSdPs_SetupTransfer(InstancePtr);
+    if (Status != XST_SUCCESS) {
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Write to the card */
-	Status = XSdPs_Write(InstancePtr, Arg, BlkCnt, Buff);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
-	}
+    /* Write to the card */
+    Status = XSdPs_Write(InstancePtr, Arg, BlkCnt, Buff);
+    if (Status != XST_SUCCESS) {
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
 RETURN_PATH:
 #if defined  (XCLOCKING)
-	Xil_ClockDisable(InstancePtr->Config.RefClk);
+    Xil_ClockDisable(InstancePtr->Config.RefClk);
 #endif
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -372,49 +372,49 @@ RETURN_PATH:
 * API to idle the SDIO Interface
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
+* @param    InstancePtr is a pointer to the XSdPs instance.
 *
-* @return	None
+* @return    None
 *
-* @note		None.
+* @note        None.
 *
 ******************************************************************************/
 s32 XSdPs_Idle(XSdPs *InstancePtr)
 {
-	s32 Status;
+    s32 Status;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
 #if defined  (XCLOCKING)
-	Xil_ClockEnable(InstancePtr->Config.RefClk);
+    Xil_ClockEnable(InstancePtr->Config.RefClk);
 #endif
 
-	/* Check if the bus is idle */
-	Status = XSdPs_CheckBusIdle(InstancePtr, XSDPS_PSR_INHIBIT_CMD_MASK
-										| XSDPS_PSR_INHIBIT_DAT_MASK
-										| XSDPS_PSR_DAT_ACTIVE_MASK);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH ;
-	}
+    /* Check if the bus is idle */
+    Status = XSdPs_CheckBusIdle(InstancePtr, XSDPS_PSR_INHIBIT_CMD_MASK
+                                        | XSDPS_PSR_INHIBIT_DAT_MASK
+                                        | XSDPS_PSR_DAT_ACTIVE_MASK);
+    if (Status != XST_SUCCESS) {
+        Status = XST_FAILURE;
+        goto RETURN_PATH ;
+    }
 
-	/* Disable the Bus Power */
-	XSdPs_DisableBusPower(InstancePtr);
+    /* Disable the Bus Power */
+    XSdPs_DisableBusPower(InstancePtr);
 
-	/* Reset Command and Data Lines */
-	Status = XSdPs_Reset(InstancePtr, XSDPS_SWRST_ALL_MASK);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH ;
-	}
+    /* Reset Command and Data Lines */
+    Status = XSdPs_Reset(InstancePtr, XSDPS_SWRST_ALL_MASK);
+    if (Status != XST_SUCCESS) {
+        Status = XST_FAILURE;
+        goto RETURN_PATH ;
+    }
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
 RETURN_PATH:
 #if defined  (XCLOCKING)
-	Xil_ClockDisable(InstancePtr->Config.RefClk);
+    Xil_ClockDisable(InstancePtr->Config.RefClk);
 #endif
-	return Status;
+    return Status;
 }
 /** @} */

+ 80 - 80
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps.h

@@ -83,14 +83,14 @@
 * 2.2   hk     07/28/14 Make changes to enable use of data cache.
 * 2.3   sk     09/23/14 Send command for relative card address
 *                       when re-initialization is done.CR# 819614.
-*						Use XSdPs_Change_ClkFreq API whenever changing
-*						clock.CR# 816586.
-* 2.4	sk	   12/04/14 Added support for micro SD without
-* 						WP/CD. CR# 810655.
-*						Checked for DAT Inhibit mask instead of CMD
-* 						Inhibit mask in Cmd Transfer API.
-*						Added Support for SD Card v1.0
-* 2.5 	sg		07/09/15 Added SD 3.0 features
+*                        Use XSdPs_Change_ClkFreq API whenever changing
+*                        clock.CR# 816586.
+* 2.4    sk       12/04/14 Added support for micro SD without
+*                         WP/CD. CR# 810655.
+*                        Checked for DAT Inhibit mask instead of CMD
+*                         Inhibit mask in Cmd Transfer API.
+*                        Added Support for SD Card v1.0
+* 2.5     sg        07/09/15 Added SD 3.0 features
 *       kvn     07/15/15 Modified the code according to MISRAC-2012.
 * 2.6   sk     10/12/15 Added support for SD card v1.0 CR# 840601.
 * 2.7   sk     11/24/15 Considered the slot type befoe checking CD/WP pins.
@@ -119,7 +119,7 @@
 *       vns    02/09/17 Added ARMA53_32 support for ZynqMP CR#968397
 *       sk     03/20/17 Add support for EL1 non-secure mode.
 * 3.3   mn     05/17/17 Add support for 64bit DMA addressing
-* 	mn     08/07/17 Modify driver to support 64-bit DMA in arm64 only
+*     mn     08/07/17 Modify driver to support 64-bit DMA in arm64 only
 *       mn     08/17/17 Enabled CCI support for A53 by adding cache coherency
 *                       information.
 *       mn     09/06/17 Resolved compilation errors with IAR toolchain
@@ -155,38 +155,38 @@ extern "C" {
 
 /************************** Constant Definitions *****************************/
 
-#define XSDPS_CT_ERROR	0x2L	/**< Command timeout flag */
-#define MAX_TUNING_COUNT	40U		/**< Maximum Tuning count */
-#define MAX_TIMEOUT		0x1FFFFFFFU		/**< Maximum Timeout */
-#define XSDPS_CMD8_VOL_PATTERN	0x1AAU
-#define XSDPS_RESPOCR_READY	0x80000000U
-#define XSDPS_ACMD41_HCS	0x40000000U
-#define XSDPS_ACMD41_3V3	0x00300000U
-#define XSDPS_CMD1_HIGH_VOL	0x00FF8000U
-#define XSDPS_CMD1_DUAL_VOL	0x00FF8010U
-#define HIGH_SPEED_SUPPORT	0x2U
-#define UHS_SDR12_SUPPORT	0x1U
-#define UHS_SDR25_SUPPORT	0x2U
-#define UHS_SDR50_SUPPORT	0x4U
-#define UHS_SDR104_SUPPORT	0x8U
-#define UHS_DDR50_SUPPORT	0x10U
-#define WIDTH_4_BIT_SUPPORT	0x4U
-#define SD_CLK_25_MHZ		25000000U
-#define SD_CLK_19_MHZ		19000000U
-#define SD_CLK_26_MHZ		26000000U
-#define EXT_CSD_DEVICE_TYPE_BYTE	196U
-#define EXT_CSD_SEC_COUNT_BYTE1		212U
-#define EXT_CSD_SEC_COUNT_BYTE2		213U
-#define EXT_CSD_SEC_COUNT_BYTE3		214U
-#define EXT_CSD_SEC_COUNT_BYTE4		215U
-#define EXT_CSD_DEVICE_TYPE_HIGH_SPEED			0x2U
-#define EXT_CSD_DEVICE_TYPE_DDR_1V8_HIGH_SPEED	0x4U
-#define EXT_CSD_DEVICE_TYPE_DDR_1V2_HIGH_SPEED	0x8U
-#define EXT_CSD_DEVICE_TYPE_SDR_1V8_HS200		0x10U
-#define EXT_CSD_DEVICE_TYPE_SDR_1V2_HS200		0x20U
-#define CSD_SPEC_VER_3		0x3U
-#define SCR_SPEC_VER_3		0x80U
-#define ADDRESS_BEYOND_32BIT	0x100000000U
+#define XSDPS_CT_ERROR    0x2L    /**< Command timeout flag */
+#define MAX_TUNING_COUNT    40U        /**< Maximum Tuning count */
+#define MAX_TIMEOUT        0x1FFFFFFFU        /**< Maximum Timeout */
+#define XSDPS_CMD8_VOL_PATTERN    0x1AAU
+#define XSDPS_RESPOCR_READY    0x80000000U
+#define XSDPS_ACMD41_HCS    0x40000000U
+#define XSDPS_ACMD41_3V3    0x00300000U
+#define XSDPS_CMD1_HIGH_VOL    0x00FF8000U
+#define XSDPS_CMD1_DUAL_VOL    0x00FF8010U
+#define HIGH_SPEED_SUPPORT    0x2U
+#define UHS_SDR12_SUPPORT    0x1U
+#define UHS_SDR25_SUPPORT    0x2U
+#define UHS_SDR50_SUPPORT    0x4U
+#define UHS_SDR104_SUPPORT    0x8U
+#define UHS_DDR50_SUPPORT    0x10U
+#define WIDTH_4_BIT_SUPPORT    0x4U
+#define SD_CLK_25_MHZ        25000000U
+#define SD_CLK_19_MHZ        19000000U
+#define SD_CLK_26_MHZ        26000000U
+#define EXT_CSD_DEVICE_TYPE_BYTE    196U
+#define EXT_CSD_SEC_COUNT_BYTE1        212U
+#define EXT_CSD_SEC_COUNT_BYTE2        213U
+#define EXT_CSD_SEC_COUNT_BYTE3        214U
+#define EXT_CSD_SEC_COUNT_BYTE4        215U
+#define EXT_CSD_DEVICE_TYPE_HIGH_SPEED            0x2U
+#define EXT_CSD_DEVICE_TYPE_DDR_1V8_HIGH_SPEED    0x4U
+#define EXT_CSD_DEVICE_TYPE_DDR_1V2_HIGH_SPEED    0x8U
+#define EXT_CSD_DEVICE_TYPE_SDR_1V8_HS200        0x10U
+#define EXT_CSD_DEVICE_TYPE_SDR_1V2_HS200        0x20U
+#define CSD_SPEC_VER_3        0x3U
+#define SCR_SPEC_VER_3        0x80U
+#define ADDRESS_BEYOND_32BIT    0x100000000U
 
 /**************************** Type Definitions *******************************/
 
@@ -196,25 +196,25 @@ typedef void (*XSdPs_ConfigTap) (u32 Bank, u32 DeviceId, u32 CardType);
  * This typedef contains configuration information for the device.
  */
 typedef struct {
-	u16 DeviceId;			/**< Unique ID  of device */
-	u32 BaseAddress;		/**< Base address of the device */
-	u32 InputClockHz;		/**< Input clock frequency */
-	u32 CardDetect;			/**< Card Detect */
-	u32 WriteProtect;			/**< Write Protect */
-	u32 BusWidth;			/**< Bus Width */
-	u32 BankNumber;			/**< MIO Bank selection for SD */
-	u32 HasEMIO;			/**< If SD is connected to EMIO */
-	u8 IsCacheCoherent; 		/**< If SD is Cache Coherent or not */
+    u16 DeviceId;            /**< Unique ID  of device */
+    u32 BaseAddress;        /**< Base address of the device */
+    u32 InputClockHz;        /**< Input clock frequency */
+    u32 CardDetect;            /**< Card Detect */
+    u32 WriteProtect;            /**< Write Protect */
+    u32 BusWidth;            /**< Bus Width */
+    u32 BankNumber;            /**< MIO Bank selection for SD */
+    u32 HasEMIO;            /**< If SD is connected to EMIO */
+    u8 IsCacheCoherent;         /**< If SD is Cache Coherent or not */
 #if defined  (XCLOCKING)
-	u32 RefClk;			/**< Input clocks */
+    u32 RefClk;            /**< Input clocks */
 #endif
 } XSdPs_Config;
 
 /* ADMA2 32-Bit descriptor table */
 typedef struct {
-	u16 Attribute;		/**< Attributes of descriptor */
-	u16 Length;		/**< Length of current dma transfer */
-	u32 Address;		/**< Address of current dma transfer */
+    u16 Attribute;        /**< Attributes of descriptor */
+    u16 Length;        /**< Length of current dma transfer */
+    u32 Address;        /**< Address of current dma transfer */
 #ifdef __ICCARM__
 #pragma data_alignment = 32
 } XSdPs_Adma2Descriptor32;
@@ -224,9 +224,9 @@ typedef struct {
 
 /* ADMA2 64-Bit descriptor table */
 typedef struct {
-	u16 Attribute;		/**< Attributes of descriptor */
-	u16 Length;		/**< Length of current dma transfer */
-	u64 Address;		/**< Address of current dma transfer */
+    u16 Attribute;        /**< Attributes of descriptor */
+    u16 Length;        /**< Length of current dma transfer */
+    u64 Address;        /**< Address of current dma transfer */
 #ifdef __ICCARM__
 #pragma data_alignment = 32
 } XSdPs_Adma2Descriptor64;
@@ -240,28 +240,28 @@ typedef struct {
  * to a variable of this type is then passed to the driver API functions.
  */
 typedef struct {
-	XSdPs_Config Config;	/**< Configuration structure */
-	u32 IsReady;		/**< Device is initialized and ready */
-	u32 Host_Caps;		/**< Capabilities of host controller */
-	u32 Host_CapsExt;	/**< Extended Capabilities */
-	u32 HCS;		/**< High capacity support in card */
-	u8  CardType;		/**< Type of card - SD/MMC/eMMC */
-	u8  Card_Version;	/**< Card version */
-	u8  HC_Version;		/**< Host controller version */
-	u8  BusWidth;		/**< Current operating bus width */
-	u32 BusSpeed;		/**< Current operating bus speed */
-	u8  Switch1v8;		/**< 1.8V Switch support */
-	u32 CardID[4];		/**< Card ID Register */
-	u32 RelCardAddr;	/**< Relative Card Address */
-	u32 CardSpecData[4];	/**< Card Specific Data Register */
-	u32 SectorCount;		/**< Sector Count */
-	u32 SdCardConfig;	/**< Sd Card Configuration Register */
-	u32 Mode;			/**< Bus Speed Mode */
-	u32 OTapDelay;		/**< Output Tap Delay */
-	u32 ITapDelay;		/**< Input Tap Delay */
-	u64 Dma64BitAddr;	/**< 64 Bit DMA Address */
-	u16 TransferMode;	/**< Transfer Mode */
-	u32 SlcrBaseAddr;	/**< SLCR base address*/
+    XSdPs_Config Config;    /**< Configuration structure */
+    u32 IsReady;        /**< Device is initialized and ready */
+    u32 Host_Caps;        /**< Capabilities of host controller */
+    u32 Host_CapsExt;    /**< Extended Capabilities */
+    u32 HCS;        /**< High capacity support in card */
+    u8  CardType;        /**< Type of card - SD/MMC/eMMC */
+    u8  Card_Version;    /**< Card version */
+    u8  HC_Version;        /**< Host controller version */
+    u8  BusWidth;        /**< Current operating bus width */
+    u32 BusSpeed;        /**< Current operating bus speed */
+    u8  Switch1v8;        /**< 1.8V Switch support */
+    u32 CardID[4];        /**< Card ID Register */
+    u32 RelCardAddr;    /**< Relative Card Address */
+    u32 CardSpecData[4];    /**< Card Specific Data Register */
+    u32 SectorCount;        /**< Sector Count */
+    u32 SdCardConfig;    /**< Sd Card Configuration Register */
+    u32 Mode;            /**< Bus Speed Mode */
+    u32 OTapDelay;        /**< Output Tap Delay */
+    u32 ITapDelay;        /**< Input Tap Delay */
+    u64 Dma64BitAddr;    /**< 64 Bit DMA Address */
+    u16 TransferMode;    /**< Transfer Mode */
+    u32 SlcrBaseAddr;    /**< SLCR base address*/
 } XSdPs;
 
 /***************** Macros (Inline Functions) Definitions *********************/
@@ -269,7 +269,7 @@ typedef struct {
 /************************** Function Prototypes ******************************/
 XSdPs_Config *XSdPs_LookupConfig(u16 DeviceId);
 s32 XSdPs_CfgInitialize(XSdPs *InstancePtr, XSdPs_Config *ConfigPtr,
-				u32 EffectiveAddr);
+                u32 EffectiveAddr);
 s32 XSdPs_CardInitialize(XSdPs *InstancePtr);
 s32 XSdPs_ReadPolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff);
 s32 XSdPs_WritePolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff);

文件差异内容过多而无法显示
+ 438 - 438
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_card.c


+ 24 - 24
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_g.c

@@ -6,9 +6,9 @@
 * DO NOT EDIT.
 *
 * Copyright (C) 2010-2020 Xilinx, Inc. All Rights Reserved.
-* SPDX-License-Identifier: MIT 
+* SPDX-License-Identifier: MIT
 
-* 
+*
 * Description: Driver configuration
 *
 *******************************************************************/
@@ -22,28 +22,28 @@
 
 XSdPs_Config XSdPs_ConfigTable[XPAR_XSDPS_NUM_INSTANCES] =
 {
-	{
-		XPAR_PSU_SD_0_DEVICE_ID,
-		XPAR_PSU_SD_0_BASEADDR,
-		XPAR_PSU_SD_0_SDIO_CLK_FREQ_HZ,
-		XPAR_PSU_SD_0_HAS_CD,
-		XPAR_PSU_SD_0_HAS_WP,
-		XPAR_PSU_SD_0_BUS_WIDTH,
-		XPAR_PSU_SD_0_MIO_BANK,
-		XPAR_PSU_SD_0_HAS_EMIO,
-		XPAR_PSU_SD_0_IS_CACHE_COHERENT
-	},
-	{
-		XPAR_PSU_SD_1_DEVICE_ID,
-		XPAR_PSU_SD_1_BASEADDR,
-		XPAR_PSU_SD_1_SDIO_CLK_FREQ_HZ,
-		XPAR_PSU_SD_1_HAS_CD,
-		XPAR_PSU_SD_1_HAS_WP,
-		XPAR_PSU_SD_1_BUS_WIDTH,
-		XPAR_PSU_SD_1_MIO_BANK,
-		XPAR_PSU_SD_1_HAS_EMIO,
-		XPAR_PSU_SD_1_IS_CACHE_COHERENT
-	}
+    {
+        XPAR_PSU_SD_0_DEVICE_ID,
+        XPAR_PSU_SD_0_BASEADDR,
+        XPAR_PSU_SD_0_SDIO_CLK_FREQ_HZ,
+        XPAR_PSU_SD_0_HAS_CD,
+        XPAR_PSU_SD_0_HAS_WP,
+        XPAR_PSU_SD_0_BUS_WIDTH,
+        XPAR_PSU_SD_0_MIO_BANK,
+        XPAR_PSU_SD_0_HAS_EMIO,
+        XPAR_PSU_SD_0_IS_CACHE_COHERENT
+    },
+    {
+        XPAR_PSU_SD_1_DEVICE_ID,
+        XPAR_PSU_SD_1_BASEADDR,
+        XPAR_PSU_SD_1_SDIO_CLK_FREQ_HZ,
+        XPAR_PSU_SD_1_HAS_CD,
+        XPAR_PSU_SD_1_HAS_WP,
+        XPAR_PSU_SD_1_BUS_WIDTH,
+        XPAR_PSU_SD_1_MIO_BANK,
+        XPAR_PSU_SD_1_HAS_EMIO,
+        XPAR_PSU_SD_1_IS_CACHE_COHERENT
+    }
 };
 
 

文件差异内容过多而无法显示
+ 442 - 442
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_host.c


文件差异内容过多而无法显示
+ 525 - 525
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_hw.h


+ 401 - 401
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_options.c

@@ -22,8 +22,8 @@
 * 2.1   hk     04/18/14 Increase sleep for eMMC switch command.
 *                       Add sleep for microblaze designs. CR# 781117.
 * 2.3   sk     09/23/14 Use XSdPs_Change_ClkFreq API whenever changing
-*						clock.CR# 816586.
-* 2.5 	sg	   07/09/15 Added SD 3.0 features
+*                        clock.CR# 816586.
+* 2.5     sg       07/09/15 Added SD 3.0 features
 *       kvn    07/15/15 Modified the code according to MISRAC-2012.
 * 2.7   sk     01/08/16 Added workaround for issue in auto tuning mode
 *                       of SDR50, SDR104 and HS200.
@@ -43,8 +43,8 @@
 *       vns    03/13/17 Fixed MISRAC mandatory violation
 *       sk     03/20/17 Add support for EL1 non-secure mode.
 * 3.3   mn     07/25/17 Removed SD0_OTAPDLYENA and SD1_OTAPDLYENA bits
-*       mn     08/07/17	Properly set OTAPDLY value by clearing previous bit
-* 			settings
+*       mn     08/07/17    Properly set OTAPDLY value by clearing previous bit
+*             settings
 *       mn     08/17/17 Added CCI support for A53 and disabled data cache
 *                       operations when it is enabled.
 *       mn     08/22/17 Updated for Word Access System support
@@ -79,33 +79,33 @@
 * API to change clock freq to given value.
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
-* @param	SelFreq - Clock frequency in Hz.
+* @param    InstancePtr is a pointer to the XSdPs instance.
+* @param    SelFreq - Clock frequency in Hz.
 *
-* @return	None
+* @return    None
 *
-* @note		This API will change clock frequency to the value less than
-*		or equal to the given value using the permissible dividors.
+* @note        This API will change clock frequency to the value less than
+*        or equal to the given value using the permissible dividors.
 *
 ******************************************************************************/
 s32 XSdPs_Change_ClkFreq(XSdPs *InstancePtr, u32 SelFreq)
 {
-	s32 Status;
+    s32 Status;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
-	if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
-		/* Program the Tap delays */
-		XSdPs_SetTapDelay(InstancePtr);
-	}
+    if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
+        /* Program the Tap delays */
+        XSdPs_SetTapDelay(InstancePtr);
+    }
 
-	Status = XSdPs_SetClock(InstancePtr, SelFreq);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-	}
+    Status = XSdPs_SetClock(InstancePtr, SelFreq);
+    if (Status != XST_SUCCESS) {
+        Status = XST_FAILURE;
+    }
 
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -113,41 +113,41 @@ s32 XSdPs_Change_ClkFreq(XSdPs *InstancePtr, u32 SelFreq)
 * @brief
 * Update Block size for read/write operations.
 *
-* @param	InstancePtr is a pointer to the instance to be worked on.
-* @param	BlkSize - Block size passed by the user.
+* @param    InstancePtr is a pointer to the instance to be worked on.
+* @param    BlkSize - Block size passed by the user.
 *
-* @return	None
+* @return    None
 *
 ******************************************************************************/
 s32 XSdPs_SetBlkSize(XSdPs *InstancePtr, u16 BlkSize)
 {
-	s32 Status;
-
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
-
-	Status = XSdPs_CheckBusIdle(InstancePtr, (XSDPS_PSR_INHIBIT_CMD_MASK
-											| XSDPS_PSR_INHIBIT_DAT_MASK
-											| XSDPS_PSR_WR_ACTIVE_MASK
-											| XSDPS_PSR_RD_ACTIVE_MASK));
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH ;
-	}
-
-	/* Send block write command */
-	Status = XSdPs_CmdTransfer(InstancePtr, CMD16, BlkSize, 0U);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
-	}
-
-	/* Set block size to the value passed */
-	XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_BLK_SIZE_OFFSET,
-			 BlkSize & XSDPS_BLK_SIZE_MASK);
+    s32 Status;
+
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+    Status = XSdPs_CheckBusIdle(InstancePtr, (XSDPS_PSR_INHIBIT_CMD_MASK
+                                            | XSDPS_PSR_INHIBIT_DAT_MASK
+                                            | XSDPS_PSR_WR_ACTIVE_MASK
+                                            | XSDPS_PSR_RD_ACTIVE_MASK));
+    if (Status != XST_SUCCESS) {
+        Status = XST_FAILURE;
+        goto RETURN_PATH ;
+    }
+
+    /* Send block write command */
+    Status = XSdPs_CmdTransfer(InstancePtr, CMD16, BlkSize, 0U);
+    if (Status != XST_SUCCESS) {
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
+
+    /* Set block size to the value passed */
+    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_BLK_SIZE_OFFSET,
+             BlkSize & XSDPS_BLK_SIZE_MASK);
 
 RETURN_PATH:
-	return Status;
+    return Status;
 }
 
 /*****************************************************************************/
@@ -157,64 +157,64 @@ RETURN_PATH:
 * API to get bus width support by card.
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
-* @param	SCR - buffer to store SCR register returned by card.
+* @param    InstancePtr is a pointer to the XSdPs instance.
+* @param    SCR - buffer to store SCR register returned by card.
 *
 * @return
-*		- XST_SUCCESS if successful.
-*		- XST_FAILURE if fail.
+*        - XST_SUCCESS if successful.
+*        - XST_FAILURE if fail.
 *
-* @note		None.
+* @note        None.
 *
 ******************************************************************************/
 s32 XSdPs_Get_BusWidth(XSdPs *InstancePtr, u8 *ReadBuff)
 {
-	s32 Status;
-	u16 BlkCnt;
-	u16 BlkSize;
-	s32 LoopCnt;
+    s32 Status;
+    u16 BlkCnt;
+    u16 BlkSize;
+    s32 LoopCnt;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
-	for (LoopCnt = 0; LoopCnt < 8; LoopCnt++) {
-		ReadBuff[LoopCnt] = 0U;
-	}
+    for (LoopCnt = 0; LoopCnt < 8; LoopCnt++) {
+        ReadBuff[LoopCnt] = 0U;
+    }
 
-	/* Send block write command */
-	Status = XSdPs_CmdTransfer(InstancePtr, CMD55,
-			InstancePtr->RelCardAddr, 0U);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
-	}
+    /* Send block write command */
+    Status = XSdPs_CmdTransfer(InstancePtr, CMD55,
+            InstancePtr->RelCardAddr, 0U);
+    if (Status != XST_SUCCESS) {
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	BlkCnt = XSDPS_SCR_BLKCNT;
-	BlkSize = XSDPS_SCR_BLKSIZE;
+    BlkCnt = XSDPS_SCR_BLKCNT;
+    BlkSize = XSDPS_SCR_BLKSIZE;
 
-	XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, ReadBuff);
+    XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, ReadBuff);
 
-	Status = XSdPs_CmdTransfer(InstancePtr, ACMD51, 0U, BlkCnt);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
-	}
+    Status = XSdPs_CmdTransfer(InstancePtr, ACMD51, 0U, BlkCnt);
+    if (Status != XST_SUCCESS) {
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Check for transfer done */
-	Status = XSdps_CheckTransferDone(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-	}
+    /* Check for transfer done */
+    Status = XSdps_CheckTransferDone(InstancePtr);
+    if (Status != XST_SUCCESS) {
+        Status = XST_FAILURE;
+    }
 
-	if (InstancePtr->Config.IsCacheCoherent == 0U) {
-		Xil_DCacheInvalidateRange((INTPTR)ReadBuff,
-				(INTPTR)BlkCnt * BlkSize);
-	}
+    if (InstancePtr->Config.IsCacheCoherent == 0U) {
+        Xil_DCacheInvalidateRange((INTPTR)ReadBuff,
+                (INTPTR)BlkCnt * BlkSize);
+    }
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
-	RETURN_PATH:
-		return Status;
+    RETURN_PATH:
+        return Status;
 
 }
 
@@ -225,99 +225,99 @@ s32 XSdPs_Get_BusWidth(XSdPs *InstancePtr, u8 *ReadBuff)
 * API to set bus width to 4-bit in card and host
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
+* @param    InstancePtr is a pointer to the XSdPs instance.
 *
 * @return
-*		- XST_SUCCESS if successful.
-*		- XST_FAILURE if fail.
+*        - XST_SUCCESS if successful.
+*        - XST_FAILURE if fail.
 *
-* @note		None.
+* @note        None.
 *
 ******************************************************************************/
 s32 XSdPs_Change_BusWidth(XSdPs *InstancePtr)
 {
-	s32 Status;
-	u32 StatusReg;
-	u32 Arg;
-
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
-
-	/*
-	 * check for bus width for 3.0 controller and return if
-	 * bus width is <4
-	 */
-	if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) &&
-			(InstancePtr->Config.BusWidth < XSDPS_WIDTH_4)) {
-		Status = XST_SUCCESS;
-		goto RETURN_PATH;
-	}
-
-	if (InstancePtr->CardType == XSDPS_CARD_SD) {
-
-		Status = XSdPs_CmdTransfer(InstancePtr, CMD55, InstancePtr->RelCardAddr,
-				0U);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
-		}
-
-		Status = XSdPs_CmdTransfer(InstancePtr, ACMD6, (u32)InstancePtr->BusWidth, 0U);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
-		}
-	} else {
-		if (InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH) {
-			if (InstancePtr->Mode == XSDPS_DDR52_MODE) {
-				Arg = XSDPS_MMC_DDR_8_BIT_BUS_ARG;
-			} else {
-				Arg = XSDPS_MMC_8_BIT_BUS_ARG;
-			}
-		} else {
-			if (InstancePtr->Mode == XSDPS_DDR52_MODE) {
-				Arg = XSDPS_MMC_DDR_4_BIT_BUS_ARG;
-			} else {
-				Arg = XSDPS_MMC_4_BIT_BUS_ARG;
-			}
-		}
-
-		Status = XSdPs_Set_Mmc_ExtCsd(InstancePtr, Arg);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
-		}
-	}
-
-	usleep(XSDPS_MMC_DELAY_FOR_SWITCH);
-
-	StatusReg = XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
-					XSDPS_HOST_CTRL1_OFFSET);
-
-	/* Width setting in controller */
-	if (InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH) {
-		StatusReg |= XSDPS_HC_EXT_BUS_WIDTH;
-	} else {
-		StatusReg |= XSDPS_HC_WIDTH_MASK;
-	}
-
-	XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
-			XSDPS_HOST_CTRL1_OFFSET,
-			(u8)StatusReg);
-
-	if (InstancePtr->Mode == XSDPS_DDR52_MODE) {
-		StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
-					XSDPS_HOST_CTRL2_OFFSET);
-		StatusReg &= (u32)(~XSDPS_HC2_UHS_MODE_MASK);
-		StatusReg |= InstancePtr->Mode;
-		XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
-					XSDPS_HOST_CTRL2_OFFSET, (u16)StatusReg);
-	}
-
-	Status = XST_SUCCESS;
-
-	RETURN_PATH:
-		return Status;
+    s32 Status;
+    u32 StatusReg;
+    u32 Arg;
+
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+    /*
+     * check for bus width for 3.0 controller and return if
+     * bus width is <4
+     */
+    if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) &&
+            (InstancePtr->Config.BusWidth < XSDPS_WIDTH_4)) {
+        Status = XST_SUCCESS;
+        goto RETURN_PATH;
+    }
+
+    if (InstancePtr->CardType == XSDPS_CARD_SD) {
+
+        Status = XSdPs_CmdTransfer(InstancePtr, CMD55, InstancePtr->RelCardAddr,
+                0U);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+
+        Status = XSdPs_CmdTransfer(InstancePtr, ACMD6, (u32)InstancePtr->BusWidth, 0U);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    } else {
+        if (InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH) {
+            if (InstancePtr->Mode == XSDPS_DDR52_MODE) {
+                Arg = XSDPS_MMC_DDR_8_BIT_BUS_ARG;
+            } else {
+                Arg = XSDPS_MMC_8_BIT_BUS_ARG;
+            }
+        } else {
+            if (InstancePtr->Mode == XSDPS_DDR52_MODE) {
+                Arg = XSDPS_MMC_DDR_4_BIT_BUS_ARG;
+            } else {
+                Arg = XSDPS_MMC_4_BIT_BUS_ARG;
+            }
+        }
+
+        Status = XSdPs_Set_Mmc_ExtCsd(InstancePtr, Arg);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    }
+
+    usleep(XSDPS_MMC_DELAY_FOR_SWITCH);
+
+    StatusReg = XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
+                    XSDPS_HOST_CTRL1_OFFSET);
+
+    /* Width setting in controller */
+    if (InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH) {
+        StatusReg |= XSDPS_HC_EXT_BUS_WIDTH;
+    } else {
+        StatusReg |= XSDPS_HC_WIDTH_MASK;
+    }
+
+    XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
+            XSDPS_HOST_CTRL1_OFFSET,
+            (u8)StatusReg);
+
+    if (InstancePtr->Mode == XSDPS_DDR52_MODE) {
+        StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+                    XSDPS_HOST_CTRL2_OFFSET);
+        StatusReg &= (u32)(~XSDPS_HC2_UHS_MODE_MASK);
+        StatusReg |= InstancePtr->Mode;
+        XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                    XSDPS_HOST_CTRL2_OFFSET, (u16)StatusReg);
+    }
+
+    Status = XST_SUCCESS;
+
+    RETURN_PATH:
+        return Status;
 
 }
 
@@ -328,60 +328,60 @@ s32 XSdPs_Change_BusWidth(XSdPs *InstancePtr)
 * API to get bus speed supported by card.
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
-* @param	ReadBuff - buffer to store function group support data
-*		returned by card.
+* @param    InstancePtr is a pointer to the XSdPs instance.
+* @param    ReadBuff - buffer to store function group support data
+*        returned by card.
 *
 * @return
-*		- XST_SUCCESS if successful.
-*		- XST_FAILURE if fail.
+*        - XST_SUCCESS if successful.
+*        - XST_FAILURE if fail.
 *
-* @note		None.
+* @note        None.
 *
 ******************************************************************************/
 s32 XSdPs_Get_BusSpeed(XSdPs *InstancePtr, u8 *ReadBuff)
 {
-	s32 Status;
-	u32 Arg;
-	u16 BlkCnt;
-	u16 BlkSize;
-	s32 LoopCnt;
+    s32 Status;
+    u32 Arg;
+    u16 BlkCnt;
+    u16 BlkSize;
+    s32 LoopCnt;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
-	for (LoopCnt = 0; LoopCnt < 64; LoopCnt++) {
-		ReadBuff[LoopCnt] = 0U;
-	}
+    for (LoopCnt = 0; LoopCnt < 64; LoopCnt++) {
+        ReadBuff[LoopCnt] = 0U;
+    }
 
-	BlkCnt = XSDPS_SWITCH_CMD_BLKCNT;
-	BlkSize = XSDPS_SWITCH_CMD_BLKSIZE;
+    BlkCnt = XSDPS_SWITCH_CMD_BLKCNT;
+    BlkSize = XSDPS_SWITCH_CMD_BLKSIZE;
 
-	XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, ReadBuff);
+    XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, ReadBuff);
 
-	Arg = XSDPS_SWITCH_CMD_HS_GET;
+    Arg = XSDPS_SWITCH_CMD_HS_GET;
 
-	Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 1U);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
-	}
+    Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 1U);
+    if (Status != XST_SUCCESS) {
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Check for transfer done */
-	Status = XSdps_CheckTransferDone(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-	}
+    /* Check for transfer done */
+    Status = XSdps_CheckTransferDone(InstancePtr);
+    if (Status != XST_SUCCESS) {
+        Status = XST_FAILURE;
+    }
 
-	if (InstancePtr->Config.IsCacheCoherent == 0U) {
-		Xil_DCacheInvalidateRange((INTPTR)ReadBuff,
-				(INTPTR)BlkCnt * BlkSize);
-	}
+    if (InstancePtr->Config.IsCacheCoherent == 0U) {
+        Xil_DCacheInvalidateRange((INTPTR)ReadBuff,
+                (INTPTR)BlkCnt * BlkSize);
+    }
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
-	RETURN_PATH:
-		return Status;
+    RETURN_PATH:
+        return Status;
 
 }
 
@@ -392,59 +392,59 @@ s32 XSdPs_Get_BusSpeed(XSdPs *InstancePtr, u8 *ReadBuff)
 * API to get SD card status information.
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
-* @param	SdStatReg - buffer to store status data returned by card.
+* @param    InstancePtr is a pointer to the XSdPs instance.
+* @param    SdStatReg - buffer to store status data returned by card.
 *
 * @return
-*		- XST_SUCCESS if successful.
-*		- XST_FAILURE if fail.
+*        - XST_SUCCESS if successful.
+*        - XST_FAILURE if fail.
 *
-* @note		None.
+* @note        None.
 *
 ******************************************************************************/
 s32 XSdPs_Get_Status(XSdPs *InstancePtr, u8 *SdStatReg)
 {
-	s32 Status;
-	u16 BlkCnt;
-	u16 BlkSize;
-
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
-
-	/* Send block write command */
-	Status = XSdPs_CmdTransfer(InstancePtr, CMD55,
-			InstancePtr->RelCardAddr, 0U);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
-	}
-
-	BlkCnt = XSDPS_SD_STATUS_BLKCNT;
-	BlkSize = XSDPS_SD_STATUS_BLKSIZE;
-
-	XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, SdStatReg);
-
-	Status = XSdPs_CmdTransfer(InstancePtr, ACMD13, 0U, BlkCnt);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
-	}
-
-	/* Check for transfer done */
-	Status = XSdps_CheckTransferDone(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-	}
-
-	if (InstancePtr->Config.IsCacheCoherent == 0U) {
-		Xil_DCacheInvalidateRange((INTPTR)SdStatReg,
-				(INTPTR)BlkCnt * BlkSize);
-	}
-
-	Status = XST_SUCCESS;
-
-	RETURN_PATH:
-		return Status;
+    s32 Status;
+    u16 BlkCnt;
+    u16 BlkSize;
+
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+    /* Send block write command */
+    Status = XSdPs_CmdTransfer(InstancePtr, CMD55,
+            InstancePtr->RelCardAddr, 0U);
+    if (Status != XST_SUCCESS) {
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
+
+    BlkCnt = XSDPS_SD_STATUS_BLKCNT;
+    BlkSize = XSDPS_SD_STATUS_BLKSIZE;
+
+    XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, SdStatReg);
+
+    Status = XSdPs_CmdTransfer(InstancePtr, ACMD13, 0U, BlkCnt);
+    if (Status != XST_SUCCESS) {
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
+
+    /* Check for transfer done */
+    Status = XSdps_CheckTransferDone(InstancePtr);
+    if (Status != XST_SUCCESS) {
+        Status = XST_FAILURE;
+    }
+
+    if (InstancePtr->Config.IsCacheCoherent == 0U) {
+        Xil_DCacheInvalidateRange((INTPTR)SdStatReg,
+                (INTPTR)BlkCnt * BlkSize);
+    }
+
+    Status = XST_SUCCESS;
+
+    RETURN_PATH:
+        return Status;
 }
 
 /*****************************************************************************/
@@ -454,65 +454,65 @@ s32 XSdPs_Get_Status(XSdPs *InstancePtr, u8 *SdStatReg)
 * API to set high speed in card and host. Changes clock in host accordingly.
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
+* @param    InstancePtr is a pointer to the XSdPs instance.
 *
 * @return
-*		- XST_SUCCESS if successful.
-*		- XST_FAILURE if fail.
+*        - XST_SUCCESS if successful.
+*        - XST_FAILURE if fail.
 *
-* @note		None.
+* @note        None.
 *
 ******************************************************************************/
 s32 XSdPs_Change_BusSpeed(XSdPs *InstancePtr)
 {
-	s32 Status;
-	u32 StatusReg;
-
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
-
-	if (InstancePtr->CardType == XSDPS_CARD_SD) {
-		Status = XSdPs_Change_SdBusSpeed(InstancePtr);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
-		}
-	} else {
-		Status = XSdPs_Change_MmcBusSpeed(InstancePtr);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
-		}
-	}
-
-	Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
-	}
-
-	if ((InstancePtr->Mode == XSDPS_HS200_MODE) ||
-		(InstancePtr->Mode == XSDPS_UHS_SPEED_MODE_SDR104) ||
-		(InstancePtr->Mode == XSDPS_UHS_SPEED_MODE_SDR50)) {
-		Status = XSdPs_Execute_Tuning(InstancePtr);
-		if (Status != XST_SUCCESS) {
-			Status = XST_FAILURE;
-			goto RETURN_PATH;
-		}
-	}
-
-	usleep(XSDPS_MMC_DELAY_FOR_SWITCH);
-
-	StatusReg = (u32)XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
-					XSDPS_HOST_CTRL1_OFFSET);
-	StatusReg |= XSDPS_HC_SPEED_MASK;
-	XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
-			XSDPS_HOST_CTRL1_OFFSET, (u8)StatusReg);
-
-	Status = XST_SUCCESS;
-
-	RETURN_PATH:
-		return Status;
+    s32 Status;
+    u32 StatusReg;
+
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+    if (InstancePtr->CardType == XSDPS_CARD_SD) {
+        Status = XSdPs_Change_SdBusSpeed(InstancePtr);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    } else {
+        Status = XSdPs_Change_MmcBusSpeed(InstancePtr);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    }
+
+    Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
+    if (Status != XST_SUCCESS) {
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
+
+    if ((InstancePtr->Mode == XSDPS_HS200_MODE) ||
+        (InstancePtr->Mode == XSDPS_UHS_SPEED_MODE_SDR104) ||
+        (InstancePtr->Mode == XSDPS_UHS_SPEED_MODE_SDR50)) {
+        Status = XSdPs_Execute_Tuning(InstancePtr);
+        if (Status != XST_SUCCESS) {
+            Status = XST_FAILURE;
+            goto RETURN_PATH;
+        }
+    }
+
+    usleep(XSDPS_MMC_DELAY_FOR_SWITCH);
+
+    StatusReg = (u32)XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
+                    XSDPS_HOST_CTRL1_OFFSET);
+    StatusReg |= XSDPS_HC_SPEED_MASK;
+    XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
+            XSDPS_HOST_CTRL1_OFFSET, (u8)StatusReg);
+
+    Status = XST_SUCCESS;
+
+    RETURN_PATH:
+        return Status;
 
 }
 
@@ -523,58 +523,58 @@ s32 XSdPs_Change_BusSpeed(XSdPs *InstancePtr)
 * API to get EXT_CSD register of eMMC.
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
-* @param	ReadBuff - buffer to store EXT_CSD
+* @param    InstancePtr is a pointer to the XSdPs instance.
+* @param    ReadBuff - buffer to store EXT_CSD
 *
 * @return
-*		- XST_SUCCESS if successful.
-*		- XST_FAILURE if fail.
+*        - XST_SUCCESS if successful.
+*        - XST_FAILURE if fail.
 *
-* @note		None.
+* @note        None.
 *
 ******************************************************************************/
 s32 XSdPs_Get_Mmc_ExtCsd(XSdPs *InstancePtr, u8 *ReadBuff)
 {
-	s32 Status;
-	u32 Arg = 0U;
-	u16 BlkCnt;
-	u16 BlkSize;
-	s32 LoopCnt;
+    s32 Status;
+    u32 Arg = 0U;
+    u16 BlkCnt;
+    u16 BlkSize;
+    s32 LoopCnt;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
-	for (LoopCnt = 0; LoopCnt < 512; LoopCnt++) {
-		ReadBuff[LoopCnt] = 0U;
-	}
+    for (LoopCnt = 0; LoopCnt < 512; LoopCnt++) {
+        ReadBuff[LoopCnt] = 0U;
+    }
 
-	BlkCnt = XSDPS_EXT_CSD_CMD_BLKCNT;
-	BlkSize = XSDPS_EXT_CSD_CMD_BLKSIZE;
+    BlkCnt = XSDPS_EXT_CSD_CMD_BLKCNT;
+    BlkSize = XSDPS_EXT_CSD_CMD_BLKSIZE;
 
-	XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, ReadBuff);
+    XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, ReadBuff);
 
-	/* Send SEND_EXT_CSD command */
-	Status = XSdPs_CmdTransfer(InstancePtr, CMD8, Arg, 1U);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
-	}
+    /* Send SEND_EXT_CSD command */
+    Status = XSdPs_CmdTransfer(InstancePtr, CMD8, Arg, 1U);
+    if (Status != XST_SUCCESS) {
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Check for transfer done */
-	Status = XSdps_CheckTransferDone(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-	}
+    /* Check for transfer done */
+    Status = XSdps_CheckTransferDone(InstancePtr);
+    if (Status != XST_SUCCESS) {
+        Status = XST_FAILURE;
+    }
 
-	if (InstancePtr->Config.IsCacheCoherent == 0U) {
-		Xil_DCacheInvalidateRange((INTPTR)ReadBuff,
-				(INTPTR)BlkCnt * BlkSize);
-	}
+    if (InstancePtr->Config.IsCacheCoherent == 0U) {
+        Xil_DCacheInvalidateRange((INTPTR)ReadBuff,
+                (INTPTR)BlkCnt * BlkSize);
+    }
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
-	RETURN_PATH:
-		return Status;
+    RETURN_PATH:
+        return Status;
 
 }
 
@@ -585,39 +585,39 @@ s32 XSdPs_Get_Mmc_ExtCsd(XSdPs *InstancePtr, u8 *ReadBuff)
 * API to write EXT_CSD register of eMMC.
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
-* @param	Arg is the argument to be sent along with the command
+* @param    InstancePtr is a pointer to the XSdPs instance.
+* @param    Arg is the argument to be sent along with the command
 *
 * @return
-*		- XST_SUCCESS if successful.
-*		- XST_FAILURE if fail.
+*        - XST_SUCCESS if successful.
+*        - XST_FAILURE if fail.
 *
-* @note		None.
+* @note        None.
 *
 ******************************************************************************/
 s32 XSdPs_Set_Mmc_ExtCsd(XSdPs *InstancePtr, u32 Arg)
 {
-	s32 Status;
+    s32 Status;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
-	Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 0U);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
-	}
+    Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 0U);
+    if (Status != XST_SUCCESS) {
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	/* Check for transfer done */
-	Status = XSdps_CheckTransferDone(InstancePtr);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-	}
+    /* Check for transfer done */
+    Status = XSdps_CheckTransferDone(InstancePtr);
+    if (Status != XST_SUCCESS) {
+        Status = XST_FAILURE;
+    }
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
-	RETURN_PATH:
-		return Status;
+    RETURN_PATH:
+        return Status;
 
 }
 
@@ -628,39 +628,39 @@ s32 XSdPs_Set_Mmc_ExtCsd(XSdPs *InstancePtr, u32 Arg)
 * API to send pullup command to card before using DAT line 3(using 4-bit bus)
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
+* @param    InstancePtr is a pointer to the XSdPs instance.
 *
 * @return
-*		- XST_SUCCESS if successful.
-*		- XST_FAILURE if fail.
+*        - XST_SUCCESS if successful.
+*        - XST_FAILURE if fail.
 *
-* @note		None.
+* @note        None.
 *
 ******************************************************************************/
 s32 XSdPs_Pullup(XSdPs *InstancePtr)
 {
-	s32 Status;
+    s32 Status;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
-	Status = XSdPs_CmdTransfer(InstancePtr, CMD55,
-			InstancePtr->RelCardAddr, 0U);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
-	}
+    Status = XSdPs_CmdTransfer(InstancePtr, CMD55,
+            InstancePtr->RelCardAddr, 0U);
+    if (Status != XST_SUCCESS) {
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	Status = XSdPs_CmdTransfer(InstancePtr, ACMD42, 0U, 0U);
-	if (Status != XST_SUCCESS) {
-		Status = XST_FAILURE;
-		goto RETURN_PATH;
-	}
+    Status = XSdPs_CmdTransfer(InstancePtr, ACMD42, 0U, 0U);
+    if (Status != XST_SUCCESS) {
+        Status = XST_FAILURE;
+        goto RETURN_PATH;
+    }
 
-	Status = XST_SUCCESS;
+    Status = XST_SUCCESS;
 
-	RETURN_PATH:
-		return Status;
+    RETURN_PATH:
+        return Status;
 
 }
 
@@ -671,28 +671,28 @@ s32 XSdPs_Pullup(XSdPs *InstancePtr)
 * Selects card and sets default block size
 *
 *
-* @param	InstancePtr is a pointer to the XSdPs instance.
+* @param    InstancePtr is a pointer to the XSdPs instance.
 *
 * @return
-*		- XST_SUCCESS if successful.
-*		- XST_FAILURE if fail.
-*		- XSDPS_CT_ERROR if Command Transfer fail.
+*        - XST_SUCCESS if successful.
+*        - XST_FAILURE if fail.
+*        - XSDPS_CT_ERROR if Command Transfer fail.
 *
-* @note		None.
+* @note        None.
 *
 ******************************************************************************/
 s32 XSdPs_Select_Card (XSdPs *InstancePtr)
 {
-	s32 Status;
+    s32 Status;
 
-	Xil_AssertNonvoid(InstancePtr != NULL);
-	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+    Xil_AssertNonvoid(InstancePtr != NULL);
+    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
 
-	/* Send CMD7 - Select card */
-	Status = XSdPs_CmdTransfer(InstancePtr, CMD7,
-			InstancePtr->RelCardAddr, 0U);
+    /* Send CMD7 - Select card */
+    Status = XSdPs_CmdTransfer(InstancePtr, CMD7,
+            InstancePtr->RelCardAddr, 0U);
 
-	return Status;
+    return Status;
 }
 
 /** @} */

+ 12 - 12
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sdps_v3_9/xsdps_sinit.c

@@ -48,28 +48,28 @@ extern XSdPs_Config XSdPs_ConfigTable[XPAR_XSDPS_NUM_INSTANCES];
 * Looks up the device configuration based on the unique device ID. A table
 * contains the configuration info for each device in the system.
 *
-* @param	DeviceId contains the ID of the device to look up the
-*		configuration for.
+* @param    DeviceId contains the ID of the device to look up the
+*        configuration for.
 *
 * @return
 *
 * A pointer to the configuration found or NULL if the specified device ID was
 * not found. See xsdps.h for the definition of XSdPs_Config.
 *
-* @note		None.
+* @note        None.
 *
 ******************************************************************************/
 XSdPs_Config *XSdPs_LookupConfig(u16 DeviceId)
 {
-	XSdPs_Config *CfgPtr = NULL;
-	u32 Index;
+    XSdPs_Config *CfgPtr = NULL;
+    u32 Index;
 
-	for (Index = 0U; Index < (u32)XPAR_XSDPS_NUM_INSTANCES; Index++) {
-		if (XSdPs_ConfigTable[Index].DeviceId == DeviceId) {
-			CfgPtr = &XSdPs_ConfigTable[Index];
-			break;
-		}
-	}
-	return (XSdPs_Config *)CfgPtr;
+    for (Index = 0U; Index < (u32)XPAR_XSDPS_NUM_INSTANCES; Index++) {
+        if (XSdPs_ConfigTable[Index].DeviceId == DeviceId) {
+            CfgPtr = &XSdPs_ConfigTable[Index];
+            break;
+        }
+    }
+    return (XSdPs_Config *)CfgPtr;
 }
 /** @} */

+ 5 - 5
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/sleep.h

@@ -13,15 +13,15 @@ extern "C" {
 
 static inline void usleep(unsigned long useconds)
 {
-	rt_uint32_t milliseconds = useconds/1000;
-	useconds = useconds%1000;
-	if (milliseconds) rt_thread_mdelay(milliseconds);
-	if (useconds) rt_hw_us_delay(useconds);
+    rt_uint32_t milliseconds = useconds/1000;
+    useconds = useconds%1000;
+    if (milliseconds) rt_thread_mdelay(milliseconds);
+    if (useconds) rt_hw_us_delay(useconds);
 }
 
 static inline void sleep(unsigned int seconds)
 {
-	rt_thread_delay(seconds);
+    rt_thread_delay(seconds*RT_TICK_PER_SECOND);
 }
 
 #ifdef __cplusplus

+ 15 - 0
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/SConscript

@@ -0,0 +1,15 @@
+import rtconfig
+from building import *
+
+# get current directory
+cwd = GetCurrentDir()
+CPPPATH = [cwd]
+
+# The set of source files associated with this SConscript file.
+
+src = Glob('*.c')
+path = cwd
+
+group = DefineGroup('ZYNQMP_HAL', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')

+ 90 - 0
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xadapter.h

@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2007 - 2019 Xilinx, Inc.
+ * Copyright (C) 2021 WangHuachen.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ */
+
+#ifndef __XADAPTER_H_
+#define __XADAPTER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "lwipopts.h"
+
+#if !NO_SYS
+#ifdef OS_IS_XILKERNEL
+#include "xmk.h"
+#endif
+#include "lwip/sys.h"
+#endif
+
+#include "lwip/netif.h"
+#include "lwip/ip.h"
+
+#include "netif/xtopology.h"
+#include <netif/ethernetif.h>
+
+struct xemac_s {
+    enum xemac_types type;
+    int  topology_index;
+    void *state;
+    struct eth_device *rt_eth_device;
+#if defined(OS_IS_FREERTOS) && defined(__arm__) && !defined(ARMR5)
+    TimerHandle_t xTimer;
+#endif
+};
+
+enum ethernet_link_status {
+    ETH_LINK_UNDEFINED = 0,
+    ETH_LINK_UP,
+    ETH_LINK_DOWN,
+    ETH_LINK_NEGOTIATING
+};
+
+void eth_link_detect(struct netif *netif);
+void         lwip_raw_init();
+int         xemacif_input(struct netif *netif);
+void         xemacif_input_thread(struct netif *netif);
+struct netif *    xemac_add(struct netif *netif,
+    ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw,
+    unsigned char *mac_ethernet_address,
+    unsigned mac_baseaddr);
+#if defined (__arm__) || defined (__aarch64__)
+void xemacpsif_resetrx_on_no_rxdata(struct netif *netif);
+#endif
+
+/* global lwip debug variable used for debugging */
+extern int lwip_runtime_debug;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 163 - 0
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xemacpsif.h

@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2010 - 2019 Xilinx, Inc.
+ * Copyright (C) 2021 WangHuachen.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ */
+
+#ifndef __NETIF_XEMACPSIF_H__
+#define __NETIF_XEMACPSIF_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "xlwipconfig.h"
+#include "lwip/netif.h"
+#include "netif/etharp.h"
+#include "lwip/sys.h"
+#include "netif/xadapter.h"
+
+#include "xstatus.h"
+#include "sleep.h"
+#include "xparameters.h"
+#include "xparameters_ps.h"    /* defines XPAR values */
+#include "xil_types.h"
+#include "xil_assert.h"
+#include "xil_io.h"
+// #include "xil_exception.h"
+// #include "xpseudo_asm.h"
+#include "xpseudo_asm_gcc.h"
+#include "xil_cache.h"
+#include "xil_printf.h"
+// #include "xscugic.h"
+#include "xemacps.h"        /* defines XEmacPs API */
+
+#include "netif/xpqueue.h"
+#include "xlwipconfig.h"
+
+#if EL1_NONSECURE
+#include "xil_smc.h"
+#endif
+
+#define ZYNQ_EMACPS_0_BASEADDR 0xE000B000
+#define ZYNQ_EMACPS_1_BASEADDR 0xE000C000
+
+#define ZYNQMP_EMACPS_0_BASEADDR 0xFF0B0000
+#define ZYNQMP_EMACPS_1_BASEADDR 0xFF0C0000
+#define ZYNQMP_EMACPS_2_BASEADDR 0xFF0D0000
+#define ZYNQMP_EMACPS_3_BASEADDR 0xFF0E0000
+
+#define CRL_APB_GEM0_REF_CTRL    0xFF5E0050
+#define CRL_APB_GEM1_REF_CTRL    0xFF5E0054
+#define CRL_APB_GEM2_REF_CTRL    0xFF5E0058
+#define CRL_APB_GEM3_REF_CTRL    0xFF5E005C
+
+#define CRL_APB_GEM_DIV0_MASK    0x00003F00
+#define CRL_APB_GEM_DIV0_SHIFT    8
+#define CRL_APB_GEM_DIV1_MASK    0x003F0000
+#define CRL_APB_GEM_DIV1_SHIFT    16
+
+#define VERSAL_EMACPS_0_BASEADDR 0xFF0C0000
+#define VERSAL_EMACPS_1_BASEADDR 0xFF0D0000
+
+#define VERSAL_CRL_GEM0_REF_CTRL    0xFF5E0118
+#define VERSAL_CRL_GEM1_REF_CTRL    0xFF5E011C
+
+#define VERSAL_CRL_GEM_DIV_MASK        0x0003FF00
+#define VERSAL_CRL_APB_GEM_DIV_SHIFT    8
+
+#if defined (ARMR5) || (__aarch64__) || (ARMA53_32) || (__MICROBLAZE__)
+#if defined (USE_JUMBO_FRAMES)
+#define ZYNQMP_USE_JUMBO
+#endif
+#endif
+
+#define GEM_VERSION_ZYNQMP    7
+#define GEM_VERSION_VERSAL    0x107
+
+#define MAX_FRAME_SIZE_JUMBO (XEMACPS_MTU_JUMBO + XEMACPS_HDR_SIZE + XEMACPS_TRL_SIZE)
+
+void     xemacpsif_setmac(u32_t index, u8_t *addr);
+u8_t*    xemacpsif_getmac(u32_t index);
+err_t     xemacpsif_init(struct netif *netif);
+s32_t     xemacpsif_input(struct netif *netif);
+
+/* xaxiemacif_hw.c */
+void     xemacps_error_handler(XEmacPs * Temac);
+
+/* structure within each netif, encapsulating all information required for
+ * using a particular temac instance
+ */
+typedef struct {
+    XEmacPs emacps;
+
+    /* queue to store overflow packets */
+    pq_queue_t *recv_q;
+    pq_queue_t *send_q;
+
+    /* pointers to memory holding buffer descriptors (used only with SDMA) */
+    void *rx_bdspace;
+    void *tx_bdspace;
+
+    unsigned int last_rx_frms_cntr;
+
+} xemacpsif_s;
+
+extern xemacpsif_s xemacpsif;
+
+s32_t    is_tx_space_available(xemacpsif_s *emac);
+
+/* xemacpsif_dma.c */
+
+void  process_sent_bds(xemacpsif_s *xemacpsif, XEmacPs_BdRing *txring);
+u32_t phy_setup_emacps (XEmacPs *xemacpsp, u32_t phy_addr);
+void detect_phy(XEmacPs *xemacpsp);
+void emacps_send_handler(void *arg);
+XStatus emacps_sgsend(xemacpsif_s *xemacpsif, struct pbuf *p);
+void emacps_recv_handler(void *arg);
+void emacps_error_handler(void *arg,u8 Direction, u32 ErrorWord);
+void setup_rx_bds(xemacpsif_s *xemacpsif, XEmacPs_BdRing *rxring);
+void HandleTxErrors(struct xemac_s *xemac);
+void HandleEmacPsError(struct xemac_s *xemac);
+XEmacPs_Config *xemacps_lookup_config(unsigned mac_base);
+void init_emacps(xemacpsif_s *xemacps, struct netif *netif);
+void setup_isr (struct xemac_s *xemac);
+XStatus init_dma(struct xemac_s *xemac);
+void start_emacps (xemacpsif_s *xemacps);
+void free_txrx_pbufs(xemacpsif_s *xemacpsif);
+void free_onlytx_pbufs(xemacpsif_s *xemacpsif);
+void init_emacps_on_error (xemacpsif_s *xemacps, struct netif *netif);
+void clean_dma_txdescs(struct xemac_s *xemac);
+void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif);
+void reset_dma(struct xemac_s *xemac);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __NETIF_XAXIEMACIF_H__ */

+ 54 - 0
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xpqueue.h

@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2007 - 2019 Xilinx, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ */
+
+#ifndef __LWIP_PBUF_QUEUE_H_
+#define __LWIP_PBUF_QUEUE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PQ_QUEUE_SIZE 4096
+
+typedef struct {
+    void *data[PQ_QUEUE_SIZE];
+    int head, tail, len;
+} pq_queue_t;
+
+pq_queue_t*    pq_create_queue();
+int         pq_enqueue(pq_queue_t *q, void *p);
+void*        pq_dequeue(pq_queue_t *q);
+int        pq_qlength(pq_queue_t *q);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 58 - 0
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/netif/xtopology.h

@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2007 - 2019 Xilinx, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ */
+
+#ifndef __XTOPOLOGY_H_
+#define __XTOPOLOGY_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum xemac_types { xemac_type_unknown = -1, xemac_type_xps_emaclite, xemac_type_xps_ll_temac, xemac_type_axi_ethernet, xemac_type_emacps };
+
+struct xtopology_t {
+    unsigned emac_baseaddr;
+    enum xemac_types emac_type;
+    unsigned intc_baseaddr;
+    unsigned intc_emac_intr;    /* valid only for xemac_type_xps_emaclite */
+    unsigned scugic_baseaddr; /* valid only for Zynq */
+    unsigned scugic_emac_intr; /* valid only for GEM */
+};
+
+extern int xtopology_n_emacs;
+extern struct xtopology_t xtopology[];
+
+int xtopology_find_index(unsigned base);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 409 - 0
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xadapter.c

@@ -0,0 +1,409 @@
+/*
+ * Copyright (C) 2007 - 2019 Xilinx, Inc.
+ * Copyright (C) 2021 WangHuachen.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ */
+
+#include "lwipopts.h"
+#include "xlwipconfig.h"
+#include "xemac_ieee_reg.h"
+
+#if !NO_SYS
+#ifdef OS_IS_XILKERNEL
+#include "xmk.h"
+#include "sys/process.h"
+#endif
+#endif
+
+#include "lwip/mem.h"
+#include "lwip/stats.h"
+#include "lwip/sys.h"
+#include "lwip/ip.h"
+#include "lwip/tcp.h"
+#include "lwip/udp.h"
+#include "lwip/priv/tcp_priv.h"
+
+#include "netif/etharp.h"
+#include "netif/xadapter.h"
+
+#ifdef XLWIP_CONFIG_INCLUDE_EMACLITE
+#include "netif/xemacliteif.h"
+#endif
+
+#ifdef XLWIP_CONFIG_INCLUDE_AXI_ETHERNET
+#include "netif/xaxiemacif.h"
+#endif
+
+#ifdef XLWIP_CONFIG_INCLUDE_GEM
+#include "netif/xemacpsif.h"
+#endif
+
+#if !NO_SYS
+#include "lwip/tcpip.h"
+#endif
+
+#ifdef OS_IS_FREERTOS
+#define THREAD_STACKSIZE 256
+#define LINK_DETECT_THREAD_INTERVAL 1000 /* one second */
+
+void link_detect_thread(void *p);
+#endif
+
+/* global lwip debug variable used for debugging */
+int lwip_runtime_debug = 0;
+
+enum ethernet_link_status eth_link_status = ETH_LINK_UNDEFINED;
+u32_t phyaddrforemac;
+
+void
+lwip_raw_init()
+{
+    ip_init();    /* Doesn't do much, it should be called to handle future changes. */
+#if LWIP_UDP
+    udp_init();    /* Clears the UDP PCB list. */
+#endif
+#if LWIP_TCP
+    tcp_init();    /* Clears the TCP PCB list and clears some internal TCP timers. */
+            /* Note: you must call tcp_fasttmr() and tcp_slowtmr() at the */
+            /* predefined regular intervals after this initialization. */
+#endif
+}
+
+static enum xemac_types
+find_mac_type(unsigned base)
+{
+    int i;
+
+    for (i = 0; i < xtopology_n_emacs; i++) {
+        if (xtopology[i].emac_baseaddr == base)
+            return xtopology[i].emac_type;
+    }
+
+    return xemac_type_unknown;
+}
+
+int
+xtopology_find_index(unsigned base)
+{
+    int i;
+
+    for (i = 0; i < xtopology_n_emacs; i++) {
+        if (xtopology[i].emac_baseaddr == base)
+            return i;
+    }
+
+    return -1;
+}
+
+/*
+ * xemac_add: this is a wrapper around lwIP's netif_add function.
+ * The objective is to provide portability between the different Xilinx MAC's
+ * This function can be used to add both xps_ethernetlite and xps_ll_temac
+ * based interfaces
+ */
+struct netif *
+xemac_add(struct netif *netif,
+    ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw,
+    unsigned char *mac_ethernet_address,
+    unsigned mac_baseaddr)
+{
+    int i;
+
+#ifdef OS_IS_FREERTOS
+    /* Start thread to detect link periodically for Hot Plug autodetect */
+    sys_thread_new("link_detect_thread", link_detect_thread, netif,
+            THREAD_STACKSIZE, tskIDLE_PRIORITY);
+#endif
+
+    /* set mac address */
+    netif->hwaddr_len = 6;
+    for (i = 0; i < 6; i++)
+        netif->hwaddr[i] = mac_ethernet_address[i];
+
+    /* initialize based on MAC type */
+        switch (find_mac_type(mac_baseaddr)) {
+            case xemac_type_xps_emaclite:
+#ifdef XLWIP_CONFIG_INCLUDE_EMACLITE
+                return netif_add(netif, ipaddr, netmask, gw,
+                    (void*)(UINTPTR)mac_baseaddr,
+                    xemacliteif_init,
+#if NO_SYS
+                    ethernet_input
+#else
+                    tcpip_input
+#endif
+                    );
+#else
+                return NULL;
+#endif
+            case xemac_type_axi_ethernet:
+#ifdef XLWIP_CONFIG_INCLUDE_AXI_ETHERNET
+                return netif_add(netif, ipaddr, netmask, gw,
+                    (void*)(UINTPTR)mac_baseaddr,
+                    xaxiemacif_init,
+#if NO_SYS
+                    ethernet_input
+#else
+                    tcpip_input
+#endif
+                    );
+#else
+                return NULL;
+#endif
+#if defined (__arm__) || defined (__aarch64__)
+            case xemac_type_emacps:
+#ifdef XLWIP_CONFIG_INCLUDE_GEM
+                return netif_add(netif, ipaddr, netmask, gw,
+                        (void*)(UINTPTR)mac_baseaddr,
+                        xemacpsif_init,
+#if NO_SYS
+                        ethernet_input
+#else
+                        tcpip_input
+#endif
+
+                        );
+#endif
+#endif
+            default:
+                xil_printf("unable to determine type of EMAC with baseaddress 0x%08x\r\n",
+                        mac_baseaddr);
+                return NULL;
+    }
+}
+
+int
+xemacif_input(struct netif *netif)
+{
+    struct xemac_s *emac = (struct xemac_s *)netif->state;
+
+    int n_packets = 0;
+
+    switch (emac->type) {
+        case xemac_type_xps_emaclite:
+#ifdef XLWIP_CONFIG_INCLUDE_EMACLITE
+            n_packets = xemacliteif_input(netif);
+            break;
+#else
+            // print("incorrect configuration: xps_ethernetlite drivers not present?");
+            while(1);
+            return 0;
+#endif
+        case xemac_type_axi_ethernet:
+#ifdef XLWIP_CONFIG_INCLUDE_AXI_ETHERNET
+            n_packets = xaxiemacif_input(netif);
+            break;
+#else
+            // print("incorrect configuration: axi_ethernet drivers not present?");
+            while(1);
+            return 0;
+#endif
+#if defined (__arm__) || defined (__aarch64__)
+        case xemac_type_emacps:
+#ifdef XLWIP_CONFIG_INCLUDE_GEM
+            n_packets = xemacpsif_input(netif);
+            break;
+#else
+            xil_printf("incorrect configuration: ps7_ethernet drivers not present?\r\n");
+            while(1);
+            return 0;
+#endif
+#endif
+        default:
+            // print("incorrect configuration: unknown temac type");
+            while(1);
+            return 0;
+    }
+
+    return n_packets;
+}
+
+#if defined(XLWIP_CONFIG_INCLUDE_GEM)
+u32_t phy_link_detect(XEmacPs *xemacp, u32_t phy_addr)
+{
+    u16_t status;
+
+    /* Read Phy Status register twice to get the confirmation of the current
+     * link status.
+     */
+    XEmacPs_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    XEmacPs_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+
+    if (status & IEEE_STAT_LINK_STATUS)
+        return 1;
+    return 0;
+}
+#elif defined(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET)
+static u32_t phy_link_detect(XAxiEthernet *xemacp, u32_t phy_addr)
+{
+    u16_t status;
+
+    /* Read Phy Status register twice to get the confirmation of the current
+     * link status.
+     */
+    XAxiEthernet_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    XAxiEthernet_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+
+    if (status & IEEE_STAT_LINK_STATUS)
+        return 1;
+    return 0;
+}
+#elif defined(XLWIP_CONFIG_INCLUDE_EMACLITE)
+static u32_t phy_link_detect(XEmacLite *xemacp, u32_t phy_addr)
+{
+    u16_t status;
+
+    /* Read Phy Status register twice to get the confirmation of the current
+     * link status.
+     */
+    XEmacLite_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    XEmacLite_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+
+    if (status & IEEE_STAT_LINK_STATUS)
+        return 1;
+    return 0;
+}
+#endif
+
+#if defined(XLWIP_CONFIG_INCLUDE_GEM)
+u32_t phy_autoneg_status(XEmacPs *xemacp, u32_t phy_addr)
+{
+    u16_t status;
+
+    /* Read Phy Status register twice to get the confirmation of the current
+     * link status.
+     */
+    XEmacPs_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    XEmacPs_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+
+    if (status & IEEE_STAT_AUTONEGOTIATE_COMPLETE)
+        return 1;
+    return 0;
+}
+#elif defined(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET)
+static u32_t phy_autoneg_status(XAxiEthernet *xemacp, u32_t phy_addr)
+{
+    u16_t status;
+
+    /* Read Phy Status register twice to get the confirmation of the current
+     * link status.
+     */
+    XAxiEthernet_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    XAxiEthernet_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+
+    if (status & IEEE_STAT_AUTONEGOTIATE_COMPLETE)
+        return 1;
+    return 0;
+}
+#elif defined(XLWIP_CONFIG_INCLUDE_EMACLITE)
+static u32_t phy_autoneg_status(XEmacLite *xemacp, u32_t phy_addr)
+{
+    u16_t status;
+
+    /* Read Phy Status register twice to get the confirmation of the current
+     * link status.
+     */
+    XEmacLite_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    XEmacLite_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+
+    if (status & IEEE_STAT_AUTONEGOTIATE_COMPLETE)
+        return 1;
+    return 0;
+}
+#endif
+
+void eth_link_detect(struct netif *netif)
+{
+    u32_t link_speed, phy_link_status;
+    struct xemac_s *xemac = (struct xemac_s *)(netif->state);
+
+#if defined(XLWIP_CONFIG_INCLUDE_GEM)
+    xemacpsif_s *xemacs = (xemacpsif_s *)(xemac->state);
+    XEmacPs *xemacp = &xemacs->emacps;
+#elif defined(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET)
+    xaxiemacif_s *xemacs = (xaxiemacif_s *)(xemac->state);
+    XAxiEthernet *xemacp = &xemacs->axi_ethernet;
+#elif defined(XLWIP_CONFIG_INCLUDE_EMACLITE)
+    xemacliteif_s *xemacs = (xemacliteif_s *)(xemac->state);
+    XEmacLite *xemacp = xemacs->instance;
+#endif
+
+    if ((xemacp->IsReady != (u32)XIL_COMPONENT_IS_READY) ||
+            (eth_link_status == ETH_LINK_UNDEFINED))
+        return;
+
+    phy_link_status = phy_link_detect(xemacp, phyaddrforemac);
+
+    if ((eth_link_status == ETH_LINK_UP) && (!phy_link_status))
+        eth_link_status = ETH_LINK_DOWN;
+
+    switch (eth_link_status) {
+        case ETH_LINK_UNDEFINED:
+        case ETH_LINK_UP:
+            return;
+        case ETH_LINK_DOWN:
+            netif_set_link_down(netif);
+            eth_link_status = ETH_LINK_NEGOTIATING;
+            xil_printf("Ethernet Link down\r\n");
+            break;
+        case ETH_LINK_NEGOTIATING:
+            if (phy_link_status &&
+                phy_autoneg_status(xemacp, phyaddrforemac)) {
+
+                /* Initiate Phy setup to get link speed */
+#if defined(XLWIP_CONFIG_INCLUDE_GEM)
+                link_speed = phy_setup_emacps(xemacp,
+                                phyaddrforemac);
+                XEmacPs_SetOperatingSpeed(xemacp, link_speed);
+#elif defined(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET)
+                link_speed = phy_setup_axiemac(xemacp);
+                XAxiEthernet_SetOperatingSpeed(xemacp,
+                                   link_speed);
+#endif
+                netif_set_link_up(netif);
+                eth_link_status = ETH_LINK_UP;
+                xil_printf("Ethernet Link up\r\n");
+            }
+            break;
+    }
+}
+
+#ifdef OS_IS_FREERTOS
+void link_detect_thread(void *p)
+{
+    struct netif *netif = (struct netif *) p;
+
+    while (1) {
+        /* Call eth_link_detect() every second to detect Ethernet link
+         * change.
+         */
+        eth_link_detect(netif);
+        vTaskDelay(LINK_DETECT_THREAD_INTERVAL / portTICK_RATE_MS);
+    }
+}
+#endif

+ 101 - 0
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemac_ieee_reg.h

@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2018 - 2019 Xilinx, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ */
+
+#ifndef __XEMAC_IEEE_REGS_H_
+#define __XEMAC_IEEE_REGS_H_
+
+/* Advertisement control register. */
+#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_100_AND_10        (ADVERTISE_10FULL | ADVERTISE_100FULL | \
+                    ADVERTISE_10HALF | ADVERTISE_100HALF)
+#define ADVERTISE_100               (ADVERTISE_100FULL | ADVERTISE_100HALF)
+#define ADVERTISE_10                (ADVERTISE_10FULL | ADVERTISE_10HALF)
+
+#define ADVERTISE_1000              0x0300
+
+
+#define IEEE_CONTROL_REG_OFFSET                    0
+#define IEEE_STATUS_REG_OFFSET                     1
+#define IEEE_AUTONEGO_ADVERTISE_REG                4
+#define IEEE_PARTNER_ABILITIES_1_REG_OFFSET        5
+#define IEEE_PARTNER_ABILITIES_2_REG_OFFSET        8
+#define IEEE_PARTNER_ABILITIES_3_REG_OFFSET        10
+#define IEEE_1000_ADVERTISE_REG_OFFSET             9
+#define IEEE_MMD_ACCESS_CONTROL_REG                13
+#define IEEE_MMD_ACCESS_ADDRESS_DATA_REG           14
+#define IEEE_COPPER_SPECIFIC_CONTROL_REG           16
+#define IEEE_SPECIFIC_STATUS_REG                   17
+#define IEEE_COPPER_SPECIFIC_STATUS_REG_2          19
+#define IEEE_EXT_PHY_SPECIFIC_CONTROL_REG          20
+#define IEEE_CONTROL_REG_MAC                       21
+#define IEEE_PAGE_ADDRESS_REGISTER                 22
+
+#define IEEE_CTRL_1GBPS_LINKSPEED_MASK             0x2040
+#define IEEE_CTRL_LINKSPEED_MASK                   0x0040
+#define IEEE_CTRL_LINKSPEED_1000M                  0x0040
+#define IEEE_CTRL_LINKSPEED_100M                   0x2000
+#define IEEE_CTRL_LINKSPEED_10M                    0x0000
+#define IEEE_CTRL_FULL_DUPLEX                      0x100
+#define IEEE_CTRL_RESET_MASK                       0x8000
+#define IEEE_CTRL_AUTONEGOTIATE_ENABLE             0x1000
+#define IEEE_STAT_AUTONEGOTIATE_CAPABLE            0x0008
+#define IEEE_STAT_AUTONEGOTIATE_COMPLETE           0x0020
+#define IEEE_STAT_AUTONEGOTIATE_RESTART            0x0200
+#define IEEE_STAT_LINK_STATUS                      0x0004
+#define IEEE_STAT_1GBPS_EXTENSIONS                 0x0100
+#define IEEE_AN1_ABILITY_MASK                      0x1FE0
+#define IEEE_AN3_ABILITY_MASK_1GBPS                0x0C00
+#define IEEE_AN1_ABILITY_MASK_100MBPS              0x0380
+#define IEEE_AN1_ABILITY_MASK_10MBPS               0x0060
+#define IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK         0x0030
+
+#define IEEE_SPEED_MASK                            0xC000
+#define IEEE_SPEED_1000                            0x8000
+#define IEEE_SPEED_100                             0x4000
+
+#define IEEE_ASYMMETRIC_PAUSE_MASK                 0x0800
+#define IEEE_PAUSE_MASK                            0x0400
+#define IEEE_AUTONEG_ERROR_MASK                    0x8000
+
+#define IEEE_MMD_ACCESS_CTRL_DEVAD_MASK            0x1F
+#define IEEE_MMD_ACCESS_CTRL_PIDEVAD_MASK          0x801F
+#define IEEE_MMD_ACCESS_CTRL_NOPIDEVAD_MASK        0x401F
+
+#endif /* __XEMAC_IEEE_REGS_H_ */

+ 756 - 0
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif.c

@@ -0,0 +1,756 @@
+/*
+ * Copyright (C) 2010 - 2019 Xilinx, Inc.
+ * Copyright (C) 2021 WangHuachen.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <xparameters.h>
+#include "lwipopts.h"
+#include "xlwipconfig.h"
+#include "lwip/opt.h"
+#include "lwip/def.h"
+#include "lwip/mem.h"
+#include "lwip/pbuf.h"
+#include "lwip/sys.h"
+#include "lwip/stats.h"
+#include "lwip/igmp.h"
+
+#include "netif/etharp.h"
+#include "netif/xemacpsif.h"
+#include "netif/xadapter.h"
+#include "netif/xpqueue.h"
+#include "xparameters.h"
+// #include "xscugic.h"
+#include "xemacps.h"
+
+#if LWIP_IPV6
+#include "lwip/ethip6.h"
+#endif
+
+#ifdef SYS_ARCH_DECL_PROTECT
+#undef SYS_ARCH_DECL_PROTECT
+#endif
+#define SYS_ARCH_DECL_PROTECT(lev) rt_base_t lev;
+
+#ifdef SYS_ARCH_PROTECT
+#undef SYS_ARCH_PROTECT
+#endif
+#define SYS_ARCH_PROTECT(lev) lev = rt_hw_interrupt_disable();
+
+#ifdef SYS_ARCH_UNPROTECT
+#undef SYS_ARCH_UNPROTECT
+#endif
+#define SYS_ARCH_UNPROTECT(lev) rt_hw_interrupt_enable(lev);
+
+/* Define those to better describe your network interface. */
+#define IFNAME0 't'
+#define IFNAME1 'e'
+
+#if LWIP_IGMP
+static err_t xemacpsif_mac_filter_update (struct netif *netif,
+                            ip_addr_t *group, u8_t action);
+
+static u8_t xemacps_mcast_entry_mask = 0;
+#endif
+
+#if LWIP_IPV6 && LWIP_IPV6_MLD
+static err_t xemacpsif_mld6_mac_filter_update (struct netif *netif,
+                            ip_addr_t *group, u8_t action);
+
+static u8_t xemacps_mld6_mcast_entry_mask;
+#endif
+
+XEmacPs_Config *mac_config;
+struct netif *NetIf;
+
+#if defined(OS_IS_FREERTOS) && defined(__arm__) && !defined(ARMR5)
+int32_t lExpireCounter = 0;
+#define RESETRXTIMEOUT 10
+#endif
+
+/*
+ * this function is always called with interrupts off
+ * this function also assumes that there are available BD's
+ */
+err_t _unbuffered_low_level_output(xemacpsif_s *xemacpsif,
+                                                    struct pbuf *p)
+{
+    XStatus status = 0;
+
+#if ETH_PAD_SIZE
+    pbuf_header(p, -ETH_PAD_SIZE);    /* drop the padding word */
+#endif
+    status = emacps_sgsend(xemacpsif, p);
+    if (status != XST_SUCCESS) {
+#if LINK_STATS
+    lwip_stats.link.drop++;
+#endif
+    }
+
+#if ETH_PAD_SIZE
+    pbuf_header(p, ETH_PAD_SIZE);    /* reclaim the padding word */
+#endif
+
+#if LINK_STATS
+    lwip_stats.link.xmit++;
+#endif /* LINK_STATS */
+
+    return ERR_OK;
+
+}
+
+/*
+ * low_level_output():
+ *
+ * Should do the actual transmission of the packet. The packet is
+ * contained in the pbuf that is passed to the function. This pbuf
+ * might be chained.
+ *
+ */
+
+static err_t low_level_output(struct netif *netif, struct pbuf *p)
+{
+    SYS_ARCH_DECL_PROTECT(lev);
+    err_t err;
+    s32_t freecnt;
+    XEmacPs_BdRing *txring;
+
+    struct xemac_s *xemac = (struct xemac_s *)(netif->state);
+    xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
+
+    SYS_ARCH_PROTECT(lev);
+
+    /* check if space is available to send */
+    freecnt = is_tx_space_available(xemacpsif);
+    if (freecnt <= 5) {
+    txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps));
+        process_sent_bds(xemacpsif, txring);
+    }
+
+    if (is_tx_space_available(xemacpsif)) {
+        _unbuffered_low_level_output(xemacpsif, p);
+        err = ERR_OK;
+    } else {
+#if LINK_STATS
+        lwip_stats.link.drop++;
+#endif
+        rt_kprintf("pack dropped, no space\r\n");
+        err = ERR_MEM;
+    }
+
+    SYS_ARCH_UNPROTECT(lev);
+    return err;
+}
+
+/*
+ * low_level_input():
+ *
+ * Should allocate a pbuf and transfer the bytes of the incoming
+ * packet from the interface into the pbuf.
+ *
+ */
+static struct pbuf * low_level_input(struct netif *netif)
+{
+    struct xemac_s *xemac = (struct xemac_s *)(netif->state);
+    xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
+    struct pbuf *p;
+
+    /* see if there is data to process */
+    if (pq_qlength(xemacpsif->recv_q) == 0)
+        return NULL;
+
+    /* return one packet from receive q */
+    p = (struct pbuf *)pq_dequeue(xemacpsif->recv_q);
+    return p;
+}
+
+/*
+ * xemacpsif_output():
+ *
+ * This function is called by the TCP/IP stack when an IP packet
+ * should be sent. It calls the function called low_level_output() to
+ * do the actual transmission of the packet.
+ *
+ */
+
+static err_t xemacpsif_output(struct netif *netif, struct pbuf *p,
+        const ip_addr_t *ipaddr)
+{
+    /* resolve hardware address, then send (or queue) packet */
+    return etharp_output(netif, p, ipaddr);
+}
+
+/*
+ * xemacpsif_input():
+ *
+ * This function should be called when a packet is ready to be read
+ * from the interface. It uses the function low_level_input() that
+ * should handle the actual reception of bytes from the network
+ * interface.
+ *
+ * Returns the number of packets read (max 1 packet on success,
+ * 0 if there are no packets)
+ *
+ */
+
+s32_t xemacpsif_input(struct netif *netif)
+{
+    struct eth_hdr *ethhdr;
+    struct pbuf *p;
+    SYS_ARCH_DECL_PROTECT(lev);
+
+#ifdef OS_IS_FREERTOS
+    while (1)
+#endif
+    {
+        /* move received packet into a new pbuf */
+        SYS_ARCH_PROTECT(lev);
+        p = low_level_input(netif);
+        SYS_ARCH_UNPROTECT(lev);
+
+        /* no packet could be read, silently ignore this */
+        if (p == NULL) {
+            return 0;
+        }
+
+        /* points to packet payload, which starts with an Ethernet header */
+        ethhdr = p->payload;
+
+    #if LINK_STATS
+        lwip_stats.link.recv++;
+    #endif /* LINK_STATS */
+
+        switch (htons(ethhdr->type)) {
+            /* IP or ARP packet? */
+            case ETHTYPE_IP:
+            case ETHTYPE_ARP:
+    #if LWIP_IPV6
+            /*IPv6 Packet?*/
+            case ETHTYPE_IPV6:
+    #endif
+    #if PPPOE_SUPPORT
+                /* PPPoE packet? */
+            case ETHTYPE_PPPOEDISC:
+            case ETHTYPE_PPPOE:
+    #endif /* PPPOE_SUPPORT */
+                /* full packet send to tcpip_thread to process */
+                if (netif->input(p, netif) != ERR_OK) {
+                    LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_input: IP input error\r\n"));
+                    pbuf_free(p);
+                    p = NULL;
+                }
+                break;
+
+            default:
+                pbuf_free(p);
+                p = NULL;
+                break;
+        }
+    }
+
+    return 1;
+}
+
+
+#if defined(OS_IS_FREERTOS) && defined(__arm__) && !defined(ARMR5)
+void vTimerCallback( TimerHandle_t pxTimer )
+{
+    /* Do something if the pxTimer parameter is NULL */
+    configASSERT(pxTimer);
+
+    lExpireCounter++;
+    /* If the timer has expired 100 times then reset RX */
+    if(lExpireCounter >= RESETRXTIMEOUT) {
+        lExpireCounter = 0;
+        xemacpsif_resetrx_on_no_rxdata(NetIf);
+    }
+}
+ #endif
+
+static err_t low_level_init(struct netif *netif)
+{
+    UINTPTR mac_address = (UINTPTR)(netif->state);
+    struct xemac_s *xemac;
+    xemacpsif_s *xemacpsif;
+    u32 dmacrreg;
+
+    s32_t status = XST_SUCCESS;
+
+    NetIf = netif;
+
+    xemacpsif = mem_malloc(sizeof *xemacpsif);
+    if (xemacpsif == NULL) {
+        LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_init: out of memory\r\n"));
+        return ERR_MEM;
+    }
+
+    xemac = mem_malloc(sizeof *xemac);
+    if (xemac == NULL) {
+        LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_init: out of memory\r\n"));
+        return ERR_MEM;
+    }
+
+    xemac->state = (void *)xemacpsif;
+    xemac->topology_index = xtopology_find_index(mac_address);
+    xemac->type = xemac_type_emacps;
+
+    xemacpsif->send_q = NULL;
+    xemacpsif->recv_q = pq_create_queue();
+    if (!xemacpsif->recv_q)
+        return ERR_MEM;
+
+    /* maximum transfer unit */
+#ifdef ZYNQMP_USE_JUMBO
+    netif->mtu = XEMACPS_MTU_JUMBO - XEMACPS_HDR_SIZE;
+#else
+    netif->mtu = XEMACPS_MTU - XEMACPS_HDR_SIZE;
+#endif
+
+#if LWIP_IGMP
+    netif->igmp_mac_filter = xemacpsif_mac_filter_update;
+#endif
+
+#if LWIP_IPV6 && LWIP_IPV6_MLD
+ netif->mld_mac_filter = xemacpsif_mld6_mac_filter_update;
+#endif
+
+    netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP |
+                                            NETIF_FLAG_LINK_UP;
+
+#if LWIP_IPV6 && LWIP_IPV6_MLD
+    netif->flags |= NETIF_FLAG_MLD6;
+#endif
+
+#if LWIP_IGMP
+    netif->flags |= NETIF_FLAG_IGMP;
+#endif
+
+    /* obtain config of this emac */
+    mac_config = (XEmacPs_Config *)xemacps_lookup_config((unsigned)(UINTPTR)netif->state);
+
+#if EL1_NONSECURE
+    /* Request device to indicate that this library is using it */
+    if (mac_config->BaseAddress == VERSAL_EMACPS_0_BASEADDR) {
+        Xil_Smc(PM_REQUEST_DEVICE_SMC_FID, DEV_GEM_0, 1, 0, 100, 1, 0, 0);
+    }
+    if (mac_config->BaseAddress == VERSAL_EMACPS_0_BASEADDR) {
+        Xil_Smc(PM_REQUEST_DEVICE_SMC_FID, DEV_GEM_1, 1, 0, 100, 1, 0, 0);
+    }
+#endif
+
+    status = XEmacPs_CfgInitialize(&xemacpsif->emacps, mac_config,
+                        mac_config->BaseAddress);
+    if (status != XST_SUCCESS) {
+        xil_printf("In %s:EmacPs Configuration Failed....\r\n", __func__);
+    }
+
+    /* initialize the mac */
+    init_emacps(xemacpsif, netif);
+
+    dmacrreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
+                                                        XEMACPS_DMACR_OFFSET);
+    dmacrreg = dmacrreg | (0x00000010);
+    XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
+                                            XEMACPS_DMACR_OFFSET, dmacrreg);
+
+#if defined(OS_IS_FREERTOS) && defined(__arm__) && !defined(ARMR5)
+    /* Freertos tick is 10ms by default; set period to the same */
+    xemac->xTimer = xTimerCreate("Timer", 10, pdTRUE, ( void * ) 1, vTimerCallback);
+    if (xemac->xTimer == NULL) {
+        xil_printf("In %s:Timer creation failed....\r\n", __func__);
+    } else {
+        if(xTimerStart(xemac->xTimer, 0) != pdPASS) {
+            xil_printf("In %s:Timer start failed....\r\n", __func__);
+        }
+    }
+#endif
+    setup_isr(xemac);
+    init_dma(xemac);
+    start_emacps(xemacpsif);
+
+    /* replace the state in netif (currently the emac baseaddress)
+     * with the mac instance pointer.
+     */
+    netif->state = (void *)xemac;
+
+    return ERR_OK;
+}
+
+void HandleEmacPsError(struct xemac_s *xemac)
+{
+    xemacpsif_s   *xemacpsif;
+    s32_t status = XST_SUCCESS;
+    u32 dmacrreg;
+
+    SYS_ARCH_DECL_PROTECT(lev);
+    SYS_ARCH_PROTECT(lev);
+
+    xemacpsif = (xemacpsif_s *)(xemac->state);
+    free_txrx_pbufs(xemacpsif);
+    status = XEmacPs_CfgInitialize(&xemacpsif->emacps, mac_config,
+                        mac_config->BaseAddress);
+    if (status != XST_SUCCESS) {
+        xil_printf("In %s:EmacPs Configuration Failed....\r\n", __func__);
+    }
+    /* initialize the mac */
+    init_emacps_on_error(xemacpsif, NetIf);
+    dmacrreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
+                                                        XEMACPS_DMACR_OFFSET);
+    dmacrreg = dmacrreg | (0x01000000);
+    XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
+                                            XEMACPS_DMACR_OFFSET, dmacrreg);
+    setup_isr(xemac);
+    init_dma(xemac);
+    start_emacps(xemacpsif);
+
+    SYS_ARCH_UNPROTECT(lev);
+}
+
+void HandleTxErrors(struct xemac_s *xemac)
+{
+    xemacpsif_s   *xemacpsif;
+    u32 netctrlreg;
+
+    SYS_ARCH_DECL_PROTECT(lev);
+    SYS_ARCH_PROTECT(lev);
+    xemacpsif = (xemacpsif_s *)(xemac->state);
+    netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
+                                                XEMACPS_NWCTRL_OFFSET);
+    netctrlreg = netctrlreg & (~XEMACPS_NWCTRL_TXEN_MASK);
+    XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
+                                    XEMACPS_NWCTRL_OFFSET, netctrlreg);
+    free_onlytx_pbufs(xemacpsif);
+
+    clean_dma_txdescs(xemac);
+    netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
+                                                    XEMACPS_NWCTRL_OFFSET);
+    netctrlreg = netctrlreg | (XEMACPS_NWCTRL_TXEN_MASK);
+    XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
+                                        XEMACPS_NWCTRL_OFFSET, netctrlreg);
+    SYS_ARCH_UNPROTECT(lev);
+}
+
+#if LWIP_IPV6 && LWIP_IPV6_MLD
+static u8_t xemacpsif_ip6_addr_ismulticast(ip6_addr_t* ip_addr)
+{
+    if(ip6_addr_ismulticast_linklocal(ip_addr)||
+           ip6_addr_ismulticast_iflocal(ip_addr)   ||
+           ip6_addr_ismulticast_adminlocal(ip_addr)||
+           ip6_addr_ismulticast_sitelocal(ip_addr) ||
+           ip6_addr_ismulticast_orglocal(ip_addr)  ||
+           ip6_addr_ismulticast_global(ip_addr)) {
+    /*Return TRUE if IPv6 is Multicast type*/
+    return TRUE;
+    } else {
+    return FALSE;
+    }
+}
+
+static void xemacpsif_mld6_mac_hash_update (struct netif *netif, u8_t *ip_addr,
+        u8_t action)
+{
+    u8_t multicast_mac_addr[6];
+    struct xemac_s *xemac = (struct xemac_s *) (netif->state);
+    xemacpsif_s *xemacpsif = (xemacpsif_s *) (xemac->state);
+    XEmacPs_BdRing *txring;
+    txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps));
+
+    multicast_mac_addr[0] = LL_IP6_MULTICAST_ADDR_0;
+    multicast_mac_addr[1] = LL_IP6_MULTICAST_ADDR_1;
+    multicast_mac_addr[2] = ip_addr[12];
+    multicast_mac_addr[3] = ip_addr[13];
+    multicast_mac_addr[4] = ip_addr[14];
+    multicast_mac_addr[5] = ip_addr[15];
+
+    /* Wait till all sent packets are acknowledged from HW */
+    while(txring->HwCnt);
+
+    SYS_ARCH_DECL_PROTECT(lev);
+
+    SYS_ARCH_PROTECT(lev);
+
+    /* Stop Ethernet */
+    XEmacPs_Stop(&xemacpsif->emacps);
+
+    if (action == NETIF_ADD_MAC_FILTER) {
+        /* Set Mulitcast mac address in hash table */
+        XEmacPs_SetHash(&xemacpsif->emacps, multicast_mac_addr);
+
+    } else if (action == NETIF_DEL_MAC_FILTER) {
+        /* Remove Mulitcast mac address in hash table */
+        XEmacPs_DeleteHash(&xemacpsif->emacps, multicast_mac_addr);
+    }
+
+    /* Reset DMA */
+    reset_dma(xemac);
+
+    /* Start Ethernet */
+    XEmacPs_Start(&xemacpsif->emacps);
+
+    SYS_ARCH_UNPROTECT(lev);
+}
+
+static err_t xemacpsif_mld6_mac_filter_update (struct netif *netif, ip_addr_t *group,
+        u8_t action)
+{
+    u8_t temp_mask;
+    unsigned int i;
+    u8_t * ip_addr = (u8_t *) group;
+
+    if(!(xemacpsif_ip6_addr_ismulticast((ip6_addr_t*) ip_addr))) {
+        LWIP_DEBUGF(NETIF_DEBUG,
+                                ("%s: The requested MAC address is not a multicast address.\r\n", __func__));                                 LWIP_DEBUGF(NETIF_DEBUG,
+                        ("Multicast address add operation failure !!\r\n"));
+                        return ERR_ARG;
+    }
+    if (action == NETIF_ADD_MAC_FILTER) {
+        for (i = 0; i < XEMACPS_MAX_MAC_ADDR; i++) {
+            temp_mask = (0x01) << i;
+            if ((xemacps_mld6_mcast_entry_mask & temp_mask) == temp_mask) {
+                continue;
+            }
+            xemacps_mld6_mcast_entry_mask |= temp_mask;
+
+            /* Update mac address in hash table */
+            xemacpsif_mld6_mac_hash_update(netif, ip_addr, action);
+
+            LWIP_DEBUGF(NETIF_DEBUG,
+                    ("%s: Multicast MAC address successfully added.\r\n", __func__));
+
+            return ERR_OK;
+        }
+        LWIP_DEBUGF(NETIF_DEBUG,
+                ("%s: No multicast address registers left.\r\n", __func__));
+        LWIP_DEBUGF(NETIF_DEBUG,
+                ("Multicast MAC address add operation failure !!\r\n"));
+        return ERR_MEM;
+    } else if (action == NETIF_DEL_MAC_FILTER) {
+        for (i = 0; i < XEMACPS_MAX_MAC_ADDR; i++) {
+            temp_mask = (0x01) << i;
+            if ((xemacps_mld6_mcast_entry_mask & temp_mask) != temp_mask) {
+                continue;
+            }
+            xemacps_mld6_mcast_entry_mask &= (~temp_mask);
+
+            /* Update mac address in hash table */
+            xemacpsif_mld6_mac_hash_update(netif, ip_addr, action);
+
+            LWIP_DEBUGF(NETIF_DEBUG,
+                    ("%s: Multicast MAC address successfully removed.\r\n", __func__));
+
+            return ERR_OK;
+        }
+        LWIP_DEBUGF(NETIF_DEBUG,
+                ("%s: No multicast address registers present with\r\n", __func__));
+        LWIP_DEBUGF(NETIF_DEBUG,
+                ("the requested Multicast MAC address.\r\n"));
+        LWIP_DEBUGF(NETIF_DEBUG,
+                ("Multicast MAC address removal failure!!.\r\n"));
+        return ERR_MEM;
+    }
+    return ERR_ARG;
+}
+#endif
+
+#if LWIP_IGMP
+static void xemacpsif_mac_hash_update (struct netif *netif, u8_t *ip_addr,
+        u8_t action)
+{
+    u8_t multicast_mac_addr[6];
+    struct xemac_s *xemac = (struct xemac_s *) (netif->state);
+    xemacpsif_s *xemacpsif = (xemacpsif_s *) (xemac->state);
+    XEmacPs_BdRing *txring;
+    txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps));
+
+    multicast_mac_addr[0] = 0x01;
+    multicast_mac_addr[1] = 0x00;
+    multicast_mac_addr[2] = 0x5E;
+    multicast_mac_addr[3] = ip_addr[1] & 0x7F;
+    multicast_mac_addr[4] = ip_addr[2];
+    multicast_mac_addr[5] = ip_addr[3];
+
+    /* Wait till all sent packets are acknowledged from HW */
+    while(txring->HwCnt);
+
+    SYS_ARCH_DECL_PROTECT(lev);
+
+    SYS_ARCH_PROTECT(lev);
+
+    /* Stop Ethernet */
+    XEmacPs_Stop(&xemacpsif->emacps);
+
+    if (action == IGMP_ADD_MAC_FILTER) {
+        /* Set Mulitcast mac address in hash table */
+        XEmacPs_SetHash(&xemacpsif->emacps, multicast_mac_addr);
+
+    } else if (action == IGMP_DEL_MAC_FILTER) {
+        /* Remove Mulitcast mac address in hash table */
+        XEmacPs_DeleteHash(&xemacpsif->emacps, multicast_mac_addr);
+    }
+
+    /* Reset DMA */
+    reset_dma(xemac);
+
+    /* Start Ethernet */
+    XEmacPs_Start(&xemacpsif->emacps);
+
+    SYS_ARCH_UNPROTECT(lev);
+}
+
+static err_t xemacpsif_mac_filter_update (struct netif *netif, ip_addr_t *group,
+        u8_t action)
+{
+    u8_t temp_mask;
+    unsigned int i;
+    u8_t * ip_addr = (u8_t *) group;
+
+    if ((ip_addr[0] < 224) && (ip_addr[0] > 239)) {
+        LWIP_DEBUGF(NETIF_DEBUG,
+                ("%s: The requested MAC address is not a multicast address.\r\n", __func__));
+        LWIP_DEBUGF(NETIF_DEBUG,
+                ("Multicast address add operation failure !!\r\n"));
+
+        return ERR_ARG;
+    }
+
+    if (action == IGMP_ADD_MAC_FILTER) {
+
+        for (i = 0; i < XEMACPS_MAX_MAC_ADDR; i++) {
+            temp_mask = (0x01) << i;
+            if ((xemacps_mcast_entry_mask & temp_mask) == temp_mask) {
+                continue;
+            }
+            xemacps_mcast_entry_mask |= temp_mask;
+
+            /* Update mac address in hash table */
+            xemacpsif_mac_hash_update(netif, ip_addr, action);
+
+            LWIP_DEBUGF(NETIF_DEBUG,
+                    ("%s: Multicast MAC address successfully added.\r\n", __func__));
+
+            return ERR_OK;
+        }
+        if (i == XEMACPS_MAX_MAC_ADDR) {
+            LWIP_DEBUGF(NETIF_DEBUG,
+                    ("%s: No multicast address registers left.\r\n", __func__));
+            LWIP_DEBUGF(NETIF_DEBUG,
+                    ("Multicast MAC address add operation failure !!\r\n"));
+
+            return ERR_MEM;
+        }
+    } else if (action == IGMP_DEL_MAC_FILTER) {
+        for (i = 0; i < XEMACPS_MAX_MAC_ADDR; i++) {
+            temp_mask = (0x01) << i;
+            if ((xemacps_mcast_entry_mask & temp_mask) != temp_mask) {
+                continue;
+            }
+            xemacps_mcast_entry_mask &= (~temp_mask);
+
+            /* Update mac address in hash table */
+            xemacpsif_mac_hash_update(netif, ip_addr, action);
+
+            LWIP_DEBUGF(NETIF_DEBUG,
+                    ("%s: Multicast MAC address successfully removed.\r\n", __func__));
+
+            return ERR_OK;
+        }
+        if (i == XEMACPS_MAX_MAC_ADDR) {
+            LWIP_DEBUGF(NETIF_DEBUG,
+                    ("%s: No multicast address registers present with\r\n", __func__));
+            LWIP_DEBUGF(NETIF_DEBUG,
+                    ("the requested Multicast MAC address.\r\n"));
+            LWIP_DEBUGF(NETIF_DEBUG,
+                    ("Multicast MAC address removal failure!!.\r\n"));
+
+            return ERR_MEM;
+        }
+    }
+    return ERR_OK;
+}
+#endif
+
+/*
+ * xemacpsif_init():
+ *
+ * Should be called at the beginning of the program to set up the
+ * network interface. It calls the function low_level_init() to do the
+ * actual setup of the hardware.
+ *
+ */
+
+err_t xemacpsif_init(struct netif *netif)
+{
+#if LWIP_SNMP
+    /* ifType ethernetCsmacd(6) @see RFC1213 */
+    netif->link_type = 6;
+    /* your link speed here */
+    netif->link_speed = ;
+    netif->ts = 0;
+    netif->ifinoctets = 0;
+    netif->ifinucastpkts = 0;
+    netif->ifinnucastpkts = 0;
+    netif->ifindiscards = 0;
+    netif->ifoutoctets = 0;
+    netif->ifoutucastpkts = 0;
+    netif->ifoutnucastpkts = 0;
+    netif->ifoutdiscards = 0;
+#endif
+
+    netif->name[0] = IFNAME0;
+    netif->name[1] = IFNAME1;
+    netif->output = xemacpsif_output;
+    netif->linkoutput = low_level_output;
+#if LWIP_IPV6
+    netif->output_ip6 = ethip6_output;
+#endif
+
+    low_level_init(netif);
+    return ERR_OK;
+}
+
+/*
+ * xemacpsif_resetrx_on_no_rxdata():
+ *
+ * Should be called by the user at regular intervals, typically
+ * from a timer (100 msecond). This is to provide a SW workaround
+ * for the HW bug (SI #692601). Please refer to the function header
+ * for the function resetrx_on_no_rxdata in xemacpsif_dma.c to
+ * know more about the SI.
+ *
+ */
+
+void xemacpsif_resetrx_on_no_rxdata(struct netif *netif)
+{
+    struct xemac_s *xemac = (struct xemac_s *)(netif->state);
+    xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
+
+    resetrx_on_no_rxdata(xemacpsif);
+}

+ 869 - 0
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_dma.c

@@ -0,0 +1,869 @@
+/*
+ * Copyright (C) 2010 - 2019 Xilinx, Inc.
+ * Copyright (C) 2021 WangHuachen.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ */
+
+#include "lwipopts.h"
+#include "lwip/stats.h"
+#include "lwip/sys.h"
+#include "lwip/inet_chksum.h"
+
+#include "netif/xadapter.h"
+#include "netif/xemacpsif.h"
+#include "xstatus.h"
+
+#include "xlwipconfig.h"
+#include "xparameters.h"
+#include "xparameters_ps.h"
+// #include "xil_exception.h"
+#include "xil_mmu.h"
+#if defined (ARMR5)
+#include "xreg_cortexr5.h"
+#endif
+#ifdef CONFIG_XTRACE
+#include "xtrace.h"
+#endif
+#ifdef OS_IS_FREERTOS
+#include "FreeRTOS.h"
+#include "semphr.h"
+#include "timers.h"
+#endif
+
+#include <stdio.h>
+
+#define INTC_BASE_ADDR        XPAR_SCUGIC_0_CPU_BASEADDR
+#define INTC_DIST_BASE_ADDR    XPAR_SCUGIC_0_DIST_BASEADDR
+
+/* Byte alignment of BDs */
+#define BD_ALIGNMENT (XEMACPS_DMABD_MINIMUM_ALIGNMENT*2)
+
+/* A max of 4 different ethernet interfaces are supported */
+static UINTPTR tx_pbufs_storage[4*XLWIP_CONFIG_N_TX_DESC];
+static UINTPTR rx_pbufs_storage[4*XLWIP_CONFIG_N_RX_DESC];
+
+static s32_t emac_intr_num;
+
+/******************************************************************************
+ * Each BD is of 8 bytes of size and the BDs (BD chain) need to be  put
+ * at uncached memory location. If they are not put at uncached
+ * locations, the user needs to flush or invalidate for each BD/packet.
+ * However, the flush or invalidate can happen over a cache line which can
+ * span multiple BDs. This means a flush or invalidate of one BD can actually
+ * flush/invalidate multiple BDs adjacent to the targeted BD.Assuming that
+ * the user and hardware both update the BD fields, this operation from user
+ * can potentially overwrite the updates done by hardware or user.
+ * To avoid this, it is always safe to put the BD chains for Rx and tx side
+ * at uncached memory location.
+ *
+ * The Xilinx standalone BSP for Cortex A9 implements only primary page tables.
+ * Each table entry corresponds to 1 MB of address map. This means, if a memory
+ * region has to be made uncached, the minimum granularity will be of 1 MB.
+ *
+ * The implementation below allocates a 1 MB of u8 array aligned to 1 MB.
+ * This ensures that this array is put at 1 MB aligned memory (e.g. 0x1200000)
+ * and accupies memory of 1 MB. The init_dma function then changes 1 MB of this
+ * region to make it uncached (strongly ordered).
+ * This increases the bss section of the program significantly and can be a
+ * wastage of memory. The reason beings, BDs will hardly occupy few KBs of
+ * memory and the rest of 1 MB of memory will be unused.
+ *
+ * If a program uses other peripherals that have DMAs/bus masters and need
+ * uncached memory, they may also end of following the same approach. This
+ * definitely aggravates the memory wastage issue. To avoid all this, the user
+ * can create a new 1 MB section in the linker script and reserve it for such
+ * use cases that need uncached memory location. They can then have their own
+ * memory allocation logic in their application that allocates uncached memory
+ * from this 1 MB location. For such a case, changes need to be done in this
+ * file and appropriate uncached memory allocated through other means can be
+ * used.
+ *
+ * The present implementation here allocates 1 MB of uncached memory. It
+ * reserves of 64 KB of memory for each BD chain. 64 KB of memory means 8192 of
+ * BDs for each BD chain which is more than enough for any application.
+ * Assuming that both emac0 and emac1 are present, 256 KB of memory is allocated
+ * for BDs. The rest 768 KB of memory is just unused.
+ *********************************************************************************/
+
+#if defined __aarch64__
+u8_t bd_space[0x200000] __attribute__ ((aligned (0x200000)));
+#else
+u8_t bd_space[0x100000] __attribute__ ((aligned (0x100000)));
+#endif
+static volatile u32_t bd_space_index = 0;
+static volatile u32_t bd_space_attr_set = 0;
+
+#ifdef OS_IS_FREERTOS
+long xInsideISR = 0;
+#endif
+
+#define XEMACPS_BD_TO_INDEX(ringptr, bdptr)                \
+    (((UINTPTR)bdptr - (UINTPTR)(ringptr)->BaseBdAddr) / (ringptr)->Separation)
+
+
+s32_t is_tx_space_available(xemacpsif_s *emac)
+{
+    XEmacPs_BdRing *txring;
+    s32_t freecnt = 0;
+
+    txring = &(XEmacPs_GetTxRing(&emac->emacps));
+
+    /* tx space is available as long as there are valid BD's */
+    freecnt = XEmacPs_BdRingGetFreeCnt(txring);
+    return freecnt;
+}
+
+
+static inline
+u32_t get_base_index_txpbufsstorage (xemacpsif_s *xemacpsif)
+{
+    u32_t index;
+#ifdef XPAR_XEMACPS_0_BASEADDR
+    if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) {
+        index = 0;
+    }
+#endif
+#ifdef XPAR_XEMACPS_1_BASEADDR
+    if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_1_BASEADDR) {
+        index = XLWIP_CONFIG_N_TX_DESC;
+    }
+#endif
+#ifdef XPAR_XEMACPS_2_BASEADDR
+    if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_2_BASEADDR) {
+        index = 2 * XLWIP_CONFIG_N_TX_DESC;
+    }
+#endif
+#ifdef XPAR_XEMACPS_3_BASEADDR
+    if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_3_BASEADDR) {
+        index = 3 * XLWIP_CONFIG_N_TX_DESC;
+    }
+#endif
+    return index;
+}
+
+static inline
+u32_t get_base_index_rxpbufsstorage (xemacpsif_s *xemacpsif)
+{
+    u32_t index;
+#ifdef XPAR_XEMACPS_0_BASEADDR
+    if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) {
+        index = 0;
+    }
+#endif
+#ifdef XPAR_XEMACPS_1_BASEADDR
+    if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_1_BASEADDR) {
+        index = XLWIP_CONFIG_N_RX_DESC;
+    }
+#endif
+#ifdef XPAR_XEMACPS_2_BASEADDR
+    if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_2_BASEADDR) {
+        index = 2 * XLWIP_CONFIG_N_RX_DESC;
+    }
+#endif
+#ifdef XPAR_XEMACPS_3_BASEADDR
+    if (xemacpsif->emacps.Config.BaseAddress == XPAR_XEMACPS_3_BASEADDR) {
+        index = 3 * XLWIP_CONFIG_N_RX_DESC;
+    }
+#endif
+    return index;
+}
+
+void process_sent_bds(xemacpsif_s *xemacpsif, XEmacPs_BdRing *txring)
+{
+    XEmacPs_Bd *txbdset;
+    XEmacPs_Bd *curbdpntr;
+    s32_t n_bds;
+    XStatus status;
+    s32_t n_pbufs_freed = 0;
+    u32_t bdindex;
+    struct pbuf *p;
+    u32 *temp;
+    u32_t index;
+
+    index = get_base_index_txpbufsstorage (xemacpsif);
+
+    while (1) {
+        /* obtain processed BD's */
+        n_bds = XEmacPs_BdRingFromHwTx(txring,
+                                XLWIP_CONFIG_N_TX_DESC, &txbdset);
+        if (n_bds == 0)  {
+            return;
+        }
+        /* free the processed BD's */
+        n_pbufs_freed = n_bds;
+        curbdpntr = txbdset;
+        while (n_pbufs_freed > 0) {
+            bdindex = XEMACPS_BD_TO_INDEX(txring, curbdpntr);
+            temp = (u32 *)curbdpntr;
+            *temp = 0;
+            temp++;
+            if (bdindex == (XLWIP_CONFIG_N_TX_DESC - 1)) {
+                *temp = 0xC0000000;
+            } else {
+                *temp = 0x80000000;
+            }
+            dsb();
+            p = (struct pbuf *)tx_pbufs_storage[index + bdindex];
+            if (p != NULL) {
+                pbuf_free(p);
+            }
+            tx_pbufs_storage[index + bdindex] = 0;
+            curbdpntr = XEmacPs_BdRingNext(txring, curbdpntr);
+            n_pbufs_freed--;
+            dsb();
+        }
+
+        status = XEmacPs_BdRingFree(txring, n_bds, txbdset);
+        if (status != XST_SUCCESS) {
+            LWIP_DEBUGF(NETIF_DEBUG, ("Failure while freeing in Tx Done ISR\r\n"));
+        }
+    }
+    return;
+}
+
+void emacps_send_handler(void *arg)
+{
+    struct xemac_s *xemac;
+    xemacpsif_s   *xemacpsif;
+    XEmacPs_BdRing *txringptr;
+    u32_t regval;
+#ifdef OS_IS_FREERTOS
+    xInsideISR++;
+#endif
+    xemac = (struct xemac_s *)(arg);
+    xemacpsif = (xemacpsif_s *)(xemac->state);
+    txringptr = &(XEmacPs_GetTxRing(&xemacpsif->emacps));
+    regval = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_TXSR_OFFSET);
+    XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,XEMACPS_TXSR_OFFSET, regval);
+
+    /* If Transmit done interrupt is asserted, process completed BD's */
+    /* Since RT-Thread does not support freeing memory in interrupts, comment it out */
+    // process_sent_bds(xemacpsif, txringptr);
+#ifdef OS_IS_FREERTOS
+    xInsideISR--;
+#endif
+}
+
+XStatus emacps_sgsend(xemacpsif_s *xemacpsif, struct pbuf *p)
+{
+    struct pbuf *q;
+    s32_t n_pbufs;
+    XEmacPs_Bd *txbdset, *txbd, *last_txbd = NULL;
+    XEmacPs_Bd *temp_txbd;
+    XStatus status;
+    XEmacPs_BdRing *txring;
+    u32_t bdindex;
+    u32_t lev;
+    u32_t index;
+    u32_t max_fr_size;
+
+    lev = mfcpsr();
+    mtcpsr(lev | 0x000000C0);
+
+    txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps));
+
+    index = get_base_index_txpbufsstorage (xemacpsif);
+
+    /* first count the number of pbufs */
+    for (q = p, n_pbufs = 0; q != NULL; q = q->next)
+        n_pbufs++;
+
+    /* obtain as many BD's */
+    status = XEmacPs_BdRingAlloc(txring, n_pbufs, &txbdset);
+    if (status != XST_SUCCESS) {
+        mtcpsr(lev);
+        LWIP_DEBUGF(NETIF_DEBUG, ("sgsend: Error allocating TxBD\r\n"));
+        return XST_FAILURE;
+    }
+
+    for(q = p, txbd = txbdset; q != NULL; q = q->next) {
+        bdindex = XEMACPS_BD_TO_INDEX(txring, txbd);
+        if (tx_pbufs_storage[index + bdindex] != 0) {
+            mtcpsr(lev);
+            LWIP_DEBUGF(NETIF_DEBUG, ("PBUFS not available\r\n"));
+            return XST_FAILURE;
+        }
+
+        /* Send the data from the pbuf to the interface, one pbuf at a
+           time. The size of the data in each pbuf is kept in the ->len
+           variable. */
+        if (xemacpsif->emacps.Config.IsCacheCoherent == 0) {
+            Xil_DCacheFlushRange((UINTPTR)q->payload, (UINTPTR)q->len);
+        }
+
+        XEmacPs_BdSetAddressTx(txbd, (UINTPTR)q->payload);
+
+#ifdef ZYNQMP_USE_JUMBO
+        max_fr_size = MAX_FRAME_SIZE_JUMBO - 18;
+#else
+        max_fr_size = XEMACPS_MAX_FRAME_SIZE - 18;
+#endif
+        if (q->len > max_fr_size)
+            XEmacPs_BdSetLength(txbd, max_fr_size & 0x3FFF);
+        else
+            XEmacPs_BdSetLength(txbd, q->len & 0x3FFF);
+
+        tx_pbufs_storage[index + bdindex] = (UINTPTR)q;
+
+        pbuf_ref(q);
+        last_txbd = txbd;
+        XEmacPs_BdClearLast(txbd);
+        txbd = XEmacPs_BdRingNext(txring, txbd);
+    }
+    XEmacPs_BdSetLast(last_txbd);
+    /* For fragmented packets, remember the 1st BD allocated for the 1st
+       packet fragment. The used bit for this BD should be cleared at the end
+       after clearing out used bits for other fragments. For packets without
+       just remember the allocated BD. */
+    temp_txbd = txbdset;
+    txbd = txbdset;
+    txbd = XEmacPs_BdRingNext(txring, txbd);
+    q = p->next;
+    for(; q != NULL; q = q->next) {
+        XEmacPs_BdClearTxUsed(txbd);
+        dsb();
+        txbd = XEmacPs_BdRingNext(txring, txbd);
+    }
+    XEmacPs_BdClearTxUsed(temp_txbd);
+    dsb();
+
+    status = XEmacPs_BdRingToHw(txring, n_pbufs, txbdset);
+    if (status != XST_SUCCESS) {
+        mtcpsr(lev);
+        LWIP_DEBUGF(NETIF_DEBUG, ("sgsend: Error submitting TxBD\r\n"));
+        return XST_FAILURE;
+    }
+    /* Start transmit */
+    XEmacPs_WriteReg((xemacpsif->emacps).Config.BaseAddress,
+    XEMACPS_NWCTRL_OFFSET,
+    (XEmacPs_ReadReg((xemacpsif->emacps).Config.BaseAddress,
+    XEMACPS_NWCTRL_OFFSET) | XEMACPS_NWCTRL_STARTTX_MASK));
+
+    mtcpsr(lev);
+    return status;
+}
+
+void setup_rx_bds(xemacpsif_s *xemacpsif, XEmacPs_BdRing *rxring)
+{
+    XEmacPs_Bd *rxbd;
+    XStatus status;
+    struct pbuf *p;
+    u32_t freebds;
+    u32_t bdindex;
+    u32 *temp;
+    u32_t index;
+
+    index = get_base_index_rxpbufsstorage (xemacpsif);
+
+    freebds = XEmacPs_BdRingGetFreeCnt (rxring);
+    while (freebds > 0) {
+        freebds--;
+#ifdef ZYNQMP_USE_JUMBO
+        p = pbuf_alloc(PBUF_RAW, MAX_FRAME_SIZE_JUMBO, PBUF_POOL);
+#else
+        p = pbuf_alloc(PBUF_RAW, XEMACPS_MAX_FRAME_SIZE, PBUF_POOL);
+#endif
+        if (!p) {
+#if LINK_STATS
+            lwip_stats.link.memerr++;
+            lwip_stats.link.drop++;
+#endif
+            rt_kprintf("unable to alloc pbuf in recv_handler\r\n");
+            return;
+        }
+        status = XEmacPs_BdRingAlloc(rxring, 1, &rxbd);
+        if (status != XST_SUCCESS) {
+            LWIP_DEBUGF(NETIF_DEBUG, ("setup_rx_bds: Error allocating RxBD\r\n"));
+            pbuf_free(p);
+            return;
+        }
+        status = XEmacPs_BdRingToHw(rxring, 1, rxbd);
+        if (status != XST_SUCCESS) {
+            LWIP_DEBUGF(NETIF_DEBUG, ("Error committing RxBD to hardware: "));
+            if (status == XST_DMA_SG_LIST_ERROR) {
+                LWIP_DEBUGF(NETIF_DEBUG, ("XST_DMA_SG_LIST_ERROR: this function was called out of sequence with XEmacPs_BdRingAlloc()\r\n"));
+            }
+            else {
+                LWIP_DEBUGF(NETIF_DEBUG, ("set of BDs was rejected because the first BD did not have its start-of-packet bit set, or the last BD did not have its end-of-packet bit set, or any one of the BD set has 0 as length value\r\n"));
+            }
+
+            pbuf_free(p);
+            XEmacPs_BdRingUnAlloc(rxring, 1, rxbd);
+            return;
+        }
+#ifdef ZYNQMP_USE_JUMBO
+        if (xemacpsif->emacps.Config.IsCacheCoherent == 0) {
+            Xil_DCacheInvalidateRange((UINTPTR)p->payload, (UINTPTR)MAX_FRAME_SIZE_JUMBO);
+        }
+#else
+        if (xemacpsif->emacps.Config.IsCacheCoherent == 0) {
+            Xil_DCacheInvalidateRange((UINTPTR)p->payload, (UINTPTR)XEMACPS_MAX_FRAME_SIZE);
+        }
+#endif
+        bdindex = XEMACPS_BD_TO_INDEX(rxring, rxbd);
+        temp = (u32 *)rxbd;
+        if (bdindex == (XLWIP_CONFIG_N_RX_DESC - 1)) {
+            *temp = 0x00000002;
+        } else {
+            *temp = 0;
+        }
+        temp++;
+        *temp = 0;
+        dsb();
+
+        XEmacPs_BdSetAddressRx(rxbd, (UINTPTR)p->payload);
+        rx_pbufs_storage[index + bdindex] = (UINTPTR)p;
+    }
+}
+
+void emacps_recv_handler(void *arg)
+{
+    struct pbuf *p;
+    XEmacPs_Bd *rxbdset, *curbdptr;
+    struct xemac_s *xemac;
+    xemacpsif_s *xemacpsif;
+    XEmacPs_BdRing *rxring;
+    volatile s32_t bd_processed;
+    s32_t rx_bytes, k;
+    u32_t bdindex;
+    u32_t regval;
+    u32_t index;
+    u32_t gigeversion;
+
+    xemac = (struct xemac_s *)(arg);
+    xemacpsif = (xemacpsif_s *)(xemac->state);
+    rxring = &XEmacPs_GetRxRing(&xemacpsif->emacps);
+
+#ifdef OS_IS_FREERTOS
+    xInsideISR++;
+#endif
+
+    gigeversion = ((Xil_In32(xemacpsif->emacps.Config.BaseAddress + 0xFC)) >> 16) & 0xFFF;
+    index = get_base_index_rxpbufsstorage (xemacpsif);
+    /*
+     * If Reception done interrupt is asserted, call RX call back function
+     * to handle the processed BDs and then raise the according flag.
+     */
+    regval = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXSR_OFFSET);
+    XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXSR_OFFSET, regval);
+    if (gigeversion <= 2) {
+            resetrx_on_no_rxdata(xemacpsif);
+    }
+
+    while(1) {
+
+        bd_processed = XEmacPs_BdRingFromHwRx(rxring, XLWIP_CONFIG_N_RX_DESC, &rxbdset);
+        if (bd_processed <= 0) {
+            break;
+        }
+        for (k = 0, curbdptr=rxbdset; k < bd_processed; k++) {
+
+            bdindex = XEMACPS_BD_TO_INDEX(rxring, curbdptr);
+            p = (struct pbuf *)rx_pbufs_storage[index + bdindex];
+            /*
+             * Adjust the buffer size to the actual number of bytes received.
+             */
+#ifdef ZYNQMP_USE_JUMBO
+            rx_bytes = XEmacPs_GetRxFrameSize(&xemacpsif->emacps, curbdptr);
+#else
+            rx_bytes = XEmacPs_BdGetLength(curbdptr);
+#endif
+            pbuf_realloc(p, rx_bytes);
+            /* Invalidate RX frame before queuing to handle
+             * L1 cache prefetch conditions on any architecture.
+             */
+            Xil_DCacheInvalidateRange((UINTPTR)p->payload, rx_bytes);
+            /* store it in the receive queue,
+             * where it'll be processed by a different handler
+             */
+            if (pq_enqueue(xemacpsif->recv_q, (void*)p) < 0) {
+#if LINK_STATS
+                lwip_stats.link.memerr++;
+                lwip_stats.link.drop++;
+#endif
+                pbuf_free(p);
+            }
+            curbdptr = XEmacPs_BdRingNext( rxring, curbdptr);
+        }
+        /* free up the BD's */
+        XEmacPs_BdRingFree(rxring, bd_processed, rxbdset);
+        setup_rx_bds(xemacpsif, rxring);
+        eth_device_ready(xemac->rt_eth_device);
+    }
+
+#ifdef OS_IS_FREERTOS
+    xInsideISR--;
+#endif
+    return;
+}
+
+void clean_dma_txdescs(struct xemac_s *xemac)
+{
+    XEmacPs_Bd bdtemplate;
+    XEmacPs_BdRing *txringptr;
+    xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
+
+    txringptr = &XEmacPs_GetTxRing(&xemacpsif->emacps);
+
+    XEmacPs_BdClear(&bdtemplate);
+    XEmacPs_BdSetStatus(&bdtemplate, XEMACPS_TXBUF_USED_MASK);
+
+    /*
+     * Create the TxBD ring
+     */
+    XEmacPs_BdRingCreate(txringptr, (UINTPTR) xemacpsif->tx_bdspace,
+            (UINTPTR) xemacpsif->tx_bdspace, BD_ALIGNMENT,
+                 XLWIP_CONFIG_N_TX_DESC);
+    XEmacPs_BdRingClone(txringptr, &bdtemplate, XEMACPS_SEND);
+}
+
+XStatus init_dma(struct xemac_s *xemac)
+{
+    XEmacPs_Bd bdtemplate;
+    XEmacPs_BdRing *rxringptr, *txringptr;
+    XEmacPs_Bd *rxbd;
+    struct pbuf *p;
+    XStatus status;
+    s32_t i;
+    u32_t bdindex;
+    volatile UINTPTR tempaddress;
+    u32_t index;
+    u32_t gigeversion;
+    XEmacPs_Bd *bdtxterminate;
+    XEmacPs_Bd *bdrxterminate;
+    u32 *temp;
+
+    xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
+    struct xtopology_t *xtopologyp = &xtopology[xemac->topology_index];
+
+    index = get_base_index_rxpbufsstorage (xemacpsif);
+    gigeversion = ((Xil_In32(xemacpsif->emacps.Config.BaseAddress + 0xFC)) >> 16) & 0xFFF;
+    /*
+     * The BDs need to be allocated in uncached memory. Hence the 1 MB
+     * address range allocated for Bd_Space is made uncached
+     * by setting appropriate attributes in the translation table.
+     * The Bd_Space is aligned to 1MB and has a size of 1 MB. This ensures
+     * a reserved uncached area used only for BDs.
+     */
+    if (bd_space_attr_set == 0) {
+#if defined (ARMR5)
+    Xil_SetTlbAttributes((s32_t)bd_space, STRONG_ORDERD_SHARED | PRIV_RW_USER_RW); // addr, attr
+#else
+#if defined __aarch64__
+    Xil_SetTlbAttributes((u64)bd_space, NORM_NONCACHE | INNER_SHAREABLE);
+#else
+    Xil_SetTlbAttributes((s32_t)bd_space, DEVICE_MEMORY); // addr, attr
+#endif
+#endif
+        bd_space_attr_set = 1;
+    }
+
+    rxringptr = &XEmacPs_GetRxRing(&xemacpsif->emacps);
+    txringptr = &XEmacPs_GetTxRing(&xemacpsif->emacps);
+    LWIP_DEBUGF(NETIF_DEBUG, ("rxringptr: 0x%08x\r\n", rxringptr));
+    LWIP_DEBUGF(NETIF_DEBUG, ("txringptr: 0x%08x\r\n", txringptr));
+
+    /* Allocate 64k for Rx and Tx bds each to take care of extreme cases */
+    tempaddress = (UINTPTR)&(bd_space[bd_space_index]);
+    xemacpsif->rx_bdspace = (void *)tempaddress;
+    bd_space_index += 0x10000;
+    tempaddress = (UINTPTR)&(bd_space[bd_space_index]);
+    xemacpsif->tx_bdspace = (void *)tempaddress;
+    bd_space_index += 0x10000;
+    if (gigeversion > 2) {
+        tempaddress = (UINTPTR)&(bd_space[bd_space_index]);
+        bdrxterminate = (XEmacPs_Bd *)tempaddress;
+        bd_space_index += 0x10000;
+        tempaddress = (UINTPTR)&(bd_space[bd_space_index]);
+        bdtxterminate = (XEmacPs_Bd *)tempaddress;
+        bd_space_index += 0x10000;
+    }
+
+    LWIP_DEBUGF(NETIF_DEBUG, ("rx_bdspace: %p \r\n", xemacpsif->rx_bdspace));
+    LWIP_DEBUGF(NETIF_DEBUG, ("tx_bdspace: %p \r\n", xemacpsif->tx_bdspace));
+
+    if (!xemacpsif->rx_bdspace || !xemacpsif->tx_bdspace) {
+        xil_printf("%s@%d: Error: Unable to allocate memory for TX/RX buffer descriptors",
+                __FILE__, __LINE__);
+        return ERR_IF;
+    }
+
+    /*
+     * Setup RxBD space.
+     *
+     * Setup a BD template for the Rx channel. This template will be copied to
+     * every RxBD. We will not have to explicitly set these again.
+     */
+    XEmacPs_BdClear(&bdtemplate);
+
+    /*
+     * Create the RxBD ring
+     */
+
+    status = XEmacPs_BdRingCreate(rxringptr, (UINTPTR) xemacpsif->rx_bdspace,
+                (UINTPTR) xemacpsif->rx_bdspace, BD_ALIGNMENT,
+                     XLWIP_CONFIG_N_RX_DESC);
+
+    if (status != XST_SUCCESS) {
+        LWIP_DEBUGF(NETIF_DEBUG, ("Error setting up RxBD space\r\n"));
+        return ERR_IF;
+    }
+
+    status = XEmacPs_BdRingClone(rxringptr, &bdtemplate, XEMACPS_RECV);
+    if (status != XST_SUCCESS) {
+        LWIP_DEBUGF(NETIF_DEBUG, ("Error initializing RxBD space\r\n"));
+        return ERR_IF;
+    }
+
+    XEmacPs_BdClear(&bdtemplate);
+    XEmacPs_BdSetStatus(&bdtemplate, XEMACPS_TXBUF_USED_MASK);
+    /*
+     * Create the TxBD ring
+     */
+    status = XEmacPs_BdRingCreate(txringptr, (UINTPTR) xemacpsif->tx_bdspace,
+                (UINTPTR) xemacpsif->tx_bdspace, BD_ALIGNMENT,
+                     XLWIP_CONFIG_N_TX_DESC);
+
+    if (status != XST_SUCCESS) {
+        return ERR_IF;
+    }
+
+    /* We reuse the bd template, as the same one will work for both rx and tx. */
+    status = XEmacPs_BdRingClone(txringptr, &bdtemplate, XEMACPS_SEND);
+    if (status != XST_SUCCESS) {
+        return ERR_IF;
+    }
+
+    /*
+     * Allocate RX descriptors, 1 RxBD at a time.
+     */
+    for (i = 0; i < XLWIP_CONFIG_N_RX_DESC; i++) {
+#ifdef ZYNQMP_USE_JUMBO
+        p = pbuf_alloc(PBUF_RAW, MAX_FRAME_SIZE_JUMBO, PBUF_POOL);
+#else
+        p = pbuf_alloc(PBUF_RAW, XEMACPS_MAX_FRAME_SIZE, PBUF_POOL);
+#endif
+        if (!p) {
+#if LINK_STATS
+            lwip_stats.link.memerr++;
+            lwip_stats.link.drop++;
+#endif
+            rt_kprintf("unable to alloc pbuf in init_dma\r\n");
+            return ERR_IF;
+        }
+        status = XEmacPs_BdRingAlloc(rxringptr, 1, &rxbd);
+        if (status != XST_SUCCESS) {
+            LWIP_DEBUGF(NETIF_DEBUG, ("init_dma: Error allocating RxBD\r\n"));
+            pbuf_free(p);
+            return ERR_IF;
+        }
+        /* Enqueue to HW */
+        status = XEmacPs_BdRingToHw(rxringptr, 1, rxbd);
+        if (status != XST_SUCCESS) {
+            LWIP_DEBUGF(NETIF_DEBUG, ("Error: committing RxBD to HW\r\n"));
+            pbuf_free(p);
+            XEmacPs_BdRingUnAlloc(rxringptr, 1, rxbd);
+            return ERR_IF;
+        }
+
+        bdindex = XEMACPS_BD_TO_INDEX(rxringptr, rxbd);
+        temp = (u32 *)rxbd;
+        *temp = 0;
+        if (bdindex == (XLWIP_CONFIG_N_RX_DESC - 1)) {
+            *temp = 0x00000002;
+        }
+        temp++;
+        *temp = 0;
+        dsb();
+#ifdef ZYNQMP_USE_JUMBO
+        if (xemacpsif->emacps.Config.IsCacheCoherent == 0) {
+            Xil_DCacheInvalidateRange((UINTPTR)p->payload, (UINTPTR)MAX_FRAME_SIZE_JUMBO);
+        }
+#else
+        if (xemacpsif->emacps.Config.IsCacheCoherent == 0) {
+            Xil_DCacheInvalidateRange((UINTPTR)p->payload, (UINTPTR)XEMACPS_MAX_FRAME_SIZE);
+        }
+#endif
+        XEmacPs_BdSetAddressRx(rxbd, (UINTPTR)p->payload);
+
+        rx_pbufs_storage[index + bdindex] = (UINTPTR)p;
+    }
+    XEmacPs_SetQueuePtr(&(xemacpsif->emacps), xemacpsif->emacps.RxBdRing.BaseBdAddr, 0, XEMACPS_RECV);
+    if (gigeversion > 2) {
+        XEmacPs_SetQueuePtr(&(xemacpsif->emacps), xemacpsif->emacps.TxBdRing.BaseBdAddr, 1, XEMACPS_SEND);
+    }else {
+        XEmacPs_SetQueuePtr(&(xemacpsif->emacps), xemacpsif->emacps.TxBdRing.BaseBdAddr, 0, XEMACPS_SEND);
+    }
+    if (gigeversion > 2)
+    {
+        /*
+         * This version of GEM supports priority queuing and the current
+         * driver is using tx priority queue 1 and normal rx queue for
+         * packet transmit and receive. The below code ensure that the
+         * other queue pointers are parked to known state for avoiding
+         * the controller to malfunction by fetching the descriptors
+         * from these queues.
+         */
+        XEmacPs_BdClear(bdrxterminate);
+        XEmacPs_BdSetAddressRx(bdrxterminate, (XEMACPS_RXBUF_NEW_MASK |
+                        XEMACPS_RXBUF_WRAP_MASK));
+        XEmacPs_Out32((xemacpsif->emacps.Config.BaseAddress + XEMACPS_RXQ1BASE_OFFSET),
+                   (UINTPTR)bdrxterminate);
+        XEmacPs_BdClear(bdtxterminate);
+        XEmacPs_BdSetStatus(bdtxterminate, (XEMACPS_TXBUF_USED_MASK |
+                        XEMACPS_TXBUF_WRAP_MASK));
+        XEmacPs_Out32((xemacpsif->emacps.Config.BaseAddress + XEMACPS_TXQBASE_OFFSET),
+                   (UINTPTR)bdtxterminate);
+    }
+
+    /*
+     * Connect the device driver handler that will be called when an
+     * interrupt for the device occurs, the handler defined above performs
+     * the specific interrupt processing for the device.
+     */
+    // XScuGic_RegisterHandler(INTC_BASE_ADDR, xtopologyp->scugic_emac_intr,
+    //             (Xil_ExceptionHandler)XEmacPs_IntrHandler,
+    //                     (void *)&xemacpsif->emacps);
+    /*
+     * Enable the interrupt for emacps.
+     */
+    // XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, (u32) xtopologyp->scugic_emac_intr);
+    emac_intr_num = (u32) xtopologyp->scugic_emac_intr;
+    return 0;
+}
+
+/*
+ * resetrx_on_no_rxdata():
+ *
+ * It is called at regular intervals through the API xemacpsif_resetrx_on_no_rxdata
+ * called by the user.
+ * The EmacPs has a HW bug (SI# 692601) on the Rx path for heavy Rx traffic.
+ * Under heavy Rx traffic because of the HW bug there are times when the Rx path
+ * becomes unresponsive. The workaround for it is to check for the Rx path for
+ * traffic (by reading the stats registers regularly). If the stats register
+ * does not increment for sometime (proving no Rx traffic), the function resets
+ * the Rx data path.
+ *
+ */
+
+void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif)
+{
+    u32_t regctrl;
+    u32_t tempcntr;
+    u32_t gigeversion;
+
+    gigeversion = ((Xil_In32(xemacpsif->emacps.Config.BaseAddress + 0xFC)) >> 16) & 0xFFF;
+    if (gigeversion == 2) {
+        tempcntr = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXCNT_OFFSET);
+        if ((!tempcntr) && (!(xemacpsif->last_rx_frms_cntr))) {
+            regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
+                    XEMACPS_NWCTRL_OFFSET);
+            regctrl &= (~XEMACPS_NWCTRL_RXEN_MASK);
+            XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
+                    XEMACPS_NWCTRL_OFFSET, regctrl);
+            regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET);
+            regctrl |= (XEMACPS_NWCTRL_RXEN_MASK);
+            XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, regctrl);
+        }
+        xemacpsif->last_rx_frms_cntr = tempcntr;
+    }
+}
+
+void free_txrx_pbufs(xemacpsif_s *xemacpsif)
+{
+    s32_t index;
+    s32_t index1;
+    struct pbuf *p;
+
+    index1 = get_base_index_txpbufsstorage (xemacpsif);
+
+    for (index = index1; index < (index1 + XLWIP_CONFIG_N_TX_DESC); index++) {
+        if (tx_pbufs_storage[index] != 0) {
+            p = (struct pbuf *)tx_pbufs_storage[index];
+            pbuf_free(p);
+            tx_pbufs_storage[index] = 0;
+        }
+    }
+
+    for (index = index1; index < (index1 + XLWIP_CONFIG_N_TX_DESC); index++) {
+        p = (struct pbuf *)rx_pbufs_storage[index];
+        pbuf_free(p);
+
+    }
+}
+
+void free_onlytx_pbufs(xemacpsif_s *xemacpsif)
+{
+    s32_t index;
+    s32_t index1;
+    struct pbuf *p;
+
+    index1 = get_base_index_txpbufsstorage (xemacpsif);
+    for (index = index1; index < (index1 + XLWIP_CONFIG_N_TX_DESC); index++) {
+        if (tx_pbufs_storage[index] != 0) {
+            p = (struct pbuf *)tx_pbufs_storage[index];
+            pbuf_free(p);
+            tx_pbufs_storage[index] = 0;
+        }
+    }
+}
+
+/* reset Tx and Rx DMA pointers after XEmacPs_Stop */
+void reset_dma(struct xemac_s *xemac)
+{
+    u8 txqueuenum;
+    u32_t gigeversion;
+    xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
+    XEmacPs_BdRing *txringptr = &XEmacPs_GetTxRing(&xemacpsif->emacps);
+    XEmacPs_BdRing *rxringptr = &XEmacPs_GetRxRing(&xemacpsif->emacps);
+
+    XEmacPs_BdRingPtrReset(txringptr, xemacpsif->tx_bdspace);
+    XEmacPs_BdRingPtrReset(rxringptr, xemacpsif->rx_bdspace);
+
+    gigeversion = ((Xil_In32(xemacpsif->emacps.Config.BaseAddress + 0xFC)) >> 16) & 0xFFF;
+    if (gigeversion > 2) {
+        txqueuenum = 1;
+    } else {
+        txqueuenum = 0;
+    }
+
+    XEmacPs_SetQueuePtr(&(xemacpsif->emacps), xemacpsif->emacps.RxBdRing.BaseBdAddr, 0, XEMACPS_RECV);
+    XEmacPs_SetQueuePtr(&(xemacpsif->emacps), xemacpsif->emacps.TxBdRing.BaseBdAddr, txqueuenum, XEMACPS_SEND);
+}
+
+void emac_disable_intr(void)
+{
+    // XScuGic_DisableIntr(INTC_DIST_BASE_ADDR, emac_intr_num);
+    rt_hw_interrupt_mask(emac_intr_num);
+}
+
+void emac_enable_intr(void)
+{
+    // XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, emac_intr_num);
+    rt_hw_interrupt_umask(emac_intr_num);
+}

+ 276 - 0
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_hw.c

@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2010 - 2019 Xilinx, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ */
+
+#include "netif/xemacpsif.h"
+#include "lwipopts.h"
+
+#if XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1 || \
+    XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT == 1
+#define PCM_PMA_CORE_PRESENT
+#else
+#undef PCM_PMA_CORE_PRESENT
+#endif
+
+u32_t link_speed = 100;
+extern XEmacPs_Config XEmacPs_ConfigTable[];
+extern u32_t phymapemac0[32];
+extern u32_t phymapemac1[32];
+extern u32_t phyaddrforemac;
+extern enum ethernet_link_status eth_link_status;
+
+#ifdef OS_IS_FREERTOS
+extern long xInsideISR;
+#endif
+
+XEmacPs_Config *xemacps_lookup_config(unsigned mac_base)
+{
+    XEmacPs_Config *cfgptr = NULL;
+    s32_t i;
+
+    for (i = 0; i < XPAR_XEMACPS_NUM_INSTANCES; i++) {
+        if (XEmacPs_ConfigTable[i].BaseAddress == mac_base) {
+            cfgptr = &XEmacPs_ConfigTable[i];
+            break;
+        }
+    }
+
+    return (cfgptr);
+}
+
+void init_emacps(xemacpsif_s *xemacps, struct netif *netif)
+{
+    XEmacPs *xemacpsp;
+    s32_t status = XST_SUCCESS;
+    u32_t i;
+    u32_t phyfoundforemac0 = FALSE;
+    u32_t phyfoundforemac1 = FALSE;
+
+    xemacpsp = &xemacps->emacps;
+
+#ifdef ZYNQMP_USE_JUMBO
+    XEmacPs_SetOptions(xemacpsp, XEMACPS_JUMBO_ENABLE_OPTION);
+#endif
+
+#ifdef LWIP_IGMP
+    XEmacPs_SetOptions(xemacpsp, XEMACPS_MULTICAST_OPTION);
+#endif
+
+    /* set mac address */
+    status = XEmacPs_SetMacAddress(xemacpsp, (void*)(netif->hwaddr), 1);
+    if (status != XST_SUCCESS) {
+        xil_printf("In %s:Emac Mac Address set failed...\r\n",__func__);
+    }
+
+    XEmacPs_SetMdioDivisor(xemacpsp, MDC_DIV_224);
+
+/*  Please refer to file header comments for the file xemacpsif_physpeed.c
+ *  to know more about the PHY programming sequence.
+ *  For PCS PMA core, phy_setup_emacps is called with the predefined PHY address
+ *  exposed through xaparemeters.h
+ *  For RGMII case, assuming multiple PHYs can be present on the MDIO bus,
+ *  detect_phy is called to get the addresses of the PHY present on
+ *  a particular MDIO bus (emac0 or emac1). This address map is populated
+ *  in phymapemac0 or phymapemac1.
+ *  phy_setup_emacps is then called for each PHY present on the MDIO bus.
+ */
+#ifdef PCM_PMA_CORE_PRESENT
+#ifdef  XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT
+    link_speed = phy_setup_emacps(xemacpsp, XPAR_PCSPMA_1000BASEX_PHYADDR);
+#elif XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT
+    link_speed = phy_setup_emacps(xemacpsp, XPAR_PCSPMA_SGMII_PHYADDR);
+#endif
+#else
+    detect_phy(xemacpsp);
+    for (i = 31; i > 0; i--) {
+        if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) {
+            if (phymapemac0[i] == TRUE) {
+                link_speed = phy_setup_emacps(xemacpsp, i);
+                phyfoundforemac0 = TRUE;
+                phyaddrforemac = i;
+            }
+        } else {
+            if (phymapemac1[i] == TRUE) {
+                link_speed = phy_setup_emacps(xemacpsp, i);
+                phyfoundforemac1 = TRUE;
+                phyaddrforemac = i;
+            }
+        }
+    }
+    /* If no PHY was detected, use broadcast PHY address of 0 */
+    if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) {
+        if (phyfoundforemac0 == FALSE)
+            link_speed = phy_setup_emacps(xemacpsp, 0);
+    } else {
+        if (phyfoundforemac1 == FALSE)
+            link_speed = phy_setup_emacps(xemacpsp, 0);
+    }
+#endif
+
+    if (link_speed == XST_FAILURE) {
+        eth_link_status = ETH_LINK_DOWN;
+        xil_printf("Phy setup failure %s \n\r",__func__);
+        return;
+    } else {
+        eth_link_status = ETH_LINK_UP;
+    }
+
+    XEmacPs_SetOperatingSpeed(xemacpsp, link_speed);
+    /* Setting the operating speed of the MAC needs a delay. */
+    {
+        volatile s32_t wait;
+        for (wait=0; wait < 20000; wait++);
+    }
+}
+
+void init_emacps_on_error (xemacpsif_s *xemacps, struct netif *netif)
+{
+    XEmacPs *xemacpsp;
+    s32_t status = XST_SUCCESS;
+
+    xemacpsp = &xemacps->emacps;
+
+    /* set mac address */
+    status = XEmacPs_SetMacAddress(xemacpsp, (void*)(netif->hwaddr), 1);
+    if (status != XST_SUCCESS) {
+        xil_printf("In %s:Emac Mac Address set failed...\r\n",__func__);
+    }
+
+    XEmacPs_SetOperatingSpeed(xemacpsp, link_speed);
+
+    /* Setting the operating speed of the MAC needs a delay. */
+    {
+        volatile s32_t wait;
+        for (wait=0; wait < 20000; wait++);
+    }
+}
+
+void setup_isr (struct xemac_s *xemac)
+{
+    xemacpsif_s   *xemacpsif;
+
+    xemacpsif = (xemacpsif_s *)(xemac->state);
+    /*
+     * Setup callbacks
+     */
+    XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMASEND,
+                     (void *) emacps_send_handler,
+                     (void *) xemac);
+
+    XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMARECV,
+                    (void *) emacps_recv_handler,
+                    (void *) xemac);
+
+    XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_ERROR,
+                    (void *) emacps_error_handler,
+                    (void *) xemac);
+}
+
+void start_emacps (xemacpsif_s *xemacps)
+{
+    /* start the temac */
+    XEmacPs_Start(&xemacps->emacps);
+}
+
+void restart_emacps_transmitter (xemacpsif_s *xemacps) {
+    u32_t Reg;
+    Reg = XEmacPs_ReadReg(xemacps->emacps.Config.BaseAddress,
+                    XEMACPS_NWCTRL_OFFSET);
+    Reg = Reg & (~XEMACPS_NWCTRL_TXEN_MASK);
+    XEmacPs_WriteReg(xemacps->emacps.Config.BaseAddress,
+                                        XEMACPS_NWCTRL_OFFSET, Reg);
+
+    Reg = XEmacPs_ReadReg(xemacps->emacps.Config.BaseAddress,
+                        XEMACPS_NWCTRL_OFFSET);
+    Reg = Reg | (XEMACPS_NWCTRL_TXEN_MASK);
+    XEmacPs_WriteReg(xemacps->emacps.Config.BaseAddress,
+                                        XEMACPS_NWCTRL_OFFSET, Reg);
+}
+
+void emacps_error_handler(void *arg,u8 Direction, u32 ErrorWord)
+{
+    struct xemac_s *xemac;
+    xemacpsif_s   *xemacpsif;
+    XEmacPs_BdRing *rxring;
+    XEmacPs_BdRing *txring;
+#ifdef OS_IS_FREERTOS
+    xInsideISR++;
+#endif
+
+    xemac = (struct xemac_s *)(arg);
+    xemacpsif = (xemacpsif_s *)(xemac->state);
+    rxring = &XEmacPs_GetRxRing(&xemacpsif->emacps);
+    txring = &XEmacPs_GetTxRing(&xemacpsif->emacps);
+
+    if (ErrorWord != 0) {
+        switch (Direction) {
+            case XEMACPS_RECV:
+            if (ErrorWord & XEMACPS_RXSR_HRESPNOK_MASK) {
+                LWIP_DEBUGF(NETIF_DEBUG, ("Receive DMA error\r\n"));
+                HandleEmacPsError(xemac);
+            }
+            if (ErrorWord & XEMACPS_RXSR_RXOVR_MASK) {
+                LWIP_DEBUGF(NETIF_DEBUG, ("Receive over run\r\n"));
+                emacps_recv_handler(arg);
+                setup_rx_bds(xemacpsif, rxring);
+            }
+            if (ErrorWord & XEMACPS_RXSR_BUFFNA_MASK) {
+                LWIP_DEBUGF(NETIF_DEBUG, ("Receive buffer not available\r\n"));
+                emacps_recv_handler(arg);
+                setup_rx_bds(xemacpsif, rxring);
+            }
+            break;
+            case XEMACPS_SEND:
+            if (ErrorWord & XEMACPS_TXSR_HRESPNOK_MASK) {
+                LWIP_DEBUGF(NETIF_DEBUG, ("Transmit DMA error\r\n"));
+                HandleEmacPsError(xemac);
+            }
+            if (ErrorWord & XEMACPS_TXSR_URUN_MASK) {
+                LWIP_DEBUGF(NETIF_DEBUG, ("Transmit under run\r\n"));
+                HandleTxErrors(xemac);
+            }
+            if (ErrorWord & XEMACPS_TXSR_BUFEXH_MASK) {
+                LWIP_DEBUGF(NETIF_DEBUG, ("Transmit buffer exhausted\r\n"));
+                HandleTxErrors(xemac);
+            }
+            if (ErrorWord & XEMACPS_TXSR_RXOVR_MASK) {
+                LWIP_DEBUGF(NETIF_DEBUG, ("Transmit retry excessed limits\r\n"));
+                HandleTxErrors(xemac);
+            }
+            if (ErrorWord & XEMACPS_TXSR_FRAMERX_MASK) {
+                LWIP_DEBUGF(NETIF_DEBUG, ("Transmit collision\r\n"));
+                // process_sent_bds(xemacpsif, txring);
+            }
+            break;
+        }
+    }
+#ifdef OS_IS_FREERTOS
+    xInsideISR--;
+#endif
+}

+ 49 - 0
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_hw.h

@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2010 - 2019 Xilinx, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ */
+
+#ifndef __XEMACPSIF_HW_H_
+#define __XEMACPSIF_HW_H_
+
+#include "netif/xemacpsif.h"
+#include "lwip/netif.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+XEmacPs_Config * lookup_config(unsigned mac_base);
+
+void init_emacps(xemacpsif_s *xemacpsif, struct netif *netif);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 1152 - 0
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xemacpsif_physpeed.c

@@ -0,0 +1,1152 @@
+/*
+ * Copyright (C) 2010 - 2019 Xilinx, Inc.
+ * Copyright (C) 2021 WangHuachen.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ */
+
+/*****************************************************************************
+* This file xemacpsif_physpeed.c implements functionalities to:
+* - Detect the available PHYs connected to a MAC
+* - Negotiate speed
+* - Configure speed
+* - Configure the SLCR registers for the negotiated speed
+*
+* In a typical use case, users of the APIs implemented in this file need to
+* do the following.
+* - Call the API detect_phy. It probes for the available PHYs connected to a MAC.
+*   The MACs can be Emac0 (XPAR_XEMACPS_0_BASEADDR, 0xE000B000) or Emac1
+*   (XPAR_XEMACPS_0_BASEADDR, 0xE000C000). It populates an array to notify
+*   about the detected PHYs. The array phymapemac0 is used for Emac0 and
+*   phymapemac1 is for Emac1.
+* - The users need to parse the corresponding arrays, phymapemac0 or phymapemac1
+*   to know the available PHYs for a MAC. The users then need to call
+*   phy_setup_emacps to setup the PHYs for proper speed setting. The API
+*   phy_setup_emacps should be called with the PHY address for which the speed
+*   needs to be negotiated or configured. In a specific use case, if 2 PHYs are
+*   connected to Emac0 with addresses of 7 and 11, then users get these address
+*   details from phymapemac0 (after calling detect_phy) and then call
+*   phy_setup_emacps twice, with ab address of 7 and 11.
+* - Points to note: The MAC can operate at only one speed. If a MAC is connected
+*   to multiple PHYs, then all PHYs must negotiate and configured for the same
+*   speed.
+* - This file implements static functions to set proper SLCR clocks. As stated
+*   above, all PHYs connected to a PHY must operate at same speed and the SLCR
+*   clock will be setup accordingly.
+*
+* This file implements the following PHY types.
+* - The standard RGMII.
+* - It provides support for GMII to RGMII converter Xilinx IP. This Xilinx IP
+*   sits on the MDIO bus with a predefined PHY address. This IP exposes register
+*   that needs to be programmed with the negotiated speed.
+*   For example, in a typical design, the Emac0 or Emac1 exposes GMII interface.
+*   The user can then use the Xilinx IP that converts GMII to RGMII.
+*   The external PHY (most typically Marvell 88E1116R) negotiates for speed
+*   with the remote PHY. The implementation in this file then programs the
+*   Xilinx IP with this negotiated speed. The Xilinx IP has a predefined IP
+*   address exposed through xparameters.h
+* - The SGMII and 1000 BaseX PHY interfaces.
+*   If the PHY interface is SGMII or 1000 BaseX a separate "get_IEEE_phy_speed"
+*   is used which is different from standard RGMII "get_IEEE_phy_speed".
+*   The 1000 BaseX always operates at 1000 Mbps. The SGMII interface can
+*   negotiate speed accordingly.
+*   For SGMII or 1000 BaseX interfaces, the detect_phy should not be called.
+*   The phy addresses for these interfaces are fixed at the design time.
+*
+* Point to note:
+* A MAC can not be connected to PHYs where there is a mix between
+* SGMII or 1000 Basex or GMII/MII/RGMII.
+* In a typical multiple PHY designs, it is expected that the PHYs connected
+* will be RGMII or GMII.
+*
+* The users can choose not to negotiate speed from lwip settings GUI.
+* If they opt to choose a particular PHY speed, then the PHY will hard code
+* the speed to operate only at the corresponding speed. It will not advertise
+* any other speeds. It is users responsibility to ensure that the remote PHY
+* supports the speed programmed through the lwip gui.
+*
+* The following combination of MDIO/PHY are supported:
+* - Multiple PHYs connected to the MDIO bus of a MAC. If Emac0 MDIO is connected
+*   to single/multiple PHYs, it is supported. Similarly Emac1 MDIO connected to
+*   single/multiple PHYs is supported.
+* - A design where both the interfaces are present and are connected to their own
+*   MDIO bus is supported.
+*
+* The following MDIO/PHY setup is not supported:
+* - A design has both the MACs present. MDIO bus is available only for one MAC
+*   (Emac0 or Emac1). This MDIO bus has multiple PHYs available for both the
+*   MACs. The negotiated speed for PHYs sitting on the MDIO bus of one MAC will
+*   not be see for the other MAC and hence the speed/SLCR settings of the other
+*   MAC cannot be programmed. Hence this kind of design will not work for
+*   this implementation.
+*
+********************************************************************************/
+
+#include "netif/xemacpsif.h"
+#include "lwipopts.h"
+#include "xparameters_ps.h"
+#include "xparameters.h"
+#include "xemac_ieee_reg.h"
+
+#if defined (__aarch64__)
+#include "bspconfig.h"
+#include "xil_smc.h"
+#endif
+
+#define CONFIG_LINKSPEED_AUTODETECT 1
+
+#define PHY_DETECT_REG                          1
+#define PHY_IDENTIFIER_1_REG                    2
+#define PHY_IDENTIFIER_2_REG                    3
+#define PHY_DETECT_MASK                     0x1808
+#define PHY_MARVELL_IDENTIFIER                0x0141
+#define PHY_TI_IDENTIFIER                    0x2000
+#define PHY_REALTEK_IDENTIFIER                0x001c
+#define PHY_XILINX_PCS_PMA_ID1            0x0174
+#define PHY_XILINX_PCS_PMA_ID2            0x0C00
+
+#define XEMACPS_GMII2RGMII_SPEED1000_FD        0x140
+#define XEMACPS_GMII2RGMII_SPEED100_FD        0x2100
+#define XEMACPS_GMII2RGMII_SPEED10_FD        0x100
+#define XEMACPS_GMII2RGMII_REG_NUM            0x10
+
+#define PHY_REGCR        0x0D
+#define PHY_ADDAR        0x0E
+#define PHY_RGMIIDCTL    0x86
+#define PHY_RGMIICTL    0x32
+#define PHY_STS            0x11
+#define PHY_TI_CR        0x10
+#define PHY_TI_CFG4        0x31
+
+#define MICREL_PHY_IDENTIFIER                0x22
+#define MICREL_PHY_KSZ9031_MODEL            0x220
+
+#define PHY_REGCR_ADDR    0x001F
+#define PHY_REGCR_DATA    0x401F
+#define PHY_TI_CRVAL    0x5048
+#define PHY_TI_CFG4RESVDBIT7    0x80
+
+/* Frequency setting */
+#define SLCR_LOCK_ADDR            (XPS_SYS_CTRL_BASEADDR + 0x4)
+#define SLCR_UNLOCK_ADDR        (XPS_SYS_CTRL_BASEADDR + 0x8)
+#define SLCR_GEM0_CLK_CTRL_ADDR    (XPS_SYS_CTRL_BASEADDR + 0x140)
+#define SLCR_GEM1_CLK_CTRL_ADDR    (XPS_SYS_CTRL_BASEADDR + 0x144)
+#define SLCR_GEM_SRCSEL_EMIO    0x40
+#define SLCR_LOCK_KEY_VALUE     0x767B
+#define SLCR_UNLOCK_KEY_VALUE    0xDF0D
+#define SLCR_ADDR_GEM_RST_CTRL    (XPS_SYS_CTRL_BASEADDR + 0x214)
+#define EMACPS_SLCR_DIV_MASK    0xFC0FC0FF
+
+#if XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1 || \
+    XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT == 1
+#define PCM_PMA_CORE_PRESENT
+#else
+#undef PCM_PMA_CORE_PRESENT
+#endif
+
+#ifdef PCM_PMA_CORE_PRESENT
+#define IEEE_CTRL_RESET                         0x9140
+#define IEEE_CTRL_ISOLATE_DISABLE               0xFBFF
+#endif
+
+u32_t phymapemac0[32];
+u32_t phymapemac1[32];
+
+#if defined (PCM_PMA_CORE_PRESENT) || defined (CONFIG_LINKSPEED_AUTODETECT)
+static u32_t get_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr);
+#endif
+static void SetUpSLCRDivisors(u32_t mac_baseaddr, s32_t speed);
+#if defined (CONFIG_LINKSPEED1000) || defined (CONFIG_LINKSPEED100) \
+    || defined (CONFIG_LINKSPEED10)
+static u32_t configure_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr, u32_t speed);
+#endif
+
+#ifdef PCM_PMA_CORE_PRESENT
+u32_t phy_setup_emacps (XEmacPs *xemacpsp, u32_t phy_addr)
+{
+    u32_t link_speed;
+    u16_t regval;
+    u16_t phy_id;
+
+    if(phy_addr == 0) {
+        for (phy_addr = 31; phy_addr > 0; phy_addr--) {
+            XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG,
+                    &phy_id);
+
+            if (phy_id == PHY_XILINX_PCS_PMA_ID1) {
+                XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_2_REG,
+                        &phy_id);
+                if (phy_id == PHY_XILINX_PCS_PMA_ID2) {
+                    /* Found a valid PHY address */
+                    LWIP_DEBUGF(NETIF_DEBUG, ("XEmacPs detect_phy: PHY detected at address %d.\r\n",
+                            phy_addr));
+                    break;
+                }
+            }
+        }
+    }
+
+    link_speed = get_IEEE_phy_speed(xemacpsp, phy_addr);
+    if (link_speed == 1000)
+        SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
+    else if (link_speed == 100)
+        SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);
+    else
+        SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);
+
+    xil_printf("link speed for phy address %d: %d\r\n", phy_addr, link_speed);
+    return link_speed;
+}
+
+static u32_t get_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
+{
+    u16_t temp;
+    u16_t control;
+    u16_t status;
+    u16_t partner_capabilities;
+
+    xil_printf("Start PHY autonegotiation \r\n");
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+    control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
+    control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
+    control &= IEEE_CTRL_ISOLATE_DISABLE;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
+
+    xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
+        sleep(1);
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,
+                                                                &status);
+    }
+    xil_printf("autonegotiation complete \r\n");
+
+#if XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 1);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, &temp);
+    if ((temp & 0x0020) == 0x0020) {
+        XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
+        return 1000;
+    }
+    else {
+        XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
+        xil_printf("Link error, temp = %x\r\n", temp);
+        return 0;
+    }
+#elif XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT == 1
+    xil_printf("Waiting for Link to be up; Polling for SGMII core Reg \r\n");
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, &temp);
+    while(!(temp & 0x8000)) {
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, &temp);
+    }
+    if((temp & 0x0C00) == 0x0800) {
+        return 1000;
+    }
+    else if((temp & 0x0C00) == 0x0400) {
+        return 100;
+    }
+    else if((temp & 0x0C00) == 0x0000) {
+        return 10;
+    } else {
+        xil_printf("get_IEEE_phy_speed(): Invalid speed bit value, Defaulting to Speed = 10 Mbps\r\n");
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &temp);
+        XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, 0x0100);
+        return 10;
+    }
+#endif
+
+}
+
+#else /*PCM_PMA_CORE_PRESENT not defined, GMII/RGMII case*/
+void detect_phy(XEmacPs *xemacpsp)
+{
+    u16_t phy_reg;
+    u32_t phy_addr;
+    u32_t emacnum;
+
+    if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR)
+        emacnum = 0;
+    else
+        emacnum = 1;
+    for (phy_addr = 31; phy_addr > 0; phy_addr--) {
+        XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_DETECT_REG,
+                            &phy_reg);
+
+        if ((phy_reg != 0xFFFF) &&
+            ((phy_reg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
+            /* Found a valid PHY address */
+            LWIP_DEBUGF(NETIF_DEBUG, ("XEmacPs detect_phy: PHY detected at address %d.\r\n",
+                                                                    phy_addr));
+            if (emacnum == 0)
+                phymapemac0[phy_addr] = TRUE;
+            else
+                phymapemac1[phy_addr] = TRUE;
+
+            XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG,
+                            &phy_reg);
+            if ((phy_reg != PHY_MARVELL_IDENTIFIER) &&
+                (phy_reg != PHY_TI_IDENTIFIER) &&
+                (phy_reg != PHY_REALTEK_IDENTIFIER)) {
+                xil_printf("WARNING: Not a Marvell or TI or Realtek Ethernet PHY. Please verify the initialization sequence\r\n");
+            }
+        }
+    }
+}
+
+u32_t phy_setup_emacps (XEmacPs *xemacpsp, u32_t phy_addr)
+{
+    u32_t link_speed;
+    u32_t conv_present = 0;
+    u32_t convspeeddupsetting = 0;
+    u32_t convphyaddr = 0;
+
+#ifdef XPAR_GMII2RGMIICON_0N_ETH0_ADDR
+    convphyaddr = XPAR_GMII2RGMIICON_0N_ETH0_ADDR;
+    conv_present = 1;
+#endif
+#ifdef XPAR_GMII2RGMIICON_0N_ETH1_ADDR
+    convphyaddr = XPAR_GMII2RGMIICON_0N_ETH1_ADDR;
+    conv_present = 1;
+#endif
+
+#ifdef  CONFIG_LINKSPEED_AUTODETECT
+    link_speed = get_IEEE_phy_speed(xemacpsp, phy_addr);
+    if (link_speed == 1000) {
+        SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
+        convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
+    } else if (link_speed == 100) {
+        SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);
+        convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;
+    } else if (link_speed != XST_FAILURE){
+        SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);
+        convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;
+    } else {
+        xil_printf("Phy setup error \r\n");
+        return XST_FAILURE;
+    }
+#elif    defined(CONFIG_LINKSPEED1000)
+    SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
+    link_speed = 1000;
+    configure_IEEE_phy_speed(xemacpsp, phy_addr, link_speed);
+    convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
+    sleep(1);
+#elif    defined(CONFIG_LINKSPEED100)
+    SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);
+    link_speed = 100;
+    configure_IEEE_phy_speed(xemacpsp, phy_addr, link_speed);
+    convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;
+    sleep(1);
+#elif    defined(CONFIG_LINKSPEED10)
+    SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);
+    link_speed = 10;
+    configure_IEEE_phy_speed(xemacpsp, phy_addr, link_speed);
+    convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;
+    sleep(1);
+#endif
+    if (conv_present) {
+        XEmacPs_PhyWrite(xemacpsp, convphyaddr,
+        XEMACPS_GMII2RGMII_REG_NUM, convspeeddupsetting);
+    }
+
+    xil_printf("link speed for phy address %d: %d\r\n", phy_addr, link_speed);
+    return link_speed;
+}
+
+#if defined CONFIG_LINKSPEED_AUTODETECT
+static u32_t get_phy_speed_ksz9031(XEmacPs *xemacpsp, u32_t phy_addr)
+{
+    static int phy_init_flag = 0;
+    u16_t temp;
+    u16_t control;
+    u16_t status;
+    u16_t status_speed;
+    u32_t timeout_counter = 0;
+
+    xil_printf("Start PHY autonegotiation \r\n");
+
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
+    control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);
+
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
+    control |= IEEE_ASYMMETRIC_PAUSE_MASK;
+    control |= IEEE_PAUSE_MASK;
+    control |= ADVERTISE_100;
+    control |= ADVERTISE_10;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
+                       &control);
+    control |= ADVERTISE_1000;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
+                       control);
+
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG, &control);
+
+    control |= (7 << 12); /* max number of gigabit attempts */
+    control |= (1 << 11); /* enable downshift */
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
+                     control);
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+    control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
+    control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+    control |= IEEE_CTRL_RESET_MASK;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
+
+    while (1) {
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+        if (control & IEEE_CTRL_RESET_MASK)
+             continue;
+        else
+            break;
+    }
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+
+    xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
+
+    while (!(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE)) {
+        sleep(1);
+        XEmacPs_PhyRead(xemacpsp, phy_addr,
+                            IEEE_COPPER_SPECIFIC_STATUS_REG_2, &temp);
+        timeout_counter++;
+        if ((phy_init_flag == 0) && (timeout_counter > 1))
+        {
+            phy_init_flag = 1;
+            return XST_FAILURE;
+        }
+        if (timeout_counter == 30) {
+            xil_printf("Auto negotiation error \r\n");
+            return XST_FAILURE;
+        }
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    }
+    xil_printf("autonegotiation complete \r\n");
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr, 0x1f, &status_speed);
+
+    if ((status_speed & 0x40) == 0x40) /* 1000Mbps */
+        return 1000;
+    else if ((status_speed & 0x20) == 0x20) /* 100Mbps */
+        return 100;
+    else if ((status_speed & 0x10) == 0x10) /* 10Mbps */
+        return 10;
+    else
+        return 0;
+    return XST_SUCCESS;
+}
+
+static u32_t get_TI_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
+{
+    u16_t control;
+    u16_t status;
+    u16_t status_speed;
+    u32_t timeout_counter = 0;
+    u32_t phyregtemp;
+    int i;
+    u32_t RetStatus;
+    static int phy_init_flag = 0;
+
+    xil_printf("Start PHY autonegotiation \r\n");
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr, 0x1F, (u16_t *)&phyregtemp);
+    phyregtemp |= 0x4000;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, 0x1F, phyregtemp);
+    RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, 0x1F, (u16_t *)&phyregtemp);
+    if (RetStatus != XST_SUCCESS) {
+        xil_printf("Error during sw reset \n\r");
+        return XST_FAILURE;
+    }
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr, 0, (u16_t *)&phyregtemp);
+    phyregtemp |= 0x8000;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, 0, phyregtemp);
+
+    /*
+     * Delay
+     */
+    for(i=0;i<1000000000;i++);
+
+    RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, 0, (u16_t *)&phyregtemp);
+    if (RetStatus != XST_SUCCESS) {
+        xil_printf("Error during reset \n\r");
+        return XST_FAILURE;
+    }
+
+    /* FIFO depth */
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_TI_CR, PHY_TI_CRVAL);
+    RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_TI_CR, (u16_t *)&phyregtemp);
+    if (RetStatus != XST_SUCCESS) {
+        xil_printf("Error writing to 0x10 \n\r");
+        return XST_FAILURE;
+    }
+
+    /* TX/RX tuning */
+    /* Write to PHY_RGMIIDCTL */
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIIDCTL);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
+    RetStatus = XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, 0xA8);
+    if (RetStatus != XST_SUCCESS) {
+        xil_printf("Error in tuning");
+        return XST_FAILURE;
+    }
+
+    /* Read PHY_RGMIIDCTL */
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIIDCTL);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
+    RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_ADDAR, (u16_t *)&phyregtemp);
+    if (RetStatus != XST_SUCCESS) {
+        xil_printf("Error in tuning");
+        return XST_FAILURE;
+    }
+
+    /* Write PHY_RGMIICTL */
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIICTL);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
+    RetStatus = XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, 0xD3);
+    if (RetStatus != XST_SUCCESS) {
+        xil_printf("Error in tuning");
+        return XST_FAILURE;
+    }
+
+    /* Read PHY_RGMIICTL */
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIICTL);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
+    RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_ADDAR, (u16_t *)&phyregtemp);
+    if (RetStatus != XST_SUCCESS) {
+        xil_printf("Error in tuning");
+        return XST_FAILURE;
+    }
+
+    /* SW workaround for unstable link when RX_CTRL is not STRAP MODE 3 or 4 */
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_TI_CFG4);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
+    RetStatus = XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_ADDAR, (u16_t *)&phyregtemp);
+    phyregtemp &= ~(PHY_TI_CFG4RESVDBIT7);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, PHY_TI_CFG4);
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA);
+    RetStatus = XEmacPs_PhyWrite(xemacpsp, phy_addr, PHY_ADDAR, phyregtemp);
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
+    control |= IEEE_ASYMMETRIC_PAUSE_MASK;
+    control |= IEEE_PAUSE_MASK;
+    control |= ADVERTISE_100;
+    control |= ADVERTISE_10;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
+                    &control);
+    control |= ADVERTISE_1000;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
+                    control);
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+    control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
+    control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+
+    xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
+
+    while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
+        sleep(1);
+        timeout_counter++;
+        if ((phy_init_flag == 0) && (timeout_counter > 1))
+        {
+            phy_init_flag = 1;
+            return XST_FAILURE;
+        }
+        if (timeout_counter == 30) {
+            xil_printf("Auto negotiation error \r\n");
+            return XST_FAILURE;
+        }
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    }
+    xil_printf("autonegotiation complete \r\n");
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_STS, &status_speed);
+    if ((status_speed & 0xC000) == 0x8000) {
+        return 1000;
+    } else if ((status_speed & 0xC000) == 0x4000) {
+        return 100;
+    } else {
+        return 10;
+    }
+
+    return XST_SUCCESS;
+}
+
+static u32_t get_Marvell_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
+{
+    u16_t temp;
+    u16_t control;
+    u16_t status;
+    u16_t status_speed;
+    u32_t timeout_counter = 0;
+    u32_t temp_speed;
+    static int phy_init_flag = 0;
+
+    xil_printf("Start PHY autonegotiation \r\n");
+
+    XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
+    control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);
+
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
+    control |= IEEE_ASYMMETRIC_PAUSE_MASK;
+    control |= IEEE_PAUSE_MASK;
+    control |= ADVERTISE_100;
+    control |= ADVERTISE_10;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
+                    &control);
+    control |= ADVERTISE_1000;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
+                    control);
+
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
+                                                                &control);
+    control |= (7 << 12);    /* max number of gigabit attempts */
+    control |= (1 << 11);    /* enable downshift */
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
+                                                                control);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+    control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
+    control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+    control |= IEEE_CTRL_RESET_MASK;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
+
+    while (1) {
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+        if (control & IEEE_CTRL_RESET_MASK)
+            continue;
+        else
+            break;
+    }
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+
+    xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
+
+    while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
+        sleep(1);
+        XEmacPs_PhyRead(xemacpsp, phy_addr,
+                        IEEE_COPPER_SPECIFIC_STATUS_REG_2,  &temp);
+        timeout_counter++;
+        if ((phy_init_flag == 0) && (timeout_counter > 1))
+        {
+            phy_init_flag = 1;
+            return XST_FAILURE;
+        }
+        if (timeout_counter == 30) {
+            xil_printf("Auto negotiation error \r\n");
+            return XST_FAILURE;
+        }
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    }
+    xil_printf("autonegotiation complete \r\n");
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr,IEEE_SPECIFIC_STATUS_REG,
+                    &status_speed);
+    if (status_speed & 0x400) {
+        temp_speed = status_speed & IEEE_SPEED_MASK;
+
+        if (temp_speed == IEEE_SPEED_1000)
+            return 1000;
+        else if(temp_speed == IEEE_SPEED_100)
+            return 100;
+        else
+            return 10;
+    }
+
+    return XST_SUCCESS;
+}
+
+static u32_t get_Realtek_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
+{
+    u16_t control;
+    u16_t status;
+    u16_t status_speed;
+    u32_t timeout_counter = 0;
+    u32_t temp_speed;
+    static int phy_init_flag = 0;
+
+    xil_printf("Start PHY autonegotiation \r\n");
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
+    control |= IEEE_ASYMMETRIC_PAUSE_MASK;
+    control |= IEEE_PAUSE_MASK;
+    control |= ADVERTISE_100;
+    control |= ADVERTISE_10;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
+                    &control);
+    control |= ADVERTISE_1000;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
+                    control);
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+    control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
+    control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+    control |= IEEE_CTRL_RESET_MASK;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
+
+    while (1) {
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+        if (control & IEEE_CTRL_RESET_MASK)
+            continue;
+        else
+            break;
+    }
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+
+    xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
+
+    while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
+        sleep(1);
+        timeout_counter++;
+        if ((phy_init_flag == 0) && (timeout_counter > 1))
+        {
+            phy_init_flag = 1;
+            return XST_FAILURE;
+        }
+        if (timeout_counter == 30) {
+            xil_printf("Auto negotiation error \r\n");
+            return XST_FAILURE;
+        }
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
+    }
+    xil_printf("autonegotiation complete \r\n");
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr,IEEE_SPECIFIC_STATUS_REG,
+                    &status_speed);
+    if (status_speed & 0x400) {
+        temp_speed = status_speed & IEEE_SPEED_MASK;
+
+        if (temp_speed == IEEE_SPEED_1000)
+            return 1000;
+        else if(temp_speed == IEEE_SPEED_100)
+            return 100;
+        else
+            return 10;
+    }
+
+    return XST_FAILURE;
+}
+
+static u32_t get_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
+{
+    u16_t phy_identity;
+    u32_t RetStatus;
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG,
+                    &phy_identity);
+    if(phy_identity == MICREL_PHY_IDENTIFIER){
+        RetStatus = get_phy_speed_ksz9031(xemacpsp, phy_addr);
+    } else if (phy_identity == PHY_TI_IDENTIFIER) {
+        RetStatus = get_TI_phy_speed(xemacpsp, phy_addr);
+    } else if (phy_identity == PHY_REALTEK_IDENTIFIER) {
+        RetStatus = get_Realtek_phy_speed(xemacpsp, phy_addr);
+    } else {
+        RetStatus = get_Marvell_phy_speed(xemacpsp, phy_addr);
+    }
+
+    return RetStatus;
+}
+#endif
+
+#if defined (CONFIG_LINKSPEED1000) || defined (CONFIG_LINKSPEED100) \
+    || defined (CONFIG_LINKSPEED10)
+static u32_t configure_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr, u32_t speed)
+{
+    u16_t control;
+    u16_t autonereg;
+
+    XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
+    control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);
+
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
+    autonereg |= IEEE_ASYMMETRIC_PAUSE_MASK;
+    autonereg |= IEEE_PAUSE_MASK;
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
+
+    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
+    control &= ~IEEE_CTRL_LINKSPEED_1000M;
+    control &= ~IEEE_CTRL_LINKSPEED_100M;
+    control &= ~IEEE_CTRL_LINKSPEED_10M;
+
+    if (speed == 1000) {
+        control |= IEEE_CTRL_LINKSPEED_1000M;
+
+        /* Don't advertise PHY speed of 100 Mbps */
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
+        autonereg &= (~ADVERTISE_100);
+        XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
+
+        /* Don't advertise PHY speed of 10 Mbps */
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
+        autonereg &= (~ADVERTISE_10);
+        XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
+
+        /* Advertise PHY speed of 1000 Mbps */
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &autonereg);
+        autonereg |= ADVERTISE_1000;
+        XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, autonereg);
+    }
+
+    else if (speed == 100) {
+        control |= IEEE_CTRL_LINKSPEED_100M;
+
+        /* Don't advertise PHY speed of 1000 Mbps */
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &autonereg);
+        autonereg &= (~ADVERTISE_1000);
+        XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, autonereg);
+
+        /* Don't advertise PHY speed of 10 Mbps */
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
+        autonereg &= (~ADVERTISE_10);
+        XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
+
+        /* Advertise PHY speed of 100 Mbps */
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
+        autonereg |= ADVERTISE_100;
+        XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
+    }
+
+    else if (speed == 10) {
+        control |= IEEE_CTRL_LINKSPEED_10M;
+
+        /* Don't advertise PHY speed of 1000 Mbps */
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &autonereg);
+        autonereg &= (~ADVERTISE_1000);
+        XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, autonereg);
+
+        /* Don't advertise PHY speed of 100 Mbps */
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
+        autonereg &= (~ADVERTISE_100);
+        XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
+
+        /* Advertise PHY speed of 10 Mbps */
+        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &autonereg);
+        autonereg |= ADVERTISE_10;
+        XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, autonereg);
+    }
+
+    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,
+                                            control | IEEE_CTRL_RESET_MASK);
+    {
+        volatile s32_t wait;
+        for (wait=0; wait < 100000; wait++);
+    }
+    return 0;
+}
+#endif
+#endif /*PCM_PMA_CORE_PRESENT*/
+
+static void SetUpSLCRDivisors(u32_t mac_baseaddr, s32_t speed)
+{
+    volatile u32_t slcrBaseAddress;
+    u32_t SlcrDiv0 = 0;
+    u32_t SlcrDiv1 = 0;
+    u32_t SlcrTxClkCntrl;
+    u32_t gigeversion;
+    volatile u32_t CrlApbBaseAddr;
+    u32_t CrlApbDiv0 = 0;
+    u32_t CrlApbDiv1 = 0;
+    u32_t CrlApbGemCtrl;
+#if EL1_NONSECURE
+    u32_t ClkId;
+#endif
+
+    gigeversion = ((Xil_In32(mac_baseaddr + 0xFC)) >> 16) & 0xFFF;
+    if (gigeversion == 2) {
+
+        *(volatile u32_t *)(SLCR_UNLOCK_ADDR) = SLCR_UNLOCK_KEY_VALUE;
+
+        if (mac_baseaddr == ZYNQ_EMACPS_0_BASEADDR) {
+            slcrBaseAddress = SLCR_GEM0_CLK_CTRL_ADDR;
+        } else {
+            slcrBaseAddress = SLCR_GEM1_CLK_CTRL_ADDR;
+        }
+
+        if((*(volatile u32_t *)(UINTPTR)(slcrBaseAddress)) &
+            SLCR_GEM_SRCSEL_EMIO) {
+                return;
+        }
+
+        if (speed == 1000) {
+            if (mac_baseaddr == XPAR_XEMACPS_0_BASEADDR) {
+#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0
+                SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
+                SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;
+#endif
+            } else {
+#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0
+                SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
+                SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;
+#endif
+            }
+        } else if (speed == 100) {
+            if (mac_baseaddr == XPAR_XEMACPS_0_BASEADDR) {
+#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0
+                SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
+                SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;
+#endif
+            } else {
+#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0
+                SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
+                SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;
+#endif
+            }
+        } else {
+            if (mac_baseaddr == XPAR_XEMACPS_0_BASEADDR) {
+#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0
+                SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
+                SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;
+#endif
+            } else {
+#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0
+                SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
+                SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;
+#endif
+            }
+        }
+
+        if (SlcrDiv0 != 0 && SlcrDiv1 != 0) {
+            SlcrTxClkCntrl = *(volatile u32_t *)(UINTPTR)(slcrBaseAddress);
+            SlcrTxClkCntrl &= EMACPS_SLCR_DIV_MASK;
+            SlcrTxClkCntrl |= (SlcrDiv1 << 20);
+            SlcrTxClkCntrl |= (SlcrDiv0 << 8);
+            *(volatile u32_t *)(UINTPTR)(slcrBaseAddress) = SlcrTxClkCntrl;
+            *(volatile u32_t *)(SLCR_LOCK_ADDR) = SLCR_LOCK_KEY_VALUE;
+        } else {
+            xil_printf("Clock Divisors incorrect - Please check\r\n");
+        }
+    } else if (gigeversion == GEM_VERSION_ZYNQMP) {
+        /* Setup divisors in CRL_APB for Zynq Ultrascale+ MPSoC */
+        if (mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR) {
+            CrlApbBaseAddr = CRL_APB_GEM0_REF_CTRL;
+        } else if (mac_baseaddr == ZYNQMP_EMACPS_1_BASEADDR) {
+            CrlApbBaseAddr = CRL_APB_GEM1_REF_CTRL;
+        } else if (mac_baseaddr == ZYNQMP_EMACPS_2_BASEADDR) {
+            CrlApbBaseAddr = CRL_APB_GEM2_REF_CTRL;
+        } else if (mac_baseaddr == ZYNQMP_EMACPS_3_BASEADDR) {
+            CrlApbBaseAddr = CRL_APB_GEM3_REF_CTRL;
+        }
+
+        if (speed == 1000) {
+            if (mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR) {
+#ifdef XPAR_PSU_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0
+                CrlApbDiv0 = XPAR_PSU_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
+                CrlApbDiv1 = XPAR_PSU_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;
+#endif
+            } else if (mac_baseaddr == ZYNQMP_EMACPS_1_BASEADDR) {
+#ifdef XPAR_PSU_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0
+                CrlApbDiv0 = XPAR_PSU_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
+                CrlApbDiv1 = XPAR_PSU_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;
+#endif
+            } else if (mac_baseaddr == ZYNQMP_EMACPS_2_BASEADDR) {
+#ifdef XPAR_PSU_ETHERNET_2_ENET_SLCR_1000MBPS_DIV0
+                CrlApbDiv0 = XPAR_PSU_ETHERNET_2_ENET_SLCR_1000MBPS_DIV0;
+                CrlApbDiv1 = XPAR_PSU_ETHERNET_2_ENET_SLCR_1000MBPS_DIV1;
+#endif
+            } else if (mac_baseaddr == ZYNQMP_EMACPS_3_BASEADDR) {
+#ifdef XPAR_PSU_ETHERNET_3_ENET_SLCR_1000MBPS_DIV0
+                CrlApbDiv0 = XPAR_PSU_ETHERNET_3_ENET_SLCR_1000MBPS_DIV0;
+                CrlApbDiv1 = XPAR_PSU_ETHERNET_3_ENET_SLCR_1000MBPS_DIV1;
+#endif
+            }
+        } else if (speed == 100) {
+            if (mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR) {
+#ifdef XPAR_PSU_ETHERNET_0_ENET_SLCR_100MBPS_DIV0
+                CrlApbDiv0 = XPAR_PSU_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
+                CrlApbDiv1 = XPAR_PSU_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;
+#endif
+            } else if (mac_baseaddr == ZYNQMP_EMACPS_1_BASEADDR) {
+#ifdef XPAR_PSU_ETHERNET_1_ENET_SLCR_100MBPS_DIV0
+                CrlApbDiv0 = XPAR_PSU_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
+                CrlApbDiv1 = XPAR_PSU_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;
+#endif
+            } else if (mac_baseaddr == ZYNQMP_EMACPS_2_BASEADDR) {
+#ifdef XPAR_PSU_ETHERNET_2_ENET_SLCR_100MBPS_DIV0
+                CrlApbDiv0 = XPAR_PSU_ETHERNET_2_ENET_SLCR_100MBPS_DIV0;
+                CrlApbDiv1 = XPAR_PSU_ETHERNET_2_ENET_SLCR_100MBPS_DIV1;
+#endif
+            } else if (mac_baseaddr == ZYNQMP_EMACPS_3_BASEADDR) {
+#ifdef XPAR_PSU_ETHERNET_3_ENET_SLCR_100MBPS_DIV0
+                CrlApbDiv0 = XPAR_PSU_ETHERNET_3_ENET_SLCR_100MBPS_DIV0;
+                CrlApbDiv1 = XPAR_PSU_ETHERNET_3_ENET_SLCR_100MBPS_DIV1;
+#endif
+            }
+        } else {
+            if (mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR) {
+#ifdef XPAR_PSU_ETHERNET_0_ENET_SLCR_10MBPS_DIV0
+                CrlApbDiv0 = XPAR_PSU_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
+                CrlApbDiv1 = XPAR_PSU_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;
+#endif
+            } else if (mac_baseaddr == ZYNQMP_EMACPS_1_BASEADDR) {
+#ifdef XPAR_PSU_ETHERNET_1_ENET_SLCR_10MBPS_DIV0
+                CrlApbDiv0 = XPAR_PSU_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
+                CrlApbDiv1 = XPAR_PSU_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;
+#endif
+            } else if (mac_baseaddr == ZYNQMP_EMACPS_2_BASEADDR) {
+#ifdef XPAR_PSU_ETHERNET_2_ENET_SLCR_10MBPS_DIV0
+                CrlApbDiv0 = XPAR_PSU_ETHERNET_2_ENET_SLCR_10MBPS_DIV0;
+                CrlApbDiv1 = XPAR_PSU_ETHERNET_2_ENET_SLCR_10MBPS_DIV1;
+#endif
+            } else if (mac_baseaddr == ZYNQMP_EMACPS_3_BASEADDR) {
+#ifdef XPAR_PSU_ETHERNET_3_ENET_SLCR_10MBPS_DIV0
+                CrlApbDiv0 = XPAR_PSU_ETHERNET_3_ENET_SLCR_10MBPS_DIV0;
+                CrlApbDiv1 = XPAR_PSU_ETHERNET_3_ENET_SLCR_10MBPS_DIV1;
+#endif
+            }
+        }
+
+        if (CrlApbDiv0 != 0 && CrlApbDiv1 != 0) {
+        #if EL1_NONSECURE
+            XSmc_OutVar RegRead;
+            RegRead = Xil_Smc(MMIO_READ_SMC_FID, (u64)(CrlApbBaseAddr),
+                                0, 0, 0, 0, 0, 0);
+            CrlApbGemCtrl = RegRead.Arg0 >> 32;
+        #else
+            CrlApbGemCtrl = *(volatile u32_t *)(UINTPTR)(CrlApbBaseAddr);
+        #endif
+            CrlApbGemCtrl &= ~CRL_APB_GEM_DIV0_MASK;
+            CrlApbGemCtrl |= CrlApbDiv0 << CRL_APB_GEM_DIV0_SHIFT;
+            CrlApbGemCtrl &= ~CRL_APB_GEM_DIV1_MASK;
+            CrlApbGemCtrl |= CrlApbDiv1 << CRL_APB_GEM_DIV1_SHIFT;
+        #if EL1_NONSECURE
+            Xil_Smc(MMIO_WRITE_SMC_FID, (u64)(CrlApbBaseAddr) | ((u64)(0xFFFFFFFF) << 32),
+                (u64)CrlApbGemCtrl, 0, 0, 0, 0, 0);
+            do {
+            RegRead = Xil_Smc(MMIO_READ_SMC_FID, (u64)(CrlApbBaseAddr),
+                0, 0, 0, 0, 0, 0);
+            } while((RegRead.Arg0 >> 32) != CrlApbGemCtrl);
+        #else
+            *(volatile u32_t *)(UINTPTR)(CrlApbBaseAddr) = CrlApbGemCtrl;
+        #endif
+        } else {
+            xil_printf("Clock Divisors incorrect - Please check\r\n");
+        }
+    } else if (gigeversion == GEM_VERSION_VERSAL) {
+        /* Setup divisors in CRL for Versal */
+        if (mac_baseaddr == VERSAL_EMACPS_0_BASEADDR) {
+            CrlApbBaseAddr = VERSAL_CRL_GEM0_REF_CTRL;
+#if EL1_NONSECURE
+            ClkId = CLK_GEM0_REF;
+#endif
+        } else if (mac_baseaddr == VERSAL_EMACPS_1_BASEADDR) {
+            CrlApbBaseAddr = VERSAL_CRL_GEM1_REF_CTRL;
+#if EL1_NONSECURE
+            ClkId = CLK_GEM1_REF;
+#endif
+        }
+
+        if (speed == 1000) {
+            if (mac_baseaddr == VERSAL_EMACPS_0_BASEADDR) {
+#ifdef XPAR_PSV_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0
+                CrlApbDiv0 = XPAR_PSV_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
+#endif
+            } else if (mac_baseaddr == VERSAL_EMACPS_1_BASEADDR) {
+#ifdef XPAR_PSV_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0
+                CrlApbDiv0 = XPAR_PSV_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
+#endif
+            }
+        } else if (speed == 100) {
+            if (mac_baseaddr == VERSAL_EMACPS_0_BASEADDR) {
+#ifdef XPAR_PSV_ETHERNET_0_ENET_SLCR_100MBPS_DIV0
+                CrlApbDiv0 = XPAR_PSV_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
+#endif
+            } else if (mac_baseaddr == VERSAL_EMACPS_1_BASEADDR) {
+#ifdef XPAR_PSV_ETHERNET_1_ENET_SLCR_100MBPS_DIV0
+                CrlApbDiv0 = XPAR_PSV_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
+#endif
+            }
+        } else {
+            if (mac_baseaddr == VERSAL_EMACPS_0_BASEADDR) {
+#ifdef XPAR_PSV_ETHERNET_0_ENET_SLCR_10MBPS_DIV0
+                CrlApbDiv0 = XPAR_PSV_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
+#endif
+            } else if (mac_baseaddr == VERSAL_EMACPS_1_BASEADDR) {
+#ifdef XPAR_PSV_ETHERNET_1_ENET_SLCR_10MBPS_DIV0
+                CrlApbDiv0 = XPAR_PSV_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
+#endif
+            }
+        }
+
+        if (CrlApbDiv0 != 0) {
+#if EL1_NONSECURE
+            Xil_Smc(PM_SET_DIVIDER_SMC_FID, (((u64)CrlApbDiv0 << 32) | ClkId), 0, 0, 0, 0, 0, 0);
+#else
+            CrlApbGemCtrl = Xil_In32((UINTPTR)CrlApbBaseAddr);
+            CrlApbGemCtrl &= ~VERSAL_CRL_GEM_DIV_MASK;
+            CrlApbGemCtrl |= CrlApbDiv0 << VERSAL_CRL_APB_GEM_DIV_SHIFT;
+
+            Xil_Out32((UINTPTR)CrlApbBaseAddr, CrlApbGemCtrl);
+#endif
+        } else {
+            xil_printf("Clock Divisors incorrect - Please check\r\n");
+        }
+    }
+
+    return;
+}

+ 44 - 0
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xlwipconfig.h

@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
+ * Copyright (C) 2007 - 2018 Xilinx, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+#ifndef __XLWIPCONFIG_H_
+#define __XLWIPCONFIG_H_
+
+
+/* This is a generated file - do not edit */
+
+#define XLWIP_CONFIG_INCLUDE_GEM 1
+#define XLWIP_CONFIG_EMAC_NUMBER 0
+#define XLWIP_CONFIG_N_TX_DESC 64
+#define XLWIP_CONFIG_N_RX_DESC 64
+
+#endif

+ 93 - 0
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xpqueue.c

@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2007 - 2019 Xilinx, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ */
+
+#include <stdlib.h>
+
+#include "netif/xpqueue.h"
+#include "xil_printf.h"
+
+#define NUM_QUEUES    2
+
+pq_queue_t pq_queue[NUM_QUEUES];
+
+pq_queue_t *
+pq_create_queue()
+{
+    static int i;
+    pq_queue_t *q = NULL;
+
+    if (i >= NUM_QUEUES) {
+        xil_printf("ERR: Max Queues allocated\n\r");
+        return q;
+    }
+
+    q = &pq_queue[i++];
+
+    if (!q)
+        return q;
+
+    q->head = q->tail = q->len = 0;
+
+    return q;
+}
+
+int
+pq_enqueue(pq_queue_t *q, void *p)
+{
+    if (q->len == PQ_QUEUE_SIZE)
+        return -1;
+
+    q->data[q->head] = p;
+    q->head = (q->head + 1)%PQ_QUEUE_SIZE;
+    q->len++;
+
+    return 0;
+}
+
+void*
+pq_dequeue(pq_queue_t *q)
+{
+    int ptail;
+
+    if (q->len == 0)
+        return NULL;
+
+    ptail = q->tail;
+    q->tail = (q->tail + 1)%PQ_QUEUE_SIZE;
+    q->len--;
+
+    return q->data[ptail];
+}
+
+int
+pq_qlength(pq_queue_t *q)
+{
+    return q->len;
+}

+ 15 - 0
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xemacpsif/xtopology_g.c

@@ -0,0 +1,15 @@
+#include "netif/xtopology.h"
+#include "xparameters.h"
+
+struct xtopology_t xtopology[] = {
+    {
+        0xFF0E0000,
+        xemac_type_emacps,
+        0x0,
+        0x0,
+        0xF8F00100,
+        XPAR_XEMACPS_3_INTR,
+    },
+};
+
+int xtopology_n_emacs = 1;

+ 34 - 34
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_io.h

@@ -20,7 +20,7 @@
 *
 * Ver   Who      Date     Changes
 * ----- -------- -------- -----------------------------------------------
-* 5.00 	pkp  	 05/29/14 First release
+* 5.00     pkp       05/29/14 First release
 * 6.00  mus      08/19/16 Remove checking of __LITTLE_ENDIAN__ flag for
 *                         ARM processors
 * 7.20  har      01/03/20 Added Xil_SecureOut32 for avoiding blindwrite for
@@ -54,15 +54,15 @@ extern "C" {
 *           from the specified address and returning the 8 bit Value read from
 *            that address.
 *
-* @param	Addr: contains the address to perform the input operation
+* @param    Addr: contains the address to perform the input operation
 *
-* @return	The 8 bit Value read from the specified input address.
+* @return    The 8 bit Value read from the specified input address.
 
 *
 ******************************************************************************/
 static INLINE u8 Xil_In8(UINTPTR Addr)
 {
-	return *(volatile u8 *) Addr;
+    return *(volatile u8 *) Addr;
 }
 
 /*****************************************************************************/
@@ -72,14 +72,14 @@ static INLINE u8 Xil_In8(UINTPTR Addr)
 *           the specified address and returning the 16 bit Value read from that
 *           address.
 *
-* @param	Addr: contains the address to perform the input operation
+* @param    Addr: contains the address to perform the input operation
 *
-* @return	The 16 bit Value read from the specified input address.
+* @return    The 16 bit Value read from the specified input address.
 *
 ******************************************************************************/
 static INLINE u16 Xil_In16(UINTPTR Addr)
 {
-	return *(volatile u16 *) Addr;
+    return *(volatile u16 *) Addr;
 }
 
 /*****************************************************************************/
@@ -89,14 +89,14 @@ static INLINE u16 Xil_In16(UINTPTR Addr)
 *           reading from the specified address and returning the 32 bit Value
 *           read  from that address.
 *
-* @param	Addr: contains the address to perform the input operation
+* @param    Addr: contains the address to perform the input operation
 *
-* @return	The 32 bit Value read from the specified input address.
+* @return    The 32 bit Value read from the specified input address.
 *
 ******************************************************************************/
 static INLINE u32 Xil_In32(UINTPTR Addr)
 {
-	return *(volatile u32 *) Addr;
+    return *(volatile u32 *) Addr;
 }
 
 /*****************************************************************************/
@@ -106,14 +106,14 @@ static INLINE u32 Xil_In32(UINTPTR Addr)
 *            64 bit Value read  from that address.
 *
 *
-* @param	Addr: contains the address to perform the input operation
+* @param    Addr: contains the address to perform the input operation
 *
-* @return	The 64 bit Value read from the specified input address.
+* @return    The 64 bit Value read from the specified input address.
 *
 ******************************************************************************/
 static INLINE u64 Xil_In64(UINTPTR Addr)
 {
-	return *(volatile u64 *) Addr;
+    return *(volatile u64 *) Addr;
 }
 
 /*****************************************************************************/
@@ -122,17 +122,17 @@ static INLINE u64 Xil_In64(UINTPTR Addr)
 * @brief    Performs an output operation for an memory location by
 *           writing the 8 bit Value to the the specified address.
 *
-* @param	Addr: contains the address to perform the output operation
-* @param	Value: contains the 8 bit Value to be written at the specified
+* @param    Addr: contains the address to perform the output operation
+* @param    Value: contains the 8 bit Value to be written at the specified
 *           address.
 *
-* @return	None.
+* @return    None.
 *
 ******************************************************************************/
 static INLINE void Xil_Out8(UINTPTR Addr, u8 Value)
 {
-	volatile u8 *LocalAddr = (volatile u8 *)Addr;
-	*LocalAddr = Value;
+    volatile u8 *LocalAddr = (volatile u8 *)Addr;
+    *LocalAddr = Value;
 }
 
 /*****************************************************************************/
@@ -141,16 +141,16 @@ static INLINE void Xil_Out8(UINTPTR Addr, u8 Value)
 * @brief    Performs an output operation for a memory location by writing the
 *            16 bit Value to the the specified address.
 *
-* @param	Addr contains the address to perform the output operation
-* @param	Value contains the Value to be written at the specified address.
+* @param    Addr contains the address to perform the output operation
+* @param    Value contains the Value to be written at the specified address.
 *
-* @return	None.
+* @return    None.
 *
 ******************************************************************************/
 static INLINE void Xil_Out16(UINTPTR Addr, u16 Value)
 {
-	volatile u16 *LocalAddr = (volatile u16 *)Addr;
-	*LocalAddr = Value;
+    volatile u16 *LocalAddr = (volatile u16 *)Addr;
+    *LocalAddr = Value;
 }
 
 /*****************************************************************************/
@@ -159,20 +159,20 @@ static INLINE void Xil_Out16(UINTPTR Addr, u16 Value)
 * @brief    Performs an output operation for a memory location by writing the
 *           32 bit Value to the the specified address.
 *
-* @param	Addr contains the address to perform the output operation
-* @param	Value contains the 32 bit Value to be written at the specified
+* @param    Addr contains the address to perform the output operation
+* @param    Value contains the 32 bit Value to be written at the specified
 *           address.
 *
-* @return	None.
+* @return    None.
 *
 ******************************************************************************/
 static INLINE void Xil_Out32(UINTPTR Addr, u32 Value)
 {
 #ifndef ENABLE_SAFETY
-	volatile u32 *LocalAddr = (volatile u32 *)Addr;
-	*LocalAddr = Value;
+    volatile u32 *LocalAddr = (volatile u32 *)Addr;
+    *LocalAddr = Value;
 #else
-	XStl_RegUpdate(Addr, Value);
+    XStl_RegUpdate(Addr, Value);
 #endif
 }
 
@@ -182,16 +182,16 @@ static INLINE void Xil_Out32(UINTPTR Addr, u32 Value)
 * @brief    Performs an output operation for a memory location by writing the
 *           64 bit Value to the the specified address.
 *
-* @param	Addr contains the address to perform the output operation
-* @param	Value contains 64 bit Value to be written at the specified address.
+* @param    Addr contains the address to perform the output operation
+* @param    Value contains 64 bit Value to be written at the specified address.
 *
-* @return	None.
+* @return    None.
 *
 ******************************************************************************/
 static INLINE void Xil_Out64(UINTPTR Addr, u64 Value)
 {
-	volatile u64 *LocalAddr = (volatile u64 *)Addr;
-	*LocalAddr = Value;
+    volatile u64 *LocalAddr = (volatile u64 *)Addr;
+    *LocalAddr = Value;
 }
 
 #ifdef __cplusplus

+ 1 - 1
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_printf.h

@@ -13,4 +13,4 @@ extern "C" {
 }
 #endif
 
-#endif	/* end of protection macro */
+#endif    /* end of protection macro */

+ 16 - 13
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xil_types.h

@@ -1,5 +1,5 @@
-#ifndef XIL_TYPES_H	/* prevent circular inclusions */
-#define XIL_TYPES_H	/* by using protection macros */
+#ifndef XIL_TYPES_H    /* prevent circular inclusions */
+#define XIL_TYPES_H    /* by using protection macros */
 
 #include <rtdef.h>
 #include <stdint.h>
@@ -12,25 +12,25 @@ extern "C" {
 /************************** Constant Definitions *****************************/
 
 #ifndef TRUE
-#  define TRUE		1U
+#  define TRUE        1U
 #endif
 
 #ifndef FALSE
-#  define FALSE		0U
+#  define FALSE        0U
 #endif
 
 #ifndef NULL
-#define NULL		0U
+#define NULL        0U
 #endif
 
 #define XIL_COMPONENT_IS_READY     0x11111111U  /**< In device drivers, This macro will be
                                                  assigend to "IsReady" member of driver
-												 instance to indicate that driver
-												 instance is initialized and ready to use. */
+                                                 instance to indicate that driver
+                                                 instance is initialized and ready to use. */
 #define XIL_COMPONENT_IS_STARTED   0x22222222U  /**< In device drivers, This macro will be assigend to
                                                  "IsStarted" member of driver instance
-												 to indicate that driver instance is
-												 started and it can be enabled. */
+                                                 to indicate that driver instance is
+                                                 started and it can be enabled. */
 
 typedef rt_uint8_t u8;
 typedef rt_uint16_t u16;
@@ -54,6 +54,9 @@ typedef long LONG;
 typedef unsigned long ULONG;
 #endif
 
+#define ULONG64_HI_MASK    0xFFFFFFFF00000000U
+#define ULONG64_LO_MASK    ~ULONG64_HI_MASK
+
 /** @{ */
 /**
  * This data type defines an interrupt handler for a device.
@@ -70,15 +73,15 @@ typedef void (*XExceptionHandler) (void *InstancePtr);
 /************************** Constant Definitions *****************************/
 
 #ifndef TRUE
-#define TRUE		1U
+#define TRUE        1U
 #endif
 
 #ifndef FALSE
-#define FALSE		0U
+#define FALSE        0U
 #endif
 
 #ifndef NULL
-#define NULL		0U
+#define NULL        0U
 #endif
 
 #ifdef __cplusplus
@@ -90,7 +93,7 @@ typedef void (*XExceptionHandler) (void *InstancePtr);
 }
 #endif
 
-#endif	/* end of protection macro */
+#endif    /* end of protection macro */
 /**
 * @} End of "addtogroup common_types".
 */

+ 9 - 9
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xparameters.h

@@ -38,16 +38,16 @@
 
 /* Platform specific definitions */
 #define PLATFORM_ZYNQMP
- 
+
 /* Definitions for debug logic configuration in lockstep mode */
 #define LOCKSTEP_MODE_DEBUG 0U
- 
+
 /* Definitions for sleep timer configuration */
 #define XSLEEP_TIMER_IS_DEFAULT_TIMER
- 
+
 /* Definitions for processor access to RPU/IOU slcr address space*/
 #define PROCESSOR_ACCESS_VALUE 255
- 
+
 /******************************************************************/
 /* Definitions for driver AVBUF */
 #define XPAR_XAVBUF_NUM_INSTANCES 1
@@ -750,11 +750,11 @@
 #define  XPAR_PSU_IPI_1_INT_ID  65U
 
 /* Canonical definitions for peripheral psu_ipi_1 */
-#define  XPAR_XIPIPSU_0_DEVICE_ID	XPAR_PSU_IPI_1_DEVICE_ID
-#define  XPAR_XIPIPSU_0_BASE_ADDRESS	XPAR_PSU_IPI_1_S_AXI_BASEADDR
-#define  XPAR_XIPIPSU_0_BIT_MASK	XPAR_PSU_IPI_1_BIT_MASK
-#define  XPAR_XIPIPSU_0_BUFFER_INDEX	XPAR_PSU_IPI_1_BUFFER_INDEX
-#define  XPAR_XIPIPSU_0_INT_ID	XPAR_PSU_IPI_1_INT_ID
+#define  XPAR_XIPIPSU_0_DEVICE_ID    XPAR_PSU_IPI_1_DEVICE_ID
+#define  XPAR_XIPIPSU_0_BASE_ADDRESS    XPAR_PSU_IPI_1_S_AXI_BASEADDR
+#define  XPAR_XIPIPSU_0_BIT_MASK    XPAR_PSU_IPI_1_BIT_MASK
+#define  XPAR_XIPIPSU_0_BUFFER_INDEX    XPAR_PSU_IPI_1_BUFFER_INDEX
+#define  XPAR_XIPIPSU_0_INT_ID    XPAR_PSU_IPI_1_INT_ID
 
 #define  XPAR_XIPIPSU_NUM_TARGETS  7U
 

+ 208 - 208
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xparameters_ps.h

@@ -20,9 +20,9 @@
 *
 * Ver   Who     Date     Changes
 * ----- ------- -------- ---------------------------------------------------
-* 5.00  pkp  	02/29/14 Initial version
+* 5.00  pkp      02/29/14 Initial version
 * 6.0   mus     08/18/16 Defined ARMR5 flag
-* 7.2	pm	03/25/20 Add wakeup Interrupt Id for usbpsu controller
+* 7.2    pm    03/25/20 Add wakeup Interrupt Id for usbpsu controller
 * </pre>
 *
 ******************************************************************************/
@@ -48,105 +48,105 @@ extern "C" {
  */
 
 /* Canonical definitions for DDR MEMORY */
-#define XPAR_DDR_MEM_BASEADDR		0x00000000U
-#define XPAR_DDR_MEM_HIGHADDR		0x3FFFFFFFU
+#define XPAR_DDR_MEM_BASEADDR        0x00000000U
+#define XPAR_DDR_MEM_HIGHADDR        0x3FFFFFFFU
 
 /* Canonical definitions for Interrupts  */
-#define XPAR_XUARTPS_0_INTR		XPS_UART0_INT_ID
-#define XPAR_XUARTPS_1_INTR		XPS_UART1_INT_ID
-#define XPAR_XIICPS_0_INTR		XPS_I2C0_INT_ID
-#define XPAR_XIICPS_1_INTR		XPS_I2C1_INT_ID
-#define XPAR_XSPIPS_0_INTR		XPS_SPI0_INT_ID
-#define XPAR_XSPIPS_1_INTR		XPS_SPI1_INT_ID
-#define XPAR_XCANPS_0_INTR		XPS_CAN0_INT_ID
-#define XPAR_XCANPS_1_INTR		XPS_CAN1_INT_ID
-#define XPAR_XGPIOPS_0_INTR		XPS_GPIO_INT_ID
-#define XPAR_XEMACPS_0_INTR		XPS_GEM0_INT_ID
-#define XPAR_XEMACPS_0_WAKE_INTR	XPS_GEM0_WAKE_INT_ID
-#define XPAR_XEMACPS_1_INTR		XPS_GEM1_INT_ID
-#define XPAR_XEMACPS_1_WAKE_INTR	XPS_GEM1_WAKE_INT_ID
-#define XPAR_XEMACPS_2_INTR		XPS_GEM2_INT_ID
-#define XPAR_XEMACPS_2_WAKE_INTR	XPS_GEM2_WAKE_INT_ID
-#define XPAR_XEMACPS_3_INTR		XPS_GEM3_INT_ID
-#define XPAR_XEMACPS_3_WAKE_INTR	XPS_GEM3_WAKE_INT_ID
-#define XPAR_XSDIOPS_0_INTR		XPS_SDIO0_INT_ID
-#define XPAR_XQSPIPS_0_INTR		XPS_QSPI_INT_ID
-#define XPAR_XSDIOPS_1_INTR		XPS_SDIO1_INT_ID
-#define XPAR_XWDTPS_0_INTR		XPS_CSU_WDT_INT_ID
-#define XPAR_XWDTPS_1_INTR		XPS_LPD_SWDT_INT_ID
-#define XPAR_XWDTPS_2_INTR		XPS_FPD_SWDT_INT_ID
-#define XPAR_XDCFG_0_INTR		XPS_DVC_INT_ID
-#define XPAR_XTTCPS_0_INTR		XPS_TTC0_0_INT_ID
-#define XPAR_XTTCPS_1_INTR		XPS_TTC0_1_INT_ID
-#define XPAR_XTTCPS_2_INTR		XPS_TTC0_2_INT_ID
-#define XPAR_XTTCPS_3_INTR		XPS_TTC1_0_INT_ID
-#define XPAR_XTTCPS_4_INTR		XPS_TTC1_1_INT_ID
-#define XPAR_XTTCPS_5_INTR		XPS_TTC1_2_INT_ID
-#define XPAR_XTTCPS_6_INTR		XPS_TTC2_0_INT_ID
-#define XPAR_XTTCPS_7_INTR		XPS_TTC2_1_INT_ID
-#define XPAR_XTTCPS_8_INTR		XPS_TTC2_2_INT_ID
-#define XPAR_XTTCPS_9_INTR		XPS_TTC3_0_INT_ID
-#define XPAR_XTTCPS_10_INTR		XPS_TTC3_1_INT_ID
-#define XPAR_XTTCPS_11_INTR		XPS_TTC3_2_INT_ID
-#define XPAR_XNANDPS8_0_INTR        	XPS_NAND_INT_ID
-#define XPAR_XADMAPS_0_INTR 		XPS_ADMA_CH0_INT_ID
-#define XPAR_XADMAPS_1_INTR 		XPS_ADMA_CH1_INT_ID
-#define XPAR_XADMAPS_2_INTR		XPS_ADMA_CH2_INT_ID
-#define XPAR_XADMAPS_3_INTR 		XPS_ADMA_CH3_INT_ID
-#define XPAR_XADMAPS_4_INTR		XPS_ADMA_CH4_INT_ID
-#define XPAR_XADMAPS_5_INTR 		XPS_ADMA_CH5_INT_ID
-#define XPAR_XADMAPS_6_INTR 		XPS_ADMA_CH6_INT_ID
-#define XPAR_XADMAPS_7_INTR 		XPS_ADMA_CH7_INT_ID
-#define XPAR_XCSUDMA_INTR 		XPS_CSU_DMA_INT_ID
-#define XPAR_PSU_ADMA_0_INTR 		XPS_ADMA_CH0_INT_ID
-#define XPAR_PSU_ADMA_1_INTR 		XPS_ADMA_CH1_INT_ID
-#define XPAR_PSU_ADMA_2_INTR		XPS_ADMA_CH2_INT_ID
-#define XPAR_PSU_ADMA_3_INTR 		XPS_ADMA_CH3_INT_ID
-#define XPAR_PSU_ADMA_4_INTR		XPS_ADMA_CH4_INT_ID
-#define XPAR_PSU_ADMA_5_INTR 		XPS_ADMA_CH5_INT_ID
-#define XPAR_PSU_ADMA_6_INTR 		XPS_ADMA_CH6_INT_ID
-#define XPAR_PSU_ADMA_7_INTR 		XPS_ADMA_CH7_INT_ID
-#define XPAR_PSU_CSUDMA_INTR 		XPS_CSU_DMA_INT_ID
-#define XPAR_XMPU_LPD_INTR 		XPS_XMPU_LPD_INT_ID
-#define XPAR_XZDMAPS_0_INTR		XPS_ZDMA_CH0_INT_ID
-#define XPAR_XZDMAPS_1_INTR		XPS_ZDMA_CH1_INT_ID
-#define XPAR_XZDMAPS_2_INTR 		XPS_ZDMA_CH2_INT_ID
-#define XPAR_XZDMAPS_3_INTR 		XPS_ZDMA_CH3_INT_ID
-#define XPAR_XZDMAPS_4_INTR		XPS_ZDMA_CH4_INT_ID
-#define XPAR_XZDMAPS_5_INTR 		XPS_ZDMA_CH5_INT_ID
-#define XPAR_XZDMAPS_6_INTR 		XPS_ZDMA_CH6_INT_ID
-#define XPAR_XZDMAPS_7_INTR 		XPS_ZDMA_CH7_INT_ID
-#define XPAR_PSU_GDMA_0_INTR		XPS_ZDMA_CH0_INT_ID
-#define XPAR_PSU_GDMA_1_INTR		XPS_ZDMA_CH1_INT_ID
-#define XPAR_PSU_GDMA_2_INTR 		XPS_ZDMA_CH2_INT_ID
-#define XPAR_PSU_GDMA_3_INTR 		XPS_ZDMA_CH3_INT_ID
-#define XPAR_PSU_GDMA_4_INTR		XPS_ZDMA_CH4_INT_ID
-#define XPAR_PSU_GDMA_5_INTR 		XPS_ZDMA_CH5_INT_ID
-#define XPAR_PSU_GDMA_6_INTR 		XPS_ZDMA_CH6_INT_ID
-#define XPAR_PSU_GDMA_7_INTR 		XPS_ZDMA_CH7_INT_ID
-#define XPAR_XMPU_FPD_INTR 		XPS_XMPU_FPD_INT_ID
-#define XPAR_XCCI_FPD_INTR 		XPS_FPD_CCI_INT_ID
-#define XPAR_XSMMU_FPD_INTR 		XPS_FPD_SMMU_INT_ID
-#define XPAR_XUSBPS_0_INTR		XPS_USB3_0_ENDPT_INT_ID
-#define XPAR_XUSBPS_1_INTR		XPS_USB3_1_ENDPT_INT_ID
-#define XPAR_XUSBPS_0_WAKE_INTR		XPS_USB3_0_WAKE_INT_ID
-#define XPAR_XUSBPS_1_WAKE_INTR		XPS_USB3_1_WAKE_INT_ID
-#define	XPAR_XRTCPSU_ALARM_INTR 	XPS_RTC_ALARM_INT_ID
-#define	XPAR_XRTCPSU_SECONDS_INTR	XPS_RTC_SEC_INT_ID
-#define XPAR_XAPMPS_0_INTR		XPS_APM0_INT_ID
-#define XPAR_XAPMPS_1_INTR		XPS_APM1_INT_ID
-#define XPAR_XAPMPS_2_INTR		XPS_APM2_INT_ID
-#define XPAR_XAPMPS_5_INTR		XPS_APM5_INT_ID
-#define XPAR_XSYSMONPSU_INTR		XPS_AMS_INT_ID
+#define XPAR_XUARTPS_0_INTR        XPS_UART0_INT_ID
+#define XPAR_XUARTPS_1_INTR        XPS_UART1_INT_ID
+#define XPAR_XIICPS_0_INTR        XPS_I2C0_INT_ID
+#define XPAR_XIICPS_1_INTR        XPS_I2C1_INT_ID
+#define XPAR_XSPIPS_0_INTR        XPS_SPI0_INT_ID
+#define XPAR_XSPIPS_1_INTR        XPS_SPI1_INT_ID
+#define XPAR_XCANPS_0_INTR        XPS_CAN0_INT_ID
+#define XPAR_XCANPS_1_INTR        XPS_CAN1_INT_ID
+#define XPAR_XGPIOPS_0_INTR        XPS_GPIO_INT_ID
+#define XPAR_XEMACPS_0_INTR        XPS_GEM0_INT_ID
+#define XPAR_XEMACPS_0_WAKE_INTR    XPS_GEM0_WAKE_INT_ID
+#define XPAR_XEMACPS_1_INTR        XPS_GEM1_INT_ID
+#define XPAR_XEMACPS_1_WAKE_INTR    XPS_GEM1_WAKE_INT_ID
+#define XPAR_XEMACPS_2_INTR        XPS_GEM2_INT_ID
+#define XPAR_XEMACPS_2_WAKE_INTR    XPS_GEM2_WAKE_INT_ID
+#define XPAR_XEMACPS_3_INTR        XPS_GEM3_INT_ID
+#define XPAR_XEMACPS_3_WAKE_INTR    XPS_GEM3_WAKE_INT_ID
+#define XPAR_XSDIOPS_0_INTR        XPS_SDIO0_INT_ID
+#define XPAR_XQSPIPS_0_INTR        XPS_QSPI_INT_ID
+#define XPAR_XSDIOPS_1_INTR        XPS_SDIO1_INT_ID
+#define XPAR_XWDTPS_0_INTR        XPS_CSU_WDT_INT_ID
+#define XPAR_XWDTPS_1_INTR        XPS_LPD_SWDT_INT_ID
+#define XPAR_XWDTPS_2_INTR        XPS_FPD_SWDT_INT_ID
+#define XPAR_XDCFG_0_INTR        XPS_DVC_INT_ID
+#define XPAR_XTTCPS_0_INTR        XPS_TTC0_0_INT_ID
+#define XPAR_XTTCPS_1_INTR        XPS_TTC0_1_INT_ID
+#define XPAR_XTTCPS_2_INTR        XPS_TTC0_2_INT_ID
+#define XPAR_XTTCPS_3_INTR        XPS_TTC1_0_INT_ID
+#define XPAR_XTTCPS_4_INTR        XPS_TTC1_1_INT_ID
+#define XPAR_XTTCPS_5_INTR        XPS_TTC1_2_INT_ID
+#define XPAR_XTTCPS_6_INTR        XPS_TTC2_0_INT_ID
+#define XPAR_XTTCPS_7_INTR        XPS_TTC2_1_INT_ID
+#define XPAR_XTTCPS_8_INTR        XPS_TTC2_2_INT_ID
+#define XPAR_XTTCPS_9_INTR        XPS_TTC3_0_INT_ID
+#define XPAR_XTTCPS_10_INTR        XPS_TTC3_1_INT_ID
+#define XPAR_XTTCPS_11_INTR        XPS_TTC3_2_INT_ID
+#define XPAR_XNANDPS8_0_INTR            XPS_NAND_INT_ID
+#define XPAR_XADMAPS_0_INTR         XPS_ADMA_CH0_INT_ID
+#define XPAR_XADMAPS_1_INTR         XPS_ADMA_CH1_INT_ID
+#define XPAR_XADMAPS_2_INTR        XPS_ADMA_CH2_INT_ID
+#define XPAR_XADMAPS_3_INTR         XPS_ADMA_CH3_INT_ID
+#define XPAR_XADMAPS_4_INTR        XPS_ADMA_CH4_INT_ID
+#define XPAR_XADMAPS_5_INTR         XPS_ADMA_CH5_INT_ID
+#define XPAR_XADMAPS_6_INTR         XPS_ADMA_CH6_INT_ID
+#define XPAR_XADMAPS_7_INTR         XPS_ADMA_CH7_INT_ID
+#define XPAR_XCSUDMA_INTR         XPS_CSU_DMA_INT_ID
+#define XPAR_PSU_ADMA_0_INTR         XPS_ADMA_CH0_INT_ID
+#define XPAR_PSU_ADMA_1_INTR         XPS_ADMA_CH1_INT_ID
+#define XPAR_PSU_ADMA_2_INTR        XPS_ADMA_CH2_INT_ID
+#define XPAR_PSU_ADMA_3_INTR         XPS_ADMA_CH3_INT_ID
+#define XPAR_PSU_ADMA_4_INTR        XPS_ADMA_CH4_INT_ID
+#define XPAR_PSU_ADMA_5_INTR         XPS_ADMA_CH5_INT_ID
+#define XPAR_PSU_ADMA_6_INTR         XPS_ADMA_CH6_INT_ID
+#define XPAR_PSU_ADMA_7_INTR         XPS_ADMA_CH7_INT_ID
+#define XPAR_PSU_CSUDMA_INTR         XPS_CSU_DMA_INT_ID
+#define XPAR_XMPU_LPD_INTR         XPS_XMPU_LPD_INT_ID
+#define XPAR_XZDMAPS_0_INTR        XPS_ZDMA_CH0_INT_ID
+#define XPAR_XZDMAPS_1_INTR        XPS_ZDMA_CH1_INT_ID
+#define XPAR_XZDMAPS_2_INTR         XPS_ZDMA_CH2_INT_ID
+#define XPAR_XZDMAPS_3_INTR         XPS_ZDMA_CH3_INT_ID
+#define XPAR_XZDMAPS_4_INTR        XPS_ZDMA_CH4_INT_ID
+#define XPAR_XZDMAPS_5_INTR         XPS_ZDMA_CH5_INT_ID
+#define XPAR_XZDMAPS_6_INTR         XPS_ZDMA_CH6_INT_ID
+#define XPAR_XZDMAPS_7_INTR         XPS_ZDMA_CH7_INT_ID
+#define XPAR_PSU_GDMA_0_INTR        XPS_ZDMA_CH0_INT_ID
+#define XPAR_PSU_GDMA_1_INTR        XPS_ZDMA_CH1_INT_ID
+#define XPAR_PSU_GDMA_2_INTR         XPS_ZDMA_CH2_INT_ID
+#define XPAR_PSU_GDMA_3_INTR         XPS_ZDMA_CH3_INT_ID
+#define XPAR_PSU_GDMA_4_INTR        XPS_ZDMA_CH4_INT_ID
+#define XPAR_PSU_GDMA_5_INTR         XPS_ZDMA_CH5_INT_ID
+#define XPAR_PSU_GDMA_6_INTR         XPS_ZDMA_CH6_INT_ID
+#define XPAR_PSU_GDMA_7_INTR         XPS_ZDMA_CH7_INT_ID
+#define XPAR_XMPU_FPD_INTR         XPS_XMPU_FPD_INT_ID
+#define XPAR_XCCI_FPD_INTR         XPS_FPD_CCI_INT_ID
+#define XPAR_XSMMU_FPD_INTR         XPS_FPD_SMMU_INT_ID
+#define XPAR_XUSBPS_0_INTR        XPS_USB3_0_ENDPT_INT_ID
+#define XPAR_XUSBPS_1_INTR        XPS_USB3_1_ENDPT_INT_ID
+#define XPAR_XUSBPS_0_WAKE_INTR        XPS_USB3_0_WAKE_INT_ID
+#define XPAR_XUSBPS_1_WAKE_INTR        XPS_USB3_1_WAKE_INT_ID
+#define    XPAR_XRTCPSU_ALARM_INTR     XPS_RTC_ALARM_INT_ID
+#define    XPAR_XRTCPSU_SECONDS_INTR    XPS_RTC_SEC_INT_ID
+#define XPAR_XAPMPS_0_INTR        XPS_APM0_INT_ID
+#define XPAR_XAPMPS_1_INTR        XPS_APM1_INT_ID
+#define XPAR_XAPMPS_2_INTR        XPS_APM2_INT_ID
+#define XPAR_XAPMPS_5_INTR        XPS_APM5_INT_ID
+#define XPAR_XSYSMONPSU_INTR        XPS_AMS_INT_ID
 
 /* Canonical definitions for SCU GIC */
-#define XPAR_SCUGIC_NUM_INSTANCES	1U
-#define XPAR_SCUGIC_SINGLE_DEVICE_ID	0U
-#define XPAR_SCUGIC_CPU_BASEADDR	(XPS_SCU_PERIPH_BASE + 0x00001000U)
-#define XPAR_SCUGIC_DIST_BASEADDR	(XPS_SCU_PERIPH_BASE + 0x00002000U)
-#define XPAR_SCUGIC_ACK_BEFORE		0U
+#define XPAR_SCUGIC_NUM_INSTANCES    1U
+#define XPAR_SCUGIC_SINGLE_DEVICE_ID    0U
+#define XPAR_SCUGIC_CPU_BASEADDR    (XPS_SCU_PERIPH_BASE + 0x00001000U)
+#define XPAR_SCUGIC_DIST_BASEADDR    (XPS_SCU_PERIPH_BASE + 0x00002000U)
+#define XPAR_SCUGIC_ACK_BEFORE        0U
 
-#define XPAR_CPU_CORTEXR5_CORE_CLOCK_FREQ_HZ	XPAR_CPU_CORTEXR5_0_CPU_CLK_FREQ_HZ
+#define XPAR_CPU_CORTEXR5_CORE_CLOCK_FREQ_HZ    XPAR_CPU_CORTEXR5_0_CPU_CLK_FREQ_HZ
 
 
 /*
@@ -154,98 +154,98 @@ extern "C" {
  * within the hardblock. These have been put for bacwards compatibility
  */
 
-#define XPS_SYS_CTRL_BASEADDR	0xFF180000U
-#define XPS_SCU_PERIPH_BASE		0xF9000000U
+#define XPS_SYS_CTRL_BASEADDR    0xFF180000U
+#define XPS_SCU_PERIPH_BASE        0xF9000000U
 
 
 /* Shared Peripheral Interrupts (SPI) */
-#define XPS_FPGA0_INT_ID		121U
-#define XPS_FPGA1_INT_ID		122U
-#define XPS_FPGA2_INT_ID		123U
-#define XPS_FPGA3_INT_ID		124U
-#define XPS_FPGA4_INT_ID		125U
-#define XPS_FPGA5_INT_ID		126U
-#define XPS_FPGA6_INT_ID		127U
-#define XPS_FPGA7_INT_ID		128U
-#define XPS_FPGA8_INT_ID		136U
-#define XPS_FPGA9_INT_ID		137U
-#define XPS_FPGA10_INT_ID		138U
-#define XPS_FPGA11_INT_ID		139U
-#define XPS_FPGA12_INT_ID		140U
-#define XPS_FPGA13_INT_ID		141U
-#define XPS_FPGA14_INT_ID		142U
-#define XPS_FPGA15_INT_ID		143U
+#define XPS_FPGA0_INT_ID        121U
+#define XPS_FPGA1_INT_ID        122U
+#define XPS_FPGA2_INT_ID        123U
+#define XPS_FPGA3_INT_ID        124U
+#define XPS_FPGA4_INT_ID        125U
+#define XPS_FPGA5_INT_ID        126U
+#define XPS_FPGA6_INT_ID        127U
+#define XPS_FPGA7_INT_ID        128U
+#define XPS_FPGA8_INT_ID        136U
+#define XPS_FPGA9_INT_ID        137U
+#define XPS_FPGA10_INT_ID        138U
+#define XPS_FPGA11_INT_ID        139U
+#define XPS_FPGA12_INT_ID        140U
+#define XPS_FPGA13_INT_ID        141U
+#define XPS_FPGA14_INT_ID        142U
+#define XPS_FPGA15_INT_ID        143U
 
 /* Updated Interrupt-IDs */
-#define XPS_OCMINTR_INT_ID		(10U + 32U)
-#define XPS_NAND_INT_ID        		(14U + 32U)
-#define XPS_QSPI_INT_ID			(15U + 32U)
-#define XPS_GPIO_INT_ID			(16U + 32U)
-#define XPS_I2C0_INT_ID			(17U + 32U)
-#define XPS_I2C1_INT_ID			(18U + 32U)
-#define XPS_SPI0_INT_ID			(19U + 32U)
-#define XPS_SPI1_INT_ID			(20U + 32U)
-#define XPS_UART0_INT_ID		(21U + 32U)
-#define XPS_UART1_INT_ID		(22U + 32U)
-#define XPS_CAN0_INT_ID			(23U + 32U)
-#define XPS_CAN1_INT_ID			(24U + 32U)
-#define	XPS_RTC_ALARM_INT_ID 	(26U + 32U)
-#define	XPS_RTC_SEC_INT_ID	 	(27U + 32U)
-#define XPS_LPD_SWDT_INT_ID		(52U + 32U)
-#define XPS_CSU_WDT_INT_ID	    (53U + 32U)
-#define XPS_FPD_SWDT_INT_ID		(113U + 32U)
-#define XPS_TTC0_0_INT_ID		(36U + 32U)
-#define XPS_TTC0_1_INT_ID		(37U + 32U)
-#define XPS_TTC0_2_INT_ID 		(38U + 32U)
-#define XPS_TTC1_0_INT_ID		(39U + 32U)
-#define XPS_TTC1_1_INT_ID		(40U + 32U)
-#define XPS_TTC1_2_INT_ID		(41U + 32U)
-#define XPS_TTC2_0_INT_ID		(42U + 32U)
-#define XPS_TTC2_1_INT_ID		(43U + 32U)
-#define XPS_TTC2_2_INT_ID		(44U + 32U)
-#define XPS_TTC3_0_INT_ID		(45U + 32U)
-#define XPS_TTC3_1_INT_ID		(46U + 32U)
-#define XPS_TTC3_2_INT_ID		(47U + 32U)
-#define XPS_SDIO0_INT_ID		(48U + 32U)
-#define XPS_SDIO1_INT_ID		(49U + 32U)
-#define XPS_AMS_INT_ID			(56U + 32U)
-#define XPS_GEM0_INT_ID			(57U + 32U)
-#define XPS_GEM0_WAKE_INT_ID		(58U + 32U)
-#define XPS_GEM1_INT_ID			(59U + 32U)
-#define XPS_GEM1_WAKE_INT_ID		(60U + 32U)
-#define XPS_GEM2_INT_ID			(61U + 32U)
-#define XPS_GEM2_WAKE_INT_ID		(62U + 32U)
-#define XPS_GEM3_INT_ID			(63U + 32U)
-#define XPS_GEM3_WAKE_INT_ID		(64U + 32U)
-#define XPS_USB3_0_ENDPT_INT_ID		(65U + 32U)
-#define XPS_USB3_1_ENDPT_INT_ID		(70U + 32U)
-#define XPS_USB3_0_WAKE_INT_ID		(75U + 32U)
-#define XPS_USB3_1_WAKE_INT_ID		(76U + 32U)
-#define XPS_ADMA_CH0_INT_ID		(77U + 32U)
-#define XPS_ADMA_CH1_INT_ID		(78U + 32U)
-#define XPS_ADMA_CH2_INT_ID		(79U + 32U)
-#define XPS_ADMA_CH3_INT_ID		(80U + 32U)
-#define XPS_ADMA_CH4_INT_ID		(81U + 32U)
-#define XPS_ADMA_CH5_INT_ID		(82U + 32U)
-#define XPS_ADMA_CH6_INT_ID		(83U + 32U)
-#define XPS_ADMA_CH7_INT_ID		(84U + 32U)
-#define XPS_CSU_DMA_INT_ID		(86U + 32U)
-#define XPS_XMPU_LPD_INT_ID		(88U + 32U)
-#define XPS_ZDMA_CH0_INT_ID		(124U + 32U)
-#define XPS_ZDMA_CH1_INT_ID		(125U + 32U)
-#define XPS_ZDMA_CH2_INT_ID		(126U + 32U)
-#define XPS_ZDMA_CH3_INT_ID		(127U + 32U)
-#define XPS_ZDMA_CH4_INT_ID		(128U + 32U)
-#define XPS_ZDMA_CH5_INT_ID		(129U + 32U)
-#define XPS_ZDMA_CH6_INT_ID		(130U + 32U)
-#define XPS_ZDMA_CH7_INT_ID		(131U + 32U)
-#define XPS_XMPU_FPD_INT_ID		(134U + 32U)
-#define XPS_FPD_CCI_INT_ID		(154U + 32U)
-#define XPS_FPD_SMMU_INT_ID		(155U + 32U)
-#define XPS_APM0_INT_ID		(123U + 32U)
-#define XPS_APM1_INT_ID		(25U + 32U)
-#define XPS_APM2_INT_ID		(25U + 32U)
-#define XPS_APM5_INT_ID		(123U + 32U)
+#define XPS_OCMINTR_INT_ID        (10U + 32U)
+#define XPS_NAND_INT_ID                (14U + 32U)
+#define XPS_QSPI_INT_ID            (15U + 32U)
+#define XPS_GPIO_INT_ID            (16U + 32U)
+#define XPS_I2C0_INT_ID            (17U + 32U)
+#define XPS_I2C1_INT_ID            (18U + 32U)
+#define XPS_SPI0_INT_ID            (19U + 32U)
+#define XPS_SPI1_INT_ID            (20U + 32U)
+#define XPS_UART0_INT_ID        (21U + 32U)
+#define XPS_UART1_INT_ID        (22U + 32U)
+#define XPS_CAN0_INT_ID            (23U + 32U)
+#define XPS_CAN1_INT_ID            (24U + 32U)
+#define    XPS_RTC_ALARM_INT_ID     (26U + 32U)
+#define    XPS_RTC_SEC_INT_ID         (27U + 32U)
+#define XPS_LPD_SWDT_INT_ID        (52U + 32U)
+#define XPS_CSU_WDT_INT_ID        (53U + 32U)
+#define XPS_FPD_SWDT_INT_ID        (113U + 32U)
+#define XPS_TTC0_0_INT_ID        (36U + 32U)
+#define XPS_TTC0_1_INT_ID        (37U + 32U)
+#define XPS_TTC0_2_INT_ID         (38U + 32U)
+#define XPS_TTC1_0_INT_ID        (39U + 32U)
+#define XPS_TTC1_1_INT_ID        (40U + 32U)
+#define XPS_TTC1_2_INT_ID        (41U + 32U)
+#define XPS_TTC2_0_INT_ID        (42U + 32U)
+#define XPS_TTC2_1_INT_ID        (43U + 32U)
+#define XPS_TTC2_2_INT_ID        (44U + 32U)
+#define XPS_TTC3_0_INT_ID        (45U + 32U)
+#define XPS_TTC3_1_INT_ID        (46U + 32U)
+#define XPS_TTC3_2_INT_ID        (47U + 32U)
+#define XPS_SDIO0_INT_ID        (48U + 32U)
+#define XPS_SDIO1_INT_ID        (49U + 32U)
+#define XPS_AMS_INT_ID            (56U + 32U)
+#define XPS_GEM0_INT_ID            (57U + 32U)
+#define XPS_GEM0_WAKE_INT_ID        (58U + 32U)
+#define XPS_GEM1_INT_ID            (59U + 32U)
+#define XPS_GEM1_WAKE_INT_ID        (60U + 32U)
+#define XPS_GEM2_INT_ID            (61U + 32U)
+#define XPS_GEM2_WAKE_INT_ID        (62U + 32U)
+#define XPS_GEM3_INT_ID            (63U + 32U)
+#define XPS_GEM3_WAKE_INT_ID        (64U + 32U)
+#define XPS_USB3_0_ENDPT_INT_ID        (65U + 32U)
+#define XPS_USB3_1_ENDPT_INT_ID        (70U + 32U)
+#define XPS_USB3_0_WAKE_INT_ID        (75U + 32U)
+#define XPS_USB3_1_WAKE_INT_ID        (76U + 32U)
+#define XPS_ADMA_CH0_INT_ID        (77U + 32U)
+#define XPS_ADMA_CH1_INT_ID        (78U + 32U)
+#define XPS_ADMA_CH2_INT_ID        (79U + 32U)
+#define XPS_ADMA_CH3_INT_ID        (80U + 32U)
+#define XPS_ADMA_CH4_INT_ID        (81U + 32U)
+#define XPS_ADMA_CH5_INT_ID        (82U + 32U)
+#define XPS_ADMA_CH6_INT_ID        (83U + 32U)
+#define XPS_ADMA_CH7_INT_ID        (84U + 32U)
+#define XPS_CSU_DMA_INT_ID        (86U + 32U)
+#define XPS_XMPU_LPD_INT_ID        (88U + 32U)
+#define XPS_ZDMA_CH0_INT_ID        (124U + 32U)
+#define XPS_ZDMA_CH1_INT_ID        (125U + 32U)
+#define XPS_ZDMA_CH2_INT_ID        (126U + 32U)
+#define XPS_ZDMA_CH3_INT_ID        (127U + 32U)
+#define XPS_ZDMA_CH4_INT_ID        (128U + 32U)
+#define XPS_ZDMA_CH5_INT_ID        (129U + 32U)
+#define XPS_ZDMA_CH6_INT_ID        (130U + 32U)
+#define XPS_ZDMA_CH7_INT_ID        (131U + 32U)
+#define XPS_XMPU_FPD_INT_ID        (134U + 32U)
+#define XPS_FPD_CCI_INT_ID        (154U + 32U)
+#define XPS_FPD_SMMU_INT_ID        (155U + 32U)
+#define XPS_APM0_INT_ID        (123U + 32U)
+#define XPS_APM1_INT_ID        (25U + 32U)
+#define XPS_APM2_INT_ID        (25U + 32U)
+#define XPS_APM5_INT_ID        (123U + 32U)
 
 /* REDEFINES for TEST APP */
 #define XPAR_PSU_UART_0_INTR        XPS_UART0_INT_ID
@@ -268,8 +268,8 @@ extern "C" {
 #define XPAR_PSU_ETHERNET_3_INTR    XPS_GEM3_INT_ID
 #define XPAR_PSU_ETHERNET_3_WAKE_INTR   XPS_GEM3_WAKE_INT_ID
 #define XPAR_PSU_QSPI_0_INTR        XPS_QSPI_INT_ID
-#define XPAR_PSU_WDT_0_INTR    		XPS_LPD_SWDT_INT_ID
-#define XPAR_PSU_WDT_1_INTR     	XPS_FPD_SWDT_INT_ID
+#define XPAR_PSU_WDT_0_INTR            XPS_LPD_SWDT_INT_ID
+#define XPAR_PSU_WDT_1_INTR         XPS_FPD_SWDT_INT_ID
 #define XPAR_PSU_XADC_0_INTR        XPS_SYSMON_INT_ID
 #define XPAR_PSU_TTC_0_INTR         XPS_TTC0_0_INT_ID
 #define XPAR_PSU_TTC_1_INTR         XPS_TTC0_1_INT_ID
@@ -277,42 +277,42 @@ extern "C" {
 #define XPAR_PSU_TTC_3_INTR         XPS_TTC1_0_INT_ID
 #define XPAR_PSU_TTC_4_INTR         XPS_TTC1_1_INT_ID
 #define XPAR_PSU_TTC_5_INTR         XPS_TTC1_2_INT_ID
-#define XPAR_PSU_TTC_6_INTR			XPS_TTC2_0_INT_ID
-#define XPAR_PSU_TTC_7_INTR			XPS_TTC2_1_INT_ID
-#define XPAR_PSU_TTC_8_INTR			XPS_TTC2_2_INT_ID
-#define XPAR_PSU_TTC_9_INTR			XPS_TTC3_0_INT_ID
-#define XPAR_PSU_TTC_10_INTR		XPS_TTC3_1_INT_ID
-#define XPAR_PSU_TTC_11_INTR		XPS_TTC3_2_INT_ID
-#define XPAR_PSU_AMS_INTR			XPS_AMS_INT_ID
+#define XPAR_PSU_TTC_6_INTR            XPS_TTC2_0_INT_ID
+#define XPAR_PSU_TTC_7_INTR            XPS_TTC2_1_INT_ID
+#define XPAR_PSU_TTC_8_INTR            XPS_TTC2_2_INT_ID
+#define XPAR_PSU_TTC_9_INTR            XPS_TTC3_0_INT_ID
+#define XPAR_PSU_TTC_10_INTR        XPS_TTC3_1_INT_ID
+#define XPAR_PSU_TTC_11_INTR        XPS_TTC3_2_INT_ID
+#define XPAR_PSU_AMS_INTR            XPS_AMS_INT_ID
 
 #define XPAR_XADCPS_NUM_INSTANCES 1U
 #define XPAR_XADCPS_0_DEVICE_ID   0U
-#define XPAR_XADCPS_0_BASEADDR	  (0xF8007000U)
-#define XPAR_XADCPS_INT_ID		XPS_SYSMON_INT_ID
+#define XPAR_XADCPS_0_BASEADDR      (0xF8007000U)
+#define XPAR_XADCPS_INT_ID        XPS_SYSMON_INT_ID
 
 /* For backwards compatibility */
-#define XPAR_XUARTPS_0_CLOCK_HZ		XPAR_XUARTPS_0_UART_CLK_FREQ_HZ
-#define XPAR_XUARTPS_1_CLOCK_HZ		XPAR_XUARTPS_1_UART_CLK_FREQ_HZ
-#define XPAR_XTTCPS_0_CLOCK_HZ		XPAR_XTTCPS_0_TTC_CLK_FREQ_HZ
-#define XPAR_XTTCPS_1_CLOCK_HZ		XPAR_XTTCPS_1_TTC_CLK_FREQ_HZ
-#define XPAR_XTTCPS_2_CLOCK_HZ		XPAR_XTTCPS_2_TTC_CLK_FREQ_HZ
-#define XPAR_XTTCPS_3_CLOCK_HZ		XPAR_XTTCPS_3_TTC_CLK_FREQ_HZ
-#define XPAR_XTTCPS_4_CLOCK_HZ		XPAR_XTTCPS_4_TTC_CLK_FREQ_HZ
-#define XPAR_XTTCPS_5_CLOCK_HZ		XPAR_XTTCPS_5_TTC_CLK_FREQ_HZ
-#define XPAR_XIICPS_0_CLOCK_HZ		XPAR_XIICPS_0_I2C_CLK_FREQ_HZ
-#define XPAR_XIICPS_1_CLOCK_HZ		XPAR_XIICPS_1_I2C_CLK_FREQ_HZ
+#define XPAR_XUARTPS_0_CLOCK_HZ        XPAR_XUARTPS_0_UART_CLK_FREQ_HZ
+#define XPAR_XUARTPS_1_CLOCK_HZ        XPAR_XUARTPS_1_UART_CLK_FREQ_HZ
+#define XPAR_XTTCPS_0_CLOCK_HZ        XPAR_XTTCPS_0_TTC_CLK_FREQ_HZ
+#define XPAR_XTTCPS_1_CLOCK_HZ        XPAR_XTTCPS_1_TTC_CLK_FREQ_HZ
+#define XPAR_XTTCPS_2_CLOCK_HZ        XPAR_XTTCPS_2_TTC_CLK_FREQ_HZ
+#define XPAR_XTTCPS_3_CLOCK_HZ        XPAR_XTTCPS_3_TTC_CLK_FREQ_HZ
+#define XPAR_XTTCPS_4_CLOCK_HZ        XPAR_XTTCPS_4_TTC_CLK_FREQ_HZ
+#define XPAR_XTTCPS_5_CLOCK_HZ        XPAR_XTTCPS_5_TTC_CLK_FREQ_HZ
+#define XPAR_XIICPS_0_CLOCK_HZ        XPAR_XIICPS_0_I2C_CLK_FREQ_HZ
+#define XPAR_XIICPS_1_CLOCK_HZ        XPAR_XIICPS_1_I2C_CLK_FREQ_HZ
 
-#define XPAR_XQSPIPS_0_CLOCK_HZ		XPAR_XQSPIPS_0_QSPI_CLK_FREQ_HZ
+#define XPAR_XQSPIPS_0_CLOCK_HZ        XPAR_XQSPIPS_0_QSPI_CLK_FREQ_HZ
 
 #ifdef XPAR_CPU_CORTEXR5_0_CPU_CLK_FREQ_HZ
-#define XPAR_CPU_CORTEXR5_CORE_CLOCK_FREQ_HZ	XPAR_CPU_CORTEXR5_0_CPU_CLK_FREQ_HZ
+#define XPAR_CPU_CORTEXR5_CORE_CLOCK_FREQ_HZ    XPAR_CPU_CORTEXR5_0_CPU_CLK_FREQ_HZ
 #endif
 
 #ifdef XPAR_CPU_CORTEXR5_1_CPU_CLK_FREQ_HZ
-#define XPAR_CPU_CORTEXR5_CORE_CLOCK_FREQ_HZ	XPAR_CPU_CORTEXR5_1_CPU_CLK_FREQ_HZ
+#define XPAR_CPU_CORTEXR5_CORE_CLOCK_FREQ_HZ    XPAR_CPU_CORTEXR5_1_CPU_CLK_FREQ_HZ
 #endif
 
-#define XPAR_SCUWDT_DEVICE_ID		0U
+#define XPAR_SCUWDT_DEVICE_ID        0U
 
 
 #ifdef __cplusplus

+ 9 - 9
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xplatform_info.h

@@ -1,5 +1,5 @@
-#ifndef XPLATFORM_INFO_H		/* prevent circular inclusions */
-#define XPLATFORM_INFO_H		/* by using protection macros */
+#ifndef XPLATFORM_INFO_H        /* prevent circular inclusions */
+#define XPLATFORM_INFO_H        /* by using protection macros */
 
 #include "xil_types.h"
 #include "xparameters.h"
@@ -12,12 +12,12 @@ extern "C" {
 #define XPAR_PMC_TAP_BASEADDR 0xF11A0000U
 #define XPAR_PMC_TAP_VERSION_OFFSET 0x00000004U
 #define XPLAT_PS_VERSION_ADDRESS (XPAR_PMC_TAP_BASEADDR + \
-									XPAR_PMC_TAP_VERSION_OFFSET)
+                                    XPAR_PMC_TAP_VERSION_OFFSET)
 #else
 #define XPAR_CSU_BASEADDR 0xFFCA0000U
-#define	XPAR_CSU_VER_OFFSET 0x00000044U
+#define    XPAR_CSU_VER_OFFSET 0x00000044U
 #define XPLAT_PS_VERSION_ADDRESS (XPAR_CSU_BASEADDR + \
-									XPAR_CSU_VER_OFFSET)
+                                    XPAR_CSU_VER_OFFSET)
 #endif
 #define XPLAT_ZYNQ_ULTRA_MP_SILICON 0x0
 #define XPLAT_ZYNQ_ULTRA_MP 0x1
@@ -44,13 +44,13 @@ extern "C" {
 static INLINE u32 XGetPlatform_Info()
 {
 #if defined (versal)
-	return XPLAT_VERSAL;
+    return XPLAT_VERSAL;
 #elif defined (ARMR5) || (__aarch64__) || (ARMA53_32) || (PSU_PMU)
-	return XPLAT_ZYNQ_ULTRA_MP;
+    return XPLAT_ZYNQ_ULTRA_MP;
 #elif (__microblaze__)
-	return XPLAT_MICROBLAZE;
+    return XPLAT_MICROBLAZE;
 #else
-	return XPLAT_ZYNQ;
+    return XPLAT_ZYNQ;
 #endif
 }
 

+ 265 - 265
bsp/zynqmp-r5-axu4ev/drivers/Zynq_HAL_Driver/xstatus.h

@@ -16,8 +16,8 @@
 * @{
 ******************************************************************************/
 
-#ifndef XSTATUS_H		/* prevent circular inclusions */
-#define XSTATUS_H		/* by using protection macros */
+#ifndef XSTATUS_H        /* prevent circular inclusions */
+#define XSTATUS_H        /* by using protection macros */
 
 #ifdef __cplusplus
 extern "C" {
@@ -42,53 +42,53 @@ extern "C" {
 #define XST_INVALID_VERSION             4L
 #define XST_DEVICE_IS_STARTED           5L
 #define XST_DEVICE_IS_STOPPED           6L
-#define XST_FIFO_ERROR                  7L	/*!< An error occurred during an
-						   operation with a FIFO such as
-						   an underrun or overrun, this
-						   error requires the device to
-						   be reset */
-#define XST_RESET_ERROR                 8L	/*!< An error occurred which requires
-						   the device to be reset */
-#define XST_DMA_ERROR                   9L	/*!< A DMA error occurred, this error
-						   typically requires the device
-						   using the DMA to be reset */
-#define XST_NOT_POLLED                  10L	/*!< The device is not configured for
-						   polled mode operation */
-#define XST_FIFO_NO_ROOM                11L	/*!< A FIFO did not have room to put
-						   the specified data into */
-#define XST_BUFFER_TOO_SMALL            12L	/*!< The buffer is not large enough
-						   to hold the expected data */
-#define XST_NO_DATA                     13L	/*!< There was no data available */
-#define XST_REGISTER_ERROR              14L	/*!< A register did not contain the
-						   expected value */
-#define XST_INVALID_PARAM               15L	/*!< An invalid parameter was passed
-						   into the function */
-#define XST_NOT_SGDMA                   16L	/*!< The device is not configured for
-						   scatter-gather DMA operation */
-#define XST_LOOPBACK_ERROR              17L	/*!< A loopback test failed */
-#define XST_NO_CALLBACK                 18L	/*!< A callback has not yet been
-						   registered */
-#define XST_NO_FEATURE                  19L	/*!< Device is not configured with
-						   the requested feature */
-#define XST_NOT_INTERRUPT               20L	/*!< Device is not configured for
-						   interrupt mode operation */
-#define XST_DEVICE_BUSY                 21L	/*!< Device is busy */
-#define XST_ERROR_COUNT_MAX             22L	/*!< The error counters of a device
-						   have maxed out */
-#define XST_IS_STARTED                  23L	/*!< Used when part of device is
-						   already started i.e.
-						   sub channel */
-#define XST_IS_STOPPED                  24L	/*!< Used when part of device is
-						   already stopped i.e.
-						   sub channel */
-#define XST_DATA_LOST                   26L	/*!< Driver defined error */
-#define XST_RECV_ERROR                  27L	/*!< Generic receive error */
-#define XST_SEND_ERROR                  28L	/*!< Generic transmit error */
-#define XST_NOT_ENABLED                 29L	/*!< A requested service is not
-						   available because it has not
-						   been enabled */
-#define XST_NO_ACCESS			30L	/* Generic access error */
-#define XST_TIMEOUT                     31L	/*!< Event timeout occurred */
+#define XST_FIFO_ERROR                  7L    /*!< An error occurred during an
+                           operation with a FIFO such as
+                           an underrun or overrun, this
+                           error requires the device to
+                           be reset */
+#define XST_RESET_ERROR                 8L    /*!< An error occurred which requires
+                           the device to be reset */
+#define XST_DMA_ERROR                   9L    /*!< A DMA error occurred, this error
+                           typically requires the device
+                           using the DMA to be reset */
+#define XST_NOT_POLLED                  10L    /*!< The device is not configured for
+                           polled mode operation */
+#define XST_FIFO_NO_ROOM                11L    /*!< A FIFO did not have room to put
+                           the specified data into */
+#define XST_BUFFER_TOO_SMALL            12L    /*!< The buffer is not large enough
+                           to hold the expected data */
+#define XST_NO_DATA                     13L    /*!< There was no data available */
+#define XST_REGISTER_ERROR              14L    /*!< A register did not contain the
+                           expected value */
+#define XST_INVALID_PARAM               15L    /*!< An invalid parameter was passed
+                           into the function */
+#define XST_NOT_SGDMA                   16L    /*!< The device is not configured for
+                           scatter-gather DMA operation */
+#define XST_LOOPBACK_ERROR              17L    /*!< A loopback test failed */
+#define XST_NO_CALLBACK                 18L    /*!< A callback has not yet been
+                           registered */
+#define XST_NO_FEATURE                  19L    /*!< Device is not configured with
+                           the requested feature */
+#define XST_NOT_INTERRUPT               20L    /*!< Device is not configured for
+                           interrupt mode operation */
+#define XST_DEVICE_BUSY                 21L    /*!< Device is busy */
+#define XST_ERROR_COUNT_MAX             22L    /*!< The error counters of a device
+                           have maxed out */
+#define XST_IS_STARTED                  23L    /*!< Used when part of device is
+                           already started i.e.
+                           sub channel */
+#define XST_IS_STOPPED                  24L    /*!< Used when part of device is
+                           already stopped i.e.
+                           sub channel */
+#define XST_DATA_LOST                   26L    /*!< Driver defined error */
+#define XST_RECV_ERROR                  27L    /*!< Generic receive error */
+#define XST_SEND_ERROR                  28L    /*!< Generic transmit error */
+#define XST_NOT_ENABLED                 29L    /*!< A requested service is not
+                           available because it has not
+                           been enabled */
+#define XST_NO_ACCESS            30L    /* Generic access error */
+#define XST_TIMEOUT                     31L    /*!< Event timeout occurred */
 
 /** @} */
 /***************** Utility Component statuses 401 - 500  *********************/
@@ -96,7 +96,7 @@ extern "C" {
 @name Utility Component Status Codes 401 - 500
 @{
 */
-#define XST_MEMTEST_FAILED              401L	/*!< Memory test failed */
+#define XST_MEMTEST_FAILED              401L    /*!< Memory test failed */
 
 /** @} */
 /***************** Common Components statuses 501 - 1000 *********************/
@@ -106,14 +106,14 @@ extern "C" {
 */
 /********************* Packet Fifo statuses 501 - 510 ************************/
 
-#define XST_PFIFO_LACK_OF_DATA          501L	/*!< Not enough data in FIFO   */
-#define XST_PFIFO_NO_ROOM               502L	/*!< Not enough room in FIFO   */
-#define XST_PFIFO_BAD_REG_VALUE         503L	/*!< Self test, a register value
-						   was invalid after reset */
-#define XST_PFIFO_ERROR                 504L	/*!< Generic packet FIFO error */
-#define XST_PFIFO_DEADLOCK              505L	/*!< Packet FIFO is reporting
-						 * empty and full simultaneously
-						 */
+#define XST_PFIFO_LACK_OF_DATA          501L    /*!< Not enough data in FIFO   */
+#define XST_PFIFO_NO_ROOM               502L    /*!< Not enough room in FIFO   */
+#define XST_PFIFO_BAD_REG_VALUE         503L    /*!< Self test, a register value
+                           was invalid after reset */
+#define XST_PFIFO_ERROR                 504L    /*!< Generic packet FIFO error */
+#define XST_PFIFO_DEADLOCK              505L    /*!< Packet FIFO is reporting
+                         * empty and full simultaneously
+                         */
 /** @} */
 /**
 @name DMA Status Codes 511 - 530
@@ -121,44 +121,44 @@ extern "C" {
 */
 /************************** DMA statuses 511 - 530 ***************************/
 
-#define XST_DMA_TRANSFER_ERROR          511L	/*!< Self test, DMA transfer
-						   failed */
-#define XST_DMA_RESET_REGISTER_ERROR    512L	/*!< Self test, a register value
-						   was invalid after reset */
-#define XST_DMA_SG_LIST_EMPTY           513L	/*!< Scatter gather list contains
-						   no buffer descriptors ready
-						   to be processed */
-#define XST_DMA_SG_IS_STARTED           514L	/*!< Scatter gather not stopped */
-#define XST_DMA_SG_IS_STOPPED           515L	/*!< Scatter gather not running */
-#define XST_DMA_SG_LIST_FULL            517L	/*!< All the buffer descriptors of
-						   the scatter gather list are
-						   being used */
-#define XST_DMA_SG_BD_LOCKED            518L	/*!< The scatter gather buffer
-						   descriptor which is to be
-						   copied over in the scatter
-						   list is locked */
-#define XST_DMA_SG_NOTHING_TO_COMMIT    519L	/*!< No buffer descriptors have been
-						   put into the scatter gather
-						   list to be committed */
-#define XST_DMA_SG_COUNT_EXCEEDED       521L	/*!< The packet count threshold
-						   specified was larger than the
-						   total # of buffer descriptors
-						   in the scatter gather list */
-#define XST_DMA_SG_LIST_EXISTS          522L	/*!< The scatter gather list has
-						   already been created */
-#define XST_DMA_SG_NO_LIST              523L	/*!< No scatter gather list has
-						   been created */
-#define XST_DMA_SG_BD_NOT_COMMITTED     524L	/*!< The buffer descriptor which was
-						   being started was not committed
-						   to the list */
-#define XST_DMA_SG_NO_DATA              525L	/*!< The buffer descriptor to start
-						   has already been used by the
-						   hardware so it can't be reused
-						 */
-#define XST_DMA_SG_LIST_ERROR           526L	/*!< General purpose list access
-						   error */
-#define XST_DMA_BD_ERROR                527L	/*!< General buffer descriptor
-						   error */
+#define XST_DMA_TRANSFER_ERROR          511L    /*!< Self test, DMA transfer
+                           failed */
+#define XST_DMA_RESET_REGISTER_ERROR    512L    /*!< Self test, a register value
+                           was invalid after reset */
+#define XST_DMA_SG_LIST_EMPTY           513L    /*!< Scatter gather list contains
+                           no buffer descriptors ready
+                           to be processed */
+#define XST_DMA_SG_IS_STARTED           514L    /*!< Scatter gather not stopped */
+#define XST_DMA_SG_IS_STOPPED           515L    /*!< Scatter gather not running */
+#define XST_DMA_SG_LIST_FULL            517L    /*!< All the buffer descriptors of
+                           the scatter gather list are
+                           being used */
+#define XST_DMA_SG_BD_LOCKED            518L    /*!< The scatter gather buffer
+                           descriptor which is to be
+                           copied over in the scatter
+                           list is locked */
+#define XST_DMA_SG_NOTHING_TO_COMMIT    519L    /*!< No buffer descriptors have been
+                           put into the scatter gather
+                           list to be committed */
+#define XST_DMA_SG_COUNT_EXCEEDED       521L    /*!< The packet count threshold
+                           specified was larger than the
+                           total # of buffer descriptors
+                           in the scatter gather list */
+#define XST_DMA_SG_LIST_EXISTS          522L    /*!< The scatter gather list has
+                           already been created */
+#define XST_DMA_SG_NO_LIST              523L    /*!< No scatter gather list has
+                           been created */
+#define XST_DMA_SG_BD_NOT_COMMITTED     524L    /*!< The buffer descriptor which was
+                           being started was not committed
+                           to the list */
+#define XST_DMA_SG_NO_DATA              525L    /*!< The buffer descriptor to start
+                           has already been used by the
+                           hardware so it can't be reused
+                         */
+#define XST_DMA_SG_LIST_ERROR           526L    /*!< General purpose list access
+                           error */
+#define XST_DMA_BD_ERROR                527L    /*!< General buffer descriptor
+                           error */
 /** @} */
 /**
 @name IPIF Status Codes Codes 531 - 550
@@ -166,34 +166,34 @@ extern "C" {
 */
 /************************** IPIF statuses 531 - 550 ***************************/
 
-#define XST_IPIF_REG_WIDTH_ERROR        531L	/*!< An invalid register width
-						   was passed into the function */
-#define XST_IPIF_RESET_REGISTER_ERROR   532L	/*!< The value of a register at
-						   reset was not valid */
-#define XST_IPIF_DEVICE_STATUS_ERROR    533L	/*!< A write to the device interrupt
-						   status register did not read
-						   back correctly */
-#define XST_IPIF_DEVICE_ACK_ERROR       534L	/*!< The device interrupt status
-						   register did not reset when
-						   acked */
-#define XST_IPIF_DEVICE_ENABLE_ERROR    535L	/*!< The device interrupt enable
-						   register was not updated when
-						   other registers changed */
-#define XST_IPIF_IP_STATUS_ERROR        536L	/*!< A write to the IP interrupt
-						   status register did not read
-						   back correctly */
-#define XST_IPIF_IP_ACK_ERROR           537L	/*!< The IP interrupt status register
-						   did not reset when acked */
-#define XST_IPIF_IP_ENABLE_ERROR        538L	/*!< IP interrupt enable register was
-						   not updated correctly when other
-						   registers changed */
-#define XST_IPIF_DEVICE_PENDING_ERROR   539L	/*!< The device interrupt pending
-						   register did not indicate the
-						   expected value */
-#define XST_IPIF_DEVICE_ID_ERROR        540L	/*!< The device interrupt ID register
-						   did not indicate the expected
-						   value */
-#define XST_IPIF_ERROR                  541L	/*!< Generic ipif error */
+#define XST_IPIF_REG_WIDTH_ERROR        531L    /*!< An invalid register width
+                           was passed into the function */
+#define XST_IPIF_RESET_REGISTER_ERROR   532L    /*!< The value of a register at
+                           reset was not valid */
+#define XST_IPIF_DEVICE_STATUS_ERROR    533L    /*!< A write to the device interrupt
+                           status register did not read
+                           back correctly */
+#define XST_IPIF_DEVICE_ACK_ERROR       534L    /*!< The device interrupt status
+                           register did not reset when
+                           acked */
+#define XST_IPIF_DEVICE_ENABLE_ERROR    535L    /*!< The device interrupt enable
+                           register was not updated when
+                           other registers changed */
+#define XST_IPIF_IP_STATUS_ERROR        536L    /*!< A write to the IP interrupt
+                           status register did not read
+                           back correctly */
+#define XST_IPIF_IP_ACK_ERROR           537L    /*!< The IP interrupt status register
+                           did not reset when acked */
+#define XST_IPIF_IP_ENABLE_ERROR        538L    /*!< IP interrupt enable register was
+                           not updated correctly when other
+                           registers changed */
+#define XST_IPIF_DEVICE_PENDING_ERROR   539L    /*!< The device interrupt pending
+                           register did not indicate the
+                           expected value */
+#define XST_IPIF_DEVICE_ID_ERROR        540L    /*!< The device interrupt ID register
+                           did not indicate the expected
+                           value */
+#define XST_IPIF_ERROR                  541L    /*!< Generic ipif error */
 /** @} */
 
 /****************** Device specific statuses 1001 - 4095 *********************/
@@ -203,16 +203,16 @@ extern "C" {
 */
 /********************* Ethernet statuses 1001 - 1050 *************************/
 
-#define XST_EMAC_MEMORY_SIZE_ERROR  1001L	/*!< Memory space is not big enough
-						 * to hold the minimum number of
-						 * buffers or descriptors */
-#define XST_EMAC_MEMORY_ALLOC_ERROR 1002L	/*!< Memory allocation failed */
-#define XST_EMAC_MII_READ_ERROR     1003L	/*!< MII read error */
-#define XST_EMAC_MII_BUSY           1004L	/*!< An MII operation is in progress */
-#define XST_EMAC_OUT_OF_BUFFERS     1005L	/*!< Driver is out of buffers */
-#define XST_EMAC_PARSE_ERROR        1006L	/*!< Invalid driver init string */
-#define XST_EMAC_COLLISION_ERROR    1007L	/*!< Excess deferral or late
-						 * collision on polled send */
+#define XST_EMAC_MEMORY_SIZE_ERROR  1001L    /*!< Memory space is not big enough
+                         * to hold the minimum number of
+                         * buffers or descriptors */
+#define XST_EMAC_MEMORY_ALLOC_ERROR 1002L    /*!< Memory allocation failed */
+#define XST_EMAC_MII_READ_ERROR     1003L    /*!< MII read error */
+#define XST_EMAC_MII_BUSY           1004L    /*!< An MII operation is in progress */
+#define XST_EMAC_OUT_OF_BUFFERS     1005L    /*!< Driver is out of buffers */
+#define XST_EMAC_PARSE_ERROR        1006L    /*!< Invalid driver init string */
+#define XST_EMAC_COLLISION_ERROR    1007L    /*!< Excess deferral or late
+                         * collision on polled send */
 /** @} */
 /**
 @name UART Status Codes 1051 - 1075
@@ -235,30 +235,30 @@ extern "C" {
 */
 /************************ IIC statuses 1076 - 1100 ***************************/
 
-#define XST_IIC_SELFTEST_FAILED         1076	/*!< self test failed            */
-#define XST_IIC_BUS_BUSY                1077	/*!< bus found busy              */
-#define XST_IIC_GENERAL_CALL_ADDRESS    1078	/*!< mastersend attempted with   */
-					     /* general call address        */
-#define XST_IIC_STAND_REG_RESET_ERROR   1079	/*!< A non parameterizable reg   */
-					     /* value after reset not valid */
-#define XST_IIC_TX_FIFO_REG_RESET_ERROR 1080	/*!< Tx fifo included in design  */
-					     /* value after reset not valid */
-#define XST_IIC_RX_FIFO_REG_RESET_ERROR 1081	/*!< Rx fifo included in design  */
-					     /* value after reset not valid */
-#define XST_IIC_TBA_REG_RESET_ERROR     1082	/*!< 10 bit addr incl in design  */
-					     /* value after reset not valid */
-#define XST_IIC_CR_READBACK_ERROR       1083	/*!< Read of the control register */
-					     /* didn't return value written */
-#define XST_IIC_DTR_READBACK_ERROR      1084	/*!< Read of the data Tx reg     */
-					     /* didn't return value written */
-#define XST_IIC_DRR_READBACK_ERROR      1085	/*!< Read of the data Receive reg */
-					     /* didn't return value written */
-#define XST_IIC_ADR_READBACK_ERROR      1086	/*!< Read of the data Tx reg     */
-					     /* didn't return value written */
-#define XST_IIC_TBA_READBACK_ERROR      1087	/*!< Read of the 10 bit addr reg */
-					     /* didn't return written value */
-#define XST_IIC_NOT_SLAVE               1088	/*!< The device isn't a slave    */
-#define XST_IIC_ARB_LOST 				1089 	/*!< Arbitration lost for master	*/
+#define XST_IIC_SELFTEST_FAILED         1076    /*!< self test failed            */
+#define XST_IIC_BUS_BUSY                1077    /*!< bus found busy              */
+#define XST_IIC_GENERAL_CALL_ADDRESS    1078    /*!< mastersend attempted with   */
+                         /* general call address        */
+#define XST_IIC_STAND_REG_RESET_ERROR   1079    /*!< A non parameterizable reg   */
+                         /* value after reset not valid */
+#define XST_IIC_TX_FIFO_REG_RESET_ERROR 1080    /*!< Tx fifo included in design  */
+                         /* value after reset not valid */
+#define XST_IIC_RX_FIFO_REG_RESET_ERROR 1081    /*!< Rx fifo included in design  */
+                         /* value after reset not valid */
+#define XST_IIC_TBA_REG_RESET_ERROR     1082    /*!< 10 bit addr incl in design  */
+                         /* value after reset not valid */
+#define XST_IIC_CR_READBACK_ERROR       1083    /*!< Read of the control register */
+                         /* didn't return value written */
+#define XST_IIC_DTR_READBACK_ERROR      1084    /*!< Read of the data Tx reg     */
+                         /* didn't return value written */
+#define XST_IIC_DRR_READBACK_ERROR      1085    /*!< Read of the data Receive reg */
+                         /* didn't return value written */
+#define XST_IIC_ADR_READBACK_ERROR      1086    /*!< Read of the data Tx reg     */
+                         /* didn't return value written */
+#define XST_IIC_TBA_READBACK_ERROR      1087    /*!< Read of the 10 bit addr reg */
+                         /* didn't return written value */
+#define XST_IIC_NOT_SLAVE               1088    /*!< The device isn't a slave    */
+#define XST_IIC_ARB_LOST                 1089     /*!< Arbitration lost for master    */
 /** @} */
 /**
 @name ATMC Status Codes 1101 - 1125
@@ -266,10 +266,10 @@ extern "C" {
 */
 /*********************** ATMC statuses 1101 - 1125 ***************************/
 
-#define XST_ATMC_ERROR_COUNT_MAX    1101L	/*!< the error counters in the ATM
-						   controller hit the max value
-						   which requires the statistics
-						   to be cleared */
+#define XST_ATMC_ERROR_COUNT_MAX    1101L    /*!< the error counters in the ATM
+                           controller hit the max value
+                           which requires the statistics
+                           to be cleared */
 /** @} */
 /**
 @name Flash Status Codes 1126 - 1150
@@ -277,31 +277,31 @@ extern "C" {
 */
 /*********************** Flash statuses 1126 - 1150 **************************/
 
-#define XST_FLASH_BUSY                1126L	/*!< Flash is erasing or programming
-						 */
-#define XST_FLASH_READY               1127L	/*!< Flash is ready for commands */
-#define XST_FLASH_ERROR               1128L	/*!< Flash had detected an internal
-						   error. Use XFlash_DeviceControl
-						   to retrieve device specific codes
-						 */
-#define XST_FLASH_ERASE_SUSPENDED     1129L	/*!< Flash is in suspended erase state
-						 */
-#define XST_FLASH_WRITE_SUSPENDED     1130L	/*!< Flash is in suspended write state
-						 */
-#define XST_FLASH_PART_NOT_SUPPORTED  1131L	/*!< Flash type not supported by
-						   driver */
-#define XST_FLASH_NOT_SUPPORTED       1132L	/*!< Operation not supported */
-#define XST_FLASH_TOO_MANY_REGIONS    1133L	/*!< Too many erase regions */
-#define XST_FLASH_TIMEOUT_ERROR       1134L	/*!< Programming or erase operation
-						   aborted due to a timeout */
-#define XST_FLASH_ADDRESS_ERROR       1135L	/*!< Accessed flash outside its
-						   addressible range */
-#define XST_FLASH_ALIGNMENT_ERROR     1136L	/*!< Write alignment error */
-#define XST_FLASH_BLOCKING_CALL_ERROR 1137L	/*!< Couldn't return immediately from
-						   write/erase function with
-						   XFL_NON_BLOCKING_WRITE/ERASE
-						   option cleared */
-#define XST_FLASH_CFI_QUERY_ERROR     1138L	/*!< Failed to query the device */
+#define XST_FLASH_BUSY                1126L    /*!< Flash is erasing or programming
+                         */
+#define XST_FLASH_READY               1127L    /*!< Flash is ready for commands */
+#define XST_FLASH_ERROR               1128L    /*!< Flash had detected an internal
+                           error. Use XFlash_DeviceControl
+                           to retrieve device specific codes
+                         */
+#define XST_FLASH_ERASE_SUSPENDED     1129L    /*!< Flash is in suspended erase state
+                         */
+#define XST_FLASH_WRITE_SUSPENDED     1130L    /*!< Flash is in suspended write state
+                         */
+#define XST_FLASH_PART_NOT_SUPPORTED  1131L    /*!< Flash type not supported by
+                           driver */
+#define XST_FLASH_NOT_SUPPORTED       1132L    /*!< Operation not supported */
+#define XST_FLASH_TOO_MANY_REGIONS    1133L    /*!< Too many erase regions */
+#define XST_FLASH_TIMEOUT_ERROR       1134L    /*!< Programming or erase operation
+                           aborted due to a timeout */
+#define XST_FLASH_ADDRESS_ERROR       1135L    /*!< Accessed flash outside its
+                           addressible range */
+#define XST_FLASH_ALIGNMENT_ERROR     1136L    /*!< Write alignment error */
+#define XST_FLASH_BLOCKING_CALL_ERROR 1137L    /*!< Couldn't return immediately from
+                           write/erase function with
+                           XFL_NON_BLOCKING_WRITE/ERASE
+                           option cleared */
+#define XST_FLASH_CFI_QUERY_ERROR     1138L    /*!< Failed to query the device */
 /** @} */
 /**
 @name SPI Status Codes 1151 - 1175
@@ -309,23 +309,23 @@ extern "C" {
 */
 /*********************** SPI statuses 1151 - 1175 ****************************/
 
-#define XST_SPI_MODE_FAULT          1151	/*!< master was selected as slave */
-#define XST_SPI_TRANSFER_DONE       1152	/*!< data transfer is complete */
-#define XST_SPI_TRANSMIT_UNDERRUN   1153	/*!< slave underruns transmit register */
-#define XST_SPI_RECEIVE_OVERRUN     1154	/*!< device overruns receive register */
-#define XST_SPI_NO_SLAVE            1155	/*!< no slave has been selected yet */
-#define XST_SPI_TOO_MANY_SLAVES     1156	/*!< more than one slave is being
-						 * selected */
-#define XST_SPI_NOT_MASTER          1157	/*!< operation is valid only as master */
-#define XST_SPI_SLAVE_ONLY          1158	/*!< device is configured as slave-only
-						 */
-#define XST_SPI_SLAVE_MODE_FAULT    1159	/*!< slave was selected while disabled */
-#define XST_SPI_SLAVE_MODE          1160	/*!< device has been addressed as slave */
-#define XST_SPI_RECEIVE_NOT_EMPTY   1161	/*!< device received data in slave mode */
-
-#define XST_SPI_COMMAND_ERROR       1162	/*!< unrecognised command - qspi only */
+#define XST_SPI_MODE_FAULT          1151    /*!< master was selected as slave */
+#define XST_SPI_TRANSFER_DONE       1152    /*!< data transfer is complete */
+#define XST_SPI_TRANSMIT_UNDERRUN   1153    /*!< slave underruns transmit register */
+#define XST_SPI_RECEIVE_OVERRUN     1154    /*!< device overruns receive register */
+#define XST_SPI_NO_SLAVE            1155    /*!< no slave has been selected yet */
+#define XST_SPI_TOO_MANY_SLAVES     1156    /*!< more than one slave is being
+                         * selected */
+#define XST_SPI_NOT_MASTER          1157    /*!< operation is valid only as master */
+#define XST_SPI_SLAVE_ONLY          1158    /*!< device is configured as slave-only
+                         */
+#define XST_SPI_SLAVE_MODE_FAULT    1159    /*!< slave was selected while disabled */
+#define XST_SPI_SLAVE_MODE          1160    /*!< device has been addressed as slave */
+#define XST_SPI_RECEIVE_NOT_EMPTY   1161    /*!< device received data in slave mode */
+
+#define XST_SPI_COMMAND_ERROR       1162    /*!< unrecognised command - qspi only */
 #define XST_SPI_POLL_DONE           1163        /*!< controller completed polling the
-						   device for status */
+                           device for status */
 /** @} */
 /**
 @name OPB Arbiter Status Codes 1176 - 1200
@@ -333,23 +333,23 @@ extern "C" {
 */
 /********************** OPB Arbiter statuses 1176 - 1200 *********************/
 
-#define XST_OPBARB_INVALID_PRIORITY  1176	/*!< the priority registers have either
-						 * one master assigned to two or more
-						 * priorities, or one master not
-						 * assigned to any priority
-						 */
-#define XST_OPBARB_NOT_SUSPENDED     1177	/*!< an attempt was made to modify the
-						 * priority levels without first
-						 * suspending the use of priority
-						 * levels
-						 */
-#define XST_OPBARB_PARK_NOT_ENABLED  1178	/*!< bus parking by id was enabled but
-						 * bus parking was not enabled
-						 */
-#define XST_OPBARB_NOT_FIXED_PRIORITY 1179	/*!< the arbiter must be in fixed
-						 * priority mode to allow the
-						 * priorities to be changed
-						 */
+#define XST_OPBARB_INVALID_PRIORITY  1176    /*!< the priority registers have either
+                         * one master assigned to two or more
+                         * priorities, or one master not
+                         * assigned to any priority
+                         */
+#define XST_OPBARB_NOT_SUSPENDED     1177    /*!< an attempt was made to modify the
+                         * priority levels without first
+                         * suspending the use of priority
+                         * levels
+                         */
+#define XST_OPBARB_PARK_NOT_ENABLED  1178    /*!< bus parking by id was enabled but
+                         * bus parking was not enabled
+                         */
+#define XST_OPBARB_NOT_FIXED_PRIORITY 1179    /*!< the arbiter must be in fixed
+                         * priority mode to allow the
+                         * priorities to be changed
+                         */
 /** @} */
 /**
 @name INTC Status Codes 1201 - 1225
@@ -357,8 +357,8 @@ extern "C" {
 */
 /************************ Intc statuses 1201 - 1225 **************************/
 
-#define XST_INTC_FAIL_SELFTEST      1201	/*!< self test failed */
-#define XST_INTC_CONNECT_ERROR      1202	/*!< interrupt already in use */
+#define XST_INTC_FAIL_SELFTEST      1201    /*!< self test failed */
+#define XST_INTC_CONNECT_ERROR      1202    /*!< interrupt already in use */
 /** @} */
 /**
 @name TmrCtr Status Codes 1226 - 1250
@@ -366,7 +366,7 @@ extern "C" {
 */
 /********************** TmrCtr statuses 1226 - 1250 **************************/
 
-#define XST_TMRCTR_TIMER_FAILED     1226	/*!< self test failed */
+#define XST_TMRCTR_TIMER_FAILED     1226    /*!< self test failed */
 /** @} */
 /**
 @name WdtTb Status Codes 1251 - 1275
@@ -406,7 +406,7 @@ extern "C" {
 */
 /********************** SysAce statuses 1351 - 1360 **************************/
 
-#define XST_SYSACE_NO_LOCK          1351L	/*!< No MPU lock has been granted */
+#define XST_SYSACE_NO_LOCK          1351L    /*!< No MPU lock has been granted */
 /** @} */
 /**
 @name PCI Bridge Status Codes 1361 - 1375
@@ -422,10 +422,10 @@ extern "C" {
 */
 /********************** FlexRay constants 1400 - 1409 *************************/
 
-#define XST_FR_TX_ERROR			1400
-#define XST_FR_TX_BUSY			1401
-#define XST_FR_BUF_LOCKED		1402
-#define XST_FR_NO_BUF			1403
+#define XST_FR_TX_ERROR            1400
+#define XST_FR_TX_BUSY            1401
+#define XST_FR_BUF_LOCKED        1402
+#define XST_FR_NO_BUF            1403
 /** @} */
 /**
 @name USB constants 1410 - 1420
@@ -433,11 +433,11 @@ extern "C" {
 */
 /****************** USB constants 1410 - 1420  *******************************/
 
-#define XST_USB_ALREADY_CONFIGURED	1410
-#define XST_USB_BUF_ALIGN_ERROR		1411
-#define XST_USB_NO_DESC_AVAILABLE	1412
-#define XST_USB_BUF_TOO_BIG		1413
-#define XST_USB_NO_BUF			1414
+#define XST_USB_ALREADY_CONFIGURED    1410
+#define XST_USB_BUF_ALIGN_ERROR        1411
+#define XST_USB_NO_DESC_AVAILABLE    1412
+#define XST_USB_BUF_TOO_BIG        1413
+#define XST_USB_NO_BUF            1414
 /** @} */
 /**
 @name HWICAP constants 1421 - 1429
@@ -445,7 +445,7 @@ extern "C" {
 */
 /****************** HWICAP constants 1421 - 1429  *****************************/
 
-#define XST_HWICAP_WRITE_DONE		1421
+#define XST_HWICAP_WRITE_DONE        1421
 
 /** @} */
 /**
@@ -454,7 +454,7 @@ extern "C" {
 */
 /****************** AXI VDMA constants 1430 - 1440  *****************************/
 
-#define XST_VDMA_MISMATCH_ERROR		1430
+#define XST_VDMA_MISMATCH_ERROR        1430
 /** @} */
 /**
 @name NAND Flash Status Codes 1441 - 1459
@@ -462,36 +462,36 @@ extern "C" {
 */
 /*********************** NAND Flash statuses 1441 - 1459  *********************/
 
-#define XST_NAND_BUSY			1441L	/*!< Flash is erasing or
-						 * programming
-						 */
-#define XST_NAND_READY			1442L	/*!< Flash is ready for commands
-						 */
-#define XST_NAND_ERROR			1443L	/*!< Flash had detected an
-						 * internal error.
-						 */
-#define XST_NAND_PART_NOT_SUPPORTED	1444L	/*!< Flash type not supported by
-						 * driver
-						 */
-#define XST_NAND_OPT_NOT_SUPPORTED	1445L	/*!< Operation not supported
-						 */
-#define XST_NAND_TIMEOUT_ERROR		1446L	/*!< Programming or erase
-						 * operation aborted due to a
-						 * timeout
-						 */
-#define XST_NAND_ADDRESS_ERROR		1447L	/*!< Accessed flash outside its
-						 * addressible range
-						 */
-#define XST_NAND_ALIGNMENT_ERROR	1448L	/*!< Write alignment error
-						 */
-#define XST_NAND_PARAM_PAGE_ERROR	1449L	/*!< Failed to read parameter
-						 * page of the device
-						 */
-#define XST_NAND_CACHE_ERROR		1450L	/*!< Flash page buffer error
-						 */
-
-#define XST_NAND_WRITE_PROTECTED	1451L	/*!< Flash is write protected
-						 */
+#define XST_NAND_BUSY            1441L    /*!< Flash is erasing or
+                         * programming
+                         */
+#define XST_NAND_READY            1442L    /*!< Flash is ready for commands
+                         */
+#define XST_NAND_ERROR            1443L    /*!< Flash had detected an
+                         * internal error.
+                         */
+#define XST_NAND_PART_NOT_SUPPORTED    1444L    /*!< Flash type not supported by
+                         * driver
+                         */
+#define XST_NAND_OPT_NOT_SUPPORTED    1445L    /*!< Operation not supported
+                         */
+#define XST_NAND_TIMEOUT_ERROR        1446L    /*!< Programming or erase
+                         * operation aborted due to a
+                         * timeout
+                         */
+#define XST_NAND_ADDRESS_ERROR        1447L    /*!< Accessed flash outside its
+                         * addressible range
+                         */
+#define XST_NAND_ALIGNMENT_ERROR    1448L    /*!< Write alignment error
+                         */
+#define XST_NAND_PARAM_PAGE_ERROR    1449L    /*!< Failed to read parameter
+                         * page of the device
+                         */
+#define XST_NAND_CACHE_ERROR        1450L    /*!< Flash page buffer error
+                         */
+
+#define XST_NAND_WRITE_PROTECTED    1451L    /*!< Flash is write protected
+                         */
 /** @} */
 
 /**************************** Type Definitions *******************************/

+ 349 - 0
bsp/zynqmp-r5-axu4ev/drivers/drv_eth.c

@@ -0,0 +1,349 @@
+/*
+ * Copyright (c) 2021, WangHuachen
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021-5-10     WangHuachen  the first version
+ */
+
+
+#include "board.h"
+#include <netif/ethernetif.h>
+#include "lwipopts.h"
+#include "lwip/opt.h"
+#include "drv_eth.h"
+#include "lwip/netif.h"
+#include "netif/xadapter.h"
+#include "netif/xemacpsif.h"
+#include "xparameters.h"
+#include "xemacps.h"
+
+#define DBG_TAG             "drv.emac"
+#define DBG_LEVEL           DBG_INFO
+#include <rtdbg.h>
+
+#define MAC_BASE_ADDR       XPAR_PSU_ETHERNET_3_BASEADDR
+#define MAX_ADDR_LEN        6
+
+struct rt_zynqmp_eth
+{
+    /* inherit from ethernet device */
+    struct eth_device parent;
+
+    /* interface address info, hw address */
+    rt_uint8_t  dev_addr[MAX_ADDR_LEN];
+
+    struct xemac_s *xemac;
+};
+
+static struct rt_zynqmp_eth zynqmp_eth_device;
+extern XEmacPs_Config *mac_config;
+extern struct netif *NetIf;
+
+static void rt_hw_eth_isr(int irqno, void *param)
+{
+    struct rt_zynqmp_eth *eth_dev = (struct rt_zynqmp_eth *)param;
+    xemacpsif_s *xemacpsif = (xemacpsif_s *)eth_dev->xemac->state;
+    XEmacPs_IntrHandler(&xemacpsif->emacps);
+}
+
+extern enum ethernet_link_status eth_link_status;
+extern u32_t phy_link_detect(XEmacPs *xemacp, u32_t phy_addr);
+extern u32_t phy_autoneg_status(XEmacPs *xemacp, u32_t phy_addr);
+extern u32_t phyaddrforemac;
+
+void rt_zynqmp_eth_link_detect(struct rt_zynqmp_eth *eth_dev)
+{
+    u32_t link_speed, phy_link_status;
+    struct xemac_s *xemac = eth_dev->xemac;
+    xemacpsif_s *xemacs = (xemacpsif_s *)(xemac->state);
+    XEmacPs *xemacp = &xemacs->emacps;
+
+    if ((xemacp->IsReady != (u32)XIL_COMPONENT_IS_READY) ||
+            (eth_link_status == ETH_LINK_UNDEFINED))
+        return;
+
+    phy_link_status = phy_link_detect(xemacp, phyaddrforemac);
+
+    if ((eth_link_status == ETH_LINK_UP) && (!phy_link_status))
+        eth_link_status = ETH_LINK_DOWN;
+
+    switch (eth_link_status) {
+        case ETH_LINK_UNDEFINED:
+        case ETH_LINK_UP:
+            return;
+        case ETH_LINK_DOWN:
+            eth_device_linkchange(&zynqmp_eth_device.parent, RT_FALSE);
+            eth_link_status = ETH_LINK_NEGOTIATING;
+            LOG_D("Ethernet Link down");
+            break;
+        case ETH_LINK_NEGOTIATING:
+            if (phy_link_status &&
+                phy_autoneg_status(xemacp, phyaddrforemac)) {
+
+                /* Initiate Phy setup to get link speed */
+                link_speed = phy_setup_emacps(xemacp,
+                                phyaddrforemac);
+                XEmacPs_SetOperatingSpeed(xemacp, link_speed);
+
+                eth_device_linkchange(&zynqmp_eth_device.parent, RT_TRUE);
+                eth_link_status = ETH_LINK_UP;
+                LOG_D("Ethernet Link up");
+            }
+            break;
+    }
+}
+
+static void phy_monitor_thread(void *parameter)
+{
+    struct rt_zynqmp_eth *eth_dev = (struct rt_zynqmp_eth *)parameter;
+
+    while (1)
+    {
+        rt_zynqmp_eth_link_detect(eth_dev);
+        rt_thread_delay(RT_TICK_PER_SECOND);
+    }
+}
+
+static rt_err_t rt_zynqmp_eth_init(rt_device_t dev)
+{
+    struct rt_zynqmp_eth *eth_dev = (struct rt_zynqmp_eth *)dev->user_data;
+    struct netif *netif = eth_dev->parent.netif;
+    struct xemac_s *xemac;
+    xemacpsif_s *xemacpsif;
+    u32 dmacrreg;
+    s32_t status = XST_SUCCESS;
+    struct xtopology_t *xtopologyp;
+
+    if (eth_dev->xemac != RT_NULL)
+    {
+        LOG_W("rt_zynqmp_eth_init: device has been initialized");
+        return -RT_ERROR;
+    }
+
+    NetIf = netif;
+
+    xemacpsif = rt_malloc(sizeof *xemacpsif);
+    if (xemacpsif == NULL)
+    {
+        LOG_E("rt_zynqmp_eth_init: out of memory");
+        return -RT_ENOMEM;
+    }
+
+    xemac = rt_malloc(sizeof *xemac);
+    if (xemac == NULL)
+    {
+        LOG_E("rt_zynqmp_eth_init: out of memory");
+        return -RT_ENOMEM;
+    }
+
+    xemac->state = (void *)xemacpsif;
+    xemac->topology_index = xtopology_find_index(MAC_BASE_ADDR);
+    xemac->type = xemac_type_emacps;
+    xemac->rt_eth_device = &eth_dev->parent;
+
+    xemacpsif->send_q = NULL;
+    xemacpsif->recv_q = pq_create_queue();
+    if (!xemacpsif->recv_q)
+        return -RT_ENOMEM;
+
+    eth_dev->xemac = xemac;
+
+    /* obtain config of this emac */
+    mac_config = (XEmacPs_Config *)xemacps_lookup_config(MAC_BASE_ADDR);
+
+    status = XEmacPs_CfgInitialize(&xemacpsif->emacps, mac_config,
+                                   mac_config->BaseAddress);
+    if (status != XST_SUCCESS)
+    {
+        LOG_W("In %s:EmacPs Configuration Failed....", __func__);
+        return -RT_ERROR;
+    }
+
+    /* initialize the mac */
+    init_emacps(xemacpsif, netif);
+
+    dmacrreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
+                               XEMACPS_DMACR_OFFSET);
+    dmacrreg = dmacrreg | (0x00000010);
+    XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
+                     XEMACPS_DMACR_OFFSET, dmacrreg);
+
+    setup_isr(xemac);
+    init_dma(xemac);
+
+    xtopologyp = &xtopology[xemac->topology_index];
+    /*
+    * Connect the device driver handler that will be called when an
+    * interrupt for the device occurs, the handler defined above performs
+    * the specific interrupt processing for the device.
+    */
+    rt_hw_interrupt_install(xtopologyp->scugic_emac_intr, rt_hw_eth_isr, (void *)eth_dev, "eth");
+    /*
+    * Enable the interrupt for emacps.
+    */
+    rt_hw_interrupt_umask(xtopologyp->scugic_emac_intr);
+
+    start_emacps(xemacpsif);
+
+    if (eth_link_status == ETH_LINK_UP)
+        eth_device_linkchange(&eth_dev->parent, RT_TRUE);
+
+    rt_thread_t tid;
+    tid = rt_thread_create("phylnk",
+                           phy_monitor_thread,
+                           eth_dev,
+                           1024,
+                           RT_THREAD_PRIORITY_MAX - 2,
+                           2);
+    if (tid != RT_NULL)
+        rt_thread_startup(tid);
+    else
+        return -RT_ERROR;
+
+    return RT_EOK;
+}
+
+static rt_err_t rt_zynqmp_eth_open(rt_device_t dev, rt_uint16_t oflag)
+{
+    LOG_D("emac open");
+    return RT_EOK;
+}
+
+static rt_err_t rt_zynqmp_eth_close(rt_device_t dev)
+{
+    LOG_D("emac close");
+    return RT_EOK;
+}
+
+static rt_size_t rt_zynqmp_eth_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
+{
+    LOG_D("emac read");
+    rt_set_errno(-RT_ENOSYS);
+    return 0;
+}
+
+static rt_size_t rt_zynqmp_eth_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
+{
+    LOG_D("emac write");
+    rt_set_errno(-RT_ENOSYS);
+    return 0;
+}
+
+static rt_err_t rt_zynqmp_eth_control(rt_device_t dev, int cmd, void *args)
+{
+    struct rt_zynqmp_eth *eth_dev = (struct rt_zynqmp_eth *)dev->user_data;
+    switch (cmd)
+    {
+    case NIOCTL_GADDR:
+        /* get mac address */
+        if (args) rt_memcpy(args, eth_dev->dev_addr, 6);
+        else return -RT_ERROR;
+        break;
+
+    default :
+        break;
+    }
+
+    return RT_EOK;
+}
+
+extern err_t _unbuffered_low_level_output(xemacpsif_s *xemacpsif, struct pbuf *p);
+rt_err_t rt_zynqmp_eth_tx(rt_device_t dev, struct pbuf *p)
+{
+    rt_base_t lev;
+    rt_err_t err;
+    XEmacPs_BdRing *txring;
+
+    struct rt_zynqmp_eth *eth_dev = (struct rt_zynqmp_eth *)dev->user_data;
+    struct xemac_s *xemac = eth_dev->xemac;
+    xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
+
+    lev = rt_hw_interrupt_disable();
+
+    txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps));
+    process_sent_bds(xemacpsif, txring);
+
+    if (is_tx_space_available(xemacpsif))
+    {
+        _unbuffered_low_level_output(xemacpsif, p);
+        err = RT_EOK;
+    }
+    else
+    {
+#if LINK_STATS
+        lwip_stats.link.drop++;
+#endif
+        LOG_D("pack dropped, no space");
+        err = -RT_ENOMEM;
+    }
+
+    rt_hw_interrupt_enable(lev);
+
+    return err;
+}
+
+struct pbuf *rt_zynqmp_eth_rx(rt_device_t dev)
+{
+    rt_base_t lev;
+    struct rt_zynqmp_eth *eth_dev = (struct rt_zynqmp_eth *)dev->user_data;
+    struct xemac_s *xemac = eth_dev->xemac;
+    xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
+    struct pbuf *p;
+
+    lev = rt_hw_interrupt_disable();
+
+    /* see if there is data to process */
+    if (pq_qlength(xemacpsif->recv_q) == 0)
+        return NULL;
+
+    /* return one packet from receive q */
+    p = (struct pbuf *)pq_dequeue(xemacpsif->recv_q);
+
+    rt_hw_interrupt_enable(lev);
+
+    return p;
+}
+
+static int rt_hw_zynqmp_eth_init(void)
+{
+    rt_err_t state = RT_EOK;
+
+    zynqmp_eth_device.xemac = RT_NULL;
+
+    zynqmp_eth_device.dev_addr[0] = 0x00;
+    zynqmp_eth_device.dev_addr[1] = 0x0A;
+    zynqmp_eth_device.dev_addr[2] = 0x35;
+    zynqmp_eth_device.dev_addr[3] = 0x00;
+    zynqmp_eth_device.dev_addr[4] = 0x01;
+    zynqmp_eth_device.dev_addr[5] = 0x02;
+
+    zynqmp_eth_device.parent.parent.init       = rt_zynqmp_eth_init;
+    zynqmp_eth_device.parent.parent.open       = rt_zynqmp_eth_open;
+    zynqmp_eth_device.parent.parent.close      = rt_zynqmp_eth_close;
+    zynqmp_eth_device.parent.parent.read       = rt_zynqmp_eth_read;
+    zynqmp_eth_device.parent.parent.write      = rt_zynqmp_eth_write;
+    zynqmp_eth_device.parent.parent.control    = rt_zynqmp_eth_control;
+    zynqmp_eth_device.parent.parent.user_data  = &zynqmp_eth_device;
+
+    zynqmp_eth_device.parent.eth_rx     = rt_zynqmp_eth_rx;
+    zynqmp_eth_device.parent.eth_tx     = rt_zynqmp_eth_tx;
+
+    /* register eth device */
+    state = eth_device_init(&(zynqmp_eth_device.parent), "e0");
+    if (RT_EOK == state)
+    {
+        LOG_D("emac device init success");
+    }
+    else
+    {
+        LOG_E("emac device init faild: %d", state);
+        state = -RT_ERROR;
+        return state;
+    }
+
+    return state;
+}
+INIT_DEVICE_EXPORT(rt_hw_zynqmp_eth_init);

+ 13 - 0
bsp/zynqmp-r5-axu4ev/drivers/drv_eth.h

@@ -0,0 +1,13 @@
+#ifndef __DRV_ETH_H__
+#define __DRV_ETH_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 8 - 8
bsp/zynqmp-r5-axu4ev/drivers/drv_sdcard.c

@@ -184,9 +184,9 @@ static DSTATUS disk_initialize(
     if (CardDetect)
     {
         /*
-			 * Card detection check
-			 * If the HC detects the No Card State, power will be cleared
-			 */
+             * Card detection check
+             * If the HC detects the No Card State, power will be cleared
+             */
         while (!((XSDPS_PSR_CARD_DPL_MASK |
                   XSDPS_PSR_CARD_STABLE_MASK |
                   XSDPS_PSR_CARD_INSRT_MASK) ==
@@ -198,8 +198,8 @@ static DSTATUS disk_initialize(
     }
 
     /*
-	 * Initialize the host controller
-	 */
+     * Initialize the host controller
+     */
     SdConfig = XSdPs_LookupConfig((u16)pdrv);
     if (NULL == SdConfig)
     {
@@ -223,9 +223,9 @@ static DSTATUS disk_initialize(
     }
 
     /*
-	 * Disk is initialized.
-	 * Store the same in Stat.
-	 */
+     * Disk is initialized.
+     * Store the same in Stat.
+     */
     s &= (~STA_NOINIT);
 
     Stat[pdrv] = s;

+ 2 - 2
bsp/zynqmp-r5-axu4ev/drivers/drv_timer.c

@@ -47,10 +47,10 @@ static int rt_hw_timer_init(void)
     /* Setup interval */
     TTC_INTERVAL_VAL(TTC0_0_BASEADDR) = TTC0_0_CLK_FREQ_HZ / RT_TICK_PER_SECOND;
     /* Clear all of the prescaler control bits in the register */
-    TTC_CLK_CNTRL(TTC0_0_BASEADDR) &= ~(TTC_CLK_CNTRL_PS_VAL_MASK | 
+    TTC_CLK_CNTRL(TTC0_0_BASEADDR) &= ~(TTC_CLK_CNTRL_PS_VAL_MASK |
                                             TTC_CLK_CNTRL_PS_EN_MASK);
     /* We do not need a prescaler*/
-    
+
     /* Register the ticker handler with the GIC */
     rt_hw_interrupt_install(XPAR_XTTCPS_0_INTR, rt_hw_timer_isr, RT_NULL, "tick");
     /* Enable TTC interrupts in the GIC */

+ 7 - 7
bsp/zynqmp-r5-axu4ev/drivers/drv_uart.c

@@ -21,7 +21,7 @@
 
 #define XUARTPS_MAX_RATE    921600U
 #define XUARTPS_MIN_RATE    110U
-#define XUARTPS_MAX_BAUD_ERROR_RATE     3U	/* max % error allowed */
+#define XUARTPS_MAX_BAUD_ERROR_RATE     3U    /* max % error allowed */
 
 #define ZynqMP_UART_INT_DISABLE(UART)       \
     (UART->IER &= ~(UART_IXR_RXOVR | UART_IXR_RXFULL))
@@ -92,12 +92,12 @@ static void rt_hw_uart_isr(int irqno, void *param)
 
 static rt_err_t XUartPsSetBandRate(struct hw_uart_device *pdev, rt_uint32_t targetBandRate)
 {
-    rt_uint32_t IterBAUDDIV;	/* Iterator for available baud divisor values */
-    rt_uint32_t BRGR_Value;		/* Calculated value for baud rate generator */
-    rt_uint32_t CalcBaudRate;	/* Calculated baud rate */
-    rt_uint32_t BaudError;		/* Diff between calculated and requested baud rate */
-    rt_uint32_t Best_BRGR = 0U;	/* Best value for baud rate generator */
-    rt_uint8_t Best_BAUDDIV = 0U;	/* Best value for baud divisor */
+    rt_uint32_t IterBAUDDIV;    /* Iterator for available baud divisor values */
+    rt_uint32_t BRGR_Value;        /* Calculated value for baud rate generator */
+    rt_uint32_t CalcBaudRate;    /* Calculated baud rate */
+    rt_uint32_t BaudError;        /* Diff between calculated and requested baud rate */
+    rt_uint32_t Best_BRGR = 0U;    /* Best value for baud rate generator */
+    rt_uint8_t Best_BAUDDIV = 0U;    /* Best value for baud divisor */
     rt_uint32_t Best_Error = 0xFFFFFFFFU;
     rt_uint32_t PercentError;
     rt_uint32_t ModeReg;

+ 5 - 5
bsp/zynqmp-r5-axu4ev/drivers/zynqmp-r5.h

@@ -9,11 +9,11 @@
 #define __REG8(x)  (*((volatile rt_uint8_t *)(x)))
 
 #define ZynqMP_CRL_APB_BASEADDR        XPAR_PSU_CRL_APB_S_AXI_BASEADDR
-#define ZynqMP_CRL_APB_IOPLL_CTRL	   0x020    
-#define ZynqMP_CRL_APB_IOPLL_CFG	   0x024   
-#define ZynqMP_CRL_APB_UART0_REF_CTRL  0x074   
-#define ZynqMP_CRL_APB_UART1_REF_CTRL  0x078   
-#define ZynqMP_CRL_APB_LPD_LSBUS_CTRL  0x0AC  
+#define ZynqMP_CRL_APB_IOPLL_CTRL       0x020
+#define ZynqMP_CRL_APB_IOPLL_CFG       0x024
+#define ZynqMP_CRL_APB_UART0_REF_CTRL  0x074
+#define ZynqMP_CRL_APB_UART1_REF_CTRL  0x078
+#define ZynqMP_CRL_APB_LPD_LSBUS_CTRL  0x0AC
 #define ZynqMP_CRL_APB_RESET_CTRL      0x218
 #define ZynqMP_RESET_MASK       0x10
 

+ 82 - 5
bsp/zynqmp-r5-axu4ev/rtconfig.h

@@ -19,6 +19,9 @@
 #define RT_USING_TIMER_SOFT
 #define RT_TIMER_THREAD_PRIO 4
 #define RT_TIMER_THREAD_STACK_SIZE 512
+
+/* kservice optimization */
+
 #define RT_DEBUG
 
 /* Inter-Thread communication */
@@ -32,7 +35,7 @@
 /* Memory Management */
 
 #define RT_USING_MEMPOOL
-#define RT_USING_SMALL_MEM
+#define RT_USING_SLAB
 #define RT_USING_HEAP
 
 /* Kernel Device Object */
@@ -41,7 +44,7 @@
 #define RT_USING_CONSOLE
 #define RT_CONSOLEBUF_SIZE 128
 #define RT_CONSOLE_DEVICE_NAME "uart0"
-#define RT_VER_NUM 0x40003
+#define RT_VER_NUM 0x40004
 
 /* RT-Thread Components */
 
@@ -83,6 +86,8 @@
 #define RT_DFS_ELM_WORD_ACCESS
 #define RT_DFS_ELM_USE_LFN_3
 #define RT_DFS_ELM_USE_LFN 3
+#define RT_DFS_ELM_LFN_UNICODE_0
+#define RT_DFS_ELM_LFN_UNICODE 0
 #define RT_DFS_ELM_MAX_LFN 255
 #define RT_DFS_ELM_DRIVES 2
 #define RT_DFS_ELM_MAX_SECTOR_SIZE 512
@@ -93,6 +98,9 @@
 
 #define RT_USING_DEVICE_IPC
 #define RT_PIPE_BUFSZ 512
+#define RT_USING_SYSTEM_WORKQUEUE
+#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048
+#define RT_SYSTEM_WORKQUEUE_PRIORITY 23
 #define RT_USING_SERIAL
 #define RT_SERIAL_USING_DMA
 #define RT_SERIAL_RB_BUFSZ 64
@@ -101,24 +109,77 @@
 /* Using USB */
 
 
-/* Using RapidIO */
-
-
 /* POSIX layer and C standard library */
 
 #define RT_USING_LIBC
 #define RT_USING_POSIX
+#define RT_LIBC_FIXED_TIMEZONE 8
 
 /* Network */
 
 /* Socket abstraction layer */
 
+#define RT_USING_SAL
+#define SAL_INTERNET_CHECK
+
+/* protocol stack implement */
+
+#define SAL_USING_LWIP
+#define SAL_USING_POSIX
 
 /* 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 32
+#define RT_LWIP_IGMP
+#define RT_LWIP_ICMP
+#define RT_LWIP_DNS
+#define RT_LWIP_DHCP
+#define IP_SOF_BROADCAST 1
+#define IP_SOF_BROADCAST_RECV 1
+
+/* Static IPv4 Address */
+
+#define RT_LWIP_IPADDR "192.168.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 256
+#define RT_LWIP_RAW_PCB_NUM 4
+#define RT_LWIP_UDP_PCB_NUM 4
+#define RT_LWIP_TCP_PCB_NUM 4
+#define RT_LWIP_TCP_SEG_NUM 40
+#define RT_LWIP_TCP_SND_BUF 8196
+#define RT_LWIP_TCP_WND 8196
+#define RT_LWIP_TCPTHREAD_PRIORITY 10
+#define RT_LWIP_TCPTHREAD_MBOX_SIZE 8
+#define RT_LWIP_TCPTHREAD_STACKSIZE 2048
+#define RT_LWIP_ETHTHREAD_PRIORITY 12
+#define RT_LWIP_ETHTHREAD_STACKSIZE 1024
+#define RT_LWIP_ETHTHREAD_MBOX_SIZE 8
+#define LWIP_NETIF_STATUS_CALLBACK 1
+#define LWIP_NETIF_LINK_CALLBACK 1
+#define SO_REUSE 1
+#define LWIP_SO_RCVTIMEO 1
+#define LWIP_SO_SNDTIMEO 1
+#define LWIP_SO_RCVBUF 1
+#define LWIP_SO_LINGER 0
+#define LWIP_NETIF_LOOPBACK 0
+#define RT_LWIP_USING_PING
 
 /* AT commands */
 
@@ -129,6 +190,9 @@
 /* Utilities */
 
 
+/* RT-Thread Utestcases */
+
+
 /* RT-Thread online packages */
 
 /* IoT - internet of things */
@@ -166,11 +230,17 @@
 /* peripheral libraries and drivers */
 
 
+/* AI packages */
+
+
 /* miscellaneous packages */
 
 
 /* samples: kernel and components samples */
 
+
+/* entertainment: terminal games and other interesting software packages */
+
 #define SOC_ZYNQMP_R5
 
 /* Hardware Drivers Config */
@@ -184,6 +254,13 @@
 #define BSP_USING_SDIO
 #define BSP_USING_SD0
 
+/* Please set RT_LWIP_PBUF_NUM is at least 256 if Enable Ethernet! */
+
+/* Please set RT_LWIP_MEM_ALIGNMENT is at 32 if Enable Ethernet! */
+
+#define BSP_USING_ETH
+#define RT_LWIP_PBUF_POOL_BUFSIZE 1700
+
 /* Board extended module Drivers */
 
 

+ 2 - 2
bsp/zynqmp-r5-axu4ev/rtconfig.py

@@ -9,8 +9,8 @@ if os.getenv('RTT_CC'):
     CROSS_TOOL = os.getenv('RTT_CC')
 
 # only support GNU GCC compiler
-PLATFORM 	= 'gcc'
-EXEC_PATH 	= '/opt/arm-none-eabi-gcc'
+PLATFORM     = 'gcc'
+EXEC_PATH     = '/opt/arm-none-eabi-gcc'
 
 if os.getenv('RTT_EXEC_PATH'):
     EXEC_PATH = os.getenv('RTT_EXEC_PATH')

+ 263 - 28
libcpu/arm/zynqmp-r5/cache.c

@@ -1,11 +1,13 @@
 /*
  * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
+ * Copyright (c) 2014 - 2020 Xilinx, Inc.  All rights reserved.
+ * Copyright (c) 2021 WangHuachen.  All rights reserved.
+ * SPDX-License-Identifier: MIT
  *
  * Change Logs:
  * Date           Author       Notes
  * 2020-03-19     WangHuachen  first version
+ * 2021-05-10     WangHuachen  add more functions
  */
 #include <rthw.h>
 #include <rtdef.h>
@@ -44,41 +46,77 @@ typedef rt_uint32_t u32;
         XREG_CP15_INVAL_IC_LINE_MVA_POU :: "r" (param))
 #endif
 
+void Xil_DCacheEnable(void);
+void Xil_DCacheDisable(void);
+void Xil_DCacheInvalidate(void);
+void Xil_DCacheInvalidateRange(INTPTR adr, u32 len);
+void Xil_DCacheFlush(void);
+void Xil_DCacheFlushRange(INTPTR adr, u32 len);
+void Xil_DCacheInvalidateLine(INTPTR adr);
+void Xil_DCacheFlushLine(INTPTR adr);
+void Xil_DCacheStoreLine(INTPTR adr);
+void Xil_ICacheEnable(void);
+void Xil_ICacheDisable(void);
+void Xil_ICacheInvalidate(void);
+void Xil_ICacheInvalidateRange(INTPTR adr, u32 len);
+void Xil_ICacheInvalidateLine(INTPTR adr);
+
+void Xil_DCacheEnable(void)
+{
+    register u32 CtrlReg;
 
-void Xil_ICacheInvalidateRange(INTPTR adr, u32 len)
+    /* enable caches only if they are disabled */
+#if defined (__GNUC__)
+    CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
+#elif defined (__ICCARM__)
+     mfcp(XREG_CP15_SYS_CONTROL,CtrlReg);
+#endif
+    if ((CtrlReg & XREG_CP15_CONTROL_C_BIT)==0x00000000U) {
+        /* invalidate the Data cache */
+        Xil_DCacheInvalidate();
+
+        /* enable the Data cache */
+        CtrlReg |= (XREG_CP15_CONTROL_C_BIT);
+
+        mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
+    }
+}
+
+void Xil_DCacheDisable(void)
+{
+    register u32 CtrlReg;
+
+    /* clean and invalidate the Data cache */
+    Xil_DCacheFlush();
+
+    /* disable the Data cache */
+#if defined (__GNUC__)
+    CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
+#elif defined (__ICCARM__)
+     mfcp(XREG_CP15_SYS_CONTROL,CtrlReg);
+#endif
+
+    CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT);
+
+    mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
+}
+
+void Xil_DCacheInvalidate(void)
 {
-    u32 LocalAddr = adr;
-    const u32 cacheline = 32U;
-    u32 end;
     u32 currmask;
 
     currmask = mfcpsr();
     mtcpsr(currmask | IRQ_FIQ_MASK);
-    if (len != 0x00000000U) {
-        /* Back the starting address up to the start of a cache line
-         * perform cache operations until adr+len
-         */
-        end = LocalAddr + len;
-        LocalAddr = LocalAddr & ~(cacheline - 1U);
-
-        /* Select cache L0 I-cache in CSSR */
-        mtcp(XREG_CP15_CACHE_SIZE_SEL, 1U);
-
-        while (LocalAddr < end) {
 
-            /* Invalidate L1 I-cache line */
-            asm_inval_ic_line_mva_pou(LocalAddr);
+    mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
 
-            LocalAddr += cacheline;
-        }
-    }
+    /*invalidate all D cache*/
+    mtcp(XREG_CP15_INVAL_DC_ALL, 0);
 
-    /* Wait for invalidate to complete */
-    dsb();
     mtcpsr(currmask);
 }
 
-void Xil_DCacheFlushLine(INTPTR adr)
+void Xil_DCacheInvalidateLine(INTPTR adr)
 {
     u32 currmask;
 
@@ -86,11 +124,11 @@ void Xil_DCacheFlushLine(INTPTR adr)
     mtcpsr(currmask | IRQ_FIQ_MASK);
 
     mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
+    mtcp(XREG_CP15_INVAL_DC_LINE_MVA_POC, (adr & (~0x1F)));
 
-    mtcp(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC, (adr & (~0x1F)));
-
-        /* Wait for flush to complete */
+        /* Wait for invalidate to complete */
     dsb();
+
     mtcpsr(currmask);
 }
 
@@ -135,6 +173,79 @@ void Xil_DCacheInvalidateRange(INTPTR adr, u32 len)
     mtcpsr(currmask);
 }
 
+void Xil_DCacheFlush(void)
+{
+    register u32 CsidReg, C7Reg;
+    u32 CacheSize, LineSize, NumWays;
+    u32 Way, WayIndex, Set, SetIndex, NumSet;
+    u32 currmask;
+
+    currmask = mfcpsr();
+    mtcpsr(currmask | IRQ_FIQ_MASK);
+
+    /* Select cache level 0 and D cache in CSSR */
+    mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
+
+#if defined (__GNUC__)
+    CsidReg = mfcp(XREG_CP15_CACHE_SIZE_ID);
+#elif defined (__ICCARM__)
+     mfcp(XREG_CP15_CACHE_SIZE_ID,CsidReg);
+#endif
+    /* Determine Cache Size */
+
+    CacheSize = (CsidReg >> 13U) & 0x000001FFU;
+    CacheSize += 0x00000001U;
+    CacheSize *= (u32)128;    /* to get number of bytes */
+
+    /* Number of Ways */
+    NumWays = (CsidReg & 0x000003ffU) >> 3U;
+    NumWays += 0x00000001U;
+
+    /* Get the cacheline size, way size, index size from csidr */
+    LineSize = (CsidReg & 0x00000007U) + 0x00000004U;
+
+    NumSet = CacheSize/NumWays;
+    NumSet /= (0x00000001U << LineSize);
+
+    Way = 0U;
+    Set = 0U;
+
+    /* Invalidate all the cachelines */
+    for (WayIndex = 0U; WayIndex < NumWays; WayIndex++) {
+        for (SetIndex = 0U; SetIndex < NumSet; SetIndex++) {
+            C7Reg = Way | Set;
+            /* Flush by Set/Way */
+            asm_clean_inval_dc_line_sw(C7Reg);
+
+            Set += (0x00000001U << LineSize);
+        }
+        Set = 0U;
+        Way += 0x40000000U;
+    }
+
+    /* Wait for flush to complete */
+    dsb();
+    mtcpsr(currmask);
+
+    mtcpsr(currmask);
+}
+
+void Xil_DCacheFlushLine(INTPTR adr)
+{
+    u32 currmask;
+
+    currmask = mfcpsr();
+    mtcpsr(currmask | IRQ_FIQ_MASK);
+
+    mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
+
+    mtcp(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC, (adr & (~0x1F)));
+
+        /* Wait for flush to complete */
+    dsb();
+    mtcpsr(currmask);
+}
+
 void Xil_DCacheFlushRange(INTPTR adr, u32 len)
 {
     u32 LocalAddr = adr;
@@ -163,6 +274,130 @@ void Xil_DCacheFlushRange(INTPTR adr, u32 len)
     mtcpsr(currmask);
 }
 
+void Xil_DCacheStoreLine(INTPTR adr)
+{
+    u32 currmask;
+
+    currmask = mfcpsr();
+    mtcpsr(currmask | IRQ_FIQ_MASK);
+
+    mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
+    mtcp(XREG_CP15_CLEAN_DC_LINE_MVA_POC, (adr & (~0x1F)));
+
+    /* Wait for store to complete */
+    dsb();
+    isb();
+
+    mtcpsr(currmask);
+}
+
+void Xil_ICacheEnable(void)
+{
+    register u32 CtrlReg;
+
+    /* enable caches only if they are disabled */
+#if defined (__GNUC__)
+    CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
+#elif defined (__ICCARM__)
+    mfcp(XREG_CP15_SYS_CONTROL, CtrlReg);
+#endif
+    if ((CtrlReg & XREG_CP15_CONTROL_I_BIT)==0x00000000U) {
+        /* invalidate the instruction cache */
+        mtcp(XREG_CP15_INVAL_IC_POU, 0);
+
+        /* enable the instruction cache */
+        CtrlReg |= (XREG_CP15_CONTROL_I_BIT);
+
+        mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
+    }
+}
+
+void Xil_ICacheDisable(void)
+{
+    register u32 CtrlReg;
+
+    dsb();
+
+    /* invalidate the instruction cache */
+    mtcp(XREG_CP15_INVAL_IC_POU, 0);
+
+        /* disable the instruction cache */
+#if defined (__GNUC__)
+    CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
+#elif defined (__ICCARM__)
+    mfcp(XREG_CP15_SYS_CONTROL,CtrlReg);
+#endif
+
+    CtrlReg &= ~(XREG_CP15_CONTROL_I_BIT);
+
+    mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
+}
+
+void Xil_ICacheInvalidate(void)
+{
+    u32 currmask;
+
+    currmask = mfcpsr();
+    mtcpsr(currmask | IRQ_FIQ_MASK);
+
+    mtcp(XREG_CP15_CACHE_SIZE_SEL, 1);
+
+    /* invalidate the instruction cache */
+    mtcp(XREG_CP15_INVAL_IC_POU, 0);
+
+    /* Wait for invalidate to complete */
+    dsb();
+    mtcpsr(currmask);
+}
+
+void Xil_ICacheInvalidateLine(INTPTR adr)
+{
+    u32 currmask;
+
+    currmask = mfcpsr();
+    mtcpsr(currmask | IRQ_FIQ_MASK);
+
+    mtcp(XREG_CP15_CACHE_SIZE_SEL, 1);
+    mtcp(XREG_CP15_INVAL_IC_LINE_MVA_POU, (adr & (~0x1F)));
+
+        /* Wait for invalidate to complete */
+    dsb();
+    mtcpsr(currmask);
+}
+
+void Xil_ICacheInvalidateRange(INTPTR adr, u32 len)
+{
+    u32 LocalAddr = adr;
+    const u32 cacheline = 32U;
+    u32 end;
+    u32 currmask;
+
+    currmask = mfcpsr();
+    mtcpsr(currmask | IRQ_FIQ_MASK);
+    if (len != 0x00000000U) {
+        /* Back the starting address up to the start of a cache line
+         * perform cache operations until adr+len
+         */
+        end = LocalAddr + len;
+        LocalAddr = LocalAddr & ~(cacheline - 1U);
+
+        /* Select cache L0 I-cache in CSSR */
+        mtcp(XREG_CP15_CACHE_SIZE_SEL, 1U);
+
+        while (LocalAddr < end) {
+
+            /* Invalidate L1 I-cache line */
+            asm_inval_ic_line_mva_pou(LocalAddr);
+
+            LocalAddr += cacheline;
+        }
+    }
+
+    /* Wait for invalidate to complete */
+    dsb();
+    mtcpsr(currmask);
+}
+
 void rt_hw_cpu_icache_ops(int ops, void *addr, int size)
 {
     if (ops == RT_HW_CACHE_INVALIDATE)

+ 4 - 0
libcpu/arm/zynqmp-r5/start_gcc.S

@@ -6,6 +6,9 @@
  * Change Logs:
  * Date           Author       Notes
  * 2020-03-19 	  WangHuachen  first version
+ * 2021-05-11 	  WangHuachen  Added call to Xil_InitializeExistingMPURegConfig to
+ *                             initialize the MPU configuration table with the MPU
+ *                             configurations already set in Init_Mpu function.
  */
 
 .equ Mode_USR,        0x10
@@ -234,6 +237,7 @@ ctor_loop:
     b       ctor_loop
 ctor_end:
 
+    bl 	Xil_InitializeExistingMPURegConfig	/* Initialize MPU config */
     /* start RT-Thread Kernel       */
     ldr     pc, _entry
 

+ 54 - 0
libcpu/arm/zynqmp-r5/xil_mmu.h

@@ -0,0 +1,54 @@
+/******************************************************************************
+* Copyright (c) 2015 - 2020 Xilinx, Inc.  All rights reserved.
+* SPDX-License-Identifier: MIT
+******************************************************************************/
+
+/*****************************************************************************/
+/**
+* @file xil_mmu.h
+* This file only includes xil_mpu.h which contains Xil_SetTlbAttributes API
+* defined for MPU in R5. R5 does not have mmu and for usage of similar API
+* the file has been created.
+*
+*
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 5.0    pkp  2/12/15 Initial version
+* </pre>
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+
+#ifndef XIL_MMU_H
+#define XIL_MMU_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/***************************** Include Files *********************************/
+
+#include "xil_mpu.h"
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/**************************** Type Definitions *******************************/
+
+/************************** Constant Definitions *****************************/
+
+/************************** Variable Definitions *****************************/
+
+/************************** Function Prototypes ******************************/
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* XIL_MMU_H */

+ 637 - 0
libcpu/arm/zynqmp-r5/xil_mpu.c

@@ -0,0 +1,637 @@
+/******************************************************************************
+*
+* Copyright (C) 2014 - 2017 Xilinx, Inc. All rights reserved.
+* Copyright (C) 2021 WangHuachen. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*
+*
+******************************************************************************/
+/*****************************************************************************/
+/**
+* @file xil_mpu.c
+*
+* This file provides APIs for enabling/disabling MPU and setting the memory
+* attributes for sections, in the MPU translation table.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 5.00  pkp  02/10/14 Initial version
+* 6.2   mus  01/27/17 Updated to support IAR compiler
+* 6.4   asa  08/16/17 Added many APIs for MPU access to make MPU usage
+*                       user-friendly. The APIs added are: Xil_UpdateMPUConfig,
+*                       Xil_GetMPUConfig, Xil_GetNumOfFreeRegions,
+*                       Xil_GetNextMPURegion, Xil_DisableMPURegionByRegNum,
+*                       Xil_GetMPUFreeRegMask, Xil_SetMPURegionByRegNum, and
+*                       Xil_InitializeExistingMPURegConfig.
+*                       Added a new array of structure of type XMpuConfig to
+*                       represent the MPU configuration table.
+* 6.8  aru  07/02/18 Returned the pointer instead of address
+*            of that pointer in Xil_MemMap().
+* </pre>
+*
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xil_cache.h"
+#include "xpseudo_asm_gcc.h"
+#include "xil_types.h"
+#include "xil_mpu.h"
+// #include "xdebug.h"
+#include "xreg_cortexr5.h"
+#include "xstatus.h"
+
+#include <rtthread.h>
+#define DBG_TAG           "xil_mpu"
+#define DBG_LVL           DBG_INFO
+#include <rtdbg.h>
+
+extern void Xil_DCacheFlush(void);
+extern void Xil_ICacheInvalidate(void);
+extern void Xil_DCacheDisable(void);
+extern void Xil_ICacheDisable(void);
+extern void Xil_DCacheEnable(void);
+extern void Xil_ICacheEnable(void);
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/**************************** Type Definitions *******************************/
+
+/************************** Constant Definitions *****************************/
+#define MPU_REGION_SIZE_MIN 0x20
+/************************** Variable Definitions *****************************/
+
+static const struct {
+    u64 size;
+    unsigned int encoding;
+}region_size[] = {
+    { 0x20, REGION_32B },
+    { 0x40, REGION_64B },
+    { 0x80, REGION_128B },
+    { 0x100, REGION_256B },
+    { 0x200, REGION_512B },
+    { 0x400, REGION_1K },
+    { 0x800, REGION_2K },
+    { 0x1000, REGION_4K },
+    { 0x2000, REGION_8K },
+    { 0x4000, REGION_16K },
+    { 0x8000, REGION_32K },
+    { 0x10000, REGION_64K },
+    { 0x20000, REGION_128K },
+    { 0x40000, REGION_256K },
+    { 0x80000, REGION_512K },
+    { 0x100000, REGION_1M },
+    { 0x200000, REGION_2M },
+    { 0x400000, REGION_4M },
+    { 0x800000, REGION_8M },
+    { 0x1000000, REGION_16M },
+    { 0x2000000, REGION_32M },
+    { 0x4000000, REGION_64M },
+    { 0x8000000, REGION_128M },
+    { 0x10000000, REGION_256M },
+    { 0x20000000, REGION_512M },
+    { 0x40000000, REGION_1G },
+    { 0x80000000, REGION_2G },
+    { 0x100000000, REGION_4G },
+};
+
+XMpu_Config Mpu_Config;
+
+/************************** Function Prototypes ******************************/
+void Xil_InitializeExistingMPURegConfig(void);
+/*****************************************************************************/
+/**
+* @brief    This function sets the memory attributes for a section covering
+*           1MB, of memory in the translation table.
+*
+* @param    Addr: 32-bit address for which memory attributes need to be set.
+* @param    attrib: Attribute for the given memory region.
+* @return    None.
+*
+*
+******************************************************************************/
+void Xil_SetTlbAttributes(INTPTR addr, u32 attrib)
+{
+    INTPTR Localaddr = addr;
+    Localaddr &= (~(0xFFFFFU));
+    /* Setting the MPU region with given attribute with 1MB size */
+    Xil_SetMPURegion(Localaddr, 0x100000, attrib);
+}
+
+/*****************************************************************************/
+/**
+* @brief    Set the memory attributes for a section of memory in the
+*           translation table.
+*
+* @param    Addr: 32-bit address for which memory attributes need to be set..
+* @param    size: size is the size of the region.
+* @param    attrib: Attribute for the given memory region.
+* @return    None.
+*
+*
+******************************************************************************/
+u32 Xil_SetMPURegion(INTPTR addr, u64 size, u32 attrib)
+{
+    u32 Regionsize = 0;
+    INTPTR Localaddr = addr;
+    u32 NextAvailableMemRegion;
+    unsigned int i;
+
+    NextAvailableMemRegion = Xil_GetNextMPURegion();
+    if (NextAvailableMemRegion == 0xFF) {
+        LOG_E("No regions available\r\n");
+        return XST_FAILURE;
+    }
+
+    Xil_DCacheFlush();
+    Xil_ICacheInvalidate();
+
+    mtcp(XREG_CP15_MPU_MEMORY_REG_NUMBER,NextAvailableMemRegion);
+    isb();
+
+    /* Lookup the size.  */
+    for (i = 0; i < sizeof region_size / sizeof region_size[0]; i++) {
+        if (size <= region_size[i].size) {
+            Regionsize = region_size[i].encoding;
+            break;
+        }
+    }
+
+    Localaddr &= ~(region_size[i].size - 1);
+
+    Regionsize <<= 1;
+    Regionsize |= REGION_EN;
+    dsb();
+    mtcp(XREG_CP15_MPU_REG_BASEADDR, Localaddr);    /* Set base address of a region */
+    mtcp(XREG_CP15_MPU_REG_ACCESS_CTRL, attrib);    /* Set the control attribute */
+    mtcp(XREG_CP15_MPU_REG_SIZE_EN, Regionsize);    /* set the region size and enable it*/
+    dsb();
+    isb();
+    Xil_UpdateMPUConfig(NextAvailableMemRegion, Localaddr, Regionsize, attrib);
+    return XST_SUCCESS;
+}
+/*****************************************************************************/
+/**
+* @brief    Enable MPU for Cortex R5 processor. This function invalidates I
+*           cache and flush the D Caches, and then enables the MPU.
+*
+*
+* @param    None.
+* @return    None.
+*
+******************************************************************************/
+void Xil_EnableMPU(void)
+{
+    u32 CtrlReg, Reg;
+    s32 DCacheStatus=0, ICacheStatus=0;
+    /* enable caches only if they are disabled */
+#if defined (__GNUC__)
+    CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
+#elif defined (__ICCARM__)
+    mfcp(XREG_CP15_SYS_CONTROL,CtrlReg);
+#endif
+    if ((CtrlReg & XREG_CP15_CONTROL_C_BIT) != 0x00000000U) {
+        DCacheStatus=1;
+    }
+    if ((CtrlReg & XREG_CP15_CONTROL_I_BIT) != 0x00000000U) {
+        ICacheStatus=1;
+    }
+
+    if(DCacheStatus != 0) {
+        Xil_DCacheDisable();
+    }
+    if(ICacheStatus != 0){
+        Xil_ICacheDisable();
+    }
+#if defined (__GNUC__)
+    Reg = mfcp(XREG_CP15_SYS_CONTROL);
+#elif defined (__ICCARM__)
+     mfcp(XREG_CP15_SYS_CONTROL,Reg);
+#endif
+    Reg |= 0x00000001U;
+    dsb();
+    mtcp(XREG_CP15_SYS_CONTROL, Reg);
+    isb();
+    /* enable caches only if they are disabled in routine*/
+    if(DCacheStatus != 0) {
+        Xil_DCacheEnable();
+    }
+    if(ICacheStatus != 0) {
+        Xil_ICacheEnable();
+    }
+}
+
+/*****************************************************************************/
+/**
+* @brief    Disable MPU for Cortex R5 processors. This function invalidates I
+*           cache and flush the D Caches, and then disabes the MPU.
+*
+* @param    None.
+*
+* @return    None.
+*
+******************************************************************************/
+void Xil_DisableMPU(void)
+{
+    u32 CtrlReg, Reg;
+    s32 DCacheStatus=0, ICacheStatus=0;
+    /* enable caches only if they are disabled */
+
+#if defined (__GNUC__)
+    CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
+#elif defined (__ICCARM__)
+    mfcp(XREG_CP15_SYS_CONTROL,CtrlReg);
+#endif
+    if ((CtrlReg & XREG_CP15_CONTROL_C_BIT) != 0x00000000U) {
+        DCacheStatus=1;
+    }
+    if ((CtrlReg & XREG_CP15_CONTROL_I_BIT) != 0x00000000U) {
+        ICacheStatus=1;
+    }
+
+    if(DCacheStatus != 0) {
+        Xil_DCacheDisable();
+    }
+    if(ICacheStatus != 0){
+        Xil_ICacheDisable();
+    }
+
+    mtcp(XREG_CP15_INVAL_BRANCH_ARRAY, 0);
+#if defined (__GNUC__)
+    Reg = mfcp(XREG_CP15_SYS_CONTROL);
+#elif defined (__ICCARM__)
+    mfcp(XREG_CP15_SYS_CONTROL,Reg);
+#endif
+    Reg &= ~(0x00000001U);
+    dsb();
+    mtcp(XREG_CP15_SYS_CONTROL, Reg);
+    isb();
+    /* enable caches only if they are disabled in routine*/
+    if(DCacheStatus != 0) {
+        Xil_DCacheEnable();
+    }
+    if(ICacheStatus != 0) {
+        Xil_ICacheEnable();
+    }
+}
+
+/*****************************************************************************/
+/**
+* @brief    Update the MPU configuration for the requested region number in
+*             the global MPU configuration table.
+*
+* @param    reg_num: The requested region number to be updated information for.
+* @param    address: 32 bit address for start of the region.
+* @param    size: Requested size of the region.
+* @param    attrib: Attribute for the corresponding region.
+* @return    XST_FAILURE: When the requested region number if 16 or more.
+*             XST_SUCCESS: When the MPU configuration table is updated.
+*
+*
+******************************************************************************/
+u32 Xil_UpdateMPUConfig(u32 reg_num, INTPTR address, u32 size, u32 attrib)
+{
+    u32 ReturnVal = XST_SUCCESS;
+    u32 Tempsize = size;
+    u32 Index;
+
+    if (reg_num >=  MAX_POSSIBLE_MPU_REGS) {
+        LOG_E("Invalid region number\r\n");
+        ReturnVal = XST_FAILURE;
+        goto exit;
+    }
+
+    if (size & REGION_EN) {
+        Mpu_Config[reg_num].RegionStatus = MPU_REG_ENABLED;
+        Mpu_Config[reg_num].BaseAddress = address;
+        Tempsize &= (~REGION_EN);
+        Tempsize >>= 1;
+        /* Lookup the size.  */
+        for (Index = 0; Index <
+                sizeof region_size / sizeof region_size[0]; Index++) {
+            if (Tempsize <= region_size[Index].encoding) {
+                Mpu_Config[reg_num].Size = region_size[Index].size;
+                break;
+            }
+        }
+        Mpu_Config[reg_num].Attribute = attrib;
+    } else {
+        Mpu_Config[reg_num].RegionStatus = 0U;
+        Mpu_Config[reg_num].BaseAddress = 0U;
+        Mpu_Config[reg_num].Size = 0U;
+        Mpu_Config[reg_num].Attribute = 0U;
+    }
+
+exit:
+    return ReturnVal;
+}
+
+/*****************************************************************************/
+/**
+* @brief    The MPU configuration table is passed to the caller.
+*
+* @param    mpuconfig: This is of type XMpu_Config which is an array of
+*             16 entries of type structure representing the MPU config table
+* @return    none
+*
+*
+******************************************************************************/
+void Xil_GetMPUConfig (XMpu_Config mpuconfig) {
+    u32 Index = 0U;
+
+    while (Index < MAX_POSSIBLE_MPU_REGS) {
+        mpuconfig[Index].RegionStatus = Mpu_Config[Index].RegionStatus;
+        mpuconfig[Index].BaseAddress = Mpu_Config[Index].BaseAddress;
+        mpuconfig[Index].Attribute = Mpu_Config[Index].Attribute;
+        mpuconfig[Index].Size = Mpu_Config[Index].Size;
+        Index++;
+    }
+}
+
+/*****************************************************************************/
+/**
+* @brief    Returns the total number of free MPU regions available.
+*
+* @param    none
+* @return    Number of free regions available to users
+*
+*
+******************************************************************************/
+u32 Xil_GetNumOfFreeRegions (void) {
+    u32 Index = 0U;
+    int NumofFreeRegs = 0U;
+
+    while (Index < MAX_POSSIBLE_MPU_REGS) {
+        if (MPU_REG_DISABLED == Mpu_Config[Index].RegionStatus) {
+            NumofFreeRegs++;
+        }
+        Index++;
+    }
+    return NumofFreeRegs;
+}
+
+/*****************************************************************************/
+/**
+* @brief    Returns the total number of free MPU regions available in the form
+*           of a mask. A bit of 1 in the returned 16 bit value represents the
+*           corresponding region number to be available.
+*           For example, if this function returns 0xC0000, this would mean, the
+*           regions 14 and 15 are available to users.
+*
+* @param    none
+* @return    The free region mask as a 16 bit value
+*
+*
+******************************************************************************/
+u16 Xil_GetMPUFreeRegMask (void) {
+    u32 Index = 0U;
+    u16 FreeRegMask = 0U;
+
+    while (Index < MAX_POSSIBLE_MPU_REGS) {
+        if (MPU_REG_DISABLED == Mpu_Config[Index].RegionStatus) {
+            FreeRegMask |= (1U << Index);
+        }
+        Index++;
+    }
+    return FreeRegMask;
+}
+
+/*****************************************************************************/
+/**
+* @brief    Disables the corresponding region number as passed by the user.
+*
+* @param    reg_num: The region number to be disabled
+* @return    XST_SUCCESS: If the region could be disabled successfully
+*             XST_FAILURE: If the requested region number is 16 or more.
+*
+*
+******************************************************************************/
+u32 Xil_DisableMPURegionByRegNum (u32 reg_num) {
+    u32 Temp = 0U;
+    u32 ReturnVal = XST_FAILURE;
+
+    if (reg_num >= 16U) {
+        LOG_E("Invalid region number\r\n");
+        goto exit1;
+    }
+    Xil_DCacheFlush();
+    Xil_ICacheInvalidate();
+
+    mtcp(XREG_CP15_MPU_MEMORY_REG_NUMBER,reg_num);
+#if defined (__GNUC__)
+    Temp = mfcp(XREG_CP15_MPU_REG_SIZE_EN);
+#elif defined (__ICCARM__)
+    mfcp(XREG_CP15_MPU_REG_SIZE_EN,Temp);
+#endif
+    Temp &= (~REGION_EN);
+    dsb();
+    mtcp(XREG_CP15_MPU_REG_SIZE_EN,Temp);
+    dsb();
+    isb();
+    Xil_UpdateMPUConfig(reg_num, 0U, 0U, 0U);
+    ReturnVal = XST_SUCCESS;
+
+exit1:
+    return ReturnVal;
+}
+
+/*****************************************************************************/
+/**
+* @brief    Enables the corresponding region number as passed by the user.
+*
+* @param    reg_num: The region number to be enabled
+* @param    address: 32 bit address for start of the region.
+* @param    size: Requested size of the region.
+* @param    attrib: Attribute for the corresponding region.
+* @return    XST_SUCCESS: If the region could be created successfully
+*             XST_FAILURE: If the requested region number is 16 or more.
+*
+*
+******************************************************************************/
+u32 Xil_SetMPURegionByRegNum (u32 reg_num, INTPTR addr, u64 size, u32 attrib)
+{
+    u32 ReturnVal = XST_SUCCESS;
+    INTPTR Localaddr = addr;
+    u32 Regionsize = 0;
+    u32 Index;
+
+    if (reg_num >= 16U) {
+        LOG_E("Invalid region number\r\n");
+        ReturnVal = XST_FAILURE;
+        goto exit2;
+    }
+
+    if (Mpu_Config[reg_num].RegionStatus == MPU_REG_ENABLED) {
+        LOG_E("Region already enabled\r\n");
+        ReturnVal = XST_FAILURE;
+        goto exit2;
+    }
+
+    Xil_DCacheFlush();
+    Xil_ICacheInvalidate();
+    mtcp(XREG_CP15_MPU_MEMORY_REG_NUMBER,reg_num);
+    isb();
+
+    /* Lookup the size.  */
+    for (Index = 0; Index <
+            sizeof region_size / sizeof region_size[0]; Index++) {
+        if (size <= region_size[Index].size) {
+            Regionsize = region_size[Index].encoding;
+            break;
+        }
+    }
+
+    Localaddr &= ~(region_size[Index].size - 1);
+    Regionsize <<= 1;
+    Regionsize |= REGION_EN;
+    dsb();
+    mtcp(XREG_CP15_MPU_REG_BASEADDR, Localaddr);
+    mtcp(XREG_CP15_MPU_REG_ACCESS_CTRL, attrib);
+    mtcp(XREG_CP15_MPU_REG_SIZE_EN, Regionsize);
+    dsb();
+    isb();
+    Xil_UpdateMPUConfig(reg_num, Localaddr, Regionsize, attrib);
+exit2:
+    return ReturnVal;
+
+}
+
+/*****************************************************************************/
+/**
+* @brief    Initializes the MPU configuration table that are setup in the
+*             R5 boot code in the Init_Mpu function called before C main.
+*
+* @param    none
+* @return    none
+*
+*
+******************************************************************************/
+void Xil_InitializeExistingMPURegConfig(void)
+{
+    u32 Index = 0U;
+    u32 Index1 = 0U;
+    u32 MPURegSize;
+    INTPTR MPURegBA;
+    u32 MPURegAttrib;
+    u32 Tempsize;
+
+    while (Index < MAX_POSSIBLE_MPU_REGS) {
+        mtcp(XREG_CP15_MPU_MEMORY_REG_NUMBER,Index);
+#if defined (__GNUC__)
+        MPURegSize = mfcp(XREG_CP15_MPU_REG_SIZE_EN);
+        MPURegBA = mfcp(XREG_CP15_MPU_REG_BASEADDR);
+        MPURegAttrib = mfcp(XREG_CP15_MPU_REG_ACCESS_CTRL);
+#elif defined (__ICCARM__)
+        mfcp(XREG_CP15_MPU_REG_SIZE_EN,MPURegSize);
+        mfcp(XREG_CP15_MPU_REG_BASEADDR, MPURegBA);
+        mfcp(XREG_CP15_MPU_REG_ACCESS_CTRL, MPURegAttrib);
+#endif
+        if (MPURegSize & REGION_EN) {
+            Mpu_Config[Index].RegionStatus = MPU_REG_ENABLED;
+            Mpu_Config[Index].BaseAddress = MPURegBA;
+            Mpu_Config[Index].Attribute = MPURegAttrib;
+            Tempsize = MPURegSize & (~REGION_EN);
+            Tempsize >>= 1;
+            for (Index1 = 0; Index1 <
+                (sizeof (region_size) / sizeof (region_size[0])); Index1++) {
+                if (Tempsize <= region_size[Index1].encoding) {
+                    Mpu_Config[Index].Size = region_size[Index1].size;
+                    break;
+                }
+            }
+        }
+        Index++;
+    }
+}
+
+/*****************************************************************************/
+/**
+* @brief    Returns the next available free MPU region
+*
+* @param    none
+* @return    The free MPU region available
+*
+*
+******************************************************************************/
+u32 Xil_GetNextMPURegion(void)
+{
+    u32 Index = 0U;
+    u32 NextAvailableReg = 0xFF;
+    while (Index < MAX_POSSIBLE_MPU_REGS) {
+        if (Mpu_Config[Index].RegionStatus != MPU_REG_ENABLED) {
+            NextAvailableReg = Index;
+            break;
+        }
+        Index++;
+    }
+    return NextAvailableReg;
+}
+
+/*****************************************************************************/
+/**
+* @brief       Memory mapping for Cortex r5.
+*
+* @param       Physaddr is base physical address at which to start mapping.
+*                   NULL in Physaddr masks possible mapping errors.
+* @param       size of region to be mapped.
+* @param       flags used to set translation table.
+*
+* @return      Physaddr on success, NULL on error. Ambiguous if Physaddr==NULL
+*
+* @note:    u32overflow() is defined for readability and (for __GNUC__) to
+*           - force the type of the check to be the same as the first argument
+*           - hide the otherwise unused third argument of the builtin
+*           - improve safety by choosing the explicit _uadd_ version.
+*           Consider __builtin_add_overflow_p() when available.
+*           Use an alternative (less optimal?) for compilers w/o the builtin.
+*
+******************************************************************************/
+#ifdef __GNUC__
+#define u32overflow(a, b) ({typeof(a) s; __builtin_uadd_overflow(a, b, &s); })
+#else
+#define u32overflow(a, b) ((a) > ((a) + (b)))
+#endif /* __GNUC__ */
+void *Xil_MemMap(UINTPTR Physaddr, size_t size, u32 flags)
+{
+    size_t Regionsize = MPU_REGION_SIZE_MIN;
+    UINTPTR Basephysaddr = 0, end = Physaddr + size;
+
+    if (!flags)
+        return (void *)Physaddr;
+    if (u32overflow(Physaddr, size))
+        return NULL;
+    for ( ; Regionsize != 0; Regionsize <<= 1) {
+        if (Regionsize >= size) {
+            Basephysaddr = Physaddr & ~(Regionsize - 1);
+            if (u32overflow(Basephysaddr, Regionsize))
+                break;
+            if ((Basephysaddr + Regionsize) >= end)
+                return Xil_SetMPURegion(Basephysaddr,
+                    Regionsize, flags) == XST_SUCCESS ?
+                    (void *)Physaddr : NULL;
+        }
+    }
+    return NULL;
+}

+ 129 - 0
libcpu/arm/zynqmp-r5/xil_mpu.h

@@ -0,0 +1,129 @@
+/******************************************************************************
+*
+* Copyright (C) 2014 - 2017 Xilinx, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*
+*
+******************************************************************************/
+/*****************************************************************************/
+/**
+* @file xil_mmu.h
+*
+* @addtogroup r5_mpu_apis Cortex R5 Processor MPU specific APIs
+*
+* MPU functions provides access to MPU operations such as enable MPU, disable
+* MPU and set attribute for section of memory.
+* Boot code invokes Init_MPU function to configure the MPU. A total of 10 MPU
+* regions are allocated with another 6 being free for users. Overview of the
+* memory attributes for different MPU regions is as given below,
+*
+*|                       | Memory Range            | Attributes of MPURegion     |
+*|-----------------------|-------------------------|-----------------------------|
+*| DDR                   | 0x00000000 - 0x7FFFFFFF | Normal write-back Cacheable |
+*| PL                    | 0x80000000 - 0xBFFFFFFF | Strongly Ordered            |
+*| QSPI                  | 0xC0000000 - 0xDFFFFFFF | Device Memory               |
+*| PCIe                  | 0xE0000000 - 0xEFFFFFFF | Device Memory               |
+*| STM_CORESIGHT         | 0xF8000000 - 0xF8FFFFFF | Device Memory               |
+*| RPU_R5_GIC            | 0xF9000000 - 0xF90FFFFF | Device memory               |
+*| FPS                   | 0xFD000000 - 0xFDFFFFFF | Device Memory               |
+*| LPS                   | 0xFE000000 - 0xFFFFFFFF | Device Memory               |
+*| OCM                   | 0xFFFC0000 - 0xFFFFFFFF | Normal write-back Cacheable |
+*
+*
+* @note
+* For a system where DDR is less than 2GB, region after DDR and before PL is
+* marked as undefined in translation table. Memory range 0xFE000000-0xFEFFFFFF is
+* allocated for upper LPS slaves, where as memory region 0xFF000000-0xFFFFFFFF is
+* allocated for lower LPS slaves.
+*
+* @{
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------
+* 5.00  pkp  02/10/14 Initial version
+* 6.4   asa  08/16/17 Added many APIs for MPU access to make MPU usage
+*                       user-friendly. The APIs added are: Xil_UpdateMPUConfig,
+*                       Xil_GetMPUConfig, Xil_GetNumOfFreeRegions,
+*                       Xil_GetNextMPURegion, Xil_DisableMPURegionByRegNum,
+*                       Xil_GetMPUFreeRegMask, Xil_SetMPURegionByRegNum, and
+*                       Xil_InitializeExistingMPURegConfig.
+*                       Added a new array of structure of type XMpuConfig to
+*                       represent the MPU configuration table.
+* </pre>
+*
+
+*
+*
+******************************************************************************/
+
+#ifndef XIL_MPU_H
+#define XIL_MPU_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#include "xil_types.h"
+/***************************** Include Files *********************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+#define MPU_REG_DISABLED        0U
+#define MPU_REG_ENABLED            1U
+#define MAX_POSSIBLE_MPU_REGS    16U
+/**************************** Type Definitions *******************************/
+struct XMpuConfig{
+    u32 RegionStatus; /* Enabled or disabled */
+    INTPTR BaseAddress;/* MPU region base address */
+    u64 Size; /* MPU region size address */
+    u32 Attribute; /* MPU region size attribute */
+};
+
+typedef struct XMpuConfig XMpu_Config[MAX_POSSIBLE_MPU_REGS];
+
+extern XMpu_Config Mpu_Config;
+/************************** Constant Definitions *****************************/
+
+/************************** Variable Definitions *****************************/
+
+/************************** Function Prototypes ******************************/
+
+void Xil_SetTlbAttributes(INTPTR Addr, u32 attrib);
+void Xil_EnableMPU(void);
+void Xil_DisableMPU(void);
+u32 Xil_SetMPURegion(INTPTR addr, u64 size, u32 attrib);
+u32 Xil_UpdateMPUConfig(u32 reg_num, INTPTR address, u32 size, u32 attrib);
+void Xil_GetMPUConfig (XMpu_Config mpuconfig);
+u32 Xil_GetNumOfFreeRegions (void);
+u32 Xil_GetNextMPURegion(void);
+u32 Xil_DisableMPURegionByRegNum (u32 reg_num);
+u16 Xil_GetMPUFreeRegMask (void);
+u32 Xil_SetMPURegionByRegNum (u32 reg_num, INTPTR addr, u64 size, u32 attrib);
+void* Xil_MemMap(UINTPTR Physaddr, size_t size, u32 flags);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* XIL_MPU_H */
+/**
+* @} End of "addtogroup r5_mpu_apis".
+*/

部分文件因为文件数量过多而无法显示