Merge pull request #827 from caogos/master

[BSP] Add EMAC driver in loongson1C (ported by chinesebear, https://github.com/chinesebear/rtt-net)
This commit is contained in:
Bernard Xiong 2017-08-25 11:07:34 +08:00 committed by GitHub
commit b9ebd183ae
17 changed files with 7613 additions and 9 deletions

View File

@ -16,11 +16,16 @@
#include <rtthread.h>
#include <components.h>
#include "net/synopGMAC.h"
#include <lwip/api.h>
void rt_init_thread_entry(void *parameter)
{
/* initialization RT-Thread Components */
rt_components_init();
// 网口EMAC初始化
rt_hw_eth_init();
}
int rt_application_init(void)

View File

@ -7,4 +7,14 @@ CPPPATH = [cwd]
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
objs = []
list = os.listdir(cwd)
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
objs = objs + SConscript(os.path.join(d, 'SConscript'))
group = group + objs
Return('group')

View File

@ -0,0 +1,11 @@
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

View File

@ -0,0 +1,150 @@
/*
* File : mii.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) chinesebear
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2017-08-24 chinesebear first version
*/
#include "mii.h"
static inline unsigned int mii_nway_result (unsigned int negotiated)
{
unsigned int ret;
if (negotiated & LPA_100FULL)
ret = LPA_100FULL;
else if (negotiated & LPA_100BASE4)
ret = LPA_100BASE4;
else if (negotiated & LPA_100HALF)
ret = LPA_100HALF;
else if (negotiated & LPA_10FULL)
ret = LPA_10FULL;
else
ret = LPA_10HALF;
return ret;
}
static int mii_check_gmii_support(struct mii_if_info *mii)
{
int reg;
reg = mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
if (reg & BMSR_ESTATEN) {
reg = mii->mdio_read(mii->dev, mii->phy_id, MII_ESTATUS);
if (reg & (ESTATUS_1000_TFULL | ESTATUS_1000_THALF))
return 1;
}
return 0;
}
static int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
{
struct synopGMACNetworkAdapter * dev = mii->dev;
u32 advert, bmcr, lpa, nego;
u32 advert2 = 0, bmcr2 = 0, lpa2 = 0;
ecmd->supported =
(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII);
if (mii->supports_gmii)
ecmd->supported |= SUPPORTED_1000baseT_Half |
SUPPORTED_1000baseT_Full;
/* only supports twisted-pair */
ecmd->port = PORT_MII;
/* only supports internal transceiver */
ecmd->transceiver = XCVR_INTERNAL;
/* this isn't fully supported at higher layers */
ecmd->phy_address = mii->phy_id;
ecmd->advertising = ADVERTISED_TP | ADVERTISED_MII;
advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE);
if (mii->supports_gmii)
advert2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000);
if (advert & ADVERTISE_10HALF)
ecmd->advertising |= ADVERTISED_10baseT_Half;
if (advert & ADVERTISE_10FULL)
ecmd->advertising |= ADVERTISED_10baseT_Full;
if (advert & ADVERTISE_100HALF)
ecmd->advertising |= ADVERTISED_100baseT_Half;
if (advert & ADVERTISE_100FULL)
ecmd->advertising |= ADVERTISED_100baseT_Full;
if (advert2 & ADVERTISE_1000HALF)
ecmd->advertising |= ADVERTISED_1000baseT_Half;
if (advert2 & ADVERTISE_1000FULL)
ecmd->advertising |= ADVERTISED_1000baseT_Full;
bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
lpa = mii->mdio_read(dev, mii->phy_id, MII_LPA);
if (mii->supports_gmii) {
bmcr2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000);
lpa2 = mii->mdio_read(dev, mii->phy_id, MII_STAT1000);
}
if (bmcr & BMCR_ANENABLE) {
ecmd->advertising |= ADVERTISED_Autoneg;
ecmd->autoneg = AUTONEG_ENABLE;
nego = mii_nway_result(advert & lpa);
if ((bmcr2 & (ADVERTISE_1000HALF | ADVERTISE_1000FULL)) &
(lpa2 >> 2))
ecmd->speed = SPEED_1000;
else if (nego == LPA_100FULL || nego == LPA_100HALF)
ecmd->speed = SPEED_100;
else
ecmd->speed = SPEED_10;
if ((lpa2 & LPA_1000FULL) || nego == LPA_100FULL ||
nego == LPA_10FULL) {
ecmd->duplex = DUPLEX_FULL;
mii->full_duplex = 1;
} else {
ecmd->duplex = DUPLEX_HALF;
mii->full_duplex = 0;
}
} else {
ecmd->autoneg = AUTONEG_DISABLE;
ecmd->speed = ((bmcr & BMCR_SPEED1000 &&
(bmcr & BMCR_SPEED100) == 0) ? SPEED_1000 :
(bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10);
ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
}
/* ignore maxtxpkt, maxrxpkt for now */
return 0;
}
static int mii_link_ok (struct mii_if_info *mii)
{
/* first, a dummy read, needed to latch some MII phys */
mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
if (mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR) & BMSR_LSTATUS)
return 1;
return 0;
}

View File

