From 877541d79dca3627e596fa604be212b3d933f4d8 Mon Sep 17 00:00:00 2001 From: cyliangtw Date: Mon, 7 Mar 2022 18:44:23 +0800 Subject: [PATCH] Add M460 EMAC driver --- .../TARGET_M460/CMakeLists.txt | 14 + .../TARGET_M460/m460_eth.c | 670 ++++ .../TARGET_M460/m460_eth.h | 91 + .../TARGET_M460/synopGMAC_Dev.c | 2947 +++++++++++++++++ .../TARGET_M460/synopGMAC_Dev.h | 1500 +++++++++ .../TARGET_M460/synopGMAC_network_interface.c | 942 ++++++ .../TARGET_M460/synopGMAC_network_interface.h | 63 + .../TARGET_M460/synopGMAC_plat.h | 183 + 8 files changed, 6410 insertions(+) create mode 100644 connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/CMakeLists.txt create mode 100644 connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/m460_eth.c create mode 100644 connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/m460_eth.h create mode 100644 connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/synopGMAC_Dev.c create mode 100644 connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/synopGMAC_Dev.h create mode 100644 connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/synopGMAC_network_interface.c create mode 100644 connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/synopGMAC_network_interface.h create mode 100644 connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/synopGMAC_plat.h diff --git a/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/CMakeLists.txt b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/CMakeLists.txt new file mode 100644 index 0000000000..222154cab7 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/CMakeLists.txt @@ -0,0 +1,14 @@ +# Copyright (c) 2020 ARM Limited. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +target_include_directories(mbed-emac + INTERFACE + . +) + +target_sources(mbed-emac + INTERFACE + m460_eth.c + synopGMAC_Dev.c + synopGMAC_network_interface.c +) diff --git a/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/m460_eth.c b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/m460_eth.c new file mode 100644 index 0000000000..d9e3bd0468 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/m460_eth.c @@ -0,0 +1,670 @@ +/* + * Copyright (c) 2022 Nuvoton Technology Corp. + * Copyright (c) 2022 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Description: M460 MAC driver source file + */ +//#include +#include "m460_eth.h" +#include "mbed_toolchain.h" +//#define NU_TRACE +#include "numaker_eth_hal.h" + +#include "synopGMAC_network_interface.h" + +#ifdef NU_TRACE_ISR +#define NU_RAW_Debug(x) { mbed_error_printf x; } +#else +#define NU_RAW_Debug(x) +#endif + +#define NU_M460_INTF 0 // Device EMAC Interface port +#define NU_M460_RMII_PIN_GRP 0 // Device EMAC RMII pin group 0 or 1 + +extern synopGMACdevice GMACdev[GMAC_CNT]; +extern struct sk_buff tx_buf[GMAC_CNT][TRANSMIT_DESC_SIZE]; +extern struct sk_buff rx_buf[GMAC_CNT][RECEIVE_DESC_SIZE]; + +eth_callback_t nu_eth_txrx_cb = NULL; +void *nu_userData = NULL; + +extern void ack_emac_rx_isr(void); + +void plat_delay(uint32_t delay) +{ + volatile uint32_t loop = delay*200; + while (loop--); +} + +static void mdio_write(int addr, int reg, int data) +{ + synopGMACdevice *gmacdev = &GMACdev[NU_M460_INTF]; + synopGMAC_write_phy_reg(gmacdev->MacBase, addr, reg, data); +} + +static int mdio_read(int addr, int reg) +{ + synopGMACdevice *gmacdev = &GMACdev[NU_M460_INTF]; + uint16_t data; + synopGMAC_read_phy_reg(gmacdev->MacBase, addr, reg, &data); + return data; +} + + +static int reset_phy(void) +{ + + uint16_t reg; + uint32_t delayCnt; + int retVal = 0; + synopGMACdevice *gmacdev = &GMACdev[NU_M460_INTF]; + + mdio_write(CONFIG_PHY_ADDR, MII_BMCR, BMCR_RESET); + + delayCnt = 2000; + while (delayCnt > 0) { + delayCnt--; + if ((mdio_read(CONFIG_PHY_ADDR, MII_BMCR) & BMCR_RESET) == 0) { + break; + } + } + + if (delayCnt == 0) { + NU_DEBUGF(("Reset phy failed\n")); + return (-1); + } + + delayCnt = 200000; + while (delayCnt > 0) { + delayCnt--; + if (numaker_eth_link_ok()) { + gmacdev->LinkState = LINKUP; + NU_DEBUGF(("Link Up\n")); + break; + } + } + if (delayCnt == 0) { + gmacdev->LinkState = LINKDOWN; + NU_DEBUGF(("Link Down\n")); + return (-1); + } + + mdio_write(CONFIG_PHY_ADDR, MII_ADVERTISE, ADVERTISE_CSMA | + ADVERTISE_10HALF | + ADVERTISE_10FULL | + ADVERTISE_100HALF | + ADVERTISE_100FULL); + + reg = mdio_read(CONFIG_PHY_ADDR, MII_BMCR); + mdio_write(CONFIG_PHY_ADDR, MII_BMCR, reg | BMCR_ANRESTART); + + delayCnt = 200000; + while (delayCnt > 0) { + delayCnt--; + if ((mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) + == (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) { + break; + } + } + + if( delayCnt == 0 ) { + NU_DEBUGF(("AN failed. Set to 100 FULL\n")); + synopGMAC_set_full_duplex(gmacdev); + synopGMAC_set_mode(NU_M460_INTF, 1); // Set mode 1: 100Mbps; 2: 10Mbps + return (-1); + } else { + reg = mdio_read(CONFIG_PHY_ADDR, MII_LPA); + if (reg & ADVERTISE_100FULL) { + NU_DEBUGF(("100 full\n")); + gmacdev->DuplexMode = FULLDUPLEX; + gmacdev->Speed = SPEED100; + synopGMAC_set_full_duplex(gmacdev); + synopGMAC_set_mode(NU_M460_INTF, 1); // Set mode 1: 100Mbps; 2: 10Mbps + } else if (reg & ADVERTISE_100HALF) { + NU_DEBUGF(("100 half\n")); + gmacdev->DuplexMode = HALFDUPLEX; + gmacdev->Speed = SPEED100; + synopGMAC_set_half_duplex(gmacdev); + synopGMAC_set_mode(NU_M460_INTF, 1); // Set mode 1: 100Mbps; 2: 10Mbps + } else if (reg & ADVERTISE_10FULL) { + NU_DEBUGF(("10 full\n")); + gmacdev->DuplexMode = FULLDUPLEX; + gmacdev->Speed = SPEED10; + synopGMAC_set_full_duplex(gmacdev); + synopGMAC_set_mode(NU_M460_INTF, 2); // Set mode 1: 100Mbps; 2: 10Mbps + } else { + NU_DEBUGF(("10 half\n")); + gmacdev->DuplexMode = HALFDUPLEX; + gmacdev->Speed = SPEED10; + synopGMAC_set_half_duplex(gmacdev); + synopGMAC_set_mode(NU_M460_INTF, 2); // Set mode 1: 100Mbps; 2: 10Mbps + } + } + + printf("PHY ID 1:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID1)); + printf("PHY ID 2:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID2)); + + return (retVal); + +} + + +void numaker_set_mac_addr(uint8_t *addr) +{ + + synopGMAC_set_mac_address(NU_M460_INTF, addr); + +} + +static void __set_mac_pins(uint32_t group) +{ + if(group == 0) + { + SET_EMAC0_RMII_MDC_PE8(); + SET_EMAC0_RMII_MDIO_PE9(); + SET_EMAC0_RMII_TXD0_PE10(); + SET_EMAC0_RMII_TXD1_PE11(); + SET_EMAC0_RMII_TXEN_PE12(); + SET_EMAC0_RMII_REFCLK_PC8(); + SET_EMAC0_RMII_RXD0_PC7(); + SET_EMAC0_RMII_RXD1_PC6(); + SET_EMAC0_RMII_CRSDV_PA7(); + SET_EMAC0_RMII_RXERR_PA6(); + + SET_EMAC0_PPS_PB6(); + } + else + { + SET_EMAC0_RMII_MDC_PB11(); + SET_EMAC0_RMII_MDIO_PB10(); + SET_EMAC0_RMII_TXD0_PB9(); + SET_EMAC0_RMII_TXD1_PB8(); + SET_EMAC0_RMII_TXEN_PB7(); + SET_EMAC0_RMII_REFCLK_PB5(); + SET_EMAC0_RMII_RXD0_PB4(); + SET_EMAC0_RMII_RXD1_PB3(); + SET_EMAC0_RMII_CRSDV_PB2(); + SET_EMAC0_RMII_RXERR_PB1(); + + SET_EMAC0_PPS_PE13(); + } +} + +static void __eth_clk_pin_init() +{ + /* Unlock protected registers */ + SYS_UnlockReg(); + + /* Enable IP clock */ + CLK_EnableModuleClock(EMAC0_MODULE); + + // Configure MDC clock rate + + /* Update System Core Clock */ + SystemCoreClockUpdate(); + + /*---------------------------------------------------------------------------------------------------------*/ + /* Init I/O Multi-function */ + /*---------------------------------------------------------------------------------------------------------*/ + // Configure RMII pins + __set_mac_pins(NU_M460_RMII_PIN_GRP); + + /* Lock protected registers */ + SYS_LockReg(); + +} + +void numaker_eth_init(uint8_t *mac_addr) +{ + int status = 0; + int retval = 0; + int i; + uint32_t offload_needed = 0; + uint32_t dma_addr; + struct sk_buff *skb; + synopGMACdevice *gmacdev = &GMACdev[NU_M460_INTF]; + + NVIC_DisableIRQ(EMAC0_TXRX_IRQn); + /* init CLK & pins */ + __eth_clk_pin_init(); + + /*Attach the device to MAC struct This will configure all the required base addresses + such as Mac base, configuration base, phy base address(out of 32 possible phys )*/ + synopGMAC_attach(gmacdev, GMAC0MappedAddr + MACBASE, GMAC0MappedAddr + DMABASE, DEFAULT_PHY_BASE); + + // Reset MAC + synopGMAC_reset(gmacdev); + gmacdev->Intf = NU_M460_INTF; + synopGMAC_read_version(gmacdev); + + /*Check for Phy initialization*/ + synopGMAC_set_mdc_clk_div(gmacdev,GmiiCsrClk5); + gmacdev->ClockDivMdc = synopGMAC_get_mdc_clk_div(gmacdev); + + /*Reset PHY*/ + //status = synopGMAC_check_phy_init(gmacdev); + status = reset_phy(); + + /*Set up the tx and rx descriptor queue/ring*/ + synopGMAC_setup_tx_desc_queue(gmacdev,TRANSMIT_DESC_SIZE, RINGMODE); + synopGMAC_init_tx_desc_base(gmacdev); //Program the transmit descriptor base address in to DmaTxBase addr + + synopGMAC_setup_rx_desc_queue(gmacdev,RECEIVE_DESC_SIZE, RINGMODE); + synopGMAC_init_rx_desc_base(gmacdev); //Program the transmit descriptor base address in to DmaTxBase addr + + /*Initialize the dma interface*/ + synopGMAC_dma_bus_mode_init(gmacdev, DmaBurstLength32 | DmaDescriptorSkip0/*DmaDescriptorSkip2*/ | DmaDescriptor8Words ); synopGMAC_dma_control_init(gmacdev,DmaStoreAndForward |DmaTxSecondFrame|DmaRxThreshCtrl128); + + /*Initialize the mac interface*/ + synopGMAC_mac_init(gmacdev); + synopGMAC_promisc_enable(gmacdev); + + synopGMAC_pause_control(gmacdev); // This enables the pause control in Full duplex mode of operation + +#if defined(NU_USING_HW_CHECKSUM) + /*IPC Checksum offloading is enabled for this driver. Should only be used if Full Ip checksumm offload engine is configured in the hardware*/ + offload_needed = 1; + synopGMAC_enable_rx_chksum_offload(gmacdev); //Enable the offload engine in the receive path + synopGMAC_rx_tcpip_chksum_drop_enable(gmacdev); // This is default configuration, DMA drops the packets if error in encapsulated ethernet payload +#endif + + for(i = 0; i < RECEIVE_DESC_SIZE; i ++) { + skb = &rx_buf[NU_M460_INTF][i]; + synopGMAC_set_rx_qptr(gmacdev, (u32)((u64)(skb->data) & 0xFFFFFFFF), sizeof(skb->data), (u32)((u64)skb & 0xFFFFFFFF)); + } + + for(i = 0; i < TRANSMIT_DESC_SIZE; i ++) { + skb = &tx_buf[NU_M460_INTF][i]; + synopGMAC_set_tx_qptr(gmacdev, (u32)((u64)(skb->data) & 0xFFFFFFFF), sizeof(skb->data), (u32)((u64)skb & 0xFFFFFFFF), offload_needed ,0); + } + + numaker_set_mac_addr(mac_addr); // need to reconfigure hardware address 'cos we just RESET emc... + + synopGMAC_clear_interrupt(gmacdev); + + synopGMAC_enable_interrupt(gmacdev,DmaIntEnable); + synopGMAC_enable_dma_rx(gmacdev); + synopGMAC_enable_dma_tx(gmacdev); + + synopGMAC_tx_enable(gmacdev); + synopGMAC_rx_enable(gmacdev); + NVIC_EnableIRQ(EMAC0_TXRX_IRQn); +} + + + +void ETH_halt(void) +{ + synopGMACdevice *gmacdev = &GMACdev[NU_M460_INTF]; + + synopGMAC_tx_disable(gmacdev); + synopGMAC_rx_disable(gmacdev); +} + +unsigned int m_status; + +/*---------------------------------------------------------------------------- + EMAC IRQ Handler + *----------------------------------------------------------------------------*/ +void EMAC0_IRQHandler(void) +{ + synopGMACdevice * gmacdev = &GMACdev[0]; + uint32_t interrupt,dma_status_reg, mac_status_reg; + int status; + uint32_t dma_addr; + + // Check GMAC interrupt + mac_status_reg = synopGMACReadReg((u32 *)gmacdev->MacBase, GmacInterruptStatus); + if(mac_status_reg & GmacTSIntSts) { + gmacdev->synopGMACNetStats.ts_int = 1; + status = synopGMACReadReg((u32 *)gmacdev->MacBase, GmacTSStatus); + if(!(status & (1 << 1))) { + NU_RAW_Debug(("TS alarm flag not set??\n")); + } else { + NU_RAW_Debug(("TS alarm!!!!!!!!!!!!!!!!\n")); + } + } + if(mac_status_reg & GmacLPIIntSts) { + //NU_RAW_Debug("LPI\n"); + //LPIStsChange = 1; + //LPIReg = synopGMACReadReg((u32 *)gmacdev->MacBase, GmacLPICtrlSts); + ; + } + if(mac_status_reg & GmacRgmiiIntSts) { + uint32_t volatile reg; + reg = synopGMACReadReg((u32 *)gmacdev->MacBase, GmacRgmiiCtrlSts); + + } + synopGMACWriteReg((u32 *)gmacdev->MacBase, GmacInterruptStatus ,mac_status_reg); + + /*Read the Dma interrupt status to know whether the interrupt got generated by our device or not*/ + dma_status_reg = synopGMACReadReg((u32 *)gmacdev->DmaBase, DmaStatus); + NU_RAW_Debug(("i %08x %08x\n", mac_status_reg, dma_status_reg)); + + if(dma_status_reg == 0) + return; + + synopGMAC_disable_interrupt_all(gmacdev); + + NU_RAW_Debug(("%s:Dma Status Reg: 0x%08x\n",__FUNCTION__,dma_status_reg)); + + if(dma_status_reg & GmacPmtIntr) { + NU_RAW_Debug(("%s:: Interrupt due to PMT module\n",__FUNCTION__)); + synopGMAC_powerup_mac(gmacdev); + } + + if(dma_status_reg & GmacLineIntfIntr) { + NU_RAW_Debug(("%s:: Interrupt due to GMAC LINE module\n",__FUNCTION__)); + } + + /*Now lets handle the DMA interrupts*/ + interrupt = synopGMAC_get_interrupt_type(gmacdev); + NU_RAW_Debug(("%s:Interrupts to be handled: 0x%08x\n",__FUNCTION__,interrupt)); + + if(interrupt & synopGMACDmaError) { + uint8_t hwaddr[6]; + mbed_mac_address((char *)hwaddr); + NU_RAW_Debug(("%s::Fatal Bus Error Interrupt Seen\n",__FUNCTION__)); + synopGMAC_disable_dma_tx(gmacdev); + synopGMAC_disable_dma_rx(gmacdev); + + synopGMAC_take_desc_ownership_tx(gmacdev); + synopGMAC_take_desc_ownership_rx(gmacdev); + + synopGMAC_init_tx_rx_desc_queue(gmacdev); + + synopGMAC_reset(gmacdev);//reset the DMA engine and the GMAC ip + synopGMAC_set_mac_address(NU_M460_INTF, (uint8_t*)hwaddr); + synopGMAC_dma_bus_mode_init(gmacdev,DmaFixedBurstEnable| DmaBurstLength8 | DmaDescriptorSkip0/*DmaDescriptorSkip2*/ ); + synopGMAC_dma_control_init(gmacdev,DmaStoreAndForward); + synopGMAC_init_rx_desc_base(gmacdev); + synopGMAC_init_tx_desc_base(gmacdev); + synopGMAC_mac_init(gmacdev); + synopGMAC_enable_dma_rx(gmacdev); + synopGMAC_enable_dma_tx(gmacdev); + + } + + if(interrupt & synopGMACDmaRxNormal) { + //NU_RAW_Debug(("rx\n")); + NU_RAW_Debug(("%s:: Rx Normal \r\n", __FUNCTION__)); + // to handle received data + if (nu_eth_txrx_cb != NULL) { + nu_eth_txrx_cb('R', nu_userData); + } + } + + if(interrupt & synopGMACDmaRxAbnormal) { + mbed_error_printf("%s::Abnormal Rx Interrupt Seen \r\n",__FUNCTION__); + gmacdev->synopGMACNetStats.rx_over_errors++; + if(gmacdev->GMAC_Power_down == 0) { // If Mac is not in powerdown + synopGMAC_resume_dma_rx(gmacdev);//To handle GBPS with 12 descriptors + } + } + + if(interrupt & synopGMACDmaRxStopped) { + mbed_error_printf("%s::Receiver stopped seeing Rx interrupts \r\n",__FUNCTION__); //Receiver gone in to stopped state + if(gmacdev->GMAC_Power_down == 0) { // If Mac is not in powerdown + gmacdev->synopGMACNetStats.rx_over_errors++; + synopGMAC_enable_dma_rx(gmacdev); + } + } + + if(interrupt & synopGMACDmaTxNormal) { + //NU_RAW_Debug(("rx\n")); + //xmit function has done its job + NU_RAW_Debug(("%s::Finished Normal Transmission \n",__FUNCTION__)); + synop_handle_transmit_over(0);//Do whatever you want after the transmission is over + if (nu_eth_txrx_cb != NULL) { + nu_eth_txrx_cb('T', nu_userData); + } + } + + if(interrupt & synopGMACDmaTxAbnormal) { + mbed_error_printf("%s::Abnormal Tx Interrupt Seen\n",__FUNCTION__); + if(gmacdev->GMAC_Power_down == 0) { // If Mac is not in powerdown + synop_handle_transmit_over(0); + if (nu_eth_txrx_cb != NULL) { + nu_eth_txrx_cb('T', nu_userData); + } + } + } + + if(interrupt & synopGMACDmaTxStopped) { + mbed_error_printf("%s::Transmitter stopped sending the packets\n",__FUNCTION__); + if(gmacdev->GMAC_Power_down == 0) { // If Mac is not in powerdown + synopGMAC_disable_dma_tx(gmacdev); + synopGMAC_take_desc_ownership_tx(gmacdev); + + synopGMAC_enable_dma_tx(gmacdev); + mbed_error_printf("%s::Transmission Resumed\n",__FUNCTION__); + } + } + + /* Enable the interrupt before returning from ISR*/ +// if( !(interrupt & synopGMACDmaRxNormal)) { /* RxNormal will enable INT in numaker_eth_trigger_rx */ + synopGMAC_enable_interrupt(gmacdev,DmaIntEnable); +// } + return; +} + +static void dump_desc(DmaDesc *desc) +{ +#if 1 + NU_DEBUGF(("###--- %s... Desc[0x%08x] status[0x%08x] ---###\r\n", __FUNCTION__, desc, desc->status)); + synopGMACdevice *gmacdev = &GMACdev[NU_M460_INTF]; + DmaDesc *tmp_desc; +#endif +#if 0 + int i=0; + for ( i=0; i< RECEIVE_DESC_SIZE; i++ ) { + tmp_desc = gmacdev->RxDesc + i; + NU_DEBUGF(("### RX %s... desc[0x%08x] status[0x%08x] length[0x%08x] buffer1[0x%08x] buffer2[0x%08x]\r\n", + __FUNCTION__, tmp_desc, tmp_desc->status, tmp_desc->length, tmp_desc->buffer1, tmp_desc->buffer2)); + //NU_DEBUGF(("### %s... length[0x%x]\r\n", __FUNCTION__, desc->length)); + //NU_DEBUGF(("### %s... buffer1[0x%x]\r\n", __FUNCTION__, desc->buffer1)); + //NU_DEBUGF(("### %s... buffer2[0x%x]\r\n", __FUNCTION__, desc->buffer2)); + } + for ( i=0; i< TRANSMIT_DESC_SIZE; i++ ) { + tmp_desc = gmacdev->TxDesc + i; + NU_DEBUGF(("### TX %s... desc[0x%08x] status[0x%08x] length[0x%08x] buffer1[0x%08x] buffer2[0x%08x]\r\n", + __FUNCTION__, tmp_desc, tmp_desc->status, tmp_desc->length, tmp_desc->buffer1, tmp_desc->buffer2)); + } +#endif +} + +void numaker_eth_trigger_rx(void) +{ + synopGMACdevice *gmacdev = &GMACdev[NU_M460_INTF]; + NU_DEBUGF(("=== %s... ---Start---\r\n", __FUNCTION__)); + dump_desc(gmacdev->RxBusyDesc); + /* Enable the interrupt */ + synopGMAC_enable_interrupt(gmacdev,DmaIntEnable); + /* Trigger RX DMA */ + synopGMAC_enable_dma_rx(gmacdev); + synopGMAC_resume_dma_rx(gmacdev); + NU_DEBUGF(("%s... resume RX DMA\r\n", __FUNCTION__)); + NU_DEBUGF(("=== %s... ---End---\r\n", __FUNCTION__)); +} + +int numaker_eth_get_rx_buf(uint16_t *len, uint8_t **buf) +{ + + synopGMACdevice *gmacdev = &GMACdev[NU_M460_INTF]; + NU_DEBUGF(("=== %s... ---Start---\r\n", __FUNCTION__)); + DmaDesc * rxdesc = gmacdev->RxBusyDesc; + dump_desc(rxdesc); + if(synopGMAC_is_desc_owned_by_dma(rxdesc)) + return -1; + if(synopGMAC_is_desc_empty(rxdesc)) + return -1; + +// synopGMAC_disable_dma_rx(gmacdev); // it will encounter DMA interrupt status as "Receiver stopped seeing Rx interrupts" + *len = synop_handle_received_data(NU_M460_INTF, buf); + dump_desc(gmacdev->RxBusyDesc); + if( *len <= 0 ) return -1; /* No available RX frame */ + + // length of payload should be <= 1514 + if (*len > (NU_ETH_MAX_FLEN - 4)) { + NU_DEBUGF(("%s... unexpected long packet length=%d, buf=0x%x\r\n", __FUNCTION__, *len, *buf)); + *len = 0; // Skip this unexpected long packet + } + NU_DEBUGF(("=== %s... ---End---\r\n", __FUNCTION__)); + return 0; +} + +void numaker_eth_rx_next(void) +{ + NU_DEBUGF(("=== %s... ---Start---\r\n", __FUNCTION__)); + /* Already did in synop_handle_received_data */ + /* No-op at this stage */ +#if 0 + synopGMACdevice *gmacdev = &GMACdev[NU_M460_INTF]; + DmaDesc * rxdesc = (gmacdev->RxBusyDesc - 1); + + rxdesc->status = DescOwnByDma; +#endif + +} + +uint8_t *numaker_eth_get_tx_buf(void) +{ + synopGMACdevice *gmacdev = &GMACdev[NU_M460_INTF]; + DmaDesc * txdesc = gmacdev->TxNextDesc; + + if(!synopGMAC_is_desc_empty(txdesc)) { + return (NULL); + } + + if (synopGMAC_is_desc_owned_by_dma(txdesc)) + { + return (NULL); + } else { + dump_desc(txdesc); + return (txdesc->buffer1); + } + +} + +void numaker_eth_trigger_tx(uint16_t length, void *p) +{ + synopGMACdevice *gmacdev = &GMACdev[NU_M460_INTF]; + DmaDesc * txdesc = gmacdev->TxNextDesc; + uint32_t txnext = gmacdev->TxNext; +#if defined(NU_USING_HW_CHECKSUM) + uint32_t offload_needed = 1; +#else + uint32_t offload_needed = 0; +#endif + + (gmacdev->BusyTxDesc)++; //busy tx descriptor is incremented by one as it will be handed over to DMA + txdesc->length |= ((length <status |= (DescTxFirst | DescTxLast | DescTxIntEnable ); //ENH_DESC + + if(offload_needed) { + /* + Make sure that the OS you are running supports the IP and TCP checksum offloading, + before calling any of the functions given below. + */ + synopGMAC_tx_checksum_offload_tcp_pseudo(gmacdev, txdesc); + } else { + synopGMAC_tx_checksum_offload_bypass(gmacdev, txdesc); + } + __DSB(); + txdesc->status |= DescOwnByDma;//ENH_DESC + + gmacdev->TxNext = synopGMAC_is_last_tx_desc(gmacdev,txdesc) ? 0 : txnext + 1; + gmacdev->TxNextDesc = synopGMAC_is_last_tx_desc(gmacdev,txdesc) ? gmacdev->TxDesc : (txdesc + 1); + + /* Enable the interrupt */ + synopGMAC_enable_interrupt(gmacdev,DmaIntEnable); + /* Trigger TX DMA */ + synopGMAC_resume_dma_tx(gmacdev); +// synopGMAC_enable_dma_tx(gmacdev); + +} + +int numaker_eth_link_ok(void) +{ + /* first, a dummy read to latch */ + mdio_read(CONFIG_PHY_ADDR, MII_BMSR); + if (mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & BMSR_LSTATUS) { + return 1; + } + return 0; +} + +void numaker_eth_set_cb(eth_callback_t eth_cb, void *userData) +{ + nu_eth_txrx_cb = eth_cb; + nu_userData = userData; +} + +// Override mbed_mac_address of mbed_interface.c to provide ethernet devices with a semi-unique MAC address +void mbed_mac_address(char *mac) +{ + uint32_t uID1; + // Fetch word 0 + uint32_t word0 = *(uint32_t *)0xFF804; // 2KB Data Flash at 0xFF800 + // Fetch word 1 + // we only want bottom 16 bits of word1 (MAC bits 32-47) + // and bit 9 forced to 1, bit 8 forced to 0 + // Locally administered MAC, reduced conflicts + // http://en.wikipedia.org/wiki/MAC_address + uint32_t word1 = *(uint32_t *)0xFF800; // 2KB Data Flash at 0xFF800 + + if (word0 == 0xFFFFFFFF) { // Not burn any mac address at 1st 2 words of Data Flash + // with a semi-unique MAC address from the UUID + /* Enable FMC ISP function */ + SYS_UnlockReg(); + FMC_Open(); + // = FMC_ReadUID(0); + uID1 = FMC_ReadUID(1); + word1 = (uID1 & 0x003FFFFF) | ((uID1 & 0x030000) << 6) >> 8; + word0 = ((FMC_ReadUID(0) >> 4) << 20) | ((uID1 & 0xFF) << 12) | (FMC_ReadUID(2) & 0xFFF); + /* Disable FMC ISP function */ + FMC_Close(); + /* Lock protected registers */ + SYS_LockReg(); + } + + word1 |= 0x00000200; + word1 &= 0x0000FEFF; + + mac[0] = (word1 & 0x0000ff00) >> 8; + mac[1] = (word1 & 0x000000ff); + mac[2] = (word0 & 0xff000000) >> 24; + mac[3] = (word0 & 0x00ff0000) >> 16; + mac[4] = (word0 & 0x0000ff00) >> 8; + mac[5] = (word0 & 0x000000ff); + + NU_DEBUGF(("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])); +} + +void numaker_eth_enable_interrupts(void) +{ + synopGMACdevice *gmacdev = &GMACdev[NU_M460_INTF]; + + /* Enable the interrupt */ + synopGMAC_enable_interrupt(gmacdev,DmaIntEnable); + + NVIC_EnableIRQ(EMAC0_TXRX_IRQn); +} + +void numaker_eth_disable_interrupts(void) +{ + NVIC_DisableIRQ(EMAC0_TXRX_IRQn); +} diff --git a/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/m460_eth.h b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/m460_eth.h new file mode 100644 index 0000000000..2850a8e955 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/m460_eth.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2022 Nuvoton Technology Corp. + * Copyright (c) 2022 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Description: M460 EMAC driver header file + */ + +#include "numaker_emac_config.h" +#include "M460.h" +#ifndef _M460_ETH_ +#define _M460_ETH_ + +/* Generic MII registers. */ + +#define MII_BMCR 0x00 /* Basic mode control register */ +#define MII_BMSR 0x01 /* Basic mode status register */ +#define MII_PHYSID1 0x02 /* PHYS ID 1 */ +#define MII_PHYSID2 0x03 /* PHYS ID 2 */ +#define MII_ADVERTISE 0x04 /* Advertisement control reg */ +#define MII_LPA 0x05 /* Link partner ability reg */ +#define MII_EXPANSION 0x06 /* Expansion register */ +#define MII_DCOUNTER 0x12 /* Disconnect counter */ +#define MII_FCSCOUNTER 0x13 /* False carrier counter */ +#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */ +#define MII_RERRCOUNTER 0x15 /* Receive error counter */ +#define MII_SREVISION 0x16 /* Silicon revision */ +#define MII_RESV1 0x17 /* Reserved... */ +#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */ +#define MII_PHYADDR 0x19 /* PHY address */ +#define MII_RESV2 0x1a /* Reserved... */ +#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */ +#define MII_NCONFIG 0x1c /* Network interface config */ + +/* Basic mode control register. */ +#define BMCR_RESV 0x007f /* Unused... */ +#define BMCR_CTST 0x0080 /* Collision test */ +#define BMCR_FULLDPLX 0x0100 /* Full duplex */ +#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */ +#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */ +#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */ +#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */ +#define BMCR_SPEED100 0x2000 /* Select 100Mbps */ +#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */ +#define BMCR_RESET 0x8000 /* Reset the DP83840 */ + +/* Basic mode status register. */ +#define BMSR_ERCAP 0x0001 /* Ext-reg capability */ +#define BMSR_JCD 0x0002 /* Jabber detected */ +#define BMSR_LSTATUS 0x0004 /* Link status */ +#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */ +#define BMSR_RFAULT 0x0010 /* Remote fault detected */ +#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */ +#define BMSR_RESV 0x07c0 /* Unused... */ +#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */ +#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */ +#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */ +#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */ +#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */ + +/* Advertisement control register. */ +#define ADVERTISE_SLCT 0x001f /* Selector bits */ +#define ADVERTISE_CSMA 0x0001 /* Only selector supported */ +#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */ +#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */ +#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */ +#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */ +#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */ +#define ADVERTISE_RESV 0x1c00 /* Unused... */ +#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */ +#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */ +#define ADVERTISE_NPAGE 0x8000 /* Next page bit */ + +#define PACKET_BUFFER_SIZE ( NU_ETH_MAX_FLEN + ((NU_ETH_MAX_FLEN%4) ? (4 - (NU_ETH_MAX_FLEN%4)) : 0) ) //For DMA 4 bytes alignment + +#define CONFIG_PHY_ADDR 1 + + +#endif /* _M460_ETH_ */ diff --git a/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/synopGMAC_Dev.c b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/synopGMAC_Dev.c new file mode 100644 index 0000000000..11a8e9ef99 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/synopGMAC_Dev.c @@ -0,0 +1,2947 @@ +/* =================================================================================== + * Copyright (c) <2009> Synopsys, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software annotated with this license and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without + * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * =================================================================================== */ + +/** \file + * This file defines the synopsys GMAC device dependent functions. + * Most of the operations on the GMAC device are available in this file. + * Functions for initiliasing and accessing MAC/DMA/PHY registers and the DMA descriptors + * are encapsulated in this file. The functions are platform/host/OS independent. + * These functions in turn use the low level device dependent (HAL) functions to + * access the register space. + * \internal + * ------------------------REVISION HISTORY--------------------------------- + * Synopsys 01/Aug/2007 Created + */ +#include +#include "synopGMAC_Dev.h" +#include "synopGMAC_network_interface.h" + +/** + * Function to set the MDC clock for mdio transactiona + * + * @param[in] pointer to device structure. + * @param[in] clk divider value. + * \return Reuturns 0 on success else return the error value. + */ +s32 synopGMAC_set_mdc_clk_div(synopGMACdevice *gmacdev,u32 clk_div_val) +{ + u32 orig_data; + orig_data = synopGMACReadReg((u32 *)gmacdev->MacBase,GmacGmiiAddr); //set the mdc clock to the user defined value + orig_data &= (~ GmiiCsrClkMask); + orig_data |= clk_div_val; + synopGMACWriteReg((u32 *)gmacdev->MacBase, GmacGmiiAddr ,orig_data); + return 0; +} + +/** + * Returns the current MDC divider value programmed in the ip. + * + * @param[in] pointer to device structure. + * @param[in] clk divider value. + * \return Returns the MDC divider value read. + */ +u32 synopGMAC_get_mdc_clk_div(synopGMACdevice *gmacdev) +{ + u32 data; + data = synopGMACReadReg((u32 *)gmacdev->MacBase,GmacGmiiAddr); + data &= GmiiCsrClkMask; + return data; +} + + + +/** + * Function to read the Phy register. The access to phy register + * is a slow process as the data is moved accross MDI/MDO interface + * @param[in] pointer to Register Base (It is the mac base in our case) . + * @param[in] PhyBase register is the index of one of supported 32 PHY devices. + * @param[in] Register offset is the index of one of the 32 phy register. + * @param[out] u16 data read from the respective phy register (only valid iff return value is 0). + * \return Returns 0 on success else return the error status. + */ +s32 synopGMAC_read_phy_reg(u32 *RegBase,u32 PhyBase, u32 RegOffset, u16 * data) +{ + u32 addr; + u32 loop_variable; + addr = ((PhyBase << GmiiDevShift) & GmiiDevMask) | ((RegOffset << GmiiRegShift) & GmiiRegMask); + addr = addr | GmiiCsrClk0 | GmiiBusy ; //Gmii busy bit + + synopGMACWriteReg(RegBase,GmacGmiiAddr,addr); //write the address from where the data to be read in GmiiGmiiAddr register of synopGMAC ip + + for(loop_variable = 0; loop_variable < DEFAULT_LOOP_VARIABLE; loop_variable++) { //Wait till the busy bit gets cleared with in a certain amount of time + if (!(synopGMACReadReg(RegBase,GmacGmiiAddr) & GmiiBusy)) { + break; + } + plat_delay(DEFAULT_DELAY_VARIABLE); + } + if(loop_variable < DEFAULT_LOOP_VARIABLE) + * data = (u16)(synopGMACReadReg(RegBase,GmacGmiiData) & 0xFFFF); + else { + TR("Error::: PHY not responding Busy bit didnot get cleared !!!!!!\n"); + return -ESYNOPGMACPHYERR; + } + return 0; +} + +/** + * Function to write to the Phy register. The access to phy register + * is a slow process as the data is moved accross MDI/MDO interface + * @param[in] pointer to Register Base (It is the mac base in our case) . + * @param[in] PhyBase register is the index of one of supported 32 PHY devices. + * @param[in] Register offset is the index of one of the 32 phy register. + * @param[in] data to be written to the respective phy register. + * \return Returns 0 on success else return the error status. + */ +s32 synopGMAC_write_phy_reg(u32 *RegBase, u32 PhyBase, u32 RegOffset, u16 data) +{ + u32 addr; + u32 loop_variable; + + synopGMACWriteReg(RegBase,GmacGmiiData,data); // write the data in to GmacGmiiData register of synopGMAC ip + + addr = ((PhyBase << GmiiDevShift) & GmiiDevMask) | ((RegOffset << GmiiRegShift) & GmiiRegMask) | GmiiWrite; + + addr = addr | GmiiCsrClk0 | GmiiBusy ; //set Gmii clk to 20-35 Mhz and Gmii busy bit + + synopGMACWriteReg(RegBase,GmacGmiiAddr,addr); + for(loop_variable = 0; loop_variable < DEFAULT_LOOP_VARIABLE; loop_variable++) { + if (!(synopGMACReadReg(RegBase,GmacGmiiAddr) & GmiiBusy)) { + break; + } + plat_delay(DEFAULT_DELAY_VARIABLE); + } + + if(loop_variable < DEFAULT_LOOP_VARIABLE) { + return 0; + } else { + TR("Error::: PHY not responding Busy bit didnot get cleared !!!!!!\n"); + return -ESYNOPGMACPHYERR; + } +} + +/** + * Function to configure the phy in loopback mode. + * + * @param[in] pointer to synopGMACdevice. + * @param[in] enable or disable the loopback. + * \return 0 on success else return the error status. + * \note Don't get confused with mac loop-back synopGMAC_loopback_on(synopGMACdevice *) + * and synopGMAC_loopback_off(synopGMACdevice *) functions. + */ +s32 synopGMAC_phy_loopback(synopGMACdevice *gmacdev, bool loopback) +{ + s32 status = 0; +#ifndef EMULATION + if(loopback) + status = synopGMAC_write_phy_reg((u32 *)gmacdev->MacBase, gmacdev->PhyBase, PHY_CONTROL_REG, Mii_Loopback); + else + status = synopGMAC_write_phy_reg((u32 *)gmacdev->MacBase, gmacdev->PhyBase, PHY_CONTROL_REG, Mii_NoLoopback); +#endif + return status; +} + + + +/** + * Function to read the GMAC IP Version and populates the same in device data structure. + * @param[in] pointer to synopGMACdevice. + * \return Always return 0. + */ + +s32 synopGMAC_read_version (synopGMACdevice * gmacdev) +{ + u32 data = 0; + data = synopGMACReadReg((u32 *)gmacdev->MacBase, GmacVersion ); + gmacdev->Version = data; + TR("The data read from %08x is %08x\n",(gmacdev->MacBase+GmacVersion),data); + return 0; +} + + +/** + * Function to reset the GMAC core. + * This reests the DMA and GMAC core. After reset all the registers holds their respective reset value + * @param[in] pointer to synopGMACdevice. + * \return 0 on success else return the error status. + */ + +s32 synopGMAC_reset (synopGMACdevice * gmacdev ) +{ + u32 data = 0; + synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaBusMode ,DmaResetOn); + plat_delay(DEFAULT_LOOP_VARIABLE); + + do { + data = synopGMACReadReg((u32 *)gmacdev->DmaBase, DmaBusMode); + }while(data & 1); + + TR("DATA after Reset = %08x\n",data); + + return 0; +} + +s32 synopGMAC_reset_nocheck (synopGMACdevice * gmacdev ) +{ + u32 data = 0; + synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaBusMode ,DmaResetOn); + plat_delay(DEFAULT_LOOP_VARIABLE); + + TR("DATA after Reset = %08x\n",data); + + return 0; +} + +/** + * Function to program DMA bus mode register. + * + * The Bus Mode register is programmed with the value given. The bits to be set are + * bit wise or'ed and sent as the second argument to this function. + * @param[in] pointer to synopGMACdevice. + * @param[in] the data to be programmed. + * \return 0 on success else return the error status. + */ +s32 synopGMAC_dma_bus_mode_init(synopGMACdevice * gmacdev, u32 init_value ) +{ + synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaBusMode ,init_value); + return 0; + +} + +/** + * Function to program DMA Control register. + * + * The Dma Control register is programmed with the value given. The bits to be set are + * bit wise or'ed and sent as the second argument to this function. + * @param[in] pointer to synopGMACdevice. + * @param[in] the data to be programmed. + * \return 0 on success else return the error status. + */ +s32 synopGMAC_dma_control_init(synopGMACdevice * gmacdev, u32 init_value) +{ + synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaControl, init_value); + return 0; +} + + +/*Gmac configuration functions*/ + +/** + * Enable the watchdog timer on the receiver. + * When enabled, Gmac enables Watchdog timer, and GMAC allows no more than + * 2048 bytes of data (10,240 if Jumbo frame enabled). + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_wd_enable(synopGMACdevice * gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase, GmacConfig, GmacWatchdog); + return; +} +/** + * Disable the watchdog timer on the receiver. + * When disabled, Gmac disabled watchdog timer, and can receive frames up to + * 16,384 bytes. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_wd_disable(synopGMACdevice * gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacConfig, GmacWatchdog); + return; +} + +/** + * Enables the Jabber frame support. + * When enabled, GMAC disabled the jabber timer, and can transfer 16,384 byte frames. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_jab_enable(synopGMACdevice * gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacConfig, GmacJabber); + return; +} +/** + * Disables the Jabber frame support. + * When disabled, GMAC enables jabber timer. It cuts of transmitter if application + * sends more than 2048 bytes of data (10240 if Jumbo frame enabled). + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_jab_disable(synopGMACdevice * gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase, GmacConfig, GmacJabber); + return; +} + +/** + * Enables Frame bursting (Only in Half Duplex Mode). + * When enabled, GMAC allows frame bursting in GMII Half Duplex mode. + * Reserved in 10/100 and Full-Duplex configurations. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_frame_burst_enable(synopGMACdevice * gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacConfig, GmacFrameBurst); + return; +} +/** + * Disables Frame bursting. + * When Disabled, frame bursting is not supported. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_frame_burst_disable(synopGMACdevice * gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase, GmacConfig, GmacFrameBurst); + return; +} + +/** + * Enable Jumbo frame support. + * When Enabled GMAC supports jumbo frames of 9018/9022(VLAN tagged). + * Giant frame error is not reported in receive frame status. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_jumbo_frame_enable(synopGMACdevice * gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacConfig, GmacJumboFrame); + return; +} +/** + * Disable Jumbo frame support. + * When Disabled GMAC does not supports jumbo frames. + * Giant frame error is reported in receive frame status. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_jumbo_frame_disable(synopGMACdevice * gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase, GmacConfig, GmacJumboFrame); + return; +} + +/** + * Disable Carrier sense. + * When Disabled GMAC ignores CRS signal during frame transmission + * in half duplex mode. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ + +void synopGMAC_disable_crs(synopGMACdevice * gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacConfig, GmacDisableCrs); + return; +} + + + +/** + * Selects the GMII port. + * When called GMII (1000Mbps) port is selected (programmable only in 10/100/1000 Mbps configuration). + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_select_gmii(synopGMACdevice * gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase, GmacConfig, GmacMiiGmii); + return; +} +/** + * Selects the MII port. + * When called MII (10/100Mbps) port is selected (programmable only in 10/100/1000 Mbps configuration). + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_select_mii(synopGMACdevice * gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacConfig, GmacMiiGmii); + return; +} + +/** + * Enables Receive Own bit (Only in Half Duplex Mode). + * When enaled GMAC receives all the packets given by phy while transmitting. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_rx_own_enable(synopGMACdevice * gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase, GmacConfig, GmacRxOwn); + return; +} +/** + * Disables Receive Own bit (Only in Half Duplex Mode). + * When enaled GMAC disables the reception of frames when gmii_txen_o is asserted. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_rx_own_disable(synopGMACdevice * gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacConfig, GmacRxOwn); + return; +} + +/** + * Sets the GMAC in loopback mode. + * When on GMAC operates in loop-back mode at GMII/MII. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + * \note (G)MII Receive clock is required for loopback to work properly, as transmit clock is + * not looped back internally. + */ +void synopGMAC_loopback_on(synopGMACdevice * gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacConfig, GmacLoopback); + return; +} +/** + * Sets the GMAC in Normal mode. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_loopback_off(synopGMACdevice * gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase, GmacConfig, GmacLoopback); + return; +} + +/** + * Sets the GMAC core in Full-Duplex mode. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_set_full_duplex(synopGMACdevice * gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacConfig, GmacDuplex); + return; +} +/** + * Sets the GMAC core in Half-Duplex mode. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_set_half_duplex(synopGMACdevice * gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase, GmacConfig, GmacDuplex); + return; +} + +/** + * GMAC tries retransmission (Only in Half Duplex mode). + * If collision occurs on the GMII/MII, GMAC attempt retries based on the + * back off limit configured. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + * \note This function is tightly coupled with synopGMAC_back_off_limit(synopGMACdev *, u32). + */ +void synopGMAC_retry_enable(synopGMACdevice * gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase, GmacConfig, GmacRetry); + return; +} +/** + * GMAC tries only one transmission (Only in Half Duplex mode). + * If collision occurs on the GMII/MII, GMAC will ignore the current frami + * transmission and report a frame abort with excessive collision in tranmit frame status. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_retry_disable(synopGMACdevice * gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacConfig, GmacRetry); + return; +} + +/** + * GMAC strips the Pad/FCS field of incoming frames. + * This is true only if the length field value is less than or equal to + * 1500 bytes. All received frames with length field greater than or equal to + * 1501 bytes are passed to the application without stripping the Pad/FCS field. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_pad_crc_strip_enable(synopGMACdevice * gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacConfig, GmacPadCrcStrip); + return; +} +/** + * GMAC doesnot strips the Pad/FCS field of incoming frames. + * GMAC will pass all the incoming frames to Host unmodified. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_pad_crc_strip_disable(synopGMACdevice * gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase, GmacConfig, GmacPadCrcStrip); + return; +} +/** + * GMAC programmed with the back off limit value. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + * \note This function is tightly coupled with synopGMAC_retry_enable(synopGMACdevice * gmacdev) + */ +void synopGMAC_back_off_limit(synopGMACdevice * gmacdev, u32 value) +{ + u32 data; + data = synopGMACReadReg((u32 *)gmacdev->MacBase, GmacConfig); + data &= (~GmacBackoffLimit); + data |= value; + synopGMACWriteReg((u32 *)gmacdev->MacBase, GmacConfig,data); + return; +} + +/** + * Enables the Deferral check in GMAC (Only in Half Duplex mode) + * GMAC issues a Frame Abort Status, along with the excessive deferral error bit set in the + * transmit frame status when transmit state machine is deferred for more than + * - 24,288 bit times in 10/100Mbps mode + * - 155,680 bit times in 1000Mbps mode or Jumbo frame mode in 10/100Mbps operation. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + * \note Deferral begins when transmitter is ready to transmit, but is prevented because of + * an active CRS (carrier sense) + */ +void synopGMAC_deferral_check_enable(synopGMACdevice * gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacConfig, GmacDeferralCheck); + return; +} +/** + * Disables the Deferral check in GMAC (Only in Half Duplex mode). + * GMAC defers until the CRS signal goes inactive. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_deferral_check_disable(synopGMACdevice * gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase, GmacConfig, GmacDeferralCheck); + return; +} +/** + * Enable the reception of frames on GMII/MII. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_rx_enable(synopGMACdevice * gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacConfig, GmacRx); + return; +} +/** + * Disable the reception of frames on GMII/MII. + * GMAC receive state machine is disabled after completion of reception of current frame. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_rx_disable(synopGMACdevice * gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase, GmacConfig, GmacRx); + return; +} +/** + * Enable the transmission of frames on GMII/MII. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_tx_enable(synopGMACdevice * gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacConfig, GmacTx); + return; +} +/** + * Disable the transmission of frames on GMII/MII. + * GMAC transmit state machine is disabled after completion of transmission of current frame. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_tx_disable(synopGMACdevice * gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase, GmacConfig, GmacTx); + return; +} + + +/*Receive frame filter configuration functions*/ + +/** + * Enables reception of all the frames to application. + * GMAC passes all the frames received to application irrespective of whether they + * pass SA/DA address filtering or not. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_frame_filter_enable(synopGMACdevice * gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase, GmacFrameFilter, GmacFilter); + return; +} +/** + * Disables reception of all the frames to application. + * GMAC passes only those received frames to application which + * pass SA/DA address filtering. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_frame_filter_disable(synopGMACdevice * gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacFrameFilter, GmacFilter); + return; +} + +/** + * Populates the Hash High register with the data supplied. + * This function is called when the Hash filtering is to be enabled. + * @param[in] pointer to synopGMACdevice. + * @param[in] data to be written to hash table high register. + * \return void. + */ +void synopGMAC_write_hash_table_high(synopGMACdevice * gmacdev, u32 data) +{ + synopGMACWriteReg((u32 *)gmacdev->MacBase,GmacHashHigh,data); + return; +} + +/** + * Populates the Hash Low register with the data supplied. + * This function is called when the Hash filtering is to be enabled. + * @param[in] pointer to synopGMACdevice. + * @param[in] data to be written to hash table low register. + * \return void. + */ +void synopGMAC_write_hash_table_low(synopGMACdevice * gmacdev, u32 data) +{ + synopGMACWriteReg((u32 *)gmacdev->MacBase,GmacHashLow,data); + return; +} + +/** + * Enables Hash or Perfect filter (only if Hash filter is enabled in H/W). + * Only frames matching either perfect filtering or Hash Filtering as per HMC and HUC + * configuration are sent to application. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_hash_perfect_filter_enable(synopGMACdevice * gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacFrameFilter, GmacHashPerfectFilter); + return; +} + +/** + * Enables only Hash(only if Hash filter is enabled in H/W). + * Only frames matching Hash Filtering as per HMC and HUC + * configuration are sent to application. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_Hash_filter_only_enable(synopGMACdevice * gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacFrameFilter, GmacHashPerfectFilter); + return; +} + +/** + * Enables Source address filtering. + * When enabled source address filtering is performed. Only frames matching SA filtering are passed to application with + * SAMatch bit of RxStatus is set. GMAC drops failed frames. + * @param[in] pointer to synopGMACdevice. + * \return void. + * \note This function is overriden by synopGMAC_frame_filter_disable(synopGMACdevice *) + */ +void synopGMAC_src_addr_filter_enable(synopGMACdevice * gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacFrameFilter, GmacSrcAddrFilter); + return; +} +/** + * Disables Source address filtering. + * When disabled GMAC forwards the received frames with updated SAMatch bit in RxStatus. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_src_addr_filter_disable(synopGMACdevice * gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase, GmacFrameFilter, GmacSrcAddrFilter); + return; +} +/** + * Enables Inverse Destination address filtering. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_dst_addr_filter_inverse(synopGMACdevice * gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacFrameFilter, GmacDestAddrFilterNor); + return; +} +/** + * Enables the normal Destination address filtering. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_dst_addr_filter_normal(synopGMACdevice * gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase, GmacFrameFilter, GmacDestAddrFilterNor); + return; +} + +/** + * Enables forwarding of control frames. + * When set forwards all the control frames (incl. unicast and multicast PAUSE frames). + * @param[in] pointer to synopGMACdevice. + * \return void. + * \note Depends on RFE of FlowControlRegister[2] + */ +void synopGMAC_set_pass_control(synopGMACdevice * gmacdev,u32 passcontrol) +{ + u32 data; + data = synopGMACReadReg((u32 *)gmacdev->MacBase, GmacFrameFilter); + data &= (~GmacPassControl); + data |= passcontrol; + synopGMACWriteReg((u32 *)gmacdev->MacBase,GmacFrameFilter,data); + return; +} + +/** + * Enables Broadcast frames. + * When enabled Address filtering module passes all incoming broadcast frames. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_broadcast_enable(synopGMACdevice * gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase, GmacFrameFilter, GmacBroadcast); + return; +} +/** + * Disable Broadcast frames. + * When disabled Address filtering module filters all incoming broadcast frames. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_broadcast_disable(synopGMACdevice * gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacFrameFilter, GmacBroadcast); + return; +} + +/** + * Enables Multicast frames. + * When enabled all multicast frames are passed. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_multicast_enable(synopGMACdevice * gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacFrameFilter, GmacMulticastFilter); + return; +} +/** + * Disable Multicast frames. + * When disabled multicast frame filtering depends on HMC bit. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_multicast_disable(synopGMACdevice * gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase, GmacFrameFilter, GmacMulticastFilter); + return; +} + +/** + * Enables multicast hash filtering. + * When enabled GMAC performs teh destination address filtering according to the hash table. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_multicast_hash_filter_enable(synopGMACdevice * gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacFrameFilter, GmacMcastHashFilter); + return; +} +/** + * Disables multicast hash filtering. + * When disabled GMAC performs perfect destination address filtering for multicast frames, it compares + * DA field with the value programmed in DA register. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_multicast_hash_filter_disable(synopGMACdevice * gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase, GmacFrameFilter, GmacMcastHashFilter); + return; +} + +/** + * Enables promiscous mode. + * When enabled Address filter modules pass all incoming frames regardless of their Destination + * and source addresses. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_promisc_enable(synopGMACdevice * gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacFrameFilter, GmacPromiscuousMode); + return; +} +/** + * Clears promiscous mode. + * When called the GMAC falls back to normal operation from promiscous mode. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_promisc_disable(synopGMACdevice * gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase, GmacFrameFilter, GmacPromiscuousMode); + return; +} + + +/** + * Enables unicast hash filtering. + * When enabled GMAC performs the destination address filtering of unicast frames according to the hash table. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_unicast_hash_filter_enable(synopGMACdevice * gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacFrameFilter, GmacUcastHashFilter); + return; +} +/** + * Disables multicast hash filtering. + * When disabled GMAC performs perfect destination address filtering for unicast frames, it compares + * DA field with the value programmed in DA register. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_unicast_hash_filter_disable(synopGMACdevice * gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase, GmacFrameFilter, GmacUcastHashFilter); + return; +} + +/*Flow control configuration functions*/ + +/** + * Enables detection of pause frames with stations unicast address. + * When enabled GMAC detects the pause frames with stations unicast address in addition to the + * detection of pause frames with unique multicast address. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_unicast_pause_frame_detect_enable(synopGMACdevice * gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacFlowControl, GmacUnicastPauseFrame); + return; +} +/** + * Disables detection of pause frames with stations unicast address. + * When disabled GMAC only detects with the unique multicast address (802.3x). + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_unicast_pause_frame_detect_disable(synopGMACdevice * gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase, GmacFlowControl, GmacUnicastPauseFrame); + return; +} +/** + * Rx flow control enable. + * When Enabled GMAC will decode the rx pause frame and disable the tx for a specified time. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_rx_flow_control_enable(synopGMACdevice * gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacFlowControl, GmacRxFlowControl); + return; +} +/** + * Rx flow control disable. + * When disabled GMAC will not decode pause frame. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_rx_flow_control_disable(synopGMACdevice * gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase, GmacFlowControl, GmacRxFlowControl); + return; +} +/** + * Tx flow control enable. + * When Enabled + * - In full duplex GMAC enables flow control operation to transmit pause frames. + * - In Half duplex GMAC enables the back pressure operation + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_tx_flow_control_enable(synopGMACdevice * gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacFlowControl, GmacTxFlowControl); + return; +} + +/** + * Tx flow control disable. + * When Disabled + * - In full duplex GMAC will not transmit any pause frames. + * - In Half duplex GMAC disables the back pressure feature. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_tx_flow_control_disable(synopGMACdevice * gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase, GmacFlowControl, GmacTxFlowControl); + return; +} + +/** + * Initiate Flowcontrol operation. + * When Set + * - In full duplex GMAC initiates pause control frame. + * - In Half duplex GMAC initiates back pressure function. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_tx_activate_flow_control(synopGMACdevice * gmacdev) +{ + //In case of full duplex check for this bit to b'0. if it is read as b'1 indicates that + //control frame transmission is in progress. + if(gmacdev->Speed == FULLDUPLEX) { + if(!synopGMACCheckBits((u32 *)gmacdev->MacBase, GmacFlowControl, GmacFlowControlBackPressure)) + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacFlowControl, GmacFlowControlBackPressure); + } else { //if half duplex mode + + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacFlowControl, GmacFlowControlBackPressure); + } + + return; +} + +/** + * stops Flowcontrol operation. + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_tx_deactivate_flow_control(synopGMACdevice * gmacdev) +{ + //In full duplex this bit is automatically cleared after transmitting a pause control frame. + if(gmacdev->Speed == HALFDUPLEX) { + synopGMACSetBits((u32 *)gmacdev->MacBase, GmacFlowControl, GmacFlowControlBackPressure); + } + return; +} + +/** + * This enables the pause frame generation after programming the appropriate registers. + * presently activation is set at 3k and deactivation set at 4k. These may have to tweaked + * if found any issues + * @param[in] pointer to synopGMACdevice. + * \return void. + */ +void synopGMAC_pause_control(synopGMACdevice *gmacdev) +{ + u32 omr_reg; + u32 mac_flow_control_reg; + omr_reg = synopGMACReadReg((u32 *)gmacdev->DmaBase,DmaControl); + omr_reg |= DmaRxFlowCtrlAct4K | DmaRxFlowCtrlDeact5K |DmaEnHwFlowCtrl; + synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaControl, omr_reg); + + mac_flow_control_reg = synopGMACReadReg((u32 *)gmacdev->MacBase,GmacFlowControl); + mac_flow_control_reg |= GmacRxFlowControl | GmacTxFlowControl | 0xFFFF0000; + synopGMACWriteReg((u32 *)gmacdev->MacBase,GmacFlowControl,mac_flow_control_reg); + + return; + +} + +/** + * Example mac initialization sequence. + * This function calls the initialization routines to initialize the GMAC register. + * One can change the functions invoked here to have different configuration as per the requirement + * @param[in] pointer to synopGMACdevice. + * \return Returns 0 on success. + */ +s32 synopGMAC_mac_init(synopGMACdevice * gmacdev) +{ + u32 PHYreg; + + if(gmacdev->DuplexMode == FULLDUPLEX) { + synopGMAC_wd_enable(gmacdev); + synopGMAC_jab_enable(gmacdev); + synopGMAC_frame_burst_enable(gmacdev); + synopGMAC_jumbo_frame_disable(gmacdev); + synopGMAC_rx_own_enable(gmacdev); + synopGMAC_loopback_off(gmacdev); + synopGMAC_set_full_duplex(gmacdev); + synopGMAC_retry_enable(gmacdev); + synopGMAC_pad_crc_strip_disable(gmacdev); + synopGMAC_back_off_limit(gmacdev,GmacBackoffLimit0); + synopGMAC_deferral_check_disable(gmacdev); + + + if(gmacdev->Speed == SPEED1000) + synopGMAC_select_gmii(gmacdev); + else + synopGMAC_select_mii(gmacdev); + + // Cannot enable tx/rx while changing Speed/mode. + synopGMAC_tx_enable(gmacdev); + synopGMAC_rx_enable(gmacdev); + /*Frame Filter Configuration*/ + synopGMAC_frame_filter_enable(gmacdev); + synopGMAC_set_pass_control(gmacdev,GmacPassControl0); + synopGMAC_broadcast_enable(gmacdev); + synopGMAC_src_addr_filter_disable(gmacdev); + synopGMAC_multicast_disable(gmacdev); + synopGMAC_dst_addr_filter_normal(gmacdev); + synopGMAC_multicast_hash_filter_disable(gmacdev); + synopGMAC_promisc_disable(gmacdev); + synopGMAC_unicast_hash_filter_disable(gmacdev); + + /*Flow Control Configuration*/ + synopGMAC_unicast_pause_frame_detect_disable(gmacdev); + synopGMAC_rx_flow_control_enable(gmacdev); + synopGMAC_tx_flow_control_enable(gmacdev); + } else { //for Half Duplex configuration + + synopGMAC_wd_enable(gmacdev); + synopGMAC_jab_enable(gmacdev); + synopGMAC_frame_burst_enable(gmacdev); + synopGMAC_jumbo_frame_disable(gmacdev); + synopGMAC_rx_own_enable(gmacdev); + synopGMAC_loopback_off(gmacdev); + synopGMAC_set_half_duplex(gmacdev); + synopGMAC_retry_enable(gmacdev); + synopGMAC_pad_crc_strip_disable(gmacdev); + synopGMAC_back_off_limit(gmacdev,GmacBackoffLimit0); + synopGMAC_deferral_check_disable(gmacdev); + + + if(gmacdev->Speed == SPEED1000) + synopGMAC_select_gmii(gmacdev); + else + synopGMAC_select_mii(gmacdev); + + synopGMAC_tx_enable(gmacdev); + synopGMAC_rx_enable(gmacdev); + /*Frame Filter Configuration*/ + synopGMAC_frame_filter_enable(gmacdev); + synopGMAC_set_pass_control(gmacdev,GmacPassControl0); + synopGMAC_broadcast_enable(gmacdev); + synopGMAC_src_addr_filter_disable(gmacdev); + synopGMAC_multicast_disable(gmacdev); + synopGMAC_dst_addr_filter_normal(gmacdev); + synopGMAC_multicast_hash_filter_disable(gmacdev); + synopGMAC_promisc_disable(gmacdev); + synopGMAC_unicast_hash_filter_disable(gmacdev); + + /*Flow Control Configuration*/ + synopGMAC_unicast_pause_frame_detect_disable(gmacdev); + synopGMAC_rx_flow_control_disable(gmacdev); + synopGMAC_tx_flow_control_disable(gmacdev); + + /*To set PHY register to enable CRS on Transmit*/ + synopGMACWriteReg((u32 *)gmacdev->MacBase, GmacGmiiAddr, GmiiBusy | 0x00000408); + PHYreg = synopGMACReadReg((u32 *)gmacdev->MacBase,GmacGmiiData); + synopGMACWriteReg((u32 *)gmacdev->MacBase, GmacGmiiData, PHYreg | 0x00000800); + synopGMACWriteReg((u32 *)gmacdev->MacBase, GmacGmiiAddr, GmiiBusy | 0x0000040a); + } + return 0; +} + + +/** + * Checks and initialze phy. + * This function checks whether the phy initialization is complete. + * @param[in] pointer to synopGMACdevice. + * \return 0 if success else returns the error number. + */ +s32 synopGMAC_check_phy_init (synopGMACdevice * gmacdev) +{ + //u32 addr; + u16 data; + s32 status = 0; + s32 loop_count; + + loop_count = DEFAULT_LOOP_VARIABLE; + while(loop_count-- > 0) { + + status = synopGMAC_read_phy_reg((u32 *)gmacdev->MacBase,gmacdev->PhyBase,PHY_STATUS_REG, &data); + if(status) + return status; + + if((data & Mii_AutoNegCmplt) != 0) { + //printf("Autonegotiation Complete\n"); + break; + } + } + + status = synopGMAC_read_phy_reg((u32 *)gmacdev->MacBase,gmacdev->PhyBase,PHY_SPECIFIC_STATUS_REG, &data); + if(status) + return status; + + if((data & Mii_phy_status_link_up) == 0) { + //printf("No Link\n"); + gmacdev->LinkState = LINKDOWN; + return -ESYNOPGMACPHYERR; + } else { + gmacdev->LinkState = LINKUP; + //printf("Link UP\n"); + } + + status = synopGMAC_read_phy_reg((u32 *)gmacdev->MacBase,gmacdev->PhyBase,PHY_SPECIFIC_STATUS_REG, &data); + if(status) + return status; + + + + gmacdev->DuplexMode = (data & Mii_phy_status_full_duplex) ? FULLDUPLEX: HALFDUPLEX ; + //printf("Link is up in %s mode\n",(gmacdev->DuplexMode == FULLDUPLEX) ? "FULL DUPLEX": "HALF DUPLEX"); + + /*if not set to Master configuration in case of Half duplex mode set it manually as Master*/ + if(gmacdev->DuplexMode == HALFDUPLEX) { + status = synopGMAC_read_phy_reg((u32 *)gmacdev->MacBase,gmacdev->PhyBase,PHY_CONTROL_REG, &data); + if(status) + return status; + //status = synopGMAC_write_phy_reg((u32 *)gmacdev->MacBase,gmacdev->PhyBase,PHY_CONTROL_REG, data | Mii_Manual_Master_Config ); + //if(status) + // return status; + } + + status = synopGMAC_read_phy_reg((u32 *)gmacdev->MacBase,gmacdev->PhyBase,PHY_SPECIFIC_STATUS_REG, &data); + if(status) + return status; + if(data & Mii_phy_status_speed_1000) + gmacdev->Speed = SPEED1000; + else if(data & Mii_phy_status_speed_100) + gmacdev->Speed = SPEED100; + else + gmacdev->Speed = SPEED10; + + return 0; +} + +/** + * Sets the Mac address in to GMAC register. + * This function sets the MAC address to the MAC register in question. + * @param[in] pointer to synopGMACdevice to populate mac dma and phy addresses. + * @param[in] Register offset for Mac address high + * @param[in] Register offset for Mac address low + * @param[in] buffer containing mac address to be programmed. + * \return 0 upon success. Error code upon failure. + */ +s32 synopGMAC_set_mac_addr(synopGMACdevice *gmacdev, u32 MacHigh, u32 MacLow, u8 *MacAddr) +{ + u32 data; + + data = (MacAddr[5] << 8) | MacAddr[4]; + synopGMACWriteReg((u32 *)gmacdev->MacBase,MacHigh,data); + data = (MacAddr[3] << 24) | (MacAddr[2] << 16) | (MacAddr[1] << 8) | MacAddr[0] ; + synopGMACWriteReg((u32 *)gmacdev->MacBase,MacLow,data); + return 0; +} + + + + +/** + * Attaches the synopGMAC device structure to the hardware. + * Device structure is populated with MAC/DMA and PHY base addresses. + * @param[in] pointer to synopGMACdevice to populate mac dma and phy addresses. + * @param[in] GMAC IP mac base address. + * @param[in] GMAC IP dma base address. + * @param[in] GMAC IP phy base address. + * \return 0 upon success. Error code upon failure. + * \note This is important function. No kernel api provided by Synopsys + */ + +s32 synopGMAC_attach (synopGMACdevice *gmacdev, u32 macBase, u32 dmaBase, u32 phyBase) +{ + u8 mac_addr0[6] = DEFAULT_MAC0_ADDRESS; + u8 mac_addr1[6] = DEFAULT_MAC1_ADDRESS; + /*Make sure the Device data strucure is cleared before we proceed further*/ + memset((void *) gmacdev,0,sizeof(synopGMACdevice)); + /*Populate the mac and dma base addresses*/ + gmacdev->MacBase = macBase; + gmacdev->DmaBase = dmaBase; + gmacdev->PhyBase = phyBase; + + /* Program/flash in the station/IP's Mac address */ + synopGMAC_set_mac_addr(gmacdev,GmacAddr0High,GmacAddr0Low, gmacdev->Intf == 0 ? mac_addr0 : mac_addr1); + + return 0; +} + + + +/** + * Initialize the rx descriptors for ring or chain mode operation. + * - Status field is initialized to 0. + * - EndOfRing set for the last descriptor. + * - buffer1 and buffer2 set to 0 for ring mode of operation. (note) + * - data1 and data2 set to 0. (note) + * @param[in] pointer to DmaDesc structure. + * @param[in] whether end of ring + * \return void. + * \note Initialization of the buffer1, buffer2, data1,data2 and status are not done here. This only initializes whether one wants to use this descriptor + * in chain mode or ring mode. For chain mode of operation the buffer2 and data2 are programmed before calling this function. + */ +void synopGMAC_rx_desc_init_ring(DmaDesc *desc, bool last_ring_desc) +{ + desc->status = 0; + desc->length = last_ring_desc ? RxDescEndOfRing : 0; + desc->buffer1 = 0; + desc->buffer2 = 0; + //desc->data1 = 0; + //desc->data2 = 0; + return; +} +/** + * Initialize the tx descriptors for ring or chain mode operation. + * - Status field is initialized to 0. + * - EndOfRing set for the last descriptor. + * - buffer1 and buffer2 set to 0 for ring mode of operation. (note) + * - data1 and data2 set to 0. (note) + * @param[in] pointer to DmaDesc structure. + * @param[in] whether end of ring + * \return void. + * \note Initialization of the buffer1, buffer2, data1,data2 and status are not done here. This only initializes whether one wants to use this descriptor + * in chain mode or ring mode. For chain mode of operation the buffer2 and data2 are programmed before calling this function. + */ +void synopGMAC_tx_desc_init_ring(DmaDesc *desc, bool last_ring_desc) +{ + + desc->status = last_ring_desc? TxDescEndOfRing : 0; + desc->length = 0; + + // desc->buffer1 = 0; // Chris: to keep pointer for get-tx buffer + desc->buffer2 = 0; + //desc->data1 = 0; + //desc->data2 = 0; + return; +} + +s32 synopGMAC_init_tx_rx_desc_queue(synopGMACdevice *gmacdev) +{ + s32 i; + for(i =0; i < gmacdev -> TxDescCount; i++) { + synopGMAC_tx_desc_init_ring(gmacdev->TxDesc + i, i == gmacdev->TxDescCount-1); + } + TR("At line %d\n",__LINE__); + for(i =0; i < gmacdev -> RxDescCount; i++) { + synopGMAC_rx_desc_init_ring(gmacdev->RxDesc + i, i == gmacdev->RxDescCount-1); + } + + gmacdev->TxNext = 0; + gmacdev->TxBusy = 0; + gmacdev->RxNext = 0; + gmacdev->RxBusy = 0; + + return 0; +} + +/** + * Programs the DmaRxBaseAddress with the Rx descriptor base address. + * Rx Descriptor's base address is available in the gmacdev structure. This function progrms the + * Dma Rx Base address with the starting address of the descriptor ring or chain. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_init_rx_desc_base(synopGMACdevice *gmacdev) +{ + synopGMACWriteReg((u32 *)gmacdev->DmaBase,DmaRxBaseAddr,(u32)((u64)gmacdev->RxDescDma & 0xFFFFFFFF)); + return; +} + +/** + * Programs the DmaTxBaseAddress with the Tx descriptor base address. + * Tx Descriptor's base address is available in the gmacdev structure. This function progrms the + * Dma Tx Base address with the starting address of the descriptor ring or chain. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_init_tx_desc_base(synopGMACdevice *gmacdev) +{ + synopGMACWriteReg((u32 *)gmacdev->DmaBase,DmaTxBaseAddr,(u32)((u64)gmacdev->TxDescDma & 0xFFFFFFFF)); + return; +} + + +/** + * Checks whether the descriptor is owned by DMA. + * If descriptor is owned by DMA then the OWN bit is set to 1. This API is same for both ring and chain mode. + * @param[in] pointer to DmaDesc structure. + * \return returns true if Dma owns descriptor and false if not. + */ +bool synopGMAC_is_desc_owned_by_dma(DmaDesc *desc) +{ + return ((desc->status & DescOwnByDma) == DescOwnByDma ); +} + +/** + * returns the byte length of received frame including CRC. + * This returns the no of bytes received in the received ethernet frame including CRC(FCS). + * @param[in] pointer to DmaDesc structure. + * \return returns the length of received frame lengths in bytes. + */ +u32 synopGMAC_get_rx_desc_frame_length(u32 status) +{ + return ((status & DescFrameLengthMask) >> DescFrameLengthShift); +} + +/** + * Checks whether the descriptor is valid + * if no errors such as CRC/Receive Error/Watchdog Timeout/Late collision/Giant Frame/Overflow/Descriptor + * error the descritpor is said to be a valid descriptor. + * @param[in] pointer to DmaDesc structure. + * \return True if desc valid. false if error. + */ +bool synopGMAC_is_desc_valid(u32 status) +{ + return ((status & DescError) == 0); +} + +/** + * Checks whether the descriptor is empty. + * If the buffer1 and buffer2 lengths are zero in ring mode descriptor is empty. + * In chain mode buffer2 length is 0 but buffer2 itself contains the next descriptor address. + * @param[in] pointer to DmaDesc structure. + * \return returns true if descriptor is empty, false if not empty. + */ +bool synopGMAC_is_desc_empty(DmaDesc *desc) +{ + //if both the buffer1 length and buffer2 length are zero desc is empty + return(((desc->length & DescSize1Mask) == 0) && ((desc->length & DescSize2Mask) == 0) ); +} + + +/** + * Checks whether the rx descriptor is valid. + * if rx descripor is not in error and complete frame is available in the same descriptor + * @param[in] pointer to DmaDesc structure. + * \return returns true if no error and first and last desc bits are set, otherwise it returns false. + */ +bool synopGMAC_is_rx_desc_valid(u32 status) +{ + return ((status & DescError) == 0) && ((status & DescRxFirst) == DescRxFirst) && ((status & DescRxLast) == DescRxLast); +} + +/** + * Checks whether the tx is aborted due to collisions. + * @param[in] pointer to DmaDesc structure. + * \return returns true if collisions, else returns false. + */ +bool synopGMAC_is_tx_aborted(u32 status) +{ + return (((status & DescTxLateCollision) == DescTxLateCollision) | ((status & DescTxExcCollisions) == DescTxExcCollisions)); + +} + +/** + * Checks whether the tx carrier error. + * @param[in] pointer to DmaDesc structure. + * \return returns true if carrier error occured, else returns falser. + */ +bool synopGMAC_is_tx_carrier_error(u32 status) +{ + return (((status & DescTxLostCarrier) == DescTxLostCarrier) | ((status & DescTxNoCarrier) == DescTxNoCarrier)); +} + + +/** + * Gives the transmission collision count. + * returns the transmission collision count indicating number of collisions occured before the frame was transmitted. + * Make sure to check excessive collision didnot happen to ensure the count is valid. + * @param[in] pointer to DmaDesc structure. + * \return returns the count value of collision. + */ +u32 synopGMAC_get_tx_collision_count(u32 status) +{ + return ((status & DescTxCollMask) >> DescTxCollShift); +} +u32 synopGMAC_is_exc_tx_collisions(u32 status) +{ + return ((status & DescTxExcCollisions) == DescTxExcCollisions); +} + + +/** + * Check for damaged frame due to overflow or collision. + * Retruns true if rx frame was damaged due to buffer overflow in MTL or late collision in half duplex mode. + * @param[in] pointer to DmaDesc structure. + * \return returns true if error else returns false. + */ +bool synopGMAC_is_rx_frame_damaged(u32 status) +{ +//bool synopGMAC_dma_rx_collisions(u32 status) + return (((status & DescRxDamaged) == DescRxDamaged) | ((status & DescRxCollision) == DescRxCollision)); +} + +/** + * Check for damaged frame due to collision. + * Retruns true if rx frame was damaged due to late collision in half duplex mode. + * @param[in] pointer to DmaDesc structure. + * \return returns true if error else returns false. + */ +bool synopGMAC_is_rx_frame_collision(u32 status) +{ +//bool synopGMAC_dma_rx_collisions(u32 status) + return ((status & DescRxCollision) == DescRxCollision); +} + +/** + * Check for receive CRC error. + * Retruns true if rx frame CRC error occured. + * @param[in] pointer to DmaDesc structure. + * \return returns true if error else returns false. + */ +bool synopGMAC_is_rx_crc(u32 status) +{ +//u32 synopGMAC_dma_rx_crc(u32 status) + return ((status & DescRxCrc) == DescRxCrc); +} + +/** + * Indicates rx frame has non integer multiple of bytes. (odd nibbles). + * Retruns true if dribbling error in rx frame. + * @param[in] pointer to DmaDesc structure. + * \return returns true if error else returns false. + */ +bool synopGMAC_is_frame_dribbling_errors(u32 status) +{ +//u32 synopGMAC_dma_rx_frame_errors(u32 status) + return ((status & DescRxDribbling) == DescRxDribbling); +} + +/** + * Indicates error in rx frame length. + * Retruns true if received frame length doesnot match with the length field + * @param[in] pointer to DmaDesc structure. + * \return returns true if error else returns false. + */ +bool synopGMAC_is_rx_frame_length_errors(u32 status) +{ +//u32 synopGMAC_dma_rx_length_errors(u32 status) + return((status & DescRxLengthError) == DescRxLengthError); +} + +/** + * Checks whether this rx descriptor is last rx descriptor. + * This returns true if it is last descriptor either in ring mode or in chain mode. + * @param[in] pointer to devic structure. + * @param[in] pointer to DmaDesc structure. + * \return returns true if it is last descriptor, false if not. + * \note This function should not be called before initializing the descriptor using synopGMAC_desc_init(). + */ +bool synopGMAC_is_last_rx_desc(synopGMACdevice * gmacdev,DmaDesc *desc) +{ +//bool synopGMAC_is_last_desc(DmaDesc *desc) + return (((desc->length & RxDescEndOfRing) == RxDescEndOfRing) /*|| ((u32)((u64)gmacdev->RxDesc & 0xFFFFFFFF) == desc->data2)*/); +} + +/** + * Checks whether this tx descriptor is last tx descriptor. + * This returns true if it is last descriptor either in ring mode or in chain mode. + * @param[in] pointer to devic structure. + * @param[in] pointer to DmaDesc structure. + * \return returns true if it is last descriptor, false if not. + * \note This function should not be called before initializing the descriptor using synopGMAC_desc_init(). + */ +bool synopGMAC_is_last_tx_desc(synopGMACdevice * gmacdev,DmaDesc *desc) +{ +//bool synopGMAC_is_last_desc(DmaDesc *desc) + + return (((desc->status & TxDescEndOfRing) == TxDescEndOfRing) /*|| ((u32)((u64)gmacdev->TxDesc & 0xFFFFFFFF) == desc->data2)*/); + +} + + +/** + * This function is defined two times. Once when the code is compiled for ENHANCED DESCRIPTOR SUPPORT and Once for Normal descriptor + * Get the index and address of Tx desc. + * This api is same for both ring mode and chain mode. + * This function tracks the tx descriptor the DMA just closed after the transmission of data from this descriptor is + * over. This returns the descriptor fields to the caller. + * @param[in] pointer to synopGMACdevice. + * @param[out] status field of the descriptor. + * @param[out] Dma-able buffer1 pointer. + * @param[out] length of buffer1 (Max is 2048). + * @param[out] virtual pointer for buffer1. + * @param[out] u32 data indicating whether the descriptor is in ring mode or chain mode. + * \return returns present tx descriptor index on success. Negative value if error. + */ +s32 synopGMAC_get_tx_qptr(synopGMACdevice * gmacdev, u32 * Status, u32 * Buffer1, u32 * Length1, u32 * Data1, u32 * Ext_Status, u32 * Time_Stamp_High, u32 * Time_Stamp_Low) +{ + u32 txover = gmacdev->TxBusy; +#ifdef CACHE_ON + DmaDesc * txdesc = (DmaDesc *)((uint64_t)(gmacdev->TxBusyDesc) | 0x100000000); +#else + DmaDesc * txdesc = gmacdev->TxBusyDesc; +#endif + if(synopGMAC_is_desc_owned_by_dma(txdesc)) + return -1; + if(synopGMAC_is_desc_empty(txdesc)) + return -1; + + (gmacdev->BusyTxDesc)--; //busy tx descriptor is reduced by one as it will be handed over to Processor now + + if(Status != 0) + *Status = txdesc->status; + + if(Ext_Status != 0) + *Ext_Status = txdesc->extstatus; + if(Time_Stamp_High != 0) + *Time_Stamp_High = txdesc->timestamphigh; + if(Time_Stamp_Low != 0) + *Time_Stamp_Low = txdesc->timestamplow; + + if(Buffer1 != 0) + *Buffer1 = txdesc->buffer1; + if(Length1 != 0) + *Length1 = (txdesc->length & DescSize1Mask) >> DescSize1Shift; + //if(Data1 != 0) + // *Data1 = txdesc->data1; + + + gmacdev->TxBusy = synopGMAC_is_last_tx_desc(gmacdev,txdesc) ? 0 : txover + 1; + + if(1 /* ring mode */) { + gmacdev->TxBusyDesc = synopGMAC_is_last_tx_desc(gmacdev,txdesc) ? gmacdev->TxDesc : (txdesc + 1); + synopGMAC_tx_desc_init_ring(txdesc, synopGMAC_is_last_tx_desc(gmacdev,txdesc)); + } + TR("(get)%02d %08x %08x %08x %08x %08x %08x %08x\n",txover,(u32)((u64)txdesc & 0xFFFFFFFF),txdesc->status,txdesc->length,txdesc->buffer1,txdesc->buffer2,txdesc->data1,txdesc->data2); + + return txover; +} + +DmaDesc * prevtx; +void synopGMAC_set_crc_replacement(synopGMACdevice * gmacdev) +{ +#ifdef CACHE_ON + DmaDesc * txdesc = (DmaDesc *)((uint64_t)(gmacdev->TxNextDesc) | 0x100000000); +#else + DmaDesc * txdesc = gmacdev->TxNextDesc; +#endif + txdesc->status |= DescTxDisableCrc | DescTxCrcReplacement; + + prevtx = txdesc; +} + +void synopGMAC_clr_crc_replacement(synopGMACdevice * gmacdev) +{ + prevtx->status &= ~(DescTxDisableCrc | DescTxCrcReplacement); + prevtx = NULL; +} + +/** + * Populate the tx desc structure with the buffer address. + * Once the driver has a packet ready to be transmitted, this function is called with the + * valid dma-able buffer addresses and their lengths. This function populates the descriptor + * and make the DMA the owner for the descriptor. This function also controls whetther Checksum + * offloading to be done in hardware or not. + * This api is same for both ring mode and chain mode. + * @param[in] pointer to synopGMACdevice. + * @param[in] Dma-able buffer1 pointer. + * @param[in] length of buffer1 (Max is 2048). + * @param[in] virtual pointer for buffer1. + + * @param[in] u32 data indicating whether the descriptor is in ring mode or chain mode. + * @param[in] u32 indicating whether the checksum offloading in HW/SW. + * \return returns present tx descriptor index on success. Negative value if error. + */ +s32 synopGMAC_set_tx_qptr(synopGMACdevice * gmacdev, u32 Buffer1, u32 Length1, u32 Data1, u32 offload_needed, u32 ts) +{ + u32 txnext = gmacdev->TxNext; +#ifdef CACHE_ON + DmaDesc * txdesc = (DmaDesc *)((uint64_t)(gmacdev->TxNextDesc) | 0x100000000); +#else + DmaDesc * txdesc = gmacdev->TxNextDesc; +#endif + if(!synopGMAC_is_desc_empty(txdesc)) + return -1; + + (gmacdev->BusyTxDesc)++; //busy tx descriptor is incremented by one as it will be handed over to DMA + + if(1 /* ring mode */) { + txdesc->length |= ((Length1 <status |= (DescTxFirst | DescTxLast | DescTxIntEnable | (ts == 1 ? DescTxTSEnable : 0) ); //ENH_DESC // FIXME: Need to set DescTxTSEnable? + + //memcpy((void *)((u64)(tx_buf[][txnext]->Data) | 0x100000000), (void *)((u64)Buffer1), Length1); + txdesc->buffer1 = Buffer1; + //txdesc->data1 = Data1; + + if(offload_needed) { + /* + Make sure that the OS you are running supports the IP and TCP checkusm offloaidng, + before calling any of the functions given below. + */ + + //TODO: + //synopGMAC_tx_checksum_offload_ipv4hdr(gmacdev, txdesc); + //synopGMAC_tx_checksum_offload_tcponly(gmacdev, txdesc); + synopGMAC_tx_checksum_offload_tcp_pseudo(gmacdev, txdesc); + } else { + synopGMAC_tx_checksum_offload_bypass(gmacdev, txdesc); + } + __DSB(); + txdesc->status |= DescOwnByDma;//ENH_DESC + + gmacdev->TxNext = synopGMAC_is_last_tx_desc(gmacdev,txdesc) ? 0 : txnext + 1; + gmacdev->TxNextDesc = synopGMAC_is_last_tx_desc(gmacdev,txdesc) ? gmacdev->TxDesc : (txdesc + 1); + } + + TR("(set)%02d %08x %08x %08x %08x %08x %08x %08x\n",txnext,(u32)((u64)txdesc & 0xFFFFFFFF),txdesc->status,txdesc->length,txdesc->buffer1,txdesc->buffer2,txdesc->data1,txdesc->data2); + return txnext; +} + +/** + * Prepares the descriptor to receive packets. + * The descriptor is allocated with the valid buffer addresses (sk_buff address) and the length fields + * and handed over to DMA by setting the ownership. After successful return from this function the + * descriptor is added to the receive descriptor pool/queue. + * This api is same for both ring mode and chain mode. + * @param[in] pointer to synopGMACdevice. + * @param[in] Dma-able buffer1 pointer. + * @param[in] length of buffer1 (Max is 2048). + * @param[in] Dma-able buffer2 pointer. + * @param[in] length of buffer2 (Max is 2048). + * @param[in] u32 data indicating whether the descriptor is in ring mode or chain mode. + * \return returns present rx descriptor index on success. Negative value if error. + */ +s32 synopGMAC_set_rx_qptr(synopGMACdevice * gmacdev, u32 Buffer1, u32 Length1, u32 Data1) +{ + u32 rxnext = gmacdev->RxNext; +#ifdef CACHE_ON + DmaDesc * rxdesc = (DmaDesc *)((uint64_t)(gmacdev->RxNextDesc) | 0x100000000); +#else + DmaDesc * rxdesc = gmacdev->RxNextDesc; +#endif + if(!synopGMAC_is_desc_empty(rxdesc)) + return -1; + + rxdesc->length |= ((Length1 <buffer1 = Buffer1; + //rxdesc->data1 = Data1; + + rxdesc->extstatus = 0; + rxdesc->reserved1 = 0; + rxdesc->timestamplow = 0; + rxdesc->timestamphigh = 0; + + rxdesc->buffer2 = 0; + //rxdesc->data2 = 0; + + if((rxnext % MODULO_INTERRUPT) !=0) + rxdesc->length |= RxDisIntCompl; + + rxdesc->status = DescOwnByDma; + + gmacdev->RxNext = synopGMAC_is_last_rx_desc(gmacdev,rxdesc) ? 0 : rxnext + 1; + gmacdev->RxNextDesc = synopGMAC_is_last_rx_desc(gmacdev,rxdesc) ? gmacdev->RxDesc : (rxdesc + 1); + + TR("%02d %08x %08x %08x %08x %08x %08x %08x\n",rxnext,(u32)((u64)rxdesc & 0xFFFFFFFF),rxdesc->status,rxdesc->length,rxdesc->buffer1,rxdesc->buffer2,rxdesc->data1,rxdesc->data2); + + (gmacdev->BusyRxDesc)++; //One descriptor will be given to Hardware. So busy count incremented by one + return rxnext; +} + + +/** + * This function is defined two times. Once when the code is compiled for ENHANCED DESCRIPTOR SUPPORT and Once for Normal descriptor + * Get back the descriptor from DMA after data has been received. + * When the DMA indicates that the data is received (interrupt is generated), this function should be + * called to get the descriptor and hence the data buffers received. With successful return from this + * function caller gets the descriptor fields for processing. check the parameters to understand the + * fields returned.` + * @param[in] pointer to synopGMACdevice. + * @param[out] pointer to hold the status of DMA. + * @param[out] Dma-able buffer1 pointer. + * @param[out] pointer to hold length of buffer1 (Max is 2048). + * @param[out] virtual pointer for buffer1. + * \return returns present rx descriptor index on success. Negative value if error. + */ +s32 synopGMAC_get_rx_qptr(synopGMACdevice * gmacdev, u32 * Status, u32 * Buffer1, u32 * Length1, u32 * Data1, + u32 * Ext_Status, u32 * Time_Stamp_High, u32 * Time_Stamp_Low) +{ + u32 rxnext = gmacdev->RxBusy; // index of descriptor the DMA just completed. May be useful when data + //is spread over multiple buffers/descriptors +#ifdef CACHE_ON + DmaDesc * rxdesc = (DmaDesc *)((uint64_t)(gmacdev->RxBusyDesc) | 0x100000000); +#else + DmaDesc * rxdesc = gmacdev->RxBusyDesc; +#endif + if(synopGMAC_is_desc_owned_by_dma(rxdesc)) + return -1; + if(synopGMAC_is_desc_empty(rxdesc)) + return -1; + + + if(Status != 0) + *Status = rxdesc->status;// send the status of this descriptor + + if(Ext_Status != 0) + *Ext_Status = rxdesc->extstatus; + if(Time_Stamp_High != 0) + *Time_Stamp_High = rxdesc->timestamphigh; + if(Time_Stamp_Low != 0) + *Time_Stamp_Low = rxdesc->timestamplow; + + if(Length1 != 0) + *Length1 = (rxdesc->length & DescSize1Mask) >> DescSize1Shift; + if(Buffer1 != 0) + *Buffer1 = rxdesc->buffer1; + //if(Data1 != 0) + // *Data1 = rxdesc->data1; + + gmacdev->RxBusy = synopGMAC_is_last_rx_desc(gmacdev,rxdesc) ? 0 : rxnext + 1; + + gmacdev->RxBusyDesc = synopGMAC_is_last_rx_desc(gmacdev,rxdesc) ? gmacdev->RxDesc : (rxdesc + 1); + // why init here.... should change onwer to DMA --ya + //synopGMAC_rx_desc_init_ring(rxdesc, synopGMAC_is_last_rx_desc(gmacdev,rxdesc)); + rxdesc->status = DescOwnByDma; + rxdesc->extstatus = 0; + rxdesc->reserved1 = 0; + rxdesc->timestamplow = 0; + rxdesc->timestamphigh = 0; + TR("%02d %08x %08x %08x %08x %08x %08x %08x\n",rxnext,(u32)((u64)rxdesc & 0xFFFFFFFF),rxdesc->status,rxdesc->length,rxdesc->buffer1,rxdesc->buffer2,rxdesc->data1,rxdesc->data2); + (gmacdev->BusyRxDesc)--; //busy tx descriptor is reduced by one as it will be handed over to Processor now + return(rxnext); + +} + + +/** + * Clears all the pending interrupts. + * If the Dma status register is read then all the interrupts gets cleared + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_clear_interrupt(synopGMACdevice *gmacdev) +{ + u32 data; + data = synopGMACReadReg((u32 *)gmacdev->DmaBase, DmaStatus); + synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaStatus ,data); +} + +/** + * Returns the all unmasked interrupt status after reading the DmaStatus register. + * @param[in] pointer to synopGMACdevice. + * \return 0 upon success. Error code upon failure. + */ +u32 synopGMAC_get_interrupt_type(synopGMACdevice *gmacdev) +{ + u32 data; + u32 interrupts = 0; + data = synopGMACReadReg((u32 *)gmacdev->DmaBase, DmaStatus); + synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaStatus ,data); //This is the appropriate location to clear the interrupts + TR("DMA status reg is %08x\n",data); + if(data & DmaIntErrorMask) interrupts |= synopGMACDmaError; + if(data & DmaIntRxNormMask) interrupts |= synopGMACDmaRxNormal; + if(data & DmaIntRxAbnMask) interrupts |= synopGMACDmaRxAbnormal; + if(data & DmaIntRxStoppedMask) interrupts |= synopGMACDmaRxStopped; + if(data & DmaIntTxNormMask) interrupts |= synopGMACDmaTxNormal; + if(data & DmaIntTxAbnMask) interrupts |= synopGMACDmaTxAbnormal; + if(data & DmaIntTxStoppedMask) interrupts |= synopGMACDmaTxStopped; + + //printf("%08x\n", data); + //if((interrupts != 0) && (interrupts != 1) && (interrupts != 8) && (interrupts != 9)) { + // printf("....\n"); + // while(1); + //} + return interrupts; +} + + +/** + * Enable all the interrupts. + * Enables the DMA interrupt as specified by the bit mask. + * @param[in] pointer to synopGMACdevice. + * @param[in] bit mask of interrupts to be enabled. + * \return returns void. + */ +void synopGMAC_enable_interrupt(synopGMACdevice *gmacdev, u32 interrupts) +{ +// synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaInterrupt, interrupts); + u32 data; + data = synopGMACReadReg((u32 *)gmacdev->DmaBase, DmaInterrupt); + data |= interrupts; + synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaInterrupt, data); + return; +} + + +/** + * Disable all the interrupts. + * Disables all DMA interrupts. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + * \note This function disabled all the interrupts, if you want to disable a particular interrupt then + * use synopGMAC_disable_interrupt(). + */ +void synopGMAC_disable_interrupt_all(synopGMACdevice *gmacdev) +{ + synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaInterrupt, DmaIntDisable); + return; +} + +/** + * Disable interrupt according to the bitfield supplied. + * Disables only those interrupts specified in the bit mask in second argument. + * @param[in] pointer to synopGMACdevice. + * @param[in] bit mask for interrupts to be disabled. + * \return returns void. + */ +void synopGMAC_disable_interrupt(synopGMACdevice *gmacdev, u32 interrupts) +{ + synopGMACClearBits((u32 *)gmacdev->DmaBase, DmaInterrupt, interrupts); + return; +} +/** + * Enable the DMA Reception. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_enable_dma_rx(synopGMACdevice * gmacdev) +{ +// synopGMACSetBits((u32 *)gmacdev->DmaBase, DmaControl, DmaRxStart); + u32 data; + data = synopGMACReadReg((u32 *)gmacdev->DmaBase, DmaControl); + data |= DmaRxStart; + synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaControl ,data); + +} + +/** + * Enable the DMA Transmission. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_enable_dma_tx(synopGMACdevice * gmacdev) +{ +// synopGMACSetBits((u32 *)gmacdev->DmaBase, DmaControl, DmaTxStart); + u32 data; + data = synopGMACReadReg((u32 *)gmacdev->DmaBase, DmaControl); + data |= DmaTxStart; + synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaControl ,data); + +} + +void synopGMAC_enable_under_size_pkt(synopGMACdevice * gmacdev) +{ + u32 data; + data = synopGMACReadReg((u32 *)gmacdev->DmaBase, DmaControl); + data |= DmaFwdUnderSzFrames; + synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaControl ,data); + +} + +void synopGMAC_disable_under_size_pkt(synopGMACdevice * gmacdev) +{ + u32 data; + data = synopGMACReadReg((u32 *)gmacdev->DmaBase, DmaControl); + data &= ~DmaFwdUnderSzFrames; + synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaControl ,data); + +} + +void synopGMAC_enable_crc_err_pkt(synopGMACdevice * gmacdev) +{ + u32 data; + data = synopGMACReadReg((u32 *)gmacdev->DmaBase, DmaControl); + data |= DmaFwdErrorFrames; + synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaControl ,data); + +} + +void synopGMAC_disable_crc_err_pkt(synopGMACdevice * gmacdev) +{ + u32 data; + data = synopGMACReadReg((u32 *)gmacdev->DmaBase, DmaControl); + data &= ~DmaFwdErrorFrames; + synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaControl ,data); + +} + + +/** + * Resumes the DMA Transmission. + * the DmaTxPollDemand is written. (the data writeen could be anything). + * This forces the DMA to resume transmission. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_resume_dma_tx(synopGMACdevice * gmacdev) +{ + synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaTxPollDemand, 0); + +} +/** + * Resumes the DMA Reception. + * the DmaRxPollDemand is written. (the data writeen could be anything). + * This forces the DMA to resume reception. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_resume_dma_rx(synopGMACdevice * gmacdev) +{ + synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaRxPollDemand, 0); + +} +/** + * Take ownership of this Descriptor. + * The function is same for both the ring mode and the chain mode DMA structures. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_take_desc_ownership(DmaDesc * desc) +{ + if(desc) { + desc->status &= ~DescOwnByDma; //Clear the DMA own bit +// desc->status |= DescError; // Set the error to indicate this descriptor is bad + } +} + +/** + * Take ownership of all the rx Descriptors. + * This function is called when there is fatal error in DMA transmission. + * When called it takes the ownership of all the rx descriptor in rx descriptor pool/queue from DMA. + * The function is same for both the ring mode and the chain mode DMA structures. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + * \note Make sure to disable the transmission before calling this function, otherwise may result in racing situation. + */ +void synopGMAC_take_desc_ownership_rx(synopGMACdevice * gmacdev) +{ + s32 i; + DmaDesc *desc; + desc = gmacdev->RxDesc; + for(i = 0; i < gmacdev->RxDescCount; i++) { + if(1 /* ring mode */) { + synopGMAC_take_desc_ownership(desc + i); + } + } +} + +/** + * Take ownership of all the rx Descriptors. + * This function is called when there is fatal error in DMA transmission. + * When called it takes the ownership of all the tx descriptor in tx descriptor pool/queue from DMA. + * The function is same for both the ring mode and the chain mode DMA structures. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + * \note Make sure to disable the transmission before calling this function, otherwise may result in racing situation. + */ +void synopGMAC_take_desc_ownership_tx(synopGMACdevice * gmacdev) +{ + s32 i; + DmaDesc *desc; + desc = gmacdev->TxDesc; + for(i = 0; i < gmacdev->TxDescCount; i++) { + if(1 /* ring mode */) { + synopGMAC_take_desc_ownership(desc + i); + } + } + +} + +/** + * Disable the DMA for Transmission. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ + +void synopGMAC_disable_dma_tx(synopGMACdevice * gmacdev) +{ +// synopGMACClearBits((u32 *)gmacdev->DmaBase, DmaControl, DmaTxStart); + u32 data; + data = synopGMACReadReg((u32 *)gmacdev->DmaBase, DmaControl); + data &= (~DmaTxStart); + synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaControl ,data); +} +/** + * Disable the DMA for Reception. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_disable_dma_rx(synopGMACdevice * gmacdev) +{ +// synopGMACClearBits((u32 *)gmacdev->DmaBase, DmaControl, DmaRxStart); + u32 data; + data = synopGMACReadReg((u32 *)gmacdev->DmaBase, DmaControl); + data &= (~DmaRxStart); + synopGMACWriteReg((u32 *)gmacdev->DmaBase, DmaControl ,data); +} + + + +/*******************PMT APIs***************************************/ + + + + +/** + * Enables the assertion of PMT interrupt. + * This enables the assertion of PMT interrupt due to Magic Pkt or Wakeup frame + * reception. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_pmt_int_enable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase,GmacInterruptMask,GmacPmtIntMask); + return; +} +/** + * Disables the assertion of PMT interrupt. + * This disables the assertion of PMT interrupt due to Magic Pkt or Wakeup frame + * reception. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_pmt_int_disable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacInterruptMask,GmacPmtIntMask); + return; +} +/** + * Enables the power down mode of GMAC. + * This function puts the Gmac in power down mode. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_power_down_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacPmtCtrlStatus,GmacPmtPowerDown); + return; +} +/** + * Disables the powerd down setting of GMAC. + * If the driver wants to bring up the GMAC from powerdown mode, even though the magic packet or the + * wake up frames received from the network, this function should be called. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_power_down_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase,GmacPmtCtrlStatus,GmacPmtPowerDown); + return; +} +/** + * Enables the pmt interrupt generation in powerdown mode. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_enable_pmt_interrupt(synopGMACdevice *gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase,GmacInterruptMask,GmacPmtIntMask); +} +/** + * Disables the pmt interrupt generation in powerdown mode. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_disable_pmt_interrupt(synopGMACdevice *gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacInterruptMask,GmacPmtIntMask); +} +/** + * Enables GMAC to look for Magic packet. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_magic_packet_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacPmtCtrlStatus,GmacPmtMagicPktEnable); + return; +} + +void synopGMAC_magic_packet_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase,GmacPmtCtrlStatus,GmacPmtMagicPktEnable); + return; +} + +/** + * Enables GMAC to look for wake up frame. + * Wake up frame is defined by the user. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_wakeup_frame_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacPmtCtrlStatus,GmacPmtWakeupFrameEnable); + return; +} + +/** + * Enables wake-up frame filter to handle unicast packets. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_pmt_unicast_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacPmtCtrlStatus,GmacPmtGlobalUnicast); + return; +} +/** + * Checks whether the packet received is a magic packet?. + * @param[in] pointer to synopGMACdevice. + * \return returns True if magic packet received else returns false. + */ +bool synopGMAC_is_magic_packet_received(synopGMACdevice *gmacdev) +{ + u32 data; + data = synopGMACReadReg((u32 *)gmacdev->MacBase,GmacPmtCtrlStatus); + return((data & GmacPmtMagicPktReceived) == GmacPmtMagicPktReceived); +} +/** + * Checks whether the packet received is a wakeup frame?. + * @param[in] pointer to synopGMACdevice. + * \return returns true if wakeup frame received else returns false. + */ +bool synopGMAC_is_wakeup_frame_received(synopGMACdevice *gmacdev) +{ + u32 data; + data = synopGMACReadReg((u32 *)gmacdev->MacBase,GmacPmtCtrlStatus); + return((data & GmacPmtWakeupFrameReceived) == GmacPmtWakeupFrameReceived); +} + +/** + * Populates the remote wakeup frame registers. + * Consecutive 8 writes to GmacWakeupAddr writes the wakeup frame filter registers. + * Before commensing a new write, frame filter pointer is reset to 0x0000. + * A small delay is introduced to allow frame filter pointer reset operation. + * @param[in] pointer to synopGMACdevice. + * @param[in] pointer to frame filter contents array. + * \return returns void. + */ +#if 0 +void synopGMAC_write_wakeup_frame_register(synopGMACdevice *gmacdev, u32 * filter_contents) +{ + s32 i; + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacPmtCtrlStatus,GmacPmtFrmFilterPtrReset); + plat_delay(10); + for(i =0; iMacBase, GmacWakeupAddr, *(filter_contents + i)); + return; + +} +#endif +/*******************PMT APIs***************************************/ + +/*******************Ip checksum offloading APIs***************************************/ + +/** + * Enables the ip checksum offloading in receive path. + * When set GMAC calculates 16 bit 1's complement of all received ethernet frame payload. + * It also checks IPv4 Header checksum is correct. GMAC core appends the 16 bit checksum calculated + * for payload of IP datagram and appends it to Ethernet frame transferred to the application. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_enable_rx_chksum_offload(synopGMACdevice *gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacConfig,GmacRxIpcOffload); + return; +} +/** + * Disable the ip checksum offloading in receive path. + * Ip checksum offloading is disabled in the receive path. + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_disable_rx_chksum_offload(synopGMACdevice *gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase,GmacConfig,GmacRxIpcOffload); +} +/** + * Instruct the DMA to drop the packets fails tcp ip checksum. + * This is to instruct the receive DMA engine to drop the recevied packet if they + * fails the tcp/ip checksum in hardware. Valid only when full checksum offloading is enabled(type-2). + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_rx_tcpip_chksum_drop_enable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->DmaBase,DmaControl,DmaDisableDropTcpCs); + return; +} +/** + * Instruct the DMA not to drop the packets even if it fails tcp ip checksum. + * This is to instruct the receive DMA engine to allow the packets even if recevied packet + * fails the tcp/ip checksum in hardware. Valid only when full checksum offloading is enabled(type-2). + * @param[in] pointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_rx_tcpip_chksum_drop_disable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->DmaBase,DmaControl,DmaDisableDropTcpCs); + return; +} + +/** + * When the Enhanced Descriptor is enabled then the bit 0 of RDES0 indicates whether the + * Extended Status is available (RDES4). Time Stamp feature and the Checksum Offload Engine2 + * makes use of this extended status to provide the status of the received packet. + * @param[in] pointer to synopGMACdevice + * \return returns TRUE or FALSE + */ + + +/** + * This function indicates whether extended status is available in the RDES0. + * Any function which accesses the fields of extended status register must ensure a check on this has been made + * This is valid only for Enhanced Descriptor. + * @param[in] pointer to synopGMACdevice. + * @param[in] u32 status field of the corresponding descriptor. + * \return returns TRUE or FALSE. + */ +bool synopGMAC_is_ext_status(synopGMACdevice *gmacdev,u32 status) // extended status present indicates that the RDES4 need to be probed +{ + return((status & DescRxEXTsts ) != 0 ); // if extstatus set then it returns 1 +} +/** + * This function returns true if the IP header checksum bit is set in the extended status. + * Valid only when enhaced status available is set in RDES0 bit 0. + * This is valid only for Enhanced Descriptor. + * @param[in] pointer to synopGMACdevice. + * @param[in] u32 status field of the corresponding descriptor. + * \return returns TRUE or FALSE. + */ +bool synopGMAC_ES_is_IP_header_error(synopGMACdevice *gmacdev,u32 ext_status) // IP header (IPV4) checksum error +{ + return((ext_status & DescRxIpHeaderError) != 0 ); // if IPV4 header error return 1 +} +/** + * This function returns true if the Checksum is bypassed in the hardware. + * Valid only when enhaced status available is set in RDES0 bit 0. + * This is valid only for Enhanced Descriptor. + * @param[in] pointer to synopGMACdevice. + * @param[in] u32 status field of the corresponding descriptor. + * \return returns TRUE or FALSE. + */ +bool synopGMAC_ES_is_rx_checksum_bypassed(synopGMACdevice *gmacdev,u32 ext_status) // Hardware engine bypassed the checksum computation/checking +{ + return((ext_status & DescRxChkSumBypass ) != 0 ); // if checksum offloading bypassed return 1 +} +/** + * This function returns true if payload checksum error is set in the extended status. + * Valid only when enhaced status available is set in RDES0 bit 0. + * This is valid only for Enhanced Descriptor. + * @param[in] pointer to synopGMACdevice. + * @param[in] u32 status field of the corresponding descriptor. + * \return returns TRUE or FALSE. + */ +bool synopGMAC_ES_is_IP_payload_error(synopGMACdevice *gmacdev,u32 ext_status) // IP payload checksum is in error (UDP/TCP/ICMP checksum error) +{ + return((ext_status & DescRxIpPayloadError) != 0 ); // if IP payload error return 1 +} + + + + +/** + * Decodes the Rx Descriptor status to various checksum error conditions. + * @param[in] pointer to synopGMACdevice. + * @param[in] u32 status field of the corresponding descriptor. + * \return returns decoded enum (u32) indicating the status. + */ +u32 synopGMAC_is_rx_checksum_error(synopGMACdevice *gmacdev, u32 status) +{ + if (((status & DescRxChkBit5) == 0) && ((status & DescRxChkBit7) == 0) && ((status & DescRxChkBit0) == 0)) + return RxLenLT600; + else if(((status & DescRxChkBit5) == 0) && ((status & DescRxChkBit7) == 0) && ((status & DescRxChkBit0) != 0)) + return RxIpHdrPayLoadChkBypass; + else if(((status & DescRxChkBit5) == 0) && ((status & DescRxChkBit7) != 0) && ((status & DescRxChkBit0) != 0)) + return RxChkBypass; + else if(((status & DescRxChkBit5) != 0) && ((status & DescRxChkBit7) == 0) && ((status & DescRxChkBit0) == 0)) + return RxNoChkError; + else if(((status & DescRxChkBit5) != 0) && ((status & DescRxChkBit7) == 0) && ((status & DescRxChkBit0) != 0)) + return RxPayLoadChkError; + else if(((status & DescRxChkBit5) != 0) && ((status & DescRxChkBit7) != 0) && ((status & DescRxChkBit0) == 0)) + return RxIpHdrChkError; + else if(((status & DescRxChkBit5) != 0) && ((status & DescRxChkBit7) != 0) && ((status & DescRxChkBit0) != 0)) + return RxIpHdrPayLoadChkError; + else + return RxIpHdrPayLoadRes; +} +/** + * Checks if any Ipv4 header checksum error in the frame just transmitted. + * This serves as indication that error occureed in the IPv4 header checksum insertion. + * The sent out frame doesnot carry any ipv4 header checksum inserted by the hardware. + * @param[in] pointer to synopGMACdevice. + * @param[in] u32 status field of the corresponding descriptor. + * \return returns true if error in ipv4 header checksum, else returns false. + */ +bool synopGMAC_is_tx_ipv4header_checksum_error(synopGMACdevice *gmacdev, u32 status) +{ + return((status & DescTxIpv4ChkError) == DescTxIpv4ChkError); +} + + +/** + * Checks if any payload checksum error in the frame just transmitted. + * This serves as indication that error occureed in the payload checksum insertion. + * The sent out frame doesnot carry any payload checksum inserted by the hardware. + * @param[in] pointer to synopGMACdevice. + * @param[in] u32 status field of the corresponding descriptor. + * \return returns true if error in ipv4 header checksum, else returns false. + */ +bool synopGMAC_is_tx_payload_checksum_error(synopGMACdevice *gmacdev, u32 status) +{ + return((status & DescTxPayChkError) == DescTxPayChkError); +} +/** + * The check summ offload engine is bypassed in the tx path. + * Checksum is not computed in the Hardware. + * @param[in] pointer to synopGMACdevice. + * @param[in] Pointer to tx descriptor for which ointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_tx_checksum_offload_bypass(synopGMACdevice *gmacdev, DmaDesc *desc) +{ + desc->status = (desc->status & (~DescTxCisMask));//ENH_DESC + + +} +/** + * The check summ offload engine is enabled to do only IPV4 header checksum. + * IPV4 header Checksum is computed in the Hardware. + * @param[in] pointer to synopGMACdevice. + * @param[in] Pointer to tx descriptor for which ointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_tx_checksum_offload_ipv4hdr(synopGMACdevice *gmacdev, DmaDesc *desc) +{ + + desc->status = ((desc->status & (~DescTxCisMask)) | DescTxCisIpv4HdrCs);//ENH_DESC + + +} + +/** + * The check summ offload engine is enabled to do TCPIP checsum assuming Pseudo header is available. + * Hardware computes the tcp ip checksum assuming pseudo header checksum is computed in software. + * Ipv4 header checksum is also inserted. + * @param[in] pointer to synopGMACdevice. + * @param[in] Pointer to tx descriptor for which ointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_tx_checksum_offload_tcponly(synopGMACdevice *gmacdev, DmaDesc *desc) +{ + + desc->status = ((desc->status & (~DescTxCisMask)) | DescTxCisTcpOnlyCs);//ENH_DESC + + +} +/** + * The check summ offload engine is enabled to do complete checksum computation. + * Hardware computes the tcp ip checksum including the pseudo header checksum. + * Here the tcp payload checksum field should be set to 0000. + * Ipv4 header checksum is also inserted. + * @param[in] pointer to synopGMACdevice. + * @param[in] Pointer to tx descriptor for which ointer to synopGMACdevice. + * \return returns void. + */ +void synopGMAC_tx_checksum_offload_tcp_pseudo(synopGMACdevice *gmacdev, DmaDesc *desc) +{ + + desc->status = ((desc->status & (~DescTxCisMask)) | DescTxCisTcpPseudoCs); + + +} +/*******************Ip checksum offloading APIs***************************************/ + + + + + +/*******************IEEE 1588 Timestamping API***************************************/ + + +/* + * At this time the driver supports the IEEE time stamping feature when the Enhanced Descriptors are enabled. + * For normal descriptor and the IEEE time stamp (version 1), driver support is not proviced + * Please make sure you have enabled the Advanced timestamp feature in the hardware and the driver should + * be compiled with the ADV_TME_STAMP feature. + * Some of the APIs provided here may not be valid for all configurations. Please make sure you call the + * API with due care. + */ + +/** + * This function enables the timestamping. This enables the timestamping for transmit and receive frames. + * When disabled timestamp is not added to tx and receive frames and timestamp generator is suspended. + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacTSControl,GmacTSENA); + return; +} +/** + * This function disables the timestamping. + * When disabled timestamp is not added to tx and receive frames and timestamp generator is suspended. + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase,GmacTSControl, GmacTSENA); + return; +} + + +/** + * Enable the interrupt to get timestamping interrupt. + * This enables the host to get the interrupt when (1) system time is greater or equal to the + * target time high and low register or (2) there is a overflow in th esecond register. + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_int_enable(synopGMACdevice *gmacdev) +{ + //synopGMACClearBits((u32 *)gmacdev->MacBase,GmacInterruptMask,GmacTSIntMask); + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacTSControl,GmacTSTRIG); + return; +} + +/** + * Disable the interrupt to get timestamping interrupt. + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_int_disable(synopGMACdevice *gmacdev) +{ + //synopGMACSetBits((u32 *)gmacdev->MacBase,GmacInterruptMask,GmacTSIntMask); + synopGMACClearBits((u32 *)gmacdev->MacBase,GmacTSControl,GmacTSTRIG); + return; +} + +/** + * Enable MAC address for PTP frame filtering. + * When enabled, uses MAC address (apart from MAC address 0) to filter the PTP frames when + * PTP is sent directly over Ethernet. + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_mac_addr_filt_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacTSControl,GmacTSENMACADDR); + return; +} + +/** + * Disables MAC address for PTP frame filtering. + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_mac_addr_filt_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase,GmacTSControl,GmacTSENMACADDR); + return; +} + + +/** + * Selet the type of clock mode for PTP. + * Please note to use one of the follwoing as the clk_type argument. + * GmacTSOrdClk = 0x00000000, 00=> Ordinary clock + * GmacTSBouClk = 0x00010000, 01=> Boundary clock + * GmacTSEtoEClk = 0x00020000, 10=> End-to-End transparent clock + * GmacTSPtoPClk = 0x00030000, 11=> P-to-P transparent clock + * @param[in] pointer to synopGMACdevice + * @param[in] u32 value representing one of the above clk value + * \return returns void + */ +void synopGMAC_TS_set_clk_type(synopGMACdevice *gmacdev, u32 clk_type) +{ + u32 clkval; + clkval = synopGMACReadReg((u32 *)gmacdev->MacBase,GmacTSControl); //set the mdc clock to the user defined value + clkval = (clkval & ~GmacTSCLKTYPE)| clk_type; + synopGMACWriteReg((u32 *)gmacdev->MacBase,GmacTSControl,clkval); + return; +} + +/** + * Enable Snapshot for messages relevant to Master. + * When enabled, snapshot is taken for messages relevant to master mode only, else snapshot is taken for messages relevant + * to slave node. + * Valid only for Ordinary clock and Boundary clock + * Reserved when "Advanced Time Stamp" is not selected + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_master_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacTSControl,GmacTSMSTRENA); + return; +} +/** + * Disable Snapshot for messages relevant to Master. + * When disabled, snapshot is taken for messages relevant + * to slave node. + * Valid only for Ordinary clock and Boundary clock + * Reserved when "Advanced Time Stamp" is not selected + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_master_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase,GmacTSControl,GmacTSMSTRENA); + return; +} +/** + * Enable Snapshot for Event messages. + * When enabled, snapshot is taken for event messages only (SYNC, Delay_Req, Pdelay_Req or Pdelay_Resp) + * When disabled, snapshot is taken for all messages except Announce, Management and Signaling. + * Reserved when "Advanced Time Stamp" is not selected + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_event_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacTSControl,GmacTSEVNTENA); + return; +} +/** + * Disable Snapshot for Event messages. + * When disabled, snapshot is taken for all messages except Announce, Management and Signaling. + * Reserved when "Advanced Time Stamp" is not selected + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_event_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase,GmacTSControl,GmacTSEVNTENA); + return; +} + +/** + * Enable time stamp snapshot for IPV4 frames. + * When enabled, time stamp snapshot is taken for IPV4 frames + * Reserved when "Advanced Time Stamp" is not selected + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_IPV4_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacTSControl,GmacTSIPV4ENA); + return; +} +/** + * Disable time stamp snapshot for IPV4 frames. + * When disabled, time stamp snapshot is not taken for IPV4 frames + * Reserved when "Advanced Time Stamp" is not selected + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_IPV4_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase,GmacTSControl,GmacTSIPV4ENA); + return; +} // Only for "Advanced Time Stamp" +/** + * Enable time stamp snapshot for IPV6 frames. + * When enabled, time stamp snapshot is taken for IPV6 frames + * Reserved when "Advanced Time Stamp" is not selected + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_IPV6_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacTSControl,GmacTSIPV6ENA); + return; +} +/** + * Disable time stamp snapshot for IPV6 frames. + * When disabled, time stamp snapshot is not taken for IPV6 frames + * Reserved when "Advanced Time Stamp" is not selected + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_IPV6_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase,GmacTSControl,GmacTSIPV6ENA); + return; +} + +/** + * Enable time stamp snapshot for PTP over Ethernet frames. + * When enabled, time stamp snapshot is taken for PTP over Ethernet frames + * Reserved when "Advanced Time Stamp" is not selected + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_ptp_over_ethernet_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacTSControl,GmacTSIPENA); + return; +} +/** + * Disable time stamp snapshot for PTP over Ethernet frames. + * When disabled, time stamp snapshot is not taken for PTP over Ethernet frames + * Reserved when "Advanced Time Stamp" is not selected + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_ptp_over_ethernet_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase,GmacTSControl,GmacTSIPENA); + return; +} + + +/** + * Snoop PTP packet for version 2 format + * When set the PTP packets are snooped using the version 2 format. + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_pkt_snoop_ver2(synopGMACdevice *gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacTSControl,GmacTSVER2ENA); + return; +} +/** + * Snoop PTP packet for version 2 format + * When set the PTP packets are snooped using the version 2 format. + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_pkt_snoop_ver1(synopGMACdevice *gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase,GmacTSControl,GmacTSVER2ENA); + return; +} + +/** + * Timestamp digital rollover + * When set the timestamp low register rolls over after 0x3B9A_C9FF value. + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_digital_rollover_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacTSControl,GmacTSCTRLSSR); + return; +} +/** + * Timestamp binary rollover + * When set the timestamp low register rolls over after 0x7FFF_FFFF value. + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_binary_rollover_enable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase,GmacTSControl,GmacTSCTRLSSR); + return; +} +/** + * Enable Time Stamp for All frames + * When set the timestamp snap shot is enabled for all frames received by the core. + * Reserved when "Advanced Time Stamp" is not selected + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_all_frames_enable(synopGMACdevice *gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacTSControl,GmacTSENALL); + return; +} +/** + * Disable Time Stamp for All frames + * When reset the timestamp snap shot is not enabled for all frames received by the core. + * Reserved when "Advanced Time Stamp" is not selected + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_all_frames_disable(synopGMACdevice *gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase,GmacTSControl,GmacTSENALL); + return; +} +/** + * Addend Register Update + * This function loads the contents of Time stamp addend register with the supplied 32 value. + * This is reserved function when only coarse correction option is selected + * @param[in] pointer to synopGMACdevice + * @param[in] 32 bit addend value + * \return returns 0 for Success or else Failure + */ +s32 synopGMAC_TS_addend_update(synopGMACdevice *gmacdev, u32 addend_value) +{ + u32 loop_variable; + synopGMACWriteReg((u32 *)gmacdev->MacBase,GmacTSAddend,addend_value);// Load the addend_value in to Addend register + for(loop_variable = 0; loop_variable < DEFAULT_LOOP_VARIABLE; loop_variable++) { //Wait till the busy bit gets cleared with in a certain amount of time + if(!((synopGMACReadReg((u32 *)gmacdev->MacBase,GmacTSControl)) & GmacTSADDREG)) { // if it is cleared then break + break; + } + plat_delay(DEFAULT_DELAY_VARIABLE); + } + if(loop_variable < DEFAULT_LOOP_VARIABLE) + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacTSControl,GmacTSADDREG); + else { + TR("Error::: The TSADDREG bit is not getting cleared !!!!!!\n"); + return -ESYNOPGMACPHYERR; + } + return 0; + +} +/** + * time stamp Update + * This function updates (adds/subtracts) with the value specified in the Timestamp High Update and + * Timestamp Low Update register. + * @param[in] pointer to synopGMACdevice + * @param[in] Timestamp High Update value + * @param[in] Timestamp Low Update value + * \return returns 0 for Success or else Failure + */ +s32 synopGMAC_TS_timestamp_update(synopGMACdevice *gmacdev, u32 high_value, u32 low_value) +{ + u32 loop_variable; + synopGMACWriteReg((u32 *)gmacdev->MacBase,GmacTSHighUpdate,high_value);// Load the high value to Timestamp High register + synopGMACWriteReg((u32 *)gmacdev->MacBase,GmacTSLowUpdate,low_value);// Load the high value to Timestamp High register + for(loop_variable = 0; loop_variable < DEFAULT_LOOP_VARIABLE; loop_variable++) { //Wait till the busy bit gets cleared with in a certain amount of time + if(!((synopGMACReadReg((u32 *)gmacdev->MacBase,GmacTSControl)) & GmacTSUPDT)) { // if it is cleared then break + break; + } + plat_delay(DEFAULT_DELAY_VARIABLE); + } + if(loop_variable < DEFAULT_LOOP_VARIABLE) + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacTSControl,GmacTSUPDT); + else { + TR("Error::: The TSADDREG bit is not getting cleared !!!!!!\n"); + return -ESYNOPGMACPHYERR; + } + return 0; +} + +/** + * time stamp Initialize + * This function Loads/Initializes h the value specified in the Timestamp High Update and + * Timestamp Low Update register. + * @param[in] pointer to synopGMACdevice + * @param[in] Timestamp High Load value + * @param[in] Timestamp Low Load value + * \return returns 0 for Success or else Failure + */ +s32 synopGMAC_TS_timestamp_init(synopGMACdevice *gmacdev, u32 high_value, u32 low_value) +{ + u32 loop_variable; + synopGMACWriteReg((u32 *)gmacdev->MacBase,GmacTSHighUpdate,high_value);// Load the high value to Timestamp High register + synopGMACWriteReg((u32 *)gmacdev->MacBase,GmacTSLowUpdate,low_value);// Load the high value to Timestamp High register + for(loop_variable = 0; loop_variable < DEFAULT_LOOP_VARIABLE; loop_variable++) { //Wait till the busy bit gets cleared with in a certain amount of time + if(!((synopGMACReadReg((u32 *)gmacdev->MacBase,GmacTSControl)) & GmacTSINT)) { // if it is cleared then break + break; + } + plat_delay(DEFAULT_DELAY_VARIABLE); + } + if(loop_variable < DEFAULT_LOOP_VARIABLE) + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacTSControl,GmacTSINT); + else { + TR("Error::: The TSADDREG bit is not getting cleared !!!!!!\n"); + return -ESYNOPGMACPHYERR; + } + return 0; +} + +/** + * Time Stamp Update Coarse + * When reset the timestamp update is done using coarse method. + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_coarse_update(synopGMACdevice *gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase,GmacTSControl,GmacTSCFUPDT); + return; +} +/** + * Time Stamp Update Fine + * When reset the timestamp update is done using Fine method. + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_fine_update(synopGMACdevice *gmacdev) +{ + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacTSControl,GmacTSCFUPDT); + return; +} + +/** + * Load the Sub Second Increment value in to Sub Second increment register + * @param[in] pointer to synopGMACdevice + * \return returns void + */ +void synopGMAC_TS_subsecond_init(synopGMACdevice *gmacdev, u32 sub_sec_inc_value) +{ + synopGMACWriteReg((u32 *)gmacdev->MacBase,GmacTSSubSecIncr,(sub_sec_inc_value & GmacSSINCMsk)); + return; +} +/** + * Reads the time stamp contents in to the respective pointers + * These registers are readonly. + * This function returns the 48 bit time stamp assuming Version 2 timestamp with higher word is selected. + * @param[in] pointer to synopGMACdevice + * @param[in] pointer to hold 16 higher bit second register contents + * @param[in] pointer to hold 32 bit second register contents + * @param[in] pointer to hold 32 bit subnanosecond register contents + * \return returns void + * \note Please note that since the atomic access to the timestamp registers is not possible, + * the contents read may be different from the actual time stamp. + */ +void synopGMAC_TS_read_timestamp(synopGMACdevice *gmacdev, u16 * higher_sec_val, u32 * sec_val, u32 * sub_sec_val) +{ + * higher_sec_val = (u16)(synopGMACReadReg((u32 *)gmacdev->MacBase,GmacTSHighWord) & GmacTSHighWordMask); + * sec_val = synopGMACReadReg((u32 *)gmacdev->MacBase,GmacTSHigh); + * sub_sec_val = synopGMACReadReg((u32 *)gmacdev->MacBase,GmacTSLow); + return; +} +/** + * Loads the time stamp higher sec value from the value supplied + * @param[in] pointer to synopGMACdevice + * @param[in] 16 higher bit second register contents passed as 32 bit value + * \return returns void + */ +void synopGMAC_TS_load_timestamp_higher_val(synopGMACdevice *gmacdev, u32 higher_sec_val) +{ + synopGMACWriteReg((u32 *)gmacdev->MacBase,GmacTSHighWord, (higher_sec_val & GmacTSHighWordMask)); + return; +} +/** + * Reads the time stamp higher sec value to respective pointers + * @param[in] pointer to synopGMACdevice + * @param[in] pointer to hold 16 higher bit second register contents + * \return returns void + */ +void synopGMAC_TS_read_timestamp_higher_val(synopGMACdevice *gmacdev, u16 * higher_sec_val) +{ + * higher_sec_val = (u16)(synopGMACReadReg((u32 *)gmacdev->MacBase,GmacTSHighWord) & GmacTSHighWordMask); + return; +} +/** + * Load the Target time stamp registers + * This function Loads the target time stamp registers with the values proviced + * @param[in] pointer to synopGMACdevice + * @param[in] target Timestamp High value + * @param[in] target Timestamp Low value + * \return returns 0 for Success or else Failure + */ +void synopGMAC_TS_load_target_timestamp(synopGMACdevice *gmacdev, u32 sec_val, u32 sub_sec_val) +{ + synopGMACWriteReg((u32 *)gmacdev->MacBase,GmacTSTargetTimeHigh,sec_val); + synopGMACWriteReg((u32 *)gmacdev->MacBase,GmacTSTargetTimeLow,sub_sec_val); + return; +} +/** + * Reads the Target time stamp registers + * This function Loads the target time stamp registers with the values proviced + * @param[in] pointer to synopGMACdevice + * @param[in] pointer to hold target Timestamp High value + * @param[in] pointer to hold target Timestamp Low value + * \return returns 0 for Success or else Failure + */ +void synopGMAC_TS_read_target_timestamp(synopGMACdevice *gmacdev, u32 * sec_val, u32 * sub_sec_val) +{ + * sec_val = synopGMACReadReg((u32 *)gmacdev->MacBase,GmacTSTargetTimeHigh); + * sub_sec_val = synopGMACReadReg((u32 *)gmacdev->MacBase,GmacTSTargetTimeLow); + return; +} + +void synopGMAC_src_addr_insert_enable(synopGMACdevice * gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase,GmacConfig,GmacSrcAddrInsRpl); + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacConfig,GmacSrcAddrIns); + +} +void synopGMAC_src_addr_insert_disable(synopGMACdevice * gmacdev) +{ + + synopGMACClearBits((u32 *)gmacdev->MacBase,GmacConfig,GmacSrcAddrInsRpl); + +} +void synopGMAC_src_addr_replace_enable(synopGMACdevice * gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase,GmacConfig,GmacSrcAddrInsRpl); + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacConfig,GmacSrcAddrRpl); + + +} +void synopGMAC_src_addr_replace_disable(synopGMACdevice * gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase,GmacConfig,GmacSrcAddrInsRpl); + +} + + +void synopGMAC_svlan_insertion_enable(synopGMACdevice * gmacdev, u16 vlantag) +{ + + synopGMACWriteReg((u32 *)gmacdev->MacBase, GmacVLANIncRep, GmacVLP | GmacSVLAN | GmacVLANIns| vlantag); + + +} + +void synopGMAC_cvlan_insertion_enable(synopGMACdevice * gmacdev, u16 vlantag) +{ + synopGMACWriteReg((u32 *)gmacdev->MacBase, GmacVLANIncRep, GmacVLP | GmacCVLAN | GmacVLANIns | vlantag); + + +} + +void synopGMAC_svlan_replace_enable(synopGMACdevice * gmacdev, u16 vlantag) +{ + synopGMACWriteReg((u32 *)gmacdev->MacBase, GmacVLANIncRep, GmacVLP | GmacSVLAN | GmacVLANRep | vlantag); + +} + +void synopGMAC_cvlan_replace_enable(synopGMACdevice * gmacdev, u16 vlantag) +{ + synopGMACWriteReg((u32 *)gmacdev->MacBase, GmacVLANIncRep, GmacVLP | GmacCVLAN | GmacVLANRep | vlantag); + +} + +void synopGMAC_vlan_deletion_enable(synopGMACdevice * gmacdev) +{ + synopGMACWriteReg((u32 *)gmacdev->MacBase, GmacVLANIncRep, GmacVLP | GmacVLANDel); + + +} + + +void synopGMAC_vlan_no_act_enable(synopGMACdevice * gmacdev) +{ + synopGMACClearBits((u32 *)gmacdev->MacBase, GmacVLANIncRep, 0xFFFFFFFF); +} + + diff --git a/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/synopGMAC_Dev.h b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/synopGMAC_Dev.h new file mode 100644 index 0000000000..011feb293a --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/synopGMAC_Dev.h @@ -0,0 +1,1500 @@ +/* =================================================================================== + * Copyright (c) <2009> Synopsys, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software annotated with this license and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without + * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * =================================================================================== */ + +/**\file + * This file defines the function prototypes for the Synopsys GMAC device and the + * Marvell 88E1011/88E1011S integrated 10/100/1000 Gigabit Ethernet Transceiver. + * Since the phy register mapping are standardised, the phy register map and the + * bit definitions remain the same for other phy as well. + * This also defines some of the Ethernet related parmeters. + * \internal + * -----------------------------REVISION HISTORY------------------------------------ + * Synopsys 01/Aug/2007 Created + */ + + +#ifndef SYNOP_GMAC_DEV_H +#define SYNOP_GMAC_DEV_H 1 + +#include "synopGMAC_plat.h" + +#define GMAC_CNT 1 + +/*SynopGMAC can support up to 32 phys*/ + +enum GMACPhyBase { + PHY0 = 0, //The device can support 32 phys, but we use first phy only + PHY1 = 1, + PHY31 = 31, +}; + +#define DEFAULT_PHY_BASE PHY1 //We use First Phy + +#define GMAC0MappedAddr EMAC_BASE //0x40012000 +#define GMAC1MappedAddr EMAC_BASE +#define MACBASE 0x0000 // The Mac Base address offset is 0x0000 +#define DMABASE 0x1000 // Dma base address starts with an offset 0x1000 + + +#define TRANSMIT_DESC_SIZE 4//32//256 //Tx Descriptors needed in the Descriptor pool/queue +#define RECEIVE_DESC_SIZE 4//32//256 //Rx Descriptors needed in the Descriptor pool/queue + +#define ETHERNET_HEADER 14 //6 byte Dest addr, 6 byte Src addr, 2 byte length/type +#define ETHERNET_CRC 4 //Ethernet CRC +#define ETHERNET_EXTRA 2 //Only God knows about this????? +#define ETHERNET_PACKET_COPY 250 // Maximum length when received data is copied on to a new skb +#define ETHERNET_PACKET_EXTRA 18 // Preallocated length for the rx packets is MTU + ETHERNET_PACKET_EXTRA +#define VLAN_TAG 4 //optional 802.1q VLAN Tag +#define MIN_ETHERNET_PAYLOAD 46 //Minimum Ethernet payload size +#define MAX_ETHERNET_PAYLOAD 1500 //Maximum Ethernet payload size +#define JUMBO_FRAME_PAYLOAD 9000 //Jumbo frame payload size + +#define TX_BUF_SIZE ETHERNET_HEADER + ETHERNET_CRC + MAX_ETHERNET_PAYLOAD + VLAN_TAG + + +// This is the IP's phy address. This is unique address for every MAC in the universe +#define DEFAULT_MAC0_ADDRESS {0x00, 0x55, 0x7B, 0xB5, 0x7D, 0xF7} +#define DEFAULT_MAC1_ADDRESS {0x00, 0x55, 0x7B, 0xB5, 0x7D, 0xF8} +/* +DMA Descriptor Structure +The structure is common for both receive and transmit descriptors +The descriptor is of 4 words, but our structrue contains 6 words where +last two words are to hold the virtual address of the network buffer pointers +for driver's use +From the GMAC core release 3.50a onwards, the Enhanced Descriptor structure got changed. +The descriptor (both transmit and receive) are of 8 words each rather the 4 words of normal +descriptor structure. +Whenever IEEE 1588 Timestamping is enabled TX/RX DESC6 provides the lower 32 bits of Timestamp value and + TX/RX DESC7 provides the upper 32 bits of Timestamp value +In addition to this whenever extended status bit is set (RX DESC0 bit 0), RX DESC4 contains the extended status information +*/ + +#define MODULO_INTERRUPT 1 // if it is set to 1, interrupt is available for all the descriptors or else interrupt is available only for +// descriptor whose index%MODULO_INTERRUPT is zero +typedef struct DmaDescStruct { + u32 status; /* Status */ + u32 length; /* Buffer 1 and Buffer 2 length */ + u32 buffer1; /* Network Buffer 1 pointer (Dma-able) */ + u32 buffer2; /* Network Buffer 2 pointer or next descriptor pointer (Dma-able)in chain structure */ + /* This data below is used only by driver */ + u32 extstatus; /* Extended status of a Rx Descriptor */ + u32 reserved1; /* Reserved word */ + u32 timestamplow; /* Lower 32 bits of the 64 bit timestamp value */ + u32 timestamphigh; /* Higher 32 bits of the 64 bit timestamp value */ + //u32 data1; /* This holds virtual address of buffer1, not used by DMA */ + //u32 data2; /* This holds virtual address of buffer2, not used by DMA */ +} DmaDesc; + +enum DescMode { + RINGMODE = 0x00000001, + CHAINMODE = 0x00000002, +}; + +enum BufferMode { + SINGLEBUF = 0x00000001, + DUALBUF = 0x00000002, +}; + +typedef u32 * dma_addr_t; + +/* synopGMAC device data */ + +struct sk_buff { + unsigned char data[2048]; + unsigned int len; + unsigned int volatile rdy; +}; + +struct net_device_stats { + u32 tx_bytes; + u32 tx_packets; + u32 tx_errors; + u32 tx_aborted_errors; + u32 tx_carrier_errors; + u32 tx_ip_header_errors; + u32 tx_ip_payload_errors; + u32 collisions; + u32 rx_bytes; + u32 rx_packets; + u32 rx_errors; + u32 rx_crc_errors; + u32 rx_frame_errors; + u32 rx_length_errors; + u32 rx_dropped; + u32 rx_over_errors; + u32 rx_ip_header_errors; + u32 rx_ip_payload_errors; + volatile u32 ts_int; +}; + +typedef struct synopGMACDeviceStruct { + u64 MacBase; /* base address of MAC registers */ + u64 DmaBase; /* base address of DMA registers */ + u64 PhyBase; /* PHY device address on MII interface */ + u64 Version; /* Gmac Revision version */ + + + /*dma_addr_t*/ DmaDesc *TxDescDma; /* Dma-able address of first tx descriptor either in ring or chain mode, this is used by the GMAC device*/ + /*dma_addr_t*/ DmaDesc *RxDescDma; /* Dma-albe address of first rx descriptor either in ring or chain mode, this is used by the GMAC device*/ + DmaDesc *TxDesc; /* start address of TX descriptors ring or chain, this is used by the driver */ + DmaDesc *RxDesc; /* start address of RX descriptors ring or chain, this is used by the driver */ + + u32 BusyTxDesc; /* Number of Tx Descriptors owned by DMA at any given time*/ + u32 BusyRxDesc; /* Number of Rx Descriptors owned by DMA at any given time*/ + + u32 RxDescCount; /* number of rx descriptors in the tx descriptor queue/pool */ + u32 TxDescCount; /* number of tx descriptors in the rx descriptor queue/pool */ + + u32 TxBusy; /* index of the tx descriptor owned by DMA, is obtained by synopGMAC_get_tx_qptr() */ + u32 TxNext; /* index of the tx descriptor next available with driver, given to DMA by synopGMAC_set_tx_qptr() */ + u32 RxBusy; /* index of the rx descriptor owned by DMA, obtained by synopGMAC_get_rx_qptr() */ + u32 RxNext; /* index of the rx descriptor next available with driver, given to DMA by synopGMAC_set_rx_qptr() */ + + DmaDesc * TxBusyDesc; /* Tx Descriptor address corresponding to the index TxBusy */ + DmaDesc * TxNextDesc; /* Tx Descriptor address corresponding to the index TxNext */ + DmaDesc * RxBusyDesc; /* Rx Descriptor address corresponding to the index TxBusy */ + DmaDesc * RxNextDesc; /* Rx Descriptor address corresponding to the index RxNext */ + + + /*Phy related stuff*/ + u32 ClockDivMdc; /* Clock divider value programmed in the hardware */ + /* The status of the link */ + u32 LinkState; /* Link status as reported by the Marvel Phy */ + u32 DuplexMode; /* Duplex mode of the Phy */ + u32 Speed; /* Speed of the Phy */ + u32 LoopBackMode; /* Loopback status of the Phy */ + u32 Intf; + struct net_device_stats synopGMACNetStats; + + u32 tx_sec; + u32 tx_subsec; + u32 rx_sec; + u32 rx_subsec; + + u32 GMAC_Power_down; + +} synopGMACdevice; + + +/* Below is "88E1011/88E1011S Integrated 10/100/1000 Gigabit Ethernet Transceiver" + * Register and their layouts. This Phy has been used in the Dot Aster GMAC Phy daughter. + * Since the Phy register map is standard, this map hardly changes to a different Ppy + */ + +enum MiiRegisters { + PHY_CONTROL_REG = 0x0000, /*Control Register*/ + PHY_STATUS_REG = 0x0001, /*Status Register */ + PHY_ID_HI_REG = 0x0002, /*PHY Identifier High Register*/ + PHY_ID_LOW_REG = 0x0003, /*PHY Identifier High Register*/ + PHY_AN_ADV_REG = 0x0004, /*Auto-Negotiation Advertisement Register*/ + PHY_LNK_PART_ABl_REG = 0x0005, /*Link Partner Ability Register (Base Page)*/ + PHY_AN_EXP_REG = 0x0006, /*Auto-Negotiation Expansion Register*/ + PHY_AN_NXT_PAGE_TX_REG = 0x0007, /*Next Page Transmit Register*/ + PHY_LNK_PART_NXT_PAGE_REG = 0x0008, /*Link Partner Next Page Register*/ + PHY_1000BT_CTRL_REG = 0x0009, /*1000BASE-T Control Register*/ + PHY_1000BT_STATUS_REG = 0x000a, /*1000BASE-T Status Register*/ + PHY_SPECIFIC_CTRL_REG = 0x0010, /*Phy specific control register*/ + PHY_SPECIFIC_STATUS_REG = 0x0011, /*Phy specific status register*/ + PHY_INTERRUPT_ENABLE_REG = 0x0012, /*Phy interrupt enable register*/ + PHY_INTERRUPT_STATUS_REG = 0x0013, /*Phy interrupt status register*/ + PHY_EXT_PHY_SPC_CTRL = 0x0014, /*Extended Phy specific control*/ + PHY_RX_ERR_COUNTER = 0x0015, /*Receive Error Counter*/ + PHY_EXT_ADDR_CBL_DIAG = 0x0016, /*Extended address for cable diagnostic register*/ + PHY_LED_CONTROL = 0x0018, /*LED Control*/ + PHY_MAN_LED_OVERIDE = 0x0019, /*Manual LED override register*/ + PHY_EXT_PHY_SPC_CTRL2 = 0x001a, /*Extended Phy specific control 2*/ + PHY_EXT_PHY_SPC_STATUS = 0x001b, /*Extended Phy specific status*/ + PHY_CBL_DIAG_REG = 0x001c, /*Cable diagnostic registers*/ +}; + + +/* This is Control register layout. Control register is of 16 bit wide. +*/ + +enum Mii_GEN_CTRL { + /* Description bits R/W default value */ + Mii_reset = 0x8000, + Mii_Speed_10 = 0x0000, /* 10 Mbps 6:13 RW */ + Mii_Speed_100 = 0x2000, /* 100 Mbps 6:13 RW */ + Mii_Speed_1000 = 0x0040, /* 1000 Mbit/s 6:13 RW */ + + Mii_Duplex = 0x0100, /* Full Duplex mode 8 RW */ + + Mii_Manual_Master_Config = 0x0800, /* Manual Master Config 11 RW */ + + Mii_Loopback = 0x4000, /* Enable Loop back 14 RW */ + Mii_NoLoopback = 0x0000, /* Enable Loop back 14 RW */ +}; + +enum Mii_Phy_Status { + Mii_phy_status_speed_10 = 0x0000, + Mii_phy_status_speed_100 = 0x4000, + Mii_phy_status_speed_1000 = 0x8000, + + Mii_phy_status_full_duplex = 0x2000, + Mii_phy_status_half_duplex = 0x0000, + + Mii_phy_status_link_up = 0x0400, +}; +/* This is Status register layout. Status register is of 16 bit wide. +*/ +enum Mii_GEN_STATUS { + Mii_AutoNegCmplt = 0x0020, /* Autonegotiation completed 5 RW */ + Mii_Link = 0x0004, /* Link status 2 RW */ +}; + +enum Mii_Link_Status { + LINKDOWN = 0, + LINKUP = 1, +}; + +enum Mii_Duplex_Mode { + HALFDUPLEX = 1, + FULLDUPLEX = 2, +}; +enum Mii_Link_Speed { + SPEED10 = 1, + SPEED100 = 2, + SPEED1000 = 3, +}; + +enum Mii_Loop_Back { + NOLOOPBACK = 0, + LOOPBACK = 1, +}; + + + +/********************************************************** + * GMAC registers Map + * For Pci based system address is BARx + GmacRegisterBase + * For any other system translation is done accordingly + **********************************************************/ +enum GmacRegisters { + GmacConfig = 0x0000, /* Mac config Register */ + GmacFrameFilter = 0x0004, /* Mac frame filtering controls */ + GmacHashHigh = 0x0008, /* Multi-cast hash table high */ + GmacHashLow = 0x000C, /* Multi-cast hash table low */ + GmacGmiiAddr = 0x0010, /* GMII address Register(ext. Phy) */ + GmacGmiiData = 0x0014, /* GMII data Register(ext. Phy) */ + GmacFlowControl = 0x0018, /* Flow control Register */ + GmacVlan = 0x001C, /* VLAN tag Register (IEEE 802.1Q) */ + + GmacVersion = 0x0020, /* GMAC Core Version Register */ + GmacDebug = 0x0024, /* GMAC Debug Register */ + GmacWakeupAddr = 0x0028, /* GMAC wake-up frame filter adrress reg */ + GmacPmtCtrlStatus = 0x002C, /* PMT control and status register */ + + + GmacLPICtrlSts = 0x0030, /* LPI (low power idle) Control and Status Register */ + GmacLPITimerCtrl = 0x0034, /* LPI timer control register */ + + + GmacInterruptStatus = 0x0038, /* Mac Interrupt ststus register */ + GmacInterruptMask = 0x003C, /* Mac Interrupt Mask register */ + + GmacAddr0High = 0x0040, /* Mac address0 high Register */ + GmacAddr0Low = 0x0044, /* Mac address0 low Register */ + GmacAddr1High = 0x0048, /* Mac address1 high Register */ + GmacAddr1Low = 0x004C, /* Mac address1 low Register */ + GmacAddr2High = 0x0050, /* Mac address2 high Register */ + GmacAddr2Low = 0x0054, /* Mac address2 low Register */ + GmacAddr3High = 0x0058, /* Mac address3 high Register */ + GmacAddr3Low = 0x005C, /* Mac address3 low Register */ + GmacAddr4High = 0x0060, /* Mac address4 high Register */ + GmacAddr4Low = 0x0064, /* Mac address4 low Register */ + GmacAddr5High = 0x0068, /* Mac address5 high Register */ + GmacAddr5Low = 0x006C, /* Mac address5 low Register */ + GmacAddr6High = 0x0070, /* Mac address6 high Register */ + GmacAddr6Low = 0x0074, /* Mac address6 low Register */ + GmacAddr7High = 0x0078, /* Mac address7 high Register */ + GmacAddr7Low = 0x007C, /* Mac address7 low Register */ + GmacAddr8High = 0x0080, /* Mac address8 high Register */ + GmacAddr8Low = 0x0084, /* Mac address8 low Register */ + GmacAddr9High = 0x0088, /* Mac address9 high Register */ + GmacAddr9Low = 0x008C, /* Mac address9 low Register */ + GmacAddr10High = 0x0090, /* Mac address10 high Register */ + GmacAddr10Low = 0x0094, /* Mac address10 low Register */ + GmacAddr11High = 0x0098, /* Mac address11 high Register */ + GmacAddr11Low = 0x009C, /* Mac address11 low Register */ + GmacAddr12High = 0x00A0, /* Mac address12 high Register */ + GmacAddr12Low = 0x00A4, /* Mac address12 low Register */ + GmacAddr13High = 0x00A8, /* Mac address13 high Register */ + GmacAddr13Low = 0x00AC, /* Mac address13 low Register */ + GmacAddr14High = 0x00B0, /* Mac address14 high Register */ + GmacAddr14Low = 0x00B4, /* Mac address14 low Register */ + GmacAddr15High = 0x00B8, /* Mac address15 high Register */ + GmacAddr15Low = 0x00BC, /* Mac address15 low Register */ + GmacRgmiiCtrlSts = 0x00D8, /*SGMII_RGMII_SMII_Control_Status Register */ + GmacVLANIncRep = 0x0584, + /*Time Stamp Register Map*/ + GmacTSControl = 0x0700, /* Controls the Timestamp update logic : only when IEEE 1588 time stamping is enabled in corekit */ + + GmacTSSubSecIncr = 0x0704, /* 8 bit value by which sub second register is incremented : only when IEEE 1588 time stamping without external timestamp input */ + + GmacTSHigh = 0x0708, /* 32 bit seconds(MS) : only when IEEE 1588 time stamping without external timestamp input */ + GmacTSLow = 0x070C, /* 32 bit nano seconds(MS) : only when IEEE 1588 time stamping without external timestamp input */ + + GmacTSHighUpdate = 0x0710, /* 32 bit seconds(MS) to be written/added/subtracted : only when IEEE 1588 time stamping without external timestamp input */ + GmacTSLowUpdate = 0x0714, /* 32 bit nano seconds(MS) to be writeen/added/subtracted : only when IEEE 1588 time stamping without external timestamp input */ + + GmacTSAddend = 0x0718, /* Used by Software to readjust the clock frequency linearly : only when IEEE 1588 time stamping without external timestamp input */ + + GmacTSTargetTimeHigh = 0x071C, /* 32 bit seconds(MS) to be compared with system time : only when IEEE 1588 time stamping without external timestamp input */ + GmacTSTargetTimeLow = 0x0720, /* 32 bit nano seconds(MS) to be compared with system time : only when IEEE 1588 time stamping without external timestamp input */ + + GmacTSHighWord = 0x0724, /* Time Stamp Higher Word Register (Version 2 only); only lower 16 bits are valid */ + //GmacTSHighWordUpdate = 0x072C, /* Time Stamp Higher Word Update Register (Version 2 only); only lower 16 bits are valid */ + + GmacTSStatus = 0x0728, /* Time Stamp Status Register */ + GmacPPSCtrl = 0x072C, /* PPS Control Register */ + GmacPPSInt = 0x0760, /* PPS0 Interval Register */ + GmacPPSWidth = 0x0764, /* PPS0 Width Register */ +}; + +/********************************************************** + * GMAC Network interface registers + * This explains the Register's Layout + + * FES is Read only by default and is enabled only when Tx + * Config Parameter is enabled for RGMII/SGMII interface + * during CoreKit Config. + + * DM is Read only with value 1'b1 in Full duplex only Config + **********************************************************/ + +/* GmacConfig = 0x0000, Mac config Register Layout */ +enum GmacConfigReg { + /* Bit description Bits R/W Reset value */ + + GmacSrcAddrInsRpl = 0x70000000, + GmacSrcAddrIns = 0x20000000, + GmacSrcAddrRpl = 0x30000000, + GmacWatchdog = 0x00800000, + GmacWatchdogDisable = 0x00800000, /* (WD)Disable watchdog timer on Rx 23 RW */ + GmacWatchdogEnable = 0x00000000, /* Enable watchdog timer 0 */ + + GmacJabber = 0x00400000, + GmacJabberDisable = 0x00400000, /* (JD)Disable jabber timer on Tx 22 RW */ + GmacJabberEnable = 0x00000000, /* Enable jabber timer 0 */ + + GmacFrameBurst = 0x00200000, + GmacFrameBurstEnable = 0x00200000, /* (BE)Enable frame bursting during Tx 21 RW */ + GmacFrameBurstDisable = 0x00000000, /* Disable frame bursting 0 */ + + GmacJumboFrame = 0x00100000, + GmacJumboFrameEnable = 0x00100000, /* (JE)Enable jumbo frame for Tx 20 RW */ + GmacJumboFrameDisable = 0x00000000, /* Disable jumbo frame 0 */ + + GmacInterFrameGap7 = 0x000E0000, /* (IFG) Config7 - 40 bit times 19:17 RW */ + GmacInterFrameGap6 = 0x000C0000, /* (IFG) Config6 - 48 bit times */ + GmacInterFrameGap5 = 0x000A0000, /* (IFG) Config5 - 56 bit times */ + GmacInterFrameGap4 = 0x00080000, /* (IFG) Config4 - 64 bit times */ + GmacInterFrameGap3 = 0x00040000, /* (IFG) Config3 - 72 bit times */ + GmacInterFrameGap2 = 0x00020000, /* (IFG) Config2 - 80 bit times */ + GmacInterFrameGap1 = 0x00010000, /* (IFG) Config1 - 88 bit times */ + GmacInterFrameGap0 = 0x00000000, /* (IFG) Config0 - 96 bit times 000 */ + + GmacDisableCrs = 0x00010000, + GmacMiiGmii = 0x00008000, + GmacSelectMii = 0x00008000, /* (PS)Port Select-MII mode 15 RW */ + GmacSelectGmii = 0x00000000, /* GMII mode 0 */ + + GmacFESpeed100 = 0x00004000, /*(FES)Fast Ethernet speed 100Mbps 14 RW */ + GmacFESpeed10 = 0x00000000, /* 10Mbps 0 */ + + GmacRxOwn = 0x00002000, + GmacDisableRxOwn = 0x00002000, /* (DO)Disable receive own packets 13 RW */ + GmacEnableRxOwn = 0x00000000, /* Enable receive own packets 0 */ + + GmacLoopback = 0x00001000, + GmacLoopbackOn = 0x00001000, /* (LM)Loopback mode for GMII/MII 12 RW */ + GmacLoopbackOff = 0x00000000, /* Normal mode 0 */ + + GmacDuplex = 0x00000800, + GmacFullDuplex = 0x00000800, /* (DM)Full duplex mode 11 RW */ + GmacHalfDuplex = 0x00000000, /* Half duplex mode 0 */ + + GmacRxIpcOffload = 0x00000400, /*IPC checksum offload 10 RW 0 */ + + GmacRetry = 0x00000200, + GmacRetryDisable = 0x00000200, /* (DR)Disable Retry 9 RW */ + GmacRetryEnable = 0x00000000, /* Enable retransmission as per BL 0 */ + + GmacLinkUp = 0x00000100, /* (LUD)Link UP 8 RW */ + GmacLinkDown = 0x00000100, /* Link Down 0 */ + + GmacPadCrcStrip = 0x00000080, + GmacPadCrcStripEnable = 0x00000080, /* (ACS) Automatic Pad/Crc strip enable 7 RW */ + GmacPadCrcStripDisable = 0x00000000, /* Automatic Pad/Crc stripping disable 0 */ + + GmacBackoffLimit = 0x00000060, + GmacBackoffLimit3 = 0x00000060, /* (BL)Back-off limit in HD mode 6:5 RW */ + GmacBackoffLimit2 = 0x00000040, /* */ + GmacBackoffLimit1 = 0x00000020, /* */ + GmacBackoffLimit0 = 0x00000000, /* 00 */ + + GmacDeferralCheck = 0x00000010, + GmacDeferralCheckEnable = 0x00000010, /* (DC)Deferral check enable in HD mode 4 RW */ + GmacDeferralCheckDisable = 0x00000000, /* Deferral check disable 0 */ + + GmacTx = 0x00000008, + GmacTxEnable = 0x00000008, /* (TE)Transmitter enable 3 RW */ + GmacTxDisable = 0x00000000, /* Transmitter disable 0 */ + + GmacRx = 0x00000004, + GmacRxEnable = 0x00000004, /* (RE)Receiver enable 2 RW */ + GmacRxDisable = 0x00000000, /* Receiver disable 0 */ +}; + +/* GmacFrameFilter = 0x0004, Mac frame filtering controls Register Layout*/ +enum GmacFrameFilterReg { + GmacFilter = 0x80000000, + GmacFilterOff = 0x80000000, /* (RA)Receive all incoming packets 31 RW */ + GmacFilterOn = 0x00000000, /* Receive filtered packets only 0 */ + GmacVlanTagFilter = 0x00010000, /*VLAN tag filter enable 16 RW 0 */ + GmacHashPerfectFilter = 0x00000400, /*Hash or Perfect Filter enable 10 RW 0 */ + + GmacSrcAddrFilter = 0x00000200, + GmacSrcAddrFilterEnable = 0x00000200, /* (SAF)Source Address Filter enable 9 RW */ + GmacSrcAddrFilterDisable = 0x00000000, /* 0 */ + + GmacSrcInvaAddrFilter = 0x00000100, + GmacSrcInvAddrFilterEn = 0x00000100, /* (SAIF)Inv Src Addr Filter enable 8 RW */ + GmacSrcInvAddrFilterDis = 0x00000000, /* 0 */ + + GmacPassControl = 0x000000C0, + GmacPassControl3 = 0x000000C0, /* (PCS)Forwards ctrl frms that pass AF 7:6 RW */ + GmacPassControl2 = 0x00000080, /* Forwards all control frames */ + GmacPassControl1 = 0x00000040, /* Does not pass control frames */ + GmacPassControl0 = 0x00000000, /* Does not pass control frames 00 */ + + GmacBroadcast = 0x00000020, + GmacBroadcastDisable = 0x00000020, /* (DBF)Disable Rx of broadcast frames 5 RW */ + GmacBroadcastEnable = 0x00000000, /* Enable broadcast frames 0 */ + + GmacMulticastFilter = 0x00000010, + GmacMulticastFilterOff = 0x00000010, /* (PM) Pass all multicast packets 4 RW */ + GmacMulticastFilterOn = 0x00000000, /* Pass filtered multicast packets 0 */ + + GmacDestAddrFilter = 0x00000008, + GmacDestAddrFilterInv = 0x00000008, /* (DAIF)Inverse filtering for DA 3 RW */ + GmacDestAddrFilterNor = 0x00000000, /* Normal filtering for DA 0 */ + + GmacMcastHashFilter = 0x00000004, + GmacMcastHashFilterOn = 0x00000004, /* (HMC)perfom multicast hash filtering 2 RW */ + GmacMcastHashFilterOff = 0x00000000, /* perfect filtering only 0 */ + + GmacUcastHashFilter = 0x00000002, + GmacUcastHashFilterOn = 0x00000002, /* (HUC)Unicast Hash filtering only 1 RW */ + GmacUcastHashFilterOff = 0x00000000, /* perfect filtering only 0 */ + + GmacPromiscuousMode = 0x00000001, + GmacPromiscuousModeOn = 0x00000001, /* Receive all frames 0 RW */ + GmacPromiscuousModeOff = 0x00000000, /* Receive filtered packets only 0 */ +}; + + +/*GmacGmiiAddr = 0x0010, GMII address Register(ext. Phy) Layout */ +enum GmacGmiiAddrReg { + GmiiDevMask = 0x0000F800, /* (PA)GMII device address 15:11 RW 0x00 */ + GmiiDevShift = 11, + + GmiiRegMask = 0x000007C0, /* (GR)GMII register in selected Phy 10:6 RW 0x00 */ + GmiiRegShift = 6, + + GmiiCsrClkMask = 0x0000001C, /*CSR Clock bit Mask 4:2 */ + GmiiCsrClk5 = 0x00000014, /* (CR)CSR Clock Range 250-300 MHz 4:2 RW 000 */ + GmiiCsrClk4 = 0x00000010, /* 150-250 MHz */ + GmiiCsrClk3 = 0x0000000C, /* 35-60 MHz */ + GmiiCsrClk2 = 0x00000008, /* 20-35 MHz */ + GmiiCsrClk1 = 0x00000004, /* 100-150 MHz */ + GmiiCsrClk0 = 0x00000000, /* 60-100 MHz */ + + GmiiWrite = 0x00000002, /* (GW)Write to register 1 RW */ + GmiiRead = 0x00000000, /* Read from register 0 */ + + GmiiBusy = 0x00000001, /* (GB)GMII interface is busy 0 RW 0 */ +}; + +enum GmacVlanTagReg { + GmacEnableSVlan = 0x00040000, /* (ESVL) Enabe S-Vlan */ + GmacVlanInvMatch = 0x00020000, /* (VTIM) VLAN tag inverse match enable */ + GmacEnable12BitComp = 0x00010000, /* (ETV) Enable 12-bit VLAN tag comparision */ + GmacVlanTagMsk = 0x0000FFFF /* (VL) VLAN tag */ + +}; + + +enum GmacLPICtrlStsReg { + GmacLPITxAuto = 0x00080000, + GmacLPIPhyStsEn = 0x00040000, + GmacLPIPhySts = 0x00020000, + GmacLPIEn = 0x00010000, + GmacRxLPISts = 0x00000200, + GmacTxLPISts = 0x00000100, + GmacRxLPIExit = 0x00000008, + GmacRxLPIEnter = 0x00000004, + GmacTxLPIExit = 0x00000002, + GmacTxLPIEnter = 0x00000001, +}; + +enum GmacLPITimerCtrlReg { + GmacLPILinkStableTimerMsk = 0x03FF0000, + GmacLPITxWaitTimerMsk = 0x0000FFFF, +}; + + +/* GmacGmiiData = 0x0014, GMII data Register(ext. Phy) Layout */ +enum GmacGmiiDataReg { + GmiiDataMask = 0x0000FFFF, /* (GD)GMII Data 15:0 RW 0x0000 */ +}; + + +/*GmacFlowControl = 0x0018, Flow control Register Layout */ +enum GmacFlowControlReg { + GmacPauseTimeMask = 0xFFFF0000, /* (PT) PAUSE TIME field in the control frame 31:16 RW 0x0000 */ + GmacPauseTimeShift = 16, + + GmacPauseLowThresh = 0x00000030, + GmacPauseLowThresh3 = 0x00000030, /* (PLT)thresh for pause tmr 256 slot time 5:4 RW */ + GmacPauseLowThresh2 = 0x00000020, /* 144 slot time */ + GmacPauseLowThresh1 = 0x00000010, /* 28 slot time */ + GmacPauseLowThresh0 = 0x00000000, /* 4 slot time 000 */ + + GmacUnicastPauseFrame = 0x00000008, + GmacUnicastPauseFrameOn = 0x00000008, /* (UP)Detect pause frame with unicast addr. 3 RW */ + GmacUnicastPauseFrameOff = 0x00000000, /* Detect only pause frame with multicast addr. 0 */ + + GmacRxFlowControl = 0x00000004, + GmacRxFlowControlEnable = 0x00000004, /* (RFE)Enable Rx flow control 2 RW */ + GmacRxFlowControlDisable = 0x00000000, /* Disable Rx flow control 0 */ + + GmacTxFlowControl = 0x00000002, + GmacTxFlowControlEnable = 0x00000002, /* (TFE)Enable Tx flow control 1 RW */ + GmacTxFlowControlDisable = 0x00000000, /* Disable flow control 0 */ + + GmacFlowControlBackPressure= 0x00000001, + GmacSendPauseFrame = 0x00000001, /* (FCB/PBA)send pause frm/Apply back pressure 0 RW 0 */ +}; + + +enum GmacVLANIncRepReg { + GmacSVLAN = 0x00080000, + GmacCVLAN = 0x00000000, + GmacVLP = 0x00040000, + GmacVLANNoACT = 0x00000000, + GmacVLANDel = 0x00010000, + GmacVLANIns = 0x00020000, + GmacVLANRep = 0x00030000, + GmacVLANMsk = 0x0000FFFF + +}; + +/* GmacInterruptStatus = 0x0038, Mac Interrupt ststus register */ +enum GmacInterruptStatusBitDefinition { + GmacLPIIntSts = 0x00000400, /* set if int generated due to TS (Read Time Stamp Status Register to know details)*/ + GmacTSIntSts = 0x00000200, /* set if int generated due to TS (Read Time Stamp Status Register to know details)*/ + GmacMmcRxChksumOffload = 0x00000080, /* set if int generated in MMC RX CHECKSUM OFFLOAD int register */ + GmacMmcTxIntSts = 0x00000040, /* set if int generated in MMC TX Int register */ + GmacMmcRxIntSts = 0x00000020, /* set if int generated in MMC RX Int register */ + GmacMmcIntSts = 0x00000010, /* set if any of the above bit [7:5] is set */ + GmacPmtIntSts = 0x00000008, /* set whenver magic pkt/wake-on-lan frame is received */ + GmacPcsAnComplete = 0x00000004, /* set when AN is complete in TBI/RTBI/SGMIII phy interface */ + GmacPcsLnkStsChange = 0x00000002, /* set if any lnk status change in TBI/RTBI/SGMII interface */ + GmacRgmiiIntSts = 0x00000001, /* set if any change in lnk status of RGMII interface */ + +}; + +/* GmacInterruptMask = 0x003C, Mac Interrupt Mask register */ +enum GmacInterruptMaskBitDefinition { + GmacTSIntMask = 0x00000200, /* when set disables the time stamp interrupt generation */ + GmacPmtIntMask = 0x00000008, /* when set Disables the assertion of PMT interrupt */ + GmacPcsAnIntMask = 0x00000004, /* When set disables the assertion of PCS AN complete interrupt */ + GmacPcsLnkStsIntMask = 0x00000002, /* when set disables the assertion of PCS lnk status change interrupt */ + GmacRgmiiIntMask = 0x00000001, /* when set disables the assertion of RGMII int */ +}; + +/********************************************************** + * GMAC DMA registers + * For Pci based system address is BARx + GmaDmaBase + * For any other system translation is done accordingly + **********************************************************/ + +enum DmaRegisters { + DmaBusMode = 0x0000, /* CSR0 - Bus Mode Register */ + DmaTxPollDemand = 0x0004, /* CSR1 - Transmit Poll Demand Register */ + DmaRxPollDemand = 0x0008, /* CSR2 - Receive Poll Demand Register */ + DmaRxBaseAddr = 0x000C, /* CSR3 - Receive Descriptor list base address */ + DmaTxBaseAddr = 0x0010, /* CSR4 - Transmit Descriptor list base address */ + DmaStatus = 0x0014, /* CSR5 - Dma status Register */ + DmaControl = 0x0018, /* CSR6 - Dma Operation Mode Register */ + DmaInterrupt = 0x001C, /* CSR7 - Interrupt enable */ + DmaMissedFr = 0x0020, /* CSR8 - Missed Frame & Buffer overflow Counter */ + DmaTxCurrDesc = 0x0048, /* - Current host Tx Desc Register */ + DmaRxCurrDesc = 0x004C, /* - Current host Rx Desc Register */ + DmaTxCurrAddr = 0x0050, /* CSR20 - Current host transmit buffer address */ + DmaRxCurrAddr = 0x0054, /* CSR21 - Current host receive buffer address */ + + +}; + +/********************************************************** + * DMA Engine registers Layout + **********************************************************/ + +/*DmaBusMode = 0x0000, CSR0 - Bus Mode */ +enum DmaBusModeReg { + /* Bit description Bits R/W Reset value */ + + DmaFixedBurstEnable = 0x00010000, /* (FB)Fixed Burst SINGLE, INCR4, INCR8 or INCR16 16 RW */ + DmaFixedBurstDisable = 0x00000000, /* SINGLE, INCR 0 */ + + DmaTxPriorityRatio11 = 0x00000000, /* (PR)TX:RX DMA priority ratio 1:1 15:14 RW 00 */ + DmaTxPriorityRatio21 = 0x00004000, /* (PR)TX:RX DMA priority ratio 2:1 */ + DmaTxPriorityRatio31 = 0x00008000, /* (PR)TX:RX DMA priority ratio 3:1 */ + DmaTxPriorityRatio41 = 0x0000C000, /* (PR)TX:RX DMA priority ratio 4:1 */ + + DmaBurstLengthx8 = 0x01000000, /* When set mutiplies the PBL by 8 24 RW 0 */ + + DmaBurstLength256 = 0x01002000, /*(DmaBurstLengthx8 | DmaBurstLength32) = 256 [24]:13:8 */ + DmaBurstLength128 = 0x01001000, /*(DmaBurstLengthx8 | DmaBurstLength16) = 128 [24]:13:8 */ + DmaBurstLength64 = 0x01000800, /*(DmaBurstLengthx8 | DmaBurstLength8) = 64 [24]:13:8 */ + DmaBurstLength32 = 0x00002000, /* (PBL) programmable Dma burst length = 32 13:8 RW */ + DmaBurstLength16 = 0x00001000, /* Dma burst length = 16 */ + DmaBurstLength8 = 0x00000800, /* Dma burst length = 8 */ + DmaBurstLength4 = 0x00000400, /* Dma burst length = 4 */ + DmaBurstLength2 = 0x00000200, /* Dma burst length = 2 */ + DmaBurstLength1 = 0x00000100, /* Dma burst length = 1 */ + DmaBurstLength0 = 0x00000000, /* Dma burst length = 0 0x00 */ + + DmaDescriptor8Words = 0x00000080, /* Enh Descriptor works 1=> 8 word descriptor 7 0 */ + DmaDescriptor4Words = 0x00000000, /* Enh Descriptor works 0=> 4 word descriptor 7 0 */ + + DmaDescriptorSkip16 = 0x00000040, /* (DSL)Descriptor skip length (no.of dwords) 6:2 RW */ + DmaDescriptorSkip8 = 0x00000020, /* between two unchained descriptors */ + DmaDescriptorSkip4 = 0x00000010, /* */ + DmaDescriptorSkip2 = 0x00000008, /* */ + DmaDescriptorSkip1 = 0x00000004, /* */ + DmaDescriptorSkip0 = 0x00000000, /* 0x00 */ + + DmaArbitRr = 0x00000000, /* (DA) DMA RR arbitration 1 RW 0 */ + DmaArbitPr = 0x00000002, /* Rx has priority over Tx */ + + DmaResetOn = 0x00000001, /* (SWR)Software Reset DMA engine 0 RW */ + DmaResetOff = 0x00000000, /* 0 */ +}; + + +/*DmaStatus = 0x0014, CSR5 - Dma status Register */ +enum DmaStatusReg { + /*Bit 28 27 and 26 indicate whether the interrupt due to PMT GMACMMC or GMAC LINE Remaining bits are DMA interrupts*/ + + + GmacLPIIntr = 0x40000000, /* GMC LPI interrupt 31 RO 0 */ + + + GmacPmtIntr = 0x10000000, /* (GPI)Gmac subsystem interrupt 28 RO 0 */ + GmacMmcIntr = 0x08000000, /* (GMI)Gmac MMC subsystem interrupt 27 RO 0 */ + GmacLineIntfIntr = 0x04000000, /* Line interface interrupt 26 RO 0 */ + + DmaErrorBit2 = 0x02000000, /* (EB)Error bits 0-data buffer, 1-desc. access 25 RO 0 */ + DmaErrorBit1 = 0x01000000, /* (EB)Error bits 0-write trnsf, 1-read transfr 24 RO 0 */ + DmaErrorBit0 = 0x00800000, /* (EB)Error bits 0-Rx DMA, 1-Tx DMA 23 RO 0 */ + + DmaTxState = 0x00700000, /* (TS)Transmit process state 22:20 RO */ + DmaTxStopped = 0x00000000, /* Stopped - Reset or Stop Tx Command issued 000 */ + DmaTxFetching = 0x00100000, /* Running - fetching the Tx descriptor */ + DmaTxWaiting = 0x00200000, /* Running - waiting for status */ + DmaTxReading = 0x00300000, /* Running - reading the data from host memory */ + DmaTxSuspended = 0x00600000, /* Suspended - Tx Descriptor unavailabe */ + DmaTxClosing = 0x00700000, /* Running - closing Rx descriptor */ + + DmaRxState = 0x000E0000, /* (RS)Receive process state 19:17 RO */ + DmaRxStopped = 0x00000000, /* Stopped - Reset or Stop Rx Command issued 000 */ + DmaRxFetching = 0x00020000, /* Running - fetching the Rx descriptor */ + DmaRxWaiting = 0x00060000, /* Running - waiting for packet */ + DmaRxSuspended = 0x00080000, /* Suspended - Rx Descriptor unavailable */ + DmaRxClosing = 0x000A0000, /* Running - closing descriptor */ + DmaRxQueuing = 0x000E0000, /* Running - queuing the recieve frame into host memory */ + + DmaIntNormal = 0x00010000, /* (NIS)Normal interrupt summary 16 RW 0 */ + DmaIntAbnormal = 0x00008000, /* (AIS)Abnormal interrupt summary 15 RW 0 */ + + DmaIntEarlyRx = 0x00004000, /* Early receive interrupt (Normal) RW 0 */ + DmaIntBusError = 0x00002000, /* Fatal bus error (Abnormal) RW 0 */ + DmaIntEarlyTx = 0x00000400, /* Early transmit interrupt (Abnormal) RW 0 */ + DmaIntRxWdogTO = 0x00000200, /* Receive Watchdog Timeout (Abnormal) RW 0 */ + DmaIntRxStopped = 0x00000100, /* Receive process stopped (Abnormal) RW 0 */ + DmaIntRxNoBuffer = 0x00000080, /* Receive buffer unavailable (Abnormal) RW 0 */ + DmaIntRxCompleted = 0x00000040, /* Completion of frame reception (Normal) RW 0 */ + DmaIntTxUnderflow = 0x00000020, /* Transmit underflow (Abnormal) RW 0 */ + DmaIntRcvOverflow = 0x00000010, /* Receive Buffer overflow interrupt RW 0 */ + DmaIntTxJabberTO = 0x00000008, /* Transmit Jabber Timeout (Abnormal) RW 0 */ + DmaIntTxNoBuffer = 0x00000004, /* Transmit buffer unavailable (Normal) RW 0 */ + DmaIntTxStopped = 0x00000002, /* Transmit process stopped (Abnormal) RW 0 */ + DmaIntTxCompleted = 0x00000001, /* Transmit completed (Normal) RW 0 */ +}; + +/*DmaControl = 0x0018, CSR6 - Dma Operation Mode Register */ +enum DmaControlReg { + DmaDisableDropTcpCs = 0x04000000, /* (DT) Dis. drop. of tcp/ip CS error frames 26 RW 0 */ + + DmaStoreAndForward = 0x00200000, /* (SF)Store and forward 21 RW 0 */ + DmaFlushTxFifo = 0x00100000, /* (FTF)Tx FIFO controller is reset to default 20 RW 0 */ + + DmaTxThreshCtrl = 0x0001C000, /* (TTC)Controls thre Threh of MTL tx Fifo 16:14 RW */ + DmaTxThreshCtrl16 = 0x0001C000, /* (TTC)Controls thre Threh of MTL tx Fifo 16 16:14 RW */ + DmaTxThreshCtrl24 = 0x00018000, /* (TTC)Controls thre Threh of MTL tx Fifo 24 16:14 RW */ + DmaTxThreshCtrl32 = 0x00014000, /* (TTC)Controls thre Threh of MTL tx Fifo 32 16:14 RW */ + DmaTxThreshCtrl40 = 0x00010000, /* (TTC)Controls thre Threh of MTL tx Fifo 40 16:14 RW */ + DmaTxThreshCtrl256 = 0x0000c000, /* (TTC)Controls thre Threh of MTL tx Fifo 256 16:14 RW */ + DmaTxThreshCtrl192 = 0x00008000, /* (TTC)Controls thre Threh of MTL tx Fifo 192 16:14 RW */ + DmaTxThreshCtrl128 = 0x00004000, /* (TTC)Controls thre Threh of MTL tx Fifo 128 16:14 RW */ + DmaTxThreshCtrl64 = 0x00000000, /* (TTC)Controls thre Threh of MTL tx Fifo 64 16:14 RW 000 */ + + DmaTxStart = 0x00002000, /* (ST)Start/Stop transmission 13 RW 0 */ + + DmaRxFlowCtrlDeact = 0x00401800, /* (RFD)Rx flow control deact. threhold [22]:12:11 RW */ + DmaRxFlowCtrlDeact1K = 0x00000000, /* (RFD)Rx flow control deact. threhold (1kbytes) [22]:12:11 RW 00 */ + DmaRxFlowCtrlDeact2K = 0x00000800, /* (RFD)Rx flow control deact. threhold (2kbytes) [22]:12:11 RW */ + DmaRxFlowCtrlDeact3K = 0x00001000, /* (RFD)Rx flow control deact. threhold (3kbytes) [22]:12:11 RW */ + DmaRxFlowCtrlDeact4K = 0x00001800, /* (RFD)Rx flow control deact. threhold (4kbytes) [22]:12:11 RW */ + DmaRxFlowCtrlDeact5K = 0x00400000, /* (RFD)Rx flow control deact. threhold (4kbytes) [22]:12:11 RW */ + DmaRxFlowCtrlDeact6K = 0x00400800, /* (RFD)Rx flow control deact. threhold (4kbytes) [22]:12:11 RW */ + DmaRxFlowCtrlDeact7K = 0x00401000, /* (RFD)Rx flow control deact. threhold (4kbytes) [22]:12:11 RW */ + + DmaRxFlowCtrlAct = 0x00800600, /* (RFA)Rx flow control Act. threhold [23]:10:09 RW */ + DmaRxFlowCtrlAct1K = 0x00000000, /* (RFA)Rx flow control Act. threhold (1kbytes) [23]:10:09 RW 00 */ + DmaRxFlowCtrlAct2K = 0x00000200, /* (RFA)Rx flow control Act. threhold (2kbytes) [23]:10:09 RW */ + DmaRxFlowCtrlAct3K = 0x00000400, /* (RFA)Rx flow control Act. threhold (3kbytes) [23]:10:09 RW */ + DmaRxFlowCtrlAct4K = 0x00000300, /* (RFA)Rx flow control Act. threhold (4kbytes) [23]:10:09 RW */ + DmaRxFlowCtrlAct5K = 0x00800000, /* (RFA)Rx flow control Act. threhold (5kbytes) [23]:10:09 RW */ + DmaRxFlowCtrlAct6K = 0x00800200, /* (RFA)Rx flow control Act. threhold (6kbytes) [23]:10:09 RW */ + DmaRxFlowCtrlAct7K = 0x00800400, /* (RFA)Rx flow control Act. threhold (7kbytes) [23]:10:09 RW */ + + DmaRxThreshCtrl = 0x00000018, /* (RTC)Controls thre Threh of MTL rx Fifo 4:3 RW */ + DmaRxThreshCtrl64 = 0x00000000, /* (RTC)Controls thre Threh of MTL tx Fifo 64 4:3 RW */ + DmaRxThreshCtrl32 = 0x00000008, /* (RTC)Controls thre Threh of MTL tx Fifo 32 4:3 RW */ + DmaRxThreshCtrl96 = 0x00000010, /* (RTC)Controls thre Threh of MTL tx Fifo 96 4:3 RW */ + DmaRxThreshCtrl128 = 0x00000018, /* (RTC)Controls thre Threh of MTL tx Fifo 128 4:3 RW */ + + DmaEnHwFlowCtrl = 0x00000100, /* (EFC)Enable HW flow control 8 RW */ + DmaDisHwFlowCtrl = 0x00000000, /* Disable HW flow control 0 */ + + DmaFwdErrorFrames = 0x00000080, /* (FEF)Forward error frames 7 RW 0 */ + DmaFwdUnderSzFrames = 0x00000040, /* (FUF)Forward undersize frames 6 RW 0 */ + DmaTxSecondFrame = 0x00000004, /* (OSF)Operate on second frame 4 RW 0 */ + DmaRxStart = 0x00000002, /* (SR)Start/Stop reception 1 RW 0 */ +}; + + +/*DmaInterrupt = 0x001C, CSR7 - Interrupt enable Register Layout */ +enum DmaInterruptReg { + DmaIeNormal = DmaIntNormal , /* Normal interrupt enable RW 0 */ + DmaIeAbnormal = DmaIntAbnormal , /* Abnormal interrupt enable RW 0 */ + + DmaIeEarlyRx = DmaIntEarlyRx , /* Early receive interrupt enable RW 0 */ + DmaIeBusError = DmaIntBusError , /* Fatal bus error enable RW 0 */ + DmaIeEarlyTx = DmaIntEarlyTx , /* Early transmit interrupt enable RW 0 */ + DmaIeRxWdogTO = DmaIntRxWdogTO , /* Receive Watchdog Timeout enable RW 0 */ + DmaIeRxStopped = DmaIntRxStopped , /* Receive process stopped enable RW 0 */ + DmaIeRxNoBuffer = DmaIntRxNoBuffer , /* Receive buffer unavailable enable RW 0 */ + DmaIeRxCompleted = DmaIntRxCompleted, /* Completion of frame reception enable RW 0 */ + DmaIeTxUnderflow = DmaIntTxUnderflow, /* Transmit underflow enable RW 0 */ + + DmaIeRxOverflow = DmaIntRcvOverflow, /* Receive Buffer overflow interrupt RW 0 */ + DmaIeTxJabberTO = DmaIntTxJabberTO , /* Transmit Jabber Timeout enable RW 0 */ + DmaIeTxNoBuffer = DmaIntTxNoBuffer , /* Transmit buffer unavailable enable RW 0 */ + DmaIeTxStopped = DmaIntTxStopped , /* Transmit process stopped enable RW 0 */ + DmaIeTxCompleted = DmaIntTxCompleted, /* Transmit completed enable RW 0 */ +}; + + +/********************************************************** + * DMA Engine descriptors + **********************************************************/ + +/* +**********Enhanced Descritpor structure to support 8K buffer per buffer **************************** + +DmaRxBaseAddr = 0x000C, CSR3 - Receive Descriptor list base address +DmaRxBaseAddr is the pointer to the first Rx Descriptors. the Descriptor format in Little endian with a +32 bit Data bus is as shown below + +Similarly +DmaTxBaseAddr = 0x0010, CSR4 - Transmit Descriptor list base address +DmaTxBaseAddr is the pointer to the first Rx Descriptors. the Descriptor format in Little endian with a +32 bit Data bus is as shown below + -------------------------------------------------------------------------- + RDES0 |OWN (31)| Status | + -------------------------------------------------------------------------- + RDES1 | Ctrl | Res | Byte Count Buffer 2 | Ctrl | Res | Byte Count Buffer 1 | + -------------------------------------------------------------------------- + RDES2 | Buffer 1 Address | + -------------------------------------------------------------------------- + RDES3 | Buffer 2 Address / Next Descriptor Address | + -------------------------------------------------------------------------- + + -------------------------------------------------------------------------- + TDES0 |OWN (31)| Ctrl | Res | Ctrl | Res | Status | + -------------------------------------------------------------------------- + TDES1 | Res | Byte Count Buffer 2 | Res | Byte Count Buffer 1 | + -------------------------------------------------------------------------- + TDES2 | Buffer 1 Address | + -------------------------------------------------------------------------- + TDES3 | Buffer 2 Address / Next Descriptor Address | + -------------------------------------------------------------------------- + +*/ + +enum DmaDescriptorStatus /* status word of DMA descriptor */ +{ + + DescOwnByDma = 0x80000000, /* (OWN)Descriptor is owned by DMA engine 31 RW */ + + DescDAFilterFail = 0x40000000, /* (AFM)Rx - DA Filter Fail for the rx frame 30 */ + + DescFrameLengthMask = 0x3FFF0000, /* (FL)Receive descriptor frame length 29:16 */ + DescFrameLengthShift = 16, + + DescError = 0x00008000, /* (ES)Error summary bit - OR of the follo. bits: 15 */ + /* DE || OE || IPC || LC || RWT || RE || CE */ + DescRxTruncated = 0x00004000, /* (DE)Rx - no more descriptors for receive frame 14 */ + DescSAFilterFail = 0x00002000, /* (SAF)Rx - SA Filter Fail for the received frame 13 */ + DescRxLengthError = 0x00001000, /* (LE)Rx - frm size not matching with len field 12 */ + DescRxDamaged = 0x00000800, /* (OE)Rx - frm was damaged due to buffer overflow 11 */ + DescRxVLANTag = 0x00000400, /* (VLAN)Rx - received frame is a VLAN frame 10 */ + DescRxFirst = 0x00000200, /* (FS)Rx - first descriptor of the frame 9 */ + DescRxLast = 0x00000100, /* (LS)Rx - last descriptor of the frame 8 */ + DescRxLongFrame = 0x00000080, /* (Giant Frame)Rx - frame is longer than 1518/1522 7 */ + DescRxTSAvailable = 0x00000080, /* Share bit with (Giant Frame)Rx 7 */ + DescRxCollision = 0x00000040, /* (LC)Rx - late collision occurred during reception 6 */ + DescRxFrameEther = 0x00000020, /* (FT)Rx - Frame type - Ethernet, otherwise 802.3 5 */ + DescRxWatchdog = 0x00000010, /* (RWT)Rx - watchdog timer expired during reception 4 */ + DescRxMiiError = 0x00000008, /* (RE)Rx - error reported by MII interface 3 */ + DescRxDribbling = 0x00000004, /* (DE)Rx - frame contains non int multiple of 8 bits 2 */ + DescRxCrc = 0x00000002, /* (CE)Rx - CRC error 1 */ +// DescRxMacMatch = 0x00000001, /* (RX MAC Address) Rx mac address reg(1 to 15)match 0 */ + + DescRxEXTsts = 0x00000001, /* Extended Status Available (RDES4) 0 */ + + DescTxIntEnable = 0x40000000, /* (IC)Tx - interrupt on completion 30 */ + DescTxLast = 0x20000000, /* (LS)Tx - Last segment of the frame 29 */ + DescTxFirst = 0x10000000, /* (FS)Tx - First segment of the frame 28 */ + DescTxDisableCrc = 0x08000000, /* (DC)Tx - Add CRC disabled (first segment only) 27 */ + DescTxDisablePadd = 0x04000000, /* (DP)disable padding, added by - reyaz 26 */ + DescTxTSEnable = 0x02000000, /* (TTSE) Transmit Timestamp Enable 25 */ + DescTxCrcReplacement = 0x01000000, /* (CRCR) CRC Replacement Control 24 */ + DescTxCisMask = 0x00c00000, /* Tx checksum offloading control mask 23:22 */ + DescTxCisBypass = 0x00000000, /* Checksum bypass */ + DescTxCisIpv4HdrCs = 0x00400000, /* IPv4 header checksum */ + DescTxCisTcpOnlyCs = 0x00800000, /* TCP/UDP/ICMP checksum. Pseudo header checksum is assumed to be present */ + DescTxCisTcpPseudoCs = 0x00c00000, /* TCP/UDP/ICMP checksum fully in hardware including pseudo header */ + + TxDescEndOfRing = 0x00200000, /* (TER)End of descriptors ring 21 */ + TxDescChain = 0x00100000, /* (TCH)Second buffer address is chain address 20 */ + + DescRxChkBit0 = 0x00000001, /*() Rx - Rx Payload Checksum Error 0 */ + DescRxChkBit7 = 0x00000080, /* (IPC CS ERROR)Rx - Ipv4 header checksum error 7 */ + DescRxChkBit5 = 0x00000020, /* (FT)Rx - Frame type - Ethernet, otherwise 802.3 5 */ + + DescRxTSavail = 0x00000080, /* Time stamp available 7 */ + DescRxFrameType = 0x00000020, /* (FT)Rx - Frame type - Ethernet, otherwise 802.3 5 */ + DescTxTSStatus = 0x00020000, /* (TTSS) Transmit Timestamp Status 17 */ + DescTxIpv4ChkError = 0x00010000, /* (IHE) Tx Ip header error 16 */ + DescTxTimeout = 0x00004000, /* (JT)Tx - Transmit jabber timeout 14 */ + DescTxFrameFlushed = 0x00002000, /* (FF)Tx - DMA/MTL flushed the frame due to SW flush 13 */ + DescTxPayChkError = 0x00001000, /* (PCE) Tx Payload checksum Error 12 */ + DescTxLostCarrier = 0x00000800, /* (LC)Tx - carrier lost during tramsmission 11 */ + DescTxNoCarrier = 0x00000400, /* (NC)Tx - no carrier signal from the tranceiver 10 */ + DescTxLateCollision = 0x00000200, /* (LC)Tx - transmission aborted due to collision 9 */ + DescTxExcCollisions = 0x00000100, /* (EC)Tx - transmission aborted after 16 collisions 8 */ + DescTxVLANFrame = 0x00000080, /* (VF)Tx - VLAN-type frame 7 */ + + DescTxCollMask = 0x00000078, /* (CC)Tx - Collision count 6:3 */ + DescTxCollShift = 3, + + DescTxExcDeferral = 0x00000004, /* (ED)Tx - excessive deferral 2 */ + DescTxUnderflow = 0x00000002, /* (UF)Tx - late data arrival from the memory 1 */ + DescTxDeferred = 0x00000001, /* (DB)Tx - frame transmision deferred 0 */ + + /* + This explains the RDES1/TDES1 bits layout + -------------------------------------------------------------------- + RDES1/TDES1 | Control Bits | Byte Count Buffer 2 | Byte Count Buffer 1 | + -------------------------------------------------------------------- + + */ +// DmaDescriptorLength length word of DMA descriptor + + + RxDisIntCompl = 0x80000000, /* (Disable Rx int on completion) 31 */ + RxDescEndOfRing = 0x00008000, /* (TER)End of descriptors ring 15 */ + RxDescChain = 0x00004000, /* (TCH)Second buffer address is chain address 14 */ + + + DescSize2Mask = 0x1FFF0000, /* (TBS2) Buffer 2 size 28:16 */ + DescSize2Shift = 16, + DescSize1Mask = 0x00001FFF, /* (TBS1) Buffer 1 size 12:0 */ + DescSize1Shift = 0, + + + /* + This explains the RDES4 Extended Status bits layout + -------------------------------------------------------------------- + RDES4 | Extended Status | + -------------------------------------------------------------------- + */ + + DescRxPtpAvail = 0x00004000, /* PTP snapshot available 14 */ + DescRxPtpVer = 0x00002000, /* When set indicates IEEE1584 Version 2 (else Ver1) 13 */ + DescRxPtpFrameType = 0x00001000, /* PTP frame type Indicates PTP sent over ethernet 12 */ + DescRxPtpMessageType = 0x00000F00, /* Message Type 11:8 */ + DescRxPtpNo = 0x00000000, /* 0000 => No PTP message received */ + DescRxPtpSync = 0x00000100, /* 0001 => Sync (all clock types) received */ + DescRxPtpFollowUp = 0x00000200, /* 0010 => Follow_Up (all clock types) received */ + DescRxPtpDelayReq = 0x00000300, /* 0011 => Delay_Req (all clock types) received */ + DescRxPtpDelayResp = 0x00000400, /* 0100 => Delay_Resp (all clock types) received */ + DescRxPtpPdelayReq = 0x00000500, /* 0101 => Pdelay_Req (in P to P tras clk) or Announce in Ord and Bound clk */ + DescRxPtpPdelayResp = 0x00000600, /* 0110 => Pdealy_Resp(in P to P trans clk) or Management in Ord and Bound clk */ + DescRxPtpPdelayRespFP = 0x00000700, /* 0111 => Pdealy_Resp_Follow_Up (in P to P trans clk) or Signaling in Ord and Bound clk */ + DescRxPtpIPV6 = 0x00000080, /* Received Packet is in IPV6 Packet 7 */ + DescRxPtpIPV4 = 0x00000040, /* Received Packet is in IPV4 Packet 6 */ + + DescRxChkSumBypass = 0x00000020, /* When set indicates checksum offload engine 5 + is bypassed */ + DescRxIpPayloadError = 0x00000010, /* When set indicates 16bit IP payload CS is in error 4 */ + DescRxIpHeaderError = 0x00000008, /* When set indicates 16bit IPV4 header CS is in 3 + error or IP datagram version is not consistent + with Ethernet type value */ + DescRxIpPayloadType = 0x00000007, /* Indicate the type of payload encapsulated 2:0 + in IPdatagram processed by COE (Rx) */ + DescRxIpPayloadUnknown= 0x00000000, /* Unknown or didnot process IP payload */ + DescRxIpPayloadUDP = 0x00000001, /* UDP */ + DescRxIpPayloadTCP = 0x00000002, /* TCP */ + DescRxIpPayloadICMP = 0x00000003, /* ICMP */ + +}; + + +// Rx Descriptor COE type2 encoding +enum RxDescCOEEncode { + RxLenLT600 = 0, /* Bit(5:7:0)=>0 IEEE 802.3 type frame Length field is Lessthan 0x0600 */ + RxIpHdrPayLoadChkBypass = 1, /* Bit(5:7:0)=>1 Payload & Ip header checksum bypassed (unsuppported payload) */ + RxIpHdrPayLoadRes = 2, /* Bit(5:7:0)=>2 Reserved */ + RxChkBypass = 3, /* Bit(5:7:0)=>3 Neither IPv4 nor IPV6. So checksum bypassed */ + RxNoChkError = 4, /* Bit(5:7:0)=>4 No IPv4/IPv6 Checksum error detected */ + RxPayLoadChkError = 5, /* Bit(5:7:0)=>5 Payload checksum error detected for Ipv4/Ipv6 frames */ + RxIpHdrChkError = 6, /* Bit(5:7:0)=>6 Ip header checksum error detected for Ipv4 frames */ + RxIpHdrPayLoadChkError = 7, /* Bit(5:7:0)=>7 Payload & Ip header checksum error detected for Ipv4/Ipv6 frames */ +}; + +/********************************************************** + * DMA engine interrupt handling functions + **********************************************************/ + +enum synopGMACDmaIntEnum /* Intrerrupt types */ +{ + synopGMACDmaRxNormal = 0x01, /* normal receiver interrupt */ + synopGMACDmaRxAbnormal = 0x02, /* abnormal receiver interrupt */ + synopGMACDmaRxStopped = 0x04, /* receiver stopped */ + synopGMACDmaTxNormal = 0x08, /* normal transmitter interrupt */ + synopGMACDmaTxAbnormal = 0x10, /* abnormal transmitter interrupt */ + synopGMACDmaTxStopped = 0x20, /* transmitter stopped */ + synopGMACDmaError = 0x80, /* Dma engine error */ + +}; + + +/********************************************************** + * Initial register values + **********************************************************/ +enum InitialRegisters { + /* Full-duplex mode with perfect filter on */ + GmacConfigInitFdx1000 = GmacWatchdogEnable | GmacJabberEnable | GmacFrameBurstEnable | GmacJumboFrameDisable + | GmacSelectGmii | GmacEnableRxOwn | GmacLoopbackOff + | GmacFullDuplex | GmacRetryEnable | GmacPadCrcStripDisable + | GmacBackoffLimit0 | GmacDeferralCheckDisable | GmacTxEnable | GmacRxEnable, + + /* Full-duplex mode with perfect filter on */ + GmacConfigInitFdx110 = GmacWatchdogEnable | GmacJabberEnable | GmacFrameBurstEnable | GmacJumboFrameDisable + | GmacSelectMii | GmacEnableRxOwn | GmacLoopbackOff + | GmacFullDuplex | GmacRetryEnable | GmacPadCrcStripDisable + | GmacBackoffLimit0 | GmacDeferralCheckDisable | GmacTxEnable | GmacRxEnable, + + /* Full-duplex mode */ + // CHANGED: Pass control config, dest addr filter normal, added source address filter, multicast & unicast + // Hash filter. + /* = GmacFilterOff | GmacPassControlOff | GmacBroadcastEnable */ + GmacFrameFilterInitFdx = GmacFilterOn | GmacPassControl0 | GmacBroadcastEnable | GmacSrcAddrFilterDisable + | GmacMulticastFilterOn | GmacDestAddrFilterNor | GmacMcastHashFilterOff + | GmacPromiscuousModeOff | GmacUcastHashFilterOff, + + /* Full-duplex mode */ + GmacFlowControlInitFdx = GmacUnicastPauseFrameOff | GmacRxFlowControlEnable | GmacTxFlowControlEnable, + + /* Full-duplex mode */ + GmacGmiiAddrInitFdx = GmiiCsrClk2, + + + /* Half-duplex mode with perfect filter on */ + // CHANGED: Removed Endian configuration, added single bit config for PAD/CRC strip, + /*| GmacSelectMii | GmacLittleEndian | GmacDisableRxOwn | GmacLoopbackOff*/ + GmacConfigInitHdx1000 = GmacWatchdogEnable | GmacJabberEnable | GmacFrameBurstEnable | GmacJumboFrameDisable + | GmacSelectGmii | GmacDisableRxOwn | GmacLoopbackOff + | GmacHalfDuplex | GmacRetryEnable | GmacPadCrcStripDisable + | GmacBackoffLimit0 | GmacDeferralCheckDisable | GmacTxEnable | GmacRxEnable, + + /* Half-duplex mode with perfect filter on */ + GmacConfigInitHdx110 = GmacWatchdogEnable | GmacJabberEnable | GmacFrameBurstEnable | GmacJumboFrameDisable + | GmacSelectMii | GmacDisableRxOwn | GmacLoopbackOff + | GmacHalfDuplex | GmacRetryEnable | GmacPadCrcStripDisable + | GmacBackoffLimit0 | GmacDeferralCheckDisable | GmacTxEnable | GmacRxEnable, + + /* Half-duplex mode */ + GmacFrameFilterInitHdx = GmacFilterOn | GmacPassControl0 | GmacBroadcastEnable | GmacSrcAddrFilterDisable + | GmacMulticastFilterOn | GmacDestAddrFilterNor | GmacMcastHashFilterOff + | GmacUcastHashFilterOff| GmacPromiscuousModeOff, + + /* Half-duplex mode */ + GmacFlowControlInitHdx = GmacUnicastPauseFrameOff | GmacRxFlowControlDisable | GmacTxFlowControlDisable, + + /* Half-duplex mode */ + GmacGmiiAddrInitHdx = GmiiCsrClk2, + + + + /********************************************** + *DMA configurations + **********************************************/ + + DmaBusModeInit = DmaFixedBurstEnable | DmaBurstLength8 | DmaDescriptorSkip2 | DmaResetOff, +// DmaBusModeInit = DmaFixedBurstEnable | DmaBurstLength8 | DmaDescriptorSkip4 | DmaResetOff, + + /* 1000 Mb/s mode */ + DmaControlInit1000 = DmaStoreAndForward,// | DmaTxSecondFrame , + + /* 100 Mb/s mode */ + DmaControlInit100 = DmaStoreAndForward, + + /* 10 Mb/s mode */ + DmaControlInit10 = DmaStoreAndForward, + + /* Interrupt groups */ + DmaIntErrorMask = DmaIntBusError, /* Error */ + DmaIntRxAbnMask = DmaIntRxNoBuffer, /* receiver abnormal interrupt */ + DmaIntRxNormMask = DmaIntRxCompleted, /* receiver normal interrupt */ + DmaIntRxStoppedMask = DmaIntRxStopped, /* receiver stopped */ + DmaIntTxAbnMask = DmaIntTxUnderflow, /* transmitter abnormal interrupt */ + DmaIntTxNormMask = DmaIntTxCompleted, /* transmitter normal interrupt */ + DmaIntTxStoppedMask = DmaIntTxStopped, /* transmitter stopped */ + + DmaIntEnable = DmaIeNormal | DmaIeAbnormal | DmaIntErrorMask + | DmaIntRxAbnMask | DmaIntRxNormMask | DmaIntRxStoppedMask + | DmaIntTxAbnMask | DmaIntTxNormMask | DmaIntTxStoppedMask, + DmaIntDisable = 0, +}; + + + + +/********************************************************** + * Power Management (PMT) Block + **********************************************************/ + +/** + * PMT supports the reception of network (remote) wake-up frames and Magic packet frames. + * It generates interrupts for wake-up frames and Magic packets received by GMAC. + * PMT sits in Rx path and is enabled with remote wake-up frame enable and Magic packet enable. + * These enable are in PMT control and Status register and are programmed by apllication. + * + * When power down mode is enabled in PMT, all rx frames are dropped by the core. Core comes + * out of power down mode only when either Magic packe tor a Remote wake-up frame is received + * and the corresponding detection is enabled. + * + * Driver need not be modified to support this feature. Only Api to put the device in to power + * down mode is sufficient + */ + +#define WAKEUP_REG_LENGTH 8 /*This is the reg length for wake up register configuration*/ + +enum GmacPmtCtrlStatusBitDefinition { + GmacPmtFrmFilterPtrReset = 0x80000000, /* when set remote wake-up frame filter register pointer to 3'b000 */ + GmacPmtGlobalUnicast = 0x00000200, /* When set enables any unicast packet to be a wake-up frame */ + GmacPmtWakeupFrameReceived = 0x00000040, /* Wake up frame received */ + GmacPmtMagicPktReceived = 0x00000020, /* Magic Packet received */ + GmacPmtWakeupFrameEnable = 0x00000004, /* Wake-up frame enable */ + GmacPmtMagicPktEnable = 0x00000002, /* Magic packet enable */ + GmacPmtPowerDown = 0x00000001, /* Power Down */ +}; + + + + +/********************************************************** + * IEEE 1588-2008 Precision Time Protocol (PTP) Support + **********************************************************/ +enum PTPMessageType { + SYNC = 0x0, + Delay_Req = 0x1, + Pdelay_Req = 0x2, + Pdelay_Resp = 0x3, + Follow_up = 0x8, + Delay_Resp = 0x9, + Pdelay_Resp_Follow_Up = 0xA, + Announce = 0xB, + Signaling = 0xC, + Management = 0xD, +}; + + + +typedef struct TimeStampStruct { + u32 TSversion; /* PTP Version 1 or PTP version2 */ + u32 TSmessagetype; /* Message type associated with this time stamp */ + + u16 TShighest16; /* Highest 16 bit time stamp value, Valid onley when ADV_TIME_HIGH_WORD configured in corekit */ + u32 TSupper32; /* Most significant 32 bit time stamp value */ + u32 TSlower32; /* Least Significat 32 bit time stamp value */ + +} TimeStamp; + + +/** + * IEEE 1588-2008 is the optional module to support Ethernet frame time stamping. + * Sixty four (+16) bit time stamps are given in each frames transmit and receive status. + * The driver assumes the following + * 1. "IEEE 1588 Time Stamping" "TIME_STAMPING"is ENABLED in corekit + * 2. "IEEE 1588 External Time Stamp Input Enable" "EXT_TIME_STAMPING" is DISABLED in corekit + * 3. "IEEE 1588 Advanced Time Stamp support" "ADV_TIME_STAMPING" is ENABLED in corekit + * 4. "IEEE 1588 Higher Word Register Enable" "ADV_TIME_HIGH_WORD" is ENABLED in corekit + */ + +/* GmacTSControl = 0x0700, Controls the Timestamp update logic : only when IEEE 1588 time stamping is enabled in corekit */ +enum GmacTSControlReg { + GmacTSENMACADDR = 0x00040000, /* Enable Mac Addr for PTP filtering 18 RW 0 */ + + GmacTSCLKTYPE = 0x00030000, /* Select the type of clock node 17:16 RW 00 */ + /* + TSCLKTYPE TSMSTRENA TSEVNTENA Messages for wihich TS snapshot is taken + 00/01 X 0 SYNC, FOLLOW_UP, DELAY_REQ, DELAY_RESP + 00/01 1 0 DELAY_REQ + 00/01 0 1 SYNC + 10 NA 0 SYNC, FOLLOW_UP, DELAY_REQ, DELAY_RESP + 10 NA 1 SYNC, FOLLOW_UP + 11 NA 0 SYNC, FOLLOW_UP, DELAY_REQ, DELAY_RESP, PDELAY_REQ, PDELAY_RESP + 11 NA 1 SYNC, PDELAY_REQ, PDELAY_RESP + */ + GmacTSOrdClk = 0x00000000, /* 00=> Ordinary clock*/ + GmacTSBouClk = 0x00010000, /* 01=> Boundary clock*/ + GmacTSEtoEClk = 0x00020000, /* 10=> End-to-End transparent clock*/ + GmacTSPtoPClk = 0x00030000, /* 11=> P-to-P transparent clock*/ + + GmacTSMSTRENA = 0x00008000, /* Ena TS Snapshot for Master Messages 15 RW 0 */ + GmacTSEVNTENA = 0x00004000, /* Ena TS Snapshot for Event Messages 14 RW 0 */ + GmacTSIPV4ENA = 0x00002000, /* Ena TS snapshot for IPv4 13 RW 1 */ + GmacTSIPV6ENA = 0x00001000, /* Ena TS snapshot for IPv6 12 RW 0 */ + GmacTSIPENA = 0x00000800, /* Ena TS snapshot for PTP over E'net 11 RW 0 */ + GmacTSVER2ENA = 0x00000400, /* Ena PTP snooping for version 2 10 RW 0 */ + + GmacTSCTRLSSR = 0x00000200, /* Digital or Binary Rollover 9 RW 0 */ + + GmacTSENALL = 0x00000100, /* Enable TS fro all frames (Ver2 only) 8 RW 0 */ + + GmacTSADDREG = 0x00000020, /* Addend Register Update 5 RW_SC 0 */ + GmacTSUPDT = 0x00000008, /* Time Stamp Update 3 RW_SC 0 */ + GmacTSINT = 0x00000004, /* Time Atamp Initialize 2 RW_SC 0 */ + + GmacTSTRIG = 0x00000010, /* Time stamp interrupt Trigger Enable 4 RW_SC 0 */ + + GmacTSCFUPDT = 0x00000002, /* Time Stamp Fine/Coarse 1 RW 0 */ + GmacTSCUPDTCoarse = 0x00000000, /* 0=> Time Stamp update method is coarse */ + GmacTSCUPDTFine = 0x00000002, /* 1=> Time Stamp update method is fine */ + + GmacTSENA = 0x00000001, /* Time Stamp Enable 0 RW 0 */ +}; + + +/* GmacTSSubSecIncr = 0x0704, 8 bit value by which sub second register is incremented : only when IEEE 1588 time stamping without external timestamp input */ +enum GmacTSSubSecIncrReg { + GmacSSINCMsk = 0x000000FF, /* Only Lower 8 bits are valid bits 7:0 RW 00 */ +}; + +/* GmacTSLow = 0x070C, Indicates whether the timestamp low count is positive or negative; for Adv timestamp it is always zero */ +enum GmacTSSign { + GmacTSSign = 0x80000000, /* PSNT 31 RW 0 */ + GmacTSPositive = 0x00000000, + GmacTSNegative = 0x80000000, +}; + +/*GmacTargetTimeLow = 0x0718, 32 bit nano seconds(MS) to be compared with system time : only when IEEE 1588 time stamping without external timestamp input */ +enum GmacTSLowReg { + GmacTSDecThr = 0x3B9AC9FF, /*when TSCTRLSSR is set the max value for GmacTargetTimeLowReg and GmacTimeStampLow register is 0x3B9AC9FF at 1ns precision */ +}; + +/* GmacTSHighWord = 0x0724, Time Stamp Higher Word Register (Version 2 only); only lower 16 bits are valid */ +enum GmacTSHighWordReg { + GmacTSHighWordMask = 0x0000FFFF, /* Time Stamp Higher work register has only lower 16 bits valid */ +}; +/*GmacTSStatus = 0x0728, Time Stamp Status Register */ +enum GmacTSStatusReg { + GmacTSTargTimeReached = 0x00000002, /* Time Stamp Target Time Reached 1 RO 0 */ + GmacTSSecondsOverflow = 0x00000001, /* Time Stamp Seconds Overflow 0 RO 0 */ +}; + + +/********************************************************** + * Time stamp related functions + **********************************************************/ +void synopGMAC_TS_enable(synopGMACdevice *gmacdev); +void synopGMAC_TS_disable(synopGMACdevice *gmacdev); + +void synopGMAC_TS_int_enable(synopGMACdevice *gmacdev); +void synopGMAC_TS_int_disable(synopGMACdevice *gmacdev); + +void synopGMAC_TS_mac_addr_filt_enable(synopGMACdevice *gmacdev); +void synopGMAC_TS_mac_addr_filt_disable(synopGMACdevice *gmacdev); +void synopGMAC_TS_set_clk_type(synopGMACdevice *gmacdev, u32 clk_type); +void synopGMAC_TS_master_enable(synopGMACdevice *gmacdev); // Only for Ordinary clock and Boundary clock and "Advanced Time Stamp" +void synopGMAC_TS_master_disable(synopGMACdevice *gmacdev); // Only for Ordinary clock and Boundary clock and "Advanced Time Stamp" +void synopGMAC_TS_event_enable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" +void synopGMAC_TS_event_disable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" +void synopGMAC_TS_IPV4_enable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" +void synopGMAC_TS_IPV4_disable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" +void synopGMAC_TS_IPV6_enable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" +void synopGMAC_TS_IPV6_disable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" +void synopGMAC_TS_ptp_over_ethernet_enable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" +void synopGMAC_TS_ptp_over_ethernet_disable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" +void synopGMAC_TS_pkt_snoop_ver2(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" +void synopGMAC_TS_pkt_snoop_ver1(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" + +void synopGMAC_TS_digital_rollover_enable(synopGMACdevice *gmacdev); +void synopGMAC_TS_binary_rollover_enable(synopGMACdevice *gmacdev); +void synopGMAC_TS_all_frames_enable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" +void synopGMAC_TS_all_frames_disable(synopGMACdevice *gmacdev); // Only for "Advanced Time Stamp" + +s32 synopGMAC_TS_addend_update(synopGMACdevice *gmacdev, u32 addend_value); +s32 synopGMAC_TS_timestamp_update(synopGMACdevice *gmacdev, u32 high_value, u32 low_value); +s32 synopGMAC_TS_timestamp_init(synopGMACdevice *gmacdev, u32 high_value, u32 low_value); + +void synopGMAC_TS_coarse_update(synopGMACdevice *gmacdev); // Only if "fine correction" enabled +void synopGMAC_TS_fine_update(synopGMACdevice *gmacdev); // Only if "fine correction" enabled + +void synopGMAC_TS_subsecond_init(synopGMACdevice *gmacdev, u32 sub_sec_inc_val); // Update should happen making use of subsecond mask +void synopGMAC_TS_read_timestamp(synopGMACdevice *gmacdev, u16 * higher_sec_val, + u32 * sec_val, u32 * sub_sec_val); // Reads the timestamp low,high and higher(Ver2) registers in the the struct pointer; readonly contents +void synopGMAC_TS_load_target_timestamp(synopGMACdevice *gmacdev, u32 sec_val, u32 sub_sec_val); //Loads the timestamp target register with the values provided + +void synopGMAC_TS_load_timestamp_higher_val(synopGMACdevice *gmacdev, u32 higher_sec_val); +void synopGMAC_TS_read_timestamp_higher_val(synopGMACdevice *gmacdev, u16 * higher_sec_val); +void synopGMAC_TS_read_target_timestamp(synopGMACdevice *gmacdev, u32 * sec_val, u32 * sub_sec_val); //Read the target time stamp register contents + + +/********************************************************** + * Common functions + **********************************************************/ +s32 synopGMAC_set_mdc_clk_div(synopGMACdevice *gmacdev,u32 clk_div_val); +u32 synopGMAC_get_mdc_clk_div(synopGMACdevice *gmacdev); +s32 synopGMAC_read_phy_reg(u32 *RegBase,u32 PhyBase, u32 RegOffset, u16 * data); +s32 synopGMAC_write_phy_reg(u32 *RegBase, u32 PhyBase, u32 RegOffset, u16 data); +s32 synopGMAC_phy_loopback(synopGMACdevice *gmacdev, bool loopback); +s32 synopGMAC_read_version (synopGMACdevice * gmacdev) ; +s32 synopGMAC_reset (synopGMACdevice * gmacdev ); +s32 synopGMAC_reset_nocheck (synopGMACdevice * gmacdev ); +s32 synopGMAC_dma_bus_mode_init(synopGMACdevice * gmacdev, u32 init_value ); +s32 synopGMAC_dma_control_init(synopGMACdevice * gmacdev, u32 init_value); +void synopGMAC_wd_enable(synopGMACdevice * gmacdev); +void synopGMAC_wd_disable(synopGMACdevice * gmacdev); +void synopGMAC_jab_enable(synopGMACdevice * gmacdev); +void synopGMAC_jab_disable(synopGMACdevice * gmacdev); +void synopGMAC_frame_burst_enable(synopGMACdevice * gmacdev); +void synopGMAC_frame_burst_disable(synopGMACdevice * gmacdev); +void synopGMAC_jumbo_frame_enable(synopGMACdevice * gmacdev); +void synopGMAC_jumbo_frame_disable(synopGMACdevice * gmacdev); +void synopGMAC_select_gmii(synopGMACdevice * gmacdev); +void synopGMAC_select_mii(synopGMACdevice * gmacdev); +void synopGMAC_rx_own_enable(synopGMACdevice * gmacdev); +void synopGMAC_rx_own_disable(synopGMACdevice * gmacdev); +void synopGMAC_loopback_on(synopGMACdevice * gmacdev); +void synopGMAC_loopback_off(synopGMACdevice * gmacdev); +void synopGMAC_set_full_duplex(synopGMACdevice * gmacdev); +void synopGMAC_set_half_duplex(synopGMACdevice * gmacdev); +void synopGMAC_retry_enable(synopGMACdevice * gmacdev); +void synopGMAC_retry_disable(synopGMACdevice * gmacdev); +void synopGMAC_pad_crc_strip_enable(synopGMACdevice * gmacdev); +void synopGMAC_pad_crc_strip_disable(synopGMACdevice * gmacdev); +void synopGMAC_back_off_limit(synopGMACdevice * gmacdev, u32 value); +void synopGMAC_deferral_check_enable(synopGMACdevice * gmacdev); +void synopGMAC_deferral_check_disable(synopGMACdevice * gmacdev); +void synopGMAC_rx_enable(synopGMACdevice * gmacdev); +void synopGMAC_rx_disable(synopGMACdevice * gmacdev); +void synopGMAC_tx_enable(synopGMACdevice * gmacdev); +void synopGMAC_tx_disable(synopGMACdevice * gmacdev); +void synopGMAC_frame_filter_enable(synopGMACdevice * gmacdev); +void synopGMAC_frame_filter_disable(synopGMACdevice * gmacdev); +void synopGMAC_write_hash_table_high(synopGMACdevice * gmacdev, u32 data); +void synopGMAC_write_hash_table_low(synopGMACdevice * gmacdev, u32 data); +void synopGMAC_hash_perfect_filter_enable(synopGMACdevice * gmacdev); +void synopGMAC_Hash_filter_only_enable(synopGMACdevice * gmacdev); +void synopGMAC_src_addr_filter_enable(synopGMACdevice * gmacdev); +void synopGMAC_src_addr_filter_disable(synopGMACdevice * gmacdev); +void synopGMAC_dst_addr_filter_inverse(synopGMACdevice * gmacdev); +void synopGMAC_dst_addr_filter_normal(synopGMACdevice * gmacdev); +void synopGMAC_set_pass_control(synopGMACdevice * gmacdev,u32 passcontrol); +void synopGMAC_broadcast_enable(synopGMACdevice * gmacdev); +void synopGMAC_broadcast_disable(synopGMACdevice * gmacdev); +void synopGMAC_multicast_enable(synopGMACdevice * gmacdev); +void synopGMAC_multicast_disable(synopGMACdevice * gmacdev); +void synopGMAC_multicast_hash_filter_enable(synopGMACdevice * gmacdev); +void synopGMAC_multicast_hash_filter_disable(synopGMACdevice * gmacdev); +void synopGMAC_promisc_enable(synopGMACdevice * gmacdev); +void synopGMAC_promisc_disable(synopGMACdevice * gmacdev); +void synopGMAC_unicast_hash_filter_enable(synopGMACdevice * gmacdev); +void synopGMAC_unicast_hash_filter_disable(synopGMACdevice * gmacdev); +void synopGMAC_unicast_pause_frame_detect_enable(synopGMACdevice * gmacdev); +void synopGMAC_unicast_pause_frame_detect_disable(synopGMACdevice * gmacdev); +void synopGMAC_rx_flow_control_enable(synopGMACdevice * gmacdev); +void synopGMAC_rx_flow_control_disable(synopGMACdevice * gmacdev); +void synopGMAC_tx_flow_control_enable(synopGMACdevice * gmacdev); +void synopGMAC_tx_flow_control_disable(synopGMACdevice * gmacdev); +void synopGMAC_tx_activate_flow_control(synopGMACdevice * gmacdev); +void synopGMAC_tx_deactivate_flow_control(synopGMACdevice * gmacdev); +void synopGMAC_pause_control(synopGMACdevice *gmacdev); +s32 synopGMAC_mac_init(synopGMACdevice * gmacdev); +s32 synopGMAC_check_phy_init (synopGMACdevice * gmacdev); +s32 synopGMAC_set_mac_addr(synopGMACdevice *gmacdev, u32 MacHigh, u32 MacLow, u8 *MacAddr); +s32 synopGMAC_get_mac_addr(synopGMACdevice *gmacdev, u32 MacHigh, u32 MacLow, u8 *MacAddr); +s32 synopGMAC_attach (synopGMACdevice * gmacdev, u32 macBase, u32 dmaBase, u32 phyBase); +void synopGMAC_rx_desc_init_ring(DmaDesc *desc, bool last_ring_desc); +void synopGMAC_tx_desc_init_ring(DmaDesc *desc, bool last_ring_desc); +void synopGMAC_rx_desc_init_chain(DmaDesc * desc); +void synopGMAC_tx_desc_init_chain(DmaDesc * desc); +s32 synopGMAC_init_tx_rx_desc_queue(synopGMACdevice *gmacdev); +void synopGMAC_init_rx_desc_base(synopGMACdevice *gmacdev); +void synopGMAC_init_tx_desc_base(synopGMACdevice *gmacdev); +void synopGMAC_set_owner_dma(DmaDesc *desc); +void synopGMAC_set_desc_sof(DmaDesc *desc); +void synopGMAC_set_desc_eof(DmaDesc *desc); +bool synopGMAC_is_sof_in_rx_desc(DmaDesc *desc); +bool synopGMAC_is_eof_in_rx_desc(DmaDesc *desc); +bool synopGMAC_is_da_filter_failed(DmaDesc *desc); +bool synopGMAC_is_sa_filter_failed(DmaDesc *desc); +bool synopGMAC_is_desc_owned_by_dma(DmaDesc *desc); +u32 synopGMAC_get_rx_desc_frame_length(u32 status); +bool synopGMAC_is_desc_valid(u32 status); +bool synopGMAC_is_desc_empty(DmaDesc *desc); +bool synopGMAC_is_rx_desc_valid(u32 status); +bool synopGMAC_is_tx_aborted(u32 status); +bool synopGMAC_is_tx_carrier_error(u32 status); +u32 synopGMAC_get_tx_collision_count(u32 status); +u32 synopGMAC_is_exc_tx_collisions(u32 status); +bool synopGMAC_is_rx_frame_damaged(u32 status); +bool synopGMAC_is_rx_frame_collision(u32 status); +bool synopGMAC_is_rx_crc(u32 status); +bool synopGMAC_is_frame_dribbling_errors(u32 status); +bool synopGMAC_is_rx_frame_length_errors(u32 status); +bool synopGMAC_is_last_rx_desc(synopGMACdevice * gmacdev,DmaDesc *desc); +bool synopGMAC_is_last_tx_desc(synopGMACdevice * gmacdev,DmaDesc *desc); +bool synopGMAC_is_rx_desc_chained(DmaDesc * desc); +bool synopGMAC_is_tx_desc_chained(DmaDesc * desc); +void synopGMAC_get_desc_data(DmaDesc * desc, u32 * Status, u32 * Buffer1, u32 * Length1, u32 * Data1); + +s32 synopGMAC_get_tx_qptr(synopGMACdevice * gmacdev, u32 * Status, u32 * Buffer1, u32 * Length1, u32 * Data1, u32 * Ext_Status, u32 * Time_Stamp_High, u32 * Time_Stamp_low); + +s32 synopGMAC_set_tx_qptr(synopGMACdevice * gmacdev, u32 Buffer1, u32 Length1, u32 Data1, u32 offload_needed, u32 ts); +s32 synopGMAC_set_rx_qptr(synopGMACdevice * gmacdev, u32 Buffer1, u32 Length1, u32 Data1); + +s32 synopGMAC_get_rx_qptr(synopGMACdevice * gmacdev, u32 * Status, u32 * Buffer1, u32 * Length1, u32 * Data1, u32 * Ext_Status, u32 * Time_Stamp_High, u32 * Time_Stamp_low); + +void synopGMAC_clear_interrupt(synopGMACdevice *gmacdev); +u32 synopGMAC_get_interrupt_type(synopGMACdevice *gmacdev); +u32 synopGMAC_get_interrupt_mask(synopGMACdevice *gmacdev); +void synopGMAC_enable_interrupt(synopGMACdevice *gmacdev, u32 interrupts); +void synopGMAC_disable_interrupt_all(synopGMACdevice *gmacdev); +void synopGMAC_disable_interrupt(synopGMACdevice *gmacdev, u32 interrupts); +void synopGMAC_enable_dma_rx(synopGMACdevice * gmacdev); +void synopGMAC_enable_dma_tx(synopGMACdevice * gmacdev); +void synopGMAC_resume_dma_tx(synopGMACdevice * gmacdev); +void synopGMAC_resume_dma_rx(synopGMACdevice * gmacdev); +void synopGMAC_take_desc_ownership(DmaDesc * desc); +void synopGMAC_take_desc_ownership_rx(synopGMACdevice * gmacdev); +void synopGMAC_take_desc_ownership_tx(synopGMACdevice * gmacdev); +void synopGMAC_disable_dma_tx(synopGMACdevice * gmacdev); +void synopGMAC_disable_dma_rx(synopGMACdevice * gmacdev); +/******Following APIs are valid only for Enhanced Descriptor from 3.50a release onwards*******/ +bool synopGMAC_is_ext_status(synopGMACdevice *gmacdev,u32 status); +bool synopGMAC_ES_is_IP_header_error(synopGMACdevice *gmacdev,u32 ext_status); +bool synopGMAC_ES_is_rx_checksum_bypassed(synopGMACdevice *gmacdev,u32 ext_status); +bool synopGMAC_ES_is_IP_payload_error(synopGMACdevice *gmacdev,u32 ext_status); +/*******************PMT APIs***************************************/ +void synopGMAC_pmt_int_enable(synopGMACdevice *gmacdev); +void synopGMAC_pmt_int_disable(synopGMACdevice *gmacdev); +void synopGMAC_power_down_enable(synopGMACdevice *gmacdev); +void synopGMAC_power_down_disable(synopGMACdevice *gmacdev); +void synopGMAC_enable_pmt_interrupt(synopGMACdevice *gmacdev); +void synopGMAC_disable_pmt_interrupt(synopGMACdevice *gmacdev); +void synopGMAC_magic_packet_enable(synopGMACdevice *gmacdev); +void synopGMAC_magic_packet_disable(synopGMACdevice *gmacdev); +void synopGMAC_wakeup_frame_enable(synopGMACdevice *gmacdev); +void synopGMAC_pmt_unicast_enable(synopGMACdevice *gmacdev); +bool synopGMAC_is_magic_packet_received(synopGMACdevice *gmacdev); +bool synopGMAC_is_wakeup_frame_received(synopGMACdevice *gmacdev); +void synopGMAC_write_wakeup_frame_register(synopGMACdevice *gmacdev, u32 * filter_contents); + +/*******************Ip checksum offloading APIs***************************************/ +void synopGMAC_enable_rx_chksum_offload(synopGMACdevice *gmacdev); +void synopGMAC_disable_rx_chksum_offload(synopGMACdevice *gmacdev); +void synopGMAC_rx_tcpip_chksum_drop_enable(synopGMACdevice *gmacdev); +void synopGMAC_rx_tcpip_chksum_drop_disable(synopGMACdevice *gmacdev); +u32 synopGMAC_is_rx_checksum_error(synopGMACdevice *gmacdev, u32 status); +bool synopGMAC_is_tx_ipv4header_checksum_error(synopGMACdevice *gmacdev, u32 status); +bool synopGMAC_is_tx_payload_checksum_error(synopGMACdevice *gmacdev, u32 status); +void synopGMAC_tx_checksum_offload_bypass(synopGMACdevice *gmacdev, DmaDesc *desc); +void synopGMAC_tx_checksum_offload_ipv4hdr(synopGMACdevice *gmacdev, DmaDesc *desc); +void synopGMAC_tx_checksum_offload_tcponly(synopGMACdevice *gmacdev, DmaDesc *desc); +void synopGMAC_tx_checksum_offload_tcp_pseudo(synopGMACdevice *gmacdev, DmaDesc *desc); + + +// For testing --ya +void synopGMAC_src_addr_insert_enable(synopGMACdevice * gmacdev); +void synopGMAC_src_addr_insert_disable(synopGMACdevice * gmacdev); +void synopGMAC_src_addr_replace_enable(synopGMACdevice * gmacdev); +void synopGMAC_src_addr_replace_disable(synopGMACdevice * gmacdev); + +void synopGMAC_svlan_insertion_enable(synopGMACdevice * gmacdev, u16 vlantag); +void synopGMAC_cvlan_insertion_enable(synopGMACdevice * gmacdev, u16 vlantag); +void synopGMAC_svlan_replace_enable(synopGMACdevice * gmacdev, u16 vlantag); +void synopGMAC_cvlan_replace_enable(synopGMACdevice * gmacdev, u16 vlantag); +void synopGMAC_vlan_deletion_enable(synopGMACdevice * gmacdev); +void synopGMAC_vlan_no_act_enable(synopGMACdevice * gmacdev); + +void synopGMAC_set_crc_replacement(synopGMACdevice * gmacdev); +void synopGMAC_clr_crc_replacement(synopGMACdevice * gmacdev); + +void synopGMAC_enable_under_size_pkt(synopGMACdevice * gmacdev); +void synopGMAC_disable_under_size_pkt(synopGMACdevice * gmacdev); + +void synopGMAC_enable_crc_err_pkt(synopGMACdevice * gmacdev); +void synopGMAC_disable_crc_err_pkt(synopGMACdevice * gmacdev); + +#endif /* End of file */ diff --git a/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/synopGMAC_network_interface.c b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/synopGMAC_network_interface.c new file mode 100644 index 0000000000..136379a4ae --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/synopGMAC_network_interface.c @@ -0,0 +1,942 @@ +/* =================================================================================== + * Copyright (c) <2009> Synopsys, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software annotated with this license and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without + * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * =================================================================================== */ + + +/** \file + * This is the network dependent layer to handle network related functionality. + * This file is tightly coupled to neworking frame work of linux 2.6.xx kernel. + * The functionality carried out in this file should be treated as an example only + * if the underlying operating system is not Linux. + * + * \note Many of the functions other than the device specific functions + * changes for operating system other than Linux 2.6.xx + * \internal + *-----------------------------REVISION HISTORY----------------------------------- + * Synopsys 01/Aug/2007 Created + */ + +#include "string.h" +#include "synopGMAC_network_interface.h" + + +synopGMACdevice GMACdev[GMAC_CNT]; +static DmaDesc tx_desc[GMAC_CNT][TRANSMIT_DESC_SIZE] __attribute__ ((aligned (64))); +static DmaDesc rx_desc[GMAC_CNT][RECEIVE_DESC_SIZE] __attribute__ ((aligned (64))); + +//static struct sk_buff tx_buf[GMAC_CNT][TRANSMIT_DESC_SIZE] __attribute__ ((aligned (64))); +//static struct sk_buff rx_buf[GMAC_CNT][RECEIVE_DESC_SIZE] __attribute__ ((aligned (64))); +struct sk_buff tx_buf[GMAC_CNT][TRANSMIT_DESC_SIZE] __attribute__ ((aligned (64))); +struct sk_buff rx_buf[GMAC_CNT][RECEIVE_DESC_SIZE] __attribute__ ((aligned (64))); + +// These 2 are accessable from application +struct sk_buff txbuf[GMAC_CNT] __attribute__ ((aligned (64))); // set align to separate cacheable and non-cacheable data to different cache line. +struct sk_buff rxbuf[GMAC_CNT] __attribute__ ((aligned (64))); + +u8 mac_addr0[6] = DEFAULT_MAC0_ADDRESS; +u8 mac_addr1[6] = DEFAULT_MAC1_ADDRESS; + +//static struct timer_list synopGMAC_cable_unplug_timer; +//static u32 GMAC_Power_down; // This global variable is used to indicate the ISR whether the interrupts occured in the process of powering down the mac or not + + +/** + * Function used to detect the cable plugging and unplugging. + * This function gets scheduled once in every second and polls + * the PHY register for network cable plug/unplug. Once the + * connection is back the GMAC device is configured as per + * new Duplex mode and Speed of the connection. + * @param[in] u32 type but is not used currently. + * \return returns void. + * \note This function is tightly coupled with Linux 2.6.xx. + * \callgraph + */ + + + +void synopGMAC_powerdown_mac(synopGMACdevice *gmacdev) +{ + TR0("Put the GMAC to power down mode..\n"); + // Disable the Dma engines in tx path + gmacdev->GMAC_Power_down = 1; // Let ISR know that Mac is going to be in the power down mode + synopGMAC_disable_dma_tx(gmacdev); + plat_delay(10000); //allow any pending transmission to complete + // Disable the Mac for both tx and rx + synopGMAC_tx_disable(gmacdev); + synopGMAC_rx_disable(gmacdev); + plat_delay(10000); //Allow any pending buffer to be read by host + //Disable the Dma in rx path + synopGMAC_disable_dma_rx(gmacdev); + + //enable the power down mode + //synopGMAC_pmt_unicast_enable(gmacdev); + + //prepare the gmac for magic packet reception and wake up frame reception + synopGMAC_magic_packet_enable(gmacdev); + + //gate the application and transmit clock inputs to the code. This is not done in this driver :). + + //enable the Mac for reception + synopGMAC_rx_enable(gmacdev); + + //Enable the assertion of PMT interrupt + synopGMAC_pmt_int_enable(gmacdev); + //enter the power down mode + synopGMAC_power_down_enable(gmacdev); + return; +} + +void synopGMAC_powerup_mac(synopGMACdevice *gmacdev) +{ + gmacdev->GMAC_Power_down = 0; // Let ISR know that MAC is out of power down now + if( synopGMAC_is_magic_packet_received(gmacdev)) + TR("GMAC wokeup due to Magic Pkt Received\n"); + if(synopGMAC_is_wakeup_frame_received(gmacdev)) + TR("GMAC wokeup due to Wakeup Frame Received\n"); + //Disable the assertion of PMT interrupt + synopGMAC_pmt_int_disable(gmacdev); + //Enable the mac and Dma rx and tx paths + synopGMAC_rx_enable(gmacdev); + synopGMAC_enable_dma_rx(gmacdev); + + synopGMAC_tx_enable(gmacdev); + synopGMAC_enable_dma_tx(gmacdev); + return; +} + +/** + * This sets up the transmit Descriptor queue in ring or chain mode. + * This function is tightly coupled to the platform and operating system + * Device is interested only after the descriptors are setup. Therefore this function + * is not included in the device driver API. This function should be treated as an + * example code to design the descriptor structures for ring mode or chain mode. + * This function depends on the pcidev structure for allocation consistent dma-able memory in case of linux. + * This limitation is due to the fact that linux uses pci structure to allocate a dmable memory + * - Allocates the memory for the descriptors. + * - Initialize the Busy and Next descriptors indices to 0(Indicating first descriptor). + * - Initialize the Busy and Next descriptors to first descriptor address. + * - Initialize the last descriptor with the endof ring in case of ring mode. + * - Initialize the descriptors in chain mode. + * @param[in] pointer to synopGMACdevice. + * @param[in] pointer to pci_device structure. + * @param[in] number of descriptor expected in tx descriptor queue. + * @param[in] whether descriptors to be created in RING mode or CHAIN mode. + * \return 0 upon success. Error code upon failure. + * \note This function fails if allocation fails for required number of descriptors in Ring mode, but in chain mode + * function returns -ESYNOPGMACNOMEM in the process of descriptor chain creation. once returned from this function + * user should for gmacdev->TxDescCount to see how many descriptors are there in the chain. Should continue further + * only if the number of descriptors in the chain meets the requirements + */ + +s32 synopGMAC_setup_tx_desc_queue(synopGMACdevice * gmacdev,u32 no_of_desc, u32 desc_mode) +{ + s32 i; + + DmaDesc *first_desc = &tx_desc[gmacdev->Intf][0]; + dma_addr_t dma_addr; + gmacdev->TxDescCount = 0; + + TR("Total size of memory required for Tx Descriptors in Ring Mode = 0x%08x\n",((sizeof(DmaDesc) * no_of_desc))); + + gmacdev->TxDescCount = no_of_desc; + gmacdev->TxDesc = first_desc; +#ifdef CACHE_ON + gmacdev->TxDescDma = (DmaDesc *)((u64)first_desc | 0x100000000); +#else + gmacdev->TxDescDma = (DmaDesc *)((u64)first_desc); +#endif + for(i =0; i < gmacdev -> TxDescCount; i++) { + synopGMAC_tx_desc_init_ring(gmacdev->TxDescDma + i, i == gmacdev->TxDescCount-1); + TR("%02d %08x \n",i, (unsigned int)(gmacdev->TxDesc + i) ); + } + + + gmacdev->TxNext = 0; + gmacdev->TxBusy = 0; + gmacdev->TxNextDesc = gmacdev->TxDesc; + gmacdev->TxBusyDesc = gmacdev->TxDesc; + gmacdev->BusyTxDesc = 0; + + return 0; +} + + +/** + * This sets up the receive Descriptor queue in ring or chain mode. + * This function is tightly coupled to the platform and operating system + * Device is interested only after the descriptors are setup. Therefore this function + * is not included in the device driver API. This function should be treated as an + * example code to design the descriptor structures in ring mode or chain mode. + * This function depends on the pcidev structure for allocation of consistent dma-able memory in case of linux. + * This limitation is due to the fact that linux uses pci structure to allocate a dmable memory + * - Allocates the memory for the descriptors. + * - Initialize the Busy and Next descriptors indices to 0(Indicating first descriptor). + * - Initialize the Busy and Next descriptors to first descriptor address. + * - Initialize the last descriptor with the endof ring in case of ring mode. + * - Initialize the descriptors in chain mode. + * @param[in] pointer to synopGMACdevice. + * @param[in] pointer to pci_device structure. + * @param[in] number of descriptor expected in rx descriptor queue. + * @param[in] whether descriptors to be created in RING mode or CHAIN mode. + * \return 0 upon success. Error code upon failure. + * \note This function fails if allocation fails for required number of descriptors in Ring mode, but in chain mode + * function returns -ESYNOPGMACNOMEM in the process of descriptor chain creation. once returned from this function + * user should for gmacdev->RxDescCount to see how many descriptors are there in the chain. Should continue further + * only if the number of descriptors in the chain meets the requirements + */ +s32 synopGMAC_setup_rx_desc_queue(synopGMACdevice * gmacdev,u32 no_of_desc, u32 desc_mode) +{ + s32 i; + + DmaDesc *first_desc = &rx_desc[gmacdev->Intf][0]; + dma_addr_t dma_addr; + gmacdev->RxDescCount = 0; + + + TR("total size of memory required for Rx Descriptors in Ring Mode = 0x%08x\n",((sizeof(DmaDesc) * no_of_desc))); + + gmacdev->RxDescCount = no_of_desc; + gmacdev->RxDesc = first_desc; +#ifdef CACHE_ON + gmacdev->RxDescDma = (DmaDesc *)((u64)first_desc | 0x100000000); +#else + gmacdev->RxDescDma = (DmaDesc *)((u64)first_desc); +#endif + for(i =0; i < gmacdev -> RxDescCount; i++) { + synopGMAC_rx_desc_init_ring(gmacdev->RxDescDma + i, i == gmacdev->RxDescCount-1); + TR("%02d %08x \n",i, (unsigned int)(gmacdev->RxDesc + i)); + } + + + gmacdev->RxNext = 0; + gmacdev->RxBusy = 0; + gmacdev->RxNextDesc = gmacdev->RxDesc; + gmacdev->RxBusyDesc = gmacdev->RxDesc; + + gmacdev->BusyRxDesc = 0; + + return 0; +} + + +/** + * This gives up the receive Descriptor queue in ring or chain mode. + * This function is tightly coupled to the platform and operating system + * Once device's Dma is stopped the memory descriptor memory and the buffer memory deallocation, + * is completely handled by the operating system, this call is kept outside the device driver Api. + * This function should be treated as an example code to de-allocate the descriptor structures in ring mode or chain mode + * and network buffer deallocation. + * This function depends on the pcidev structure for dma-able memory deallocation for both descriptor memory and the + * network buffer memory under linux. + * The responsibility of this function is to + * - Free the network buffer memory if any. + * - Fee the memory allocated for the descriptors. + * @param[in] pointer to synopGMACdevice. + * @param[in] pointer to pci_device structure. + * @param[in] number of descriptor expected in rx descriptor queue. + * @param[in] whether descriptors to be created in RING mode or CHAIN mode. + * \return 0 upon success. Error code upon failure. + * \note No referece should be made to descriptors once this function is called. This function is invoked when the device is closed. + */ +void synopGMAC_giveup_rx_desc_queue(synopGMACdevice * gmacdev, u32 desc_mode) +{ + gmacdev->RxDesc = NULL; + gmacdev->RxDescDma = 0; + return; +} + +/** + * This gives up the transmit Descriptor queue in ring or chain mode. + * This function is tightly coupled to the platform and operating system + * Once device's Dma is stopped the memory descriptor memory and the buffer memory deallocation, + * is completely handled by the operating system, this call is kept outside the device driver Api. + * This function should be treated as an example code to de-allocate the descriptor structures in ring mode or chain mode + * and network buffer deallocation. + * This function depends on the pcidev structure for dma-able memory deallocation for both descriptor memory and the + * network buffer memory under linux. + * The responsibility of this function is to + * - Free the network buffer memory if any. + * - Fee the memory allocated for the descriptors. + * @param[in] pointer to synopGMACdevice. + * @param[in] pointer to pci_device structure. + * @param[in] number of descriptor expected in tx descriptor queue. + * @param[in] whether descriptors to be created in RING mode or CHAIN mode. + * \return 0 upon success. Error code upon failure. + * \note No reference should be made to descriptors once this function is called. This function is invoked when the device is closed. + */ +void synopGMAC_giveup_tx_desc_queue(synopGMACdevice * gmacdev, u32 desc_mode) +{ + + + gmacdev->TxDesc = NULL; + gmacdev->TxDescDma = 0; + return; +} + +/** + * Function to handle housekeeping after a packet is transmitted over the wire. + * After the transmission of a packet DMA generates corresponding interrupt + * (if it is enabled). It takes care of returning the sk_buff to the linux + * kernel, updating the networking statistics and tracking the descriptors. + * @param[in] pointer to net_device structure. + * \return void. + * \note This function runs in interrupt context + */ +void synop_handle_transmit_over(int intf) +{ + synopGMACdevice * gmacdev; + s32 desc_index; + u32 data1; + u32 status; + u32 length1; + u32 dma_addr1; + + u32 ext_status; + //u16 time_stamp_higher; + u32 time_stamp_high; + u32 time_stamp_low; + + + gmacdev = &GMACdev[intf]; + + /*Handle the transmit Descriptors*/ + do { + + desc_index = synopGMAC_get_tx_qptr(gmacdev, &status, &dma_addr1, &length1, &data1,&ext_status,&time_stamp_high,&time_stamp_low); + //synopGMAC_TS_read_timestamp_higher_val(gmacdev, &time_stamp_higher); + + if(desc_index >= 0 /*&& data1 != 0*/) { + TR("Finished Transmit at Tx Descriptor %d for skb 0x%08x and buffer = %08x whose status is %08x \n", desc_index,data1,dma_addr1,status); + + if(synopGMAC_is_tx_ipv4header_checksum_error(gmacdev, status)) { + TR("Harware Failed to Insert IPV4 Header Checksum\n"); + gmacdev->synopGMACNetStats.tx_ip_header_errors++; + } + if(synopGMAC_is_tx_payload_checksum_error(gmacdev, status)) { + TR("Harware Failed to Insert Payload Checksum\n"); + gmacdev->synopGMACNetStats.tx_ip_payload_errors++; + } + + + + if(synopGMAC_is_desc_valid(status)) { + gmacdev->synopGMACNetStats.tx_bytes += length1; + gmacdev->synopGMACNetStats.tx_packets++; + if(status & DescTxTSStatus) { + gmacdev->tx_sec = time_stamp_high; + gmacdev->tx_subsec = time_stamp_low; + } else { + gmacdev->tx_sec = 0; + gmacdev->tx_subsec = 0; + } + } else { + TR("Error in Status %08x\n",status); + gmacdev->synopGMACNetStats.tx_errors++; + gmacdev->synopGMACNetStats.tx_aborted_errors += synopGMAC_is_tx_aborted(status); + gmacdev->synopGMACNetStats.tx_carrier_errors += synopGMAC_is_tx_carrier_error(status); + } + } + gmacdev->synopGMACNetStats.collisions += synopGMAC_get_tx_collision_count(status); + } while(desc_index >= 0); + +} + + + + +/** + * Function to Receive a packet from the interface. + * After Receiving a packet, DMA transfers the received packet to the system memory + * and generates corresponding interrupt (if it is enabled). This function prepares + * the sk_buff for received packet after removing the ethernet CRC, and hands it over + * to linux networking stack. + * - Updataes the networking interface statistics + * - Keeps track of the rx descriptors + * @param[in] pointer to net_device structure. + * \return void. + * \note This function runs in interrupt context. + */ +extern DmaDesc * prevtx; // for CRC test +s32 synop_handle_received_data(int intf, u8 **buf) // Chris, to get RX buffer pointer +{ + + synopGMACdevice * gmacdev; + s32 desc_index; + + u32 data1; + u32 len = 0; + u32 status; + u32 dma_addr1; + + u32 ext_status; + //u16 time_stamp_higher; + u32 time_stamp_high; + u32 time_stamp_low; + struct sk_buff *rb = &rxbuf[intf]; + + //struct sk_buff *skb; //This is the pointer to hold the received data + + TR("%s\n",__FUNCTION__); + + + + gmacdev = &GMACdev[intf]; + + /*Handle the Receive Descriptors*/ + do { + + desc_index = synopGMAC_get_rx_qptr(gmacdev, &status, + &dma_addr1, NULL, &data1, + &ext_status, &time_stamp_high, &time_stamp_low); + if(desc_index >0) { + //synopGMAC_TS_read_timestamp_higher_val(gmacdev, &time_stamp_higher); + //TR("S:%08x ES:%08x DA1:%08x d1:%08x TSH:%08x TSL:%08x TSHW:%08x \n",status,ext_status,dma_addr1, data1,time_stamp_high,time_stamp_low,time_stamp_higher); + TR("S:%08x ES:%08x DA1:%08x d1:%08x TSH:%08x TSL:%08x\n",status,ext_status,dma_addr1, data1,time_stamp_high,time_stamp_low); + } + + if(desc_index >= 0 /*&& data1 != 0*/) { + TR("Received Data at Rx Descriptor %d for skb 0x%08x whose status is %08x\n",desc_index,data1,status); + + + //skb = (struct sk_buff *)((u64)data1); + if(1/*synopGMAC_is_rx_desc_valid(status)*/) { + // Always enter this loop. synopGMAC_is_rx_desc_valid() also report invalid descriptor + // if there's packet error generated by test code and drop it. But we need to execute ext_status + // check code to tell what's going on. --ya + + len = synopGMAC_get_rx_desc_frame_length(status) - 4; //Not interested in Ethernet CRC bytes + + + // Now lets check for the IPC offloading + /* Since we have enabled the checksum offloading in hardware, lets inform the kernel + not to perform the checksum computation on the incoming packet. Note that ip header + checksum will be computed by the kernel immaterial of what we inform. Similary TCP/UDP/ICMP + pseudo header checksum will be computed by the stack. What we can inform is not to perform + payload checksum. + When CHECKSUM_UNNECESSARY is set kernel bypasses the checksum computation. + */ + + TR("Checksum Offloading will be done now\n"); + + if(synopGMAC_is_ext_status(gmacdev, status)) { // extended status present indicates that the RDES4 need to be probed + TR("Extended Status present\n"); + if(synopGMAC_ES_is_IP_header_error(gmacdev,ext_status)) { // IP header (IPV4) checksum error + //Linux Kernel doesnot care for ipv4 header checksum. So we will simply proceed by printing a warning .... + TR("(EXTSTS)Error in IP header error\n"); + gmacdev->synopGMACNetStats.rx_ip_header_errors++; + } + if(synopGMAC_ES_is_rx_checksum_bypassed(gmacdev,ext_status)) { // Hardware engine bypassed the checksum computation/checking + TR("(EXTSTS)Hardware bypassed checksum computation\n"); + } + if(synopGMAC_ES_is_IP_payload_error(gmacdev,ext_status)) { // IP payload checksum is in error (UDP/TCP/ICMP checksum error) + TR("(EXTSTS) Error in EP payload\n"); + gmacdev->synopGMACNetStats.rx_ip_payload_errors++; + } + } else { // No extended status. So relevant information is available in the status itself + if(synopGMAC_is_rx_checksum_error(gmacdev, status) == RxNoChkError ) { + TR("Ip header and TCP/UDP payload checksum Bypassed \n"); + } + if(synopGMAC_is_rx_checksum_error(gmacdev, status) == RxIpHdrChkError ) { + //Linux Kernel doesnot care for ipv4 header checksum. So we will simply proceed by printing a warning .... + TR(" Error in 16bit IPV4 Header Checksum \n"); + gmacdev->synopGMACNetStats.rx_ip_header_errors++; + } + if(synopGMAC_is_rx_checksum_error(gmacdev, status) == RxLenLT600 ) { + TR("IEEE 802.3 type frame with Length field Lesss than 0x0600 \n"); + } + if(synopGMAC_is_rx_checksum_error(gmacdev, status) == RxIpHdrPayLoadChkBypass ) { + TR("Ip header and TCP/UDP payload checksum Bypassed \n"); + } + if(synopGMAC_is_rx_checksum_error(gmacdev, status) == RxChkBypass ) { + TR("Ip header and TCP/UDP payload checksum Bypassed \n"); + } + if(synopGMAC_is_rx_checksum_error(gmacdev, status) == RxPayLoadChkError ) { + TR(" TCP/UDP payload checksum Error \n"); + gmacdev->synopGMACNetStats.rx_ip_payload_errors++; + } + if(synopGMAC_is_rx_checksum_error(gmacdev, status) == RxIpHdrPayLoadChkError ) { + //Linux Kernel doesnot care for ipv4 header checksum. So we will simply proceed by printing a warning .... + TR(" Both IP header and Payload Checksum Error \n"); + gmacdev->synopGMACNetStats.rx_ip_header_errors++; + gmacdev->synopGMACNetStats.rx_ip_payload_errors++; + } + } +#if 0 +#ifdef CACHE_ON + memcpy((void *)rb->data, (void *)((u64)dma_addr1 | 0x100000000), len); +#else + memcpy((void *)rb->data, (void *)((u64)dma_addr1), len); +#endif + if(prevtx != NULL) { +#ifdef CACHE_ON + memcpy((void *)(rb->data + len), (void *)((u64)(dma_addr1 | 0x100000000) + len), 4); +#else + memcpy((void *)(rb->data + len), (void *)((u64)dma_addr1 + len), 4); +#endif + } +#else + *buf = (u32)((u64)dma_addr1); +#endif + rb->rdy = 1; + rb->len = len; + gmacdev->synopGMACNetStats.rx_packets++; + gmacdev->synopGMACNetStats.rx_bytes += len; + if(status & DescRxTSAvailable) { + gmacdev->rx_sec = time_stamp_high; + gmacdev->rx_subsec = time_stamp_low; + } else { + gmacdev->rx_sec = 0; + gmacdev->rx_subsec = 0; + } + } else { + /*Now the present skb should be set free*/ + TR("s: %08x\n",status); + gmacdev->synopGMACNetStats.rx_errors++; + gmacdev->synopGMACNetStats.collisions += synopGMAC_is_rx_frame_collision(status); + gmacdev->synopGMACNetStats.rx_crc_errors += synopGMAC_is_rx_crc(status); + gmacdev->synopGMACNetStats.rx_frame_errors += synopGMAC_is_frame_dribbling_errors(status); + gmacdev->synopGMACNetStats.rx_length_errors += synopGMAC_is_rx_frame_length_errors(status); + } + } + } while(0); //while(desc_index >= 0); + return len; +} + +u32 volatile LPIStsChange = 0; +u32 volatile LPIReg = 0; +/** + * Interrupt service routing. + * This is the function registered as ISR for device interrupts. + * @param[in] interrupt number. + * @param[in] void pointer to device unique structure (Required for shared interrupts in Linux). + * @param[in] pointer to pt_regs (not used). + * \return Returns IRQ_NONE if not device interrupts IRQ_HANDLED for device interrupts. + * \note This function runs in interrupt context + * + */ +void synopGMAC0_intr_handler(void) +{ + synopGMACdevice * gmacdev = &GMACdev[0]; + u32 interrupt,dma_status_reg, mac_status_reg; + s32 status; + u32 dma_addr; + + // Check GMAC interrupt + mac_status_reg = synopGMACReadReg((u32 *)gmacdev->MacBase, GmacInterruptStatus); + if(mac_status_reg & GmacTSIntSts) { + gmacdev->synopGMACNetStats.ts_int = 1; + status = synopGMACReadReg((u32 *)gmacdev->MacBase, GmacTSStatus); + if(!(status & (1 << 1))) + printf("TS alarm flag not set??\n"); + else + printf("TS alarm!!!!!!!!!!!!!!!!\n"); + + } + if(mac_status_reg & GmacLPIIntSts) { + //printf("LPI\n"); + LPIStsChange = 1; + LPIReg = synopGMACReadReg((u32 *)gmacdev->MacBase, GmacLPICtrlSts); + + } + if(mac_status_reg & GmacRgmiiIntSts) { + u32 volatile reg; + reg = synopGMACReadReg((u32 *)gmacdev->MacBase, GmacRgmiiCtrlSts); + + } + synopGMACWriteReg((u32 *)gmacdev->MacBase, GmacInterruptStatus ,mac_status_reg); + + /*Read the Dma interrupt status to know whether the interrupt got generated by our device or not*/ + dma_status_reg = synopGMACReadReg((u32 *)gmacdev->DmaBase, DmaStatus); + //printf("i"); + //printf("i %08x %08x\n", mac_status_reg, dma_status_reg); + + if(dma_status_reg == 0) + return; + + synopGMAC_disable_interrupt_all(gmacdev); + + TR("%s:Dma Status Reg: 0x%08x\n",__FUNCTION__,dma_status_reg); + + if(dma_status_reg & GmacPmtIntr) { + TR("%s:: Interrupt due to PMT module\n",__FUNCTION__); + synopGMAC_powerup_mac(gmacdev); + } + + if(dma_status_reg & GmacLineIntfIntr) { + TR("%s:: Interrupt due to GMAC LINE module\n",__FUNCTION__); + } + + /*Now lets handle the DMA interrupts*/ + interrupt = synopGMAC_get_interrupt_type(gmacdev); + TR("%s:Interrupts to be handled: 0x%08x\n",__FUNCTION__,interrupt); + + + if(interrupt & synopGMACDmaError) { + + TR("%s::Fatal Bus Error Inetrrupt Seen\n",__FUNCTION__); + synopGMAC_disable_dma_tx(gmacdev); + synopGMAC_disable_dma_rx(gmacdev); + + synopGMAC_take_desc_ownership_tx(gmacdev); + synopGMAC_take_desc_ownership_rx(gmacdev); + + synopGMAC_init_tx_rx_desc_queue(gmacdev); + + synopGMAC_reset(gmacdev);//reset the DMA engine and the GMAC ip + + synopGMAC_set_mac_addr(gmacdev,GmacAddr0High,GmacAddr0Low, gmacdev->Intf == 0 ? mac_addr0 : mac_addr1); + synopGMAC_dma_bus_mode_init(gmacdev,DmaFixedBurstEnable| DmaBurstLength8 | DmaDescriptorSkip0/*DmaDescriptorSkip2*/ ); + synopGMAC_dma_control_init(gmacdev,DmaStoreAndForward); + synopGMAC_init_rx_desc_base(gmacdev); + synopGMAC_init_tx_desc_base(gmacdev); + synopGMAC_mac_init(gmacdev); + synopGMAC_enable_dma_rx(gmacdev); + synopGMAC_enable_dma_tx(gmacdev); + + } + + + if(interrupt & synopGMACDmaRxNormal) { + u8 **buf + //printf("rx\n"); + TR("%s:: Rx Normal \n", __FUNCTION__); + synop_handle_received_data(0, buf); // Chris, to get RX buffer pointer + } + + if(interrupt & synopGMACDmaRxAbnormal) { + TR("%s::Abnormal Rx Interrupt Seen\n",__FUNCTION__); + gmacdev->synopGMACNetStats.rx_over_errors++; +#if 1 + + if(gmacdev->GMAC_Power_down == 0) { // If Mac is not in powerdown + synopGMAC_resume_dma_rx(gmacdev);//To handle GBPS with 12 descriptors + } +#endif + } + + if(interrupt & synopGMACDmaRxStopped) { + TR("%s::Receiver stopped seeing Rx interrupts\n",__FUNCTION__); //Receiver gone in to stopped state +#if 1 + if(gmacdev->GMAC_Power_down == 0) { // If Mac is not in powerdown + gmacdev->synopGMACNetStats.rx_over_errors++; + synopGMAC_enable_dma_rx(gmacdev); + } +#endif + } + + if(interrupt & synopGMACDmaTxNormal) { + //printf("tx\n"); + //xmit function has done its job + TR("%s::Finished Normal Transmission \n",__FUNCTION__); + synop_handle_transmit_over(0);//Do whatever you want after the transmission is over + + + } + + if(interrupt & synopGMACDmaTxAbnormal) { + TR("%s::Abnormal Tx Interrupt Seen\n",__FUNCTION__); +#if 1 + if(gmacdev->GMAC_Power_down == 0) { // If Mac is not in powerdown + synop_handle_transmit_over(0); + } +#endif + } + + + + if(interrupt & synopGMACDmaTxStopped) { + TR("%s::Transmitter stopped sending the packets\n",__FUNCTION__); +#if 1 + if(gmacdev->GMAC_Power_down == 0) { // If Mac is not in powerdown + synopGMAC_disable_dma_tx(gmacdev); + synopGMAC_take_desc_ownership_tx(gmacdev); + + synopGMAC_enable_dma_tx(gmacdev); + TR("%s::Transmission Resumed\n",__FUNCTION__); + } +#endif + } + + /* Enable the interrupt before returning from ISR*/ + synopGMAC_enable_interrupt(gmacdev,DmaIntEnable); + return; +} + +void synopGMAC_set_speed(int intf) +{ + + synopGMACdevice *gmacdev = &GMACdev[intf]; + + switch (gmacdev->Speed) { + case SPEED1000: + synopGMACClearBits((u32 *)gmacdev->MacBase,GmacConfig,GmacMiiGmii); + break; + case SPEED100: + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacConfig,GmacMiiGmii); + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacConfig,GmacFESpeed100); + break; + case SPEED10: + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacConfig,GmacMiiGmii); + synopGMACClearBits((u32 *)gmacdev->MacBase,GmacConfig,GmacFESpeed100); + default: + break; + } + +} + +/** + * Function used when the interface is opened for use. + * We register synopGMAC_linux_open function to linux open(). Basically this + * function prepares the the device for operation . This function is called whenever ifconfig (in Linux) + * activates the device (for example "ifconfig eth0 up"). This function registers + * system resources needed + * - Attaches device to device specific structure + * - Programs the MDC clock for PHY configuration + * - Check and initialize the PHY interface + * - ISR registration + * - Setup and initialize Tx and Rx descriptors + * - Initialize MAC and DMA + * - Allocate Memory for RX descriptors (The should be DMAable) + * - Initialize one second timer to detect cable plug/unplug + * - Configure and Enable Interrupts + * - Enable Tx and Rx + * - start the Linux network queue interface + * @param[in] pointer to net_device structure. + * \return Returns 0 on success and error status upon failure. + * \callgraph + */ + +s32 synopGMAC_open(int intf) +{ + //s32 status = 0; + s32 retval = 0; + s32 i; + //s32 reserve_len=2; + u32 dma_addr; + struct sk_buff *skb; + synopGMACdevice * gmacdev = &GMACdev[intf]; + + /*Attach the device to MAC struct This will configure all the required base addresses + such as Mac base, configuration base, phy base address(out of 32 possible phys )*/ + if(intf == 0) + synopGMAC_attach(gmacdev, GMAC0MappedAddr + MACBASE, GMAC0MappedAddr + DMABASE, DEFAULT_PHY_BASE); + else + synopGMAC_attach(gmacdev, GMAC1MappedAddr + MACBASE, GMAC1MappedAddr + DMABASE, DEFAULT_PHY_BASE); + + synopGMAC_reset(gmacdev); // Reset to make RGMII/RMII setting take affect --ya + gmacdev->Intf = intf; + /*Lets read the version of ip in to device structure*/ + synopGMAC_read_version(gmacdev); + + /*Check for Phy initialization*/ + synopGMAC_set_mdc_clk_div(gmacdev,GmiiCsrClk5); + //synopGMAC_set_mdc_clk_div(gmacdev, (GmiiCsrClk2|BIT5)); + gmacdev->ClockDivMdc = synopGMAC_get_mdc_clk_div(gmacdev); + //status = synopGMAC_check_phy_init(gmacdev); + synopGMAC_check_phy_init(gmacdev); + + /*Set up the tx and rx descriptor queue/ring*/ + + synopGMAC_setup_tx_desc_queue(gmacdev,TRANSMIT_DESC_SIZE, RINGMODE); + synopGMAC_init_tx_desc_base(gmacdev); //Program the transmit descriptor base address in to DmaTxBase addr + + synopGMAC_setup_rx_desc_queue(gmacdev,RECEIVE_DESC_SIZE, RINGMODE); + synopGMAC_init_rx_desc_base(gmacdev); //Program the transmit descriptor base address in to DmaTxBase addr + + + synopGMAC_dma_bus_mode_init(gmacdev, DmaBurstLength32 | DmaDescriptorSkip0/*DmaDescriptorSkip2*/ | DmaDescriptor8Words ); //pbl32 incr with rxthreshold 128 and Desc is 8 Words + + synopGMAC_dma_control_init(gmacdev,DmaStoreAndForward |DmaTxSecondFrame|DmaRxThreshCtrl128); + + /*Initialize the mac interface*/ + + synopGMAC_mac_init(gmacdev); + synopGMAC_promisc_enable(gmacdev); + + synopGMAC_pause_control(gmacdev); // This enables the pause control in Full duplex mode of operation + +#if 0 + /*IPC Checksum offloading is enabled for this driver. Should only be used if Full Ip checksumm offload engine is configured in the hardware*/ + synopGMAC_enable_rx_chksum_offload(gmacdev); //Enable the offload engine in the receive path + synopGMAC_rx_tcpip_chksum_drop_enable(gmacdev); // This is default configuration, DMA drops the packets if error in encapsulated ethernet payload +#endif + + for(i = 0; i < RECEIVE_DESC_SIZE; i ++) { + skb = &rx_buf[intf][i]; + synopGMAC_set_rx_qptr(gmacdev, (u32)((u64)(skb->data) & 0xFFFFFFFF), sizeof(skb->data), (u32)((u64)skb & 0xFFFFFFFF)); + } + + synopGMAC_clear_interrupt(gmacdev); + + synopGMAC_enable_interrupt(gmacdev,DmaIntEnable); + synopGMAC_enable_dma_rx(gmacdev); + synopGMAC_enable_dma_tx(gmacdev); + + + synopGMAC_set_mac_address(intf, intf == 0 ? mac_addr0 : mac_addr1); + + + return 0; + +} + +/** + * Function used when the interface is closed. + * + * This function is registered to linux stop() function. This function is + * called whenever ifconfig (in Linux) closes the device (for example "ifconfig eth0 down"). + * This releases all the system resources allocated during open call. + * system resources int needs + * - Disable the device interrupts + * - Stop the receiver and get back all the rx descriptors from the DMA + * - Stop the transmitter and get back all the tx descriptors from the DMA + * - Stop the Linux network queue interface + * - Free the irq (ISR registered is removed from the kernel) + * - Release the TX and RX descripor memory + * - De-initialize one second timer rgistered for cable plug/unplug tracking + * @param[in] pointer to net_device structure. + * \return Returns 0 on success and error status upon failure. + * \callgraph + */ + +s32 synopGMAC_close(int intf) +{ + + synopGMACdevice * gmacdev = &GMACdev[intf];; + + //TR0("%s\n",__FUNCTION__); + + /*Disable all the interrupts*/ + synopGMAC_disable_interrupt_all(gmacdev); + + + TR("the synopGMAC interrupt has been disabled\n"); + + /*Disable the reception*/ + synopGMAC_disable_dma_rx(gmacdev); + synopGMAC_take_desc_ownership_rx(gmacdev); + TR("the synopGMAC Reception has been disabled\n"); + + /*Disable the transmission*/ + synopGMAC_disable_dma_tx(gmacdev); + synopGMAC_take_desc_ownership_tx(gmacdev); + + TR("the synopGMAC interrupt handler has been removed\n"); + + /*Free the Rx Descriptor contents*/ + TR("Now calling synopGMAC_giveup_rx_desc_queue \n"); + synopGMAC_giveup_rx_desc_queue(gmacdev, RINGMODE); + + TR("Now calling synopGMAC_giveup_tx_desc_queue \n"); + synopGMAC_giveup_tx_desc_queue(gmacdev, RINGMODE); + + return 0; + +} + + +/** + * Function to transmit a given packet on the wire. + * Whenever Linux Kernel has a packet ready to be transmitted, this function is called. + * The function prepares a packet and prepares the descriptor and + * enables/resumes the transmission. + * @param[in] pointer to sk_buff structure. + * @param[in] pointer to net_device structure. + * \return Returns 0 on success and Error code on failure. + * \note structure sk_buff is used to hold packet in Linux networking stacks. + */ +s32 synopGMAC_xmit_frames(struct sk_buff *skb, int intf, u32 offload_needed, u32 ts) +{ + s32 status = 0; + + u32 dma_addr = (u32)((u64)skb->data & 0xFFFFFFFF); + + synopGMACdevice * gmacdev; + + + gmacdev = &GMACdev[intf]; + + /*Now we have skb ready and OS invoked this function. Lets make our DMA know about this*/ + status = synopGMAC_set_tx_qptr(gmacdev, dma_addr, skb->len, (u32)((u64)skb & 0xFFFFFFFF), offload_needed, ts); + if(status < 0) { + TR0("%s No More Free Tx Descriptors\n",__FUNCTION__); + return -1; + } + + /*Now force the DMA to start transmission*/ + synopGMAC_resume_dma_tx(gmacdev); + + + return 0; +} + + +/** + * Function to set ethernet address of the NIC. + * @param[in] pointer to net_device structure. + * @param[in] pointer to an address structure. + * \return Returns 0 on success Errorcode on failure. + */ +s32 synopGMAC_set_mac_address(int intf, u8* macaddr) +{ + + + synopGMACdevice * gmacdev = NULL; + + gmacdev = &GMACdev[intf]; + + + synopGMAC_set_mac_addr(gmacdev, GmacAddr0High, GmacAddr0Low, macaddr); + + return 0; +} + +// mode 0: 1000Mbps, 1: 100Mbps, 2: 10Mbps + +void synopGMAC_set_mode(int intf, int mode) +{ + + synopGMACdevice *gmacdev = &GMACdev[intf]; + + // Must stop Tx/Rx before change speed/mode + synopGMAC_tx_disable(gmacdev); + synopGMAC_rx_disable(gmacdev); + switch (mode) { + case 0: + synopGMACClearBits((u32 *)gmacdev->MacBase,GmacConfig,GmacMiiGmii); + gmacdev->Speed = SPEED1000; + break; + case 1: + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacConfig,GmacMiiGmii); + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacConfig,GmacFESpeed100); + gmacdev->Speed = SPEED100; + break; + case 2: + synopGMACSetBits((u32 *)gmacdev->MacBase,GmacConfig,GmacMiiGmii); + synopGMACClearBits((u32 *)gmacdev->MacBase,GmacConfig,GmacFESpeed100); + gmacdev->Speed = SPEED10; + default: + break; + } + synopGMAC_tx_enable(gmacdev); + synopGMAC_rx_enable(gmacdev); +} + diff --git a/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/synopGMAC_network_interface.h b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/synopGMAC_network_interface.h new file mode 100644 index 0000000000..0c95eee55f --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/synopGMAC_network_interface.h @@ -0,0 +1,63 @@ +/* =================================================================================== + * Copyright (c) <2009> Synopsys, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software annotated with this license and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without + * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * =================================================================================== */ + +/** \file + * Header file for the nework dependent functionality. + * The function prototype listed here are linux dependent. + * + * \internal + * ---------------------------REVISION HISTORY------------------- + * Synopsys 01/Aug/2007 Created + */ +#include "synopGMAC_Dev.h" + + +#ifndef SYNOP_GMAC_NETWORK_INTERFACE_H +#define SYNOP_GMAC_NETWORK_INTERFACE_H 1 + +//#define EMULATION + +//#define TEST_RGMII +#define TEST_RMII + +//#define CACHE_ON + + +s32 synopGMAC_open(int intf); +s32 synopGMAC_open_selftest(int intf); +s32 synopGMAC_close(int intf); +s32 synopGMAC_xmit_frames(struct sk_buff *, int intf, u32 offload_needed, u32 ts); +void synopGMAC_set_multicast_list(int intf); +s32 synopGMAC_set_mac_address(int intf, u8*); +s32 synopGMAC_change_mtu(int intf,s32); +void synop_handle_transmit_over(int intf); +//void synop_handle_received_data(int intf); +s32 synop_handle_received_data(int intf, u8 **buf); // Chris, to get RX buffer pointer +void synopGMAC_set_mode(int intf, int mode); + +void synopGMAC_powerup_mac(synopGMACdevice *gmacdev); +void synopGMAC_powerdown_mac(synopGMACdevice *gmacdev); +s32 synopGMAC_setup_tx_desc_queue(synopGMACdevice * gmacdev,u32 no_of_desc, u32 desc_mode); +s32 synopGMAC_setup_rx_desc_queue(synopGMACdevice * gmacdev,u32 no_of_desc, u32 desc_mode); + + +#endif /* End of file */ diff --git a/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/synopGMAC_plat.h b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/synopGMAC_plat.h new file mode 100644 index 0000000000..b3daf4a1ec --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M460/synopGMAC_plat.h @@ -0,0 +1,183 @@ +/* =================================================================================== + * Copyright (c) <2009> Synopsys, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software annotated with this license and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without + * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * =================================================================================== */ + +/**\file + * This file serves as the wrapper for the platform/OS dependent functions + * It is needed to modify these functions accordingly based on the platform and the + * OS. Whenever the synopsys GMAC driver ported on to different platform, this file + * should be handled at most care. + * The corresponding function definitions for non-inline functions are available in + * synopGMAC_plat.c file. + * \internal + * -------------------------------------REVISION HISTORY--------------------------- + * Synopsys 01/Aug/2007 Created + */ + + +#ifndef SYNOP_GMAC_PLAT_H +#define SYNOP_GMAC_PLAT_H 1 + +#include +#include "NuMicro.h" + +#define TR0(fmt, args...) printf("SynopGMAC: " fmt, ##args) + +//#define DEBUG +#ifdef DEBUG +#undef TR +# define TR(fmt, args...) printf("SynopGMAC: " fmt, ##args) +#else +# define TR(fmt, args...) /* not debugging: nothing */ +#endif + +typedef unsigned char u8; ///< Define 8-bit unsigned data type +typedef unsigned short u16; ///< Define 16-bit unsigned data type +typedef unsigned int u32; ///< Define 32-bit unsigned data type +typedef signed int s32; ///< Define 32-bit signed data type +//typedef unsigned long long u64; +typedef unsigned int u64; + + +typedef int bool; +enum synopGMAC_boolean { + false = 0, + true = 1 +}; + +#define DEFAULT_DELAY_VARIABLE 10 +#define DEFAULT_LOOP_VARIABLE 10000 + +/* There are platform related endian conversions + * + */ + +#define LE32_TO_CPU __le32_to_cpu +#define BE32_TO_CPU __be32_to_cpu +#define CPU_TO_LE32 __cpu_to_le32 + +/* Error Codes */ +#define ESYNOPGMACNOERR 0 +#define ESYNOPGMACNOMEM 1 +#define ESYNOPGMACPHYERR 2 +#define ESYNOPGMACBUSY 3 + + +/** + * These are the wrapper function prototypes for OS/platform related routines + */ + +extern void plat_delay(uint32_t ticks); + + +/** + * The Low level function to read register contents from Hardware. + * + * @param[in] pointer to the base of register map + * @param[in] Offset from the base + * \return Returns the register contents + */ +static u32 __INLINE synopGMACReadReg(u32 *RegBase, u32 RegOffset) +{ + + u64 addr = (u64)RegBase + RegOffset; + u32 data = inp32((void *)addr); + return data; + +} + +/** + * The Low level function to write to a register in Hardware. + * + * @param[in] pointer to the base of register map + * @param[in] Offset from the base + * @param[in] Data to be written + * \return void + */ +static void __INLINE synopGMACWriteReg(u32 *RegBase, u32 RegOffset, u32 RegData) +{ + + u64 addr = (u64)RegBase + RegOffset; + if(RegOffset == 0) + plat_delay(1); + outp32((void *)addr, RegData); + return; +} + +/** + * The Low level function to set bits of a register in Hardware. + * + * @param[in] pointer to the base of register map + * @param[in] Offset from the base + * @param[in] Bit mask to set bits to logical 1 + * \return void + */ +static void __INLINE synopGMACSetBits(u32 *RegBase, u32 RegOffset, u32 BitPos) +{ + u64 addr = (u64)RegBase + RegOffset; + u32 data = inp32((void *)addr); + data |= BitPos; + + outp32((void *)addr, data); + + return; +} + + +/** + * The Low level function to clear bits of a register in Hardware. + * + * @param[in] pointer to the base of register map + * @param[in] Offset from the base + * @param[in] Bit mask to clear bits to logical 0 + * \return void + */ +static void __INLINE synopGMACClearBits(u32 *RegBase, u32 RegOffset, u32 BitPos) +{ + u64 addr = (u64)RegBase + RegOffset; + u32 data = inp32((void *)addr); + data &= (~BitPos); + + outp32((void *)addr, data); + return; +} + +/** + * The Low level function to Check the setting of the bits. + * + * @param[in] pointer to the base of register map + * @param[in] Offset from the base + * @param[in] Bit mask to set bits to logical 1 + * \return returns TRUE if set to '1' returns FALSE if set to '0'. Result undefined there are no bit set in the BitPos argument. + * + */ +static bool __INLINE synopGMACCheckBits(u32 *RegBase, u32 RegOffset, u32 BitPos) +{ + u64 addr = (u64)RegBase + RegOffset; + u32 data = inp32((void *)addr); + data &= BitPos; + if(data) return true; + else return false; + +} + + +#endif