commit
de0bb6f96c
|
@ -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')
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include <rtthread.h>
|
||||
#include "ls2k1000.h"
|
||||
|
||||
|
||||
struct loongson_pll {
|
||||
rt_uint64_t PLL_SYS_0;
|
||||
rt_uint64_t PLL_SYS_1;
|
||||
|
|
|
@ -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 <components/drivers/include/drivers/pin.h>
|
||||
* 2017-10-20 ZYH add mode open drain and input pull down
|
||||
* 2020-06-01 Du Huanpeng GPIO driver based on <components/drivers/include/drivers/pin.h>
|
||||
*/
|
||||
#include <rtthread.h>
|
||||
#include <drivers/pin.h>
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -15,100 +15,99 @@
|
|||
#include <rthw.h>
|
||||
|
||||
/* UART registers */
|
||||
#define UART_DAT(base) HWREG8(base + 0x00)
|
||||
#define UART_IER(base) HWREG8(base + 0x01)
|
||||
#define UART_IIR(base) HWREG8(base + 0x02)
|
||||
#define UART_FCR(base) HWREG8(base + 0x02)
|
||||
#define UART_LCR(base) HWREG8(base + 0x03)
|
||||
#define UART_MCR(base) HWREG8(base + 0x04)
|
||||
#define UART_LSR(base) HWREG8(base + 0x05)
|
||||
#define UART_MSR(base) HWREG8(base + 0x06)
|
||||
#define UART_DAT(base) HWREG8(base + 0x00)
|
||||
#define UART_IER(base) HWREG8(base + 0x01)
|
||||
#define UART_IIR(base) HWREG8(base + 0x02)
|
||||
#define UART_FCR(base) HWREG8(base + 0x02)
|
||||
#define UART_LCR(base) HWREG8(base + 0x03)
|
||||
#define UART_MCR(base) HWREG8(base + 0x04)
|
||||
#define UART_LSR(base) HWREG8(base + 0x05)
|
||||
#define UART_MSR(base) HWREG8(base + 0x06)
|
||||
|
||||
#define UART_LSB(base) HWREG8(base + 0x00)
|
||||
#define UART_MSB(base) HWREG8(base + 0x01)
|
||||
#define UART_LSB(base) HWREG8(base + 0x00)
|
||||
#define UART_MSB(base) HWREG8(base + 0x01)
|
||||
|
||||
/* interrupt enable register */
|
||||
#define IER_IRxE 0x1
|
||||
#define IER_ITxE 0x2
|
||||
#define IER_ILE 0x4
|
||||
#define IER_IME 0x8
|
||||
#define IER_IRxE 0x1
|
||||
#define IER_ITxE 0x2
|
||||
#define IER_ILE 0x4
|
||||
#define IER_IME 0x8
|
||||
|
||||
/* interrupt identification register */
|
||||
#define IIR_IMASK 0xf /* mask */
|
||||
#define IIR_RXTOUT 0xc /* receive timeout */
|
||||
#define IIR_RLS 0x6 /* receive line status */
|
||||
#define IIR_RXRDY 0x4 /* receive ready */
|
||||
#define IIR_TXRDY 0x2 /* transmit ready */
|
||||
#define IIR_NOPEND 0x1 /* nothing */
|
||||
#define IIR_MLSC 0x0 /* modem status */
|
||||
#define IIR_FIFO_MASK 0xc0 /* set if FIFOs are enabled */
|
||||
#define IIR_IMASK 0xf /* mask */
|
||||
#define IIR_RXTOUT 0xc /* receive timeout */
|
||||
#define IIR_RLS 0x6 /* receive line status */
|
||||
#define IIR_RXRDY 0x4 /* receive ready */
|
||||
#define IIR_TXRDY 0x2 /* transmit ready */
|
||||
#define IIR_NOPEND 0x1 /* nothing */
|
||||
#define IIR_MLSC 0x0 /* modem status */
|
||||
#define IIR_FIFO_MASK 0xc0 /* set if FIFOs are enabled */
|
||||
|
||||
/* fifo control register */
|
||||
#define FIFO_ENABLE 0x01 /* enable fifo */
|
||||
#define FIFO_RCV_RST 0x02 /* reset receive fifo */
|
||||
#define FIFO_XMT_RST 0x04 /* reset transmit fifo */
|
||||
#define FIFO_DMA_MODE 0x08 /* enable dma mode */
|
||||
#define FIFO_TRIGGER_1 0x00 /* trigger at 1 char */
|
||||
#define FIFO_TRIGGER_4 0x40 /* trigger at 4 chars */
|
||||
#define FIFO_TRIGGER_8 0x80 /* trigger at 8 chars */
|
||||
#define FIFO_TRIGGER_14 0xc0 /* trigger at 14 chars */
|
||||
#define FIFO_ENABLE 0x01 /* enable fifo */
|
||||
#define FIFO_RCV_RST 0x02 /* reset receive fifo */
|
||||
#define FIFO_XMT_RST 0x04 /* reset transmit fifo */
|
||||
#define FIFO_DMA_MODE 0x08 /* enable dma mode */
|
||||
#define FIFO_TRIGGER_1 0x00 /* trigger at 1 char */
|
||||
#define FIFO_TRIGGER_4 0x40 /* trigger at 4 chars */
|
||||
#define FIFO_TRIGGER_8 0x80 /* trigger at 8 chars */
|
||||
#define FIFO_TRIGGER_14 0xc0 /* trigger at 14 chars */
|
||||
|
||||
// 线路控制寄存器
|
||||
/* character format control register */
|
||||
#define CFCR_DLAB 0x80 /* divisor latch */
|
||||
#define CFCR_SBREAK 0x40 /* send break */
|
||||
#define CFCR_PZERO 0x30 /* zero parity */
|
||||
#define CFCR_PONE 0x20 /* one parity */
|
||||
#define CFCR_PEVEN 0x10 /* even parity */
|
||||
#define CFCR_PODD 0x00 /* odd parity */
|
||||
#define CFCR_PENAB 0x08 /* parity enable */
|
||||
#define CFCR_STOPB 0x04 /* 2 stop bits */
|
||||
#define CFCR_8BITS 0x03 /* 8 data bits */
|
||||
#define CFCR_7BITS 0x02 /* 7 data bits */
|
||||
#define CFCR_6BITS 0x01 /* 6 data bits */
|
||||
#define CFCR_5BITS 0x00 /* 5 data bits */
|
||||
#define CFCR_DLAB 0x80 /* divisor latch */
|
||||
#define CFCR_SBREAK 0x40 /* send break */
|
||||
#define CFCR_PZERO 0x30 /* zero parity */
|
||||
#define CFCR_PONE 0x20 /* one parity */
|
||||
#define CFCR_PEVEN 0x10 /* even parity */
|
||||
#define CFCR_PODD 0x00 /* odd parity */
|
||||
#define CFCR_PENAB 0x08 /* parity enable */
|
||||
#define CFCR_STOPB 0x04 /* 2 stop bits */
|
||||
#define CFCR_8BITS 0x03 /* 8 data bits */
|
||||
#define CFCR_7BITS 0x02 /* 7 data bits */
|
||||
#define CFCR_6BITS 0x01 /* 6 data bits */
|
||||
#define CFCR_5BITS 0x00 /* 5 data bits */
|
||||
|
||||
/* modem control register */
|
||||
#define MCR_LOOPBACK 0x10 /* loopback */
|
||||
#define MCR_IENABLE 0x08 /* output 2 = int enable */
|
||||
#define MCR_DRS 0x04 /* output 1 = xxx */
|
||||
#define MCR_RTS 0x02 /* enable RTS */
|
||||
#define MCR_DTR 0x01 /* enable DTR */
|
||||
#define MCR_LOOPBACK 0x10 /* loopback */
|
||||
#define MCR_IENABLE 0x08 /* output 2 = int enable */
|
||||
#define MCR_DRS 0x04 /* output 1 = xxx */
|
||||
#define MCR_RTS 0x02 /* enable RTS */
|
||||
#define MCR_DTR 0x01 /* enable DTR */
|
||||
|
||||
/* line status register */
|
||||
#define LSR_RCV_FIFO 0x80 /* error in receive fifo */
|
||||
#define LSR_TSRE 0x40 /* transmitter empty */
|
||||
#define LSR_TXRDY 0x20 /* transmitter ready */
|
||||
#define LSR_BI 0x10 /* break detected */
|
||||
#define LSR_FE 0x08 /* framing error */
|
||||
#define LSR_PE 0x04 /* parity error */
|
||||
#define LSR_OE 0x02 /* overrun error */
|
||||
#define LSR_RXRDY 0x01 /* receiver ready */
|
||||
#define LSR_RCV_MASK 0x1f
|
||||
#define LSR_RCV_FIFO 0x80 /* error in receive fifo */
|
||||
#define LSR_TSRE 0x40 /* transmitter empty */
|
||||
#define LSR_TXRDY 0x20 /* transmitter ready */
|
||||
#define LSR_BI 0x10 /* break detected */
|
||||
#define LSR_FE 0x08 /* framing error */
|
||||
#define LSR_PE 0x04 /* parity error */
|
||||
#define LSR_OE 0x02 /* overrun error */
|
||||
#define LSR_RXRDY 0x01 /* receiver ready */
|
||||
#define LSR_RCV_MASK 0x1f
|
||||
|
||||
|
||||
/* UART interrupt enable register value */
|
||||
#define UARTIER_IME (1 << 3)
|
||||
#define UARTIER_ILE (1 << 2)
|
||||
#define UARTIER_ITXE (1 << 1)
|
||||
#define UARTIER_IRXE (1 << 0)
|
||||
#define UARTIER_IME (1 << 3)
|
||||
#define UARTIER_ILE (1 << 2)
|
||||
#define UARTIER_ITXE (1 << 1)
|
||||
#define UARTIER_IRXE (1 << 0)
|
||||
|
||||
/* UART line control register value */
|
||||
#define UARTLCR_DLAB (1 << 7)
|
||||
#define UARTLCR_BCB (1 << 6)
|
||||
#define UARTLCR_SPB (1 << 5)
|
||||
#define UARTLCR_EPS (1 << 4)
|
||||
#define UARTLCR_PE (1 << 3)
|
||||
#define UARTLCR_SB (1 << 2)
|
||||
#define UARTLCR_DLAB (1 << 7)
|
||||
#define UARTLCR_BCB (1 << 6)
|
||||
#define UARTLCR_SPB (1 << 5)
|
||||
#define UARTLCR_EPS (1 << 4)
|
||||
#define UARTLCR_PE (1 << 3)
|
||||
#define UARTLCR_SB (1 << 2)
|
||||
|
||||
/* UART line status register value */
|
||||
#define UARTLSR_ERROR (1 << 7)
|
||||
#define UARTLSR_TE (1 << 6)
|
||||
#define UARTLSR_TFE (1 << 5)
|
||||
#define UARTLSR_BI (1 << 4)
|
||||
#define UARTLSR_FE (1 << 3)
|
||||
#define UARTLSR_PE (1 << 2)
|
||||
#define UARTLSR_OE (1 << 1)
|
||||
#define UARTLSR_DR (1 << 0)
|
||||
#define UARTLSR_ERROR (1 << 7)
|
||||
#define UARTLSR_TE (1 << 6)
|
||||
#define UARTLSR_TFE (1 << 5)
|
||||
#define UARTLSR_BI (1 << 4)
|
||||
#define UARTLSR_FE (1 << 3)
|
||||
#define UARTLSR_PE (1 << 2)
|
||||
#define UARTLSR_OE (1 << 1)
|
||||
#define UARTLSR_DR (1 << 0)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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
|
||||
#endif
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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')
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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 <rtthread.h>
|
||||
#include <rtdef.h>
|
||||
//#include <lwip/pbuf.h>
|
||||
|
||||
#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);
|
|
@ -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*/
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2017-08-24 chinesebear first version
|
||||
*/
|
||||
|
||||
#ifndef __DEBUG_H__
|
||||
#define __DEBUG_H__
|
||||
|
||||
//#define GMAC_DEBUG
|
||||
#include <rtthread.h>
|
||||
#ifdef GMAC_DEBUG
|
||||
#define DEBUG_MES rt_kprintf
|
||||
#else
|
||||
#define DEBUG_MES(...)
|
||||
#endif
|
||||
|
||||
#endif /*__DEBUG_H__*/
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2017-08-24 chinesebear first version
|
||||
*/
|
||||
|
||||
#ifndef SYNOP_GMAC_NETWORK_INTERFACE_H
|
||||
#define SYNOP_GMAC_NETWORK_INTERFACE_H 1
|
||||
|
||||
#include <lwip/sys.h>
|
||||
#include <netif/ethernetif.h>
|
||||
#include "synopGMAC_plat.h"
|
||||
#include "synopGMAC_Host.h"
|
||||
#include "synopGMAC_Dev.h"
|
||||
|
||||
#define NET_IF_TIMEOUT (10*HZ)
|
||||
#define CHECK_TIME (HZ)
|
||||
|
||||
s32 synopGMAC_init_network_interface(char* xname,u64 synopGMACMappedAddr);
|
||||
void synopGMAC_exit_network_interface(void);
|
||||
|
||||
s32 synopGMAC_linux_open(struct eth_device *);
|
||||
s32 synopGMAC_linux_close(struct eth_device *);
|
||||
struct net_device_stats * synopGMAC_linux_get_stats(struct synopGMACNetworkAdapter *);
|
||||
|
||||
s32 synopGMAC_test(synopGMACdevice * gmacdev_0,synopGMACdevice * gmacdev_1);
|
||||
|
||||
void dumpreg(u64 );
|
||||
void dumpphyreg();
|
||||
|
||||
/*
|
||||
* gethex(vp,p,n)
|
||||
* convert n hex digits from p to binary, result in vp,
|
||||
* rtn 1 on success
|
||||
*/
|
||||
static int gethex(u8 *vp, char *p, int n)
|
||||
{
|
||||
u8 v;
|
||||
int digit;
|
||||
|
||||
for (v = 0; n > 0; n--) {
|
||||
if (*p == 0)
|
||||
return (0);
|
||||
if (*p >= '0' && *p <= '9')
|
||||
digit = *p - '0';
|
||||
else if (*p >= 'a' && *p <= 'f')
|
||||
digit = *p - 'a' + 10;
|
||||
else if (*p >= 'A' && *p <= 'F')
|
||||
digit = *p - 'A' + 10;
|
||||
else
|
||||
return (0);
|
||||
|
||||
v <<= 4;
|
||||
v |= digit;
|
||||
p++;
|
||||
}
|
||||
*vp = v;
|
||||
return (1);
|
||||
}
|
||||
|
||||
#endif /* End of file */
|
|
@ -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 <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
void flush_cache(unsigned long start_addr, unsigned long size)
|
||||
{
|
||||
/*r4k_dcache_wback_inv(start_addr,size);
|
||||
|
||||
//rt_kprintf("flush_cache:start_addr = 0x%p,size = 0x%p",start_addr,size);
|
||||
unsigned long new_addr = start_addr - CACHED_MEMORY_ADDR + UNCACHED_MEMORY_ADDR;
|
||||
rt_memcpy(new_addr,start_addr,size);
|
||||
|
||||
if(rt_memcmp(start_addr,new_addr,size) != 0)
|
||||
{
|
||||
rt_kprintf("flush_cache:data isn't matched!\n");
|
||||
while(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
//rt_kprintf("flush_cache:data is matched!\n");
|
||||
}*/
|
||||
}
|
||||
|
||||
//convert virtual address to physical address
|
||||
dma_addr_t __attribute__((weak)) gmac_dmamap(unsigned long va,u32 size)
|
||||
{
|
||||
return VA_TO_PA (va);
|
||||
//return UNCACHED_TO_PHYS(va);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a wrapper function for Memory allocation routine. In linux Kernel
|
||||
* it it kmalloc function
|
||||
* @param[in] bytes in bytes to allocate
|
||||
*/
|
||||
|
||||
void *plat_alloc_memory(u32 bytes)
|
||||
{
|
||||
//return (void*)malloc((size_t)bytes, M_DEVBUF, M_DONTWAIT);
|
||||
void *buf = (void*)rt_malloc((u32)bytes);
|
||||
flush_cache((unsigned long)buf, bytes);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a wrapper function for consistent dma-able Memory allocation routine.
|
||||
* In linux Kernel, it depends on pci dev structure
|
||||
* @param[in] bytes in bytes to allocate
|
||||
*/
|
||||
|
||||
//allocate a space aligned to 16-byte boundary without cache
|
||||
void *plat_alloc_consistent_dmaable_memory(synopGMACdevice *pcidev, u32 size, u32 *addr)
|
||||
{
|
||||
void *buf;
|
||||
buf = (void*)rt_malloc((u32)(size + 16));
|
||||
//CPU_IOFlushDCache( buf,size, SYNC_W);
|
||||
unsigned long i = (unsigned long)buf;
|
||||
// rt_kprintf("size = %d\n", size);
|
||||
// rt_kprintf("bufaddr = %p\n", buf);
|
||||
// rt_kprintf("i%%16 == %d\n", i%16);
|
||||
if(i % 16 == 8){
|
||||
i += 8;
|
||||
}
|
||||
else if(i % 16 == 4){
|
||||
i += 12;
|
||||
}
|
||||
else if(i % 16 == 12){
|
||||
i += 4;
|
||||
}
|
||||
|
||||
flush_cache(i, size);
|
||||
*addr = gmac_dmamap(i, size);
|
||||
buf = (unsigned char *)CACHED_TO_UNCACHED(i);
|
||||
//rt_kprintf("bufaddr = %p\n", buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a wrapper function for freeing consistent dma-able Memory.
|
||||
* In linux Kernel, it depends on pci dev structure
|
||||
* @param[in] bytes in bytes to allocate
|
||||
*/
|
||||
//void plat_free_consistent_dmaable_memory(void * addr)
|
||||
void plat_free_consistent_dmaable_memory(synopGMACdevice *pcidev, u32 size, void * addr,u64 dma_addr)
|
||||
{
|
||||
rt_free((void*)PHYS_TO_CACHED(UNCACHED_TO_PHYS(addr)));
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a wrapper function for Memory free routine. In linux Kernel
|
||||
* it it kfree function
|
||||
* @param[in] buffer pointer to be freed
|
||||
*/
|
||||
void plat_free_memory(void *buffer)
|
||||
{
|
||||
rt_free(buffer);
|
||||
return ;
|
||||
}
|
||||
|
||||
//convert virtual address to physical address and flush cache
|
||||
dma_addr_t plat_dma_map_single(void *hwdev,void *ptr,u32 size)
|
||||
{
|
||||
unsigned long addr = (unsigned long) ptr;
|
||||
//CPU_IOFlushDCache(addr,size, direction);
|
||||
flush_cache(addr, size);
|
||||
return gmac_dmamap(addr, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a wrapper function for platform dependent delay
|
||||
* Take care while passing the argument to this function
|
||||
* @param[in] buffer pointer to be freed
|
||||
*/
|
||||
void plat_delay(u32 delay)
|
||||
{
|
||||
while (delay--);
|
||||
return;
|
||||
}
|
|
@ -0,0 +1,242 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2017-08-24 chinesebear first version
|
||||
* 2020-08-10 lizhirui porting to ls2k
|
||||
*/
|
||||
|
||||
#ifndef SYNOP_GMAC_PLAT_H
|
||||
#define SYNOP_GMAC_PLAT_H 1
|
||||
|
||||
/* sw
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pci.h>
|
||||
*/
|
||||
#include "synopGMAC_types.h"
|
||||
#include "synopGMAC_debug.h"
|
||||
//#include "mii.h"
|
||||
//#include "GMAC_Pmon.h"
|
||||
//#include "synopGMAC_Host.h"
|
||||
#include <rtthread.h>
|
||||
#include <stdint.h>
|
||||
#include "mips_addrspace.h"
|
||||
//sw: copy the type define into here
|
||||
#define IOCTL_READ_REGISTER SIOCDEVPRIVATE+1
|
||||
#define IOCTL_WRITE_REGISTER SIOCDEVPRIVATE+2
|
||||
#define IOCTL_READ_IPSTRUCT SIOCDEVPRIVATE+3
|
||||
#define IOCTL_READ_RXDESC SIOCDEVPRIVATE+4
|
||||
#define IOCTL_READ_TXDESC SIOCDEVPRIVATE+5
|
||||
#define IOCTL_POWER_DOWN SIOCDEVPRIVATE+6
|
||||
|
||||
#define SYNOP_GMAC0 1
|
||||
|
||||
typedef int bool;
|
||||
//typedef unsigned long dma_addr_t;
|
||||
|
||||
#define KUSEG_ADDR 0x0
|
||||
#define CACHED_MEMORY_ADDR KSEG0BASE
|
||||
#define UNCACHED_MEMORY_ADDR KSEG0BASE
|
||||
#define KSEG2_ADDR KSEG2BASE
|
||||
#define MAX_MEM_ADDR KSEG3BASE
|
||||
#define RESERVED_ADDR KSEG3BASE
|
||||
|
||||
#define CACHED_TO_PHYS(x) ((uint64_t)(x) - CACHED_MEMORY_ADDR)
|
||||
#define PHYS_TO_CACHED(x) ((uint64_t)(x) + CACHED_MEMORY_ADDR)
|
||||
#define UNCACHED_TO_PHYS(x) ((uint64_t)(x) - UNCACHED_MEMORY_ADDR)
|
||||
#define PHYS_TO_UNCACHED(x) ((uint64_t)(x) + UNCACHED_MEMORY_ADDR)
|
||||
#define VA_TO_CINDEX(x) (PHYS_TO_CACHED(UNCACHED_TO_PHYS(x)))
|
||||
#define CACHED_TO_UNCACHED(x) (PHYS_TO_UNCACHED(CACHED_TO_PHYS(x)))
|
||||
|
||||
#define VA_TO_PA(x) CACHED_TO_PHYS(x)
|
||||
|
||||
/* sw
|
||||
#define TR0(fmt, args...) printk(KERN_CRIT "SynopGMAC: " fmt, ##args)
|
||||
|
||||
#ifdef DEBUG
|
||||
#undef TR
|
||||
# define TR(fmt, args...) printk(KERN_CRIT "SynopGMAC: " fmt, ##args)
|
||||
#else
|
||||
# define TR(fmt, args...) // not debugging: nothing
|
||||
#endif
|
||||
*/
|
||||
/*
|
||||
#define TR0(fmt, args...) printf("SynopGMAC: " fmt, ##args)
|
||||
*/
|
||||
|
||||
/*
|
||||
#ifdef DEBUG
|
||||
#undef TR
|
||||
# define TR(fmt, args...) printf("SynopGMAC: " fmt, ##args)
|
||||
#else
|
||||
//# define TR(fmt, args...) // not debugging: nothing
|
||||
#define TR(fmt, args...) printf("SynopGMAC: " fmt, ##args)
|
||||
#endif
|
||||
*/
|
||||
|
||||
//sw: nothing to display
|
||||
#define TR0(fmt, args...) //rt_kprintf(fmt, ##args)
|
||||
#define TR(fmt, args...) //rt_kprintf(fmt, ##args)
|
||||
|
||||
//typedef int bool;
|
||||
enum synopGMAC_boolean
|
||||
{
|
||||
false = 0,
|
||||
true = 1
|
||||
};
|
||||
|
||||
#define DEFAULT_DELAY_VARIABLE 10
|
||||
#define DEFAULT_LOOP_VARIABLE 10000
|
||||
|
||||
/* There are platform related endian conversions
|
||||
*
|
||||
*/
|
||||
#define LE32_TO_CPU __le32_to_cpu
|
||||
#define BE32_TO_CPU __be32_to_cpu
|
||||
#define CPU_TO_LE32 __cpu_to_le32
|
||||
|
||||
/* Error Codes */
|
||||
#define ESYNOPGMACNOERR 0
|
||||
#define ESYNOPGMACNOMEM 1
|
||||
#define ESYNOPGMACPHYERR 2
|
||||
#define ESYNOPGMACBUSY 3
|
||||
|
||||
struct Network_interface_data
|
||||
{
|
||||
u32 unit;
|
||||
u64 addr;
|
||||
u32 data;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* These are the wrapper function prototypes for OS/platform related routines
|
||||
*/
|
||||
void * plat_alloc_memory(u32 );
|
||||
void plat_free_memory(void *);
|
||||
|
||||
//void * plat_alloc_consistent_dmaable_memory(struct pci_dev *, u32, u32 *);
|
||||
//void plat_free_consistent_dmaable_memory (struct pci_dev *, u32, void *, u32);
|
||||
void plat_delay(u32);
|
||||
|
||||
|
||||
/**
|
||||
* The Low level function to read register contents from Hardware.
|
||||
*
|
||||
* @param[in] pointer to the base of register map
|
||||
* @param[in] Offset from the base
|
||||
* \return Returns the register contents
|
||||
*/
|
||||
static u32 synopGMACReadReg(u64 RegBase, u32 RegOffset)
|
||||
{
|
||||
u64 addr;
|
||||
u32 data;
|
||||
|
||||
addr = RegBase + (u32)RegOffset;
|
||||
data = *(volatile u32 *)addr;
|
||||
|
||||
#if SYNOP_REG_DEBUG
|
||||
TR("%s RegBase = 0x%08x RegOffset = 0x%08x RegData = 0x%08x\n", __FUNCTION__, (u32)RegBase, RegOffset, data );
|
||||
#endif
|
||||
// rt_kprintf("%s RegBase = 0x%08x RegOffset = 0x%08x RegData = 0x%08x\n", __FUNCTION__, (u32)RegBase, RegOffset, data );
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The Low level function to write to a register in Hardware.
|
||||
*
|
||||
* @param[in] pointer to the base of register map
|
||||
* @param[in] Offset from the base
|
||||
* @param[in] Data to be written
|
||||
* \return void
|
||||
*/
|
||||
static void synopGMACWriteReg(u64 RegBase, u32 RegOffset, u32 RegData )
|
||||
{
|
||||
u64 addr;
|
||||
addr = RegBase + (u32)RegOffset;
|
||||
// rt_kprintf("%s RegBase = 0x%08x RegOffset = 0x%08x RegData = 0x%08x\n", __FUNCTION__,(u32) RegBase, RegOffset, RegData );
|
||||
#if SYNOP_REG_DEBUG
|
||||
TR("%s RegBase = 0x%p RegOffset = 0x%08x RegData = 0x%08x\n", __FUNCTION__,(u32) RegBase, RegOffset, RegData );
|
||||
#endif
|
||||
*(volatile u32 *)addr = RegData;
|
||||
/*if(addr == 0xbfe1100c)
|
||||
DEBUG_MES("regdata = %08x\n", RegData);*/
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Low level function to set bits of a register in Hardware.
|
||||
*
|
||||
* @param[in] pointer to the base of register map
|
||||
* @param[in] Offset from the base
|
||||
* @param[in] Bit mask to set bits to logical 1
|
||||
* \return void
|
||||
*/
|
||||
static void synopGMACSetBits(u64 RegBase, u32 RegOffset, u32 BitPos)
|
||||
{
|
||||
//u64 addr = (u64)RegBase + (u64)RegOffset;
|
||||
u32 data;
|
||||
data = synopGMACReadReg(RegBase, RegOffset);
|
||||
data |= BitPos;
|
||||
synopGMACWriteReg(RegBase, RegOffset, data);
|
||||
// writel(data,(void *)addr);
|
||||
#if SYNOP_REG_DEBUG
|
||||
TR("%s !!!!!!!!!!!!! RegOffset = 0x%08x RegData = 0x%08x\n", __FUNCTION__, RegOffset, data );
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The Low level function to clear bits of a register in Hardware.
|
||||
*
|
||||
* @param[in] pointer to the base of register map
|
||||
* @param[in] Offset from the base
|
||||
* @param[in] Bit mask to clear bits to logical 0
|
||||
* \return void
|
||||
*/
|
||||
static void synopGMACClearBits(u64 RegBase, u32 RegOffset, u32 BitPos)
|
||||
{
|
||||
u32 data;
|
||||
data = synopGMACReadReg(RegBase, RegOffset);
|
||||
data &= (~BitPos);
|
||||
synopGMACWriteReg(RegBase, RegOffset, data);
|
||||
#if SYNOP_REG_DEBUG
|
||||
TR("%s !!!!!!!!!!!!! RegOffset = 0x%08x RegData = 0x%08x\n", __FUNCTION__, RegOffset, data );
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Low level function to Check the setting of the bits.
|
||||
*
|
||||
* @param[in] pointer to the base of register map
|
||||
* @param[in] Offset from the base
|
||||
* @param[in] Bit mask to set bits to logical 1
|
||||
* \return returns TRUE if set to '1' returns FALSE if set to '0'. Result undefined there are no bit set in the BitPos argument.
|
||||
*
|
||||
*/
|
||||
static bool synopGMACCheckBits(u64 RegBase, u32 RegOffset, u32 BitPos)
|
||||
{
|
||||
u32 data;
|
||||
data = synopGMACReadReg(RegBase, RegOffset);
|
||||
data &= BitPos;
|
||||
|
||||
if(data)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -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*/
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 <rthw.h>
|
||||
#include <rtdef.h>
|
||||
|
||||
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;
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
jr ra
|
||||
|
|
|
@ -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 <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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 <rtthread.h>
|
||||
#include <mips.h>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -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 <rtthread.h>
|
||||
#include <rthw.h>
|
||||
#include <board.h>
|
||||
|
||||
#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
|
|
@ -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 <rtthread.h>
|
||||
|
||||
#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
|
Loading…
Reference in New Issue