@ -0,0 +1,245 @@
/*
* File : mii.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) chinesebear
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2017-08-24 chinesebear first version
*/
#ifndef __MII_H__
#define __MII_H__
/* Generic MII registers. */
#include "synopGMAC_types.h"
#define MII_BMCR 0x00 /* Basic mode control register */
#define MII_BMSR 0x01 /* Basic mode status register */
#define MII_PHYSID1 0x02 /* PHYS ID 1 */
#define MII_PHYSID2 0x03 /* PHYS ID 2 */
#define MII_ADVERTISE 0x04 /* Advertisement control reg */
#define MII_LPA 0x05 /* Link partner ability reg */
#define MII_EXPANSION 0x06 /* Expansion register */
#define MII_CTRL1000 0x09 /* 1000BASE-T control */
#define MII_STAT1000 0x0a /* 1000BASE-T status */
#define MII_ESTATUS 0x0f /* Extended Status */
#define MII_DCOUNTER 0x12 /* Disconnect counter */
#define MII_FCSCOUNTER 0x13 /* False carrier counter */
#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */
#define MII_RERRCOUNTER 0x15 /* Receive error counter */
#define MII_SREVISION 0x16 /* Silicon revision */
#define MII_RESV1 0x17 /* Reserved... */
#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */
#define MII_PHYADDR 0x19 /* PHY address */
#define MII_RESV2 0x1a /* Reserved... */
#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */
#define MII_NCONFIG 0x1c /* Network interface config */
/* Basic mode control register. */
#define BMCR_RESV 0x003f /* Unused... */
#define BMCR_SPEED1000 0x0040 /* MSB of Speed (1000) */
#define BMCR_CTST 0x0080 /* Collision test */
#define BMCR_FULLDPLX 0x0100 /* Full duplex */
#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */
#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */
#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */
#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */
#define BMCR_SPEED100 0x2000 /* Select 100Mbps */
#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */
#define BMCR_RESET 0x8000 /* Reset the DP83840 */
/* Basic mode status register. */
#define BMSR_ERCAP 0x0001 /* Ext-reg capability */
#define BMSR_JCD 0x0002 /* Jabber detected */
#define BMSR_LSTATUS 0x0004 /* Link status */
#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */
#define BMSR_RFAULT 0x0010 /* Remote fault detected */
#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */
#define BMSR_RESV 0x00c0 /* Unused... */
#define BMSR_ESTATEN 0x0100 /* Extended Status in R15 */
#define BMSR_100FULL2 0x0200 /* Can do 100BASE-T2 HDX */
#define BMSR_100HALF2 0x0400 /* Can do 100BASE-T2 FDX */
#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */
#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */
#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */
#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */
#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */
/* Advertisement control register. */
#define ADVERTISE_SLCT 0x001f /* Selector bits */
#define ADVERTISE_CSMA 0x0001 /* Only selector supported */
#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
#define ADVERTISE_1000XFULL 0x0020 /* Try for 1000BASE-X full-duplex */
#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
#define ADVERTISE_1000XHALF 0x0040 /* Try for 1000BASE-X half-duplex */
#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
#define ADVERTISE_1000XPAUSE 0x0080 /* Try for 1000BASE-X pause */
#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
#define ADVERTISE_1000XPSE_ASYM 0x0100 /* Try for 1000BASE-X asym pause */
#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */
#define ADVERTISE_PAUSE_CAP 0x0400 /* Try for pause */
#define ADVERTISE_PAUSE_ASYM 0x0800 /* Try for asymetric pause */
#define ADVERTISE_RESV 0x1000 /* Unused... */
#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */
#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */
#define ADVERTISE_NPAGE 0x8000 /* Next page bit */
#define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \
ADVERTISE_CSMA)
#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \
ADVERTISE_100HALF | ADVERTISE_100FULL)
/* Indicates what features are advertised by the interface. */
#define ADVERTISED_10baseT_Half (1 << 0)
#define ADVERTISED_10baseT_Full (1 << 1)
#define ADVERTISED_100baseT_Half (1 << 2)
#define ADVERTISED_100baseT_Full (1 << 3)
#define ADVERTISED_1000baseT_Half (1 << 4)
#define ADVERTISED_1000baseT_Full (1 << 5)
#define ADVERTISED_Autoneg (1 << 6)
#define ADVERTISED_TP (1 << 7)
#define ADVERTISED_AUI (1 << 8)
#define ADVERTISED_MII (1 << 9)
#define ADVERTISED_FIBRE (1 << 10)
#define ADVERTISED_BNC (1 << 11)
#define ADVERTISED_10000baseT_Full (1 << 12)
#define ADVERTISED_Pause (1 << 13)
#define ADVERTISED_Asym_Pause (1 << 14)
/* Link partner ability register. */
#define LPA_SLCT 0x001f /* Same as advertise selector */
#define LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */
#define LPA_1000XFULL 0x0020 /* Can do 1000BASE-X full-duplex */
#define LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */
#define LPA_1000XHALF 0x0040 /* Can do 1000BASE-X half-duplex */
#define LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */
#define LPA_1000XPAUSE 0x0080 /* Can do 1000BASE-X pause */
#define LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */
#define LPA_1000XPAUSE_ASYM 0x0100 /* Can do 1000BASE-X pause asym*/
#define LPA_100BASE4 0x0200 /* Can do 100mbps 4k packets */
#define LPA_PAUSE_CAP 0x0400 /* Can pause */
#define LPA_PAUSE_ASYM 0x0800 /* Can pause asymetrically */
#define LPA_RESV 0x1000 /* Unused... */
#define LPA_RFAULT 0x2000 /* Link partner faulted */
#define LPA_LPACK 0x4000 /* Link partner acked us */
#define LPA_NPAGE 0x8000 /* Next page bit */
#define LPA_DUPLEX (LPA_10FULL | LPA_100FULL)
#define LPA_100 (LPA_100FULL | LPA_100HALF | LPA_100BASE4)
/* Expansion register for auto-negotiation. */
#define EXPANSION_NWAY 0x0001 /* Can do N-way auto-nego */
#define EXPANSION_LCWP 0x0002 /* Got new RX page code word */
#define EXPANSION_ENABLENPAGE 0x0004 /* This enables npage words */
#define EXPANSION_NPCAPABLE 0x0008 /* Link partner supports npage */
#define EXPANSION_MFAULTS 0x0010 /* Multiple faults detected */
#define EXPANSION_RESV 0xffe0 /* Unused... */
#define ESTATUS_1000_TFULL 0x2000 /* Can do 1000BT Full */
#define ESTATUS_1000_THALF 0x1000 /* Can do 1000BT Half */
/* N-way test register. */
#define NWAYTEST_RESV1 0x00ff /* Unused... */
#define NWAYTEST_LOOPBACK 0x0100 /* Enable loopback for N-way */
#define NWAYTEST_RESV2 0xfe00 /* Unused... */
/* 1000BASE-T Control register */
#define ADVERTISE_1000FULL 0x0200 /* Advertise 1000BASE-T full duplex */
#define ADVERTISE_1000HALF 0x0100 /* Advertise 1000BASE-T half duplex */
/* 1000BASE-T Status register */
#define LPA_1000LOCALRXOK 0x2000 /* Link partner local receiver status */
#define LPA_1000REMRXOK 0x1000 /* Link partner remote receiver status */
#define LPA_1000FULL 0x0800 /* Link partner 1000BASE-T full duplex */
#define SUPPORTED_10baseT_Half (1 << 0)
#define SUPPORTED_10baseT_Full (1 << 1)
#define SUPPORTED_100baseT_Half (1 << 2)
#define SUPPORTED_100baseT_Full (1 << 3)
#define SUPPORTED_1000baseT_Half (1 << 4)
#define SUPPORTED_1000baseT_Full (1 << 5)
#define SUPPORTED_Autoneg (1 << 6)
#define SUPPORTED_TP (1 << 7)
#define SUPPORTED_AUI (1 << 8)
#define SUPPORTED_MII (1 << 9)
#define SUPPORTED_FIBRE (1 << 10)
#define SUPPORTED_BNC (1 << 11)
#define SUPPORTED_10000baseT_Full (1 << 12)
#define SUPPORTED_Pause (1 << 13)
#define SUPPORTED_Asym_Pause (1 << 14)
/* Which connector port. */
#define PORT_TP 0x00
#define PORT_AUI 0x01
#define PORT_MII 0x02
#define PORT_FIBRE 0x03
#define PORT_BNC 0x04
/* Which transceiver to use. */
#define XCVR_INTERNAL 0x00
#define XCVR_EXTERNAL 0x01
#define XCVR_DUMMY1 0x02
#define XCVR_DUMMY2 0x03
#define XCVR_DUMMY3 0x04
#define AUTONEG_DISABLE 0x00
#define AUTONEG_ENABLE 0x01
#define SPEED_10 10
#define SPEED_100 100
#define SPEED_1000 1000
#define SPEED_2500 2500
#define SPEED_10000 10000
#define DUPLEX_HALF 0x00
#define DUPLEX_FULL 0x01
struct ethtool_cmd {
u32 cmd;
u32 supported; /* Features this interface supports */
u32 advertising; /* Features this interface advertises */
u16 speed; /* The forced speed, 10Mb, 100Mb, gigabit */
u8 duplex; /* Duplex, half or full */
u8 port; /* Which connector port */
u8 phy_address;
u8 transceiver; /* Which transceiver to use */
u8 autoneg; /* Enable or disable autonegotiation */
u32 maxtxpkt; /* Tx pkts before generating tx int */
u32 maxrxpkt; /* Rx pkts before generating rx int */
u32 reserved[4];
};
struct mii_if_info {
int phy_id;
int advertising;
int phy_id_mask;
int reg_num_mask;
unsigned int full_duplex : 1; /* is full duplex? */
unsigned int force_media : 1; /* is autoneg. disabled? */
unsigned int supports_gmii : 1; /* are GMII registers supported? */
struct synopGMACNetworkAdapter *dev;
int (*mdio_read) (struct synopGMACNetworkAdapter *dev, int phy_id, int location);
void (*mdio_write) (struct synopGMACNetworkAdapter *dev, int phy_id, int location, int val);
};
#endif

View File

