mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			Add M460 EMAC driver
							parent
							
								
									501aa00fa0
								
							
						
					
					
						commit
						877541d79d
					
				| 
						 | 
				
			
			@ -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
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -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 <stdbool.h>
 | 
			
		||||
#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 <<DescSize1Shift) & DescSize1Mask);
 | 
			
		||||
    txdesc->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);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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_ */
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -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 <Chk Status = 4>  \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 <Chk Status = 6>  \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 <Chk Status = 0> \n");
 | 
			
		||||
                    }
 | 
			
		||||
                    if(synopGMAC_is_rx_checksum_error(gmacdev, status) == RxIpHdrPayLoadChkBypass ) {
 | 
			
		||||
                        TR("Ip header and TCP/UDP payload checksum Bypassed <Chk Status = 1>\n");
 | 
			
		||||
                    }
 | 
			
		||||
                    if(synopGMAC_is_rx_checksum_error(gmacdev, status) == RxChkBypass ) {
 | 
			
		||||
                        TR("Ip header and TCP/UDP payload checksum Bypassed <Chk Status = 3>  \n");
 | 
			
		||||
                    }
 | 
			
		||||
                    if(synopGMAC_is_rx_checksum_error(gmacdev, status) == RxPayLoadChkError ) {
 | 
			
		||||
                        TR(" TCP/UDP payload checksum Error <Chk Status = 5>  \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 <Chk Status = 7>  \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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -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 */
 | 
			
		||||
| 
						 | 
				
			
			@ -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 <stdio.h>
 | 
			
		||||
#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
 | 
			
		||||
		Loading…
	
		Reference in New Issue