diff --git a/bsp/ls1bdev/SConstruct b/bsp/ls1bdev/SConstruct index 3fe0da6a6f6d5b1c47ee9668bb878ee6bcc0dc34..8288427b809c60e18b017c19d0aa9bfdb4516719 100644 --- a/bsp/ls1bdev/SConstruct +++ b/bsp/ls1bdev/SConstruct @@ -19,6 +19,7 @@ env = Environment(tools = ['mingw'], AR = rtconfig.AR, ARFLAGS = '-rc', LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) env.PrependENVPath('PATH', rtconfig.EXEC_PATH) +env['ASCOM'] = env['ASPPCOM'] Export('RTT_ROOT') Export('rtconfig') diff --git a/bsp/ls1cdev/SConstruct b/bsp/ls1cdev/SConstruct index 4ea8c066ec973e491915f191a4f15893a7b186ed..d1aa24f9d79db5adb3ec5a5cde3916a20907335d 100644 --- a/bsp/ls1cdev/SConstruct +++ b/bsp/ls1cdev/SConstruct @@ -12,7 +12,6 @@ from building import * TARGET = 'rtthread.' + rtconfig.TARGET_EXT -rtconfig.AFLAGS += ' -I' + str(Dir('#')) DefaultEnvironment(tools=[]) env = Environment(tools = ['mingw'], @@ -21,6 +20,7 @@ env = Environment(tools = ['mingw'], AR = rtconfig.AR, ARFLAGS = '-rc', LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) env.PrependENVPath('PATH', rtconfig.EXEC_PATH) +env['ASCOM'] = env['ASPPCOM'] Export('RTT_ROOT') Export('rtconfig') diff --git a/bsp/ls2kdev/.config b/bsp/ls2kdev/.config index 904e3c848d1857a9321e168c03fffea1163acb1a..1189e52a5ca18ec755ed395e3010c9cdf389d2ed 100644 --- a/bsp/ls2kdev/.config +++ b/bsp/ls2kdev/.config @@ -6,7 +6,7 @@ # # RT-Thread Kernel # -CONFIG_RT_NAME_MAX=8 +CONFIG_RT_NAME_MAX=30 # CONFIG_RT_USING_ARCH_DATA_TYPE is not set # CONFIG_RT_USING_SMP is not set CONFIG_RT_ALIGN_SIZE=8 @@ -14,12 +14,12 @@ CONFIG_RT_ALIGN_SIZE=8 CONFIG_RT_THREAD_PRIORITY_32=y # CONFIG_RT_THREAD_PRIORITY_256 is not set CONFIG_RT_THREAD_PRIORITY_MAX=32 -CONFIG_RT_TICK_PER_SECOND=100 +CONFIG_RT_TICK_PER_SECOND=1000 CONFIG_RT_USING_OVERFLOW_CHECK=y CONFIG_RT_USING_HOOK=y CONFIG_RT_USING_IDLE_HOOK=y CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 -CONFIG_IDLE_THREAD_STACK_SIZE=2048 +CONFIG_IDLE_THREAD_STACK_SIZE=16384 # CONFIG_RT_USING_TIMER_SOFT is not set CONFIG_RT_DEBUG=y # CONFIG_RT_DEBUG_COLOR is not set @@ -65,6 +65,7 @@ CONFIG_RT_USING_CONSOLE=y CONFIG_RT_CONSOLEBUF_SIZE=256 CONFIG_RT_CONSOLE_DEVICE_NAME="uart" CONFIG_RT_VER_NUM=0x40003 +CONFIG_ARCH_CPU_64BIT=y # CONFIG_RT_USING_CPU_FFS is not set CONFIG_ARCH_MIPS64=y # CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set @@ -74,7 +75,7 @@ CONFIG_ARCH_MIPS64=y # CONFIG_RT_USING_COMPONENTS_INIT=y CONFIG_RT_USING_USER_MAIN=y -CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 +CONFIG_RT_MAIN_THREAD_STACK_SIZE=16384 CONFIG_RT_MAIN_THREAD_PRIORITY=10 # @@ -93,7 +94,7 @@ CONFIG_FINSH_USING_SYMTAB=y CONFIG_FINSH_USING_DESCRIPTION=y # CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set CONFIG_FINSH_THREAD_PRIORITY=20 -CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_THREAD_STACK_SIZE=16384 CONFIG_FINSH_CMD_SIZE=80 # CONFIG_FINSH_USING_AUTH is not set CONFIG_FINSH_USING_MSH=y @@ -106,23 +107,42 @@ CONFIG_FINSH_ARG_MAX=10 # CONFIG_RT_USING_DFS=y CONFIG_DFS_USING_WORKDIR=y -CONFIG_DFS_FILESYSTEMS_MAX=2 -CONFIG_DFS_FILESYSTEM_TYPES_MAX=2 +CONFIG_DFS_FILESYSTEMS_MAX=10 +CONFIG_DFS_FILESYSTEM_TYPES_MAX=10 CONFIG_DFS_FD_MAX=16 # CONFIG_RT_USING_DFS_MNTTABLE is not set -# CONFIG_RT_USING_DFS_ELMFAT is not set +CONFIG_RT_USING_DFS_ELMFAT=y + +# +# elm-chan's FatFs, Generic FAT Filesystem Module +# +CONFIG_RT_DFS_ELM_CODE_PAGE=936 +CONFIG_RT_DFS_ELM_WORD_ACCESS=y +# CONFIG_RT_DFS_ELM_USE_LFN_0 is not set +# CONFIG_RT_DFS_ELM_USE_LFN_1 is not set +# CONFIG_RT_DFS_ELM_USE_LFN_2 is not set +CONFIG_RT_DFS_ELM_USE_LFN_3=y +CONFIG_RT_DFS_ELM_USE_LFN=3 +CONFIG_RT_DFS_ELM_MAX_LFN=255 +CONFIG_RT_DFS_ELM_DRIVES=9 +CONFIG_RT_DFS_ELM_MAX_SECTOR_SIZE=512 +# CONFIG_RT_DFS_ELM_USE_ERASE is not set +CONFIG_RT_DFS_ELM_REENTRANT=y CONFIG_RT_USING_DFS_DEVFS=y # CONFIG_RT_USING_DFS_ROMFS is not set # CONFIG_RT_USING_DFS_RAMFS is not set # CONFIG_RT_USING_DFS_UFFS is not set # CONFIG_RT_USING_DFS_JFFS2 is not set +# CONFIG_RT_USING_DFS_NFS is not set # # Device Drivers # CONFIG_RT_USING_DEVICE_IPC=y CONFIG_RT_PIPE_BUFSZ=512 -# CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set +CONFIG_RT_USING_SYSTEM_WORKQUEUE=y +CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=16384 +CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=5 CONFIG_RT_USING_SERIAL=y CONFIG_RT_SERIAL_USING_DMA=y CONFIG_RT_SERIAL_RB_BUFSZ=64 @@ -132,6 +152,7 @@ CONFIG_RT_SERIAL_RB_BUFSZ=64 # CONFIG_RT_USING_I2C is not set CONFIG_RT_USING_PIN=y # CONFIG_RT_USING_ADC is not set +# CONFIG_RT_USING_DAC is not set # CONFIG_RT_USING_PWM is not set # CONFIG_RT_USING_MTD_NOR is not set # CONFIG_RT_USING_MTD_NAND is not set @@ -172,22 +193,91 @@ CONFIG_RT_USING_POSIX=y # # Socket abstraction layer # -# CONFIG_RT_USING_SAL is not set +CONFIG_RT_USING_SAL=y + +# +# protocol stack implement +# +CONFIG_SAL_USING_LWIP=y +# CONFIG_SAL_USING_POSIX is not set +CONFIG_SAL_SOCKETS_NUM=16 # # Network interface device # -# CONFIG_RT_USING_NETDEV is not set +CONFIG_RT_USING_NETDEV=y +CONFIG_NETDEV_USING_IFCONFIG=y +CONFIG_NETDEV_USING_PING=y +CONFIG_NETDEV_USING_NETSTAT=y +CONFIG_NETDEV_USING_AUTO_DEFAULT=y +# CONFIG_NETDEV_USING_IPV6 is not set +CONFIG_NETDEV_IPV4=1 +CONFIG_NETDEV_IPV6=0 +# CONFIG_NETDEV_IPV6_SCOPES is not set # # light weight TCP/IP stack # -# CONFIG_RT_USING_LWIP is not set +CONFIG_RT_USING_LWIP=y +# CONFIG_RT_USING_LWIP141 is not set +CONFIG_RT_USING_LWIP202=y +# CONFIG_RT_USING_LWIP212 is not set +# CONFIG_RT_USING_LWIP_IPV6 is not set +CONFIG_RT_LWIP_MEM_ALIGNMENT=8 +CONFIG_RT_LWIP_IGMP=y +CONFIG_RT_LWIP_ICMP=y +CONFIG_RT_LWIP_SNMP=y +CONFIG_RT_LWIP_DNS=y +CONFIG_RT_LWIP_DHCP=y +CONFIG_IP_SOF_BROADCAST=1 +CONFIG_IP_SOF_BROADCAST_RECV=1 + +# +# Static IPv4 Address +# +CONFIG_RT_LWIP_IPADDR="192.168.1.30" +CONFIG_RT_LWIP_GWADDR="192.168.1.1" +CONFIG_RT_LWIP_MSKADDR="255.255.255.0" +CONFIG_RT_LWIP_UDP=y +CONFIG_RT_LWIP_TCP=y +CONFIG_RT_LWIP_RAW=y +# CONFIG_RT_LWIP_PPP is not set +CONFIG_RT_MEMP_NUM_NETCONN=8 +CONFIG_RT_LWIP_PBUF_NUM=16 +CONFIG_RT_LWIP_RAW_PCB_NUM=4 +CONFIG_RT_LWIP_UDP_PCB_NUM=4 +CONFIG_RT_LWIP_TCP_PCB_NUM=4 +CONFIG_RT_LWIP_TCP_SEG_NUM=40 +CONFIG_RT_LWIP_TCP_SND_BUF=8196 +CONFIG_RT_LWIP_TCP_WND=8196 +CONFIG_RT_LWIP_TCPTHREAD_PRIORITY=5 +CONFIG_RT_LWIP_TCPTHREAD_MBOX_SIZE=32 +CONFIG_RT_LWIP_TCPTHREAD_STACKSIZE=16384 +# CONFIG_LWIP_NO_RX_THREAD is not set +# CONFIG_LWIP_NO_TX_THREAD is not set +CONFIG_RT_LWIP_ETHTHREAD_PRIORITY=5 +CONFIG_RT_LWIP_ETHTHREAD_STACKSIZE=16384 +CONFIG_RT_LWIP_ETHTHREAD_MBOX_SIZE=32 +CONFIG_RT_LWIP_REASSEMBLY_FRAG=y +CONFIG_LWIP_NETIF_STATUS_CALLBACK=1 +CONFIG_LWIP_NETIF_LINK_CALLBACK=1 +CONFIG_SO_REUSE=1 +CONFIG_LWIP_SO_RCVTIMEO=1 +CONFIG_LWIP_SO_SNDTIMEO=1 +CONFIG_LWIP_SO_RCVBUF=1 +CONFIG_LWIP_SO_LINGER=0 +# CONFIG_RT_LWIP_NETIF_LOOPBACK is not set +CONFIG_LWIP_NETIF_LOOPBACK=0 +CONFIG_RT_LWIP_STATS=y +# CONFIG_RT_LWIP_USING_HW_CHECKSUM is not set +CONFIG_RT_LWIP_USING_PING=y +# CONFIG_RT_LWIP_DEBUG is not set # # AT commands # # CONFIG_RT_USING_AT is not set +# CONFIG_LWIP_USING_DHCPD is not set # # VBUS(Virtual Software BUS) @@ -213,7 +303,9 @@ CONFIG_RT_USING_POSIX=y # # IoT - internet of things # +# CONFIG_PKG_USING_LORAWAN_DRIVER is not set # CONFIG_PKG_USING_PAHOMQTT is not set +# CONFIG_PKG_USING_UMQTT is not set # CONFIG_PKG_USING_WEBCLIENT is not set # CONFIG_PKG_USING_WEBNET is not set # CONFIG_PKG_USING_MONGOOSE is not set @@ -259,7 +351,7 @@ CONFIG_RT_USING_POSIX=y # CONFIG_PKG_USING_GAGENT_CLOUD is not set # CONFIG_PKG_USING_ALI_IOTKIT is not set # CONFIG_PKG_USING_AZURE is not set -# CONFIG_PKG_USING_TENCENT_IOTHUB is not set +# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set # CONFIG_PKG_USING_JIOT-C-SDK is not set # CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set # CONFIG_PKG_USING_JOYLINK is not set @@ -281,6 +373,8 @@ CONFIG_RT_USING_POSIX=y # CONFIG_PKG_USING_CAPNP is not set # CONFIG_PKG_USING_RT_CJSON_TOOLS is not set # CONFIG_PKG_USING_AGILE_TELNET is not set +# CONFIG_PKG_USING_NMEALIB is not set +# CONFIG_PKG_USING_AGILE_JSMN is not set # # security packages @@ -289,6 +383,7 @@ CONFIG_RT_USING_POSIX=y # CONFIG_PKG_USING_libsodium is not set # CONFIG_PKG_USING_TINYCRYPT is not set # CONFIG_PKG_USING_TFM is not set +# CONFIG_PKG_USING_YD_CRYPTO is not set # # language packages @@ -323,7 +418,9 @@ CONFIG_RT_USING_POSIX=y # CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set # CONFIG_PKG_USING_LUNAR_CALENDAR is not set # CONFIG_PKG_USING_BS8116A is not set +# CONFIG_PKG_USING_GPS_RMC is not set # CONFIG_PKG_USING_URLENCODE is not set +# CONFIG_PKG_USING_UMCN is not set # # system packages @@ -331,9 +428,15 @@ 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_LWEXT4=y +CONFIG_PKG_LWEXT4_PATH="/packages/system/lwext4" +CONFIG_RT_USING_DFS_LWEXT4=y +CONFIG_PKG_USING_LWEXT4_LATEST_VERSION=y +# CONFIG_PKG_USING_LWEXT4_V100 is not set +CONFIG_PKG_LWEXT4_VER="latest" # CONFIG_PKG_USING_PARTITION is not set # CONFIG_PKG_USING_FAL is not set +# CONFIG_PKG_USING_FLASHDB is not set # CONFIG_PKG_USING_SQLITE is not set # CONFIG_PKG_USING_RTI is not set # CONFIG_PKG_USING_LITTLEVGL2RTT is not set @@ -346,6 +449,10 @@ CONFIG_RT_USING_POSIX=y # CONFIG_PKG_USING_SYSWATCH is not set # CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set # CONFIG_PKG_USING_PLCCORE is not set +# CONFIG_PKG_USING_RAMDISK is not set +# CONFIG_PKG_USING_MININI is not set +# CONFIG_PKG_USING_QBOOT is not set +# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set # # peripheral libraries and drivers @@ -383,6 +490,7 @@ CONFIG_RT_USING_POSIX=y # CONFIG_PKG_USING_RPLIDAR is not set # CONFIG_PKG_USING_AS608 is not set # CONFIG_PKG_USING_RC522 is not set +# CONFIG_PKG_USING_WS2812B is not set # CONFIG_PKG_USING_EMBARC_BSP is not set # CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set # CONFIG_PKG_USING_MULTI_RTIMER is not set @@ -390,6 +498,13 @@ CONFIG_RT_USING_POSIX=y # CONFIG_PKG_USING_BEEP is not set # CONFIG_PKG_USING_EASYBLINK is not set # CONFIG_PKG_USING_PMS_SERIES is not set +# CONFIG_PKG_USING_CAN_YMODEM is not set +# CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set +# CONFIG_PKG_USING_QLED is not set +# CONFIG_PKG_USING_PAJ7620 is not set +# CONFIG_PKG_USING_AGILE_CONSOLE is not set +# CONFIG_PKG_USING_LD3320 is not set +# CONFIG_PKG_USING_WK2124 is not set # # miscellaneous packages @@ -426,36 +541,5 @@ CONFIG_RT_USING_POSIX=y # CONFIG_PKG_USING_VT100 is not set # CONFIG_PKG_USING_ULAPACK is not set # CONFIG_PKG_USING_UKAL is not set - -# -# Privated Packages of RealThread -# -# CONFIG_PKG_USING_CODEC is not set -# CONFIG_PKG_USING_PLAYER is not set -# CONFIG_PKG_USING_MPLAYER is not set -# CONFIG_PKG_USING_PERSIMMON_SRC is not set -# CONFIG_PKG_USING_JS_PERSIMMON is not set -# CONFIG_PKG_USING_JERRYSCRIPT_WIN32 is not set - -# -# Network Utilities -# -# CONFIG_PKG_USING_WICED is not set -# CONFIG_PKG_USING_CLOUDSDK is not set -# CONFIG_PKG_USING_POWER_MANAGER is not set -# CONFIG_PKG_USING_RT_OTA is not set -# CONFIG_PKG_USING_RDBD_SRC is not set -# CONFIG_PKG_USING_RTINSIGHT is not set -# CONFIG_PKG_USING_SMARTCONFIG is not set -# CONFIG_PKG_USING_RTX is not set -# CONFIG_RT_USING_TESTCASE is not set -# CONFIG_PKG_USING_NGHTTP2 is not set -# CONFIG_PKG_USING_AVS is not set -# CONFIG_PKG_USING_ALI_LINKKIT is not set -# CONFIG_PKG_USING_STS is not set -# CONFIG_PKG_USING_DLMS is not set -# CONFIG_PKG_USING_AUDIO_FRAMEWORK is not set -# CONFIG_PKG_USING_ZBAR is not set -# CONFIG_PKG_USING_MCF is not set -# CONFIG_PKG_USING_URPC is not set +# CONFIG_PKG_USING_CRCLIB is not set CONFIG_SOC_LS2K1000=y diff --git a/bsp/ls2kdev/README.md b/bsp/ls2kdev/README.md index 783f4b2d4192434232053f00157f84fafab29e03..ff5ea50afba5502a0e5875a9f0df9b068dd47bd2 100644 --- a/bsp/ls2kdev/README.md +++ b/bsp/ls2kdev/README.md @@ -84,13 +84,43 @@ Hi, this is RT-Thread!! msh > ``` -## 4. 支持情况 +## 4.开机自动启动 + +在调试阶段,可以利用脚本,在pmon阶段从TFTP服务器上获取固件,然后引导启动。这样可以节省开发配置的时间。具体的步骤如下: + +**第一步:** +设置开发板的IP地址,在进入pmon的控制台后,输入`set ifconfig syn0:10.1.1.100`。其中`syn0`后面的ip地址为开发板的ip地址,与存放rt-thread固件的TFTP的服务器IP地址在**同一网段**。 + +**第二步:** + +进入龙芯的Debian系统,用管理员权限进入,输入用户名`root`,密码`loongson`。并且修改boot分区下的boot.cfg文件。增加如下: + +``` +title TFTPBOOT + kernel tftfp://10.1.1.118/rtthread.elf + args console=tty root=/dev/sda2 + initrd (wd0,0)/initrd.img +``` + +其中`tftfp://10.1.1.118/rtthread.elf`中的`10.1.1.118`为tftp服务器的ip地址。 + +**第三步:** + +电脑开启TFTP服务器,将路径指向存放有ls2k的rt-thread固件的目录下。 + +以上三步完成之后,重启系统,就可以省略每次都需要进入pmon的输入命令的麻烦,板子上电后,可以自动从系统TFTP服务器中获取固件,然后启动,大大提高调试代码效率。 + +## 5. 支持情况 | 驱动 | 支持情况 | 备注 | | ------ | ---- | :------: | | UART | 支持 | UART0| +| GPIO | 支持 | - | +| PWM | 支持 | - | +| GMAC | 支持 | 网卡驱动 | +| RTC | 支持 | - | -## 5. 联系人信息 +## 6. 联系人信息 维护人:[bernard][4] diff --git a/bsp/ls2kdev/SConstruct b/bsp/ls2kdev/SConstruct index 6fd6fc67f95e53535323d08b39e57766111b43a4..66b5ae86034c93bfeb7934da1575ccd78c5d030e 100644 --- a/bsp/ls2kdev/SConstruct +++ b/bsp/ls2kdev/SConstruct @@ -9,8 +9,6 @@ from building import * TARGET = 'rtthread.' + rtconfig.TARGET_EXT -rtconfig.AFLAGS += ' -I' + str(Dir('#')) + ' -I ' + RTT_ROOT + '/libcpu/mips/common/' - DefaultEnvironment(tools=[]) env = Environment(tools = ['mingw'], AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, @@ -19,6 +17,7 @@ env = Environment(tools = ['mingw'], AR = rtconfig.AR, ARFLAGS = '-rc', LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) env.PrependENVPath('PATH', rtconfig.EXEC_PATH) +env['ASCOM'] = env['ASPPCOM'] Export('RTT_ROOT') Export('rtconfig') diff --git a/bsp/ls2kdev/drivers/SConscript b/bsp/ls2kdev/drivers/SConscript index d5542b768f13877cd6fb933767564f4846aad919..33310b6d7ea403c49ceb462fc8264dbd7d032f96 100644 --- a/bsp/ls2kdev/drivers/SConscript +++ b/bsp/ls2kdev/drivers/SConscript @@ -7,4 +7,14 @@ CPPPATH = [cwd] group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH) +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +group = group + objs + Return('group') diff --git a/bsp/ls2kdev/drivers/board.h b/bsp/ls2kdev/drivers/board.h index aa2344ff764801f5a017e34e3fc29cf790af72ca..ca57ebf3f2664d8ed6566e1a8f203bce75673a94 100644 --- a/bsp/ls2kdev/drivers/board.h +++ b/bsp/ls2kdev/drivers/board.h @@ -15,8 +15,8 @@ extern unsigned char __bss_end; -#define CPU_HZ (1000 * 1000 * 1000) //QEMU 200*1000*1000 -#define RT_HW_HEAP_BEGIN KSEG1BASE//(void*)&__bss_end +#define CPU_HZ (1000 * 1000 * 1000) //QEMU 200*1000*1000 +#define RT_HW_HEAP_BEGIN (void*)&__bss_end #define RT_HW_HEAP_END (void*)(RT_HW_HEAP_BEGIN + 64 * 1024 * 1024) void rt_hw_board_init(void); diff --git a/bsp/ls2kdev/drivers/clk.c b/bsp/ls2kdev/drivers/clk.c index aba08bd87a59255b0d7a01ea2188a10b9f190b91..7a043e9ff43e9b488495894e3bc50458ce85e588 100644 --- a/bsp/ls2kdev/drivers/clk.c +++ b/bsp/ls2kdev/drivers/clk.c @@ -14,7 +14,6 @@ #include #include "ls2k1000.h" - struct loongson_pll { rt_uint64_t PLL_SYS_0; rt_uint64_t PLL_SYS_1; diff --git a/bsp/ls2kdev/drivers/drv_gpio.c b/bsp/ls2kdev/drivers/drv_gpio.c index f948bf6e1faf0f13af03971f8d192f4bbd29473f..40a859082a7aaaabc91b661d47eeed54a3c82e96 100644 --- a/bsp/ls2kdev/drivers/drv_gpio.c +++ b/bsp/ls2kdev/drivers/drv_gpio.c @@ -5,8 +5,8 @@ * Change Logs: * Date Author Notes * 2015-01-20 Bernard the first version - * 2017-10-20 ZYH add mode open drain and input pull down - * 2020-06-01 Du Huanpeng GPIO driver based on + * 2017-10-20 ZYH add mode open drain and input pull down + * 2020-06-01 Du Huanpeng GPIO driver based on */ #include #include diff --git a/bsp/ls2kdev/drivers/drv_gpio.h b/bsp/ls2kdev/drivers/drv_gpio.h index 51a75c306eb09e4911cba39e9ff3ba174872daeb..4bf1ba80f50c3b5f072879f75b8b569f0022ab82 100644 --- a/bsp/ls2kdev/drivers/drv_gpio.h +++ b/bsp/ls2kdev/drivers/drv_gpio.h @@ -6,7 +6,7 @@ * * Change Logs: * Date Author Notes - * 2017-11-24 勤为本 first version + * 2017-11-24 勤为本 first version * 2018-05-11 zhuangwei add gpio interrupt ops */ @@ -36,6 +36,5 @@ struct loongson_gpio { int loongson_pin_init(void); - #endif diff --git a/bsp/ls2kdev/drivers/drv_uart.h b/bsp/ls2kdev/drivers/drv_uart.h index 4d17b99b3505cd7fb9ecbe27960130a8782bb836..ca3e856d06a3ec03471c0d4b5ac5f3fae56192d6 100644 --- a/bsp/ls2kdev/drivers/drv_uart.h +++ b/bsp/ls2kdev/drivers/drv_uart.h @@ -15,100 +15,99 @@ #include /* UART registers */ -#define UART_DAT(base) HWREG8(base + 0x00) -#define UART_IER(base) HWREG8(base + 0x01) -#define UART_IIR(base) HWREG8(base + 0x02) -#define UART_FCR(base) HWREG8(base + 0x02) -#define UART_LCR(base) HWREG8(base + 0x03) -#define UART_MCR(base) HWREG8(base + 0x04) -#define UART_LSR(base) HWREG8(base + 0x05) -#define UART_MSR(base) HWREG8(base + 0x06) +#define UART_DAT(base) HWREG8(base + 0x00) +#define UART_IER(base) HWREG8(base + 0x01) +#define UART_IIR(base) HWREG8(base + 0x02) +#define UART_FCR(base) HWREG8(base + 0x02) +#define UART_LCR(base) HWREG8(base + 0x03) +#define UART_MCR(base) HWREG8(base + 0x04) +#define UART_LSR(base) HWREG8(base + 0x05) +#define UART_MSR(base) HWREG8(base + 0x06) -#define UART_LSB(base) HWREG8(base + 0x00) -#define UART_MSB(base) HWREG8(base + 0x01) +#define UART_LSB(base) HWREG8(base + 0x00) +#define UART_MSB(base) HWREG8(base + 0x01) /* interrupt enable register */ -#define IER_IRxE 0x1 -#define IER_ITxE 0x2 -#define IER_ILE 0x4 -#define IER_IME 0x8 +#define IER_IRxE 0x1 +#define IER_ITxE 0x2 +#define IER_ILE 0x4 +#define IER_IME 0x8 /* interrupt identification register */ -#define IIR_IMASK 0xf /* mask */ -#define IIR_RXTOUT 0xc /* receive timeout */ -#define IIR_RLS 0x6 /* receive line status */ -#define IIR_RXRDY 0x4 /* receive ready */ -#define IIR_TXRDY 0x2 /* transmit ready */ -#define IIR_NOPEND 0x1 /* nothing */ -#define IIR_MLSC 0x0 /* modem status */ -#define IIR_FIFO_MASK 0xc0 /* set if FIFOs are enabled */ +#define IIR_IMASK 0xf /* mask */ +#define IIR_RXTOUT 0xc /* receive timeout */ +#define IIR_RLS 0x6 /* receive line status */ +#define IIR_RXRDY 0x4 /* receive ready */ +#define IIR_TXRDY 0x2 /* transmit ready */ +#define IIR_NOPEND 0x1 /* nothing */ +#define IIR_MLSC 0x0 /* modem status */ +#define IIR_FIFO_MASK 0xc0 /* set if FIFOs are enabled */ /* fifo control register */ -#define FIFO_ENABLE 0x01 /* enable fifo */ -#define FIFO_RCV_RST 0x02 /* reset receive fifo */ -#define FIFO_XMT_RST 0x04 /* reset transmit fifo */ -#define FIFO_DMA_MODE 0x08 /* enable dma mode */ -#define FIFO_TRIGGER_1 0x00 /* trigger at 1 char */ -#define FIFO_TRIGGER_4 0x40 /* trigger at 4 chars */ -#define FIFO_TRIGGER_8 0x80 /* trigger at 8 chars */ -#define FIFO_TRIGGER_14 0xc0 /* trigger at 14 chars */ +#define FIFO_ENABLE 0x01 /* enable fifo */ +#define FIFO_RCV_RST 0x02 /* reset receive fifo */ +#define FIFO_XMT_RST 0x04 /* reset transmit fifo */ +#define FIFO_DMA_MODE 0x08 /* enable dma mode */ +#define FIFO_TRIGGER_1 0x00 /* trigger at 1 char */ +#define FIFO_TRIGGER_4 0x40 /* trigger at 4 chars */ +#define FIFO_TRIGGER_8 0x80 /* trigger at 8 chars */ +#define FIFO_TRIGGER_14 0xc0 /* trigger at 14 chars */ -// 线路控制寄存器 /* character format control register */ -#define CFCR_DLAB 0x80 /* divisor latch */ -#define CFCR_SBREAK 0x40 /* send break */ -#define CFCR_PZERO 0x30 /* zero parity */ -#define CFCR_PONE 0x20 /* one parity */ -#define CFCR_PEVEN 0x10 /* even parity */ -#define CFCR_PODD 0x00 /* odd parity */ -#define CFCR_PENAB 0x08 /* parity enable */ -#define CFCR_STOPB 0x04 /* 2 stop bits */ -#define CFCR_8BITS 0x03 /* 8 data bits */ -#define CFCR_7BITS 0x02 /* 7 data bits */ -#define CFCR_6BITS 0x01 /* 6 data bits */ -#define CFCR_5BITS 0x00 /* 5 data bits */ +#define CFCR_DLAB 0x80 /* divisor latch */ +#define CFCR_SBREAK 0x40 /* send break */ +#define CFCR_PZERO 0x30 /* zero parity */ +#define CFCR_PONE 0x20 /* one parity */ +#define CFCR_PEVEN 0x10 /* even parity */ +#define CFCR_PODD 0x00 /* odd parity */ +#define CFCR_PENAB 0x08 /* parity enable */ +#define CFCR_STOPB 0x04 /* 2 stop bits */ +#define CFCR_8BITS 0x03 /* 8 data bits */ +#define CFCR_7BITS 0x02 /* 7 data bits */ +#define CFCR_6BITS 0x01 /* 6 data bits */ +#define CFCR_5BITS 0x00 /* 5 data bits */ /* modem control register */ -#define MCR_LOOPBACK 0x10 /* loopback */ -#define MCR_IENABLE 0x08 /* output 2 = int enable */ -#define MCR_DRS 0x04 /* output 1 = xxx */ -#define MCR_RTS 0x02 /* enable RTS */ -#define MCR_DTR 0x01 /* enable DTR */ +#define MCR_LOOPBACK 0x10 /* loopback */ +#define MCR_IENABLE 0x08 /* output 2 = int enable */ +#define MCR_DRS 0x04 /* output 1 = xxx */ +#define MCR_RTS 0x02 /* enable RTS */ +#define MCR_DTR 0x01 /* enable DTR */ /* line status register */ -#define LSR_RCV_FIFO 0x80 /* error in receive fifo */ -#define LSR_TSRE 0x40 /* transmitter empty */ -#define LSR_TXRDY 0x20 /* transmitter ready */ -#define LSR_BI 0x10 /* break detected */ -#define LSR_FE 0x08 /* framing error */ -#define LSR_PE 0x04 /* parity error */ -#define LSR_OE 0x02 /* overrun error */ -#define LSR_RXRDY 0x01 /* receiver ready */ -#define LSR_RCV_MASK 0x1f +#define LSR_RCV_FIFO 0x80 /* error in receive fifo */ +#define LSR_TSRE 0x40 /* transmitter empty */ +#define LSR_TXRDY 0x20 /* transmitter ready */ +#define LSR_BI 0x10 /* break detected */ +#define LSR_FE 0x08 /* framing error */ +#define LSR_PE 0x04 /* parity error */ +#define LSR_OE 0x02 /* overrun error */ +#define LSR_RXRDY 0x01 /* receiver ready */ +#define LSR_RCV_MASK 0x1f /* UART interrupt enable register value */ -#define UARTIER_IME (1 << 3) -#define UARTIER_ILE (1 << 2) -#define UARTIER_ITXE (1 << 1) -#define UARTIER_IRXE (1 << 0) +#define UARTIER_IME (1 << 3) +#define UARTIER_ILE (1 << 2) +#define UARTIER_ITXE (1 << 1) +#define UARTIER_IRXE (1 << 0) /* UART line control register value */ -#define UARTLCR_DLAB (1 << 7) -#define UARTLCR_BCB (1 << 6) -#define UARTLCR_SPB (1 << 5) -#define UARTLCR_EPS (1 << 4) -#define UARTLCR_PE (1 << 3) -#define UARTLCR_SB (1 << 2) +#define UARTLCR_DLAB (1 << 7) +#define UARTLCR_BCB (1 << 6) +#define UARTLCR_SPB (1 << 5) +#define UARTLCR_EPS (1 << 4) +#define UARTLCR_PE (1 << 3) +#define UARTLCR_SB (1 << 2) /* UART line status register value */ -#define UARTLSR_ERROR (1 << 7) -#define UARTLSR_TE (1 << 6) -#define UARTLSR_TFE (1 << 5) -#define UARTLSR_BI (1 << 4) -#define UARTLSR_FE (1 << 3) -#define UARTLSR_PE (1 << 2) -#define UARTLSR_OE (1 << 1) -#define UARTLSR_DR (1 << 0) +#define UARTLSR_ERROR (1 << 7) +#define UARTLSR_TE (1 << 6) +#define UARTLSR_TFE (1 << 5) +#define UARTLSR_BI (1 << 4) +#define UARTLSR_FE (1 << 3) +#define UARTLSR_PE (1 << 2) +#define UARTLSR_OE (1 << 1) +#define UARTLSR_DR (1 << 0) #endif diff --git a/bsp/ls2kdev/drivers/interrupt.h b/bsp/ls2kdev/drivers/interrupt.h index 18707f73217de2f790c92bd546fe2d331acd4a87..df55437cf987181e8b022ad8cddf54ba46f92115 100644 --- a/bsp/ls2kdev/drivers/interrupt.h +++ b/bsp/ls2kdev/drivers/interrupt.h @@ -64,22 +64,22 @@ #define LS2K_GPIO2_INT_IRQ (62) #define LS2K_GPIO3_INT_IRQ (63) -#define MAX_INTR 64 -#define LIOINTC0_IRQBASE 0 -#define LIOINTC1_IRQBASE 32 +#define MAX_INTR (64) +#define LIOINTC0_IRQBASE (0) +#define LIOINTC1_IRQBASE (32) -#define LIOINTC_SHIFT_INTx 4 -#define LIOINTC_COREx_INTy(x, y) ((1 << x) | (1 << (y + LIOINTC_SHIFT_INTx))) +#define LIOINTC_SHIFT_INTx (4) +#define LIOINTC_COREx_INTy(x, y) ((1 << x) | (1 << (y + LIOINTC_SHIFT_INTx))) -#define LIOINTC_INTC_CHIP_START 0x20 +#define LIOINTC_INTC_CHIP_START 0x20 -#define LIOINTC_REG_INTC_STATUS (LIOINTC_INTC_CHIP_START + 0x00) -#define LIOINTC_REG_INTC_EN_STATUS (LIOINTC_INTC_CHIP_START + 0x04) -#define LIOINTC_REG_INTC_ENABLE (LIOINTC_INTC_CHIP_START + 0x08) -#define LIOINTC_REG_INTC_DISABLE (LIOINTC_INTC_CHIP_START + 0x0c) -#define LIOINTC_REG_INTC_POL (LIOINTC_INTC_CHIP_START + 0x10) -#define LIOINTC_REG_INTC_EDGE (LIOINTC_INTC_CHIP_START + 0x14) +#define LIOINTC_REG_INTC_STATUS (LIOINTC_INTC_CHIP_START + 0x00) +#define LIOINTC_REG_INTC_EN_STATUS (LIOINTC_INTC_CHIP_START + 0x04) +#define LIOINTC_REG_INTC_ENABLE (LIOINTC_INTC_CHIP_START + 0x08) +#define LIOINTC_REG_INTC_DISABLE (LIOINTC_INTC_CHIP_START + 0x0c) +#define LIOINTC_REG_INTC_POL (LIOINTC_INTC_CHIP_START + 0x10) +#define LIOINTC_REG_INTC_EDGE (LIOINTC_INTC_CHIP_START + 0x14) void liointc_set_irq_mode(int irq, int mode); -#endif \ No newline at end of file +#endif diff --git a/bsp/ls2kdev/drivers/ls2k1000.h b/bsp/ls2kdev/drivers/ls2k1000.h index 24396e7d3b9a3b5d8fb14fb6b6611f997beab9d5..38e83875fbe9c538ff90ea09840c554b4f50826a 100644 --- a/bsp/ls2kdev/drivers/ls2k1000.h +++ b/bsp/ls2kdev/drivers/ls2k1000.h @@ -6,11 +6,11 @@ #define APB_BASE CKSEG1ADDR(0xbfe00000) -#define UART0_BASE_ADDR 0xbfe00000 -#define UART0_OFF 0x0 -#define UART0_BASE CKSEG1ADDR(UART0_BASE_ADDR + UART0_OFF) +#define UART0_BASE_ADDR (0xbfe00000) +#define UART0_OFF (0x0) +#define UART0_BASE CKSEG1ADDR(UART0_BASE_ADDR + UART0_OFF) -#define UARTx_BASE(x) ((APB_BASE | (0x0 << 12) | (x << 8))) +#define UARTx_BASE(x) ((APB_BASE | (0x0 << 12) | (x << 8))) #define LIOINTC0_BASE CKSEG1ADDR(0x1fe11400) #define CORE0_INTISR0 CKSEG1ADDR(0x1fe11040) @@ -18,11 +18,11 @@ #define LIOINTC1_BASE CKSEG1ADDR(0x1fe11440) #define CORE0_INTISR1 CKSEG1ADDR(0x1fe11048) -#define GPIO_BASE 0xFFFFFFFFBFE10500 -#define PLL_SYS_BASE 0xFFFFFFFFBFE10480 -#define RTC_BASE 0xFFFFFFFFBFE07820 +#define GPIO_BASE (0xFFFFFFFFBFE10500) +#define PLL_SYS_BASE (0xFFFFFFFFBFE10480) +#define RTC_BASE (0xFFFFFFFFBFE07820) -#define GEN_CONFIG0_REG 0xFFFFFFFFBfe10420 +#define GEN_CONFIG0_REG (0xFFFFFFFFBfe10420) void rt_hw_timer_handler(void); void rt_hw_uart_init(void); diff --git a/bsp/ls2kdev/drivers/net/SConscript b/bsp/ls2kdev/drivers/net/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..841d177c42ac5c661c570522bcea876d95e7a0fe --- /dev/null +++ b/bsp/ls2kdev/drivers/net/SConscript @@ -0,0 +1,16 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') + +CPPPATH = [cwd] + +if GetDepend('RT_USING_LWIP') == False: + SrcRemove(src, 'mii.c') + SrcRemove(src, 'synopGMAC.c') + SrcRemove(src, 'synopGMAC_Dev.c') + SrcRemove(src, 'synopGMAC_plat.c') + +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/ls2kdev/drivers/net/mii.c b/bsp/ls2kdev/drivers/net/mii.c new file mode 100644 index 0000000000000000000000000000000000000000..a0b3a7adce03f8067ce57aa99c15cd549ec77d92 --- /dev/null +++ b/bsp/ls2kdev/drivers/net/mii.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-08-24 chinesebear first version + */ +#include "mii.h" + +static inline unsigned int mii_nway_result (unsigned int negotiated) +{ + unsigned int ret; + + if (negotiated & LPA_100FULL) + ret = LPA_100FULL; + else if (negotiated & LPA_100BASE4) + ret = LPA_100BASE4; + else if (negotiated & LPA_100HALF) + ret = LPA_100HALF; + else if (negotiated & LPA_10FULL) + ret = LPA_10FULL; + else + ret = LPA_10HALF; + + return ret; +} + +static int mii_check_gmii_support(struct mii_if_info *mii) +{ + int reg; + + reg = mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR); + if (reg & BMSR_ESTATEN) { + reg = mii->mdio_read(mii->dev, mii->phy_id, MII_ESTATUS); + if (reg & (ESTATUS_1000_TFULL | ESTATUS_1000_THALF)) + return 1; + } + + return 0; +} + +static int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) +{ + struct synopGMACNetworkAdapter * dev = mii->dev; + u32 advert, bmcr, lpa, nego; + u32 advert2 = 0, bmcr2 = 0, lpa2 = 0; + + ecmd->supported = + (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | + SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII); + if (mii->supports_gmii) + ecmd->supported |= SUPPORTED_1000baseT_Half | + SUPPORTED_1000baseT_Full; + + /* only supports twisted-pair */ + ecmd->port = PORT_MII; + + /* only supports internal transceiver */ + ecmd->transceiver = XCVR_INTERNAL; + + /* this isn't fully supported at higher layers */ + ecmd->phy_address = mii->phy_id; + + ecmd->advertising = ADVERTISED_TP | ADVERTISED_MII; + advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE); + if (mii->supports_gmii) + advert2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000); + + if (advert & ADVERTISE_10HALF) + ecmd->advertising |= ADVERTISED_10baseT_Half; + if (advert & ADVERTISE_10FULL) + ecmd->advertising |= ADVERTISED_10baseT_Full; + if (advert & ADVERTISE_100HALF) + ecmd->advertising |= ADVERTISED_100baseT_Half; + if (advert & ADVERTISE_100FULL) + ecmd->advertising |= ADVERTISED_100baseT_Full; + if (advert2 & ADVERTISE_1000HALF) + ecmd->advertising |= ADVERTISED_1000baseT_Half; + if (advert2 & ADVERTISE_1000FULL) + ecmd->advertising |= ADVERTISED_1000baseT_Full; + + bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); + lpa = mii->mdio_read(dev, mii->phy_id, MII_LPA); + if (mii->supports_gmii) { + bmcr2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000); + lpa2 = mii->mdio_read(dev, mii->phy_id, MII_STAT1000); + } + if (bmcr & BMCR_ANENABLE) { + ecmd->advertising |= ADVERTISED_Autoneg; + ecmd->autoneg = AUTONEG_ENABLE; + + nego = mii_nway_result(advert & lpa); + if ((bmcr2 & (ADVERTISE_1000HALF | ADVERTISE_1000FULL)) & + (lpa2 >> 2)) + ecmd->speed = SPEED_1000; + else if (nego == LPA_100FULL || nego == LPA_100HALF) + ecmd->speed = SPEED_100; + else + ecmd->speed = SPEED_10; + if ((lpa2 & LPA_1000FULL) || nego == LPA_100FULL || + nego == LPA_10FULL) { + ecmd->duplex = DUPLEX_FULL; + mii->full_duplex = 1; + } else { + ecmd->duplex = DUPLEX_HALF; + mii->full_duplex = 0; + } + } else { + ecmd->autoneg = AUTONEG_DISABLE; + + ecmd->speed = ((bmcr & BMCR_SPEED1000 && + (bmcr & BMCR_SPEED100) == 0) ? SPEED_1000 : + (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10); + ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; + } + + /* ignore maxtxpkt, maxrxpkt for now */ + + return 0; +} + +static int mii_link_ok (struct mii_if_info *mii) +{ + /* first, a dummy read, needed to latch some MII phys */ + mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR); + if (mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR) & BMSR_LSTATUS) + return 1; + return 0; +} diff --git a/bsp/ls2kdev/drivers/net/mii.h b/bsp/ls2kdev/drivers/net/mii.h new file mode 100644 index 0000000000000000000000000000000000000000..bc6d6c7a0cc6fcd96c6e20ad1d52b92ae7717a48 --- /dev/null +++ b/bsp/ls2kdev/drivers/net/mii.h @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-08-24 chinesebear first version + */ +#ifndef __MII_H__ +#define __MII_H__ +/* Generic MII registers. */ + +#include "synopGMAC_types.h" + +#define MII_BMCR 0x00 /* Basic mode control register */ +#define MII_BMSR 0x01 /* Basic mode status register */ +#define MII_PHYSID1 0x02 /* PHYS ID 1 */ +#define MII_PHYSID2 0x03 /* PHYS ID 2 */ +#define MII_ADVERTISE 0x04 /* Advertisement control reg */ +#define MII_LPA 0x05 /* Link partner ability reg */ +#define MII_EXPANSION 0x06 /* Expansion register */ +#define MII_CTRL1000 0x09 /* 1000BASE-T control */ +#define MII_STAT1000 0x0a /* 1000BASE-T status */ +#define MII_ESTATUS 0x0f /* Extended Status */ +#define MII_DCOUNTER 0x12 /* Disconnect counter */ +#define MII_FCSCOUNTER 0x13 /* False carrier counter */ +#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */ +#define MII_RERRCOUNTER 0x15 /* Receive error counter */ +#define MII_SREVISION 0x16 /* Silicon revision */ +#define MII_RESV1 0x17 /* Reserved... */ +#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */ +#define MII_PHYADDR 0x19 /* PHY address */ +#define MII_RESV2 0x1a /* Reserved... */ +#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */ +#define MII_NCONFIG 0x1c /* Network interface config */ + +/* Basic mode control register. */ +#define BMCR_RESV 0x003f /* Unused... */ +#define BMCR_SPEED1000 0x0040 /* MSB of Speed (1000) */ +#define BMCR_CTST 0x0080 /* Collision test */ +#define BMCR_FULLDPLX 0x0100 /* Full duplex */ +#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */ +#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */ +#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */ +#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */ +#define BMCR_SPEED100 0x2000 /* Select 100Mbps */ +#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */ +#define BMCR_RESET 0x8000 /* Reset the DP83840 */ + +/* Basic mode status register. */ +#define BMSR_ERCAP 0x0001 /* Ext-reg capability */ +#define BMSR_JCD 0x0002 /* Jabber detected */ +#define BMSR_LSTATUS 0x0004 /* Link status */ +#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */ +#define BMSR_RFAULT 0x0010 /* Remote fault detected */ +#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */ +#define BMSR_RESV 0x00c0 /* Unused... */ +#define BMSR_ESTATEN 0x0100 /* Extended Status in R15 */ +#define BMSR_100FULL2 0x0200 /* Can do 100BASE-T2 HDX */ +#define BMSR_100HALF2 0x0400 /* Can do 100BASE-T2 FDX */ +#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */ +#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */ +#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */ +#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */ +#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */ + +/* Advertisement control register. */ +#define ADVERTISE_SLCT 0x001f /* Selector bits */ +#define ADVERTISE_CSMA 0x0001 /* Only selector supported */ +#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */ +#define ADVERTISE_1000XFULL 0x0020 /* Try for 1000BASE-X full-duplex */ +#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */ +#define ADVERTISE_1000XHALF 0x0040 /* Try for 1000BASE-X half-duplex */ +#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */ +#define ADVERTISE_1000XPAUSE 0x0080 /* Try for 1000BASE-X pause */ +#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */ +#define ADVERTISE_1000XPSE_ASYM 0x0100 /* Try for 1000BASE-X asym pause */ +#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */ +#define ADVERTISE_PAUSE_CAP 0x0400 /* Try for pause */ +#define ADVERTISE_PAUSE_ASYM 0x0800 /* Try for asymetric pause */ +#define ADVERTISE_RESV 0x1000 /* Unused... */ +#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */ +#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */ +#define ADVERTISE_NPAGE 0x8000 /* Next page bit */ + +#define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \ + ADVERTISE_CSMA) +#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \ + ADVERTISE_100HALF | ADVERTISE_100FULL) + +/* Indicates what features are advertised by the interface. */ +#define ADVERTISED_10baseT_Half (1 << 0) +#define ADVERTISED_10baseT_Full (1 << 1) +#define ADVERTISED_100baseT_Half (1 << 2) +#define ADVERTISED_100baseT_Full (1 << 3) +#define ADVERTISED_1000baseT_Half (1 << 4) +#define ADVERTISED_1000baseT_Full (1 << 5) +#define ADVERTISED_Autoneg (1 << 6) +#define ADVERTISED_TP (1 << 7) +#define ADVERTISED_AUI (1 << 8) +#define ADVERTISED_MII (1 << 9) +#define ADVERTISED_FIBRE (1 << 10) +#define ADVERTISED_BNC (1 << 11) +#define ADVERTISED_10000baseT_Full (1 << 12) +#define ADVERTISED_Pause (1 << 13) +#define ADVERTISED_Asym_Pause (1 << 14) + +/* Link partner ability register. */ +#define LPA_SLCT 0x001f /* Same as advertise selector */ +#define LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */ +#define LPA_1000XFULL 0x0020 /* Can do 1000BASE-X full-duplex */ +#define LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */ +#define LPA_1000XHALF 0x0040 /* Can do 1000BASE-X half-duplex */ +#define LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */ +#define LPA_1000XPAUSE 0x0080 /* Can do 1000BASE-X pause */ +#define LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */ +#define LPA_1000XPAUSE_ASYM 0x0100 /* Can do 1000BASE-X pause asym*/ +#define LPA_100BASE4 0x0200 /* Can do 100mbps 4k packets */ +#define LPA_PAUSE_CAP 0x0400 /* Can pause */ +#define LPA_PAUSE_ASYM 0x0800 /* Can pause asymetrically */ +#define LPA_RESV 0x1000 /* Unused... */ +#define LPA_RFAULT 0x2000 /* Link partner faulted */ +#define LPA_LPACK 0x4000 /* Link partner acked us */ +#define LPA_NPAGE 0x8000 /* Next page bit */ + +#define LPA_DUPLEX (LPA_10FULL | LPA_100FULL) +#define LPA_100 (LPA_100FULL | LPA_100HALF | LPA_100BASE4) + +/* Expansion register for auto-negotiation. */ +#define EXPANSION_NWAY 0x0001 /* Can do N-way auto-nego */ +#define EXPANSION_LCWP 0x0002 /* Got new RX page code word */ +#define EXPANSION_ENABLENPAGE 0x0004 /* This enables npage words */ +#define EXPANSION_NPCAPABLE 0x0008 /* Link partner supports npage */ +#define EXPANSION_MFAULTS 0x0010 /* Multiple faults detected */ +#define EXPANSION_RESV 0xffe0 /* Unused... */ + +#define ESTATUS_1000_TFULL 0x2000 /* Can do 1000BT Full */ +#define ESTATUS_1000_THALF 0x1000 /* Can do 1000BT Half */ + +/* N-way test register. */ +#define NWAYTEST_RESV1 0x00ff /* Unused... */ +#define NWAYTEST_LOOPBACK 0x0100 /* Enable loopback for N-way */ +#define NWAYTEST_RESV2 0xfe00 /* Unused... */ + +/* 1000BASE-T Control register */ +#define ADVERTISE_1000FULL 0x0200 /* Advertise 1000BASE-T full duplex */ +#define ADVERTISE_1000HALF 0x0100 /* Advertise 1000BASE-T half duplex */ + +/* 1000BASE-T Status register */ +#define LPA_1000LOCALRXOK 0x2000 /* Link partner local receiver status */ +#define LPA_1000REMRXOK 0x1000 /* Link partner remote receiver status */ +#define LPA_1000FULL 0x0800 /* Link partner 1000BASE-T full duplex */ + +#define SUPPORTED_10baseT_Half (1 << 0) +#define SUPPORTED_10baseT_Full (1 << 1) +#define SUPPORTED_100baseT_Half (1 << 2) +#define SUPPORTED_100baseT_Full (1 << 3) +#define SUPPORTED_1000baseT_Half (1 << 4) +#define SUPPORTED_1000baseT_Full (1 << 5) +#define SUPPORTED_Autoneg (1 << 6) +#define SUPPORTED_TP (1 << 7) +#define SUPPORTED_AUI (1 << 8) +#define SUPPORTED_MII (1 << 9) +#define SUPPORTED_FIBRE (1 << 10) +#define SUPPORTED_BNC (1 << 11) +#define SUPPORTED_10000baseT_Full (1 << 12) +#define SUPPORTED_Pause (1 << 13) +#define SUPPORTED_Asym_Pause (1 << 14) + + +/* Which connector port. */ +#define PORT_TP 0x00 +#define PORT_AUI 0x01 +#define PORT_MII 0x02 +#define PORT_FIBRE 0x03 +#define PORT_BNC 0x04 + +/* Which transceiver to use. */ +#define XCVR_INTERNAL 0x00 +#define XCVR_EXTERNAL 0x01 +#define XCVR_DUMMY1 0x02 +#define XCVR_DUMMY2 0x03 +#define XCVR_DUMMY3 0x04 + +#define AUTONEG_DISABLE 0x00 +#define AUTONEG_ENABLE 0x01 + + +#define SPEED_10 10 +#define SPEED_100 100 +#define SPEED_1000 1000 +#define SPEED_2500 2500 +#define SPEED_10000 10000 + +#define DUPLEX_HALF 0x00 +#define DUPLEX_FULL 0x01 + +struct ethtool_cmd { + u32 cmd; + u32 supported; /* Features this interface supports */ + u32 advertising; /* Features this interface advertises */ + u16 speed; /* The forced speed, 10Mb, 100Mb, gigabit */ + u8 duplex; /* Duplex, half or full */ + u8 port; /* Which connector port */ + u8 phy_address; + u8 transceiver; /* Which transceiver to use */ + u8 autoneg; /* Enable or disable autonegotiation */ + u32 maxtxpkt; /* Tx pkts before generating tx int */ + u32 maxrxpkt; /* Rx pkts before generating rx int */ + u32 reserved[4]; +}; + +struct mii_if_info { + int phy_id; + int advertising; + int phy_id_mask; + int reg_num_mask; + + unsigned int full_duplex : 1; /* is full duplex? */ + unsigned int force_media : 1; /* is autoneg. disabled? */ + unsigned int supports_gmii : 1; /* are GMII registers supported? */ + + struct synopGMACNetworkAdapter *dev; + int (*mdio_read) (struct synopGMACNetworkAdapter *dev, int phy_id, int location); + void (*mdio_write) (struct synopGMACNetworkAdapter *dev, int phy_id, int location, int val); +}; + +#endif diff --git a/bsp/ls2kdev/drivers/net/synopGMAC.c b/bsp/ls2kdev/drivers/net/synopGMAC.c new file mode 100644 index 0000000000000000000000000000000000000000..f58f67ff5f3a0c1481d98032054e14aaf9abeb32 --- /dev/null +++ b/bsp/ls2kdev/drivers/net/synopGMAC.c @@ -0,0 +1,961 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-08-24 chinesebear first version + * 2020-08-10 lizhirui porting to ls2k + */ + +#include +#include +//#include + +#include "synopGMAC.h" +#include "mii.c" +#include "synopGMAC_debug.h" + +#define RMII + +#define Gmac_base (0x9000000000000000 | 0x40040000) +#define Buffer_Size 2048 +#define MAX_ADDR_LEN 6 +#define NAMESIZE 16 + +#define LS1B_GMAC0_IRQ 34 +#define BUS_SIZE_ALIGN(x) ((x+15)&~15) + +#define DEFAULT_MAC_ADDRESS {0x00, 0x55, 0x7B, 0xB5, 0x7D, 0xF7} + +u64 regbase = 0x9000000000000000 | 0x40040000; +static u32 GMAC_Power_down; +extern void *plat_alloc_consistent_dmaable_memory(synopGMACdevice *pcidev, u32 size, u32 *addr) ; +extern s32 synopGMAC_check_phy_init(synopGMACPciNetworkAdapter *adapter) ; +extern int init_phy(synopGMACdevice *gmacdev); +dma_addr_t plat_dma_map_single(void *hwdev, void *ptr, u32 size); + +void eth_rx_irq(int irqno, void *param); +static char Rx_Buffer[Buffer_Size]; +static char Tx_Buffer[Buffer_Size]; + +struct rt_eth_dev +{ + struct eth_device parent; + rt_uint8_t dev_addr[MAX_ADDR_LEN]; + char *name; + int iobase; + int state; + int index; + struct rt_timer link_timer; + struct rt_timer rx_poll_timer; + void *priv; +}; +static struct rt_eth_dev eth_dev; +static struct rt_semaphore sem_ack, sem_lock; + +/** + * This sets up the transmit Descriptor queue in ring or chain mode. + * This function is tightly coupled to the platform and operating system + * Device is interested only after the descriptors are setup. Therefore this function + * is not included in the device driver API. This function should be treated as an + * example code to design the descriptor structures for ring mode or chain mode. + * This function depends on the pcidev structure for allocation consistent dma-able memory in case + * of linux. + * This limitation is due to the fact that linux uses pci structure to allocate a dmable memory + * - Allocates the memory for the descriptors. + * - Initialize the Busy and Next descriptors indices to 0(Indicating first descriptor). + * - Initialize the Busy and Next descriptors to first descriptor address. + * - Initialize the last descriptor with the endof ring in case of ring mode. + * - Initialize the descriptors in chain mode. + * @param[in] pointer to synopGMACdevice. + * @param[in] pointer to pci_device structure. + * @param[in] number of descriptor expected in tx descriptor queue. + * @param[in] whether descriptors to be created in RING mode or CHAIN mode. + * \return 0 upon success. Error code upon failure. + * \note This function fails if allocation fails for required number of descriptors in Ring mode, + * but in chain mode + * function returns -ESYNOPGMACNOMEM in the process of descriptor chain creation. once returned from + * this function + * user should for gmacdev->TxDescCount to see how many descriptors are there in the chain. Should + * continue further + * only if the number of descriptors in the chain meets the requirements + */ +s32 synopGMAC_setup_tx_desc_queue(synopGMACdevice *gmacdev, u32 no_of_desc, u32 desc_mode) +{ + s32 i; + DmaDesc *bf1; + + DmaDesc *first_desc = NULL; + + dma_addr_t dma_addr; + gmacdev->TxDescCount = 0; + + first_desc = (DmaDesc *)plat_alloc_consistent_dmaable_memory(gmacdev, sizeof(DmaDesc) * (no_of_desc), &dma_addr); + + if (first_desc == NULL) + { + rt_kprintf("Error in Tx Descriptors memory allocation\n"); + return -ESYNOPGMACNOMEM; + } + + DEBUG_MES("tx_first_desc_addr = %p\n", first_desc); + DEBUG_MES("dmaadr = %p\n", dma_addr); + gmacdev->TxDescCount = no_of_desc; + gmacdev->TxDesc = first_desc; + gmacdev->TxDescDma = dma_addr; + + for (i = 0; i < gmacdev->TxDescCount; i++) + { + synopGMAC_tx_desc_init_ring(gmacdev->TxDesc + i, i == gmacdev->TxDescCount - 1); + +#if SYNOP_TOP_DEBUG + rt_kprintf("\n%02d %08x \n", i, (unsigned int)(gmacdev->TxDesc + i)); + rt_kprintf("%08x ", (unsigned int)((gmacdev->TxDesc + i))->status); + rt_kprintf("%08x ", (unsigned int)((gmacdev->TxDesc + i)->length)); + rt_kprintf("%08x ", (unsigned int)((gmacdev->TxDesc + i)->buffer1)); + rt_kprintf("%08x ", (unsigned int)((gmacdev->TxDesc + i)->buffer2)); + rt_kprintf("%08x ", (unsigned int)((gmacdev->TxDesc + i)->data1)); + rt_kprintf("%08x ", (unsigned int)((gmacdev->TxDesc + i)->data2)); + rt_kprintf("%08x ", (unsigned int)((gmacdev->TxDesc + i)->dummy1)); + rt_kprintf("%08x ", (unsigned int)((gmacdev->TxDesc + i)->dummy2)); +#endif + } + + gmacdev->TxNext = 0; + gmacdev->TxBusy = 0; + gmacdev->TxNextDesc = gmacdev->TxDesc; + gmacdev->TxBusyDesc = gmacdev->TxDesc; + gmacdev->BusyTxDesc = 0; + + return -ESYNOPGMACNOERR; +} + +/** + * This sets up the receive Descriptor queue in ring or chain mode. + * This function is tightly coupled to the platform and operating system + * Device is interested only after the descriptors are setup. Therefore this function + * is not included in the device driver API. This function should be treated as an + * example code to design the descriptor structures in ring mode or chain mode. + * This function depends on the pcidev structure for allocation of consistent dma-able memory in + * case of linux. + * This limitation is due to the fact that linux uses pci structure to allocate a dmable memory + * - Allocates the memory for the descriptors. + * - Initialize the Busy and Next descriptors indices to 0(Indicating first descriptor). + * - Initialize the Busy and Next descriptors to first descriptor address. + * - Initialize the last descriptor with the endof ring in case of ring mode. + * - Initialize the descriptors in chain mode. + * @param[in] pointer to synopGMACdevice. + * @param[in] pointer to pci_device structure. + * @param[in] number of descriptor expected in rx descriptor queue. + * @param[in] whether descriptors to be created in RING mode or CHAIN mode. + * \return 0 upon success. Error code upon failure. + * \note This function fails if allocation fails for required number of descriptors in Ring mode, + * but in chain mode + * function returns -ESYNOPGMACNOMEM in the process of descriptor chain creation. once returned from + * this function + * user should for gmacdev->RxDescCount to see how many descriptors are there in the chain. Should + * continue further + * only if the number of descriptors in the chain meets the requirements + */ +s32 synopGMAC_setup_rx_desc_queue(synopGMACdevice *gmacdev, u32 no_of_desc, u32 desc_mode) +{ + s32 i; + DmaDesc *bf1; + DmaDesc *first_desc = NULL; + + dma_addr_t dma_addr; + + gmacdev->RxDescCount = 0; + first_desc = (DmaDesc *)plat_alloc_consistent_dmaable_memory(gmacdev, sizeof(DmaDesc) * no_of_desc, &dma_addr); + if (first_desc == NULL) + { + rt_kprintf("Error in Rx Descriptor Memory allocation in Ring mode\n"); + return -ESYNOPGMACNOMEM; + } + + DEBUG_MES("rx_first_desc_addr = %p\n", first_desc); + DEBUG_MES("dmaadr = %p\n", dma_addr); + gmacdev->RxDescCount = no_of_desc; + gmacdev->RxDesc = (DmaDesc *)first_desc; + gmacdev->RxDescDma = dma_addr; + + for (i = 0; i < gmacdev->RxDescCount; i++) + { + synopGMAC_rx_desc_init_ring(gmacdev->RxDesc + i, i == gmacdev->RxDescCount - 1); + } + + gmacdev->RxNext = 0; + gmacdev->RxBusy = 0; + gmacdev->RxNextDesc = gmacdev->RxDesc; + gmacdev->RxBusyDesc = gmacdev->RxDesc; + + gmacdev->BusyRxDesc = 0; + + return -ESYNOPGMACNOERR; +} + +void synopGMAC_linux_cable_unplug_function(void *adaptr) +{ + s32 data; + synopGMACPciNetworkAdapter *adapter = (synopGMACPciNetworkAdapter *)adaptr; + synopGMACdevice *gmacdev = adapter->synopGMACdev; + struct ethtool_cmd cmd; + + //rt_kprintf("%s\n",__FUNCTION__); + if (!mii_link_ok(&adapter->mii)) + { + if (gmacdev->LinkState) + rt_kprintf("\r\nNo Link\r\n"); + gmacdev->DuplexMode = 0; + gmacdev->Speed = 0; + gmacdev->LoopBackMode = 0; + gmacdev->LinkState = 0; + } + else + { + data = synopGMAC_check_phy_init(adapter); + + if (gmacdev->LinkState != data) + { + gmacdev->LinkState = data; + synopGMAC_mac_init(gmacdev); + rt_kprintf("Link is up in %s mode\n", (gmacdev->DuplexMode == FULLDUPLEX) ? "FULL DUPLEX" : "HALF DUPLEX"); + if (gmacdev->Speed == SPEED1000) + rt_kprintf("Link is with 1000M Speed \r\n"); + if (gmacdev->Speed == SPEED100) + rt_kprintf("Link is with 100M Speed \n"); + if (gmacdev->Speed == SPEED10) + rt_kprintf("Link is with 10M Speed \n"); + } + } +} + +s32 synopGMAC_check_phy_init(synopGMACPciNetworkAdapter *adapter) +{ + struct ethtool_cmd cmd; + synopGMACdevice *gmacdev = adapter->synopGMACdev; + + if (!mii_link_ok(&adapter->mii)) + { + gmacdev->DuplexMode = FULLDUPLEX; + gmacdev->Speed = SPEED100; + + return 0; + } + else + { + mii_ethtool_gset(&adapter->mii, &cmd); + + gmacdev->DuplexMode = (cmd.duplex == DUPLEX_FULL) ? FULLDUPLEX : HALFDUPLEX ; + if (cmd.speed == SPEED_1000) + gmacdev->Speed = SPEED1000; + else if (cmd.speed == SPEED_100) + gmacdev->Speed = SPEED100; + else + gmacdev->Speed = SPEED10; + } + + return gmacdev->Speed | (gmacdev->DuplexMode << 4); +} + +static int Mac_change_check(u8 *macaddr0, u8 *macaddr1) +{ + int i; + for (i = 0; i < 6; i++) + { + if (macaddr0[i] != macaddr1[i]) + return 1; + } + return 0; +} + +static rt_err_t eth_init(rt_device_t device) +{ + struct eth_device *eth_device = (struct eth_device *)device; + RT_ASSERT(eth_device != RT_NULL); + + s32 ijk; + s32 status = 0; + u64 dma_addr; + u32 Mac_changed = 0; + struct pbuf *pbuf; + u8 macaddr[6] = DEFAULT_MAC_ADDRESS; + struct rt_eth_dev *dev = ð_dev; + struct synopGMACNetworkAdapter *adapter = dev->priv; + synopGMACdevice *gmacdev = (synopGMACdevice *)adapter->synopGMACdev; + + synopGMAC_reset(gmacdev); + synopGMAC_attach(gmacdev, (regbase + MACBASE), (regbase + DMABASE), DEFAULT_PHY_BASE, macaddr); + + synopGMAC_read_version(gmacdev); + + synopGMAC_set_mdc_clk_div(gmacdev, GmiiCsrClk3); + gmacdev->ClockDivMdc = synopGMAC_get_mdc_clk_div(gmacdev); + + init_phy(adapter->synopGMACdev); + + DEBUG_MES("tx desc_queue\n"); + synopGMAC_setup_tx_desc_queue(gmacdev, TRANSMIT_DESC_SIZE, RINGMODE); + synopGMAC_init_tx_desc_base(gmacdev); + + DEBUG_MES("rx desc_queue\n"); + synopGMAC_setup_rx_desc_queue(gmacdev, RECEIVE_DESC_SIZE, RINGMODE); + synopGMAC_init_rx_desc_base(gmacdev); + DEBUG_MES("DmaRxBaseAddr = %08x\n", synopGMACReadReg(gmacdev->DmaBase, DmaRxBaseAddr)); + +// u32 dmaRx_Base_addr = synopGMACReadReg(gmacdev->DmaBase,DmaRxBaseAddr); +// rt_kprintf("first_desc_addr = 0x%x\n", dmaRx_Base_addr); + +#ifdef ENH_DESC_8W + synopGMAC_dma_bus_mode_init(gmacdev, DmaBurstLength32 | DmaDescriptorSkip2 | DmaDescriptor8Words); +#else + synopGMAC_dma_bus_mode_init(gmacdev, DmaBurstLength4 | DmaDescriptorSkip1); + //synopGMAC_dma_bus_mode_init(gmacdev, DmaBurstLength4 | DmaDescriptorSkip2); +#endif + synopGMAC_dma_control_init(gmacdev, DmaStoreAndForward | DmaTxSecondFrame | DmaRxThreshCtrl128); + + status = synopGMAC_check_phy_init(adapter); + synopGMAC_mac_init(gmacdev); + + synopGMAC_pause_control(gmacdev); + +#ifdef IPC_OFFLOAD + synopGMAC_enable_rx_chksum_offload(gmacdev); + synopGMAC_rx_tcpip_chksum_drop_enable(gmacdev); +#endif + + u64 skb; + do + { + skb = (u64)plat_alloc_memory(RX_BUF_SIZE); //should skb aligned here? + if (skb == RT_NULL) + { + rt_kprintf("ERROR in skb buffer allocation\n"); + break; + } + + dma_addr = plat_dma_map_single(gmacdev, (void *)skb, RX_BUF_SIZE); //获取 skb 的 dma 地址 + + status = synopGMAC_set_rx_qptr(gmacdev, dma_addr, RX_BUF_SIZE, (u64)skb, 0, 0, 0); + if (status < 0) + { + rt_kprintf("status < 0!!\n"); + plat_free_memory((void *)skb); + } + } + while (status >= 0 && (status < (RECEIVE_DESC_SIZE - 1))); + synopGMAC_clear_interrupt(gmacdev); + + synopGMAC_disable_mmc_tx_interrupt(gmacdev, 0xFFFFFFFF); + synopGMAC_disable_mmc_rx_interrupt(gmacdev, 0xFFFFFFFF); + synopGMAC_disable_mmc_ipc_rx_interrupt(gmacdev, 0xFFFFFFFF); + +// synopGMAC_disable_interrupt_all(gmacdev); + synopGMAC_enable_interrupt(gmacdev, DmaIntEnable); + synopGMAC_enable_dma_rx(gmacdev); + synopGMAC_enable_dma_tx(gmacdev); + + plat_delay(DEFAULT_LOOP_VARIABLE); + synopGMAC_check_phy_init(adapter); + synopGMAC_mac_init(gmacdev); + + rt_timer_init(&dev->link_timer, "link_timer", + synopGMAC_linux_cable_unplug_function, + (void *)adapter, + RT_TICK_PER_SECOND, + RT_TIMER_FLAG_PERIODIC); + + rt_timer_start(&dev->link_timer); +#ifdef RT_USING_GMAC_INT_MODE + /* installl isr */ + DEBUG_MES("%s\n", __FUNCTION__); + rt_hw_interrupt_install(LS1C_MAC_IRQ, eth_rx_irq, RT_NULL, "e0_isr"); + rt_hw_interrupt_umask(LS1C_MAC_IRQ); +#else + rt_timer_init(&dev->rx_poll_timer, "rx_poll_timer", + eth_rx_irq, + (void *)adapter, + 1, + RT_TIMER_FLAG_PERIODIC); + + rt_timer_start(&dev->rx_poll_timer); +#endif /*RT_USING_GMAC_INT_MODE*/ + + return RT_EOK; +} + +static rt_err_t eth_open(rt_device_t dev, rt_uint16_t oflag) +{ + rt_kprintf("eth_open!!\n"); + + return RT_EOK; +} + +static rt_err_t eth_close(rt_device_t dev) +{ + return RT_EOK; +} + +static rt_size_t eth_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + rt_set_errno(-RT_ENOSYS); + return 0; +} + +static rt_size_t eth_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +{ + rt_set_errno(-RT_ENOSYS); + return 0; +} + +static rt_err_t eth_control(rt_device_t dev, int cmd, void *args) +{ + switch (cmd) + { + case NIOCTL_GADDR: + if (args) rt_memcpy(args, eth_dev.dev_addr, 6); + else return -RT_ERROR; + break; + + default : + break; + } + return RT_EOK; +} + +rt_err_t rt_eth_tx(rt_device_t device, struct pbuf *p) +{ + /* lock eth device */ + rt_sem_take(&sem_lock, RT_WAITING_FOREVER); + + DEBUG_MES("in %s\n", __FUNCTION__); + + s32 status; + u64 pbuf; + u64 dma_addr; + u32 offload_needed = 0; + u32 index; + DmaDesc *dpr; + struct rt_eth_dev *dev = (struct rt_eth_dev *) device; + struct synopGMACNetworkAdapter *adapter; + synopGMACdevice *gmacdev; + adapter = (struct synopGMACNetworkAdapter *) dev->priv; + if (adapter == NULL) + return -1; + + gmacdev = (synopGMACdevice *) adapter->synopGMACdev; + if (gmacdev == NULL) + return -1; + + if (!synopGMAC_is_desc_owned_by_dma(gmacdev->TxNextDesc)) + { + + pbuf = (u64)plat_alloc_memory(p->tot_len); + //pbuf = (u32)pbuf_alloc(PBUF_LINK, p->len, PBUF_RAM); + if (pbuf == 0) + { + rt_kprintf("===error in alloc bf1\n"); + return -1; + } + + DEBUG_MES("p->len = %d\n", p->len); + pbuf_copy_partial(p, (void *)pbuf, p->tot_len, 0); + dma_addr = plat_dma_map_single(gmacdev, (void *)pbuf, p->tot_len); + + status = synopGMAC_set_tx_qptr(gmacdev, dma_addr, p->tot_len, pbuf, 0, 0, 0, offload_needed, &index, dpr); + + if (status < 0) + { + rt_kprintf("%s No More Free Tx Descriptors\n", __FUNCTION__); + + plat_free_memory((void *)pbuf); + return -16; + } + } + + synopGMAC_resume_dma_tx(gmacdev); + + + s32 desc_index; + u64 data1, data2; + u32 dma_addr1, dma_addr2; + u32 length1, length2; +#ifdef ENH_DESC_8W + u32 ext_status; + u16 time_stamp_higher; + u32 time_stamp_high; + u32 time_stamp_low; +#endif + do + { +#ifdef ENH_DESC_8W + desc_index = synopGMAC_get_tx_qptr(gmacdev, &status, &dma_addr1, &length1, &data1, &dma_addr2, &length2, &data2, &ext_status, &time_stamp_high, &time_stamp_low); + synopGMAC_TS_read_timestamp_higher_val(gmacdev, &time_stamp_higher); +#else + desc_index = synopGMAC_get_tx_qptr(gmacdev, &status, &dma_addr1, &length1, &data1, &dma_addr2, &length2, &data2); +#endif + if (desc_index >= 0 && data1 != 0) + { +#ifdef IPC_OFFLOAD + if (synopGMAC_is_tx_ipv4header_checksum_error(gmacdev, status)) + { + rt_kprintf("Harware Failed to Insert IPV4 Header Checksum\n"); + } + if (synopGMAC_is_tx_payload_checksum_error(gmacdev, status)) + { + rt_kprintf("Harware Failed to Insert Payload Checksum\n"); + } +#endif + + plat_free_memory((void *)(data1)); //sw: data1 = buffer1 + + if (synopGMAC_is_desc_valid(status)) + { + adapter->synopGMACNetStats.tx_bytes += length1; + adapter->synopGMACNetStats.tx_packets++; + } + else + { + adapter->synopGMACNetStats.tx_errors++; + adapter->synopGMACNetStats.tx_aborted_errors += synopGMAC_is_tx_aborted(status); + adapter->synopGMACNetStats.tx_carrier_errors += synopGMAC_is_tx_carrier_error(status); + } + } + + adapter->synopGMACNetStats.collisions += synopGMAC_get_tx_collision_count(status); + } + while (desc_index >= 0); + + /* unlock eth device */ + rt_sem_release(&sem_lock); +// rt_kprintf("output %d bytes\n", p->len); + u32 test_data; + test_data = synopGMACReadReg(gmacdev->DmaBase, DmaStatus); + //rt_kprintf("dma_status = 0x%08x\n",test_data); + + return RT_EOK; +} + +struct pbuf *rt_eth_rx(rt_device_t device) +{ + DEBUG_MES("%s : \n", __FUNCTION__); + struct rt_eth_dev *dev = ð_dev; + struct synopGMACNetworkAdapter *adapter; + synopGMACdevice *gmacdev; +// struct PmonInet * pinetdev; + s32 desc_index; + int i; + char *ptr; + u32 bf1; + u64 data1; + u64 data2; + u32 len; + u32 status; + u32 dma_addr1; + u32 dma_addr2; + struct pbuf *pbuf = RT_NULL; + rt_sem_take(&sem_lock, RT_WAITING_FOREVER); + + adapter = (struct synopGMACNetworkAdapter *) dev->priv; + if (adapter == NULL) + { + rt_kprintf("%S : Unknown Device !!\n", __FUNCTION__); + return NULL; + } + + gmacdev = (synopGMACdevice *) adapter->synopGMACdev; + if (gmacdev == NULL) + { + rt_kprintf("%s : GMAC device structure is missing\n", __FUNCTION__); + return NULL; + } + + /*Handle the Receive Descriptors*/ + desc_index = synopGMAC_get_rx_qptr(gmacdev, &status, &dma_addr1, NULL, &data1, &dma_addr2, NULL, &data2); + + if(((u32)desc_index >= RECEIVE_DESC_SIZE) && (desc_index != -1)) + { + rt_kprintf("host receive descriptor address pointer = 0x%08x\n",synopGMACReadReg(gmacdev->DmaBase,DmaRxCurrDesc)); + rt_kprintf("host receive buffer = 0x%08x\n",synopGMACReadReg(gmacdev->DmaBase,DmaRxCurrAddr)); + rt_kprintf("desc_index error!!!!,tick = %d\n",rt_tick_get()); + while(1); + } + + if (desc_index >= 0 && data1 != 0) + { + DEBUG_MES("Received Data at Rx Descriptor %d for skb 0x%08x whose status is %08x\n", desc_index, dma_addr1, status); + + if (synopGMAC_is_rx_desc_valid(status) || SYNOP_PHY_LOOPBACK) + { + dma_addr1 = plat_dma_map_single(gmacdev, (void *)data1, RX_BUF_SIZE); + len = synopGMAC_get_rx_desc_frame_length(status)-4; //Not interested in Ethernet CRC bytes + pbuf = pbuf_alloc(PBUF_LINK, len, PBUF_RAM); + if (pbuf == 0) rt_kprintf("===error in pbuf_alloc\n"); + rt_memcpy(pbuf->payload, (char *)data1, len); + DEBUG_MES("==get pkg len: %d\n", len); + } + else + { + rt_kprintf("s: %08x\n", status); + adapter->synopGMACNetStats.rx_errors++; + adapter->synopGMACNetStats.collisions += synopGMAC_is_rx_frame_collision(status); + adapter->synopGMACNetStats.rx_crc_errors += synopGMAC_is_rx_crc(status); + adapter->synopGMACNetStats.rx_frame_errors += synopGMAC_is_frame_dribbling_errors(status); + adapter->synopGMACNetStats.rx_length_errors += synopGMAC_is_rx_frame_length_errors(status); + } + desc_index = synopGMAC_set_rx_qptr(gmacdev, dma_addr1, RX_BUF_SIZE, (u64)data1, 0, 0, 0); + if (desc_index < 0) + { +#if SYNOP_RX_DEBUG + rt_kprintf("Cannot set Rx Descriptor for data1 %08x\n", (u32)data1); +#endif + + plat_free_memory((void *)data1); + } + } + rt_sem_release(&sem_lock); + DEBUG_MES("%s : before return \n", __FUNCTION__); + return pbuf; +} + +static int rtl88e1111_config_init(synopGMACdevice *gmacdev) +{ + int retval, err; + u16 data; + + DEBUG_MES("in %s\n", __FUNCTION__); + synopGMAC_read_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x14, &data); + data = data | 0x82; + err = synopGMAC_write_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x14, data); + synopGMAC_read_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x00, &data); + data = data | 0x8000; + err = synopGMAC_write_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x00, data); +#if SYNOP_PHY_LOOPBACK + synopGMAC_read_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x14, &data); + data = data | 0x70; + data = data & 0xffdf; + err = synopGMAC_write_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x14, data); + data = 0x8000; + err = synopGMAC_write_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x00, data); + data = 0x5140; + err = synopGMAC_write_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x00, data); +#endif + if (err < 0) + return err; + return 0; +} + +int init_phy(synopGMACdevice *gmacdev) +{ + u16 data; + + synopGMAC_read_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 2, &data); + /*set 88e1111 clock phase delay*/ + if (data == 0x141) + rtl88e1111_config_init(gmacdev); +#if defined (RMII) + else if (data == 0x8201) + { + //RTL8201 + data = 0x400; // set RMII mode + synopGMAC_write_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x19, data); + synopGMAC_read_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x19, &data); + TR("phy reg25 is %0x \n", data); + + data = 0x3100; //set 100M speed + synopGMAC_write_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x0, data); + } + else if (data == 0x0180 || data == 0x0181) + { + //DM9161 + synopGMAC_read_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x10, &data); + data |= (1 << 8); //set RMII mode + synopGMAC_write_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x10, data); //set RMII mode + synopGMAC_read_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x10, &data); + TR("phy reg16 is 0x%0x \n", data); + + // synopGMAC_read_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0x0,&data); + // data &= ~(1<<10); + data = 0x3100; //set auto- + //data = 0x0100; //set 10M speed + synopGMAC_write_phy_reg(gmacdev->MacBase, gmacdev->PhyBase, 0x0, data); + } +#endif + + return 0; +} + +u32 synopGMAC_wakeup_filter_config3[] = +{ + 0x00000000, + 0x000000FF, + 0x00000000, + 0x00000000, + 0x00000100, + 0x00003200, + 0x7eED0000, + 0x00000000 +}; + +static void synopGMAC_linux_powerdown_mac(synopGMACdevice *gmacdev) +{ + rt_kprintf("Put the GMAC to power down mode..\n"); + + GMAC_Power_down = 1; + + synopGMAC_disable_dma_tx(gmacdev); + plat_delay(10000); + + synopGMAC_tx_disable(gmacdev); + synopGMAC_rx_disable(gmacdev); + plat_delay(10000); + + synopGMAC_disable_dma_rx(gmacdev); + + synopGMAC_magic_packet_enable(gmacdev); + synopGMAC_write_wakeup_frame_register(gmacdev, synopGMAC_wakeup_filter_config3); + + synopGMAC_wakeup_frame_enable(gmacdev); + + synopGMAC_rx_enable(gmacdev); + + synopGMAC_pmt_int_enable(gmacdev); + + synopGMAC_power_down_enable(gmacdev); + return; +} + +static void synopGMAC_linux_powerup_mac(synopGMACdevice *gmacdev) +{ + GMAC_Power_down = 0; + if (synopGMAC_is_magic_packet_received(gmacdev)) + rt_kprintf("GMAC wokeup due to Magic Pkt Received\n"); + if (synopGMAC_is_wakeup_frame_received(gmacdev)) + rt_kprintf("GMAC wokeup due to Wakeup Frame Received\n"); + + synopGMAC_pmt_int_disable(gmacdev); + + synopGMAC_rx_enable(gmacdev); + synopGMAC_enable_dma_rx(gmacdev); + + synopGMAC_tx_enable(gmacdev); + synopGMAC_enable_dma_tx(gmacdev); + return; +} + + +static int mdio_read(synopGMACPciNetworkAdapter *adapter, int addr, int reg) +{ + synopGMACdevice *gmacdev; + u16 data; + gmacdev = adapter->synopGMACdev; + + synopGMAC_read_phy_reg(gmacdev->MacBase, addr, reg, &data); + return data; +} + +static void mdio_write(synopGMACPciNetworkAdapter *adapter, int addr, int reg, int data) +{ + synopGMACdevice *gmacdev; + gmacdev = adapter->synopGMACdev; + synopGMAC_write_phy_reg(gmacdev->MacBase, addr, reg, data); +} + +void eth_rx_irq(int irqno, void *param) +{ + struct rt_eth_dev *dev = ð_dev; + struct synopGMACNetworkAdapter *adapter = dev->priv; + //DEBUG_MES("in irq!!\n"); +#ifdef RT_USING_GMAC_INT_MODE + int i ; + for (i = 0; i < 7200; i++) + ; +#endif /*RT_USING_GMAC_INT_MODE*/ + synopGMACdevice *gmacdev = (synopGMACdevice *)adapter->synopGMACdev; + + u32 interrupt, dma_status_reg; + s32 status; + u32 dma_addr; + + //rt_kprintf("irq i = %d\n", i++); + dma_status_reg = synopGMACReadReg(gmacdev->DmaBase, DmaStatus); + if (dma_status_reg == 0) + { + rt_kprintf("dma_status ==0 \n"); + return; + } + + //rt_kprintf("dma_status_reg is 0x%x\n", dma_status_reg); + u32 gmacstatus; + synopGMAC_disable_interrupt_all(gmacdev); + gmacstatus = synopGMACReadReg(gmacdev->MacBase, GmacStatus); + + if (dma_status_reg & GmacPmtIntr) + { + rt_kprintf("%s:: Interrupt due to PMT module\n", __FUNCTION__); + //synopGMAC_linux_powerup_mac(gmacdev); + } + if (dma_status_reg & GmacMmcIntr) + { + rt_kprintf("%s:: Interrupt due to MMC module\n", __FUNCTION__); + DEBUG_MES("%s:: synopGMAC_rx_int_status = %08x\n", __FUNCTION__, synopGMAC_read_mmc_rx_int_status(gmacdev)); + DEBUG_MES("%s:: synopGMAC_tx_int_status = %08x\n", __FUNCTION__, synopGMAC_read_mmc_tx_int_status(gmacdev)); + } + + if (dma_status_reg & GmacLineIntfIntr) + { + //rt_kprintf("%s:: Interrupt due to GMAC LINE module\n", __FUNCTION__); + } + + interrupt = synopGMAC_get_interrupt_type(gmacdev); + //rt_kprintf("%s:Interrupts to be handled: 0x%08x\n",__FUNCTION__,interrupt); + if (interrupt & synopGMACDmaError) + { + u8 mac_addr0[6]; + rt_kprintf("%s::Fatal Bus Error Inetrrupt Seen\n", __FUNCTION__); + + memcpy(mac_addr0, dev->dev_addr, 6); + synopGMAC_disable_dma_tx(gmacdev); + synopGMAC_disable_dma_rx(gmacdev); + + synopGMAC_take_desc_ownership_tx(gmacdev); + synopGMAC_take_desc_ownership_rx(gmacdev); + + synopGMAC_init_tx_rx_desc_queue(gmacdev); + + synopGMAC_reset(gmacdev); + + synopGMAC_set_mac_addr(gmacdev, GmacAddr0High, GmacAddr0Low, mac_addr0); + synopGMAC_dma_bus_mode_init(gmacdev, DmaFixedBurstEnable | DmaBurstLength8 | DmaDescriptorSkip1); + synopGMAC_dma_control_init(gmacdev, DmaStoreAndForward); + synopGMAC_init_rx_desc_base(gmacdev); + synopGMAC_init_tx_desc_base(gmacdev); + synopGMAC_mac_init(gmacdev); + synopGMAC_enable_dma_rx(gmacdev); + synopGMAC_enable_dma_tx(gmacdev); + + } + if (interrupt & synopGMACDmaRxNormal) + { + //DEBUG_MES("%s:: Rx Normal \n", __FUNCTION__); + //synop_handle_received_data(netdev); + eth_device_ready(ð_dev.parent); + } + if (interrupt & synopGMACDmaRxAbnormal) + { + //rt_kprintf("%s::Abnormal Rx Interrupt Seen\n",__FUNCTION__); + if (GMAC_Power_down == 0) + { + adapter->synopGMACNetStats.rx_over_errors++; + synopGMACWriteReg(gmacdev->DmaBase, DmaStatus, 0x80); + synopGMAC_resume_dma_rx(gmacdev); + } + } + if (interrupt & synopGMACDmaRxStopped) + { + rt_kprintf("%s::Receiver stopped seeing Rx interrupts\n", __FUNCTION__); //Receiver gone in to stopped state + } + + if (interrupt & synopGMACDmaTxNormal) + { + DEBUG_MES("%s::Finished Normal Transmission \n", __FUNCTION__); + // synop_handle_transmit_over(netdev); + } + + if (interrupt & synopGMACDmaTxAbnormal) + { + rt_kprintf("%s::Abnormal Tx Interrupt Seen\n", __FUNCTION__); + } + if (interrupt & synopGMACDmaTxStopped) + { + TR("%s::Transmitter stopped sending the packets\n", __FUNCTION__); + if (GMAC_Power_down == 0) // If Mac is not in powerdown + { + synopGMAC_disable_dma_tx(gmacdev); + synopGMAC_take_desc_ownership_tx(gmacdev); + + synopGMAC_enable_dma_tx(gmacdev); + // netif_wake_queue(netdev); + TR("%s::Transmission Resumed\n", __FUNCTION__); + } + } + /* Enable the interrrupt before returning from ISR*/ + synopGMAC_enable_interrupt(gmacdev, DmaIntEnable); + + return; +} + +int rt_hw_eth_init(void) +{ + u64 base_addr = Gmac_base; + struct synopGMACNetworkAdapter *synopGMACadapter; + static u8 mac_addr0[6] = DEFAULT_MAC_ADDRESS; + int index; + rt_sem_init(&sem_ack, "tx_ack", 1, RT_IPC_FLAG_FIFO); + rt_sem_init(&sem_lock, "eth_lock", 1, RT_IPC_FLAG_FIFO); + + memset(ð_dev, 0, sizeof(eth_dev)); + synopGMACadapter = (struct synopGMACNetworkAdapter *)plat_alloc_memory(sizeof(struct synopGMACNetworkAdapter)); + if (!synopGMACadapter) + { + rt_kprintf("Error in Memory Allocataion, Founction : %s \n", __FUNCTION__); + } + memset((char *)synopGMACadapter, 0, sizeof(struct synopGMACNetworkAdapter)); + + synopGMACadapter->synopGMACdev = NULL; + + synopGMACadapter->synopGMACdev = (synopGMACdevice *) plat_alloc_memory(sizeof(synopGMACdevice)); + if (!synopGMACadapter->synopGMACdev) + { + rt_kprintf("Error in Memory Allocataion, Founction : %s \n", __FUNCTION__); + } + + memset((char *)synopGMACadapter->synopGMACdev, 0, sizeof(synopGMACdevice)); + + /* + * Attach the device to MAC struct This will configure all the required base addresses + * such as Mac base, configuration base, phy base address(out of 32 possible phys) + * */ + synopGMAC_attach(synopGMACadapter->synopGMACdev, (regbase + MACBASE), regbase + DMABASE, DEFAULT_PHY_BASE, mac_addr0); + + init_phy(synopGMACadapter->synopGMACdev); + synopGMAC_reset(synopGMACadapter->synopGMACdev); + + /* MII setup */ + synopGMACadapter->mii.phy_id_mask = 0x1F; + synopGMACadapter->mii.reg_num_mask = 0x1F; + synopGMACadapter->mii.dev = synopGMACadapter; + synopGMACadapter->mii.mdio_read = mdio_read; + synopGMACadapter->mii.mdio_write = mdio_write; + synopGMACadapter->mii.phy_id = synopGMACadapter->synopGMACdev->PhyBase; + synopGMACadapter->mii.supports_gmii = mii_check_gmii_support(&synopGMACadapter->mii); + + eth_dev.iobase = base_addr; + eth_dev.name = "e0"; + eth_dev.priv = synopGMACadapter; + eth_dev.dev_addr[0] = mac_addr0[0]; + eth_dev.dev_addr[1] = mac_addr0[1]; + eth_dev.dev_addr[2] = mac_addr0[2]; + eth_dev.dev_addr[3] = mac_addr0[3]; + eth_dev.dev_addr[4] = mac_addr0[4]; + eth_dev.dev_addr[5] = mac_addr0[5]; + + eth_dev.parent.parent.type = RT_Device_Class_NetIf; + eth_dev.parent.parent.init = eth_init; + eth_dev.parent.parent.open = eth_open; + eth_dev.parent.parent.close = eth_close; + eth_dev.parent.parent.read = eth_read; + eth_dev.parent.parent.write = eth_write; + eth_dev.parent.parent.control = eth_control; + eth_dev.parent.parent.user_data = RT_NULL; + + eth_dev.parent.eth_tx = rt_eth_tx; + eth_dev.parent.eth_rx = rt_eth_rx; + + eth_device_init(&(eth_dev.parent), "e0"); + eth_device_linkchange(ð_dev.parent, RT_TRUE); //linkup the e0 for lwip to check + return 0; +} +INIT_COMPONENT_EXPORT(rt_hw_eth_init); diff --git a/bsp/ls2kdev/drivers/net/synopGMAC.h b/bsp/ls2kdev/drivers/net/synopGMAC.h new file mode 100644 index 0000000000000000000000000000000000000000..a1369ae00f3bacdf1d1034d05cd1ebef47264a37 --- /dev/null +++ b/bsp/ls2kdev/drivers/net/synopGMAC.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-08-24 chinesebear first version + */ + +#ifndef __SYNOPGMAC__H +#define __SYNOPGMAC__H + +#include "synopGMAC_network_interface.h" +#include "synopGMAC_Host.h" +#include "synopGMAC_Dev.h" +#include "synopGMAC_plat.h" +#include "mii.h" +#include "synopGMAC_types.h" + +int rt_hw_eth_init(void); + +#endif /*__SYNOPGMAC__H*/ diff --git a/bsp/ls2kdev/drivers/net/synopGMAC_Dev.c b/bsp/ls2kdev/drivers/net/synopGMAC_Dev.c new file mode 100644 index 0000000000000000000000000000000000000000..cdd4585670af311f2d2565914b41e290bead2cf9 --- /dev/null +++ b/bsp/ls2kdev/drivers/net/synopGMAC_Dev.c @@ -0,0 +1,3721 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-08-24 chinesebear first version + * 2020-08-10 lizhirui porting to ls2k + */ + +#include "synopGMAC_Dev.h" +#include +#include + +#define UNUSED 1 + +/** + * Function to set the MDC clock for mdio transactiona + * + * @param[in] pointer to device structure. + * @param[in] clk divider value. + * \return Reuturns 0 on success else return the error value. + */ +s32 synopGMAC_set_mdc_clk_div(synopGMACdevice *gmacdev,u32 clk_div_val) +{ + u32 orig_data; + orig_data = synopGMACReadReg(gmacdev -> MacBase,GmacGmiiAddr);//set the mdc clock to the user defined value + orig_data &= (~GmiiCsrClkMask); + orig_data |= clk_div_val; + synopGMACWriteReg(gmacdev -> MacBase,GmacGmiiAddr,orig_data); + return 0; +} + +/** + * Returns the current MDC divider value programmed in the ip. + * + * @param[in] pointer to device structure. + * @param[in] clk divider value. + * \return Returns the MDC divider value read. + */ +u32 synopGMAC_get_mdc_clk_div(synopGMACdevice *gmacdev) +{ + u32 data; + data = synopGMACReadReg(gmacdev->MacBase,GmacGmiiAddr); + data &= GmiiCsrClkMask; + return data; +} + + +/** + * Function to read the Phy register. The access to phy register + * is a slow process as the data is moved accross MDI/MDO interface + * @param[in] pointer to Register Base (It is the mac base in our case) . + * @param[in] PhyBase register is the index of one of supported 32 PHY devices. + * @param[in] Register offset is the index of one of the 32 phy register. + * @param[out] u16 data read from the respective phy register (only valid iff return value is 0). + * \return Returns 0 on success else return the error status. + */ +s32 synopGMAC_read_phy_reg(u64 RegBase,u32 PhyBase, u32 RegOffset, u16 * data ) +{ + u64 addr; + u32 loop_variable; + addr = ((PhyBase << GmiiDevShift) & GmiiDevMask) | ((RegOffset << GmiiRegShift) & GmiiRegMask) + | GmiiCsrClk3; //sw: add GmiiCsrClk + addr = addr | GmiiBusy ; //Gmii busy bit + + synopGMACWriteReg(RegBase,GmacGmiiAddr,addr); + //write the address from where the data to be read in GmiiGmiiAddr register of synopGMAC ip + + for(loop_variable = 0;loop_variable < DEFAULT_LOOP_VARIABLE;loop_variable++) + { + //Wait till the busy bit gets cleared within a certain amount of time + if (!(synopGMACReadReg(RegBase,GmacGmiiAddr) & GmiiBusy)) + { + break; + } + + plat_delay(DEFAULT_DELAY_VARIABLE); + } + + if(loop_variable < DEFAULT_LOOP_VARIABLE) + { + *data = (u16)(synopGMACReadReg(RegBase,GmacGmiiData) & 0xFFFF); + } + else + { + TR("Error::: PHY not responding Busy bit didnot get cleared !!!!!!\n"); + return -ESYNOPGMACPHYERR; + } + //sw +#if SYNOP_REG_DEBUG + printf("read phy reg: offset = 0x%x\tdata = 0x%x\n",RegOffset,*data); +#endif + + return -ESYNOPGMACNOERR; +} + +/** + * Function to write to the Phy register. The access to phy register + * is a slow process as the data is moved accross MDI/MDO interface + * @param[in] pointer to Register Base (It is the mac base in our case) . + * @param[in] PhyBase register is the index of one of supported 32 PHY devices. + * @param[in] Register offset is the index of one of the 32 phy register. + * @param[in] data to be written to the respective phy register. + * \return Returns 0 on success else return the error status. + */ +s32 synopGMAC_write_phy_reg(u64 RegBase, u32 PhyBase, u32 RegOffset, u16 data) +{ + u32 addr; + u32 loop_variable; + + synopGMACWriteReg(RegBase,GmacGmiiData,data); // write the data in to GmacGmiiData register of synopGMAC ip + + addr = ((PhyBase << GmiiDevShift) & GmiiDevMask) | ((RegOffset << GmiiRegShift) & GmiiRegMask) | GmiiWrite | GmiiCsrClk3; //sw: add GmiiCsrclk + + addr = addr | GmiiBusy ; //set Gmii clk to 20-35 Mhz and Gmii busy bit + + synopGMACWriteReg(RegBase,GmacGmiiAddr,addr); + for(loop_variable = 0;loop_variable < DEFAULT_LOOP_VARIABLE;loop_variable++) + { + if (!(synopGMACReadReg(RegBase,GmacGmiiAddr) & GmiiBusy)) + { + break; + } + + plat_delay(DEFAULT_DELAY_VARIABLE); + } + + if(loop_variable < DEFAULT_LOOP_VARIABLE) + { + return -ESYNOPGMACNOERR; + } + else + { + TR("Error::: PHY not responding Busy bit didnot get cleared !!!!!!\n"); + return -ESYNOPGMACPHYERR; + } +#if SYNOP_REG_DEBUG + printf("write phy reg: offset = 0x%x\tdata = 0x%x",RegOffset,data); +#endif +} + +/** + * Function to configure the phy in loopback mode. + * + * @param[in] pointer to synopGMACdevice. + * @param[in] enable or disable the loopback. + * \return 0 on success else return the error status. + * \note Don't get confused with mac loop-back synopGMAC_loopback_on(synopGMACdevice *) + * and synopGMAC_loopback_off(synopGMACdevice *) functions. + */ +#if UNUSED +s32 synopGMAC_phy_loopback(synopGMACdevice *gmacdev,bool loopback) +{ + s32 status = -ESYNOPGMACNOERR; + u16 temp; + + status = synopGMAC_read_phy_reg(gmacdev -> MacBase, gmacdev -> PhyBase,PHY_CONTROL_REG,&temp); + + if(loopback) + { + temp |= 0x4000; + } + else + { + temp = temp; + } + + status = synopGMAC_write_phy_reg(gmacdev -> MacBase,gmacdev -> PhyBase,PHY_CONTROL_REG,temp); + return status; +} + +#endif + +/** + * Function to read the GMAC IP Version and populates the same in device data structure. + * @param[in] pointer to synopGMACdevice. + * \return Always return 0. + */ + +s32 synopGMAC_read_version(synopGMACdevice *gmacdev) +{ + u32 data = 0; + data = synopGMACReadReg(gmacdev -> MacBase,GmacVersion); + gmacdev -> Version = data; + return 0; +} + + +/** + * Function to reset the GMAC core. + * This reests the DMA and GMAC core. After reset all the registers holds their respective reset value + * @param[in] pointer to synopGMACdevice. + * \return 0 on success else return the error status. + */ +s32 synopGMAC_reset(synopGMACdevice *gmacdev) +{ + u32 data = 0; + synopGMACWriteReg(gmacdev -> DmaBase,DmaBusMode,DmaResetOn); + plat_delay(DEFAULT_LOOP_VARIABLE); + data = synopGMACReadReg(gmacdev -> DmaBase,DmaBusMode); + TR("DATA after Reset = %08x\n",data); + + return 0; +} + + +/** + * Function to program DMA bus mode register. + * + * The Bus Mode register is programmed with the value given. The bits to be set are + * bit wise or'ed and sent as the second argument to this function. + * @param[in] pointer to synopGMACdevice. + * @param[in] the data to be programmed. + * \return 0 on success else return the error status. + */ +s32 synopGMAC_dma_bus_mode_init(synopGMACdevice *gmacdev,u32 init_value) +{ + synopGMACWriteReg(gmacdev -> DmaBase,DmaBusMode,init_value); + return 0; +} + +/** + * Function to program DMA Control register(Operation Mode Register 0x18). + * + * The Dma Control register is programmed with the value given. The bits to be set are + * bit wise or'ed and sent as the second argument to this function. + * @param[in] pointer to synopGMACdevice. + * @param[in] the data to be programmed. + * \return 0 on success else return the error status. + */ +s32 synopGMAC_dma_control_init(synopGMACdevice *gmacdev,u32 init_value) +{ + synopGMACWriteReg(gmacdev -> DmaBase,DmaControl,init_value); + return 0; +} + + +/*Gmac configuration functions*/ + +/** + * Enable the watchdog timer on the receiver. + * When enabled, Gmac enables Watchdog timer, and GMAC allows no more than + * 2048 bytes of data (10,240 if Jumbo frame enabled). + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_wd_enable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev -> MacBase,GmacConfig,GmacWatchdog); + return; +} +/** + * Disable the watchdog timer on the receiver. + * When disabled, Gmac disabled watchdog timer, and can receive frames up to + * 16,384 bytes. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ + +void synopGMAC_wd_disable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev -> MacBase,GmacConfig,GmacWatchdog); + return; +} + +/** + * Enables the Jabber frame support. + * When enabled, GMAC disabled the jabber timer, and can transfer 16,384 byte frames. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_jab_enable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev -> MacBase,GmacConfig,GmacJabber); + return; +} +/** + * Disables the Jabber frame support. + * When disabled, GMAC enables jabber timer. It cuts of transmitter if application + * sends more than 2048 bytes of data (10240 if Jumbo frame enabled). + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +#if UNUSED +void synopGMAC_jab_disable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev -> MacBase,GmacConfig,GmacJabber); + return; +} +#endif + +/** + * Enables Frame bursting (Only in Half Duplex Mode). + * When enabled, GMAC allows frame bursting in GMII Half Duplex mode. + * Reserved in 10/100 and Full-Duplex configurations. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_frame_burst_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev -> MacBase,GmacConfig,GmacFrameBurst); + return; +} +/** + * Disables Frame bursting. + * When Disabled, frame bursting is not supported. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +#if UNUSED +void synopGMAC_frame_burst_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev -> MacBase,GmacConfig,GmacFrameBurst); + return; +} +#endif + +/** + * Enable Jumbo frame support. + * When Enabled GMAC supports jumbo frames of 9018/9022(VLAN tagged). + * Giant frame error is not reported in receive frame status. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +#if UNUSED +void synopGMAC_jumbo_frame_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev -> MacBase,GmacConfig,GmacJumboFrame); + return; +} +#endif +/** + * Disable Jumbo frame support. + * When Disabled GMAC does not supports jumbo frames. + * Giant frame error is reported in receive frame status. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_jumbo_frame_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev -> MacBase,GmacConfig,GmacJumboFrame); + return; +} + +/** + * Disable Carrier sense. + * When Disabled GMAC ignores CRS signal during frame transmission + * in half duplex mode. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ + +#if UNUSED +void synopGMAC_disable_crs(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev -> MacBase,GmacConfig,GmacDisableCrs); + return; +} +#endif + + + +/** + * Selects the GMII port. + * When called GMII (1000Mbps) port is selected (programmable only in 10/100/1000 Mbps configuration). + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_select_gmii(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev -> MacBase,GmacConfig,GmacMiiGmii); + return; +} +/** + * Selects the MII port. + * When called MII (10/100Mbps) port is selected (programmable only in 10/100/1000 Mbps configuration). + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_select_mii(synopGMACdevice * gmacdev) +{ + synopGMACSetBits(gmacdev -> MacBase,GmacConfig,GmacMiiGmii); + return; +} + +/** + * Enables Receive Own bit (Only in Half Duplex Mode). + * When enaled GMAC receives all the packets given by phy while transmitting. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_rx_own_enable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev -> MacBase,GmacConfig,GmacRxOwn); + return; +} +/** + * Disables Receive Own bit (Only in Half Duplex Mode). + * When enaled GMAC disables the reception of frames when gmii_txen_o is asserted. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +#if UNUSED +void synopGMAC_rx_own_disable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev -> MacBase,GmacConfig,GmacRxOwn); + return; +} +#endif + +/** + * Sets the GMAC in loopback mode. + * When on GMAC operates in loop-back mode at GMII/MII. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + * \note (G)MII Receive clock is required for loopback to work properly, as transmit clock is + * not looped back internally. + */ +void synopGMAC_loopback_on(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev -> MacBase,GmacConfig,GmacLoopback); + return; +} +/** + * Sets the GMAC in Normal mode. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_loopback_off(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev -> MacBase,GmacConfig,GmacLoopback); + return; +} + +/** + * Sets the GMAC core in Full-Duplex mode. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_set_full_duplex(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev -> MacBase,GmacConfig,GmacDuplex); + return; +} +/** + * Sets the GMAC core in Half-Duplex mode. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_set_half_duplex(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev -> MacBase,GmacConfig,GmacDuplex); + return; +} + +/** + * GMAC tries retransmission (Only in Half Duplex mode). + * If collision occurs on the GMII/MII, GMAC attempt retries based on the + * back off limit configured. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + * \note This function is tightly coupled with synopGMAC_back_off_limit(synopGMACdev *, u32). + */ +void synopGMAC_retry_enable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev -> MacBase,GmacConfig,GmacRetry); + return; +} +/** + * GMAC tries only one transmission (Only in Half Duplex mode). + * If collision occurs on the GMII/MII, GMAC will ignore the current frami + * transmission and report a frame abort with excessive collision in tranmit frame status. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +#if UNUSED +void synopGMAC_retry_disable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev -> MacBase,GmacConfig,GmacRetry); + return; +} +#endif + +/** + * GMAC strips the Pad/FCS field of incoming frames. + * This is true only if the length field value is less than or equal to + * 1500 bytes. All received frames with length field greater than or equal to + * 1501 bytes are passed to the application without stripping the Pad/FCS field. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +#if UNUSED +void synopGMAC_pad_crc_strip_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev -> MacBase,GmacConfig,GmacPadCrcStrip); + return; +} +#endif +/** + * GMAC doesnot strips the Pad/FCS field of incoming frames. + * GMAC will pass all the incoming frames to Host unmodified. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_pad_crc_strip_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev -> MacBase,GmacConfig,GmacPadCrcStrip); + u32 status = synopGMACReadReg(gmacdev -> MacBase,GmacConfig); + DEBUG_MES("strips status : %u\n", status & GmacPadCrcStrip); + return; +} +/** + * GMAC programmed with the back off limit value. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + * \note This function is tightly coupled with synopGMAC_retry_enable(synopGMACdevice * gmacdev) + */ +void synopGMAC_back_off_limit(synopGMACdevice *gmacdev,u32 value) +{ + u32 data; + data = synopGMACReadReg(gmacdev -> MacBase,GmacConfig); + data &= (~GmacBackoffLimit); + data |= value; + synopGMACWriteReg(gmacdev -> MacBase,GmacConfig,data); + return; +} + +/** + * Enables the Deferral check in GMAC (Only in Half Duplex mode) + * GMAC issues a Frame Abort Status, along with the excessive deferral error bit set in the + * transmit frame status when transmit state machine is deferred for more than + * - 24,288 bit times in 10/100Mbps mode + * - 155,680 bit times in 1000Mbps mode or Jumbo frame mode in 10/100Mbps operation. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + * \note Deferral begins when transmitter is ready to transmit, but is prevented because of + * an active CRS (carrier sense) + */ +#if UNUSED +void synopGMAC_deferral_check_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev -> MacBase,GmacConfig,GmacDeferralCheck); + return; +} +#endif +/** + * Disables the Deferral check in GMAC (Only in Half Duplex mode). + * GMAC defers until the CRS signal goes inactive. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_deferral_check_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev -> MacBase,GmacConfig,GmacDeferralCheck); + return; +} +/** + * Enable the reception of frames on GMII/MII. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_rx_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev -> MacBase,GmacConfig,GmacRx); + return; +} +/** + * Disable the reception of frames on GMII/MII. + * GMAC receive state machine is disabled after completion of reception of current frame. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +#if UNUSED +void synopGMAC_rx_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev -> MacBase,GmacConfig,GmacRx); + return; +} +#endif +/** + * Enable the transmission of frames on GMII/MII. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_tx_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev -> MacBase,GmacConfig,GmacTx); + return; +} +/** + * Disable the transmission of frames on GMII/MII. + * GMAC transmit state machine is disabled after completion of transmission of current frame. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +#if UNUSED +void synopGMAC_tx_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev -> MacBase,GmacConfig,GmacTx); + return; +} +#endif + + +/*Receive frame filter configuration functions*/ + +/** + * Disables reception of all the frames to application. + * GMAC passes only those received frames to application which + * pass SA/DA address filtering. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_frame_filter_enable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev -> MacBase,GmacFrameFilter,GmacFilter); + return; +} + + /** + * Enables reception of all the frames to application. + * GMAC passes all the frames received to application irrespective of whether they + * pass SA/DA address filtering or not. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_frame_filter_disable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev -> MacBase,GmacFrameFilter,GmacFilter); + return; +} + +/** + * Populates the Hash High register with the data supplied. + * This function is called when the Hash filtering is to be enabled. + * @param[in] pointer to synopGMACdevice. + * @param[in] data to be written to hash table high register. + * \return void. + */ +#if UNUSED +void synopGMAC_write_hash_table_high(synopGMACdevice *gmacdev,u32 data) +{ + synopGMACWriteReg(gmacdev -> MacBase,GmacHashHigh,data); + return; +} +#endif + +/** + * Populates the Hash Low register with the data supplied. + * This function is called when the Hash filtering is to be enabled. + * @param[in] pointer to synopGMACdevice. + * @param[in] data to be written to hash table low register. + * \return void. + */ +#if UNUSED +void synopGMAC_write_hash_table_low(synopGMACdevice *gmacdev,u32 data) +{ + synopGMACWriteReg(gmacdev -> MacBase,GmacHashLow,data); + return; +} +#endif + +/** + * Enables Hash or Perfect filter (only if Hash filter is enabled in H/W). + * Only frames matching either perfect filtering or Hash Filtering as per HMC and HUC + * configuration are sent to application. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +#if UNUSED +void synopGMAC_hash_perfect_filter_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev -> MacBase,GmacFrameFilter,GmacHashPerfectFilter); + return; +} +#endif + +/** + * Enables only Hash(only if Hash filter is enabled in H/W). + * Only frames matching Hash Filtering as per HMC and HUC + * configuration are sent to application. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +#if UNUSED +void synopGMAC_Hash_filter_only_enable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev -> MacBase,GmacFrameFilter,GmacHashPerfectFilter); + return; +} +#endif + +/** + * Enables Source address filtering. + * When enabled source address filtering is performed. Only frames matching SA filtering are passed to application with + * SAMatch bit of RxStatus is set. GMAC drops failed frames. + * @param[in] pointer to synopGMACdevice. + * \return void. + * \note This function is overriden by synopGMAC_frame_filter_disable(synopGMACdevice *) + */ +#if UNUSED +void synopGMAC_src_addr_filter_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev -> MacBase,GmacFrameFilter,GmacSrcAddrFilter); + return; +} +#endif +/** + * Disables Source address filtering. + * When disabled GMAC forwards the received frames with updated SAMatch bit in RxStatus. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_src_addr_filter_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev -> MacBase,GmacFrameFilter,GmacSrcAddrFilter); + return; +} +/** + * Enables Inverse Destination address filtering. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +#if UNUSED +void synopGMAC_dst_addr_filter_inverse(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev -> MacBase,GmacFrameFilter,GmacDestAddrFilterInv); + return; +} +#endif +/** + * Enables the normal Destination address filtering. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_dst_addr_filter_normal(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev -> MacBase,GmacFrameFilter,GmacDestAddrFilterInv); + return; +} + +/** + * Enables forwarding of control frames. + * When set forwards all the control frames (incl. unicast and multicast PAUSE frames). + * @param[in] pointer to synopGMACdevice. + * \return void. + * \note Depends on RFE of FlowControlRegister[2] + */ +void synopGMAC_set_pass_control(synopGMACdevice *gmacdev,u32 passcontrol) +{ + u32 data; + data = synopGMACReadReg(gmacdev -> MacBase,GmacFrameFilter); + data &= (~GmacPassControl); + data |= passcontrol; + synopGMACWriteReg(gmacdev -> MacBase,GmacFrameFilter,data); + return; +} + +/** + * Enables Broadcast frames. + * When enabled Address filtering module passes all incoming broadcast frames. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_broadcast_enable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev -> MacBase,GmacFrameFilter,GmacBroadcast); + return; +} +/** + * Disable Broadcast frames. + * When disabled Address filtering module filters all incoming broadcast frames. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +#if UNUSED +void synopGMAC_broadcast_disable(synopGMACdevice * gmacdev) +{ + synopGMACSetBits(gmacdev->MacBase, GmacFrameFilter, GmacBroadcast); + return; +} +#endif + +/** + * Enables Multicast frames. + * When enabled all multicast frames are passed. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +#if UNUSED +void synopGMAC_multicast_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev -> MacBase,GmacFrameFilter,GmacMulticastFilter); + return; +} +#endif +/** + * Disable Multicast frames. + * When disabled multicast frame filtering depends on HMC bit. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_multicast_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev -> MacBase,GmacFrameFilter,GmacMulticastFilter); + return; +} + +/** + * Enables multicast hash filtering. + * When enabled GMAC performs teh destination address filtering according to the hash table. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +#if UNUSED +void synopGMAC_multicast_hash_filter_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev -> MacBase,GmacFrameFilter,GmacMcastHashFilter); + return; +} +#endif +/** + * Disables multicast hash filtering. + * When disabled GMAC performs perfect destination address filtering for multicast frames, it compares + * DA field with the value programmed in DA register. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_multicast_hash_filter_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev -> MacBase,GmacFrameFilter,GmacMcastHashFilter); + return; +} + +/** + * Enables promiscous mode. + * When enabled Address filter modules pass all incoming frames regardless of their Destination + * and source addresses. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +#if UNUSED +void synopGMAC_promisc_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev -> MacBase,GmacFrameFilter,GmacPromiscuousMode); + return; +} +#endif +/** + * Clears promiscous mode. + * When called the GMAC falls back to normal operation from promiscous mode. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_promisc_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev -> MacBase,GmacFrameFilter,GmacPromiscuousMode); + return; +} + +/** + * Enables unicast hash filtering. + * When enabled GMAC performs the destination address filtering of unicast frames according to the hash table. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +#if UNUSED +void synopGMAC_unicast_hash_filter_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev -> MacBase,GmacFrameFilter,GmacUcastHashFilter); + return; +} +#endif +/** + * Disables multicast hash filtering. + * When disabled GMAC performs perfect destination address filtering for unicast frames, it compares + * DA field with the value programmed in DA register. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_unicast_hash_filter_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev -> MacBase,GmacFrameFilter,GmacUcastHashFilter); + return; +} + +/*Flow control configuration functions*/ + +/** + * Enables detection of pause frames with stations unicast address. + * When enabled GMAC detects the pause frames with stations unicast address in addition to the + * detection of pause frames with unique multicast address. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +#if UNUSED +void synopGMAC_unicast_pause_frame_detect_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev -> MacBase,GmacFlowControl,GmacUnicastPauseFrame); + return; +} +#endif +/** + * Disables detection of pause frames with stations unicast address. + * When disabled GMAC only detects with the unique multicast address (802.3x). + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_unicast_pause_frame_detect_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev -> MacBase,GmacFlowControl,GmacUnicastPauseFrame); + return; +} +/** + * Rx flow control enable. + * When Enabled GMAC will decode the rx pause frame and disable the tx for a specified time. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_rx_flow_control_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev -> MacBase,GmacFlowControl,GmacRxFlowControl); + return; +} +/** + * Rx flow control disable. + * When disabled GMAC will not decode pause frame. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_rx_flow_control_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev -> MacBase,GmacFlowControl,GmacRxFlowControl); + return; +} +/** + * Tx flow control enable. + * When Enabled + * - In full duplex GMAC enables flow control operation to transmit pause frames. + * - In Half duplex GMAC enables the back pressure operation + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_tx_flow_control_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev -> MacBase,GmacFlowControl,GmacTxFlowControl); + return; +} + +/** + * Tx flow control disable. + * When Disabled + * - In full duplex GMAC will not transmit any pause frames. + * - In Half duplex GMAC disables the back pressure feature. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_tx_flow_control_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev -> MacBase,GmacFlowControl,GmacTxFlowControl); + return; +} + +/** + * Initiate Flowcontrol operation. + * When Set + * - In full duplex GMAC initiates pause control frame. + * - In Half duplex GMAC initiates back pressure function. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +#if UNUSED +void synopGMAC_tx_activate_flow_control(synopGMACdevice *gmacdev) +{ + //In case of full duplex check for this bit to b'0. if it is read as b'1 indicates that + //control frame transmission is in progress. + if(gmacdev -> Speed == FULLDUPLEX) + { + if(!synopGMACCheckBits(gmacdev -> MacBase,GmacFlowControl,GmacFlowControlBackPressure)) + { + synopGMACSetBits(gmacdev -> MacBase,GmacFlowControl,GmacFlowControlBackPressure); + } + } + else//if half duplex mode + { + + synopGMACSetBits(gmacdev -> MacBase,GmacFlowControl,GmacFlowControlBackPressure); + } + + return; +} +#endif + +/** + * stops Flowcontrol operation. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +#if UNUSED +void synopGMAC_tx_deactivate_flow_control(synopGMACdevice *gmacdev) +{ + //In full duplex this bit is automatically cleared after transmitting a pause control frame. + if(gmacdev->Speed == HALFDUPLEX) + { + synopGMACSetBits(gmacdev -> MacBase,GmacFlowControl,GmacFlowControlBackPressure); + } + + return; +} +#endif + +/** + * This enables the pause frame generation after programming the appropriate registers. + * presently activation is set at 3k and deactivation set at 4k. These may have to tweaked + * if found any issues + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_pause_control(synopGMACdevice *gmacdev) +{ + u32 omr_reg; + u32 mac_flow_control_reg; + omr_reg = synopGMACReadReg(gmacdev -> DmaBase,DmaControl); + omr_reg |= DmaRxFlowCtrlAct4K | DmaRxFlowCtrlDeact5K | DmaEnHwFlowCtrl; + synopGMACWriteReg(gmacdev -> DmaBase,DmaControl,omr_reg); + + mac_flow_control_reg = synopGMACReadReg(gmacdev -> MacBase,GmacFlowControl); + mac_flow_control_reg |= GmacRxFlowControl | GmacTxFlowControl | 0xFFFF0000; + synopGMACWriteReg(gmacdev -> MacBase,GmacFlowControl,mac_flow_control_reg); + + return; +} + +/** + * Example mac initialization sequence. + * This function calls the initialization routines to initialize the GMAC register. + * One can change the functions invoked here to have different configuration as per the requirement + * @param[in] pointer to synopGMACdevice. + * \return Returns 0 on success. + */ +s32 synopGMAC_mac_init(synopGMACdevice *gmacdev) +{ + u32 PHYreg; + + if(gmacdev->DuplexMode == FULLDUPLEX) + { + TR("\n===phy FULLDUPLEX MODE\n"); //sw: debug + synopGMAC_wd_enable(gmacdev); + synopGMAC_jab_enable(gmacdev); + synopGMAC_frame_burst_enable(gmacdev); + synopGMAC_jumbo_frame_disable(gmacdev); + synopGMAC_rx_own_enable(gmacdev); +#if SYNOP_LOOPBACK_MODE + synopGMAC_loopback_on(gmacdev); +#else + synopGMAC_loopback_off(gmacdev); +#endif + synopGMAC_set_full_duplex(gmacdev); //1 + synopGMAC_retry_enable(gmacdev); + synopGMAC_pad_crc_strip_disable(gmacdev); + synopGMAC_back_off_limit(gmacdev,GmacBackoffLimit0); + synopGMAC_deferral_check_disable(gmacdev); + + synopGMAC_tx_enable(gmacdev); //according to Tang Dan's commitment + synopGMAC_rx_enable(gmacdev); + + synopGMACSetBits(gmacdev -> DmaBase,DmaControl,DmaStoreAndForward);//3 + synopGMACSetBits(gmacdev -> DmaBase,DmaControl,DmaFwdErrorFrames); + + if(gmacdev -> Speed == SPEED1000) + { + synopGMAC_select_gmii(gmacdev); + } + else + { + synopGMAC_select_mii(gmacdev); + + if(gmacdev -> Speed == SPEED100) + { + synopGMACSetBits(gmacdev -> MacBase,GmacConfig,GmacFESpeed100); + } + else + { + synopGMACSetBits(gmacdev -> MacBase,GmacConfig,GmacFESpeed10); + } + } + + + /*Frame Filter Configuration*/ + //synopGMAC_frame_filter_enable(gmacdev); //2 + synopGMAC_frame_filter_disable(gmacdev); //2 + synopGMAC_set_pass_control(gmacdev,GmacPassControl0); + synopGMAC_broadcast_enable(gmacdev); + synopGMAC_src_addr_filter_disable(gmacdev); + synopGMAC_multicast_disable(gmacdev); + synopGMAC_dst_addr_filter_normal(gmacdev); //scl + //synopGMAC_dst_addr_filter_inverse(gmacdev); + synopGMAC_multicast_hash_filter_disable(gmacdev); + synopGMAC_promisc_disable(gmacdev); + synopGMAC_unicast_hash_filter_disable(gmacdev); + + /*Flow Control Configuration*/ + synopGMAC_unicast_pause_frame_detect_disable(gmacdev); + synopGMAC_rx_flow_control_enable(gmacdev); + synopGMAC_tx_flow_control_enable(gmacdev); + } + else//for Half Duplex configuration + { + + TR("\n===phy HALFDUPLEX MODE\n"); //sw: debug + synopGMAC_wd_enable(gmacdev ); + synopGMAC_jab_enable(gmacdev); + synopGMAC_frame_burst_enable(gmacdev); + synopGMAC_jumbo_frame_disable(gmacdev); + synopGMAC_rx_own_enable(gmacdev); +#if SYNOP_LOOPBACK_MODE + synopGMAC_loopback_on(gmacdev); +#else + synopGMAC_loopback_off(gmacdev); +#endif + synopGMAC_set_half_duplex(gmacdev); + synopGMAC_retry_enable(gmacdev); + synopGMAC_pad_crc_strip_disable(gmacdev); + synopGMAC_back_off_limit(gmacdev,GmacBackoffLimit0); + synopGMAC_deferral_check_disable(gmacdev); + +//sw: set efe & tsf + synopGMACSetBits(gmacdev -> DmaBase,DmaControl,DmaStoreAndForward); + synopGMACSetBits(gmacdev -> DmaBase,DmaControl,DmaFwdErrorFrames); +//sw: put it in the end + synopGMAC_tx_enable(gmacdev); + synopGMAC_rx_enable(gmacdev); + + + if(gmacdev -> Speed == SPEED1000) + synopGMAC_select_gmii(gmacdev); + else{ + synopGMAC_select_mii(gmacdev); + + if(gmacdev -> Speed == SPEED100) + { + synopGMACSetBits(gmacdev -> MacBase,GmacConfig,GmacFESpeed100); + } + else + { + synopGMACSetBits(gmacdev -> MacBase,GmacConfig,GmacFESpeed10); + } + } + +// synopGMACSetBits(gmacdev->MacBase, GmacConfig, GmacDisableCrs); +// synopGMAC_select_gmii(gmacdev); + + /*Frame Filter Configuration*/ + synopGMAC_frame_filter_enable(gmacdev); +// synopGMAC_frame_filter_disable(gmacdev); + + synopGMAC_set_pass_control(gmacdev,GmacPassControl0); + synopGMAC_broadcast_enable(gmacdev); + synopGMAC_src_addr_filter_disable(gmacdev); + synopGMAC_multicast_disable(gmacdev); + synopGMAC_dst_addr_filter_normal(gmacdev); + synopGMAC_multicast_hash_filter_disable(gmacdev); + + synopGMAC_promisc_disable(gmacdev); +// synopGMAC_promisc_enable(gmacdev); + synopGMAC_unicast_hash_filter_disable(gmacdev); + +//sw: loopback mode +// synopGMAC_loopback_on(gmacdev); + + /*Flow Control Configuration*/ + synopGMAC_unicast_pause_frame_detect_disable(gmacdev); + synopGMAC_rx_flow_control_disable(gmacdev); + synopGMAC_tx_flow_control_disable(gmacdev); + + /*To set PHY register to enable CRS on Transmit*/ + } + return 0; +} + + +/** + * Sets the Mac address in to GMAC register. + * This function sets the MAC address to the MAC register in question. + * @param[in] pointer to synopGMACdevice to populate mac dma and phy addresses. + * @param[in] Register offset for Mac address high + * @param[in] Register offset for Mac address low + * @param[in] buffer containing mac address to be programmed. + * \return 0 upon success. Error code upon failure. + */ +s32 synopGMAC_set_mac_addr(synopGMACdevice *gmacdev,u32 MacHigh,u32 MacLow,u8 *MacAddr) +{ + u32 data; + + data = (MacAddr[5] << 8) | MacAddr[4]; + synopGMACWriteReg(gmacdev -> MacBase,MacHigh,data); + data = (MacAddr[3] << 24) | (MacAddr[2] << 16) | (MacAddr[1] << 8) | MacAddr[0]; + synopGMACWriteReg(gmacdev -> MacBase,MacLow,data); + + return 0; +} + + +/** + * Get the Mac address in to the address specified. + * The mac register contents are read and written to buffer passed. + * @param[in] pointer to synopGMACdevice to populate mac dma and phy addresses. + * @param[in] Register offset for Mac address high + * @param[in] Register offset for Mac address low + * @param[out] buffer containing the device mac address. + * \return 0 upon success. Error code upon failure. + */ +s32 synopGMAC_get_mac_addr(synopGMACdevice *gmacdev,u32 MacHigh,u32 MacLow,u8 *MacAddr) +{ + u32 data; + + data = synopGMACReadReg(gmacdev -> MacBase,MacHigh); + MacAddr[5] = (data >> 8) & 0xff; + MacAddr[4] = (data) & 0xff; + + data = synopGMACReadReg(gmacdev -> MacBase,MacLow); + MacAddr[3] = (data >> 24) & 0xff; + MacAddr[2] = (data >> 16) & 0xff; + MacAddr[1] = (data >> 8 ) & 0xff; + MacAddr[0] = (data ) & 0xff; + +// rt_kprintf("MacAddr = 0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\n",MacAddr[0],MacAddr[1],MacAddr[2],MacAddr[3],MacAddr[4],MacAddr[5]); + + return 0; +} + + +/** + * Attaches the synopGMAC device structure to the hardware. + * Device structure is populated with MAC/DMA and PHY base addresses. + * @param[in] pointer to synopGMACdevice to populate mac dma and phy addresses. + * @param[in] GMAC IP mac base address. + * @param[in] GMAC IP dma base address. + * @param[in] GMAC IP phy base address. + * \return 0 upon success. Error code upon failure. + * \note This is important function. No kernel api provided by Synopsys + */ + +s32 synopGMAC_attach(synopGMACdevice *gmacdev,u64 macBase,u64 dmaBase,u64 phyBase,u8 *mac_addr) +{ + /*Make sure the Device data strucure is cleared before we proceed further*/ + rt_memset((void *)gmacdev,0,sizeof(synopGMACdevice)); + /*Populate the mac and dma base addresses*/ + gmacdev -> MacBase = macBase; + gmacdev -> DmaBase = dmaBase; + gmacdev -> PhyBase = phyBase; +// rt_kprintf("gmacdev->DmaBase = 0x%x\n", gmacdev->DmaBase); +// rt_kprintf("dmaBase = 0x%x\n", dmaBase); + { + int i,j; + u16 data; + + for (i = phyBase,j = 0;j < 32;i = (i + 1) & 0x1f,j++) + { + synopGMAC_read_phy_reg(gmacdev -> MacBase,i,2,&data); + + if(data != 0 && data != 0xffff) + { + break; + } + + synopGMAC_read_phy_reg(gmacdev -> MacBase,i,3,&data); + + if(data != 0 && data != 0xffff) + { + break; + } + } + + if(j == 32) + { + rt_kprintf("phy_detect: can't find PHY!\n"); + } + + gmacdev -> PhyBase = i; + } + +// synopGMAC_get_mac_addr(gmacdev, GmacAddr0High, GmacAddr0Low, mac_addr); + + /* Program/flash in the station/IP's Mac address */ + synopGMAC_set_mac_addr(gmacdev,GmacAddr0High,GmacAddr0Low,mac_addr); + + return 0; +} + + + + +/** + * Initialize the rx descriptors for ring or chain mode operation. + * - Status field is initialized to 0. + * - EndOfRing set for the last descriptor. + * - buffer1 and buffer2 set to 0 for ring mode of operation. (note) + * - data1 and data2 set to 0. (note) + * @param[in] pointer to DmaDesc structure. + * @param[in] whether end of ring + * \return void. + * \note Initialization of the buffer1, buffer2, data1,data2 and status are not done here. This only initializes whether one wants to use this descriptor + * in chain mode or ring mode. For chain mode of operation the buffer2 and data2 are programmed before calling this function. + */ +void synopGMAC_rx_desc_init_ring(DmaDesc *desc,bool last_ring_desc) +{ + desc -> length = last_ring_desc ? RxDescEndOfRing : 0; + desc -> status = 0; + desc -> buffer1 = 0; + desc -> buffer2 = 0; + desc -> data1 = 0; + desc -> data2 = 0; + //desc -> dummy1 = 0; + //desc -> dummy2 = 0; + + return; +} +void synopGMAC_rx_desc_recycle(DmaDesc *desc,bool last_ring_desc) +{ + desc -> status = DescOwnByDma; + desc -> length = last_ring_desc ? RxDescEndOfRing : 0; + //desc->buffer1 = 0; + //desc->buffer2 = 0; + //desc->data1 = 0; + //desc->data2 = 0; + //desc -> dummy1 = 0; + //desc -> dummy2 = 0; + + return; +} +/** + * Initialize the tx descriptors for ring or chain mode operation. + * - Status field is initialized to 0. + * - EndOfRing set for the last descriptor. + * - buffer1 and buffer2 set to 0 for ring mode of operation. (note) + * - data1 and data2 set to 0. (note) + * @param[in] pointer to DmaDesc structure. + * @param[in] whether end of ring + * \return void. + * \note Initialization of the buffer1, buffer2, data1,data2 and status are not done here. This only initializes whether one wants to use this descriptor + * in chain mode or ring mode. For chain mode of operation the buffer2 and data2 are programmed before calling this function. + */ +void synopGMAC_tx_desc_init_ring(DmaDesc *desc, bool last_ring_desc) +{ + #ifdef ENH_DESC + desc -> status = last_ring_desc ? TxDescEndOfRing : 0; + desc -> length = 0; + #else + desc -> length = last_ring_desc ? TxDescEndOfRing : 0; + desc -> status = 0; + #endif +//sw + desc -> buffer1 = 0; + desc -> buffer2 = 0; + desc -> data1 = 0; + desc -> data2 = 0; + //desc -> dummy1 = 0; + //desc -> dummy2 = 0; + return; +} + +/** + * Initialize the rx descriptors for chain mode of operation. + * - Status field is initialized to 0. + * - EndOfRing set for the last descriptor. + * - buffer1 and buffer2 set to 0. + * - data1 and data2 set to 0. + * @param[in] pointer to DmaDesc structure. + * @param[in] whether end of ring + * \return void. + */ + +void synopGMAC_rx_desc_init_chain(DmaDesc * desc) +{ + desc -> status = 0; + desc -> length = RxDescChain; + desc -> buffer1 = 0; + desc -> data1 = 0; + return; +} +/** + * Initialize the rx descriptors for chain mode of operation. + * - Status field is initialized to 0. + * - EndOfRing set for the last descriptor. + * - buffer1 and buffer2 set to 0. + * - data1 and data2 set to 0. + * @param[in] pointer to DmaDesc structure. + * @param[in] whether end of ring + * \return void. + */ +void synopGMAC_tx_desc_init_chain(DmaDesc * desc) +{ + #ifdef ENH_DESC + desc -> status = TxDescChain; + desc -> length = 0; + #else + desc -> length = TxDescChain; + #endif + desc -> buffer1 = 0; + desc -> data1 = 0; + return; +} + +s32 synopGMAC_init_tx_rx_desc_queue(synopGMACdevice *gmacdev) +{ + s32 i; + + for(i = 0;i < gmacdev -> TxDescCount;i++) + { + synopGMAC_tx_desc_init_ring(gmacdev -> TxDesc + i, i == gmacdev -> TxDescCount - 1); + } + + TR("At line %d\n",__LINE__); + + for(i = 0; i < gmacdev -> RxDescCount; i++) + { + synopGMAC_rx_desc_init_ring(gmacdev -> RxDesc + i, i == gmacdev -> RxDescCount - 1); + } + + gmacdev -> TxNext = 0; + gmacdev -> TxBusy = 0; + gmacdev -> RxNext = 0; + gmacdev -> RxBusy = 0; + + return -ESYNOPGMACNOERR; +} +/** + * Programs the DmaRxBaseAddress with the Rx descriptor base address. + * Rx Descriptor's base address is available in the gmacdev structure. This function progrms the + * Dma Rx Base address with the starting address of the descriptor ring or chain. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_init_rx_desc_base(synopGMACdevice *gmacdev) +{ + DEBUG_MES("gmacdev->RxDescDma = %08x\n",gmacdev -> RxDescDma); + synopGMACWriteReg(gmacdev -> DmaBase,DmaRxBaseAddr,(u32)gmacdev -> RxDescDma); + return; +} + +/** + * Programs the DmaTxBaseAddress with the Tx descriptor base address. + * Tx Descriptor's base address is available in the gmacdev structure. This function progrms the + * Dma Tx Base address with the starting address of the descriptor ring or chain. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_init_tx_desc_base(synopGMACdevice *gmacdev) +{ + synopGMACWriteReg(gmacdev -> DmaBase,DmaTxBaseAddr,(u32)gmacdev -> TxDescDma); + return; +} + + +/** + * Makes the Dma as owner for this descriptor. + * This function sets the own bit of status field of the DMA descriptor, + * indicating the DMA is the owner for this descriptor. + * @param[in] pointer to DmaDesc structure. + * \return returns void. + */ +void synopGMAC_set_owner_dma(DmaDesc *desc) +{ + desc -> status |= DescOwnByDma; +} + +/** + * set tx descriptor to indicate SOF. + * This Descriptor contains the start of ethernet frame. + * @param[in] pointer to DmaDesc structure. + * \return returns void. + */ +void synopGMAC_set_desc_sof(DmaDesc *desc) +{ + #ifdef ENH_DESC + desc -> status |= DescTxFirst;//ENH_DESC + #else + desc -> length |= DescTxFirst; + #endif +} + +/** + * set tx descriptor to indicate EOF. + * This descriptor contains the End of ethernet frame. + * @param[in] pointer to DmaDesc structure. + * \return returns void. + */ +void synopGMAC_set_desc_eof(DmaDesc *desc) +{ + #ifdef ENH_DESC + desc -> status |= DescTxLast;//ENH_DESC + #else + desc -> length |= DescTxLast; + #endif +} + + +/** + * checks whether this descriptor contains start of frame. + * This function is to check whether the descriptor's data buffer + * contains a fresh ethernet frame? + * @param[in] pointer to DmaDesc structure. + * \return returns true if SOF in current descriptor, else returns fail. + */ +bool synopGMAC_is_sof_in_rx_desc(DmaDesc *desc) +{ + return ((desc -> status & DescRxFirst) == DescRxFirst); +} + +/** + * checks whether this descriptor contains end of frame. + * This function is to check whether the descriptor's data buffer + * contains end of ethernet frame? + * @param[in] pointer to DmaDesc structure. + * \return returns true if SOF in current descriptor, else returns fail. + */ +bool synopGMAC_is_eof_in_rx_desc(DmaDesc *desc) +{ + return ((desc -> status & DescRxLast) == DescRxLast); +} + +/** + * checks whether destination address filter failed in the rx frame. + * @param[in] pointer to DmaDesc structure. + * \return returns true if Failed, false if not. + */ +bool synopGMAC_is_da_filter_failed(DmaDesc *desc) +{ + return ((desc -> status & DescDAFilterFail) == DescDAFilterFail); +} + +/** + * checks whether source address filter failed in the rx frame. + * @param[in] pointer to DmaDesc structure. + * \return returns true if Failed, false if not. + */ +bool synopGMAC_is_sa_filter_failed(DmaDesc *desc) +{ + return ((desc -> status & DescSAFilterFail) == DescSAFilterFail); +} + +/** + * Checks whether the descriptor is owned by DMA. + * If descriptor is owned by DMA then the OWN bit is set to 1. This API is same for both ring and chain mode. + * @param[in] pointer to DmaDesc structure. + * \return returns true if Dma owns descriptor and false if not. + */ +bool synopGMAC_is_desc_owned_by_dma(DmaDesc *desc) +{ + return ((desc -> status & DescOwnByDma) == DescOwnByDma); +} + +/** + * returns the byte length of received frame including CRC. + * This returns the no of bytes received in the received ethernet frame including CRC(FCS). + * @param[in] pointer to DmaDesc structure. + * \return returns the length of received frame lengths in bytes. + */ +u32 synopGMAC_get_rx_desc_frame_length(u32 status) +{ + return ((status & DescFrameLengthMask) >> DescFrameLengthShift); +} + +/** + * Checks whether the descriptor is valid + * if no errors such as CRC/Receive Error/Watchdog Timeout/Late collision/Giant Frame/Overflow/Descriptor + * error the descritpor is said to be a valid descriptor. + * @param[in] pointer to DmaDesc structure. + * \return True if desc valid. false if error. + */ +bool synopGMAC_is_desc_valid(u32 status) +{ + return ((status & DescError) == 0); +} + +/** + * Checks whether the descriptor is empty. + * If the buffer1 and buffer2 lengths are zero in ring mode descriptor is empty. + * In chain mode buffer2 length is 0 but buffer2 itself contains the next descriptor address. + * @param[in] pointer to DmaDesc structure. + * \return returns true if descriptor is empty, false if not empty. + */ +bool synopGMAC_is_desc_empty(DmaDesc *desc) +{ + //if both the buffer1 length and buffer2 length are zero desc is empty + return(((desc -> length & DescSize1Mask) == 0) && ((desc -> length & DescSize2Mask) == 0)); +} + + +/** + * Checks whether the rx descriptor is valid. + * if rx descripor is not in error and complete frame is available in the same descriptor + * @param[in] pointer to DmaDesc structure. + * \return returns true if no error and first and last desc bits are set, otherwise it returns false. + */ +bool synopGMAC_is_rx_desc_valid(u32 status) +{ + return ((status & DescError) == 0) && ((status & DescRxFirst) == DescRxFirst) && ((status & DescRxLast) == DescRxLast); +} + +/** + * Checks whether the tx is aborted due to collisions. + * @param[in] pointer to DmaDesc structure. + * \return returns true if collisions, else returns false. + */ +bool synopGMAC_is_tx_aborted(u32 status) +{ + return (((status & DescTxLateCollision) == DescTxLateCollision) | ((status & DescTxExcCollisions) == DescTxExcCollisions)); + +} + +/** + * Checks whether the tx carrier error. + * @param[in] pointer to DmaDesc structure. + * \return returns true if carrier error occured, else returns falser. + */ +bool synopGMAC_is_tx_carrier_error(u32 status) +{ + return (((status & DescTxLostCarrier) == DescTxLostCarrier) | ((status & DescTxNoCarrier) == DescTxNoCarrier)); +} + + +/** + * Gives the transmission collision count. + * returns the transmission collision count indicating number of collisions occured before the frame was transmitted. + * Make sure to check excessive collision didnot happen to ensure the count is valid. + * @param[in] pointer to DmaDesc structure. + * \return returns the count value of collision. + */ +u32 synopGMAC_get_tx_collision_count(u32 status) +{ + return ((status & DescTxCollMask) >> DescTxCollShift); +} +u32 synopGMAC_is_exc_tx_collisions(u32 status) +{ + return ((status & DescTxExcCollisions) == DescTxExcCollisions); +} + + +/** + * Check for damaged frame due to overflow or collision. + * Retruns true if rx frame was damaged due to buffer overflow in MTL or late collision in half duplex mode. + * @param[in] pointer to DmaDesc structure. + * \return returns true if error else returns false. + */ +bool synopGMAC_is_rx_frame_damaged(u32 status) +{ +//bool synopGMAC_dma_rx_collisions(u32 status) + return (((status & DescRxDamaged) == DescRxDamaged) | ((status & DescRxCollision) == DescRxCollision)); +} + +/** + * Check for damaged frame due to collision. + * Retruns true if rx frame was damaged due to late collision in half duplex mode. + * @param[in] pointer to DmaDesc structure. + * \return returns true if error else returns false. + */ +bool synopGMAC_is_rx_frame_collision(u32 status) +{ +//bool synopGMAC_dma_rx_collisions(u32 status) + return ((status & DescRxCollision) == DescRxCollision); +} + +/** + * Check for receive CRC error. + * Retruns true if rx frame CRC error occured. + * @param[in] pointer to DmaDesc structure. + * \return returns true if error else returns false. + */ +bool synopGMAC_is_rx_crc(u32 status) +{ +//u32 synopGMAC_dma_rx_crc(u32 status) + return ((status & DescRxCrc) == DescRxCrc); +} + +/** + * Indicates rx frame has non integer multiple of bytes. (odd nibbles). + * Retruns true if dribbling error in rx frame. + * @param[in] pointer to DmaDesc structure. + * \return returns true if error else returns false. + */ +bool synopGMAC_is_frame_dribbling_errors(u32 status) +{ +//u32 synopGMAC_dma_rx_frame_errors(u32 status) + return ((status & DescRxDribbling) == DescRxDribbling); +} + +/** + * Indicates error in rx frame length. + * Retruns true if received frame length doesnot match with the length field + * @param[in] pointer to DmaDesc structure. + * \return returns true if error else returns false. + */ +bool synopGMAC_is_rx_frame_length_errors(u32 status) +{ +//u32 synopGMAC_dma_rx_length_errors(u32 status) + return((status & DescRxLengthError) == DescRxLengthError); +} + +/** + * Checks whether this rx descriptor is last rx descriptor. + * This returns true if it is last descriptor either in ring mode or in chain mode. + * @param[in] pointer to devic structure. + * @param[in] pointer to DmaDesc structure. + * \return returns true if it is last descriptor, false if not. + * \note This function should not be called before initializing the descriptor using synopGMAC_desc_init(). + */ +bool synopGMAC_is_last_rx_desc(synopGMACdevice *gmacdev,DmaDesc *desc) +{ +//bool synopGMAC_is_last_desc(DmaDesc *desc) + return (((desc -> length & RxDescEndOfRing) == RxDescEndOfRing) || ((u64)gmacdev -> RxDesc == desc -> data2)); +} + +/** + * Checks whether this tx descriptor is last tx descriptor. + * This returns true if it is last descriptor either in ring mode or in chain mode. + * @param[in] pointer to devic structure. + * @param[in] pointer to DmaDesc structure. + * \return returns true if it is last descriptor, false if not. + * \note This function should not be called before initializing the descriptor using synopGMAC_desc_init(). + */ +bool synopGMAC_is_last_tx_desc(synopGMACdevice *gmacdev,DmaDesc *desc) +{ +//bool synopGMAC_is_last_desc(DmaDesc *desc) +#ifdef ENH_DESC + return (((desc->status & TxDescEndOfRing) == TxDescEndOfRing) || ((u64)gmacdev -> TxDesc == desc -> data2)); +#else + return (((desc->length & TxDescEndOfRing) == TxDescEndOfRing) || ((u64)gmacdev -> TxDesc == desc -> data2)); +#endif +} + +/** + * Checks whether this rx descriptor is in chain mode. + * This returns true if it is this descriptor is in chain mode. + * @param[in] pointer to DmaDesc structure. + * \return returns true if chain mode is set, false if not. + */ +bool synopGMAC_is_rx_desc_chained(DmaDesc *desc) +{ + return((desc -> length & RxDescChain) == RxDescChain); +} + +/** + * Checks whether this tx descriptor is in chain mode. + * This returns true if it is this descriptor is in chain mode. + * @param[in] pointer to DmaDesc structure. + * \return returns true if chain mode is set, false if not. + */ +bool synopGMAC_is_tx_desc_chained(DmaDesc *desc) +{ +#ifdef ENH_DESC + return((desc -> status & TxDescChain) == TxDescChain); +#else + return((desc -> length & TxDescChain) == TxDescChain); +#endif +} + +/** + * Driver Api to get the descriptor field information. + * This returns the status, dma-able address of buffer1, the length of buffer1, virtual address of buffer1 + * dma-able address of buffer2, length of buffer2, virtural adddress of buffer2. + * @param[in] pointer to DmaDesc structure. + * @param[out] pointer to status field fo descriptor. + * @param[out] dma-able address of buffer1. + * @param[out] length of buffer1. + * @param[out] virtual address of buffer1. + * @param[out] dma-able address of buffer2. + * @param[out] length of buffer2. + * @param[out] virtual address of buffer2. + * \return returns void. + */ +void synopGMAC_get_desc_data(DmaDesc *desc,u32 *Status,u32 *Buffer1,u32 *Length1,u64 *Data1,u32 *Buffer2,u32 *Length2,u64 *Data2) +{ + + if(Status != 0) + { + *Status = desc -> status; + } + + if(Buffer1 != 0) + { + *Buffer1 = desc -> buffer1; + } + + if(Length1 != 0) + { + *Length1 = (desc -> length & DescSize1Mask) >> DescSize1Shift; + } + + if(Data1 != 0) + { + *Data1 = desc -> data1; + } + + if(Buffer2 != 0) + { + *Buffer2 = desc -> buffer2; + } + + if(Length2 != 0) + { + *Length2 = (desc -> length & DescSize2Mask) >> DescSize2Shift; + } + + if(Data2 != 0) + { + *Data2 = desc -> data2; + } + + return; +} + +#ifdef ENH_DESC_8W +/** + * This function is defined two times. Once when the code is compiled for ENHANCED DESCRIPTOR SUPPORT and Once for Normal descriptor + * Get the index and address of Tx desc. + * This api is same for both ring mode and chain mode. + * This function tracks the tx descriptor the DMA just closed after the transmission of data from this descriptor is + * over. This returns the descriptor fields to the caller. + * @param[in] pointer to synopGMACdevice. + * @param[out] status field of the descriptor. + * @param[out] Dma-able buffer1 pointer. + * @param[out] length of buffer1 (Max is 2048). + * @param[out] virtual pointer for buffer1. + * @param[out] Dma-able buffer2 pointer. + * @param[out] length of buffer2 (Max is 2048). + * @param[out] virtual pointer for buffer2. + * @param[out] u32 data indicating whether the descriptor is in ring mode or chain mode. + * \return returns present tx descriptor index on success. Negative value if error. + */ +s32 synopGMAC_get_tx_qptr(synopGMACdevice * gmacdev, u32 * Status, u32 * Buffer1, u32 * Length1, u64 * Data1, u32 * Buffer2, u32 * Length2, u64 * Data2, + u32 * Ext_Status, u32 * Time_Stamp_High, u32 * Time_Stamp_Low) +{ + u32 txover = gmacdev->TxBusy; + DmaDesc * txdesc = gmacdev->TxBusyDesc; + + if(synopGMAC_is_desc_owned_by_dma(txdesc)) + return -1; + if(synopGMAC_is_desc_empty(txdesc)) + return -1; + + (gmacdev->BusyTxDesc)--; //busy tx descriptor is reduced by one as it will be handed over to Processor now + + if(Status != 0) + *Status = txdesc->status; + + if(Ext_Status != 0) + *Ext_Status = txdesc->extstatus; + if(Time_Stamp_High != 0) + *Time_Stamp_High = txdesc->timestamphigh; + if(Time_Stamp_Low != 0) + *Time_Stamp_High = txdesc->timestamplow; + + if(Buffer1 != 0) + *Buffer1 = txdesc->buffer1; + if(Length1 != 0) + *Length1 = (txdesc->length & DescSize1Mask) >> DescSize1Shift; + if(Data1 != 0) + *Data1 = txdesc->data1; + + if(Buffer2 != 0) + *Buffer2 = txdesc->buffer2; + if(Length2 != 0) + *Length2 = (txdesc->length & DescSize2Mask) >> DescSize2Shift; + if(Data1 != 0) + *Data2 = txdesc->data2; + + gmacdev->TxBusy = synopGMAC_is_last_tx_desc(gmacdev,txdesc) ? 0 : txover + 1; + + if(synopGMAC_is_tx_desc_chained(txdesc)){ + gmacdev->TxBusyDesc = (DmaDesc *)txdesc->data2; + synopGMAC_tx_desc_init_chain(txdesc); + } + else{ + gmacdev->TxBusyDesc = synopGMAC_is_last_tx_desc(gmacdev,txdesc) ? gmacdev->TxDesc : (txdesc + 1); + synopGMAC_tx_desc_init_ring(txdesc, synopGMAC_is_last_tx_desc(gmacdev,txdesc)); + } + TR("%02d %08x %08x %08x %08x %08x %08x %08x\n",txover,(u32)txdesc,txdesc->status,txdesc->length,txdesc->buffer1,txdesc->buffer2,txdesc->data1,txdesc->data2); + + return txover; +} +#else + +/** + * Get the index and address of Tx desc. + * This api is same for both ring mode and chain mode. + * This function tracks the tx descriptor the DMA just closed after the transmission of data from this descriptor is + * over. This returns the descriptor fields to the caller. + * @param[in] pointer to synopGMACdevice. + * @param[out] status field of the descriptor. + * @param[out] Dma-able buffer1 pointer. + * @param[out] length of buffer1 (Max is 2048). + * @param[out] virtual pointer for buffer1. + * @param[out] Dma-able buffer2 pointer. + * @param[out] length of buffer2 (Max is 2048). + * @param[out] virtual pointer for buffer2. + * @param[out] u32 data indicating whether the descriptor is in ring mode or chain mode. + * \return returns present tx descriptor index on success. Negative value if error. + */ +s32 synopGMAC_get_tx_qptr(synopGMACdevice * gmacdev, u32 * Status, u32 * Buffer1, u32 * Length1, u64 * Data1, u32 * Buffer2, u32 * Length2, u64 * Data2 ) +{ + u32 txover = gmacdev->TxBusy; + DmaDesc * txdesc = gmacdev->TxBusyDesc; + int i; +//sw: dbg + //pci_sync_cache(0, (vm_offset_t)txdesc, 64, SYNC_R); + //pci_sync_cache(0, (vm_offset_t)txdesc, 64, SYNC_W); +#if SYNOP_TX_DEBUG + printf("Cache sync before get a used tx dma desc!\n"); + printf("\n==%02d %08x %08x %08x %08x %08x %08x %08x\n",txover,(u32)txdesc,txdesc->status,txdesc->length,txdesc->buffer1,txdesc->buffer2,txdesc->data1,txdesc->data2); +#endif + if(synopGMAC_is_desc_owned_by_dma(txdesc)) + { + return -1; + } +// gmacdev->TxBusy = synopGMAC_is_last_tx_desc(gmacdev,txdesc) ? 0 : txover + 1; +// gmacdev->TxBusyDesc = synopGMAC_is_last_tx_desc(gmacdev,txdesc) ? gmacdev->TxDesc : (txdesc + 1); + if(synopGMAC_is_desc_empty(txdesc)) + { + return -1; + } + (gmacdev->BusyTxDesc)--; //busy tx descriptor is reduced by one as it will be handed over to Processor now + + if(Status != 0) + *Status = txdesc->status; + + if(Buffer1 != 0) + *Buffer1 = txdesc->buffer1; + if(Length1 != 0) + *Length1 = (txdesc->length & DescSize1Mask) >> DescSize1Shift; + if(Data1 != 0) + *Data1 = txdesc->data1; + + if(Buffer2 != 0) + *Buffer2 = txdesc->buffer2; + if(Length2 != 0) + *Length2 = (txdesc->length & DescSize2Mask) >> DescSize2Shift; + if(Data1 != 0) + *Data2 = txdesc->data2; + + gmacdev->TxBusy = synopGMAC_is_last_tx_desc(gmacdev,txdesc) ? 0 : txover + 1; + + if(synopGMAC_is_tx_desc_chained(txdesc)) + { + gmacdev->TxBusyDesc = (DmaDesc *)txdesc->data2; + synopGMAC_tx_desc_init_chain(txdesc); + } + else + { + gmacdev->TxBusyDesc = synopGMAC_is_last_tx_desc(gmacdev,txdesc) ? gmacdev->TxDesc : (txdesc + 1); + synopGMAC_tx_desc_init_ring(txdesc, synopGMAC_is_last_tx_desc(gmacdev,txdesc)); + } + //printf("%02d %08x %08x %08x %08x %08x %08x %08x\n",txover,(u32)txdesc,txdesc->status,txdesc->length,txdesc->buffer1,txdesc->buffer2,txdesc->data1,txdesc->data2); + //pci_sync_cache(0, (vm_offset_t)txdesc, 64, SYNC_W); +#if SYNOP_TX_DEBUG + printf("Cache sync after re-init a tx dma desc!\n"); +#endif + + return txover; +} + +#endif +/** + * Populate the tx desc structure with the buffer address. + * Once the driver has a packet ready to be transmitted, this function is called with the + * valid dma-able buffer addresses and their lengths. This function populates the descriptor + * and make the DMA the owner for the descriptor. This function also controls whether Checksum + * offloading to be done in hardware or not. + * This api is same for both ring mode and chain mode. + * @param[in] pointer to synopGMACdevice. + * @param[in] Dma-able buffer1 pointer. + * @param[in] length of buffer1 (Max is 2048). + * @param[in] virtual pointer for buffer1. + * @param[in] Dma-able buffer2 pointer. + * @param[in] length of buffer2 (Max is 2048). + * @param[in] virtual pointer for buffer2. + * @param[in] u32 data indicating whether the descriptor is in ring mode or chain mode. + * @param[in] u32 indicating whether the checksum offloading in HW/SW. + * \return returns present tx descriptor index on success. Negative value if error. + */ +u32 len; +s32 synopGMAC_set_tx_qptr(synopGMACdevice * gmacdev, u32 Buffer1, u32 Length1, u64 Data1, u32 Buffer2, u32 Length2, u64 Data2,u32 offload_needed,u32 * index, DmaDesc * Dpr) +{ + u32 txnext = gmacdev->TxNext; + DmaDesc * txdesc = gmacdev->TxNextDesc; + + *index = txnext; + Dpr = txdesc; + + if(!synopGMAC_is_desc_empty(txdesc)) + { + TR("set tx qptr: desc empty!\n"); + return -1; + } + + (gmacdev->BusyTxDesc)++; //busy tx descriptor is reduced by one as it will be handed over to Processor now + + if(synopGMAC_is_tx_desc_chained(txdesc)) + { + txdesc->length |= ((Length1 <status |= (DescTxFirst | DescTxLast | DescTxIntEnable); //ENH_DESC + #else + txdesc->length |= (DescTxFirst | DescTxLast | DescTxIntEnable); //Its always assumed that complete data will fit in to one descriptor + #endif + + txdesc->buffer1 = Buffer1; + txdesc->data1 = Data1; + + if(offload_needed) + { + /* + Make sure that the OS you are running supports the IP and TCP checkusm offloaidng, + before calling any of the functions given below. + */ + synopGMAC_tx_checksum_offload_ipv4hdr(gmacdev, txdesc); + synopGMAC_tx_checksum_offload_tcponly(gmacdev, txdesc); +// synopGMAC_tx_checksum_offload_tcp_pseudo(gmacdev, txdesc); + } + #ifdef ENH_DESC + txdesc->status |= DescOwnByDma;//ENH_DESC + #else + txdesc->status = DescOwnByDma; + #endif + + gmacdev->TxNext = synopGMAC_is_last_tx_desc(gmacdev,txdesc) ? 0 : txnext + 1; + gmacdev->TxNextDesc = (DmaDesc *)txdesc->data2; + } + else + { +// printf("synopGMAC_set_tx_qptr:in ring mode\n"); + txdesc->length |= (((Length1 <status |= (DescTxFirst | DescTxLast | DescTxIntEnable); //ENH_DESC + #else + txdesc->length |= (DescTxFirst | DescTxLast | DescTxIntEnable); //Its always assumed that complete data will fit in to one descriptor + #endif + + txdesc->buffer1 = Buffer1; + txdesc->data1 = Data1; + + txdesc->buffer2 = Buffer2; + txdesc->data2 = Data2; + + if(offload_needed) + { + /* + Make sure that the OS you are running supports the IP and TCP checkusm offloaidng, + before calling any of the functions given below. + */ +//sw: i am not sure about the checksum.so i omit it in the outside + synopGMAC_tx_checksum_offload_ipv4hdr(gmacdev, txdesc); + synopGMAC_tx_checksum_offload_tcponly(gmacdev, txdesc); +// synopGMAC_tx_checksum_offload_tcp_pseudo(gmacdev, txdesc); + } + #ifdef ENH_DESC + txdesc->status |= DescOwnByDma;//ENH_DESC + #else +// printf("synopGMAC_set_tx_qptr:give the tx descroptor to dma\n"); + txdesc->status = DescOwnByDma; + #endif + + gmacdev->TxNext = synopGMAC_is_last_tx_desc(gmacdev,txdesc) ? 0 : txnext + 1; + gmacdev->TxNextDesc = synopGMAC_is_last_tx_desc(gmacdev,txdesc) ? gmacdev->TxDesc : (txdesc + 1); + } + + +#if SYNOP_TX_DEBUG + printf("%02d %08x %08x %08x %08x %08x %08x %08x\n",txnext,(u32)txdesc,txdesc->status,txdesc->length,txdesc->buffer1,txdesc->buffer2,txdesc->data1,txdesc->data2); +#endif + //pci_sync_cache(0, (vm_offset_t)txdesc, 64, SYNC_W); +#if SYNOP_TX_DEBUG + printf("Cache sync to set a tx desc!\n"); +#endif + //pci_sync_cache(0, (vm_offset_t)(txdesc->data1), 32, SYNC_W); +#if SYNOP_TX_DEBUG + //printf("Cache sync for data in the buf of the tx desc!\n"); +#endif + return txnext; +} +#ifdef ENH_DESC_8W +/** + * Prepares the descriptor to receive packets. + * The descriptor is allocated with the valid buffer addresses (sk_buff address) and the length fields + * and handed over to DMA by setting the ownership. After successful return from this function the + * descriptor is added to the receive descriptor pool/queue. + * This api is same for both ring mode and chain mode. + * @param[in] pointer to synopGMACdevice. + * @param[in] Dma-able buffer1 pointer. + * @param[in] length of buffer1 (Max is 2048). + * @param[in] Dma-able buffer2 pointer. + * @param[in] length of buffer2 (Max is 2048). + * @param[in] u32 data indicating whether the descriptor is in ring mode or chain mode. + * \return returns present rx descriptor index on success. Negative value if error. + */ +// dma_addr RX_BUF_SIZE skb +s32 synopGMAC_set_rx_qptr(synopGMACdevice * gmacdev, u32 Buffer1, u32 Length1, u64 Data1, u32 Buffer2, u32 Length2, u64 Data2) +{ + u32 rxnext = gmacdev->RxNext; + DmaDesc * rxdesc = gmacdev->RxNextDesc; + + if(!synopGMAC_is_desc_empty(rxdesc)) + return -1; + + if(synopGMAC_is_rx_desc_chained(rxdesc)){ + rxdesc->length |= ((Length1 <buffer1 = Buffer1; + rxdesc->data1 = Data1; + + rxdesc->extstatus = 0; + rxdesc->reserved1 = 0; + rxdesc->timestamplow = 0; + rxdesc->timestamphigh = 0; + + if((rxnext % MODULO_INTERRUPT) !=0) + rxdesc->length |= RxDisIntCompl; + + rxdesc->status = DescOwnByDma; + + gmacdev->RxNext = synopGMAC_is_last_rx_desc(gmacdev,rxdesc) ? 0 : rxnext + 1; + gmacdev->RxNextDesc = (DmaDesc *)rxdesc->data2; + } + else{ + rxdesc->length |= (((Length1 <buffer1 = Buffer1; + rxdesc->data1 = Data1; + + rxdesc->extstatus = 0; + rxdesc->reserved1 = 0; + rxdesc->timestamplow = 0; + rxdesc->timestamphigh = 0; + + rxdesc->buffer2 = Buffer2; + rxdesc->data2 = Data2; + + if((rxnext % MODULO_INTERRUPT) !=0) + rxdesc->length |= RxDisIntCompl; + + rxdesc->status = DescOwnByDma; + gmacdev->RxNext = synopGMAC_is_last_rx_desc(gmacdev,rxdesc) ? 0 : rxnext + 1; + gmacdev->RxNextDesc = synopGMAC_is_last_rx_desc(gmacdev,rxdesc) ? gmacdev->RxDesc : (rxdesc + 1); + } +#if SYNOP_RX_DEBUG + TR("%02d %08x %08x %08x %08x %08x %08x %08x %08x %08x\n",rxnext,(u32)rxdesc,rxdesc->status,rxdesc->length,rxdesc->buffer1,rxdesc->buffer2,rxdesc->data1,rxdesc->data2,rxdesc->dummy1,rxdesc->dummy2); +#endif + + (gmacdev->BusyRxDesc)++; //One descriptor will be given to Hardware. So busy count incremented by one + //pci_sync_cache(0, (vm_offset_t)rxdesc,64, SYNC_W); + return rxnext; +} + +#else +/** + * Prepares the descriptor to receive packets. + * The descriptor is allocated with the valid buffer addresses (sk_buff address) and the length fields + * and handed over to DMA by setting the ownership. After successful return from this function the + * descriptor is added to the receive descriptor pool/queue. + * This api is same for both ring mode and chain mode. + * @param[in] pointer to synopGMACdevice. + * @param[in] Dma-able buffer1 pointer. + * @param[in] length of buffer1 (Max is 2048). + * @param[in] Dma-able buffer2 pointer. + * @param[in] length of buffer2 (Max is 2048). + * @param[in] u32 data indicating whether the descriptor is in ring mode or chain mode. + * \return returns present rx descriptor index on success. Negative value if error. + */ +s32 synopGMAC_set_rx_qptr(synopGMACdevice * gmacdev, u32 Buffer1, u32 Length1, u64 Data1, u32 Buffer2, u32 Length2, u64 Data2) +{ + u32 rxnext = gmacdev->RxNext; + DmaDesc * rxdesc = gmacdev->RxNextDesc; + + if(!synopGMAC_is_desc_empty(rxdesc)) + return -1; + + if(synopGMAC_is_rx_desc_chained(rxdesc)){ + rxdesc->length |= ((Length1 <buffer1 = Buffer1; + rxdesc->data1 = Data1; + + if((rxnext % MODULO_INTERRUPT) !=0) + rxdesc->length |= RxDisIntCompl; + + rxdesc->status = DescOwnByDma; + + gmacdev->RxNext = synopGMAC_is_last_rx_desc(gmacdev,rxdesc) ? 0 : rxnext + 1; + gmacdev->RxNextDesc = (DmaDesc *)rxdesc->data2; + } + else{ + rxdesc->length |= (((Length1 <buffer1 = Buffer1; + rxdesc->data1 = Data1; + + rxdesc->buffer2 = Buffer2; + rxdesc->data2 = Data2; + + if((rxnext % MODULO_INTERRUPT) !=0) + rxdesc->length |= RxDisIntCompl; + + rxdesc->status = DescOwnByDma; + + gmacdev->RxNext = synopGMAC_is_last_rx_desc(gmacdev,rxdesc) ? 0 : rxnext + 1; + gmacdev->RxNextDesc = synopGMAC_is_last_rx_desc(gmacdev,rxdesc) ? gmacdev->RxDesc : (rxdesc + 1); + } +#if SYNOP_RX_DEBUG + TR("%02d %08x %08x %08x %08x %08x %08x %08x\n",rxnext,(u32)rxdesc,rxdesc->status,rxdesc->length,rxdesc->buffer1,rxdesc->buffer2,rxdesc->data1,rxdesc->data2); +#endif + (gmacdev->BusyRxDesc)++; //One descriptor will be given to Hardware. So busy count incremented by one + + return rxnext; +} + +s32 synopGMAC_set_rx_qptr_init(synopGMACdevice * gmacdev, u32 Buffer1, u32 Length1, u64 Data1, u32 Buffer2, u32 Length2, u64 Data2) +{ + u32 rxnext = gmacdev->RxNext; + DmaDesc * rxdesc = gmacdev->RxNextDesc; + +/* sw + if(synopGMAC_is_desc_owned_by_dma(rxdesc)) + return -1; +*/ + + if(!synopGMAC_is_desc_empty(rxdesc)) + return -1; + + if(synopGMAC_is_rx_desc_chained(rxdesc)){ + rxdesc->length |= ((Length1 <buffer1 = Buffer1; + rxdesc->data1 = Data1; + + if((rxnext % MODULO_INTERRUPT) !=0) + rxdesc->length |= RxDisIntCompl; + + rxdesc->status = DescOwnByDma; + rxdesc->status = 0; + + gmacdev->RxNext = synopGMAC_is_last_rx_desc(gmacdev,rxdesc) ? 0 : rxnext + 1; + gmacdev->RxNextDesc = (DmaDesc *)rxdesc->data2; + } + else{ + rxdesc->length |= (((Length1 <buffer1 = Buffer1; + rxdesc->data1 = Data1; + + rxdesc->buffer2 = Buffer2; + rxdesc->data2 = Data2; + + if((rxnext % MODULO_INTERRUPT) !=0) + rxdesc->length |= RxDisIntCompl; + + rxdesc->status = DescOwnByDma; + rxdesc->status = 0; + + gmacdev->RxNext = synopGMAC_is_last_rx_desc(gmacdev,rxdesc) ? 0 : rxnext + 1; + gmacdev->RxNextDesc = synopGMAC_is_last_rx_desc(gmacdev,rxdesc) ? gmacdev->RxDesc : (rxdesc + 1); + } + TR("%02d %08x %08x %08x %08x %08x %08x %08x\n",rxnext,(u32)rxdesc,rxdesc->status,rxdesc->length,rxdesc->buffer1,rxdesc->buffer2,rxdesc->data1,rxdesc->data2); + (gmacdev->BusyRxDesc)++; //One descriptor will be given to Hardware. So busy count incremented by one + return rxnext; +} +#endif +#ifdef ENH_DESC_8W +/** + * This function is defined two times. Once when the code is compiled for ENHANCED DESCRIPTOR SUPPORT and Once for Normal descriptor + * Get back the descriptor from DMA after data has been received. + * When the DMA indicates that the data is received (interrupt is generated), this function should be + * called to get the descriptor and hence the data buffers received. With successful return from this + * function caller gets the descriptor fields for processing. check the parameters to understand the + * fields returned.` + * @param[in] pointer to synopGMACdevice. + * @param[out] pointer to hold the status of DMA. + * @param[out] Dma-able buffer1 pointer. + * @param[out] pointer to hold length of buffer1 (Max is 2048). + * @param[out] virtual pointer for buffer1. + * @param[out] Dma-able buffer2 pointer. + * @param[out] pointer to hold length of buffer2 (Max is 2048). + * @param[out] virtual pointer for buffer2. + * \return returns present rx descriptor index on success. Negative value if error. + */ +s32 synopGMAC_get_rx_qptr(synopGMACdevice * gmacdev, u32 * Status, u32 * Buffer1, u32 * Length1, u64 * Data1, u32 * Buffer2, u32 * Length2, u64 * Data2, + u32 * Ext_Status, u32 * Time_Stamp_High, u32 * Time_Stamp_Low) +{ + u32 rxnext = gmacdev->RxBusy; // index of descriptor the DMA just completed. May be useful when data + //is spread over multiple buffers/descriptors + DmaDesc * rxdesc = gmacdev->RxBusyDesc; + if(synopGMAC_is_desc_owned_by_dma(rxdesc)) + return -1; + if(synopGMAC_is_desc_empty(rxdesc)) + return -1; + + + if(Status != 0) + *Status = rxdesc->status;// send the status of this descriptor + + if(Ext_Status != 0) + *Ext_Status = rxdesc->extstatus; + if(Time_Stamp_High != 0) + *Time_Stamp_High = rxdesc->timestamphigh; + if(Time_Stamp_Low != 0) + *Time_Stamp_Low = rxdesc->timestamplow; + + if(Length1 != 0) + *Length1 = (rxdesc->length & DescSize1Mask) >> DescSize1Shift; + if(Buffer1 != 0) + *Buffer1 = rxdesc->buffer1; + if(Data1 != 0) + *Data1 = rxdesc->data1; + + if(Length2 != 0) + *Length2 = (rxdesc->length & DescSize2Mask) >> DescSize2Shift; + if(Buffer2 != 0) + *Buffer2 = rxdesc->buffer2; + if(Data1 != 0) + *Data2 = rxdesc->data2; + + gmacdev->RxBusy = synopGMAC_is_last_rx_desc(gmacdev,rxdesc) ? 0 : rxnext + 1; + + if(synopGMAC_is_rx_desc_chained(rxdesc)){ + gmacdev->RxBusyDesc = (DmaDesc *)rxdesc->data2; + synopGMAC_rx_desc_init_chain(rxdesc); + //synopGMAC_desc_init_chain(rxdesc, synopGMAC_is_last_rx_desc(gmacdev,rxdesc),0,0); + } + else{ + gmacdev->RxBusyDesc = synopGMAC_is_last_rx_desc(gmacdev,rxdesc) ? gmacdev->RxDesc : (rxdesc + 1); + synopGMAC_rx_desc_init_ring(rxdesc, synopGMAC_is_last_rx_desc(gmacdev,rxdesc)); + } + TR("%02d %08x %08x %08x %08x %08x %08x %08x\n",rxnext,(u32)rxdesc,rxdesc->status,rxdesc->length,rxdesc->buffer1,rxdesc->buffer2,rxdesc->data1,rxdesc->data2); + (gmacdev->BusyRxDesc)--; //busy tx descriptor is reduced by one as it will be handed over to Processor now + return(rxnext); + +} +#else + +/** + * Get back the descriptor from DMA after data has been received. + * When the DMA indicates that the data is received (interrupt is generated), this function should be + * called to get the descriptor and hence the data buffers received. With successful return from this + * function caller gets the descriptor fields for processing. check the parameters to understand the + * fields returned.` + * @param[in] pointer to synopGMACdevice. + * @param[out] pointer to hold the status of DMA. + * @param[out] Dma-able buffer1 pointer. + * @param[out] pointer to hold length of buffer1 (Max is 2048). + * @param[out] virtual pointer for buffer1. + * @param[out] Dma-able buffer2 pointer. + * @param[out] pointer to hold length of buffer2 (Max is 2048). + * @param[out] virtual pointer for buffer2. + * \return returns present rx descriptor index on success. Negative value if error. + */ +s32 synopGMAC_get_rx_qptr(synopGMACdevice * gmacdev, u32 * Status, u32 * Buffer1, u32 * Length1, u64 * Data1, u32 * Buffer2, u32 * Length2, u64 * Data2) +{ + u32 rxnext = gmacdev->RxBusy; // index of descriptor the DMA just completed. May be useful when data + //is spread over multiple buffers/descriptors + DmaDesc * rxdesc = gmacdev->RxBusyDesc; + u32 len; + if(synopGMAC_is_desc_owned_by_dma(rxdesc)) + { + DEBUG_MES("synopGMAC_get_rx_qptr:DMA descriptor is owned by GMAC!\n"); + return -1; + } + + if(synopGMAC_is_desc_empty(rxdesc)) + { + DEBUG_MES("synopGMAC_get_rx_qptr:rx desc is empty!\n"); + return -1; + } + + if(Status != 0) + *Status = rxdesc->status;// send the status of this descriptor + + if(Length1 != 0) + *Length1 = (rxdesc->length & DescSize1Mask) >> DescSize1Shift; + if(Buffer1 != 0) + *Buffer1 = rxdesc->buffer1; + if(Data1 != 0) + *Data1 = rxdesc->data1; + if(Length2 != 0) + *Length2 = (rxdesc->length & DescSize2Mask) >> DescSize2Shift; + if(Buffer2 != 0) + *Buffer2 = rxdesc->buffer2; + if(Data1 != 0) + *Data2 = rxdesc->data2; + + len = synopGMAC_get_rx_desc_frame_length(*Status); + DEBUG_MES("Cache sync for data buffer in rx dma desc: length = 0x%x\n",len); + gmacdev->RxBusy = synopGMAC_is_last_rx_desc(gmacdev,rxdesc) ? 0 : rxnext + 1; + if(synopGMAC_is_rx_desc_chained(rxdesc)){ + gmacdev->RxBusyDesc = (DmaDesc *)rxdesc->data2; + synopGMAC_rx_desc_init_chain(rxdesc); + } + else{ + gmacdev->RxBusyDesc = synopGMAC_is_last_rx_desc(gmacdev,rxdesc) ? gmacdev->RxDesc : (rxdesc + 1); +//sw: raw data +#if SYNOP_RX_DEBUG + DEBUG_MES("%02d %08x %08x %08x %08x %08x %08x %08x\n",rxnext,(u32)rxdesc,rxdesc->status,rxdesc->length,rxdesc->buffer1,rxdesc->buffer2,rxdesc->data1,rxdesc->data2); +#endif + synopGMAC_rx_desc_init_ring(rxdesc, synopGMAC_is_last_rx_desc(gmacdev,rxdesc)); + } +#if SYNOP_RX_DEBUG + DEBUG_MES("%02d %08x %08x %08x %08x %08x %08x %08x\n",rxnext,(u32)rxdesc,rxdesc->status,rxdesc->length,rxdesc->buffer1,rxdesc->buffer2,rxdesc->data1,rxdesc->data2); +#endif + + (gmacdev->BusyRxDesc)--; //This returns one descriptor to processor. So busy count will be decremented by one + return(rxnext); + +} + +#endif + +/** + * Clears all the pending interrupts. + * If the Dma status register is read then all the interrupts gets cleared + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_clear_interrupt(synopGMACdevice *gmacdev) +{ + u32 data; + data = synopGMACReadReg(gmacdev->DmaBase, DmaStatus); + TR("DMA status reg = 0x%x before cleared!\n",data); + synopGMACWriteReg(gmacdev->DmaBase, DmaStatus ,data); + // plat_delay(DEFAULT_LOOP_VARIABLE); +// data = synopGMACReadReg(gmacdev->DmaBase, DmaStatus); + TR("DMA status reg = 0x%x after cleared!\n",data); +} + +/** + * Returns the all unmasked interrupt status after reading the DmaStatus register. + * @param[in] pointer to synopGMACdevice. + * \return 0 upon success. Error code upon failure. + */ +u32 synopGMAC_get_interrupt_type(synopGMACdevice *gmacdev) +{ + u32 data; + u32 interrupts = 0; + data = synopGMACReadReg(gmacdev->DmaBase, DmaStatus); + + //data = data & ~0x84; //sw: some bits shoud not be cleaned + synopGMACWriteReg(gmacdev->DmaBase, DmaStatus ,data); //manju: I think this is the appropriate location to clear the interrupts + plat_delay(DEFAULT_LOOP_VARIABLE); + if(data & DmaIntErrorMask) interrupts |= synopGMACDmaError; + if(data & DmaIntRxNormMask) interrupts |= synopGMACDmaRxNormal; + if(data & DmaIntRxAbnMask) interrupts |= synopGMACDmaRxAbnormal; + if(data & DmaIntRxStoppedMask) interrupts |= synopGMACDmaRxStopped; + if(data & DmaIntTxNormMask) interrupts |= synopGMACDmaTxNormal; + if(data & DmaIntTxAbnMask) interrupts |= synopGMACDmaTxAbnormal; + if(data & DmaIntTxStoppedMask) interrupts |= synopGMACDmaTxStopped; + + return interrupts; +} + +/** + * Returns the interrupt mask. + * @param[in] pointer to synopGMACdevice. + * \return 0 upon success. Error code upon failure. + */ +#if UNUSED +u32 synopGMAC_get_interrupt_mask(synopGMACdevice *gmacdev) +{ + return(synopGMACReadReg(gmacdev->DmaBase, DmaInterrupt)); +} +#endif + +/** + * Enable all the interrupts. + * Enables the DMA interrupt as specified by the bit mask. + * @param[in] pointer to synopGMACdevice. + * @param[in] bit mask of interrupts to be enabled. + * \return returns void. + */ +#if UNUSED +void synopGMAC_enable_interrupt(synopGMACdevice *gmacdev, u32 interrupts) +{ + synopGMACWriteReg(gmacdev->DmaBase, DmaInterrupt, interrupts); + return; +} +#endif + + +/** + * Disable all the interrupts. + * Disables all DMA interrupts. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + * \note This function disabled all the interrupts, if you want to disable a particular interrupt then + * use synopGMAC_disable_interrupt(). + */ +void synopGMAC_disable_interrupt_all(synopGMACdevice *gmacdev) +{ +// rt_kprintf("dmabase = 0x%x\n",gmacdev->DmaBase); + synopGMACWriteReg(gmacdev->DmaBase, DmaInterrupt, DmaIntDisable); +// synopGMACReadReg(gmacdev->DmaBase, DmaInterrupt); + return; +} + +/** + * Disable interrupt according to the bitfield supplied. + * Disables only those interrupts specified in the bit mask in second argument. + * @param[in] pointer to synopGMACdevice. + * @param[in] bit mask for interrupts to be disabled. + * \return returns void. + */ +#if UNUSED +void synopGMAC_disable_interrupt(synopGMACdevice *gmacdev, u32 interrupts) +{ + synopGMACClearBits(gmacdev->DmaBase, DmaInterrupt, interrupts); + return; +} +#endif +/** + * Enable the DMA Reception. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_enable_dma_rx(synopGMACdevice * gmacdev) +{ +// synopGMACSetBits(gmacdev->DmaBase, DmaControl, DmaRxStart); + u32 data; + data = synopGMACReadReg(gmacdev->DmaBase, DmaControl); + data |= DmaRxStart; + TR0(" ===33334\n"); + synopGMACWriteReg(gmacdev->DmaBase, DmaControl ,data); + TR0(" ===33344\n"); +} + +/** + * Enable the DMA Transmission. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_enable_dma_tx(synopGMACdevice * gmacdev) +{ +// synopGMACSetBits(gmacdev->DmaBase, DmaControl, DmaTxStart); + u32 data; + data = synopGMACReadReg(gmacdev->DmaBase, DmaControl); + data |= DmaTxStart; + synopGMACWriteReg(gmacdev->DmaBase, DmaControl ,data); + +} + +/** + * Resumes the DMA Transmission. + * the DmaTxPollDemand is written. (the data writeen could be anything). + * This forces the DMA to resume transmission. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_resume_dma_tx(synopGMACdevice * gmacdev) +{ + synopGMACWriteReg(gmacdev->DmaBase, DmaTxPollDemand, 1); + +} +/** + * Resumes the DMA Reception. + * the DmaRxPollDemand is written. (the data writeen could be anything). + * This forces the DMA to resume reception. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_resume_dma_rx(synopGMACdevice * gmacdev) +{ + synopGMACWriteReg(gmacdev->DmaBase, DmaRxPollDemand, 0); + +} +/** + * Take ownership of this Descriptor. + * The function is same for both the ring mode and the chain mode DMA structures. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_take_desc_ownership(DmaDesc * desc) +{ + if(desc){ + desc->status &= ~DescOwnByDma; //Clear the DMA own bit +// desc->status |= DescError; // Set the error to indicate this descriptor is bad + } +} + +/** + * Take ownership of all the rx Descriptors. + * This function is called when there is fatal error in DMA transmission. + * When called it takes the ownership of all the rx descriptor in rx descriptor pool/queue from DMA. + * The function is same for both the ring mode and the chain mode DMA structures. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + * \note Make sure to disable the transmission before calling this function, otherwise may result in racing situation. + */ +void synopGMAC_take_desc_ownership_rx(synopGMACdevice * gmacdev) +{ + s32 i; + DmaDesc *desc; + desc = gmacdev->RxDesc; + for(i = 0; i < gmacdev->RxDescCount; i++){ + if(synopGMAC_is_rx_desc_chained(desc)){ //This descriptor is in chain mode + + synopGMAC_take_desc_ownership(desc); + desc = (DmaDesc *)desc->data2; + } + else{ + synopGMAC_take_desc_ownership(desc + i); + } + } +} + +/** + * Take ownership of all the rx Descriptors. + * This function is called when there is fatal error in DMA transmission. + * When called it takes the ownership of all the tx descriptor in tx descriptor pool/queue from DMA. + * The function is same for both the ring mode and the chain mode DMA structures. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + * \note Make sure to disable the transmission before calling this function, otherwise may result in racing situation. + */ +void synopGMAC_take_desc_ownership_tx(synopGMACdevice * gmacdev) +{ + s32 i; + DmaDesc *desc; + desc = gmacdev->TxDesc; + for(i = 0; i < gmacdev->TxDescCount; i++){ + if(synopGMAC_is_tx_desc_chained(desc)){ //This descriptor is in chain mode + synopGMAC_take_desc_ownership(desc); + desc = (DmaDesc *)desc->data2; + } + else{ + synopGMAC_take_desc_ownership(desc + i); + } + } +} + +/** + * Disable the DMA for Transmission. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ + +void synopGMAC_disable_dma_tx(synopGMACdevice * gmacdev) +{ +// synopGMACClearBits(gmacdev->DmaBase, DmaControl, DmaTxStart); + u32 data; + data = synopGMACReadReg(gmacdev->DmaBase, DmaControl); + data &= (~DmaTxStart); + synopGMACWriteReg(gmacdev->DmaBase, DmaControl ,data); +} +/** + * Disable the DMA for Reception. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_disable_dma_rx(synopGMACdevice * gmacdev) +{ +// synopGMACClearBits(gmacdev->DmaBase, DmaControl, DmaRxStart); + u32 data; + data = synopGMACReadReg(gmacdev->DmaBase, DmaControl); + data &= (~DmaRxStart); + synopGMACWriteReg(gmacdev->DmaBase, DmaControl ,data); +} +/*******************PMT APIs***************************************/ +/** + * Enables the assertion of PMT interrupt. + * This enables the assertion of PMT interrupt due to Magic Pkt or Wakeup frame + * reception. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +#if UNUSED +void synopGMAC_pmt_int_enable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev->MacBase,GmacInterruptMask,GmacPmtIntMask); + return; +} +#endif +/** + * Disables the assertion of PMT interrupt. + * This disables the assertion of PMT interrupt due to Magic Pkt or Wakeup frame + * reception. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_pmt_int_disable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev->MacBase,GmacInterruptMask,GmacPmtIntMask); + return; +} +/** + * Enables the power down mode of GMAC. + * This function puts the Gmac in power down mode. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +#if UNUSED +void synopGMAC_power_down_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev->MacBase,GmacPmtCtrlStatus,GmacPmtPowerDown); + return; +} +#endif +/** + * Disables the powerd down setting of GMAC. + * If the driver wants to bring up the GMAC from powerdown mode, even though the magic packet or the + * wake up frames received from the network, this function should be called. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +#if UNUSED +void synopGMAC_power_down_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev->MacBase,GmacPmtCtrlStatus,GmacPmtPowerDown); + return; +} +#endif +/** + * Enables the pmt interrupt generation in powerdown mode. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +#if UNUSED +void synopGMAC_enable_pmt_interrupt(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev->MacBase,GmacInterruptMask,GmacPmtIntMask); +} +#endif +/** + * Disables the pmt interrupt generation in powerdown mode. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +#if UNUSED +void synopGMAC_disable_pmt_interrupt(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev->MacBase,GmacInterruptMask,GmacPmtIntMask); +} +#endif +/** + * Enables GMAC to look for Magic packet. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +#if UNUSED +void synopGMAC_magic_packet_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev->MacBase,GmacPmtCtrlStatus,GmacPmtMagicPktEnable); + return; +} +#endif + +/** + * Enables GMAC to look for wake up frame. + * Wake up frame is defined by the user. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +#if UNUSED +void synopGMAC_wakeup_frame_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev->MacBase,GmacPmtCtrlStatus,GmacPmtWakeupFrameEnable); + return; +} +#endif + +/** + * Enables wake-up frame filter to handle unicast packets. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +#if UNUSED +void synopGMAC_pmt_unicast_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev->MacBase,GmacPmtCtrlStatus,GmacPmtGlobalUnicast); + return; +} +#endif +/** + * Checks whether the packet received is a magic packet?. + * @param[in] pointer to synopGMACdevice. + * \return returns True if magic packet received else returns false. + */ +bool synopGMAC_is_magic_packet_received(synopGMACdevice *gmacdev) +{ + u32 data; + data = synopGMACReadReg(gmacdev->MacBase,GmacPmtCtrlStatus); + return((data & GmacPmtMagicPktReceived) == GmacPmtMagicPktReceived); +} +/** + * Checks whether the packet received is a wakeup frame?. + * @param[in] pointer to synopGMACdevice. + * \return returns true if wakeup frame received else returns false. + */ +bool synopGMAC_is_wakeup_frame_received(synopGMACdevice *gmacdev) +{ + u32 data; + data = synopGMACReadReg(gmacdev->MacBase,GmacPmtCtrlStatus); + return((data & GmacPmtWakeupFrameReceived) == GmacPmtWakeupFrameReceived); +} + +/** + * Populates the remote wakeup frame registers. + * Consecutive 8 writes to GmacWakeupAddr writes the wakeup frame filter registers. + * Before commensing a new write, frame filter pointer is reset to 0x0000. + * A small delay is introduced to allow frame filter pointer reset operation. + * @param[in] pointer to synopGMACdevice. + * @param[in] pointer to frame filter contents array. + * \return returns void. + */ +#if UNUSED +void synopGMAC_write_wakeup_frame_register(synopGMACdevice *gmacdev, u32 * filter_contents) +{ + s32 i; + synopGMACSetBits(gmacdev->MacBase,GmacPmtCtrlStatus,GmacPmtFrmFilterPtrReset); + plat_delay(10); + for(i =0; iMacBase, GmacWakeupAddr, *(filter_contents + i)); + return; + +} +#endif + +/*******************PMT APIs***************************************/ +/*******************MMC APIs***************************************/ +/** + * Freezes the MMC counters. + * This function call freezes the MMC counters. None of the MMC counters are updated + * due to any tx or rx frames until synopGMAC_mmc_counters_resume is called. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +#if UNUSED +void synopGMAC_mmc_counters_stop(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev->MacBase,GmacMmcCntrl,GmacMmcCounterFreeze); + return; +} +#endif +/** + * Resumes the MMC counter updation. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +#if UNUSED +void synopGMAC_mmc_counters_resume(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev->MacBase,GmacMmcCntrl,GmacMmcCounterFreeze); + return; +} +#endif +/** + * Configures the MMC in Self clearing mode. + * Programs MMC interface so that counters are cleared when the counters are read. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +#if UNUSED +void synopGMAC_mmc_counters_set_selfclear(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev->MacBase,GmacMmcCntrl,GmacMmcCounterResetOnRead); + return; +} +#endif +/** + * Configures the MMC in non-Self clearing mode. + * Programs MMC interface so that counters are cleared when the counters are read. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +#if UNUSED +void synopGMAC_mmc_counters_reset_selfclear(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev->MacBase,GmacMmcCntrl,GmacMmcCounterResetOnRead); + return; +} +#endif +/** + * Configures the MMC to stop rollover. + * Programs MMC interface so that counters will not rollover after reaching maximum value. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +#if UNUSED +void synopGMAC_mmc_counters_disable_rollover(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev->MacBase,GmacMmcCntrl,GmacMmcCounterStopRollover); + return; +} +/** + * Configures the MMC to rollover. + * Programs MMC interface so that counters will rollover after reaching maximum value. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_mmc_counters_enable_rollover(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev->MacBase,GmacMmcCntrl,GmacMmcCounterStopRollover); + return; +} + +/** + * Read the MMC Counter. + * @param[in] pointer to synopGMACdevice. + * @param[in] the counter to be read. + * \return returns the read count value. + */ +u32 synopGMAC_read_mmc_counter(synopGMACdevice *gmacdev, u32 counter) +{ + return( synopGMACReadReg(gmacdev->MacBase,counter)); +} +#endif +/** + * Read the MMC Rx interrupt status. + * @param[in] pointer to synopGMACdevice. + * \return returns the Rx interrupt status. + */ +u32 synopGMAC_read_mmc_rx_int_status(synopGMACdevice *gmacdev) +{ + return( synopGMACReadReg(gmacdev->MacBase,GmacMmcIntrRx)); +} +/** + * Read the MMC Tx interrupt status. + * @param[in] pointer to synopGMACdevice. + * \return returns the Tx interrupt status. + */ +u32 synopGMAC_read_mmc_tx_int_status(synopGMACdevice *gmacdev) +{ + return( synopGMACReadReg(gmacdev->MacBase,GmacMmcIntrTx)); +} +/** + * Disable the MMC Tx interrupt. + * The MMC tx interrupts are masked out as per the mask specified. + * @param[in] pointer to synopGMACdevice. + * @param[in] tx interrupt bit mask for which interrupts needs to be disabled. + * \return returns void. + */ +void synopGMAC_disable_mmc_tx_interrupt(synopGMACdevice *gmacdev, u32 mask) +{ + synopGMACSetBits(gmacdev->MacBase,GmacMmcIntrMaskTx,mask); + return; +} +/** + * Enable the MMC Tx interrupt. + * The MMC tx interrupts are enabled as per the mask specified. + * @param[in] pointer to synopGMACdevice. + * @param[in] tx interrupt bit mask for which interrupts needs to be enabled. + * \return returns void. + */ +#if UNUSED +void synopGMAC_enable_mmc_tx_interrupt(synopGMACdevice *gmacdev, u32 mask) +{ + synopGMACClearBits(gmacdev->MacBase,GmacMmcIntrMaskTx,mask); +} +#endif +/** + * Disable the MMC Rx interrupt. + * The MMC rx interrupts are masked out as per the mask specified. + * @param[in] pointer to synopGMACdevice. + * @param[in] rx interrupt bit mask for which interrupts needs to be disabled. + * \return returns void. + */ +void synopGMAC_disable_mmc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask) +{ + synopGMACSetBits(gmacdev->MacBase,GmacMmcIntrMaskRx,mask); + return; +} +/** + * Enable the MMC Rx interrupt. + * The MMC rx interrupts are enabled as per the mask specified. + * @param[in] pointer to synopGMACdevice. + * @param[in] rx interrupt bit mask for which interrupts needs to be enabled. + * \return returns void. + */ +#if UNUSED +void synopGMAC_enable_mmc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask) +{ + synopGMACClearBits(gmacdev->MacBase,GmacMmcIntrMaskRx,mask); + return; +} +#endif +/** + * Disable the MMC ipc rx checksum offload interrupt. + * The MMC ipc rx checksum offload interrupts are masked out as per the mask specified. + * @param[in] pointer to synopGMACdevice. + * @param[in] rx interrupt bit mask for which interrupts needs to be disabled. + * \return returns void. + */ +void synopGMAC_disable_mmc_ipc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask) +{ + synopGMACSetBits(gmacdev->MacBase,GmacMmcRxIpcIntrMask,mask); + return; +} +/** + * Enable the MMC ipc rx checksum offload interrupt. + * The MMC ipc rx checksum offload interrupts are enabled as per the mask specified. + * @param[in] pointer to synopGMACdevice. + * @param[in] rx interrupt bit mask for which interrupts needs to be enabled. + * \return returns void. + */ +#if UNUSED +void synopGMAC_enable_mmc_ipc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask) +{ + synopGMACClearBits(gmacdev->MacBase,GmacMmcRxIpcIntrMask,mask); + return; +} +#endif +/*******************MMC APIs***************************************/ +/*******************Ip checksum offloading APIs***************************************/ + +/** + * Enables the ip checksum offloading in receive path. + * When set GMAC calculates 16 bit 1's complement of all received ethernet frame payload. + * It also checks IPv4 Header checksum is correct. GMAC core appends the 16 bit checksum calculated + * for payload of IP datagram and appends it to Ethernet frame transferred to the application. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +#if UNUSED +void synopGMAC_enable_rx_chksum_offload(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev->MacBase,GmacConfig,GmacRxIpcOffload); + return; +} +/** + * Disable the ip checksum offloading in receive path. + * Ip checksum offloading is disabled in the receive path. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_disable_rx_Ipchecksum_offload(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev->MacBase,GmacConfig,GmacRxIpcOffload); +} +/** + * Instruct the DMA to drop the packets fails tcp ip checksum. + * This is to instruct the receive DMA engine to drop the recevied packet if they + * fails the tcp/ip checksum in hardware. Valid only when full checksum offloading is enabled(type-2). + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_rx_tcpip_chksum_drop_enable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev->DmaBase,DmaControl,DmaDisableDropTcpCs); + return; +} +/** + * Instruct the DMA not to drop the packets even if it fails tcp ip checksum. + * This is to instruct the receive DMA engine to allow the packets even if recevied packet + * fails the tcp/ip checksum in hardware. Valid only when full checksum offloading is enabled(type-2). + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_rx_tcpip_chksum_drop_disable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev->DmaBase,DmaControl,DmaDisableDropTcpCs); + return; +} +#endif + +/** + * When the Enhanced Descriptor is enabled then the bit 0 of RDES0 indicates whether the + * Extended Status is available (RDES4). Time Stamp feature and the Checksum Offload Engine2 + * makes use of this extended status to provide the status of the received packet. + * @param[in] pointer to synopGMACdevice + * \return returns TRUE or FALSE + */ +#ifdef ENH_DESC_8W +/** + * This function indicates whether extended status is available in the RDES0. + * Any function which accesses the fields of extended status register must ensure a check on this has been made + * This is valid only for Enhanced Descriptor. + * @param[in] pointer to synopGMACdevice. + * @param[in] u32 status field of the corresponding descriptor. + * \return returns TRUE or FALSE. + */ +bool synopGMAC_is_ext_status(synopGMACdevice *gmacdev,u32 status) // extended status present indicates that the RDES4 need to be probed +{ + return((status & DescRxEXTsts ) != 0 ); // if extstatus set then it returns 1 +} +/** + * This function returns true if the IP header checksum bit is set in the extended status. + * Valid only when enhaced status available is set in RDES0 bit 0. + * This is valid only for Enhanced Descriptor. + * @param[in] pointer to synopGMACdevice. + * @param[in] u32 status field of the corresponding descriptor. + * \return returns TRUE or FALSE. + */ +bool synopGMAC_ES_is_IP_header_error(synopGMACdevice *gmacdev,u32 ext_status) // IP header (IPV4) checksum error +{ + return((ext_status & DescRxIpHeaderError) != 0 ); // if IPV4 header error return 1 +} +/** + * This function returns true if the Checksum is bypassed in the hardware. + * Valid only when enhaced status available is set in RDES0 bit 0. + * This is valid only for Enhanced Descriptor. + * @param[in] pointer to synopGMACdevice. + * @param[in] u32 status field of the corresponding descriptor. + * \return returns TRUE or FALSE. + */ +bool synopGMAC_ES_is_rx_checksum_bypassed(synopGMACdevice *gmacdev,u32 ext_status) // Hardware engine bypassed the checksum computation/checking +{ + return((ext_status & DescRxChkSumBypass ) != 0 ); // if checksum offloading bypassed return 1 +} +/** + * This function returns true if payload checksum error is set in the extended status. + * Valid only when enhaced status available is set in RDES0 bit 0. + * This is valid only for Enhanced Descriptor. + * @param[in] pointer to synopGMACdevice. + * @param[in] u32 status field of the corresponding descriptor. + * \return returns TRUE or FALSE. + */ +bool synopGMAC_ES_is_IP_payload_error(synopGMACdevice *gmacdev,u32 ext_status) // IP payload checksum is in error (UDP/TCP/ICMP checksum error) +{ + return((ext_status & DescRxIpPayloadError) != 0 ); // if IP payload error return 1 +} +#endif + +/** + * Decodes the Rx Descriptor status to various checksum error conditions. + * @param[in] pointer to synopGMACdevice. + * @param[in] u32 status field of the corresponding descriptor. + * \return returns decoded enum (u32) indicating the status. + */ +u32 synopGMAC_is_rx_checksum_error(synopGMACdevice *gmacdev, u32 status) +{ + if (((status & DescRxChkBit5) == 0) && ((status & DescRxChkBit7) == 0) && ((status & DescRxChkBit0) == 0)) + return RxLenLT600; + else if(((status & DescRxChkBit5) == 0) && ((status & DescRxChkBit7) == 0) && ((status & DescRxChkBit0) != 0)) + return RxIpHdrPayLoadChkBypass; + else if(((status & DescRxChkBit5) == 0) && ((status & DescRxChkBit7) != 0) && ((status & DescRxChkBit0) != 0)) + return RxChkBypass; + else if(((status & DescRxChkBit5) != 0) && ((status & DescRxChkBit7) == 0) && ((status & DescRxChkBit0) == 0)) + return RxNoChkError; + else if(((status & DescRxChkBit5) != 0) && ((status & DescRxChkBit7) == 0) && ((status & DescRxChkBit0) != 0)) + return RxPayLoadChkError; + else if(((status & DescRxChkBit5) != 0) && ((status & DescRxChkBit7) != 0) && ((status & DescRxChkBit0) == 0)) + return RxIpHdrChkError; + else if(((status & DescRxChkBit5) != 0) && ((status & DescRxChkBit7) != 0) && ((status & DescRxChkBit0) != 0)) + return RxIpHdrPayLoadChkError; + else + return RxIpHdrPayLoadRes; +} +/** + * Checks if any Ipv4 header checksum error in the frame just transmitted. + * This serves as indication that error occureed in the IPv4 header checksum insertion. + * The sent out frame doesnot carry any ipv4 header checksum inserted by the hardware. + * @param[in] pointer to synopGMACdevice. + * @param[in] u32 status field of the corresponding descriptor. + * \return returns true if error in ipv4 header checksum, else returns false. + */ +bool synopGMAC_is_tx_ipv4header_checksum_error(synopGMACdevice *gmacdev, u32 status) +{ + return((status & DescTxIpv4ChkError) == DescTxIpv4ChkError); +} + +/** + * Checks if any payload checksum error in the frame just transmitted. + * This serves as indication that error occureed in the payload checksum insertion. + * The sent out frame doesnot carry any payload checksum inserted by the hardware. + * @param[in] pointer to synopGMACdevice. + * @param[in] u32 status field of the corresponding descriptor. + * \return returns true if error in ipv4 header checksum, else returns false. + */ +bool synopGMAC_is_tx_payload_checksum_error(synopGMACdevice *gmacdev, u32 status) +{ + return((status & DescTxPayChkError) == DescTxPayChkError); +} +/** + * The check summ offload engine is bypassed in the tx path. + * Checksum is not computed in the Hardware. + * @param[in] pointer to synopGMACdevice. + * @param[in] Pointer to tx descriptor for which ointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_tx_checksum_offload_bypass(synopGMACdevice *gmacdev, DmaDesc *desc) +{ + #ifdef ENH_DESC + desc->status = (desc->length & (~DescTxCisMask));//ENH_DESC + #else + desc->length = (desc->length & (~DescTxCisMask)); + #endif +} +/** + * The check summ offload engine is enabled to do only IPV4 header checksum. + * IPV4 header Checksum is computed in the Hardware. + * @param[in] pointer to synopGMACdevice. + * @param[in] Pointer to tx descriptor for which ointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_tx_checksum_offload_ipv4hdr(synopGMACdevice *gmacdev, DmaDesc *desc) +{ + #ifdef ENH_DESC + desc->status = ((desc->status & (~DescTxCisMask)) | DescTxCisIpv4HdrCs);//ENH_DESC + #else + desc->length = ((desc->length & (~DescTxCisMask)) | DescTxCisIpv4HdrCs); + #endif +} + +/** + * The check summ offload engine is enabled to do TCPIP checsum assuming Pseudo header is available. + * Hardware computes the tcp ip checksum assuming pseudo header checksum is computed in software. + * Ipv4 header checksum is also inserted. + * @param[in] pointer to synopGMACdevice. + * @param[in] Pointer to tx descriptor for which ointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_tx_checksum_offload_tcponly(synopGMACdevice *gmacdev, DmaDesc *desc) +{ + #ifdef ENH_DESC + desc->status = ((desc->status & (~DescTxCisMask)) | DescTxCisTcpOnlyCs);//ENH_DESC + #else + desc->length = ((desc->length & (~DescTxCisMask)) | DescTxCisTcpOnlyCs); + #endif +} +/** + * The check summ offload engine is enabled to do complete checksum computation. + * Hardware computes the tcp ip checksum including the pseudo header checksum. + * Here the tcp payload checksum field should be set to 0000. + * Ipv4 header checksum is also inserted. + * @param[in] pointer to synopGMACdevice. + * @param[in] Pointer to tx descriptor for which ointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_tx_checksum_offload_tcp_pseudo(synopGMACdevice *gmacdev, DmaDesc *desc) +{ + #ifdef ENH_DESC + desc->status = ((desc->length & (~DescTxCisMask)) | DescTxCisTcpPseudoCs); + #else + desc->length = ((desc->length & (~DescTxCisMask)) | DescTxCisTcpPseudoCs); + #endif + +} +/*******************Ip checksum offloading APIs***************************************/ +/*******************IEEE 1588 Timestamping API***************************************/ +/* + * At this time the driver supports the IEEE time stamping feature when the Enhanced Descriptors are enabled. + * For normal descriptor and the IEEE time stamp (version 1), driver support is not proviced + * Please make sure you have enabled the Advanced timestamp feature in the hardware and the driver should + * be compiled with the ADV_TME_STAMP feature. + * Some of the APIs provided here may not be valid for all configurations. Please make sure you call the + * API with due care. + */ + +/** + * This function enables the timestamping. This enables the timestamping for transmit and receive frames. + * When disabled timestamp is not added to tx and receive frames and timestamp generator is suspended. + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +#if UNUSED +void synopGMAC_TS_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev->MacBase,GmacTSControl,GmacTSENA); + return; +} +/** + * This function disables the timestamping. + * When disabled timestamp is not added to tx and receive frames and timestamp generator is suspended. + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev->MacBase,GmacInterruptMask, GmacTSIntMask); + return; +} + +/** + * Enable the interrupt to get timestamping interrupt. + * This enables the host to get the interrupt when (1) system time is greater or equal to the + * target time high and low register or (2) there is a overflow in th esecond register. + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_int_enable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev->MacBase,GmacInterruptMask,GmacPmtIntMask); + return; +} + +/** + * Disable the interrupt to get timestamping interrupt. + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_int_disable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev->MacBase,GmacInterruptMask,GmacPmtIntMask); + return; +} + +/** + * Enable MAC address for PTP frame filtering. + * When enabled, uses MAC address (apart from MAC address 0) to filter the PTP frames when + * PTP is sent directly over Ethernet. + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_mac_addr_filt_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev->MacBase,GmacTSControl,GmacTSENMACADDR); + return; +} + +/** + * Disables MAC address for PTP frame filtering. + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_mac_addr_filt_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev->MacBase,GmacTSControl,GmacTSENMACADDR); + return; +} + +/** + * Selet the type of clock mode for PTP. + * Please note to use one of the follwoing as the clk_type argument. + * GmacTSOrdClk = 0x00000000, 00=> Ordinary clock + * GmacTSBouClk = 0x00010000, 01=> Boundary clock + * GmacTSEtoEClk = 0x00020000, 10=> End-to-End transparent clock + * GmacTSPtoPClk = 0x00030000, 11=> P-to-P transparent clock + * @param[in] pointer to synopGMACdevice + * @param[in] u32 value representing one of the above clk value + * \return returns void + */ +void synopGMAC_TS_set_clk_type(synopGMACdevice *gmacdev, u32 clk_type) +{ + u32 clkval; + clkval = synopGMACReadReg(gmacdev->MacBase,GmacTSControl); //set the mdc clock to the user defined value + clkval = clkval | clk_type; + synopGMACWriteReg(gmacdev->MacBase,GmacTSControl,clkval); + return; +} + +/** + * Enable Snapshot for messages relevant to Master. + * When enabled, snapshot is taken for messages relevant to master mode only, else snapshot is taken for messages relevant + * to slave node. + * Valid only for Ordinary clock and Boundary clock + * Reserved when "Advanced Time Stamp" is not selected + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_master_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev->MacBase,GmacTSControl,GmacTSMSTRENA); + return; +} +/** + * Disable Snapshot for messages relevant to Master. + * When disabled, snapshot is taken for messages relevant + * to slave node. + * Valid only for Ordinary clock and Boundary clock + * Reserved when "Advanced Time Stamp" is not selected + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_master_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev->MacBase,GmacTSControl,GmacTSMSTRENA); + return; +} +/** + * Enable Snapshot for Event messages. + * When enabled, snapshot is taken for event messages only (SYNC, Delay_Req, Pdelay_Req or Pdelay_Resp) + * When disabled, snapshot is taken for all messages except Announce, Management and Signaling. + * Reserved when "Advanced Time Stamp" is not selected + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_event_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev->MacBase,GmacTSControl,GmacTSEVNTENA); + return; +} +/** + * Disable Snapshot for Event messages. + * When disabled, snapshot is taken for all messages except Announce, Management and Signaling. + * Reserved when "Advanced Time Stamp" is not selected + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_event_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev->MacBase,GmacTSControl,GmacTSEVNTENA); + return; +} + +/** + * Enable time stamp snapshot for IPV4 frames. + * When enabled, time stamp snapshot is taken for IPV4 frames + * Reserved when "Advanced Time Stamp" is not selected + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_IPV4_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev->MacBase,GmacTSControl,GmacTSIPV4ENA); + return; +} +/** + * Disable time stamp snapshot for IPV4 frames. + * When disabled, time stamp snapshot is not taken for IPV4 frames + * Reserved when "Advanced Time Stamp" is not selected + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_IPV4_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev->MacBase,GmacTSControl,GmacTSIPV4ENA); + return; +} // Only for "Advanced Time Stamp" +/** + * Enable time stamp snapshot for IPV6 frames. + * When enabled, time stamp snapshot is taken for IPV6 frames + * Reserved when "Advanced Time Stamp" is not selected + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_IPV6_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev->MacBase,GmacTSControl,GmacTSIPV6ENA); + return; +} +/** + * Disable time stamp snapshot for IPV6 frames. + * When disabled, time stamp snapshot is not taken for IPV6 frames + * Reserved when "Advanced Time Stamp" is not selected + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_IPV6_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev->MacBase,GmacTSControl,GmacTSIPV6ENA); + return; +} + +/** + * Enable time stamp snapshot for PTP over Ethernet frames. + * When enabled, time stamp snapshot is taken for PTP over Ethernet frames + * Reserved when "Advanced Time Stamp" is not selected + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_ptp_over_ethernet_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev->MacBase,GmacTSControl,GmacTSIPENA); + return; +} +/** + * Disable time stamp snapshot for PTP over Ethernet frames. + * When disabled, time stamp snapshot is not taken for PTP over Ethernet frames + * Reserved when "Advanced Time Stamp" is not selected + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_ptp_over_ethernet_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev->MacBase,GmacTSControl,GmacTSIPENA); + return; +} + +/** + * Snoop PTP packet for version 2 format + * When set the PTP packets are snooped using the version 2 format. + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_pkt_snoop_ver2(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev->MacBase,GmacTSControl,GmacTSVER2ENA); + return; +} +/** + * Snoop PTP packet for version 2 format + * When set the PTP packets are snooped using the version 2 format. + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_pkt_snoop_ver1(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev->MacBase,GmacTSControl,GmacTSVER2ENA); + return; +} + +/** + * Timestamp digital rollover + * When set the timestamp low register rolls over after 0x3B9A_C9FF value. + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_digital_rollover_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev->MacBase,GmacTSControl,GmacTSCTRLSSR); + return; +} +/** + * Timestamp binary rollover + * When set the timestamp low register rolls over after 0x7FFF_FFFF value. + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_binary_rollover_enable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev->MacBase,GmacTSControl,GmacTSCTRLSSR); + return; +} +/** + * Enable Time Stamp for All frames + * When set the timestamp snap shot is enabled for all frames received by the core. + * Reserved when "Advanced Time Stamp" is not selected + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_all_frames_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev->MacBase,GmacTSControl,GmacTSENALL); + return; +} +/** + * Disable Time Stamp for All frames + * When reset the timestamp snap shot is not enabled for all frames received by the core. + * Reserved when "Advanced Time Stamp" is not selected + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_all_frames_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev->MacBase,GmacTSControl,GmacTSENALL); + return; +} +/** + * Addend Register Update + * This function loads the contents of Time stamp addend register with the supplied 32 value. + * This is reserved function when only coarse correction option is selected + * @param[in] pointer to synopGMACdevice + * @param[in] 32 bit addend value + * \return returns 0 for Success or else Failure + */ +s32 synopGMAC_TS_addend_update(synopGMACdevice *gmacdev, u32 addend_value) +{ + u32 loop_variable; + synopGMACWriteReg(gmacdev->MacBase,GmacTSAddend,addend_value);// Load the addend_value in to Addend register + for(loop_variable = 0; loop_variable < DEFAULT_LOOP_VARIABLE; loop_variable++){ //Wait till the busy bit gets cleared with in a certain amount of time + if(!((synopGMACReadReg(gmacdev->MacBase,GmacTSControl)) & GmacTSADDREG)){ // if it is cleared then break + break; + } + plat_delay(DEFAULT_DELAY_VARIABLE); + } + if(loop_variable < DEFAULT_LOOP_VARIABLE) + synopGMACSetBits(gmacdev->MacBase,GmacTSControl,GmacTSADDREG); + else{ + TR("Error::: The TSADDREG bit is not getting cleared !!!!!!\n"); + return -ESYNOPGMACPHYERR; + } + return -ESYNOPGMACNOERR; +} +/** + * time stamp Update + * This function updates (adds/subtracts) with the value specified in the Timestamp High Update and + * Timestamp Low Update register. + * @param[in] pointer to synopGMACdevice + * @param[in] Timestamp High Update value + * @param[in] Timestamp Low Update value + * \return returns 0 for Success or else Failure + */ +s32 synopGMAC_TS_timestamp_update(synopGMACdevice *gmacdev, u32 high_value, u32 low_value) +{ + u32 loop_variable; + synopGMACWriteReg(gmacdev->MacBase,GmacTSHighUpdate,high_value);// Load the high value to Timestamp High register + synopGMACWriteReg(gmacdev->MacBase,GmacTSLowUpdate,low_value);// Load the high value to Timestamp High register + for(loop_variable = 0; loop_variable < DEFAULT_LOOP_VARIABLE; loop_variable++){ //Wait till the busy bit gets cleared with in a certain amount of time + if(!((synopGMACReadReg(gmacdev->MacBase,GmacTSControl)) & GmacTSUPDT)){ // if it is cleared then break + break; + } + plat_delay(DEFAULT_DELAY_VARIABLE); + } + if(loop_variable < DEFAULT_LOOP_VARIABLE) + synopGMACSetBits(gmacdev->MacBase,GmacTSControl,GmacTSUPDT); + else{ + TR("Error::: The TSADDREG bit is not getting cleared !!!!!!\n"); + return -ESYNOPGMACPHYERR; + } + return -ESYNOPGMACNOERR; +} + +/** + * time stamp Initialize + * This function Loads/Initializes h the value specified in the Timestamp High Update and + * Timestamp Low Update register. + * @param[in] pointer to synopGMACdevice + * @param[in] Timestamp High Load value + * @param[in] Timestamp Low Load value + * \return returns 0 for Success or else Failure + */ +s32 synopGMAC_TS_timestamp_init(synopGMACdevice *gmacdev, u32 high_value, u32 low_value) +{ + u32 loop_variable; + synopGMACWriteReg(gmacdev->MacBase,GmacTSHighUpdate,high_value);// Load the high value to Timestamp High register + synopGMACWriteReg(gmacdev->MacBase,GmacTSLowUpdate,low_value);// Load the high value to Timestamp High register + for(loop_variable = 0; loop_variable < DEFAULT_LOOP_VARIABLE; loop_variable++){ //Wait till the busy bit gets cleared with in a certain amount of time + if(!((synopGMACReadReg(gmacdev->MacBase,GmacTSControl)) & GmacTSINT)){ // if it is cleared then break + break; + } + plat_delay(DEFAULT_DELAY_VARIABLE); + } + if(loop_variable < DEFAULT_LOOP_VARIABLE) + synopGMACSetBits(gmacdev->MacBase,GmacTSControl,GmacTSINT); + else{ + TR("Error::: The TSADDREG bit is not getting cleared !!!!!!\n"); + return -ESYNOPGMACPHYERR; + } + return -ESYNOPGMACNOERR; +} + +/** + * Time Stamp Update Coarse + * When reset the timestamp update is done using coarse method. + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_coarse_update(synopGMACdevice *gmacdev) +{ + synopGMACClearBits(gmacdev->MacBase,GmacTSControl,GmacTSCFUPDT); + return; +} +/** + * Time Stamp Update Fine + * When reset the timestamp update is done using Fine method. + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_fine_update(synopGMACdevice *gmacdev) +{ + synopGMACSetBits(gmacdev->MacBase,GmacTSControl,GmacTSCFUPDT); + return; +} + +/** + * Load the Sub Second Increment value in to Sub Second increment register + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_subsecond_init(synopGMACdevice *gmacdev, u32 sub_sec_inc_value) +{ + synopGMACWriteReg(gmacdev->MacBase,GmacTSSubSecIncr,(sub_sec_inc_value & GmacSSINCMsk)); + return; +} +/** + * Reads the time stamp contents in to the respective pointers + * These registers are readonly. + * This function returns the 48 bit time stamp assuming Version 2 timestamp with higher word is selected. + * @param[in] pointer to synopGMACdevice + * @param[in] pointer to hold 16 higher bit second register contents + * @param[in] pointer to hold 32 bit second register contents + * @param[in] pointer to hold 32 bit subnanosecond register contents + * \return returns void + * \note Please note that since the atomic access to the timestamp registers is not possible, + * the contents read may be different from the actual time stamp. + */ +void synopGMAC_TS_read_timestamp(synopGMACdevice *gmacdev, u16 * higher_sec_val, u32 * sec_val, u32 * sub_sec_val) +{ + * higher_sec_val = (u16)(synopGMACReadReg(gmacdev->MacBase,GmacTSHighWord) & GmacTSHighWordMask); + * sec_val = synopGMACReadReg(gmacdev->MacBase,GmacTSHigh); + * sub_sec_val = synopGMACReadReg(gmacdev->MacBase,GmacTSLow); + return; +} +/** + * Loads the time stamp higher sec value from the value supplied + * @param[in] pointer to synopGMACdevice + * @param[in] 16 higher bit second register contents passed as 32 bit value + * \return returns void + */ +void synopGMAC_TS_load_timestamp_higher_val(synopGMACdevice *gmacdev, u32 higher_sec_val) +{ + synopGMACWriteReg(gmacdev->MacBase,GmacTSHighWord, (higher_sec_val & GmacTSHighWordMask)); + return; +} +/** + * Reads the time stamp higher sec value to respective pointers + * @param[in] pointer to synopGMACdevice + * @param[in] pointer to hold 16 higher bit second register contents + * \return returns void + */ +void synopGMAC_TS_read_timestamp_higher_val(synopGMACdevice *gmacdev, u16 * higher_sec_val) +{ + * higher_sec_val = (u16)(synopGMACReadReg(gmacdev->MacBase,GmacTSHighWord) & GmacTSHighWordMask); + return; +} +/** + * Load the Target time stamp registers + * This function Loads the target time stamp registers with the values proviced + * @param[in] pointer to synopGMACdevice + * @param[in] target Timestamp High value + * @param[in] target Timestamp Low value + * \return returns 0 for Success or else Failure + */ +void synopGMAC_TS_load_target_timestamp(synopGMACdevice *gmacdev, u32 sec_val, u32 sub_sec_val) +{ + synopGMACWriteReg(gmacdev->MacBase,GmacTSTargetTimeHigh,sec_val); + synopGMACWriteReg(gmacdev->MacBase,GmacTSTargetTimeLow,sub_sec_val); + return; +} +/** + * Reads the Target time stamp registers + * This function Loads the target time stamp registers with the values proviced + * @param[in] pointer to synopGMACdevice + * @param[in] pointer to hold target Timestamp High value + * @param[in] pointer to hold target Timestamp Low value + * \return returns 0 for Success or else Failure + */ +void synopGMAC_TS_read_target_timestamp(synopGMACdevice *gmacdev, u32 * sec_val, u32 * sub_sec_val) +{ + * sec_val = synopGMACReadReg(gmacdev->MacBase,GmacTSTargetTimeHigh); + * sub_sec_val = synopGMACReadReg(gmacdev->MacBase,GmacTSTargetTimeLow); + return; +} +#endif diff --git a/bsp/ls2kdev/drivers/net/synopGMAC_Dev.h b/bsp/ls2kdev/drivers/net/synopGMAC_Dev.h new file mode 100644 index 0000000000000000000000000000000000000000..f47046d5bae45f7728b210e811230113803afd8f --- /dev/null +++ b/bsp/ls2kdev/drivers/net/synopGMAC_Dev.h @@ -0,0 +1,1717 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-08-24 chinesebear first version + * 2020-08-10 lizhirui porting to ls2k + */ + +#define UNUSED 1 + +#ifndef SYNOP_GMAC_DEV_H +#define SYNOP_GMAC_DEV_H 1 + +/*******************************************************************/ +#define SYNOP_LOOPBACK_MODE (0) +#define SYNOP_LOOPBACK_DEBUG (0) +#define SYNOP_PHY_LOOPBACK (0) + +#define SYNOP_TX_TEST (0) +#define SYNOP_RX_TEST (0) + +#define SYNOP_TOP_DEBUG (0) +#define SYNOP_REG_DEBUG (0) +#define SYNOP_RX_DEBUG (0) +#define SYNOP_TX_DEBUG (0) + +#define ENH_DESC +/*******************************************************************/ + +#include "synopGMAC_plat.h" +#include "synopGMAC_types.h" + +//sw: typedef are included in synopGMAC_plat.h +// it is strange that we should add it here again!! + +/*SynopGMAC can support up to 32 phys*/ +#define GMAC_PHY_BASE 1 +#ifdef GMAC_PHY_BASE +#define DEFAULT_PHY_BASE GMAC_PHY_BASE +#else +#define DEFAULT_PHY_BASE PHY16 //We use First Phy +#endif +#define MACBASE 0x0000 // The Mac Base address offset is 0x0000 +#define DMABASE 0x1000 // Dma base address starts with an offset 0x1000 + + +enum GMACPhyBase +{ + PHY0 = 0, //The device can support 32 phys, but we use first phy only + PHY1 = 1, + PHY16 = 16, + PHY31 = 31, +}; + + +//#define TRANSMIT_DESC_SIZE 256 //Tx Descriptors needed in the Descriptor pool/queue +//#define RECEIVE_DESC_SIZE 256 //Rx Descriptors needed in the Descriptor pool/queue +//#define TRANSMIT_DESC_SIZE 13//256 //Tx Descriptors needed in the Descriptor pool/queue +#define TRANSMIT_DESC_SIZE 36 //48 //Tx Descriptors needed in the Descriptor pool/queue +#define RECEIVE_DESC_SIZE 36 //96 //Rx Descriptors needed in the Descriptor pool/queue + +#define ETHERNET_HEADER 14 //6 byte Dest addr, 6 byte Src addr, 2 byte length/type +#define ETHERNET_CRC 4 //Ethernet CRC +#define ETHERNET_EXTRA 2 //Only God knows about this????? +#define ETHERNET_PACKET_COPY 250 // Maximum length when received data is copied on to a new skb +#define ETHERNET_PACKET_EXTRA 18 // Preallocated length for the rx packets is MTU + ETHERNET_PACKET_EXTRA +#define VLAN_TAG 4 //optional 802.1q VLAN Tag +#define MIN_ETHERNET_PAYLOAD 46 //Minimum Ethernet payload size +#define MAX_ETHERNET_PAYLOAD 1500 //Maximum Ethernet payload size +#define JUMBO_FRAME_PAYLOAD 9000 //Jumbo frame payload size + +#define TX_BUF_SIZE ETHERNET_HEADER + ETHERNET_CRC + MAX_ETHERNET_PAYLOAD + VLAN_TAG + 1000 +#define RX_BUF_SIZE ETHERNET_HEADER + ETHERNET_CRC + MAX_ETHERNET_PAYLOAD + VLAN_TAG + 1000 + + +// This is the IP's phy address. This is unique address for every MAC in the universe +#define DEFAULT_MAC_ADDRESS {0x00, 0x55, 0x7B, 0xB5, 0x7D, 0xF7} + +/* +DMA Descriptor Structure +The structure is common for both receive and transmit descriptors +The descriptor is of 4 words, but our structrue contains 6 words where +last two words are to hold the virtual address of the network buffer pointers +for driver's use +From the GMAC core release 3.50a onwards, the Enhanced Descriptor structure got changed. +The descriptor (both transmit and receive) are of 8 words each rather the 4 words of normal +descriptor structure. +Whenever IEEE 1588 Timestamping is enabled TX/RX DESC6 provides the lower 32 bits of Timestamp value and + TX/RX DESC7 provides the upper 32 bits of Timestamp value +In addition to this whenever extended status bit is set (RX DESC0 bit 0), RX DESC4 contains the extended status information +*/ + +#define MODULO_INTERRUPT 1 // if it is set to 1, interrupt is available for all the descriptors or else interrupt is available only for + // descriptor whose index%MODULO_INTERRUPT is zero +#ifdef ENH_DESC_8W +typedef struct DmaDescStruct +{ + u32 status; /* Status */ + u32 length; /* Buffer 1 and Buffer 2 length */ + u32 buffer1; /* Network Buffer 1 pointer (Dma-able) */ + u32 buffer2; /* Network Buffer 2 pointer or next descriptor pointer (Dma-able)in chain structure */ + /* This data below is used only by driver */ + u32 extstatus; /* Extended status of a Rx Descriptor */ + u32 reserved1; /* Reserved word */ + u32 timestamplow; /* Lower 32 bits of the 64 bit timestamp value */ + u32 timestamphigh; /* Higher 32 bits of the 64 bit timestamp value */ + u64 data1; /* This holds virtual address of buffer1, not used by DMA */ + u64 data2; /* This holds virtual address of buffer2, not used by DMA */ +} DmaDesc; +#else +typedef struct DmaDescStruct +{ + u32 status; /* Status */ + u32 length; /* Buffer 1 and Buffer 2 length */ + u32 buffer1; /* Network Buffer 1 pointer (Dma-able) */ + u32 buffer2; /* Network Buffer 2 pointer or next descriptor pointer (Dma-able)in chain structure */ + /* This data below is used only by driver */ + u64 data1; /* This holds virtual address of buffer1, not used by DMA */ + u64 data2; /* This holds virtual address of buffer2, not used by DMA */ + + //u32 dummy1; //sw: for addr align + //u32 dummy2; // + +} DmaDesc; +#endif + +enum DescMode +{ + RINGMODE = 0x00000001, + CHAINMODE = 0x00000002, +}; + +enum BufferMode +{ + SINGLEBUF = 0x00000001, + DUALBUF = 0x00000002, +}; + +/* synopGMAC device data */ + +typedef struct synopGMACDeviceStruct +{ + u64 MacBase; /* base address of MAC registers */ + u64 DmaBase; /* base address of DMA registers */ + u64 PhyBase; /* PHY device address on MII interface */ + u32 Version; /* Gmac Revision version */ + + dma_addr_t TxDescDma; /* Dma-able address of first tx descriptor either in ring or chain mode, this is used by the GMAC device*/ + dma_addr_t RxDescDma; /* Dma-able address of first rx descriptor either in ring or chain mode, this is used by the GMAC device*/ + DmaDesc *TxDesc; /* start address of TX descriptors ring or chain, this is used by the driver */ + DmaDesc *RxDesc; /* start address of RX descriptors ring or chain, this is used by the driver */ + + u32 BusyTxDesc; /* Number of Tx Descriptors owned by DMA at any given time*/ + u32 BusyRxDesc; /* Number of Rx Descriptors owned by DMA at any given time*/ + + u32 RxDescCount; /* number of rx descriptors in the tx descriptor queue/pool */ + u32 TxDescCount; /* number of tx descriptors in the rx descriptor queue/pool */ + + u32 TxBusy; /* index of the tx descriptor owned by DMA, is obtained by synopGMAC_get_tx_qptr() */ + u32 TxNext; /* index of the tx descriptor next available with driver, given to DMA by synopGMAC_set_tx_qptr() */ + u32 RxBusy; /* index of the rx descriptor owned by DMA, obtained by synopGMAC_get_rx_qptr() */ + u32 RxNext; /* index of the rx descriptor next available with driver, given to DMA by synopGMAC_set_rx_qptr() */ + + DmaDesc * TxBusyDesc; /* Tx Descriptor address corresponding to the index TxBusy */ + DmaDesc * TxNextDesc; /* Tx Descriptor address corresponding to the index TxNext */ + DmaDesc * RxBusyDesc; /* Rx Descriptor address corresponding to the index TxBusy */ + DmaDesc * RxNextDesc; /* Rx Descriptor address corresponding to the index RxNext */ + + /*Phy related stuff*/ + u32 ClockDivMdc; /* Clock divider value programmed in the hardware */ + /* The status of the link */ + u32 LinkState0; /* Link status as reported by the Marvel Phy */ + u32 LinkState; /* Link status as reported by the Marvel Phy */ + u32 DuplexMode; /* Duplex mode of the Phy */ + u32 Speed; /* Speed of the Phy */ + u32 LoopBackMode; /* Loopback status of the Phy */ +// void * FirstTxDesc; +// void * FirstRxDesc; +// u32 skb_array[RECEIVE_DESC_SIZE]; +} synopGMACdevice; + +/* Below is "88E1011/88E1011S Integrated 10/100/1000 Gigabit Ethernet Transceiver" + * Register and their layouts. This Phy has been used in the Dot Aster GMAC Phy daughter. + * Since the Phy register map is standard, this map hardly changes to a different Ppy + */ +enum MiiRegisters +{ + PHY_CONTROL_REG = 0x0000, /*Control Register*/ + PHY_STATUS_REG = 0x0001, /*Status Register */ + PHY_ID_HI_REG = 0x0002, /*PHY Identifier High Register*/ + PHY_ID_LOW_REG = 0x0003, /*PHY Identifier High Register*/ + PHY_AN_ADV_REG = 0x0004, /*Auto-Negotiation Advertisement Register*/ + PHY_LNK_PART_ABl_REG = 0x0005, /*Link Partner Ability Register (Base Page)*/ + PHY_AN_EXP_REG = 0x0006, /*Auto-Negotiation Expansion Register*/ + PHY_AN_NXT_PAGE_TX_REG = 0x0007, /*Next Page Transmit Register*/ + PHY_LNK_PART_NXT_PAGE_REG = 0x0008, /*Link Partner Next Page Register*/ + PHY_1000BT_CTRL_REG = 0x0009, /*1000BASE-T Control Register*/ + PHY_1000BT_STATUS_REG = 0x000a, /*1000BASE-T Status Register*/ + PHY_SPECIFIC_CTRL_REG = 0x0010, /*Phy specific control register*/ + PHY_SPECIFIC_STATUS_REG = 0x0011, /*Phy specific status register*/ + PHY_INTERRUPT_ENABLE_REG = 0x0012, /*Phy interrupt enable register*/ + PHY_INTERRUPT_STATUS_REG = 0x0013, /*Phy interrupt status register*/ + PHY_EXT_PHY_SPC_CTRL = 0x0014, /*Extended Phy specific control*/ + PHY_RX_ERR_COUNTER = 0x0015, /*Receive Error Counter*/ + PHY_EXT_ADDR_CBL_DIAG = 0x0016, /*Extended address for cable diagnostic register*/ + PHY_LED_CONTROL = 0x0018, /*LED Control*/ + PHY_MAN_LED_OVERIDE = 0x0019, /*Manual LED override register*/ + PHY_EXT_PHY_SPC_CTRL2 = 0x001a, /*Extended Phy specific control 2*/ + PHY_EXT_PHY_SPC_STATUS = 0x001b, /*Extended Phy specific status*/ + PHY_CBL_DIAG_REG = 0x001c, /*Cable diagnostic registers*/ +}; + +/* This is Control register layout. Control register is of 16 bit wide. +*/ +enum Mii_GEN_CTRL +{ /* Description bits R/W default value */ + Mii_reset = 0x8000, + Mii_Speed_10 = 0x0000, /* 10 Mbps 6:13 RW */ + Mii_Speed_100 = 0x2000, /* 100 Mbps 6:13 RW */ + Mii_Speed_1000 = 0x0040, /* 1000 Mbit/s 6:13 RW */ + + Mii_Duplex = 0x0100, /* Full Duplex mode 8 RW */ + + Mii_Manual_Master_Config = 0x0800, /* Manual Master Config 11 RW */ + + Mii_Loopback = 0x4000, /* Enable Loop back 14 RW */ + Mii_NoLoopback = 0x0000, /* Enable Loop back 14 RW */ +}; + +enum Mii_Phy_Status +{ + Mii_phy_status_speed_10 = 0x0000, + Mii_phy_status_speed_100 = 0x4000, + Mii_phy_status_speed_1000 = 0x8000, + + Mii_phy_status_full_duplex = 0x2000, + Mii_phy_status_half_duplex = 0x0000, + + Mii_phy_status_link_up = 0x0400, //lyf:rtl 8211 phy +// Mii_phy_status_link_up = 0x0100, //sw: broadcom BCM5461 PHY +}; +/* This is Status register layout. Status register is of 16 bit wide. +*/ +enum Mii_GEN_STATUS +{ + Mii_AutoNegCmplt = 0x0020, /* Autonegotiation completed 5 RW */ + Mii_Link = 0x0004, /* Link status 2 RW */ +}; + +enum Mii_Link_Status +{ + LINKDOWN = 0, + LINKUP = 1, +}; + +enum Mii_Duplex_Mode +{ + HALFDUPLEX = 1, + FULLDUPLEX = 2, +}; +enum Mii_Link_Speed +{ + SPEED10 = 1, + SPEED100 = 2, + SPEED1000 = 3, +}; + +enum Mii_Loop_Back +{ + NOLOOPBACK = 0, + LOOPBACK = 1, +}; + +/********************************************************** + * GMAC registers Map + * For Pci based system address is BARx + GmacRegisterBase + * For any other system translation is done accordingly + **********************************************************/ +enum GmacRegisters +{ + GmacConfig = 0x0000, /* Mac config Register */ + GmacFrameFilter = 0x0004, /* Mac frame filtering controls */ + GmacHashHigh = 0x0008, /* Multi-cast hash table high */ + GmacHashLow = 0x000C, /* Multi-cast hash table low */ + GmacGmiiAddr = 0x0010, /* GMII address Register(ext. Phy) */ + GmacGmiiData = 0x0014, /* GMII data Register(ext. Phy) */ + GmacFlowControl = 0x0018, /* Flow control Register */ + GmacVlan = 0x001C, /* VLAN tag Register (IEEE 802.1Q) */ + + GmacVersion = 0x0020, /* GMAC Core Version Register */ + GmacWakeupAddr = 0x0028, /* GMAC wake-up frame filter adrress reg */ + GmacPmtCtrlStatus = 0x002C, /* PMT control and status register */ + + GmacInterruptStatus = 0x0038, /* Mac Interrupt ststus register */ + GmacInterruptMask = 0x003C, /* Mac Interrupt Mask register */ + + GmacAddr0High = 0x0040, /* Mac address0 high Register */ + GmacAddr0Low = 0x0044, /* Mac address0 low Register */ + GmacAddr1High = 0x0048, /* Mac address1 high Register */ + GmacAddr1Low = 0x004C, /* Mac address1 low Register */ + GmacAddr2High = 0x0050, /* Mac address2 high Register */ + GmacAddr2Low = 0x0054, /* Mac address2 low Register */ + GmacAddr3High = 0x0058, /* Mac address3 high Register */ + GmacAddr3Low = 0x005C, /* Mac address3 low Register */ + GmacAddr4High = 0x0060, /* Mac address4 high Register */ + GmacAddr4Low = 0x0064, /* Mac address4 low Register */ + GmacAddr5High = 0x0068, /* Mac address5 high Register */ + GmacAddr5Low = 0x006C, /* Mac address5 low Register */ + GmacAddr6High = 0x0070, /* Mac address6 high Register */ + GmacAddr6Low = 0x0074, /* Mac address6 low Register */ + GmacAddr7High = 0x0078, /* Mac address7 high Register */ + GmacAddr7Low = 0x007C, /* Mac address7 low Register */ + GmacAddr8High = 0x0080, /* Mac address8 high Register */ + GmacAddr8Low = 0x0084, /* Mac address8 low Register */ + GmacAddr9High = 0x0088, /* Mac address9 high Register */ + GmacAddr9Low = 0x008C, /* Mac address9 low Register */ + GmacAddr10High = 0x0090, /* Mac address10 high Register */ + GmacAddr10Low = 0x0094, /* Mac address10 low Register */ + GmacAddr11High = 0x0098, /* Mac address11 high Register */ + GmacAddr11Low = 0x009C, /* Mac address11 low Register */ + GmacAddr12High = 0x00A0, /* Mac address12 high Register */ + GmacAddr12Low = 0x00A4, /* Mac address12 low Register */ + GmacAddr13High = 0x00A8, /* Mac address13 high Register */ + GmacAddr13Low = 0x00AC, /* Mac address13 low Register */ + GmacAddr14High = 0x00B0, /* Mac address14 high Register */ + GmacAddr14Low = 0x00B4, /* Mac address14 low Register */ + GmacAddr15High = 0x00B8, /* Mac address15 high Register */ + GmacAddr15Low = 0x00BC, /* Mac address15 low Register */ + GmacStatus = 0x00d8, /* MAC status */ + + /*Time Stamp Register Map*/ + GmacTSControl = 0x0700, /* Controls the Timestamp update logic : only when IEEE 1588 time stamping is enabled in corekit */ + + GmacTSSubSecIncr = 0x0704, /* 8 bit value by which sub second register is incremented : only when IEEE 1588 time stamping without external timestamp input */ + + GmacTSHigh = 0x0708, /* 32 bit seconds(MS) : only when IEEE 1588 time stamping without external timestamp input */ + GmacTSLow = 0x070C, /* 32 bit nano seconds(MS) : only when IEEE 1588 time stamping without external timestamp input */ + + GmacTSHighUpdate = 0x0710, /* 32 bit seconds(MS) to be written/added/subtracted : only when IEEE 1588 time stamping without external timestamp input */ + GmacTSLowUpdate = 0x0714, /* 32 bit nano seconds(MS) to be writeen/added/subtracted : only when IEEE 1588 time stamping without external timestamp input */ + + GmacTSAddend = 0x0718, /* Used by Software to readjust the clock frequency linearly : only when IEEE 1588 time stamping without external timestamp input */ + + GmacTSTargetTimeHigh = 0x071C, /* 32 bit seconds(MS) to be compared with system time : only when IEEE 1588 time stamping without external timestamp input */ + GmacTSTargetTimeLow = 0x0720, /* 32 bit nano seconds(MS) to be compared with system time : only when IEEE 1588 time stamping without external timestamp input */ + + GmacTSHighWord = 0x0724, /* Time Stamp Higher Word Register (Version 2 only); only lower 16 bits are valid */ +//GmacTSHighWordUpdate = 0x072C, /* Time Stamp Higher Word Update Register (Version 2 only); only lower 16 bits are valid */ + + GmacTSStatus = 0x0728, /* Time Stamp Status Register */ +}; + +/********************************************************** + * GMAC Network interface registers + * This explains the Register's Layout + + * FES is Read only by default and is enabled only when Tx + * Config Parameter is enabled for RGMII/SGMII interface + * during CoreKit Config. + + * DM is Read only with value 1'b1 in Full duplex only Config + **********************************************************/ + +/* GmacConfig = 0x0000, Mac config Register Layout */ +enum GmacConfigReg +{ + /* Bit description Bits R/W Reset value */ + GmacWatchdog = 0x00800000, + GmacWatchdogDisable = 0x00800000, /* (WD)Disable watchdog timer on Rx 23 RW */ + GmacWatchdogEnable = 0x00000000, /* Enable watchdog timer 0 */ + + GmacJabber = 0x00400000, + GmacJabberDisable = 0x00400000, /* (JD)Disable jabber timer on Tx 22 RW */ + GmacJabberEnable = 0x00000000, /* Enable jabber timer 0 */ + + GmacFrameBurst = 0x00200000, + GmacFrameBurstEnable = 0x00200000, /* (BE)Enable frame bursting during Tx 21 RW */ + GmacFrameBurstDisable = 0x00000000, /* Disable frame bursting 0 */ + + GmacJumboFrame = 0x00100000, + GmacJumboFrameEnable = 0x00100000, /* (JE)Enable jumbo frame for Tx 20 RW */ + GmacJumboFrameDisable = 0x00000000, /* Disable jumbo frame 0 */ + + GmacInterFrameGap7 = 0x000E0000, /* (IFG) Config7 - 40 bit times 19:17 RW */ + GmacInterFrameGap6 = 0x000C0000, /* (IFG) Config6 - 48 bit times */ + GmacInterFrameGap5 = 0x000A0000, /* (IFG) Config5 - 56 bit times */ + GmacInterFrameGap4 = 0x00080000, /* (IFG) Config4 - 64 bit times */ + GmacInterFrameGap3 = 0x00040000, /* (IFG) Config3 - 72 bit times */ + GmacInterFrameGap2 = 0x00020000, /* (IFG) Config2 - 80 bit times */ + GmacInterFrameGap1 = 0x00010000, /* (IFG) Config1 - 88 bit times */ + GmacInterFrameGap0 = 0x00000000, /* (IFG) Config0 - 96 bit times 000 */ + + GmacDisableCrs = 0x00010000, + GmacMiiGmii = 0x00008000, + GmacSelectMii = 0x00008000, /* (PS)Port Select-MII mode 15 RW */ + GmacSelectGmii = 0x00000000, /* GMII mode 0 */ + + GmacFESpeed100 = 0x00004000, /*(FES)Fast Ethernet speed 100Mbps 14 RW */ + GmacFESpeed10 = 0x00000000, /* 10Mbps 0 */ + + GmacRxOwn = 0x00002000, + GmacDisableRxOwn = 0x00002000, /* (DO)Disable receive own packets 13 RW */ + GmacEnableRxOwn = 0x00000000, /* Enable receive own packets 0 */ + + GmacLoopback = 0x00001000, + GmacLoopbackOn = 0x00001000, /* (LM)Loopback mode for GMII/MII 12 RW */ + GmacLoopbackOff = 0x00000000, /* Normal mode 0 */ + + GmacDuplex = 0x00000800, + GmacFullDuplex = 0x00000800, /* (DM)Full duplex mode 11 RW */ + GmacHalfDuplex = 0x00000000, /* Half duplex mode 0 */ + + GmacRxIpcOffload = 0x00000400, /* IPC checksum offload 10 RW 0 */ + + GmacRetry = 0x00000200, + GmacRetryDisable = 0x00000200, /* (DR)Disable Retry 9 RW */ + GmacRetryEnable = 0x00000000, /* Enable retransmission as per BL 0 */ + + GmacLinkUp = 0x00000100, /* (LUD)Link UP 8 RW */ + GmacLinkDown = 0x00000100, /* Link Down 0 */ + + GmacPadCrcStrip = 0x00000080, + GmacPadCrcStripEnable = 0x00000080, /* (ACS) Automatic Pad/Crc strip enable 7 RW */ + GmacPadCrcStripDisable = 0x00000000, /* Automatic Pad/Crc stripping disable 0 */ + + GmacBackoffLimit = 0x00000060, + GmacBackoffLimit3 = 0x00000060, /* (BL)Back-off limit in HD mode 6:5 RW */ + GmacBackoffLimit2 = 0x00000040, /* */ + GmacBackoffLimit1 = 0x00000020, /* */ + GmacBackoffLimit0 = 0x00000000, /* 00 */ + + GmacDeferralCheck = 0x00000010, + GmacDeferralCheckEnable = 0x00000010, /* (DC)Deferral check enable in HD mode 4 RW */ + GmacDeferralCheckDisable = 0x00000000, /* Deferral check disable 0 */ + + GmacTx = 0x00000008, + GmacTxEnable = 0x00000008, /* (TE)Transmitter enable 3 RW */ + GmacTxDisable = 0x00000000, /* Transmitter disable 0 */ + + GmacRx = 0x00000004, + GmacRxEnable = 0x00000004, /* (RE)Receiver enable 2 RW */ + GmacRxDisable = 0x00000000, /* Receiver disable 0 */ +}; + +/* GmacFrameFilter = 0x0004, Mac frame filtering controls Register Layout*/ +enum GmacFrameFilterReg +{ + GmacFilter = 0x80000000, + GmacFilterOff = 0x80000000, /* (RA)Receive all incoming packets 31 RW */ + GmacFilterOn = 0x00000000, /* Receive filtered packets only 0 */ + + GmacHashPerfectFilter = 0x00000400, /*Hash or Perfect Filter enable 10 RW 0 */ + + GmacSrcAddrFilter = 0x00000200, + GmacSrcAddrFilterEnable = 0x00000200, /* (SAF)Source Address Filter enable 9 RW */ + GmacSrcAddrFilterDisable = 0x00000000, /* 0 */ + + GmacSrcInvaAddrFilter = 0x00000100, + GmacSrcInvAddrFilterEn = 0x00000100, /* (SAIF)Inv Src Addr Filter enable 8 RW */ + GmacSrcInvAddrFilterDis = 0x00000000, /* 0 */ + + GmacPassControl = 0x000000C0, + GmacPassControl3 = 0x000000C0, /* (PCS)Forwards ctrl frms that pass AF 7:6 RW */ + GmacPassControl2 = 0x00000080, /* Forwards all control frames */ + GmacPassControl1 = 0x00000040, /* Does not pass control frames */ + GmacPassControl0 = 0x00000000, /* Does not pass control frames 00 */ + + GmacBroadcast = 0x00000020, + GmacBroadcastDisable = 0x00000020, /* (DBF)Disable Rx of broadcast frames 5 RW */ + GmacBroadcastEnable = 0x00000000, /* Enable broadcast frames 0 */ + + GmacMulticastFilter = 0x00000010, + GmacMulticastFilterOff = 0x00000010, /* (PM) Pass all multicast packets 4 RW */ + GmacMulticastFilterOn = 0x00000000, /* Pass filtered multicast packets 0 */ + + GmacDestAddrFilter = 0x00000008, + GmacDestAddrFilterInv = 0x00000008, /* (DAIF)Inverse filtering for DA 3 RW */ + GmacDestAddrFilterNor = 0x00000000, /* Normal filtering for DA 0 */ + + GmacMcastHashFilter = 0x00000004, + GmacMcastHashFilterOn = 0x00000004, /* (HMC)perfom multicast hash filtering 2 RW */ + GmacMcastHashFilterOff = 0x00000000, /* perfect filtering only 0 */ + + GmacUcastHashFilter = 0x00000002, + GmacUcastHashFilterOn = 0x00000002, /* (HUC)Unicast Hash filtering only 1 RW */ + GmacUcastHashFilterOff = 0x00000000, /* perfect filtering only 0 */ + + GmacPromiscuousMode = 0x00000001, + GmacPromiscuousModeOn = 0x00000001, /* Receive all frames 0 RW */ + GmacPromiscuousModeOff = 0x00000000, /* Receive filtered packets only 0 */ +}; + +/*GmacGmiiAddr = 0x0010, GMII address Register(ext. Phy) Layout */ +enum GmacGmiiAddrReg +{ + GmiiDevMask = 0x0000F800, /* (PA)GMII device address 15:11 RW 0x00 */ + GmiiDevShift = 11, + + GmiiRegMask = 0x000007C0, /* (GR)GMII register in selected Phy 10:6 RW 0x00 */ + GmiiRegShift = 6, + + GmiiCsrClkMask = 0x0000001C, /* CSR Clock bit Mask 4:2 */ + GmiiCsrClk5 = 0x00000014, /* (CR)CSR Clock Range 250-300 MHz 4:2 RW 000 */ + GmiiCsrClk4 = 0x00000010, /* 150-250 MHz */ + GmiiCsrClk3 = 0x0000000C, /* 35-60 MHz */ + GmiiCsrClk2 = 0x00000008, /* 20-35 MHz */ + GmiiCsrClk1 = 0x00000004, /* 100-150 MHz */ + GmiiCsrClk0 = 0x00000000, /* 60-100 MHz */ + + GmiiWrite = 0x00000002, /* (GW)Write to register 1 RW */ + GmiiRead = 0x00000000, /* Read from register 0 */ + + GmiiBusy = 0x00000001, /* (GB)GMII interface is busy 0 RW 0 */ +}; + +/* GmacGmiiData = 0x0014, GMII data Register(ext. Phy) Layout */ +enum GmacGmiiDataReg +{ + GmiiDataMask = 0x0000FFFF, /* (GD)GMII Data 15:0 RW 0x0000 */ +}; + +/*GmacFlowControl = 0x0018, Flow control Register Layout */ +enum GmacFlowControlReg +{ + GmacPauseTimeMask = 0xFFFF0000, /* (PT) PAUSE TIME field in the control frame 31:16 RW 0x0000 */ + GmacPauseTimeShift = 16, + + GmacPauseLowThresh = 0x00000030, + GmacPauseLowThresh3 = 0x00000030, /* (PLT)thresh for pause tmr 256 slot time 5:4 RW */ + GmacPauseLowThresh2 = 0x00000020, /* 144 slot time */ + GmacPauseLowThresh1 = 0x00000010, /* 28 slot time */ + GmacPauseLowThresh0 = 0x00000000, /* 4 slot time 000 */ + + GmacUnicastPauseFrame = 0x00000008, + GmacUnicastPauseFrameOn = 0x00000008, /* (UP)Detect pause frame with unicast addr. 3 RW */ + GmacUnicastPauseFrameOff = 0x00000000, /* Detect only pause frame with multicast addr. 0 */ + + GmacRxFlowControl = 0x00000004, + GmacRxFlowControlEnable = 0x00000004, /* (RFE)Enable Rx flow control 2 RW */ + GmacRxFlowControlDisable = 0x00000000, /* Disable Rx flow control 0 */ + + GmacTxFlowControl = 0x00000002, + GmacTxFlowControlEnable = 0x00000002, /* (TFE)Enable Tx flow control 1 RW */ + GmacTxFlowControlDisable = 0x00000000, /* Disable flow control 0 */ + + GmacFlowControlBackPressure= 0x00000001, + GmacSendPauseFrame = 0x00000001, /* (FCB/PBA)send pause frm/Apply back pressure 0 RW 0 */ +}; + +/* GmacInterruptStatus = 0x0038, Mac Interrupt ststus register */ +enum GmacInterruptStatusBitDefinition +{ + GmacTSIntSts = 0x00000200, /* set if int generated due to TS (Read Time Stamp Status Register to know details)*/ + GmacMmcRxChksumOffload = 0x00000080, /* set if int generated in MMC RX CHECKSUM OFFLOAD int register */ + GmacMmcTxIntSts = 0x00000040, /* set if int generated in MMC TX Int register */ + GmacMmcRxIntSts = 0x00000020, /* set if int generated in MMC RX Int register */ + GmacMmcIntSts = 0x00000010, /* set if any of the above bit [7:5] is set */ + GmacPmtIntSts = 0x00000008, /* set whenver magic pkt/wake-on-lan frame is received */ + GmacPcsAnComplete = 0x00000004, /* set when AN is complete in TBI/RTBI/SGMIII phy interface */ + GmacPcsLnkStsChange = 0x00000002, /* set if any lnk status change in TBI/RTBI/SGMII interface */ + GmacRgmiiIntSts = 0x00000001, /* set if any change in lnk status of RGMII interface */ +}; + +/* GmacInterruptMask = 0x003C, Mac Interrupt Mask register */ +enum GmacInterruptMaskBitDefinition +{ + GmacTSIntMask = 0x00000200, /* when set disables the time stamp interrupt generation */ + GmacPmtIntMask = 0x00000008, /* when set Disables the assertion of PMT interrupt */ + GmacPcsAnIntMask = 0x00000004, /* When set disables the assertion of PCS AN complete interrupt */ + GmacPcsLnkStsIntMask = 0x00000002, /* when set disables the assertion of PCS lnk status change interrupt */ + GmacRgmiiIntMask = 0x00000001, /* when set disables the assertion of RGMII int */ +}; + +/********************************************************** + * GMAC DMA registers + * For Pci based system address is BARx + GmaDmaBase + * For any other system translation is done accordingly + **********************************************************/ +enum DmaRegisters +{ + DmaBusMode = 0x0000, /* CSR0 - Bus Mode Register */ + DmaTxPollDemand = 0x0004, /* CSR1 - Transmit Poll Demand Register */ + DmaRxPollDemand = 0x0008, /* CSR2 - Receive Poll Demand Register */ + DmaRxBaseAddr = 0x000C, /* CSR3 - Receive Descriptor list base address */ + DmaTxBaseAddr = 0x0010, /* CSR4 - Transmit Descriptor list base address */ + DmaStatus = 0x0014, /* CSR5 - Dma status Register */ + DmaControl = 0x0018, /* CSR6 - Dma Operation Mode Register */ + DmaInterrupt = 0x001C, /* CSR7 - Interrupt enable */ + DmaMissedFr = 0x0020, /* CSR8 - Missed Frame & Buffer overflow Counter */ + DmaTxCurrDesc = 0x0048, /* - Current host Tx Desc Register */ + DmaRxCurrDesc = 0x004C, /* - Current host Rx Desc Register */ + DmaTxCurrAddr = 0x0050, /* CSR20 - Current host transmit buffer address */ + DmaRxCurrAddr = 0x0054, /* CSR21 - Current host receive buffer address */ +}; + +/********************************************************** + * DMA Engine registers Layout + **********************************************************/ + +/*DmaBusMode = 0x0000, CSR0 - Bus Mode */ +enum DmaBusModeReg +{ /* Bit description Bits R/W Reset value */ + DmaFixedBurstEnable = 0x00010000, /* (FB)Fixed Burst SINGLE, INCR4, INCR8 or INCR16 16 RW */ + DmaFixedBurstDisable = 0x00000000, /* SINGLE, INCR 0 */ + + DmaTxPriorityRatio11 = 0x00000000, /* (PR)TX:RX DMA priority ratio 1:1 15:14 RW 00 */ + DmaTxPriorityRatio21 = 0x00004000, /* (PR)TX:RX DMA priority ratio 2:1 */ + DmaTxPriorityRatio31 = 0x00008000, /* (PR)TX:RX DMA priority ratio 3:1 */ + DmaTxPriorityRatio41 = 0x0000C000, /* (PR)TX:RX DMA priority ratio 4:1 */ + + DmaBurstLengthx8 = 0x01000000, /* When set mutiplies the PBL by 8 24 RW 0 */ + + DmaBurstLength256 = 0x01002000, /*(DmaBurstLengthx8 | DmaBurstLength32) = 256 [24]:13:8 */ + DmaBurstLength128 = 0x01001000, /*(DmaBurstLengthx8 | DmaBurstLength16) = 128 [24]:13:8 */ + DmaBurstLength64 = 0x01000800, /*(DmaBurstLengthx8 | DmaBurstLength8) = 64 [24]:13:8 */ + DmaBurstLength32 = 0x00002000, /* (PBL) programmable Dma burst length = 32 13:8 RW */ + DmaBurstLength16 = 0x00001000, /* Dma burst length = 16 */ + DmaBurstLength8 = 0x00000800, /* Dma burst length = 8 */ + DmaBurstLength4 = 0x00000400, /* Dma burst length = 4 */ + DmaBurstLength2 = 0x00000200, /* Dma burst length = 2 */ + DmaBurstLength1 = 0x00000100, /* Dma burst length = 1 */ + DmaBurstLength0 = 0x00000000, /* Dma burst length = 0 0x00 */ + + DmaDescriptor8Words = 0x00000080, /* Enh Descriptor works 1=> 8 word descriptor 7 0 */ + DmaDescriptor4Words = 0x00000000, /* Enh Descriptor works 0=> 4 word descriptor 7 0 */ + + DmaDescriptorSkip16 = 0x00000040, /* (DSL)Descriptor skip length (no.of dwords) 6:2 RW */ + DmaDescriptorSkip8 = 0x00000020, /* between two unchained descriptors */ + DmaDescriptorSkip4 = 0x00000010, /* */ + DmaDescriptorSkip2 = 0x00000008, /* */ + DmaDescriptorSkip1 = 0x00000004, /* */ + DmaDescriptorSkip0 = 0x00000000, /* 0x00 */ + + DmaArbitRr = 0x00000000, /* (DA) DMA RR arbitration 1 RW 0 */ + DmaArbitPr = 0x00000002, /* Rx has priority over Tx */ + + DmaResetOn = 0x00000001, /* (SWR)Software Reset DMA engine 0 RW */ + DmaResetOff = 0x00000000, /* 0 */ +}; + +/*DmaStatus = 0x0014, CSR5 - Dma status Register */ +enum DmaStatusReg +{ + /*Bit 28 27 and 26 indicate whether the interrupt due to PMT GMACMMC or GMAC LINE Remaining bits are DMA interrupts*/ + GmacPmtIntr = 0x10000000, /* (GPI)Gmac subsystem interrupt 28 RO 0 */ + GmacMmcIntr = 0x08000000, /* (GMI)Gmac MMC subsystem interrupt 27 RO 0 */ + GmacLineIntfIntr = 0x04000000, /* Line interface interrupt 26 RO 0 */ + + DmaErrorBit2 = 0x02000000, /* (EB)Error bits 0-data buffer, 1-desc. access 25 RO 0 */ + DmaErrorBit1 = 0x01000000, /* (EB)Error bits 0-write trnsf, 1-read transfr 24 RO 0 */ + DmaErrorBit0 = 0x00800000, /* (EB)Error bits 0-Rx DMA, 1-Tx DMA 23 RO 0 */ + + DmaTxState = 0x00700000, /* (TS)Transmit process state 22:20 RO */ + DmaTxStopped = 0x00000000, /* Stopped - Reset or Stop Tx Command issued 000 */ + DmaTxFetching = 0x00100000, /* Running - fetching the Tx descriptor */ + DmaTxWaiting = 0x00200000, /* Running - waiting for status */ + DmaTxReading = 0x00300000, /* Running - reading the data from host memory */ + DmaTxSuspended = 0x00600000, /* Suspended - Tx Descriptor unavailabe */ + DmaTxClosing = 0x00700000, /* Running - closing Rx descriptor */ + + DmaRxState = 0x000E0000, /* (RS)Receive process state 19:17 RO */ + DmaRxStopped = 0x00000000, /* Stopped - Reset or Stop Rx Command issued 000 */ + DmaRxFetching = 0x00020000, /* Running - fetching the Rx descriptor */ + DmaRxWaiting = 0x00060000, /* Running - waiting for packet */ + DmaRxSuspended = 0x00080000, /* Suspended - Rx Descriptor unavailable */ + DmaRxClosing = 0x000A0000, /* Running - closing descriptor */ + DmaRxQueuing = 0x000E0000, /* Running - queuing the recieve frame into host memory */ + + DmaIntNormal = 0x00010000, /* (NIS)Normal interrupt summary 16 RW 0 */ + DmaIntAbnormal = 0x00008000, /* (AIS)Abnormal interrupt summary 15 RW 0 */ + + DmaIntEarlyRx = 0x00004000, /* Early receive interrupt (Normal) RW 0 */ + DmaIntBusError = 0x00002000, /* Fatal bus error (Abnormal) RW 0 */ + DmaIntEarlyTx = 0x00000400, /* Early transmit interrupt (Abnormal) RW 0 */ + DmaIntRxWdogTO = 0x00000200, /* Receive Watchdog Timeout (Abnormal) RW 0 */ + DmaIntRxStopped = 0x00000100, /* Receive process stopped (Abnormal) RW 0 */ + DmaIntRxNoBuffer = 0x00000080, /* Receive buffer unavailable (Abnormal) RW 0 */ + DmaIntRxCompleted = 0x00000040, /* Completion of frame reception (Normal) RW 0 */ + DmaIntTxUnderflow = 0x00000020, /* Transmit underflow (Abnormal) RW 0 */ + DmaIntRcvOverflow = 0x00000010, /* Receive Buffer overflow interrupt RW 0 */ + DmaIntTxJabberTO = 0x00000008, /* Transmit Jabber Timeout (Abnormal) RW 0 */ + DmaIntTxNoBuffer = 0x00000004, /* Transmit buffer unavailable (Normal) RW 0 */ + DmaIntTxStopped = 0x00000002, /* Transmit process stopped (Abnormal) RW 0 */ + DmaIntTxCompleted = 0x00000001, /* Transmit completed (Normal) RW 0 */ +}; + +/*DmaControl = 0x0018, CSR6 - Dma Operation Mode Register */ +enum DmaControlReg +{ + DmaDisableDropTcpCs = 0x04000000, /* (DT) Dis. drop. of tcp/ip CS error frames 26 RW 0 */ + + DmaStoreAndForward = 0x02200000, /* (SF)Store and forward 21 RW 0 */ + DmaFlushTxFifo = 0x00100000, /* (FTF)Tx FIFO controller is reset to default 20 RW 0 */ + + DmaTxThreshCtrl = 0x0001C000, /* (TTC)Controls thre Threh of MTL tx Fifo 16:14 RW */ + DmaTxThreshCtrl16 = 0x0001C000, /* (TTC)Controls thre Threh of MTL tx Fifo 16 16:14 RW */ + DmaTxThreshCtrl24 = 0x00018000, /* (TTC)Controls thre Threh of MTL tx Fifo 24 16:14 RW */ + DmaTxThreshCtrl32 = 0x00014000, /* (TTC)Controls thre Threh of MTL tx Fifo 32 16:14 RW */ + DmaTxThreshCtrl40 = 0x00010000, /* (TTC)Controls thre Threh of MTL tx Fifo 40 16:14 RW */ + DmaTxThreshCtrl256 = 0x0000c000, /* (TTC)Controls thre Threh of MTL tx Fifo 256 16:14 RW */ + DmaTxThreshCtrl192 = 0x00008000, /* (TTC)Controls thre Threh of MTL tx Fifo 192 16:14 RW */ + DmaTxThreshCtrl128 = 0x00004000, /* (TTC)Controls thre Threh of MTL tx Fifo 128 16:14 RW */ + DmaTxThreshCtrl64 = 0x00000000, /* (TTC)Controls thre Threh of MTL tx Fifo 64 16:14 RW 000 */ + + DmaTxStart = 0x00002000, /* (ST)Start/Stop transmission 13 RW 0 */ + + DmaRxFlowCtrlDeact = 0x00401800, /* (RFD)Rx flow control deact. threhold [22]:12:11 RW */ + DmaRxFlowCtrlDeact1K = 0x00000000, /* (RFD)Rx flow control deact. threhold (1kbytes) [22]:12:11 RW 00 */ + DmaRxFlowCtrlDeact2K = 0x00000800, /* (RFD)Rx flow control deact. threhold (2kbytes) [22]:12:11 RW */ + DmaRxFlowCtrlDeact3K = 0x00001000, /* (RFD)Rx flow control deact. threhold (3kbytes) [22]:12:11 RW */ + DmaRxFlowCtrlDeact4K = 0x00001800, /* (RFD)Rx flow control deact. threhold (4kbytes) [22]:12:11 RW */ + DmaRxFlowCtrlDeact5K = 0x00400000, /* (RFD)Rx flow control deact. threhold (4kbytes) [22]:12:11 RW */ + DmaRxFlowCtrlDeact6K = 0x00400800, /* (RFD)Rx flow control deact. threhold (4kbytes) [22]:12:11 RW */ + DmaRxFlowCtrlDeact7K = 0x00401000, /* (RFD)Rx flow control deact. threhold (4kbytes) [22]:12:11 RW */ + + DmaRxFlowCtrlAct = 0x00800600, /* (RFA)Rx flow control Act. threhold [23]:10:09 RW */ + DmaRxFlowCtrlAct1K = 0x00000000, /* (RFA)Rx flow control Act. threhold (1kbytes) [23]:10:09 RW 00 */ + DmaRxFlowCtrlAct2K = 0x00000200, /* (RFA)Rx flow control Act. threhold (2kbytes) [23]:10:09 RW */ + DmaRxFlowCtrlAct3K = 0x00000400, /* (RFA)Rx flow control Act. threhold (3kbytes) [23]:10:09 RW */ + DmaRxFlowCtrlAct4K = 0x00000600, /* (RFA)Rx flow control Act. threhold (4kbytes) [23]:10:09 RW */ + DmaRxFlowCtrlAct5K = 0x00800000, /* (RFA)Rx flow control Act. threhold (5kbytes) [23]:10:09 RW */ + DmaRxFlowCtrlAct6K = 0x00800200, /* (RFA)Rx flow control Act. threhold (6kbytes) [23]:10:09 RW */ + DmaRxFlowCtrlAct7K = 0x00800400, /* (RFA)Rx flow control Act. threhold (7kbytes) [23]:10:09 RW */ + + DmaRxThreshCtrl = 0x00000018, /* (RTC)Controls thre Threh of MTL rx Fifo 4:3 RW */ + DmaRxThreshCtrl64 = 0x00000000, /* (RTC)Controls thre Threh of MTL tx Fifo 64 4:3 RW */ + DmaRxThreshCtrl32 = 0x00000008, /* (RTC)Controls thre Threh of MTL tx Fifo 32 4:3 RW */ + DmaRxThreshCtrl96 = 0x00000010, /* (RTC)Controls thre Threh of MTL tx Fifo 96 4:3 RW */ + DmaRxThreshCtrl128 = 0x00000018, /* (RTC)Controls thre Threh of MTL tx Fifo 128 4:3 RW */ + + DmaEnHwFlowCtrl = 0x00000100, /* (EFC)Enable HW flow control 8 RW */ + DmaDisHwFlowCtrl = 0x00000000, /* Disable HW flow control 0 */ + + DmaFwdErrorFrames = 0x00000080, /* (FEF)Forward error frames 7 RW 0 */ + DmaFwdUnderSzFrames = 0x00000040, /* (FUF)Forward undersize frames 6 RW 0 */ + DmaTxSecondFrame = 0x00000004, /* (OSF)Operate on second frame 4 RW 0 */ + DmaRxStart = 0x00000002, /* (SR)Start/Stop reception 1 RW 0 */ +}; + + +/*DmaInterrupt = 0x001C, CSR7 - Interrupt enable Register Layout */ +enum DmaInterruptReg +{ + DmaIeNormal = DmaIntNormal , /* Normal interrupt enable RW 0 */ + DmaIeAbnormal = DmaIntAbnormal , /* Abnormal interrupt enable RW 0 */ + + DmaIeEarlyRx = DmaIntEarlyRx , /* Early receive interrupt enable RW 0 */ + DmaIeBusError = DmaIntBusError , /* Fatal bus error enable RW 0 */ + DmaIeEarlyTx = DmaIntEarlyTx , /* Early transmit interrupt enable RW 0 */ + DmaIeRxWdogTO = DmaIntRxWdogTO , /* Receive Watchdog Timeout enable RW 0 */ + DmaIeRxStopped = DmaIntRxStopped , /* Receive process stopped enable RW 0 */ + DmaIeRxNoBuffer = DmaIntRxNoBuffer , /* Receive buffer unavailable enable RW 0 */ + DmaIeRxCompleted = DmaIntRxCompleted, /* Completion of frame reception enable RW 0 */ + DmaIeTxUnderflow = DmaIntTxUnderflow, /* Transmit underflow enable RW 0 */ + + DmaIeRxOverflow = DmaIntRcvOverflow, /* Receive Buffer overflow interrupt RW 0 */ + DmaIeTxJabberTO = DmaIntTxJabberTO , /* Transmit Jabber Timeout enable RW 0 */ + DmaIeTxNoBuffer = DmaIntTxNoBuffer , /* Transmit buffer unavailable enable RW 0 */ + DmaIeTxStopped = DmaIntTxStopped , /* Transmit process stopped enable RW 0 */ + DmaIeTxCompleted = DmaIntTxCompleted, /* Transmit completed enable RW 0 */ +}; + + + +/********************************************************** + * DMA Engine descriptors + **********************************************************/ +#ifdef ENH_DESC +/* +**********Enhanced Descritpor structure to support 8K buffer per buffer **************************** + +DmaRxBaseAddr = 0x000C, CSR3 - Receive Descriptor list base address +DmaRxBaseAddr is the pointer to the first Rx Descriptors. the Descriptor format in Little endian with a +32 bit Data bus is as shown below + +Similarly +DmaTxBaseAddr = 0x0010, CSR4 - Transmit Descriptor list base address +DmaTxBaseAddr is the pointer to the first Rx Descriptors. the Descriptor format in Little endian with a +32 bit Data bus is as shown below + -------------------------------------------------------------------------- + RDES0 |OWN (31)| Status | + -------------------------------------------------------------------------- + RDES1 | Ctrl | Res | Byte Count Buffer 2 | Ctrl | Res | Byte Count Buffer 1 | + -------------------------------------------------------------------------- + RDES2 | Buffer 1 Address | + -------------------------------------------------------------------------- + RDES3 | Buffer 2 Address / Next Descriptor Address | + -------------------------------------------------------------------------- + + -------------------------------------------------------------------------- + TDES0 |OWN (31)| Ctrl | Res | Ctrl | Res | Status | + -------------------------------------------------------------------------- + TDES1 | Res | Byte Count Buffer 2 | Res | Byte Count Buffer 1 | + -------------------------------------------------------------------------- + TDES2 | Buffer 1 Address | + -------------------------------------------------------------------------- + TDES3 | Buffer 2 Address / Next Descriptor Address | + -------------------------------------------------------------------------- + +*/ + +enum DmaDescriptorStatus /* status word of DMA descriptor */ +{ + DescOwnByDma = 0x80000000, /* (OWN)Descriptor is owned by DMA engine 31 RW */ + + DescDAFilterFail = 0x40000000, /* (AFM)Rx - DA Filter Fail for the rx frame 30 */ + + DescFrameLengthMask = 0x3FFF0000, /* (FL)Receive descriptor frame length 29:16 */ + DescFrameLengthShift = 16, + + DescError = 0x00008000, /* (ES)Error summary bit - OR of the follo. bits: 15 */ + /* DE || OE || IPC || LC || RWT || RE || CE */ + DescRxTruncated = 0x00004000, /* (DE)Rx - no more descriptors for receive frame 14 */ + DescSAFilterFail = 0x00002000, /* (SAF)Rx - SA Filter Fail for the received frame 13 */ + DescRxLengthError = 0x00001000, /* (LE)Rx - frm size not matching with len field 12 */ + DescRxDamaged = 0x00000800, /* (OE)Rx - frm was damaged due to buffer overflow 11 */ + DescRxVLANTag = 0x00000400, /* (VLAN)Rx - received frame is a VLAN frame 10 */ + DescRxFirst = 0x00000200, /* (FS)Rx - first descriptor of the frame 9 */ + DescRxLast = 0x00000100, /* (LS)Rx - last descriptor of the frame 8 */ + DescRxLongFrame = 0x00000080, /* (Giant Frame)Rx - frame is longer than 1518/1522 7 */ + DescRxCollision = 0x00000040, /* (LC)Rx - late collision occurred during reception 6 */ + DescRxFrameEther = 0x00000020, /* (FT)Rx - Frame type - Ethernet, otherwise 802.3 5 */ + DescRxWatchdog = 0x00000010, /* (RWT)Rx - watchdog timer expired during reception 4 */ + DescRxMiiError = 0x00000008, /* (RE)Rx - error reported by MII interface 3 */ + DescRxDribbling = 0x00000004, /* (DE)Rx - frame contains non int multiple of 8 bits 2 */ + DescRxCrc = 0x00000002, /* (CE)Rx - CRC error 1 */ +// DescRxMacMatch = 0x00000001, /* (RX MAC Address) Rx mac address reg(1 to 15)match 0 */ + + DescRxEXTsts = 0x00000001, /* Extended Status Available (RDES4) 0 */ + + DescTxIntEnable = 0x40000000, /* (IC)Tx - interrupt on completion 30 */ + DescTxLast = 0x20000000, /* (LS)Tx - Last segment of the frame 29 */ + DescTxFirst = 0x10000000, /* (FS)Tx - First segment of the frame 28 */ + DescTxDisableCrc = 0x08000000, /* (DC)Tx - Add CRC disabled (first segment only) 27 */ + DescTxDisablePadd = 0x04000000, /* (DP)disable padding, added by - reyaz 26 */ + + DescTxCisMask = 0x00c00000, /* Tx checksum offloading control mask 23:22 */ + DescTxCisBypass = 0x00000000, /* Checksum bypass */ + DescTxCisIpv4HdrCs = 0x00400000, /* IPv4 header checksum */ + DescTxCisTcpOnlyCs = 0x00800000, /* TCP/UDP/ICMP checksum. Pseudo header checksum is assumed to be present */ + DescTxCisTcpPseudoCs = 0x00c00000, /* TCP/UDP/ICMP checksum fully in hardware including pseudo header */ + + TxDescEndOfRing = 0x00200000, /* (TER)End of descriptors ring 21 */ + TxDescChain = 0x00100000, /* (TCH)Second buffer address is chain address 20 */ + + DescRxChkBit0 = 0x00000001, /*() Rx - Rx Payload Checksum Error 0 */ + DescRxChkBit7 = 0x00000080, /* (IPC CS ERROR)Rx - Ipv4 header checksum error 7 */ + DescRxChkBit5 = 0x00000020, /* (FT)Rx - Frame type - Ethernet, otherwise 802.3 5 */ + + DescRxTSavail = 0x00000080, /* Time stamp available 7 */ + DescRxFrameType = 0x00000020, /* (FT)Rx - Frame type - Ethernet, otherwise 802.3 5 */ + + DescTxIpv4ChkError = 0x00010000, /* (IHE) Tx Ip header error 16 */ + DescTxTimeout = 0x00004000, /* (JT)Tx - Transmit jabber timeout 14 */ + DescTxFrameFlushed = 0x00002000, /* (FF)Tx - DMA/MTL flushed the frame due to SW flush 13 */ + DescTxPayChkError = 0x00001000, /* (PCE) Tx Payload checksum Error 12 */ + DescTxLostCarrier = 0x00000800, /* (LC)Tx - carrier lost during tramsmission 11 */ + DescTxNoCarrier = 0x00000400, /* (NC)Tx - no carrier signal from the tranceiver 10 */ + DescTxLateCollision = 0x00000200, /* (LC)Tx - transmission aborted due to collision 9 */ + DescTxExcCollisions = 0x00000100, /* (EC)Tx - transmission aborted after 16 collisions 8 */ + DescTxVLANFrame = 0x00000080, /* (VF)Tx - VLAN-type frame 7 */ + + DescTxCollMask = 0x00000078, /* (CC)Tx - Collision count 6:3 */ + DescTxCollShift = 3, + + DescTxExcDeferral = 0x00000004, /* (ED)Tx - excessive deferral 2 */ + DescTxUnderflow = 0x00000002, /* (UF)Tx - late data arrival from the memory 1 */ + DescTxDeferred = 0x00000001, /* (DB)Tx - frame transmision deferred 0 */ + /* + This explains the RDES1/TDES1 bits layout + -------------------------------------------------------------------- + RDES1/TDES1 | Control Bits | Byte Count Buffer 2 | Byte Count Buffer 1 | + -------------------------------------------------------------------- + */ +// DmaDescriptorLength length word of DMA descriptor + RxDisIntCompl = 0x80000000, /* (Disable Rx int on completion) 31 */ + RxDescEndOfRing = 0x00008000, /* (TER)End of descriptors ring 15 */ + RxDescChain = 0x00004000, /* (TCH)Second buffer address is chain address 14 */ + + DescSize2Mask = 0x1FFF0000, /* (TBS2) Buffer 2 size 28:16 */ + DescSize2Shift = 16, + DescSize1Mask = 0x00001FFF, /* (TBS1) Buffer 1 size 12:0 */ + DescSize1Shift = 0, + /* + This explains the RDES4 Extended Status bits layout + -------------------------------------------------------------------- + RDES4 | Extended Status | + -------------------------------------------------------------------- + */ + DescRxPtpAvail = 0x00004000, /* PTP snapshot available 14 */ + DescRxPtpVer = 0x00002000, /* When set indicates IEEE1584 Version 2 (else Ver1) 13 */ + DescRxPtpFrameType = 0x00001000, /* PTP frame type Indicates PTP sent over ethernet 12 */ + DescRxPtpMessageType = 0x00000F00, /* Message Type 11:8 */ + DescRxPtpNo = 0x00000000, /* 0000 => No PTP message received */ + DescRxPtpSync = 0x00000100, /* 0001 => Sync (all clock types) received */ + DescRxPtpFollowUp = 0x00000200, /* 0010 => Follow_Up (all clock types) received */ + DescRxPtpDelayReq = 0x00000300, /* 0011 => Delay_Req (all clock types) received */ + DescRxPtpDelayResp = 0x00000400, /* 0100 => Delay_Resp (all clock types) received */ + DescRxPtpPdelayReq = 0x00000500, /* 0101 => Pdelay_Req (in P to P tras clk) or Announce in Ord and Bound clk */ + DescRxPtpPdelayResp = 0x00000600, /* 0110 => Pdealy_Resp(in P to P trans clk) or Management in Ord and Bound clk */ + DescRxPtpPdelayRespFP = 0x00000700, /* 0111 => Pdealy_Resp_Follow_Up (in P to P trans clk) or Signaling in Ord and Bound clk */ + DescRxPtpIPV6 = 0x00000080, /* Received Packet is in IPV6 Packet 7 */ + DescRxPtpIPV4 = 0x00000040, /* Received Packet is in IPV4 Packet 6 */ + + DescRxChkSumBypass = 0x00000020, /* When set indicates checksum offload engine 5 + is bypassed */ + DescRxIpPayloadError = 0x00000010, /* When set indicates 16bit IP payload CS is in error 4 */ + DescRxIpHeaderError = 0x00000008, /* When set indicates 16bit IPV4 header CS is in 3 + error or IP datagram version is not consistent + with Ethernet type value */ + DescRxIpPayloadType = 0x00000007, /* Indicate the type of payload encapsulated 2:0 + in IPdatagram processed by COE (Rx) */ + DescRxIpPayloadUnknown= 0x00000000, /* Unknown or didnot process IP payload */ + DescRxIpPayloadUDP = 0x00000001, /* UDP */ + DescRxIpPayloadTCP = 0x00000002, /* TCP */ + DescRxIpPayloadICMP = 0x00000003, /* ICMP */ + +}; + +#else +/* + +********** Default Descritpor structure **************************** +DmaRxBaseAddr = 0x000C, CSR3 - Receive Descriptor list base address +DmaRxBaseAddr is the pointer to the first Rx Descriptors. the Descriptor format in Little endian with a +32 bit Data bus is as shown below + +Similarly +DmaTxBaseAddr = 0x0010, CSR4 - Transmit Descriptor list base address +DmaTxBaseAddr is the pointer to the first Rx Descriptors. the Descriptor format in Little endian with a +32 bit Data bus is as shown below + -------------------------------------------------------------------- + RDES0/TDES0 |OWN (31)| Status | + -------------------------------------------------------------------- + RDES1/TDES1 | Control Bits | Byte Count Buffer 2 | Byte Count Buffer 1 | + -------------------------------------------------------------------- + RDES2/TDES2 | Buffer 1 Address | + -------------------------------------------------------------------- + RDES3/TDES3 | Buffer 2 Address / Next Descriptor Address | + -------------------------------------------------------------------- +*/ +enum DmaDescriptorStatus /* status word of DMA descriptor */ +{ + DescOwnByDma = 0x80000000, /* (OWN)Descriptor is owned by DMA engine 31 RW */ + + DescDAFilterFail = 0x40000000, /* (AFM)Rx - DA Filter Fail for the rx frame 30 */ + + DescFrameLengthMask = 0x3FFF0000, /* (FL)Receive descriptor frame length 29:16 */ + DescFrameLengthShift = 16, + + DescError = 0x00008000, /* (ES)Error summary bit - OR of the follo. bits: 15 */ + /* DE || OE || IPC || LC || RWT || RE || CE */ + DescRxTruncated = 0x00004000, /* (DE)Rx - no more descriptors for receive frame 14 */ + DescSAFilterFail = 0x00002000, /* (SAF)Rx - SA Filter Fail for the received frame 13 */ + DescRxLengthError = 0x00001000, /* (LE)Rx - frm size not matching with len field 12 */ + DescRxDamaged = 0x00000800, /* (OE)Rx - frm was damaged due to buffer overflow 11 */ + DescRxVLANTag = 0x00000400, /* (VLAN)Rx - received frame is a VLAN frame 10 */ + DescRxFirst = 0x00000200, /* (FS)Rx - first descriptor of the frame 9 */ + DescRxLast = 0x00000100, /* (LS)Rx - last descriptor of the frame 8 */ + DescRxLongFrame = 0x00000080, /* (Giant Frame)Rx - frame is longer than 1518/1522 7 */ + DescRxCollision = 0x00000040, /* (LC)Rx - late collision occurred during reception 6 */ + DescRxFrameEther = 0x00000020, /* (FT)Rx - Frame type - Ethernet, otherwise 802.3 5 */ + DescRxWatchdog = 0x00000010, /* (RWT)Rx - watchdog timer expired during reception 4 */ + DescRxMiiError = 0x00000008, /* (RE)Rx - error reported by MII interface 3 */ + DescRxDribbling = 0x00000004, /* (DE)Rx - frame contains non int multiple of 8 bits 2 */ + DescRxCrc = 0x00000002, /* (CE)Rx - CRC error 1 */ + DescRxMacMatch = 0x00000001, /* (RX MAC Address) Rx mac address reg(1 to 15)match 0 */ + +//Rx Descriptor Checksum Offload engine (type 2) encoding +//DescRxPayChkError = 0x00000001, /* () Rx - Rx Payload Checksum Error 0 */ +//DescRxIpv4ChkError = 0x00000080, /* (IPC CS ERROR)Rx - Ipv4 header checksum error 7 */ + + DescRxChkBit0 = 0x00000001, /*() Rx - Rx Payload Checksum Error 0 */ + DescRxChkBit7 = 0x00000080, /* (IPC CS ERROR)Rx - Ipv4 header checksum error 7 */ + DescRxChkBit5 = 0x00000020, /* (FT)Rx - Frame type - Ethernet, otherwise 802.3 5 */ + + DescTxIpv4ChkError = 0x00010000, /* (IHE) Tx Ip header error 16 */ + DescTxTimeout = 0x00004000, /* (JT)Tx - Transmit jabber timeout 14 */ + DescTxFrameFlushed = 0x00002000, /* (FF)Tx - DMA/MTL flushed the frame due to SW flush 13 */ + DescTxPayChkError = 0x00001000, /* (PCE) Tx Payload checksum Error 12 */ + DescTxLostCarrier = 0x00000800, /* (LC)Tx - carrier lost during tramsmission 11 */ + DescTxNoCarrier = 0x00000400, /* (NC)Tx - no carrier signal from the tranceiver 10 */ + DescTxLateCollision = 0x00000200, /* (LC)Tx - transmission aborted due to collision 9 */ + DescTxExcCollisions = 0x00000100, /* (EC)Tx - transmission aborted after 16 collisions 8 */ + DescTxVLANFrame = 0x00000080, /* (VF)Tx - VLAN-type frame 7 */ + + DescTxCollMask = 0x00000078, /* (CC)Tx - Collision count 6:3 */ + DescTxCollShift = 3, + + DescTxExcDeferral = 0x00000004, /* (ED)Tx - excessive deferral 2 */ + DescTxUnderflow = 0x00000002, /* (UF)Tx - late data arrival from the memory 1 */ + DescTxDeferred = 0x00000001, /* (DB)Tx - frame transmision deferred 0 */ + + /* + This explains the RDES1/TDES1 bits layout + -------------------------------------------------------------------- + RDES1/TDES1 | Control Bits | Byte Count Buffer 2 | Byte Count Buffer 1 | + -------------------------------------------------------------------- + + */ +//DmaDescriptorLength length word of DMA descriptor + DescTxIntEnable = 0x80000000, /* (IC)Tx - interrupt on completion 31 */ + DescTxLast = 0x40000000, /* (LS)Tx - Last segment of the frame 30 */ + DescTxFirst = 0x20000000, /* (FS)Tx - First segment of the frame 29 */ + DescTxDisableCrc = 0x04000000, /* (DC)Tx - Add CRC disabled (first segment only) 26 */ + + RxDisIntCompl = 0x80000000, /* (Disable Rx int on completion) 31 */ + RxDescEndOfRing = 0x02000000, /* (TER)End of descriptors ring */ + RxDescChain = 0x01000000, /* (TCH)Second buffer address is chain address 24 */ + + DescTxDisablePadd = 0x00800000, /* (DP)disable padding, added by - reyaz 23 */ + + TxDescEndOfRing = 0x02000000, /* (TER)End of descriptors ring */ + TxDescChain = 0x01000000, /* (TCH)Second buffer address is chain address 24 */ + + DescSize2Mask = 0x003FF800, /* (TBS2) Buffer 2 size 21:11 */ + DescSize2Shift = 11, + DescSize1Mask = 0x000007FF, /* (TBS1) Buffer 1 size 10:0 */ + DescSize1Shift = 0, + + DescTxCisMask = 0x18000000, /* Tx checksum offloading control mask 28:27 */ + DescTxCisBypass = 0x00000000, /* Checksum bypass */ + DescTxCisIpv4HdrCs = 0x08000000, /* IPv4 header checksum */ + DescTxCisTcpOnlyCs = 0x10000000, /* TCP/UDP/ICMP checksum. Pseudo header checksum is assumed to be present */ + DescTxCisTcpPseudoCs = 0x18000000, /* TCP/UDP/ICMP checksum fully in hardware including pseudo header */ +}; +#endif + +// Rx Descriptor COE type2 encoding +enum RxDescCOEEncode +{ + RxLenLT600 = 0, /* Bit(5:7:0)=>0 IEEE 802.3 type frame Length field is Lessthan 0x0600 */ + RxIpHdrPayLoadChkBypass = 1, /* Bit(5:7:0)=>1 Payload & Ip header checksum bypassed (unsuppported payload) */ + RxIpHdrPayLoadRes = 2, /* Bit(5:7:0)=>2 Reserved */ + RxChkBypass = 3, /* Bit(5:7:0)=>3 Neither IPv4 nor IPV6. So checksum bypassed */ + RxNoChkError = 4, /* Bit(5:7:0)=>4 No IPv4/IPv6 Checksum error detected */ + RxPayLoadChkError = 5, /* Bit(5:7:0)=>5 Payload checksum error detected for Ipv4/Ipv6 frames */ + RxIpHdrChkError = 6, /* Bit(5:7:0)=>6 Ip header checksum error detected for Ipv4 frames */ + RxIpHdrPayLoadChkError = 7, /* Bit(5:7:0)=>7 Payload & Ip header checksum error detected for Ipv4/Ipv6 frames */ +}; + +/********************************************************** + * DMA engine interrupt handling functions + **********************************************************/ + + enum synopGMACDmaIntEnum /* Intrerrupt types */ +{ + synopGMACDmaRxNormal = 0x01, /* normal receiver interrupt */ + synopGMACDmaRxAbnormal = 0x02, /* abnormal receiver interrupt */ + synopGMACDmaRxStopped = 0x04, /* receiver stopped */ + synopGMACDmaTxNormal = 0x08, /* normal transmitter interrupt */ + synopGMACDmaTxAbnormal = 0x10, /* abnormal transmitter interrupt */ + synopGMACDmaTxStopped = 0x20, /* transmitter stopped */ + synopGMACDmaError = 0x80, /* Dma engine error */ +}; + + +/********************************************************** + * Initial register values + **********************************************************/ +enum InitialRegisters +{ + /* Full-duplex mode with perfect filter on */ + GmacConfigInitFdx1000 = GmacWatchdogEnable | GmacJabberEnable | GmacFrameBurstEnable | GmacJumboFrameDisable + | GmacSelectGmii | GmacEnableRxOwn | GmacLoopbackOff + | GmacFullDuplex | GmacRetryEnable | GmacPadCrcStripDisable + | GmacBackoffLimit0 | GmacDeferralCheckDisable | GmacTxEnable | GmacRxEnable, + + /* Full-duplex mode with perfect filter on */ + GmacConfigInitFdx110 = GmacWatchdogEnable | GmacJabberEnable | GmacFrameBurstEnable | GmacJumboFrameDisable + | GmacSelectMii | GmacEnableRxOwn | GmacLoopbackOff + | GmacFullDuplex | GmacRetryEnable | GmacPadCrcStripDisable + | GmacBackoffLimit0 | GmacDeferralCheckDisable | GmacTxEnable | GmacRxEnable, + + /* Full-duplex mode */ + // CHANGED: Pass control config, dest addr filter normal, added source address filter, multicast & unicast + // Hash filter. + /* = GmacFilterOff | GmacPassControlOff | GmacBroadcastEnable */ + GmacFrameFilterInitFdx = GmacFilterOn | GmacPassControl0 | GmacBroadcastEnable | GmacSrcAddrFilterDisable + | GmacMulticastFilterOn | GmacDestAddrFilterNor | GmacMcastHashFilterOff + | GmacPromiscuousModeOff | GmacUcastHashFilterOff, + + /* Full-duplex mode */ + GmacFlowControlInitFdx = GmacUnicastPauseFrameOff | GmacRxFlowControlEnable | GmacTxFlowControlEnable, + + /* Full-duplex mode */ + GmacGmiiAddrInitFdx = GmiiCsrClk2, + + + /* Half-duplex mode with perfect filter on */ + // CHANGED: Removed Endian configuration, added single bit config for PAD/CRC strip, + /*| GmacSelectMii | GmacLittleEndian | GmacDisableRxOwn | GmacLoopbackOff*/ + GmacConfigInitHdx1000 = GmacWatchdogEnable | GmacJabberEnable | GmacFrameBurstEnable | GmacJumboFrameDisable + | GmacSelectGmii | GmacDisableRxOwn | GmacLoopbackOff + | GmacHalfDuplex | GmacRetryEnable | GmacPadCrcStripDisable + | GmacBackoffLimit0 | GmacDeferralCheckDisable | GmacTxEnable | GmacRxEnable, + + /* Half-duplex mode with perfect filter on */ + GmacConfigInitHdx110 = GmacWatchdogEnable | GmacJabberEnable | GmacFrameBurstEnable | GmacJumboFrameDisable + | GmacSelectMii | GmacDisableRxOwn | GmacLoopbackOff + | GmacHalfDuplex | GmacRetryEnable | GmacPadCrcStripDisable + | GmacBackoffLimit0 | GmacDeferralCheckDisable | GmacTxEnable | GmacRxEnable, + + /* Half-duplex mode */ + GmacFrameFilterInitHdx = GmacFilterOn | GmacPassControl0 | GmacBroadcastEnable | GmacSrcAddrFilterDisable + | GmacMulticastFilterOn | GmacDestAddrFilterNor | GmacMcastHashFilterOff + | GmacUcastHashFilterOff| GmacPromiscuousModeOff, + + /* Half-duplex mode */ + GmacFlowControlInitHdx = GmacUnicastPauseFrameOff | GmacRxFlowControlDisable | GmacTxFlowControlDisable, + + /* Half-duplex mode */ + GmacGmiiAddrInitHdx = GmiiCsrClk2, + + /********************************************** + *DMA configurations + **********************************************/ + + DmaBusModeInit = DmaFixedBurstEnable | DmaBurstLength8 | DmaDescriptorSkip1 | DmaResetOff, +// DmaBusModeInit = DmaFixedBurstEnable | DmaBurstLength8 | DmaDescriptorSkip4 | DmaResetOff, + + /* 1000 Mb/s mode */ + DmaControlInit1000 = DmaStoreAndForward,// | DmaTxSecondFrame , + + /* 100 Mb/s mode */ + DmaControlInit100 = DmaStoreAndForward, + + /* 10 Mb/s mode */ + DmaControlInit10 = DmaStoreAndForward, + + /* Interrupt groups */ + DmaIntErrorMask = DmaIntBusError, /* Error */ + DmaIntRxAbnMask = DmaIntRxNoBuffer, /* receiver abnormal interrupt */ + DmaIntRxNormMask = DmaIntRxCompleted, /* receiver normal interrupt */ + DmaIntRxStoppedMask = DmaIntRxStopped, /* receiver stopped */ + DmaIntTxAbnMask = DmaIntTxUnderflow, /* transmitter abnormal interrupt */ + DmaIntTxNormMask = DmaIntTxCompleted, /* transmitter normal interrupt */ + DmaIntTxStoppedMask = DmaIntTxStopped, /* transmitter stopped */ + + DmaIntEnable = DmaIeNormal | DmaIeAbnormal | DmaIntErrorMask +//DmaIntEnable = DmaIeNormal | DmaIntErrorMask + | DmaIntRxAbnMask | DmaIntRxNormMask | DmaIntRxStoppedMask +// | DmaIntRxNormMask | DmaIntRxStoppedMask + | DmaIntTxAbnMask | DmaIntTxNormMask | DmaIntTxStoppedMask, + DmaIntDisable = 0, +}; + + +/********************************************************** + * Mac Management Counters (MMC) + **********************************************************/ + +enum MMC_ENABLE +{ + GmacMmcCntrl = 0x0100, /* mmc control for operating mode of MMC */ + GmacMmcIntrRx = 0x0104, /* maintains interrupts generated by rx counters */ + GmacMmcIntrTx = 0x0108, /* maintains interrupts generated by tx counters */ + GmacMmcIntrMaskRx = 0x010C, /* mask for interrupts generated from rx counters */ + GmacMmcIntrMaskTx = 0x0110, /* mask for interrupts generated from tx counters */ +}; +enum MMC_TX +{ + GmacMmcTxOctetCountGb = 0x0114, /*Bytes Tx excl. of preamble and retried bytes (Good or Bad) */ + GmacMmcTxFrameCountGb = 0x0118, /*Frames Tx excl. of retried frames (Good or Bad) */ + GmacMmcTxBcFramesG = 0x011C, /*Broadcast Frames Tx (Good) */ + GmacMmcTxMcFramesG = 0x0120, /*Multicast Frames Tx (Good) */ + + GmacMmcTx64OctetsGb = 0x0124, /*Tx with len 64 bytes excl. of pre and retried (Good or Bad) */ + GmacMmcTx65To127OctetsGb = 0x0128, /*Tx with len >64 bytes <=127 excl. of pre and retried (Good or Bad) */ + GmacMmcTx128To255OctetsGb = 0x012C, /*Tx with len >128 bytes <=255 excl. of pre and retried (Good or Bad) */ + GmacMmcTx256To511OctetsGb = 0x0130, /*Tx with len >256 bytes <=511 excl. of pre and retried (Good or Bad) */ + GmacMmcTx512To1023OctetsGb = 0x0134, /*Tx with len >512 bytes <=1023 excl. of pre and retried (Good or Bad) */ + GmacMmcTx1024ToMaxOctetsGb = 0x0138, /*Tx with len >1024 bytes <=MaxSize excl. of pre and retried (Good or Bad) */ + + GmacMmcTxUcFramesGb = 0x013C, /*Unicast Frames Tx (Good or Bad) */ + GmacMmcTxMcFramesGb = 0x0140, /*Multicast Frames Tx (Good and Bad) */ + GmacMmcTxBcFramesGb = 0x0144, /*Broadcast Frames Tx (Good and Bad) */ + GmacMmcTxUnderFlowError = 0x0148, /*Frames aborted due to Underflow error */ + GmacMmcTxSingleColG = 0x014C, /*Successfully Tx Frames after singel collision in Half duplex mode */ + GmacMmcTxMultiColG = 0x0150, /*Successfully Tx Frames after more than singel collision in Half duplex mode */ + GmacMmcTxDeferred = 0x0154, /*Successfully Tx Frames after a deferral in Half duplex mode */ + GmacMmcTxLateCol = 0x0158, /*Frames aborted due to late collision error */ + GmacMmcTxExessCol = 0x015C, /*Frames aborted due to excessive (16) collision errors */ + GmacMmcTxCarrierError = 0x0160, /*Frames aborted due to carrier sense error (No carrier or Loss of carrier) */ + GmacMmcTxOctetCountG = 0x0164, /*Bytes Tx excl. of preamble and retried bytes (Good) */ + GmacMmcTxFrameCountG = 0x0168, /*Frames Tx (Good) */ + GmacMmcTxExessDef = 0x016C, /*Frames aborted due to excessive deferral errors (deferred for more than 2 max-sized frame times)*/ + + GmacMmcTxPauseFrames = 0x0170, /*Number of good pause frames Tx. */ + GmacMmcTxVlanFramesG = 0x0174, /*Number of good Vlan frames Tx excl. retried frames */ +}; +enum MMC_RX +{ + GmacMmcRxFrameCountGb = 0x0180, /*Frames Rx (Good or Bad) */ + GmacMmcRxOctetCountGb = 0x0184, /*Bytes Rx excl. of preamble and retried bytes (Good or Bad) */ + GmacMmcRxOctetCountG = 0x0188, /*Bytes Rx excl. of preamble and retried bytes (Good) */ + GmacMmcRxBcFramesG = 0x018C, /*Broadcast Frames Rx (Good) */ + GmacMmcRxMcFramesG = 0x0190, /*Multicast Frames Rx (Good) */ + + GmacMmcRxCrcError = 0x0194, /*Number of frames received with CRC error */ + GmacMmcRxAlignError = 0x0198, /*Number of frames received with alignment (dribble) error. Only in 10/100mode */ + GmacMmcRxRuntError = 0x019C, /*Number of frames received with runt (<64 bytes and CRC error) error */ + GmacMmcRxJabberError = 0x01A0, /*Number of frames rx with jabber (>1518/1522 or >9018/9022 and CRC) */ + GmacMmcRxUnderSizeG = 0x01A4, /*Number of frames received with <64 bytes without any error */ + GmacMmcRxOverSizeG = 0x01A8, /*Number of frames received with >1518/1522 bytes without any error */ + + GmacMmcRx64OctetsGb = 0x01AC, /*Rx with len 64 bytes excl. of pre and retried (Good or Bad) */ + GmacMmcRx65To127OctetsGb = 0x01B0, /*Rx with len >64 bytes <=127 excl. of pre and retried (Good or Bad) */ + GmacMmcRx128To255OctetsGb = 0x01B4, /*Rx with len >128 bytes <=255 excl. of pre and retried (Good or Bad) */ + GmacMmcRx256To511OctetsGb = 0x01B8, /*Rx with len >256 bytes <=511 excl. of pre and retried (Good or Bad) */ + GmacMmcRx512To1023OctetsGb = 0x01BC, /*Rx with len >512 bytes <=1023 excl. of pre and retried (Good or Bad) */ + GmacMmcRx1024ToMaxOctetsGb = 0x01C0, /*Rx with len >1024 bytes <=MaxSize excl. of pre and retried (Good or Bad) */ + + GmacMmcRxUcFramesG = 0x01C4, /*Unicast Frames Rx (Good) */ + GmacMmcRxLengthError = 0x01C8, /*Number of frames received with Length type field != frame size */ + GmacMmcRxOutOfRangeType = 0x01CC, /*Number of frames received with length field != valid frame size */ + + GmacMmcRxPauseFrames = 0x01D0, /*Number of good pause frames Rx. */ + GmacMmcRxFifoOverFlow = 0x01D4, /*Number of missed rx frames due to FIFO overflow */ + GmacMmcRxVlanFramesGb = 0x01D8, /*Number of good Vlan frames Rx */ + + GmacMmcRxWatchdobError = 0x01DC, /*Number of frames rx with error due to watchdog timeout error */ +}; + +enum MMC_IP_RELATED +{ + GmacMmcRxIpcIntrMask = 0x0200, /*Maintains the mask for interrupt generated from rx IPC statistic counters */ + GmacMmcRxIpcIntr = 0x0208, /*Maintains the interrupt that rx IPC statistic counters generate */ + + GmacMmcRxIpV4FramesG = 0x0210, /*Good IPV4 datagrams received */ + GmacMmcRxIpV4HdrErrFrames = 0x0214, /*Number of IPV4 datagrams received with header errors */ + GmacMmcRxIpV4NoPayFrames = 0x0218, /*Number of IPV4 datagrams received which didnot have TCP/UDP/ICMP payload */ + GmacMmcRxIpV4FragFrames = 0x021C, /*Number of IPV4 datagrams received with fragmentation */ + GmacMmcRxIpV4UdpChkDsblFrames = 0x0220, /*Number of IPV4 datagrams received that had a UDP payload checksum disabled */ + + GmacMmcRxIpV6FramesG = 0x0224, /*Good IPV6 datagrams received */ + GmacMmcRxIpV6HdrErrFrames = 0x0228, /*Number of IPV6 datagrams received with header errors */ + GmacMmcRxIpV6NoPayFrames = 0x022C, /*Number of IPV6 datagrams received which didnot have TCP/UDP/ICMP payload */ + + GmacMmcRxUdpFramesG = 0x0230, /*Number of good IP datagrams with good UDP payload */ + GmacMmcRxUdpErrorFrames = 0x0234, /*Number of good IP datagrams with UDP payload having checksum error */ + + GmacMmcRxTcpFramesG = 0x0238, /*Number of good IP datagrams with good TDP payload */ + GmacMmcRxTcpErrorFrames = 0x023C, /*Number of good IP datagrams with TCP payload having checksum error */ + + GmacMmcRxIcmpFramesG = 0x0240, /*Number of good IP datagrams with good Icmp payload */ + GmacMmcRxIcmpErrorFrames = 0x0244, /*Number of good IP datagrams with Icmp payload having checksum error */ + + GmacMmcRxIpV4OctetsG = 0x0250, /*Good IPV4 datagrams received excl. Ethernet hdr,FCS,Pad,Ip Pad bytes */ + GmacMmcRxIpV4HdrErrorOctets = 0x0254, /*Number of bytes in IPV4 datagram with header errors */ + GmacMmcRxIpV4NoPayOctets = 0x0258, /*Number of bytes in IPV4 datagram with no TCP/UDP/ICMP payload */ + GmacMmcRxIpV4FragOctets = 0x025C, /*Number of bytes received in fragmented IPV4 datagrams */ + GmacMmcRxIpV4UdpChkDsblOctets = 0x0260, /*Number of bytes received in UDP segment that had UDP checksum disabled */ + + GmacMmcRxIpV6OctetsG = 0x0264, /*Good IPV6 datagrams received excl. Ethernet hdr,FCS,Pad,Ip Pad bytes */ + GmacMmcRxIpV6HdrErrorOctets = 0x0268, /*Number of bytes in IPV6 datagram with header errors */ + GmacMmcRxIpV6NoPayOctets = 0x026C, /*Number of bytes in IPV6 datagram with no TCP/UDP/ICMP payload */ + + GmacMmcRxUdpOctetsG = 0x0270, /*Number of bytes in IP datagrams with good UDP payload */ + GmacMmcRxUdpErrorOctets = 0x0274, /*Number of bytes in IP datagrams with UDP payload having checksum error */ + + GmacMmcRxTcpOctetsG = 0x0278, /*Number of bytes in IP datagrams with good TDP payload */ + GmacMmcRxTcpErrorOctets = 0x027C, /*Number of bytes in IP datagrams with TCP payload having checksum error */ + + GmacMmcRxIcmpOctetsG = 0x0280, /*Number of bytes in IP datagrams with good Icmp payload */ + GmacMmcRxIcmpErrorOctets = 0x0284, /*Number of bytes in IP datagrams with Icmp payload having checksum error */ +}; + + +enum MMC_CNTRL_REG_BIT_DESCRIPTIONS +{ + GmacMmcCounterFreeze = 0x00000008, /* when set MMC counters freeze to current value */ + GmacMmcCounterResetOnRead = 0x00000004, /* when set MMC counters will be reset to 0 after read */ + GmacMmcCounterStopRollover = 0x00000002, /* when set counters will not rollover after max value */ + GmacMmcCounterReset = 0x00000001, /* when set all counters wil be reset (automatically cleared after 1 clk) */ +}; + +enum MMC_RX_INTR_MASK_AND_STATUS_BIT_DESCRIPTIONS +{ + GmacMmcRxWDInt = 0x00800000, /* set when rxwatchdog error reaches half of max value */ + GmacMmcRxVlanInt = 0x00400000, /* set when GmacMmcRxVlanFramesGb counter reaches half of max value */ + GmacMmcRxFifoOverFlowInt = 0x00200000, /* set when GmacMmcRxFifoOverFlow counter reaches half of max value */ + GmacMmcRxPauseFrameInt = 0x00100000, /* set when GmacMmcRxPauseFrames counter reaches half of max value */ + GmacMmcRxOutOfRangeInt = 0x00080000, /* set when GmacMmcRxOutOfRangeType counter reaches half of max value */ + GmacMmcRxLengthErrorInt = 0x00040000, /* set when GmacMmcRxLengthError counter reaches half of max value */ + GmacMmcRxUcFramesInt = 0x00020000, /* set when GmacMmcRxUcFramesG counter reaches half of max value */ + GmacMmcRx1024OctInt = 0x00010000, /* set when GmacMmcRx1024ToMaxOctetsGb counter reaches half of max value */ + GmacMmcRx512OctInt = 0x00008000, /* set when GmacMmcRx512To1023OctetsGb counter reaches half of max value */ + GmacMmcRx256OctInt = 0x00004000, /* set when GmacMmcRx256To511OctetsGb counter reaches half of max value */ + GmacMmcRx128OctInt = 0x00002000, /* set when GmacMmcRx128To255OctetsGb counter reaches half of max value */ + GmacMmcRx65OctInt = 0x00001000, /* set when GmacMmcRx65To127OctetsG counter reaches half of max value */ + GmacMmcRx64OctInt = 0x00000800, /* set when GmacMmcRx64OctetsGb counter reaches half of max value */ + GmacMmcRxOverSizeInt = 0x00000400, /* set when GmacMmcRxOverSizeG counter reaches half of max value */ + GmacMmcRxUnderSizeInt = 0x00000200, /* set when GmacMmcRxUnderSizeG counter reaches half of max value */ + GmacMmcRxJabberErrorInt = 0x00000100, /* set when GmacMmcRxJabberError counter reaches half of max value */ + GmacMmcRxRuntErrorInt = 0x00000080, /* set when GmacMmcRxRuntError counter reaches half of max value */ + GmacMmcRxAlignErrorInt = 0x00000040, /* set when GmacMmcRxAlignError counter reaches half of max value */ + GmacMmcRxCrcErrorInt = 0x00000020, /* set when GmacMmcRxCrcError counter reaches half of max value */ + GmacMmcRxMcFramesInt = 0x00000010, /* set when GmacMmcRxMcFramesG counter reaches half of max value */ + GmacMmcRxBcFramesInt = 0x00000008, /* set when GmacMmcRxBcFramesG counter reaches half of max value */ + GmacMmcRxOctetGInt = 0x00000004, /* set when GmacMmcRxOctetCountG counter reaches half of max value */ + GmacMmcRxOctetGbInt = 0x00000002, /* set when GmacMmcRxOctetCountGb counter reaches half of max value */ + GmacMmcRxFrameInt = 0x00000001, /* set when GmacMmcRxFrameCountGb counter reaches half of max value */ +}; + +enum MMC_TX_INTR_MASK_AND_STATUS_BIT_DESCRIPTIONS +{ + + GmacMmcTxVlanInt = 0x01000000, /* set when GmacMmcTxVlanFramesG counter reaches half of max value */ + GmacMmcTxPauseFrameInt = 0x00800000, /* set when GmacMmcTxPauseFrames counter reaches half of max value */ + GmacMmcTxExessDefInt = 0x00400000, /* set when GmacMmcTxExessDef counter reaches half of max value */ + GmacMmcTxFrameInt = 0x00200000, /* set when GmacMmcTxFrameCount counter reaches half of max value */ + GmacMmcTxOctetInt = 0x00100000, /* set when GmacMmcTxOctetCountG counter reaches half of max value */ + GmacMmcTxCarrierErrorInt = 0x00080000, /* set when GmacMmcTxCarrierError counter reaches half of max value */ + GmacMmcTxExessColInt = 0x00040000, /* set when GmacMmcTxExessCol counter reaches half of max value */ + GmacMmcTxLateColInt = 0x00020000, /* set when GmacMmcTxLateCol counter reaches half of max value */ + GmacMmcTxDeferredInt = 0x00010000, /* set when GmacMmcTxDeferred counter reaches half of max value */ + GmacMmcTxMultiColInt = 0x00008000, /* set when GmacMmcTxMultiColG counter reaches half of max value */ + GmacMmcTxSingleCol = 0x00004000, /* set when GmacMmcTxSingleColG counter reaches half of max value */ + GmacMmcTxUnderFlowErrorInt = 0x00002000, /* set when GmacMmcTxUnderFlowError counter reaches half of max value */ + GmacMmcTxBcFramesGbInt = 0x00001000, /* set when GmacMmcTxBcFramesGb counter reaches half of max value */ + GmacMmcTxMcFramesGbInt = 0x00000800, /* set when GmacMmcTxMcFramesGb counter reaches half of max value */ + GmacMmcTxUcFramesInt = 0x00000400, /* set when GmacMmcTxUcFramesGb counter reaches half of max value */ + GmacMmcTx1024OctInt = 0x00000200, /* set when GmacMmcTx1024ToMaxOctetsGb counter reaches half of max value */ + GmacMmcTx512OctInt = 0x00000100, /* set when GmacMmcTx512To1023OctetsGb counter reaches half of max value */ + GmacMmcTx256OctInt = 0x00000080, /* set when GmacMmcTx256To511OctetsGb counter reaches half of max value */ + GmacMmcTx128OctInt = 0x00000040, /* set when GmacMmcTx128To255OctetsGb counter reaches half of max value */ + GmacMmcTx65OctInt = 0x00000020, /* set when GmacMmcTx65To127OctetsGb counter reaches half of max value */ + GmacMmcTx64OctInt = 0x00000010, /* set when GmacMmcTx64OctetsGb counter reaches half of max value */ + GmacMmcTxMcFramesInt = 0x00000008, /* set when GmacMmcTxMcFramesG counter reaches half of max value */ + GmacMmcTxBcFramesInt = 0x00000004, /* set when GmacMmcTxBcFramesG counter reaches half of max value */ + GmacMmcTxFrameGbInt = 0x00000002, /* set when GmacMmcTxFrameCountGb counter reaches half of max value */ + GmacMmcTxOctetGbInt = 0x00000001, /* set when GmacMmcTxOctetCountGb counter reaches half of max value */ +}; + + +/********************************************************** + * Power Management (PMT) Block + **********************************************************/ + +/** + * PMT supports the reception of network (remote) wake-up frames and Magic packet frames. + * It generates interrupts for wake-up frames and Magic packets received by GMAC. + * PMT sits in Rx path and is enabled with remote wake-up frame enable and Magic packet enable. + * These enable are in PMT control and Status register and are programmed by apllication. + * + * When power down mode is enabled in PMT, all rx frames are dropped by the core. Core comes + * out of power down mode only when either Magic packe tor a Remote wake-up frame is received + * and the corresponding detection is enabled. + * + * Driver need not be modified to support this feature. Only Api to put the device in to power + * down mode is sufficient + */ + +#define WAKEUP_REG_LENGTH 8 /*This is the reg length for wake up register configuration*/ + +enum GmacPmtCtrlStatusBitDefinition +{ + GmacPmtFrmFilterPtrReset = 0x80000000, /* when set remote wake-up frame filter register pointer to 3'b000 */ + GmacPmtGlobalUnicast = 0x00000200, /* When set enables any unicast packet to be a wake-up frame */ + GmacPmtWakeupFrameReceived = 0x00000040, /* Wake up frame received */ + GmacPmtMagicPktReceived = 0x00000020, /* Magic Packet received */ + GmacPmtWakeupFrameEnable = 0x00000004, /* Wake-up frame enable */ + GmacPmtMagicPktEnable = 0x00000002, /* Magic packet enable */ + GmacPmtPowerDown = 0x00000001, /* Power Down */ +}; + +/********************************************************** + * IEEE 1588-2008 Precision Time Protocol (PTP) Support + **********************************************************/ +enum PTPMessageType +{ + SYNC = 0x0, + Delay_Req = 0x1, + Pdelay_Req = 0x2, + Pdelay_Resp = 0x3, + Follow_up = 0x8, + Delay_Resp = 0x9, + Pdelay_Resp_Follow_Up = 0xA, + Announce = 0xB, + Signaling = 0xC, + Management = 0xD, +}; + +typedef struct TimeStampStruct +{ + u32 TSversion; /* PTP Version 1 or PTP version2 */ + u32 TSmessagetype; /* Message type associated with this time stamp */ + + u16 TShighest16; /* Highest 16 bit time stamp value, Valid onley when ADV_TIME_HIGH_WORD configured in corekit */ + u32 TSupper32; /* Most significant 32 bit time stamp value */ + u32 TSlower32; /* Least Significat 32 bit time stamp value */ + +} TimeStamp; + + +/** + * IEEE 1588-2008 is the optional module to support Ethernet frame time stamping. + * Sixty four (+16) bit time stamps are given in each frames transmit and receive status. + * The driver assumes the following + * 1. "IEEE 1588 Time Stamping" "TIME_STAMPING"is ENABLED in corekit + * 2. "IEEE 1588 External Time Stamp Input Enable" "EXT_TIME_STAMPING" is DISABLED in corekit + * 3. "IEEE 1588 Advanced Time Stamp support" "ADV_TIME_STAMPING" is ENABLED in corekit + * 4. "IEEE 1588 Higher Word Register Enable" "ADV_TIME_HIGH_WORD" is ENABLED in corekit + */ + +/* GmacTSControl = 0x0700, Controls the Timestamp update logic : only when IEEE 1588 time stamping is enabled in corekit */ +enum GmacTSControlReg +{ + GmacTSENMACADDR = 0x00040000, /* Enable Mac Addr for PTP filtering 18 RW 0 */ + + GmacTSCLKTYPE = 0x00030000, /* Select the type of clock node 17:16 RW 00 */ + /* + TSCLKTYPE TSMSTRENA TSEVNTENA Messages for wihich TS snapshot is taken + 00/01 X 0 SYNC, FOLLOW_UP, DELAY_REQ, DELAY_RESP + 00/01 1 0 DELAY_REQ + 00/01 0 1 SYNC + 10 NA 0 SYNC, FOLLOW_UP, DELAY_REQ, DELAY_RESP + 10 NA 1 SYNC, FOLLOW_UP + 11 NA 0 SYNC, FOLLOW_UP, DELAY_REQ, DELAY_RESP, PDELAY_REQ, PDELAY_RESP + 11 NA 1 SYNC, PDELAY_REQ, PDELAY_RESP + */ + GmacTSOrdClk = 0x00000000, /* 00=> Ordinary clock*/ + GmacTSBouClk = 0x00010000, /* 01=> Boundary clock*/ + GmacTSEtoEClk = 0x00020000, /* 10=> End-to-End transparent clock*/ + GmacTSPtoPClk = 0x00030000, /* 11=> P-to-P transparent clock*/ + + GmacTSMSTRENA = 0x00008000, /* Ena TS Snapshot for Master Messages 15 RW 0 */ + GmacTSEVNTENA = 0x00004000, /* Ena TS Snapshot for Event Messages 14 RW 0 */ + GmacTSIPV4ENA = 0x00002000, /* Ena TS snapshot for IPv4 13 RW 1 */ + GmacTSIPV6ENA = 0x00001000, /* Ena TS snapshot for IPv6 12 RW 0 */ + GmacTSIPENA = 0x00000800, /* Ena TS snapshot for PTP over E'net 11 RW 0 */ + GmacTSVER2ENA = 0x00000400, /* Ena PTP snooping for version 2 10 RW 0 */ + + GmacTSCTRLSSR = 0x00000200, /* Digital or Binary Rollover 9 RW 0 */ + + GmacTSENALL = 0x00000100, /* Enable TS fro all frames (Ver2 only) 8 RW 0 */ + + GmacTSADDREG = 0x00000020, /* Addend Register Update 5 RW_SC 0 */ + GmacTSUPDT = 0x00000008, /* Time Stamp Update 3 RW_SC 0 */ + GmacTSINT = 0x00000004, /* Time Atamp Initialize 2 RW_SC 0 */ + + GmacTSTRIG = 0x00000010, /* Time stamp interrupt Trigger Enable 4 RW_SC 0 */ + + GmacTSCFUPDT = 0x00000002, /* Time Stamp Fine/Coarse 1 RW 0 */ + GmacTSCUPDTCoarse = 0x00000000, /* 0=> Time Stamp update method is coarse */ + GmacTSCUPDTFine = 0x00000002, /* 1=> Time Stamp update method is fine */ + + GmacTSENA = 0x00000001, /* Time Stamp Enable 0 RW 0 */ +}; + + +/* GmacTSSubSecIncr = 0x0704, 8 bit value by which sub second register is incremented : only when IEEE 1588 time stamping without external timestamp input */ +enum GmacTSSubSecIncrReg +{ + GmacSSINCMsk = 0x000000FF, /* Only Lower 8 bits are valid bits 7:0 RW 00 */ +}; + +/* GmacTSLow = 0x070C, Indicates whether the timestamp low count is positive or negative; for Adv timestamp it is always zero */ +enum GmacTSSign +{ + GmacTSSign = 0x80000000, /* PSNT 31 RW 0 */ + GmacTSPositive = 0x00000000, + GmacTSNegative = 0x80000000, +}; + +/*GmacTargetTimeLow = 0x0718, 32 bit nano seconds(MS) to be compared with system time : only when IEEE 1588 time stamping without external timestamp input */ +enum GmacTSLowReg +{ + GmacTSDecThr = 0x3B9AC9FF, /*when TSCTRLSSR is set the max value for GmacTargetTimeLowReg and GmacTimeStampLow register is 0x3B9AC9FF at 1ns precision */ +}; + +/* GmacTSHighWord = 0x0724, Time Stamp Higher Word Register (Version 2 only); only lower 16 bits are valid */ +enum GmacTSHighWordReg +{ + GmacTSHighWordMask = 0x0000FFFF, /* Time Stamp Higher work register has only lower 16 bits valid */ +}; +/*GmacTSStatus = 0x0728, Time Stamp Status Register */ +enum GmacTSStatusReg +{ + GmacTSTargTimeReached = 0x00000002, /* Time Stamp Target Time Reached 1 RO 0 */ + GmacTSSecondsOverflow = 0x00000001, /* Time Stamp Seconds Overflow 0 RO 0 */ +}; + +/********************************************************** + * Time stamp related functions + **********************************************************/ +void synopGMAC_TS_enable(synopGMACdevice *gmacdev); +void synopGMAC_TS_disable(synopGMACdevice *gmacdev); + +void synopGMAC_TS_int_enable(synopGMACdevice *gmacdev); +void synopGMAC_TS_int_disable(synopGMACdevice *gmacdev); + +void synopGMAC_TS_mac_addr_filt_enable(synopGMACdevice *gmacdev); +void synopGMAC_TS_mac_addr_filt_disable(synopGMACdevice *gmacdev); +void synopGMAC_TS_set_clk_type(synopGMACdevice *gmacdev, u32 clk_type); +void synopGMAC_TS_master_enable(synopGMACdevice *gmacdev); // Only for Ordinary clock and Boundary clock and "Advanced Time Stamp" +void synopGMAC_TS_master_disable(synopGMACdevice *gmacdev); // Only for Ordinary clock and Boundary clock and "Advanced Time Stamp" +void synopGMAC_TS_event_enable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" +void synopGMAC_TS_event_disable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" +void synopGMAC_TS_IPV4_enable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" +void synopGMAC_TS_IPV4_disable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" +void synopGMAC_TS_IPV6_enable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" +void synopGMAC_TS_IPV6_disable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" +void synopGMAC_TS_ptp_over_ethernet_enable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" +void synopGMAC_TS_ptp_over_ethernet_disable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" +void synopGMAC_TS_pkt_snoop_ver2(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" +void synopGMAC_TS_pkt_snoop_ver1(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" + +void synopGMAC_TS_digital_rollover_enable(synopGMACdevice *gmacdev); +void synopGMAC_TS_binary_rollover_enable(synopGMACdevice *gmacdev); +void synopGMAC_TS_all_frames_enable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" +void synopGMAC_TS_all_frames_disable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" + +s32 synopGMAC_TS_addend_update(synopGMACdevice *gmacdev, u32 addend_value); +s32 synopGMAC_TS_timestamp_update(synopGMACdevice *gmacdev, u32 high_value, u32 low_value); +s32 synopGMAC_TS_timestamp_init(synopGMACdevice *gmacdev, u32 high_value, u32 low_value); + +void synopGMAC_TS_coarse_update(synopGMACdevice *gmacdev); // Only if "fine correction" enabled +void synopGMAC_TS_fine_update(synopGMACdevice *gmacdev); // Only if "fine correction" enabled + +void synopGMAC_TS_subsecond_init(synopGMACdevice *gmacdev, u32 sub_sec_inc_val); // Update should happen making use of subsecond mask +void synopGMAC_TS_read_timestamp(synopGMACdevice *gmacdev, u16 * higher_sec_val, + u32 * sec_val, u32 * sub_sec_val); // Reads the timestamp low,high and higher(Ver2) registers in the the struct pointer; readonly contents +void synopGMAC_TS_load_target_timestamp(synopGMACdevice *gmacdev, u32 sec_val, u32 sub_sec_val); //Loads the timestamp target register with the values provided + +void synopGMAC_TS_load_timestamp_higher_val(synopGMACdevice *gmacdev, u32 higher_sec_val); +void synopGMAC_TS_read_timestamp_higher_val(synopGMACdevice *gmacdev, u16 * higher_sec_val); +void synopGMAC_TS_read_target_timestamp(synopGMACdevice *gmacdev, u32 * sec_val, u32 * sub_sec_val); //Read the target time stamp register contents + + +/********************************************************** + * Common functions + **********************************************************/ +s32 synopGMAC_set_mdc_clk_div(synopGMACdevice *gmacdev,u32 clk_div_val ); +u32 synopGMAC_get_mdc_clk_div(synopGMACdevice *gmacdev); +s32 synopGMAC_read_phy_reg(u64 RegBase,u32 PhyBase, u32 RegOffset, u16 * data); +s32 synopGMAC_write_phy_reg(u64 RegBase, u32 PhyBase, u32 RegOffset, u16 data); +s32 synopGMAC_phy_loopback(synopGMACdevice *gmacdev, bool loopback); +s32 synopGMAC_read_version (synopGMACdevice * gmacdev) ; +s32 synopGMAC_reset (synopGMACdevice * gmacdev ); +s32 synopGMAC_dma_bus_mode_init(synopGMACdevice * gmacdev, u32 init_value ); +s32 synopGMAC_dma_control_init(synopGMACdevice * gmacdev, u32 init_value ); +void synopGMAC_wd_enable(synopGMACdevice * gmacdev); +void synopGMAC_wd_disable(synopGMACdevice * gmacdev); +void synopGMAC_jab_enable(synopGMACdevice * gmacdev); +void synopGMAC_jab_disable(synopGMACdevice * gmacdev); +void synopGMAC_frame_burst_enable(synopGMACdevice * gmacdev); +void synopGMAC_frame_burst_disable(synopGMACdevice * gmacdev); +void synopGMAC_jumbo_frame_enable(synopGMACdevice * gmacdev); +void synopGMAC_jumbo_frame_disable(synopGMACdevice * gmacdev); +void synopGMAC_select_gmii(synopGMACdevice * gmacdev); +void synopGMAC_select_mii(synopGMACdevice * gmacdev); +void synopGMAC_rx_own_enable(synopGMACdevice * gmacdev); +void synopGMAC_rx_own_disable(synopGMACdevice * gmacdev); +void synopGMAC_loopback_on(synopGMACdevice * gmacdev); +void synopGMAC_loopback_off(synopGMACdevice * gmacdev); +void synopGMAC_set_full_duplex(synopGMACdevice * gmacdev); +void synopGMAC_set_half_duplex(synopGMACdevice * gmacdev); +void synopGMAC_retry_enable(synopGMACdevice * gmacdev); +void synopGMAC_retry_disable(synopGMACdevice * gmacdev); +void synopGMAC_pad_crc_strip_enable(synopGMACdevice * gmacdev); +void synopGMAC_pad_crc_strip_disable(synopGMACdevice * gmacdev); +void synopGMAC_back_off_limit(synopGMACdevice * gmacdev, u32 value); +void synopGMAC_deferral_check_enable(synopGMACdevice * gmacdev); +void synopGMAC_deferral_check_disable(synopGMACdevice * gmacdev); +void synopGMAC_rx_enable(synopGMACdevice * gmacdev); +void synopGMAC_rx_disable(synopGMACdevice * gmacdev); +void synopGMAC_tx_enable(synopGMACdevice * gmacdev); +void synopGMAC_tx_disable(synopGMACdevice * gmacdev); +void synopGMAC_frame_filter_enable(synopGMACdevice * gmacdev); +void synopGMAC_frame_filter_disable(synopGMACdevice * gmacdev); +void synopGMAC_write_hash_table_high(synopGMACdevice * gmacdev, u32 data); +void synopGMAC_write_hash_table_low(synopGMACdevice * gmacdev, u32 data); +void synopGMAC_hash_perfect_filter_enable(synopGMACdevice * gmacdev); +void synopGMAC_Hash_filter_only_enable(synopGMACdevice * gmacdev); +void synopGMAC_src_addr_filter_enable(synopGMACdevice * gmacdev); +void synopGMAC_src_addr_filter_disable(synopGMACdevice * gmacdev); +void synopGMAC_dst_addr_filter_inverse(synopGMACdevice * gmacdev); +void synopGMAC_dst_addr_filter_normal(synopGMACdevice * gmacdev); +void synopGMAC_set_pass_control(synopGMACdevice * gmacdev,u32 passcontrol); +void synopGMAC_broadcast_enable(synopGMACdevice * gmacdev); +void synopGMAC_broadcast_disable(synopGMACdevice * gmacdev); +void synopGMAC_multicast_enable(synopGMACdevice * gmacdev); +void synopGMAC_multicast_disable(synopGMACdevice * gmacdev); +void synopGMAC_multicast_hash_filter_enable(synopGMACdevice * gmacdev); +void synopGMAC_multicast_hash_filter_disable(synopGMACdevice * gmacdev); +void synopGMAC_promisc_enable(synopGMACdevice * gmacdev); +void synopGMAC_promisc_disable(synopGMACdevice * gmacdev); +void synopGMAC_unicast_hash_filter_enable(synopGMACdevice * gmacdev); +void synopGMAC_unicast_hash_filter_disable(synopGMACdevice * gmacdev); +void synopGMAC_unicast_pause_frame_detect_enable(synopGMACdevice * gmacdev); +void synopGMAC_unicast_pause_frame_detect_disable(synopGMACdevice * gmacdev); +void synopGMAC_rx_flow_control_enable(synopGMACdevice * gmacdev); +void synopGMAC_rx_flow_control_disable(synopGMACdevice * gmacdev); +void synopGMAC_tx_flow_control_enable(synopGMACdevice * gmacdev); +void synopGMAC_tx_flow_control_disable(synopGMACdevice * gmacdev); +void synopGMAC_tx_activate_flow_control(synopGMACdevice * gmacdev); +void synopGMAC_tx_deactivate_flow_control(synopGMACdevice * gmacdev); +void synopGMAC_pause_control(synopGMACdevice *gmacdev); +s32 synopGMAC_mac_init(synopGMACdevice * gmacdev); +s32 synopGMAC_set_mac_addr(synopGMACdevice *gmacdev, u32 MacHigh, u32 MacLow, u8 *MacAddr ); +s32 synopGMAC_get_mac_addr(synopGMACdevice *gmacdev, u32 MacHigh, u32 MacLow, u8 *MacAddr ); +s32 synopGMAC_attach (synopGMACdevice * gmacdev, u64 macBase, u64 dmaBase, u64 phyBase,u8 *mac_addr); +void synopGMAC_rx_desc_init_ring(DmaDesc *desc, bool last_ring_desc); +void synopGMAC_tx_desc_init_ring(DmaDesc *desc, bool last_ring_desc); +void synopGMAC_rx_desc_init_chain(DmaDesc * desc); +void synopGMAC_tx_desc_init_chain(DmaDesc * desc); +s32 synopGMAC_init_tx_rx_desc_queue(synopGMACdevice *gmacdev); +void synopGMAC_init_rx_desc_base(synopGMACdevice *gmacdev); +void synopGMAC_init_tx_desc_base(synopGMACdevice *gmacdev); +void synopGMAC_set_owner_dma(DmaDesc *desc); +void synopGMAC_set_desc_sof(DmaDesc *desc); +void synopGMAC_set_desc_eof(DmaDesc *desc); +bool synopGMAC_is_sof_in_rx_desc(DmaDesc *desc); +bool synopGMAC_is_eof_in_rx_desc(DmaDesc *desc); +bool synopGMAC_is_da_filter_failed(DmaDesc *desc); +bool synopGMAC_is_sa_filter_failed(DmaDesc *desc); +bool synopGMAC_is_desc_owned_by_dma(DmaDesc *desc); +u32 synopGMAC_get_rx_desc_frame_length(u32 status); +bool synopGMAC_is_desc_valid(u32 status); +bool synopGMAC_is_desc_empty(DmaDesc *desc); +bool synopGMAC_is_rx_desc_valid(u32 status); +bool synopGMAC_is_tx_aborted(u32 status); +bool synopGMAC_is_tx_carrier_error(u32 status); +u32 synopGMAC_get_tx_collision_count(u32 status); +u32 synopGMAC_is_exc_tx_collisions(u32 status); +bool synopGMAC_is_rx_frame_damaged(u32 status); +bool synopGMAC_is_rx_frame_collision(u32 status); +bool synopGMAC_is_rx_crc(u32 status); +bool synopGMAC_is_frame_dribbling_errors(u32 status); +bool synopGMAC_is_rx_frame_length_errors(u32 status); +bool synopGMAC_is_last_rx_desc(synopGMACdevice * gmacdev,DmaDesc *desc); +bool synopGMAC_is_last_tx_desc(synopGMACdevice * gmacdev,DmaDesc *desc); +bool synopGMAC_is_rx_desc_chained(DmaDesc * desc); +bool synopGMAC_is_tx_desc_chained(DmaDesc * desc); +void synopGMAC_get_desc_data(DmaDesc * desc, u32 * Status, u32 * Buffer1, u32 * Length1, u64 * Data1, u32 * Buffer2, u32 * Length2, u64 * Data2); +#ifdef ENH_DESC_8W +s32 synopGMAC_get_tx_qptr(synopGMACdevice * gmacdev, u32 * Status, u32 * Buffer1, u32 * Length1, u64 * Data1, u32 * Buffer2, u32 * Length2, u64 * Data2, + u32 * Ext_Status, u32 * Time_Stamp_High, u32 * Time_Stamp_low); +#else +s32 synopGMAC_get_tx_qptr(synopGMACdevice * gmacdev, u32 * Status, u32 * Buffer1, u32 * Length1, u64 * Data1, u32 * Buffer2, u32 * Length2, u64 * Data2 ); +#endif +s32 synopGMAC_set_tx_qptr(synopGMACdevice * gmacdev, u32 Buffer1, u32 Length1, u64 Data1, u32 Buffer2, u32 Length2, u64 Data2,u32 offload_needed,u32 * index,DmaDesc *Dpr); +s32 synopGMAC_set_rx_qptr(synopGMACdevice * gmacdev, u32 Buffer1, u32 Length1, u64 Data1, u32 Buffer2, u32 Length2, u64 Data2); +#ifdef ENH_DESC_8W +s32 synopGMAC_get_rx_qptr(synopGMACdevice * gmacdev, u32 * Status, u32 * Buffer1, u32 * Length1, u64 * Data1, u32 * Buffer2, u32 * Length2, u64 * Data2, + u32 * Ext_Status, u32 * Time_Stamp_High, u32 * Time_Stamp_low); +#else +s32 synopGMAC_get_rx_qptr(synopGMACdevice * gmacdev, u32 * Status, u32 * Buffer1, u32 * Length1, u64 * Data1, u32 * Buffer2, u32 * Length2, u64 * Data2); +#endif +void synopGMAC_clear_interrupt(synopGMACdevice *gmacdev); +u32 synopGMAC_get_interrupt_type(synopGMACdevice *gmacdev); +u32 synopGMAC_get_interrupt_mask(synopGMACdevice *gmacdev); +void synopGMAC_enable_interrupt(synopGMACdevice *gmacdev, u32 interrupts); +void synopGMAC_disable_interrupt_all(synopGMACdevice *gmacdev); +void synopGMAC_disable_interrupt(synopGMACdevice *gmacdev, u32 interrupts); +void synopGMAC_enable_dma_rx(synopGMACdevice * gmacdev); +void synopGMAC_enable_dma_tx(synopGMACdevice * gmacdev); +void synopGMAC_resume_dma_tx(synopGMACdevice * gmacdev); +void synopGMAC_resume_dma_rx(synopGMACdevice * gmacdev); +void synopGMAC_take_desc_ownership(DmaDesc * desc); +void synopGMAC_take_desc_ownership_rx(synopGMACdevice * gmacdev); +void synopGMAC_take_desc_ownership_tx(synopGMACdevice * gmacdev); +void synopGMAC_disable_dma_tx(synopGMACdevice * gmacdev); +void synopGMAC_disable_dma_rx(synopGMACdevice * gmacdev); +/******Following APIs are valid only for Enhanced Descriptor from 3.50a release onwards*******/ +bool synopGMAC_is_ext_status(synopGMACdevice *gmacdev,u32 status); +bool synopGMAC_ES_is_IP_header_error(synopGMACdevice *gmacdev,u32 ext_status); +bool synopGMAC_ES_is_rx_checksum_bypassed(synopGMACdevice *gmacdev,u32 ext_status); +bool synopGMAC_ES_is_IP_payload_error(synopGMACdevice *gmacdev,u32 ext_status); +/*******************PMT APIs***************************************/ +void synopGMAC_pmt_int_enable(synopGMACdevice *gmacdev); +void synopGMAC_pmt_int_disable(synopGMACdevice *gmacdev); +void synopGMAC_power_down_enable(synopGMACdevice *gmacdev); +void synopGMAC_power_down_disable(synopGMACdevice *gmacdev); +void synopGMAC_enable_pmt_interrupt(synopGMACdevice *gmacdev); +void synopGMAC_disable_pmt_interrupt(synopGMACdevice *gmacdev); +void synopGMAC_magic_packet_enable(synopGMACdevice *gmacdev); +void synopGMAC_wakeup_frame_enable(synopGMACdevice *gmacdev); +void synopGMAC_pmt_unicast_enable(synopGMACdevice *gmacdev); +bool synopGMAC_is_magic_packet_received(synopGMACdevice *gmacdev); +bool synopGMAC_is_wakeup_frame_received(synopGMACdevice *gmacdev); +void synopGMAC_write_wakeup_frame_register(synopGMACdevice *gmacdev, u32 * filter_contents); +/*******************MMC APIs***************************************/ +void synopGMAC_mmc_counters_stop(synopGMACdevice *gmacdev); +void synopGMAC_mmc_counters_resume(synopGMACdevice *gmacdev); +void synopGMAC_mmc_counters_set_selfclear(synopGMACdevice *gmacdev); +void synopGMAC_mmc_counters_reset_selfclear(synopGMACdevice *gmacdev); +void synopGMAC_mmc_counters_disable_rollover(synopGMACdevice *gmacdev); +void synopGMAC_mmc_counters_enable_rollover(synopGMACdevice *gmacdev); +u32 synopGMAC_read_mmc_counter(synopGMACdevice *gmacdev, u32 counter); +u32 synopGMAC_read_mmc_rx_int_status(synopGMACdevice *gmacdev); +u32 synopGMAC_read_mmc_tx_int_status(synopGMACdevice *gmacdev); +void synopGMAC_disable_mmc_tx_interrupt(synopGMACdevice *gmacdev, u32 mask); +void synopGMAC_enable_mmc_tx_interrupt(synopGMACdevice *gmacdev, u32 mask); +void synopGMAC_disable_mmc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask); +void synopGMAC_enable_mmc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask); +void synopGMAC_enable_mmc_ipc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask); +void synopGMAC_disable_mmc_ipc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask); +/*******************Ip checksum offloading APIs***************************************/ +void synopGMAC_enable_rx_chksum_offload(synopGMACdevice *gmacdev); +void synopGMAC_disable_rx_Ipchecksum_offload(synopGMACdevice *gmacdev); +void synopGMAC_rx_tcpip_chksum_drop_enable(synopGMACdevice *gmacdev); +void synopGMAC_rx_tcpip_chksum_drop_disable(synopGMACdevice *gmacdev); +u32 synopGMAC_is_rx_checksum_error(synopGMACdevice *gmacdev, u32 status); +bool synopGMAC_is_tx_ipv4header_checksum_error(synopGMACdevice *gmacdev, u32 status); +bool synopGMAC_is_tx_payload_checksum_error(synopGMACdevice *gmacdev, u32 status); +void synopGMAC_tx_checksum_offload_bypass(synopGMACdevice *gmacdev, DmaDesc *desc); +void synopGMAC_tx_checksum_offload_ipv4hdr(synopGMACdevice *gmacdev, DmaDesc *desc); +void synopGMAC_tx_checksum_offload_tcponly(synopGMACdevice *gmacdev, DmaDesc *desc); +void synopGMAC_tx_checksum_offload_tcp_pseudo(synopGMACdevice *gmacdev, DmaDesc *desc); + +#endif /* End of file */ diff --git a/bsp/ls2kdev/drivers/net/synopGMAC_Host.h b/bsp/ls2kdev/drivers/net/synopGMAC_Host.h new file mode 100644 index 0000000000000000000000000000000000000000..b81b0c29f0e9ba728cf4c1472a32de8e75a8f920 --- /dev/null +++ b/bsp/ls2kdev/drivers/net/synopGMAC_Host.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-08-24 chinesebear first version + */ + +#ifndef SYNOP_GMAC_HOST_H +#define SYNOP_GMAC_HOST_H 1 + +#include "synopGMAC_plat.h" +#include "synopGMAC_Dev.h" +#include "mii.h" + +struct net_device_stats +{ + unsigned long rx_packets; /* total packets received */ + unsigned long tx_packets; /* total packets transmitted */ + unsigned long rx_bytes; /* total bytes received */ + unsigned long tx_bytes; /* total bytes transmitted */ + unsigned long rx_errors; /* bad packets received */ + unsigned long tx_errors; /* packet transmit problems */ + unsigned long rx_dropped; /* no space in linux buffers */ + unsigned long tx_dropped; /* no space available in linux */ + unsigned long multicast; /* multicast packets received */ + unsigned long collisions; + + /* detailed rx_errors: */ + unsigned long rx_length_errors; + unsigned long rx_over_errors; /* receiver ring buff overflow */ + unsigned long rx_crc_errors; /* recved pkt with crc error */ + unsigned long rx_frame_errors; /* recv'd frame alignment error */ + unsigned long rx_fifo_errors; /* recv'r fifo overrun */ + unsigned long rx_missed_errors; /* receiver missed packet */ + + /* detailed tx_errors */ + unsigned long tx_aborted_errors; + unsigned long tx_carrier_errors; + unsigned long tx_fifo_errors; + unsigned long tx_heartbeat_errors; + unsigned long tx_window_errors; + + /* for cslip etc */ + unsigned long rx_compressed; + unsigned long tx_compressed; +}; + +typedef struct synopGMACNetworkAdapter{ +/*Device Dependent Data structur*/ +synopGMACdevice * synopGMACdev; + +struct net_device_stats synopGMACNetStats; + +struct mii_if_info mii; +} synopGMACPciNetworkAdapter; + +#endif diff --git a/bsp/ls2kdev/drivers/net/synopGMAC_debug.h b/bsp/ls2kdev/drivers/net/synopGMAC_debug.h new file mode 100644 index 0000000000000000000000000000000000000000..c5387d00d885be8695347d6fd05a1d62c9b53731 --- /dev/null +++ b/bsp/ls2kdev/drivers/net/synopGMAC_debug.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-08-24 chinesebear first version + */ + +#ifndef __DEBUG_H__ +#define __DEBUG_H__ + +//#define GMAC_DEBUG +#include +#ifdef GMAC_DEBUG +#define DEBUG_MES rt_kprintf +#else +#define DEBUG_MES(...) +#endif + +#endif /*__DEBUG_H__*/ diff --git a/bsp/ls2kdev/drivers/net/synopGMAC_network_interface.h b/bsp/ls2kdev/drivers/net/synopGMAC_network_interface.h new file mode 100644 index 0000000000000000000000000000000000000000..5cb0c6d6d3d463a67f3dc2c55aa438410a14f577 --- /dev/null +++ b/bsp/ls2kdev/drivers/net/synopGMAC_network_interface.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-08-24 chinesebear first version + */ + +#ifndef SYNOP_GMAC_NETWORK_INTERFACE_H +#define SYNOP_GMAC_NETWORK_INTERFACE_H 1 + +#include +#include +#include "synopGMAC_plat.h" +#include "synopGMAC_Host.h" +#include "synopGMAC_Dev.h" + +#define NET_IF_TIMEOUT (10*HZ) +#define CHECK_TIME (HZ) + +s32 synopGMAC_init_network_interface(char* xname,u64 synopGMACMappedAddr); +void synopGMAC_exit_network_interface(void); + +s32 synopGMAC_linux_open(struct eth_device *); +s32 synopGMAC_linux_close(struct eth_device *); +struct net_device_stats * synopGMAC_linux_get_stats(struct synopGMACNetworkAdapter *); + +s32 synopGMAC_test(synopGMACdevice * gmacdev_0,synopGMACdevice * gmacdev_1); + +void dumpreg(u64 ); +void dumpphyreg(); + +/* + * gethex(vp,p,n) + * convert n hex digits from p to binary, result in vp, + * rtn 1 on success + */ +static int gethex(u8 *vp, char *p, int n) +{ + u8 v; + int digit; + + for (v = 0; n > 0; n--) { + if (*p == 0) + return (0); + if (*p >= '0' && *p <= '9') + digit = *p - '0'; + else if (*p >= 'a' && *p <= 'f') + digit = *p - 'a' + 10; + else if (*p >= 'A' && *p <= 'F') + digit = *p - 'A' + 10; + else + return (0); + + v <<= 4; + v |= digit; + p++; + } + *vp = v; + return (1); +} + +#endif /* End of file */ diff --git a/bsp/ls2kdev/drivers/net/synopGMAC_plat.c b/bsp/ls2kdev/drivers/net/synopGMAC_plat.c new file mode 100644 index 0000000000000000000000000000000000000000..64ccb91e6074c9357c5934151259f9ae81035689 --- /dev/null +++ b/bsp/ls2kdev/drivers/net/synopGMAC_plat.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-08-24 chinesebear first version + * 2020-08-10 lizhirui porting to ls2k + */ +#include "synopGMAC_plat.h" +#include "synopGMAC_Dev.h" +#include +#include + +void flush_cache(unsigned long start_addr, unsigned long size) +{ + /*r4k_dcache_wback_inv(start_addr,size); + + //rt_kprintf("flush_cache:start_addr = 0x%p,size = 0x%p",start_addr,size); + unsigned long new_addr = start_addr - CACHED_MEMORY_ADDR + UNCACHED_MEMORY_ADDR; + rt_memcpy(new_addr,start_addr,size); + + if(rt_memcmp(start_addr,new_addr,size) != 0) + { + rt_kprintf("flush_cache:data isn't matched!\n"); + while(1); + } + else + { + //rt_kprintf("flush_cache:data is matched!\n"); + }*/ +} + +//convert virtual address to physical address +dma_addr_t __attribute__((weak)) gmac_dmamap(unsigned long va,u32 size) +{ + return VA_TO_PA (va); + //return UNCACHED_TO_PHYS(va); +} + +/** + * This is a wrapper function for Memory allocation routine. In linux Kernel + * it it kmalloc function + * @param[in] bytes in bytes to allocate + */ + +void *plat_alloc_memory(u32 bytes) +{ +//return (void*)malloc((size_t)bytes, M_DEVBUF, M_DONTWAIT); + void *buf = (void*)rt_malloc((u32)bytes); + flush_cache((unsigned long)buf, bytes); + return buf; +} + +/** + * This is a wrapper function for consistent dma-able Memory allocation routine. + * In linux Kernel, it depends on pci dev structure + * @param[in] bytes in bytes to allocate + */ + +//allocate a space aligned to 16-byte boundary without cache +void *plat_alloc_consistent_dmaable_memory(synopGMACdevice *pcidev, u32 size, u32 *addr) +{ + void *buf; + buf = (void*)rt_malloc((u32)(size + 16)); + //CPU_IOFlushDCache( buf,size, SYNC_W); + unsigned long i = (unsigned long)buf; +// rt_kprintf("size = %d\n", size); +// rt_kprintf("bufaddr = %p\n", buf); +// rt_kprintf("i%%16 == %d\n", i%16); + if(i % 16 == 8){ + i += 8; + } + else if(i % 16 == 4){ + i += 12; + } + else if(i % 16 == 12){ + i += 4; + } + + flush_cache(i, size); + *addr = gmac_dmamap(i, size); + buf = (unsigned char *)CACHED_TO_UNCACHED(i); + //rt_kprintf("bufaddr = %p\n", buf); + return buf; +} + +/** + * This is a wrapper function for freeing consistent dma-able Memory. + * In linux Kernel, it depends on pci dev structure + * @param[in] bytes in bytes to allocate + */ +//void plat_free_consistent_dmaable_memory(void * addr) +void plat_free_consistent_dmaable_memory(synopGMACdevice *pcidev, u32 size, void * addr,u64 dma_addr) +{ + rt_free((void*)PHYS_TO_CACHED(UNCACHED_TO_PHYS(addr))); + return; +} + +/** + * This is a wrapper function for Memory free routine. In linux Kernel + * it it kfree function + * @param[in] buffer pointer to be freed + */ +void plat_free_memory(void *buffer) +{ + rt_free(buffer); + return ; +} + +//convert virtual address to physical address and flush cache +dma_addr_t plat_dma_map_single(void *hwdev,void *ptr,u32 size) +{ + unsigned long addr = (unsigned long) ptr; + //CPU_IOFlushDCache(addr,size, direction); + flush_cache(addr, size); + return gmac_dmamap(addr, size); +} + +/** + * This is a wrapper function for platform dependent delay + * Take care while passing the argument to this function + * @param[in] buffer pointer to be freed + */ +void plat_delay(u32 delay) +{ + while (delay--); + return; +} diff --git a/bsp/ls2kdev/drivers/net/synopGMAC_plat.h b/bsp/ls2kdev/drivers/net/synopGMAC_plat.h new file mode 100644 index 0000000000000000000000000000000000000000..3b6eaca197cc2c841ca9a5fd2ef0c18df6a7c417 --- /dev/null +++ b/bsp/ls2kdev/drivers/net/synopGMAC_plat.h @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-08-24 chinesebear first version + * 2020-08-10 lizhirui porting to ls2k + */ + +#ifndef SYNOP_GMAC_PLAT_H +#define SYNOP_GMAC_PLAT_H 1 + +/* sw +#include +#include +#include +#include +#include +*/ +#include "synopGMAC_types.h" +#include "synopGMAC_debug.h" +//#include "mii.h" +//#include "GMAC_Pmon.h" +//#include "synopGMAC_Host.h" +#include +#include +#include "mips_addrspace.h" +//sw: copy the type define into here +#define IOCTL_READ_REGISTER SIOCDEVPRIVATE+1 +#define IOCTL_WRITE_REGISTER SIOCDEVPRIVATE+2 +#define IOCTL_READ_IPSTRUCT SIOCDEVPRIVATE+3 +#define IOCTL_READ_RXDESC SIOCDEVPRIVATE+4 +#define IOCTL_READ_TXDESC SIOCDEVPRIVATE+5 +#define IOCTL_POWER_DOWN SIOCDEVPRIVATE+6 + +#define SYNOP_GMAC0 1 + +typedef int bool; +//typedef unsigned long dma_addr_t; + +#define KUSEG_ADDR 0x0 +#define CACHED_MEMORY_ADDR KSEG0BASE +#define UNCACHED_MEMORY_ADDR KSEG0BASE +#define KSEG2_ADDR KSEG2BASE +#define MAX_MEM_ADDR KSEG3BASE +#define RESERVED_ADDR KSEG3BASE + +#define CACHED_TO_PHYS(x) ((uint64_t)(x) - CACHED_MEMORY_ADDR) +#define PHYS_TO_CACHED(x) ((uint64_t)(x) + CACHED_MEMORY_ADDR) +#define UNCACHED_TO_PHYS(x) ((uint64_t)(x) - UNCACHED_MEMORY_ADDR) +#define PHYS_TO_UNCACHED(x) ((uint64_t)(x) + UNCACHED_MEMORY_ADDR) +#define VA_TO_CINDEX(x) (PHYS_TO_CACHED(UNCACHED_TO_PHYS(x))) +#define CACHED_TO_UNCACHED(x) (PHYS_TO_UNCACHED(CACHED_TO_PHYS(x))) + +#define VA_TO_PA(x) CACHED_TO_PHYS(x) + +/* sw +#define TR0(fmt, args...) printk(KERN_CRIT "SynopGMAC: " fmt, ##args) + +#ifdef DEBUG +#undef TR +# define TR(fmt, args...) printk(KERN_CRIT "SynopGMAC: " fmt, ##args) +#else +# define TR(fmt, args...) // not debugging: nothing +#endif +*/ +/* +#define TR0(fmt, args...) printf("SynopGMAC: " fmt, ##args) +*/ + +/* +#ifdef DEBUG +#undef TR +# define TR(fmt, args...) printf("SynopGMAC: " fmt, ##args) +#else +//# define TR(fmt, args...) // not debugging: nothing +#define TR(fmt, args...) printf("SynopGMAC: " fmt, ##args) +#endif +*/ + +//sw: nothing to display +#define TR0(fmt, args...) //rt_kprintf(fmt, ##args) +#define TR(fmt, args...) //rt_kprintf(fmt, ##args) + +//typedef int bool; +enum synopGMAC_boolean + { + false = 0, + true = 1 + }; + +#define DEFAULT_DELAY_VARIABLE 10 +#define DEFAULT_LOOP_VARIABLE 10000 + +/* There are platform related endian conversions + * + */ +#define LE32_TO_CPU __le32_to_cpu +#define BE32_TO_CPU __be32_to_cpu +#define CPU_TO_LE32 __cpu_to_le32 + +/* Error Codes */ +#define ESYNOPGMACNOERR 0 +#define ESYNOPGMACNOMEM 1 +#define ESYNOPGMACPHYERR 2 +#define ESYNOPGMACBUSY 3 + +struct Network_interface_data +{ + u32 unit; + u64 addr; + u32 data; +}; + + +/** + * These are the wrapper function prototypes for OS/platform related routines + */ +void * plat_alloc_memory(u32 ); +void plat_free_memory(void *); + +//void * plat_alloc_consistent_dmaable_memory(struct pci_dev *, u32, u32 *); +//void plat_free_consistent_dmaable_memory (struct pci_dev *, u32, void *, u32); +void plat_delay(u32); + + +/** + * The Low level function to read register contents from Hardware. + * + * @param[in] pointer to the base of register map + * @param[in] Offset from the base + * \return Returns the register contents + */ +static u32 synopGMACReadReg(u64 RegBase, u32 RegOffset) +{ + u64 addr; + u32 data; + + addr = RegBase + (u32)RegOffset; + data = *(volatile u32 *)addr; + +#if SYNOP_REG_DEBUG + TR("%s RegBase = 0x%08x RegOffset = 0x%08x RegData = 0x%08x\n", __FUNCTION__, (u32)RegBase, RegOffset, data ); +#endif + // rt_kprintf("%s RegBase = 0x%08x RegOffset = 0x%08x RegData = 0x%08x\n", __FUNCTION__, (u32)RegBase, RegOffset, data ); + return data; + +} + +/** + * The Low level function to write to a register in Hardware. + * + * @param[in] pointer to the base of register map + * @param[in] Offset from the base + * @param[in] Data to be written + * \return void + */ +static void synopGMACWriteReg(u64 RegBase, u32 RegOffset, u32 RegData ) +{ + u64 addr; + addr = RegBase + (u32)RegOffset; +// rt_kprintf("%s RegBase = 0x%08x RegOffset = 0x%08x RegData = 0x%08x\n", __FUNCTION__,(u32) RegBase, RegOffset, RegData ); +#if SYNOP_REG_DEBUG + TR("%s RegBase = 0x%p RegOffset = 0x%08x RegData = 0x%08x\n", __FUNCTION__,(u32) RegBase, RegOffset, RegData ); +#endif + *(volatile u32 *)addr = RegData; + /*if(addr == 0xbfe1100c) + DEBUG_MES("regdata = %08x\n", RegData);*/ + return; +} + +/** + * The Low level function to set bits of a register in Hardware. + * + * @param[in] pointer to the base of register map + * @param[in] Offset from the base + * @param[in] Bit mask to set bits to logical 1 + * \return void + */ +static void synopGMACSetBits(u64 RegBase, u32 RegOffset, u32 BitPos) +{ + //u64 addr = (u64)RegBase + (u64)RegOffset; + u32 data; + data = synopGMACReadReg(RegBase, RegOffset); + data |= BitPos; + synopGMACWriteReg(RegBase, RegOffset, data); + // writel(data,(void *)addr); + #if SYNOP_REG_DEBUG + TR("%s !!!!!!!!!!!!! RegOffset = 0x%08x RegData = 0x%08x\n", __FUNCTION__, RegOffset, data ); + #endif + return; +} + + +/** + * The Low level function to clear bits of a register in Hardware. + * + * @param[in] pointer to the base of register map + * @param[in] Offset from the base + * @param[in] Bit mask to clear bits to logical 0 + * \return void + */ +static void synopGMACClearBits(u64 RegBase, u32 RegOffset, u32 BitPos) +{ + u32 data; + data = synopGMACReadReg(RegBase, RegOffset); + data &= (~BitPos); + synopGMACWriteReg(RegBase, RegOffset, data); + #if SYNOP_REG_DEBUG + TR("%s !!!!!!!!!!!!! RegOffset = 0x%08x RegData = 0x%08x\n", __FUNCTION__, RegOffset, data ); + #endif + return; +} + +/** + * The Low level function to Check the setting of the bits. + * + * @param[in] pointer to the base of register map + * @param[in] Offset from the base + * @param[in] Bit mask to set bits to logical 1 + * \return returns TRUE if set to '1' returns FALSE if set to '0'. Result undefined there are no bit set in the BitPos argument. + * + */ +static bool synopGMACCheckBits(u64 RegBase, u32 RegOffset, u32 BitPos) +{ + u32 data; + data = synopGMACReadReg(RegBase, RegOffset); + data &= BitPos; + + if(data) + { + return true; + } + else + { + return false; + } +} + +#endif diff --git a/bsp/ls2kdev/drivers/net/synopGMAC_types.h b/bsp/ls2kdev/drivers/net/synopGMAC_types.h new file mode 100644 index 0000000000000000000000000000000000000000..52c7870905ead3f5b540fb962e57e77b3c83512f --- /dev/null +++ b/bsp/ls2kdev/drivers/net/synopGMAC_types.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-08-24 chinesebear first version + */ + +#ifndef __TYPES__H +#define __TYPES__H + +typedef unsigned char uint8_t; +typedef unsigned long long u64; +typedef unsigned int u32; +typedef unsigned short u16; +typedef unsigned char u8; +typedef signed int s32; + +typedef u32 dma_addr_t; + +#endif /*__TYPES__H*/ diff --git a/bsp/ls2kdev/rtconfig.h b/bsp/ls2kdev/rtconfig.h index c18aef3d38cf38f0a6bd06ce3d1e6ed807002aed..7399ca03369ef00f785a3c7bd98de46610d68324 100644 --- a/bsp/ls2kdev/rtconfig.h +++ b/bsp/ls2kdev/rtconfig.h @@ -6,16 +6,16 @@ /* RT-Thread Kernel */ -#define RT_NAME_MAX 8 +#define RT_NAME_MAX 30 #define RT_ALIGN_SIZE 8 #define RT_THREAD_PRIORITY_32 #define RT_THREAD_PRIORITY_MAX 32 -#define RT_TICK_PER_SECOND 100 +#define RT_TICK_PER_SECOND 1000 #define RT_USING_OVERFLOW_CHECK #define RT_USING_HOOK #define RT_USING_IDLE_HOOK #define RT_IDLE_HOOK_LIST_SIZE 4 -#define IDLE_THREAD_STACK_SIZE 2048 +#define IDLE_THREAD_STACK_SIZE 16384 #define RT_DEBUG /* Inter-Thread communication */ @@ -39,13 +39,14 @@ #define RT_CONSOLEBUF_SIZE 256 #define RT_CONSOLE_DEVICE_NAME "uart" #define RT_VER_NUM 0x40003 +#define ARCH_CPU_64BIT #define ARCH_MIPS64 /* RT-Thread Components */ #define RT_USING_COMPONENTS_INIT #define RT_USING_USER_MAIN -#define RT_MAIN_THREAD_STACK_SIZE 2048 +#define RT_MAIN_THREAD_STACK_SIZE 16384 #define RT_MAIN_THREAD_PRIORITY 10 /* C++ features */ @@ -60,7 +61,7 @@ #define FINSH_USING_SYMTAB #define FINSH_USING_DESCRIPTION #define FINSH_THREAD_PRIORITY 20 -#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_THREAD_STACK_SIZE 16384 #define FINSH_CMD_SIZE 80 #define FINSH_USING_MSH #define FINSH_USING_MSH_DEFAULT @@ -70,15 +71,30 @@ #define RT_USING_DFS #define DFS_USING_WORKDIR -#define DFS_FILESYSTEMS_MAX 2 -#define DFS_FILESYSTEM_TYPES_MAX 2 +#define DFS_FILESYSTEMS_MAX 10 +#define DFS_FILESYSTEM_TYPES_MAX 10 #define DFS_FD_MAX 16 +#define RT_USING_DFS_ELMFAT + +/* elm-chan's FatFs, Generic FAT Filesystem Module */ + +#define RT_DFS_ELM_CODE_PAGE 936 +#define RT_DFS_ELM_WORD_ACCESS +#define RT_DFS_ELM_USE_LFN_3 +#define RT_DFS_ELM_USE_LFN 3 +#define RT_DFS_ELM_MAX_LFN 255 +#define RT_DFS_ELM_DRIVES 9 +#define RT_DFS_ELM_MAX_SECTOR_SIZE 512 +#define RT_DFS_ELM_REENTRANT #define RT_USING_DFS_DEVFS /* Device Drivers */ #define RT_USING_DEVICE_IPC #define RT_PIPE_BUFSZ 512 +#define RT_USING_SYSTEM_WORKQUEUE +#define RT_SYSTEM_WORKQUEUE_STACKSIZE 16384 +#define RT_SYSTEM_WORKQUEUE_PRIORITY 5 #define RT_USING_SERIAL #define RT_SERIAL_USING_DMA #define RT_SERIAL_RB_BUFSZ 64 @@ -96,12 +112,69 @@ /* Socket abstraction layer */ +#define RT_USING_SAL + +/* protocol stack implement */ + +#define SAL_USING_LWIP +#define SAL_SOCKETS_NUM 16 /* Network interface device */ +#define RT_USING_NETDEV +#define NETDEV_USING_IFCONFIG +#define NETDEV_USING_PING +#define NETDEV_USING_NETSTAT +#define NETDEV_USING_AUTO_DEFAULT +#define NETDEV_IPV4 1 +#define NETDEV_IPV6 0 /* light weight TCP/IP stack */ +#define RT_USING_LWIP +#define RT_USING_LWIP202 +#define RT_LWIP_MEM_ALIGNMENT 8 +#define RT_LWIP_IGMP +#define RT_LWIP_ICMP +#define RT_LWIP_SNMP +#define RT_LWIP_DNS +#define RT_LWIP_DHCP +#define IP_SOF_BROADCAST 1 +#define IP_SOF_BROADCAST_RECV 1 + +/* Static IPv4 Address */ + +#define RT_LWIP_IPADDR "192.168.1.30" +#define RT_LWIP_GWADDR "192.168.1.1" +#define RT_LWIP_MSKADDR "255.255.255.0" +#define RT_LWIP_UDP +#define RT_LWIP_TCP +#define RT_LWIP_RAW +#define RT_MEMP_NUM_NETCONN 8 +#define RT_LWIP_PBUF_NUM 16 +#define RT_LWIP_RAW_PCB_NUM 4 +#define RT_LWIP_UDP_PCB_NUM 4 +#define RT_LWIP_TCP_PCB_NUM 4 +#define RT_LWIP_TCP_SEG_NUM 40 +#define RT_LWIP_TCP_SND_BUF 8196 +#define RT_LWIP_TCP_WND 8196 +#define RT_LWIP_TCPTHREAD_PRIORITY 5 +#define RT_LWIP_TCPTHREAD_MBOX_SIZE 32 +#define RT_LWIP_TCPTHREAD_STACKSIZE 16384 +#define RT_LWIP_ETHTHREAD_PRIORITY 5 +#define RT_LWIP_ETHTHREAD_STACKSIZE 16384 +#define RT_LWIP_ETHTHREAD_MBOX_SIZE 32 +#define RT_LWIP_REASSEMBLY_FRAG +#define LWIP_NETIF_STATUS_CALLBACK 1 +#define LWIP_NETIF_LINK_CALLBACK 1 +#define SO_REUSE 1 +#define LWIP_SO_RCVTIMEO 1 +#define LWIP_SO_SNDTIMEO 1 +#define LWIP_SO_RCVBUF 1 +#define LWIP_SO_LINGER 0 +#define LWIP_NETIF_LOOPBACK 0 +#define RT_LWIP_STATS +#define RT_LWIP_USING_PING /* AT commands */ @@ -145,6 +218,9 @@ /* system packages */ +#define PKG_USING_LWEXT4 +#define RT_USING_DFS_LWEXT4 +#define PKG_USING_LWEXT4_LATEST_VERSION /* peripheral libraries and drivers */ @@ -154,12 +230,6 @@ /* samples: kernel and components samples */ - -/* Privated Packages of RealThread */ - - -/* Network Utilities */ - #define SOC_LS2K1000 #endif diff --git a/components/net/Kconfig b/components/net/Kconfig index 45bc8d101c013a9ba5358419317859d7014fddcd..3a4f39ed49f4b7d86288d549646448cdb8172d65 100644 --- a/components/net/Kconfig +++ b/components/net/Kconfig @@ -118,7 +118,7 @@ config RT_USING_LWIP config RT_USING_LWIP202 bool "lwIP v2.0.2" - config RT_USING_LWIP212 + config RT_USING_LWIP212 bool "lwIP v2.1.2" endchoice @@ -131,6 +131,10 @@ config RT_USING_LWIP select NETDEV_IPV6_SCOPES if RT_USING_LWIP212 endif + config RT_LWIP_MEM_ALIGNMENT + int "Memory alignment" + default 4 + config RT_LWIP_IGMP bool "IGMP protocol" default y diff --git a/components/net/lwip-2.0.2/src/arch/sys_arch.c b/components/net/lwip-2.0.2/src/arch/sys_arch.c index f7ed6eedec6df40e5ae767ca3602f50628a9d7b6..40c79011ec612e762276212c16ae7aed10fe859d 100644 --- a/components/net/lwip-2.0.2/src/arch/sys_arch.c +++ b/components/net/lwip-2.0.2/src/arch/sys_arch.c @@ -460,7 +460,7 @@ void sys_mbox_post(sys_mbox_t *mbox, void *msg) { RT_DEBUG_NOT_IN_INTERRUPT; - rt_mb_send_wait(*mbox, (rt_uint32_t)msg, RT_WAITING_FOREVER); + rt_mb_send_wait(*mbox, (rt_ubase_t)msg, RT_WAITING_FOREVER); return; } @@ -472,7 +472,7 @@ void sys_mbox_post(sys_mbox_t *mbox, void *msg) */ err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) { - if (rt_mb_send(*mbox, (rt_uint32_t)msg) == RT_EOK) + if (rt_mb_send(*mbox, (rt_ubase_t)msg) == RT_EOK) return ERR_OK; return ERR_MEM; diff --git a/components/net/lwip-2.0.2/src/lwipopts.h b/components/net/lwip-2.0.2/src/lwipopts.h index c53863e1abe858b14df28b838a8a8ec3292b2da6..09bd223aa4245b6501dc034d5b8b7728b99b11fb 100644 --- a/components/net/lwip-2.0.2/src/lwipopts.h +++ b/components/net/lwip-2.0.2/src/lwipopts.h @@ -230,7 +230,12 @@ #define LWIP_DBG_TYPES_ON (LWIP_DBG_ON|LWIP_DBG_TRACE|LWIP_DBG_STATE|LWIP_DBG_FRESH|LWIP_DBG_HALT) /* ---------- Memory options ---------- */ +#ifdef RT_LWIP_MEM_ALIGNMENT +#define MEM_ALIGNMENT RT_LWIP_MEM_ALIGNMENT +#else #define MEM_ALIGNMENT 4 +#endif + #define MEMP_OVERFLOW_CHECK 1 //// #define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 1 //// //#define MEM_LIBC_MALLOC 1 diff --git a/components/net/lwip-2.0.2/src/netif/ethernetif.c b/components/net/lwip-2.0.2/src/netif/ethernetif.c index 2fa528aa0dd12bf638bd518c3258d48f04c976ec..b93acb1fcf8b3648e389c8637a959f4afbfeab09 100644 --- a/components/net/lwip-2.0.2/src/netif/ethernetif.c +++ b/components/net/lwip-2.0.2/src/netif/ethernetif.c @@ -38,6 +38,7 @@ * after lwIP initialization. * 2013-02-28 aozima fixed list_tcps bug: ipaddr_ntoa isn't reentrant. * 2016-08-18 Bernard port to lwIP 2.0.0 + * 2020-08-10 lizhirui fixed some problems when this is running on 64-bit cpu */ #include "lwip/opt.h" @@ -85,10 +86,10 @@ struct eth_tx_msg static struct rt_mailbox eth_tx_thread_mb; static struct rt_thread eth_tx_thread; #ifndef RT_LWIP_ETHTHREAD_MBOX_SIZE -static char eth_tx_thread_mb_pool[32 * 4]; +static char eth_tx_thread_mb_pool[32 * sizeof(rt_ubase_t)]; static char eth_tx_thread_stack[512]; #else -static char eth_tx_thread_mb_pool[RT_LWIP_ETHTHREAD_MBOX_SIZE * 4]; +static char eth_tx_thread_mb_pool[RT_LWIP_ETHTHREAD_MBOX_SIZE * sizeof(rt_ubase_t)]; static char eth_tx_thread_stack[RT_LWIP_ETHTHREAD_STACKSIZE]; #endif #endif @@ -97,10 +98,10 @@ static char eth_tx_thread_stack[RT_LWIP_ETHTHREAD_STACKSIZE]; static struct rt_mailbox eth_rx_thread_mb; static struct rt_thread eth_rx_thread; #ifndef RT_LWIP_ETHTHREAD_MBOX_SIZE -static char eth_rx_thread_mb_pool[48 * 4]; +static char eth_rx_thread_mb_pool[48 * sizeof(rt_ubase_t)]; static char eth_rx_thread_stack[1024]; #else -static char eth_rx_thread_mb_pool[RT_LWIP_ETHTHREAD_MBOX_SIZE * 4]; +static char eth_rx_thread_mb_pool[RT_LWIP_ETHTHREAD_MBOX_SIZE * sizeof(rt_ubase_t)]; static char eth_rx_thread_stack[RT_LWIP_ETHTHREAD_STACKSIZE]; #endif #endif @@ -395,7 +396,7 @@ static err_t ethernetif_linkoutput(struct netif *netif, struct pbuf *p) /* send a message to eth tx thread */ msg.netif = netif; msg.buf = p; - if (rt_mb_send(ð_tx_thread_mb, (rt_uint32_t) &msg) == RT_EOK) + if (rt_mb_send(ð_tx_thread_mb, (rt_ubase_t) &msg) == RT_EOK) { /* waiting for ack */ rt_sem_take(&(enetif->tx_ack), RT_WAITING_FOREVER); @@ -599,7 +600,7 @@ rt_err_t eth_device_ready(struct eth_device* dev) { if (dev->netif) /* post message to Ethernet thread */ - return rt_mb_send(ð_rx_thread_mb, (rt_uint32_t)dev); + return rt_mb_send(ð_rx_thread_mb, (rt_ubase_t)dev); else return ERR_OK; /* netif is not initialized yet, just return. */ } @@ -619,7 +620,7 @@ rt_err_t eth_device_linkchange(struct eth_device* dev, rt_bool_t up) rt_hw_interrupt_enable(level); /* post message to ethernet thread */ - return rt_mb_send(ð_rx_thread_mb, (rt_uint32_t)dev); + return rt_mb_send(ð_rx_thread_mb, (rt_ubase_t)dev); } #else /* NOTE: please not use it in interrupt when no RxThread exist */ @@ -739,7 +740,7 @@ int eth_system_device_init_private(void) #ifndef LWIP_NO_RX_THREAD /* initialize mailbox and create Ethernet Rx thread */ result = rt_mb_init(ð_rx_thread_mb, "erxmb", - ð_rx_thread_mb_pool[0], sizeof(eth_rx_thread_mb_pool)/4, + ð_rx_thread_mb_pool[0], sizeof(eth_rx_thread_mb_pool)/sizeof(rt_ubase_t), RT_IPC_FLAG_FIFO); RT_ASSERT(result == RT_EOK); @@ -755,7 +756,7 @@ int eth_system_device_init_private(void) #ifndef LWIP_NO_TX_THREAD /* initialize mailbox and create Ethernet Tx thread */ result = rt_mb_init(ð_tx_thread_mb, "etxmb", - ð_tx_thread_mb_pool[0], sizeof(eth_tx_thread_mb_pool)/4, + ð_tx_thread_mb_pool[0], sizeof(eth_tx_thread_mb_pool)/sizeof(rt_ubase_t), RT_IPC_FLAG_FIFO); RT_ASSERT(result == RT_EOK); diff --git a/components/net/uip/rt-thread/uip_ethernetif.c b/components/net/uip/rt-thread/uip_ethernetif.c index fa4e52461e0284018fad116fd7378f743d67b245..4fef184f4a678d703afb2069392ce8edddc78f71 100644 --- a/components/net/uip/rt-thread/uip_ethernetif.c +++ b/components/net/uip/rt-thread/uip_ethernetif.c @@ -63,11 +63,11 @@ static struct rt_mailbox eth_rx_thread_mb; static struct rt_thread eth_rx_thread; #ifndef RT_LWIP_ETHTHREAD_PRIORITY #define RT_ETHERNETIF_THREAD_PREORITY 0x90 -static char eth_rx_thread_mb_pool[48 * 4]; +static char eth_rx_thread_mb_pool[48 * sizeof(rt_ubase_t)]; static char eth_rx_thread_stack[1024]; #else #define RT_ETHERNETIF_THREAD_PREORITY RT_LWIP_ETHTHREAD_PRIORITY -static char eth_rx_thread_mb_pool[RT_LWIP_ETHTHREAD_MBOX_SIZE * 4]; +static char eth_rx_thread_mb_pool[RT_LWIP_ETHTHREAD_MBOX_SIZE * sizeof(rt_ubase_t)]; static char eth_rx_thread_stack[RT_LWIP_ETHTHREAD_STACKSIZE]; #endif @@ -79,10 +79,10 @@ struct eth_tx_msg static struct rt_mailbox eth_tx_thread_mb; static struct rt_thread eth_tx_thread; #ifndef RT_LWIP_ETHTHREAD_PRIORITY -static char eth_tx_thread_mb_pool[32 * 4]; +static char eth_tx_thread_mb_pool[32 * sizeof(rt_ubase_t)]; static char eth_tx_thread_stack[512]; #else -static char eth_tx_thread_mb_pool[RT_LWIP_ETHTHREAD_MBOX_SIZE * 4]; +static char eth_tx_thread_mb_pool[RT_LWIP_ETHTHREAD_MBOX_SIZE * sizeof(rt_ubase_t)]; static char eth_tx_thread_stack[RT_LWIP_ETHTHREAD_STACKSIZE]; #endif @@ -281,7 +281,7 @@ rt_err_t eth_system_device_init() /* init rx thread */ /* init mailbox and create ethernet thread */ result = rt_mb_init(ð_rx_thread_mb, "erxmb", - ð_rx_thread_mb_pool[0], sizeof(eth_rx_thread_mb_pool)/4, + ð_rx_thread_mb_pool[0], sizeof(eth_rx_thread_mb_pool)/sizeof(rt_ubase_t), RT_IPC_FLAG_FIFO); RT_ASSERT(result == RT_EOK); @@ -297,7 +297,7 @@ rt_err_t eth_system_device_init() /* init mailbox and create ethernet thread */ result = rt_mb_init(ð_tx_thread_mb, "etxmb", - ð_tx_thread_mb_pool[0], sizeof(eth_tx_thread_mb_pool)/4, + ð_tx_thread_mb_pool[0], sizeof(eth_tx_thread_mb_pool)/sizeof(rt_ubase_t), RT_IPC_FLAG_FIFO); RT_ASSERT(result == RT_EOK); diff --git a/libcpu/Kconfig b/libcpu/Kconfig index e355664de2fabfd837ccd2ea326665c4a3b02951..ae2767dec9ca53cfe5e53fd4b3a73f8040b7363b 100644 --- a/libcpu/Kconfig +++ b/libcpu/Kconfig @@ -82,6 +82,10 @@ config ARCH_MIPS config ARCH_MIPS64 bool + select ARCH_CPU_64BIT + +config ARCH_CPU_64BIT + bool config ARCH_MIPS_XBURST bool diff --git a/libcpu/mips/common/context_gcc.S b/libcpu/mips/common/context_gcc.S index cdcdede39a5955e5265b2a3f3cd5429fae88b70e..3fdbe374c9b226d1e6ed1bf9c0228013355124e8 100644 --- a/libcpu/mips/common/context_gcc.S +++ b/libcpu/mips/common/context_gcc.S @@ -1,11 +1,12 @@ /* - * Copyright (c) 2006-2019, RT-Thread Development Team + * Copyright (c) 2006-2020, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2019-12-04 Jiaxun Yang Initial version + * 2020-07-26 lizhirui Fixed some problems */ #ifndef __ASSEMBLY__ @@ -56,12 +57,12 @@ rt_hw_context_switch_interrupt: bnez t1, _reswitch nop li t1, 0x01 /* set rt_thread_switch_interrupt_flag to 1 */ - sw t1, 0(t0) + LONG_S t1, 0(t0) PTR_LA t0, rt_interrupt_from_thread /* set rt_interrupt_from_thread */ - sw a0, 0(t0) + LONG_S a0, 0(t0) _reswitch: PTR_LA t0, rt_interrupt_to_thread /* set rt_interrupt_to_thread */ - sw a1, 0(t0) + LONG_S a1, 0(t0) jr ra nop @@ -97,24 +98,24 @@ mips_irq_handle: * rt_hw_context_switch_interrupt_do and do not return */ PTR_LA k0, rt_thread_switch_interrupt_flag - lw k1, 0(k0) + LONG_L k1, 0(k0) beqz k1, spurious_interrupt nop - sw zero, 0(k0) /* clear flag */ + LONG_S zero, 0(k0) /* clear flag */ nop /* * switch to the new thread */ PTR_LA k0, rt_interrupt_from_thread - lw k1, 0(k0) + LONG_L k1, 0(k0) nop - sw sp, 0(k1) /* store sp in preempted task TCB */ + LONG_S sp, 0(k1) /* store sp in preempted task TCB */ PTR_LA k0, rt_interrupt_to_thread - lw k1, 0(k0) + LONG_L k1, 0(k0) nop - lw sp, 0(k1) /* get new task stack pointer */ + LONG_L sp, 0(k1) /* get new task stack pointer */ j spurious_interrupt nop diff --git a/libcpu/mips/common/exception.c b/libcpu/mips/common/exception.c index 84bb0446d69812fa6236d02e85beb356ef2f9c8e..94be4758782c77effbd079c699590af871493f9d 100644 --- a/libcpu/mips/common/exception.c +++ b/libcpu/mips/common/exception.c @@ -24,6 +24,41 @@ rt_ubase_t rt_interrupt_from_thread; rt_ubase_t rt_interrupt_to_thread; rt_ubase_t rt_thread_switch_interrupt_flag; +const char *exception_name[] = { + "Interrupt", + "(X)TLB Modify Exception", + "(X)TLB Read/Fetch Exception", + "(X)TLB Write Exception", + "Address Read/Fetch Exception", + "Address Write Exception", + "", + "", + "Syscall", + "Breakpoint", + "Reversed Instruction Exception", + "Coprocessor Unit Invalid", + "Overflow", + "Trap", + "FPU Exception in Vector Instruction", + "FPU Exception", + "Loongson Custom Exception", + "", + "", + "(X)TLB Read Denied Exception", + "(X)TLB Execute Denied Exception", + "Vector Module Disabled Exception", + "", + "", + "", + "", + "", + "", + "", + "", + "Cache Error Exception", + "" + }; + rt_base_t rt_hw_interrupt_disable(void) { rt_base_t status = read_c0_status(); @@ -87,10 +122,15 @@ void cache_error_handler(void) static void unhandled_exception_handle(struct pt_regs *regs) { - rt_kprintf("Unknown Exception, EPC: 0x%08x, CAUSE: 0x%08x\n", read_c0_epc(), - read_c0_cause()); - rt_kprintf("ST0: 0x%08x ", regs->cp0_status); - rt_kprintf("ErrorPC: 0x%08x\n", read_c0_errorepc()); + rt_kprintf("Unknown Exception, EPC: 0x%p, CAUSE: 0x%08x\n", read_c0_epc(), read_c0_cause()); + rt_kprintf("Exception Name:%s\n",exception_name[(read_c0_cause() >> 2) & 0x1f]); +#ifdef SOC_LS2K1000 + rt_kprintf("ExeCode = 0x%08x,BadAddr = 0x%p\n",(read_c0_cause() >> 2) & 0x1f,mmu_tlb_get_bad_vaddr()); +#else + rt_kprintf("ExeCode = 0x%08x\n",(read_c0_cause() >> 2) & 0x1f); +#endif + rt_kprintf("ST0: 0x%08x ",regs->cp0_status); + rt_kprintf("ErrorPC: 0x%p\n",read_c0_errorepc()); mips_dump_regs(regs); rt_hw_cpu_shutdown(); } diff --git a/libcpu/mips/common/exception_gcc.S b/libcpu/mips/common/exception_gcc.S index 9664438ac1a6373a733ff2c090020d94b7b0f1cc..c685928a8401a31d5da92a0a3d4e932241dfca7b 100644 --- a/libcpu/mips/common/exception_gcc.S +++ b/libcpu/mips/common/exception_gcc.S @@ -1,11 +1,12 @@ /* - * Copyright (c) 2006-2019, RT-Thread Development Team + * Copyright (c) 2006-2020, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2019-12-04 Jiaxun Yang Initial version + * 2020-07-26 lizhirui Add xtlb exception entry */ #ifndef __ASSEMBLY__ #define __ASSEMBLY__ @@ -26,6 +27,11 @@ tlb_refill_exception: b _general_exception_handler nop + /* 0x080 - XTLB refill handler */ + .org ebase_start + 0x080 + b _general_exception_handler + nop + /* 0x100 - Cache error handler */ .org ebase_start + 0x100 j cache_error_handler diff --git a/libcpu/mips/common/stackframe.h b/libcpu/mips/common/stackframe.h index 4f1157aebfbbf9c38c61a7d343fa7de00b21a401..bb92a18c9c0d2349a6c4037dce1e672ce1ff78d5 100644 --- a/libcpu/mips/common/stackframe.h +++ b/libcpu/mips/common/stackframe.h @@ -206,6 +206,8 @@ li v1, ~(ST0_CU1 | ST0_FR | ST0_IM) and v0, v1 or v0, a0 + li v1, (ST0_KX | ST0_SX | ST0_UX) + or v0, v1 mtc0 v0, CP0_STATUS LONG_L v1, PT_EPC(sp) MTC0 v1, CP0_EPC diff --git a/libcpu/mips/gs264/cache.c b/libcpu/mips/gs264/cache.c new file mode 100644 index 0000000000000000000000000000000000000000..54d38d0d3f515b4e10da9d81bc485c40450b7394 --- /dev/null +++ b/libcpu/mips/gs264/cache.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-03-29 quanzhao the first version + * 2020-07-26 lizhirui porting to ls2k + */ + +#include +#include + +rt_inline rt_uint64_t rt_cpu_icache_line_size(void) +{ + rt_uint64_t ctr; + return 4 << (ctr & 0xF); +} + +rt_inline rt_uint64_t rt_cpu_dcache_line_size(void) +{ + rt_uint64_t ctr; + return 4 << ((ctr >> 16) & 0xF); +} + +void rt_hw_cpu_icache_invalidate(void *addr, int size) +{ + rt_uint64_t line_size = rt_cpu_icache_line_size(); + rt_uint64_t start_addr = (rt_uint64_t)addr; + rt_uint64_t end_addr = (rt_uint64_t) addr + size + line_size - 1; +} + +void rt_hw_cpu_dcache_invalidate(void *addr, int size) +{ + rt_uint64_t line_size = rt_cpu_dcache_line_size(); + rt_uint64_t start_addr = (rt_uint64_t)addr; + rt_uint64_t end_addr = (rt_uint64_t) addr + size + line_size - 1; +} + +void rt_hw_cpu_dcache_clean(void *addr, int size) +{ + rt_uint64_t line_size = rt_cpu_dcache_line_size(); + rt_uint64_t start_addr = (rt_uint64_t)addr; + rt_uint64_t end_addr = (rt_uint64_t) addr + size + line_size - 1; +} + +void rt_hw_cpu_icache_ops(int ops, void *addr, int size) +{ + if (ops == RT_HW_CACHE_INVALIDATE) + rt_hw_cpu_icache_invalidate(addr, size); +} + +void rt_hw_cpu_dcache_ops(int ops, void *addr, int size) +{ + if (ops == RT_HW_CACHE_FLUSH) + rt_hw_cpu_dcache_clean(addr, size); + else if (ops == RT_HW_CACHE_INVALIDATE) + rt_hw_cpu_dcache_invalidate(addr, size); +} + +rt_base_t rt_hw_cpu_icache_status(void) +{ + return 0; +} + +rt_base_t rt_hw_cpu_dcache_status(void) +{ + return 0; +} diff --git a/libcpu/mips/gs264/cache.h b/libcpu/mips/gs264/cache.h new file mode 100644 index 0000000000000000000000000000000000000000..10a4afd899a2dae18a5ab0819e6199f3d03c5e4b --- /dev/null +++ b/libcpu/mips/gs264/cache.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-03-25 quanzhao the first version + */ +#ifndef __CACHE_H__ +#define __CACHE_H__ + +unsigned long rt_cpu_get_smp_id(void); + +void rt_cpu_mmu_disable(void); +void rt_cpu_mmu_enable(void); +void rt_cpu_tlb_set(volatile unsigned long*); + +void rt_cpu_dcache_clean_flush(void); +void rt_cpu_icache_flush(void); + +void rt_cpu_vector_set_base(unsigned int addr); + +#endif diff --git a/libcpu/mips/gs264/cpuinit_gcc.S b/libcpu/mips/gs264/cpuinit_gcc.S index bd8466335096fa138f3372e473eec8fe11979ac5..592fedd88ab25eed70e94bc69f38aa428bc92cc5 100644 --- a/libcpu/mips/gs264/cpuinit_gcc.S +++ b/libcpu/mips/gs264/cpuinit_gcc.S @@ -19,8 +19,8 @@ .globl rt_cpu_early_init rt_cpu_early_init: - mfc0 t0, CP0_CONFIG - ori t0, 3 - mtc0 t0, CP0_CONFIG + mfc0 t0, CP0_CONFIG + ori t0, 3 + mtc0 t0, CP0_CONFIG ehb - jr ra \ No newline at end of file + jr ra diff --git a/libcpu/mips/gs264/mips_mmu.c b/libcpu/mips/gs264/mips_mmu.c new file mode 100644 index 0000000000000000000000000000000000000000..7bed69596a4ec573c0e7b8be2de8eb9ad8677aeb --- /dev/null +++ b/libcpu/mips/gs264/mips_mmu.c @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-07-26 lizhirui the first version + */ + +#include +#include + +#include "mips.h" +#include "mips_mmu.h" + +void mmu_init() +{ + uint32_t status = read_c0_status(); + status |= 0x07 << 5;//ux = 1,sx = 1,kx = 1 + write_c0_status(status); + + mmu_clear_tlb(); + mmu_clear_itlb(); +} + +void mmu_set_cpu_mode(cpu_mode_t cpu_mode) +{ + uint32_t status = read_c0_status(); + status &= ~(0x03 << 3); + status |= ((uint32_t)cpu_mode & 0x03) << 3; + write_c0_status(status); +} + +cpu_mode_t mmu_get_cpu_mode() +{ + uint32_t status = read_c0_status(); + return (cpu_mode_t)((status >> 3) & 0x03); +} + +void mmu_clear_tlb() +{ + uint32_t max_tlb_index = mmu_get_max_tlb_index(); + uint64_t va = KSEG0BASE; + uint32_t entry; + tlb_item_t tlb_item; + + for(entry = 0;entry <= max_tlb_index;entry++) + { + mmu_tlb_item_init(&tlb_item); + mmu_tlb_write_indexed(entry,&tlb_item); + } +} + +void mmu_clear_itlb() +{ + uint32_t diag = read_c0_diag(); + write_c0_diag(diag | (0x01 << 2));//write ITLB bit + read_c0_entrylo0(); +} + +uint32_t mmu_get_max_tlb_index() +{ + uint32_t config1 = read_c0_config1(); + return ((config1 >> 25) & 0x3F); +} + +void mmu_tlb_write_indexed(uint32_t index,tlb_item_t *tlb_item) +{ + tlb_item -> entry_lo[0].g |= tlb_item -> entry_lo[1].g; + tlb_item -> entry_lo[1].g |= tlb_item -> entry_lo[0].g; + mmu_tlb_set_index(index); + write_c0_entrylo0(reg_type_convert(tlb_item -> entry_lo[0],uint64_t)); + write_c0_entrylo1(reg_type_convert(tlb_item -> entry_lo[1],uint64_t)); + write_c0_entryhi(reg_type_convert(tlb_item -> entry_hi,uint64_t)); + write_c0_pagemask(reg_type_convert(tlb_item -> page_mask,uint64_t)); + tlb_write_indexed(); + read_c0_entrylo0(); +} + +void mmu_tlb_write_random(tlb_item_t *tlb_item) +{ + tlb_item -> entry_lo[0].g |= tlb_item -> entry_lo[1].g; + tlb_item -> entry_lo[1].g |= tlb_item -> entry_lo[0].g; + write_c0_entrylo0(reg_type_convert(tlb_item -> entry_lo[0],uint64_t)); + write_c0_entrylo1(reg_type_convert(tlb_item -> entry_lo[1],uint64_t)); + write_c0_entryhi(reg_type_convert(tlb_item -> entry_hi,uint64_t)); + write_c0_pagemask(reg_type_convert(tlb_item -> page_mask,uint64_t)); + tlb_write_random(); + read_c0_entrylo0(); +} + +void mmu_tlb_read(uint32_t index,tlb_item_t *tlb_item) +{ + mmu_tlb_set_index(index); + tlb_read(); + uint64_t entrylo[2]; + uint64_t entryhi; + uint64_t page_mask; + entrylo[0] = read_c0_entrylo0(); + entrylo[1] = read_c0_entrylo1(); + entryhi = read_c0_entryhi(); + page_mask = read_c0_pagemask(); + tlb_item -> entry_lo[0] = reg_type_convert(entrylo[0],entry_lo_t); + tlb_item -> entry_lo[1] = reg_type_convert(entrylo[1],entry_lo_t); + tlb_item -> entry_hi = reg_type_convert(entryhi,entry_hi_t); + tlb_item -> page_mask = reg_type_convert(page_mask,page_mask_t); +} + +uint32_t mmu_tlb_find(uint64_t vpn,uint32_t asid,uint32_t *index) +{ + entry_hi_t entry_hi; + entry_hi.r = (vpn >> 62) & 0x03; + entry_hi.vpn2 = (vpn >> 13) & 0x7FFFFFFU; + entry_hi.asid = asid & 0xFFU; + tlb_item_t tlb_item; + //mmu_tlb_read(6,&tlb_item); + //tlb_dump(); + mmu_tlb_item_init(&tlb_item); + tlb_item.entry_lo[0].g = tlb_item.entry_lo[1].g = 1; + read_c0_entrylo0();//i don't know why,but if i don't read any register of mmu,tplb will be failed in qemu. + write_c0_entrylo0(reg_type_convert(tlb_item.entry_lo[0],uint64_t)); + write_c0_entrylo1(reg_type_convert(tlb_item.entry_lo[1],uint64_t)); + write_c0_entryhi(reg_type_convert(entry_hi,uint64_t)); + //__asm__ __volatile__("ehb"); + //read_c0_entryhi(); + //rt_kprintf("entry_hi = %p\n",read_c0_entryhi()); + tlb_probe(); + *index = mmu_tlb_get_index(); + return mmu_tlb_is_matched(); +} + +void mmu_tlb_item_init(tlb_item_t *tlb_item) +{ + memset(tlb_item,0,sizeof(tlb_item_t)); + tlb_item -> entry_lo[0].c = 0x03; + tlb_item -> entry_lo[1].c = 0x03; +} + +void mmu_set_map(uint64_t vpn,uint64_t ppn,page_mask_enum_t page_mask,uint32_t asid,uint32_t global) +{ + uint64_t page_mask_v = (uint64_t)page_mask; + + /*if(page_mask_v & (1 << 13)) + { + page_mask_v |= (1 << 12); + }*/ + + uint64_t lb = lowbit((~(page_mask_v)) << 12); + uint64_t pn_remained = ((~(page_mask_v)) << 12) | lb; + vpn &= pn_remained; + ppn &= pn_remained; + uint64_t odd_vpn = vpn | lb; + uint64_t even_vpn = vpn & (~lb); + uint32_t index; + tlb_item_t tlb_item,tlb2_item; + + mmu_tlb_item_init(&tlb_item); + mmu_tlb_item_init(&tlb2_item); + tlb_item.page_mask.mask = page_mask; + + if(mmu_tlb_find(vpn & (~lb),asid,&index)) + { + mmu_tlb_read(index,&tlb_item); + mmu_tlb_write_indexed(index,&tlb2_item); + } + + entry_lo_t *entry_lo = &tlb_item.entry_lo[vpn == even_vpn ? 0 : 1]; + tlb_item.entry_lo[0].g = tlb_item.entry_lo[1].g = global; + entry_lo -> d = 1; + entry_lo -> ri = 0; + entry_lo -> xi = 0; + entry_lo -> v = 1; + entry_lo -> pfn = ppn >> 12; + tlb_item.entry_hi.r = (vpn >> 62) & 0x03; + tlb_item.entry_hi.vpn2 = (vpn >> 13) & 0x7FFFFFFU; + tlb_item.entry_hi.asid = asid & 0xFFU; + mmu_tlb_write_random(&tlb_item); +} + +uint32_t mmu_tlb_get_random() +{ + return read_c0_random(); +} + +uint32_t mmu_tlb_get_index() +{ + return read_c0_index() & 0x3F; +} + +void mmu_tlb_set_index(uint32_t index) +{ + write_c0_index(index & 0x3F); +} + +uint32_t mmu_tlb_is_matched() +{ + return (read_c0_index() & 0x80000000) == 0; +} + +uint64_t mmu_tlb_get_bad_vaddr() +{ + return read_c0_badvaddr(); +} + +void tlb_dump() +{ + uint32_t max_index = mmu_get_max_tlb_index(); + //uint32_t max_index = 10; + uint32_t entry; + tlb_item_t tlb_item; + + for(entry = 0;entry <= max_index;entry++) + { + mmu_tlb_read(entry,&tlb_item); + //mmu_tlb_write_indexed(entry,&tlb_item); + //mmu_tlb_read(entry,&tlb_item); + rt_kprintf("vpn = 0x%p,ppn0 = 0x%p,ppn1 = 0x%p\n",(uint64_t)tlb_item.entry_hi.vpn2 << 13 | (uint64_t)tlb_item.entry_hi.asid << 62,(uint64_t)tlb_item.entry_lo[0].pfn << 12,(uint64_t)tlb_item.entry_lo[1].pfn << 12); + rt_kprintf("v = %d,d = %d,g = %d,ri = %d,xi = %d,c = %d\n",tlb_item.entry_lo[0].v,tlb_item.entry_lo[0].d,tlb_item.entry_lo[0].g,tlb_item.entry_lo[0].ri,tlb_item.entry_lo[0].xi,tlb_item.entry_lo[0].c); + rt_kprintf("v = %d,d = %d,g = %d,ri = %d,xi = %d,c = %d\n",tlb_item.entry_lo[1].v,tlb_item.entry_lo[1].d,tlb_item.entry_lo[1].g,tlb_item.entry_lo[1].ri,tlb_item.entry_lo[1].xi,tlb_item.entry_lo[1].c); + } +} diff --git a/libcpu/mips/gs264/mips_mmu.h b/libcpu/mips/gs264/mips_mmu.h new file mode 100644 index 0000000000000000000000000000000000000000..fcbcef36210486514b8ac7ce441de2a8bfefff19 --- /dev/null +++ b/libcpu/mips/gs264/mips_mmu.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-07-26 lizhirui the first version + */ +#ifndef __MIPS_MMU_H__ +#define __MIPS_MMU_H__ + +typedef enum cpu_mode_t +{ + CPU_MODE_KERNEL = 0x00, + CPU_MODE_SUPERVISOR = 0x01, + CPU_MODE_USER = 0x02 +}cpu_mode_t; + +typedef enum page_mask_enum_t +{ + PAGE_MASK_4KB = 0x00, + PAGE_MASK_16KB = 0x03, + PAGE_MASK_64KB = 0x0F, + PAGE_MASK_256KB = 0x3F, + PAGE_MASK_1MB = 0xFF, + PAGE_MASK_4MB = 0x3FF, + PAGE_MASK_16MB = 0xFFF, + PAGE_MASK_64MB = 0x3FFF, + PAGE_MASK_256MB = 0xFFFF, + PAGE_MASK_1GB = 0x3FFFF +}page_mask_enum_t; + +typedef struct page_mask_t +{ + uint64_t : 11; + uint64_t : 2; + uint64_t mask : 18; + uint64_t : 33; +}page_mask_t; + +typedef struct entry_lo_t +{ + uint64_t g : 1; + uint64_t v : 1; + uint64_t d : 1; + uint64_t c : 3; + uint64_t pfn : 24; + uint64_t pfnx : 3; + uint64_t : 29; + uint64_t xi : 1; + uint64_t ri : 1; +}entry_lo_t; + +typedef struct entry_hi_t +{ + uint64_t asid : 8; + uint64_t : 5; + uint64_t vpn2 : 27; + uint64_t : 22; + uint64_t r : 2; +}entry_hi_t; + +typedef struct tlb_item_t +{ + entry_lo_t entry_lo[2]; + entry_hi_t entry_hi; + page_mask_t page_mask; +}tlb_item_t; + +#define read_c0_diag() __read_32bit_c0_register($22, 0) +#define write_c0_diag(val) __write_32bit_c0_register($22, 0, val) +#define read_c0_badvaddr() __read_64bit_c0_register($8, 0) +#define read_c0_random() __read_32bit_c0_register($1, 0) + +#define reg_type_convert(variable,new_type) *((new_type *)(&variable)) +#define lowbit(x) ((x) & (-(x))) + +void mmu_init(); +void mmu_set_cpu_mode(cpu_mode_t cpu_mode); +cpu_mode_t mmu_get_cpu_mode(); +void mmu_clear_tlb(); +void mmu_clear_itlb(); +uint32_t mmu_get_max_tlb_index(); +void mmu_tlb_write_indexed(uint32_t index,tlb_item_t *tlb_item); +void mmu_tlb_write_random(tlb_item_t *tlb_item); +void mmu_tlb_read(uint32_t index,tlb_item_t *tlb_item); +uint32_t mmu_tlb_find(uint64_t vpn,uint32_t asid,uint32_t *index); +void mmu_tlb_item_init(tlb_item_t *tlb_item); +void mmu_set_map(uint64_t vpn,uint64_t ppn,page_mask_enum_t page_mask,uint32_t asid,uint32_t global); +uint32_t mmu_tlb_get_random(); +uint32_t mmu_tlb_get_index(); +void mmu_tlb_set_index(uint32_t index); +uint32_t mmu_tlb_is_matched(); +uint64_t mmu_tlb_get_bad_vaddr(); + +void tlb_dump(); + +#endif \ No newline at end of file diff --git a/libcpu/mips/gs264/mipscfg.c b/libcpu/mips/gs264/mipscfg.c new file mode 100644 index 0000000000000000000000000000000000000000..b2aed120aeb070765662c5fe7819cde9446c5af8 --- /dev/null +++ b/libcpu/mips/gs264/mipscfg.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-07-28 lizhirui first version + */ +#include +#include + +mips32_core_cfg_t g_mips_core = +{ + 64, /* icache_line_size */ + 128, /* icache_lines_per_way */ + 4, /* icache_ways */ + 32768, + 64, /* dcache_line_size */ + 128, /* dcache_lines_per_way */ + 4, /* dcache_ways */ + 32768, + 64, /* max_tlb_entries */ +}; + +static rt_uint16_t m_pow(rt_uint16_t b, rt_uint16_t n) +{ + rt_uint16_t rets = 1; + + while (n--) + rets *= b; + + return rets; +} + +static rt_uint16_t m_log2(rt_uint16_t b) +{ + rt_uint16_t rets = 0; + + while (b != 1) + { + b /= 2; + rets++; + } + + return rets; +} + +/** + * read core attribute + */ +void mips32_cfg_init(void) +{ + rt_uint16_t val; + rt_uint32_t cp0_config1; + + cp0_config1 = read_c0_config(); + if (cp0_config1 & 0x80000000) + { + cp0_config1 = read_c0_config1(); + + val = (cp0_config1 & (7<<22))>>22; + g_mips_core.icache_lines_per_way = 64 * m_pow(2, val); + val = (cp0_config1 & (7<<19))>>19; + g_mips_core.icache_line_size = 2 * m_pow(2, val); + val = (cp0_config1 & (7<<16))>>16; + g_mips_core.icache_ways = val + 1; + + val = (cp0_config1 & (7<<13))>>13; + g_mips_core.dcache_lines_per_way = 64 * m_pow(2, val); + val = (cp0_config1 & (7<<10))>>10; + g_mips_core.dcache_line_size = 2 * m_pow(2, val); + val = (cp0_config1 & (7<<7))>>7; + g_mips_core.dcache_ways = val + 1; + + val = (cp0_config1 & (0x3F<<25))>>25; + g_mips_core.max_tlb_entries = val + 1; + } +} diff --git a/libcpu/mips/gs264/mmu.c b/libcpu/mips/gs264/mmu.c new file mode 100644 index 0000000000000000000000000000000000000000..b5bedace50e09b3782691a63a6b700bcb5c648f2 --- /dev/null +++ b/libcpu/mips/gs264/mmu.c @@ -0,0 +1,819 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2012-01-10 bernard porting to AM1808 + * 2020-07-26 lizhirui porting to ls2k + */ + +#include +#include +#include + +#include "cache.h" +#include "mips_mmu.h" +#include "mmu.h" + +void *current_mmu_table = RT_NULL; + +void *mmu_table_get() +{ + return current_mmu_table; +} + +void switch_mmu(void *mmu_table) +{ + current_mmu_table = mmu_table; + + mmu_clear_tlb(); + mmu_clear_itlb(); +} + +/* dump 2nd level page table */ +void rt_hw_cpu_dump_page_table_2nd(rt_uint32_t *ptb) +{ + int i; + int fcnt = 0; + + for (i = 0; i < 256; i++) + { + rt_uint32_t pte2 = ptb[i]; + if ((pte2 & 0x3) == 0) + { + if (fcnt == 0) + rt_kprintf(" "); + rt_kprintf("%04x: ", i); + fcnt++; + if (fcnt == 16) + { + rt_kprintf("fault\n"); + fcnt = 0; + } + continue; + } + if (fcnt != 0) + { + rt_kprintf("fault\n"); + fcnt = 0; + } + + rt_kprintf(" %04x: %x: ", i, pte2); + if ((pte2 & 0x3) == 0x1) + { + rt_kprintf("L,ap:%x,xn:%d,texcb:%02x\n", + ((pte2 >> 7) | (pte2 >> 4))& 0xf, + (pte2 >> 15) & 0x1, + ((pte2 >> 10) | (pte2 >> 2)) & 0x1f); + } + else + { + rt_kprintf("S,ap:%x,xn:%d,texcb:%02x\n", + ((pte2 >> 7) | (pte2 >> 4))& 0xf, pte2 & 0x1, + ((pte2 >> 4) | (pte2 >> 2)) & 0x1f); + } + } +} + +void rt_hw_cpu_dump_page_table(rt_uint32_t *ptb) +{ + int i; + int fcnt = 0; + + rt_kprintf("page table@%p\n", ptb); + for (i = 0; i < 1024*4; i++) + { + rt_uint32_t pte1 = ptb[i]; + if ((pte1 & 0x3) == 0) + { + rt_kprintf("%03x: ", i); + fcnt++; + if (fcnt == 16) + { + rt_kprintf("fault\n"); + fcnt = 0; + } + continue; + } + if (fcnt != 0) + { + rt_kprintf("fault\n"); + fcnt = 0; + } + + rt_kprintf("%03x: %08x: ", i, pte1); + if ((pte1 & 0x3) == 0x3) + { + rt_kprintf("LPAE\n"); + } + else if ((pte1 & 0x3) == 0x1) + { + rt_kprintf("pte,ns:%d,domain:%d\n", + (pte1 >> 3) & 0x1, (pte1 >> 5) & 0xf); + /* + *rt_hw_cpu_dump_page_table_2nd((void*)((pte1 & 0xfffffc000) + * - 0x80000000 + 0xC0000000)); + */ + } + else if (pte1 & (1 << 18)) + { + rt_kprintf("super section,ns:%d,ap:%x,xn:%d,texcb:%02x\n", + (pte1 >> 19) & 0x1, + ((pte1 >> 13) | (pte1 >> 10))& 0xf, + (pte1 >> 4) & 0x1, + ((pte1 >> 10) | (pte1 >> 2)) & 0x1f); + } + else + { + rt_kprintf("section,ns:%d,ap:%x," + "xn:%d,texcb:%02x,domain:%d\n", + (pte1 >> 19) & 0x1, + ((pte1 >> 13) | (pte1 >> 10))& 0xf, + (pte1 >> 4) & 0x1, + (((pte1 & (0x7 << 12)) >> 10) | + ((pte1 & 0x0c) >> 2)) & 0x1f, + (pte1 >> 5) & 0xf); + } + } +} + +/* level1 page table, each entry for 1MB memory. */ +volatile unsigned long MMUTable[4*1024] __attribute__((aligned(16*1024))); +void rt_hw_mmu_setmtt(rt_uint32_t vaddrStart, + rt_uint32_t vaddrEnd, + rt_uint32_t paddrStart, + rt_uint32_t attr) +{ + volatile rt_uint32_t *pTT; + volatile int i, nSec; + pTT = (rt_uint32_t *)MMUTable + (vaddrStart >> 20); + nSec = (vaddrEnd >> 20) - (vaddrStart >> 20); + for(i = 0; i <= nSec; i++) + { + *pTT = attr | (((paddrStart >> 20) + i) << 20); + pTT++; + } +} + +unsigned long rt_hw_set_domain_register(unsigned long domain_val) +{ + unsigned long old_domain; + + //asm volatile ("mrc p15, 0, %0, c3, c0\n" : "=r" (old_domain)); + //asm volatile ("mcr p15, 0, %0, c3, c0\n" : :"r" (domain_val) : "memory"); + + return old_domain; +} + +void rt_hw_cpu_dcache_clean(void *addr, int size); +void rt_hw_init_mmu_table(struct mem_desc *mdesc, rt_uint32_t size) +{ + /* set page table */ + for(; size > 0; size--) + { + rt_hw_mmu_setmtt(mdesc->vaddr_start, mdesc->vaddr_end, + mdesc->paddr_start, mdesc->attr); + mdesc++; + } + rt_hw_cpu_dcache_clean((void*)MMUTable, sizeof MMUTable); +} + +void rt_hw_mmu_init(void) +{ + rt_cpu_dcache_clean_flush(); + rt_cpu_icache_flush(); + rt_hw_cpu_dcache_disable(); + rt_hw_cpu_icache_disable(); + rt_cpu_mmu_disable(); + + /*rt_hw_cpu_dump_page_table(MMUTable);*/ + rt_hw_set_domain_register(0x55555555); + + rt_cpu_tlb_set(MMUTable); + + rt_cpu_mmu_enable(); + + rt_hw_cpu_icache_enable(); + rt_hw_cpu_dcache_enable(); +} + +/* + mem map +*/ + +void rt_hw_cpu_dcache_clean(void *addr, int size); + +int rt_hw_mmu_map_init(rt_mmu_info *mmu_info, void* v_address, size_t size, size_t *vtable, size_t pv_off) +{ + size_t l1_off, va_s, va_e; + rt_base_t level; + + if (!mmu_info || !vtable) + { + return -1; + } + + va_s = (size_t)v_address; + va_e = (size_t)v_address + size - 1; + + if ( va_e < va_s) + { + return -1; + } + + va_s >>= ARCH_SECTION_SHIFT; + va_e >>= ARCH_SECTION_SHIFT; + + if (va_s == 0) + { + return -1; + } + + level = rt_hw_interrupt_disable(); + + for (l1_off = va_s; l1_off <= va_e; l1_off++) + { + size_t v = vtable[l1_off]; + + if (v & ARCH_MMU_USED_MASK) + { + rt_kprintf("Error:vtable[%d] = 0x%p(is not zero),va_s = 0x%p,va_e = 0x%p!\n",l1_off,v,va_s,va_e); + rt_hw_interrupt_enable(level); + return -1; + } + } + + mmu_info->vtable = vtable; + mmu_info->vstart = va_s; + mmu_info->vend = va_e; + mmu_info->pv_off = pv_off; + + rt_hw_interrupt_enable(level); + + return 0; +} + +static size_t find_vaddr(rt_mmu_info *mmu_info, int pages) +{ + size_t l1_off, l2_off; + size_t *mmu_l1, *mmu_l2; + size_t find_off = 0; + size_t find_va = 0; + int n = 0; + + if (!pages) + { + return 0; + } + + if (!mmu_info) + { + return 0; + } + + for (l1_off = mmu_info->vstart; l1_off <= mmu_info->vend; l1_off++) + { + mmu_l1 = (size_t*)mmu_info->vtable + l1_off; + if (*mmu_l1 & ARCH_MMU_USED_MASK) + { + mmu_l2 = (size_t *)((*mmu_l1 & ~ARCH_PAGE_TBL_MASK) - mmu_info->pv_off); + for (l2_off = 0; l2_off < (ARCH_SECTION_SIZE/ARCH_PAGE_SIZE); l2_off++) + { + if (*(mmu_l2 + l2_off) & ARCH_MMU_USED_MASK) + { + /* in use */ + n = 0; + } + else + { + if (!n) + { + find_va = l1_off; + find_off = l2_off; + } + n++; + if (n >= pages) + { + return (find_va << ARCH_SECTION_SHIFT) + (find_off << ARCH_PAGE_SHIFT); + } + } + } + } + else + { + if (!n) + { + find_va = l1_off; + find_off = 0; + } + n += (ARCH_SECTION_SIZE/ARCH_PAGE_SIZE); + if (n >= pages) + { + return (find_va << ARCH_SECTION_SHIFT) + (find_off << ARCH_PAGE_SHIFT); + } + } + } + return 0; +} + +#ifdef RT_USING_USERSPACE +static int check_vaddr(rt_mmu_info *mmu_info, void *va, int pages) +{ + size_t loop_va = (size_t)va & ~ARCH_PAGE_MASK; + size_t l1_off, l2_off; + size_t *mmu_l1, *mmu_l2; + + if (!pages) + { + return -1; + } + + if (!mmu_info) + { + return -1; + } + + while (pages--) + { + l1_off = (loop_va >> ARCH_SECTION_SHIFT); + l2_off = ((loop_va & ARCH_SECTION_MASK) >> ARCH_PAGE_SHIFT); + mmu_l1 = (size_t*)mmu_info->vtable + l1_off; + + if (*mmu_l1 & ARCH_MMU_USED_MASK) + { + mmu_l2 = (size_t *)((*mmu_l1 & ~ARCH_PAGE_TBL_MASK) - mmu_info->pv_off); + if (*(mmu_l2 + l2_off) & ARCH_MMU_USED_MASK) + { + return -1; + } + } + loop_va += ARCH_PAGE_SIZE; + } + return 0; +} +#endif + +static void __rt_hw_mmu_unmap(rt_mmu_info *mmu_info, void* v_addr, size_t npages) +{ + size_t loop_va = (size_t)v_addr & ~ARCH_PAGE_MASK; + size_t l1_off, l2_off; + size_t *mmu_l1, *mmu_l2; + size_t *ref_cnt; + + if (!mmu_info) + { + return; + } + + while (npages--) + { + l1_off = (loop_va >> ARCH_SECTION_SHIFT); + if (l1_off < mmu_info->vstart || l1_off > mmu_info->vend) + { + return; + } + + l2_off = ((loop_va & ARCH_SECTION_MASK) >> ARCH_PAGE_SHIFT); + mmu_l1 = (size_t*)mmu_info->vtable + l1_off; + + if (*mmu_l1 & ARCH_MMU_USED_MASK) + { + mmu_l2 = (size_t *)((*mmu_l1 & ~ARCH_PAGE_TBL_MASK) - mmu_info->pv_off); + } + else + { + return; + } + + if (*(mmu_l2 + l2_off) & ARCH_MMU_USED_MASK) + { + *(mmu_l2 + l2_off) = 0; + /* cache maintain */ + rt_hw_cpu_dcache_clean(mmu_l2 + l2_off, 4); + + ref_cnt = mmu_l2 + (ARCH_SECTION_SIZE/ARCH_PAGE_SIZE); + (*ref_cnt)--; + if (!*ref_cnt) + { +#ifdef RT_USING_USERSPACE + rt_pages_free(mmu_l2, 0); +#else + rt_free_align(mmu_l2); +#endif + *mmu_l1 = 0; + + /* cache maintain */ + rt_hw_cpu_dcache_clean(mmu_l1, 4); + } + } + loop_va += ARCH_PAGE_SIZE; + } +} + +static int __rt_hw_mmu_map(rt_mmu_info *mmu_info, void* v_addr, void* p_addr, size_t npages, size_t attr) +{ + size_t loop_va = (size_t)v_addr & ~ARCH_PAGE_MASK; + size_t loop_pa = (size_t)p_addr & ~ARCH_PAGE_MASK; + size_t l1_off, l2_off; + size_t *mmu_l1, *mmu_l2; + size_t *ref_cnt; + + if (!mmu_info) + { + return -1; + } + + while (npages--) + { + l1_off = (loop_va >> ARCH_SECTION_SHIFT); + l2_off = ((loop_va & ARCH_SECTION_MASK) >> ARCH_PAGE_SHIFT); + mmu_l1 = (size_t*)mmu_info->vtable + l1_off; + + if (*mmu_l1 & ARCH_MMU_USED_MASK) + { + mmu_l2 = (size_t *)((*mmu_l1 & ~ARCH_PAGE_TBL_MASK) - mmu_info->pv_off); + } + else + { +#ifdef RT_USING_USERSPACE + mmu_l2 = (size_t*)rt_pages_alloc(0); +#else + mmu_l2 = (size_t*)rt_malloc_align(ARCH_PAGE_TBL_SIZE * 2, ARCH_PAGE_TBL_SIZE); +#endif + if (mmu_l2) + { + rt_memset(mmu_l2, 0, ARCH_PAGE_TBL_SIZE * 2); + /* cache maintain */ + rt_hw_cpu_dcache_clean(mmu_l2, ARCH_PAGE_TBL_SIZE); + + *mmu_l1 = (((size_t)mmu_l2 + mmu_info->pv_off) | 0x1); + /* cache maintain */ + rt_hw_cpu_dcache_clean(mmu_l1, 4); + } + else + { + /* error, unmap and quit */ + __rt_hw_mmu_unmap(mmu_info, v_addr, npages); + return -1; + } + } + + ref_cnt = mmu_l2 + (ARCH_SECTION_SIZE/ARCH_PAGE_SIZE); + (*ref_cnt)++; + + *(mmu_l2 + l2_off) = (loop_pa | attr); + /* cache maintain */ + rt_hw_cpu_dcache_clean(mmu_l2 + l2_off, 4); + + loop_va += ARCH_PAGE_SIZE; + loop_pa += ARCH_PAGE_SIZE; + } + return 0; +} + +static void rt_hw_cpu_tlb_invalidate(void) +{ + mmu_clear_tlb(); + mmu_clear_itlb(); +} + +#ifdef RT_USING_USERSPACE +void *_rt_hw_mmu_map(rt_mmu_info *mmu_info, void *v_addr, void* p_addr, size_t size, size_t attr) +{ + size_t pa_s, pa_e; + size_t vaddr; + int pages; + int ret; + + if (!size) + { + return 0; + } + pa_s = (size_t)p_addr; + pa_e = (size_t)p_addr + size - 1; + pa_s >>= ARCH_PAGE_SHIFT; + pa_e >>= ARCH_PAGE_SHIFT; + pages = pa_e - pa_s + 1; + if (v_addr) + { + vaddr = (size_t)v_addr; + pa_s = (size_t)p_addr; + if ((vaddr & ARCH_PAGE_MASK) != (pa_s & ARCH_PAGE_MASK)) + { + return 0; + } + vaddr &= ~ARCH_PAGE_MASK; + if (check_vaddr(mmu_info, (void*)vaddr, pages) != 0) + { + return 0; + } + } + else + { + vaddr = find_vaddr(mmu_info, pages); + } + if (vaddr) { + ret = __rt_hw_mmu_map(mmu_info, (void*)vaddr, p_addr, pages, attr); + if (ret == 0) + { + rt_hw_cpu_tlb_invalidate(); + return (void*)(vaddr + ((size_t)p_addr & ARCH_PAGE_MASK)); + } + } + return 0; +} +#else +void *_rt_hw_mmu_map(rt_mmu_info *mmu_info, void* p_addr, size_t size, size_t attr) +{ + size_t pa_s, pa_e; + size_t vaddr; + int pages; + int ret; + + pa_s = (size_t)p_addr; + pa_e = (size_t)p_addr + size - 1; + pa_s >>= ARCH_PAGE_SHIFT; + pa_e >>= ARCH_PAGE_SHIFT; + pages = pa_e - pa_s + 1; + vaddr = find_vaddr(mmu_info, pages); + if (vaddr) { + ret = __rt_hw_mmu_map(mmu_info, (void*)vaddr, p_addr, pages, attr); + if (ret == 0) + { + rt_hw_cpu_tlb_invalidate(); + return (void*)(vaddr + ((size_t)p_addr & ARCH_PAGE_MASK)); + } + } + return 0; +} +#endif + +#ifdef RT_USING_USERSPACE +static int __rt_hw_mmu_map_auto(rt_mmu_info *mmu_info, void* v_addr, size_t npages, size_t attr) +{ + size_t loop_va = (size_t)v_addr & ~ARCH_PAGE_MASK; + size_t loop_pa; + size_t l1_off, l2_off; + size_t *mmu_l1, *mmu_l2; + size_t *ref_cnt; + + if (!mmu_info) + { + return -1; + } + + while (npages--) + { + loop_pa = (size_t)rt_pages_alloc(0) + mmu_info->pv_off; + if (!loop_pa) + goto err; + + //rt_kprintf("vaddr = %08x is mapped to paddr = %08x\n",v_addr,loop_pa); + l1_off = (loop_va >> ARCH_SECTION_SHIFT); + l2_off = ((loop_va & ARCH_SECTION_MASK) >> ARCH_PAGE_SHIFT); + mmu_l1 = (size_t*)mmu_info->vtable + l1_off; + + if (*mmu_l1 & ARCH_MMU_USED_MASK) + { + mmu_l2 = (size_t *)((*mmu_l1 & ~ARCH_PAGE_TBL_MASK) - mmu_info->pv_off); + } + else + { + //mmu_l2 = (size_t*)rt_malloc_align(ARCH_PAGE_TBL_SIZE * 2, ARCH_PAGE_TBL_SIZE); + mmu_l2 = (size_t*)rt_pages_alloc(0); + if (mmu_l2) + { + rt_memset(mmu_l2, 0, ARCH_PAGE_TBL_SIZE * 2); + /* cache maintain */ + rt_hw_cpu_dcache_clean(mmu_l2, ARCH_PAGE_TBL_SIZE); + + *mmu_l1 = (((size_t)mmu_l2 + mmu_info->pv_off) | 0x1); + /* cache maintain */ + rt_hw_cpu_dcache_clean(mmu_l1, 4); + } + else + goto err; + } + + ref_cnt = mmu_l2 + (ARCH_SECTION_SIZE/ARCH_PAGE_SIZE); + (*ref_cnt)++; + + //loop_pa += mmu_info->pv_off; + *(mmu_l2 + l2_off) = (loop_pa | attr); + /* cache maintain */ + rt_hw_cpu_dcache_clean(mmu_l2 + l2_off, 4); + + loop_va += ARCH_PAGE_SIZE; + } + return 0; +err: + { + /* error, unmap and quit */ + int i; + void *va, *pa; + + va = (void*)((size_t)v_addr & ~ARCH_PAGE_MASK); + for (i = 0; i < npages; i++) + { + pa = rt_hw_mmu_v2p(mmu_info, va); + pa -= mmu_info->pv_off; + rt_pages_free(pa, 0); + va += ARCH_PAGE_SIZE; + } + + __rt_hw_mmu_unmap(mmu_info, v_addr, npages); + return -1; + } +} + +void *_rt_hw_mmu_map_auto(rt_mmu_info *mmu_info, void *v_addr, size_t size, size_t attr) +{ + size_t vaddr; + size_t offset; + int pages; + int ret; + + if (!size) + { + return 0; + } + offset = (size_t)v_addr & ARCH_PAGE_MASK; + size += (offset + ARCH_PAGE_SIZE - 1); + pages = (size >> ARCH_PAGE_SHIFT); + if (v_addr) + { + vaddr = (size_t)v_addr; + vaddr &= ~ARCH_PAGE_MASK; + if (check_vaddr(mmu_info, (void*)vaddr, pages) != 0) + { + return 0; + } + } + else + { + vaddr = find_vaddr(mmu_info, pages); + } + if (vaddr) { + ret = __rt_hw_mmu_map_auto(mmu_info, (void*)vaddr, pages, attr); + if (ret == 0) + { + rt_hw_cpu_tlb_invalidate(); + return (void*)vaddr + offset; + } + } + return 0; +} +#endif + +void _rt_hw_mmu_unmap(rt_mmu_info *mmu_info, void* v_addr, size_t size) +{ + size_t va_s, va_e; + int pages; + + va_s = (size_t)v_addr; + va_e = (size_t)v_addr + size - 1; + va_s >>= ARCH_PAGE_SHIFT; + va_e >>= ARCH_PAGE_SHIFT; + pages = va_e - va_s + 1; + __rt_hw_mmu_unmap(mmu_info, v_addr, pages); + rt_hw_cpu_tlb_invalidate(); +} + +//va --> pa +void *rt_hw_kernel_virt_to_phys(void *v_addr, size_t size) +{ + void *p_addr = 0; + + return p_addr; +} + +//pa --> va +void *rt_hw_kernel_phys_to_virt(void *p_addr, size_t size) +{ + void *v_addr = 0; + + #ifdef RT_USING_USERSPACE + extern rt_mmu_info mmu_info; + v_addr = rt_hw_mmu_map(&mmu_info, 0, p_addr, size, MMU_MAP_K_RW); + #else + v_addr = p_addr; + #endif + + return v_addr; +} + +#ifdef RT_USING_USERSPACE +void *rt_hw_mmu_map(rt_mmu_info *mmu_info, void *v_addr, void* p_addr, size_t size, size_t attr) +{ + void *ret; + rt_base_t level; + + level = rt_hw_interrupt_disable(); + ret = _rt_hw_mmu_map(mmu_info, v_addr, p_addr, size, attr); + rt_hw_interrupt_enable(level); + return ret; +} + +void *rt_hw_mmu_map_auto(rt_mmu_info *mmu_info, void *v_addr, size_t size, size_t attr) +{ + void *ret; + rt_base_t level; + + level = rt_hw_interrupt_disable(); + ret = _rt_hw_mmu_map_auto(mmu_info, v_addr, size, attr); + rt_hw_interrupt_enable(level); + return ret; +} +#endif + +void rt_hw_mmu_unmap(rt_mmu_info *mmu_info, void* v_addr, size_t size) +{ + rt_base_t level; + + level = rt_hw_interrupt_disable(); + _rt_hw_mmu_unmap(mmu_info, v_addr, size); + rt_hw_interrupt_enable(level); +} + +void *_rt_hw_mmu_v2p(rt_mmu_info *mmu_info, void* v_addr) +{ + size_t l1_off, l2_off; + size_t *mmu_l1, *mmu_l2; + size_t tmp; + size_t pa; + + l1_off = (size_t)v_addr >> ARCH_SECTION_SHIFT; + + if (!mmu_info) + { + return (void*)0; + } + + mmu_l1 = (size_t*)mmu_info->vtable + l1_off; + + tmp = *mmu_l1; + + switch (tmp & ARCH_MMU_USED_MASK) + { + case 0: /* not used */ + break; + case 1: /* page table */ + mmu_l2 = (size_t *)((tmp & ~ARCH_PAGE_TBL_MASK) - mmu_info->pv_off); + l2_off = (((size_t)v_addr & ARCH_SECTION_MASK) >> ARCH_PAGE_SHIFT); + pa = *(mmu_l2 + l2_off); + if (pa & ARCH_MMU_USED_MASK) + { + if ((pa & ARCH_MMU_USED_MASK) == 1) + { + /* lage page, not support */ + break; + } + pa &= ~(ARCH_PAGE_MASK); + pa += ((size_t)v_addr & ARCH_PAGE_MASK); + return (void*)pa; + } + break; + case 2: + case 3: + /* section */ + if (tmp & ARCH_TYPE_SUPERSECTION) + { + /* super section, not support */ + break; + } + pa = (tmp & ~ARCH_SECTION_MASK); + pa += ((size_t)v_addr & ARCH_SECTION_MASK); + return (void*)pa; + } + return (void*)0; +} + +void *rt_hw_mmu_v2p(rt_mmu_info *mmu_info, void* v_addr) +{ + void *ret; + rt_base_t level; + + level = rt_hw_interrupt_disable(); + ret = _rt_hw_mmu_v2p(mmu_info, v_addr); + rt_hw_interrupt_enable(level); + return ret; +} + +#ifdef RT_USING_USERSPACE +void init_mm_setup(unsigned int *mtbl, unsigned int size, unsigned int pv_off) { + unsigned int va; + + for (va = 0; va < 0x1000; va++) { + unsigned int vaddr = (va << 20); + if (vaddr >= KERNEL_VADDR_START && vaddr - KERNEL_VADDR_START < size) { + mtbl[va] = ((va << 20) + pv_off) | NORMAL_MEM; + } else if (vaddr >= (KERNEL_VADDR_START + pv_off) && vaddr - (KERNEL_VADDR_START + pv_off) < size) { + mtbl[va] = (va << 20) | NORMAL_MEM; + } else { + mtbl[va] = 0; + } + } +} +#endif diff --git a/libcpu/mips/gs264/mmu.h b/libcpu/mips/gs264/mmu.h new file mode 100644 index 0000000000000000000000000000000000000000..2472bf975f8b28c3d70b6b83b287e0005c113e35 --- /dev/null +++ b/libcpu/mips/gs264/mmu.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-03-25 quanzhao the first version + * 2020-07-26 lizhirui porting to ls2k + */ +#ifndef __MMU_H_ +#define __MMU_H_ + +#include + +#define DESC_SEC (0x2) +#define MEMWBWA ((1<<12)|(3<<2)) /* write back, write allocate */ +#define MEMWB (3<<2) /* write back, no write allocate */ +#define MEMWT (2<<2) /* write through, no write allocate */ +#define SHAREDEVICE (1<<2) /* shared device */ +#define STRONGORDER (0<<2) /* strong ordered */ +#define XN (1<<4) /* execute Never */ +#ifdef RT_USING_USERSPACE +#define AP_RW (1<<10) /* supervisor=RW, user=No */ +#define AP_RO ((1<<10) |(1 << 15)) /* supervisor=RW, user=No */ +#else +#define AP_RW (3<<10) /* supervisor=RW, user=RW */ +#define AP_RO ((2<<10) /* supervisor=RW, user=RO */ +#endif + +#define SHARED (1<<16) /* shareable */ + +#define DOMAIN_FAULT (0x0) +#define DOMAIN_CHK (0x1) +#define DOMAIN_NOTCHK (0x3) +#define DOMAIN0 (0x0<<5) +#define DOMAIN1 (0x1<<5) + +#define DOMAIN0_ATTR (DOMAIN_CHK<<0) +#define DOMAIN1_ATTR (DOMAIN_FAULT<<2) + +/* device mapping type */ +#define DEVICE_MEM (SHARED|AP_RW|DOMAIN0|SHAREDEVICE|DESC_SEC|XN) +/* normal memory mapping type */ +#define NORMAL_MEM (SHARED|AP_RW|DOMAIN0|MEMWBWA|DESC_SEC) + +#define STRONG_ORDER_MEM (SHARED|AP_RO|XN|DESC_SEC) + +struct mem_desc +{ + rt_uint32_t vaddr_start; + rt_uint32_t vaddr_end; + rt_uint32_t paddr_start; + rt_uint32_t attr; +}; + +#define MMU_MAP_MTBL_XN (1<<0) +#define MMU_MAP_MTBL_A (1<<1) +#define MMU_MAP_MTBL_B (1<<2) +#define MMU_MAP_MTBL_C (1<<3) +#define MMU_MAP_MTBL_AP01(x) (x<<4) +#define MMU_MAP_MTBL_TEX(x) (x<<6) +#define MMU_MAP_MTBL_AP2(x) (x<<9) +#define MMU_MAP_MTBL_SHARE (1<<10) + +#define MMU_MAP_K_RO (MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(1)|MMU_MAP_MTBL_AP01(1)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_C|MMU_MAP_MTBL_SHARE) +#define MMU_MAP_K_RWCB (MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(1)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_B|MMU_MAP_MTBL_C|MMU_MAP_MTBL_SHARE) +#define MMU_MAP_K_RW (MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(1)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_SHARE) +#define MMU_MAP_K_DEVICE (MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(1)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_B|MMU_MAP_MTBL_SHARE) +#define MMU_MAP_U_RO (MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(1)|MMU_MAP_MTBL_AP01(2)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_C|MMU_MAP_MTBL_SHARE) +#define MMU_MAP_U_RWCB (MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(3)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_B|MMU_MAP_MTBL_C|MMU_MAP_MTBL_SHARE) +#define MMU_MAP_U_RW (MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(3)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_SHARE) +#define MMU_MAP_U_DEVICE (MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(3)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_B|MMU_MAP_MTBL_SHARE) + +#define ARCH_SECTION_SHIFT 20 +#define ARCH_SECTION_SIZE (1 << ARCH_SECTION_SHIFT) +#define ARCH_SECTION_MASK (ARCH_SECTION_SIZE - 1) +#define ARCH_PAGE_SHIFT 14 +#define ARCH_PAGE_SIZE (1 << ARCH_PAGE_SHIFT) +#define ARCH_PAGE_MASK (ARCH_PAGE_SIZE - 1) +#define ARCH_PAGE_TBL_SHIFT 10 +#define ARCH_PAGE_TBL_SIZE (1 << ARCH_PAGE_TBL_SHIFT) +#define ARCH_PAGE_TBL_MASK (ARCH_PAGE_TBL_SIZE - 1) + +#define ARCH_MMU_USED_MASK 3 + +#define ARCH_TYPE_SUPERSECTION (1 << 18) + +typedef struct +{ + size_t *vtable; + size_t vstart; + size_t vend; + size_t pv_off; +} rt_mmu_info; + +void *mmu_table_get(); +void switch_mmu(void *mmu_table); + +int rt_hw_mmu_map_init(rt_mmu_info *mmu_info, void* v_address, size_t size, size_t *vtable, size_t pv_off); +#ifdef RT_USING_USERSPACE +void *rt_hw_mmu_map(rt_mmu_info *mmu_info, void *v_addr, void* p_addr, size_t size, size_t attr); +void *rt_hw_mmu_map_auto(rt_mmu_info *mmu_info, void *v_addr, size_t size, size_t attr); +#else +void *rt_hw_mmu_map(rt_mmu_info *mmu_info, void* p_addr, size_t size, size_t attr); +#endif +void rt_hw_mmu_unmap(rt_mmu_info *mmu_info, void* v_addr, size_t size); +void *rt_hw_mmu_v2p(rt_mmu_info *mmu_info, void* v_addr); + +void *rt_hw_kernel_phys_to_virt(void *p_addr, size_t size); +void *rt_hw_kernel_virt_to_phys(void *v_addr, size_t size); + +#endif