@ -0,0 +1,929 @@
/*
* File : synopGMAC.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) chinesebear
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2017-08-24 chinesebear first version
*/
#include <rtthread.h>
#include <components.h>
#include <rtdef.h>
//#include <lwip/pbuf.h>
#include "synopGMAC.h"
#include "mii.c"
#include "synopGMAC_debug.h"
#include <ls1c.h>
#define RMII
#define Gmac_base 0xbfe10000
#define Buffer_Size 2048
#define MAX_ADDR_LEN 6
#define NAMESIZE 16
#define LS1B_GMAC0_IRQ 34
#define BUS_SIZE_ALIGN(x) ((x+15)&~15)
#define DEFAULT_MAC_ADDRESS {0x00, 0x55, 0x7B, 0xB5, 0x7D, 0xF7}
u32 regbase = 0xbfe10000;
static u32 GMAC_Power_down;
extern void *plat_alloc_consistent_dmaable_memory(synopGMACdevice *pcidev, u32 size, u32 *addr) ;
extern s32 synopGMAC_check_phy_init (synopGMACPciNetworkAdapter *adapter) ;
extern int init_phy(synopGMACdevice *gmacdev);
dma_addr_t plat_dma_map_single(void *hwdev, void *ptr,u32 size);
void eth_rx_irq(int irqno,void *param);
static char Rx_Buffer[Buffer_Size];
static char Tx_Buffer[Buffer_Size];
struct rt_eth_dev
{
struct eth_device parent;
rt_uint8_t dev_addr[MAX_ADDR_LEN];
char *name;
int iobase;
int state;
int index;
struct rt_timer link_timer;
struct rt_timer rx_poll_timer;
void *priv;
};
static struct rt_eth_dev eth_dev;
static struct rt_semaphore sem_ack, sem_lock;
/**
* This sets up the transmit Descriptor queue in ring or chain mode.
* This function is tightly coupled to the platform and operating system
* Device is interested only after the descriptors are setup. Therefore this function
* is not included in the device driver API. This function should be treated as an
* example code to design the descriptor structures for ring mode or chain mode.
* This function depends on the pcidev structure for allocation consistent dma-able memory in case
* of linux.
* This limitation is due to the fact that linux uses pci structure to allocate a dmable memory
* - Allocates the memory for the descriptors.
* - Initialize the Busy and Next descriptors indices to 0(Indicating first descriptor).
* - Initialize the Busy and Next descriptors to first descriptor address.
* - Initialize the last descriptor with the endof ring in case of ring mode.
* - Initialize the descriptors in chain mode.
* @param[in] pointer to synopGMACdevice.
* @param[in] pointer to pci_device structure.
* @param[in] number of descriptor expected in tx descriptor queue.
* @param[in] whether descriptors to be created in RING mode or CHAIN mode.
* \return 0 upon success. Error code upon failure.
* \note This function fails if allocation fails for required number of descriptors in Ring mode,
* but in chain mode
* function returns -ESYNOPGMACNOMEM in the process of descriptor chain creation. once returned from
* this function
* user should for gmacdev->TxDescCount to see how many descriptors are there in the chain. Should
* continue further
* only if the number of descriptors in the chain meets the requirements
*/
s32 synopGMAC_setup_tx_desc_queue(synopGMACdevice * gmacdev,u32 no_of_desc, u32 desc_mode)
{
s32 i;
DmaDesc * bf1;
DmaDesc *first_desc = NULL;
dma_addr_t dma_addr;
gmacdev->TxDescCount = 0;
first_desc = (DmaDesc *)plat_alloc_consistent_dmaable_memory (gmacdev, sizeof(DmaDesc) * no_of_desc,&dma_addr);
if(first_desc == NULL){
rt_kprintf("Error in Tx Descriptors memory allocation\n");
return -ESYNOPGMACNOMEM;
}
DEBUG_MES("tx_first_desc_addr = %p\n", first_desc);
DEBUG_MES("dmaadr = %p\n", dma_addr);
gmacdev->TxDescCount = no_of_desc;
gmacdev->TxDesc = first_desc;
gmacdev->TxDescDma = dma_addr;
for(i =0; i < gmacdev->TxDescCount; i++){
synopGMAC_tx_desc_init_ring(gmacdev->TxDesc + i, i == gmacdev->TxDescCount-1);
#if SYNOP_TOP_DEBUG
rt_kprintf("\n%02d %08x \n",i,(unsigned int)(gmacdev->TxDesc + i));
rt_kprintf("%08x ",(unsigned int)((gmacdev->TxDesc + i))->status);
rt_kprintf("%08x ",(unsigned int)((gmacdev->TxDesc + i)->length));
rt_kprintf("%08x ",(unsigned int)((gmacdev->TxDesc + i)->buffer1));
rt_kprintf("%08x ",(unsigned int)((gmacdev->TxDesc + i)->buffer2));
rt_kprintf("%08x ",(unsigned int)((gmacdev->TxDesc + i)->data1));
rt_kprintf("%08x ",(unsigned int)((gmacdev->TxDesc + i)->data2));
rt_kprintf("%08x ",(unsigned int)((gmacdev->TxDesc + i)->dummy1));
rt_kprintf("%08x ",(unsigned int)((gmacdev->TxDesc + i)->dummy2));
#endif
}
gmacdev->TxNext = 0;
gmacdev->TxBusy = 0;
gmacdev->TxNextDesc = gmacdev->TxDesc;
gmacdev->TxBusyDesc = gmacdev->TxDesc;
gmacdev->BusyTxDesc = 0;
return -ESYNOPGMACNOERR;
}
/**
* This sets up the receive Descriptor queue in ring or chain mode.
* This function is tightly coupled to the platform and operating system
* Device is interested only after the descriptors are setup. Therefore this function
* is not included in the device driver API. This function should be treated as an
* example code to design the descriptor structures in ring mode or chain mode.
* This function depends on the pcidev structure for allocation of consistent dma-able memory in
* case of linux.
* This limitation is due to the fact that linux uses pci structure to allocate a dmable memory
* - Allocates the memory for the descriptors.
* - Initialize the Busy and Next descriptors indices to 0(Indicating first descriptor).
* - Initialize the Busy and Next descriptors to first descriptor address.
* - Initialize the last descriptor with the endof ring in case of ring mode.
* - Initialize the descriptors in chain mode.
* @param[in] pointer to synopGMACdevice.
* @param[in] pointer to pci_device structure.
* @param[in] number of descriptor expected in rx descriptor queue.
* @param[in] whether descriptors to be created in RING mode or CHAIN mode.
* \return 0 upon success. Error code upon failure.
* \note This function fails if allocation fails for required number of descriptors in Ring mode,
* but in chain mode
* function returns -ESYNOPGMACNOMEM in the process of descriptor chain creation. once returned from
* this function
* user should for gmacdev->RxDescCount to see how many descriptors are there in the chain. Should
* continue further
* only if the number of descriptors in the chain meets the requirements
*/
s32 synopGMAC_setup_rx_desc_queue(synopGMACdevice * gmacdev,u32 no_of_desc, u32 desc_mode)
{
s32 i;
DmaDesc * bf1;
DmaDesc *first_desc = NULL;
dma_addr_t dma_addr;
gmacdev->RxDescCount = 0;
first_desc =(DmaDesc *)plat_alloc_consistent_dmaable_memory (gmacdev, sizeof(DmaDesc) * no_of_desc, &dma_addr);
if(first_desc == NULL){
rt_kprintf("Error in Rx Descriptor Memory allocation in Ring mode\n");
return -ESYNOPGMACNOMEM;
}
DEBUG_MES("rx_first_desc_addr = %p\n", first_desc);
DEBUG_MES("dmaadr = %p\n", dma_addr);
gmacdev->RxDescCount = no_of_desc;
gmacdev->RxDesc = (DmaDesc *)first_desc;
gmacdev->RxDescDma = dma_addr;
for(i =0; i < gmacdev->RxDescCount; i++){
synopGMAC_rx_desc_init_ring(gmacdev->RxDesc + i, i == gmacdev->RxDescCount-1);
}
gmacdev->RxNext = 0;
gmacdev->RxBusy = 0;
gmacdev->RxNextDesc = gmacdev->RxDesc;
gmacdev->RxBusyDesc = gmacdev->RxDesc;
gmacdev->BusyRxDesc = 0;
return -ESYNOPGMACNOERR;
}
void synopGMAC_linux_cable_unplug_function(void *adaptr)
{
s32 data;
synopGMACPciNetworkAdapter *adapter = (synopGMACPciNetworkAdapter *)adaptr;
synopGMACdevice *gmacdev = adapter->synopGMACdev;
struct ethtool_cmd cmd;
//rt_kprintf("%s\n",__FUNCTION__);
if(!mii_link_ok(&adapter->mii)){
if(gmacdev->LinkState)
rt_kprintf("\r\nNo Link\r\n");
gmacdev->DuplexMode = 0;
gmacdev->Speed = 0;
gmacdev->LoopBackMode = 0;
gmacdev->LinkState = 0;
}
else{
data = synopGMAC_check_phy_init(adapter);
if(gmacdev->LinkState != data){
gmacdev->LinkState = data;
synopGMAC_mac_init(gmacdev);
rt_kprintf("Link is up in %s mode\n",(gmacdev->DuplexMode == FULLDUPLEX) ? "FULL DUPLEX": "HALF DUPLEX");
if(gmacdev->Speed == SPEED1000)
rt_kprintf("Link is with 1000M Speed \r\n");
if(gmacdev->Speed == SPEED100)
rt_kprintf("Link is with 100M Speed \n");
if(gmacdev->Speed == SPEED10)
rt_kprintf("Link is with 10M Speed \n");
}
}
}
s32 synopGMAC_check_phy_init (synopGMACPciNetworkAdapter *adapter)
{
struct ethtool_cmd cmd;
synopGMACdevice *gmacdev = adapter->synopGMACdev;
if(!mii_link_ok(&adapter->mii))
{
gmacdev->DuplexMode = FULLDUPLEX;
gmacdev->Speed = SPEED100;
return 0;
}
else
{
mii_ethtool_gset(&adapter->mii, &cmd);
gmacdev->DuplexMode = (cmd.duplex == DUPLEX_FULL) ? FULLDUPLEX: HALFDUPLEX ;
if(cmd.speed == SPEED_1000)
gmacdev->Speed = SPEED1000;
else if(cmd.speed == SPEED_100)
gmacdev->Speed = SPEED100;
else
gmacdev->Speed = SPEED10;
}
return gmacdev->Speed|(gmacdev->DuplexMode<<4);
}
static int Mac_change_check(u8 *macaddr0, u8 *macaddr1)
{
int i;
for(i = 0; i < 6; i++){
if(macaddr0[i] != macaddr1[i])
return 1;
}
return 0;
}
static rt_err_t eth_init(rt_device_t device )
{
struct eth_device *eth_device = (struct eth_device *)device;
RT_ASSERT(eth_device != RT_NULL);
s32 ijk;
s32 status = 0;
u64 dma_addr;
u32 Mac_changed = 0;
struct pbuf *pbuf;
u8 macaddr[6] = DEFAULT_MAC_ADDRESS;
struct rt_eth_dev *dev = &eth_dev;
struct synopGMACNetworkAdapter *adapter = dev->priv;
synopGMACdevice * gmacdev = (synopGMACdevice *)adapter->synopGMACdev;
synopGMAC_reset(gmacdev);
synopGMAC_attach(gmacdev,(regbase + MACBASE),(regbase + DMABASE), DEFAULT_PHY_BASE, macaddr);
synopGMAC_read_version(gmacdev);
synopGMAC_set_mdc_clk_div(gmacdev,GmiiCsrClk3);
gmacdev->ClockDivMdc = synopGMAC_get_mdc_clk_div(gmacdev);
init_phy(adapter->synopGMACdev);
rt_kprintf("tx desc_queue\n");
synopGMAC_setup_tx_desc_queue(gmacdev,TRANSMIT_DESC_SIZE, RINGMODE);
synopGMAC_init_tx_desc_base(gmacdev);
rt_kprintf("rx desc_queue\n");
synopGMAC_setup_rx_desc_queue(gmacdev,RECEIVE_DESC_SIZE, RINGMODE);
synopGMAC_init_rx_desc_base(gmacdev);
DEBUG_MES("DmaRxBaseAddr = %08x\n",synopGMACReadReg(gmacdev->DmaBase,DmaRxBaseAddr));
// u32 dmaRx_Base_addr = synopGMACReadReg(gmacdev->DmaBase,DmaRxBaseAddr);
// rt_kprintf("first_desc_addr = 0x%x\n", dmaRx_Base_addr);
#ifdef ENH_DESC_8W
synopGMAC_dma_bus_mode_init(gmacdev, DmaBurstLength32 | DmaDescriptorSkip2 | DmaDescriptor8Words );
#else
//synopGMAC_dma_bus_mode_init(gmacdev, DmaBurstLength4 | DmaDescriptorSkip1);
synopGMAC_dma_bus_mode_init(gmacdev, DmaBurstLength4 | DmaDescriptorSkip2);
#endif
synopGMAC_dma_control_init(gmacdev,DmaStoreAndForward |DmaTxSecondFrame|DmaRxThreshCtrl128);
status = synopGMAC_check_phy_init(adapter);
synopGMAC_mac_init(gmacdev);
synopGMAC_pause_control(gmacdev);
#ifdef IPC_OFFLOAD
synopGMAC_enable_rx_chksum_offload(gmacdev);
synopGMAC_rx_tcpip_chksum_drop_enable(gmacdev);
#endif
u32 skb;
do{
skb = (u32)plat_alloc_memory(RX_BUF_SIZE); //should skb aligned here?
if(skb == RT_NULL){
rt_kprintf("ERROR in skb buffer allocation\n");
break;
}
dma_addr = plat_dma_map_single(gmacdev,(void *)skb,RX_BUF_SIZE); //获取 skb 的 dma 地址
status = synopGMAC_set_rx_qptr(gmacdev,dma_addr,RX_BUF_SIZE,(u32)skb,0,0,0);
if(status < 0)
{
rt_kprintf("status < 0!!\n");
plat_free_memory((void *)skb);
}
}while(status >= 0 && (status < (RECEIVE_DESC_SIZE - 1)));
synopGMAC_clear_interrupt(gmacdev);
synopGMAC_disable_mmc_tx_interrupt(gmacdev, 0xFFFFFFFF);
synopGMAC_disable_mmc_rx_interrupt(gmacdev, 0xFFFFFFFF);
synopGMAC_disable_mmc_ipc_rx_interrupt(gmacdev, 0xFFFFFFFF);
// synopGMAC_disable_interrupt_all(gmacdev);
synopGMAC_enable_interrupt(gmacdev, DmaIntEnable);
synopGMAC_enable_dma_rx(gmacdev);
synopGMAC_enable_dma_tx(gmacdev);
plat_delay(DEFAULT_LOOP_VARIABLE);
synopGMAC_check_phy_init(adapter);
synopGMAC_mac_init(gmacdev);
rt_timer_init(&dev->link_timer, "link_timer",
synopGMAC_linux_cable_unplug_function,
(void *)adapter,
RT_TICK_PER_SECOND,
RT_TIMER_FLAG_PERIODIC);
rt_timer_start(&dev->link_timer);
#ifdef RT_USING_GMAC_INT_MODE
/* installl isr */
DEBUG_MES("%s\n", __FUNCTION__);
rt_hw_interrupt_install(LS1C_MAC_IRQ, eth_rx_irq, RT_NULL, "e0_isr");
rt_hw_interrupt_umask(LS1C_MAC_IRQ);
#else
rt_timer_init(&dev->rx_poll_timer, "rx_poll_timer",
eth_rx_irq,
(void *)adapter,
1,
RT_TIMER_FLAG_PERIODIC);
rt_timer_start(&dev->rx_poll_timer);
#endif /*RT_USING_GMAC_INT_MODE*/
rt_kprintf("eth_inited!\n");
return RT_EOK;
}
static rt_err_t eth_open(rt_device_t dev, rt_uint16_t oflag)
{
rt_kprintf("eth_open!!\n");
return RT_EOK;
}
static rt_err_t eth_close(rt_device_t dev)
{
return RT_EOK;
}
static rt_size_t eth_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
{
rt_set_errno(-RT_ENOSYS);
return 0;
}
static rt_size_t eth_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
{
rt_set_errno(-RT_ENOSYS);
return 0;
}
static rt_err_t eth_control(rt_device_t dev, rt_uint8_t cmd, void *args)
{
switch (cmd)
{
case NIOCTL_GADDR:
if(args) rt_memcpy(args, eth_dev.dev_addr, 6);
else return -RT_ERROR;
break;
default :
break;
}
return RT_EOK;
}
rt_err_t rt_eth_tx(rt_device_t device, struct pbuf* p)
{
/* lock eth device */
rt_sem_take(&sem_lock, RT_WAITING_FOREVER);
DEBUG_MES("in %s\n", __FUNCTION__);
s32 status;
u32 pbuf;
u64 dma_addr;
u32 offload_needed = 0;
u32 index;
DmaDesc * dpr;
struct rt_eth_dev *dev = (struct rt_eth_dev *) device;
struct synopGMACNetworkAdapter *adapter;
synopGMACdevice * gmacdev;
adapter = (struct synopGMACNetworkAdapter *) dev->priv;
if(adapter == NULL)
return -1;
gmacdev = (synopGMACdevice *) adapter->synopGMACdev;
if(gmacdev == NULL)
return -1;
if(!synopGMAC_is_desc_owned_by_dma(gmacdev->TxNextDesc))
{
pbuf = (u32)plat_alloc_memory(p->len);
//pbuf = (u32)pbuf_alloc(PBUF_LINK, p->len, PBUF_RAM);
if(pbuf == 0)
{
rt_kprintf("===error in alloc bf1\n");
return -1;
}
DEBUG_MES("p->len = %d\n", p->len);
memcpy((void *)pbuf, p->payload, p->len);
dma_addr = plat_dma_map_single(gmacdev,(void*)pbuf,p->len);
status = synopGMAC_set_tx_qptr(gmacdev,dma_addr,p->len,pbuf,0,0,0,offload_needed,&index,dpr);
if(status < 0){
rt_kprintf("%s No More Free Tx Descriptors\n",__FUNCTION__);
plat_free_memory((void *)pbuf);
return -16;
}
}
synopGMAC_resume_dma_tx(gmacdev);
s32 desc_index;
u32 data1, data2;
u32 dma_addr1, dma_addr2;
u32 length1, length2;
#ifdef ENH_DESC_8W
u32 ext_status;
u16 time_stamp_higher;
u32 time_stamp_high;
u32 time_stamp_low;
#endif
do {
#ifdef ENH_DESC_8W
desc_index = synopGMAC_get_tx_qptr(gmacdev, &status, &dma_addr1, &length1, &data1, &dma_addr2, &length2, &data2,&ext_status,&time_stamp_high,&time_stamp_low);
synopGMAC_TS_read_timestamp_higher_val(gmacdev, &time_stamp_higher);
#else
desc_index = synopGMAC_get_tx_qptr(gmacdev, &status, &dma_addr1, &length1, &data1, &dma_addr2, &length2, &data2);
#endif
if(desc_index >= 0 && data1 != 0){
#ifdef IPC_OFFLOAD
if(synopGMAC_is_tx_ipv4header_checksum_error(gmacdev, status)){
rt_kprintf("Harware Failed to Insert IPV4 Header Checksum\n");
}
if(synopGMAC_is_tx_payload_checksum_error(gmacdev, status)){
rt_kprintf("Harware Failed to Insert Payload Checksum\n");
}
#endif
plat_free_memory((void *)(data1)); //sw: data1 = buffer1
if(synopGMAC_is_desc_valid(status)){
adapter->synopGMACNetStats.tx_bytes += length1;
adapter->synopGMACNetStats.tx_packets++;
}
else {
adapter->synopGMACNetStats.tx_errors++;
adapter->synopGMACNetStats.tx_aborted_errors += synopGMAC_is_tx_aborted(status);
adapter->synopGMACNetStats.tx_carrier_errors += synopGMAC_is_tx_carrier_error(status);
}
} adapter->synopGMACNetStats.collisions += synopGMAC_get_tx_collision_count(status);
} while(desc_index >= 0);
/* unlock eth device */
rt_sem_release(&sem_lock);
// rt_kprintf("output %d bytes\n", p->len);
u32 test_data;
test_data = synopGMACReadReg(gmacdev->DmaBase, DmaStatus);
return RT_EOK;
}
struct pbuf *rt_eth_rx(rt_device_t device)
{
DEBUG_MES("%s : \n", __FUNCTION__);
struct rt_eth_dev *dev = &eth_dev;
struct synopGMACNetworkAdapter *adapter;
synopGMACdevice * gmacdev;
// struct PmonInet * pinetdev;
s32 desc_index;
int i;
char * ptr;
u32 bf1;
u32 data1;
u32 data2;
u32 len;
u32 status;
u32 dma_addr1;
u32 dma_addr2;
struct pbuf *pbuf = RT_NULL;
rt_sem_take(&sem_lock, RT_WAITING_FOREVER);
adapter = (struct synopGMACNetworkAdapter *) dev->priv;
if(adapter == NULL){
rt_kprintf("%S : Unknown Device !!\n", __FUNCTION__);
return NULL;
}
gmacdev = (synopGMACdevice *) adapter->synopGMACdev;
if(gmacdev == NULL){
rt_kprintf("%s : GMAC device structure is missing\n", __FUNCTION__);
return NULL;
}
/*Handle the Receive Descriptors*/
// do{
desc_index = synopGMAC_get_rx_qptr(gmacdev, &status,&dma_addr1,NULL, &data1,&dma_addr2,NULL,&data2);
if(desc_index >= 0 && data1 != 0){
DEBUG_MES("Received Data at Rx Descriptor %d for skb 0x%08x whose status is %08x\n",desc_index,dma_addr1,status);
if(synopGMAC_is_rx_desc_valid(status)||SYNOP_PHY_LOOPBACK)
{
pbuf = pbuf_alloc(PBUF_LINK, MAX_ETHERNET_PAYLOAD, PBUF_RAM);
if(pbuf == 0) rt_kprintf("===error in pbuf_alloc\n");
dma_addr1 = plat_dma_map_single(gmacdev,(void*)data1,RX_BUF_SIZE);
len = synopGMAC_get_rx_desc_frame_length(status); //Not interested in Ethernet CRC bytes
rt_memcpy( pbuf->payload, (char *)data1, len);
DEBUG_MES("==get pkg len: %d\n",len);
}
else
{
rt_kprintf("s: %08x\n",status);
adapter->synopGMACNetStats.rx_errors++;
adapter->synopGMACNetStats.collisions += synopGMAC_is_rx_frame_collision(status);
adapter->synopGMACNetStats.rx_crc_errors += synopGMAC_is_rx_crc(status);
adapter->synopGMACNetStats.rx_frame_errors += synopGMAC_is_frame_dribbling_errors(status);
adapter->synopGMACNetStats.rx_length_errors += synopGMAC_is_rx_frame_length_errors(status);
}
desc_index = synopGMAC_set_rx_qptr(gmacdev,dma_addr1, RX_BUF_SIZE, (u32)data1,0,0,0);
if(desc_index < 0){
#if SYNOP_RX_DEBUG
rt_kprintf("Cannot set Rx Descriptor for data1 %08x\n",(u32)data1);
#endif
plat_free_memory((void *)data1);
}
}
// }while(desc_index >= 0);
rt_sem_release(&sem_lock);
DEBUG_MES("%s : before return \n", __FUNCTION__);
return pbuf;
}
static int rtl88e1111_config_init(synopGMACdevice *gmacdev)
{
int retval, err;
u16 data;
DEBUG_MES("in %s\n", __FUNCTION__);
synopGMAC_read_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0x14,&data);
data = data | 0x82;
err = synopGMAC_write_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0x14,data);
synopGMAC_read_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0x00,&data);
data = data | 0x8000;
err = synopGMAC_write_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0x00,data);
#if SYNOP_PHY_LOOPBACK
synopGMAC_read_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0x14,&data);
data = data | 0x70;
data = data & 0xffdf;
err = synopGMAC_write_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0x14,data);
data = 0x8000;
err = synopGMAC_write_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0x00,data);
data = 0x5140;
err = synopGMAC_write_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0x00,data);
#endif
if (err < 0)
return err;
return 0;
}
int init_phy(synopGMACdevice *gmacdev)
{
u16 data;
synopGMAC_read_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,2,&data);
/*set 88e1111 clock phase delay*/
if(data == 0x141)
rtl88e1111_config_init(gmacdev);
#if defined (RMII)
else if(data == 0x8201)
{
//RTL8201
data = 0x400; // set RMII mode
synopGMAC_write_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0x19,data);
synopGMAC_read_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0x19,&data);
TR("phy reg25 is %0x \n",data);
data = 0x3100; //set 100M speed
synopGMAC_write_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0x0,data);
}
else if(data == 0x0180 || data == 0x0181)
{
//DM9161
synopGMAC_read_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0x10,&data);
data |= (1 << 8); //set RMII mode
synopGMAC_write_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0x10,data); //set RMII mode
synopGMAC_read_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0x10,&data);
TR("phy reg16 is 0x%0x \n",data);
// synopGMAC_read_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0x0,&data);
// data &= ~(1<<10);
data = 0x3100; //set auto-
//data = 0x0100; //set 10M speed
synopGMAC_write_phy_reg(gmacdev->MacBase,gmacdev->PhyBase,0x0,data);
}
#endif
return 0;
}
u32 synopGMAC_wakeup_filter_config3[] = {
0x00000000,
0x000000FF,
0x00000000,
0x00000000,
0x00000100,
0x00003200,
0x7eED0000,
0x00000000
};
static void synopGMAC_linux_powerdown_mac(synopGMACdevice *gmacdev)
{
rt_kprintf("Put the GMAC to power down mode..\n");
GMAC_Power_down = 1;
synopGMAC_disable_dma_tx(gmacdev);
plat_delay(10000);
synopGMAC_tx_disable(gmacdev);
synopGMAC_rx_disable(gmacdev);
plat_delay(10000);
synopGMAC_disable_dma_rx(gmacdev);
synopGMAC_magic_packet_enable(gmacdev);
synopGMAC_write_wakeup_frame_register(gmacdev, synopGMAC_wakeup_filter_config3);
synopGMAC_wakeup_frame_enable(gmacdev);
synopGMAC_rx_enable(gmacdev);
synopGMAC_pmt_int_enable(gmacdev);
synopGMAC_power_down_enable(gmacdev);
return;
}
static void synopGMAC_linux_powerup_mac(synopGMACdevice *gmacdev)
{
GMAC_Power_down = 0;
if( synopGMAC_is_magic_packet_received(gmacdev))
rt_kprintf("GMAC wokeup due to Magic Pkt Received\n");
if(synopGMAC_is_wakeup_frame_received(gmacdev))
rt_kprintf("GMAC wokeup due to Wakeup Frame Received\n");
synopGMAC_pmt_int_disable(gmacdev);
synopGMAC_rx_enable(gmacdev);
synopGMAC_enable_dma_rx(gmacdev);
synopGMAC_tx_enable(gmacdev);
synopGMAC_enable_dma_tx(gmacdev);
return;
}
static int mdio_read(synopGMACPciNetworkAdapter *adapter, int addr, int reg)
{
synopGMACdevice * gmacdev;
u16 data;
gmacdev = adapter->synopGMACdev;
synopGMAC_read_phy_reg(gmacdev->MacBase,addr,reg, &data);
return data;
}
static void mdio_write(synopGMACPciNetworkAdapter *adapter, int addr, int reg, int data)
{
synopGMACdevice * gmacdev;
gmacdev = adapter->synopGMACdev;
synopGMAC_write_phy_reg(gmacdev->MacBase,addr,reg,data);
}
void eth_rx_irq(int irqno,void *param)
{
struct rt_eth_dev *dev = &eth_dev;
struct synopGMACNetworkAdapter *adapter = dev->priv;
//DEBUG_MES("in irq!!\n");
#ifdef RT_USING_GMAC_INT_MODE
int i ;
for(i = 0; i < 7200; i++)
;
#endif /*RT_USING_GMAC_INT_MODE*/
synopGMACdevice * gmacdev = (synopGMACdevice *)adapter->synopGMACdev;
u32 interrupt,dma_status_reg;
s32 status;
u32 dma_addr;
//rt_kprintf("irq i = %d\n", i++);
dma_status_reg = synopGMACReadReg(gmacdev->DmaBase, DmaStatus);
if(dma_status_reg == 0)
{
rt_kprintf("dma_status ==0 \n");
return;
}
//rt_kprintf("dma_status_reg is 0x%x\n", dma_status_reg);
u32 gmacstatus;
synopGMAC_disable_interrupt_all(gmacdev);
gmacstatus = synopGMACReadReg(gmacdev->MacBase,GmacStatus);
if(dma_status_reg & GmacPmtIntr){
rt_kprintf("%s:: Interrupt due to PMT module\n",__FUNCTION__);
//synopGMAC_linux_powerup_mac(gmacdev);
}
if(dma_status_reg & GmacMmcIntr){
rt_kprintf("%s:: Interrupt due to MMC module\n",__FUNCTION__);
DEBUG_MES("%s:: synopGMAC_rx_int_status = %08x\n",__FUNCTION__,synopGMAC_read_mmc_rx_int_status(gmacdev));
DEBUG_MES("%s:: synopGMAC_tx_int_status = %08x\n",__FUNCTION__,synopGMAC_read_mmc_tx_int_status(gmacdev));
}
if(dma_status_reg & GmacLineIntfIntr){
rt_kprintf("%s:: Interrupt due to GMAC LINE module\n",__FUNCTION__);
}
interrupt = synopGMAC_get_interrupt_type(gmacdev);
//rt_kprintf("%s:Interrupts to be handled: 0x%08x\n",__FUNCTION__,interrupt);
if(interrupt & synopGMACDmaError){
u8 mac_addr0[6];
rt_kprintf("%s::Fatal Bus Error Inetrrupt Seen\n",__FUNCTION__);
memcpy(mac_addr0,dev->dev_addr,6);
synopGMAC_disable_dma_tx(gmacdev);
synopGMAC_disable_dma_rx(gmacdev);
synopGMAC_take_desc_ownership_tx(gmacdev);
synopGMAC_take_desc_ownership_rx(gmacdev);
synopGMAC_init_tx_rx_desc_queue(gmacdev);
synopGMAC_reset(gmacdev);
synopGMAC_set_mac_addr(gmacdev,GmacAddr0High,GmacAddr0Low, mac_addr0);
synopGMAC_dma_bus_mode_init(gmacdev,DmaFixedBurstEnable| DmaBurstLength8 | 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){
//DEBUG_MES("%s:: Rx Normal \n", __FUNCTION__);
//synop_handle_received_data(netdev);
eth_device_ready(&eth_dev.parent);
}
if(interrupt & synopGMACDmaRxAbnormal){
//rt_kprintf("%s::Abnormal Rx Interrupt Seen\n",__FUNCTION__);
if(GMAC_Power_down == 0){
adapter->synopGMACNetStats.rx_over_errors++;
synopGMACWriteReg(gmacdev->DmaBase, DmaStatus ,0x80);
synopGMAC_resume_dma_rx(gmacdev);
}
}
if(interrupt & synopGMACDmaRxStopped){
rt_kprintf("%s::Receiver stopped seeing Rx interrupts\n",__FUNCTION__); //Receiver gone in to stopped state
}
if(interrupt & synopGMACDmaTxNormal){
DEBUG_MES("%s::Finished Normal Transmission \n",__FUNCTION__);
// synop_handle_transmit_over(netdev);
}
if(interrupt & synopGMACDmaTxAbnormal){
rt_kprintf("%s::Abnormal Tx Interrupt Seen\n",__FUNCTION__);
}
if(interrupt & synopGMACDmaTxStopped){
TR("%s::Transmitter stopped sending the packets\n",__FUNCTION__);
if(GMAC_Power_down == 0){ // If Mac is not in powerdown
synopGMAC_disable_dma_tx(gmacdev);
synopGMAC_take_desc_ownership_tx(gmacdev);
synopGMAC_enable_dma_tx(gmacdev);
// netif_wake_queue(netdev);
TR("%s::Transmission Resumed\n",__FUNCTION__);
}
}
/* Enable the interrrupt before returning from ISR*/
synopGMAC_enable_interrupt(gmacdev,DmaIntEnable);
return;
}
void rt_hw_eth_init(void)
{
u64 base_addr = Gmac_base;
struct synopGMACNetworkAdapter * synopGMACadapter;
static u8 mac_addr0[6] = DEFAULT_MAC_ADDRESS;
rt_sem_init(&sem_ack, "tx_ack", 1, RT_IPC_FLAG_FIFO);
rt_sem_init(&sem_lock, "eth_lock", 1, RT_IPC_FLAG_FIFO);
memset(&eth_dev, 0, sizeof(eth_dev));
synopGMACadapter = (struct synopGMACNetworkAdapter * )plat_alloc_memory(sizeof (struct synopGMACNetworkAdapter));
if(!synopGMACadapter){
rt_kprintf("Error in Memory Allocataion, Founction : %s \n", __FUNCTION__);
}
memset((char *)synopGMACadapter ,0, sizeof (struct synopGMACNetworkAdapter));
synopGMACadapter->synopGMACdev = NULL;
synopGMACadapter->synopGMACdev = (synopGMACdevice *) plat_alloc_memory(sizeof (synopGMACdevice));
if(!synopGMACadapter->synopGMACdev){
rt_kprintf("Error in Memory Allocataion, Founction : %s \n", __FUNCTION__);
}
memset((char *)synopGMACadapter->synopGMACdev ,0, sizeof (synopGMACdevice));
/*
* Attach the device to MAC struct This will configure all the required base addresses
* such as Mac base, configuration base, phy base address(out of 32 possible phys)
* */
synopGMAC_attach(synopGMACadapter->synopGMACdev,(regbase + MACBASE), regbase + DMABASE, DEFAULT_PHY_BASE, mac_addr0);
init_phy(synopGMACadapter->synopGMACdev);
synopGMAC_reset(synopGMACadapter->synopGMACdev);
/* MII setup */
synopGMACadapter->mii.phy_id_mask = 0x1F;
synopGMACadapter->mii.reg_num_mask = 0x1F;
synopGMACadapter->mii.dev = synopGMACadapter;
synopGMACadapter->mii.mdio_read = mdio_read;
synopGMACadapter->mii.mdio_write = mdio_write;
synopGMACadapter->mii.phy_id = synopGMACadapter->synopGMACdev->PhyBase;
synopGMACadapter->mii.supports_gmii = mii_check_gmii_support(&synopGMACadapter->mii);
eth_dev.iobase = base_addr;
eth_dev.name = "e0";
eth_dev.priv = synopGMACadapter;
eth_dev.dev_addr[0] = mac_addr0[0];
eth_dev.dev_addr[1] = mac_addr0[1];
eth_dev.dev_addr[2] = mac_addr0[2];
eth_dev.dev_addr[3] = mac_addr0[3];
eth_dev.dev_addr[4] = mac_addr0[4];
eth_dev.dev_addr[5] = mac_addr0[5];
eth_dev.parent.parent.type = RT_Device_Class_NetIf;
eth_dev.parent.parent.init = eth_init;
eth_dev.parent.parent.open = eth_open;
eth_dev.parent.parent.close = eth_close;
eth_dev.parent.parent.read = eth_read;
eth_dev.parent.parent.write = eth_write;
eth_dev.parent.parent.control = eth_control;
eth_dev.parent.parent.user_data = RT_NULL;
eth_dev.parent.eth_tx = rt_eth_tx;
eth_dev.parent.eth_rx = rt_eth_rx;
eth_device_init(&(eth_dev.parent), "e0");
}

View File

@ -0,0 +1,37 @@
/*
* File : synopGMAC.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) chinesebear
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2017-08-24 chinesebear first version
*/
#ifndef __SYNOPGMAC__H
#define __SYNOPGMAC__H
#include "synopGMAC_network_interface.h"
#include "synopGMAC_Host.h"
#include "synopGMAC_Dev.h"
#include "synopGMAC_plat.h"
#include "mii.h"
#include "synopGMAC_types.h"
void rt_hw_eth_init(void);
#endif /*__SYNOPGMAC__H*/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,88 @@
/*
* File : synopGMAC_Host.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) chinesebear
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2017-08-24 chinesebear first version
*/
#ifndef SYNOP_GMAC_HOST_H
#define SYNOP_GMAC_HOST_H 1
#include "synopGMAC_plat.h"
#include "synopGMAC_Dev.h"
#include "mii.h"
struct net_device_stats
{
unsigned long rx_packets; /* total packets received */
unsigned long tx_packets; /* total packets transmitted */
unsigned long rx_bytes; /* total bytes received */
unsigned long tx_bytes; /* total bytes transmitted */
unsigned long rx_errors; /* bad packets received */
unsigned long tx_errors; /* packet transmit problems */
unsigned long rx_dropped; /* no space in linux buffers */
unsigned long tx_dropped; /* no space available in linux */
unsigned long multicast; /* multicast packets received */
unsigned long collisions;
/* detailed rx_errors: */
unsigned long rx_length_errors;
unsigned long rx_over_errors; /* receiver ring buff overflow */
unsigned long rx_crc_errors; /* recved pkt with crc error */
unsigned long rx_frame_errors; /* recv'd frame alignment error */
unsigned long rx_fifo_errors; /* recv'r fifo overrun */
unsigned long rx_missed_errors; /* receiver missed packet */
/* detailed tx_errors */
unsigned long tx_aborted_errors;
unsigned long tx_carrier_errors;
unsigned long tx_fifo_errors;
unsigned long tx_heartbeat_errors;
unsigned long tx_window_errors;
/* for cslip etc */
unsigned long rx_compressed;
unsigned long tx_compressed;
};
typedef struct synopGMACNetworkAdapter{
/*Device Dependent Data structur*/
synopGMACdevice * synopGMACdev;
struct net_device_stats synopGMACNetStats;
struct mii_if_info mii;
} synopGMACPciNetworkAdapter;
#endif

View File

@ -0,0 +1,37 @@
/*
* File : synopGMAC_debug.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) chinesebear
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2017-08-24 chinesebear first version
*/
#ifndef __DEBUG_H__
#define __DEBUG_H__
//#define GMAC_DEBUG
#include <rtthread.h>
#ifdef GMAC_DEBUG
#define DEBUG_MES rt_kprintf
#else
#define DEBUG_MES(...)
#endif
#endif /*__DEBUG_H__*/

View File

@ -0,0 +1,98 @@
/** \file
* Header file for the nework dependent functionality.
* The function prototype listed here are linux dependent.
*
* \internal
* ---------------------------REVISION HISTORY-------------------
* Synopsys 01/Aug/2007 Created
*/
/*
* File : synopGMAC_network_interface.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) chinesebear
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2017-08-24 chinesebear first version
*/
#ifndef SYNOP_GMAC_NETWORK_INTERFACE_H
#define SYNOP_GMAC_NETWORK_INTERFACE_H 1
#include "synopGMAC_plat.h"
#include "synopGMAC_Host.h"
#include "synopGMAC_Dev.h"
//#include <common.h>
//#include <net.h>
//#include <linux/stddef.h>
#define NET_IF_TIMEOUT (10*HZ)
#define CHECK_TIME (HZ)
s32 synopGMAC_init_network_interface(char* xname,u64 synopGMACMappedAddr);
void synopGMAC_exit_network_interface(void);
s32 synopGMAC_linux_open(struct eth_device *);
s32 synopGMAC_linux_close(struct eth_device *);
//s32 synopGMAC_linux_xmit_frames(struct ifnet *);
struct net_device_stats * synopGMAC_linux_get_stats(struct synopGMACNetworkAdapter *);
//void synopGMAC_linux_set_multicast_list(struct net_device *);
//s32 synopGMAC_linux_set_mac_address(struct synopGMACNetwokrAdapter*,void *);
//s32 synopGMAC_linux_change_mtu(struct net_device *,s32);
//s32 synopGMAC_linux_do_ioctl(struct ifnet *,struct ifreq *,s32);
//void synopGMAC_linux_tx_timeout(struct net_device *);
s32 synopGMAC_test(synopGMACdevice * gmacdev_0,synopGMACdevice * gmacdev_1);
void dumpreg(u64 );
void dumpphyreg();
/*
* gethex(vp,p,n)
* convert n hex digits from p to binary, result in vp,
* rtn 1 on success
*/
static int gethex(u8 *vp, char *p, int n)
{
u8 v;
int digit;
for (v = 0; n > 0; n--) {
if (*p == 0)
return (0);
if (*p >= '0' && *p <= '9')
digit = *p - '0';
else if (*p >= 'a' && *p <= 'f')
digit = *p - 'a' + 10;
else if (*p >= 'A' && *p <= 'F')
digit = *p - 'A' + 10;
else
return (0);
v <<= 4;
v |= digit;
p++;
}
*vp = v;
return (1);
}
#endif /* End of file */

View File

@ -0,0 +1,150 @@
/**\file
* This file defines the wrapper for the platform/OS related functions
* The function definitions needs to be modified according to the platform
* and the Operating system used.
* This file should be handled with greatest care while porting the driver
* to a different platform running different operating system other than
* Linux 2.6.xx.
* \internal
* ----------------------------REVISION HISTORY-----------------------------
* Synopsys 01/Aug/2007 Created
*/
/*
* File : synopGMAC_plat.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) chinesebear
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2017-08-24 chinesebear first version
*/
#include "synopGMAC_plat.h"
#include "synopGMAC_Dev.h"
#include <rthw.h>
#include <rtthread.h>
extern void flush_cache(unsigned long start_addr, unsigned long size);
dma_addr_t __attribute__((weak)) gmac_dmamap(unsigned long va,u32 size)
{
return VA_TO_PA (va);
//return UNCACHED_TO_PHYS(va);
}
/**
* This is a wrapper function for Memory allocation routine. In linux Kernel
* it it kmalloc function
* @param[in] bytes in bytes to allocate
*/
void *plat_alloc_memory(u32 bytes)
{
//return (void*)malloc((size_t)bytes, M_DEVBUF, M_DONTWAIT);
void *buf = (void*)rt_malloc((u32)bytes);
flush_cache((unsigned long)buf, bytes);
return buf;
}
/**
* This is a wrapper function for consistent dma-able Memory allocation routine.
* In linux Kernel, it depends on pci dev structure
* @param[in] bytes in bytes to allocate
*/
//void *plat_alloc_consistent_dmaable_memory(struct synopGMACdevice *dev, u32 size, u32 *addr)
void *plat_alloc_consistent_dmaable_memory(synopGMACdevice *pcidev, u32 size, u32 *addr)
{
void *buf;
buf = (void*)rt_malloc((u32)(size+16));
//CPU_IOFlushDCache( buf,size, SYNC_W);
unsigned long i = (unsigned long)buf;
// rt_kprintf("size = %d\n", size);
// rt_kprintf("bufaddr = %p\n", buf);
// rt_kprintf("i%%16 == %d\n", i%16);
if(i%16 == 8){
i += 8;
}
else if(i%16 == 4){
i += 12;
}
else if(i%16 == 12){
i += 4;
}
flush_cache(i, size);
*addr =gmac_dmamap(i, size);
buf = (unsigned char *)CACHED_TO_UNCACHED(i);
// rt_kprintf("bufaddr = %p\n", buf);
return buf;
}
/**
* This is a wrapper function for freeing consistent dma-able Memory.
* In linux Kernel, it depends on pci dev structure
* @param[in] bytes in bytes to allocate
*/
//void plat_free_consistent_dmaable_memory(void * addr)
void plat_free_consistent_dmaable_memory(synopGMACdevice *pcidev, u32 size, void * addr,u32 dma_addr)
{
rt_free((void*)PHYS_TO_CACHED(UNCACHED_TO_PHYS(addr)));
return;
}
/**
* This is a wrapper function for Memory free routine. In linux Kernel
* it it kfree function
* @param[in] buffer pointer to be freed
*/
void plat_free_memory(void *buffer)
{
rt_free(buffer);
return ;
}
dma_addr_t plat_dma_map_single(void *hwdev, void *ptr,
u32 size)
{
unsigned long addr = (unsigned long) ptr;
//CPU_IOFlushDCache(addr,size, direction);
flush_cache(addr, size);
return gmac_dmamap(addr, size);
}
/**
* This is a wrapper function for platform dependent delay
* Take care while passing the argument to this function
* @param[in] buffer pointer to be freed
*/
void plat_delay(u32 delay)
{
while (delay--);
return;
}

View File

@ -0,0 +1,285 @@
/**\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
*/
/*
* File : synopGMAC_plat.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) chinesebear
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2017-08-24 chinesebear first version
*/
#ifndef SYNOP_GMAC_PLAT_H
#define SYNOP_GMAC_PLAT_H 1
/* sw
#include <linux/kernel.h>
#include <asm/io.h>
#include <linux/gfp.h>
#include <linux/slab.h>
#include <linux/pci.h>
*/
#include "synopGMAC_types.h"
#include "synopGMAC_debug.h"
//#include "mii.h"
//#include "GMAC_Pmon.h"
//#include "synopGMAC_Host.h"
#include <rtthread.h>
//sw: copy the type define into here
#define IOCTL_READ_REGISTER SIOCDEVPRIVATE+1
#define IOCTL_WRITE_REGISTER SIOCDEVPRIVATE+2
#define IOCTL_READ_IPSTRUCT SIOCDEVPRIVATE+3
#define IOCTL_READ_RXDESC SIOCDEVPRIVATE+4
#define IOCTL_READ_TXDESC SIOCDEVPRIVATE+5
#define IOCTL_POWER_DOWN SIOCDEVPRIVATE+6
#define SYNOP_GMAC0 1
typedef int bool;
//typedef unsigned long dma_addr_t;
//sw
/* write/read MMIO register */
#define writeb(val, addr) (*(volatile u8*)(addr) = (val))
#define writew(val, addr) (*(volatile u16*)(addr) = (val))
#define writel(val, addr) (*(volatile u32*)(addr) = (val))
#define readb(addr) (*(volatile u8*)(addr))
#define readw(addr) (*(volatile u16*)(addr))
#define readl(addr) (*(volatile u32*)(addr))
#define KUSEG_ADDR 0x0
#define CACHED_MEMORY_ADDR 0x80000000
#define UNCACHED_MEMORY_ADDR 0xa0000000
#define KSEG2_ADDR 0xc0000000
#define MAX_MEM_ADDR 0xbe000000
#define RESERVED_ADDR 0xbfc80000
#define CACHED_TO_PHYS(x) ((unsigned)(x) & 0x7fffffff)
#define PHYS_TO_CACHED(x) ((unsigned)(x) | CACHED_MEMORY_ADDR)
#define UNCACHED_TO_PHYS(x) ((unsigned)(x) & 0x1fffffff)
#define PHYS_TO_UNCACHED(x) ((unsigned)(x) | UNCACHED_MEMORY_ADDR)
#define VA_TO_CINDEX(x) ((unsigned)(x) & 0xffffff | CACHED_MEMORY_ADDR)
#define CACHED_TO_UNCACHED(x) (PHYS_TO_UNCACHED(CACHED_TO_PHYS(x)))
#define VA_TO_PA(x) UNCACHED_TO_PHYS(x)
/* sw
#define TR0(fmt, args...) printk(KERN_CRIT "SynopGMAC: " fmt, ##args)
#ifdef DEBUG
#undef TR
# define TR(fmt, args...) printk(KERN_CRIT "SynopGMAC: " fmt, ##args)
#else
# define TR(fmt, args...) // not debugging: nothing
#endif
*/
/*
#define TR0(fmt, args...) printf("SynopGMAC: " fmt, ##args)
*/
/*
#ifdef DEBUG
#undef TR
# define TR(fmt, args...) printf("SynopGMAC: " fmt, ##args)
#else
//# define TR(fmt, args...) // not debugging: nothing
#define TR(fmt, args...) printf("SynopGMAC: " fmt, ##args)
#endif
*/
//sw: nothing to display
#define TR0(fmt, args...) rt_kprintf(fmt, ##args)
#define TR(fmt, args...) rt_kprintf(fmt, ##args)
//#define TR rt_kprintf
//typedef int bool;
enum synopGMAC_boolean
{
false = 0,
true = 1
};
#define DEFAULT_DELAY_VARIABLE 10
#define DEFAULT_LOOP_VARIABLE 10000
/* There are platform related endian conversions
*
*/
#define LE32_TO_CPU __le32_to_cpu
#define BE32_TO_CPU __be32_to_cpu
#define CPU_TO_LE32 __cpu_to_le32
/* Error Codes */
#define ESYNOPGMACNOERR 0
#define ESYNOPGMACNOMEM 1
#define ESYNOPGMACPHYERR 2
#define ESYNOPGMACBUSY 3
struct Network_interface_data
{
u32 unit;
u32 addr;
u32 data;
};
/**
* These are the wrapper function prototypes for OS/platform related routines
*/
void * plat_alloc_memory(u32 );
void plat_free_memory(void *);
//void * plat_alloc_consistent_dmaable_memory(struct pci_dev *, u32, u32 *);
//void plat_free_consistent_dmaable_memory (struct pci_dev *, u32, void *, u32);
void plat_delay(u32);
/**
* The Low level function to read register contents from Hardware.
*
* @param[in] pointer to the base of register map
* @param[in] Offset from the base
* \return Returns the register contents
*/
static u32 synopGMACReadReg(u32 RegBase, u32 RegOffset)
{
u32 addr;
u32 data;
addr = RegBase + (u32)RegOffset;
data = *(volatile u32 *)addr;
#if SYNOP_REG_DEBUG
TR("%s RegBase = 0x%08x RegOffset = 0x%08x RegData = 0x%08x\n", __FUNCTION__, (u32)RegBase, RegOffset, data );
#endif
// rt_kprintf("%s RegBase = 0x%08x RegOffset = 0x%08x RegData = 0x%08x\n", __FUNCTION__, (u32)RegBase, RegOffset, data );
return data;
}
/**
* The Low level function to write to a register in Hardware.
*
* @param[in] pointer to the base of register map
* @param[in] Offset from the base
* @param[in] Data to be written
* \return void
*/
static void synopGMACWriteReg(u32 RegBase, u32 RegOffset, u32 RegData )
{
u32 addr;
addr = RegBase + (u32)RegOffset;
// rt_kprintf("%s RegBase = 0x%08x RegOffset = 0x%08x RegData = 0x%08x\n", __FUNCTION__,(u32) RegBase, RegOffset, RegData );
#if SYNOP_REG_DEBUG
TR("%s RegBase = 0x%08x RegOffset = 0x%08x RegData = 0x%08x\n", __FUNCTION__,(u32) RegBase, RegOffset, RegData );
#endif
*(volatile u32 *)addr = RegData;
if(addr == 0xbfe1100c)
DEBUG_MES("regdata = %08x\n", RegData);
return;
}
/**
* The Low level function to set bits of a register in Hardware.
*
* @param[in] pointer to the base of register map
* @param[in] Offset from the base
* @param[in] Bit mask to set bits to logical 1
* \return void
*/
static void synopGMACSetBits(u32 RegBase, u32 RegOffset, u32 BitPos)
{
//u64 addr = (u64)RegBase + (u64)RegOffset;
u32 data;
data = synopGMACReadReg(RegBase, RegOffset);
data |= BitPos;
synopGMACWriteReg(RegBase, RegOffset, data);
// writel(data,(void *)addr);
#if SYNOP_REG_DEBUG
TR("%s !!!!!!!!!!!!! RegOffset = 0x%08x RegData = 0x%08x\n", __FUNCTION__, RegOffset, data );
#endif
return;
}
/**
* The Low level function to clear bits of a register in Hardware.
*
* @param[in] pointer to the base of register map
* @param[in] Offset from the base
* @param[in] Bit mask to clear bits to logical 0
* \return void
*/
static void synopGMACClearBits(u32 RegBase, u32 RegOffset, u32 BitPos)
{
u32 data;
data = synopGMACReadReg(RegBase, RegOffset);
data &= (~BitPos);
synopGMACWriteReg(RegBase, RegOffset, data);
#if SYNOP_REG_DEBUG
TR("%s !!!!!!!!!!!!! RegOffset = 0x%08x RegData = 0x%08x\n", __FUNCTION__, RegOffset, data );
#endif
return;
}
/**
* The Low level function to Check the setting of the bits.
*
* @param[in] pointer to the base of register map
* @param[in] Offset from the base
* @param[in] Bit mask to set bits to logical 1
* \return returns TRUE if set to '1' returns FALSE if set to '0'. Result undefined there are no bit set in the BitPos argument.
*
*/
static bool synopGMACCheckBits(u32 RegBase, u32 RegOffset, u32 BitPos)
{
u32 data;
data = synopGMACReadReg(RegBase, RegOffset);
data &= BitPos;
if(data) return true;
else return false;
}
#endif

View File

@ -0,0 +1,39 @@
/*
* File : synopGMAC_types.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) chinesebear
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2017-08-24 chinesebear first version
*/
#ifndef __TYPES__H
#define __TYPES__H
typedef unsigned char uint8_t;
typedef unsigned long long u64;
typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;
typedef signed int s32;
typedef u32 dma_addr_t;
#endif /*__TYPES__H*/

View File

@ -131,15 +131,21 @@
// <bool name="RT_USING_DFS_NFS" description="Using NFS v3 client file system" default="false" />
// #define RT_USING_DFS_NFS
// <string name="RT_NFS_HOST_EXPORT" description="NFSv3 host export" default="192.168.1.5:/" />
#define RT_NFS_HOST_EXPORT "192.168.3.108:/"
#define RT_NFS_HOST_EXPORT "192.168.1.254:/"
// </section>
// <section name="RT_USING_LWIP" description="lwip, a lightweight TCP/IP protocol stack" default="true" >
// #define RT_USING_LWIP
#define RT_USING_LWIP
#define RT_USING_GMAC_INT_MODE
#define RT_USING_LWIP141
//#define RT_LWIP_DEBUG
#define RT_LWIP_USING_RT_MEM
// <bool name="RT_LWIP_ICMP" description="Enable ICMP protocol" default="true" />
#define RT_LWIP_ICMP
// <bool name="RT_LWIP_IGMP" description="Enable IGMP protocol" default="false" />
// #define RT_LWIP_IGMP
#define RT_LWIP_IGMP
// <bool name="RT_LWIP_UDP" description="Enable UDP protocol" default="true" />
#define RT_LWIP_UDP
// <bool name="RT_LWIP_TCP" description="Enable TCP protocol" default="true" />
@ -148,10 +154,11 @@
#define RT_LWIP_DNS
// <integer name="RT_LWIP_PBUF_NUM" description="Maximal number of buffers in the pbuf pool" default="4" />
#define RT_LWIP_PBUF_NUM 4
#define RT_LWIP_PBUF_POOL_BUFSIZE 2048
// <integer name="RT_LWIP_TCP_PCB_NUM" description="Maximal number of simultaneously active TCP connections" default="5" />
#define RT_LWIP_TCP_PCB_NUM 3
// <integer name="RT_LWIP_TCP_SND_BUF" description="TCP sender buffer size" default="8192" />
#define RT_LWIP_TCP_SND_BUF 2048
#define RT_LWIP_TCP_SND_BUF 4096
// <integer name="RT_LWIP_TCP_WND" description="TCP receive window" default="8192" />
#define RT_LWIP_TCP_WND 2048
// <bool name="RT_LWIP_SNMP" description="Enable SNMP protocol" default="false" />
@ -159,7 +166,7 @@
// <bool name="RT_LWIP_DHCP" description="Enable DHCP client to get IP address" default="false" />
// #define RT_LWIP_DHCP
// <integer name="RT_LWIP_TCP_SEG_NUM" description="the number of simultaneously queued TCP" default="4" />
#define RT_LWIP_TCP_SEG_NUM 4
#define RT_LWIP_TCP_SEG_NUM 40
// <integer name="RT_LWIP_TCPTHREAD_PRIORITY" description="the thread priority of TCP thread" default="128" />
#define RT_LWIP_TCPTHREAD_PRIORITY 12
// <integer name="RT_LWIP_TCPTHREAD_MBOX_SIZE" description="the mail box size of TCP thread to wait for" default="32" />
@ -175,13 +182,13 @@
// <ipaddr name="RT_LWIP_IPADDR" description="IP address of device" default="192.168.1.30" />
#define RT_LWIP_IPADDR0 192
#define RT_LWIP_IPADDR1 168
#define RT_LWIP_IPADDR2 3
#define RT_LWIP_IPADDR3 108
#define RT_LWIP_IPADDR2 1
#define RT_LWIP_IPADDR3 254
// <ipaddr name="RT_LWIP_GWADDR" description="Gateway address of device" default="192.168.1.1" />
#define RT_LWIP_GWADDR0 192
#define RT_LWIP_GWADDR1 168
#define RT_LWIP_GWADDR2 3
#define RT_LWIP_GWADDR3 1
#define RT_LWIP_GWADDR2 1
#define RT_LWIP_GWADDR3 3
// <ipaddr name="RT_LWIP_MSKADDR" description="Mask address of device" default="255.255.255.0" />
#define RT_LWIP_MSKADDR0 255
#define RT_LWIP_MSKADDR1 255

View File

@ -121,5 +121,41 @@ rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, rt_uint8_t *stack_ad
return (rt_uint8_t *)stk;
}
#define cache_op(op,addr) \
__asm__ __volatile__( \
" .set push \n" \
" .set noreorder \n" \
" .set mips3\n\t \n" \
" cache %0, %1 \n" \
" .set pop \n" \
: \
: "i" (op), "R" (*(unsigned char *)(addr)))
#if defined(CONFIG_CPU_LOONGSON2)
#define Hit_Invalidate_I 0x00
#else
#define Hit_Invalidate_I 0x10
#endif
#define Hit_Invalidate_D 0x11
#define CONFIG_SYS_CACHELINE_SIZE 32
#define Hit_Writeback_Inv_D 0x15
void flush_cache(unsigned long start_addr, unsigned long size)
{
unsigned long lsize = CONFIG_SYS_CACHELINE_SIZE;
unsigned long addr = start_addr & ~(lsize - 1);
unsigned long aend = (start_addr + size - 1) & ~(lsize - 1);
while (1) {
cache_op(Hit_Writeback_Inv_D, addr);
cache_op(Hit_Invalidate_I, addr);
if (addr == aend)
break;
addr += lsize;
}
}
/*@}*/