diff --git a/.gitmodules b/.gitmodules index e2382d003..b2960750c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "machines/riscv/pulpino/pulpino"] path = machines/riscv/pulpino/pulpino url = https://github.com/Instrumented-Pulpino/pulpino.git +[submodule "libraries/net/ethernet/lwip"] + path = libraries/net/ethernet/lwip + url = https://git.savannah.nongnu.org/git/lwip.git diff --git a/examples/cortex-a-r/armv8/spider/ethernet/build.sh b/examples/cortex-a-r/armv8/spider/ethernet/build.sh new file mode 100755 index 000000000..cb0690389 --- /dev/null +++ b/examples/cortex-a-r/armv8/spider/ethernet/build.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +#stop on errors +set -e + +if [[ ! -d "_build" ]] +then + mkdir _build +fi + +echo "*** Run Goil ***" +goil --target=cortex-a-r/armv8/spider --templates=../../../../../goil/templates/ eth.oil + +echo "*** Run Make ***" +./make.py diff --git a/examples/cortex-a-r/armv8/spider/ethernet/eth.oil b/examples/cortex-a-r/armv8/spider/ethernet/eth.oil new file mode 100644 index 000000000..59bb6e7a7 --- /dev/null +++ b/examples/cortex-a-r/armv8/spider/ethernet/eth.oil @@ -0,0 +1,94 @@ +OIL_VERSION = "4.0"; + +IMPLEMENTATION trampoline { + TASK { + UINT32 STACKSIZE = 2048 ; + } ; + + ISR { + UINT32 STACKSIZE = 2048 ; + } ; +}; + +CPU eth { + OS config { + STATUS = EXTENDED; + + BUILD = TRUE { + TRAMPOLINE_BASE_PATH = "../../../../.."; + APP_SRC = "main.c"; + APP_NAME = "eth_exe.elf"; + CFLAGS = "-O0 -g -DHSCIF_1843200BPS -DNO_SYS"; + LDFLAGS = "-Map=eth_exe.map"; + COMPILER = "arm-none-eabi-gcc"; + CPPCOMPILER = "arm-none-eabi-g++"; + ASSEMBLER = "arm-none-eabi-as"; + LINKER = "arm-none-eabi-ld"; + COPIER = "arm-none-eabi-objcopy"; + SYSTEM = PYTHON; + LIBRARY = serial; + LIBRARY = lwip; + }; + SYSTEM_CALL = TRUE; + MEMMAP = TRUE { + COMPILER = gcc; + LINKER = gnu_ld { SCRIPT = "script.ld"; }; + ASSEMBLER = gnu_as; + MEMORY_PROTECTION = FALSE; + }; + }; + + APPMODE std {}; + + TASK sample_init { + PRIORITY = 1; + AUTOSTART = TRUE { APPMODE = std; }; + ACTIVATION = 1; + SCHEDULE = FULL; + }; + + TASK monitor { + PRIORITY = 1; + AUTOSTART = FALSE; + ACTIVATION = 1; + SCHEDULE = FULL; + }; + + /* ethernet driver needs */ + TASK gwca1_rx_tx_task { + PRIORITY = 2; + AUTOSTART = FALSE; + ACTIVATION = 1; + SCHEDULE = FULL; + }; + + ISR gwca1_rx_tx_int { + CATEGORY = 2; + PRIORITY = 2; + SOURCE = GWCA1_RX_TX_INT; + }; + + ISR gwca1_rx_ts_int { + CATEGORY = 2; + PRIORITY = 3; + SOURCE = GWCA1_RX_TS_INT; + }; + + ISR coma_err_int { + CATEGORY = 2; + PRIORITY = 4; + SOURCE = COMA_ERR_INT; + }; + + ISR gwca1_err_int { + CATEGORY = 2; + PRIORITY = 5; + SOURCE = GWCA1_ERR_INT; + }; + + ISR etha0_err_int { + CATEGORY = 2; + PRIORITY = 6; + SOURCE = ETHA0_ERR_INT; + }; +}; diff --git a/examples/cortex-a-r/armv8/spider/ethernet/main.c b/examples/cortex-a-r/armv8/spider/ethernet/main.c new file mode 100644 index 000000000..ef475c145 --- /dev/null +++ b/examples/cortex-a-r/armv8/spider/ethernet/main.c @@ -0,0 +1,58 @@ +#include "tpl_os.h" +#include "utils.h" +#include "spider_serial.h" +#include "string.h" +#include "lwip/netif.h" +#include "lwip/ip4_addr.h" +#include "lwip/timeouts.h" +#include "ethif.h" + +#define APP_Task_sample_init_START_SEC_CODE +#include "tpl_memmap.h" + +ip4_addr_t ip4_addr, net_mask, gateway; +struct netif ethif_netif; + +// Is this the right section for the main function?? +FUNC(int, OS_APPL_CODE) main(void) +{ + StartOS(OSDEFAULTAPPMODE); + return 0; +} + +TASK(sample_init) { + Serial_Init(); + + rswitch_enable_clock_and_reset(); + port_init(); + + lwip_init(); + + IP4_ADDR(&ip4_addr, 192, 168, 1, 2); + IP4_ADDR(&net_mask, 255, 255, 255, 0); + IP4_ADDR(&gateway, 0, 0, 0, 0); + + netif_add(ðif_netif, &ip4_addr, &net_mask, &gateway, NULL, + ethif_init, netif_input); + + netif_set_up(ðif_netif); + + ActivateTask(monitor); + + TerminateTask(); +} + +#define APP_Task_sample_init_STOP_SEC_CODE +#include "tpl_memmap.h" + +#define APP_Task_sample_init_START_SEC_CODE +#include "tpl_memmap.h" + +TASK(monitor) { + while (1) { + sys_check_timeouts(); + } +} + +#define APP_Task_sample_init_STOP_SEC_CODE +#include "tpl_memmap.h" diff --git a/examples/cortex-a-r/armv8/spider/ethernet_basic/build.sh b/examples/cortex-a-r/armv8/spider/ethernet_basic/build.sh new file mode 100755 index 000000000..cb0690389 --- /dev/null +++ b/examples/cortex-a-r/armv8/spider/ethernet_basic/build.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +#stop on errors +set -e + +if [[ ! -d "_build" ]] +then + mkdir _build +fi + +echo "*** Run Goil ***" +goil --target=cortex-a-r/armv8/spider --templates=../../../../../goil/templates/ eth.oil + +echo "*** Run Make ***" +./make.py diff --git a/examples/cortex-a-r/armv8/spider/ethernet_basic/eth.oil b/examples/cortex-a-r/armv8/spider/ethernet_basic/eth.oil new file mode 100644 index 000000000..51e4c81c5 --- /dev/null +++ b/examples/cortex-a-r/armv8/spider/ethernet_basic/eth.oil @@ -0,0 +1,93 @@ +OIL_VERSION = "4.0"; + +IMPLEMENTATION trampoline { + TASK { + UINT32 STACKSIZE = 2048 ; + } ; + + ISR { + UINT32 STACKSIZE = 2048 ; + } ; +}; + +CPU eth { + OS config { + STATUS = EXTENDED; + + BUILD = TRUE { + TRAMPOLINE_BASE_PATH = "../../../../.."; + APP_SRC = "main.c"; + APP_NAME = "eth_exe.elf"; + CFLAGS = "-O0 -g -DHSCIF_1843200BPS"; + LDFLAGS = "-Map=eth_exe.map"; + COMPILER = "arm-none-eabi-gcc"; + CPPCOMPILER = "arm-none-eabi-g++"; + ASSEMBLER = "arm-none-eabi-as"; + LINKER = "arm-none-eabi-ld"; + COPIER = "arm-none-eabi-objcopy"; + SYSTEM = PYTHON; + LIBRARY = serial; + LIBRARY = ethernet; + }; + SYSTEM_CALL = TRUE; + MEMMAP = TRUE { + COMPILER = gcc; + LINKER = gnu_ld { SCRIPT = "script.ld"; }; + ASSEMBLER = gnu_as; + MEMORY_PROTECTION = FALSE; + }; + }; + + APPMODE std {}; + + TASK sample_init { + PRIORITY = 1; + AUTOSTART = TRUE { APPMODE = std; }; + ACTIVATION = 1; + SCHEDULE = FULL; + }; + + TASK echo { + PRIORITY = 1; + AUTOSTART = FALSE; + ACTIVATION = 1; + SCHEDULE = FULL; + }; + + TASK gwca1_rx_tx_task { + PRIORITY = 2; + AUTOSTART = FALSE; + ACTIVATION = 1; + SCHEDULE = FULL; + }; + + ISR gwca1_rx_tx_int { + CATEGORY = 1; + PRIORITY = 3; + SOURCE = GWCA1_RX_TX_INT; + }; + + ISR gwca1_rx_ts_int { + CATEGORY = 1; + PRIORITY = 4; + SOURCE = GWCA1_RX_TS_INT; + }; + + ISR coma_err_int { + CATEGORY = 1; + PRIORITY = 5; + SOURCE = COMA_ERR_INT; + }; + + ISR gwca1_err_int { + CATEGORY = 1; + PRIORITY = 6; + SOURCE = GWCA1_ERR_INT; + }; + + ISR etha0_err_int { + CATEGORY = 1; + PRIORITY = 7; + SOURCE = ETHA0_ERR_INT; + }; +}; diff --git a/examples/cortex-a-r/armv8/spider/ethernet_basic/main.c b/examples/cortex-a-r/armv8/spider/ethernet_basic/main.c new file mode 100644 index 000000000..c49621955 --- /dev/null +++ b/examples/cortex-a-r/armv8/spider/ethernet_basic/main.c @@ -0,0 +1,182 @@ +#include "tpl_os.h" +#include "utils.h" +#include "eth_serdes.h" +#include "rswitch.h" +#include "eth_gptp.h" +#include "spider_serial.h" +#include "string.h" + +#define APP_Task_sample_init_START_SEC_CODE +#include "tpl_memmap.h" + +uint8 tmp_buffer[1600]; +uint16 tmp_buffer_len = 0; + +// Is this the right section for the main function?? +FUNC(int, OS_APPL_CODE) main(void) +{ + StartOS(OSDEFAULTAPPMODE); + return 0; +} + +void eth_callback(uint8 *data, uint16 len) +{ + /* Copy the data into the local buffer and then activate the Echo task */ + memcpy(tmp_buffer, data, len); + tmp_buffer_len = len; + ActivateTask(echo); +} + +TASK(sample_init) { + int ret; + + Serial_Init(); + + rswitch_enable_clock_and_reset(); + port_init(); + // Interrupt initializazion done by Trampoline + eth_disable_fuse_ovr(); + + ret = eth_serdes_initialize(); + if (ret != 0) { + debug_msg("Error in eth_serdes_initialize"); + goto exit; + } + debug_msg("SERDES initialization done"); + + ret = rswitch_init(); + if (ret != 0) { + debug_msg("Error in rswitch_init\n"); + goto exit; + } + debug_msg("RSwitch initialization done"); + + debug_msg("Initialize gPTP"); + eth_gptp_init(); + + ret = rswitch_open(); + if (ret != 0) { + debug_msg("Error in rswitch_open\n"); + goto exit; + } + debug_msg("RSwitch open completed"); + + rswitch_regiter_data_received_callback(eth_callback); + + debug_msg("Initialization completed"); +exit: + TerminateTask(); +} + +#define APP_Task_sample_init_STOP_SEC_CODE +#include "tpl_memmap.h" + +#define APP_Task_echo_START_SEC_CODE +#include "tpl_memmap.h" + +TASK(echo) +{ + int ret; + uint8 src_mac[6]; + uint8 dst_mac[6]; + +#if 0 /* set to 1 if debug logs are needed */ + debug_msg("## Echo task ##"); + debug_msg("Received:"); + debug_print_buffer(tmp_buffer, tmp_buffer_len); +#endif + + /* check if protocol = ARP */ + if ((tmp_buffer[12]==0x08)&&(tmp_buffer[13]==0x06)) { + /* Swap MAC addresses */ + memcpy(dst_mac, &tmp_buffer[6], 6); + memcpy(&tmp_buffer[0], dst_mac, 6); + /* Send our MAC address */ + tmp_buffer[6] = 0x2E; + tmp_buffer[7] = 0x09; + tmp_buffer[8] = 0x0A; + tmp_buffer[9] = 0x00; + tmp_buffer[10] = 0x00; + tmp_buffer[11] = 0x00; + + /* Swap MAC addresses */ + memcpy(src_mac, &tmp_buffer[22], 6); + memcpy(&tmp_buffer[32], src_mac, 6); + /* Send our MAC address */ + tmp_buffer[22] = 0x2E; + tmp_buffer[23] = 0x09; + tmp_buffer[24] = 0x0A; + tmp_buffer[25] = 0x00; + tmp_buffer[26] = 0x00; + tmp_buffer[27] = 0x00; + + /* Swap IP addresses */ + memcpy(src_mac, &tmp_buffer[28], 4); + memcpy(dst_mac, &tmp_buffer[38], 4); + memcpy(&tmp_buffer[28], dst_mac, 4); + memcpy(&tmp_buffer[38], src_mac, 4); + + /* Answer arp */ + tmp_buffer[21] = 2; + } + + /* Check if protocol = ICMP (ping) */ + if ((tmp_buffer[12]==0x08)&&(tmp_buffer[13]==0x00)&&(tmp_buffer[23]==0x01)) { + /* Switch mac addresses */ + memcpy(src_mac, &tmp_buffer[0], 6); + memcpy(dst_mac, &tmp_buffer[6], 6); + memcpy(&tmp_buffer[0], dst_mac, 6); + memcpy(&tmp_buffer[6], src_mac, 6); + + /* Switch IP addresses */ + memcpy(src_mac, &tmp_buffer[26], 4); + memcpy(dst_mac, &tmp_buffer[30], 4); + memcpy(&tmp_buffer[26], dst_mac, 4); + memcpy(&tmp_buffer[30], src_mac, 4); + + /***************************/ + /* Compute header checksum */ + /***************************/ + /* Clear checksum */ + tmp_buffer[24] = 0x0; + tmp_buffer[25] = 0x0; + /* Compute sum */ + uint32 checksum = 0x0; + for(uint8 i=0; i<10; i++) { + checksum += tmp_buffer[14+2*i] * 0x100; + checksum += tmp_buffer[15+2*i]; + } + /* Compute carry */ + while(checksum > 0xffff) { + checksum = (checksum & 0xffff) + (checksum >> 16); + } + /* Compute the ones' complement */ + checksum = 0xffff - checksum; + /* Update checksum field */ + tmp_buffer[24] = (checksum >> 8) & 0xff; + tmp_buffer[25] = checksum & 0xff; + + /* Answer ping */ + tmp_buffer[34] = 0; + + /* ICMP checksum */ + /* We only modify the ICMP type for 0x8 (ping request) to 0x0 (ping answer) */ + /* so, no need to compute the checksum, only need to add 8 to it */ + if(tmp_buffer[36]>=0xf8) tmp_buffer[37] = tmp_buffer[37]+1; + tmp_buffer[36] = tmp_buffer[36] + 8; + } + + ret = rswitch_send_data(tmp_buffer, tmp_buffer_len); + if (ret != 0) { + debug_msg("Send data back: FAILED"); + } + + /* Clear the data for the next iteration */ + memset(tmp_buffer, 0, sizeof(tmp_buffer)); + tmp_buffer_len = 0; + + TerminateTask(); +} + +#define APP_Task_echo_STOP_SEC_CODE +#include "tpl_memmap.h" \ No newline at end of file diff --git a/examples/cortex-a-r/armv8/spider/lwip/build.sh b/examples/cortex-a-r/armv8/spider/lwip/build.sh new file mode 100755 index 000000000..9d6672db6 --- /dev/null +++ b/examples/cortex-a-r/armv8/spider/lwip/build.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +#stop on errors +set -e + +if [[ ! -d "_build" ]] +then + mkdir _build +fi + +echo "*** Run Goil ***" +goil --target=cortex-a-r/armv8/spider --templates=../../../../../goil/templates/ lwip.oil + +echo "*** Run Make ***" +./make.py diff --git a/examples/cortex-a-r/armv8/spider/lwip/lwip.c b/examples/cortex-a-r/armv8/spider/lwip/lwip.c new file mode 100755 index 000000000..3d0ad3461 --- /dev/null +++ b/examples/cortex-a-r/armv8/spider/lwip/lwip.c @@ -0,0 +1,57 @@ +#include "tpl_os.h" + +#include "spider_serial.h" +#include "printf.h" +#include "utils.h" + +#include "ethif.h" + +/* lwIP core includes */ +#include "lwip/opt.h" +#include "lwip/dhcp.h" +#include "lwip/tcpip.h" + +struct netif this_netif; + +FUNC(int, OS_APPL_CODE) main(void) +{ + Serial_Init(); + StartOS(OSDEFAULTAPPMODE); + return 0; +} + +#define DHCP 0 + +TASK(lwip) +{ + debug_msg("init: call"); + struct netif this_netif; + ip4_addr_t ip4_addr, net_mask, gateway; + + debug_msg("init ethernet low level"); + rswitch_enable_clock_and_reset(); + port_init(); + + debug_msg("ethernet_init_inside_thread"); + tcpip_init(NULL,NULL); + + IP4_ADDR(&ip4_addr, 192, 168, 1, 2); + IP4_ADDR(&net_mask, 255, 255, 255, 0); + IP4_ADDR(&gateway, 192, 168, 1, 255); +#if DHCP==1 + netif_add( &this_netif, NULL, &net_mask, NULL, NULL, ethif_init, tcpip_input); +#else + netif_add( &this_netif, &ip4_addr, &net_mask, NULL, NULL, ethif_init, tcpip_input); +#endif + + netif_set_up(&this_netif); + +#if DHCP==1 + dhcp_start(&this_netif); +#endif + + debug_msg("init: done"); + + TerminateTask(); +} + diff --git a/examples/cortex-a-r/armv8/spider/lwip/lwip.oil b/examples/cortex-a-r/armv8/spider/lwip/lwip.oil new file mode 100755 index 000000000..fb66d29ab --- /dev/null +++ b/examples/cortex-a-r/armv8/spider/lwip/lwip.oil @@ -0,0 +1,108 @@ +OIL_VERSION = "4.0"; + +IMPLEMENTATION trampoline { + + /* This fix the default STACKSIZE of tasks */ + TASK { + UINT32 STACKSIZE = 2000 ; + } ; + + /* This fix the default STACKSIZE of ISRs */ + ISR { + UINT32 STACKSIZE = 2000 ; + } ; +}; + +CPU lwip { + OS config { + STATUS = EXTENDED; + + BUILD = TRUE { + TRAMPOLINE_BASE_PATH = "../../../../.."; + APP_SRC = "lwip.c"; + + APP_NAME = "lwip_exe.elf"; + CFLAGS = "-O0 -DHSCIF_1843200BPS -ggdb"; + LDFLAGS = "-Map=lwip.map"; + COMPILER = "arm-none-eabi-gcc"; + CPPCOMPILER = "arm-none-eabi-g++"; + ASSEMBLER = "arm-none-eabi-as"; + LINKER = "arm-none-eabi-ld"; + COPIER = "arm-none-eabi-objcopy"; + SYSTEM = PYTHON; + + LIBRARY = serial; + LIBRARY = lwip; + }; + SYSTEM_CALL = TRUE; + MEMMAP = TRUE { + COMPILER = gcc; + LINKER = gnu_ld { SCRIPT = "script.ld"; }; + ASSEMBLER = gnu_as; + MEMORY_PROTECTION = FALSE; + }; + }; + + APPMODE std {}; + + TASK lwip { + PRIORITY = 1; + AUTOSTART = TRUE { APPMODE = std; }; + ACTIVATION = 1; + SCHEDULE = FULL; + }; + + /* LWIP needs */ + EVENT lwip_sync { + MASK = AUTO; + }; + + TASK tcpip_task { + PRIORITY = 1; + AUTOSTART = FALSE; + ACTIVATION = 1; + SCHEDULE = FULL; + EVENT = lwip_sync; + }; + + /* eth driver needs */ + TASK gwca1_rx_tx_task { + PRIORITY = 2; + AUTOSTART = FALSE; + ACTIVATION = 1; + SCHEDULE = FULL; + EVENT = lwip_sync; + }; + + ISR gwca1_rx_tx_int { + CATEGORY = 1; + PRIORITY = 3; + SOURCE = GWCA1_RX_TX_INT; + }; + + ISR gwca1_rx_ts_int { + CATEGORY = 1; + PRIORITY = 4; + SOURCE = GWCA1_RX_TS_INT; + }; + + ISR coma_err_int { + CATEGORY = 1; + PRIORITY = 5; + SOURCE = COMA_ERR_INT; + }; + + ISR gwca1_err_int { + CATEGORY = 1; + PRIORITY = 6; + SOURCE = GWCA1_ERR_INT; + }; + + ISR etha0_err_int { + CATEGORY = 1; + PRIORITY = 7; + SOURCE = ETHA0_ERR_INT; + }; + +}; + diff --git a/examples/cortex-a-r/armv8/spider/serial/build.sh b/examples/cortex-a-r/armv8/spider/serial/build.sh new file mode 100755 index 000000000..3e642b991 --- /dev/null +++ b/examples/cortex-a-r/armv8/spider/serial/build.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +#stop on errors +set -e + +if [[ ! -d "_build" ]] +then + mkdir _build +fi + +echo "*** Run Goil ***" +goil --target=cortex-a-r/armv8/spider --templates=../../../../../goil/templates/ serial.oil + +echo "*** Run Make ***" +./make.py diff --git a/examples/cortex-a-r/armv8/spider/serial/serial.c b/examples/cortex-a-r/armv8/spider/serial/serial.c new file mode 100755 index 000000000..097497854 --- /dev/null +++ b/examples/cortex-a-r/armv8/spider/serial/serial.c @@ -0,0 +1,33 @@ +#include "tpl_os.h" + +#include "spider_serial.h" + +FUNC(int, OS_APPL_CODE) main(void) +{ + Serial_Init(); + + StartOS(OSDEFAULTAPPMODE); + return 0; +} + +volatile uint32 tmp = 0; +TASK(serial_rx) +{ + uint8 uart_rx; + while(1) + { + if (Serial_Rx(&uart_rx)) + { + /* If received a char, send back the next one */ + Serial_Tx(uart_rx+1); + } + } +} + +TASK(serial_tx) +{ + /* Send next alphabet letter each time*/ + static uint8 uart_char=0; + uart_char = (uart_char+1) % 26; + Serial_Tx('a' + uart_char); +} diff --git a/examples/cortex-a-r/armv8/spider/serial/serial.oil b/examples/cortex-a-r/armv8/spider/serial/serial.oil new file mode 100755 index 000000000..b0ae804da --- /dev/null +++ b/examples/cortex-a-r/armv8/spider/serial/serial.oil @@ -0,0 +1,72 @@ +OIL_VERSION = "4.0"; + +IMPLEMENTATION trampoline { + + /* This fix the default STACKSIZE of tasks */ + TASK { + UINT32 STACKSIZE = 1000 ; + } ; + + /* This fix the default STACKSIZE of ISRs */ + ISR { + UINT32 STACKSIZE = 1000 ; + } ; +}; + +CPU serial { + OS config { + STATUS = EXTENDED; + + BUILD = TRUE { + TRAMPOLINE_BASE_PATH = "../../../../.."; + APP_SRC = "serial.c"; + APP_NAME = "serial_exe.elf"; + CFLAGS = "-O0 -DHSCIF_1843200BPS"; + LDFLAGS = "-Map=serial.map"; + COMPILER = "arm-none-eabi-gcc"; + CPPCOMPILER = "arm-none-eabi-g++"; + ASSEMBLER = "arm-none-eabi-as"; + LINKER = "arm-none-eabi-ld"; + COPIER = "arm-none-eabi-objcopy"; + SYSTEM = PYTHON; + + LIBRARY = serial; + }; + SYSTEM_CALL = TRUE; + MEMMAP = TRUE { + COMPILER = gcc; + LINKER = gnu_ld { SCRIPT = "script.ld"; }; + ASSEMBLER = gnu_as; + MEMORY_PROTECTION = FALSE; + }; + }; + + APPMODE std {}; + + TASK serial_rx { + PRIORITY = 1; + AUTOSTART = TRUE { APPMODE = std; }; + ACTIVATION = 1; + SCHEDULE = FULL; + }; + + TASK serial_tx { + PRIORITY = 2; + AUTOSTART = FALSE; + ACTIVATION = 1; + SCHEDULE = FULL; + }; + + ALARM serial_serial { + COUNTER = SystemCounter; + ACTION = ACTIVATETASK { + TASK = serial_tx; + }; + AUTOSTART = TRUE { + APPMODE = std; + ALARMTIME = 100; + CYCLETIME = 100; + }; + }; +}; + diff --git a/goil/templates/config/cortex-a-r/armv8/spider/config.oil b/goil/templates/config/cortex-a-r/armv8/spider/config.oil index 3193107a3..3f2c057e7 100755 --- a/goil/templates/config/cortex-a-r/armv8/spider/config.oil +++ b/goil/templates/config/cortex-a-r/armv8/spider/config.oil @@ -5,6 +5,9 @@ IMPLEMENTATION spider { BOOLEAN [ TRUE { ENUM [ + serial, + ethernet, + lwip, can ] LIBRARY[]; }, @@ -33,6 +36,16 @@ CPU spider { // TO BE UPDATED INTERRUPT_SOURCE ARM_TIMER { SOURCE_NUM = 27; VECTOR = IRQ_Interrupt; ACK = TRUE; }; INTERRUPT_SOURCE ICCOM_INT { SOURCE_NUM = 353; VECTOR = IRQ_Interrupt; ACK = TRUE; }; + INTERRUPT_SOURCE GWCA0_RX_TX_INT { SOURCE_NUM = 312; VECTOR = IRQ_Interrupt; ACK = TRUE; }; + INTERRUPT_SOURCE GWCA1_RX_TX_INT { SOURCE_NUM = 320; VECTOR = IRQ_Interrupt; ACK = TRUE; }; + INTERRUPT_SOURCE GWCA0_RX_TS_INT { SOURCE_NUM = 328; VECTOR = IRQ_Interrupt; ACK = TRUE; }; + INTERRUPT_SOURCE GWCA1_RX_TS_INT { SOURCE_NUM = 330; VECTOR = IRQ_Interrupt; ACK = TRUE; }; + INTERRUPT_SOURCE COMA_ERR_INT { SOURCE_NUM = 290; VECTOR = IRQ_Interrupt; ACK = TRUE; }; + INTERRUPT_SOURCE GWCA0_ERR_INT { SOURCE_NUM = 291; VECTOR = IRQ_Interrupt; ACK = TRUE; }; + INTERRUPT_SOURCE GWCA1_ERR_INT { SOURCE_NUM = 292; VECTOR = IRQ_Interrupt; ACK = TRUE; }; + INTERRUPT_SOURCE ETHA0_ERR_INT { SOURCE_NUM = 293; VECTOR = IRQ_Interrupt; ACK = TRUE; }; + INTERRUPT_SOURCE ETHA1_ERR_INT { SOURCE_NUM = 294; VECTOR = IRQ_Interrupt; ACK = TRUE; }; + INTERRUPT_SOURCE ETHA2_ERR_INT { SOURCE_NUM = 295; VECTOR = IRQ_Interrupt; ACK = TRUE; }; PLATFORM_FILES spider { PATH = "cortex-a-r/armv8/spider"; @@ -45,6 +58,29 @@ CPU spider { CFILE = "tpl_vector_table_ns.s"; }; + LIBRARY serial { + GLOBAL = TRUE; + PATH = "drivers/serial/renesas"; + }; + + LIBRARY ethernet { + GLOBAL = TRUE; + PATH = "drivers/ethernet/renesas"; + NEEDS = serial; + }; + + LIBRARY lwip_port_renesas_spider { + GLOBAL = TRUE; + NEEDS = ethernet; + PATH = "drivers/lwip_port/renesas"; + }; + + LIBRARY lwip { + GLOBAL = TRUE; + NEEDS = lwip_port_renesas_spider; + PATH = "net/ethernet/lwip"; + }; + LIBRARY net_can_renesas_spider_driver { GLOBAL = TRUE; PATH = "drivers/can/renesas"; diff --git a/goil/templates/config/cortex-a-r/armv8/spider/interruptSources.oil b/goil/templates/config/cortex-a-r/armv8/spider/interruptSources.oil index 07aef5022..cb298815c 100755 --- a/goil/templates/config/cortex-a-r/armv8/spider/interruptSources.oil +++ b/goil/templates/config/cortex-a-r/armv8/spider/interruptSources.oil @@ -4,5 +4,15 @@ ENUM [ /* ARM IRQs */ ARM_TIMER, /* 0 */ - ICCOM_INT /* 1 */ + ICCOM_INT, /* 1 */ + GWCA0_RX_TX_INT, /* 2 */ + GWCA1_RX_TX_INT, /* 3 */ + GWCA0_RX_TS_INT, /* 4 */ + GWCA1_RX_TS_INT, /* 5 */ + COMA_ERR_INT, /* 6 */ + GWCA0_ERR_INT, /* 7 */ + GWCA1_ERR_INT, /* 8 */ + ETHA0_ERR_INT, /* 9 */ + ETHA1_ERR_INT, /* 10 */ + ETHA2_ERR_INT /* 11 */ ] SOURCE; diff --git a/goil/templates/libraries/drivers/ethernet/renesas/config.oil b/goil/templates/libraries/drivers/ethernet/renesas/config.oil new file mode 100644 index 000000000..0a48f8d43 --- /dev/null +++ b/goil/templates/libraries/drivers/ethernet/renesas/config.oil @@ -0,0 +1,10 @@ +CPU drivers_ethernet_renesas_spider_files { + LIBRARY ethernet { + PATH = "drivers/ethernet/renesas"; + + CFILE = "utils.c"; + CFILE = "rswitch.c"; + CFILE = "eth_serdes.c"; + CFILE = "eth_gptp.c"; + }; +}; diff --git a/goil/templates/libraries/drivers/lwip_port/renesas/config.oil b/goil/templates/libraries/drivers/lwip_port/renesas/config.oil new file mode 100644 index 000000000..22353bf51 --- /dev/null +++ b/goil/templates/libraries/drivers/lwip_port/renesas/config.oil @@ -0,0 +1,7 @@ +CPU drivers_lwip_port_renesas_spider_files { + LIBRARY lwip_port_renesas_spider { + PATH = "drivers/lwip_port/renesas"; + CFILE = "sys_arch.c"; + CFILE = "ethif.c"; + }; +}; diff --git a/goil/templates/libraries/drivers/serial/renesas/config.oil b/goil/templates/libraries/drivers/serial/renesas/config.oil new file mode 100644 index 000000000..6cf0d8395 --- /dev/null +++ b/goil/templates/libraries/drivers/serial/renesas/config.oil @@ -0,0 +1,7 @@ +CPU net_serial_renesas_spider_driver_files { + LIBRARY serial { + PATH = "drivers/serial/renesas"; + CFILE = "spider_serial.c"; + CFILE = "printf.c"; + }; +}; diff --git a/goil/templates/libraries/net/ethernet/lwip/config.oil b/goil/templates/libraries/net/ethernet/lwip/config.oil new file mode 100755 index 000000000..94e6161bf --- /dev/null +++ b/goil/templates/libraries/net/ethernet/lwip/config.oil @@ -0,0 +1,55 @@ +CPU net_ethernet_lwip_files { + LIBRARY lwip { + PATH = "net/ethernet/lwip/src/include"; + + // The minimum set of files needed for lwIP. + CFILE = "../core/init.c"; + CFILE = "../core/def.c"; + CFILE = "../core/dns.c"; + CFILE = "../core/inet_chksum.c"; + CFILE = "../core/ip.c"; + CFILE = "../core/mem.c"; + CFILE = "../core/memp.c"; + CFILE = "../core/netif.c"; + CFILE = "../core/pbuf.c"; + CFILE = "../core/raw.c"; + CFILE = "../core/stats.c"; + CFILE = "../core/sys.c"; + CFILE = "../core/altcp.c"; + CFILE = "../core/altcp_alloc.c"; + CFILE = "../core/altcp_tcp.c"; + CFILE = "../core/tcp.c"; + CFILE = "../core/tcp_in.c"; + CFILE = "../core/tcp_out.c"; + CFILE = "../core/timeouts.c"; + CFILE = "../core/udp.c"; + + // lwipcore4 + CFILE = "../core/ipv4/acd.c"; + CFILE = "../core/ipv4/autoip.c"; + CFILE = "../core/ipv4/dhcp.c"; + CFILE = "../core/ipv4/etharp.c"; + CFILE = "../core/ipv4/icmp.c"; + CFILE = "../core/ipv4/igmp.c"; + CFILE = "../core/ipv4/ip4_frag.c"; + CFILE = "../core/ipv4/ip4.c"; + CFILE = "../core/ipv4/ip4_addr.c"; + + // APIFILES: The files which implement the sequential and socket APIs. + CFILE = "../api/api_lib.c"; + CFILE = "../api/api_msg.c"; + CFILE = "../api/err.c"; + //CFILE = "../api/if_api.c"; + CFILE = "../api/netbuf.c"; + CFILE = "../api/netdb.c"; + CFILE = "../api/netifapi.c"; + //CFILE = "../api/sockets.c"; + CFILE = "../api/tcpip.c"; + + // Files implementing various generic network interface functions + CFILE = "../netif/ethernet.c"; + CFILE = "../netif/bridgeif.c"; + CFILE = "../netif/bridgeif_fdb.c"; + }; +}; + diff --git a/libraries/drivers/ethernet/renesas/err_codes.h b/libraries/drivers/ethernet/renesas/err_codes.h new file mode 100644 index 000000000..ca307be8d --- /dev/null +++ b/libraries/drivers/ethernet/renesas/err_codes.h @@ -0,0 +1,8 @@ +#ifndef _ERR_CODES_H_ +#define _ERR_CODES_H_ + +#define ERR_TIMEOUT (-1) +#define ERR_BUFF_TOO_LARGE (-2) +#define ERR_TX_FAILURE (-3) + +#endif /* _ERR_CODES_H_ */ \ No newline at end of file diff --git a/libraries/drivers/ethernet/renesas/eth_gptp.c b/libraries/drivers/ethernet/renesas/eth_gptp.c new file mode 100644 index 000000000..eaedc3d40 --- /dev/null +++ b/libraries/drivers/ethernet/renesas/eth_gptp.c @@ -0,0 +1,35 @@ +#include "eth_gptp.h" +#include "rswitch_regs.h" +#include "utils.h" + +/* Note: we are only using Timer0 */ + +#define PTPTIVC_INIT 0x19000000 /* 320MHz */ +#define RCAR_GEN4_PTP_CLOCK_S4 PTPTIVC_INIT + +#define PTPRO RSWITCH_GPTP_ADDR + +#define PTPTMEC PTPRO + 0x0010 +#define PTPTMDC PTPRO + 0x0014 +#define PTPTIVC0 PTPRO + 0x0020 +#define PTPTOVC00 PTPRO + 0x0030 +#define PTPTOVC10 PTPRO + 0x0034 +#define PTPTOVC20 PTPRO + 0x0038 +#define PTPGPTPTM00 PTPRO + 0x0050 +#define PTPGPTPTM10 PTPRO + 0x0054 +#define PTPGPTPTM20 PTPRO + 0x0058 + +void eth_gptp_init(void) +{ + reg_write32(RCAR_GEN4_PTP_CLOCK_S4, PTPTIVC0); + reg_write32(0x1, PTPTMEC); +} + +void eth_gptp_get_time(struct gptp_time *output) +{ + output->nano = reg_read32(PTPGPTPTM00); + output->seconds = reg_read32(PTPGPTPTM10) + + (((uint64) reg_read32(PTPGPTPTM20)) << 32); + /* A better implementation might check that none of the above + registers overflowed while reading others... */ +} \ No newline at end of file diff --git a/libraries/drivers/ethernet/renesas/eth_gptp.h b/libraries/drivers/ethernet/renesas/eth_gptp.h new file mode 100644 index 000000000..83d6c5bbe --- /dev/null +++ b/libraries/drivers/ethernet/renesas/eth_gptp.h @@ -0,0 +1,14 @@ +#ifndef _ETH_GPTP_H_ +#define _ETH_GPTP_H_ + +#include "tpl_os.h" + +struct gptp_time { + uint64 seconds; + uint32 nano; +}; + +void eth_gptp_init(void); +void eth_gptp_get_time(struct gptp_time *output); + +#endif /* _ETH_GPTP_H_ */ \ No newline at end of file diff --git a/libraries/drivers/ethernet/renesas/eth_serdes.c b/libraries/drivers/ethernet/renesas/eth_serdes.c new file mode 100644 index 000000000..d83ea9ad1 --- /dev/null +++ b/libraries/drivers/ethernet/renesas/eth_serdes.c @@ -0,0 +1,351 @@ +#include "tpl_os.h" +#include "eth_serdes.h" +#include "err_codes.h" +#include "utils.h" + +//#define ETH_SERDES_AN_ENABLED + +#define ETH_SERDES_CH_NUM 3 +#define ETH_SERDES_XPCS_CH0 0UL +#define ETH_SERDES_XPCS_CH1 1UL +#define ETH_SERDES_XPCS_CH2 2UL + +/* Maximum Ethernet Timeout Count */ +#define ETH_TIMEOUT_COUNT 63158UL + +/* Ethernet SERDES registers Base Address */ +#define ETH_SERDES_XPCS0_BASE 0xE6444000UL +#define ETH_SERDES_XPCS1_BASE 0xE6444400UL +#define ETH_SERDES_XPCS2_BASE 0xE6444800UL +/* Ehternet SERDES Bank Register Address */ +#define ETH_SERDES_XPCS0_BANK 0xE64443FCUL +#define ETH_SERDES_XPCS1_BANK 0xE64447FCUL +#define ETH_SERDES_XPCS2_BANK 0xE6444BFCUL + +uint32 eth_serdes_base_addr[ETH_SERDES_CH_NUM] = { + ETH_SERDES_XPCS0_BASE, + ETH_SERDES_XPCS1_BASE, + ETH_SERDES_XPCS2_BASE +}; + +uint32 eth_serdes_bank_addr[ETH_SERDES_CH_NUM] = { + ETH_SERDES_XPCS0_BANK, + ETH_SERDES_XPCS1_BANK, + ETH_SERDES_XPCS2_BANK +}; + +typedef enum { + ETH_MAC_LAYER_SPEED_10M = 0, + ETH_MAC_LAYER_SPEED_100M, + ETH_MAC_LAYER_SPEED_1G, + ETH_MAC_LAYER_SPEED_2500M, + ETH_MAC_LAYER_SPEED_10G +} eth_serdes_speed_t; + +#define ETH_SERDES_BPS ETH_MAC_LAYER_SPEED_1G + +#define ETH_SERDES_SEL_BANK(ch, value) \ + {*(volatile uint32*)eth_serdes_bank_addr[ch] = (uint32)value;} +#define ETH_SERDES_REG_WRITE(ch, offset, value) \ + {*(volatile uint32*)(eth_serdes_base_addr[ch] + (uint16)offset) = (uint32)value;} +#define ETH_SERDES_REG_READ(ch, offset) \ + (*(volatile uint32*)(eth_serdes_base_addr[ch] + (uint16)offset)) + +void eth_disable_fuse_ovr(void) +{ + /* Disable Fuse_override_en */ + uint32 address; + volatile uint32 val; + + address = 0xE6446600; + val = *((volatile uint32*)address); + *((volatile uint32*)address) = 0x00000000U; + val = *((volatile uint32*)address); + (void) val; +} + +static int eth_serdes_wait_for_update(uint32 ch, uint16 offset, uint32 mask, + uint32 exp_val, uint32 timeout) +{ + uint32 start_time; + uint32 reg_val; + + start_time = get_time(); + + do { + reg_val = ETH_SERDES_REG_READ(ch, offset); + if ((reg_val & mask) == exp_val) { + return 0; + } + } while (get_elapsed_time(start_time) < timeout); + + return ERR_TIMEOUT; +} + +static int eth_serdes_wait_reset(void) +{ + int ch, ret; + + for (ch = 0; ch < ETH_SERDES_CH_NUM; ch++) { + ETH_SERDES_SEL_BANK(ch, 0x0180U); + ret = eth_serdes_wait_for_update(ch, 0x026C, BIT(0), BIT(0), ETH_TIMEOUT_COUNT); + if (ret != 0) { + break; + } + } + return ret; +} + +static int eth_serdes_initialize_SRAM(void) +{ + int ch, ret; + + ret = eth_serdes_wait_reset(); + if (ret != 0) { + return ret; + } + + ETH_SERDES_SEL_BANK(ETH_SERDES_XPCS_CH0, 0x0180); + ETH_SERDES_REG_WRITE(ETH_SERDES_XPCS_CH0, 0x026C, 0x3); + + for (ch = ETH_SERDES_XPCS_CH0; ch < ETH_SERDES_CH_NUM; ch++) { + ETH_SERDES_SEL_BANK(ch, 0x0300U); + ret = eth_serdes_wait_for_update(ch, 0x0000U, BIT(15), 0UL, ETH_TIMEOUT_COUNT); + if (ret != 0) { + break; + } + } + + return ret; +} + +static void eth_serdes_set_SGMII_common_settings(void) +{ + /* Steps S.4.1 to S.4.5 */ + ETH_SERDES_SEL_BANK(ETH_SERDES_XPCS_CH0, 0x0180); + ETH_SERDES_REG_WRITE(ETH_SERDES_XPCS_CH0, 0x0244, 0x97); + ETH_SERDES_REG_WRITE(ETH_SERDES_XPCS_CH0, 0x01D0, 0x60); + ETH_SERDES_REG_WRITE(ETH_SERDES_XPCS_CH0, 0x01D8, 0x2200); + ETH_SERDES_REG_WRITE(ETH_SERDES_XPCS_CH0, 0x01D4, 0x0); + ETH_SERDES_REG_WRITE(ETH_SERDES_XPCS_CH0, 0x01E0, 0x3D); +} + +static int eth_serdes_PHY_soft_reset(void) +{ + int ret; + + /* Step:5 */ + ETH_SERDES_SEL_BANK(ETH_SERDES_XPCS_CH0, 0x0380); + ETH_SERDES_REG_WRITE(ETH_SERDES_XPCS_CH0, 0x0000, 0x8000); + + /* Step:6 */ + ret = eth_serdes_wait_reset(); + if (ret != 0) { + return ret; + } + + /* Step:7 */ + ETH_SERDES_SEL_BANK(ETH_SERDES_XPCS_CH0, 0x0180U); + ETH_SERDES_REG_WRITE(ETH_SERDES_XPCS_CH0, 0x026CU, 0x00000003UL); + + /* Step:8 */ + ETH_SERDES_SEL_BANK(ETH_SERDES_XPCS_CH0, 0x0380U); + ret = eth_serdes_wait_for_update(ETH_SERDES_XPCS_CH0, 0x0000U, BIT(15), 0UL, ETH_TIMEOUT_COUNT); + + return ret; +} + +static int eth_serdes_channel_SGMII_common_configuration(uint32 ch) +{ + int ret; + + /* Steps S/SA.9.1 to S/SA.9.14 */ + ETH_SERDES_SEL_BANK(ch, 0x0380); + ETH_SERDES_REG_WRITE(ch, 0x0000, 0x2000); + ETH_SERDES_SEL_BANK(ch, 0x0180); + ETH_SERDES_REG_WRITE(ch, 0x01C0, 0x11); + ETH_SERDES_REG_WRITE(ch, 0x0248, 0x540); + ETH_SERDES_REG_WRITE(ch, 0x0258, 0x15); + ETH_SERDES_REG_WRITE(ch, 0x0144, 0x100); + ETH_SERDES_REG_WRITE(ch, 0x01A0, 0x0); + ETH_SERDES_REG_WRITE(ch, 0x00D0, 0x2); + ETH_SERDES_REG_WRITE(ch, 0x0150, 0x3); + ETH_SERDES_REG_WRITE(ch, 0x00C8, 0x100); + ETH_SERDES_REG_WRITE(ch, 0x0148, 0x100); + ETH_SERDES_REG_WRITE(ch, 0x0174, 0x0); + ETH_SERDES_REG_WRITE(ch, 0x0160, 0x7); + ETH_SERDES_REG_WRITE(ch, 0x01AC, 0x0); + ETH_SERDES_REG_WRITE(ch, 0x00C4, 0x310); + + /* Step: S/SA.9.15 */ + ETH_SERDES_REG_WRITE(ch, 0x00C8, 0x101); + + /* Step: S/SA.9.16 */ + ret = eth_serdes_wait_for_update(ch, 0x00C8, BIT(0), 0x0, ETH_TIMEOUT_COUNT); + if (ret != 0) { + return ret; + } + + /* Step: S/SA.9.17 */ + ETH_SERDES_REG_WRITE(ch, 0x0148, 0x101); + + /* Step: S/SA.9.18 */ + ret = eth_serdes_wait_for_update(ch, 0x0148, BIT(0), 0x0, ETH_TIMEOUT_COUNT); + if (ret != 0) { + return ret; + } + + /* Steps S/SA.9.19 to S/SA.9.24 */ + ETH_SERDES_REG_WRITE(ch, 0x00C4, 0x1310); + ETH_SERDES_REG_WRITE(ch, 0x00D8, 0x1800); + ETH_SERDES_REG_WRITE(ch, 0x00DC, 0x0); + + ETH_SERDES_SEL_BANK(ch, 0x0300); + ETH_SERDES_REG_WRITE(ch, 0x001C, 0x1); + ETH_SERDES_SEL_BANK(ch, 0x0380); + ETH_SERDES_REG_WRITE(ch, 0x0000, 0x2100); + + ret = eth_serdes_wait_for_update(ch, 0x0000, BIT(8), 0x0, ETH_TIMEOUT_COUNT); + + return ret; +} + +#if defined(ETH_SERDES_AN_ENABLED) +static void eth_serdes_channel_SGMII_enable_AN(uint32 ch, eth_serdes_speed_t LenSpeed) +{ + /* Step: SA.9.25 */ + ETH_SERDES_SEL_BANK(ch, 0x1F00); + if (ETH_MAC_LAYER_SPEED_1G == ch) { + /* select when 1Gbps */ + ETH_SERDES_REG_WRITE(ch, 0x0000, 0x140); + } else { + /* select when 100Mbps */ + ETH_SERDES_REG_WRITE(ch, 0x0000, 0x2100); + } + + /* Steps SA.9.26 to SA.9.28 */ + ETH_SERDES_SEL_BANK(ch, 0x1F80); + ETH_SERDES_REG_WRITE(ch, 0x0004, 0x005); + ETH_SERDES_REG_WRITE(ch, 0x0028, 0x7A1); + ETH_SERDES_REG_WRITE(ch, 0x0000, 0x208); +} +#endif + +#if defined(ETH_SERDES_AN_ENABLED) +static int eth_serdes_channel_set_bps_SGMII_ANON(uint32 ch, eth_serdes_speed_t LenSpeed) +{ + int ret; + + /* Step: SA.10.1 */ + ETH_SERDES_SEL_BANK(ch, 0x1F00); + + /* Mode Selection Method is provisional */ + if (ETH_MAC_LAYER_SPEED_1G == LenSpeed) { + /* select 1Gbps */ + ETH_SERDES_REG_WRITE(ch, 0x0000, 0x1140); + } else { + /* select 100Mbps */ + ETH_SERDES_REG_WRITE(ch, 0x0000, 0x3100); + } + + /* Step: SA.10.2 */ + ETH_SERDES_SEL_BANK(ch, 0x1F80); + ret = eth_serdes_wait_for_update(ch, 0x0008, BIT(0), BIT(0), ETH_TIMEOUT_COUNT); + if (ret != 0) { + return ret; + } + + ETH_SERDES_REG_WRITE(ch, 0x0008, 0x0); + + return ret; +} +#endif + +static void eth_serdes_channel_set_bps_SGMII_ANOFF(uint32 ch, eth_serdes_speed_t LenSpeed) +{ + /* Step:S.10.1 */ + ETH_SERDES_SEL_BANK(ch, 0x1F00); + + /* Mode Selection Method is provisional */ + if (ETH_MAC_LAYER_SPEED_1G == LenSpeed) { + /* select 1Gbps */ + ETH_SERDES_REG_WRITE(ch, 0x0000, 0x140); + } else { + /* select 100Mbps */ + ETH_SERDES_REG_WRITE(ch, 0x0000, 0x2100); + } +} + +/* Following User's Manual at section 100.6.3 */ +int eth_serdes_initialize(void) +{ + int ret, ch; + + /* Step 1: Initialize SRAM */ + ret = eth_serdes_initialize_SRAM(); + if (ret != 0) { + return ret; + } + + /* Step 2 */ + for (ch = ETH_SERDES_XPCS_CH0; ch < ETH_SERDES_CH_NUM; ch++) { + ETH_SERDES_SEL_BANK(ch, 0x0380); + ETH_SERDES_REG_WRITE(ch, 0x03D4, 0x443); + } + + /* Step 3 */ + eth_serdes_set_SGMII_common_settings(); + + /* Step 4 */ + for (ch = ETH_SERDES_XPCS_CH0; ch < ETH_SERDES_CH_NUM; ch++) { + ETH_SERDES_SEL_BANK(ch, 0x0380); + ETH_SERDES_REG_WRITE(ch, 0X03D0, 0x1); + } + + /* Steps 5 to 8 */ + ret = eth_serdes_PHY_soft_reset(); + if (ret != 0) { + return ret; + } + + /* Step 9 */ + for (ch = ETH_SERDES_XPCS_CH0; ch < ETH_SERDES_CH_NUM; ch++) { + /* Steps S/SA.9.1 to S/SA.9.24 */ + ret = eth_serdes_channel_SGMII_common_configuration(ch); + if (ret != 0) { + return ret; + } +#if defined(ETH_SERDES_AN_ENABLED) + /* Steps SA.9.25 to SA.9.28 */ + eth_serdes_channel_SGMII_enable_AN(ch, ETH_SERDES_BPS); +#endif + } + + /* Step 10: */ + for (ch = ETH_SERDES_XPCS_CH0; ch < ETH_SERDES_CH_NUM; ch++) { +#if defined(ETH_SERDES_AN_ENABLED) + /* Steps SA.10.1 to SA.10.3 */ + ret = eth_serdes_channel_set_bps_SGMII_ANON(ch, ETH_SERDES_BPS); + if (ret != 0) { + return ret; + } +#else + /* Step: S.10.1 */ + eth_serdes_channel_set_bps_SGMII_ANOFF(ch, ETH_SERDES_BPS); +#endif + } + + /* Step 11 */ + for (ch = ETH_SERDES_XPCS_CH0; ch < ETH_SERDES_CH_NUM; ch++) { + ETH_SERDES_SEL_BANK(ch, 0x0380); + ETH_SERDES_REG_WRITE(ch, 0x03C0, 0x0); + } + + /* Step 12 */ + for (ch = ETH_SERDES_XPCS_CH0; ch < ETH_SERDES_CH_NUM; ch++) { + ETH_SERDES_SEL_BANK(ch, 0x0380); + ETH_SERDES_REG_WRITE(ch, 0x03D0, 0x0); + } + + return 0; +} diff --git a/libraries/drivers/ethernet/renesas/eth_serdes.h b/libraries/drivers/ethernet/renesas/eth_serdes.h new file mode 100644 index 000000000..e75a08785 --- /dev/null +++ b/libraries/drivers/ethernet/renesas/eth_serdes.h @@ -0,0 +1,7 @@ +#ifndef _ETH_SERDES_H_ +#define _ETH_SERDES_H_ + +void eth_disable_fuse_ovr(void); +int eth_serdes_initialize(void); + +#endif /* _ETH_SERDES_H_ */ \ No newline at end of file diff --git a/libraries/drivers/ethernet/renesas/pfcmap.h b/libraries/drivers/ethernet/renesas/pfcmap.h new file mode 100644 index 000000000..f0b063f36 --- /dev/null +++ b/libraries/drivers/ethernet/renesas/pfcmap.h @@ -0,0 +1,60 @@ +#ifndef PFCMAP_H +#define PFCMAP_H + +/* PFC base */ +#define PFC_GP0_BASE (0xE6050000UL) +#define PFC_GP4_BASE (0xDFD90000UL) + +static const unsigned int PRTGRP_OFFSET[] = +{ + 0x0000U, /* PRTGRP0 */ + 0x0000U, /* PRTGRP1 */ + 0x0800U, /* PRTGRP2 */ + 0x0800U, /* PRTGRP3 */ + 0x0000U, /* PRTGRP4 */ + 0x0800U, /* PRTGRP5 */ + 0x0000U, /* PRTGRP6 */ + 0x0800U, /* PRTGRP7 */ + 0x1000U, /* PRTGRP8 */ + 0x1800U, /* PRTGRP9 */ + 0x0000U, /* PRTGRP10 */ +}; + +#define PFC_GPSR_BmPlTt_OFFSET(m, l, t) (0x0040U + PFC_GROUPS_OFFSET(m, l, t)) + +/* PFC[0] = m=0~3, l=1, t=0~2 */ +/* PFC[1] = m=0~3, l=0, t=0~2 */ +/* PFC[2] = m=0~3, l=4,5, t=0~2 */ +/* PFC[3] = m=0~3, l=6~9, t=0~2 */ + +#define PFC_IPnSR_BmPlTt_OFFSET(n, m, l, t) (0x0060U + (0x0004U * n) + PFC_GROUPS_OFFSET(m, l, t)) + +/* PFC[0] = m=0~3, l=1, t=0~2 */ +/* PFC[1] = m=0~3, l=0, t=0~2 */ +/* PFC[2] = m=0~3, l=4,5, t=0~2 */ +/* PFC[3] = m=0~3, l=6~9, t=0~2 */ + +#define PFC_POC_BmPlTt_OFFSET(m, l, t) (0x00A0U + PFC_GROUPS_OFFSET(m, l, t)) + +/* PFC[0] = m=0~3, l=1, t=0~2 */ +/* PFC[1] = m=0~3, l=0, t=0~2 */ +/* PFC[2] = m=0~3, l=4,5, t=0~2 */ +/* PFC[3] = m=0~3, l=6~9, t=0~2 */ + +#define PFC_DRVnCTRL_BmPlTt_OFFSET(n, m, l, t) (0x0080U + (0x0004U * n) + PFC_GROUPS_OFFSET(m, l, t)) + +#define PFC_GROUPS_OFFSET(m, l, t) (((m) * 0x2000U) + PRTGRP_OFFSET[l] + ((t) * 0x0200U)) +/* R/W 32 LSI Multiplexed Pin Setting Mask Register */ +#define PFC_PMMR(addr) ((addr & 0xFFFFF800U) + 0x0000UL) + +#define PFC_PORTGP_OFFSET (0x800U) +#define PFC_GPn_BASE(n) (((n < 4)? PFC_GP0_BASE : PFC_GP4_BASE) + (PFC_PORTGP_OFFSET * (n % 4))) + +#define PFC_GPSR_GPn_DM0(n) (PFC_GPn_BASE(n) + PFC_GPSR_BmPlTt_OFFSET(0,0,0)) +#define PFC_IPSRm_GPn_DM0(m, n) (PFC_GPn_BASE(n) + PFC_IPnSR_BmPlTt_OFFSET(m,0,0,0)) +/* R/W 32 POC control register0 PortGroup 3 */ +#define PFC_POC_GPn_DM0(n) (PFC_GPn_BASE(n) + PFC_POC_BmPlTt_OFFSET(0,0,0)) +/* R/W 32 POC control register0 PortGroup 3 */ +#define PFC_DRVCTRLm_GPn_DM0(m, n) (PFC_GPn_BASE(n) + PFC_DRVnCTRL_BmPlTt_OFFSET(m,0,0,0)) + +#endif /* PFCMAP_H */ diff --git a/libraries/drivers/ethernet/renesas/rswitch.c b/libraries/drivers/ethernet/renesas/rswitch.c new file mode 100644 index 000000000..d8be1aec2 --- /dev/null +++ b/libraries/drivers/ethernet/renesas/rswitch.c @@ -0,0 +1,1081 @@ +#include "tpl_os.h" +#include "utils.h" +#include "rswitch.h" +#include "rswitch_regs.h" +#include "err_codes.h" +#include + +#define PORT_TSNA_N 3 +#define PORT_GWCA_N 2 +#define TOT_PORT_NUM (PORT_TSNA_N + PORT_GWCA_N) + +#define RSWITCH_GWCA_IDX_TO_HW_NUM(i) ((i) + PORT_TSNA_N) +#define RSWITCH_HW_NUM_TO_GWCA_IDX(i) ((i) - PORT_TSNA_N) + +#define TSNA0_PORT_NUM 0 +#define TSNA1_PORT_NUM 1 +#define TSNA2_PORT_NUM 2 +#define GWCA0_PORT_NUM 3 +#define GWCA1_PORT_NUM 4 + +#define TSN_PORT_IN_USE TSNA0_PORT_NUM +#define GWCA_PORT_IN_USE (GWCA1_PORT_NUM - PORT_TSNA_N) + +/* GWCA */ +enum rswitch_gwca_mode { + GWMC_OPC_RESET, + GWMC_OPC_DISABLE, + GWMC_OPC_CONFIG, + GWMC_OPC_OPERATION, +}; +#define GWMS_OPS_MASK GWMC_OPC_OPERATION +#define GWVCC_VEM_SC_TAG (0x3 << 16) +#define GWMTIRM_MTIOG BIT(0) +#define GWMTIRM_MTR BIT(1) +#define GWARIRM_ARIOG BIT(0) +#define GWARIRM_ARR BIT(1) + +#define GWDCC_BALR BIT(24) +#define GWDCC_DCP(q, idx) ((q + (idx * 2)) << 16) +#define GWDCC_DQT BIT(11) +#define GWDCC_ETS BIT(9) +#define GWDCC_EDE BIT(8) +#define GWDCC_OFFS(chain) (GWDCC0 + (chain) * 4) + +enum DIE_DT { + /* Frame data */ + DT_FSINGLE = 0x80, + DT_FSTART = 0x90, + DT_FMID = 0xA0, + DT_FEND = 0xB8, + + /* Chain control */ + DT_LEMPTY = 0xC0, + DT_EEMPTY = 0xD0, + DT_LINKFIX = 0x00, + DT_LINK = 0xE0, + DT_EOS = 0xF0, + /* HW/SW arbitration */ + DT_FEMPTY = 0x40, + DT_FEMPTY_IS = 0x10, + DT_FEMPTY_IC = 0x20, + DT_FEMPTY_ND = 0x38, + DT_FEMPTY_START = 0x50, + DT_FEMPTY_MID = 0x60, + DT_FEMPTY_END = 0x70, + + DT_MASK = 0xF0, + DIE = 0x08, /* Descriptor Interrupt Enable */ +}; + +struct rswitch_desc { + uint16 info_ds; /* Descriptor size */ + uint8 die_dt; /* Descriptor interrupt enable and type */ + uint8 dptrh; /* Descriptor pointer MSB */ + uint32 dptrl; /* Descriptor pointer LSW */ +} __attribute__((packed)); + +struct rswitch_ts_desc { + uint16 info_ds; /* Descriptor size */ + uint8 die_dt; /* Descriptor interrupt enable and type */ + uint8 dptrh; /* Descriptor pointer MSB */ + uint32 dptrl; /* Descriptor pointer LSW */ + uint32 ts_nsec; + uint32 ts_sec; +} __attribute__((packed)); + +struct rswitch_ext_desc { + uint16 info_ds; /* Descriptor size */ + uint8 die_dt; /* Descriptor interrupt enable and type */ + uint8 dptrh; /* Descriptor pointer MSB */ + uint32 dptrl; /* Descriptor pointer LSW */ + uint64 info1; +} __attribute__((packed)); + +struct rswitch_ext_ts_desc { + uint16 info_ds; /* Descriptor size */ + uint8 die_dt; /* Descriptor interrupt enable and type */ + uint8 dptrh; /* Descriptor pointer MSB */ + uint32 dptrl; /* Descriptor pointer LSW */ + uint64 info1; + uint32 ts_nsec; + uint32 ts_sec; +} __attribute__((packed)); + +#define NUM_DEVICES 3 +#define NUM_CHAINS_PER_NDEV 2 + +#define RSWITCH_MAX_NUM_CHAINS 128 +#define RSWITCH_NUM_IRQ_REGS (RSWITCH_MAX_NUM_CHAINS / BITS_PER_TYPE(uint32)) + +#define MAC_ADDRESS_LEN 6 +struct rswitch_etha { + uint8 port_num; + uint32 base_addr; + uint8 mac_addr[MAC_ADDRESS_LEN]; + int speed; +} etha_props[PORT_TSNA_N] = +{ + { .port_num = TSNA0_PORT_NUM, .base_addr = RSWITCH_ETHA0_ADDR }, + { .port_num = TSNA1_PORT_NUM, .base_addr = RSWITCH_ETHA1_ADDR }, + { .port_num = TSNA2_PORT_NUM, .base_addr = RSWITCH_ETHA2_ADDR }, +}; + +enum rswitch_etha_mode { + EAMC_OPC_RESET, + EAMC_OPC_DISABLE, + EAMC_OPC_CONFIG, + EAMC_OPC_OPERATION, +}; +#define EAMS_OPS_MASK EAMC_OPC_OPERATION +#define EAVCC_VEM_SC_TAG (0x3 << 16) + +#define MPIC_PIS_MII 0x00 +#define MPIC_PIS_GMII 0x02 +#define MPIC_PIS_XGMII 0x04 +#define MPIC_LSC_SHIFT 3 +#define MPIC_LSC_10M (0 << MPIC_LSC_SHIFT) +#define MPIC_LSC_100M (1 << MPIC_LSC_SHIFT) +#define MPIC_LSC_1G (2 << MPIC_LSC_SHIFT) +#define MPIC_LSC_2_5G (3 << MPIC_LSC_SHIFT) +#define MPIC_LSC_5G (4 << MPIC_LSC_SHIFT) +#define MPIC_LSC_10G (5 << MPIC_LSC_SHIFT) +#define MPIC_PSMCS_SHIFT 16 +#define MPIC_PSMCS_MASK GENMASK(22, MPIC_PSMCS_SHIFT) +#define MPIC_PSMCS(val) ((val) << MPIC_PSMCS_SHIFT) +#define MPIC_PSMHT_SHIFT 24 +#define MPIC_PSMHT_MASK GENMASK(26, MPIC_PSMHT_SHIFT) +#define MPIC_PSMHT(val) ((val) << MPIC_PSMHT_SHIFT) +#define MPSM_MFF_C45 BIT(2) +#define MLVC_PLV BIT(16) +#define MDIO_READ_C45 0x03 +#define MDIO_WRITE_C45 0x01 +#define MII_ADDR_C45 (1<<30) +#define MII_DEVADDR_C45_SHIFT 16 +#define MII_REGADDR_C45_MASK GENMASK(15, 0) +#define MMIS1_PAACS BIT(2) /* Address */ +#define MMIS1_PWACS BIT(1) /* Write */ +#define MMIS1_PRACS BIT(0) /* Read */ +#define MMIS1_CLEAR_FLAGS 0xf +#define MPSM_PSME BIT(0) +#define MPSM_MFF_C45 BIT(2) +#define MPSM_PDA_SHIFT 3 +#define MPSM_PDA_MASK GENMASK(7, MPSM_PDA_SHIFT) +#define MPSM_PDA(val) ((val) << MPSM_PDA_SHIFT) +#define MPSM_PRA_SHIFT 8 +#define MPSM_PRA_MASK GENMASK(12, MPSM_PRA_SHIFT) +#define MPSM_PRA(val) ((val) << MPSM_PRA_SHIFT) +#define MPSM_POP_SHIFT 13 +#define MPSM_POP_MASK GENMASK(14, MPSM_POP_SHIFT) +#define MPSM_POP(val) ((val) << MPSM_POP_SHIFT) +#define MPSM_PRD_SHIFT 16 +#define MPSM_PRD_MASK GENMASK(31, MPSM_PRD_SHIFT) +#define MPSM_PRD_WRITE(val) ((val) << MPSM_PRD_SHIFT) +#define MPSM_PRD_READ(val) ((val) & MPSM_PRD_MASK >> MPSM_PRD_SHIFT) + +#define TX_RX_RING_SIZE 32 +#define PKT_BUF_SZ 1584 +#define PKT_BUF_SZ_ALIGN 1792 /* 0x700 to keep elements aligned to the value + specified by RSWITCH_ALIGN */ +#define RSWITCH_ALIGN 1 /* kenel uses 128, so 7 bits (=log_2(128)) are enough + * to represent this value, so we round up to 1 byte. */ + +/* These elements should either be rswitch_ext_desc or rswitch_ext_ts_desc + * depending if gptp is used or not. */ +struct rswitch_ext_ts_desc rx_ring[TX_RX_RING_SIZE]; +struct rswitch_ext_desc tx_ring[TX_RX_RING_SIZE]; + +uint8 rx_data_buff[TX_RX_RING_SIZE][PKT_BUF_SZ_ALIGN] __attribute__((aligned(RSWITCH_ALIGN))); +uint8 tx_data_buff[TX_RX_RING_SIZE][PKT_BUF_SZ_ALIGN] __attribute__((aligned(RSWITCH_ALIGN))); + +struct rswitch_gwca_chain { + uint8 chain_index; + uint8 dir_tx; + // bool gptp; + union { + struct rswitch_ext_desc *ring; + struct rswitch_ext_ts_desc *ts_ring; + }; + uint32 num_ring; + uint32 next_index; // next descriptor (as index) to be processed + uint8 *data_buffers[TX_RX_RING_SIZE]; + uint8 irq_triggered; +}; + +struct rswitch_gwca { + uint8 port_num; + uint32 base_addr; + struct rswitch_gwca_chain rx_chain; + struct rswitch_gwca_chain tx_chain; + int speed; +} gwca_props[PORT_GWCA_N] = { + { .port_num = GWCA0_PORT_NUM, .base_addr = RSWITCH_GWCA0_ADDR }, + { .port_num = GWCA1_PORT_NUM, .base_addr = RSWITCH_GWCA1_ADDR }, +}; + +struct rswitch_device { + struct rswitch_desc base_descriptors[NUM_CHAINS_PER_NDEV]; + struct rswitch_etha *etha; + struct rswitch_gwca *gwca; + uint32 fwd_base_addr; + uint32 coma_base_addr; +} rsw_dev = { + .fwd_base_addr = RSWITCH_FWD_ADDR, + .coma_base_addr = RSWITCH_COMA_ADDR, + .etha = ða_props[TSN_PORT_IN_USE], + .gwca = &gwca_props[GWCA_PORT_IN_USE], +}; + +/* MFWD */ +#define FWPC0_LTHTA BIT(0) +#define FWPC0_IP4UE BIT(3) +#define FWPC0_IP4TE BIT(4) +#define FWPC0_IP4OE BIT(5) +#define FWPC0_L2SE BIT(9) +#define FWPC0_IP4EA BIT(10) +#define FWPC0_IPDSA BIT(12) +#define FWPC0_IPHLA BIT(18) +#define FWPC0_MACSDA BIT(20) +#define FWPC0_MACHLA BIT(26) +#define FWPC0_MACHMA BIT(27) +#define FWPC0_VLANSA BIT(28) + +#define FWPC0(i) (FWPC00 + (i) * 0x10) +#define FWPC1(i) (FWPC10 + (i) * 0x10) +#define FWPC0_DEFAULT (FWPC0_LTHTA | FWPC0_IP4UE | FWPC0_IP4TE | \ + FWPC0_IP4OE | FWPC0_L2SE | FWPC0_IP4EA | \ + FWPC0_IPDSA | FWPC0_IPHLA | FWPC0_MACSDA | \ + FWPC0_MACHLA | FWPC0_MACHMA | FWPC0_VLANSA) +#define FWPC1_DDE BIT(0) +#define FWPBFC(i) (FWPBFCi + (i) * 0x10) +#define FWPBFCSDC(j, i) (FWPBFCSDC00 + (i) * 0x10 + (j) * 0x04) + +/* Interrupts */ +#define GWCA0_RX_TX_IRQ 312 +#define GWCA1_RX_TX_IRQ 320 +#define GWCA0_RX_TS_IRQ 328 +#define GWCA1_RX_TS_IRQ 330 +#define COMA_ERR_IRQ 290 +#define GWCA0_ERR_IRQ 291 +#define GWCA1_ERR_IRQ 292 +#define ETHA0_ERR_IRQ 293 +#define ETHA1_ERR_IRQ 294 +#define ETHA2_ERR_IRQ 295 + +/* GWCA data interrupt status */ +#define GWDIS0i_OFFSET(index) (GWDIS0 + (index/32) * 0x10) +#define GWDIS0i_BIT(index) (BIT(index % 32)) + +/* Well, this shouldn't be here as it should be included from "tpl_os.h", but + * that doesn't work, so we will redeclare it here... */ +extern FUNC(void, OS_CODE) CallTerminateISR2(void); + +/* This is the callback function that is invoked every time some data is received */ +rx_callback_fn rx_cb = NULL; + +#define RSWITCH_TIMEOUT_MS 10000 +static int rswitch_reg_wait(uint32 addr, uint32 mask, uint32 expected) +{ + int i; + + for (i = 0; i < RSWITCH_TIMEOUT_MS; i++) { + if ((reg_read32(addr) & mask) == expected) + return 0; + + ms_delay(1); + } + + return ERR_TIMEOUT; +} + +static void rswitch_modify(uint32 addr, uint32 clear, uint32 set) +{ + uint32 val = reg_read32(addr) & ~clear; + reg_write32(val | set, addr); +} + +static int rswitch_mii_set_access(struct rswitch_etha *etha, uint8 read, + uint32 phyad, uint32 devad, uint32 regad, + uint16 *data) +{ + int pop = read ? MDIO_READ_C45 : MDIO_WRITE_C45; + uint32 val; + int ret; + + /* Clear completion flags */ + reg_write32(MMIS1_CLEAR_FLAGS, etha->base_addr + MMIS1); + + /* Submit address to PHY (MDIO_ADDR_C45 << 13) */ + val = MPSM_PSME | MPSM_MFF_C45; + reg_write32((regad << 16) | (devad << 8) | (phyad << 3) | val, + etha->base_addr + MPSM); + + CHECK_RET(rswitch_reg_wait(etha->base_addr + MMIS1, MMIS1_PAACS, MMIS1_PAACS)); + + /* Clear address completion flag */ + rswitch_modify(etha->base_addr + MMIS1, MMIS1_PAACS, MMIS1_PAACS); + + /* Read/Write PHY register */ + if (read) { + reg_write32((pop << 13) | (devad << 8) | (phyad << 3) | val, + etha->base_addr + MPSM); + + CHECK_RET(rswitch_reg_wait(etha->base_addr + MMIS1, MMIS1_PRACS, MMIS1_PRACS)); + + /* Read data */ + ret = (reg_read32(etha->base_addr + MPSM) & MPSM_PRD_MASK) >> 16; + *data = ret; + + /* Clear read completion flag */ + rswitch_modify(etha->base_addr + MMIS1, MMIS1_PRACS, MMIS1_PRACS); + } else { + reg_write32((*data << 16) | (pop << 13) | (devad << 8) | (phyad << 3) | val, + etha->base_addr + MPSM); + + ret = rswitch_reg_wait(etha->base_addr + MMIS1, MMIS1_PWACS, MMIS1_PWACS); + } + + return 0; +} + +static int rswitch_mii_read(struct rswitch_etha *etha, uint32 phyaddr, + uint32 devad, uint32 regad, uint32 *data) +{ + uint16 tmp; + int ret; + ret = rswitch_mii_set_access(etha, TRUE, phyaddr, devad, regad, &tmp); + *data = tmp; + + return ret; +} + +static int rswitch_mii_write(struct rswitch_etha *etha, uint32 phyaddr, + uint32 devad, uint32 regad, uint32 *data) +{ + uint16 tmp = (uint16) *data; + return rswitch_mii_set_access(etha, FALSE, phyaddr, devad, regad, &tmp); +} + +static int rswitch_agent_clock_is_enabled(int port) +{ + uint32 val = reg_read32(rsw_dev.coma_base_addr + RCEC); + + if (val & RCEC_RCE) + return (val & BIT(port)) ? TRUE : FALSE; + else + return FALSE; +} + +static void rswitch_agent_clock_ctrl(int port, int enable) +{ + uint32 val; + + if (enable) { + val = reg_read32(rsw_dev.coma_base_addr + RCEC); + reg_write32(val | RCEC_RCE | BIT(port), + rsw_dev.coma_base_addr + RCEC); + } else { + val = reg_read32(rsw_dev.coma_base_addr + RCDC); + reg_write32(val | BIT(port), rsw_dev.coma_base_addr + RCDC); + } +} + +/* mac is supposed to be an array of 6 bytes */ +static void __unused rswitch_etha_read_mac_address(struct rswitch_etha *eth_dev) +{ + uint32 mrmac0 = reg_read32(eth_dev->base_addr + MRMAC0); + uint32 mrmac1 = reg_read32(eth_dev->base_addr + MRMAC1); + + eth_dev->mac_addr[0] = (mrmac0 >> 8) & 0xFF; + eth_dev->mac_addr[1] = (mrmac0 >> 0) & 0xFF; + eth_dev->mac_addr[2] = (mrmac1 >> 24) & 0xFF; + eth_dev->mac_addr[3] = (mrmac1 >> 16) & 0xFF; + eth_dev->mac_addr[4] = (mrmac1 >> 8) & 0xFF; + eth_dev->mac_addr[5] = (mrmac1 >> 0) & 0xFF; +} + +/* This function sets only data in the global strucure, not on the hardware */ +static void rswitch_etha_set_mac_address(struct rswitch_etha *eth_dev) +{ + int i; + uint32 tmp = 0; + + // Values from MCAL + static const uint8 predefined_mac_address[PORT_TSNA_N][6] = { + {0x74U, 0x90U, 0x50U, 0x00U, 0x00U, 0x00U}, + {0x74U, 0x90U, 0x50U, 0x00U, 0x00U, 0x01U}, + {0x74U, 0x90U, 0x50U, 0x00U, 0x00U, 0x02U}, + }; + + /* The following works only because TSN port's numbers starts from 0 as + * if they were indexes. */ + for (i = 0; i < MAC_ADDRESS_LEN; i++) { + eth_dev->mac_addr[i] = predefined_mac_address[eth_dev->port_num][i]; + } + + tmp = (eth_dev->mac_addr[0] << 8) + (eth_dev->mac_addr[1]); + reg_write32(tmp, eth_dev->base_addr + MRMAC0); + tmp = (eth_dev->mac_addr[2] << 24) + (eth_dev->mac_addr[3] << 16) + + (eth_dev->mac_addr[4] << 8) + (eth_dev->mac_addr[5]); + reg_write32(tmp, eth_dev->base_addr + MRMAC1); +} + +static void rswitch_soft_reset(void) +{ + reg_write32(RRC_RR, rsw_dev.coma_base_addr + RRC); + reg_write32(RRC_RR_CLR, rsw_dev.coma_base_addr + RRC); + + /* Clock initialization and module reset have already been done before + * in utils.c */ +} + +static int rswitch_gwca_change_mode(struct rswitch_gwca *gwca, + enum rswitch_gwca_mode mode) +{ + int ret; + + /* Enable clock */ + if (!rswitch_agent_clock_is_enabled(gwca->port_num)) + rswitch_agent_clock_ctrl(gwca->port_num, 1); + + reg_write32(mode, gwca->base_addr + GWMC); + + ret = rswitch_reg_wait(gwca->base_addr + GWMS, GWMS_OPS_MASK, mode); + + /* Disable clock */ + if (mode == GWMC_OPC_DISABLE) + rswitch_agent_clock_ctrl(gwca->port_num, 0); + + return ret; +} + +static int rswitch_gwca_mcast_table_reset(struct rswitch_gwca *gwca) +{ + reg_write32(GWMTIRM_MTIOG, gwca->base_addr + GWMTIRM); + return rswitch_reg_wait(gwca->base_addr + GWMTIRM, GWMTIRM_MTR, GWMTIRM_MTR); +} + +static int rswitch_gwca_axi_ram_reset(struct rswitch_gwca *gwca) +{ + reg_write32(GWARIRM_ARIOG, gwca->base_addr + GWARIRM); + return rswitch_reg_wait(gwca->base_addr + GWARIRM, GWARIRM_ARR, GWARIRM_ARR); +} + +static void rswitch_gwca_set_rate_limit(struct rswitch_gwca *gwca) +{ + uint32 gwgrlulc, gwgrlc; + + switch (gwca->speed) { + case 1000: + gwgrlulc = 0x0000005f; + gwgrlc = 0x00010260; + break; + default: + debug_msg("%s: This rate is not supported (%d)\n", __func__, gwca->speed); + return; + } + + reg_write32(gwgrlulc, gwca->base_addr + GWGRLULC); + reg_write32(gwgrlc, gwca->base_addr + GWGRLC); +} + +static int rswitch_gwca_hw_init(struct rswitch_device *rswitch) +{ + int ret, i; + uint32 descriptors_addr = (uint32) rswitch->base_descriptors; + struct rswitch_gwca *gwca = rswitch->gwca; + + for (i = 0; i < NUM_CHAINS_PER_NDEV; i++) { + rswitch->base_descriptors[i].die_dt = DT_EOS; + } + + CHECK_RET(rswitch_gwca_change_mode(gwca, GWMC_OPC_DISABLE)); + CHECK_RET(rswitch_gwca_change_mode(gwca, GWMC_OPC_CONFIG)); + CHECK_RET(rswitch_gwca_mcast_table_reset(gwca)); + CHECK_RET(rswitch_gwca_axi_ram_reset(gwca)); + + /* Full setting flow */ + reg_write32(GWVCC_VEM_SC_TAG, gwca->base_addr + GWVCC); + reg_write32(0, gwca->base_addr + GWTTFC); + reg_write32(descriptors_addr, gwca->base_addr + GWDCBAC1); + reg_write32(0x00, gwca->base_addr + GWDCBAC0); + + gwca->speed = 1000; + rswitch_gwca_set_rate_limit(gwca); + + CHECK_RET(rswitch_gwca_change_mode(gwca, GWMC_OPC_DISABLE)); + CHECK_RET(rswitch_gwca_change_mode(gwca, GWMC_OPC_OPERATION)); + + return 0; +} + +static void rswitch_gwca_chain_format(struct rswitch_device *rswitch, + struct rswitch_gwca_chain *c) +{ + struct rswitch_ext_desc *ring; + struct rswitch_desc *base_desc; + int ring_size = sizeof(*ring) * c->num_ring; + int i; + + memset(c->ring, 0, ring_size); + for (i = 0, ring = c->ring; i < c->num_ring - 1; i++, ring++) { + if (!c->dir_tx) { + ring->info_ds = PKT_BUF_SZ; + ring->dptrl = (uint32) c->data_buffers[i]; + ring->dptrh = 0x00; + ring->die_dt = DT_FEMPTY | DIE; + } else { + ring->info_ds = 0; + ring->dptrl = (uint32) c->data_buffers[i]; + ring->dptrh = 0x00; + ring->die_dt = DT_EEMPTY | DIE; + } + } + + /* Close the loop */ + ring->dptrl = (uint32) c->ring; + ring->dptrh = 0x00; + ring->die_dt = DT_LINKFIX; + + /* Configure the base descriptor */ + base_desc = &rswitch->base_descriptors[c->chain_index]; + base_desc->die_dt = DT_LINKFIX; + base_desc->dptrl = (uint32) c->ring; + base_desc->dptrh = 0x00; + + /* FIXME: GWDCC_DCP */ + reg_write32(GWDCC_BALR | (c->dir_tx ? GWDCC_DQT : 0) | GWDCC_EDE, + rswitch->gwca->base_addr + GWDCC_OFFS(c->chain_index)); +} + +static void rswitch_gwca_chain_ts_format(struct rswitch_device *rswitch, + struct rswitch_gwca_chain *c) +{ + struct rswitch_ext_ts_desc *ring; + struct rswitch_desc *base_desc; + int ring_size = sizeof(*ring) * c->num_ring; + int i; + + memset(c->ring, 0, ring_size); + for (i = 0, ring = c->ts_ring; i < c->num_ring - 1; i++, ring++) { + if (!c->dir_tx) { + ring->info_ds = PKT_BUF_SZ; + ring->dptrl = (uint32) c->data_buffers[i]; + ring->dptrh = 0x00; + ring->die_dt = DT_FEMPTY | DIE; + } else { + ring->info_ds = 0; + ring->dptrl = (uint32) c->data_buffers[i]; + ring->dptrh = 0x00; + ring->die_dt = DT_EEMPTY | DIE; + } + } + + /* Close the loop */ + ring->dptrl = (uint32) c->ts_ring; + ring->dptrh = 0x00; + ring->die_dt = DT_LINKFIX; + + /* Configure the base descriptor */ + base_desc = &rswitch->base_descriptors[c->chain_index]; + base_desc->die_dt = DT_LINKFIX; + base_desc->dptrl = (uint32) c->ts_ring; + base_desc->dptrh = 0x00; + + /* FIXME: GWDCC_DCP */ + reg_write32(GWDCC_BALR | (c->dir_tx ? GWDCC_DQT : 0) | GWDCC_ETS | GWDCC_EDE, + rswitch->gwca->base_addr + GWDCC_OFFS(c->chain_index)); +} + +static int rswitch_bpool_config(struct rswitch_device *rswitch) +{ + uint32 val; + + val = reg_read32(rswitch->coma_base_addr + CABPIRM); + if (val & CABPIRM_BPR) + return 0; + + reg_write32(CABPIRM_BPIOG, rswitch->coma_base_addr + CABPIRM); + return rswitch_reg_wait(rswitch->coma_base_addr + CABPIRM, CABPIRM_BPR, CABPIRM_BPR); +} + +static void rswitch_fwd_init(struct rswitch_device *rswitch) +{ + int eth_port_num = rswitch->etha->port_num; + int gwca_port_num = rswitch->gwca->port_num; + int gwca_idx = RSWITCH_HW_NUM_TO_GWCA_IDX(gwca_port_num); + + /* Set RX chain as destination for port based forwarding from the selected + * ethernet port. */ + reg_write32(rswitch->gwca->rx_chain.chain_index, + rswitch->fwd_base_addr + FWPBFCSDC(gwca_idx, eth_port_num)); + /* Static routing ETHA --> GWCA. */ + reg_write32(BIT(rswitch->gwca->port_num), + rswitch->fwd_base_addr + FWPBFC(eth_port_num)); + /* Static routing GWCA --> ETHA. */ + reg_write32(0, rswitch->fwd_base_addr + FWPBFC(gwca_port_num)); + reg_write32(BIT(eth_port_num), rswitch->fwd_base_addr + FWPBFC(gwca_port_num)); +} + +static __unused void rswitch_get_data_irq_status(struct rswitch_device *rswitch, uint32 *dis) +{ + int i; + + for (i = 0; i < RSWITCH_NUM_IRQ_REGS; i++) { + dis[i] = reg_read32(rswitch->gwca->base_addr + GWDIS0 + i * 0x10); + } +} + +static void rswitch_enadis_data_irq(struct rswitch_gwca *gwca, int index, + int enable) +{ + uint32 offs = (enable ? GWDIE0 : GWDID0) + (index / 32) * 0x10; + uint32 tmp = 0; + + /* For VPF? */ + if (enable) + tmp = reg_read32(gwca->base_addr + offs); + + reg_write32(BIT(index % 32) | tmp, gwca->base_addr + offs); +} + +static void rswitch_enable_irqs(void) +{ + /* Enables IRQs on the core side */ + enable_int(GWCA1_RX_TX_IRQ); + enable_int(GWCA1_RX_TS_IRQ); + enable_int(GWCA1_ERR_IRQ); + enable_int(ETHA0_ERR_IRQ); + enable_int(COMA_ERR_IRQ); +} + +int rswitch_init(void) +{ + int i, ret; + + memset(rx_data_buff, 0, sizeof(rx_data_buff)); + memset(tx_data_buff, 0, sizeof(tx_data_buff)); + + // Enable clocks to all the agents + for (i = 0; i < TOT_PORT_NUM; i++) { + rswitch_agent_clock_ctrl(i, 1); + } + + rswitch_soft_reset(); + + CHECK_RET(rswitch_gwca_hw_init(&rsw_dev)); + + /* Copy speed property from GWCA */ + rsw_dev.etha->speed = rsw_dev.gwca->speed; + + rsw_dev.gwca->rx_chain.chain_index = 0; + rsw_dev.gwca->rx_chain.ts_ring = rx_ring; + for (i = 0; i < TX_RX_RING_SIZE; i++) { + rsw_dev.gwca->rx_chain.data_buffers[i] = rx_data_buff[i]; + } + rsw_dev.gwca->rx_chain.num_ring = TX_RX_RING_SIZE; + rsw_dev.gwca->rx_chain.dir_tx = 0; + rswitch_gwca_chain_ts_format(&rsw_dev, &(rsw_dev.gwca->rx_chain)); + + rsw_dev.gwca->tx_chain.chain_index = 1; + rsw_dev.gwca->tx_chain.ring = tx_ring; + for (i = 0; i < TX_RX_RING_SIZE; i++) { + rsw_dev.gwca->tx_chain.data_buffers[i] = tx_data_buff[i]; + } + rsw_dev.gwca->tx_chain.num_ring = TX_RX_RING_SIZE; + rsw_dev.gwca->tx_chain.dir_tx = 1; + rswitch_gwca_chain_format(&rsw_dev, &(rsw_dev.gwca->tx_chain)); + + CHECK_RET(rswitch_bpool_config(&rsw_dev)); + + rswitch_fwd_init(&rsw_dev); + + rswitch_enable_irqs(); + + return 0; +} + +static int rswitch_etha_change_mode(struct rswitch_etha *etha, + enum rswitch_etha_mode mode) +{ + int ret; + + /* Enable clock */ + if (!rswitch_agent_clock_is_enabled(etha->port_num)) + rswitch_agent_clock_ctrl(etha->port_num, 1); + + reg_write32(mode, etha->base_addr + EAMC); + + ret = rswitch_reg_wait(etha->base_addr + EAMS, EAMS_OPS_MASK, mode); + + /* Disable clock */ + if (mode == EAMC_OPC_DISABLE) + rswitch_agent_clock_ctrl(etha->port_num, 0); + + return ret; +} + +static void rswitch_rmac_setting(struct rswitch_etha *etha) +{ + uint32 val; + + switch (etha->speed) { + case 10: + val = MPIC_LSC_10M; + break; + case 100: + val = MPIC_LSC_100M; + break; + case 1000: + val = MPIC_LSC_1G; + break; + default: + return; + } + + reg_write32(MPIC_PIS_GMII | val, etha->base_addr + MPIC); +} + +static void rswitch_etha_enable_mii(struct rswitch_etha *etha) +{ + rswitch_modify(etha->base_addr + MPIC, MPIC_PSMCS_MASK | MPIC_PSMHT_MASK, + MPIC_PSMCS(0x05) | MPIC_PSMHT(0x06)); + rswitch_modify(etha->base_addr + MPSM, 0, MPSM_MFF_C45); +} + +static uint8 rswitch_etha_wait_link_verification(struct rswitch_etha *etha) +{ + /* Request Link Verification */ + reg_write32(MLVC_PLV, etha->base_addr + MLVC); + return rswitch_reg_wait(etha->base_addr + MLVC, MLVC_PLV, 0); +} + +static int rswitch_etha_hw_init(struct rswitch_etha *etha) +{ + int ret; + + /* Change to CONFIG Mode */ + CHECK_RET(rswitch_etha_change_mode(etha, EAMC_OPC_DISABLE)); + CHECK_RET(rswitch_etha_change_mode(etha, EAMC_OPC_CONFIG)); + + rswitch_etha_set_mac_address(etha); + + reg_write32(EAVCC_VEM_SC_TAG, etha->base_addr + EAVCC); + + rswitch_rmac_setting(etha); + rswitch_etha_enable_mii(etha); + + /* Change to OPERATION Mode */ + CHECK_RET(rswitch_etha_change_mode(etha, EAMC_OPC_OPERATION)); + + /* Link Verification */ + return rswitch_etha_wait_link_verification(etha); +} + +static int rswitch_phy_init(struct rswitch_etha *etha) +{ + uint32 reg_data; + int ret; + + /* Reset */ + CHECK_RET(rswitch_mii_read(etha, 1, etha->port_num + 1, 0xC04A, ®_data)); + reg_data |= BIT(15); + CHECK_RET(rswitch_mii_write(etha, 1, etha->port_num + 1, 0xC04A, ®_data)); + CHECK_RET(rswitch_mii_write(etha, 1, etha->port_num + 1, 0xC04A, ®_data)); /* MCAL does it twice... */ + + /* Check mode */ + CHECK_RET(rswitch_mii_read(etha, 1, etha->port_num + 1, 0xC04A, ®_data)); + if ((reg_data & 0x7) != 0x4 ) { /* 4 stands for SGMII */ + reg_data &= ~0x7; + reg_data |= BIT(15) | 0x4; + CHECK_RET(rswitch_mii_write(etha, 1, etha->port_num + 1, 0xC04A, ®_data)); + + /* Run SERDES Init */ + CHECK_RET(rswitch_mii_read(etha, 1, etha->port_num + 1, 0x800F, ®_data)); + reg_data |= BIT(15) | BIT(13); + CHECK_RET(rswitch_mii_write(etha, 1, etha->port_num + 1, 0x800F, ®_data)); + + reg_data = 0x0U; + do { + CHECK_RET(rswitch_mii_read(etha, 1, etha->port_num + 1, 0x800F, ®_data)); + } while (reg_data & BIT(15)); + + /* Auto SERDES Init Disable */ + reg_data &= ~BIT(13); + CHECK_RET(rswitch_mii_write(etha, 1, etha->port_num + 1, 0x800F, ®_data)); + } + + return 0; +} + +int rswitch_open(void) +{ + int ret; + + CHECK_RET(rswitch_etha_hw_init(rsw_dev.etha)); + CHECK_RET(rswitch_phy_init(rsw_dev.etha)); + + /* Enable RX */ + rswitch_modify(rsw_dev.gwca->base_addr + GWTRC0, 0, + BIT(rsw_dev.gwca->rx_chain.chain_index)); + + /* Enable interrupt */ + rswitch_enadis_data_irq(rsw_dev.gwca, rsw_dev.gwca->tx_chain.chain_index, + TRUE); + rswitch_enadis_data_irq(rsw_dev.gwca, rsw_dev.gwca->rx_chain.chain_index, + TRUE); + + return 0; +} + +int rswitch_send_data(uint8 *buf, uint16 size) +{ + struct rswitch_gwca_chain *chain = &rsw_dev.gwca->tx_chain; + struct rswitch_ext_desc *desc; + uint8 *dest_buf; + + /* Temporary code: try to fit into a single packet. This can be extended + * in the future but it requires code to handle data splitting. */ + if (size > PKT_BUF_SZ) { + debug_msg("Error: transmitted buffer is too large"); + return ERR_BUFF_TOO_LARGE; + } + + /* Pick the 1st not used descriptor that can be used for transmission */ + desc = &chain->ring[chain->next_index]; + /* Check that this descriptor is REALLY free */ + if (desc->die_dt != (DT_EEMPTY | DIE)) { + debug_msg("Error: invalid descriptor selected for transmission"); + return ERR_TX_FAILURE; + } + /* Prepare the descriptor */ + desc->die_dt = DT_FSINGLE | DIE; + desc->info_ds = size & 0xFFF; + /* Copy data to be transmitted */ + dest_buf = (uint8 *) desc->dptrl; + memcpy(dest_buf, buf, size); + + /* Start transmission */ + rswitch_modify(rsw_dev.gwca->base_addr + GWTRC0, 0, BIT(chain->chain_index)); + + /* Move to the next item in the list. */ + chain->next_index++; + /* The last item is a LINKFIX and we know that, so we wrap back + * to the 1st item earlier. */ + if (chain->next_index >= chain->num_ring - 1) { + chain->next_index = 0; + } + + return 0; +} + +void rswitch_regiter_data_received_callback(rx_callback_fn func) +{ + rx_cb = func; +} + +/* Determine which chain (rx or tx) generated the interrupt */ +static void rswitch_get_interrupt_source_and_clear() +{ + struct rswitch_gwca_chain *chain; + uint32 chain_index; + uint32 reg_val; + + /* Check if the IRQ was triggered by the RX chain */ + chain = &rsw_dev.gwca->rx_chain; + chain_index = chain->chain_index; + reg_val = reg_read32(rsw_dev.gwca->base_addr + GWDIS0i_OFFSET(chain_index)); + if (reg_val & GWDIS0i_BIT(chain_index)) { + chain->irq_triggered = 1; + reg_write32(GWDIS0i_BIT(chain_index), rsw_dev.gwca->base_addr + + GWDIS0i_OFFSET(chain_index)); + } + + /* Check if the IRQ was triggered by the TX chain */ + chain_index = rsw_dev.gwca->tx_chain.chain_index; + reg_val = reg_read32(rsw_dev.gwca->base_addr + GWDIS0i_OFFSET(chain_index)); + if (reg_val & GWDIS0i_BIT(chain_index)) { + rsw_dev.gwca->tx_chain.irq_triggered = 1; + reg_write32(GWDIS0i_BIT(chain_index), rsw_dev.gwca->base_addr + + GWDIS0i_OFFSET(chain_index)); + } +} + +/*****************************************************************************/ +/*****************************************************************************/ + +#define APP_ISR_gwca1_rx_tx_int_START_SEC_CODE +#include "tpl_memmap.h" +static int nb_int = 0; + +ISR(gwca1_rx_tx_int) +{ + nb_int++; + ActivateTask(gwca1_rx_tx_task); + CallTerminateISR2(); +} + +TASK(gwca1_rx_tx_task) { + struct rswitch_gwca_chain *chain; + struct rswitch_ext_ts_desc *ts_desc; + struct rswitch_ext_desc *desc; + uint8 *data_ptr; + uint16 data_len; + int i; + + // debug_msg("%s", __func__); + while(1) { + chain = &rsw_dev.gwca->rx_chain; + if (chain->irq_triggered != 0) { + /* Go through the descriptors chain to parse received data */ + while (1) { + ts_desc = &(chain->ts_ring[chain->next_index]); + /* Stop once we get to a descriptor that was not modified */ + if (ts_desc->die_dt == (DT_FEMPTY | DIE)) { + break; + } + /* We know that "dptrh" is always 0x0 so we ignore it intentionally */ + data_ptr = (uint8 *) ts_desc->dptrl; + data_len = (ts_desc->info_ds) & 0xFFF; + /* If the callback is present then call it, otherwise just print + * the data */ + if (rx_cb != NULL) { + rx_cb(data_ptr, data_len); + } else { + debug_print_buffer(data_ptr, data_len); + } + /* Reset the data buffer */ + memset(data_ptr, 0, PKT_BUF_SZ_ALIGN); + /* Reset the descriptor so that it can be used again in the next round */ + memset(ts_desc, 0, sizeof(*ts_desc)); + ts_desc->die_dt = (DT_FEMPTY | DIE); + ts_desc->info_ds = PKT_BUF_SZ; + ts_desc->dptrl = (uint32) data_ptr; + /* Move to the next item in the list. */ + chain->next_index++; + /* The last item is a LINKFIX and we know that, so we wrap back + * to the 1st item earlier. */ + if (chain->next_index >= chain->num_ring - 1) { + chain->next_index = 0; + } + } + /* Remove the flag for the received data. + * Note = this is not the best technique because another IRQ might + * be triggered in the meanwhile (is it possible?) so we might + * miss it. Might be improved if problems appear... */ + chain->irq_triggered = 0; + } + + chain = &rsw_dev.gwca->tx_chain; + if (chain->irq_triggered) { + /* Here we reset all the descriptors and data buffers of the TX chain. + * It works only if 1 descriptor is transmitted at a time. + * TODO: improve to handle transmissions of multiple descriptors. */ + for (i = 0; i < chain->num_ring - 1; i++) { + desc = &(chain->ring[i]); + desc->die_dt = DT_EEMPTY | DIE; + desc->info_ds = 0; + desc->info1 = 0; + data_ptr = (uint8 *) desc->dptrl; + memset(data_ptr, 0, PKT_BUF_SZ_ALIGN); + } + chain->irq_triggered = 0; + } + + DisableAllInterrupts(); + nb_int--; + if (nb_int==0) break; + EnableAllInterrupts(); + } + + TerminateTask(); +} + +FUNC(void, OS_CODE) GWCA1_RX_TX_INT_ClearFlag(void) +{ + //debug_msg("%s", __func__); + rswitch_get_interrupt_source_and_clear(); +} + +#define APP_ISR_gwca1_rx_tx_int_STOP_SEC_CODE +#include "tpl_memmap.h" + +/*****************************************************************************/ +/*****************************************************************************/ + +#define APP_ISR_gwca1_rx_ts_int_START_SEC_CODE +#include "tpl_memmap.h" + +ISR(gwca1_rx_ts_int) +{ + debug_msg("%s", __func__); + CallTerminateISR2(); +} + +FUNC(void, OS_CODE) GWCA1_RX_TS_INT_ClearFlag(void) +{ + debug_msg("%s", __func__); +} + +#define APP_ISR_gwca1_rx_ts_int_STOP_SEC_CODE +#include "tpl_memmap.h" + +/*****************************************************************************/ +/*****************************************************************************/ + +#define APP_ISR_coma_err_int_START_SEC_CODE +#include "tpl_memmap.h" + +ISR(coma_err_int) +{ + debug_msg("%s", __func__); + CallTerminateISR2(); +} + +FUNC(void, OS_CODE) COMA_ERR_INT_ClearFlag(void) +{ + debug_msg("%s", __func__); +} + +#define APP_ISR_coma_err_int_STOP_SEC_CODE +#include "tpl_memmap.h" + +/*****************************************************************************/ +/*****************************************************************************/ + +#define APP_ISR_gwca1_err_int_START_SEC_CODE +#include "tpl_memmap.h" + +ISR(gwca1_err_int) +{ + debug_msg("%s", __func__); + CallTerminateISR2(); +} + +FUNC(void, OS_CODE) GWCA1_ERR_INT_ClearFlag(void) +{ + debug_msg("%s", __func__); +} + +#define APP_ISR_gwca1_err_int_STOP_SEC_CODE +#include "tpl_memmap.h" + +/*****************************************************************************/ +/*****************************************************************************/ + +#define APP_ISR_etha0_err_int_START_SEC_CODE +#include "tpl_memmap.h" + +ISR(etha0_err_int) +{ + debug_msg("%s", __func__); + CallTerminateISR2(); +} + +FUNC(void, OS_CODE) ETHA0_ERR_INT_ClearFlag(void) +{ + debug_msg("%s", __func__); +} + +#define APP_ISR_etha0_err_int_STOP_SEC_CODE +#include "tpl_memmap.h" diff --git a/libraries/drivers/ethernet/renesas/rswitch.h b/libraries/drivers/ethernet/renesas/rswitch.h new file mode 100644 index 000000000..520f6e9af --- /dev/null +++ b/libraries/drivers/ethernet/renesas/rswitch.h @@ -0,0 +1,12 @@ +#ifndef _ETH_H_ +#define _ETH_H_ + +int rswitch_init(void); +int rswitch_open(void); + +typedef void (*rx_callback_fn)(uint8 *buf, uint16 len); + +void rswitch_regiter_data_received_callback(rx_callback_fn func); +int rswitch_send_data(uint8 *buf, uint16 size); + +#endif /* _ETH_H_ */ \ No newline at end of file diff --git a/libraries/drivers/ethernet/renesas/rswitch_regs.h b/libraries/drivers/ethernet/renesas/rswitch_regs.h new file mode 100644 index 000000000..d740438ce --- /dev/null +++ b/libraries/drivers/ethernet/renesas/rswitch_regs.h @@ -0,0 +1,659 @@ +#ifndef RSWITCH_REGS_H +#define RSWITCH_REGS_H + +#define RSWITCH_BASE 0xE68C0000 + +#define RSWITCH_FWD_ADDR (RSWITCH_BASE + 0x00000000) +#define RSWITCH_FAB_ADDR (RSWITCH_BASE + 0x00008000) +#define RSWITCH_COMA_ADDR (RSWITCH_BASE + 0x00009000) +#define RSWITCH_ETHA0_ADDR (RSWITCH_BASE + 0x0000a000) +#define RSWITCH_ETHA1_ADDR (RSWITCH_BASE + 0x0000c000) +#define RSWITCH_ETHA2_ADDR (RSWITCH_BASE + 0x0000e000) +#define RSWITCH_GWCA0_ADDR (RSWITCH_BASE + 0x00010000) +#define RSWITCH_GWCA1_ADDR (RSWITCH_BASE + 0x00012000) +#define RSWITCH_GPTP_ADDR (RSWITCH_BASE + 0x00018000) + +#define FWRO 0 +#define CARO 0 +#define GWRO 0 +#define TARO 0 +#define RMRO 0x1000 + +#define FWGC (FWRO + 0x0000) +#define FWTTC0 (FWRO + 0x0010) +#define FWTTC1 (FWRO + 0x0014) +#define FWLBMC (FWRO + 0x0018) +#define FWCEPTC (FWRO + 0x020) +#define FWCEPRC0 (FWRO + 0x024) +#define FWCEPRC1 (FWRO + 0x028) +#define FWCEPRC2 (FWRO + 0x02C) +#define FWCLPTC (FWRO + 0x030) +#define FWCLPRC (FWRO + 0x034) +#define FWCMPTC (FWRO + 0x040) +#define FWEMPTC (FWRO + 0x044) +#define FWSDMPTC (FWRO + 0x050) +#define FWSDMPVC (FWRO + 0x054) +#define FWLBWMC0 (FWRO + 0x080) +#define FWPC00 (FWRO + 0x100) +#define FWPC10 (FWRO + 0x104) +#define FWPC20 (FWRO + 0x108) +#define FWCTGC00 (FWRO + 0x400) +#define FWCTGC10 (FWRO + 0x404) +#define FWCTTC00 (FWRO + 0x408) +#define FWCTTC10 (FWRO + 0x40C) +#define FWCTTC200 (FWRO + 0x410) +#define FWCTSC00 (FWRO + 0x420) +#define FWCTSC10 (FWRO + 0x424) +#define FWCTSC20 (FWRO + 0x428) +#define FWCTSC30 (FWRO + 0x42C) +#define FWCTSC40 (FWRO + 0x430) +#define FWTWBFC0 (FWRO + 0x1000) +#define FWTWBFVC0 (FWRO + 0x1004) +#define FWTHBFC0 (FWRO + 0x1400) +#define FWTHBFV0C0 (FWRO + 0x1404) +#define FWTHBFV1C0 (FWRO + 0x1408) +#define FWFOBFC0 (FWRO + 0x1800) +#define FWFOBFV0C0 (FWRO + 0x1804) +#define FWFOBFV1C0 (FWRO + 0x1808) +#define FWRFC0 (FWRO + 0x1C00) +#define FWRFVC0 (FWRO + 0x1C04) +#define FWCFC0 (FWRO + 0x2000) +#define FWCFMC00 (FWRO + 0x2004) +#define FWIP4SC (FWRO + 0x4008) +#define FWIP6SC (FWRO + 0x4018) +#define FWIP6OC (FWRO + 0x401C) +#define FWL2SC (FWRO + 0x4020) +#define FWSFHEC (FWRO + 0x4030) +#define FWSHCR0 (FWRO + 0x4040) +#define FWSHCR1 (FWRO + 0x4044) +#define FWSHCR2 (FWRO + 0x4048) +#define FWSHCR3 (FWRO + 0x404C) +#define FWSHCR4 (FWRO + 0x4050) +#define FWSHCR5 (FWRO + 0x4054) +#define FWSHCR6 (FWRO + 0x4058) +#define FWSHCR7 (FWRO + 0x405C) +#define FWSHCR8 (FWRO + 0x4060) +#define FWSHCR9 (FWRO + 0x4064) +#define FWSHCR10 (FWRO + 0x4068) +#define FWSHCR11 (FWRO + 0x406C) +#define FWSHCR12 (FWRO + 0x4070) +#define FWSHCR13 (FWRO + 0x4074) +#define FWSHCRR (FWRO + 0x4078) +#define FWLTHHEC (FWRO + 0x4090) +#define FWLTHHC (FWRO + 0x4094) +#define FWLTHTL0 (FWRO + 0x40A0) +#define FWLTHTL1 (FWRO + 0x40A4) +#define FWLTHTL2 (FWRO + 0x40A8) +#define FWLTHTL3 (FWRO + 0x40AC) +#define FWLTHTL4 (FWRO + 0x40B0) +#define FWLTHTL5 (FWRO + 0x40B4) +#define FWLTHTL6 (FWRO + 0x40B8) +#define FWLTHTL7 (FWRO + 0x40BC) +#define FWLTHTL80 (FWRO + 0x40C0) +#define FWLTHTL9 (FWRO + 0x40D0) +#define FWLTHTLR (FWRO + 0x40D4) +#define FWLTHTIM (FWRO + 0x40E0) +#define FWLTHTEM (FWRO + 0x40E4) +#define FWLTHTS0 (FWRO + 0x4100) +#define FWLTHTS1 (FWRO + 0x4104) +#define FWLTHTS2 (FWRO + 0x4108) +#define FWLTHTS3 (FWRO + 0x410C) +#define FWLTHTS4 (FWRO + 0x4110) +#define FWLTHTSR0 (FWRO + 0x4120) +#define FWLTHTSR1 (FWRO + 0x4124) +#define FWLTHTSR2 (FWRO + 0x4128) +#define FWLTHTSR3 (FWRO + 0x412C) +#define FWLTHTSR40 (FWRO + 0x4130) +#define FWLTHTSR5 (FWRO + 0x4140) +#define FWLTHTR (FWRO + 0x4150) +#define FWLTHTRR0 (FWRO + 0x4154) +#define FWLTHTRR1 (FWRO + 0x4158) +#define FWLTHTRR2 (FWRO + 0x415C) +#define FWLTHTRR3 (FWRO + 0x4160) +#define FWLTHTRR4 (FWRO + 0x4164) +#define FWLTHTRR5 (FWRO + 0x4168) +#define FWLTHTRR6 (FWRO + 0x416C) +#define FWLTHTRR7 (FWRO + 0x4170) +#define FWLTHTRR8 (FWRO + 0x4174) +#define FWLTHTRR9 (FWRO + 0x4180) +#define FWLTHTRR10 (FWRO + 0x4190) +#define FWIPHEC (FWRO + 0x4214) +#define FWIPHC (FWRO + 0x4218) +#define FWIPTL0 (FWRO + 0x4220) +#define FWIPTL1 (FWRO + 0x4224) +#define FWIPTL2 (FWRO + 0x4228) +#define FWIPTL3 (FWRO + 0x422C) +#define FWIPTL4 (FWRO + 0x4230) +#define FWIPTL5 (FWRO + 0x4234) +#define FWIPTL6 (FWRO + 0x4238) +#define FWIPTL7 (FWRO + 0x4240) +#define FWIPTL8 (FWRO + 0x4250) +#define FWIPTLR (FWRO + 0x4254) +#define FWIPTIM (FWRO + 0x4260) +#define FWIPTEM (FWRO + 0x4264) +#define FWIPTS0 (FWRO + 0x4270) +#define FWIPTS1 (FWRO + 0x4274) +#define FWIPTS2 (FWRO + 0x4278) +#define FWIPTS3 (FWRO + 0x427C) +#define FWIPTS4 (FWRO + 0x4280) +#define FWIPTSR0 (FWRO + 0x4284) +#define FWIPTSR1 (FWRO + 0x4288) +#define FWIPTSR2 (FWRO + 0x428C) +#define FWIPTSR3 (FWRO + 0x4290) +#define FWIPTSR4 (FWRO + 0x42A0) +#define FWIPTR (FWRO + 0x42B0) +#define FWIPTRR0 (FWRO + 0x42B4) +#define FWIPTRR1 (FWRO + 0x42B8) +#define FWIPTRR2 (FWRO + 0x42BC) +#define FWIPTRR3 (FWRO + 0x42C0) +#define FWIPTRR4 (FWRO + 0x42C4) +#define FWIPTRR5 (FWRO + 0x42C8) +#define FWIPTRR6 (FWRO + 0x42CC) +#define FWIPTRR7 (FWRO + 0x42D0) +#define FWIPTRR8 (FWRO + 0x42E0) +#define FWIPTRR9 (FWRO + 0x42F0) +#define FWIPHLEC (FWRO + 0x4300) +#define FWIPAGUSPC (FWRO + 0x4500) +#define FWIPAGC (FWRO + 0x4504) +#define FWIPAGM0 (FWRO + 0x4510) +#define FWIPAGM1 (FWRO + 0x4514) +#define FWIPAGM2 (FWRO + 0x4518) +#define FWIPAGM3 (FWRO + 0x451C) +#define FWIPAGM4 (FWRO + 0x4520) +#define FWMACHEC (FWRO + 0x4620) +#define FWMACHC (FWRO + 0x4624) +#define FWMACTL0 (FWRO + 0x4630) +#define FWMACTL1 (FWRO + 0x4634) +#define FWMACTL2 (FWRO + 0x4638) +#define FWMACTL3 (FWRO + 0x463C) +#define FWMACTL4 (FWRO + 0x4640) +#define FWMACTL5 (FWRO + 0x4650) +#define FWMACTLR (FWRO + 0x4654) +#define FWMACTIM (FWRO + 0x4660) +#define FWMACTEM (FWRO + 0x4664) +#define FWMACTS0 (FWRO + 0x4670) +#define FWMACTS1 (FWRO + 0x4674) +#define FWMACTSR0 (FWRO + 0x4678) +#define FWMACTSR1 (FWRO + 0x467C) +#define FWMACTSR2 (FWRO + 0x4680) +#define FWMACTSR3 (FWRO + 0x4690) +#define FWMACTR (FWRO + 0x46A0) +#define FWMACTRR0 (FWRO + 0x46A4) +#define FWMACTRR1 (FWRO + 0x46A8) +#define FWMACTRR2 (FWRO + 0x46AC) +#define FWMACTRR3 (FWRO + 0x46B0) +#define FWMACTRR4 (FWRO + 0x46B4) +#define FWMACTRR5 (FWRO + 0x46C0) +#define FWMACTRR6 (FWRO + 0x46D0) +#define FWMACHLEC (FWRO + 0x4700) +#define FWMACAGUSPC (FWRO + 0x4880) +#define FWMACAGC (FWRO + 0x4884) +#define FWMACAGM0 (FWRO + 0x4888) +#define FWMACAGM1 (FWRO + 0x488C) +#define FWVLANTEC (FWRO + 0x4900) +#define FWVLANTL0 (FWRO + 0x4910) +#define FWVLANTL1 (FWRO + 0x4914) +#define FWVLANTL2 (FWRO + 0x4918) +#define FWVLANTL3 (FWRO + 0x4920) +#define FWVLANTL4 (FWRO + 0x4930) +#define FWVLANTLR (FWRO + 0x4934) +#define FWVLANTIM (FWRO + 0x4940) +#define FWVLANTEM (FWRO + 0x4944) +#define FWVLANTS (FWRO + 0x4950) +#define FWVLANTSR0 (FWRO + 0x4954) +#define FWVLANTSR1 (FWRO + 0x4958) +#define FWVLANTSR2 (FWRO + 0x4960) +#define FWVLANTSR3 (FWRO + 0x4970) +#define FWPBFCi (FWRO + 0x4A00) +#define FWPBFCSDC00 (FWRO + 0x4A04) +#define FWL23URL0 (FWRO + 0x4E00) +#define FWL23URL1 (FWRO + 0x4E04) +#define FWL23URL2 (FWRO + 0x4E08) +#define FWL23URL3 (FWRO + 0x4E0C) +#define FWL23URLR (FWRO + 0x4E10) +#define FWL23UTIM (FWRO + 0x4E20) +#define FWL23URR (FWRO + 0x4E30) +#define FWL23URRR0 (FWRO + 0x4E34) +#define FWL23URRR1 (FWRO + 0x4E38) +#define FWL23URRR2 (FWRO + 0x4E3C) +#define FWL23URRR3 (FWRO + 0x4E40) +#define FWL23URMC0 (FWRO + 0x4F00) +#define FWPMFGC0 (FWRO + 0x5000) +#define FWPGFC0 (FWRO + 0x5100) +#define FWPGFIGSC0 (FWRO + 0x5104) +#define FWPGFENC0 (FWRO + 0x5108) +#define FWPGFENM0 (FWRO + 0x510c) +#define FWPGFCSTC00 (FWRO + 0x5110) +#define FWPGFCSTC10 (FWRO + 0x5114) +#define FWPGFCSTM00 (FWRO + 0x5118) +#define FWPGFCSTM10 (FWRO + 0x511C) +#define FWPGFCTC0 (FWRO + 0x5120) +#define FWPGFCTM0 (FWRO + 0x5124) +#define FWPGFHCC0 (FWRO + 0x5128) +#define FWPGFSM0 (FWRO + 0x512C) +#define FWPGFGC0 (FWRO + 0x5130) +#define FWPGFGL0 (FWRO + 0x5500) +#define FWPGFGL1 (FWRO + 0x5504) +#define FWPGFGLR (FWRO + 0x5518) +#define FWPGFGR (FWRO + 0x5510) +#define FWPGFGRR0 (FWRO + 0x5514) +#define FWPGFGRR1 (FWRO + 0x5518) +#define FWPGFRIM (FWRO + 0x5520) +#define FWPMTRFC0 (FWRO + 0x5600) +#define FWPMTRCBSC0 (FWRO + 0x5604) +#define FWPMTRC0RC0 (FWRO + 0x5608) +#define FWPMTREBSC0 (FWRO + 0x560C) +#define FWPMTREIRC0 (FWRO + 0x5610) +#define FWPMTRFM0 (FWRO + 0x5614) +#define FWFTL0 (FWRO + 0x6000) +#define FWFTL1 (FWRO + 0x6004) +#define FWFTLR (FWRO + 0x6008) +#define FWFTOC (FWRO + 0x6010) +#define FWFTOPC (FWRO + 0x6014) +#define FWFTIM (FWRO + 0x6020) +#define FWFTR (FWRO + 0x6030) +#define FWFTRR0 (FWRO + 0x6034) +#define FWFTRR1 (FWRO + 0x6038) +#define FWFTRR2 (FWRO + 0x603C) +#define FWSEQNGC0 (FWRO + 0x6100) +#define FWSEQNGM0 (FWRO + 0x6104) +#define FWSEQNRC (FWRO + 0x6200) +#define FWCTFDCN0 (FWRO + 0x6300) +#define FWLTHFDCN0 (FWRO + 0x6304) +#define FWIPFDCN0 (FWRO + 0x6308) +#define FWLTWFDCN0 (FWRO + 0x630C) +#define FWPBFDCN0 (FWRO + 0x6310) +#define FWMHLCN0 (FWRO + 0x6314) +#define FWIHLCN0 (FWRO + 0x6318) +#define FWICRDCN0 (FWRO + 0x6500) +#define FWWMRDCN0 (FWRO + 0x6504) +#define FWCTRDCN0 (FWRO + 0x6508) +#define FWLTHRDCN0 (FWRO + 0x650C) +#define FWIPRDCN0 (FWRO + 0x6510) +#define FWLTWRDCN0 (FWRO + 0x6514) +#define FWPBRDCN0 (FWRO + 0x6518) +#define FWPMFDCN0 (FWRO + 0x6700) +#define FWPGFDCN0 (FWRO + 0x6780) +#define FWPMGDCN0 (FWRO + 0x6800) +#define FWPMYDCN0 (FWRO + 0x6804) +#define FWPMRDCN0 (FWRO + 0x6808) +#define FWFRPPCN0 (FWRO + 0x6A00) +#define FWFRDPCN0 (FWRO + 0x6A04) +#define FWEIS00 (FWRO + 0x7900) +#define FWEIE00 (FWRO + 0x7904) +#define FWEID00 (FWRO + 0x7908) +#define FWEIS1 (FWRO + 0x7A00) +#define FWEIE1 (FWRO + 0x7A04) +#define FWEID1 (FWRO + 0x7A08) +#define FWEIS2 (FWRO + 0x7A10) +#define FWEIE2 (FWRO + 0x7A14) +#define FWEID2 (FWRO + 0x7A18) +#define FWEIS3 (FWRO + 0x7A20) +#define FWEIE3 (FWRO + 0x7A24) +#define FWEID3 (FWRO + 0x7A28) +#define FWEIS4 (FWRO + 0x7A30) +#define FWEIE4 (FWRO + 0x7A34) +#define FWEID4 (FWRO + 0x7A38) +#define FWEIS5 (FWRO + 0x7A40) +#define FWEIE5 (FWRO + 0x7A44) +#define FWEID5 (FWRO + 0x7A48) +#define FWEIS60 (FWRO + 0x7A50) +#define FWEIE60 (FWRO + 0x7A54) +#define FWEID60 (FWRO + 0x7A58) +#define FWEIS61 (FWRO + 0x7A60) +#define FWEIE61 (FWRO + 0x7A64) +#define FWEID61 (FWRO + 0x7A68) +#define FWEIS62 (FWRO + 0x7A70) +#define FWEIE62 (FWRO + 0x7A74) +#define FWEID62 (FWRO + 0x7A78) +#define FWEIS63 (FWRO + 0x7A80) +#define FWEIE63 (FWRO + 0x7A84) +#define FWEID63 (FWRO + 0x7A88) +#define FWEIS70 (FWRO + 0x7A90) +#define FWEIE70 (FWRO + 0x7A94) +#define FWEID70 (FWRO + 0x7A98) +#define FWEIS71 (FWRO + 0x7AA0) +#define FWEIE71 (FWRO + 0x7AA4) +#define FWEID71 (FWRO + 0x7AA8) +#define FWEIS72 (FWRO + 0x7AB0) +#define FWEIE72 (FWRO + 0x7AB4) +#define FWEID72 (FWRO + 0x7AB8) +#define FWEIS73 (FWRO + 0x7AC0) +#define FWEIE73 (FWRO + 0x7AC4) +#define FWEID73 (FWRO + 0x7AC8) +#define FWEIS80 (FWRO + 0x7AD0) +#define FWEIE80 (FWRO + 0x7AD4) +#define FWEID80 (FWRO + 0x7AD8) +#define FWEIS81 (FWRO + 0x7AE0) +#define FWEIE81 (FWRO + 0x7AE4) +#define FWEID81 (FWRO + 0x7AE8) +#define FWEIS82 (FWRO + 0x7AF0) +#define FWEIE82 (FWRO + 0x7AF4) +#define FWEID82 (FWRO + 0x7AF8) +#define FWEIS83 (FWRO + 0x7B00) +#define FWEIE83 (FWRO + 0x7B04) +#define FWEID83 (FWRO + 0x7B08) +#define FWMIS0 (FWRO + 0x7C00) +#define FWMIE0 (FWRO + 0x7C04) +#define FWMID0 (FWRO + 0x7C08) +#define FWSCR0 (FWRO + 0x7D00) +#define FWSCR1 (FWRO + 0x7D04) +#define FWSCR2 (FWRO + 0x7D08) +#define FWSCR3 (FWRO + 0x7D0C) +#define FWSCR4 (FWRO + 0x7D10) +#define FWSCR5 (FWRO + 0x7D14) +#define FWSCR6 (FWRO + 0x7D18) +#define FWSCR7 (FWRO + 0x7D1C) +#define FWSCR8 (FWRO + 0x7D20) +#define FWSCR9 (FWRO + 0x7D24) +#define FWSCR10 (FWRO + 0x7D28) +#define FWSCR11 (FWRO + 0x7D2C) +#define FWSCR12 (FWRO + 0x7D30) +#define FWSCR13 (FWRO + 0x7D34) +#define FWSCR14 (FWRO + 0x7D38) +#define FWSCR15 (FWRO + 0x7D3C) +#define FWSCR16 (FWRO + 0x7D40) +#define FWSCR17 (FWRO + 0x7D44) +#define FWSCR18 (FWRO + 0x7D48) +#define FWSCR19 (FWRO + 0x7D4C) +#define FWSCR20 (FWRO + 0x7D50) +#define FWSCR21 (FWRO + 0x7D54) +#define FWSCR22 (FWRO + 0x7D58) +#define FWSCR23 (FWRO + 0x7D5C) +#define FWSCR24 (FWRO + 0x7D60) +#define FWSCR25 (FWRO + 0x7D64) +#define FWSCR26 (FWRO + 0x7D68) +#define FWSCR27 (FWRO + 0x7D6C) +#define FWSCR28 (FWRO + 0x7D70) +#define FWSCR29 (FWRO + 0x7D74) +#define FWSCR30 (FWRO + 0x7D78) +#define FWSCR31 (FWRO + 0x7D7C) +#define FWSCR32 (FWRO + 0x7D80) +#define FWSCR33 (FWRO + 0x7D84) +#define FWSCR34 (FWRO + 0x7D88) +#define FWSCR35 (FWRO + 0x7D8C) +#define FWSCR36 (FWRO + 0x7D90) +#define FWSCR37 (FWRO + 0x7D94) +#define FWSCR38 (FWRO + 0x7D98) +#define FWSCR39 (FWRO + 0x7D9C) +#define FWSCR40 (FWRO + 0x7DA0) +#define FWSCR41 (FWRO + 0x7DA4) +#define FWSCR42 (FWRO + 0x7DA8) +#define FWSCR43 (FWRO + 0x7DAC) +#define FWSCR44 (FWRO + 0x7DB0) +#define FWSCR45 (FWRO + 0x7DB4) +#define FWSCR46 (FWRO + 0x7DB8) + +#define RIPV (CARO + 0x0000) +#define RRC (CARO + 0x0004) +#define RCEC (CARO + 0x0008) +#define RCDC (CARO + 0x000C) +#define RSSIS (CARO + 0x0010) +#define RSSIE (CARO + 0x0014) +#define RSSID (CARO + 0x0018) +#define CABPIBWMC (CARO + 0x0020) +#define CABPWMLC (CARO + 0x0040) +#define CABPPFLC0 (CARO + 0x0050) +#define CABPPWMLC0 (CARO + 0x0060) +#define CABPPPFLC00 (CARO + 0x00A0) +#define CABPULC (CARO + 0x0100) +#define CABPIRM (CARO + 0x0140) +#define CABPPCM (CARO + 0x0144) +#define CABPLCM (CARO + 0x0148) +#define CABPCPM (CARO + 0x0180) +#define CABPMCPM (CARO + 0x0200) +#define CARDNM (CARO + 0x0280) +#define CARDMNM (CARO + 0x0284) +#define CARDCN (CARO + 0x0290) +#define CAEIS0 (CARO + 0x0300) +#define CAEIE0 (CARO + 0x0304) +#define CAEID0 (CARO + 0x0308) +#define CAEIS1 (CARO + 0x0310) +#define CAEIE1 (CARO + 0x0314) +#define CAEID1 (CARO + 0x0318) +#define CAMIS0 (CARO + 0x0340) +#define CAMIE0 (CARO + 0x0344) +#define CAMID0 (CARO + 0x0348) +#define CAMIS1 (CARO + 0x0350) +#define CAMIE1 (CARO + 0x0354) +#define CAMID1 (CARO + 0x0358) +#define CASCR (CARO + 0x0380) + +/* Ethernet Agent Address space Empty in spec */ +#define EAMC (TARO + 0x0000) +#define EAMS (TARO + 0x0004) +#define EAIRC (TARO + 0x0010) +#define EATDQSC (TARO + 0x0014) +#define EATDQC (TARO + 0x0018) +#define EATDQAC (TARO + 0x001C) +#define EATPEC (TARO + 0x0020) +#define EATMFSC0 (TARO + 0x0040) +#define EATDQDC0 (TARO + 0x0060) +#define EATDQM0 (TARO + 0x0080) +#define EATDQMLM0 (TARO + 0x00A0) +#define EACTQC (TARO + 0x0100) +#define EACTDQDC (TARO + 0x0104) +#define EACTDQM (TARO + 0x0108) +#define EACTDQMLM (TARO + 0x010C) +#define EAVCC (TARO + 0x0130) +#define EAVTC (TARO + 0x0134) +#define EATTFC (TARO + 0x0138) +#define EACAEC (TARO + 0x0200) +#define EACC (TARO + 0x0204) +#define EACAIVC0 (TARO + 0x0220) +#define EACAULC0 (TARO + 0x0240) +#define EACOEM (TARO + 0x0260) +#define EACOIVM0 (TARO + 0x0280) +#define EACOULM0 (TARO + 0x02A0) +#define EACGSM (TARO + 0x02C0) +#define EATASC (TARO + 0x0300) +#define EATASENC0 (TARO + 0x0320) +#define EATASCTENC (TARO + 0x0340) +#define EATASENM0 (TARO + 0x0360) +#define EATASCTENM (TARO + 0x0380) +#define EATASCSTC0 (TARO + 0x03A0) +#define EATASCSTC1 (TARO + 0x03A4) +#define EATASCSTM0 (TARO + 0x03A8) +#define EATASCSTM1 (TARO + 0x03AC) +#define EATASCTC (TARO + 0x03B0) +#define EATASCTM (TARO + 0x03B4) +#define EATASGL0 (TARO + 0x03C0) +#define EATASGL1 (TARO + 0x03C4) +#define EATASGLR (TARO + 0x03C8) +#define EATASGR (TARO + 0x03D0) +#define EATASGRR (TARO + 0x03D4) +#define EATASHCC (TARO + 0x03E0) +#define EATASRIRM (TARO + 0x03E4) +#define EATASSM (TARO + 0x03E8) +#define EAUSMFSECN (TARO + 0x0400) +#define EATFECN (TARO + 0x0404) +#define EAFSECN (TARO + 0x0408) +#define EADQOECN (TARO + 0x040C) +#define EADQSECN (TARO + 0x0410) +#define EACKSECN (TARO + 0x0414) +#define EAEIS0 (TARO + 0x0500) +#define EAEIE0 (TARO + 0x0504) +#define EAEID0 (TARO + 0x0508) +#define EAEIS1 (TARO + 0x0510) +#define EAEIE1 (TARO + 0x0514) +#define EAEID1 (TARO + 0x0518) +#define EAEIS2 (TARO + 0x0520) +#define EAEIE2 (TARO + 0x0524) +#define EAEID2 (TARO + 0x0528) +#define EASCR (TARO + 0x0580) + +#define MPSM (RMRO + 0x0000) +#define MPIC (RMRO + 0x0004) +#define MPIM (RMRO + 0x0008) +#define MIOC (RMRO + 0x0010) +#define MIOM (RMRO + 0x0014) +#define MXMS (RMRO + 0x0018) +#define MTFFC (RMRO + 0x0020) +#define MTPFC (RMRO + 0x0024) +#define MTPFC2 (RMRO + 0x0028) +#define MTPFC30 (RMRO + 0x0030) +#define MTATC0 (RMRO + 0x0050) +#define MTIM (RMRO + 0x0060) +#define MRGC (RMRO + 0x0080) +#define MRMAC0 (RMRO + 0x0084) +#define MRMAC1 (RMRO + 0x0088) +#define MRAFC (RMRO + 0x008C) +#define MRSCE (RMRO + 0x0090) +#define MRSCP (RMRO + 0x0094) +#define MRSCC (RMRO + 0x0098) +#define MRFSCE (RMRO + 0x009C) +#define MRFSCP (RMRO + 0x00a0) +#define MTRC (RMRO + 0x00a4) +#define MRIM (RMRO + 0x00a8) +#define MRPFM (RMRO + 0x00aC) +#define MPFC0 (RMRO + 0x0100) +#define MLVC (RMRO + 0x0180) +#define MEEEC (RMRO + 0x0184) +#define MLBC (RMRO + 0x0188) +#define MXGMIIC (RMRO + 0x0190) +#define MPCH (RMRO + 0x0194) +#define MANC (RMRO + 0x0198) +#define MANM (RMRO + 0x019C) +#define MPLCA1 (RMRO + 0x01a0) +#define MPLCA2 (RMRO + 0x01a4) +#define MPLCA3 (RMRO + 0x01a8) +#define MPLCA4 (RMRO + 0x01ac) +#define MPLCAM (RMRO + 0x01b0) +#define MHDC1 (RMRO + 0x01c0) +#define MHDC2 (RMRO + 0x01c4) +#define MEIS (RMRO + 0x0200) +#define MEIE (RMRO + 0x0204) +#define MEID (RMRO + 0x0208) +#define MMIS0 (RMRO + 0x0210) +#define MMIE0 (RMRO + 0x0214) +#define MMID0 (RMRO + 0x0218) +#define MMIS1 (RMRO + 0x0220) +#define MMIE1 (RMRO + 0x0224) +#define MMID1 (RMRO + 0x0228) +#define MMIS2 (RMRO + 0x0230) +#define MMIE2 (RMRO + 0x0234) +#define MMID2 (RMRO + 0x0238) +#define MMPFTCT (RMRO + 0x0300) +#define MAPFTCT (RMRO + 0x0304) +#define MPFRCT (RMRO + 0x0308) +#define MFCICT (RMRO + 0x030c) +#define MEEECT (RMRO + 0x0310) +#define MMPCFTCT0 (RMRO + 0x0320) +#define MAPCFTCT0 (RMRO + 0x0330) +#define MPCFRCT0 (RMRO + 0x0340) +#define MHDCC (RMRO + 0x0350) +#define MROVFC (RMRO + 0x0354) +#define MRHCRCEC (RMRO + 0x0358) +#define MRXBCE (RMRO + 0x0400) +#define MRXBCP (RMRO + 0x0404) +#define MRGFCE (RMRO + 0x0408) +#define MRGFCP (RMRO + 0x040C) +#define MRBFC (RMRO + 0x0410) +#define MRMFC (RMRO + 0x0414) +#define MRUFC (RMRO + 0x0418) +#define MRPEFC (RMRO + 0x041C) +#define MRNEFC (RMRO + 0x0420) +#define MRFMEFC (RMRO + 0x0424) +#define MRFFMEFC (RMRO + 0x0428) +#define MRCFCEFC (RMRO + 0x042C) +#define MRFCEFC (RMRO + 0x0430) +#define MRRCFEFC (RMRO + 0x0434) +#define MRUEFC (RMRO + 0x043C) +#define MROEFC (RMRO + 0x0440) +#define MRBOEC (RMRO + 0x0444) +#define MTXBCE (RMRO + 0x0500) +#define MTXBCP (RMRO + 0x0504) +#define MTGFCE (RMRO + 0x0508) +#define MTGFCP (RMRO + 0x050C) +#define MTBFC (RMRO + 0x0510) +#define MTMFC (RMRO + 0x0514) +#define MTUFC (RMRO + 0x0518) +#define MTEFC (RMRO + 0x051C) + +#define GWMC (GWRO + 0x0000) +#define GWMS (GWRO + 0x0004) +#define GWIRC (GWRO + 0x0010) +#define GWRDQSC (GWRO + 0x0014) +#define GWRDQC (GWRO + 0x0018) +#define GWRDQAC (GWRO + 0x001C) +#define GWRGC (GWRO + 0x0020) +#define GWRMFSC0 (GWRO + 0x0040) +#define GWRDQDC0 (GWRO + 0x0060) +#define GWRDQM0 (GWRO + 0x0080) +#define GWRDQMLM0 (GWRO + 0x00A0) +#define GWMTIRM (GWRO + 0x0100) +#define GWMSTLS (GWRO + 0x0104) +#define GWMSTLR (GWRO + 0x0108) +#define GWMSTSS (GWRO + 0x010C) +#define GWMSTSR (GWRO + 0x0110) +#define GWMAC0 (GWRO + 0x0120) +#define GWMAC1 (GWRO + 0x0124) +#define GWVCC (GWRO + 0x0130) +#define GWVTC (GWRO + 0x0134) +#define GWTTFC (GWRO + 0x0138) +#define GWTDCAC00 (GWRO + 0x0140) +#define GWTDCAC10 (GWRO + 0x0144) +#define GWTSDCC0 (GWRO + 0x0160) +#define GWTNM (GWRO + 0x0180) +#define GWTMNM (GWRO + 0x0184) +#define GWAC (GWRO + 0x0190) +#define GWDCBAC0 (GWRO + 0x0194) +#define GWDCBAC1 (GWRO + 0x0198) +#define GWIICBSC (GWRO + 0x019C) +#define GWMDNC (GWRO + 0x01A0) +#define GWTRC0 (GWRO + 0x0200) +#define GWTPC0 (GWRO + 0x0300) +#define GWARIRM (GWRO + 0x0380) +#define GWDCC0 (GWRO + 0x0400) +#define GWAARSS (GWRO + 0x0800) +#define GWAARSR0 (GWRO + 0x0804) +#define GWAARSR1 (GWRO + 0x0808) +#define GWIDAUAS0 (GWRO + 0x0840) +#define GWIDASM0 (GWRO + 0x0880) +#define GWIDASAM00 (GWRO + 0x0900) +#define GWIDASAM10 (GWRO + 0x0904) +#define GWIDACAM00 (GWRO + 0x0980) +#define GWIDACAM10 (GWRO + 0x0984) +#define GWGRLC (GWRO + 0x0A00) +#define GWGRLULC (GWRO + 0x0A04) +#define GWRLIVC0 (GWRO + 0x0A80) +#define GWRLULC0 (GWRO + 0x0A84) +#define GWIDPC (GWRO + 0x0B00) +#define GWIDC0 (GWRO + 0x0C00) +#define GWDIS0 (GWRO + 0x1100) +#define GWDIE0 (GWRO + 0x1104) +#define GWDID0 (GWRO + 0x1108) +#define GWTSDIS (GWRO + 0x1180) +#define GWTSDIE (GWRO + 0x1184) +#define GWTSDID (GWRO + 0x1188) +#define GWEIS0 (GWRO + 0x1190) +#define GWEIE0 (GWRO + 0x1194) +#define GWEID0 (GWRO + 0x1198) +#define GWEIS1 (GWRO + 0x11A0) +#define GWEIE1 (GWRO + 0x11A4) +#define GWEID1 (GWRO + 0x11A8) +#define GWEIS20 (GWRO + 0x1200) +#define GWEIE20 (GWRO + 0x1204) +#define GWEID20 (GWRO + 0x1208) +#define GWEIS3 (GWRO + 0x1280) +#define GWEIE3 (GWRO + 0x1284) +#define GWEID3 (GWRO + 0x1288) +#define GWEIS4 (GWRO + 0x1290) +#define GWEIE4 (GWRO + 0x1294) +#define GWEID4 (GWRO + 0x1298) +#define GWEIS5 (GWRO + 0x12A0) +#define GWEIE5 (GWRO + 0x12A4) +#define GWEID5 (GWRO + 0x12A8) +#define GWSCR0 (GWRO + 0x1800) +#define GWSCR1 (GWRO + 0x1900) + +/* COMA */ +#define RRC_RR BIT(0) +#define RRC_RR_CLR (0) +#define RCEC_RCE BIT(16) +#define RCDC_RCD BIT(16) + +#define CABPIRM_BPIOG BIT(0) +#define CABPIRM_BPR BIT(1) + +#endif /* RSWITCH_REGS_H */ \ No newline at end of file diff --git a/libraries/drivers/ethernet/renesas/utils.c b/libraries/drivers/ethernet/renesas/utils.c new file mode 100644 index 000000000..c3941441d --- /dev/null +++ b/libraries/drivers/ethernet/renesas/utils.c @@ -0,0 +1,156 @@ +#include "tpl_os.h" +#include "utils.h" +#include "pfcmap.h" + +#define ETH_CPUCLK_MHZ 1066UL +#define ETH_WAIT_NS(t) \ + { \ + volatile uint32 cnt; \ + for (cnt = 0; \ + cnt < ((((uint32)ETH_CPUCLK_MHZ * ((uint32)t)) / (uint32)1000) + (uint32)1); \ + cnt++); \ + } + +/* Module Standby, Software reset */ +#define MSTPCR_ETH_1 (*((volatile uint32 *)0xE6152D3CUL)) /* MSTPCR15 Register */ +#define MSTPSR_ETH_1 (*((volatile uint32 *)0xE6152E3CUL)) /* MSTPSR15 Register */ +#define MSTP_BIT_ETHIP (uint32)(1 << 5) +#define MSTP_BIT_ETHPHY (uint32)(1 << 6) + +/* CPG */ +#define CPG_CPGWPR (*((volatile uint32 *)0xE6150000UL)) /* CPGWPR Register used to remove MSTPCR write protection */ +#define CKCR_ETH_1 (*((volatile uint32 *)0xE61508E8UL)) /* RSW2CKCR Register */ +#define CKCR_BIT_ETHIP (uint32)(1 << 8) + +#define SRCR_ETH_1 (*((volatile uint32 *)0xE6152C3CUL)) /* SRCR15 Register */ +#define SRSTCLR_ETH_1 (*((volatile uint32 *)0xE6152CBCUL)) /* SRSTCLCR15 Register */ +#define SRCR_BIT_ETHIP (uint32)(1 << 5) +#define SRCR_BIT_ETHPHY (uint32)(1 << 6) + +void rswitch_enable_clock_and_reset(void) +{ + volatile uint32 regval = 0x0UL; + + /* Enable RSW2 clock by writing 0 to CKCR */ + regval = CKCR_ETH_1; /* RSW2CKCR */ + if (regval & CKCR_BIT_ETHIP) /* 1: Stops the clock */ + { + regval &= ~CKCR_BIT_ETHIP; + CKCR_ETH_1 = regval; /* 0: Supplies the clock */ + while (CKCR_ETH_1 & CKCR_BIT_ETHIP); /* Wait for the register value to change */ + } + + /* Supply RSW2 and ETHPHY clock by writing 0 to MSTPSR */ + regval = MSTPSR_ETH_1; + if (regval & (MSTP_BIT_ETHIP | MSTP_BIT_ETHPHY)) /* If either one is 1(=Stops the clock), execute the process */ + { + regval &= ~(MSTP_BIT_ETHIP | MSTP_BIT_ETHPHY); + CPG_CPGWPR = ~regval; /* Release MSTPCR write protection by writing the inverse of the value to CPGWPR */ + MSTPCR_ETH_1 = regval; /* 0: Supplies the clock */ + while (MSTPSR_ETH_1 & (MSTP_BIT_ETHIP | MSTP_BIT_ETHPHY)); /* Wait for the register value to change */ + } + + /* Reset RSW2 and ETHPHY by writing 1 to SRCR */ + CPG_CPGWPR = ~(SRCR_BIT_ETHIP | SRCR_BIT_ETHPHY); /* Release SRCR write protection by writing the inverse of the value to CPGWR */ + SRCR_ETH_1 = (uint32)(SRCR_BIT_ETHIP | SRCR_BIT_ETHPHY); /* SRCR does not require read-modify write */ + ETH_WAIT_NS(20*1000); + + /* Release the reset RSW2 and ETHPHY by writing 1 to SRSTCLR */ + CPG_CPGWPR = ~(SRCR_BIT_ETHIP | SRCR_BIT_ETHPHY); /* Release SRSTCLR write protection by writing the inverse of the value to CPGWR */ + SRSTCLR_ETH_1 = (uint32)(SRCR_BIT_ETHIP | SRCR_BIT_ETHPHY); /* SRSTCLR does not require read-modify write */ + ETH_WAIT_NS(40*1000); +} + +uint32 reg_read32(uint32 addr) +{ + return *((volatile uint32*)addr); +} + +void reg_write32(uint32 data, uint32 addr) +{ + *((volatile uint32*)addr) = data; +} + +extern volatile VAR(uint32, OS_VAR) tpl_time_counter; +uint32 get_time(void) +{ + return tpl_time_counter; +} + +uint32 get_elapsed_time(uint32 start_val) +{ + return (tpl_time_counter - start_val); +} + +void ms_delay(uint32 value) +{ + uint32 start_time = get_time(); + + while(get_elapsed_time(start_time) < value); +} + +void port_init(void) +{ + uint32 dataL; + + /*------- + * GPSR3[18:0] = 18'b1111111111111111111 + * = TSNx_AVTP_CAPTURE, TSNx_AVTP_MATCH, TSNx_AVTP_PPS, TSN0_MAGIC, TSNx_PHY_INT, TSNx_LINK, TSNx_MDC, TSNx_MDIO */ + dataL = *((volatile uint32 *)(PFC_GPSR_GPn_DM0(3))); + dataL &= ~(0x0007FFFFUL); + dataL |= (0x0007FFFFUL); + *((volatile uint32 *)(PFC_PMMR(PFC_GPn_BASE(3)))) = ~dataL; + *((volatile uint32 *)(PFC_GPSR_GPn_DM0(3))) = dataL; + + /*------- + * DRV0CTRL4 [31:28] AVB0_TXC + * [27:24] AVB0_TX_CTL + * DRV1CTRL4 [15:12] AVB0_TD3 + * [11:8] AVB0_TD2 + * [7:4] AVB0_TD1 + * [3:0] AVB0_TD0 */ + dataL = *((volatile uint32 *)PFC_DRVCTRLm_GPn_DM0(0,3)); + dataL &= ~0x77777777UL; + dataL |= 0x33333333UL; + *((volatile uint32 *)(PFC_PMMR(PFC_GPn_BASE(3)))) = ~dataL; + *((volatile uint32 *)(PFC_DRVCTRLm_GPn_DM0(0,3))) = dataL; + + dataL = *((volatile uint32 *)PFC_DRVCTRLm_GPn_DM0(1,3)); + dataL &= ~0x77777777UL; + dataL |= 0x33333333UL; + *((volatile uint32 *)(PFC_PMMR(PFC_GPn_BASE(3)))) = ~dataL; + *((volatile uint32 *)(PFC_DRVCTRLm_GPn_DM0(1,3))) = dataL; + + dataL = *((volatile uint32 *)PFC_DRVCTRLm_GPn_DM0(2,3)); + dataL &= ~0x00000777UL; + dataL |= 0x00000333UL; + *((volatile uint32 *)(PFC_PMMR(PFC_GPn_BASE(3)))) = ~dataL; + *((volatile uint32 *)(PFC_DRVCTRLm_GPn_DM0(2,3))) = dataL; + + /* Ether TSN IO voltage level = 1.8V + * POC3 bit[18:0] = 0 = IO voltage level = 1.8V */ + dataL = *((volatile uint32 *)PFC_POC_GPn_DM0(3)); + dataL &= ~(0x0007FFFFUL); + *((volatile uint32 *)(PFC_PMMR(PFC_GPn_BASE(3)))) = ~dataL; + *((volatile uint32 *)(PFC_POC_GPn_DM0(3))) = dataL; +} + +#define GICD_ISENABLER (0xf0000100) + +void enable_int(uint32 num) +{ + *((volatile uint32 *)(GICD_ISENABLER + 4 * (num / 32))) = 1 << (num % 32); +} + +void debug_print_buffer(uint8 *buf, uint32 len) +{ + uint32 i = 0; + + for (i = 0; i < len; i++) { + if ((i != 0) && ((i % 16) == 0)) { + debug_printf("\n\r"); + } + debug_printf("%02x ", buf[i]); + } + debug_printf("\n\r"); +} diff --git a/libraries/drivers/ethernet/renesas/utils.h b/libraries/drivers/ethernet/renesas/utils.h new file mode 100644 index 000000000..790177f6c --- /dev/null +++ b/libraries/drivers/ethernet/renesas/utils.h @@ -0,0 +1,41 @@ +#ifndef _UTILS_H_ +#define _UTILS_H_ + +#include "tpl_os_types.h" +#include "printf.h" + +#define debug_msg(...) \ + do { \ + debug_printf(__VA_ARGS__); \ + debug_printf("\n\r"); \ + } while(0) + +#define BIT(x) (1UL << x) +#define BITS_PER_TYPE(x) (sizeof(x) * 8) +#define BITS_PER_LONG (BITS_PER_TYPE(unsigned long)) + +#define GENMASK(h, l) \ + (((~(0UL)) - ((1UL) << (l)) + 1) & \ + (~(0UL) >> (BITS_PER_LONG - 1 - (h)))) + +#define CHECK_RET(f) \ + ret = (f); \ + if (ret != 0) { \ + return ret; \ + } + +uint32 reg_read32(uint32 addr); +void reg_write32(uint32 data, uint32 addr); + +void rswitch_enable_clock_and_reset(void); +void port_init(void); + +void enable_int(uint32 irq); + +uint32 get_time(void); +uint32 get_elapsed_time(uint32 start_val); +void ms_delay(uint32 value); + +void debug_print_buffer(uint8 *buf, uint32 len); + +#endif /* _UTILS_H_ */ diff --git a/libraries/drivers/lwip_port/renesas/arch/cc.h b/libraries/drivers/lwip_port/renesas/arch/cc.h new file mode 100644 index 000000000..1692c833d --- /dev/null +++ b/libraries/drivers/lwip_port/renesas/arch/cc.h @@ -0,0 +1,40 @@ +#ifndef __ARCH_CC_H__ +#define __ARCH_CC_H__ + +#include "utils.h" + +// Hack to use our own 'atoi' function in order to prevent usage of libc one, because libc 'atoi' has many dependencies +#undef atoi +//unsigned int atoi(const unsigned char* s); +int atoi(const char *num); + +#define LWIP_ERR_T int + +#define LWIP_PROVIDE_ERRNO + +/* Define (sn)printf formatters for these lwIP types */ +#define U16_F "u" +#define S16_F "d" +#define X16_F "x" +#define U32_F "u" +#define S32_F "d" +#define X32_F "x" + +#define BYTE_ORDER LITTLE_ENDIAN + +/* Compiler hints for packing structures */ +#define PACK_STRUCT_FIELD(x) x +#define PACK_STRUCT_STRUCT __attribute__((packed)) +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_END + +/* Plaform specific diagnostic output */ +#define LWIP_PLATFORM_DIAG(x) do { \ + debug_msg x; \ + } while (0) + +#define LWIP_PLATFORM_ASSERT(x) do { \ + while(1); \ + } while (0) + +#endif /* __ARCH_CC_H__ */ diff --git a/libraries/drivers/lwip_port/renesas/arch/sys_arch.h b/libraries/drivers/lwip_port/renesas/arch/sys_arch.h new file mode 100644 index 000000000..686bc831b --- /dev/null +++ b/libraries/drivers/lwip_port/renesas/arch/sys_arch.h @@ -0,0 +1,42 @@ +#ifndef LWIP_ARCH_SYS_ARCH_H +#define LWIP_ARCH_SYS_ARCH_H + +#include "lwip/arch.h" + +#if !NO_SYS + +#define SYS_MBOX_NULL NULL +#define SYS_SEM_NULL NULL + +#define MAX_NB_MUTEX 100 +#define MAX_NB_SEM 40 +#define MAX_NB_MBOX 10 + +typedef u32_t sys_prot_t; + +struct sys_sem; +typedef struct sys_sem * sys_sem_t; +#define sys_sem_valid(sem) (((sem) != NULL) && (*(sem) != NULL)) +#define sys_sem_valid_val(sem) ((sem) != NULL) +#define sys_sem_set_invalid(sem) do { if((sem) != NULL) { *(sem) = NULL; }}while(0) +#define sys_sem_set_invalid_val(sem) do { (sem) = NULL; }while(0) + +struct sys_mutex; +typedef struct sys_mutex * sys_mutex_t; +#define sys_mutex_valid(mutex) sys_sem_valid(mutex) +#define sys_mutex_set_invalid(mutex) sys_sem_set_invalid(mutex) + +struct sys_mbox; +typedef struct sys_mbox * sys_mbox_t; +#define sys_mbox_valid(mbox) sys_sem_valid(mbox) +#define sys_mbox_valid_val(mbox) sys_sem_valid_val(mbox) +#define sys_mbox_set_invalid(mbox) sys_sem_set_invalid(mbox) +#define sys_mbox_set_invalid_val(mbox) sys_sem_set_invalid_val(mbox) + +struct sys_thread; +typedef struct sys_thread * sys_thread_t; + +#endif /* !NO_SYS */ + +#endif /* LWIP_ARCH_SYS_ARCH_H */ + diff --git a/libraries/drivers/lwip_port/renesas/ethif.c b/libraries/drivers/lwip_port/renesas/ethif.c new file mode 100644 index 000000000..83f5525bf --- /dev/null +++ b/libraries/drivers/lwip_port/renesas/ethif.c @@ -0,0 +1,144 @@ +#include +#include "ethif.h" +#include "utils.h" +#include "eth_serdes.h" +#include "rswitch.h" +#include "eth_gptp.h" +#include "lwip/etharp.h" + +static struct netif *netif_ref = NULL; + +void ethif_callback(uint8 *data, uint16 len) +{ + struct pbuf *p, *q; + uint8_t *data_ptr = data; + err_t ret; + + /* move received packet into a new pbuf */ +#if ETH_PAD_SIZE + len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ +#endif + /* We allocate a pbuf chain of pbufs from the pool. */ + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + if (p == NULL) { + debug_msg("Error: unable to allocate memory in %s", __func__); + return; + } + +#if ETH_PAD_SIZE + pbuf_remove_header(p, ETH_PAD_SIZE); /* drop the padding word */ +#endif + /* We iterate over the pbuf chain until we have read the entire + * packet into the pbuf. */ + for (q = p; q != NULL; q = q->next) { + memcpy(q->payload, data_ptr, q->len); + data_ptr += q->len; + } +#if ETH_PAD_SIZE + pbuf_add_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + + /* pass all packets to ethernet_input, which decides what packets it supports */ + ret = netif_ref->input(p, netif_ref); + if (ret != ERR_OK) { + debug_msg("Error: netif->input returned %d\n", ret); + pbuf_free(p); + } +} + +static err_t low_level_output(struct netif *netif, struct pbuf *p) +{ + (void) netif; + struct pbuf *q; + int ret; + +#if ETH_PAD_SIZE + pbuf_remove_header(p, ETH_PAD_SIZE); /* drop the padding word */ +#endif + + for (q = p; q != NULL; q = q->next) { + /* Send the data from the pbuf to the interface, one pbuf at a + time. The size of the data in each pbuf is kept in the ->len + variable. */ + ret = rswitch_send_data(q->payload, q->len); + if (ret != 0) { + return ERR_IF; + } + } + +#if ETH_PAD_SIZE + pbuf_add_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + + return ERR_OK; +} + +static err_t low_level_init(struct netif *netif) +{ + int ret; + + netif->hwaddr_len = ETHARP_HWADDR_LEN; + /* This is the same value set in "rswitch.c" */ + netif->hwaddr[0] = 0x74U; + netif->hwaddr[1] = 0x90U; + netif->hwaddr[2] = 0x50U; + netif->hwaddr[3] = 0x00U; + netif->hwaddr[4] = 0x00U; + netif->hwaddr[5] = 0x00U; + netif->mtu = 1500; + + /* device capabilities */ + /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_LINK_UP; + + // Interrupt initializazion done by Trampoline + eth_disable_fuse_ovr(); + + ret = eth_serdes_initialize(); + if (ret != 0) { + debug_msg("Error in eth_serdes_initialize"); + return ERR_IF; + } + debug_msg("SERDES initialization done"); + + ret = rswitch_init(); + if (ret != 0) { + debug_msg("Error in rswitch_init\n"); + return ERR_IF; + } + debug_msg("RSwitch initialization done"); + + debug_msg("Initialize gPTP"); + eth_gptp_init(); + + ret = rswitch_open(); + if (ret != 0) { + debug_msg("Error in rswitch_open\n"); + return ERR_IF; + } + debug_msg("RSwitch open completed"); + + rswitch_regiter_data_received_callback(ethif_callback); + + debug_msg("Initialization completed"); + + return ERR_OK; +} + +err_t ethif_init(struct netif *netif) +{ + debug_msg("%s", __func__); + + netif_ref = netif; + + netif->name[0] = 'r'; + netif->name[1] = 'n'; + netif->mtu = 1500; + + netif->state = NULL; // Set to anything, if necessary + + netif->linkoutput = low_level_output; + netif->output = etharp_output; + + return low_level_init(netif); +} \ No newline at end of file diff --git a/libraries/drivers/lwip_port/renesas/ethif.h b/libraries/drivers/lwip_port/renesas/ethif.h new file mode 100644 index 000000000..60225bd2b --- /dev/null +++ b/libraries/drivers/lwip_port/renesas/ethif.h @@ -0,0 +1,10 @@ +#ifndef _ETHERNET_IF_H_ +#define _ETHERNET_IF_H_ + +#include "lwip/init.h" +#include "lwip/err.h" +#include "lwip/netif.h" + +err_t ethif_init(struct netif *netif); + +#endif // _ETHERNET_IF_H_ \ No newline at end of file diff --git a/libraries/drivers/lwip_port/renesas/lwipopts.h b/libraries/drivers/lwip_port/renesas/lwipopts.h new file mode 100644 index 000000000..582df0f84 --- /dev/null +++ b/libraries/drivers/lwip_port/renesas/lwipopts.h @@ -0,0 +1,307 @@ +#if NO_SYS +#define SYS_LIGHTWEIGHT_PROT 0 +#define LWIP_SOCKET 0 +#else +#define SYS_LIGHTWEIGHT_PROT 1 +#define LWIP_SOCKET 1 +#endif + +#define LWIP_TCP 1 +#define LWIP_TCPIP_CORE_LOCKING 0 +#define LWIP_RAW 1 +#define SO_REUSE 1 + +#define TCPIP_MBOX_SIZE 5 +#define PBUF_POOL_SIZE 16 +#define MEMP_NUM_PBUF 30 + +//#define LWIP_DEBUG 1 + +/* test an lwipopts.h file with default contents */ +#define NO_SYS_NO_TIMERS 1 +#define LWIP_TIMERS 1 +#define LWIP_TIMERS_CUSTOM 0 +#define LWIP_MPU_COMPATIBLE 0 +#define LWIP_TCPIP_CORE_LOCKING_INPUT 0 +#define MEM_LIBC_MALLOC 0 +#define MEMP_MEM_MALLOC 0 +#define MEMP_MEM_INIT 0 +#define MEM_ALIGNMENT 1 +#define MEM_SIZE 1600 +#define MEMP_OVERFLOW_CHECK 0 +#define MEMP_SANITY_CHECK 0 +#define MEM_OVERFLOW_CHECK 0 +#define MEM_SANITY_CHECK 0 +#define MEM_USE_POOLS 0 +#define MEM_USE_POOLS_TRY_BIGGER_POOL 0 +#define MEMP_USE_CUSTOM_POOLS 0 +#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 0 +/*#define MEMP_NUM_PBUF 16 +#define MEMP_NUM_RAW_PCB 4 +#define MEMP_NUM_UDP_PCB 4 +#define MEMP_NUM_TCP_PCB 5 +#define MEMP_NUM_TCP_PCB_LISTEN 8 +#define MEMP_NUM_TCP_SEG 16 +#define MEMP_NUM_ALTCP_PCB MEMP_NUM_TCP_PCB +#define MEMP_NUM_REASSDATA 5 +#define MEMP_NUM_FRAG_PBUF 15 +#define MEMP_NUM_ARP_QUEUE 30 +#define MEMP_NUM_IGMP_GROUP 8 +#define MEMP_NUM_SYS_TIMEOUT (LWIP_NUM_SYS_TIMEOUT_INTERNAL + 2) +#define MEMP_NUM_NETBUF 2 +#define MEMP_NUM_NETCONN 4 +#define MEMP_NUM_SELECT_CB 4 +#define MEMP_NUM_TCPIP_MSG_API 8 +#define MEMP_NUM_TCPIP_MSG_INPKT 8 +#define MEMP_NUM_NETDB 1 +#define MEMP_NUM_LOCALHOSTLIST 1 +#define PBUF_POOL_SIZE 16 +#define MEMP_NUM_API_MSG MEMP_NUM_TCPIP_MSG_API +#define MEMP_NUM_DNS_API_MSG MEMP_NUM_TCPIP_MSG_API +#define MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA MEMP_NUM_TCPIP_MSG_API +#define MEMP_NUM_NETIFAPI_MSG MEMP_NUM_TCPIP_MSG_API*/ +#define LWIP_ARP 1 +#define ARP_TABLE_SIZE 10 +#define ARP_MAXAGE 300 +#define ARP_QUEUEING 0 +#define ARP_QUEUE_LEN 3 +#define ETHARP_SUPPORT_VLAN 0 +#define LWIP_ETHERNET LWIP_ARP +#define ETH_PAD_SIZE 0 +#define ETHARP_SUPPORT_STATIC_ENTRIES 0 +#define ETHARP_TABLE_MATCH_NETIF !LWIP_SINGLE_NETIF +#define LWIP_IPV4 1 +#define IP_FORWARD 0 +#define IP_REASSEMBLY 1 +#define IP_FRAG 1 +#define IP_OPTIONS_ALLOWED 1 +#define IP_REASS_MAXAGE 15 +#define IP_REASS_MAX_PBUFS 10 +#define IP_DEFAULT_TTL 255 +#define IP_SOF_BROADCAST 0 +#define IP_SOF_BROADCAST_RECV 0 +#define IP_FORWARD_ALLOW_TX_ON_RX_NETIF 0 +#define LWIP_ICMP 1 +#define ICMP_TTL (IP_DEFAULT_TTL) +#define LWIP_BROADCAST_PING 0 +#define LWIP_MULTICAST_PING 0 +#define RAW_TTL (IP_DEFAULT_TTL) +#define LWIP_DHCP 1 +#define LWIP_DHCP_CHECK_LINK_UP 0 +#define LWIP_DHCP_BOOTP_FILE 0 +#define LWIP_DHCP_GET_NTP_SRV 0 +#define LWIP_DHCP_MAX_NTP_SERVERS 1 +#define LWIP_DHCP_MAX_DNS_SERVERS DNS_MAX_SERVERS +#define LWIP_AUTOIP 0 +#define LWIP_DHCP_AUTOIP_COOP 0 +#define LWIP_DHCP_AUTOIP_COOP_TRIES 9 +#define LWIP_MIB2_CALLBACKS 0 +#define LWIP_MULTICAST_TX_OPTIONS ((LWIP_IGMP || LWIP_IPV6_MLD) && (LWIP_UDP || LWIP_RAW)) +#define LWIP_IGMP 0 +#define LWIP_DNS 0 +#define DNS_TABLE_SIZE 4 +#define DNS_MAX_NAME_LENGTH 256 +#define DNS_MAX_SERVERS 2 +#define DNS_MAX_RETRIES 4 +#define DNS_DOES_NAME_CHECK 1 +#define LWIP_DNS_SECURE (LWIP_DNS_SECURE_RAND_XID | LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING | LWIP_DNS_SECURE_RAND_SRC_PORT) +#define DNS_LOCAL_HOSTLIST 0 +#define DNS_LOCAL_HOSTLIST_IS_DYNAMIC 0 +#define LWIP_DNS_SUPPORT_MDNS_QUERIES 0 +#define LWIP_UDP 1 +#define LWIP_UDPLITE 0 +#define UDP_TTL (IP_DEFAULT_TTL) +#define LWIP_NETBUF_RECVINFO 0 +#define TCP_TTL (IP_DEFAULT_TTL) +#define TCP_WND (4 * TCP_MSS) +#define TCP_MAXRTX 12 +#define TCP_SYNMAXRTX 6 +#define TCP_QUEUE_OOSEQ (LWIP_TCP) +#define LWIP_TCP_SACK_OUT 0 +#define LWIP_TCP_MAX_SACK_NUM 4 +#define TCP_MSS 536 +#define TCP_CALCULATE_EFF_SEND_MSS 1 +#define TCP_SND_BUF (2 * TCP_MSS) +#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS)) +#define TCP_SNDLOWAT LWIP_MIN(LWIP_MAX(((TCP_SND_BUF)/2), (2 * TCP_MSS) + 1), (TCP_SND_BUF) - 1) +#define TCP_SNDQUEUELOWAT LWIP_MAX(((TCP_SND_QUEUELEN)/2), 5) +#define TCP_OOSEQ_MAX_BYTES 0 +#define TCP_OOSEQ_BYTES_LIMIT(pcb) TCP_OOSEQ_MAX_BYTES +#define TCP_OOSEQ_MAX_PBUFS 0 +#define TCP_OOSEQ_PBUFS_LIMIT(pcb) TCP_OOSEQ_MAX_PBUFS +#define TCP_LISTEN_BACKLOG 0 +#define TCP_DEFAULT_LISTEN_BACKLOG 0xff +#define TCP_OVERSIZE TCP_MSS +#define LWIP_TCP_TIMESTAMPS 0 +#define TCP_WND_UPDATE_THRESHOLD LWIP_MIN((TCP_WND / 4), (TCP_MSS * 4)) +#define LWIP_EVENT_API 0 +#define LWIP_CALLBACK_API 1 +#define LWIP_WND_SCALE 0 +#define TCP_RCV_SCALE 0 +#define LWIP_TCP_PCB_NUM_EXT_ARGS 0 +#define LWIP_ALTCP 0 +#define LWIP_ALTCP_TLS 0 +#define PBUF_LINK_HLEN (14 + ETH_PAD_SIZE) +#define PBUF_LINK_ENCAPSULATION_HLEN 0 +#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_ENCAPSULATION_HLEN+PBUF_LINK_HLEN) +#define LWIP_PBUF_REF_T u8_t +#define LWIP_SINGLE_NETIF 0 +#define LWIP_NETIF_HOSTNAME 0 +#define LWIP_NETIF_API 0 +#define LWIP_NETIF_STATUS_CALLBACK 0 +#define LWIP_NETIF_EXT_STATUS_CALLBACK 0 +#define LWIP_NETIF_LINK_CALLBACK 0 +#define LWIP_NETIF_REMOVE_CALLBACK 0 +#define LWIP_NETIF_HWADDRHINT 0 +#define LWIP_NETIF_TX_SINGLE_PBUF 0 +#define LWIP_NUM_NETIF_CLIENT_DATA 0 +#define LWIP_HAVE_LOOPIF (LWIP_NETIF_LOOPBACK && !LWIP_SINGLE_NETIF) +#define LWIP_LOOPIF_MULTICAST 0 +#define LWIP_NETIF_LOOPBACK 0 +#define LWIP_LOOPBACK_MAX_PBUFS 0 +#define LWIP_NETIF_LOOPBACK_MULTITHREADING (!NO_SYS) +/*#define TCPIP_THREAD_NAME "tcpip_thread" +#define TCPIP_THREAD_STACKSIZE 0 +#define TCPIP_THREAD_PRIO 1 +#define TCPIP_MBOX_SIZE 0 +#define LWIP_TCPIP_THREAD_ALIVE() +#define SLIPIF_THREAD_NAME "slipif_loop" +#define SLIPIF_THREAD_STACKSIZE 0 +#define SLIPIF_THREAD_PRIO 1 +#define DEFAULT_THREAD_NAME "lwIP" +#define DEFAULT_THREAD_STACKSIZE 0 +#define DEFAULT_THREAD_PRIO 1 +#define DEFAULT_RAW_RECVMBOX_SIZE 0 +#define DEFAULT_UDP_RECVMBOX_SIZE 0 +#define DEFAULT_TCP_RECVMBOX_SIZE 0 +#define DEFAULT_ACCEPTMBOX_SIZE 0*/ +#define LWIP_NETCONN 0 +#define LWIP_TCPIP_TIMEOUT 0 +#define LWIP_NETCONN_SEM_PER_THREAD 0 +#define LWIP_NETCONN_FULLDUPLEX 0 +#define LWIP_COMPAT_SOCKETS 1 /* 0..2 */ +#define LWIP_POSIX_SOCKETS_IO_NAMES 1 +#define LWIP_SOCKET_OFFSET 0 +#define LWIP_TCP_KEEPALIVE 0 +#define LWIP_SO_SNDTIMEO 0 +#define LWIP_SO_RCVTIMEO 0 +#define LWIP_SO_SNDRCVTIMEO_NONSTANDARD 0 +#define LWIP_SO_RCVBUF 0 +#define LWIP_SO_LINGER 0 +#define RECV_BUFSIZE_DEFAULT INT_MAX +#define LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT 20000 +#define SO_REUSE_RXTOALL 0 +#define LWIP_FIONREAD_LINUXMODE 0 +#define LWIP_SOCKET_SELECT 1 +#define LWIP_SOCKET_POLL 1 +#define LWIP_STATS 1 +#define LWIP_STATS_DISPLAY 0 +#define LINK_STATS 1 +#define ETHARP_STATS (LWIP_ARP) +#define IP_STATS 1 +#define IPFRAG_STATS (IP_REASSEMBLY || IP_FRAG) +#define ICMP_STATS 1 +#define IGMP_STATS (LWIP_IGMP) +#define UDP_STATS (LWIP_UDP) +#define TCP_STATS (LWIP_TCP) +#define MEM_STATS ((MEM_LIBC_MALLOC == 0) && (MEM_USE_POOLS == 0)) +#define MEMP_STATS (MEMP_MEM_MALLOC == 0) +#define SYS_STATS (NO_SYS == 0) +#define IP6_STATS (LWIP_IPV6) +#define ICMP6_STATS (LWIP_IPV6 && LWIP_ICMP6) +#define IP6_FRAG_STATS (LWIP_IPV6 && (LWIP_IPV6_FRAG || LWIP_IPV6_REASS)) +#define MLD6_STATS (LWIP_IPV6 && LWIP_IPV6_MLD) +#define ND6_STATS (LWIP_IPV6) +#define MIB2_STATS 0 +#define LWIP_CHECKSUM_CTRL_PER_NETIF 0 +#define CHECKSUM_GEN_IP 1 +#define CHECKSUM_GEN_UDP 1 +#define CHECKSUM_GEN_TCP 1 +#define CHECKSUM_GEN_ICMP 1 +#define CHECKSUM_GEN_ICMP6 1 +#define CHECKSUM_CHECK_IP 1 +#define CHECKSUM_CHECK_UDP 1 +#define CHECKSUM_CHECK_TCP 1 +#define CHECKSUM_CHECK_ICMP 1 +#define CHECKSUM_CHECK_ICMP6 1 +#define LWIP_CHECKSUM_ON_COPY 0 +#define LWIP_IPV6 0 +#define IPV6_REASS_MAXAGE 60 +#define LWIP_IPV6_SCOPES (LWIP_IPV6 && !LWIP_SINGLE_NETIF) +#define LWIP_IPV6_SCOPES_DEBUG 0 +#define LWIP_IPV6_NUM_ADDRESSES 3 +#define LWIP_IPV6_FORWARD 0 +#define LWIP_IPV6_FRAG 1 +#define LWIP_IPV6_REASS (LWIP_IPV6) +#define LWIP_IPV6_SEND_ROUTER_SOLICIT 1 +#define LWIP_IPV6_AUTOCONFIG (LWIP_IPV6) +#define LWIP_IPV6_ADDRESS_LIFETIMES (LWIP_IPV6_AUTOCONFIG) +#define LWIP_IPV6_DUP_DETECT_ATTEMPTS 1 +#define LWIP_ICMP6 (LWIP_IPV6) +#define LWIP_ICMP6_DATASIZE 8 +#define LWIP_ICMP6_HL 255 +#define LWIP_IPV6_MLD (LWIP_IPV6) +#define MEMP_NUM_MLD6_GROUP 4 +#define LWIP_ND6_QUEUEING (LWIP_IPV6) +#define MEMP_NUM_ND6_QUEUE 20 +#define LWIP_ND6_NUM_NEIGHBORS 10 +#define LWIP_ND6_NUM_DESTINATIONS 10 +#define LWIP_ND6_NUM_PREFIXES 5 +#define LWIP_ND6_NUM_ROUTERS 3 +#define LWIP_ND6_MAX_MULTICAST_SOLICIT 3 +#define LWIP_ND6_MAX_UNICAST_SOLICIT 3 +#define LWIP_ND6_MAX_ANYCAST_DELAY_TIME 1000 +#define LWIP_ND6_MAX_NEIGHBOR_ADVERTISEMENT 3 +#define LWIP_ND6_REACHABLE_TIME 30000 +#define LWIP_ND6_RETRANS_TIMER 1000 +#define LWIP_ND6_DELAY_FIRST_PROBE_TIME 5000 +#define LWIP_ND6_ALLOW_RA_UPDATES 1 +#define LWIP_ND6_TCP_REACHABILITY_HINTS 1 +#define LWIP_ND6_RDNSS_MAX_DNS_SERVERS 0 +#define LWIP_IPV6_DHCP6 0 +#define LWIP_IPV6_DHCP6_STATEFUL 0 +#define LWIP_IPV6_DHCP6_STATELESS LWIP_IPV6_DHCP6 +#define LWIP_DHCP6_GET_NTP_SRV 0 +#define LWIP_DHCP6_MAX_NTP_SERVERS 1 +#define LWIP_DHCP6_MAX_DNS_SERVERS DNS_MAX_SERVERS + +/* TODO: check hooks */ + +#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL +#define LWIP_DBG_TYPES_ON LWIP_DBG_ON +#define ETHARP_DEBUG LWIP_DBG_ON +#define NETIF_DEBUG LWIP_DBG_OFF +#define PBUF_DEBUG LWIP_DBG_OFF +#define API_LIB_DEBUG LWIP_DBG_OFF +#define API_MSG_DEBUG LWIP_DBG_OFF +#define SOCKETS_DEBUG LWIP_DBG_OFF +#define ICMP_DEBUG LWIP_DBG_ON +#define IGMP_DEBUG LWIP_DBG_OFF +#define INET_DEBUG LWIP_DBG_OFF +#define IP_DEBUG LWIP_DBG_ON +#define IP_REASS_DEBUG LWIP_DBG_OFF +#define RAW_DEBUG LWIP_DBG_OFF +#define MEM_DEBUG LWIP_DBG_OFF +#define MEMP_DEBUG LWIP_DBG_OFF +#define SYS_DEBUG LWIP_DBG_OFF +#define TIMERS_DEBUG LWIP_DBG_OFF +#define TCP_DEBUG LWIP_DBG_OFF +#define TCP_INPUT_DEBUG LWIP_DBG_OFF +#define TCP_FR_DEBUG LWIP_DBG_OFF +#define TCP_RTO_DEBUG LWIP_DBG_OFF +#define TCP_CWND_DEBUG LWIP_DBG_OFF +#define TCP_WND_DEBUG LWIP_DBG_OFF +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF +#define TCP_RST_DEBUG LWIP_DBG_OFF +#define TCP_QLEN_DEBUG LWIP_DBG_OFF +#define UDP_DEBUG LWIP_DBG_OFF +#define TCPIP_DEBUG LWIP_DBG_OFF +#define SLIP_DEBUG LWIP_DBG_OFF +#define DHCP_DEBUG LWIP_DBG_OFF +#define AUTOIP_DEBUG LWIP_DBG_OFF +#define DNS_DEBUG LWIP_DBG_OFF +#define IP6_DEBUG LWIP_DBG_OFF +#define DHCP6_DEBUG LWIP_DBG_OFF +#define LWIP_TESTMODE 0 + +#define LWIP_PERF 0 diff --git a/libraries/drivers/lwip_port/renesas/sys_arch.c b/libraries/drivers/lwip_port/renesas/sys_arch.c new file mode 100644 index 000000000..0fc1f27bc --- /dev/null +++ b/libraries/drivers/lwip_port/renesas/sys_arch.c @@ -0,0 +1,645 @@ +#include "lwip/sys.h" +#include "arch/sys_arch.h" +#include "tpl_os.h" +#include + +#define MS_PER_TICKS 10 +extern VAR(uint32, OS_VAR) tpl_time_counter; +extern CONST(tpl_proc_id, AUTOMATIC) INVALID_TASK; + +static int hexval(char c) { + if (c >= '0' && c <= '9') + return c - '0'; + else if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return 0; +} + +/* This is needed because "netif.c" uses it and without this implementation + * this would cause LIBC to be included and that's something we don't want. */ +int atoi(const char *num) { + long value = 0; + int neg = 0; + + if (num[0] == '0' && num[1] == 'x') { + // hex + num += 2; + while (*num && isxdigit((unsigned char) *num)) + value = value * 16 + hexval(*num++); + } else { + // decimal + if (num[0] == '-') { + neg = 1; + num++; + } + while (*num && *num >= '0' && *num <= '9') + value = value * 10 + *num++ - '0'; + } + if (neg) + value = -value; + return value; +} + +#if !NO_SYS + +struct sys_mbox_msg { + struct sys_mbox_msg *next; + void *msg; +}; + +#define SYS_MBOX_SIZE 128 + +struct sys_mbox { + int used; + int first, last; + void *msgs[SYS_MBOX_SIZE]; + struct sys_sem *not_empty; + struct sys_sem *not_full; + struct sys_sem *mutex; + int wait_send; +}; + +struct sys_mbox sys_mbox_list[MAX_NB_MBOX]; + +#define UNLOCKED 0 +#define LOCKED 1 + +int waiting_task[TASK_COUNT]; + +struct sys_mutex { + int used; + int locked; +}; + +struct sys_mutex sys_mutex_list[MAX_NB_MUTEX]; + +struct sys_sem { + int used; + unsigned int c; + struct sys_mutex * mutex; +}; + +struct sys_sem sys_sem_list[MAX_NB_SEM]; + + +struct sys_thread { + int dummy; +}; + +static struct sys_sem *sys_sem_new_internal(u8_t count); + +/* Threads */ +int debug_printf(const char *format, ...); + +lwip_thread_fn threadPtr = NULL; + +TASK(tcpip_task) { + threadPtr(NULL); + TerminateTask(); +} + +sys_thread_t sys_thread_new(const char *name, lwip_thread_fn function, void *arg, int stacksize, int prio) +{ + if(!strcmp(TCPIP_THREAD_NAME,name)) { + threadPtr = function; + ActivateTask(tcpip_task); + } else { + debug_printf("Task %s was not defined\n\r", name); + } + + return NULL; + } + +#if LWIP_TCPIP_CORE_LOCKING +TaskType lwip_core_lock_holder_task_id; +extern sys_mutex_t lock_tcpip_core; + +void sys_lock_tcpip_core(void) +{ + sys_mutex_lock(&lock_tcpip_core); + GetTaskID(&lwip_core_lock_holder_task_id); +} + +void sys_unlock_tcpip_core(void) +{ + lwip_core_lock_holder_task_id = INVALID_TASK; + sys_mutex_unlock(&lock_tcpip_core); +} +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +TaskType lwip_tcpip_task_id; +void sys_mark_tcpip_thread(void) +{ + GetTaskID(&lwip_tcpip_task_id); +} + +void sys_check_core_locking(void) +{ + /* Embedded systems should check we are NOT in an interrupt context here */ + + if (lwip_tcpip_task_id != INVALID_TASK) { + TaskType current_task_id; + GetTaskID(¤t_task_id); + +#if LWIP_TCPIP_CORE_LOCKING + LWIP_ASSERT("Function called without core lock", current_task_id == lwip_core_lock_holder_task_id); +#else /* LWIP_TCPIP_CORE_LOCKING */ +// LWIP_ASSERT("Function called from wrong task", current_task_id == lwip_tcpip_task_id); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + } +} + +/*-----------------------------------------------------------------------------------*/ +/* Mailbox */ +err_t sys_mbox_new(struct sys_mbox **mb, int size) +{ + int i; + LWIP_ASSERT("mbox != NULL", mb != NULL); + LWIP_ASSERT("size > 0", size > 0); + + if (size > SYS_MBOX_SIZE) { + return ERR_MEM; + } + + for(i=0; i< MAX_NB_MBOX; i++) { + if(!sys_mbox_list[i].used) { + break; + } + } + + if(i == MAX_NB_MBOX) { + LWIP_PLATFORM_DIAG(("no more available mbox")); + return ERR_MEM; + } + + sys_mbox_list[i].used = 1; + sys_mbox_list[i].first = sys_mbox_list[i].last = 0; + sys_mbox_list[i].not_empty = sys_sem_new_internal(0); + sys_mbox_list[i].not_full = sys_sem_new_internal(0); + sys_mbox_list[i].mutex = sys_sem_new_internal(1); + sys_mbox_list[i].wait_send = 0; + + //SYS_STATS_INC_USED(mbox); + *mb = &sys_mbox_list[i]; + return ERR_OK; +} + +void sys_mbox_free(struct sys_mbox **mb) +{ + LWIP_ASSERT("mbox != NULL", mb != NULL); + LWIP_ASSERT("*mbox != SYS_MBOX_NULL", *mb != SYS_MBOX_NULL); + + struct sys_mbox *mbox = *mb; + //SYS_STATS_DEC(mbox); + sys_arch_sem_wait(&mbox->mutex, 0); + + sys_sem_free(&mbox->not_empty); + sys_sem_free(&mbox->not_full); + sys_sem_free(&mbox->mutex); + mbox->not_empty = mbox->not_full = mbox->mutex = NULL; + + mbox->used = 0; +} + +err_t +sys_mbox_trypost(struct sys_mbox **mb, void *msg) +{ + u8_t first; + struct sys_mbox *mbox; + LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL)); + mbox = *mb; + + sys_arch_sem_wait(&mbox->mutex, 0); + + LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_trypost: mbox %p msg %p\n", + (void *)mbox, (void *)msg)); + + if ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) { + sys_sem_signal(&mbox->mutex); + return ERR_MEM; + } + + mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg; + + if (mbox->last == mbox->first) { + first = 1; + } else { + first = 0; + } + + mbox->last++; + + if (first) { + sys_sem_signal(&mbox->not_empty); + } + + sys_sem_signal(&mbox->mutex); + + return ERR_OK; +} + +err_t +sys_mbox_trypost_fromisr(sys_mbox_t *q, void *msg) +{ + return sys_mbox_trypost(q, msg); +} + +void sys_mbox_post(struct sys_mbox **mb, void *msg) +{ + u8_t first; + struct sys_mbox *mbox; + LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL)); + mbox = *mb; + + sys_arch_sem_wait(&mbox->mutex, 0); + + LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_post: mbox %p msg %p\n", (void *)mbox, (void *)msg)); + + while ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) { + mbox->wait_send++; + sys_sem_signal(&mbox->mutex); + sys_arch_sem_wait(&mbox->not_full, 0); + sys_arch_sem_wait(&mbox->mutex, 0); + mbox->wait_send--; + } + + mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg; + + if (mbox->last == mbox->first) { + first = 1; + } else { + first = 0; + } + + mbox->last++; + + if (first) { + sys_sem_signal(&mbox->not_empty); + } + + sys_sem_signal(&mbox->mutex); +} + +u32_t sys_arch_mbox_tryfetch(struct sys_mbox **mb, void **msg) +{ + struct sys_mbox *mbox; + LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL)); + mbox = *mb; + + sys_arch_sem_wait(&mbox->mutex, 0); + + if (mbox->first == mbox->last) { + sys_sem_signal(&mbox->mutex); + return SYS_MBOX_EMPTY; + } + + if (msg != NULL) { + LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p msg %p\n", (void *)mbox, *msg)); + *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE]; + } + else{ + LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p, null msg\n", (void *)mbox)); + } + + mbox->first++; + + if (mbox->wait_send) { + sys_sem_signal(&mbox->not_full); + } + + sys_sem_signal(&mbox->mutex); + + return 0; +} + +u32_t sys_arch_mbox_fetch(struct sys_mbox **mb, void **msg, u32_t timeout) +{ + u32_t time_needed = 0; + struct sys_mbox *mbox; + LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL)); + mbox = *mb; + + /* The mutex lock is quick so we don't bother with the timeout + stuff here. */ + sys_arch_sem_wait(&mbox->mutex, 0); + + while (mbox->first == mbox->last) { + sys_sem_signal(&mbox->mutex); + + /* We block while waiting for a mail to arrive in the mailbox. We + must be prepared to timeout. */ + if (timeout != 0) { + time_needed = sys_arch_sem_wait(&mbox->not_empty, timeout); + + if (time_needed == SYS_ARCH_TIMEOUT) { + return SYS_ARCH_TIMEOUT; + } + } else { + sys_arch_sem_wait(&mbox->not_empty, 0); + } + + sys_arch_sem_wait(&mbox->mutex, 0); + } + + if (msg != NULL) { + LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p msg %p\n", (void *)mbox, *msg)); + *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE]; + } + else{ + LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p, null msg\n", (void *)mbox)); + } + + mbox->first++; + + if (mbox->wait_send) { + sys_sem_signal(&mbox->not_full); + } + + sys_sem_signal(&mbox->mutex); + + return time_needed; +} + +/* + * Don't use tpl_disable_all_interrupts_service() and + * tpl_enable_all_interrupts_service() because several + * functions like 'GetTaskID()' can't be called while + * interrupt disabled + */ +void disable_interrupts() { + __asm__ volatile ("CPSID IF"); /* Disable interrupts */ + //DisableAllInterrupts(); +} + +void enable_interrupts() { + __asm__ volatile ("CPSIE IF"); /* Enable interrupts */ + //EnableAllInterrupts(); +} + +void wait_synchro(void) { + TaskType curr_task; + GetTaskID(&curr_task); + LWIP_ASSERT("invalid task id", (curr_taskmutex); + + //SYS_STATS_DEC(sem); + sem->used = 0; +} + +void sys_sem_signal(sys_sem_t *s) +{ + struct sys_sem *sem; + LWIP_ASSERT("invalid sem", (s != NULL) && (*s != NULL)); + sem = *s; + + sys_mutex_lock(&(sem->mutex)); + sem->c++; + + if (sem->c > 1) { + sem->c = 1; + } + + sys_mutex_unlock(&(sem->mutex)); +} + + +u32_t sys_arch_sem_wait(sys_sem_t *s, u32_t timeout_ms) +{ + u32_t time_needed = 0; + struct sys_sem *sem; + LWIP_ASSERT("invalid sem", (s != NULL) && (*s != NULL)); + sem = *s; + + sys_mutex_lock(&(sem->mutex)); + if (timeout_ms > 0) { + u32_t star_ms = sys_now(); + while ((sem->c <= 0) && (sys_now() < star_ms + timeout_ms)) { + sys_mutex_unlock(&(sem->mutex)); + sys_schedule(); + sys_mutex_lock(&(sem->mutex)); + } + + if (sem->c <= 0) { + sys_mutex_unlock(&(sem->mutex)); + return SYS_ARCH_TIMEOUT; + } + } else { + while (sem->c <= 0) { + sys_mutex_unlock(&(sem->mutex)); + sys_schedule(); + sys_mutex_lock(&(sem->mutex)); + } + } + + sem->c--; + sys_mutex_unlock(&(sem->mutex)); + return (u32_t)time_needed; +} +/*-----------------------------------------------------------------------------------*/ +/* Mutex */ +/** Create a new mutex + * @param mutex pointer to the mutex to create + * @return a new mutex */ + +err_t +sys_mutex_new(struct sys_mutex **mutex) +{ + int i; + + disable_interrupts(); + + for(i=0; i< MAX_NB_MUTEX; i++) { + if(!sys_mutex_list[i].used) { + break; + } + } + + if(i == MAX_NB_MUTEX) { + LWIP_PLATFORM_DIAG(("no more available mutex")); + enable_interrupts(); + return ERR_MEM; + } + + sys_mutex_list[i].used = 1; + sys_mutex_list[i].locked = UNLOCKED; + + *mutex = &sys_mutex_list[i]; + + enable_interrupts(); + + return ERR_OK; +} + +/** Lock a mutex + * @param mutex the mutex to lock */ +void +sys_mutex_lock(struct sys_mutex **mutex) +{ + struct sys_mutex *mtx; + + disable_interrupts(); + mtx = *mutex; + + while(mtx->locked == LOCKED) { + enable_interrupts(); + + wait_synchro(); + + disable_interrupts(); + } + + mtx->locked = LOCKED; + + enable_interrupts(); +} + +/** Unlock a mutex + * @param mutex the mutex to unlock */ +void +sys_mutex_unlock(struct sys_mutex **mutex) +{ + struct sys_mutex *mtx; + + disable_interrupts(); + mtx = *mutex; + mtx->locked = UNLOCKED; + enable_interrupts(); + + wakeup_waiting_tasks(); +} + +/** Delete a mutex + * @param mutex the mutex to delete */ +void +sys_mutex_free(struct sys_mutex **mutex) +{ + struct sys_mutex *mtx; + + disable_interrupts(); + mtx = *mutex; + mtx->used = 0; + enable_interrupts(); +} + +#endif /* !NO_SYS */ + +/* Time */ +u32_t sys_now(void) { +#if !NO_SYS + return tpl_time_counter * MS_PER_TICKS; +#else + return 0; +#endif +} + +/* Init */ +void sys_init(void) +{ +#if !NO_SYS + int i; + + for(i = 0; i < TASK_COUNT; i++) { + waiting_task[i] = 0; + } + + for(i = 0; i < MAX_NB_MUTEX; i++) { + sys_mutex_list[i].used = 0; + } + + for(i = 0; i < MAX_NB_SEM; i++) { + sys_sem_list[i].used = 0; + } + + for(i = 0; i < MAX_NB_MBOX; i++) { + sys_mbox_list[i].used = 0; + } +#endif /* !NO_SYS */ +} + +#if SYS_LIGHTWEIGHT_PROT + +sys_prot_t +sys_arch_protect(void) +{ + return 0; +} + +void +sys_arch_unprotect(sys_prot_t pval) +{ +} + +#endif /* SYS_LIGHTWEIGHT_PROT */ diff --git a/libraries/drivers/serial/renesas/printf.c b/libraries/drivers/serial/renesas/printf.c new file mode 100644 index 000000000..b8e3a6693 --- /dev/null +++ b/libraries/drivers/serial/renesas/printf.c @@ -0,0 +1,188 @@ +/* + Copyright 2001-2021 Georges Menie + https://www.menie.org/georges/embedded/small_printf_source_code.html + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "printf.h" +#include "spider_serial.h" + +static void printchar(char **str, int c) +{ + if (str) { + **str = c; + ++(*str); + } else { + Serial_Tx(c); + } +} + +#define PAD_RIGHT 1 +#define PAD_ZERO 2 + +static int prints(char **out, const char *string, int width, int pad) +{ + register int pc = 0, padchar = ' '; + + if (width > 0) { + register int len = 0; + register const char *ptr; + for (ptr = string; *ptr; ++ptr) ++len; + if (len >= width) width = 0; + else width -= len; + if (pad & PAD_ZERO) padchar = '0'; + } + if (!(pad & PAD_RIGHT)) { + for ( ; width > 0; --width) { + printchar (out, padchar); + ++pc; + } + } + for ( ; *string ; ++string) { + printchar (out, *string); + ++pc; + } + for ( ; width > 0; --width) { + printchar (out, padchar); + ++pc; + } + + return pc; +} + +/* the following should be enough for 32 bit int */ +#define PRINT_BUF_LEN 12 + +static int printi(char **out, int i, int b, int sg, int width, int pad, int letbase) +{ + char print_buf[PRINT_BUF_LEN]; + register char *s; + register int t, neg = 0, pc = 0; + register unsigned int u = i; + + if (i == 0) { + print_buf[0] = '0'; + print_buf[1] = '\0'; + return prints (out, print_buf, width, pad); + } + + if (sg && b == 10 && i < 0) { + neg = 1; + u = -i; + } + + s = print_buf + PRINT_BUF_LEN-1; + *s = '\0'; + + while (u) { + t = u % b; + if( t >= 10 ) + t += letbase - '0' - 10; + *--s = t + '0'; + u /= b; + } + + if (neg) { + if( width && (pad & PAD_ZERO) ) { + printchar (out, '-'); + ++pc; + --width; + } + else { + *--s = '-'; + } + } + + return pc + prints (out, s, width, pad); +} + +static int print(char **out, int *varg) +{ + register int width, pad; + register int pc = 0; + register char *format = (char *)(*varg++); + char scr[2]; + + for (; *format != 0; ++format) { + if (*format == '%') { + ++format; + width = pad = 0; + if (*format == '\0') break; + if (*format == '%') goto out; + if (*format == '-') { + ++format; + pad = PAD_RIGHT; + } + while (*format == '0') { + ++format; + pad |= PAD_ZERO; + } + for ( ; *format >= '0' && *format <= '9'; ++format) { + width *= 10; + width += *format - '0'; + } + if( *format == 's' ) { + register char *s = *((char **)varg++); + pc += prints (out, s?s:"(null)", width, pad); + continue; + } + if( *format == 'd' ) { + pc += printi (out, *varg++, 10, 1, width, pad, 'a'); + continue; + } + if( *format == 'x' ) { + pc += printi (out, *varg++, 16, 0, width, pad, 'a'); + continue; + } + if( *format == 'X' ) { + pc += printi (out, *varg++, 16, 0, width, pad, 'A'); + continue; + } + if( *format == 'u' ) { + pc += printi (out, *varg++, 10, 0, width, pad, 'a'); + continue; + } + if( *format == 'c' ) { + /* char are converted to int then pushed on the stack */ + scr[0] = *varg++; + scr[1] = '\0'; + pc += prints (out, scr, width, pad); + continue; + } + } + else { + out: + printchar (out, *format); + ++pc; + } + } + if (out) **out = '\0'; + return pc; +} + +/* assuming sizeof(void *) == sizeof(int) */ + +int debug_printf(const char *format, ...) +{ + register int *varg = (int *)(&format); + return print(0, varg); +} + +int debug_sprintf(char *out, const char *format, ...) +{ + register int *varg = (int *)(&format); + return print(&out, varg); +} \ No newline at end of file diff --git a/libraries/drivers/serial/renesas/printf.h b/libraries/drivers/serial/renesas/printf.h new file mode 100644 index 000000000..aea99a835 --- /dev/null +++ b/libraries/drivers/serial/renesas/printf.h @@ -0,0 +1,7 @@ +#ifndef __PRINTF_H__ +#define __PRINTF_H__ + +int debug_printf(const char *format, ...); +int debug_sprintf(char *out, const char *format, ...); + +#endif diff --git a/libraries/drivers/serial/renesas/spider_serial.c b/libraries/drivers/serial/renesas/spider_serial.c new file mode 100644 index 000000000..e56b5765c --- /dev/null +++ b/libraries/drivers/serial/renesas/spider_serial.c @@ -0,0 +1,90 @@ +#include "spider_serial.h" + +uint32 Serial_Init(void) +{ + volatile uint8 wait_cmpt; + + /* Clear bits TE and RE in HSSCR to 0 */ + SERIAL_SCR = SERIAL_SCR_INT_VALUE; + + /* Set bits TFRST and RFRST in FCR to 1 */ + SERIAL_FCR |= SERIAL_FCR_TFRST_MASK | SERIAL_FCR_RFRS_MASK; + + /* Clear flags ER, DR, BRK, and RDF in FSR */ + SERIAL_FSR = SERIAL_FSR_INIT_VALUE; + + /* Clear TO and ORER in LSR,*/ + SERIAL_LSR = SERIAL_LSR_INIT_VALUE; + + /* Set bits CKE[1:0] in SCR (leaving other bits cleared to 0) */ + SERIAL_SCR = (SERIAL_SCR & ~SERIAL_SCR_CKE_MASK) | SERIAL_SCR_CKE_INIT_VALUE; + + /* Set data transfer format in HSSMR ( 8 bits, no parity, 1 stop bit, async) */ + SERIAL_SMR = SERIAL_SMR_INIT_VALUE; + + /* Baud rate setting */ + SERIAL_BRR = SERIAL_BAUDRATE; + +#if (SERIAL_BASE_ADDR == SCIF_BASE_ADDR) + /* SCIF module used */ + SERIAL_DL = SERIAL_DL_SETTING_VALUE; + SERIAL_CKS &= ~(SERIAL_CKS_DIV_MASK | SERIAL_CKS_XIN_MASK); +#else + /* HSCIF module used */ + /* Sampling rate 8 */ + SERIAL_SRR = SERIAL_SRR_VAL; +#endif + + for (wait_cmpt = 0; wait_cmpt < 100; wait_cmpt++) + { + } + + /* reset-off, tx-fifo, rx-fifo */ + SERIAL_FCR = SERIAL_FCR_INIT_VALUE; + + /* Enable TE and RE bits*/ + SERIAL_SCR |= SERIAL_SCR_TE_MASK | SERIAL_SCR_RE_MASK; + + return 1; +} + +void Serial_Tx_Wait(void) +{ + /* Wait until TX FIFO is empty */ + do + { + } while ((SERIAL_FSR & SERIAL_TX_DONE) != SERIAL_TX_DONE); +} + +uint32 Serial_Tx(uint8 data) +{ + Serial_Tx_Wait(); + + /* Fill FTDR register with data to send */ + SERIAL_FTDR = data; + + /* Clear TX status bits */ + SERIAL_FSR &= ~SERIAL_TX_DONE; + + return 1; +} + +uint8 Serial_Rx(uint8* data) +{ + /* Check if data available */ + if((SERIAL_FSR & SERIAL_FSR_RDF_MASK) != SERIAL_FSR_RDF_MASK) + return 0; + + /* Check Data Ready and no break, timeout, overrun nor receive errors */ + if (((SERIAL_FSR & SERIAL_RX_READY) != 0) || (SERIAL_LSR != 0)) + return 2; + + /* Get rx data */ + *data = SERIAL_FRDR; + /* Send back data */ + Serial_Tx(*data); + /* Clear RDF flag */ + SERIAL_FSR &= ~SERIAL_FSR_RDF_MASK; + + return 1; +} diff --git a/libraries/drivers/serial/renesas/spider_serial.h b/libraries/drivers/serial/renesas/spider_serial.h new file mode 100644 index 000000000..a32563166 --- /dev/null +++ b/libraries/drivers/serial/renesas/spider_serial.h @@ -0,0 +1,95 @@ +#ifndef SERIAL_H +#define SERIAL_H + +#include "tpl_os.h" + +/* SCIF3 */ +#define SCIF_BASE_ADDR 0xE6C50000 + +/* HSCIF0 */ +#define HSCIF_BASE_ADDR 0xE6540000 + +/* BRR computing: + * HSBRR: Register value = Internal clock / ( Sr * 2^(2*n + 1) * B) * 10^6 -1 + * SCBRR: Register value = PCK / ( 64 * 2^(2*n - 1) * B) * 10^6 -1 + * + * with: + * - PCK: Peripheral module operating frequency (MHz) + * - B: Baudrate + * - Sr: Sampling rate (8 to 32) + * - n: Baudrate generator clock (0 to 3) + * + * In our case: Internal clock = 266, Sr = 8, PCK = 66 and n = 0 + */ +#define HSBRR_1843200BPS (uint8)(0x08U) +#define HSBRR_921600BPS (uint8)(0x11U) +#define SCBRR_115200BPS (uint8)(0x11U) + +/* A proper #define must be used between: SCIF_115200BPS, HSCIF_921600BPS and HSCIF_1843200BPS */ +#if defined SCIF_115200BPS +#define SERIAL_BASE_ADDR SCIF_BASE_ADDR +#define SERIAL_BAUDRATE SCBRR_115200BPS +#elif defined HSCIF_921600BPS +#define SERIAL_BASE_ADDR HSCIF_BASE_ADDR +#define SERIAL_BAUDRATE HSBRR_921600BPS +#elif defined HSCIF_1843200BPS +#define SERIAL_BASE_ADDR HSCIF_BASE_ADDR +#define SERIAL_BAUDRATE HSBRR_1843200BPS +#else +#error "No baudrate defined for serial communication" +#endif + +#define SERIAL_SMR (*(volatile uint16 *)(SERIAL_BASE_ADDR + 0x00)) +#define SERIAL_BRR (*(volatile uint8 *)(SERIAL_BASE_ADDR + 0x04)) +#define SERIAL_SCR (*(volatile uint16 *)(SERIAL_BASE_ADDR + 0x08)) +#define SERIAL_FTDR (*(volatile uint8 *)(SERIAL_BASE_ADDR + 0x0C)) +#define SERIAL_FSR (*(volatile uint16 *)(SERIAL_BASE_ADDR + 0x10)) +#define SERIAL_FRDR (*(volatile uint8 *)(SERIAL_BASE_ADDR + 0x14)) +#define SERIAL_FCR (*(volatile uint16 *)(SERIAL_BASE_ADDR + 0x18)) +#define SERIAL_FDR (*(volatile uint16 *)(SERIAL_BASE_ADDR + 0x1C)) +#define SERIAL_SPTR (*(volatile uint16 *)(SERIAL_BASE_ADDR + 0x20)) +#define SERIAL_LSR (*(volatile uint16 *)(SERIAL_BASE_ADDR + 0x24)) +#define SERIAL_DL (*(volatile uint16 *)(SERIAL_BASE_ADDR + 0x30)) /* Only used by SCIF */ +#define SERIAL_CKS (*(volatile uint16 *)(SERIAL_BASE_ADDR + 0x34)) /* Only used by SCIF */ +#define SERIAL_SRR (*(volatile uint16 *)(SERIAL_BASE_ADDR + 0x40)) /* Only used by HSCIF */ + +#define SERIAL_SMR_INIT_VALUE (0x0000U) + +#define SERIAL_SCR_INT_VALUE (0x0000U) +#define SERIAL_SCR_CKE_MASK (3U << 0) +#define SERIAL_SCR_CKE_BRG_VALUE (0x0002U) +#define SERIAL_SCR_CKE_INIT_VALUE (0x0000U) +#define SERIAL_SCR_RE_MASK (1U << 4) +#define SERIAL_SCR_TE_MASK (1U << 5) + +#define SERIAL_FSR_INIT_VALUE (0x0000U) +#define SERIAL_FSR_DR_MASK (1U << 0) +#define SERIAL_FSR_RDF_MASK (1U << 1) +#define SERIAL_FSR_BRK_MASK (1U << 4) +#define SERIAL_FSR_TDFE_MASK (1U << 5) +#define SERIAL_FSR_TEND_MASK (1U << 6) +#define SERIAL_FSR_ER_MASK (1U << 7) +#define SERIAL_RX_READY (SERIAL_FSR_DR_MASK | SERIAL_FSR_BRK_MASK | SERIAL_FSR_ER_MASK) +#define SERIAL_TX_DONE (SERIAL_FSR_TDFE_MASK | SERIAL_FSR_TEND_MASK) + +#define SERIAL_FCR_INIT_VALUE (0x0000U) +#define SERIAL_FCR_TFRST_MASK (1U << 2) +#define SERIAL_FCR_RFRS_MASK (1U << 1) + +#define SERIAL_LSR_INIT_VALUE (0x0000U) + +#define SERIAL_DL_SETTING_VALUE (0x0008U) + +#define SERIAL_CKS_DIV_MASK (1U << 15) +#define SERIAL_CKS_XIN_MASK (1U << 14) + +#define SERIAL_SRR_SRE (1U << 15) +#define SERIAL_SRR_SRCYC8 (7U << 0) +#define SERIAL_SRR_VAL (SERIAL_SRR_SRE | SERIAL_SRR_SRCYC8) + +uint32 Serial_Init(void); +void Serial_Tx_Wait(void); +uint32 Serial_Tx(uint8 data); +uint8 Serial_Rx(uint8* data); + +#endif diff --git a/libraries/net/ethernet/lwip b/libraries/net/ethernet/lwip new file mode 160000 index 000000000..84fde1ebb --- /dev/null +++ b/libraries/net/ethernet/lwip @@ -0,0 +1 @@ +Subproject commit 84fde1ebbfe35b3125fc2d89b8a456cbacf148e9