blob: 06f062e73677b12fc72e223284b20bfe3d2be147 [file] [log] [blame]
/*
* (C) Copyright 2006
* Mindspeed Technologies
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <common.h>
#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_COMCERTO_EMAC)
#if !defined(CONFIG_EMAC0) && !defined(CONFIG_EMAC1)
#error must define one of CONFIG_EMAC0 or CONFIG_EMAC1
#endif
#include <asm/io.h>
#include <asm/hardware.h>
#include <net.h>
#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
#include <miiphy.h>
#endif
#define MAX_DEVNAME_SIZE 8
struct bdesc {
volatile u8 *bptr;
volatile u32 bcontrol;
u32 dummy1;
u32 dummy2;
};
struct fdesc {
/* Hardware mapped fields */
void *next; /* 4 bytes */
volatile u32 system; /* 4 bytes */
volatile u32 fstatus; /* 4 bytes */
volatile u32 fcontrol; /* 4 bytes */
struct bdesc bdesc; /* 16 bytes */
};
struct emac_dev {
char devname[MAX_DEVNAME_SIZE];
u32 baseaddr;
u32 idma_baseaddr;
s8 miifdl;
s8 mii100l;
unsigned int md_clk;
u8 phy_addr;
u8 mii_mode;
u8 phyctrldis;
u8 mii_link_pol;
};
static struct emac_dev emac0 = {
.devname = "emac0",
.baseaddr = EMAC0_BASEADDR,
.idma_baseaddr = IDMA_EMAC0_BASEADDR,
#ifdef CONFIG_EMAC0_MIIFDL
.miifdl = CONFIG_EMAC0_MIIFDL,
#else
.miifdl = -1,
#endif
#ifdef CONFIG_EMAC0_MII100L
.mii100l = CONFIG_EMAC0_MII100L,
#else
.mii100l = -1,
#endif
#ifdef CONFIG_EMAC0_MII_MODE
.mii_mode = CONFIG_EMAC0_MII_MODE,
#else
.mii_mode = EMAC_RMII_SMII_MODE,
#endif
#ifdef CONFIG_EMAC0_PHYCTRLDIS
.phyctrldis = CONFIG_EMAC0_PHYCTRLDIS,
#else
.phyctrldis = 0x1,
#endif
#if CONFIG_EMAC0_MII_LINK_POL
.mii_link_pol = CONFIG_EMAC0_MII_LINK_POL,
#else
.mii_link_pol = 0x0,
#endif
#ifdef CONFIG_EMAC0_MDCLOCK
.md_clk = CONFIG_EMAC0_MDCLOCK,
#else
.md_clk = 2500000,
#endif
#ifdef CONFIG_EMAC0_PHY_ADDR
.phy_addr = CONFIG_EMAC0_PHY_ADDR,
#else
.phy_addr = 0x00,
#endif
};
#ifdef CONFIG_COMCERTO_800
static struct emac_dev emac1 = {
.devname = "emac1",
.baseaddr = EMAC1_BASEADDR,
.idma_baseaddr = IDMA_EMAC1_BASEADDR,
#ifdef CONFIG_EMAC1_MIIFDL
.miifdl = CONFIG_EMAC1_MIIFDL,
#else
.miifdl = -1,
#endif
#ifdef CONFIG_EMAC1_MII100L
.mii100l = CONFIG_EMAC1_MII100L,
#else
.mii100l = -1,
#endif
#ifdef CONFIG_EMAC1_MII_MODE
.mii_mode = CONFIG_EMAC1_MII_MODE,
#else
.mii_mode = EMAC_RMII_SMII_MODE,
#endif
#ifdef CONFIG_EMAC1_PHYCTRLDIS
.phyctrldis = CONFIG_EMAC1_PHYCTRLDIS,
#else
.phyctrldis = 0x1,
#endif
#if CONFIG_EMAC1_MII_LINK_POL
.mii_link_pol = CONFIG_EMAC1_MII_LINK_POL,
#else
.mii_link_pol = 0x0,
#endif
#ifdef CONFIG_EMAC1_MDCLOCK
.md_clk = CONFIG_EMAC1_MDCLOCK,
#else
.md_clk = 2500000,
#endif
#ifdef CONFIG_EMAC1_PHY_ADDR
.phy_addr = CONFIG_EMAC1_PHY_ADDR,
#else
.phy_addr = 0x00,
#endif
};
#endif /* CONFIG_COMCERTO_800 */
#ifdef CONFIG_EMAC0
static struct emac_dev *emac = &emac0;
#else
static struct emac_dev *emac = &emac1;
#endif
#define NUM_RX_DESC 16
#define MAX_RX_BUFF_SIZE 2048
static u32 rx_next;
static u8 rx_ring_data_buff[NUM_RX_DESC * MAX_RX_BUFF_SIZE];
static struct fdesc buff_aligned[NUM_RX_DESC] __attribute((aligned(16)));
static struct fdesc tx_fdesc __attribute((aligned(16)));
static struct fdesc *rx_ring;
#define EMAC_disable_rx(emac)\
*(volatile u32 *)((emac)->baseaddr + EMAC_RXCTRL) &= ~RX_EN
#define EMAC_disable_tx(emac)\
*(volatile u32 *)((emac)->baseaddr + EMAC_TXCTRL) &= ~TX_EN
#define EMAC_enable_rx(emac)\
*(volatile u32 *)((emac)->baseaddr + EMAC_RXCTRL) |= RX_EN
#define EMAC_enable_tx(emac)\
*(volatile u32 *)((emac)->baseaddr + EMAC_TXCTRL) |= TX_EN
static int get_mdcckse(int md_clk)
{
unsigned int div = CFG_HZ_CLOCK / md_clk;
if (div > 60)
return 0x3;
else if (div > 28)
return 0x2;
else if (div > 16)
return 0x1;
else
return 0x0;
}
#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
static int comcerto_miiphy_write(char *devname, unsigned char addr,
unsigned char reg, unsigned short value)
{
struct emac_dev *emac;
if ((addr > 31) || (reg > 31))
return 1;
if (!strcmp(devname, emac0.devname))
emac = &emac0;
#ifdef CONFIG_COMCERTO_800
else if (!strcmp(devname, emac1.devname))
emac = &emac1;
#endif
else
return -1;
if (*(volatile u32 *)(emac->baseaddr + EMAC_MDCA) & EMAC_MDIO_BUSY)
return 1;
/* start a write */
*(volatile u32 *)(emac->baseaddr + EMAC_MDDATA) = value;
*(volatile u32 *)(emac->baseaddr + EMAC_MDCA) = (reg | (addr << 5) | EMAC_MDIO_WRITE | EMAC_MDIO_BUSY);
while (*(volatile u32 *)(emac->baseaddr + EMAC_MDCA) & EMAC_MDIO_BUSY) ;
return 0;
}
static int comcerto_miiphy_read(char *devname, unsigned char addr,
unsigned char reg, unsigned short *value)
{
struct emac_dev *emac;
if ((addr > 31) || (reg > 31))
return 1;
if (!strcmp(devname, emac0.devname))
emac = &emac0;
#ifdef CONFIG_COMCERTO_800
else if (!strcmp(devname, emac1.devname))
emac = &emac1;
#endif
else
return -1;
if (*(volatile u32 *)(emac->baseaddr + EMAC_MDCA) & EMAC_MDIO_BUSY)
return 1;
*(volatile u32 *)(emac->baseaddr + EMAC_MDCA) = (reg | (addr << 5) | EMAC_MDIO_BUSY);
while (*(volatile u32 *)(emac->baseaddr + EMAC_MDCA) & EMAC_MDIO_BUSY) ;
*value = *(volatile u32 *)(emac->baseaddr + EMAC_MDDATA);
return 0;
}
static u32 get_ocr_mii_cfg(struct emac_dev *emac, u32 ocr)
{
unsigned short tmp;
miiphy_read(emac->devname, emac->phy_addr, PHY_BMSR, &tmp);
#ifdef CFG_FAULT_ECHO_LINK_DOWN
if (miiphy_link(emac->devname, emac->phy_addr))
ocr &= ~EMAC_OCR_MII100L;
else
ocr |= EMAC_OCR_MII100L;
#else
ocr &= ~EMAC_OCR_MII100L;
#endif /* CFG_FAULT_ECHO_LINK_DOWN */
if (emac->miifdl < 0) {
/* get link duplex from phy */
if (miiphy_duplex(emac->devname, emac->phy_addr) == HALF)
ocr |= EMAC_OCR_MIIFDL;
else
ocr &= ~EMAC_OCR_MIIFDL;
} else {
/* force link duplex */
if (emac->miifdl)
ocr |= EMAC_OCR_MIIFDL;
else
ocr &= ~EMAC_OCR_MIIFDL;
}
if (emac->mii100l < 0) {
/* get link speed from phy */
if (miiphy_speed(emac->devname, emac->phy_addr) == _10BASET)
ocr |= EMAC_OCR_MII100L;
else
ocr &= ~EMAC_OCR_MII100L;
} else {
/* force link speed */
if (emac->mii100l)
ocr |= EMAC_OCR_MII100L;
else
ocr &= ~EMAC_OCR_MII100L;
}
return ocr;
}
#else
static u32 get_ocr_mii_cfg(struct emac_dev *emac, u32 ocr)
{
ocr &= ~EMAC_OCR_MII100L;
if (emac->miifdl < 0) {
ocr &= ~EMAC_OCR_MIIFDL;
} else {
/* force link duplex */
if (emac->miifdl)
ocr |= EMAC_OCR_MIIFDL;
else
ocr &= ~EMAC_OCR_MIIFDL;
}
if (emac->mii100l < 0) {
ocr &= ~EMAC_OCR_MII100L;
} else {
/* force link speed */
if (emac->mii100l)
ocr |= EMAC_OCR_MII100L;
else
ocr &= ~EMAC_OCR_MII100L;
}
return ocr;
}
#endif /* defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) */
#ifdef CONFIG_NET_MULTI
#else
int comcerto_miiphy_initialize(bd_t *bis)
{
#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
u32 ocr;
#ifdef CONFIG_EMAC0
ocr = *(volatile u32 *)(emac0.baseaddr + EMAC_OCR);
ocr &= ~(0x3 << 2);
*(volatile u32 *)(emac0.baseaddr + EMAC_OCR) = ocr | (get_mdcckse(emac0.md_clk) << 2);
miiphy_register(emac0.devname, comcerto_miiphy_read, comcerto_miiphy_write);
#endif
#ifdef CONFIG_EMAC1
ocr = *(volatile u32 *)(emac1.baseaddr + EMAC_OCR);
ocr &= ~(0x3 << 2);
*(volatile u32 *)(emac1.baseaddr + EMAC_OCR) = ocr | (get_mdcckse(emac1.md_clk) << 2);
miiphy_register(emac1.devname, comcerto_miiphy_read, comcerto_miiphy_write);
#endif
#endif /* defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) */
return 0;
}
#endif /* CONFIG_NET_MULTI */
static int emac_arc_add(struct emac_dev *emac, u8 *mac_addr)
{
u32 temp;
u8 offset = 0;
/* we are in boot loader, even though this EMAC handles more than 20 entries,
we only gonna use one (Entry 0) */
temp = *mac_addr++;
temp <<= 8;
temp |= *mac_addr++;
temp <<= 8;
temp |= *mac_addr++;
temp <<= 8;
temp |= *mac_addr++;
*(volatile u32 *)(emac->baseaddr + EMAC_ARC_TABLE + offset) = temp;
offset += 4;
temp = *mac_addr++;
temp <<= 8;
temp |= *mac_addr++;
temp <<= 16;
*(volatile u32 *)(emac->baseaddr + EMAC_ARC_TABLE + offset) = ((*(volatile u32 *)(emac->baseaddr + EMAC_ARC_TABLE + offset)) & 0x0000FFFF) | temp;
*(volatile u32 *)(emac->baseaddr + EMAC_ARCENA) |= 1;
*(volatile u32 *)(emac->baseaddr + EMAC_ARCCTRL) |= ARC_COMPENA;
return 1;
}
static void emac_rx_ring_init(void)
{
u32 i;
u8 *pU8;
pU8 = rx_ring_data_buff;
rx_ring = buff_aligned;
for (i = 0; i < NUM_RX_DESC - 1; i++) {
rx_ring[i].next = &rx_ring[i + 1];
rx_ring[i].system = i;
rx_ring[i].fstatus = 0;
rx_ring[i].fcontrol = IDMA_FCONTROL_FREADY;
rx_ring[i].bdesc.bptr = pU8;
rx_ring[i].bdesc.bcontrol = 0;
pU8 += MAX_RX_BUFF_SIZE;
}
rx_ring[i].next = &rx_ring[0];
rx_ring[i].system = i;
rx_ring[i].fstatus = 0;
rx_ring[i].fcontrol = 0;
rx_ring[i].bdesc.bptr = pU8;
rx_ring[i].bdesc.bcontrol = 0;
rx_next = 0;
}
static void emac_ip_init(struct emac_dev *emac)
{
u32 i;
/* EMAC_MACCTRL register : set FullDup (as MII_Conn is high), Conn as Force MII, and Soft reset */
*(volatile u32 *)(emac->baseaddr + EMAC_MACCTRL) = MAC_FULLDUP | MAC_MIIRATE | MAC_RESET;
/* wait reset done */
while (*(volatile u32 *)(emac->baseaddr + EMAC_MACCTRL) & MAC_RESET) ;
/* EMAC_ARC_TABLE init */
for (i = 0; i < (6 * MAX_ARC_ENTRIES); i += 4)
*(volatile u32 *)((emac->baseaddr + EMAC_ARC_TABLE) + i) = 0;
/* EMAC_ARCENA : set to 0 as no ARC entry yet */
*(volatile u32 *)(emac->baseaddr + EMAC_ARCENA) = 0;
/* EMAC_ARCCTRL : accept BroadCast only (Local MAC address no yet defined) */
*(volatile u32 *)(emac->baseaddr + EMAC_ARCCTRL) = ARC_BROADACC;
/* EMAC_TXCTRL : set Tx_en */
*(volatile u32 *)(emac->baseaddr + EMAC_TXCTRL) = TX_EN;
/* EMAC_RXCTRL : set Rx_en, Strip CRC, ShortEn, */
*(volatile u32 *)(emac->baseaddr + EMAC_RXCTRL) = RX_EN | RX_STRIPCRC | RX_SHORTEN;
}
static void emac_ipif_init(struct emac_dev *emac)
{
u32 ocr, icr;
#ifdef CONFIG_COMCERTO_530
ocr = 0x00200200 | (get_mdcckse(emac->md_clk) << 2); /* force 100Mbit, full duplex, link up */
icr = 0x00000000;
ocr = get_ocr_mii_cfg(emac, ocr);
#else
ocr = 0x00200200 | (get_mdcckse(emac->md_clk) << 2); /* force 100Mbit, full duplex, link up */
icr = 0x00008000; /* use software settings */
switch (emac->mii_mode) {
case EMAC_MII_MODE:
ocr |= EMAC_OCR_SEL_MII_MODE;
break;
case EMAC_FORCE_RMII_MODE:
ocr &= ~EMAC_OCR_SEL_MII_MODE;
ocr |= EMAC_OCR_SW_SMII_OVRD;
ocr &= ~EMAC_OCR_SW_SMII_MODE;
break;
case EMAC_FORCE_SMII_MODE:
ocr &= ~EMAC_OCR_SEL_MII_MODE;
ocr |= EMAC_OCR_SW_SMII_OVRD;
ocr |= EMAC_OCR_SW_SMII_MODE;
break;
case EMAC_RMII_SMII_MODE:
default:
ocr &= ~EMAC_OCR_SEL_MII_MODE;
ocr &= ~EMAC_OCR_SW_SMII_OVRD;
break;
}
switch (emac->mii_mode) {
case EMAC_MII_MODE:
ocr = get_ocr_mii_cfg(emac, ocr);
break;
case EMAC_FORCE_RMII_MODE:
case EMAC_FORCE_SMII_MODE:
case EMAC_RMII_SMII_MODE:
default:
if (emac->phyctrldis) {
icr |= EMAC_ICR_PHYCTRLDIS;
ocr = get_ocr_mii_cfg(emac, ocr);
} else {
icr &= ~EMAC_ICR_PHYCTRLDIS;
icr &= ~(EMAC_ICR_MII100L_POL | EMAC_ICR_MIIFDL_POL | EMAC_ICR_MIILINK_POL);
icr |= (emac->mii_link_pol & 0x7) << 8;
}
break;
}
#endif
/* Init EMAC Operation Controlling Register */
*(volatile u32 *)(emac->baseaddr + EMAC_OCR) = ocr;
*(volatile u32 *)(emac->baseaddr + EMAC_ICR) = icr;
/* init DMA TX/RX Data FIFO Config Registers */
*(volatile u32 *)(emac->baseaddr + EMAC_HOST_FIFO_CONTROL) = EMAC_HOST_HBTXRQ_EN | EMAC_HOST_RXFF_EN | EMAC_HOST_HBTXRQ_EN | EMAC_HOST_TXFF_EN;
/* TX threshold Host =EMAC */
*(volatile u32 *)(emac->baseaddr + EMAC_HOST_FIFO_TXHIGH) = 0x000F3;
*(volatile u32 *)(emac->baseaddr + EMAC_HOST_FIFO_TXLOW) = 0x00F0;
/* RX threshold */
*(volatile u32 *)(emac->baseaddr + EMAC_HOST_FIFO_RXHIGH) = 0x0013;
*(volatile u32 *)(emac->baseaddr + EMAC_HOST_FIFO_RXLOW) = 0x0012;
/* arm side */
*(volatile u32 *)(emac->baseaddr + EMAC_ARM_FIFO_TXHIGH) = 0x00C0;
*(volatile u32 *)(emac->baseaddr + EMAC_ARM_FIFO_TXLOW) = 0x0020;
/* RX threshold */
*(volatile u32 *)(emac->baseaddr + EMAC_ARM_FIFO_RXHIGH) = 0x00E0;
*(volatile u32 *)(emac->baseaddr + EMAC_ARM_FIFO_RXLOW) = 0x0040;
*(volatile u32 *)(emac->baseaddr + EMAC_ARM_FIFO_CONTROL) = EMAC_ARM_RXDREQWE | EMAC_ARM_TXDREQRE;
*(volatile u32 *)ASA_TERMINAL_COUNT_CFG |= ASA_TC_REQIDMAEN;
}
static void emac_dma_init(struct emac_dev *emac)
{
/* Init IDMA */
/* Memory to EMAC (Tx) */
*(volatile u32 *)(emac->idma_baseaddr + MMEM_BURST) = (IDMA_BURST_MASK & 0xFF) | (IDMA_PRTY_MASK & 0x0200); /* burst size 255, priority 1 */
*(volatile u32 *)(emac->idma_baseaddr + MMEM_START) = 0;
/* EMAC to Memory (Rx) */
*(volatile u32 *)(emac->idma_baseaddr + EMMM_BURST) = (IDMA_BURST_MASK & 0xFF) | (IDMA_PRTY_MASK & 0x0100); /* burst size 255, priority 1 */
*(volatile u32 *)(emac->idma_baseaddr + EMMM_START) = 0;
}
static int emac_init(struct emac_dev *emac, u8 *mac_addr)
{
*(volatile u32 *)(emac->idma_baseaddr + EMMM_SOFT_RESET) = 0x1;
*(volatile u32 *)(emac->idma_baseaddr + MMEM_SOFT_RESET) = 0x1;
*(volatile u32 *)(emac->baseaddr + EMAC_OCR) |= EMAC_OCR_IP_HRESET;
udelay(100);
*(volatile u32 *)(emac->baseaddr + EMAC_OCR) &= ~EMAC_OCR_IP_HRESET;
emac_ipif_init(emac);
emac_ip_init(emac);
emac_dma_init(emac);
/* Add Mac Address in the ARC table */
emac_arc_add(emac, mac_addr);
/* Init Ehternet buffers */
emac_rx_ring_init();
/* Start Rx EDMA */
*(volatile u32 *)(emac->idma_baseaddr + EMMM_HEAD) = (u32) &rx_ring[rx_next];
*(volatile u32 *)(emac->idma_baseaddr + EMMM_START) |= IDMA_START;
return 0;
}
static int emac_send(struct emac_dev *emac, volatile void *packet, int length)
{
int i;
memset(&tx_fdesc, 0, sizeof(struct fdesc));
/* build the tx frame descriptor here */
tx_fdesc.fcontrol = IDMA_FCONTROL_FREADY | IDMA_FCONTROL_FLAST;
tx_fdesc.fstatus = 0;
tx_fdesc.bdesc.bptr = packet;
tx_fdesc.bdesc.bcontrol = length | IDMA_BCONTROL_BLAST;
/* Check if DMA Stopped */
if (!(*(volatile u32 *)(emac->idma_baseaddr + MMEM_START) & IDMA_START)) {
*(volatile u32 *)(emac->idma_baseaddr + MMEM_HEAD) = (u32) &tx_fdesc;
*(volatile u32 *)(emac->idma_baseaddr + MMEM_START) |= IDMA_START;
} else {
printf("Emac: tx EDMA busy!\n");
return (-1);
}
i = 0;
while ((tx_fdesc.fstatus & IDMA_FSTATUS_FRAME_DONE_MASK) == 0) {
udelay(100);
i++;
if (i == 50000) {
printf("Emac: tx timed out! %x\n", tx_fdesc.fstatus);
return (-1);
}
}
if (*(volatile u32 *)(emac->idma_baseaddr + MMEM_START) & IDMA_START) {
printf("Emac: tx did not stop after sending a packet!\n");
}
return (length);
}
static int emac_rx(struct emac_dev *emac)
{
int rx_prev;
int length;
int total_length = 0;
/* loop thru rx FDescs */
while (1) {
if ((rx_ring[rx_next].fstatus & IDMA_FSTATUS_FRAME_DONE_MASK) == 0)
break;
/* mark rx_next not usable */
rx_ring[rx_next].fcontrol = 0;
if (rx_ring[rx_next].fstatus & (1 << 10)) {
length = rx_ring[rx_next].bdesc.bcontrol & IDMA_BCONTROL_BLEN_MASK;
if (length > MAX_RX_BUFF_SIZE) {
printf("Emac: frame too big (%d bytes)!\n", length);
length = MAX_RX_BUFF_SIZE;
}
/* Pass the packet up to the protocol layers. */
NetReceive(rx_ring[rx_next].bdesc.bptr, length);
total_length += length;
}
/* rx_prev can be used now */
if (rx_next == 0)
rx_prev = NUM_RX_DESC - 1;
else
rx_prev = rx_next - 1;
rx_ring[rx_prev].fstatus = 0;
rx_ring[rx_prev].fcontrol = IDMA_FCONTROL_FREADY;
rx_next++;
if (rx_next == NUM_RX_DESC)
rx_next = 0;
}
/* Check if DMA Stopped, if RX is stopped, restart */
if (!(*(volatile u32 *)(emac->idma_baseaddr + EMMM_START) & IDMA_START)) {
*(volatile u32 *)(emac->idma_baseaddr + EMMM_HEAD) = (u32) &rx_ring[rx_next];
*(volatile u32 *)(emac->idma_baseaddr + EMMM_START) |= IDMA_START;
}
return (total_length);
}
static void emac_halt(struct emac_dev *emac)
{
/* stop EMAC */
EMAC_disable_rx(emac);
EMAC_disable_tx(emac);
*(volatile u32 *)(emac->idma_baseaddr + EMMM_SOFT_RESET) = 0x1;
*(volatile u32 *)(emac->idma_baseaddr + MMEM_SOFT_RESET) = 0x1;
}
#ifdef CONFIG_NET_MULTI
#else
int eth_send(volatile void *packet, int length)
{
if (length <= 0) {
printf("Emac: bad packet size: %d\n", length);
return (-1);
}
return emac_send(emac, packet, length);
}
int eth_init(bd_t * bd)
{
return emac_init(emac, bd->bi_enetaddr);
}
int eth_rx(void)
{
return emac_rx(emac);
}
void eth_halt(void)
{
emac_halt(emac);
}
#endif /* CONFIG_NET_MULTI */
#endif /* (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_COMCERTO_EMAC) */