diff options
| author | Mike Frysinger <vapier@gentoo.org> | 2008-02-24 23:58:13 -0500 | 
|---|---|---|
| committer | Wolfgang Denk <wd@denx.de> | 2008-03-25 22:35:26 +0100 | 
| commit | 395bce4f59a507a60a475f7ee46bed47de9482df (patch) | |
| tree | 354c55a5041a0c3e7b9b9ada917cb8eacbde069f /drivers/net | |
| parent | 8a30b4700942f37495d2e67f5998cdffb6e3ba8a (diff) | |
| download | olio-uboot-2014.01-395bce4f59a507a60a475f7ee46bed47de9482df.tar.xz olio-uboot-2014.01-395bce4f59a507a60a475f7ee46bed47de9482df.zip | |
net/Blackfin: move on-chip MAC driver into drivers/net/
The Blackfin on-chip MAC driver was being managed in the BF537-STAMP board
directory, but it is not board specific, so relocate it to the drivers dir
so that other Blackfin ports can utilize it.
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'drivers/net')
| -rw-r--r-- | drivers/net/Makefile | 1 | ||||
| -rw-r--r-- | drivers/net/bfin_mac.c | 523 | ||||
| -rw-r--r-- | drivers/net/bfin_mac.h | 89 | 
3 files changed, 613 insertions, 0 deletions
| diff --git a/drivers/net/Makefile b/drivers/net/Makefile index b9723fa78..321bd08ad 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -27,6 +27,7 @@ LIB 	:= $(obj)libnet.a  COBJS-y += 3c589.o  COBJS-y += bcm570x.o bcm570x_autoneg.o 5701rls.o +COBJS-$(CONFIG_BFIN_MAC) += bfin_mac.o  COBJS-y += cs8900.o  COBJS-y += dc2114x.o  COBJS-y += dm9000x.o diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c new file mode 100644 index 000000000..afe122a33 --- /dev/null +++ b/drivers/net/bfin_mac.c @@ -0,0 +1,523 @@ +/* + * Driver for Blackfin On-Chip MAC device + * + * Copyright (c) 2005-2008 Analog Device, Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include <common.h> +#include <config.h> +#include <net.h> +#include <command.h> +#include <malloc.h> + +#include <asm/blackfin.h> +#include <asm/mach-common/bits/dma.h> +#include <asm/mach-common/bits/emac.h> +#include <asm/mach-common/bits/pll.h> + +#include "bfin_mac.h" + +#ifdef CONFIG_POST +#include <post.h> +#endif + +#undef DEBUG_ETHERNET + +#ifdef DEBUG_ETHERNET +#define DEBUGF(fmt, args...) printf(fmt, ##args) +#else +#define DEBUGF(fmt, args...) +#endif + +#define RXBUF_BASE_ADDR		0xFF900000 +#define TXBUF_BASE_ADDR		0xFF800000 +#define TX_BUF_CNT		1 + +#define TOUT_LOOP 		1000000 + +ADI_ETHER_BUFFER *txbuf[TX_BUF_CNT]; +ADI_ETHER_BUFFER *rxbuf[PKTBUFSRX]; +static u16 txIdx;		/* index of the current RX buffer */ +static u16 rxIdx;		/* index of the current TX buffer */ + +u16 PHYregs[NO_PHY_REGS];	/* u16 PHYADDR; */ + +/* DMAx_CONFIG values at DMA Restart */ +const ADI_DMA_CONFIG_REG rxdmacfg = { +	.b_DMA_EN  = 1,	/* enabled */ +	.b_WNR     = 1,	/* write to memory */ +	.b_WDSIZE  = 2,	/* wordsize is 32 bits */ +	.b_DMA2D   = 0, +	.b_RESTART = 0, +	.b_DI_SEL  = 0, +	.b_DI_EN   = 0,	/* no interrupt */ +	.b_NDSIZE  = 5,	/* 5 half words is desc size */ +	.b_FLOW    = 7	/* large desc flow */ +}; + +const ADI_DMA_CONFIG_REG txdmacfg = { +	.b_DMA_EN  = 1,	/* enabled */ +	.b_WNR     = 0,	/* read from memory */ +	.b_WDSIZE  = 2,	/* wordsize is 32 bits */ +	.b_DMA2D   = 0, +	.b_RESTART = 0, +	.b_DI_SEL  = 0, +	.b_DI_EN   = 0,	/* no interrupt */ +	.b_NDSIZE  = 5,	/* 5 half words is desc size */ +	.b_FLOW    = 7	/* large desc flow */ +}; + +int bfin_EMAC_initialize(bd_t *bis) +{ +	struct eth_device *dev; +	dev = (struct eth_device *)malloc(sizeof(*dev)); +	if (dev == NULL) +		hang(); + +	memset(dev, 0, sizeof(*dev)); +	sprintf(dev->name, "Blackfin EMAC"); + +	dev->iobase = 0; +	dev->priv = 0; +	dev->init = bfin_EMAC_init; +	dev->halt = bfin_EMAC_halt; +	dev->send = bfin_EMAC_send; +	dev->recv = bfin_EMAC_recv; + +	eth_register(dev); + +	return 1; +} + +static int bfin_EMAC_send(struct eth_device *dev, volatile void *packet, +			  int length) +{ +	int i; +	int result = 0; +	unsigned int *buf; +	buf = (unsigned int *)packet; + +	if (length <= 0) { +		printf("Ethernet: bad packet size: %d\n", length); +		goto out; +	} + +	if ((*pDMA2_IRQ_STATUS & DMA_ERR) != 0) { +		printf("Ethernet: tx DMA error\n"); +		goto out; +	} + +	for (i = 0; (*pDMA2_IRQ_STATUS & DMA_RUN) != 0; i++) { +		if (i > TOUT_LOOP) { +			puts("Ethernet: tx time out\n"); +			goto out; +		} +	} +	txbuf[txIdx]->FrmData->NoBytes = length; +	memcpy(txbuf[txIdx]->FrmData->Dest, (void *)packet, length); +	txbuf[txIdx]->Dma[0].START_ADDR = (u32) txbuf[txIdx]->FrmData; +	*pDMA2_NEXT_DESC_PTR = &txbuf[txIdx]->Dma[0]; +	*pDMA2_CONFIG = *(u16 *) (void *)(&txdmacfg); +	*pEMAC_OPMODE |= TE; + +	for (i = 0; (txbuf[txIdx]->StatusWord & TX_COMP) == 0; i++) { +		if (i > TOUT_LOOP) { +			puts("Ethernet: tx error\n"); +			goto out; +		} +	} +	result = txbuf[txIdx]->StatusWord; +	txbuf[txIdx]->StatusWord = 0; +	if ((txIdx + 1) >= TX_BUF_CNT) +		txIdx = 0; +	else +		txIdx++; + out: +	DEBUGF("BFIN EMAC send: length = %d\n", length); +	return result; +} + +static int bfin_EMAC_recv(struct eth_device *dev) +{ +	int length = 0; + +	for (;;) { +		if ((rxbuf[rxIdx]->StatusWord & RX_COMP) == 0) { +			length = -1; +			break; +		} +		if ((rxbuf[rxIdx]->StatusWord & RX_DMAO) != 0) { +			printf("Ethernet: rx dma overrun\n"); +			break; +		} +		if ((rxbuf[rxIdx]->StatusWord & RX_OK) == 0) { +			printf("Ethernet: rx error\n"); +			break; +		} +		length = rxbuf[rxIdx]->StatusWord & 0x000007FF; +		if (length <= 4) { +			printf("Ethernet: bad frame\n"); +			break; +		} +		NetRxPackets[rxIdx] = +		    (volatile uchar *)(rxbuf[rxIdx]->FrmData->Dest); +		NetReceive(NetRxPackets[rxIdx], length - 4); +		*pDMA1_IRQ_STATUS |= DMA_DONE | DMA_ERR; +		rxbuf[rxIdx]->StatusWord = 0x00000000; +		if ((rxIdx + 1) >= PKTBUFSRX) +			rxIdx = 0; +		else +			rxIdx++; +	} + +	return length; +} + +/************************************************************** + * + * Ethernet Initialization Routine + * + *************************************************************/ + +static int bfin_EMAC_init(struct eth_device *dev, bd_t *bd) +{ +	u32 opmode; +	int dat; +	int i; +	DEBUGF("Eth_init: ......\n"); + +	txIdx = 0; +	rxIdx = 0; + +/* Initialize System Register */ +	if (SetupSystemRegs(&dat) < 0) +		return -1; + +/* Initialize EMAC address */ +	bfin_EMAC_setup_addr(bd); + +/* Initialize TX and RX buffer */ +	for (i = 0; i < PKTBUFSRX; i++) { +		rxbuf[i] = SetupRxBuffer(i); +		if (i > 0) { +			rxbuf[i - 1]->Dma[1].NEXT_DESC_PTR = +			    &(rxbuf[i]->Dma[0]); +			if (i == (PKTBUFSRX - 1)) +				rxbuf[i]->Dma[1].NEXT_DESC_PTR = +				    &(rxbuf[0]->Dma[0]); +		} +	} +	for (i = 0; i < TX_BUF_CNT; i++) { +		txbuf[i] = SetupTxBuffer(i); +		if (i > 0) { +			txbuf[i - 1]->Dma[1].NEXT_DESC_PTR = +			    &(txbuf[i]->Dma[0]); +			if (i == (TX_BUF_CNT - 1)) +				txbuf[i]->Dma[1].NEXT_DESC_PTR = +				    &(txbuf[0]->Dma[0]); +		} +	} + +	/* Set RX DMA */ +	*pDMA1_NEXT_DESC_PTR = &rxbuf[0]->Dma[0]; +	*pDMA1_CONFIG = *((u16 *) (void *)&rxbuf[0]->Dma[0].CONFIG); + +	/* Wait MII done */ +	PollMdcDone(); + +	/* We enable only RX here */ +	/* ASTP   : Enable Automatic Pad Stripping +	   PR     : Promiscuous Mode for test +	   PSF    : Receive frames with total length less than 64 bytes. +	   FDMODE : Full Duplex Mode +	   LB	  : Internal Loopback for test +	   RE     : Receiver Enable */ +	if (dat == FDMODE) +		opmode = ASTP | FDMODE | PSF; +	else +		opmode = ASTP | PSF; +	opmode |= RE; +#ifdef CONFIG_BFIN_MAC_RMII +	opmode |= TE | RMII; +#endif +	/* Turn on the EMAC */ +	*pEMAC_OPMODE = opmode; +	return 0; +} + +static void bfin_EMAC_halt(struct eth_device *dev) +{ +	DEBUGF("Eth_halt: ......\n"); +	/* Turn off the EMAC */ +	*pEMAC_OPMODE = 0x00000000; +	/* Turn off the EMAC RX DMA */ +	*pDMA1_CONFIG = 0x0000; +	*pDMA2_CONFIG = 0x0000; + +} + +void bfin_EMAC_setup_addr(bd_t *bd) +{ +	*pEMAC_ADDRLO = +		bd->bi_enetaddr[0] | +		bd->bi_enetaddr[1] << 8 | +		bd->bi_enetaddr[2] << 16 | +		bd->bi_enetaddr[3] << 24; +	*pEMAC_ADDRHI = +		bd->bi_enetaddr[4] | +		bd->bi_enetaddr[5] << 8; +} + +static void PollMdcDone(void) +{ +	/* poll the STABUSY bit */ +	while (*pEMAC_STAADD & STABUSY) ; +} + +static void WrPHYReg(u16 PHYAddr, u16 RegAddr, u16 Data) +{ +	PollMdcDone(); + +	*pEMAC_STADAT = Data; + +	*pEMAC_STAADD = SET_PHYAD(PHYAddr) | SET_REGAD(RegAddr) | +	    STAOP | STAIE | STABUSY; +} + +/********************************************************************************* + *		Read an off-chip register in a PHY through the MDC/MDIO port     * + *********************************************************************************/ +static u16 RdPHYReg(u16 PHYAddr, u16 RegAddr) +{ +	u16 Data; + +	PollMdcDone(); + +	*pEMAC_STAADD = SET_PHYAD(PHYAddr) | SET_REGAD(RegAddr) | +	    STAIE | STABUSY; + +	PollMdcDone(); + +	Data = (u16) * pEMAC_STADAT; + +	PHYregs[RegAddr] = Data;	/* save shadow copy */ + +	return Data; +} + +#if 0 /* dead code ? */ +static void SoftResetPHY(void) +{ +	u16 phydat; +	/* set the reset bit */ +	WrPHYReg(PHYADDR, PHY_MODECTL, PHY_RESET); +	/* and clear it again */ +	WrPHYReg(PHYADDR, PHY_MODECTL, 0x0000); +	do { +		/* poll until reset is complete */ +		phydat = RdPHYReg(PHYADDR, PHY_MODECTL); +	} while ((phydat & PHY_RESET) != 0); +} +#endif + +static int SetupSystemRegs(int *opmode) +{ +	u16 sysctl, phydat; +	int count = 0; +	/* Enable PHY output */ +	*pVR_CTL |= CLKBUFOE; +	/* Set all the pins to peripheral mode */ + +#ifndef CONFIG_BFIN_MAC_RMII +	*pPORTH_FER = 0xFFFF; +#ifdef __ADSPBF52x__ +	*pPORTH_MUX = PORT_x_MUX_0_FUNC_2 | PORT_x_MUX_1_FUNC_2 | PORT_x_MUX_2_FUNC_2; +#endif +#else +#if defined(__ADSPBF536__) || defined(__ADSPBF537__) +	*pPORTH_FER = 0xC373; +#endif +#ifdef __ADSPBF52x__ +	*pPORTH_FER = 0x01FF; +	*pPORTH_MUX = PORT_x_MUX_0_FUNC_2 | PORT_x_MUX_1_FUNC_2; +#endif +#endif +	/* MDC  = 2.5 MHz */ +	sysctl = SET_MDCDIV(24); +	/* Odd word alignment for Receive Frame DMA word */ +	/* Configure checksum support and rcve frame word alignment */ +	sysctl |= RXDWA | RXCKS; +	*pEMAC_SYSCTL = sysctl; +	/* auto negotiation on  */ +	/* full duplex */ +	/* 100 Mbps */ +	phydat = PHY_ANEG_EN | PHY_DUPLEX | PHY_SPD_SET; +	WrPHYReg(PHYADDR, PHY_MODECTL, phydat); +	do { +		udelay(1000); +		phydat = RdPHYReg(PHYADDR, PHY_MODESTAT); +		if (count > 3000) { +			printf +			    ("Link is down, please check your network connection\n"); +			return -1; +		} +		count++; +	} while (!(phydat & 0x0004)); + +	phydat = RdPHYReg(PHYADDR, PHY_ANLPAR); + +	if ((phydat & 0x0100) || (phydat & 0x0040)) +		*opmode = FDMODE; +	else +		*opmode = 0; + +	*pEMAC_MMC_CTL = RSTC | CROLL; + +	/* Initialize the TX DMA channel registers */ +	*pDMA2_X_COUNT = 0; +	*pDMA2_X_MODIFY = 4; +	*pDMA2_Y_COUNT = 0; +	*pDMA2_Y_MODIFY = 0; + +	/* Initialize the RX DMA channel registers */ +	*pDMA1_X_COUNT = 0; +	*pDMA1_X_MODIFY = 4; +	*pDMA1_Y_COUNT = 0; +	*pDMA1_Y_MODIFY = 0; +	return 0; +} + +ADI_ETHER_BUFFER *SetupRxBuffer(int no) +{ +	ADI_ETHER_FRAME_BUFFER *frmbuf; +	ADI_ETHER_BUFFER *buf; +	int nobytes_buffer = sizeof(ADI_ETHER_BUFFER[2]) / 2;	/* ensure a multi. of 4 */ +	int total_size = nobytes_buffer + RECV_BUFSIZE; + +	buf = (ADI_ETHER_BUFFER *) (RXBUF_BASE_ADDR + no * total_size); +	frmbuf = +	    (ADI_ETHER_FRAME_BUFFER *) (RXBUF_BASE_ADDR + no * total_size + +					nobytes_buffer); + +	memset(buf, 0x00, nobytes_buffer); +	buf->FrmData = frmbuf; +	memset(frmbuf, 0xfe, RECV_BUFSIZE); + +	/* set up first desc to point to receive frame buffer */ +	buf->Dma[0].NEXT_DESC_PTR = &(buf->Dma[1]); +	buf->Dma[0].START_ADDR = (u32) buf->FrmData; +	buf->Dma[0].CONFIG.b_DMA_EN = 1;	/* enabled */ +	buf->Dma[0].CONFIG.b_WNR = 1;	/* Write to memory */ +	buf->Dma[0].CONFIG.b_WDSIZE = 2;	/* wordsize is 32 bits */ +	buf->Dma[0].CONFIG.b_NDSIZE = 5;	/* 5 half words is desc size. */ +	buf->Dma[0].CONFIG.b_FLOW = 7;	/* large desc flow */ + +	/* set up second desc to point to status word */ +	buf->Dma[1].NEXT_DESC_PTR = &(buf->Dma[0]); +	buf->Dma[1].START_ADDR = (u32) & buf->IPHdrChksum; +	buf->Dma[1].CONFIG.b_DMA_EN = 1;	/* enabled */ +	buf->Dma[1].CONFIG.b_WNR = 1;	/* Write to memory */ +	buf->Dma[1].CONFIG.b_WDSIZE = 2;	/* wordsize is 32 bits */ +	buf->Dma[1].CONFIG.b_DI_EN = 1;	/* enable interrupt */ +	buf->Dma[1].CONFIG.b_NDSIZE = 5;	/* must be 0 when FLOW is 0 */ +	buf->Dma[1].CONFIG.b_FLOW = 7;	/* stop */ + +	return buf; +} + +ADI_ETHER_BUFFER *SetupTxBuffer(int no) +{ +	ADI_ETHER_FRAME_BUFFER *frmbuf; +	ADI_ETHER_BUFFER *buf; +	int nobytes_buffer = sizeof(ADI_ETHER_BUFFER[2]) / 2;	/* ensure a multi. of 4 */ +	int total_size = nobytes_buffer + RECV_BUFSIZE; + +	buf = (ADI_ETHER_BUFFER *) (TXBUF_BASE_ADDR + no * total_size); +	frmbuf = +	    (ADI_ETHER_FRAME_BUFFER *) (TXBUF_BASE_ADDR + no * total_size + +					nobytes_buffer); + +	memset(buf, 0x00, nobytes_buffer); +	buf->FrmData = frmbuf; +	memset(frmbuf, 0x00, RECV_BUFSIZE); + +	/* set up first desc to point to receive frame buffer */ +	buf->Dma[0].NEXT_DESC_PTR = &(buf->Dma[1]); +	buf->Dma[0].START_ADDR = (u32) buf->FrmData; +	buf->Dma[0].CONFIG.b_DMA_EN = 1;	/* enabled */ +	buf->Dma[0].CONFIG.b_WNR = 0;	/* Read to memory */ +	buf->Dma[0].CONFIG.b_WDSIZE = 2;	/* wordsize is 32 bits */ +	buf->Dma[0].CONFIG.b_NDSIZE = 5;	/* 5 half words is desc size. */ +	buf->Dma[0].CONFIG.b_FLOW = 7;	/* large desc flow */ + +	/* set up second desc to point to status word */ +	buf->Dma[1].NEXT_DESC_PTR = &(buf->Dma[0]); +	buf->Dma[1].START_ADDR = (u32) & buf->StatusWord; +	buf->Dma[1].CONFIG.b_DMA_EN = 1;	/* enabled */ +	buf->Dma[1].CONFIG.b_WNR = 1;	/* Write to memory */ +	buf->Dma[1].CONFIG.b_WDSIZE = 2;	/* wordsize is 32 bits */ +	buf->Dma[1].CONFIG.b_DI_EN = 1;	/* enable interrupt */ +	buf->Dma[1].CONFIG.b_NDSIZE = 0;	/* must be 0 when FLOW is 0 */ +	buf->Dma[1].CONFIG.b_FLOW = 0;	/* stop */ + +	return buf; +} + +#if defined(CONFIG_POST) && defined(CFG_POST_ETHER) +int ether_post_test(int flags) +{ +	uchar buf[64]; +	int i, value = 0; +	int length; + +	printf("\n--------"); +	bfin_EMAC_init(NULL, NULL); +	/* construct the package */ +	buf[0] = buf[6] = (unsigned char)(*pEMAC_ADDRLO & 0xFF); +	buf[1] = buf[7] = (unsigned char)((*pEMAC_ADDRLO & 0xFF00) >> 8); +	buf[2] = buf[8] = (unsigned char)((*pEMAC_ADDRLO & 0xFF0000) >> 16); +	buf[3] = buf[9] = (unsigned char)((*pEMAC_ADDRLO & 0xFF000000) >> 24); +	buf[4] = buf[10] = (unsigned char)(*pEMAC_ADDRHI & 0xFF); +	buf[5] = buf[11] = (unsigned char)((*pEMAC_ADDRHI & 0xFF00) >> 8); +	buf[12] = 0x08;		/* Type: ARP */ +	buf[13] = 0x06; +	buf[14] = 0x00;		/* Hardware type: Ethernet */ +	buf[15] = 0x01; +	buf[16] = 0x08;		/* Protocal type: IP */ +	buf[17] = 0x00; +	buf[18] = 0x06;		/* Hardware size    */ +	buf[19] = 0x04;		/* Protocol size    */ +	buf[20] = 0x00;		/* Opcode: request  */ +	buf[21] = 0x01; + +	for (i = 0; i < 42; i++) +		buf[i + 22] = i; +	printf("--------Send 64 bytes......\n"); +	bfin_EMAC_send(NULL, (volatile void *)buf, 64); +	for (i = 0; i < 100; i++) { +		udelay(10000); +		if ((rxbuf[rxIdx]->StatusWord & RX_COMP) != 0) { +			value = 1; +			break; +		} +	} +	if (value == 0) { +		printf("--------EMAC can't receive any data\n"); +		eth_halt(); +		return -1; +	} +	length = rxbuf[rxIdx]->StatusWord & 0x000007FF - 4; +	for (i = 0; i < length; i++) { +		if (rxbuf[rxIdx]->FrmData->Dest[i] != buf[i]) { +			printf("--------EMAC receive error data!\n"); +			eth_halt(); +			return -1; +		} +	} +	printf("--------receive %d bytes, matched\n", length); +	bfin_EMAC_halt(NULL); +	return 0; +} +#endif diff --git a/drivers/net/bfin_mac.h b/drivers/net/bfin_mac.h new file mode 100644 index 000000000..c8a94d0c9 --- /dev/null +++ b/drivers/net/bfin_mac.h @@ -0,0 +1,89 @@ +/* + * bfin_mac.h - some defines/structures for the Blackfin on-chip MAC. + * + * Copyright (c) 2005-2008 Analog Device, Inc. + * + * Licensed under the GPL-2 or later. + */ + +#ifndef __BFIN_MAC_H__ +#define __BFIN_MAC_H__ + +#define PHYADDR			0x01 +#define NO_PHY_REGS		0x20 + +#define DEFAULT_PHY_PHYID1	0x0007 +#define DEFAULT_PHY_PHYID2	0xC0A3 +#define PHY_MODECTL		0x00 +#define PHY_MODESTAT		0x01 +#define PHY_PHYID1		0x02 +#define PHY_PHYID2		0x03 +#define PHY_ANAR		0x04 +#define PHY_ANLPAR		0x05 +#define PHY_ANER		0x06 + +#define PHY_RESET		0x8000 +#define PHY_ANEG_EN		0x1000 +#define PHY_DUPLEX		0x0100 +#define PHY_SPD_SET		0x2000 + +#define RECV_BUFSIZE		(0x614) + +typedef volatile u32 reg32; +typedef volatile u16 reg16; + +typedef struct ADI_DMA_CONFIG_REG { +	u16 b_DMA_EN:1;		/* 0	Enabled				*/ +	u16 b_WNR:1;		/* 1	Direction			*/ +	u16 b_WDSIZE:2;		/* 2:3	Transfer word size		*/ +	u16 b_DMA2D:1;		/* 4	DMA mode			*/ +	u16 b_RESTART:1;	/* 5	Retain FIFO			*/ +	u16 b_DI_SEL:1;		/* 6	Data interrupt timing select	*/ +	u16 b_DI_EN:1;		/* 7	Data interrupt enabled		*/ +	u16 b_NDSIZE:4;		/* 8:11	Flex descriptor size		*/ +	u16 b_FLOW:3;		/* 12:14Flow				*/ +} ADI_DMA_CONFIG_REG; + +typedef struct adi_ether_frame_buffer { +	u16 NoBytes;		/* the no. of following bytes	*/ +	u8 Dest[6];		/* destination MAC address	*/ +	u8 Srce[6];		/* source MAC address		*/ +	u16 LTfield;		/* length/type field		*/ +	u8 Data[0];		/* payload bytes		*/ +} ADI_ETHER_FRAME_BUFFER; +/* 16 bytes/struct	*/ + +typedef struct dma_descriptor { +	struct dma_descriptor *NEXT_DESC_PTR; +	u32 START_ADDR; +	ADI_DMA_CONFIG_REG CONFIG; +} DMA_DESCRIPTOR; +/* 10 bytes/struct in 12 bytes */ + +typedef struct adi_ether_buffer { +	DMA_DESCRIPTOR Dma[2];		/* first for the frame, second for the status */ +	ADI_ETHER_FRAME_BUFFER *FrmData;/* pointer to data */ +	struct adi_ether_buffer *pNext;	/* next buffer */ +	struct adi_ether_buffer *pPrev;	/* prev buffer */ +	u16 IPHdrChksum;		/* the IP header checksum */ +	u16 IPPayloadChksum;		/* the IP header and payload checksum */ +	volatile u32 StatusWord;	/* the frame status word */ +} ADI_ETHER_BUFFER; +/* 40 bytes/struct in 44 bytes */ + +static ADI_ETHER_BUFFER *SetupRxBuffer(int no); +static ADI_ETHER_BUFFER *SetupTxBuffer(int no); + +static int bfin_EMAC_init(struct eth_device *dev, bd_t *bd); +static void bfin_EMAC_halt(struct eth_device *dev); +static int bfin_EMAC_send(struct eth_device *dev, volatile void *packet, int length); +static int bfin_EMAC_recv(struct eth_device *dev); + +static void PollMdcDone(void); +static void WrPHYReg(u16 PHYAddr, u16 RegAddr, u16 Data); +static u16 RdPHYReg(u16 PHYAddr, u16 RegAddr); +static int SetupSystemRegs(int *opmode); + +static void bfin_EMAC_setup_addr(bd_t *bd); + +#endif |